]> gitweb.factorcode.org Git - factor.git/blobdiff - basis/bootstrap/assembler/arm.64.factor
arm64: 9999 BRK works again
[factor.git] / basis / bootstrap / assembler / arm.64.factor
index f870742c80aa536ad2fbc96ba00610292a2d149d..6079c7a0c9dba7498874f6f9fee9cd605f88b26a 100644 (file)
@@ -25,8 +25,10 @@ big-endian off
 ! x29/fp       Non-volatile    Frame pointer
 ! x30/lr       Non-volatile    Link registers
 
-: stack-frame-size ( -- n ) 4 bootstrap-cells ;
+! varargs https://developer.arm.com/documentation/ihi0055/d/?lang=en
+: stack-frame-size ( -- n ) 8 bootstrap-cells ;
 : volatile-regs ( -- seq ) { X0 X1 X2 X3 X4 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 } ;
+! windows arm - X18 is non-volatile https://docs.microsoft.com/en-us/cpp/build/arm64-windows-abi-conventions?view=msvc-160
 : nv-regs ( -- seq ) { X18 X19 X20 X21 X22 X23 X24 X25 X26 X27 X28 X29 X30 } ;
 
 ! callee-save = non-volatile aka call-preserved
@@ -44,22 +46,41 @@ big-endian off
 
 
 ! https://en.wikichip.org/wiki/arm/aarch64
-! Generally, X0 through X18 can corrupt while X19-X29 must be preserved
+! Generally, X0 through X18 (volatile, can corrupt) while X19-X29 must be preserved (non-volatile)
+! Volatile registers' content may change over a subroutine call
+! non-volatile register is a type of register with contents that must be preserved over subroutine calls
 ! Register   Role    Requirement
-! X0 -  X7   Parameter/result registers   Can Corrupt
-! X8         Indirect result location register
-! X9 -  X15  Temporary registers
-! X16 - X17  Intra-procedure call temporary
-! X18        Platform register, otherwise temporary
+! X0 -  X7   Parameter/result registers   Can Corrupt (volatile)
+! X8         Indirect result location register (volatile)
+! X9 -  X15  Temporary registers (volatile)
+! X16 - X17  Intra-procedure call temporary (volatile)
+! x16 - syscall reg with SVC instructioin
+! X18        Platform register, otherwise temporary, DONT USE (volatile)
 
-! X19 - X29    Callee-saved register    Must preserve
-! X30    Link Register    Can Corrupt
+! X19 - X29    Callee-saved register    Must preserve (non-volatile)
+! X29 - frame pointer register, must always be valid
+! X30    Link Register LR   Can Corrupt
+! X31  Stack Pointer SP
+! 16-byte stack alignment
+
+! stack walking - {fp, lr} pairs if compiled with frame pointers enabled
 
 : arg1 ( -- reg ) X0 ;
 : arg2 ( -- reg ) X1 ;
 : arg3 ( -- reg ) X2 ;
 : arg4 ( -- reg ) X3 ;
-: red-zone-size ( -- n ) 16 ;
+
+! Red zone
+! windows arm64: 16 bytes https://devblogs.microsoft.com/oldnewthing/20190111-00/?p=100685
+! windows arm32: 8 bytes
+! x86/x64: 0 bytes
+! Apple arm64: 128 bytes https://developer.apple.com/documentation/xcode/writing_arm64_code_for_apple_platforms?language=objc
+: red-zone-size ( -- n ) 16 ; ! 16 bytes on windows, or 128 bytes on linux? or 0?
+! 0 or 16 likely
+! no red zone on x86/x64 windows
+
+
+! https://github.com/MicrosoftDocs/cpp-docs/blob/master/docs/build/arm64-windows-abi-conventions.md
 
 : shift-arg ( -- reg ) X1 ;
 : div-arg ( -- reg ) X0 ;
@@ -73,17 +94,16 @@ big-endian off
 : temp3 ( -- reg ) X12 ;
 
 
-
 ! : pic-tail-reg ( -- reg ) RBX ;
 : return-reg ( -- reg ) X0 ;
-! : nv-reg ( -- reg ) RBX ;
-! : stack-reg ( -- reg ) RSP ;
-! : frame-reg ( -- reg ) RBP ;
-! : link-reg ( -- reg ) R11 ;
+: stack-reg ( -- reg ) SP ;
+! https://developer.arm.com/documentation/dui0801/a/Overview-of-AArch64-state/Link-registers
+: link-reg ( -- reg ) X30 ; ! LR
+: stack-frame-reg ( -- reg ) X29 ; ! FP
+: vm-reg ( -- reg ) X28 ;
+: ds-reg ( -- reg ) X27 ;
+: rs-reg ( -- reg ) X26 ;
 ! : ctx-reg ( -- reg ) R12 ;
-: vm-reg ( -- reg ) X7 ;
-: ds-reg ( -- reg ) X5 ;
-: rs-reg ( -- reg ) X6 ;
 ! : fixnum>slot@ ( -- ) temp0 1 SAR ;
 ! : rex-length ( -- n ) 1 ;
 
@@ -91,7 +111,7 @@ big-endian off
 : jit-call ( name -- )
     0 X0 MOVwi64
     f rc-absolute-cell rel-dlsym
-    X0 BR ;
+    X0 BLR ;
     ! RAX 0 MOV f rc-absolute-cell rel-dlsym
     ! RAX CALL ;
 
@@ -139,6 +159,7 @@ big-endian off
 
 
 [
+
     ! ! ctx-reg is preserved across the call because it is non-volatile
     ! ! in the C ABI
     ! jit-save-context
@@ -150,13 +171,14 @@ big-endian off
 ] JIT-PRIMITIVE jit-define
 
 
-: jit-jump-quot ( -- ) ;
+: jit-jump-quot ( -- )
+    quot-entry-point-offset arg1 ADR
+    arg1 BR ;
     ! arg1 quot-entry-point-offset [+] JMP ;
 
 : jit-call-quot ( -- )
     quot-entry-point-offset arg1 ADR
-    arg1 BR ;
-
+    arg1 BLR ;
     ! arg1 quot-entry-point-offset [+] CALL ;
 
 : signal-handler-save-regs ( -- regs ) { } ;
@@ -276,8 +298,37 @@ big-endian off
 ] JIT-SAFEPOINT jit-define
 
 ! # All arm.64 subprimitives
-
 {
+    { c-to-factor [
+            ! Set up the datastack and retainstack registers
+            ! and jump into the quotation
+
+
+            ! write()
+            ! 68 X8 MOVwi64
+            ! X2 MOVwi64
+            ! 0 SVC
+
+            ! exit(42)
+
+            ! 9999 BRK
+            ! 42 X0 MOVwi64
+            ! 93 X8 MOVwi64
+            ! 0 SVC
+
+            ! Rn Rd MOVr64 ! comment
+            arg1 arg2 MOVr64
+            vm-reg "begin_callback" jit-call-1arg
+
+            return-reg arg1 MOVr64 ! arg1 is return
+            jit-call-quot
+
+            vm-reg "end_callback" jit-call-1arg
+     ] }
+} define-sub-primitives
+
+
+! {
     ! ## Contexts
     ! { (set-context) [ jit-set-context ] }
     ! { (set-context-and-delete) [
@@ -288,44 +339,44 @@ big-endian off
     ! { (start-context-and-delete) [ jit-start-context-and-delete ] }
 
     ! ## Entry points
-    { c-to-factor [
-        ! dst src MOV
-        ! arg2 arg1 MOV
-        ! vm-reg "begin_callback" jit-call-1arg
+    { c-to-factor [
+        ! dst src MOV
+        ! arg2 arg1 MOV
+        ! vm-reg "begin_callback" jit-call-1arg
 
-        ! ! call the quotation
-        ! arg1 return-reg MOV
-        ! jit-call-quot
+        ! ! call the quotation
+        ! arg1 return-reg MOV
+        ! jit-call-quot
 
-        ! vm-reg "end_callback" jit-call-1arg
+        ! vm-reg "end_callback" jit-call-1arg
 
-        [
+        [
 
-            ! write()
-            ! 68 X8 MOVwi64
-            ! X2 MOVwi64
-            ! 0 SVC
+            ! write()
+            ! 68 X8 MOVwi64
+            ! X2 MOVwi64
+            ! 0 SVC
 
-            ! exit(42)
-            9999 BRK
-            42 X0 MOVwi64
-            93 X8 MOVwi64
-            0 SVC
+            ! exit(42)
+            9999 BRK
+            42 X0 MOVwi64
+            93 X8 MOVwi64
+            0 SVC
 
             
 
-            ! Rn Rd MOVr64
-            ! arg1 arg2 MOVr64
-            ! vm-reg "begin_callback" jit-call-1arg
+            ! Rn Rd MOVr64
+            ! arg1 arg2 MOVr64
+            ! vm-reg "begin_callback" jit-call-1arg
 
-            ! return-reg arg1 MOVr64 ! arg1 is return
-            ! jit-call-quot
+            ! return-reg arg1 MOVr64 ! arg1 is return
+            ! jit-call-quot
 
-            ! vm-reg "end_callback" jit-call-1arg
+            ! vm-reg "end_callback" jit-call-1arg
 
-        ] assemble-arm %
+        ] assemble-arm %
 
-    ] }
+    ] }
     ! { unwind-native-frames [ ] }
 
     ! ## Math
@@ -390,12 +441,14 @@ big-endian off
     !     ! Return with new callstack
     !     0 RET
     ! ] }
-} define-sub-primitives
+} define-sub-primitives
 
 
 
 ! C to Factor entry point
 [
+
+    9999 BRK
     ! ! Optimizing compiler's side of callback accesses
     ! ! arguments that are on the stack via the frame pointer.
     ! ! On x86-32 fastcall, and x86-64, some arguments are passed
@@ -550,16 +603,29 @@ big-endian off
     ! temp0 word-entry-point-offset [+] JMP
 ] JIT-EXECUTE jit-define
 
+
+! https://elixir.bootlin.com/linux/latest/source/arch/arm64/kernel/stacktrace.c#L22
 [
-    ! stack-reg stack-frame-size bootstrap-cell - SUB
+    ! x64 ! stack-reg stack-frame-size bootstrap-cell - SUB
+
+
+    ! : link-reg ( -- reg ) X30 ; ! LR
+    ! : stack-frame-reg ( -- reg ) X29 ; ! FP
+
+    ! ! make room for LR plus magic number of callback, 16byte align
+    stack-frame-size bootstrap-cell 2 * + stack-reg stack-reg SUBi64
+    ! link-reg X29 stack-reg STP
+    -16 SP link-reg X29 STP-pre
 ] JIT-PROLOG jit-define
 
 [
-    ! stack-reg stack-frame-size bootstrap-cell - ADD
+    ! x64 ! stack-reg stack-frame-size bootstrap-cell - ADD
+    -16 SP link-reg X29 LDP-pre
+    stack-frame-size bootstrap-cell 2 * + stack-reg stack-reg ADDi64
 ] JIT-EPILOG jit-define
 
 [
-    ! 0 RET
+    f RET
 ] JIT-RETURN jit-define
 
 ! ! ! Polymorphic inline caches