1 |
/* |
/* |
2 |
* Copyright (C) 2005-2006 Anders Gavare. All rights reserved. |
* Copyright (C) 2005-2007 Anders Gavare. All rights reserved. |
3 |
* |
* |
4 |
* Redistribution and use in source and binary forms, with or without |
* Redistribution and use in source and binary forms, with or without |
5 |
* modification, are permitted provided that the following conditions are met: |
* modification, are permitted provided that the following conditions are met: |
25 |
* SUCH DAMAGE. |
* SUCH DAMAGE. |
26 |
* |
* |
27 |
* |
* |
28 |
* $Id: cpu_mips_instr.c,v 1.118 2006/10/29 05:10:27 debug Exp $ |
* $Id: cpu_mips_instr.c,v 1.124 2007/02/03 10:00:52 debug Exp $ |
29 |
* |
* |
30 |
* MIPS instructions. |
* MIPS instructions. |
31 |
* |
* |
2586 |
|
|
2587 |
|
|
2588 |
#ifdef MODE32 |
#ifdef MODE32 |
2589 |
/* |
/* multi_{l,s}w_2, _3, etc. */ |
2590 |
* multi_sw_2, _3, _4: |
#include "tmp_mips_loadstore_multi.c" |
|
* |
|
|
* sw r?,ofs(rX) r?=arg[0], rX=arg[1], ofs=arg[2] |
|
|
*/ |
|
|
X(multi_sw_2_le) |
|
|
{ |
|
|
uint32_t *page; |
|
|
MODE_uint_t rX = reg(ic[0].arg[1]), r1, r2; |
|
|
MODE_uint_t addr0 = rX + (int32_t)ic[0].arg[2]; |
|
|
MODE_uint_t addr1 = rX + (int32_t)ic[1].arg[2]; |
|
|
uint32_t index0 = addr0 >> 12, index1 = addr1 >> 12; |
|
|
|
|
|
page = (uint32_t *) cpu->cd.mips.host_store[index0]; |
|
|
|
|
|
/* Fallback: */ |
|
|
if (cpu->delay_slot || |
|
|
page == NULL || (addr0 & 3) != 0 || (addr1 & 3) != 0 || |
|
|
index0 != index1) { |
|
|
/* Normal safe sw: */ |
|
|
mips32_loadstore[8 + 2 * 2](cpu, ic); |
|
|
return; |
|
|
} |
|
|
|
|
|
addr0 = (addr0 >> 2) & 0x3ff; |
|
|
addr1 = (addr1 >> 2) & 0x3ff; |
|
|
|
|
|
r1 = reg(ic[0].arg[0]); |
|
|
r2 = reg(ic[1].arg[0]); |
|
|
|
|
|
r1 = LE32_TO_HOST(r1); |
|
|
r2 = LE32_TO_HOST(r2); |
|
|
|
|
|
page[addr0] = r1; |
|
|
page[addr1] = r2; |
|
|
|
|
|
cpu->n_translated_instrs ++; |
|
|
cpu->cd.mips.next_ic ++; |
|
|
} |
|
|
X(multi_sw_2_be) |
|
|
{ |
|
|
uint32_t *page; |
|
|
MODE_uint_t rX = reg(ic[0].arg[1]), r1, r2; |
|
|
MODE_uint_t addr0 = rX + (int32_t)ic[0].arg[2]; |
|
|
MODE_uint_t addr1 = rX + (int32_t)ic[1].arg[2]; |
|
|
uint32_t index0 = addr0 >> 12, index1 = addr1 >> 12; |
|
|
|
|
|
page = (uint32_t *) cpu->cd.mips.host_store[index0]; |
|
|
|
|
|
/* Fallback: */ |
|
|
if (cpu->delay_slot || |
|
|
page == NULL || (addr0 & 3) != 0 || (addr1 & 3) != 0 || |
|
|
index0 != index1) { |
|
|
/* Normal safe sw: */ |
|
|
mips32_loadstore[16 + 8 + 2 * 2](cpu, ic); |
|
|
return; |
|
|
} |
|
|
|
|
|
addr0 = (addr0 >> 2) & 0x3ff; |
|
|
addr1 = (addr1 >> 2) & 0x3ff; |
|
|
|
|
|
r1 = reg(ic[0].arg[0]); |
|
|
r2 = reg(ic[1].arg[0]); |
|
|
|
|
|
r1 = BE32_TO_HOST(r1); |
|
|
r2 = BE32_TO_HOST(r2); |
|
|
|
|
|
page[addr0] = r1; |
|
|
page[addr1] = r2; |
|
|
|
|
|
cpu->n_translated_instrs ++; |
|
|
cpu->cd.mips.next_ic ++; |
|
|
} |
|
|
X(multi_sw_3_le) |
|
|
{ |
|
|
uint32_t *page; |
|
|
MODE_uint_t rX = reg(ic[0].arg[1]), r1, r2, r3; |
|
|
MODE_uint_t addr0 = rX + (int32_t)ic[0].arg[2]; |
|
|
MODE_uint_t addr1 = rX + (int32_t)ic[1].arg[2]; |
|
|
MODE_uint_t addr2 = rX + (int32_t)ic[2].arg[2]; |
|
|
uint32_t index0 = addr0 >> 12, index1 = addr1 >> 12, |
|
|
index2 = addr2 >> 12; |
|
|
|
|
|
page = (uint32_t *) cpu->cd.mips.host_store[index0]; |
|
|
|
|
|
/* Fallback: */ |
|
|
if (cpu->delay_slot || |
|
|
page == NULL || (addr0 & 3) != 0 || (addr1 & 3) != 0 || |
|
|
(addr2 & 3) != 0 || index0 != index1 || index0 != index2) { |
|
|
/* Normal safe sw: */ |
|
|
mips32_loadstore[8 + 2 * 2](cpu, ic); |
|
|
return; |
|
|
} |
|
|
|
|
|
addr0 = (addr0 >> 2) & 0x3ff; |
|
|
addr1 = (addr1 >> 2) & 0x3ff; |
|
|
addr2 = (addr2 >> 2) & 0x3ff; |
|
|
|
|
|
/* printf("addr0=%x 1=%x 2=%x\n", |
|
|
(int)addr0, (int)addr1, (int)addr2); */ |
|
|
|
|
|
r1 = reg(ic[0].arg[0]); |
|
|
r2 = reg(ic[1].arg[0]); |
|
|
r3 = reg(ic[2].arg[0]); |
|
|
|
|
|
r1 = LE32_TO_HOST(r1); |
|
|
r2 = LE32_TO_HOST(r2); |
|
|
r3 = LE32_TO_HOST(r3); |
|
|
|
|
|
page[addr0] = r1; |
|
|
page[addr1] = r2; |
|
|
page[addr2] = r3; |
|
|
|
|
|
cpu->n_translated_instrs += 2; |
|
|
cpu->cd.mips.next_ic += 2; |
|
|
} |
|
|
X(multi_sw_3_be) |
|
|
{ |
|
|
uint32_t *page; |
|
|
MODE_uint_t rX = reg(ic[0].arg[1]), r1, r2, r3; |
|
|
MODE_uint_t addr0 = rX + (int32_t)ic[0].arg[2]; |
|
|
MODE_uint_t addr1 = rX + (int32_t)ic[1].arg[2]; |
|
|
MODE_uint_t addr2 = rX + (int32_t)ic[2].arg[2]; |
|
|
uint32_t index0 = addr0 >> 12, index1 = addr1 >> 12, |
|
|
index2 = addr2 >> 12; |
|
|
|
|
|
page = (uint32_t *) cpu->cd.mips.host_store[index0]; |
|
|
|
|
|
/* Fallback: */ |
|
|
if (cpu->delay_slot || |
|
|
page == NULL || (addr0 & 3) != 0 || (addr1 & 3) != 0 || |
|
|
(addr2 & 3) != 0 || index0 != index1 || index0 != index2) { |
|
|
/* Normal safe sw: */ |
|
|
mips32_loadstore[16 + 8 + 2 * 2](cpu, ic); |
|
|
return; |
|
|
} |
|
|
|
|
|
addr0 = (addr0 >> 2) & 0x3ff; |
|
|
addr1 = (addr1 >> 2) & 0x3ff; |
|
|
addr2 = (addr2 >> 2) & 0x3ff; |
|
|
|
|
|
/* printf("addr0=%x 1=%x 2=%x\n", |
|
|
(int)addr0, (int)addr1, (int)addr2); */ |
|
|
|
|
|
r1 = reg(ic[0].arg[0]); |
|
|
r2 = reg(ic[1].arg[0]); |
|
|
r3 = reg(ic[2].arg[0]); |
|
|
|
|
|
r1 = BE32_TO_HOST(r1); |
|
|
r2 = BE32_TO_HOST(r2); |
|
|
r3 = BE32_TO_HOST(r3); |
|
|
|
|
|
page[addr0] = r1; |
|
|
page[addr1] = r2; |
|
|
page[addr2] = r3; |
|
|
|
|
|
cpu->n_translated_instrs += 2; |
|
|
cpu->cd.mips.next_ic += 2; |
|
|
} |
|
|
X(multi_sw_4_le) |
|
|
{ |
|
|
uint32_t *page; |
|
|
MODE_uint_t rX = reg(ic[0].arg[1]), r1, r2, r3, r4; |
|
|
MODE_uint_t addr0 = rX + (int32_t)ic[0].arg[2]; |
|
|
MODE_uint_t addr1 = rX + (int32_t)ic[1].arg[2]; |
|
|
MODE_uint_t addr2 = rX + (int32_t)ic[2].arg[2]; |
|
|
MODE_uint_t addr3 = rX + (int32_t)ic[3].arg[2]; |
|
|
uint32_t index0 = addr0 >> 12, index1 = addr1 >> 12, |
|
|
index2 = addr2 >> 12, index3 = addr3 >> 12; |
|
|
|
|
|
page = (uint32_t *) cpu->cd.mips.host_store[index0]; |
|
|
|
|
|
/* Fallback: */ |
|
|
if (cpu->delay_slot || |
|
|
page == NULL || (addr0 & 3) != 0 || (addr1 & 3) != 0 || |
|
|
(addr2 & 3) != 0 || (addr3 & 3) != 0 || index0 != index1 || |
|
|
index0 != index2 || index0 != index3) { |
|
|
/* Normal safe sw: */ |
|
|
mips32_loadstore[8 + 2 * 2](cpu, ic); |
|
|
return; |
|
|
} |
|
|
|
|
|
addr0 = (addr0 >> 2) & 0x3ff; |
|
|
addr1 = (addr1 >> 2) & 0x3ff; |
|
|
addr2 = (addr2 >> 2) & 0x3ff; |
|
|
addr3 = (addr3 >> 2) & 0x3ff; |
|
|
|
|
|
r1 = reg(ic[0].arg[0]); |
|
|
r2 = reg(ic[1].arg[0]); |
|
|
r3 = reg(ic[2].arg[0]); |
|
|
r4 = reg(ic[3].arg[0]); |
|
|
|
|
|
r1 = LE32_TO_HOST(r1); |
|
|
r2 = LE32_TO_HOST(r2); |
|
|
r3 = LE32_TO_HOST(r3); |
|
|
r4 = LE32_TO_HOST(r4); |
|
|
|
|
|
page[addr0] = r1; |
|
|
page[addr1] = r2; |
|
|
page[addr2] = r3; |
|
|
page[addr3] = r4; |
|
|
|
|
|
cpu->n_translated_instrs += 3; |
|
|
cpu->cd.mips.next_ic += 3; |
|
|
} |
|
|
X(multi_sw_4_be) |
|
|
{ |
|
|
uint32_t *page; |
|
|
MODE_uint_t rX = reg(ic[0].arg[1]), r1, r2, r3, r4; |
|
|
MODE_uint_t addr0 = rX + (int32_t)ic[0].arg[2]; |
|
|
MODE_uint_t addr1 = rX + (int32_t)ic[1].arg[2]; |
|
|
MODE_uint_t addr2 = rX + (int32_t)ic[2].arg[2]; |
|
|
MODE_uint_t addr3 = rX + (int32_t)ic[3].arg[2]; |
|
|
uint32_t index0 = addr0 >> 12, index1 = addr1 >> 12, |
|
|
index2 = addr2 >> 12, index3 = addr3 >> 12; |
|
|
|
|
|
page = (uint32_t *) cpu->cd.mips.host_store[index0]; |
|
|
|
|
|
/* Fallback: */ |
|
|
if (cpu->delay_slot || |
|
|
page == NULL || (addr0 & 3) != 0 || (addr1 & 3) != 0 || |
|
|
(addr2 & 3) != 0 || (addr3 & 3) != 0 || index0 != index1 || |
|
|
index0 != index2 || index0 != index3) { |
|
|
/* Normal safe sw: */ |
|
|
mips32_loadstore[16 + 8 + 2 * 2](cpu, ic); |
|
|
return; |
|
|
} |
|
|
|
|
|
addr0 = (addr0 >> 2) & 0x3ff; |
|
|
addr1 = (addr1 >> 2) & 0x3ff; |
|
|
addr2 = (addr2 >> 2) & 0x3ff; |
|
|
addr3 = (addr3 >> 2) & 0x3ff; |
|
|
|
|
|
r1 = reg(ic[0].arg[0]); |
|
|
r2 = reg(ic[1].arg[0]); |
|
|
r3 = reg(ic[2].arg[0]); |
|
|
r4 = reg(ic[3].arg[0]); |
|
|
|
|
|
r1 = BE32_TO_HOST(r1); |
|
|
r2 = BE32_TO_HOST(r2); |
|
|
r3 = BE32_TO_HOST(r3); |
|
|
r4 = BE32_TO_HOST(r4); |
|
|
|
|
|
page[addr0] = r1; |
|
|
page[addr1] = r2; |
|
|
page[addr2] = r3; |
|
|
page[addr3] = r4; |
|
|
|
|
|
cpu->n_translated_instrs += 3; |
|
|
cpu->cd.mips.next_ic += 3; |
|
|
} |
|
|
#endif |
|
|
|
|
|
|
|
|
#ifdef MODE32 |
|
|
/* |
|
|
* multi_lw_2, _3, _4: |
|
|
* |
|
|
* lw r?,ofs(rX) r?=arg[0], rX=arg[1], ofs=arg[2] |
|
|
*/ |
|
|
X(multi_lw_2_le) |
|
|
{ |
|
|
uint32_t *page; |
|
|
MODE_uint_t rX = reg(ic[0].arg[1]), r1, r2; |
|
|
MODE_uint_t addr0 = rX + (int32_t)ic[0].arg[2]; |
|
|
MODE_uint_t addr1 = rX + (int32_t)ic[1].arg[2]; |
|
|
uint32_t index0 = addr0 >> 12, index1 = addr1 >> 12; |
|
|
|
|
|
page = (uint32_t *) cpu->cd.mips.host_load[index0]; |
|
|
|
|
|
/* Fallback: */ |
|
|
if (cpu->delay_slot || |
|
|
page == NULL || (addr0 & 3) != 0 || (addr1 & 3) != 0 || |
|
|
index0 != index1) { |
|
|
/* Normal safe lw: */ |
|
|
mips32_loadstore[2 * 2 + 1](cpu, ic); |
|
|
return; |
|
|
} |
|
|
|
|
|
addr0 = (addr0 >> 2) & 0x3ff; |
|
|
addr1 = (addr1 >> 2) & 0x3ff; |
|
|
|
|
|
r1 = page[addr0]; |
|
|
r2 = page[addr1]; |
|
|
|
|
|
r1 = LE32_TO_HOST(r1); |
|
|
r2 = LE32_TO_HOST(r2); |
|
|
|
|
|
reg(ic[0].arg[0]) = r1; |
|
|
reg(ic[1].arg[0]) = r2; |
|
|
|
|
|
cpu->n_translated_instrs ++; |
|
|
cpu->cd.mips.next_ic ++; |
|
|
} |
|
|
X(multi_lw_2_be) |
|
|
{ |
|
|
uint32_t *page; |
|
|
MODE_uint_t rX = reg(ic[0].arg[1]), r1, r2; |
|
|
MODE_uint_t addr0 = rX + (int32_t)ic[0].arg[2]; |
|
|
MODE_uint_t addr1 = rX + (int32_t)ic[1].arg[2]; |
|
|
uint32_t index0 = addr0 >> 12, index1 = addr1 >> 12; |
|
|
|
|
|
page = (uint32_t *) cpu->cd.mips.host_load[index0]; |
|
|
|
|
|
/* Fallback: */ |
|
|
if (cpu->delay_slot || |
|
|
page == NULL || (addr0 & 3) != 0 || (addr1 & 3) != 0 || |
|
|
index0 != index1) { |
|
|
/* Normal safe lw: */ |
|
|
mips32_loadstore[16 + 2 * 2 + 1](cpu, ic); |
|
|
return; |
|
|
} |
|
|
|
|
|
addr0 = (addr0 >> 2) & 0x3ff; |
|
|
addr1 = (addr1 >> 2) & 0x3ff; |
|
|
|
|
|
r1 = page[addr0]; |
|
|
r2 = page[addr1]; |
|
|
|
|
|
r1 = BE32_TO_HOST(r1); |
|
|
r2 = BE32_TO_HOST(r2); |
|
|
|
|
|
reg(ic[0].arg[0]) = r1; |
|
|
reg(ic[1].arg[0]) = r2; |
|
|
|
|
|
cpu->n_translated_instrs ++; |
|
|
cpu->cd.mips.next_ic ++; |
|
|
} |
|
|
X(multi_lw_3_le) |
|
|
{ |
|
|
uint32_t *page; |
|
|
MODE_uint_t rX = reg(ic[0].arg[1]), r1, r2, r3; |
|
|
MODE_uint_t addr0 = rX + (int32_t)ic[0].arg[2]; |
|
|
MODE_uint_t addr1 = rX + (int32_t)ic[1].arg[2]; |
|
|
MODE_uint_t addr2 = rX + (int32_t)ic[2].arg[2]; |
|
|
uint32_t index0 = addr0 >> 12, index1 = addr1 >> 12, |
|
|
index2 = addr2 >> 12; |
|
|
|
|
|
page = (uint32_t *) cpu->cd.mips.host_load[index0]; |
|
|
|
|
|
/* Fallback: */ |
|
|
if (cpu->delay_slot || |
|
|
page == NULL || (addr0 & 3) != 0 || (addr1 & 3) != 0 || |
|
|
(addr2 & 3) != 0 || index0 != index1 || index0 != index2) { |
|
|
/* Normal safe lw: */ |
|
|
mips32_loadstore[2 * 2 + 1](cpu, ic); |
|
|
return; |
|
|
} |
|
|
|
|
|
addr0 = (addr0 >> 2) & 0x3ff; |
|
|
addr1 = (addr1 >> 2) & 0x3ff; |
|
|
addr2 = (addr2 >> 2) & 0x3ff; |
|
|
|
|
|
/* printf("addr0=%x 1=%x 2=%x\n", |
|
|
(int)addr0, (int)addr1, (int)addr2); */ |
|
|
|
|
|
r1 = page[addr0]; |
|
|
r2 = page[addr1]; |
|
|
r3 = page[addr2]; |
|
|
|
|
|
r1 = LE32_TO_HOST(r1); |
|
|
r2 = LE32_TO_HOST(r2); |
|
|
r3 = LE32_TO_HOST(r3); |
|
|
|
|
|
reg(ic[0].arg[0]) = r1; |
|
|
reg(ic[1].arg[0]) = r2; |
|
|
reg(ic[2].arg[0]) = r3; |
|
|
|
|
|
cpu->n_translated_instrs += 2; |
|
|
cpu->cd.mips.next_ic += 2; |
|
|
} |
|
|
X(multi_lw_3_be) |
|
|
{ |
|
|
uint32_t *page; |
|
|
MODE_uint_t rX = reg(ic[0].arg[1]), r1, r2, r3; |
|
|
MODE_uint_t addr0 = rX + (int32_t)ic[0].arg[2]; |
|
|
MODE_uint_t addr1 = rX + (int32_t)ic[1].arg[2]; |
|
|
MODE_uint_t addr2 = rX + (int32_t)ic[2].arg[2]; |
|
|
uint32_t index0 = addr0 >> 12, index1 = addr1 >> 12, |
|
|
index2 = addr2 >> 12; |
|
|
|
|
|
page = (uint32_t *) cpu->cd.mips.host_load[index0]; |
|
|
|
|
|
/* Fallback: */ |
|
|
if (cpu->delay_slot || |
|
|
page == NULL || (addr0 & 3) != 0 || (addr1 & 3) != 0 || |
|
|
(addr2 & 3) != 0 || index0 != index1 || index0 != index2) { |
|
|
/* Normal safe lw: */ |
|
|
mips32_loadstore[16 + 2 * 2 + 1](cpu, ic); |
|
|
return; |
|
|
} |
|
|
|
|
|
addr0 = (addr0 >> 2) & 0x3ff; |
|
|
addr1 = (addr1 >> 2) & 0x3ff; |
|
|
addr2 = (addr2 >> 2) & 0x3ff; |
|
|
|
|
|
/* printf("addr0=%x 1=%x 2=%x\n", |
|
|
(int)addr0, (int)addr1, (int)addr2); */ |
|
|
|
|
|
r1 = page[addr0]; |
|
|
r2 = page[addr1]; |
|
|
r3 = page[addr2]; |
|
|
|
|
|
r1 = BE32_TO_HOST(r1); |
|
|
r2 = BE32_TO_HOST(r2); |
|
|
r3 = BE32_TO_HOST(r3); |
|
|
|
|
|
reg(ic[0].arg[0]) = r1; |
|
|
reg(ic[1].arg[0]) = r2; |
|
|
reg(ic[2].arg[0]) = r3; |
|
|
|
|
|
cpu->n_translated_instrs += 2; |
|
|
cpu->cd.mips.next_ic += 2; |
|
|
} |
|
|
X(multi_lw_4_le) |
|
|
{ |
|
|
uint32_t *page; |
|
|
MODE_uint_t rX = reg(ic[0].arg[1]), r1, r2, r3, r4; |
|
|
MODE_uint_t addr0 = rX + (int32_t)ic[0].arg[2]; |
|
|
MODE_uint_t addr1 = rX + (int32_t)ic[1].arg[2]; |
|
|
MODE_uint_t addr2 = rX + (int32_t)ic[2].arg[2]; |
|
|
MODE_uint_t addr3 = rX + (int32_t)ic[3].arg[2]; |
|
|
uint32_t index0 = addr0 >> 12, index1 = addr1 >> 12, |
|
|
index2 = addr2 >> 12, index3 = addr3 >> 12; |
|
|
|
|
|
page = (uint32_t *) cpu->cd.mips.host_load[index0]; |
|
|
|
|
|
/* Fallback: */ |
|
|
if (cpu->delay_slot || |
|
|
page == NULL || (addr0 & 3) != 0 || (addr1 & 3) != 0 || |
|
|
(addr2 & 3) != 0 || (addr3 & 3) != 0 || |
|
|
index0 != index1 || index0 != index2 || index0 != index3) { |
|
|
/* Normal safe lw: */ |
|
|
mips32_loadstore[2 * 2 + 1](cpu, ic); |
|
|
return; |
|
|
} |
|
|
|
|
|
addr0 = (addr0 >> 2) & 0x3ff; |
|
|
addr1 = (addr1 >> 2) & 0x3ff; |
|
|
addr2 = (addr2 >> 2) & 0x3ff; |
|
|
addr3 = (addr3 >> 2) & 0x3ff; |
|
|
|
|
|
r1 = page[addr0]; |
|
|
r2 = page[addr1]; |
|
|
r3 = page[addr2]; |
|
|
r4 = page[addr3]; |
|
|
|
|
|
r1 = LE32_TO_HOST(r1); |
|
|
r2 = LE32_TO_HOST(r2); |
|
|
r3 = LE32_TO_HOST(r3); |
|
|
r4 = LE32_TO_HOST(r4); |
|
|
|
|
|
reg(ic[0].arg[0]) = r1; |
|
|
reg(ic[1].arg[0]) = r2; |
|
|
reg(ic[2].arg[0]) = r3; |
|
|
reg(ic[3].arg[0]) = r4; |
|
|
|
|
|
cpu->n_translated_instrs += 3; |
|
|
cpu->cd.mips.next_ic += 3; |
|
|
} |
|
|
X(multi_lw_4_be) |
|
|
{ |
|
|
uint32_t *page; |
|
|
MODE_uint_t rX = reg(ic[0].arg[1]), r1, r2, r3, r4; |
|
|
MODE_uint_t addr0 = rX + (int32_t)ic[0].arg[2]; |
|
|
MODE_uint_t addr1 = rX + (int32_t)ic[1].arg[2]; |
|
|
MODE_uint_t addr2 = rX + (int32_t)ic[2].arg[2]; |
|
|
MODE_uint_t addr3 = rX + (int32_t)ic[3].arg[2]; |
|
|
uint32_t index0 = addr0 >> 12, index1 = addr1 >> 12, |
|
|
index2 = addr2 >> 12, index3 = addr3 >> 12; |
|
|
|
|
|
page = (uint32_t *) cpu->cd.mips.host_load[index0]; |
|
|
|
|
|
/* Fallback: */ |
|
|
if (cpu->delay_slot || |
|
|
page == NULL || (addr0 & 3) != 0 || (addr1 & 3) != 0 || |
|
|
(addr2 & 3) != 0 || (addr3 & 3) != 0 || |
|
|
index0 != index1 || index0 != index2 || index0 != index3) { |
|
|
/* Normal safe lw: */ |
|
|
mips32_loadstore[16 + 2 * 2 + 1](cpu, ic); |
|
|
return; |
|
|
} |
|
|
|
|
|
addr0 = (addr0 >> 2) & 0x3ff; |
|
|
addr1 = (addr1 >> 2) & 0x3ff; |
|
|
addr2 = (addr2 >> 2) & 0x3ff; |
|
|
addr3 = (addr3 >> 2) & 0x3ff; |
|
|
|
|
|
r1 = page[addr0]; |
|
|
r2 = page[addr1]; |
|
|
r3 = page[addr2]; |
|
|
r4 = page[addr3]; |
|
|
|
|
|
r1 = BE32_TO_HOST(r1); |
|
|
r2 = BE32_TO_HOST(r2); |
|
|
r3 = BE32_TO_HOST(r3); |
|
|
r4 = BE32_TO_HOST(r4); |
|
|
|
|
|
reg(ic[0].arg[0]) = r1; |
|
|
reg(ic[1].arg[0]) = r2; |
|
|
reg(ic[2].arg[0]) = r3; |
|
|
reg(ic[3].arg[0]) = r4; |
|
|
|
|
|
cpu->n_translated_instrs += 3; |
|
|
cpu->cd.mips.next_ic += 3; |
|
|
} |
|
2591 |
#endif |
#endif |
2592 |
|
|
2593 |
|
|
3377 |
int in_crosspage_delayslot = 0; |
int in_crosspage_delayslot = 0; |
3378 |
void (*samepage_function)(struct cpu *, struct mips_instr_call *); |
void (*samepage_function)(struct cpu *, struct mips_instr_call *); |
3379 |
int store, signedness, size; |
int store, signedness, size; |
3380 |
|
#ifdef NATIVE_CODE_GENERATION |
3381 |
|
int native = 0; |
3382 |
|
|
3383 |
|
if (!cpu->currently_translating_to_native) |
3384 |
|
cpu->native_code_function_pointer = (void *) &ic->f; |
3385 |
|
#endif |
3386 |
|
|
3387 |
/* Figure out the (virtual) address of the instruction: */ |
/* Figure out the (virtual) address of the instruction: */ |
3388 |
low_pc = ((size_t)ic - (size_t)cpu->cd.mips.cur_ic_page) |
low_pc = ((size_t)ic - (size_t)cpu->cd.mips.cur_ic_page) |
3532 |
default:goto bad; |
default:goto bad; |
3533 |
} |
} |
3534 |
} |
} |
3535 |
|
|
3536 |
|
#ifdef NATIVE_CODE_GENERATION |
3537 |
|
if (native_code_translation_enabled && |
3538 |
|
!cpu->delay_slot && ic->f == instr(nop)) |
3539 |
|
native = native_nop(cpu); |
3540 |
|
#endif |
3541 |
|
|
3542 |
break; |
break; |
3543 |
|
|
3544 |
case SPECIAL_ADD: |
case SPECIAL_ADD: |
3673 |
|
|
3674 |
if (ic->f == instr(addu)) |
if (ic->f == instr(addu)) |
3675 |
cpu->cd.mips.combination_check = COMBINE(addu); |
cpu->cd.mips.combination_check = COMBINE(addu); |
3676 |
|
|
3677 |
break; |
break; |
3678 |
|
|
3679 |
case SPECIAL_JR: |
case SPECIAL_JR: |
3865 |
instruction combinations, to do lui + addiu, etc. */ |
instruction combinations, to do lui + addiu, etc. */ |
3866 |
if (rt == MIPS_GPR_ZERO) |
if (rt == MIPS_GPR_ZERO) |
3867 |
ic->f = instr(nop); |
ic->f = instr(nop); |
3868 |
|
#ifdef NATIVE_CODE_GENERATION |
3869 |
|
#ifdef MODE32 |
3870 |
|
if (native_code_translation_enabled && !cpu->delay_slot |
3871 |
|
&& (addr & 0xffc) >= 4) |
3872 |
|
native = native_set_u32_p32(cpu, |
3873 |
|
ic->arg[1], ®(&cpu->cd.mips.gpr[rt])); |
3874 |
|
#endif |
3875 |
|
#endif |
3876 |
break; |
break; |
3877 |
|
|
3878 |
case HI6_J: |
case HI6_J: |
4106 |
goto bad; |
goto bad; |
4107 |
break; |
break; |
4108 |
|
|
4109 |
|
case HI6_COP3: |
4110 |
|
/* Always cause a coprocessor unusable exception if |
4111 |
|
there is no coprocessor 3: */ |
4112 |
|
if (cpu->cd.mips.coproc[3] == NULL) { |
4113 |
|
ic->f = instr(cpu); |
4114 |
|
ic->arg[0] = 3; |
4115 |
|
break; |
4116 |
|
} |
4117 |
|
|
4118 |
|
if (iword == 0x4d00ffff) { |
4119 |
|
/* R2020 writeback thing, used by e.g. NetBSD/pmax |
4120 |
|
on MIPSMATE. */ |
4121 |
|
ic->f = instr(nop); |
4122 |
|
} else { |
4123 |
|
fatal("COP3 iword=0x%08x\n", iword); |
4124 |
|
goto bad; |
4125 |
|
} |
4126 |
|
break; |
4127 |
|
|
4128 |
case HI6_SPECIAL2: |
case HI6_SPECIAL2: |
4129 |
if (cpu->cd.mips.cpu_type.rev == MIPS_R5900) { |
if (cpu->cd.mips.cpu_type.rev == MIPS_R5900) { |
4130 |
/* R5900, TX79/C790, have MMI instead of SPECIAL2: */ |
/* R5900, TX79/C790, have MMI instead of SPECIAL2: */ |
4568 |
default:goto bad; |
default:goto bad; |
4569 |
} |
} |
4570 |
|
|
4571 |
|
|
4572 |
#ifdef MODE32 |
#ifdef MODE32 |
4573 |
if (x64) { |
if (x64) { |
4574 |
static int has_warned = 0; |
static int has_warned = 0; |
4581 |
} |
} |
4582 |
#endif |
#endif |
4583 |
|
|
4584 |
|
#ifdef NATIVE_CODE_GENERATION |
4585 |
|
/* |
4586 |
|
* End the native code generation when an instruction is translated |
4587 |
|
* (or found in the following slow) which is not translatable. |
4588 |
|
*/ |
4589 |
|
if (cpu->currently_translating_to_native && (!native || |
4590 |
|
(addr & 0xffc) == 0xffc || |
4591 |
|
cpu->cd.mips.next_ic->f != instr(to_be_translated))) { |
4592 |
|
native_commit(cpu); |
4593 |
|
} |
4594 |
|
#endif |
4595 |
|
|
4596 |
|
|
4597 |
#define DYNTRANS_TO_BE_TRANSLATED_TAIL |
#define DYNTRANS_TO_BE_TRANSLATED_TAIL |
4598 |
#include "cpu_dyntrans.c" |
#include "cpu_dyntrans.c" |