On Fri, Aug 02, 2002 at 01:06:27AM -0300, Daniel Grunblatt wrote:
> 
> On Thu, 1 Aug 2002, Nicholas Clark wrote:
> 
> > Here goes. This *isn't* functional - it's the least amount of work I could
> > get away with (before midnight) that gets the inner loop of mops.pasm JITted.
> >
> 
> Applied, many many thanks.
> 
> > including this judicious bit of cheating:
> > because I need if_i_ic JITted but mops only needs backwards jumps (which are
> > easy, and don't require me to write the fixup routine yet)
> 
> We can wait, no problem.

I wasn't actually expecting you to apply that :-)
It was more a "where I am at now" informational patch.

I think that this patch is at good point to pause and take stock. I believe
it JITs just about every integer op (including some i386 isn't JITting yet)
OK, it doesn't JIT the logical xor op, but that one scares me, and I'm unsure
how useful it is.

I've not done the floating point ops (or anything else) partly because I
don't have a good reference for the format of the floating point instructions.
[However, it's not that hard, as I have source code to both point emulators
supplied with ARM Linux, so I can see the decode code :-)]
But more because I'm not sure that it will give such a speed it.

I feel I've demonstrated to myself that it will be possible to generate all
forms of parrot ops without undue problems. However, I've hardly used any
registers in my ops so far (at most 3, but I only actually needed 2) when
there are up to 12 at my disposal. I've no real idea which will turn out to
be the most useful in real parrot programs, and hence where the effort in
JITting will get most reward, so I think it best to wait now and see what
is needed most.

My other thought is that with the current JIT architecture I'm loading
everything from RAM at the start of the ops (1 or 2 instructions), and save it
back at the end (1 instruction) with only 1 or 2 instructions need to actually
do the work. With 10 registers spare, and 60% of my instructions shifting data
around like some job creation scheme for out of work electrons, I think that
it might be best to wait and see what we (*) learn from JITs on other
platforms, then use that to design a third generation JIT that is capable of
mapping parrot registers onto hardware CPU registers.

* Er, "we" is probably just Daniel as I confess I don't feel motivated to
attempt to learn other assembly language to write JITs for hardware I don't
own. Hey, all you Mac fans, where's the PPC JIT? <ducks>

Nicholas Clark
-- 
Even better than the real thing:        http://nms-cgi.sourceforge.net/

--- jit/arm/jit_emit.h.orig     Fri Aug  2 04:25:05 2002
+++ jit/arm/jit_emit.h  Sat Aug  3 18:39:12 2002
@@ -154,7 +154,8 @@ typedef enum {
 
 /* IIRC bx is branch into thumb mode, so don't name this back to bx  */
 
-char *emit_branch(char *pc,
+static char *
+emit_branch(char *pc,
                   arm_cond_t cond,
                   int L,
                   int imm) {
@@ -216,14 +217,16 @@ typedef enum {
     dir_Down = 0x00
 } ldr_str_dir_t;
 
-char *
+enum { JIT_ARMBRANCH };
+
+static char *
 emit_ldmstm_x(char *pc,
              arm_cond_t cond,
              int l_s,
              ldm_stm_dir_t direction,
              int caret,
              int writeback,
-             int base,
+             arm_register_t base,
              int regmask) {
     if ((l_s == is_load) && (direction & 0x10))
         direction >>= 2;
@@ -306,7 +309,7 @@ emit_ldmstm_x(char *pc,
  * you'll get silent undefined behaviour.
  */
 
-char *
+static char *
 emit_ldrstr(char *pc,
             arm_cond_t cond,
             int l_s,
@@ -314,8 +317,8 @@ emit_ldrstr(char *pc,
             int pre,
             int writeback,
             int byte, 
-            int dest,
-            int base,
+            arm_register_t dest,
+            arm_register_t base,
             int offset_type,
             unsigned int offset) {
 
@@ -326,15 +329,15 @@ emit_ldrstr(char *pc,
     return pc;
 }
 
-char *
+static char *
 emit_ldrstr_offset (char *pc,
                     arm_cond_t cond,
                     int l_s,
                     int pre,
                     int writeback,
                     int byte,
-                    int dest,
-                    int base,
+                    arm_register_t dest,
+                    arm_register_t base,
                     int offset) {
     ldr_str_dir_t direction = dir_Up;
     if (offset > 4095 || offset < -4095) {
@@ -391,7 +394,7 @@ typedef enum {
 /* RRX (rotate right with extend - a 1 position 33 bit rotate including the
    carry flag) is encoded as ROR by 0.  */
 
-char *
+static char *
 emit_arith(char *pc,
            arm_cond_t cond,
            alu_op_t op,
@@ -407,6 +410,130 @@ emit_arith(char *pc,
     return pc;
 }
 
+static char *
+emit_mul(char *pc,
+         arm_cond_t cond,
+         int status,
+         arm_register_t rd,
+         arm_register_t rm,
+         arm_register_t rs) {
+    *(pc++) = 0x90 | rm;
+    *(pc++) = rs;
+    *(pc++) = status | rd;
+    *(pc++) = cond | 0;
+    return pc;
+}
+
+static char *
+emit_mla(char *pc,
+         arm_cond_t cond,
+         int status,
+         arm_register_t rd,
+         arm_register_t rm,
+         arm_register_t rs,
+         arm_register_t rn) {
+    *(pc++) = 0x90 | rm;
+    *(pc++) = rn << 4 | rs;
+    *(pc++) = 0x20 | status | rd;
+    *(pc++) = cond | 0;
+    return pc;
+}
+
+/* operand2 immedate constants are expressed as val rotate right (2 * n),
+   where val is 8 bits, n is 4 bits. This uses the 12 bits available to
+   generate many useful common constants, far more than would be given by a
+   12 bit number 0 - 0xFFF.
+   Often, you're trying to use the immediate constant in an operand that could
+   be replaced its complement. So if MOV rd, #const doesn't work,
+   MVN rn, #~const might. And ADD rd, rn, #const may be impossible, but
+   SUB rd, rn, #-const will. So allow the return struct to flag this.
+
+   I believe that the only case where a 32 bit value and its converse is
+   representable in 8 shift 4 is for 0 and -(0)
+   So it's perfectly valid to try the inverse every time.  */
+
+
+enum constant_state {doesnt_fit, fits_as_not, fits_as_neg, fits_as_is};
+
+/* Deliberate 4th char to pad the struct and hence silence a warning.  */
+struct constant {
+    unsigned char value;
+    unsigned char rotation;
+    unsigned char state;
+    unsigned char pad;
+};
+/* XXX Future work would be to try to find a fast compramise way of looking
+   for the double instruction constants. eg 0xFFF is 0xF00 + 0xFF, or
+   0xF00 | 0xFF
+   The problem comes that for building an immediate constant all combinations
+   are on (ie MOV followed by anything, including hacks with setting the carry
+   flag using non-standard rotations) but for add_i_i_ic you probably only
+   want to break down into two halves that are in turn each added/subtracted.
+*/
+
+static void
+constant_neg (int value,  struct constant *result) {
+    result->rotation = 0;
+    while (1) {
+        if ((value & ~0xFF) == 0) {
+            /* No bits spill out.  */
+            result->state = fits_as_is;
+            result->value = value;
+            return;
+        }
+        if (((-value) & ~0xFF) == 0) {
+            result->value = -value;
+            result->state = fits_as_neg;
+            return;
+        }
+        if (++result->rotation == 16)
+            break;
+
+        /* There is no rotate op in C, and to do it with 2 shifts and an or
+           would mean casting to unsigned to prevent sign extensions, and it's
+           exactly 1 arm instruction I need, so it's clearer like this:  */
+        __asm__ (
+            "mov     %0, %1, ror #30\n"
+            : "=r" (value)
+            : "r" (value));
+        
+    } 
+    result->state = doesnt_fit;
+    return;
+}
+
+
+static void
+constant_not (int value,  struct constant *result) {
+    result->rotation = 0;
+    while (1) {
+        if ((value & ~0xFF) == 0) {
+            /* No bits spill out.  */
+            result->state = fits_as_is;
+            result->value = value;
+            return;
+        }
+        if (((~value) & ~0xFF) == 0) {
+            result->value = ~value;
+            result->state = fits_as_not;
+            return;
+        }
+        if (++result->rotation == 16)
+            break;
+
+        /* There is no rotate op in C, and to do it with 2 shifts and an or
+           would mean casting to unsigned to prevent sign extensions, and it's
+           exactly 1 arm instruction I need, so it's clearer like this:  */
+        __asm__ (
+            "mov     %0, %1, ror #30\n"
+            : "=r" (value)
+            : "r" (value));
+        
+    } 
+    result->state = doesnt_fit;
+    return;
+}
+
 /* eg add r0, r3, r7  */
 #define emit_arith_reg(pc, cond, op, status, rd, rn, rm) \
        emit_arith (pc, cond, op, status, rd, rn, 0, rm)
@@ -432,14 +559,84 @@ emit_arith(char *pc,
 /* MOV ignores rn  */
 #define emit_mov(pc, dest, src) emit_arith_reg (pc, cond_AL, MOV, 0, dest, 0, src)
 
-#define emit_dcd(pc, word)  { \
-    *((int *)pc) = word; \
-    pc+=4; }
+static char *
+emit_word(char *pc, unsigned int word) {
+    *(pc++) = word;
+    *(pc++) = word >> 8;
+    *(pc++) = word >> 16;
+    *(pc++) = word >> 24;
+    return pc;
+}
+
+static void emit_jump_to_op(Parrot_jit_info *jit_info, arm_cond_t cond,
+                            opcode_t disp) {
+    opcode_t opcode = jit_info->op_i + disp;
+    int offset = 0;
+    if(opcode <= jit_info->op_i) {
+        offset = jit_info->op_map[opcode].offset -
+            (jit_info->native_ptr - jit_info->arena_start);
+    } else {
+        Parrot_jit_newfixup(jit_info); 
+        jit_info->fixups->type = JIT_ARMBRANCH;
+        jit_info->fixups->param.opcode = opcode;
+    }
+
+    jit_info->native_ptr
+        = emit_branch(jit_info->native_ptr, cond, 0, (offset >> 2) - 2);
+}
+
+static char *
+emit_load_constant_from_pool (char *pc,
+                              struct Parrot_Interp *interpreter,
+                              arm_cond_t cond,
+                              int value,
+                              arm_register_t hwreg) {
+    /* can't do it in one.  XXX this should use a constant pool.
+       ldr  rd, [pc]   ; pipelining makes this .L1
+       b    L2
+       .L1 value
+       .L2 next
+    */
+
+    pc = emit_ldrstr_offset (pc, cond,
+                             is_load, is_pre,
+                             0, 0,
+                             hwreg,
+                             REG15_pc, 0);
+    /* Must always jump round our inlined constant, if if we don't load it
+       (due to condition codes) */
+    pc = emit_b(pc, cond_AL, 0);
+    pc = emit_word (pc, value);
+    return pc;
+}   
+
+static char *
+emit_load_constant (char *pc,
+                    struct Parrot_Interp *interpreter,
+                    arm_cond_t cond,
+                    int value,
+                    arm_register_t hwreg) {
+    struct constant immediate;
+
+    constant_not (value, &immediate);
+
+    if (immediate.state == fits_as_is) {
+        pc = emit_arith_immediate(pc, cond, MOV, 0, hwreg, 0,
+                                  immediate.value, immediate.rotation);
+    } else if (immediate.state == fits_as_not) {
+        pc = emit_arith_immediate(pc, cond, MVN, 0, hwreg, 0,
+                                   immediate.value, immediate.rotation);
+    } else {
+        pc = emit_load_constant_from_pool (pc, interpreter, cond, value, hwreg);
+    }
+    return pc;
+}   
 
 static void Parrot_jit_int_load(Parrot_jit_info *jit_info,
-                             struct Parrot_Interp *interpreter,
-                             int param,
-                             int hwreg)
+                                struct Parrot_Interp *interpreter,
+                                arm_cond_t cond,
+                                int param,
+                                arm_register_t hwreg)
 {
     opcode_t op_type
         = interpreter->op_info_table[*jit_info->cur_op].types[param];
@@ -456,7 +653,7 @@ static void Parrot_jit_int_load(Parrot_j
                            val, offset);
             }
             jit_info->native_ptr = emit_ldrstr_offset (jit_info->native_ptr,
-                                                       cond_AL,
+                                                       cond,
                                                        is_load,
                                                        is_pre,
                                                        0, 0,
@@ -464,8 +661,13 @@ static void Parrot_jit_int_load(Parrot_j
                                                        INTERP_STRUCT_ADDR_REG,
                                                        offset);
             break;
-
         case PARROT_ARG_IC:
+            jit_info->native_ptr = emit_load_constant (jit_info->native_ptr,
+                                                       interpreter,
+                                                       cond,
+                                                       val,
+                                                       hwreg);
+            break;
         default:
             internal_exception(JIT_ERROR,
                                "Unsupported op parameter type %d in jit_int_load\n",
@@ -474,9 +676,10 @@ static void Parrot_jit_int_load(Parrot_j
 }
 
 static void Parrot_jit_int_store(Parrot_jit_info *jit_info,
-                             struct Parrot_Interp *interpreter,
-                             int param,
-                             int hwreg)
+                                 struct Parrot_Interp *interpreter,
+                                 arm_cond_t cond,
+                                 int param,
+                                 arm_register_t hwreg)
 {
     opcode_t op_type
          = interpreter->op_info_table[*jit_info->cur_op].types[param];
@@ -493,7 +696,7 @@ static void Parrot_jit_int_store(Parrot_
                            val, offset);
             }
             jit_info->native_ptr = emit_ldrstr_offset (jit_info->native_ptr,
-                                                       cond_AL,
+                                                       cond,
                                                        is_store,
                                                        is_pre,
                                                        0, 0,
@@ -510,26 +713,118 @@ static void Parrot_jit_int_store(Parrot_
     }
 }
 
-static void emit_jump_to_op(Parrot_jit_info *jit_info, arm_cond_t cond,
-                            int L, opcode_t disp) {
-    opcode_t opcode = jit_info->op_i + disp;
+static void
+Parrot_jit_arith_const_alternate (Parrot_jit_info *jit_info, 
+                                  struct Parrot_Interp *interpreter,
+                                  arm_cond_t cond,
+                                  enum constant_state alternate_on,
+                                  alu_op_t normal, alu_op_t alternative,
+                                  int dest, int src, int const_val) {
+    struct constant val;
+
+    Parrot_jit_int_load(jit_info, interpreter, cond, src, r0);
+
+    constant_neg (const_val, &val);
+
+    if (val.state == fits_as_is || val.state == alternate_on) {
+        /* We can use an immediate constant.  */
+        /* say plus is ADD, minus is SUB
+           Then if value fits into an immediate constant, we add r0, r0, #value
+           If -value fits, then we sub, r0, r0, #-value
+        */
+        jit_info->native_ptr
+            = emit_arith_immediate (jit_info->native_ptr, cond,
+                                    val.state == fits_as_is
+                                    ? normal : alternative,
+                                    0, r0, r0, val.value, val.rotation);
+    } else {
+        /* Else we load it into a reg the slow way. */
+        jit_info->native_ptr
+            = emit_load_constant_from_pool (jit_info->native_ptr, interpreter,
+                                            cond, const_val, r1);
+        jit_info->native_ptr
+            = emit_arith_reg (jit_info->native_ptr, cond, normal, 0,
+                              r0, r0, r1);
+    }
+    Parrot_jit_int_store(jit_info, interpreter, cond, dest, r0);
+}
 
-    if(opcode <= jit_info->op_i) {
-        int offset = jit_info->op_map[opcode].offset -
-            (jit_info->native_ptr - jit_info->arena_start);
+#define Parrot_jit_arith_const_neg(ji, i, cond, plus, minus, dest, src, const_val) \
+    Parrot_jit_arith_const_alternate (ji, i, cond, fits_as_neg, \
+                                     plus, minus, dest, src, const_val)
+
+#define Parrot_jit_arith_const_not(ji, i, cond, plus, minus, dest, src, const_val) \
+    Parrot_jit_arith_const_alternate (ji, i, cond, fits_as_not, \
+                                     plus, minus, dest, src, const_val)
+#define Parrot_jit_arith_const(ji, i, cond, plus, dest, src, const_val) \
+    Parrot_jit_arith_const_alternate (ji, i, cond, fits_as_is, \
+                                     plus, plus, dest, src, const_val)
+
+
+/* branching on if cannot (in future) be conditional (easily), because we
+   want to set the flags.
+   Yes, for seriously advanced stuff you can
+   1: chain compatible comparisons (eg someting setting LE and something else
+      setting LE can be done with the second conditional)
+   2: use TEQ which doesn't change the V flag (or C, IIRC), and chain that with
+      someting else that did set the V flag
 
+   but that's JIT v5 or later (where v3 can hold intermediate values in CPU
+   registers, and v4 can do some things conditionally)
+*/
+static void
+Parrot_jit_jumpif_const (Parrot_jit_info *jit_info, 
+                         struct Parrot_Interp *interpreter,
+                         int src, int const_val, int where_to,
+                         arm_cond_t when) {
+    struct constant val;
+
+    Parrot_jit_int_load(jit_info, interpreter, cond_AL, src, r0);
+
+    constant_neg (const_val, &val);
+
+    if (val.state == fits_as_is || val.state == fits_as_neg) {
+        /* We can use an immediate constant.  */
+        jit_info->native_ptr
+            = emit_arith_immediate (jit_info->native_ptr, cond_AL,
+                                    val.state == fits_as_is ? CMP : CMN, 0,
+                                    0, r0, val.value, val.rotation);
+    } else {
+        /* Else we load it into a reg the slow way. */
         jit_info->native_ptr
-            = emit_branch(jit_info->native_ptr, cond, L, (offset >> 2) - 2);
-        return;
+            = emit_load_constant_from_pool (jit_info->native_ptr, interpreter,
+                                            cond_AL, const_val, r1);
+        jit_info->native_ptr
+            = emit_arith_reg (jit_info->native_ptr, cond_AL, CMP, 0, 0, r0, r1);
     }
-    internal_exception(JIT_ERROR, "Can't go forward yet\n");
-    
+    emit_jump_to_op (jit_info, when, where_to);
 }
 
 void Parrot_jit_dofixup(Parrot_jit_info *jit_info,
                         struct Parrot_Interp * interpreter)
 {
-    /* Todo.  */
+    Parrot_jit_fixup *fixup = jit_info->fixups;
+
+    while(fixup){
+        switch(fixup->type){
+            case JIT_ARMBRANCH:
+            {
+                char *fixup_ptr = Parrot_jit_fixup_target(jit_info, fixup);
+                int offset = jit_info->op_map[fixup->param.opcode].offset
+                    - fixup->native_offset;
+                int disp = (offset >> 2) - 2;
+                *(fixup_ptr++) = disp; 
+                *(fixup_ptr++) = disp >> 8; 
+                *(fixup_ptr) = disp >> 16; 
+                break;
+            }
+            default:
+                internal_exception(JIT_ERROR, "Unknown fixup type:%d\n",
+                                   fixup->type);
+                break;
+        }
+        fixup = fixup->next;
+    }
 }
 /* My entry code is create a stack frame:
        mov     ip, sp
@@ -612,19 +907,17 @@ Parrot_jit_normal_op(Parrot_jit_info *ji
                                         reg2mask(0) | reg2mask(REG12_ip));
     jit_info->native_ptr = emit_mov (jit_info->native_ptr, REG15_pc, REG12_ip);
 #endif
-    emit_dcd (jit_info->native_ptr, (int) jit_info->cur_op);
-    emit_dcd (jit_info->native_ptr,
-              (int) interpreter->op_func_table[*(jit_info->cur_op)]);
+    jit_info->native_ptr
+        = emit_word (jit_info->native_ptr, (int) jit_info->cur_op);
+    jit_info->native_ptr
+        = emit_word (jit_info->native_ptr,
+                     (int) interpreter->op_func_table[*(jit_info->cur_op)]);
 }
 
-/* We get back address of opcode in bytecode.
-   We want address of equivalent bit of jit code, which is stored as an
-   address at the same offset in a jit table. */
-void Parrot_jit_cpcf_op(Parrot_jit_info *jit_info,
-                        struct Parrot_Interp * interpreter)
-{
-    Parrot_jit_normal_op(jit_info, interpreter);
-
+static void
+Parrot_jump_to_op_in_reg(Parrot_jit_info *jit_info,
+                         struct Parrot_Interp * interpreter,
+                         arm_register_t reg) {
     /* This is effectively the pseudo-opcode ldr - ie load relative to PC.
        So offset includes pipeline.  */
     jit_info->native_ptr = emit_ldrstr_offset (jit_info->native_ptr, cond_AL,
@@ -633,13 +926,24 @@ void Parrot_jit_cpcf_op(Parrot_jit_info 
     /* ldr pc, [r14, r0]  */
     /* lazy. this is offset type 0, 0x000 which is r0 with zero shift  */
     jit_info->native_ptr = emit_ldrstr (jit_info->native_ptr, cond_AL,
-                                        is_load, dir_Up, is_pre, 0, 0,
+                                        is_load, dir_Up, is_pre, 0, reg,
                                         REG15_pc, REG14_lr, 2, 0);
     /* and this "instruction" is never reached, so we can use it to store
        the constant that we load into r14  */
-    emit_dcd (jit_info->native_ptr,
-              ((long) jit_info->op_map) -
-              ((long) interpreter->code->byte_code));
+    jit_info->native_ptr
+        = emit_word (jit_info->native_ptr,
+                     ((int) jit_info->op_map) -
+                     ((int) interpreter->code->byte_code));
+}
+
+/* We get back address of opcode in bytecode.
+   We want address of equivalent bit of jit code, which is stored as an
+   address at the same offset in a jit table. */
+void Parrot_jit_cpcf_op(Parrot_jit_info *jit_info,
+                        struct Parrot_Interp * interpreter)
+{
+    Parrot_jit_normal_op(jit_info, interpreter);
+    Parrot_jump_to_op_in_reg(jit_info, interpreter, r0);
 }
 
 /*
--- jit/arm/core.jit.orig       Fri Aug  2 04:25:05 2002
+++ jit/arm/core.jit    Sat Aug  3 18:33:50 2002
@@ -42,30 +42,598 @@ Parrot_end {
 ; nothing :-)] and choose how to maximise use of as many real CPU registers as
 ; possible.
 
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+; set ops
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+
 Parrot_set_i_i {
-    Parrot_jit_int_load(jit_info, interpreter, 2, r0);
-    Parrot_jit_int_store(jit_info, interpreter, 1, r0);
+    Parrot_jit_int_load(jit_info, interpreter, cond_AL, 2, r0);
+    Parrot_jit_int_store(jit_info, interpreter, cond_AL, 1, r0);
+}
+Parrot_set_i_ic {
+    Parrot_jit_int_load(jit_info, interpreter, cond_AL, 2, r0);
+    Parrot_jit_int_store(jit_info, interpreter, cond_AL, 1, r0);
+}
+
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+; comparison ops
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+
+Parrot_eq_i_i_ic {
+    Parrot_jit_int_load(jit_info, interpreter, cond_AL, 1, r0);
+    Parrot_jit_int_load(jit_info, interpreter, cond_AL, 2, r1);
+    jit_info->native_ptr = emit_arith_reg (jit_info->native_ptr, cond_AL,
+                                                 CMP, 0, 0, r0, r1);
+    emit_jump_to_op (jit_info, cond_EQ, *INT_CONST[3]);
+}
+Parrot_eq_i_ic_ic {
+    Parrot_jit_jumpif_const (jit_info, interpreter, 1, *INT_CONST[2],
+                             *INT_CONST[3], cond_EQ);
+}
+Parrot_eq_ic_i_ic {
+    Parrot_jit_jumpif_const (jit_info, interpreter, 2, *INT_CONST[1],
+                             *INT_CONST[3], cond_EQ);
+}
+Parrot_eq_ic_ic_ic {
+    if (*INT_CONST[1] == *INT_CONST[2])
+        emit_jump_to_op (jit_info, cond_AL, *INT_CONST[3]);
+}
+
+Parrot_ne_i_i_ic {
+    Parrot_jit_int_load(jit_info, interpreter, cond_AL, 1, r0);
+    Parrot_jit_int_load(jit_info, interpreter, cond_AL, 2, r1);
+    jit_info->native_ptr = emit_arith_reg (jit_info->native_ptr, cond_AL,
+                                                 CMP, 0, 0, r0, r1);
+    emit_jump_to_op (jit_info, cond_NE, *INT_CONST[3]);
+}
+Parrot_ne_i_ic_ic {
+    Parrot_jit_jumpif_const (jit_info, interpreter, 1, *INT_CONST[2],
+                             *INT_CONST[3], cond_NE);
+}
+Parrot_ne_ic_i_ic {
+    Parrot_jit_jumpif_const (jit_info, interpreter, 2, *INT_CONST[1],
+                             *INT_CONST[3], cond_NE);
+}
+Parrot_ne_ic_ic_ic {
+    if (*INT_CONST[1] != *INT_CONST[2])
+        emit_jump_to_op (jit_info, cond_AL, *INT_CONST[3]);
+}
+
+Parrot_lt_i_i_ic {
+    Parrot_jit_int_load(jit_info, interpreter, cond_AL, 1, r0);
+    Parrot_jit_int_load(jit_info, interpreter, cond_AL, 2, r1);
+    jit_info->native_ptr = emit_arith_reg (jit_info->native_ptr, cond_AL,
+                                                 CMP, 0, 0, r0, r1);
+    emit_jump_to_op (jit_info, cond_LT, *INT_CONST[3]);
+}
+Parrot_lt_i_ic_ic {
+    Parrot_jit_jumpif_const (jit_info, interpreter, 1, *INT_CONST[2],
+                             *INT_CONST[3], cond_LT);
+}
+Parrot_lt_ic_i_ic {
+    Parrot_jit_jumpif_const (jit_info, interpreter, 2, *INT_CONST[1],
+                             *INT_CONST[3], cond_GE);
+}
+Parrot_lt_ic_ic_ic {
+    if (*INT_CONST[1] < *INT_CONST[2])
+        emit_jump_to_op (jit_info, cond_AL, *INT_CONST[3]);
+}
+
+Parrot_le_i_i_ic {
+    Parrot_jit_int_load(jit_info, interpreter, cond_AL, 1, r0);
+    Parrot_jit_int_load(jit_info, interpreter, cond_AL, 2, r1);
+    jit_info->native_ptr = emit_arith_reg (jit_info->native_ptr, cond_AL,
+                                                 CMP, 0, 0, r0, r1);
+    emit_jump_to_op (jit_info, cond_LE, *INT_CONST[3]);
+}
+Parrot_le_i_ic_ic {
+    Parrot_jit_jumpif_const (jit_info, interpreter, 1, *INT_CONST[2],
+                             *INT_CONST[3], cond_LE);
+}
+Parrot_le_ic_i_ic {
+    Parrot_jit_jumpif_const (jit_info, interpreter, 2, *INT_CONST[1],
+                             *INT_CONST[3], cond_GT);
+}
+Parrot_le_ic_ic_ic {
+    if (*INT_CONST[1] <= *INT_CONST[2])
+        emit_jump_to_op (jit_info, cond_AL, *INT_CONST[3]);
+}
+
+Parrot_gt_i_i_ic {
+    Parrot_jit_int_load(jit_info, interpreter, cond_AL, 1, r0);
+    Parrot_jit_int_load(jit_info, interpreter, cond_AL, 2, r1);
+    jit_info->native_ptr = emit_arith_reg (jit_info->native_ptr, cond_AL,
+                                                 CMP, 0, 0, r0, r1);
+    emit_jump_to_op (jit_info, cond_GT, *INT_CONST[3]);
+}
+Parrot_gt_i_ic_ic {
+    Parrot_jit_jumpif_const (jit_info, interpreter, 1, *INT_CONST[2],
+                             *INT_CONST[3], cond_GT);
+}
+Parrot_gt_ic_i_ic {
+    Parrot_jit_jumpif_const (jit_info, interpreter, 2, *INT_CONST[1],
+                             *INT_CONST[3], cond_LE);
+}
+Parrot_gt_ic_ic_ic {
+    if (*INT_CONST[1] > *INT_CONST[2])
+        emit_jump_to_op (jit_info, cond_AL, *INT_CONST[3]);
 }
 
+Parrot_ge_i_i_ic {
+    Parrot_jit_int_load(jit_info, interpreter, cond_AL, 1, r0);
+    Parrot_jit_int_load(jit_info, interpreter, cond_AL, 2, r1);
+    jit_info->native_ptr = emit_arith_reg (jit_info->native_ptr, cond_AL,
+                                                 CMP, 0, 0, r0, r1);
+    emit_jump_to_op (jit_info, cond_GE, *INT_CONST[3]);
+}
+Parrot_ge_i_ic_ic {
+    Parrot_jit_jumpif_const (jit_info, interpreter, 1, *INT_CONST[2],
+                             *INT_CONST[3], cond_GE);
+}
+Parrot_ge_ic_i_ic {
+    Parrot_jit_jumpif_const (jit_info, interpreter, 2, *INT_CONST[1],
+                             *INT_CONST[3], cond_LT);
+}
+Parrot_ge_ic_ic_ic {
+    if (*INT_CONST[1] >= *INT_CONST[2])
+        emit_jump_to_op (jit_info, cond_AL, *INT_CONST[3]);
+}
+
+Parrot_if_i_ic {
+    Parrot_jit_jumpif_const (jit_info, interpreter, 1, 0, *INT_CONST[2],
+                             cond_NE);
+}
+Parrot_unless_i_ic {
+    Parrot_jit_jumpif_const (jit_info, interpreter, 1, 0, *INT_CONST[2],
+                             cond_EQ);
+}
+
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+; arithmetic ops
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+
+Parrot_abs_i_ic {
+    jit_info->native_ptr = emit_load_constant (jit_info->native_ptr,
+                                               interpreter, cond_AL,
+                                               (*INT_CONST[2] < 0)
+                                               ? -*INT_CONST[2] : *INT_CONST[2],
+                                               r0);
+    Parrot_jit_int_store(jit_info, interpreter, cond_AL, 1, r0);
+}
+;
+; maybe not the best way:
+; cmp   r0, #0
+; rsblt r0, r0, #0
+;
+Parrot_abs_i_i {
+    Parrot_jit_int_load(jit_info, interpreter, cond_AL, 2, r0);
+    jit_info->native_ptr = emit_arith_immediate (jit_info->native_ptr, cond_AL,
+                                                 CMP, 0, 0, r0, 0, 0);
+    jit_info->native_ptr = emit_arith_immediate (jit_info->native_ptr, cond_LT,
+                                                 RSB, 0, r0, r0, 0, 0);
+    Parrot_jit_int_store(jit_info, interpreter, cond_AL, 1, r0);
+}
+;
+; rsbs  r0, r0, #0
+; strgt r0, [...]
+;
+;Parrot_abs_i {
+;    Parrot_jit_int_laod(jit_info, interpreter, cond_AL, 1, r0);
+;    jit_info->native_ptr = emit_arith_immediate (jit_info->native_ptr, cond_AL,
+;                                                 RSB, arith_sets_S,
+;                                                 r0, r0, 0, 0);
+;    Parrot_jit_int_store(jit_info, interpreter, cond_GT, 1, r0);
+;}
+
 Parrot_add_i_i_i {
-    Parrot_jit_int_load(jit_info, interpreter, 2, r0);
-    Parrot_jit_int_load(jit_info, interpreter, 3, r1);
+    Parrot_jit_int_load(jit_info, interpreter, cond_AL, 2, r0);
+    Parrot_jit_int_load(jit_info, interpreter, cond_AL, 3, r1);
     jit_info->native_ptr = emit_arith_reg (jit_info->native_ptr, cond_AL,
                                                  ADD, 0, r2, r0, r1);
-    Parrot_jit_int_store(jit_info, interpreter, 1, r2);
+    Parrot_jit_int_store(jit_info, interpreter, cond_AL, 1, r2);
 }
+Parrot_add_i_i_ic {
+    Parrot_jit_arith_const_neg (jit_info, interpreter, cond_AL, ADD, SUB,
+        1, 2, *INT_CONST[3]);
+}
+Parrot_add_i_ic_i {
+    Parrot_jit_arith_const_neg (jit_info, interpreter, cond_AL, ADD, SUB,
+        1, 3, *INT_CONST[2]);
+}
+Parrot_add_i_ic_ic {
+    jit_info->native_ptr = emit_load_constant (jit_info->native_ptr,
+                                               interpreter,
+                                               cond_AL,
+                                               *INT_CONST[2] + *INT_CONST[3],
+                                               r0);
+    Parrot_jit_int_store(jit_info, interpreter, cond_AL, 1, r0);
+}
+Parrot_add_i_ic {
+    Parrot_jit_arith_const_neg (jit_info, interpreter, cond_AL, ADD, SUB,
+        1, 1, *INT_CONST[2]);
+}
+
+Parrot_dec_i {
+    Parrot_jit_arith_const_neg (jit_info, interpreter, cond_AL, SUB, ADD,
+        1, 1, 1);
+}
+Parrot_inc_i {
+    Parrot_jit_arith_const_neg (jit_info, interpreter, cond_AL, ADD, SUB,
+        1, 1, 1);
+}
+
+; mul can't do immediate constants, and there are restrictions on which
+; registers you can use. (IIRC rd and rn can't be the same register)
+Parrot_mul_i_i {
+    Parrot_jit_int_load(jit_info, interpreter, cond_AL, 1, r0);
+    Parrot_jit_int_load(jit_info, interpreter, cond_AL, 2, r1);
+    jit_info->native_ptr = emit_mul (jit_info->native_ptr, cond_AL, 0,
+                                     r2, r0, r1);
+    Parrot_jit_int_store(jit_info, interpreter, cond_AL, 1, r2);
+}
+Parrot_mul_i_i_i {
+    Parrot_jit_int_load(jit_info, interpreter, cond_AL, 2, r0);
+    Parrot_jit_int_load(jit_info, interpreter, cond_AL, 3, r1);
+    jit_info->native_ptr = emit_mul (jit_info->native_ptr, cond_AL, 0,
+                                     r2, r0, r1);
+    Parrot_jit_int_store(jit_info, interpreter, cond_AL, 1, r2);
+}
+Parrot_mul_i_ic_ic {
+    jit_info->native_ptr = emit_load_constant (jit_info->native_ptr,
+                                               interpreter,
+                                               cond_AL,
+                                               *INT_CONST[2] * *INT_CONST[3],
+                                               r0);
+    Parrot_jit_int_store(jit_info, interpreter, cond_AL, 1, r0);
+}
+
+Parrot_neg_i {
+    Parrot_jit_arith_const (jit_info, interpreter, cond_AL, RSB, 1, 1, 0);
+}
+Parrot_neg_i_i {
+    Parrot_jit_arith_const (jit_info, interpreter, cond_AL, RSB, 1, 2, 0);
+}
+Parrot_neg_i_ic {
+    jit_info->native_ptr = emit_load_constant (jit_info->native_ptr,
+                                               interpreter,
+                                               cond_AL,
+                                               -*INT_CONST[2],
+                                               r0);
+    Parrot_jit_int_store(jit_info, interpreter, cond_AL, 1, r0);
+}
+
 
 Parrot_sub_i_i_i {
-    Parrot_jit_int_load(jit_info, interpreter, 2, r0);
-    Parrot_jit_int_load(jit_info, interpreter, 3, r1);
+    Parrot_jit_int_load(jit_info, interpreter, cond_AL, 2, r0);
+    Parrot_jit_int_load(jit_info, interpreter, cond_AL, 3, r1);
     jit_info->native_ptr = emit_arith_reg (jit_info->native_ptr, cond_AL,
                                                  SUB, 0, r2, r0, r1);
-    Parrot_jit_int_store(jit_info, interpreter, 1, r2);
+    Parrot_jit_int_store(jit_info, interpreter, cond_AL, 1, r2);
+}
+Parrot_sub_i_i_ic {
+    Parrot_jit_arith_const_neg (jit_info, interpreter, cond_AL, SUB, ADD,
+        1, 2, *INT_CONST[3]);
+}
+Parrot_sub_i_ic_i {
+    Parrot_jit_arith_const_neg (jit_info, interpreter, cond_AL, RSB, ADD,
+        1, 3, *INT_CONST[2]);
+}
+Parrot_sub_i_ic_ic {
+    jit_info->native_ptr = emit_load_constant (jit_info->native_ptr,
+                                               interpreter,
+                                               cond_AL,
+                                               *INT_CONST[2] - *INT_CONST[3],
+                                               r0);
+    Parrot_jit_int_store(jit_info, interpreter, cond_AL, 1, r0);
+}
+Parrot_sub_i_ic {
+    Parrot_jit_arith_const_neg (jit_info, interpreter, cond_AL, SUB, ADD,
+        1, 1, *INT_CONST[2]);
 }
 
-Parrot_if_i_ic {
-    Parrot_jit_int_load(jit_info, interpreter, 1, r0);
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+; bit ops
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+
+Parrot_band_i_i_i {
+    Parrot_jit_int_load(jit_info, interpreter, cond_AL, 2, r0);
+    Parrot_jit_int_load(jit_info, interpreter, cond_AL, 3, r1);
+    jit_info->native_ptr = emit_arith_reg (jit_info->native_ptr, cond_AL,
+                                                 AND, 0, r2, r0, r1);
+    Parrot_jit_int_store(jit_info, interpreter, cond_AL, 1, r2);
+}
+Parrot_band_i_i_ic {
+    Parrot_jit_arith_const_not (jit_info, interpreter, cond_AL, AND, BIC,
+        1, 2, *INT_CONST[3]);
+}
+Parrot_band_i_ic_i {
+    Parrot_jit_arith_const_not (jit_info, interpreter, cond_AL, AND, BIC,
+        1, 3, *INT_CONST[2]);
+}
+Parrot_band_i_ic_ic {
+    jit_info->native_ptr = emit_load_constant (jit_info->native_ptr,
+                                               interpreter,
+                                               cond_AL,
+                                               *INT_CONST[2] & *INT_CONST[3],
+                                               r0);
+    Parrot_jit_int_store(jit_info, interpreter, cond_AL, 1, r0);
+}
+Parrot_band_i_ic {
+    Parrot_jit_arith_const_not (jit_info, interpreter, cond_AL, AND, BIC,
+        1, 1, *INT_CONST[2]);
+}
+
+;Parrot_bnot_i {
+;    Parrot_jit_int_load(jit_info, interpreter, cond_AL, 1, r0);
+;    jit_info->native_ptr = emit_arith_reg (jit_info->native_ptr, cond_AL,
+;                                                 MVN, 0, r0, 0, r0);
+;    Parrot_jit_int_store(jit_info, interpreter, cond_AL, 1, r0);
+;}
+Parrot_bnot_i_i {
+    Parrot_jit_int_load(jit_info, interpreter, cond_AL, 2, r0);
+    jit_info->native_ptr = emit_arith_reg (jit_info->native_ptr, cond_AL,
+                                                 MVN, 0, r0, 0, r0);
+    Parrot_jit_int_store(jit_info, interpreter, cond_AL, 1, r0);
+}
+Parrot_bnot_i_ic {
+    jit_info->native_ptr = emit_load_constant (jit_info->native_ptr,
+                                               interpreter,
+                                               cond_AL,
+                                               ~*INT_CONST[2],
+                                               r0);
+    Parrot_jit_int_store(jit_info, interpreter, cond_AL, 1, r0);
+}
+
+Parrot_bor_i_i_i {
+    Parrot_jit_int_load(jit_info, interpreter, cond_AL, 2, r0);
+    Parrot_jit_int_load(jit_info, interpreter, cond_AL, 3, r1);
+    jit_info->native_ptr = emit_arith_reg (jit_info->native_ptr, cond_AL,
+                                           ORR, 0, r2, r0, r1);
+    Parrot_jit_int_store(jit_info, interpreter, cond_AL, 1, r2);
+}
+Parrot_bor_i_i_ic {
+    Parrot_jit_arith_const (jit_info, interpreter, cond_AL, ORR,
+                            1, 2, *INT_CONST[3]);
+}
+Parrot_bor_i_ic_i {
+    Parrot_jit_arith_const (jit_info, interpreter, cond_AL, ORR,
+                            1, 3, *INT_CONST[2]);
+}
+Parrot_bor_i_ic_ic {
+    jit_info->native_ptr = emit_load_constant (jit_info->native_ptr,
+                                               interpreter,
+                                               cond_AL,
+                                               *INT_CONST[2] | *INT_CONST[3],
+                                               r0);
+    Parrot_jit_int_store(jit_info, interpreter, cond_AL, 1, r0);
+}
+Parrot_bor_i_ic {
+    Parrot_jit_arith_const(jit_info, interpreter, cond_AL, ORR,
+                           1, 1, *INT_CONST[2]);
+}
+
+Parrot_bxor_i_i_i {
+    Parrot_jit_int_load(jit_info, interpreter, cond_AL, 2, r0);
+    Parrot_jit_int_load(jit_info, interpreter, cond_AL, 3, r1);
+    jit_info->native_ptr = emit_arith_reg (jit_info->native_ptr, cond_AL,
+                                           EOR, 0, r2, r0, r1);
+    Parrot_jit_int_store(jit_info, interpreter, cond_AL, 1, r2);
+}
+Parrot_bxor_i_i_ic {
+    Parrot_jit_arith_const (jit_info, interpreter, cond_AL, EOR,
+                            1, 2, *INT_CONST[3]);
+}
+Parrot_bxor_i_ic_i {
+    Parrot_jit_arith_const (jit_info, interpreter, cond_AL, EOR,
+                            1, 3, *INT_CONST[2]);
+}
+Parrot_bxor_i_ic_ic {
+    jit_info->native_ptr = emit_load_constant (jit_info->native_ptr,
+                                               interpreter,
+                                               cond_AL,
+                                               *INT_CONST[2] | *INT_CONST[3],
+                                               r0);
+    Parrot_jit_int_store(jit_info, interpreter, cond_AL, 1, r0);
+}
+Parrot_bxor_i_ic {
+    Parrot_jit_arith_const(jit_info, interpreter, cond_AL, EOR,
+                           1, 1, *INT_CONST[2]);
+}
+
+Parrot_shl_i_i_i {
+    Parrot_jit_int_load(jit_info, interpreter, cond_AL, 2, r0);
+    Parrot_jit_int_load(jit_info, interpreter, cond_AL, 3, r1);
+    jit_info->native_ptr
+       = emit_arith_reg_shift_reg (jit_info->native_ptr, cond_AL,
+                                   MOV, 0, r2, 0, r0, shift_LSL, r1);
+    Parrot_jit_int_store(jit_info, interpreter, cond_AL, 1, r2);
+}
+Parrot_shl_i_i_ic {
+    Parrot_jit_int_load(jit_info, interpreter, cond_AL, 2, r0);
+    jit_info->native_ptr
+       = emit_arith_reg_shift_const (jit_info->native_ptr, cond_AL,
+                                     MOV, 0, r2, 0, r0, shift_LSL,
+                                     *INT_CONST[3]);
+    Parrot_jit_int_store(jit_info, interpreter, cond_AL, 1, r2);
+}
+Parrot_shl_i_ic_i {
+    Parrot_jit_int_load(jit_info, interpreter, cond_AL, 2, r0);
+    Parrot_jit_int_load(jit_info, interpreter, cond_AL, 3, r1);
+    jit_info->native_ptr
+       = emit_arith_reg_shift_reg (jit_info->native_ptr, cond_AL,
+                                   MOV, 0, r2, 0, r0, shift_LSL, r1);
+    Parrot_jit_int_store(jit_info, interpreter, cond_AL, 1, r2);
+}
+Parrot_shl_i_ic_ic {
+    jit_info->native_ptr = emit_load_constant (jit_info->native_ptr,
+                                               interpreter,
+                                               cond_AL,
+                                               *INT_CONST[2] << *INT_CONST[3],
+                                               r0);
+    Parrot_jit_int_store(jit_info, interpreter, cond_AL, 1, r0);
+}
+Parrot_shr_i_i_i {
+    Parrot_jit_int_load(jit_info, interpreter, cond_AL, 2, r0);
+    Parrot_jit_int_load(jit_info, interpreter, cond_AL, 3, r1);
+    jit_info->native_ptr
+       = emit_arith_reg_shift_reg (jit_info->native_ptr, cond_AL,
+                                   MOV, 0, r2, 0, r0, shift_ASR, r1);
+    Parrot_jit_int_store(jit_info, interpreter, cond_AL, 1, r2);
+}
+Parrot_shr_i_i_ic {
+    Parrot_jit_int_load(jit_info, interpreter, cond_AL, 2, r0);
+    jit_info->native_ptr
+       = emit_arith_reg_shift_const (jit_info->native_ptr, cond_AL,
+                                     MOV, 0, r2, 0, r0, shift_ASR,
+                                     *INT_CONST[3]);
+    Parrot_jit_int_store(jit_info, interpreter, cond_AL, 1, r2);
+}
+Parrot_shr_i_ic_i {
+    Parrot_jit_int_load(jit_info, interpreter, cond_AL, 2, r0);
+    Parrot_jit_int_load(jit_info, interpreter, cond_AL, 3, r1);
+    jit_info->native_ptr
+       = emit_arith_reg_shift_reg (jit_info->native_ptr, cond_AL,
+                                   MOV, 0, r2, 0, r0, shift_ASR, r1);
+    Parrot_jit_int_store(jit_info, interpreter, cond_AL, 1, r2);
+}
+Parrot_shr_i_ic_ic {
+    jit_info->native_ptr = emit_load_constant (jit_info->native_ptr,
+                                               interpreter,
+                                               cond_AL,
+                                               *INT_CONST[2] >> *INT_CONST[3],
+                                               r0);
+    Parrot_jit_int_store(jit_info, interpreter, cond_AL, 1, r0);
+}
+
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+; logical ops
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+
+Parrot_and_i_i_i {
+    Parrot_jit_int_load(jit_info, interpreter, cond_AL, 2, r0);
+    jit_info->native_ptr = emit_arith_immediate (jit_info->native_ptr, cond_AL,
+                                                 CMP, 0, 0, r0, 0, 0);
+    Parrot_jit_int_load(jit_info, interpreter, cond_NE, 3, r0);
+    Parrot_jit_int_store(jit_info, interpreter, cond_AL, 1, r0);
+}
+Parrot_and_i_i_ic {
+    Parrot_jit_int_load(jit_info, interpreter, cond_AL, 2, r0);
+    jit_info->native_ptr = emit_arith_immediate (jit_info->native_ptr, cond_AL,
+                                                 CMP, 0, 0, r0, 0, 0);
+    Parrot_jit_int_load(jit_info, interpreter, cond_NE, 3, r1);
+    Parrot_jit_int_store(jit_info, interpreter, cond_AL, 1, r0);
+}
+Parrot_and_i_ic_i {
+    if (*INT_CONST[2]) {
+        Parrot_jit_int_load(jit_info, interpreter, cond_AL, 3, r0);
+    } else {
+        /* *INT_CONST[2] is going to be 0 anyway, but this does generate the
+           shortest code to load 0.  */
+        Parrot_jit_int_load(jit_info, interpreter, cond_AL, 2, r0);
+    }
+    Parrot_jit_int_store(jit_info, interpreter, cond_AL, 1, r0);
+}
+Parrot_and_i_ic_ic {
+    if (*INT_CONST[2]) {
+        Parrot_jit_int_load(jit_info, interpreter, cond_AL, 3, r0);
+    } else {
+        /* *INT_CONST[2] is going to be 0 anyway, but this does generate the
+           shortest code to load 0.  */
+        Parrot_jit_int_load(jit_info, interpreter, cond_AL, 2, r0);
+    }
+    Parrot_jit_int_store(jit_info, interpreter, cond_AL, 1, r0);
+}
+
+Parrot_or_i_i_i {
+    Parrot_jit_int_load(jit_info, interpreter, cond_AL, 2, r0);
+    jit_info->native_ptr = emit_arith_immediate (jit_info->native_ptr, cond_AL,
+                                                 CMP, 0, 0, r0, 0, 0);
+    Parrot_jit_int_load(jit_info, interpreter, cond_EQ, 3, r0);
+    Parrot_jit_int_store(jit_info, interpreter, cond_AL, 1, r0);
+}
+Parrot_or_i_i_ic {
+    Parrot_jit_int_load(jit_info, interpreter, cond_AL, 2, r0);
     jit_info->native_ptr = emit_arith_immediate (jit_info->native_ptr, cond_AL,
                                                  CMP, 0, 0, r0, 0, 0);
-    emit_jump_to_op (jit_info, cond_NE, 0, *INT_CONST[2]);
+    Parrot_jit_int_load(jit_info, interpreter, cond_EQ, 3, r0);
+    Parrot_jit_int_store(jit_info, interpreter, cond_AL, 1, r0);
+}
+Parrot_or_i_ic_i {
+    if (*INT_CONST[2]) {
+        Parrot_jit_int_load(jit_info, interpreter, cond_AL, 2, r0);
+    } else {
+        Parrot_jit_int_load(jit_info, interpreter, cond_AL, 3, r0);
+    }
+    Parrot_jit_int_store(jit_info, interpreter, cond_AL, 1, r0);
+}
+Parrot_or_i_ic_ic {
+    if (*INT_CONST[2]) {
+        Parrot_jit_int_load(jit_info, interpreter, cond_AL, 2, r0);
+    } else {
+        Parrot_jit_int_load(jit_info, interpreter, cond_AL, 3, r0);
+    }
+    Parrot_jit_int_store(jit_info, interpreter, cond_AL, 1, r0);
+}
+;
+; no or_i_i :-(
+;
+;
+; RSBS  r1, r0, #1
+; ie flags set for CMP #1, r0
+; think unsigned - if r0 is 0, #1 is HIgher
+; for all other cases it's Lower or Same.
+; if r0 is 0, then #1 - #0 is 1, and r1 is set correctly.
+; else
+; MOVLS r1, #0
+; (actaully it's also set correctly for r0 is #1)
+Parrot_not_i_i {
+    Parrot_jit_int_load(jit_info, interpreter, cond_AL, 2, r0);
+    jit_info->native_ptr = emit_arith_immediate (jit_info->native_ptr, cond_AL,
+                                                 RSB, arith_sets_S,
+                                                 r1, r0, 1, 0);
+    jit_info->native_ptr = emit_arith_immediate (jit_info->native_ptr, cond_LS,
+                                                 MOV, 0,
+                                                 r1, 0, 0, 0);
+    Parrot_jit_int_store(jit_info, interpreter, cond_AL, 1, r1);
 }
+Parrot_not_i_ic {
+    jit_info->native_ptr = emit_load_constant (jit_info->native_ptr,
+                                               interpreter,
+                                               cond_AL,
+                                               !*INT_CONST[2],
+                                               r0);
+    Parrot_jit_int_store(jit_info, interpreter, cond_AL, 1, r0);
+}
+
+; XXX TODO - the non constant versions of this
+Parrot_xor_i_ic_ic {
+    jit_info->native_ptr
+       = emit_load_constant (jit_info->native_ptr, interpreter, cond_AL,
+                             (*INT_CONST[2] && ! *INT_CONST[3])
+                               ? *INT_CONST[2]
+                               : (*INT_CONST[3] && ! *INT_CONST[2])
+                                 ? *INT_CONST[3] : 0, r0);
+    Parrot_jit_int_store(jit_info, interpreter, cond_AL, 1, r0);
+}
+
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+; branches
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+
+Parrot_branch_i {
+   Parrot_jit_int_load(jit_info, interpreter, cond_AL, 1, r0);
+   Parrot_jump_to_op_in_reg(jit_info, interpreter, r0);
+}
+Parrot_branch_ic {
+    emit_jump_to_op (jit_info, cond_AL, *INT_CONST[1]);
+}
+
+/*
+ * Local variables:
+ * c-indentation-style: bsd
+ * c-basic-offset: 4
+ * indent-tabs-mode: nil 
+ * End:
+ *
+ * vim: expandtab shiftwidth=4:
+ */

Reply via email to