Revision 324d9e32

b/target-mips/translate.c
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 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 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 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 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 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 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 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 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 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 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);

Also available in: Unified diff