| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272 |
- // -------------------------------------------------------------------------------------------------------
- // Copyright (C) Microsoft. All rights reserved.
- // Licensed under the MIT license. See LICENSE.txt file in the project root for full license information.
- // -------------------------------------------------------------------------------------------------------
- // 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 LEAF_ENTRY Name, Section
- .thumb_func
- .global C_FUNC(\Name)
- .type \Name, %function
- C_FUNC(\Name):
- .fnstart
- .endm
- .macro NESTED_ENTRY Name, Section, Handler
- LEAF_ENTRY \Name, \Section
- .ifnc \Handler, NoHandler
- .personality C_FUNC(\Handler)
- .endif
- .endm
- .macro NESTED_END Name, Section
- LEAF_END \Name, \Section
- .endm
- .macro NESTED_END_MARKED Name, Section
- LEAF_END_MARKED \Name, \Section
- .endm
- .macro PATCH_LABEL Name
- .thumb_func
- .global C_FUNC(\Name)
- C_FUNC(\Name):
- .endm
- .macro LEAF_END Name, Section
- .size \Name, .-\Name
- .fnend
- .endm
- .macro LEAF_END_MARKED Name, Section
- .thumb_func
- .global C_FUNC(\Name\()_End)
- C_FUNC(\Name\()_End):
- LEAF_END \Name, \Section
- .endm
- .macro PREPARE_EXTERNAL_VAR Name, HelperReg
- ldr \HelperReg, [pc, #C_FUNC(\Name)@GOTPCREL]
- .endm
- .macro push_nonvol_reg Register
- push \Register
- .save \Register
- .endm
- .macro pop_nonvol_reg Register
- pop \Register
- .endm
- .macro vpush_nonvol_reg Register
- vpush \Register
- .vsave \Register
- .endm
- .macro vpop_nonvol_reg Register
- vpop \Register
- .endm
- .macro alloc_stack Size
- sub sp, sp, (\Size)
- .pad #(\Size)
- .endm
- .macro free_stack Size
- add sp, sp, (\Size)
- .pad #-(\Size)
- .endm
- .macro POP_CALLEE_SAVED_REGISTERS
- pop_nonvol_reg "{r4-r11, lr}"
- .endm
- .macro PUSH_CALLEE_SAVED_REGISTERS
- push_nonvol_reg "{r4-r11, lr}"
- .endm
- .macro push_register Reg
- push \Reg
- .endm
- .macro push_argument_register Reg
- push_register \Reg
- .endm
- .macro PUSH_ARGUMENT_REGISTERS
- push {r0-r3}
- .save {r0-r3}
- .endm
- .macro pop_register Reg
- pop \Reg
- .endm
- .macro pop_argument_register Reg
- pop_register \Reg
- .endm
- .macro POP_ARGUMENT_REGISTERS
- pop {r0-r3}
- .endm
- // Stack layout:
- //
- // (stack parameters)
- // ...
- // ArgumentRegisters::r3
- // ArgumentRegisters::r2
- // ArgumentRegisters::r1
- // ArgumentRegisters::r0
- // CalleeSavedRegisters::lr
- // CalleeSavedRegisters::r11
- // CalleeSavedRegisters::r10
- // CalleeSavedRegisters::r9
- // CalleeSavedRegisters::r8
- // CalleeSavedRegisters::r7 <- r7
- // CalleeSavedRegisters::r6
- // CalleeSavedRegisters::r5
- // CalleeSavedRegisters::r4 <- __PWTB_StackAlloc, __PWTB_TransitionBlock
- // padding to align float save area
- // d7
- // d6
- // d5
- // d4
- // d3
- // d2
- // d1
- // d0 <- __PWTB_FloatArgumentRegisters
- .macro PROLOG_WITH_TRANSITION_BLOCK extraLocals = 0, saveFpArgs = 1, pushArgRegs = 0
- __PWTB_FloatArgumentRegisters = \extraLocals
- __PWTB_SaveFPArgs = \saveFpArgs
- .if (__PWTB_SaveFPArgs == 1)
- .if ((__PWTB_FloatArgumentRegisters % 8) != 0)
- __PWTB_FloatArgumentRegisters = __PWTB_FloatArgumentRegisters + 4
- .endif
- __PWTB_TransitionBlock = __PWTB_FloatArgumentRegisters + 8 * 8 + 4 // 8 floating point registers + padding
- .else
- .if ((__PWTB_FloatArgumentRegisters % 8) == 0)
- __PWTB_FloatArgumentRegisters = __PWTB_FloatArgumentRegisters + 4
- .endif
- __PWTB_TransitionBlock = __PWTB_FloatArgumentRegisters
- .endif
- __PWTB_StackAlloc = __PWTB_TransitionBlock
- .ifnc \pushArgRegs, DoNotPushArgRegs
- PUSH_ARGUMENT_REGISTERS
- .endif
- PUSH_CALLEE_SAVED_REGISTERS
- PROLOG_STACK_SAVE_OFFSET r7, #12
- // let r7 point the saved r7 in the stack (clang FP style)
- alloc_stack __PWTB_StackAlloc
- .if (__PWTB_SaveFPArgs == 1)
- add r6, sp, #(__PWTB_FloatArgumentRegisters)
- vstm r6, {d0-d7}
- .endif
- CHECK_STACK_ALIGNMENT
- END_PROLOGUE
- .endm
- .macro EPILOG_WITH_TRANSITION_BLOCK_RETURN
- free_stack __PWTB_StackAlloc
- POP_CALLEE_SAVED_REGISTERS
- free_stack 16
- bx lr
- .endm
- .macro EPILOG_WITH_TRANSITION_BLOCK_TAILCALL
- .if (__PWTB_SaveFPArgs == 1)
- add r6, sp, #(__PWTB_FloatArgumentRegisters)
- vldm r6, {d0-d7}
- .endif
- free_stack __PWTB_StackAlloc
- POP_CALLEE_SAVED_REGISTERS
- POP_ARGUMENT_REGISTERS
- .endm
- .macro EMIT_BREAKPOINT
- .inst.w 0xde01
- .endm
- .macro PROLOG_PUSH RegList
- push_nonvol_reg "\RegList"
- .endm
- .macro PROLOG_VPUSH RegList
- vpush_nonvol_reg "\RegList"
- .endm
- .macro PROLOG_STACK_SAVE Register
- .setfp \Register, sp
- mov \Register, sp
- .endm
- .macro PROLOG_STACK_SAVE_OFFSET Register, Offset
- .setfp \Register, sp, \Offset
- add \Register, sp, \Offset
- .endm
- .macro EPILOG_STACK_FREE Size
- add sp, sp, \Size
- .endm
- .macro EPILOG_STACK_RESTORE Register
- mov sp, \Register
- .endm
- .macro EPILOG_STACK_RESTORE_OFFSET Register, Offset
- sub sp, \Register, \Offset
- .endm
- .macro EPILOG_BRANCH Target
- b \Target
- .endm
- .macro EPILOG_BRANCH_REG reg
- bx \reg
- .endm
- .macro EPILOG_POP RegList
- pop_nonvol_reg "\RegList"
- .endm
- .macro EPILOG_VPOP RegList
- vpop_nonvol_reg "\RegList"
- .endm
- //-----------------------------------------------------------------------------
- // Macro used to check (in debug builds only) whether the stack is 64-bit aligned (a requirement before calling
- // out into C++/OS code). Invoke this directly after your prolog (if the stack frame size is fixed) or directly
- // before a call (if you have a frame pointer and a dynamic stack). A breakpoint will be invoked if the stack
- // is misaligned.
- //
- .macro CHECK_STACK_ALIGNMENT
- #ifdef _DEBUG
- push {r0}
- add r0, sp, #4
- tst r0, #7
- pop {r0}
- beq 0f
- EMIT_BREAKPOINT
- 0:
- #endif
- .endm
|