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