From 164eeca3c99aa69abfd7321c2d24f177af97b0f1 Mon Sep 17 00:00:00 2001 From: Rhys Weatherley Date: Wed, 26 May 2004 03:47:38 +0000 Subject: [PATCH] More selection cases for the x86 back end. --- ChangeLog | 3 + jit/jit-rules-x86.c | 9 +- jit/jit-rules-x86.sel | 300 +++++++++++++++++++++++++++++++++++++--- tools/gen-sel-parser.y | 18 ++- tools/gen-sel-scanner.l | 3 + 5 files changed, 309 insertions(+), 24 deletions(-) diff --git a/ChangeLog b/ChangeLog index f3b4dc5..d808343 100644 --- a/ChangeLog +++ b/ChangeLog @@ -17,6 +17,9 @@ testing if the last block is reachable or not, taking empty trailing blocks into account. + * jit/jit-rules-x86.c, jit/jit-rules-x86.sel, tools/gen-sel-parser.y, + tools/gen-sel-scanner.l: more selection cases for the x86 back end. + 2004-05-25 Rhys Weatherley * tools/.cvsignore, tools/Makefile.am, tools/gen-sel-parser.y, diff --git a/jit/jit-rules-x86.c b/jit/jit-rules-x86.c index 8a33790..81d549c 100644 --- a/jit/jit-rules-x86.c +++ b/jit/jit-rules-x86.c @@ -1045,7 +1045,14 @@ void _jit_gen_load_value } ptr = _jit_cache_alloc(&(gen->posn), sizeof(jit_nfloat)); jit_memcpy(ptr, &nfloat_value, sizeof(nfloat_value)); - x86_fld80_mem(inst, ptr); + if(sizeof(jit_nfloat) != sizeof(jit_float64)) + { + x86_fld80_mem(inst, ptr); + } + else + { + x86_fld(inst, ptr, 1); + } } break; } diff --git a/jit/jit-rules-x86.sel b/jit/jit-rules-x86.sel index bf62140..ddd8eab 100644 --- a/jit/jit-rules-x86.sel +++ b/jit/jit-rules-x86.sel @@ -78,6 +78,81 @@ JIT_OP_INEG: unary x86_neg_reg(inst, $1); } +JIT_OP_FADD: binary, stack + [freg, freg] -> { + x86_fp_op_reg(inst, X86_FADD, 1, 1); + } + +JIT_OP_FSUB: binary, stack + [freg, freg] -> { + x86_fp_op_reg(inst, X86_FSUB, 1, 1); + } + +JIT_OP_FMUL: binary, stack + [freg, freg] -> { + x86_fp_op_reg(inst, X86_FMUL, 1, 1); + } + +JIT_OP_FDIV: binary, stack + [freg, freg] -> { + x86_fp_op_reg(inst, X86_FDIV, 1, 1); + } + +JIT_OP_FNEG: unary, stack + [freg] -> { + x86_fchs(inst); + } + +JIT_OP_DADD: binary, stack + [freg, freg] -> { + x86_fp_op_reg(inst, X86_FADD, 1, 1); + } + +JIT_OP_DSUB: binary, stack + [freg, freg] -> { + x86_fp_op_reg(inst, X86_FSUB, 1, 1); + } + +JIT_OP_DMUL: binary, stack + [freg, freg] -> { + x86_fp_op_reg(inst, X86_FMUL, 1, 1); + } + +JIT_OP_DDIV: binary, stack + [freg, freg] -> { + x86_fp_op_reg(inst, X86_FDIV, 1, 1); + } + +JIT_OP_DNEG: unary, stack + [freg] -> { + x86_fchs(inst); + } + +JIT_OP_NFADD: binary, stack + [freg, freg] -> { + x86_fp_op_reg(inst, X86_FADD, 1, 1); + } + +JIT_OP_NFSUB: binary, stack + [freg, freg] -> { + x86_fp_op_reg(inst, X86_FSUB, 1, 1); + } + +JIT_OP_NFMUL: binary, stack + [freg, freg] -> { + x86_fp_op_reg(inst, X86_FMUL, 1, 1); + } + +JIT_OP_NFDIV: binary, stack + [freg, freg] -> { + x86_fp_op_reg(inst, X86_FDIV, 1, 1); + } + +JIT_OP_NFNEG: unary, stack + [freg] -> { + x86_fchs(inst); + } + /* * Bitwise opcodes. */ @@ -469,7 +544,7 @@ JIT_OP_IGE_UN: binary * Pointer check opcodes. */ -JIT_OP_CHECK_NULL: unary_branch +JIT_OP_CHECK_NULL: unary_note [reg] -> { /* TODO: won't work in a function with a "try" block */ unsigned char *patch; @@ -517,7 +592,7 @@ JIT_OP_RETURN: inst = jump_to_epilog(gen, inst, block); } -JIT_OP_RETURN_INT: unary_branch +JIT_OP_RETURN_INT: unary_note [reg] -> { int cpu_reg = $1; if(cpu_reg != X86_EAX) @@ -529,21 +604,35 @@ JIT_OP_RETURN_INT: unary_branch JIT_OP_RETURN_LONG: spill_before [] -> { - /* TODO: load the return value into EAX:EDX */ + if(jit_value_is_constant(insn->value1)) + { + x86_mov_reg_imm(inst, X86_EAX, + ((jit_int *)(insn->value1->address))[0]); + x86_mov_reg_imm(inst, X86_EDX, + ((jit_int *)(insn->value1->address))[1]); + } + else + { + jit_nint offset; + _jit_gen_fix_value(insn->value1); + offset = insn->value1->frame_offset; + x86_mov_reg_membase(inst, X86_EAX, X86_EBP, offset, 4); + x86_mov_reg_membase(inst, X86_EDX, X86_EBP, offset + 4, 4); + } inst = jump_to_epilog(gen, inst, block); } -JIT_OP_RETURN_FLOAT32: unary_branch, stack /*, only*/ +JIT_OP_RETURN_FLOAT32: unary_note, stack, only [freg] -> { inst = jump_to_epilog(gen, inst, block); } -JIT_OP_RETURN_FLOAT64: unary_branch, stack /*, only*/ +JIT_OP_RETURN_FLOAT64: unary_note, stack, only [freg] -> { inst = jump_to_epilog(gen, inst, block); } -JIT_OP_RETURN_NFLOAT: unary_branch, stack /*, only*/ +JIT_OP_RETURN_NFLOAT: unary_note, stack, only [freg] -> { inst = jump_to_epilog(gen, inst, block); } @@ -604,11 +693,65 @@ JIT_OP_IMPORT: /* TODO */ } +/* + * Data manipulation. + */ + +JIT_OP_COPY_LOAD_SBYTE: unary + [reg] -> {} + +JIT_OP_COPY_LOAD_UBYTE: unary + [reg] -> {} + +JIT_OP_COPY_LOAD_SHORT: unary + [reg] -> {} + +JIT_OP_COPY_LOAD_USHORT: unary + [reg] -> {} + +JIT_OP_COPY_INT: unary + [reg] -> {} + +JIT_OP_COPY_LONG: spill_before + [] -> { + /* TODO */ + } + +JIT_OP_COPY_FLOAT32: unary + [freg] -> {} + +JIT_OP_COPY_FLOAT64: unary + [freg] -> {} + +JIT_OP_COPY_NFLOAT: unary + [freg] -> {} + +JIT_OP_COPY_STRUCT: + [] -> { + /* TODO */ + } + +JIT_OP_COPY_STORE_BYTE: + [] -> { + /* TODO */ + } + +JIT_OP_COPY_STORE_SHORT: + [] -> { + /* TODO */ + } + +JIT_OP_ADDRESS_OF: + [] -> { + _jit_gen_fix_value(insn->value1); + /* TODO: get a register to hold the result */ + } + /* * Stack pushes and pops. */ -JIT_OP_PUSH_INT: unary_branch +JIT_OP_PUSH_INT: unary_note [imm] -> { x86_push_imm(inst, $1); } @@ -619,28 +762,81 @@ JIT_OP_PUSH_INT: unary_branch x86_push_reg(inst, $1); } -JIT_OP_PUSH_LONG: +JIT_OP_PUSH_LONG: spill_before [] -> { - /* TODO */ + if(jit_value_is_constant(insn->value1)) + { + x86_push_imm(inst, ((jit_int *)(insn->value1->address))[1]); + x86_push_imm(inst, ((jit_int *)(insn->value1->address))[0]); + } + else + { + jit_nint offset; + _jit_gen_fix_value(insn->value1); + offset = insn->value1->frame_offset; + x86_push_membase(inst, X86_EBP, offset + 4); + x86_push_membase(inst, X86_EBP, offset); + } } -JIT_OP_PUSH_FLOAT32: - [] -> { - /* TODO */ +JIT_OP_PUSH_FLOAT32: unary_note + [imm] -> { + x86_push_imm(inst, *((jit_int *)(insn->value1->address))); + } + [local] -> { + x86_push_membase(inst, X86_EBP, $1); + } + [reg] -> { + x86_alu_reg_imm(inst, X86_SUB, X86_ESP, sizeof(jit_float32)); + x86_fst_membase(inst, X86_ESP, 0, 0, 1); } -JIT_OP_PUSH_FLOAT64: - [] -> { - /* TODO */ +JIT_OP_PUSH_FLOAT64: unary_note + [imm] -> { + x86_push_imm(inst, ((jit_int *)(insn->value1->address))[1]); + x86_push_imm(inst, ((jit_int *)(insn->value1->address))[0]); + } + [local] -> { + x86_push_membase(inst, X86_EBP, $1 + 4); + x86_push_membase(inst, X86_EBP, $1); + } + [reg] -> { + x86_alu_reg_imm(inst, X86_SUB, X86_ESP, sizeof(jit_float64)); + x86_fst_membase(inst, X86_ESP, 0, 1, 1); } -JIT_OP_PUSH_NFLOAT: - [] -> { - /* TODO */ +JIT_OP_PUSH_NFLOAT: unary_note + [imm] -> { + if(sizeof(jit_nfloat) != sizeof(jit_float64)) + { + x86_push_imm(inst, ((jit_int *)(insn->value1->address))[2]); + } + x86_push_imm(inst, ((jit_int *)(insn->value1->address))[1]); + x86_push_imm(inst, ((jit_int *)(insn->value1->address))[0]); + } + [local] -> { + if(sizeof(jit_nfloat) != sizeof(jit_float64)) + { + x86_push_membase(inst, X86_EBP, $1 + 8); + } + x86_push_membase(inst, X86_EBP, $1 + 4); + x86_push_membase(inst, X86_EBP, $1); + } + [reg] -> { + if(sizeof(jit_nfloat) != sizeof(jit_float64)) + { + x86_alu_reg_imm(inst, X86_SUB, X86_ESP, sizeof(jit_nfloat)); + x86_fst80_membase(inst, X86_ESP, 0); + } + else + { + x86_alu_reg_imm(inst, X86_SUB, X86_ESP, sizeof(jit_float64)); + x86_fst_membase(inst, X86_ESP, 0, 1, 1); + } } -JIT_OP_PUSH_STRUCT: - [] -> { +JIT_OP_PUSH_STRUCT: unary_note + [reg] -> { /* TODO */ } @@ -651,5 +847,67 @@ JIT_OP_POP_STACK: JIT_OP_FLUSH_SMALL_STRUCT: [] -> { - /* TODO */ + jit_nuint size; + jit_nint offset; + _jit_gen_fix_value(insn->value1); + size = jit_type_get_size(jit_value_get_type(insn->value1)); + offset = insn->value1->frame_offset; + switch(size) + { + case 1: + { + x86_mov_membase_reg(inst, X86_EBP, offset, X86_EAX, 1); + } + break; + + case 2: + { + x86_mov_membase_reg(inst, X86_EBP, offset, X86_EAX, 2); + } + break; + + case 3: + { + x86_mov_membase_reg(inst, X86_EBP, offset, X86_EAX, 2); + x86_shift_reg_imm(inst, X86_EAX, X86_SHR, 16); + x86_mov_membase_reg(inst, X86_EBP, offset + 2, X86_EAX, 1); + } + break; + + case 4: + { + x86_mov_membase_reg(inst, X86_EBP, offset, X86_EAX, 4); + } + break; + + case 5: + { + x86_mov_membase_reg(inst, X86_EBP, offset, X86_EAX, 4); + x86_mov_membase_reg(inst, X86_EBP, offset + 4, X86_EDX, 1); + } + break; + + case 6: + { + x86_mov_membase_reg(inst, X86_EBP, offset, X86_EAX, 4); + x86_mov_membase_reg(inst, X86_EBP, offset + 4, X86_EDX, 2); + } + break; + + case 7: + { + x86_mov_membase_reg(inst, X86_EBP, offset, X86_EAX, 4); + x86_mov_membase_reg(inst, X86_EBP, offset + 4, X86_EDX, 2); + x86_shift_reg_imm(inst, X86_EDX, X86_SHR, 16); + x86_mov_membase_reg(inst, X86_EBP, offset + 6, X86_EDX, 1); + } + break; + + case 8: + { + x86_mov_membase_reg(inst, X86_EBP, offset, X86_EAX, 4); + x86_mov_membase_reg(inst, X86_EBP, offset + 4, X86_EDX, 4); + } + break; + } } diff --git a/tools/gen-sel-parser.y b/tools/gen-sel-parser.y index a8e30d4..368e102 100644 --- a/tools/gen-sel-parser.y +++ b/tools/gen-sel-parser.y @@ -75,6 +75,7 @@ static int gensel_first_stack_reg = 8; /* st0 under x86 */ #define GENSEL_OPT_STACK 0x0010 #define GENSEL_OPT_UNARY_BRANCH 0x0020 #define GENSEL_OPT_BINARY_BRANCH 0x0040 +#define GENSEL_OPT_ONLY 0x0080 /* * Pattern values. @@ -512,6 +513,15 @@ static void gensel_output_clauses(gensel_clause_t clauses, int options) } else { + if((options & GENSEL_OPT_ONLY) != 0) + { + printf("\t\tif(!_jit_regs_is_top(gen, insn->value1) ||\n"); + printf("\t\t _jit_regs_num_used(gen, %d) != 1)\n", + gensel_first_stack_reg); + printf("\t\t{\n"); + printf("\t\t\t_jit_regs_spill_all(gen);\n"); + printf("\t\t}\n"); + } if((options & GENSEL_OPT_TERNARY) != 0) { printf("\t\treg = _jit_regs_load_to_top_three\n"); @@ -525,7 +535,8 @@ static void gensel_output_clauses(gensel_clause_t clauses, int options) "%d);\n", gensel_first_stack_reg); } - else if((options & GENSEL_OPT_BINARY) != 0) + else if((options & (GENSEL_OPT_BINARY | + GENSEL_OPT_BINARY_BRANCH)) != 0) { printf("\t\treg = _jit_regs_load_to_top_two\n"); printf("\t\t\t(gen, insn->value1, insn->value2,\n"); @@ -536,7 +547,8 @@ static void gensel_output_clauses(gensel_clause_t clauses, int options) "%d);\n", gensel_first_stack_reg); } - else if((options & GENSEL_OPT_UNARY) != 0) + else if((options & (GENSEL_OPT_UNARY | + GENSEL_OPT_UNARY_BRANCH)) != 0) { printf("\t\treg = _jit_regs_load_to_top\n"); printf("\t\t\t(gen, insn->value1,\n"); @@ -643,6 +655,7 @@ static void gensel_output_supported(void) %token K_BINARY_BRANCH "`binary_branch'" %token K_TERNARY "`ternary'" %token K_STACK "`stack'" +%token K_ONLY "`only'" %token K_INST_TYPE "`%inst_type'" /* @@ -719,6 +732,7 @@ Option | K_BINARY_BRANCH { $$ = GENSEL_OPT_BINARY_BRANCH; } | K_TERNARY { $$ = GENSEL_OPT_TERNARY; } | K_STACK { $$ = GENSEL_OPT_STACK; } + | K_ONLY { $$ = GENSEL_OPT_ONLY; } ; Clauses diff --git a/tools/gen-sel-scanner.l b/tools/gen-sel-scanner.l index 9cfa20f..69a7df5 100644 --- a/tools/gen-sel-scanner.l +++ b/tools/gen-sel-scanner.l @@ -98,7 +98,10 @@ WHITE [ \t\v\r\f] "ternary" { RETURNTOK(K_TERNARY); } "unary_branch" { RETURNTOK(K_UNARY_BRANCH); } "binary_branch" { RETURNTOK(K_BINARY_BRANCH); } +"unary_note" { RETURNTOK(K_UNARY_BRANCH); } +"binary_note" { RETURNTOK(K_BINARY_BRANCH); } "stack" { RETURNTOK(K_STACK); } +"only" { RETURNTOK(K_ONLY); } "%inst_type" { RETURNTOK(K_INST_TYPE); } {IDALPHA}({DIGIT}|{IDALPHA})* { -- 2.47.3