return inst;
}
+/*
+ * Copy a block of memory that has a specific size. Other than
+ * the parameter pointers, all registers must be unused at this point.
+ */
+static unsigned char *memory_copy
+ (jit_gencode_t gen, unsigned char *inst, int dreg, jit_nint doffset,
+ int sreg, jit_nint soffset, jit_nuint size)
+{
+ int temp_reg = get_temp_reg(dreg, sreg, -1);
+ if(size <= 4 * sizeof(void *))
+ {
+ /* Use direct copies to copy the memory */
+ int offset = 0;
+ while(size >= sizeof(void *))
+ {
+ x86_mov_reg_membase(inst, temp_reg, sreg,
+ soffset + offset, sizeof(void *));
+ x86_mov_membase_reg(inst, dreg, doffset + offset,
+ temp_reg, sizeof(void *));
+ size -= sizeof(void *);
+ offset += sizeof(void *);
+ }
+ #ifdef JIT_NATIVE_INT64
+ if(size >= 4)
+ {
+ x86_mov_reg_membase(inst, temp_reg, sreg, soffset + offset, 4);
+ x86_mov_membase_reg(inst, dreg, doffset + offset, temp_reg, 4);
+ size -= 4;
+ offset += 4;
+ }
+ #endif
+ if(size >= 2)
+ {
+ x86_mov_reg_membase(inst, temp_reg, sreg, soffset + offset, 2);
+ x86_mov_membase_reg(inst, dreg, doffset + offset, temp_reg, 2);
+ size -= 2;
+ offset += 2;
+ }
+ if(size >= 1)
+ {
+ /* We assume that temp_reg is EAX, ECX, or EDX, which it
+ should be after calling "get_temp_reg" */
+ x86_mov_reg_membase(inst, temp_reg, sreg, soffset + offset, 1);
+ x86_mov_membase_reg(inst, dreg, doffset + offset, temp_reg, 1);
+ }
+ }
+ else
+ {
+ /* Call out to "jit_memcpy" to effect the copy */
+ x86_push_imm(inst, size);
+ if(soffset == 0)
+ {
+ x86_push_reg(inst, sreg);
+ }
+ else
+ {
+ x86_lea_membase(inst, temp_reg, sreg, soffset);
+ x86_push_reg(inst, temp_reg);
+ }
+ if(dreg != X86_ESP)
+ {
+ if(doffset == 0)
+ {
+ x86_push_reg(inst, dreg);
+ }
+ else
+ {
+ x86_lea_membase(inst, temp_reg, dreg, doffset);
+ x86_push_reg(inst, temp_reg);
+ }
+ }
+ else
+ {
+ /* Copying a structure value onto the stack */
+ x86_lea_membase(inst, temp_reg, X86_ESP,
+ doffset + 2 * sizeof(void *));
+ x86_push_reg(inst, temp_reg);
+ }
+ x86_call_code(inst, jit_memcpy);
+ x86_alu_reg_imm(inst, X86_ADD, X86_ESP, 3 * sizeof(void *));
+ }
+ return inst;
+}
+
#define TODO() \
do { \
fprintf(stderr, "TODO at %s, %d\n", __FILE__, (int)__LINE__); \
JIT_OP_COPY_NFLOAT: unary, stack
[freg] -> {}
-JIT_OP_COPY_STRUCT: manual
+JIT_OP_COPY_STRUCT: manual, spill_before
[] -> {
- /* TODO */
- TODO();
+ unsigned char *inst;
+ _jit_gen_fix_value(insn->dest);
+ _jit_gen_fix_value(insn->value1);
+ inst = gen->posn.ptr;
+ if(!jit_cache_check_for_n(&(gen->posn), 128))
+ {
+ jit_cache_mark_full(&(gen->posn));
+ return;
+ }
+ inst = memory_copy(gen, inst, X86_EBP, insn->dest->frame_offset,
+ X86_EBP, insn->value1->frame_offset,
+ jit_type_get_size(jit_value_get_type(insn->dest)));
+ gen->posn.ptr = inst;
}
JIT_OP_COPY_STORE_BYTE: manual
gen->stack_changed = 1;
}
-JIT_OP_PUSH_STRUCT: unary_note
+JIT_OP_PUSH_STRUCT: unary_branch, more_space
[reg] -> {
- /* TODO */
- TODO();
+ jit_nuint size;
+ size = (jit_nuint)jit_value_get_nint_constant(insn->value2);
+ if((size % sizeof(void *)) == 0 && size <= 4 * sizeof(void *))
+ {
+ /* Handle small structures that are a multiple of the word size */
+ while(size > 0)
+ {
+ size -= sizeof(void *);
+ x86_push_membase(inst, $1, size);
+ }
+ }
+ else
+ {
+ /* Handle arbitrary-sized structures */
+ x86_alu_reg_imm(inst, X86_SUB, X86_ESP, ROUND_STACK(size));
+ inst = memory_copy(gen, inst, X86_ESP, 0, $1, 0, size);
+ }
gen->stack_changed = 1;
}
gen->posn.ptr = inst;
}
-JIT_OP_LOAD_RELATIVE_STRUCT: manual
- [] -> {
- /* TODO */
- TODO();
+JIT_OP_LOAD_RELATIVE_STRUCT: unary_branch, more_space
+ [reg] -> {
+ _jit_gen_fix_value(insn->dest);
+ inst = memory_copy(gen, inst, X86_EBP, insn->dest->frame_offset,
+ $1, jit_value_get_nint_constant(insn->value2),
+ jit_type_get_size(jit_value_get_type(insn->dest)));
}
JIT_OP_STORE_RELATIVE_BYTE: manual