Alien-LibJIT
view release on metacpan or search on metacpan
libjit/jit/jit-gen-arm.h view on Meta::CPAN
/*
* Call a subroutine immediate by a byte offset.
*/
#define arm_call_imm(inst,imm) \
do { \
arm_inst_add((inst), arm_prefix(0x0B000000) | \
(((unsigned int)(((int)(imm)) >> 2)) & \
0x00FFFFFF)); \
} while (0)
/*
* Call a subroutine at a specific target location.
* (Equivalent to x86_call_code)
*/
#define arm_call(inst,target) \
do { \
int __call_offset = (int)(((unsigned char *)(target)) - \
(((unsigned char *)((inst).current)) + 8)); \
if(__call_offset >= -0x04000000 && __call_offset < 0x04000000) \
{ \
arm_call_imm((inst), __call_offset); \
} \
else \
{ \
arm_load_membase((inst), ARM_WORK, ARM_PC, 4); \
arm_alu_reg_imm8((inst), ARM_ADD, ARM_LINK, ARM_PC, 4); \
arm_mov_reg_reg((inst), ARM_PC, ARM_WORK); \
arm_inst_add((inst), (int)(target)); \
} \
} while (0)
/*
* Return from a subroutine, where the return address is in the link register.
*/
#define arm_return(inst) \
do { \
arm_mov_reg_reg((inst), ARM_PC, ARM_LINK); \
} while (0)
/*
* Push a register onto the system stack.
*/
#define arm_push_reg(inst,reg) \
do { \
arm_inst_add((inst), arm_prefix(0x05200004) | \
(((unsigned int)ARM_SP) << 16) | \
(((unsigned int)(reg)) << 12)); \
} while (0)
/*
* Pop a register from the system stack.
*/
#define arm_pop_reg(inst,reg) \
do { \
arm_inst_add((inst), arm_prefix(0x04900004) | \
(((unsigned int)ARM_SP) << 16) | \
(((unsigned int)(reg)) << 12)); \
} while (0)
/*
* Pop the top of the system stack and put it at a given offset from the position specified by basereg (that is, usually, the frame pointer). NB: This macro thrashes the content of ARM_WORK
*/
#define arm_pop_membase(inst,basereg,offset) \
do { \
arm_pop_reg((inst), ARM_WORK); \
arm_store_membase((inst),ARM_WORK,basereg,offset); \
} while (0)
/*
* Set up a local variable frame, and save the registers in "regset".
*/
#define arm_setup_frame(inst,regset) \
do { \
arm_mov_reg_reg((inst), ARM_WORK, ARM_SP); \
arm_inst_add((inst), arm_prefix(0x0920D800) | \
(((unsigned int)ARM_SP) << 16) | \
(((unsigned int)(regset)))); \
arm_alu_reg_imm8((inst), ARM_SUB, ARM_FP, ARM_WORK, 4); \
} while (0)
/*
* Pop a local variable frame, restore the registers in "regset",
* and return to the caller.
*/
#define arm_pop_frame(inst,regset) \
do { \
arm_inst_add((inst), arm_prefix(0x0910A800) | \
(((unsigned int)ARM_FP) << 16) | \
(((unsigned int)(regset)))); \
} while (0)
/*
* Pop a local variable frame, in preparation for a tail call.
* This restores "lr" to its original value, but does not set "pc".
*/
#define arm_pop_frame_tail(inst,regset) \
do { \
arm_inst_add((inst), arm_prefix(0x09106800) | \
(((unsigned int)ARM_FP) << 16) | \
(((unsigned int)(regset)))); \
} while (0)
/*
* Load a word value from a pointer and then advance the pointer.
*/
#define arm_load_advance(inst,dreg,sreg) \
do { \
arm_inst_add((inst), arm_prefix(0x04900004) | \
(((unsigned int)(sreg)) << 16) | \
(((unsigned int)(dreg)) << 12)); \
} while (0)
/*
* Load a value from an address into a register.
*/
#define arm_load_membase_either(inst,reg,basereg,imm,mask) \
do { \
int __mb_offset = (int)(imm); \
if(__mb_offset >= 0 && __mb_offset < (1 << 12)) \
{ \
arm_inst_add((inst), arm_prefix(0x05900000 | (mask)) | \
(((unsigned int)(basereg)) << 16) | \
(((unsigned int)(reg)) << 12) | \
((unsigned int)__mb_offset)); \
} \
else if(__mb_offset > -(1 << 12) && __mb_offset < 0) \
{ \
arm_inst_add((inst), arm_prefix(0x05100000 | (mask)) | \
(((unsigned int)(basereg)) << 16) | \
(((unsigned int)(reg)) << 12) | \
((unsigned int)(-__mb_offset))); \
} \
else \
{ \
assert(basereg!=ARM_WORK); \
arm_mov_reg_imm((inst), ARM_WORK, __mb_offset); \
arm_inst_add((inst), arm_prefix(0x07900000 | (mask)) | \
(((unsigned int)(basereg)) << 16) | \
(((unsigned int)(reg)) << 12) | \
((unsigned int)ARM_WORK)); \
} \
} while (0)
#define arm_load_membase(inst,reg,basereg,imm) \
do { \
arm_load_membase_either((inst), (reg), (basereg), (imm), 0); \
} while (0)
/**
* Moves the content of 1 byte (is_half==0) or 2 bytes (is_half==1) from memory address basereg+disp+(indexreg<<shift) into dreg, with sign extension (is_signed==1) or zero extension (is_signed==0)
*/
#define arm_widen_memindex(inst,dreg,basereg,disp,indexreg,shift,is_signed,is_half) \
do { \
int scratchreg=ARM_WORK; \
if(is_half) \
{ \
arm_mov_reg_memindex((inst),(dreg),(basereg),(disp),(indexreg),(shift),2, scratchreg); \
( run in 0.668 second using v1.01-cache-2.11-cpan-df04353d9ac )