inline
float getR4LittleEndian(const BYTE * ptr)
-{ return *(UNALIGNED float*)ptr; }
+{
+ __int32 val = getI4LittleEndian(ptr);
+ return *(float *)&val;
+}
inline
double getR8LittleEndian(const BYTE * ptr)
-{ return *(UNALIGNED double*)ptr; }
+{
+ __int64 val = getI8LittleEndian(ptr);
+ return *(double *)&val;
+}
/*****************************************************************************
LEAF_END_MARKED \Name, \Section
.endm
-.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 0, C_FUNC(\Handler) // 0 == DW_EH_PE_absptr
-#endif
- .endif
-.endm
-
-.macro NESTED_END Name, Section
- LEAF_END \Name, \Section
-#if defined(__APPLE__)
- .section __LD,__compact_unwind,regular,debug
- .quad C_FUNC(\Name)
- .set C_FUNC(\Name\()_Size), C_FUNC(\Name\()_End) - C_FUNC(\Name)
- .long C_FUNC(\Name\()_Size)
- .long 0x04000000 # DWARF
- .quad 0
- .quad 0
-#endif
-.endm
-
.macro END_PROLOGUE
.endm
// Licensed under the MIT license. See LICENSE 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 0, C_FUNC(\Handler) // 0 == DW_EH_PE_absptr
+#endif
+ .endif
+.endm
+
+.macro NESTED_END Name, Section
+ LEAF_END \Name, \Section
+#if defined(__APPLE__)
+ .section __LD,__compact_unwind,regular,debug
+ .quad C_FUNC(\Name)
+ .set C_FUNC(\Name\()_Size), C_FUNC(\Name\()_End) - C_FUNC(\Name)
+ .long C_FUNC(\Name\()_Size)
+ .long 0x04000000 # DWARF
+ .quad 0
+ .quad 0
+#endif
+.endm
+
.macro PATCH_LABEL Name
.global C_FUNC(\Name)
C_FUNC(\Name):
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
//
+.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 PATCH_LABEL Name
.thumb_func
.global C_FUNC(\Name)
.global C_FUNC(\Name)
.type \Name, %function
C_FUNC(\Name):
- .cfi_startproc
+ .fnstart
.endm
.macro LEAF_END_MARKED Name, Section
.global C_FUNC(\Name\()_End)
C_FUNC(\Name\()_End):
.size \Name, .-\Name
- .cfi_endproc
+ .fnend
.endm
.macro PREPARE_EXTERNAL_VAR Name, HelperReg
.endm
.macro push_nonvol_reg Register
- push {\Register}
- .cfi_adjust_cfa_offset 4
- .cfi_rel_offset \Register, 0
+ push \Register
+ .save \Register
.endm
.macro pop_nonvol_reg Register
- pop {\Register}
- .cfi_adjust_cfa_offset -4
- .cfi_restore \Register
-.endm
-
-.macro alloc_stack Size
- sub sp, sp, \Size
- .cfi_adjust_cfa_offset \Size
+ pop \Register
.endm
-.macro free_stack Size
- add sp, sp, \Size
- .cfi_adjust_cfa_offset -\Size
+.macro vpush_nonvol_reg Register
+ vpush \Register
+ .vsave \Register
.endm
-.macro set_cfa_register Reg, Offset
- .cfi_def_cfa_register \Reg
- .cfi_def_cfa_offset \Offset
+.macro vpop_nonvol_reg Register
+ vpop \Register
.endm
-.macro save_reg_postsp Reg, Offset
- str \Reg, [sp, #\Offset]
- .cfi_rel_offset \Reg, __Offset
+.macro alloc_stack Size
+ sub sp, sp, \Size
+ .pad #\Size
.endm
-.macro restore_reg Reg, Offset
- ldr \Reg, [sp, #\Offset]
- .cfi_restore \Reg
+.macro free_stack Size
+ add sp, sp, \Size
+ .pad #-\Size
.endm
.macro POP_CALLEE_SAVED_REGISTERS
- pop {r4-r11, lr}
- .cfi_adjust_cfa_offset -(4*9)
- .cfi_restore r4
- .cfi_restore r5
- .cfi_restore r6
- .cfi_restore r7
- .cfi_restore r8
- .cfi_restore r9
- .cfi_restore r10
- .cfi_restore r11
- .cfi_restore lr
+ pop_nonvol_reg "{r4-r11, lr}"
.endm
.macro PUSH_CALLEE_SAVED_REGISTERS
- push {r4-r11, lr}
- .cfi_adjust_cfa_offset (4*9)
+ push_nonvol_reg "{r4-r11, lr}"
.endm
.macro push_register Reg
- push {\Reg}
- .cfi_adjust_cfa_offset 4
+ push \Reg
.endm
.macro push_argument_register Reg
.macro PUSH_ARGUMENT_REGISTERS
push {r0-r3}
- .cfi_adjust_cfa_offset (4*4)
.endm
.macro pop_register Reg
- pop {\Reg}
- .cfi_adjust_cfa_offset -4
+ pop \Reg
.endm
.macro pop_argument_register Reg
.macro POP_ARGUMENT_REGISTERS
pop {r0-r3}
- .cfi_adjust_cfa_offset -(4*4)
.endm
// Stack layout:
.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 EPILOG_STACK_RESTORE Register
+ mov sp, \Register
+.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
unw_set_reg(cursor, UNW_X86_64_R14, winContext->R14);
unw_set_reg(cursor, UNW_X86_64_R15, winContext->R15);
#elif defined(_ARM_)
- unw_set_reg(cursor, UNW_REG_IP, winContext->Pc);
- unw_set_reg(cursor, UNW_REG_SP, winContext->Sp);
+ unw_set_reg(cursor, UNW_ARM_R13, winContext->Sp);
unw_set_reg(cursor, UNW_ARM_R14, winContext->Lr);
+ unw_set_reg(cursor, UNW_ARM_R15, winContext->Pc);
unw_set_reg(cursor, UNW_ARM_R4, winContext->R4);
unw_set_reg(cursor, UNW_ARM_R5, winContext->R5);
unw_set_reg(cursor, UNW_ARM_R6, winContext->R6);
unw_get_reg(cursor, UNW_X86_64_R14, (unw_word_t *) &winContext->R14);
unw_get_reg(cursor, UNW_X86_64_R15, (unw_word_t *) &winContext->R15);
#elif defined(_ARM_)
- unw_get_reg(cursor, UNW_REG_IP, (unw_word_t *) &winContext->Pc);
- unw_get_reg(cursor, UNW_REG_SP, (unw_word_t *) &winContext->Sp);
+ unw_get_reg(cursor, UNW_ARM_R13, (unw_word_t *) &winContext->Sp);
unw_get_reg(cursor, UNW_ARM_R14, (unw_word_t *) &winContext->Lr);
+ unw_get_reg(cursor, UNW_ARM_R15, (unw_word_t *) &winContext->Pc);
unw_get_reg(cursor, UNW_ARM_R4, (unw_word_t *) &winContext->R4);
unw_get_reg(cursor, UNW_ARM_R5, (unw_word_t *) &winContext->R5);
unw_get_reg(cursor, UNW_ARM_R6, (unw_word_t *) &winContext->R6);
#define STATUS_UNWIND_UNSUPPORTED_VERSION STATUS_UNSUCCESSFUL
-#define UPDATE_CONTEXT_POINTERS(Params, RegisterNumber, Address)
-#define UPDATE_FP_CONTEXT_POINTERS(Params, RegisterNumber, Address)
+#define UPDATE_CONTEXT_POINTERS(Params, RegisterNumber, Address) \
+do { \
+ PKNONVOLATILE_CONTEXT_POINTERS ContextPointers = (Params)->ContextPointers; \
+ if (ARGUMENT_PRESENT(ContextPointers)) { \
+ if (RegisterNumber >= 4 && RegisterNumber <= 11) { \
+ (&ContextPointers->R4)[RegisterNumber - 4] = (PULONG)Address; \
+ } else if (RegisterNumber == 14) { \
+ ContextPointers->Lr = (PULONG)Address; \
+ } \
+ } \
+} while (0)
+
+#define UPDATE_FP_CONTEXT_POINTERS(Params, RegisterNumber, Address) \
+do { \
+ PKNONVOLATILE_CONTEXT_POINTERS ContextPointers = (Params)->ContextPointers; \
+ if (ARGUMENT_PRESENT(ContextPointers) && \
+ (RegisterNumber >= 8) && \
+ (RegisterNumber <= 15)) { \
+ \
+ (&ContextPointers->D8)[RegisterNumber - 8] = (PULONGLONG)Address; \
+ } \
+} while (0)
+
#define VALIDATE_STACK_ADDRESS(Params, Context, DataSize, Alignment, OutStatus)
#define UNWIND_PARAMS_SET_TRAP_FRAME(Params, Address)
#define CONTEXT_REGISTER(ctx, idx) ((&(ctx)->R0)[idx])
+typedef struct _ARM_UNWIND_PARAMS
+{
+ PKNONVOLATILE_CONTEXT_POINTERS ContextPointers;
+} ARM_UNWIND_PARAMS, *PARM_UNWIND_PARAMS;
//
// The ConditionTable is used to look up the state of a condition
RtlpUnwindCustom(
__inout PT_CONTEXT ContextRecord,
__in BYTE Opcode,
- __in PVOID UnwindParams
+ __in PARM_UNWIND_PARAMS UnwindParams
)
/*++
__inout PT_CONTEXT ContextRecord,
__in ULONG RegStart,
__in ULONG RegStop,
- __in PVOID UnwindParams
+ __in PARM_UNWIND_PARAMS UnwindParams
)
/*++
RtlpPopRegisterMask(
__inout PT_CONTEXT ContextRecord,
__in WORD RegMask,
- __in PVOID UnwindParams
+ __in PARM_UNWIND_PARAMS UnwindParams
)
/*++
__out PULONG EstablisherFrame,
__deref_opt_out_opt PEXCEPTION_ROUTINE *HandlerRoutine,
__out PVOID *HandlerData,
- __in PVOID UnwindParams
+ __in PARM_UNWIND_PARAMS UnwindParams
)
{
ULONG CBit;
__out PULONG EstablisherFrame,
__deref_opt_out_opt PEXCEPTION_ROUTINE *HandlerRoutine,
__out PVOID *HandlerData,
- __in PVOID UnwindParams
+ __in PARM_UNWIND_PARAMS UnwindParams
)
/*++
__inout_opt PKNONVOLATILE_CONTEXT_POINTERS ContextPointers
)
{
- PORTABILITY_ASSERT("Implement for PAL");
+ PEXCEPTION_ROUTINE handlerRoutine;
+ HRESULT res;
+
+ IMAGE_ARM_RUNTIME_FUNCTION_ENTRY rfe;
+ rfe.BeginAddress = FunctionEntry->BeginAddress;
+ rfe.UnwindData = FunctionEntry->UnwindData;
+
+ ARM_UNWIND_PARAMS unwindParams;
+ unwindParams.ContextPointers = ContextPointers;
+
+ if ((FunctionEntry->UnwindData & 3) != 0)
+ {
+ res = RtlpUnwindFunctionCompact(ControlPc - ImageBase,
+ &rfe,
+ ContextRecord,
+ EstablisherFrame,
+ &handlerRoutine,
+ HandlerData,
+ &unwindParams);
+
+ }
+ else
+ {
+ res = RtlpUnwindFunctionFull(ControlPc - ImageBase,
+ ImageBase,
+ &rfe,
+ ContextRecord,
+ EstablisherFrame,
+ &handlerRoutine,
+ HandlerData,
+ &unwindParams);
+ }
+
+ _ASSERTE(SUCCEEDED(res));
- return NULL;
+ return handlerRoutine;
}
#endif
//-----------------------------------------------------------------------------
//void CallDescrWorkerInternal(CallDescrData * pCallDescrData)//
NESTED_ENTRY CallDescrWorkerInternal,_TEXT,NoHandler
- push {r4,r5,r7,lr}
- mov r7, sp
+ PROLOG_PUSH "{r4,r5,r7,lr}"
+ PROLOG_STACK_SAVE r7
mov r5,r0 // save pCallDescrData in r5
vldm sp, {d0-d3}
#endif
- mov sp, r7
- pop {r4,r5,r7,pc}
+ EPILOG_STACK_RESTORE r7
+ EPILOG_POP "{r4,r5,r7,pc}"
NESTED_END CallDescrWorkerInternal,_TEXT
//
// Spill callee saved registers and return address.
- push {r4-r11,lr}
+ PROLOG_PUSH "{r4-r11,lr}"
- mov r7, sp
+ PROLOG_STACK_SAVE r7
//
// This is the code that would have to run to setup this frame
//
// epilog
//
- mov sp, r7
- pop {r4-r11,lr}
+ EPILOG_STACK_RESTORE r7
+ EPILOG_POP "{r4-r11,lr}"
bx lr
NESTED_END TailCallHelperStub, _TEXT
// r12 = UMEntryThunk*
//
NESTED_ENTRY UMThunkStub,_TEXT,NoHandler
- push {r4,r5,r7,r11,lr}
- push {r0-r3,r12}
- mov r7, sp
+ PROLOG_PUSH "{r4,r5,r7,r11,lr}"
+ push {r0-r3,r12}
+ PROLOG_STACK_SAVE r7
//GBLA UMThunkStub_HiddenArg // offset of saved UMEntryThunk *
//GBLA UMThunkStub_StackArgs // offset of original stack args (total size of UMThunkStub frame)
mov r4, 0
str r4, [r5, #Thread__m_fPreemptiveGCDisabled]
- mov sp, r7
- add sp, sp, #(4 * 5)
- pop {r4,r5,r7,r11,pc}
+ EPILOG_STACK_RESTORE r7
+ free_stack 4 * 5
+ EPILOG_POP "{r4,r5,r7,r11,pc}"
LOCAL_LABEL(UMThunkStub_DoThreadSetup):
sub sp, #SIZEOF__FloatArgumentRegisters
NESTED_ENTRY UM2MThunk_WrapperHelper, _TEXT, NoHandler
- push {r4-r7,r11,lr}
- mov r7, sp
+ PROLOG_PUSH "{r4-r7,r11,lr}"
+ PROLOG_STACK_SAVE r7
CHECK_STACK_ALIGNMENT
vldm sp, {d0-d3}
#endif
- mov sp, r7
- pop {r4-r7,r11,pc}
+ EPILOG_STACK_RESTORE r7
+ EPILOG_POP "{r4-r7,r11,pc}"
NESTED_END UM2MThunk_WrapperHelper, _TEXT
// r12 = FixupPrecode *
- push {r0-r1}
+ PROLOG_PUSH "{r0-r1}"
// Inline computation done by FixupPrecode::GetMethodDesc()
ldrb r0, [r12, #3] // m_PrecodeChunkIndex
ldr r0, [r0,#8]
add r12,r0,r1,lsl #2
- pop {r0-r1}
+ EPILOG_POP "{r0-r1}"
b C_FUNC(ThePreStub)
NESTED_END PrecodeFixupThunk, _TEXT
NESTED_ENTRY RedirectedHandledJITCaseFor\reason\()_Stub, _TEXT, NoHandler
- push {r7,lr} // return address
- alloc_stack 4 // stack slot to save the CONTEXT *
- mov r7, sp
+ PROLOG_PUSH "{r7,lr}" // return address
+ alloc_stack 4 // stack slot to save the CONTEXT *
+ PROLOG_STACK_SAVE r7
//REDIRECTSTUB_SP_OFFSET_CONTEXT is defined in asmconstants.h
//If CONTEXT is not saved at 0 offset from SP it must be changed as well.
NESTED_END checkStack, _TEXT
NESTED_ENTRY stackProbe, _TEXT, NoHandler
- push {r5,r6}
+ PROLOG_PUSH "{r5,r6}"
mov r6, r12
bfc r6, #0, #0xc // align down (4K)
LOCAL_LABEL(stackProbe_loop):
ldr r5,[r4] // try to read ... this should move the guard page
cmp r4,r6
bne LOCAL_LABEL(stackProbe_loop)
- pop {r5,r6}
+ EPILOG_POP "{r5,r6}"
sub r4,sp,r12
bx lr
NESTED_END stackProbe, _TEXT
//
NESTED_ENTRY JIT_RareDisableHelper, _TEXT, NoHandler
- push {r0-r1, r11, lr} // save integer return value
- vpush {d0-d3} // floating point return value
+ PROLOG_PUSH "{r0-r1, r11, lr}" // save integer return value
+ vpush {d0-d3} // floating point return value
CHECK_STACK_ALIGNMENT
bl C_FUNC(JIT_RareDisableHelperWorker)
vpop {d0-d3}
- pop {r0-r1, r11, pc}
+ EPILOG_POP "{r0-r1, r11, pc}"
NESTED_END JIT_RareDisableHelper, _TEXT
// IN: lr: original IP before redirect
//
- push {r4,r7,lr}
+ PROLOG_PUSH "{r4,r7,lr}"
alloc_stack OFFSET_OF_FRAME + SIZEOF__FaultingExceptionFrame
// At this point, the stack maybe misaligned if the thread abort was asynchronously
// align the stack before calling into the VM.
//
// Runtime check for 8-byte alignment.
- mov r7, sp
+ PROLOG_STACK_SAVE r7
and r0, r7, #4
sub sp, sp, r0
// This helper enables us to call into a funclet after applying the non-volatiles
NESTED_ENTRY CallEHFunclet, _TEXT, NoHandler
- push {r4-r11, lr}
+ PROLOG_PUSH "{r4-r11, lr}"
alloc_stack 4
// On entry:
blx r1
free_stack 4
- pop {r4-r11, pc}
+ EPILOG_POP "{r4-r11, pc}"
NESTED_END CallEHFunclet, _TEXT
// frame pointer for accessing the locals in the parent method.
NESTED_ENTRY CallEHFilterFunclet, _TEXT, NoHandler
- push {lr}
+ PROLOG_PUSH "{lr}"
alloc_stack 4
// On entry:
blx r2
free_stack 4
- pop {pc}
+ EPILOG_POP "{pc}"
NESTED_END CallEHFilterFunclet, _TEXT
do
{
+#ifndef FEATURE_PAL
pvControlPc = Thread::VirtualUnwindCallFrame(&ctx, &nonVolRegPtrs);
+#else // !FEATURE_PAL
+ PAL_VirtualUnwind(&ctx, &nonVolRegPtrs);
+ pvControlPc = GetIP(&ctx);
+#endif // !FEATURE_PAL
if (funCallDepth > 0)
{