Commit 324d9e320426253bd710a9efe210797435173eab

Authored by aurel32
1 parent b2ee0ce2

target-mips: optimize gen_arith_imm()

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

git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@7092 c046a42c-6fe2-441c-8c8c-71466251a162
Showing 1 changed file with 161 additions and 106 deletions
target-mips/translate.c
... ... @@ -57,10 +57,12 @@ enum {
57 57 OPC_ADDIU = (0x09 << 26),
58 58 OPC_SLTI = (0x0A << 26),
59 59 OPC_SLTIU = (0x0B << 26),
  60 + /* logic with immediate */
60 61 OPC_ANDI = (0x0C << 26),
61 62 OPC_ORI = (0x0D << 26),
62 63 OPC_XORI = (0x0E << 26),
63 64 OPC_LUI = (0x0F << 26),
  65 + /* arithmetic with immediate */
64 66 OPC_DADDI = (0x18 << 26),
65 67 OPC_DADDIU = (0x19 << 26),
66 68 /* Jump and branches */
... ... @@ -1197,140 +1199,184 @@ static void gen_flt_ldst (DisasContext *ctx, uint32_t opc, int ft,
1197 1199 static void gen_arith_imm (CPUState *env, DisasContext *ctx, uint32_t opc,
1198 1200 int rt, int rs, int16_t imm)
1199 1201 {
1200   - target_ulong uimm;
  1202 + target_ulong uimm = (target_long)imm; /* Sign extend to 32/64 bits */
1201 1203 const char *opn = "imm arith";
1202   - TCGv t0 = tcg_temp_local_new();
1203 1204  
1204 1205 if (rt == 0 && opc != OPC_ADDI && opc != OPC_DADDI) {
1205 1206 /* If no destination, treat it as a NOP.
1206 1207 For addi, we must generate the overflow exception when needed. */
1207 1208 MIPS_DEBUG("NOP");
1208   - goto out;
1209   - }
1210   - uimm = (uint16_t)imm;
1211   - switch (opc) {
1212   - case OPC_ADDI:
1213   - case OPC_ADDIU:
1214   -#if defined(TARGET_MIPS64)
1215   - case OPC_DADDI:
1216   - case OPC_DADDIU:
1217   -#endif
1218   - case OPC_SLTI:
1219   - case OPC_SLTIU:
1220   - uimm = (target_long)imm; /* Sign extend to 32/64 bits */
1221   - /* Fall through. */
1222   - case OPC_ANDI:
1223   - case OPC_ORI:
1224   - case OPC_XORI:
1225   - gen_load_gpr(t0, rs);
1226   - break;
1227   - case OPC_LUI:
1228   - tcg_gen_movi_tl(t0, imm << 16);
1229   - break;
1230   - case OPC_SLL:
1231   - case OPC_SRA:
1232   - case OPC_SRL:
1233   -#if defined(TARGET_MIPS64)
1234   - case OPC_DSLL:
1235   - case OPC_DSRA:
1236   - case OPC_DSRL:
1237   - case OPC_DSLL32:
1238   - case OPC_DSRA32:
1239   - case OPC_DSRL32:
1240   -#endif
1241   - uimm &= 0x1f;
1242   - gen_load_gpr(t0, rs);
1243   - break;
  1209 + return;
1244 1210 }
1245 1211 switch (opc) {
1246 1212 case OPC_ADDI:
1247 1213 {
1248   - TCGv r_tmp1 = tcg_temp_new();
1249   - TCGv r_tmp2 = tcg_temp_new();
  1214 + TCGv t0 = tcg_temp_local_new();
  1215 + TCGv t1 = tcg_temp_new();
  1216 + TCGv t2 = tcg_temp_new();
1250 1217 int l1 = gen_new_label();
1251 1218  
1252   - save_cpu_state(ctx, 1);
1253   - tcg_gen_ext32s_tl(r_tmp1, t0);
1254   - tcg_gen_addi_tl(t0, r_tmp1, uimm);
  1219 + gen_load_gpr(t1, rs);
  1220 + tcg_gen_addi_tl(t0, t1, uimm);
  1221 + tcg_gen_ext32s_tl(t0, t0);
1255 1222  
1256   - tcg_gen_xori_tl(r_tmp1, r_tmp1, ~uimm);
1257   - tcg_gen_xori_tl(r_tmp2, t0, uimm);
1258   - tcg_gen_and_tl(r_tmp1, r_tmp1, r_tmp2);
1259   - tcg_temp_free(r_tmp2);
1260   - tcg_gen_brcondi_tl(TCG_COND_GE, r_tmp1, 0, l1);
  1223 + tcg_gen_xori_tl(t1, t1, ~uimm);
  1224 + tcg_gen_xori_tl(t2, t0, uimm);
  1225 + tcg_gen_and_tl(t1, t1, t2);
  1226 + tcg_temp_free(t2);
  1227 + tcg_gen_brcondi_tl(TCG_COND_GE, t1, 0, l1);
  1228 + tcg_temp_free(t1);
1261 1229 /* operands of same sign, result different sign */
1262 1230 generate_exception(ctx, EXCP_OVERFLOW);
1263 1231 gen_set_label(l1);
1264   - tcg_temp_free(r_tmp1);
1265   -
1266 1232 tcg_gen_ext32s_tl(t0, t0);
  1233 + gen_store_gpr(t0, rt);
  1234 + tcg_temp_free(t0);
1267 1235 }
1268 1236 opn = "addi";
1269 1237 break;
1270 1238 case OPC_ADDIU:
1271   - tcg_gen_addi_tl(t0, t0, uimm);
1272   - tcg_gen_ext32s_tl(t0, t0);
  1239 + if (rs != 0) {
  1240 + tcg_gen_addi_tl(cpu_gpr[rt], cpu_gpr[rs], uimm);
  1241 + tcg_gen_ext32s_tl(cpu_gpr[rt], cpu_gpr[rt]);
  1242 + } else {
  1243 + tcg_gen_movi_tl(cpu_gpr[rt], uimm);
  1244 + }
1273 1245 opn = "addiu";
1274 1246 break;
1275 1247 #if defined(TARGET_MIPS64)
1276 1248 case OPC_DADDI:
1277 1249 {
1278   - TCGv r_tmp1 = tcg_temp_new();
1279   - TCGv r_tmp2 = tcg_temp_new();
  1250 + TCGv t0 = tcg_temp_local_new();
  1251 + TCGv t1 = tcg_temp_new();
  1252 + TCGv t2 = tcg_temp_new();
1280 1253 int l1 = gen_new_label();
1281 1254  
1282   - save_cpu_state(ctx, 1);
1283   - tcg_gen_mov_tl(r_tmp1, t0);
1284   - tcg_gen_addi_tl(t0, t0, uimm);
  1255 + gen_load_gpr(t1, rs);
  1256 + tcg_gen_addi_tl(t0, t1, uimm);
1285 1257  
1286   - tcg_gen_xori_tl(r_tmp1, r_tmp1, ~uimm);
1287   - tcg_gen_xori_tl(r_tmp2, t0, uimm);
1288   - tcg_gen_and_tl(r_tmp1, r_tmp1, r_tmp2);
1289   - tcg_temp_free(r_tmp2);
1290   - tcg_gen_brcondi_tl(TCG_COND_GE, r_tmp1, 0, l1);
  1258 + tcg_gen_xori_tl(t1, t1, ~uimm);
  1259 + tcg_gen_xori_tl(t2, t0, uimm);
  1260 + tcg_gen_and_tl(t1, t1, t2);
  1261 + tcg_temp_free(t2);
  1262 + tcg_gen_brcondi_tl(TCG_COND_GE, t1, 0, l1);
  1263 + tcg_temp_free(t1);
1291 1264 /* operands of same sign, result different sign */
1292 1265 generate_exception(ctx, EXCP_OVERFLOW);
1293 1266 gen_set_label(l1);
1294   - tcg_temp_free(r_tmp1);
  1267 + gen_store_gpr(t0, rt);
  1268 + tcg_temp_free(t0);
1295 1269 }
1296 1270 opn = "daddi";
1297 1271 break;
1298 1272 case OPC_DADDIU:
1299   - tcg_gen_addi_tl(t0, t0, uimm);
  1273 + if (rs != 0) {
  1274 + tcg_gen_addi_tl(cpu_gpr[rt], cpu_gpr[rs], uimm);
  1275 + } else {
  1276 + tcg_gen_movi_tl(cpu_gpr[rt], uimm);
  1277 + }
1300 1278 opn = "daddiu";
1301 1279 break;
1302 1280 #endif
1303   - case OPC_SLTI:
1304   - gen_op_lti(t0, t0, uimm);
1305   - opn = "slti";
1306   - break;
1307   - case OPC_SLTIU:
1308   - gen_op_ltiu(t0, t0, uimm);
1309   - opn = "sltiu";
1310   - break;
  1281 + }
  1282 + MIPS_DEBUG("%s %s, %s, " TARGET_FMT_lx, opn, regnames[rt], regnames[rs], uimm);
  1283 +}
  1284 +
  1285 +/* Logic with immediate operand */
  1286 +static void gen_logic_imm (CPUState *env, uint32_t opc, int rt, int rs, int16_t imm)
  1287 +{
  1288 + target_ulong uimm;
  1289 + const char *opn = "imm logic";
  1290 +
  1291 + if (rt == 0) {
  1292 + /* If no destination, treat it as a NOP. */
  1293 + MIPS_DEBUG("NOP");
  1294 + return;
  1295 + }
  1296 + uimm = (uint16_t)imm;
  1297 + switch (opc) {
1311 1298 case OPC_ANDI:
1312   - tcg_gen_andi_tl(t0, t0, uimm);
  1299 + if (likely(rs != 0))
  1300 + tcg_gen_andi_tl(cpu_gpr[rt], cpu_gpr[rs], uimm);
  1301 + else
  1302 + tcg_gen_movi_tl(cpu_gpr[rt], 0);
1313 1303 opn = "andi";
1314 1304 break;
1315 1305 case OPC_ORI:
1316   - tcg_gen_ori_tl(t0, t0, uimm);
  1306 + if (rs != 0)
  1307 + tcg_gen_ori_tl(cpu_gpr[rt], cpu_gpr[rs], uimm);
  1308 + else
  1309 + tcg_gen_movi_tl(cpu_gpr[rt], uimm);
1317 1310 opn = "ori";
1318 1311 break;
1319 1312 case OPC_XORI:
1320   - tcg_gen_xori_tl(t0, t0, uimm);
  1313 + if (likely(rs != 0))
  1314 + tcg_gen_xori_tl(cpu_gpr[rt], cpu_gpr[rs], uimm);
  1315 + else
  1316 + tcg_gen_movi_tl(cpu_gpr[rt], uimm);
1321 1317 opn = "xori";
1322 1318 break;
1323 1319 case OPC_LUI:
  1320 + tcg_gen_movi_tl(cpu_gpr[rt], imm << 16);
1324 1321 opn = "lui";
1325 1322 break;
  1323 + }
  1324 + MIPS_DEBUG("%s %s, %s, " TARGET_FMT_lx, opn, regnames[rt], regnames[rs], uimm);
  1325 +}
  1326 +
  1327 +/* Set on less than with immediate operand */
  1328 +static void gen_slt_imm (CPUState *env, uint32_t opc, int rt, int rs, int16_t imm)
  1329 +{
  1330 + target_ulong uimm = (target_long)imm; /* Sign extend to 32/64 bits */
  1331 + const char *opn = "imm arith";
  1332 + TCGv t0;
  1333 +
  1334 + if (rt == 0) {
  1335 + /* If no destination, treat it as a NOP. */
  1336 + MIPS_DEBUG("NOP");
  1337 + return;
  1338 + }
  1339 + t0 = tcg_temp_new();
  1340 + gen_load_gpr(t0, rs);
  1341 + switch (opc) {
  1342 + case OPC_SLTI:
  1343 + gen_op_lti(cpu_gpr[rt], t0, uimm);
  1344 + opn = "slti";
  1345 + break;
  1346 + case OPC_SLTIU:
  1347 + gen_op_ltiu(cpu_gpr[rt], t0, uimm);
  1348 + opn = "sltiu";
  1349 + break;
  1350 + }
  1351 + MIPS_DEBUG("%s %s, %s, " TARGET_FMT_lx, opn, regnames[rt], regnames[rs], uimm);
  1352 + tcg_temp_free(t0);
  1353 +}
  1354 +
  1355 +/* Shifts with immediate operand */
  1356 +static void gen_shift_imm(CPUState *env, DisasContext *ctx, uint32_t opc,
  1357 + int rt, int rs, int16_t imm)
  1358 +{
  1359 + target_ulong uimm = ((uint16_t)imm) & 0x1f;
  1360 + const char *opn = "imm shift";
  1361 + TCGv t0;
  1362 +
  1363 + if (rt == 0) {
  1364 + /* If no destination, treat it as a NOP. */
  1365 + MIPS_DEBUG("NOP");
  1366 + return;
  1367 + }
  1368 +
  1369 + t0 = tcg_temp_new();
  1370 + gen_load_gpr(t0, rs);
  1371 + switch (opc) {
1326 1372 case OPC_SLL:
1327 1373 tcg_gen_shli_tl(t0, t0, uimm);
1328   - tcg_gen_ext32s_tl(t0, t0);
  1374 + tcg_gen_ext32s_tl(cpu_gpr[rt], t0);
1329 1375 opn = "sll";
1330 1376 break;
1331 1377 case OPC_SRA:
1332 1378 tcg_gen_ext32s_tl(t0, t0);
1333   - tcg_gen_sari_tl(t0, t0, uimm);
  1379 + tcg_gen_sari_tl(cpu_gpr[rt], t0, uimm);
1334 1380 opn = "sra";
1335 1381 break;
1336 1382 case OPC_SRL:
... ... @@ -1338,9 +1384,9 @@ static void gen_arith_imm (CPUState *env, DisasContext *ctx, uint32_t opc,
1338 1384 case 0:
1339 1385 if (uimm != 0) {
1340 1386 tcg_gen_ext32u_tl(t0, t0);
1341   - tcg_gen_shri_tl(t0, t0, uimm);
  1387 + tcg_gen_shri_tl(cpu_gpr[rt], t0, uimm);
1342 1388 } else {
1343   - tcg_gen_ext32s_tl(t0, t0);
  1389 + tcg_gen_ext32s_tl(cpu_gpr[rt], t0);
1344 1390 }
1345 1391 opn = "srl";
1346 1392 break;
... ... @@ -1352,16 +1398,16 @@ static void gen_arith_imm (CPUState *env, DisasContext *ctx, uint32_t opc,
1352 1398  
1353 1399 tcg_gen_trunc_tl_i32(r_tmp1, t0);
1354 1400 tcg_gen_rotri_i32(r_tmp1, r_tmp1, uimm);
1355   - tcg_gen_ext_i32_tl(t0, r_tmp1);
  1401 + tcg_gen_ext_i32_tl(cpu_gpr[rt], r_tmp1);
1356 1402 tcg_temp_free_i32(r_tmp1);
1357 1403 }
1358 1404 opn = "rotr";
1359 1405 } else {
1360 1406 if (uimm != 0) {
1361 1407 tcg_gen_ext32u_tl(t0, t0);
1362   - tcg_gen_shri_tl(t0, t0, uimm);
  1408 + tcg_gen_shri_tl(cpu_gpr[rt], t0, uimm);
1363 1409 } else {
1364   - tcg_gen_ext32s_tl(t0, t0);
  1410 + tcg_gen_ext32s_tl(cpu_gpr[rt], t0);
1365 1411 }
1366 1412 opn = "srl";
1367 1413 }
... ... @@ -1374,28 +1420,28 @@ static void gen_arith_imm (CPUState *env, DisasContext *ctx, uint32_t opc,
1374 1420 break;
1375 1421 #if defined(TARGET_MIPS64)
1376 1422 case OPC_DSLL:
1377   - tcg_gen_shli_tl(t0, t0, uimm);
  1423 + tcg_gen_shli_tl(cpu_gpr[rt], t0, uimm);
1378 1424 opn = "dsll";
1379 1425 break;
1380 1426 case OPC_DSRA:
1381   - tcg_gen_sari_tl(t0, t0, uimm);
  1427 + tcg_gen_sari_tl(cpu_gpr[rt], t0, uimm);
1382 1428 opn = "dsra";
1383 1429 break;
1384 1430 case OPC_DSRL:
1385 1431 switch ((ctx->opcode >> 21) & 0x1f) {
1386 1432 case 0:
1387   - tcg_gen_shri_tl(t0, t0, uimm);
  1433 + tcg_gen_shri_tl(cpu_gpr[rt], t0, uimm);
1388 1434 opn = "dsrl";
1389 1435 break;
1390 1436 case 1:
1391 1437 /* drotr is decoded as dsrl on non-R2 CPUs */
1392 1438 if (env->insn_flags & ISA_MIPS32R2) {
1393 1439 if (uimm != 0) {
1394   - tcg_gen_rotri_tl(t0, t0, uimm);
  1440 + tcg_gen_rotri_tl(cpu_gpr[rt], t0, uimm);
1395 1441 }
1396 1442 opn = "drotr";
1397 1443 } else {
1398   - tcg_gen_shri_tl(t0, t0, uimm);
  1444 + tcg_gen_shri_tl(cpu_gpr[rt], t0, uimm);
1399 1445 opn = "dsrl";
1400 1446 }
1401 1447 break;
... ... @@ -1406,26 +1452,26 @@ static void gen_arith_imm (CPUState *env, DisasContext *ctx, uint32_t opc,
1406 1452 }
1407 1453 break;
1408 1454 case OPC_DSLL32:
1409   - tcg_gen_shli_tl(t0, t0, uimm + 32);
  1455 + tcg_gen_shli_tl(cpu_gpr[rt], t0, uimm + 32);
1410 1456 opn = "dsll32";
1411 1457 break;
1412 1458 case OPC_DSRA32:
1413   - tcg_gen_sari_tl(t0, t0, uimm + 32);
  1459 + tcg_gen_sari_tl(cpu_gpr[rt], t0, uimm + 32);
1414 1460 opn = "dsra32";
1415 1461 break;
1416 1462 case OPC_DSRL32:
1417 1463 switch ((ctx->opcode >> 21) & 0x1f) {
1418 1464 case 0:
1419   - tcg_gen_shri_tl(t0, t0, uimm + 32);
  1465 + tcg_gen_shri_tl(cpu_gpr[rt], t0, uimm + 32);
1420 1466 opn = "dsrl32";
1421 1467 break;
1422 1468 case 1:
1423 1469 /* drotr32 is decoded as dsrl32 on non-R2 CPUs */
1424 1470 if (env->insn_flags & ISA_MIPS32R2) {
1425   - tcg_gen_rotri_tl(t0, t0, uimm + 32);
  1471 + tcg_gen_rotri_tl(cpu_gpr[rt], t0, uimm + 32);
1426 1472 opn = "drotr32";
1427 1473 } else {
1428   - tcg_gen_shri_tl(t0, t0, uimm + 32);
  1474 + tcg_gen_shri_tl(cpu_gpr[rt], t0, uimm + 32);
1429 1475 opn = "dsrl32";
1430 1476 }
1431 1477 break;
... ... @@ -1436,14 +1482,8 @@ static void gen_arith_imm (CPUState *env, DisasContext *ctx, uint32_t opc,
1436 1482 }
1437 1483 break;
1438 1484 #endif
1439   - default:
1440   - MIPS_INVAL(opn);
1441   - generate_exception(ctx, EXCP_RI);
1442   - goto out;
1443 1485 }
1444   - gen_store_gpr(t0, rt);
1445 1486 MIPS_DEBUG("%s %s, %s, " TARGET_FMT_lx, opn, regnames[rt], regnames[rs], uimm);
1446   - out:
1447 1487 tcg_temp_free(t0);
1448 1488 }
1449 1489  
... ... @@ -7556,9 +7596,10 @@ static void decode_opc (CPUState *env, DisasContext *ctx)
7556 7596 case OPC_SPECIAL:
7557 7597 op1 = MASK_SPECIAL(ctx->opcode);
7558 7598 switch (op1) {
7559   - case OPC_SLL: /* Arithmetic with immediate */
7560   - case OPC_SRL ... OPC_SRA:
7561   - gen_arith_imm(env, ctx, op1, rd, rt, sa);
  7599 + case OPC_SLL: /* Shift with immediate */
  7600 + case OPC_SRA:
  7601 + case OPC_SRL:
  7602 + gen_shift_imm(env, ctx, op1, rd, rt, sa);
7562 7603 break;
7563 7604 case OPC_MOVN: /* Conditional move */
7564 7605 case OPC_MOVZ:
... ... @@ -7648,12 +7689,14 @@ static void decode_opc (CPUState *env, DisasContext *ctx)
7648 7689 #if defined(TARGET_MIPS64)
7649 7690 /* MIPS64 specific opcodes */
7650 7691 case OPC_DSLL:
7651   - case OPC_DSRL ... OPC_DSRA:
  7692 + case OPC_DSRA:
  7693 + case OPC_DSRL:
7652 7694 case OPC_DSLL32:
7653   - case OPC_DSRL32 ... OPC_DSRA32:
  7695 + case OPC_DSRA32:
  7696 + case OPC_DSRL32:
7654 7697 check_insn(env, ctx, ISA_MIPS3);
7655 7698 check_mips_64(ctx);
7656   - gen_arith_imm(env, ctx, op1, rd, rt, sa);
  7699 + gen_shift_imm(env, ctx, op1, rd, rt, sa);
7657 7700 break;
7658 7701 case OPC_DADD ... OPC_DSUBU:
7659 7702 check_insn(env, ctx, ISA_MIPS3);
... ... @@ -7928,9 +7971,20 @@ static void decode_opc (CPUState *env, DisasContext *ctx)
7928 7971 break;
7929 7972 }
7930 7973 break;
7931   - case OPC_ADDI ... OPC_LUI: /* Arithmetic with immediate opcode */
  7974 + case OPC_ADDI: /* Arithmetic with immediate opcode */
  7975 + case OPC_ADDIU:
7932 7976 gen_arith_imm(env, ctx, op, rt, rs, imm);
7933 7977 break;
  7978 + case OPC_SLTI: /* Set on less than with immediate opcode */
  7979 + case OPC_SLTIU:
  7980 + gen_slt_imm(env, op, rt, rs, imm);
  7981 + break;
  7982 + case OPC_ANDI: /* Arithmetic with immediate opcode */
  7983 + case OPC_LUI:
  7984 + case OPC_ORI:
  7985 + case OPC_XORI:
  7986 + gen_logic_imm(env, op, rt, rs, imm);
  7987 + break;
7934 7988 case OPC_J ... OPC_JAL: /* Jump */
7935 7989 offset = (int32_t)(ctx->opcode & 0x3FFFFFF) << 2;
7936 7990 gen_compute_branch(ctx, op, rs, rt, offset);
... ... @@ -8080,7 +8134,8 @@ static void decode_opc (CPUState *env, DisasContext *ctx)
8080 8134 check_mips_64(ctx);
8081 8135 gen_ldst(ctx, op, rt, rs, imm);
8082 8136 break;
8083   - case OPC_DADDI ... OPC_DADDIU:
  8137 + case OPC_DADDI:
  8138 + case OPC_DADDIU:
8084 8139 check_insn(env, ctx, ISA_MIPS3);
8085 8140 check_mips_64(ctx);
8086 8141 gen_arith_imm(env, ctx, op, rt, rs, imm);
... ...