From c6a3501dc5ce56f61b9dd35fd059a6a50f34fe29 Mon Sep 17 00:00:00 2001 From: Rhys Weatherley Date: Mon, 14 Jun 2004 07:14:28 +0000 Subject: [PATCH] Enable register allocation for 64-bit values under x86 and ARM; expand some 64-bit opcodes in the instruction selectors. --- ChangeLog | 17 +++- jit/jit-rules-arm.h | 4 +- jit/jit-rules-arm.sel | 170 ++++++++++++++------------------- jit/jit-rules-x86.h | 4 +- jit/jit-rules-x86.sel | 209 +++++++++++++++++++++++++++-------------- tools/gen-sel-parser.y | 20 ++++ 6 files changed, 241 insertions(+), 183 deletions(-) diff --git a/ChangeLog b/ChangeLog index 2676ede..a713d1c 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,4 +1,16 @@ +2004-06-14 Rhys Weatherley + + * dpas/dpas-internal.h, dpas/dpas-parser.y, dpas/dpas-scanner.l, + jit/jit-rules-x86.c, jit/jit-rules-x86.sel, tests/Makefile.am, + tests/param.pas, tools/gen-apply.c: add some test cases for + parameter passing; fix fastcall/stdcall conventions for x86. + + * jit/jit-rules-arm.h, jit/jit-rules-arm.sel, jit/jit-rules-x86.h, + jit/jit-rules-x86.sel, tools/gen-sel-parser.y: enable register + allocation for 64-bit values under x86 and ARM; expand some + 64-bit opcodes in the instruction selectors. + 2004-06-12 Rhys Weatherley * jit/jit-insn.c, jit/jit-rules-x86.c, jit/jit-rules-x86.sel: @@ -10,11 +22,6 @@ jitplus/jit-plus-function.cpp: add the "outgoing_frame_posn" instruction, to support tail calls. - * dpas/dpas-internal.h, dpas/dpas-parser.y, dpas/dpas-scanner.l, - jit/jit-rules-x86.c, jit/jit-rules-x86.sel, tests/Makefile.am, - tests/param.pas, tools/gen-apply.c: add some test cases for - parameter passing; fix fastcall/stdcall conventions for x86. - 2004-06-11 Rhys Weatherley * doc/libjit.texi, jit/jit-insn.c, jit/jit-internal.h, diff --git a/jit/jit-rules-arm.h b/jit/jit-rules-arm.h index 94acca0..935fdb7 100644 --- a/jit/jit-rules-arm.h +++ b/jit/jit-rules-arm.h @@ -48,9 +48,9 @@ extern "C" { #define JIT_REG_ARM_FLOAT JIT_REG_FIXED #endif #define JIT_REG_INFO \ - {"r0", 0, 1, JIT_REG_WORD | JIT_REG_CALL_USED}, \ + {"r0", 0, 1, JIT_REG_WORD | JIT_REG_LONG | JIT_REG_CALL_USED}, \ {"r1", 1, -1, JIT_REG_WORD | JIT_REG_CALL_USED}, \ - {"r2", 2, 3, JIT_REG_WORD | JIT_REG_CALL_USED}, \ + {"r2", 2, 3, JIT_REG_WORD | JIT_REG_LONG | JIT_REG_CALL_USED}, \ {"r3", 3, -1, JIT_REG_WORD | JIT_REG_CALL_USED}, \ {"r4", 4, -1, JIT_REG_WORD}, \ {"r5", 5, -1, JIT_REG_WORD}, \ diff --git a/jit/jit-rules-arm.sel b/jit/jit-rules-arm.sel index f25973e..173033f 100644 --- a/jit/jit-rules-arm.sel +++ b/jit/jit-rules-arm.sel @@ -149,6 +149,26 @@ JIT_OP_INEG: unary arm_alu_reg_imm8(inst, ARM_RSB, $1, $1, 0); } +JIT_OP_LADD: binary + [lreg, lreg] -> { + arm_alu_cc_reg_reg(inst, ARM_ADD, $1, $1, $2); + arm_alu_reg_reg(inst, ARM_ADC, %1, %1, %2); + } + +JIT_OP_LSUB: binary + [lreg, lreg] -> { + arm_alu_cc_reg_reg(inst, ARM_SUB, $1, $1, $2); + arm_alu_reg_reg(inst, ARM_SBC, %1, %1, %2); + } + +JIT_OP_LNEG: unary + [lreg] -> { + arm_alu_reg(inst, ARM_MVN, $1, $1); + arm_alu_reg(inst, ARM_MVN, %1, %1); + arm_alu_cc_reg_imm8(inst, ARM_ADD, $1, $1, 1); + arm_alu_reg_imm8(inst, ARM_ADC, %1, %1, 0); + } + JIT_OP_FADD (JIT_ARM_HAS_FLOAT_REGS): binary [freg, freg] -> { arm_alu_freg_freg_32(inst, ARM_ADF, $1, $1, $2); @@ -260,6 +280,30 @@ JIT_OP_ISHR_UN: binary arm_shift_reg_reg(inst, ARM_SHR, $1, $1, ARM_WORK); } +JIT_OP_LAND: binary + [lreg, lreg] -> { + arm_alu_reg_reg(inst, ARM_AND, $1, $1, $2); + arm_alu_reg_reg(inst, ARM_AND, %1, %1, %2); + } + +JIT_OP_LOR: binary + [lreg, lreg] -> { + arm_alu_reg_reg(inst, ARM_ORR, $1, $1, $2); + arm_alu_reg_reg(inst, ARM_ORR, %1, %1, %2); + } + +JIT_OP_LXOR: binary + [lreg, lreg] -> { + arm_alu_reg_reg(inst, ARM_EOR, $1, $1, $2); + arm_alu_reg_reg(inst, ARM_EOR, %1, %1, %2); + } + +JIT_OP_LNOT: unary + [lreg] -> { + arm_alu_reg(inst, ARM_MVN, $1, $1); + arm_alu_reg(inst, ARM_MVN, %1, %1); + } + /* * Branch opcodes. */ @@ -599,22 +643,22 @@ JIT_OP_RETURN_INT: unary_branch jump_to_epilog(gen, &inst, block); } -JIT_OP_RETURN_LONG: spill_before - [] -> { - if(jit_value_is_constant(insn->value1)) - { - mov_reg_imm - (gen, &inst, ARM_R0, ((jit_int *)(insn->value1->address))[0]); - mov_reg_imm - (gen, &inst, ARM_R1, ((jit_int *)(insn->value1->address))[1]); - } - else +JIT_OP_RETURN_LONG: unary_branch + [imm] -> { + mov_reg_imm(gen, &inst, ARM_R0, ((jit_int *)($1))[0]); + mov_reg_imm(gen, &inst, ARM_R1, ((jit_int *)($1))[1]); + jump_to_epilog(gen, &inst, block); + } + [local] -> { + arm_load_membase(inst, ARM_R0, ARM_FP, $1); + arm_load_membase(inst, ARM_R1, ARM_FP, $1 + 4); + jump_to_epilog(gen, &inst, block); + } + [lreg] -> { + if($1 != 0) { - jit_nint offset; - _jit_gen_fix_value(insn->value1); - offset = insn->value1->frame_offset; - arm_load_membase(inst, ARM_R0, ARM_FP, offset); - arm_load_membase(inst, ARM_R1, ARM_FP, offset + 4); + arm_mov_reg_reg(inst, ARM_R0, $1); + arm_mov_reg_reg(inst, ARM_R1, %1); } jump_to_epilog(gen, &inst, block); } @@ -815,38 +859,8 @@ JIT_OP_COPY_LOAD_USHORT: unary JIT_OP_COPY_INT: unary [reg] -> {} -JIT_OP_COPY_LONG: manual - [] -> { - arm_inst_buf inst; - _jit_regs_force_out(gen, insn->value1, 0); - _jit_regs_force_out(gen, insn->dest, 1); - _jit_gen_fix_value(insn->value1); - _jit_gen_fix_value(insn->dest); - jit_gen_load_inst_ptr(gen, inst); - if(insn->value1->is_constant) - { - mov_reg_imm - (gen, &inst, ARM_WORK, ((int *)(insn->value1->address))[0]); - arm_store_membase(inst, ARM_WORK, ARM_FP, - insn->dest->frame_offset); - mov_reg_imm - (gen, &inst, ARM_WORK, ((int *)(insn->value1->address))[1]); - arm_store_membase(inst, ARM_WORK, ARM_FP, - insn->dest->frame_offset + 4); - } - else - { - arm_load_membase(inst, ARM_WORK, ARM_FP, - insn->value1->frame_offset); - arm_store_membase(inst, ARM_WORK, ARM_FP, - insn->dest->frame_offset); - arm_load_membase(inst, ARM_WORK, ARM_FP, - insn->value1->frame_offset + 4); - arm_store_membase(inst, ARM_WORK, ARM_FP, - insn->dest->frame_offset + 4); - } - jit_gen_save_inst_ptr(gen, inst); - } +JIT_OP_COPY_LONG: unary + [lreg] -> {} JIT_OP_COPY_FLOAT32 (JIT_ARM_HAS_FLOAT_REGS): unary [freg] -> {} @@ -985,31 +999,10 @@ JIT_OP_PUSH_INT: unary_note arm_push_reg(inst, $1); } -JIT_OP_PUSH_LONG: manual - [] -> { - arm_inst_buf inst; - _jit_regs_force_out(gen, insn->value1, 0); - _jit_gen_fix_value(insn->value1); - jit_gen_load_inst_ptr(gen, inst); - if(insn->value1->is_constant) - { - mov_reg_imm - (gen, &inst, ARM_WORK, ((int *)(insn->value1->address))[1]); - arm_push_reg(inst, ARM_WORK); - mov_reg_imm - (gen, &inst, ARM_WORK, ((int *)(insn->value1->address))[0]); - arm_push_reg(inst, ARM_WORK); - } - else - { - arm_load_membase(inst, ARM_WORK, ARM_FP, - insn->value1->frame_offset + 4); - arm_push_reg(inst, ARM_WORK); - arm_load_membase(inst, ARM_WORK, ARM_FP, - insn->value1->frame_offset); - arm_push_reg(inst, ARM_WORK); - } - jit_gen_save_inst_ptr(gen, inst); +JIT_OP_PUSH_LONG: unary_note + [lreg] -> { + arm_push_reg(inst, %1); + arm_push_reg(inst, $1); } JIT_OP_PUSH_FLOAT32 (JIT_ARM_HAS_FLOAT_REGS): unary_note @@ -1154,35 +1147,10 @@ JIT_OP_SET_PARAM_INT: unary_note arm_store_membase(inst, $1, ARM_SP, insn->value2->address); } -JIT_OP_SET_PARAM_LONG: manual - [] -> { - arm_inst_buf inst; - _jit_regs_force_out(gen, insn->value1, 0); - _jit_gen_fix_value(insn->value1); - jit_gen_load_inst_ptr(gen, inst); - if(insn->value1->is_constant) - { - mov_reg_imm - (gen, &inst, ARM_WORK, ((int *)(insn->value1->address))[0]); - arm_store_membase - (inst, ARM_WORK, ARM_SP, insn->value2->address); - mov_reg_imm - (gen, &inst, ARM_WORK, ((int *)(insn->value1->address))[1]); - arm_store_membase - (inst, ARM_WORK, ARM_SP, insn->value2->address + 4); - } - else - { - arm_load_membase(inst, ARM_WORK, ARM_FP, - insn->value1->frame_offset); - arm_store_membase - (inst, ARM_WORK, ARM_SP, insn->value2->address); - arm_load_membase(inst, ARM_WORK, ARM_FP, - insn->value1->frame_offset + 4); - arm_store_membase - (inst, ARM_WORK, ARM_SP, insn->value2->address + 4); - } - jit_gen_save_inst_ptr(gen, inst); +JIT_OP_SET_PARAM_LONG: unary_note + [lreg] -> { + arm_store_membase(inst, $1, ARM_SP, insn->value2->address); + arm_store_membase(inst, %1, ARM_SP, insn->value2->address + 4); } JIT_OP_SET_PARAM_FLOAT32 (JIT_ARM_HAS_FLOAT_REGS): unary_note diff --git a/jit/jit-rules-x86.h b/jit/jit-rules-x86.h index b144f54..8db9c7c 100644 --- a/jit/jit-rules-x86.h +++ b/jit/jit-rules-x86.h @@ -29,8 +29,8 @@ extern "C" { * Information about all of the registers, in allocation order. */ #define JIT_REG_INFO \ - {"eax", 0, 2, JIT_REG_WORD | JIT_REG_CALL_USED}, \ - {"ecx", 1, 3, JIT_REG_WORD | JIT_REG_CALL_USED}, \ + {"eax", 0, 2, JIT_REG_WORD | JIT_REG_LONG | JIT_REG_CALL_USED}, \ + {"ecx", 1, 3, JIT_REG_WORD | JIT_REG_LONG | JIT_REG_CALL_USED}, \ {"edx", 2, -1, JIT_REG_WORD | JIT_REG_CALL_USED}, \ {"ebx", 3, -1, JIT_REG_WORD | JIT_REG_GLOBAL}, \ {"esi", 6, -1, JIT_REG_WORD | JIT_REG_GLOBAL}, \ diff --git a/jit/jit-rules-x86.sel b/jit/jit-rules-x86.sel index 0b50bde..5481814 100644 --- a/jit/jit-rules-x86.sel +++ b/jit/jit-rules-x86.sel @@ -1031,6 +1031,60 @@ JIT_OP_INEG: unary x86_neg_reg(inst, $1); } +JIT_OP_LADD: binary + [lreg, imm] -> { + jit_int value1 = ((jit_int *)($2))[0]; + jit_int value2 = ((jit_int *)($2))[1]; + if(value1 != 0) + { + x86_alu_reg_imm(inst, X86_ADD, $1, value1); + x86_alu_reg_imm(inst, X86_ADC, %1, value2); + } + else + { + x86_alu_reg_imm(inst, X86_ADD, %1, value2); + } + } + [lreg, local] -> { + x86_alu_reg_membase(inst, X86_ADD, $1, X86_EBP, $2); + x86_alu_reg_membase(inst, X86_ADC, %1, X86_EBP, $2 + 4); + } + [lreg, lreg] -> { + x86_alu_reg_reg(inst, X86_ADD, $1, $2); + x86_alu_reg_reg(inst, X86_ADC, %1, %2); + } + +JIT_OP_LSUB: binary + [lreg, imm] -> { + jit_int value1 = ((jit_int *)($2))[0]; + jit_int value2 = ((jit_int *)($2))[1]; + if(value1 != 0) + { + x86_alu_reg_imm(inst, X86_SUB, $1, value1); + x86_alu_reg_imm(inst, X86_SBB, %1, value2); + } + else + { + x86_alu_reg_imm(inst, X86_SUB, %1, value2); + } + } + [lreg, local] -> { + x86_alu_reg_membase(inst, X86_SUB, $1, X86_EBP, $2); + x86_alu_reg_membase(inst, X86_SBB, %1, X86_EBP, $2 + 4); + } + [lreg, lreg] -> { + x86_alu_reg_reg(inst, X86_SUB, $1, $2); + x86_alu_reg_reg(inst, X86_SBB, %1, %2); + } + +JIT_OP_LNEG: unary + [lreg] -> { + x86_not_reg(inst, $1); + x86_not_reg(inst, %1); + x86_alu_reg_imm(inst, X86_ADD, $1, 1); + x86_alu_reg_imm(inst, X86_ADC, %1, 0); + } + JIT_OP_FADD, JIT_OP_DADD, JIT_OP_NFADD: binary, stack [freg, freg] -> { x86_fp_op_reg(inst, X86_FADD, 1, 1); @@ -1145,6 +1199,60 @@ JIT_OP_ISHR_UN: binary inst = shift_reg(inst, X86_SHR, $1, $2); } +JIT_OP_LAND: binary + [lreg, imm] -> { + jit_int value1 = ((jit_int *)($2))[0]; + jit_int value2 = ((jit_int *)($2))[1]; + x86_alu_reg_imm(inst, X86_AND, $1, value1); + x86_alu_reg_imm(inst, X86_AND, %1, value2); + } + [lreg, local] -> { + x86_alu_reg_membase(inst, X86_AND, $1, X86_EBP, $2); + x86_alu_reg_membase(inst, X86_AND, %1, X86_EBP, $2 + 4); + } + [lreg, lreg] -> { + x86_alu_reg_reg(inst, X86_AND, $1, $2); + x86_alu_reg_reg(inst, X86_AND, %1, %2); + } + +JIT_OP_LOR: binary + [lreg, imm] -> { + jit_int value1 = ((jit_int *)($2))[0]; + jit_int value2 = ((jit_int *)($2))[1]; + x86_alu_reg_imm(inst, X86_OR, $1, value1); + x86_alu_reg_imm(inst, X86_OR, %1, value2); + } + [lreg, local] -> { + x86_alu_reg_membase(inst, X86_OR, $1, X86_EBP, $2); + x86_alu_reg_membase(inst, X86_OR, %1, X86_EBP, $2 + 4); + } + [lreg, lreg] -> { + x86_alu_reg_reg(inst, X86_OR, $1, $2); + x86_alu_reg_reg(inst, X86_OR, %1, %2); + } + +JIT_OP_LXOR: binary + [lreg, imm] -> { + jit_int value1 = ((jit_int *)($2))[0]; + jit_int value2 = ((jit_int *)($2))[1]; + x86_alu_reg_imm(inst, X86_XOR, $1, value1); + x86_alu_reg_imm(inst, X86_XOR, %1, value2); + } + [lreg, local] -> { + x86_alu_reg_membase(inst, X86_XOR, $1, X86_EBP, $2); + x86_alu_reg_membase(inst, X86_XOR, %1, X86_EBP, $2 + 4); + } + [lreg, lreg] -> { + x86_alu_reg_reg(inst, X86_XOR, $1, $2); + x86_alu_reg_reg(inst, X86_XOR, %1, %2); + } + +JIT_OP_LNOT: binary + [lreg] -> { + x86_not_reg(inst, $1); + x86_not_reg(inst, %1); + } + /* * Branch opcodes. */ @@ -1564,22 +1672,19 @@ JIT_OP_RETURN_INT: unary_branch inst = jump_to_epilog(gen, inst, block); } -JIT_OP_RETURN_LONG: spill_before - [] -> { - 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_OP_RETURN_LONG: unary_branch + [imm] -> { + 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]); + inst = jump_to_epilog(gen, inst, block); + } + [lreg] -> { + if($1 != X86_EAX) { - 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); + x86_mov_reg_reg(inst, X86_EAX, $1, 4); + x86_mov_reg_reg(inst, X86_EDX, %1, 4); } inst = jump_to_epilog(gen, inst, block); } @@ -1894,48 +1999,8 @@ JIT_OP_COPY_LOAD_USHORT: unary JIT_OP_COPY_INT: unary [reg] -> {} -JIT_OP_COPY_LONG: manual - [] -> { - unsigned char *inst; - int offset, offset2, reg, reg2; - _jit_regs_force_out(gen, insn->dest, 1); - _jit_gen_fix_value(insn->dest); - offset = insn->dest->frame_offset; - if(jit_value_is_constant(insn->value1)) - { - 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, offset, - ((int *)(insn->value1->address))[0], 4); - x86_mov_membase_imm(inst, X86_EBP, offset + 4, - ((int *)(insn->value1->address))[1], 4); - gen->posn.ptr = inst; - } - else - { - _jit_regs_force_out(gen, insn->value1, 0); - _jit_gen_fix_value(insn->value1); - offset2 = insn->value1->frame_offset; - _jit_regs_get_reg_pair(gen, -1, -1, -1, ®, ®2); - reg = _jit_reg_info[reg].cpu_reg; - reg2 = _jit_reg_info[reg2].cpu_reg; - 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, reg, X86_EBP, offset2, 4); - x86_mov_reg_membase(inst, reg2, X86_EBP, offset2 + 4, 4); - x86_mov_membase_reg(inst, X86_EBP, offset, reg, 4); - x86_mov_membase_reg(inst, X86_EBP, offset + 4, reg2, 4); - gen->posn.ptr = inst; - } - } +JIT_OP_COPY_LONG: unary + [lreg] -> {} JIT_OP_COPY_FLOAT32: unary, stack [freg] -> {} @@ -2064,22 +2129,20 @@ JIT_OP_PUSH_INT: unary_note gen->stack_changed = 1; } -JIT_OP_PUSH_LONG: spill_before - [] -> { - /* TODO: use 'manual' to avoid register spills */ - 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_LONG: unary_note + [imm] -> { + x86_push_imm(inst, ((jit_int *)($1))[1]); + x86_push_imm(inst, ((jit_int *)($1))[0]); + gen->stack_changed = 1; + } + [local] -> { + x86_push_membase(inst, X86_EBP, $1 + 4); + x86_push_membase(inst, X86_EBP, $1); + gen->stack_changed = 1; + } + [reg] -> { + x86_push_reg(inst, %1); + x86_push_reg(inst, $1); gen->stack_changed = 1; } diff --git a/tools/gen-sel-parser.y b/tools/gen-sel-parser.y index ac76699..d896849 100644 --- a/tools/gen-sel-parser.y +++ b/tools/gen-sel-parser.y @@ -257,6 +257,26 @@ static void gensel_output_clause_code(gensel_clause_t clause) } code += 2; } + else if(*code == '%' && code[1] >= '1' && code[1] <= '9') + { + index = code[1] - '1'; + switch(clause->pattern[index]) + { + case GENSEL_PATT_REG: + case GENSEL_PATT_LREG: + case GENSEL_PATT_FREG: + { + if(index == 0) + printf("_jit_reg_info[_jit_reg_info[reg].other_reg].cpu_reg"); + else if(index == 1) + printf("_jit_reg_info[_jit_reg_info[reg2].other_reg].cpu_reg"); + else + printf("_jit_reg_info[_jit_reg_info[reg3].other_reg].cpu_reg"); + } + break; + } + code += 2; + } else if(*code == '\n') { putc(*code, stdout); -- 2.47.3