Browse Source

Add the beginnings of the instruction selector for ARM.

cache-refactoring
Rhys Weatherley 21 years ago
parent
commit
cf40d2ffe9
  1. 4
      ChangeLog
  2. 8
      jit/Makefile.am
  3. 3
      jit/jit-gen-arm.h
  4. 80
      jit/jit-rules-arm.c
  5. 428
      jit/jit-rules-arm.sel

4
ChangeLog

@ -20,6 +20,10 @@
* 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.
* jit/Makefile.am, jit/jit-gen-arm.h, jit/jit-rules-arm.c,
jit/jit-rules-arm.sel: add the beginnings of the instruction
selector for ARM.
2004-05-25 Rhys Weatherley <rweather@southern-storm.com.au>
* tools/.cvsignore, tools/Makefile.am, tools/gen-sel-parser.y,

8
jit/Makefile.am

@ -67,4 +67,10 @@ jit-rules-x86.slc: jit-rules-x86.sel $(top_builddir)/tools/gen-sel$(EXEEXT)
$(top_builddir)/tools/gen-sel$(EXEEXT) $(srcdir)/jit-rules-x86.sel \
>jit-rules-x86.slc
CLEANFILES = jit-interp-labels.h jit-rules-x86.slc
jit-rules-arm.lo: jit-rules-arm.slc
jit-rules-arm.slc: jit-rules-arm.sel $(top_builddir)/tools/gen-sel$(EXEEXT)
$(top_builddir)/tools/gen-sel$(EXEEXT) $(srcdir)/jit-rules-arm.sel \
>jit-rules-arm.slc
CLEANFILES = jit-interp-labels.h jit-rules-x86.slc jit-rules-arm.slc

3
jit/jit-gen-arm.h

@ -202,8 +202,7 @@ extern arm_inst_ptr _arm_alu_reg_imm
if(__alu_imm >= 0 && __alu_imm < 256) \
{ \
arm_alu_reg_imm8 \
((inst), (opc), (dreg), (sreg), __alu_imm, \
arm_execute); \
((inst), (opc), (dreg), (sreg), __alu_imm); \
} \
else \
{ \

80
jit/jit-rules-arm.c

@ -25,6 +25,7 @@
#if defined(JIT_BACKEND_ARM)
#include "jit-gen-arm.h"
#include "jit-reg-alloc.h"
/*
* Determine if we actually have floating-point registers.
@ -491,6 +492,17 @@ int _jit_create_call_return_insns
return 1;
}
int _jit_opcode_is_supported(int opcode)
{
switch(opcode)
{
#define JIT_INCLUDE_SUPPORTED
#include "jit-rules-arm.slc"
#undef JIT_INCLUDE_SUPPORTED
}
return 0;
}
void *_jit_gen_prolog(jit_gencode_t gen, jit_function_t func, void *buf)
{
unsigned int prolog[JIT_PROLOG_SIZE / sizeof(int)];
@ -639,15 +651,79 @@ void _jit_gen_fix_value(jit_value_t value)
}
}
/*
* Output a branch instruction.
*/
static arm_inst_ptr output_branch
(jit_function_t func, arm_inst_ptr inst, int cond, jit_insn_t insn)
{
jit_block_t block;
int offset;
block = jit_block_from_label(func, (jit_label_t)(insn->dest));
if(!block)
{
return inst;
}
if(block->address)
{
/* We already know the address of the block */
arm_branch(inst, cond, block->address);
}
else
{
/* Output a placeholder and record on the block's fixup list */
if(block->fixup_list)
{
offset = (int)(((unsigned char *)inst) -
((unsigned char *)(block->fixup_list)));
}
else
{
offset = 0;
}
arm_branch_imm(inst, cond, offset);
block->fixup_list = (void *)(inst - 1);
}
return inst;
}
void _jit_gen_insn(jit_gencode_t gen, jit_function_t func,
jit_block_t block, jit_insn_t insn)
{
/* TODO */
switch(insn->opcode)
{
#define JIT_INCLUDE_RULES
#include "jit-rules-arm.slc"
#undef JIT_INCLUDE_RULES
}
}
void _jit_gen_start_block(jit_gencode_t gen, jit_block_t block)
{
/* TODO: label fixups */
void **fixup;
void **next;
jit_nint offset;
/* Set the address of this block */
block->address = (void *)(gen->posn.ptr);
/* If this block has pending fixups, then apply them now */
fixup = (void **)(block->fixup_list);
while(fixup != 0)
{
offset = (((jit_nint)(fixup[0])) & 0x00FFFFFF) << 2;
if(!offset)
{
next = 0;
}
else
{
next = (void **)(((unsigned char *)fixup) - offset);
}
arm_patch(fixup, block->address);
fixup = next;
}
block->fixup_list = 0;
}
void _jit_gen_end_block(jit_gencode_t gen, jit_block_t block)

428
jit/jit-rules-arm.sel

@ -0,0 +1,428 @@
/*
* jit-rules-arm.sel - Instruction selector for ARM.
*
* Copyright (C) 2004 Southern Storm Software, Pty Ltd.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
%inst_type arm_inst_ptr
/*
* Conversion opcodes.
*/
JIT_OP_TRUNC_SBYTE: unary
[reg] -> {
arm_shift_reg_imm8(inst, ARM_SHL, $1, $1, 24);
arm_shift_reg_imm8(inst, ARM_SAR, $1, $1, 24);
}
JIT_OP_TRUNC_UBYTE: unary
[reg] -> {
arm_alu_reg_imm8(inst, ARM_AND, $1, $1, 0xFF);
}
JIT_OP_TRUNC_SHORT: unary
[reg] -> {
arm_shift_reg_imm8(inst, ARM_SHL, $1, $1, 16);
arm_shift_reg_imm8(inst, ARM_SAR, $1, $1, 16);
}
JIT_OP_TRUNC_USHORT: unary
[reg] -> {
arm_shift_reg_imm8(inst, ARM_SHL, $1, $1, 16);
arm_shift_reg_imm8(inst, ARM_SHR, $1, $1, 16);
}
/*
* Arithmetic opcodes.
*/
JIT_OP_IADD: binary
[reg, immu8] -> {
arm_alu_reg_imm8(inst, ARM_ADD, $1, $1, $2);
}
[reg, reg] -> {
arm_alu_reg_reg(inst, ARM_ADD, $1, $1, $2);
}
JIT_OP_ISUB: binary
[reg, immu8] -> {
arm_alu_reg_imm8(inst, ARM_SUB, $1, $1, $2);
}
[reg, reg] -> {
arm_alu_reg_reg(inst, ARM_SUB, $1, $1, $2);
}
JIT_OP_IMUL: binary
[reg, immu8] -> {
arm_mov_reg_imm8(inst, ARM_WORK, $2);
arm_mul_reg_reg(inst, $1, $1, ARM_WORK);
}
[reg, reg] -> {
if($1 != $2)
{
arm_mul_reg_reg(inst, $1, $1, $2);
}
else
{
/* Cannot use the same register for both arguments */
arm_mov_reg_reg(inst, ARM_WORK, $2);
arm_mul_reg_reg(inst, $1, $1, ARM_WORK);
}
}
JIT_OP_INEG: unary
[reg] -> {
/* -x is the same as (0 - x) */
arm_alu_reg_imm8(inst, ARM_RSB, $1, $1, 0);
}
/*
* Bitwise opcodes.
*/
JIT_OP_IAND: binary
[reg, immu8] -> {
arm_alu_reg_imm8(inst, ARM_AND, $1, $1, $2);
}
[reg, reg] -> {
arm_alu_reg_reg(inst, ARM_AND, $1, $1, $2);
}
JIT_OP_IOR: binary
[reg, immu8] -> {
arm_alu_reg_imm8(inst, ARM_ORR, $1, $1, $2);
}
[reg, reg] -> {
arm_alu_reg_reg(inst, ARM_ORR, $1, $1, $2);
}
JIT_OP_IXOR: binary
[reg, immu8] -> {
arm_alu_reg_imm8(inst, ARM_EOR, $1, $1, $2);
}
[reg, reg] -> {
arm_alu_reg_reg(inst, ARM_EOR, $1, $1, $2);
}
JIT_OP_INOT: unary
[reg] -> {
/* MVN == "move not" */
arm_alu_reg(inst, ARM_MVN, $1, $1);
}
JIT_OP_ISHL: binary
[reg, imm] -> {
arm_shift_reg_imm8(inst, ARM_SHL, $1, $1, ($2 & 0x1F));
}
[reg, reg] -> {
arm_alu_reg_imm8(inst, ARM_AND, ARM_WORK, $2, 0x1F);
arm_shift_reg_reg(inst, ARM_SHL, $1, $1, ARM_WORK);
}
JIT_OP_ISHR: binary
[reg, imm] -> {
arm_shift_reg_imm8(inst, ARM_SAR, $1, $1, ($2 & 0x1F));
}
[reg, reg] -> {
arm_alu_reg_imm8(inst, ARM_AND, ARM_WORK, $2, 0x1F);
arm_shift_reg_reg(inst, ARM_SAR, $1, $1, ARM_WORK);
}
JIT_OP_ISHR_UN: binary
[reg, imm] -> {
arm_shift_reg_imm8(inst, ARM_SHR, $1, $1, ($2 & 0x1F));
}
[reg, reg] -> {
arm_alu_reg_imm8(inst, ARM_AND, ARM_WORK, $2, 0x1F);
arm_shift_reg_reg(inst, ARM_SHR, $1, $1, ARM_WORK);
}
/*
* Branch opcodes.
*/
JIT_OP_BR: spill_before
[] -> {
/* ARM_CC_AL == "always branch" */
inst = output_branch(func, inst, ARM_CC_AL, insn);
}
JIT_OP_BR_IFALSE: unary_branch
[reg] -> {
arm_test_reg_imm8(inst, ARM_CMP, $1, 0);
inst = output_branch(func, inst, ARM_CC_EQ, insn);
}
JIT_OP_BR_ITRUE: unary_branch
[reg] -> {
arm_test_reg_imm8(inst, ARM_CMP, $1, 0);
inst = output_branch(func, inst, ARM_CC_NE, insn);
}
JIT_OP_BR_IEQ: binary_branch
[reg, immu8] -> {
arm_test_reg_imm8(inst, ARM_CMP, $1, $2);
inst = output_branch(func, inst, ARM_CC_EQ, insn);
}
[reg, reg] -> {
arm_test_reg_reg(inst, ARM_CMP, $1, $2);
inst = output_branch(func, inst, ARM_CC_EQ, insn);
}
JIT_OP_BR_INE: binary_branch
[reg, immu8] -> {
arm_test_reg_imm8(inst, ARM_CMP, $1, $2);
inst = output_branch(func, inst, ARM_CC_NE, insn);
}
[reg, reg] -> {
arm_test_reg_reg(inst, ARM_CMP, $1, $2);
inst = output_branch(func, inst, ARM_CC_NE, insn);
}
JIT_OP_BR_ILT: binary_branch
[reg, immu8] -> {
arm_test_reg_imm8(inst, ARM_CMP, $1, $2);
inst = output_branch(func, inst, ARM_CC_LT, insn);
}
[reg, reg] -> {
arm_test_reg_reg(inst, ARM_CMP, $1, $2);
inst = output_branch(func, inst, ARM_CC_LT, insn);
}
JIT_OP_BR_ILT_UN: binary_branch
[reg, immu8] -> {
arm_test_reg_imm8(inst, ARM_CMP, $1, $2);
inst = output_branch(func, inst, ARM_CC_LT_UN, insn);
}
[reg, reg] -> {
arm_test_reg_reg(inst, ARM_CMP, $1, $2);
inst = output_branch(func, inst, ARM_CC_LT_UN, insn);
}
JIT_OP_BR_ILE: binary_branch
[reg, immu8] -> {
arm_test_reg_imm8(inst, ARM_CMP, $1, $2);
inst = output_branch(func, inst, ARM_CC_LE, insn);
}
[reg, reg] -> {
arm_test_reg_reg(inst, ARM_CMP, $1, $2);
inst = output_branch(func, inst, ARM_CC_LE, insn);
}
JIT_OP_BR_ILE_UN: binary_branch
[reg, immu8] -> {
arm_test_reg_imm8(inst, ARM_CMP, $1, $2);
inst = output_branch(func, inst, ARM_CC_LE_UN, insn);
}
[reg, reg] -> {
arm_test_reg_reg(inst, ARM_CMP, $1, $2);
inst = output_branch(func, inst, ARM_CC_LE_UN, insn);
}
JIT_OP_BR_IGT: binary_branch
[reg, immu8] -> {
arm_test_reg_imm8(inst, ARM_CMP, $1, $2);
inst = output_branch(func, inst, ARM_CC_GT, insn);
}
[reg, reg] -> {
arm_test_reg_reg(inst, ARM_CMP, $1, $2);
inst = output_branch(func, inst, ARM_CC_GT, insn);
}
JIT_OP_BR_IGT_UN: binary_branch
[reg, immu8] -> {
arm_test_reg_imm8(inst, ARM_CMP, $1, $2);
inst = output_branch(func, inst, ARM_CC_GT_UN, insn);
}
[reg, reg] -> {
arm_test_reg_reg(inst, ARM_CMP, $1, $2);
inst = output_branch(func, inst, ARM_CC_GT_UN, insn);
}
JIT_OP_BR_IGE: binary_branch
[reg, immu8] -> {
arm_test_reg_imm8(inst, ARM_CMP, $1, $2);
inst = output_branch(func, inst, ARM_CC_GE, insn);
}
[reg, reg] -> {
arm_test_reg_reg(inst, ARM_CMP, $1, $2);
inst = output_branch(func, inst, ARM_CC_GE, insn);
}
JIT_OP_BR_IGE_UN: binary_branch
[reg, immu8] -> {
arm_test_reg_imm8(inst, ARM_CMP, $1, $2);
inst = output_branch(func, inst, ARM_CC_GE_UN, insn);
}
[reg, reg] -> {
arm_test_reg_reg(inst, ARM_CMP, $1, $2);
inst = output_branch(func, inst, ARM_CC_GE_UN, insn);
}
/*
* Comparison opcodes.
*/
JIT_OP_ICMP: binary
[reg, immu8] -> {
arm_test_reg_imm8(inst, ARM_CMP, $1, $2);
arm_alu_reg_imm8_cond(inst, ARM_MOV, $1, 0, 1, ARM_CC_GT);
arm_alu_reg_imm8_cond(inst, ARM_MOV, $1, 0, 0, ARM_CC_LE);
arm_alu_reg_cond(inst, ARM_MVN, $1, $1, ARM_CC_LT);
}
[reg, reg] -> {
arm_test_reg_reg(inst, ARM_CMP, $1, $2);
arm_alu_reg_imm8_cond(inst, ARM_MOV, $1, 0, 1, ARM_CC_GT);
arm_alu_reg_imm8_cond(inst, ARM_MOV, $1, 0, 0, ARM_CC_LE);
arm_alu_reg_cond(inst, ARM_MVN, $1, $1, ARM_CC_LT);
}
JIT_OP_ICMP_UN: binary
[reg, immu8] -> {
arm_test_reg_imm8(inst, ARM_CMP, $1, $2);
arm_alu_reg_imm8_cond(inst, ARM_MOV, $1, 0, 1, ARM_CC_GT_UN);
arm_alu_reg_imm8_cond(inst, ARM_MOV, $1, 0, 0, ARM_CC_LE_UN);
arm_alu_reg_cond(inst, ARM_MVN, $1, $1, ARM_CC_LT_UN);
}
[reg, reg] -> {
arm_test_reg_reg(inst, ARM_CMP, $1, $2);
arm_alu_reg_imm8_cond(inst, ARM_MOV, $1, 0, 1, ARM_CC_GT_UN);
arm_alu_reg_imm8_cond(inst, ARM_MOV, $1, 0, 0, ARM_CC_LE_UN);
arm_alu_reg_cond(inst, ARM_MVN, $1, $1, ARM_CC_LT_UN);
}
JIT_OP_IEQ: binary
[reg, immu8] -> {
arm_test_reg_imm8(inst, ARM_CMP, $1, $2);
arm_alu_reg_imm8_cond(inst, ARM_MOV, $1, 0, 1, ARM_CC_EQ);
arm_alu_reg_imm8_cond(inst, ARM_MOV, $1, 0, 0, ARM_CC_NE);
}
[reg, reg] -> {
arm_test_reg_reg(inst, ARM_CMP, $1, $2);
arm_alu_reg_imm8_cond(inst, ARM_MOV, $1, 0, 1, ARM_CC_EQ);
arm_alu_reg_imm8_cond(inst, ARM_MOV, $1, 0, 0, ARM_CC_NE);
}
JIT_OP_INE: binary
[reg, immu8] -> {
arm_test_reg_imm8(inst, ARM_CMP, $1, $2);
arm_alu_reg_imm8_cond(inst, ARM_MOV, $1, 0, 1, ARM_CC_NE);
arm_alu_reg_imm8_cond(inst, ARM_MOV, $1, 0, 0, ARM_CC_EQ);
}
[reg, reg] -> {
arm_test_reg_reg(inst, ARM_CMP, $1, $2);
arm_alu_reg_imm8_cond(inst, ARM_MOV, $1, 0, 1, ARM_CC_NE);
arm_alu_reg_imm8_cond(inst, ARM_MOV, $1, 0, 0, ARM_CC_EQ);
}
JIT_OP_ILT: binary
[reg, immu8] -> {
arm_test_reg_imm8(inst, ARM_CMP, $1, $2);
arm_alu_reg_imm8_cond(inst, ARM_MOV, $1, 0, 1, ARM_CC_LT);
arm_alu_reg_imm8_cond(inst, ARM_MOV, $1, 0, 0, ARM_CC_GE);
}
[reg, reg] -> {
arm_test_reg_reg(inst, ARM_CMP, $1, $2);
arm_alu_reg_imm8_cond(inst, ARM_MOV, $1, 0, 1, ARM_CC_LT);
arm_alu_reg_imm8_cond(inst, ARM_MOV, $1, 0, 0, ARM_CC_GE);
}
JIT_OP_ILT_UN: binary
[reg, immu8] -> {
arm_test_reg_imm8(inst, ARM_CMP, $1, $2);
arm_alu_reg_imm8_cond(inst, ARM_MOV, $1, 0, 1, ARM_CC_LT_UN);
arm_alu_reg_imm8_cond(inst, ARM_MOV, $1, 0, 0, ARM_CC_GE_UN);
}
[reg, reg] -> {
arm_test_reg_reg(inst, ARM_CMP, $1, $2);
arm_alu_reg_imm8_cond(inst, ARM_MOV, $1, 0, 1, ARM_CC_LT_UN);
arm_alu_reg_imm8_cond(inst, ARM_MOV, $1, 0, 0, ARM_CC_GE_UN);
}
JIT_OP_ILE: binary
[reg, immu8] -> {
arm_test_reg_imm8(inst, ARM_CMP, $1, $2);
arm_alu_reg_imm8_cond(inst, ARM_MOV, $1, 0, 1, ARM_CC_LE);
arm_alu_reg_imm8_cond(inst, ARM_MOV, $1, 0, 0, ARM_CC_GT);
}
[reg, reg] -> {
arm_test_reg_reg(inst, ARM_CMP, $1, $2);
arm_alu_reg_imm8_cond(inst, ARM_MOV, $1, 0, 1, ARM_CC_LE);
arm_alu_reg_imm8_cond(inst, ARM_MOV, $1, 0, 0, ARM_CC_GT);
}
JIT_OP_ILE_UN: binary
[reg, immu8] -> {
arm_test_reg_imm8(inst, ARM_CMP, $1, $2);
arm_alu_reg_imm8_cond(inst, ARM_MOV, $1, 0, 1, ARM_CC_LE_UN);
arm_alu_reg_imm8_cond(inst, ARM_MOV, $1, 0, 0, ARM_CC_GT_UN);
}
[reg, reg] -> {
arm_test_reg_reg(inst, ARM_CMP, $1, $2);
arm_alu_reg_imm8_cond(inst, ARM_MOV, $1, 0, 1, ARM_CC_LE_UN);
arm_alu_reg_imm8_cond(inst, ARM_MOV, $1, 0, 0, ARM_CC_GT_UN);
}
JIT_OP_IGT: binary
[reg, immu8] -> {
arm_test_reg_imm8(inst, ARM_CMP, $1, $2);
arm_alu_reg_imm8_cond(inst, ARM_MOV, $1, 0, 1, ARM_CC_GT);
arm_alu_reg_imm8_cond(inst, ARM_MOV, $1, 0, 0, ARM_CC_LE);
}
[reg, reg] -> {
arm_test_reg_reg(inst, ARM_CMP, $1, $2);
arm_alu_reg_imm8_cond(inst, ARM_MOV, $1, 0, 1, ARM_CC_GT);
arm_alu_reg_imm8_cond(inst, ARM_MOV, $1, 0, 0, ARM_CC_LE);
}
JIT_OP_IGT_UN: binary
[reg, immu8] -> {
arm_test_reg_imm8(inst, ARM_CMP, $1, $2);
arm_alu_reg_imm8_cond(inst, ARM_MOV, $1, 0, 1, ARM_CC_GT_UN);
arm_alu_reg_imm8_cond(inst, ARM_MOV, $1, 0, 0, ARM_CC_LE_UN);
}
[reg, reg] -> {
arm_test_reg_reg(inst, ARM_CMP, $1, $2);
arm_alu_reg_imm8_cond(inst, ARM_MOV, $1, 0, 1, ARM_CC_GT_UN);
arm_alu_reg_imm8_cond(inst, ARM_MOV, $1, 0, 0, ARM_CC_LE_UN);
}
JIT_OP_IGE: binary
[reg, immu8] -> {
arm_test_reg_imm8(inst, ARM_CMP, $1, $2);
arm_alu_reg_imm8_cond(inst, ARM_MOV, $1, 0, 1, ARM_CC_GE);
arm_alu_reg_imm8_cond(inst, ARM_MOV, $1, 0, 0, ARM_CC_LT);
}
[reg, reg] -> {
arm_test_reg_reg(inst, ARM_CMP, $1, $2);
arm_alu_reg_imm8_cond(inst, ARM_MOV, $1, 0, 1, ARM_CC_GE);
arm_alu_reg_imm8_cond(inst, ARM_MOV, $1, 0, 0, ARM_CC_LT);
}
JIT_OP_IGE_UN: binary
[reg, immu8] -> {
arm_test_reg_imm8(inst, ARM_CMP, $1, $2);
arm_alu_reg_imm8_cond(inst, ARM_MOV, $1, 0, 1, ARM_CC_GE_UN);
arm_alu_reg_imm8_cond(inst, ARM_MOV, $1, 0, 0, ARM_CC_LT_UN);
}
[reg, reg] -> {
arm_test_reg_reg(inst, ARM_CMP, $1, $2);
arm_alu_reg_imm8_cond(inst, ARM_MOV, $1, 0, 1, ARM_CC_GE_UN);
arm_alu_reg_imm8_cond(inst, ARM_MOV, $1, 0, 0, ARM_CC_LT_UN);
}
Loading…
Cancel
Save