From 3b318617df8f3b03a3b23bd5f29d5aa49ef7d9d8 Mon Sep 17 00:00:00 2001 From: Rhys Weatherley Date: Thu, 9 Sep 2004 03:07:11 +0000 Subject: [PATCH] Add some support for structure copying to the x86 back end. --- ChangeLog | 5 +++ jit/jit-rules-x86.c | 84 +++++++++++++++++++++++++++++++++++++++++++ jit/jit-rules-x86.sel | 48 +++++++++++++++++++------ 3 files changed, 127 insertions(+), 10 deletions(-) diff --git a/ChangeLog b/ChangeLog index edc2bfc..e86a900 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,4 +1,9 @@ +2004-09-09 Rhys Weatherley + + * jit/jit-rules-x86.c, jit/jit-rules-x86.sel: add some support + for structure copying to the x86 back end. + 2004-09-06 Rhys Weatherley * jit/jit-rules-interp.c: the pointer value for indirect and vtable diff --git a/jit/jit-rules-x86.c b/jit/jit-rules-x86.c index a814c66..b027446 100644 --- a/jit/jit-rules-x86.c +++ b/jit/jit-rules-x86.c @@ -1271,6 +1271,90 @@ static unsigned char *throw_builtin 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__); \ diff --git a/jit/jit-rules-x86.sel b/jit/jit-rules-x86.sel index 2ff235a..0a30084 100644 --- a/jit/jit-rules-x86.sel +++ b/jit/jit-rules-x86.sel @@ -1935,10 +1935,21 @@ JIT_OP_COPY_FLOAT64: unary, stack 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 @@ -2141,10 +2152,25 @@ JIT_OP_PUSH_NFLOAT: unary_note, stack 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; } @@ -2287,10 +2313,12 @@ JIT_OP_LOAD_RELATIVE_NFLOAT: manual 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 -- 2.47.3