diff options
Diffstat (limited to 'src/pal/inc/unixasmmacrosarm.inc')
-rw-r--r-- | src/pal/inc/unixasmmacrosarm.inc | 268 |
1 files changed, 268 insertions, 0 deletions
diff --git a/src/pal/inc/unixasmmacrosarm.inc b/src/pal/inc/unixasmmacrosarm.inc new file mode 100644 index 0000000000..14b0b4160e --- /dev/null +++ b/src/pal/inc/unixasmmacrosarm.inc @@ -0,0 +1,268 @@ +// 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 |