Revision 161f85e6 target-mips/translate.c
b/target-mips/translate.c | ||
---|---|---|
267 | 267 |
OPC_MUL = 0x02 | OPC_SPECIAL2, |
268 | 268 |
OPC_MSUB = 0x04 | OPC_SPECIAL2, |
269 | 269 |
OPC_MSUBU = 0x05 | OPC_SPECIAL2, |
270 |
/* Loongson 2F */ |
|
271 |
OPC_MULT_G_2F = 0x10 | OPC_SPECIAL2, |
|
272 |
OPC_DMULT_G_2F = 0x11 | OPC_SPECIAL2, |
|
273 |
OPC_MULTU_G_2F = 0x12 | OPC_SPECIAL2, |
|
274 |
OPC_DMULTU_G_2F = 0x13 | OPC_SPECIAL2, |
|
275 |
OPC_DIV_G_2F = 0x14 | OPC_SPECIAL2, |
|
276 |
OPC_DDIV_G_2F = 0x15 | OPC_SPECIAL2, |
|
277 |
OPC_DIVU_G_2F = 0x16 | OPC_SPECIAL2, |
|
278 |
OPC_DDIVU_G_2F = 0x17 | OPC_SPECIAL2, |
|
279 |
OPC_MOD_G_2F = 0x1c | OPC_SPECIAL2, |
|
280 |
OPC_DMOD_G_2F = 0x1d | OPC_SPECIAL2, |
|
281 |
OPC_MODU_G_2F = 0x1e | OPC_SPECIAL2, |
|
282 |
OPC_DMODU_G_2F = 0x1f | OPC_SPECIAL2, |
|
270 | 283 |
/* Misc */ |
271 | 284 |
OPC_CLZ = 0x20 | OPC_SPECIAL2, |
272 | 285 |
OPC_CLO = 0x21 | OPC_SPECIAL2, |
... | ... | |
293 | 306 |
OPC_BSHFL = 0x20 | OPC_SPECIAL3, |
294 | 307 |
OPC_DBSHFL = 0x24 | OPC_SPECIAL3, |
295 | 308 |
OPC_RDHWR = 0x3B | OPC_SPECIAL3, |
309 |
|
|
310 |
/* Loongson 2E */ |
|
311 |
OPC_MULT_G_2E = 0x18 | OPC_SPECIAL3, |
|
312 |
OPC_MULTU_G_2E = 0x19 | OPC_SPECIAL3, |
|
313 |
OPC_DIV_G_2E = 0x1A | OPC_SPECIAL3, |
|
314 |
OPC_DIVU_G_2E = 0x1B | OPC_SPECIAL3, |
|
315 |
OPC_DMULT_G_2E = 0x1C | OPC_SPECIAL3, |
|
316 |
OPC_DMULTU_G_2E = 0x1D | OPC_SPECIAL3, |
|
317 |
OPC_DDIV_G_2E = 0x1E | OPC_SPECIAL3, |
|
318 |
OPC_DDIVU_G_2E = 0x1F | OPC_SPECIAL3, |
|
319 |
OPC_MOD_G_2E = 0x22 | OPC_SPECIAL3, |
|
320 |
OPC_MODU_G_2E = 0x23 | OPC_SPECIAL3, |
|
321 |
OPC_DMOD_G_2E = 0x26 | OPC_SPECIAL3, |
|
322 |
OPC_DMODU_G_2E = 0x27 | OPC_SPECIAL3, |
|
296 | 323 |
}; |
297 | 324 |
|
298 | 325 |
/* BSHFL opcodes */ |
... | ... | |
2325 | 2352 |
tcg_temp_free(t0); |
2326 | 2353 |
} |
2327 | 2354 |
|
2355 |
/* Godson integer instructions */ |
|
2356 |
static void gen_loongson_integer (DisasContext *ctx, uint32_t opc, |
|
2357 |
int rd, int rs, int rt) |
|
2358 |
{ |
|
2359 |
const char *opn = "loongson"; |
|
2360 |
TCGv t0, t1; |
|
2361 |
|
|
2362 |
if (rd == 0) { |
|
2363 |
/* Treat as NOP. */ |
|
2364 |
MIPS_DEBUG("NOP"); |
|
2365 |
return; |
|
2366 |
} |
|
2367 |
|
|
2368 |
switch (opc) { |
|
2369 |
case OPC_MULT_G_2E: |
|
2370 |
case OPC_MULT_G_2F: |
|
2371 |
case OPC_MULTU_G_2E: |
|
2372 |
case OPC_MULTU_G_2F: |
|
2373 |
#if defined(TARGET_MIPS64) |
|
2374 |
case OPC_DMULT_G_2E: |
|
2375 |
case OPC_DMULT_G_2F: |
|
2376 |
case OPC_DMULTU_G_2E: |
|
2377 |
case OPC_DMULTU_G_2F: |
|
2378 |
#endif |
|
2379 |
t0 = tcg_temp_new(); |
|
2380 |
t1 = tcg_temp_new(); |
|
2381 |
break; |
|
2382 |
default: |
|
2383 |
t0 = tcg_temp_local_new(); |
|
2384 |
t1 = tcg_temp_local_new(); |
|
2385 |
break; |
|
2386 |
} |
|
2387 |
|
|
2388 |
gen_load_gpr(t0, rs); |
|
2389 |
gen_load_gpr(t1, rt); |
|
2390 |
|
|
2391 |
switch (opc) { |
|
2392 |
case OPC_MULT_G_2E: |
|
2393 |
case OPC_MULT_G_2F: |
|
2394 |
tcg_gen_mul_tl(cpu_gpr[rd], t0, t1); |
|
2395 |
tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]); |
|
2396 |
opn = "mult.g"; |
|
2397 |
break; |
|
2398 |
case OPC_MULTU_G_2E: |
|
2399 |
case OPC_MULTU_G_2F: |
|
2400 |
tcg_gen_ext32u_tl(t0, t0); |
|
2401 |
tcg_gen_ext32u_tl(t1, t1); |
|
2402 |
tcg_gen_mul_tl(cpu_gpr[rd], t0, t1); |
|
2403 |
tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]); |
|
2404 |
opn = "multu.g"; |
|
2405 |
break; |
|
2406 |
case OPC_DIV_G_2E: |
|
2407 |
case OPC_DIV_G_2F: |
|
2408 |
{ |
|
2409 |
int l1 = gen_new_label(); |
|
2410 |
int l2 = gen_new_label(); |
|
2411 |
int l3 = gen_new_label(); |
|
2412 |
tcg_gen_ext32s_tl(t0, t0); |
|
2413 |
tcg_gen_ext32s_tl(t1, t1); |
|
2414 |
tcg_gen_brcondi_tl(TCG_COND_NE, t1, 0, l1); |
|
2415 |
tcg_gen_movi_tl(cpu_gpr[rd], 0); |
|
2416 |
tcg_gen_br(l3); |
|
2417 |
gen_set_label(l1); |
|
2418 |
tcg_gen_brcondi_tl(TCG_COND_NE, t0, INT_MIN, l2); |
|
2419 |
tcg_gen_brcondi_tl(TCG_COND_NE, t1, -1, l2); |
|
2420 |
tcg_gen_mov_tl(cpu_gpr[rd], t0); |
|
2421 |
tcg_gen_br(l3); |
|
2422 |
gen_set_label(l2); |
|
2423 |
tcg_gen_div_tl(cpu_gpr[rd], t0, t1); |
|
2424 |
tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]); |
|
2425 |
gen_set_label(l3); |
|
2426 |
} |
|
2427 |
opn = "div.g"; |
|
2428 |
break; |
|
2429 |
case OPC_DIVU_G_2E: |
|
2430 |
case OPC_DIVU_G_2F: |
|
2431 |
{ |
|
2432 |
int l1 = gen_new_label(); |
|
2433 |
int l2 = gen_new_label(); |
|
2434 |
tcg_gen_ext32u_tl(t0, t0); |
|
2435 |
tcg_gen_ext32u_tl(t1, t1); |
|
2436 |
tcg_gen_brcondi_tl(TCG_COND_NE, t1, 0, l1); |
|
2437 |
tcg_gen_movi_tl(cpu_gpr[rd], 0); |
|
2438 |
tcg_gen_br(l2); |
|
2439 |
gen_set_label(l1); |
|
2440 |
tcg_gen_divu_tl(cpu_gpr[rd], t0, t1); |
|
2441 |
tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]); |
|
2442 |
gen_set_label(l2); |
|
2443 |
} |
|
2444 |
opn = "divu.g"; |
|
2445 |
break; |
|
2446 |
case OPC_MOD_G_2E: |
|
2447 |
case OPC_MOD_G_2F: |
|
2448 |
{ |
|
2449 |
int l1 = gen_new_label(); |
|
2450 |
int l2 = gen_new_label(); |
|
2451 |
int l3 = gen_new_label(); |
|
2452 |
tcg_gen_ext32u_tl(t0, t0); |
|
2453 |
tcg_gen_ext32u_tl(t1, t1); |
|
2454 |
tcg_gen_brcondi_tl(TCG_COND_EQ, t1, 0, l1); |
|
2455 |
tcg_gen_brcondi_tl(TCG_COND_NE, t0, INT_MIN, l2); |
|
2456 |
tcg_gen_brcondi_tl(TCG_COND_NE, t1, -1, l2); |
|
2457 |
gen_set_label(l1); |
|
2458 |
tcg_gen_movi_tl(cpu_gpr[rd], 0); |
|
2459 |
tcg_gen_br(l3); |
|
2460 |
gen_set_label(l2); |
|
2461 |
tcg_gen_rem_tl(cpu_gpr[rd], t0, t1); |
|
2462 |
tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]); |
|
2463 |
gen_set_label(l3); |
|
2464 |
} |
|
2465 |
opn = "mod.g"; |
|
2466 |
break; |
|
2467 |
case OPC_MODU_G_2E: |
|
2468 |
case OPC_MODU_G_2F: |
|
2469 |
{ |
|
2470 |
int l1 = gen_new_label(); |
|
2471 |
int l2 = gen_new_label(); |
|
2472 |
tcg_gen_ext32u_tl(t0, t0); |
|
2473 |
tcg_gen_ext32u_tl(t1, t1); |
|
2474 |
tcg_gen_brcondi_tl(TCG_COND_NE, t1, 0, l1); |
|
2475 |
tcg_gen_movi_tl(cpu_gpr[rd], 0); |
|
2476 |
tcg_gen_br(l2); |
|
2477 |
gen_set_label(l1); |
|
2478 |
tcg_gen_remu_tl(cpu_gpr[rd], t0, t1); |
|
2479 |
tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]); |
|
2480 |
gen_set_label(l2); |
|
2481 |
} |
|
2482 |
opn = "modu.g"; |
|
2483 |
break; |
|
2484 |
#if defined(TARGET_MIPS64) |
|
2485 |
case OPC_DMULT_G_2E: |
|
2486 |
case OPC_DMULT_G_2F: |
|
2487 |
tcg_gen_mul_tl(cpu_gpr[rd], t0, t1); |
|
2488 |
opn = "dmult.g"; |
|
2489 |
break; |
|
2490 |
case OPC_DMULTU_G_2E: |
|
2491 |
case OPC_DMULTU_G_2F: |
|
2492 |
tcg_gen_mul_tl(cpu_gpr[rd], t0, t1); |
|
2493 |
opn = "dmultu.g"; |
|
2494 |
break; |
|
2495 |
case OPC_DDIV_G_2E: |
|
2496 |
case OPC_DDIV_G_2F: |
|
2497 |
{ |
|
2498 |
int l1 = gen_new_label(); |
|
2499 |
int l2 = gen_new_label(); |
|
2500 |
int l3 = gen_new_label(); |
|
2501 |
tcg_gen_brcondi_tl(TCG_COND_NE, t1, 0, l1); |
|
2502 |
tcg_gen_movi_tl(cpu_gpr[rd], 0); |
|
2503 |
tcg_gen_br(l3); |
|
2504 |
gen_set_label(l1); |
|
2505 |
tcg_gen_brcondi_tl(TCG_COND_NE, t0, -1LL << 63, l2); |
|
2506 |
tcg_gen_brcondi_tl(TCG_COND_NE, t1, -1LL, l2); |
|
2507 |
tcg_gen_mov_tl(cpu_gpr[rd], t0); |
|
2508 |
tcg_gen_br(l3); |
|
2509 |
gen_set_label(l2); |
|
2510 |
tcg_gen_div_tl(cpu_gpr[rd], t0, t1); |
|
2511 |
gen_set_label(l3); |
|
2512 |
} |
|
2513 |
opn = "ddiv.g"; |
|
2514 |
break; |
|
2515 |
case OPC_DDIVU_G_2E: |
|
2516 |
case OPC_DDIVU_G_2F: |
|
2517 |
{ |
|
2518 |
int l1 = gen_new_label(); |
|
2519 |
int l2 = gen_new_label(); |
|
2520 |
tcg_gen_brcondi_tl(TCG_COND_NE, t1, 0, l1); |
|
2521 |
tcg_gen_movi_tl(cpu_gpr[rd], 0); |
|
2522 |
tcg_gen_br(l2); |
|
2523 |
gen_set_label(l1); |
|
2524 |
tcg_gen_divu_tl(cpu_gpr[rd], t0, t1); |
|
2525 |
gen_set_label(l2); |
|
2526 |
} |
|
2527 |
opn = "ddivu.g"; |
|
2528 |
break; |
|
2529 |
case OPC_DMOD_G_2E: |
|
2530 |
case OPC_DMOD_G_2F: |
|
2531 |
{ |
|
2532 |
int l1 = gen_new_label(); |
|
2533 |
int l2 = gen_new_label(); |
|
2534 |
int l3 = gen_new_label(); |
|
2535 |
tcg_gen_brcondi_tl(TCG_COND_EQ, t1, 0, l1); |
|
2536 |
tcg_gen_brcondi_tl(TCG_COND_NE, t0, -1LL << 63, l2); |
|
2537 |
tcg_gen_brcondi_tl(TCG_COND_NE, t1, -1LL, l2); |
|
2538 |
gen_set_label(l1); |
|
2539 |
tcg_gen_movi_tl(cpu_gpr[rd], 0); |
|
2540 |
tcg_gen_br(l3); |
|
2541 |
gen_set_label(l2); |
|
2542 |
tcg_gen_rem_tl(cpu_gpr[rd], t0, t1); |
|
2543 |
gen_set_label(l3); |
|
2544 |
} |
|
2545 |
opn = "dmod.g"; |
|
2546 |
break; |
|
2547 |
case OPC_DMODU_G_2E: |
|
2548 |
case OPC_DMODU_G_2F: |
|
2549 |
{ |
|
2550 |
int l1 = gen_new_label(); |
|
2551 |
int l2 = gen_new_label(); |
|
2552 |
tcg_gen_brcondi_tl(TCG_COND_NE, t1, 0, l1); |
|
2553 |
tcg_gen_movi_tl(cpu_gpr[rd], 0); |
|
2554 |
tcg_gen_br(l2); |
|
2555 |
gen_set_label(l1); |
|
2556 |
tcg_gen_remu_tl(cpu_gpr[rd], t0, t1); |
|
2557 |
gen_set_label(l2); |
|
2558 |
} |
|
2559 |
opn = "dmodu.g"; |
|
2560 |
break; |
|
2561 |
#endif |
|
2562 |
} |
|
2563 |
|
|
2564 |
MIPS_DEBUG("%s %s, %s", opn, regnames[rd], regnames[rs]); |
|
2565 |
tcg_temp_free(t0); |
|
2566 |
tcg_temp_free(t1); |
|
2567 |
} |
|
2568 |
|
|
2328 | 2569 |
/* Traps */ |
2329 | 2570 |
static void gen_trap (DisasContext *ctx, uint32_t opc, |
2330 | 2571 |
int rs, int rt, int16_t imm) |
... | ... | |
11596 | 11837 |
} |
11597 | 11838 |
/* Treat as NOP. */ |
11598 | 11839 |
break; |
11840 |
case OPC_DIV_G_2F: |
|
11841 |
case OPC_DIVU_G_2F: |
|
11842 |
case OPC_MULT_G_2F: |
|
11843 |
case OPC_MULTU_G_2F: |
|
11844 |
case OPC_MOD_G_2F: |
|
11845 |
case OPC_MODU_G_2F: |
|
11846 |
check_insn(env, ctx, INSN_LOONGSON2F); |
|
11847 |
gen_loongson_integer(ctx, op1, rd, rs, rt); |
|
11848 |
break; |
|
11599 | 11849 |
#if defined(TARGET_MIPS64) |
11600 | 11850 |
case OPC_DCLO: |
11601 | 11851 |
case OPC_DCLZ: |
... | ... | |
11603 | 11853 |
check_mips_64(ctx); |
11604 | 11854 |
gen_cl(ctx, op1, rd, rs); |
11605 | 11855 |
break; |
11856 |
case OPC_DMULT_G_2F: |
|
11857 |
case OPC_DMULTU_G_2F: |
|
11858 |
case OPC_DDIV_G_2F: |
|
11859 |
case OPC_DDIVU_G_2F: |
|
11860 |
case OPC_DMOD_G_2F: |
|
11861 |
case OPC_DMODU_G_2F: |
|
11862 |
check_insn(env, ctx, INSN_LOONGSON2F); |
|
11863 |
gen_loongson_integer(ctx, op1, rd, rs, rt); |
|
11864 |
break; |
|
11606 | 11865 |
#endif |
11607 | 11866 |
default: /* Invalid */ |
11608 | 11867 |
MIPS_INVAL("special2"); |
... | ... | |
11651 | 11910 |
tcg_temp_free(t0); |
11652 | 11911 |
} |
11653 | 11912 |
break; |
11913 |
case OPC_DIV_G_2E ... OPC_DIVU_G_2E: |
|
11914 |
case OPC_MULT_G_2E ... OPC_MULTU_G_2E: |
|
11915 |
case OPC_MOD_G_2E ... OPC_MODU_G_2E: |
|
11916 |
check_insn(env, ctx, INSN_LOONGSON2E); |
|
11917 |
gen_loongson_integer(ctx, op1, rd, rs, rt); |
|
11918 |
break; |
|
11654 | 11919 |
#if defined(TARGET_MIPS64) |
11655 | 11920 |
case OPC_DEXTM ... OPC_DEXT: |
11656 | 11921 |
case OPC_DINSM ... OPC_DINS: |
... | ... | |
11664 | 11929 |
op2 = MASK_DBSHFL(ctx->opcode); |
11665 | 11930 |
gen_bshfl(ctx, op2, rt, rd); |
11666 | 11931 |
break; |
11932 |
case OPC_DDIV_G_2E ... OPC_DDIVU_G_2E: |
|
11933 |
case OPC_DMULT_G_2E ... OPC_DMULTU_G_2E: |
|
11934 |
case OPC_DMOD_G_2E ... OPC_DMODU_G_2E: |
|
11935 |
check_insn(env, ctx, INSN_LOONGSON2E); |
|
11936 |
gen_loongson_integer(ctx, op1, rd, rs, rt); |
|
11937 |
break; |
|
11667 | 11938 |
#endif |
11668 | 11939 |
default: /* Invalid */ |
11669 | 11940 |
MIPS_INVAL("special3"); |
Also available in: Unified diff