]> git.unchartedbackwaters.co.uk Git - francis/libjit.git/commitdiff
Relative loads and stores for x86.
authorRhys Weatherley <rweather@southern-storm.com.au>
Thu, 27 May 2004 04:36:30 +0000 (04:36 +0000)
committerRhys Weatherley <rweather@southern-storm.com.au>
Thu, 27 May 2004 04:36:30 +0000 (04:36 +0000)
ChangeLog
jit/jit-rules-x86.c
jit/jit-rules-x86.sel
tools/gen-sel-parser.y
tools/gen-sel-scanner.l

index 5a8147e2884716911bb719c77917c3c92b7a479d..9de459f4f445704537582cb1763091a11f4e6146 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -10,6 +10,9 @@
        "nfloat" as identical on platforms whose "long double" type is
        the same as "double".
 
+       * jit/jit-rules-x86.c, jit/jit-rules-x86.sel, tools/gen-sel-parser.y,
+       tools/gen-sel-scanner.l: relative loads and stores for x86.
+
 2004-05-26  Rhys Weatherley  <rweather@southern-storm.com.au>
 
        * jit/jit-insn.c, jit/jit-rules-x86.c, jit/jit-rules-x86.sel,
index 81d549c35518b64671dd10f811d660f05f67f8ec..62cb530802fb7f391c8d2495c6247dd14b4955c6 100644 (file)
@@ -1326,6 +1326,80 @@ static unsigned char *jump_to_epilog
        return inst;
 }
 
+/*
+ * Get a register pair for temporary operations on "long" values.
+ */
+static void get_reg_pair(jit_gencode_t gen, int not_this1, int not_this2,
+                                                int not_this3, int *reg, int *reg2)
+{
+       int index;
+       for(index = 0; index < 8; ++index)
+       {
+               if((_jit_reg_info[index].flags & JIT_REG_WORD) == 0 ||
+                  jit_reg_is_used(gen->permanent, index))
+               {
+                       continue;
+               }
+               if(index != not_this1 && index != not_this2 &&
+                  index != not_this3)
+               {
+                       break;
+               }
+       }
+       *reg = index;
+       _jit_regs_want_reg(gen, index, 0);
+       for(; index < 8; ++index)
+       {
+               if((_jit_reg_info[index].flags & JIT_REG_WORD) == 0 ||
+                  jit_reg_is_used(gen->permanent, index))
+               {
+                       continue;
+               }
+               if(index != not_this1 && index != not_this2 &&
+                  index != not_this3 && index != *reg)
+               {
+                       break;
+               }
+       }
+       if(index >= 8)
+       {
+               *reg2 = -1;
+       }
+       else
+       {
+               *reg2 = index;
+               _jit_regs_want_reg(gen, index, 0);
+       }
+}
+
+/*
+ * Store a byte value to a membase address.
+ */
+static unsigned char *mov_membase_reg_byte
+                       (unsigned char *inst, int basereg, int offset, int srcreg)
+{
+       if(srcreg == X86_EAX || srcreg == X86_EBX ||
+          srcreg == X86_ECX || srcreg == X86_EDX)
+       {
+               x86_mov_membase_reg(inst, basereg, offset, srcreg, 1);
+       }
+       else if(basereg != X86_EAX)
+       {
+               x86_push_reg(inst, X86_EAX);
+               x86_mov_reg_reg(inst, X86_EAX, srcreg, 4);
+               x86_mov_membase_reg(inst, basereg, offset, X86_EAX, 1);
+               x86_pop_reg(inst, X86_EAX);
+       }
+       else
+       {
+               x86_push_reg(inst, X86_EDX);
+               x86_mov_reg_reg(inst, X86_EDX, srcreg, 4);
+               x86_mov_membase_reg(inst, basereg, offset, X86_EDX, 1);
+               x86_pop_reg(inst, X86_EDX);
+       }
+       return inst;
+}
+
 void _jit_gen_insn(jit_gencode_t gen, jit_function_t func,
                                   jit_block_t block, jit_insn_t insn)
 {
index ddd8eab8fec76e6f2fbeb5dc2f3de1d24acd87f6..fa8fc6fd788e20147f0b6944a9ace831a5419d98 100644 (file)
@@ -911,3 +911,440 @@ JIT_OP_FLUSH_SMALL_STRUCT:
                        break;
                }
        }
+
+/*
+ * Pointer-relative loads and stores.
+ */
+
+JIT_OP_LOAD_RELATIVE_SBYTE: unary
+       [reg] -> {
+               x86_widen_membase(inst, $1, $1, insn->value2->address, 1, 0);
+       }
+
+JIT_OP_LOAD_RELATIVE_UBYTE: unary
+       [reg] -> {
+               x86_widen_membase(inst, $1, $1, insn->value2->address, 0, 0);
+       }
+
+JIT_OP_LOAD_RELATIVE_SHORT: unary
+       [reg] -> {
+               x86_widen_membase(inst, $1, $1, insn->value2->address, 1, 1);
+       }
+
+JIT_OP_LOAD_RELATIVE_USHORT: unary
+       [reg] -> {
+               x86_widen_membase(inst, $1, $1, insn->value2->address, 0, 1);
+       }
+
+JIT_OP_LOAD_RELATIVE_INT: unary
+       [reg] -> {
+               x86_mov_reg_membase(inst, $1, $1, insn->value2->address, 4);
+       }
+
+JIT_OP_LOAD_RELATIVE_LONG: manual
+       [] -> {
+               unsigned char *inst;
+               int reg = _jit_regs_load_value
+                       (gen, insn->value1, 0,
+                        (insn->flags & (JIT_INSN_VALUE1_NEXT_USE |
+                                                        JIT_INSN_VALUE1_LIVE)));
+               int reg2, reg3;
+               int frame_offset;
+               _jit_gen_fix_value(insn->dest);
+               get_reg_pair(gen, reg, -1, -1, &reg2, &reg3);
+               reg  = _jit_reg_info[reg].cpu_reg;
+               reg2 = _jit_reg_info[reg2].cpu_reg;
+               reg3 = _jit_reg_info[reg3].cpu_reg;
+               frame_offset = insn->dest->frame_offset;
+               inst = gen->posn.ptr;
+               if(!jit_cache_check_for_n(&(gen->posn), 32))
+               {
+                       jit_cache_mark_full(&(gen->posn));
+                       return;
+               }
+               x86_mov_reg_membase(inst, reg2, reg, insn->value2->address, 4);
+               x86_mov_reg_membase(inst, reg3, reg, insn->value2->address + 4, 4);
+               x86_mov_membase_reg(inst, X86_EBP, frame_offset, reg2, 4);
+               x86_mov_membase_reg(inst, X86_EBP, frame_offset + 4, reg3, 4);
+               insn->dest->in_frame = 1;
+               gen->posn.ptr = inst;
+       }
+
+JIT_OP_LOAD_RELATIVE_FLOAT32: manual
+       [] -> {
+               unsigned char *inst;
+               int reg = _jit_regs_load_value
+                       (gen, insn->value1, 0,
+                        (insn->flags & (JIT_INSN_VALUE1_NEXT_USE |
+                                                        JIT_INSN_VALUE1_LIVE)));
+               _jit_regs_new_top(gen, insn->dest, 8);
+               inst = gen->posn.ptr;
+               if(!jit_cache_check_for_n(&(gen->posn), 32))
+               {
+                       jit_cache_mark_full(&(gen->posn));
+                       return;
+               }
+               reg = _jit_reg_info[reg].cpu_reg;
+               x86_fld_membase(inst, reg, insn->value2->address, 0);
+               gen->posn.ptr = inst;
+       }
+
+JIT_OP_LOAD_RELATIVE_FLOAT64: manual
+       [] -> {
+               unsigned char *inst;
+               int reg = _jit_regs_load_value
+                       (gen, insn->value1, 0,
+                        (insn->flags & (JIT_INSN_VALUE1_NEXT_USE |
+                                                        JIT_INSN_VALUE1_LIVE)));
+               _jit_regs_new_top(gen, insn->dest, 8);
+               inst = gen->posn.ptr;
+               if(!jit_cache_check_for_n(&(gen->posn), 32))
+               {
+                       jit_cache_mark_full(&(gen->posn));
+                       return;
+               }
+               reg = _jit_reg_info[reg].cpu_reg;
+               x86_fld_membase(inst, reg, insn->value2->address, 1);
+               gen->posn.ptr = inst;
+       }
+
+JIT_OP_LOAD_RELATIVE_NFLOAT: manual
+       [] -> {
+               unsigned char *inst;
+               int reg = _jit_regs_load_value
+                       (gen, insn->value1, 0,
+                        (insn->flags & (JIT_INSN_VALUE1_NEXT_USE |
+                                                        JIT_INSN_VALUE1_LIVE)));
+               _jit_regs_new_top(gen, insn->dest, 8);
+               inst = gen->posn.ptr;
+               if(!jit_cache_check_for_n(&(gen->posn), 32))
+               {
+                       jit_cache_mark_full(&(gen->posn));
+                       return;
+               }
+               reg = _jit_reg_info[reg].cpu_reg;
+               if(sizeof(jit_nfloat) != sizeof(jit_float64))
+               {
+                       x86_fld80_membase(inst, reg, insn->value2->address);
+               }
+               else
+               {
+                       x86_fld_membase(inst, reg, insn->value2->address, 1);
+               }
+               gen->posn.ptr = inst;
+       }
+
+JIT_OP_LOAD_RELATIVE_STRUCT: manual
+       [] -> {
+               /* TODO */
+       }
+
+JIT_OP_STORE_RELATIVE_BYTE: manual
+       [] -> {
+               unsigned char *inst;
+               int reg = _jit_regs_load_value
+                       (gen, insn->dest, 0,
+                        (insn->flags & (JIT_INSN_DEST_NEXT_USE |
+                                                        JIT_INSN_DEST_LIVE)));
+               if(!(insn->value1->is_constant))
+               {
+                       int reg2 = _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;
+                       }
+                       reg  = _jit_reg_info[reg].cpu_reg;
+                       reg2 = _jit_reg_info[reg2].cpu_reg;
+                       inst = mov_membase_reg_byte
+                               (inst, reg, insn->value2->address, reg2);
+                       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;
+                       }
+                       reg = _jit_reg_info[reg].cpu_reg;
+                       x86_mov_membase_imm(inst, reg, insn->value2->address,
+                                                               insn->value1->address, 1);
+                       gen->posn.ptr = inst;
+               }
+       }
+
+JIT_OP_STORE_RELATIVE_SHORT: manual
+       [] -> {
+               unsigned char *inst;
+               int reg = _jit_regs_load_value
+                       (gen, insn->dest, 0,
+                        (insn->flags & (JIT_INSN_DEST_NEXT_USE |
+                                                        JIT_INSN_DEST_LIVE)));
+               if(!(insn->value1->is_constant))
+               {
+                       int reg2 = _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;
+                       }
+                       reg  = _jit_reg_info[reg].cpu_reg;
+                       reg2 = _jit_reg_info[reg2].cpu_reg;
+                       x86_mov_membase_reg(inst, reg, insn->value2->address, reg2, 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;
+                       }
+                       reg = _jit_reg_info[reg].cpu_reg;
+                       x86_mov_membase_imm(inst, reg, insn->value2->address,
+                                                               insn->value1->address, 2);
+                       gen->posn.ptr = inst;
+               }
+       }
+
+JIT_OP_STORE_RELATIVE_INT: manual
+       [] -> {
+               unsigned char *inst;
+               int reg = _jit_regs_load_value
+                       (gen, insn->dest, 0,
+                        (insn->flags & (JIT_INSN_DEST_NEXT_USE |
+                                                        JIT_INSN_DEST_LIVE)));
+               if(!(insn->value1->is_constant))
+               {
+                       int reg2 = _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;
+                       }
+                       reg  = _jit_reg_info[reg].cpu_reg;
+                       reg2 = _jit_reg_info[reg2].cpu_reg;
+                       x86_mov_membase_reg(inst, reg, insn->value2->address, reg2, 4);
+                       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;
+                       }
+                       reg = _jit_reg_info[reg].cpu_reg;
+                       x86_mov_membase_imm(inst, reg, insn->value2->address,
+                                                               insn->value1->address, 4);
+                       gen->posn.ptr = inst;
+               }
+       }
+
+JIT_OP_STORE_RELATIVE_LONG: manual
+       [] -> {
+               unsigned char *inst;
+               int reg = _jit_regs_load_value
+                       (gen, insn->dest, 0,
+                        (insn->flags & (JIT_INSN_DEST_NEXT_USE |
+                                                        JIT_INSN_DEST_LIVE)));
+               int reg2, reg3;
+               int frame_offset;
+               if(!(insn->value1->is_constant))
+               {
+                       get_reg_pair(gen, reg, -1, -1, &reg2, &reg3);
+                       _jit_gen_fix_value(insn->value1);
+                       inst = gen->posn.ptr;
+                       if(!jit_cache_check_for_n(&(gen->posn), 32))
+                       {
+                               jit_cache_mark_full(&(gen->posn));
+                               return;
+                       }
+                       reg  = _jit_reg_info[reg].cpu_reg;
+                       reg2 = _jit_reg_info[reg2].cpu_reg;
+                       reg3 = _jit_reg_info[reg3].cpu_reg;
+                       frame_offset = insn->value1->frame_offset;
+                       x86_mov_reg_membase(inst, reg2, X86_EBP, frame_offset, 4);
+                       x86_mov_reg_membase(inst, reg3, X86_EBP, frame_offset + 4, 4);
+                       x86_mov_membase_reg(inst, reg, insn->value2->address, reg2, 4);
+                       x86_mov_membase_reg(inst, reg, insn->value2->address + 4, reg3, 4);
+                       gen->posn.ptr = inst;
+               }
+               else
+               {
+                       jit_long const_value = jit_value_get_long_constant(insn->value1);
+                       inst = gen->posn.ptr;
+                       if(!jit_cache_check_for_n(&(gen->posn), 32))
+                       {
+                               jit_cache_mark_full(&(gen->posn));
+                               return;
+                       }
+                       reg = _jit_reg_info[reg].cpu_reg;
+                       x86_mov_membase_imm
+                               (inst, reg, insn->value2->address,
+                                (jit_int)(const_value & jit_max_uint), 4);
+                       x86_mov_membase_imm
+                               (inst, reg, insn->value2->address,
+                                (jit_int)((const_value >> 32) & jit_max_uint), 4);
+                       gen->posn.ptr = inst;
+               }
+       }
+
+JIT_OP_STORE_RELATIVE_FLOAT32: manual
+       [] -> {
+               unsigned char *inst;
+               int reg = _jit_regs_load_value
+                       (gen, insn->dest, 0,
+                        (insn->flags & (JIT_INSN_DEST_NEXT_USE |
+                                                        JIT_INSN_DEST_LIVE)));
+               if(!(insn->value1->is_constant))
+               {
+                       _jit_regs_load_to_top
+                               (gen, insn->value1,
+                                (insn->flags & (JIT_INSN_VALUE1_NEXT_USE |
+                                                                JIT_INSN_VALUE1_LIVE)), 8);
+                       inst = gen->posn.ptr;
+                       if(!jit_cache_check_for_n(&(gen->posn), 32))
+                       {
+                               jit_cache_mark_full(&(gen->posn));
+                               return;
+                       }
+                       reg = _jit_reg_info[reg].cpu_reg;
+                       x86_fst_membase(inst, reg, insn->value2->address, 0, 1);
+                       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;
+                       }
+                       reg = _jit_reg_info[reg].cpu_reg;
+                       x86_mov_membase_imm(inst, reg, insn->value2->address,
+                                                               *((int *)(insn->value1->address)), 4);
+                       gen->posn.ptr = inst;
+               }
+       }
+
+JIT_OP_STORE_RELATIVE_FLOAT64: manual
+       [] -> {
+               unsigned char *inst;
+               int reg = _jit_regs_load_value
+                       (gen, insn->dest, 0,
+                        (insn->flags & (JIT_INSN_DEST_NEXT_USE |
+                                                        JIT_INSN_DEST_LIVE)));
+               if(!(insn->value1->is_constant))
+               {
+                       _jit_regs_load_to_top
+                               (gen, insn->value1,
+                                (insn->flags & (JIT_INSN_VALUE1_NEXT_USE |
+                                                                JIT_INSN_VALUE1_LIVE)), 8);
+                       inst = gen->posn.ptr;
+                       if(!jit_cache_check_for_n(&(gen->posn), 32))
+                       {
+                               jit_cache_mark_full(&(gen->posn));
+                               return;
+                       }
+                       reg = _jit_reg_info[reg].cpu_reg;
+                       x86_fst_membase(inst, reg, insn->value2->address, 1, 1);
+                       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;
+                       }
+                       reg = _jit_reg_info[reg].cpu_reg;
+                       x86_mov_membase_imm(inst, reg, insn->value2->address,
+                                                               ((int *)(insn->value1->address))[0], 4);
+                       x86_mov_membase_imm(inst, reg, insn->value2->address + 4,
+                                                               ((int *)(insn->value1->address))[1], 4);
+                       gen->posn.ptr = inst;
+               }
+       }
+
+JIT_OP_STORE_RELATIVE_NFLOAT: manual
+       [] -> {
+               unsigned char *inst;
+               int reg = _jit_regs_load_value
+                       (gen, insn->dest, 0,
+                        (insn->flags & (JIT_INSN_DEST_NEXT_USE |
+                                                        JIT_INSN_DEST_LIVE)));
+               if(!(insn->value1->is_constant))
+               {
+                       _jit_regs_load_to_top
+                               (gen, insn->value1,
+                                (insn->flags & (JIT_INSN_VALUE1_NEXT_USE |
+                                                                JIT_INSN_VALUE1_LIVE)), 8);
+                       inst = gen->posn.ptr;
+                       if(!jit_cache_check_for_n(&(gen->posn), 32))
+                       {
+                               jit_cache_mark_full(&(gen->posn));
+                               return;
+                       }
+                       reg = _jit_reg_info[reg].cpu_reg;
+                       if(sizeof(jit_nfloat) != sizeof(jit_float64))
+                       {
+                               x86_fst80_membase(inst, reg, insn->value2->address);
+                       }
+                       else
+                       {
+                               x86_fst_membase(inst, reg, insn->value2->address, 1, 1);
+                       }
+                       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;
+                       }
+                       reg = _jit_reg_info[reg].cpu_reg;
+                       x86_mov_membase_imm(inst, reg, insn->value2->address,
+                                                               ((int *)(insn->value1->address))[0], 4);
+                       x86_mov_membase_imm(inst, reg, insn->value2->address + 4,
+                                                               ((int *)(insn->value1->address))[1], 4);
+                       if(sizeof(jit_nfloat) != sizeof(jit_float64))
+                       {
+                               x86_mov_membase_imm(inst, reg, insn->value2->address + 8,
+                                                                       ((int *)(insn->value1->address))[2], 4);
+                       }
+                       gen->posn.ptr = inst;
+               }
+       }
+
+JIT_OP_STORE_RELATIVE_STRUCT: manual
+       [] -> {
+               /* TODO */
+       }
+
+JIT_OP_ADD_RELATIVE: unary
+       [reg] -> {
+               if(insn->value2->address != 0)
+               {
+                       x86_alu_reg_imm(inst, X86_ADD, $1, insn->value2->address);
+               }
+       }
index 368e102434e95dc1ebce9d7db278cf13526a7abc..b6ac6fe46dab39eb706ee69e0af39878e33a6139 100644 (file)
@@ -76,6 +76,7 @@ static int gensel_first_stack_reg = 8;        /* st0 under x86 */
 #define        GENSEL_OPT_UNARY_BRANCH                 0x0020
 #define        GENSEL_OPT_BINARY_BRANCH                0x0040
 #define        GENSEL_OPT_ONLY                                 0x0080
+#define        GENSEL_OPT_MANUAL                               0x0100
 
 /*
  * Pattern values.
@@ -194,22 +195,13 @@ static void gensel_declare_regs(gensel_clause_t clauses, int options)
 }
 
 /*
- * Output a single clause for a rule.
+ * Output the code within a clause.
  */
-static void gensel_output_clause(gensel_clause_t clause)
+static void gensel_output_clause_code(gensel_clause_t clause)
 {
        char *code;
        int index;
 
-       /* Cache the instruction pointer into "inst" */
-       printf("\t\tinst = (%s)(gen->posn.ptr);\n", gensel_inst_type);
-       printf("\t\tif(!jit_cache_check_for_n(&(gen->posn), %d))\n",
-                  gensel_reserve_space);
-       printf("\t\t{\n");
-       printf("\t\t\tjit_cache_mark_full(&(gen->posn));\n");
-       printf("\t\t\treturn;\n");
-       printf("\t\t}\n");
-
        /* Output the line number information from the original file */
        printf("#line %ld \"%s\"\n", clause->linenum, clause->filename);
 
@@ -268,6 +260,24 @@ static void gensel_output_clause(gensel_clause_t clause)
                }
        }
        printf("\n");
+}
+
+/*
+ * Output a single clause for a rule.
+ */
+static void gensel_output_clause(gensel_clause_t clause)
+{
+       /* Cache the instruction pointer into "inst" */
+       printf("\t\tinst = (%s)(gen->posn.ptr);\n", gensel_inst_type);
+       printf("\t\tif(!jit_cache_check_for_n(&(gen->posn), %d))\n",
+                  gensel_reserve_space);
+       printf("\t\t{\n");
+       printf("\t\t\tjit_cache_mark_full(&(gen->posn));\n");
+       printf("\t\t\treturn;\n");
+       printf("\t\t}\n");
+
+       /* Output the clause code */
+       gensel_output_clause_code(clause);
 
        /* Copy "inst" back into the generation context */
        printf("\t\tgen->posn.ptr = (unsigned char *)inst;\n");
@@ -295,6 +305,13 @@ static void gensel_output_clauses(gensel_clause_t clauses, int options)
        int first, index;
        int check_index;
 
+       /* If the clause is manual, then output it as-is */
+       if((options & GENSEL_OPT_MANUAL) != 0)
+       {
+               gensel_output_clause_code(clauses);
+               return;
+       }
+
        /* Determine the location of this instruction's arguments */
        if((options & GENSEL_OPT_TERNARY) != 0)
        {
@@ -656,6 +673,7 @@ static void gensel_output_supported(void)
 %token K_TERNARY                       "`ternary'"
 %token K_STACK                         "`stack'"
 %token K_ONLY                          "`only'"
+%token K_MANUAL                                "`manual'"
 %token K_INST_TYPE                     "`%inst_type'"
 
 /*
@@ -685,7 +703,10 @@ Rules
 Rule
        : IDENTIFIER ':' Options Clauses {
                                printf("case %s:\n{\n", $1);
-                               printf("\t%s inst;\n", gensel_inst_type);
+                               if(($3 & GENSEL_OPT_MANUAL) == 0)
+                               {
+                                       printf("\t%s inst;\n", gensel_inst_type);
+                               }
                                gensel_declare_regs($4.head, $3);
                                if(($3 & GENSEL_OPT_SPILL_BEFORE) != 0)
                                {
@@ -733,6 +754,7 @@ Option
        | K_TERNARY                                     { $$ = GENSEL_OPT_TERNARY; }
        | K_STACK                                       { $$ = GENSEL_OPT_STACK; }
        | K_ONLY                                        { $$ = GENSEL_OPT_ONLY; }
+       | K_MANUAL                                      { $$ = GENSEL_OPT_MANUAL; }
        ;
 
 Clauses
index 69a7df5003de4682a4b6a1a9fbcd78cdbd5f5797..51a793458f6d33cd1fdd543a1a86398988f0fe20 100644 (file)
@@ -100,6 +100,7 @@ WHITE                                       [ \t\v\r\f]
 "binary_branch"                        { RETURNTOK(K_BINARY_BRANCH); }
 "unary_note"                   { RETURNTOK(K_UNARY_BRANCH); }
 "binary_note"                  { RETURNTOK(K_BINARY_BRANCH); }
+"manual"                               { RETURNTOK(K_MANUAL); }
 "stack"                                        { RETURNTOK(K_STACK); }
 "only"                                 { RETURNTOK(K_ONLY); }
 "%inst_type"                   { RETURNTOK(K_INST_TYPE); }