64-bit opcodes in the instruction selectors.
+2004-06-14 Rhys Weatherley <rweather@southern-storm.com.au>
+
+ * 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 <rweather@southern-storm.com.au>
* jit/jit-insn.c, jit/jit-rules-x86.c, jit/jit-rules-x86.sel:
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 <rweather@southern-storm.com.au>
* doc/libjit.texi, jit/jit-insn.c, jit/jit-internal.h,
#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}, \
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);
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.
*/
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);
}
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] -> {}
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
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
* 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}, \
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);
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.
*/
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);
}
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] -> {}
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;
}
}
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);