]> git.unchartedbackwaters.co.uk Git - francis/libjit.git/commitdiff
Selectors for branch instructions.
authorRhys Weatherley <rweather@southern-storm.com.au>
Tue, 25 May 2004 05:13:22 +0000 (05:13 +0000)
committerRhys Weatherley <rweather@southern-storm.com.au>
Tue, 25 May 2004 05:13:22 +0000 (05:13 +0000)
ChangeLog
jit/jit-rules-x86.sel
tools/gen-sel-parser.y
tools/gen-sel-scanner.l

index fdfbb2cb3b7e5a9bf476cd363b7d8f60bf45861e..3b1db139c30c6d4ff021e624952ec815783f445f 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -9,6 +9,9 @@
        jit/jit-rules-x86.sel, tools/gen-sel-parser.y: check in the
        initial instruction selector for x86 (incomplete).
 
+       * jit/jit-rules-x86.sel, tools/gen-sel-parser.y,
+       tools/gen-sel-scanner.l: selectors for branch instructions.
+
 2004-05-24  Rhys Weatherley  <rweather@southern-storm.com.au>
 
        * include/jit/jit-insn.h, include/jit/jit-opcode.h, jit/jit-block.c,
index e90e3ee0edb4b26fc926113f28d2521863365eb8..22e358ad99b93a2722c6a43cb1134c178ab2b024 100644 (file)
@@ -148,13 +148,180 @@ JIT_OP_ISHR_UN: binary
  * Branch opcodes.
  */
 
-/* TODO */
+JIT_OP_BR: spill_before
+       [] -> {
+               inst = output_branch(inst, 0xE9, insn);
+       }
+
+JIT_OP_BR_IFALSE: unary_branch
+       [reg] -> {
+               x86_alu_reg_reg(inst, X86_OR, $1, $1);
+               inst = output_branch(inst, 0x74 /* eq */, insn);
+       }
+
+JIT_OP_BR_ITRUE: unary_branch
+       [reg] -> {
+               x86_alu_reg_reg(inst, X86_OR, $1, $1);
+               inst = output_branch(inst, 0x75 /* ne */, insn);
+       }
+
+JIT_OP_BR_IEQ: binary_branch
+       [reg, immzero] -> {
+               x86_alu_reg_reg(inst, X86_OR, $1, $1);
+               inst = output_branch(inst, 0x74 /* eq */, insn);
+       }
+       [reg, imm] -> {
+               x86_alu_reg_imm(inst, X86_CMP, $1, $2);
+               inst = output_branch(inst, 0x74 /* eq */, insn);
+       }
+       [reg, local] -> {
+               x86_alu_reg_membase(inst, X86_CMP, $1, X86_EBP, $2);
+               inst = output_branch(inst, 0x74 /* eq */, insn);
+       }
+       [reg, reg] -> {
+               x86_alu_reg_reg(inst, X86_CMP, $1, $2);
+               inst = output_branch(inst, 0x74 /* eq */, insn);
+       }
+
+JIT_OP_BR_INE: binary_branch
+       [reg, immzero] -> {
+               x86_alu_reg_reg(inst, X86_OR, $1, $1);
+               inst = output_branch(inst, 0x75 /* ne */, insn);
+       }
+       [reg, imm] -> {
+               x86_alu_reg_imm(inst, X86_CMP, $1, $2);
+               inst = output_branch(inst, 0x75 /* ne */, insn);
+       }
+       [reg, local] -> {
+               x86_alu_reg_membase(inst, X86_CMP, $1, X86_EBP, $2);
+               inst = output_branch(inst, 0x75 /* ne */, insn);
+       }
+       [reg, reg] -> {
+               x86_alu_reg_reg(inst, X86_CMP, $1, $2);
+               inst = output_branch(inst, 0x75 /* ne */, insn);
+       }
+
+JIT_OP_BR_ILT: binary_branch
+       [reg, imm] -> {
+               x86_alu_reg_imm(inst, X86_CMP, $1, $2);
+               inst = output_branch(inst, 0x7C /* lt */, insn);
+       }
+       [reg, local] -> {
+               x86_alu_reg_membase(inst, X86_CMP, $1, X86_EBP, $2);
+               inst = output_branch(inst, 0x7C /* lt */, insn);
+       }
+       [reg, reg] -> {
+               x86_alu_reg_reg(inst, X86_CMP, $1, $2);
+               inst = output_branch(inst, 0x7C /* lt */, insn);
+       }
+
+JIT_OP_BR_ILT_UN: binary_branch
+       [reg, imm] -> {
+               x86_alu_reg_imm(inst, X86_CMP, $1, $2);
+               inst = output_branch(inst, 0x72 /* lt_un */, insn);
+       }
+       [reg, local] -> {
+               x86_alu_reg_membase(inst, X86_CMP, $1, X86_EBP, $2);
+               inst = output_branch(inst, 0x72 /* lt_un */, insn);
+       }
+       [reg, reg] -> {
+               x86_alu_reg_reg(inst, X86_CMP, $1, $2);
+               inst = output_branch(inst, 0x72 /* lt_un */, insn);
+       }
+
+JIT_OP_BR_ILE: binary_branch
+       [reg, imm] -> {
+               x86_alu_reg_imm(inst, X86_CMP, $1, $2);
+               inst = output_branch(inst, 0x7E /* le */, insn);
+       }
+       [reg, local] -> {
+               x86_alu_reg_membase(inst, X86_CMP, $1, X86_EBP, $2);
+               inst = output_branch(inst, 0x7E /* le */, insn);
+       }
+       [reg, reg] -> {
+               x86_alu_reg_reg(inst, X86_CMP, $1, $2);
+               inst = output_branch(inst, 0x7E /* le */, insn);
+       }
+
+JIT_OP_BR_ILE_UN: binary_branch
+       [reg, imm] -> {
+               x86_alu_reg_imm(inst, X86_CMP, $1, $2);
+               inst = output_branch(inst, 0x76 /* le_un */, insn);
+       }
+       [reg, local] -> {
+               x86_alu_reg_membase(inst, X86_CMP, $1, X86_EBP, $2);
+               inst = output_branch(inst, 0x76 /* le_un */, insn);
+       }
+       [reg, reg] -> {
+               x86_alu_reg_reg(inst, X86_CMP, $1, $2);
+               inst = output_branch(inst, 0x76 /* le_un */, insn);
+       }
+
+JIT_OP_BR_IGT: binary_branch
+       [reg, imm] -> {
+               x86_alu_reg_imm(inst, X86_CMP, $1, $2);
+               inst = output_branch(inst, 0x7F /* gt */, insn);
+       }
+       [reg, local] -> {
+               x86_alu_reg_membase(inst, X86_CMP, $1, X86_EBP, $2);
+               inst = output_branch(inst, 0x7F /* gt */, insn);
+       }
+       [reg, reg] -> {
+               x86_alu_reg_reg(inst, X86_CMP, $1, $2);
+               inst = output_branch(inst, 0x7F /* gt */, insn);
+       }
+
+JIT_OP_BR_IGT_UN: binary_branch
+       [reg, imm] -> {
+               x86_alu_reg_imm(inst, X86_CMP, $1, $2);
+               inst = output_branch(inst, 0x77 /* gt_un */, insn);
+       }
+       [reg, local] -> {
+               x86_alu_reg_membase(inst, X86_CMP, $1, X86_EBP, $2);
+               inst = output_branch(inst, 0x77 /* gt_un */, insn);
+       }
+       [reg, reg] -> {
+               x86_alu_reg_reg(inst, X86_CMP, $1, $2);
+               inst = output_branch(inst, 0x77 /* gt_un */, insn);
+       }
+
+JIT_OP_BR_IGE: binary_branch
+       [reg, imm] -> {
+               x86_alu_reg_imm(inst, X86_CMP, $1, $2);
+               inst = output_branch(inst, 0x7D /* ge */, insn);
+       }
+       [reg, local] -> {
+               x86_alu_reg_membase(inst, X86_CMP, $1, X86_EBP, $2);
+               inst = output_branch(inst, 0x7D /* ge */, insn);
+       }
+       [reg, reg] -> {
+               x86_alu_reg_reg(inst, X86_CMP, $1, $2);
+               inst = output_branch(inst, 0x7D /* ge */, insn);
+       }
+
+JIT_OP_BR_IGE_UN: binary_branch
+       [reg, imm] -> {
+               x86_alu_reg_imm(inst, X86_CMP, $1, $2);
+               inst = output_branch(inst, 0x73 /* ge_un */, insn);
+       }
+       [reg, local] -> {
+               x86_alu_reg_membase(inst, X86_CMP, $1, X86_EBP, $2);
+               inst = output_branch(inst, 0x73 /* ge_un */, insn);
+       }
+       [reg, reg] -> {
+               x86_alu_reg_reg(inst, X86_CMP, $1, $2);
+               inst = output_branch(inst, 0x73 /* ge_un */, insn);
+       }
 
 /*
  * Comparison opcodes.
  */
 
 JIT_OP_IEQ: binary
+       [reg, immzero] -> {
+               x86_alu_reg_reg(inst, X86_OR, $1, $1);
+               inst = setcc_reg(inst, $1, X86_CC_EQ, 0);
+       }
        [reg, imm] -> {
                x86_alu_reg_imm(inst, X86_CMP, $1, $2);
                inst = setcc_reg(inst, $1, X86_CC_EQ, 0);
@@ -169,6 +336,10 @@ JIT_OP_IEQ: binary
        }
 
 JIT_OP_INE: binary
+       [reg, immzero] -> {
+               x86_alu_reg_reg(inst, X86_OR, $1, $1);
+               inst = setcc_reg(inst, $1, X86_CC_NE, 0);
+       }
        [reg, imm] -> {
                x86_alu_reg_imm(inst, X86_CMP, $1, $2);
                inst = setcc_reg(inst, $1, X86_CC_NE, 0);
index e0856ef16ed44a061bd6f460a7f14964f24913ba..fbc78f5d33563a549914b88c68aff69ce0935a18 100644 (file)
@@ -73,6 +73,8 @@ static int gensel_first_stack_reg = 8;        /* st0 under x86 */
 #define        GENSEL_OPT_UNARY                                0x0004
 #define        GENSEL_OPT_TERNARY                              0x0008
 #define        GENSEL_OPT_STACK                                0x0010
+#define        GENSEL_OPT_UNARY_BRANCH                 0x0020
+#define        GENSEL_OPT_BINARY_BRANCH                0x0040
 
 /*
  * Pattern values.
@@ -82,11 +84,12 @@ static int gensel_first_stack_reg = 8;      /* st0 under x86 */
 #define        GENSEL_PATT_LREG                                2
 #define        GENSEL_PATT_FREG                                3
 #define        GENSEL_PATT_IMM                                 4
-#define        GENSEL_PATT_IMMS8                               5
-#define        GENSEL_PATT_IMMU8                               6
-#define        GENSEL_PATT_IMMS16                              7
-#define        GENSEL_PATT_IMMU16                              8
-#define        GENSEL_PATT_LOCAL                               9
+#define        GENSEL_PATT_IMMZERO                             5
+#define        GENSEL_PATT_IMMS8                               6
+#define        GENSEL_PATT_IMMU8                               7
+#define        GENSEL_PATT_IMMS16                              8
+#define        GENSEL_PATT_IMMU16                              9
+#define        GENSEL_PATT_LOCAL                               10
 
 /*
  * Information about clauses.
@@ -146,6 +149,8 @@ static void gensel_declare_regs(gensel_clause_t clauses, int options)
                                }
                                break;
 
+                               case GENSEL_PATT_IMMZERO: break;
+
                                case GENSEL_PATT_IMM:
                                case GENSEL_PATT_IMMS8:
                                case GENSEL_PATT_IMMU8:
@@ -231,6 +236,7 @@ static void gensel_output_clause(gensel_clause_t clause)
                                break;
 
                                case GENSEL_PATT_IMM:
+                               case GENSEL_PATT_IMMZERO:
                                case GENSEL_PATT_IMMS8:
                                case GENSEL_PATT_IMMU8:
                                case GENSEL_PATT_IMMS16:
@@ -309,7 +315,15 @@ static void gensel_output_clauses(gensel_clause_t clauses, int options)
                flag1 = "VALUE1";
                flag2 = "VALUE2";
                flag3 = "??";
-               destroy1 = 1;
+               if((options & (GENSEL_OPT_BINARY_BRANCH |
+                                          GENSEL_OPT_UNARY_BRANCH)) != 0)
+               {
+                       destroy1 = 0;
+               }
+               else
+               {
+                       destroy1 = 1;
+               }
                destroy2 = 0;
                destroy3 = 0;
        }
@@ -317,7 +331,8 @@ static void gensel_output_clauses(gensel_clause_t clauses, int options)
        /* If all of the clauses start with a register, then load the first
           value into a register before we start checking cases */
        check_index = 0;
-       if((options & (GENSEL_OPT_BINARY | GENSEL_OPT_UNARY)) != 0 &&
+       if((options & (GENSEL_OPT_BINARY | GENSEL_OPT_UNARY |
+                                  GENSEL_OPT_BINARY_BRANCH | GENSEL_OPT_UNARY_BRANCH)) != 0 &&
           (options & GENSEL_OPT_STACK) == 0)
        {
                clause = clauses;
@@ -333,7 +348,8 @@ static void gensel_output_clauses(gensel_clause_t clauses, int options)
                }
                if(!clause)
                {
-                       printf("\treg = _jit_regs_load_value(gen, %s, 1, ", arg1);
+                       printf("\treg = _jit_regs_load_value(gen, %s, %d, ",
+                                  arg1, destroy1);
                        printf("(insn->flags & (JIT_INSN_%s_NEXT_USE | "
                                                                   "JIT_INSN_%s_LIVE)));\n", flag1, flag1);
                        check_index = 1;
@@ -375,6 +391,13 @@ static void gensel_output_clauses(gensel_clause_t clauses, int options)
                                        }
                                        break;
 
+                                       case GENSEL_PATT_IMMZERO:
+                                       {
+                                               printf("%s->is_nint_constant && ", arg);
+                                               printf("%s->address == 0", arg);
+                                       }
+                                       break;
+
                                        case GENSEL_PATT_IMMS8:
                                        {
                                                printf("%s->is_nint_constant && ", arg);
@@ -467,6 +490,8 @@ static void gensel_output_clauses(gensel_clause_t clauses, int options)
                                        }
                                        break;
        
+                                       case GENSEL_PATT_IMMZERO: break;
+
                                        case GENSEL_PATT_IMM:
                                        case GENSEL_PATT_IMMS8:
                                        case GENSEL_PATT_IMMU8:
@@ -521,6 +546,12 @@ static void gensel_output_clauses(gensel_clause_t clauses, int options)
                                           gensel_first_stack_reg);
                        }
                }
+               if((options & (GENSEL_OPT_BINARY_BRANCH |
+                                          GENSEL_OPT_UNARY_BRANCH)) != 0)
+               {
+                       /* Spill all registers back to their original positions */
+                       printf("\t\t_jit_gen_spill_all(gen);\n");
+               }
                gensel_output_clause(clause);
                printf("\t}\n");
                first = 0;
@@ -599,6 +630,7 @@ static void gensel_output_supported(void)
 %token K_LREG                          "long register"
 %token K_FREG                          "float register"
 %token K_IMM                           "immediate value"
+%token K_IMMZERO                       "immediate zero value"
 %token K_IMMS8                         "immediate signed 8-bit value"
 %token K_IMMU8                         "immediate unsigned 8-bit value"
 %token K_IMMS16                                "immediate signed 16-bit value"
@@ -607,6 +639,8 @@ static void gensel_output_supported(void)
 %token K_SPILL_BEFORE          "`spill_before'"
 %token K_BINARY                                "`binary'"
 %token K_UNARY                         "`unary'"
+%token K_UNARY_BRANCH          "`unary_branch'"
+%token K_BINARY_BRANCH         "`binary_branch'"
 %token K_TERNARY                       "`ternary'"
 %token K_STACK                         "`stack'"
 %token K_INST_TYPE                     "`%inst_type'"
@@ -618,7 +652,7 @@ static void gensel_output_supported(void)
 %type <code>                           CODE_BLOCK
 %type <options>                                Options OptionList Option PatternElement
 %type <clauses>                                Clauses Clause
-%type <pattern>                                Pattern
+%type <pattern>                                Pattern Pattern2
 
 %expect 0
 
@@ -681,6 +715,8 @@ Option
        : K_SPILL_BEFORE                        { $$ = GENSEL_OPT_SPILL_BEFORE; }
        | K_BINARY                                      { $$ = GENSEL_OPT_BINARY; }
        | K_UNARY                                       { $$ = GENSEL_OPT_UNARY; }
+       | K_UNARY_BRANCH                        { $$ = GENSEL_OPT_UNARY_BRANCH; }
+       | K_BINARY_BRANCH                       { $$ = GENSEL_OPT_BINARY_BRANCH; }
        | K_TERNARY                                     { $$ = GENSEL_OPT_TERNARY; }
        | K_STACK                                       { $$ = GENSEL_OPT_STACK; }
        ;
@@ -717,12 +753,20 @@ Clause
        ;
 
 Pattern
+       : /* empty */           {
+                               $$.elem[0] = GENSEL_PATT_END;
+                               $$.size = 0;
+                       }
+       | Pattern2                      { $$ = $1; }
+       ;
+
+Pattern2
        : PatternElement                                {
                                $$.elem[0] = $1;
                                $$.elem[1] = GENSEL_PATT_END;
                                $$.size = 1;
                        }
-       | Pattern ',' PatternElement    {
+       | Pattern2 ',' PatternElement   {
                                $$.elem[$1.size] = $3;
                                $$.elem[$1.size + 1] = GENSEL_PATT_END;
                                $$.size = $1.size + 1;
@@ -734,6 +778,7 @@ PatternElement
        | K_LREG                                        { $$ = GENSEL_PATT_LREG; }
        | K_FREG                                        { $$ = GENSEL_PATT_FREG; }
        | K_IMM                                         { $$ = GENSEL_PATT_IMM; }
+       | K_IMMZERO                                     { $$ = GENSEL_PATT_IMMZERO; }
        | K_IMMS8                                       { $$ = GENSEL_PATT_IMMS8; }
        | K_IMMU8                                       { $$ = GENSEL_PATT_IMMU8; }
        | K_IMMS16                                      { $$ = GENSEL_PATT_IMMS16; }
index 18bbcd633b31650244d101830fb176c02774008b..9cfa20fcab0226f4709aa7f24325fe154f6098a9 100644 (file)
@@ -86,6 +86,7 @@ WHITE                                 [ \t\v\r\f]
 "lreg"                                 { RETURNTOK(K_LREG); }
 "freg"                                 { RETURNTOK(K_FREG); }
 "imm"                                  { RETURNTOK(K_IMM); }
+"immzero"                              { RETURNTOK(K_IMMZERO); }
 "imms8"                                        { RETURNTOK(K_IMMS8); }
 "immu8"                                        { RETURNTOK(K_IMMU8); }
 "imms16"                               { RETURNTOK(K_IMMS16); }
@@ -95,6 +96,8 @@ WHITE                                 [ \t\v\r\f]
 "binary"                               { RETURNTOK(K_BINARY); }
 "unary"                                        { RETURNTOK(K_UNARY); }
 "ternary"                              { RETURNTOK(K_TERNARY); }
+"unary_branch"                 { RETURNTOK(K_UNARY_BRANCH); }
+"binary_branch"                        { RETURNTOK(K_BINARY_BRANCH); }
 "stack"                                        { RETURNTOK(K_STACK); }
 "%inst_type"                   { RETURNTOK(K_INST_TYPE); }