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 )