]> git.unchartedbackwaters.co.uk Git - francis/libjit.git/commitdiff
Add the beginnings of the instruction selector for ARM.
authorRhys Weatherley <rweather@southern-storm.com.au>
Wed, 26 May 2004 07:21:04 +0000 (07:21 +0000)
committerRhys Weatherley <rweather@southern-storm.com.au>
Wed, 26 May 2004 07:21:04 +0000 (07:21 +0000)
ChangeLog
jit/Makefile.am
jit/jit-gen-arm.h
jit/jit-rules-arm.c
jit/jit-rules-arm.sel [new file with mode: 0644]

index d808343183d47800514bd20b027399026dbf576c..629b4e561203bdf8b2f12011a54035c5c9100b1e 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
        * jit/jit-rules-x86.c, jit/jit-rules-x86.sel, tools/gen-sel-parser.y,
        tools/gen-sel-scanner.l: more selection cases for the x86 back end.
 
+       * jit/Makefile.am, jit/jit-gen-arm.h, jit/jit-rules-arm.c,
+       jit/jit-rules-arm.sel: add the beginnings of the instruction
+       selector for ARM.
+
 2004-05-25  Rhys Weatherley  <rweather@southern-storm.com.au>
 
        * tools/.cvsignore, tools/Makefile.am, tools/gen-sel-parser.y,
index 2b4dbfe66d2c85c87ccb2516ae897c35b27c3a02..1f6fd7a14d6ee8981deb63d0a209235c7141c14d 100644 (file)
@@ -67,4 +67,10 @@ jit-rules-x86.slc: jit-rules-x86.sel $(top_builddir)/tools/gen-sel$(EXEEXT)
        $(top_builddir)/tools/gen-sel$(EXEEXT) $(srcdir)/jit-rules-x86.sel \
                        >jit-rules-x86.slc
 
-CLEANFILES = jit-interp-labels.h jit-rules-x86.slc
+jit-rules-arm.lo: jit-rules-arm.slc
+
+jit-rules-arm.slc: jit-rules-arm.sel $(top_builddir)/tools/gen-sel$(EXEEXT)
+       $(top_builddir)/tools/gen-sel$(EXEEXT) $(srcdir)/jit-rules-arm.sel \
+                       >jit-rules-arm.slc
+
+CLEANFILES = jit-interp-labels.h jit-rules-x86.slc jit-rules-arm.slc
index bc18b8ba2f41ff132c8c7e641c0b5e89d5075717..69b7e62787e0c0e7a83c39a97da4bbcfaa6f1e36 100644 (file)
@@ -202,8 +202,7 @@ extern arm_inst_ptr _arm_alu_reg_imm
                                if(__alu_imm >= 0 && __alu_imm < 256) \
                                { \
                                        arm_alu_reg_imm8 \
-                                               ((inst), (opc), (dreg), (sreg), __alu_imm, \
-                                                arm_execute); \
+                                               ((inst), (opc), (dreg), (sreg), __alu_imm); \
                                } \
                                else \
                                { \
index 7f3a228f149f606d744c31ce5390080486d08ed7..c613b738b75d529307c4d05c6959e37d32e3a688 100644 (file)
@@ -25,6 +25,7 @@
 #if defined(JIT_BACKEND_ARM)
 
 #include "jit-gen-arm.h"
+#include "jit-reg-alloc.h"
 
 /*
  * Determine if we actually have floating-point registers.
@@ -491,6 +492,17 @@ int _jit_create_call_return_insns
        return 1;
 }
 
+int _jit_opcode_is_supported(int opcode)
+{
+       switch(opcode)
+       {
+               #define JIT_INCLUDE_SUPPORTED
+               #include "jit-rules-arm.slc"
+               #undef JIT_INCLUDE_SUPPORTED
+       }
+       return 0;
+}
+
 void *_jit_gen_prolog(jit_gencode_t gen, jit_function_t func, void *buf)
 {
        unsigned int prolog[JIT_PROLOG_SIZE / sizeof(int)];
@@ -639,15 +651,79 @@ void _jit_gen_fix_value(jit_value_t value)
        }
 }
 
+/*
+ * Output a branch instruction.
+ */
+static arm_inst_ptr output_branch
+       (jit_function_t func, arm_inst_ptr inst, int cond, jit_insn_t insn)
+{
+       jit_block_t block;
+       int offset;
+       block = jit_block_from_label(func, (jit_label_t)(insn->dest));
+       if(!block)
+       {
+               return inst;
+       }
+       if(block->address)
+       {
+               /* We already know the address of the block */
+               arm_branch(inst, cond, block->address);
+       }
+       else
+       {
+               /* Output a placeholder and record on the block's fixup list */
+               if(block->fixup_list)
+               {
+                       offset = (int)(((unsigned char *)inst) -
+                                                  ((unsigned char *)(block->fixup_list)));
+               }
+               else
+               {
+                       offset = 0;
+               }
+               arm_branch_imm(inst, cond, offset);
+               block->fixup_list = (void *)(inst - 1);
+       }
+       return inst;
+}
+
 void _jit_gen_insn(jit_gencode_t gen, jit_function_t func,
                                   jit_block_t block, jit_insn_t insn)
 {
-       /* TODO */
+       switch(insn->opcode)
+       {
+               #define JIT_INCLUDE_RULES
+               #include "jit-rules-arm.slc"
+               #undef JIT_INCLUDE_RULES
+       }
 }
 
 void _jit_gen_start_block(jit_gencode_t gen, jit_block_t block)
 {
-       /* TODO: label fixups */
+       void **fixup;
+       void **next;
+       jit_nint offset;
+
+       /* Set the address of this block */
+       block->address = (void *)(gen->posn.ptr);
+
+       /* If this block has pending fixups, then apply them now */
+       fixup = (void **)(block->fixup_list);
+       while(fixup != 0)
+       {
+               offset = (((jit_nint)(fixup[0])) & 0x00FFFFFF) << 2;
+               if(!offset)
+               {
+                       next = 0;
+               }
+               else
+               {
+                       next = (void **)(((unsigned char *)fixup) - offset);
+               }
+               arm_patch(fixup, block->address);
+               fixup = next;
+       }
+       block->fixup_list = 0;
 }
 
 void _jit_gen_end_block(jit_gencode_t gen, jit_block_t block)
diff --git a/jit/jit-rules-arm.sel b/jit/jit-rules-arm.sel
new file mode 100644 (file)
index 0000000..7cd98ee
--- /dev/null
@@ -0,0 +1,428 @@
+/*
+ * jit-rules-arm.sel - Instruction selector for ARM.
+ *
+ * Copyright (C) 2004  Southern Storm Software, Pty Ltd.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+%inst_type arm_inst_ptr
+
+/*
+ * Conversion opcodes.
+ */
+
+JIT_OP_TRUNC_SBYTE: unary
+       [reg] -> {
+               arm_shift_reg_imm8(inst, ARM_SHL, $1, $1, 24);
+               arm_shift_reg_imm8(inst, ARM_SAR, $1, $1, 24);
+       }
+
+JIT_OP_TRUNC_UBYTE: unary
+       [reg] -> {
+               arm_alu_reg_imm8(inst, ARM_AND, $1, $1, 0xFF);
+       }
+
+JIT_OP_TRUNC_SHORT: unary
+       [reg] -> {
+               arm_shift_reg_imm8(inst, ARM_SHL, $1, $1, 16);
+               arm_shift_reg_imm8(inst, ARM_SAR, $1, $1, 16);
+       }
+
+JIT_OP_TRUNC_USHORT: unary
+       [reg] -> {
+               arm_shift_reg_imm8(inst, ARM_SHL, $1, $1, 16);
+               arm_shift_reg_imm8(inst, ARM_SHR, $1, $1, 16);
+       }
+
+/*
+ * Arithmetic opcodes.
+ */
+
+JIT_OP_IADD: binary
+       [reg, immu8] -> {
+               arm_alu_reg_imm8(inst, ARM_ADD, $1, $1, $2);
+       }
+       [reg, reg] -> {
+               arm_alu_reg_reg(inst, ARM_ADD, $1, $1, $2);
+       }
+
+JIT_OP_ISUB: binary
+       [reg, immu8] -> {
+               arm_alu_reg_imm8(inst, ARM_SUB, $1, $1, $2);
+       }
+       [reg, reg] -> {
+               arm_alu_reg_reg(inst, ARM_SUB, $1, $1, $2);
+       }
+
+JIT_OP_IMUL: binary
+       [reg, immu8] -> {
+               arm_mov_reg_imm8(inst, ARM_WORK, $2);
+               arm_mul_reg_reg(inst, $1, $1, ARM_WORK);
+       }
+       [reg, reg] -> {
+               if($1 != $2)
+               {
+                       arm_mul_reg_reg(inst, $1, $1, $2);
+               }
+               else
+               {
+                       /* Cannot use the same register for both arguments */
+                       arm_mov_reg_reg(inst, ARM_WORK, $2);
+                       arm_mul_reg_reg(inst, $1, $1, ARM_WORK);
+               }
+       }
+
+JIT_OP_INEG: unary
+       [reg] -> {
+               /* -x is the same as (0 - x) */
+               arm_alu_reg_imm8(inst, ARM_RSB, $1, $1, 0);
+       }
+
+/*
+ * Bitwise opcodes.
+ */
+
+JIT_OP_IAND: binary
+       [reg, immu8] -> {
+               arm_alu_reg_imm8(inst, ARM_AND, $1, $1, $2);
+       }
+       [reg, reg] -> {
+               arm_alu_reg_reg(inst, ARM_AND, $1, $1, $2);
+       }
+
+JIT_OP_IOR: binary
+       [reg, immu8] -> {
+               arm_alu_reg_imm8(inst, ARM_ORR, $1, $1, $2);
+       }
+       [reg, reg] -> {
+               arm_alu_reg_reg(inst, ARM_ORR, $1, $1, $2);
+       }
+
+JIT_OP_IXOR: binary
+       [reg, immu8] -> {
+               arm_alu_reg_imm8(inst, ARM_EOR, $1, $1, $2);
+       }
+       [reg, reg] -> {
+               arm_alu_reg_reg(inst, ARM_EOR, $1, $1, $2);
+       }
+
+JIT_OP_INOT: unary
+       [reg] -> {
+               /* MVN == "move not" */
+               arm_alu_reg(inst, ARM_MVN, $1, $1);
+       }
+
+JIT_OP_ISHL: binary
+       [reg, imm] -> {
+               arm_shift_reg_imm8(inst, ARM_SHL, $1, $1, ($2 & 0x1F));
+       }
+       [reg, reg] -> {
+               arm_alu_reg_imm8(inst, ARM_AND, ARM_WORK, $2, 0x1F);
+               arm_shift_reg_reg(inst, ARM_SHL, $1, $1, ARM_WORK);
+       }
+
+JIT_OP_ISHR: binary
+       [reg, imm] -> {
+               arm_shift_reg_imm8(inst, ARM_SAR, $1, $1, ($2 & 0x1F));
+       }
+       [reg, reg] -> {
+               arm_alu_reg_imm8(inst, ARM_AND, ARM_WORK, $2, 0x1F);
+               arm_shift_reg_reg(inst, ARM_SAR, $1, $1, ARM_WORK);
+       }
+
+JIT_OP_ISHR_UN: binary
+       [reg, imm] -> {
+               arm_shift_reg_imm8(inst, ARM_SHR, $1, $1, ($2 & 0x1F));
+       }
+       [reg, reg] -> {
+               arm_alu_reg_imm8(inst, ARM_AND, ARM_WORK, $2, 0x1F);
+               arm_shift_reg_reg(inst, ARM_SHR, $1, $1, ARM_WORK);
+       }
+
+/*
+ * Branch opcodes.
+ */
+
+JIT_OP_BR: spill_before
+       [] -> {
+               /* ARM_CC_AL == "always branch" */
+               inst = output_branch(func, inst, ARM_CC_AL, insn);
+       }
+
+JIT_OP_BR_IFALSE: unary_branch
+       [reg] -> {
+               arm_test_reg_imm8(inst, ARM_CMP, $1, 0);
+               inst = output_branch(func, inst, ARM_CC_EQ, insn);
+       }
+
+JIT_OP_BR_ITRUE: unary_branch
+       [reg] -> {
+               arm_test_reg_imm8(inst, ARM_CMP, $1, 0);
+               inst = output_branch(func, inst, ARM_CC_NE, insn);
+       }
+
+JIT_OP_BR_IEQ: binary_branch
+       [reg, immu8] -> {
+               arm_test_reg_imm8(inst, ARM_CMP, $1, $2);
+               inst = output_branch(func, inst, ARM_CC_EQ, insn);
+       }
+       [reg, reg] -> {
+               arm_test_reg_reg(inst, ARM_CMP, $1, $2);
+               inst = output_branch(func, inst, ARM_CC_EQ, insn);
+       }
+
+JIT_OP_BR_INE: binary_branch
+       [reg, immu8] -> {
+               arm_test_reg_imm8(inst, ARM_CMP, $1, $2);
+               inst = output_branch(func, inst, ARM_CC_NE, insn);
+       }
+       [reg, reg] -> {
+               arm_test_reg_reg(inst, ARM_CMP, $1, $2);
+               inst = output_branch(func, inst, ARM_CC_NE, insn);
+       }
+
+JIT_OP_BR_ILT: binary_branch
+       [reg, immu8] -> {
+               arm_test_reg_imm8(inst, ARM_CMP, $1, $2);
+               inst = output_branch(func, inst, ARM_CC_LT, insn);
+       }
+       [reg, reg] -> {
+               arm_test_reg_reg(inst, ARM_CMP, $1, $2);
+               inst = output_branch(func, inst, ARM_CC_LT, insn);
+       }
+
+JIT_OP_BR_ILT_UN: binary_branch
+       [reg, immu8] -> {
+               arm_test_reg_imm8(inst, ARM_CMP, $1, $2);
+               inst = output_branch(func, inst, ARM_CC_LT_UN, insn);
+       }
+       [reg, reg] -> {
+               arm_test_reg_reg(inst, ARM_CMP, $1, $2);
+               inst = output_branch(func, inst, ARM_CC_LT_UN, insn);
+       }
+
+JIT_OP_BR_ILE: binary_branch
+       [reg, immu8] -> {
+               arm_test_reg_imm8(inst, ARM_CMP, $1, $2);
+               inst = output_branch(func, inst, ARM_CC_LE, insn);
+       }
+       [reg, reg] -> {
+               arm_test_reg_reg(inst, ARM_CMP, $1, $2);
+               inst = output_branch(func, inst, ARM_CC_LE, insn);
+       }
+
+JIT_OP_BR_ILE_UN: binary_branch
+       [reg, immu8] -> {
+               arm_test_reg_imm8(inst, ARM_CMP, $1, $2);
+               inst = output_branch(func, inst, ARM_CC_LE_UN, insn);
+       }
+       [reg, reg] -> {
+               arm_test_reg_reg(inst, ARM_CMP, $1, $2);
+               inst = output_branch(func, inst, ARM_CC_LE_UN, insn);
+       }
+
+JIT_OP_BR_IGT: binary_branch
+       [reg, immu8] -> {
+               arm_test_reg_imm8(inst, ARM_CMP, $1, $2);
+               inst = output_branch(func, inst, ARM_CC_GT, insn);
+       }
+       [reg, reg] -> {
+               arm_test_reg_reg(inst, ARM_CMP, $1, $2);
+               inst = output_branch(func, inst, ARM_CC_GT, insn);
+       }
+
+JIT_OP_BR_IGT_UN: binary_branch
+       [reg, immu8] -> {
+               arm_test_reg_imm8(inst, ARM_CMP, $1, $2);
+               inst = output_branch(func, inst, ARM_CC_GT_UN, insn);
+       }
+       [reg, reg] -> {
+               arm_test_reg_reg(inst, ARM_CMP, $1, $2);
+               inst = output_branch(func, inst, ARM_CC_GT_UN, insn);
+       }
+
+JIT_OP_BR_IGE: binary_branch
+       [reg, immu8] -> {
+               arm_test_reg_imm8(inst, ARM_CMP, $1, $2);
+               inst = output_branch(func, inst, ARM_CC_GE, insn);
+       }
+       [reg, reg] -> {
+               arm_test_reg_reg(inst, ARM_CMP, $1, $2);
+               inst = output_branch(func, inst, ARM_CC_GE, insn);
+       }
+
+JIT_OP_BR_IGE_UN: binary_branch
+       [reg, immu8] -> {
+               arm_test_reg_imm8(inst, ARM_CMP, $1, $2);
+               inst = output_branch(func, inst, ARM_CC_GE_UN, insn);
+       }
+       [reg, reg] -> {
+               arm_test_reg_reg(inst, ARM_CMP, $1, $2);
+               inst = output_branch(func, inst, ARM_CC_GE_UN, insn);
+       }
+
+/*
+ * Comparison opcodes.
+ */
+
+JIT_OP_ICMP: binary
+       [reg, immu8] -> {
+               arm_test_reg_imm8(inst, ARM_CMP, $1, $2);
+               arm_alu_reg_imm8_cond(inst, ARM_MOV, $1, 0, 1, ARM_CC_GT);
+               arm_alu_reg_imm8_cond(inst, ARM_MOV, $1, 0, 0, ARM_CC_LE);
+               arm_alu_reg_cond(inst, ARM_MVN, $1, $1, ARM_CC_LT);
+       }
+       [reg, reg] -> {
+               arm_test_reg_reg(inst, ARM_CMP, $1, $2);
+               arm_alu_reg_imm8_cond(inst, ARM_MOV, $1, 0, 1, ARM_CC_GT);
+               arm_alu_reg_imm8_cond(inst, ARM_MOV, $1, 0, 0, ARM_CC_LE);
+               arm_alu_reg_cond(inst, ARM_MVN, $1, $1, ARM_CC_LT);
+       }
+
+JIT_OP_ICMP_UN: binary
+       [reg, immu8] -> {
+               arm_test_reg_imm8(inst, ARM_CMP, $1, $2);
+               arm_alu_reg_imm8_cond(inst, ARM_MOV, $1, 0, 1, ARM_CC_GT_UN);
+               arm_alu_reg_imm8_cond(inst, ARM_MOV, $1, 0, 0, ARM_CC_LE_UN);
+               arm_alu_reg_cond(inst, ARM_MVN, $1, $1, ARM_CC_LT_UN);
+       }
+       [reg, reg] -> {
+               arm_test_reg_reg(inst, ARM_CMP, $1, $2);
+               arm_alu_reg_imm8_cond(inst, ARM_MOV, $1, 0, 1, ARM_CC_GT_UN);
+               arm_alu_reg_imm8_cond(inst, ARM_MOV, $1, 0, 0, ARM_CC_LE_UN);
+               arm_alu_reg_cond(inst, ARM_MVN, $1, $1, ARM_CC_LT_UN);
+       }
+
+JIT_OP_IEQ: binary
+       [reg, immu8] -> {
+               arm_test_reg_imm8(inst, ARM_CMP, $1, $2);
+               arm_alu_reg_imm8_cond(inst, ARM_MOV, $1, 0, 1, ARM_CC_EQ);
+               arm_alu_reg_imm8_cond(inst, ARM_MOV, $1, 0, 0, ARM_CC_NE);
+       }
+       [reg, reg] -> {
+               arm_test_reg_reg(inst, ARM_CMP, $1, $2);
+               arm_alu_reg_imm8_cond(inst, ARM_MOV, $1, 0, 1, ARM_CC_EQ);
+               arm_alu_reg_imm8_cond(inst, ARM_MOV, $1, 0, 0, ARM_CC_NE);
+       }
+
+JIT_OP_INE: binary
+       [reg, immu8] -> {
+               arm_test_reg_imm8(inst, ARM_CMP, $1, $2);
+               arm_alu_reg_imm8_cond(inst, ARM_MOV, $1, 0, 1, ARM_CC_NE);
+               arm_alu_reg_imm8_cond(inst, ARM_MOV, $1, 0, 0, ARM_CC_EQ);
+       }
+       [reg, reg] -> {
+               arm_test_reg_reg(inst, ARM_CMP, $1, $2);
+               arm_alu_reg_imm8_cond(inst, ARM_MOV, $1, 0, 1, ARM_CC_NE);
+               arm_alu_reg_imm8_cond(inst, ARM_MOV, $1, 0, 0, ARM_CC_EQ);
+       }
+
+JIT_OP_ILT: binary
+       [reg, immu8] -> {
+               arm_test_reg_imm8(inst, ARM_CMP, $1, $2);
+               arm_alu_reg_imm8_cond(inst, ARM_MOV, $1, 0, 1, ARM_CC_LT);
+               arm_alu_reg_imm8_cond(inst, ARM_MOV, $1, 0, 0, ARM_CC_GE);
+       }
+       [reg, reg] -> {
+               arm_test_reg_reg(inst, ARM_CMP, $1, $2);
+               arm_alu_reg_imm8_cond(inst, ARM_MOV, $1, 0, 1, ARM_CC_LT);
+               arm_alu_reg_imm8_cond(inst, ARM_MOV, $1, 0, 0, ARM_CC_GE);
+       }
+
+JIT_OP_ILT_UN: binary
+       [reg, immu8] -> {
+               arm_test_reg_imm8(inst, ARM_CMP, $1, $2);
+               arm_alu_reg_imm8_cond(inst, ARM_MOV, $1, 0, 1, ARM_CC_LT_UN);
+               arm_alu_reg_imm8_cond(inst, ARM_MOV, $1, 0, 0, ARM_CC_GE_UN);
+       }
+       [reg, reg] -> {
+               arm_test_reg_reg(inst, ARM_CMP, $1, $2);
+               arm_alu_reg_imm8_cond(inst, ARM_MOV, $1, 0, 1, ARM_CC_LT_UN);
+               arm_alu_reg_imm8_cond(inst, ARM_MOV, $1, 0, 0, ARM_CC_GE_UN);
+       }
+
+JIT_OP_ILE: binary
+       [reg, immu8] -> {
+               arm_test_reg_imm8(inst, ARM_CMP, $1, $2);
+               arm_alu_reg_imm8_cond(inst, ARM_MOV, $1, 0, 1, ARM_CC_LE);
+               arm_alu_reg_imm8_cond(inst, ARM_MOV, $1, 0, 0, ARM_CC_GT);
+       }
+       [reg, reg] -> {
+               arm_test_reg_reg(inst, ARM_CMP, $1, $2);
+               arm_alu_reg_imm8_cond(inst, ARM_MOV, $1, 0, 1, ARM_CC_LE);
+               arm_alu_reg_imm8_cond(inst, ARM_MOV, $1, 0, 0, ARM_CC_GT);
+       }
+
+JIT_OP_ILE_UN: binary
+       [reg, immu8] -> {
+               arm_test_reg_imm8(inst, ARM_CMP, $1, $2);
+               arm_alu_reg_imm8_cond(inst, ARM_MOV, $1, 0, 1, ARM_CC_LE_UN);
+               arm_alu_reg_imm8_cond(inst, ARM_MOV, $1, 0, 0, ARM_CC_GT_UN);
+       }
+       [reg, reg] -> {
+               arm_test_reg_reg(inst, ARM_CMP, $1, $2);
+               arm_alu_reg_imm8_cond(inst, ARM_MOV, $1, 0, 1, ARM_CC_LE_UN);
+               arm_alu_reg_imm8_cond(inst, ARM_MOV, $1, 0, 0, ARM_CC_GT_UN);
+       }
+
+JIT_OP_IGT: binary
+       [reg, immu8] -> {
+               arm_test_reg_imm8(inst, ARM_CMP, $1, $2);
+               arm_alu_reg_imm8_cond(inst, ARM_MOV, $1, 0, 1, ARM_CC_GT);
+               arm_alu_reg_imm8_cond(inst, ARM_MOV, $1, 0, 0, ARM_CC_LE);
+       }
+       [reg, reg] -> {
+               arm_test_reg_reg(inst, ARM_CMP, $1, $2);
+               arm_alu_reg_imm8_cond(inst, ARM_MOV, $1, 0, 1, ARM_CC_GT);
+               arm_alu_reg_imm8_cond(inst, ARM_MOV, $1, 0, 0, ARM_CC_LE);
+       }
+
+JIT_OP_IGT_UN: binary
+       [reg, immu8] -> {
+               arm_test_reg_imm8(inst, ARM_CMP, $1, $2);
+               arm_alu_reg_imm8_cond(inst, ARM_MOV, $1, 0, 1, ARM_CC_GT_UN);
+               arm_alu_reg_imm8_cond(inst, ARM_MOV, $1, 0, 0, ARM_CC_LE_UN);
+       }
+       [reg, reg] -> {
+               arm_test_reg_reg(inst, ARM_CMP, $1, $2);
+               arm_alu_reg_imm8_cond(inst, ARM_MOV, $1, 0, 1, ARM_CC_GT_UN);
+               arm_alu_reg_imm8_cond(inst, ARM_MOV, $1, 0, 0, ARM_CC_LE_UN);
+       }
+
+JIT_OP_IGE: binary
+       [reg, immu8] -> {
+               arm_test_reg_imm8(inst, ARM_CMP, $1, $2);
+               arm_alu_reg_imm8_cond(inst, ARM_MOV, $1, 0, 1, ARM_CC_GE);
+               arm_alu_reg_imm8_cond(inst, ARM_MOV, $1, 0, 0, ARM_CC_LT);
+       }
+       [reg, reg] -> {
+               arm_test_reg_reg(inst, ARM_CMP, $1, $2);
+               arm_alu_reg_imm8_cond(inst, ARM_MOV, $1, 0, 1, ARM_CC_GE);
+               arm_alu_reg_imm8_cond(inst, ARM_MOV, $1, 0, 0, ARM_CC_LT);
+       }
+
+JIT_OP_IGE_UN: binary
+       [reg, immu8] -> {
+               arm_test_reg_imm8(inst, ARM_CMP, $1, $2);
+               arm_alu_reg_imm8_cond(inst, ARM_MOV, $1, 0, 1, ARM_CC_GE_UN);
+               arm_alu_reg_imm8_cond(inst, ARM_MOV, $1, 0, 0, ARM_CC_LT_UN);
+       }
+       [reg, reg] -> {
+               arm_test_reg_reg(inst, ARM_CMP, $1, $2);
+               arm_alu_reg_imm8_cond(inst, ARM_MOV, $1, 0, 1, ARM_CC_GE_UN);
+               arm_alu_reg_imm8_cond(inst, ARM_MOV, $1, 0, 0, ARM_CC_LT_UN);
+       }
+