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