Example #1
0
void _jit_create_closure(unsigned char *buf, void *func,
                         void *closure, void *_type)
{
	arm_inst_buf inst;

	/* Initialize the instruction buffer */
	arm_inst_buf_init(inst, buf, buf + jit_closure_size);

	/* Set up the local stack frame */
	arm_setup_frame(inst, 0);
	arm_alu_reg_imm8(inst, ARM_SUB, ARM_SP, ARM_SP, 24);

	/* Create the apply argument block on the stack */
	arm_store_membase(inst, ARM_R0, ARM_FP, -28);
	arm_store_membase(inst, ARM_R1, ARM_FP, -24);
	arm_store_membase(inst, ARM_R2, ARM_FP, -20);
	arm_store_membase(inst, ARM_R3, ARM_FP, -16);
	arm_alu_reg_imm(inst, ARM_ADD, ARM_R3, ARM_FP, 4);
	arm_store_membase(inst, ARM_R3, ARM_FP, -36);
	arm_store_membase(inst, ARM_R0, ARM_FP, -32);

	/* Set up the arguments for calling "func" */
	arm_mov_reg_imm(inst, ARM_R0, (int)(jit_nint)closure);
	arm_mov_reg_reg(inst, ARM_R1, ARM_SP);

	/* Call the closure handling function */
	arm_call(inst, func);

	/* Pop the current stack frame and return */
	arm_pop_frame(inst, 0);
}
Example #2
0
/**
 * Creates the indirector, that is the trampoline that permits the Just In Time 
 * compilation of a method the first time that it is executed and its direct execution
 * the following times
 */
void *_jit_create_indirector(unsigned char *buf, void **entry)
{
	arm_inst_buf inst;
	void *start = (void *)buf;

	/* Initialize the instruction buffer */
	arm_inst_buf_init(inst, buf, buf + jit_indirector_size);

	//Load the content of memory at address "entry", that is, the entry point of the function
	arm_mov_reg_imm(inst,ARM_WORK,entry);
	arm_mov_reg_membase(inst,ARM_WORK,ARM_WORK,0,4);
	
	/* Jump to the entry point. */
	arm_mov_reg_reg(inst, ARM_PC, ARM_WORK);

	/* Flush the cache lines that we just wrote */
	_jit_flush_exec(buf, ((unsigned char *)(inst.current)) - buf);
	
	return start;
}
Example #3
0
/*
 * Load an immediate value into a word register.  If the value is
 * complicated, then add an entry to the constant pool.
 */
static void mov_reg_imm
	(jit_gencode_t gen, arm_inst_buf *inst, int reg, int value)
{
	arm_inst_word *fixup;

	/* Bail out if the value is not complex enough to need a pool entry */
	if(!arm_is_complex_imm(value))
	{
		arm_mov_reg_imm(*inst, reg, value);
		return;
	}

	/* Output a placeholder to load the value later */
	fixup = arm_inst_get_posn(*inst);
	arm_load_membase(*inst, reg, ARM_PC, 0);

	/* Add the constant to the pool, which may cause a flush */
	jit_gen_save_inst_ptr(gen, *inst);
	add_constant(gen, value, fixup);
	jit_gen_load_inst_ptr(gen, *inst);
}
Example #4
0
void *_jit_create_redirector(unsigned char *buf, void *func,
							 void *user_data, int abi)
{
	arm_inst_buf inst;

	/* Align "buf" on an appropriate boundary */
	if((((jit_nint)buf) % jit_closure_align) != 0)
	{
		buf += jit_closure_align - (((jit_nint)buf) % jit_closure_align);
	}

	/* Initialize the instruction buffer */
	arm_inst_buf_init(inst, buf, buf + jit_redirector_size);

	/* Set up the local stack frame, and save R0-R3 */
	arm_setup_frame(inst, 0x000F);

	/* Set up the arguments for calling "func" */
	arm_mov_reg_imm(inst, ARM_R0, (int)(jit_nint)user_data);

	/* Call the redirector handling function */
	arm_call(inst, func);

	/* Shift the result into R12, because we are about to restore R0 */
	arm_mov_reg_reg(inst, ARM_R12, ARM_R0);

	/* Pop the current stack frame, but don't change PC yet */
	arm_pop_frame_tail(inst, 0x000F);

	/* Jump to the function that the redirector indicated */
	arm_mov_reg_reg(inst, ARM_PC, ARM_R12);

	/* Flush the cache lines that we just wrote */
	_jit_flush_exec(buf, ((unsigned char *)(inst.current)) - buf);

	/* Return the aligned start of the buffer as the entry point */
	return (void *)buf;
}