25 |
* SUCH DAMAGE. |
* SUCH DAMAGE. |
26 |
* |
* |
27 |
* |
* |
28 |
* $Id: cpu_mips_instr.c,v 1.97 2006/07/20 03:20:03 debug Exp $ |
* $Id: cpu_mips_instr.c,v 1.104 2006/08/14 17:45:47 debug Exp $ |
29 |
* |
* |
30 |
* MIPS instructions. |
* MIPS instructions. |
31 |
* |
* |
1679 |
uint32_t cause = cpu->cd.mips.coproc[0]->reg[COP0_CAUSE]; |
uint32_t cause = cpu->cd.mips.coproc[0]->reg[COP0_CAUSE]; |
1680 |
/* NOTE: STATUS_IE happens to match the enable bit also |
/* NOTE: STATUS_IE happens to match the enable bit also |
1681 |
on R2000/R3000, so this is ok. */ |
on R2000/R3000, so this is ok. */ |
1682 |
if (status & (STATUS_EXL | STATUS_ERL)) |
if (cpu->cd.mips.cpu_type.exc_model != EXC3K) { |
1683 |
status &= ~STATUS_IE; |
if (status & (STATUS_EXL | STATUS_ERL)) |
1684 |
|
status &= ~STATUS_IE; |
1685 |
|
} |
1686 |
/* Ugly R5900 special case: (TODO: move this?) */ |
/* Ugly R5900 special case: (TODO: move this?) */ |
1687 |
if (cpu->cd.mips.cpu_type.rev == MIPS_R5900 && |
if (cpu->cd.mips.cpu_type.rev == MIPS_R5900 && |
1688 |
!(status & R5900_STATUS_EIE)) |
!(status & R5900_STATUS_EIE)) |
1809 |
cpu->pc += (low_pc << MIPS_INSTR_ALIGNMENT_SHIFT); |
cpu->pc += (low_pc << MIPS_INSTR_ALIGNMENT_SHIFT); |
1810 |
mips_cpu_exception(cpu, EXCEPTION_BP, 0, 0, 0, 0, 0, 0); |
mips_cpu_exception(cpu, EXCEPTION_BP, 0, 0, 0, 0, 0, 0); |
1811 |
} |
} |
1812 |
|
X(reboot) |
1813 |
|
{ |
1814 |
|
cpu->running = 0; |
1815 |
|
debugger_n_steps_left_before_interaction = 0; |
1816 |
|
cpu->cd.mips.next_ic = ¬hing_call; |
1817 |
|
} |
1818 |
|
|
1819 |
|
|
1820 |
/* |
/* |
1960 |
|
|
1961 |
|
|
1962 |
/* |
/* |
1963 |
|
* wait: Wait for external interrupt. |
1964 |
|
*/ |
1965 |
|
X(wait) |
1966 |
|
{ |
1967 |
|
/* |
1968 |
|
* If there is an interrupt, then just return. Otherwise |
1969 |
|
* re-run the wait instruction (after a delay). |
1970 |
|
*/ |
1971 |
|
uint32_t status = cpu->cd.mips.coproc[0]->reg[COP0_STATUS]; |
1972 |
|
uint32_t cause = cpu->cd.mips.coproc[0]->reg[COP0_CAUSE]; |
1973 |
|
|
1974 |
|
/* NOTE: STATUS_IE happens to match the enable bit also |
1975 |
|
on R2000/R3000, so this is ok. */ |
1976 |
|
if (cpu->cd.mips.cpu_type.exc_model != EXC3K) { |
1977 |
|
if (status & (STATUS_EXL | STATUS_ERL)) |
1978 |
|
status &= ~STATUS_IE; |
1979 |
|
} |
1980 |
|
/* Ugly R5900 special case: (TODO: move this?) */ |
1981 |
|
if (cpu->cd.mips.cpu_type.rev == MIPS_R5900 && |
1982 |
|
!(status & R5900_STATUS_EIE)) |
1983 |
|
status &= ~STATUS_IE; |
1984 |
|
if (status & STATUS_IE && (status & cause & STATUS_IM_MASK)) |
1985 |
|
return; |
1986 |
|
|
1987 |
|
cpu->cd.mips.next_ic = ic; |
1988 |
|
cpu->is_halted = 1; |
1989 |
|
|
1990 |
|
/* |
1991 |
|
* There was no interrupt. Go to sleep. |
1992 |
|
* |
1993 |
|
* TODO: |
1994 |
|
* |
1995 |
|
* Think about how to actually implement this usleep stuff, |
1996 |
|
* in an SMP and/or timing accurate environment. |
1997 |
|
*/ |
1998 |
|
|
1999 |
|
if (cpu->machine->ncpus == 1) { |
2000 |
|
static int x = 0; |
2001 |
|
if ((++x) == 600) { |
2002 |
|
usleep(1); |
2003 |
|
x = 0; |
2004 |
|
} |
2005 |
|
cpu->n_translated_instrs += N_SAFE_DYNTRANS_LIMIT / 6; |
2006 |
|
} |
2007 |
|
} |
2008 |
|
|
2009 |
|
|
2010 |
|
/* |
2011 |
* rdhwr: Read hardware register into gpr (MIPS32/64 rev 2). |
* rdhwr: Read hardware register into gpr (MIPS32/64 rev 2). |
2012 |
* |
* |
2013 |
* arg[0] = ptr to rt (destination register) |
* arg[0] = ptr to rt (destination register) |
2437 |
if (cpu->delay_slot || page == NULL || (rX & 3) != 0 || rZ != 0) { |
if (cpu->delay_slot || page == NULL || (rX & 3) != 0 || rZ != 0) { |
2438 |
instr(addiu)(cpu, ic); |
instr(addiu)(cpu, ic); |
2439 |
return; |
return; |
2440 |
} |
} |
2441 |
|
|
2442 |
if (rYp == (uint64_t *) ic->arg[0]) |
if (rYp == (uint64_t *) ic->arg[0]) |
2443 |
rYp = (uint64_t *) ic[1].arg[1]; |
rYp = (uint64_t *) ic[1].arg[1]; |
2466 |
} |
} |
2467 |
|
|
2468 |
|
|
2469 |
|
#ifdef MODE32 |
2470 |
/* |
/* |
2471 |
* multi_sw_3: |
* multi_sw_2, _3, _4: |
2472 |
* |
* |
2473 |
* sw r?,ofs(rX) r?=arg[0], rX=arg[1], ofs=arg[2] |
* sw r?,ofs(rX) r?=arg[0], rX=arg[1], ofs=arg[2] |
|
* sw r?,ofs(rX) r?=arg[0], rX=arg[1], ofs=arg[2] |
|
|
* sw r?,ofs(rX) r?=arg[0], rX=arg[1], ofs=arg[2] |
|
2474 |
*/ |
*/ |
2475 |
|
X(multi_sw_2_le) |
2476 |
|
{ |
2477 |
|
uint32_t *page; |
2478 |
|
MODE_uint_t rX = reg(ic[0].arg[1]), r1, r2; |
2479 |
|
MODE_uint_t addr0 = rX + (int32_t)ic[0].arg[2]; |
2480 |
|
MODE_uint_t addr1 = rX + (int32_t)ic[1].arg[2]; |
2481 |
|
uint32_t index0 = addr0 >> 12, index1 = addr1 >> 12; |
2482 |
|
|
2483 |
|
page = (uint32_t *) cpu->cd.mips.host_store[index0]; |
2484 |
|
|
2485 |
|
/* Fallback: */ |
2486 |
|
if (cpu->delay_slot || |
2487 |
|
page == NULL || (addr0 & 3) != 0 || (addr1 & 3) != 0 || |
2488 |
|
index0 != index1) { |
2489 |
|
/* Normal safe sw: */ |
2490 |
|
mips32_loadstore[8 + 2 * 2](cpu, ic); |
2491 |
|
return; |
2492 |
|
} |
2493 |
|
|
2494 |
|
addr0 = (addr0 >> 2) & 0x3ff; |
2495 |
|
addr1 = (addr1 >> 2) & 0x3ff; |
2496 |
|
|
2497 |
|
r1 = reg(ic[0].arg[0]); |
2498 |
|
r2 = reg(ic[1].arg[0]); |
2499 |
|
|
2500 |
|
r1 = LE32_TO_HOST(r1); |
2501 |
|
r2 = LE32_TO_HOST(r2); |
2502 |
|
|
2503 |
|
page[addr0] = r1; |
2504 |
|
page[addr1] = r2; |
2505 |
|
|
2506 |
|
cpu->n_translated_instrs ++; |
2507 |
|
cpu->cd.mips.next_ic ++; |
2508 |
|
} |
2509 |
|
X(multi_sw_2_be) |
2510 |
|
{ |
2511 |
|
uint32_t *page; |
2512 |
|
MODE_uint_t rX = reg(ic[0].arg[1]), r1, r2; |
2513 |
|
MODE_uint_t addr0 = rX + (int32_t)ic[0].arg[2]; |
2514 |
|
MODE_uint_t addr1 = rX + (int32_t)ic[1].arg[2]; |
2515 |
|
uint32_t index0 = addr0 >> 12, index1 = addr1 >> 12; |
2516 |
|
|
2517 |
|
page = (uint32_t *) cpu->cd.mips.host_store[index0]; |
2518 |
|
|
2519 |
|
/* Fallback: */ |
2520 |
|
if (cpu->delay_slot || |
2521 |
|
page == NULL || (addr0 & 3) != 0 || (addr1 & 3) != 0 || |
2522 |
|
index0 != index1) { |
2523 |
|
/* Normal safe sw: */ |
2524 |
|
mips32_loadstore[16 + 8 + 2 * 2](cpu, ic); |
2525 |
|
return; |
2526 |
|
} |
2527 |
|
|
2528 |
|
addr0 = (addr0 >> 2) & 0x3ff; |
2529 |
|
addr1 = (addr1 >> 2) & 0x3ff; |
2530 |
|
|
2531 |
|
r1 = reg(ic[0].arg[0]); |
2532 |
|
r2 = reg(ic[1].arg[0]); |
2533 |
|
|
2534 |
|
r1 = BE32_TO_HOST(r1); |
2535 |
|
r2 = BE32_TO_HOST(r2); |
2536 |
|
|
2537 |
|
page[addr0] = r1; |
2538 |
|
page[addr1] = r2; |
2539 |
|
|
2540 |
|
cpu->n_translated_instrs ++; |
2541 |
|
cpu->cd.mips.next_ic ++; |
2542 |
|
} |
2543 |
X(multi_sw_3_le) |
X(multi_sw_3_le) |
2544 |
{ |
{ |
2545 |
uint32_t *page; |
uint32_t *page; |
2557 |
page == NULL || (addr0 & 3) != 0 || (addr1 & 3) != 0 || |
page == NULL || (addr0 & 3) != 0 || (addr1 & 3) != 0 || |
2558 |
(addr2 & 3) != 0 || index0 != index1 || index0 != index2) { |
(addr2 & 3) != 0 || index0 != index1 || index0 != index2) { |
2559 |
/* Normal safe sw: */ |
/* Normal safe sw: */ |
2560 |
ic[1].f(cpu, ic); |
mips32_loadstore[8 + 2 * 2](cpu, ic); |
2561 |
return; |
return; |
2562 |
} |
} |
2563 |
|
|
2581 |
page[addr2] = r3; |
page[addr2] = r3; |
2582 |
|
|
2583 |
cpu->n_translated_instrs += 2; |
cpu->n_translated_instrs += 2; |
2584 |
cpu->cd.mips.next_ic = (struct mips_instr_call *) &ic[3]; |
cpu->cd.mips.next_ic += 2; |
2585 |
} |
} |
2586 |
X(multi_sw_3_be) |
X(multi_sw_3_be) |
2587 |
{ |
{ |
2600 |
page == NULL || (addr0 & 3) != 0 || (addr1 & 3) != 0 || |
page == NULL || (addr0 & 3) != 0 || (addr1 & 3) != 0 || |
2601 |
(addr2 & 3) != 0 || index0 != index1 || index0 != index2) { |
(addr2 & 3) != 0 || index0 != index1 || index0 != index2) { |
2602 |
/* Normal safe sw: */ |
/* Normal safe sw: */ |
2603 |
ic[1].f(cpu, ic); |
mips32_loadstore[16 + 8 + 2 * 2](cpu, ic); |
2604 |
return; |
return; |
2605 |
} |
} |
2606 |
|
|
2624 |
page[addr2] = r3; |
page[addr2] = r3; |
2625 |
|
|
2626 |
cpu->n_translated_instrs += 2; |
cpu->n_translated_instrs += 2; |
2627 |
cpu->cd.mips.next_ic = (struct mips_instr_call *) &ic[3]; |
cpu->cd.mips.next_ic += 2; |
2628 |
|
} |
2629 |
|
X(multi_sw_4_le) |
2630 |
|
{ |
2631 |
|
uint32_t *page; |
2632 |
|
MODE_uint_t rX = reg(ic[0].arg[1]), r1, r2, r3, r4; |
2633 |
|
MODE_uint_t addr0 = rX + (int32_t)ic[0].arg[2]; |
2634 |
|
MODE_uint_t addr1 = rX + (int32_t)ic[1].arg[2]; |
2635 |
|
MODE_uint_t addr2 = rX + (int32_t)ic[2].arg[2]; |
2636 |
|
MODE_uint_t addr3 = rX + (int32_t)ic[3].arg[2]; |
2637 |
|
uint32_t index0 = addr0 >> 12, index1 = addr1 >> 12, |
2638 |
|
index2 = addr2 >> 12, index3 = addr3 >> 12; |
2639 |
|
|
2640 |
|
page = (uint32_t *) cpu->cd.mips.host_store[index0]; |
2641 |
|
|
2642 |
|
/* Fallback: */ |
2643 |
|
if (cpu->delay_slot || |
2644 |
|
page == NULL || (addr0 & 3) != 0 || (addr1 & 3) != 0 || |
2645 |
|
(addr2 & 3) != 0 || (addr3 & 3) != 0 || index0 != index1 || |
2646 |
|
index0 != index2 || index0 != index3) { |
2647 |
|
/* Normal safe sw: */ |
2648 |
|
mips32_loadstore[8 + 2 * 2](cpu, ic); |
2649 |
|
return; |
2650 |
|
} |
2651 |
|
|
2652 |
|
addr0 = (addr0 >> 2) & 0x3ff; |
2653 |
|
addr1 = (addr1 >> 2) & 0x3ff; |
2654 |
|
addr2 = (addr2 >> 2) & 0x3ff; |
2655 |
|
addr3 = (addr3 >> 2) & 0x3ff; |
2656 |
|
|
2657 |
|
r1 = reg(ic[0].arg[0]); |
2658 |
|
r2 = reg(ic[1].arg[0]); |
2659 |
|
r3 = reg(ic[2].arg[0]); |
2660 |
|
r4 = reg(ic[3].arg[0]); |
2661 |
|
|
2662 |
|
r1 = LE32_TO_HOST(r1); |
2663 |
|
r2 = LE32_TO_HOST(r2); |
2664 |
|
r3 = LE32_TO_HOST(r3); |
2665 |
|
r4 = LE32_TO_HOST(r4); |
2666 |
|
|
2667 |
|
page[addr0] = r1; |
2668 |
|
page[addr1] = r2; |
2669 |
|
page[addr2] = r3; |
2670 |
|
page[addr3] = r4; |
2671 |
|
|
2672 |
|
cpu->n_translated_instrs += 3; |
2673 |
|
cpu->cd.mips.next_ic += 3; |
2674 |
|
} |
2675 |
|
X(multi_sw_4_be) |
2676 |
|
{ |
2677 |
|
uint32_t *page; |
2678 |
|
MODE_uint_t rX = reg(ic[0].arg[1]), r1, r2, r3, r4; |
2679 |
|
MODE_uint_t addr0 = rX + (int32_t)ic[0].arg[2]; |
2680 |
|
MODE_uint_t addr1 = rX + (int32_t)ic[1].arg[2]; |
2681 |
|
MODE_uint_t addr2 = rX + (int32_t)ic[2].arg[2]; |
2682 |
|
MODE_uint_t addr3 = rX + (int32_t)ic[3].arg[2]; |
2683 |
|
uint32_t index0 = addr0 >> 12, index1 = addr1 >> 12, |
2684 |
|
index2 = addr2 >> 12, index3 = addr3 >> 12; |
2685 |
|
|
2686 |
|
page = (uint32_t *) cpu->cd.mips.host_store[index0]; |
2687 |
|
|
2688 |
|
/* Fallback: */ |
2689 |
|
if (cpu->delay_slot || |
2690 |
|
page == NULL || (addr0 & 3) != 0 || (addr1 & 3) != 0 || |
2691 |
|
(addr2 & 3) != 0 || (addr3 & 3) != 0 || index0 != index1 || |
2692 |
|
index0 != index2 || index0 != index3) { |
2693 |
|
/* Normal safe sw: */ |
2694 |
|
mips32_loadstore[16 + 8 + 2 * 2](cpu, ic); |
2695 |
|
return; |
2696 |
|
} |
2697 |
|
|
2698 |
|
addr0 = (addr0 >> 2) & 0x3ff; |
2699 |
|
addr1 = (addr1 >> 2) & 0x3ff; |
2700 |
|
addr2 = (addr2 >> 2) & 0x3ff; |
2701 |
|
addr3 = (addr3 >> 2) & 0x3ff; |
2702 |
|
|
2703 |
|
r1 = reg(ic[0].arg[0]); |
2704 |
|
r2 = reg(ic[1].arg[0]); |
2705 |
|
r3 = reg(ic[2].arg[0]); |
2706 |
|
r4 = reg(ic[3].arg[0]); |
2707 |
|
|
2708 |
|
r1 = BE32_TO_HOST(r1); |
2709 |
|
r2 = BE32_TO_HOST(r2); |
2710 |
|
r3 = BE32_TO_HOST(r3); |
2711 |
|
r4 = BE32_TO_HOST(r4); |
2712 |
|
|
2713 |
|
page[addr0] = r1; |
2714 |
|
page[addr1] = r2; |
2715 |
|
page[addr2] = r3; |
2716 |
|
page[addr3] = r4; |
2717 |
|
|
2718 |
|
cpu->n_translated_instrs += 3; |
2719 |
|
cpu->cd.mips.next_ic += 3; |
2720 |
|
} |
2721 |
|
#endif |
2722 |
|
|
2723 |
|
|
2724 |
|
#ifdef MODE32 |
2725 |
|
/* |
2726 |
|
* multi_lw_2, _3, _4: |
2727 |
|
* |
2728 |
|
* lw r?,ofs(rX) r?=arg[0], rX=arg[1], ofs=arg[2] |
2729 |
|
*/ |
2730 |
|
X(multi_lw_2_le) |
2731 |
|
{ |
2732 |
|
uint32_t *page; |
2733 |
|
MODE_uint_t rX = reg(ic[0].arg[1]), r1, r2; |
2734 |
|
MODE_uint_t addr0 = rX + (int32_t)ic[0].arg[2]; |
2735 |
|
MODE_uint_t addr1 = rX + (int32_t)ic[1].arg[2]; |
2736 |
|
uint32_t index0 = addr0 >> 12, index1 = addr1 >> 12; |
2737 |
|
|
2738 |
|
page = (uint32_t *) cpu->cd.mips.host_load[index0]; |
2739 |
|
|
2740 |
|
/* Fallback: */ |
2741 |
|
if (cpu->delay_slot || |
2742 |
|
page == NULL || (addr0 & 3) != 0 || (addr1 & 3) != 0 || |
2743 |
|
index0 != index1) { |
2744 |
|
/* Normal safe lw: */ |
2745 |
|
mips32_loadstore[2 * 2 + 1](cpu, ic); |
2746 |
|
return; |
2747 |
|
} |
2748 |
|
|
2749 |
|
addr0 = (addr0 >> 2) & 0x3ff; |
2750 |
|
addr1 = (addr1 >> 2) & 0x3ff; |
2751 |
|
|
2752 |
|
r1 = page[addr0]; |
2753 |
|
r2 = page[addr1]; |
2754 |
|
|
2755 |
|
r1 = LE32_TO_HOST(r1); |
2756 |
|
r2 = LE32_TO_HOST(r2); |
2757 |
|
|
2758 |
|
reg(ic[0].arg[0]) = r1; |
2759 |
|
reg(ic[1].arg[0]) = r2; |
2760 |
|
|
2761 |
|
cpu->n_translated_instrs ++; |
2762 |
|
cpu->cd.mips.next_ic ++; |
2763 |
|
} |
2764 |
|
X(multi_lw_2_be) |
2765 |
|
{ |
2766 |
|
uint32_t *page; |
2767 |
|
MODE_uint_t rX = reg(ic[0].arg[1]), r1, r2; |
2768 |
|
MODE_uint_t addr0 = rX + (int32_t)ic[0].arg[2]; |
2769 |
|
MODE_uint_t addr1 = rX + (int32_t)ic[1].arg[2]; |
2770 |
|
uint32_t index0 = addr0 >> 12, index1 = addr1 >> 12; |
2771 |
|
|
2772 |
|
page = (uint32_t *) cpu->cd.mips.host_load[index0]; |
2773 |
|
|
2774 |
|
/* Fallback: */ |
2775 |
|
if (cpu->delay_slot || |
2776 |
|
page == NULL || (addr0 & 3) != 0 || (addr1 & 3) != 0 || |
2777 |
|
index0 != index1) { |
2778 |
|
/* Normal safe lw: */ |
2779 |
|
mips32_loadstore[16 + 2 * 2 + 1](cpu, ic); |
2780 |
|
return; |
2781 |
|
} |
2782 |
|
|
2783 |
|
addr0 = (addr0 >> 2) & 0x3ff; |
2784 |
|
addr1 = (addr1 >> 2) & 0x3ff; |
2785 |
|
|
2786 |
|
r1 = page[addr0]; |
2787 |
|
r2 = page[addr1]; |
2788 |
|
|
2789 |
|
r1 = BE32_TO_HOST(r1); |
2790 |
|
r2 = BE32_TO_HOST(r2); |
2791 |
|
|
2792 |
|
reg(ic[0].arg[0]) = r1; |
2793 |
|
reg(ic[1].arg[0]) = r2; |
2794 |
|
|
2795 |
|
cpu->n_translated_instrs ++; |
2796 |
|
cpu->cd.mips.next_ic ++; |
2797 |
|
} |
2798 |
|
X(multi_lw_3_le) |
2799 |
|
{ |
2800 |
|
uint32_t *page; |
2801 |
|
MODE_uint_t rX = reg(ic[0].arg[1]), r1, r2, r3; |
2802 |
|
MODE_uint_t addr0 = rX + (int32_t)ic[0].arg[2]; |
2803 |
|
MODE_uint_t addr1 = rX + (int32_t)ic[1].arg[2]; |
2804 |
|
MODE_uint_t addr2 = rX + (int32_t)ic[2].arg[2]; |
2805 |
|
uint32_t index0 = addr0 >> 12, index1 = addr1 >> 12, |
2806 |
|
index2 = addr2 >> 12; |
2807 |
|
|
2808 |
|
page = (uint32_t *) cpu->cd.mips.host_load[index0]; |
2809 |
|
|
2810 |
|
/* Fallback: */ |
2811 |
|
if (cpu->delay_slot || |
2812 |
|
page == NULL || (addr0 & 3) != 0 || (addr1 & 3) != 0 || |
2813 |
|
(addr2 & 3) != 0 || index0 != index1 || index0 != index2) { |
2814 |
|
/* Normal safe lw: */ |
2815 |
|
mips32_loadstore[2 * 2 + 1](cpu, ic); |
2816 |
|
return; |
2817 |
|
} |
2818 |
|
|
2819 |
|
addr0 = (addr0 >> 2) & 0x3ff; |
2820 |
|
addr1 = (addr1 >> 2) & 0x3ff; |
2821 |
|
addr2 = (addr2 >> 2) & 0x3ff; |
2822 |
|
|
2823 |
|
/* printf("addr0=%x 1=%x 2=%x\n", |
2824 |
|
(int)addr0, (int)addr1, (int)addr2); */ |
2825 |
|
|
2826 |
|
r1 = page[addr0]; |
2827 |
|
r2 = page[addr1]; |
2828 |
|
r3 = page[addr2]; |
2829 |
|
|
2830 |
|
r1 = LE32_TO_HOST(r1); |
2831 |
|
r2 = LE32_TO_HOST(r2); |
2832 |
|
r3 = LE32_TO_HOST(r3); |
2833 |
|
|
2834 |
|
reg(ic[0].arg[0]) = r1; |
2835 |
|
reg(ic[1].arg[0]) = r2; |
2836 |
|
reg(ic[2].arg[0]) = r3; |
2837 |
|
|
2838 |
|
cpu->n_translated_instrs += 2; |
2839 |
|
cpu->cd.mips.next_ic += 2; |
2840 |
|
} |
2841 |
|
X(multi_lw_3_be) |
2842 |
|
{ |
2843 |
|
uint32_t *page; |
2844 |
|
MODE_uint_t rX = reg(ic[0].arg[1]), r1, r2, r3; |
2845 |
|
MODE_uint_t addr0 = rX + (int32_t)ic[0].arg[2]; |
2846 |
|
MODE_uint_t addr1 = rX + (int32_t)ic[1].arg[2]; |
2847 |
|
MODE_uint_t addr2 = rX + (int32_t)ic[2].arg[2]; |
2848 |
|
uint32_t index0 = addr0 >> 12, index1 = addr1 >> 12, |
2849 |
|
index2 = addr2 >> 12; |
2850 |
|
|
2851 |
|
page = (uint32_t *) cpu->cd.mips.host_load[index0]; |
2852 |
|
|
2853 |
|
/* Fallback: */ |
2854 |
|
if (cpu->delay_slot || |
2855 |
|
page == NULL || (addr0 & 3) != 0 || (addr1 & 3) != 0 || |
2856 |
|
(addr2 & 3) != 0 || index0 != index1 || index0 != index2) { |
2857 |
|
/* Normal safe lw: */ |
2858 |
|
mips32_loadstore[16 + 2 * 2 + 1](cpu, ic); |
2859 |
|
return; |
2860 |
|
} |
2861 |
|
|
2862 |
|
addr0 = (addr0 >> 2) & 0x3ff; |
2863 |
|
addr1 = (addr1 >> 2) & 0x3ff; |
2864 |
|
addr2 = (addr2 >> 2) & 0x3ff; |
2865 |
|
|
2866 |
|
/* printf("addr0=%x 1=%x 2=%x\n", |
2867 |
|
(int)addr0, (int)addr1, (int)addr2); */ |
2868 |
|
|
2869 |
|
r1 = page[addr0]; |
2870 |
|
r2 = page[addr1]; |
2871 |
|
r3 = page[addr2]; |
2872 |
|
|
2873 |
|
r1 = BE32_TO_HOST(r1); |
2874 |
|
r2 = BE32_TO_HOST(r2); |
2875 |
|
r3 = BE32_TO_HOST(r3); |
2876 |
|
|
2877 |
|
reg(ic[0].arg[0]) = r1; |
2878 |
|
reg(ic[1].arg[0]) = r2; |
2879 |
|
reg(ic[2].arg[0]) = r3; |
2880 |
|
|
2881 |
|
cpu->n_translated_instrs += 2; |
2882 |
|
cpu->cd.mips.next_ic += 2; |
2883 |
|
} |
2884 |
|
X(multi_lw_4_le) |
2885 |
|
{ |
2886 |
|
uint32_t *page; |
2887 |
|
MODE_uint_t rX = reg(ic[0].arg[1]), r1, r2, r3, r4; |
2888 |
|
MODE_uint_t addr0 = rX + (int32_t)ic[0].arg[2]; |
2889 |
|
MODE_uint_t addr1 = rX + (int32_t)ic[1].arg[2]; |
2890 |
|
MODE_uint_t addr2 = rX + (int32_t)ic[2].arg[2]; |
2891 |
|
MODE_uint_t addr3 = rX + (int32_t)ic[3].arg[2]; |
2892 |
|
uint32_t index0 = addr0 >> 12, index1 = addr1 >> 12, |
2893 |
|
index2 = addr2 >> 12, index3 = addr3 >> 12; |
2894 |
|
|
2895 |
|
page = (uint32_t *) cpu->cd.mips.host_load[index0]; |
2896 |
|
|
2897 |
|
/* Fallback: */ |
2898 |
|
if (cpu->delay_slot || |
2899 |
|
page == NULL || (addr0 & 3) != 0 || (addr1 & 3) != 0 || |
2900 |
|
(addr2 & 3) != 0 || (addr3 & 3) != 0 || |
2901 |
|
index0 != index1 || index0 != index2 || index0 != index3) { |
2902 |
|
/* Normal safe lw: */ |
2903 |
|
mips32_loadstore[2 * 2 + 1](cpu, ic); |
2904 |
|
return; |
2905 |
|
} |
2906 |
|
|
2907 |
|
addr0 = (addr0 >> 2) & 0x3ff; |
2908 |
|
addr1 = (addr1 >> 2) & 0x3ff; |
2909 |
|
addr2 = (addr2 >> 2) & 0x3ff; |
2910 |
|
addr3 = (addr3 >> 2) & 0x3ff; |
2911 |
|
|
2912 |
|
r1 = page[addr0]; |
2913 |
|
r2 = page[addr1]; |
2914 |
|
r3 = page[addr2]; |
2915 |
|
r4 = page[addr3]; |
2916 |
|
|
2917 |
|
r1 = LE32_TO_HOST(r1); |
2918 |
|
r2 = LE32_TO_HOST(r2); |
2919 |
|
r3 = LE32_TO_HOST(r3); |
2920 |
|
r4 = LE32_TO_HOST(r4); |
2921 |
|
|
2922 |
|
reg(ic[0].arg[0]) = r1; |
2923 |
|
reg(ic[1].arg[0]) = r2; |
2924 |
|
reg(ic[2].arg[0]) = r3; |
2925 |
|
reg(ic[3].arg[0]) = r4; |
2926 |
|
|
2927 |
|
cpu->n_translated_instrs += 3; |
2928 |
|
cpu->cd.mips.next_ic += 3; |
2929 |
|
} |
2930 |
|
X(multi_lw_4_be) |
2931 |
|
{ |
2932 |
|
uint32_t *page; |
2933 |
|
MODE_uint_t rX = reg(ic[0].arg[1]), r1, r2, r3, r4; |
2934 |
|
MODE_uint_t addr0 = rX + (int32_t)ic[0].arg[2]; |
2935 |
|
MODE_uint_t addr1 = rX + (int32_t)ic[1].arg[2]; |
2936 |
|
MODE_uint_t addr2 = rX + (int32_t)ic[2].arg[2]; |
2937 |
|
MODE_uint_t addr3 = rX + (int32_t)ic[3].arg[2]; |
2938 |
|
uint32_t index0 = addr0 >> 12, index1 = addr1 >> 12, |
2939 |
|
index2 = addr2 >> 12, index3 = addr3 >> 12; |
2940 |
|
|
2941 |
|
page = (uint32_t *) cpu->cd.mips.host_load[index0]; |
2942 |
|
|
2943 |
|
/* Fallback: */ |
2944 |
|
if (cpu->delay_slot || |
2945 |
|
page == NULL || (addr0 & 3) != 0 || (addr1 & 3) != 0 || |
2946 |
|
(addr2 & 3) != 0 || (addr3 & 3) != 0 || |
2947 |
|
index0 != index1 || index0 != index2 || index0 != index3) { |
2948 |
|
/* Normal safe lw: */ |
2949 |
|
mips32_loadstore[16 + 2 * 2 + 1](cpu, ic); |
2950 |
|
return; |
2951 |
|
} |
2952 |
|
|
2953 |
|
addr0 = (addr0 >> 2) & 0x3ff; |
2954 |
|
addr1 = (addr1 >> 2) & 0x3ff; |
2955 |
|
addr2 = (addr2 >> 2) & 0x3ff; |
2956 |
|
addr3 = (addr3 >> 2) & 0x3ff; |
2957 |
|
|
2958 |
|
r1 = page[addr0]; |
2959 |
|
r2 = page[addr1]; |
2960 |
|
r3 = page[addr2]; |
2961 |
|
r4 = page[addr3]; |
2962 |
|
|
2963 |
|
r1 = BE32_TO_HOST(r1); |
2964 |
|
r2 = BE32_TO_HOST(r2); |
2965 |
|
r3 = BE32_TO_HOST(r3); |
2966 |
|
r4 = BE32_TO_HOST(r4); |
2967 |
|
|
2968 |
|
reg(ic[0].arg[0]) = r1; |
2969 |
|
reg(ic[1].arg[0]) = r2; |
2970 |
|
reg(ic[2].arg[0]) = r3; |
2971 |
|
reg(ic[3].arg[0]) = r4; |
2972 |
|
|
2973 |
|
cpu->n_translated_instrs += 3; |
2974 |
|
cpu->cd.mips.next_ic += 3; |
2975 |
|
} |
2976 |
|
#endif |
2977 |
|
|
2978 |
|
|
2979 |
|
/* |
2980 |
|
* multi_addu_3: |
2981 |
|
*/ |
2982 |
|
X(multi_addu_3) |
2983 |
|
{ |
2984 |
|
/* Fallback: */ |
2985 |
|
if (cpu->delay_slot) { |
2986 |
|
instr(addu)(cpu, ic); |
2987 |
|
return; |
2988 |
|
} |
2989 |
|
|
2990 |
|
reg(ic[0].arg[2]) = (int32_t)(reg(ic[0].arg[0]) + reg(ic[0].arg[1])); |
2991 |
|
reg(ic[1].arg[2]) = (int32_t)(reg(ic[1].arg[0]) + reg(ic[1].arg[1])); |
2992 |
|
reg(ic[2].arg[2]) = (int32_t)(reg(ic[2].arg[0]) + reg(ic[2].arg[1])); |
2993 |
|
cpu->n_translated_instrs += 2; |
2994 |
|
cpu->cd.mips.next_ic += 2; |
2995 |
} |
} |
2996 |
|
|
2997 |
|
|
3082 |
|
|
3083 |
|
|
3084 |
/* |
/* |
3085 |
* lui_32bit: |
* addiu_bne_samepage_addiu: |
|
* |
|
|
* Combination of lui and addiu. |
|
|
* Note: All 32 bits of arg[2] of the lui instr_call are used. |
|
3086 |
*/ |
*/ |
3087 |
X(lui_32bit) |
X(addiu_bne_samepage_addiu) |
3088 |
{ |
{ |
3089 |
reg(ic[0].arg[0]) = (int32_t) ic[0].arg[2]; |
MODE_uint_t rs, rt; |
3090 |
|
|
3091 |
|
if (cpu->delay_slot) { |
3092 |
|
instr(addiu)(cpu, ic); |
3093 |
|
return; |
3094 |
|
} |
3095 |
|
|
3096 |
|
cpu->n_translated_instrs += 2; |
3097 |
|
reg(ic[0].arg[1]) = (int32_t) |
3098 |
|
((int32_t)reg(ic[0].arg[0]) + (int32_t)ic[0].arg[2]); |
3099 |
|
rs = reg(ic[1].arg[0]); |
3100 |
|
rt = reg(ic[1].arg[1]); |
3101 |
|
reg(ic[2].arg[1]) = (int32_t) |
3102 |
|
((int32_t)reg(ic[2].arg[0]) + (int32_t)ic[2].arg[2]); |
3103 |
|
if (rs != rt) |
3104 |
|
cpu->cd.mips.next_ic = (struct mips_instr_call *) ic[1].arg[2]; |
3105 |
|
else |
3106 |
|
cpu->cd.mips.next_ic += 2; |
3107 |
|
} |
3108 |
|
|
3109 |
|
|
3110 |
|
/* |
3111 |
|
* xor_andi_sll: |
3112 |
|
*/ |
3113 |
|
X(xor_andi_sll) |
3114 |
|
{ |
3115 |
|
/* Fallback: */ |
3116 |
|
if (cpu->delay_slot) { |
3117 |
|
instr(xor)(cpu, ic); |
3118 |
|
return; |
3119 |
|
} |
3120 |
|
|
3121 |
|
reg(ic[0].arg[2]) = reg(ic[0].arg[0]) ^ reg(ic[0].arg[1]); |
3122 |
|
reg(ic[1].arg[1]) = reg(ic[1].arg[0]) & (uint32_t)ic[1].arg[2]; |
3123 |
|
reg(ic[2].arg[2]) = (int32_t)(reg(ic[2].arg[0])<<(int32_t)ic[2].arg[1]); |
3124 |
|
|
3125 |
|
cpu->n_translated_instrs += 2; |
3126 |
|
cpu->cd.mips.next_ic += 2; |
3127 |
|
} |
3128 |
|
|
3129 |
|
|
3130 |
|
/* |
3131 |
|
* andi_sll: |
3132 |
|
*/ |
3133 |
|
X(andi_sll) |
3134 |
|
{ |
3135 |
|
/* Fallback: */ |
3136 |
|
if (cpu->delay_slot) { |
3137 |
|
instr(andi)(cpu, ic); |
3138 |
|
return; |
3139 |
|
} |
3140 |
|
|
3141 |
|
reg(ic[0].arg[1]) = reg(ic[0].arg[0]) & (uint32_t)ic[0].arg[2]; |
3142 |
|
reg(ic[1].arg[2]) = (int32_t)(reg(ic[1].arg[0])<<(int32_t)ic[1].arg[1]); |
3143 |
|
|
3144 |
|
cpu->n_translated_instrs ++; |
3145 |
|
cpu->cd.mips.next_ic ++; |
3146 |
|
} |
3147 |
|
|
3148 |
|
|
3149 |
|
/* |
3150 |
|
* lui_ori: |
3151 |
|
*/ |
3152 |
|
X(lui_ori) |
3153 |
|
{ |
3154 |
|
/* Fallback: */ |
3155 |
|
if (cpu->delay_slot) { |
3156 |
|
instr(set)(cpu, ic); |
3157 |
|
return; |
3158 |
|
} |
3159 |
|
|
3160 |
|
reg(ic[0].arg[0]) = (int32_t)ic[0].arg[1]; |
3161 |
|
reg(ic[1].arg[1]) = reg(ic[1].arg[0]) | (uint32_t)ic[1].arg[2]; |
3162 |
|
|
3163 |
|
cpu->n_translated_instrs ++; |
3164 |
|
cpu->cd.mips.next_ic ++; |
3165 |
|
} |
3166 |
|
|
3167 |
|
|
3168 |
|
/* |
3169 |
|
* lui_addiu: |
3170 |
|
*/ |
3171 |
|
X(lui_addiu) |
3172 |
|
{ |
3173 |
|
/* Fallback: */ |
3174 |
|
if (cpu->delay_slot) { |
3175 |
|
instr(set)(cpu, ic); |
3176 |
|
return; |
3177 |
|
} |
3178 |
|
|
3179 |
|
reg(ic[0].arg[0]) = (int32_t)ic[0].arg[1]; |
3180 |
|
reg(ic[1].arg[1]) = (int32_t) |
3181 |
|
((int32_t)reg(ic[1].arg[0]) + (int32_t)ic[1].arg[2]); |
3182 |
|
|
3183 |
cpu->n_translated_instrs ++; |
cpu->n_translated_instrs ++; |
3184 |
cpu->cd.mips.next_ic ++; |
cpu->cd.mips.next_ic ++; |
3185 |
} |
} |
3319 |
ic[0].arg[0] != ic[0].arg[1] && |
ic[0].arg[0] != ic[0].arg[1] && |
3320 |
ic[0].arg[1] == ic[-2].arg[0] && (int32_t)ic[0].arg[2] == -4) { |
ic[0].arg[1] == ic[-2].arg[0] && (int32_t)ic[0].arg[2] == -4) { |
3321 |
ic[-2].f = instr(sw_loop); |
ic[-2].f = instr(sw_loop); |
|
combined; |
|
3322 |
} |
} |
3323 |
} |
} |
3324 |
|
|
3325 |
|
|
3326 |
|
/* Only for 32-bit virtual address translation so far. */ |
3327 |
|
#ifdef MODE32 |
3328 |
/* |
/* |
3329 |
* Combine: Multiple SW in a row using the same base register |
* Combine: Multiple SW in a row using the same base register |
3330 |
* |
* |
3339 |
int n_back = (low_addr >> MIPS_INSTR_ALIGNMENT_SHIFT) |
int n_back = (low_addr >> MIPS_INSTR_ALIGNMENT_SHIFT) |
3340 |
& (MIPS_IC_ENTRIES_PER_PAGE - 1); |
& (MIPS_IC_ENTRIES_PER_PAGE - 1); |
3341 |
|
|
3342 |
/* Only for 32-bit virtual address translation so far. */ |
if (n_back < 3) |
|
if (!cpu->is_32bit) |
|
3343 |
return; |
return; |
3344 |
|
|
3345 |
if (n_back < 4) |
/* Convert a multi_sw_3 to a multi_sw_4: */ |
3346 |
return; |
if ((ic[-3].f == instr(multi_sw_3_be) || |
3347 |
|
ic[-3].f == instr(multi_sw_3_le)) && |
3348 |
|
ic[-3].arg[1] == ic[0].arg[1]) { |
3349 |
|
if (cpu->byte_order == EMUL_LITTLE_ENDIAN) |
3350 |
|
ic[-3].f = instr(multi_sw_4_le); |
3351 |
|
else |
3352 |
|
ic[-3].f = instr(multi_sw_4_be); |
3353 |
|
} |
3354 |
|
|
3355 |
/* Avoid "overlapping" instruction combinations: */ |
/* Convert a multi_sw_2 to a multi_sw_3: */ |
3356 |
if (ic[-4].f == instr(multi_sw_3_be)||ic[-3].f == instr(multi_sw_3_be)|| |
if ((ic[-2].f == instr(multi_sw_2_be) || |
3357 |
ic[-4].f == instr(multi_sw_3_le)||ic[-3].f == instr(multi_sw_3_le)) |
ic[-2].f == instr(multi_sw_2_le)) && |
3358 |
|
ic[-2].arg[1] == ic[0].arg[1]) { |
3359 |
|
if (cpu->byte_order == EMUL_LITTLE_ENDIAN) |
3360 |
|
ic[-2].f = instr(multi_sw_3_le); |
3361 |
|
else |
3362 |
|
ic[-2].f = instr(multi_sw_3_be); |
3363 |
|
} |
3364 |
|
|
3365 |
|
if (ic[-1].f == ic[0].f && ic[-1].arg[1] == ic[0].arg[1]) { |
3366 |
|
if (cpu->byte_order == EMUL_LITTLE_ENDIAN) |
3367 |
|
ic[-1].f = instr(multi_sw_2_le); |
3368 |
|
else |
3369 |
|
ic[-1].f = instr(multi_sw_2_be); |
3370 |
|
} |
3371 |
|
} |
3372 |
|
#endif |
3373 |
|
|
3374 |
|
|
3375 |
|
/* Only for 32-bit virtual address translation so far. */ |
3376 |
|
#ifdef MODE32 |
3377 |
|
/* |
3378 |
|
* Combine: Multiple LW in a row using the same base register |
3379 |
|
* |
3380 |
|
* lw r?,???(rX) |
3381 |
|
* lw r?,???(rX) |
3382 |
|
* lw r?,???(rX) |
3383 |
|
* ... |
3384 |
|
*/ |
3385 |
|
void COMBINE(multi_lw)(struct cpu *cpu, struct mips_instr_call *ic, |
3386 |
|
int low_addr) |
3387 |
|
{ |
3388 |
|
int n_back = (low_addr >> MIPS_INSTR_ALIGNMENT_SHIFT) |
3389 |
|
& (MIPS_IC_ENTRIES_PER_PAGE - 1); |
3390 |
|
|
3391 |
|
if (n_back < 3) |
3392 |
return; |
return; |
3393 |
|
|
3394 |
if (ic[-2].f == ic[0].f && ic[-1].f == ic[0].f && |
/* Convert a multi_lw_3 to a multi_lw_4: */ |
3395 |
|
if ((ic[-3].f == instr(multi_lw_3_be) || |
3396 |
|
ic[-3].f == instr(multi_lw_3_le)) && |
3397 |
|
ic[-3].arg[1] == ic[0].arg[1] && |
3398 |
|
ic[-1].arg[0] != ic[0].arg[1]) { |
3399 |
|
if (cpu->byte_order == EMUL_LITTLE_ENDIAN) |
3400 |
|
ic[-3].f = instr(multi_lw_4_le); |
3401 |
|
else |
3402 |
|
ic[-3].f = instr(multi_lw_4_be); |
3403 |
|
} |
3404 |
|
|
3405 |
|
/* Convert a multi_lw_2 to a multi_lw_3: */ |
3406 |
|
if ((ic[-2].f == instr(multi_lw_2_be) || |
3407 |
|
ic[-2].f == instr(multi_lw_2_le)) && |
3408 |
ic[-2].arg[1] == ic[0].arg[1] && |
ic[-2].arg[1] == ic[0].arg[1] && |
3409 |
ic[-1].arg[1] == ic[0].arg[1]) { |
ic[-1].arg[0] != ic[0].arg[1]) { |
3410 |
if (cpu->byte_order == EMUL_LITTLE_ENDIAN) |
if (cpu->byte_order == EMUL_LITTLE_ENDIAN) |
3411 |
ic[-2].f = instr(multi_sw_3_le); |
ic[-2].f = instr(multi_lw_3_le); |
3412 |
else |
else |
3413 |
ic[-2].f = instr(multi_sw_3_be); |
ic[-2].f = instr(multi_lw_3_be); |
3414 |
combined; |
} |
3415 |
|
|
3416 |
|
/* Note: Loads to the base register are not allowed in slot -1. */ |
3417 |
|
if (ic[-1].f == ic[0].f && |
3418 |
|
ic[-1].arg[1] == ic[0].arg[1] && |
3419 |
|
ic[-1].arg[0] != ic[0].arg[1]) { |
3420 |
|
if (cpu->byte_order == EMUL_LITTLE_ENDIAN) |
3421 |
|
ic[-1].f = instr(multi_lw_2_le); |
3422 |
|
else |
3423 |
|
ic[-1].f = instr(multi_lw_2_be); |
3424 |
} |
} |
3425 |
} |
} |
3426 |
|
#endif |
3427 |
|
|
3428 |
|
|
3429 |
/* |
/* |
3459 |
ic[-3].arg[1] == ic[-5].arg[0] && |
ic[-3].arg[1] == ic[-5].arg[0] && |
3460 |
ic[-2].f == instr(nop) && ic[-1].f == instr(nop)) { |
ic[-2].f == instr(nop) && ic[-1].f == instr(nop)) { |
3461 |
ic[-8].f = instr(netbsd_r3k_picache_do_inv); |
ic[-8].f = instr(netbsd_r3k_picache_do_inv); |
|
combined; |
|
3462 |
} |
} |
3463 |
} |
} |
3464 |
|
|
3487 |
ic[-1].arg[1] == (size_t) &cpu->cd.mips.gpr[MIPS_GPR_ZERO] && |
ic[-1].arg[1] == (size_t) &cpu->cd.mips.gpr[MIPS_GPR_ZERO] && |
3488 |
ic[-1].f == instr(bne_samepage)) { |
ic[-1].f == instr(bne_samepage)) { |
3489 |
ic[-3].f = instr(netbsd_strlen); |
ic[-3].f = instr(netbsd_strlen); |
|
combined; |
|
3490 |
return; |
return; |
3491 |
} |
} |
3492 |
#endif |
#endif |
3496 |
|
|
3497 |
if (ic[-1].f == instr(bne_samepage)) { |
if (ic[-1].f == instr(bne_samepage)) { |
3498 |
ic[-1].f = instr(bne_samepage_nop); |
ic[-1].f = instr(bne_samepage_nop); |
|
combined; |
|
3499 |
return; |
return; |
3500 |
} |
} |
3501 |
|
|
3502 |
if (ic[-1].f == instr(beq_samepage)) { |
if (ic[-1].f == instr(beq_samepage)) { |
3503 |
ic[-1].f = instr(beq_samepage_nop); |
ic[-1].f = instr(beq_samepage_nop); |
|
combined; |
|
3504 |
return; |
return; |
3505 |
} |
} |
3506 |
|
|
3511 |
/* |
/* |
3512 |
* Combine: |
* Combine: |
3513 |
* |
* |
3514 |
|
* xor + andi + sll |
3515 |
|
* andi + sll |
3516 |
|
*/ |
3517 |
|
void COMBINE(sll)(struct cpu *cpu, struct mips_instr_call *ic, int low_addr) |
3518 |
|
{ |
3519 |
|
int n_back = (low_addr >> MIPS_INSTR_ALIGNMENT_SHIFT) |
3520 |
|
& (MIPS_IC_ENTRIES_PER_PAGE - 1); |
3521 |
|
|
3522 |
|
if (n_back < 2) |
3523 |
|
return; |
3524 |
|
|
3525 |
|
if (ic[-2].f == instr(xor) && ic[-1].f == instr(andi)) { |
3526 |
|
ic[-2].f = instr(xor_andi_sll); |
3527 |
|
return; |
3528 |
|
} |
3529 |
|
|
3530 |
|
if (ic[-1].f == instr(andi)) { |
3531 |
|
ic[-1].f = instr(andi_sll); |
3532 |
|
return; |
3533 |
|
} |
3534 |
|
} |
3535 |
|
|
3536 |
|
|
3537 |
|
/* |
3538 |
|
* lui + ori |
3539 |
|
*/ |
3540 |
|
void COMBINE(ori)(struct cpu *cpu, struct mips_instr_call *ic, int low_addr) |
3541 |
|
{ |
3542 |
|
int n_back = (low_addr >> MIPS_INSTR_ALIGNMENT_SHIFT) |
3543 |
|
& (MIPS_IC_ENTRIES_PER_PAGE - 1); |
3544 |
|
|
3545 |
|
if (n_back < 1) |
3546 |
|
return; |
3547 |
|
|
3548 |
|
if (ic[-1].f == instr(set)) { |
3549 |
|
ic[-1].f = instr(lui_ori); |
3550 |
|
return; |
3551 |
|
} |
3552 |
|
} |
3553 |
|
|
3554 |
|
|
3555 |
|
/* |
3556 |
|
* addu + addu + addu |
3557 |
|
*/ |
3558 |
|
void COMBINE(addu)(struct cpu *cpu, struct mips_instr_call *ic, int low_addr) |
3559 |
|
{ |
3560 |
|
int n_back = (low_addr >> MIPS_INSTR_ALIGNMENT_SHIFT) |
3561 |
|
& (MIPS_IC_ENTRIES_PER_PAGE - 1); |
3562 |
|
|
3563 |
|
if (n_back < 4) |
3564 |
|
return; |
3565 |
|
|
3566 |
|
/* Avoid "overlapping" instruction combinations: */ |
3567 |
|
if (ic[-4].f == instr(multi_addu_3) || |
3568 |
|
ic[-3].f == instr(multi_addu_3)) |
3569 |
|
return; |
3570 |
|
|
3571 |
|
if (ic[-2].f == instr(addu) && ic[-1].f == instr(addu)) { |
3572 |
|
ic[-2].f = instr(multi_addu_3); |
3573 |
|
return; |
3574 |
|
} |
3575 |
|
} |
3576 |
|
|
3577 |
|
|
3578 |
|
/* |
3579 |
|
* Combine: |
3580 |
|
* |
3581 |
* [Conditional] branch, followed by addiu. |
* [Conditional] branch, followed by addiu. |
|
* lui + addiu. |
|
3582 |
*/ |
*/ |
3583 |
void COMBINE(addiu)(struct cpu *cpu, struct mips_instr_call *ic, int low_addr) |
void COMBINE(addiu)(struct cpu *cpu, struct mips_instr_call *ic, int low_addr) |
3584 |
{ |
{ |
3585 |
int n_back = (low_addr >> MIPS_INSTR_ALIGNMENT_SHIFT) |
int n_back = (low_addr >> MIPS_INSTR_ALIGNMENT_SHIFT) |
3586 |
& (MIPS_IC_ENTRIES_PER_PAGE - 1); |
& (MIPS_IC_ENTRIES_PER_PAGE - 1); |
3587 |
|
|
3588 |
if (n_back < 1) |
if (n_back < 2) |
3589 |
|
return; |
3590 |
|
|
3591 |
|
if (ic[-2].f == instr(addiu) && |
3592 |
|
ic[-1].f == instr(bne_samepage)) { |
3593 |
|
ic[-2].f = instr(addiu_bne_samepage_addiu); |
3594 |
return; |
return; |
3595 |
|
} |
3596 |
|
|
3597 |
if (ic[-1].f == instr(set) && ic[-1].arg[0] == ic[0].arg[0] && |
if (ic[-1].f == instr(set)) { |
3598 |
ic[0].arg[0] == ic[0].arg[1]) { |
ic[-1].f = instr(lui_addiu); |
|
ic[-1].f = instr(lui_32bit); |
|
|
ic[-1].arg[2] = (int32_t) (ic[-1].arg[1] + ic[0].arg[2]); |
|
|
combined; |
|
3599 |
return; |
return; |
3600 |
} |
} |
3601 |
|
|
3602 |
if (ic[-1].f == instr(b_samepage)) { |
if (ic[-1].f == instr(b_samepage)) { |
3603 |
ic[-1].f = instr(b_samepage_addiu); |
ic[-1].f = instr(b_samepage_addiu); |
|
combined; |
|
3604 |
return; |
return; |
3605 |
} |
} |
3606 |
|
|
3607 |
if (ic[-1].f == instr(beq_samepage)) { |
if (ic[-1].f == instr(beq_samepage)) { |
3608 |
ic[-1].f = instr(beq_samepage_addiu); |
ic[-1].f = instr(beq_samepage_addiu); |
|
combined; |
|
3609 |
return; |
return; |
3610 |
} |
} |
3611 |
|
|
3612 |
if (ic[-1].f == instr(bne_samepage)) { |
if (ic[-1].f == instr(bne_samepage)) { |
3613 |
ic[-1].f = instr(bne_samepage_addiu); |
ic[-1].f = instr(bne_samepage_addiu); |
|
combined; |
|
3614 |
return; |
return; |
3615 |
} |
} |
3616 |
|
|
3617 |
if (ic[-1].f == instr(jr_ra)) { |
if (ic[-1].f == instr(jr_ra)) { |
3618 |
ic[-1].f = instr(jr_ra_addiu); |
ic[-1].f = instr(jr_ra_addiu); |
|
combined; |
|
3619 |
return; |
return; |
3620 |
} |
} |
3621 |
|
|
3637 |
|
|
3638 |
if (ic[-1].f == instr(b_samepage)) { |
if (ic[-1].f == instr(b_samepage)) { |
3639 |
ic[-1].f = instr(b_samepage_daddiu); |
ic[-1].f = instr(b_samepage_daddiu); |
|
combined; |
|
3640 |
} |
} |
3641 |
|
|
3642 |
/* TODO: other branches that are followed by daddiu should be here */ |
/* TODO: other branches that are followed by daddiu should be here */ |
3793 |
ic->arg[2] = (size_t)&cpu->cd.mips.gpr[rd]; |
ic->arg[2] = (size_t)&cpu->cd.mips.gpr[rd]; |
3794 |
if (rd == MIPS_GPR_ZERO) |
if (rd == MIPS_GPR_ZERO) |
3795 |
ic->f = instr(nop); |
ic->f = instr(nop); |
3796 |
|
if (ic->f == instr(sll)) |
3797 |
|
cpu->cd.mips.combination_check = COMBINE(sll); |
3798 |
break; |
break; |
3799 |
|
|
3800 |
case SPECIAL_ADD: |
case SPECIAL_ADD: |
3926 |
default:if (rd == MIPS_GPR_ZERO) |
default:if (rd == MIPS_GPR_ZERO) |
3927 |
ic->f = instr(nop); |
ic->f = instr(nop); |
3928 |
} |
} |
3929 |
|
|
3930 |
|
if (ic->f == instr(addu)) |
3931 |
|
cpu->cd.mips.combination_check = COMBINE(addu); |
3932 |
break; |
break; |
3933 |
|
|
3934 |
case SPECIAL_JR: |
case SPECIAL_JR: |
3972 |
break; |
break; |
3973 |
|
|
3974 |
case SPECIAL_BREAK: |
case SPECIAL_BREAK: |
3975 |
ic->f = instr(break); |
if (((iword >> 6) & 0xfffff) == 0x30378) { |
3976 |
|
/* "Magic trap" for REBOOT: */ |
3977 |
|
ic->f = instr(reboot); |
3978 |
|
} else { |
3979 |
|
ic->f = instr(break); |
3980 |
|
} |
3981 |
break; |
break; |
3982 |
|
|
3983 |
case SPECIAL_SYNC: |
case SPECIAL_SYNC: |
4104 |
if (rt == MIPS_GPR_ZERO) |
if (rt == MIPS_GPR_ZERO) |
4105 |
ic->f = instr(nop); |
ic->f = instr(nop); |
4106 |
|
|
4107 |
|
if (ic->f == instr(ori)) |
4108 |
|
cpu->cd.mips.combination_check = COMBINE(ori); |
4109 |
if (ic->f == instr(addiu)) |
if (ic->f == instr(addiu)) |
4110 |
cpu->cd.mips.combination_check = COMBINE(addiu); |
cpu->cd.mips.combination_check = COMBINE(addiu); |
4111 |
if (ic->f == instr(daddiu)) |
if (ic->f == instr(daddiu)) |
4171 |
case COP0_DERET: |
case COP0_DERET: |
4172 |
ic->f = instr(deret); |
ic->f = instr(deret); |
4173 |
break; |
break; |
4174 |
case COP0_IDLE: |
case COP0_WAIT: |
4175 |
|
ic->f = instr(wait); |
4176 |
|
if (cpu->cd.mips.cpu_type.rev != MIPS_RM5200 && |
4177 |
|
cpu->cd.mips.cpu_type.isa_level < 32) { |
4178 |
|
static int warned = 0; |
4179 |
|
ic->f = instr(reserved); |
4180 |
|
if (!warned) { |
4181 |
|
fatal("{ WARNING: Attempt to " |
4182 |
|
"execute the WAIT instruct" |
4183 |
|
"ion, but the emulated CPU " |
4184 |
|
"is neither RM52xx, nor " |
4185 |
|
"MIPS32/64! }\n"); |
4186 |
|
warned = 1; |
4187 |
|
} |
4188 |
|
} |
4189 |
|
break; |
4190 |
case COP0_STANDBY: |
case COP0_STANDBY: |
4191 |
case COP0_SUSPEND: |
case COP0_SUSPEND: |
4192 |
case COP0_HIBERNATE: |
case COP0_HIBERNATE: |
4561 |
if (!store && rt == MIPS_GPR_ZERO) |
if (!store && rt == MIPS_GPR_ZERO) |
4562 |
ic->arg[0] = (size_t)&cpu->cd.mips.scratch; |
ic->arg[0] = (size_t)&cpu->cd.mips.scratch; |
4563 |
|
|
4564 |
/* Check for multiple stores in a row using the same |
/* Check for multiple loads or stores in a row using the same |
4565 |
base register: */ |
base register: */ |
4566 |
if (main_opcode == HI6_SW && rs == MIPS_GPR_SP) |
#ifdef MODE32 |
4567 |
|
if (main_opcode == HI6_LW) |
4568 |
|
cpu->cd.mips.combination_check = COMBINE(multi_lw); |
4569 |
|
if (main_opcode == HI6_SW) |
4570 |
cpu->cd.mips.combination_check = COMBINE(multi_sw); |
cpu->cd.mips.combination_check = COMBINE(multi_sw); |
4571 |
|
#endif |
4572 |
break; |
break; |
4573 |
|
|
4574 |
case HI6_LL: |
case HI6_LL: |