63 int IB, DB, SB,
IC, DC, SC, IA, DA;
86 IB = IB < 0? 0 : (IB > 7? 7 : IB);
88 DB = DB < 0? 0 : (DB > 7? 7 : DB);
121 IB = IB < 0? 0 : (IB > 1? 1 : IB);
123 DB = DB < 0? 0 : (DB > 1? 1 : DB);
125 SB = SB < 0? 0 : (SB > 3? 3 : SB);
129 DC = DC < 0? 0 : (DC > 7? 7 : DC);
163 IB = IB < 0? 0 : (IB > 1? 1 : IB);
165 DB = DB < 0? 0 : (DB > 1? 1 : DB);
169 DC = DC < 0? 0 : (DC > 7? 7 : DC);
236 DC = DC < 0? 0 : (DC > 7? 7 : DC);
238 SC = SC < 0? 0 : (SC > 7? 7 : SC);
302 default:
fatal(
"Internal error: No initialization code for"
317 uint64_t other_stuff = 0;
402 initialize_cop0_config(
cpu, c);
409 initialize_cop1(
cpu, c);
418 static void mips_timer_tick(
struct timer *
timer,
void *extra)
439 uint64_t vaddr, uint64_t paddr0, uint64_t paddr1,
440 int valid0,
int valid1,
int dirty0,
int dirty1,
int global,
int asid,
441 int cachealgo0,
int cachealgo1)
444 printf(
"mips_coproc_tlb_set_entry(): invalid entry nr: %i\n",
452 printf(
"mips_coproc_tlb_set_entry(): invalid pagesize "
453 "(%i) for MMU3K\n", size);
483 (2*size - 1) & ~0x1fff;
512 static void invalidate_asid(
struct cpu *
cpu,
unsigned int asid)
519 for (i = 0; i < ntlbs; i++)
528 for (i = 0; i < ntlbs; i++) {
533 uint64_t pagesize = 0x1000;
534 uint64_t tmp =
mask >> 13;
543 oldvaddr = cp->
tlbs[i].
hi &
548 oldvaddr = (int32_t)oldvaddr;
551 oldvaddr = cp->
tlbs[i].
hi &
561 for (uint64_t ofs = 0; ofs < pagesize; ofs += 0x1000)
565 for (uint64_t ofs = 0; ofs < pagesize; ofs += 0x1000)
578 struct mips_coproc *cp,
int reg_nr, uint64_t *ptr,
int select)
607 default:
fatal(
"coproc_register_read(): unimplemented"
608 " config register select %i\n", select);
635 fatal(
"cpu%i: warning: read from unimplemented coproc%i"
637 cp->
coproc_nr==0? cop0_names[reg_nr] :
"?");
644 *ptr = cp->
reg[reg_nr];
654 struct mips_coproc *cp,
int reg_nr, uint64_t *ptr,
int flag64,
660 uint64_t tmp2 = 0, old;
662 unsigned int old_asid;
698 debug(
"[ MIPS coproc_register_write: unimplemented c = %i ]\n", c);
709 fatal(
"Attempt to access ENTRYLO1 with MMU3K?\n");
750 fatal(
"[ cpu%i: trying to write an invalid"
751 " pagemask 0x%08lx to COP0_PAGEMASK ]\n",
764 fatal(
"[ cpu%i: r2k/r3k wired register must "
773 if (tmp != (uint64_t)(int64_t)(int32_t)tmp)
774 fatal(
"[ WARNING: trying to write a 64-bit value"
775 " to the COUNT register! ]\n");
776 tmp = (int64_t)(int32_t)tmp;
781 int32_t compare_diff = tmp -
785 if (compare_diff < 0)
788 if (compare_diff == 0)
792 / (
double)compare_diff;
798 hz, mips_timer_tick,
cpu);
813 if (tmp != (uint64_t)(int64_t)(int32_t)tmp)
814 fatal(
"[ WARNING: trying to write a 64-bit value"
815 " to the COMPARE register! ]\n");
817 tmp = (int64_t)(int32_t)tmp;
844 invalidate_asid(
cpu, old_asid);
883 default:
fatal(
"[ coproc_register_write(): unimpl"
884 "emented config register select "
895 cp->
reg[reg_nr] &= ~(0x3); cp->
reg[reg_nr] |= tmp;
982 fatal(
"[ cpu%i: warning: write to unimplemented coproc%i "
983 "register %i (%s), data = 0x%016llx ]\n",
cpu->
cpu_id,
985 cop0_names[reg_nr] :
"?", (
long long)tmp);
993 fatal(
"[ cpu%i: warning: write to READONLY coproc%i register "
998 cp->
reg[reg_nr] = tmp;
1001 cp->
reg[reg_nr] = (int64_t)(int32_t)cp->
reg[reg_nr];
1010 static int mips_fmt_to_ieee_fmt[32] = {
1011 0, 0, 0, 0, 0, 0, 0, 0,
1012 0, 0, 0, 0, 0, 0, 0, 0,
1015 0, 0, 0, 0, 0, 0, 0, 0 };
1017 static const char *fmtname[32] = {
1018 "0",
"1",
"2",
"3",
"4",
"5",
"6",
"7",
1019 "8",
"9",
"10",
"11",
"12",
"13",
"14",
"15",
1020 "s",
"d",
"18",
"19",
"w",
"l",
"ps",
"23",
1021 "24",
"25",
"26",
"27",
"28",
"29",
"30",
"31" };
1023 static const char *ccname[16] = {
1024 "f",
"un",
"eq",
"ueq",
"olt",
"ult",
"ole",
"ule",
1025 "sf",
"ngle",
"seq",
"ngl",
"lt",
"nge",
"le",
"ngt" };
1027 #define FPU_OP_ADD 1
1028 #define FPU_OP_SUB 2
1029 #define FPU_OP_MUL 3
1030 #define FPU_OP_DIV 4
1031 #define FPU_OP_SQRT 5
1032 #define FPU_OP_MOV 6
1033 #define FPU_OP_CVT 7
1035 #define FPU_OP_ABS 9
1036 #define FPU_OP_NEG 10
1045 static void fpu_store_float_value(
bool fr,
struct mips_coproc *cp,
int fd,
1046 double nf,
int fmt,
int nan)
1048 int ieee_fmt = mips_fmt_to_ieee_fmt[fmt];
1059 cp->
reg[fd] = r & 0xffffffffULL;
1060 cp->
reg[(fd+1) & 31] = (r >> 32) & 0xffffffffULL;
1062 if (cp->
reg[fd] & 0x80000000ULL)
1063 cp->
reg[fd] |= 0xffffffff00000000ULL;
1064 if (cp->
reg[fd+1] & 0x80000000ULL)
1065 cp->
reg[fd+1] |= 0xffffffff00000000ULL;
1068 cp->
reg[fd] = r & 0xffffffffULL;
1070 if (cp->
reg[fd] & 0x80000000ULL)
1071 cp->
reg[fd] |= 0xffffffff00000000ULL;
1086 int ft,
int fs,
int fd,
int cond,
int output_fmt)
1090 int unordered,
nan, ieee_fmt = mips_fmt_to_ieee_fmt[fmt];
1101 fs_v = (fs_v & 0xffffffffULL) +
1102 (cp->
reg[(fs + 1) & 31] << 32);
1108 uint64_t v = cp->
reg[ft];
1111 v = (v & 0xffffffffULL) +
1112 (cp->
reg[(ft + 1) & 31] << 32);
1121 nf = float_value[0].f + float_value[1].f;
1124 fpu_store_float_value(fr, cp, fd, nf, output_fmt,
1125 float_value[0].
nan || float_value[1].
nan);
1128 nf = float_value[0].f - float_value[1].f;
1131 fpu_store_float_value(fr, cp, fd, nf, output_fmt,
1132 float_value[0].
nan || float_value[1].
nan);
1135 nf = float_value[0].f * float_value[1].f;
1138 fpu_store_float_value(fr, cp, fd, nf, output_fmt,
1139 float_value[0].
nan || float_value[1].
nan);
1142 nan = float_value[0].nan || float_value[1].nan;
1143 if (fabs(float_value[1].
f) > 0.00000000001)
1144 nf = float_value[0].f / float_value[1].f;
1146 fatal(
"DIV by zero !!!! TODO\n");
1154 fpu_store_float_value(fr, cp, fd, nf, output_fmt,
nan);
1157 nan = float_value[0].nan;
1158 if (float_value[0].
f >= 0.0)
1159 nf = sqrt(float_value[0].
f);
1161 fatal(
"SQRT by less than zero, %f !!!!\n",
1167 fpu_store_float_value(fr, cp, fd, nf, output_fmt,
nan);
1170 nf = fabs(float_value[0].
f);
1172 fpu_store_float_value(fr, cp, fd, nf, output_fmt,
1173 float_value[0].
nan);
1176 nf = - float_value[0].f;
1178 fpu_store_float_value(fr, cp, fd, nf, output_fmt,
1179 float_value[0].
nan);
1182 nf = float_value[0].f;
1184 fpu_store_float_value(fr, cp, fd, nf, output_fmt,
1185 float_value[0].
nan);
1197 cp->
reg[fd] = fs_v & 0xffffffffULL;
1198 cp->
reg[(fd+1) & 31] = (fs_v >> 32) & 0xffffffffULL;
1199 if (cp->
reg[fd] & 0x80000000ULL)
1200 cp->
reg[fd] |= 0xffffffff00000000ULL;
1201 if (cp->
reg[fd+1] & 0x80000000ULL)
1202 cp->
reg[fd+1] |= 0xffffffff00000000ULL;
1205 cp->
reg[fd] = fs_v & 0xffffffffULL;
1206 if (cp->
reg[fd] & 0x80000000ULL)
1207 cp->
reg[fd] |= 0xffffffff00000000ULL;
1214 if (float_value[0].
nan || float_value[1].
nan)
1219 return (float_value[0].
f == float_value[1].
f);
1221 return (float_value[0].
f < float_value[1].
f)
1224 return (float_value[0].
f < float_value[1].
f)
1227 return (float_value[0].
f <= float_value[1].
f)
1230 return (float_value[0].
f <= float_value[1].
f)
1233 return (float_value[0].
f < float_value[1].
f);
1235 return (float_value[0].
f <= float_value[1].
f);
1242 case 3:
return (float_value[0].
f == float_value[1].
f);
1246 case 10:
return (float_value[0].
f == float_value[1].
f);
1247 case 11:
return (float_value[0].
f == float_value[1].
f);
1249 case 13:
return !(float_value[0].f >= float_value[1].f);
1251 case 15:
return !(float_value[0].f > float_value[1].f);
1255 fatal(
"fpu_op(): unimplemented condition "
1256 "code %i. see cpu_mips_coproc.c\n",
cond);
1260 fatal(
"fpu_op(): unimplemented op %i\n",
op);
1274 uint32_t
function,
int unassemble_only)
1276 int fd, fs, ft, fmt,
cond, cc;
1278 fmt = (
function >> 21) & 31;
1279 ft = (
function >> 16) & 31;
1280 fs = (
function >> 11) & 31;
1281 cc = (
function >> 8) & 7;
1282 fd = (
function >> 6) & 31;
1283 cond = (
function >> 0) & 15;
1287 if ((
function & 0x03e00000) == 0x01000000) {
1289 const char *instr_mnem;
1292 cc = (
function >> 18) & 7;
1293 nd = (
function >> 17) & 1;
1294 tf = (
function >> 16) & 1;
1295 imm =
function & 65535;
1300 if (nd == 0 && tf == 0) instr_mnem =
"bc1f";
1301 if (nd == 0 && tf == 1) instr_mnem =
"bc1t";
1302 if (nd == 1 && tf == 0) instr_mnem =
"bc1fl";
1303 if (nd == 1 && tf == 1) instr_mnem =
"bc1tl";
1306 debug(
"%s\t%i,0x%016llx\n", instr_mnem, cc,
1307 (
long long) (
cpu->
pc + 4 + (imm << 2)));
1308 if (unassemble_only)
1311 fatal(
"INTERNAL ERROR: MIPS coprocessor branches should not"
1312 " be implemented in cpu_mips_coproc.c, but in"
1313 " cpu_mips_instr.c!\n");
1318 if ((
function & 0x0000003f) == 0x00000000) {
1320 debug(
"add.%s\tr%i,r%i,r%i\n",
1321 fmtname[fmt], fd, fs, ft);
1322 if (unassemble_only)
1330 if ((
function & 0x0000003f) == 0x00000001) {
1332 debug(
"sub.%s\tr%i,r%i,r%i\n",
1333 fmtname[fmt], fd, fs, ft);
1334 if (unassemble_only)
1342 if ((
function & 0x0000003f) == 0x00000002) {
1344 debug(
"mul.%s\tr%i,r%i,r%i\n",
1345 fmtname[fmt], fd, fs, ft);
1346 if (unassemble_only)
1354 if ((
function & 0x0000003f) == 0x00000003) {
1356 debug(
"div.%s\tr%i,r%i,r%i\n",
1357 fmtname[fmt], fd, fs, ft);
1358 if (unassemble_only)
1366 if ((
function & 0x001f003f) == 0x00000004) {
1368 debug(
"sqrt.%s\tr%i,r%i\n", fmtname[fmt], fd, fs);
1369 if (unassemble_only)
1377 if ((
function & 0x001f003f) == 0x00000005) {
1379 debug(
"abs.%s\tr%i,r%i\n", fmtname[fmt], fd, fs);
1380 if (unassemble_only)
1388 if ((
function & 0x0000003f) == 0x00000006) {
1390 debug(
"mov.%s\tr%i,r%i\n", fmtname[fmt], fd, fs);
1391 if (unassemble_only)
1399 if ((
function & 0x001f003f) == 0x00000007) {
1401 debug(
"neg.%s\tr%i,r%i\n", fmtname[fmt], fd, fs);
1402 if (unassemble_only)
1410 if ((
function & 0x001f003f) == 0x00000009) {
1412 debug(
"trunc.l.%s\tr%i,r%i\n", fmtname[fmt], fd, fs);
1413 if (unassemble_only)
1423 if ((
function & 0x001f003f) == 0x0000000d) {
1425 debug(
"trunc.w.%s\tr%i,r%i\n", fmtname[fmt], fd, fs);
1426 if (unassemble_only)
1436 if ((
function & 0x000000f0) == 0x00000030) {
1441 debug(
"c.%s.%s\tcc%i,r%i,r%i\n", ccname[
cond],
1442 fmtname[fmt], cc, fs, ft);
1443 if (unassemble_only)
1447 ft, fs, -1,
cond, fmt);
1474 if ((
function & 0x001f003f) == 0x00000020) {
1476 debug(
"cvt.s.%s\tr%i,r%i\n", fmtname[fmt], fd, fs);
1477 if (unassemble_only)
1485 if ((
function & 0x001f003f) == 0x00000021) {
1487 debug(
"cvt.d.%s\tr%i,r%i\n", fmtname[fmt], fd, fs);
1488 if (unassemble_only)
1496 if ((
function & 0x001f003f) == 0x00000024) {
1498 debug(
"cvt.w.%s\tr%i,r%i\n", fmtname[fmt], fd, fs);
1499 if (unassemble_only)
1518 int i, found, g_bit;
1519 uint64_t vpn2, xmask;
1528 fatal(
"[ warning: tlbr from index %i (too "
1540 fatal(
"[ warning: tlbr from index %i (too "
1601 uint64_t a = vpn2 & ~cp->
tlbs[i].
mask;
1602 uint64_t b = (cp->
tlbs[i].
hi & xmask) &
1625 0xffffffff00000000ULL;
1662 fatal(
"warning: tlb index %i too high (max is %i)\n",
1671 fatal(
"{ old TLB entry at index %02x:", index);
1673 fatal(
" hi=%08" PRIx32, (uint32_t)cp->
tlbs[index].
hi);
1674 fatal(
" lo=%08" PRIx32, (uint32_t)cp->
tlbs[index].
lo0);
1678 fatal(
" hi=%08" PRIx32, (uint32_t)cp->
tlbs[index].
hi);
1679 fatal(
" lo0=%08" PRIx32, (uint32_t)cp->
tlbs[index].
lo0);
1680 fatal(
" lo1=%08" PRIx32, (uint32_t)cp->
tlbs[index].
lo1);
1704 oldvaddr = (int32_t) oldvaddr;
1716 oldvaddr = cp->
tlbs[index].
hi &
1721 oldvaddr = (int32_t)oldvaddr;
1724 oldvaddr = cp->
tlbs[index].
hi &
1730 uint64_t dpmask = cp->
tlbs[index].
mask;
1737 if (dpmask == 0x7ff) {
1740 fatal(
"1KB pages don't work with dyntrans.\n");
1746 uint64_t mask = dpmask >> 1;
1748 uint64_t pagesize = mask + 1;
1750 oldvaddr &= ~dpmask;
1755 for (uint64_t ofs = 0; ofs < pagesize; ofs += 0x1000)
1759 for (uint64_t ofs = 0; ofs < pagesize; ofs += 0x1000)
1775 uint64_t vaddr1, vaddr2;
1786 if (i == index && !randomflag)
1793 vaddr2 = cp->
tlbs[i].
hi &
1795 if (vaddr1 == vaddr2 && ((cp->
tlbs[i].
lo0 &
1797 fatal(
"\n[ WARNING! tlbw%s to index 0x%02x "
1798 "vaddr=0x%llx (asid 0x%02x) is already in"
1799 " the TLB (entry 0x%02x) ! ]\n\n",
1800 randomflag?
"r" :
"i", index,
1801 (
long long)vaddr1, asid, i);
1809 uint32_t vaddr, paddr;
1829 fatal(
"Wow! Interesting case; tlbw* while caches"
1830 " are isolated. TODO\n");
1840 if (memblock != NULL)
1846 uint64_t vaddr0, vaddr1, ptmp, psize;
1864 if (dpmask == 0x7ff) {
1867 fatal(
"1KB pages don't work with dyntrans.\n");
1873 uint64_t mask = dpmask >> 1;
1880 uint64_t paddr0, paddr1;
1883 paddr0 = (pfn0 << 10) & ~mask;
1884 paddr1 = (pfn1 << 10) & ~mask;
1886 paddr0 = (pfn0 << 12) & ~mask;
1887 paddr1 = (pfn1 << 12) & ~mask;
1895 vaddr0 = (int32_t)vaddr0;
1904 vaddr1 = vaddr0 | psize;
1927 for (ptmp = 0; ptmp < psize; ptmp += 0x1000)
1932 for (ptmp = 0; ptmp < psize; ptmp += 0x1000)
1947 if (psize == 0x1000) {
1950 if (memblock != NULL)
1955 if (memblock != NULL)
1996 uint32_t
function,
int unassemble_only,
int running)
1998 int co_bit,
op, rt, rd, fs, copz;
2002 if (unassemble_only) {
2003 debug(
"cop%i\t0x%08x (coprocessor not available)\n",
2004 cpnr, (
int)
function);
2007 fatal(
"[ pc=0x%016llx cop%i\t0x%08x (coprocessor not "
2008 "available)\n", (
long long)
cpu->
pc, cpnr, (
int)
function);
2019 copz = (
function >> 21) & 31;
2020 rt = (
function >> 16) & 31;
2021 rd = (
function >> 11) & 31;
2023 if (cpnr < 2 && (((
function & 0x03e007f8) == (
COPz_MFCz << 21))
2024 || ((
function & 0x03e007f8) == (
COPz_DMFCz << 21)))) {
2025 if (unassemble_only) {
2027 cpnr, regnames[rt]);
2029 debug(
"%s", cop0_names[rd]);
2033 debug(
",%i", (
int)(
function & 7));
2038 rd, &tmpvalue,
function & 7);
2049 if (cpnr < 2 && (((
function & 0x03e007f8) == (
COPz_MTCz << 21))
2050 || ((
function & 0x03e007f8) == (
COPz_DMTCz << 21)))) {
2054 tmpvalue &= 0xffffffffULL;
2055 if (tmpvalue & 0x80000000ULL)
2056 tmpvalue |= 0xffffffff00000000ULL;
2058 if (unassemble_only) {
2060 cpnr, regnames[rt]);
2062 debug(
"%s", cop0_names[rd]);
2066 debug(
",%i", (
int)(
function & 7));
2067 debug(
" [%016llx]", (
long long)tmpvalue);
2072 &tmpvalue, copz ==
COPz_DMTCz,
function & 7);
2076 if (cpnr <= 1 && (((
function & 0x03e007ff) == (
COPz_CFCz << 21))
2077 || ((
function & 0x03e007ff) == (
COPz_CTCz << 21)))) {
2080 rt = (
function >> 16) & 31;
2081 fs = (
function >> 11) & 31;
2082 if (unassemble_only) {
2083 debug(
"cfc%i\t%s,r%i\n", cpnr,
2092 rt = (
function >> 16) & 31;
2093 fs = (
function >> 11) & 31;
2094 if (unassemble_only) {
2095 debug(
"ctc%i\t%s,r%i\n", cpnr,
2102 fatal(
"[ warning: unimplemented ctc%i, "
2103 "0x%08x -> ctl reg %i ]\n", cpnr,
2108 fatal(
"[ Attempt to write to FPU "
2109 "control register 0 (?) ]\n");
2122 0x017fffffULL) | ((tmp & 1)
2124 | (((tmp & 0xfe) >> 1) <<
2130 0xffffff00ULL) | ((tmp >>
2153 if (fpu_function(
cpu, cp,
function, unassemble_only))
2160 if ((
function & 0xfffff) ==
COP0_EI) {
2161 if (unassemble_only) {
2170 if ((
function & 0xfffff) ==
COP0_DI) {
2171 if (unassemble_only) {
2181 co_bit = (
function >> 25) & 1;
2185 if (!unassemble_only) {
2186 fatal(
"FATAL INTERNAL ERROR: Should be implemented"
2187 " with dyntrans instead.\n");
2193 if ((
function & 0x03e0ffdf) == 0x01606000) {
2194 debug(
"%ci",
function & 0x20?
'e' :
'd');
2196 debug(
"\t%s", regnames[rt]);
2202 op = (
function) & 0xff;
2217 debug(
"\tindex=%08llx",
2219 debug(
", random=%08llx",
2221 debug(
", mask=%016llx",
2223 debug(
", hi=%016llx",
2225 debug(
", lo0=%016llx",
2227 debug(
", lo1=%016llx\n",
2246 int code = (
function >> 6) & 0x7ffff;
2249 debug(
"\t0x%x", code);
2260 debug(
"hibernate\n");
2271 if (unassemble_only) {
2272 debug(
"decstation_r2020_writeback\n");
2279 if (unassemble_only) {
2280 debug(
"cop%i\t0x%08x (unimplemented)\n", cpnr, (
int)
function);
2284 fatal(
"cpu%i: UNIMPLEMENTED coproc%i function %08" PRIx32
" "
2286 (uint32_t)
function,
cpu->
pc);