tcg/mips: use seb/seh instructions on MIPS32R2
authorAurelien Jarno <aurelien@aurel32.net>
Mon, 5 Apr 2010 11:19:56 +0000 (13:19 +0200)
committerAurelien Jarno <aurelien@aurel32.net>
Mon, 5 Apr 2010 13:16:44 +0000 (15:16 +0200)
Signed-off-by: Aurelien Jarno <aurelien@aurel32.net>
tcg/mips/tcg-target.c
tcg/mips/tcg-target.h

index a33e785f94f54a71424c540dc9c9458f8db12971..f4fb615bf0c4affdd947124523056508734c0ef7 100644 (file)
@@ -270,7 +270,6 @@ static inline int tcg_target_const_match(tcg_target_long val,
 
 /* instruction opcodes */
 enum {
-    OPC_SPECIAL  = 0x00 << 26,
     OPC_BEQ      = 0x04 << 26,
     OPC_BNE      = 0x05 << 26,
     OPC_ADDIU    = 0x09 << 26,
@@ -289,6 +288,8 @@ enum {
     OPC_SB       = 0x28 << 26,
     OPC_SH       = 0x29 << 26,
     OPC_SW       = 0x2B << 26,
+
+    OPC_SPECIAL  = 0x00 << 26,
     OPC_SLL      = OPC_SPECIAL | 0x00,
     OPC_SRL      = OPC_SPECIAL | 0x02,
     OPC_SRA      = OPC_SPECIAL | 0x03,
@@ -311,6 +312,10 @@ enum {
     OPC_NOR      = OPC_SPECIAL | 0x27,
     OPC_SLT      = OPC_SPECIAL | 0x2A,
     OPC_SLTU     = OPC_SPECIAL | 0x2B,
+
+    OPC_SPECIAL3 = 0x1f << 26,
+    OPC_SEB      = OPC_SPECIAL3 | 0x420,
+    OPC_SEH      = OPC_SPECIAL3 | 0x620,
 };
 
 /*
@@ -441,6 +446,26 @@ static inline void tcg_out_bswap32(TCGContext *s, int ret, int arg)
     tcg_out_opc_reg(s, OPC_OR, ret, ret, TCG_REG_AT);
 }
 
+static inline void tcg_out_ext8s(TCGContext *s, int ret, int arg)
+{
+#ifdef _MIPS_ARCH_MIPS32R2
+    tcg_out_opc_reg(s, OPC_SEB, ret, 0, arg);
+#else
+    tcg_out_opc_sa(s, OPC_SLL, ret, arg, 24);
+    tcg_out_opc_sa(s, OPC_SRA, ret, ret, 24);
+#endif
+}
+
+static inline void tcg_out_ext16s(TCGContext *s, int ret, int arg)
+{
+#ifdef _MIPS_ARCH_MIPS32R2
+    tcg_out_opc_reg(s, OPC_SEH, ret, 0, arg);
+#else
+    tcg_out_opc_sa(s, OPC_SLL, ret, arg, 16);
+    tcg_out_opc_sa(s, OPC_SRA, ret, ret, 16);
+#endif
+}
+
 static inline void tcg_out_ldst(TCGContext *s, int opc, int arg,
                               int arg1, tcg_target_long arg2)
 {
@@ -838,15 +863,13 @@ static void tcg_out_qemu_ld(TCGContext *s, const TCGArg *args,
         tcg_out_opc_imm(s, OPC_ANDI, data_reg1, TCG_REG_V0, 0xff);
         break;
     case 0 | 4:
-        tcg_out_opc_sa(s, OPC_SLL, TCG_REG_V0, TCG_REG_V0, 24);
-        tcg_out_opc_sa(s, OPC_SRA, data_reg1, TCG_REG_V0, 24);
+        tcg_out_ext8s(s, data_reg1, TCG_REG_V0);
         break;
     case 1:
         tcg_out_opc_imm(s, OPC_ANDI, data_reg1, TCG_REG_V0, 0xffff);
         break;
     case 1 | 4:
-        tcg_out_opc_sa(s, OPC_SLL, TCG_REG_V0, TCG_REG_V0, 16);
-        tcg_out_opc_sa(s, OPC_SRA, data_reg1, TCG_REG_V0, 16);
+        tcg_out_ext16s(s, data_reg1, TCG_REG_V0);
         break;
     case 2:
         tcg_out_mov(s, data_reg1, TCG_REG_V0);
@@ -1149,7 +1172,7 @@ static inline void tcg_out_op(TCGContext *s, TCGOpcode opc,
         break;
 
     case INDEX_op_ld8u_i32:
-       tcg_out_ldst(s, OPC_LBU, args[0], args[1], args[2]);
+        tcg_out_ldst(s, OPC_LBU, args[0], args[1], args[2]);
         break;
     case INDEX_op_ld8s_i32:
         tcg_out_ldst(s, OPC_LB, args[0], args[1], args[2]);
@@ -1293,6 +1316,13 @@ static inline void tcg_out_op(TCGContext *s, TCGOpcode opc,
         }
         break;
 
+    case INDEX_op_ext8s_i32:
+        tcg_out_ext8s(s, args[0], args[1]);
+        break;
+    case INDEX_op_ext16s_i32:
+        tcg_out_ext16s(s, args[0], args[1]);
+        break;
+
     case INDEX_op_brcond_i32:
         tcg_out_brcond(s, args[2], args[0], args[1], args[3]);
         break;
@@ -1380,6 +1410,9 @@ static const TCGTargetOpDef mips_op_defs[] = {
     { INDEX_op_shr_i32, { "r", "rZ", "riZ" } },
     { INDEX_op_sar_i32, { "r", "rZ", "riZ" } },
 
+    { INDEX_op_ext8s_i32, { "r", "rZ" } },
+    { INDEX_op_ext16s_i32, { "r", "rZ" } },
+
     { INDEX_op_brcond_i32, { "rZ", "rZ" } },
     { INDEX_op_setcond_i32, { "r", "rZ", "rZ" } },
     { INDEX_op_setcond2_i32, { "r", "rZ", "rZ", "rZ", "rZ" } },
index 172577a71e9c6064e7ed674200a6f84c5e14bbe9..0292d3360d1762f2fff94b84e8f54a00f289ed1e 100644 (file)
@@ -82,8 +82,8 @@ enum {
 #define TCG_TARGET_HAS_not_i32
 #define TCG_TARGET_HAS_nor_i32
 #undef TCG_TARGET_HAS_rot_i32
-#undef TCG_TARGET_HAS_ext8s_i32
-#undef TCG_TARGET_HAS_ext16s_i32
+#define TCG_TARGET_HAS_ext8s_i32
+#define TCG_TARGET_HAS_ext16s_i32
 #undef TCG_TARGET_HAS_bswap32_i32
 #undef TCG_TARGET_HAS_bswap16_i32
 #undef TCG_TARGET_HAS_andc_i32