Commit 51789c410beb34423b1188a6b6e069fe8b68aebe
1 parent
e864cabd
PowerPC improvments:
- add missing 64 bits rotate instructions - safely define TARGET_PPCSPE when 64 bits registers are used a separate target will be needed to use it in 32 bits mode on 32 bits hosts. git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@2527 c046a42c-6fe2-441c-8c8c-71466251a162
Showing
3 changed files
with
104 additions
and
25 deletions
target-ppc/cpu.h
@@ -23,13 +23,18 @@ | @@ -23,13 +23,18 @@ | ||
23 | #include "config.h" | 23 | #include "config.h" |
24 | #include <stdint.h> | 24 | #include <stdint.h> |
25 | 25 | ||
26 | +#if defined(TARGET_PPC64) || (HOST_LONG_BITS >= 64) | ||
27 | +/* When using 64 bits temporary registers, | ||
28 | + * we can use 64 bits GPR with no extra cost | ||
29 | + */ | ||
30 | +#define TARGET_PPCSPE | ||
31 | +#endif | ||
32 | + | ||
26 | #if defined (TARGET_PPC64) | 33 | #if defined (TARGET_PPC64) |
27 | typedef uint64_t ppc_gpr_t; | 34 | typedef uint64_t ppc_gpr_t; |
28 | #define TARGET_LONG_BITS 64 | 35 | #define TARGET_LONG_BITS 64 |
29 | #define TARGET_GPR_BITS 64 | 36 | #define TARGET_GPR_BITS 64 |
30 | #define REGX "%016" PRIx64 | 37 | #define REGX "%016" PRIx64 |
31 | -/* We can safely use PowerPC SPE extension when compiling PowerPC 64 */ | ||
32 | -#define TARGET_PPCSPE | ||
33 | #elif defined(TARGET_PPCSPE) | 38 | #elif defined(TARGET_PPCSPE) |
34 | /* GPR are 64 bits: used by vector extension */ | 39 | /* GPR are 64 bits: used by vector extension */ |
35 | typedef uint64_t ppc_gpr_t; | 40 | typedef uint64_t ppc_gpr_t; |
target-ppc/op.c
@@ -1444,6 +1444,20 @@ void OPPROTO op_rotli32_T0 (void) | @@ -1444,6 +1444,20 @@ void OPPROTO op_rotli32_T0 (void) | ||
1444 | RETURN(); | 1444 | RETURN(); |
1445 | } | 1445 | } |
1446 | 1446 | ||
1447 | +#if defined(TARGET_PPC64) | ||
1448 | +void OPPROTO op_rotl64_T0_T1 (void) | ||
1449 | +{ | ||
1450 | + T0 = rotl64(T0, T1 & 0x3F); | ||
1451 | + RETURN(); | ||
1452 | +} | ||
1453 | + | ||
1454 | +void OPPROTO op_rotli64_T0 (void) | ||
1455 | +{ | ||
1456 | + T0 = rotl64(T0, PARAM1); | ||
1457 | + RETURN(); | ||
1458 | +} | ||
1459 | +#endif | ||
1460 | + | ||
1447 | /*** Integer shift ***/ | 1461 | /*** Integer shift ***/ |
1448 | /* shift left word */ | 1462 | /* shift left word */ |
1449 | void OPPROTO op_slw (void) | 1463 | void OPPROTO op_slw (void) |
target-ppc/translate.c
@@ -1109,12 +1109,10 @@ GEN_HANDLER(rlwimi, 0x14, 0xFF, 0xFF, 0x00000000, PPC_INTEGER) | @@ -1109,12 +1109,10 @@ GEN_HANDLER(rlwimi, 0x14, 0xFF, 0xFF, 0x00000000, PPC_INTEGER) | ||
1109 | { | 1109 | { |
1110 | target_ulong mask; | 1110 | target_ulong mask; |
1111 | uint32_t mb, me, sh; | 1111 | uint32_t mb, me, sh; |
1112 | - int n; | ||
1113 | 1112 | ||
1114 | mb = MB(ctx->opcode); | 1113 | mb = MB(ctx->opcode); |
1115 | me = ME(ctx->opcode); | 1114 | me = ME(ctx->opcode); |
1116 | sh = SH(ctx->opcode); | 1115 | sh = SH(ctx->opcode); |
1117 | - n = me + 1 - mb; | ||
1118 | if (likely(sh == 0)) { | 1116 | if (likely(sh == 0)) { |
1119 | if (likely(mb == 0 && me == 31)) { | 1117 | if (likely(mb == 0 && me == 31)) { |
1120 | gen_op_load_gpr_T0(rS(ctx->opcode)); | 1118 | gen_op_load_gpr_T0(rS(ctx->opcode)); |
@@ -1231,68 +1229,130 @@ GEN_HANDLER(name##3, opc1, opc2 | 0x11, 0xFF, 0x00000000, PPC_64B) \ | @@ -1231,68 +1229,130 @@ GEN_HANDLER(name##3, opc1, opc2 | 0x11, 0xFF, 0x00000000, PPC_64B) \ | ||
1231 | { \ | 1229 | { \ |
1232 | gen_##name(ctx, 1, 1); \ | 1230 | gen_##name(ctx, 1, 1); \ |
1233 | } | 1231 | } |
1232 | + | ||
1233 | +static inline void gen_rldinm (DisasContext *ctx, uint32_t mb, uint32_t me, | ||
1234 | + uint32_t sh) | ||
1235 | +{ | ||
1236 | + gen_op_load_gpr_T0(rS(ctx->opcode)); | ||
1237 | + if (likely(sh == 0)) { | ||
1238 | + goto do_mask; | ||
1239 | + } | ||
1240 | + if (likely(mb == 0)) { | ||
1241 | + if (likely(me == 63)) { | ||
1242 | + gen_op_rotli32_T0(sh); | ||
1243 | + goto do_store; | ||
1244 | + } else if (likely(me == (63 - sh))) { | ||
1245 | + gen_op_sli_T0(sh); | ||
1246 | + goto do_store; | ||
1247 | + } | ||
1248 | + } else if (likely(me == 63)) { | ||
1249 | + if (likely(sh == (64 - mb))) { | ||
1250 | + gen_op_srli_T0(mb); | ||
1251 | + goto do_store; | ||
1252 | + } | ||
1253 | + } | ||
1254 | + gen_op_rotli64_T0(sh); | ||
1255 | + do_mask: | ||
1256 | + gen_op_andi_T0(MASK(mb, me)); | ||
1257 | + do_store: | ||
1258 | + gen_op_store_T0_gpr(rA(ctx->opcode)); | ||
1259 | + if (unlikely(Rc(ctx->opcode) != 0)) | ||
1260 | + gen_set_Rc0(ctx); | ||
1261 | +} | ||
1234 | /* rldicl - rldicl. */ | 1262 | /* rldicl - rldicl. */ |
1235 | static inline void gen_rldicl (DisasContext *ctx, int mbn, int shn) | 1263 | static inline void gen_rldicl (DisasContext *ctx, int mbn, int shn) |
1236 | { | 1264 | { |
1237 | - int sh, mb; | 1265 | + uint32_t sh, mb; |
1238 | 1266 | ||
1239 | sh = SH(ctx->opcode) | (1 << shn); | 1267 | sh = SH(ctx->opcode) | (1 << shn); |
1240 | mb = (MB(ctx->opcode) << 1) | mbn; | 1268 | mb = (MB(ctx->opcode) << 1) | mbn; |
1241 | - /* XXX: TODO */ | ||
1242 | - RET_INVAL(ctx); | 1269 | + gen_rldinm(ctx, mb, 63, sh); |
1243 | } | 1270 | } |
1244 | -GEN_PPC64_R4(rldicl, 0x1E, 0x00) | 1271 | +GEN_PPC64_R4(rldicl, 0x1E, 0x00); |
1245 | /* rldicr - rldicr. */ | 1272 | /* rldicr - rldicr. */ |
1246 | static inline void gen_rldicr (DisasContext *ctx, int men, int shn) | 1273 | static inline void gen_rldicr (DisasContext *ctx, int men, int shn) |
1247 | { | 1274 | { |
1248 | - int sh, me; | 1275 | + uint32_t sh, me; |
1249 | 1276 | ||
1250 | sh = SH(ctx->opcode) | (1 << shn); | 1277 | sh = SH(ctx->opcode) | (1 << shn); |
1251 | me = (MB(ctx->opcode) << 1) | men; | 1278 | me = (MB(ctx->opcode) << 1) | men; |
1252 | - /* XXX: TODO */ | ||
1253 | - RET_INVAL(ctx); | 1279 | + gen_rldinm(ctx, 0, me, sh); |
1254 | } | 1280 | } |
1255 | -GEN_PPC64_R4(rldicr, 0x1E, 0x02) | 1281 | +GEN_PPC64_R4(rldicr, 0x1E, 0x02); |
1256 | /* rldic - rldic. */ | 1282 | /* rldic - rldic. */ |
1257 | static inline void gen_rldic (DisasContext *ctx, int mbn, int shn) | 1283 | static inline void gen_rldic (DisasContext *ctx, int mbn, int shn) |
1258 | { | 1284 | { |
1259 | - int sh, mb; | 1285 | + uint32_t sh, mb; |
1260 | 1286 | ||
1261 | sh = SH(ctx->opcode) | (1 << shn); | 1287 | sh = SH(ctx->opcode) | (1 << shn); |
1262 | mb = (MB(ctx->opcode) << 1) | mbn; | 1288 | mb = (MB(ctx->opcode) << 1) | mbn; |
1263 | - /* XXX: TODO */ | ||
1264 | - RET_INVAL(ctx); | 1289 | + gen_rldinm(ctx, mb, 63 - sh, sh); |
1265 | } | 1290 | } |
1266 | -GEN_PPC64_R4(rldic, 0x1E, 0x04) | 1291 | +GEN_PPC64_R4(rldic, 0x1E, 0x04); |
1292 | + | ||
1293 | +static inline void gen_rldnm (DisasContext *ctx, uint32_t mb, uint32_t me) | ||
1294 | +{ | ||
1295 | + gen_op_load_gpr_T0(rS(ctx->opcode)); | ||
1296 | + gen_op_load_gpr_T1(rB(ctx->opcode)); | ||
1297 | + gen_op_rotl64_T0_T1(); | ||
1298 | + if (unlikely(mb != 0 || me != 63)) { | ||
1299 | + gen_op_andi_T0(MASK(mb, me)); | ||
1300 | + } | ||
1301 | + gen_op_store_T0_gpr(rA(ctx->opcode)); | ||
1302 | + if (unlikely(Rc(ctx->opcode) != 0)) | ||
1303 | + gen_set_Rc0(ctx); | ||
1304 | +} | ||
1305 | + | ||
1267 | /* rldcl - rldcl. */ | 1306 | /* rldcl - rldcl. */ |
1268 | static inline void gen_rldcl (DisasContext *ctx, int mbn) | 1307 | static inline void gen_rldcl (DisasContext *ctx, int mbn) |
1269 | { | 1308 | { |
1270 | - int mb; | 1309 | + uint32_t mb; |
1271 | 1310 | ||
1272 | mb = (MB(ctx->opcode) << 1) | mbn; | 1311 | mb = (MB(ctx->opcode) << 1) | mbn; |
1273 | - /* XXX: TODO */ | ||
1274 | - RET_INVAL(ctx); | 1312 | + gen_rldnm(ctx, mb, 63); |
1275 | } | 1313 | } |
1276 | GEN_PPC64_R2(rldcl, 0x1E, 0x08) | 1314 | GEN_PPC64_R2(rldcl, 0x1E, 0x08) |
1277 | /* rldcr - rldcr. */ | 1315 | /* rldcr - rldcr. */ |
1278 | static inline void gen_rldcr (DisasContext *ctx, int men) | 1316 | static inline void gen_rldcr (DisasContext *ctx, int men) |
1279 | { | 1317 | { |
1280 | - int me; | 1318 | + uint32_t me; |
1281 | 1319 | ||
1282 | me = (MB(ctx->opcode) << 1) | men; | 1320 | me = (MB(ctx->opcode) << 1) | men; |
1283 | - /* XXX: TODO */ | ||
1284 | - RET_INVAL(ctx); | 1321 | + gen_rldnm(ctx, 0, me); |
1285 | } | 1322 | } |
1286 | GEN_PPC64_R2(rldcr, 0x1E, 0x09) | 1323 | GEN_PPC64_R2(rldcr, 0x1E, 0x09) |
1287 | /* rldimi - rldimi. */ | 1324 | /* rldimi - rldimi. */ |
1288 | static inline void gen_rldimi (DisasContext *ctx, int mbn, int shn) | 1325 | static inline void gen_rldimi (DisasContext *ctx, int mbn, int shn) |
1289 | { | 1326 | { |
1290 | - int sh, mb; | 1327 | + uint64_t mask; |
1328 | + uint32_t sh, mb; | ||
1291 | 1329 | ||
1292 | sh = SH(ctx->opcode) | (1 << shn); | 1330 | sh = SH(ctx->opcode) | (1 << shn); |
1293 | mb = (MB(ctx->opcode) << 1) | mbn; | 1331 | mb = (MB(ctx->opcode) << 1) | mbn; |
1294 | - /* XXX: TODO */ | ||
1295 | - RET_INVAL(ctx); | 1332 | + if (likely(sh == 0)) { |
1333 | + if (likely(mb == 0)) { | ||
1334 | + gen_op_load_gpr_T0(rS(ctx->opcode)); | ||
1335 | + goto do_store; | ||
1336 | + } else if (likely(mb == 63)) { | ||
1337 | + gen_op_load_gpr_T0(rA(ctx->opcode)); | ||
1338 | + goto do_store; | ||
1339 | + } | ||
1340 | + gen_op_load_gpr_T0(rS(ctx->opcode)); | ||
1341 | + gen_op_load_gpr_T1(rA(ctx->opcode)); | ||
1342 | + goto do_mask; | ||
1343 | + } | ||
1344 | + gen_op_load_gpr_T0(rS(ctx->opcode)); | ||
1345 | + gen_op_load_gpr_T1(rA(ctx->opcode)); | ||
1346 | + gen_op_rotli64_T0(SH(ctx->opcode)); | ||
1347 | + do_mask: | ||
1348 | + mask = MASK(mb, 63 - sh); | ||
1349 | + gen_op_andi_T0(mask); | ||
1350 | + gen_op_andi_T1(~mask); | ||
1351 | + gen_op_or(); | ||
1352 | + do_store: | ||
1353 | + gen_op_store_T0_gpr(rA(ctx->opcode)); | ||
1354 | + if (unlikely(Rc(ctx->opcode) != 0)) | ||
1355 | + gen_set_Rc0(ctx); | ||
1296 | } | 1356 | } |
1297 | GEN_PPC64_R4(rldimi, 0x1E, 0x06) | 1357 | GEN_PPC64_R4(rldimi, 0x1E, 0x06) |
1298 | #endif | 1358 | #endif |