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();
366 size_t instrSize =
sizeof(uint32_t);
367 uint32_t instructionWord;
375 const uint32_t iw = instructionWord;
380 ss.flags(std::ios::hex);
381 ss << std::setfill(
'0') << std::setw(8) << (uint32_t) iw;
383 ss <<
" (delayslot)";
384 result.push_back(ss.str());
387 const uint32_t op26 = (iw >> 26) & 0x3f;
388 const uint32_t op11 = (iw >> 11) & 0x1f;
389 const uint32_t op10 = (iw >> 10) & 0x3f;
390 const uint32_t d = (iw >> 21) & 0x1f;
391 const uint32_t s1 = (iw >> 16) & 0x1f;
392 const uint32_t s2 = iw & 0x1f;
393 const uint32_t op3d = (iw >> 8) & 0xff;
394 const uint32_t imm16 = iw & 0xffff;
395 const uint32_t w5 = (iw >> 5) & 0x1f;
396 const uint32_t cr6 = (iw >> 5) & 0x3f;
397 const int32_t d16 = ((int16_t) (iw & 0xffff)) * 4;
398 const int32_t d26 = ((int32_t)((iw & 0x03ffffff) << 6)) >> 4;
430 if (iw == 0x00000000) {
431 result.push_back(
"-");
434 result.push_back(opcode_names[op26]);
437 ss <<
"r" << d <<
",r" << s1;
438 ss.flags(std::ios::hex | std::ios::showbase);
440 result.push_back(ss.str());
445 if ((iw & 0x001ff81f) == 0x00004000) {
446 result.push_back(
"ldcr");
448 ss <<
"r" << d <<
",cr" << cr6;
449 result.push_back(ss.str());
451 stringstream comment;
452 comment <<
"; cr" << cr6 <<
" = " << m88k_cr_name(cr6);
453 result.push_back(comment.str());
454 }
else if ((iw & 0x001ff81f) == 0x00004800) {
455 result.push_back(
"fldcr");
457 ss <<
"r" << d <<
",fcr" << cr6;
458 result.push_back(ss.str());
459 }
else if ((iw & 0x03e0f800) == 0x00008000) {
460 result.push_back(
"stcr");
462 ss <<
"r" << s1 <<
",cr" << cr6;
463 result.push_back(ss.str());
465 result.push_back(
"; Weird encoding: s1 != s2");
467 stringstream comment;
468 comment <<
"; cr" << cr6 <<
" = " << m88k_cr_name(cr6);
469 result.push_back(comment.str());
470 }
else if ((iw & 0x03e0f800) == 0x00008800) {
471 result.push_back(
"fstcr");
473 ss <<
"r" << s1 <<
",fcr" << cr6;
474 result.push_back(ss.str());
476 result.push_back(
"; Weird encoding: s1 != s2");
477 }
else if ((iw & 0x0000f800) == 0x0000c000) {
478 result.push_back(
"xcr");
480 ss <<
"r" << d <<
",r" << s1 <<
",cr" << cr6;
481 result.push_back(ss.str());
483 result.push_back(
"; Weird encoding: s1 != s2");
485 stringstream comment;
486 comment <<
"; cr" << cr6 <<
" = " << m88k_cr_name(cr6);
487 result.push_back(comment.str());
488 }
else if ((iw & 0x0000f800) == 0x0000c800) {
489 result.push_back(
"fxcr");
491 ss <<
"r" << d <<
",r" << s1 <<
",fcr" << cr6;
492 result.push_back(ss.str());
494 result.push_back(
"; Weird encoding: s1 != s2");
496 result.push_back(
"unimpl_0x20_variant");
510 case 0x00: ss <<
"fmul";
break;
511 case 0x05: ss <<
"fadd";
break;
512 case 0x06: ss <<
"fsub";
break;
513 case 0x07: ss <<
"fcmp";
break;
514 case 0x0e: ss <<
"fdiv";
break;
517 (((iw >> 5) & 1)?
"d" :
"s") <<
518 (((iw >> 9) & 1)?
"d" :
"s") <<
519 (((iw >> 7) & 1)?
"d" :
"s");
520 result.push_back(ss.str());
523 ss2 <<
"r" << d <<
",r" << s1 <<
",r" << s2;
524 result.push_back(ss2.str());
531 case 0x04: ss <<
"flt";
break;
533 ss <<
"." << (((iw >> 5) & 1)?
"d" :
"s") <<
"s";
534 result.push_back(ss.str());
537 ss2 <<
"r" << d <<
",r" << s2;
538 result.push_back(ss2.str());
547 case 0x09: ss <<
"int";
break;
548 case 0x0a: ss <<
"nint";
break;
549 case 0x0b: ss <<
"trnc";
break;
551 ss <<
".s" << (((iw >> 7) & 1)?
"d" :
"s");
552 result.push_back(ss.str());
555 ss2 <<
"r" << d <<
",r" << s2;
556 result.push_back(ss2.str());
561 ss <<
"unimpl_0x21, op11=" << op11;
562 result.push_back(ss.str());
572 result.push_back(opcode_names[op26]);
575 ss.flags(std::ios::hex | std::ios::showbase);
576 ss << ((uint32_t) (vaddr + d26));
577 result.push_back(ss.str());
580 (uint32_t) (vaddr + d26),
true);
582 result.push_back(
"; <" +
symbol +
">");
593 result.push_back(opcode_names[op26]);
596 if (op26 == 0x3a || op26 == 0x3b) {
599 case 0x1: ss <<
"gt0";
break;
600 case 0x2: ss <<
"eq0";
break;
601 case 0x3: ss <<
"ge0";
break;
602 case 0x7: ss <<
"not_maxneg";
break;
603 case 0x8: ss <<
"maxneg";
break;
604 case 0xc: ss <<
"lt0";
break;
605 case 0xd: ss <<
"ne0";
break;
606 case 0xe: ss <<
"le0";
break;
607 default: ss <<
"unk_" << d;
613 ss <<
",r" << s1 <<
",";
615 ss.flags(std::ios::hex | std::ios::showbase);
616 ss << ((uint32_t) (vaddr + d16));
617 result.push_back(ss.str());
620 (uint32_t) (vaddr + d16),
true);
622 result.push_back(
"; <" +
symbol +
">");
628 if ((iw & 0x0000f000)==0x1000 || (iw & 0x0000f000)==0x2000) {
631 ss << ((iw & 0x0000f000) == 0x1000?
"ld" :
"st");
633 switch (iw & 0x00000c00) {
634 case 0x000: ss <<
".d";
break;
636 case 0x800: ss <<
".x";
break;
637 default: ss <<
".UNIMPLEMENTED";
645 result.push_back(ss.str());
648 ss2 <<
"r" << d <<
",r" << s1;
650 ss2 <<
"[r" << s2 <<
"]";
654 result.push_back(ss2.str());
655 }
else switch (op10) {
664 result.push_back(opcode_names_3c[op10]);
667 ss <<
"r" << d <<
",r" << s1 <<
",";
674 ss <<
"<" << s2 <<
">";
676 result.push_back(ss.str());
683 result.push_back(opcode_names_3c[op10]);
686 ss << d <<
",r" << s1 <<
",";
687 ss.flags(std::ios::hex | std::ios::showbase);
689 result.push_back(ss.str());
694 ss <<
"unimpl_" << opcode_names_3c[op10];
695 result.push_back(ss.str());
701 if ((iw & 0xf000) <= 0x3fff) {
705 switch (iw & 0xf000) {
706 case 0x2000:
op <<
"st";
break;
707 case 0x3000:
op <<
"lda";
break;
708 default:
if ((iw & 0xf800) >= 0x0800)
714 if ((iw & 0xf000) >= 0x1000) {
716 op << memop[(iw >> 10) & 3];
717 }
else if ((iw & 0xf800) == 0x0000) {
723 if ((iw & 0xf00) < 0xc00)
734 result.push_back(
op.str());
737 ss <<
"r" << d <<
",r" << s1;
739 ss <<
"[r" << s2 <<
"]";
743 result.push_back(ss.str());
744 }
else switch (op3d) {
782 result.push_back(opcode_names_3d[op3d]);
785 ss <<
"r" << d <<
",r" << s1 <<
",r" << s2;
786 result.push_back(ss.str());
795 result.push_back(opcode_names_3d[op3d]);
798 ss <<
"(r" << s2 <<
")";
799 result.push_back(ss.str());
806 result.push_back(opcode_names_3d[op3d]);
809 ss <<
"r" << d <<
",r" << s2;
810 result.push_back(ss.str());
816 result.push_back(opcode_names_3d[op3d]);
819 ss <<
"r" << s1 <<
",r" << s2;
820 result.push_back(ss.str());
826 result.push_back(
"rte");
833 ss <<
"illop" << (iw & 0xff);
834 result.push_back(ss.str());
838 result.push_back(
"gxemul_prom_call");
841 result.push_back(
"gxemul_fail_early");
844 result.push_back(
"gxemul_fail_late");
848 ss <<
"unimpl_3d_0xfc_" << (iw & 0xff);
849 result.push_back(ss.str());
855 ss <<
"unimpl_" << opcode_names_3d[op3d];
856 result.push_back(ss.str());
863 result.push_back(opcode_names[op26]);
867 ss.flags(std::ios::hex | std::ios::showbase);
869 result.push_back(ss.str());
876 ss <<
"unimpl_" << opcode_names[op26];
877 result.push_back(ss.str());
888 if (attributeName ==
"description")
889 return "Motorola 88000 processor.";
898 void M88K_CPUComponent::stcr(
int cr, uint32_t value,
bool is_rte)
900 uint32_t old = m_cr[cr];
907 std::cerr <<
"TODO: attempt to change endianness by flipping"
908 " the endianness bit in the PSR. How should this"
909 " be handled? Aborting.\n";
910 std::cerr <<
"TODO: abort in a nicer way\n";
911 throw std::exception();
918 " cleared; this should be done using the RTE "
919 "instruction only, according to the M88100 "
920 "manual! Continuing anyway.\n");
925 std::cerr <<
"m88k stcr: TODO: MXM support\n";
926 std::cerr <<
"TODO: abort in a nicer way\n";
927 throw std::exception();
933 std::cerr <<
"m88k stcr: TODO: PSR mode switch.\n";
934 std::cerr <<
"TODO: abort in a nicer way\n";
935 throw std::exception();
955 ui->
ShowDebugMessage(
this,
"WARNING! bit 0 non-zero when writing to SSBR\n");
962 if (value & 0x00000fff) {
965 ui->
ShowDebugMessage(
this,
"WARNING! bits 0..11 non-zero when writing to VBR\n");
984 default:std::cerr <<
"m88k stcr: UNIMPLEMENTED cr = " << cr <<
"\n";
985 std::cerr <<
"TODO: abort in a nicer way\n";
986 throw std::exception();
999 void M88K_CPUComponent::m88k_cmp(
struct DyntransIC *
ic, uint32_t y)
1001 uint32_t x =
REG32(
ic->arg[1]);
1012 if ((int32_t)x > (int32_t)y)
1032 cpu->m88k_cmp(
ic,
ic->arg[2].u32);
1046 void M88K_CPUComponent::m88k_extu(
struct DyntransIC *
ic,
int w,
int o)
1048 uint32_t x =
REG32(
ic->arg[1]) >> o;
1056 void M88K_CPUComponent::m88k_ext(
struct DyntransIC *
ic,
int w,
int o)
1058 int32_t x =
REG32(
ic->arg[1]);
1070 cpu->m88k_extu(
ic,
ic->arg[2].u32 >> 5,
ic->arg[2].u32 & 0x1f);
1080 cpu->m88k_ext(
ic,
ic->arg[2].u32 >> 5,
ic->arg[2].u32 & 0x1f);
1097 void M88K_CPUComponent::m88k_mak(
struct DyntransIC *
ic,
int w,
int o)
1099 uint32_t x =
REG32(
ic->arg[1]);
1119 cpu->m88k_mak(
ic,
ic->arg[2].u32 >> 5,
ic->arg[2].u32 & 0x1f);
1140 }
else if (
ic->arg[2].u32 == 0) {
1169 cpu->m_pc = (uint32_t) (
cpu->m_pc +
ic->arg[1].u32);
1170 cpu->DyntransPCtoPointers();
1191 cpu->m_pc = (uint32_t) (
cpu->m_pc +
ic->arg[1].u32);
1193 bool continueExecution =
cpu->FunctionTraceCall();
1194 cpu->DyntransPCtoPointers();
1196 if (!continueExecution)
1197 cpu->m_nextIC = &
cpu->m_abortIC;
1209 cpu->m_exceptionOrAbortInDelaySlot =
false;
1210 cpu->m_inDelaySlot =
true;
1211 cpu->m_delaySlotTarget = (uint32_t) (startOfPage +
ic->arg[1].u32);
1215 cpu->m_executedCycles ++;
1218 if (!
cpu->m_exceptionOrAbortInDelaySlot) {
1219 cpu->m_pc = (uint32_t) (startOfPage +
ic->arg[1].u32);
1220 cpu->DyntransPCtoPointers();
1222 cpu->m_inDelaySlot =
false;
1227 cpu->m_exceptionOrAbortInDelaySlot =
false;
1239 cpu->m_inDelaySlot =
true;
1240 cpu->m_exceptionOrAbortInDelaySlot =
false;
1244 cpu->m_executedCycles ++;
1247 if (!
cpu->m_exceptionOrAbortInDelaySlot) {
1248 cpu->m_pc = (uint32_t) (startOfPage +
ic->arg[1].u32);
1250 bool continueExecution =
cpu->FunctionTraceCall();
1251 cpu->DyntransPCtoPointers();
1253 cpu->m_inDelaySlot =
false;
1255 if (!continueExecution)
1256 cpu->m_nextIC = &
cpu->m_abortIC;
1261 cpu->m_exceptionOrAbortInDelaySlot =
false;
1272 cpu->m_inDelaySlot =
true;
1273 cpu->m_exceptionOrAbortInDelaySlot =
false;
1278 uint32_t old_pc =
cpu->m_pc;
1280 cpu->m_pc = (uint32_t) (
cpu->m_pc +
ic->arg[1].u32);
1282 if (
cpu->m_showFunctionTraceCall)
1283 cpu->FunctionTraceCall();
1285 cpu->m_delaySlotTarget =
cpu->m_pc;
1288 cpu->m_nextIC =
ic + 1;
1307 else if (
op == 7)
cond = ((uint32_t)
REG32(
ic->arg[0]) != 0x80000000UL);
1308 else if (
op == 8)
cond = ((uint32_t)
REG32(
ic->arg[0]) == 0x80000000UL);
1310 else if (
op == 13)
cond = ((int32_t)
REG32(
ic->arg[0]) != 0);
1318 cpu->m_inDelaySlot =
true;
1319 cpu->m_exceptionOrAbortInDelaySlot =
false;
1323 cpu->m_delaySlotTarget = (uint32_t) (
cpu->m_delaySlotTarget +
ic->arg[2].u32);
1325 cpu->m_delaySlotTarget =
cpu->m_pc + 8;
1328 cpu->m_nextIC =
ic + 1;
1331 cpu->m_inDelaySlot =
true;
1332 cpu->m_exceptionOrAbortInDelaySlot =
false;
1336 cpu->m_executedCycles ++;
1339 if (!
cpu->m_exceptionOrAbortInDelaySlot) {
1342 cpu->m_pc = (uint32_t) (
cpu->m_pc +
ic->arg[2].u32);
1343 cpu->DyntransPCtoPointers();
1345 cpu->m_nextIC =
ic + 2;
1348 cpu->m_inDelaySlot =
false;
1354 cpu->m_exceptionOrAbortInDelaySlot =
false;
1360 cpu->m_pc = (uint32_t) (
cpu->m_pc +
ic->arg[2].u32);
1361 cpu->DyntransPCtoPointers();
1381 bool bit =
REG32(
ic->arg[0]) &
ic->arg[1].u32;
1387 cpu->m_pc = (uint32_t) (
cpu->m_pc +
ic->arg[2].u32);
1388 cpu->DyntransPCtoPointers();
1398 bool bit =
REG32(
ic->arg[0]) &
ic->arg[1].u32;
1401 cpu->m_inDelaySlot =
true;
1402 cpu->m_exceptionOrAbortInDelaySlot =
false;
1406 cpu->m_executedCycles ++;
1409 if (!
cpu->m_exceptionOrAbortInDelaySlot) {
1412 cpu->m_pc = (uint32_t) (
cpu->m_pc +
ic->arg[2].u32);
1413 cpu->DyntransPCtoPointers();
1415 cpu->m_nextIC =
ic + 2;
1418 cpu->m_inDelaySlot =
false;
1424 cpu->m_exceptionOrAbortInDelaySlot =
false;
1432 bool bit =
REG32(
ic->arg[0]) &
ic->arg[1].u32;
1437 cpu->m_inDelaySlot =
true;
1438 cpu->m_exceptionOrAbortInDelaySlot =
false;
1442 cpu->m_delaySlotTarget = (uint32_t) (
cpu->m_delaySlotTarget +
ic->arg[2].u32);
1444 cpu->m_delaySlotTarget =
cpu->m_pc + 8;
1447 cpu->m_nextIC =
ic + 1;
1454 bool continueExecution =
true;
1457 continueExecution =
cpu->FunctionTraceReturn();
1460 cpu->DyntransPCtoPointers();
1462 if (!continueExecution)
1463 cpu->m_nextIC = &
cpu->m_abortIC;
1472 cpu->m_inDelaySlot =
true;
1473 cpu->m_exceptionOrAbortInDelaySlot =
false;
1474 uint32_t branchTarget =
REG32(
ic->arg[2]);
1478 cpu->m_executedCycles ++;
1481 if (!
cpu->m_exceptionOrAbortInDelaySlot) {
1482 cpu->m_pc = branchTarget;
1483 cpu->DyntransPCtoPointers();
1485 cpu->m_inDelaySlot =
false;
1491 cpu->m_exceptionOrAbortInDelaySlot =
false;
1500 cpu->m_inDelaySlot =
true;
1501 cpu->m_exceptionOrAbortInDelaySlot =
false;
1502 uint32_t branchTarget =
REG32(
ic->arg[2]);
1506 cpu->m_executedCycles ++;
1509 if (!
cpu->m_exceptionOrAbortInDelaySlot) {
1510 bool continueExecution =
true;
1512 continueExecution =
cpu->FunctionTraceReturn();
1514 cpu->m_pc = branchTarget;
1515 cpu->DyntransPCtoPointers();
1517 cpu->m_inDelaySlot =
false;
1519 if (!continueExecution)
1520 cpu->m_nextIC = &
cpu->m_abortIC;
1526 cpu->m_exceptionOrAbortInDelaySlot =
false;
1537 cpu->FunctionTraceReturn();
1540 cpu->m_inDelaySlot =
true;
1541 cpu->m_exceptionOrAbortInDelaySlot =
false;
1560 int cr =
ic->arg[1].u32;
1588 cpu->m_nextIC =
ic + 1;
1610 bool bit = (
REG32(
ic->arg[1]) &
ic->arg[0].u32) > 0;
1613 cpu->Exception(
ic->arg[2].u32, 1);
1638 template<
bool store,
typename T,
bool doubleword,
bool regofs,
bool scaled,
bool signedLoad>
void M88K_CPUComponent::instr_loadstore(
CPUDyntransComponent* cpubase,
DyntransIC*
ic)
1648 (scaled? (doubleword?
sizeof(uint64_t) :
sizeof(T)) : 1) *
1649 (regofs?
REG32(
ic->arg[2]) :
ic->arg[2].u32);
1651 if (
sizeof(T) > 1 && (
addr & (
sizeof(T)-1))) {
1671 if (
sizeof(T) ==
sizeof(uint16_t))
1673 if (
sizeof(T) ==
sizeof(uint8_t))
1683 uint32_t data2 = (* (((uint32_t*)(
ic->arg[0].p)) + 1) );
1684 cpu->AddressSelect(
addr +
sizeof(uint32_t));
1690 cpu->AddressSelect(
addr +
sizeof(uint32_t));
1695 (* (((uint32_t*)(
ic->arg[0].p)) + 1) ) = data2;
1718 cpu->m_executedCycles --;
1721 cpu->m_nextIC = &
cpu->m_abortIC;
1722 if (
cpu->m_inDelaySlot)
1723 cpu->m_exceptionOrAbortInDelaySlot =
true;
1735 cpu->m_pc +=
sizeof(uint32_t);
1738 cpu->m_nextIC = &
cpu->m_abortIC;
1739 if (
cpu->m_inDelaySlot)
1740 cpu->m_exceptionOrAbortInDelaySlot =
true;
1747 void M88K_CPUComponent::Translate(uint32_t iw,
struct DyntransIC*
ic)
1752 uint32_t op26 = (iw >> 26) & 0x3f;
1754 uint32_t op10 = (iw >> 10) & 0x3f;
1755 uint32_t d = (iw >> 21) & 0x1f;
1756 uint32_t s1 = (iw >> 16) & 0x1f;
1757 uint32_t s2 = iw & 0x1f;
1759 uint32_t imm16 = iw & 0xffff;
1761 uint32_t cr6 = (iw >> 5) & 0x3f;
1762 int32_t d16 = ((int16_t) (iw & 0xffff)) * 4;
1763 int32_t d26 = ((int32_t)((iw & 0x03ffffff) << 6)) >> 4;
1778 bool store = op26 >= 0x08;
1781 ic->arg[0].p = &m_r[d];
1782 ic->arg[1].p = &m_r[s1];
1783 ic->arg[2].u32 = imm16;
1786 case 0x02:
ic->f = instr_loadstore<false, uint16_t, false, false, false, false>; opsize = 1;
break;
1787 case 0x03:
ic->f = instr_loadstore<false, uint8_t, false, false, false, false>; opsize = 0;
break;
1788 case 0x04:
ic->f = instr_loadstore<false, uint32_t, true, false, false, false>; opsize = 3;
break;
1789 case 0x05:
ic->f = instr_loadstore<false, uint32_t, false, false, false, false>; opsize = 2;
break;
1790 case 0x06:
ic->f = instr_loadstore<false, uint16_t, false, false, false, true>; opsize = 1;
break;
1791 case 0x07:
ic->f = instr_loadstore<false, uint8_t, false, false, false, true>; opsize = 0;
break;
1792 case 0x08:
ic->f = instr_loadstore<true, uint32_t, true, false, false, false>; opsize = 3;
break;
1793 case 0x09:
ic->f = instr_loadstore<true, uint32_t, false, false, false, false>; opsize = 2;
break;
1794 case 0x0a:
ic->f = instr_loadstore<true, uint16_t, false, false, false, false>; opsize = 1;
break;
1795 case 0x0b:
ic->f = instr_loadstore<true, uint8_t, false, false, false, false>; opsize = 0;
break;
1798 if (opsize == 3 && d == 31) {
1809 ic->arg[0].p = &m_zero_scratch;
1829 case 0x10:
ic->f = instr_and_u32_u32_immu32;
break;
1830 case 0x11:
ic->f = instr_and_u32_u32_immu32; shift = 16;
break;
1831 case 0x12:
ic->f = instr_and_u32_u32_immu32;
break;
1832 case 0x13:
ic->f = instr_and_u32_u32_immu32; shift = 16;
break;
1833 case 0x14:
ic->f = instr_xor_u32_u32_immu32;
break;
1834 case 0x15:
ic->f = instr_xor_u32_u32_immu32; shift = 16;
break;
1835 case 0x16:
ic->f = instr_or_u32_u32_immu32;
break;
1836 case 0x17:
ic->f = instr_or_u32_u32_immu32; shift = 16;
break;
1837 case 0x18:
ic->f = instr_add_u32_u32_immu32;
break;
1838 case 0x19:
ic->f = instr_sub_u32_u32_immu32;
break;
1839 case 0x1a:
ic->f = instr_divu_imm;
break;
1840 case 0x1b:
ic->f = instr_mulu_imm;
break;
1844 case 0x1f:
ic->f = instr_cmp_imm;
break;
1847 ic->arg[0].p = &m_r[d];
1848 ic->arg[1].p = &m_r[s1];
1849 ic->arg[2].u32 = imm16 << shift;
1855 ic->arg[2].u32 |= 0xffff0000;
1857 ic->arg[2].u32 |= 0x0000ffff;
1865 if ((iw & 0x001ff81f) == 0x00004000) {
1867 ic->arg[0].p = &m_r[d];
1868 ic->arg[1].u32 = cr6;
1870 ic->arg[0].p = &m_zero_scratch;
1878 }
else if ((iw & 0x03e0f800) == 0x00008000) {
1880 ic->arg[0].p = &m_r[s1];
1881 ic->arg[1].u32 = cr6;
1886 ss.flags(std::ios::hex);
1887 ss <<
"stcr with s1 != s2? TODO: how "
1888 "should this be handled? s1=0x"
1889 << s1 <<
", s2=0x" << s2;
1906 }
else if (ui != NULL) {
1923 samepage_function = instr_branch_samepage;
1932 samepage_function = instr_bsr_samepage;
1935 ic->f = instr_bsr_n;
1937 f_singleStepping = instr_bsr_n_functioncalltrace_singlestep;
1941 if (singleInstructionLeft && (op26 == 0x31 || op26 == 0x33)) {
1942 ic->f = f_singleStepping;
1943 samepage_function = NULL;
1946 int offset = (
m_pc & 0xffc) + d26;
1951 ic->arg[1].u32 = offset;
1954 ic->arg[2].u32 = (
m_pc & 0xffc) + ((op26 & 1)? 8 : 4);
1956 if (offset >= 0 && offset <= 0xffc && samepage_function != NULL)
1957 ic->f = samepage_function;
1961 ic->f = instr_bsr_functioncalltrace;
1963 if (singleInstructionLeft)
1964 ic->f = instr_bsr_n_functioncalltrace_singlestep;
1966 ic->f = instr_bsr_n_functioncalltrace;
1982 ic->f = instr_bb<false,false>;
1983 samepage_function = instr_bb<false,true>;
1986 ic->f = instr_bb_n<false>;
1987 singlestep_function = instr_bb_n_singlestep<false>;
1990 ic->f = instr_bb<true,false>;
1991 samepage_function = instr_bb<true,true>;
1994 ic->f = instr_bb_n<true>;
1995 singlestep_function = instr_bb_n_singlestep<true>;
1999 ic->arg[0].p = &m_r[s1];
2000 ic->arg[1].u32 = (1 << d);
2002 int offset = (
m_pc & 0xffc) + d16;
2003 ic->arg[2].u32 = offset;
2005 if (singleInstructionLeft && singlestep_function != NULL)
2006 ic->f = singlestep_function;
2007 else if (offset >= 0 && offset <= 0xffc && samepage_function != NULL) {
2008 ic->f = samepage_function;
2022 case 1:
ic->f = instr_bcnd<true,1, false>; singlestep_f = instr_bcnd<true,1, true>;
break;
2023 case 2:
ic->f = instr_bcnd<true,2, false>; singlestep_f = instr_bcnd<true,2, true>;
break;
2024 case 3:
ic->f = instr_bcnd<true,3, false>; singlestep_f = instr_bcnd<true,3, true>;
break;
2025 case 7:
ic->f = instr_bcnd<true,7, false>; singlestep_f = instr_bcnd<true,7, true>;
break;
2026 case 8:
ic->f = instr_bcnd<true,8, false>; singlestep_f = instr_bcnd<true,8, true>;
break;
2027 case 12:
ic->f = instr_bcnd<true,12,false>; singlestep_f = instr_bcnd<true,12,true>;
break;
2028 case 13:
ic->f = instr_bcnd<true,13,false>; singlestep_f = instr_bcnd<true,13,true>;
break;
2029 case 14:
ic->f = instr_bcnd<true,14,false>; singlestep_f = instr_bcnd<true,14,true>;
break;
2033 case 1:
ic->f = instr_bcnd<false,1, false>;
break;
2034 case 2:
ic->f = instr_bcnd<false,2, false>;
break;
2035 case 3:
ic->f = instr_bcnd<false,3, false>;
break;
2036 case 7:
ic->f = instr_bcnd<false,7, false>;
break;
2037 case 8:
ic->f = instr_bcnd<false,8, false>;
break;
2038 case 12:
ic->f = instr_bcnd<false,12,false>;
break;
2039 case 13:
ic->f = instr_bcnd<false,13,false>;
break;
2040 case 14:
ic->f = instr_bcnd<false,14,false>;
break;
2048 if (
ic->f == NULL) {
2051 ss.flags(std::ios::hex);
2052 ss <<
"unimplemented bcnd condition code d = " << d;
2059 ic->arg[0].p = &m_r[s1];
2061 int offset = (
m_pc & 0xffc) + d16;
2062 ic->arg[2].u32 = offset;
2064 if (singleInstructionLeft && singlestep_f != NULL) {
2065 ic->f = singlestep_f;
2066 }
else if (offset >= 0 && offset <= 0xffc && samepage_function != NULL) {
2067 ic->f = samepage_function;
2081 ic->arg[0].p = &m_r[d];
2082 ic->arg[1].p = &m_r[s1];
2083 ic->arg[2].u32 = iw & 0x3ff;
2106 case 0x24:
ic->f = instr_ext_imm;
break;
2107 case 0x26:
ic->f = instr_extu_imm;
break;
2108 case 0x28:
ic->f = instr_mak_imm;
break;
2117 ic->arg[0].u32 = 1 << d;
2118 ic->arg[1].p = &m_r[s1];
2119 ic->arg[2].u32 = iw & 0x1ff;
2121 case 0x34:
ic->f = instr_tb<false>;
break;
2122 case 0x36:
ic->f = instr_tb<true>;
break;
2129 ss.flags(std::ios::hex);
2130 ss <<
"unimplemented opcode 0x" << op26 <<
",0x" << op10;
2137 if ((iw & 0xf000) <= 0x3fff ) {
2139 int op = 0, opsize, user = 0, wt = 0;
2140 int signedness = 1, scaled = 0;
2142 switch (iw & 0xf000) {
2143 case 0x2000:
op = 1;
break;
2144 case 0x3000:
op = 2;
break;
2145 default:
if ((iw & 0xf800) >= 0x0800)
2152 opsize = (iw >> 10) & 3;
2155 opsize = 3 - opsize;
2160 switch ((iw >> 10) & 3) {
2161 case 0: opsize = 0;
break;
2162 case 1: opsize = 2;
break;
2169 if ((iw & 0xf800) == 0x800) {
2171 if ((iw & 0xf00) < 0xc00)
2176 if (opsize >= 2 ||
op == 1)
2194 ic->arg[0].p = &m_r[d];
2195 ic->arg[1].p = &m_r[s1];
2196 ic->arg[2].p = &m_r[s2];
2198 if (
op == 0 ||
op == 1) {
2202 ((
op == 1)? 4 : 0) +
2203 (signedness? 8 : 0) +
2212 case 0 + 0 + 0 + 0 + 0 + 0:
ic->f = instr_loadstore<false, uint8_t, false, true, false, false>;
break;
2213 case 0 + 0 + 0 + 0 + 32 + 0:
ic->f = instr_loadstore<false, uint8_t, false, true, true, false>;
break;
2214 case 0 + 0 + 0 + 16 + 0 + 0:
ic->f = instr_loadstore<false, uint8_t, false, true, false, false>;
break;
2215 case 0 + 0 + 0 + 16 + 32 + 0:
ic->f = instr_loadstore<false, uint8_t, false, true, true, false>;
break;
2216 case 1 + 0 + 0 + 0 + 0 + 0:
ic->f = instr_loadstore<false, uint16_t, false, true, false, false>;
break;
2217 case 1 + 0 + 0 + 0 + 32 + 0:
ic->f = instr_loadstore<false, uint16_t, false, true, true, false>;
break;
2218 case 1 + 0 + 0 + 16 + 0 + 0:
ic->f = instr_loadstore<false, uint16_t, false, true, false, false>;
break;
2219 case 1 + 0 + 0 + 16 + 32 + 0:
ic->f = instr_loadstore<false, uint16_t, false, true, true, false>;
break;
2220 case 2 + 0 + 0 + 0 + 0 + 0:
ic->f = instr_loadstore<false, uint32_t, false, true, false, false>;
break;
2221 case 2 + 0 + 0 + 0 + 32 + 0:
ic->f = instr_loadstore<false, uint32_t, false, true, true, false>;
break;
2222 case 2 + 0 + 0 + 16 + 0 + 0:
ic->f = instr_loadstore<false, uint32_t, false, true, false, false>;
break;
2223 case 2 + 0 + 0 + 16 + 32 + 0:
ic->f = instr_loadstore<false, uint32_t, false, true, true, false>;
break;
2224 case 3 + 0 + 0 + 0 + 0 + 0:
ic->f = instr_loadstore<false, uint32_t, true, true, false, false>;
break;
2225 case 3 + 0 + 0 + 0 + 32 + 0:
ic->f = instr_loadstore<false, uint32_t, true, true, true, false>;
break;
2226 case 3 + 0 + 0 + 16 + 0 + 0:
ic->f = instr_loadstore<false, uint32_t, true, true, false, false>;
break;
2227 case 3 + 0 + 0 + 16 + 32 + 0:
ic->f = instr_loadstore<false, uint32_t, true, true, true, false>;
break;
2229 case 0 + 4 + 0 + 0 + 0 + 0:
ic->f = instr_loadstore<true, uint8_t, false, true, false, false>;
break;
2230 case 0 + 4 + 0 + 0 + 32 + 0:
ic->f = instr_loadstore<true, uint8_t, false, true, true, false>;
break;
2231 case 0 + 4 + 0 + 16 + 0 + 0:
ic->f = instr_loadstore<true, uint8_t, false, true, false, false>;
break;
2232 case 0 + 4 + 0 + 16 + 32 + 0:
ic->f = instr_loadstore<true, uint8_t, false, true, true, false>;
break;
2233 case 1 + 4 + 0 + 0 + 0 + 0:
ic->f = instr_loadstore<true, uint16_t, false, true, false, false>;
break;
2234 case 1 + 4 + 0 + 0 + 32 + 0:
ic->f = instr_loadstore<true, uint16_t, false, true, true, false>;
break;
2235 case 1 + 4 + 0 + 16 + 0 + 0:
ic->f = instr_loadstore<true, uint16_t, false, true, false, false>;
break;
2236 case 1 + 4 + 0 + 16 + 32 + 0:
ic->f = instr_loadstore<true, uint16_t, false, true, true, false>;
break;
2237 case 2 + 4 + 0 + 0 + 0 + 0:
ic->f = instr_loadstore<true, uint32_t, false, true, false, false>;
break;
2238 case 2 + 4 + 0 + 0 + 32 + 0:
ic->f = instr_loadstore<true, uint32_t, false, true, true, false>;
break;
2239 case 2 + 4 + 0 + 16 + 0 + 0:
ic->f = instr_loadstore<true, uint32_t, false, true, false, false>;
break;
2240 case 2 + 4 + 0 + 16 + 32 + 0:
ic->f = instr_loadstore<true, uint32_t, false, true, true, false>;
break;
2241 case 3 + 4 + 0 + 0 + 0 + 0:
ic->f = instr_loadstore<true, uint32_t, true, true, false, false>;
break;
2242 case 3 + 4 + 0 + 0 + 32 + 0:
ic->f = instr_loadstore<true, uint32_t, true, true, true, false>;
break;
2243 case 3 + 4 + 0 + 16 + 0 + 0:
ic->f = instr_loadstore<true, uint32_t, true, true, false, false>;
break;
2244 case 3 + 4 + 0 + 16 + 32 + 0:
ic->f = instr_loadstore<true, uint32_t, true, true, true, false>;
break;
2246 std::cerr <<
"TODO generalize! scaled="<<scaled <<
" user="<<
2247 user<<
" signedness="<<signedness <<
" opsize=" << opsize <<
"\n";
2255 ic->arg[0].p = &m_zero_scratch;
2257 if (opsize == 3 && d == 31) {
2263 }
else if (
op == 2) {
2268 case 1:
ic->f = instr_lda<2>;
break;
2269 case 2:
ic->f = instr_lda<4>;
break;
2270 case 3:
ic->f = instr_lda<8>;
break;
2288 }
else switch ((iw >> 8) & 0xff) {
2312 ic->arg[0].p = &m_r[d];
2313 ic->arg[1].p = &m_r[s1];
2314 ic->arg[2].p = &m_r[s2];
2316 switch ((iw >> 8) & 0xff) {
2319 case 0x50:
ic->f = instr_xor_u32_u32_u32;
break;
2321 case 0x58:
ic->f = instr_or_u32_u32_u32;
break;
2323 case 0x60:
ic->f = instr_add_u32_u32_u32;
break;
2326 case 0x64:
ic->f = instr_sub_u32_u32_u32;
break;
2333 case 0x7c:
ic->f = instr_cmp;
break;
2336 case 0x90:
ic->f = instr_ext;
break;
2337 case 0x98:
ic->f = instr_extu;
break;
2338 case 0xa0:
ic->f = instr_mak;
break;
2352 int opc = (iw >> 8) & 0xff;
2353 if (opc != 0x61 && opc != 0x63 &&
2354 opc != 0x65 && opc != 0x67 &&
2355 opc != 0x71 && opc != 0x73 &&
2356 opc != 0x75 && opc != 0x77 &&
2357 opc != 0x68 && opc != 0x69 &&
2358 opc != 0x6c && opc != 0x6d &&
2359 opc != 0x6e && opc != 0x78 )
2362 ic->arg[0].p = &m_zero_scratch;
2365 if (
ic->f == NULL && ui != NULL) {
2367 ss.flags(std::ios::hex);
2368 ss <<
"unimplemented opcode 0x3d,0x" << ((iw >> 8) & 0xff);
2380 switch ((iw >> 8) & 0xff) {
2381 case 0xc0:
ic->f = instr_jmp;
break;
2382 case 0xc4:
ic->f = instr_jmp_n; f_ss = instr_jmp_n_functioncalltrace_singlestep;
break;
2387 ic->arg[1].u32 = (
m_pc & 0xffc) + 4;
2388 ic->arg[2].p = &m_r[s2];
2390 if (((iw >> 8) & 0x04) == 0x04)
2391 ic->arg[1].u32 = (
m_pc & 0xffc) + 8;
2394 if (
ic->f == instr_jmp_n) {
2395 ic->f = instr_jmp_n_functioncalltrace;
2396 f_ss = instr_jmp_n_functioncalltrace_singlestep;
2409 if (singleInstructionLeft && f_ss != NULL)
2417 switch (iw & 0xff) {
2424 ic->f = instr_fail_early;
2428 default:
if (ui != NULL) {
2430 ss.flags(std::ios::hex);
2431 ss <<
"unimplemented opcode 0x3d,0xfc,0x" << (iw & 0xff);
2439 ss.flags(std::ios::hex);
2440 ss <<
"unimplemented opcode 0x3d,0x" << ((iw >> 8) & 0xff);
2449 ss.flags(std::ios::hex);
2450 ss <<
"unimplemented opcode 0x" << op26;
2461 cpu->DyntransToBeTranslatedBegin(
ic);
2464 if (
cpu->DyntransReadInstruction(iword))
2465 cpu->Translate(iword,
ic);
2467 if (
cpu->m_inDelaySlot &&
ic->f == NULL)
2468 ic->f = instr_abort;
2470 cpu->DyntransToBeTranslatedDone(
ic);
2477 #ifdef WITHUNITTESTS
2481 static void Test_M88K_CPUComponent_Create()
2496 static void Test_M88K_CPUComponent_Create_with_r31()
2510 cpu->SetVariableValue(
"r31",
"0xf00");
2521 static void Test_M88K_CPUComponent_IsCPU()
2530 static void Test_M88K_CPUComponent_DefaultModel()
2539 cpu->GetVariable(
"model")->ToString(),
"88100");
2542 static void Test_M88K_CPUComponent_Disassembly_Basic()
2551 vector<string> result;
2556 uint32_t data32 = 0x63df0010;
2559 len =
cpu->DisassembleInstruction(512, result);
2568 static void Test_M88K_CPUComponent_Execute_Basic()
2581 uint32_t data32 = 0x63df0010;
2588 cpu->SetVariableValue(
"pc",
"48");
2589 cpu->SetVariableValue(
"r30",
"1234");
2590 cpu->SetVariableValue(
"r31",
"5678");
2596 UnitTest::Assert(
"r30 should have been modified",
cpu->GetVariable(
"r30")->ToInteger(), 5678 + 0x10);
2597 UnitTest::Assert(
"r31 should not have been modified",
cpu->GetVariable(
"r31")->ToInteger(), 5678);
2599 cpu->SetVariableValue(
"r31",
"1111");
2604 UnitTest::Assert(
"pc should have increased again",
cpu->GetVariable(
"pc")->ToInteger(), 56);
2605 UnitTest::Assert(
"r30 should have been modified again",
cpu->GetVariable(
"r30")->ToInteger(), 1111 + 0x10);
2608 static void Test_M88K_CPUComponent_Execute_DelayBranchWithValidInstruction()
2619 uint32_t data32 = 0xcc000010;
2623 data32 = 0x63df0010;
2627 cpu->SetVariableValue(
"pc",
"0x1000");
2638 UnitTest::Assert(
"delay slot after execute",
cpu->GetVariable(
"inDelaySlot")->ToString(),
"false");
2643 static void Test_M88K_CPUComponent_Execute_DelayBranchWithValidInstruction_SingleStepping()
2654 uint32_t data32 = 0xcc000010;
2658 data32 = 0x63df0010;
2662 cpu->SetVariableValue(
"pc",
"0x1000");
2673 UnitTest::Assert(
"pc should have changed 1",
cpu->GetVariable(
"pc")->ToInteger(), 0x1004);
2674 UnitTest::Assert(
"delay slot after execute 1",
cpu->GetVariable(
"inDelaySlot")->ToString(),
"true");
2681 UnitTest::Assert(
"delay slot after execute 2",
cpu->GetVariable(
"inDelaySlot")->ToString(),
"false");
2682 UnitTest::Assert(
"pc should have changed 2",
cpu->GetVariable(
"pc")->ToInteger(), 0x1040);
2687 static void Test_M88K_CPUComponent_Execute_DelayBranchWithValidInstruction_RunTwoTimes()
2698 uint32_t data32 = 0xcc000010;
2702 data32 = 0x63df0010;
2706 cpu->SetVariableValue(
"pc",
"0x1000");
2717 UnitTest::Assert(
"pc should have changed 1",
cpu->GetVariable(
"pc")->ToInteger(), 0x1004);
2718 UnitTest::Assert(
"delay slot after execute 1",
cpu->GetVariable(
"inDelaySlot")->ToString(),
"true");
2725 UnitTest::Assert(
"delay slot after execute 2",
cpu->GetVariable(
"inDelaySlot")->ToString(),
"false");
2726 UnitTest::Assert(
"pc should have changed 2",
cpu->GetVariable(
"pc")->ToInteger(), 0x1040);
2731 static void Test_M88K_CPUComponent_Execute_DelayBranchWithFault()
2742 uint32_t data32 = 0xcc000010;
2746 data32 = 0xffffffff;
2750 cpu->SetVariableValue(
"pc",
"0x1000");
2760 UnitTest::Assert(
"pc should have increased one step",
cpu->GetVariable(
"pc")->ToInteger(), 0x1004ULL);
2761 UnitTest::Assert(
"should be in delay slot after execution",
cpu->GetVariable(
"inDelaySlot")->ToString(),
"true");
2766 UnitTest::Assert(
"pc should not have increased",
cpu->GetVariable(
"pc")->ToInteger(), 0x1004ULL);
2767 UnitTest::Assert(
"should still be in delay slot",
cpu->GetVariable(
"inDelaySlot")->ToString(),
"true");
2770 static void Test_M88K_CPUComponent_Execute_EarlyAbortDuringRuntime_Singlestep()
2781 uint32_t data32 = 0xcc000010;
2785 data32 = 0xf400fc93;
2790 cpu->SetVariableValue(
"pc",
"0x1000");
2798 UnitTest::Assert(
"1 step should have executed",
cpu->GetVariable(
"step")->ToInteger(), 1);
2799 UnitTest::Assert(
"pc should have increased one step",
cpu->GetVariable(
"pc")->ToInteger(), 0x1004ULL);
2800 UnitTest::Assert(
"should be in delay slot after execution",
cpu->GetVariable(
"inDelaySlot")->ToString(),
"true");
2801 UnitTest::Assert(
"delay target should have been updated",
cpu->GetVariable(
"delaySlotTarget")->ToInteger(), 0x1040);
2806 UnitTest::Assert(
"no more steps should have executed",
cpu->GetVariable(
"step")->ToInteger(), 1);
2807 UnitTest::Assert(
"pc should not have increased",
cpu->GetVariable(
"pc")->ToInteger(), 0x1004ULL);
2808 UnitTest::Assert(
"should still be in delay slot",
cpu->GetVariable(
"inDelaySlot")->ToString(),
"true");
2809 UnitTest::Assert(
"delay target should not have been updated",
cpu->GetVariable(
"delaySlotTarget")->ToInteger(), 0x1040);
2812 static void Test_M88K_CPUComponent_Execute_EarlyAbortDuringRuntime_Running()
2823 uint32_t data32 = 0xcc000010;
2827 data32 = 0xf400fc93;
2832 cpu->SetVariableValue(
"pc",
"0x1000");
2840 UnitTest::Assert(
"1 step should have executed",
cpu->GetVariable(
"step")->ToInteger(), 1);
2841 UnitTest::Assert(
"pc should have increased one step",
cpu->GetVariable(
"pc")->ToInteger(), 0x1004ULL);
2842 UnitTest::Assert(
"should be in delay slot after execution",
cpu->GetVariable(
"inDelaySlot")->ToString(),
"true");
2843 UnitTest::Assert(
"delay target should have been updated",
cpu->GetVariable(
"delaySlotTarget")->ToInteger(), 0x1040);
2848 UnitTest::Assert(
"no more steps should have executed",
cpu->GetVariable(
"step")->ToInteger(), 1);
2849 UnitTest::Assert(
"pc should not have increased",
cpu->GetVariable(
"pc")->ToInteger(), 0x1004ULL);
2850 UnitTest::Assert(
"should still be in delay slot",
cpu->GetVariable(
"inDelaySlot")->ToString(),
"true");
2851 UnitTest::Assert(
"delay target should not have been updated",
cpu->GetVariable(
"delaySlotTarget")->ToInteger(), 0x1040);
2856 UNITTEST(Test_M88K_CPUComponent_Create);
2857 UNITTEST(Test_M88K_CPUComponent_Create_with_r31);
2858 UNITTEST(Test_M88K_CPUComponent_IsCPU);
2859 UNITTEST(Test_M88K_CPUComponent_DefaultModel);
2862 UNITTEST(Test_M88K_CPUComponent_Disassembly_Basic);
2865 UNITTEST(Test_M88K_CPUComponent_Execute_Basic);
2866 UNITTEST(Test_M88K_CPUComponent_Execute_DelayBranchWithValidInstruction);
2867 UNITTEST(Test_M88K_CPUComponent_Execute_DelayBranchWithValidInstruction_SingleStepping);
2868 UNITTEST(Test_M88K_CPUComponent_Execute_DelayBranchWithValidInstruction_RunTwoTimes);
2869 UNITTEST(Test_M88K_CPUComponent_Execute_DelayBranchWithFault);
2870 UNITTEST(Test_M88K_CPUComponent_Execute_EarlyAbortDuringRuntime_Singlestep);
2871 UNITTEST(Test_M88K_CPUComponent_Execute_EarlyAbortDuringRuntime_Running);