]> git.unchartedbackwaters.co.uk Git - francis/libjit.git/commitdiff
Add some support for structure copying to the x86 back end.
authorRhys Weatherley <rweather@southern-storm.com.au>
Thu, 9 Sep 2004 03:07:11 +0000 (03:07 +0000)
committerRhys Weatherley <rweather@southern-storm.com.au>
Thu, 9 Sep 2004 03:07:11 +0000 (03:07 +0000)
ChangeLog
jit/jit-rules-x86.c
jit/jit-rules-x86.sel

index edc2bfcc2665afb784a93ace736ae817dbfe710b..e86a9004b88d5d13e51720e19ce3355b57e03283 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,4 +1,9 @@
 
+2004-09-09  Rhys Weatherley  <rweather@southern-storm.com.au>
+
+       * 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  <rweather@southern-storm.com.au>
 
        * jit/jit-rules-interp.c: the pointer value for indirect and vtable
index a814c66e982818d9a754347fb83451b9e59438bd..b027446a901acb7ca4f36c9e565b83b5fa17f0e6 100644 (file)
@@ -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__); \
index 2ff235ac6fabaec50cad0b534b15bf93b95e4aff..0a300848468a42043cb15f9ef5a4a0b6d6590f9c 100644 (file)
@@ -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