diff options
Diffstat (limited to 'src/vm/arm/cgencpu.h')
-rw-r--r-- | src/vm/arm/cgencpu.h | 55 |
1 files changed, 54 insertions, 1 deletions
diff --git a/src/vm/arm/cgencpu.h b/src/vm/arm/cgencpu.h index 34af8187b2..181d5f10eb 100644 --- a/src/vm/arm/cgencpu.h +++ b/src/vm/arm/cgencpu.h @@ -57,7 +57,7 @@ EXTERN_C void checkStack(void); #define JUMP_ALLOCATE_SIZE 8 // # bytes to allocate for a jump instruction #define BACK_TO_BACK_JUMP_ALLOCATE_SIZE 8 // # bytes to allocate for a back to back jump instruction -//#define HAS_COMPACT_ENTRYPOINTS 1 +#define HAS_COMPACT_ENTRYPOINTS 1 #define HAS_NDIRECT_IMPORT_PRECODE 1 @@ -90,6 +90,12 @@ EXTERN_C void setFPReturn(int fpSize, INT64 retVal); // this is the offset by which it should be decremented to arrive at the callsite. #define STACKWALK_CONTROLPC_ADJUST_OFFSET 2 +// Max offset for unconditional thumb branch +#define MAX_OFFSET_UNCONDITIONAL_BRANCH_THUMB 2048 + +// Offset of pc register +#define PC_REG_RELATIVE_OFFSET 4 + //======================================================================= // IMPORTANT: This value is used to figure out how much to allocate // for a fixed array of FieldMarshaler's. That means it must be at least @@ -236,6 +242,53 @@ void emitCOMStubCall (ComCallMethodDesc *pCOMMethod, PCODE target); #endif // FEATURE_COMINTEROP //------------------------------------------------------------------------ +inline void emitUnconditionalBranchThumb(LPBYTE pBuffer, int16_t offset) +{ + LIMITED_METHOD_CONTRACT; + + uint16_t *pInstr = (uint16_t *) pBuffer; + + // offset from -2KB to +2KB + _ASSERTE (offset >= - MAX_OFFSET_UNCONDITIONAL_BRANCH_THUMB && offset < MAX_OFFSET_UNCONDITIONAL_BRANCH_THUMB); + + if (offset >= 0) + { + offset = offset >> 1; + } + else + { + offset = ((MAX_OFFSET_UNCONDITIONAL_BRANCH_THUMB + offset) >> 1) | 0x400; + } + + *pInstr = 0xE000 | offset; +} + +//------------------------------------------------------------------------ +inline int16_t decodeUnconditionalBranchThumb(LPBYTE pBuffer) +{ + LIMITED_METHOD_CONTRACT; + + uint16_t *pInstr = (uint16_t *) pBuffer; + + int16_t offset = (~0xE000) & (*pInstr); + + if ((offset & 0x400) == 0) + { + offset = offset << 1; + } + else + { + offset = (~0x400) & offset; + offset = (offset << 1) - MAX_OFFSET_UNCONDITIONAL_BRANCH_THUMB; + } + + // offset from -2KB to +2KB + _ASSERTE (offset >= - MAX_OFFSET_UNCONDITIONAL_BRANCH_THUMB && offset < MAX_OFFSET_UNCONDITIONAL_BRANCH_THUMB); + + return offset; +} + +//------------------------------------------------------------------------ inline void emitJump(LPBYTE pBuffer, LPVOID target) { LIMITED_METHOD_CONTRACT; |