179#include <type_traits>
204 #define MAYBE_UNUSED_LABEL [[maybe_unused]]
206 #pragma warning(disable : 4102)
207 #define MAYBE_UNUSED_LABEL
213enum Reg8 :
int {
A,
F,
B,
C,
D,
E,
H,
L,
IXH,
IXL,
IYH,
IYL,
REG_I,
REG_R,
DUMMY };
217static constexpr byte S_FLAG = 0x80;
218static constexpr byte Z_FLAG = 0x40;
219static constexpr byte Y_FLAG = 0x20;
220static constexpr byte H_FLAG = 0x10;
221static constexpr byte X_FLAG = 0x08;
222static constexpr byte V_FLAG = 0x04;
223static constexpr byte P_FLAG = V_FLAG;
224static constexpr byte N_FLAG = 0x02;
225static constexpr byte C_FLAG = 0x01;
229 std::array<byte, 256>
ZS;
231 std::array<byte, 256>
ZSP;
236static constexpr byte ZS0 = Z_FLAG;
237static constexpr byte ZSXY0 = Z_FLAG;
238static constexpr byte ZSP0 = Z_FLAG | V_FLAG;
239static constexpr byte ZSPXY0 = Z_FLAG | V_FLAG;
240static constexpr byte ZS255 = S_FLAG;
241static constexpr byte ZSXY255 = S_FLAG | X_FLAG | Y_FLAG;
243static constexpr Table initTables()
247 for (
auto i_ :
xrange(256)) {
248 auto i = narrow_cast<byte>(i_);
249 byte zFlag = (i == 0) ? Z_FLAG : 0;
250 byte sFlag = i & S_FLAG;
251 byte xFlag = i & X_FLAG;
252 byte yFlag = i & Y_FLAG;
254 for (
int v = 128; v != 0; v >>= 1) {
255 if (i & v) vFlag ^= V_FLAG;
257 table.
ZS [i] = zFlag | sFlag;
258 table.
ZSXY [i] = zFlag | sFlag | xFlag | yFlag;
259 table.
ZSP [i] = zFlag | sFlag | vFlag;
260 table.
ZSPXY[i] = zFlag | sFlag | xFlag | yFlag | vFlag;
261 table.
ZSPH [i] = zFlag | sFlag | vFlag | H_FLAG;
263 assert(table.
ZS [ 0] == ZS0);
264 assert(table.
ZSXY [ 0] == ZSXY0);
265 assert(table.
ZSP [ 0] == ZSP0);
266 assert(table.
ZSPXY[ 0] == ZSPXY0);
267 assert(table.
ZS [255] == ZS255);
268 assert(table.
ZSXY [255] == ZSXY255);
273static constexpr Table table = initTables();
297 , T(time, motherboard_.getScheduler())
298 , motherboard(motherboard_)
299 , scheduler(motherboard.getScheduler())
300 , traceSetting(traceSetting_)
301 , diHaltCallback(diHaltCallback_)
302 , IRQStatus(motherboard.getDebugger(), name +
".pendingIRQ",
303 "Non-zero if there are pending IRQs (thus CPU would enter "
304 "interrupt routine in EI mode).",
306 , IRQAccept(motherboard.getDebugger(), name +
".acceptIRQ",
307 "This probe is only useful to set a breakpoint on (the value "
308 "return by read is meaningless). The breakpoint gets triggered "
309 "right after the CPU accepted an IRQ.")
311 motherboard.getCommandController(),
tmpStrCat(name,
"_freq_locked"),
312 "real (locked) or custom (unlocked) CPU frequency",
315 motherboard.getCommandController(),
tmpStrCat(name,
"_freq"),
316 "custom CPU frequency (only valid when unlocked)",
317 T::CLOCK_FREQ, 1000000, 1000000000)
318 , freq(T::CLOCK_FREQ)
319 , tracingEnabled(traceSetting.getBoolean())
320 , isCMOS(motherboard.hasToshibaEngine())
322 static_assert(!std::is_polymorphic_v<CPUCore<T>>,
323 "keep CPUCore non-virtual to keep PC at offset 0");
330 assert(T::getTimeFast() <= time);
363 T::setMemPtr(0xFFFF);
393 assert(NMIStatus == 0);
394 assert(IRQStatus == 0);
416 if (exitLoop) [[unlikely]] {
431template<
typename T>
void CPUCore<T>::setSlowInstructions()
433 slowInstructions = 2;
439 assert(IRQStatus >= 0);
440 if (IRQStatus == 0) {
441 setSlowInstructions();
443 IRQStatus = IRQStatus + 1;
448 IRQStatus = IRQStatus - 1;
449 assert(IRQStatus >= 0);
454 assert(NMIStatus >= 0);
455 if (NMIStatus == 0) {
457 setSlowInstructions();
465 assert(NMIStatus >= 0);
481 return address == getPC();
486 assert(time >= getCurrentTime());
487 scheduler.schedule(time);
488 T::advanceTime(time);
494 EmuTime time2 = T::calcTime(time, cycles);
497 scheduler.schedule(time2);
507static constexpr char toHex(
byte x)
509 return narrow<char>((x < 10) ? (x +
'0') : (x - 10 +
'A'));
511static constexpr void toHex(
byte x, std::span<char, 3> buf)
513 buf[0] = toHex(x / 16);
514 buf[1] = toHex(x & 15);
520 word address = (tokens.size() < 3) ? getPC() :
word(tokens[2].getInt(interp));
521 std::array<byte, 4> outBuf;
522 std::string dasmOutput;
523 unsigned len =
dasm(*interface, address, outBuf, dasmOutput,
526 std::array<char, 3> tmp; tmp[2] = 0;
527 for (
auto i :
xrange(len)) {
528 toHex(outBuf[i], tmp);
537 }
else if (&
setting == &freqValue) {
539 }
else if (&
setting == &traceSetting) {
540 tracingEnabled = traceSetting.getBoolean();
552 if (freqLocked.getBoolean()) {
557 T::setFreq(freqValue.getInt());
562template<
typename T>
inline byte CPUCore<T>::READ_PORT(
word port,
unsigned cc)
564 EmuTime time = T::getTimeFast(cc);
565 scheduler.schedule(time);
566 byte result = interface->readIO(port, time);
571template<
typename T>
inline void CPUCore<T>::WRITE_PORT(
word port,
byte value,
unsigned cc)
573 EmuTime time = T::getTimeFast(cc);
574 scheduler.schedule(time);
575 interface->writeIO(port, value, time);
579template<
typename T>
template<
bool PRE_PB,
bool POST_PB>
585 if (readCacheLine[high] ==
nullptr) {
588 if (
const byte* line = interface->getReadCacheLine(addrBase)) {
590 T::template PRE_MEM<PRE_PB, POST_PB>(address);
591 T::template POST_MEM< POST_PB>(address);
592 readCacheLine[high] = line - addrBase;
593 return readCacheLine[high][address];
597 readCacheLine[high] =
reinterpret_cast<const byte*
>(1);
598 T::template PRE_MEM<PRE_PB, POST_PB>(address);
599 EmuTime time = T::getTimeFast(cc);
600 scheduler.schedule(time);
601 byte result = interface->readMem(narrow_cast<word>(address), time);
602 T::template POST_MEM<POST_PB>(address);
605template<
typename T>
template<
bool PRE_PB,
bool POST_PB>
609 if (uintptr_t(line) > 1) [[likely]] {
611 T::template PRE_MEM<PRE_PB, POST_PB>(address);
612 T::template POST_MEM< POST_PB>(address);
613 return line[address];
615 return RDMEMslow<PRE_PB, POST_PB>(address, cc);
618template<
typename T>
template<
bool PRE_PB,
bool POST_PB>
621 constexpr bool PRE = T::template Normalize<PRE_PB >::value;
622 constexpr bool POST = T::template Normalize<POST_PB>::value;
623 return RDMEM_impl2<PRE, POST>(address, cc);
636 unsigned address = narrow_cast<word>(getPC() + PC_OFFSET);
637 return RDMEM_impl<false, false>(address, cc);
641 return RDMEM_impl<true, true>(address, cc);
644template<
typename T>
template<
bool PRE_PB,
bool POST_PB>
647 auto res =
word(RDMEM_impl<PRE_PB, false>(address, cc));
648 res |=
word(RDMEM_impl<false, POST_PB>(narrow_cast<word>(address + 1), cc + T::CC_RDMEM) << 8);
651template<
typename T>
template<
bool PRE_PB,
bool POST_PB>
657 T::template PRE_WORD<PRE_PB, POST_PB>(address);
658 T::template POST_WORD< POST_PB>(address);
662 return RD_WORD_slow<PRE_PB, POST_PB>(address, cc);
665template<
typename T>
template<
bool PRE_PB,
bool POST_PB>
668 constexpr bool PRE = T::template Normalize<PRE_PB >::value;
669 constexpr bool POST = T::template Normalize<POST_PB>::value;
670 return RD_WORD_impl2<PRE, POST>(address, cc);
674 unsigned addr = narrow_cast<word>(getPC() + PC_OFFSET);
675 return RD_WORD_impl<false, false>(addr, cc);
678 unsigned address,
unsigned cc)
680 return RD_WORD_impl<true, true>(address, cc);
683template<
typename T>
template<
bool PRE_PB,
bool POST_PB>
689 if (writeCacheLine[high] ==
nullptr) {
692 if (
byte* line = interface->getWriteCacheLine(addrBase)) {
694 T::template PRE_MEM<PRE_PB, POST_PB>(address);
695 T::template POST_MEM< POST_PB>(address);
696 writeCacheLine[high] = line - addrBase;
697 writeCacheLine[high][address] = value;
702 writeCacheLine[high] =
reinterpret_cast<byte*
>(1);
703 T::template PRE_MEM<PRE_PB, POST_PB>(address);
704 EmuTime time = T::getTimeFast(cc);
705 scheduler.schedule(time);
706 interface->writeMem(narrow_cast<word>(address), value, time);
707 T::template POST_MEM<POST_PB>(address);
709template<
typename T>
template<
bool PRE_PB,
bool POST_PB>
711 unsigned address,
byte value,
unsigned cc)
714 if (uintptr_t(line) > 1) [[likely]] {
716 T::template PRE_MEM<PRE_PB, POST_PB>(address);
717 T::template POST_MEM< POST_PB>(address);
718 line[address] = value;
720 WRMEMslow<PRE_PB, POST_PB>(address, value, cc);
723template<
typename T>
template<
bool PRE_PB,
bool POST_PB>
725 unsigned address,
byte value,
unsigned cc)
727 constexpr bool PRE = T::template Normalize<PRE_PB >::value;
728 constexpr bool POST = T::template Normalize<POST_PB>::value;
729 WRMEM_impl2<PRE, POST>(address, value, cc);
732 unsigned address,
byte value,
unsigned cc)
734 WRMEM_impl<true, true>(address, value, cc);
737template<
typename T>
NEVER_INLINE void CPUCore<T>::WR_WORD_slow(
738 unsigned address,
word value,
unsigned cc)
740 WRMEM_impl<true, false>( address,
byte(value & 255), cc);
741 WRMEM_impl<false, true>(narrow_cast<word>(address + 1),
byte(value >> 8), cc + T::CC_WRMEM);
744 unsigned address,
word value,
unsigned cc)
749 T::template PRE_WORD<true, true>(address);
750 T::template POST_WORD< true>(address);
754 WR_WORD_slow(address, value, cc);
759template<
typename T>
template<
bool PRE_PB,
bool POST_PB>
761 unsigned address,
word value,
unsigned cc)
763 WRMEM_impl<PRE_PB, false>(narrow_cast<word>(address + 1),
byte(value >> 8), cc);
764 WRMEM_impl<false, POST_PB>( address,
byte(value & 255), cc + T::CC_WRMEM);
766template<
typename T>
template<
bool PRE_PB,
bool POST_PB>
768 unsigned address,
word value,
unsigned cc)
773 T::template PRE_WORD<PRE_PB, POST_PB>(address);
774 T::template POST_WORD< POST_PB>(address);
778 WR_WORD_rev_slow<PRE_PB, POST_PB>(address, value, cc);
781template<
typename T>
template<
bool PRE_PB,
bool POST_PB>
783 unsigned address,
word value,
unsigned cc)
785 constexpr bool PRE = T::template Normalize<PRE_PB >::value;
786 constexpr bool POST = T::template Normalize<POST_PB>::value;
787 WR_WORD_rev2<PRE, POST>(address, value, cc);
797 PUSH<T::EE_NMI_1>(getPC());
803template<
typename T>
inline void CPUCore<T>::irq0()
807 assert(interface->readIRQVector() == 0xFF);
812 PUSH<T::EE_IRQ0_1>(getPC());
814 T::setMemPtr(getPC());
819template<
typename T>
inline void CPUCore<T>::irq1()
825 PUSH<T::EE_IRQ1_1>(getPC());
827 T::setMemPtr(getPC());
832template<
typename T>
inline void CPUCore<T>::irq2()
838 PUSH<T::EE_IRQ2_1>(getPC());
839 unsigned x = interface->readIRQVector() | (getI() << 8);
840 setPC(RD_WORD(x, T::CC_IRQ2_2));
841 T::setMemPtr(getPC());
846void CPUCore<T>::executeInstructions()
848 checkNoCurrentFlags();
849#ifdef USE_COMPUTED_GOTO
852 static void* opcodeTable[256] = {
853 &&op00, &&op01, &&op02, &&op03, &&op04, &&op05, &&op06, &&op07,
854 &&op08, &&op09, &&op0A, &&op0B, &&op0C, &&op0D, &&op0E, &&op0F,
855 &&op10, &&op11, &&op12, &&op13, &&op14, &&op15, &&op16, &&op17,
856 &&op18, &&op19, &&op1A, &&op1B, &&op1C, &&op1D, &&op1E, &&op1F,
857 &&op20, &&op21, &&op22, &&op23, &&op24, &&op25, &&op26, &&op27,
858 &&op28, &&op29, &&op2A, &&op2B, &&op2C, &&op2D, &&op2E, &&op2F,
859 &&op30, &&op31, &&op32, &&op33, &&op34, &&op35, &&op36, &&op37,
860 &&op38, &&op39, &&op3A, &&op3B, &&op3C, &&op3D, &&op3E, &&op3F,
861 &&op00, &&op41, &&op42, &&op43, &&op44, &&op45, &&op46, &&op47,
862 &&op48, &&op00, &&op4A, &&op4B, &&op4C, &&op4D, &&op4E, &&op4F,
863 &&op50, &&op51, &&op00, &&op53, &&op54, &&op55, &&op56, &&op57,
864 &&op58, &&op59, &&op5A, &&op00, &&op5C, &&op5D, &&op5E, &&op5F,
865 &&op60, &&op61, &&op62, &&op63, &&op00, &&op65, &&op66, &&op67,
866 &&op68, &&op69, &&op6A, &&op6B, &&op6C, &&op00, &&op6E, &&op6F,
867 &&op70, &&op71, &&op72, &&op73, &&op74, &&op75, &&op76, &&op77,
868 &&op78, &&op79, &&op7A, &&op7B, &&op7C, &&op7D, &&op7E, &&op00,
869 &&op80, &&op81, &&op82, &&op83, &&op84, &&op85, &&op86, &&op87,
870 &&op88, &&op89, &&op8A, &&op8B, &&op8C, &&op8D, &&op8E, &&op8F,
871 &&op90, &&op91, &&op92, &&op93, &&op94, &&op95, &&op96, &&op97,
872 &&op98, &&op99, &&op9A, &&op9B, &&op9C, &&op9D, &&op9E, &&op9F,
873 &&opA0, &&opA1, &&opA2, &&opA3, &&opA4, &&opA5, &&opA6, &&opA7,
874 &&opA8, &&opA9, &&opAA, &&opAB, &&opAC, &&opAD, &&opAE, &&opAF,
875 &&opB0, &&opB1, &&opB2, &&opB3, &&opB4, &&opB5, &&opB6, &&opB7,
876 &&opB8, &&opB9, &&opBA, &&opBB, &&opBC, &&opBD, &&opBE, &&opBF,
877 &&opC0, &&opC1, &&opC2, &&opC3, &&opC4, &&opC5, &&opC6, &&opC7,
878 &&opC8, &&opC9, &&opCA, &&opCB, &&opCC, &&opCD, &&opCE, &&opCF,
879 &&opD0, &&opD1, &&opD2, &&opD3, &&opD4, &&opD5, &&opD6, &&opD7,
880 &&opD8, &&opD9, &&opDA, &&opDB, &&opDC, &&opDD, &&opDE, &&opDF,
881 &&opE0, &&opE1, &&opE2, &&opE3, &&opE4, &&opE5, &&opE6, &&opE7,
882 &&opE8, &&opE9, &&opEA, &&opEB, &&opEC, &&opED, &&opEE, &&opEF,
883 &&opF0, &&opF1, &&opF2, &&opF3, &&opF4, &&opF5, &&opF6, &&opF7,
884 &&opF8, &&opF9, &&opFA, &&opFB, &&opFC, &&opFD, &&opFE, &&opFF,
890 setPC(getPC() + ii.length); \
892 T::R800Refresh(*this); \
893 if (!T::limitReached()) [[likely]] { \
895 unsigned address = getPC(); \
896 const byte* line = readCacheLine[address >> CacheLine::BITS]; \
897 if (uintptr_t(line) > 1) [[likely]] { \
898 T::template PRE_MEM<false, false>(address); \
899 T::template POST_MEM< false>(address); \
900 byte op = line[address]; \
901 goto *(opcodeTable[op]); \
910 setPC(getPC() + ii.length); \
912 T::R800Refresh(*this); \
913 assert(T::limitReached()); \
917 setPC(getPC() + ii.length); \
920 assert(T::limitReached()); \
924#define CASE(X) op##X:
929 setPC(getPC() + ii.length); \
931 T::R800Refresh(*this); \
932 if (!T::limitReached()) [[likely]] { \
938 setPC(getPC() + ii.length); \
940 T::R800Refresh(*this); \
941 assert(T::limitReached()); \
945 setPC(getPC() + ii.length); \
948 assert(T::limitReached()); \
951#define CASE(X) case 0x##X:
955#ifndef USE_COMPUTED_GOTO
959 byte opcodeMain = RDMEM_OPCODE<0>(T::CC_MAIN);
961#ifdef USE_COMPUTED_GOTO
962 goto *(opcodeTable[opcodeMain]);
965 unsigned address = getPC();
966 byte opcodeSlow = RDMEMslow<false, false>(address, T::CC_MAIN);
967 goto *(opcodeTable[opcodeSlow]);
971#ifndef USE_COMPUTED_GOTO
973 switch (opcodeMain) {
987CASE(08) { II ii = ex_af_af();
NEXT; }
992CASE(20) { II ii = jr(CondNZ());
NEXT; }
993CASE(28) { II ii = jr(CondZ ());
NEXT; }
994CASE(30) { II ii = jr(CondNC());
NEXT; }
995CASE(38) { II ii = jr(CondC ());
NEXT; }
996CASE(18) { II ii = jr(CondTrue());
NEXT; }
998CASE(32) { II ii = ld_xbyte_a();
NEXT; }
1000CASE(22) { II ii = ld_xword_SS<HL,0>();
NEXT; }
1001CASE(2
A) { II ii = ld_SS_xword<HL,0>();
NEXT; }
1002CASE(02) { II ii = ld_SS_a<BC>();
NEXT; }
1003CASE(12) { II ii = ld_SS_a<DE>();
NEXT; }
1004CASE(1
A) { II ii = ld_a_SS<DE>();
NEXT; }
1005CASE(0
A) { II ii = ld_a_SS<BC>();
NEXT; }
1006CASE(03) { II ii = inc_SS<BC,0>();
NEXT; }
1007CASE(13) { II ii = inc_SS<DE,0>();
NEXT; }
1008CASE(23) { II ii = inc_SS<HL,0>();
NEXT; }
1009CASE(33) { II ii = inc_SS<SP,0>();
NEXT; }
1010CASE(0
B) { II ii = dec_SS<BC,0>();
NEXT; }
1011CASE(1
B) { II ii = dec_SS<DE,0>();
NEXT; }
1012CASE(2
B) { II ii = dec_SS<HL,0>();
NEXT; }
1013CASE(3
B) { II ii = dec_SS<SP,0>();
NEXT; }
1014CASE(09) { II ii = add_SS_TT<HL,BC,0>();
NEXT; }
1015CASE(19) { II ii = add_SS_TT<HL,DE,0>();
NEXT; }
1016CASE(29) { II ii = add_SS_SS<HL ,0>();
NEXT; }
1017CASE(39) { II ii = add_SS_TT<HL,SP,0>();
NEXT; }
1018CASE(01) { II ii = ld_SS_word<BC,0>();
NEXT; }
1019CASE(11) { II ii = ld_SS_word<DE,0>();
NEXT; }
1020CASE(21) { II ii = ld_SS_word<HL,0>();
NEXT; }
1021CASE(31) { II ii = ld_SS_word<SP,0>();
NEXT; }
1022CASE(04) { II ii = inc_R<B,0>();
NEXT; }
1024CASE(14) { II ii = inc_R<D,0>();
NEXT; }
1026CASE(24) { II ii = inc_R<H,0>();
NEXT; }
1029CASE(34) { II ii = inc_xhl();
NEXT; }
1030CASE(05) { II ii = dec_R<B,0>();
NEXT; }
1032CASE(15) { II ii = dec_R<D,0>();
NEXT; }
1034CASE(25) { II ii = dec_R<H,0>();
NEXT; }
1037CASE(35) { II ii = dec_xhl();
NEXT; }
1038CASE(06) { II ii = ld_R_byte<B,0>();
NEXT; }
1039CASE(0
E) { II ii = ld_R_byte<C,0>();
NEXT; }
1040CASE(16) { II ii = ld_R_byte<D,0>();
NEXT; }
1041CASE(1
E) { II ii = ld_R_byte<E,0>();
NEXT; }
1042CASE(26) { II ii = ld_R_byte<H,0>();
NEXT; }
1043CASE(2
E) { II ii = ld_R_byte<L,0>();
NEXT; }
1044CASE(3
E) { II ii = ld_R_byte<A,0>();
NEXT; }
1045CASE(36) { II ii = ld_xhl_byte();
NEXT; }
1047CASE(41) { II ii = ld_R_R<B,C,0>();
NEXT; }
1048CASE(42) { II ii = ld_R_R<B,D,0>();
NEXT; }
1049CASE(43) { II ii = ld_R_R<B,E,0>();
NEXT; }
1050CASE(44) { II ii = ld_R_R<B,H,0>();
NEXT; }
1051CASE(45) { II ii = ld_R_R<B,L,0>();
NEXT; }
1052CASE(47) { II ii = ld_R_R<B,A,0>();
NEXT; }
1053CASE(48) { II ii = ld_R_R<C,B,0>();
NEXT; }
1054CASE(4
A) { II ii = ld_R_R<C,D,0>();
NEXT; }
1055CASE(4
B) { II ii = ld_R_R<C,E,0>();
NEXT; }
1056CASE(4
C) { II ii = ld_R_R<C,H,0>();
NEXT; }
1057CASE(4
D) { II ii = ld_R_R<C,L,0>();
NEXT; }
1058CASE(4
F) { II ii = ld_R_R<C,A,0>();
NEXT; }
1059CASE(50) { II ii = ld_R_R<D,B,0>();
NEXT; }
1060CASE(51) { II ii = ld_R_R<D,C,0>();
NEXT; }
1061CASE(53) { II ii = ld_R_R<D,E,0>();
NEXT; }
1062CASE(54) { II ii = ld_R_R<D,H,0>();
NEXT; }
1063CASE(55) { II ii = ld_R_R<D,L,0>();
NEXT; }
1064CASE(57) { II ii = ld_R_R<D,A,0>();
NEXT; }
1065CASE(58) { II ii = ld_R_R<E,B,0>();
NEXT; }
1066CASE(59) { II ii = ld_R_R<E,C,0>();
NEXT; }
1067CASE(5
A) { II ii = ld_R_R<E,D,0>();
NEXT; }
1068CASE(5
C) { II ii = ld_R_R<E,H,0>();
NEXT; }
1069CASE(5
D) { II ii = ld_R_R<E,L,0>();
NEXT; }
1070CASE(5
F) { II ii = ld_R_R<E,A,0>();
NEXT; }
1071CASE(60) { II ii = ld_R_R<H,B,0>();
NEXT; }
1072CASE(61) { II ii = ld_R_R<H,C,0>();
NEXT; }
1073CASE(62) { II ii = ld_R_R<H,D,0>();
NEXT; }
1074CASE(63) { II ii = ld_R_R<H,E,0>();
NEXT; }
1075CASE(65) { II ii = ld_R_R<H,L,0>();
NEXT; }
1076CASE(67) { II ii = ld_R_R<H,A,0>();
NEXT; }
1077CASE(68) { II ii = ld_R_R<L,B,0>();
NEXT; }
1078CASE(69) { II ii = ld_R_R<L,C,0>();
NEXT; }
1079CASE(6
A) { II ii = ld_R_R<L,D,0>();
NEXT; }
1080CASE(6
B) { II ii = ld_R_R<L,E,0>();
NEXT; }
1081CASE(6
C) { II ii = ld_R_R<L,H,0>();
NEXT; }
1082CASE(6
F) { II ii = ld_R_R<L,A,0>();
NEXT; }
1083CASE(78) { II ii = ld_R_R<A,B,0>();
NEXT; }
1084CASE(79) { II ii = ld_R_R<A,C,0>();
NEXT; }
1085CASE(7
A) { II ii = ld_R_R<A,D,0>();
NEXT; }
1086CASE(7
B) { II ii = ld_R_R<A,E,0>();
NEXT; }
1087CASE(7
C) { II ii = ld_R_R<A,H,0>();
NEXT; }
1088CASE(7
D) { II ii = ld_R_R<A,L,0>();
NEXT; }
1089CASE(70) { II ii = ld_xhl_R<B>();
NEXT; }
1090CASE(71) { II ii = ld_xhl_R<C>();
NEXT; }
1091CASE(72) { II ii = ld_xhl_R<D>();
NEXT; }
1092CASE(73) { II ii = ld_xhl_R<E>();
NEXT; }
1093CASE(74) { II ii = ld_xhl_R<H>();
NEXT; }
1094CASE(75) { II ii = ld_xhl_R<L>();
NEXT; }
1095CASE(77) { II ii = ld_xhl_R<A>();
NEXT; }
1096CASE(46) { II ii = ld_R_xhl<B>();
NEXT; }
1097CASE(4
E) { II ii = ld_R_xhl<C>();
NEXT; }
1098CASE(56) { II ii = ld_R_xhl<D>();
NEXT; }
1099CASE(5
E) { II ii = ld_R_xhl<E>();
NEXT; }
1100CASE(66) { II ii = ld_R_xhl<H>();
NEXT; }
1101CASE(6
E) { II ii = ld_R_xhl<L>();
NEXT; }
1102CASE(7
E) { II ii = ld_R_xhl<A>();
NEXT; }
1105CASE(80) { II ii = add_a_R<B,0>();
NEXT; }
1106CASE(81) { II ii = add_a_R<C,0>();
NEXT; }
1107CASE(82) { II ii = add_a_R<D,0>();
NEXT; }
1108CASE(83) { II ii = add_a_R<E,0>();
NEXT; }
1109CASE(84) { II ii = add_a_R<H,0>();
NEXT; }
1110CASE(85) { II ii = add_a_R<L,0>();
NEXT; }
1111CASE(86) { II ii = add_a_xhl();
NEXT; }
1112CASE(87) { II ii = add_a_a();
NEXT; }
1113CASE(88) { II ii = adc_a_R<B,0>();
NEXT; }
1114CASE(89) { II ii = adc_a_R<C,0>();
NEXT; }
1115CASE(8
A) { II ii = adc_a_R<D,0>();
NEXT; }
1116CASE(8
B) { II ii = adc_a_R<E,0>();
NEXT; }
1117CASE(8
C) { II ii = adc_a_R<H,0>();
NEXT; }
1118CASE(8
D) { II ii = adc_a_R<L,0>();
NEXT; }
1121CASE(90) { II ii = sub_R<B,0>();
NEXT; }
1122CASE(91) { II ii = sub_R<C,0>();
NEXT; }
1123CASE(92) { II ii = sub_R<D,0>();
NEXT; }
1124CASE(93) { II ii = sub_R<E,0>();
NEXT; }
1125CASE(94) { II ii = sub_R<H,0>();
NEXT; }
1126CASE(95) { II ii = sub_R<L,0>();
NEXT; }
1127CASE(96) { II ii = sub_xhl();
NEXT; }
1129CASE(98) { II ii = sbc_a_R<B,0>();
NEXT; }
1130CASE(99) { II ii = sbc_a_R<C,0>();
NEXT; }
1131CASE(9
A) { II ii = sbc_a_R<D,0>();
NEXT; }
1132CASE(9
B) { II ii = sbc_a_R<E,0>();
NEXT; }
1133CASE(9
C) { II ii = sbc_a_R<H,0>();
NEXT; }
1134CASE(9
D) { II ii = sbc_a_R<L,0>();
NEXT; }
1137CASE(A0) { II ii = and_R<B,0>();
NEXT; }
1138CASE(A1) { II ii = and_R<C,0>();
NEXT; }
1140CASE(A3) { II ii = and_R<E,0>();
NEXT; }
1141CASE(A4) { II ii = and_R<H,0>();
NEXT; }
1142CASE(A5) { II ii = and_R<L,0>();
NEXT; }
1143CASE(A6) { II ii = and_xhl();
NEXT; }
1145CASE(A8) { II ii = xor_R<B,0>();
NEXT; }
1146CASE(A9) { II ii = xor_R<C,0>();
NEXT; }
1147CASE(AA) { II ii = xor_R<D,0>();
NEXT; }
1148CASE(AB) { II ii = xor_R<E,0>();
NEXT; }
1149CASE(AC) { II ii = xor_R<H,0>();
NEXT; }
1150CASE(AD) { II ii = xor_R<L,0>();
NEXT; }
1151CASE(AE) { II ii = xor_xhl();
NEXT; }
1161CASE(B8) { II ii = cp_R<B,0>();
NEXT; }
1162CASE(B9) { II ii = cp_R<C,0>();
NEXT; }
1163CASE(BA) { II ii = cp_R<D,0>();
NEXT; }
1164CASE(BB) { II ii = cp_R<E,0>();
NEXT; }
1166CASE(BD) { II ii = cp_R<L,0>();
NEXT; }
1167CASE(BE) { II ii = cp_xhl();
NEXT; }
1170CASE(D3) { II ii = out_byte_a();
NEXT; }
1171CASE(DB) { II ii = in_a_byte();
NEXT; }
1173CASE(E3) { II ii = ex_xsp_SS<HL,0>();
NEXT; }
1174CASE(EB) { II ii = ex_de_hl();
NEXT; }
1175CASE(E9) { II ii = jp_SS<HL,0>();
NEXT; }
1176CASE(F9) { II ii = ld_sp_SS<HL,0>();
NEXT; }
1179CASE(C6) { II ii = add_a_byte();
NEXT; }
1180CASE(CE) { II ii = adc_a_byte();
NEXT; }
1181CASE(D6) { II ii = sub_byte();
NEXT; }
1183CASE(E6) { II ii = and_byte();
NEXT; }
1184CASE(EE) { II ii = xor_byte();
NEXT; }
1185CASE(F6) { II ii = or_byte();
NEXT; }
1186CASE(FE) { II ii = cp_byte();
NEXT; }
1187CASE(C0) { II ii = ret(CondNZ());
NEXT; }
1188CASE(C8) { II ii = ret(CondZ ());
NEXT; }
1189CASE(D0) { II ii = ret(CondNC());
NEXT; }
1190CASE(D8) { II ii = ret(CondC ());
NEXT; }
1191CASE(E0) { II ii = ret(CondPO());
NEXT; }
1192CASE(E8) { II ii = ret(CondPE());
NEXT; }
1193CASE(F0) { II ii = ret(CondP ());
NEXT; }
1194CASE(F8) { II ii = ret(CondM ());
NEXT; }
1196CASE(C2) { II ii = jp(CondNZ());
NEXT; }
1197CASE(CA) { II ii = jp(CondZ ());
NEXT; }
1198CASE(D2) { II ii = jp(CondNC());
NEXT; }
1199CASE(DA) { II ii = jp(CondC ());
NEXT; }
1200CASE(E2) { II ii = jp(CondPO());
NEXT; }
1201CASE(EA) { II ii = jp(CondPE());
NEXT; }
1202CASE(F2) { II ii = jp(CondP ());
NEXT; }
1203CASE(FA) { II ii = jp(CondM ());
NEXT; }
1204CASE(C3) { II ii = jp(CondTrue());
NEXT; }
1205CASE(C4) { II ii = call(CondNZ());
NEXT; }
1206CASE(CC) { II ii = call(CondZ ());
NEXT; }
1207CASE(D4) { II ii = call(CondNC());
NEXT; }
1208CASE(DC) { II ii = call(CondC ());
NEXT; }
1209CASE(E4) { II ii = call(CondPO());
NEXT; }
1210CASE(EC) { II ii = call(CondPE());
NEXT; }
1211CASE(F4) { II ii = call(CondP ());
NEXT; }
1212CASE(FC) { II ii = call(CondM ());
NEXT; }
1213CASE(CD) { II ii = call(CondTrue());
NEXT; }
1214CASE(C1) { II ii = pop_SS <BC,0>();
NEXT; }
1215CASE(D1) { II ii = pop_SS <DE,0>();
NEXT; }
1216CASE(E1) { II ii = pop_SS <HL,0>();
NEXT; }
1217CASE(F1) { II ii = pop_SS <AF,0>();
NEXT; }
1218CASE(C5) { II ii = push_SS<BC,0>();
NEXT; }
1219CASE(D5) { II ii = push_SS<DE,0>();
NEXT; }
1220CASE(E5) { II ii = push_SS<HL,0>();
NEXT; }
1221CASE(F5) { II ii = push_SS<AF,0>();
NEXT; }
1222CASE(C7) { II ii = rst<0x00>();
NEXT; }
1223CASE(CF) { II ii = rst<0x08>();
NEXT; }
1224CASE(D7) { II ii = rst<0x10>();
NEXT; }
1225CASE(DF) { II ii = rst<0x18>();
NEXT; }
1226CASE(E7) { II ii = rst<0x20>();
NEXT; }
1227CASE(EF) { II ii = rst<0x28>();
NEXT; }
1228CASE(F7) { II ii = rst<0x30>();
NEXT; }
1229CASE(FF) { II ii = rst<0x38>();
NEXT; }
1232 byte cb_opcode = RDMEM_OPCODE<0>(T::CC_PREFIX);
1234 switch (cb_opcode) {
1235 case 0x00: { II ii = rlc_R<B>();
NEXT; }
1236 case 0x01: { II ii = rlc_R<C>();
NEXT; }
1237 case 0x02: { II ii = rlc_R<D>();
NEXT; }
1238 case 0x03: { II ii = rlc_R<E>();
NEXT; }
1239 case 0x04: { II ii = rlc_R<H>();
NEXT; }
1240 case 0x05: { II ii = rlc_R<L>();
NEXT; }
1241 case 0x07: { II ii = rlc_R<A>();
NEXT; }
1242 case 0x06: { II ii = rlc_xhl();
NEXT; }
1243 case 0x08: { II ii = rrc_R<B>();
NEXT; }
1244 case 0x09: { II ii = rrc_R<C>();
NEXT; }
1245 case 0x0a: { II ii = rrc_R<D>();
NEXT; }
1246 case 0x0b: { II ii = rrc_R<E>();
NEXT; }
1247 case 0x0c: { II ii = rrc_R<H>();
NEXT; }
1248 case 0x0d: { II ii = rrc_R<L>();
NEXT; }
1249 case 0x0f: { II ii = rrc_R<A>();
NEXT; }
1250 case 0x0e: { II ii = rrc_xhl();
NEXT; }
1251 case 0x10: { II ii = rl_R<B>();
NEXT; }
1252 case 0x11: { II ii = rl_R<C>();
NEXT; }
1253 case 0x12: { II ii = rl_R<D>();
NEXT; }
1254 case 0x13: { II ii = rl_R<E>();
NEXT; }
1255 case 0x14: { II ii = rl_R<H>();
NEXT; }
1256 case 0x15: { II ii = rl_R<L>();
NEXT; }
1257 case 0x17: { II ii = rl_R<A>();
NEXT; }
1258 case 0x16: { II ii = rl_xhl();
NEXT; }
1259 case 0x18: { II ii = rr_R<B>();
NEXT; }
1260 case 0x19: { II ii = rr_R<C>();
NEXT; }
1261 case 0x1a: { II ii = rr_R<D>();
NEXT; }
1262 case 0x1b: { II ii = rr_R<E>();
NEXT; }
1263 case 0x1c: { II ii = rr_R<H>();
NEXT; }
1264 case 0x1d: { II ii = rr_R<L>();
NEXT; }
1265 case 0x1f: { II ii = rr_R<A>();
NEXT; }
1266 case 0x1e: { II ii = rr_xhl();
NEXT; }
1267 case 0x20: { II ii = sla_R<B>();
NEXT; }
1268 case 0x21: { II ii = sla_R<C>();
NEXT; }
1269 case 0x22: { II ii = sla_R<D>();
NEXT; }
1270 case 0x23: { II ii = sla_R<E>();
NEXT; }
1271 case 0x24: { II ii = sla_R<H>();
NEXT; }
1272 case 0x25: { II ii = sla_R<L>();
NEXT; }
1273 case 0x27: { II ii = sla_R<A>();
NEXT; }
1274 case 0x26: { II ii = sla_xhl();
NEXT; }
1275 case 0x28: { II ii = sra_R<B>();
NEXT; }
1276 case 0x29: { II ii = sra_R<C>();
NEXT; }
1277 case 0x2a: { II ii = sra_R<D>();
NEXT; }
1278 case 0x2b: { II ii = sra_R<E>();
NEXT; }
1279 case 0x2c: { II ii = sra_R<H>();
NEXT; }
1280 case 0x2d: { II ii = sra_R<L>();
NEXT; }
1281 case 0x2f: { II ii = sra_R<A>();
NEXT; }
1282 case 0x2e: { II ii = sra_xhl();
NEXT; }
1283 case 0x30: { II ii = T::IS_R800 ? sla_R<B>() : sll_R<
B>();
NEXT; }
1284 case 0x31: { II ii = T::IS_R800 ? sla_R<C>() : sll_R<
C>();
NEXT; }
1285 case 0x32: { II ii = T::IS_R800 ? sla_R<D>() : sll_R<
D>();
NEXT; }
1286 case 0x33: { II ii = T::IS_R800 ? sla_R<E>() : sll_R<
E>();
NEXT; }
1287 case 0x34: { II ii = T::IS_R800 ? sla_R<H>() : sll_R<
H>();
NEXT; }
1288 case 0x35: { II ii = T::IS_R800 ? sla_R<L>() : sll_R<
L>();
NEXT; }
1289 case 0x37: { II ii = T::IS_R800 ? sla_R<A>() : sll_R<
A>();
NEXT; }
1290 case 0x36: { II ii = T::IS_R800 ? sla_xhl() : sll_xhl();
NEXT; }
1291 case 0x38: { II ii = srl_R<B>();
NEXT; }
1292 case 0x39: { II ii = srl_R<C>();
NEXT; }
1293 case 0x3a: { II ii = srl_R<D>();
NEXT; }
1294 case 0x3b: { II ii = srl_R<E>();
NEXT; }
1295 case 0x3c: { II ii = srl_R<H>();
NEXT; }
1296 case 0x3d: { II ii = srl_R<L>();
NEXT; }
1297 case 0x3f: { II ii = srl_R<A>();
NEXT; }
1298 case 0x3e: { II ii = srl_xhl();
NEXT; }
1300 case 0x40: { II ii = bit_N_R<0,B>();
NEXT; }
1301 case 0x41: { II ii = bit_N_R<0,C>();
NEXT; }
1302 case 0x42: { II ii = bit_N_R<0,D>();
NEXT; }
1303 case 0x43: { II ii = bit_N_R<0,E>();
NEXT; }
1304 case 0x44: { II ii = bit_N_R<0,H>();
NEXT; }
1305 case 0x45: { II ii = bit_N_R<0,L>();
NEXT; }
1306 case 0x47: { II ii = bit_N_R<0,A>();
NEXT; }
1307 case 0x48: { II ii = bit_N_R<1,B>();
NEXT; }
1308 case 0x49: { II ii = bit_N_R<1,C>();
NEXT; }
1309 case 0x4a: { II ii = bit_N_R<1,D>();
NEXT; }
1310 case 0x4b: { II ii = bit_N_R<1,E>();
NEXT; }
1311 case 0x4c: { II ii = bit_N_R<1,H>();
NEXT; }
1312 case 0x4d: { II ii = bit_N_R<1,L>();
NEXT; }
1313 case 0x4f: { II ii = bit_N_R<1,A>();
NEXT; }
1314 case 0x50: { II ii = bit_N_R<2,B>();
NEXT; }
1315 case 0x51: { II ii = bit_N_R<2,C>();
NEXT; }
1316 case 0x52: { II ii = bit_N_R<2,D>();
NEXT; }
1317 case 0x53: { II ii = bit_N_R<2,E>();
NEXT; }
1318 case 0x54: { II ii = bit_N_R<2,H>();
NEXT; }
1319 case 0x55: { II ii = bit_N_R<2,L>();
NEXT; }
1320 case 0x57: { II ii = bit_N_R<2,A>();
NEXT; }
1321 case 0x58: { II ii = bit_N_R<3,B>();
NEXT; }
1322 case 0x59: { II ii = bit_N_R<3,C>();
NEXT; }
1323 case 0x5a: { II ii = bit_N_R<3,D>();
NEXT; }
1324 case 0x5b: { II ii = bit_N_R<3,E>();
NEXT; }
1325 case 0x5c: { II ii = bit_N_R<3,H>();
NEXT; }
1326 case 0x5d: { II ii = bit_N_R<3,L>();
NEXT; }
1327 case 0x5f: { II ii = bit_N_R<3,A>();
NEXT; }
1328 case 0x60: { II ii = bit_N_R<4,B>();
NEXT; }
1329 case 0x61: { II ii = bit_N_R<4,C>();
NEXT; }
1330 case 0x62: { II ii = bit_N_R<4,D>();
NEXT; }
1331 case 0x63: { II ii = bit_N_R<4,E>();
NEXT; }
1332 case 0x64: { II ii = bit_N_R<4,H>();
NEXT; }
1333 case 0x65: { II ii = bit_N_R<4,L>();
NEXT; }
1334 case 0x67: { II ii = bit_N_R<4,A>();
NEXT; }
1335 case 0x68: { II ii = bit_N_R<5,B>();
NEXT; }
1336 case 0x69: { II ii = bit_N_R<5,C>();
NEXT; }
1337 case 0x6a: { II ii = bit_N_R<5,D>();
NEXT; }
1338 case 0x6b: { II ii = bit_N_R<5,E>();
NEXT; }
1339 case 0x6c: { II ii = bit_N_R<5,H>();
NEXT; }
1340 case 0x6d: { II ii = bit_N_R<5,L>();
NEXT; }
1341 case 0x6f: { II ii = bit_N_R<5,A>();
NEXT; }
1342 case 0x70: { II ii = bit_N_R<6,B>();
NEXT; }
1343 case 0x71: { II ii = bit_N_R<6,C>();
NEXT; }
1344 case 0x72: { II ii = bit_N_R<6,D>();
NEXT; }
1345 case 0x73: { II ii = bit_N_R<6,E>();
NEXT; }
1346 case 0x74: { II ii = bit_N_R<6,H>();
NEXT; }
1347 case 0x75: { II ii = bit_N_R<6,L>();
NEXT; }
1348 case 0x77: { II ii = bit_N_R<6,A>();
NEXT; }
1349 case 0x78: { II ii = bit_N_R<7,B>();
NEXT; }
1350 case 0x79: { II ii = bit_N_R<7,C>();
NEXT; }
1351 case 0x7a: { II ii = bit_N_R<7,D>();
NEXT; }
1352 case 0x7b: { II ii = bit_N_R<7,E>();
NEXT; }
1353 case 0x7c: { II ii = bit_N_R<7,H>();
NEXT; }
1354 case 0x7d: { II ii = bit_N_R<7,L>();
NEXT; }
1355 case 0x7f: { II ii = bit_N_R<7,A>();
NEXT; }
1356 case 0x46: { II ii = bit_N_xhl<0>();
NEXT; }
1357 case 0x4e: { II ii = bit_N_xhl<1>();
NEXT; }
1358 case 0x56: { II ii = bit_N_xhl<2>();
NEXT; }
1359 case 0x5e: { II ii = bit_N_xhl<3>();
NEXT; }
1360 case 0x66: { II ii = bit_N_xhl<4>();
NEXT; }
1361 case 0x6e: { II ii = bit_N_xhl<5>();
NEXT; }
1362 case 0x76: { II ii = bit_N_xhl<6>();
NEXT; }
1363 case 0x7e: { II ii = bit_N_xhl<7>();
NEXT; }
1365 case 0x80: { II ii = res_N_R<0,B>();
NEXT; }
1366 case 0x81: { II ii = res_N_R<0,C>();
NEXT; }
1367 case 0x82: { II ii = res_N_R<0,D>();
NEXT; }
1368 case 0x83: { II ii = res_N_R<0,E>();
NEXT; }
1369 case 0x84: { II ii = res_N_R<0,H>();
NEXT; }
1370 case 0x85: { II ii = res_N_R<0,L>();
NEXT; }
1371 case 0x87: { II ii = res_N_R<0,A>();
NEXT; }
1372 case 0x88: { II ii = res_N_R<1,B>();
NEXT; }
1373 case 0x89: { II ii = res_N_R<1,C>();
NEXT; }
1374 case 0x8a: { II ii = res_N_R<1,D>();
NEXT; }
1375 case 0x8b: { II ii = res_N_R<1,E>();
NEXT; }
1376 case 0x8c: { II ii = res_N_R<1,H>();
NEXT; }
1377 case 0x8d: { II ii = res_N_R<1,L>();
NEXT; }
1378 case 0x8f: { II ii = res_N_R<1,A>();
NEXT; }
1379 case 0x90: { II ii = res_N_R<2,B>();
NEXT; }
1380 case 0x91: { II ii = res_N_R<2,C>();
NEXT; }
1381 case 0x92: { II ii = res_N_R<2,D>();
NEXT; }
1382 case 0x93: { II ii = res_N_R<2,E>();
NEXT; }
1383 case 0x94: { II ii = res_N_R<2,H>();
NEXT; }
1384 case 0x95: { II ii = res_N_R<2,L>();
NEXT; }
1385 case 0x97: { II ii = res_N_R<2,A>();
NEXT; }
1386 case 0x98: { II ii = res_N_R<3,B>();
NEXT; }
1387 case 0x99: { II ii = res_N_R<3,C>();
NEXT; }
1388 case 0x9a: { II ii = res_N_R<3,D>();
NEXT; }
1389 case 0x9b: { II ii = res_N_R<3,E>();
NEXT; }
1390 case 0x9c: { II ii = res_N_R<3,H>();
NEXT; }
1391 case 0x9d: { II ii = res_N_R<3,L>();
NEXT; }
1392 case 0x9f: { II ii = res_N_R<3,A>();
NEXT; }
1393 case 0xa0: { II ii = res_N_R<4,B>();
NEXT; }
1394 case 0xa1: { II ii = res_N_R<4,C>();
NEXT; }
1395 case 0xa2: { II ii = res_N_R<4,D>();
NEXT; }
1396 case 0xa3: { II ii = res_N_R<4,E>();
NEXT; }
1397 case 0xa4: { II ii = res_N_R<4,H>();
NEXT; }
1398 case 0xa5: { II ii = res_N_R<4,L>();
NEXT; }
1399 case 0xa7: { II ii = res_N_R<4,A>();
NEXT; }
1400 case 0xa8: { II ii = res_N_R<5,B>();
NEXT; }
1401 case 0xa9: { II ii = res_N_R<5,C>();
NEXT; }
1402 case 0xaa: { II ii = res_N_R<5,D>();
NEXT; }
1403 case 0xab: { II ii = res_N_R<5,E>();
NEXT; }
1404 case 0xac: { II ii = res_N_R<5,H>();
NEXT; }
1405 case 0xad: { II ii = res_N_R<5,L>();
NEXT; }
1406 case 0xaf: { II ii = res_N_R<5,A>();
NEXT; }
1407 case 0xb0: { II ii = res_N_R<6,B>();
NEXT; }
1408 case 0xb1: { II ii = res_N_R<6,C>();
NEXT; }
1409 case 0xb2: { II ii = res_N_R<6,D>();
NEXT; }
1410 case 0xb3: { II ii = res_N_R<6,E>();
NEXT; }
1411 case 0xb4: { II ii = res_N_R<6,H>();
NEXT; }
1412 case 0xb5: { II ii = res_N_R<6,L>();
NEXT; }
1413 case 0xb7: { II ii = res_N_R<6,A>();
NEXT; }
1414 case 0xb8: { II ii = res_N_R<7,B>();
NEXT; }
1415 case 0xb9: { II ii = res_N_R<7,C>();
NEXT; }
1416 case 0xba: { II ii = res_N_R<7,D>();
NEXT; }
1417 case 0xbb: { II ii = res_N_R<7,E>();
NEXT; }
1418 case 0xbc: { II ii = res_N_R<7,H>();
NEXT; }
1419 case 0xbd: { II ii = res_N_R<7,L>();
NEXT; }
1420 case 0xbf: { II ii = res_N_R<7,A>();
NEXT; }
1421 case 0x86: { II ii = res_N_xhl<0>();
NEXT; }
1422 case 0x8e: { II ii = res_N_xhl<1>();
NEXT; }
1423 case 0x96: { II ii = res_N_xhl<2>();
NEXT; }
1424 case 0x9e: { II ii = res_N_xhl<3>();
NEXT; }
1425 case 0xa6: { II ii = res_N_xhl<4>();
NEXT; }
1426 case 0xae: { II ii = res_N_xhl<5>();
NEXT; }
1427 case 0xb6: { II ii = res_N_xhl<6>();
NEXT; }
1428 case 0xbe: { II ii = res_N_xhl<7>();
NEXT; }
1430 case 0xc0: { II ii = set_N_R<0,B>();
NEXT; }
1431 case 0xc1: { II ii = set_N_R<0,C>();
NEXT; }
1432 case 0xc2: { II ii = set_N_R<0,D>();
NEXT; }
1433 case 0xc3: { II ii = set_N_R<0,E>();
NEXT; }
1434 case 0xc4: { II ii = set_N_R<0,H>();
NEXT; }
1435 case 0xc5: { II ii = set_N_R<0,L>();
NEXT; }
1436 case 0xc7: { II ii = set_N_R<0,A>();
NEXT; }
1437 case 0xc8: { II ii = set_N_R<1,B>();
NEXT; }
1438 case 0xc9: { II ii = set_N_R<1,C>();
NEXT; }
1439 case 0xca: { II ii = set_N_R<1,D>();
NEXT; }
1440 case 0xcb: { II ii = set_N_R<1,E>();
NEXT; }
1441 case 0xcc: { II ii = set_N_R<1,H>();
NEXT; }
1442 case 0xcd: { II ii = set_N_R<1,L>();
NEXT; }
1443 case 0xcf: { II ii = set_N_R<1,A>();
NEXT; }
1444 case 0xd0: { II ii = set_N_R<2,B>();
NEXT; }
1445 case 0xd1: { II ii = set_N_R<2,C>();
NEXT; }
1446 case 0xd2: { II ii = set_N_R<2,D>();
NEXT; }
1447 case 0xd3: { II ii = set_N_R<2,E>();
NEXT; }
1448 case 0xd4: { II ii = set_N_R<2,H>();
NEXT; }
1449 case 0xd5: { II ii = set_N_R<2,L>();
NEXT; }
1450 case 0xd7: { II ii = set_N_R<2,A>();
NEXT; }
1451 case 0xd8: { II ii = set_N_R<3,B>();
NEXT; }
1452 case 0xd9: { II ii = set_N_R<3,C>();
NEXT; }
1453 case 0xda: { II ii = set_N_R<3,D>();
NEXT; }
1454 case 0xdb: { II ii = set_N_R<3,E>();
NEXT; }
1455 case 0xdc: { II ii = set_N_R<3,H>();
NEXT; }
1456 case 0xdd: { II ii = set_N_R<3,L>();
NEXT; }
1457 case 0xdf: { II ii = set_N_R<3,A>();
NEXT; }
1458 case 0xe0: { II ii = set_N_R<4,B>();
NEXT; }
1459 case 0xe1: { II ii = set_N_R<4,C>();
NEXT; }
1460 case 0xe2: { II ii = set_N_R<4,D>();
NEXT; }
1461 case 0xe3: { II ii = set_N_R<4,E>();
NEXT; }
1462 case 0xe4: { II ii = set_N_R<4,H>();
NEXT; }
1463 case 0xe5: { II ii = set_N_R<4,L>();
NEXT; }
1464 case 0xe7: { II ii = set_N_R<4,A>();
NEXT; }
1465 case 0xe8: { II ii = set_N_R<5,B>();
NEXT; }
1466 case 0xe9: { II ii = set_N_R<5,C>();
NEXT; }
1467 case 0xea: { II ii = set_N_R<5,D>();
NEXT; }
1468 case 0xeb: { II ii = set_N_R<5,E>();
NEXT; }
1469 case 0xec: { II ii = set_N_R<5,H>();
NEXT; }
1470 case 0xed: { II ii = set_N_R<5,L>();
NEXT; }
1471 case 0xef: { II ii = set_N_R<5,A>();
NEXT; }
1472 case 0xf0: { II ii = set_N_R<6,B>();
NEXT; }
1473 case 0xf1: { II ii = set_N_R<6,C>();
NEXT; }
1474 case 0xf2: { II ii = set_N_R<6,D>();
NEXT; }
1475 case 0xf3: { II ii = set_N_R<6,E>();
NEXT; }
1476 case 0xf4: { II ii = set_N_R<6,H>();
NEXT; }
1477 case 0xf5: { II ii = set_N_R<6,L>();
NEXT; }
1478 case 0xf7: { II ii = set_N_R<6,A>();
NEXT; }
1479 case 0xf8: { II ii = set_N_R<7,B>();
NEXT; }
1480 case 0xf9: { II ii = set_N_R<7,C>();
NEXT; }
1481 case 0xfa: { II ii = set_N_R<7,D>();
NEXT; }
1482 case 0xfb: { II ii = set_N_R<7,E>();
NEXT; }
1483 case 0xfc: { II ii = set_N_R<7,H>();
NEXT; }
1484 case 0xfd: { II ii = set_N_R<7,L>();
NEXT; }
1485 case 0xff: { II ii = set_N_R<7,A>();
NEXT; }
1486 case 0xc6: { II ii = set_N_xhl<0>();
NEXT; }
1487 case 0xce: { II ii = set_N_xhl<1>();
NEXT; }
1488 case 0xd6: { II ii = set_N_xhl<2>();
NEXT; }
1489 case 0xde: { II ii = set_N_xhl<3>();
NEXT; }
1490 case 0xe6: { II ii = set_N_xhl<4>();
NEXT; }
1491 case 0xee: { II ii = set_N_xhl<5>();
NEXT; }
1492 case 0xf6: { II ii = set_N_xhl<6>();
NEXT; }
1493 case 0xfe: { II ii = set_N_xhl<7>();
NEXT; }
1499 byte ed_opcode = RDMEM_OPCODE<0>(T::CC_PREFIX);
1501 switch (ed_opcode) {
1502 case 0x00:
case 0x01:
case 0x02:
case 0x03:
1503 case 0x04:
case 0x05:
case 0x06:
case 0x07:
1504 case 0x08:
case 0x09:
case 0x0a:
case 0x0b:
1505 case 0x0c:
case 0x0d:
case 0x0e:
case 0x0f:
1506 case 0x10:
case 0x11:
case 0x12:
case 0x13:
1507 case 0x14:
case 0x15:
case 0x16:
case 0x17:
1508 case 0x18:
case 0x19:
case 0x1a:
case 0x1b:
1509 case 0x1c:
case 0x1d:
case 0x1e:
case 0x1f:
1510 case 0x20:
case 0x21:
case 0x22:
case 0x23:
1511 case 0x24:
case 0x25:
case 0x26:
case 0x27:
1512 case 0x28:
case 0x29:
case 0x2a:
case 0x2b:
1513 case 0x2c:
case 0x2d:
case 0x2e:
case 0x2f:
1514 case 0x30:
case 0x31:
case 0x32:
case 0x33:
1515 case 0x34:
case 0x35:
case 0x36:
case 0x37:
1516 case 0x38:
case 0x39:
case 0x3a:
case 0x3b:
1517 case 0x3c:
case 0x3d:
case 0x3e:
case 0x3f:
1519 case 0x77:
case 0x7f:
1521 case 0x80:
case 0x81:
case 0x82:
case 0x83:
1522 case 0x84:
case 0x85:
case 0x86:
case 0x87:
1523 case 0x88:
case 0x89:
case 0x8a:
case 0x8b:
1524 case 0x8c:
case 0x8d:
case 0x8e:
case 0x8f:
1525 case 0x90:
case 0x91:
case 0x92:
case 0x93:
1526 case 0x94:
case 0x95:
case 0x96:
case 0x97:
1527 case 0x98:
case 0x99:
case 0x9a:
case 0x9b:
1528 case 0x9c:
case 0x9d:
case 0x9e:
case 0x9f:
1529 case 0xa4:
case 0xa5:
case 0xa6:
case 0xa7:
1530 case 0xac:
case 0xad:
case 0xae:
case 0xaf:
1531 case 0xb4:
case 0xb5:
case 0xb6:
case 0xb7:
1532 case 0xbc:
case 0xbd:
case 0xbe:
case 0xbf:
1534 case 0xc0:
case 0xc2:
1535 case 0xc4:
case 0xc5:
case 0xc6:
case 0xc7:
1536 case 0xc8:
case 0xca:
case 0xcb:
1537 case 0xcc:
case 0xcd:
case 0xce:
case 0xcf:
1538 case 0xd0:
case 0xd2:
case 0xd3:
1539 case 0xd4:
case 0xd5:
case 0xd6:
case 0xd7:
1540 case 0xd8:
case 0xda:
case 0xdb:
1541 case 0xdc:
case 0xdd:
case 0xde:
case 0xdf:
1542 case 0xe0:
case 0xe1:
case 0xe2:
case 0xe3:
1543 case 0xe4:
case 0xe5:
case 0xe6:
case 0xe7:
1544 case 0xe8:
case 0xe9:
case 0xea:
case 0xeb:
1545 case 0xec:
case 0xed:
case 0xee:
case 0xef:
1546 case 0xf0:
case 0xf1:
case 0xf2:
1547 case 0xf4:
case 0xf5:
case 0xf6:
case 0xf7:
1548 case 0xf8:
case 0xf9:
case 0xfa:
case 0xfb:
1549 case 0xfc:
case 0xfd:
case 0xfe:
case 0xff:
1550 { II ii = nop();
NEXT; }
1552 case 0x40: { II ii = in_R_c<B>();
NEXT; }
1553 case 0x48: { II ii = in_R_c<C>();
NEXT; }
1554 case 0x50: { II ii = in_R_c<D>();
NEXT; }
1555 case 0x58: { II ii = in_R_c<E>();
NEXT; }
1556 case 0x60: { II ii = in_R_c<H>();
NEXT; }
1557 case 0x68: { II ii = in_R_c<L>();
NEXT; }
1558 case 0x70: { II ii = in_R_c<DUMMY>();
NEXT; }
1559 case 0x78: { II ii = in_R_c<A>();
NEXT; }
1561 case 0x41: { II ii = out_c_R<B>();
NEXT; }
1562 case 0x49: { II ii = out_c_R<C>();
NEXT; }
1563 case 0x51: { II ii = out_c_R<D>();
NEXT; }
1564 case 0x59: { II ii = out_c_R<E>();
NEXT; }
1565 case 0x61: { II ii = out_c_R<H>();
NEXT; }
1566 case 0x69: { II ii = out_c_R<L>();
NEXT; }
1567 case 0x71: { II ii = out_c_0();
NEXT; }
1568 case 0x79: { II ii = out_c_R<A>();
NEXT; }
1570 case 0x42: { II ii = sbc_hl_SS<BC>();
NEXT; }
1571 case 0x52: { II ii = sbc_hl_SS<DE>();
NEXT; }
1572 case 0x62: { II ii = sbc_hl_hl ();
NEXT; }
1573 case 0x72: { II ii = sbc_hl_SS<SP>();
NEXT; }
1575 case 0x4a: { II ii = adc_hl_SS<BC>();
NEXT; }
1576 case 0x5a: { II ii = adc_hl_SS<DE>();
NEXT; }
1577 case 0x6a: { II ii = adc_hl_hl ();
NEXT; }
1578 case 0x7a: { II ii = adc_hl_SS<SP>();
NEXT; }
1580 case 0x43: { II ii = ld_xword_SS_ED<BC>();
NEXT; }
1581 case 0x53: { II ii = ld_xword_SS_ED<DE>();
NEXT; }
1582 case 0x63: { II ii = ld_xword_SS_ED<HL>();
NEXT; }
1583 case 0x73: { II ii = ld_xword_SS_ED<SP>();
NEXT; }
1585 case 0x4b: { II ii = ld_SS_xword_ED<BC>();
NEXT; }
1586 case 0x5b: { II ii = ld_SS_xword_ED<DE>();
NEXT; }
1587 case 0x6b: { II ii = ld_SS_xword_ED<HL>();
NEXT; }
1588 case 0x7b: { II ii = ld_SS_xword_ED<SP>();
NEXT; }
1590 case 0x47: { II ii = ld_i_a();
NEXT; }
1591 case 0x4f: { II ii = ld_r_a();
NEXT; }
1592 case 0x57: { II ii = ld_a_IR<REG_I>();
if (T::IS_R800) {
NEXT; }
else {
NEXT_STOP; }}
1593 case 0x5f: { II ii = ld_a_IR<REG_R>();
if (T::IS_R800) {
NEXT; }
else {
NEXT_STOP; }}
1595 case 0x67: { II ii = rrd();
NEXT; }
1596 case 0x6f: { II ii = rld();
NEXT; }
1598 case 0x45:
case 0x4d:
case 0x55:
case 0x5d:
1599 case 0x65:
case 0x6d:
case 0x75:
case 0x7d:
1601 case 0x46:
case 0x4e:
case 0x66:
case 0x6e:
1602 { II ii = im_N<0>();
NEXT; }
1603 case 0x56:
case 0x76:
1604 { II ii = im_N<1>();
NEXT; }
1605 case 0x5e:
case 0x7e:
1606 { II ii = im_N<2>();
NEXT; }
1607 case 0x44:
case 0x4c:
case 0x54:
case 0x5c:
1608 case 0x64:
case 0x6c:
case 0x74:
case 0x7c:
1609 { II ii = neg();
NEXT; }
1611 case 0xa0: { II ii = ldi();
NEXT; }
1612 case 0xa1: { II ii = cpi();
NEXT; }
1613 case 0xa2: { II ii = ini();
NEXT; }
1614 case 0xa3: { II ii = outi();
NEXT; }
1615 case 0xa8: { II ii = ldd();
NEXT; }
1616 case 0xa9: { II ii = cpd();
NEXT; }
1617 case 0xaa: { II ii = ind();
NEXT; }
1618 case 0xab: { II ii = outd();
NEXT; }
1619 case 0xb0: { II ii = ldir();
NEXT; }
1620 case 0xb1: { II ii = cpir();
NEXT; }
1621 case 0xb2: { II ii = inir();
NEXT; }
1622 case 0xb3: { II ii = otir();
NEXT; }
1623 case 0xb8: { II ii = lddr();
NEXT; }
1624 case 0xb9: { II ii = cpdr();
NEXT; }
1625 case 0xba: { II ii = indr();
NEXT; }
1626 case 0xbb: { II ii = otdr();
NEXT; }
1628 case 0xc1: { II ii = T::IS_R800 ? mulub_a_R<B>() : nop();
NEXT; }
1629 case 0xc9: { II ii = T::IS_R800 ? mulub_a_R<C>() : nop();
NEXT; }
1630 case 0xd1: { II ii = T::IS_R800 ? mulub_a_R<D>() : nop();
NEXT; }
1631 case 0xd9: { II ii = T::IS_R800 ? mulub_a_R<E>() : nop();
NEXT; }
1632 case 0xc3: { II ii = T::IS_R800 ? muluw_hl_SS<BC>() : nop();
NEXT; }
1633 case 0xf3: { II ii = T::IS_R800 ? muluw_hl_SS<SP>() : nop();
NEXT; }
1640 byte opcodeDD = RDMEM_OPCODE<0>(T::CC_DD + T::CC_MAIN);
1816 if constexpr (T::IS_R800) {
1817 II ii = nop<T::CC_DD>();
NEXT;
1820 #ifdef USE_COMPUTED_GOTO
1821 goto *(opcodeTable[opcodeDD]);
1823 opcodeMain = opcodeDD;
1828 case 0x09: { II ii = add_SS_TT<IX,BC,T::CC_DD>();
NEXT; }
1829 case 0x19: { II ii = add_SS_TT<IX,DE,T::CC_DD>();
NEXT; }
1830 case 0x29: { II ii = add_SS_SS<IX ,T::CC_DD>();
NEXT; }
1831 case 0x39: { II ii = add_SS_TT<IX,SP,T::CC_DD>();
NEXT; }
1832 case 0x21: { II ii = ld_SS_word<IX,T::CC_DD>();
NEXT; }
1833 case 0x22: { II ii = ld_xword_SS<IX,T::CC_DD>();
NEXT; }
1834 case 0x2a: { II ii = ld_SS_xword<IX,T::CC_DD>();
NEXT; }
1835 case 0x23: { II ii = inc_SS<IX,T::CC_DD>();
NEXT; }
1836 case 0x2b: { II ii = dec_SS<IX,T::CC_DD>();
NEXT; }
1837 case 0x24: { II ii = inc_R<IXH,T::CC_DD>();
NEXT; }
1838 case 0x2c: { II ii = inc_R<IXL,T::CC_DD>();
NEXT; }
1839 case 0x25: { II ii = dec_R<IXH,T::CC_DD>();
NEXT; }
1840 case 0x2d: { II ii = dec_R<IXL,T::CC_DD>();
NEXT; }
1841 case 0x26: { II ii = ld_R_byte<IXH,T::CC_DD>();
NEXT; }
1842 case 0x2e: { II ii = ld_R_byte<IXL,T::CC_DD>();
NEXT; }
1843 case 0x34: { II ii = inc_xix<IX>();
NEXT; }
1844 case 0x35: { II ii = dec_xix<IX>();
NEXT; }
1845 case 0x36: { II ii = ld_xix_byte<IX>();
NEXT; }
1847 case 0x44: { II ii = ld_R_R<B,IXH,T::CC_DD>();
NEXT; }
1848 case 0x45: { II ii = ld_R_R<B,IXL,T::CC_DD>();
NEXT; }
1849 case 0x4c: { II ii = ld_R_R<C,IXH,T::CC_DD>();
NEXT; }
1850 case 0x4d: { II ii = ld_R_R<C,IXL,T::CC_DD>();
NEXT; }
1851 case 0x54: { II ii = ld_R_R<D,IXH,T::CC_DD>();
NEXT; }
1852 case 0x55: { II ii = ld_R_R<D,IXL,T::CC_DD>();
NEXT; }
1853 case 0x5c: { II ii = ld_R_R<E,IXH,T::CC_DD>();
NEXT; }
1854 case 0x5d: { II ii = ld_R_R<E,IXL,T::CC_DD>();
NEXT; }
1855 case 0x7c: { II ii = ld_R_R<A,IXH,T::CC_DD>();
NEXT; }
1856 case 0x7d: { II ii = ld_R_R<A,IXL,T::CC_DD>();
NEXT; }
1857 case 0x60: { II ii = ld_R_R<IXH,B,T::CC_DD>();
NEXT; }
1858 case 0x61: { II ii = ld_R_R<IXH,C,T::CC_DD>();
NEXT; }
1859 case 0x62: { II ii = ld_R_R<IXH,D,T::CC_DD>();
NEXT; }
1860 case 0x63: { II ii = ld_R_R<IXH,E,T::CC_DD>();
NEXT; }
1861 case 0x65: { II ii = ld_R_R<IXH,IXL,T::CC_DD>();
NEXT; }
1862 case 0x67: { II ii = ld_R_R<IXH,A,T::CC_DD>();
NEXT; }
1863 case 0x68: { II ii = ld_R_R<IXL,B,T::CC_DD>();
NEXT; }
1864 case 0x69: { II ii = ld_R_R<IXL,C,T::CC_DD>();
NEXT; }
1865 case 0x6a: { II ii = ld_R_R<IXL,D,T::CC_DD>();
NEXT; }
1866 case 0x6b: { II ii = ld_R_R<IXL,E,T::CC_DD>();
NEXT; }
1867 case 0x6c: { II ii = ld_R_R<IXL,IXH,T::CC_DD>();
NEXT; }
1868 case 0x6f: { II ii = ld_R_R<IXL,A,T::CC_DD>();
NEXT; }
1869 case 0x70: { II ii = ld_xix_R<IX,B>();
NEXT; }
1870 case 0x71: { II ii = ld_xix_R<IX,C>();
NEXT; }
1871 case 0x72: { II ii = ld_xix_R<IX,D>();
NEXT; }
1872 case 0x73: { II ii = ld_xix_R<IX,E>();
NEXT; }
1873 case 0x74: { II ii = ld_xix_R<IX,H>();
NEXT; }
1874 case 0x75: { II ii = ld_xix_R<IX,L>();
NEXT; }
1875 case 0x77: { II ii = ld_xix_R<IX,A>();
NEXT; }
1876 case 0x46: { II ii = ld_R_xix<B,IX>();
NEXT; }
1877 case 0x4e: { II ii = ld_R_xix<C,IX>();
NEXT; }
1878 case 0x56: { II ii = ld_R_xix<D,IX>();
NEXT; }
1879 case 0x5e: { II ii = ld_R_xix<E,IX>();
NEXT; }
1880 case 0x66: { II ii = ld_R_xix<H,IX>();
NEXT; }
1881 case 0x6e: { II ii = ld_R_xix<L,IX>();
NEXT; }
1882 case 0x7e: { II ii = ld_R_xix<A,IX>();
NEXT; }
1884 case 0x84: { II ii = add_a_R<IXH,T::CC_DD>();
NEXT; }
1885 case 0x85: { II ii = add_a_R<IXL,T::CC_DD>();
NEXT; }
1886 case 0x86: { II ii = add_a_xix<IX>();
NEXT; }
1887 case 0x8c: { II ii = adc_a_R<IXH,T::CC_DD>();
NEXT; }
1888 case 0x8d: { II ii = adc_a_R<IXL,T::CC_DD>();
NEXT; }
1889 case 0x8e: { II ii = adc_a_xix<IX>();
NEXT; }
1890 case 0x94: { II ii = sub_R<IXH,T::CC_DD>();
NEXT; }
1891 case 0x95: { II ii = sub_R<IXL,T::CC_DD>();
NEXT; }
1892 case 0x96: { II ii = sub_xix<IX>();
NEXT; }
1893 case 0x9c: { II ii = sbc_a_R<IXH,T::CC_DD>();
NEXT; }
1894 case 0x9d: { II ii = sbc_a_R<IXL,T::CC_DD>();
NEXT; }
1895 case 0x9e: { II ii = sbc_a_xix<IX>();
NEXT; }
1896 case 0xa4: { II ii = and_R<IXH,T::CC_DD>();
NEXT; }
1897 case 0xa5: { II ii = and_R<IXL,T::CC_DD>();
NEXT; }
1898 case 0xa6: { II ii = and_xix<IX>();
NEXT; }
1899 case 0xac: { II ii = xor_R<IXH,T::CC_DD>();
NEXT; }
1900 case 0xad: { II ii = xor_R<IXL,T::CC_DD>();
NEXT; }
1901 case 0xae: { II ii = xor_xix<IX>();
NEXT; }
1902 case 0xb4: { II ii = or_R<IXH,T::CC_DD>();
NEXT; }
1903 case 0xb5: { II ii = or_R<IXL,T::CC_DD>();
NEXT; }
1904 case 0xb6: { II ii = or_xix<IX>();
NEXT; }
1905 case 0xbc: { II ii = cp_R<IXH,T::CC_DD>();
NEXT; }
1906 case 0xbd: { II ii = cp_R<IXL,T::CC_DD>();
NEXT; }
1907 case 0xbe: { II ii = cp_xix<IX>();
NEXT; }
1909 case 0xe1: { II ii = pop_SS <IX,T::CC_DD>();
NEXT; }
1910 case 0xe5: { II ii = push_SS<IX,T::CC_DD>();
NEXT; }
1911 case 0xe3: { II ii = ex_xsp_SS<IX,T::CC_DD>();
NEXT; }
1912 case 0xe9: { II ii = jp_SS<IX,T::CC_DD>();
NEXT; }
1913 case 0xf9: { II ii = ld_sp_SS<IX,T::CC_DD>();
NEXT; }
1914 case 0xcb: ixy = getIX();
goto xx_cb;
1916 if constexpr (T::IS_R800) {
1917 II ii = nop<T::CC_DD>();
NEXT;
1919 T::add(T::CC_DD);
goto opDD_2;
1922 if constexpr (T::IS_R800) {
1923 II ii = nop<T::CC_DD>();
NEXT;
1925 T::add(T::CC_DD);
goto opFD_2;
1933 byte opcodeFD = RDMEM_OPCODE<0>(T::CC_DD + T::CC_MAIN);
2109 if constexpr (T::IS_R800) {
2110 II ii = nop<T::CC_DD>();
NEXT;
2113 #ifdef USE_COMPUTED_GOTO
2114 goto *(opcodeTable[opcodeFD]);
2116 opcodeMain = opcodeFD;
2121 case 0x09: { II ii = add_SS_TT<IY,BC,T::CC_DD>();
NEXT; }
2122 case 0x19: { II ii = add_SS_TT<IY,DE,T::CC_DD>();
NEXT; }
2123 case 0x29: { II ii = add_SS_SS<IY ,T::CC_DD>();
NEXT; }
2124 case 0x39: { II ii = add_SS_TT<IY,SP,T::CC_DD>();
NEXT; }
2125 case 0x21: { II ii = ld_SS_word<IY,T::CC_DD>();
NEXT; }
2126 case 0x22: { II ii = ld_xword_SS<IY,T::CC_DD>();
NEXT; }
2127 case 0x2a: { II ii = ld_SS_xword<IY,T::CC_DD>();
NEXT; }
2128 case 0x23: { II ii = inc_SS<IY,T::CC_DD>();
NEXT; }
2129 case 0x2b: { II ii = dec_SS<IY,T::CC_DD>();
NEXT; }
2130 case 0x24: { II ii = inc_R<IYH,T::CC_DD>();
NEXT; }
2131 case 0x2c: { II ii = inc_R<IYL,T::CC_DD>();
NEXT; }
2132 case 0x25: { II ii = dec_R<IYH,T::CC_DD>();
NEXT; }
2133 case 0x2d: { II ii = dec_R<IYL,T::CC_DD>();
NEXT; }
2134 case 0x26: { II ii = ld_R_byte<IYH,T::CC_DD>();
NEXT; }
2135 case 0x2e: { II ii = ld_R_byte<IYL,T::CC_DD>();
NEXT; }
2136 case 0x34: { II ii = inc_xix<IY>();
NEXT; }
2137 case 0x35: { II ii = dec_xix<IY>();
NEXT; }
2138 case 0x36: { II ii = ld_xix_byte<IY>();
NEXT; }
2140 case 0x44: { II ii = ld_R_R<B,IYH,T::CC_DD>();
NEXT; }
2141 case 0x45: { II ii = ld_R_R<B,IYL,T::CC_DD>();
NEXT; }
2142 case 0x4c: { II ii = ld_R_R<C,IYH,T::CC_DD>();
NEXT; }
2143 case 0x4d: { II ii = ld_R_R<C,IYL,T::CC_DD>();
NEXT; }
2144 case 0x54: { II ii = ld_R_R<D,IYH,T::CC_DD>();
NEXT; }
2145 case 0x55: { II ii = ld_R_R<D,IYL,T::CC_DD>();
NEXT; }
2146 case 0x5c: { II ii = ld_R_R<E,IYH,T::CC_DD>();
NEXT; }
2147 case 0x5d: { II ii = ld_R_R<E,IYL,T::CC_DD>();
NEXT; }
2148 case 0x7c: { II ii = ld_R_R<A,IYH,T::CC_DD>();
NEXT; }
2149 case 0x7d: { II ii = ld_R_R<A,IYL,T::CC_DD>();
NEXT; }
2150 case 0x60: { II ii = ld_R_R<IYH,B,T::CC_DD>();
NEXT; }
2151 case 0x61: { II ii = ld_R_R<IYH,C,T::CC_DD>();
NEXT; }
2152 case 0x62: { II ii = ld_R_R<IYH,D,T::CC_DD>();
NEXT; }
2153 case 0x63: { II ii = ld_R_R<IYH,E,T::CC_DD>();
NEXT; }
2154 case 0x65: { II ii = ld_R_R<IYH,IYL,T::CC_DD>();
NEXT; }
2155 case 0x67: { II ii = ld_R_R<IYH,A,T::CC_DD>();
NEXT; }
2156 case 0x68: { II ii = ld_R_R<IYL,B,T::CC_DD>();
NEXT; }
2157 case 0x69: { II ii = ld_R_R<IYL,C,T::CC_DD>();
NEXT; }
2158 case 0x6a: { II ii = ld_R_R<IYL,D,T::CC_DD>();
NEXT; }
2159 case 0x6b: { II ii = ld_R_R<IYL,E,T::CC_DD>();
NEXT; }
2160 case 0x6c: { II ii = ld_R_R<IYL,IYH,T::CC_DD>();
NEXT; }
2161 case 0x6f: { II ii = ld_R_R<IYL,A,T::CC_DD>();
NEXT; }
2162 case 0x70: { II ii = ld_xix_R<IY,B>();
NEXT; }
2163 case 0x71: { II ii = ld_xix_R<IY,C>();
NEXT; }
2164 case 0x72: { II ii = ld_xix_R<IY,D>();
NEXT; }
2165 case 0x73: { II ii = ld_xix_R<IY,E>();
NEXT; }
2166 case 0x74: { II ii = ld_xix_R<IY,H>();
NEXT; }
2167 case 0x75: { II ii = ld_xix_R<IY,L>();
NEXT; }
2168 case 0x77: { II ii = ld_xix_R<IY,A>();
NEXT; }
2169 case 0x46: { II ii = ld_R_xix<B,IY>();
NEXT; }
2170 case 0x4e: { II ii = ld_R_xix<C,IY>();
NEXT; }
2171 case 0x56: { II ii = ld_R_xix<D,IY>();
NEXT; }
2172 case 0x5e: { II ii = ld_R_xix<E,IY>();
NEXT; }
2173 case 0x66: { II ii = ld_R_xix<H,IY>();
NEXT; }
2174 case 0x6e: { II ii = ld_R_xix<L,IY>();
NEXT; }
2175 case 0x7e: { II ii = ld_R_xix<A,IY>();
NEXT; }
2177 case 0x84: { II ii = add_a_R<IYH,T::CC_DD>();
NEXT; }
2178 case 0x85: { II ii = add_a_R<IYL,T::CC_DD>();
NEXT; }
2179 case 0x86: { II ii = add_a_xix<IY>();
NEXT; }
2180 case 0x8c: { II ii = adc_a_R<IYH,T::CC_DD>();
NEXT; }
2181 case 0x8d: { II ii = adc_a_R<IYL,T::CC_DD>();
NEXT; }
2182 case 0x8e: { II ii = adc_a_xix<IY>();
NEXT; }
2183 case 0x94: { II ii = sub_R<IYH,T::CC_DD>();
NEXT; }
2184 case 0x95: { II ii = sub_R<IYL,T::CC_DD>();
NEXT; }
2185 case 0x96: { II ii = sub_xix<IY>();
NEXT; }
2186 case 0x9c: { II ii = sbc_a_R<IYH,T::CC_DD>();
NEXT; }
2187 case 0x9d: { II ii = sbc_a_R<IYL,T::CC_DD>();
NEXT; }
2188 case 0x9e: { II ii = sbc_a_xix<IY>();
NEXT; }
2189 case 0xa4: { II ii = and_R<IYH,T::CC_DD>();
NEXT; }
2190 case 0xa5: { II ii = and_R<IYL,T::CC_DD>();
NEXT; }
2191 case 0xa6: { II ii = and_xix<IY>();
NEXT; }
2192 case 0xac: { II ii = xor_R<IYH,T::CC_DD>();
NEXT; }
2193 case 0xad: { II ii = xor_R<IYL,T::CC_DD>();
NEXT; }
2194 case 0xae: { II ii = xor_xix<IY>();
NEXT; }
2195 case 0xb4: { II ii = or_R<IYH,T::CC_DD>();
NEXT; }
2196 case 0xb5: { II ii = or_R<IYL,T::CC_DD>();
NEXT; }
2197 case 0xb6: { II ii = or_xix<IY>();
NEXT; }
2198 case 0xbc: { II ii = cp_R<IYH,T::CC_DD>();
NEXT; }
2199 case 0xbd: { II ii = cp_R<IYL,T::CC_DD>();
NEXT; }
2200 case 0xbe: { II ii = cp_xix<IY>();
NEXT; }
2202 case 0xe1: { II ii = pop_SS <IY,T::CC_DD>();
NEXT; }
2203 case 0xe5: { II ii = push_SS<IY,T::CC_DD>();
NEXT; }
2204 case 0xe3: { II ii = ex_xsp_SS<IY,T::CC_DD>();
NEXT; }
2205 case 0xe9: { II ii = jp_SS<IY,T::CC_DD>();
NEXT; }
2206 case 0xf9: { II ii = ld_sp_SS<IY,T::CC_DD>();
NEXT; }
2207 case 0xcb: ixy = getIY();
goto xx_cb;
2209 if constexpr (T::IS_R800) {
2210 II ii = nop<T::CC_DD>();
NEXT;
2212 T::add(T::CC_DD);
goto opDD_2;
2215 if constexpr (T::IS_R800) {
2216 II ii = nop<T::CC_DD>();
NEXT;
2218 T::add(T::CC_DD);
goto opFD_2;
2223#ifndef USE_COMPUTED_GOTO
2229 unsigned tmp = RD_WORD_PC<1>(T::CC_DD + T::CC_DD_CB);
2230 auto ofst = narrow_cast<int8_t>(tmp & 0xFF);
2231 unsigned addr = narrow_cast<word>(ixy + ofst);
2232 auto xxcb_opcode = narrow_cast<byte>(tmp >> 8);
2233 switch (xxcb_opcode) {
2234 case 0x00: { II ii = rlc_xix_R<B>(addr);
NEXT; }
2235 case 0x01: { II ii = rlc_xix_R<C>(addr);
NEXT; }
2236 case 0x02: { II ii = rlc_xix_R<D>(addr);
NEXT; }
2237 case 0x03: { II ii = rlc_xix_R<E>(addr);
NEXT; }
2238 case 0x04: { II ii = rlc_xix_R<H>(addr);
NEXT; }
2239 case 0x05: { II ii = rlc_xix_R<L>(addr);
NEXT; }
2240 case 0x06: { II ii = rlc_xix_R<DUMMY>(addr);
NEXT; }
2241 case 0x07: { II ii = rlc_xix_R<A>(addr);
NEXT; }
2242 case 0x08: { II ii = rrc_xix_R<B>(addr);
NEXT; }
2243 case 0x09: { II ii = rrc_xix_R<C>(addr);
NEXT; }
2244 case 0x0a: { II ii = rrc_xix_R<D>(addr);
NEXT; }
2245 case 0x0b: { II ii = rrc_xix_R<E>(addr);
NEXT; }
2246 case 0x0c: { II ii = rrc_xix_R<H>(addr);
NEXT; }
2247 case 0x0d: { II ii = rrc_xix_R<L>(addr);
NEXT; }
2248 case 0x0e: { II ii = rrc_xix_R<DUMMY>(addr);
NEXT; }
2249 case 0x0f: { II ii = rrc_xix_R<A>(addr);
NEXT; }
2250 case 0x10: { II ii = rl_xix_R<B>(addr);
NEXT; }
2251 case 0x11: { II ii = rl_xix_R<C>(addr);
NEXT; }
2252 case 0x12: { II ii = rl_xix_R<D>(addr);
NEXT; }
2253 case 0x13: { II ii = rl_xix_R<E>(addr);
NEXT; }
2254 case 0x14: { II ii = rl_xix_R<H>(addr);
NEXT; }
2255 case 0x15: { II ii = rl_xix_R<L>(addr);
NEXT; }
2256 case 0x16: { II ii = rl_xix_R<DUMMY>(addr);
NEXT; }
2257 case 0x17: { II ii = rl_xix_R<A>(addr);
NEXT; }
2258 case 0x18: { II ii = rr_xix_R<B>(addr);
NEXT; }
2259 case 0x19: { II ii = rr_xix_R<C>(addr);
NEXT; }
2260 case 0x1a: { II ii = rr_xix_R<D>(addr);
NEXT; }
2261 case 0x1b: { II ii = rr_xix_R<E>(addr);
NEXT; }
2262 case 0x1c: { II ii = rr_xix_R<H>(addr);
NEXT; }
2263 case 0x1d: { II ii = rr_xix_R<L>(addr);
NEXT; }
2264 case 0x1e: { II ii = rr_xix_R<DUMMY>(addr);
NEXT; }
2265 case 0x1f: { II ii = rr_xix_R<A>(addr);
NEXT; }
2266 case 0x20: { II ii = sla_xix_R<B>(addr);
NEXT; }
2267 case 0x21: { II ii = sla_xix_R<C>(addr);
NEXT; }
2268 case 0x22: { II ii = sla_xix_R<D>(addr);
NEXT; }
2269 case 0x23: { II ii = sla_xix_R<E>(addr);
NEXT; }
2270 case 0x24: { II ii = sla_xix_R<H>(addr);
NEXT; }
2271 case 0x25: { II ii = sla_xix_R<L>(addr);
NEXT; }
2272 case 0x26: { II ii = sla_xix_R<DUMMY>(addr);
NEXT; }
2273 case 0x27: { II ii = sla_xix_R<A>(addr);
NEXT; }
2274 case 0x28: { II ii = sra_xix_R<B>(addr);
NEXT; }
2275 case 0x29: { II ii = sra_xix_R<C>(addr);
NEXT; }
2276 case 0x2a: { II ii = sra_xix_R<D>(addr);
NEXT; }
2277 case 0x2b: { II ii = sra_xix_R<E>(addr);
NEXT; }
2278 case 0x2c: { II ii = sra_xix_R<H>(addr);
NEXT; }
2279 case 0x2d: { II ii = sra_xix_R<L>(addr);
NEXT; }
2280 case 0x2e: { II ii = sra_xix_R<DUMMY>(addr);
NEXT; }
2281 case 0x2f: { II ii = sra_xix_R<A>(addr);
NEXT; }
2282 case 0x30: { II ii = T::IS_R800 ? sll2() : sll_xix_R<
B>(addr);
NEXT; }
2283 case 0x31: { II ii = T::IS_R800 ? sll2() : sll_xix_R<
C>(addr);
NEXT; }
2284 case 0x32: { II ii = T::IS_R800 ? sll2() : sll_xix_R<
D>(addr);
NEXT; }
2285 case 0x33: { II ii = T::IS_R800 ? sll2() : sll_xix_R<
E>(addr);
NEXT; }
2286 case 0x34: { II ii = T::IS_R800 ? sll2() : sll_xix_R<
H>(addr);
NEXT; }
2287 case 0x35: { II ii = T::IS_R800 ? sll2() : sll_xix_R<
L>(addr);
NEXT; }
2288 case 0x36: { II ii = T::IS_R800 ? sll2() : sll_xix_R<
DUMMY>(addr);
NEXT; }
2289 case 0x37: { II ii = T::IS_R800 ? sll2() : sll_xix_R<
A>(addr);
NEXT; }
2290 case 0x38: { II ii = srl_xix_R<B>(addr);
NEXT; }
2291 case 0x39: { II ii = srl_xix_R<C>(addr);
NEXT; }
2292 case 0x3a: { II ii = srl_xix_R<D>(addr);
NEXT; }
2293 case 0x3b: { II ii = srl_xix_R<E>(addr);
NEXT; }
2294 case 0x3c: { II ii = srl_xix_R<H>(addr);
NEXT; }
2295 case 0x3d: { II ii = srl_xix_R<L>(addr);
NEXT; }
2296 case 0x3e: { II ii = srl_xix_R<DUMMY>(addr);
NEXT; }
2297 case 0x3f: { II ii = srl_xix_R<A>(addr);
NEXT; }
2299 case 0x40:
case 0x41:
case 0x42:
case 0x43:
2300 case 0x44:
case 0x45:
case 0x46:
case 0x47:
2301 { II ii = bit_N_xix<0>(addr);
NEXT; }
2302 case 0x48:
case 0x49:
case 0x4a:
case 0x4b:
2303 case 0x4c:
case 0x4d:
case 0x4e:
case 0x4f:
2304 { II ii = bit_N_xix<1>(addr);
NEXT; }
2305 case 0x50:
case 0x51:
case 0x52:
case 0x53:
2306 case 0x54:
case 0x55:
case 0x56:
case 0x57:
2307 { II ii = bit_N_xix<2>(addr);
NEXT; }
2308 case 0x58:
case 0x59:
case 0x5a:
case 0x5b:
2309 case 0x5c:
case 0x5d:
case 0x5e:
case 0x5f:
2310 { II ii = bit_N_xix<3>(addr);
NEXT; }
2311 case 0x60:
case 0x61:
case 0x62:
case 0x63:
2312 case 0x64:
case 0x65:
case 0x66:
case 0x67:
2313 { II ii = bit_N_xix<4>(addr);
NEXT; }
2314 case 0x68:
case 0x69:
case 0x6a:
case 0x6b:
2315 case 0x6c:
case 0x6d:
case 0x6e:
case 0x6f:
2316 { II ii = bit_N_xix<5>(addr);
NEXT; }
2317 case 0x70:
case 0x71:
case 0x72:
case 0x73:
2318 case 0x74:
case 0x75:
case 0x76:
case 0x77:
2319 { II ii = bit_N_xix<6>(addr);
NEXT; }
2320 case 0x78:
case 0x79:
case 0x7a:
case 0x7b:
2321 case 0x7c:
case 0x7d:
case 0x7e:
case 0x7f:
2322 { II ii = bit_N_xix<7>(addr);
NEXT; }
2324 case 0x80: { II ii = res_N_xix_R<0,B>(addr);
NEXT; }
2325 case 0x81: { II ii = res_N_xix_R<0,C>(addr);
NEXT; }
2326 case 0x82: { II ii = res_N_xix_R<0,D>(addr);
NEXT; }
2327 case 0x83: { II ii = res_N_xix_R<0,E>(addr);
NEXT; }
2328 case 0x84: { II ii = res_N_xix_R<0,H>(addr);
NEXT; }
2329 case 0x85: { II ii = res_N_xix_R<0,L>(addr);
NEXT; }
2330 case 0x87: { II ii = res_N_xix_R<0,A>(addr);
NEXT; }
2331 case 0x88: { II ii = res_N_xix_R<1,B>(addr);
NEXT; }
2332 case 0x89: { II ii = res_N_xix_R<1,C>(addr);
NEXT; }
2333 case 0x8a: { II ii = res_N_xix_R<1,D>(addr);
NEXT; }
2334 case 0x8b: { II ii = res_N_xix_R<1,E>(addr);
NEXT; }
2335 case 0x8c: { II ii = res_N_xix_R<1,H>(addr);
NEXT; }
2336 case 0x8d: { II ii = res_N_xix_R<1,L>(addr);
NEXT; }
2337 case 0x8f: { II ii = res_N_xix_R<1,A>(addr);
NEXT; }
2338 case 0x90: { II ii = res_N_xix_R<2,B>(addr);
NEXT; }
2339 case 0x91: { II ii = res_N_xix_R<2,C>(addr);
NEXT; }
2340 case 0x92: { II ii = res_N_xix_R<2,D>(addr);
NEXT; }
2341 case 0x93: { II ii = res_N_xix_R<2,E>(addr);
NEXT; }
2342 case 0x94: { II ii = res_N_xix_R<2,H>(addr);
NEXT; }
2343 case 0x95: { II ii = res_N_xix_R<2,L>(addr);
NEXT; }
2344 case 0x97: { II ii = res_N_xix_R<2,A>(addr);
NEXT; }
2345 case 0x98: { II ii = res_N_xix_R<3,B>(addr);
NEXT; }
2346 case 0x99: { II ii = res_N_xix_R<3,C>(addr);
NEXT; }
2347 case 0x9a: { II ii = res_N_xix_R<3,D>(addr);
NEXT; }
2348 case 0x9b: { II ii = res_N_xix_R<3,E>(addr);
NEXT; }
2349 case 0x9c: { II ii = res_N_xix_R<3,H>(addr);
NEXT; }
2350 case 0x9d: { II ii = res_N_xix_R<3,L>(addr);
NEXT; }
2351 case 0x9f: { II ii = res_N_xix_R<3,A>(addr);
NEXT; }
2352 case 0xa0: { II ii = res_N_xix_R<4,B>(addr);
NEXT; }
2353 case 0xa1: { II ii = res_N_xix_R<4,C>(addr);
NEXT; }
2354 case 0xa2: { II ii = res_N_xix_R<4,D>(addr);
NEXT; }
2355 case 0xa3: { II ii = res_N_xix_R<4,E>(addr);
NEXT; }
2356 case 0xa4: { II ii = res_N_xix_R<4,H>(addr);
NEXT; }
2357 case 0xa5: { II ii = res_N_xix_R<4,L>(addr);
NEXT; }
2358 case 0xa7: { II ii = res_N_xix_R<4,A>(addr);
NEXT; }
2359 case 0xa8: { II ii = res_N_xix_R<5,B>(addr);
NEXT; }
2360 case 0xa9: { II ii = res_N_xix_R<5,C>(addr);
NEXT; }
2361 case 0xaa: { II ii = res_N_xix_R<5,D>(addr);
NEXT; }
2362 case 0xab: { II ii = res_N_xix_R<5,E>(addr);
NEXT; }
2363 case 0xac: { II ii = res_N_xix_R<5,H>(addr);
NEXT; }
2364 case 0xad: { II ii = res_N_xix_R<5,L>(addr);
NEXT; }
2365 case 0xaf: { II ii = res_N_xix_R<5,A>(addr);
NEXT; }
2366 case 0xb0: { II ii = res_N_xix_R<6,B>(addr);
NEXT; }
2367 case 0xb1: { II ii = res_N_xix_R<6,C>(addr);
NEXT; }
2368 case 0xb2: { II ii = res_N_xix_R<6,D>(addr);
NEXT; }
2369 case 0xb3: { II ii = res_N_xix_R<6,E>(addr);
NEXT; }
2370 case 0xb4: { II ii = res_N_xix_R<6,H>(addr);
NEXT; }
2371 case 0xb5: { II ii = res_N_xix_R<6,L>(addr);
NEXT; }
2372 case 0xb7: { II ii = res_N_xix_R<6,A>(addr);
NEXT; }
2373 case 0xb8: { II ii = res_N_xix_R<7,B>(addr);
NEXT; }
2374 case 0xb9: { II ii = res_N_xix_R<7,C>(addr);
NEXT; }
2375 case 0xba: { II ii = res_N_xix_R<7,D>(addr);
NEXT; }
2376 case 0xbb: { II ii = res_N_xix_R<7,E>(addr);
NEXT; }
2377 case 0xbc: { II ii = res_N_xix_R<7,H>(addr);
NEXT; }
2378 case 0xbd: { II ii = res_N_xix_R<7,L>(addr);
NEXT; }
2379 case 0xbf: { II ii = res_N_xix_R<7,A>(addr);
NEXT; }
2380 case 0x86: { II ii = res_N_xix_R<0,DUMMY>(addr);
NEXT; }
2381 case 0x8e: { II ii = res_N_xix_R<1,DUMMY>(addr);
NEXT; }
2382 case 0x96: { II ii = res_N_xix_R<2,DUMMY>(addr);
NEXT; }
2383 case 0x9e: { II ii = res_N_xix_R<3,DUMMY>(addr);
NEXT; }
2384 case 0xa6: { II ii = res_N_xix_R<4,DUMMY>(addr);
NEXT; }
2385 case 0xae: { II ii = res_N_xix_R<5,DUMMY>(addr);
NEXT; }
2386 case 0xb6: { II ii = res_N_xix_R<6,DUMMY>(addr);
NEXT; }
2387 case 0xbe: { II ii = res_N_xix_R<7,DUMMY>(addr);
NEXT; }
2389 case 0xc0: { II ii = set_N_xix_R<0,B>(addr);
NEXT; }
2390 case 0xc1: { II ii = set_N_xix_R<0,C>(addr);
NEXT; }
2391 case 0xc2: { II ii = set_N_xix_R<0,D>(addr);
NEXT; }
2392 case 0xc3: { II ii = set_N_xix_R<0,E>(addr);
NEXT; }
2393 case 0xc4: { II ii = set_N_xix_R<0,H>(addr);
NEXT; }
2394 case 0xc5: { II ii = set_N_xix_R<0,L>(addr);
NEXT; }
2395 case 0xc7: { II ii = set_N_xix_R<0,A>(addr);
NEXT; }
2396 case 0xc8: { II ii = set_N_xix_R<1,B>(addr);
NEXT; }
2397 case 0xc9: { II ii = set_N_xix_R<1,C>(addr);
NEXT; }
2398 case 0xca: { II ii = set_N_xix_R<1,D>(addr);
NEXT; }
2399 case 0xcb: { II ii = set_N_xix_R<1,E>(addr);
NEXT; }
2400 case 0xcc: { II ii = set_N_xix_R<1,H>(addr);
NEXT; }
2401 case 0xcd: { II ii = set_N_xix_R<1,L>(addr);
NEXT; }
2402 case 0xcf: { II ii = set_N_xix_R<1,A>(addr);
NEXT; }
2403 case 0xd0: { II ii = set_N_xix_R<2,B>(addr);
NEXT; }
2404 case 0xd1: { II ii = set_N_xix_R<2,C>(addr);
NEXT; }
2405 case 0xd2: { II ii = set_N_xix_R<2,D>(addr);
NEXT; }
2406 case 0xd3: { II ii = set_N_xix_R<2,E>(addr);
NEXT; }
2407 case 0xd4: { II ii = set_N_xix_R<2,H>(addr);
NEXT; }
2408 case 0xd5: { II ii = set_N_xix_R<2,L>(addr);
NEXT; }
2409 case 0xd7: { II ii = set_N_xix_R<2,A>(addr);
NEXT; }
2410 case 0xd8: { II ii = set_N_xix_R<3,B>(addr);
NEXT; }
2411 case 0xd9: { II ii = set_N_xix_R<3,C>(addr);
NEXT; }
2412 case 0xda: { II ii = set_N_xix_R<3,D>(addr);
NEXT; }
2413 case 0xdb: { II ii = set_N_xix_R<3,E>(addr);
NEXT; }
2414 case 0xdc: { II ii = set_N_xix_R<3,H>(addr);
NEXT; }
2415 case 0xdd: { II ii = set_N_xix_R<3,L>(addr);
NEXT; }
2416 case 0xdf: { II ii = set_N_xix_R<3,A>(addr);
NEXT; }
2417 case 0xe0: { II ii = set_N_xix_R<4,B>(addr);
NEXT; }
2418 case 0xe1: { II ii = set_N_xix_R<4,C>(addr);
NEXT; }
2419 case 0xe2: { II ii = set_N_xix_R<4,D>(addr);
NEXT; }
2420 case 0xe3: { II ii = set_N_xix_R<4,E>(addr);
NEXT; }
2421 case 0xe4: { II ii = set_N_xix_R<4,H>(addr);
NEXT; }
2422 case 0xe5: { II ii = set_N_xix_R<4,L>(addr);
NEXT; }
2423 case 0xe7: { II ii = set_N_xix_R<4,A>(addr);
NEXT; }
2424 case 0xe8: { II ii = set_N_xix_R<5,B>(addr);
NEXT; }
2425 case 0xe9: { II ii = set_N_xix_R<5,C>(addr);
NEXT; }
2426 case 0xea: { II ii = set_N_xix_R<5,D>(addr);
NEXT; }
2427 case 0xeb: { II ii = set_N_xix_R<5,E>(addr);
NEXT; }
2428 case 0xec: { II ii = set_N_xix_R<5,H>(addr);
NEXT; }
2429 case 0xed: { II ii = set_N_xix_R<5,L>(addr);
NEXT; }
2430 case 0xef: { II ii = set_N_xix_R<5,A>(addr);
NEXT; }
2431 case 0xf0: { II ii = set_N_xix_R<6,B>(addr);
NEXT; }
2432 case 0xf1: { II ii = set_N_xix_R<6,C>(addr);
NEXT; }
2433 case 0xf2: { II ii = set_N_xix_R<6,D>(addr);
NEXT; }
2434 case 0xf3: { II ii = set_N_xix_R<6,E>(addr);
NEXT; }
2435 case 0xf4: { II ii = set_N_xix_R<6,H>(addr);
NEXT; }
2436 case 0xf5: { II ii = set_N_xix_R<6,L>(addr);
NEXT; }
2437 case 0xf7: { II ii = set_N_xix_R<6,A>(addr);
NEXT; }
2438 case 0xf8: { II ii = set_N_xix_R<7,B>(addr);
NEXT; }
2439 case 0xf9: { II ii = set_N_xix_R<7,C>(addr);
NEXT; }
2440 case 0xfa: { II ii = set_N_xix_R<7,D>(addr);
NEXT; }
2441 case 0xfb: { II ii = set_N_xix_R<7,E>(addr);
NEXT; }
2442 case 0xfc: { II ii = set_N_xix_R<7,H>(addr);
NEXT; }
2443 case 0xfd: { II ii = set_N_xix_R<7,L>(addr);
NEXT; }
2444 case 0xff: { II ii = set_N_xix_R<7,A>(addr);
NEXT; }
2445 case 0xc6: { II ii = set_N_xix_R<0,DUMMY>(addr);
NEXT; }
2446 case 0xce: { II ii = set_N_xix_R<1,DUMMY>(addr);
NEXT; }
2447 case 0xd6: { II ii = set_N_xix_R<2,DUMMY>(addr);
NEXT; }
2448 case 0xde: { II ii = set_N_xix_R<3,DUMMY>(addr);
NEXT; }
2449 case 0xe6: { II ii = set_N_xix_R<4,DUMMY>(addr);
NEXT; }
2450 case 0xee: { II ii = set_N_xix_R<5,DUMMY>(addr);
NEXT; }
2451 case 0xf6: { II ii = set_N_xix_R<6,DUMMY>(addr);
NEXT; }
2452 case 0xfe: { II ii = set_N_xix_R<7,DUMMY>(addr);
NEXT; }
2458template<
typename T>
inline void CPUCore<T>::cpuTracePre()
2462template<
typename T>
inline void CPUCore<T>::cpuTracePost()
2464 if (tracingEnabled) [[unlikely]] {
2465 cpuTracePost_slow();
2468template<
typename T>
void CPUCore<T>::cpuTracePost_slow()
2470 std::array<byte, 4> opBuf;
2471 std::string dasmOutput;
2472 dasm(*interface, start_pc, opBuf, dasmOutput, T::getTimeFast());
2473 std::cout << strCat(hex_string<4>(start_pc),
2475 " AF=", hex_string<4>(getAF()),
2476 " BC=", hex_string<4>(getBC()),
2477 " DE=", hex_string<4>(getDE()),
2478 " HL=", hex_string<4>(getHL()),
2479 " IX=", hex_string<4>(getIX()),
2480 " IY=", hex_string<4>(getIY()),
2481 " SP=", hex_string<4>(getSP()),
2486template<
typename T>
ExecIRQ CPUCore<T>::getExecIRQ()
const
2489 if (IRQStatus && getIFF1() && !prevWasEI()) [[unlikely]]
return ExecIRQ::IRQ;
2493template<
typename T>
void CPUCore<T>::executeSlow(
ExecIRQ execIRQ)
2500 if (prevWasLDAI()) [[unlikely]] {
2518 assert(getF() & V_FLAG);
2519 setF(getF() & ~V_FLAG);
2532 }
else if (getHALT()) [[unlikely]] {
2534 incR(narrow_cast<byte>(T::advanceHalt(T::HALT_STATES, scheduler.getNext())));
2535 setSlowInstructions();
2538 assert(T::limitReached());
2539 executeInstructions();
2542 if constexpr (T::IS_R800) {
2543 if ((prev2WasCall()) && (!prevWasPopRet())) [[unlikely]] {
2565 assert(fastForward || !interface->isBreaked());
2567 interface->setFastForward(
true);
2569 execute2(fastForward);
2570 interface->setFastForward(
false);
2579 scheduler.schedule(T::getTime());
2580 setSlowInstructions();
2586 (!interface->anyBreakPoints() && !tracingEnabled)) {
2589 if (slowInstructions) {
2591 executeSlow(getExecIRQ());
2592 scheduler.schedule(T::getTimeFast());
2594 while (slowInstructions == 0) {
2596 if (!T::limitReached()) [[likely]] {
2598 executeInstructions();
2603 scheduler.schedule(T::getTimeFast());
2604 if (needExitCPULoop())
return;
2607 }
while (!needExitCPULoop());
2610 if (slowInstructions == 0) {
2612 assert(T::limitReached());
2613 executeInstructions();
2618 executeSlow(getExecIRQ());
2623 scheduler.schedule(T::getTime());
2656 auto execIRQ = getExecIRQ();
2658 interface->checkBreakPoints(getPC())) {
2659 assert(interface->isBreaked());
2662 }
while (!needExitCPULoop());
2667 if constexpr (R8 ==
A) {
return getA(); }
2668 else if constexpr (R8 ==
F) {
return getF(); }
2669 else if constexpr (R8 ==
B) {
return getB(); }
2670 else if constexpr (R8 ==
C) {
return getC(); }
2671 else if constexpr (R8 ==
D) {
return getD(); }
2672 else if constexpr (R8 ==
E) {
return getE(); }
2673 else if constexpr (R8 ==
H) {
return getH(); }
2674 else if constexpr (R8 ==
L) {
return getL(); }
2675 else if constexpr (R8 ==
IXH) {
return getIXh(); }
2676 else if constexpr (R8 ==
IXL) {
return getIXl(); }
2677 else if constexpr (R8 ==
IYH) {
return getIYh(); }
2678 else if constexpr (R8 ==
IYL) {
return getIYl(); }
2679 else if constexpr (R8 ==
REG_I) {
return getI(); }
2680 else if constexpr (R8 ==
REG_R) {
return getR(); }
2681 else if constexpr (R8 ==
DUMMY) {
return 0; }
2685 if constexpr (R16 ==
AF) {
return getAF(); }
2686 else if constexpr (R16 ==
BC) {
return getBC(); }
2687 else if constexpr (R16 ==
DE) {
return getDE(); }
2688 else if constexpr (R16 ==
HL) {
return getHL(); }
2689 else if constexpr (R16 ==
IX) {
return getIX(); }
2690 else if constexpr (R16 ==
IY) {
return getIY(); }
2691 else if constexpr (R16 ==
SP) {
return getSP(); }
2695 if constexpr (R8 ==
A) { setA(x); }
2696 else if constexpr (R8 ==
F) { setF(x); }
2697 else if constexpr (R8 ==
B) { setB(x); }
2698 else if constexpr (R8 ==
C) { setC(x); }
2699 else if constexpr (R8 ==
D) { setD(x); }
2700 else if constexpr (R8 ==
E) { setE(x); }
2701 else if constexpr (R8 ==
H) { setH(x); }
2702 else if constexpr (R8 ==
L) { setL(x); }
2703 else if constexpr (R8 ==
IXH) { setIXh(x); }
2704 else if constexpr (R8 ==
IXL) { setIXl(x); }
2705 else if constexpr (R8 ==
IYH) { setIYh(x); }
2706 else if constexpr (R8 ==
IYL) { setIYl(x); }
2707 else if constexpr (R8 ==
REG_I) { setI(x); }
2708 else if constexpr (R8 ==
REG_R) { setR(x); }
2709 else if constexpr (R8 ==
DUMMY) { }
2713 if constexpr (R16 ==
AF) { setAF(x); }
2714 else if constexpr (R16 ==
BC) { setBC(x); }
2715 else if constexpr (R16 ==
DE) { setDE(x); }
2716 else if constexpr (R16 ==
HL) { setHL(x); }
2717 else if constexpr (R16 ==
IX) { setIX(x); }
2718 else if constexpr (R16 ==
IY) { setIY(x); }
2719 else if constexpr (R16 ==
SP) { setSP(x); }
2725 set8<DST>(get8<SRC>());
return {1, T::CC_LD_R_R + EE};
2729template<
typename T>
template<Reg16 REG,
int EE> II CPUCore<T>::ld_sp_SS() {
2730 setSP(get16<REG>());
return {1, T::CC_LD_SP_HL + EE};
2734template<
typename T>
template<Reg16 REG> II CPUCore<T>::ld_SS_a() {
2735 T::setMemPtr((getA() << 8) | ((get16<REG>() + 1) & 0xFF));
2736 WRMEM(get16<REG>(), getA(), T::CC_LD_SS_A_1);
2737 return {1, T::CC_LD_SS_A};
2741template<
typename T>
template<Reg8 SRC> II CPUCore<T>::ld_xhl_R() {
2742 WRMEM(getHL(), get8<SRC>(), T::CC_LD_HL_R_1);
2743 return {1, T::CC_LD_HL_R};
2747template<
typename T>
template<Reg16 IXY, Reg8 SRC> II CPUCore<T>::ld_xix_R() {
2748 int8_t ofst = RDMEM_OPCODE<1>(T::CC_DD + T::CC_LD_XIX_R_1);
2749 unsigned addr = narrow_cast<word>(get16<IXY>() + ofst);
2751 WRMEM(addr, get8<SRC>(), T::CC_DD + T::CC_LD_XIX_R_2);
2752 return {2, T::CC_DD + T::CC_LD_XIX_R};
2756template<
typename T> II CPUCore<T>::ld_xhl_byte() {
2757 byte val = RDMEM_OPCODE<1>(T::CC_LD_HL_N_1);
2758 WRMEM(getHL(), val, T::CC_LD_HL_N_2);
2759 return {2, T::CC_LD_HL_N};
2763template<
typename T>
template<Reg16 IXY> II CPUCore<T>::ld_xix_byte() {
2764 unsigned tmp = RD_WORD_PC<1>(T::CC_DD + T::CC_LD_XIX_N_1);
2765 auto ofst = narrow_cast<int8_t>(tmp & 0xFF);
2766 auto val = narrow_cast<byte>(tmp >> 8);
2767 unsigned addr = narrow_cast<word>(get16<IXY>() + ofst);
2769 WRMEM(addr, val, T::CC_DD + T::CC_LD_XIX_N_2);
2770 return {3, T::CC_DD + T::CC_LD_XIX_N};
2774template<
typename T> II CPUCore<T>::ld_xbyte_a() {
2775 unsigned x = RD_WORD_PC<1>(T::CC_LD_NN_A_1);
2776 T::setMemPtr((getA() << 8) | ((x + 1) & 0xFF));
2777 WRMEM(x, getA(), T::CC_LD_NN_A_2);
2778 return {3, T::CC_LD_NN_A};
2782template<
typename T>
template<
int EE>
inline II CPUCore<T>::WR_NN_Y(
word reg) {
2783 unsigned addr = RD_WORD_PC<1>(T::CC_LD_XX_HL_1 + EE);
2784 T::setMemPtr(addr + 1);
2785 WR_WORD(addr, reg, T::CC_LD_XX_HL_2 + EE);
2786 return {3, T::CC_LD_XX_HL + EE};
2788template<
typename T>
template<Reg16 REG,
int EE> II CPUCore<T>::ld_xword_SS() {
2789 return WR_NN_Y<EE >(get16<REG>());
2791template<
typename T>
template<Reg16 REG> II CPUCore<T>::ld_xword_SS_ED() {
2792 return WR_NN_Y<T::EE_ED>(get16<REG>());
2796template<
typename T>
template<Reg16 REG> II CPUCore<T>::ld_a_SS() {
2797 T::setMemPtr(get16<REG>() + 1);
2798 setA(RDMEM(get16<REG>(), T::CC_LD_A_SS_1));
2799 return {1, T::CC_LD_A_SS};
2803template<
typename T> II CPUCore<T>::ld_a_xbyte() {
2804 unsigned addr = RD_WORD_PC<1>(T::CC_LD_A_NN_1);
2805 T::setMemPtr(addr + 1);
2806 setA(RDMEM(addr, T::CC_LD_A_NN_2));
2807 return {3, T::CC_LD_A_NN};
2811template<
typename T>
template<Reg8 DST,
int EE> II CPUCore<T>::ld_R_byte() {
2812 set8<DST>(RDMEM_OPCODE<1>(T::CC_LD_R_N_1 + EE));
return {2, T::CC_LD_R_N + EE};
2816template<
typename T>
template<Reg8 DST> II CPUCore<T>::ld_R_xhl() {
2817 set8<DST>(RDMEM(getHL(), T::CC_LD_R_HL_1));
return {1, T::CC_LD_R_HL};
2821template<
typename T>
template<Reg8 DST, Reg16 IXY> II CPUCore<T>::ld_R_xix() {
2822 int8_t ofst = RDMEM_OPCODE<1>(T::CC_DD + T::CC_LD_R_XIX_1);
2823 unsigned addr = narrow_cast<word>(get16<IXY>() + ofst);
2825 set8<DST>(RDMEM(addr, T::CC_DD + T::CC_LD_R_XIX_2));
2826 return {2, T::CC_DD + T::CC_LD_R_XIX};
2830template<
typename T>
template<
int EE>
inline word CPUCore<T>::RD_P_XX() {
2831 unsigned addr = RD_WORD_PC<1>(T::CC_LD_HL_XX_1 + EE);
2832 T::setMemPtr(addr + 1);
2833 return RD_WORD(addr, T::CC_LD_HL_XX_2 + EE);
2835template<
typename T>
template<Reg16 REG,
int EE> II CPUCore<T>::ld_SS_xword() {
2836 set16<REG>(RD_P_XX<EE>());
return {3, T::CC_LD_HL_XX + EE};
2838template<
typename T>
template<Reg16 REG> II CPUCore<T>::ld_SS_xword_ED() {
2839 set16<REG>(RD_P_XX<T::EE_ED>());
return {3, T::CC_LD_HL_XX + T::EE_ED};
2843template<
typename T>
template<Reg16 REG,
int EE> II CPUCore<T>::ld_SS_word() {
2844 set16<REG>(RD_WORD_PC<1>(T::CC_LD_SS_NN_1 + EE));
return {3, T::CC_LD_SS_NN + EE};
2849template<
typename T>
inline void CPUCore<T>::ADC(
byte reg) {
2850 unsigned res = getA() + reg + ((getF() & C_FLAG) ? 1 : 0);
2851 byte f = ((res & 0x100) ? C_FLAG : 0) |
2852 ((getA() ^ res ^ reg) & H_FLAG) |
2853 (((getA() ^ res) & (reg ^ res) & 0x80) >> 5) |
2855 if constexpr (T::IS_R800) {
2856 f |= table.
ZS[res & 0xFF];
2857 f |=
byte(getF() & (X_FLAG | Y_FLAG));
2859 f |= table.
ZSXY[res & 0xFF];
2862 setA(narrow_cast<byte>(res));
2864template<
typename T>
inline II CPUCore<T>::adc_a_a() {
2865 unsigned res = 2 * getA() + ((getF() & C_FLAG) ? 1 : 0);
2866 byte f = ((res & 0x100) ? C_FLAG : 0) |
2868 (((getA() ^ res) & 0x80) >> 5) |
2870 if constexpr (T::IS_R800) {
2871 f |= table.
ZS[res & 0xFF];
2872 f |=
byte(getF() & (X_FLAG | Y_FLAG));
2874 f |= table.
ZSXY[res & 0xFF];
2877 setA(narrow_cast<byte>(res));
2878 return {1, T::CC_CP_R};
2880template<
typename T>
template<Reg8 SRC,
int EE> II CPUCore<T>::adc_a_R() {
2881 ADC(get8<SRC>());
return {1, T::CC_CP_R + EE};
2883template<
typename T> II CPUCore<T>::adc_a_byte() {
2884 ADC(RDMEM_OPCODE<1>(T::CC_CP_N_1));
return {2, T::CC_CP_N};
2886template<
typename T> II CPUCore<T>::adc_a_xhl() {
2887 ADC(RDMEM(getHL(), T::CC_CP_XHL_1));
return {1, T::CC_CP_XHL};
2889template<
typename T>
template<Reg16 IXY> II CPUCore<T>::adc_a_xix() {
2890 int8_t ofst = RDMEM_OPCODE<1>(T::CC_DD + T::CC_CP_XIX_1);
2891 unsigned addr = narrow_cast<word>(get16<IXY>() + ofst);
2893 ADC(RDMEM(addr, T::CC_DD + T::CC_CP_XIX_2));
2894 return {2, T::CC_DD + T::CC_CP_XIX};
2898template<
typename T>
inline void CPUCore<T>::ADD(
byte reg) {
2899 unsigned res = getA() + reg;
2900 byte f = ((res & 0x100) ? C_FLAG : 0) |
2901 ((getA() ^ res ^ reg) & H_FLAG) |
2902 (((getA() ^ res) & (reg ^ res) & 0x80) >> 5) |
2904 if constexpr (T::IS_R800) {
2905 f |= table.
ZS[res & 0xFF];
2906 f |=
byte(getF() & (X_FLAG | Y_FLAG));
2908 f |= table.
ZSXY[res & 0xFF];
2911 setA(narrow_cast<byte>(res));
2913template<
typename T>
inline II CPUCore<T>::add_a_a() {
2914 unsigned res = 2 * getA();
2915 byte f = ((res & 0x100) ? C_FLAG : 0) |
2917 (((getA() ^ res) & 0x80) >> 5) |
2919 if constexpr (T::IS_R800) {
2920 f |= table.
ZS[res & 0xFF];
2921 f |=
byte(getF() & (X_FLAG | Y_FLAG));
2923 f |= table.
ZSXY[res & 0xFF];
2926 setA(narrow_cast<byte>(res));
2927 return {1, T::CC_CP_R};
2929template<
typename T>
template<Reg8 SRC,
int EE> II CPUCore<T>::add_a_R() {
2930 ADD(get8<SRC>());
return {1, T::CC_CP_R + EE};
2932template<
typename T> II CPUCore<T>::add_a_byte() {
2933 ADD(RDMEM_OPCODE<1>(T::CC_CP_N_1));
return {2, T::CC_CP_N};
2935template<
typename T> II CPUCore<T>::add_a_xhl() {
2936 ADD(RDMEM(getHL(), T::CC_CP_XHL_1));
return {1, T::CC_CP_XHL};
2938template<
typename T>
template<Reg16 IXY> II CPUCore<T>::add_a_xix() {
2939 int8_t ofst = RDMEM_OPCODE<1>(T::CC_DD + T::CC_CP_XIX_1);
2940 unsigned addr = narrow_cast<word>(get16<IXY>() + ofst);
2942 ADD(RDMEM(addr, T::CC_DD + T::CC_CP_XIX_2));
2943 return {2, T::CC_DD + T::CC_CP_XIX};
2947template<
typename T>
inline void CPUCore<T>::AND(
byte reg) {
2950 if constexpr (T::IS_R800) {
2951 f |= table.
ZSPH[getA()];
2952 f |=
byte(getF() & (X_FLAG | Y_FLAG));
2954 f |= table.
ZSPXY[getA()];
2959template<
typename T> II CPUCore<T>::and_a() {
2961 if constexpr (T::IS_R800) {
2962 f |= table.
ZSPH[getA()];
2963 f |=
byte(getF() & (X_FLAG | Y_FLAG));
2965 f |= table.
ZSPXY[getA()];
2969 return {1, T::CC_CP_R};
2971template<
typename T>
template<Reg8 SRC,
int EE> II CPUCore<T>::and_R() {
2972 AND(get8<SRC>());
return {1, T::CC_CP_R + EE};
2974template<
typename T> II CPUCore<T>::and_byte() {
2975 AND(RDMEM_OPCODE<1>(T::CC_CP_N_1));
return {2, T::CC_CP_N};
2977template<
typename T> II CPUCore<T>::and_xhl() {
2978 AND(RDMEM(getHL(), T::CC_CP_XHL_1));
return {1, T::CC_CP_XHL};
2980template<
typename T>
template<Reg16 IXY> II CPUCore<T>::and_xix() {
2981 int8_t ofst = RDMEM_OPCODE<1>(T::CC_DD + T::CC_CP_XIX_1);
2982 unsigned addr = narrow_cast<word>(get16<IXY>() + ofst);
2984 AND(RDMEM(addr, T::CC_DD + T::CC_CP_XIX_2));
2985 return {2, T::CC_DD + T::CC_CP_XIX};
2989template<
typename T>
inline void CPUCore<T>::CP(
byte reg) {
2990 unsigned q = getA() - reg;
2991 byte f = table.
ZS[q & 0xFF] |
2992 ((q & 0x100) ? C_FLAG : 0) |
2994 ((getA() ^
byte(q) ^ reg) & H_FLAG) |
2995 (((reg ^ getA()) & (getA() ^
byte(q)) & 0x80) >> 5);
2996 if constexpr (T::IS_R800) {
2997 f |=
byte(getF() & (X_FLAG | Y_FLAG));
2999 f |=
byte(reg & (X_FLAG | Y_FLAG));
3003template<
typename T> II CPUCore<T>::cp_a() {
3004 byte f = ZS0 | N_FLAG;
3005 if constexpr (T::IS_R800) {
3006 f |=
byte(getF() & (X_FLAG | Y_FLAG));
3008 f |=
byte(getA() & (X_FLAG | Y_FLAG));
3011 return {1, T::CC_CP_R};
3013template<
typename T>
template<Reg8 SRC,
int EE> II CPUCore<T>::cp_R() {
3014 CP(get8<SRC>());
return {1, T::CC_CP_R + EE};
3016template<
typename T> II CPUCore<T>::cp_byte() {
3017 CP(RDMEM_OPCODE<1>(T::CC_CP_N_1));
return {2, T::CC_CP_N};
3019template<
typename T> II CPUCore<T>::cp_xhl() {
3020 CP(RDMEM(getHL(), T::CC_CP_XHL_1));
return {1, T::CC_CP_XHL};
3022template<
typename T>
template<Reg16 IXY> II CPUCore<T>::cp_xix() {
3023 int8_t ofst = RDMEM_OPCODE<1>(T::CC_DD + T::CC_CP_XIX_1);
3024 unsigned addr = narrow_cast<word>(get16<IXY>() + ofst);
3026 CP(RDMEM(addr, T::CC_DD + T::CC_CP_XIX_2));
3027 return {2, T::CC_DD + T::CC_CP_XIX};
3031template<
typename T>
inline void CPUCore<T>::OR(
byte reg) {
3034 if constexpr (T::IS_R800) {
3035 f |= table.
ZSP[getA()];
3036 f |=
byte(getF() & (X_FLAG | Y_FLAG));
3038 f |= table.
ZSPXY[getA()];
3042template<
typename T> II CPUCore<T>::or_a() {
3044 if constexpr (T::IS_R800) {
3045 f |= table.
ZSP[getA()];
3046 f |=
byte(getF() & (X_FLAG | Y_FLAG));
3048 f |= table.
ZSPXY[getA()];
3051 return {1, T::CC_CP_R};
3053template<
typename T>
template<Reg8 SRC,
int EE> II CPUCore<T>::or_R() {
3054 OR(get8<SRC>());
return {1, T::CC_CP_R + EE};
3056template<
typename T> II CPUCore<T>::or_byte() {
3057 OR(RDMEM_OPCODE<1>(T::CC_CP_N_1));
return {2, T::CC_CP_N};
3059template<
typename T> II CPUCore<T>::or_xhl() {
3060 OR(RDMEM(getHL(), T::CC_CP_XHL_1));
return {1, T::CC_CP_XHL};
3062template<
typename T>
template<Reg16 IXY> II CPUCore<T>::or_xix() {
3063 int8_t ofst = RDMEM_OPCODE<1>(T::CC_DD + T::CC_CP_XIX_1);
3064 unsigned addr = narrow_cast<word>(get16<IXY>() + ofst);
3066 OR(RDMEM(addr, T::CC_DD + T::CC_CP_XIX_2));
3067 return {2, T::CC_DD + T::CC_CP_XIX};
3071template<
typename T>
inline void CPUCore<T>::SBC(
byte reg) {
3072 unsigned res = getA() - reg - ((getF() & C_FLAG) ? 1 : 0);
3073 byte f = ((res & 0x100) ? C_FLAG : 0) |
3075 ((getA() ^ res ^ reg) & H_FLAG) |
3076 (((reg ^ getA()) & (getA() ^ res) & 0x80) >> 5);
3077 if constexpr (T::IS_R800) {
3078 f |= table.
ZS[res & 0xFF];
3079 f |=
byte(getF() & (X_FLAG | Y_FLAG));
3081 f |= table.
ZSXY[res & 0xFF];
3084 setA(narrow_cast<byte>(res));
3086template<
typename T> II CPUCore<T>::sbc_a_a() {
3087 if constexpr (T::IS_R800) {
3088 word t = (getF() & C_FLAG)
3089 ? (255 * 256 | ZS255 | C_FLAG | H_FLAG | N_FLAG)
3090 : ( 0 * 256 | ZS0 | N_FLAG);
3091 setAF(
t | (getF() & (X_FLAG | Y_FLAG)));
3093 setAF((getF() & C_FLAG) ?
3094 (255 * 256 | ZSXY255 | C_FLAG | H_FLAG | N_FLAG) :
3095 ( 0 * 256 | ZSXY0 | N_FLAG));
3097 return {1, T::CC_CP_R};
3099template<
typename T>
template<Reg8 SRC,
int EE> II CPUCore<T>::sbc_a_R() {
3100 SBC(get8<SRC>());
return {1, T::CC_CP_R + EE};
3102template<
typename T> II CPUCore<T>::sbc_a_byte() {
3103 SBC(RDMEM_OPCODE<1>(T::CC_CP_N_1));
return {2, T::CC_CP_N};
3105template<
typename T> II CPUCore<T>::sbc_a_xhl() {
3106 SBC(RDMEM(getHL(), T::CC_CP_XHL_1));
return {1, T::CC_CP_XHL};
3108template<
typename T>
template<Reg16 IXY> II CPUCore<T>::sbc_a_xix() {
3109 int8_t ofst = RDMEM_OPCODE<1>(T::CC_DD + T::CC_CP_XIX_1);
3110 unsigned addr = narrow_cast<word>(get16<IXY>() + ofst);
3112 SBC(RDMEM(addr, T::CC_DD + T::CC_CP_XIX_2));
3113 return {2, T::CC_DD + T::CC_CP_XIX};
3117template<
typename T>
inline void CPUCore<T>::SUB(
byte reg) {
3118 unsigned res = getA() - reg;
3119 byte f = ((res & 0x100) ? C_FLAG : 0) |
3121 ((getA() ^ res ^ reg) & H_FLAG) |
3122 (((reg ^ getA()) & (getA() ^ res) & 0x80) >> 5);
3123 if constexpr (T::IS_R800) {
3124 f |= table.
ZS[res & 0xFF];
3125 f |=
byte(getF() & (X_FLAG | Y_FLAG));
3127 f |= table.
ZSXY[res & 0xFF];
3130 setA(narrow_cast<byte>(res));
3132template<
typename T> II CPUCore<T>::sub_a() {
3133 if constexpr (T::IS_R800) {
3134 word t = 0 * 256 | ZS0 | N_FLAG;
3135 setAF(
t | (getF() & (X_FLAG | Y_FLAG)));
3137 setAF(0 * 256 | ZSXY0 | N_FLAG);
3139 return {1, T::CC_CP_R};
3141template<
typename T>
template<Reg8 SRC,
int EE> II CPUCore<T>::sub_R() {
3142 SUB(get8<SRC>());
return {1, T::CC_CP_R + EE};
3144template<
typename T> II CPUCore<T>::sub_byte() {
3145 SUB(RDMEM_OPCODE<1>(T::CC_CP_N_1));
return {2, T::CC_CP_N};
3147template<
typename T> II CPUCore<T>::sub_xhl() {
3148 SUB(RDMEM(getHL(), T::CC_CP_XHL_1));
return {1, T::CC_CP_XHL};
3150template<
typename T>
template<Reg16 IXY> II CPUCore<T>::sub_xix() {
3151 int8_t ofst = RDMEM_OPCODE<1>(T::CC_DD + T::CC_CP_XIX_1);
3152 unsigned addr = narrow_cast<word>(get16<IXY>() + ofst);
3154 SUB(RDMEM(addr, T::CC_DD + T::CC_CP_XIX_2));
3155 return {2, T::CC_DD + T::CC_CP_XIX};
3159template<
typename T>
inline void CPUCore<T>::XOR(
byte reg) {
3162 if constexpr (T::IS_R800) {
3163 f |= table.
ZSP[getA()];
3164 f |=
byte(getF() & (X_FLAG | Y_FLAG));
3166 f |= table.
ZSPXY[getA()];
3170template<
typename T> II CPUCore<T>::xor_a() {
3171 if constexpr (T::IS_R800) {
3172 word t = 0 * 256 + ZSP0;
3173 setAF(
t | (getF() & (X_FLAG | Y_FLAG)));
3175 setAF(0 * 256 + ZSPXY0);
3177 return {1, T::CC_CP_R};
3179template<
typename T>
template<Reg8 SRC,
int EE> II CPUCore<T>::xor_R() {
3180 XOR(get8<SRC>());
return {1, T::CC_CP_R + EE};
3182template<
typename T> II CPUCore<T>::xor_byte() {
3183 XOR(RDMEM_OPCODE<1>(T::CC_CP_N_1));
return {2, T::CC_CP_N};
3185template<
typename T> II CPUCore<T>::xor_xhl() {
3186 XOR(RDMEM(getHL(), T::CC_CP_XHL_1));
return {1, T::CC_CP_XHL};
3188template<
typename T>
template<Reg16 IXY> II CPUCore<T>::xor_xix() {
3189 int8_t ofst = RDMEM_OPCODE<1>(T::CC_DD + T::CC_CP_XIX_1);
3190 unsigned addr = narrow_cast<word>(get16<IXY>() + ofst);
3192 XOR(RDMEM(addr, T::CC_DD + T::CC_CP_XIX_2));
3193 return {2, T::CC_DD + T::CC_CP_XIX};
3198template<
typename T>
inline byte CPUCore<T>::DEC(
byte reg) {
3200 byte f = ((reg & ~res & 0x80) >> 5) |
3201 (((res & 0x0F) + 1) & H_FLAG) |
3203 if constexpr (T::IS_R800) {
3204 f |=
byte(getF() & (C_FLAG | X_FLAG | Y_FLAG));
3207 f |=
byte(getF() & C_FLAG);
3208 f |= table.
ZSXY[res];
3213template<
typename T>
template<Reg8 REG,
int EE> II CPUCore<T>::dec_R() {
3214 set8<REG>(DEC(get8<REG>()));
return {1, T::CC_INC_R + EE};
3216template<
typename T>
template<
int EE>
inline void CPUCore<T>::DEC_X(
unsigned x) {
3217 byte val = DEC(RDMEM(x, T::CC_INC_XHL_1 + EE));
3218 WRMEM(x, val, T::CC_INC_XHL_2 + EE);
3220template<
typename T> II CPUCore<T>::dec_xhl() {
3222 return {1, T::CC_INC_XHL};
3224template<
typename T>
template<Reg16 IXY> II CPUCore<T>::dec_xix() {
3225 int8_t ofst = RDMEM_OPCODE<1>(T::CC_DD + T::CC_INC_XIX_1);
3226 unsigned addr = narrow_cast<word>(get16<IXY>() + ofst);
3228 DEC_X<T::CC_DD + T::EE_INC_XIX>(addr);
3229 return {2, T::CC_INC_XHL + T::CC_DD + T::EE_INC_XIX};
3233template<
typename T>
inline byte CPUCore<T>::INC(
byte reg) {
3235 byte f = ((reg & -reg & 0x80) >> 5) |
3236 (((reg & 0x0F) - 1) & H_FLAG) |
3238 if constexpr (T::IS_R800) {
3239 f |=
byte(getF() & (C_FLAG | X_FLAG | Y_FLAG));
3242 f |=
byte(getF() & C_FLAG);
3243 f |= table.
ZSXY[reg];
3248template<
typename T>
template<Reg8 REG,
int EE> II CPUCore<T>::inc_R() {
3249 set8<REG>(INC(get8<REG>()));
return {1, T::CC_INC_R + EE};
3251template<
typename T>
template<
int EE>
inline void CPUCore<T>::INC_X(
unsigned x) {
3252 byte val = INC(RDMEM(x, T::CC_INC_XHL_1 + EE));
3253 WRMEM(x, val, T::CC_INC_XHL_2 + EE);
3255template<
typename T> II CPUCore<T>::inc_xhl() {
3257 return {1, T::CC_INC_XHL};
3259template<
typename T>
template<Reg16 IXY> II CPUCore<T>::inc_xix() {
3260 int8_t ofst = RDMEM_OPCODE<1>(T::CC_DD + T::CC_INC_XIX_1);
3261 unsigned addr = narrow_cast<word>(get16<IXY>() + ofst);
3263 INC_X<T::CC_DD + T::EE_INC_XIX>(addr);
3264 return {2, T::CC_INC_XHL + T::CC_DD + T::EE_INC_XIX};
3269template<
typename T>
template<Reg16 REG>
inline II CPUCore<T>::adc_hl_SS() {
3270 unsigned reg = get16<REG>();
3271 T::setMemPtr(getHL() + 1);
3272 unsigned res = getHL() + reg + ((getF() & C_FLAG) ? 1 : 0);
3273 byte f =
byte(res >> 16) |
3275 if constexpr (T::IS_R800) {
3276 f |=
byte(getF() & (X_FLAG | Y_FLAG));
3279 f |=
byte(((getHL() ^ res ^ reg) >> 8) & H_FLAG);
3281 f |=
byte(((getHL() ^ res) & (reg ^ res) & 0x8000) >> 13);
3282 if constexpr (T::IS_R800) {
3283 f |= (res >> 8) & S_FLAG;
3285 f |= (res >> 8) & (S_FLAG | X_FLAG | Y_FLAG);
3288 f |=
byte(((getHL() ^ reg) >> 8) & H_FLAG);
3290 f |=
byte((getHL() & reg & 0x8000) >> 13);
3294 setHL(narrow_cast<word>(res));
3295 return {1, T::CC_ADC_HL_SS};
3297template<
typename T> II CPUCore<T>::adc_hl_hl() {
3298 T::setMemPtr(getHL() + 1);
3299 unsigned res = 2 * getHL() + ((getF() & C_FLAG) ? 1 : 0);
3300 byte f =
byte(res >> 16) |
3302 if constexpr (T::IS_R800) {
3303 f |=
byte(getF() & (X_FLAG | Y_FLAG));
3307 f |=
byte(((getHL() ^ res) & 0x8000) >> 13);
3308 if constexpr (T::IS_R800) {
3309 f |=
byte((res >> 8) & (H_FLAG | S_FLAG));
3311 f |=
byte((res >> 8) & (H_FLAG | S_FLAG | X_FLAG | Y_FLAG));
3315 f |=
byte((getHL() & 0x8000) >> 13);
3319 setHL(narrow_cast<word>(res));
3320 return {1, T::CC_ADC_HL_SS};
3324template<
typename T>
template<Reg16 REG1, Reg16 REG2,
int EE> II CPUCore<T>::add_SS_TT() {
3325 unsigned reg1 = get16<REG1>();
3326 unsigned reg2 = get16<REG2>();
3327 T::setMemPtr(reg1 + 1);
3328 unsigned res = reg1 + reg2;
3329 byte f =
byte(((reg1 ^ res ^ reg2) >> 8) & H_FLAG) |
3332 if constexpr (T::IS_R800) {
3333 f |=
byte(getF() & (S_FLAG | Z_FLAG | V_FLAG | X_FLAG | Y_FLAG));
3335 f |=
byte(getF() & (S_FLAG | Z_FLAG | V_FLAG));
3336 f |=
byte((res >> 8) & (X_FLAG | Y_FLAG));
3339 set16<REG1>(narrow_cast<word>(res));
3340 return {1, T::CC_ADD_HL_SS + EE};
3342template<
typename T>
template<Reg16 REG,
int EE> II CPUCore<T>::add_SS_SS() {
3343 unsigned reg = get16<REG>();
3344 T::setMemPtr(reg + 1);
3345 unsigned res = 2 * reg;
3346 byte f =
byte(res >> 16) |
3348 if constexpr (T::IS_R800) {
3349 f |=
byte(getF() & (S_FLAG | Z_FLAG | V_FLAG | X_FLAG | Y_FLAG));
3350 f |=
byte((res >> 8) & H_FLAG);
3352 f |=
byte(getF() & (S_FLAG | Z_FLAG | V_FLAG));
3353 f |=
byte((res >> 8) & (H_FLAG | X_FLAG | Y_FLAG));
3356 set16<REG>(narrow_cast<word>(res));
3357 return {1, T::CC_ADD_HL_SS + EE};
3361template<
typename T>
template<Reg16 REG>
inline II CPUCore<T>::sbc_hl_SS() {
3362 unsigned reg = get16<REG>();
3363 T::setMemPtr(getHL() + 1);
3364 unsigned res = getHL() - reg - ((getF() & C_FLAG) ? 1 : 0);
3365 byte f = ((res & 0x10000) ? C_FLAG : 0) |
3367 if constexpr (T::IS_R800) {
3368 f |=
byte(getF() & (X_FLAG | Y_FLAG));
3371 f |=
byte(((getHL() ^ res ^ reg) >> 8) & H_FLAG);
3373 f |=
byte(((reg ^ getHL()) & (getHL() ^ res) & 0x8000) >> 13);
3374 if constexpr (T::IS_R800) {
3375 f |=
byte((res >> 8) & S_FLAG);
3377 f |=
byte((res >> 8) & (S_FLAG | X_FLAG | Y_FLAG));
3380 f |=
byte(((getHL() ^ reg) >> 8) & H_FLAG);
3382 f |=
byte(((reg ^ getHL()) & getHL() & 0x8000) >> 13);
3386 setHL(narrow_cast<word>(res));
3387 return {1, T::CC_ADC_HL_SS};
3389template<
typename T> II CPUCore<T>::sbc_hl_hl() {
3390 T::setMemPtr(getHL() + 1);
3391 byte f = T::IS_R800 ? (getF() & (X_FLAG | Y_FLAG)) : 0;
3392 if (getF() & C_FLAG) {
3393 f |= C_FLAG | H_FLAG | S_FLAG | N_FLAG;
3394 if constexpr (!T::IS_R800) {
3395 f |= X_FLAG | Y_FLAG;
3399 f |= Z_FLAG | N_FLAG;
3403 return {1, T::CC_ADC_HL_SS};
3407template<
typename T>
template<Reg16 REG,
int EE> II CPUCore<T>::dec_SS() {
3408 set16<REG>(narrow_cast<word>(get16<REG>() - 1));
return {1, T::CC_INC_SS + EE};
3412template<
typename T>
template<Reg16 REG,
int EE> II CPUCore<T>::inc_SS() {
3413 set16<REG>(narrow_cast<word>(get16<REG>() + 1));
return {1, T::CC_INC_SS + EE};
3418template<
typename T>
template<
unsigned N, Reg8 REG> II CPUCore<T>::bit_N_R() {
3419 byte reg = get8<REG>();
3421 if constexpr (T::IS_R800) {
3423 f |=
byte(getF() & (S_FLAG | V_FLAG | C_FLAG | X_FLAG | Y_FLAG));
3425 f |= (reg & (1 << N)) ? 0 : Z_FLAG;
3427 f |= table.
ZSPH[reg & (1 << N)];
3428 f |=
byte(getF() & C_FLAG);
3429 f |=
byte(reg & (X_FLAG | Y_FLAG));
3432 return {1, T::CC_BIT_R};
3434template<
typename T>
template<
unsigned N>
inline II CPUCore<T>::bit_N_xhl() {
3435 byte m = RDMEM(getHL(), T::CC_BIT_XHL_1) & (1 << N);
3437 if constexpr (T::IS_R800) {
3438 f |=
byte(getF() & (S_FLAG | V_FLAG | C_FLAG | X_FLAG | Y_FLAG));
3440 f |= m ? 0 : Z_FLAG;
3443 f |=
byte(getF() & C_FLAG);
3444 f |=
byte((T::getMemPtr() >> 8) & (X_FLAG | Y_FLAG));
3447 return {1, T::CC_BIT_XHL};
3449template<
typename T>
template<
unsigned N>
inline II CPUCore<T>::bit_N_xix(
unsigned addr) {
3451 byte m = RDMEM(addr, T::CC_DD + T::CC_BIT_XIX_1) & (1 << N);
3453 if constexpr (T::IS_R800) {
3454 f |=
byte(getF() & (S_FLAG | V_FLAG | C_FLAG | X_FLAG | Y_FLAG));
3456 f |= m ? 0 : Z_FLAG;
3459 f |=
byte(getF() & C_FLAG);
3460 f |=
byte((addr >> 8) & (X_FLAG | Y_FLAG));
3463 return {3, T::CC_DD + T::CC_BIT_XIX};
3467static constexpr byte RES(
unsigned b,
byte reg) {
3468 return reg &
byte(~(1 << b));
3470template<
typename T>
template<
unsigned N, Reg8 REG> II CPUCore<T>::res_N_R() {
3471 set8<REG>(RES(N, get8<REG>()));
return {1, T::CC_SET_R};
3473template<
typename T>
template<
int EE>
inline byte CPUCore<T>::RES_X(
unsigned bit,
unsigned addr) {
3474 byte res = RES(bit, RDMEM(addr, T::CC_SET_XHL_1 + EE));
3475 WRMEM(addr, res, T::CC_SET_XHL_2 + EE);
3478template<
typename T>
template<
unsigned N> II CPUCore<T>::res_N_xhl() {
3479 RES_X<0>(N, getHL());
return {1, T::CC_SET_XHL};
3481template<
typename T>
template<
unsigned N, Reg8 REG> II CPUCore<T>::res_N_xix_R(
unsigned a) {
3483 set8<REG>(RES_X<T::CC_DD + T::EE_SET_XIX>(N, a));
3484 return {3, T::CC_DD + T::CC_SET_XIX};
3488static constexpr byte SET(
unsigned b,
byte reg) {
3489 return reg |
byte(1 << b);
3491template<
typename T>
template<
unsigned N, Reg8 REG> II CPUCore<T>::set_N_R() {
3492 set8<REG>(SET(N, get8<REG>()));
return {1, T::CC_SET_R};
3494template<
typename T>
template<
int EE>
inline byte CPUCore<T>::SET_X(
unsigned bit,
unsigned addr) {
3495 byte res = SET(bit, RDMEM(addr, T::CC_SET_XHL_1 + EE));
3496 WRMEM(addr, res, T::CC_SET_XHL_2 + EE);
3499template<
typename T>
template<
unsigned N> II CPUCore<T>::set_N_xhl() {
3500 SET_X<0>(N, getHL());
return {1, T::CC_SET_XHL};
3502template<
typename T>
template<
unsigned N, Reg8 REG> II CPUCore<T>::set_N_xix_R(
unsigned a) {
3504 set8<REG>(SET_X<T::CC_DD + T::EE_SET_XIX>(N, a));
3505 return {3, T::CC_DD + T::CC_SET_XIX};
3509template<
typename T>
inline byte CPUCore<T>::RL(
byte reg) {
3511 reg = narrow_cast<byte>((reg << 1) | ((getF() & C_FLAG) ? 0x01 : 0));
3512 byte f = c ? C_FLAG : 0;
3513 if constexpr (T::IS_R800) {
3514 f |= table.
ZSP[reg];
3515 f |=
byte(getF() & (X_FLAG | Y_FLAG));
3517 f |= table.
ZSPXY[reg];
3522template<
typename T>
template<
int EE>
inline byte CPUCore<T>::RL_X(
unsigned x) {
3523 byte res = RL(RDMEM(x, T::CC_SET_XHL_1 + EE));
3524 WRMEM(x, res, T::CC_SET_XHL_2 + EE);
3527template<
typename T>
template<Reg8 REG> II CPUCore<T>::rl_R() {
3528 set8<REG>(RL(get8<REG>()));
return {1, T::CC_SET_R};
3530template<
typename T> II CPUCore<T>::rl_xhl() {
3531 RL_X<0>(getHL());
return {1, T::CC_SET_XHL};
3533template<
typename T>
template<Reg8 REG> II CPUCore<T>::rl_xix_R(
unsigned a) {
3535 set8<REG>(RL_X<T::CC_DD + T::EE_SET_XIX>(a));
3536 return {3, T::CC_DD + T::CC_SET_XIX};
3540template<
typename T>
inline byte CPUCore<T>::RLC(
byte reg) {
3542 reg = narrow_cast<byte>((reg << 1) | c);
3543 byte f = c ? C_FLAG : 0;
3544 if constexpr (T::IS_R800) {
3545 f |= table.
ZSP[reg];
3546 f |=
byte(getF() & (X_FLAG | Y_FLAG));
3548 f |= table.
ZSPXY[reg];
3553template<
typename T>
template<
int EE>
inline byte CPUCore<T>::RLC_X(
unsigned x) {
3554 byte res = RLC(RDMEM(x, T::CC_SET_XHL_1 + EE));
3555 WRMEM(x, res, T::CC_SET_XHL_2 + EE);
3558template<
typename T>
template<Reg8 REG> II CPUCore<T>::rlc_R() {
3559 set8<REG>(RLC(get8<REG>()));
return {1, T::CC_SET_R};
3561template<
typename T> II CPUCore<T>::rlc_xhl() {
3562 RLC_X<0>(getHL());
return {1, T::CC_SET_XHL};
3564template<
typename T>
template<Reg8 REG> II CPUCore<T>::rlc_xix_R(
unsigned a) {
3566 set8<REG>(RLC_X<T::CC_DD + T::EE_SET_XIX>(a));
3567 return {3, T::CC_DD + T::CC_SET_XIX};
3571template<
typename T>
inline byte CPUCore<T>::RR(
byte reg) {
3573 reg = narrow_cast<byte>((reg >> 1) | ((getF() & C_FLAG) << 7));
3574 byte f = c ? C_FLAG : 0;
3575 if constexpr (T::IS_R800) {
3576 f |= table.
ZSP[reg];
3577 f |=
byte(getF() & (X_FLAG | Y_FLAG));
3579 f |= table.
ZSPXY[reg];
3584template<
typename T>
template<
int EE>
inline byte CPUCore<T>::RR_X(
unsigned x) {
3585 byte res = RR(RDMEM(x, T::CC_SET_XHL_1 + EE));
3586 WRMEM(x, res, T::CC_SET_XHL_2 + EE);
3589template<
typename T>
template<Reg8 REG> II CPUCore<T>::rr_R() {
3590 set8<REG>(RR(get8<REG>()));
return {1, T::CC_SET_R};
3592template<
typename T> II CPUCore<T>::rr_xhl() {
3593 RR_X<0>(getHL());
return {1, T::CC_SET_XHL};
3595template<
typename T>
template<Reg8 REG> II CPUCore<T>::rr_xix_R(
unsigned a) {
3597 set8<REG>(RR_X<T::CC_DD + T::EE_SET_XIX>(a));
3598 return {3, T::CC_DD + T::CC_SET_XIX};
3602template<
typename T>
inline byte CPUCore<T>::RRC(
byte reg) {
3604 reg = narrow_cast<byte>((reg >> 1) | (c << 7));
3605 byte f = c ? C_FLAG : 0;
3606 if constexpr (T::IS_R800) {
3607 f |= table.
ZSP[reg];
3608 f |=
byte(getF() & (X_FLAG | Y_FLAG));
3610 f |= table.
ZSPXY[reg];
3615template<
typename T>
template<
int EE>
inline byte CPUCore<T>::RRC_X(
unsigned x) {
3616 byte res = RRC(RDMEM(x, T::CC_SET_XHL_1 + EE));
3617 WRMEM(x, res, T::CC_SET_XHL_2 + EE);
3620template<
typename T>
template<Reg8 REG> II CPUCore<T>::rrc_R() {
3621 set8<REG>(RRC(get8<REG>()));
return {1, T::CC_SET_R};
3623template<
typename T> II CPUCore<T>::rrc_xhl() {
3624 RRC_X<0>(getHL());
return {1, T::CC_SET_XHL};
3626template<
typename T>
template<Reg8 REG> II CPUCore<T>::rrc_xix_R(
unsigned a) {
3628 set8<REG>(RRC_X<T::CC_DD + T::EE_SET_XIX>(a));
3629 return {3, T::CC_DD + T::CC_SET_XIX};
3633template<
typename T>
inline byte CPUCore<T>::SLA(
byte reg) {
3636 byte f = c ? C_FLAG : 0;
3637 if constexpr (T::IS_R800) {
3638 f |= table.
ZSP[reg];
3639 f |=
byte(getF() & (X_FLAG | Y_FLAG));
3641 f |= table.
ZSPXY[reg];
3646template<
typename T>
template<
int EE>
inline byte CPUCore<T>::SLA_X(
unsigned x) {
3647 byte res = SLA(RDMEM(x, T::CC_SET_XHL_1 + EE));
3648 WRMEM(x, res, T::CC_SET_XHL_2 + EE);
3651template<
typename T>
template<Reg8 REG> II CPUCore<T>::sla_R() {
3652 set8<REG>(SLA(get8<REG>()));
return {1, T::CC_SET_R};
3654template<
typename T> II CPUCore<T>::sla_xhl() {
3655 SLA_X<0>(getHL());
return {1, T::CC_SET_XHL};
3657template<
typename T>
template<Reg8 REG> II CPUCore<T>::sla_xix_R(
unsigned a) {
3659 set8<REG>(SLA_X<T::CC_DD + T::EE_SET_XIX>(a));
3660 return {3, T::CC_DD + T::CC_SET_XIX};
3664template<
typename T>
inline byte CPUCore<T>::SLL(
byte reg) {
3665 assert(!T::IS_R800);
3667 reg = narrow_cast<byte>((reg << 1) | 1);
3668 byte f = c ? C_FLAG : 0;
3669 f |= table.
ZSPXY[reg];
3673template<
typename T>
template<
int EE>
inline byte CPUCore<T>::SLL_X(
unsigned x) {
3674 byte res = SLL(RDMEM(x, T::CC_SET_XHL_1 + EE));
3675 WRMEM(x, res, T::CC_SET_XHL_2 + EE);
3678template<
typename T>
template<Reg8 REG> II CPUCore<T>::sll_R() {
3679 set8<REG>(SLL(get8<REG>()));
return {1, T::CC_SET_R};
3681template<
typename T> II CPUCore<T>::sll_xhl() {
3682 SLL_X<0>(getHL());
return {1, T::CC_SET_XHL};
3684template<
typename T>
template<Reg8 REG> II CPUCore<T>::sll_xix_R(
unsigned a) {
3686 set8<REG>(SLL_X<T::CC_DD + T::EE_SET_XIX>(a));
3687 return {3, T::CC_DD + T::CC_SET_XIX};
3689template<
typename T> II CPUCore<T>::sll2() {
3691 byte f = (getF() & (X_FLAG | Y_FLAG)) |
3695 return {3, T::CC_DD + T::CC_SET_XIX};
3699template<
typename T>
inline byte CPUCore<T>::SRA(
byte reg) {
3701 reg = (reg >> 1) | (reg & 0x80);
3702 byte f = c ? C_FLAG : 0;
3703 if constexpr (T::IS_R800) {
3704 f |= table.
ZSP[reg];
3705 f |=
byte(getF() & (X_FLAG | Y_FLAG));
3707 f |= table.
ZSPXY[reg];
3712template<
typename T>
template<
int EE>
inline byte CPUCore<T>::SRA_X(
unsigned x) {
3713 byte res = SRA(RDMEM(x, T::CC_SET_XHL_1 + EE));
3714 WRMEM(x, res, T::CC_SET_XHL_2 + EE);
3717template<
typename T>
template<Reg8 REG> II CPUCore<T>::sra_R() {
3718 set8<REG>(SRA(get8<REG>()));
return {1, T::CC_SET_R};
3720template<
typename T> II CPUCore<T>::sra_xhl() {
3721 SRA_X<0>(getHL());
return {1, T::CC_SET_XHL};
3723template<
typename T>
template<Reg8 REG> II CPUCore<T>::sra_xix_R(
unsigned a) {
3725 set8<REG>(SRA_X<T::CC_DD + T::EE_SET_XIX>(a));
3726 return {3, T::CC_DD + T::CC_SET_XIX};
3730template<
typename T>
inline byte CPUCore<T>::SRL(
byte reg) {
3733 byte f = c ? C_FLAG : 0;
3734 if constexpr (T::IS_R800) {
3735 f |= table.
ZSP[reg];
3736 f |=
byte(getF() & (X_FLAG | Y_FLAG));
3738 f |= table.
ZSPXY[reg];
3743template<
typename T>
template<
int EE>
inline byte CPUCore<T>::SRL_X(
unsigned x) {
3744 byte res = SRL(RDMEM(x, T::CC_SET_XHL_1 + EE));
3745 WRMEM(x, res, T::CC_SET_XHL_2 + EE);
3748template<
typename T>
template<Reg8 REG> II CPUCore<T>::srl_R() {
3749 set8<REG>(SRL(get8<REG>()));
return {1, T::CC_SET_R};
3751template<
typename T> II CPUCore<T>::srl_xhl() {
3752 SRL_X<0>(getHL());
return {1, T::CC_SET_XHL};
3754template<
typename T>
template<Reg8 REG> II CPUCore<T>::srl_xix_R(
unsigned a) {
3756 set8<REG>(SRL_X<T::CC_DD + T::EE_SET_XIX>(a));
3757 return {3, T::CC_DD + T::CC_SET_XIX};
3761template<
typename T> II CPUCore<T>::rla() {
3762 byte c = getF() & C_FLAG;
3763 byte f = (getA() & 0x80) ? C_FLAG : 0;
3764 if constexpr (T::IS_R800) {
3765 f |=
byte(getF() & (S_FLAG | Z_FLAG | P_FLAG | X_FLAG | Y_FLAG));
3767 f |=
byte(getF() & (S_FLAG | Z_FLAG | P_FLAG));
3769 setA(narrow_cast<byte>((getA() << 1) | (c ? 1 : 0)));
3770 if constexpr (!T::IS_R800) {
3771 f |=
byte(getA() & (X_FLAG | Y_FLAG));
3774 return {1, T::CC_RLA};
3776template<
typename T> II CPUCore<T>::rlca() {
3777 setA(narrow_cast<byte>((getA() << 1) | (getA() >> 7)));
3779 if constexpr (T::IS_R800) {
3780 f |=
byte(getF() & (S_FLAG | Z_FLAG | P_FLAG | X_FLAG | Y_FLAG));
3781 f |=
byte(getA() & C_FLAG);
3783 f |=
byte(getF() & (S_FLAG | Z_FLAG | P_FLAG));
3784 f |=
byte(getA() & (Y_FLAG | X_FLAG | C_FLAG));
3787 return {1, T::CC_RLA};
3789template<
typename T> II CPUCore<T>::rra() {
3790 auto c =
byte((getF() & C_FLAG) << 7);
3791 byte f = (getA() & 0x01) ? C_FLAG : 0;
3792 if constexpr (T::IS_R800) {
3793 f |=
byte(getF() & (S_FLAG | Z_FLAG | P_FLAG | X_FLAG | Y_FLAG));
3795 f |=
byte(getF() & (S_FLAG | Z_FLAG | P_FLAG));
3797 setA((getA() >> 1) | c);
3798 if constexpr (!T::IS_R800) {
3799 f |=
byte(getA() & (X_FLAG | Y_FLAG));
3802 return {1, T::CC_RLA};
3804template<
typename T> II CPUCore<T>::rrca() {
3805 byte f = getA() & C_FLAG;
3806 if constexpr (T::IS_R800) {
3807 f |=
byte(getF() & (S_FLAG | Z_FLAG | P_FLAG | X_FLAG | Y_FLAG));
3809 f |=
byte(getF() & (S_FLAG | Z_FLAG | P_FLAG));
3811 setA(narrow_cast<byte>((getA() >> 1) | (getA() << 7)));
3812 if constexpr (!T::IS_R800) {
3813 f |=
byte(getA() & (X_FLAG | Y_FLAG));
3816 return {1, T::CC_RLA};
3821template<
typename T> II CPUCore<T>::rld() {
3822 byte val = RDMEM(getHL(), T::CC_RLD_1);
3823 T::setMemPtr(getHL() + 1);
3824 WRMEM(getHL(), narrow_cast<byte>((val << 4) | (getA() & 0x0F)), T::CC_RLD_2);
3825 setA((getA() & 0xF0) | (val >> 4));
3827 if constexpr (T::IS_R800) {
3828 f |=
byte(getF() & (C_FLAG | X_FLAG | Y_FLAG));
3829 f |= table.
ZSP[getA()];
3831 f |=
byte(getF() & C_FLAG);
3832 f |= table.
ZSPXY[getA()];
3835 return {1, T::CC_RLD};
3839template<
typename T> II CPUCore<T>::rrd() {
3840 byte val = RDMEM(getHL(), T::CC_RLD_1);
3841 T::setMemPtr(getHL() + 1);
3842 WRMEM(getHL(), narrow_cast<byte>((val >> 4) | (getA() << 4)), T::CC_RLD_2);
3843 setA((getA() & 0xF0) | (val & 0x0F));
3845 if constexpr (T::IS_R800) {
3846 f |=
byte(getF() & (C_FLAG | X_FLAG | Y_FLAG));
3847 f |= table.
ZSP[getA()];
3849 f |=
byte(getF() & C_FLAG);
3850 f |= table.
ZSPXY[getA()];
3853 return {1, T::CC_RLD};
3858template<
typename T>
template<
int EE>
inline void CPUCore<T>::PUSH(
word reg) {
3860 WR_WORD_rev<true, true>(getSP(), reg, T::CC_PUSH_1 + EE);
3862template<
typename T>
template<Reg16 REG,
int EE> II CPUCore<T>::push_SS() {
3863 PUSH<EE>(get16<REG>());
return {1, T::CC_PUSH + EE};
3867template<
typename T>
template<
int EE>
inline word CPUCore<T>::POP() {
3868 word addr = getSP();
3870 if constexpr (T::IS_R800) {
3872 if constexpr (EE == 0) {
3880 return RD_WORD(addr, T::CC_POP_1 + EE);
3882template<
typename T>
template<Reg16 REG,
int EE> II CPUCore<T>::pop_SS() {
3883 set16<REG>(POP<EE>());
return {1, T::CC_POP + EE};
3888template<
typename T>
template<
typename COND> II CPUCore<T>::call(COND cond) {
3889 word addr = RD_WORD_PC<1>(T::CC_CALL_1);
3892 PUSH<T::EE_CALL>(getPC() + 3);
3894 if constexpr (T::IS_R800) {
3896 setSlowInstructions();
3898 return {0, T::CC_CALL_A};
3900 return {3, T::CC_CALL_B};
3906template<
typename T>
template<
unsigned ADDR> II CPUCore<T>::rst() {
3907 PUSH<0>(getPC() + 1);
3910 if constexpr (T::IS_R800) {
3912 setSlowInstructions();
3914 return {0, T::CC_RST};
3919template<
typename T>
template<
int EE,
typename COND>
inline II CPUCore<T>::RET(COND cond) {
3921 auto addr = POP<EE>();
3924 return {0, T::CC_RET_A + EE};
3926 return {1, T::CC_RET_B + EE};
3929template<
typename T>
template<
typename COND> II CPUCore<T>::ret(COND cond) {
3930 return RET<T::EE_RET_C>(cond);
3932template<
typename T> II CPUCore<T>::ret() {
3933 return RET<0>(CondTrue());
3935template<
typename T> II CPUCore<T>::retn() {
3937 setSlowInstructions();
3938 return RET<T::EE_RETN>(CondTrue());
3943template<
typename T>
template<Reg16 REG,
int EE> II CPUCore<T>::jp_SS() {
3944 setPC(get16<REG>()); T::R800ForcePageBreak();
return {0, T::CC_JP_HL + EE};
3948template<
typename T>
template<
typename COND> II CPUCore<T>::jp(COND cond) {
3949 word addr = RD_WORD_PC<1>(T::CC_JP_1);
3953 T::R800ForcePageBreak();
3954 return {0, T::CC_JP_A};
3956 return {3, T::CC_JP_B};
3961template<
typename T>
template<
typename COND> II CPUCore<T>::jr(COND cond) {
3962 int8_t ofst = RDMEM_OPCODE<1>(T::CC_JR_1);
3964 if (((getPC() + 2) & 0xFF) == 0) {
3992 T::R800ForcePageBreak();
3994 setPC(narrow_cast<word>(getPC() + 2 + ofst));
3995 T::setMemPtr(getPC());
3996 return {0, T::CC_JR_A};
3998 return {2, T::CC_JR_B};
4003template<
typename T> II CPUCore<T>::djnz() {
4004 byte b = getB() - 1;
4006 int8_t ofst = RDMEM_OPCODE<1>(T::CC_JR_1 + T::EE_DJNZ);
4008 if (((getPC() + 2) & 0xFF) == 0) {
4010 T::R800ForcePageBreak();
4012 setPC(narrow_cast<word>(getPC() + 2 + ofst));
4013 T::setMemPtr(getPC());
4014 return {0, T::CC_JR_A + T::EE_DJNZ};
4016 return {2, T::CC_JR_B + T::EE_DJNZ};
4021template<
typename T>
template<Reg16 REG,
int EE> II CPUCore<T>::ex_xsp_SS() {
4022 word res = RD_WORD_impl<true, false>(getSP(), T::CC_EX_SP_HL_1 + EE);
4024 WR_WORD_rev<false, true>(getSP(), get16<REG>(), T::CC_EX_SP_HL_2 + EE);
4026 return {1, T::CC_EX_SP_HL + EE};
4030template<
typename T>
template<Reg8 REG> II CPUCore<T>::in_R_c() {
4031 if constexpr (T::IS_R800) T::waitForEvenCycle(T::CC_IN_R_C_1);
4032 T::setMemPtr(getBC() + 1);
4033 byte res = READ_PORT(getBC(), T::CC_IN_R_C_1);
4035 if constexpr (T::IS_R800) {
4036 f |=
byte(getF() & (C_FLAG | X_FLAG | Y_FLAG));
4037 f |= table.
ZSP[res];
4039 f |=
byte(getF() & C_FLAG);
4040 f |= table.
ZSPXY[res];
4044 return {1, T::CC_IN_R_C};
4048template<
typename T> II CPUCore<T>::in_a_byte() {
4049 unsigned y = RDMEM_OPCODE<1>(T::CC_IN_A_N_1) + 256 * getA();
4050 T::setMemPtr(y + 1);
4051 if constexpr (T::IS_R800) T::waitForEvenCycle(T::CC_IN_A_N_2);
4052 setA(READ_PORT(narrow_cast<word>(y), T::CC_IN_A_N_2));
4053 return {2, T::CC_IN_A_N};
4057template<
typename T>
template<Reg8 REG> II CPUCore<T>::out_c_R() {
4058 if constexpr (T::IS_R800) T::waitForEvenCycle(T::CC_OUT_C_R_1);
4059 T::setMemPtr(getBC() + 1);
4060 WRITE_PORT(getBC(), get8<REG>(), T::CC_OUT_C_R_1);
4061 return {1, T::CC_OUT_C_R};
4063template<
typename T> II CPUCore<T>::out_c_0() {
4065 if constexpr (T::IS_R800) T::waitForEvenCycle(T::CC_OUT_C_R_1);
4066 T::setMemPtr(getBC() + 1);
4067 byte out_c_x = isCMOS ? 255 : 0;
4068 WRITE_PORT(getBC(), out_c_x, T::CC_OUT_C_R_1);
4069 return {1, T::CC_OUT_C_R};
4073template<
typename T> II CPUCore<T>::out_byte_a() {
4074 byte port = RDMEM_OPCODE<1>(T::CC_OUT_N_A_1);
4075 auto y = narrow_cast<word>((getA() << 8) | port);
4076 T::setMemPtr((getA() << 8) | ((port + 1) & 255));
4077 if constexpr (T::IS_R800) T::waitForEvenCycle(T::CC_OUT_N_A_2);
4078 WRITE_PORT(y, getA(), T::CC_OUT_N_A_2);
4079 return {2, T::CC_OUT_N_A};
4084template<
typename T>
inline II CPUCore<T>::BLOCK_CP(
int increase,
bool repeat) {
4085 T::setMemPtr(T::getMemPtr() + increase);
4086 byte val = RDMEM(getHL(), T::CC_CPI_1);
4087 byte res = getA() - val;
4088 setHL(narrow_cast<word>(getHL() + increase));
4090 byte f = ((getA() ^ val ^ res) & H_FLAG) |
4093 (getBC() ? V_FLAG : 0);
4094 if constexpr (T::IS_R800) {
4095 f |=
byte(getF() & (C_FLAG | X_FLAG | Y_FLAG));
4097 f |=
byte(getF() & C_FLAG);
4098 unsigned k = res - ((f & H_FLAG) >> 4);
4099 f |= (k << 4) & Y_FLAG;
4103 if (
repeat && getBC() && res) {
4105 T::setMemPtr(getPC() + 1);
4106 return {
word(-1), T::CC_CPIR};
4108 return {1, T::CC_CPI};
4111template<
typename T> II CPUCore<T>::cpd() {
return BLOCK_CP(-1,
false); }
4112template<
typename T> II CPUCore<T>::cpi() {
return BLOCK_CP( 1,
false); }
4113template<
typename T> II CPUCore<T>::cpdr() {
return BLOCK_CP(-1,
true ); }
4114template<
typename T> II CPUCore<T>::cpir() {
return BLOCK_CP( 1,
true ); }
4118template<
typename T>
inline II CPUCore<T>::BLOCK_LD(
int increase,
bool repeat) {
4119 byte val = RDMEM(getHL(), T::CC_LDI_1);
4120 WRMEM(getDE(), val, T::CC_LDI_2);
4121 setHL(narrow_cast<word>(getHL() + increase));
4122 setDE(narrow_cast<word>(getDE() + increase));
4124 byte f = getBC() ? V_FLAG : 0;
4125 if constexpr (T::IS_R800) {
4126 f |=
byte(getF() & (S_FLAG | Z_FLAG | C_FLAG | X_FLAG | Y_FLAG));
4128 f |=
byte(getF() & (S_FLAG | Z_FLAG | C_FLAG));
4129 f |=
byte(((getA() + val) << 4) & Y_FLAG);
4130 f |=
byte((getA() + val) & X_FLAG);
4135 T::setMemPtr(getPC() + 1);
4136 return {
word(-1), T::CC_LDIR};
4138 return {1, T::CC_LDI};
4141template<
typename T> II CPUCore<T>::ldd() {
return BLOCK_LD(-1,
false); }
4142template<
typename T> II CPUCore<T>::ldi() {
return BLOCK_LD( 1,
false); }
4143template<
typename T> II CPUCore<T>::lddr() {
return BLOCK_LD(-1,
true ); }
4144template<
typename T> II CPUCore<T>::ldir() {
return BLOCK_LD( 1,
true ); }
4148template<
typename T>
inline II CPUCore<T>::BLOCK_IN(
int increase,
bool repeat) {
4149 if constexpr (T::IS_R800) T::waitForEvenCycle(T::CC_INI_1);
4150 T::setMemPtr(getBC() + increase);
4151 setBC(getBC() - 0x100);
4152 byte val = READ_PORT(getBC(), T::CC_INI_1);
4153 WRMEM(getHL(), val, T::CC_INI_2);
4154 setHL(narrow_cast<word>(getHL() + increase));
4155 unsigned k = val + ((getC() + increase) & 0xFF);
4157 if constexpr (T::IS_R800) {
4158 setF((getF() & ~Z_FLAG) | (b ? 0 : Z_FLAG) | N_FLAG);
4160 setF(((val & S_FLAG) >> 6) |
4161 ((k & 0x100) ? (H_FLAG | C_FLAG) : 0) |
4163 (table.
ZSPXY[(k & 0x07) ^ b] & P_FLAG));
4167 return {
word(-1), T::CC_INIR};
4169 return {1, T::CC_INI};
4172template<
typename T> II CPUCore<T>::ind() {
return BLOCK_IN(-1,
false); }
4173template<
typename T> II CPUCore<T>::ini() {
return BLOCK_IN( 1,
false); }
4174template<
typename T> II CPUCore<T>::indr() {
return BLOCK_IN(-1,
true ); }
4175template<
typename T> II CPUCore<T>::inir() {
return BLOCK_IN( 1,
true ); }
4179template<
typename T>
inline II CPUCore<T>::BLOCK_OUT(
int increase,
bool repeat) {
4180 byte val = RDMEM(getHL(), T::CC_OUTI_1);
4181 setHL(narrow_cast<word>(getHL() + increase));
4182 if constexpr (T::IS_R800) T::waitForEvenCycle(T::CC_OUTI_2);
4183 WRITE_PORT(getBC(), val, T::CC_OUTI_2);
4184 setBC(getBC() - 0x100);
4185 T::setMemPtr(getBC() + increase);
4186 unsigned k = val + getL();
4188 if constexpr (T::IS_R800) {
4189 setF((getF() & ~Z_FLAG) | (b ? 0 : Z_FLAG) | N_FLAG);
4191 setF(((val & S_FLAG) >> 6) |
4192 ((k & 0x100) ? (H_FLAG | C_FLAG) : 0) |
4194 (table.
ZSPXY[(k & 0x07) ^ b] & P_FLAG));
4198 return {
word(-1), T::CC_OTIR};
4200 return {1, T::CC_OUTI};
4203template<
typename T> II CPUCore<T>::outd() {
return BLOCK_OUT(-1,
false); }
4204template<
typename T> II CPUCore<T>::outi() {
return BLOCK_OUT( 1,
false); }
4205template<
typename T> II CPUCore<T>::otdr() {
return BLOCK_OUT(-1,
true ); }
4206template<
typename T> II CPUCore<T>::otir() {
return BLOCK_OUT( 1,
true ); }
4210template<
typename T>
template<
int EE> II CPUCore<T>::nop() {
return {1, T::CC_NOP + EE}; }
4211template<
typename T> II CPUCore<T>::ccf() {
4213 if constexpr (T::IS_R800) {
4215 f |=
byte(getF() & (S_FLAG | Z_FLAG | P_FLAG | C_FLAG | X_FLAG | Y_FLAG | H_FLAG));
4217 f |=
byte((getF() & C_FLAG) << 4);
4221 f |=
byte(getF() & (S_FLAG | Z_FLAG | P_FLAG | C_FLAG | Y_FLAG));
4222 f |=
byte((getF() | getA()) & X_FLAG);
4224 f |=
byte(getF() & (S_FLAG | Z_FLAG | P_FLAG | C_FLAG));
4225 f |=
byte((getF() | getA()) & (X_FLAG | Y_FLAG));
4230 return {1, T::CC_CCF};
4232template<
typename T> II CPUCore<T>::cpl() {
4233 setA(getA() ^ 0xFF);
4234 byte f = H_FLAG | N_FLAG;
4235 if constexpr (T::IS_R800) {
4238 f |=
byte(getF() & (S_FLAG | Z_FLAG | P_FLAG | C_FLAG));
4239 f |=
byte(getA() & (X_FLAG | Y_FLAG));
4242 return {1, T::CC_CPL};
4244template<
typename T> II CPUCore<T>::daa() {
4248 if ((f & H_FLAG) || ((getA() & 0xf) > 9)) adjust += 6;
4249 if ((f & C_FLAG) || (getA() > 0x99)) adjust += 0x60;
4250 if (f & N_FLAG) a -= adjust;
else a += adjust;
4251 if constexpr (T::IS_R800) {
4252 f &= C_FLAG | N_FLAG | X_FLAG | Y_FLAG;
4255 f &= C_FLAG | N_FLAG;
4256 f |= table.
ZSPXY[a];
4258 f |=
byte((getA() > 0x99) | ((getA() ^ a) & H_FLAG));
4261 return {1, T::CC_DAA};
4263template<
typename T> II CPUCore<T>::neg() {
4265 unsigned a = getA();
4266 unsigned res = -signed(a);
4267 byte f = ((res & 0x100) ? C_FLAG : 0) |
4269 ((res ^ a) & H_FLAG) |
4270 ((a & res & 0x80) >> 5);
4271 if constexpr (T::IS_R800) {
4272 f |= table.
ZS[res & 0xFF];
4273 f |=
byte(getF() & (X_FLAG | Y_FLAG));
4275 f |= table.
ZSXY[res & 0xFF];
4278 setA(narrow_cast<byte>(res));
4279 return {1, T::CC_NEG};
4281template<
typename T> II CPUCore<T>::scf() {
4283 if constexpr (T::IS_R800) {
4284 f |=
byte(getF() & (S_FLAG | Z_FLAG | P_FLAG | X_FLAG | Y_FLAG));
4289 f |=
byte(getF() & (S_FLAG | Z_FLAG | P_FLAG | Y_FLAG));
4290 f |=
byte((getF() | getA()) & X_FLAG);
4292 f |=
byte(getF() & (S_FLAG | Z_FLAG | P_FLAG));
4293 f |=
byte((getF() | getA()) & (X_FLAG | Y_FLAG));
4297 return {1, T::CC_SCF};
4300template<
typename T> II CPUCore<T>::ex_af_af() {
4301 auto t = getAF2(); setAF2(getAF()); setAF(
t);
4302 return {1, T::CC_EX};
4304template<
typename T> II CPUCore<T>::ex_de_hl() {
4305 auto t = getDE(); setDE(getHL()); setHL(
t);
4306 return {1, T::CC_EX};
4308template<
typename T> II CPUCore<T>::exx() {
4309 auto t1 = getBC2(); setBC2(getBC()); setBC(t1);
4310 auto t2 = getDE2(); setDE2(getDE()); setDE(t2);
4311 auto t3 = getHL2(); setHL2(getHL()); setHL(t3);
4312 return {1, T::CC_EX};
4315template<
typename T> II CPUCore<T>::di() {
4318 return {1, T::CC_DI};
4320template<
typename T> II CPUCore<T>::ei() {
4324 setSlowInstructions();
4325 return {1, T::CC_EI};
4327template<
typename T> II CPUCore<T>::halt() {
4329 setSlowInstructions();
4331 if (!(getIFF1() || getIFF2())) {
4332 diHaltCallback.execute();
4334 return {1, T::CC_HALT};
4336template<
typename T>
template<
unsigned N> II CPUCore<T>::im_N() {
4337 setIM(N);
return {1, T::CC_IM};
4341template<
typename T>
template<Reg8 REG> II CPUCore<T>::ld_a_IR() {
4343 byte f = getIFF2() ? V_FLAG : 0;
4344 if constexpr (T::IS_R800) {
4345 f |=
byte(getF() & (C_FLAG | X_FLAG | Y_FLAG));
4346 f |= table.
ZS[getA()];
4348 f |=
byte(getF() & C_FLAG);
4349 f |= table.
ZSXY[getA()];
4352 setSlowInstructions();
4355 return {1, T::CC_LD_A_I};
4359template<
typename T> II CPUCore<T>::ld_r_a() {
4368 if constexpr (T::IS_R800) val -= 1;
4370 return {1, T::CC_LD_A_I};
4372template<
typename T> II CPUCore<T>::ld_i_a() {
4374 return {1, T::CC_LD_A_I};
4378template<
typename T>
template<Reg8 REG> II CPUCore<T>::mulub_a_R() {
4385 setHL(
word(getA()) *
word(get8<REG>()));
4386 setF((getF() & (N_FLAG | H_FLAG | X_FLAG | Y_FLAG)) |
4388 (getHL() ? 0 : Z_FLAG) |
4389 ((getHL() & 0xFF00) ? C_FLAG : 0));
4390 return {1, T::CC_MULUB};
4394template<
typename T>
template<Reg16 REG> II CPUCore<T>::muluw_hl_SS() {
4401 uint32_t res = uint32_t(getHL()) * get16<REG>();
4402 setDE(narrow_cast<word>(res >> 16));
4403 setHL(narrow_cast<word>(res >> 0));
4404 setF((getF() & (N_FLAG | H_FLAG | X_FLAG | Y_FLAG)) |
4406 (res ? 0 : Z_FLAG) |
4407 ((res & 0xFFFF0000) ? C_FLAG : 0));
4408 return {1, T::CC_MULUW};
4418template<
typename T>
template<
typename Archive>
4422 ar.serialize(
"regs",
static_cast<CPURegs&
>(*
this));
4423 if (ar.versionBelow(version, 2)) {
4425 ar.serialize(
"memptr", mPtr);
4429 if (ar.versionBelow(version, 5)) {
4438 ar.serialize(
"nmiEdge", nmiEdge);
4447 if constexpr (T::IS_R800) {
4448 if (ar.versionBelow(version, 4)) {
4449 motherboard.getMSXCliComm().printWarning(
4450 "Loading an old savestate: the timing of the R800 "
4451 "emulation has changed. This may cause synchronization "
4452 "problems in replay.");
#define MAYBE_UNUSED_LABEL
void lowerIRQ()
Lowers the maskable interrupt count.
void setNextSyncPoint(EmuTime::param time)
void disasmCommand(Interpreter &interp, std::span< const TclObject > tokens, TclObject &result) const
void setFreq(unsigned freq)
Change the clock freq.
void execute(bool fastForward)
void warp(EmuTime::param time)
CPUCore(MSXMotherBoard &motherboard, const std::string &name, const BooleanSetting &traceSetting, TclCallback &diHaltCallback, EmuTime::param time)
void lowerNMI()
Lowers the non-maskable interrupt count.
void exitCPULoopSync()
Request to exit the main CPU emulation loop.
EmuTime::param getCurrentTime() const
void exitCPULoopAsync()
Similar to exitCPULoopSync(), but this method may be called from any thread.
void raiseNMI()
Raises the non-maskable interrupt count.
void serialize(Archive &ar, unsigned version)
void doReset(EmuTime::param time)
Reset the CPU.
void wait(EmuTime::param time)
EmuTime waitCycles(EmuTime::param time, unsigned cycles)
bool isM1Cycle(unsigned address) const
void raiseIRQ()
Raises the maskable interrupt count.
void addListElement(const T &t)
ALWAYS_INLINE uint16_t read_UA_L16(const void *p)
ALWAYS_INLINE void write_UA_L16(void *p, uint16_t x)
bool isMainThread()
Returns true when called from the main thread.
This file implemented 3 utility functions:
uint8_t byte
8 bit unsigned integer
unsigned dasm(const MSXCPUInterface &interface, word pc, std::span< byte, 4 > buf, std::string &dest, EmuTime::param time)
Disassemble.
uint16_t word
16 bit unsigned integer
void serialize(Archive &ar, T &t, unsigned version)
std::array< const EDStorage, 4 > A
std::array< const A, 3 > A2
#define INSTANTIATE_SERIALIZE_METHODS(CLASS)
TemporaryString tmpStrCat(Ts &&... ts)
bool operator()(byte f) const
bool operator()(byte f) const
bool operator()(byte f) const
bool operator()(byte f) const
bool operator()(byte f) const
bool operator()(byte f) const
bool operator()(byte f) const
bool operator()(byte) const
bool operator()(byte f) const
std::array< byte, 256 > ZSPXY
std::array< byte, 256 > ZSP
std::array< byte, 256 > ZSPH
std::array< byte, 256 > ZSXY
std::array< byte, 256 > ZS
constexpr void repeat(T n, Op op)
Repeat the given operation 'op' 'n' times.
constexpr auto xrange(T e)