arm: cleanuos and fixes
authorWim Taymans <wim.taymans@collabora.co.uk>
Sat, 19 Sep 2009 18:07:20 +0000 (20:07 +0200)
committerDavid Schleef <ds@schleef.org>
Sun, 20 Sep 2009 05:20:35 +0000 (22:20 -0700)
orc/orcarm.c
orc/orcarm.h
orc/orcprogram-arm.c
orc/orcrules-arm.c

index 39f54ef..9fd715a 100644 (file)
@@ -205,23 +205,23 @@ orc_arm_emit_load_reg (OrcCompiler *compiler, int dest, int src1, int offset)
  * |rotimm |   immed_8     |
  * +-+-+-+-+-+-+-+-+-+-+-+-+
  */
-#define arm_so_imm(rot,imm) (((rot)<<8)|(imm))
+#define arm_so_i(rot,imm) ((((rot)&15)<<8)|((imm)&255))
 /*    1
  *  1 0 9 8 7 6 5 4 3 2 1 0
  * +-+-+-+-+-+-+-+-+-+-+-+-+
  * |    Si   | St  |0| Rm  |
  * +-+-+-+-+-+-+-+-+-+-+-+-+
  */
-#define arm_so_shift_imm(Si,St,Rm) (((Si)<<7)|((St)<<5)|(Rm))
-#define arm_so_rrx_reg(Rm)     arm_so_shift_imm(0,ORC_ARM_ROR,Rm)
-#define arm_so_reg(Rm)        (Rm)
+#define arm_so_rsi(Si,St,Rm)   ((((Si)&31)<<7)|(((St)&7)<<5)|((Rm)&7))
+#define arm_so_rrx(Rm)         arm_so_rsi(0,ORC_ARM_ROR,Rm)
+#define arm_so_r(Rm)           ((Rm)&7)
 /*    1
  *  1 0 9 8 7 6 5 4 3 2 1 0
  * +-+-+-+-+-+-+-+-+-+-+-+-+
  * |  Rs   |0| St  |1| Rm  |
  * +-+-+-+-+-+-+-+-+-+-+-+-+
  */
-#define arm_so_shift_reg(Rs,St,Rm) (0x008|((Rs)<<8)|((St)<<5)|(Rm))
+#define arm_so_rsr(Rs,St,Rm)   (0x008|(((Rs)&15)<<8)|(((St)&7)<<5)|((Rm)&7))
 
 /* data processing instructions */
 /*    3   2 2 2 2 2     2 2 1     1 1     1   1
@@ -230,9 +230,10 @@ orc_arm_emit_load_reg (OrcCompiler *compiler, int dest, int src1, int offset)
  * | cond  |0 0|I| opcode|S|   Rn  |  Rd   |   shifter_operand     |
  * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
  */
-#define arm_dp(cond,I,opcode,S,Rn,Rd,So) (((cond)<<28)|((I)<<25)|((opcode)<<21)|((S)<<20)|((Rn)<<16)|((Rd)<<12)|So)
-#define arm_dp_reg(cond,opcode,S,Rn,Rd,So) arm_dp (cond,0,opcode,S,Rn,Rd,So)
-#define arm_dp_imm(cond,opcode,S,Rn,Rd,So) arm_dp (cond,1,opcode,S,Rn,Rd,So)
+#define arm_code_dp(cond,I,opcode,S,Rn,Rd,So) ((((cond)&15)<<28) | (((I)&1)<<25) |   \
+                                              (((opcode)&15)<<21) | (((S)&1)<<20) | \
+                                              (((Rn)&15)<<16) | (((Rd)&15)<<12) |   \
+                                              ((So)&0xfff))
 
 /*
  * type 0:  <op>{<cond>}{s} {<Rd>}, <Rn>, #imm   (imm = (val>>(shift*2))|(val<<(32-(shift*2))))
@@ -243,12 +244,12 @@ orc_arm_emit_load_reg (OrcCompiler *compiler, int dest, int src1, int offset)
  */
 void
 orc_arm_emit_dp (OrcCompiler *p, int type, OrcArmCond cond, OrcArmDP opcode,
-    int S, int Rd, int Rn, int Rm, int shift, int val)
+    int S, int Rd, int Rn, int Rm, int shift, uint32_t val)
 {
   uint32_t code;
   int I = 0;
   int shifter_op;
-  char shifter[100];
+  char shifter[64];
   uint32_t imm;
   static const char *shift_names[] = {
     "LSL", "LSR", "ASR", "ROR"
@@ -269,33 +270,41 @@ orc_arm_emit_dp (OrcCompiler *p, int type, OrcArmCond cond, OrcArmDP opcode,
   switch (type) {
     case 0:
       /* #imm */
-      imm = val & 0xff;
-      shifter_op = arm_so_imm (shift, imm);
-      if (shift > 0)
-        imm = (imm >> (shift*2)) | (imm << (32-(shift*2)));
-      snprintf (shifter, sizeof(shifter), "#%08x", imm);
+      imm = (uint32_t) val;
+      /* if imm <= 0xff we're done. It's recommanded that we choose the
+       * smallest shifter value. Impossible values will overflow the shifter. */
+      while (imm > 0xff && shift < 16) {
+        imm = (imm << 2) | (imm >> 30);
+        shift++;
+      }
+      if (shift > 15) {
+        ORC_COMPILER_ERROR(p,"invalid ARM immediate %08x", val);
+        return;
+      }
+      shifter_op = arm_so_i (shift, imm);
+      snprintf (shifter, sizeof(shifter), "#%08x", val);
       I = 1;
       break;
     case 1:
       /* <Rm> */
-      shifter_op = arm_so_reg (Rm);
+      shifter_op = arm_so_r (Rm);
       snprintf (shifter, sizeof(shifter), "%s", orc_arm_reg_name (Rm));
       break;
     case 2:
       /* <Rm>, [LSL|LSR|ASR] #imm */
-      shifter_op = arm_so_shift_imm (val,shift,Rm);
+      shifter_op = arm_so_rsi (val,shift,Rm);
       snprintf (shifter, sizeof(shifter), "%s, %s #%d",
           orc_arm_reg_name (Rm), shift_names[shift], val);
       break;
     case 3:
       /* <Rm>, [LSL|LSR|ASR] <Rs> */
-      shifter_op = arm_so_shift_reg (val,shift,Rm);
+      shifter_op = arm_so_rsr (val,shift,Rm);
       snprintf (shifter, sizeof(shifter), "%s, %s %s",
           orc_arm_reg_name (Rm), shift_names[shift], orc_arm_reg_name (val));
       break;
     case 4:
       /* <Rm>, RRX */
-      shifter_op = arm_so_rrx_reg (Rm);
+      shifter_op = arm_so_rrx (Rm);
       snprintf (shifter, sizeof(shifter), "%s, RRX",
           orc_arm_reg_name (Rm));
       break;
@@ -307,20 +316,20 @@ orc_arm_emit_dp (OrcCompiler *p, int type, OrcArmCond cond, OrcArmDP opcode,
   if (op_Rd[opcode]) {
     if (op_Rn[opcode]) {
       /* opcode using Rn */
-      code = arm_dp (cond, I, opcode, S, Rn, Rd, shifter_op);
+      code = arm_code_dp (cond, I, opcode, S, Rn, Rd, shifter_op);
       ORC_ASM_CODE(p,"  %s%s%s %s, %s, %s\n",
           dp_insn_names[opcode], orc_arm_cond_name(cond), (S ? "s" : ""),
           orc_arm_reg_name (Rd), orc_arm_reg_name (Rn), shifter);
     } else {
       /* opcode using Rd and val (mov, mvn) */
-      code = arm_dp (cond, I, opcode, S, Rn, Rd, shifter_op);
+      code = arm_code_dp (cond, I, opcode, S, Rn, Rd, shifter_op);
       ORC_ASM_CODE(p,"  %s%s%s %s, %s\n",
           dp_insn_names[opcode], orc_arm_cond_name(cond), (S ? "s" : ""),
           orc_arm_reg_name (Rd), shifter);
     }
   } else {
     /* opcode does not change Rd, change status register (cmp, tst, ..) */
-    code = arm_dp (cond, I, opcode, 1, Rn, 0, shifter_op);
+    code = arm_code_dp (cond, I, opcode, 1, Rn, 0, shifter_op);
     ORC_ASM_CODE(p,"  %s%s %s, %s\n",
         dp_insn_names[opcode], orc_arm_cond_name(cond), orc_arm_reg_name (Rn), shifter);
   }
@@ -334,19 +343,164 @@ orc_arm_emit_dp (OrcCompiler *p, int type, OrcArmCond cond, OrcArmDP opcode,
  * | cond  |      mode     |   Rn  |  Rd   |0 0 0 0|  op   |  Rm   |
  * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
  */
-#define arm_code_mm(cond,mode,Rn,Rd,op,Rm) (((cond)<<28)|((mode)<<20)|((Rn)<<16)|((Rd)<<12)|((op)<<4)|(Rm))
+#define arm_code_par(cond,mode,Rn,Rd,op,Rm) (((cond)<<28)|((mode)<<20)|((Rn)<<16)|((Rd)<<12)|((op)<<4)|(Rm))
 
 void
-orc_arm_emit_mm (OrcCompiler *p, const char *name, OrcArmCond cond, int mode,
-            int op, int dest, int src1, int src2)
+orc_arm_emit_par (OrcCompiler *p, int op, int mode, OrcArmCond cond,
+    int Rd, int Rn, int Rm)
 {
   uint32_t code;
+  static const int par_op[] = {
+    1, 3, 5, 7, 9, 15, 11, 5, 5
+  };
+  static const char *par_op_names[] = {
+    "add16", "addsubx", "subaddx", "sub16", "add8", "sub8", "sel", "add", "sub"
+  };
+  static const int par_mode[] = {
+    0x61, 0x62, 0x63, 0x65, 0x66, 0x67, 0x68, 0x10, 0x12, 0x14, 0x16
+  };
+  static const char *par_mode_names[] = {
+    "s", "q", "sh", "u", "uq", "uh", "", "q", "q", "qd", "qd"
+  };
 
-  code = arm_code_mm (cond, mode, src1, dest, op, src2);
-  ORC_ASM_CODE(p,"  %s%s %s, %s, %s\n",
-      name, orc_arm_cond_name(cond),
-      orc_arm_reg_name (dest),
-      orc_arm_reg_name (src1),
-      orc_arm_reg_name (src2));
+  code = arm_code_par (cond, par_mode[mode], Rn, Rd, par_op[op], Rm);
+  ORC_ASM_CODE(p,"  %s%s%s %s, %s, %s\n",
+      par_mode_names[mode], par_op_names[op], orc_arm_cond_name(cond),
+      orc_arm_reg_name (Rd),
+      orc_arm_reg_name (Rn),
+      orc_arm_reg_name (Rm));
+  orc_arm_emit (p, code);
+}
+
+/* extend instructions */
+/*    3   2 2 2 2 2     2 2 1     1 1     1 1 1
+ *  1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0
+ * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ * | cond  |0 1 1 0 0 0 0 0|   Rn  |  Rd   |rot|0 0|0 1 1 1|  Rm   |
+ * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ */
+#define arm_code_xt(op,cond,Rn,Rd,r8,Rm) (op|((cond)<<28)|((Rn)<<16)|((Rd)<<12)|(((r8)&0x18)<<7)|(Rm))
+
+void
+orc_arm_emit_xt (OrcCompiler *p, int op, OrcArmCond cond,
+        int Rd, int Rn, int Rm, int r8)
+{
+  uint32_t code;
+  char shifter[64];
+  static const uint32_t xt_opcodes[] = {
+    0x06800070, 0x06a00070, 0x06b00070, 0x06c00070, 0x06e00070, 0x06f00070
+  };
+  static const char *xt_insn_names[] = {
+    "sxtb16", "sxtb", "sxth", "uxtb16", "uxtb", "uxth",
+    "sxtab16", "sxtab", "sxtah", "uxtab16", "uxtab", "uxtah",
+  };
+
+  if (r8 & 0x18)
+    snprintf (shifter, sizeof (shifter), ", ROR #%d", r8 & 0x18);
+  else
+    shifter[0] = '\0';
+
+  code = arm_code_xt (xt_opcodes[op], cond, Rn, Rd, r8, Rm);
+  if (Rn < 15) {
+    /* with Rn */
+    ORC_ASM_CODE(p,"  %s%s %s, %s, %s%s\n",
+        xt_insn_names[op], orc_arm_cond_name(cond),
+        orc_arm_reg_name (Rd),
+        orc_arm_reg_name (Rn),
+        orc_arm_reg_name (Rm),
+        shifter);
+  } else {
+    ORC_ASM_CODE(p,"  %s%s %s, %s%s\n",
+        xt_insn_names[op], orc_arm_cond_name(cond),
+        orc_arm_reg_name (Rd),
+        orc_arm_reg_name (Rm),
+        shifter);
+  }
+  orc_arm_emit (p, code);
+}
+
+#define arm_code_pkh(op,cond,Rn,Rd,sh,Rm) (op|((cond)<<28)|((Rn)<<16)|((Rd)<<12)|((sh)<<7)|(Rm))
+void
+orc_arm_emit_pkh (OrcCompiler *p, int op, OrcArmCond cond,
+    int Rd, int Rn, int Rm, int sh)
+{
+  uint32_t code;
+  char shifter[64];
+  static const uint32_t pkh_opcodes[] = { 0x06800010, 0x06800050 };
+  static const char *pkh_insn_names[] = { "pkhbt", "pkhtb" };
+
+  if (sh > 0) {
+    snprintf (shifter, sizeof (shifter), ", %s #%d",
+        (op == 0 ? "LSL" : "ASR"), sh);
+  } else {
+    shifter[0] = '\0';
+  }
+
+  code = arm_code_pkh (pkh_opcodes[op], cond, Rn, Rd, sh, Rm);
+  ORC_ASM_CODE(p,"  %s%s %s, %s, %s%s\n",
+      pkh_insn_names[op], orc_arm_cond_name(cond),
+      orc_arm_reg_name (Rd),
+      orc_arm_reg_name (Rn),
+      orc_arm_reg_name (Rm),
+      shifter);
+  orc_arm_emit (p, code);
+}
+
+/* extend instructions */
+/*    3   2 2     2       2 1     1 1     1 1 1
+ *  1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0
+ * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ * | cond  |0 1 1 0|x x x|   sat   |  Rd   |   sh    |a|0 1|  Rm   |
+ * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ */
+#define arm_code_sat(op,cond,sat,Rd,sh,a,Rm) (op|(((cond)&15)<<28)|(((sat)&31)<<16)|\
+                                              (((Rd)&15)<<12)|(((sh)&31)<<7)|(((a)&1)<<6)|\
+                                              ((Rm)&15))
+void
+orc_arm_emit_sat (OrcCompiler *p, int op, OrcArmCond cond,
+        int Rd, int sat, int Rm, int sh, int asr)
+{
+  uint32_t code;
+  char shifter[64];
+  static const uint32_t sat_opcodes[] = { 0x06a00010, 0x06e00010, 0, 0 };
+  static const char *sat_insn_names[] = { "ssat", "usat", "ssat16", "usat16" };
+  static const int par_mode[] = { 0, 0, 0x6a, 0x6e };
+  static const int par_op[] = { 0, 0, 3, 3 };
+
+  if (sh > 0) {
+    snprintf (shifter, sizeof (shifter), ", %s #%d",
+        (asr&1 ? "ASR" : "LSL"), sh);
+  } else {
+    shifter[0] = '\0';
+  }
+
+  if (op < 2) {
+    code = arm_code_sat (sat_opcodes[op], cond, sat, Rd, sh, asr, Rm);
+  } else {
+    code = arm_code_par (cond, par_mode[op], sat, Rd, par_op[op], Rm);
+  }
+  ORC_ASM_CODE(p,"  %s%s %s, #%d, %s%s\n",
+      sat_insn_names[op], orc_arm_cond_name(cond),
+      orc_arm_reg_name (Rd),
+      sat,
+      orc_arm_reg_name (Rm),
+      shifter);
+  orc_arm_emit (p, code);
+}
+
+#define arm_code_rv(op,cond,Rd,Rm) (op|(((cond)&15)<<28)|(((Rd)&15)<<12)|((Rm)&15))
+void
+orc_arm_emit_rv (OrcCompiler *p, int op, OrcArmCond cond,
+    int Rd, int Rm)
+{
+  uint32_t code;
+  static const uint32_t rv_opcodes[] = { 0x06b00030, 0x06e000b0 };
+  static const char *rv_insn_names[] = { "rev", "rev16" };
+
+  code = arm_code_rv (rv_opcodes[op], cond, Rd, Rm);
+  ORC_ASM_CODE(p,"  %s%s %s, %s\n",
+      rv_insn_names[op], orc_arm_cond_name(cond),
+      orc_arm_reg_name (Rd), orc_arm_reg_name (Rm));
   orc_arm_emit (p, code);
 }
+
index af3c92c..1ed8554 100644 (file)
@@ -87,29 +87,37 @@ void orc_arm_emit_load_reg (OrcCompiler *compiler, int dest, int src1, int offse
 void orc_arm_do_fixups (OrcCompiler *compiler);
 
 void orc_arm_emit_dp (OrcCompiler *p, int type, OrcArmCond cond, OrcArmDP opcode,
-        int S, int Rd, int Rn, int Rm, int shift, int val);
-void orc_arm_emit_mm (OrcCompiler *p, const char *name, OrcArmCond cond, int mode,
-        int op, int dest, int src1, int src2);
+    int S, int Rd, int Rn, int Rm, int shift, uint32_t val);
+void orc_arm_emit_par (OrcCompiler *p, int op, int mode, OrcArmCond cond,
+    int Rd, int Rn, int Rm);
+void orc_arm_emit_xt (OrcCompiler *p, int op, OrcArmCond cond,
+    int Rd, int Rn, int Rm, int r8);
+void orc_arm_emit_pkh (OrcCompiler *p, int op, OrcArmCond cond,
+    int Rd, int Rn, int Rm, int sh);
+void orc_arm_emit_sat (OrcCompiler *p, int op, OrcArmCond cond,
+    int Rd, int sat, int Rm, int sh, int asr);
+void orc_arm_emit_rv (OrcCompiler *p, int op, OrcArmCond cond,
+    int Rd, int Rm);
 
 /* ALL cpus */
 /* data procesing instructions */
 /* <op>{<cond>}{s} {<Rd>}, <Rn>, #imm */
-#define orc_arm_emit_and_i(p,cond,S,Rd,Rn,rot,imm)    orc_arm_emit_dp(p,0,cond,ORC_ARM_DP_AND,S,Rd,Rn,0,rot,imm)
-#define orc_arm_emit_eor_i(p,cond,S,Rd,Rn,rot,imm)    orc_arm_emit_dp(p,0,cond,ORC_ARM_DP_EOR,S,Rd,Rn,0,rot,imm)
-#define orc_arm_emit_sub_i(p,cond,S,Rd,Rn,rot,imm)    orc_arm_emit_dp(p,0,cond,ORC_ARM_DP_SUB,S,Rd,Rn,0,rot,imm)
-#define orc_arm_emit_rsb_i(p,cond,S,Rd,Rn,rot,imm)    orc_arm_emit_dp(p,0,cond,ORC_ARM_DP_RSB,S,Rd,Rn,0,rot,imm)
-#define orc_arm_emit_add_i(p,cond,S,Rd,Rn,rot,imm)    orc_arm_emit_dp(p,0,cond,ORC_ARM_DP_ADD,S,Rd,Rn,0,rot,imm)
-#define orc_arm_emit_adc_i(p,cond,S,Rd,Rn,rot,imm)    orc_arm_emit_dp(p,0,cond,ORC_ARM_DP_ADC,S,Rd,Rn,0,rot,imm)
-#define orc_arm_emit_sbc_i(p,cond,S,Rd,Rn,rot,imm)    orc_arm_emit_dp(p,0,cond,ORC_ARM_DP_SBC,S,Rd,Rn,0,rot,imm)
-#define orc_arm_emit_rsc_i(p,cond,S,Rd,Rn,rot,imm)    orc_arm_emit_dp(p,0,cond,ORC_ARM_DP_RSC,S,Rd,Rn,0,rot,imm)
-#define orc_arm_emit_tst_i(p,cond,Rn,rot,imm)         orc_arm_emit_dp(p,0,cond,ORC_ARM_DP_TST,1, 0,Rn,0,rot,imm)
-#define orc_arm_emit_teq_i(p,cond,Rn,rot,imm)         orc_arm_emit_dp(p,0,cond,ORC_ARM_DP_TEQ,1, 0,Rn,0,rot,imm)
-#define orc_arm_emit_cmp_i(p,cond,Rn,rot,imm)         orc_arm_emit_dp(p,0,cond,ORC_ARM_DP_CMP,1, 0,Rn,0,rot,imm)
-#define orc_arm_emit_cmn_i(p,cond,Rn,rot,imm)         orc_arm_emit_dp(p,0,cond,ORC_ARM_DP_CMN,1, 0,Rn,0,rot,imm)
-#define orc_arm_emit_orr_i(p,cond,S,Rd,Rn,rot,imm)    orc_arm_emit_dp(p,0,cond,ORC_ARM_DP_ORR,S,Rd,Rn,0,rot,imm)
-#define orc_arm_emit_mov_i(p,cond,S,Rd,rot,imm)       orc_arm_emit_dp(p,0,cond,ORC_ARM_DP_MOV,S,Rd, 0,0,rot,imm)
-#define orc_arm_emit_bic_i(p,cond,S,Rd,Rn,rot,imm)    orc_arm_emit_dp(p,0,cond,ORC_ARM_DP_BIC,S,Rd,Rn,0,rot,imm)
-#define orc_arm_emit_mvn_i(p,cond,S,Rd,rot,imm)       orc_arm_emit_dp(p,0,cond,ORC_ARM_DP_MVN,S,Rd, 0,0,rot,imm)
+#define orc_arm_emit_and_i(p,cond,S,Rd,Rn,imm)        orc_arm_emit_dp(p,0,cond,ORC_ARM_DP_AND,S,Rd,Rn,0,0,imm)
+#define orc_arm_emit_eor_i(p,cond,S,Rd,Rn,imm)        orc_arm_emit_dp(p,0,cond,ORC_ARM_DP_EOR,S,Rd,Rn,0,0,imm)
+#define orc_arm_emit_sub_i(p,cond,S,Rd,Rn,imm)        orc_arm_emit_dp(p,0,cond,ORC_ARM_DP_SUB,S,Rd,Rn,0,0,imm)
+#define orc_arm_emit_rsb_i(p,cond,S,Rd,Rn,imm)        orc_arm_emit_dp(p,0,cond,ORC_ARM_DP_RSB,S,Rd,Rn,0,0,imm)
+#define orc_arm_emit_add_i(p,cond,S,Rd,Rn,imm)        orc_arm_emit_dp(p,0,cond,ORC_ARM_DP_ADD,S,Rd,Rn,0,0,imm)
+#define orc_arm_emit_adc_i(p,cond,S,Rd,Rn,imm)        orc_arm_emit_dp(p,0,cond,ORC_ARM_DP_ADC,S,Rd,Rn,0,0,imm)
+#define orc_arm_emit_sbc_i(p,cond,S,Rd,Rn,imm)        orc_arm_emit_dp(p,0,cond,ORC_ARM_DP_SBC,S,Rd,Rn,0,0,imm)
+#define orc_arm_emit_rsc_i(p,cond,S,Rd,Rn,imm)        orc_arm_emit_dp(p,0,cond,ORC_ARM_DP_RSC,S,Rd,Rn,0,0,imm)
+#define orc_arm_emit_tst_i(p,cond,Rn,imm)             orc_arm_emit_dp(p,0,cond,ORC_ARM_DP_TST,1, 0,Rn,0,0,imm)
+#define orc_arm_emit_teq_i(p,cond,Rn,imm)             orc_arm_emit_dp(p,0,cond,ORC_ARM_DP_TEQ,1, 0,Rn,0,0,imm)
+#define orc_arm_emit_cmp_i(p,cond,Rn,imm)             orc_arm_emit_dp(p,0,cond,ORC_ARM_DP_CMP,1, 0,Rn,0,0,imm)
+#define orc_arm_emit_cmn_i(p,cond,Rn,imm)             orc_arm_emit_dp(p,0,cond,ORC_ARM_DP_CMN,1, 0,Rn,0,0,imm)
+#define orc_arm_emit_orr_i(p,cond,S,Rd,Rn,imm)        orc_arm_emit_dp(p,0,cond,ORC_ARM_DP_ORR,S,Rd,Rn,0,0,imm)
+#define orc_arm_emit_mov_i(p,cond,S,Rd,imm)           orc_arm_emit_dp(p,0,cond,ORC_ARM_DP_MOV,S,Rd, 0,0,0,imm)
+#define orc_arm_emit_bic_i(p,cond,S,Rd,Rn,imm)        orc_arm_emit_dp(p,0,cond,ORC_ARM_DP_BIC,S,Rd,Rn,0,0,imm)
+#define orc_arm_emit_mvn_i(p,cond,S,Rd,imm)           orc_arm_emit_dp(p,0,cond,ORC_ARM_DP_MVN,S,Rd, 0,0,0,imm)
 
 /* <op>{<cond>}{s} {<Rd>}, <Rn>, <Rm> */
 #define orc_arm_emit_and_r(p,cond,S,Rd,Rn,Rm)         orc_arm_emit_dp(p,1,cond,ORC_ARM_DP_AND,S,Rd,Rn,Rm,0,0)
@@ -184,58 +192,107 @@ void orc_arm_emit_mm (OrcCompiler *p, const char *name, OrcArmCond cond, int mod
 #define orc_arm_emit_mvn_rrx(p,cond,S,Rd,Rm)          orc_arm_emit_dp(p,4,cond,ORC_ARM_DP_MVN,S,Rd, 0,Rm,0,0)
 
 /* parallel instructions */
-#define orc_arm_emit_sadd16(p,cond,Rd,Rn,Rm)    orc_arm_emit_mm(p,"sadd16",   cond,0x61,0x1,Rd,Rn,Rm)
-#define orc_arm_emit_qadd16(p,cond,Rd,Rn,Rm)    orc_arm_emit_mm(p,"qadd16",   cond,0x62,0x1,Rd,Rn,Rm)
-#define orc_arm_emit_shadd16(p,cond,Rd,Rn,Rm)   orc_arm_emit_mm(p,"shadd16",  cond,0x63,0x1,Rd,Rn,Rm)
-#define orc_arm_emit_uadd16(p,cond,Rd,Rn,Rm)    orc_arm_emit_mm(p,"uadd16",   cond,0x65,0x1,Rd,Rn,Rm)
-#define orc_arm_emit_uqadd16(p,cond,Rd,Rn,Rm)   orc_arm_emit_mm(p,"uqadd16",  cond,0x66,0x1,Rd,Rn,Rm)
-#define orc_arm_emit_uhadd16(p,cond,Rd,Rn,Rm)   orc_arm_emit_mm(p,"uhadd16",  cond,0x67,0x1,Rd,Rn,Rm)
-
-#define orc_arm_emit_saddsubx(p,cond,Rd,Rn,Rm)  orc_arm_emit_mm(p,"saddsubx", cond,0x61,0x3,Rd,Rn,Rm)
-#define orc_arm_emit_qaddsubx(p,cond,Rd,Rn,Rm)  orc_arm_emit_mm(p,"qaddsubx", cond,0x62,0x3,Rd,Rn,Rm)
-#define orc_arm_emit_shaddsubx(p,cond,Rd,Rn,Rm) orc_arm_emit_mm(p,"shaddsubx",cond,0x63,0x3,Rd,Rn,Rm)
-#define orc_arm_emit_uaddsubx(p,cond,Rd,Rn,Rm)  orc_arm_emit_mm(p,"uaddsubx", cond,0x65,0x3,Rd,Rn,Rm)
-#define orc_arm_emit_uqaddsubx(p,cond,Rd,Rn,Rm) orc_arm_emit_mm(p,"uqaddsubx",cond,0x66,0x3,Rd,Rn,Rm)
-#define orc_arm_emit_uhaddsubx(p,cond,Rd,Rn,Rm) orc_arm_emit_mm(p,"uhaddsubx",cond,0x67,0x3,Rd,Rn,Rm)
-
-#define orc_arm_emit_ssubaddx(p,cond,Rd,Rn,Rm)  orc_arm_emit_mm(p,"ssubaddx", cond,0x61,0x5,Rd,Rn,Rm)
-#define orc_arm_emit_qsubaddx(p,cond,Rd,Rn,Rm)  orc_arm_emit_mm(p,"qsubaddx", cond,0x62,0x5,Rd,Rn,Rm)
-#define orc_arm_emit_shsubaddx(p,cond,Rd,Rn,Rm) orc_arm_emit_mm(p,"shsubaddx",cond,0x63,0x5,Rd,Rn,Rm)
-#define orc_arm_emit_usubaddx(p,cond,Rd,Rn,Rm)  orc_arm_emit_mm(p,"usubaddx", cond,0x65,0x5,Rd,Rn,Rm)
-#define orc_arm_emit_uqsubaddx(p,cond,Rd,Rn,Rm) orc_arm_emit_mm(p,"uqsubaddx",cond,0x66,0x5,Rd,Rn,Rm)
-#define orc_arm_emit_uhsubaddx(p,cond,Rd,Rn,Rm) orc_arm_emit_mm(p,"uhsubaddx",cond,0x67,0x5,Rd,Rn,Rm)
-
-#define orc_arm_emit_ssub16(p,cond,Rd,Rn,Rm)    orc_arm_emit_mm(p,"ssub16",   cond,0x61,0x7,Rd,Rn,Rm)
-#define orc_arm_emit_qsub16(p,cond,Rd,Rn,Rm)    orc_arm_emit_mm(p,"qsub16",   cond,0x62,0x7,Rd,Rn,Rm)
-#define orc_arm_emit_shsub16(p,cond,Rd,Rn,Rm)   orc_arm_emit_mm(p,"shsub16",  cond,0x63,0x7,Rd,Rn,Rm)
-#define orc_arm_emit_usub16(p,cond,Rd,Rn,Rm)    orc_arm_emit_mm(p,"usub16",   cond,0x65,0x7,Rd,Rn,Rm)
-#define orc_arm_emit_uqsub16(p,cond,Rd,Rn,Rm)   orc_arm_emit_mm(p,"uqsub16",  cond,0x66,0x7,Rd,Rn,Rm)
-#define orc_arm_emit_uhsub16(p,cond,Rd,Rn,Rm)   orc_arm_emit_mm(p,"uhsub16",  cond,0x67,0x7,Rd,Rn,Rm)
-
-#define orc_arm_emit_sadd8(p,cond,Rd,Rn,Rm)     orc_arm_emit_mm(p,"sadd8",    cond,0x61,0x9,Rd,Rn,Rm)
-#define orc_arm_emit_qadd8(p,cond,Rd,Rn,Rm)     orc_arm_emit_mm(p,"qadd8",    cond,0x62,0x9,Rd,Rn,Rm)
-#define orc_arm_emit_shadd8(p,cond,Rd,Rn,Rm)    orc_arm_emit_mm(p,"shadd8",   cond,0x63,0x9,Rd,Rn,Rm)
-#define orc_arm_emit_uadd8(p,cond,Rd,Rn,Rm)     orc_arm_emit_mm(p,"uadd8",    cond,0x65,0x9,Rd,Rn,Rm)
-#define orc_arm_emit_uqadd8(p,cond,Rd,Rn,Rm)    orc_arm_emit_mm(p,"uqadd8",   cond,0x66,0x9,Rd,Rn,Rm)
-#define orc_arm_emit_uhadd8(p,cond,Rd,Rn,Rm)    orc_arm_emit_mm(p,"uhadd8",   cond,0x67,0x9,Rd,Rn,Rm)
-
-#define orc_arm_emit_ssub8(p,cond,Rd,Rn,Rm)     orc_arm_emit_mm(p,"ssub8",    cond,0x61,0xf,Rd,Rn,Rm)
-#define orc_arm_emit_qsub8(p,cond,Rd,Rn,Rm)     orc_arm_emit_mm(p,"qsub8",    cond,0x62,0xf,Rd,Rn,Rm)
-#define orc_arm_emit_shsub8(p,cond,Rd,Rn,Rm)    orc_arm_emit_mm(p,"shsub8",   cond,0x63,0xf,Rd,Rn,Rm)
-#define orc_arm_emit_usub8(p,cond,Rd,Rn,Rm)     orc_arm_emit_mm(p,"usub8",    cond,0x65,0xf,Rd,Rn,Rm)
-#define orc_arm_emit_uqsub8(p,cond,Rd,Rn,Rm)    orc_arm_emit_mm(p,"uqsub8",   cond,0x66,0xf,Rd,Rn,Rm)
-#define orc_arm_emit_uhsub8(p,cond,Rd,Rn,Rm)    orc_arm_emit_mm(p,"uhsub8",   cond,0x67,0xf,Rd,Rn,Rm)
-
-#define orc_arm_emit_ssat16(p,cond,Rd,sat,Rm)   orc_arm_emit_mm(p,"ssat16",   cond,0x6a,0x3,Rd,sat,Rm)
-#define orc_arm_emit_usat16(p,cond,Rd,sat,Rm)   orc_arm_emit_mm(p,"usat16",   cond,0x6e,0x3,Rd,sat,Rm)
+#define orc_arm_emit_sadd16(p,cond,Rd,Rn,Rm)          orc_arm_emit_par(p,0,0,cond,Rd,Rn,Rm)
+#define orc_arm_emit_qadd16(p,cond,Rd,Rn,Rm)          orc_arm_emit_par(p,0,1,cond,Rd,Rn,Rm)
+#define orc_arm_emit_shadd16(p,cond,Rd,Rn,Rm)         orc_arm_emit_par(p,0,2,cond,Rd,Rn,Rm)
+#define orc_arm_emit_uadd16(p,cond,Rd,Rn,Rm)          orc_arm_emit_par(p,0,3,cond,Rd,Rn,Rm)
+#define orc_arm_emit_uqadd16(p,cond,Rd,Rn,Rm)         orc_arm_emit_par(p,0,4,cond,Rd,Rn,Rm)
+#define orc_arm_emit_uhadd16(p,cond,Rd,Rn,Rm)         orc_arm_emit_par(p,0,5,cond,Rd,Rn,Rm)
+
+#define orc_arm_emit_saddsubx(p,cond,Rd,Rn,Rm)        orc_arm_emit_par(p,1,0,cond,Rd,Rn,Rm)
+#define orc_arm_emit_qaddsubx(p,cond,Rd,Rn,Rm)        orc_arm_emit_par(p,1,1,cond,Rd,Rn,Rm)
+#define orc_arm_emit_shaddsubx(p,cond,Rd,Rn,Rm)       orc_arm_emit_par(p,1,2,cond,Rd,Rn,Rm)
+#define orc_arm_emit_uaddsubx(p,cond,Rd,Rn,Rm)        orc_arm_emit_par(p,1,3,cond,Rd,Rn,Rm)
+#define orc_arm_emit_uqaddsubx(p,cond,Rd,Rn,Rm)       orc_arm_emit_par(p,1,4,cond,Rd,Rn,Rm)
+#define orc_arm_emit_uhaddsubx(p,cond,Rd,Rn,Rm)       orc_arm_emit_par(p,1,5,cond,Rd,Rn,Rm)
+
+#define orc_arm_emit_ssubaddx(p,cond,Rd,Rn,Rm)        orc_arm_emit_par(p,2,0,cond,Rd,Rn,Rm)
+#define orc_arm_emit_qsubaddx(p,cond,Rd,Rn,Rm)        orc_arm_emit_par(p,2,1,cond,Rd,Rn,Rm)
+#define orc_arm_emit_shsubaddx(p,cond,Rd,Rn,Rm)       orc_arm_emit_par(p,2,2,cond,Rd,Rn,Rm)
+#define orc_arm_emit_usubaddx(p,cond,Rd,Rn,Rm)        orc_arm_emit_par(p,2,3,cond,Rd,Rn,Rm)
+#define orc_arm_emit_uqsubaddx(p,cond,Rd,Rn,Rm)       orc_arm_emit_par(p,2,4,cond,Rd,Rn,Rm)
+#define orc_arm_emit_uhsubaddx(p,cond,Rd,Rn,Rm)       orc_arm_emit_par(p,2,5,cond,Rd,Rn,Rm)
+
+#define orc_arm_emit_ssub16(p,cond,Rd,Rn,Rm)          orc_arm_emit_par(p,3,0,cond,Rd,Rn,Rm)
+#define orc_arm_emit_qsub16(p,cond,Rd,Rn,Rm)          orc_arm_emit_par(p,3,1,cond,Rd,Rn,Rm)
+#define orc_arm_emit_shsub16(p,cond,Rd,Rn,Rm)         orc_arm_emit_par(p,3,2,cond,Rd,Rn,Rm)
+#define orc_arm_emit_usub16(p,cond,Rd,Rn,Rm)          orc_arm_emit_par(p,3,3,cond,Rd,Rn,Rm)
+#define orc_arm_emit_uqsub16(p,cond,Rd,Rn,Rm)         orc_arm_emit_par(p,3,4,cond,Rd,Rn,Rm)
+#define orc_arm_emit_uhsub16(p,cond,Rd,Rn,Rm)         orc_arm_emit_par(p,3,5,cond,Rd,Rn,Rm)
+
+#define orc_arm_emit_sadd8(p,cond,Rd,Rn,Rm)           orc_arm_emit_par(p,4,0,cond,Rd,Rn,Rm)
+#define orc_arm_emit_qadd8(p,cond,Rd,Rn,Rm)           orc_arm_emit_par(p,4,1,cond,Rd,Rn,Rm)
+#define orc_arm_emit_shadd8(p,cond,Rd,Rn,Rm)          orc_arm_emit_par(p,4,2,cond,Rd,Rn,Rm)
+#define orc_arm_emit_uadd8(p,cond,Rd,Rn,Rm)           orc_arm_emit_par(p,4,3,cond,Rd,Rn,Rm)
+#define orc_arm_emit_uqadd8(p,cond,Rd,Rn,Rm)          orc_arm_emit_par(p,4,4,cond,Rd,Rn,Rm)
+#define orc_arm_emit_uhadd8(p,cond,Rd,Rn,Rm)          orc_arm_emit_par(p,4,5,cond,Rd,Rn,Rm)
+
+#define orc_arm_emit_ssub8(p,cond,Rd,Rn,Rm)           orc_arm_emit_par(p,5,0,cond,Rd,Rn,Rm)
+#define orc_arm_emit_qsub8(p,cond,Rd,Rn,Rm)           orc_arm_emit_par(p,5,1,cond,Rd,Rn,Rm)
+#define orc_arm_emit_shsub8(p,cond,Rd,Rn,Rm)          orc_arm_emit_par(p,5,2,cond,Rd,Rn,Rm)
+#define orc_arm_emit_usub8(p,cond,Rd,Rn,Rm)           orc_arm_emit_par(p,5,3,cond,Rd,Rn,Rm)
+#define orc_arm_emit_uqsub8(p,cond,Rd,Rn,Rm)          orc_arm_emit_par(p,5,4,cond,Rd,Rn,Rm)
+#define orc_arm_emit_uhsub8(p,cond,Rd,Rn,Rm)          orc_arm_emit_par(p,5,5,cond,Rd,Rn,Rm)
+
+/* selection */
+#define orc_arm_emit_sel(p,cond,Rd,Rn,Rm)             orc_arm_emit_par(p,6,6,cond,Rd,Rn,Rm)
+
+/* saturating add */
+#define orc_arm_emit_qadd(p,cond,Rd,Rn,Rm)            orc_arm_emit_par(p,7,7, cond,Rd,Rn,Rm)
+#define orc_arm_emit_qsub(p,cond,Rd,Rn,Rm)            orc_arm_emit_par(p,8,8, cond,Rd,Rn,Rm)
+#define orc_arm_emit_qdadd(p,cond,Rd,Rn,Rm)           orc_arm_emit_par(p,7,9, cond,Rd,Rn,Rm)
+#define orc_arm_emit_qdsub(p,cond,Rd,Rn,Rm)           orc_arm_emit_par(p,8,10,cond,Rd,Rn,Rm)
+
+/* extend instructions */
+/* with ROR #r8, r8 should be a multiple of 8 */
+#define orc_arm_emit_sxtb16_r8(p,cond,Rd,Rm,r8)       orc_arm_emit_xt(p,0, cond,Rd,15,Rm,r8)
+#define orc_arm_emit_sxtb_r8(p,cond,Rd,Rm,r8)         orc_arm_emit_xt(p,1, cond,Rd,15,Rm,r8)
+#define orc_arm_emit_sxth_r8(p,cond,Rd,Rm,r8)         orc_arm_emit_xt(p,2, cond,Rd,15,Rm,r8)
+#define orc_arm_emit_uxtb16_r8(p,cond,Rd,Rm,r8)       orc_arm_emit_xt(p,3, cond,Rd,15,Rm,r8)
+#define orc_arm_emit_uxtb_r8(p,cond,Rd,Rm,r8)         orc_arm_emit_xt(p,4, cond,Rd,15,Rm,r8)
+#define orc_arm_emit_uxth_r8(p,cond,Rd,Rm,r8)         orc_arm_emit_xt(p,5, cond,Rd,15,Rm,r8)
+#define orc_arm_emit_sxtab16_r8(p,cond,Rd,Rn,Rm,r8)   orc_arm_emit_xt(p,6, cond,Rd,Rn,Rm,r8)
+#define orc_arm_emit_sxtab_r8(p,cond,Rd,Rn,Rm,r8)     orc_arm_emit_xt(p,7, cond,Rd,Rn,Rm,r8)
+#define orc_arm_emit_sxtah_r8(p,cond,Rd,Rn,Rm,r8)     orc_arm_emit_xt(p,8, cond,Rd,Rn,Rm,r8)
+#define orc_arm_emit_uxtab16_r8(p,cond,Rd,Rn,Rm,r8)   orc_arm_emit_xt(p,9, cond,Rd,Rn,Rm,r8)
+#define orc_arm_emit_uxtab_r8(p,cond,Rd,Rn,Rm,r8)     orc_arm_emit_xt(p,10,cond,Rd,Rn,Rm,r8)
+#define orc_arm_emit_uxtah_r8(p,cond,Rd,Rn,Rm,r8)     orc_arm_emit_xt(p,11,cond,Rd,Rn,Rm,r8)
+/* with out rotate */
+#define orc_arm_emit_sxtb16(p,cond,Rd,Rm)             orc_arm_emit_sxtb_r8(p,cond,Rd,Rm,0)
+#define orc_arm_emit_sxtb(p,cond,Rd,Rm)               orc_arm_emit_sxtb_r8(p,cond,Rd,Rm,0)
+#define orc_arm_emit_sxth(p,cond,Rd,Rm)               orc_arm_emit_sxtb_r8(p,cond,Rd,Rm,0)
+#define orc_arm_emit_uxtb16(p,cond,Rd,Rm)             orc_arm_emit_sxtb_r8(p,cond,Rd,Rm,0)
+#define orc_arm_emit_uxtb(p,cond,Rd,Rm)               orc_arm_emit_sxtb_r8(p,cond,Rd,Rm,0)
+#define orc_arm_emit_uxth(p,cond,Rd,Rm)               orc_arm_emit_sxtb_r8(p,cond,Rd,Rm,0)
+#define orc_arm_emit_sxtab16(p,cond,Rd,Rn,Rm)         orc_arm_emit_sxtb_r8(p,cond,Rd,Rm,0)
+#define orc_arm_emit_sxtab(p,cond,Rd,Rn,Rm)           orc_arm_emit_sxtb_r8(p,cond,Rd,Rm,0)
+#define orc_arm_emit_sxtah(p,cond,Rd,Rn,Rm)           orc_arm_emit_sxtb_r8(p,cond,Rd,Rm,0)
+#define orc_arm_emit_uxtab16(p,cond,Rd,Rn,Rm)         orc_arm_emit_sxtb_r8(p,cond,Rd,Rm,0)
+#define orc_arm_emit_uxtab(p,cond,Rd,Rn,Rm)           orc_arm_emit_sxtb_r8(p,cond,Rd,Rm,0)
+#define orc_arm_emit_uxtah(p,cond,Rd,Rn,Rm)           orc_arm_emit_sxtb_r8(p,cond,Rd,Rm,0)
 
 /* misc instructions */
-#define orc_arm_emit_sel(p,cond,Rd,Rn,Rm)       orc_arm_emit_mm(p,"sel", cond,0x68,0xb,Rd,Rn,Rm)
 
-#define orc_arm_emit_qadd(p,cond,Rd,Rn,Rm)      orc_arm_emit_mm(p,"qadd",     cond,0x10,0x5,Rd,Rn,Rm)
-#define orc_arm_emit_qsub(p,cond,Rd,Rn,Rm)      orc_arm_emit_mm(p,"qsub",     cond,0x12,0x5,Rd,Rn,Rm)
-#define orc_arm_emit_qdadd(p,cond,Rd,Rn,Rm)     orc_arm_emit_mm(p,"qdadd",    cond,0x14,0x5,Rd,Rn,Rm)
-#define orc_arm_emit_qdsub(p,cond,Rd,Rn,Rm)     orc_arm_emit_mm(p,"qdsub",    cond,0x16,0x5,Rd,Rn,Rm)
+/* packing */
+#define orc_arm_emit_pkhbt(p,cond,Rd,Rn,Rm)           orc_arm_emit_pkh(p,0,cond,Rd,Rn,Rm,0)
+#define orc_arm_emit_pkhtb(p,cond,Rd,Rn,Rm)           orc_arm_emit_pkh(p,1,cond,Rd,Rn,Rm,0)
+/* with  [LSL|ASR] #imm */
+#define orc_arm_emit_pkhbt_s(p,cond,Rd,Rn,Rm,lsl)     orc_arm_emit_pkh(p,0,cond,Rd,Rn,Rm,lsl)
+#define orc_arm_emit_pkhtb_s(p,cond,Rd,Rn,Rm,asr)     orc_arm_emit_pkh(p,1,cond,Rd,Rn,Rm,asr)
+
+/* saturation */
+#define orc_arm_emit_ssat(p,cond,Rd,sat,Rm)           orc_arm_emit_sat(p,0,cond,Rd,sat,Rm,0, 0)
+#define orc_arm_emit_usat(p,cond,Rd,sat,Rm)           orc_arm_emit_sat(p,1,cond,Rd,sat,Rm,0, 0)
+#define orc_arm_emit_ssat_lsl(p,cond,Rd,sat,Rm,sh)    orc_arm_emit_sat(p,0,cond,Rd,sat,Rm,sh,0)
+#define orc_arm_emit_usat_lsl(p,cond,Rd,sat,Rm,sh)    orc_arm_emit_sat(p,1,cond,Rd,sat,Rm,sh,0)
+#define orc_arm_emit_ssat_asr(p,cond,Rd,sat,Rm,sh)    orc_arm_emit_sat(p,0,cond,Rd,sat,Rm,sh,1)
+#define orc_arm_emit_usat_asr(p,cond,Rd,sat,Rm,sh)    orc_arm_emit_sat(p,1,cond,Rd,sat,Rm,sh,1)
+#define orc_arm_emit_ssat16(p,cond,Rd,sat,Rm)         orc_arm_emit_sat(p,2,cond,Rd,sat,Rm,0, 0)
+#define orc_arm_emit_usat16(p,cond,Rd,sat,Rm)         orc_arm_emit_sat(p,3,cond,Rd,sat,Rm,0, 0)
+
+/* reversing */
+#define orc_arm_emit_rev(p,cond,Rd,Rm)                orc_arm_emit_rv (p,0,cond,Rd,Rm)
+#define orc_arm_emit_rev16(p,cond,Rd,Rm)              orc_arm_emit_rv (p,1,cond,Rd,Rm)
 
 #endif
 
index b6694d0..23f4b7e 100644 (file)
@@ -254,13 +254,13 @@ orc_compiler_orc_arm_assemble (OrcCompiler *compiler)
 
   orc_arm_emit_label (compiler, 1);
 
-  orc_arm_emit_cmp_i (compiler, ORC_ARM_COND_AL, ORC_ARM_IP, 0, 0);
+  orc_arm_emit_cmp_i (compiler, ORC_ARM_COND_AL, ORC_ARM_IP, 0);
   orc_arm_emit_branch (compiler, ORC_ARM_COND_EQ, 3);
 
   orc_arm_emit_label (compiler, 2);
   orc_arm_emit_loop (compiler);
-  orc_arm_emit_sub_i (compiler, ORC_ARM_COND_AL, 0, ORC_ARM_IP, ORC_ARM_IP, 0, 1);
-  orc_arm_emit_cmp_i (compiler, ORC_ARM_COND_AL, ORC_ARM_IP, 0, 0);
+  orc_arm_emit_sub_i (compiler, ORC_ARM_COND_AL, 0, ORC_ARM_IP, ORC_ARM_IP, 1);
+  orc_arm_emit_cmp_i (compiler, ORC_ARM_COND_AL, ORC_ARM_IP, 0);
   orc_arm_emit_branch (compiler, ORC_ARM_COND_NE, 2);
   orc_arm_emit_label (compiler, 3);
 
@@ -349,7 +349,7 @@ orc_arm_emit_loop (OrcCompiler *compiler)
       if (compiler->vars[k].ptr_register) {
         orc_arm_emit_add_i (compiler, ORC_ARM_COND_AL, 0,
             compiler->vars[k].ptr_register,
-            compiler->vars[k].ptr_register, 0,
+            compiler->vars[k].ptr_register,
             compiler->vars[k].size << compiler->loop_shift);
       } else {
         //orc_arm_emit_add_imm_memoffset (compiler, orc_arm_ptr_size,
index db75342..4d3604d 100644 (file)
@@ -35,33 +35,7 @@ arm_rule_ ## opcode (OrcCompiler *p, void *user, OrcInstruction *insn) \
   orc_arm_emit_##insn_name (p, ORC_ARM_COND_AL, dest, src1, src2);     \
 }
 
-#define orc_arm_xt(op,cond,Rn,Rd,Rm,rot) (op|((cond)<<28)|((Rn)<<16)|((Rd)<<12)|((rot)<<10)|(Rm))
-#define orc_arm_emit_sxtb(p,cond,Rd,Rm,rot)       orc_arm_emit (p, orc_arm_xt (0x06a00070,cond,0xf,Rd,Rm,rot))
-#define orc_arm_emit_sxth(p,cond,Rd,Rm,rot)       orc_arm_emit (p, orc_arm_xt (0x06b00070,cond,0xf,Rd,Rm,rot))
-#define orc_arm_emit_uxtb(p,cond,Rd,Rm,rot)       orc_arm_emit (p, orc_arm_xt (0x06e00070,cond,0xf,Rd,Rm,rot))
-#define orc_arm_emit_uxth(p,cond,Rd,Rm,rot)       orc_arm_emit (p, orc_arm_xt (0x06f00070,cond,0xf,Rd,Rm,rot))
-#define orc_arm_emit_sxtb16(p,cond,Rd,Rm,rot)     orc_arm_emit (p, orc_arm_xt (0x06800070,cond,0xf,Rd,Rm,rot))
-#define orc_arm_emit_uxtb16(p,cond,Rd,Rm,rot)     orc_arm_emit (p, orc_arm_xt (0x06c00070,cond,0xf,Rd,Rm,rot))
-
-#define orc_arm_emit_sxtab(p,cond,Rd,Rn,Rm,rot)   orc_arm_emit (p, orc_arm_xt (0x06a00070,cond,Rn,Rd,Rm,rot))
-#define orc_arm_emit_sxtah(p,cond,Rd,Rn,Rm,rot)   orc_arm_emit (p, orc_arm_xt (0x06b00070,cond,Rn,Rd,Rm,rot))
-#define orc_arm_emit_uxtab(p,cond,Rd,Rn,Rm,rot)   orc_arm_emit (p, orc_arm_xt (0x06e00070,cond,Rn,Rd,Rm,rot))
-#define orc_arm_emit_uxtah(p,cond,Rd,Rn,Rm,rot)   orc_arm_emit (p, orc_arm_xt (0x06f00070,cond,Rn,Rd,Rm,rot))
-#define orc_arm_emit_sxtab16(p,cond,Rd,Rn,Rm,rot) orc_arm_emit (p, orc_arm_xt (0x06800070,cond,Rn,Rd,Rm,rot))
-#define orc_arm_emit_uxtab16(p,cond,Rd,Rn,Rm,rot) orc_arm_emit (p, orc_arm_xt (0x06c00070,cond,Rn,Rd,Rm,rot))
-
-#define orc_arm_pkh(op,cond,Rn,Rd,Rm,sh) (op|((cond)<<28)|((Rn)<<16)|((Rd)<<12)|((sh)<<7)|(Rm))
-#define orc_arm_emit_pkhbt(p,cond,Rd,Rn,Rm,sh) orc_arm_emit (p, orc_arm_xt (0x06800010,cond,Rd,Rn,Rm,sh))
-#define orc_arm_emit_pkhtb(p,cond,Rd,Rn,Rm,sh) orc_arm_emit (p, orc_arm_xt (0x06800050,cond,Rd,Rn,Rm,sh))
-
-#define orc_arm_sat(op,cond,Rd,sat,Rm,sh,a) (op|((cond)<<28)|((sat)<<16)|((Rd)<<12)|((sh)<<7)|((a)<<6)|(Rm))
-#define orc_arm_emit_ssat(p,cond,Rd,sat,Rm,sh,a) orc_arm_emit (p, orc_arm_sat (0x06a00010,cond,Rd,sat,Rm,sh,a))
-#define orc_arm_emit_usat(p,cond,Rd,sat,Rm,sh,a) orc_arm_emit (p, orc_arm_sat (0x06e00010,cond,Rd,sat,Rm,sh,a))
-
-#define orc_arm_rev(op,cond,Rd,Rm) (op|((cond)<<28)|((Rd)<<12)|(Rm))
-#define orc_arm_emit_rev(p,cond,Rd,Rm)   orc_arm_emit (p, orc_arm_rev (0x06b00030,cond,Rd,Rm))
-#define orc_arm_emit_rev16(p,cond,Rd,Rm) orc_arm_emit (p, orc_arm_rev (0x06e000b0,cond,Rd,Rm))
-
+/* multiplies */
 #define orc_arm_smulxy(cond,x,y,Rd,Rm,Rs) (0x01600080|((cond)<<28)|((Rd)<<16)|((Rs)<<8)|((y)<<6)|((x)<<5)|(Rm))
 #define orc_arm_emit_smulbb(p,cond,Rd,Rm,Rs) orc_arm_emit (p, orc_arm_smulxy (cond,0,0,Rd,Rm,Rs))
 #define orc_arm_emit_smulbt(p,cond,Rd,Rm,Rs) orc_arm_emit (p, orc_arm_smulxy (cond,0,1,Rd,Rm,Rs))
@@ -112,14 +86,8 @@ orc_arm_storew (OrcCompiler *compiler, int dest, int offset, int src1)
 void
 orc_arm_emit_mov_iw (OrcCompiler *p, int cond, int dest, int val, int loop)
 {
-  int shift = 0;
-
-  while (val && ((val & 3) == 0)) {
-    val >>= 2;
-    shift++;
-  }
   /* dest = val */
-  orc_arm_emit_mov_i (p, cond, 0, dest, shift, val);
+  orc_arm_emit_mov_i (p, cond, 0, dest, val);
   if (loop > 1)
     /* 2 words:  dest |= dest << 16 */
     orc_arm_emit_orr_rsi (p, cond, 0, dest, dest, dest, ORC_ARM_LSL, 16);
@@ -128,14 +96,8 @@ orc_arm_emit_mov_iw (OrcCompiler *p, int cond, int dest, int val, int loop)
 void
 orc_arm_emit_mov_ib (OrcCompiler *p, int cond, int dest, int val, int loop)
 {
-  int shift = 0;
-
-  while (val && ((val & 3) == 0)) {
-    val >>= 2;
-    shift++;
-  }
   /* 1 byte */
-  orc_arm_emit_mov_i (p, cond, 0, dest, shift, val);
+  orc_arm_emit_mov_i (p, cond, 0, dest, val);
   if (loop > 1)
     /* 2 bytes:  dest |= dest << 8 */
     orc_arm_emit_orr_rsi (p, cond, 0, dest, dest, dest, ORC_ARM_LSL, 8);
@@ -153,7 +115,7 @@ arm_rule_absX (OrcCompiler *p, void *user, OrcInstruction *insn)
   int tmp = p->tmpreg;
   int type = ORC_PTR_TO_INT(user);
 
-  orc_arm_emit_mov_i (p, ORC_ARM_COND_AL, 0, dest, 0, 0);
+  orc_arm_emit_mov_i (p, ORC_ARM_COND_AL, 0, dest, 0);
 
   if (type == 0) {
     /* negate tmp = 0 - src1 */
@@ -187,7 +149,7 @@ arm_rule_avgX (OrcCompiler *p, void *user, OrcInstruction *insn)
   /* signed variant, make a mask, FIXME, instruction constants */
   if (type >= 2) {
     /* mask for word 0x80008000 */
-    orc_arm_emit_mov_i (p, ORC_ARM_COND_AL, 0, mask, 4, 8);
+    orc_arm_emit_mov_i (p, ORC_ARM_COND_AL, 0, mask, 0x80000000);
     orc_arm_emit_orr_rsi (p, ORC_ARM_COND_AL, 0, mask, mask, mask, ORC_ARM_LSR, 16);
 
     if (type >= 3) {
@@ -210,12 +172,12 @@ arm_rule_avgX (OrcCompiler *p, void *user, OrcInstruction *insn)
    * need instruction wide constants */
   if (type <= 1) {
     /* clear 0x00010000 */
-    orc_arm_emit_bic_i (p, ORC_ARM_COND_AL, 0, dest, dest, 8, 1);
+    orc_arm_emit_bic_i (p, ORC_ARM_COND_AL, 0, dest, dest, 0x00010000);
     if (type == 0) {
       /* clear 0x00000100 */
-      orc_arm_emit_bic_i (p, ORC_ARM_COND_AL, 0, dest, dest, 12, 1);
+      orc_arm_emit_bic_i (p, ORC_ARM_COND_AL, 0, dest, dest, 0x00000100);
       /* clear 0x01000000 */
-      orc_arm_emit_bic_i (p, ORC_ARM_COND_AL, 0, dest, dest, 4, 1);
+      orc_arm_emit_bic_i (p, ORC_ARM_COND_AL, 0, dest, dest, 0x01000000);
     }
   } else if (type >= 2) {
     /* already have a mask, use it here */
@@ -244,7 +206,7 @@ arm_rule_cmpeqX (OrcCompiler *p, void *user, OrcInstruction *insn)
   orc_arm_emit_eor_r (p, ORC_ARM_COND_AL, 0, tmp, src1, src2);
 
   /* clear dest register */
-  orc_arm_emit_mov_i (p, ORC_ARM_COND_AL, 0, dest, 0, 0);
+  orc_arm_emit_mov_i (p, ORC_ARM_COND_AL, 0, dest, 0);
 
   /* tmp = 0 - tmp, set GE flags for 0 bytes */
   if (size == 1) {
@@ -254,7 +216,7 @@ arm_rule_cmpeqX (OrcCompiler *p, void *user, OrcInstruction *insn)
   }
 
   /* make 0xffffffff in tmp */
-  orc_arm_emit_mvn_i (p, ORC_ARM_COND_AL, 0, tmp, 0, 0);
+  orc_arm_emit_mvn_i (p, ORC_ARM_COND_AL, 0, tmp, 0);
 
   /* set 0xff for 0 bytes, 0x00 otherwise */
   orc_arm_emit_sel (p, ORC_ARM_COND_AL, dest, tmp, dest);
@@ -276,9 +238,9 @@ arm_rule_cmpgtsX (OrcCompiler *p, void *user, OrcInstruction *insn)
   }
 
   /* clear dest register */
-  orc_arm_emit_mov_i (p, ORC_ARM_COND_AL, 0, dest, 0, 0);
+  orc_arm_emit_mov_i (p, ORC_ARM_COND_AL, 0, dest, 0);
   /* make 0xffffffff in tmp */
-  orc_arm_emit_mvn_i (p, ORC_ARM_COND_AL, 0, tmp, 0, 0);
+  orc_arm_emit_mvn_i (p, ORC_ARM_COND_AL, 0, tmp, 0);
 
   /* set 0x00 for src2 >= src1 bytes, 0xff if src2 < src1 */
   orc_arm_emit_sel (p, ORC_ARM_COND_AL, dest, dest, tmp);
@@ -344,34 +306,34 @@ arm_rule_mullb (OrcCompiler *p, void *user, OrcInstruction *insn)
   int tmp3 = ORC_ARM_V8;
   int loop = 1;
 
-  /* first item */
-  orc_arm_emit_uxtb16 (p, ORC_ARM_COND_AL, tmp1, src1, 0);
-  orc_arm_emit_uxtb16 (p, ORC_ARM_COND_AL, tmp2, src2, 0);
+  /* extract and multiply first item */
+  orc_arm_emit_uxtb16 (p, ORC_ARM_COND_AL, tmp1, src1);
+  orc_arm_emit_uxtb16 (p, ORC_ARM_COND_AL, tmp2, src2);
   orc_arm_emit_smulbb (p, ORC_ARM_COND_AL, dest, tmp1, tmp2);
 
   if (loop > 1) {
     if (loop > 2) {
-      /* third item */
+      /* third item, reuse extracted bits for first item */
       orc_arm_emit_smultt (p, ORC_ARM_COND_AL, tmp1, tmp1, tmp2);
       /* merge with first */
-      orc_arm_emit_pkhbt (p, ORC_ARM_COND_AL, dest, dest, tmp1, 16);
+      orc_arm_emit_pkhbt_s (p, ORC_ARM_COND_AL, dest, dest, tmp1, 16);
     }
     /* clear upper bits */
-    orc_arm_emit_uxtb16 (p, ORC_ARM_COND_AL, dest, dest, 0);
+    orc_arm_emit_uxtb16 (p, ORC_ARM_COND_AL, dest, dest);
 
-    /* second item */
-    orc_arm_emit_uxtb16 (p, ORC_ARM_COND_AL, tmp1, src1, 1);
-    orc_arm_emit_uxtb16 (p, ORC_ARM_COND_AL, tmp2, src2, 1);
+    /* extract and multiply second item */
+    orc_arm_emit_uxtb16_r8 (p, ORC_ARM_COND_AL, tmp1, src1, 8);
+    orc_arm_emit_uxtb16_r8 (p, ORC_ARM_COND_AL, tmp2, src2, 8);
     orc_arm_emit_smulbb (p, ORC_ARM_COND_AL, tmp3, tmp1, tmp2);
 
     if (loop > 2) {
       /* forth item */
       orc_arm_emit_smultt (p, ORC_ARM_COND_AL, tmp1, tmp1, tmp2);
       /* merge with second */
-      orc_arm_emit_pkhbt (p, ORC_ARM_COND_AL, tmp3, tmp3, tmp1, 16);
+      orc_arm_emit_pkhbt_s (p, ORC_ARM_COND_AL, tmp3, tmp3, tmp1, 16);
     }
     /* clear upper bits */
-    orc_arm_emit_uxtb16 (p, ORC_ARM_COND_AL, tmp3, tmp3, 0);
+    orc_arm_emit_uxtb16 (p, ORC_ARM_COND_AL, tmp3, tmp3);
 
     /* merge results */
     orc_arm_emit_orr_rsi (p, ORC_ARM_COND_AL, 0, dest, dest, tmp3, ORC_ARM_LSL, 8);
@@ -391,8 +353,8 @@ arm_rule_mulhsb (OrcCompiler *p, void *user, OrcInstruction *insn)
   int loop = 1;
 
   /* first item (and third) */
-  orc_arm_emit_sxtb16 (p, ORC_ARM_COND_AL, tmp1, src1, 0);
-  orc_arm_emit_sxtb16 (p, ORC_ARM_COND_AL, tmp2, src2, 0);
+  orc_arm_emit_sxtb16 (p, ORC_ARM_COND_AL, tmp1, src1);
+  orc_arm_emit_sxtb16 (p, ORC_ARM_COND_AL, tmp2, src2);
   orc_arm_emit_smulbb (p, ORC_ARM_COND_AL, dest, tmp1, tmp2);
 
   if (loop > 1) {
@@ -400,24 +362,24 @@ arm_rule_mulhsb (OrcCompiler *p, void *user, OrcInstruction *insn)
       /* third item */
       orc_arm_emit_smultt (p, ORC_ARM_COND_AL, tmp1, tmp1, tmp2);
       /* merge with first */
-      orc_arm_emit_pkhbt (p, ORC_ARM_COND_AL, dest, dest, tmp1, 16);
+      orc_arm_emit_pkhbt_s (p, ORC_ARM_COND_AL, dest, dest, tmp1, 16);
     }
     /* extract upper bits */
-    orc_arm_emit_uxtb16 (p, ORC_ARM_COND_AL, dest, dest, 8);
+    orc_arm_emit_uxtb16_r8 (p, ORC_ARM_COND_AL, dest, dest, 8);
 
     /* second item (and fourth) */
-    orc_arm_emit_sxtb16 (p, ORC_ARM_COND_AL, tmp1, src1, 1);
-    orc_arm_emit_sxtb16 (p, ORC_ARM_COND_AL, tmp2, src2, 1);
+    orc_arm_emit_sxtb16_r8 (p, ORC_ARM_COND_AL, tmp1, src1, 8);
+    orc_arm_emit_sxtb16_r8 (p, ORC_ARM_COND_AL, tmp2, src2, 8);
     orc_arm_emit_smulbb (p, ORC_ARM_COND_AL, tmp3, tmp1, tmp2);
 
     if (loop > 2) {
       /* forth item */
       orc_arm_emit_smultt (p, ORC_ARM_COND_AL, tmp1, tmp1, tmp2);
       /* merge with second */
-      orc_arm_emit_pkhbt (p, ORC_ARM_COND_AL, tmp3, tmp3, tmp1, 16);
+      orc_arm_emit_pkhbt_s (p, ORC_ARM_COND_AL, tmp3, tmp3, tmp1, 16);
     }
     /* extract upper bits */
-    orc_arm_emit_uxtb16 (p, ORC_ARM_COND_AL, tmp3, tmp3, 8);
+    orc_arm_emit_uxtb16_r8 (p, ORC_ARM_COND_AL, tmp3, tmp3, 8);
 
     /* merge tmp3 */
     orc_arm_emit_orr_rsi (p, ORC_ARM_COND_AL, 0, dest, dest, tmp3, ORC_ARM_LSL, 8);
@@ -440,8 +402,8 @@ arm_rule_mulhub (OrcCompiler *p, void *user, OrcInstruction *insn)
   int loop = 1;
 
   /* first item (and third) */
-  orc_arm_emit_uxtb16 (p, ORC_ARM_COND_AL, tmp1, src1, 0);
-  orc_arm_emit_uxtb16 (p, ORC_ARM_COND_AL, tmp2, src2, 0);
+  orc_arm_emit_uxtb16 (p, ORC_ARM_COND_AL, tmp1, src1);
+  orc_arm_emit_uxtb16 (p, ORC_ARM_COND_AL, tmp2, src2);
   orc_arm_emit_smulbb (p, ORC_ARM_COND_AL, dest, tmp1, tmp2);
 
   if (loop > 1) {
@@ -449,24 +411,24 @@ arm_rule_mulhub (OrcCompiler *p, void *user, OrcInstruction *insn)
       /* third item */
       orc_arm_emit_smultt (p, ORC_ARM_COND_AL, tmp1, tmp1, tmp2);
       /* merge with first */
-      orc_arm_emit_pkhbt (p, ORC_ARM_COND_AL, dest, dest, tmp1, 16);
+      orc_arm_emit_pkhbt_s (p, ORC_ARM_COND_AL, dest, dest, tmp1, 16);
     }
     /* extract upper bits */
-    orc_arm_emit_uxtb16 (p, ORC_ARM_COND_AL, dest, dest, 8);
+    orc_arm_emit_uxtb16_r8 (p, ORC_ARM_COND_AL, dest, dest, 8);
 
     /* second item (and fourth) */
-    orc_arm_emit_uxtb16 (p, ORC_ARM_COND_AL, tmp1, src1, 1);
-    orc_arm_emit_uxtb16 (p, ORC_ARM_COND_AL, tmp2, src2, 1);
+    orc_arm_emit_uxtb16_r8 (p, ORC_ARM_COND_AL, tmp1, src1, 8);
+    orc_arm_emit_uxtb16_r8 (p, ORC_ARM_COND_AL, tmp2, src2, 8);
     orc_arm_emit_smulbb (p, ORC_ARM_COND_AL, tmp3, tmp1, tmp2);
 
     if (loop > 2) {
       /* forth item */
       orc_arm_emit_smultt (p, ORC_ARM_COND_AL, tmp1, tmp1, tmp2);
       /* merge with second */
-      orc_arm_emit_pkhbt (p, ORC_ARM_COND_AL, tmp3, tmp3, tmp1, 16);
+      orc_arm_emit_pkhbt_s (p, ORC_ARM_COND_AL, tmp3, tmp3, tmp1, 16);
     }
     /* extract upper bits */
-    orc_arm_emit_uxtb16 (p, ORC_ARM_COND_AL, tmp3, tmp3, 8);
+    orc_arm_emit_uxtb16_r8 (p, ORC_ARM_COND_AL, tmp3, tmp3, 8);
 
     /* merge tmp3 */
     orc_arm_emit_orr_rsi (p, ORC_ARM_COND_AL, 0, dest, dest, tmp3, ORC_ARM_LSL, 8);
@@ -505,7 +467,7 @@ arm_rule_shlX (OrcCompiler *p, void *user, OrcInstruction *insn)
       /* bigger values, shift and mask out excess bits */
       if (val >= size) {
         /* too big, clear all */
-        orc_arm_emit_mov_i (p, ORC_ARM_COND_AL, 0, dest, 0, 0);
+        orc_arm_emit_mov_i (p, ORC_ARM_COND_AL, 0, dest, 0);
       } else if (val > 0) {
         if (loop > 1 && size < 4) {
           /* shift, note that we skip the next instructions when 0 */
@@ -571,27 +533,32 @@ arm_rule_shrsX (OrcCompiler *p, void *user, OrcInstruction *insn)
 
       /* shift */
       if (size < 4) {
-        if (size == 1)
-          /* make loop * 80, position of sign bit after shift */
-          orc_arm_emit_mov_ib (p, ORC_ARM_COND_AL, mask, 0x80, loop);
-        else
-          /* make loop * 8000 */
-          orc_arm_emit_mov_iw (p, ORC_ARM_COND_AL, mask, 0x8000, loop);
-        /* make mask, save in tmp, we need the original mask */
-        orc_arm_emit_sub_rsi (p, ORC_ARM_COND_AL, 0, tmp, mask, mask, ORC_ARM_LSR, val);
-
-        /* do the shift */
-        orc_arm_emit_mov_rsi (p, ORC_ARM_COND_AL, 1, dest, src1, ORC_ARM_LSR, val);
-        /* clear upper bits */
-        orc_arm_emit_bic_rsi (p, ORC_ARM_COND_NE, 0, dest, dest, tmp, ORC_ARM_LSL, 1);
-
-        /* flip sign bit */
-        orc_arm_emit_eor_r (p, ORC_ARM_COND_NE, 0, dest, dest, mask);
-        /* extend sign bits */
-        if (size == 1)
-          orc_arm_emit_usub8 (p, ORC_ARM_COND_NE, dest, dest, mask);
-        else
-          orc_arm_emit_usub16 (p, ORC_ARM_COND_NE, dest, dest, mask);
+        if (size == 2 && val == 8) {
+          /* half word shift by 8 */
+          orc_arm_emit_sxtb16_r8 (p, ORC_ARM_COND_AL, dest, src1, 8);
+        } else {
+          if (size == 1)
+            /* make loop * 80, position of sign bit after shift */
+            orc_arm_emit_mov_ib (p, ORC_ARM_COND_AL, mask, 0x80, loop);
+          else
+            /* make loop * 8000 */
+            orc_arm_emit_mov_iw (p, ORC_ARM_COND_AL, mask, 0x8000, loop);
+          /* make mask, save in tmp, we need the original mask */
+          orc_arm_emit_sub_rsi (p, ORC_ARM_COND_AL, 0, tmp, mask, mask, ORC_ARM_LSR, val);
+
+          /* do the shift */
+          orc_arm_emit_mov_rsi (p, ORC_ARM_COND_AL, 1, dest, src1, ORC_ARM_LSR, val);
+          /* clear upper bits */
+          orc_arm_emit_bic_rsi (p, ORC_ARM_COND_NE, 0, dest, dest, tmp, ORC_ARM_LSL, 1);
+
+          /* flip sign bit */
+          orc_arm_emit_eor_r (p, ORC_ARM_COND_NE, 0, dest, dest, mask);
+          /* extend sign bits */
+          if (size == 1)
+            orc_arm_emit_usub8 (p, ORC_ARM_COND_NE, dest, dest, mask);
+          else
+            orc_arm_emit_usub16 (p, ORC_ARM_COND_NE, dest, dest, mask);
+        }
       } else {
         /* full word shift */
         orc_arm_emit_mov_rsi (p, ORC_ARM_COND_AL, 0, dest, src1, ORC_ARM_ASR, val);
@@ -648,24 +615,30 @@ arm_rule_shruX (OrcCompiler *p, void *user, OrcInstruction *insn)
     /* shift and mask out excess bits */
     if (val >= size) {
       /* too big, clear all */
-      orc_arm_emit_mov_i (p, ORC_ARM_COND_AL, 0, dest, 0, 0);
+      orc_arm_emit_mov_i (p, ORC_ARM_COND_AL, 0, dest, 0);
     } else if (val > 0) {
       if (size < 4) {
-        /* do the shift */
-        orc_arm_emit_mov_rsi (p, ORC_ARM_COND_AL, 1, dest, src1, ORC_ARM_LSR, val);
+        if (size == 2 && val == 8) {
+          /* half word shift by 8 */
+          orc_arm_emit_uxtb16_r8 (p, ORC_ARM_COND_AL, dest, src1, 8);
+        } else {
+          /* do the shift, set S flags */
+          orc_arm_emit_mov_rsi (p, ORC_ARM_COND_AL, 1, dest, src1, ORC_ARM_LSR, val);
 
-        if (size == 1)
-          /* make loop * 0x80 */
-          orc_arm_emit_mov_ib (p, ORC_ARM_COND_NE, mask, 0x80, loop);
-        else
-          /* make loop * 0x8000 */
-          orc_arm_emit_mov_iw (p, ORC_ARM_COND_NE, mask, 0x8000, loop);
-        /* make mask */
-        orc_arm_emit_sub_rsi (p, ORC_ARM_COND_NE, 0, mask, mask, mask, ORC_ARM_LSR, val);
+          if (size == 1)
+            /* make loop * 0x80 */
+            orc_arm_emit_mov_ib (p, ORC_ARM_COND_NE, mask, 0x80, loop);
+          else
+            /* make loop * 0x8000 */
+            orc_arm_emit_mov_iw (p, ORC_ARM_COND_NE, mask, 0x8000, loop);
+          /* make mask */
+          orc_arm_emit_sub_rsi (p, ORC_ARM_COND_NE, 0, mask, mask, mask, ORC_ARM_LSR, val);
 
-        /* clear upper bits */
-        orc_arm_emit_bic_rsi (p, ORC_ARM_COND_NE, 0, dest, dest, mask, ORC_ARM_LSL, 1);
+          /* clear upper bits */
+          orc_arm_emit_bic_rsi (p, ORC_ARM_COND_NE, 0, dest, dest, mask, ORC_ARM_LSL, 1);
+        }
       } else {
+        /* one 4 byte shift, no need for the S flag */
         orc_arm_emit_mov_rsi (p, ORC_ARM_COND_AL, 0, dest, src1, ORC_ARM_LSR, val);
       }
     }
@@ -682,7 +655,7 @@ arm_rule_shruX (OrcCompiler *p, void *user, OrcInstruction *insn)
       else
         /* make loop * 0x8000 */
         orc_arm_emit_mov_iw (p, ORC_ARM_COND_NE, mask, 0x8000, loop);
-      /* mask mask */
+      /* make mask */
       orc_arm_emit_sub_rsr (p, ORC_ARM_COND_NE, 0, mask, mask, mask, ORC_ARM_LSR, src2);
 
       /* clear bits */
@@ -707,9 +680,9 @@ arm_rule_signX (OrcCompiler *p, void *user, OrcInstruction *insn)
   int type = ORC_PTR_TO_INT(user);
 
   /* make 0 */
-  orc_arm_emit_mov_i (p, ORC_ARM_COND_AL, 0, zero, 0, 0);
+  orc_arm_emit_mov_i (p, ORC_ARM_COND_AL, 0, zero, 0);
   /* make 0xffffffff */
-  orc_arm_emit_mvn_i (p, ORC_ARM_COND_AL, 0, ones, 0, 0);
+  orc_arm_emit_mvn_i (p, ORC_ARM_COND_AL, 0, ones, 0);
 
   /* dest = src1 - 0 (src1 >= 0 ? 0 : -1) */
   if (type == 0)
@@ -797,7 +770,7 @@ arm_rule_mullw (OrcCompiler *p, void *user, OrcInstruction *insn)
 
   if (loop == 2) {
     orc_arm_emit_smultt (p, ORC_ARM_COND_AL, tmp, src1, src2);
-    orc_arm_emit_pkhbt (p, ORC_ARM_COND_AL, dest, dest, tmp, 16);
+    orc_arm_emit_pkhbt_s (p, ORC_ARM_COND_AL, dest, dest, tmp, 16);
   }
 }
 static void
@@ -814,7 +787,7 @@ arm_rule_mulhsw (OrcCompiler *p, void *user, OrcInstruction *insn)
     orc_arm_emit_mov_rsi (p, ORC_ARM_COND_AL, 0, dest, dest, ORC_ARM_ASR, 16);
   } else {
     orc_arm_emit_smultt (p, ORC_ARM_COND_AL, tmp, src1, src2);
-    orc_arm_emit_pkhtb (p, ORC_ARM_COND_AL, dest, tmp, dest, 16);
+    orc_arm_emit_pkhtb_s (p, ORC_ARM_COND_AL, dest, tmp, dest, 16);
   }
 }
 static void
@@ -829,8 +802,8 @@ arm_rule_mulhuw (OrcCompiler *p, void *user, OrcInstruction *insn)
   int loop = 1;
 
   /* extract first halves */
-  orc_arm_emit_uxth (p, ORC_ARM_COND_AL, tmp1, src1, 0);
-  orc_arm_emit_uxth (p, ORC_ARM_COND_AL, tmp2, src2, 0);
+  orc_arm_emit_uxth (p, ORC_ARM_COND_AL, tmp1, src1);
+  orc_arm_emit_uxth (p, ORC_ARM_COND_AL, tmp2, src2);
   /* multiply, result should fit in the word */
   orc_arm_emit_mul (p, ORC_ARM_COND_AL, 0, dest, tmp1, tmp2);
 
@@ -838,11 +811,11 @@ arm_rule_mulhuw (OrcCompiler *p, void *user, OrcInstruction *insn)
     orc_arm_emit_mov_rsi (p, ORC_ARM_COND_AL, 0, dest, dest, ORC_ARM_LSR, 16);
   } else {
     /* second halves */
-    orc_arm_emit_uxth (p, ORC_ARM_COND_AL, tmp1, src1, 2);
-    orc_arm_emit_uxth (p, ORC_ARM_COND_AL, tmp2, src2, 2);
+    orc_arm_emit_uxth_r8 (p, ORC_ARM_COND_AL, tmp1, src1, 16);
+    orc_arm_emit_uxth_r8 (p, ORC_ARM_COND_AL, tmp2, src2, 16);
     orc_arm_emit_mul (p, ORC_ARM_COND_AL, 0, tmp1, tmp1, tmp2);
     /* merge */
-    orc_arm_emit_pkhtb (p, ORC_ARM_COND_AL, dest, tmp1, dest, 16);
+    orc_arm_emit_pkhtb_s (p, ORC_ARM_COND_AL, dest, tmp1, dest, 16);
   }
 }
 BINARY_MM (subw, ssub16);
@@ -856,7 +829,7 @@ arm_rule_absl (OrcCompiler *p, void *user, OrcInstruction *insn)
   int dest = ORC_DEST_ARG (p, insn, 0);
 
   /* reverse sign 0 - src1, assume the value is negative */
-  orc_arm_emit_rsb_i (p, ORC_ARM_COND_AL, 1, dest, src1, 0, 0);
+  orc_arm_emit_rsb_i (p, ORC_ARM_COND_AL, 1, dest, src1, 0);
 
   /* if we got negative, copy the original value again */
   orc_arm_emit_mov_r (p, ORC_ARM_COND_MI, 0, dest, src1);
@@ -875,7 +848,7 @@ arm_rule_addusl (OrcCompiler *p, void *user, OrcInstruction *insn)
   orc_arm_emit_add_r (p, ORC_ARM_COND_AL, 1, dest, src1, src2);
 
   /* on overflow, move ffffffff */
-  orc_arm_emit_mvn_i (p, ORC_ARM_COND_CS, 0, dest, 0, 0);
+  orc_arm_emit_mvn_i (p, ORC_ARM_COND_CS, 0, dest, 0);
 }
 static void
 arm_rule_avgXl (OrcCompiler *p, void *user, OrcInstruction *insn)
@@ -904,10 +877,10 @@ arm_rule_cmpeql (OrcCompiler *p, void *user, OrcInstruction *insn)
   orc_arm_emit_cmp_r (p, ORC_ARM_COND_AL, src1, src2);
 
   /* set to all 0 when not equal */
-  orc_arm_emit_mov_i (p, ORC_ARM_COND_NE, 0, dest, 0, 0);
+  orc_arm_emit_mov_i (p, ORC_ARM_COND_NE, 0, dest, 0);
 
   /* set to all ff when equal */
-  orc_arm_emit_mvn_i (p, ORC_ARM_COND_EQ, 0, dest, 0, 0);
+  orc_arm_emit_mvn_i (p, ORC_ARM_COND_EQ, 0, dest, 0);
 }
 static void
 arm_rule_cmpgtsl (OrcCompiler *p, void *user, OrcInstruction *insn)
@@ -920,10 +893,10 @@ arm_rule_cmpgtsl (OrcCompiler *p, void *user, OrcInstruction *insn)
   orc_arm_emit_cmp_r (p, ORC_ARM_COND_AL, src1, src2);
 
   /* set to all 0 when less or equal */
-  orc_arm_emit_mov_i (p, ORC_ARM_COND_LE, 0, dest, 0, 0);
+  orc_arm_emit_mov_i (p, ORC_ARM_COND_LE, 0, dest, 0);
 
   /* set to all ff when greater */
-  orc_arm_emit_mvn_i (p, ORC_ARM_COND_GT, 0, dest, 0, 0);
+  orc_arm_emit_mvn_i (p, ORC_ARM_COND_GT, 0, dest, 0);
 }
 
 static void
@@ -1020,7 +993,7 @@ arm_rule_signl (OrcCompiler *p, void *user, OrcInstruction *insn)
   int tmp = p->tmpreg;
 
   /* dest = 0 - src1 */
-  orc_arm_emit_rsb_i (p, ORC_ARM_COND_AL, 0, dest, src1, 0, 0);
+  orc_arm_emit_rsb_i (p, ORC_ARM_COND_AL, 0, dest, src1, 0);
 
   /* move src1 sign into tmp */
   orc_arm_emit_mov_rsi (p, ORC_ARM_COND_AL, 0, tmp, src1, ORC_ARM_ASR, 31);
@@ -1041,7 +1014,7 @@ arm_rule_subusl (OrcCompiler *p, void *user, OrcInstruction *insn)
   orc_arm_emit_sub_r (p, ORC_ARM_COND_AL, 1, dest, src1, src2);
 
   /* overflow, move 00000000 */
-  orc_arm_emit_mov_i (p, ORC_ARM_COND_CC, 0, dest, 0, 0);
+  orc_arm_emit_mov_i (p, ORC_ARM_COND_CC, 0, dest, 0);
 }
 
 static void
@@ -1053,11 +1026,11 @@ arm_rule_convsbw (OrcCompiler *p, void *user, OrcInstruction *insn)
 
   if (loop == 1) {
     /* single byte */
-    orc_arm_emit_sxtb (p, ORC_ARM_COND_AL, dest, src1, 0);
+    orc_arm_emit_sxtb (p, ORC_ARM_COND_AL, dest, src1);
   } else {
     /* two bytes */
-    orc_arm_emit_pkhbt (p, ORC_ARM_COND_AL, dest, src1, src1, 8);
-    orc_arm_emit_sxtb16 (p, ORC_ARM_COND_AL, dest, dest, 0);
+    orc_arm_emit_pkhbt_s (p, ORC_ARM_COND_AL, dest, src1, src1, 8);
+    orc_arm_emit_sxtb16 (p, ORC_ARM_COND_AL, dest, dest);
   }
 }
 
@@ -1070,11 +1043,11 @@ arm_rule_convubw (OrcCompiler *p, void *user, OrcInstruction *insn)
 
   if (loop == 1) {
     /* single byte */
-    orc_arm_emit_uxtb (p, ORC_ARM_COND_AL, dest, src1, 0);
+    orc_arm_emit_uxtb (p, ORC_ARM_COND_AL, dest, src1);
   } else {
     /* two bytes */
-    orc_arm_emit_pkhbt (p, ORC_ARM_COND_AL, dest, src1, src1, 8);
-    orc_arm_emit_uxtb16 (p, ORC_ARM_COND_AL, dest, dest, 0);
+    orc_arm_emit_pkhbt_s (p, ORC_ARM_COND_AL, dest, src1, src1, 8);
+    orc_arm_emit_uxtb16 (p, ORC_ARM_COND_AL, dest, dest);
   }
 }
 
@@ -1084,7 +1057,7 @@ arm_rule_convswl (OrcCompiler *p, void *user, OrcInstruction *insn)
   int src1 = ORC_SRC_ARG (p, insn, 0);
   int dest = ORC_DEST_ARG (p, insn, 0);
 
-  orc_arm_emit_sxth (p, ORC_ARM_COND_AL, dest, src1, 0);
+  orc_arm_emit_sxth (p, ORC_ARM_COND_AL, dest, src1);
 }
 static void
 arm_rule_convuwl (OrcCompiler *p, void *user, OrcInstruction *insn)
@@ -1092,7 +1065,7 @@ arm_rule_convuwl (OrcCompiler *p, void *user, OrcInstruction *insn)
   int src1 = ORC_SRC_ARG (p, insn, 0);
   int dest = ORC_DEST_ARG (p, insn, 0);
 
-  orc_arm_emit_uxth (p, ORC_ARM_COND_AL, dest, src1, 0);
+  orc_arm_emit_uxth (p, ORC_ARM_COND_AL, dest, src1);
 }
 
 static void
@@ -1104,7 +1077,7 @@ arm_rule_convwb (OrcCompiler *p, void *user, OrcInstruction *insn)
 
   if (loop == 2) {
     /* two words */
-    orc_arm_emit_uxtb16 (p, ORC_ARM_COND_AL, dest, src1, 0);
+    orc_arm_emit_uxtb16 (p, ORC_ARM_COND_AL, dest, src1);
     orc_arm_emit_orr_rsi (p, ORC_ARM_COND_AL, 0, dest, dest, dest, ORC_ARM_LSR, 8);
   }
 }
@@ -1120,7 +1093,7 @@ arm_rule_convssswb (OrcCompiler *p, void *user, OrcInstruction *insn)
 
   if (loop == 2) {
     /* two words */
-    orc_arm_emit_uxtb16 (p, ORC_ARM_COND_AL, dest, src1, 0);
+    orc_arm_emit_uxtb16 (p, ORC_ARM_COND_AL, dest, dest);
     orc_arm_emit_orr_rsi (p, ORC_ARM_COND_AL, 0, dest, dest, dest, ORC_ARM_LSR, 8);
   }
 }
@@ -1135,7 +1108,7 @@ arm_rule_convsuswb (OrcCompiler *p, void *user, OrcInstruction *insn)
 
   if (loop == 2) {
     /* two words */
-    orc_arm_emit_uxtb16 (p, ORC_ARM_COND_AL, dest, src1, 0);
+    orc_arm_emit_uxtb16 (p, ORC_ARM_COND_AL, dest, dest);
     orc_arm_emit_orr_rsi (p, ORC_ARM_COND_AL, 0, dest, dest, dest, ORC_ARM_LSR, 8);
   }
 }
@@ -1147,16 +1120,16 @@ arm_rule_convusswb (OrcCompiler *p, void *user, OrcInstruction *insn)
   int loop = 1;
 
   /* sign bias */
-  orc_arm_emit_eor_i (p, ORC_ARM_COND_AL, 0, dest, src1, 8, 2);
+  orc_arm_emit_eor_i (p, ORC_ARM_COND_AL, 0, dest, src1, 0x00008000);
   if (loop == 2)
-    orc_arm_emit_eor_i (p, ORC_ARM_COND_AL, 0, dest, src1, 1, 2);
+    orc_arm_emit_eor_i (p, ORC_ARM_COND_AL, 0, dest, dest, 0x80000000);
 
   /* saturate to signed region */
   orc_arm_emit_usat16 (p, ORC_ARM_COND_AL, dest, 7, dest);
 
   if (loop == 2) {
     /* pack two words */
-    orc_arm_emit_uxtb16 (p, ORC_ARM_COND_AL, dest, src1, 0);
+    orc_arm_emit_uxtb16 (p, ORC_ARM_COND_AL, dest, dest);
     orc_arm_emit_orr_rsi (p, ORC_ARM_COND_AL, 0, dest, dest, dest, ORC_ARM_LSR, 8);
   }
 }
@@ -1168,16 +1141,16 @@ arm_rule_convuuswb (OrcCompiler *p, void *user, OrcInstruction *insn)
   int loop = 1;
 
   /* sign bias */
-  orc_arm_emit_eor_i (p, ORC_ARM_COND_AL, 0, dest, src1, 8, 2);
+  orc_arm_emit_eor_i (p, ORC_ARM_COND_AL, 0, dest, src1, 0x00008000);
   if (loop == 2)
-    orc_arm_emit_eor_i (p, ORC_ARM_COND_AL, 0, dest, src1, 1, 2);
+    orc_arm_emit_eor_i (p, ORC_ARM_COND_AL, 0, dest, dest, 0x80000000);
 
   /* saturate to unsigned region */
   orc_arm_emit_usat16 (p, ORC_ARM_COND_AL, dest, 8, dest);
 
   if (loop == 2) {
     /* pack two words */
-    orc_arm_emit_uxtb16 (p, ORC_ARM_COND_AL, dest, src1, 0);
+    orc_arm_emit_uxtb16 (p, ORC_ARM_COND_AL, dest, dest);
     orc_arm_emit_orr_rsi (p, ORC_ARM_COND_AL, 0, dest, dest, dest, ORC_ARM_LSR, 8);
   }
 }
@@ -1193,7 +1166,7 @@ arm_rule_convssslw (OrcCompiler *p, void *user, OrcInstruction *insn)
   int src1 = ORC_SRC_ARG (p, insn, 0);
   int dest = ORC_DEST_ARG (p, insn, 0);
 
-  orc_arm_emit_ssat (p, ORC_ARM_COND_AL, dest, 16, src1, 0, 0);
+  orc_arm_emit_ssat (p, ORC_ARM_COND_AL, dest, 16, src1);
 }
 static void
 arm_rule_convsuslw (OrcCompiler *p, void *user, OrcInstruction *insn)
@@ -1201,7 +1174,7 @@ arm_rule_convsuslw (OrcCompiler *p, void *user, OrcInstruction *insn)
   int src1 = ORC_SRC_ARG (p, insn, 0);
   int dest = ORC_DEST_ARG (p, insn, 0);
 
-  orc_arm_emit_usat (p, ORC_ARM_COND_AL, dest, 16, src1, 0, 0);
+  orc_arm_emit_usat (p, ORC_ARM_COND_AL, dest, 16, src1);
 }
 static void
 arm_rule_convusslw (OrcCompiler *p, void *user, OrcInstruction *insn)
@@ -1210,9 +1183,9 @@ arm_rule_convusslw (OrcCompiler *p, void *user, OrcInstruction *insn)
   int dest = ORC_DEST_ARG (p, insn, 0);
 
   /* sign bias */
-  orc_arm_emit_eor_i (p, ORC_ARM_COND_AL, 0, dest, src1, 1, 2);
+  orc_arm_emit_eor_i (p, ORC_ARM_COND_AL, 0, dest, src1, 0x80000000);
   /* saturate to signed region */
-  orc_arm_emit_usat (p, ORC_ARM_COND_AL, dest, 7, dest, 0, 0);
+  orc_arm_emit_usat (p, ORC_ARM_COND_AL, dest, 15, dest);
 }
 static void
 arm_rule_convuuslw (OrcCompiler *p, void *user, OrcInstruction *insn)
@@ -1221,9 +1194,9 @@ arm_rule_convuuslw (OrcCompiler *p, void *user, OrcInstruction *insn)
   int dest = ORC_DEST_ARG (p, insn, 0);
 
   /* sign bias */
-  orc_arm_emit_eor_i (p, ORC_ARM_COND_AL, 0, dest, src1, 1, 2);
+  orc_arm_emit_eor_i (p, ORC_ARM_COND_AL, 0, dest, src1, 0x80000000);
   /* saturate to unsigned region */
-  orc_arm_emit_usat (p, ORC_ARM_COND_AL, dest, 8, dest, 0, 0);
+  orc_arm_emit_usat (p, ORC_ARM_COND_AL, dest, 16, dest);
 }
 
 static void
@@ -1238,14 +1211,14 @@ arm_rule_mulsbw (OrcCompiler *p, void *user, OrcInstruction *insn)
   int loop = 1;
 
   /* first item */
-  orc_arm_emit_sxtb16 (p, ORC_ARM_COND_AL, tmp1, src1, 0);
-  orc_arm_emit_sxtb16 (p, ORC_ARM_COND_AL, tmp2, src2, 0);
+  orc_arm_emit_sxtb16 (p, ORC_ARM_COND_AL, tmp1, src1);
+  orc_arm_emit_sxtb16 (p, ORC_ARM_COND_AL, tmp2, src2);
   orc_arm_emit_smulbb (p, ORC_ARM_COND_AL, dest, tmp1, tmp2);
 
   if (loop > 1) {
     /* second item */
-    orc_arm_emit_sxtb16 (p, ORC_ARM_COND_AL, tmp1, src1, 1);
-    orc_arm_emit_sxtb16 (p, ORC_ARM_COND_AL, tmp2, src2, 1);
+    orc_arm_emit_sxtb16_r8 (p, ORC_ARM_COND_AL, tmp1, src1, 8);
+    orc_arm_emit_sxtb16_r8 (p, ORC_ARM_COND_AL, tmp2, src2, 8);
     orc_arm_emit_smulbb (p, ORC_ARM_COND_AL, tmp1, tmp1, tmp2);
 
     /* merge results */
@@ -1265,14 +1238,14 @@ arm_rule_mulubw (OrcCompiler *p, void *user, OrcInstruction *insn)
   int loop = 1;
 
   /* first item */
-  orc_arm_emit_uxtb16 (p, ORC_ARM_COND_AL, tmp1, src1, 0);
-  orc_arm_emit_uxtb16 (p, ORC_ARM_COND_AL, tmp2, src2, 0);
+  orc_arm_emit_uxtb16 (p, ORC_ARM_COND_AL, tmp1, src1);
+  orc_arm_emit_uxtb16 (p, ORC_ARM_COND_AL, tmp2, src2);
   orc_arm_emit_smulbb (p, ORC_ARM_COND_AL, dest, tmp1, tmp2);
 
   if (loop > 1) {
     /* second item */
-    orc_arm_emit_uxtb16 (p, ORC_ARM_COND_AL, tmp1, src1, 1);
-    orc_arm_emit_uxtb16 (p, ORC_ARM_COND_AL, tmp2, src2, 1);
+    orc_arm_emit_uxtb16_r8 (p, ORC_ARM_COND_AL, tmp1, src1, 8);
+    orc_arm_emit_uxtb16_r8 (p, ORC_ARM_COND_AL, tmp2, src2, 8);
     orc_arm_emit_smulbb (p, ORC_ARM_COND_AL, tmp1, tmp1, tmp2);
 
     /* merge results */
@@ -1289,8 +1262,8 @@ arm_rule_mulswl (OrcCompiler *p, void *user, OrcInstruction *insn)
   int dest = ORC_DEST_ARG (p, insn, 0);
   int tmp1 = p->tmpreg;
 
-  orc_arm_emit_sxth (p, ORC_ARM_COND_AL, tmp1, src1, 0);
-  orc_arm_emit_sxth (p, ORC_ARM_COND_AL, dest, src2, 0);
+  orc_arm_emit_sxth (p, ORC_ARM_COND_AL, tmp1, src1);
+  orc_arm_emit_sxth (p, ORC_ARM_COND_AL, dest, src2);
   orc_arm_emit_mul (p, ORC_ARM_COND_AL, 0, dest, tmp1, dest);
 }
 
@@ -1303,8 +1276,8 @@ arm_rule_muluwl (OrcCompiler *p, void *user, OrcInstruction *insn)
   int dest = ORC_DEST_ARG (p, insn, 0);
   int tmp1 = p->tmpreg;
 
-  orc_arm_emit_uxth (p, ORC_ARM_COND_AL, tmp1, src1, 0);
-  orc_arm_emit_uxth (p, ORC_ARM_COND_AL, dest, src2, 0);
+  orc_arm_emit_uxth (p, ORC_ARM_COND_AL, tmp1, src1);
+  orc_arm_emit_uxth (p, ORC_ARM_COND_AL, dest, src2);
   orc_arm_emit_mul (p, ORC_ARM_COND_AL, 0, dest, tmp1, dest);
 }
 
@@ -1315,25 +1288,28 @@ arm_rule_mergewl (OrcCompiler *p, void *user, OrcInstruction *insn)
   int src2 = ORC_SRC_ARG (p, insn, 1);
   int dest = ORC_DEST_ARG (p, insn, 0);
 
-  orc_arm_emit_pkhbt (p, ORC_ARM_COND_AL, dest, src1, src2, 16);
+  orc_arm_emit_pkhbt_s (p, ORC_ARM_COND_AL, dest, src1, src2, 16);
 }
 static void
 arm_rule_mergebw (OrcCompiler *p, void *user, OrcInstruction *insn)
 {
+  /* BINARY_BW(mergebw, "((uint8_t)%s) | ((uint8_t)%s << 8)") */
   int src1 = ORC_SRC_ARG (p, insn, 0);
   int src2 = ORC_SRC_ARG (p, insn, 1);
   int dest = ORC_DEST_ARG (p, insn, 0);
   int tmp = p->tmpreg;
   int loop = 1;
 
-  orc_arm_emit_uxtb (p, ORC_ARM_COND_AL, dest, src1, 0);
-
   if (loop == 1) {
     /* 1 word */
+    orc_arm_emit_uxtb (p, ORC_ARM_COND_AL, dest, src1);
     orc_arm_emit_orr_rsi (p, ORC_ARM_COND_AL, 0, dest, dest, src2, ORC_ARM_LSL, 8);
   } else {
     /* 2 words */
-    orc_arm_emit_uxtb (p, ORC_ARM_COND_AL, tmp, src2, 0);
+    orc_arm_emit_pkhbt_s (p, ORC_ARM_COND_AL, dest, src1, src1, 8);
+    orc_arm_emit_uxtb16 (p, ORC_ARM_COND_AL, dest, dest);
+    orc_arm_emit_pkhbt_s (p, ORC_ARM_COND_AL, tmp, src2, src2, 8);
+    orc_arm_emit_uxtb16 (p, ORC_ARM_COND_AL, tmp, tmp);
     orc_arm_emit_orr_rsi (p, ORC_ARM_COND_AL, 0, dest, dest, tmp, ORC_ARM_LSL, 8);
   }
 }
@@ -1341,51 +1317,52 @@ arm_rule_mergebw (OrcCompiler *p, void *user, OrcInstruction *insn)
 static void
 arm_rule_select0wb (OrcCompiler *p, void *user, OrcInstruction *insn)
 {
+  /* UNARY_WB(select0wb, "(uint16_t)%s & 0xff") */
   int src1 = ORC_SRC_ARG (p, insn, 0);
   int dest = ORC_DEST_ARG (p, insn, 0);
-  int tmp = p->tmpreg;
   int loop = 1;
 
-  orc_arm_emit_uxtb (p, ORC_ARM_COND_AL, dest, src1, 0);
-
-  if (loop == 2) {
+  if (loop == 1) {
+    /* 1 words */
+    /* NOP */
+  } else {
     /* 2 words */
-    orc_arm_emit_uxtb (p, ORC_ARM_COND_AL, tmp, src1, 2);
-    orc_arm_emit_orr_rsi (p, ORC_ARM_COND_AL, 0, dest, dest, tmp, ORC_ARM_LSL, 8);
+    orc_arm_emit_uxtb16 (p, ORC_ARM_COND_AL, dest, src1);
+    orc_arm_emit_orr_rsi (p, ORC_ARM_COND_AL, 0, dest, dest, dest, ORC_ARM_LSR, 8);
   }
 }
 
 static void
 arm_rule_select1wb (OrcCompiler *p, void *user, OrcInstruction *insn)
 {
+  /* UNARY_WB(select1wb, "((uint16_t)%s >> 8)&0xff") */
   int src1 = ORC_SRC_ARG (p, insn, 0);
   int dest = ORC_DEST_ARG (p, insn, 0);
-  int tmp = p->tmpreg;
   int loop = 1;
 
-  orc_arm_emit_uxtb (p, ORC_ARM_COND_AL, dest, src1, 1);
-
-  if (loop == 2) {
+  if (loop == 1) {
+    /* 1 words */
+    orc_arm_emit_mov_rsi (p, ORC_ARM_COND_AL, 0, dest, src1, ORC_ARM_LSR, 8);
+  } else {
     /* 2 words */
-    orc_arm_emit_uxtb (p, ORC_ARM_COND_AL, tmp, src1, 3);
-    orc_arm_emit_orr_rsi (p, ORC_ARM_COND_AL, 0, dest, dest, tmp, ORC_ARM_LSL, 8);
+    orc_arm_emit_uxtb16_r8 (p, ORC_ARM_COND_AL, dest, src1, 8);
+    orc_arm_emit_orr_rsi (p, ORC_ARM_COND_AL, 0, dest, dest, dest, ORC_ARM_LSR, 8);
   }
 }
 static void
 arm_rule_select0lw (OrcCompiler *p, void *user, OrcInstruction *insn)
 {
-  int src1 = ORC_SRC_ARG (p, insn, 0);
-  int dest = ORC_DEST_ARG (p, insn, 0);
-
-  orc_arm_emit_uxth (p, ORC_ARM_COND_AL, dest, src1, 0);
+  /* UNARY_LW(select0lw, "(uint32_t)%s & 0xffff") */
+  /* NOP */
 }
 static void
 arm_rule_select1lw (OrcCompiler *p, void *user, OrcInstruction *insn)
 {
+  /* UNARY_LW(select1lw, "((uint32_t)%s >> 16)&0xffff") */
   int src1 = ORC_SRC_ARG (p, insn, 0);
   int dest = ORC_DEST_ARG (p, insn, 0);
 
-  orc_arm_emit_uxth (p, ORC_ARM_COND_AL, dest, src1, 2);
+  orc_arm_emit_mov_rsi (p, ORC_ARM_COND_AL, 0, dest, src1, ORC_ARM_LSR, 16);
 }
 
 static void