dotgnu-pnet-commits
[Top][All Lists]
Advanced

[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, &reg2, &reg3);
-               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, &reg2, &reg3);
-               _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);
-               }
-       }




reply via email to

[Prev in Thread] Current Thread [Next in Thread]