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
void _jit_pad_buffer(unsigned char *buf, int len)
{
	arm_inst_buf inst;
	
	/* Initialize the instruction buffer */
	arm_inst_buf_init(inst, buf, buf + len*4);
	while(len > 0)
	{
		/* Traditional arm NOP */
		arm_nop(inst);
		--len;
	}
	
	/* Flush the cache lines that we just wrote */
	_jit_flush_exec(buf, ((unsigned char *)(inst.current)) - buf);
}
Example #3
0
void *_jit_gen_prolog(jit_gencode_t gen, jit_function_t func, void *buf)
{
	unsigned int prolog[JIT_PROLOG_SIZE / sizeof(int)];
	arm_inst_buf inst;
	int reg, regset;
	unsigned int saved;
	unsigned int frame_size;

	/* Initialize the instruction buffer */
	arm_inst_buf_init(inst, prolog, prolog + JIT_PROLOG_SIZE / sizeof(int));

	/* Determine which registers need to be preserved */
	regset = 0;
	saved = 0;
	for(reg = 0; reg <= 15; ++reg)
	{
		if(jit_reg_is_used(gen->touched, reg) &&
		   (_jit_reg_info[reg].flags & JIT_REG_CALL_USED) == 0)
		{
			regset |= (1 << reg);
			saved += sizeof(void *);
		}
	}

	/* Setup the frame, pushing all the callee-save registers */
	arm_setup_frame(inst, regset);

	/* Allocate space for the local variable frame.  Subtract off
	   the space for the registers that we just saved.  The pc, lr,
	   and fp registers are always saved, so account for them too */
	frame_size = func->builder->frame_size - (saved + 3 * sizeof(void *));
	frame_size += (unsigned int)(func->builder->param_area_size);
	if(frame_size > 0)
	{
		arm_alu_reg_imm(inst, ARM_SUB, ARM_SP, ARM_SP, frame_size);
	}

	/* Copy the prolog into place and return the adjusted entry position */
	reg = (int)((arm_inst_get_posn(inst) - prolog) * sizeof(unsigned int));
	jit_memcpy(((unsigned char *)buf) + JIT_PROLOG_SIZE - reg, prolog, reg);
	return (void *)(((unsigned char *)buf) + JIT_PROLOG_SIZE - reg);
}
Example #4
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 #5
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;
}