x86_alu_reg_reg(inst, X86_CMP, $1, $2);
inst = setcc_reg(inst, $1, X86_CC_GE, 0);
}
+
+/*
+ * Pointer check opcodes.
+ */
+
+JIT_OP_CHECK_NULL: unary_branch
+ [reg] -> {
+ /* TODO: won't work in a function with a "try" block */
+ unsigned char *patch;
+ x86_alu_reg_reg(inst, X86_OR, $1, $1);
+ patch = inst;
+ x86_branch8(inst, X86_CC_NE, 0, 0);
+ x86_push_imm(inst, JIT_RESULT_NULL_REFERENCE);
+ x86_call_code(inst, (void *)jit_exception_builtin);
+ x86_patch(patch, inst);
+ }
+
+/*
+ * Function calls.
+ */
+
+JIT_OP_CALL:
+ [] -> {
+ jit_function_t func = (jit_function_t)(insn->dest);
+ x86_call_code(inst, func->closure_entry);
+ }
+
+JIT_OP_CALL_TAIL:
+ [] -> {
+ jit_function_t func = (jit_function_t)(insn->dest);
+ x86_jump_code(inst, func->closure_entry);
+ }
+
+JIT_OP_CALL_INDIRECT:
+ [] -> {
+ x86_call_reg(inst, X86_EAX);
+ }
+
+JIT_OP_CALL_VTABLE_PTR:
+ [] -> {
+ x86_call_reg(inst, X86_EAX);
+ }
+
+JIT_OP_CALL_EXTERNAL:
+ [] -> {
+ x86_call_code(inst, (void *)(insn->dest));
+ }
+
+JIT_OP_RETURN:
+ [] -> {
+ inst = jump_to_epilog(gen, inst, insn);
+ }
+
+JIT_OP_RETURN_INT: unary_branch
+ [reg] -> {
+ int cpu_reg = $1;
+ if(cpu_reg != X86_EAX)
+ {
+ x86_mov_reg_reg(inst, X86_EAX, cpu_reg, 4);
+ }
+ inst = jump_to_epilog(gen, inst, insn);
+ }
+
+JIT_OP_RETURN_LONG: spill_before
+ [] -> {
+ /* TODO: load the return value into EAX:EDX */
+ inst = jump_to_epilog(gen, inst, insn);
+ }
+
+JIT_OP_RETURN_FLOAT32: unary_branch, stack /*, only*/
+ [freg] -> {
+ inst = jump_to_epilog(gen, inst, insn);
+ }
+
+JIT_OP_RETURN_FLOAT64: unary_branch, stack /*, only*/
+ [freg] -> {
+ inst = jump_to_epilog(gen, inst, insn);
+ }
+
+JIT_OP_RETURN_NFLOAT: unary_branch, stack /*, only*/
+ [freg] -> {
+ inst = jump_to_epilog(gen, inst, insn);
+ }
+
+JIT_OP_RETURN_SMALL_STRUCT: spill_before
+ [] -> {
+ /* TODO: load the structure value into EAX:EDX */
+ inst = jump_to_epilog(gen, inst, insn);
+ }
+
+JIT_OP_SETUP_FOR_NESTED: spill_before
+ [] -> {
+ jit_nint nest_reg = jit_value_get_nint_constant(insn->value1);
+ if(nest_reg == -1)
+ {
+ x86_push_reg(inst, X86_EBP);
+ }
+ else
+ {
+ x86_mov_reg_reg(inst, _jit_reg_info[nest_reg].cpu_reg,
+ X86_EBP, sizeof(void *));
+ }
+ }
+
+JIT_OP_SETUP_FOR_SIBLING: spill_before
+ [] -> {
+ jit_nint level = jit_value_get_nint_constant(insn->value1);
+ jit_nint nest_reg = jit_value_get_nint_constant(insn->value2);
+ int cpu_reg;
+ if(nest_reg == -1)
+ {
+ cpu_reg = X86_EAX;
+ }
+ else
+ {
+ cpu_reg = _jit_reg_info[nest_reg].cpu_reg;
+ }
+ x86_mov_reg_membase(inst, cpu_reg, X86_EBP, 0, sizeof(void *));
+ while(level > 0)
+ {
+ gen->posn.ptr = inst;
+ if(!jit_cache_check_for_n(&(gen->posn), 16))
+ {
+ jit_cache_mark_full(&(gen->posn));
+ return;
+ }
+ x86_mov_reg_membase(inst, cpu_reg, cpu_reg, 0, sizeof(void *));
+ --level;
+ }
+ if(nest_reg == -1)
+ {
+ x86_push_reg(inst, cpu_reg);
+ }
+ }
+
+JIT_OP_IMPORT:
+ [] -> {
+ /* TODO */
+ }