Alien-LibJIT
view release on metacpan or search on metacpan
libjit/jit/jit-rules-x86.c view on Meta::CPAN
return 0;
}
void *_jit_gen_prolog(jit_gencode_t gen, jit_function_t func, void *buf)
{
unsigned char prolog[JIT_PROLOG_SIZE];
unsigned char *inst = prolog;
int reg;
/* Push ebp onto the stack */
x86_push_reg(inst, X86_EBP);
/* Initialize EBP for the current frame */
x86_mov_reg_reg(inst, X86_EBP, X86_ESP, sizeof(void *));
/* Allocate space for the local variable frame */
if(func->builder->frame_size > 0)
{
x86_alu_reg_imm(inst, X86_SUB, X86_ESP,
(int)(func->builder->frame_size));
}
/* Save registers that we need to preserve */
for(reg = 0; reg <= 7; ++reg)
{
if(jit_reg_is_used(gen->touched, reg) &&
(_jit_reg_info[reg].flags & JIT_REG_CALL_USED) == 0)
{
x86_push_reg(inst, _jit_reg_info[reg].cpu_reg);
}
}
/* Copy the prolog into place and return the adjusted entry position */
reg = (int)(inst - prolog);
jit_memcpy(((unsigned char *)buf) + JIT_PROLOG_SIZE - reg, prolog, reg);
return (void *)(((unsigned char *)buf) + JIT_PROLOG_SIZE - reg);
}
void _jit_gen_epilog(jit_gencode_t gen, jit_function_t func)
{
jit_nint pop_bytes = 0;
int reg, offset;
unsigned char *inst;
int struct_return_offset = 0;
void **fixup;
void **next;
/* Check if there is sufficient space for the epilog */
_jit_gen_check_space(gen, 48);
#if JIT_APPLY_X86_FASTCALL == 1
/* Determine the number of parameter bytes to pop when we return */
{
jit_type_t signature;
unsigned int num_params;
unsigned int param;
signature = func->signature;
if(jit_type_get_abi(signature) == jit_abi_stdcall ||
jit_type_get_abi(signature) == jit_abi_fastcall)
{
if(func->nested_parent)
{
pop_bytes += sizeof(void *);
}
if(jit_type_return_via_pointer(jit_type_get_return(signature)))
{
struct_return_offset = 2 * sizeof(void *) + pop_bytes;
pop_bytes += sizeof(void *);
}
num_params = jit_type_num_params(signature);
for(param = 0; param < num_params; ++param)
{
pop_bytes += ROUND_STACK
(jit_type_get_size
(jit_type_get_param(signature, param)));
}
if(jit_type_get_abi(signature) == jit_abi_fastcall)
{
/* The first two words are in fastcall registers */
if(pop_bytes > (2 * sizeof(void *)))
{
pop_bytes -= 2 * sizeof(void *);
}
else
{
pop_bytes = 0;
}
struct_return_offset = 0;
}
}
else if(!(func->nested_parent) &&
jit_type_return_via_pointer(jit_type_get_return(signature)))
{
#if JIT_APPLY_X86_POP_STRUCT_RETURN == 1
pop_bytes += sizeof(void *);
#endif
struct_return_offset = 2 * sizeof(void *);
}
}
#else
{
/* We only need to pop structure pointers in non-nested functions */
jit_type_t signature;
signature = func->signature;
if(!(func->nested_parent) &&
jit_type_return_via_pointer(jit_type_get_return(signature)))
{
#if JIT_APPLY_X86_POP_STRUCT_RETURN == 1
pop_bytes += sizeof(void *);
#endif
struct_return_offset = 2 * sizeof(void *);
}
}
#endif
/* Perform fixups on any blocks that jump to the epilog */
inst = gen->ptr;
fixup = (void **)(gen->epilog_fixup);
while(fixup != 0)
{
next = (void **)(fixup[0]);
fixup[0] = (void *)(((jit_nint)inst) - ((jit_nint)fixup) - 4);
fixup = next;
}
gen->epilog_fixup = 0;
/* If we are returning a structure via a pointer, then copy
the pointer value into EAX when we return */
if(struct_return_offset != 0)
{
x86_mov_reg_membase(inst, X86_EAX, X86_EBP, struct_return_offset, 4);
}
/* Restore the callee save registers that we used */
if(gen->stack_changed)
{
offset = -(func->builder->frame_size);
for(reg = 0; reg <= 7; ++reg)
{
if(jit_reg_is_used(gen->touched, reg) &&
(_jit_reg_info[reg].flags & JIT_REG_CALL_USED) == 0)
{
offset -= sizeof(void *);
x86_mov_reg_membase(inst, _jit_reg_info[reg].cpu_reg,
X86_EBP, offset, sizeof(void *));
}
}
}
else
{
for(reg = 7; reg >= 0; --reg)
{
if(jit_reg_is_used(gen->touched, reg) &&
(_jit_reg_info[reg].flags & JIT_REG_CALL_USED) == 0)
{
x86_pop_reg(inst, _jit_reg_info[reg].cpu_reg);
}
}
}
/* Pop the stack frame and restore the saved copy of ebp */
if(gen->stack_changed || func->builder->frame_size > 0)
{
x86_mov_reg_reg(inst, X86_ESP, X86_EBP, sizeof(void *));
}
( run in 4.707 seconds using v1.01-cache-2.11-cpan-cdf2f3d4e48 )