[Top][All Lists]
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[dotgnu-pnet-commits] libjit ChangeLog jit/Makefile.am jit/jit-rules-...
From: |
Aleksey Demakov |
Subject: |
[dotgnu-pnet-commits] libjit ChangeLog jit/Makefile.am jit/jit-rules-... |
Date: |
Thu, 05 Feb 2009 21:21:08 +0000 |
CVSROOT: /sources/dotgnu-pnet
Module name: libjit
Changes by: Aleksey Demakov <avd> 09/02/05 21:21:08
Modified files:
. : ChangeLog
jit : Makefile.am
Added files:
jit : jit-rules-arm.ins
Removed files:
jit : jit-rules-arm.sel
Log message:
replace ARM .sel file with .ins
CVSWeb URLs:
http://cvs.savannah.gnu.org/viewcvs/libjit/ChangeLog?cvsroot=dotgnu-pnet&r1=1.403&r2=1.404
http://cvs.savannah.gnu.org/viewcvs/libjit/jit/Makefile.am?cvsroot=dotgnu-pnet&r1=1.26&r2=1.27
http://cvs.savannah.gnu.org/viewcvs/libjit/jit/jit-rules-arm.ins?cvsroot=dotgnu-pnet&rev=1.1
http://cvs.savannah.gnu.org/viewcvs/libjit/jit/jit-rules-arm.sel?cvsroot=dotgnu-pnet&r1=1.16&r2=0
Patches:
Index: ChangeLog
===================================================================
RCS file: /sources/dotgnu-pnet/libjit/ChangeLog,v
retrieving revision 1.403
retrieving revision 1.404
diff -u -b -r1.403 -r1.404
--- ChangeLog 5 Feb 2009 21:06:43 -0000 1.403
+++ ChangeLog 5 Feb 2009 21:21:06 -0000 1.404
@@ -3,6 +3,8 @@
* jit/jit-rules.h; define JIT_BACKEND_ARM on ARM.
* tools/gen-apply.c: define PLATFORM_IS_ARM on ARM.
* include/jit/jit-arch-arm.h: add ARM arch header.
+ * jit/Makefile.am, jit/jit-rules-arm.ins, jit/jit-rules-arm.sel:
+ replace obsolete .sel file for ARM with .ins file.
2009-01-30 Peter Fristedt <address@hidden>
Kirill Kononenko <address@hidden>
Index: jit/Makefile.am
===================================================================
RCS file: /sources/dotgnu-pnet/libjit/jit/Makefile.am,v
retrieving revision 1.26
retrieving revision 1.27
diff -u -b -r1.26 -r1.27
--- jit/Makefile.am 29 May 2008 21:03:30 -0000 1.26
+++ jit/Makefile.am 5 Feb 2009 21:21:07 -0000 1.27
@@ -78,7 +78,7 @@
EXTRA_DIST = \
mklabel.sh \
jit-rules-alpha.ins \
- jit-rules-arm.sel \
+ jit-rules-arm.ins \
jit-rules-x86.ins \
jit-rules-x86-64.ins
@@ -100,11 +100,11 @@
$(top_builddir)/tools/gen-rules$(EXEEXT) $(srcdir)/jit-rules-x86.ins \
>jit-rules-x86.inc
-jit-rules-arm.lo: jit-rules-arm.slc
+jit-rules-arm.lo: jit-rules-arm.inc
-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
+jit-rules-arm.inc: jit-rules-arm.ins $(top_builddir)/tools/gen-rules$(EXEEXT)
+ $(top_builddir)/tools/gen-rules$(EXEEXT) $(srcdir)/jit-rules-arm.ins \
+ >jit-rules-arm.inc
jit-rules-alpha.lo: jit-rules-alpha.inc
@@ -121,6 +121,6 @@
CLEANFILES = \
jit-interp-labels.h \
jit-rules-alpha.inc \
- jit-rules-arm.slc \
+ jit-rules-arm.inc \
jit-rules-x86.inc \
jit-rules-x86-64.inc
Index: jit/jit-rules-arm.ins
===================================================================
RCS file: jit/jit-rules-arm.ins
diff -N jit/jit-rules-arm.ins
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ jit/jit-rules-arm.ins 5 Feb 2009 21:21:07 -0000 1.1
@@ -0,0 +1,1855 @@
+/* * jit-rules-arm.ins - Instruction selector for ARM.
+ *
+ * Copyright (C) 2004 Southern Storm Software, Pty Ltd.
+ * Copyright (C) 2008 Michele Tartara <address@hidden>
+ *
+ * This file is part of the libjit library.
+ *
+ * The libjit library is free software: you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public License
+ * as published by the Free Software Foundation, either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * The libjit library 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with the libjit library. If not, see
+ * <http://www.gnu.org/licenses/>.
+ */
+
+%inst_type arm_inst_buf
+
+/*
+ * Register classes
+ */
+%regclass reg arm_reg
+%regclass freg32 arm_freg32
+%regclass freg64 arm_freg64
+%lregclass lreg arm_lreg
+%regclass breg arm_breg
+
+/*
+ * Conversion opcodes.
+ */
+
+JIT_OP_TRUNC_SBYTE:
+ [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:
+ [reg] -> {
+ arm_alu_reg_imm8(inst, ARM_AND, $1, $1, 0xFF);
+ }
+
+JIT_OP_TRUNC_SHORT:
+ [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:
+ [reg] -> {
+ arm_shift_reg_imm8(inst, ARM_SHL, $1, $1, 16);
+ arm_shift_reg_imm8(inst, ARM_SHR, $1, $1, 16);
+ }
+
+JIT_OP_INT_TO_NFLOAT:
+ [=freg64, local, scratch freg32] -> {
+ //Load int from a local variable stored in memory
+ arm_load_membase_float(inst, $3, ARM_FP, $2, 0);
+ arm_convert_float_signed_integer_double(inst, $1, $3);
+ }
+ [=freg64, reg, scratch freg32] -> {
+ //The int value is in a register
+ arm_mov_float_reg(inst, $3, $2);
+ arm_convert_float_signed_integer_double(inst, $1, $3)
+ }
+
+JIT_OP_NFLOAT_TO_FLOAT32:
+ [=freg32, freg64] -> {
+ arm_convert_float_single_double(inst, $1, $2);
+ }
+
+JIT_OP_NFLOAT_TO_FLOAT64, JIT_OP_FLOAT64_TO_NFLOAT: copy
+ [freg64] -> {
+ /* Nothing to do: float64 and nfloat are the same thing on ARM
linux. Just copy the value */
+ }
+
+JIT_OP_FLOAT32_TO_NFLOAT:
+ [=freg64, freg32] -> {
+ arm_convert_float_double_single(inst, $1, $2);
+ }
+
+/*
+ * Arithmetic opcodes.
+ */
+
+JIT_OP_IADD:
+ [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:
+ [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:
+ [reg, immu8] -> {
+ /* Handle special cases of immediate multiplies */
+ switch($2)
+ {
+ case 0:
+ {
+ arm_mov_reg_imm8(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)
+ {
+ 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:
+ [reg] -> {
+ /* -x is the same as (0 - x) */
+ arm_alu_reg_imm8(inst, ARM_RSB, $1, $1, 0);
+ }
+
+JIT_OP_LADD:
+ [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:
+ [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:
+ [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):
+ [freg32, freg32] -> {
+ arm_alu_freg_freg_32(inst, ARM_FADD, $1, $1, $2);
+ }
+
+JIT_OP_FSUB (JIT_ARM_HAS_FLOAT_REGS):
+ [freg32, freg32] -> {
+ arm_alu_freg_freg_32(inst, ARM_FSUB, $1, $1, $2);
+ }
+
+JIT_OP_FMUL (JIT_ARM_HAS_FLOAT_REGS):
+ [freg32, freg32] -> {
+ arm_alu_freg_freg_32(inst, ARM_FMUL, $1, $1, $2);
+ }
+
+JIT_OP_FDIV (JIT_ARM_HAS_FLOAT_REGS):
+ [freg32, freg32] -> {
+ arm_alu_freg_freg_32(inst, ARM_FDIV, $1, $1, $2);
+ }
+
+JIT_OP_FNEG (JIT_ARM_HAS_FLOAT_REGS):
+ [freg32] -> {
+ arm_alu_freg_32(inst, ARM_MNF, $1, $1);
+ }
+
+JIT_OP_DADD, JIT_OP_NFADD (JIT_ARM_HAS_FLOAT_REGS):
+ [freg64, freg64] -> {
+ arm_alu_freg_freg(inst, ARM_FADD, $1, $1, $2);
+ }
+
+JIT_OP_DSUB, JIT_OP_NFSUB (JIT_ARM_HAS_FLOAT_REGS):
+ [freg64, freg64] -> {
+ arm_alu_freg_freg(inst, ARM_FSUB, $1, $1, $2);
+ }
+
+JIT_OP_DMUL, JIT_OP_NFMUL (JIT_ARM_HAS_FLOAT_REGS):
+ [freg64, freg64] -> {
+ arm_alu_freg_freg(inst, ARM_FMUL, $1, $1, $2);
+ }
+
+JIT_OP_DDIV, JIT_OP_NFDIV (JIT_ARM_HAS_FLOAT_REGS):
+ [freg64, freg64] -> {
+ arm_alu_freg_freg(inst, ARM_FDIV, $1, $1, $2);
+ }
+
+JIT_OP_DNEG, JIT_OP_NFNEG (JIT_ARM_HAS_FLOAT_REGS):
+ [freg64] -> {
+ arm_alu_freg(inst, ARM_MNF, $1, $1);
+ }
+
+/*
+ * Bitwise opcodes.
+ */
+
+JIT_OP_IAND:
+ [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:
+ [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:
+ [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:
+ [reg] -> {
+ /* MVN == "move not" */
+ arm_alu_reg(inst, ARM_MVN, $1, $1);
+ }
+
+JIT_OP_ISHL:
+ [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:
+ [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:
+ [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);
+ }
+
+JIT_OP_LAND:
+ [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:
+ [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:
+ [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:
+ [lreg] -> {
+ arm_alu_reg(inst, ARM_MVN, $1, $1);
+ arm_alu_reg(inst, ARM_MVN, %1, %1);
+ }
+
+/*
+ * Branch opcodes.
+ */
+
+JIT_OP_BR: branch /*spill_before*/
+ [] -> {
+ /* ARM_CC_AL == "always branch" */
+ output_branch(func, &inst, ARM_CC_AL, insn);
+
+ /* Flush the constant pool now, to minimize the probability that
+ it is accidentally flushed in the middle of a loop body */
+ jit_gen_save_inst_ptr(gen, inst);
+ flush_constants(gen, 1);
+ jit_gen_load_inst_ptr(gen, inst);
+ }
+
+JIT_OP_BR_IFALSE: branch
+ [reg] -> {
+ arm_test_reg_imm8(inst, ARM_CMP, $1, 0);
+ output_branch(func, &inst, ARM_CC_EQ, insn);
+ }
+
+JIT_OP_BR_ITRUE: branch
+ [reg] -> {
+ arm_test_reg_imm8(inst, ARM_CMP, $1, 0);
+ output_branch(func, &inst, ARM_CC_NE, insn);
+ }
+
+JIT_OP_BR_IEQ: branch
+ [reg, immu8] -> {
+ arm_test_reg_imm8(inst, ARM_CMP, $1, $2);
+ output_branch(func, &inst, ARM_CC_EQ, insn);
+ }
+ [reg, reg] -> {
+ arm_test_reg_reg(inst, ARM_CMP, $1, $2);
+ output_branch(func, &inst, ARM_CC_EQ, insn);
+ }
+
+JIT_OP_BR_INE: branch
+ [reg, immu8] -> {
+ arm_test_reg_imm8(inst, ARM_CMP, $1, $2);
+ output_branch(func, &inst, ARM_CC_NE, insn);
+ }
+ [reg, reg] -> {
+ arm_test_reg_reg(inst, ARM_CMP, $1, $2);
+ output_branch(func, &inst, ARM_CC_NE, insn);
+ }
+
+JIT_OP_BR_ILT: branch
+ [reg, immu8] -> {
+ arm_test_reg_imm8(inst, ARM_CMP, $1, $2);
+ output_branch(func, &inst, ARM_CC_LT, insn);
+ }
+ [reg, reg] -> {
+ arm_test_reg_reg(inst, ARM_CMP, $1, $2);
+ output_branch(func, &inst, ARM_CC_LT, insn);
+ }
+
+JIT_OP_BR_ILT_UN: branch
+ [reg, immu8] -> {
+ arm_test_reg_imm8(inst, ARM_CMP, $1, $2);
+ output_branch(func, &inst, ARM_CC_LT_UN, insn);
+ }
+ [reg, reg] -> {
+ arm_test_reg_reg(inst, ARM_CMP, $1, $2);
+ output_branch(func, &inst, ARM_CC_LT_UN, insn);
+ }
+
+JIT_OP_BR_ILE: branch
+ [reg, immu8] -> {
+ arm_test_reg_imm8(inst, ARM_CMP, $1, $2);
+ output_branch(func, &inst, ARM_CC_LE, insn);
+ }
+ [reg, reg] -> {
+ arm_test_reg_reg(inst, ARM_CMP, $1, $2);
+ output_branch(func, &inst, ARM_CC_LE, insn);
+ }
+
+JIT_OP_BR_ILE_UN: branch
+ [reg, immu8] -> {
+ arm_test_reg_imm8(inst, ARM_CMP, $1, $2);
+ output_branch(func, &inst, ARM_CC_LE_UN, insn);
+ }
+ [reg, reg] -> {
+ arm_test_reg_reg(inst, ARM_CMP, $1, $2);
+ output_branch(func, &inst, ARM_CC_LE_UN, insn);
+ }
+
+JIT_OP_BR_IGT: branch
+ [reg, immu8] -> {
+ arm_test_reg_imm8(inst, ARM_CMP, $1, $2);
+ output_branch(func, &inst, ARM_CC_GT, insn);
+ }
+ [reg, reg] -> {
+ arm_test_reg_reg(inst, ARM_CMP, $1, $2);
+ output_branch(func, &inst, ARM_CC_GT, insn);
+ }
+
+JIT_OP_BR_IGT_UN: branch
+ [reg, immu8] -> {
+ arm_test_reg_imm8(inst, ARM_CMP, $1, $2);
+ output_branch(func, &inst, ARM_CC_GT_UN, insn);
+ }
+ [reg, reg] -> {
+ arm_test_reg_reg(inst, ARM_CMP, $1, $2);
+ output_branch(func, &inst, ARM_CC_GT_UN, insn);
+ }
+
+JIT_OP_BR_IGE: branch
+ [reg, immu8] -> {
+ arm_test_reg_imm8(inst, ARM_CMP, $1, $2);
+ output_branch(func, &inst, ARM_CC_GE, insn);
+ }
+ [reg, reg] -> {
+ arm_test_reg_reg(inst, ARM_CMP, $1, $2);
+ output_branch(func, &inst, ARM_CC_GE, insn);
+ }
+
+JIT_OP_BR_IGE_UN: branch
+ [reg, immu8] -> {
+ arm_test_reg_imm8(inst, ARM_CMP, $1, $2);
+ output_branch(func, &inst, ARM_CC_GE_UN, insn);
+ }
+ [reg, reg] -> {
+ arm_test_reg_reg(inst, ARM_CMP, $1, $2);
+ output_branch(func, &inst, ARM_CC_GE_UN, insn);
+ }
+
+/*
+ * Comparison opcodes.
+ */
+
+JIT_OP_ICMP:
+ [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:
+ [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:
+ [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:
+ [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:
+ [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:
+ [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:
+ [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:
+ [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:
+ [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:
+ [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:
+ [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:
+ [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);
+ }
+
+/*
+ * Pointer check opcodes.
+ */
+
+JIT_OP_CHECK_NULL: note
+ [reg] -> {
+ arm_test_reg_imm8(inst, ARM_CMP, $1, 0);
+ 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, jit_function_to_closure(func));
+ }
+
+JIT_OP_CALL_TAIL:
+ [] -> {
+ jit_function_t func = (jit_function_t)(insn->dest);
+ arm_pop_frame_tail(inst, 0);
+ arm_jump(inst, jit_function_to_closure(func));
+ }
+
+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:
+ [] -> {
+ jump_to_epilog(gen, &inst, block);
+ }
+
+JIT_OP_RETURN_INT: /*unary_branch*/
+ [reg] -> {
+ int cpu_reg = $1;
+ if(cpu_reg != ARM_R0)
+ {
+ arm_mov_reg_reg(inst, ARM_R0, cpu_reg);
+ }
+ jump_to_epilog(gen, &inst, block);
+ }
+
+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)
+ {
+ arm_mov_reg_reg(inst, ARM_R0, $1);
+ arm_mov_reg_reg(inst, ARM_R1, %1);
+ }
+ jump_to_epilog(gen, &inst, block);
+ }
+
+JIT_OP_RETURN_FLOAT32 (JIT_ARM_HAS_FLOAT_REGS): branch
+ [freg32, clobber("r0")] -> {
+ arm_mov_reg_float(inst, ARM_R0, $1);
+ jump_to_epilog(gen, &inst, block);
+ }
+
+JIT_OP_RETURN_FLOAT32 (!JIT_ARM_HAS_FLOAT_REGS): manual
+ [] -> {
+ arm_inst_buf inst;
+ _jit_regs_spill_all(gen);
+ _jit_gen_fix_value(insn->value1);
+ jit_gen_load_inst_ptr(gen, inst);
+ if(insn->value1->is_constant)
+ {
+ mov_reg_imm
+ (gen, &inst, ARM_R0, ((int
*)(insn->value1->address))[0]);
+ }
+ else
+ {
+ arm_load_membase(inst, ARM_R0, ARM_FP,
insn->value1->frame_offset);
+ }
+ jump_to_epilog(gen, &inst, block);
+ jit_gen_save_inst_ptr(gen, inst);
+ }
+
+JIT_OP_RETURN_FLOAT64, JIT_OP_RETURN_NFLOAT
+ (JIT_ARM_HAS_FLOAT_REGS): branch
+ [freg64, clobber("r0", "r1")] -> {
+ arm_mov_reg_reg_double(inst,ARM_R0,ARM_R1, $1);
+ jump_to_epilog(gen, &inst, block);
+ }
+
+JIT_OP_RETURN_FLOAT64, JIT_OP_RETURN_NFLOAT (!JIT_ARM_HAS_FLOAT_REGS): manual
+ [] -> {
+ arm_inst_buf inst;
+ _jit_regs_spill_all(gen);
+ _jit_gen_fix_value(insn->value1);
+ jit_gen_load_inst_ptr(gen, inst);
+ if(insn->value1->is_constant)
+ {
+ mov_reg_imm
+ (gen, &inst, ARM_R0, ((int
*)(insn->value1->address))[0]);
+ mov_reg_imm
+ (gen, &inst, ARM_R1, ((int
*)(insn->value1->address))[1]);
+ }
+ else
+ {
+ arm_load_membase(inst, ARM_R0, ARM_FP,
insn->value1->frame_offset);
+ arm_load_membase(inst, ARM_R1, ARM_FP,
+
insn->value1->frame_offset + 4);
+ }
+ jump_to_epilog(gen, &inst, block);
+ jit_gen_save_inst_ptr(gen, inst);
+ }
+
+JIT_OP_RETURN_SMALL_STRUCT: note
+ [reg, imm, clobber("r0", "r1")] -> {
+ //$1: address of the struct to be returned
+ //$2: size of the struct to be returned
+
+ //Prevent the accidental overwriting of the address
+ int temp_reg = $1;
+ if(temp_reg < 3)
+ {
+ arm_mov_reg_reg(inst, ARM_WORK, temp_reg);
+ temp_reg = ARM_WORK;
+ }
+
+ //Copy the struct to the return register in a way that's
appropriate to its size
+ switch($2)
+ {
+ case 1:
+ arm_load_membase_byte(inst, ARM_R0, temp_reg, 0);
+ break;
+
+ case 2:
+ arm_load_membase_ushort(inst, ARM_R0, temp_reg, 0);
+ break;
+
+ case 3:
+ arm_load_membase_ushort(inst, ARM_R0, temp_reg, 0);
+ arm_load_membase_byte(inst, ARM_R1, temp_reg, 2);
+ arm_shift_reg_imm8(inst, ARM_SHL, ARM_R1, ARM_R1, 16);
+ arm_alu_reg_reg(inst, ARM_ORR, ARM_R0, ARM_R0, ARM_R1);
+ break;
+
+ case 4:
+ arm_load_membase(inst, ARM_R0, temp_reg, 0);
+ break;
+
+ /*TODO: is this the right way to return a struct > 4 bytes?
+ * Or should it be returned by address? Look at the Procedure
Call Standard!
+ */
+
+ case 5:
+ arm_load_membase(inst, ARM_R0, temp_reg, 0);
+ arm_load_membase_byte(inst, ARM_R1, temp_reg, 4);
+ break;
+
+ case 6:
+ arm_load_membase(inst, ARM_R0, temp_reg, 0);
+ arm_load_membase_ushort(inst, ARM_R1, temp_reg, 4);
+ break;
+
+ case 7:
+ arm_load_membase(inst, ARM_R0, temp_reg, 0);
+ arm_load_membase_ushort(inst, ARM_R1, temp_reg, 4);
+ arm_load_membase_byte(inst, ARM_R2, temp_reg, 6);
+ arm_shift_reg_imm8(inst, ARM_SHL, ARM_R2, ARM_R2, 16);
+ arm_alu_reg_reg(inst, ARM_ORR, ARM_R1, ARM_R1, ARM_R2);
+ break;
+
+ case 8:
+ arm_load_membase(inst, ARM_R0, temp_reg, 0);
+ arm_load_membase(inst, ARM_R1, temp_reg, 4);
+ break;
+ }
+
+ 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)
+ {
+ 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();
+ }
+
+/*
+ * Exception handling
+ */
+JIT_OP_THROW: branch
+ [reg] -> {
+
+ arm_push_reg(inst, $1);
+ if(func->builder->setjmp_value != 0)
+ {
+ /* We have a "setjmp" block in the current function,
+ so we must record the location of the throw first */
+ jit_nint pc_offset;
+
+ _jit_gen_fix_value(func->builder->setjmp_value);
+
+ pc_offset = func->builder->setjmp_value->frame_offset +
+ jit_jmp_catch_pc_offset;
+
+ if(func->builder->position_independent)
+ {
+ arm_call_imm(inst, 0);
+ arm_pop_membase(inst, ARM_FP, pc_offset);
+ }
+ else
+ {
+ int pc = (int) (unsigned char *)
arm_inst_get_posn(inst);
+ arm_mov_membase_imm(inst, ARM_FP, pc_offset,
pc, 4, ARM_WORK);
+ }
+ }
+ arm_call(inst, (void *)jit_exception_throw);
+ }
+
+JIT_OP_LOAD_PC:
+[=reg] -> {
+ if(func->builder->position_independent)
+ {
+ arm_call_imm(inst, 0);
+ arm_pop_reg(inst, $1);
+ }
+ else
+ {
+ int pc = inst.current;
+ mov_reg_imm(gen, &inst, $1, pc);
+ }
+}
+
+JIT_OP_ENTER_FINALLY:
+[] -> { /*
+ * The return address is in the link register
+ * We must save it on the stack in case it will be overwritten by the
content
+ * of the "finally" block.
+ * In order to respect the ABI of the ARM architecture, that prescribes
an 8-byte
+ * alignment for the stack at a public interface, we save the value
twice,
+ * in order to move the current SP by 8 bytes
+ * (we could have just saved the value once and then moved the SP by 4
bytes)
+ */
+ arm_push_reg(inst, ARM_LINK);
+ arm_push_reg(inst, ARM_LINK);
+}
+
+JIT_OP_LEAVE_FINALLY: branch
+[] -> {
+ /* The "finally" return address is on the stack (twice, just for
padding)*/
+ arm_pop_reg(inst, ARM_LINK);
+ arm_pop_reg(inst, ARM_LINK);
+ arm_return(inst);
+}
+
+JIT_OP_CALL_FINALLY: branch
+[] -> {
+ jit_block_t block;
+ int offset;
+ block = jit_block_from_label(func, (jit_label_t)(insn->dest));
+ if(!block)
+ {
+ return;
+ }
+ if(arm_inst_get_posn(inst) >= arm_inst_get_limit(inst))
+ {
+ /* The buffer has overflowed, so don't worry about fixups */
+ return;
+ }
+ if(block->address)
+ {
+ /* We already know the address of the block */
+ arm_call(inst, block->address);
+ }
+ else
+ {
+ /* Output a placeholder and record on the block's fixup list */
+ if(block->fixup_list)
+ {
+ offset = (int)(((unsigned char
*)arm_inst_get_posn(inst)) -
+ ((unsigned char *)(block->fixup_list)));
+ }
+ else
+ {
+ offset = 0;
+ }
+ arm_call_imm(inst, offset);
+ block->fixup_list = (void *)(arm_inst_get_posn(inst) - 1);
+ }
+}
+
+JIT_OP_ADDRESS_OF_LABEL:
+[=reg] -> {
+ block = jit_block_from_label(func, (jit_label_t)(insn->value1));
+ if(func->builder->position_independent)
+ {
+ /* TODO */
+ TODO();
+ }
+ else
+ {
+ if(block->address)
+ {
+ mov_reg_imm(gen, &inst, $1, block->address);
+ }
+ else
+ {
+ /* Output a placeholder and record on the block's fixup
list */
+ mov_reg_imm(gen, &inst, $1,
(int)(block->fixup_absolute_list));
+ block->fixup_absolute_list = (void
*)(inst.current - 1);
+ }
+ }
+}
+
+/*
+ * Data manipulation.
+ */
+
+JIT_OP_COPY_LOAD_SBYTE:
+ [reg] -> {}
+
+JIT_OP_COPY_LOAD_UBYTE:
+ [reg] -> {}
+
+JIT_OP_COPY_LOAD_SHORT:
+ [reg] -> {}
+
+JIT_OP_COPY_LOAD_USHORT:
+ [reg] -> {}
+
+JIT_OP_COPY_INT: copy
+ [=local, imm, scratch reg] -> {
+ arm_mov_membase_imm(inst, ARM_FP, $1, $2, 4, $3);
+ }
+ [reg] -> {}
+
+
+JIT_OP_COPY_LONG: copy
+ [lreg] -> {}
+
+JIT_OP_COPY_FLOAT32 (JIT_ARM_HAS_FLOAT_REGS): copy
+ [freg32] -> {}
+
+JIT_OP_COPY_FLOAT32 (!JIT_ARM_HAS_FLOAT_REGS): 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]);
+ }
+ 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);
+ jit_gen_save_inst_ptr(gen, inst);
+ }
+
+JIT_OP_COPY_FLOAT64, JIT_OP_COPY_NFLOAT (JIT_ARM_HAS_FLOAT_REGS): copy
+ [freg64] -> {}
+
+JIT_OP_COPY_FLOAT64, JIT_OP_COPY_NFLOAT (!JIT_ARM_HAS_FLOAT_REGS): 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_STRUCT:
+ [=frame, frame, scratch reg] -> {
+ inst = memory_copy(gen, inst, ARM_FP, $1, ARM_FP, $2,
+
jit_type_get_size(jit_value_get_type(insn->dest)), $3);
+ }
+
+JIT_OP_COPY_STORE_BYTE: manual
+ [] -> {
+ arm_inst_buf inst;
+ int reg;
+ _jit_regs_force_out(gen, insn->dest, 1);
+ _jit_gen_fix_value(insn->dest);
+ reg = _jit_regs_load_value
+ (gen, insn->value1, 0,
+ (insn->flags & (JIT_INSN_VALUE1_NEXT_USE |
+
JIT_INSN_VALUE1_LIVE)));
+ jit_gen_load_inst_ptr(gen, inst);
+ arm_store_membase_byte(inst, _jit_reg_info[reg].cpu_reg,
+ ARM_FP,
insn->dest->frame_offset);
+ jit_gen_save_inst_ptr(gen, inst);
+ }
+
+JIT_OP_COPY_STORE_SHORT: manual
+ [] -> {
+ arm_inst_buf inst;
+ int reg;
+ _jit_regs_force_out(gen, insn->dest, 1);
+ _jit_gen_fix_value(insn->dest);
+ reg = _jit_regs_load_value
+ (gen, insn->value1, 1,
+ (insn->flags & (JIT_INSN_VALUE1_NEXT_USE |
+
JIT_INSN_VALUE1_LIVE)));
+ jit_gen_load_inst_ptr(gen, inst);
+ arm_store_membase_short(inst, _jit_reg_info[reg].cpu_reg,
+ ARM_FP,
insn->dest->frame_offset);
+ jit_gen_save_inst_ptr(gen, inst);
+ //_jit_regs_free_reg(gen, reg, 1); //TODO: check if it's needed
+ }
+
+JIT_OP_ADDRESS_OF:
+ [=reg, frame] -> {
+ if($2 > 0)
+ {
+ arm_alu_reg_imm(inst, ARM_ADD, $1, ARM_FP, $2);
+ }
+ else if($2 < 0)
+ {
+ arm_alu_reg_imm(inst, ARM_SUB, $1, ARM_FP, -$2);
+ }
+ else
+ {
+ arm_mov_reg_reg(inst, $1, ARM_FP);
+ }
+
+ }
+
+/*
+ * Stack pushes and pops.
+ */
+
+JIT_OP_INCOMING_REG, JIT_OP_RETURN_REG: note
+ [reg] -> {
+ /*
+ * This rule does nothing itself. Also at this point
+ * the value is supposed to be already in the register
+ * so the "reg" pattern does not load it either. But
+ * it allows the allocator to check the liveness flags
+ * and free the register if the value is dead.
+ */
+ }
+
+JIT_OP_PUSH_INT: note
+ [reg] -> {
+ arm_push_reg(inst, $1);
+ }
+
+JIT_OP_PUSH_LONG: note
+ [lreg] -> {
+ arm_push_reg(inst, %1);
+ arm_push_reg(inst, $1);
+ gen->stack_changed=1;
+ }
+
+JIT_OP_PUSH_FLOAT32 (JIT_ARM_HAS_FLOAT_REGS): note
+ [freg32] -> {
+ arm_push_reg_float32(inst, $1);
+ }
+
+JIT_OP_PUSH_FLOAT32 (!JIT_ARM_HAS_FLOAT_REGS): 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]);
+ }
+ else
+ {
+ 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_FLOAT64, JIT_OP_PUSH_NFLOAT (JIT_ARM_HAS_FLOAT_REGS): note
+ [freg64] -> {
+ arm_push_reg_float64(inst, $1);
+ }
+
+JIT_OP_PUSH_FLOAT64, JIT_OP_PUSH_NFLOAT (!JIT_ARM_HAS_FLOAT_REGS): 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_STRUCT: /*unary_note*/
+ [reg] -> {
+ /* TODO */
+ TODO();
+ }
+
+JIT_OP_POP_STACK:
+ [] -> {
+ arm_alu_reg_imm(inst, ARM_ADD, ARM_SP, ARM_SP,
insn->value1->address);
+ }
+
+JIT_OP_FLUSH_SMALL_STRUCT:
+ [] -> {
+ jit_nuint size;
+ jit_nint offset;
+ _jit_gen_fix_value(insn->value1);
+ size = jit_type_get_size(jit_value_get_type(insn->value1));
+ offset = insn->value1->frame_offset;
+ switch(size)
+ {
+ case 1:
+ {
+ arm_store_membase_byte(inst, ARM_R0, ARM_FP,
offset);
+ }
+ break;
+
+ case 2:
+ {
+ arm_store_membase_short(inst, ARM_R0, ARM_FP,
offset);
+ }
+ break;
+
+ case 3:
+ {
+ arm_mov_reg_reg(inst, ARM_R1, ARM_R0);
+ arm_store_membase_short(inst, ARM_R0, ARM_FP,
offset);
+ arm_shift_reg_imm8(inst, ARM_SHR, ARM_R0,
ARM_R1, 16);
+ arm_store_membase_byte(inst, ARM_R0, ARM_FP,
offset + 2);
+ }
+ break;
+
+ case 4:
+ {
+ arm_store_membase(inst, ARM_R0, ARM_FP, offset);
+ }
+ break;
+
+ case 5:
+ {
+ arm_store_membase(inst, ARM_R0, ARM_FP, offset);
+ arm_store_membase_byte(inst, ARM_R1, ARM_FP,
offset + 4);
+ }
+ break;
+
+ case 6:
+ {
+ arm_store_membase(inst, ARM_R0, ARM_FP, offset);
+ arm_store_membase_short(inst, ARM_R1, ARM_FP,
offset + 4);
+ }
+ break;
+
+ case 7:
+ {
+ arm_store_membase(inst, ARM_R0, ARM_FP, offset);
+ arm_mov_reg_reg(inst, ARM_R2, ARM_R1);
+ arm_store_membase_short(inst, ARM_R1, ARM_FP,
offset + 4);
+ arm_shift_reg_imm8(inst, ARM_SHR, ARM_R1,
ARM_R2, 16);
+ arm_store_membase_byte(inst, ARM_R1, ARM_FP,
offset + 6);
+ }
+ break;
+
+ case 8:
+ {
+ arm_store_membase(inst, ARM_R0, ARM_FP, offset);
+ arm_store_membase(inst, ARM_R1, ARM_FP, offset
+ 4);
+ }
+ break;
+ }
+ }
+
+JIT_OP_SET_PARAM_INT: note
+ [imm, imm] -> {
+ arm_mov_membase_imm(inst, ARM_SP, $2, $1, 4, ARM_WORK);
+ }
+ [reg, imm] -> {
+ arm_mov_membase_reg(inst, ARM_SP, $2, $1, 4);
+ }
+
+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*/
+ [freg32] -> {
+ arm_store_membase_float32(inst, $1, ARM_SP,
insn->value2->address);
+ }
+
+JIT_OP_SET_PARAM_FLOAT32 (!JIT_ARM_HAS_FLOAT_REGS): 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);
+ }
+ else
+ {
+ arm_load_membase(inst, ARM_WORK, ARM_FP,
+
insn->value1->frame_offset);
+ arm_store_membase
+ (inst, ARM_WORK, ARM_SP, insn->value2->address);
+ }
+ jit_gen_save_inst_ptr(gen, inst);
+ }
+
+JIT_OP_SET_PARAM_FLOAT64, JIT_OP_SET_PARAM_NFLOAT
+ (JIT_ARM_HAS_FLOAT_REGS): /*unary_note*/
+ [freg64] -> {
+ arm_store_membase_float64(inst, $1, ARM_SP,
insn->value2->address);
+ }
+
+JIT_OP_SET_PARAM_FLOAT64, JIT_OP_SET_PARAM_NFLOAT
+ (!JIT_ARM_HAS_FLOAT_REGS): 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_STRUCT: note
+[reg, imm, scratch reg] -> {
+ /* Handle arbitrary-sized structures */
+ jit_nint offset = jit_value_get_nint_constant(insn->dest);
+ inst = memory_copy(gen, inst, ARM_SP, offset, $1, 0, $2, $3);
+}
+
+/*
+ * Pointer-relative loads and stores.
+ */
+JIT_OP_LOAD_RELATIVE_SBYTE:
+ [reg] -> {
+ arm_load_membase_sbyte(inst, $1, $1, insn->value2->address);
+ }
+
+JIT_OP_LOAD_RELATIVE_UBYTE:
+ [reg] -> {
+ arm_load_membase_byte(inst, $1, $1, insn->value2->address);
+ }
+
+JIT_OP_LOAD_RELATIVE_SHORT:
+ [reg] -> {
+ arm_load_membase_short(inst, $1, $1, insn->value2->address);
+ }
+
+JIT_OP_LOAD_RELATIVE_USHORT:
+ [reg] -> {
+ arm_load_membase_ushort(inst, $1, $1, insn->value2->address);
+ }
+
+JIT_OP_LOAD_RELATIVE_INT:
+ [reg] -> {
+ arm_load_membase(inst, $1, $1, insn->value2->address);
+ }
+
+JIT_OP_LOAD_RELATIVE_LONG:
+ [=lreg, reg, imm] -> {
+ if($1 == $2)
+ {
+ arm_mov_reg_membase(inst, %1, $2, $3 + 4, 4);
+ arm_mov_reg_membase(inst, $1, $2, $3, 4);
+ }
+ else
+ {
+ arm_mov_reg_membase(inst, $1, $2, $3, 4);
+ arm_mov_reg_membase(inst, %1, $2, $3 + 4, 4);
+ }
+ }
+
+JIT_OP_LOAD_RELATIVE_FLOAT32:
+[=freg32, reg, imm] -> {
+ arm_fld_membase(inst, $1, $2, $3, 0);
+}
+
+JIT_OP_LOAD_RELATIVE_FLOAT64:
+[=freg64, reg, imm] -> {
+ arm_fld_membase(inst, $1, $2, $3, 1);
+}
+
+JIT_OP_LOAD_RELATIVE_NFLOAT: manual
+ [] -> {
+ /* TODO */
+ TODO();
+ abort();
+ }
+
+JIT_OP_LOAD_RELATIVE_STRUCT: more_space
+[=frame, reg, imm, scratch reg] -> {
+ inst = memory_copy(gen, inst, ARM_FP, $1, $2, $3,
jit_type_get_size(jit_value_get_type(insn->dest)), $4);
+}
+
+JIT_OP_STORE_RELATIVE_BYTE: ternary
+[imm, imm, imm, scratch reg] -> {
+ arm_mov_mem_imm(inst, $1 + $3, $2, 1, $4);
+}
+[imm, breg, imm] -> {
+ arm_mov_mem_reg(inst, $1 + $3, $2, 1);
+}
+[reg, imm, imm] -> {
+ arm_mov_membase_imm(inst, $1, $3, $2, 1, ARM_WORK);
+}
+[reg, breg, imm] -> {
+ arm_mov_membase_reg(inst, $1, $3, $2, 1);
+}
+
+JIT_OP_STORE_RELATIVE_SHORT: ternary
+[imm, imm, imm, scratch reg] -> {
+ arm_mov_mem_imm(inst, $1 + $3, $2, 2, $4);
+}
+[imm, reg, imm] -> {
+ arm_mov_mem_reg(inst, $1 + $3, $2, 2);
+}
+[reg, imm, imm] -> {
+ arm_mov_membase_imm(inst, $1, $3, $2, 2, ARM_WORK);
+}
+[reg, reg, imm] -> {
+ arm_mov_membase_reg(inst, $1, $3, $2, 2);
+}
+
+JIT_OP_STORE_RELATIVE_INT: ternary
+ [imm, imm, imm, scratch reg] -> {
+ arm_mov_mem_imm(inst, $1 + $3, $2, 4, $4);
+ }
+ [imm, reg, imm] -> {
+ arm_mov_mem_reg(inst, $1 + $3, $2, 4);
+ }
+ [reg, imm, imm] -> {
+ arm_mov_membase_imm(inst, $1, $3, $2, 4, ARM_WORK);
+ }
+ [reg, reg, imm] -> {
+ arm_mov_membase_reg(inst, $1, $3, $2, 4);
+ }
+
+JIT_OP_STORE_RELATIVE_LONG: ternary
+ [reg, imm, imm] -> {
+ arm_mov_membase_imm(inst, $1, $3, *(int *)($2), 4, ARM_WORK);
+ arm_mov_membase_imm(inst, $1, $3 + 4, *(int *)($2 + 4), 4,
ARM_WORK);
+ }
+ [reg, local, imm, scratch reg] -> {
+ arm_mov_reg_membase(inst, $4, ARM_FP, $2, 4);
+ arm_mov_membase_reg(inst, $1, $3, $4, 4);
+ arm_mov_reg_membase(inst, $4, ARM_FP, $2 + 4, 4);
+ arm_mov_membase_reg(inst, $1, $3 + 4, $4, 4);
+ }
+ [reg, lreg, imm] -> {
+ arm_mov_membase_reg(inst, $1, $3, $2, 4);
+ arm_mov_membase_reg(inst, $1, $3 + 4, %2, 4);
+ }
+
+JIT_OP_STORE_RELATIVE_FLOAT32: ternary
+ [reg, imm, imm] -> {
+ arm_mov_membase_imm(inst, $1, $3, ((int *)($2))[0], 4,
ARM_WORK);
+ }
+ [reg, freg32, imm] -> {
+ arm_store_membase_float32(inst, $2, $1, $3);
+ }
+
+JIT_OP_STORE_RELATIVE_FLOAT64: ternary
+ [reg, imm, imm, scratch reg] -> {
+ arm_mov_membase_imm(inst, $1, $3, ((int *)($2))[0], 4, $4);
+ arm_mov_membase_imm(inst, $1, $3 + 4, ((int *)($2))[1], 4, $4);
+ }
+ [reg, freg64, imm] -> {
+ arm_store_membase_float64(inst, $2, $1, $3);
+ }
+
+JIT_OP_STORE_RELATIVE_NFLOAT: manual
+ [] -> {
+ /* TODO */
+ TODO();
+ abort();
+ }
+
+JIT_OP_STORE_RELATIVE_STRUCT: manual
+[] -> {
+ arm_inst_buf inst;
+ int reg = _jit_regs_load_value(gen, insn->dest, 0,
+ (insn->flags & (JIT_INSN_DEST_NEXT_USE |
+ JIT_INSN_DEST_LIVE)));
+ _jit_regs_spill_all(gen);
+ _jit_gen_fix_value(insn->value1);
+ jit_gen_load_inst_ptr(gen, inst);
+ if(!jit_cache_check_for_n(&(gen->posn), 128))
+ {
+ jit_cache_mark_full(&(gen->posn));
+ return;
+ }
+ reg = _jit_reg_info[reg].cpu_reg;
+ inst = memory_copy(gen, inst, reg, (int)(insn->value2->address),
+ ARM_FP, insn->value1->frame_offset,
+ jit_type_get_size(jit_value_get_type(insn->value1)),
-1);
+ jit_gen_save_inst_ptr(gen, inst);
+}
+
+JIT_OP_ADD_RELATIVE:
+ [reg] -> {
+ if(insn->value2->address != 0)
+ {
+ arm_alu_reg_imm(inst, ARM_ADD, $1, $1,
insn->value2->address);
+ }
+ }
+
+/*
+* Array element loads and stores.
+*/
+JIT_OP_LOAD_ELEMENT_UBYTE:
+[=reg, reg, reg] -> {
+ arm_widen_memindex(inst, $1, $2, 0, $3, 0, 0, 0);
+}
+
+JIT_OP_LOAD_ELEMENT_USHORT:
+[=reg, reg, reg] -> {
+ arm_widen_memindex(inst, $1, $2, 0, $3, 1, 0, 1);
+}
+
+JIT_OP_LOAD_ELEMENT_INT:
+[=reg, reg, reg] -> {
+ /* The last parameter is unimportant: it's not used,
+ since the displacement (4th param) is 0 */
+ arm_mov_reg_memindex(inst, $1, $2, 0, $3, 2, 4, 0);
+}
+
+JIT_OP_LOAD_ELEMENT_LONG:
+[=lreg, reg, reg, scratch reg, scratch reg] -> {
+ //$1=destination long register (1-st word, LSB)
+ //%1=destination long register (2-nd word, MSB)
+ //$2=base register
+ //$3=index register
+ //$4=scratch register for arm_mov_reg_memindex
+ //$5=scratch register for overwriting prevention
+
+ assert($2 != $3);
+
+ int basereg=$2;
+ int indexreg=$3;
+
+ //Write the 1-st word
+ if($1 == basereg)
+ {
+ //Prevent base reg from being overwritten
+ arm_mov_reg_reg(inst, $5, basereg);
+ basereg=$5;
+ }
+ else if ($1 == indexreg)
+ {
+ //Prevent index reg from being overwritten
+ arm_mov_reg_reg(inst, $5, indexreg);
+ indexreg=$5;
+ }
+ arm_mov_reg_memindex(inst, $1, basereg, 0, indexreg, 3, 4, $4);
+
+ //Write the 2-nd word
+ arm_mov_reg_memindex(inst, %1, basereg, 4, indexreg, 3, 4, $4);
+}
+
+JIT_OP_LOAD_ELEMENT_FLOAT64:
+[=freg64, reg, reg, scratch reg] -> {
+ arm_fld_memindex(inst, $1, $2, 0, $3, 3, 1, $4);
+}
+
+JIT_OP_STORE_ELEMENT_BYTE: ternary
+[reg, reg, breg, scratch reg] -> {
+ arm_mov_memindex_reg(inst, $1, 0, $2, 0, $3, 1, $4);
+}
+
+JIT_OP_STORE_ELEMENT_SHORT: ternary
+[reg, reg, reg, scratch reg] -> {
+ arm_mov_memindex_reg(inst, $1, 0, $2, 1, $3, 2, $4);
+}
+
+JIT_OP_STORE_ELEMENT_INT: ternary
+[reg, reg, reg, scratch reg] -> {
+ arm_mov_memindex_reg(inst, $1, 0, $2, 2, $3, 4, $4);
+}
+
+JIT_OP_STORE_ELEMENT_FLOAT64: ternary
+[reg, reg, freg64, scratch reg] -> {
+ arm_fst_memindex(inst, $3, $1, 0, $2, 3, 1, $4);
+}
+
+/*
+* Allocate memory from the stack.
+*/
+JIT_OP_ALLOCA:
+[reg] -> {
+ //The ARM stack must always be 4-byte aligned and must be 8-byte
aligned at a public interface.
+ //Since we don't know when this function will be called, let's align to
8 bytes.
+ arm_alu_reg_imm(inst, ARM_ADD, $1, $1, 7);
+ arm_alu_reg_imm(inst, ARM_AND, $1, $1, ~7);
+ arm_alu_reg_reg(inst, ARM_SUB, ARM_SP, ARM_SP, $1);
+ arm_mov_reg_reg(inst, $1, ARM_SP);
+ gen->stack_changed = 1;
+}
+
+/*
+ * Block operations
+ */
+JIT_OP_MEMCPY: ternary
+ [any, any, imm, if("$3 <= 0")] -> { }
+ [reg, reg, imm, scratch reg, clobber("r0", "r1", "r2")] ->
+ {
+ /*
+ * Call jit_memcpy(dest,src,size).
+ * $1=dest, $2=src, $3=size
+ */
+ int dest=$1;
+ int src=$2;
+
+ if (dest != ARM_R0) {
+ if(src==ARM_R0)
+ {
+ //Prevent overwriting useful data
+ arm_mov_reg_reg(inst, $4, src);
+ src=$4;
+ }
+ arm_mov_reg_reg((inst), ARM_R0, dest);
+ }
+ if (src != ARM_R1) {
+ //Move the "src" from wherever it is to where it should
be
+ arm_mov_reg_reg(inst, ARM_R1, src);
+ }
+ mov_reg_imm(gen, &(inst), ARM_R2, $3);
+
+ //Call the function
+ arm_call(inst, jit_memcpy);
+ }
+ [reg, reg, reg, scratch breg, clobber("r0", "r1", "r2")] -> {
+ /*
+ * Call jit_memcpy(dest,src,size).
+ * $1=dest, $2=src, $3=size
+ */
+ if ($1 != ARM_R0) {
+ if($2==ARM_R0)
+ {
+ //Prevent overwriting useful data
+ arm_mov_reg_reg(inst, $4, $2);
+ }
+ arm_mov_reg_reg((inst), ARM_R0, $1);
+ }
+ if ($2 != ARM_R1) {
+ if ($2==ARM_R0)
+ {
+ //Recover previously saved data
+ arm_mov_reg_reg(inst, ARM_R1, $4);
+ }
+ else
+ {
+ arm_mov_reg_reg((inst), ARM_R1, $2);
+ }
+ }
+ if ($3 != ARM_R2) {
+ arm_mov_reg_reg((inst), ARM_R2, $3);
+ }
+
+ //Call the function
+ arm_call(inst, jit_memcpy);
+
+ }
+
+JIT_OP_MEMSET: ternary
+[any, any, imm, if("$3 <= 0")] -> { }
+[reg, imm, imm, if("$3 <= 32"), space("32 + $3 * 4")] -> {
+ // $1 = pointer to the initial memory location
+ // $2 = value to be written in memory
+ // $3 = length in bytes
+ int disp;
+ disp = 0;
+ while($3 >= (disp + 4))
+ {
+ //NB: if 0<A<255, then A*0x01010101 = a 32-bit value where each
of its four bytes is A.
+ arm_mov_membase_imm(inst, $1, disp, $2 * 0x01010101, 4,
ARM_WORK);
+ disp += 4;
+ }
+ if($3 >= (disp + 2))
+ {
+ arm_mov_membase_imm(inst, $1, disp, $2 * 0x0101, 2, ARM_WORK);
+ disp += 2;
+ }
+ if(insn->value2->address > disp)
+ {
+ arm_mov_membase_imm(inst, $1, disp, $2, 1, ARM_WORK);
+ }
+}
+[reg, breg, imm, if("$3 < 4")] -> {
+ TODO();
+ abort();
+}
+[reg, +reg, imm, scratch reg, if("$3 <= 32 && ($3 % 2) == 0"), space("32 + $3
* 4")] -> {
+ // $1 = pointer to the initial memory location
+ // $2 = value to be written in memory
+ // $3 = length in bytes
+ // $4 = scratch register
+ int disp;
+ arm_mov_reg_reg(inst, $4, $2);
+ arm_shift_reg_imm8(inst, ARM_SHL, $2, $2, 8);
+ arm_alu_reg_reg(inst, ARM_ORR, $2, $2, $4);
+ arm_mov_reg_reg(inst, $4, $2);
+ arm_shift_reg_imm8(inst, ARM_SHL, $2, $2, 16);
+ arm_alu_reg_reg(inst, ARM_ORR, $2, $2, $4);
+ disp = 0;
+ while($3 >= (disp + 4))
+ {
+ arm_mov_membase_reg(inst, $1, disp, $2, 4);
+ disp += 4;
+ }
+ if($3 > disp)
+ {
+ arm_mov_membase_reg(inst, $1, disp, $2, 2);
+ }
+}
+[reg, +breg, imm, scratch reg,
+if("$3 <= 32 && ($3 % 2) != 0"), space("32 + $3 * 4")] -> {
+ TODO();
+ abort();
+}
+[reg, reg, reg, clobber("r0", "r1", "r2"), scratch reg] -> {
+ // $1 = pointer to the initial memory location
+ // $2 = value to be written in memory
+ // $3 = length in bytes
+ // $4 = scratch register
+
+ int scratchContains=0; //< Number of the parameter in the scratch
register. 0 means no param in scratch reg.
+ int allOk=0;
+
+ /* Move the outgoing parameters in the right registers (if they are not
already where they should be */
+ if ($1 != ARM_R0) {
+ if($2 == ARM_R0)
+ {
+ arm_mov_reg_reg((inst), $4, ARM_R0);
+ scratchContains=2;
+ }
+ else if($3==ARM_R0)
+ {
+ arm_mov_reg_reg((inst), $4, ARM_R0);
+ scratchContains=3;
+ }
+ arm_mov_reg_reg((inst), ARM_R0, $1);
+ }
+
+ if ($2 != ARM_R1)
+ {
+ if ($3 == ARM_R1)
+ {
+ //We must save param 3, that's in ARM_R1
+ if(scratchContains==2)
+ {
+ /*scratch reg contains the parameter that will
go in ARM_R1 and can't be overwritten. Copy param 3 directly to its register. */
+ arm_mov_reg_reg(inst, ARM_R2, ARM_R1);
+ allOk=1;
+ }
+ else
+ {
+ assert(scratchContains==0);
+ //Scratch reg is free. Use it to store param 3
+ arm_mov_reg_reg(inst, $4, ARM_R1);
+ scratchContains=3;
+ }
+ }
+
+ //Set param 2
+ if(scratchContains==2)
+ {
+ arm_mov_reg_reg((inst), ARM_R1, $4);
+ }
+ else
+ {
+ arm_mov_reg_reg((inst), ARM_R1, $2);
+ }
+ }
+
+ if(!allOk)
+ {
+ if($3 != ARM_R1)
+ {
+ //Param 3 still isn't in place
+ if(scratchContains==3)
+ {
+ //Get param 3 from the scratch reg
+ arm_mov_reg_reg(inst, ARM_R2, $4);
+ }
+ else
+ {
+ //Get param 3 from wherever it is
+ arm_mov_reg_reg(inst, ARM_R2, $3);
+ }
+
+ allOk=1;
+ }
+ }
+
+ arm_call(inst, jit_memset);
+}
Index: jit/jit-rules-arm.sel
===================================================================
RCS file: jit/jit-rules-arm.sel
diff -N jit/jit-rules-arm.sel
--- jit/jit-rules-arm.sel 24 Jan 2008 20:12:53 -0000 1.16
+++ /dev/null 1 Jan 1970 00:00:00 -0000
@@ -1,1403 +0,0 @@
-/*
- * jit-rules-arm.sel - Instruction selector for ARM.
- *
- * Copyright (C) 2004 Southern Storm Software, Pty Ltd.
- *
- * This file is part of the libjit library.
- *
- * The libjit library is free software: you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public License
- * as published by the Free Software Foundation, either version 2.1 of
- * the License, or (at your option) any later version.
- *
- * The libjit library 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
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with the libjit library. If not, see
- * <http://www.gnu.org/licenses/>.
- */
-
-%inst_type arm_inst_buf
-
-/*
- * 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] -> {
- /* Handle special cases of immediate multiplies */
- switch($2)
- {
- case 0:
- {
- arm_mov_reg_imm8(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)
- {
- 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);
- }
-
-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);
- }
-
-JIT_OP_FSUB (JIT_ARM_HAS_FLOAT_REGS): binary
- [freg, freg] -> {
- arm_alu_freg_freg_32(inst, ARM_SUF, $1, $1, $2);
- }
-
-JIT_OP_FMUL (JIT_ARM_HAS_FLOAT_REGS): binary
- [freg, freg] -> {
- arm_alu_freg_freg_32(inst, ARM_MUF, $1, $1, $2);
- }
-
-JIT_OP_FDIV (JIT_ARM_HAS_FLOAT_REGS): binary
- [freg, freg] -> {
- arm_alu_freg_freg_32(inst, ARM_DVF, $1, $1, $2);
- }
-
-JIT_OP_FNEG (JIT_ARM_HAS_FLOAT_REGS): unary
- [freg] -> {
- arm_alu_freg_32(inst, ARM_MNF, $1, $1);
- }
-
-JIT_OP_DADD, JIT_OP_NFADD (JIT_ARM_HAS_FLOAT_REGS): binary
- [freg, freg] -> {
- arm_alu_freg_freg(inst, ARM_ADF, $1, $1, $2);
- }
-
-JIT_OP_DSUB, JIT_OP_NFSUB (JIT_ARM_HAS_FLOAT_REGS): binary
- [freg, freg] -> {
- arm_alu_freg_freg(inst, ARM_SUF, $1, $1, $2);
- }
-
-JIT_OP_DMUL, JIT_OP_NFMUL (JIT_ARM_HAS_FLOAT_REGS): binary
- [freg, freg] -> {
- arm_alu_freg_freg(inst, ARM_MUF, $1, $1, $2);
- }
-
-JIT_OP_DDIV, JIT_OP_NFDIV (JIT_ARM_HAS_FLOAT_REGS): binary
- [freg, freg] -> {
- arm_alu_freg_freg(inst, ARM_DVF, $1, $1, $2);
- }
-
-JIT_OP_DNEG, JIT_OP_NFNEG (JIT_ARM_HAS_FLOAT_REGS): unary
- [freg] -> {
- arm_alu_freg(inst, ARM_MNF, $1, $1);
- }
-
-/*
- * 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);
- }
-
-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.
- */
-
-JIT_OP_BR: spill_before
- [] -> {
- /* ARM_CC_AL == "always branch" */
- output_branch(func, &inst, ARM_CC_AL, insn);
-
- /* Flush the constant pool now, to minimize the probability that
- it is accidentally flushed in the middle of a loop body */
- jit_gen_save_inst_ptr(gen, inst);
- flush_constants(gen, 1);
- jit_gen_load_inst_ptr(gen, inst);
- }
-
-JIT_OP_BR_IFALSE: unary_branch
- [reg] -> {
- arm_test_reg_imm8(inst, ARM_CMP, $1, 0);
- output_branch(func, &inst, ARM_CC_EQ, insn);
- }
-
-JIT_OP_BR_ITRUE: unary_branch
- [reg] -> {
- arm_test_reg_imm8(inst, ARM_CMP, $1, 0);
- 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);
- output_branch(func, &inst, ARM_CC_EQ, insn);
- }
- [reg, reg] -> {
- arm_test_reg_reg(inst, ARM_CMP, $1, $2);
- 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);
- output_branch(func, &inst, ARM_CC_NE, insn);
- }
- [reg, reg] -> {
- arm_test_reg_reg(inst, ARM_CMP, $1, $2);
- 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);
- output_branch(func, &inst, ARM_CC_LT, insn);
- }
- [reg, reg] -> {
- arm_test_reg_reg(inst, ARM_CMP, $1, $2);
- 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);
- output_branch(func, &inst, ARM_CC_LT_UN, insn);
- }
- [reg, reg] -> {
- arm_test_reg_reg(inst, ARM_CMP, $1, $2);
- 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);
- output_branch(func, &inst, ARM_CC_LE, insn);
- }
- [reg, reg] -> {
- arm_test_reg_reg(inst, ARM_CMP, $1, $2);
- 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);
- output_branch(func, &inst, ARM_CC_LE_UN, insn);
- }
- [reg, reg] -> {
- arm_test_reg_reg(inst, ARM_CMP, $1, $2);
- 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);
- output_branch(func, &inst, ARM_CC_GT, insn);
- }
- [reg, reg] -> {
- arm_test_reg_reg(inst, ARM_CMP, $1, $2);
- 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);
- output_branch(func, &inst, ARM_CC_GT_UN, insn);
- }
- [reg, reg] -> {
- arm_test_reg_reg(inst, ARM_CMP, $1, $2);
- 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);
- output_branch(func, &inst, ARM_CC_GE, insn);
- }
- [reg, reg] -> {
- arm_test_reg_reg(inst, ARM_CMP, $1, $2);
- 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);
- output_branch(func, &inst, ARM_CC_GE_UN, insn);
- }
- [reg, reg] -> {
- arm_test_reg_reg(inst, ARM_CMP, $1, $2);
- 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);
- }
-
-/*
- * Pointer check opcodes.
- */
-
-JIT_OP_CHECK_NULL: unary_note
- [reg] -> {
- arm_test_reg_imm8(inst, ARM_CMP, $1, 0);
- 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_pop_frame_tail(inst, 0);
- 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:
- [] -> {
- jump_to_epilog(gen, &inst, block);
- }
-
-JIT_OP_RETURN_INT: unary_branch
- [reg] -> {
- int cpu_reg = $1;
- if(cpu_reg != ARM_R0)
- {
- arm_mov_reg_reg(inst, ARM_R0, cpu_reg);
- }
- jump_to_epilog(gen, &inst, block);
- }
-
-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)
- {
- arm_mov_reg_reg(inst, ARM_R0, $1);
- arm_mov_reg_reg(inst, ARM_R1, %1);
- }
- jump_to_epilog(gen, &inst, block);
- }
-
-JIT_OP_RETURN_FLOAT32 (JIT_ARM_HAS_FLOAT_REGS): unary_branch
- [freg] -> {
- if($1 != 0)
- {
- arm_alu_freg_32(inst, ARM_MVF, ARM_F0, $1);
- }
- jump_to_epilog(gen, &inst, block);
- }
-
-JIT_OP_RETURN_FLOAT32 (!JIT_ARM_HAS_FLOAT_REGS): manual
- [] -> {
- arm_inst_buf inst;
- _jit_regs_spill_all(gen);
- _jit_gen_fix_value(insn->value1);
- jit_gen_load_inst_ptr(gen, inst);
- if(insn->value1->is_constant)
- {
- mov_reg_imm
- (gen, &inst, ARM_R0, ((int
*)(insn->value1->address))[0]);
- }
- else
- {
- arm_load_membase(inst, ARM_R0, ARM_FP,
insn->value1->frame_offset);
- }
- jump_to_epilog(gen, &inst, block);
- jit_gen_save_inst_ptr(gen, inst);
- }
-
-JIT_OP_RETURN_FLOAT64, JIT_OP_RETURN_NFLOAT
- (JIT_ARM_HAS_FLOAT_REGS): unary_branch
- [freg] -> {
- if($1 != 0)
- {
- arm_alu_freg(inst, ARM_MVF, ARM_F0, $1);
- }
- jump_to_epilog(gen, &inst, block);
- }
-
-JIT_OP_RETURN_FLOAT64, JIT_OP_RETURN_NFLOAT (!JIT_ARM_HAS_FLOAT_REGS): manual
- [] -> {
- arm_inst_buf inst;
- _jit_regs_spill_all(gen);
- _jit_gen_fix_value(insn->value1);
- jit_gen_load_inst_ptr(gen, inst);
- if(insn->value1->is_constant)
- {
- mov_reg_imm
- (gen, &inst, ARM_R0, ((int
*)(insn->value1->address))[0]);
- mov_reg_imm
- (gen, &inst, ARM_R1, ((int
*)(insn->value1->address))[1]);
- }
- else
- {
- arm_load_membase(inst, ARM_R0, ARM_FP,
insn->value1->frame_offset);
- arm_load_membase(inst, ARM_R1, ARM_FP,
-
insn->value1->frame_offset + 4);
- }
- jump_to_epilog(gen, &inst, block);
- jit_gen_save_inst_ptr(gen, inst);
- }
-
-JIT_OP_RETURN_SMALL_STRUCT: unary_branch
- [reg] -> {
- int temp_reg = $1;
- if(temp_reg < 3)
- {
- arm_mov_reg_reg(inst, ARM_WORK, temp_reg);
- temp_reg = ARM_WORK;
- }
- switch(insn->value2->address)
- {
- case 1:
- {
- arm_load_membase_byte(inst, ARM_R0, temp_reg,
0);
- }
- break;
-
- case 2:
- {
- arm_load_membase_ushort(inst, ARM_R0, temp_reg,
0);
- }
- break;
-
- case 3:
- {
- arm_load_membase_ushort(inst, ARM_R0, temp_reg,
0);
- arm_load_membase_byte(inst, ARM_R1, temp_reg,
2);
- arm_shift_reg_imm8(inst, ARM_SHL, ARM_R1,
ARM_R1, 16);
- arm_alu_reg_reg(inst, ARM_ORR, ARM_R0, ARM_R0,
ARM_R1);
- }
- break;
-
- case 4:
- {
- arm_load_membase(inst, ARM_R0, temp_reg, 0);
- }
- break;
-
- case 5:
- {
- arm_load_membase(inst, ARM_R0, temp_reg, 0);
- arm_load_membase_byte(inst, ARM_R1, temp_reg,
4);
- }
- break;
-
- case 6:
- {
- arm_load_membase(inst, ARM_R0, temp_reg, 0);
- arm_load_membase_ushort(inst, ARM_R1, temp_reg,
4);
- }
- break;
-
- case 7:
- {
- arm_load_membase(inst, ARM_R0, temp_reg, 0);
- arm_load_membase_ushort(inst, ARM_R1, temp_reg,
4);
- arm_load_membase_byte(inst, ARM_R2, temp_reg,
6);
- arm_shift_reg_imm8(inst, ARM_SHL, ARM_R2,
ARM_R2, 16);
- arm_alu_reg_reg(inst, ARM_ORR, ARM_R1, ARM_R1,
ARM_R2);
- }
- break;
-
- case 8:
- {
- arm_load_membase(inst, ARM_R0, temp_reg, 0);
- arm_load_membase(inst, ARM_R1, temp_reg, 4);
- }
- break;
- }
- 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)
- {
- 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();
- }
-
-/*
- * Data manipulation.
- */
-
-JIT_OP_COPY_LOAD_SBYTE: unary
- [reg] -> {}
-
-JIT_OP_COPY_LOAD_UBYTE: unary
- [reg] -> {}
-
-JIT_OP_COPY_LOAD_SHORT: unary
- [reg] -> {}
-
-JIT_OP_COPY_LOAD_USHORT: unary
- [reg] -> {}
-
-JIT_OP_COPY_INT: unary
- [reg] -> {}
-
-JIT_OP_COPY_LONG: unary
- [lreg] -> {}
-
-JIT_OP_COPY_FLOAT32 (JIT_ARM_HAS_FLOAT_REGS): unary
- [freg] -> {}
-
-JIT_OP_COPY_FLOAT32 (!JIT_ARM_HAS_FLOAT_REGS): 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]);
- }
- 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);
- jit_gen_save_inst_ptr(gen, inst);
- }
-
-JIT_OP_COPY_FLOAT64, JIT_OP_COPY_NFLOAT (JIT_ARM_HAS_FLOAT_REGS): unary
- [freg] -> {}
-
-JIT_OP_COPY_FLOAT64, JIT_OP_COPY_NFLOAT (!JIT_ARM_HAS_FLOAT_REGS): 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_STRUCT: manual
- [] -> {
- /* TODO */
- TODO();
- }
-
-JIT_OP_COPY_STORE_BYTE: manual
- [] -> {
- arm_inst_buf inst;
- int reg;
- _jit_regs_force_out(gen, insn->dest, 1);
- _jit_gen_fix_value(insn->dest);
- reg = _jit_regs_load_value
- (gen, insn->value1, 0,
- (insn->flags & (JIT_INSN_VALUE1_NEXT_USE |
-
JIT_INSN_VALUE1_LIVE)));
- jit_gen_load_inst_ptr(gen, inst);
- arm_store_membase_byte(inst, _jit_reg_info[reg].cpu_reg,
- ARM_FP,
insn->dest->frame_offset);
- jit_gen_save_inst_ptr(gen, inst);
- }
-
-JIT_OP_COPY_STORE_SHORT: manual
- [] -> {
- arm_inst_buf inst;
- int reg;
- _jit_regs_force_out(gen, insn->dest, 1);
- _jit_gen_fix_value(insn->dest);
- reg = _jit_regs_load_value
- (gen, insn->value1, 1,
- (insn->flags & (JIT_INSN_VALUE1_NEXT_USE |
-
JIT_INSN_VALUE1_LIVE)));
- jit_gen_load_inst_ptr(gen, inst);
- arm_store_membase_short(inst, _jit_reg_info[reg].cpu_reg,
- ARM_FP,
insn->dest->frame_offset);
- jit_gen_save_inst_ptr(gen, inst);
- _jit_regs_free_reg(gen, reg, 1);
- }
-
-JIT_OP_ADDRESS_OF: manual
- [] -> {
- arm_inst_buf inst;
- int reg, offset;
- _jit_regs_force_out(gen, insn->value1, 0);
- _jit_gen_fix_value(insn->value1);
- jit_gen_load_inst_ptr(gen, inst);
- reg = _jit_regs_dest_value(gen, insn->dest);
- reg = _jit_reg_info[reg].cpu_reg;
- offset = insn->value1->frame_offset;
- if(offset > 0)
- {
- arm_alu_reg_imm(inst, ARM_ADD, reg, ARM_FP, offset);
- }
- else if(offset < 0)
- {
- arm_alu_reg_imm(inst, ARM_SUB, reg, ARM_FP, -offset);
- }
- else
- {
- arm_mov_reg_reg(inst, reg, ARM_FP);
- }
- jit_gen_save_inst_ptr(gen, inst);
- }
-
-/*
- * Stack pushes and pops.
- */
-
-JIT_OP_RETURN_REG: manual
- [] -> { /* Nothing to do here */ }
-
-JIT_OP_PUSH_INT: unary_note
- [reg] -> {
- arm_push_reg(inst, $1);
- }
-
-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
- [freg] -> {
- arm_push_reg_float32(inst, $1);
- }
-
-JIT_OP_PUSH_FLOAT32 (!JIT_ARM_HAS_FLOAT_REGS): 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]);
- }
- else
- {
- 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_FLOAT64, JIT_OP_PUSH_NFLOAT (JIT_ARM_HAS_FLOAT_REGS): unary_note
- [freg] -> {
- arm_push_reg_float64(inst, $1);
- }
-
-JIT_OP_PUSH_FLOAT64, JIT_OP_PUSH_NFLOAT (!JIT_ARM_HAS_FLOAT_REGS): 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_STRUCT: unary_note
- [reg] -> {
- /* TODO */
- TODO();
- }
-
-JIT_OP_POP_STACK:
- [] -> {
- arm_alu_reg_imm(inst, ARM_ADD, ARM_SP, ARM_SP,
insn->value1->address);
- }
-
-JIT_OP_FLUSH_SMALL_STRUCT:
- [] -> {
- jit_nuint size;
- jit_nint offset;
- _jit_gen_fix_value(insn->value1);
- size = jit_type_get_size(jit_value_get_type(insn->value1));
- offset = insn->value1->frame_offset;
- switch(size)
- {
- case 1:
- {
- arm_store_membase_byte(inst, ARM_R0, ARM_FP,
offset);
- }
- break;
-
- case 2:
- {
- arm_store_membase_short(inst, ARM_R0, ARM_FP,
offset);
- }
- break;
-
- case 3:
- {
- arm_mov_reg_reg(inst, ARM_R1, ARM_R0);
- arm_store_membase_short(inst, ARM_R0, ARM_FP,
offset);
- arm_shift_reg_imm8(inst, ARM_SHR, ARM_R0,
ARM_R1, 16);
- arm_store_membase_byte(inst, ARM_R0, ARM_FP,
offset + 2);
- }
- break;
-
- case 4:
- {
- arm_store_membase(inst, ARM_R0, ARM_FP, offset);
- }
- break;
-
- case 5:
- {
- arm_store_membase(inst, ARM_R0, ARM_FP, offset);
- arm_store_membase_byte(inst, ARM_R1, ARM_FP,
offset + 4);
- }
- break;
-
- case 6:
- {
- arm_store_membase(inst, ARM_R0, ARM_FP, offset);
- arm_store_membase_short(inst, ARM_R1, ARM_FP,
offset + 4);
- }
- break;
-
- case 7:
- {
- arm_store_membase(inst, ARM_R0, ARM_FP, offset);
- arm_mov_reg_reg(inst, ARM_R2, ARM_R1);
- arm_store_membase_short(inst, ARM_R1, ARM_FP,
offset + 4);
- arm_shift_reg_imm8(inst, ARM_SHR, ARM_R1,
ARM_R2, 16);
- arm_store_membase_byte(inst, ARM_R1, ARM_FP,
offset + 6);
- }
- break;
-
- case 8:
- {
- arm_store_membase(inst, ARM_R0, ARM_FP, offset);
- arm_store_membase(inst, ARM_R1, ARM_FP, offset
+ 4);
- }
- break;
- }
- }
-
-JIT_OP_SET_PARAM_INT: unary_note
- [reg] -> {
- arm_store_membase(inst, $1, ARM_SP, insn->value2->address);
- }
-
-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
- [freg] -> {
- arm_store_membase_float32(inst, $1, ARM_SP,
insn->value2->address);
- }
-
-JIT_OP_SET_PARAM_FLOAT32 (!JIT_ARM_HAS_FLOAT_REGS): 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);
- }
- else
- {
- arm_load_membase(inst, ARM_WORK, ARM_FP,
-
insn->value1->frame_offset);
- arm_store_membase
- (inst, ARM_WORK, ARM_SP, insn->value2->address);
- }
- jit_gen_save_inst_ptr(gen, inst);
- }
-
-JIT_OP_SET_PARAM_FLOAT64, JIT_OP_SET_PARAM_NFLOAT
- (JIT_ARM_HAS_FLOAT_REGS): unary_note
- [freg] -> {
- arm_store_membase_float64(inst, $1, ARM_SP,
insn->value2->address);
- }
-
-JIT_OP_SET_PARAM_FLOAT64, JIT_OP_SET_PARAM_NFLOAT
- (!JIT_ARM_HAS_FLOAT_REGS): 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_STRUCT: unary_note
- [reg] -> {
- /* TODO */
- TODO();
- }
-
-/*
- * Pointer-relative loads and stores.
- */
-
-JIT_OP_LOAD_RELATIVE_SBYTE: unary
- [reg] -> {
- arm_load_membase_sbyte(inst, $1, $1, insn->value2->address);
- }
-
-JIT_OP_LOAD_RELATIVE_UBYTE: unary
- [reg] -> {
- arm_load_membase_byte(inst, $1, $1, insn->value2->address);
- }
-
-JIT_OP_LOAD_RELATIVE_SHORT: unary
- [reg] -> {
- arm_load_membase_short(inst, $1, $1, insn->value2->address);
- }
-
-JIT_OP_LOAD_RELATIVE_USHORT: unary
- [reg] -> {
- arm_load_membase_ushort(inst, $1, $1, insn->value2->address);
- }
-
-JIT_OP_LOAD_RELATIVE_INT: unary
- [reg] -> {
- arm_load_membase(inst, $1, $1, insn->value2->address);
- }
-
-JIT_OP_LOAD_RELATIVE_LONG: manual
- [] -> {
- arm_inst_buf inst;
- int reg = _jit_regs_load_value
- (gen, insn->value1, 0,
- (insn->flags & (JIT_INSN_VALUE1_NEXT_USE |
-
JIT_INSN_VALUE1_LIVE)));
- int reg2, reg3;
- int frame_offset;
- _jit_gen_fix_value(insn->dest);
- _jit_regs_get_reg_pair(gen, reg, -1, -1, ®2, ®3);
- reg = _jit_reg_info[reg].cpu_reg;
- reg2 = _jit_reg_info[reg2].cpu_reg;
- reg3 = _jit_reg_info[reg3].cpu_reg;
- frame_offset = insn->dest->frame_offset;
- jit_gen_load_inst_ptr(gen, inst);
- arm_load_membase(inst, reg2, reg, insn->value2->address);
- arm_load_membase(inst, reg3, reg, insn->value2->address + 4);
- arm_store_membase(inst, reg2, ARM_FP, frame_offset);
- arm_store_membase(inst, reg3, ARM_FP, frame_offset + 4);
- insn->dest->in_frame = 1;
- jit_gen_save_inst_ptr(gen, inst);
- }
-
-JIT_OP_LOAD_RELATIVE_FLOAT32: manual
- [] -> {
- /* TODO */
- TODO();
- }
-
-JIT_OP_LOAD_RELATIVE_FLOAT64, JIT_OP_LOAD_RELATIVE_NFLOAT: manual
- [] -> {
- /* TODO */
- TODO();
- }
-
-JIT_OP_LOAD_RELATIVE_STRUCT: manual
- [] -> {
- /* TODO */
- TODO();
- }
-
-JIT_OP_STORE_RELATIVE_BYTE: manual
- [] -> {
- arm_inst_buf inst;
- int reg = _jit_regs_load_value
- (gen, insn->dest, 0,
- (insn->flags & (JIT_INSN_DEST_NEXT_USE |
- JIT_INSN_DEST_LIVE)));
- int reg2 = _jit_regs_load_value
- (gen, insn->value1, 0,
- (insn->flags & (JIT_INSN_VALUE1_NEXT_USE |
-
JIT_INSN_VALUE1_LIVE)));
- jit_gen_load_inst_ptr(gen, inst);
- reg = _jit_reg_info[reg].cpu_reg;
- reg2 = _jit_reg_info[reg2].cpu_reg;
- arm_store_membase_byte(inst, reg2, reg, insn->value2->address);
- jit_gen_save_inst_ptr(gen, inst);
- }
-
-JIT_OP_STORE_RELATIVE_SHORT: manual
- [] -> {
- arm_inst_buf inst;
- int reg = _jit_regs_load_value
- (gen, insn->dest, 0,
- (insn->flags & (JIT_INSN_DEST_NEXT_USE |
- JIT_INSN_DEST_LIVE)));
- int reg2 = _jit_regs_load_value
- (gen, insn->value1, 1,
- (insn->flags & (JIT_INSN_VALUE1_NEXT_USE |
-
JIT_INSN_VALUE1_LIVE)));
- jit_gen_load_inst_ptr(gen, inst);
- reg = _jit_reg_info[reg].cpu_reg;
- reg2 = _jit_reg_info[reg2].cpu_reg;
- arm_store_membase_short(inst, reg2, reg, insn->value2->address);
- jit_gen_save_inst_ptr(gen, inst);
- _jit_regs_free_reg(gen, reg2, 1);
- }
-
-JIT_OP_STORE_RELATIVE_INT: manual
- [] -> {
- arm_inst_buf inst;
- int reg = _jit_regs_load_value
- (gen, insn->dest, 0,
- (insn->flags & (JIT_INSN_DEST_NEXT_USE |
- JIT_INSN_DEST_LIVE)));
- int reg2 = _jit_regs_load_value
- (gen, insn->value1, 0,
- (insn->flags & (JIT_INSN_VALUE1_NEXT_USE |
-
JIT_INSN_VALUE1_LIVE)));
- jit_gen_load_inst_ptr(gen, inst);
- reg = _jit_reg_info[reg].cpu_reg;
- reg2 = _jit_reg_info[reg2].cpu_reg;
- arm_store_membase(inst, reg2, reg, insn->value2->address);
- jit_gen_save_inst_ptr(gen, inst);
- }
-
-JIT_OP_STORE_RELATIVE_LONG: manual
- [] -> {
- arm_inst_buf inst;
- int reg = _jit_regs_load_value
- (gen, insn->dest, 0,
- (insn->flags & (JIT_INSN_DEST_NEXT_USE |
- JIT_INSN_DEST_LIVE)));
- int reg2, reg3;
- int frame_offset;
- _jit_regs_get_reg_pair(gen, reg, -1, -1, ®2, ®3);
- _jit_gen_fix_value(insn->value1);
- jit_gen_load_inst_ptr(gen, inst);
- reg = _jit_reg_info[reg].cpu_reg;
- reg2 = _jit_reg_info[reg2].cpu_reg;
- reg3 = _jit_reg_info[reg3].cpu_reg;
- frame_offset = insn->value1->frame_offset;
- arm_load_membase(inst, reg2, ARM_FP, frame_offset);
- arm_load_membase(inst, reg3, ARM_FP, frame_offset + 4);
- arm_store_membase(inst, reg2, reg, insn->value2->address);
- arm_store_membase(inst, reg3, reg, insn->value2->address + 4);
- jit_gen_save_inst_ptr(gen, inst);
- }
-
-JIT_OP_STORE_RELATIVE_FLOAT32: manual
- [] -> {
- /* TODO */
- TODO();
- }
-
-JIT_OP_STORE_RELATIVE_FLOAT64, JIT_OP_STORE_RELATIVE_NFLOAT: manual
- [] -> {
- /* TODO */
- TODO();
- }
-
-JIT_OP_STORE_RELATIVE_STRUCT: manual
- [] -> {
- /* TODO */
- TODO();
- }
-
-JIT_OP_ADD_RELATIVE: unary
- [reg] -> {
- if(insn->value2->address != 0)
- {
- arm_alu_reg_imm(inst, ARM_ADD, $1, $1,
insn->value2->address);
- }
- }
[Prev in Thread] |
Current Thread |
[Next in Thread] |
- [dotgnu-pnet-commits] libjit ChangeLog jit/Makefile.am jit/jit-rules-...,
Aleksey Demakov <=