Commit 57951c27422fc41586a5d4032e05bb300cced78d

Authored by aurel32
1 parent 970d622e

target-ppc: convert most SPE integer instructions to TCG

Signed-off-by: Aurelien Jarno <aurelien@aurel32.net>

git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@5668 c046a42c-6fe2-441c-8c8c-71466251a162
target-ppc/cpu.h
... ... @@ -832,10 +832,14 @@ static inline void cpu_clone_regs(CPUState *env, target_ulong newsp)
832 832  
833 833 /*****************************************************************************/
834 834 /* CRF definitions */
835   -#define CRF_LT 3
836   -#define CRF_GT 2
837   -#define CRF_EQ 1
838   -#define CRF_SO 0
  835 +#define CRF_LT 3
  836 +#define CRF_GT 2
  837 +#define CRF_EQ 1
  838 +#define CRF_SO 0
  839 +#define CRF_CH (1 << 4)
  840 +#define CRF_CL (1 << 3)
  841 +#define CRF_CH_OR_CL (1 << 2)
  842 +#define CRF_CH_AND_CL (1 << 1)
839 843  
840 844 /* XER definitions */
841 845 #define XER_SO 31
... ...
target-ppc/helper.h
... ... @@ -23,3 +23,6 @@ DEF_HELPER(target_ulong, helper_popcntb_64, (target_ulong val))
23 23 DEF_HELPER(target_ulong, helper_srad, (target_ulong, target_ulong))
24 24 #endif
25 25  
  26 +DEF_HELPER(uint32_t, helper_cntlsw32, (uint32_t))
  27 +DEF_HELPER(uint32_t, helper_cntlzw32, (uint32_t))
  28 +DEF_HELPER(uint32_t, helper_brinc, (uint32_t, uint32_t))
... ...
target-ppc/op.c
... ... @@ -1227,22 +1227,6 @@ void OPPROTO op_splatw_T1_64 (void)
1227 1227 RETURN();
1228 1228 }
1229 1229  
1230   -void OPPROTO op_splatwi_T0_64 (void)
1231   -{
1232   - uint64_t tmp = PARAM1;
1233   -
1234   - T0_64 = (tmp << 32) | tmp;
1235   - RETURN();
1236   -}
1237   -
1238   -void OPPROTO op_splatwi_T1_64 (void)
1239   -{
1240   - uint64_t tmp = PARAM1;
1241   -
1242   - T1_64 = (tmp << 32) | tmp;
1243   - RETURN();
1244   -}
1245   -
1246 1230 void OPPROTO op_extsh_T1_64 (void)
1247 1231 {
1248 1232 T1_64 = (int32_t)((int16_t)T1_64);
... ... @@ -1267,152 +1251,6 @@ void OPPROTO op_srli32_T1_64 (void)
1267 1251 RETURN();
1268 1252 }
1269 1253  
1270   -void OPPROTO op_evsel (void)
1271   -{
1272   - do_evsel();
1273   - RETURN();
1274   -}
1275   -
1276   -void OPPROTO op_evaddw (void)
1277   -{
1278   - do_evaddw();
1279   - RETURN();
1280   -}
1281   -
1282   -void OPPROTO op_evsubfw (void)
1283   -{
1284   - do_evsubfw();
1285   - RETURN();
1286   -}
1287   -
1288   -void OPPROTO op_evneg (void)
1289   -{
1290   - do_evneg();
1291   - RETURN();
1292   -}
1293   -
1294   -void OPPROTO op_evabs (void)
1295   -{
1296   - do_evabs();
1297   - RETURN();
1298   -}
1299   -
1300   -void OPPROTO op_evextsh (void)
1301   -{
1302   - T0_64 = ((uint64_t)((int32_t)(int16_t)(T0_64 >> 32)) << 32) |
1303   - (uint64_t)((int32_t)(int16_t)T0_64);
1304   - RETURN();
1305   -}
1306   -
1307   -void OPPROTO op_evextsb (void)
1308   -{
1309   - T0_64 = ((uint64_t)((int32_t)(int8_t)(T0_64 >> 32)) << 32) |
1310   - (uint64_t)((int32_t)(int8_t)T0_64);
1311   - RETURN();
1312   -}
1313   -
1314   -void OPPROTO op_evcntlzw (void)
1315   -{
1316   - do_evcntlzw();
1317   - RETURN();
1318   -}
1319   -
1320   -void OPPROTO op_evrndw (void)
1321   -{
1322   - do_evrndw();
1323   - RETURN();
1324   -}
1325   -
1326   -void OPPROTO op_brinc (void)
1327   -{
1328   - do_brinc();
1329   - RETURN();
1330   -}
1331   -
1332   -void OPPROTO op_evcntlsw (void)
1333   -{
1334   - do_evcntlsw();
1335   - RETURN();
1336   -}
1337   -
1338   -void OPPROTO op_evsrws (void)
1339   -{
1340   - do_evsrws();
1341   - RETURN();
1342   -}
1343   -
1344   -void OPPROTO op_evsrwu (void)
1345   -{
1346   - do_evsrwu();
1347   - RETURN();
1348   -}
1349   -
1350   -void OPPROTO op_evslw (void)
1351   -{
1352   - do_evslw();
1353   - RETURN();
1354   -}
1355   -
1356   -void OPPROTO op_evrlw (void)
1357   -{
1358   - do_evrlw();
1359   - RETURN();
1360   -}
1361   -
1362   -void OPPROTO op_evmergelo (void)
1363   -{
1364   - T0_64 = (T0_64 << 32) | (T1_64 & 0x00000000FFFFFFFFULL);
1365   - RETURN();
1366   -}
1367   -
1368   -void OPPROTO op_evmergehi (void)
1369   -{
1370   - T0_64 = (T0_64 & 0xFFFFFFFF00000000ULL) | (T1_64 >> 32);
1371   - RETURN();
1372   -}
1373   -
1374   -void OPPROTO op_evmergelohi (void)
1375   -{
1376   - T0_64 = (T0_64 << 32) | (T1_64 >> 32);
1377   - RETURN();
1378   -}
1379   -
1380   -void OPPROTO op_evmergehilo (void)
1381   -{
1382   - T0_64 = (T0_64 & 0xFFFFFFFF00000000ULL) | (T1_64 & 0x00000000FFFFFFFFULL);
1383   - RETURN();
1384   -}
1385   -
1386   -void OPPROTO op_evcmpgts (void)
1387   -{
1388   - do_evcmpgts();
1389   - RETURN();
1390   -}
1391   -
1392   -void OPPROTO op_evcmpgtu (void)
1393   -{
1394   - do_evcmpgtu();
1395   - RETURN();
1396   -}
1397   -
1398   -void OPPROTO op_evcmplts (void)
1399   -{
1400   - do_evcmplts();
1401   - RETURN();
1402   -}
1403   -
1404   -void OPPROTO op_evcmpltu (void)
1405   -{
1406   - do_evcmpltu();
1407   - RETURN();
1408   -}
1409   -
1410   -void OPPROTO op_evcmpeq (void)
1411   -{
1412   - do_evcmpeq();
1413   - RETURN();
1414   -}
1415   -
1416 1254 void OPPROTO op_evfssub (void)
1417 1255 {
1418 1256 do_evfssub();
... ...
target-ppc/op_helper.c
... ... @@ -1624,46 +1624,18 @@ static always_inline uint32_t word_reverse (uint32_t val)
1624 1624 }
1625 1625  
1626 1626 #define MASKBITS 16 // Random value - to be fixed (implementation dependant)
1627   -void do_brinc (void)
  1627 +target_ulong helper_brinc (target_ulong arg1, target_ulong arg2)
1628 1628 {
1629 1629 uint32_t a, b, d, mask;
1630 1630  
1631 1631 mask = UINT32_MAX >> (32 - MASKBITS);
1632   - a = T0 & mask;
1633   - b = T1 & mask;
  1632 + a = arg1 & mask;
  1633 + b = arg2 & mask;
1634 1634 d = word_reverse(1 + word_reverse(a | ~b));
1635   - T0 = (T0 & ~mask) | (d & b);
  1635 + return (arg1 & ~mask) | (d & b);
1636 1636 }
1637 1637  
1638   -#define DO_SPE_OP2(name) \
1639   -void do_ev##name (void) \
1640   -{ \
1641   - T0_64 = ((uint64_t)_do_e##name(T0_64 >> 32, T1_64 >> 32) << 32) | \
1642   - (uint64_t)_do_e##name(T0_64, T1_64); \
1643   -}
1644   -
1645   -#define DO_SPE_OP1(name) \
1646   -void do_ev##name (void) \
1647   -{ \
1648   - T0_64 = ((uint64_t)_do_e##name(T0_64 >> 32) << 32) | \
1649   - (uint64_t)_do_e##name(T0_64); \
1650   -}
1651   -
1652   -/* Fixed-point vector arithmetic */
1653   -static always_inline uint32_t _do_eabs (uint32_t val)
1654   -{
1655   - if ((val & 0x80000000) && val != 0x80000000)
1656   - val -= val;
1657   -
1658   - return val;
1659   -}
1660   -
1661   -static always_inline uint32_t _do_eaddw (uint32_t op1, uint32_t op2)
1662   -{
1663   - return op1 + op2;
1664   -}
1665   -
1666   -static always_inline int _do_ecntlsw (uint32_t val)
  1638 +uint32_t helper_cntlsw32 (uint32_t val)
1667 1639 {
1668 1640 if (val & 0x80000000)
1669 1641 return clz32(~val);
... ... @@ -1671,88 +1643,23 @@ static always_inline int _do_ecntlsw (uint32_t val)
1671 1643 return clz32(val);
1672 1644 }
1673 1645  
1674   -static always_inline int _do_ecntlzw (uint32_t val)
  1646 +uint32_t helper_cntlzw32 (uint32_t val)
1675 1647 {
1676 1648 return clz32(val);
1677 1649 }
1678 1650  
1679   -static always_inline uint32_t _do_eneg (uint32_t val)
1680   -{
1681   - if (val != 0x80000000)
1682   - val -= val;
1683   -
1684   - return val;
1685   -}
1686   -
1687   -static always_inline uint32_t _do_erlw (uint32_t op1, uint32_t op2)
1688   -{
1689   - return rotl32(op1, op2);
1690   -}
1691   -
1692   -static always_inline uint32_t _do_erndw (uint32_t val)
1693   -{
1694   - return (val + 0x000080000000) & 0xFFFF0000;
1695   -}
1696   -
1697   -static always_inline uint32_t _do_eslw (uint32_t op1, uint32_t op2)
1698   -{
1699   - /* No error here: 6 bits are used */
1700   - return op1 << (op2 & 0x3F);
1701   -}
1702   -
1703   -static always_inline int32_t _do_esrws (int32_t op1, uint32_t op2)
1704   -{
1705   - /* No error here: 6 bits are used */
1706   - return op1 >> (op2 & 0x3F);
1707   -}
1708   -
1709   -static always_inline uint32_t _do_esrwu (uint32_t op1, uint32_t op2)
1710   -{
1711   - /* No error here: 6 bits are used */
1712   - return op1 >> (op2 & 0x3F);
1713   -}
1714   -
1715   -static always_inline uint32_t _do_esubfw (uint32_t op1, uint32_t op2)
1716   -{
1717   - return op2 - op1;
1718   -}
1719   -
1720   -/* evabs */
1721   -DO_SPE_OP1(abs);
1722   -/* evaddw */
1723   -DO_SPE_OP2(addw);
1724   -/* evcntlsw */
1725   -DO_SPE_OP1(cntlsw);
1726   -/* evcntlzw */
1727   -DO_SPE_OP1(cntlzw);
1728   -/* evneg */
1729   -DO_SPE_OP1(neg);
1730   -/* evrlw */
1731   -DO_SPE_OP2(rlw);
1732   -/* evrnd */
1733   -DO_SPE_OP1(rndw);
1734   -/* evslw */
1735   -DO_SPE_OP2(slw);
1736   -/* evsrws */
1737   -DO_SPE_OP2(srws);
1738   -/* evsrwu */
1739   -DO_SPE_OP2(srwu);
1740   -/* evsubfw */
1741   -DO_SPE_OP2(subfw);
1742   -
1743   -/* evsel is a little bit more complicated... */
1744   -static always_inline uint32_t _do_esel (uint32_t op1, uint32_t op2, int n)
1745   -{
1746   - if (n)
1747   - return op1;
1748   - else
1749   - return op2;
  1651 +#define DO_SPE_OP1(name) \
  1652 +void do_ev##name (void) \
  1653 +{ \
  1654 + T0_64 = ((uint64_t)_do_e##name(T0_64 >> 32) << 32) | \
  1655 + (uint64_t)_do_e##name(T0_64); \
1750 1656 }
1751 1657  
1752   -void do_evsel (void)
1753   -{
1754   - T0_64 = ((uint64_t)_do_esel(T0_64 >> 32, T1_64 >> 32, T0 >> 3) << 32) |
1755   - (uint64_t)_do_esel(T0_64, T1_64, (T0 >> 2) & 1);
  1658 +#define DO_SPE_OP2(name) \
  1659 +void do_ev##name (void) \
  1660 +{ \
  1661 + T0_64 = ((uint64_t)_do_e##name(T0_64 >> 32, T1_64 >> 32) << 32) | \
  1662 + (uint64_t)_do_e##name(T0_64, T1_64); \
1756 1663 }
1757 1664  
1758 1665 /* Fixed-point vector comparisons */
... ... @@ -1768,41 +1675,6 @@ static always_inline uint32_t _do_evcmp_merge (int t0, int t1)
1768 1675 {
1769 1676 return (t0 << 3) | (t1 << 2) | ((t0 | t1) << 1) | (t0 & t1);
1770 1677 }
1771   -static always_inline int _do_ecmpeq (uint32_t op1, uint32_t op2)
1772   -{
1773   - return op1 == op2 ? 1 : 0;
1774   -}
1775   -
1776   -static always_inline int _do_ecmpgts (int32_t op1, int32_t op2)
1777   -{
1778   - return op1 > op2 ? 1 : 0;
1779   -}
1780   -
1781   -static always_inline int _do_ecmpgtu (uint32_t op1, uint32_t op2)
1782   -{
1783   - return op1 > op2 ? 1 : 0;
1784   -}
1785   -
1786   -static always_inline int _do_ecmplts (int32_t op1, int32_t op2)
1787   -{
1788   - return op1 < op2 ? 1 : 0;
1789   -}
1790   -
1791   -static always_inline int _do_ecmpltu (uint32_t op1, uint32_t op2)
1792   -{
1793   - return op1 < op2 ? 1 : 0;
1794   -}
1795   -
1796   -/* evcmpeq */
1797   -DO_SPE_CMP(cmpeq);
1798   -/* evcmpgts */
1799   -DO_SPE_CMP(cmpgts);
1800   -/* evcmpgtu */
1801   -DO_SPE_CMP(cmpgtu);
1802   -/* evcmplts */
1803   -DO_SPE_CMP(cmplts);
1804   -/* evcmpltu */
1805   -DO_SPE_CMP(cmpltu);
1806 1678  
1807 1679 /* Single precision floating-point conversions from/to integer */
1808 1680 static always_inline uint32_t _do_efscfsi (int32_t val)
... ...
target-ppc/translate.c
... ... @@ -6023,158 +6023,564 @@ GEN_SPE_STX(name)
6023 6023 GEN_SPEOP_LD(name, sh); \
6024 6024 GEN_SPEOP_ST(name, sh)
6025 6025  
6026   -/* SPE arithmetic and logic */
6027   -#define GEN_SPEOP_ARITH2(name) \
  6026 +/* SPE logic */
  6027 +#if defined(TARGET_PPC64)
  6028 +#define GEN_SPEOP_LOGIC2(name, tcg_op) \
6028 6029 static always_inline void gen_##name (DisasContext *ctx) \
6029 6030 { \
6030 6031 if (unlikely(!ctx->spe_enabled)) { \
6031 6032 GEN_EXCP_NO_AP(ctx); \
6032 6033 return; \
6033 6034 } \
6034   - gen_load_gpr64(cpu_T64[0], rA(ctx->opcode)); \
6035   - gen_load_gpr64(cpu_T64[1], rB(ctx->opcode)); \
6036   - gen_op_##name(); \
6037   - gen_store_gpr64(rD(ctx->opcode), cpu_T64[0]); \
  6035 + tcg_op(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rA(ctx->opcode)], \
  6036 + cpu_gpr[rB(ctx->opcode)]); \
  6037 +}
  6038 +#else
  6039 +#define GEN_SPEOP_LOGIC2(name, tcg_op) \
  6040 +static always_inline void gen_##name (DisasContext *ctx) \
  6041 +{ \
  6042 + if (unlikely(!ctx->spe_enabled)) { \
  6043 + GEN_EXCP_NO_AP(ctx); \
  6044 + return; \
  6045 + } \
  6046 + tcg_op(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rA(ctx->opcode)], \
  6047 + cpu_gpr[rB(ctx->opcode)]); \
  6048 + tcg_op(cpu_gprh[rD(ctx->opcode)], cpu_gprh[rA(ctx->opcode)], \
  6049 + cpu_gprh[rB(ctx->opcode)]); \
6038 6050 }
  6051 +#endif
  6052 +
  6053 +GEN_SPEOP_LOGIC2(evand, tcg_gen_and_tl);
  6054 +GEN_SPEOP_LOGIC2(evandc, tcg_gen_andc_tl);
  6055 +GEN_SPEOP_LOGIC2(evxor, tcg_gen_xor_tl);
  6056 +GEN_SPEOP_LOGIC2(evor, tcg_gen_or_tl);
  6057 +GEN_SPEOP_LOGIC2(evnor, tcg_gen_nor_tl);
  6058 +GEN_SPEOP_LOGIC2(eveqv, tcg_gen_eqv_tl);
  6059 +GEN_SPEOP_LOGIC2(evorc, tcg_gen_orc_tl);
  6060 +GEN_SPEOP_LOGIC2(evnand, tcg_gen_nand_tl);
6039 6061  
6040   -#define GEN_SPEOP_TCG_ARITH2(name, tcg_op) \
  6062 +/* SPE logic immediate */
  6063 +#if defined(TARGET_PPC64)
  6064 +#define GEN_SPEOP_TCG_LOGIC_IMM2(name, tcg_opi) \
6041 6065 static always_inline void gen_##name (DisasContext *ctx) \
6042 6066 { \
6043 6067 if (unlikely(!ctx->spe_enabled)) { \
6044 6068 GEN_EXCP_NO_AP(ctx); \
6045 6069 return; \
6046 6070 } \
6047   - TCGv t0 = tcg_temp_new(TCG_TYPE_I64); \
6048   - TCGv t1 = tcg_temp_new(TCG_TYPE_I64); \
6049   - gen_load_gpr64(t0, rA(ctx->opcode)); \
6050   - gen_load_gpr64(t1, rB(ctx->opcode)); \
6051   - tcg_op(t0, t0, t1); \
6052   - gen_store_gpr64(rD(ctx->opcode), t0); \
  6071 + TCGv t0 = tcg_temp_local_new(TCG_TYPE_I32); \
  6072 + TCGv t1 = tcg_temp_local_new(TCG_TYPE_I32); \
  6073 + TCGv t2 = tcg_temp_local_new(TCG_TYPE_I64); \
  6074 + tcg_gen_trunc_i64_i32(t0, cpu_gpr[rA(ctx->opcode)]); \
  6075 + tcg_opi(t0, t0, rB(ctx->opcode)); \
  6076 + tcg_gen_shri_i64(t2, cpu_gpr[rA(ctx->opcode)], 32); \
  6077 + tcg_gen_trunc_i64_i32(t1, t2); \
  6078 + tcg_temp_free(t2); \
  6079 + tcg_opi(t1, t1, rB(ctx->opcode)); \
  6080 + tcg_gen_concat_i32_i64(cpu_gpr[rD(ctx->opcode)], t0, t1); \
6053 6081 tcg_temp_free(t0); \
6054 6082 tcg_temp_free(t1); \
6055 6083 }
6056   -
6057   -#define GEN_SPEOP_ARITH1(name) \
  6084 +#else
  6085 +#define GEN_SPEOP_TCG_LOGIC_IMM2(name, tcg_opi) \
6058 6086 static always_inline void gen_##name (DisasContext *ctx) \
6059 6087 { \
6060 6088 if (unlikely(!ctx->spe_enabled)) { \
6061 6089 GEN_EXCP_NO_AP(ctx); \
6062 6090 return; \
6063 6091 } \
6064   - gen_load_gpr64(cpu_T64[0], rA(ctx->opcode)); \
6065   - gen_op_##name(); \
6066   - gen_store_gpr64(rD(ctx->opcode), cpu_T64[0]); \
  6092 + tcg_opi(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rA(ctx->opcode)], \
  6093 + rB(ctx->opcode)); \
  6094 + tcg_opi(cpu_gprh[rD(ctx->opcode)], cpu_gprh[rA(ctx->opcode)], \
  6095 + rB(ctx->opcode)); \
6067 6096 }
  6097 +#endif
  6098 +GEN_SPEOP_TCG_LOGIC_IMM2(evslwi, tcg_gen_shli_i32);
  6099 +GEN_SPEOP_TCG_LOGIC_IMM2(evsrwiu, tcg_gen_shri_i32);
  6100 +GEN_SPEOP_TCG_LOGIC_IMM2(evsrwis, tcg_gen_sari_i32);
  6101 +GEN_SPEOP_TCG_LOGIC_IMM2(evrlwi, tcg_gen_rotli_i32);
6068 6102  
6069   -#define GEN_SPEOP_COMP(name) \
  6103 +/* SPE arithmetic */
  6104 +#if defined(TARGET_PPC64)
  6105 +#define GEN_SPEOP_ARITH1(name, tcg_op) \
6070 6106 static always_inline void gen_##name (DisasContext *ctx) \
6071 6107 { \
6072 6108 if (unlikely(!ctx->spe_enabled)) { \
6073 6109 GEN_EXCP_NO_AP(ctx); \
6074 6110 return; \
6075 6111 } \
6076   - gen_load_gpr64(cpu_T64[0], rA(ctx->opcode)); \
6077   - gen_load_gpr64(cpu_T64[1], rB(ctx->opcode)); \
6078   - gen_op_##name(); \
6079   - tcg_gen_andi_i32(cpu_crf[crfD(ctx->opcode)], cpu_T[0], 0xf); \
  6112 + TCGv t0 = tcg_temp_local_new(TCG_TYPE_I32); \
  6113 + TCGv t1 = tcg_temp_local_new(TCG_TYPE_I32); \
  6114 + TCGv t2 = tcg_temp_local_new(TCG_TYPE_I64); \
  6115 + tcg_gen_trunc_i64_i32(t0, cpu_gpr[rA(ctx->opcode)]); \
  6116 + tcg_op(t0, t0); \
  6117 + tcg_gen_shri_i64(t2, cpu_gpr[rA(ctx->opcode)], 32); \
  6118 + tcg_gen_trunc_i64_i32(t1, t2); \
  6119 + tcg_temp_free(t2); \
  6120 + tcg_op(t1, t1); \
  6121 + tcg_gen_concat_i32_i64(cpu_gpr[rD(ctx->opcode)], t0, t1); \
  6122 + tcg_temp_free(t0); \
  6123 + tcg_temp_free(t1); \
6080 6124 }
  6125 +#else
  6126 +#define GEN_SPEOP_ARITH1(name, tcg_op) \
  6127 +static always_inline void gen_##name (DisasContext *ctx) \
  6128 +{ \
  6129 + if (unlikely(!ctx->spe_enabled)) { \
  6130 + GEN_EXCP_NO_AP(ctx); \
  6131 + return; \
  6132 + } \
  6133 + tcg_op(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rA(ctx->opcode)]); \
  6134 + tcg_op(cpu_gprh[rD(ctx->opcode)], cpu_gprh[rA(ctx->opcode)]); \
  6135 +}
  6136 +#endif
6081 6137  
6082   -/* Logical */
6083   -GEN_SPEOP_TCG_ARITH2(evand, tcg_gen_and_i64);
6084   -GEN_SPEOP_TCG_ARITH2(evandc, tcg_gen_andc_i64);
6085   -GEN_SPEOP_TCG_ARITH2(evxor, tcg_gen_xor_i64);
6086   -GEN_SPEOP_TCG_ARITH2(evor, tcg_gen_or_i64);
6087   -GEN_SPEOP_TCG_ARITH2(evnor, tcg_gen_nor_i64);
6088   -GEN_SPEOP_TCG_ARITH2(eveqv, tcg_gen_eqv_i64);
6089   -GEN_SPEOP_TCG_ARITH2(evorc, tcg_gen_orc_i64);
6090   -GEN_SPEOP_TCG_ARITH2(evnand, tcg_gen_nand_i64);
6091   -GEN_SPEOP_ARITH2(evsrwu);
6092   -GEN_SPEOP_ARITH2(evsrws);
6093   -GEN_SPEOP_ARITH2(evslw);
6094   -GEN_SPEOP_ARITH2(evrlw);
6095   -GEN_SPEOP_ARITH2(evmergehi);
6096   -GEN_SPEOP_ARITH2(evmergelo);
6097   -GEN_SPEOP_ARITH2(evmergehilo);
6098   -GEN_SPEOP_ARITH2(evmergelohi);
  6138 +static always_inline void gen_op_evabs (TCGv ret, TCGv arg1)
  6139 +{
  6140 + int l1 = gen_new_label();
  6141 + int l2 = gen_new_label();
6099 6142  
6100   -/* Arithmetic */
6101   -GEN_SPEOP_ARITH2(evaddw);
6102   -GEN_SPEOP_ARITH2(evsubfw);
6103   -GEN_SPEOP_ARITH1(evabs);
6104   -GEN_SPEOP_ARITH1(evneg);
6105   -GEN_SPEOP_ARITH1(evextsb);
6106   -GEN_SPEOP_ARITH1(evextsh);
6107   -GEN_SPEOP_ARITH1(evrndw);
6108   -GEN_SPEOP_ARITH1(evcntlzw);
6109   -GEN_SPEOP_ARITH1(evcntlsw);
6110   -static always_inline void gen_brinc (DisasContext *ctx)
  6143 + tcg_gen_brcondi_i32(TCG_COND_GE, arg1, 0, l1);
  6144 + tcg_gen_neg_i32(ret, arg1);
  6145 + tcg_gen_br(l2);
  6146 + gen_set_label(l1);
  6147 + tcg_gen_mov_tl(ret, arg1);
  6148 + gen_set_label(l2);
  6149 +}
  6150 +GEN_SPEOP_ARITH1(evabs, gen_op_evabs);
  6151 +GEN_SPEOP_ARITH1(evneg, tcg_gen_neg_i32);
  6152 +GEN_SPEOP_ARITH1(evextsb, tcg_gen_ext8s_i32);
  6153 +GEN_SPEOP_ARITH1(evextsh, tcg_gen_ext16s_i32);
  6154 +static always_inline void gen_op_evrndw (TCGv ret, TCGv arg1)
6111 6155 {
6112   - /* Note: brinc is usable even if SPE is disabled */
6113   - tcg_gen_mov_tl(cpu_T[0], cpu_gpr[rA(ctx->opcode)]);
6114   - tcg_gen_mov_tl(cpu_T[1], cpu_gpr[rB(ctx->opcode)]);
6115   - gen_op_brinc();
6116   - tcg_gen_mov_tl(cpu_gpr[rD(ctx->opcode)], cpu_T[0]);
  6156 + tcg_gen_addi_i32(ret, arg1, 0x8000);
  6157 + tcg_gen_ext16u_i32(ret, ret);
  6158 +}
  6159 +GEN_SPEOP_ARITH1(evrndw, gen_op_evrndw);
  6160 +static always_inline void gen_op_cntlsw (TCGv ret, TCGv arg1)
  6161 +{
  6162 + tcg_gen_helper_1_1(helper_cntlsw32, ret, arg1);
  6163 +}
  6164 +GEN_SPEOP_ARITH1(evcntlsw, gen_op_cntlsw);
  6165 +static always_inline void gen_op_cntlzw (TCGv ret, TCGv arg1)
  6166 +{
  6167 + tcg_gen_helper_1_1(helper_cntlzw32, ret, arg1);
6117 6168 }
  6169 +GEN_SPEOP_ARITH1(evcntlzw, gen_op_cntlzw);
6118 6170  
6119   -#define GEN_SPEOP_ARITH_IMM2(name) \
6120   -static always_inline void gen_##name##i (DisasContext *ctx) \
  6171 +#if defined(TARGET_PPC64)
  6172 +#define GEN_SPEOP_ARITH2(name, tcg_op) \
  6173 +static always_inline void gen_##name (DisasContext *ctx) \
6121 6174 { \
6122 6175 if (unlikely(!ctx->spe_enabled)) { \
6123 6176 GEN_EXCP_NO_AP(ctx); \
6124 6177 return; \
6125 6178 } \
6126   - gen_load_gpr64(cpu_T64[0], rB(ctx->opcode)); \
6127   - gen_op_splatwi_T1_64(rA(ctx->opcode)); \
6128   - gen_op_##name(); \
6129   - gen_store_gpr64(rD(ctx->opcode), cpu_T64[0]); \
  6179 + TCGv t0 = tcg_temp_local_new(TCG_TYPE_I32); \
  6180 + TCGv t1 = tcg_temp_local_new(TCG_TYPE_I32); \
  6181 + TCGv t2 = tcg_temp_local_new(TCG_TYPE_I32); \
  6182 + TCGv t3 = tcg_temp_local_new(TCG_TYPE_I64); \
  6183 + tcg_gen_trunc_i64_i32(t0, cpu_gpr[rA(ctx->opcode)]); \
  6184 + tcg_gen_trunc_i64_i32(t2, cpu_gpr[rB(ctx->opcode)]); \
  6185 + tcg_op(t0, t0, t2); \
  6186 + tcg_gen_shri_i64(t3, cpu_gpr[rA(ctx->opcode)], 32); \
  6187 + tcg_gen_trunc_i64_i32(t1, t3); \
  6188 + tcg_gen_shri_i64(t3, cpu_gpr[rB(ctx->opcode)], 32); \
  6189 + tcg_gen_trunc_i64_i32(t2, t3); \
  6190 + tcg_temp_free(t3); \
  6191 + tcg_op(t1, t1, t2); \
  6192 + tcg_temp_free(t2); \
  6193 + tcg_gen_concat_i32_i64(cpu_gpr[rD(ctx->opcode)], t0, t1); \
  6194 + tcg_temp_free(t0); \
  6195 + tcg_temp_free(t1); \
6130 6196 }
6131   -
6132   -#define GEN_SPEOP_LOGIC_IMM2(name) \
6133   -static always_inline void gen_##name##i (DisasContext *ctx) \
  6197 +#else
  6198 +#define GEN_SPEOP_ARITH2(name, tcg_op) \
  6199 +static always_inline void gen_##name (DisasContext *ctx) \
6134 6200 { \
6135 6201 if (unlikely(!ctx->spe_enabled)) { \
6136 6202 GEN_EXCP_NO_AP(ctx); \
6137 6203 return; \
6138 6204 } \
6139   - gen_load_gpr64(cpu_T64[0], rA(ctx->opcode)); \
6140   - gen_op_splatwi_T1_64(rB(ctx->opcode)); \
6141   - gen_op_##name(); \
6142   - gen_store_gpr64(rD(ctx->opcode), cpu_T64[0]); \
  6205 + tcg_op(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rA(ctx->opcode)], \
  6206 + cpu_gpr[rB(ctx->opcode)]); \
  6207 + tcg_op(cpu_gprh[rD(ctx->opcode)], cpu_gprh[rA(ctx->opcode)], \
  6208 + cpu_gprh[rB(ctx->opcode)]); \
6143 6209 }
  6210 +#endif
6144 6211  
6145   -GEN_SPEOP_ARITH_IMM2(evaddw);
6146   -#define gen_evaddiw gen_evaddwi
6147   -GEN_SPEOP_ARITH_IMM2(evsubfw);
6148   -#define gen_evsubifw gen_evsubfwi
6149   -GEN_SPEOP_LOGIC_IMM2(evslw);
6150   -GEN_SPEOP_LOGIC_IMM2(evsrwu);
6151   -#define gen_evsrwis gen_evsrwsi
6152   -GEN_SPEOP_LOGIC_IMM2(evsrws);
6153   -#define gen_evsrwiu gen_evsrwui
6154   -GEN_SPEOP_LOGIC_IMM2(evrlw);
  6212 +static always_inline void gen_op_evsrwu (TCGv ret, TCGv arg1, TCGv arg2)
  6213 +{
  6214 + TCGv t0;
  6215 + int l1, l2;
6155 6216  
6156   -static always_inline void gen_evsplati (DisasContext *ctx)
  6217 + l1 = gen_new_label();
  6218 + l2 = gen_new_label();
  6219 + t0 = tcg_temp_local_new(TCG_TYPE_I32);
  6220 + /* No error here: 6 bits are used */
  6221 + tcg_gen_andi_i32(t0, arg2, 0x3F);
  6222 + tcg_gen_brcondi_i32(TCG_COND_GE, t0, 32, l1);
  6223 + tcg_gen_shr_i32(ret, arg1, t0);
  6224 + tcg_gen_br(l2);
  6225 + gen_set_label(l1);
  6226 + tcg_gen_movi_i32(ret, 0);
  6227 + tcg_gen_br(l2);
  6228 + tcg_temp_free(t0);
  6229 +}
  6230 +GEN_SPEOP_ARITH2(evsrwu, gen_op_evsrwu);
  6231 +static always_inline void gen_op_evsrws (TCGv ret, TCGv arg1, TCGv arg2)
  6232 +{
  6233 + TCGv t0;
  6234 + int l1, l2;
  6235 +
  6236 + l1 = gen_new_label();
  6237 + l2 = gen_new_label();
  6238 + t0 = tcg_temp_local_new(TCG_TYPE_I32);
  6239 + /* No error here: 6 bits are used */
  6240 + tcg_gen_andi_i32(t0, arg2, 0x3F);
  6241 + tcg_gen_brcondi_i32(TCG_COND_GE, t0, 32, l1);
  6242 + tcg_gen_sar_i32(ret, arg1, t0);
  6243 + tcg_gen_br(l2);
  6244 + gen_set_label(l1);
  6245 + tcg_gen_movi_i32(ret, 0);
  6246 + tcg_gen_br(l2);
  6247 + tcg_temp_free(t0);
  6248 +}
  6249 +GEN_SPEOP_ARITH2(evsrws, gen_op_evsrws);
  6250 +static always_inline void gen_op_evslw (TCGv ret, TCGv arg1, TCGv arg2)
  6251 +{
  6252 + TCGv t0;
  6253 + int l1, l2;
  6254 +
  6255 + l1 = gen_new_label();
  6256 + l2 = gen_new_label();
  6257 + t0 = tcg_temp_local_new(TCG_TYPE_I32);
  6258 + /* No error here: 6 bits are used */
  6259 + tcg_gen_andi_i32(t0, arg2, 0x3F);
  6260 + tcg_gen_brcondi_i32(TCG_COND_GE, t0, 32, l1);
  6261 + tcg_gen_shl_i32(ret, arg1, t0);
  6262 + tcg_gen_br(l2);
  6263 + gen_set_label(l1);
  6264 + tcg_gen_movi_i32(ret, 0);
  6265 + tcg_gen_br(l2);
  6266 + tcg_temp_free(t0);
  6267 +}
  6268 +GEN_SPEOP_ARITH2(evslw, gen_op_evslw);
  6269 +static always_inline void gen_op_evrlw (TCGv ret, TCGv arg1, TCGv arg2)
  6270 +{
  6271 + TCGv t0 = tcg_temp_new(TCG_TYPE_I32);
  6272 + tcg_gen_andi_i32(t0, arg2, 0x1F);
  6273 + tcg_gen_rotl_i32(ret, arg1, t0);
  6274 + tcg_temp_free(t0);
  6275 +}
  6276 +GEN_SPEOP_ARITH2(evrlw, gen_op_evrlw);
  6277 +static always_inline void gen_evmergehi (DisasContext *ctx)
  6278 +{
  6279 + if (unlikely(!ctx->spe_enabled)) {
  6280 + GEN_EXCP_NO_AP(ctx);
  6281 + return;
  6282 + }
  6283 +#if defined(TARGET_PPC64)
  6284 + TCGv t0 = tcg_temp_new(TCG_TYPE_TL);
  6285 + TCGv t1 = tcg_temp_new(TCG_TYPE_TL);
  6286 + tcg_gen_shri_tl(t0, cpu_gpr[rB(ctx->opcode)], 32);
  6287 + tcg_gen_andi_tl(t1, cpu_gpr[rA(ctx->opcode)], 0xFFFFFFFF0000000ULL);
  6288 + tcg_gen_or_tl(cpu_gpr[rD(ctx->opcode)], t0, t1);
  6289 + tcg_temp_free(t0);
  6290 + tcg_temp_free(t1);
  6291 +#else
  6292 + tcg_gen_mov_i32(cpu_gpr[rD(ctx->opcode)], cpu_gprh[rB(ctx->opcode)]);
  6293 + tcg_gen_mov_i32(cpu_gprh[rD(ctx->opcode)], cpu_gprh[rA(ctx->opcode)]);
  6294 +#endif
  6295 +}
  6296 +GEN_SPEOP_ARITH2(evaddw, tcg_gen_add_i32);
  6297 +static always_inline void gen_op_evsubf (TCGv ret, TCGv arg1, TCGv arg2)
6157 6298 {
6158   - int32_t imm = (int32_t)(rA(ctx->opcode) << 27) >> 27;
  6299 + tcg_gen_sub_i32(ret, arg2, arg1);
  6300 +}
  6301 +GEN_SPEOP_ARITH2(evsubfw, gen_op_evsubf);
6159 6302  
6160   - gen_op_splatwi_T0_64(imm);
6161   - gen_store_gpr64(rD(ctx->opcode), cpu_T64[0]);
  6303 +/* SPE arithmetic immediate */
  6304 +#if defined(TARGET_PPC64)
  6305 +#define GEN_SPEOP_ARITH_IMM2(name, tcg_op) \
  6306 +static always_inline void gen_##name (DisasContext *ctx) \
  6307 +{ \
  6308 + if (unlikely(!ctx->spe_enabled)) { \
  6309 + GEN_EXCP_NO_AP(ctx); \
  6310 + return; \
  6311 + } \
  6312 + TCGv t0 = tcg_temp_local_new(TCG_TYPE_I32); \
  6313 + TCGv t1 = tcg_temp_local_new(TCG_TYPE_I32); \
  6314 + TCGv t2 = tcg_temp_local_new(TCG_TYPE_I64); \
  6315 + tcg_gen_trunc_i64_i32(t0, cpu_gpr[rB(ctx->opcode)]); \
  6316 + tcg_op(t0, t0, rA(ctx->opcode)); \
  6317 + tcg_gen_shri_i64(t2, cpu_gpr[rB(ctx->opcode)], 32); \
  6318 + tcg_gen_trunc_i64_i32(t1, t2); \
  6319 + tcg_temp_free(t2); \
  6320 + tcg_op(t1, t1, rA(ctx->opcode)); \
  6321 + tcg_gen_concat_i32_i64(cpu_gpr[rD(ctx->opcode)], t0, t1); \
  6322 + tcg_temp_free(t0); \
  6323 + tcg_temp_free(t1); \
  6324 +}
  6325 +#else
  6326 +#define GEN_SPEOP_ARITH_IMM2(name, tcg_op) \
  6327 +static always_inline void gen_##name (DisasContext *ctx) \
  6328 +{ \
  6329 + if (unlikely(!ctx->spe_enabled)) { \
  6330 + GEN_EXCP_NO_AP(ctx); \
  6331 + return; \
  6332 + } \
  6333 + tcg_op(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rB(ctx->opcode)], \
  6334 + rA(ctx->opcode)); \
  6335 + tcg_op(cpu_gprh[rD(ctx->opcode)], cpu_gprh[rB(ctx->opcode)], \
  6336 + rA(ctx->opcode)); \
  6337 +}
  6338 +#endif
  6339 +GEN_SPEOP_ARITH_IMM2(evaddiw, tcg_gen_addi_i32);
  6340 +GEN_SPEOP_ARITH_IMM2(evsubifw, tcg_gen_subi_i32);
  6341 +
  6342 +/* SPE comparison */
  6343 +#if defined(TARGET_PPC64)
  6344 +#define GEN_SPEOP_COMP(name, tcg_cond) \
  6345 +static always_inline void gen_##name (DisasContext *ctx) \
  6346 +{ \
  6347 + if (unlikely(!ctx->spe_enabled)) { \
  6348 + GEN_EXCP_NO_AP(ctx); \
  6349 + return; \
  6350 + } \
  6351 + int l1 = gen_new_label(); \
  6352 + int l2 = gen_new_label(); \
  6353 + int l3 = gen_new_label(); \
  6354 + int l4 = gen_new_label(); \
  6355 + TCGv t0 = tcg_temp_local_new(TCG_TYPE_I32); \
  6356 + TCGv t1 = tcg_temp_local_new(TCG_TYPE_I32); \
  6357 + TCGv t2 = tcg_temp_local_new(TCG_TYPE_I64); \
  6358 + tcg_gen_trunc_i64_i32(t0, cpu_gpr[rA(ctx->opcode)]); \
  6359 + tcg_gen_trunc_i64_i32(t1, cpu_gpr[rB(ctx->opcode)]); \
  6360 + tcg_gen_brcond_i32(tcg_cond, t0, t1, l1); \
  6361 + tcg_gen_movi_tl(cpu_crf[crfD(ctx->opcode)], 0); \
  6362 + tcg_gen_br(l2); \
  6363 + gen_set_label(l1); \
  6364 + tcg_gen_movi_i32(cpu_crf[crfD(ctx->opcode)], \
  6365 + CRF_CL | CRF_CH_OR_CL | CRF_CH_AND_CL); \
  6366 + gen_set_label(l2); \
  6367 + tcg_gen_shri_i64(t2, cpu_gpr[rA(ctx->opcode)], 32); \
  6368 + tcg_gen_trunc_i64_i32(t0, t2); \
  6369 + tcg_gen_shri_i64(t2, cpu_gpr[rB(ctx->opcode)], 32); \
  6370 + tcg_gen_trunc_i64_i32(t1, t2); \
  6371 + tcg_temp_free(t2); \
  6372 + tcg_gen_brcond_i32(tcg_cond, t0, t1, l3); \
  6373 + tcg_gen_andi_i32(cpu_crf[crfD(ctx->opcode)], cpu_crf[crfD(ctx->opcode)], \
  6374 + ~(CRF_CH | CRF_CH_AND_CL)); \
  6375 + tcg_gen_br(l4); \
  6376 + gen_set_label(l3); \
  6377 + tcg_gen_ori_i32(cpu_crf[crfD(ctx->opcode)], cpu_crf[crfD(ctx->opcode)], \
  6378 + CRF_CH | CRF_CH_OR_CL); \
  6379 + gen_set_label(l4); \
  6380 + tcg_temp_free(t0); \
  6381 + tcg_temp_free(t1); \
  6382 +}
  6383 +#else
  6384 +#define GEN_SPEOP_COMP(name, tcg_cond) \
  6385 +static always_inline void gen_##name (DisasContext *ctx) \
  6386 +{ \
  6387 + if (unlikely(!ctx->spe_enabled)) { \
  6388 + GEN_EXCP_NO_AP(ctx); \
  6389 + return; \
  6390 + } \
  6391 + int l1 = gen_new_label(); \
  6392 + int l2 = gen_new_label(); \
  6393 + int l3 = gen_new_label(); \
  6394 + int l4 = gen_new_label(); \
  6395 + \
  6396 + tcg_gen_brcond_i32(tcg_cond, cpu_gpr[rA(ctx->opcode)], \
  6397 + cpu_gpr[rB(ctx->opcode)], l1); \
  6398 + tcg_gen_movi_tl(cpu_crf[crfD(ctx->opcode)], 0); \
  6399 + tcg_gen_br(l2); \
  6400 + gen_set_label(l1); \
  6401 + tcg_gen_movi_i32(cpu_crf[crfD(ctx->opcode)], \
  6402 + CRF_CL | CRF_CH_OR_CL | CRF_CH_AND_CL); \
  6403 + gen_set_label(l2); \
  6404 + tcg_gen_brcond_i32(tcg_cond, cpu_gprh[rA(ctx->opcode)], \
  6405 + cpu_gprh[rB(ctx->opcode)], l3); \
  6406 + tcg_gen_andi_i32(cpu_crf[crfD(ctx->opcode)], cpu_crf[crfD(ctx->opcode)], \
  6407 + ~(CRF_CH | CRF_CH_AND_CL)); \
  6408 + tcg_gen_br(l4); \
  6409 + gen_set_label(l3); \
  6410 + tcg_gen_ori_i32(cpu_crf[crfD(ctx->opcode)], cpu_crf[crfD(ctx->opcode)], \
  6411 + CRF_CH | CRF_CH_OR_CL); \
  6412 + gen_set_label(l4); \
  6413 +}
  6414 +#endif
  6415 +GEN_SPEOP_COMP(evcmpgtu, TCG_COND_GTU);
  6416 +GEN_SPEOP_COMP(evcmpgts, TCG_COND_GT);
  6417 +GEN_SPEOP_COMP(evcmpltu, TCG_COND_LTU);
  6418 +GEN_SPEOP_COMP(evcmplts, TCG_COND_LT);
  6419 +GEN_SPEOP_COMP(evcmpeq, TCG_COND_EQ);
  6420 +
  6421 +/* SPE misc */
  6422 +static always_inline void gen_brinc (DisasContext *ctx)
  6423 +{
  6424 + /* Note: brinc is usable even if SPE is disabled */
  6425 + tcg_gen_helper_1_2(helper_brinc, cpu_gpr[rD(ctx->opcode)],
  6426 + cpu_gpr[rA(ctx->opcode)], cpu_gpr[rB(ctx->opcode)]);
6162 6427 }
  6428 +static always_inline void gen_evmergelo (DisasContext *ctx)
  6429 +{
  6430 + if (unlikely(!ctx->spe_enabled)) {
  6431 + GEN_EXCP_NO_AP(ctx);
  6432 + return;
  6433 + }
  6434 +#if defined(TARGET_PPC64)
  6435 + TCGv t0 = tcg_temp_new(TCG_TYPE_TL);
  6436 + TCGv t1 = tcg_temp_new(TCG_TYPE_TL);
  6437 + tcg_gen_andi_tl(t0, cpu_gpr[rB(ctx->opcode)], 0x00000000FFFFFFFFLL);
  6438 + tcg_gen_shli_tl(t1, cpu_gpr[rA(ctx->opcode)], 32);
  6439 + tcg_gen_or_tl(cpu_gpr[rD(ctx->opcode)], t0, t1);
  6440 + tcg_temp_free(t0);
  6441 + tcg_temp_free(t1);
  6442 +#else
  6443 + tcg_gen_mov_i32(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rB(ctx->opcode)]);
  6444 + tcg_gen_mov_i32(cpu_gprh[rD(ctx->opcode)], cpu_gpr[rA(ctx->opcode)]);
  6445 +#endif
  6446 +}
  6447 +static always_inline void gen_evmergehilo (DisasContext *ctx)
  6448 +{
  6449 + if (unlikely(!ctx->spe_enabled)) {
  6450 + GEN_EXCP_NO_AP(ctx);
  6451 + return;
  6452 + }
  6453 +#if defined(TARGET_PPC64)
  6454 + TCGv t0 = tcg_temp_new(TCG_TYPE_TL);
  6455 + TCGv t1 = tcg_temp_new(TCG_TYPE_TL);
  6456 + tcg_gen_andi_tl(t0, cpu_gpr[rB(ctx->opcode)], 0x00000000FFFFFFFFLL);
  6457 + tcg_gen_andi_tl(t1, cpu_gpr[rA(ctx->opcode)], 0xFFFFFFFF0000000ULL);
  6458 + tcg_gen_or_tl(cpu_gpr[rD(ctx->opcode)], t0, t1);
  6459 + tcg_temp_free(t0);
  6460 + tcg_temp_free(t1);
  6461 +#else
  6462 + tcg_gen_mov_i32(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rB(ctx->opcode)]);
  6463 + tcg_gen_mov_i32(cpu_gprh[rD(ctx->opcode)], cpu_gprh[rA(ctx->opcode)]);
  6464 +#endif
  6465 +}
  6466 +static always_inline void gen_evmergelohi (DisasContext *ctx)
  6467 +{
  6468 + if (unlikely(!ctx->spe_enabled)) {
  6469 + GEN_EXCP_NO_AP(ctx);
  6470 + return;
  6471 + }
  6472 +#if defined(TARGET_PPC64)
  6473 + TCGv t0 = tcg_temp_new(TCG_TYPE_TL);
  6474 + TCGv t1 = tcg_temp_new(TCG_TYPE_TL);
  6475 + tcg_gen_shri_tl(t0, cpu_gpr[rB(ctx->opcode)], 32);
  6476 + tcg_gen_shli_tl(t1, cpu_gpr[rA(ctx->opcode)], 32);
  6477 + tcg_gen_or_tl(cpu_gpr[rD(ctx->opcode)], t0, t1);
  6478 + tcg_temp_free(t0);
  6479 + tcg_temp_free(t1);
  6480 +#else
  6481 + tcg_gen_mov_i32(cpu_gpr[rD(ctx->opcode)], cpu_gprh[rB(ctx->opcode)]);
  6482 + tcg_gen_mov_i32(cpu_gprh[rD(ctx->opcode)], cpu_gpr[rA(ctx->opcode)]);
  6483 +#endif
  6484 +}
  6485 +static always_inline void gen_evsplati (DisasContext *ctx)
  6486 +{
  6487 + int32_t imm = (int32_t)(rA(ctx->opcode) << 11) >> 27;
6163 6488  
  6489 +#if defined(TARGET_PPC64)
  6490 + TCGv t0 = tcg_temp_new(TCG_TYPE_TL);
  6491 + TCGv t1 = tcg_temp_new(TCG_TYPE_TL);
  6492 + tcg_gen_movi_tl(t0, imm);
  6493 + tcg_gen_shri_tl(t1, t0, 32);
  6494 + tcg_gen_or_tl(cpu_gpr[rD(ctx->opcode)], t0, t1);
  6495 + tcg_temp_free(t0);
  6496 + tcg_temp_free(t1);
  6497 +#else
  6498 + tcg_gen_movi_i32(cpu_gpr[rD(ctx->opcode)], imm);
  6499 + tcg_gen_movi_i32(cpu_gprh[rD(ctx->opcode)], imm);
  6500 +#endif
  6501 +}
6164 6502 static always_inline void gen_evsplatfi (DisasContext *ctx)
6165 6503 {
6166   - uint32_t imm = rA(ctx->opcode) << 27;
  6504 + uint32_t imm = rA(ctx->opcode) << 11;
6167 6505  
6168   - gen_op_splatwi_T0_64(imm);
6169   - gen_store_gpr64(rD(ctx->opcode), cpu_T64[0]);
  6506 +#if defined(TARGET_PPC64)
  6507 + TCGv t0 = tcg_temp_new(TCG_TYPE_TL);
  6508 + TCGv t1 = tcg_temp_new(TCG_TYPE_TL);
  6509 + tcg_gen_movi_tl(t0, imm);
  6510 + tcg_gen_shri_tl(t1, t0, 32);
  6511 + tcg_gen_or_tl(cpu_gpr[rD(ctx->opcode)], t0, t1);
  6512 + tcg_temp_free(t0);
  6513 + tcg_temp_free(t1);
  6514 +#else
  6515 + tcg_gen_movi_i32(cpu_gpr[rD(ctx->opcode)], imm);
  6516 + tcg_gen_movi_i32(cpu_gprh[rD(ctx->opcode)], imm);
  6517 +#endif
6170 6518 }
6171 6519  
6172   -/* Comparison */
6173   -GEN_SPEOP_COMP(evcmpgtu);
6174   -GEN_SPEOP_COMP(evcmpgts);
6175   -GEN_SPEOP_COMP(evcmpltu);
6176   -GEN_SPEOP_COMP(evcmplts);
6177   -GEN_SPEOP_COMP(evcmpeq);
  6520 +static always_inline void gen_evsel (DisasContext *ctx)
  6521 +{
  6522 + int l1 = gen_new_label();
  6523 + int l2 = gen_new_label();
  6524 + int l3 = gen_new_label();
  6525 + int l4 = gen_new_label();
  6526 + TCGv t0 = tcg_temp_local_new(TCG_TYPE_I32);
  6527 +#if defined(TARGET_PPC64)
  6528 + TCGv t1 = tcg_temp_local_new(TCG_TYPE_TL);
  6529 + TCGv t2 = tcg_temp_local_new(TCG_TYPE_TL);
  6530 +#endif
  6531 + tcg_gen_andi_i32(t0, cpu_crf[ctx->opcode & 0x07], 1 << 3);
  6532 + tcg_gen_brcondi_i32(TCG_COND_EQ, t0, 0, l1);
  6533 +#if defined(TARGET_PPC64)
  6534 + tcg_gen_andi_tl(t1, cpu_gpr[rA(ctx->opcode)], 0xFFFFFFFF00000000ULL);
  6535 +#else
  6536 + tcg_gen_mov_tl(cpu_gprh[rD(ctx->opcode)], cpu_gprh[rA(ctx->opcode)]);
  6537 +#endif
  6538 + tcg_gen_br(l2);
  6539 + gen_set_label(l1);
  6540 +#if defined(TARGET_PPC64)
  6541 + tcg_gen_andi_tl(t1, cpu_gpr[rB(ctx->opcode)], 0xFFFFFFFF00000000ULL);
  6542 +#else
  6543 + tcg_gen_mov_tl(cpu_gprh[rD(ctx->opcode)], cpu_gprh[rB(ctx->opcode)]);
  6544 +#endif
  6545 + gen_set_label(l2);
  6546 + tcg_gen_andi_i32(t0, cpu_crf[ctx->opcode & 0x07], 1 << 2);
  6547 + tcg_gen_brcondi_i32(TCG_COND_EQ, t0, 0, l3);
  6548 +#if defined(TARGET_PPC64)
  6549 + tcg_gen_andi_tl(t2, cpu_gpr[rA(ctx->opcode)], 0x00000000FFFFFFFFULL);
  6550 +#else
  6551 + tcg_gen_mov_tl(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rA(ctx->opcode)]);
  6552 +#endif
  6553 + tcg_gen_br(l4);
  6554 + gen_set_label(l3);
  6555 +#if defined(TARGET_PPC64)
  6556 + tcg_gen_andi_tl(t2, cpu_gpr[rB(ctx->opcode)], 0x00000000FFFFFFFFULL);
  6557 +#else
  6558 + tcg_gen_mov_tl(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rB(ctx->opcode)]);
  6559 +#endif
  6560 + gen_set_label(l4);
  6561 + tcg_temp_free(t0);
  6562 +#if defined(TARGET_PPC64)
  6563 + tcg_gen_or_tl(cpu_gpr[rD(ctx->opcode)], t1, t2);
  6564 + tcg_temp_free(t1);
  6565 + tcg_temp_free(t2);
  6566 +#endif
  6567 +}
  6568 +GEN_HANDLER2(evsel0, "evsel", 0x04, 0x1c, 0x09, 0x00000000, PPC_SPE)
  6569 +{
  6570 + gen_evsel(ctx);
  6571 +}
  6572 +GEN_HANDLER2(evsel1, "evsel", 0x04, 0x1d, 0x09, 0x00000000, PPC_SPE)
  6573 +{
  6574 + gen_evsel(ctx);
  6575 +}
  6576 +GEN_HANDLER2(evsel2, "evsel", 0x04, 0x1e, 0x09, 0x00000000, PPC_SPE)
  6577 +{
  6578 + gen_evsel(ctx);
  6579 +}
  6580 +GEN_HANDLER2(evsel3, "evsel", 0x04, 0x1f, 0x09, 0x00000000, PPC_SPE)
  6581 +{
  6582 + gen_evsel(ctx);
  6583 +}
6178 6584  
6179 6585 GEN_SPE(evaddw, speundef, 0x00, 0x08, 0x00000000, PPC_SPE); ////
6180 6586 GEN_SPE(evaddiw, speundef, 0x01, 0x08, 0x00000000, PPC_SPE);
... ... @@ -6202,36 +6608,6 @@ GEN_SPE(evcmpgtu, evcmpgts, 0x18, 0x08, 0x00600000, PPC_SPE); ////
6202 6608 GEN_SPE(evcmpltu, evcmplts, 0x19, 0x08, 0x00600000, PPC_SPE); ////
6203 6609 GEN_SPE(evcmpeq, speundef, 0x1A, 0x08, 0x00600000, PPC_SPE); ////
6204 6610  
6205   -static always_inline void gen_evsel (DisasContext *ctx)
6206   -{
6207   - if (unlikely(!ctx->spe_enabled)) {
6208   - GEN_EXCP_NO_AP(ctx);
6209   - return;
6210   - }
6211   - tcg_gen_mov_i32(cpu_T[0], cpu_crf[ctx->opcode & 0x7]);
6212   - gen_load_gpr64(cpu_T64[0], rA(ctx->opcode));
6213   - gen_load_gpr64(cpu_T64[1], rB(ctx->opcode));
6214   - gen_op_evsel();
6215   - gen_store_gpr64(rD(ctx->opcode), cpu_T64[0]);
6216   -}
6217   -
6218   -GEN_HANDLER2(evsel0, "evsel", 0x04, 0x1c, 0x09, 0x00000000, PPC_SPE)
6219   -{
6220   - gen_evsel(ctx);
6221   -}
6222   -GEN_HANDLER2(evsel1, "evsel", 0x04, 0x1d, 0x09, 0x00000000, PPC_SPE)
6223   -{
6224   - gen_evsel(ctx);
6225   -}
6226   -GEN_HANDLER2(evsel2, "evsel", 0x04, 0x1e, 0x09, 0x00000000, PPC_SPE)
6227   -{
6228   - gen_evsel(ctx);
6229   -}
6230   -GEN_HANDLER2(evsel3, "evsel", 0x04, 0x1f, 0x09, 0x00000000, PPC_SPE)
6231   -{
6232   - gen_evsel(ctx);
6233   -}
6234   -
6235 6611 /* Load and stores */
6236 6612 GEN_SPEOP_LDST(dd, 3);
6237 6613 GEN_SPEOP_LDST(dw, 3);
... ... @@ -6500,15 +6876,53 @@ static always_inline void gen_##name (DisasContext *ctx) \
6500 6876 gen_store_gpr64(rD(ctx->opcode), cpu_T64[0]); \
6501 6877 }
6502 6878  
  6879 +#define GEN_SPEFPUOP_ARITH1(name) \
  6880 +static always_inline void gen_##name (DisasContext *ctx) \
  6881 +{ \
  6882 + if (unlikely(!ctx->spe_enabled)) { \
  6883 + GEN_EXCP_NO_AP(ctx); \
  6884 + return; \
  6885 + } \
  6886 + gen_load_gpr64(cpu_T64[0], rA(ctx->opcode)); \
  6887 + gen_op_##name(); \
  6888 + gen_store_gpr64(rD(ctx->opcode), cpu_T64[0]); \
  6889 +}
  6890 +
  6891 +#define GEN_SPEFPUOP_ARITH2(name) \
  6892 +static always_inline void gen_##name (DisasContext *ctx) \
  6893 +{ \
  6894 + if (unlikely(!ctx->spe_enabled)) { \
  6895 + GEN_EXCP_NO_AP(ctx); \
  6896 + return; \
  6897 + } \
  6898 + gen_load_gpr64(cpu_T64[0], rA(ctx->opcode)); \
  6899 + gen_load_gpr64(cpu_T64[1], rB(ctx->opcode)); \
  6900 + gen_op_##name(); \
  6901 + gen_store_gpr64(rD(ctx->opcode), cpu_T64[0]); \
  6902 +}
  6903 +
  6904 +#define GEN_SPEFPUOP_COMP(name) \
  6905 +static always_inline void gen_##name (DisasContext *ctx) \
  6906 +{ \
  6907 + if (unlikely(!ctx->spe_enabled)) { \
  6908 + GEN_EXCP_NO_AP(ctx); \
  6909 + return; \
  6910 + } \
  6911 + gen_load_gpr64(cpu_T64[0], rA(ctx->opcode)); \
  6912 + gen_load_gpr64(cpu_T64[1], rB(ctx->opcode)); \
  6913 + gen_op_##name(); \
  6914 + tcg_gen_andi_i32(cpu_crf[crfD(ctx->opcode)], cpu_T[0], 0xf); \
  6915 +}
  6916 +
6503 6917 /* Single precision floating-point vectors operations */
6504 6918 /* Arithmetic */
6505   -GEN_SPEOP_ARITH2(evfsadd);
6506   -GEN_SPEOP_ARITH2(evfssub);
6507   -GEN_SPEOP_ARITH2(evfsmul);
6508   -GEN_SPEOP_ARITH2(evfsdiv);
6509   -GEN_SPEOP_ARITH1(evfsabs);
6510   -GEN_SPEOP_ARITH1(evfsnabs);
6511   -GEN_SPEOP_ARITH1(evfsneg);
  6919 +GEN_SPEFPUOP_ARITH2(evfsadd);
  6920 +GEN_SPEFPUOP_ARITH2(evfssub);
  6921 +GEN_SPEFPUOP_ARITH2(evfsmul);
  6922 +GEN_SPEFPUOP_ARITH2(evfsdiv);
  6923 +GEN_SPEFPUOP_ARITH1(evfsabs);
  6924 +GEN_SPEFPUOP_ARITH1(evfsnabs);
  6925 +GEN_SPEFPUOP_ARITH1(evfsneg);
6512 6926 /* Conversion */
6513 6927 GEN_SPEFPUOP_CONV(evfscfui);
6514 6928 GEN_SPEFPUOP_CONV(evfscfsi);
... ... @@ -6521,12 +6935,12 @@ GEN_SPEFPUOP_CONV(evfsctsf);
6521 6935 GEN_SPEFPUOP_CONV(evfsctuiz);
6522 6936 GEN_SPEFPUOP_CONV(evfsctsiz);
6523 6937 /* Comparison */
6524   -GEN_SPEOP_COMP(evfscmpgt);
6525   -GEN_SPEOP_COMP(evfscmplt);
6526   -GEN_SPEOP_COMP(evfscmpeq);
6527   -GEN_SPEOP_COMP(evfststgt);
6528   -GEN_SPEOP_COMP(evfststlt);
6529   -GEN_SPEOP_COMP(evfststeq);
  6938 +GEN_SPEFPUOP_COMP(evfscmpgt);
  6939 +GEN_SPEFPUOP_COMP(evfscmplt);
  6940 +GEN_SPEFPUOP_COMP(evfscmpeq);
  6941 +GEN_SPEFPUOP_COMP(evfststgt);
  6942 +GEN_SPEFPUOP_COMP(evfststlt);
  6943 +GEN_SPEFPUOP_COMP(evfststeq);
6530 6944  
6531 6945 /* Opcodes definitions */
6532 6946 GEN_SPE(evfsadd, evfssub, 0x00, 0x0A, 0x00000000, PPC_SPEFPU); //
... ... @@ -6546,13 +6960,13 @@ GEN_SPE(evfststeq, speundef, 0x0F, 0x0A, 0x00600000, PPC_SPEFPU); //
6546 6960  
6547 6961 /* Single precision floating-point operations */
6548 6962 /* Arithmetic */
6549   -GEN_SPEOP_ARITH2(efsadd);
6550   -GEN_SPEOP_ARITH2(efssub);
6551   -GEN_SPEOP_ARITH2(efsmul);
6552   -GEN_SPEOP_ARITH2(efsdiv);
6553   -GEN_SPEOP_ARITH1(efsabs);
6554   -GEN_SPEOP_ARITH1(efsnabs);
6555   -GEN_SPEOP_ARITH1(efsneg);
  6963 +GEN_SPEFPUOP_ARITH2(efsadd);
  6964 +GEN_SPEFPUOP_ARITH2(efssub);
  6965 +GEN_SPEFPUOP_ARITH2(efsmul);
  6966 +GEN_SPEFPUOP_ARITH2(efsdiv);
  6967 +GEN_SPEFPUOP_ARITH1(efsabs);
  6968 +GEN_SPEFPUOP_ARITH1(efsnabs);
  6969 +GEN_SPEFPUOP_ARITH1(efsneg);
6556 6970 /* Conversion */
6557 6971 GEN_SPEFPUOP_CONV(efscfui);
6558 6972 GEN_SPEFPUOP_CONV(efscfsi);
... ... @@ -6566,12 +6980,12 @@ GEN_SPEFPUOP_CONV(efsctuiz);
6566 6980 GEN_SPEFPUOP_CONV(efsctsiz);
6567 6981 GEN_SPEFPUOP_CONV(efscfd);
6568 6982 /* Comparison */
6569   -GEN_SPEOP_COMP(efscmpgt);
6570   -GEN_SPEOP_COMP(efscmplt);
6571   -GEN_SPEOP_COMP(efscmpeq);
6572   -GEN_SPEOP_COMP(efststgt);
6573   -GEN_SPEOP_COMP(efststlt);
6574   -GEN_SPEOP_COMP(efststeq);
  6983 +GEN_SPEFPUOP_COMP(efscmpgt);
  6984 +GEN_SPEFPUOP_COMP(efscmplt);
  6985 +GEN_SPEFPUOP_COMP(efscmpeq);
  6986 +GEN_SPEFPUOP_COMP(efststgt);
  6987 +GEN_SPEFPUOP_COMP(efststlt);
  6988 +GEN_SPEFPUOP_COMP(efststeq);
6575 6989  
6576 6990 /* Opcodes definitions */
6577 6991 GEN_SPE(efsadd, efssub, 0x00, 0x0B, 0x00000000, PPC_SPEFPU); //
... ... @@ -6591,13 +7005,13 @@ GEN_SPE(efststeq, speundef, 0x0F, 0x0B, 0x00600000, PPC_SPEFPU); //
6591 7005  
6592 7006 /* Double precision floating-point operations */
6593 7007 /* Arithmetic */
6594   -GEN_SPEOP_ARITH2(efdadd);
6595   -GEN_SPEOP_ARITH2(efdsub);
6596   -GEN_SPEOP_ARITH2(efdmul);
6597   -GEN_SPEOP_ARITH2(efddiv);
6598   -GEN_SPEOP_ARITH1(efdabs);
6599   -GEN_SPEOP_ARITH1(efdnabs);
6600   -GEN_SPEOP_ARITH1(efdneg);
  7008 +GEN_SPEFPUOP_ARITH2(efdadd);
  7009 +GEN_SPEFPUOP_ARITH2(efdsub);
  7010 +GEN_SPEFPUOP_ARITH2(efdmul);
  7011 +GEN_SPEFPUOP_ARITH2(efddiv);
  7012 +GEN_SPEFPUOP_ARITH1(efdabs);
  7013 +GEN_SPEFPUOP_ARITH1(efdnabs);
  7014 +GEN_SPEFPUOP_ARITH1(efdneg);
6601 7015 /* Conversion */
6602 7016  
6603 7017 GEN_SPEFPUOP_CONV(efdcfui);
... ... @@ -6616,12 +7030,12 @@ GEN_SPEFPUOP_CONV(efdcfsid);
6616 7030 GEN_SPEFPUOP_CONV(efdctuidz);
6617 7031 GEN_SPEFPUOP_CONV(efdctsidz);
6618 7032 /* Comparison */
6619   -GEN_SPEOP_COMP(efdcmpgt);
6620   -GEN_SPEOP_COMP(efdcmplt);
6621   -GEN_SPEOP_COMP(efdcmpeq);
6622   -GEN_SPEOP_COMP(efdtstgt);
6623   -GEN_SPEOP_COMP(efdtstlt);
6624   -GEN_SPEOP_COMP(efdtsteq);
  7033 +GEN_SPEFPUOP_COMP(efdcmpgt);
  7034 +GEN_SPEFPUOP_COMP(efdcmplt);
  7035 +GEN_SPEFPUOP_COMP(efdcmpeq);
  7036 +GEN_SPEFPUOP_COMP(efdtstgt);
  7037 +GEN_SPEFPUOP_COMP(efdtstlt);
  7038 +GEN_SPEFPUOP_COMP(efdtsteq);
6625 7039  
6626 7040 /* Opcodes definitions */
6627 7041 GEN_SPE(efdadd, efdsub, 0x10, 0x0B, 0x00000000, PPC_SPEFPU); //
... ...