Browse Source

More instruction selection rules for ARM.

cache-refactoring
Rhys Weatherley 21 years ago
parent
commit
f9aae1aee6
  1. 3
      ChangeLog
  2. 96
      jit/jit-rules-arm.c
  3. 216
      jit/jit-rules-arm.sel

3
ChangeLog

@ -4,6 +4,9 @@
* jit/jit-cache.c, jit/jit-elf-read.c, tools/gen-apply.c:
fix some gcc 3.x compile warnings.
* jit/jit-rules-arm.c, jit/jit-rules-arm.sel: more instruction
selection rules for ARM.
2004-05-31 Rhys Weatherley <rweather@southern-storm.com.au>
* jit/jit-rules-x86.sel: optimize multiplications for x86.

96
jit/jit-rules-arm.c

@ -26,6 +26,7 @@
#include "jit-gen-arm.h"
#include "jit-reg-alloc.h"
#include <stdio.h>
/*
* Determine if we actually have floating-point registers.
@ -546,6 +547,9 @@ void _jit_gen_epilog(jit_gencode_t gen, jit_function_t func)
{
int reg, regset;
arm_inst_ptr inst;
void **fixup;
void **next;
jit_nint offset;
/* Bail out if there is insufficient space for the epilog */
if(!jit_cache_check_for_n(&(gen->posn), 4))
@ -565,6 +569,24 @@ void _jit_gen_epilog(jit_gencode_t gen, jit_function_t func)
}
}
/* Apply fixups for blocks that jump to the epilog */
fixup = (void **)(gen->epilog_fixup);
while(fixup != 0)
{
offset = (((jit_nint)(fixup[0])) & 0x00FFFFFF) << 2;
if(!offset)
{
next = 0;
}
else
{
next = (void **)(((unsigned char *)fixup) - offset);
}
arm_patch(fixup, gen->posn.ptr);
fixup = next;
}
gen->epilog_fixup = 0;
/* Pop the local stack frame and return */
inst = (arm_inst_ptr)(gen->posn.ptr);
arm_pop_frame(inst, regset);
@ -687,6 +709,73 @@ static arm_inst_ptr output_branch
return inst;
}
/*
* Throw a builtin exception.
*/
static arm_inst_ptr throw_builtin
(arm_inst_ptr inst, jit_function_t func, int cond, int type)
{
#if 0
/* TODO: port to ARM */
/* We need to update "catch_pc" if we have a "try" block */
if(func->builder->setjmp_value != 0)
{
_jit_gen_fix_value(func->builder->setjmp_value);
x86_call_imm(inst, 0);
x86_pop_membase(inst, X86_EBP,
func->builder->setjmp_value->frame_offset +
jit_jmp_catch_pc_offset);
}
/* Push the exception type onto the stack */
x86_push_imm(inst, type);
/* Call the "jit_exception_builtin" function, which will never return */
x86_call_code(inst, jit_exception_builtin);
#endif
return inst;
}
/*
* Jump to the current function's epilog.
*/
static arm_inst_ptr jump_to_epilog
(jit_gencode_t gen, arm_inst_ptr inst, jit_block_t block)
{
int offset;
/* If the epilog is the next thing that we will output,
then fall through to the epilog directly */
block = block->next;
while(block != 0 && block->first_insn > block->last_insn)
{
block = block->next;
}
if(!block)
{
return inst;
}
/* Output a placeholder for the jump and add it to the fixup list */
if(gen->epilog_fixup)
{
offset = (int)(((unsigned char *)inst) -
((unsigned char *)(gen->epilog_fixup)));
}
else
{
offset = 0;
}
arm_branch_imm(inst, ARM_CC_AL, offset);
gen->epilog_fixup = (void *)(inst - 1);
return inst;
}
#define TODO() \
do { \
fprintf(stderr, "TODO at %s, %d\n", __FILE__, (int)__LINE__); \
} while (0)
void _jit_gen_insn(jit_gencode_t gen, jit_function_t func,
jit_block_t block, jit_insn_t insn)
{
@ -695,6 +784,13 @@ void _jit_gen_insn(jit_gencode_t gen, jit_function_t func,
#define JIT_INCLUDE_RULES
#include "jit-rules-arm.slc"
#undef JIT_INCLUDE_RULES
default:
{
fprintf(stderr, "TODO(%x) at %s, %d\n",
(int)(insn->opcode), __FILE__, (int)__LINE__);
}
break;
}
}

216
jit/jit-rules-arm.sel

@ -69,8 +69,66 @@ JIT_OP_ISUB: binary
JIT_OP_IMUL: binary
[reg, immu8] -> {
arm_mov_reg_imm8(inst, ARM_WORK, $2);
arm_mul_reg_reg(inst, $1, $1, ARM_WORK);
/* Handle special cases of immediate multiplies */
switch($2)
{
case 0:
{
arm_mov_reg_imm(inst, $1, 0);
}
break;
case 1: break;
case 2:
{
arm_shift_reg_imm8(inst, ARM_SHL, $1, $1, 1);
}
break;
case 4:
{
arm_shift_reg_imm8(inst, ARM_SHL, $1, $1, 2);
}
break;
case 8:
{
arm_shift_reg_imm8(inst, ARM_SHL, $1, $1, 3);
}
break;
case 16:
{
arm_shift_reg_imm8(inst, ARM_SHL, $1, $1, 4);
}
break;
case 32:
{
arm_shift_reg_imm8(inst, ARM_SHL, $1, $1, 5);
}
break;
case 64:
{
arm_shift_reg_imm8(inst, ARM_SHL, $1, $1, 6);
}
break;
case 128:
{
arm_shift_reg_imm8(inst, ARM_SHL, $1, $1, 7);
}
break;
default:
{
arm_mov_reg_imm8(inst, ARM_WORK, $2);
arm_mul_reg_reg(inst, $1, $1, ARM_WORK);
}
break;
}
}
[reg, reg] -> {
if($1 != $2)
@ -426,3 +484,157 @@ JIT_OP_IGE_UN: binary
arm_alu_reg_imm8_cond(inst, ARM_MOV, $1, 0, 0, ARM_CC_LT_UN);
}
/*
* Pointer check opcodes.
*/
JIT_OP_CHECK_NULL: unary_note
[reg] -> {
arm_test_reg_imm8(inst, ARM_CMP, $1, 0);
inst = throw_builtin(inst, func, ARM_CC_EQ, JIT_RESULT_NULL_REFERENCE);
}
/*
* Function calls.
*/
JIT_OP_CALL:
[] -> {
jit_function_t func = (jit_function_t)(insn->dest);
arm_call(inst, func->closure_entry);
}
JIT_OP_CALL_TAIL:
[] -> {
jit_function_t func = (jit_function_t)(insn->dest);
arm_jump(inst, func->closure_entry);
}
JIT_OP_CALL_INDIRECT:
[] -> {
arm_mov_reg_reg((inst), ARM_LINK, ARM_PC);
arm_mov_reg_reg((inst), ARM_PC, ARM_WORK);
}
JIT_OP_CALL_VTABLE_PTR:
[] -> {
arm_mov_reg_reg((inst), ARM_LINK, ARM_PC);
arm_mov_reg_reg((inst), ARM_PC, ARM_WORK);
}
JIT_OP_CALL_EXTERNAL:
[] -> {
arm_call(inst, (void *)(insn->dest));
}
JIT_OP_RETURN:
[] -> {
inst = jump_to_epilog(gen, inst, block);
}
JIT_OP_RETURN_INT: unary_note
[reg] -> {
int cpu_reg = $1;
if(cpu_reg != ARM_R0)
{
arm_mov_reg_reg(inst, ARM_R0, cpu_reg);
}
inst = jump_to_epilog(gen, inst, block);
}
JIT_OP_RETURN_LONG: spill_before
[] -> {
if(jit_value_is_constant(insn->value1))
{
arm_mov_reg_imm(inst, ARM_R0,
((jit_int *)(insn->value1->address))[0]);
arm_mov_reg_imm(inst, ARM_R1,
((jit_int *)(insn->value1->address))[1]);
}
else
{
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);
}
inst = jump_to_epilog(gen, inst, block);
}
JIT_OP_RETURN_FLOAT32: manual
[] -> {
/* TODO */
TODO();
}
JIT_OP_RETURN_FLOAT64: manual
[] -> {
/* TODO */
TODO();
}
JIT_OP_RETURN_NFLOAT: manual
[] -> {
/* TODO */
TODO();
}
JIT_OP_RETURN_SMALL_STRUCT: spill_before
[] -> {
/* TODO: load the structure value into EAX:EDX */
TODO();
inst = jump_to_epilog(gen, inst, block);
}
JIT_OP_SETUP_FOR_NESTED: spill_before
[] -> {
jit_nint nest_reg = jit_value_get_nint_constant(insn->value1);
if(nest_reg == -1)
{
arm_push_reg(inst, ARM_FP);
}
else
{
arm_mov_reg_reg(inst, _jit_reg_info[nest_reg].cpu_reg, ARM_FP);
}
}
JIT_OP_SETUP_FOR_SIBLING: spill_before
[] -> {
jit_nint level = jit_value_get_nint_constant(insn->value1);
jit_nint nest_reg = jit_value_get_nint_constant(insn->value2);
int cpu_reg;
if(nest_reg == -1)
{
cpu_reg = ARM_R0;
}
else
{
cpu_reg = _jit_reg_info[nest_reg].cpu_reg;
}
arm_load_membase(inst, cpu_reg, ARM_FP, JIT_APPLY_PARENT_FRAME_OFFSET);
while(level > 0)
{
gen->posn.ptr = (unsigned char *)inst;
if(!jit_cache_check_for_n(&(gen->posn), 16))
{
jit_cache_mark_full(&(gen->posn));
return;
}
arm_load_membase(inst, cpu_reg, cpu_reg,
JIT_APPLY_PARENT_FRAME_OFFSET);
--level;
}
if(nest_reg == -1)
{
arm_push_reg(inst, cpu_reg);
}
}
JIT_OP_IMPORT:
[] -> {
/* TODO */
TODO();
}

Loading…
Cancel
Save