| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366 |
- //-------------------------------------------------------------------------------------------------------
- // ChakraCore/Pal
- // Contains portions (c) copyright Microsoft, portions copyright (c) the .NET Foundation and Contributors
- // and edits (c) copyright the ChakraCore Contributors.
- // See THIRD-PARTY-NOTICES.txt in the project root for .NET Foundation license
- // Licensed under the MIT license. See LICENSE.txt file in the project root for full license information.
- //-------------------------------------------------------------------------------------------------------
- .macro NESTED_ENTRY Name, Section, Handler
- LEAF_ENTRY \Name, \Section
- .ifnc \Handler, NoHandler
- #if defined(__APPLE__)
- .cfi_personality 0x9b, C_FUNC(\Handler) // 0x9b == DW_EH_PE_indirect | DW_EH_PE_pcrel | DW_EH_PE_sdata4
- #else
- .cfi_personality 0x1b, C_FUNC(\Handler) // 0x1b == DW_EH_PE_pcrel | DW_EH_PE_sdata4
- #endif
- .endif
- .endm
- .macro NESTED_END Name, Section
- LEAF_END \Name, \Section
- .endm
- .macro PATCH_LABEL Name
- .global C_FUNC(\Name)
- C_FUNC(\Name):
- .endm
- .macro LEAF_ENTRY Name, Section
- .global C_FUNC(\Name)
- #if defined(__APPLE__)
- .text
- .p2align 2
- #else
- .type \Name, %function
- #endif
- C_FUNC(\Name):
- .cfi_startproc
- .endm
- .macro LEAF_END Name, Section
- #if !defined(__APPLE__)
- .size \Name, .-\Name
- #endif
- .cfi_endproc
- .endm
- .macro LEAF_END_MARKED Name, Section
- C_FUNC(\Name\()_End):
- .global C_FUNC(\Name\()_End)
- LEAF_END \Name, \Section
- // make sure this symbol gets its own address
- nop
- .endm
- .macro PREPARE_EXTERNAL_VAR Name, HelperReg
- #if defined(__APPLE__)
- adrp \HelperReg, C_FUNC(\Name)@GOTPAGE
- ldr \HelperReg, [\HelperReg, C_FUNC(\Name)@GOTPAGEOFF]
- #else
- adrp \HelperReg, C_FUNC(\Name)
- add \HelperReg, \HelperReg, :lo12:C_FUNC(\Name)
- #endif
- .endm
- .macro PROLOG_STACK_ALLOC Size
- sub sp, sp, \Size
- .endm
- .macro EPILOG_STACK_FREE Size
- add sp, sp, \Size
- .cfi_adjust_cfa_offset -\Size
- .endm
- .macro EPILOG_STACK_RESTORE
- mov sp, fp
- .cfi_restore sp
- .endm
- .macro PROLOG_SAVE_REG reg, ofs
- str \reg, [sp, \ofs]
- .cfi_rel_offset \reg, \ofs
- .endm
- .macro PROLOG_SAVE_REG_PAIR reg1, reg2, ofs
- stp \reg1, \reg2, [sp, \ofs]
- .cfi_rel_offset \reg1, \ofs
- .cfi_rel_offset \reg2, \ofs + 8
- .ifc \reg1, fp
- mov fp, sp
- .cfi_def_cfa_register fp
- .endif
- .endm
- .macro PROLOG_SAVE_REG_PAIR_INDEXED reg1, reg2, ofs
- stp \reg1, \reg2, [sp, \ofs]!
- .cfi_adjust_cfa_offset -\ofs
- .cfi_rel_offset \reg1, 0
- .cfi_rel_offset \reg2, 8
- .ifc \reg1, fp
- mov fp, sp
- .cfi_def_cfa_register fp
- .endif
- .endm
- .macro EPILOG_RESTORE_REG reg, ofs
- ldr \reg, [sp, \ofs]
- .cfi_restore \reg
- .endm
- .macro EPILOG_RESTORE_REG_PAIR reg1, reg2, ofs
- ldp \reg1, \reg2, [sp, \ofs]
- .cfi_restore \reg1
- .cfi_restore \reg2
- .endm
- .macro EPILOG_RESTORE_REG_PAIR_INDEXED reg1, reg2, ofs
- ldp \reg1, \reg2, [sp], \ofs
- .cfi_restore \reg1
- .cfi_restore \reg2
- .cfi_adjust_cfa_offset -\ofs
- .endm
- .macro EPILOG_RETURN
- ret
- .endm
- .macro EMIT_BREAKPOINT
- brk #0
- .endm
- //-----------------------------------------------------------------------------
- // 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
- //
- // Stack layout:
- //
- // (stack parameters)
- // ...
- // fp
- // lr
- // CalleeSavedRegisters::x28
- // CalleeSavedRegisters::x27
- // CalleeSavedRegisters::x26
- // CalleeSavedRegisters::x25
- // CalleeSavedRegisters::x24
- // CalleeSavedRegisters::x23
- // CalleeSavedRegisters::x22
- // CalleeSavedRegisters::x21
- // CalleeSavedRegisters::x20
- // CalleeSavedRegisters::x19
- // CalleeSavedRegisters::x30 (Lr)
- // CalleeSavedRegisters::x29 (Fp)
- // ArgumentRegisters::x7
- // ArgumentRegisters::x6
- // ArgumentRegisters::x5
- // ArgumentRegisters::x4
- // ArgumentRegisters::x3
- // ArgumentRegisters::x2
- // ArgumentRegisters::x1
- // ArgumentRegisters::x0
- // FloatRegisters::q7
- // FloatRegisters::q6
- // FloatRegisters::q5
- // FloatRegisters::q4
- // FloatRegisters::q3
- // FloatRegisters::q2
- // FloatRegisters::q1
- // FloatRegisters::q0
- .macro PROLOG_WITH_TRANSITION_BLOCK extraLocals = 0, SaveFPArgs = 1
- __PWTB_FloatArgumentRegisters = \extraLocals
- __PWTB_SaveFPArgs = \SaveFPArgs
- .if ((__PWTB_FloatArgumentRegisters % 16) != 0)
- __PWTB_FloatArgumentRegisters = __PWTB_FloatArgumentRegisters + 8
- .endif
- __PWTB_TransitionBlock = __PWTB_FloatArgumentRegisters
- .if (__PWTB_SaveFPArgs == 1)
- __PWTB_TransitionBlock = __PWTB_TransitionBlock + SIZEOF__FloatArgumentRegisters
- .endif
- __PWTB_StackAlloc = __PWTB_TransitionBlock
- __PWTB_ArgumentRegisters = __PWTB_StackAlloc + 104
- __PWTB_ArgumentRegister_FirstArg = __PWTB_ArgumentRegisters + 8
- PROLOG_SAVE_REG_PAIR_INDEXED 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 == 1)
- SAVE_FLOAT_ARGUMENT_REGISTERS sp, \extraLocals
- .endif
- .endm
- //-----------------------------------------------------------------------------
- // The Following sets of SAVE_*_REGISTERS expect the memory to be reserved and
- // base address to be passed in $reg
- //
- // Reserve 64 bytes of memory before calling SAVE_ARGUMENT_REGISTERS
- .macro SAVE_ARGUMENT_REGISTERS reg, ofs
- str x8, [\reg, #(\ofs)]
- stp x0, x1, [\reg, #(\ofs + 8)]
- stp x2, x3, [\reg, #(\ofs + 24)]
- stp x4, x5, [\reg, #(\ofs + 40)]
- stp x6, x7, [\reg, #(\ofs + 56)]
- .endm
- // Reserve 128 bytes of memory before calling SAVE_FLOAT_ARGUMENT_REGISTERS
- .macro SAVE_FLOAT_ARGUMENT_REGISTERS reg, ofs
- stp q0, q1, [\reg, #(\ofs)]
- stp q2, q3, [\reg, #(\ofs + 32)]
- stp q4, q5, [\reg, #(\ofs + 64)]
- stp q6, q7, [\reg, #(\ofs + 96)]
- .endm
- .macro RESTORE_ARGUMENT_REGISTERS reg, ofs
- ldr x8, [\reg, #(\ofs)]
- ldp x0, x1, [\reg, #(\ofs + 8)]
- ldp x2, x3, [\reg, #(\ofs + 24)]
- ldp x4, x5, [\reg, #(\ofs + 40)]
- ldp x6, x7, [\reg, #(\ofs + 56)]
- .endm
- .macro RESTORE_FLOAT_ARGUMENT_REGISTERS reg, ofs
- ldp q0, q1, [\reg, #(\ofs)]
- ldp q2, q3, [\reg, #(\ofs + 32)]
- ldp q4, q5, [\reg, #(\ofs + 64)]
- ldp q6, q7, [\reg, #(\ofs + 96)]
- .endm
- .macro EPILOG_BRANCH Target
- b \Target
- .endm
- .macro EPILOG_BRANCH_REG reg
- br \reg
- .endm
- .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_INDEXED fp, lr, 176
- ret
- .endm
- //-----------------------------------------------------------------------------
- // 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 == 1)
- 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_INDEXED fp, lr, 176
- .endm
- // ------------------------------------------------------------------
- // 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
- #if NOTYET
- 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
- #else
- EMIT_BREAKPOINT
- #endif
- .endm
|