#include "jit-internal.h"
#include "jit-apply-rules.h"
#include "jit-apply-func.h"
#if defined(__i386) || defined(__i386__) || defined(_M_IX86)
#include "jit-gen-x86.h"
void _jit_create_closure(unsigned char *buf, void *func,
void *closure, void *_type)
{
jit_type_t signature = (jit_type_t)_type;
jit_type_t type;
#if JIT_APPLY_X86_FASTCALL == 1
jit_abi_t abi = jit_type_get_abi(signature);
#endif
unsigned int num_bytes = 0;
int struct_return_offset = 0;
x86_push_reg(buf, X86_EBP);
x86_mov_reg_reg(buf, X86_EBP, X86_ESP, 4);
#if JIT_APPLY_X86_FASTCALL == 1
if(abi == jit_abi_fastcall)
{
x86_push_reg(buf, X86_EDX);
x86_push_reg(buf, X86_ECX);
}
#endif
x86_lea_membase(buf, X86_EAX, X86_EBP, 8);
x86_push_reg(buf, X86_EAX);
x86_mov_reg_reg(buf, X86_EAX, X86_ESP, 4);
x86_push_reg(buf, X86_EAX);
x86_push_imm(buf, (int)closure);
x86_call_code(buf, func);
#if JIT_APPLY_X86_FASTCALL == 1
if(abi == jit_abi_stdcall || abi == jit_abi_fastcall)
{
unsigned int word_regs;
unsigned int size;
unsigned int num_params;
unsigned int param;
if(abi == jit_abi_stdcall)
{
word_regs = 0;
}
else
{
word_regs = 2;
}
type = jit_type_normalize(jit_type_get_return(signature));
if(jit_type_return_via_pointer(type))
{
if(word_regs > 0)
{
--word_regs;
}
else
{
num_bytes += sizeof(void *);
struct_return_offset = 2 * sizeof(void *);
}
}
num_params = jit_type_num_params(signature);
for(param = 0; param < num_params; ++param)
{
type = jit_type_normalize(jit_type_get_param(signature, param));
size = jit_type_get_size(type);
if(word_regs > 0)
{
switch(type->kind)
{
case JIT_TYPE_SBYTE:
case JIT_TYPE_UBYTE:
case JIT_TYPE_SHORT:
case JIT_TYPE_USHORT:
case JIT_TYPE_INT:
case JIT_TYPE_UINT:
case JIT_TYPE_NINT:
case JIT_TYPE_NUINT:
case JIT_TYPE_SIGNATURE:
case JIT_TYPE_PTR:
{
--word_regs;
}
continue;
case JIT_TYPE_LONG:
case JIT_TYPE_ULONG:
{
if(word_regs == 1)
{
num_bytes += sizeof(void *);
}
word_regs = 0;
}
continue;
}
word_regs = 0;
}
num_bytes += (size + sizeof(void *) - 1) & ~(sizeof(void *) - 1);
}
}
else
#endif
{
type = jit_type_normalize(jit_type_get_return(signature));
if(jit_type_return_via_pointer(type))
{
#if JIT_APPLY_X86_POP_STRUCT_RETURN == 1
num_bytes += sizeof(void *);
#endif
struct_return_offset = 2 * sizeof(void *);
}
}
if(struct_return_offset != 0)
{
x86_mov_reg_membase(buf, X86_EAX, X86_EBP, struct_return_offset, 4);
}
x86_mov_reg_reg(buf, X86_ESP, X86_EBP, 4);
x86_pop_reg(buf, X86_EBP);
if(num_bytes > 0)
{
x86_ret_imm(buf, num_bytes);
}
else
{
x86_ret(buf);
}
}
void *_jit_create_redirector(unsigned char *buf, void *func,
void *user_data, int abi)
{
void *start = (void *)buf;
#if JIT_APPLY_X86_FASTCALL == 1
if(abi == (int)jit_abi_fastcall)
{
x86_push_reg(buf, X86_EDX);
x86_push_reg(buf, X86_ECX);
}
#endif
x86_push_imm(buf, (int)user_data);
x86_call_code(buf, func);
x86_pop_reg(buf, X86_ECX);
#if JIT_APPLY_X86_FASTCALL == 1
if(abi == (int)jit_abi_fastcall)
{
x86_pop_reg(buf, X86_ECX);
x86_pop_reg(buf, X86_EDX);
}
#endif
x86_jump_reg(buf, X86_EAX);
return start;
}
void *_jit_create_indirector(unsigned char *buf, void **entry)
{
void *start = (void *)buf;
x86_jump_mem(buf, entry);
return start;
}
void _jit_pad_buffer(unsigned char *buf, int len)
{
while(len >= 6)
{
*buf++ = (unsigned char)0x8D;
x86_address_byte(buf, 2, X86_ESI, X86_ESI);
x86_imm_emit32(buf, 0);
len -= 6;
}
if(len >= 3)
{
*buf++ = (unsigned char)0x8D;
x86_address_byte(buf, 1, X86_ESI, X86_ESI);
x86_imm_emit8(buf, 0);
len -= 3;
}
if(len == 1)
{
x86_nop(buf);
}
else if(len == 2)
{
x86_mov_reg_reg(buf, X86_ESI, X86_ESI, 4);
}
}
#endif