Alien-LibJIT

 view release on metacpan or  search on metacpan

libjit/jit/jit-rules-arm.ins  view on Meta::CPAN

	}

JIT_OP_IMPORT:
	[] -> {
		/* TODO */
		TODO();
	}

/*
 * Exception handling
 */
JIT_OP_THROW: branch
	[reg] -> {

		arm_push_reg(inst, $1);
		if(func->builder->setjmp_value != 0)
		{
			/* We have a "setjmp" block in the current function,
			   so we must record the location of the throw first */
			jit_nint pc_offset;
		
			_jit_gen_fix_value(func->builder->setjmp_value);
			
			pc_offset = func->builder->setjmp_value->frame_offset +
							jit_jmp_catch_pc_offset;
							
			if(func->builder->position_independent)
			{
				arm_call_imm(inst, 0);
				arm_pop_membase(inst, ARM_FP, pc_offset);
			}
			else
			{
				int pc = (int) (unsigned char *) arm_inst_get_posn(inst);
				arm_mov_membase_imm(inst, ARM_FP, pc_offset, pc, 4, ARM_WORK);
			}
		}
		arm_call(inst, (void *)jit_exception_throw);
	}

JIT_OP_LOAD_PC:
[=reg] -> {
	if(func->builder->position_independent)
	{
		arm_call_imm(inst, 0);
		arm_pop_reg(inst, $1);
	}
	else
	{
		int pc = inst.current;
		mov_reg_imm(gen, &inst, $1, pc);
	}
}

JIT_OP_ENTER_FINALLY:
[] -> { /* 
	 * The return address is in the link register
	 * We must save it on the stack in case it will be overwritten by the content
	 * of the "finally" block.
	 * In order to respect the ABI of the ARM architecture, that prescribes an 8-byte
	 * alignment for the stack at a public interface, we save the value twice, 
	 * in order to move the current SP by 8 bytes 
	 * (we could have just saved the value once and then moved the SP by 4 bytes)
	 */
	arm_push_reg(inst, ARM_LINK);
	arm_push_reg(inst, ARM_LINK);
}

JIT_OP_LEAVE_FINALLY: branch
[] -> {
	/* The "finally" return address is on the stack (twice, just for padding)*/
		arm_pop_reg(inst, ARM_LINK);
		arm_pop_reg(inst, ARM_LINK);
		arm_return(inst);
}

JIT_OP_CALL_FINALLY: branch
[] -> {
	jit_block_t block;
	int offset;
	block = jit_block_from_label(func, (jit_label_t)(insn->dest));
	if(!block)
	{
		return;
	}
	if(arm_inst_get_posn(inst) >= arm_inst_get_limit(inst))
	{
		/* The buffer has overflowed, so don't worry about fixups */
		return;
	}
	if(block->address)
	{
		/* We already know the address of the block */
		arm_call(inst, block->address);
	}
	else
	{
		/* Output a placeholder and record on the block's fixup list */
		if(block->fixup_list)
		{
			offset = (int)(((unsigned char *)arm_inst_get_posn(inst)) -
			((unsigned char *)(block->fixup_list)));
		}
		else
		{
			offset = 0;
		}
		arm_call_imm(inst, offset);
		block->fixup_list = (void *)(arm_inst_get_posn(inst) - 1);
	}
}

JIT_OP_ADDRESS_OF_LABEL:
[=reg] -> {
	block = jit_block_from_label(func, (jit_label_t)(insn->value1));
	if(func->builder->position_independent)
	{
		/* TODO */
			TODO();
	}
	else

libjit/jit/jit-rules-arm.ins  view on Meta::CPAN

	else if ($1 == indexreg)
	{	
		//Prevent index reg from being overwritten
		arm_mov_reg_reg(inst, $5, indexreg);
		indexreg=$5;
	}
	arm_mov_reg_memindex(inst, $1, basereg, 0, indexreg, 3, 4, $4);
	
	//Write the 2-nd word
	arm_mov_reg_memindex(inst, %1, basereg, 4, indexreg, 3, 4, $4);
}

JIT_OP_LOAD_ELEMENT_FLOAT64:
[=freg64, reg, reg, scratch reg] -> {
	arm_fld_memindex(inst, $1, $2, 0, $3, 3, 1, $4);
}

JIT_OP_STORE_ELEMENT_BYTE: ternary
[reg, reg, reg, scratch reg] -> {
	arm_mov_memindex_reg(inst, $1, 0, $2, 0, $3, 1, $4);
}

JIT_OP_STORE_ELEMENT_SHORT: ternary
[reg, reg, reg, scratch reg] -> {
	arm_mov_memindex_reg(inst, $1, 0, $2, 1, $3, 2, $4);
}

JIT_OP_STORE_ELEMENT_INT: ternary
[reg, reg, reg, scratch reg] -> {
	arm_mov_memindex_reg(inst, $1, 0, $2, 2, $3, 4, $4);
}

JIT_OP_STORE_ELEMENT_LONG: ternary
	[reg, reg, imm] -> {
		TODO();
		abort();
		//x86_mov_memindex_imm(inst, $1, 0, $2, 3, *(int *)($3), 4);
		//x86_mov_memindex_imm(inst, $1, 4, $2, 3, *(int *)($3 + 4), 4);
	}
	[reg, reg, local, scratch reg, scratch reg] -> {
		arm_mov_reg_membase(inst, $4, ARM_FP, $3, 4);
		arm_mov_memindex_reg(inst, $1, 0, $2, 3, $4, 4, $5);
		arm_mov_reg_membase(inst, $4, ARM_FP, $3 + 4, 4);
		arm_mov_memindex_reg(inst, $1, 4, $2, 3, $4, 4, $5);
	}
	[reg, reg, lreg, scratch reg] -> {
		arm_mov_memindex_reg(inst, $1, 0, $2, 3, $3, 4, $4);
		arm_mov_memindex_reg(inst, $1, 4, $2, 3, %3, 4, $4);
	}

JIT_OP_STORE_ELEMENT_FLOAT64: ternary
[reg, reg, freg64, scratch reg] -> {
	arm_fst_memindex(inst, $3, $1, 0, $2, 3, 1, $4);
}

/*
* Allocate memory from the stack.
*/
JIT_OP_ALLOCA:
[reg] -> {
	//The ARM stack must always be 4-byte aligned and must be 8-byte aligned at a public interface.
	//Since we don't know when this function will be called, let's align to 8 bytes.
	arm_alu_reg_imm(inst, ARM_ADD, $1, $1, 7);
	arm_alu_reg_imm(inst, ARM_AND, $1, $1, ~7);
	arm_alu_reg_reg(inst, ARM_SUB, ARM_SP, ARM_SP, $1);
	arm_mov_reg_reg(inst, $1, ARM_SP);
	gen->stack_changed = 1;
}

/*
 * Block operations
 */
JIT_OP_MEMCPY: ternary
	[any, any, imm, if("$3 <= 0")] -> { }
	[reg, reg, imm, scratch reg, clobber("r0", "r1", "r2")] ->
	{
		/* 
		 * Call jit_memcpy(dest,src,size).
		 * $1=dest, $2=src, $3=size
		 */
		int dest=$1;
		int src=$2;
		
		if (dest != ARM_R0) {
			if(src==ARM_R0)
			{
				//Prevent overwriting useful data
				arm_mov_reg_reg(inst, $4, src);
				src=$4;
			}
			arm_mov_reg_reg((inst), ARM_R0, dest);
		}
		if (src != ARM_R1) {
			//Move the "src" from wherever it is to where it should be
			arm_mov_reg_reg(inst, ARM_R1, src);
		}
		mov_reg_imm(gen, &(inst), ARM_R2, $3);
	    
		//Call the function
		arm_call(inst, jit_memcpy);
	}
	[reg, reg, reg, scratch reg, clobber("r0", "r1", "r2")] -> {
		/* 
		* Call jit_memcpy(dest,src,size).
		* $1=dest, $2=src, $3=size
		*/
		if ($1 != ARM_R0) {
			if($2==ARM_R0)
			{
				//Prevent overwriting useful data
				arm_mov_reg_reg(inst, $4, $2);
			}
			arm_mov_reg_reg((inst), ARM_R0, $1);
		}
		if ($2 != ARM_R1) {
			if ($2==ARM_R0)
			{
				//Recover previously saved data
				arm_mov_reg_reg(inst, ARM_R1, $4);
			}
			else



( run in 0.458 second using v1.01-cache-2.11-cpan-5623c5533a1 )