summaryrefslogtreecommitdiff
path: root/src/vm/arm64/asmmacros.h
diff options
context:
space:
mode:
Diffstat (limited to 'src/vm/arm64/asmmacros.h')
-rw-r--r--src/vm/arm64/asmmacros.h296
1 files changed, 296 insertions, 0 deletions
diff --git a/src/vm/arm64/asmmacros.h b/src/vm/arm64/asmmacros.h
new file mode 100644
index 0000000000..74613daa8f
--- /dev/null
+++ b/src/vm/arm64/asmmacros.h
@@ -0,0 +1,296 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+;; ==++==
+;;
+
+;;
+;; ==--==
+
+;-----------------------------------------------------------------------------
+; Macro used to assign an alternate name to a symbol containing characters normally disallowed in a symbol
+; name (e.g. C++ decorated names).
+ MACRO
+ SETALIAS $name, $symbol
+ GBLS $name
+$name SETS "|$symbol|"
+ MEND
+
+;-----------------------------------------------------------------------------
+; Basic extension of Assembler Macros- For Consistency
+
+ MACRO
+ EPILOG_BRANCH_REG $reg
+
+ EPILOG_NOP br $reg
+ MEND
+;-----------------------------------------------------------------------------
+
+ MACRO
+ EPILOG_BRANCH $_target
+
+ EPILOG_NOP b $_target
+ MEND
+;-----------------------------------------------------------------------------
+; The following group of macros assist in implementing prologs and epilogs for methods that set up some
+; subclass of TransitionFrame. They ensure that the SP is 16-byte aligned at the conclusion of the prolog
+
+;-----------------------------------------------------------------------------
+; Define the prolog for a TransitionFrame-based method. This macro should be called first in the method and
+; comprises the entire prolog (i.e. don't modify SP after calling this).The locals must be 8 byte aligned
+;
+ MACRO
+ PROLOG_WITH_TRANSITION_BLOCK $extraLocals, $SaveFPArgs
+
+ GBLA __PWTB_FloatArgumentRegisters
+ GBLA __PWTB_ArgumentRegisters
+ GBLA __PWTB_StackAlloc
+ GBLA __PWTB_TransitionBlock
+ GBLL __PWTB_SaveFPArgs
+
+ IF "$SaveFPArgs" != ""
+__PWTB_SaveFPArgs SETL $SaveFPArgs
+ ELSE
+__PWTB_SaveFPArgs SETL {true}
+ ENDIF
+
+ IF "$extraLocals" != ""
+__PWTB_FloatArgumentRegisters SETA $extraLocals
+ ELSE
+__PWTB_FloatArgumentRegisters SETA 0
+ ENDIF
+
+ IF __PWTB_FloatArgumentRegisters:MOD:16 != 0
+__PWTB_FloatArgumentRegisters SETA __PWTB_FloatArgumentRegisters + 8
+ ENDIF
+
+ IF __PWTB_SaveFPArgs
+__PWTB_TransitionBlock SETA __PWTB_FloatArgumentRegisters + SIZEOF__FloatArgumentRegisters
+ ELSE
+__PWTB_TransitionBlock SETA __PWTB_FloatArgumentRegisters
+ ENDIF
+
+__PWTB_StackAlloc SETA __PWTB_TransitionBlock
+__PWTB_ArgumentRegisters SETA __PWTB_StackAlloc + 96
+
+ PROLOG_SAVE_REG_PAIR fp, lr, #-176!
+ ; Spill callee saved registers
+ PROLOG_SAVE_REG_PAIR x19, x20, #16
+ PROLOG_SAVE_REG_PAIR x21, x22, #32
+ PROLOG_SAVE_REG_PAIR x23, x24, #48
+ PROLOG_SAVE_REG_PAIR x25, x26, #64
+ PROLOG_SAVE_REG_PAIR x27, x28, #80
+
+ ; Allocate space for the rest of the frame
+ PROLOG_STACK_ALLOC __PWTB_StackAlloc
+
+ ; Spill argument registers.
+ SAVE_ARGUMENT_REGISTERS sp, __PWTB_ArgumentRegisters
+
+ IF __PWTB_SaveFPArgs
+ SAVE_FLOAT_ARGUMENT_REGISTERS sp, __PWTB_FloatArgumentRegisters
+ ENDIF
+
+ MEND
+
+;-----------------------------------------------------------------------------
+; Provides a matching epilog to PROLOG_WITH_TRANSITION_BLOCK and returns to caller.
+;
+ MACRO
+ EPILOG_WITH_TRANSITION_BLOCK_RETURN
+
+ EPILOG_STACK_FREE __PWTB_StackAlloc
+
+ EPILOG_RESTORE_REG_PAIR x19, x20, #16
+ EPILOG_RESTORE_REG_PAIR x21, x22, #32
+ EPILOG_RESTORE_REG_PAIR x23, x24, #48
+ EPILOG_RESTORE_REG_PAIR x25, x26, #64
+ EPILOG_RESTORE_REG_PAIR x27, x28, #80
+ EPILOG_RESTORE_REG_PAIR fp, lr, #176!
+ EPILOG_RETURN
+ MEND
+
+;-----------------------------------------------------------------------------
+; Provides a matching epilog to PROLOG_WITH_TRANSITION_BLOCK and ends by preparing for tail-calling.
+; Since this is a tail call argument registers are restored.
+;
+ MACRO
+ EPILOG_WITH_TRANSITION_BLOCK_TAILCALL
+
+ IF __PWTB_SaveFPArgs
+ RESTORE_FLOAT_ARGUMENT_REGISTERS sp, __PWTB_FloatArgumentRegisters
+ ENDIF
+
+ RESTORE_ARGUMENT_REGISTERS sp, __PWTB_ArgumentRegisters
+ EPILOG_STACK_FREE __PWTB_StackAlloc
+
+ EPILOG_RESTORE_REG_PAIR x19, x20, #16
+ EPILOG_RESTORE_REG_PAIR x21, x22, #32
+ EPILOG_RESTORE_REG_PAIR x23, x24, #48
+ EPILOG_RESTORE_REG_PAIR x25, x26, #64
+ EPILOG_RESTORE_REG_PAIR x27, x28, #80
+ EPILOG_RESTORE_REG_PAIR fp, lr, #176!
+ MEND
+
+;-----------------------------------------------------------------------------
+; Macro used to end a function with explicit _End label
+ MACRO
+ LEAF_END_MARKED $FuncName
+
+ LCLS __EndLabelName
+__EndLabelName SETS "$FuncName":CC:"_End"
+ EXPORT $__EndLabelName
+$__EndLabelName
+
+ LEAF_END $FuncName
+
+ MEND
+;-----------------------------------------------------------------------------
+; Macro use for enabling C++ to know where to patch code at runtime.
+ MACRO
+ PATCH_LABEL $FuncName
+$FuncName
+ EXPORT $FuncName
+
+ MEND
+
+;-----------------------------------------------------------------------------
+; The Following sets of SAVE_*_REGISTERS expect the memory to be reserved and
+; base address to be passed in $reg
+;
+
+; Reserve 72 bytes of memory before calling SAVE_ARGUMENT_REGISTERS
+ MACRO
+ SAVE_ARGUMENT_REGISTERS $reg, $offset
+
+ GBLA __PWTB_SAVE_ARGUMENT_REGISTERS_OFFSET
+
+ IF "$offset" != ""
+__PWTB_SAVE_ARGUMENT_REGISTERS_OFFSET SETA $offset
+ ELSE
+__PWTB_SAVE_ARGUMENT_REGISTERS_OFFSET SETA 0
+ ENDIF
+
+ stp x0, x1, [$reg, #(__PWTB_SAVE_ARGUMENT_REGISTERS_OFFSET)]
+ stp x2, x3, [$reg, #(__PWTB_SAVE_ARGUMENT_REGISTERS_OFFSET + 16)]
+ stp x4, x5, [$reg, #(__PWTB_SAVE_ARGUMENT_REGISTERS_OFFSET + 32)]
+ stp x6, x7, [$reg, #(__PWTB_SAVE_ARGUMENT_REGISTERS_OFFSET + 48)]
+ str x8, [$reg, #(__PWTB_SAVE_ARGUMENT_REGISTERS_OFFSET + 64)]
+ MEND
+
+; Reserve 64 bytes of memory before calling SAVE_FLOAT_ARGUMENT_REGISTERS
+ MACRO
+ SAVE_FLOAT_ARGUMENT_REGISTERS $reg, $offset
+
+ GBLA __PWTB_SAVE_FLOAT_ARGUMENT_REGISTERS_OFFSET
+
+ IF "$offset" != ""
+__PWTB_SAVE_FLOAT_ARGUMENT_REGISTERS_OFFSET SETA $offset
+ ELSE
+__PWTB_SAVE_FLOAT_ARGUMENT_REGISTERS_OFFSET SETA 0
+ ENDIF
+
+ stp d0, d1, [$reg, #(__PWTB_SAVE_FLOAT_ARGUMENT_REGISTERS_OFFSET)]
+ stp d2, d3, [$reg, #(__PWTB_SAVE_FLOAT_ARGUMENT_REGISTERS_OFFSET + 16)]
+ stp d4, d5, [$reg, #(__PWTB_SAVE_FLOAT_ARGUMENT_REGISTERS_OFFSET + 32)]
+ stp d6, d7, [$reg, #(__PWTB_SAVE_FLOAT_ARGUMENT_REGISTERS_OFFSET + 48)]
+ MEND
+
+ MACRO
+ RESTORE_ARGUMENT_REGISTERS $reg, $offset
+
+ GBLA __PWTB_RESTORE_ARGUMENT_REGISTERS_OFFSET
+
+ IF "$offset" != ""
+__PWTB_RESTORE_ARGUMENT_REGISTERS_OFFSET SETA $offset
+ ELSE
+__PWTB_RESTORE_ARGUMENT_REGISTERS_OFFSET SETA 0
+ ENDIF
+
+ ldp x0, x1, [$reg, #(__PWTB_RESTORE_ARGUMENT_REGISTERS_OFFSET)]
+ ldp x2, x3, [$reg, #(__PWTB_RESTORE_ARGUMENT_REGISTERS_OFFSET + 16)]
+ ldp x4, x5, [$reg, #(__PWTB_RESTORE_ARGUMENT_REGISTERS_OFFSET + 32)]
+ ldp x6, x7, [$reg, #(__PWTB_RESTORE_ARGUMENT_REGISTERS_OFFSET + 48)]
+ ldr x8, [$reg, #(__PWTB_RESTORE_ARGUMENT_REGISTERS_OFFSET + 64)]
+ MEND
+
+ MACRO
+ RESTORE_FLOAT_ARGUMENT_REGISTERS $reg, $offset
+
+ GBLA __PWTB_RESTORE_FLOAT_ARGUMENT_REGISTERS_OFFSET
+
+ IF "$offset" != ""
+__PWTB_RESTORE_FLOAT_ARGUMENT_REGISTERS_OFFSET SETA $offset
+ ELSE
+__PWTB_RESTORE_FLOAT_ARGUMENT_REGISTERS_OFFSET SETA 0
+ ENDIF
+
+ ldp d0, d1, [$reg, #(__PWTB_RESTORE_FLOAT_ARGUMENT_REGISTERS_OFFSET)]
+ ldp d2, d3, [$reg, #(__PWTB_RESTORE_FLOAT_ARGUMENT_REGISTERS_OFFSET + 16)]
+ ldp d4, d5, [$reg, #(__PWTB_RESTORE_FLOAT_ARGUMENT_REGISTERS_OFFSET + 32)]
+ ldp d6, d7, [$reg, #(__PWTB_RESTORE_FLOAT_ARGUMENT_REGISTERS_OFFSET + 48)]
+ MEND
+
+; ------------------------------------------------------------------
+; Macro to generate Redirection Stubs
+;
+; $reason : reason for redirection
+; Eg. GCThreadControl
+; NOTE: If you edit this macro, make sure you update GetCONTEXTFromRedirectedStubStackFrame.
+; This function is used by both the personality routine and the debugger to retrieve the original CONTEXT.
+ MACRO
+ GenerateRedirectedHandledJITCaseStub $reason
+
+ GBLS __RedirectionStubFuncName
+ GBLS __RedirectionStubEndFuncName
+ GBLS __RedirectionFuncName
+__RedirectionStubFuncName SETS "RedirectedHandledJITCaseFor":CC:"$reason":CC:"_Stub"
+__RedirectionStubEndFuncName SETS "RedirectedHandledJITCaseFor":CC:"$reason":CC:"_StubEnd"
+__RedirectionFuncName SETS "|?RedirectedHandledJITCaseFor":CC:"$reason":CC:"@Thread@@CAXXZ|"
+
+ IMPORT $__RedirectionFuncName
+
+ NESTED_ENTRY $__RedirectionStubFuncName
+ PROLOG_SAVE_REG_PAIR fp, lr, #-16!
+ sub sp, sp, #16 ; stack slot for CONTEXT * and padding
+
+ ;REDIRECTSTUB_SP_OFFSET_CONTEXT is defined in asmconstants.h and is used in GetCONTEXTFromRedirectedStubStackFrame
+ ;If CONTEXT is not saved at 0 offset from SP it must be changed as well.
+ ASSERT REDIRECTSTUB_SP_OFFSET_CONTEXT == 0
+
+ ; Stack alignment. This check is necessary as this function can be
+ ; entered before complete execution of the prolog of another function.
+ and x8, fp, #15
+ sub sp, sp, x8
+
+
+ ;
+ ; Save a copy of the redirect CONTEXT*.
+ ; This is needed for the debugger to unwind the stack.
+ ;
+ bl GetCurrentSavedRedirectContext
+ str x0, [sp]
+
+ ;
+ ; Fetch the interrupted pc and save it as our return address.
+ ;
+ ldr x1, [x0, #CONTEXT_Pc]
+ str x1, [fp, #8]
+
+ ;
+ ; Call target, which will do whatever we needed to do in the context
+ ; of the target thread, and will RtlRestoreContext when it is done.
+ ;
+ bl $__RedirectionFuncName
+
+ EMIT_BREAKPOINT ; Unreachable
+
+; Put a label here to tell the debugger where the end of this function is.
+$__RedirectionStubEndFuncName
+ EXPORT $__RedirectionStubEndFuncName
+
+ NESTED_END
+
+ MEND
+