Commit 324d9e320426253bd710a9efe210797435173eab
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,10 +57,12 @@ enum { | ||
57 | OPC_ADDIU = (0x09 << 26), | 57 | OPC_ADDIU = (0x09 << 26), |
58 | OPC_SLTI = (0x0A << 26), | 58 | OPC_SLTI = (0x0A << 26), |
59 | OPC_SLTIU = (0x0B << 26), | 59 | OPC_SLTIU = (0x0B << 26), |
60 | + /* logic with immediate */ | ||
60 | OPC_ANDI = (0x0C << 26), | 61 | OPC_ANDI = (0x0C << 26), |
61 | OPC_ORI = (0x0D << 26), | 62 | OPC_ORI = (0x0D << 26), |
62 | OPC_XORI = (0x0E << 26), | 63 | OPC_XORI = (0x0E << 26), |
63 | OPC_LUI = (0x0F << 26), | 64 | OPC_LUI = (0x0F << 26), |
65 | + /* arithmetic with immediate */ | ||
64 | OPC_DADDI = (0x18 << 26), | 66 | OPC_DADDI = (0x18 << 26), |
65 | OPC_DADDIU = (0x19 << 26), | 67 | OPC_DADDIU = (0x19 << 26), |
66 | /* Jump and branches */ | 68 | /* Jump and branches */ |
@@ -1197,140 +1199,184 @@ static void gen_flt_ldst (DisasContext *ctx, uint32_t opc, int ft, | @@ -1197,140 +1199,184 @@ static void gen_flt_ldst (DisasContext *ctx, uint32_t opc, int ft, | ||
1197 | static void gen_arith_imm (CPUState *env, DisasContext *ctx, uint32_t opc, | 1199 | static void gen_arith_imm (CPUState *env, DisasContext *ctx, uint32_t opc, |
1198 | int rt, int rs, int16_t imm) | 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 | const char *opn = "imm arith"; | 1203 | const char *opn = "imm arith"; |
1202 | - TCGv t0 = tcg_temp_local_new(); | ||
1203 | 1204 | ||
1204 | if (rt == 0 && opc != OPC_ADDI && opc != OPC_DADDI) { | 1205 | if (rt == 0 && opc != OPC_ADDI && opc != OPC_DADDI) { |
1205 | /* If no destination, treat it as a NOP. | 1206 | /* If no destination, treat it as a NOP. |
1206 | For addi, we must generate the overflow exception when needed. */ | 1207 | For addi, we must generate the overflow exception when needed. */ |
1207 | MIPS_DEBUG("NOP"); | 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 | switch (opc) { | 1211 | switch (opc) { |
1246 | case OPC_ADDI: | 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 | int l1 = gen_new_label(); | 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 | /* operands of same sign, result different sign */ | 1229 | /* operands of same sign, result different sign */ |
1262 | generate_exception(ctx, EXCP_OVERFLOW); | 1230 | generate_exception(ctx, EXCP_OVERFLOW); |
1263 | gen_set_label(l1); | 1231 | gen_set_label(l1); |
1264 | - tcg_temp_free(r_tmp1); | ||
1265 | - | ||
1266 | tcg_gen_ext32s_tl(t0, t0); | 1232 | tcg_gen_ext32s_tl(t0, t0); |
1233 | + gen_store_gpr(t0, rt); | ||
1234 | + tcg_temp_free(t0); | ||
1267 | } | 1235 | } |
1268 | opn = "addi"; | 1236 | opn = "addi"; |
1269 | break; | 1237 | break; |
1270 | case OPC_ADDIU: | 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 | opn = "addiu"; | 1245 | opn = "addiu"; |
1274 | break; | 1246 | break; |
1275 | #if defined(TARGET_MIPS64) | 1247 | #if defined(TARGET_MIPS64) |
1276 | case OPC_DADDI: | 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 | int l1 = gen_new_label(); | 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 | /* operands of same sign, result different sign */ | 1264 | /* operands of same sign, result different sign */ |
1292 | generate_exception(ctx, EXCP_OVERFLOW); | 1265 | generate_exception(ctx, EXCP_OVERFLOW); |
1293 | gen_set_label(l1); | 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 | opn = "daddi"; | 1270 | opn = "daddi"; |
1297 | break; | 1271 | break; |
1298 | case OPC_DADDIU: | 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 | opn = "daddiu"; | 1278 | opn = "daddiu"; |
1301 | break; | 1279 | break; |
1302 | #endif | 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 | case OPC_ANDI: | 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 | opn = "andi"; | 1303 | opn = "andi"; |
1314 | break; | 1304 | break; |
1315 | case OPC_ORI: | 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 | opn = "ori"; | 1310 | opn = "ori"; |
1318 | break; | 1311 | break; |
1319 | case OPC_XORI: | 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 | opn = "xori"; | 1317 | opn = "xori"; |
1322 | break; | 1318 | break; |
1323 | case OPC_LUI: | 1319 | case OPC_LUI: |
1320 | + tcg_gen_movi_tl(cpu_gpr[rt], imm << 16); | ||
1324 | opn = "lui"; | 1321 | opn = "lui"; |
1325 | break; | 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 | case OPC_SLL: | 1372 | case OPC_SLL: |
1327 | tcg_gen_shli_tl(t0, t0, uimm); | 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 | opn = "sll"; | 1375 | opn = "sll"; |
1330 | break; | 1376 | break; |
1331 | case OPC_SRA: | 1377 | case OPC_SRA: |
1332 | tcg_gen_ext32s_tl(t0, t0); | 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 | opn = "sra"; | 1380 | opn = "sra"; |
1335 | break; | 1381 | break; |
1336 | case OPC_SRL: | 1382 | case OPC_SRL: |
@@ -1338,9 +1384,9 @@ static void gen_arith_imm (CPUState *env, DisasContext *ctx, uint32_t opc, | @@ -1338,9 +1384,9 @@ static void gen_arith_imm (CPUState *env, DisasContext *ctx, uint32_t opc, | ||
1338 | case 0: | 1384 | case 0: |
1339 | if (uimm != 0) { | 1385 | if (uimm != 0) { |
1340 | tcg_gen_ext32u_tl(t0, t0); | 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 | } else { | 1388 | } else { |
1343 | - tcg_gen_ext32s_tl(t0, t0); | 1389 | + tcg_gen_ext32s_tl(cpu_gpr[rt], t0); |
1344 | } | 1390 | } |
1345 | opn = "srl"; | 1391 | opn = "srl"; |
1346 | break; | 1392 | break; |
@@ -1352,16 +1398,16 @@ static void gen_arith_imm (CPUState *env, DisasContext *ctx, uint32_t opc, | @@ -1352,16 +1398,16 @@ static void gen_arith_imm (CPUState *env, DisasContext *ctx, uint32_t opc, | ||
1352 | 1398 | ||
1353 | tcg_gen_trunc_tl_i32(r_tmp1, t0); | 1399 | tcg_gen_trunc_tl_i32(r_tmp1, t0); |
1354 | tcg_gen_rotri_i32(r_tmp1, r_tmp1, uimm); | 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 | tcg_temp_free_i32(r_tmp1); | 1402 | tcg_temp_free_i32(r_tmp1); |
1357 | } | 1403 | } |
1358 | opn = "rotr"; | 1404 | opn = "rotr"; |
1359 | } else { | 1405 | } else { |
1360 | if (uimm != 0) { | 1406 | if (uimm != 0) { |
1361 | tcg_gen_ext32u_tl(t0, t0); | 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 | } else { | 1409 | } else { |
1364 | - tcg_gen_ext32s_tl(t0, t0); | 1410 | + tcg_gen_ext32s_tl(cpu_gpr[rt], t0); |
1365 | } | 1411 | } |
1366 | opn = "srl"; | 1412 | opn = "srl"; |
1367 | } | 1413 | } |
@@ -1374,28 +1420,28 @@ static void gen_arith_imm (CPUState *env, DisasContext *ctx, uint32_t opc, | @@ -1374,28 +1420,28 @@ static void gen_arith_imm (CPUState *env, DisasContext *ctx, uint32_t opc, | ||
1374 | break; | 1420 | break; |
1375 | #if defined(TARGET_MIPS64) | 1421 | #if defined(TARGET_MIPS64) |
1376 | case OPC_DSLL: | 1422 | case OPC_DSLL: |
1377 | - tcg_gen_shli_tl(t0, t0, uimm); | 1423 | + tcg_gen_shli_tl(cpu_gpr[rt], t0, uimm); |
1378 | opn = "dsll"; | 1424 | opn = "dsll"; |
1379 | break; | 1425 | break; |
1380 | case OPC_DSRA: | 1426 | case OPC_DSRA: |
1381 | - tcg_gen_sari_tl(t0, t0, uimm); | 1427 | + tcg_gen_sari_tl(cpu_gpr[rt], t0, uimm); |
1382 | opn = "dsra"; | 1428 | opn = "dsra"; |
1383 | break; | 1429 | break; |
1384 | case OPC_DSRL: | 1430 | case OPC_DSRL: |
1385 | switch ((ctx->opcode >> 21) & 0x1f) { | 1431 | switch ((ctx->opcode >> 21) & 0x1f) { |
1386 | case 0: | 1432 | case 0: |
1387 | - tcg_gen_shri_tl(t0, t0, uimm); | 1433 | + tcg_gen_shri_tl(cpu_gpr[rt], t0, uimm); |
1388 | opn = "dsrl"; | 1434 | opn = "dsrl"; |
1389 | break; | 1435 | break; |
1390 | case 1: | 1436 | case 1: |
1391 | /* drotr is decoded as dsrl on non-R2 CPUs */ | 1437 | /* drotr is decoded as dsrl on non-R2 CPUs */ |
1392 | if (env->insn_flags & ISA_MIPS32R2) { | 1438 | if (env->insn_flags & ISA_MIPS32R2) { |
1393 | if (uimm != 0) { | 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 | opn = "drotr"; | 1442 | opn = "drotr"; |
1397 | } else { | 1443 | } else { |
1398 | - tcg_gen_shri_tl(t0, t0, uimm); | 1444 | + tcg_gen_shri_tl(cpu_gpr[rt], t0, uimm); |
1399 | opn = "dsrl"; | 1445 | opn = "dsrl"; |
1400 | } | 1446 | } |
1401 | break; | 1447 | break; |
@@ -1406,26 +1452,26 @@ static void gen_arith_imm (CPUState *env, DisasContext *ctx, uint32_t opc, | @@ -1406,26 +1452,26 @@ static void gen_arith_imm (CPUState *env, DisasContext *ctx, uint32_t opc, | ||
1406 | } | 1452 | } |
1407 | break; | 1453 | break; |
1408 | case OPC_DSLL32: | 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 | opn = "dsll32"; | 1456 | opn = "dsll32"; |
1411 | break; | 1457 | break; |
1412 | case OPC_DSRA32: | 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 | opn = "dsra32"; | 1460 | opn = "dsra32"; |
1415 | break; | 1461 | break; |
1416 | case OPC_DSRL32: | 1462 | case OPC_DSRL32: |
1417 | switch ((ctx->opcode >> 21) & 0x1f) { | 1463 | switch ((ctx->opcode >> 21) & 0x1f) { |
1418 | case 0: | 1464 | case 0: |
1419 | - tcg_gen_shri_tl(t0, t0, uimm + 32); | 1465 | + tcg_gen_shri_tl(cpu_gpr[rt], t0, uimm + 32); |
1420 | opn = "dsrl32"; | 1466 | opn = "dsrl32"; |
1421 | break; | 1467 | break; |
1422 | case 1: | 1468 | case 1: |
1423 | /* drotr32 is decoded as dsrl32 on non-R2 CPUs */ | 1469 | /* drotr32 is decoded as dsrl32 on non-R2 CPUs */ |
1424 | if (env->insn_flags & ISA_MIPS32R2) { | 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 | opn = "drotr32"; | 1472 | opn = "drotr32"; |
1427 | } else { | 1473 | } else { |
1428 | - tcg_gen_shri_tl(t0, t0, uimm + 32); | 1474 | + tcg_gen_shri_tl(cpu_gpr[rt], t0, uimm + 32); |
1429 | opn = "dsrl32"; | 1475 | opn = "dsrl32"; |
1430 | } | 1476 | } |
1431 | break; | 1477 | break; |
@@ -1436,14 +1482,8 @@ static void gen_arith_imm (CPUState *env, DisasContext *ctx, uint32_t opc, | @@ -1436,14 +1482,8 @@ static void gen_arith_imm (CPUState *env, DisasContext *ctx, uint32_t opc, | ||
1436 | } | 1482 | } |
1437 | break; | 1483 | break; |
1438 | #endif | 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 | MIPS_DEBUG("%s %s, %s, " TARGET_FMT_lx, opn, regnames[rt], regnames[rs], uimm); | 1486 | MIPS_DEBUG("%s %s, %s, " TARGET_FMT_lx, opn, regnames[rt], regnames[rs], uimm); |
1446 | - out: | ||
1447 | tcg_temp_free(t0); | 1487 | tcg_temp_free(t0); |
1448 | } | 1488 | } |
1449 | 1489 | ||
@@ -7556,9 +7596,10 @@ static void decode_opc (CPUState *env, DisasContext *ctx) | @@ -7556,9 +7596,10 @@ static void decode_opc (CPUState *env, DisasContext *ctx) | ||
7556 | case OPC_SPECIAL: | 7596 | case OPC_SPECIAL: |
7557 | op1 = MASK_SPECIAL(ctx->opcode); | 7597 | op1 = MASK_SPECIAL(ctx->opcode); |
7558 | switch (op1) { | 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 | break; | 7603 | break; |
7563 | case OPC_MOVN: /* Conditional move */ | 7604 | case OPC_MOVN: /* Conditional move */ |
7564 | case OPC_MOVZ: | 7605 | case OPC_MOVZ: |
@@ -7648,12 +7689,14 @@ static void decode_opc (CPUState *env, DisasContext *ctx) | @@ -7648,12 +7689,14 @@ static void decode_opc (CPUState *env, DisasContext *ctx) | ||
7648 | #if defined(TARGET_MIPS64) | 7689 | #if defined(TARGET_MIPS64) |
7649 | /* MIPS64 specific opcodes */ | 7690 | /* MIPS64 specific opcodes */ |
7650 | case OPC_DSLL: | 7691 | case OPC_DSLL: |
7651 | - case OPC_DSRL ... OPC_DSRA: | 7692 | + case OPC_DSRA: |
7693 | + case OPC_DSRL: | ||
7652 | case OPC_DSLL32: | 7694 | case OPC_DSLL32: |
7653 | - case OPC_DSRL32 ... OPC_DSRA32: | 7695 | + case OPC_DSRA32: |
7696 | + case OPC_DSRL32: | ||
7654 | check_insn(env, ctx, ISA_MIPS3); | 7697 | check_insn(env, ctx, ISA_MIPS3); |
7655 | check_mips_64(ctx); | 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 | break; | 7700 | break; |
7658 | case OPC_DADD ... OPC_DSUBU: | 7701 | case OPC_DADD ... OPC_DSUBU: |
7659 | check_insn(env, ctx, ISA_MIPS3); | 7702 | check_insn(env, ctx, ISA_MIPS3); |
@@ -7928,9 +7971,20 @@ static void decode_opc (CPUState *env, DisasContext *ctx) | @@ -7928,9 +7971,20 @@ static void decode_opc (CPUState *env, DisasContext *ctx) | ||
7928 | break; | 7971 | break; |
7929 | } | 7972 | } |
7930 | break; | 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 | gen_arith_imm(env, ctx, op, rt, rs, imm); | 7976 | gen_arith_imm(env, ctx, op, rt, rs, imm); |
7933 | break; | 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 | case OPC_J ... OPC_JAL: /* Jump */ | 7988 | case OPC_J ... OPC_JAL: /* Jump */ |
7935 | offset = (int32_t)(ctx->opcode & 0x3FFFFFF) << 2; | 7989 | offset = (int32_t)(ctx->opcode & 0x3FFFFFF) << 2; |
7936 | gen_compute_branch(ctx, op, rs, rt, offset); | 7990 | gen_compute_branch(ctx, op, rs, rt, offset); |
@@ -8080,7 +8134,8 @@ static void decode_opc (CPUState *env, DisasContext *ctx) | @@ -8080,7 +8134,8 @@ static void decode_opc (CPUState *env, DisasContext *ctx) | ||
8080 | check_mips_64(ctx); | 8134 | check_mips_64(ctx); |
8081 | gen_ldst(ctx, op, rt, rs, imm); | 8135 | gen_ldst(ctx, op, rt, rs, imm); |
8082 | break; | 8136 | break; |
8083 | - case OPC_DADDI ... OPC_DADDIU: | 8137 | + case OPC_DADDI: |
8138 | + case OPC_DADDIU: | ||
8084 | check_insn(env, ctx, ISA_MIPS3); | 8139 | check_insn(env, ctx, ISA_MIPS3); |
8085 | check_mips_64(ctx); | 8140 | check_mips_64(ctx); |
8086 | gen_arith_imm(env, ctx, op, rt, rs, imm); | 8141 | gen_arith_imm(env, ctx, op, rt, rs, imm); |