From: Rhys Weatherley Date: Tue, 25 May 2004 05:13:22 +0000 (+0000) Subject: Selectors for branch instructions. X-Git-Tag: r.0.0.4~85 X-Git-Url: https://git.unchartedbackwaters.co.uk/w/?a=commitdiff_plain;h=d0673c90a317879617621f3232ed4ccf20b45b3e;p=francis%2Flibjit.git Selectors for branch instructions. --- diff --git a/ChangeLog b/ChangeLog index fdfbb2c..3b1db13 100644 --- 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 * include/jit/jit-insn.h, include/jit/jit-opcode.h, jit/jit-block.c, diff --git a/jit/jit-rules-x86.sel b/jit/jit-rules-x86.sel index e90e3ee..22e358a 100644 --- a/jit/jit-rules-x86.sel +++ b/jit/jit-rules-x86.sel @@ -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); diff --git a/tools/gen-sel-parser.y b/tools/gen-sel-parser.y index e0856ef..fbc78f5 100644 --- a/tools/gen-sel-parser.y +++ b/tools/gen-sel-parser.y @@ -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_BLOCK %type Options OptionList Option PatternElement %type Clauses Clause -%type Pattern +%type 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; } diff --git a/tools/gen-sel-scanner.l b/tools/gen-sel-scanner.l index 18bbcd6..9cfa20f 100644 --- a/tools/gen-sel-scanner.l +++ b/tools/gen-sel-scanner.l @@ -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); }