]> git.unchartedbackwaters.co.uk Git - francis/libjit.git/commitdiff
Continue the x86 back end; particularly byte/short stores.
authorRhys Weatherley <rweather@southern-storm.com.au>
Sat, 29 May 2004 09:44:51 +0000 (09:44 +0000)
committerRhys Weatherley <rweather@southern-storm.com.au>
Sat, 29 May 2004 09:44:51 +0000 (09:44 +0000)
ChangeLog
jit/jit-insn.c
jit/jit-reg-alloc.c
jit/jit-reg-alloc.h
jit/jit-rules-x86.c
jit/jit-rules-x86.sel

index 9de459f4f445704537582cb1763091a11f4e6146..20b4b767b717548a468d13671307dab8187e83b9 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,4 +1,10 @@
 
+2004-05-29  Rhys Weatherley  <rweather@southern-storm.com.au>
+
+       * jit/jit-insn.c, jit/jit-reg-alloc.c, jit/jit-reg-alloc.h,
+       jit/jit-rules-x86.c, jit/jit-rules-x86.sel: continue the
+       x86 back end; particularly byte/short stores.
+
 2004-05-27  Rhys Weatherley  <rweather@southern-storm.com.au>
 
        * tools/gen-apply.c: split "detect_struct_conventions" up a bit
index 457c609d64e9177085901378c9c843ff52374bd2..00b97a935310adf7c91c06c070b108bfb4f6f751 100644 (file)
@@ -5449,10 +5449,10 @@ jit_value_t jit_insn_call_intrinsic
        {
                const1 = jit_value_get_constant(arg1);
                const2 = jit_value_get_constant(arg2);
-               return_const.type = descriptor->ptr_result_type;
                if(return_value)
                {
                        jit_int result;
+                       return_const.type = descriptor->ptr_result_type;
                        temp_const.un.ptr_value = &return_const.un;
                        apply_args[0] = &temp_const.un;
                        apply_args[1] = &const1.un;
@@ -5468,6 +5468,7 @@ jit_value_t jit_insn_call_intrinsic
                }
                else
                {
+                       return_const.type = descriptor->return_type;
                        apply_args[0] = &const1.un;
                        apply_args[1] = &const2.un;
                        jit_apply(signature, intrinsic_func, apply_args,
index d3af23abe80fd7db6a31594dc32201f32fdd0169..2352484eeea4d41965132e0ae5de3d48b529e6c2 100644 (file)
@@ -551,7 +551,7 @@ static void free_reg_and_spill
 }
 
 /*@
- * @deftypefun void _jit_regs_want_reg (jit_gencode_t gen, int reg)
+ * @deftypefun void _jit_regs_want_reg (jit_gencode_t gen, int reg, int for_long)
  * Tell the register allocator that we want a particular register
  * for a specific purpose.  The current contents of the register
  * are spilled.  If @code{reg} is part of a register pair, then the
@@ -821,76 +821,22 @@ static void load_value(jit_gencode_t gen, int reg, int other_reg,
        }
 }
 
-/*@
- * @deftypefun int _jit_regs_load_value (jit_gencode_t gen, jit_value_t value, int destroy, int used_again)
- * Load a value into any register that is suitable and return that register.
- * If the value needs a long pair, then this will return the first register
- * in the pair.  Returns -1 if the value will not fit into any register.
- *
- * If @code{destroy} is non-zero, then we are about to destroy the register,
- * so the system must make sure that such destruction will not side-effect
- * @code{value} or any of the other values currently in that register.
- *
- * If @code{used_again} is non-zero, then it indicates that the value is
- * used again further down the block.
- * @end deftypefun
-@*/
-int _jit_regs_load_value
-       (jit_gencode_t gen, jit_value_t value, int destroy, int used_again)
+/*
+ * Find a free register to hold the contents of a value.
+ */
+static int free_register_for_value
+       (jit_gencode_t gen, jit_value_t value, int *other_reg)
 {
-       int reg, other_reg, type;
+       int reg, type;
        int suitable_reg, need_pair;
        int suitable_age;
 
+       /* Clear the other register before we start */
+       *other_reg = -1;
+
        /* Determine if we need a long pair for this value */
        need_pair = _jit_regs_needs_long_pair(value->type);
 
-       /* If the value is already in a register, then try to use that register */
-       if(value->in_register)
-       {
-               reg = value->reg;
-               if(destroy)
-               {
-                       if(gen->contents[reg].num_values == 1 &&
-                          (value->in_frame || !used_again))
-                       {
-                               /* We are the only value in this register, and the
-                                  value is duplicated in the frame, or will never
-                                  be used again in this block.  In this case,
-                                  we can disassociate the register from the value
-                                  and just return the register as-is */
-                               value->in_register = 0;
-                               gen->contents[reg].num_values = 0;
-                               gen->contents[reg].used_for_temp = 1;
-                               gen->contents[reg].age = gen->current_age;
-                               if(need_pair)
-                               {
-                                       other_reg = _jit_reg_info[reg].other_reg;
-                                       gen->contents[other_reg].used_for_temp = 1;
-                                       gen->contents[other_reg].age = gen->current_age;
-                               }
-                               ++(gen->current_age);
-                               return reg;
-                       }
-                       else
-                       {
-                               /* We need to spill the register and then reload it */
-                               spill_register(gen, reg);
-                       }
-               }
-               else
-               {
-                       gen->contents[reg].age = gen->current_age;
-                       if(need_pair)
-                       {
-                               other_reg = _jit_reg_info[reg].other_reg;
-                               gen->contents[other_reg].age = gen->current_age;
-                       }
-                       ++(gen->current_age);
-                       return reg;
-               }
-       }
-
        /* Determine the type of register that we need */
        switch(jit_type_normalize(value->type)->kind)
        {
@@ -943,7 +889,6 @@ int _jit_regs_load_value
                        {
                                /* We always load stack values to the top of the stack */
                                reg = create_stack_reg(gen, reg, 1);
-                               load_value(gen, reg, -1, value, destroy);
                                return reg;
                        }
                        else if(!need_pair)
@@ -951,19 +896,17 @@ int _jit_regs_load_value
                                if(gen->contents[reg].num_values == 0 &&
                                   !(gen->contents[reg].used_for_temp))
                                {
-                                       load_value(gen, reg, -1, value, destroy);
                                        return reg;
                                }
                        }
                        else
                        {
-                               other_reg = _jit_reg_info[reg].other_reg;
+                               *other_reg = _jit_reg_info[reg].other_reg;
                                if(gen->contents[reg].num_values == 0 &&
                                   !(gen->contents[reg].used_for_temp) &&
-                                  gen->contents[other_reg].num_values == 0 &&
-                                  !(gen->contents[other_reg].used_for_temp))
+                                  gen->contents[*other_reg].num_values == 0 &&
+                                  !(gen->contents[*other_reg].used_for_temp))
                                {
-                                       load_value(gen, reg, other_reg, value, destroy);
                                        return reg;
                                }
                        }
@@ -983,17 +926,114 @@ int _jit_regs_load_value
        }
 
        /* Eject the current contents of the register */
-       reg = _jit_regs_want_reg(gen, reg, need_pair);
+       reg = _jit_regs_want_reg(gen, suitable_reg, need_pair);
+       if(need_pair)
+       {
+               *other_reg = _jit_reg_info[reg].other_reg;
+       }
+       return reg;
+}
+
+/*@
+ * @deftypefun int _jit_regs_load_value (jit_gencode_t gen, jit_value_t value, int destroy, int used_again)
+ * Load a value into any register that is suitable and return that register.
+ * If the value needs a long pair, then this will return the first register
+ * in the pair.  Returns -1 if the value will not fit into any register.
+ *
+ * If @code{destroy} is non-zero, then we are about to destroy the register,
+ * so the system must make sure that such destruction will not side-effect
+ * @code{value} or any of the other values currently in that register.
+ *
+ * If @code{used_again} is non-zero, then it indicates that the value is
+ * used again further down the block.
+ * @end deftypefun
+@*/
+int _jit_regs_load_value
+       (jit_gencode_t gen, jit_value_t value, int destroy, int used_again)
+{
+       int reg, other_reg, need_pair;
 
-       /* Load the value into the register */
-       if(!need_pair)
+       /* Determine if we need a long pair for this value */
+       need_pair = _jit_regs_needs_long_pair(value->type);
+
+       /* If the value is already in a register, then try to use that register */
+       if(value->in_register)
        {
-               load_value(gen, reg, -1, value, destroy);
+               reg = value->reg;
+               if(destroy)
+               {
+                       if(gen->contents[reg].num_values == 1 &&
+                          (value->in_frame || !used_again))
+                       {
+                               /* We are the only value in this register, and the
+                                  value is duplicated in the frame, or will never
+                                  be used again in this block.  In this case,
+                                  we can disassociate the register from the value
+                                  and just return the register as-is */
+                               value->in_register = 0;
+                               gen->contents[reg].num_values = 0;
+                               gen->contents[reg].used_for_temp = 1;
+                               gen->contents[reg].age = gen->current_age;
+                               if(need_pair)
+                               {
+                                       other_reg = _jit_reg_info[reg].other_reg;
+                                       gen->contents[other_reg].used_for_temp = 1;
+                                       gen->contents[other_reg].age = gen->current_age;
+                               }
+                               ++(gen->current_age);
+                               return reg;
+                       }
+                       else
+                       {
+                               /* We need to spill the register and then reload it */
+                               spill_register(gen, reg);
+                       }
+               }
+               else
+               {
+                       gen->contents[reg].age = gen->current_age;
+                       if(need_pair)
+                       {
+                               other_reg = _jit_reg_info[reg].other_reg;
+                               gen->contents[other_reg].age = gen->current_age;
+                       }
+                       ++(gen->current_age);
+                       return reg;
+               }
        }
-       else
+
+       /* Search for a free register to hold the value */
+       reg = free_register_for_value(gen, value, &other_reg);
+       load_value(gen, reg, other_reg, value, destroy);
+       return reg;
+}
+
+/*@
+ * @deftypefun int _jit_regs_dest_value (jit_gencode_t gen, jit_value_t value)
+ * Get a new register to hold @code{value} as a destination.  This cannot
+ * be used for stack register destinations (use @code{_jit_regs_new_top}
+ * for that).
+ * @end deftypefun
+@*/
+int _jit_regs_dest_value(jit_gencode_t gen, jit_value_t value)
+{
+       int reg, other_reg;
+
+       /* If the value is exclusively in a register already, then use that */
+       if(value->in_register)
        {
-               load_value(gen, reg, _jit_reg_info[reg].other_reg, value, destroy);
+               reg = value->reg;
+               if(gen->contents[reg].num_values == 1)
+               {
+                       value->in_frame = 0;
+                       return reg;
+               }
+               free_reg_and_spill(gen, reg, 0, 1);
        }
+
+       /* Find a suitable register to hold the destination */
+       reg = free_register_for_value(gen, value, &other_reg);
+       _jit_regs_set_value(gen, reg, value, 0);
        return reg;
 }
 
@@ -1282,3 +1322,26 @@ int _jit_regs_new_top(jit_gencode_t gen, jit_value_t value, int type_reg)
        /* Return the allocated register to the caller */
        return reg;
 }
+
+/*@
+ * @deftypefun void _jit_regs_force_out (jit_gencode_t gen, jit_value_t value, int is_dest)
+ * If @code{value} is currently in a register, then force its value out
+ * into the stack frame.  The @code{is_dest} flag indicates that the value
+ * will be a destination, so we don't care about the original value.
+ * @end deftypefun
+@*/
+void _jit_regs_force_out(jit_gencode_t gen, jit_value_t value, int is_dest)
+{
+       if(value->in_register)
+       {
+               if((_jit_reg_info[value->reg].flags & JIT_REG_IN_STACK) == 0)
+               {
+                       free_reg_and_spill(gen, value->reg, 0, !is_dest);
+               }
+               else
+               {
+                       /* Always do a spill for a stack register */
+                       _jit_regs_want_reg(gen, value->reg, 0);
+               }
+       }
+}
index b78adcce33e06a6d9ef4bd52b5b675842313f98a..01a1c65137cc5f4061294aa392794fdc48c20f6b 100644 (file)
@@ -42,6 +42,7 @@ int _jit_regs_is_top_two
        (jit_gencode_t gen, jit_value_t value1, jit_value_t value2);
 int _jit_regs_load_value
        (jit_gencode_t gen, jit_value_t value, int destroy, int used_again);
+int _jit_regs_dest_value(jit_gencode_t gen, jit_value_t value);
 int _jit_regs_load_to_top
        (jit_gencode_t gen, jit_value_t value, int used_again, int type_reg);
 int _jit_regs_load_to_top_two
@@ -53,6 +54,7 @@ void _jit_regs_load_to_top_three
         int used_again3, int type_reg);
 int _jit_regs_num_used(jit_gencode_t gen, int type_reg);
 int _jit_regs_new_top(jit_gencode_t gen, jit_value_t value, int type_reg);
+void _jit_regs_force_out(jit_gencode_t gen, jit_value_t value, int is_dest);
 
 #ifdef __cplusplus
 };
index 62cb530802fb7f391c8d2495c6247dd14b4955c6..adb1574c6d5ef50b688b7e096272b04567381506 100644 (file)
@@ -26,6 +26,7 @@
 
 #include "jit-gen-x86.h"
 #include "jit-reg-alloc.h"
+#include <stdio.h>
 
 /*
  * Pseudo register numbers for the x86 registers.  These are not the
@@ -1400,6 +1401,11 @@ static unsigned char *mov_membase_reg_byte
        return inst;
 }
 
+#define        TODO()          \
+       do { \
+               fprintf(stderr, "TODO at %s, %d\n", __FILE__, (int)__LINE__); \
+       } while (0)
+
 void _jit_gen_insn(jit_gencode_t gen, jit_function_t func,
                                   jit_block_t block, jit_insn_t insn)
 {
@@ -1408,6 +1414,13 @@ void _jit_gen_insn(jit_gencode_t gen, jit_function_t func,
                #define JIT_INCLUDE_RULES
                #include "jit-rules-x86.slc"
                #undef JIT_INCLUDE_RULES
+
+               default:
+               {
+                       fprintf(stderr, "TODO(%x) at %s, %d\n",
+                                       (int)(insn->opcode), __FILE__, (int)__LINE__);
+               }
+               break;
        }
 }
 
index fa8fc6fd788e20147f0b6944a9ace831a5419d98..ad95ad2d5adc43db9b3038754baf18ad00f543b0 100644 (file)
@@ -548,6 +548,7 @@ JIT_OP_CHECK_NULL: unary_note
        [reg] -> {
                /* TODO: won't work in a function with a "try" block */
                unsigned char *patch;
+               TODO();
                x86_alu_reg_reg(inst, X86_OR, $1, $1);
                patch = inst;
                x86_branch8(inst, X86_CC_NE, 0, 0);
@@ -640,6 +641,7 @@ JIT_OP_RETURN_NFLOAT: unary_note, stack, only
 JIT_OP_RETURN_SMALL_STRUCT: spill_before
        [] -> {
                /* TODO: load the structure value into EAX:EDX */
+               TODO();
                inst = jump_to_epilog(gen, inst, block);
        }
 
@@ -691,6 +693,7 @@ JIT_OP_SETUP_FOR_SIBLING: spill_before
 JIT_OP_IMPORT:
        [] -> {
                /* TODO */
+               TODO();
        }
 
 /*
@@ -715,6 +718,7 @@ JIT_OP_COPY_INT: unary
 JIT_OP_COPY_LONG: spill_before
        [] -> {
                /* TODO */
+               TODO();
        }
 
 JIT_OP_COPY_FLOAT32: unary
@@ -726,25 +730,101 @@ JIT_OP_COPY_FLOAT64: unary
 JIT_OP_COPY_NFLOAT: unary
        [freg] -> {}
 
-JIT_OP_COPY_STRUCT:
+JIT_OP_COPY_STRUCT: manual
        [] -> {
                /* TODO */
+               TODO();
        }
 
-JIT_OP_COPY_STORE_BYTE:
+JIT_OP_COPY_STORE_BYTE: manual
        [] -> {
-               /* TODO */
+               unsigned char *inst;
+               int reg;
+               _jit_regs_force_out(gen, insn->dest, 1);
+               _jit_gen_fix_value(insn->dest);
+               if(!(insn->value1->is_constant))
+               {
+                       reg = _jit_regs_load_value
+                               (gen, insn->value1, 0,
+                                (insn->flags & (JIT_INSN_VALUE1_NEXT_USE |
+                                                                JIT_INSN_VALUE1_LIVE)));
+                       inst = gen->posn.ptr;
+                       if(!jit_cache_check_for_n(&(gen->posn), 32))
+                       {
+                               jit_cache_mark_full(&(gen->posn));
+                               return;
+                       }
+                       inst = mov_membase_reg_byte
+                               (inst, X86_EBP, insn->dest->frame_offset,
+                                _jit_reg_info[reg].cpu_reg);
+                       gen->posn.ptr = inst;
+               }
+               else
+               {
+                       inst = gen->posn.ptr;
+                       if(!jit_cache_check_for_n(&(gen->posn), 32))
+                       {
+                               jit_cache_mark_full(&(gen->posn));
+                               return;
+                       }
+                       x86_mov_membase_imm(inst, X86_EBP, insn->dest->frame_offset,
+                                                               insn->value1->address, 1);
+                       gen->posn.ptr = inst;
+               }
        }
 
-JIT_OP_COPY_STORE_SHORT:
+JIT_OP_COPY_STORE_SHORT: manual
        [] -> {
-               /* TODO */
+               unsigned char *inst;
+               int reg;
+               _jit_regs_force_out(gen, insn->dest, 1);
+               _jit_gen_fix_value(insn->dest);
+               if(!(insn->value1->is_constant))
+               {
+                       reg = _jit_regs_load_value
+                               (gen, insn->value1, 0,
+                                (insn->flags & (JIT_INSN_VALUE1_NEXT_USE |
+                                                                JIT_INSN_VALUE1_LIVE)));
+                       inst = gen->posn.ptr;
+                       if(!jit_cache_check_for_n(&(gen->posn), 32))
+                       {
+                               jit_cache_mark_full(&(gen->posn));
+                               return;
+                       }
+                       x86_mov_membase_reg(inst, X86_EBP, insn->dest->frame_offset,
+                                                               _jit_reg_info[reg].cpu_reg, 2);
+                       gen->posn.ptr = inst;
+               }
+               else
+               {
+                       inst = gen->posn.ptr;
+                       if(!jit_cache_check_for_n(&(gen->posn), 32))
+                       {
+                               jit_cache_mark_full(&(gen->posn));
+                               return;
+                       }
+                       x86_mov_membase_imm(inst, X86_EBP, insn->dest->frame_offset,
+                                                               insn->value1->address, 2);
+                       gen->posn.ptr = inst;
+               }
        }
 
-JIT_OP_ADDRESS_OF:
+JIT_OP_ADDRESS_OF: manual
        [] -> {
+               unsigned char *inst;
+               int reg;
+               _jit_regs_force_out(gen, insn->value1, 0);
                _jit_gen_fix_value(insn->value1);
-               /* TODO: get a register to hold the result */
+               inst = gen->posn.ptr;
+               if(!jit_cache_check_for_n(&(gen->posn), 32))
+               {
+                       jit_cache_mark_full(&(gen->posn));
+                       return;
+               }
+               reg = _jit_regs_dest_value(gen, insn->dest);
+               reg = _jit_reg_info[reg].cpu_reg;
+               x86_lea_membase(inst, reg, X86_EBP, insn->value1->frame_offset);
+               gen->posn.ptr = inst;
        }
 
 /*
@@ -838,6 +918,7 @@ JIT_OP_PUSH_NFLOAT: unary_note
 JIT_OP_PUSH_STRUCT: unary_note
        [reg] -> {
                /* TODO */
+               TODO();
        }
 
 JIT_OP_POP_STACK:
@@ -1037,6 +1118,7 @@ JIT_OP_LOAD_RELATIVE_NFLOAT: manual
 JIT_OP_LOAD_RELATIVE_STRUCT: manual
        [] -> {
                /* TODO */
+               TODO();
        }
 
 JIT_OP_STORE_RELATIVE_BYTE: manual
@@ -1339,6 +1421,7 @@ JIT_OP_STORE_RELATIVE_NFLOAT: manual
 JIT_OP_STORE_RELATIVE_STRUCT: manual
        [] -> {
                /* TODO */
+               TODO();
        }
 
 JIT_OP_ADD_RELATIVE: unary