openMSX
CPUCore.cc
Go to the documentation of this file.
1 // MEMORY EMULATION
2 // ----------------
3 //
4 // Memory access emulation is a very important part of the CPU emulation.
5 // Because they happen so frequently they really need to be executed as fast as
6 // possible otherwise they will completely bring down the speed of the CPU
7 // emulation.
8 //
9 // A very fast way to emulate memory accesses is by simply reading/writing to a
10 // 64kb array (for a 16-bit address space). Unfortunately this doesn't allow
11 // for memory mapped IO (MMIO). These are memory regions where read/writes
12 // trigger side effects, so where we need to execute device-specific code on
13 // read or writes. An alternative that does work with MMIO is for every access
14 // execute a virtual method call, (this is the approach taken by most current
15 // MSX emulators). Unfortunately this is also a lot slower.
16 //
17 // It is possible to combine the speed of array accesses with the flexibility
18 // of virtual methods. In openMSX it's implemened as follows: the 64kb address
19 // space is divided in 256 regions of 256 bytes (called cacheLines in the code
20 // below). For each such region we store a pointer, if this pointer is nullptr
21 // then we have to use the slow way (=virtual method call). If it is not nullptr,
22 // the pointer points to a block of memory that can be directly accessed. In
23 // some contexts accesses via the pointer are known as backdoor accesses while
24 // the accesses directly to the device are known as frontdoor accesses.
25 //
26 // We keep different pointers for read and write accesses. This allows to also
27 // implement ROMs efficiently: read is handled as regular RAM, but writes end
28 // up in some dummy memory region. This region is called 'unmappedWrite' in the
29 // code. There is also a special region 'unmappedRead', this region is filled
30 // with 0xFF and can be used to model (parts of) a device that don't react to
31 // reads (so reads return 0xFF).
32 //
33 // Because of bankswitching (the MSX slot select mechanism, but also e.g.
34 // MegaROM backswitching) the memory map as seen by the Z80 is not static. This
35 // means that the cacheLine pointers also need to change during runtime. To
36 // solve this we made the bankswitch code also responsible for invalidating the
37 // cacheLines of the switched region. These pointers are filled-in again in a
38 // lazy way: the first read or write to a cache line will first get this
39 // pointer (see getReadCacheLine() and getWriteCacheLine() in the code below),
40 // from then on this pointer is used for all further accesses to this region,
41 // until the cache is invalidated again.
42 //
43 //
44 // INSTRUCTION EMULATION
45 // ---------------------
46 //
47 // UPDATE: the 'threaded interpreter model' is not enabled by default
48 // main reason is the huge memory requirement while compiling
49 // and that it doesn't work on non-gcc compilers
50 //
51 // The current implementation is based on a 'threaded interpreter model'. In
52 // the text below I'll call the older implementation the 'traditional
53 // interpreter model'. From a very high level these two models look like this:
54 //
55 // Traditional model:
56 // while (!needExit()) {
57 // byte opcode = fetch(PC++);
58 // switch (opcode) {
59 // case 0x00: nop(); break;
60 // case 0x01: ld_bc_nn(); break;
61 // ...
62 // }
63 // }
64 //
65 // Threaded model:
66 // byte opcode = fetch(PC++); //
67 // goto *(table[opcode]); // fetch-and-dispatch
68 // // note: the goto * syntax is a gcc extension called computed-gotos
69 //
70 // op00: nop(); if (!needExit()) [fetch-and-dispatch];
71 // op01: ld_bc_nn(); if (!needExit()) [fetch-and-dispatch];
72 // ...
73 //
74 // In the first model there is a central place in the code that fetches (the
75 // first byte of) the instruction and based on this byte jumps to the
76 // appropriate routine. In the second model, this fetch-and-dispatch logic is
77 // duplicated at the end of each instruction.
78 //
79 // Typically the 'dispatch' part in above paragraph is implemented (either by
80 // the compiler or manually using computed goto's) via a jump table. Thus on
81 // assembler level via an indirect jump. For the host CPU it's hard to predict
82 // the destination address of such an indirect jump, certainly if there's only
83 // one such jump for all dispatching (the traditional model). If each
84 // instruction has its own indirect jump instruction (the threaded model), it
85 // becomes a bit easier, because often one particular z80 instructions is
86 // followed by a specific other z80 instruction (or one from a small subset).
87 // For example a z80 'cp' instruction is most likely followed by a 'conditional
88 // jump' z80 instruction. Modern CPUs are quite sensitive to
89 // branch-(mis)predictions, so the above optimization helps quite a lot. I
90 // measured a speedup of more than 10%!
91 //
92 // There is another advantage to the threaded model. Because also the
93 // needExit() test is duplicated for each instruction, it becomes possible to
94 // tweak it for individual instructions. But first let me explain this
95 // exit-test in more detail.
96 //
97 // These are the main reasons why the emulator should stop emulating CPU
98 // instructions:
99 // 1) When other devices than the CPU must be emulated (e.g. video frame
100 // rendering). In openMSX this is handled by the Scheduler class and
101 // actually we don't exit the CPU loop (anymore) for this. Instead we
102 // simply execute the device code as a subroutine. Each time right before
103 // we access an IO port or do a frontdoor memory access, there is a check
104 // whether we should emulate device code (search for schedule() in the code
105 // below).
106 // 2) To keep the inner CPU loop as fast as possible we don't check for IRQ,
107 // NMI or HALT status in this loop. Instead this condition is checked only
108 // once at the beginning outside of the loop (if there wasn't a pending IRQ
109 // on the first instruction there also won't be one on the second
110 // instruction, if all we did was emulating cpu instructions). Now when one
111 // of these conditions changes, we must exit the inner loop and re-evaluate
112 // them. For example after an EI instruction we must check the IRQ status
113 // again.
114 // 3) Various reasons like:
115 // * Z80/R800 switch
116 // * executing a Tcl command (could be a cpu-register debug read)
117 // * exit the emulator
118 // 4) 'once-in-a-while': To avoid threading problems and race conditions,
119 // several threads in openMSX only 'schedule' work that will later be
120 // executed by the main emulation thread. The main thread checks for such
121 // task outside of the cpu emulation loop. So once-in-a-while we need to
122 // exit the loop. The exact timing doesn't matter here because anyway the
123 // relative timing between threads is undefined.
124 // So for 1) we don't need to do anything (we don't actually exit). For 2) and
125 // 3) we need the exit the loop as soon as possible (right after the current
126 // instruction is finished). For 4) it's OK to exit 'eventually' (a few hundred
127 // z80 instructions late is still OK).
128 //
129 // Condition 2) is implemented with the 'slowInstructions' mechanism. Condition
130 // 3) via exitCPULoopSync() (may only get called by the main emulation thread)
131 // and condition 4) is implemented via exitCPULoopAsync() (can be called from
132 // any thread).
133 //
134 // Now back to the exit-test optimization: in the threaded model each
135 // instruction ends with:
136 //
137 // if (needExit()) return
138 // byte opcode = fetch(PC++);
139 // goto *(table[opcode]);
140 //
141 // And if we look in more detail at fetch():
142 //
143 // if (canDoBackdoor(addr)) {
144 // doBackdoorAccess(addr);
145 // } else {
146 // doFrontdoorAccess(addr);
147 // }
148 //
149 // So there are in fact two checks per instruction. This can be reduced to only
150 // one check with the following trick:
151 //
152 // !!!WRONG!!!
153 // In the past we optimized this to only check canDoBackdoor() (and make sure
154 // canDoBackdoor() returned false when needExit() would return true). This
155 // worked rather well, except for one case: when we exit the CPU loop we also
156 // check for pending Syncronization points. It is possible such a SyncPoint
157 // raises the IRQ line. So it is important to check for exit after every
158 // instruction, otherwise we would enter the IRQ routine a couple of
159 // instructions too late.
160 
161 #include "CPUCore.hh"
162 #include "MSXCPUInterface.hh"
163 #include "Scheduler.hh"
164 #include "MSXMotherBoard.hh"
165 #include "CliComm.hh"
166 #include "TclCallback.hh"
167 #include "Dasm.hh"
168 #include "Z80.hh"
169 #include "R800.hh"
170 #include "Thread.hh"
171 #include "endian.hh"
172 #include "likely.hh"
173 #include "inline.hh"
174 #include "unreachable.hh"
175 #include <iostream>
176 #include <type_traits>
177 #include <cassert>
178 #include <cstring>
179 
180 
181 //
182 // #define USE_COMPUTED_GOTO
183 //
184 // Computed goto's are not enabled by default:
185 // - Computed goto's are a gcc extension, it's not part of the official c++
186 // standard. So this will only work if you use gcc as your compiler (it
187 // won't work with visual c++ for example)
188 // - This is only beneficial on CPUs with branch prediction for indirect jumps
189 // and a reasonable amout of cache. For example it is very benefical for a
190 // intel core2 cpu (10% faster), but not for a ARM920 (a few percent slower)
191 // - Compiling src/cpu/CPUCore.cc with computed goto's enabled is very demanding
192 // on the compiler. On older gcc versions it requires up to 1.5GB of memory.
193 // But even on more recent gcc versions it still requires around 700MB.
194 //
195 // Probably the easiest way to enable this, is to pass the -DUSE_COMPUTED_GOTO
196 // flag to the compiler. This is for example done in the super-opt flavour.
197 // See build/flavour-super-opt.mk
198 
199 
200 using std::string;
201 
202 namespace openmsx {
203 
204 // This actually belongs in Z80.cc and R800.cc (these files don't exist yet).
205 // As a quick hack I put these two lines here because I found it overkill to
206 // create two files each containing only a single line.
207 // Technically these two lines _are_ required according to the c++ standard.
208 // Though usually it works just find without them, but during experiments I did
209 // get a link error when these lines were missing (it only happened during a
210 // debug build with some specific compiler version and only with some
211 // combination of other code changes, but again when strictly following the
212 // language rules, these lines should be here).
213 // ... But visual studio is not fully standard compliant, see also comment
214 // in SectorAccesibleDisk.cc
215 #ifndef _MSC_VER
216 const int Z80TYPE ::CLOCK_FREQ;
217 const int R800TYPE::CLOCK_FREQ;
218 #endif
219 
220 enum Reg8 : int { A, F, B, C, D, E, H, L, IXH, IXL, IYH, IYL, REG_I, REG_R, DUMMY };
221 enum Reg16 : int { AF, BC, DE, HL, IX, IY, SP };
222 
223 // flag positions
224 static const byte S_FLAG = 0x80;
225 static const byte Z_FLAG = 0x40;
226 static const byte Y_FLAG = 0x20;
227 static const byte H_FLAG = 0x10;
228 static const byte X_FLAG = 0x08;
229 static const byte V_FLAG = 0x04;
230 static const byte P_FLAG = V_FLAG;
231 static const byte N_FLAG = 0x02;
232 static const byte C_FLAG = 0x01;
233 
234 // flag-register lookup tables
235 struct Table {
236  byte ZS [256];
237  byte ZSXY [256];
238  byte ZSP [256];
239  byte ZSPXY[256];
240  byte ZSPH [256];
241 };
242 
243 static const byte ZS0 = Z_FLAG;
244 static const byte ZSXY0 = Z_FLAG;
245 static const byte ZSP0 = Z_FLAG | V_FLAG;
246 static const byte ZSPXY0 = Z_FLAG | V_FLAG;
247 static const byte ZS255 = S_FLAG;
248 static const byte ZSXY255 = S_FLAG | X_FLAG | Y_FLAG;
249 
250 static constexpr Table initTables()
251 {
252  Table table = {};
253 
254  for (int i = 0; i < 256; ++i) {
255  byte zFlag = (i == 0) ? Z_FLAG : 0;
256  byte sFlag = i & S_FLAG;
257  byte xFlag = i & X_FLAG;
258  byte yFlag = i & Y_FLAG;
259  byte vFlag = V_FLAG;
260  for (int v = 128; v != 0; v >>= 1) {
261  if (i & v) vFlag ^= V_FLAG;
262  }
263  table.ZS [i] = zFlag | sFlag;
264  table.ZSXY [i] = zFlag | sFlag | xFlag | yFlag;
265  table.ZSP [i] = zFlag | sFlag | vFlag;
266  table.ZSPXY[i] = zFlag | sFlag | xFlag | yFlag | vFlag;
267  table.ZSPH [i] = zFlag | sFlag | vFlag | H_FLAG;
268  }
269  assert(table.ZS [ 0] == ZS0);
270  assert(table.ZSXY [ 0] == ZSXY0);
271  assert(table.ZSP [ 0] == ZSP0);
272  assert(table.ZSPXY[ 0] == ZSPXY0);
273  assert(table.ZS [255] == ZS255);
274  assert(table.ZSXY [255] == ZSXY255);
275 
276  return table;
277 }
278 
279 static constexpr Table table = initTables();
280 
281 // Global variable, because it should be shared between Z80 and R800.
282 // It must not be shared between the CPUs of different MSX machines, but
283 // the (logical) lifetime of this variable cannot overlap between execution
284 // of two MSX machines.
285 static word start_pc;
286 
287 // conditions
288 struct CondC { bool operator()(byte f) const { return (f & C_FLAG) != 0; } };
289 struct CondNC { bool operator()(byte f) const { return !(f & C_FLAG); } };
290 struct CondZ { bool operator()(byte f) const { return (f & Z_FLAG) != 0; } };
291 struct CondNZ { bool operator()(byte f) const { return !(f & Z_FLAG); } };
292 struct CondM { bool operator()(byte f) const { return (f & S_FLAG) != 0; } };
293 struct CondP { bool operator()(byte f) const { return !(f & S_FLAG); } };
294 struct CondPE { bool operator()(byte f) const { return (f & V_FLAG) != 0; } };
295 struct CondPO { bool operator()(byte f) const { return !(f & V_FLAG); } };
296 struct CondTrue { bool operator()(byte /*f*/) const { return true; } };
297 
298 template<class T> CPUCore<T>::CPUCore(
299  MSXMotherBoard& motherboard_, const string& name,
300  const BooleanSetting& traceSetting_,
301  TclCallback& diHaltCallback_, EmuTime::param time)
302  : CPURegs(T::isR800())
303  , T(time, motherboard_.getScheduler())
304  , motherboard(motherboard_)
305  , scheduler(motherboard.getScheduler())
306  , interface(nullptr)
307  , traceSetting(traceSetting_)
308  , diHaltCallback(diHaltCallback_)
309  , IRQStatus(motherboard.getDebugger(), name + ".pendingIRQ",
310  "Non-zero if there are pending IRQs (thus CPU would enter "
311  "interrupt routine in EI mode).",
312  0)
313  , IRQAccept(motherboard.getDebugger(), name + ".acceptIRQ",
314  "This probe is only useful to set a breakpoint on (the value "
315  "return by read is meaningless). The breakpoint gets triggered "
316  "right after the CPU accepted an IRQ.")
317  , freqLocked(
318  motherboard.getCommandController(), name + "_freq_locked",
319  strCat("real (locked) or custom (unlocked) ", name, " frequency"),
320  true)
321  , freqValue(
322  motherboard.getCommandController(), name + "_freq",
323  strCat("custom ", name, " frequency (only valid when unlocked)"),
324  T::CLOCK_FREQ, 1000000, 1000000000)
325  , freq(T::CLOCK_FREQ)
326  , NMIStatus(0)
327  , nmiEdge(false)
328  , exitLoop(false)
329  , tracingEnabled(traceSetting.getBoolean())
330  , isTurboR(motherboard.isTurboR())
331 {
332  static_assert(!std::is_polymorphic<CPUCore<T>>::value,
333  "keep CPUCore non-virtual to keep PC at offset 0");
334  doSetFreq();
335  doReset(time);
336 }
337 
338 template<class T> void CPUCore<T>::warp(EmuTime::param time)
339 {
340  assert(T::getTimeFast() <= time);
341  T::setTime(time);
342 }
343 
344 template<class T> EmuTime::param CPUCore<T>::getCurrentTime() const
345 {
346  return T::getTime();
347 }
348 
349 template<class T> void CPUCore<T>::invalidateMemCache(unsigned start, unsigned size)
350 {
351  unsigned first = start / CacheLine::SIZE;
352  unsigned num = (size + CacheLine::SIZE - 1) / CacheLine::SIZE;
353  memset(&readCacheLine [first], 0, num * sizeof(byte*)); // nullptr
354  memset(&writeCacheLine [first], 0, num * sizeof(byte*)); //
355  memset(&readCacheTried [first], 0, num * sizeof(bool)); // FALSE
356  memset(&writeCacheTried[first], 0, num * sizeof(bool)); //
357 }
358 
359 template<class T> void CPUCore<T>::doReset(EmuTime::param time)
360 {
361  // AF and SP are 0xFFFF
362  // PC, R, IFF1, IFF2, HALT and IM are 0x0
363  // all others are random
364  setAF(0xFFFF);
365  setBC(0xFFFF);
366  setDE(0xFFFF);
367  setHL(0xFFFF);
368  setIX(0xFFFF);
369  setIY(0xFFFF);
370  setPC(0x0000);
371  setSP(0xFFFF);
372  setAF2(0xFFFF);
373  setBC2(0xFFFF);
374  setDE2(0xFFFF);
375  setHL2(0xFFFF);
376  setIFF1(false);
377  setIFF2(false);
378  setHALT(false);
379  setExtHALT(false);
380  setIM(0);
381  setI(0x00);
382  setR(0x00);
383  T::setMemPtr(0xFFFF);
384  clearPrevious();
385  invalidateMemCache(0x0000, 0x10000);
386 
387  // We expect this assert to be valid
388  // assert(T::getTimeFast() <= time); // time shouldn't go backwards
389  // But it's disabled for the following reason:
390  // 'motion' (IRC nickname) managed to create a replay file that
391  // contains a reset command that falls in the middle of a Z80
392  // instruction. Replayed commands go via the Scheduler, and are
393  // (typically) executed right after a complete CPU instruction. So
394  // the CPU is (slightly) ahead in time of the about to be executed
395  // reset command.
396  // Normally this situation should never occur: console commands,
397  // hotkeys, commands over clicomm, ... are all handled via the global
398  // event mechanism. Such global events are scheduled between CPU
399  // instructions, so also in a replay they should fall between CPU
400  // instructions.
401  // However if for some reason the timing of the emulation changed
402  // (improved emulation accuracy or a bug so that emulation isn't
403  // deterministic or the replay file was edited, ...), then the above
404  // reasoning no longer holds and the assert can trigger.
405  // We need to be robust against loading older replays (when emulation
406  // timing has changed). So in that respect disabling the assert is
407  // good. Though in the example above (motion's replay) it's not clear
408  // whether the assert is really triggered by mixing an old replay
409  // with a newer openMSX version. In any case so far we haven't been
410  // able to reproduce this assert by recording and replaying using a
411  // single openMSX version.
412  T::setTime(time);
413 
414  assert(NMIStatus == 0); // other devices must reset their NMI source
415  assert(IRQStatus == 0); // other devices must reset their IRQ source
416 }
417 
418 // I believe the following two methods are thread safe even without any
419 // locking. The worst that can happen is that we occasionally needlessly
420 // exit the CPU loop, but that's harmless
421 // TODO thread issues are always tricky, can someone confirm this really
422 // is thread safe
423 template<class T> void CPUCore<T>::exitCPULoopAsync()
424 {
425  // can get called from non-main threads
426  exitLoop = true;
427 }
428 template<class T> void CPUCore<T>::exitCPULoopSync()
429 {
430  assert(Thread::isMainThread());
431  exitLoop = true;
432  T::disableLimit();
433 }
434 template<class T> inline bool CPUCore<T>::needExitCPULoop()
435 {
436  // always executed in main thread
437  if (unlikely(exitLoop)) {
438  // Note: The test-and-set is _not_ atomic! But that's fine.
439  // An atomic implementation is trivial (see below), but
440  // this version (at least on x86) avoids the more expensive
441  // instructions on the likely path.
442  exitLoop = false;
443  return true;
444  }
445  return false;
446 
447  // Alternative implementation:
448  // atomically set to false and return the old value
449  //return exitLoop.exchange(false);
450 }
451 
452 template<class T> void CPUCore<T>::setSlowInstructions()
453 {
454  slowInstructions = 2;
455  T::disableLimit();
456 }
457 
458 template<class T> void CPUCore<T>::raiseIRQ()
459 {
460  assert(IRQStatus >= 0);
461  if (IRQStatus == 0) {
462  setSlowInstructions();
463  }
464  IRQStatus = IRQStatus + 1;
465 }
466 
467 template<class T> void CPUCore<T>::lowerIRQ()
468 {
469  IRQStatus = IRQStatus - 1;
470  assert(IRQStatus >= 0);
471 }
472 
473 template<class T> void CPUCore<T>::raiseNMI()
474 {
475  assert(NMIStatus >= 0);
476  if (NMIStatus == 0) {
477  nmiEdge = true;
478  setSlowInstructions();
479  }
480  NMIStatus++;
481 }
482 
483 template<class T> void CPUCore<T>::lowerNMI()
484 {
485  NMIStatus--;
486  assert(NMIStatus >= 0);
487 }
488 
489 template<class T> bool CPUCore<T>::isM1Cycle(unsigned address) const
490 {
491  // This method should only be called from within a MSXDevice::readMem()
492  // method. It can be used to check whether the current read action has
493  // the M1 pin active. The 'address' parameter that is give to readMem()
494  // should be passed (unchanged) to this method.
495  //
496  // This simple implementation works because the rest of the CPUCore
497  // code is careful to only update the PC register on M1 cycles. In
498  // practice that means that the PC is (only) updated at the very end of
499  // every instruction, even if is a multi-byte instruction. Or for
500  // prefix-instructions the PC is also updated after the prefix is
501  // fetched (because such instructions activate M1 twice).
502  return address == getPC();
503 }
504 
505 template<class T> void CPUCore<T>::wait(EmuTime::param time)
506 {
507  assert(time >= getCurrentTime());
508  scheduler.schedule(time);
509  T::advanceTime(time);
510 }
511 
512 template<class T> EmuTime CPUCore<T>::waitCycles(EmuTime::param time, unsigned cycles)
513 {
514  T::add(cycles);
515  EmuTime time2 = T::calcTime(time, cycles);
516  // note: time2 is not necessarily equal to T::getTime() because of the
517  // way how WRITE_PORT() is implemented.
518  scheduler.schedule(time2);
519  return time2;
520 }
521 
522 template<class T> void CPUCore<T>::setNextSyncPoint(EmuTime::param time)
523 {
524  T::setLimit(time);
525 }
526 
527 
528 static inline char toHex(byte x)
529 {
530  return (x < 10) ? (x + '0') : (x - 10 + 'A');
531 }
532 static void toHex(byte x, char* buf)
533 {
534  buf[0] = toHex(x / 16);
535  buf[1] = toHex(x & 15);
536 }
537 
538 template<class T> void CPUCore<T>::disasmCommand(
539  Interpreter& interp, span<const TclObject> tokens, TclObject& result) const
540 {
541  word address = (tokens.size() < 3) ? getPC() : tokens[2].getInt(interp);
542  byte outBuf[4];
543  std::string dasmOutput;
544  unsigned len = dasm(*interface, address, outBuf, dasmOutput,
545  T::getTimeFast());
546  result.addListElement(dasmOutput);
547  char tmp[3]; tmp[2] = 0;
548  for (unsigned i = 0; i < len; ++i) {
549  toHex(outBuf[i], tmp);
550  result.addListElement(tmp);
551  }
552 }
553 
554 template<class T> void CPUCore<T>::update(const Setting& setting)
555 {
556  if (&setting == &freqLocked) {
557  doSetFreq();
558  } else if (&setting == &freqValue) {
559  doSetFreq();
560  } else if (&setting == &traceSetting) {
561  tracingEnabled = traceSetting.getBoolean();
562  }
563 }
564 
565 template<class T> void CPUCore<T>::setFreq(unsigned freq_)
566 {
567  freq = freq_;
568  doSetFreq();
569 }
570 
571 template<class T> void CPUCore<T>::doSetFreq()
572 {
573  if (freqLocked.getBoolean()) {
574  // locked, use value set via setFreq()
575  T::setFreq(freq);
576  } else {
577  // unlocked, use value set by user
578  T::setFreq(freqValue.getInt());
579  }
580 }
581 
582 
583 template<class T> inline byte CPUCore<T>::READ_PORT(unsigned port, unsigned cc)
584 {
585  EmuTime time = T::getTimeFast(cc);
586  scheduler.schedule(time);
587  byte result = interface->readIO(port, time);
588  // note: no forced page-break after IO
589  return result;
590 }
591 
592 template<class T> inline void CPUCore<T>::WRITE_PORT(unsigned port, byte value, unsigned cc)
593 {
594  EmuTime time = T::getTimeFast(cc);
595  scheduler.schedule(time);
596  interface->writeIO(port, value, time);
597  // note: no forced page-break after IO
598 }
599 
600 template<class T> template<bool PRE_PB, bool POST_PB>
601 NEVER_INLINE byte CPUCore<T>::RDMEMslow(unsigned address, unsigned cc)
602 {
603  // not cached
604  unsigned high = address >> CacheLine::BITS;
605  if (!readCacheTried[high]) {
606  // try to cache now
607  unsigned addrBase = address & CacheLine::HIGH;
608  if (const byte* line = interface->getReadCacheLine(addrBase)) {
609  // cached ok
610  T::template PRE_MEM<PRE_PB, POST_PB>(address);
611  T::template POST_MEM< POST_PB>(address);
612  readCacheLine[high] = line - addrBase;
613  return readCacheLine[high][address];
614  }
615  }
616  // uncacheable
617  readCacheTried[high] = true;
618  T::template PRE_MEM<PRE_PB, POST_PB>(address);
619  EmuTime time = T::getTimeFast(cc);
620  scheduler.schedule(time);
621  byte result = interface->readMem(address, time);
622  T::template POST_MEM<POST_PB>(address);
623  return result;
624 }
625 template<class T> template<bool PRE_PB, bool POST_PB>
626 ALWAYS_INLINE byte CPUCore<T>::RDMEM_impl2(unsigned address, unsigned cc)
627 {
628  const byte* line = readCacheLine[address >> CacheLine::BITS];
629  if (likely(line != nullptr)) {
630  // cached, fast path
631  T::template PRE_MEM<PRE_PB, POST_PB>(address);
632  T::template POST_MEM< POST_PB>(address);
633  return line[address];
634  } else {
635  return RDMEMslow<PRE_PB, POST_PB>(address, cc); // not inlined
636  }
637 }
638 template<class T> template<bool PRE_PB, bool POST_PB>
639 ALWAYS_INLINE byte CPUCore<T>::RDMEM_impl(unsigned address, unsigned cc)
640 {
641  static const bool PRE = T::template Normalize<PRE_PB >::value;
642  static const bool POST = T::template Normalize<POST_PB>::value;
643  return RDMEM_impl2<PRE, POST>(address, cc);
644 }
645 template<class T> template<unsigned PC_OFFSET> ALWAYS_INLINE byte CPUCore<T>::RDMEM_OPCODE(unsigned cc)
646 {
647  // Real Z80 would update the PC register now. In this implementation
648  // we've chosen to instead update PC only once at the end of the
649  // instruction. (Of course we made sure this difference is not
650  // noticeable by the program).
651  //
652  // See the comments in isM1Cycle() for the motivation for this
653  // deviation. Apart from that functional aspect it also turns out to be
654  // faster to only update PC once per instruction instead of after each
655  // fetch.
656  unsigned address = (getPC() + PC_OFFSET) & 0xFFFF;
657  return RDMEM_impl<false, false>(address, cc);
658 }
659 template<class T> ALWAYS_INLINE byte CPUCore<T>::RDMEM(unsigned address, unsigned cc)
660 {
661  return RDMEM_impl<true, true>(address, cc);
662 }
663 
664 template<class T> template<bool PRE_PB, bool POST_PB>
665 NEVER_INLINE unsigned CPUCore<T>::RD_WORD_slow(unsigned address, unsigned cc)
666 {
667  unsigned res = RDMEM_impl<PRE_PB, false>(address, cc);
668  res += RDMEM_impl<false, POST_PB>((address + 1) & 0xFFFF, cc + T::CC_RDMEM) << 8;
669  return res;
670 }
671 template<class T> template<bool PRE_PB, bool POST_PB>
672 ALWAYS_INLINE unsigned CPUCore<T>::RD_WORD_impl2(unsigned address, unsigned cc)
673 {
674  const byte* line = readCacheLine[address >> CacheLine::BITS];
675  if (likely(((address & CacheLine::LOW) != CacheLine::LOW) && line)) {
676  // fast path: cached and two bytes in same cache line
677  T::template PRE_WORD<PRE_PB, POST_PB>(address);
678  T::template POST_WORD< POST_PB>(address);
679  return Endian::read_UA_L16(&line[address]);
680  } else {
681  // slow path, not inline
682  return RD_WORD_slow<PRE_PB, POST_PB>(address, cc);
683  }
684 }
685 template<class T> template<bool PRE_PB, bool POST_PB>
686 ALWAYS_INLINE unsigned CPUCore<T>::RD_WORD_impl(unsigned address, unsigned cc)
687 {
688  static const bool PRE = T::template Normalize<PRE_PB >::value;
689  static const bool POST = T::template Normalize<POST_PB>::value;
690  return RD_WORD_impl2<PRE, POST>(address, cc);
691 }
692 template<class T> template<unsigned PC_OFFSET> ALWAYS_INLINE unsigned CPUCore<T>::RD_WORD_PC(unsigned cc)
693 {
694  unsigned addr = (getPC() + PC_OFFSET) & 0xFFFF;
695  return RD_WORD_impl<false, false>(addr, cc);
696 }
697 template<class T> ALWAYS_INLINE unsigned CPUCore<T>::RD_WORD(
698  unsigned address, unsigned cc)
699 {
700  return RD_WORD_impl<true, true>(address, cc);
701 }
702 
703 template<class T> template<bool PRE_PB, bool POST_PB>
704 NEVER_INLINE void CPUCore<T>::WRMEMslow(unsigned address, byte value, unsigned cc)
705 {
706  // not cached
707  unsigned high = address >> CacheLine::BITS;
708  if (!writeCacheTried[high]) {
709  // try to cache now
710  unsigned addrBase = address & CacheLine::HIGH;
711  if (byte* line = interface->getWriteCacheLine(addrBase)) {
712  // cached ok
713  T::template PRE_MEM<PRE_PB, POST_PB>(address);
714  T::template POST_MEM< POST_PB>(address);
715  writeCacheLine[high] = line - addrBase;
716  writeCacheLine[high][address] = value;
717  return;
718  }
719  }
720  // uncacheable
721  writeCacheTried[high] = true;
722  T::template PRE_MEM<PRE_PB, POST_PB>(address);
723  EmuTime time = T::getTimeFast(cc);
724  scheduler.schedule(time);
725  interface->writeMem(address, value, time);
726  T::template POST_MEM<POST_PB>(address);
727 }
728 template<class T> template<bool PRE_PB, bool POST_PB>
730  unsigned address, byte value, unsigned cc)
731 {
732  byte* line = writeCacheLine[address >> CacheLine::BITS];
733  if (likely(line != nullptr)) {
734  // cached, fast path
735  T::template PRE_MEM<PRE_PB, POST_PB>(address);
736  T::template POST_MEM< POST_PB>(address);
737  line[address] = value;
738  } else {
739  WRMEMslow<PRE_PB, POST_PB>(address, value, cc); // not inlined
740  }
741 }
742 template<class T> template<bool PRE_PB, bool POST_PB>
744  unsigned address, byte value, unsigned cc)
745 {
746  static const bool PRE = T::template Normalize<PRE_PB >::value;
747  static const bool POST = T::template Normalize<POST_PB>::value;
748  WRMEM_impl2<PRE, POST>(address, value, cc);
749 }
750 template<class T> ALWAYS_INLINE void CPUCore<T>::WRMEM(
751  unsigned address, byte value, unsigned cc)
752 {
753  WRMEM_impl<true, true>(address, value, cc);
754 }
755 
756 template<class T> NEVER_INLINE void CPUCore<T>::WR_WORD_slow(
757  unsigned address, unsigned value, unsigned cc)
758 {
759  WRMEM_impl<true, false>( address, value & 255, cc);
760  WRMEM_impl<false, true>((address + 1) & 0xFFFF, value >> 8, cc + T::CC_WRMEM);
761 }
762 template<class T> ALWAYS_INLINE void CPUCore<T>::WR_WORD(
763  unsigned address, unsigned value, unsigned cc)
764 {
765  byte* line = writeCacheLine[address >> CacheLine::BITS];
766  if (likely(((address & CacheLine::LOW) != CacheLine::LOW) && line)) {
767  // fast path: cached and two bytes in same cache line
768  T::template PRE_WORD<true, true>(address);
769  T::template POST_WORD< true>(address);
770  Endian::write_UA_L16(&line[address], value);
771  } else {
772  // slow path, not inline
773  WR_WORD_slow(address, value, cc);
774  }
775 }
776 
777 // same as WR_WORD, but writes high byte first
778 template<class T> template<bool PRE_PB, bool POST_PB>
780  unsigned address, unsigned value, unsigned cc)
781 {
782  WRMEM_impl<PRE_PB, false>((address + 1) & 0xFFFF, value >> 8, cc);
783  WRMEM_impl<false, POST_PB>( address, value & 255, cc + T::CC_WRMEM);
784 }
785 template<class T> template<bool PRE_PB, bool POST_PB>
787  unsigned address, unsigned value, unsigned cc)
788 {
789  byte* line = writeCacheLine[address >> CacheLine::BITS];
790  if (likely(((address & CacheLine::LOW) != CacheLine::LOW) && line)) {
791  // fast path: cached and two bytes in same cache line
792  T::template PRE_WORD<PRE_PB, POST_PB>(address);
793  T::template POST_WORD< POST_PB>(address);
794  Endian::write_UA_L16(&line[address], value);
795  } else {
796  // slow path, not inline
797  WR_WORD_rev_slow<PRE_PB, POST_PB>(address, value, cc);
798  }
799 }
800 template<class T> template<bool PRE_PB, bool POST_PB>
802  unsigned address, unsigned value, unsigned cc)
803 {
804  static const bool PRE = T::template Normalize<PRE_PB >::value;
805  static const bool POST = T::template Normalize<POST_PB>::value;
806  WR_WORD_rev2<PRE, POST>(address, value, cc);
807 }
808 
809 
810 // NMI interrupt
811 template<class T> inline void CPUCore<T>::nmi()
812 {
813  incR(1);
814  setHALT(false);
815  setIFF1(false);
816  PUSH<T::EE_NMI_1>(getPC());
817  setPC(0x0066);
818  T::add(T::CC_NMI);
819 }
820 
821 // IM0 interrupt
822 template<class T> inline void CPUCore<T>::irq0()
823 {
824  // TODO current implementation only works for 1-byte instructions
825  // ok for MSX
826  assert(interface->readIRQVector() == 0xFF);
827  incR(1);
828  setHALT(false);
829  setIFF1(false);
830  setIFF2(false);
831  PUSH<T::EE_IRQ0_1>(getPC());
832  setPC(0x0038);
833  T::setMemPtr(getPC());
834  T::add(T::CC_IRQ0);
835 }
836 
837 // IM1 interrupt
838 template<class T> inline void CPUCore<T>::irq1()
839 {
840  incR(1);
841  setHALT(false);
842  setIFF1(false);
843  setIFF2(false);
844  PUSH<T::EE_IRQ1_1>(getPC());
845  setPC(0x0038);
846  T::setMemPtr(getPC());
847  T::add(T::CC_IRQ1);
848 }
849 
850 // IM2 interrupt
851 template<class T> inline void CPUCore<T>::irq2()
852 {
853  incR(1);
854  setHALT(false);
855  setIFF1(false);
856  setIFF2(false);
857  PUSH<T::EE_IRQ2_1>(getPC());
858  unsigned x = interface->readIRQVector() | (getI() << 8);
859  setPC(RD_WORD(x, T::CC_IRQ2_2));
860  T::setMemPtr(getPC());
861  T::add(T::CC_IRQ2);
862 }
863 
864 template<class T>
866 {
867  checkNoCurrentFlags();
868 #ifdef USE_COMPUTED_GOTO
869  // Addresses of all main-opcode routines,
870  // Note that 40/49/53/5B/64/6D/7F is replaced by 00 (ld r,r == nop)
871  static void* opcodeTable[256] = {
872  &&op00, &&op01, &&op02, &&op03, &&op04, &&op05, &&op06, &&op07,
873  &&op08, &&op09, &&op0A, &&op0B, &&op0C, &&op0D, &&op0E, &&op0F,
874  &&op10, &&op11, &&op12, &&op13, &&op14, &&op15, &&op16, &&op17,
875  &&op18, &&op19, &&op1A, &&op1B, &&op1C, &&op1D, &&op1E, &&op1F,
876  &&op20, &&op21, &&op22, &&op23, &&op24, &&op25, &&op26, &&op27,
877  &&op28, &&op29, &&op2A, &&op2B, &&op2C, &&op2D, &&op2E, &&op2F,
878  &&op30, &&op31, &&op32, &&op33, &&op34, &&op35, &&op36, &&op37,
879  &&op38, &&op39, &&op3A, &&op3B, &&op3C, &&op3D, &&op3E, &&op3F,
880  &&op00, &&op41, &&op42, &&op43, &&op44, &&op45, &&op46, &&op47,
881  &&op48, &&op00, &&op4A, &&op4B, &&op4C, &&op4D, &&op4E, &&op4F,
882  &&op50, &&op51, &&op00, &&op53, &&op54, &&op55, &&op56, &&op57,
883  &&op58, &&op59, &&op5A, &&op00, &&op5C, &&op5D, &&op5E, &&op5F,
884  &&op60, &&op61, &&op62, &&op63, &&op00, &&op65, &&op66, &&op67,
885  &&op68, &&op69, &&op6A, &&op6B, &&op6C, &&op00, &&op6E, &&op6F,
886  &&op70, &&op71, &&op72, &&op73, &&op74, &&op75, &&op76, &&op77,
887  &&op78, &&op79, &&op7A, &&op7B, &&op7C, &&op7D, &&op7E, &&op00,
888  &&op80, &&op81, &&op82, &&op83, &&op84, &&op85, &&op86, &&op87,
889  &&op88, &&op89, &&op8A, &&op8B, &&op8C, &&op8D, &&op8E, &&op8F,
890  &&op90, &&op91, &&op92, &&op93, &&op94, &&op95, &&op96, &&op97,
891  &&op98, &&op99, &&op9A, &&op9B, &&op9C, &&op9D, &&op9E, &&op9F,
892  &&opA0, &&opA1, &&opA2, &&opA3, &&opA4, &&opA5, &&opA6, &&opA7,
893  &&opA8, &&opA9, &&opAA, &&opAB, &&opAC, &&opAD, &&opAE, &&opAF,
894  &&opB0, &&opB1, &&opB2, &&opB3, &&opB4, &&opB5, &&opB6, &&opB7,
895  &&opB8, &&opB9, &&opBA, &&opBB, &&opBC, &&opBD, &&opBE, &&opBF,
896  &&opC0, &&opC1, &&opC2, &&opC3, &&opC4, &&opC5, &&opC6, &&opC7,
897  &&opC8, &&opC9, &&opCA, &&opCB, &&opCC, &&opCD, &&opCE, &&opCF,
898  &&opD0, &&opD1, &&opD2, &&opD3, &&opD4, &&opD5, &&opD6, &&opD7,
899  &&opD8, &&opD9, &&opDA, &&opDB, &&opDC, &&opDD, &&opDE, &&opDF,
900  &&opE0, &&opE1, &&opE2, &&opE3, &&opE4, &&opE5, &&opE6, &&opE7,
901  &&opE8, &&opE9, &&opEA, &&opEB, &&opEC, &&opED, &&opEE, &&opEF,
902  &&opF0, &&opF1, &&opF2, &&opF3, &&opF4, &&opF5, &&opF6, &&opF7,
903  &&opF8, &&opF9, &&opFA, &&opFB, &&opFC, &&opFD, &&opFE, &&opFF,
904  };
905 
906 // Check T::limitReached(). If it's OK to continue,
907 // fetch and execute next instruction.
908 #define NEXT \
909  setPC(getPC() + ii.length); \
910  T::add(ii.cycles); \
911  T::R800Refresh(*this); \
912  if (likely(!T::limitReached())) { \
913  incR(1); \
914  unsigned address = getPC(); \
915  const byte* line = readCacheLine[address >> CacheLine::BITS]; \
916  if (likely(line != nullptr)) { \
917  T::template PRE_MEM<false, false>(address); \
918  T::template POST_MEM< false>(address); \
919  byte op = line[address]; \
920  goto *(opcodeTable[op]); \
921  } else { \
922  goto fetchSlow; \
923  } \
924  } \
925  return;
926 
927 // After some instructions we must always exit the CPU loop (ei, halt, retn)
928 #define NEXT_STOP \
929  setPC(getPC() + ii.length); \
930  T::add(ii.cycles); \
931  T::R800Refresh(*this); \
932  assert(T::limitReached()); \
933  return;
934 
935 #define NEXT_EI \
936  setPC(getPC() + ii.length); \
937  T::add(ii.cycles); \
938  /* !! NO T::R800Refresh(*this); !! */ \
939  assert(T::limitReached()); \
940  return;
941 
942 // Define a label (instead of case in a switch statement)
943 #define CASE(X) op##X:
944 
945 #else // USE_COMPUTED_GOTO
946 
947 #define NEXT \
948  setPC(getPC() + ii.length); \
949  T::add(ii.cycles); \
950  T::R800Refresh(*this); \
951  if (likely(!T::limitReached())) { \
952  goto start; \
953  } \
954  return;
955 
956 #define NEXT_STOP \
957  setPC(getPC() + ii.length); \
958  T::add(ii.cycles); \
959  T::R800Refresh(*this); \
960  assert(T::limitReached()); \
961  return;
962 
963 #define NEXT_EI \
964  setPC(getPC() + ii.length); \
965  T::add(ii.cycles); \
966  /* !! NO T::R800Refresh(*this); !! */ \
967  assert(T::limitReached()); \
968  return;
969 
970 #define CASE(X) case 0x##X:
971 
972 #endif // USE_COMPUTED_GOTO
973 
974 #ifndef USE_COMPUTED_GOTO
975 start:
976 #endif
977  unsigned ixy; // for dd_cb/fd_cb
978  byte opcodeMain = RDMEM_OPCODE<0>(T::CC_MAIN);
979  incR(1);
980 #ifdef USE_COMPUTED_GOTO
981  goto *(opcodeTable[opcodeMain]);
982 
983 fetchSlow: {
984  unsigned address = getPC();
985  byte opcodeSlow = RDMEMslow<false, false>(address, T::CC_MAIN);
986  goto *(opcodeTable[opcodeSlow]);
987 }
988 #endif
989 
990 #ifndef USE_COMPUTED_GOTO
991 switchopcode:
992  switch (opcodeMain) {
993 CASE(40) // ld b,b
994 CASE(49) // ld c,c
995 CASE(52) // ld d,d
996 CASE(5B) // ld e,e
997 CASE(64) // ld h,h
998 CASE(6D) // ld l,l
999 CASE(7F) // ld a,a
1000 #endif
1001 CASE(00) { II ii = nop(); NEXT; }
1002 CASE(07) { II ii = rlca(); NEXT; }
1003 CASE(0F) { II ii = rrca(); NEXT; }
1004 CASE(17) { II ii = rla(); NEXT; }
1005 CASE(1F) { II ii = rra(); NEXT; }
1006 CASE(08) { II ii = ex_af_af(); NEXT; }
1007 CASE(27) { II ii = daa(); NEXT; }
1008 CASE(2F) { II ii = cpl(); NEXT; }
1009 CASE(37) { II ii = scf(); NEXT; }
1010 CASE(3F) { II ii = ccf(); NEXT; }
1011 CASE(20) { II ii = jr(CondNZ()); NEXT; }
1012 CASE(28) { II ii = jr(CondZ ()); NEXT; }
1013 CASE(30) { II ii = jr(CondNC()); NEXT; }
1014 CASE(38) { II ii = jr(CondC ()); NEXT; }
1015 CASE(18) { II ii = jr(CondTrue()); NEXT; }
1016 CASE(10) { II ii = djnz(); NEXT; }
1017 CASE(32) { II ii = ld_xbyte_a(); NEXT; }
1018 CASE(3A) { II ii = ld_a_xbyte(); NEXT; }
1019 CASE(22) { II ii = ld_xword_SS<HL,0>(); NEXT; }
1020 CASE(2A) { II ii = ld_SS_xword<HL,0>(); NEXT; }
1021 CASE(02) { II ii = ld_SS_a<BC>(); NEXT; }
1022 CASE(12) { II ii = ld_SS_a<DE>(); NEXT; }
1023 CASE(1A) { II ii = ld_a_SS<DE>(); NEXT; }
1024 CASE(0A) { II ii = ld_a_SS<BC>(); NEXT; }
1025 CASE(03) { II ii = inc_SS<BC,0>(); NEXT; }
1026 CASE(13) { II ii = inc_SS<DE,0>(); NEXT; }
1027 CASE(23) { II ii = inc_SS<HL,0>(); NEXT; }
1028 CASE(33) { II ii = inc_SS<SP,0>(); NEXT; }
1029 CASE(0B) { II ii = dec_SS<BC,0>(); NEXT; }
1030 CASE(1B) { II ii = dec_SS<DE,0>(); NEXT; }
1031 CASE(2B) { II ii = dec_SS<HL,0>(); NEXT; }
1032 CASE(3B) { II ii = dec_SS<SP,0>(); NEXT; }
1033 CASE(09) { II ii = add_SS_TT<HL,BC,0>(); NEXT; }
1034 CASE(19) { II ii = add_SS_TT<HL,DE,0>(); NEXT; }
1035 CASE(29) { II ii = add_SS_SS<HL ,0>(); NEXT; }
1036 CASE(39) { II ii = add_SS_TT<HL,SP,0>(); NEXT; }
1037 CASE(01) { II ii = ld_SS_word<BC,0>(); NEXT; }
1038 CASE(11) { II ii = ld_SS_word<DE,0>(); NEXT; }
1039 CASE(21) { II ii = ld_SS_word<HL,0>(); NEXT; }
1040 CASE(31) { II ii = ld_SS_word<SP,0>(); NEXT; }
1041 CASE(04) { II ii = inc_R<B,0>(); NEXT; }
1042 CASE(0C) { II ii = inc_R<C,0>(); NEXT; }
1043 CASE(14) { II ii = inc_R<D,0>(); NEXT; }
1044 CASE(1C) { II ii = inc_R<E,0>(); NEXT; }
1045 CASE(24) { II ii = inc_R<H,0>(); NEXT; }
1046 CASE(2C) { II ii = inc_R<L,0>(); NEXT; }
1047 CASE(3C) { II ii = inc_R<A,0>(); NEXT; }
1048 CASE(34) { II ii = inc_xhl(); NEXT; }
1049 CASE(05) { II ii = dec_R<B,0>(); NEXT; }
1050 CASE(0D) { II ii = dec_R<C,0>(); NEXT; }
1051 CASE(15) { II ii = dec_R<D,0>(); NEXT; }
1052 CASE(1D) { II ii = dec_R<E,0>(); NEXT; }
1053 CASE(25) { II ii = dec_R<H,0>(); NEXT; }
1054 CASE(2D) { II ii = dec_R<L,0>(); NEXT; }
1055 CASE(3D) { II ii = dec_R<A,0>(); NEXT; }
1056 CASE(35) { II ii = dec_xhl(); NEXT; }
1057 CASE(06) { II ii = ld_R_byte<B,0>(); NEXT; }
1058 CASE(0E) { II ii = ld_R_byte<C,0>(); NEXT; }
1059 CASE(16) { II ii = ld_R_byte<D,0>(); NEXT; }
1060 CASE(1E) { II ii = ld_R_byte<E,0>(); NEXT; }
1061 CASE(26) { II ii = ld_R_byte<H,0>(); NEXT; }
1062 CASE(2E) { II ii = ld_R_byte<L,0>(); NEXT; }
1063 CASE(3E) { II ii = ld_R_byte<A,0>(); NEXT; }
1064 CASE(36) { II ii = ld_xhl_byte(); NEXT; }
1065 
1066 CASE(41) { II ii = ld_R_R<B,C,0>(); NEXT; }
1067 CASE(42) { II ii = ld_R_R<B,D,0>(); NEXT; }
1068 CASE(43) { II ii = ld_R_R<B,E,0>(); NEXT; }
1069 CASE(44) { II ii = ld_R_R<B,H,0>(); NEXT; }
1070 CASE(45) { II ii = ld_R_R<B,L,0>(); NEXT; }
1071 CASE(47) { II ii = ld_R_R<B,A,0>(); NEXT; }
1072 CASE(48) { II ii = ld_R_R<C,B,0>(); NEXT; }
1073 CASE(4A) { II ii = ld_R_R<C,D,0>(); NEXT; }
1074 CASE(4B) { II ii = ld_R_R<C,E,0>(); NEXT; }
1075 CASE(4C) { II ii = ld_R_R<C,H,0>(); NEXT; }
1076 CASE(4D) { II ii = ld_R_R<C,L,0>(); NEXT; }
1077 CASE(4F) { II ii = ld_R_R<C,A,0>(); NEXT; }
1078 CASE(50) { II ii = ld_R_R<D,B,0>(); NEXT; }
1079 CASE(51) { II ii = ld_R_R<D,C,0>(); NEXT; }
1080 CASE(53) { II ii = ld_R_R<D,E,0>(); NEXT; }
1081 CASE(54) { II ii = ld_R_R<D,H,0>(); NEXT; }
1082 CASE(55) { II ii = ld_R_R<D,L,0>(); NEXT; }
1083 CASE(57) { II ii = ld_R_R<D,A,0>(); NEXT; }
1084 CASE(58) { II ii = ld_R_R<E,B,0>(); NEXT; }
1085 CASE(59) { II ii = ld_R_R<E,C,0>(); NEXT; }
1086 CASE(5A) { II ii = ld_R_R<E,D,0>(); NEXT; }
1087 CASE(5C) { II ii = ld_R_R<E,H,0>(); NEXT; }
1088 CASE(5D) { II ii = ld_R_R<E,L,0>(); NEXT; }
1089 CASE(5F) { II ii = ld_R_R<E,A,0>(); NEXT; }
1090 CASE(60) { II ii = ld_R_R<H,B,0>(); NEXT; }
1091 CASE(61) { II ii = ld_R_R<H,C,0>(); NEXT; }
1092 CASE(62) { II ii = ld_R_R<H,D,0>(); NEXT; }
1093 CASE(63) { II ii = ld_R_R<H,E,0>(); NEXT; }
1094 CASE(65) { II ii = ld_R_R<H,L,0>(); NEXT; }
1095 CASE(67) { II ii = ld_R_R<H,A,0>(); NEXT; }
1096 CASE(68) { II ii = ld_R_R<L,B,0>(); NEXT; }
1097 CASE(69) { II ii = ld_R_R<L,C,0>(); NEXT; }
1098 CASE(6A) { II ii = ld_R_R<L,D,0>(); NEXT; }
1099 CASE(6B) { II ii = ld_R_R<L,E,0>(); NEXT; }
1100 CASE(6C) { II ii = ld_R_R<L,H,0>(); NEXT; }
1101 CASE(6F) { II ii = ld_R_R<L,A,0>(); NEXT; }
1102 CASE(78) { II ii = ld_R_R<A,B,0>(); NEXT; }
1103 CASE(79) { II ii = ld_R_R<A,C,0>(); NEXT; }
1104 CASE(7A) { II ii = ld_R_R<A,D,0>(); NEXT; }
1105 CASE(7B) { II ii = ld_R_R<A,E,0>(); NEXT; }
1106 CASE(7C) { II ii = ld_R_R<A,H,0>(); NEXT; }
1107 CASE(7D) { II ii = ld_R_R<A,L,0>(); NEXT; }
1108 CASE(70) { II ii = ld_xhl_R<B>(); NEXT; }
1109 CASE(71) { II ii = ld_xhl_R<C>(); NEXT; }
1110 CASE(72) { II ii = ld_xhl_R<D>(); NEXT; }
1111 CASE(73) { II ii = ld_xhl_R<E>(); NEXT; }
1112 CASE(74) { II ii = ld_xhl_R<H>(); NEXT; }
1113 CASE(75) { II ii = ld_xhl_R<L>(); NEXT; }
1114 CASE(77) { II ii = ld_xhl_R<A>(); NEXT; }
1115 CASE(46) { II ii = ld_R_xhl<B>(); NEXT; }
1116 CASE(4E) { II ii = ld_R_xhl<C>(); NEXT; }
1117 CASE(56) { II ii = ld_R_xhl<D>(); NEXT; }
1118 CASE(5E) { II ii = ld_R_xhl<E>(); NEXT; }
1119 CASE(66) { II ii = ld_R_xhl<H>(); NEXT; }
1120 CASE(6E) { II ii = ld_R_xhl<L>(); NEXT; }
1121 CASE(7E) { II ii = ld_R_xhl<A>(); NEXT; }
1122 CASE(76) { II ii = halt(); NEXT_STOP; }
1123 
1124 CASE(80) { II ii = add_a_R<B,0>(); NEXT; }
1125 CASE(81) { II ii = add_a_R<C,0>(); NEXT; }
1126 CASE(82) { II ii = add_a_R<D,0>(); NEXT; }
1127 CASE(83) { II ii = add_a_R<E,0>(); NEXT; }
1128 CASE(84) { II ii = add_a_R<H,0>(); NEXT; }
1129 CASE(85) { II ii = add_a_R<L,0>(); NEXT; }
1130 CASE(86) { II ii = add_a_xhl(); NEXT; }
1131 CASE(87) { II ii = add_a_a(); NEXT; }
1132 CASE(88) { II ii = adc_a_R<B,0>(); NEXT; }
1133 CASE(89) { II ii = adc_a_R<C,0>(); NEXT; }
1134 CASE(8A) { II ii = adc_a_R<D,0>(); NEXT; }
1135 CASE(8B) { II ii = adc_a_R<E,0>(); NEXT; }
1136 CASE(8C) { II ii = adc_a_R<H,0>(); NEXT; }
1137 CASE(8D) { II ii = adc_a_R<L,0>(); NEXT; }
1138 CASE(8E) { II ii = adc_a_xhl(); NEXT; }
1139 CASE(8F) { II ii = adc_a_a(); NEXT; }
1140 CASE(90) { II ii = sub_R<B,0>(); NEXT; }
1141 CASE(91) { II ii = sub_R<C,0>(); NEXT; }
1142 CASE(92) { II ii = sub_R<D,0>(); NEXT; }
1143 CASE(93) { II ii = sub_R<E,0>(); NEXT; }
1144 CASE(94) { II ii = sub_R<H,0>(); NEXT; }
1145 CASE(95) { II ii = sub_R<L,0>(); NEXT; }
1146 CASE(96) { II ii = sub_xhl(); NEXT; }
1147 CASE(97) { II ii = sub_a(); NEXT; }
1148 CASE(98) { II ii = sbc_a_R<B,0>(); NEXT; }
1149 CASE(99) { II ii = sbc_a_R<C,0>(); NEXT; }
1150 CASE(9A) { II ii = sbc_a_R<D,0>(); NEXT; }
1151 CASE(9B) { II ii = sbc_a_R<E,0>(); NEXT; }
1152 CASE(9C) { II ii = sbc_a_R<H,0>(); NEXT; }
1153 CASE(9D) { II ii = sbc_a_R<L,0>(); NEXT; }
1154 CASE(9E) { II ii = sbc_a_xhl(); NEXT; }
1155 CASE(9F) { II ii = sbc_a_a(); NEXT; }
1156 CASE(A0) { II ii = and_R<B,0>(); NEXT; }
1157 CASE(A1) { II ii = and_R<C,0>(); NEXT; }
1158 CASE(A2) { II ii = and_R<D,0>(); NEXT; }
1159 CASE(A3) { II ii = and_R<E,0>(); NEXT; }
1160 CASE(A4) { II ii = and_R<H,0>(); NEXT; }
1161 CASE(A5) { II ii = and_R<L,0>(); NEXT; }
1162 CASE(A6) { II ii = and_xhl(); NEXT; }
1163 CASE(A7) { II ii = and_a(); NEXT; }
1164 CASE(A8) { II ii = xor_R<B,0>(); NEXT; }
1165 CASE(A9) { II ii = xor_R<C,0>(); NEXT; }
1166 CASE(AA) { II ii = xor_R<D,0>(); NEXT; }
1167 CASE(AB) { II ii = xor_R<E,0>(); NEXT; }
1168 CASE(AC) { II ii = xor_R<H,0>(); NEXT; }
1169 CASE(AD) { II ii = xor_R<L,0>(); NEXT; }
1170 CASE(AE) { II ii = xor_xhl(); NEXT; }
1171 CASE(AF) { II ii = xor_a(); NEXT; }
1172 CASE(B0) { II ii = or_R<B,0>(); NEXT; }
1173 CASE(B1) { II ii = or_R<C,0>(); NEXT; }
1174 CASE(B2) { II ii = or_R<D,0>(); NEXT; }
1175 CASE(B3) { II ii = or_R<E,0>(); NEXT; }
1176 CASE(B4) { II ii = or_R<H,0>(); NEXT; }
1177 CASE(B5) { II ii = or_R<L,0>(); NEXT; }
1178 CASE(B6) { II ii = or_xhl(); NEXT; }
1179 CASE(B7) { II ii = or_a(); NEXT; }
1180 CASE(B8) { II ii = cp_R<B,0>(); NEXT; }
1181 CASE(B9) { II ii = cp_R<C,0>(); NEXT; }
1182 CASE(BA) { II ii = cp_R<D,0>(); NEXT; }
1183 CASE(BB) { II ii = cp_R<E,0>(); NEXT; }
1184 CASE(BC) { II ii = cp_R<H,0>(); NEXT; }
1185 CASE(BD) { II ii = cp_R<L,0>(); NEXT; }
1186 CASE(BE) { II ii = cp_xhl(); NEXT; }
1187 CASE(BF) { II ii = cp_a(); NEXT; }
1188 
1189 CASE(D3) { II ii = out_byte_a(); NEXT; }
1190 CASE(DB) { II ii = in_a_byte(); NEXT; }
1191 CASE(D9) { II ii = exx(); NEXT; }
1192 CASE(E3) { II ii = ex_xsp_SS<HL,0>(); NEXT; }
1193 CASE(EB) { II ii = ex_de_hl(); NEXT; }
1194 CASE(E9) { II ii = jp_SS<HL,0>(); NEXT; }
1195 CASE(F9) { II ii = ld_sp_SS<HL,0>(); NEXT; }
1196 CASE(F3) { II ii = di(); NEXT; }
1197 CASE(FB) { II ii = ei(); NEXT_EI; }
1198 CASE(C6) { II ii = add_a_byte(); NEXT; }
1199 CASE(CE) { II ii = adc_a_byte(); NEXT; }
1200 CASE(D6) { II ii = sub_byte(); NEXT; }
1201 CASE(DE) { II ii = sbc_a_byte(); NEXT; }
1202 CASE(E6) { II ii = and_byte(); NEXT; }
1203 CASE(EE) { II ii = xor_byte(); NEXT; }
1204 CASE(F6) { II ii = or_byte(); NEXT; }
1205 CASE(FE) { II ii = cp_byte(); NEXT; }
1206 CASE(C0) { II ii = ret(CondNZ()); NEXT; }
1207 CASE(C8) { II ii = ret(CondZ ()); NEXT; }
1208 CASE(D0) { II ii = ret(CondNC()); NEXT; }
1209 CASE(D8) { II ii = ret(CondC ()); NEXT; }
1210 CASE(E0) { II ii = ret(CondPO()); NEXT; }
1211 CASE(E8) { II ii = ret(CondPE()); NEXT; }
1212 CASE(F0) { II ii = ret(CondP ()); NEXT; }
1213 CASE(F8) { II ii = ret(CondM ()); NEXT; }
1214 CASE(C9) { II ii = ret(); NEXT; }
1215 CASE(C2) { II ii = jp(CondNZ()); NEXT; }
1216 CASE(CA) { II ii = jp(CondZ ()); NEXT; }
1217 CASE(D2) { II ii = jp(CondNC()); NEXT; }
1218 CASE(DA) { II ii = jp(CondC ()); NEXT; }
1219 CASE(E2) { II ii = jp(CondPO()); NEXT; }
1220 CASE(EA) { II ii = jp(CondPE()); NEXT; }
1221 CASE(F2) { II ii = jp(CondP ()); NEXT; }
1222 CASE(FA) { II ii = jp(CondM ()); NEXT; }
1223 CASE(C3) { II ii = jp(CondTrue()); NEXT; }
1224 CASE(C4) { II ii = call(CondNZ()); NEXT; }
1225 CASE(CC) { II ii = call(CondZ ()); NEXT; }
1226 CASE(D4) { II ii = call(CondNC()); NEXT; }
1227 CASE(DC) { II ii = call(CondC ()); NEXT; }
1228 CASE(E4) { II ii = call(CondPO()); NEXT; }
1229 CASE(EC) { II ii = call(CondPE()); NEXT; }
1230 CASE(F4) { II ii = call(CondP ()); NEXT; }
1231 CASE(FC) { II ii = call(CondM ()); NEXT; }
1232 CASE(CD) { II ii = call(CondTrue()); NEXT; }
1233 CASE(C1) { II ii = pop_SS <BC,0>(); NEXT; }
1234 CASE(D1) { II ii = pop_SS <DE,0>(); NEXT; }
1235 CASE(E1) { II ii = pop_SS <HL,0>(); NEXT; }
1236 CASE(F1) { II ii = pop_SS <AF,0>(); NEXT; }
1237 CASE(C5) { II ii = push_SS<BC,0>(); NEXT; }
1238 CASE(D5) { II ii = push_SS<DE,0>(); NEXT; }
1239 CASE(E5) { II ii = push_SS<HL,0>(); NEXT; }
1240 CASE(F5) { II ii = push_SS<AF,0>(); NEXT; }
1241 CASE(C7) { II ii = rst<0x00>(); NEXT; }
1242 CASE(CF) { II ii = rst<0x08>(); NEXT; }
1243 CASE(D7) { II ii = rst<0x10>(); NEXT; }
1244 CASE(DF) { II ii = rst<0x18>(); NEXT; }
1245 CASE(E7) { II ii = rst<0x20>(); NEXT; }
1246 CASE(EF) { II ii = rst<0x28>(); NEXT; }
1247 CASE(F7) { II ii = rst<0x30>(); NEXT; }
1248 CASE(FF) { II ii = rst<0x38>(); NEXT; }
1249 CASE(CB) {
1250  setPC(getPC() + 1); // M1 cycle at this point
1251  byte cb_opcode = RDMEM_OPCODE<0>(T::CC_PREFIX);
1252  incR(1);
1253  switch (cb_opcode) {
1254  case 0x00: { II ii = rlc_R<B>(); NEXT; }
1255  case 0x01: { II ii = rlc_R<C>(); NEXT; }
1256  case 0x02: { II ii = rlc_R<D>(); NEXT; }
1257  case 0x03: { II ii = rlc_R<E>(); NEXT; }
1258  case 0x04: { II ii = rlc_R<H>(); NEXT; }
1259  case 0x05: { II ii = rlc_R<L>(); NEXT; }
1260  case 0x07: { II ii = rlc_R<A>(); NEXT; }
1261  case 0x06: { II ii = rlc_xhl(); NEXT; }
1262  case 0x08: { II ii = rrc_R<B>(); NEXT; }
1263  case 0x09: { II ii = rrc_R<C>(); NEXT; }
1264  case 0x0a: { II ii = rrc_R<D>(); NEXT; }
1265  case 0x0b: { II ii = rrc_R<E>(); NEXT; }
1266  case 0x0c: { II ii = rrc_R<H>(); NEXT; }
1267  case 0x0d: { II ii = rrc_R<L>(); NEXT; }
1268  case 0x0f: { II ii = rrc_R<A>(); NEXT; }
1269  case 0x0e: { II ii = rrc_xhl(); NEXT; }
1270  case 0x10: { II ii = rl_R<B>(); NEXT; }
1271  case 0x11: { II ii = rl_R<C>(); NEXT; }
1272  case 0x12: { II ii = rl_R<D>(); NEXT; }
1273  case 0x13: { II ii = rl_R<E>(); NEXT; }
1274  case 0x14: { II ii = rl_R<H>(); NEXT; }
1275  case 0x15: { II ii = rl_R<L>(); NEXT; }
1276  case 0x17: { II ii = rl_R<A>(); NEXT; }
1277  case 0x16: { II ii = rl_xhl(); NEXT; }
1278  case 0x18: { II ii = rr_R<B>(); NEXT; }
1279  case 0x19: { II ii = rr_R<C>(); NEXT; }
1280  case 0x1a: { II ii = rr_R<D>(); NEXT; }
1281  case 0x1b: { II ii = rr_R<E>(); NEXT; }
1282  case 0x1c: { II ii = rr_R<H>(); NEXT; }
1283  case 0x1d: { II ii = rr_R<L>(); NEXT; }
1284  case 0x1f: { II ii = rr_R<A>(); NEXT; }
1285  case 0x1e: { II ii = rr_xhl(); NEXT; }
1286  case 0x20: { II ii = sla_R<B>(); NEXT; }
1287  case 0x21: { II ii = sla_R<C>(); NEXT; }
1288  case 0x22: { II ii = sla_R<D>(); NEXT; }
1289  case 0x23: { II ii = sla_R<E>(); NEXT; }
1290  case 0x24: { II ii = sla_R<H>(); NEXT; }
1291  case 0x25: { II ii = sla_R<L>(); NEXT; }
1292  case 0x27: { II ii = sla_R<A>(); NEXT; }
1293  case 0x26: { II ii = sla_xhl(); NEXT; }
1294  case 0x28: { II ii = sra_R<B>(); NEXT; }
1295  case 0x29: { II ii = sra_R<C>(); NEXT; }
1296  case 0x2a: { II ii = sra_R<D>(); NEXT; }
1297  case 0x2b: { II ii = sra_R<E>(); NEXT; }
1298  case 0x2c: { II ii = sra_R<H>(); NEXT; }
1299  case 0x2d: { II ii = sra_R<L>(); NEXT; }
1300  case 0x2f: { II ii = sra_R<A>(); NEXT; }
1301  case 0x2e: { II ii = sra_xhl(); NEXT; }
1302  case 0x30: { II ii = T::isR800() ? sla_R<B>() : sll_R<B>(); NEXT; }
1303  case 0x31: { II ii = T::isR800() ? sla_R<C>() : sll_R<C>(); NEXT; }
1304  case 0x32: { II ii = T::isR800() ? sla_R<D>() : sll_R<D>(); NEXT; }
1305  case 0x33: { II ii = T::isR800() ? sla_R<E>() : sll_R<E>(); NEXT; }
1306  case 0x34: { II ii = T::isR800() ? sla_R<H>() : sll_R<H>(); NEXT; }
1307  case 0x35: { II ii = T::isR800() ? sla_R<L>() : sll_R<L>(); NEXT; }
1308  case 0x37: { II ii = T::isR800() ? sla_R<A>() : sll_R<A>(); NEXT; }
1309  case 0x36: { II ii = T::isR800() ? sla_xhl() : sll_xhl(); NEXT; }
1310  case 0x38: { II ii = srl_R<B>(); NEXT; }
1311  case 0x39: { II ii = srl_R<C>(); NEXT; }
1312  case 0x3a: { II ii = srl_R<D>(); NEXT; }
1313  case 0x3b: { II ii = srl_R<E>(); NEXT; }
1314  case 0x3c: { II ii = srl_R<H>(); NEXT; }
1315  case 0x3d: { II ii = srl_R<L>(); NEXT; }
1316  case 0x3f: { II ii = srl_R<A>(); NEXT; }
1317  case 0x3e: { II ii = srl_xhl(); NEXT; }
1318 
1319  case 0x40: { II ii = bit_N_R<0,B>(); NEXT; }
1320  case 0x41: { II ii = bit_N_R<0,C>(); NEXT; }
1321  case 0x42: { II ii = bit_N_R<0,D>(); NEXT; }
1322  case 0x43: { II ii = bit_N_R<0,E>(); NEXT; }
1323  case 0x44: { II ii = bit_N_R<0,H>(); NEXT; }
1324  case 0x45: { II ii = bit_N_R<0,L>(); NEXT; }
1325  case 0x47: { II ii = bit_N_R<0,A>(); NEXT; }
1326  case 0x48: { II ii = bit_N_R<1,B>(); NEXT; }
1327  case 0x49: { II ii = bit_N_R<1,C>(); NEXT; }
1328  case 0x4a: { II ii = bit_N_R<1,D>(); NEXT; }
1329  case 0x4b: { II ii = bit_N_R<1,E>(); NEXT; }
1330  case 0x4c: { II ii = bit_N_R<1,H>(); NEXT; }
1331  case 0x4d: { II ii = bit_N_R<1,L>(); NEXT; }
1332  case 0x4f: { II ii = bit_N_R<1,A>(); NEXT; }
1333  case 0x50: { II ii = bit_N_R<2,B>(); NEXT; }
1334  case 0x51: { II ii = bit_N_R<2,C>(); NEXT; }
1335  case 0x52: { II ii = bit_N_R<2,D>(); NEXT; }
1336  case 0x53: { II ii = bit_N_R<2,E>(); NEXT; }
1337  case 0x54: { II ii = bit_N_R<2,H>(); NEXT; }
1338  case 0x55: { II ii = bit_N_R<2,L>(); NEXT; }
1339  case 0x57: { II ii = bit_N_R<2,A>(); NEXT; }
1340  case 0x58: { II ii = bit_N_R<3,B>(); NEXT; }
1341  case 0x59: { II ii = bit_N_R<3,C>(); NEXT; }
1342  case 0x5a: { II ii = bit_N_R<3,D>(); NEXT; }
1343  case 0x5b: { II ii = bit_N_R<3,E>(); NEXT; }
1344  case 0x5c: { II ii = bit_N_R<3,H>(); NEXT; }
1345  case 0x5d: { II ii = bit_N_R<3,L>(); NEXT; }
1346  case 0x5f: { II ii = bit_N_R<3,A>(); NEXT; }
1347  case 0x60: { II ii = bit_N_R<4,B>(); NEXT; }
1348  case 0x61: { II ii = bit_N_R<4,C>(); NEXT; }
1349  case 0x62: { II ii = bit_N_R<4,D>(); NEXT; }
1350  case 0x63: { II ii = bit_N_R<4,E>(); NEXT; }
1351  case 0x64: { II ii = bit_N_R<4,H>(); NEXT; }
1352  case 0x65: { II ii = bit_N_R<4,L>(); NEXT; }
1353  case 0x67: { II ii = bit_N_R<4,A>(); NEXT; }
1354  case 0x68: { II ii = bit_N_R<5,B>(); NEXT; }
1355  case 0x69: { II ii = bit_N_R<5,C>(); NEXT; }
1356  case 0x6a: { II ii = bit_N_R<5,D>(); NEXT; }
1357  case 0x6b: { II ii = bit_N_R<5,E>(); NEXT; }
1358  case 0x6c: { II ii = bit_N_R<5,H>(); NEXT; }
1359  case 0x6d: { II ii = bit_N_R<5,L>(); NEXT; }
1360  case 0x6f: { II ii = bit_N_R<5,A>(); NEXT; }
1361  case 0x70: { II ii = bit_N_R<6,B>(); NEXT; }
1362  case 0x71: { II ii = bit_N_R<6,C>(); NEXT; }
1363  case 0x72: { II ii = bit_N_R<6,D>(); NEXT; }
1364  case 0x73: { II ii = bit_N_R<6,E>(); NEXT; }
1365  case 0x74: { II ii = bit_N_R<6,H>(); NEXT; }
1366  case 0x75: { II ii = bit_N_R<6,L>(); NEXT; }
1367  case 0x77: { II ii = bit_N_R<6,A>(); NEXT; }
1368  case 0x78: { II ii = bit_N_R<7,B>(); NEXT; }
1369  case 0x79: { II ii = bit_N_R<7,C>(); NEXT; }
1370  case 0x7a: { II ii = bit_N_R<7,D>(); NEXT; }
1371  case 0x7b: { II ii = bit_N_R<7,E>(); NEXT; }
1372  case 0x7c: { II ii = bit_N_R<7,H>(); NEXT; }
1373  case 0x7d: { II ii = bit_N_R<7,L>(); NEXT; }
1374  case 0x7f: { II ii = bit_N_R<7,A>(); NEXT; }
1375  case 0x46: { II ii = bit_N_xhl<0>(); NEXT; }
1376  case 0x4e: { II ii = bit_N_xhl<1>(); NEXT; }
1377  case 0x56: { II ii = bit_N_xhl<2>(); NEXT; }
1378  case 0x5e: { II ii = bit_N_xhl<3>(); NEXT; }
1379  case 0x66: { II ii = bit_N_xhl<4>(); NEXT; }
1380  case 0x6e: { II ii = bit_N_xhl<5>(); NEXT; }
1381  case 0x76: { II ii = bit_N_xhl<6>(); NEXT; }
1382  case 0x7e: { II ii = bit_N_xhl<7>(); NEXT; }
1383 
1384  case 0x80: { II ii = res_N_R<0,B>(); NEXT; }
1385  case 0x81: { II ii = res_N_R<0,C>(); NEXT; }
1386  case 0x82: { II ii = res_N_R<0,D>(); NEXT; }
1387  case 0x83: { II ii = res_N_R<0,E>(); NEXT; }
1388  case 0x84: { II ii = res_N_R<0,H>(); NEXT; }
1389  case 0x85: { II ii = res_N_R<0,L>(); NEXT; }
1390  case 0x87: { II ii = res_N_R<0,A>(); NEXT; }
1391  case 0x88: { II ii = res_N_R<1,B>(); NEXT; }
1392  case 0x89: { II ii = res_N_R<1,C>(); NEXT; }
1393  case 0x8a: { II ii = res_N_R<1,D>(); NEXT; }
1394  case 0x8b: { II ii = res_N_R<1,E>(); NEXT; }
1395  case 0x8c: { II ii = res_N_R<1,H>(); NEXT; }
1396  case 0x8d: { II ii = res_N_R<1,L>(); NEXT; }
1397  case 0x8f: { II ii = res_N_R<1,A>(); NEXT; }
1398  case 0x90: { II ii = res_N_R<2,B>(); NEXT; }
1399  case 0x91: { II ii = res_N_R<2,C>(); NEXT; }
1400  case 0x92: { II ii = res_N_R<2,D>(); NEXT; }
1401  case 0x93: { II ii = res_N_R<2,E>(); NEXT; }
1402  case 0x94: { II ii = res_N_R<2,H>(); NEXT; }
1403  case 0x95: { II ii = res_N_R<2,L>(); NEXT; }
1404  case 0x97: { II ii = res_N_R<2,A>(); NEXT; }
1405  case 0x98: { II ii = res_N_R<3,B>(); NEXT; }
1406  case 0x99: { II ii = res_N_R<3,C>(); NEXT; }
1407  case 0x9a: { II ii = res_N_R<3,D>(); NEXT; }
1408  case 0x9b: { II ii = res_N_R<3,E>(); NEXT; }
1409  case 0x9c: { II ii = res_N_R<3,H>(); NEXT; }
1410  case 0x9d: { II ii = res_N_R<3,L>(); NEXT; }
1411  case 0x9f: { II ii = res_N_R<3,A>(); NEXT; }
1412  case 0xa0: { II ii = res_N_R<4,B>(); NEXT; }
1413  case 0xa1: { II ii = res_N_R<4,C>(); NEXT; }
1414  case 0xa2: { II ii = res_N_R<4,D>(); NEXT; }
1415  case 0xa3: { II ii = res_N_R<4,E>(); NEXT; }
1416  case 0xa4: { II ii = res_N_R<4,H>(); NEXT; }
1417  case 0xa5: { II ii = res_N_R<4,L>(); NEXT; }
1418  case 0xa7: { II ii = res_N_R<4,A>(); NEXT; }
1419  case 0xa8: { II ii = res_N_R<5,B>(); NEXT; }
1420  case 0xa9: { II ii = res_N_R<5,C>(); NEXT; }
1421  case 0xaa: { II ii = res_N_R<5,D>(); NEXT; }
1422  case 0xab: { II ii = res_N_R<5,E>(); NEXT; }
1423  case 0xac: { II ii = res_N_R<5,H>(); NEXT; }
1424  case 0xad: { II ii = res_N_R<5,L>(); NEXT; }
1425  case 0xaf: { II ii = res_N_R<5,A>(); NEXT; }
1426  case 0xb0: { II ii = res_N_R<6,B>(); NEXT; }
1427  case 0xb1: { II ii = res_N_R<6,C>(); NEXT; }
1428  case 0xb2: { II ii = res_N_R<6,D>(); NEXT; }
1429  case 0xb3: { II ii = res_N_R<6,E>(); NEXT; }
1430  case 0xb4: { II ii = res_N_R<6,H>(); NEXT; }
1431  case 0xb5: { II ii = res_N_R<6,L>(); NEXT; }
1432  case 0xb7: { II ii = res_N_R<6,A>(); NEXT; }
1433  case 0xb8: { II ii = res_N_R<7,B>(); NEXT; }
1434  case 0xb9: { II ii = res_N_R<7,C>(); NEXT; }
1435  case 0xba: { II ii = res_N_R<7,D>(); NEXT; }
1436  case 0xbb: { II ii = res_N_R<7,E>(); NEXT; }
1437  case 0xbc: { II ii = res_N_R<7,H>(); NEXT; }
1438  case 0xbd: { II ii = res_N_R<7,L>(); NEXT; }
1439  case 0xbf: { II ii = res_N_R<7,A>(); NEXT; }
1440  case 0x86: { II ii = res_N_xhl<0>(); NEXT; }
1441  case 0x8e: { II ii = res_N_xhl<1>(); NEXT; }
1442  case 0x96: { II ii = res_N_xhl<2>(); NEXT; }
1443  case 0x9e: { II ii = res_N_xhl<3>(); NEXT; }
1444  case 0xa6: { II ii = res_N_xhl<4>(); NEXT; }
1445  case 0xae: { II ii = res_N_xhl<5>(); NEXT; }
1446  case 0xb6: { II ii = res_N_xhl<6>(); NEXT; }
1447  case 0xbe: { II ii = res_N_xhl<7>(); NEXT; }
1448 
1449  case 0xc0: { II ii = set_N_R<0,B>(); NEXT; }
1450  case 0xc1: { II ii = set_N_R<0,C>(); NEXT; }
1451  case 0xc2: { II ii = set_N_R<0,D>(); NEXT; }
1452  case 0xc3: { II ii = set_N_R<0,E>(); NEXT; }
1453  case 0xc4: { II ii = set_N_R<0,H>(); NEXT; }
1454  case 0xc5: { II ii = set_N_R<0,L>(); NEXT; }
1455  case 0xc7: { II ii = set_N_R<0,A>(); NEXT; }
1456  case 0xc8: { II ii = set_N_R<1,B>(); NEXT; }
1457  case 0xc9: { II ii = set_N_R<1,C>(); NEXT; }
1458  case 0xca: { II ii = set_N_R<1,D>(); NEXT; }
1459  case 0xcb: { II ii = set_N_R<1,E>(); NEXT; }
1460  case 0xcc: { II ii = set_N_R<1,H>(); NEXT; }
1461  case 0xcd: { II ii = set_N_R<1,L>(); NEXT; }
1462  case 0xcf: { II ii = set_N_R<1,A>(); NEXT; }
1463  case 0xd0: { II ii = set_N_R<2,B>(); NEXT; }
1464  case 0xd1: { II ii = set_N_R<2,C>(); NEXT; }
1465  case 0xd2: { II ii = set_N_R<2,D>(); NEXT; }
1466  case 0xd3: { II ii = set_N_R<2,E>(); NEXT; }
1467  case 0xd4: { II ii = set_N_R<2,H>(); NEXT; }
1468  case 0xd5: { II ii = set_N_R<2,L>(); NEXT; }
1469  case 0xd7: { II ii = set_N_R<2,A>(); NEXT; }
1470  case 0xd8: { II ii = set_N_R<3,B>(); NEXT; }
1471  case 0xd9: { II ii = set_N_R<3,C>(); NEXT; }
1472  case 0xda: { II ii = set_N_R<3,D>(); NEXT; }
1473  case 0xdb: { II ii = set_N_R<3,E>(); NEXT; }
1474  case 0xdc: { II ii = set_N_R<3,H>(); NEXT; }
1475  case 0xdd: { II ii = set_N_R<3,L>(); NEXT; }
1476  case 0xdf: { II ii = set_N_R<3,A>(); NEXT; }
1477  case 0xe0: { II ii = set_N_R<4,B>(); NEXT; }
1478  case 0xe1: { II ii = set_N_R<4,C>(); NEXT; }
1479  case 0xe2: { II ii = set_N_R<4,D>(); NEXT; }
1480  case 0xe3: { II ii = set_N_R<4,E>(); NEXT; }
1481  case 0xe4: { II ii = set_N_R<4,H>(); NEXT; }
1482  case 0xe5: { II ii = set_N_R<4,L>(); NEXT; }
1483  case 0xe7: { II ii = set_N_R<4,A>(); NEXT; }
1484  case 0xe8: { II ii = set_N_R<5,B>(); NEXT; }
1485  case 0xe9: { II ii = set_N_R<5,C>(); NEXT; }
1486  case 0xea: { II ii = set_N_R<5,D>(); NEXT; }
1487  case 0xeb: { II ii = set_N_R<5,E>(); NEXT; }
1488  case 0xec: { II ii = set_N_R<5,H>(); NEXT; }
1489  case 0xed: { II ii = set_N_R<5,L>(); NEXT; }
1490  case 0xef: { II ii = set_N_R<5,A>(); NEXT; }
1491  case 0xf0: { II ii = set_N_R<6,B>(); NEXT; }
1492  case 0xf1: { II ii = set_N_R<6,C>(); NEXT; }
1493  case 0xf2: { II ii = set_N_R<6,D>(); NEXT; }
1494  case 0xf3: { II ii = set_N_R<6,E>(); NEXT; }
1495  case 0xf4: { II ii = set_N_R<6,H>(); NEXT; }
1496  case 0xf5: { II ii = set_N_R<6,L>(); NEXT; }
1497  case 0xf7: { II ii = set_N_R<6,A>(); NEXT; }
1498  case 0xf8: { II ii = set_N_R<7,B>(); NEXT; }
1499  case 0xf9: { II ii = set_N_R<7,C>(); NEXT; }
1500  case 0xfa: { II ii = set_N_R<7,D>(); NEXT; }
1501  case 0xfb: { II ii = set_N_R<7,E>(); NEXT; }
1502  case 0xfc: { II ii = set_N_R<7,H>(); NEXT; }
1503  case 0xfd: { II ii = set_N_R<7,L>(); NEXT; }
1504  case 0xff: { II ii = set_N_R<7,A>(); NEXT; }
1505  case 0xc6: { II ii = set_N_xhl<0>(); NEXT; }
1506  case 0xce: { II ii = set_N_xhl<1>(); NEXT; }
1507  case 0xd6: { II ii = set_N_xhl<2>(); NEXT; }
1508  case 0xde: { II ii = set_N_xhl<3>(); NEXT; }
1509  case 0xe6: { II ii = set_N_xhl<4>(); NEXT; }
1510  case 0xee: { II ii = set_N_xhl<5>(); NEXT; }
1511  case 0xf6: { II ii = set_N_xhl<6>(); NEXT; }
1512  case 0xfe: { II ii = set_N_xhl<7>(); NEXT; }
1513  default: UNREACHABLE; return;
1514  }
1515 }
1516 CASE(ED) {
1517  setPC(getPC() + 1); // M1 cycle at this point
1518  byte ed_opcode = RDMEM_OPCODE<0>(T::CC_PREFIX);
1519  incR(1);
1520  switch (ed_opcode) {
1521  case 0x00: case 0x01: case 0x02: case 0x03:
1522  case 0x04: case 0x05: case 0x06: case 0x07:
1523  case 0x08: case 0x09: case 0x0a: case 0x0b:
1524  case 0x0c: case 0x0d: case 0x0e: case 0x0f:
1525  case 0x10: case 0x11: case 0x12: case 0x13:
1526  case 0x14: case 0x15: case 0x16: case 0x17:
1527  case 0x18: case 0x19: case 0x1a: case 0x1b:
1528  case 0x1c: case 0x1d: case 0x1e: case 0x1f:
1529  case 0x20: case 0x21: case 0x22: case 0x23:
1530  case 0x24: case 0x25: case 0x26: case 0x27:
1531  case 0x28: case 0x29: case 0x2a: case 0x2b:
1532  case 0x2c: case 0x2d: case 0x2e: case 0x2f:
1533  case 0x30: case 0x31: case 0x32: case 0x33:
1534  case 0x34: case 0x35: case 0x36: case 0x37:
1535  case 0x38: case 0x39: case 0x3a: case 0x3b:
1536  case 0x3c: case 0x3d: case 0x3e: case 0x3f:
1537 
1538  case 0x77: case 0x7f:
1539 
1540  case 0x80: case 0x81: case 0x82: case 0x83:
1541  case 0x84: case 0x85: case 0x86: case 0x87:
1542  case 0x88: case 0x89: case 0x8a: case 0x8b:
1543  case 0x8c: case 0x8d: case 0x8e: case 0x8f:
1544  case 0x90: case 0x91: case 0x92: case 0x93:
1545  case 0x94: case 0x95: case 0x96: case 0x97:
1546  case 0x98: case 0x99: case 0x9a: case 0x9b:
1547  case 0x9c: case 0x9d: case 0x9e: case 0x9f:
1548  case 0xa4: case 0xa5: case 0xa6: case 0xa7:
1549  case 0xac: case 0xad: case 0xae: case 0xaf:
1550  case 0xb4: case 0xb5: case 0xb6: case 0xb7:
1551  case 0xbc: case 0xbd: case 0xbe: case 0xbf:
1552 
1553  case 0xc0: case 0xc2:
1554  case 0xc4: case 0xc5: case 0xc6: case 0xc7:
1555  case 0xc8: case 0xca: case 0xcb:
1556  case 0xcc: case 0xcd: case 0xce: case 0xcf:
1557  case 0xd0: case 0xd2: case 0xd3:
1558  case 0xd4: case 0xd5: case 0xd6: case 0xd7:
1559  case 0xd8: case 0xda: case 0xdb:
1560  case 0xdc: case 0xdd: case 0xde: case 0xdf:
1561  case 0xe0: case 0xe1: case 0xe2: case 0xe3:
1562  case 0xe4: case 0xe5: case 0xe6: case 0xe7:
1563  case 0xe8: case 0xe9: case 0xea: case 0xeb:
1564  case 0xec: case 0xed: case 0xee: case 0xef:
1565  case 0xf0: case 0xf1: case 0xf2:
1566  case 0xf4: case 0xf5: case 0xf6: case 0xf7:
1567  case 0xf8: case 0xf9: case 0xfa: case 0xfb:
1568  case 0xfc: case 0xfd: case 0xfe: case 0xff:
1569  { II ii = nop(); NEXT; }
1570 
1571  case 0x40: { II ii = in_R_c<B>(); NEXT; }
1572  case 0x48: { II ii = in_R_c<C>(); NEXT; }
1573  case 0x50: { II ii = in_R_c<D>(); NEXT; }
1574  case 0x58: { II ii = in_R_c<E>(); NEXT; }
1575  case 0x60: { II ii = in_R_c<H>(); NEXT; }
1576  case 0x68: { II ii = in_R_c<L>(); NEXT; }
1577  case 0x70: { II ii = in_R_c<DUMMY>(); NEXT; }
1578  case 0x78: { II ii = in_R_c<A>(); NEXT; }
1579 
1580  case 0x41: { II ii = out_c_R<B>(); NEXT; }
1581  case 0x49: { II ii = out_c_R<C>(); NEXT; }
1582  case 0x51: { II ii = out_c_R<D>(); NEXT; }
1583  case 0x59: { II ii = out_c_R<E>(); NEXT; }
1584  case 0x61: { II ii = out_c_R<H>(); NEXT; }
1585  case 0x69: { II ii = out_c_R<L>(); NEXT; }
1586  case 0x71: { II ii = out_c_0(); NEXT; }
1587  case 0x79: { II ii = out_c_R<A>(); NEXT; }
1588 
1589  case 0x42: { II ii = sbc_hl_SS<BC>(); NEXT; }
1590  case 0x52: { II ii = sbc_hl_SS<DE>(); NEXT; }
1591  case 0x62: { II ii = sbc_hl_hl (); NEXT; }
1592  case 0x72: { II ii = sbc_hl_SS<SP>(); NEXT; }
1593 
1594  case 0x4a: { II ii = adc_hl_SS<BC>(); NEXT; }
1595  case 0x5a: { II ii = adc_hl_SS<DE>(); NEXT; }
1596  case 0x6a: { II ii = adc_hl_hl (); NEXT; }
1597  case 0x7a: { II ii = adc_hl_SS<SP>(); NEXT; }
1598 
1599  case 0x43: { II ii = ld_xword_SS_ED<BC>(); NEXT; }
1600  case 0x53: { II ii = ld_xword_SS_ED<DE>(); NEXT; }
1601  case 0x63: { II ii = ld_xword_SS_ED<HL>(); NEXT; }
1602  case 0x73: { II ii = ld_xword_SS_ED<SP>(); NEXT; }
1603 
1604  case 0x4b: { II ii = ld_SS_xword_ED<BC>(); NEXT; }
1605  case 0x5b: { II ii = ld_SS_xword_ED<DE>(); NEXT; }
1606  case 0x6b: { II ii = ld_SS_xword_ED<HL>(); NEXT; }
1607  case 0x7b: { II ii = ld_SS_xword_ED<SP>(); NEXT; }
1608 
1609  case 0x47: { II ii = ld_i_a(); NEXT; }
1610  case 0x4f: { II ii = ld_r_a(); NEXT; }
1611  case 0x57: { II ii = ld_a_IR<REG_I>(); if (T::isR800()) { NEXT; } else { NEXT_STOP; }}
1612  case 0x5f: { II ii = ld_a_IR<REG_R>(); if (T::isR800()) { NEXT; } else { NEXT_STOP; }}
1613 
1614  case 0x67: { II ii = rrd(); NEXT; }
1615  case 0x6f: { II ii = rld(); NEXT; }
1616 
1617  case 0x45: case 0x4d: case 0x55: case 0x5d:
1618  case 0x65: case 0x6d: case 0x75: case 0x7d:
1619  { II ii = retn(); NEXT_STOP; }
1620  case 0x46: case 0x4e: case 0x66: case 0x6e:
1621  { II ii = im_N<0>(); NEXT; }
1622  case 0x56: case 0x76:
1623  { II ii = im_N<1>(); NEXT; }
1624  case 0x5e: case 0x7e:
1625  { II ii = im_N<2>(); NEXT; }
1626  case 0x44: case 0x4c: case 0x54: case 0x5c:
1627  case 0x64: case 0x6c: case 0x74: case 0x7c:
1628  { II ii = neg(); NEXT; }
1629 
1630  case 0xa0: { II ii = ldi(); NEXT; }
1631  case 0xa1: { II ii = cpi(); NEXT; }
1632  case 0xa2: { II ii = ini(); NEXT; }
1633  case 0xa3: { II ii = outi(); NEXT; }
1634  case 0xa8: { II ii = ldd(); NEXT; }
1635  case 0xa9: { II ii = cpd(); NEXT; }
1636  case 0xaa: { II ii = ind(); NEXT; }
1637  case 0xab: { II ii = outd(); NEXT; }
1638  case 0xb0: { II ii = ldir(); NEXT; }
1639  case 0xb1: { II ii = cpir(); NEXT; }
1640  case 0xb2: { II ii = inir(); NEXT; }
1641  case 0xb3: { II ii = otir(); NEXT; }
1642  case 0xb8: { II ii = lddr(); NEXT; }
1643  case 0xb9: { II ii = cpdr(); NEXT; }
1644  case 0xba: { II ii = indr(); NEXT; }
1645  case 0xbb: { II ii = otdr(); NEXT; }
1646 
1647  case 0xc1: { II ii = T::isR800() ? mulub_a_R<B>() : nop(); NEXT; }
1648  case 0xc9: { II ii = T::isR800() ? mulub_a_R<C>() : nop(); NEXT; }
1649  case 0xd1: { II ii = T::isR800() ? mulub_a_R<D>() : nop(); NEXT; }
1650  case 0xd9: { II ii = T::isR800() ? mulub_a_R<E>() : nop(); NEXT; }
1651  case 0xc3: { II ii = T::isR800() ? muluw_hl_SS<BC>() : nop(); NEXT; }
1652  case 0xf3: { II ii = T::isR800() ? muluw_hl_SS<SP>() : nop(); NEXT; }
1653  default: UNREACHABLE; return;
1654  }
1655 }
1656 opDD_2:
1657 CASE(DD) {
1658  setPC(getPC() + 1); // M1 cycle at this point
1659  byte opcodeDD = RDMEM_OPCODE<0>(T::CC_DD + T::CC_MAIN);
1660  incR(1);
1661  switch (opcodeDD) {
1662  case 0x00: // nop();
1663  case 0x01: // ld_bc_word();
1664  case 0x02: // ld_xbc_a();
1665  case 0x03: // inc_bc();
1666  case 0x04: // inc_b();
1667  case 0x05: // dec_b();
1668  case 0x06: // ld_b_byte();
1669  case 0x07: // rlca();
1670  case 0x08: // ex_af_af();
1671  case 0x0a: // ld_a_xbc();
1672  case 0x0b: // dec_bc();
1673  case 0x0c: // inc_c();
1674  case 0x0d: // dec_c();
1675  case 0x0e: // ld_c_byte();
1676  case 0x0f: // rrca();
1677  case 0x10: // djnz();
1678  case 0x11: // ld_de_word();
1679  case 0x12: // ld_xde_a();
1680  case 0x13: // inc_de();
1681  case 0x14: // inc_d();
1682  case 0x15: // dec_d();
1683  case 0x16: // ld_d_byte();
1684  case 0x17: // rla();
1685  case 0x18: // jr();
1686  case 0x1a: // ld_a_xde();
1687  case 0x1b: // dec_de();
1688  case 0x1c: // inc_e();
1689  case 0x1d: // dec_e();
1690  case 0x1e: // ld_e_byte();
1691  case 0x1f: // rra();
1692  case 0x20: // jr_nz();
1693  case 0x27: // daa();
1694  case 0x28: // jr_z();
1695  case 0x2f: // cpl();
1696  case 0x30: // jr_nc();
1697  case 0x31: // ld_sp_word();
1698  case 0x32: // ld_xbyte_a();
1699  case 0x33: // inc_sp();
1700  case 0x37: // scf();
1701  case 0x38: // jr_c();
1702  case 0x3a: // ld_a_xbyte();
1703  case 0x3b: // dec_sp();
1704  case 0x3c: // inc_a();
1705  case 0x3d: // dec_a();
1706  case 0x3e: // ld_a_byte();
1707  case 0x3f: // ccf();
1708 
1709  case 0x40: // ld_b_b();
1710  case 0x41: // ld_b_c();
1711  case 0x42: // ld_b_d();
1712  case 0x43: // ld_b_e();
1713  case 0x47: // ld_b_a();
1714  case 0x48: // ld_c_b();
1715  case 0x49: // ld_c_c();
1716  case 0x4a: // ld_c_d();
1717  case 0x4b: // ld_c_e();
1718  case 0x4f: // ld_c_a();
1719  case 0x50: // ld_d_b();
1720  case 0x51: // ld_d_c();
1721  case 0x52: // ld_d_d();
1722  case 0x53: // ld_d_e();
1723  case 0x57: // ld_d_a();
1724  case 0x58: // ld_e_b();
1725  case 0x59: // ld_e_c();
1726  case 0x5a: // ld_e_d();
1727  case 0x5b: // ld_e_e();
1728  case 0x5f: // ld_e_a();
1729  case 0x64: // ld_ixh_ixh(); == nop
1730  case 0x6d: // ld_ixl_ixl(); == nop
1731  case 0x76: // halt();
1732  case 0x78: // ld_a_b();
1733  case 0x79: // ld_a_c();
1734  case 0x7a: // ld_a_d();
1735  case 0x7b: // ld_a_e();
1736  case 0x7f: // ld_a_a();
1737 
1738  case 0x80: // add_a_b();
1739  case 0x81: // add_a_c();
1740  case 0x82: // add_a_d();
1741  case 0x83: // add_a_e();
1742  case 0x87: // add_a_a();
1743  case 0x88: // adc_a_b();
1744  case 0x89: // adc_a_c();
1745  case 0x8a: // adc_a_d();
1746  case 0x8b: // adc_a_e();
1747  case 0x8f: // adc_a_a();
1748  case 0x90: // sub_b();
1749  case 0x91: // sub_c();
1750  case 0x92: // sub_d();
1751  case 0x93: // sub_e();
1752  case 0x97: // sub_a();
1753  case 0x98: // sbc_a_b();
1754  case 0x99: // sbc_a_c();
1755  case 0x9a: // sbc_a_d();
1756  case 0x9b: // sbc_a_e();
1757  case 0x9f: // sbc_a_a();
1758  case 0xa0: // and_b();
1759  case 0xa1: // and_c();
1760  case 0xa2: // and_d();
1761  case 0xa3: // and_e();
1762  case 0xa7: // and_a();
1763  case 0xa8: // xor_b();
1764  case 0xa9: // xor_c();
1765  case 0xaa: // xor_d();
1766  case 0xab: // xor_e();
1767  case 0xaf: // xor_a();
1768  case 0xb0: // or_b();
1769  case 0xb1: // or_c();
1770  case 0xb2: // or_d();
1771  case 0xb3: // or_e();
1772  case 0xb7: // or_a();
1773  case 0xb8: // cp_b();
1774  case 0xb9: // cp_c();
1775  case 0xba: // cp_d();
1776  case 0xbb: // cp_e();
1777  case 0xbf: // cp_a();
1778 
1779  case 0xc0: // ret_nz();
1780  case 0xc1: // pop_bc();
1781  case 0xc2: // jp_nz();
1782  case 0xc3: // jp();
1783  case 0xc4: // call_nz();
1784  case 0xc5: // push_bc();
1785  case 0xc6: // add_a_byte();
1786  case 0xc7: // rst_00();
1787  case 0xc8: // ret_z();
1788  case 0xc9: // ret();
1789  case 0xca: // jp_z();
1790  case 0xcc: // call_z();
1791  case 0xcd: // call();
1792  case 0xce: // adc_a_byte();
1793  case 0xcf: // rst_08();
1794  case 0xd0: // ret_nc();
1795  case 0xd1: // pop_de();
1796  case 0xd2: // jp_nc();
1797  case 0xd3: // out_byte_a();
1798  case 0xd4: // call_nc();
1799  case 0xd5: // push_de();
1800  case 0xd6: // sub_byte();
1801  case 0xd7: // rst_10();
1802  case 0xd8: // ret_c();
1803  case 0xd9: // exx();
1804  case 0xda: // jp_c();
1805  case 0xdb: // in_a_byte();
1806  case 0xdc: // call_c();
1807  case 0xde: // sbc_a_byte();
1808  case 0xdf: // rst_18();
1809  case 0xe0: // ret_po();
1810  case 0xe2: // jp_po();
1811  case 0xe4: // call_po();
1812  case 0xe6: // and_byte();
1813  case 0xe7: // rst_20();
1814  case 0xe8: // ret_pe();
1815  case 0xea: // jp_pe();
1816  case 0xeb: // ex_de_hl();
1817  case 0xec: // call_pe();
1818  case 0xed: // ed();
1819  case 0xee: // xor_byte();
1820  case 0xef: // rst_28();
1821  case 0xf0: // ret_p();
1822  case 0xf1: // pop_af();
1823  case 0xf2: // jp_p();
1824  case 0xf3: // di();
1825  case 0xf4: // call_p();
1826  case 0xf5: // push_af();
1827  case 0xf6: // or_byte();
1828  case 0xf7: // rst_30();
1829  case 0xf8: // ret_m();
1830  case 0xfa: // jp_m();
1831  case 0xfb: // ei();
1832  case 0xfc: // call_m();
1833  case 0xfe: // cp_byte();
1834  case 0xff: // rst_38();
1835  if (T::isR800()) {
1836  II ii = nop();
1837  ii.cycles += T::CC_DD;
1838  NEXT;
1839  } else {
1840  T::add(T::CC_DD);
1841  #ifdef USE_COMPUTED_GOTO
1842  goto *(opcodeTable[opcodeDD]);
1843  #else
1844  opcodeMain = opcodeDD;
1845  goto switchopcode;
1846  #endif
1847  }
1848 
1849  case 0x09: { II ii = add_SS_TT<IX,BC,T::CC_DD>(); NEXT; }
1850  case 0x19: { II ii = add_SS_TT<IX,DE,T::CC_DD>(); NEXT; }
1851  case 0x29: { II ii = add_SS_SS<IX ,T::CC_DD>(); NEXT; }
1852  case 0x39: { II ii = add_SS_TT<IX,SP,T::CC_DD>(); NEXT; }
1853  case 0x21: { II ii = ld_SS_word<IX,T::CC_DD>(); NEXT; }
1854  case 0x22: { II ii = ld_xword_SS<IX,T::CC_DD>(); NEXT; }
1855  case 0x2a: { II ii = ld_SS_xword<IX,T::CC_DD>(); NEXT; }
1856  case 0x23: { II ii = inc_SS<IX,T::CC_DD>(); NEXT; }
1857  case 0x2b: { II ii = dec_SS<IX,T::CC_DD>(); NEXT; }
1858  case 0x24: { II ii = inc_R<IXH,T::CC_DD>(); NEXT; }
1859  case 0x2c: { II ii = inc_R<IXL,T::CC_DD>(); NEXT; }
1860  case 0x25: { II ii = dec_R<IXH,T::CC_DD>(); NEXT; }
1861  case 0x2d: { II ii = dec_R<IXL,T::CC_DD>(); NEXT; }
1862  case 0x26: { II ii = ld_R_byte<IXH,T::CC_DD>(); NEXT; }
1863  case 0x2e: { II ii = ld_R_byte<IXL,T::CC_DD>(); NEXT; }
1864  case 0x34: { II ii = inc_xix<IX>(); NEXT; }
1865  case 0x35: { II ii = dec_xix<IX>(); NEXT; }
1866  case 0x36: { II ii = ld_xix_byte<IX>(); NEXT; }
1867 
1868  case 0x44: { II ii = ld_R_R<B,IXH,T::CC_DD>(); NEXT; }
1869  case 0x45: { II ii = ld_R_R<B,IXL,T::CC_DD>(); NEXT; }
1870  case 0x4c: { II ii = ld_R_R<C,IXH,T::CC_DD>(); NEXT; }
1871  case 0x4d: { II ii = ld_R_R<C,IXL,T::CC_DD>(); NEXT; }
1872  case 0x54: { II ii = ld_R_R<D,IXH,T::CC_DD>(); NEXT; }
1873  case 0x55: { II ii = ld_R_R<D,IXL,T::CC_DD>(); NEXT; }
1874  case 0x5c: { II ii = ld_R_R<E,IXH,T::CC_DD>(); NEXT; }
1875  case 0x5d: { II ii = ld_R_R<E,IXL,T::CC_DD>(); NEXT; }
1876  case 0x7c: { II ii = ld_R_R<A,IXH,T::CC_DD>(); NEXT; }
1877  case 0x7d: { II ii = ld_R_R<A,IXL,T::CC_DD>(); NEXT; }
1878  case 0x60: { II ii = ld_R_R<IXH,B,T::CC_DD>(); NEXT; }
1879  case 0x61: { II ii = ld_R_R<IXH,C,T::CC_DD>(); NEXT; }
1880  case 0x62: { II ii = ld_R_R<IXH,D,T::CC_DD>(); NEXT; }
1881  case 0x63: { II ii = ld_R_R<IXH,E,T::CC_DD>(); NEXT; }
1882  case 0x65: { II ii = ld_R_R<IXH,IXL,T::CC_DD>(); NEXT; }
1883  case 0x67: { II ii = ld_R_R<IXH,A,T::CC_DD>(); NEXT; }
1884  case 0x68: { II ii = ld_R_R<IXL,B,T::CC_DD>(); NEXT; }
1885  case 0x69: { II ii = ld_R_R<IXL,C,T::CC_DD>(); NEXT; }
1886  case 0x6a: { II ii = ld_R_R<IXL,D,T::CC_DD>(); NEXT; }
1887  case 0x6b: { II ii = ld_R_R<IXL,E,T::CC_DD>(); NEXT; }
1888  case 0x6c: { II ii = ld_R_R<IXL,IXH,T::CC_DD>(); NEXT; }
1889  case 0x6f: { II ii = ld_R_R<IXL,A,T::CC_DD>(); NEXT; }
1890  case 0x70: { II ii = ld_xix_R<IX,B>(); NEXT; }
1891  case 0x71: { II ii = ld_xix_R<IX,C>(); NEXT; }
1892  case 0x72: { II ii = ld_xix_R<IX,D>(); NEXT; }
1893  case 0x73: { II ii = ld_xix_R<IX,E>(); NEXT; }
1894  case 0x74: { II ii = ld_xix_R<IX,H>(); NEXT; }
1895  case 0x75: { II ii = ld_xix_R<IX,L>(); NEXT; }
1896  case 0x77: { II ii = ld_xix_R<IX,A>(); NEXT; }
1897  case 0x46: { II ii = ld_R_xix<B,IX>(); NEXT; }
1898  case 0x4e: { II ii = ld_R_xix<C,IX>(); NEXT; }
1899  case 0x56: { II ii = ld_R_xix<D,IX>(); NEXT; }
1900  case 0x5e: { II ii = ld_R_xix<E,IX>(); NEXT; }
1901  case 0x66: { II ii = ld_R_xix<H,IX>(); NEXT; }
1902  case 0x6e: { II ii = ld_R_xix<L,IX>(); NEXT; }
1903  case 0x7e: { II ii = ld_R_xix<A,IX>(); NEXT; }
1904 
1905  case 0x84: { II ii = add_a_R<IXH,T::CC_DD>(); NEXT; }
1906  case 0x85: { II ii = add_a_R<IXL,T::CC_DD>(); NEXT; }
1907  case 0x86: { II ii = add_a_xix<IX>(); NEXT; }
1908  case 0x8c: { II ii = adc_a_R<IXH,T::CC_DD>(); NEXT; }
1909  case 0x8d: { II ii = adc_a_R<IXL,T::CC_DD>(); NEXT; }
1910  case 0x8e: { II ii = adc_a_xix<IX>(); NEXT; }
1911  case 0x94: { II ii = sub_R<IXH,T::CC_DD>(); NEXT; }
1912  case 0x95: { II ii = sub_R<IXL,T::CC_DD>(); NEXT; }
1913  case 0x96: { II ii = sub_xix<IX>(); NEXT; }
1914  case 0x9c: { II ii = sbc_a_R<IXH,T::CC_DD>(); NEXT; }
1915  case 0x9d: { II ii = sbc_a_R<IXL,T::CC_DD>(); NEXT; }
1916  case 0x9e: { II ii = sbc_a_xix<IX>(); NEXT; }
1917  case 0xa4: { II ii = and_R<IXH,T::CC_DD>(); NEXT; }
1918  case 0xa5: { II ii = and_R<IXL,T::CC_DD>(); NEXT; }
1919  case 0xa6: { II ii = and_xix<IX>(); NEXT; }
1920  case 0xac: { II ii = xor_R<IXH,T::CC_DD>(); NEXT; }
1921  case 0xad: { II ii = xor_R<IXL,T::CC_DD>(); NEXT; }
1922  case 0xae: { II ii = xor_xix<IX>(); NEXT; }
1923  case 0xb4: { II ii = or_R<IXH,T::CC_DD>(); NEXT; }
1924  case 0xb5: { II ii = or_R<IXL,T::CC_DD>(); NEXT; }
1925  case 0xb6: { II ii = or_xix<IX>(); NEXT; }
1926  case 0xbc: { II ii = cp_R<IXH,T::CC_DD>(); NEXT; }
1927  case 0xbd: { II ii = cp_R<IXL,T::CC_DD>(); NEXT; }
1928  case 0xbe: { II ii = cp_xix<IX>(); NEXT; }
1929 
1930  case 0xe1: { II ii = pop_SS <IX,T::CC_DD>(); NEXT; }
1931  case 0xe5: { II ii = push_SS<IX,T::CC_DD>(); NEXT; }
1932  case 0xe3: { II ii = ex_xsp_SS<IX,T::CC_DD>(); NEXT; }
1933  case 0xe9: { II ii = jp_SS<IX,T::CC_DD>(); NEXT; }
1934  case 0xf9: { II ii = ld_sp_SS<IX,T::CC_DD>(); NEXT; }
1935  case 0xcb: ixy = getIX(); goto xx_cb;
1936  case 0xdd: T::add(T::CC_DD); goto opDD_2;
1937  case 0xfd: T::add(T::CC_DD); goto opFD_2;
1938  default: UNREACHABLE; return;
1939  }
1940 }
1941 opFD_2:
1942 CASE(FD) {
1943  setPC(getPC() + 1); // M1 cycle at this point
1944  byte opcodeFD = RDMEM_OPCODE<0>(T::CC_DD + T::CC_MAIN);
1945  incR(1);
1946  switch (opcodeFD) {
1947  case 0x00: // nop();
1948  case 0x01: // ld_bc_word();
1949  case 0x02: // ld_xbc_a();
1950  case 0x03: // inc_bc();
1951  case 0x04: // inc_b();
1952  case 0x05: // dec_b();
1953  case 0x06: // ld_b_byte();
1954  case 0x07: // rlca();
1955  case 0x08: // ex_af_af();
1956  case 0x0a: // ld_a_xbc();
1957  case 0x0b: // dec_bc();
1958  case 0x0c: // inc_c();
1959  case 0x0d: // dec_c();
1960  case 0x0e: // ld_c_byte();
1961  case 0x0f: // rrca();
1962  case 0x10: // djnz();
1963  case 0x11: // ld_de_word();
1964  case 0x12: // ld_xde_a();
1965  case 0x13: // inc_de();
1966  case 0x14: // inc_d();
1967  case 0x15: // dec_d();
1968  case 0x16: // ld_d_byte();
1969  case 0x17: // rla();
1970  case 0x18: // jr();
1971  case 0x1a: // ld_a_xde();
1972  case 0x1b: // dec_de();
1973  case 0x1c: // inc_e();
1974  case 0x1d: // dec_e();
1975  case 0x1e: // ld_e_byte();
1976  case 0x1f: // rra();
1977  case 0x20: // jr_nz();
1978  case 0x27: // daa();
1979  case 0x28: // jr_z();
1980  case 0x2f: // cpl();
1981  case 0x30: // jr_nc();
1982  case 0x31: // ld_sp_word();
1983  case 0x32: // ld_xbyte_a();
1984  case 0x33: // inc_sp();
1985  case 0x37: // scf();
1986  case 0x38: // jr_c();
1987  case 0x3a: // ld_a_xbyte();
1988  case 0x3b: // dec_sp();
1989  case 0x3c: // inc_a();
1990  case 0x3d: // dec_a();
1991  case 0x3e: // ld_a_byte();
1992  case 0x3f: // ccf();
1993 
1994  case 0x40: // ld_b_b();
1995  case 0x41: // ld_b_c();
1996  case 0x42: // ld_b_d();
1997  case 0x43: // ld_b_e();
1998  case 0x47: // ld_b_a();
1999  case 0x48: // ld_c_b();
2000  case 0x49: // ld_c_c();
2001  case 0x4a: // ld_c_d();
2002  case 0x4b: // ld_c_e();
2003  case 0x4f: // ld_c_a();
2004  case 0x50: // ld_d_b();
2005  case 0x51: // ld_d_c();
2006  case 0x52: // ld_d_d();
2007  case 0x53: // ld_d_e();
2008  case 0x57: // ld_d_a();
2009  case 0x58: // ld_e_b();
2010  case 0x59: // ld_e_c();
2011  case 0x5a: // ld_e_d();
2012  case 0x5b: // ld_e_e();
2013  case 0x5f: // ld_e_a();
2014  case 0x64: // ld_ixh_ixh(); == nop
2015  case 0x6d: // ld_ixl_ixl(); == nop
2016  case 0x76: // halt();
2017  case 0x78: // ld_a_b();
2018  case 0x79: // ld_a_c();
2019  case 0x7a: // ld_a_d();
2020  case 0x7b: // ld_a_e();
2021  case 0x7f: // ld_a_a();
2022 
2023  case 0x80: // add_a_b();
2024  case 0x81: // add_a_c();
2025  case 0x82: // add_a_d();
2026  case 0x83: // add_a_e();
2027  case 0x87: // add_a_a();
2028  case 0x88: // adc_a_b();
2029  case 0x89: // adc_a_c();
2030  case 0x8a: // adc_a_d();
2031  case 0x8b: // adc_a_e();
2032  case 0x8f: // adc_a_a();
2033  case 0x90: // sub_b();
2034  case 0x91: // sub_c();
2035  case 0x92: // sub_d();
2036  case 0x93: // sub_e();
2037  case 0x97: // sub_a();
2038  case 0x98: // sbc_a_b();
2039  case 0x99: // sbc_a_c();
2040  case 0x9a: // sbc_a_d();
2041  case 0x9b: // sbc_a_e();
2042  case 0x9f: // sbc_a_a();
2043  case 0xa0: // and_b();
2044  case 0xa1: // and_c();
2045  case 0xa2: // and_d();
2046  case 0xa3: // and_e();
2047  case 0xa7: // and_a();
2048  case 0xa8: // xor_b();
2049  case 0xa9: // xor_c();
2050  case 0xaa: // xor_d();
2051  case 0xab: // xor_e();
2052  case 0xaf: // xor_a();
2053  case 0xb0: // or_b();
2054  case 0xb1: // or_c();
2055  case 0xb2: // or_d();
2056  case 0xb3: // or_e();
2057  case 0xb7: // or_a();
2058  case 0xb8: // cp_b();
2059  case 0xb9: // cp_c();
2060  case 0xba: // cp_d();
2061  case 0xbb: // cp_e();
2062  case 0xbf: // cp_a();
2063 
2064  case 0xc0: // ret_nz();
2065  case 0xc1: // pop_bc();
2066  case 0xc2: // jp_nz();
2067  case 0xc3: // jp();
2068  case 0xc4: // call_nz();
2069  case 0xc5: // push_bc();
2070  case 0xc6: // add_a_byte();
2071  case 0xc7: // rst_00();
2072  case 0xc8: // ret_z();
2073  case 0xc9: // ret();
2074  case 0xca: // jp_z();
2075  case 0xcc: // call_z();
2076  case 0xcd: // call();
2077  case 0xce: // adc_a_byte();
2078  case 0xcf: // rst_08();
2079  case 0xd0: // ret_nc();
2080  case 0xd1: // pop_de();
2081  case 0xd2: // jp_nc();
2082  case 0xd3: // out_byte_a();
2083  case 0xd4: // call_nc();
2084  case 0xd5: // push_de();
2085  case 0xd6: // sub_byte();
2086  case 0xd7: // rst_10();
2087  case 0xd8: // ret_c();
2088  case 0xd9: // exx();
2089  case 0xda: // jp_c();
2090  case 0xdb: // in_a_byte();
2091  case 0xdc: // call_c();
2092  case 0xde: // sbc_a_byte();
2093  case 0xdf: // rst_18();
2094  case 0xe0: // ret_po();
2095  case 0xe2: // jp_po();
2096  case 0xe4: // call_po();
2097  case 0xe6: // and_byte();
2098  case 0xe7: // rst_20();
2099  case 0xe8: // ret_pe();
2100  case 0xea: // jp_pe();
2101  case 0xeb: // ex_de_hl();
2102  case 0xec: // call_pe();
2103  case 0xed: // ed();
2104  case 0xee: // xor_byte();
2105  case 0xef: // rst_28();
2106  case 0xf0: // ret_p();
2107  case 0xf1: // pop_af();
2108  case 0xf2: // jp_p();
2109  case 0xf3: // di();
2110  case 0xf4: // call_p();
2111  case 0xf5: // push_af();
2112  case 0xf6: // or_byte();
2113  case 0xf7: // rst_30();
2114  case 0xf8: // ret_m();
2115  case 0xfa: // jp_m();
2116  case 0xfb: // ei();
2117  case 0xfc: // call_m();
2118  case 0xfe: // cp_byte();
2119  case 0xff: // rst_38();
2120  if (T::isR800()) {
2121  II ii = nop();
2122  ii.cycles += T::CC_DD;
2123  NEXT;
2124  } else {
2125  T::add(T::CC_DD);
2126  #ifdef USE_COMPUTED_GOTO
2127  goto *(opcodeTable[opcodeFD]);
2128  #else
2129  opcodeMain = opcodeFD;
2130  goto switchopcode;
2131  #endif
2132  }
2133 
2134  case 0x09: { II ii = add_SS_TT<IY,BC,T::CC_DD>(); NEXT; }
2135  case 0x19: { II ii = add_SS_TT<IY,DE,T::CC_DD>(); NEXT; }
2136  case 0x29: { II ii = add_SS_SS<IY ,T::CC_DD>(); NEXT; }
2137  case 0x39: { II ii = add_SS_TT<IY,SP,T::CC_DD>(); NEXT; }
2138  case 0x21: { II ii = ld_SS_word<IY,T::CC_DD>(); NEXT; }
2139  case 0x22: { II ii = ld_xword_SS<IY,T::CC_DD>(); NEXT; }
2140  case 0x2a: { II ii = ld_SS_xword<IY,T::CC_DD>(); NEXT; }
2141  case 0x23: { II ii = inc_SS<IY,T::CC_DD>(); NEXT; }
2142  case 0x2b: { II ii = dec_SS<IY,T::CC_DD>(); NEXT; }
2143  case 0x24: { II ii = inc_R<IYH,T::CC_DD>(); NEXT; }
2144  case 0x2c: { II ii = inc_R<IYL,T::CC_DD>(); NEXT; }
2145  case 0x25: { II ii = dec_R<IYH,T::CC_DD>(); NEXT; }
2146  case 0x2d: { II ii = dec_R<IYL,T::CC_DD>(); NEXT; }
2147  case 0x26: { II ii = ld_R_byte<IYH,T::CC_DD>(); NEXT; }
2148  case 0x2e: { II ii = ld_R_byte<IYL,T::CC_DD>(); NEXT; }
2149  case 0x34: { II ii = inc_xix<IY>(); NEXT; }
2150  case 0x35: { II ii = dec_xix<IY>(); NEXT; }
2151  case 0x36: { II ii = ld_xix_byte<IY>(); NEXT; }
2152 
2153  case 0x44: { II ii = ld_R_R<B,IYH,T::CC_DD>(); NEXT; }
2154  case 0x45: { II ii = ld_R_R<B,IYL,T::CC_DD>(); NEXT; }
2155  case 0x4c: { II ii = ld_R_R<C,IYH,T::CC_DD>(); NEXT; }
2156  case 0x4d: { II ii = ld_R_R<C,IYL,T::CC_DD>(); NEXT; }
2157  case 0x54: { II ii = ld_R_R<D,IYH,T::CC_DD>(); NEXT; }
2158  case 0x55: { II ii = ld_R_R<D,IYL,T::CC_DD>(); NEXT; }
2159  case 0x5c: { II ii = ld_R_R<E,IYH,T::CC_DD>(); NEXT; }
2160  case 0x5d: { II ii = ld_R_R<E,IYL,T::CC_DD>(); NEXT; }
2161  case 0x7c: { II ii = ld_R_R<A,IYH,T::CC_DD>(); NEXT; }
2162  case 0x7d: { II ii = ld_R_R<A,IYL,T::CC_DD>(); NEXT; }
2163  case 0x60: { II ii = ld_R_R<IYH,B,T::CC_DD>(); NEXT; }
2164  case 0x61: { II ii = ld_R_R<IYH,C,T::CC_DD>(); NEXT; }
2165  case 0x62: { II ii = ld_R_R<IYH,D,T::CC_DD>(); NEXT; }
2166  case 0x63: { II ii = ld_R_R<IYH,E,T::CC_DD>(); NEXT; }
2167  case 0x65: { II ii = ld_R_R<IYH,IYL,T::CC_DD>(); NEXT; }
2168  case 0x67: { II ii = ld_R_R<IYH,A,T::CC_DD>(); NEXT; }
2169  case 0x68: { II ii = ld_R_R<IYL,B,T::CC_DD>(); NEXT; }
2170  case 0x69: { II ii = ld_R_R<IYL,C,T::CC_DD>(); NEXT; }
2171  case 0x6a: { II ii = ld_R_R<IYL,D,T::CC_DD>(); NEXT; }
2172  case 0x6b: { II ii = ld_R_R<IYL,E,T::CC_DD>(); NEXT; }
2173  case 0x6c: { II ii = ld_R_R<IYL,IYH,T::CC_DD>(); NEXT; }
2174  case 0x6f: { II ii = ld_R_R<IYL,A,T::CC_DD>(); NEXT; }
2175  case 0x70: { II ii = ld_xix_R<IY,B>(); NEXT; }
2176  case 0x71: { II ii = ld_xix_R<IY,C>(); NEXT; }
2177  case 0x72: { II ii = ld_xix_R<IY,D>(); NEXT; }
2178  case 0x73: { II ii = ld_xix_R<IY,E>(); NEXT; }
2179  case 0x74: { II ii = ld_xix_R<IY,H>(); NEXT; }
2180  case 0x75: { II ii = ld_xix_R<IY,L>(); NEXT; }
2181  case 0x77: { II ii = ld_xix_R<IY,A>(); NEXT; }
2182  case 0x46: { II ii = ld_R_xix<B,IY>(); NEXT; }
2183  case 0x4e: { II ii = ld_R_xix<C,IY>(); NEXT; }
2184  case 0x56: { II ii = ld_R_xix<D,IY>(); NEXT; }
2185  case 0x5e: { II ii = ld_R_xix<E,IY>(); NEXT; }
2186  case 0x66: { II ii = ld_R_xix<H,IY>(); NEXT; }
2187  case 0x6e: { II ii = ld_R_xix<L,IY>(); NEXT; }
2188  case 0x7e: { II ii = ld_R_xix<A,IY>(); NEXT; }
2189 
2190  case 0x84: { II ii = add_a_R<IYH,T::CC_DD>(); NEXT; }
2191  case 0x85: { II ii = add_a_R<IYL,T::CC_DD>(); NEXT; }
2192  case 0x86: { II ii = add_a_xix<IY>(); NEXT; }
2193  case 0x8c: { II ii = adc_a_R<IYH,T::CC_DD>(); NEXT; }
2194  case 0x8d: { II ii = adc_a_R<IYL,T::CC_DD>(); NEXT; }
2195  case 0x8e: { II ii = adc_a_xix<IY>(); NEXT; }
2196  case 0x94: { II ii = sub_R<IYH,T::CC_DD>(); NEXT; }
2197  case 0x95: { II ii = sub_R<IYL,T::CC_DD>(); NEXT; }
2198  case 0x96: { II ii = sub_xix<IY>(); NEXT; }
2199  case 0x9c: { II ii = sbc_a_R<IYH,T::CC_DD>(); NEXT; }
2200  case 0x9d: { II ii = sbc_a_R<IYL,T::CC_DD>(); NEXT; }
2201  case 0x9e: { II ii = sbc_a_xix<IY>(); NEXT; }
2202  case 0xa4: { II ii = and_R<IYH,T::CC_DD>(); NEXT; }
2203  case 0xa5: { II ii = and_R<IYL,T::CC_DD>(); NEXT; }
2204  case 0xa6: { II ii = and_xix<IY>(); NEXT; }
2205  case 0xac: { II ii = xor_R<IYH,T::CC_DD>(); NEXT; }
2206  case 0xad: { II ii = xor_R<IYL,T::CC_DD>(); NEXT; }
2207  case 0xae: { II ii = xor_xix<IY>(); NEXT; }
2208  case 0xb4: { II ii = or_R<IYH,T::CC_DD>(); NEXT; }
2209  case 0xb5: { II ii = or_R<IYL,T::CC_DD>(); NEXT; }
2210  case 0xb6: { II ii = or_xix<IY>(); NEXT; }
2211  case 0xbc: { II ii = cp_R<IYH,T::CC_DD>(); NEXT; }
2212  case 0xbd: { II ii = cp_R<IYL,T::CC_DD>(); NEXT; }
2213  case 0xbe: { II ii = cp_xix<IY>(); NEXT; }
2214 
2215  case 0xe1: { II ii = pop_SS <IY,T::CC_DD>(); NEXT; }
2216  case 0xe5: { II ii = push_SS<IY,T::CC_DD>(); NEXT; }
2217  case 0xe3: { II ii = ex_xsp_SS<IY,T::CC_DD>(); NEXT; }
2218  case 0xe9: { II ii = jp_SS<IY,T::CC_DD>(); NEXT; }
2219  case 0xf9: { II ii = ld_sp_SS<IY,T::CC_DD>(); NEXT; }
2220  case 0xcb: ixy = getIY(); goto xx_cb;
2221  case 0xdd: T::add(T::CC_DD); goto opDD_2;
2222  case 0xfd: T::add(T::CC_DD); goto opFD_2;
2223  default: UNREACHABLE; return;
2224  }
2225 }
2226 #ifndef USE_COMPUTED_GOTO
2227  default: UNREACHABLE; return;
2228 }
2229 #endif
2230 
2231 xx_cb: {
2232  unsigned tmp = RD_WORD_PC<1>(T::CC_DD + T::CC_DD_CB);
2233  int8_t ofst = tmp & 0xFF;
2234  unsigned addr = (ixy + ofst) & 0xFFFF;
2235  byte xxcb_opcode = tmp >> 8;
2236  switch (xxcb_opcode) {
2237  case 0x00: { II ii = rlc_xix_R<B>(addr); NEXT; }
2238  case 0x01: { II ii = rlc_xix_R<C>(addr); NEXT; }
2239  case 0x02: { II ii = rlc_xix_R<D>(addr); NEXT; }
2240  case 0x03: { II ii = rlc_xix_R<E>(addr); NEXT; }
2241  case 0x04: { II ii = rlc_xix_R<H>(addr); NEXT; }
2242  case 0x05: { II ii = rlc_xix_R<L>(addr); NEXT; }
2243  case 0x06: { II ii = rlc_xix_R<DUMMY>(addr); NEXT; }
2244  case 0x07: { II ii = rlc_xix_R<A>(addr); NEXT; }
2245  case 0x08: { II ii = rrc_xix_R<B>(addr); NEXT; }
2246  case 0x09: { II ii = rrc_xix_R<C>(addr); NEXT; }
2247  case 0x0a: { II ii = rrc_xix_R<D>(addr); NEXT; }
2248  case 0x0b: { II ii = rrc_xix_R<E>(addr); NEXT; }
2249  case 0x0c: { II ii = rrc_xix_R<H>(addr); NEXT; }
2250  case 0x0d: { II ii = rrc_xix_R<L>(addr); NEXT; }
2251  case 0x0e: { II ii = rrc_xix_R<DUMMY>(addr); NEXT; }
2252  case 0x0f: { II ii = rrc_xix_R<A>(addr); NEXT; }
2253  case 0x10: { II ii = rl_xix_R<B>(addr); NEXT; }
2254  case 0x11: { II ii = rl_xix_R<C>(addr); NEXT; }
2255  case 0x12: { II ii = rl_xix_R<D>(addr); NEXT; }
2256  case 0x13: { II ii = rl_xix_R<E>(addr); NEXT; }
2257  case 0x14: { II ii = rl_xix_R<H>(addr); NEXT; }
2258  case 0x15: { II ii = rl_xix_R<L>(addr); NEXT; }
2259  case 0x16: { II ii = rl_xix_R<DUMMY>(addr); NEXT; }
2260  case 0x17: { II ii = rl_xix_R<A>(addr); NEXT; }
2261  case 0x18: { II ii = rr_xix_R<B>(addr); NEXT; }
2262  case 0x19: { II ii = rr_xix_R<C>(addr); NEXT; }
2263  case 0x1a: { II ii = rr_xix_R<D>(addr); NEXT; }
2264  case 0x1b: { II ii = rr_xix_R<E>(addr); NEXT; }
2265  case 0x1c: { II ii = rr_xix_R<H>(addr); NEXT; }
2266  case 0x1d: { II ii = rr_xix_R<L>(addr); NEXT; }
2267  case 0x1e: { II ii = rr_xix_R<DUMMY>(addr); NEXT; }
2268  case 0x1f: { II ii = rr_xix_R<A>(addr); NEXT; }
2269  case 0x20: { II ii = sla_xix_R<B>(addr); NEXT; }
2270  case 0x21: { II ii = sla_xix_R<C>(addr); NEXT; }
2271  case 0x22: { II ii = sla_xix_R<D>(addr); NEXT; }
2272  case 0x23: { II ii = sla_xix_R<E>(addr); NEXT; }
2273  case 0x24: { II ii = sla_xix_R<H>(addr); NEXT; }
2274  case 0x25: { II ii = sla_xix_R<L>(addr); NEXT; }
2275  case 0x26: { II ii = sla_xix_R<DUMMY>(addr); NEXT; }
2276  case 0x27: { II ii = sla_xix_R<A>(addr); NEXT; }
2277  case 0x28: { II ii = sra_xix_R<B>(addr); NEXT; }
2278  case 0x29: { II ii = sra_xix_R<C>(addr); NEXT; }
2279  case 0x2a: { II ii = sra_xix_R<D>(addr); NEXT; }
2280  case 0x2b: { II ii = sra_xix_R<E>(addr); NEXT; }
2281  case 0x2c: { II ii = sra_xix_R<H>(addr); NEXT; }
2282  case 0x2d: { II ii = sra_xix_R<L>(addr); NEXT; }
2283  case 0x2e: { II ii = sra_xix_R<DUMMY>(addr); NEXT; }
2284  case 0x2f: { II ii = sra_xix_R<A>(addr); NEXT; }
2285  case 0x30: { II ii = T::isR800() ? sll2() : sll_xix_R<B>(addr); NEXT; }
2286  case 0x31: { II ii = T::isR800() ? sll2() : sll_xix_R<C>(addr); NEXT; }
2287  case 0x32: { II ii = T::isR800() ? sll2() : sll_xix_R<D>(addr); NEXT; }
2288  case 0x33: { II ii = T::isR800() ? sll2() : sll_xix_R<E>(addr); NEXT; }
2289  case 0x34: { II ii = T::isR800() ? sll2() : sll_xix_R<H>(addr); NEXT; }
2290  case 0x35: { II ii = T::isR800() ? sll2() : sll_xix_R<L>(addr); NEXT; }
2291  case 0x36: { II ii = T::isR800() ? sll2() : sll_xix_R<DUMMY>(addr); NEXT; }
2292  case 0x37: { II ii = T::isR800() ? sll2() : sll_xix_R<A>(addr); NEXT; }
2293  case 0x38: { II ii = srl_xix_R<B>(addr); NEXT; }
2294  case 0x39: { II ii = srl_xix_R<C>(addr); NEXT; }
2295  case 0x3a: { II ii = srl_xix_R<D>(addr); NEXT; }
2296  case 0x3b: { II ii = srl_xix_R<E>(addr); NEXT; }
2297  case 0x3c: { II ii = srl_xix_R<H>(addr); NEXT; }
2298  case 0x3d: { II ii = srl_xix_R<L>(addr); NEXT; }
2299  case 0x3e: { II ii = srl_xix_R<DUMMY>(addr); NEXT; }
2300  case 0x3f: { II ii = srl_xix_R<A>(addr); NEXT; }
2301 
2302  case 0x40: case 0x41: case 0x42: case 0x43:
2303  case 0x44: case 0x45: case 0x46: case 0x47:
2304  { II ii = bit_N_xix<0>(addr); NEXT; }
2305  case 0x48: case 0x49: case 0x4a: case 0x4b:
2306  case 0x4c: case 0x4d: case 0x4e: case 0x4f:
2307  { II ii = bit_N_xix<1>(addr); NEXT; }
2308  case 0x50: case 0x51: case 0x52: case 0x53:
2309  case 0x54: case 0x55: case 0x56: case 0x57:
2310  { II ii = bit_N_xix<2>(addr); NEXT; }
2311  case 0x58: case 0x59: case 0x5a: case 0x5b:
2312  case 0x5c: case 0x5d: case 0x5e: case 0x5f:
2313  { II ii = bit_N_xix<3>(addr); NEXT; }
2314  case 0x60: case 0x61: case 0x62: case 0x63:
2315  case 0x64: case 0x65: case 0x66: case 0x67:
2316  { II ii = bit_N_xix<4>(addr); NEXT; }
2317  case 0x68: case 0x69: case 0x6a: case 0x6b:
2318  case 0x6c: case 0x6d: case 0x6e: case 0x6f:
2319  { II ii = bit_N_xix<5>(addr); NEXT; }
2320  case 0x70: case 0x71: case 0x72: case 0x73:
2321  case 0x74: case 0x75: case 0x76: case 0x77:
2322  { II ii = bit_N_xix<6>(addr); NEXT; }
2323  case 0x78: case 0x79: case 0x7a: case 0x7b:
2324  case 0x7c: case 0x7d: case 0x7e: case 0x7f:
2325  { II ii = bit_N_xix<7>(addr); NEXT; }
2326 
2327  case 0x80: { II ii = res_N_xix_R<0,B>(addr); NEXT; }
2328  case 0x81: { II ii = res_N_xix_R<0,C>(addr); NEXT; }
2329  case 0x82: { II ii = res_N_xix_R<0,D>(addr); NEXT; }
2330  case 0x83: { II ii = res_N_xix_R<0,E>(addr); NEXT; }
2331  case 0x84: { II ii = res_N_xix_R<0,H>(addr); NEXT; }
2332  case 0x85: { II ii = res_N_xix_R<0,L>(addr); NEXT; }
2333  case 0x87: { II ii = res_N_xix_R<0,A>(addr); NEXT; }
2334  case 0x88: { II ii = res_N_xix_R<1,B>(addr); NEXT; }
2335  case 0x89: { II ii = res_N_xix_R<1,C>(addr); NEXT; }
2336  case 0x8a: { II ii = res_N_xix_R<1,D>(addr); NEXT; }
2337  case 0x8b: { II ii = res_N_xix_R<1,E>(addr); NEXT; }
2338  case 0x8c: { II ii = res_N_xix_R<1,H>(addr); NEXT; }
2339  case 0x8d: { II ii = res_N_xix_R<1,L>(addr); NEXT; }
2340  case 0x8f: { II ii = res_N_xix_R<1,A>(addr); NEXT; }
2341  case 0x90: { II ii = res_N_xix_R<2,B>(addr); NEXT; }
2342  case 0x91: { II ii = res_N_xix_R<2,C>(addr); NEXT; }
2343  case 0x92: { II ii = res_N_xix_R<2,D>(addr); NEXT; }
2344  case 0x93: { II ii = res_N_xix_R<2,E>(addr); NEXT; }
2345  case 0x94: { II ii = res_N_xix_R<2,H>(addr); NEXT; }
2346  case 0x95: { II ii = res_N_xix_R<2,L>(addr); NEXT; }
2347  case 0x97: { II ii = res_N_xix_R<2,A>(addr); NEXT; }
2348  case 0x98: { II ii = res_N_xix_R<3,B>(addr); NEXT; }
2349  case 0x99: { II ii = res_N_xix_R<3,C>(addr); NEXT; }
2350  case 0x9a: { II ii = res_N_xix_R<3,D>(addr); NEXT; }
2351  case 0x9b: { II ii = res_N_xix_R<3,E>(addr); NEXT; }
2352  case 0x9c: { II ii = res_N_xix_R<3,H>(addr); NEXT; }
2353  case 0x9d: { II ii = res_N_xix_R<3,L>(addr); NEXT; }
2354  case 0x9f: { II ii = res_N_xix_R<3,A>(addr); NEXT; }
2355  case 0xa0: { II ii = res_N_xix_R<4,B>(addr); NEXT; }
2356  case 0xa1: { II ii = res_N_xix_R<4,C>(addr); NEXT; }
2357  case 0xa2: { II ii = res_N_xix_R<4,D>(addr); NEXT; }
2358  case 0xa3: { II ii = res_N_xix_R<4,E>(addr); NEXT; }
2359  case 0xa4: { II ii = res_N_xix_R<4,H>(addr); NEXT; }
2360  case 0xa5: { II ii = res_N_xix_R<4,L>(addr); NEXT; }
2361  case 0xa7: { II ii = res_N_xix_R<4,A>(addr); NEXT; }
2362  case 0xa8: { II ii = res_N_xix_R<5,B>(addr); NEXT; }
2363  case 0xa9: { II ii = res_N_xix_R<5,C>(addr); NEXT; }
2364  case 0xaa: { II ii = res_N_xix_R<5,D>(addr); NEXT; }
2365  case 0xab: { II ii = res_N_xix_R<5,E>(addr); NEXT; }
2366  case 0xac: { II ii = res_N_xix_R<5,H>(addr); NEXT; }
2367  case 0xad: { II ii = res_N_xix_R<5,L>(addr); NEXT; }
2368  case 0xaf: { II ii = res_N_xix_R<5,A>(addr); NEXT; }
2369  case 0xb0: { II ii = res_N_xix_R<6,B>(addr); NEXT; }
2370  case 0xb1: { II ii = res_N_xix_R<6,C>(addr); NEXT; }
2371  case 0xb2: { II ii = res_N_xix_R<6,D>(addr); NEXT; }
2372  case 0xb3: { II ii = res_N_xix_R<6,E>(addr); NEXT; }
2373  case 0xb4: { II ii = res_N_xix_R<6,H>(addr); NEXT; }
2374  case 0xb5: { II ii = res_N_xix_R<6,L>(addr); NEXT; }
2375  case 0xb7: { II ii = res_N_xix_R<6,A>(addr); NEXT; }
2376  case 0xb8: { II ii = res_N_xix_R<7,B>(addr); NEXT; }
2377  case 0xb9: { II ii = res_N_xix_R<7,C>(addr); NEXT; }
2378  case 0xba: { II ii = res_N_xix_R<7,D>(addr); NEXT; }
2379  case 0xbb: { II ii = res_N_xix_R<7,E>(addr); NEXT; }
2380  case 0xbc: { II ii = res_N_xix_R<7,H>(addr); NEXT; }
2381  case 0xbd: { II ii = res_N_xix_R<7,L>(addr); NEXT; }
2382  case 0xbf: { II ii = res_N_xix_R<7,A>(addr); NEXT; }
2383  case 0x86: { II ii = res_N_xix_R<0,DUMMY>(addr); NEXT; }
2384  case 0x8e: { II ii = res_N_xix_R<1,DUMMY>(addr); NEXT; }
2385  case 0x96: { II ii = res_N_xix_R<2,DUMMY>(addr); NEXT; }
2386  case 0x9e: { II ii = res_N_xix_R<3,DUMMY>(addr); NEXT; }
2387  case 0xa6: { II ii = res_N_xix_R<4,DUMMY>(addr); NEXT; }
2388  case 0xae: { II ii = res_N_xix_R<5,DUMMY>(addr); NEXT; }
2389  case 0xb6: { II ii = res_N_xix_R<6,DUMMY>(addr); NEXT; }
2390  case 0xbe: { II ii = res_N_xix_R<7,DUMMY>(addr); NEXT; }
2391 
2392  case 0xc0: { II ii = set_N_xix_R<0,B>(addr); NEXT; }
2393  case 0xc1: { II ii = set_N_xix_R<0,C>(addr); NEXT; }
2394  case 0xc2: { II ii = set_N_xix_R<0,D>(addr); NEXT; }
2395  case 0xc3: { II ii = set_N_xix_R<0,E>(addr); NEXT; }
2396  case 0xc4: { II ii = set_N_xix_R<0,H>(addr); NEXT; }
2397  case 0xc5: { II ii = set_N_xix_R<0,L>(addr); NEXT; }
2398  case 0xc7: { II ii = set_N_xix_R<0,A>(addr); NEXT; }
2399  case 0xc8: { II ii = set_N_xix_R<1,B>(addr); NEXT; }
2400  case 0xc9: { II ii = set_N_xix_R<1,C>(addr); NEXT; }
2401  case 0xca: { II ii = set_N_xix_R<1,D>(addr); NEXT; }
2402  case 0xcb: { II ii = set_N_xix_R<1,E>(addr); NEXT; }
2403  case 0xcc: { II ii = set_N_xix_R<1,H>(addr); NEXT; }
2404  case 0xcd: { II ii = set_N_xix_R<1,L>(addr); NEXT; }
2405  case 0xcf: { II ii = set_N_xix_R<1,A>(addr); NEXT; }
2406  case 0xd0: { II ii = set_N_xix_R<2,B>(addr); NEXT; }
2407  case 0xd1: { II ii = set_N_xix_R<2,C>(addr); NEXT; }
2408  case 0xd2: { II ii = set_N_xix_R<2,D>(addr); NEXT; }
2409  case 0xd3: { II ii = set_N_xix_R<2,E>(addr); NEXT; }
2410  case 0xd4: { II ii = set_N_xix_R<2,H>(addr); NEXT; }
2411  case 0xd5: { II ii = set_N_xix_R<2,L>(addr); NEXT; }
2412  case 0xd7: { II ii = set_N_xix_R<2,A>(addr); NEXT; }
2413  case 0xd8: { II ii = set_N_xix_R<3,B>(addr); NEXT; }
2414  case 0xd9: { II ii = set_N_xix_R<3,C>(addr); NEXT; }
2415  case 0xda: { II ii = set_N_xix_R<3,D>(addr); NEXT; }
2416  case 0xdb: { II ii = set_N_xix_R<3,E>(addr); NEXT; }
2417  case 0xdc: { II ii = set_N_xix_R<3,H>(addr); NEXT; }
2418  case 0xdd: { II ii = set_N_xix_R<3,L>(addr); NEXT; }
2419  case 0xdf: { II ii = set_N_xix_R<3,A>(addr); NEXT; }
2420  case 0xe0: { II ii = set_N_xix_R<4,B>(addr); NEXT; }
2421  case 0xe1: { II ii = set_N_xix_R<4,C>(addr); NEXT; }
2422  case 0xe2: { II ii = set_N_xix_R<4,D>(addr); NEXT; }
2423  case 0xe3: { II ii = set_N_xix_R<4,E>(addr); NEXT; }
2424  case 0xe4: { II ii = set_N_xix_R<4,H>(addr); NEXT; }
2425  case 0xe5: { II ii = set_N_xix_R<4,L>(addr); NEXT; }
2426  case 0xe7: { II ii = set_N_xix_R<4,A>(addr); NEXT; }
2427  case 0xe8: { II ii = set_N_xix_R<5,B>(addr); NEXT; }
2428  case 0xe9: { II ii = set_N_xix_R<5,C>(addr); NEXT; }
2429  case 0xea: { II ii = set_N_xix_R<5,D>(addr); NEXT; }
2430  case 0xeb: { II ii = set_N_xix_R<5,E>(addr); NEXT; }
2431  case 0xec: { II ii = set_N_xix_R<5,H>(addr); NEXT; }
2432  case 0xed: { II ii = set_N_xix_R<5,L>(addr); NEXT; }
2433  case 0xef: { II ii = set_N_xix_R<5,A>(addr); NEXT; }
2434  case 0xf0: { II ii = set_N_xix_R<6,B>(addr); NEXT; }
2435  case 0xf1: { II ii = set_N_xix_R<6,C>(addr); NEXT; }
2436  case 0xf2: { II ii = set_N_xix_R<6,D>(addr); NEXT; }
2437  case 0xf3: { II ii = set_N_xix_R<6,E>(addr); NEXT; }
2438  case 0xf4: { II ii = set_N_xix_R<6,H>(addr); NEXT; }
2439  case 0xf5: { II ii = set_N_xix_R<6,L>(addr); NEXT; }
2440  case 0xf7: { II ii = set_N_xix_R<6,A>(addr); NEXT; }
2441  case 0xf8: { II ii = set_N_xix_R<7,B>(addr); NEXT; }
2442  case 0xf9: { II ii = set_N_xix_R<7,C>(addr); NEXT; }
2443  case 0xfa: { II ii = set_N_xix_R<7,D>(addr); NEXT; }
2444  case 0xfb: { II ii = set_N_xix_R<7,E>(addr); NEXT; }
2445  case 0xfc: { II ii = set_N_xix_R<7,H>(addr); NEXT; }
2446  case 0xfd: { II ii = set_N_xix_R<7,L>(addr); NEXT; }
2447  case 0xff: { II ii = set_N_xix_R<7,A>(addr); NEXT; }
2448  case 0xc6: { II ii = set_N_xix_R<0,DUMMY>(addr); NEXT; }
2449  case 0xce: { II ii = set_N_xix_R<1,DUMMY>(addr); NEXT; }
2450  case 0xd6: { II ii = set_N_xix_R<2,DUMMY>(addr); NEXT; }
2451  case 0xde: { II ii = set_N_xix_R<3,DUMMY>(addr); NEXT; }
2452  case 0xe6: { II ii = set_N_xix_R<4,DUMMY>(addr); NEXT; }
2453  case 0xee: { II ii = set_N_xix_R<5,DUMMY>(addr); NEXT; }
2454  case 0xf6: { II ii = set_N_xix_R<6,DUMMY>(addr); NEXT; }
2455  case 0xfe: { II ii = set_N_xix_R<7,DUMMY>(addr); NEXT; }
2456  default: UNREACHABLE;
2457  }
2458  }
2459 }
2460 
2461 template<class T> inline void CPUCore<T>::cpuTracePre()
2462 {
2463  start_pc = getPC();
2464 }
2465 template<class T> inline void CPUCore<T>::cpuTracePost()
2466 {
2467  if (unlikely(tracingEnabled)) {
2468  cpuTracePost_slow();
2469  }
2470 }
2471 template<class T> void CPUCore<T>::cpuTracePost_slow()
2472 {
2473  byte opbuf[4];
2474  string dasmOutput;
2475  dasm(*interface, start_pc, opbuf, dasmOutput, T::getTimeFast());
2476  std::cout << strCat(hex_string<4>(start_pc),
2477  " : ", dasmOutput,
2478  " AF=", hex_string<4>(getAF()),
2479  " BC=", hex_string<4>(getBC()),
2480  " DE=", hex_string<4>(getDE()),
2481  " HL=", hex_string<4>(getHL()),
2482  " IX=", hex_string<4>(getIX()),
2483  " IY=", hex_string<4>(getIY()),
2484  " SP=", hex_string<4>(getSP()),
2485  '\n')
2486  << std::flush;
2487 }
2488 
2489 template<class T> ExecIRQ CPUCore<T>::getExecIRQ() const
2490 {
2491  if (unlikely(nmiEdge)) return ExecIRQ::NMI;
2492  if (unlikely(IRQStatus && getIFF1() && !prevWasEI())) return ExecIRQ::IRQ;
2493  return ExecIRQ::NONE;
2494 }
2495 
2496 template<class T> void CPUCore<T>::executeSlow(ExecIRQ execIRQ)
2497 {
2498  if (unlikely(execIRQ == ExecIRQ::NMI)) {
2499  nmiEdge = false;
2500  nmi(); // NMI occured
2501  } else if (unlikely(execIRQ == ExecIRQ::IRQ)) {
2502  // normal interrupt
2503  if (unlikely(prevWasLDAI())) {
2504  // HACK!!!
2505  // The 'ld a,i' or 'ld a,r' instruction copies the IFF2
2506  // bit to the V flag. Though when the Z80 accepts an
2507  // IRQ directly after this instruction, the V flag is 0
2508  // (instead of the expected value 1). This can probably
2509  // be explained if you look at the pipeline of the Z80.
2510  // But for speed reasons we implement it here as a
2511  // fix-up (a hack) in the IRQ routine. This behaviour
2512  // is actually a bug in the Z80.
2513  // Thanks to n_n for reporting this behaviour. I think
2514  // this was discovered by GuyveR800. Also thanks to
2515  // n_n for writing a test program that demonstrates
2516  // this quirk.
2517  // I also wrote a test program that demonstrates this
2518  // behaviour is the same whether 'ld a,i' is preceded
2519  // by a 'ei' instruction or not (so it's not caused by
2520  // the 'delayed IRQ acceptance of ei').
2521  assert(getF() & V_FLAG);
2522  setF(getF() & ~V_FLAG);
2523  }
2524  IRQAccept.signal();
2525  switch (getIM()) {
2526  case 0: irq0();
2527  break;
2528  case 1: irq1();
2529  break;
2530  case 2: irq2();
2531  break;
2532  default:
2533  UNREACHABLE;
2534  }
2535  } else if (unlikely(getHALT())) {
2536  // in halt mode
2537  incR(T::advanceHalt(T::haltStates(), scheduler.getNext()));
2538  setSlowInstructions();
2539  } else {
2540  cpuTracePre();
2541  assert(T::limitReached()); // we want only one instruction
2542  executeInstructions();
2543  endInstruction();
2544 
2545  if (T::isR800()) {
2546  if (unlikely(prev2WasCall()) && likely(!prevWasPopRet())) {
2547  // On R800 a CALL or RST instruction not _immediately_
2548  // followed by a (single-byte) POP or RET instruction
2549  // causes an extra cycle in that following instruction.
2550  // No idea why yet. See doc/internal/r800-call.txt
2551  // for more information.
2552  //
2553  // TODO this implementation adds the extra cycle at
2554  // the end of the instruction POP/RET. It is not known
2555  // where in the instruction the real R800 adds this cycle.
2556  T::add(1);
2557  }
2558  }
2559  cpuTracePost();
2560  }
2561 }
2562 
2563 template<class T> void CPUCore<T>::execute(bool fastForward)
2564 {
2565  // In fast-forward mode, breakpoints, watchpoints or debug condtions
2566  // won't trigger. It is possible we already are in break mode, but
2567  // break is ignored in fast-forward mode.
2568  assert(fastForward || !interface->isBreaked());
2569  if (fastForward) {
2570  interface->setFastForward(true);
2571  }
2572  execute2(fastForward);
2573  interface->setFastForward(false);
2574 }
2575 
2576 template<class T> void CPUCore<T>::execute2(bool fastForward)
2577 {
2578  // note: Don't use getTimeFast() here, because 'once in a while' we
2579  // need to CPUClock::sync() to avoid overflow.
2580  // Should be done at least once per second (approx). So only
2581  // once in this method is enough.
2582  scheduler.schedule(T::getTime());
2583  setSlowInstructions();
2584 
2585  if (!fastForward && (interface->isContinue() || interface->isStep())) {
2586  // at least one instruction
2587  interface->setContinue(false);
2588  executeSlow(getExecIRQ());
2589  scheduler.schedule(T::getTimeFast());
2590  --slowInstructions;
2591  if (interface->isStep()) {
2592  interface->setStep(false);
2593  interface->doBreak();
2594  return;
2595  }
2596  }
2597 
2598  // Note: we call scheduler _after_ executing the instruction and before
2599  // deciding between executeFast() and executeSlow() (because a
2600  // SyncPoint could set an IRQ and then we must choose executeSlow())
2601  if (fastForward ||
2602  (!interface->anyBreakPoints() && !tracingEnabled)) {
2603  // fast path, no breakpoints, no tracing
2604  while (!needExitCPULoop()) {
2605  if (slowInstructions) {
2606  --slowInstructions;
2607  executeSlow(getExecIRQ());
2608  scheduler.schedule(T::getTimeFast());
2609  } else {
2610  while (slowInstructions == 0) {
2611  T::enableLimit(); // does CPUClock::sync()
2612  if (likely(!T::limitReached())) {
2613  // multiple instructions
2614  executeInstructions();
2615  // note: pipeline only shifted one
2616  // step for multiple instructions
2617  endInstruction();
2618  }
2619  scheduler.schedule(T::getTimeFast());
2620  if (needExitCPULoop()) return;
2621  }
2622  }
2623  }
2624  } else {
2625  while (!needExitCPULoop()) {
2626  // Only check for breakpoints when we're not about to jump to an IRQ handler.
2627  //
2628  // This fixes the following problem reported by Grauw:
2629  //
2630  // I found a breakpoints bug: sometimes a breakpoint gets hit twice even
2631  // though the code is executed once. This manifests itself in my profiler
2632  // as an imbalance between section begin- and end-calls.
2633  //
2634  // Turns out this occurs when an interrupt occurs exactly on the line of
2635  // the breakpoint, then the breakpoint gets hit before immediately going
2636  // to the ISR, as well as when returning from the ISR.
2637  //
2638  // The IRQ is handled by the Z80 at the end of an instruction. So it
2639  // should change the PC before the next instruction is fetched and the
2640  // breakpoints should be evaluated during instruction fetch.
2641  //
2642  // I think Grauw's analysis is correct. Though for performance reasons we
2643  // don't emulate the Z80 like that: we don't check for IRQs at the end of
2644  // every instruction. In the openMSX emulation model, we can only enter an
2645  // ISR:
2646  // - (One instruction after) switching from DI to EI mode.
2647  // - After emulating device code. This can be:
2648  // * When the Z80 communicated with the device (IO or memory mapped IO).
2649  // * The device had set a synchronization point.
2650  // In all cases disableLimit() gets called which will cause
2651  // limitReached() to return true (and possibly slowInstructions to be > 0).
2652  // So after most emulated Z80 instructions there can't be a pending IRQ, so
2653  // checking for it is wasteful. Also synchronization points are handled
2654  // between emulated Z80 instructions, that means me must check for pending
2655  // IRQs at the start (instead of end) of an instruction.
2656  //
2657  auto execIRQ = getExecIRQ();
2658  if ((execIRQ == ExecIRQ::NONE) &&
2659  interface->checkBreakPoints(getPC(), motherboard)) {
2660  assert(interface->isBreaked());
2661  break;
2662  }
2663  if (slowInstructions == 0) {
2664  cpuTracePre();
2665  assert(T::limitReached()); // only one instruction
2666  executeInstructions();
2667  endInstruction();
2668  cpuTracePost();
2669  } else {
2670  --slowInstructions;
2671  executeSlow(execIRQ);
2672  }
2673  // Don't use getTimeFast() here, we need a call to
2674  // CPUClock::sync() 'once in a while'. (During a
2675  // reverse fast-forward this wasn't always the case).
2676  scheduler.schedule(T::getTime());
2677  }
2678  }
2679 }
2680 
2681 template<class T> template<Reg8 R8> ALWAYS_INLINE byte CPUCore<T>::get8() const {
2682  if (R8 == A) { return getA(); }
2683  else if (R8 == F) { return getF(); }
2684  else if (R8 == B) { return getB(); }
2685  else if (R8 == C) { return getC(); }
2686  else if (R8 == D) { return getD(); }
2687  else if (R8 == E) { return getE(); }
2688  else if (R8 == H) { return getH(); }
2689  else if (R8 == L) { return getL(); }
2690  else if (R8 == IXH) { return getIXh(); }
2691  else if (R8 == IXL) { return getIXl(); }
2692  else if (R8 == IYH) { return getIYh(); }
2693  else if (R8 == IYL) { return getIYl(); }
2694  else if (R8 == REG_I) { return getI(); }
2695  else if (R8 == REG_R) { return getR(); }
2696  else if (R8 == DUMMY) { return 0; }
2697  else { UNREACHABLE; return 0; }
2698 }
2699 template<class T> template<Reg16 R16> ALWAYS_INLINE unsigned CPUCore<T>::get16() const {
2700  if (R16 == AF) { return getAF(); }
2701  else if (R16 == BC) { return getBC(); }
2702  else if (R16 == DE) { return getDE(); }
2703  else if (R16 == HL) { return getHL(); }
2704  else if (R16 == IX) { return getIX(); }
2705  else if (R16 == IY) { return getIY(); }
2706  else if (R16 == SP) { return getSP(); }
2707  else { UNREACHABLE; return 0; }
2708 }
2709 template<class T> template<Reg8 R8> ALWAYS_INLINE void CPUCore<T>::set8(byte x) {
2710  if (R8 == A) { setA(x); }
2711  else if (R8 == F) { setF(x); }
2712  else if (R8 == B) { setB(x); }
2713  else if (R8 == C) { setC(x); }
2714  else if (R8 == D) { setD(x); }
2715  else if (R8 == E) { setE(x); }
2716  else if (R8 == H) { setH(x); }
2717  else if (R8 == L) { setL(x); }
2718  else if (R8 == IXH) { setIXh(x); }
2719  else if (R8 == IXL) { setIXl(x); }
2720  else if (R8 == IYH) { setIYh(x); }
2721  else if (R8 == IYL) { setIYl(x); }
2722  else if (R8 == REG_I) { setI(x); }
2723  else if (R8 == REG_R) { setR(x); }
2724  else if (R8 == DUMMY) { /* nothing */ }
2725  else { UNREACHABLE; }
2726 }
2727 template<class T> template<Reg16 R16> ALWAYS_INLINE void CPUCore<T>::set16(unsigned x) {
2728  if (R16 == AF) { setAF(x); }
2729  else if (R16 == BC) { setBC(x); }
2730  else if (R16 == DE) { setDE(x); }
2731  else if (R16 == HL) { setHL(x); }
2732  else if (R16 == IX) { setIX(x); }
2733  else if (R16 == IY) { setIY(x); }
2734  else if (R16 == SP) { setSP(x); }
2735  else { UNREACHABLE; }
2736 }
2737 
2738 // LD r,r
2739 template<class T> template<Reg8 DST, Reg8 SRC, int EE> II CPUCore<T>::ld_R_R() {
2740  set8<DST>(get8<SRC>()); return {1, T::CC_LD_R_R + EE};
2741 }
2742 
2743 // LD SP,ss
2744 template<class T> template<Reg16 REG, int EE> II CPUCore<T>::ld_sp_SS() {
2745  setSP(get16<REG>()); return {1, T::CC_LD_SP_HL + EE};
2746 }
2747 
2748 // LD (ss),a
2749 template<class T> template<Reg16 REG> II CPUCore<T>::ld_SS_a() {
2750  T::setMemPtr((getA() << 8) | ((get16<REG>() + 1) & 0xFF));
2751  WRMEM(get16<REG>(), getA(), T::CC_LD_SS_A_1);
2752  return {1, T::CC_LD_SS_A};
2753 }
2754 
2755 // LD (HL),r
2756 template<class T> template<Reg8 SRC> II CPUCore<T>::ld_xhl_R() {
2757  WRMEM(getHL(), get8<SRC>(), T::CC_LD_HL_R_1);
2758  return {1, T::CC_LD_HL_R};
2759 }
2760 
2761 // LD (IXY+e),r
2762 template<class T> template<Reg16 IXY, Reg8 SRC> II CPUCore<T>::ld_xix_R() {
2763  int8_t ofst = RDMEM_OPCODE<1>(T::CC_DD + T::CC_LD_XIX_R_1);
2764  unsigned addr = (get16<IXY>() + ofst) & 0xFFFF;
2765  T::setMemPtr(addr);
2766  WRMEM(addr, get8<SRC>(), T::CC_DD + T::CC_LD_XIX_R_2);
2767  return {2, T::CC_DD + T::CC_LD_XIX_R};
2768 }
2769 
2770 // LD (HL),n
2771 template<class T> II CPUCore<T>::ld_xhl_byte() {
2772  byte val = RDMEM_OPCODE<1>(T::CC_LD_HL_N_1);
2773  WRMEM(getHL(), val, T::CC_LD_HL_N_2);
2774  return {2, T::CC_LD_HL_N};
2775 }
2776 
2777 // LD (IXY+e),n
2778 template<class T> template<Reg16 IXY> II CPUCore<T>::ld_xix_byte() {
2779  unsigned tmp = RD_WORD_PC<1>(T::CC_DD + T::CC_LD_XIX_N_1);
2780  int8_t ofst = tmp & 0xFF;
2781  byte val = tmp >> 8;
2782  unsigned addr = (get16<IXY>() + ofst) & 0xFFFF;
2783  T::setMemPtr(addr);
2784  WRMEM(addr, val, T::CC_DD + T::CC_LD_XIX_N_2);
2785  return {3, T::CC_DD + T::CC_LD_XIX_N};
2786 }
2787 
2788 // LD (nn),A
2789 template<class T> II CPUCore<T>::ld_xbyte_a() {
2790  unsigned x = RD_WORD_PC<1>(T::CC_LD_NN_A_1);
2791  T::setMemPtr((getA() << 8) | ((x + 1) & 0xFF));
2792  WRMEM(x, getA(), T::CC_LD_NN_A_2);
2793  return {3, T::CC_LD_NN_A};
2794 }
2795 
2796 // LD (nn),ss
2797 template<class T> template<int EE> inline II CPUCore<T>::WR_NN_Y(unsigned reg) {
2798  unsigned addr = RD_WORD_PC<1>(T::CC_LD_XX_HL_1 + EE);
2799  T::setMemPtr(addr + 1);
2800  WR_WORD(addr, reg, T::CC_LD_XX_HL_2 + EE);
2801  return {3, T::CC_LD_XX_HL + EE};
2802 }
2803 template<class T> template<Reg16 REG, int EE> II CPUCore<T>::ld_xword_SS() {
2804  return WR_NN_Y<EE >(get16<REG>());
2805 }
2806 template<class T> template<Reg16 REG> II CPUCore<T>::ld_xword_SS_ED() {
2807  return WR_NN_Y<T::EE_ED>(get16<REG>());
2808 }
2809 
2810 // LD A,(ss)
2811 template<class T> template<Reg16 REG> II CPUCore<T>::ld_a_SS() {
2812  T::setMemPtr(get16<REG>() + 1);
2813  setA(RDMEM(get16<REG>(), T::CC_LD_A_SS_1));
2814  return {1, T::CC_LD_A_SS};
2815 }
2816 
2817 // LD A,(nn)
2818 template<class T> II CPUCore<T>::ld_a_xbyte() {
2819  unsigned addr = RD_WORD_PC<1>(T::CC_LD_A_NN_1);
2820  T::setMemPtr(addr + 1);
2821  setA(RDMEM(addr, T::CC_LD_A_NN_2));
2822  return {3, T::CC_LD_A_NN};
2823 }
2824 
2825 // LD r,n
2826 template<class T> template<Reg8 DST, int EE> II CPUCore<T>::ld_R_byte() {
2827  set8<DST>(RDMEM_OPCODE<1>(T::CC_LD_R_N_1 + EE)); return {2, T::CC_LD_R_N + EE};
2828 }
2829 
2830 // LD r,(hl)
2831 template<class T> template<Reg8 DST> II CPUCore<T>::ld_R_xhl() {
2832  set8<DST>(RDMEM(getHL(), T::CC_LD_R_HL_1)); return {1, T::CC_LD_R_HL};
2833 }
2834 
2835 // LD r,(IXY+e)
2836 template<class T> template<Reg8 DST, Reg16 IXY> II CPUCore<T>::ld_R_xix() {
2837  int8_t ofst = RDMEM_OPCODE<1>(T::CC_DD + T::CC_LD_R_XIX_1);
2838  unsigned addr = (get16<IXY>() + ofst) & 0xFFFF;
2839  T::setMemPtr(addr);
2840  set8<DST>(RDMEM(addr, T::CC_DD + T::CC_LD_R_XIX_2));
2841  return {2, T::CC_DD + T::CC_LD_R_XIX};
2842 }
2843 
2844 // LD ss,(nn)
2845 template<class T> template<int EE> inline unsigned CPUCore<T>::RD_P_XX() {
2846  unsigned addr = RD_WORD_PC<1>(T::CC_LD_HL_XX_1 + EE);
2847  T::setMemPtr(addr + 1);
2848  unsigned result = RD_WORD(addr, T::CC_LD_HL_XX_2 + EE);
2849  return result;
2850 }
2851 template<class T> template<Reg16 REG, int EE> II CPUCore<T>::ld_SS_xword() {
2852  set16<REG>(RD_P_XX<EE>()); return {3, T::CC_LD_HL_XX + EE};
2853 }
2854 template<class T> template<Reg16 REG> II CPUCore<T>::ld_SS_xword_ED() {
2855  set16<REG>(RD_P_XX<T::EE_ED>()); return {3, T::CC_LD_HL_XX + T::EE_ED};
2856 }
2857 
2858 // LD ss,nn
2859 template<class T> template<Reg16 REG, int EE> II CPUCore<T>::ld_SS_word() {
2860  set16<REG>(RD_WORD_PC<1>(T::CC_LD_SS_NN_1 + EE)); return {3, T::CC_LD_SS_NN + EE};
2861 }
2862 
2863 
2864 // ADC A,r
2865 template<class T> inline void CPUCore<T>::ADC(byte reg) {
2866  unsigned res = getA() + reg + ((getF() & C_FLAG) ? 1 : 0);
2867  byte f = ((res & 0x100) ? C_FLAG : 0) |
2868  ((getA() ^ res ^ reg) & H_FLAG) |
2869  (((getA() ^ res) & (reg ^ res) & 0x80) >> 5) | // V_FLAG
2870  0; // N_FLAG
2871  if (T::isR800()) {
2872  f |= table.ZS[res & 0xFF];
2873  f |= getF() & (X_FLAG | Y_FLAG);
2874  } else {
2875  f |= table.ZSXY[res & 0xFF];
2876  }
2877  setF(f);
2878  setA(res);
2879 }
2880 template<class T> inline II CPUCore<T>::adc_a_a() {
2881  unsigned res = 2 * getA() + ((getF() & C_FLAG) ? 1 : 0);
2882  byte f = ((res & 0x100) ? C_FLAG : 0) |
2883  (res & H_FLAG) |
2884  (((getA() ^ res) & 0x80) >> 5) | // V_FLAG
2885  0; // N_FLAG
2886  if (T::isR800()) {
2887  f |= table.ZS[res & 0xFF];
2888  f |= getF() & (X_FLAG | Y_FLAG);
2889  } else {
2890  f |= table.ZSXY[res & 0xFF];
2891  }
2892  setF(f);
2893  setA(res);
2894  return {1, T::CC_CP_R};
2895 }
2896 template<class T> template<Reg8 SRC, int EE> II CPUCore<T>::adc_a_R() {
2897  ADC(get8<SRC>()); return {1, T::CC_CP_R + EE};
2898 }
2899 template<class T> II CPUCore<T>::adc_a_byte() {
2900  ADC(RDMEM_OPCODE<1>(T::CC_CP_N_1)); return {2, T::CC_CP_N};
2901 }
2902 template<class T> II CPUCore<T>::adc_a_xhl() {
2903  ADC(RDMEM(getHL(), T::CC_CP_XHL_1)); return {1, T::CC_CP_XHL};
2904 }
2905 template<class T> template<Reg16 IXY> II CPUCore<T>::adc_a_xix() {
2906  int8_t ofst = RDMEM_OPCODE<1>(T::CC_DD + T::CC_CP_XIX_1);
2907  unsigned addr = (get16<IXY>() + ofst) & 0xFFFF;
2908  T::setMemPtr(addr);
2909  ADC(RDMEM(addr, T::CC_DD + T::CC_CP_XIX_2));
2910  return {2, T::CC_DD + T::CC_CP_XIX};
2911 }
2912 
2913 // ADD A,r
2914 template<class T> inline void CPUCore<T>::ADD(byte reg) {
2915  unsigned res = getA() + reg;
2916  byte f = ((res & 0x100) ? C_FLAG : 0) |
2917  ((getA() ^ res ^ reg) & H_FLAG) |
2918  (((getA() ^ res) & (reg ^ res) & 0x80) >> 5) | // V_FLAG
2919  0; // N_FLAG
2920  if (T::isR800()) {
2921  f |= table.ZS[res & 0xFF];
2922  f |= getF() & (X_FLAG | Y_FLAG);
2923  } else {
2924  f |= table.ZSXY[res & 0xFF];
2925  }
2926  setF(f);
2927  setA(res);
2928 }
2929 template<class T> inline II CPUCore<T>::add_a_a() {
2930  unsigned res = 2 * getA();
2931  byte f = ((res & 0x100) ? C_FLAG : 0) |
2932  (res & H_FLAG) |
2933  (((getA() ^ res) & 0x80) >> 5) | // V_FLAG
2934  0; // N_FLAG
2935  if (T::isR800()) {
2936  f |= table.ZS[res & 0xFF];
2937  f |= getF() & (X_FLAG | Y_FLAG);
2938  } else {
2939  f |= table.ZSXY[res & 0xFF];
2940  }
2941  setF(f);
2942  setA(res);
2943  return {1, T::CC_CP_R};
2944 }
2945 template<class T> template<Reg8 SRC, int EE> II CPUCore<T>::add_a_R() {
2946  ADD(get8<SRC>()); return {1, T::CC_CP_R + EE};
2947 }
2948 template<class T> II CPUCore<T>::add_a_byte() {
2949  ADD(RDMEM_OPCODE<1>(T::CC_CP_N_1)); return {2, T::CC_CP_N};
2950 }
2951 template<class T> II CPUCore<T>::add_a_xhl() {
2952  ADD(RDMEM(getHL(), T::CC_CP_XHL_1)); return {1, T::CC_CP_XHL};
2953 }
2954 template<class T> template<Reg16 IXY> II CPUCore<T>::add_a_xix() {
2955  int8_t ofst = RDMEM_OPCODE<1>(T::CC_DD + T::CC_CP_XIX_1);
2956  unsigned addr = (get16<IXY>() + ofst) & 0xFFFF;
2957  T::setMemPtr(addr);
2958  ADD(RDMEM(addr, T::CC_DD + T::CC_CP_XIX_2));
2959  return {2, T::CC_DD + T::CC_CP_XIX};
2960 }
2961 
2962 // AND r
2963 template<class T> inline void CPUCore<T>::AND(byte reg) {
2964  setA(getA() & reg);
2965  byte f = 0;
2966  if (T::isR800()) {
2967  f |= table.ZSPH[getA()];
2968  f |= getF() & (X_FLAG | Y_FLAG);
2969  } else {
2970  f |= table.ZSPXY[getA()] | H_FLAG;
2971  }
2972  setF(f);
2973 }
2974 template<class T> II CPUCore<T>::and_a() {
2975  byte f = 0;
2976  if (T::isR800()) {
2977  f |= table.ZSPH[getA()];
2978  f |= getF() & (X_FLAG | Y_FLAG);
2979  } else {
2980  f |= table.ZSPXY[getA()] | H_FLAG;
2981  }
2982  setF(f);
2983  return {1, T::CC_CP_R};
2984 }
2985 template<class T> template<Reg8 SRC, int EE> II CPUCore<T>::and_R() {
2986  AND(get8<SRC>()); return {1, T::CC_CP_R + EE};
2987 }
2988 template<class T> II CPUCore<T>::and_byte() {
2989  AND(RDMEM_OPCODE<1>(T::CC_CP_N_1)); return {2, T::CC_CP_N};
2990 }
2991 template<class T> II CPUCore<T>::and_xhl() {
2992  AND(RDMEM(getHL(), T::CC_CP_XHL_1)); return {1, T::CC_CP_XHL};
2993 }
2994 template<class T> template<Reg16 IXY> II CPUCore<T>::and_xix() {
2995  int8_t ofst = RDMEM_OPCODE<1>(T::CC_DD + T::CC_CP_XIX_1);
2996  unsigned addr = (get16<IXY>() + ofst) & 0xFFFF;
2997  T::setMemPtr(addr);
2998  AND(RDMEM(addr, T::CC_DD + T::CC_CP_XIX_2));
2999  return {2, T::CC_DD + T::CC_CP_XIX};
3000 }
3001 
3002 // CP r
3003 template<class T> inline void CPUCore<T>::CP(byte reg) {
3004  unsigned q = getA() - reg;
3005  byte f = table.ZS[q & 0xFF] |
3006  ((q & 0x100) ? C_FLAG : 0) |
3007  N_FLAG |
3008  ((getA() ^ q ^ reg) & H_FLAG) |
3009  (((reg ^ getA()) & (getA() ^ q) & 0x80) >> 5); // V_FLAG
3010  if (T::isR800()) {
3011  f |= getF() & (X_FLAG | Y_FLAG);
3012  } else {
3013  f |= reg & (X_FLAG | Y_FLAG); // XY from operand, not from result
3014  }
3015  setF(f);
3016 }
3017 template<class T> II CPUCore<T>::cp_a() {
3018  byte f = ZS0 | N_FLAG;
3019  if (T::isR800()) {
3020  f |= getF() & (X_FLAG | Y_FLAG);
3021  } else {
3022  f |= getA() & (X_FLAG | Y_FLAG); // XY from operand, not from result
3023  }
3024  setF(f);
3025  return {1, T::CC_CP_R};
3026 }
3027 template<class T> template<Reg8 SRC, int EE> II CPUCore<T>::cp_R() {
3028  CP(get8<SRC>()); return {1, T::CC_CP_R + EE};
3029 }
3030 template<class T> II CPUCore<T>::cp_byte() {
3031  CP(RDMEM_OPCODE<1>(T::CC_CP_N_1)); return {2, T::CC_CP_N};
3032 }
3033 template<class T> II CPUCore<T>::cp_xhl() {
3034  CP(RDMEM(getHL(), T::CC_CP_XHL_1)); return {1, T::CC_CP_XHL};
3035 }
3036 template<class T> template<Reg16 IXY> II CPUCore<T>::cp_xix() {
3037  int8_t ofst = RDMEM_OPCODE<1>(T::CC_DD + T::CC_CP_XIX_1);
3038  unsigned addr = (get16<IXY>() + ofst) & 0xFFFF;
3039  T::setMemPtr(addr);
3040  CP(RDMEM(addr, T::CC_DD + T::CC_CP_XIX_2));
3041  return {2, T::CC_DD + T::CC_CP_XIX};
3042 }
3043 
3044 // OR r
3045 template<class T> inline void CPUCore<T>::OR(byte reg) {
3046  setA(getA() | reg);
3047  byte f = 0;
3048  if (T::isR800()) {
3049  f |= table.ZSP[getA()];
3050  f |= getF() & (X_FLAG | Y_FLAG);
3051  } else {
3052  f |= table.ZSPXY[getA()];
3053  }
3054  setF(f);
3055 }
3056 template<class T> II CPUCore<T>::or_a() {
3057  byte f = 0;
3058  if (T::isR800()) {
3059  f |= table.ZSP[getA()];
3060  f |= getF() & (X_FLAG | Y_FLAG);
3061  } else {
3062  f |= table.ZSPXY[getA()];
3063  }
3064  setF(f);
3065  return {1, T::CC_CP_R};
3066 }
3067 template<class T> template<Reg8 SRC, int EE> II CPUCore<T>::or_R() {
3068  OR(get8<SRC>()); return {1, T::CC_CP_R + EE};
3069 }
3070 template<class T> II CPUCore<T>::or_byte() {
3071  OR(RDMEM_OPCODE<1>(T::CC_CP_N_1)); return {2, T::CC_CP_N};
3072 }
3073 template<class T> II CPUCore<T>::or_xhl() {
3074  OR(RDMEM(getHL(), T::CC_CP_XHL_1)); return {1, T::CC_CP_XHL};
3075 }
3076 template<class T> template<Reg16 IXY> II CPUCore<T>::or_xix() {
3077  int8_t ofst = RDMEM_OPCODE<1>(T::CC_DD + T::CC_CP_XIX_1);
3078  unsigned addr = (get16<IXY>() + ofst) & 0xFFFF;
3079  T::setMemPtr(addr);
3080  OR(RDMEM(addr, T::CC_DD + T::CC_CP_XIX_2));
3081  return {2, T::CC_DD + T::CC_CP_XIX};
3082 }
3083 
3084 // SBC A,r
3085 template<class T> inline void CPUCore<T>::SBC(byte reg) {
3086  unsigned res = getA() - reg - ((getF() & C_FLAG) ? 1 : 0);
3087  byte f = ((res & 0x100) ? C_FLAG : 0) |
3088  N_FLAG |
3089  ((getA() ^ res ^ reg) & H_FLAG) |
3090  (((reg ^ getA()) & (getA() ^ res) & 0x80) >> 5); // V_FLAG
3091  if (T::isR800()) {
3092  f |= table.ZS[res & 0xFF];
3093  f |= getF() & (X_FLAG | Y_FLAG);
3094  } else {
3095  f |= table.ZSXY[res & 0xFF];
3096  }
3097  setF(f);
3098  setA(res);
3099 }
3100 template<class T> II CPUCore<T>::sbc_a_a() {
3101  if (T::isR800()) {
3102  word t = (getF() & C_FLAG)
3103  ? (255 * 256 | ZS255 | C_FLAG | H_FLAG | N_FLAG)
3104  : ( 0 * 256 | ZS0 | N_FLAG);
3105  setAF(t | (getF() & (X_FLAG | Y_FLAG)));
3106  } else {
3107  setAF((getF() & C_FLAG) ?
3108  (255 * 256 | ZSXY255 | C_FLAG | H_FLAG | N_FLAG) :
3109  ( 0 * 256 | ZSXY0 | N_FLAG));
3110  }
3111  return {1, T::CC_CP_R};
3112 }
3113 template<class T> template<Reg8 SRC, int EE> II CPUCore<T>::sbc_a_R() {
3114  SBC(get8<SRC>()); return {1, T::CC_CP_R + EE};
3115 }
3116 template<class T> II CPUCore<T>::sbc_a_byte() {
3117  SBC(RDMEM_OPCODE<1>(T::CC_CP_N_1)); return {2, T::CC_CP_N};
3118 }
3119 template<class T> II CPUCore<T>::sbc_a_xhl() {
3120  SBC(RDMEM(getHL(), T::CC_CP_XHL_1)); return {1, T::CC_CP_XHL};
3121 }
3122 template<class T> template<Reg16 IXY> II CPUCore<T>::sbc_a_xix() {
3123  int8_t ofst = RDMEM_OPCODE<1>(T::CC_DD + T::CC_CP_XIX_1);
3124  unsigned addr = (get16<IXY>() + ofst) & 0xFFFF;
3125  T::setMemPtr(addr);
3126  SBC(RDMEM(addr, T::CC_DD + T::CC_CP_XIX_2));
3127  return {2, T::CC_DD + T::CC_CP_XIX};
3128 }
3129 
3130 // SUB r
3131 template<class T> inline void CPUCore<T>::SUB(byte reg) {
3132  unsigned res = getA() - reg;
3133  byte f = ((res & 0x100) ? C_FLAG : 0) |
3134  N_FLAG |
3135  ((getA() ^ res ^ reg) & H_FLAG) |
3136  (((reg ^ getA()) & (getA() ^ res) & 0x80) >> 5); // V_FLAG
3137  if (T::isR800()) {
3138  f |= table.ZS[res & 0xFF];
3139  f |= getF() & (X_FLAG | Y_FLAG);
3140  } else {
3141  f |= table.ZSXY[res & 0xFF];
3142  }
3143  setF(f);
3144  setA(res);
3145 }
3146 template<class T> II CPUCore<T>::sub_a() {
3147  if (T::isR800()) {
3148  word t = 0 * 256 | ZS0 | N_FLAG;
3149  setAF(t | (getF() & (X_FLAG | Y_FLAG)));
3150  } else {
3151  setAF(0 * 256 | ZSXY0 | N_FLAG);
3152  }
3153  return {1, T::CC_CP_R};
3154 }
3155 template<class T> template<Reg8 SRC, int EE> II CPUCore<T>::sub_R() {
3156  SUB(get8<SRC>()); return {1, T::CC_CP_R + EE};
3157 }
3158 template<class T> II CPUCore<T>::sub_byte() {
3159  SUB(RDMEM_OPCODE<1>(T::CC_CP_N_1)); return {2, T::CC_CP_N};
3160 }
3161 template<class T> II CPUCore<T>::sub_xhl() {
3162  SUB(RDMEM(getHL(), T::CC_CP_XHL_1)); return {1, T::CC_CP_XHL};
3163 }
3164 template<class T> template<Reg16 IXY> II CPUCore<T>::sub_xix() {
3165  int8_t ofst = RDMEM_OPCODE<1>(T::CC_DD + T::CC_CP_XIX_1);
3166  unsigned addr = (get16<IXY>() + ofst) & 0xFFFF;
3167  T::setMemPtr(addr);
3168  SUB(RDMEM(addr, T::CC_DD + T::CC_CP_XIX_2));
3169  return {2, T::CC_DD + T::CC_CP_XIX};
3170 }
3171 
3172 // XOR r
3173 template<class T> inline void CPUCore<T>::XOR(byte reg) {
3174  setA(getA() ^ reg);
3175  byte f = 0;
3176  if (T::isR800()) {
3177  f |= table.ZSP[getA()];
3178  f |= getF() & (X_FLAG | Y_FLAG);
3179  } else {
3180  f |= table.ZSPXY[getA()];
3181  }
3182  setF(f);
3183 }
3184 template<class T> II CPUCore<T>::xor_a() {
3185  if (T::isR800()) {
3186  word t = 0 * 256 + ZSP0;
3187  setAF(t | (getF() & (X_FLAG | Y_FLAG)));
3188  } else {
3189  setAF(0 * 256 + ZSPXY0);
3190  }
3191  return {1, T::CC_CP_R};
3192 }
3193 template<class T> template<Reg8 SRC, int EE> II CPUCore<T>::xor_R() {
3194  XOR(get8<SRC>()); return {1, T::CC_CP_R + EE};
3195 }
3196 template<class T> II CPUCore<T>::xor_byte() {
3197  XOR(RDMEM_OPCODE<1>(T::CC_CP_N_1)); return {2, T::CC_CP_N};
3198 }
3199 template<class T> II CPUCore<T>::xor_xhl() {
3200  XOR(RDMEM(getHL(), T::CC_CP_XHL_1)); return {1, T::CC_CP_XHL};
3201 }
3202 template<class T> template<Reg16 IXY> II CPUCore<T>::xor_xix() {
3203  int8_t ofst = RDMEM_OPCODE<1>(T::CC_DD + T::CC_CP_XIX_1);
3204  unsigned addr = (get16<IXY>() + ofst) & 0xFFFF;
3205  T::setMemPtr(addr);
3206  XOR(RDMEM(addr, T::CC_DD + T::CC_CP_XIX_2));
3207  return {2, T::CC_DD + T::CC_CP_XIX};
3208 }
3209 
3210 
3211 // DEC r
3212 template<class T> inline byte CPUCore<T>::DEC(byte reg) {
3213  byte res = reg - 1;
3214  byte f = ((reg & ~res & 0x80) >> 5) | // V_FLAG
3215  (((res & 0x0F) + 1) & H_FLAG) |
3216  N_FLAG;
3217  if (T::isR800()) {
3218  f |= getF() & (C_FLAG | X_FLAG | Y_FLAG);
3219  f |= table.ZS[res];
3220  } else {
3221  f |= getF() & C_FLAG;
3222  f |= table.ZSXY[res];
3223  }
3224  setF(f);
3225  return res;
3226 }
3227 template<class T> template<Reg8 REG, int EE> II CPUCore<T>::dec_R() {
3228  set8<REG>(DEC(get8<REG>())); return {1, T::CC_INC_R + EE};
3229 }
3230 template<class T> template<int EE> inline void CPUCore<T>::DEC_X(unsigned x) {
3231  byte val = DEC(RDMEM(x, T::CC_INC_XHL_1 + EE));
3232  WRMEM(x, val, T::CC_INC_XHL_2 + EE);
3233 }
3234 template<class T> II CPUCore<T>::dec_xhl() {
3235  DEC_X<0>(getHL());
3236  return {1, T::CC_INC_XHL};
3237 }
3238 template<class T> template<Reg16 IXY> II CPUCore<T>::dec_xix() {
3239  int8_t ofst = RDMEM_OPCODE<1>(T::CC_DD + T::CC_INC_XIX_1);
3240  unsigned addr = (get16<IXY>() + ofst) & 0xFFFF;
3241  T::setMemPtr(addr);
3242  DEC_X<T::CC_DD + T::EE_INC_XIX>(addr);
3243  return {2, T::CC_INC_XHL + T::CC_DD + T::EE_INC_XIX};
3244 }
3245 
3246 // INC r
3247 template<class T> inline byte CPUCore<T>::INC(byte reg) {
3248  reg++;
3249  byte f = ((reg & -reg & 0x80) >> 5) | // V_FLAG
3250  (((reg & 0x0F) - 1) & H_FLAG) |
3251  0; // N_FLAG
3252  if (T::isR800()) {
3253  f |= getF() & (C_FLAG | X_FLAG | Y_FLAG);
3254  f |= table.ZS[reg];
3255  } else {
3256  f |= getF() & C_FLAG;
3257  f |= table.ZSXY[reg];
3258  }
3259  setF(f);
3260  return reg;
3261 }
3262 template<class T> template<Reg8 REG, int EE> II CPUCore<T>::inc_R() {
3263  set8<REG>(INC(get8<REG>())); return {1, T::CC_INC_R + EE};
3264 }
3265 template<class T> template<int EE> inline void CPUCore<T>::INC_X(unsigned x) {
3266  byte val = INC(RDMEM(x, T::CC_INC_XHL_1 + EE));
3267  WRMEM(x, val, T::CC_INC_XHL_2 + EE);
3268 }
3269 template<class T> II CPUCore<T>::inc_xhl() {
3270  INC_X<0>(getHL());
3271  return {1, T::CC_INC_XHL};
3272 }
3273 template<class T> template<Reg16 IXY> II CPUCore<T>::inc_xix() {
3274  int8_t ofst = RDMEM_OPCODE<1>(T::CC_DD + T::CC_INC_XIX_1);
3275  unsigned addr = (get16<IXY>() + ofst) & 0xFFFF;
3276  T::setMemPtr(addr);
3277  INC_X<T::CC_DD + T::EE_INC_XIX>(addr);
3278  return {2, T::CC_INC_XHL + T::CC_DD + T::EE_INC_XIX};
3279 }
3280 
3281 
3282 // ADC HL,ss
3283 template<class T> template<Reg16 REG> inline II CPUCore<T>::adc_hl_SS() {
3284  unsigned reg = get16<REG>();
3285  T::setMemPtr(getHL() + 1);
3286  unsigned res = getHL() + reg + ((getF() & C_FLAG) ? 1 : 0);
3287  byte f = (res >> 16) | // C_FLAG
3288  0; // N_FLAG
3289  if (T::isR800()) {
3290  f |= getF() & (X_FLAG | Y_FLAG);
3291  }
3292  if (res & 0xFFFF) {
3293  f |= ((getHL() ^ res ^ reg) >> 8) & H_FLAG;
3294  f |= 0; // Z_FLAG
3295  f |= ((getHL() ^ res) & (reg ^ res) & 0x8000) >> 13; // V_FLAG
3296  if (T::isR800()) {
3297  f |= (res >> 8) & S_FLAG;
3298  } else {
3299  f |= (res >> 8) & (S_FLAG | X_FLAG | Y_FLAG);
3300  }
3301  } else {
3302  f |= ((getHL() ^ reg) >> 8) & H_FLAG;
3303  f |= Z_FLAG;
3304  f |= (getHL() & reg & 0x8000) >> 13; // V_FLAG
3305  f |= 0; // S_FLAG (X_FLAG Y_FLAG)
3306  }
3307  setF(f);
3308  setHL(res);
3309  return {1, T::CC_ADC_HL_SS};
3310 }
3311 template<class T> II CPUCore<T>::adc_hl_hl() {
3312  T::setMemPtr(getHL() + 1);
3313  unsigned res = 2 * getHL() + ((getF() & C_FLAG) ? 1 : 0);
3314  byte f = (res >> 16) | // C_FLAG
3315  0; // N_FLAG
3316  if (T::isR800()) {
3317  f |= getF() & (X_FLAG | Y_FLAG);
3318  }
3319  if (res & 0xFFFF) {
3320  f |= 0; // Z_FLAG
3321  f |= ((getHL() ^ res) & 0x8000) >> 13; // V_FLAG
3322  if (T::isR800()) {
3323  f |= (res >> 8) & (H_FLAG | S_FLAG);
3324  } else {
3325  f |= (res >> 8) & (H_FLAG | S_FLAG | X_FLAG | Y_FLAG);
3326  }
3327  } else {
3328  f |= Z_FLAG;
3329  f |= (getHL() & 0x8000) >> 13; // V_FLAG
3330  f |= 0; // H_FLAG S_FLAG (X_FLAG Y_FLAG)
3331  }
3332  setF(f);
3333  setHL(res);
3334  return {1, T::CC_ADC_HL_SS};
3335 }
3336 
3337 // ADD HL/IX/IY,ss
3338 template<class T> template<Reg16 REG1, Reg16 REG2, int EE> II CPUCore<T>::add_SS_TT() {
3339  unsigned reg1 = get16<REG1>();
3340  unsigned reg2 = get16<REG2>();
3341  T::setMemPtr(reg1 + 1);
3342  unsigned res = reg1 + reg2;
3343  byte f = (((reg1 ^ res ^ reg2) >> 8) & H_FLAG) |
3344  (res >> 16) | // C_FLAG
3345  0; // N_FLAG
3346  if (T::isR800()) {
3347  f |= getF() & (S_FLAG | Z_FLAG | V_FLAG | X_FLAG | Y_FLAG);
3348  } else {
3349  f |= getF() & (S_FLAG | Z_FLAG | V_FLAG);
3350  f |= (res >> 8) & (X_FLAG | Y_FLAG);
3351  }
3352  setF(f);
3353  set16<REG1>(res & 0xFFFF);
3354  return {1, T::CC_ADD_HL_SS + EE};
3355 }
3356 template<class T> template<Reg16 REG, int EE> II CPUCore<T>::add_SS_SS() {
3357  unsigned reg = get16<REG>();
3358  T::setMemPtr(reg + 1);
3359  unsigned res = 2 * reg;
3360  byte f = (res >> 16) | // C_FLAG
3361  0; // N_FLAG
3362  if (T::isR800()) {
3363  f |= getF() & (S_FLAG | Z_FLAG | V_FLAG | X_FLAG | Y_FLAG);
3364  f |= (res >> 8) & H_FLAG;
3365  } else {
3366  f |= getF() & (S_FLAG | Z_FLAG | V_FLAG);
3367  f |= (res >> 8) & (H_FLAG | X_FLAG | Y_FLAG);
3368  }
3369  setF(f);
3370  set16<REG>(res & 0xFFFF);
3371  return {1, T::CC_ADD_HL_SS + EE};
3372 }
3373 
3374 // SBC HL,ss
3375 template<class T> template<Reg16 REG> inline II CPUCore<T>::sbc_hl_SS() {
3376  unsigned reg = get16<REG>();
3377  T::setMemPtr(getHL() + 1);
3378  unsigned res = getHL() - reg - ((getF() & C_FLAG) ? 1 : 0);
3379  byte f = ((res & 0x10000) ? C_FLAG : 0) |
3380  N_FLAG;
3381  if (T::isR800()) {
3382  f |= getF() & (X_FLAG | Y_FLAG);
3383  }
3384  if (res & 0xFFFF) {
3385  f |= ((getHL() ^ res ^ reg) >> 8) & H_FLAG;
3386  f |= 0; // Z_FLAG
3387  f |= ((reg ^ getHL()) & (getHL() ^ res) & 0x8000) >> 13; // V_FLAG
3388  if (T::isR800()) {
3389  f |= (res >> 8) & S_FLAG;
3390  } else {
3391  f |= (res >> 8) & (S_FLAG | X_FLAG | Y_FLAG);
3392  }
3393  } else {
3394  f |= ((getHL() ^ reg) >> 8) & H_FLAG;
3395  f |= Z_FLAG;
3396  f |= ((reg ^ getHL()) & getHL() & 0x8000) >> 13; // V_FLAG
3397  f |= 0; // S_FLAG (X_FLAG Y_FLAG)
3398  }
3399  setF(f);
3400  setHL(res);
3401  return {1, T::CC_ADC_HL_SS};
3402 }
3403 template<class T> II CPUCore<T>::sbc_hl_hl() {
3404  T::setMemPtr(getHL() + 1);
3405  byte f = T::isR800() ? (getF() & (X_FLAG | Y_FLAG)) : 0;
3406  if (getF() & C_FLAG) {
3407  f |= C_FLAG | H_FLAG | S_FLAG | N_FLAG;
3408  if (!T::isR800()) {
3409  f |= X_FLAG | Y_FLAG;
3410  }
3411  setHL(0xFFFF);
3412  } else {
3413  f |= Z_FLAG | N_FLAG;
3414  setHL(0);
3415  }
3416  setF(f);
3417  return {1, T::CC_ADC_HL_SS};
3418 }
3419 
3420 // DEC ss
3421 template<class T> template<Reg16 REG, int EE> II CPUCore<T>::dec_SS() {
3422  set16<REG>(get16<REG>() - 1); return {1, T::CC_INC_SS + EE};
3423 }
3424 
3425 // INC ss
3426 template<class T> template<Reg16 REG, int EE> II CPUCore<T>::inc_SS() {
3427  set16<REG>(get16<REG>() + 1); return {1, T::CC_INC_SS + EE};
3428 }
3429 
3430 
3431 // BIT n,r
3432 template<class T> template<unsigned N, Reg8 REG> II CPUCore<T>::bit_N_R() {
3433  byte reg = get8<REG>();
3434  byte f = 0; // N_FLAG
3435  if (T::isR800()) {
3436  // this is very different from Z80 (not only XY flags)
3437  f |= getF() & (S_FLAG | V_FLAG | C_FLAG | X_FLAG | Y_FLAG);
3438  f |= H_FLAG;
3439  f |= (reg & (1 << N)) ? 0 : Z_FLAG;
3440  } else {
3441  f |= table.ZSPH[reg & (1 << N)];
3442  f |= getF() & C_FLAG;
3443  f |= reg & (X_FLAG | Y_FLAG);
3444  }
3445  setF(f);
3446  return {1, T::CC_BIT_R};
3447 }
3448 template<class T> template<unsigned N> inline II CPUCore<T>::bit_N_xhl() {
3449  byte m = RDMEM(getHL(), T::CC_BIT_XHL_1) & (1 << N);
3450  byte f = 0; // N_FLAG
3451  if (T::isR800()) {
3452  f |= getF() & (S_FLAG | V_FLAG | C_FLAG | X_FLAG | Y_FLAG);
3453  f |= H_FLAG;
3454  f |= m ? 0 : Z_FLAG;
3455  } else {
3456  f |= table.ZSPH[m];
3457  f |= getF() & C_FLAG;
3458  f |= (T::getMemPtr() >> 8) & (X_FLAG | Y_FLAG);
3459  }
3460  setF(f);
3461  return {1, T::CC_BIT_XHL};
3462 }
3463 template<class T> template<unsigned N> inline II CPUCore<T>::bit_N_xix(unsigned addr) {
3464  T::setMemPtr(addr);
3465  byte m = RDMEM(addr, T::CC_DD + T::CC_BIT_XIX_1) & (1 << N);
3466  byte f = 0; // N_FLAG
3467  if (T::isR800()) {
3468  f |= getF() & (S_FLAG | V_FLAG | C_FLAG | X_FLAG | Y_FLAG);
3469  f |= H_FLAG;
3470  f |= m ? 0 : Z_FLAG;
3471  } else {
3472  f |= table.ZSPH[m];
3473  f |= getF() & C_FLAG;
3474  f |= (addr >> 8) & (X_FLAG | Y_FLAG);
3475  }
3476  setF(f);
3477  return {3, T::CC_DD + T::CC_BIT_XIX};
3478 }
3479 
3480 // RES n,r
3481 static inline byte RES(unsigned b, byte reg) {
3482  return reg & ~(1 << b);
3483 }
3484 template<class T> template<unsigned N, Reg8 REG> II CPUCore<T>::res_N_R() {
3485  set8<REG>(RES(N, get8<REG>())); return {1, T::CC_SET_R};
3486 }
3487 template<class T> template<int EE> inline byte CPUCore<T>::RES_X(unsigned bit, unsigned addr) {
3488  byte res = RES(bit, RDMEM(addr, T::CC_SET_XHL_1 + EE));
3489  WRMEM(addr, res, T::CC_SET_XHL_2 + EE);
3490  return res;
3491 }
3492 template<class T> template<unsigned N> II CPUCore<T>::res_N_xhl() {
3493  RES_X<0>(N, getHL()); return {1, T::CC_SET_XHL};
3494 }
3495 template<class T> template<unsigned N, Reg8 REG> II CPUCore<T>::res_N_xix_R(unsigned a) {
3496  T::setMemPtr(a);
3497  set8<REG>(RES_X<T::CC_DD + T::EE_SET_XIX>(N, a));
3498  return {3, T::CC_DD + T::CC_SET_XIX};
3499 }
3500 
3501 // SET n,r
3502 static inline byte SET(unsigned b, byte reg) {
3503  return reg | (1 << b);
3504 }
3505 template<class T> template<unsigned N, Reg8 REG> II CPUCore<T>::set_N_R() {
3506  set8<REG>(SET(N, get8<REG>())); return {1, T::CC_SET_R};
3507 }
3508 template<class T> template<int EE> inline byte CPUCore<T>::SET_X(unsigned bit, unsigned addr) {
3509  byte res = SET(bit, RDMEM(addr, T::CC_SET_XHL_1 + EE));
3510  WRMEM(addr, res, T::CC_SET_XHL_2 + EE);
3511  return res;
3512 }
3513 template<class T> template<unsigned N> II CPUCore<T>::set_N_xhl() {
3514  SET_X<0>(N, getHL()); return {1, T::CC_SET_XHL};
3515 }
3516 template<class T> template<unsigned N, Reg8 REG> II CPUCore<T>::set_N_xix_R(unsigned a) {
3517  T::setMemPtr(a);
3518  set8<REG>(SET_X<T::CC_DD + T::EE_SET_XIX>(N, a));
3519  return {3, T::CC_DD + T::CC_SET_XIX};
3520 }
3521 
3522 // RL r
3523 template<class T> inline byte CPUCore<T>::RL(byte reg) {
3524  byte c = reg >> 7;
3525  reg = (reg << 1) | ((getF() & C_FLAG) ? 0x01 : 0);
3526  byte f = c ? C_FLAG : 0;
3527  if (T::isR800()) {
3528  f |= table.ZSP[reg];
3529  f |= getF() & (X_FLAG | Y_FLAG);
3530  } else {
3531  f |= table.ZSPXY[reg];
3532  }
3533  setF(f);
3534  return reg;
3535 }
3536 template<class T> template<int EE> inline byte CPUCore<T>::RL_X(unsigned x) {
3537  byte res = RL(RDMEM(x, T::CC_SET_XHL_1 + EE));
3538  WRMEM(x, res, T::CC_SET_XHL_2 + EE);
3539  return res;
3540 }
3541 template<class T> template<Reg8 REG> II CPUCore<T>::rl_R() {
3542  set8<REG>(RL(get8<REG>())); return {1, T::CC_SET_R};
3543 }
3544 template<class T> II CPUCore<T>::rl_xhl() {
3545  RL_X<0>(getHL()); return {1, T::CC_SET_XHL};
3546 }
3547 template<class T> template<Reg8 REG> II CPUCore<T>::rl_xix_R(unsigned a) {
3548  T::setMemPtr(a);
3549  set8<REG>(RL_X<T::CC_DD + T::EE_SET_XIX>(a));
3550  return {3, T::CC_DD + T::CC_SET_XIX};
3551 }
3552 
3553 // RLC r
3554 template<class T> inline byte CPUCore<T>::RLC(byte reg) {
3555  byte c = reg >> 7;
3556  reg = (reg << 1) | c;
3557  byte f = c ? C_FLAG : 0;
3558  if (T::isR800()) {
3559  f |= table.ZSP[reg];
3560  f |= getF() & (X_FLAG | Y_FLAG);
3561  } else {
3562  f |= table.ZSPXY[reg];
3563  }
3564  setF(f);
3565  return reg;
3566 }
3567 template<class T> template<int EE> inline byte CPUCore<T>::RLC_X(unsigned x) {
3568  byte res = RLC(RDMEM(x, T::CC_SET_XHL_1 + EE));
3569  WRMEM(x, res, T::CC_SET_XHL_2 + EE);
3570  return res;
3571 }
3572 template<class T> template<Reg8 REG> II CPUCore<T>::rlc_R() {
3573  set8<REG>(RLC(get8<REG>())); return {1, T::CC_SET_R};
3574 }
3575 template<class T> II CPUCore<T>::rlc_xhl() {
3576  RLC_X<0>(getHL()); return {1, T::CC_SET_XHL};
3577 }
3578 template<class T> template<Reg8 REG> II CPUCore<T>::rlc_xix_R(unsigned a) {
3579  T::setMemPtr(a);
3580  set8<REG>(RLC_X<T::CC_DD + T::EE_SET_XIX>(a));
3581  return {3, T::CC_DD + T::CC_SET_XIX};
3582 }
3583 
3584 // RR r
3585 template<class T> inline byte CPUCore<T>::RR(byte reg) {
3586  byte c = reg & 1;
3587  reg = (reg >> 1) | ((getF() & C_FLAG) << 7);
3588  byte f = c ? C_FLAG : 0;
3589  if (T::isR800()) {
3590  f |= table.ZSP[reg];
3591  f |= getF() & (X_FLAG | Y_FLAG);
3592  } else {
3593  f |= table.ZSPXY[reg];
3594  }
3595  setF(f);
3596  return reg;
3597 }
3598 template<class T> template<int EE> inline byte CPUCore<T>::RR_X(unsigned x) {
3599  byte res = RR(RDMEM(x, T::CC_SET_XHL_1 + EE));
3600  WRMEM(x, res, T::CC_SET_XHL_2 + EE);
3601  return res;
3602 }
3603 template<class T> template<Reg8 REG> II CPUCore<T>::rr_R() {
3604  set8<REG>(RR(get8<REG>())); return {1, T::CC_SET_R};
3605 }
3606 template<class T> II CPUCore<T>::rr_xhl() {
3607  RR_X<0>(getHL()); return {1, T::CC_SET_XHL};
3608 }
3609 template<class T> template<Reg8 REG> II CPUCore<T>::rr_xix_R(unsigned a) {
3610  T::setMemPtr(a);
3611  set8<REG>(RR_X<T::CC_DD + T::EE_SET_XIX>(a));
3612  return {3, T::CC_DD + T::CC_SET_XIX};
3613 }
3614 
3615 // RRC r
3616 template<class T> inline byte CPUCore<T>::RRC(byte reg) {
3617  byte c = reg & 1;
3618  reg = (reg >> 1) | (c << 7);
3619  byte f = c ? C_FLAG : 0;
3620  if (T::isR800()) {
3621  f |= table.ZSP[reg];
3622  f |= getF() & (X_FLAG | Y_FLAG);
3623  } else {
3624  f |= table.ZSPXY[reg];
3625  }
3626  setF(f);
3627  return reg;
3628 }
3629 template<class T> template<int EE> inline byte CPUCore<T>::RRC_X(unsigned x) {
3630  byte res = RRC(RDMEM(x, T::CC_SET_XHL_1 + EE));
3631  WRMEM(x, res, T::CC_SET_XHL_2 + EE);
3632  return res;
3633 }
3634 template<class T> template<Reg8 REG> II CPUCore<T>::rrc_R() {
3635  set8<REG>(RRC(get8<REG>())); return {1, T::CC_SET_R};
3636 }
3637 template<class T> II CPUCore<T>::rrc_xhl() {
3638  RRC_X<0>(getHL()); return {1, T::CC_SET_XHL};
3639 }
3640 template<class T> template<Reg8 REG> II CPUCore<T>::rrc_xix_R(unsigned a) {
3641  T::setMemPtr(a);
3642  set8<REG>(RRC_X<T::CC_DD + T::EE_SET_XIX>(a));
3643  return {3, T::CC_DD + T::CC_SET_XIX};
3644 }
3645 
3646 // SLA r
3647 template<class T> inline byte CPUCore<T>::SLA(byte reg) {
3648  byte c = reg >> 7;
3649  reg <<= 1;
3650  byte f = c ? C_FLAG : 0;
3651  if (T::isR800()) {
3652  f |= table.ZSP[reg];
3653  f |= getF() & (X_FLAG | Y_FLAG);
3654  } else {
3655  f |= table.ZSPXY[reg];
3656  }
3657  setF(f);
3658  return reg;
3659 }
3660 template<class T> template<int EE> inline byte CPUCore<T>::SLA_X(unsigned x) {
3661  byte res = SLA(RDMEM(x, T::CC_SET_XHL_1 + EE));
3662  WRMEM(x, res, T::CC_SET_XHL_2 + EE);
3663  return res;
3664 }
3665 template<class T> template<Reg8 REG> II CPUCore<T>::sla_R() {
3666  set8<REG>(SLA(get8<REG>())); return {1, T::CC_SET_R};
3667 }
3668 template<class T> II CPUCore<T>::sla_xhl() {
3669  SLA_X<0>(getHL()); return {1, T::CC_SET_XHL};
3670 }
3671 template<class T> template<Reg8 REG> II CPUCore<T>::sla_xix_R(unsigned a) {
3672  T::setMemPtr(a);
3673  set8<REG>(SLA_X<T::CC_DD + T::EE_SET_XIX>(a));
3674  return {3, T::CC_DD + T::CC_SET_XIX};
3675 }
3676 
3677 // SLL r
3678 template<class T> inline byte CPUCore<T>::SLL(byte reg) {
3679  assert(!T::isR800()); // this instruction is Z80-only
3680  byte c = reg >> 7;
3681  reg = (reg << 1) | 1;
3682  byte f = c ? C_FLAG : 0;
3683  f |= table.ZSPXY[reg];
3684  setF(f);
3685  return reg;
3686 }
3687 template<class T> template<int EE> inline byte CPUCore<T>::SLL_X(unsigned x) {
3688  byte res = SLL(RDMEM(x, T::CC_SET_XHL_1 + EE));
3689  WRMEM(x, res, T::CC_SET_XHL_2 + EE);
3690  return res;
3691 }
3692 template<class T> template<Reg8 REG> II CPUCore<T>::sll_R() {
3693  set8<REG>(SLL(get8<REG>())); return {1, T::CC_SET_R};
3694 }
3695 template<class T> II CPUCore<T>::sll_xhl() {
3696  SLL_X<0>(getHL()); return {1, T::CC_SET_XHL};
3697 }
3698 template<class T> template<Reg8 REG> II CPUCore<T>::sll_xix_R(unsigned a) {
3699  T::setMemPtr(a);
3700  set8<REG>(SLL_X<T::CC_DD + T::EE_SET_XIX>(a));
3701  return {3, T::CC_DD + T::CC_SET_XIX};
3702 }
3703 template<class T> II CPUCore<T>::sll2() {
3704  assert(T::isR800()); // this instruction is R800-only
3705  byte f = (getF() & (X_FLAG | Y_FLAG)) |
3706  (getA() >> 7) | // C_FLAG
3707  0; // all other flags zero
3708  setF(f);
3709  return {3, T::CC_DD + T::CC_SET_XIX}; // TODO
3710 }
3711 
3712 // SRA r
3713 template<class T> inline byte CPUCore<T>::SRA(byte reg) {
3714  byte c = reg & 1;
3715  reg = (reg >> 1) | (reg & 0x80);
3716  byte f = c ? C_FLAG : 0;
3717  if (T::isR800()) {
3718  f |= table.ZSP[reg];
3719  f |= getF() & (X_FLAG | Y_FLAG);
3720  } else {
3721  f |= table.ZSPXY[reg];
3722  }
3723  setF(f);
3724  return reg;
3725 }
3726 template<class T> template<int EE> inline byte CPUCore<T>::SRA_X(unsigned x) {
3727  byte res = SRA(RDMEM(x, T::CC_SET_XHL_1 + EE));
3728  WRMEM(x, res, T::CC_SET_XHL_2 + EE);
3729  return res;
3730 }
3731 template<class T> template<Reg8 REG> II CPUCore<T>::sra_R() {
3732  set8<REG>(SRA(get8<REG>())); return {1, T::CC_SET_R};
3733 }
3734 template<class T> II CPUCore<T>::sra_xhl() {
3735  SRA_X<0>(getHL()); return {1, T::CC_SET_XHL};
3736 }
3737 template<class T> template<Reg8 REG> II CPUCore<T>::sra_xix_R(unsigned a) {
3738  T::setMemPtr(a);
3739  set8<REG>(SRA_X<T::CC_DD + T::EE_SET_XIX>(a));
3740  return {3, T::CC_DD + T::CC_SET_XIX};
3741 }
3742 
3743 // SRL R
3744 template<class T> inline byte CPUCore<T>::SRL(byte reg) {
3745  byte c = reg & 1;
3746  reg >>= 1;
3747  byte f = c ? C_FLAG : 0;
3748  if (T::isR800()) {
3749  f |= table.ZSP[reg];
3750  f |= getF() & (X_FLAG | Y_FLAG);
3751  } else {
3752  f |= table.ZSPXY[reg];
3753  }
3754  setF(f);
3755  return reg;
3756 }
3757 template<class T> template<int EE> inline byte CPUCore<T>::SRL_X(unsigned x) {
3758  byte res = SRL(RDMEM(x, T::CC_SET_XHL_1 + EE));
3759  WRMEM(x, res, T::CC_SET_XHL_2 + EE);
3760  return res;
3761 }
3762 template<class T> template<Reg8 REG> II CPUCore<T>::srl_R() {
3763  set8<REG>(SRL(get8<REG>())); return {1, T::CC_SET_R};
3764 }
3765 template<class T> II CPUCore<T>::srl_xhl() {
3766  SRL_X<0>(getHL()); return {1, T::CC_SET_XHL};
3767 }
3768 template<class T> template<Reg8 REG> II CPUCore<T>::srl_xix_R(unsigned a) {
3769  T::setMemPtr(a);
3770  set8<REG>(SRL_X<T::CC_DD + T::EE_SET_XIX>(a));
3771  return {3, T::CC_DD + T::CC_SET_XIX};
3772 }
3773 
3774 // RLA RLCA RRA RRCA
3775 template<class T> II CPUCore<T>::rla() {
3776  byte c = getF() & C_FLAG;
3777  byte f = (getA() & 0x80) ? C_FLAG : 0;
3778  if (T::isR800()) {
3779  f |= getF() & (S_FLAG | Z_FLAG | P_FLAG | X_FLAG | Y_FLAG);
3780  } else {
3781  f |= getF() & (S_FLAG | Z_FLAG | P_FLAG);
3782  }
3783  setA((getA() << 1) | (c ? 1 : 0));
3784  if (!T::isR800()) {
3785  f |= getA() & (X_FLAG | Y_FLAG);
3786  }
3787  setF(f);
3788  return {1, T::CC_RLA};
3789 }
3790 template<class T> II CPUCore<T>::rlca() {
3791  setA((getA() << 1) | (getA() >> 7));
3792  byte f = 0;
3793  if (T::isR800()) {
3794  f |= getF() & (S_FLAG | Z_FLAG | P_FLAG | X_FLAG | Y_FLAG);
3795  f |= getA() & C_FLAG;
3796  } else {
3797  f |= getF() & (S_FLAG | Z_FLAG | P_FLAG);
3798  f |= getA() & (Y_FLAG | X_FLAG | C_FLAG);
3799  }
3800  setF(f);
3801  return {1, T::CC_RLA};
3802 }
3803 template<class T> II CPUCore<T>::rra() {
3804  byte c = (getF() & C_FLAG) << 7;
3805  byte f = (getA() & 0x01) ? C_FLAG : 0;
3806  if (T::isR800()) {
3807  f |= getF() & (S_FLAG | Z_FLAG | P_FLAG | X_FLAG | Y_FLAG);
3808  } else {
3809  f |= getF() & (S_FLAG | Z_FLAG | P_FLAG);
3810  }
3811  setA((getA() >> 1) | c);
3812  if (!T::isR800()) {
3813  f |= getA() & (X_FLAG | Y_FLAG);
3814  }
3815  setF(f);
3816  return {1, T::CC_RLA};
3817 }
3818 template<class T> II CPUCore<T>::rrca() {
3819  byte f = getA() & C_FLAG;
3820  if (T::isR800()) {
3821  f |= getF() & (S_FLAG | Z_FLAG | P_FLAG | X_FLAG | Y_FLAG);
3822  } else {
3823  f |= getF() & (S_FLAG | Z_FLAG | P_FLAG);
3824  }
3825  setA((getA() >> 1) | (getA() << 7));
3826  if (!T::isR800()) {
3827  f |= getA() & (X_FLAG | Y_FLAG);
3828  }
3829  setF(f);
3830  return {1, T::CC_RLA};
3831 }
3832 
3833 
3834 // RLD
3835 template<class T> II CPUCore<T>::rld() {
3836  byte val = RDMEM(getHL(), T::CC_RLD_1);
3837  T::setMemPtr(getHL() + 1);
3838  WRMEM(getHL(), (val << 4) | (getA() & 0x0F), T::CC_RLD_2);
3839  setA((getA() & 0xF0) | (val >> 4));
3840  byte f = 0;
3841  if (T::isR800()) {
3842  f |= getF() & (C_FLAG | X_FLAG | Y_FLAG);
3843  f |= table.ZSP[getA()];
3844  } else {
3845  f |= getF() & C_FLAG;
3846  f |= table.ZSPXY[getA()];
3847  }
3848  setF(f);
3849  return {1, T::CC_RLD};
3850 }
3851 
3852 // RRD
3853 template<class T> II CPUCore<T>::rrd() {
3854  byte val = RDMEM(getHL(), T::CC_RLD_1);
3855  T::setMemPtr(getHL() + 1);
3856  WRMEM(getHL(), (val >> 4) | (getA() << 4), T::CC_RLD_2);
3857  setA((getA() & 0xF0) | (val & 0x0F));
3858  byte f = 0;
3859  if (T::isR800()) {
3860  f |= getF() & (C_FLAG | X_FLAG | Y_FLAG);
3861  f |= table.ZSP[getA()];
3862  } else {
3863  f |= getF() & C_FLAG;
3864  f |= table.ZSPXY[getA()];
3865  }
3866  setF(f);
3867  return {1, T::CC_RLD};
3868 }
3869 
3870 
3871 // PUSH ss
3872 template<class T> template<int EE> inline void CPUCore<T>::PUSH(unsigned reg) {
3873  setSP(getSP() - 2);
3874  WR_WORD_rev<true, true>(getSP(), reg, T::CC_PUSH_1 + EE);
3875 }
3876 template<class T> template<Reg16 REG, int EE> II CPUCore<T>::push_SS() {
3877  PUSH<EE>(get16<REG>()); return {1, T::CC_PUSH + EE};
3878 }
3879 
3880 // POP ss
3881 template<class T> template<int EE> inline unsigned CPUCore<T>::POP() {
3882  unsigned addr = getSP();
3883  setSP(addr + 2);
3884  if (T::isR800()) {
3885  // handles both POP and RET instructions (RET with condition = true)
3886  if (EE == 0) { // not reti/retn, not pop ix/iy
3887  setCurrentPopRet();
3888  // No need for setSlowInstructions()
3889  // -> this only matters directly after a CALL
3890  // instruction and in that case we're still
3891  // executing slow instructions.
3892  }
3893  }
3894  return RD_WORD(addr, T::CC_POP_1 + EE);
3895 }
3896 template<class T> template<Reg16 REG, int EE> II CPUCore<T>::pop_SS() {
3897  set16<REG>(POP<EE>()); return {1, T::CC_POP + EE};
3898 }
3899 
3900 
3901 // CALL nn / CALL cc,nn
3902 template<class T> template<typename COND> II CPUCore<T>::call(COND cond) {
3903  unsigned addr = RD_WORD_PC<1>(T::CC_CALL_1);
3904  T::setMemPtr(addr);
3905  if (cond(getF())) {
3906  PUSH<T::EE_CALL>(getPC() + 3);
3907  setPC(addr);
3908  if (T::isR800()) {
3909  setCurrentCall();
3910  setSlowInstructions();
3911  }
3912  return {0/*3*/, T::CC_CALL_A};
3913  } else {
3914  return {3, T::CC_CALL_B};
3915  }
3916 }
3917 
3918 
3919 // RST n
3920 template<class T> template<unsigned ADDR> II CPUCore<T>::rst() {
3921  PUSH<0>(getPC() + 1);
3922  T::setMemPtr(ADDR);
3923  setPC(ADDR);
3924  if (T::isR800()) {
3925  setCurrentCall();
3926  setSlowInstructions();
3927  }
3928  return {0/*1*/, T::CC_RST};
3929 }
3930 
3931 
3932 // RET
3933 template<class T> template<int EE, typename COND> inline II CPUCore<T>::RET(COND cond) {
3934  if (cond(getF())) {
3935  unsigned addr = POP<EE>();
3936  T::setMemPtr(addr);
3937  setPC(addr);
3938  return {0/*1*/, T::CC_RET_A + EE};
3939  } else {
3940  return {1, T::CC_RET_B + EE};
3941  }
3942 }
3943 template<class T> template<typename COND> II CPUCore<T>::ret(COND cond) {
3944  return RET<T::EE_RET_C>(cond);
3945 }
3946 template<class T> II CPUCore<T>::ret() {
3947  return RET<0>(CondTrue());
3948 }
3949 template<class T> II CPUCore<T>::retn() { // also reti
3950  setIFF1(getIFF2());
3951  setSlowInstructions();
3952  return RET<T::EE_RETN>(CondTrue());
3953 }
3954 
3955 
3956 // JP ss
3957 template<class T> template<Reg16 REG, int EE> II CPUCore<T>::jp_SS() {
3958  setPC(get16<REG>()); T::R800ForcePageBreak(); return {0/*1*/, T::CC_JP_HL + EE};
3959 }
3960 
3961 // JP nn / JP cc,nn
3962 template<class T> template<typename COND> II CPUCore<T>::jp(COND cond) {
3963  unsigned addr = RD_WORD_PC<1>(T::CC_JP_1);
3964  T::setMemPtr(addr);
3965  if (cond(getF())) {
3966  setPC(addr);
3967  T::R800ForcePageBreak();
3968  return {0/*3*/, T::CC_JP_A};
3969  } else {
3970  return {3, T::CC_JP_B};
3971  }
3972 }
3973 
3974 // JR e
3975 template<class T> template<typename COND> II CPUCore<T>::jr(COND cond) {
3976  int8_t ofst = RDMEM_OPCODE<1>(T::CC_JR_1);
3977  if (cond(getF())) {
3978  if (((getPC() + 2) & 0xFF) == 0) {
3979  // On R800, when this instruction is located in the
3980  // last two byte of a page (a page is a 256-byte
3981  // (aligned) memory block) and even if we jump back,
3982  // thus fetching the next opcode byte does not cause a
3983  // page-break, there still is one cycle overhead. It's
3984  // as-if there is a page-break.
3985  //
3986  // This could be explained by some (very limited)
3987  // pipeline behaviour in R800: it seems that the
3988  // decision to cause a page-break on the next
3989  // instruction is already made before the jump
3990  // destination address for the current instruction is
3991  // calculated (though a destination address in another
3992  // page is also a reason for a page-break).
3993  //
3994  // It's likely all instructions behave like this, but I
3995  // think we can get away with only explicitly emulating
3996  // this behaviour in the djnz and the jr (conditional
3997  // or not) instructions: all other instructions that
3998  // cause the PC to change in a non-incremental way do
3999  // already force a pagebreak for another reason, so
4000  // this effect is masked. Examples of such instructions
4001  // are: JP, RET, CALL, RST, all repeated block
4002  // instructions, accepting an IRQ, (are there more
4003  // instructions or events that change PC?)
4004  //
4005  // See doc/r800-djnz.txt for more details.
4006  T::R800ForcePageBreak();
4007  }
4008  setPC((getPC() + 2 + ofst) & 0xFFFF);
4009  T::setMemPtr(getPC());
4010  return {0/*2*/, T::CC_JR_A};
4011  } else {
4012  return {2, T::CC_JR_B};
4013  }
4014 }
4015 
4016 // DJNZ e
4017 template<class T> II CPUCore<T>::djnz() {
4018  byte b = getB() - 1;
4019  setB(b);
4020  int8_t ofst = RDMEM_OPCODE<1>(T::CC_JR_1 + T::EE_DJNZ);
4021  if (b) {
4022  if (((getPC() + 2) & 0xFF) == 0) {
4023  // See comment in jr()
4024  T::R800ForcePageBreak();
4025  }
4026  setPC((getPC() + 2 + ofst) & 0xFFFF);
4027  T::setMemPtr(getPC());
4028  return {0/*2*/, T::CC_JR_A + T::EE_DJNZ};
4029  } else {
4030  return {2, T::CC_JR_B + T::EE_DJNZ};
4031  }
4032 }
4033 
4034 // EX (SP),ss
4035 template<class T> template<Reg16 REG, int EE> II CPUCore<T>::ex_xsp_SS() {
4036  unsigned res = RD_WORD_impl<true, false>(getSP(), T::CC_EX_SP_HL_1 + EE);
4037  T::setMemPtr(res);
4038  WR_WORD_rev<false, true>(getSP(), get16<REG>(), T::CC_EX_SP_HL_2 + EE);
4039  set16<REG>(res);
4040  return {1, T::CC_EX_SP_HL + EE};
4041 }
4042 
4043 // IN r,(c)
4044 template<class T> template<Reg8 REG> II CPUCore<T>::in_R_c() {
4045  if (T::isR800()) T::waitForEvenCycle(T::CC_IN_R_C_1);
4046  T::setMemPtr(getBC() + 1);
4047  byte res = READ_PORT(getBC(), T::CC_IN_R_C_1);
4048  byte f = 0;
4049  if (T::isR800()) {
4050  f |= getF() & (C_FLAG | X_FLAG | Y_FLAG);
4051  f |= table.ZSP[res];
4052  } else {
4053  f |= getF() & C_FLAG;
4054  f |= table.ZSPXY[res];
4055  }
4056  setF(f);
4057  set8<REG>(res);
4058  return {1, T::CC_IN_R_C};
4059 }
4060 
4061 // IN a,(n)
4062 template<class T> II CPUCore<T>::in_a_byte() {
4063  unsigned y = RDMEM_OPCODE<1>(T::CC_IN_A_N_1) + 256 * getA();
4064  T::setMemPtr(y + 1);
4065  if (T::isR800()) T::waitForEvenCycle(T::CC_IN_A_N_2);
4066  setA(READ_PORT(y, T::CC_IN_A_N_2));
4067  return {2, T::CC_IN_A_N};
4068 }
4069 
4070 // OUT (c),r
4071 template<class T> template<Reg8 REG> II CPUCore<T>::out_c_R() {
4072  if (T::isR800()) T::waitForEvenCycle(T::CC_OUT_C_R_1);
4073  T::setMemPtr(getBC() + 1);
4074  WRITE_PORT(getBC(), get8<REG>(), T::CC_OUT_C_R_1);
4075  return {1, T::CC_OUT_C_R};
4076 }
4077 template<class T> II CPUCore<T>::out_c_0() {
4078  // TODO not on R800
4079  if (T::isR800()) T::waitForEvenCycle(T::CC_OUT_C_R_1);
4080  T::setMemPtr(getBC() + 1);
4081  byte out_c_x = isTurboR ? 255 : 0;
4082  WRITE_PORT(getBC(), out_c_x, T::CC_OUT_C_R_1);
4083  return {1, T::CC_OUT_C_R};
4084 }
4085 
4086 // OUT (n),a
4087 template<class T> II CPUCore<T>::out_byte_a() {
4088  byte port = RDMEM_OPCODE<1>(T::CC_OUT_N_A_1);
4089  unsigned y = (getA() << 8) | port;
4090  T::setMemPtr((getA() << 8) | ((port + 1) & 255));
4091  if (T::isR800()) T::waitForEvenCycle(T::CC_OUT_N_A_2);
4092  WRITE_PORT(y, getA(), T::CC_OUT_N_A_2);
4093  return {2, T::CC_OUT_N_A};
4094 }
4095 
4096 
4097 // block CP
4098 template<class T> inline II CPUCore<T>::BLOCK_CP(int increase, bool repeat) {
4099  T::setMemPtr(T::getMemPtr() + increase);
4100  byte val = RDMEM(getHL(), T::CC_CPI_1);
4101  byte res = getA() - val;
4102  setHL(getHL() + increase);
4103  setBC(getBC() - 1);
4104  byte f = ((getA() ^ val ^ res) & H_FLAG) |
4105  table.ZS[res] |
4106  N_FLAG |
4107  (getBC() ? V_FLAG : 0);
4108  if (T::isR800()) {
4109  f |= getF() & (C_FLAG | X_FLAG | Y_FLAG);
4110  } else {
4111  f |= getF() & C_FLAG;
4112  unsigned k = res - ((f & H_FLAG) >> 4);
4113  f |= (k << 4) & Y_FLAG; // bit 1 -> flag 5
4114  f |= k & X_FLAG; // bit 3 -> flag 3
4115  }
4116  setF(f);
4117  if (repeat && getBC() && res) {
4118  //setPC(getPC() - 2);
4119  T::setMemPtr(getPC() + 1);
4120  return {-1/*1*/, T::CC_CPIR};
4121  } else {
4122  return {1, T::CC_CPI};
4123  }
4124 }
4125 template<class T> II CPUCore<T>::cpd() { return BLOCK_CP(-1, false); }
4126 template<class T> II CPUCore<T>::cpi() { return BLOCK_CP( 1, false); }
4127 template<class T> II CPUCore<T>::cpdr() { return BLOCK_CP(-1, true ); }
4128 template<class T> II CPUCore<T>::cpir() { return BLOCK_CP( 1, true ); }
4129 
4130 
4131 // block LD
4132 template<class T> inline II CPUCore<T>::BLOCK_LD(int increase, bool repeat) {
4133  byte val = RDMEM(getHL(), T::CC_LDI_1);
4134  WRMEM(getDE(), val, T::CC_LDI_2);
4135  setHL(getHL() + increase);
4136  setDE(getDE() + increase);
4137  setBC(getBC() - 1);
4138  byte f = getBC() ? V_FLAG : 0;
4139  if (T::isR800()) {
4140  f |= getF() & (S_FLAG | Z_FLAG | C_FLAG | X_FLAG | Y_FLAG);
4141  } else {
4142  f |= getF() & (S_FLAG | Z_FLAG | C_FLAG);
4143  f |= ((getA() + val) << 4) & Y_FLAG; // bit 1 -> flag 5
4144  f |= (getA() + val) & X_FLAG; // bit 3 -> flag 3
4145  }
4146  setF(f);
4147  if (repeat && getBC()) {
4148  //setPC(getPC() - 2);
4149  T::setMemPtr(getPC() + 1);
4150  return {-1/*1*/, T::CC_LDIR};
4151  } else {
4152  return {1, T::CC_LDI};
4153  }
4154 }
4155 template<class T> II CPUCore<T>::ldd() { return BLOCK_LD(-1, false); }
4156 template<class T> II CPUCore<T>::ldi() { return BLOCK_LD( 1, false); }
4157 template<class T> II CPUCore<T>::lddr() { return BLOCK_LD(-1, true ); }
4158 template<class T> II CPUCore<T>::ldir() { return BLOCK_LD( 1, true ); }
4159 
4160 
4161 // block IN
4162 template<class T> inline II CPUCore<T>::BLOCK_IN(int increase, bool repeat) {
4163  // TODO R800 flags
4164  if (T::isR800()) T::waitForEvenCycle(T::CC_INI_1);
4165  T::setMemPtr(getBC() + increase);
4166  setBC(getBC() - 0x100); // decr before use
4167  byte val = READ_PORT(getBC(), T::CC_INI_1);
4168  WRMEM(getHL(), val, T::CC_INI_2);
4169  setHL(getHL() + increase);
4170  unsigned k = val + ((getC() + increase) & 0xFF);
4171  byte b = getB();
4172  setF(((val & S_FLAG) >> 6) | // N_FLAG
4173  ((k & 0x100) ? (H_FLAG | C_FLAG) : 0) |
4174  table.ZSXY[b] |
4175  (table.ZSPXY[(k & 0x07) ^ b] & P_FLAG));
4176  if (repeat && b) {
4177  //setPC(getPC() - 2);
4178  return {-1/*1*/, T::CC_INIR};
4179  } else {
4180  return {1, T::CC_INI};
4181  }
4182 }
4183 template<class T> II CPUCore<T>::ind() { return BLOCK_IN(-1, false); }
4184 template<class T> II CPUCore<T>::ini() { return BLOCK_IN( 1, false); }
4185 template<class T> II CPUCore<T>::indr() { return BLOCK_IN(-1, true ); }
4186 template<class T> II CPUCore<T>::inir() { return BLOCK_IN( 1, true ); }
4187 
4188 
4189 // block OUT
4190 template<class T> inline II CPUCore<T>::BLOCK_OUT(int increase, bool repeat) {
4191  // TODO R800 flags
4192  byte val = RDMEM(getHL(), T::CC_OUTI_1);
4193  setHL(getHL() + increase);
4194  if (T::isR800()) T::waitForEvenCycle(T::CC_OUTI_2);
4195  WRITE_PORT(getBC(), val, T::CC_OUTI_2);
4196  setBC(getBC() - 0x100); // decr after use
4197  T::setMemPtr(getBC() + increase);
4198  unsigned k = val + getL();
4199  byte b = getB();
4200  setF(((val & S_FLAG) >> 6) | // N_FLAG
4201  ((k & 0x100) ? (H_FLAG | C_FLAG) : 0) |
4202  table.ZSXY[b] |
4203  (table.ZSPXY[(k & 0x07) ^ b] & P_FLAG));
4204  if (repeat && b) {
4205  //setPC(getPC() - 2);
4206  return {-1/*1*/, T::CC_OTIR};
4207  } else {
4208  return {1, T::CC_OUTI};
4209  }
4210 }
4211 template<class T> II CPUCore<T>::outd() { return BLOCK_OUT(-1, false); }
4212 template<class T> II CPUCore<T>::outi() { return BLOCK_OUT( 1, false); }
4213 template<class T> II CPUCore<T>::otdr() { return BLOCK_OUT(-1, true ); }
4214 template<class T> II CPUCore<T>::otir() { return BLOCK_OUT( 1, true ); }
4215 
4216 
4217 // various
4218 template<class T> II CPUCore<T>::nop() { return {1, T::CC_NOP}; }
4219 template<class T> II CPUCore<T>::ccf() {
4220  byte f = 0;
4221  if (T::isR800()) {
4222  // H flag is different from Z80 (and as always XY flags as well)
4223  f |= getF() & (S_FLAG | Z_FLAG | P_FLAG | C_FLAG | X_FLAG | Y_FLAG | H_FLAG);
4224  } else {
4225  f |= (getF() & C_FLAG) << 4; // H_FLAG
4226  // only set X(Y) flag (don't reset if already set)
4227  if (isTurboR) {
4228  // Y flag is not changed on a turboR-Z80
4229  f |= getF() & (S_FLAG | Z_FLAG | P_FLAG | C_FLAG | Y_FLAG);
4230  f |= (getF() | getA()) & X_FLAG;
4231  } else {
4232  f |= getF() & (S_FLAG | Z_FLAG | P_FLAG | C_FLAG);
4233  f |= (getF() | getA()) & (X_FLAG | Y_FLAG);
4234  }
4235  }
4236  f ^= C_FLAG;
4237  setF(f);
4238  return {1, T::CC_CCF};
4239 }
4240 template<class T> II CPUCore<T>::cpl() {
4241  setA(getA() ^ 0xFF);
4242  byte f = H_FLAG | N_FLAG;
4243  if (T::isR800()) {
4244  f |= getF();
4245  } else {
4246  f |= getF() & (S_FLAG | Z_FLAG | P_FLAG | C_FLAG);
4247  f |= getA() & (X_FLAG | Y_FLAG);
4248  }
4249  setF(f);
4250  return {1, T::CC_CPL};
4251 }
4252 template<class T> II CPUCore<T>::daa() {
4253  byte a = getA();
4254  byte f = getF();
4255  byte adjust = 0;
4256  if ((f & H_FLAG) || ((getA() & 0xf) > 9)) adjust += 6;
4257  if ((f & C_FLAG) || (getA() > 0x99)) adjust += 0x60;
4258  if (f & N_FLAG) a -= adjust; else a += adjust;
4259  if (T::isR800()) {
4260  f &= C_FLAG | N_FLAG | X_FLAG | Y_FLAG;
4261  f |= table.ZSP[a];
4262  } else {
4263  f &= C_FLAG | N_FLAG;
4264  f |= table.ZSPXY[a];
4265  }
4266  f |= (getA() > 0x99) | ((getA() ^ a) & H_FLAG);
4267  setA(a);
4268  setF(f);
4269  return {1, T::CC_DAA};
4270 }
4271 template<class T> II CPUCore<T>::neg() {
4272  // alternative: LUT word negTable[256]
4273  unsigned a = getA();
4274  unsigned res = -signed(a);
4275  byte f = ((res & 0x100) ? C_FLAG : 0) |
4276  N_FLAG |
4277  ((res ^ a) & H_FLAG) |
4278  ((a & res & 0x80) >> 5); // V_FLAG
4279  if (T::isR800()) {
4280  f |= table.ZS[res & 0xFF];
4281  f |= getF() & (X_FLAG | Y_FLAG);
4282  } else {
4283  f |= table.ZSXY[res & 0xFF];
4284  }
4285  setF(f);
4286  setA(res);
4287  return {1, T::CC_NEG};
4288 }
4289 template<class T> II CPUCore<T>::scf() {
4290  byte f = C_FLAG;
4291  if (T::isR800()) {
4292  f |= getF() & (S_FLAG | Z_FLAG | P_FLAG | X_FLAG | Y_FLAG);
4293  } else {
4294  // only set X(Y) flag (don't reset if already set)
4295  if (isTurboR) {
4296  // Y flag is not changed on a turboR-Z80
4297  f |= getF() & (S_FLAG | Z_FLAG | P_FLAG | Y_FLAG);
4298  f |= (getF() | getA()) & X_FLAG;
4299  } else {
4300  f |= getF() & (S_FLAG | Z_FLAG | P_FLAG);
4301  f |= (getF() | getA()) & (X_FLAG | Y_FLAG);
4302  }
4303  }
4304  setF(f);
4305  return {1, T::CC_SCF};
4306 }
4307 
4308 template<class T> II CPUCore<T>::ex_af_af() {
4309  unsigned t = getAF2(); setAF2(getAF()); setAF(t);
4310  return {1, T::CC_EX};
4311 }
4312 template<class T> II CPUCore<T>::ex_de_hl() {
4313  unsigned t = getDE(); setDE(getHL()); setHL(t);
4314  return {1, T::CC_EX};
4315 }
4316 template<class T> II CPUCore<T>::exx() {
4317  unsigned t1 = getBC2(); setBC2(getBC()); setBC(t1);
4318  unsigned t2 = getDE2(); setDE2(getDE()); setDE(t2);
4319  unsigned t3 = getHL2(); setHL2(getHL()); setHL(t3);
4320  return {1, T::CC_EX};
4321 }
4322 
4323 template<class T> II CPUCore<T>::di() {
4324  setIFF1(false);
4325  setIFF2(false);
4326  return {1, T::CC_DI};
4327 }
4328 template<class T> II CPUCore<T>::ei() {
4329  setIFF1(true);
4330  setIFF2(true);
4331  setCurrentEI(); // no ints directly after this instr
4332  setSlowInstructions();
4333  return {1, T::CC_EI};
4334 }
4335 template<class T> II CPUCore<T>::halt() {
4336  setHALT(true);
4337  setSlowInstructions();
4338 
4339  if (!(getIFF1() || getIFF2())) {
4340  diHaltCallback.execute();
4341  }
4342  return {1, T::CC_HALT};
4343 }
4344 template<class T> template<unsigned N> II CPUCore<T>::im_N() {
4345  setIM(N); return {1, T::CC_IM};
4346 }
4347 
4348 // LD A,I/R
4349 template<class T> template<Reg8 REG> II CPUCore<T>::ld_a_IR() {
4350  setA(get8<REG>());
4351  byte f = getIFF2() ? V_FLAG : 0;
4352  if (T::isR800()) {
4353  f |= getF() & (C_FLAG | X_FLAG | Y_FLAG);
4354  f |= table.ZS[getA()];
4355  } else {
4356  f |= getF() & C_FLAG;
4357  f |= table.ZSXY[getA()];
4358  // see comment in the IRQ acceptance part of executeSlow().
4359  setCurrentLDAI(); // only Z80 (not R800) has this quirk
4360  setSlowInstructions();
4361  }
4362  setF(f);
4363  return {1, T::CC_LD_A_I};
4364 }
4365 
4366 // LD I/R,A
4367 template<class T> II CPUCore<T>::ld_r_a() {
4368  // This code sequence:
4369  // XOR A / LD R,A / LD A,R
4370  // gives A=2 for Z80, but A=1 for R800. The difference can possibly be
4371  // explained by a difference in the relative time between writing the
4372  // new value to the R register and increasing the R register per M1
4373  // cycle. Here we implemented the R800 behaviour by storing 'A-1' into
4374  // R, that's good enough for now.
4375  byte val = getA();
4376  if (T::isR800()) val -= 1;
4377  setR(val);
4378  return {1, T::CC_LD_A_I};
4379 }
4380 template<class T> II CPUCore<T>::ld_i_a() {
4381  setI(getA());
4382  return {1, T::CC_LD_A_I};
4383 }
4384 
4385 // MULUB A,r
4386 template<class T> template<Reg8 REG> II CPUCore<T>::mulub_a_R() {
4387  assert(T::isR800()); // this instruction is R800-only
4388  // Verified on real R800:
4389  // YHXN flags are unchanged
4390  // SV flags are reset
4391  // Z flag is set when result is zero
4392  // C flag is set when result doesn't fit in 8-bit
4393  setHL(unsigned(getA()) * get8<REG>());
4394  setF((getF() & (N_FLAG | H_FLAG | X_FLAG | Y_FLAG)) |
4395  0 | // S_FLAG V_FLAG
4396  (getHL() ? 0 : Z_FLAG) |
4397  ((getHL() & 0xFF00) ? C_FLAG : 0));
4398  return {1, T::CC_MULUB};
4399 }
4400 
4401 // MULUW HL,ss
4402 template<class T> template<Reg16 REG> II CPUCore<T>::muluw_hl_SS() {
4403  assert(T::isR800()); // this instruction is R800-only
4404  // Verified on real R800:
4405  // YHXN flags are unchanged
4406  // SV flags are reset
4407  // Z flag is set when result is zero
4408  // C flag is set when result doesn't fit in 16-bit
4409  unsigned res = unsigned(getHL()) * get16<REG>();
4410  setDE(res >> 16);
4411  setHL(res & 0xffff);
4412  setF((getF() & (N_FLAG | H_FLAG | X_FLAG | Y_FLAG)) |
4413  0 | // S_FLAG V_FLAG
4414  (res ? 0 : Z_FLAG) |
4415  ((res & 0xFFFF0000) ? C_FLAG : 0));
4416  return {1, T::CC_MULUW};
4417 }
4418 
4419 
4420 // versions:
4421 // 1 -> initial version
4422 // 2 -> moved memptr from here to Z80TYPE (and not to R800TYPE)
4423 // 3 -> timing of the emulation changed (no changes in serialization)
4424 // 4 -> timing of the emulation changed again (see doc/internal/r800-call.txt)
4425 // 5 -> added serialization of nmiEdge
4426 template<class T> template<typename Archive>
4427 void CPUCore<T>::serialize(Archive& ar, unsigned version)
4428 {
4429  T::serialize(ar, version);
4430  ar.serialize("regs", static_cast<CPURegs&>(*this));
4431  if (ar.versionBelow(version, 2)) {
4432  unsigned mptr = 0; // dummy value (avoid warning)
4433  ar.serialize("memptr", mptr);
4434  T::setMemPtr(mptr);
4435  }
4436 
4437  if (ar.versionBelow(version, 5)) {
4438  // NMI is unused on MSX and even on systems where it is used nmiEdge
4439  // is true only between the moment the NMI request comes in and the
4440  // moment the Z80 jumps to the NMI handler, so defaulting to false
4441  // is pretty safe.
4442  nmiEdge = false;
4443  } else {
4444  // CPU is deserialized after devices, so nmiEdge is restored to the
4445  // saved version even if IRQHelpers set it on deserialization.
4446  ar.serialize("nmiEdge", nmiEdge);
4447  }
4448 
4449  if (ar.isLoader()) {
4450  invalidateMemCache(0x0000, 0x10000);
4451  }
4452 
4453  // Don't serialize:
4454  // - IRQStatus, NMIStatus:
4455  // the IRQHelper deserialization makes sure these get the right value
4456  // - slowInstructions, exitLoop:
4457  // serialization happens outside the CPU emulation loop
4458 
4459  if (T::isR800() && ar.versionBelow(version, 4)) {
4460  motherboard.getMSXCliComm().printWarning(
4461  "Loading an old savestate: the timing of the R800 "
4462  "emulation has changed. This may cause synchronization "
4463  "problems in replay.");
4464  }
4465 }
4466 
4467 // Force template instantiation
4468 template class CPUCore<Z80TYPE>;
4469 template class CPUCore<R800TYPE>;
4470 
4473 
4474 } // namespace openmsx
#define CASE(X)
static const int CLOCK_FREQ
Definition: R800.hh:33
#define NEVER_INLINE
Definition: inline.hh:17
#define ALWAYS_INLINE
Definition: inline.hh:16
#define unlikely(x)
Definition: likely.hh:15
Definition: span.hh:34
uint8_t byte
8 bit unsigned integer
Definition: openmsx.hh:26
unsigned dasm(const MSXCPUInterface &interf, word pc, byte buf[4], std::string &dest, EmuTime::param time)
Disassemble.
Definition: Dasm.cc:18
CPUCore(MSXMotherBoard &motherboard, const std::string &name, const BooleanSetting &traceSetting, TclCallback &diHaltCallback, EmuTime::param time)
Definition: CPUCore.cc:298
bool operator()(byte f) const
Definition: CPUCore.cc:288
byte ZS[256]
Definition: CPUCore.cc:236
bool operator()(byte f) const
Definition: CPUCore.cc:289
#define NEXT
#define NEXT_STOP
int cycles
Definition: CPUCore.hh:39
byte ZSPH[256]
Definition: CPUCore.cc:240
bool operator()(byte) const
Definition: CPUCore.cc:296
Thanks to enen for testing this on a real cartridge:
Definition: Autofire.cc:5
bool operator()(byte f) const
Definition: CPUCore.cc:295
static const int CLOCK_FREQ
Definition: Z80.hh:17
uint16_t word
16 bit unsigned integer
Definition: openmsx.hh:29
void addListElement(T t)
Definition: TclObject.hh:121
#define INSTANTIATE_SERIALIZE_METHODS(CLASS)
Definition: serialize.hh:1006
bool operator()(byte f) const
Definition: CPUCore.cc:292
bool operator()(byte f) const
Definition: CPUCore.cc:294
bool operator()(byte f) const
Definition: CPUCore.cc:290
byte ZSP[256]
Definition: CPUCore.cc:238
#define NEXT_EI
#define likely(x)
Definition: likely.hh:14
std::string strCat(Ts &&...ts)
Definition: strCat.hh:577
bool operator()(byte f) const
Definition: CPUCore.cc:293
byte ZSXY[256]
Definition: CPUCore.cc:237
constexpr auto size(const C &c) -> decltype(c.size())
Definition: span.hh:62
bool operator()(byte f) const
Definition: CPUCore.cc:291
byte ZSPXY[256]
Definition: CPUCore.cc:239
TclObject t
void serialize(Archive &ar, T &t, unsigned version)
bool isMainThread()
Returns true when called from the main thread.
Definition: Thread.cc:16
#define UNREACHABLE
Definition: unreachable.hh:38