diff options
author | Jan Kotas <jkotas@microsoft.com> | 2018-05-19 18:26:14 +0300 |
---|---|---|
committer | GitHub <noreply@github.com> | 2018-05-19 18:26:14 +0300 |
commit | 69568a3d8d22a7671dc17f6e3c9d49860c7c925f (patch) | |
tree | f7a76c170ab04df3e2cb88bcd0a3f56edb571aad /src/Native | |
parent | 087b8f88e266ca28994ffa5a1c77ac0810827c63 (diff) | |
parent | f563c36911083bca9f919ad9bd2a2e58dc75f95b (diff) |
Merge pull request #5816 from dotnet/nmirror
Merge nmirror to master
Diffstat (limited to 'src/Native')
-rw-r--r-- | src/Native/Runtime/arm64/GcProbe.asm | 112 |
1 files changed, 61 insertions, 51 deletions
diff --git a/src/Native/Runtime/arm64/GcProbe.asm b/src/Native/Runtime/arm64/GcProbe.asm index 3554c8eb3..f83141684 100644 --- a/src/Native/Runtime/arm64/GcProbe.asm +++ b/src/Native/Runtime/arm64/GcProbe.asm @@ -48,7 +48,7 @@ PROBE_FRAME_SIZE field 0 ;; Perform the parts of setting up a probe frame that can occur during the prolog (and indeed this macro ;; can only be called from within the prolog). MACRO - ALLOC_PROBE_FRAME $extraStackSpace + ALLOC_PROBE_FRAME $extraStackSpace, $saveFPRegisters ;; First create PInvokeTransitionFrame PROLOG_SAVE_REG_PAIR fp, lr, #-(PROBE_FRAME_SIZE + $extraStackSpace)! ;; Push down stack pointer and store FP and LR @@ -80,16 +80,18 @@ PROBE_FRAME_SIZE field 0 ;; Slot at [sp, #0x118] is reserved for NZCV - ; Save the floating return registers - PROLOG_NOP stp d0, d1, [sp, #0x120] - PROLOG_NOP stp d2, d3, [sp, #0x130] + ;; Save the floating return registers + IF $saveFPRegisters + PROLOG_NOP stp d0, d1, [sp, #0x120] + PROLOG_NOP stp d2, d3, [sp, #0x130] + ENDIF MEND ;; Undo the effects of an ALLOC_PROBE_FRAME. This may only be called within an epilog. Note that all ;; registers are restored (apart for sp and pc), even volatiles. MACRO - FREE_PROBE_FRAME $extraStackSpace + FREE_PROBE_FRAME $extraStackSpace, $restoreFPRegisters ;; Restore the scratch registers PROLOG_NOP ldr x0, [sp, #0x78] @@ -105,8 +107,10 @@ PROBE_FRAME_SIZE field 0 PROLOG_NOP ldr lr, [sp, #0x110] ; Restore the floating return registers - EPILOG_NOP ldp d0, d1, [sp, #0x120] - EPILOG_NOP ldp d2, d3, [sp, #0x130] + IF $restoreFPRegisters + EPILOG_NOP ldp d0, d1, [sp, #0x120] + EPILOG_NOP ldp d2, d3, [sp, #0x130] + ENDIF ;; Restore callee saved registers EPILOG_RESTORE_REG_PAIR x19, x20, #0x20 @@ -167,7 +171,7 @@ __PPF_ThreadReg SETS "$threadReg" ; Define the method prolog, allocating enough stack space for the PInvokeTransitionFrame and saving ; incoming register values into it. - ALLOC_PROBE_FRAME 0 + ALLOC_PROBE_FRAME 0, {true} ; If the caller didn't provide a value for $threadReg then generate code to fetch the Thread* into x2. ; Record that x2 holds the Thread* in our local variable. @@ -188,58 +192,64 @@ __PPF_ThreadReg SETS "x2" MACRO EPILOG_PROBE_FRAME - FREE_PROBE_FRAME 0 + FREE_PROBE_FRAME 0, {true} EPILOG_RETURN MEND -;; ALLOC_PROBE_FRAME will save the first 4 vfp registers, in order to avoid trashing VFP registers across the loop -;; hijack, we must save the rest -- d4-d31 (28). -EXTRA_SAVE_SIZE equ (28*8) +;; In order to avoid trashing VFP registers across the loop hijack we must save all user registers, so that +;; registers used by the loop being hijacked will not be affected. Unlike ARM32 where neon registers (NQ0, ..., NQ15) +;; are fully covered by the floating point registers D0 ... D31, we have 32 neon registers Q0, ... Q31 on ARM64 +;; which are not fully covered by the register D0 ... D31. Therefore we must explicitly save all Q registers. +EXTRA_SAVE_SIZE equ (32*16) MACRO ALLOC_LOOP_HIJACK_FRAME PROLOG_STACK_ALLOC EXTRA_SAVE_SIZE -;; save VFP registers that were not saved by the ALLOC_PROBE_FRAME - PROLOG_NOP stp d4, d5, [sp] - PROLOG_NOP stp d6, d7, [sp, #0x10] - PROLOG_NOP stp d8, d9, [sp, #0x20] - PROLOG_NOP stp d10, d11, [sp, #0x30] - PROLOG_NOP stp d12, d13, [sp, #0x40] - PROLOG_NOP stp d14, d15, [sp, #0x50] - PROLOG_NOP stp d16, d17, [sp, #0x60] - PROLOG_NOP stp d18, d19, [sp, #0x70] - PROLOG_NOP stp d20, d21, [sp, #0x80] - PROLOG_NOP stp d22, d23, [sp, #0x90] - PROLOG_NOP stp d24, d25, [sp, #0xA0] - PROLOG_NOP stp d26, d27, [sp, #0xB0] - PROLOG_NOP stp d28, d29, [sp, #0xC0] - PROLOG_NOP stp d30, d31, [sp, #0xD0] - - ALLOC_PROBE_FRAME 0 + ;; Save all neon registers + PROLOG_NOP stp q0, q1, [sp] + PROLOG_NOP stp q2, q3, [sp, #0x20] + PROLOG_NOP stp q4, q5, [sp, #0x40] + PROLOG_NOP stp q6, q7, [sp, #0x60] + PROLOG_NOP stp q8, q9, [sp, #0x80] + PROLOG_NOP stp q10, q11, [sp, #0xA0] + PROLOG_NOP stp q12, q13, [sp, #0xC0] + PROLOG_NOP stp q14, q15, [sp, #0xE0] + PROLOG_NOP stp q16, q17, [sp, #0x100] + PROLOG_NOP stp q18, q19, [sp, #0x120] + PROLOG_NOP stp q20, q21, [sp, #0x140] + PROLOG_NOP stp q22, q23, [sp, #0x160] + PROLOG_NOP stp q24, q25, [sp, #0x180] + PROLOG_NOP stp q26, q27, [sp, #0x1A0] + PROLOG_NOP stp q28, q29, [sp, #0x1C0] + PROLOG_NOP stp q30, q31, [sp, #0x1E0] + + ALLOC_PROBE_FRAME 0, {false} MEND MACRO FREE_LOOP_HIJACK_FRAME - FREE_PROBE_FRAME 0 - -;; restore VFP registers that will not be restored by the FREE_PROBE_FRAME - PROLOG_NOP ldp d4, d5, [sp] - PROLOG_NOP ldp d6, d7, [sp, #0x10] - PROLOG_NOP ldp d8, d9, [sp, #0x20] - PROLOG_NOP ldp d10, d11, [sp, #0x30] - PROLOG_NOP ldp d12, d13, [sp, #0x40] - PROLOG_NOP ldp d14, d15, [sp, #0x50] - PROLOG_NOP ldp d16, d17, [sp, #0x60] - PROLOG_NOP ldp d18, d19, [sp, #0x70] - PROLOG_NOP ldp d20, d21, [sp, #0x80] - PROLOG_NOP ldp d22, d23, [sp, #0x90] - PROLOG_NOP ldp d24, d25, [sp, #0xA0] - PROLOG_NOP ldp d26, d27, [sp, #0xB0] - PROLOG_NOP ldp d28, d29, [sp, #0xC0] - PROLOG_NOP ldp d30, d31, [sp, #0xD0] + FREE_PROBE_FRAME 0, {false} + + ;; restore all neon registers + PROLOG_NOP ldp q0, q1, [sp] + PROLOG_NOP ldp q2, q3, [sp, #0x20] + PROLOG_NOP ldp q4, q5, [sp, #0x40] + PROLOG_NOP ldp q6, q7, [sp, #0x60] + PROLOG_NOP ldp q8, q9, [sp, #0x80] + PROLOG_NOP ldp q10, q11, [sp, #0xA0] + PROLOG_NOP ldp q12, q13, [sp, #0xC0] + PROLOG_NOP ldp q14, q15, [sp, #0xE0] + PROLOG_NOP ldp q16, q17, [sp, #0x100] + PROLOG_NOP ldp q18, q19, [sp, #0x120] + PROLOG_NOP ldp q20, q21, [sp, #0x140] + PROLOG_NOP ldp q22, q23, [sp, #0x160] + PROLOG_NOP ldp q24, q25, [sp, #0x180] + PROLOG_NOP ldp q26, q27, [sp, #0x1A0] + PROLOG_NOP ldp q28, q29, [sp, #0x1C0] + PROLOG_NOP ldp q30, q31, [sp, #0x1E0] EPILOG_STACK_FREE EXTRA_SAVE_SIZE MEND @@ -405,7 +415,7 @@ EXTRA_SAVE_SIZE equ (28*8) EPILOG_PROBE_FRAME 1 - FREE_PROBE_FRAME 0 + FREE_PROBE_FRAME 0, {true} EPILOG_NOP mov w0, #STATUS_REDHAWK_THREAD_ABORT EPILOG_NOP mov x1, lr ;; return address as exception PC EPILOG_NOP b RhpThrowHwEx @@ -630,7 +640,7 @@ EXTRA_SAVE_SIZE equ (28*8) EHJumpProbeProlog PROLOG_NOP mov x0, x1 ; move the ex object reference into x0 so we can report it - ALLOC_PROBE_FRAME 0x10 + ALLOC_PROBE_FRAME 0x10, {true} str x2, [sp, #PROBE_FRAME_SIZE] ;; x2 <- GetThread(), TRASHES x1 @@ -665,7 +675,7 @@ EXTRA_SAVE_SIZE equ (28*8) EHJumpProbeEpilog ldr x2, [sp, #PROBE_FRAME_SIZE] - FREE_PROBE_FRAME 0x10 ; This restores exception object back into x0 + FREE_PROBE_FRAME 0x10, {true} ; This restores exception object back into x0 EPILOG_NOP mov x1, x0 ; Move the Exception object back into x1 where the catch handler expects it EPILOG_NOP ret x2 MEND @@ -898,8 +908,8 @@ Abort ;; ;; [sp + 118] -> NZCV ;; - ;; [sp + 120] -> d0, d1, d2, d3 - ;; [sp + 140] -> d4 ... d31 + ;; [sp + 120] -> not used + ;; [sp + 140] -> q0 ... q31 ;; ALLOC_LOOP_HIJACK_FRAME |