43 static const char *memop[4] = {
".d",
"",
".h",
".b" };
48 static const char *m88k_cr_name(
int i)
50 const char **cr_names = m88k_cr_names;
62 , m_m88k_type(
"88100")
67 memset((
void*) &m_type, 0,
sizeof(m_type));
68 for (
size_t j=0; cpu_type_defs[j].
name != NULL; j++) {
69 if (m_m88k_type == cpu_type_defs[j].name) {
70 m_type = cpu_type_defs[j];
75 if (m_type.name == NULL) {
76 std::cerr <<
"Internal error: Unimplemented M88K type?\n";
77 throw std::exception();
100 m_initial_r31 = 0x00000000;
124 if (!
cpu->SetVariableValue(
"model",
"\"" +
settings[
"model"] +
"\""))
127 if (!
cpu->SetVariableValue(
"initial_r31",
settings[
"r31"]))
129 if (!
cpu->SetVariableValue(
"r31",
settings[
"r31"]))
171 "must contain the value 0.\n");
175 if (
m_pc > (uint64_t)0xffffffff) {
177 "must be a 32-bit value.\n");
183 " its lower two bits clear!\n");
189 "register following r31 must mimic the r0 register.\nIf"
190 " you encounter this message, please write a bug report!\n");
205 "must contain the value 0.\n");
210 if (m_m88k_type != m_type.
name) {
212 for (
size_t j=0; cpu_type_defs[j].
name != NULL; j++) {
213 if (m_m88k_type == cpu_type_defs[j].name) {
214 m_type = cpu_type_defs[j];
223 ss <<
"Unknown model \"" + m_m88k_type +
"\". Available types are:\n";
224 for (
size_t j=0; cpu_type_defs[j].
name != NULL; j++) {
227 ss << cpu_type_defs[j].
name;
246 ss.flags(std::ios::hex);
248 if (arguments.size() == 0 ||
249 find(arguments.begin(), arguments.end(),
"r") != arguments.end()) {
250 ss <<
" pc = 0x" << std::setfill(
'0') << std::setw(8) <<
m_pc;
254 ss <<
" <" <<
symbol <<
">";
258 stringstream regname;
261 ss << std::setfill(
' ');
262 ss << std::setw(5) << regname.str() <<
" = 0x";
263 ss << std::setfill(
'0') << std::setw(8) << m_r[i];
273 if (find(arguments.begin(), arguments.end(),
"cr") != arguments.end()) {
275 stringstream regname;
276 regname <<
"cr" << i;
278 ss << std::setfill(
' ');
279 ss << std::setw(5) << regname.str() <<
" = 0x";
280 ss << std::setfill(
'0') << std::setw(8) << m_cr[i];
290 if (find(arguments.begin(), arguments.end(),
"crn") != arguments.end()) {
292 ss << std::setfill(
' ');
293 ss << std::setw(5) << m88k_cr_name(i) <<
" = 0x";
294 ss << std::setfill(
'0') << std::setw(8) << m_cr[i];
304 if (find(arguments.begin(), arguments.end(),
"fcr") != arguments.end()) {
306 stringstream regname;
307 regname <<
"fcr" << i;
309 ss << std::setfill(
' ');
310 ss << std::setw(5) << regname.str() <<
" = 0x";
311 ss << std::setfill(
'0') << std::setw(8) << m_fcr[i];
322 ss <<
"M88K usage: .registers [r] [cr] [crn] [fcr]\n"
323 "r = pc and general purpose registers (default)\n"
324 "cr = control registers\n"
325 "crn = control registers with symbolic names instead of crX\n"
326 "fcr = floating point control registers\n";
342 return instr_ToBeTranslated;
351 paddr = vaddr & 0xffffffff;
357 void M88K_CPUComponent::Exception(
int vector,
int is_trap)
359 std::cerr <<
"TODO: M88K exception\n";
360 throw std::exception();
365 unsigned char *instruction, vector<string>& result)
367 const size_t instrSize =
sizeof(uint32_t);
369 if (maxLen < instrSize) {
375 uint32_t instructionWord = *((uint32_t *)(
void*) instruction);
381 const uint32_t iw = instructionWord;
386 ss.flags(std::ios::hex);
387 ss << std::setfill(
'0') << std::setw(8) << (uint32_t) iw;
389 ss <<
" (delayslot)";
390 result.push_back(ss.str());
393 const uint32_t op26 = (iw >> 26) & 0x3f;
394 const uint32_t op11 = (iw >> 11) & 0x1f;
395 const uint32_t op10 = (iw >> 10) & 0x3f;
396 const uint32_t d = (iw >> 21) & 0x1f;
397 const uint32_t s1 = (iw >> 16) & 0x1f;
398 const uint32_t s2 = iw & 0x1f;
399 const uint32_t op3d = (iw >> 8) & 0xff;
400 const uint32_t imm16 = iw & 0xffff;
401 const uint32_t w5 = (iw >> 5) & 0x1f;
402 const uint32_t cr6 = (iw >> 5) & 0x3f;
403 const int32_t d16 = ((int16_t) (iw & 0xffff)) * 4;
404 const int32_t d26 = ((int32_t)((iw & 0x03ffffff) << 6)) >> 4;
436 if (iw == 0x00000000) {
437 result.push_back(
"-");
440 result.push_back(opcode_names[op26]);
443 ss <<
"r" << d <<
",r" << s1;
444 ss.flags(std::ios::hex | std::ios::showbase);
446 result.push_back(ss.str());
451 if ((iw & 0x001ff81f) == 0x00004000) {
452 result.push_back(
"ldcr");
454 ss <<
"r" << d <<
",cr" << cr6;
455 result.push_back(ss.str());
457 stringstream comment;
458 comment <<
"; cr" << cr6 <<
" = " << m88k_cr_name(cr6);
459 result.push_back(comment.str());
460 }
else if ((iw & 0x001ff81f) == 0x00004800) {
461 result.push_back(
"fldcr");
463 ss <<
"r" << d <<
",fcr" << cr6;
464 result.push_back(ss.str());
465 }
else if ((iw & 0x03e0f800) == 0x00008000) {
466 result.push_back(
"stcr");
468 ss <<
"r" << s1 <<
",cr" << cr6;
469 result.push_back(ss.str());
471 result.push_back(
"; Weird encoding: s1 != s2");
473 stringstream comment;
474 comment <<
"; cr" << cr6 <<
" = " << m88k_cr_name(cr6);
475 result.push_back(comment.str());
476 }
else if ((iw & 0x03e0f800) == 0x00008800) {
477 result.push_back(
"fstcr");
479 ss <<
"r" << s1 <<
",fcr" << cr6;
480 result.push_back(ss.str());
482 result.push_back(
"; Weird encoding: s1 != s2");
483 }
else if ((iw & 0x0000f800) == 0x0000c000) {
484 result.push_back(
"xcr");
486 ss <<
"r" << d <<
",r" << s1 <<
",cr" << cr6;
487 result.push_back(ss.str());
489 result.push_back(
"; Weird encoding: s1 != s2");
491 stringstream comment;
492 comment <<
"; cr" << cr6 <<
" = " << m88k_cr_name(cr6);
493 result.push_back(comment.str());
494 }
else if ((iw & 0x0000f800) == 0x0000c800) {
495 result.push_back(
"fxcr");
497 ss <<
"r" << d <<
",r" << s1 <<
",fcr" << cr6;
498 result.push_back(ss.str());
500 result.push_back(
"; Weird encoding: s1 != s2");
502 result.push_back(
"unimpl_0x20_variant");
516 case 0x00: ss <<
"fmul";
break;
517 case 0x05: ss <<
"fadd";
break;
518 case 0x06: ss <<
"fsub";
break;
519 case 0x07: ss <<
"fcmp";
break;
520 case 0x0e: ss <<
"fdiv";
break;
523 (((iw >> 5) & 1)?
"d" :
"s") <<
524 (((iw >> 9) & 1)?
"d" :
"s") <<
525 (((iw >> 7) & 1)?
"d" :
"s");
526 result.push_back(ss.str());
529 ss2 <<
"r" << d <<
",r" << s1 <<
",r" << s2;
530 result.push_back(ss2.str());
537 case 0x04: ss <<
"flt";
break;
539 ss <<
"." << (((iw >> 5) & 1)?
"d" :
"s") <<
"s";
540 result.push_back(ss.str());
543 ss2 <<
"r" << d <<
",r" << s2;
544 result.push_back(ss2.str());
553 case 0x09: ss <<
"int";
break;
554 case 0x0a: ss <<
"nint";
break;
555 case 0x0b: ss <<
"trnc";
break;
557 ss <<
".s" << (((iw >> 7) & 1)?
"d" :
"s");
558 result.push_back(ss.str());
561 ss2 <<
"r" << d <<
",r" << s2;
562 result.push_back(ss2.str());
567 ss <<
"unimpl_0x21, op11=" << op11;
568 result.push_back(ss.str());
578 result.push_back(opcode_names[op26]);
581 ss.flags(std::ios::hex | std::ios::showbase);
582 ss << ((uint32_t) (vaddr + d26));
583 result.push_back(ss.str());
586 (uint32_t) (vaddr + d26),
true);
588 result.push_back(
"; <" +
symbol +
">");
599 result.push_back(opcode_names[op26]);
602 if (op26 == 0x3a || op26 == 0x3b) {
605 case 0x1: ss <<
"gt0";
break;
606 case 0x2: ss <<
"eq0";
break;
607 case 0x3: ss <<
"ge0";
break;
608 case 0x7: ss <<
"not_maxneg";
break;
609 case 0x8: ss <<
"maxneg";
break;
610 case 0xc: ss <<
"lt0";
break;
611 case 0xd: ss <<
"ne0";
break;
612 case 0xe: ss <<
"le0";
break;
613 default: ss <<
"unk_" << d;
619 ss <<
",r" << s1 <<
",";
621 ss.flags(std::ios::hex | std::ios::showbase);
622 ss << ((uint32_t) (vaddr + d16));
623 result.push_back(ss.str());
626 (uint32_t) (vaddr + d16),
true);
628 result.push_back(
"; <" +
symbol +
">");
634 if ((iw & 0x0000f000)==0x1000 || (iw & 0x0000f000)==0x2000) {
637 ss << ((iw & 0x0000f000) == 0x1000?
"ld" :
"st");
639 switch (iw & 0x00000c00) {
640 case 0x000: ss <<
".d";
break;
642 case 0x800: ss <<
".x";
break;
643 default: ss <<
".UNIMPLEMENTED";
651 result.push_back(ss.str());
654 ss2 <<
"r" << d <<
",r" << s1;
656 ss2 <<
"[r" << s2 <<
"]";
660 result.push_back(ss2.str());
661 }
else switch (op10) {
670 result.push_back(opcode_names_3c[op10]);
673 ss <<
"r" << d <<
",r" << s1 <<
",";
680 ss <<
"<" << s2 <<
">";
682 result.push_back(ss.str());
689 result.push_back(opcode_names_3c[op10]);
692 ss << d <<
",r" << s1 <<
",";
693 ss.flags(std::ios::hex | std::ios::showbase);
695 result.push_back(ss.str());
700 ss <<
"unimpl_" << opcode_names_3c[op10];
701 result.push_back(ss.str());
707 if ((iw & 0xf000) <= 0x3fff) {
711 switch (iw & 0xf000) {
712 case 0x2000:
op <<
"st";
break;
713 case 0x3000:
op <<
"lda";
break;
714 default:
if ((iw & 0xf800) >= 0x0800)
720 if ((iw & 0xf000) >= 0x1000) {
722 op << memop[(iw >> 10) & 3];
723 }
else if ((iw & 0xf800) == 0x0000) {
729 if ((iw & 0xf00) < 0xc00)
740 result.push_back(
op.str());
743 ss <<
"r" << d <<
",r" << s1;
745 ss <<
"[r" << s2 <<
"]";
749 result.push_back(ss.str());
750 }
else switch (op3d) {
788 result.push_back(opcode_names_3d[op3d]);
791 ss <<
"r" << d <<
",r" << s1 <<
",r" << s2;
792 result.push_back(ss.str());
801 result.push_back(opcode_names_3d[op3d]);
804 ss <<
"(r" << s2 <<
")";
805 result.push_back(ss.str());
812 result.push_back(opcode_names_3d[op3d]);
815 ss <<
"r" << d <<
",r" << s2;
816 result.push_back(ss.str());
822 result.push_back(opcode_names_3d[op3d]);
825 ss <<
"r" << s1 <<
",r" << s2;
826 result.push_back(ss.str());
832 result.push_back(
"rte");
839 ss <<
"illop" << (iw & 0xff);
840 result.push_back(ss.str());
844 result.push_back(
"gxemul_prom_call");
847 result.push_back(
"gxemul_fail_early");
850 result.push_back(
"gxemul_fail_late");
854 ss <<
"unimpl_3d_0xfc_" << (iw & 0xff);
855 result.push_back(ss.str());
861 ss <<
"unimpl_" << opcode_names_3d[op3d];
862 result.push_back(ss.str());
869 result.push_back(opcode_names[op26]);
873 ss.flags(std::ios::hex | std::ios::showbase);
875 result.push_back(ss.str());
882 ss <<
"unimpl_" << opcode_names[op26];
883 result.push_back(ss.str());
894 if (attributeName ==
"stable")
897 if (attributeName ==
"description")
898 return "Motorola 88000 processor.";
907 void M88K_CPUComponent::stcr(
int cr, uint32_t value,
bool is_rte)
909 uint32_t old = m_cr[cr];
916 std::cerr <<
"TODO: attempt to change endianness by flipping"
917 " the endianness bit in the PSR. How should this"
918 " be handled? Aborting.\n";
919 std::cerr <<
"TODO: abort in a nicer way\n";
920 throw std::exception();
927 " cleared; this should be done using the RTE "
928 "instruction only, according to the M88100 "
929 "manual! Continuing anyway.\n");
934 std::cerr <<
"m88k stcr: TODO: MXM support\n";
935 std::cerr <<
"TODO: abort in a nicer way\n";
936 throw std::exception();
942 std::cerr <<
"m88k stcr: TODO: PSR mode switch.\n";
943 std::cerr <<
"TODO: abort in a nicer way\n";
944 throw std::exception();
964 ui->
ShowDebugMessage(
this,
"WARNING! bit 0 non-zero when writing to SSBR\n");
971 if (value & 0x00000fff) {
974 ui->
ShowDebugMessage(
this,
"WARNING! bits 0..11 non-zero when writing to VBR\n");
993 default:std::cerr <<
"m88k stcr: UNIMPLEMENTED cr = " << cr <<
"\n";
994 std::cerr <<
"TODO: abort in a nicer way\n";
995 throw std::exception();
1008 void M88K_CPUComponent::m88k_cmp(
struct DyntransIC *
ic, uint32_t y)
1010 uint32_t x =
REG32(
ic->arg[1]);
1021 if ((int32_t)x > (int32_t)y)
1041 cpu->m88k_cmp(
ic,
ic->arg[2].u32);
1055 void M88K_CPUComponent::m88k_extu(
struct DyntransIC *
ic,
int w,
int o)
1057 uint32_t x =
REG32(
ic->arg[1]) >> o;
1065 void M88K_CPUComponent::m88k_ext(
struct DyntransIC *
ic,
int w,
int o)
1067 int32_t x =
REG32(
ic->arg[1]);
1079 cpu->m88k_extu(
ic,
ic->arg[2].u32 >> 5,
ic->arg[2].u32 & 0x1f);
1089 cpu->m88k_ext(
ic,
ic->arg[2].u32 >> 5,
ic->arg[2].u32 & 0x1f);
1106 void M88K_CPUComponent::m88k_mak(
struct DyntransIC *
ic,
int w,
int o)
1108 uint32_t x =
REG32(
ic->arg[1]);
1128 cpu->m88k_mak(
ic,
ic->arg[2].u32 >> 5,
ic->arg[2].u32 & 0x1f);
1149 }
else if (
ic->arg[2].u32 == 0) {
1178 cpu->m_pc = (uint32_t) (
cpu->m_pc +
ic->arg[1].u32);
1179 cpu->DyntransPCtoPointers();
1200 cpu->m_pc = (uint32_t) (
cpu->m_pc +
ic->arg[1].u32);
1202 bool continueExecution =
cpu->FunctionTraceCall();
1203 cpu->DyntransPCtoPointers();
1205 if (!continueExecution)
1206 cpu->m_nextIC = &
cpu->m_abortIC;
1218 cpu->m_exceptionOrAbortInDelaySlot =
false;
1219 cpu->m_inDelaySlot =
true;
1220 cpu->m_delaySlotTarget = (uint32_t) (startOfPage +
ic->arg[1].u32);
1224 cpu->m_executedCycles ++;
1227 if (!
cpu->m_exceptionOrAbortInDelaySlot) {
1228 cpu->m_pc = (uint32_t) (startOfPage +
ic->arg[1].u32);
1229 cpu->DyntransPCtoPointers();
1231 cpu->m_inDelaySlot =
false;
1236 cpu->m_exceptionOrAbortInDelaySlot =
false;
1248 cpu->m_inDelaySlot =
true;
1249 cpu->m_exceptionOrAbortInDelaySlot =
false;
1253 cpu->m_executedCycles ++;
1256 if (!
cpu->m_exceptionOrAbortInDelaySlot) {
1257 cpu->m_pc = (uint32_t) (startOfPage +
ic->arg[1].u32);
1259 bool continueExecution =
cpu->FunctionTraceCall();
1260 cpu->DyntransPCtoPointers();
1262 cpu->m_inDelaySlot =
false;
1264 if (!continueExecution)
1265 cpu->m_nextIC = &
cpu->m_abortIC;
1270 cpu->m_exceptionOrAbortInDelaySlot =
false;
1281 cpu->m_inDelaySlot =
true;
1282 cpu->m_exceptionOrAbortInDelaySlot =
false;
1287 uint32_t old_pc =
cpu->m_pc;
1289 cpu->m_pc = (uint32_t) (
cpu->m_pc +
ic->arg[1].u32);
1291 if (
cpu->m_showFunctionTraceCall)
1292 cpu->FunctionTraceCall();
1294 cpu->m_delaySlotTarget =
cpu->m_pc;
1297 cpu->m_nextIC =
ic + 1;
1316 else if (
op == 7)
cond = ((uint32_t)
REG32(
ic->arg[0]) != 0x80000000UL);
1317 else if (
op == 8)
cond = ((uint32_t)
REG32(
ic->arg[0]) == 0x80000000UL);
1319 else if (
op == 13)
cond = ((int32_t)
REG32(
ic->arg[0]) != 0);
1327 cpu->m_inDelaySlot =
true;
1328 cpu->m_exceptionOrAbortInDelaySlot =
false;
1332 cpu->m_delaySlotTarget = (uint32_t) (
cpu->m_delaySlotTarget +
ic->arg[2].u32);
1334 cpu->m_delaySlotTarget =
cpu->m_pc + 8;
1337 cpu->m_nextIC =
ic + 1;
1340 cpu->m_inDelaySlot =
true;
1341 cpu->m_exceptionOrAbortInDelaySlot =
false;
1345 cpu->m_executedCycles ++;
1348 if (!
cpu->m_exceptionOrAbortInDelaySlot) {
1351 cpu->m_pc = (uint32_t) (
cpu->m_pc +
ic->arg[2].u32);
1352 cpu->DyntransPCtoPointers();
1354 cpu->m_nextIC =
ic + 2;
1357 cpu->m_inDelaySlot =
false;
1363 cpu->m_exceptionOrAbortInDelaySlot =
false;
1369 cpu->m_pc = (uint32_t) (
cpu->m_pc +
ic->arg[2].u32);
1370 cpu->DyntransPCtoPointers();
1390 bool bit =
REG32(
ic->arg[0]) &
ic->arg[1].u32;
1396 cpu->m_pc = (uint32_t) (
cpu->m_pc +
ic->arg[2].u32);
1397 cpu->DyntransPCtoPointers();
1407 bool bit =
REG32(
ic->arg[0]) &
ic->arg[1].u32;
1410 cpu->m_inDelaySlot =
true;
1411 cpu->m_exceptionOrAbortInDelaySlot =
false;
1415 cpu->m_executedCycles ++;
1418 if (!
cpu->m_exceptionOrAbortInDelaySlot) {
1421 cpu->m_pc = (uint32_t) (
cpu->m_pc +
ic->arg[2].u32);
1422 cpu->DyntransPCtoPointers();
1424 cpu->m_nextIC =
ic + 2;
1427 cpu->m_inDelaySlot =
false;
1433 cpu->m_exceptionOrAbortInDelaySlot =
false;
1441 bool bit =
REG32(
ic->arg[0]) &
ic->arg[1].u32;
1446 cpu->m_inDelaySlot =
true;
1447 cpu->m_exceptionOrAbortInDelaySlot =
false;
1451 cpu->m_delaySlotTarget = (uint32_t) (
cpu->m_delaySlotTarget +
ic->arg[2].u32);
1453 cpu->m_delaySlotTarget =
cpu->m_pc + 8;
1456 cpu->m_nextIC =
ic + 1;
1463 bool continueExecution =
true;
1466 continueExecution =
cpu->FunctionTraceReturn();
1469 cpu->DyntransPCtoPointers();
1471 if (!continueExecution)
1472 cpu->m_nextIC = &
cpu->m_abortIC;
1481 cpu->m_inDelaySlot =
true;
1482 cpu->m_exceptionOrAbortInDelaySlot =
false;
1483 uint32_t branchTarget =
REG32(
ic->arg[2]);
1487 cpu->m_executedCycles ++;
1490 if (!
cpu->m_exceptionOrAbortInDelaySlot) {
1491 cpu->m_pc = branchTarget;
1492 cpu->DyntransPCtoPointers();
1494 cpu->m_inDelaySlot =
false;
1500 cpu->m_exceptionOrAbortInDelaySlot =
false;
1509 cpu->m_inDelaySlot =
true;
1510 cpu->m_exceptionOrAbortInDelaySlot =
false;
1511 uint32_t branchTarget =
REG32(
ic->arg[2]);
1515 cpu->m_executedCycles ++;
1518 if (!
cpu->m_exceptionOrAbortInDelaySlot) {
1519 bool continueExecution =
true;
1521 continueExecution =
cpu->FunctionTraceReturn();
1523 cpu->m_pc = branchTarget;
1524 cpu->DyntransPCtoPointers();
1526 cpu->m_inDelaySlot =
false;
1528 if (!continueExecution)
1529 cpu->m_nextIC = &
cpu->m_abortIC;
1535 cpu->m_exceptionOrAbortInDelaySlot =
false;
1546 cpu->FunctionTraceReturn();
1549 cpu->m_inDelaySlot =
true;
1550 cpu->m_exceptionOrAbortInDelaySlot =
false;
1569 int cr =
ic->arg[1].u32;
1597 cpu->m_nextIC =
ic + 1;
1619 bool bit = (
REG32(
ic->arg[1]) &
ic->arg[0].u32) > 0;
1622 cpu->Exception(
ic->arg[2].u32, 1);
1647 template<
bool store,
typename T,
bool doubleword,
bool regofs,
bool scaled,
bool signedLoad>
void M88K_CPUComponent::instr_loadstore(
CPUDyntransComponent* cpubase,
DyntransIC*
ic)
1657 (scaled? (doubleword?
sizeof(uint64_t) :
sizeof(T)) : 1) *
1658 (regofs?
REG32(
ic->arg[2]) :
ic->arg[2].u32);
1660 if (
sizeof(T) > 1 && (
addr & (
sizeof(T)-1))) {
1680 if (
sizeof(T) ==
sizeof(uint16_t))
1682 if (
sizeof(T) ==
sizeof(uint8_t))
1692 uint32_t data2 = (* (((uint32_t*)(
ic->arg[0].p)) + 1) );
1693 cpu->AddressSelect(
addr +
sizeof(uint32_t));
1699 cpu->AddressSelect(
addr +
sizeof(uint32_t));
1704 (* (((uint32_t*)(
ic->arg[0].p)) + 1) ) = data2;
1727 cpu->m_executedCycles --;
1730 cpu->m_nextIC = &
cpu->m_abortIC;
1731 if (
cpu->m_inDelaySlot)
1732 cpu->m_exceptionOrAbortInDelaySlot =
true;
1744 cpu->m_pc +=
sizeof(uint32_t);
1747 cpu->m_nextIC = &
cpu->m_abortIC;
1748 if (
cpu->m_inDelaySlot)
1749 cpu->m_exceptionOrAbortInDelaySlot =
true;
1756 void M88K_CPUComponent::Translate(uint32_t iw,
struct DyntransIC*
ic)
1761 uint32_t op26 = (iw >> 26) & 0x3f;
1763 uint32_t op10 = (iw >> 10) & 0x3f;
1764 uint32_t d = (iw >> 21) & 0x1f;
1765 uint32_t s1 = (iw >> 16) & 0x1f;
1766 uint32_t s2 = iw & 0x1f;
1768 uint32_t imm16 = iw & 0xffff;
1770 uint32_t cr6 = (iw >> 5) & 0x3f;
1771 int32_t d16 = ((int16_t) (iw & 0xffff)) * 4;
1772 int32_t d26 = ((int32_t)((iw & 0x03ffffff) << 6)) >> 4;
1787 bool store = op26 >= 0x08;
1790 ic->arg[0].p = &m_r[d];
1791 ic->arg[1].p = &m_r[s1];
1792 ic->arg[2].u32 = imm16;
1795 case 0x02:
ic->f = instr_loadstore<false, uint16_t, false, false, false, false>; opsize = 1;
break;
1796 case 0x03:
ic->f = instr_loadstore<false, uint8_t, false, false, false, false>; opsize = 0;
break;
1797 case 0x04:
ic->f = instr_loadstore<false, uint32_t, true, false, false, false>; opsize = 3;
break;
1798 case 0x05:
ic->f = instr_loadstore<false, uint32_t, false, false, false, false>; opsize = 2;
break;
1799 case 0x06:
ic->f = instr_loadstore<false, uint16_t, false, false, false, true>; opsize = 1;
break;
1800 case 0x07:
ic->f = instr_loadstore<false, uint8_t, false, false, false, true>; opsize = 0;
break;
1801 case 0x08:
ic->f = instr_loadstore<true, uint32_t, true, false, false, false>; opsize = 3;
break;
1802 case 0x09:
ic->f = instr_loadstore<true, uint32_t, false, false, false, false>; opsize = 2;
break;
1803 case 0x0a:
ic->f = instr_loadstore<true, uint16_t, false, false, false, false>; opsize = 1;
break;
1804 case 0x0b:
ic->f = instr_loadstore<true, uint8_t, false, false, false, false>; opsize = 0;
break;
1807 if (opsize == 3 && d == 31) {
1818 ic->arg[0].p = &m_zero_scratch;
1838 case 0x10:
ic->f = instr_and_u32_u32_immu32;
break;
1839 case 0x11:
ic->f = instr_and_u32_u32_immu32; shift = 16;
break;
1840 case 0x12:
ic->f = instr_and_u32_u32_immu32;
break;
1841 case 0x13:
ic->f = instr_and_u32_u32_immu32; shift = 16;
break;
1842 case 0x14:
ic->f = instr_xor_u32_u32_immu32;
break;
1843 case 0x15:
ic->f = instr_xor_u32_u32_immu32; shift = 16;
break;
1844 case 0x16:
ic->f = instr_or_u32_u32_immu32;
break;
1845 case 0x17:
ic->f = instr_or_u32_u32_immu32; shift = 16;
break;
1846 case 0x18:
ic->f = instr_add_u32_u32_immu32;
break;
1847 case 0x19:
ic->f = instr_sub_u32_u32_immu32;
break;
1848 case 0x1a:
ic->f = instr_divu_imm;
break;
1849 case 0x1b:
ic->f = instr_mulu_imm;
break;
1853 case 0x1f:
ic->f = instr_cmp_imm;
break;
1856 ic->arg[0].p = &m_r[d];
1857 ic->arg[1].p = &m_r[s1];
1858 ic->arg[2].u32 = imm16 << shift;
1864 ic->arg[2].u32 |= 0xffff0000;
1866 ic->arg[2].u32 |= 0x0000ffff;
1874 if ((iw & 0x001ff81f) == 0x00004000) {
1876 ic->arg[0].p = &m_r[d];
1877 ic->arg[1].u32 = cr6;
1879 ic->arg[0].p = &m_zero_scratch;
1887 }
else if ((iw & 0x03e0f800) == 0x00008000) {
1889 ic->arg[0].p = &m_r[s1];
1890 ic->arg[1].u32 = cr6;
1895 ss.flags(std::ios::hex);
1896 ss <<
"stcr with s1 != s2? TODO: how "
1897 "should this be handled? s1=0x"
1898 << s1 <<
", s2=0x" << s2;
1915 }
else if (ui != NULL) {
1932 samepage_function = instr_branch_samepage;
1941 samepage_function = instr_bsr_samepage;
1944 ic->f = instr_bsr_n;
1946 f_singleStepping = instr_bsr_n_functioncalltrace_singlestep;
1950 if (singleInstructionLeft && (op26 == 0x31 || op26 == 0x33)) {
1951 ic->f = f_singleStepping;
1952 samepage_function = NULL;
1955 int offset = (
m_pc & 0xffc) + d26;
1960 ic->arg[1].u32 = offset;
1963 ic->arg[2].u32 = (
m_pc & 0xffc) + ((op26 & 1)? 8 : 4);
1965 if (offset >= 0 && offset <= 0xffc && samepage_function != NULL)
1966 ic->f = samepage_function;
1970 ic->f = instr_bsr_functioncalltrace;
1972 if (singleInstructionLeft)
1973 ic->f = instr_bsr_n_functioncalltrace_singlestep;
1975 ic->f = instr_bsr_n_functioncalltrace;
1991 ic->f = instr_bb<false,false>;
1992 samepage_function = instr_bb<false,true>;
1995 ic->f = instr_bb_n<false>;
1996 singlestep_function = instr_bb_n_singlestep<false>;
1999 ic->f = instr_bb<true,false>;
2000 samepage_function = instr_bb<true,true>;
2003 ic->f = instr_bb_n<true>;
2004 singlestep_function = instr_bb_n_singlestep<true>;
2008 ic->arg[0].p = &m_r[s1];
2009 ic->arg[1].u32 = (1 << d);
2011 int offset = (
m_pc & 0xffc) + d16;
2012 ic->arg[2].u32 = offset;
2014 if (singleInstructionLeft && singlestep_function != NULL)
2015 ic->f = singlestep_function;
2016 else if (offset >= 0 && offset <= 0xffc && samepage_function != NULL) {
2017 ic->f = samepage_function;
2031 case 1:
ic->f = instr_bcnd<true,1, false>; singlestep_f = instr_bcnd<true,1, true>;
break;
2032 case 2:
ic->f = instr_bcnd<true,2, false>; singlestep_f = instr_bcnd<true,2, true>;
break;
2033 case 3:
ic->f = instr_bcnd<true,3, false>; singlestep_f = instr_bcnd<true,3, true>;
break;
2034 case 7:
ic->f = instr_bcnd<true,7, false>; singlestep_f = instr_bcnd<true,7, true>;
break;
2035 case 8:
ic->f = instr_bcnd<true,8, false>; singlestep_f = instr_bcnd<true,8, true>;
break;
2036 case 12:
ic->f = instr_bcnd<true,12,false>; singlestep_f = instr_bcnd<true,12,true>;
break;
2037 case 13:
ic->f = instr_bcnd<true,13,false>; singlestep_f = instr_bcnd<true,13,true>;
break;
2038 case 14:
ic->f = instr_bcnd<true,14,false>; singlestep_f = instr_bcnd<true,14,true>;
break;
2042 case 1:
ic->f = instr_bcnd<false,1, false>;
break;
2043 case 2:
ic->f = instr_bcnd<false,2, false>;
break;
2044 case 3:
ic->f = instr_bcnd<false,3, false>;
break;
2045 case 7:
ic->f = instr_bcnd<false,7, false>;
break;
2046 case 8:
ic->f = instr_bcnd<false,8, false>;
break;
2047 case 12:
ic->f = instr_bcnd<false,12,false>;
break;
2048 case 13:
ic->f = instr_bcnd<false,13,false>;
break;
2049 case 14:
ic->f = instr_bcnd<false,14,false>;
break;
2057 if (
ic->f == NULL) {
2060 ss.flags(std::ios::hex);
2061 ss <<
"unimplemented bcnd condition code d = " << d;
2068 ic->arg[0].p = &m_r[s1];
2070 int offset = (
m_pc & 0xffc) + d16;
2071 ic->arg[2].u32 = offset;
2073 if (singleInstructionLeft && singlestep_f != NULL) {
2074 ic->f = singlestep_f;
2075 }
else if (offset >= 0 && offset <= 0xffc && samepage_function != NULL) {
2076 ic->f = samepage_function;
2090 ic->arg[0].p = &m_r[d];
2091 ic->arg[1].p = &m_r[s1];
2092 ic->arg[2].u32 = iw & 0x3ff;
2115 case 0x24:
ic->f = instr_ext_imm;
break;
2116 case 0x26:
ic->f = instr_extu_imm;
break;
2117 case 0x28:
ic->f = instr_mak_imm;
break;
2126 ic->arg[0].u32 = 1 << d;
2127 ic->arg[1].p = &m_r[s1];
2128 ic->arg[2].u32 = iw & 0x1ff;
2130 case 0x34:
ic->f = instr_tb<false>;
break;
2131 case 0x36:
ic->f = instr_tb<true>;
break;
2138 ss.flags(std::ios::hex);
2139 ss <<
"unimplemented opcode 0x" << op26 <<
",0x" << op10;
2146 if ((iw & 0xf000) <= 0x3fff ) {
2148 int op = 0, opsize, user = 0, wt = 0;
2149 int signedness = 1, scaled = 0;
2151 switch (iw & 0xf000) {
2152 case 0x2000:
op = 1;
break;
2153 case 0x3000:
op = 2;
break;
2154 default:
if ((iw & 0xf800) >= 0x0800)
2161 opsize = (iw >> 10) & 3;
2164 opsize = 3 - opsize;
2169 switch ((iw >> 10) & 3) {
2170 case 0: opsize = 0;
break;
2171 case 1: opsize = 2;
break;
2178 if ((iw & 0xf800) == 0x800) {
2180 if ((iw & 0xf00) < 0xc00)
2185 if (opsize >= 2 ||
op == 1)
2203 ic->arg[0].p = &m_r[d];
2204 ic->arg[1].p = &m_r[s1];
2205 ic->arg[2].p = &m_r[s2];
2207 if (
op == 0 ||
op == 1) {
2211 ((
op == 1)? 4 : 0) +
2212 (signedness? 8 : 0) +
2221 case 0 + 0 + 0 + 0 + 0 + 0:
ic->f = instr_loadstore<false, uint8_t, false, true, false, false>;
break;
2222 case 0 + 0 + 0 + 0 + 32 + 0:
ic->f = instr_loadstore<false, uint8_t, false, true, true, false>;
break;
2223 case 0 + 0 + 0 + 16 + 0 + 0:
ic->f = instr_loadstore<false, uint8_t, false, true, false, false>;
break;
2224 case 0 + 0 + 0 + 16 + 32 + 0:
ic->f = instr_loadstore<false, uint8_t, false, true, true, false>;
break;
2225 case 1 + 0 + 0 + 0 + 0 + 0:
ic->f = instr_loadstore<false, uint16_t, false, true, false, false>;
break;
2226 case 1 + 0 + 0 + 0 + 32 + 0:
ic->f = instr_loadstore<false, uint16_t, false, true, true, false>;
break;
2227 case 1 + 0 + 0 + 16 + 0 + 0:
ic->f = instr_loadstore<false, uint16_t, false, true, false, false>;
break;
2228 case 1 + 0 + 0 + 16 + 32 + 0:
ic->f = instr_loadstore<false, uint16_t, false, true, true, false>;
break;
2229 case 2 + 0 + 0 + 0 + 0 + 0:
ic->f = instr_loadstore<false, uint32_t, false, true, false, false>;
break;
2230 case 2 + 0 + 0 + 0 + 32 + 0:
ic->f = instr_loadstore<false, uint32_t, false, true, true, false>;
break;
2231 case 2 + 0 + 0 + 16 + 0 + 0:
ic->f = instr_loadstore<false, uint32_t, false, true, false, false>;
break;
2232 case 2 + 0 + 0 + 16 + 32 + 0:
ic->f = instr_loadstore<false, uint32_t, false, true, true, false>;
break;
2233 case 3 + 0 + 0 + 0 + 0 + 0:
ic->f = instr_loadstore<false, uint32_t, true, true, false, false>;
break;
2234 case 3 + 0 + 0 + 0 + 32 + 0:
ic->f = instr_loadstore<false, uint32_t, true, true, true, false>;
break;
2235 case 3 + 0 + 0 + 16 + 0 + 0:
ic->f = instr_loadstore<false, uint32_t, true, true, false, false>;
break;
2236 case 3 + 0 + 0 + 16 + 32 + 0:
ic->f = instr_loadstore<false, uint32_t, true, true, true, false>;
break;
2238 case 0 + 4 + 0 + 0 + 0 + 0:
ic->f = instr_loadstore<true, uint8_t, false, true, false, false>;
break;
2239 case 0 + 4 + 0 + 0 + 32 + 0:
ic->f = instr_loadstore<true, uint8_t, false, true, true, false>;
break;
2240 case 0 + 4 + 0 + 16 + 0 + 0:
ic->f = instr_loadstore<true, uint8_t, false, true, false, false>;
break;
2241 case 0 + 4 + 0 + 16 + 32 + 0:
ic->f = instr_loadstore<true, uint8_t, false, true, true, false>;
break;
2242 case 1 + 4 + 0 + 0 + 0 + 0:
ic->f = instr_loadstore<true, uint16_t, false, true, false, false>;
break;
2243 case 1 + 4 + 0 + 0 + 32 + 0:
ic->f = instr_loadstore<true, uint16_t, false, true, true, false>;
break;
2244 case 1 + 4 + 0 + 16 + 0 + 0:
ic->f = instr_loadstore<true, uint16_t, false, true, false, false>;
break;
2245 case 1 + 4 + 0 + 16 + 32 + 0:
ic->f = instr_loadstore<true, uint16_t, false, true, true, false>;
break;
2246 case 2 + 4 + 0 + 0 + 0 + 0:
ic->f = instr_loadstore<true, uint32_t, false, true, false, false>;
break;
2247 case 2 + 4 + 0 + 0 + 32 + 0:
ic->f = instr_loadstore<true, uint32_t, false, true, true, false>;
break;
2248 case 2 + 4 + 0 + 16 + 0 + 0:
ic->f = instr_loadstore<true, uint32_t, false, true, false, false>;
break;
2249 case 2 + 4 + 0 + 16 + 32 + 0:
ic->f = instr_loadstore<true, uint32_t, false, true, true, false>;
break;
2250 case 3 + 4 + 0 + 0 + 0 + 0:
ic->f = instr_loadstore<true, uint32_t, true, true, false, false>;
break;
2251 case 3 + 4 + 0 + 0 + 32 + 0:
ic->f = instr_loadstore<true, uint32_t, true, true, true, false>;
break;
2252 case 3 + 4 + 0 + 16 + 0 + 0:
ic->f = instr_loadstore<true, uint32_t, true, true, false, false>;
break;
2253 case 3 + 4 + 0 + 16 + 32 + 0:
ic->f = instr_loadstore<true, uint32_t, true, true, true, false>;
break;
2255 std::cerr <<
"TODO generalize! scaled="<<scaled <<
" user="<<
2256 user<<
" signedness="<<signedness <<
" opsize=" << opsize <<
"\n";
2264 ic->arg[0].p = &m_zero_scratch;
2266 if (opsize == 3 && d == 31) {
2272 }
else if (
op == 2) {
2277 case 1:
ic->f = instr_lda<2>;
break;
2278 case 2:
ic->f = instr_lda<4>;
break;
2279 case 3:
ic->f = instr_lda<8>;
break;
2297 }
else switch ((iw >> 8) & 0xff) {
2321 ic->arg[0].p = &m_r[d];
2322 ic->arg[1].p = &m_r[s1];
2323 ic->arg[2].p = &m_r[s2];
2325 switch ((iw >> 8) & 0xff) {
2328 case 0x50:
ic->f = instr_xor_u32_u32_u32;
break;
2330 case 0x58:
ic->f = instr_or_u32_u32_u32;
break;
2332 case 0x60:
ic->f = instr_add_u32_u32_u32;
break;
2335 case 0x64:
ic->f = instr_sub_u32_u32_u32;
break;
2342 case 0x7c:
ic->f = instr_cmp;
break;
2345 case 0x90:
ic->f = instr_ext;
break;
2346 case 0x98:
ic->f = instr_extu;
break;
2347 case 0xa0:
ic->f = instr_mak;
break;
2361 int opc = (iw >> 8) & 0xff;
2362 if (opc != 0x61 && opc != 0x63 &&
2363 opc != 0x65 && opc != 0x67 &&
2364 opc != 0x71 && opc != 0x73 &&
2365 opc != 0x75 && opc != 0x77 &&
2366 opc != 0x68 && opc != 0x69 &&
2367 opc != 0x6c && opc != 0x6d &&
2368 opc != 0x6e && opc != 0x78 )
2371 ic->arg[0].p = &m_zero_scratch;
2374 if (
ic->f == NULL && ui != NULL) {
2376 ss.flags(std::ios::hex);
2377 ss <<
"unimplemented opcode 0x3d,0x" << ((iw >> 8) & 0xff);
2389 switch ((iw >> 8) & 0xff) {
2390 case 0xc0:
ic->f = instr_jmp;
break;
2391 case 0xc4:
ic->f = instr_jmp_n; f_ss = instr_jmp_n_functioncalltrace_singlestep;
break;
2396 ic->arg[1].u32 = (
m_pc & 0xffc) + 4;
2397 ic->arg[2].p = &m_r[s2];
2399 if (((iw >> 8) & 0x04) == 0x04)
2400 ic->arg[1].u32 = (
m_pc & 0xffc) + 8;
2403 if (
ic->f == instr_jmp_n) {
2404 ic->f = instr_jmp_n_functioncalltrace;
2405 f_ss = instr_jmp_n_functioncalltrace_singlestep;
2418 if (singleInstructionLeft && f_ss != NULL)
2426 switch (iw & 0xff) {
2433 ic->f = instr_fail_early;
2437 default:
if (ui != NULL) {
2439 ss.flags(std::ios::hex);
2440 ss <<
"unimplemented opcode 0x3d,0xfc,0x" << (iw & 0xff);
2448 ss.flags(std::ios::hex);
2449 ss <<
"unimplemented opcode 0x3d,0x" << ((iw >> 8) & 0xff);
2458 ss.flags(std::ios::hex);
2459 ss <<
"unimplemented opcode 0x" << op26;
2470 cpu->DyntransToBeTranslatedBegin(
ic);
2473 if (
cpu->DyntransReadInstruction(iword))
2474 cpu->Translate(iword,
ic);
2476 if (
cpu->m_inDelaySlot &&
ic->f == NULL)
2477 ic->f = instr_abort;
2479 cpu->DyntransToBeTranslatedDone(
ic);
2486 #ifdef WITHUNITTESTS
2490 static void Test_M88K_CPUComponent_IsStable()
2496 static void Test_M88K_CPUComponent_Create()
2511 static void Test_M88K_CPUComponent_Create_with_r31()
2525 cpu->SetVariableValue(
"r31",
"0xf00");
2536 static void Test_M88K_CPUComponent_IsCPU()
2545 static void Test_M88K_CPUComponent_DefaultModel()
2554 cpu->GetVariable(
"model")->ToString(),
"88100");
2557 static void Test_M88K_CPUComponent_Disassembly_Basic()
2563 vector<string> result;
2565 unsigned char instruction[
sizeof(uint32_t)];
2567 instruction[0] = 0x63;
2568 instruction[1] = 0xdf;
2569 instruction[2] = 0x00;
2570 instruction[3] = 0x10;
2572 len =
cpu->DisassembleInstruction(0x12345678,
sizeof(uint32_t),
2573 instruction, result);
2582 static void Test_M88K_CPUComponent_Execute_Basic()
2595 uint32_t data32 = 0x63df0010;
2602 cpu->SetVariableValue(
"pc",
"48");
2603 cpu->SetVariableValue(
"r30",
"1234");
2604 cpu->SetVariableValue(
"r31",
"5678");
2610 UnitTest::Assert(
"r30 should have been modified",
cpu->GetVariable(
"r30")->ToInteger(), 5678 + 0x10);
2611 UnitTest::Assert(
"r31 should not have been modified",
cpu->GetVariable(
"r31")->ToInteger(), 5678);
2613 cpu->SetVariableValue(
"r31",
"1111");
2618 UnitTest::Assert(
"pc should have increased again",
cpu->GetVariable(
"pc")->ToInteger(), 56);
2619 UnitTest::Assert(
"r30 should have been modified again",
cpu->GetVariable(
"r30")->ToInteger(), 1111 + 0x10);
2622 static void Test_M88K_CPUComponent_Execute_DelayBranchWithValidInstruction()
2633 uint32_t data32 = 0xcc000010;
2637 data32 = 0x63df0010;
2641 cpu->SetVariableValue(
"pc",
"0x1000");
2652 UnitTest::Assert(
"delay slot after execute",
cpu->GetVariable(
"inDelaySlot")->ToString(),
"false");
2657 static void Test_M88K_CPUComponent_Execute_DelayBranchWithValidInstruction_SingleStepping()
2668 uint32_t data32 = 0xcc000010;
2672 data32 = 0x63df0010;
2676 cpu->SetVariableValue(
"pc",
"0x1000");
2687 UnitTest::Assert(
"pc should have changed 1",
cpu->GetVariable(
"pc")->ToInteger(), 0x1004);
2688 UnitTest::Assert(
"delay slot after execute 1",
cpu->GetVariable(
"inDelaySlot")->ToString(),
"true");
2695 UnitTest::Assert(
"delay slot after execute 2",
cpu->GetVariable(
"inDelaySlot")->ToString(),
"false");
2696 UnitTest::Assert(
"pc should have changed 2",
cpu->GetVariable(
"pc")->ToInteger(), 0x1040);
2701 static void Test_M88K_CPUComponent_Execute_DelayBranchWithValidInstruction_RunTwoTimes()
2712 uint32_t data32 = 0xcc000010;
2716 data32 = 0x63df0010;
2720 cpu->SetVariableValue(
"pc",
"0x1000");
2731 UnitTest::Assert(
"pc should have changed 1",
cpu->GetVariable(
"pc")->ToInteger(), 0x1004);
2732 UnitTest::Assert(
"delay slot after execute 1",
cpu->GetVariable(
"inDelaySlot")->ToString(),
"true");
2739 UnitTest::Assert(
"delay slot after execute 2",
cpu->GetVariable(
"inDelaySlot")->ToString(),
"false");
2740 UnitTest::Assert(
"pc should have changed 2",
cpu->GetVariable(
"pc")->ToInteger(), 0x1040);
2745 static void Test_M88K_CPUComponent_Execute_DelayBranchWithFault()
2756 uint32_t data32 = 0xcc000010;
2760 data32 = 0xffffffff;
2764 cpu->SetVariableValue(
"pc",
"0x1000");
2774 UnitTest::Assert(
"pc should have increased one step",
cpu->GetVariable(
"pc")->ToInteger(), 0x1004ULL);
2775 UnitTest::Assert(
"should be in delay slot after execution",
cpu->GetVariable(
"inDelaySlot")->ToString(),
"true");
2780 UnitTest::Assert(
"pc should not have increased",
cpu->GetVariable(
"pc")->ToInteger(), 0x1004ULL);
2781 UnitTest::Assert(
"should still be in delay slot",
cpu->GetVariable(
"inDelaySlot")->ToString(),
"true");
2784 static void Test_M88K_CPUComponent_Execute_EarlyAbortDuringRuntime_Singlestep()
2795 uint32_t data32 = 0xcc000010;
2799 data32 = 0xf400fc93;
2804 cpu->SetVariableValue(
"pc",
"0x1000");
2812 UnitTest::Assert(
"1 step should have executed",
cpu->GetVariable(
"step")->ToInteger(), 1);
2813 UnitTest::Assert(
"pc should have increased one step",
cpu->GetVariable(
"pc")->ToInteger(), 0x1004ULL);
2814 UnitTest::Assert(
"should be in delay slot after execution",
cpu->GetVariable(
"inDelaySlot")->ToString(),
"true");
2815 UnitTest::Assert(
"delay target should have been updated",
cpu->GetVariable(
"delaySlotTarget")->ToInteger(), 0x1040);
2820 UnitTest::Assert(
"no more steps should have executed",
cpu->GetVariable(
"step")->ToInteger(), 1);
2821 UnitTest::Assert(
"pc should not have increased",
cpu->GetVariable(
"pc")->ToInteger(), 0x1004ULL);
2822 UnitTest::Assert(
"should still be in delay slot",
cpu->GetVariable(
"inDelaySlot")->ToString(),
"true");
2823 UnitTest::Assert(
"delay target should not have been updated",
cpu->GetVariable(
"delaySlotTarget")->ToInteger(), 0x1040);
2826 static void Test_M88K_CPUComponent_Execute_EarlyAbortDuringRuntime_Running()
2837 uint32_t data32 = 0xcc000010;
2841 data32 = 0xf400fc93;
2846 cpu->SetVariableValue(
"pc",
"0x1000");
2854 UnitTest::Assert(
"1 step should have executed",
cpu->GetVariable(
"step")->ToInteger(), 1);
2855 UnitTest::Assert(
"pc should have increased one step",
cpu->GetVariable(
"pc")->ToInteger(), 0x1004ULL);
2856 UnitTest::Assert(
"should be in delay slot after execution",
cpu->GetVariable(
"inDelaySlot")->ToString(),
"true");
2857 UnitTest::Assert(
"delay target should have been updated",
cpu->GetVariable(
"delaySlotTarget")->ToInteger(), 0x1040);
2862 UnitTest::Assert(
"no more steps should have executed",
cpu->GetVariable(
"step")->ToInteger(), 1);
2863 UnitTest::Assert(
"pc should not have increased",
cpu->GetVariable(
"pc")->ToInteger(), 0x1004ULL);
2864 UnitTest::Assert(
"should still be in delay slot",
cpu->GetVariable(
"inDelaySlot")->ToString(),
"true");
2865 UnitTest::Assert(
"delay target should not have been updated",
cpu->GetVariable(
"delaySlotTarget")->ToInteger(), 0x1040);
2870 UNITTEST(Test_M88K_CPUComponent_IsStable);
2871 UNITTEST(Test_M88K_CPUComponent_Create);
2872 UNITTEST(Test_M88K_CPUComponent_Create_with_r31);
2873 UNITTEST(Test_M88K_CPUComponent_IsCPU);
2874 UNITTEST(Test_M88K_CPUComponent_DefaultModel);
2877 UNITTEST(Test_M88K_CPUComponent_Disassembly_Basic);
2880 UNITTEST(Test_M88K_CPUComponent_Execute_Basic);
2881 UNITTEST(Test_M88K_CPUComponent_Execute_DelayBranchWithValidInstruction);
2882 UNITTEST(Test_M88K_CPUComponent_Execute_DelayBranchWithValidInstruction_SingleStepping);
2883 UNITTEST(Test_M88K_CPUComponent_Execute_DelayBranchWithValidInstruction_RunTwoTimes);
2884 UNITTEST(Test_M88K_CPUComponent_Execute_DelayBranchWithFault);
2885 UNITTEST(Test_M88K_CPUComponent_Execute_EarlyAbortDuringRuntime_Singlestep);
2886 UNITTEST(Test_M88K_CPUComponent_Execute_EarlyAbortDuringRuntime_Running);