Alien-LibJIT

 view release on metacpan or  search on metacpan

libjit/attic/jit-rules-alpha.c  view on Meta::CPAN

	 * (__implver == 1)	ev5 class processors
	 * (__implver == 2)	ev6 class processors
	 */
        __asm__ ("implver %0" : "=r"(__implver));
	return (__implver >= 2);
}

/*
 * Round a size up to a multiple of the stack word size.
 */
#define ROUND_STACK(size)       \
	(((size) + (sizeof(alpha_inst) - 1)) & ~(sizeof(alpha_inst) - 1))


/*
 * Setup or teardown the alpha code output process.
 */
#define jit_cache_setup_output(needed)			\
	alpha_inst inst = (alpha_inst) gen->ptr;	\
	_jit_gen_check_space(gen, (needed))

#define jit_cache_end_output()  \
	gen->ptr = (unsigned char*) inst

/*
 * Load the instruction pointer from the generation context.
 */
#define jit_gen_load_inst_ptr(gen,inst) \
	inst = (alpha_inst) (gen)->ptr;

/*
 * Save the instruction pointer back to the generation context.
 */
#define jit_gen_save_inst_ptr(gen,inst) \
	(gen)->ptr = (unsigned char *) inst;

static _jit_regclass_t *alpha_reg;
static _jit_regclass_t *alpha_freg;

/*
 * Initialize the backend. This is normally used to configure registers 
 * that may not appear on all CPU's in a given family. For example, only 
 * some ARM cores have floating-point registers.
 */
void _jit_init_backend(void) {
	alpha_reg = _jit_regclass_create("reg", JIT_REG_WORD | JIT_REG_LONG, 18,
		ALPHA_T0, ALPHA_T1, ALPHA_T2, ALPHA_T3,  ALPHA_T4,  ALPHA_T5,
		ALPHA_T6, ALPHA_T7, ALPHA_T8, ALPHA_T9, ALPHA_T10, ALPHA_T11,
		ALPHA_S0, ALPHA_S1, ALPHA_S2, ALPHA_S3,  ALPHA_S4,  ALPHA_S5
	);

	alpha_freg = _jit_regclass_create("freg", JIT_REG_FLOAT32 | JIT_REG_FLOAT64 | JIT_REG_NFLOAT, 8,
		ALPHA_FS0, ALPHA_FS1, ALPHA_FS2, ALPHA_FS3, ALPHA_FS4,
		ALPHA_FS5, ALPHA_FS6, ALPHA_FS7, ALPHA_FT0, ALPHA_FT1,
		ALPHA_FT2, ALPHA_FT3, ALPHA_FT4, ALPHA_FT5
	);
}

#define TODO()          \
        do { \
                fprintf(stderr, "TODO at %s, %d\n", __FILE__, (int)__LINE__); \
        } while (0)


/*
 * Get the ELF machine and ABI type information for this platform. The 
 * machine field should be set to one of the EM_* values in 
 * jit-elf-defs.h. The abi field should be set to one of the ELFOSABI_* 
 * values in jit-elf-defs.h (ELFOSABI_SYSV will normally suffice if you 
 * are unsure). The abi_version field should be set to the ABI version, 
 * which is usually zero.
 */
void _jit_gen_get_elf_info(jit_elf_info_t *info) {
	info->machine = EM_ALPHA;
	info->abi = ELFOSABI_SYSV;
	info->abi_version = 0;
}

/*
 * Generate the prolog for a function into a previously-prepared buffer 
 * area of JIT_PROLOG_SIZE bytes in size. Returns the start of the 
 * prolog, which may be different than buf.
 *
 * This function is called at the end of the code generation process, 
 * not the beginning. At this point, it is known which callee save 
 * registers must be preserved, allowing the back end to output the 
 * most compact prolog possible. 
 */
void *_jit_gen_prolog(jit_gencode_t gen, jit_function_t func, void *buf) {
	unsigned int prolog[JIT_PROLOG_SIZE];
	alpha_inst inst = prolog;

	/* Compute and load the global pointer (2 instruction) */
        alpha_ldah(inst,ALPHA_GP,ALPHA_PV,0);
        alpha_lda( inst,ALPHA_GP,ALPHA_GP,0);

	/* Allocate space for a new stack frame. (1 instruction) */
	alpha_lda(inst,ALPHA_SP,ALPHA_SP,-(2*8));

	/* Save the return address. (1 instruction) */
	alpha_stq(inst,ALPHA_RA,ALPHA_SP,0*8);

	/* Save the frame pointer. (1 instruction) */
	alpha_stq(inst,ALPHA_FP,ALPHA_SP,1*8);

	/* Set the frame pointer (1 instruction) */
	alpha_mov(inst,ALPHA_SP,ALPHA_FP);

	/* Force any pending hardware exceptions to be raised. (1 instruction) */
	alpha_trapb(inst);

	/* Copy the prolog into place and return the entry position */
	jit_memcpy(buf, prolog, JIT_PROLOG_SIZE);
	return (void *) buf;
}

/*
 * Generate a function epilog, restoring the registers that were saved on entry to the 
 * function, and then returning.
 *
 * Only one epilog is generated per function. Functions with multiple jit_insn_return 

libjit/attic/jit-rules-alpha.c  view on Meta::CPAN

				break;
			case JIT_TYPE_UINT:
/* TODO add alpha_ldlu		alpha_ldlu(inst,_jit_reg_info[reg].cpu_reg,ALPHA_SP,offset);
*/				break;
			case JIT_TYPE_LONG:
				alpha_ldq(inst,_jit_reg_info[reg].cpu_reg,ALPHA_SP,offset);
				break;
			case JIT_TYPE_ULONG:
/* TODO add alpha_ldqu		alpha_ldqu(inst,_jit_reg_info[reg].cpu_reg,ALPHA_SP,offset);
*/				break;

			/* TODO requires floating-point support */
			case JIT_TYPE_FLOAT32:
			case JIT_TYPE_FLOAT64:
			case JIT_TYPE_NFLOAT:
				break;
		}
	}

	jit_cache_end_output();
}

void _jit_gen_load_global(jit_gencode_t gen, int reg, jit_value_t value) {
	TODO();
}


/*
 * Generate code for a redirector, which makes an indirect jump to the contents of 
 * func->entry_point. Redirectors are used on recompilable functions in place of the 
 * regular entry point. This allows libjit to redirect existing calls to the new 
 * version after recompilation.
 */
void *_jit_gen_redirector(jit_gencode_t gen, jit_function_t func) {
	void *ptr, *entry;
	alpha_inst inst = (alpha_inst) gen->ptr;

	_jit_gen_check_space(gen, 8*6);

	ptr = (void *)&(func->entry_point);
	entry = gen->ptr;

	alpha_call(inst, ptr);

	return entry;
}

/*
 * Generate native code for the specified insn. This function should call the 
 * appropriate register allocation routines, output the instruction, and then arrange 
 * for the result to be placed in an appropriate register or memory destination.
 */
void _jit_gen_insn(jit_gencode_t gen, jit_function_t func, jit_block_t block, jit_insn_t insn) {

	switch (insn->opcode) {
		#define JIT_INCLUDE_RULES
			#include "jit-rules-alpha.inc"
		#undef JIT_INCLUDE_RULES

		default:
			fprintf(stderr, "TODO(%x) at %s, %d\n", (int)(insn->opcode), __FILE__, (int)__LINE__);
			break;
	}
}

void _jit_gen_fix_value(jit_value_t value) {

	if (!(value->has_frame_offset) && !(value->is_constant)) {
		jit_nint size = (jit_nint)(ROUND_STACK(jit_type_get_size(value->type)));
		value->block->func->builder->frame_size += size;
		value->frame_offset = -(value->block->func->builder->frame_size);
		value->has_frame_offset = 1;
	}
}

/*
 * Output a branch instruction.
 */
void alpha_output_branch(jit_function_t func, alpha_inst inst, int opcode, jit_insn_t insn, int reg) {
	jit_block_t block;

	if (!(block = jit_block_from_label(func, (jit_label_t)(insn->dest))))
		return;

	if (block->address) {
		/* We already know the address of the block */
		short offset = ((unsigned long) block->address - (unsigned long) inst);
		alpha_encode_branch(inst,opcode,reg,offset);

	} else {
		long *addr = (void*) inst;

		/* Output a placeholder and record on the block's fixup list */
		*addr = (long) block->fixup_list;
		inst++; inst++;

		_jit_pad_buffer((unsigned char*)inst,6);
	}
}

/*
 * Jump to the current function's epilog.
 */
void jump_to_epilog(jit_gencode_t gen, alpha_inst inst, jit_block_t block) {
	long *addr = (void*) inst;

	/*
	 * If the epilog is the next thing that we will output,
	 * then fall through to the epilog directly.
	 */
	if(_jit_block_is_final(block))
	{
		return;
	}

	/*
	 * fixups are slightly strange for the alpha port. On alpha you 
	 * cannot use an address stored in memory for jumps. The address 
	 * has to stored in a register.
	 *
	 * The fixups need the address stored in memory so that they can



( run in 0.844 second using v1.01-cache-2.11-cpan-cdf2f3d4e48 )