| /*************************************************************************** |
| * __________ __ ___. |
| * Open \______ \ ____ ____ | | _\_ |__ _______ ___ |
| * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / |
| * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < |
| * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ |
| * \/ \/ \/ \/ \/ |
| * $Id$ |
| * |
| * Pacbox - a Pacman Emulator for Rockbox |
| * |
| * Based on PIE - Pacman Instructional Emulator |
| * |
| * Copyright (c) 1997-2003,2004 Alessandro Scotti |
| * http://www.ascotti.org/ |
| * |
| * This program is free software; you can redistribute it and/or |
| * modify it under the terms of the GNU General Public License |
| * as published by the Free Software Foundation; either version 2 |
| * of the License, or (at your option) any later version. |
| * |
| * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY |
| * KIND, either express or implied. |
| * |
| ****************************************************************************/ |
| |
| #include "plugin.h" |
| #include "hardware.h" |
| #include "z80.h" |
| #include "z80_internal.h" |
| |
| // Table with parity, sign and zero flags precomputed for each byte value |
| unsigned char PSZ_[256] IDATA_ATTR = { |
| Zero|Parity, 0, 0, Parity, 0, Parity, Parity, 0, 0, Parity, Parity, 0, Parity, 0, 0, Parity, |
| 0, Parity, Parity, 0, Parity, 0, 0, Parity, Parity, 0, 0, Parity, 0, Parity, Parity, 0, |
| 0, Parity, Parity, 0, Parity, 0, 0, Parity, Parity, 0, 0, Parity, 0, Parity, Parity, 0, |
| Parity, 0, 0, Parity, 0, Parity, Parity, 0, 0, Parity, Parity, 0, Parity, 0, 0, Parity, |
| 0, Parity, Parity, 0, Parity, 0, 0, Parity, Parity, 0, 0, Parity, 0, Parity, Parity, 0, |
| Parity, 0, 0, Parity, 0, Parity, Parity, 0, 0, Parity, Parity, 0, Parity, 0, 0, Parity, |
| Parity, 0, 0, Parity, 0, Parity, Parity, 0, 0, Parity, Parity, 0, Parity, 0, 0, Parity, |
| 0, Parity, Parity, 0, Parity, 0, 0, Parity, Parity, 0, 0, Parity, 0, Parity, Parity, 0, |
| Sign, Sign|Parity, Sign|Parity, Sign, Sign|Parity, Sign, Sign, Sign|Parity, Sign|Parity, Sign, Sign, Sign|Parity, Sign, Sign|Parity, Sign|Parity, Sign, |
| Sign|Parity, Sign, Sign, Sign|Parity, Sign, Sign|Parity, Sign|Parity, Sign, Sign, Sign|Parity, Sign|Parity, Sign, Sign|Parity, Sign, Sign, Sign|Parity, |
| Sign|Parity, Sign, Sign, Sign|Parity, Sign, Sign|Parity, Sign|Parity, Sign, Sign, Sign|Parity, Sign|Parity, Sign, Sign|Parity, Sign, Sign, Sign|Parity, |
| Sign, Sign|Parity, Sign|Parity, Sign, Sign|Parity, Sign, Sign, Sign|Parity, Sign|Parity, Sign, Sign, Sign|Parity, Sign, Sign|Parity, Sign|Parity, Sign, |
| Sign|Parity, Sign, Sign, Sign|Parity, Sign, Sign|Parity, Sign|Parity, Sign, Sign, Sign|Parity, Sign|Parity, Sign, Sign|Parity, Sign, Sign, Sign|Parity, |
| Sign, Sign|Parity, Sign|Parity, Sign, Sign|Parity, Sign, Sign, Sign|Parity, Sign|Parity, Sign, Sign, Sign|Parity, Sign, Sign|Parity, Sign|Parity, Sign, |
| Sign, Sign|Parity, Sign|Parity, Sign, Sign|Parity, Sign, Sign, Sign|Parity, Sign|Parity, Sign, Sign, Sign|Parity, Sign, Sign|Parity, Sign|Parity, Sign, |
| Sign|Parity, Sign, Sign, Sign|Parity, Sign, Sign|Parity, Sign|Parity, Sign, Sign, Sign|Parity, Sign|Parity, Sign, Sign|Parity, Sign, Sign, Sign|Parity |
| }; |
| |
| // Interrupt flags |
| enum { |
| IFF1 = 0x40, // Interrupts enabled/disabled |
| IFF2 = 0x20, // Copy of IFF1 (used by non-maskable interrupts) |
| Halted = 0x10 // Internal use: signals that the CPU is halted |
| }; |
| |
| // Implements an opcode |
| typedef void (OpcodeHandler)(void); |
| |
| typedef struct { |
| OpcodeHandler* handler; |
| unsigned cycles; |
| } OpcodeInfo; |
| |
| // Implements an opcode for instructions that use the form (IX/IY + b) |
| typedef void (OpcodeHandlerXY)( unsigned ); |
| |
| typedef struct { |
| OpcodeHandlerXY* handler; |
| unsigned cycles; |
| } OpcodeInfoXY; |
| |
| /** */ |
| void do_opcode_xy( OpcodeInfo * ); |
| |
| /** */ |
| unsigned do_opcode_xycb( unsigned xy ); |
| |
| unsigned iflags_ IBSS_ATTR; // Interrupt mode (bits 0 and 1) and flags |
| unsigned cycles_ IBSS_ATTR; // Number of CPU cycles elapsed so far |
| |
| |
| // Registers |
| unsigned char B IBSS_ATTR; //@- B register |
| unsigned char C IBSS_ATTR; //@- C register |
| unsigned char D IBSS_ATTR; //@- D register |
| unsigned char E IBSS_ATTR; //@- E register |
| unsigned char H IBSS_ATTR; //@- H register |
| unsigned char L IBSS_ATTR; //@- L register |
| unsigned char A IBSS_ATTR; //@- A register (accumulator) |
| unsigned char F IBSS_ATTR; //@- Flags register |
| unsigned char B1 IBSS_ATTR; //@- Alternate B register (B') |
| unsigned char C1 IBSS_ATTR; //@- Alternate C register (C') |
| unsigned char D1 IBSS_ATTR; //@- Alternate D register (D') |
| unsigned char E1 IBSS_ATTR; //@- Alternate E register (E') |
| unsigned char H1 IBSS_ATTR; //@- Alternate H register (H') |
| unsigned char L1 IBSS_ATTR; //@- Alternate L register (L') |
| unsigned char A1 IBSS_ATTR; //@- Alternate A register (A') |
| unsigned char F1 IBSS_ATTR; //@- Alternate flags register (F') |
| unsigned IX IBSS_ATTR; //@- Index register X |
| unsigned IY IBSS_ATTR; //@- Index register Y |
| unsigned PC IBSS_ATTR; //@- Program counter |
| unsigned SP IBSS_ATTR; //@- Stack pointer |
| unsigned char I IBSS_ATTR; //@- Interrupt register |
| unsigned char R IBSS_ATTR; //@- Refresh register |
| |
| |
| /** Returns the 16 bit register BC. */ |
| #define BC() (((unsigned)B << 8) | C) |
| #define DE() (((unsigned)D << 8) | E) |
| #define HL() (((unsigned)H << 8) | L) |
| |
| /** |
| Returns the number of Z80 CPU cycles elapsed so far. |
| |
| The cycle count is reset to zero when reset() is called, or |
| it can be set to any value with setCycles(). It is updated after |
| a CPU instruction is executed, for example by calling step() |
| or interrupt(). |
| */ |
| unsigned getCycles(void) { |
| return cycles_; |
| } |
| |
| /** Sets the CPU cycle counter to the specified value. */ |
| void setCycles( unsigned value ) { |
| cycles_ = value; |
| } |
| |
| /** Returns the current interrupt mode. */ |
| unsigned getInterruptMode(void) { |
| return iflags_ & 0x03; |
| } |
| |
| /** Sets the interrupt mode to the specified value. */ |
| void setInterruptMode( unsigned mode ); |
| |
| /** Returns non-zero if the CPU is halted, otherwise zero. */ |
| int isHalted(void) { |
| return iflags_ & Halted; |
| } |
| |
| /* |
| Sets the interrupt mode to IM0, IM1 or IM2. |
| */ |
| void setInterruptMode( unsigned mode ) |
| { |
| if( mode <= 2 ) { |
| iflags_ = (iflags_ & ~0x03) | mode; |
| } |
| } |
| |
| /* |
| Calls a subroutine at the specified address. |
| */ |
| void callSub( unsigned addr ) |
| { |
| SP -= 2; |
| writeWord( SP, PC ); // Save current program counter in the stack |
| PC = addr & 0xFFFF; // Jump to the specified address |
| } |
| |
| /* |
| Decrements a byte value by one. |
| Note that this is different from subtracting one from the byte value, |
| because flags behave differently. |
| */ |
| static inline unsigned char decByte( unsigned char b ) |
| { |
| F = Subtraction | (F & Carry); // Preserve the carry flag |
| if( (b & 0x0F) == 0 ) F |= Halfcarry; |
| --b; |
| if( b == 0x7F ) F |= Overflow; |
| if( b & 0x80 ) F |= Sign; |
| if( b == 0 ) F |= Zero; |
| |
| return b; |
| } |
| |
| /* |
| Increments a byte value by one. |
| Note that this is different from adding one to the byte value, |
| because flags behave differently. |
| */ |
| static inline unsigned char incByte( unsigned char b ) |
| { |
| ++b; |
| F &= Carry; // Preserve the carry flag |
| if( ! (b & 0x0F) ) F |= Halfcarry; |
| if( b == 0x80 ) F |= Overflow; |
| if( b & 0x80 ) F |= Sign; |
| if( b == 0 ) F |= Zero; |
| |
| return b; |
| } |
| |
| /* |
| Reads one byte from port C, updating flags according to the rules of "IN r,(C)". |
| */ |
| static inline unsigned char inpReg(void) |
| { |
| unsigned char r = readPort( C ); |
| |
| F = (F & Carry) | PSZ_[r]; |
| |
| return r; |
| } |
| |
| /* |
| Performs a relative jump to the specified offset. |
| */ |
| static inline void relJump( unsigned char o ) |
| { |
| int offset = (int)((signed char)o); |
| |
| PC = (unsigned)((int)PC + offset) & 0xFFFF; |
| cycles_++; |
| } |
| |
| /* |
| Returns from a subroutine, popping the saved Program Counter from the stack. |
| */ |
| static inline void retFromSub(void) |
| { |
| PC = readWord( SP ); |
| SP += 2; |
| } |
| |
| /* |
| Rotates left one byte thru the carry flag. |
| */ |
| static inline unsigned char rotateLeft( unsigned char op ) |
| { |
| unsigned char f = F; |
| |
| F = 0; |
| if( op & 0x80 ) F |= Carry; |
| op <<= 1; |
| if( f & Carry ) op |= 0x01; |
| F |= PSZ_[op]; |
| |
| return op; |
| } |
| |
| /* |
| Rotates left one byte copying the most significant bit (bit 7) in the carry flag. |
| */ |
| static inline unsigned char rotateLeftCarry( unsigned char op ) |
| { |
| F = 0; |
| if( op & 0x80 ) F |= Carry; |
| op = (op << 1) | (op >> 7); |
| F |= PSZ_[op]; |
| |
| return op; |
| } |
| |
| /* |
| Rotates right one byte thru the carry flag. |
| */ |
| static inline unsigned char rotateRight( unsigned char op ) |
| { |
| unsigned char f = F; |
| |
| F = 0; |
| if( op & 0x01 ) F |= Carry; |
| op >>= 1; |
| if( f & Carry ) op |= 0x80; |
| F |= PSZ_[op]; |
| |
| return op; |
| } |
| |
| /* |
| Rotates right one byte copying the least significant bit (bit 0) in the carry flag. |
| */ |
| static inline unsigned char rotateRightCarry( unsigned char op ) |
| { |
| F = 0; |
| if( op & 0x01 ) F |= Carry; |
| op = (op >> 1) | (op << 7); |
| F |= PSZ_[op]; |
| |
| return op; |
| } |
| |
| /* |
| Shifts left one byte. |
| */ |
| static inline unsigned char shiftLeft( unsigned char op ) |
| { |
| F = 0; |
| if( op & 0x80 ) F |= Carry; |
| op <<= 1; |
| F |= PSZ_[op]; |
| |
| return op; |
| } |
| |
| /* |
| Shifts right one byte, preserving its sign (most significant bit). |
| */ |
| static inline unsigned char shiftRightArith( unsigned char op ) |
| { |
| F = 0; |
| if( op & 0x01 ) F |= Carry; |
| op = (op >> 1) | (op & 0x80); |
| |
| F |= PSZ_[op]; |
| |
| return op; |
| } |
| |
| /* |
| Shifts right one byte. |
| */ |
| static inline unsigned char shiftRightLogical( unsigned char op ) |
| { |
| F = 0; |
| if( op & 0x01 ) F |= Carry; |
| op >>= 1; |
| |
| F |= PSZ_[op]; |
| |
| return op; |
| } |
| |
| /* |
| Tests whether the specified bit of op is set. |
| */ |
| static inline void testBit( unsigned char bit, unsigned char op ) |
| { |
| // Flags for a bit test operation are: |
| // S, P: unknown |
| // Z: set if bit is zero, reset otherwise |
| // N: reset |
| // H: set |
| // C: unaffected |
| // However, it seems that parity is always set like Z, so we emulate that as well. |
| F = (F & (Carry | Sign)) | Halfcarry; |
| |
| if( (op & (1 << bit)) == 0 ) { |
| // Bit is not set, so set the zero flag |
| F |= Zero | Parity; |
| } |
| } |
| |
| /* |
| Adds the specified byte op to the accumulator, adding |
| carry. |
| */ |
| static inline void addByte( unsigned char op, unsigned char cf ) |
| { |
| unsigned x = A + op; |
| |
| if( cf ) x++; // Add carry |
| |
| F = 0; |
| if( !(x & 0xFF) ) F |= Zero; |
| if( x & 0x80 ) F |= Sign; |
| if( x >= 0x100 ) F |= Carry; |
| |
| /* |
| Halfcarry is set on carry from the low order four bits. |
| |
| To see how to compute it, let's take a look at the following table, which |
| shows the binary addition of two binary numbers: |
| |
| A B A+B |
| ----------- |
| 0 0 0 |
| 0 1 1 |
| 1 0 1 |
| 1 1 0 |
| |
| Note that if only the lowest bit is used, then A+B, A-B and A^B yield the same |
| value. If we know A, B and the sum A+B+C, then C is easily derived: |
| C = A+B+C - A - B, that is |
| C = A+B+C ^ A ^ B. |
| |
| For the halfcarry, A and B above are the fifth bit of a byte, which corresponds |
| to the value 0x10. So: |
| |
| Halfcarry = ((accumulator+operand+halfcarry) ^ accumulator ^ operand) & 0x10 |
| |
| Note that masking off all bits but one is important because we have worked all |
| the math by using one bit only. |
| */ |
| if( (A ^ op ^ x) & 0x10 ) F |= Halfcarry; |
| |
| /* |
| The overflow bit is set when the result is too large to fit into the destination |
| register, causing a change in the sign bit. |
| |
| For a sum, we can only have overflow when adding two numbers that are both positive |
| or both negative. For example 0x5E + 0x4B (94 + 75) yields 0xA9 (169), which fits |
| into an 8-bit register only if it is interpreted as an unsigned number. If we |
| consider the result as a signed integer, then 0xA9 corresponds to decimal -87 and |
| we have overflow. |
| Note that if we add two signed numbers of opposite sign then we cannot overflow |
| the destination register, because the absolute value of the result will always fit |
| in 7 bits, leaving the most significant bit free for use as a sign bit. |
| |
| We can code all the above concisely by noting that: |
| |
| ~(A ^ op) & 0x80 |
| |
| is true if and only if A and op have the same sign. Also: |
| |
| (x ^ op) & 0x80 |
| |
| is true if and only if the sum of A and op has taken a sign opposite to that |
| of its operands. |
| |
| Thus the expression: |
| |
| ~(A ^ op) & (x ^ op) & 0x80 |
| |
| reads "A has the same sign as op, and the opposite as x", where x is the sum of |
| A and op (and an optional carry). |
| */ |
| if( ~(A ^ op) & (x ^ op) & 0x80 ) F |= Overflow; |
| |
| A = x; |
| } |
| |
| /* |
| Subtracts the specified byte op from the accumulator, using carry as |
| borrow from a previous operation. |
| */ |
| static inline unsigned char subByte( unsigned char op, unsigned char cf ) |
| { |
| unsigned char x = A - op; |
| |
| if( cf ) x--; |
| |
| F = Subtraction; |
| if( x == 0 ) F |= Zero; |
| if( x & 0x80 ) F |= Sign; |
| if( (x >= A) && (op | cf)) F |= Carry; |
| |
| // See addByte() for an explanation of the halfcarry bit |
| if( (A ^ op ^ x) & 0x10 ) F |= Halfcarry; |
| |
| // See addByte() for an explanation of the overflow bit. The only difference here |
| // is that for a subtraction we must check that the two operands have different |
| // sign, because in fact A-B is A+(-B). Note however that since subtraction is not |
| // symmetric, we have to use (x ^ A) to get the correct result, whereas for the |
| // addition (x ^ A) is equivalent to (x ^ op) |
| if( (A ^ op) & (x ^ A) & 0x80 ) F |= Overflow; |
| |
| return x; |
| } |
| |
| static inline unsigned addDispl( unsigned addr, unsigned char displ ) { |
| return (unsigned)((int)addr + (int)(signed char)displ); |
| } |
| |
| /** Compares the accumulator and the specified operand (CP op) */ |
| static inline void cmpByte( unsigned char op ) { |
| subByte( op, 0 ); |
| } |
| |
| /** Fetches a byte from the program counter location */ |
| static inline unsigned char fetchByte(void) { |
| return readByte( PC++ ); |
| } |
| |
| /** Fetches a 16 bit word from the program counter location */ |
| static inline unsigned fetchWord(void) { |
| unsigned x = readWord( PC ); |
| PC += 2; |
| return x; |
| } |
| |
| /** Sets the parity, sign and zero flags from the accumulator value */ |
| static inline void setFlagsPSZ(void) { |
| F = Halfcarry | PSZ_[A]; |
| } |
| |
| /** Sets the parity, sign, zero, 3rd and 5th flag bits from the accumulator value */ |
| static inline void setFlags35PSZ(void) { |
| F = (F & (Carry | Halfcarry | Subtraction)) | PSZ_[A]; |
| } |
| |
| /** */ |
| static inline void setFlags35PSZ000(void) { |
| F = PSZ_[A]; |
| } |
| |
| /* Resets the CPU */ |
| void z80_reset() |
| { |
| PC = 0; // Program counter is zero |
| I = 0; // Interrupt register cleared |
| R = 0; // Memory refresh register cleared |
| iflags_ = 0; // IFF1 and IFF2 cleared, IM0 enabled |
| cycles_ = 0; // Could that be 2 (according to some Zilog docs)? |
| |
| // There is no official documentation for the following! |
| B = B1 = 0; |
| C = C1 = 0; |
| D = D1 = 0; |
| E = E1 = 0; |
| H = H1 = 0; |
| L = L1 = 0; |
| A = A1 = 0; |
| F = F1 = 0; |
| IX = 0; |
| IY = 0; |
| SP = 0xF000; |
| } |
| |
| unsigned z80_getSizeOfSnapshotBuffer(void) |
| { |
| unsigned result = |
| 8*2 + // 8-bit registers |
| 1 + // I |
| 1 + // R |
| 2 + // IX |
| 2 + // IY |
| 2 + // PC |
| 2 + // SP |
| 4 + // iflags_ |
| 4; // cycles_ |
| |
| return result; |
| } |
| |
| static unsigned saveUint16( unsigned char * buffer, unsigned u ) |
| { |
| *buffer++ = (unsigned char) (u >> 8); |
| *buffer = (unsigned char) (u); |
| |
| return 2; |
| } |
| |
| unsigned z80_takeSnapshot( unsigned char * buffer ) |
| { |
| unsigned char * buf = buffer; |
| |
| *buf++ = A; *buf++ = A1; |
| *buf++ = B; *buf++ = B1; |
| *buf++ = C; *buf++ = C1; |
| *buf++ = D; *buf++ = D1; |
| *buf++ = E; *buf++ = E1; |
| *buf++ = H; *buf++ = H1; |
| *buf++ = L; *buf++ = L1; |
| *buf++ = F; *buf++ = F1; |
| |
| *buf++ = I; |
| *buf++ = R; |
| |
| buf += saveUint16( buf, IX ); |
| buf += saveUint16( buf, IY ); |
| buf += saveUint16( buf, PC ); |
| buf += saveUint16( buf, SP ); |
| |
| buf += saveUint16( buf, iflags_ >> 16 ); |
| buf += saveUint16( buf, iflags_ ); |
| buf += saveUint16( buf, cycles_ >> 16 ); |
| buf += saveUint16( buf, cycles_ ); |
| |
| return buffer - buf; |
| } |
| |
| static unsigned loadUint16( unsigned char ** buffer ) |
| { |
| unsigned char * buf = *buffer; |
| unsigned result = *buf++; |
| |
| result = (result << 8) | *buf++; |
| |
| *buffer = buf; |
| |
| return result; |
| } |
| |
| unsigned z80_restoreSnapshot( unsigned char * buffer ) |
| { |
| unsigned char * buf = buffer; |
| |
| A = *buf++; A1 = *buf++; |
| B = *buf++; B1 = *buf++; |
| C = *buf++; C1 = *buf++; |
| D = *buf++; D1 = *buf++; |
| E = *buf++; E1 = *buf++; |
| H = *buf++; H1 = *buf++; |
| L = *buf++; L1 = *buf++; |
| F = *buf++; F1 = *buf++; |
| |
| I = *buf++; |
| R = *buf++; |
| |
| IX = loadUint16( &buf ); |
| IY = loadUint16( &buf ); |
| PC = loadUint16( &buf ); |
| SP = loadUint16( &buf ); |
| |
| iflags_ = loadUint16( &buf ); |
| iflags_ = (iflags_ << 16) | loadUint16(&buf); |
| cycles_ = loadUint16( &buf ); |
| cycles_ = (cycles_ << 16) | loadUint16(&buf); |
| |
| return buf - buffer; |
| } |
| |
| OpcodeInfo OpInfoCB_[256] = { |
| { &opcode_cb_00, 8 }, // RLC B |
| { &opcode_cb_01, 8 }, // RLC C |
| { &opcode_cb_02, 8 }, // RLC D |
| { &opcode_cb_03, 8 }, // RLC E |
| { &opcode_cb_04, 8 }, // RLC H |
| { &opcode_cb_05, 8 }, // RLC L |
| { &opcode_cb_06, 15 }, // RLC (HL) |
| { &opcode_cb_07, 8 }, // RLC A |
| { &opcode_cb_08, 8 }, // RRC B |
| { &opcode_cb_09, 8 }, // RRC C |
| { &opcode_cb_0a, 8 }, // RRC D |
| { &opcode_cb_0b, 8 }, // RRC E |
| { &opcode_cb_0c, 8 }, // RRC H |
| { &opcode_cb_0d, 8 }, // RRC L |
| { &opcode_cb_0e, 15 }, // RRC (HL) |
| { &opcode_cb_0f, 8 }, // RRC A |
| { &opcode_cb_10, 8 }, // RL B |
| { &opcode_cb_11, 8 }, // RL C |
| { &opcode_cb_12, 8 }, // RL D |
| { &opcode_cb_13, 8 }, // RL E |
| { &opcode_cb_14, 8 }, // RL H |
| { &opcode_cb_15, 8 }, // RL L |
| { &opcode_cb_16, 15 }, // RL (HL) |
| { &opcode_cb_17, 8 }, // RL A |
| { &opcode_cb_18, 8 }, // RR B |
| { &opcode_cb_19, 8 }, // RR C |
| { &opcode_cb_1a, 8 }, // RR D |
| { &opcode_cb_1b, 8 }, // RR E |
| { &opcode_cb_1c, 8 }, // RR H |
| { &opcode_cb_1d, 8 }, // RR L |
| { &opcode_cb_1e, 15 }, // RR (HL) |
| { &opcode_cb_1f, 8 }, // RR A |
| { &opcode_cb_20, 8 }, // SLA B |
| { &opcode_cb_21, 8 }, // SLA C |
| { &opcode_cb_22, 8 }, // SLA D |
| { &opcode_cb_23, 8 }, // SLA E |
| { &opcode_cb_24, 8 }, // SLA H |
| { &opcode_cb_25, 8 }, // SLA L |
| { &opcode_cb_26, 15 }, // SLA (HL) |
| { &opcode_cb_27, 8 }, // SLA A |
| { &opcode_cb_28, 8 }, // SRA B |
| { &opcode_cb_29, 8 }, // SRA C |
| { &opcode_cb_2a, 8 }, // SRA D |
| { &opcode_cb_2b, 8 }, // SRA E |
| { &opcode_cb_2c, 8 }, // SRA H |
| { &opcode_cb_2d, 8 }, // SRA L |
| { &opcode_cb_2e, 15 }, // SRA (HL) |
| { &opcode_cb_2f, 8 }, // SRA A |
| { &opcode_cb_30, 8 }, // SLL B |
| { &opcode_cb_31, 8 }, // SLL C |
| { &opcode_cb_32, 8 }, // SLL D |
| { &opcode_cb_33, 8 }, // SLL E |
| { &opcode_cb_34, 8 }, // SLL H |
| { &opcode_cb_35, 8 }, // SLL L |
| { &opcode_cb_36, 15 }, // SLL (HL) |
| { &opcode_cb_37, 8 }, // SLL A |
| { &opcode_cb_38, 8 }, // SRL B |
| { &opcode_cb_39, 8 }, // SRL C |
| { &opcode_cb_3a, 8 }, // SRL D |
| { &opcode_cb_3b, 8 }, // SRL E |
| { &opcode_cb_3c, 8 }, // SRL H |
| { &opcode_cb_3d, 8 }, // SRL L |
| { &opcode_cb_3e, 15 }, // SRL (HL) |
| { &opcode_cb_3f, 8 }, // SRL A |
| { &opcode_cb_40, 8 }, // BIT 0, B |
| { &opcode_cb_41, 8 }, // BIT 0, C |
| { &opcode_cb_42, 8 }, // BIT 0, D |
| { &opcode_cb_43, 8 }, // BIT 0, E |
| { &opcode_cb_44, 8 }, // BIT 0, H |
| { &opcode_cb_45, 8 }, // BIT 0, L |
| { &opcode_cb_46, 12 }, // BIT 0, (HL) |
| { &opcode_cb_47, 8 }, // BIT 0, A |
| { &opcode_cb_48, 8 }, // BIT 1, B |
| { &opcode_cb_49, 8 }, // BIT 1, C |
| { &opcode_cb_4a, 8 }, // BIT 1, D |
| { &opcode_cb_4b, 8 }, // BIT 1, E |
| { &opcode_cb_4c, 8 }, // BIT 1, H |
| { &opcode_cb_4d, 8 }, // BIT 1, L |
| { &opcode_cb_4e, 12 }, // BIT 1, (HL) |
| { &opcode_cb_4f, 8 }, // BIT 1, A |
| { &opcode_cb_50, 8 }, // BIT 2, B |
| { &opcode_cb_51, 8 }, // BIT 2, C |
| { &opcode_cb_52, 8 }, // BIT 2, D |
| { &opcode_cb_53, 8 }, // BIT 2, E |
| { &opcode_cb_54, 8 }, // BIT 2, H |
| { &opcode_cb_55, 8 }, // BIT 2, L |
| { &opcode_cb_56, 12 }, // BIT 2, (HL) |
| { &opcode_cb_57, 8 }, // BIT 2, A |
| { &opcode_cb_58, 8 }, // BIT 3, B |
| { &opcode_cb_59, 8 }, // BIT 3, C |
| { &opcode_cb_5a, 8 }, // BIT 3, D |
| { &opcode_cb_5b, 8 }, // BIT 3, E |
| { &opcode_cb_5c, 8 }, // BIT 3, H |
| { &opcode_cb_5d, 8 }, // BIT 3, L |
| { &opcode_cb_5e, 12 }, // BIT 3, (HL) |
| { &opcode_cb_5f, 8 }, // BIT 3, A |
| { &opcode_cb_60, 8 }, // BIT 4, B |
| { &opcode_cb_61, 8 }, // BIT 4, C |
| { &opcode_cb_62, 8 }, // BIT 4, D |
| { &opcode_cb_63, 8 }, // BIT 4, E |
| { &opcode_cb_64, 8 }, // BIT 4, H |
| { &opcode_cb_65, 8 }, // BIT 4, L |
| { &opcode_cb_66, 12 }, // BIT 4, (HL) |
| { &opcode_cb_67, 8 }, // BIT 4, A |
| { &opcode_cb_68, 8 }, // BIT 5, B |
| { &opcode_cb_69, 8 }, // BIT 5, C |
| { &opcode_cb_6a, 8 }, // BIT 5, D |
| { &opcode_cb_6b, 8 }, // BIT 5, E |
| { &opcode_cb_6c, 8 }, // BIT 5, H |
| { &opcode_cb_6d, 8 }, // BIT 5, L |
| { &opcode_cb_6e, 12 }, // BIT 5, (HL) |
| { &opcode_cb_6f, 8 }, // BIT 5, A |
| { &opcode_cb_70, 8 }, // BIT 6, B |
| { &opcode_cb_71, 8 }, // BIT 6, C |
| { &opcode_cb_72, 8 }, // BIT 6, D |
| { &opcode_cb_73, 8 }, // BIT 6, E |
| { &opcode_cb_74, 8 }, // BIT 6, H |
| { &opcode_cb_75, 8 }, // BIT 6, L |
| { &opcode_cb_76, 12 }, // BIT 6, (HL) |
| { &opcode_cb_77, 8 }, // BIT 6, A |
| { &opcode_cb_78, 8 }, // BIT 7, B |
| { &opcode_cb_79, 8 }, // BIT 7, C |
| { &opcode_cb_7a, 8 }, // BIT 7, D |
| { &opcode_cb_7b, 8 }, // BIT 7, E |
| { &opcode_cb_7c, 8 }, // BIT 7, H |
| { &opcode_cb_7d, 8 }, // BIT 7, L |
| { &opcode_cb_7e, 12 }, // BIT 7, (HL) |
| { &opcode_cb_7f, 8 }, // BIT 7, A |
| { &opcode_cb_80, 8 }, // RES 0, B |
| { &opcode_cb_81, 8 }, // RES 0, C |
| { &opcode_cb_82, 8 }, // RES 0, D |
| { &opcode_cb_83, 8 }, // RES 0, E |
| { &opcode_cb_84, 8 }, // RES 0, H |
| { &opcode_cb_85, 8 }, // RES 0, L |
| { &opcode_cb_86, 15 }, // RES 0, (HL) |
| { &opcode_cb_87, 8 }, // RES 0, A |
| { &opcode_cb_88, 8 }, // RES 1, B |
| { &opcode_cb_89, 8 }, // RES 1, C |
| { &opcode_cb_8a, 8 }, // RES 1, D |
| { &opcode_cb_8b, 8 }, // RES 1, E |
| { &opcode_cb_8c, 8 }, // RES 1, H |
| { &opcode_cb_8d, 8 }, // RES 1, L |
| { &opcode_cb_8e, 15 }, // RES 1, (HL) |
| { &opcode_cb_8f, 8 }, // RES 1, A |
| { &opcode_cb_90, 8 }, // RES 2, B |
| { &opcode_cb_91, 8 }, // RES 2, C |
| { &opcode_cb_92, 8 }, // RES 2, D |
| { &opcode_cb_93, 8 }, // RES 2, E |
| { &opcode_cb_94, 8 }, // RES 2, H |
| { &opcode_cb_95, 8 }, // RES 2, L |
| { &opcode_cb_96, 15 }, // RES 2, (HL) |
| { &opcode_cb_97, 8 }, // RES 2, A |
| { &opcode_cb_98, 8 }, // RES 3, B |
| { &opcode_cb_99, 8 }, // RES 3, C |
| { &opcode_cb_9a, 8 }, // RES 3, D |
| { &opcode_cb_9b, 8 }, // RES 3, E |
| { &opcode_cb_9c, 8 }, // RES 3, H |
| { &opcode_cb_9d, 8 }, // RES 3, L |
| { &opcode_cb_9e, 15 }, // RES 3, (HL) |
| { &opcode_cb_9f, 8 }, // RES 3, A |
| { &opcode_cb_a0, 8 }, // RES 4, B |
| { &opcode_cb_a1, 8 }, // RES 4, C |
| { &opcode_cb_a2, 8 }, // RES 4, D |
| { &opcode_cb_a3, 8 }, // RES 4, E |
| { &opcode_cb_a4, 8 }, // RES 4, H |
| { &opcode_cb_a5, 8 }, // RES 4, L |
| { &opcode_cb_a6, 15 }, // RES 4, (HL) |
| { &opcode_cb_a7, 8 }, // RES 4, A |
| { &opcode_cb_a8, 8 }, // RES 5, B |
| { &opcode_cb_a9, 8 }, // RES 5, C |
| { &opcode_cb_aa, 8 }, // RES 5, D |
| { &opcode_cb_ab, 8 }, // RES 5, E |
| { &opcode_cb_ac, 8 }, // RES 5, H |
| { &opcode_cb_ad, 8 }, // RES 5, L |
| { &opcode_cb_ae, 15 }, // RES 5, (HL) |
| { &opcode_cb_af, 8 }, // RES 5, A |
| { &opcode_cb_b0, 8 }, // RES 6, B |
| { &opcode_cb_b1, 8 }, // RES 6, C |
| { &opcode_cb_b2, 8 }, // RES 6, D |
| { &opcode_cb_b3, 8 }, // RES 6, E |
| { &opcode_cb_b4, 8 }, // RES 6, H |
| { &opcode_cb_b5, 8 }, // RES 6, L |
| { &opcode_cb_b6, 15 }, // RES 6, (HL) |
| { &opcode_cb_b7, 8 }, // RES 6, A |
| { &opcode_cb_b8, 8 }, // RES 7, B |
| { &opcode_cb_b9, 8 }, // RES 7, C |
| { &opcode_cb_ba, 8 }, // RES 7, D |
| { &opcode_cb_bb, 8 }, // RES 7, E |
| { &opcode_cb_bc, 8 }, // RES 7, H |
| { &opcode_cb_bd, 8 }, // RES 7, L |
| { &opcode_cb_be, 15 }, // RES 7, (HL) |
| { &opcode_cb_bf, 8 }, // RES 7, A |
| { &opcode_cb_c0, 8 }, // SET 0, B |
| { &opcode_cb_c1, 8 }, // SET 0, C |
| { &opcode_cb_c2, 8 }, // SET 0, D |
| { &opcode_cb_c3, 8 }, // SET 0, E |
| { &opcode_cb_c4, 8 }, // SET 0, H |
| { &opcode_cb_c5, 8 }, // SET 0, L |
| { &opcode_cb_c6, 15 }, // SET 0, (HL) |
| { &opcode_cb_c7, 8 }, // SET 0, A |
| { &opcode_cb_c8, 8 }, // SET 1, B |
| { &opcode_cb_c9, 8 }, // SET 1, C |
| { &opcode_cb_ca, 8 }, // SET 1, D |
| { &opcode_cb_cb, 8 }, // SET 1, E |
| { &opcode_cb_cc, 8 }, // SET 1, H |
| { &opcode_cb_cd, 8 }, // SET 1, L |
| { &opcode_cb_ce, 15 }, // SET 1, (HL) |
| { &opcode_cb_cf, 8 }, // SET 1, A |
| { &opcode_cb_d0, 8 }, // SET 2, B |
| { &opcode_cb_d1, 8 }, // SET 2, C |
| { &opcode_cb_d2, 8 }, // SET 2, D |
| { &opcode_cb_d3, 8 }, // SET 2, E |
| { &opcode_cb_d4, 8 }, // SET 2, H |
| { &opcode_cb_d5, 8 }, // SET 2, L |
| { &opcode_cb_d6, 15 }, // SET 2, (HL) |
| { &opcode_cb_d7, 8 }, // SET 2, A |
| { &opcode_cb_d8, 8 }, // SET 3, B |
| { &opcode_cb_d9, 8 }, // SET 3, C |
| { &opcode_cb_da, 8 }, // SET 3, D |
| { &opcode_cb_db, 8 }, // SET 3, E |
| { &opcode_cb_dc, 8 }, // SET 3, H |
| { &opcode_cb_dd, 8 }, // SET 3, L |
| { &opcode_cb_de, 15 }, // SET 3, (HL) |
| { &opcode_cb_df, 8 }, // SET 3, A |
| { &opcode_cb_e0, 8 }, // SET 4, B |
| { &opcode_cb_e1, 8 }, // SET 4, C |
| { &opcode_cb_e2, 8 }, // SET 4, D |
| { &opcode_cb_e3, 8 }, // SET 4, E |
| { &opcode_cb_e4, 8 }, // SET 4, H |
| { &opcode_cb_e5, 8 }, // SET 4, L |
| { &opcode_cb_e6, 15 }, // SET 4, (HL) |
| { &opcode_cb_e7, 8 }, // SET 4, A |
| { &opcode_cb_e8, 8 }, // SET 5, B |
| { &opcode_cb_e9, 8 }, // SET 5, C |
| { &opcode_cb_ea, 8 }, // SET 5, D |
| { &opcode_cb_eb, 8 }, // SET 5, E |
| { &opcode_cb_ec, 8 }, // SET 5, H |
| { &opcode_cb_ed, 8 }, // SET 5, L |
| { &opcode_cb_ee, 15 }, // SET 5, (HL) |
| { &opcode_cb_ef, 8 }, // SET 5, A |
| { &opcode_cb_f0, 8 }, // SET 6, B |
| { &opcode_cb_f1, 8 }, // SET 6, C |
| { &opcode_cb_f2, 8 }, // SET 6, D |
| { &opcode_cb_f3, 8 }, // SET 6, E |
| { &opcode_cb_f4, 8 }, // SET 6, H |
| { &opcode_cb_f5, 8 }, // SET 6, L |
| { &opcode_cb_f6, 15 }, // SET 6, (HL) |
| { &opcode_cb_f7, 8 }, // SET 6, A |
| { &opcode_cb_f8, 8 }, // SET 7, B |
| { &opcode_cb_f9, 8 }, // SET 7, C |
| { &opcode_cb_fa, 8 }, // SET 7, D |
| { &opcode_cb_fb, 8 }, // SET 7, E |
| { &opcode_cb_fc, 8 }, // SET 7, H |
| { &opcode_cb_fd, 8 }, // SET 7, L |
| { &opcode_cb_fe, 15 }, // SET 7, (HL) |
| { &opcode_cb_ff, 8 } // SET 7, A |
| }; |
| |
| void opcode_cb_00() // RLC B |
| { |
| B = rotateLeftCarry( B ); |
| } |
| |
| void opcode_cb_01() // RLC C |
| { |
| C = rotateLeftCarry( C ); |
| } |
| |
| void opcode_cb_02() // RLC D |
| { |
| D = rotateLeftCarry( D ); |
| } |
| |
| void opcode_cb_03() // RLC E |
| { |
| E = rotateLeftCarry( E ); |
| } |
| |
| void opcode_cb_04() // RLC H |
| { |
| H = rotateLeftCarry( H ); |
| } |
| |
| void opcode_cb_05() // RLC L |
| { |
| L = rotateLeftCarry( L ); |
| } |
| |
| void opcode_cb_06() // RLC (HL) |
| { |
| writeByte( HL(), rotateLeftCarry( readByte( HL() ) ) ); |
| } |
| |
| void opcode_cb_07() // RLC A |
| { |
| A = rotateLeftCarry( A ); |
| } |
| |
| void opcode_cb_08() // RRC B |
| { |
| B = rotateRightCarry( B ); |
| } |
| |
| void opcode_cb_09() // RRC C |
| { |
| C = rotateLeftCarry( C ); |
| } |
| |
| void opcode_cb_0a() // RRC D |
| { |
| D = rotateLeftCarry( D ); |
| } |
| |
| void opcode_cb_0b() // RRC E |
| { |
| E = rotateLeftCarry( E ); |
| } |
| |
| void opcode_cb_0c() // RRC H |
| { |
| H = rotateLeftCarry( H ); |
| } |
| |
| void opcode_cb_0d() // RRC L |
| { |
| L = rotateLeftCarry( L ); |
| } |
| |
| void opcode_cb_0e() // RRC (HL) |
| { |
| writeByte( HL(), rotateRightCarry( readByte( HL() ) ) ); |
| } |
| |
| void opcode_cb_0f() // RRC A |
| { |
| A = rotateLeftCarry( A ); |
| } |
| |
| void opcode_cb_10() // RL B |
| { |
| B = rotateLeft( B ); |
| } |
| |
| void opcode_cb_11() // RL C |
| { |
| C = rotateLeft( C ); |
| } |
| |
| void opcode_cb_12() // RL D |
| { |
| D = rotateLeft( D ); |
| } |
| |
| void opcode_cb_13() // RL E |
| { |
| E = rotateLeft( E ); |
| } |
| |
| void opcode_cb_14() // RL H |
| { |
| H = rotateLeft( H ); |
| } |
| |
| void opcode_cb_15() // RL L |
| { |
| L = rotateLeft( L ); |
| } |
| |
| void opcode_cb_16() // RL (HL) |
| { |
| writeByte( HL(), rotateLeft( readByte( HL() ) ) ); |
| } |
| |
| void opcode_cb_17() // RL A |
| { |
| A = rotateLeft( A ); |
| } |
| |
| void opcode_cb_18() // RR B |
| { |
| B = rotateRight( B ); |
| } |
| |
| void opcode_cb_19() // RR C |
| { |
| C = rotateRight( C ); |
| } |
| |
| void opcode_cb_1a() // RR D |
| { |
| D = rotateRight( D ); |
| } |
| |
| void opcode_cb_1b() // RR E |
| { |
| E = rotateRight( E ); |
| } |
| |
| void opcode_cb_1c() // RR H |
| { |
| H = rotateRight( H ); |
| } |
| |
| void opcode_cb_1d() // RR L |
| { |
| L = rotateRight( L ); |
| } |
| |
| void opcode_cb_1e() // RR (HL) |
| { |
| writeByte( HL(), rotateRight( readByte( HL() ) ) ); |
| } |
| |
| void opcode_cb_1f() // RR A |
| { |
| A = rotateRight( A ); |
| } |
| |
| void opcode_cb_20() // SLA B |
| { |
| B = shiftLeft( B ); |
| } |
| |
| void opcode_cb_21() // SLA C |
| { |
| C = shiftLeft( C ); |
| } |
| |
| void opcode_cb_22() // SLA D |
| { |
| D = shiftLeft( D ); |
| } |
| |
| void opcode_cb_23() // SLA E |
| { |
| E = shiftLeft( E ); |
| } |
| |
| void opcode_cb_24() // SLA H |
| { |
| H = shiftLeft( H ); |
| } |
| |
| void opcode_cb_25() // SLA L |
| { |
| L = shiftLeft( L ); |
| } |
| |
| void opcode_cb_26() // SLA (HL) |
| { |
| writeByte( HL(), shiftLeft( readByte( HL() ) ) ); |
| } |
| |
| void opcode_cb_27() // SLA A |
| { |
| A = shiftLeft( A ); |
| } |
| |
| void opcode_cb_28() // SRA B |
| { |
| B = shiftRightArith( B ); |
| } |
| |
| void opcode_cb_29() // SRA C |
| { |
| C = shiftRightArith( C ); |
| } |
| |
| void opcode_cb_2a() // SRA D |
| { |
| D = shiftRightArith( D ); |
| } |
| |
| void opcode_cb_2b() // SRA E |
| { |
| E = shiftRightArith( E ); |
| } |
| |
| void opcode_cb_2c() // SRA H |
| { |
| H = shiftRightArith( H ); |
| } |
| |
| void opcode_cb_2d() // SRA L |
| { |
| L = shiftRightArith( L ); |
| } |
| |
| void opcode_cb_2e() // SRA (HL) |
| { |
| writeByte( HL(), shiftRightArith( readByte( HL() ) ) ); |
| } |
| |
| void opcode_cb_2f() // SRA A |
| { |
| A = shiftRightArith( A ); |
| } |
| |
| void opcode_cb_30() // SLL B |
| { |
| B = shiftLeft( B ) | 0x01; |
| } |
| |
| void opcode_cb_31() // SLL C |
| { |
| C = shiftLeft( C ) | 0x01; |
| } |
| |
| void opcode_cb_32() // SLL D |
| { |
| D = shiftLeft( D ) | 0x01; |
| } |
| |
| void opcode_cb_33() // SLL E |
| { |
| E = shiftLeft( E ) | 0x01; |
| } |
| |
| void opcode_cb_34() // SLL H |
| { |
| H = shiftLeft( H ) | 0x01; |
| } |
| |
| void opcode_cb_35() // SLL L |
| { |
| L = shiftLeft( L ) | 0x01; |
| } |
| |
| void opcode_cb_36() // SLL (HL) |
| { |
| writeByte( HL(), shiftLeft( readByte( HL() ) ) | 0x01 ); |
| } |
| |
| void opcode_cb_37() // SLL A |
| { |
| A = shiftLeft( A ) | 0x01; |
| } |
| |
| void opcode_cb_38() // SRL B |
| { |
| B = shiftRightLogical( B ); |
| } |
| |
| void opcode_cb_39() // SRL C |
| { |
| C = shiftRightLogical( C ); |
| } |
| |
| void opcode_cb_3a() // SRL D |
| { |
| D = shiftRightLogical( D ); |
| } |
| |
| void opcode_cb_3b() // SRL E |
| { |
| E = shiftRightLogical( E ); |
| } |
| |
| void opcode_cb_3c() // SRL H |
| { |
| H = shiftRightLogical( H ); |
| } |
| |
| void opcode_cb_3d() // SRL L |
| { |
| L = shiftRightLogical( L ); |
| } |
| |
| void opcode_cb_3e() // SRL (HL) |
| { |
| writeByte( HL(), shiftRightLogical( readByte( HL() ) ) ); |
| } |
| |
| void opcode_cb_3f() // SRL A |
| { |
| A = shiftRightLogical( A ); |
| } |
| |
| void opcode_cb_40() // BIT 0, B |
| { |
| testBit( 0, B ); |
| } |
| |
| void opcode_cb_41() // BIT 0, C |
| { |
| testBit( 0, C ); |
| } |
| |
| void opcode_cb_42() // BIT 0, D |
| { |
| testBit( 0, D ); |
| } |
| |
| void opcode_cb_43() // BIT 0, E |
| { |
| testBit( 0, E ); |
| } |
| |
| void opcode_cb_44() // BIT 0, H |
| { |
| testBit( 0, H ); |
| } |
| |
| void opcode_cb_45() // BIT 0, L |
| { |
| testBit( 0, L ); |
| } |
| |
| void opcode_cb_46() // BIT 0, (HL) |
| { |
| testBit( 0, readByte( HL() ) ); |
| } |
| |
| void opcode_cb_47() // BIT 0, A |
| { |
| testBit( 0, A ); |
| } |
| |
| void opcode_cb_48() // BIT 1, B |
| { |
| testBit( 1, B ); |
| } |
| |
| void opcode_cb_49() // BIT 1, C |
| { |
| testBit( 1, C ); |
| } |
| |
| void opcode_cb_4a() // BIT 1, D |
| { |
| testBit( 1, D ); |
| } |
| |
| void opcode_cb_4b() // BIT 1, E |
| { |
| testBit( 1, E ); |
| } |
| |
| void opcode_cb_4c() // BIT 1, H |
| { |
| testBit( 1, H ); |
| } |
| |
| void opcode_cb_4d() // BIT 1, L |
| { |
| testBit( 1, L ); |
| } |
| |
| void opcode_cb_4e() // BIT 1, (HL) |
| { |
| testBit( 1, readByte( HL() ) ); |
| } |
| |
| void opcode_cb_4f() // BIT 1, A |
| { |
| testBit( 1, A ); |
| } |
| |
| void opcode_cb_50() // BIT 2, B |
| { |
| testBit( 2, B ); |
| } |
| |
| void opcode_cb_51() // BIT 2, C |
| { |
| testBit( 2, C ); |
| } |
| |
| void opcode_cb_52() // BIT 2, D |
| { |
| testBit( 2, D ); |
| } |
| |
| void opcode_cb_53() // BIT 2, E |
| { |
| testBit( 2, E ); |
| } |
| |
| void opcode_cb_54() // BIT 2, H |
| { |
| testBit( 2, H ); |
| } |
| |
| void opcode_cb_55() // BIT 2, L |
| { |
| testBit( 2, L ); |
| } |
| |
| void opcode_cb_56() // BIT 2, (HL) |
| { |
| testBit( 2, readByte( HL() ) ); |
| } |
| |
| void opcode_cb_57() // BIT 2, A |
| { |
| testBit( 2, A ); |
| } |
| |
| void opcode_cb_58() // BIT 3, B |
| { |
| testBit( 3, B ); |
| } |
| |
| void opcode_cb_59() // BIT 3, C |
| { |
| testBit( 3, C ); |
| } |
| |
| void opcode_cb_5a() // BIT 3, D |
| { |
| testBit( 3, D ); |
| } |
| |
| void opcode_cb_5b() // BIT 3, E |
| { |
| testBit( 3, E ); |
| } |
| |
| void opcode_cb_5c() // BIT 3, H |
| { |
| testBit( 3, H ); |
| } |
| |
| void opcode_cb_5d() // BIT 3, L |
| { |
| testBit( 3, L ); |
| } |
| |
| void opcode_cb_5e() // BIT 3, (HL) |
| { |
| testBit( 3, readByte( HL() ) ); |
| } |
| |
| void opcode_cb_5f() // BIT 3, A |
| { |
| testBit( 3, A ); |
| } |
| |
| void opcode_cb_60() // BIT 4, B |
| { |
| testBit( 4, B ); |
| } |
| |
| void opcode_cb_61() // BIT 4, C |
| { |
| testBit( 4, C ); |
| } |
| |
| void opcode_cb_62() // BIT 4, D |
| { |
| testBit( 4, D ); |
| } |
| |
| void opcode_cb_63() // BIT 4, E |
| { |
| testBit( 4, E ); |
| } |
| |
| void opcode_cb_64() // BIT 4, H |
| { |
| testBit( 4, H ); |
| } |
| |
| void opcode_cb_65() // BIT 4, L |
| { |
| testBit( 4, L ); |
| } |
| |
| void opcode_cb_66() // BIT 4, (HL) |
| { |
| testBit( 4, readByte( HL() ) ); |
| } |
| |
| void opcode_cb_67() // BIT 4, A |
| { |
| testBit( 4, A ); |
| } |
| |
| void opcode_cb_68() // BIT 5, B |
| { |
| testBit( 5, B ); |
| } |
| |
| void opcode_cb_69() // BIT 5, C |
| { |
| testBit( 5, C ); |
| } |
| |
| void opcode_cb_6a() // BIT 5, D |
| { |
| testBit( 5, D ); |
| } |
| |
| void opcode_cb_6b() // BIT 5, E |
| { |
| testBit( 5, E ); |
| } |
| |
| void opcode_cb_6c() // BIT 5, H |
| { |
| testBit( 5, H ); |
| } |
| |
| void opcode_cb_6d() // BIT 5, L |
| { |
| testBit( 5, L ); |
| } |
| |
| void opcode_cb_6e() // BIT 5, (HL) |
| { |
| testBit( 5, readByte( HL() ) ); |
| } |
| |
| void opcode_cb_6f() // BIT 5, A |
| { |
| testBit( 5, A ); |
| } |
| |
| void opcode_cb_70() // BIT 6, B |
| { |
| testBit( 6, B ); |
| } |
| |
| void opcode_cb_71() // BIT 6, C |
| { |
| testBit( 6, C ); |
| } |
| |
| void opcode_cb_72() // BIT 6, D |
| { |
| testBit( 6, D ); |
| } |
| |
| void opcode_cb_73() // BIT 6, E |
| { |
| testBit( 6, E ); |
| } |
| |
| void opcode_cb_74() // BIT 6, H |
| { |
| testBit( 6, H ); |
| } |
| |
| void opcode_cb_75() // BIT 6, L |
| { |
| testBit( 6, L ); |
| } |
| |
| void opcode_cb_76() // BIT 6, (HL) |
| { |
| testBit( 6, readByte( HL() ) ); |
| } |
| |
| void opcode_cb_77() // BIT 6, A |
| { |
| testBit( 6, A ); |
| } |
| |
| void opcode_cb_78() // BIT 7, B |
| { |
| testBit( 7, B ); |
| } |
| |
| void opcode_cb_79() // BIT 7, C |
| { |
| testBit( 7, C ); |
| } |
| |
| void opcode_cb_7a() // BIT 7, D |
| { |
| testBit( 7, D ); |
| } |
| |
| void opcode_cb_7b() // BIT 7, E |
| { |
| testBit( 7, E ); |
| } |
| |
| void opcode_cb_7c() // BIT 7, H |
| { |
| testBit( 7, H ); |
| } |
| |
| void opcode_cb_7d() // BIT 7, L |
| { |
| testBit( 7, L ); |
| } |
| |
| void opcode_cb_7e() // BIT 7, (HL) |
| { |
| testBit( 7, readByte( HL() ) ); |
| } |
| |
| void opcode_cb_7f() // BIT 7, A |
| { |
| testBit( 7, A ); |
| } |
| |
| void opcode_cb_80() // RES 0, B |
| { |
| B &= ~(unsigned char) (1 << 0); |
| } |
| |
| void opcode_cb_81() // RES 0, C |
| { |
| C &= ~(unsigned char) (1 << 0); |
| } |
| |
| void opcode_cb_82() // RES 0, D |
| { |
| D &= ~(unsigned char) (1 << 0); |
| } |
| |
| void opcode_cb_83() // RES 0, E |
| { |
| E &= ~(unsigned char) (1 << 0); |
| } |
| |
| void opcode_cb_84() // RES 0, H |
| { |
| H &= ~(unsigned char) (1 << 0); |
| } |
| |
| void opcode_cb_85() // RES 0, L |
| { |
| L &= ~(unsigned char) (1 << 0); |
| } |
| |
| void opcode_cb_86() // RES 0, (HL) |
| { |
| writeByte( HL(), readByte( HL() ) & (unsigned char) ~(unsigned char) (1 << 0) ); |
| } |
| |
| void opcode_cb_87() // RES 0, A |
| { |
| A &= ~(unsigned char) (1 << 0); |
| } |
| |
| void opcode_cb_88() // RES 1, B |
| { |
| B &= ~(unsigned char) (1 << 1); |
| } |
| |
| void opcode_cb_89() // RES 1, C |
| { |
| C &= ~(unsigned char) (1 << 1); |
| } |
| |
| void opcode_cb_8a() // RES 1, D |
| { |
| D &= ~(unsigned char) (1 << 1); |
| } |
| |
| void opcode_cb_8b() // RES 1, E |
| { |
| E &= ~(unsigned char) (1 << 1); |
| } |
| |
| void opcode_cb_8c() // RES 1, H |
| { |
| H &= ~(unsigned char) (1 << 1); |
| } |
| |
| void opcode_cb_8d() // RES 1, L |
| { |
| L &= ~(unsigned char) (1 << 1); |
| } |
| |
| void opcode_cb_8e() // RES 1, (HL) |
| { |
| writeByte( HL(), readByte( HL() ) & (unsigned char) ~(unsigned char) (1 << 1) ); |
| } |
| |
| void opcode_cb_8f() // RES 1, A |
| { |
| A &= ~(unsigned char) (1 << 1); |
| } |
| |
| void opcode_cb_90() // RES 2, B |
| { |
| B &= ~(unsigned char) (1 << 2); |
| } |
| |
| void opcode_cb_91() // RES 2, C |
| { |
| C &= ~(unsigned char) (1 << 2); |
| } |
| |
| void opcode_cb_92() // RES 2, D |
| { |
| D &= ~(unsigned char) (1 << 2); |
| } |
| |
| void opcode_cb_93() // RES 2, E |
| { |
| E &= ~(unsigned char) (1 << 2); |
| } |
| |
| void opcode_cb_94() // RES 2, H |
| { |
| H &= ~(unsigned char) (1 << 2); |
| } |
| |
| void opcode_cb_95() // RES 2, L |
| { |
| L &= ~(unsigned char) (1 << 2); |
| } |
| |
| void opcode_cb_96() // RES 2, (HL) |
| { |
| writeByte( HL(), readByte( HL() ) & (unsigned char) ~(unsigned char) (1 << 2) ); |
| } |
| |
| void opcode_cb_97() // RES 2, A |
| { |
| A &= ~(unsigned char) (1 << 2); |
| } |
| |
| void opcode_cb_98() // RES 3, B |
| { |
| B &= ~(unsigned char) (1 << 3); |
| } |
| |
| void opcode_cb_99() // RES 3, C |
| { |
| C &= ~(unsigned char) (1 << 3); |
| } |
| |
| void opcode_cb_9a() // RES 3, D |
| { |
| D &= ~(unsigned char) (1 << 3); |
| } |
| |
| void opcode_cb_9b() // RES 3, E |
| { |
| E &= ~(unsigned char) (1 << 3); |
| } |
| |
| void opcode_cb_9c() // RES 3, H |
| { |
| H &= ~(unsigned char) (1 << 3); |
| } |
| |
| void opcode_cb_9d() // RES 3, L |
| { |
| L &= ~(unsigned char) (1 << 3); |
| } |
| |
| void opcode_cb_9e() // RES 3, (HL) |
| { |
| writeByte( HL(), readByte( HL() ) & (unsigned char) ~(unsigned char) (1 << 3) ); |
| } |
| |
| void opcode_cb_9f() // RES 3, A |
| { |
| A &= ~(unsigned char) (1 << 3); |
| } |
| |
| void opcode_cb_a0() // RES 4, B |
| { |
| B &= ~(unsigned char) (1 << 4); |
| } |
| |
| void opcode_cb_a1() // RES 4, C |
| { |
| C &= ~(unsigned char) (1 << 4); |
| } |
| |
| void opcode_cb_a2() // RES 4, D |
| { |
| D &= ~(unsigned char) (1 << 4); |
| } |
| |
| void opcode_cb_a3() // RES 4, E |
| { |
| E &= ~(unsigned char) (1 << 4); |
| } |
| |
| void opcode_cb_a4() // RES 4, H |
| { |
| H &= ~(unsigned char) (1 << 4); |
| } |
| |
| void opcode_cb_a5() // RES 4, L |
| { |
| L &= ~(unsigned char) (1 << 4); |
| } |
| |
| void opcode_cb_a6() // RES 4, (HL) |
| { |
| writeByte( HL(), readByte( HL() ) & (unsigned char) ~(unsigned char) (1 << 4) ); |
| } |
| |
| void opcode_cb_a7() // RES 4, A |
| { |
| A &= ~(unsigned char) (1 << 4); |
| } |
| |
| void opcode_cb_a8() // RES 5, B |
| { |
| B &= ~(unsigned char) (1 << 5); |
| } |
| |
| void opcode_cb_a9() // RES 5, C |
| { |
| C &= ~(unsigned char) (1 << 5); |
| } |
| |
| void opcode_cb_aa() // RES 5, D |
| { |
| D &= ~(unsigned char) (1 << 5); |
| } |
| |
| void opcode_cb_ab() // RES 5, E |
| { |
| E &= ~(unsigned char) (1 << 5); |
| } |
| |
| void opcode_cb_ac() // RES 5, H |
| { |
| H &= ~(unsigned char) (1 << 5); |
| } |
| |
| void opcode_cb_ad() // RES 5, L |
| { |
| L &= ~(unsigned char) (1 << 5); |
| } |
| |
| void opcode_cb_ae() // RES 5, (HL) |
| { |
| writeByte( HL(), readByte( HL() ) & (unsigned char) ~(unsigned char) (1 << 5) ); |
| } |
| |
| void opcode_cb_af() // RES 5, A |
| { |
| A &= ~(unsigned char) (1 << 5); |
| } |
| |
| void opcode_cb_b0() // RES 6, B |
| { |
| B &= ~(unsigned char) (1 << 6); |
| } |
| |
| void opcode_cb_b1() // RES 6, C |
| { |
| C &= ~(unsigned char) (1 << 6); |
| } |
| |
| void opcode_cb_b2() // RES 6, D |
| { |
| D &= ~(unsigned char) (1 << 6); |
| } |
| |
| void opcode_cb_b3() // RES 6, E |
| { |
| E &= ~(unsigned char) (1 << 6); |
| } |
| |
| void opcode_cb_b4() // RES 6, H |
| { |
| H &= ~(unsigned char) (1 << 6); |
| } |
| |
| void opcode_cb_b5() // RES 6, L |
| { |
| L &= ~(unsigned char) (1 << 6); |
| } |
| |
| void opcode_cb_b6() // RES 6, (HL) |
| { |
| writeByte( HL(), readByte( HL() ) & (unsigned char) ~(unsigned char) (1 << 6) ); |
| } |
| |
| void opcode_cb_b7() // RES 6, A |
| { |
| A &= ~(unsigned char) (1 << 6); |
| } |
| |
| void opcode_cb_b8() // RES 7, B |
| { |
| B &= ~(unsigned char) (1 << 7); |
| } |
| |
| void opcode_cb_b9() // RES 7, C |
| { |
| C &= ~(unsigned char) (1 << 7); |
| } |
| |
| void opcode_cb_ba() // RES 7, D |
| { |
| D &= ~(unsigned char) (1 << 7); |
| } |
| |
| void opcode_cb_bb() // RES 7, E |
| { |
| E &= ~(unsigned char) (1 << 7); |
| } |
| |
| void opcode_cb_bc() // RES 7, H |
| { |
| H &= ~(unsigned char) (1 << 7); |
| } |
| |
| void opcode_cb_bd() // RES 7, L |
| { |
| L &= ~(unsigned char) (1 << 7); |
| } |
| |
| void opcode_cb_be() // RES 7, (HL) |
| { |
| writeByte( HL(), readByte( HL() ) & (unsigned char) ~(unsigned char) (1 << 7) ); |
| } |
| |
| void opcode_cb_bf() // RES 7, A |
| { |
| A &= ~(unsigned char) (1 << 7); |
| } |
| |
| void opcode_cb_c0() // SET 0, B |
| { |
| B |= (unsigned char) (1 << 0); |
| } |
| |
| void opcode_cb_c1() // SET 0, C |
| { |
| C |= (unsigned char) (1 << 0); |
| } |
| |
| void opcode_cb_c2() // SET 0, D |
| { |
| D |= (unsigned char) (1 << 0); |
| } |
| |
| void opcode_cb_c3() // SET 0, E |
| { |
| E |= (unsigned char) (1 << 0); |
| } |
| |
| void opcode_cb_c4() // SET 0, H |
| { |
| H |= (unsigned char) (1 << 0); |
| } |
| |
| void opcode_cb_c5() // SET 0, L |
| { |
| L |= (unsigned char) (1 << 0); |
| } |
| |
| void opcode_cb_c6() // SET 0, (HL) |
| { |
| writeByte( HL(), readByte( HL() ) | (unsigned char) (1 << 0) ); |
| } |
| |
| void opcode_cb_c7() // SET 0, A |
| { |
| A |= (unsigned char) (1 << 0); |
| } |
| |
| void opcode_cb_c8() // SET 1, B |
| { |
| B |= (unsigned char) (1 << 1); |
| } |
| |
| void opcode_cb_c9() // SET 1, C |
| { |
| C |= (unsigned char) (1 << 1); |
| } |
| |
| void opcode_cb_ca() // SET 1, D |
| { |
| D |= (unsigned char) (1 << 1); |
| } |
| |
| void opcode_cb_cb() // SET 1, E |
| { |
| E |= (unsigned char) (1 << 1); |
| } |
| |
| void opcode_cb_cc() // SET 1, H |
| { |
| H |= (unsigned char) (1 << 1); |
| } |
| |
| void opcode_cb_cd() // SET 1, L |
| { |
| L |= (unsigned char) (1 << 1); |
| } |
| |
| void opcode_cb_ce() // SET 1, (HL) |
| { |
| writeByte( HL(), readByte( HL() ) | (unsigned char) (1 << 1) ); |
| } |
| |
| void opcode_cb_cf() // SET 1, A |
| { |
| A |= (unsigned char) (1 << 1); |
| } |
| |
| void opcode_cb_d0() // SET 2, B |
| { |
| B |= (unsigned char) (1 << 2); |
| } |
| |
| void opcode_cb_d1() // SET 2, C |
| { |
| C |= (unsigned char) (1 << 2); |
| } |
| |
| void opcode_cb_d2() // SET 2, D |
| { |
| D |= (unsigned char) (1 << 2); |
| } |
| |
| void opcode_cb_d3() // SET 2, E |
| { |
| E |= (unsigned char) (1 << 2); |
| } |
| |
| void opcode_cb_d4() // SET 2, H |
| { |
| H |= (unsigned char) (1 << 2); |
| } |
| |
| void opcode_cb_d5() // SET 2, L |
| { |
| L |= (unsigned char) (1 << 2); |
| } |
| |
| void opcode_cb_d6() // SET 2, (HL) |
| { |
| writeByte( HL(), readByte( HL() ) | (unsigned char) (1 << 2) ); |
| } |
| |
| void opcode_cb_d7() // SET 2, A |
| { |
| A |= (unsigned char) (1 << 2); |
| } |
| |
| void opcode_cb_d8() // SET 3, B |
| { |
| B |= (unsigned char) (1 << 3); |
| } |
| |
| void opcode_cb_d9() // SET 3, C |
| { |
| C |= (unsigned char) (1 << 3); |
| } |
| |
| void opcode_cb_da() // SET 3, D |
| { |
| D |= (unsigned char) (1 << 3); |
| } |
| |
| void opcode_cb_db() // SET 3, E |
| { |
| E |= (unsigned char) (1 << 3); |
| } |
| |
| void opcode_cb_dc() // SET 3, H |
| { |
| H |= (unsigned char) (1 << 3); |
| } |
| |
| void opcode_cb_dd() // SET 3, L |
| { |
| L |= (unsigned char) (1 << 3); |
| } |
| |
| void opcode_cb_de() // SET 3, (HL) |
| { |
| writeByte( HL(), readByte( HL() ) | (unsigned char) (1 << 3) ); |
| } |
| |
| void opcode_cb_df() // SET 3, A |
| { |
| A |= (unsigned char) (1 << 3); |
| } |
| |
| void opcode_cb_e0() // SET 4, B |
| { |
| B |= (unsigned char) (1 << 4); |
| } |
| |
| void opcode_cb_e1() // SET 4, C |
| { |
| C |= (unsigned char) (1 << 4); |
| } |
| |
| void opcode_cb_e2() // SET 4, D |
| { |
| D |= (unsigned char) (1 << 4); |
| } |
| |
| void opcode_cb_e3() // SET 4, E |
| { |
| E |= (unsigned char) (1 << 4); |
| } |
| |
| void opcode_cb_e4() // SET 4, H |
| { |
| H |= (unsigned char) (1 << 4); |
| } |
| |
| void opcode_cb_e5() // SET 4, L |
| { |
| L |= (unsigned char) (1 << 4); |
| } |
| |
| void opcode_cb_e6() // SET 4, (HL) |
| { |
| writeByte( HL(), readByte( HL() ) | (unsigned char) (1 << 4) ); |
| } |
| |
| void opcode_cb_e7() // SET 4, A |
| { |
| A |= (unsigned char) (1 << 4); |
| } |
| |
| void opcode_cb_e8() // SET 5, B |
| { |
| B |= (unsigned char) (1 << 5); |
| } |
| |
| void opcode_cb_e9() // SET 5, C |
| { |
| C |= (unsigned char) (1 << 5); |
| } |
| |
| void opcode_cb_ea() // SET 5, D |
| { |
| D |= (unsigned char) (1 << 5); |
| } |
| |
| void opcode_cb_eb() // SET 5, E |
| { |
| E |= (unsigned char) (1 << 5); |
| } |
| |
| void opcode_cb_ec() // SET 5, H |
| { |
| H |= (unsigned char) (1 << 5); |
| } |
| |
| void opcode_cb_ed() // SET 5, L |
| { |
| L |= (unsigned char) (1 << 5); |
| } |
| |
| void opcode_cb_ee() // SET 5, (HL) |
| { |
| writeByte( HL(), readByte( HL() ) | (unsigned char) (1 << 5) ); |
| } |
| |
| void opcode_cb_ef() // SET 5, A |
| { |
| A |= (unsigned char) (1 << 5); |
| } |
| |
| void opcode_cb_f0() // SET 6, B |
| { |
| B |= (unsigned char) (1 << 6); |
| } |
| |
| void opcode_cb_f1() // SET 6, C |
| { |
| C |= (unsigned char) (1 << 6); |
| } |
| |
| void opcode_cb_f2() // SET 6, D |
| { |
| D |= (unsigned char) (1 << 6); |
| } |
| |
| void opcode_cb_f3() // SET 6, E |
| { |
| E |= (unsigned char) (1 << 6); |
| } |
| |
| void opcode_cb_f4() // SET 6, H |
| { |
| H |= (unsigned char) (1 << 6); |
| } |
| |
| void opcode_cb_f5() // SET 6, L |
| { |
| L |= (unsigned char) (1 << 6); |
| } |
| |
| void opcode_cb_f6() // SET 6, (HL) |
| { |
| writeByte( HL(), readByte( HL() ) | (unsigned char) (1 << 6) ); |
| } |
| |
| void opcode_cb_f7() // SET 6, A |
| { |
| A |= (unsigned char) (1 << 6); |
| } |
| |
| void opcode_cb_f8() // SET 7, B |
| { |
| B |= (unsigned char) (1 << 7); |
| } |
| |
| void opcode_cb_f9() // SET 7, C |
| { |
| C |= (unsigned char) (1 << 7); |
| } |
| |
| void opcode_cb_fa() // SET 7, D |
| { |
| D |= (unsigned char) (1 << 7); |
| } |
| |
| void opcode_cb_fb() // SET 7, E |
| { |
| E |= (unsigned char) (1 << 7); |
| } |
| |
| void opcode_cb_fc() // SET 7, H |
| { |
| H |= (unsigned char) (1 << 7); |
| } |
| |
| void opcode_cb_fd() // SET 7, L |
| { |
| L |= (unsigned char) (1 << 7); |
| } |
| |
| void opcode_cb_fe() // SET 7, (HL) |
| { |
| writeByte( HL(), readByte( HL() ) | (unsigned char) (1 << 7) ); |
| } |
| |
| void opcode_cb_ff() // SET 7, A |
| { |
| A |= (unsigned char) (1 << 7); |
| } |
| |
| OpcodeInfo OpInfoDD_[256] = { |
| { 0, 0 }, // 0x00 |
| { 0, 0 }, // 0x01 |
| { 0, 0 }, // 0x02 |
| { 0, 0 }, // 0x03 |
| { 0, 0 }, // 0x04 |
| { 0, 0 }, // 0x05 |
| { 0, 0 }, // 0x06 |
| { 0, 0 }, // 0x07 |
| { 0, 0 }, // 0x08 |
| { &opcode_dd_09, 15 }, // ADD IX, BC |
| { 0, 0 }, // 0x0A |
| { 0, 0 }, // 0x0B |
| { 0, 0 }, // 0x0C |
| { 0, 0 }, // 0x0D |
| { 0, 0 }, // 0x0E |
| { 0, 0 }, // 0x0F |
| { 0, 0 }, // 0x10 |
| { 0, 0 }, // 0x11 |
| { 0, 0 }, // 0x12 |
| { 0, 0 }, // 0x13 |
| { 0, 0 }, // 0x14 |
| { 0, 0 }, // 0x15 |
| { 0, 0 }, // 0x16 |
| { 0, 0 }, // 0x17 |
| { 0, 0 }, // 0x18 |
| { &opcode_dd_19, 15 }, // ADD IX, DE |
| { 0, 0 }, // 0x1A |
| { 0, 0 }, // 0x1B |
| { 0, 0 }, // 0x1C |
| { 0, 0 }, // 0x1D |
| { 0, 0 }, // 0x1E |
| { 0, 0 }, // 0x1F |
| { 0, 0 }, // 0x20 |
| { &opcode_dd_21, 14 }, // LD IX, nn |
| { &opcode_dd_22, 20 }, // LD (nn), IX |
| { &opcode_dd_23, 10 }, // INC IX |
| { &opcode_dd_24, 9 }, // INC IXH |
| { &opcode_dd_25, 9 }, // DEC IXH |
| { &opcode_dd_26, 9 }, // LD IXH, n |
| { 0, 0 }, // 0x27 |
| { 0, 0 }, // 0x28 |
| { &opcode_dd_29, 15 }, // ADD IX, IX |
| { &opcode_dd_2a, 20 }, // LD IX, (nn) |
| { &opcode_dd_2b, 10 }, // DEC IX |
| { &opcode_dd_2c, 9 }, // INC IXL |
| { &opcode_dd_2d, 9 }, // DEC IXL |
| { &opcode_dd_2e, 9 }, // LD IXL, n |
| { 0, 0 }, // 0x2F |
| { 0, 0 }, // 0x30 |
| { 0, 0 }, // 0x31 |
| { 0, 0 }, // 0x32 |
| { 0, 0 }, // 0x33 |
| { &opcode_dd_34, 23 }, // INC (IX + d) |
| { &opcode_dd_35, 23 }, // DEC (IX + d) |
| { &opcode_dd_36, 19 }, // LD (IX + d), n |
| { 0, 0 }, // 0x37 |
| { 0, 0 }, // 0x38 |
| { &opcode_dd_39, 15 }, // ADD IX, SP |
| { 0, 0 }, // 0x3A |
| { 0, 0 }, // 0x3B |
| { 0, 0 }, // 0x3C |
| { 0, 0 }, // 0x3D |
| { 0, 0 }, // 0x3E |
| { 0, 0 }, // 0x3F |
| { 0, 0 }, // 0x40 |
| { 0, 0 }, // 0x41 |
| { 0, 0 }, // 0x42 |
| { 0, 0 }, // 0x43 |
| { &opcode_dd_44, 9 }, // LD B, IXH |
| { &opcode_dd_45, 9 }, // LD B, IXL |
| { &opcode_dd_46, 19 }, // LD B, (IX + d) |
| { 0, 0 }, // 0x47 |
| { 0, 0 }, // 0x48 |
| { 0, 0 }, // 0x49 |
| { 0, 0 }, // 0x4A |
| { 0, 0 }, // 0x4B |
| { &opcode_dd_4c, 9 }, // LD C, IXH |
| { &opcode_dd_4d, 9 }, // LD C, IXL |
| { &opcode_dd_4e, 19 }, // LD C, (IX + d) |
| { 0, 0 }, // 0x4F |
| { 0, 0 }, // 0x50 |
| { 0, 0 }, // 0x51 |
| { 0, 0 }, // 0x52 |
| { 0, 0 }, // 0x53 |
| { &opcode_dd_54, 9 }, // LD D, IXH |
| { &opcode_dd_55, 9 }, // LD D, IXL |
| { &opcode_dd_56, 19 }, // LD D, (IX + d) |
| { 0, 0 }, // 0x57 |
| { 0, 0 }, // 0x58 |
| { 0, 0 }, // 0x59 |
| { 0, 0 }, // 0x5A |
| { 0, 0 }, // 0x5B |
| { &opcode_dd_5c, 9 }, // LD E, IXH |
| { &opcode_dd_5d, 9 }, // LD E, IXL |
| { &opcode_dd_5e, 19 }, // LD E, (IX + d) |
| { 0, 0 }, // 0x5F |
| { &opcode_dd_60, 9 }, // LD IXH, B |
| { &opcode_dd_61, 9 }, // LD IXH, C |
| { &opcode_dd_62, 9 }, // LD IXH, D |
| { &opcode_dd_63, 9 }, // LD IXH, E |
| { &opcode_dd_64, 9 }, // LD IXH, IXH |
| { &opcode_dd_65, 9 }, // LD IXH, IXL |
| { &opcode_dd_66, 9 }, // LD H, (IX + d) |
| { &opcode_dd_67, 9 }, // LD IXH, A |
| { &opcode_dd_68, 9 }, // LD IXL, B |
| { &opcode_dd_69, 9 }, // LD IXL, C |
| { &opcode_dd_6a, 9 }, // LD IXL, D |
| { &opcode_dd_6b, 9 }, // LD IXL, E |
| { &opcode_dd_6c, 9 }, // LD IXL, IXH |
| { &opcode_dd_6d, 9 }, // LD IXL, IXL |
| { &opcode_dd_6e, 9 }, // LD L, (IX + d) |
| { &opcode_dd_6f, 9 }, // LD IXL, A |
| { &opcode_dd_70, 19 }, // LD (IX + d), B |
| { &opcode_dd_71, 19 }, // LD (IX + d), C |
| { &opcode_dd_72, 19 }, // LD (IX + d), D |
| { &opcode_dd_73, 19 }, // LD (IX + d), E |
| { &opcode_dd_74, 19 }, // LD (IX + d), H |
| { &opcode_dd_75, 19 }, // LD (IX + d), L |
| { 0,19 }, // 0x76 |
| { &opcode_dd_77, 19 }, // LD (IX + d), A |
| { 0, 0 }, // 0x78 |
| { 0, 0 }, // 0x79 |
| { 0, 0 }, // 0x7A |
| { 0, 0 }, // 0x7B |
| { &opcode_dd_7c, 9 }, // LD A, IXH |
| { &opcode_dd_7d, 9 }, // LD A, IXL |
| { &opcode_dd_7e, 19 }, // LD A, (IX + d) |
| { 0, 0 }, // 0x7F |
| { 0, 0 }, // 0x80 |
| { 0, 0 }, // 0x81 |
| { 0, 0 }, // 0x82 |
| { 0, 0 }, // 0x83 |
| { &opcode_dd_84, 9 }, // ADD A, IXH |
| { &opcode_dd_85, 9 }, // ADD A, IXL |
| { &opcode_dd_86, 19 }, // ADD A, (IX + d) |
| { 0, 0 }, // 0x87 |
| { 0, 0 }, // 0x88 |
| { 0, 0 }, // 0x89 |
| { 0, 0 }, // 0x8A |
| { 0, 0 }, // 0x8B |
| { &opcode_dd_8c, 9 }, // ADC A, IXH |
| { &opcode_dd_8d, 9 }, // ADC A, IXL |
| { &opcode_dd_8e, 19 }, // ADC A, (IX + d) |
| { 0, 0 }, // 0x8F |
| { 0, 0 }, // 0x90 |
| { 0, 0 }, // 0x91 |
| { 0, 0 }, // 0x92 |
| { 0, 0 }, // 0x93 |
| { &opcode_dd_94, 9 }, // SUB IXH |
| { &opcode_dd_95, 9 }, // SUB IXL |
| { &opcode_dd_96, 19 }, // SUB (IX + d) |
| { 0, 0 }, // 0x97 |
| { 0, 0 }, // 0x98 |
| { 0, 0 }, // 0x99 |
| { 0, 0 }, // 0x9A |
| { 0, 0 }, // 0x9B |
| { &opcode_dd_9c, 9 }, // SBC A, IXH |
| { &opcode_dd_9d, 9 }, // SBC A, IXL |
| { &opcode_dd_9e, 19 }, // SBC A, (IX + d) |
| { 0, 0 }, // 0x9F |
| { 0, 0 }, // 0xA0 |
| { 0, 0 }, // 0xA1 |
| { 0, 0 }, // 0xA2 |
| { 0, 0 }, // 0xA3 |
| { &opcode_dd_a4, 9 }, // AND IXH |
| { &opcode_dd_a5, 9 }, // AND IXL |
| { &opcode_dd_a6, 19 }, // AND (IX + d) |
| { 0, 0 }, // 0xA7 |
| { 0, 0 }, // 0xA8 |
| { 0, 0 }, // 0xA9 |
| { 0, 0 }, // 0xAA |
| { 0, 0 }, // 0xAB |
| { &opcode_dd_ac, 9 }, // XOR IXH |
| { &opcode_dd_ad, 9 }, // XOR IXL |
| { &opcode_dd_ae, 19 }, // XOR (IX + d) |
| { 0, 0 }, // 0xAF |
| { 0, 0 }, // 0xB0 |
| { 0, 0 }, // 0xB1 |
| { 0, 0 }, // 0xB2 |
| { 0, 0 }, // 0xB3 |
| { &opcode_dd_b4, 9 }, // OR IXH |
| { &opcode_dd_b5, 9 }, // OR IXL |
| { &opcode_dd_b6, 19 }, // OR (IX + d) |
| { 0, 0 }, // 0xB7 |
| { 0, 0 }, // 0xB8 |
| { 0, 0 }, // 0xB9 |
| { 0, 0 }, // 0xBA |
| { 0, 0 }, // 0xBB |
| { &opcode_dd_bc, 9 }, // CP IXH |
| { &opcode_dd_bd, 9 }, // CP IXL |
| { &opcode_dd_be, 19 }, // CP (IX + d) |
| { 0, 0 }, // 0xBF |
| { 0, 0 }, // 0xC0 |
| { 0, 0 }, // 0xC1 |
| { 0, 0 }, // 0xC2 |
| { 0, 0 }, // 0xC3 |
| { 0, 0 }, // 0xC4 |
| { 0, 0 }, // 0xC5 |
| { 0, 0 }, // 0xC6 |
| { 0, 0 }, // 0xC7 |
| { 0, 0 }, // 0xC8 |
| { 0, 0 }, // 0xC9 |
| { 0, 0 }, // 0xCA |
| { &opcode_dd_cb, 0 }, // |
| { 0, 0 }, // 0xCC |
| { 0, 0 }, // 0xCD |
| { 0, 0 }, // 0xCE |
| { 0, 0 }, // 0xCF |
| { 0, 0 }, // 0xD0 |
| { 0, 0 }, // 0xD1 |
| { 0, 0 }, // 0xD2 |
| { 0, 0 }, // 0xD3 |
| { 0, 0 }, // 0xD4 |
| { 0, 0 }, // 0xD5 |
| { 0, 0 }, // 0xD6 |
| { 0, 0 }, // 0xD7 |
| { 0, 0 }, // 0xD8 |
| { 0, 0 }, // 0xD9 |
| { 0, 0 }, // 0xDA |
| { 0, 0 }, // 0xDB |
| { 0, 0 }, // 0xDC |
| { 0, 0 }, // 0xDD |
| { 0, 0 }, // 0xDE |
| { 0, 0 }, // 0xDF |
| { 0, 0 }, // 0xE0 |
| { &opcode_dd_e1, 14 }, // POP IX |
| { 0, 0 }, // 0xE2 |
| { &opcode_dd_e3, 23 }, // EX (SP), IX |
| { 0, 0 }, // 0xE4 |
| { &opcode_dd_e5, 15 }, // PUSH IX |
| { 0, 0 }, // 0xE6 |
| { 0, 0 }, // 0xE7 |
| { 0, 0 }, // 0xE8 |
| { &opcode_dd_e9, 8 }, // JP (IX) |
| { 0, 0 }, // 0xEA |
| { 0, 0 }, // 0xEB |
| { 0, 0 }, // 0xEC |
| { 0, 0 }, // 0xED |
| { 0, 0 }, // 0xEE |
| { 0, 0 }, // 0xEF |
| { 0, 0 }, // 0xF0 |
| { 0, 0 }, // 0xF1 |
| { 0, 0 }, // 0xF2 |
| { 0, 0 }, // 0xF3 |
| { 0, 0 }, // 0xF4 |
| { 0, 0 }, // 0xF5 |
| { 0, 0 }, // 0xF6 |
| { 0, 0 }, // 0xF7 |
| { 0, 0 }, // 0xF8 |
| { &opcode_dd_f9, 10 }, // LD SP, IX |
| { 0, 0 }, // 0xFA |
| { 0, 0 }, // 0xFB |
| { 0, 0 }, // 0xFC |
| { 0, 0 }, // 0xFD |
| { 0, 0 }, // 0xFE |
| { 0, 0 } // 0xFF |
| }; |
| |
| void opcode_dd_09() // ADD IX, BC |
| { |
| unsigned rr = BC(); |
| |
| F &= (Zero | Sign | Parity); |
| if( ((IX & 0xFFF)+(rr & 0xFFF)) > 0xFFF ) F |= Halfcarry; |
| IX += rr; |
| if( IX & 0x10000 ) F |= Carry; |
| } |
| |
| void opcode_dd_19() // ADD IX, DE |
| { |
| unsigned rr = DE(); |
| |
| F &= (Zero | Sign | Parity); |
| if( ((IX & 0xFFF)+(rr & 0xFFF)) > 0xFFF ) F |= Halfcarry; |
| IX += rr; |
| if( IX & 0x10000 ) F |= Carry; |
| } |
| |
| void opcode_dd_21() // LD IX, nn |
| { |
| IX = fetchWord(); |
| } |
| |
| void opcode_dd_22() // LD (nn), IX |
| { |
| writeWord( fetchWord(), IX ); |
| } |
| |
| void opcode_dd_23() // INC IX |
| { |
| IX++; |
| } |
| |
| void opcode_dd_24() // INC IXH |
| { |
| IX = (IX & 0xFF) | ((unsigned)incByte( IX >> 8 ) << 8); |
| } |
| |
| void opcode_dd_25() // DEC IXH |
| { |
| IX = (IX & 0xFF) | ((unsigned)decByte( IX >> 8 ) << 8); |
| } |
| |
| void opcode_dd_26() // LD IXH, n |
| { |
| IX = (IX & 0xFF) | ((unsigned)fetchByte() << 8); |
| } |
| |
| void opcode_dd_29() // ADD IX, IX |
| { |
| F &= (Zero | Sign | Parity); |
| if( IX & 0x800 ) F |= Halfcarry; |
| IX += IX; |
| if( IX & 0x10000 ) F |= Carry; |
| } |
| |
| void opcode_dd_2a() // LD IX, (nn) |
| { |
| IX = readWord( fetchWord() ); |
| } |
| |
| void opcode_dd_2b() // DEC IX |
| { |
| IX--; |
| } |
| |
| void opcode_dd_2c() // INC IXL |
| { |
| IX = (IX & 0xFF00) | incByte( IX & 0xFF ); |
| } |
| |
| void opcode_dd_2d() // DEC IXL |
| { |
| IX = (IX & 0xFF00) | decByte( IX & 0xFF ); |
| } |
| |
| void opcode_dd_2e() // LD IXL, n |
| { |
| IX = (IX & 0xFF00) | fetchByte(); |
| } |
| |
| void opcode_dd_34() // INC (IX + d) |
| { |
| unsigned addr = addDispl( IX, fetchByte() ); |
| |
| writeByte( addr, incByte( readByte( addr ) ) ); |
| } |
| |
| void opcode_dd_35() // DEC (IX + d) |
| { |
| unsigned addr = addDispl( IX, fetchByte() ); |
| |
| writeByte( addr, decByte( readByte( addr ) ) ); |
| } |
| |
| void opcode_dd_36() // LD (IX + d), n |
| { |
| unsigned addr = addDispl( IX, fetchByte() ); |
| |
| writeByte( addr, fetchByte() ); |
| } |
| |
| void opcode_dd_39() // ADD IX, SP |
| { |
| F &= (Zero | Sign | Parity); |
| if( ((IX & 0xFFF)+(SP & 0xFFF)) > 0xFFF ) F |= Halfcarry; |
| IX += SP; |
| if( IX & 0x10000 ) F |= Carry; |
| } |
| |
| void opcode_dd_44() // LD B, IXH |
| { |
| B = IX >> 8; |
| } |
| |
| void opcode_dd_45() // LD B, IXL |
| { |
| B = IX & 0xFF; |
| } |
| |
| void opcode_dd_46() // LD B, (IX + d) |
| { |
| B = readByte( addDispl(IX,fetchByte()) ); |
| } |
| |
| void opcode_dd_4c() // LD C, IXH |
| { |
| C = IX >> 8; |
| } |
| |
| void opcode_dd_4d() // LD C, IXL |
| { |
| C = IX & 0xFF; |
| } |
| |
| void opcode_dd_4e() // LD C, (IX + d) |
| { |
| C = readByte( addDispl(IX,fetchByte()) ); |
| } |
| |
| void opcode_dd_54() // LD D, IXH |
| { |
| D = IX >> 8; |
| } |
| |
| void opcode_dd_55() // LD D, IXL |
| { |
| D = IX & 0xFF; |
| } |
| |
| void opcode_dd_56() // LD D, (IX + d) |
| { |
| D = readByte( addDispl(IX,fetchByte()) ); |
| } |
| |
| void opcode_dd_5c() // LD E, IXH |
| { |
| E = IX >> 8; |
| } |
| |
| void opcode_dd_5d() // LD E, IXL |
| { |
| E = IX & 0xFF; |
| } |
| |
| void opcode_dd_5e() // LD E, (IX + d) |
| { |
| E = readByte( addDispl(IX,fetchByte()) ); |
| } |
| |
| void opcode_dd_60() // LD IXH, B |
| { |
| IX = (IX & 0xFF) | ((unsigned)B << 8); |
| } |
| |
| void opcode_dd_61() // LD IXH, C |
| { |
| IX = (IX & 0xFF) | ((unsigned)C << 8); |
| } |
| |
| void opcode_dd_62() // LD IXH, D |
| { |
| IX = (IX & 0xFF) | ((unsigned)D << 8); |
| } |
| |
| void opcode_dd_63() // LD IXH, E |
| { |
| IX = (IX & 0xFF) | ((unsigned)E << 8); |
| } |
| |
| void opcode_dd_64() // LD IXH, IXH |
| { |
| } |
| |
| void opcode_dd_65() // LD IXH, IXL |
| { |
| IX = (IX & 0xFF) | ((IX << 8) & 0xFF00); |
| } |
| |
| void opcode_dd_66() // LD H, (IX + d) |
| { |
| H = readByte( addDispl(IX,fetchByte()) ); |
| } |
| |
| void opcode_dd_67() // LD IXH, A |
| { |
| IX = (IX & 0xFF) | ((unsigned)A << 8); |
| } |
| |
| void opcode_dd_68() // LD IXL, B |
| { |
| IX = (IX & 0xFF00) | B; |
| } |
| |
| void opcode_dd_69() // LD IXL, C |
| { |
| IX = (IX & 0xFF00) | C; |
|