]> git.unchartedbackwaters.co.uk Git - francis/libjit.git/commitdiff
More instruction selection rules for ARM.
authorRhys Weatherley <rweather@southern-storm.com.au>
Tue, 1 Jun 2004 09:55:54 +0000 (09:55 +0000)
committerRhys Weatherley <rweather@southern-storm.com.au>
Tue, 1 Jun 2004 09:55:54 +0000 (09:55 +0000)
ChangeLog
jit/jit-rules-arm.c
jit/jit-rules-arm.sel

index 5259272b7460c8f42036b83c5ea23198a653eed7..d6167fd38b5bc6b96bf008e9d49d752ba3359aa1 100644 (file)
--- a/ChangeLog
+++ b/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.
index c613b738b75d529307c4d05c6959e37d32e3a688..2e7e1cde1958923dec2344421f21da290a95ef9d 100644 (file)
@@ -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;
        }
 }
 
index 7cd98ee827e89e20047301cc2988051d76717acc..0fab535401599be568a6a300d8b0202809087626 100644 (file)
@@ -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();
+       }
+