#include "jit-internal.h"
#include "jit-rules.h"
#include "jit-reg-alloc.h"
#if defined(JIT_BACKEND_INTERP)
#include "jit-interp.h"
#define jit_cache_native(gen,value) \
do { \
_jit_gen_check_space((gen), sizeof(jit_nuint)); \
*((jit_nuint *)((gen)->ptr)) = (jit_nuint)(value); \
(gen)->ptr += sizeof(jit_nuint); \
} while (0)
#define jit_cache_opcode(gen,opcode) \
jit_cache_native((gen), (jit_nint)(opcode))
#define jit_cache_add_n(gen,buf,size) \
do { \
unsigned int __size = \
((size) + sizeof(void *) - 1) & ~(sizeof(void *) - 1); \
_jit_gen_check_space((gen), __size); \
jit_memcpy((gen)->ptr, (buf), (size)); \
(gen)->ptr += __size; \
} while (0)
#define adjust_working(gen,adjust) \
do { \
(gen)->working_area += (adjust); \
if((gen)->working_area > (gen)->max_working_area) \
{ \
(gen)->max_working_area = (gen)->working_area; \
} \
} while (0)
void _jit_init_backend(void)
{
}
void _jit_gen_get_elf_info(jit_elf_info_t *info)
{
info->machine = 0x4C6A;
info->abi = 0;
info->abi_version = JIT_OPCODE_VERSION;
}
int _jit_create_entry_insns(jit_function_t func)
{
jit_type_t signature = func->signature;
jit_type_t type;
jit_nint offset;
jit_value_t value;
unsigned int num_params;
unsigned int param;
func->builder->frame_size = 0;
offset = -1;
if(func->nested_parent)
{
offset -= 2;
}
value = jit_value_get_struct_pointer(func);
if(value)
{
if(!jit_insn_incoming_frame_posn(func, value, offset))
{
return 0;
}
--offset;
}
num_params = jit_type_num_params(signature);
for(param = 0; param < num_params; ++param)
{
value = jit_value_get_param(func, param);
if(!value)
{
continue;
}
type = jit_type_normalize(jit_value_get_type(value));
switch(type->kind)
{
case JIT_TYPE_SBYTE:
case JIT_TYPE_UBYTE:
{
if(!jit_insn_incoming_frame_posn
(func, value, offset - _jit_int_lowest_byte()))
{
return 0;
}
--offset;
}
break;
case JIT_TYPE_SHORT:
case JIT_TYPE_USHORT:
{
if(!jit_insn_incoming_frame_posn
(func, value, offset - _jit_int_lowest_short()))
{
return 0;
}
--offset;
}
break;
case JIT_TYPE_INT:
case JIT_TYPE_UINT:
case JIT_TYPE_NINT:
case JIT_TYPE_NUINT:
case JIT_TYPE_SIGNATURE:
case JIT_TYPE_PTR:
case JIT_TYPE_LONG:
case JIT_TYPE_ULONG:
case JIT_TYPE_FLOAT32:
case JIT_TYPE_FLOAT64:
case JIT_TYPE_NFLOAT:
{
if(!jit_insn_incoming_frame_posn(func, value, offset))
{
return 0;
}
--offset;
}
break;
case JIT_TYPE_STRUCT:
case JIT_TYPE_UNION:
{
if(!jit_insn_incoming_frame_posn(func, value, offset))
{
return 0;
}
offset -= JIT_NUM_ITEMS_IN_STRUCT(jit_type_get_size(type));
}
break;
}
}
return 1;
}
int _jit_create_call_setup_insns
(jit_function_t func, jit_type_t signature,
jit_value_t *args, unsigned int num_args,
int is_nested, int nested_level, jit_value_t *struct_return, int flags)
{
jit_type_t type;
jit_type_t vtype;
jit_value_t value;
unsigned int arg_num;
jit_nint offset;
jit_nuint size;
if((flags & JIT_CALL_TAIL) == 0)
{
while(num_args > 0)
{
--num_args;
type = jit_type_normalize(jit_type_get_param(signature, num_args));
if(type->kind == JIT_TYPE_STRUCT || type->kind == JIT_TYPE_UNION)
{
vtype = jit_type_normalize(jit_value_get_type(args[num_args]));
if(vtype->kind <= JIT_TYPE_MAX_PRIMITIVE)
{
if(!jit_insn_push_ptr(func, args[num_args], type))
{
return 0;
}
continue;
}
}
if(!jit_insn_push(func, args[num_args]))
{
return 0;
}
}
type = jit_type_get_return(signature);
if(jit_type_return_via_pointer(type))
{
value = jit_value_create(func, type);
if(!value)
{
return 0;
}
*struct_return = value;
value = jit_insn_address_of(func, value);
if(!value)
{
return 0;
}
if(!jit_insn_push(func, value))
{
return 0;
}
}
else if((flags & JIT_CALL_NATIVE) != 0)
{
if(!jit_insn_push_return_area_ptr(func))
{
return 0;
}
*struct_return = 0;
}
else
{
*struct_return = 0;
}
if(is_nested)
{
if(!jit_insn_setup_for_nested(func, nested_level, -1))
{
return 0;
}
}
}
else
{
offset = -1;
if(func->nested_parent)
{
offset -= 2;
}
type = jit_type_get_return(signature);
if(jit_type_return_via_pointer(type))
{
--offset;
}
for(arg_num = 0; arg_num < num_args; ++arg_num)
{
type = jit_type_get_param(signature, arg_num);
value = jit_value_create(func, type);
if(!value)
{
return 0;
}
if(!jit_insn_outgoing_frame_posn(func, value, offset))
{
return 0;
}
type = jit_type_normalize(type);
size = jit_type_get_size(type);
offset -= (jit_nint)(JIT_NUM_ITEMS_IN_STRUCT(size));
if(type->kind == JIT_TYPE_STRUCT || type->kind == JIT_TYPE_UNION)
{
vtype = jit_type_normalize(jit_value_get_type(args[arg_num]));
if(vtype->kind <= JIT_TYPE_MAX_PRIMITIVE)
{
value = jit_insn_address_of(func, value);
if(!value)
{
return 0;
}
if(!jit_insn_memcpy
(func, value, args[arg_num],
jit_value_create_nint_constant
(func, jit_type_nint, (jit_nint)size)))
{
return 0;
}
continue;
}
}
if(!jit_insn_store(func, value, args[arg_num]))
{
return 0;
}
}
*struct_return = 0;
}
return 1;
}
int _jit_setup_indirect_pointer(jit_function_t func, jit_value_t value)
{
return 1;
}
int _jit_create_call_return_insns
(jit_function_t func, jit_type_t signature,
jit_value_t *args, unsigned int num_args,
jit_value_t return_value, int is_nested)
{
jit_nint pop_items;
unsigned int size;
jit_type_t return_type;
int ptr_return;
pop_items = 0;
while(num_args > 0)
{
--num_args;
size = jit_type_get_size(jit_value_get_type(args[num_args]));
pop_items += JIT_NUM_ITEMS_IN_STRUCT(size);
}
return_type = jit_type_normalize(jit_type_get_return(signature));
ptr_return = jit_type_return_via_pointer(return_type);
if(ptr_return)
{
++pop_items;
}
if(is_nested)
{
pop_items += 2;
}
if(pop_items > 0)
{
if(!jit_insn_pop_stack(func, pop_items))
{
return 0;
}
}
if(!return_value || ptr_return)
{
return 1;
}
if(jit_type_is_struct(return_type) || jit_type_is_union(return_type))
{
if(!jit_insn_flush_struct(func, return_value))
{
return 0;
}
}
else if(return_type->kind != JIT_TYPE_VOID)
{
if(!jit_insn_return_reg(func, return_value, 0))
{
return 0;
}
}
return 1;
}
int _jit_opcode_is_supported(int opcode)
{
return 1;
}
unsigned int _jit_interp_calculate_arg_size
(jit_function_t func, jit_type_t signature)
{
unsigned int size = 0;
jit_type_t type;
unsigned int num_params;
unsigned int param;
if(func->nested_parent)
{
size += 2 * sizeof(jit_item);
}
type = jit_type_get_return(signature);
if(jit_type_return_via_pointer(type))
{
size += sizeof(jit_item);
}
num_params = jit_type_num_params(signature);
for(param = 0; param < num_params; ++param)
{
type = jit_type_normalize(jit_type_get_param(signature, param));
if(type->kind == JIT_TYPE_STRUCT || type->kind == JIT_TYPE_UNION)
{
size += JIT_NUM_ITEMS_IN_STRUCT(jit_type_get_size(type)) *
sizeof(jit_item);
}
else
{
size += sizeof(jit_item);
}
}
return size;
}
void *_jit_gen_prolog(jit_gencode_t gen, jit_function_t func, void *buf)
{
jit_function_interp_t interp = (jit_function_interp_t)buf;
unsigned int max_working_area =
gen->max_working_area + gen->extra_working_space;
interp->func = func;
interp->args_size = _jit_interp_calculate_arg_size(func, func->signature);
interp->frame_size =
(func->builder->frame_size + max_working_area) * sizeof(jit_item);
interp->working_area = max_working_area;
return buf;
}
void _jit_gen_epilog(jit_gencode_t gen, jit_function_t func)
{
}
void *_jit_gen_redirector(jit_gencode_t gen, jit_function_t func)
{
return 0;
}
void _jit_gen_spill_reg(jit_gencode_t gen, int reg,
int other_reg, jit_value_t value)
{
}
void _jit_gen_free_reg(jit_gencode_t gen, int reg,
int other_reg, int value_used)
{
}
void _jit_gen_load_value
(jit_gencode_t gen, int reg, int other_reg, jit_value_t value)
{
}
void _jit_gen_spill_global(jit_gencode_t gen, int reg, jit_value_t value)
{
}
void _jit_gen_load_global(jit_gencode_t gen, int reg, jit_value_t value)
{
}
void _jit_gen_exch_top(jit_gencode_t gen, int reg)
{
}
void _jit_gen_move_top(jit_gencode_t gen, int reg)
{
}
void _jit_gen_spill_top(jit_gencode_t gen, int reg, jit_value_t value, int pop)
{
}
void _jit_gen_fix_value(jit_value_t value)
{
if(!(value->has_frame_offset) && !(value->is_constant))
{
jit_nint size = (jit_nint)
(JIT_NUM_ITEMS_IN_STRUCT(jit_type_get_size(value->type)));
value->frame_offset = value->block->func->builder->frame_size;
value->block->func->builder->frame_size += size;
value->has_frame_offset = 1;
}
}
static void
load_value(jit_gencode_t gen, jit_value_t value, int index)
{
int opcode;
jit_nint offset;
if(value->is_constant)
{
switch(jit_type_normalize(value->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:
jit_cache_opcode(gen, JIT_INTERP_OP_LDC_0_INT + index);
jit_cache_native(gen, (jit_nint)(value->address));
break;
case JIT_TYPE_LONG:
case JIT_TYPE_ULONG:
{
jit_long long_value;
long_value = jit_value_get_long_constant(value);
jit_cache_opcode(gen, JIT_INTERP_OP_LDC_0_LONG + index);
#ifdef JIT_NATIVE_INT64
jit_cache_native(gen, long_value);
#else
jit_cache_add_n(gen, &long_value, sizeof(long_value));
#endif
break;
}
case JIT_TYPE_FLOAT32:
{
jit_float32 float32_value;
float32_value = jit_value_get_float32_constant(value);
jit_cache_opcode(gen, JIT_INTERP_OP_LDC_0_FLOAT32 + index);
jit_cache_add_n(gen, &float32_value, sizeof(float32_value));
break;
}
case JIT_TYPE_FLOAT64:
{
jit_float64 float64_value;
float64_value = jit_value_get_float64_constant(value);
jit_cache_opcode(gen, JIT_INTERP_OP_LDC_0_FLOAT64 + index);
jit_cache_add_n (gen, &float64_value, sizeof(float64_value));
break;
}
case JIT_TYPE_NFLOAT:
{
jit_nfloat nfloat_value;
nfloat_value = jit_value_get_nfloat_constant(value);
jit_cache_opcode(gen, JIT_INTERP_OP_LDC_0_NFLOAT + index);
jit_cache_add_n (gen, &nfloat_value, sizeof(nfloat_value));
break;
}
}
}
else
{
_jit_gen_fix_value(value);
if(value->frame_offset >= 0)
{
switch(index)
{
case 0:
opcode = JIT_INTERP_OP_LDL_0_SBYTE;
break;
case 1:
opcode = JIT_INTERP_OP_LDL_1_SBYTE;
break;
case 2:
opcode = JIT_INTERP_OP_LDL_2_SBYTE;
break;
default:
return;
}
opcode = _jit_load_opcode(opcode, value->type, value, 0);
offset = value->frame_offset;
}
else
{
switch(index)
{
case 0:
opcode = JIT_INTERP_OP_LDA_0_SBYTE;
break;
case 1:
opcode = JIT_INTERP_OP_LDA_1_SBYTE;
break;
case 2:
opcode = JIT_INTERP_OP_LDA_2_SBYTE;
break;
default:
return;
}
opcode = _jit_load_opcode(opcode, value->type, value, 0);
offset = -(value->frame_offset + 1);
}
jit_cache_opcode(gen, opcode);
jit_cache_native(gen, offset);
}
}
static void
store_value(jit_gencode_t gen, jit_value_t value)
{
int opcode;
jit_nint offset;
_jit_gen_fix_value(value);
offset = value->frame_offset;
if(offset >= 0)
{
opcode = _jit_store_opcode(JIT_INTERP_OP_STL_0_BYTE, 0, value->type);
}
else
{
opcode = _jit_store_opcode(JIT_INTERP_OP_STA_0_BYTE, 0, value->type);
offset = -(offset + 1);
}
jit_cache_opcode(gen, opcode);
jit_cache_native(gen, offset);
}
void _jit_gen_insn(jit_gencode_t gen, jit_function_t func,
jit_block_t block, jit_insn_t insn)
{
jit_label_t label;
void **pc;
jit_nint offset;
jit_nint size;
switch(insn->opcode)
{
case JIT_OP_BR_IEQ:
case JIT_OP_BR_INE:
case JIT_OP_BR_ILT:
case JIT_OP_BR_ILT_UN:
case JIT_OP_BR_ILE:
case JIT_OP_BR_ILE_UN:
case JIT_OP_BR_IGT:
case JIT_OP_BR_IGT_UN:
case JIT_OP_BR_IGE:
case JIT_OP_BR_IGE_UN:
case JIT_OP_BR_LEQ:
case JIT_OP_BR_LNE:
case JIT_OP_BR_LLT:
case JIT_OP_BR_LLT_UN:
case JIT_OP_BR_LLE:
case JIT_OP_BR_LLE_UN:
case JIT_OP_BR_LGT:
case JIT_OP_BR_LGT_UN:
case JIT_OP_BR_LGE:
case JIT_OP_BR_LGE_UN:
case JIT_OP_BR_FEQ:
case JIT_OP_BR_FNE:
case JIT_OP_BR_FLT:
case JIT_OP_BR_FLE:
case JIT_OP_BR_FGT:
case JIT_OP_BR_FGE:
case JIT_OP_BR_FLT_INV:
case JIT_OP_BR_FLE_INV:
case JIT_OP_BR_FGT_INV:
case JIT_OP_BR_FGE_INV:
case JIT_OP_BR_DEQ:
case JIT_OP_BR_DNE:
case JIT_OP_BR_DLT:
case JIT_OP_BR_DLE:
case JIT_OP_BR_DGT:
case JIT_OP_BR_DGE:
case JIT_OP_BR_DLT_INV:
case JIT_OP_BR_DLE_INV:
case JIT_OP_BR_DGT_INV:
case JIT_OP_BR_DGE_INV:
case JIT_OP_BR_NFEQ:
case JIT_OP_BR_NFNE:
case JIT_OP_BR_NFLT:
case JIT_OP_BR_NFLE:
case JIT_OP_BR_NFGT:
case JIT_OP_BR_NFGE:
case JIT_OP_BR_NFLT_INV:
case JIT_OP_BR_NFLE_INV:
case JIT_OP_BR_NFGT_INV:
case JIT_OP_BR_NFGE_INV:
load_value(gen, insn->value2, 2);
case JIT_OP_BR_IFALSE:
case JIT_OP_BR_ITRUE:
case JIT_OP_BR_LFALSE:
case JIT_OP_BR_LTRUE:
load_value(gen, insn->value1, 1);
case JIT_OP_BR:
case JIT_OP_CALL_FINALLY:
branch:
label = (jit_label_t)(insn->dest);
pc = (void **)(gen->ptr);
jit_cache_opcode(gen, insn->opcode);
block = jit_block_from_label(func, label);
if(!block)
{
break;
}
if(block->address)
{
jit_cache_native(gen, ((void **)(block->address)) - pc);
}
else
{
jit_cache_native(gen, block->fixup_list);
block->fixup_list = (void *)pc;
}
break;
case JIT_OP_CALL_FILTER:
load_value(gen, insn->value1, 0);
goto branch;
case JIT_OP_JUMP_TABLE:
{
jit_label_t *labels;
jit_nint num_labels;
jit_nint index;
load_value(gen, insn->dest, 0);
labels = (jit_label_t *) insn->value1->address;
num_labels = insn->value2->address;
jit_cache_opcode(gen, insn->opcode);
jit_cache_native(gen, num_labels);
for(index = 0; index < num_labels; index++)
{
block = jit_block_from_label(func, labels[index]);
if(!block)
{
return;
}
if(block->address)
{
jit_cache_native(gen, block->address);
}
else
{
pc = (void **)(gen->ptr);
jit_cache_native(gen, block->fixup_absolute_list);
block->fixup_absolute_list = pc;
}
}
break;
}
case JIT_OP_ADDRESS_OF_LABEL:
label = (jit_label_t)(insn->value1);
block = jit_block_from_label(func, label);
if(!block)
{
break;
}
pc = (void **)(gen->ptr);
jit_cache_opcode(gen, insn->opcode);
if(block->address)
{
jit_cache_native(gen, ((void **)(block->address)) - pc);
}
else
{
jit_cache_native(gen, block->fixup_list);
block->fixup_list = (void *)pc;
}
store_value(gen, insn->dest);
break;
case JIT_OP_CALL:
case JIT_OP_CALL_TAIL:
jit_cache_opcode(gen, insn->opcode);
jit_cache_native(gen, (jit_nint)(insn->dest));
break;
case JIT_OP_CALL_INDIRECT:
case JIT_OP_CALL_INDIRECT_TAIL:
load_value(gen, insn->value1, 1);
jit_cache_opcode(gen, insn->opcode);
jit_cache_native(gen, (jit_nint)(insn->value2));
jit_cache_native(gen, (jit_nint)
(jit_type_num_params((jit_type_t)(insn->value2))));
break;
case JIT_OP_CALL_VTABLE_PTR:
case JIT_OP_CALL_VTABLE_PTR_TAIL:
load_value(gen, insn->value1, 1);
jit_cache_opcode(gen, insn->opcode);
break;
case JIT_OP_CALL_EXTERNAL:
case JIT_OP_CALL_EXTERNAL_TAIL:
jit_cache_opcode(gen, insn->opcode);
jit_cache_native(gen, (jit_nint)(insn->value2));
jit_cache_native(gen, (jit_nint)(insn->dest));
jit_cache_native(gen, (jit_nint)
(jit_type_num_params((jit_type_t)(insn->value2))));
break;
case JIT_OP_RETURN:
jit_cache_opcode(gen, JIT_OP_RETURN);
break;
case JIT_OP_RETURN_INT:
case JIT_OP_RETURN_LONG:
case JIT_OP_RETURN_FLOAT32:
case JIT_OP_RETURN_FLOAT64:
case JIT_OP_RETURN_NFLOAT:
load_value(gen, insn->value1, 1);
jit_cache_opcode(gen, insn->opcode);
break;
case JIT_OP_RETURN_SMALL_STRUCT:
load_value(gen, insn->value1, 1);
jit_cache_opcode(gen, insn->opcode);
jit_cache_native(gen, jit_value_get_nint_constant(insn->value2));
break;
case JIT_OP_SETUP_FOR_NESTED:
jit_cache_opcode(gen, insn->opcode);
adjust_working(gen, 2);
break;
case JIT_OP_SETUP_FOR_SIBLING:
jit_cache_opcode(gen, insn->opcode);
jit_cache_native(gen, jit_value_get_nint_constant(insn->value1));
adjust_working(gen, 2);
break;
case JIT_OP_IMPORT:
_jit_gen_fix_value(insn->value1);
if(insn->value1->frame_offset >= 0)
{
jit_cache_opcode(gen, JIT_INTERP_OP_IMPORT_LOCAL);
jit_cache_native(gen, insn->value1->frame_offset);
jit_cache_native(gen, jit_value_get_nint_constant(insn->value2));
}
else
{
jit_cache_opcode(gen, JIT_INTERP_OP_IMPORT_ARG);
jit_cache_native(gen, -(insn->value1->frame_offset + 1));
jit_cache_native(gen, jit_value_get_nint_constant(insn->value2));
}
store_value(gen, insn->dest);
break;
case JIT_OP_THROW:
load_value(gen, insn->value1, 1);
jit_cache_opcode(gen, insn->opcode);
break;
case JIT_OP_LOAD_PC:
case JIT_OP_LOAD_EXCEPTION_PC:
jit_cache_opcode(gen, insn->opcode);
store_value(gen, insn->dest);
break;
case JIT_OP_CALL_FILTER_RETURN:
store_value(gen, insn->dest);
break;
case JIT_OP_ENTER_FINALLY:
++(gen->extra_working_space);
break;
case JIT_OP_LEAVE_FINALLY:
jit_cache_opcode(gen, insn->opcode);
break;
case JIT_OP_ENTER_FILTER:
++(gen->extra_working_space);
store_value(gen, insn->dest);
break;
case JIT_OP_LEAVE_FILTER:
load_value(gen, insn->value1, 0);
jit_cache_opcode(gen, insn->opcode);
break;
case JIT_OP_INCOMING_REG:
store_value(gen, insn->value1);
break;
case JIT_OP_RETURN_REG:
switch(jit_type_normalize(insn->value1->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:
jit_cache_opcode(gen, JIT_INTERP_OP_LDR_0_INT);
store_value(gen, insn->value1);
break;
case JIT_TYPE_LONG:
case JIT_TYPE_ULONG:
jit_cache_opcode(gen, JIT_INTERP_OP_LDR_0_LONG);
store_value(gen, insn->value1);
break;
case JIT_TYPE_FLOAT32:
jit_cache_opcode(gen, JIT_INTERP_OP_LDR_0_FLOAT32);
store_value(gen, insn->value1);
break;
case JIT_TYPE_FLOAT64:
jit_cache_opcode(gen, JIT_INTERP_OP_LDR_0_FLOAT64);
store_value(gen, insn->value1);
break;
case JIT_TYPE_NFLOAT:
jit_cache_opcode(gen, JIT_INTERP_OP_LDR_0_NFLOAT);
store_value(gen, insn->value1);
break;
}
break;
case JIT_OP_COPY_LOAD_SBYTE:
case JIT_OP_COPY_LOAD_UBYTE:
case JIT_OP_COPY_LOAD_SHORT:
case JIT_OP_COPY_LOAD_USHORT:
case JIT_OP_COPY_INT:
case JIT_OP_COPY_LONG:
case JIT_OP_COPY_FLOAT32:
case JIT_OP_COPY_FLOAT64:
case JIT_OP_COPY_NFLOAT:
case JIT_OP_COPY_STORE_BYTE:
case JIT_OP_COPY_STORE_SHORT:
load_value(gen, insn->value1, 0);
store_value(gen, insn->dest);
break;
case JIT_OP_COPY_STRUCT:
load_value(gen, insn->dest, 0);
load_value(gen, insn->value1, 1);
size = (jit_nint)jit_type_get_size(jit_value_get_type(insn->dest));
jit_cache_opcode(gen, insn->opcode);
jit_cache_native(gen, size);
break;
case JIT_OP_ADDRESS_OF:
_jit_gen_fix_value(insn->value1);
if(insn->value1->frame_offset >= 0)
{
jit_cache_opcode(gen, JIT_INTERP_OP_LDLA_0);
jit_cache_native(gen, insn->value1->frame_offset);
}
else
{
jit_cache_opcode(gen, JIT_INTERP_OP_LDAA_0);
jit_cache_native(gen, -(insn->value1->frame_offset + 1));
}
store_value(gen, insn->dest);
break;
case JIT_OP_PUSH_INT:
case JIT_OP_PUSH_LONG:
case JIT_OP_PUSH_FLOAT32:
case JIT_OP_PUSH_FLOAT64:
case JIT_OP_PUSH_NFLOAT:
load_value(gen, insn->value1, 1);
jit_cache_opcode(gen, insn->opcode);
adjust_working(gen, 1);
break;
case JIT_OP_PUSH_STRUCT:
load_value(gen, insn->value1, 1);
size = jit_value_get_nint_constant(insn->value2);
jit_cache_opcode(gen, insn->opcode);
jit_cache_native(gen, size);
adjust_working(gen, JIT_NUM_ITEMS_IN_STRUCT(size));
break;
case JIT_OP_PUSH_RETURN_AREA_PTR:
jit_cache_opcode(gen, insn->opcode);
adjust_working(gen, 1);
break;
case JIT_OP_POP_STACK:
size = jit_value_get_nint_constant(insn->value1);
if(size == 1)
{
jit_cache_opcode(gen, JIT_INTERP_OP_POP);
}
else if(size == 2)
{
jit_cache_opcode(gen, JIT_INTERP_OP_POP_2);
}
else if(size == 3)
{
jit_cache_opcode(gen, JIT_INTERP_OP_POP_3);
}
else if(size != 0)
{
jit_cache_opcode(gen, JIT_OP_POP_STACK);
jit_cache_native(gen, size);
}
break;
case JIT_OP_FLUSH_SMALL_STRUCT:
load_value(gen, insn->value1, 0);
size = (jit_nint)jit_type_get_size(jit_value_get_type(insn->value1));
jit_cache_opcode(gen, insn->opcode);
jit_cache_native(gen, size);
break;
case JIT_OP_LOAD_RELATIVE_SBYTE:
case JIT_OP_LOAD_RELATIVE_UBYTE:
case JIT_OP_LOAD_RELATIVE_SHORT:
case JIT_OP_LOAD_RELATIVE_USHORT:
case JIT_OP_LOAD_RELATIVE_INT:
case JIT_OP_LOAD_RELATIVE_LONG:
case JIT_OP_LOAD_RELATIVE_FLOAT32:
case JIT_OP_LOAD_RELATIVE_FLOAT64:
case JIT_OP_LOAD_RELATIVE_NFLOAT:
load_value(gen, insn->value1, 1);
offset = jit_value_get_nint_constant(insn->value2);
jit_cache_opcode(gen, insn->opcode);
jit_cache_native(gen, offset);
store_value(gen, insn->dest);
break;
case JIT_OP_LOAD_RELATIVE_STRUCT:
load_value(gen, insn->dest, 0);
load_value(gen, insn->value1, 1);
offset = jit_value_get_nint_constant(insn->value2);
size = (jit_nint)jit_type_get_size(jit_value_get_type(insn->dest));
jit_cache_opcode(gen, insn->opcode);
jit_cache_native(gen, offset);
jit_cache_native(gen, size);
break;
case JIT_OP_STORE_RELATIVE_BYTE:
case JIT_OP_STORE_RELATIVE_SHORT:
case JIT_OP_STORE_RELATIVE_INT:
case JIT_OP_STORE_RELATIVE_LONG:
case JIT_OP_STORE_RELATIVE_FLOAT32:
case JIT_OP_STORE_RELATIVE_FLOAT64:
case JIT_OP_STORE_RELATIVE_NFLOAT:
load_value(gen, insn->dest, 0);
load_value(gen, insn->value1, 1);
offset = jit_value_get_nint_constant(insn->value2);
jit_cache_opcode(gen, insn->opcode);
jit_cache_native(gen, offset);
break;
case JIT_OP_STORE_RELATIVE_STRUCT:
load_value(gen, insn->dest, 0);
load_value(gen, insn->value1, 1);
offset = jit_value_get_nint_constant(insn->value2);
size = (jit_nint)jit_type_get_size(jit_value_get_type(insn->value1));
jit_cache_opcode(gen, insn->opcode);
jit_cache_native(gen, offset);
jit_cache_native(gen, size);
break;
case JIT_OP_ADD_RELATIVE:
offset = jit_value_get_nint_constant(insn->value2);
if(offset != 0)
{
load_value(gen, insn->value1, 1);
jit_cache_opcode(gen, insn->opcode);
jit_cache_native(gen, offset);
store_value(gen, insn->dest);
}
else
{
load_value(gen, insn->value1, 0);
store_value(gen, insn->dest);
}
break;
case JIT_OP_MARK_BREAKPOINT:
jit_cache_opcode(gen, insn->opcode);
jit_cache_native(gen, insn->value1->address);
jit_cache_native(gen, insn->value2->address);
break;
default:
if(insn->dest && (insn->flags & JIT_INSN_DEST_IS_VALUE) != 0)
{
load_value(gen, insn->dest, 0);
}
if(insn->value1)
{
load_value(gen, insn->value1, 1);
}
if(insn->value2)
{
load_value(gen, insn->value2, 2);
}
jit_cache_opcode(gen, insn->opcode);
if(insn->dest && (insn->flags & JIT_INSN_DEST_IS_VALUE) == 0)
{
store_value(gen, insn->dest);
}
break;
}
}
void _jit_gen_start_block(jit_gencode_t gen, jit_block_t block)
{
void **fixup;
void **next;
block->address = (void *)(gen->ptr);
fixup = (void **)(block->fixup_list);
while(fixup != 0)
{
next = (void **)(fixup[1]);
fixup[1] = (void *)(jit_nint)(((void **)(block->address)) - fixup);
fixup = next;
}
block->fixup_list = 0;
fixup = (void **)(block->fixup_absolute_list);
while(fixup != 0)
{
next = (void **)(fixup[0]);
fixup[0] = (void *)(jit_nint)((void **)(block->address));
fixup = next;
}
block->fixup_absolute_list = 0;
if(block->label == block->func->builder->catcher_label &&
block->func->has_try)
{
block->func->cookie = block->address;
}
}
void _jit_gen_end_block(jit_gencode_t gen, jit_block_t block)
{
gen->working_area = 0;
}
int _jit_gen_is_global_candidate(jit_type_t type)
{
return 0;
}
int _jit_reg_get_pair(jit_type_t type, int reg)
{
return -1;
}
#endif