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.118 2006/10/29 05:10:27 debug Exp $ |
29 |
* |
* |
30 |
* MIPS instructions. |
* MIPS instructions. |
31 |
* |
* |
37 |
|
|
38 |
|
|
39 |
/* |
/* |
40 |
|
* COPROC_AVAILABILITY_CHECK(n) checks for the coprocessor available bit for |
41 |
|
* coprocessor number n, and causes a CoProcessor Unusable exception if it |
42 |
|
* is not set. (Note: For coprocessor 0 checks, use cop0_availability_check!) |
43 |
|
*/ |
44 |
|
#ifndef COPROC_AVAILABILITY_CHECK |
45 |
|
#define COPROC_AVAILABILITY_CHECK(x) { \ |
46 |
|
const int cpnr = (x); \ |
47 |
|
int low_pc = ((size_t)ic - (size_t)cpu->cd.mips.cur_ic_page) \ |
48 |
|
/ sizeof(struct mips_instr_call); \ |
49 |
|
cpu->pc &= ~((MIPS_IC_ENTRIES_PER_PAGE-1) \ |
50 |
|
<< MIPS_INSTR_ALIGNMENT_SHIFT); \ |
51 |
|
cpu->pc += (low_pc << MIPS_INSTR_ALIGNMENT_SHIFT); \ |
52 |
|
if (!(cpu->cd.mips.coproc[0]->reg[COP0_STATUS] & \ |
53 |
|
((1 << cpnr) << STATUS_CU_SHIFT)) ) { \ |
54 |
|
mips_cpu_exception(cpu, EXCEPTION_CPU, \ |
55 |
|
0, 0, cpnr, 0, 0, 0); \ |
56 |
|
return; \ |
57 |
|
} \ |
58 |
|
} |
59 |
|
#endif |
60 |
|
|
61 |
|
|
62 |
|
#ifndef COP0_AVAILABILITY_CHECK_INCLUDED |
63 |
|
#define COP0_AVAILABILITY_CHECK_INCLUDED |
64 |
|
/* |
65 |
|
* cop0_availability_check() causes a CoProcessor Unusable exception if |
66 |
|
* we are currently running in usermode, and the coprocessor available bit |
67 |
|
* for coprocessor 0 is not set. |
68 |
|
* |
69 |
|
* Returns 1 if ok (i.e. if the coprocessor was usable), 0 on exceptions. |
70 |
|
*/ |
71 |
|
int cop0_availability_check(struct cpu *cpu, struct mips_instr_call *ic) |
72 |
|
{ |
73 |
|
int in_usermode = 0; |
74 |
|
struct mips_coproc *cp0 = cpu->cd.mips.coproc[0]; |
75 |
|
|
76 |
|
switch (cpu->cd.mips.cpu_type.exc_model) { |
77 |
|
case EXC3K: |
78 |
|
/* |
79 |
|
* NOTE: If the KU bit is checked, Linux crashes. |
80 |
|
* It is the PC that counts. |
81 |
|
* |
82 |
|
* TODO: Check whether this is true or not for R4000 as well. |
83 |
|
*/ |
84 |
|
/* TODO: if (cp0->reg[COP0_STATUS] & MIPS1_SR_KU_CUR) */ |
85 |
|
if (cpu->pc <= 0x7fffffff) |
86 |
|
in_usermode = 1; |
87 |
|
break; |
88 |
|
default: |
89 |
|
/* R4000 etc: (TODO: How about supervisor mode?) */ |
90 |
|
if (((cp0->reg[COP0_STATUS] & |
91 |
|
STATUS_KSU_MASK) >> STATUS_KSU_SHIFT) != KSU_KERNEL) |
92 |
|
in_usermode = 1; |
93 |
|
if (cp0->reg[COP0_STATUS] & (STATUS_ERL | STATUS_EXL)) |
94 |
|
in_usermode = 0; |
95 |
|
break; |
96 |
|
} |
97 |
|
|
98 |
|
if (in_usermode) { |
99 |
|
int low_pc = ((size_t)ic - (size_t)cpu->cd.mips.cur_ic_page) |
100 |
|
/ sizeof(struct mips_instr_call); |
101 |
|
cpu->pc &= ~((MIPS_IC_ENTRIES_PER_PAGE-1) |
102 |
|
<< MIPS_INSTR_ALIGNMENT_SHIFT); |
103 |
|
cpu->pc += (low_pc << MIPS_INSTR_ALIGNMENT_SHIFT); |
104 |
|
if (!(cpu->cd.mips.coproc[0]->reg[COP0_STATUS] & |
105 |
|
(1 << STATUS_CU_SHIFT)) ) { |
106 |
|
mips_cpu_exception(cpu, EXCEPTION_CPU, |
107 |
|
0, 0, /* cpnr */ 0, 0, 0, 0); |
108 |
|
return 0; |
109 |
|
} |
110 |
|
} |
111 |
|
|
112 |
|
return 1; |
113 |
|
} |
114 |
|
#endif |
115 |
|
|
116 |
|
|
117 |
|
/* |
118 |
* invalid: For catching bugs. |
* invalid: For catching bugs. |
119 |
*/ |
*/ |
120 |
X(invalid) |
X(invalid) |
1149 |
|
|
1150 |
|
|
1151 |
/* |
/* |
1152 |
|
* ext: Extract bitfield. |
1153 |
|
* |
1154 |
|
* arg[0] = pointer to rt |
1155 |
|
* arg[1] = pointer to rs |
1156 |
|
* arg[2] = (msbd << 5) + lsb |
1157 |
|
*/ |
1158 |
|
X(ext) |
1159 |
|
{ |
1160 |
|
fatal("ext: todo\n"); |
1161 |
|
exit(1); |
1162 |
|
} |
1163 |
|
|
1164 |
|
|
1165 |
|
/* |
1166 |
|
* dsbh: Doubleword swap bytes within half-word |
1167 |
|
* dshd: Doubleword swap half-words within double-word |
1168 |
|
* wsbh: Word swap bytes within half-word |
1169 |
|
* seb: Sign-extend byte |
1170 |
|
* seh: Sign-extend half-word |
1171 |
|
* |
1172 |
|
* arg[0] = pointer to rt |
1173 |
|
* arg[1] = pointer to rd |
1174 |
|
*/ |
1175 |
|
X(dsbh) |
1176 |
|
{ |
1177 |
|
uint64_t x = reg(ic->arg[0]); |
1178 |
|
x = ((x & 0x00ff00ff00ff00ffULL) << 8) |
1179 |
|
| ((x & 0xff00ff00ff00ff00ULL) >> 8); |
1180 |
|
reg(ic->arg[1]) = x; |
1181 |
|
} |
1182 |
|
X(dshd) |
1183 |
|
{ |
1184 |
|
uint64_t x = reg(ic->arg[0]); |
1185 |
|
x = ((x & 0x000000000000ffffULL) << 48) |
1186 |
|
| ((x & 0x00000000ffff0000ULL) << 16) |
1187 |
|
| ((x & 0x0000ffff00000000ULL) >> 16) |
1188 |
|
| ((x & 0xffff000000000000ULL) >> 48); |
1189 |
|
reg(ic->arg[1]) = x; |
1190 |
|
} |
1191 |
|
X(wsbh) |
1192 |
|
{ |
1193 |
|
uint32_t x = reg(ic->arg[0]); |
1194 |
|
x = ((x & 0x00ff00ff) << 8) | ((x & 0xff00ff00) >> 8); |
1195 |
|
reg(ic->arg[1]) = (int32_t) x; |
1196 |
|
} |
1197 |
|
X(seb) { reg(ic->arg[1]) = (int8_t)reg(ic->arg[0]); } |
1198 |
|
X(seh) { reg(ic->arg[1]) = (int16_t)reg(ic->arg[0]); } |
1199 |
|
|
1200 |
|
|
1201 |
|
/* |
1202 |
* 2-register + immediate: |
* 2-register + immediate: |
1203 |
* |
* |
1204 |
* arg[0] = pointer to rs |
* arg[0] = pointer to rs |
1224 |
res = 0, rem = a; |
res = 0, rem = a; |
1225 |
else |
else |
1226 |
res = a / b, rem = a - b*res; |
res = a / b, rem = a - b*res; |
1227 |
reg(&cpu->cd.mips.lo) = (int32_t)res; |
cpu->cd.mips.lo = (int32_t)res; |
1228 |
reg(&cpu->cd.mips.hi) = (int32_t)rem; |
cpu->cd.mips.hi = (int32_t)rem; |
1229 |
} |
} |
1230 |
X(divu) |
X(divu) |
1231 |
{ |
{ |
1235 |
res = 0, rem = a; |
res = 0, rem = a; |
1236 |
else |
else |
1237 |
res = a / b, rem = a - b*res; |
res = a / b, rem = a - b*res; |
1238 |
reg(&cpu->cd.mips.lo) = (int32_t)res; |
cpu->cd.mips.lo = (int32_t)res; |
1239 |
reg(&cpu->cd.mips.hi) = (int32_t)rem; |
cpu->cd.mips.hi = (int32_t)rem; |
1240 |
} |
} |
1241 |
X(ddiv) |
X(ddiv) |
1242 |
{ |
{ |
1247 |
else |
else |
1248 |
res = a / b; |
res = a / b; |
1249 |
rem = a - b*res; |
rem = a - b*res; |
1250 |
reg(&cpu->cd.mips.lo) = res; |
cpu->cd.mips.lo = res; |
1251 |
reg(&cpu->cd.mips.hi) = rem; |
cpu->cd.mips.hi = rem; |
1252 |
} |
} |
1253 |
X(ddivu) |
X(ddivu) |
1254 |
{ |
{ |
1259 |
else |
else |
1260 |
res = a / b; |
res = a / b; |
1261 |
rem = a - b*res; |
rem = a - b*res; |
1262 |
reg(&cpu->cd.mips.lo) = res; |
cpu->cd.mips.lo = res; |
1263 |
reg(&cpu->cd.mips.hi) = rem; |
cpu->cd.mips.hi = rem; |
1264 |
} |
} |
1265 |
X(mult) |
X(mult) |
1266 |
{ |
{ |
1267 |
int32_t a = reg(ic->arg[0]), b = reg(ic->arg[1]); |
int32_t a = reg(ic->arg[0]), b = reg(ic->arg[1]); |
1268 |
int64_t res = (int64_t)a * (int64_t)b; |
int64_t res = (int64_t)a * (int64_t)b; |
1269 |
reg(&cpu->cd.mips.lo) = (int32_t)res; |
cpu->cd.mips.lo = (int32_t)res; |
1270 |
reg(&cpu->cd.mips.hi) = (int32_t)(res >> 32); |
cpu->cd.mips.hi = (int32_t)(res >> 32); |
1271 |
} |
} |
1272 |
X(mult_r5900) |
X(mult_r5900) |
1273 |
{ |
{ |
1275 |
hi, lo, and a third register */ |
hi, lo, and a third register */ |
1276 |
int32_t a = reg(ic->arg[0]), b = reg(ic->arg[1]); |
int32_t a = reg(ic->arg[0]), b = reg(ic->arg[1]); |
1277 |
int64_t res = (int64_t)a * (int64_t)b; |
int64_t res = (int64_t)a * (int64_t)b; |
1278 |
reg(&cpu->cd.mips.lo) = (int32_t)res; |
cpu->cd.mips.lo = (int32_t)res; |
1279 |
reg(&cpu->cd.mips.hi) = (int32_t)(res >> 32); |
cpu->cd.mips.hi = (int32_t)(res >> 32); |
1280 |
reg(ic->arg[2]) = (int32_t)res; |
reg(ic->arg[2]) = (int32_t)res; |
1281 |
} |
} |
1282 |
X(multu) |
X(multu) |
1283 |
{ |
{ |
1284 |
uint32_t a = reg(ic->arg[0]), b = reg(ic->arg[1]); |
uint32_t a = reg(ic->arg[0]), b = reg(ic->arg[1]); |
1285 |
uint64_t res = (uint64_t)a * (uint64_t)b; |
uint64_t res = (uint64_t)a * (uint64_t)b; |
1286 |
reg(&cpu->cd.mips.lo) = (int32_t)res; |
cpu->cd.mips.lo = (int32_t)res; |
1287 |
reg(&cpu->cd.mips.hi) = (int32_t)(res >> 32); |
cpu->cd.mips.hi = (int32_t)(res >> 32); |
1288 |
} |
} |
1289 |
X(multu_r5900) |
X(multu_r5900) |
1290 |
{ |
{ |
1292 |
hi, lo, and a third register */ |
hi, lo, and a third register */ |
1293 |
uint32_t a = reg(ic->arg[0]), b = reg(ic->arg[1]); |
uint32_t a = reg(ic->arg[0]), b = reg(ic->arg[1]); |
1294 |
uint64_t res = (uint64_t)a * (uint64_t)b; |
uint64_t res = (uint64_t)a * (uint64_t)b; |
1295 |
reg(&cpu->cd.mips.lo) = (int32_t)res; |
cpu->cd.mips.lo = (int32_t)res; |
1296 |
reg(&cpu->cd.mips.hi) = (int32_t)(res >> 32); |
cpu->cd.mips.hi = (int32_t)(res >> 32); |
1297 |
reg(ic->arg[2]) = (int32_t)res; |
reg(ic->arg[2]) = (int32_t)res; |
1298 |
} |
} |
1299 |
X(dmult) |
X(dmult) |
1322 |
hi ^= (int64_t) -1; |
hi ^= (int64_t) -1; |
1323 |
lo ^= (int64_t) -1; |
lo ^= (int64_t) -1; |
1324 |
} |
} |
1325 |
reg(&cpu->cd.mips.lo) = lo; |
cpu->cd.mips.lo = lo; |
1326 |
reg(&cpu->cd.mips.hi) = hi; |
cpu->cd.mips.hi = hi; |
1327 |
} |
} |
1328 |
X(dmultu) |
X(dmultu) |
1329 |
{ |
{ |
1339 |
} |
} |
1340 |
c = (c << 1) | (b >> 63); b <<= 1; |
c = (c << 1) | (b >> 63); b <<= 1; |
1341 |
} |
} |
1342 |
reg(&cpu->cd.mips.lo) = lo; |
cpu->cd.mips.lo = lo; |
1343 |
reg(&cpu->cd.mips.hi) = hi; |
cpu->cd.mips.hi = hi; |
1344 |
} |
} |
1345 |
X(tge) |
X(tge) |
1346 |
{ |
{ |
1749 |
|
|
1750 |
/* |
/* |
1751 |
* set: Set a register to an immediate (signed) 32-bit value. |
* set: Set a register to an immediate (signed) 32-bit value. |
1752 |
|
* (This is the actual implementation of the lui instruction.) |
1753 |
* |
* |
1754 |
* arg[0] = pointer to the register |
* arg[0] = pointer to the register |
1755 |
* arg[1] = (int32_t) immediate value |
* arg[1] = (int32_t) immediate value |
1788 |
coproc_register_read(cpu, cpu->cd.mips.coproc[0], rd, &tmp, select); |
coproc_register_read(cpu, cpu->cd.mips.coproc[0], rd, &tmp, select); |
1789 |
reg(ic->arg[0]) = (int32_t)tmp; |
reg(ic->arg[0]) = (int32_t)tmp; |
1790 |
} |
} |
1791 |
|
X(mfc0_select0) |
1792 |
|
{ |
1793 |
|
/* Fast int32_t read, with no side effects: */ |
1794 |
|
int rd = ic->arg[1] & 31; |
1795 |
|
#if 0 |
1796 |
|
uint64_t tmp; |
1797 |
|
cpu->pc &= ~((MIPS_IC_ENTRIES_PER_PAGE-1)<<MIPS_INSTR_ALIGNMENT_SHIFT); |
1798 |
|
cpu->pc |= ic->arg[2]; |
1799 |
|
/* TODO: cause exception if necessary */ |
1800 |
|
#endif |
1801 |
|
reg(ic->arg[0]) = (int32_t)cpu->cd.mips.coproc[0]->reg[rd]; |
1802 |
|
} |
1803 |
X(mtc0) |
X(mtc0) |
1804 |
{ |
{ |
1805 |
int rd = ic->arg[1] & 31, select = ic->arg[1] >> 5; |
int rd = ic->arg[1] & 31, select = ic->arg[1] >> 5; |
1820 |
uint32_t cause = cpu->cd.mips.coproc[0]->reg[COP0_CAUSE]; |
uint32_t cause = cpu->cd.mips.coproc[0]->reg[COP0_CAUSE]; |
1821 |
/* NOTE: STATUS_IE happens to match the enable bit also |
/* NOTE: STATUS_IE happens to match the enable bit also |
1822 |
on R2000/R3000, so this is ok. */ |
on R2000/R3000, so this is ok. */ |
1823 |
if (status & (STATUS_EXL | STATUS_ERL)) |
if (cpu->cd.mips.cpu_type.exc_model != EXC3K) { |
1824 |
status &= ~STATUS_IE; |
if (status & (STATUS_EXL | STATUS_ERL)) |
1825 |
|
status &= ~STATUS_IE; |
1826 |
|
} |
1827 |
/* Ugly R5900 special case: (TODO: move this?) */ |
/* Ugly R5900 special case: (TODO: move this?) */ |
1828 |
if (cpu->cd.mips.cpu_type.rev == MIPS_R5900 && |
if (cpu->cd.mips.cpu_type.rev == MIPS_R5900 && |
1829 |
!(status & R5900_STATUS_EIE)) |
!(status & R5900_STATUS_EIE)) |
1843 |
coproc_register_read(cpu, cpu->cd.mips.coproc[0], rd, |
coproc_register_read(cpu, cpu->cd.mips.coproc[0], rd, |
1844 |
(uint64_t *)ic->arg[0], select); |
(uint64_t *)ic->arg[0], select); |
1845 |
} |
} |
1846 |
|
X(dmfc0_select0) |
1847 |
|
{ |
1848 |
|
/* Fast int64_t read, with no side effects: */ |
1849 |
|
int rd = ic->arg[1] & 31; |
1850 |
|
#if 0 |
1851 |
|
uint64_t tmp; |
1852 |
|
cpu->pc &= ~((MIPS_IC_ENTRIES_PER_PAGE-1)<<MIPS_INSTR_ALIGNMENT_SHIFT); |
1853 |
|
cpu->pc |= ic->arg[2]; |
1854 |
|
/* TODO: cause exception if necessary */ |
1855 |
|
#endif |
1856 |
|
reg(ic->arg[0]) = cpu->cd.mips.coproc[0]->reg[rd]; |
1857 |
|
} |
1858 |
X(dmtc0) |
X(dmtc0) |
1859 |
{ |
{ |
1860 |
int rd = ic->arg[1] & 31, select = ic->arg[1] >> 5; |
int rd = ic->arg[1] & 31, select = ic->arg[1] >> 5; |
1876 |
X(cop1_bc) |
X(cop1_bc) |
1877 |
{ |
{ |
1878 |
MODE_int_t old_pc = cpu->pc; |
MODE_int_t old_pc = cpu->pc; |
1879 |
const int cpnr = 1; |
int x, cc = ic->arg[0]; |
|
int x, low_pc, cc = ic->arg[0]; |
|
1880 |
|
|
1881 |
low_pc = ((size_t)ic - (size_t)cpu->cd.mips.cur_ic_page) |
COPROC_AVAILABILITY_CHECK(1); |
|
/ sizeof(struct mips_instr_call); |
|
|
cpu->pc &= ~((MIPS_IC_ENTRIES_PER_PAGE-1)<< MIPS_INSTR_ALIGNMENT_SHIFT); |
|
|
cpu->pc += (low_pc << MIPS_INSTR_ALIGNMENT_SHIFT); |
|
|
if (!(cpu->cd.mips.coproc[0]-> |
|
|
reg[COP0_STATUS] & ((1 << cpnr) << STATUS_CU_SHIFT)) ) { |
|
|
mips_cpu_exception(cpu, EXCEPTION_CPU, 0, 0, cpnr, 0, 0, 0); |
|
|
return; |
|
|
} |
|
1882 |
|
|
1883 |
/* Get the correct condition code bit: */ |
/* Get the correct condition code bit: */ |
1884 |
if (cc == 0) |
if (cc == 0) |
1918 |
*/ |
*/ |
1919 |
X(cop1_slow) |
X(cop1_slow) |
1920 |
{ |
{ |
1921 |
const int cpnr = 1; |
COPROC_AVAILABILITY_CHECK(1); |
|
int low_pc = ((size_t)ic - (size_t)cpu->cd.mips.cur_ic_page) |
|
|
/ sizeof(struct mips_instr_call); |
|
|
cpu->pc &= ~((MIPS_IC_ENTRIES_PER_PAGE-1)<< MIPS_INSTR_ALIGNMENT_SHIFT); |
|
|
cpu->pc += (low_pc << MIPS_INSTR_ALIGNMENT_SHIFT); |
|
|
|
|
|
if (!(cpu->cd.mips.coproc[0]-> |
|
|
reg[COP0_STATUS] & ((1 << cpnr) << STATUS_CU_SHIFT)) ) { |
|
|
mips_cpu_exception(cpu, EXCEPTION_CPU, 0, 0, cpnr, 0, 0, 0); |
|
|
return; |
|
|
} |
|
1922 |
|
|
1923 |
coproc_function(cpu, cpu->cd.mips.coproc[1], 1, ic->arg[0], 0, 1); |
coproc_function(cpu, cpu->cd.mips.coproc[1], 1, ic->arg[0], 0, 1); |
1924 |
} |
} |
1943 |
cpu->pc += (low_pc << MIPS_INSTR_ALIGNMENT_SHIFT); |
cpu->pc += (low_pc << MIPS_INSTR_ALIGNMENT_SHIFT); |
1944 |
mips_cpu_exception(cpu, EXCEPTION_BP, 0, 0, 0, 0, 0, 0); |
mips_cpu_exception(cpu, EXCEPTION_BP, 0, 0, 0, 0, 0, 0); |
1945 |
} |
} |
1946 |
|
X(reboot) |
1947 |
|
{ |
1948 |
|
if (!cop0_availability_check(cpu, ic)) |
1949 |
|
return; |
1950 |
|
|
1951 |
|
cpu->running = 0; |
1952 |
|
debugger_n_steps_left_before_interaction = 0; |
1953 |
|
cpu->cd.mips.next_ic = ¬hing_call; |
1954 |
|
} |
1955 |
|
|
1956 |
|
|
1957 |
/* |
/* |
2010 |
*/ |
*/ |
2011 |
X(tlbw) |
X(tlbw) |
2012 |
{ |
{ |
2013 |
|
if (!cop0_availability_check(cpu, ic)) |
2014 |
|
return; |
2015 |
|
|
2016 |
cpu->pc &= ~((MIPS_IC_ENTRIES_PER_PAGE-1)<<MIPS_INSTR_ALIGNMENT_SHIFT); |
cpu->pc &= ~((MIPS_IC_ENTRIES_PER_PAGE-1)<<MIPS_INSTR_ALIGNMENT_SHIFT); |
2017 |
cpu->pc |= ic->arg[2]; |
cpu->pc |= ic->arg[2]; |
2018 |
coproc_tlbwri(cpu, ic->arg[0]); |
coproc_tlbwri(cpu, ic->arg[0]); |
2027 |
*/ |
*/ |
2028 |
X(tlbp) |
X(tlbp) |
2029 |
{ |
{ |
2030 |
|
if (!cop0_availability_check(cpu, ic)) |
2031 |
|
return; |
2032 |
|
|
2033 |
cpu->pc &= ~((MIPS_IC_ENTRIES_PER_PAGE-1)<<MIPS_INSTR_ALIGNMENT_SHIFT); |
cpu->pc &= ~((MIPS_IC_ENTRIES_PER_PAGE-1)<<MIPS_INSTR_ALIGNMENT_SHIFT); |
2034 |
cpu->pc |= ic->arg[2]; |
cpu->pc |= ic->arg[2]; |
2035 |
coproc_tlbpr(cpu, 0); |
coproc_tlbpr(cpu, 0); |
2036 |
} |
} |
2037 |
X(tlbr) |
X(tlbr) |
2038 |
{ |
{ |
2039 |
|
if (!cop0_availability_check(cpu, ic)) |
2040 |
|
return; |
2041 |
|
|
2042 |
cpu->pc &= ~((MIPS_IC_ENTRIES_PER_PAGE-1)<<MIPS_INSTR_ALIGNMENT_SHIFT); |
cpu->pc &= ~((MIPS_IC_ENTRIES_PER_PAGE-1)<<MIPS_INSTR_ALIGNMENT_SHIFT); |
2043 |
cpu->pc |= ic->arg[2]; |
cpu->pc |= ic->arg[2]; |
2044 |
coproc_tlbpr(cpu, 1); |
coproc_tlbpr(cpu, 1); |
2050 |
*/ |
*/ |
2051 |
X(rfe) |
X(rfe) |
2052 |
{ |
{ |
2053 |
|
if (!cop0_availability_check(cpu, ic)) |
2054 |
|
return; |
2055 |
|
|
2056 |
/* Just rotate the interrupt/user bits: */ |
/* Just rotate the interrupt/user bits: */ |
2057 |
cpu->cd.mips.coproc[0]->reg[COP0_STATUS] = |
cpu->cd.mips.coproc[0]->reg[COP0_STATUS] = |
2058 |
(cpu->cd.mips.coproc[0]->reg[COP0_STATUS] & ~0x3f) | |
(cpu->cd.mips.coproc[0]->reg[COP0_STATUS] & ~0x3f) | |
2071 |
*/ |
*/ |
2072 |
X(eret) |
X(eret) |
2073 |
{ |
{ |
2074 |
|
if (!cop0_availability_check(cpu, ic)) |
2075 |
|
return; |
2076 |
|
|
2077 |
if (cpu->cd.mips.coproc[0]->reg[COP0_STATUS] & STATUS_ERL) { |
if (cpu->cd.mips.coproc[0]->reg[COP0_STATUS] & STATUS_ERL) { |
2078 |
cpu->pc = cpu->cd.mips.coproc[0]->reg[COP0_ERROREPC]; |
cpu->pc = cpu->cd.mips.coproc[0]->reg[COP0_ERROREPC]; |
2079 |
cpu->cd.mips.coproc[0]->reg[COP0_STATUS] &= ~STATUS_ERL; |
cpu->cd.mips.coproc[0]->reg[COP0_STATUS] &= ~STATUS_ERL; |
2094 |
*/ |
*/ |
2095 |
X(deret) |
X(deret) |
2096 |
{ |
{ |
2097 |
|
if (!cop0_availability_check(cpu, ic)) |
2098 |
|
return; |
2099 |
|
|
2100 |
/* |
/* |
2101 |
* According to the MIPS64 manual, deret loads PC from the DEPC cop0 |
* According to the MIPS64 manual, deret loads PC from the DEPC cop0 |
2102 |
* register, and jumps there immediately. No delay slot. |
* register, and jumps there immediately. No delay slot. |
2115 |
|
|
2116 |
|
|
2117 |
/* |
/* |
2118 |
|
* idle: Called from the implementation of wait, or netbsd_pmax_idle. |
2119 |
|
*/ |
2120 |
|
X(idle) |
2121 |
|
{ |
2122 |
|
/* |
2123 |
|
* If there is an interrupt, then just return. Otherwise |
2124 |
|
* re-run the wait instruction (after a delay). |
2125 |
|
*/ |
2126 |
|
uint32_t status = cpu->cd.mips.coproc[0]->reg[COP0_STATUS]; |
2127 |
|
uint32_t cause = cpu->cd.mips.coproc[0]->reg[COP0_CAUSE]; |
2128 |
|
|
2129 |
|
if (cpu->cd.mips.cpu_type.exc_model != EXC3K) { |
2130 |
|
if (status & (STATUS_EXL | STATUS_ERL)) |
2131 |
|
status &= ~STATUS_IE; |
2132 |
|
} |
2133 |
|
|
2134 |
|
/* Ugly R5900 special case: (TODO: move this?) */ |
2135 |
|
if (cpu->cd.mips.cpu_type.rev == MIPS_R5900 && |
2136 |
|
!(status & R5900_STATUS_EIE)) |
2137 |
|
status &= ~STATUS_IE; |
2138 |
|
if (status & STATUS_IE && (status & cause & STATUS_IM_MASK)) |
2139 |
|
return; |
2140 |
|
|
2141 |
|
cpu->cd.mips.next_ic = ic; |
2142 |
|
cpu->is_halted = 1; |
2143 |
|
cpu->has_been_idling = 1; |
2144 |
|
|
2145 |
|
/* |
2146 |
|
* There was no interrupt. Go to sleep. |
2147 |
|
* |
2148 |
|
* TODO: |
2149 |
|
* |
2150 |
|
* Think about how to actually implement this usleep stuff, |
2151 |
|
* in an SMP and/or timing accurate environment. |
2152 |
|
*/ |
2153 |
|
|
2154 |
|
if (cpu->machine->ncpus == 1) { |
2155 |
|
static int x = 0; |
2156 |
|
if ((++x) == 600) { |
2157 |
|
usleep(10); |
2158 |
|
x = 0; |
2159 |
|
} |
2160 |
|
cpu->n_translated_instrs += N_SAFE_DYNTRANS_LIMIT / 6; |
2161 |
|
} |
2162 |
|
} |
2163 |
|
|
2164 |
|
|
2165 |
|
/* |
2166 |
|
* wait: Wait for external interrupt. |
2167 |
|
*/ |
2168 |
|
X(wait) |
2169 |
|
{ |
2170 |
|
if (!cop0_availability_check(cpu, ic)) |
2171 |
|
return; |
2172 |
|
|
2173 |
|
instr(idle)(cpu, ic); |
2174 |
|
} |
2175 |
|
|
2176 |
|
|
2177 |
|
/* |
2178 |
* rdhwr: Read hardware register into gpr (MIPS32/64 rev 2). |
* rdhwr: Read hardware register into gpr (MIPS32/64 rev 2). |
2179 |
* |
* |
2180 |
* arg[0] = ptr to rt (destination register) |
* arg[0] = ptr to rt (destination register) |
2411 |
*/ |
*/ |
2412 |
X(lwc1) |
X(lwc1) |
2413 |
{ |
{ |
2414 |
const int cpnr = 1; |
COPROC_AVAILABILITY_CHECK(1); |
|
|
|
|
/* Synch. PC and call the generic load/store function: */ |
|
|
int low_pc = ((size_t)ic - (size_t)cpu->cd.mips.cur_ic_page) |
|
|
/ sizeof(struct mips_instr_call); |
|
|
cpu->pc &= ~((MIPS_IC_ENTRIES_PER_PAGE-1) |
|
|
<< MIPS_INSTR_ALIGNMENT_SHIFT); |
|
|
cpu->pc += (low_pc << MIPS_INSTR_ALIGNMENT_SHIFT); |
|
|
|
|
|
/* ... but first, let's see if the coprocessor is available: */ |
|
|
if (!(cpu->cd.mips.coproc[0]-> |
|
|
reg[COP0_STATUS] & ((1 << cpnr) << STATUS_CU_SHIFT)) ) { |
|
|
mips_cpu_exception(cpu, EXCEPTION_CPU, 0, 0, cpnr, 0, 0, 0); |
|
|
return; |
|
|
} |
|
2415 |
|
|
2416 |
#ifdef MODE32 |
#ifdef MODE32 |
2417 |
mips32_loadstore |
mips32_loadstore |
2423 |
} |
} |
2424 |
X(swc1) |
X(swc1) |
2425 |
{ |
{ |
2426 |
const int cpnr = 1; |
COPROC_AVAILABILITY_CHECK(1); |
|
|
|
|
/* Synch. PC and call the generic load/store function: */ |
|
|
int low_pc = ((size_t)ic - (size_t)cpu->cd.mips.cur_ic_page) |
|
|
/ sizeof(struct mips_instr_call); |
|
|
cpu->pc &= ~((MIPS_IC_ENTRIES_PER_PAGE-1) |
|
|
<< MIPS_INSTR_ALIGNMENT_SHIFT); |
|
|
cpu->pc += (low_pc << MIPS_INSTR_ALIGNMENT_SHIFT); |
|
|
|
|
|
/* ... but first, let's see if the coprocessor is available: */ |
|
|
if (!(cpu->cd.mips.coproc[0]-> |
|
|
reg[COP0_STATUS] & ((1 << cpnr) << STATUS_CU_SHIFT)) ) { |
|
|
mips_cpu_exception(cpu, EXCEPTION_CPU, 0, 0, cpnr, 0, 0, 0); |
|
|
return; |
|
|
} |
|
2427 |
|
|
2428 |
#ifdef MODE32 |
#ifdef MODE32 |
2429 |
mips32_loadstore |
mips32_loadstore |
2435 |
} |
} |
2436 |
X(ldc1) |
X(ldc1) |
2437 |
{ |
{ |
|
const int cpnr = 1; |
|
2438 |
int use_fp_pairs = |
int use_fp_pairs = |
2439 |
!(cpu->cd.mips.coproc[0]->reg[COP0_STATUS] & STATUS_FR); |
!(cpu->cd.mips.coproc[0]->reg[COP0_STATUS] & STATUS_FR); |
2440 |
uint64_t fpr, *backup_ptr; |
uint64_t fpr, *backup_ptr; |
2441 |
|
|
2442 |
/* Synch. PC and call the generic load/store function: */ |
COPROC_AVAILABILITY_CHECK(1); |
|
int low_pc = ((size_t)ic - (size_t)cpu->cd.mips.cur_ic_page) |
|
|
/ sizeof(struct mips_instr_call); |
|
|
cpu->pc &= ~((MIPS_IC_ENTRIES_PER_PAGE-1) |
|
|
<< MIPS_INSTR_ALIGNMENT_SHIFT); |
|
|
cpu->pc += (low_pc << MIPS_INSTR_ALIGNMENT_SHIFT); |
|
|
|
|
|
/* ... but first, let's see if the coprocessor is available: */ |
|
|
if (!(cpu->cd.mips.coproc[0]-> |
|
|
reg[COP0_STATUS] & ((1 << cpnr) << STATUS_CU_SHIFT)) ) { |
|
|
mips_cpu_exception(cpu, EXCEPTION_CPU, 0, 0, cpnr, 0, 0, 0); |
|
|
return; |
|
|
} |
|
2443 |
|
|
2444 |
backup_ptr = (uint64_t *) ic->arg[0]; |
backup_ptr = (uint64_t *) ic->arg[0]; |
2445 |
ic->arg[0] = (size_t) &fpr; |
ic->arg[0] = (size_t) &fpr; |
2463 |
} |
} |
2464 |
X(sdc1) |
X(sdc1) |
2465 |
{ |
{ |
|
const int cpnr = 1; |
|
2466 |
int use_fp_pairs = |
int use_fp_pairs = |
2467 |
!(cpu->cd.mips.coproc[0]->reg[COP0_STATUS] & STATUS_FR); |
!(cpu->cd.mips.coproc[0]->reg[COP0_STATUS] & STATUS_FR); |
2468 |
uint64_t fpr, *backup_ptr; |
uint64_t fpr, *backup_ptr; |
2469 |
|
|
2470 |
/* Synch. PC and call the generic load/store function: */ |
COPROC_AVAILABILITY_CHECK(1); |
|
int low_pc = ((size_t)ic - (size_t)cpu->cd.mips.cur_ic_page) |
|
|
/ sizeof(struct mips_instr_call); |
|
|
cpu->pc &= ~((MIPS_IC_ENTRIES_PER_PAGE-1) |
|
|
<< MIPS_INSTR_ALIGNMENT_SHIFT); |
|
|
cpu->pc += (low_pc << MIPS_INSTR_ALIGNMENT_SHIFT); |
|
|
|
|
|
/* ... but first, let's see if the coprocessor is available: */ |
|
|
if (!(cpu->cd.mips.coproc[0]-> |
|
|
reg[COP0_STATUS] & ((1 << cpnr) << STATUS_CU_SHIFT)) ) { |
|
|
mips_cpu_exception(cpu, EXCEPTION_CPU, 0, 0, cpnr, 0, 0, 0); |
|
|
return; |
|
|
} |
|
2471 |
|
|
2472 |
backup_ptr = (uint64_t *) ic->arg[0]; |
backup_ptr = (uint64_t *) ic->arg[0]; |
2473 |
ic->arg[0] = (size_t) &fpr; |
ic->arg[0] = (size_t) &fpr; |
2518 |
*/ |
*/ |
2519 |
X(di_r5900) |
X(di_r5900) |
2520 |
{ |
{ |
2521 |
|
if (!cop0_availability_check(cpu, ic)) |
2522 |
|
return; |
2523 |
|
|
2524 |
cpu->cd.mips.coproc[0]->reg[COP0_STATUS] &= ~R5900_STATUS_EIE; |
cpu->cd.mips.coproc[0]->reg[COP0_STATUS] &= ~R5900_STATUS_EIE; |
2525 |
} |
} |
2526 |
X(ei_r5900) |
X(ei_r5900) |
2527 |
{ |
{ |
2528 |
|
if (!cop0_availability_check(cpu, ic)) |
2529 |
|
return; |
2530 |
|
|
2531 |
cpu->cd.mips.coproc[0]->reg[COP0_STATUS] |= R5900_STATUS_EIE; |
cpu->cd.mips.coproc[0]->reg[COP0_STATUS] |= R5900_STATUS_EIE; |
2532 |
} |
} |
2533 |
|
|
2556 |
if (cpu->delay_slot || page == NULL || (rX & 3) != 0 || rZ != 0) { |
if (cpu->delay_slot || page == NULL || (rX & 3) != 0 || rZ != 0) { |
2557 |
instr(addiu)(cpu, ic); |
instr(addiu)(cpu, ic); |
2558 |
return; |
return; |
2559 |
} |
} |
2560 |
|
|
2561 |
if (rYp == (uint64_t *) ic->arg[0]) |
if (rYp == (uint64_t *) ic->arg[0]) |
2562 |
rYp = (uint64_t *) ic[1].arg[1]; |
rYp = (uint64_t *) ic[1].arg[1]; |
2585 |
} |
} |
2586 |
|
|
2587 |
|
|
2588 |
|
#ifdef MODE32 |
2589 |
/* |
/* |
2590 |
* multi_sw_3: |
* multi_sw_2, _3, _4: |
2591 |
* |
* |
2592 |
* 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] |
|
2593 |
*/ |
*/ |
2594 |
|
X(multi_sw_2_le) |
2595 |
|
{ |
2596 |
|
uint32_t *page; |
2597 |
|
MODE_uint_t rX = reg(ic[0].arg[1]), r1, r2; |
2598 |
|
MODE_uint_t addr0 = rX + (int32_t)ic[0].arg[2]; |
2599 |
|
MODE_uint_t addr1 = rX + (int32_t)ic[1].arg[2]; |
2600 |
|
uint32_t index0 = addr0 >> 12, index1 = addr1 >> 12; |
2601 |
|
|
2602 |
|
page = (uint32_t *) cpu->cd.mips.host_store[index0]; |
2603 |
|
|
2604 |
|
/* Fallback: */ |
2605 |
|
if (cpu->delay_slot || |
2606 |
|
page == NULL || (addr0 & 3) != 0 || (addr1 & 3) != 0 || |
2607 |
|
index0 != index1) { |
2608 |
|
/* Normal safe sw: */ |
2609 |
|
mips32_loadstore[8 + 2 * 2](cpu, ic); |
2610 |
|
return; |
2611 |
|
} |
2612 |
|
|
2613 |
|
addr0 = (addr0 >> 2) & 0x3ff; |
2614 |
|
addr1 = (addr1 >> 2) & 0x3ff; |
2615 |
|
|
2616 |
|
r1 = reg(ic[0].arg[0]); |
2617 |
|
r2 = reg(ic[1].arg[0]); |
2618 |
|
|
2619 |
|
r1 = LE32_TO_HOST(r1); |
2620 |
|
r2 = LE32_TO_HOST(r2); |
2621 |
|
|
2622 |
|
page[addr0] = r1; |
2623 |
|
page[addr1] = r2; |
2624 |
|
|
2625 |
|
cpu->n_translated_instrs ++; |
2626 |
|
cpu->cd.mips.next_ic ++; |
2627 |
|
} |
2628 |
|
X(multi_sw_2_be) |
2629 |
|
{ |
2630 |
|
uint32_t *page; |
2631 |
|
MODE_uint_t rX = reg(ic[0].arg[1]), r1, r2; |
2632 |
|
MODE_uint_t addr0 = rX + (int32_t)ic[0].arg[2]; |
2633 |
|
MODE_uint_t addr1 = rX + (int32_t)ic[1].arg[2]; |
2634 |
|
uint32_t index0 = addr0 >> 12, index1 = addr1 >> 12; |
2635 |
|
|
2636 |
|
page = (uint32_t *) cpu->cd.mips.host_store[index0]; |
2637 |
|
|
2638 |
|
/* Fallback: */ |
2639 |
|
if (cpu->delay_slot || |
2640 |
|
page == NULL || (addr0 & 3) != 0 || (addr1 & 3) != 0 || |
2641 |
|
index0 != index1) { |
2642 |
|
/* Normal safe sw: */ |
2643 |
|
mips32_loadstore[16 + 8 + 2 * 2](cpu, ic); |
2644 |
|
return; |
2645 |
|
} |
2646 |
|
|
2647 |
|
addr0 = (addr0 >> 2) & 0x3ff; |
2648 |
|
addr1 = (addr1 >> 2) & 0x3ff; |
2649 |
|
|
2650 |
|
r1 = reg(ic[0].arg[0]); |
2651 |
|
r2 = reg(ic[1].arg[0]); |
2652 |
|
|
2653 |
|
r1 = BE32_TO_HOST(r1); |
2654 |
|
r2 = BE32_TO_HOST(r2); |
2655 |
|
|
2656 |
|
page[addr0] = r1; |
2657 |
|
page[addr1] = r2; |
2658 |
|
|
2659 |
|
cpu->n_translated_instrs ++; |
2660 |
|
cpu->cd.mips.next_ic ++; |
2661 |
|
} |
2662 |
X(multi_sw_3_le) |
X(multi_sw_3_le) |
2663 |
{ |
{ |
2664 |
uint32_t *page; |
uint32_t *page; |
2676 |
page == NULL || (addr0 & 3) != 0 || (addr1 & 3) != 0 || |
page == NULL || (addr0 & 3) != 0 || (addr1 & 3) != 0 || |
2677 |
(addr2 & 3) != 0 || index0 != index1 || index0 != index2) { |
(addr2 & 3) != 0 || index0 != index1 || index0 != index2) { |
2678 |
/* Normal safe sw: */ |
/* Normal safe sw: */ |
2679 |
ic[1].f(cpu, ic); |
mips32_loadstore[8 + 2 * 2](cpu, ic); |
2680 |
return; |
return; |
2681 |
} |
} |
2682 |
|
|
2700 |
page[addr2] = r3; |
page[addr2] = r3; |
2701 |
|
|
2702 |
cpu->n_translated_instrs += 2; |
cpu->n_translated_instrs += 2; |
2703 |
cpu->cd.mips.next_ic = (struct mips_instr_call *) &ic[3]; |
cpu->cd.mips.next_ic += 2; |
2704 |
} |
} |
2705 |
X(multi_sw_3_be) |
X(multi_sw_3_be) |
2706 |
{ |
{ |
2719 |
page == NULL || (addr0 & 3) != 0 || (addr1 & 3) != 0 || |
page == NULL || (addr0 & 3) != 0 || (addr1 & 3) != 0 || |
2720 |
(addr2 & 3) != 0 || index0 != index1 || index0 != index2) { |
(addr2 & 3) != 0 || index0 != index1 || index0 != index2) { |
2721 |
/* Normal safe sw: */ |
/* Normal safe sw: */ |
2722 |
ic[1].f(cpu, ic); |
mips32_loadstore[16 + 8 + 2 * 2](cpu, ic); |
2723 |
return; |
return; |
2724 |
} |
} |
2725 |
|
|
2743 |
page[addr2] = r3; |
page[addr2] = r3; |
2744 |
|
|
2745 |
cpu->n_translated_instrs += 2; |
cpu->n_translated_instrs += 2; |
2746 |
cpu->cd.mips.next_ic = (struct mips_instr_call *) &ic[3]; |
cpu->cd.mips.next_ic += 2; |
2747 |
|
} |
2748 |
|
X(multi_sw_4_le) |
2749 |
|
{ |
2750 |
|
uint32_t *page; |
2751 |
|
MODE_uint_t rX = reg(ic[0].arg[1]), r1, r2, r3, r4; |
2752 |
|
MODE_uint_t addr0 = rX + (int32_t)ic[0].arg[2]; |
2753 |
|
MODE_uint_t addr1 = rX + (int32_t)ic[1].arg[2]; |
2754 |
|
MODE_uint_t addr2 = rX + (int32_t)ic[2].arg[2]; |
2755 |
|
MODE_uint_t addr3 = rX + (int32_t)ic[3].arg[2]; |
2756 |
|
uint32_t index0 = addr0 >> 12, index1 = addr1 >> 12, |
2757 |
|
index2 = addr2 >> 12, index3 = addr3 >> 12; |
2758 |
|
|
2759 |
|
page = (uint32_t *) cpu->cd.mips.host_store[index0]; |
2760 |
|
|
2761 |
|
/* Fallback: */ |
2762 |
|
if (cpu->delay_slot || |
2763 |
|
page == NULL || (addr0 & 3) != 0 || (addr1 & 3) != 0 || |
2764 |
|
(addr2 & 3) != 0 || (addr3 & 3) != 0 || index0 != index1 || |
2765 |
|
index0 != index2 || index0 != index3) { |
2766 |
|
/* Normal safe sw: */ |
2767 |
|
mips32_loadstore[8 + 2 * 2](cpu, ic); |
2768 |
|
return; |
2769 |
|
} |
2770 |
|
|
2771 |
|
addr0 = (addr0 >> 2) & 0x3ff; |
2772 |
|
addr1 = (addr1 >> 2) & 0x3ff; |
2773 |
|
addr2 = (addr2 >> 2) & 0x3ff; |
2774 |
|
addr3 = (addr3 >> 2) & 0x3ff; |
2775 |
|
|
2776 |
|
r1 = reg(ic[0].arg[0]); |
2777 |
|
r2 = reg(ic[1].arg[0]); |
2778 |
|
r3 = reg(ic[2].arg[0]); |
2779 |
|
r4 = reg(ic[3].arg[0]); |
2780 |
|
|
2781 |
|
r1 = LE32_TO_HOST(r1); |
2782 |
|
r2 = LE32_TO_HOST(r2); |
2783 |
|
r3 = LE32_TO_HOST(r3); |
2784 |
|
r4 = LE32_TO_HOST(r4); |
2785 |
|
|
2786 |
|
page[addr0] = r1; |
2787 |
|
page[addr1] = r2; |
2788 |
|
page[addr2] = r3; |
2789 |
|
page[addr3] = r4; |
2790 |
|
|
2791 |
|
cpu->n_translated_instrs += 3; |
2792 |
|
cpu->cd.mips.next_ic += 3; |
2793 |
|
} |
2794 |
|
X(multi_sw_4_be) |
2795 |
|
{ |
2796 |
|
uint32_t *page; |
2797 |
|
MODE_uint_t rX = reg(ic[0].arg[1]), r1, r2, r3, r4; |
2798 |
|
MODE_uint_t addr0 = rX + (int32_t)ic[0].arg[2]; |
2799 |
|
MODE_uint_t addr1 = rX + (int32_t)ic[1].arg[2]; |
2800 |
|
MODE_uint_t addr2 = rX + (int32_t)ic[2].arg[2]; |
2801 |
|
MODE_uint_t addr3 = rX + (int32_t)ic[3].arg[2]; |
2802 |
|
uint32_t index0 = addr0 >> 12, index1 = addr1 >> 12, |
2803 |
|
index2 = addr2 >> 12, index3 = addr3 >> 12; |
2804 |
|
|
2805 |
|
page = (uint32_t *) cpu->cd.mips.host_store[index0]; |
2806 |
|
|
2807 |
|
/* Fallback: */ |
2808 |
|
if (cpu->delay_slot || |
2809 |
|
page == NULL || (addr0 & 3) != 0 || (addr1 & 3) != 0 || |
2810 |
|
(addr2 & 3) != 0 || (addr3 & 3) != 0 || index0 != index1 || |
2811 |
|
index0 != index2 || index0 != index3) { |
2812 |
|
/* Normal safe sw: */ |
2813 |
|
mips32_loadstore[16 + 8 + 2 * 2](cpu, ic); |
2814 |
|
return; |
2815 |
|
} |
2816 |
|
|
2817 |
|
addr0 = (addr0 >> 2) & 0x3ff; |
2818 |
|
addr1 = (addr1 >> 2) & 0x3ff; |
2819 |
|
addr2 = (addr2 >> 2) & 0x3ff; |
2820 |
|
addr3 = (addr3 >> 2) & 0x3ff; |
2821 |
|
|
2822 |
|
r1 = reg(ic[0].arg[0]); |
2823 |
|
r2 = reg(ic[1].arg[0]); |
2824 |
|
r3 = reg(ic[2].arg[0]); |
2825 |
|
r4 = reg(ic[3].arg[0]); |
2826 |
|
|
2827 |
|
r1 = BE32_TO_HOST(r1); |
2828 |
|
r2 = BE32_TO_HOST(r2); |
2829 |
|
r3 = BE32_TO_HOST(r3); |
2830 |
|
r4 = BE32_TO_HOST(r4); |
2831 |
|
|
2832 |
|
page[addr0] = r1; |
2833 |
|
page[addr1] = r2; |
2834 |
|
page[addr2] = r3; |
2835 |
|
page[addr3] = r4; |
2836 |
|
|
2837 |
|
cpu->n_translated_instrs += 3; |
2838 |
|
cpu->cd.mips.next_ic += 3; |
2839 |
|
} |
2840 |
|
#endif |
2841 |
|
|
2842 |
|
|
2843 |
|
#ifdef MODE32 |
2844 |
|
/* |
2845 |
|
* multi_lw_2, _3, _4: |
2846 |
|
* |
2847 |
|
* lw r?,ofs(rX) r?=arg[0], rX=arg[1], ofs=arg[2] |
2848 |
|
*/ |
2849 |
|
X(multi_lw_2_le) |
2850 |
|
{ |
2851 |
|
uint32_t *page; |
2852 |
|
MODE_uint_t rX = reg(ic[0].arg[1]), r1, r2; |
2853 |
|
MODE_uint_t addr0 = rX + (int32_t)ic[0].arg[2]; |
2854 |
|
MODE_uint_t addr1 = rX + (int32_t)ic[1].arg[2]; |
2855 |
|
uint32_t index0 = addr0 >> 12, index1 = addr1 >> 12; |
2856 |
|
|
2857 |
|
page = (uint32_t *) cpu->cd.mips.host_load[index0]; |
2858 |
|
|
2859 |
|
/* Fallback: */ |
2860 |
|
if (cpu->delay_slot || |
2861 |
|
page == NULL || (addr0 & 3) != 0 || (addr1 & 3) != 0 || |
2862 |
|
index0 != index1) { |
2863 |
|
/* Normal safe lw: */ |
2864 |
|
mips32_loadstore[2 * 2 + 1](cpu, ic); |
2865 |
|
return; |
2866 |
|
} |
2867 |
|
|
2868 |
|
addr0 = (addr0 >> 2) & 0x3ff; |
2869 |
|
addr1 = (addr1 >> 2) & 0x3ff; |
2870 |
|
|
2871 |
|
r1 = page[addr0]; |
2872 |
|
r2 = page[addr1]; |
2873 |
|
|
2874 |
|
r1 = LE32_TO_HOST(r1); |
2875 |
|
r2 = LE32_TO_HOST(r2); |
2876 |
|
|
2877 |
|
reg(ic[0].arg[0]) = r1; |
2878 |
|
reg(ic[1].arg[0]) = r2; |
2879 |
|
|
2880 |
|
cpu->n_translated_instrs ++; |
2881 |
|
cpu->cd.mips.next_ic ++; |
2882 |
|
} |
2883 |
|
X(multi_lw_2_be) |
2884 |
|
{ |
2885 |
|
uint32_t *page; |
2886 |
|
MODE_uint_t rX = reg(ic[0].arg[1]), r1, r2; |
2887 |
|
MODE_uint_t addr0 = rX + (int32_t)ic[0].arg[2]; |
2888 |
|
MODE_uint_t addr1 = rX + (int32_t)ic[1].arg[2]; |
2889 |
|
uint32_t index0 = addr0 >> 12, index1 = addr1 >> 12; |
2890 |
|
|
2891 |
|
page = (uint32_t *) cpu->cd.mips.host_load[index0]; |
2892 |
|
|
2893 |
|
/* Fallback: */ |
2894 |
|
if (cpu->delay_slot || |
2895 |
|
page == NULL || (addr0 & 3) != 0 || (addr1 & 3) != 0 || |
2896 |
|
index0 != index1) { |
2897 |
|
/* Normal safe lw: */ |
2898 |
|
mips32_loadstore[16 + 2 * 2 + 1](cpu, ic); |
2899 |
|
return; |
2900 |
|
} |
2901 |
|
|
2902 |
|
addr0 = (addr0 >> 2) & 0x3ff; |
2903 |
|
addr1 = (addr1 >> 2) & 0x3ff; |
2904 |
|
|
2905 |
|
r1 = page[addr0]; |
2906 |
|
r2 = page[addr1]; |
2907 |
|
|
2908 |
|
r1 = BE32_TO_HOST(r1); |
2909 |
|
r2 = BE32_TO_HOST(r2); |
2910 |
|
|
2911 |
|
reg(ic[0].arg[0]) = r1; |
2912 |
|
reg(ic[1].arg[0]) = r2; |
2913 |
|
|
2914 |
|
cpu->n_translated_instrs ++; |
2915 |
|
cpu->cd.mips.next_ic ++; |
2916 |
|
} |
2917 |
|
X(multi_lw_3_le) |
2918 |
|
{ |
2919 |
|
uint32_t *page; |
2920 |
|
MODE_uint_t rX = reg(ic[0].arg[1]), r1, r2, r3; |
2921 |
|
MODE_uint_t addr0 = rX + (int32_t)ic[0].arg[2]; |
2922 |
|
MODE_uint_t addr1 = rX + (int32_t)ic[1].arg[2]; |
2923 |
|
MODE_uint_t addr2 = rX + (int32_t)ic[2].arg[2]; |
2924 |
|
uint32_t index0 = addr0 >> 12, index1 = addr1 >> 12, |
2925 |
|
index2 = addr2 >> 12; |
2926 |
|
|
2927 |
|
page = (uint32_t *) cpu->cd.mips.host_load[index0]; |
2928 |
|
|
2929 |
|
/* Fallback: */ |
2930 |
|
if (cpu->delay_slot || |
2931 |
|
page == NULL || (addr0 & 3) != 0 || (addr1 & 3) != 0 || |
2932 |
|
(addr2 & 3) != 0 || index0 != index1 || index0 != index2) { |
2933 |
|
/* Normal safe lw: */ |
2934 |
|
mips32_loadstore[2 * 2 + 1](cpu, ic); |
2935 |
|
return; |
2936 |
|
} |
2937 |
|
|
2938 |
|
addr0 = (addr0 >> 2) & 0x3ff; |
2939 |
|
addr1 = (addr1 >> 2) & 0x3ff; |
2940 |
|
addr2 = (addr2 >> 2) & 0x3ff; |
2941 |
|
|
2942 |
|
/* printf("addr0=%x 1=%x 2=%x\n", |
2943 |
|
(int)addr0, (int)addr1, (int)addr2); */ |
2944 |
|
|
2945 |
|
r1 = page[addr0]; |
2946 |
|
r2 = page[addr1]; |
2947 |
|
r3 = page[addr2]; |
2948 |
|
|
2949 |
|
r1 = LE32_TO_HOST(r1); |
2950 |
|
r2 = LE32_TO_HOST(r2); |
2951 |
|
r3 = LE32_TO_HOST(r3); |
2952 |
|
|
2953 |
|
reg(ic[0].arg[0]) = r1; |
2954 |
|
reg(ic[1].arg[0]) = r2; |
2955 |
|
reg(ic[2].arg[0]) = r3; |
2956 |
|
|
2957 |
|
cpu->n_translated_instrs += 2; |
2958 |
|
cpu->cd.mips.next_ic += 2; |
2959 |
|
} |
2960 |
|
X(multi_lw_3_be) |
2961 |
|
{ |
2962 |
|
uint32_t *page; |
2963 |
|
MODE_uint_t rX = reg(ic[0].arg[1]), r1, r2, r3; |
2964 |
|
MODE_uint_t addr0 = rX + (int32_t)ic[0].arg[2]; |
2965 |
|
MODE_uint_t addr1 = rX + (int32_t)ic[1].arg[2]; |
2966 |
|
MODE_uint_t addr2 = rX + (int32_t)ic[2].arg[2]; |
2967 |
|
uint32_t index0 = addr0 >> 12, index1 = addr1 >> 12, |
2968 |
|
index2 = addr2 >> 12; |
2969 |
|
|
2970 |
|
page = (uint32_t *) cpu->cd.mips.host_load[index0]; |
2971 |
|
|
2972 |
|
/* Fallback: */ |
2973 |
|
if (cpu->delay_slot || |
2974 |
|
page == NULL || (addr0 & 3) != 0 || (addr1 & 3) != 0 || |
2975 |
|
(addr2 & 3) != 0 || index0 != index1 || index0 != index2) { |
2976 |
|
/* Normal safe lw: */ |
2977 |
|
mips32_loadstore[16 + 2 * 2 + 1](cpu, ic); |
2978 |
|
return; |
2979 |
|
} |
2980 |
|
|
2981 |
|
addr0 = (addr0 >> 2) & 0x3ff; |
2982 |
|
addr1 = (addr1 >> 2) & 0x3ff; |
2983 |
|
addr2 = (addr2 >> 2) & 0x3ff; |
2984 |
|
|
2985 |
|
/* printf("addr0=%x 1=%x 2=%x\n", |
2986 |
|
(int)addr0, (int)addr1, (int)addr2); */ |
2987 |
|
|
2988 |
|
r1 = page[addr0]; |
2989 |
|
r2 = page[addr1]; |
2990 |
|
r3 = page[addr2]; |
2991 |
|
|
2992 |
|
r1 = BE32_TO_HOST(r1); |
2993 |
|
r2 = BE32_TO_HOST(r2); |
2994 |
|
r3 = BE32_TO_HOST(r3); |
2995 |
|
|
2996 |
|
reg(ic[0].arg[0]) = r1; |
2997 |
|
reg(ic[1].arg[0]) = r2; |
2998 |
|
reg(ic[2].arg[0]) = r3; |
2999 |
|
|
3000 |
|
cpu->n_translated_instrs += 2; |
3001 |
|
cpu->cd.mips.next_ic += 2; |
3002 |
|
} |
3003 |
|
X(multi_lw_4_le) |
3004 |
|
{ |
3005 |
|
uint32_t *page; |
3006 |
|
MODE_uint_t rX = reg(ic[0].arg[1]), r1, r2, r3, r4; |
3007 |
|
MODE_uint_t addr0 = rX + (int32_t)ic[0].arg[2]; |
3008 |
|
MODE_uint_t addr1 = rX + (int32_t)ic[1].arg[2]; |
3009 |
|
MODE_uint_t addr2 = rX + (int32_t)ic[2].arg[2]; |
3010 |
|
MODE_uint_t addr3 = rX + (int32_t)ic[3].arg[2]; |
3011 |
|
uint32_t index0 = addr0 >> 12, index1 = addr1 >> 12, |
3012 |
|
index2 = addr2 >> 12, index3 = addr3 >> 12; |
3013 |
|
|
3014 |
|
page = (uint32_t *) cpu->cd.mips.host_load[index0]; |
3015 |
|
|
3016 |
|
/* Fallback: */ |
3017 |
|
if (cpu->delay_slot || |
3018 |
|
page == NULL || (addr0 & 3) != 0 || (addr1 & 3) != 0 || |
3019 |
|
(addr2 & 3) != 0 || (addr3 & 3) != 0 || |
3020 |
|
index0 != index1 || index0 != index2 || index0 != index3) { |
3021 |
|
/* Normal safe lw: */ |
3022 |
|
mips32_loadstore[2 * 2 + 1](cpu, ic); |
3023 |
|
return; |
3024 |
|
} |
3025 |
|
|
3026 |
|
addr0 = (addr0 >> 2) & 0x3ff; |
3027 |
|
addr1 = (addr1 >> 2) & 0x3ff; |
3028 |
|
addr2 = (addr2 >> 2) & 0x3ff; |
3029 |
|
addr3 = (addr3 >> 2) & 0x3ff; |
3030 |
|
|
3031 |
|
r1 = page[addr0]; |
3032 |
|
r2 = page[addr1]; |
3033 |
|
r3 = page[addr2]; |
3034 |
|
r4 = page[addr3]; |
3035 |
|
|
3036 |
|
r1 = LE32_TO_HOST(r1); |
3037 |
|
r2 = LE32_TO_HOST(r2); |
3038 |
|
r3 = LE32_TO_HOST(r3); |
3039 |
|
r4 = LE32_TO_HOST(r4); |
3040 |
|
|
3041 |
|
reg(ic[0].arg[0]) = r1; |
3042 |
|
reg(ic[1].arg[0]) = r2; |
3043 |
|
reg(ic[2].arg[0]) = r3; |
3044 |
|
reg(ic[3].arg[0]) = r4; |
3045 |
|
|
3046 |
|
cpu->n_translated_instrs += 3; |
3047 |
|
cpu->cd.mips.next_ic += 3; |
3048 |
|
} |
3049 |
|
X(multi_lw_4_be) |
3050 |
|
{ |
3051 |
|
uint32_t *page; |
3052 |
|
MODE_uint_t rX = reg(ic[0].arg[1]), r1, r2, r3, r4; |
3053 |
|
MODE_uint_t addr0 = rX + (int32_t)ic[0].arg[2]; |
3054 |
|
MODE_uint_t addr1 = rX + (int32_t)ic[1].arg[2]; |
3055 |
|
MODE_uint_t addr2 = rX + (int32_t)ic[2].arg[2]; |
3056 |
|
MODE_uint_t addr3 = rX + (int32_t)ic[3].arg[2]; |
3057 |
|
uint32_t index0 = addr0 >> 12, index1 = addr1 >> 12, |
3058 |
|
index2 = addr2 >> 12, index3 = addr3 >> 12; |
3059 |
|
|
3060 |
|
page = (uint32_t *) cpu->cd.mips.host_load[index0]; |
3061 |
|
|
3062 |
|
/* Fallback: */ |
3063 |
|
if (cpu->delay_slot || |
3064 |
|
page == NULL || (addr0 & 3) != 0 || (addr1 & 3) != 0 || |
3065 |
|
(addr2 & 3) != 0 || (addr3 & 3) != 0 || |
3066 |
|
index0 != index1 || index0 != index2 || index0 != index3) { |
3067 |
|
/* Normal safe lw: */ |
3068 |
|
mips32_loadstore[16 + 2 * 2 + 1](cpu, ic); |
3069 |
|
return; |
3070 |
|
} |
3071 |
|
|
3072 |
|
addr0 = (addr0 >> 2) & 0x3ff; |
3073 |
|
addr1 = (addr1 >> 2) & 0x3ff; |
3074 |
|
addr2 = (addr2 >> 2) & 0x3ff; |
3075 |
|
addr3 = (addr3 >> 2) & 0x3ff; |
3076 |
|
|
3077 |
|
r1 = page[addr0]; |
3078 |
|
r2 = page[addr1]; |
3079 |
|
r3 = page[addr2]; |
3080 |
|
r4 = page[addr3]; |
3081 |
|
|
3082 |
|
r1 = BE32_TO_HOST(r1); |
3083 |
|
r2 = BE32_TO_HOST(r2); |
3084 |
|
r3 = BE32_TO_HOST(r3); |
3085 |
|
r4 = BE32_TO_HOST(r4); |
3086 |
|
|
3087 |
|
reg(ic[0].arg[0]) = r1; |
3088 |
|
reg(ic[1].arg[0]) = r2; |
3089 |
|
reg(ic[2].arg[0]) = r3; |
3090 |
|
reg(ic[3].arg[0]) = r4; |
3091 |
|
|
3092 |
|
cpu->n_translated_instrs += 3; |
3093 |
|
cpu->cd.mips.next_ic += 3; |
3094 |
|
} |
3095 |
|
#endif |
3096 |
|
|
3097 |
|
|
3098 |
|
/* |
3099 |
|
* multi_addu_3: |
3100 |
|
*/ |
3101 |
|
X(multi_addu_3) |
3102 |
|
{ |
3103 |
|
/* Fallback: */ |
3104 |
|
if (cpu->delay_slot) { |
3105 |
|
instr(addu)(cpu, ic); |
3106 |
|
return; |
3107 |
|
} |
3108 |
|
|
3109 |
|
reg(ic[0].arg[2]) = (int32_t)(reg(ic[0].arg[0]) + reg(ic[0].arg[1])); |
3110 |
|
reg(ic[1].arg[2]) = (int32_t)(reg(ic[1].arg[0]) + reg(ic[1].arg[1])); |
3111 |
|
reg(ic[2].arg[2]) = (int32_t)(reg(ic[2].arg[0]) + reg(ic[2].arg[1])); |
3112 |
|
cpu->n_translated_instrs += 2; |
3113 |
|
cpu->cd.mips.next_ic += 2; |
3114 |
} |
} |
3115 |
|
|
3116 |
|
|
3148 |
|
|
3149 |
#ifdef MODE32 |
#ifdef MODE32 |
3150 |
/* |
/* |
3151 |
|
* netbsd_pmax_idle(): |
3152 |
|
* |
3153 |
|
* s: lui rX, hi |
3154 |
|
* lw rY, lo(rX) |
3155 |
|
* nop |
3156 |
|
* beq zr, rY, s |
3157 |
|
* nop |
3158 |
|
*/ |
3159 |
|
X(netbsd_pmax_idle) |
3160 |
|
{ |
3161 |
|
uint32_t addr, pageindex, i; |
3162 |
|
int32_t *page; |
3163 |
|
|
3164 |
|
reg(ic[0].arg[0]) = (int32_t)ic[0].arg[1]; |
3165 |
|
|
3166 |
|
addr = reg(ic[0].arg[0]) + (int32_t)ic[1].arg[2]; |
3167 |
|
pageindex = addr >> 12; |
3168 |
|
i = (addr & 0xfff) >> 2; |
3169 |
|
page = (int32_t *) cpu->cd.mips.host_load[pageindex]; |
3170 |
|
|
3171 |
|
/* Fallback: */ |
3172 |
|
if (cpu->delay_slot || page == NULL || page[i] != 0) |
3173 |
|
return; |
3174 |
|
|
3175 |
|
instr(idle)(cpu, ic); |
3176 |
|
} |
3177 |
|
|
3178 |
|
|
3179 |
|
/* |
3180 |
|
* linux_pmax_idle(): |
3181 |
|
* |
3182 |
|
* s: lui rX, hi |
3183 |
|
* lw rX, lo(rX) |
3184 |
|
* nop |
3185 |
|
* bne zr, rX, ... |
3186 |
|
* nop |
3187 |
|
* lw rX, ofs(gp) |
3188 |
|
* nop |
3189 |
|
* beq zr, rX, s |
3190 |
|
* nop |
3191 |
|
*/ |
3192 |
|
X(linux_pmax_idle) |
3193 |
|
{ |
3194 |
|
uint32_t addr, addr2, pageindex, pageindex2, i, i2; |
3195 |
|
int32_t *page, *page2; |
3196 |
|
|
3197 |
|
reg(ic[0].arg[0]) = (int32_t)ic[0].arg[1]; |
3198 |
|
|
3199 |
|
addr = reg(ic[0].arg[0]) + (int32_t)ic[1].arg[2]; |
3200 |
|
pageindex = addr >> 12; |
3201 |
|
i = (addr & 0xfff) >> 2; |
3202 |
|
page = (int32_t *) cpu->cd.mips.host_load[pageindex]; |
3203 |
|
|
3204 |
|
addr2 = reg(ic[5].arg[1]) + (int32_t)ic[5].arg[2]; |
3205 |
|
pageindex2 = addr2 >> 12; |
3206 |
|
i2 = (addr2 & 0xfff) >> 2; |
3207 |
|
page2 = (int32_t *) cpu->cd.mips.host_load[pageindex2]; |
3208 |
|
|
3209 |
|
/* Fallback: */ |
3210 |
|
if (cpu->delay_slot || page == NULL || page[i] != 0 || page2[i2] != 0) |
3211 |
|
return; |
3212 |
|
|
3213 |
|
instr(idle)(cpu, ic); |
3214 |
|
} |
3215 |
|
|
3216 |
|
|
3217 |
|
/* |
3218 |
* netbsd_strlen(): |
* netbsd_strlen(): |
3219 |
* |
* |
3220 |
* lb rV,0(rX) |
* lb rV,0(rX) |
3268 |
|
|
3269 |
|
|
3270 |
/* |
/* |
3271 |
* 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. |
|
3272 |
*/ |
*/ |
3273 |
X(lui_32bit) |
X(addiu_bne_samepage_addiu) |
3274 |
{ |
{ |
3275 |
reg(ic[0].arg[0]) = (int32_t) ic[0].arg[2]; |
MODE_uint_t rs, rt; |
3276 |
|
|
3277 |
|
if (cpu->delay_slot) { |
3278 |
|
instr(addiu)(cpu, ic); |
3279 |
|
return; |
3280 |
|
} |
3281 |
|
|
3282 |
|
cpu->n_translated_instrs += 2; |
3283 |
|
reg(ic[0].arg[1]) = (int32_t) |
3284 |
|
((int32_t)reg(ic[0].arg[0]) + (int32_t)ic[0].arg[2]); |
3285 |
|
rs = reg(ic[1].arg[0]); |
3286 |
|
rt = reg(ic[1].arg[1]); |
3287 |
|
reg(ic[2].arg[1]) = (int32_t) |
3288 |
|
((int32_t)reg(ic[2].arg[0]) + (int32_t)ic[2].arg[2]); |
3289 |
|
if (rs != rt) |
3290 |
|
cpu->cd.mips.next_ic = (struct mips_instr_call *) ic[1].arg[2]; |
3291 |
|
else |
3292 |
|
cpu->cd.mips.next_ic += 2; |
3293 |
|
} |
3294 |
|
|
3295 |
|
|
3296 |
|
/* |
3297 |
|
* xor_andi_sll: |
3298 |
|
*/ |
3299 |
|
X(xor_andi_sll) |
3300 |
|
{ |
3301 |
|
/* Fallback: */ |
3302 |
|
if (cpu->delay_slot) { |
3303 |
|
instr(xor)(cpu, ic); |
3304 |
|
return; |
3305 |
|
} |
3306 |
|
|
3307 |
|
reg(ic[0].arg[2]) = reg(ic[0].arg[0]) ^ reg(ic[0].arg[1]); |
3308 |
|
reg(ic[1].arg[1]) = reg(ic[1].arg[0]) & (uint32_t)ic[1].arg[2]; |
3309 |
|
reg(ic[2].arg[2]) = (int32_t)(reg(ic[2].arg[0])<<(int32_t)ic[2].arg[1]); |
3310 |
|
|
3311 |
|
cpu->n_translated_instrs += 2; |
3312 |
|
cpu->cd.mips.next_ic += 2; |
3313 |
|
} |
3314 |
|
|
3315 |
|
|
3316 |
|
/* |
3317 |
|
* andi_sll: |
3318 |
|
*/ |
3319 |
|
X(andi_sll) |
3320 |
|
{ |
3321 |
|
/* Fallback: */ |
3322 |
|
if (cpu->delay_slot) { |
3323 |
|
instr(andi)(cpu, ic); |
3324 |
|
return; |
3325 |
|
} |
3326 |
|
|
3327 |
|
reg(ic[0].arg[1]) = reg(ic[0].arg[0]) & (uint32_t)ic[0].arg[2]; |
3328 |
|
reg(ic[1].arg[2]) = (int32_t)(reg(ic[1].arg[0])<<(int32_t)ic[1].arg[1]); |
3329 |
|
|
3330 |
|
cpu->n_translated_instrs ++; |
3331 |
|
cpu->cd.mips.next_ic ++; |
3332 |
|
} |
3333 |
|
|
3334 |
|
|
3335 |
|
/* |
3336 |
|
* lui_ori: |
3337 |
|
*/ |
3338 |
|
X(lui_ori) |
3339 |
|
{ |
3340 |
|
/* Fallback: */ |
3341 |
|
if (cpu->delay_slot) { |
3342 |
|
instr(set)(cpu, ic); |
3343 |
|
return; |
3344 |
|
} |
3345 |
|
|
3346 |
|
reg(ic[0].arg[0]) = (int32_t)ic[0].arg[1]; |
3347 |
|
reg(ic[1].arg[1]) = reg(ic[1].arg[0]) | (uint32_t)ic[1].arg[2]; |
3348 |
|
|
3349 |
|
cpu->n_translated_instrs ++; |
3350 |
|
cpu->cd.mips.next_ic ++; |
3351 |
|
} |
3352 |
|
|
3353 |
|
|
3354 |
|
/* |
3355 |
|
* lui_addiu: |
3356 |
|
*/ |
3357 |
|
X(lui_addiu) |
3358 |
|
{ |
3359 |
|
/* Fallback: */ |
3360 |
|
if (cpu->delay_slot) { |
3361 |
|
instr(set)(cpu, ic); |
3362 |
|
return; |
3363 |
|
} |
3364 |
|
|
3365 |
|
reg(ic[0].arg[0]) = (int32_t)ic[0].arg[1]; |
3366 |
|
reg(ic[1].arg[1]) = (int32_t) |
3367 |
|
((int32_t)reg(ic[1].arg[0]) + (int32_t)ic[1].arg[2]); |
3368 |
|
|
3369 |
cpu->n_translated_instrs ++; |
cpu->n_translated_instrs ++; |
3370 |
cpu->cd.mips.next_ic ++; |
cpu->cd.mips.next_ic ++; |
3371 |
} |
} |
3505 |
ic[0].arg[0] != ic[0].arg[1] && |
ic[0].arg[0] != ic[0].arg[1] && |
3506 |
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) { |
3507 |
ic[-2].f = instr(sw_loop); |
ic[-2].f = instr(sw_loop); |
|
combined; |
|
3508 |
} |
} |
3509 |
} |
} |
3510 |
|
|
3511 |
|
|
3512 |
|
/* Only for 32-bit virtual address translation so far. */ |
3513 |
|
#ifdef MODE32 |
3514 |
/* |
/* |
3515 |
* Combine: Multiple SW in a row using the same base register |
* Combine: Multiple SW in a row using the same base register |
3516 |
* |
* |
3525 |
int n_back = (low_addr >> MIPS_INSTR_ALIGNMENT_SHIFT) |
int n_back = (low_addr >> MIPS_INSTR_ALIGNMENT_SHIFT) |
3526 |
& (MIPS_IC_ENTRIES_PER_PAGE - 1); |
& (MIPS_IC_ENTRIES_PER_PAGE - 1); |
3527 |
|
|
3528 |
/* Only for 32-bit virtual address translation so far. */ |
if (n_back < 3) |
|
if (!cpu->is_32bit) |
|
3529 |
return; |
return; |
3530 |
|
|
3531 |
if (n_back < 4) |
/* Convert a multi_sw_3 to a multi_sw_4: */ |
3532 |
return; |
if ((ic[-3].f == instr(multi_sw_3_be) || |
3533 |
|
ic[-3].f == instr(multi_sw_3_le)) && |
3534 |
|
ic[-3].arg[1] == ic[0].arg[1]) { |
3535 |
|
if (cpu->byte_order == EMUL_LITTLE_ENDIAN) |
3536 |
|
ic[-3].f = instr(multi_sw_4_le); |
3537 |
|
else |
3538 |
|
ic[-3].f = instr(multi_sw_4_be); |
3539 |
|
} |
3540 |
|
|
3541 |
/* Avoid "overlapping" instruction combinations: */ |
/* Convert a multi_sw_2 to a multi_sw_3: */ |
3542 |
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) || |
3543 |
ic[-4].f == instr(multi_sw_3_le)||ic[-3].f == instr(multi_sw_3_le)) |
ic[-2].f == instr(multi_sw_2_le)) && |
3544 |
|
ic[-2].arg[1] == ic[0].arg[1]) { |
3545 |
|
if (cpu->byte_order == EMUL_LITTLE_ENDIAN) |
3546 |
|
ic[-2].f = instr(multi_sw_3_le); |
3547 |
|
else |
3548 |
|
ic[-2].f = instr(multi_sw_3_be); |
3549 |
|
} |
3550 |
|
|
3551 |
|
if (ic[-1].f == ic[0].f && ic[-1].arg[1] == ic[0].arg[1]) { |
3552 |
|
if (cpu->byte_order == EMUL_LITTLE_ENDIAN) |
3553 |
|
ic[-1].f = instr(multi_sw_2_le); |
3554 |
|
else |
3555 |
|
ic[-1].f = instr(multi_sw_2_be); |
3556 |
|
} |
3557 |
|
} |
3558 |
|
#endif |
3559 |
|
|
3560 |
|
|
3561 |
|
/* Only for 32-bit virtual address translation so far. */ |
3562 |
|
#ifdef MODE32 |
3563 |
|
/* |
3564 |
|
* Combine: Multiple LW in a row using the same base register |
3565 |
|
* |
3566 |
|
* lw r?,???(rX) |
3567 |
|
* lw r?,???(rX) |
3568 |
|
* lw r?,???(rX) |
3569 |
|
* ... |
3570 |
|
*/ |
3571 |
|
void COMBINE(multi_lw)(struct cpu *cpu, struct mips_instr_call *ic, |
3572 |
|
int low_addr) |
3573 |
|
{ |
3574 |
|
int n_back = (low_addr >> MIPS_INSTR_ALIGNMENT_SHIFT) |
3575 |
|
& (MIPS_IC_ENTRIES_PER_PAGE - 1); |
3576 |
|
|
3577 |
|
if (n_back < 3) |
3578 |
return; |
return; |
3579 |
|
|
3580 |
if (ic[-2].f == ic[0].f && ic[-1].f == ic[0].f && |
/* Convert a multi_lw_3 to a multi_lw_4: */ |
3581 |
|
if ((ic[-3].f == instr(multi_lw_3_be) || |
3582 |
|
ic[-3].f == instr(multi_lw_3_le)) && |
3583 |
|
ic[-3].arg[1] == ic[0].arg[1] && |
3584 |
|
ic[-1].arg[0] != ic[0].arg[1]) { |
3585 |
|
if (cpu->byte_order == EMUL_LITTLE_ENDIAN) |
3586 |
|
ic[-3].f = instr(multi_lw_4_le); |
3587 |
|
else |
3588 |
|
ic[-3].f = instr(multi_lw_4_be); |
3589 |
|
} |
3590 |
|
|
3591 |
|
/* Convert a multi_lw_2 to a multi_lw_3: */ |
3592 |
|
if ((ic[-2].f == instr(multi_lw_2_be) || |
3593 |
|
ic[-2].f == instr(multi_lw_2_le)) && |
3594 |
ic[-2].arg[1] == ic[0].arg[1] && |
ic[-2].arg[1] == ic[0].arg[1] && |
3595 |
ic[-1].arg[1] == ic[0].arg[1]) { |
ic[-1].arg[0] != ic[0].arg[1]) { |
3596 |
if (cpu->byte_order == EMUL_LITTLE_ENDIAN) |
if (cpu->byte_order == EMUL_LITTLE_ENDIAN) |
3597 |
ic[-2].f = instr(multi_sw_3_le); |
ic[-2].f = instr(multi_lw_3_le); |
3598 |
else |
else |
3599 |
ic[-2].f = instr(multi_sw_3_be); |
ic[-2].f = instr(multi_lw_3_be); |
3600 |
combined; |
} |
3601 |
|
|
3602 |
|
/* Note: Loads to the base register are not allowed in slot -1. */ |
3603 |
|
if (ic[-1].f == ic[0].f && |
3604 |
|
ic[-1].arg[1] == ic[0].arg[1] && |
3605 |
|
ic[-1].arg[0] != ic[0].arg[1]) { |
3606 |
|
if (cpu->byte_order == EMUL_LITTLE_ENDIAN) |
3607 |
|
ic[-1].f = instr(multi_lw_2_le); |
3608 |
|
else |
3609 |
|
ic[-1].f = instr(multi_lw_2_be); |
3610 |
} |
} |
3611 |
} |
} |
3612 |
|
#endif |
3613 |
|
|
3614 |
|
|
3615 |
/* |
/* |
3645 |
ic[-3].arg[1] == ic[-5].arg[0] && |
ic[-3].arg[1] == ic[-5].arg[0] && |
3646 |
ic[-2].f == instr(nop) && ic[-1].f == instr(nop)) { |
ic[-2].f == instr(nop) && ic[-1].f == instr(nop)) { |
3647 |
ic[-8].f = instr(netbsd_r3k_picache_do_inv); |
ic[-8].f = instr(netbsd_r3k_picache_do_inv); |
|
combined; |
|
3648 |
} |
} |
3649 |
} |
} |
3650 |
|
|
3654 |
* |
* |
3655 |
* NetBSD's strlen core. |
* NetBSD's strlen core. |
3656 |
* [Conditional] branch, followed by nop. |
* [Conditional] branch, followed by nop. |
3657 |
|
* NetBSD/pmax' idle loop (and possibly others as well). |
3658 |
|
* Linux/pmax' idle loop. |
3659 |
*/ |
*/ |
3660 |
void COMBINE(nop)(struct cpu *cpu, struct mips_instr_call *ic, int low_addr) |
void COMBINE(nop)(struct cpu *cpu, struct mips_instr_call *ic, int low_addr) |
3661 |
{ |
{ |
3662 |
int n_back = (low_addr >> MIPS_INSTR_ALIGNMENT_SHIFT) |
int n_back = (low_addr >> MIPS_INSTR_ALIGNMENT_SHIFT) |
3663 |
& (MIPS_IC_ENTRIES_PER_PAGE - 1); |
& (MIPS_IC_ENTRIES_PER_PAGE - 1); |
3664 |
|
|
3665 |
|
if (n_back < 8) |
3666 |
|
return; |
3667 |
|
|
3668 |
#ifdef MODE32 |
#ifdef MODE32 |
3669 |
if (n_back < 3) |
if (ic[-8].f == instr(set) && |
3670 |
|
ic[-7].f == mips32_loadstore[4 + 1] && |
3671 |
|
ic[-7].arg[0] == ic[-1].arg[0] && |
3672 |
|
ic[-7].arg[0] == ic[-3].arg[0] && |
3673 |
|
ic[-7].arg[0] == ic[-5].arg[0] && |
3674 |
|
ic[-7].arg[0] == ic[-7].arg[1] && |
3675 |
|
ic[-7].arg[0] == ic[-8].arg[0] && |
3676 |
|
ic[-6].f == instr(nop) && |
3677 |
|
ic[-5].arg[1] == (size_t) &cpu->cd.mips.gpr[MIPS_GPR_ZERO] && |
3678 |
|
ic[-5].f == instr(bne_samepage_nop) && |
3679 |
|
ic[-4].f == instr(nop) && |
3680 |
|
ic[-3].f == mips32_loadstore[4 + 1] && |
3681 |
|
ic[-2].f == instr(nop) && |
3682 |
|
ic[-1].arg[1] == (size_t) &cpu->cd.mips.gpr[MIPS_GPR_ZERO] && |
3683 |
|
ic[-1].arg[2] == (size_t) &ic[-8] && |
3684 |
|
ic[-1].f == instr(beq_samepage)) { |
3685 |
|
ic[-8].f = instr(linux_pmax_idle); |
3686 |
|
return; |
3687 |
|
} |
3688 |
|
|
3689 |
|
if (ic[-4].f == instr(set) && |
3690 |
|
ic[-3].f == mips32_loadstore[4 + 1] && |
3691 |
|
ic[-3].arg[0] == ic[-1].arg[0] && |
3692 |
|
ic[-3].arg[1] == ic[-4].arg[0] && |
3693 |
|
ic[-2].f == instr(nop) && |
3694 |
|
ic[-1].arg[1] == (size_t) &cpu->cd.mips.gpr[MIPS_GPR_ZERO] && |
3695 |
|
ic[-1].arg[2] == (size_t) &ic[-4] && |
3696 |
|
ic[-1].f == instr(beq_samepage)) { |
3697 |
|
ic[-4].f = instr(netbsd_pmax_idle); |
3698 |
return; |
return; |
3699 |
|
} |
3700 |
|
|
3701 |
if ((ic[-3].f == mips32_loadstore[1] || |
if ((ic[-3].f == mips32_loadstore[1] || |
3702 |
ic[-3].f == mips32_loadstore[16 + 1]) && |
ic[-3].f == mips32_loadstore[16 + 1]) && |
3707 |
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] && |
3708 |
ic[-1].f == instr(bne_samepage)) { |
ic[-1].f == instr(bne_samepage)) { |
3709 |
ic[-3].f = instr(netbsd_strlen); |
ic[-3].f = instr(netbsd_strlen); |
|
combined; |
|
3710 |
return; |
return; |
3711 |
} |
} |
3712 |
#endif |
#endif |
3713 |
|
|
|
if (n_back < 1) |
|
|
return; |
|
|
|
|
3714 |
if (ic[-1].f == instr(bne_samepage)) { |
if (ic[-1].f == instr(bne_samepage)) { |
3715 |
ic[-1].f = instr(bne_samepage_nop); |
ic[-1].f = instr(bne_samepage_nop); |
|
combined; |
|
3716 |
return; |
return; |
3717 |
} |
} |
3718 |
|
|
3719 |
if (ic[-1].f == instr(beq_samepage)) { |
if (ic[-1].f == instr(beq_samepage)) { |
3720 |
ic[-1].f = instr(beq_samepage_nop); |
ic[-1].f = instr(beq_samepage_nop); |
|
combined; |
|
3721 |
return; |
return; |
3722 |
} |
} |
3723 |
|
|
3728 |
/* |
/* |
3729 |
* Combine: |
* Combine: |
3730 |
* |
* |
3731 |
|
* xor + andi + sll |
3732 |
|
* andi + sll |
3733 |
|
*/ |
3734 |
|
void COMBINE(sll)(struct cpu *cpu, struct mips_instr_call *ic, int low_addr) |
3735 |
|
{ |
3736 |
|
int n_back = (low_addr >> MIPS_INSTR_ALIGNMENT_SHIFT) |
3737 |
|
& (MIPS_IC_ENTRIES_PER_PAGE - 1); |
3738 |
|
|
3739 |
|
if (n_back < 2) |
3740 |
|
return; |
3741 |
|
|
3742 |
|
if (ic[-2].f == instr(xor) && ic[-1].f == instr(andi)) { |
3743 |
|
ic[-2].f = instr(xor_andi_sll); |
3744 |
|
return; |
3745 |
|
} |
3746 |
|
|
3747 |
|
if (ic[-1].f == instr(andi)) { |
3748 |
|
ic[-1].f = instr(andi_sll); |
3749 |
|
return; |
3750 |
|
} |
3751 |
|
} |
3752 |
|
|
3753 |
|
|
3754 |
|
/* |
3755 |
|
* lui + ori |
3756 |
|
*/ |
3757 |
|
void COMBINE(ori)(struct cpu *cpu, struct mips_instr_call *ic, int low_addr) |
3758 |
|
{ |
3759 |
|
int n_back = (low_addr >> MIPS_INSTR_ALIGNMENT_SHIFT) |
3760 |
|
& (MIPS_IC_ENTRIES_PER_PAGE - 1); |
3761 |
|
|
3762 |
|
if (n_back < 1) |
3763 |
|
return; |
3764 |
|
|
3765 |
|
if (ic[-1].f == instr(set)) { |
3766 |
|
ic[-1].f = instr(lui_ori); |
3767 |
|
return; |
3768 |
|
} |
3769 |
|
} |
3770 |
|
|
3771 |
|
|
3772 |
|
/* |
3773 |
|
* addu + addu + addu |
3774 |
|
*/ |
3775 |
|
void COMBINE(addu)(struct cpu *cpu, struct mips_instr_call *ic, int low_addr) |
3776 |
|
{ |
3777 |
|
int n_back = (low_addr >> MIPS_INSTR_ALIGNMENT_SHIFT) |
3778 |
|
& (MIPS_IC_ENTRIES_PER_PAGE - 1); |
3779 |
|
|
3780 |
|
if (n_back < 4) |
3781 |
|
return; |
3782 |
|
|
3783 |
|
/* Avoid "overlapping" instruction combinations: */ |
3784 |
|
if (ic[-4].f == instr(multi_addu_3) || |
3785 |
|
ic[-3].f == instr(multi_addu_3)) |
3786 |
|
return; |
3787 |
|
|
3788 |
|
if (ic[-2].f == instr(addu) && ic[-1].f == instr(addu)) { |
3789 |
|
ic[-2].f = instr(multi_addu_3); |
3790 |
|
return; |
3791 |
|
} |
3792 |
|
} |
3793 |
|
|
3794 |
|
|
3795 |
|
/* |
3796 |
|
* Combine: |
3797 |
|
* |
3798 |
* [Conditional] branch, followed by addiu. |
* [Conditional] branch, followed by addiu. |
|
* lui + addiu. |
|
3799 |
*/ |
*/ |
3800 |
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) |
3801 |
{ |
{ |
3802 |
int n_back = (low_addr >> MIPS_INSTR_ALIGNMENT_SHIFT) |
int n_back = (low_addr >> MIPS_INSTR_ALIGNMENT_SHIFT) |
3803 |
& (MIPS_IC_ENTRIES_PER_PAGE - 1); |
& (MIPS_IC_ENTRIES_PER_PAGE - 1); |
3804 |
|
|
3805 |
if (n_back < 1) |
if (n_back < 2) |
3806 |
return; |
return; |
3807 |
|
|
3808 |
if (ic[-1].f == instr(set) && ic[-1].arg[0] == ic[0].arg[0] && |
if (ic[-2].f == instr(addiu) && |
3809 |
ic[0].arg[0] == ic[0].arg[1]) { |
ic[-1].f == instr(bne_samepage)) { |
3810 |
ic[-1].f = instr(lui_32bit); |
ic[-2].f = instr(addiu_bne_samepage_addiu); |
3811 |
ic[-1].arg[2] = (int32_t) (ic[-1].arg[1] + ic[0].arg[2]); |
return; |
3812 |
combined; |
} |
3813 |
|
|
3814 |
|
if (ic[-1].f == instr(set)) { |
3815 |
|
ic[-1].f = instr(lui_addiu); |
3816 |
return; |
return; |
3817 |
} |
} |
3818 |
|
|
3819 |
if (ic[-1].f == instr(b_samepage)) { |
if (ic[-1].f == instr(b_samepage)) { |
3820 |
ic[-1].f = instr(b_samepage_addiu); |
ic[-1].f = instr(b_samepage_addiu); |
|
combined; |
|
3821 |
return; |
return; |
3822 |
} |
} |
3823 |
|
|
3824 |
if (ic[-1].f == instr(beq_samepage)) { |
if (ic[-1].f == instr(beq_samepage)) { |
3825 |
ic[-1].f = instr(beq_samepage_addiu); |
ic[-1].f = instr(beq_samepage_addiu); |
|
combined; |
|
3826 |
return; |
return; |
3827 |
} |
} |
3828 |
|
|
3829 |
if (ic[-1].f == instr(bne_samepage)) { |
if (ic[-1].f == instr(bne_samepage)) { |
3830 |
ic[-1].f = instr(bne_samepage_addiu); |
ic[-1].f = instr(bne_samepage_addiu); |
|
combined; |
|
3831 |
return; |
return; |
3832 |
} |
} |
3833 |
|
|
3834 |
if (ic[-1].f == instr(jr_ra)) { |
if (ic[-1].f == instr(jr_ra)) { |
3835 |
ic[-1].f = instr(jr_ra_addiu); |
ic[-1].f = instr(jr_ra_addiu); |
|
combined; |
|
3836 |
return; |
return; |
3837 |
} |
} |
3838 |
|
|
3854 |
|
|
3855 |
if (ic[-1].f == instr(b_samepage)) { |
if (ic[-1].f == instr(b_samepage)) { |
3856 |
ic[-1].f = instr(b_samepage_daddiu); |
ic[-1].f = instr(b_samepage_daddiu); |
|
combined; |
|
3857 |
} |
} |
3858 |
|
|
3859 |
/* TODO: other branches that are followed by daddiu should be here */ |
/* TODO: other branches that are followed by daddiu should be here */ |
3877 |
uint32_t iword, imm; |
uint32_t iword, imm; |
3878 |
unsigned char *page; |
unsigned char *page; |
3879 |
unsigned char ib[4]; |
unsigned char ib[4]; |
3880 |
int main_opcode, rt, rs, rd, sa, s6, x64 = 0; |
int main_opcode, rt, rs, rd, sa, s6, x64 = 0, s10; |
3881 |
int in_crosspage_delayslot = 0; |
int in_crosspage_delayslot = 0; |
3882 |
void (*samepage_function)(struct cpu *, struct mips_instr_call *); |
void (*samepage_function)(struct cpu *, struct mips_instr_call *); |
3883 |
int store, signedness, size; |
int store, signedness, size; |
3958 |
sa = (iword >> 6) & 31; |
sa = (iword >> 6) & 31; |
3959 |
imm = (int16_t)iword; |
imm = (int16_t)iword; |
3960 |
s6 = iword & 63; |
s6 = iword & 63; |
3961 |
|
s10 = (rs << 5) | sa; |
3962 |
|
|
3963 |
switch (main_opcode) { |
switch (main_opcode) { |
3964 |
|
|
4011 |
ic->arg[2] = (size_t)&cpu->cd.mips.gpr[rd]; |
ic->arg[2] = (size_t)&cpu->cd.mips.gpr[rd]; |
4012 |
if (rd == MIPS_GPR_ZERO) |
if (rd == MIPS_GPR_ZERO) |
4013 |
ic->f = instr(nop); |
ic->f = instr(nop); |
4014 |
|
if (ic->f == instr(sll)) |
4015 |
|
cpu->cd.mips.combination_check = COMBINE(sll); |
4016 |
|
if (ic->f == instr(nop)) |
4017 |
|
cpu->cd.mips.combination_check = COMBINE(nop); |
4018 |
|
|
4019 |
|
/* Special checks for MIPS32/64 revision 2 opcodes, |
4020 |
|
such as rotation instructions: */ |
4021 |
|
if (sa >= 0 && rs != 0x00) { |
4022 |
|
switch (rs) { |
4023 |
|
/* TODO: [d]ror, etc. */ |
4024 |
|
default:goto bad; |
4025 |
|
} |
4026 |
|
} |
4027 |
|
if (sa < 0 && (s10 & 0x1f) != 0) { |
4028 |
|
switch (s10 & 0x1f) { |
4029 |
|
/* TODO: [d]rorv, etc. */ |
4030 |
|
default:goto bad; |
4031 |
|
} |
4032 |
|
} |
4033 |
break; |
break; |
4034 |
|
|
4035 |
case SPECIAL_ADD: |
case SPECIAL_ADD: |
4161 |
default:if (rd == MIPS_GPR_ZERO) |
default:if (rd == MIPS_GPR_ZERO) |
4162 |
ic->f = instr(nop); |
ic->f = instr(nop); |
4163 |
} |
} |
4164 |
|
|
4165 |
|
if (ic->f == instr(addu)) |
4166 |
|
cpu->cd.mips.combination_check = COMBINE(addu); |
4167 |
break; |
break; |
4168 |
|
|
4169 |
case SPECIAL_JR: |
case SPECIAL_JR: |
4207 |
break; |
break; |
4208 |
|
|
4209 |
case SPECIAL_BREAK: |
case SPECIAL_BREAK: |
4210 |
ic->f = instr(break); |
if (((iword >> 6) & 0xfffff) == 0x30378) { |
4211 |
|
/* "Magic trap" for REBOOT: */ |
4212 |
|
ic->f = instr(reboot); |
4213 |
|
} else { |
4214 |
|
ic->f = instr(break); |
4215 |
|
} |
4216 |
break; |
break; |
4217 |
|
|
4218 |
case SPECIAL_SYNC: |
case SPECIAL_SYNC: |
4339 |
if (rt == MIPS_GPR_ZERO) |
if (rt == MIPS_GPR_ZERO) |
4340 |
ic->f = instr(nop); |
ic->f = instr(nop); |
4341 |
|
|
4342 |
|
if (ic->f == instr(ori)) |
4343 |
|
cpu->cd.mips.combination_check = COMBINE(ori); |
4344 |
if (ic->f == instr(addiu)) |
if (ic->f == instr(addiu)) |
4345 |
cpu->cd.mips.combination_check = COMBINE(addiu); |
cpu->cd.mips.combination_check = COMBINE(addiu); |
4346 |
if (ic->f == instr(daddiu)) |
if (ic->f == instr(daddiu)) |
4406 |
case COP0_DERET: |
case COP0_DERET: |
4407 |
ic->f = instr(deret); |
ic->f = instr(deret); |
4408 |
break; |
break; |
4409 |
case COP0_IDLE: |
case COP0_WAIT: |
4410 |
|
ic->f = instr(wait); |
4411 |
|
if (cpu->cd.mips.cpu_type.rev != MIPS_RM5200 && |
4412 |
|
cpu->cd.mips.cpu_type.isa_level < 32) { |
4413 |
|
static int warned = 0; |
4414 |
|
ic->f = instr(reserved); |
4415 |
|
if (!warned) { |
4416 |
|
fatal("{ WARNING: Attempt to " |
4417 |
|
"execute the WAIT instruct" |
4418 |
|
"ion, but the emulated CPU " |
4419 |
|
"is neither RM52xx, nor " |
4420 |
|
"MIPS32/64! }\n"); |
4421 |
|
warned = 1; |
4422 |
|
} |
4423 |
|
} |
4424 |
|
break; |
4425 |
case COP0_STANDBY: |
case COP0_STANDBY: |
4426 |
case COP0_SUSPEND: |
/* NOTE: Reusing the 'wait' instruction: */ |
4427 |
|
ic->f = instr(wait); |
4428 |
|
if (cpu->cd.mips.cpu_type.rev != MIPS_R4100) { |
4429 |
|
static int warned = 0; |
4430 |
|
ic->f = instr(reserved); |
4431 |
|
if (!warned) { |
4432 |
|
fatal("{ WARNING: Attempt to " |
4433 |
|
"execute a R41xx instruct" |
4434 |
|
"ion, but the emulated CPU " |
4435 |
|
"doesn't support it! }\n"); |
4436 |
|
warned = 1; |
4437 |
|
} |
4438 |
|
} |
4439 |
|
break; |
4440 |
case COP0_HIBERNATE: |
case COP0_HIBERNATE: |
4441 |
/* TODO */ |
/* TODO */ |
4442 |
ic->f = instr(nop); |
goto bad; |
4443 |
|
case COP0_SUSPEND: |
4444 |
|
/* Used by NetBSD on HPCmips (VR41xx) to |
4445 |
|
halt the machine. */ |
4446 |
|
ic->f = instr(reboot); |
4447 |
break; |
break; |
4448 |
case COP0_EI: |
case COP0_EI: |
4449 |
if (cpu->cd.mips.cpu_type.rev == MIPS_R5900) { |
if (cpu->cd.mips.cpu_type.rev == MIPS_R5900) { |
4480 |
ic->arg[1] = rd + ((iword & 7) << 5); |
ic->arg[1] = rd + ((iword & 7) << 5); |
4481 |
ic->arg[2] = addr & 0xffc; |
ic->arg[2] = addr & 0xffc; |
4482 |
ic->f = rs == COPz_MFCz? instr(mfc0) : instr(dmfc0); |
ic->f = rs == COPz_MFCz? instr(mfc0) : instr(dmfc0); |
4483 |
|
if (rs == COPz_MFCz && (iword & 7) == 0 && |
4484 |
|
rd != COP0_COUNT) |
4485 |
|
ic->f = instr(mfc0_select0); |
4486 |
|
if (rs == COPz_DMFCz && (iword & 7) == 0 && |
4487 |
|
rd != COP0_COUNT) |
4488 |
|
ic->f = instr(dmfc0_select0); |
4489 |
if (rt == MIPS_GPR_ZERO) |
if (rt == MIPS_GPR_ZERO) |
4490 |
ic->f = instr(nop); |
ic->f = instr(nop); |
4491 |
break; |
break; |
4819 |
if (!store && rt == MIPS_GPR_ZERO) |
if (!store && rt == MIPS_GPR_ZERO) |
4820 |
ic->arg[0] = (size_t)&cpu->cd.mips.scratch; |
ic->arg[0] = (size_t)&cpu->cd.mips.scratch; |
4821 |
|
|
4822 |
/* Check for multiple stores in a row using the same |
/* Check for multiple loads or stores in a row using the same |
4823 |
base register: */ |
base register: */ |
4824 |
if (main_opcode == HI6_SW && rs == MIPS_GPR_SP) |
#ifdef MODE32 |
4825 |
|
if (main_opcode == HI6_LW) |
4826 |
|
cpu->cd.mips.combination_check = COMBINE(multi_lw); |
4827 |
|
if (main_opcode == HI6_SW) |
4828 |
cpu->cd.mips.combination_check = COMBINE(multi_sw); |
cpu->cd.mips.combination_check = COMBINE(multi_sw); |
4829 |
|
#endif |
4830 |
break; |
break; |
4831 |
|
|
4832 |
case HI6_LL: |
case HI6_LL: |
4959 |
|
|
4960 |
switch (s6) { |
switch (s6) { |
4961 |
|
|
4962 |
|
case SPECIAL3_EXT: |
4963 |
|
/* TODO: Cleanup and extend to DEXT... etc */ |
4964 |
|
{ |
4965 |
|
int msbd = rd, lsb = (iword >> 6) & 0x1f; |
4966 |
|
ic->arg[0] = (size_t)&cpu->cd.mips.gpr[rt]; |
4967 |
|
ic->arg[1] = (size_t)&cpu->cd.mips.gpr[rs]; |
4968 |
|
ic->arg[2] = (msbd << 5) + lsb; |
4969 |
|
ic->f = instr(ext); |
4970 |
|
if (rt == MIPS_GPR_ZERO) |
4971 |
|
ic->f = instr(nop); |
4972 |
|
} |
4973 |
|
break; |
4974 |
|
|
4975 |
|
case SPECIAL3_BSHFL: |
4976 |
|
ic->arg[0] = (size_t)&cpu->cd.mips.gpr[rt]; |
4977 |
|
ic->arg[1] = (size_t)&cpu->cd.mips.gpr[rd]; |
4978 |
|
switch (s10) { |
4979 |
|
case BSHFL_WSBH: |
4980 |
|
ic->f = instr(wsbh); |
4981 |
|
break; |
4982 |
|
case BSHFL_SEB: |
4983 |
|
ic->f = instr(seb); |
4984 |
|
break; |
4985 |
|
case BSHFL_SEH: |
4986 |
|
ic->f = instr(seh); |
4987 |
|
break; |
4988 |
|
default:goto bad; |
4989 |
|
} |
4990 |
|
break; |
4991 |
|
|
4992 |
|
case SPECIAL3_DBSHFL: |
4993 |
|
ic->arg[0] = (size_t)&cpu->cd.mips.gpr[rt]; |
4994 |
|
ic->arg[1] = (size_t)&cpu->cd.mips.gpr[rd]; |
4995 |
|
switch (s10) { |
4996 |
|
case BSHFL_DSBH: |
4997 |
|
ic->f = instr(dsbh); |
4998 |
|
break; |
4999 |
|
case BSHFL_DSHD: |
5000 |
|
ic->f = instr(dshd); |
5001 |
|
break; |
5002 |
|
default:goto bad; |
5003 |
|
} |
5004 |
|
break; |
5005 |
|
|
5006 |
case SPECIAL3_RDHWR: |
case SPECIAL3_RDHWR: |
5007 |
ic->arg[0] = (size_t)&cpu->cd.mips.gpr[rt]; |
ic->arg[0] = (size_t)&cpu->cd.mips.gpr[rt]; |
5008 |
|
|
5043 |
} |
} |
5044 |
#endif |
#endif |
5045 |
|
|
|
if (ic->f == instr(nop) && cpu->cd.mips.combination_check == NULL) |
|
|
cpu->cd.mips.combination_check = COMBINE(nop); |
|
|
|
|
5046 |
|
|
5047 |
#define DYNTRANS_TO_BE_TRANSLATED_TAIL |
#define DYNTRANS_TO_BE_TRANSLATED_TAIL |
5048 |
#include "cpu_dyntrans.c" |
#include "cpu_dyntrans.c" |