25 |
* SUCH DAMAGE. |
* SUCH DAMAGE. |
26 |
* |
* |
27 |
* |
* |
28 |
* $Id: cpu_mips_instr.c,v 1.87 2006/06/25 02:46:08 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 |
* |
* |
135 |
} |
} |
136 |
cpu->delay_slot = NOT_DELAYED; |
cpu->delay_slot = NOT_DELAYED; |
137 |
} |
} |
138 |
|
X(beq_samepage_addiu) |
139 |
|
{ |
140 |
|
MODE_uint_t rs = reg(ic->arg[0]), rt = reg(ic->arg[1]); |
141 |
|
cpu->n_translated_instrs ++; |
142 |
|
reg(ic[1].arg[1]) = (int32_t) |
143 |
|
((int32_t)reg(ic[1].arg[0]) + (int32_t)ic[1].arg[2]); |
144 |
|
if (rs == rt) |
145 |
|
cpu->cd.mips.next_ic = (struct mips_instr_call *) ic->arg[2]; |
146 |
|
else |
147 |
|
cpu->cd.mips.next_ic ++; |
148 |
|
} |
149 |
|
X(beq_samepage_nop) |
150 |
|
{ |
151 |
|
MODE_uint_t rs = reg(ic->arg[0]), rt = reg(ic->arg[1]); |
152 |
|
cpu->n_translated_instrs ++; |
153 |
|
if (rs == rt) |
154 |
|
cpu->cd.mips.next_ic = (struct mips_instr_call *) ic->arg[2]; |
155 |
|
else |
156 |
|
cpu->cd.mips.next_ic ++; |
157 |
|
} |
158 |
X(bne) |
X(bne) |
159 |
{ |
{ |
160 |
MODE_int_t old_pc = cpu->pc; |
MODE_int_t old_pc = cpu->pc; |
192 |
} |
} |
193 |
cpu->delay_slot = NOT_DELAYED; |
cpu->delay_slot = NOT_DELAYED; |
194 |
} |
} |
195 |
|
X(bne_samepage_addiu) |
196 |
|
{ |
197 |
|
MODE_uint_t rs = reg(ic->arg[0]), rt = reg(ic->arg[1]); |
198 |
|
cpu->n_translated_instrs ++; |
199 |
|
reg(ic[1].arg[1]) = (int32_t) |
200 |
|
((int32_t)reg(ic[1].arg[0]) + (int32_t)ic[1].arg[2]); |
201 |
|
if (rs != rt) |
202 |
|
cpu->cd.mips.next_ic = (struct mips_instr_call *) ic->arg[2]; |
203 |
|
else |
204 |
|
cpu->cd.mips.next_ic ++; |
205 |
|
} |
206 |
|
X(bne_samepage_nop) |
207 |
|
{ |
208 |
|
MODE_uint_t rs = reg(ic->arg[0]), rt = reg(ic->arg[1]); |
209 |
|
cpu->n_translated_instrs ++; |
210 |
|
if (rs != rt) |
211 |
|
cpu->cd.mips.next_ic = (struct mips_instr_call *) ic->arg[2]; |
212 |
|
else |
213 |
|
cpu->cd.mips.next_ic ++; |
214 |
|
} |
215 |
X(b) |
X(b) |
216 |
{ |
{ |
217 |
MODE_int_t old_pc = cpu->pc; |
MODE_int_t old_pc = cpu->pc; |
936 |
} else |
} else |
937 |
cpu->delay_slot = NOT_DELAYED; |
cpu->delay_slot = NOT_DELAYED; |
938 |
} |
} |
939 |
|
X(jr_ra_addiu) |
940 |
|
{ |
941 |
|
/* jr ra, followed by an addiu */ |
942 |
|
MODE_int_t rs = cpu->cd.mips.gpr[MIPS_GPR_RA]; |
943 |
|
reg(ic[1].arg[1]) = (int32_t) |
944 |
|
((int32_t)reg(ic[1].arg[0]) + (int32_t)ic[1].arg[2]); |
945 |
|
cpu->pc = rs; |
946 |
|
quick_pc_to_pointers(cpu); |
947 |
|
cpu->n_translated_instrs ++; |
948 |
|
} |
949 |
X(jr_ra_trace) |
X(jr_ra_trace) |
950 |
{ |
{ |
951 |
MODE_int_t rs = cpu->cd.mips.gpr[MIPS_GPR_RA]; |
MODE_int_t rs = cpu->cd.mips.gpr[MIPS_GPR_RA]; |
1063 |
*/ |
*/ |
1064 |
X(cache) |
X(cache) |
1065 |
{ |
{ |
1066 |
/* TODO. For now, just clear the rmw bit: */ |
/* TODO: Implement cache operations. */ |
|
cpu->cd.mips.rmw = 0; |
|
1067 |
|
|
1068 |
/* TODO: fix */ |
/* Make sure the rmw bit is cleared: */ |
1069 |
cpu->invalidate_code_translation(cpu, 0, INVALIDATE_ALL); |
cpu->cd.mips.rmw = 0; |
|
cpu->invalidate_translation_caches(cpu, 0, INVALIDATE_ALL); |
|
|
/* cpu_create_or_reset_tc(cpu); */ |
|
1070 |
} |
} |
1071 |
|
|
1072 |
|
|
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 |
/* |
/* |
1904 |
*/ |
*/ |
1905 |
X(rfe) |
X(rfe) |
1906 |
{ |
{ |
1907 |
coproc_rfe(cpu); |
/* Just rotate the interrupt/user bits: */ |
1908 |
|
cpu->cd.mips.coproc[0]->reg[COP0_STATUS] = |
1909 |
|
(cpu->cd.mips.coproc[0]->reg[COP0_STATUS] & ~0x3f) | |
1910 |
|
((cpu->cd.mips.coproc[0]->reg[COP0_STATUS] & 0x3c) >> 2); |
1911 |
|
|
1912 |
/* Note: no pc to pointers conversion is necessary here. */ |
/* |
1913 |
|
* Note: no pc to pointers conversion is necessary here. Usually the |
1914 |
|
* rfe instruction resides in the delay slot of a jr k0/k1, and |
1915 |
|
* it is up to that instruction to do the pointer conversion. |
1916 |
|
*/ |
1917 |
} |
} |
1918 |
|
|
1919 |
|
|
1920 |
/* |
/* |
1921 |
* eret: Return from exception handler |
* eret: Return from exception handler (non-R3000 style) |
1922 |
*/ |
*/ |
1923 |
X(eret) |
X(eret) |
1924 |
{ |
{ |
1925 |
coproc_eret(cpu); |
if (cpu->cd.mips.coproc[0]->reg[COP0_STATUS] & STATUS_ERL) { |
1926 |
|
cpu->pc = cpu->cd.mips.coproc[0]->reg[COP0_ERROREPC]; |
1927 |
|
cpu->cd.mips.coproc[0]->reg[COP0_STATUS] &= ~STATUS_ERL; |
1928 |
|
} else { |
1929 |
|
cpu->pc = cpu->cd.mips.coproc[0]->reg[COP0_EPC]; |
1930 |
|
cpu->delay_slot = 0; |
1931 |
|
cpu->cd.mips.coproc[0]->reg[COP0_STATUS] &= ~STATUS_EXL; |
1932 |
|
} |
1933 |
|
|
1934 |
quick_pc_to_pointers(cpu); |
quick_pc_to_pointers(cpu); |
1935 |
|
|
1936 |
|
cpu->cd.mips.rmw = 0; /* the "LL bit" */ |
1937 |
} |
} |
1938 |
|
|
1939 |
|
|
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) |
2417 |
|
|
2418 |
|
|
2419 |
/* |
/* |
2420 |
|
* sw_loop: |
2421 |
|
* |
2422 |
|
* s: addiu rX,rX,4 rX = arg[0] and arg[1] |
2423 |
|
* bne rY,rX,s (or rX,rY,s) rt=arg[1], rs=arg[0] |
2424 |
|
* sw rZ,-4(rX) rt=arg[0], rs=arg[1] |
2425 |
|
*/ |
2426 |
|
X(sw_loop) |
2427 |
|
{ |
2428 |
|
MODE_uint_t rX = reg(ic->arg[0]), rZ = reg(ic[2].arg[0]); |
2429 |
|
uint64_t *rYp = (uint64_t *) ic[1].arg[0]; |
2430 |
|
MODE_uint_t rY, bytes_to_write; |
2431 |
|
unsigned char *page; |
2432 |
|
int partial = 0; |
2433 |
|
|
2434 |
|
page = cpu->cd.mips.host_store[rX >> 12]; |
2435 |
|
|
2436 |
|
/* Fallback: */ |
2437 |
|
if (cpu->delay_slot || page == NULL || (rX & 3) != 0 || rZ != 0) { |
2438 |
|
instr(addiu)(cpu, ic); |
2439 |
|
return; |
2440 |
|
} |
2441 |
|
|
2442 |
|
if (rYp == (uint64_t *) ic->arg[0]) |
2443 |
|
rYp = (uint64_t *) ic[1].arg[1]; |
2444 |
|
|
2445 |
|
rY = reg(rYp); |
2446 |
|
|
2447 |
|
bytes_to_write = rY - rX; |
2448 |
|
if ((rX & 0xfff) + bytes_to_write > 0x1000) { |
2449 |
|
bytes_to_write = 0x1000 - (rX & 0xfff); |
2450 |
|
partial = 1; |
2451 |
|
} |
2452 |
|
|
2453 |
|
/* printf("rX = %08x\n", (int)rX); |
2454 |
|
printf("rY = %08x\n", (int)rY); |
2455 |
|
printf("rZ = %08x\n", (int)rZ); |
2456 |
|
printf("%i bytes\n", (int)bytes_to_write); */ |
2457 |
|
|
2458 |
|
memset(page + (rX & 0xfff), 0, bytes_to_write); |
2459 |
|
|
2460 |
|
reg(ic->arg[0]) = rX + bytes_to_write; |
2461 |
|
|
2462 |
|
cpu->n_translated_instrs += bytes_to_write / 4 * 3 - 1; |
2463 |
|
cpu->cd.mips.next_ic = partial? |
2464 |
|
(struct mips_instr_call *) &ic[0] : |
2465 |
|
(struct mips_instr_call *) &ic[3]; |
2466 |
|
} |
2467 |
|
|
2468 |
|
|
2469 |
|
#ifdef MODE32 |
2470 |
|
/* |
2471 |
|
* multi_sw_2, _3, _4: |
2472 |
|
* |
2473 |
|
* 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) |
2544 |
|
{ |
2545 |
|
uint32_t *page; |
2546 |
|
MODE_uint_t rX = reg(ic[0].arg[1]), r1, r2, r3; |
2547 |
|
MODE_uint_t addr0 = rX + (int32_t)ic[0].arg[2]; |
2548 |
|
MODE_uint_t addr1 = rX + (int32_t)ic[1].arg[2]; |
2549 |
|
MODE_uint_t addr2 = rX + (int32_t)ic[2].arg[2]; |
2550 |
|
uint32_t index0 = addr0 >> 12, index1 = addr1 >> 12, |
2551 |
|
index2 = addr2 >> 12; |
2552 |
|
|
2553 |
|
page = (uint32_t *) cpu->cd.mips.host_store[index0]; |
2554 |
|
|
2555 |
|
/* Fallback: */ |
2556 |
|
if (cpu->delay_slot || |
2557 |
|
page == NULL || (addr0 & 3) != 0 || (addr1 & 3) != 0 || |
2558 |
|
(addr2 & 3) != 0 || index0 != index1 || index0 != index2) { |
2559 |
|
/* Normal safe sw: */ |
2560 |
|
mips32_loadstore[8 + 2 * 2](cpu, ic); |
2561 |
|
return; |
2562 |
|
} |
2563 |
|
|
2564 |
|
addr0 = (addr0 >> 2) & 0x3ff; |
2565 |
|
addr1 = (addr1 >> 2) & 0x3ff; |
2566 |
|
addr2 = (addr2 >> 2) & 0x3ff; |
2567 |
|
|
2568 |
|
/* printf("addr0=%x 1=%x 2=%x\n", |
2569 |
|
(int)addr0, (int)addr1, (int)addr2); */ |
2570 |
|
|
2571 |
|
r1 = reg(ic[0].arg[0]); |
2572 |
|
r2 = reg(ic[1].arg[0]); |
2573 |
|
r3 = reg(ic[2].arg[0]); |
2574 |
|
|
2575 |
|
r1 = LE32_TO_HOST(r1); |
2576 |
|
r2 = LE32_TO_HOST(r2); |
2577 |
|
r3 = LE32_TO_HOST(r3); |
2578 |
|
|
2579 |
|
page[addr0] = r1; |
2580 |
|
page[addr1] = r2; |
2581 |
|
page[addr2] = r3; |
2582 |
|
|
2583 |
|
cpu->n_translated_instrs += 2; |
2584 |
|
cpu->cd.mips.next_ic += 2; |
2585 |
|
} |
2586 |
|
X(multi_sw_3_be) |
2587 |
|
{ |
2588 |
|
uint32_t *page; |
2589 |
|
MODE_uint_t rX = reg(ic[0].arg[1]), r1, r2, r3; |
2590 |
|
MODE_uint_t addr0 = rX + (int32_t)ic[0].arg[2]; |
2591 |
|
MODE_uint_t addr1 = rX + (int32_t)ic[1].arg[2]; |
2592 |
|
MODE_uint_t addr2 = rX + (int32_t)ic[2].arg[2]; |
2593 |
|
uint32_t index0 = addr0 >> 12, index1 = addr1 >> 12, |
2594 |
|
index2 = addr2 >> 12; |
2595 |
|
|
2596 |
|
page = (uint32_t *) cpu->cd.mips.host_store[index0]; |
2597 |
|
|
2598 |
|
/* Fallback: */ |
2599 |
|
if (cpu->delay_slot || |
2600 |
|
page == NULL || (addr0 & 3) != 0 || (addr1 & 3) != 0 || |
2601 |
|
(addr2 & 3) != 0 || index0 != index1 || index0 != index2) { |
2602 |
|
/* Normal safe sw: */ |
2603 |
|
mips32_loadstore[16 + 8 + 2 * 2](cpu, ic); |
2604 |
|
return; |
2605 |
|
} |
2606 |
|
|
2607 |
|
addr0 = (addr0 >> 2) & 0x3ff; |
2608 |
|
addr1 = (addr1 >> 2) & 0x3ff; |
2609 |
|
addr2 = (addr2 >> 2) & 0x3ff; |
2610 |
|
|
2611 |
|
/* printf("addr0=%x 1=%x 2=%x\n", |
2612 |
|
(int)addr0, (int)addr1, (int)addr2); */ |
2613 |
|
|
2614 |
|
r1 = reg(ic[0].arg[0]); |
2615 |
|
r2 = reg(ic[1].arg[0]); |
2616 |
|
r3 = reg(ic[2].arg[0]); |
2617 |
|
|
2618 |
|
r1 = BE32_TO_HOST(r1); |
2619 |
|
r2 = BE32_TO_HOST(r2); |
2620 |
|
r3 = BE32_TO_HOST(r3); |
2621 |
|
|
2622 |
|
page[addr0] = r1; |
2623 |
|
page[addr1] = r2; |
2624 |
|
page[addr2] = r3; |
2625 |
|
|
2626 |
|
cpu->n_translated_instrs += 2; |
2627 |
|
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 |
|
|
2998 |
|
/* |
2999 |
|
* netbsd_r3k_picache_do_inv: |
3000 |
|
* |
3001 |
|
* ic[0] mtc0 rV,status |
3002 |
|
* 1 nop |
3003 |
|
* 2 nop |
3004 |
|
* 3 s: addiu rX,rX,4 |
3005 |
|
* 4 bne rY,rX,s |
3006 |
|
* 5 sb zr,-4(rX) |
3007 |
|
* 6 nop |
3008 |
|
* 7 nop |
3009 |
|
* 8 mtc0 rT,status |
3010 |
|
*/ |
3011 |
|
X(netbsd_r3k_picache_do_inv) |
3012 |
|
{ |
3013 |
|
MODE_uint_t rx = reg(ic[3].arg[0]), ry = reg(ic[4].arg[1]); |
3014 |
|
|
3015 |
|
/* Fallback if the environment isn't exactly right: */ |
3016 |
|
if (!(reg(ic[0].arg[0]) & MIPS1_ISOL_CACHES) || |
3017 |
|
(rx & 3) || (ry & 3) || cpu->delay_slot) { |
3018 |
|
instr(mtc0)(cpu, ic); |
3019 |
|
return; |
3020 |
|
} |
3021 |
|
|
3022 |
|
reg(ic[3].arg[0]) = ry; |
3023 |
|
cpu->n_translated_instrs += (ry - rx + 4) / 4 * 3 + 4; |
3024 |
|
|
3025 |
|
/* Run the last mtc0 instruction: */ |
3026 |
|
cpu->cd.mips.next_ic = (struct mips_instr_call *) &ic[8]; |
3027 |
|
} |
3028 |
|
|
3029 |
|
|
3030 |
|
#ifdef MODE32 |
3031 |
|
/* |
3032 |
|
* netbsd_strlen(): |
3033 |
|
* |
3034 |
|
* lb rV,0(rX) |
3035 |
|
* s: addiu rX,rX,1 |
3036 |
|
* bne zr,rV,s |
3037 |
|
* nop |
3038 |
|
*/ |
3039 |
|
X(netbsd_strlen) |
3040 |
|
{ |
3041 |
|
MODE_uint_t rx = reg(ic[0].arg[1]); |
3042 |
|
MODE_int_t rv; |
3043 |
|
signed char *page; |
3044 |
|
uint32_t pageindex = rx >> 12; |
3045 |
|
int i; |
3046 |
|
|
3047 |
|
page = (signed char *) cpu->cd.mips.host_load[pageindex]; |
3048 |
|
|
3049 |
|
/* Fallback: */ |
3050 |
|
if (cpu->delay_slot || page == NULL) { |
3051 |
|
/* |
3052 |
|
* Normal lb: NOTE: It doesn't matter whether [1] or |
3053 |
|
* [16+1] is called here, because endianness for 8-bit |
3054 |
|
* loads is irrelevant. :-) |
3055 |
|
*/ |
3056 |
|
mips32_loadstore[1](cpu, ic); |
3057 |
|
return; |
3058 |
|
} |
3059 |
|
|
3060 |
|
i = rx & 0xfff; |
3061 |
|
|
3062 |
|
/* |
3063 |
|
* TODO: This loop can be optimized further for optimal |
3064 |
|
* performance on the host, e.g. by reading full words... |
3065 |
|
*/ |
3066 |
|
do { |
3067 |
|
rv = page[i ++]; |
3068 |
|
} while (i < 0x1000 && rv != 0); |
3069 |
|
|
3070 |
|
cpu->n_translated_instrs += (i - (rx & 0xfff)) * 4 - 1; |
3071 |
|
|
3072 |
|
reg(ic[0].arg[1]) = (rx & ~0xfff) + i; |
3073 |
|
reg(ic[2].arg[0]) = rv; |
3074 |
|
|
3075 |
|
/* Done with the loop? Or continue on the next rx page? */ |
3076 |
|
if (rv == 0) |
3077 |
|
cpu->cd.mips.next_ic = (struct mips_instr_call *) &ic[4]; |
3078 |
|
else |
3079 |
|
cpu->cd.mips.next_ic = (struct mips_instr_call *) &ic[0]; |
3080 |
|
} |
3081 |
|
#endif |
3082 |
|
|
3083 |
|
|
3084 |
|
/* |
3085 |
|
* addiu_bne_samepage_addiu: |
3086 |
|
*/ |
3087 |
|
X(addiu_bne_samepage_addiu) |
3088 |
|
{ |
3089 |
|
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 ++; |
3184 |
|
cpu->cd.mips.next_ic ++; |
3185 |
|
} |
3186 |
|
|
3187 |
|
|
3188 |
|
/* |
3189 |
* b_samepage_addiu: |
* b_samepage_addiu: |
3190 |
* |
* |
3191 |
* Combination of branch within the same page, followed by addiu. |
* Combination of branch within the same page, followed by addiu. |
3291 |
|
|
3292 |
|
|
3293 |
/* |
/* |
3294 |
* Combine: [Conditional] branch, followed by addiu. |
* Combine: Memory fill loop (addiu, bne, sw) |
3295 |
|
* |
3296 |
|
* s: addiu rX,rX,4 |
3297 |
|
* bne rY,rX,s |
3298 |
|
* sw rZ,-4(rX) |
3299 |
*/ |
*/ |
3300 |
void COMBINE(b_addiu)(struct cpu *cpu, struct mips_instr_call *ic, |
void COMBINE(sw_loop)(struct cpu *cpu, struct mips_instr_call *ic, int low_addr) |
3301 |
|
{ |
3302 |
|
int n_back = (low_addr >> MIPS_INSTR_ALIGNMENT_SHIFT) |
3303 |
|
& (MIPS_IC_ENTRIES_PER_PAGE - 1); |
3304 |
|
|
3305 |
|
/* Only for 32-bit virtual address translation so far. */ |
3306 |
|
if (!cpu->is_32bit) |
3307 |
|
return; |
3308 |
|
|
3309 |
|
if (n_back < 2) |
3310 |
|
return; |
3311 |
|
|
3312 |
|
if (ic[-2].f == instr(addiu) && ic[-2].arg[0] == ic[-2].arg[1] && |
3313 |
|
(int32_t)ic[-2].arg[2] == 4 && |
3314 |
|
ic[-1].f == instr(bne_samepage) && |
3315 |
|
(ic[-1].arg[0] == ic[-2].arg[0] || |
3316 |
|
ic[-1].arg[1] == ic[-2].arg[0]) && |
3317 |
|
ic[-1].arg[0] != ic[-1].arg[1] && |
3318 |
|
ic[-1].arg[2] == (size_t) &ic[-2] && |
3319 |
|
ic[0].arg[0] != ic[0].arg[1] && |
3320 |
|
ic[0].arg[1] == ic[-2].arg[0] && (int32_t)ic[0].arg[2] == -4) { |
3321 |
|
ic[-2].f = instr(sw_loop); |
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 |
3330 |
|
* |
3331 |
|
* sw r?,???(rX) |
3332 |
|
* sw r?,???(rX) |
3333 |
|
* sw r?,???(rX) |
3334 |
|
* ... |
3335 |
|
*/ |
3336 |
|
void COMBINE(multi_sw)(struct cpu *cpu, struct mips_instr_call *ic, |
3337 |
int low_addr) |
int low_addr) |
3338 |
{ |
{ |
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 |
|
if (n_back < 3) |
3343 |
|
return; |
3344 |
|
|
3345 |
|
/* Convert a multi_sw_3 to a multi_sw_4: */ |
3346 |
|
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 |
|
/* Convert a multi_sw_2 to a multi_sw_3: */ |
3356 |
|
if ((ic[-2].f == instr(multi_sw_2_be) || |
3357 |
|
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; |
3393 |
|
|
3394 |
|
/* 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] && |
3409 |
|
ic[-1].arg[0] != ic[0].arg[1]) { |
3410 |
|
if (cpu->byte_order == EMUL_LITTLE_ENDIAN) |
3411 |
|
ic[-2].f = instr(multi_lw_3_le); |
3412 |
|
else |
3413 |
|
ic[-2].f = instr(multi_lw_3_be); |
3414 |
|
} |
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 |
|
/* |
3430 |
|
* Combine: NetBSD/pmax 3.0 R2000/R3000 physical cache invalidation loop |
3431 |
|
* |
3432 |
|
* Instruction cache loop: |
3433 |
|
* |
3434 |
|
* ic[-8] mtc0 rV,status |
3435 |
|
* -7 nop |
3436 |
|
* -6 nop |
3437 |
|
* -5 s: addiu rX,rX,4 |
3438 |
|
* -4 bne rY,rX,s |
3439 |
|
* -3 sb zr,-4(rX) |
3440 |
|
* -2 nop |
3441 |
|
* -1 nop |
3442 |
|
* 0 mtc0 rT,status |
3443 |
|
*/ |
3444 |
|
void COMBINE(netbsd_r3k_cache_inv)(struct cpu *cpu, |
3445 |
|
struct mips_instr_call *ic, int low_addr) |
3446 |
|
{ |
3447 |
|
int n_back = (low_addr >> MIPS_INSTR_ALIGNMENT_SHIFT) |
3448 |
|
& (MIPS_IC_ENTRIES_PER_PAGE - 1); |
3449 |
|
|
3450 |
|
if (n_back < 8) |
3451 |
|
return; |
3452 |
|
|
3453 |
|
if (ic[-8].f == instr(mtc0) && ic[-8].arg[1] == COP0_STATUS && |
3454 |
|
ic[-7].f == instr(nop) && ic[-6].f == instr(nop) && |
3455 |
|
ic[-5].f == instr(addiu) && ic[-5].arg[0] == ic[-5].arg[1] && |
3456 |
|
(int32_t)ic[-5].arg[2] == 4 && ic[-4].f == instr(bne_samepage) && |
3457 |
|
ic[-4].arg[0] == ic[-5].arg[0] && ic[-4].arg[0] != ic[-4].arg[1] && |
3458 |
|
ic[-4].arg[2] == (size_t) &ic[-5] && |
3459 |
|
ic[-3].arg[1] == ic[-5].arg[0] && |
3460 |
|
ic[-2].f == instr(nop) && ic[-1].f == instr(nop)) { |
3461 |
|
ic[-8].f = instr(netbsd_r3k_picache_do_inv); |
3462 |
|
} |
3463 |
|
} |
3464 |
|
|
3465 |
|
|
3466 |
|
/* |
3467 |
|
* Combine: something ending with a nop. |
3468 |
|
* |
3469 |
|
* NetBSD's strlen core. |
3470 |
|
* [Conditional] branch, followed by nop. |
3471 |
|
*/ |
3472 |
|
void COMBINE(nop)(struct cpu *cpu, struct mips_instr_call *ic, int low_addr) |
3473 |
|
{ |
3474 |
|
int n_back = (low_addr >> MIPS_INSTR_ALIGNMENT_SHIFT) |
3475 |
|
& (MIPS_IC_ENTRIES_PER_PAGE - 1); |
3476 |
|
|
3477 |
|
#ifdef MODE32 |
3478 |
|
if (n_back < 3) |
3479 |
|
return; |
3480 |
|
|
3481 |
|
if ((ic[-3].f == mips32_loadstore[1] || |
3482 |
|
ic[-3].f == mips32_loadstore[16 + 1]) && |
3483 |
|
ic[-3].arg[2] == 0 && |
3484 |
|
ic[-3].arg[0] == ic[-1].arg[0] && ic[-3].arg[1] == ic[-2].arg[0] && |
3485 |
|
ic[-2].arg[0] == ic[-2].arg[1] && ic[-2].arg[2] == 1 && |
3486 |
|
ic[-2].f == instr(addiu) && ic[-1].arg[2] == (size_t) &ic[-3] && |
3487 |
|
ic[-1].arg[1] == (size_t) &cpu->cd.mips.gpr[MIPS_GPR_ZERO] && |
3488 |
|
ic[-1].f == instr(bne_samepage)) { |
3489 |
|
ic[-3].f = instr(netbsd_strlen); |
3490 |
|
return; |
3491 |
|
} |
3492 |
|
#endif |
3493 |
|
|
3494 |
|
if (n_back < 1) |
3495 |
|
return; |
3496 |
|
|
3497 |
|
if (ic[-1].f == instr(bne_samepage)) { |
3498 |
|
ic[-1].f = instr(bne_samepage_nop); |
3499 |
|
return; |
3500 |
|
} |
3501 |
|
|
3502 |
|
if (ic[-1].f == instr(beq_samepage)) { |
3503 |
|
ic[-1].f = instr(beq_samepage_nop); |
3504 |
|
return; |
3505 |
|
} |
3506 |
|
|
3507 |
|
/* TODO: other branches that are followed by nop should be here */ |
3508 |
|
} |
3509 |
|
|
3510 |
|
|
3511 |
|
/* |
3512 |
|
* 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) |
if (n_back < 1) |
3546 |
return; |
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. |
3582 |
|
*/ |
3583 |
|
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) |
3586 |
|
& (MIPS_IC_ENTRIES_PER_PAGE - 1); |
3587 |
|
|
3588 |
|
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; |
3595 |
|
} |
3596 |
|
|
3597 |
|
if (ic[-1].f == instr(set)) { |
3598 |
|
ic[-1].f = instr(lui_addiu); |
3599 |
|
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); |
3604 |
combined; |
return; |
3605 |
|
} |
3606 |
|
|
3607 |
|
if (ic[-1].f == instr(beq_samepage)) { |
3608 |
|
ic[-1].f = instr(beq_samepage_addiu); |
3609 |
|
return; |
3610 |
|
} |
3611 |
|
|
3612 |
|
if (ic[-1].f == instr(bne_samepage)) { |
3613 |
|
ic[-1].f = instr(bne_samepage_addiu); |
3614 |
|
return; |
3615 |
|
} |
3616 |
|
|
3617 |
|
if (ic[-1].f == instr(jr_ra)) { |
3618 |
|
ic[-1].f = instr(jr_ra_addiu); |
3619 |
|
return; |
3620 |
} |
} |
3621 |
|
|
3622 |
/* TODO: other branches that are followed by addiu should be here */ |
/* TODO: other branches that are followed by addiu should be here */ |
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: |
4093 |
case HI6_XORI: ic->f = instr(xori); break; |
case HI6_XORI: ic->f = instr(xori); break; |
4094 |
} |
} |
4095 |
|
|
4096 |
|
if (ic->arg[2] == 0) { |
4097 |
|
if ((cpu->is_32bit && ic->f == instr(addiu)) || |
4098 |
|
(!cpu->is_32bit && ic->f == instr(daddiu))) { |
4099 |
|
ic->f = instr(mov); |
4100 |
|
ic->arg[2] = ic->arg[1]; |
4101 |
|
} |
4102 |
|
} |
4103 |
|
|
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(b_addiu); |
cpu->cd.mips.combination_check = COMBINE(addiu); |
4111 |
if (ic->f == instr(daddiu)) |
if (ic->f == instr(daddiu)) |
4112 |
cpu->cd.mips.combination_check = COMBINE(b_daddiu); |
cpu->cd.mips.combination_check = COMBINE(b_daddiu); |
4113 |
break; |
break; |
4116 |
ic->f = instr(set); |
ic->f = instr(set); |
4117 |
ic->arg[0] = (size_t)&cpu->cd.mips.gpr[rt]; |
ic->arg[0] = (size_t)&cpu->cd.mips.gpr[rt]; |
4118 |
ic->arg[1] = (int32_t) (imm << 16); |
ic->arg[1] = (int32_t) (imm << 16); |
4119 |
|
/* NOTE: Don't use arg[2] here. It can be used with |
4120 |
|
instruction combinations, to do lui + addiu, etc. */ |
4121 |
if (rt == MIPS_GPR_ZERO) |
if (rt == MIPS_GPR_ZERO) |
4122 |
ic->f = instr(nop); |
ic->f = instr(nop); |
4123 |
break; |
break; |
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: |
4237 |
ic->arg[1] = rd + ((iword & 7) << 5); |
ic->arg[1] = rd + ((iword & 7) << 5); |
4238 |
ic->arg[2] = addr & 0xffc; |
ic->arg[2] = addr & 0xffc; |
4239 |
ic->f = rs == COPz_MTCz? instr(mtc0) : instr(dmtc0); |
ic->f = rs == COPz_MTCz? instr(mtc0) : instr(dmtc0); |
4240 |
|
|
4241 |
|
if (cpu->cd.mips.cpu_type.exc_model == EXC3K && |
4242 |
|
rs == COPz_MTCz && rd == COP0_STATUS) |
4243 |
|
cpu->cd.mips.combination_check = |
4244 |
|
COMBINE(netbsd_r3k_cache_inv); |
4245 |
|
|
4246 |
break; |
break; |
4247 |
case 8: if (iword == 0x4100ffff) { |
case 8: if (iword == 0x4100ffff) { |
4248 |
/* R2020 DECstation write-loop thingy. */ |
/* R2020 DECstation write-loop thingy. */ |
4560 |
/* Load into the dummy scratch register, if rt = zero */ |
/* Load into the dummy scratch register, if rt = zero */ |
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 loads or stores in a row using the same |
4565 |
|
base register: */ |
4566 |
|
#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); |
4571 |
|
#endif |
4572 |
break; |
break; |
4573 |
|
|
4574 |
case HI6_LL: |
case HI6_LL: |
4688 |
cpu->cd.mips.cpu_type.isa_revision < 2) { |
cpu->cd.mips.cpu_type.isa_revision < 2) { |
4689 |
static int warning = 0; |
static int warning = 0; |
4690 |
if (!warning) { |
if (!warning) { |
4691 |
fatal("[ WARNING! SPECIAL3 opcode used on a" |
fatal("[ WARNING! SPECIAL3 opcode used, but" |
4692 |
" cpu which doesn't implement it ]\n"); |
" the %s processor does not implement " |
4693 |
|
"such instructions. Only printing this " |
4694 |
|
"warning once. ]\n", |
4695 |
|
cpu->cd.mips.cpu_type.name); |
4696 |
warning = 1; |
warning = 1; |
4697 |
} |
} |
4698 |
ic->f = instr(reserved); |
ic->f = instr(reserved); |
4741 |
} |
} |
4742 |
#endif |
#endif |
4743 |
|
|
4744 |
|
if (ic->f == instr(nop) && cpu->cd.mips.combination_check == NULL) |
4745 |
|
cpu->cd.mips.combination_check = COMBINE(nop); |
4746 |
|
|
4747 |
|
|
4748 |
#define DYNTRANS_TO_BE_TRANSLATED_TAIL |
#define DYNTRANS_TO_BE_TRANSLATED_TAIL |
4749 |
#include "cpu_dyntrans.c" |
#include "cpu_dyntrans.c" |