diff options
author | Torne Wuff <torne@wolfpuppy.org.uk> | 2011-11-06 22:44:25 +0000 |
---|---|---|
committer | Torne Wuff <torne@wolfpuppy.org.uk> | 2011-11-06 22:44:25 +0000 |
commit | 569285794b9112f0134ddad4bb886308ea4a7be6 (patch) | |
tree | ce702cb07829820261a682c471133c76d11c610e /apps/codecs/libgme/z80_cpu_run.h | |
parent | d9b7d58fa6c9ceb136bea429adf6746cc7138208 (diff) | |
download | rockbox-569285794b9112f0134ddad4bb886308ea4a7be6.tar.gz rockbox-569285794b9112f0134ddad4bb886308ea4a7be6.zip |
Bulk convert all DOS line endings to UNIX.
For the git migration we want a nice clean repository with UNIX line
endings. git does not use svn:eol-style, we just need the file contents to be
sane.
Sorry everybody. I know this messes up blame.
Scumbag *NIX developer says migrating to git will make line ending issues go
away; commits giant change to svn which changes line endings anyway. :)
git-svn-id: svn://svn.rockbox.org/rockbox/trunk@30924 a1c6a512-1295-4272-9138-f99709370657
Diffstat (limited to 'apps/codecs/libgme/z80_cpu_run.h')
-rw-r--r-- | apps/codecs/libgme/z80_cpu_run.h | 3392 |
1 files changed, 1696 insertions, 1696 deletions
diff --git a/apps/codecs/libgme/z80_cpu_run.h b/apps/codecs/libgme/z80_cpu_run.h index 18195ac92b..a453487bb0 100644 --- a/apps/codecs/libgme/z80_cpu_run.h +++ b/apps/codecs/libgme/z80_cpu_run.h | |||
@@ -1,1696 +1,1696 @@ | |||
1 | // Game_Music_Emu 0.6-pre. http://www.slack.net/~ant/ | 1 | // Game_Music_Emu 0.6-pre. http://www.slack.net/~ant/ |
2 | 2 | ||
3 | // Last validated with zexall 2009.12.05. | 3 | // Last validated with zexall 2009.12.05. |
4 | // Doesn't implement the R register or immediate interrupt after EI. | 4 | // Doesn't implement the R register or immediate interrupt after EI. |
5 | // Address wrap-around isn't completely correct, but is prevented from crashing emulator. | 5 | // Address wrap-around isn't completely correct, but is prevented from crashing emulator. |
6 | // 16-bit memory accesses are made directly to mapped memory, instead of using macro. | 6 | // 16-bit memory accesses are made directly to mapped memory, instead of using macro. |
7 | 7 | ||
8 | #if 0 | 8 | #if 0 |
9 | /* Define these macros in the source file before #including this file. | 9 | /* Define these macros in the source file before #including this file. |
10 | - Parameters might be expressions, so they are best evaluated only once, | 10 | - Parameters might be expressions, so they are best evaluated only once, |
11 | though they NEVER have side-effects, so multiple evaluation is OK. | 11 | though they NEVER have side-effects, so multiple evaluation is OK. |
12 | - Output parameters might be a multiple-assignment expression like "a=x", | 12 | - Output parameters might be a multiple-assignment expression like "a=x", |
13 | so they must NOT be parenthesized. | 13 | so they must NOT be parenthesized. |
14 | - Except where noted, time() and related functions will NOT work | 14 | - Except where noted, time() and related functions will NOT work |
15 | correctly inside a macro. TIME() is always correct, and between FLUSH_TIME() and | 15 | correctly inside a macro. TIME() is always correct, and between FLUSH_TIME() and |
16 | CACHE_TIME() the normal time changing functions can be used. | 16 | CACHE_TIME() the normal time changing functions can be used. |
17 | - Macros "returning" void may use a {} statement block. */ | 17 | - Macros "returning" void may use a {} statement block. */ |
18 | 18 | ||
19 | // 0 <= addr <= 0xFFFF + 0x100 | 19 | // 0 <= addr <= 0xFFFF + 0x100 |
20 | // Optional; default uses whatever was set with map_mem() | 20 | // Optional; default uses whatever was set with map_mem() |
21 | int READ_MEM( addr_t ); | 21 | int READ_MEM( addr_t ); |
22 | void WRITE_MEM( addr_t, int data ); | 22 | void WRITE_MEM( addr_t, int data ); |
23 | 23 | ||
24 | // 0 <= port <= 0xFFFF (apparently upper 8 bits are output by hardware) | 24 | // 0 <= port <= 0xFFFF (apparently upper 8 bits are output by hardware) |
25 | void OUT_PORT( int port, int data ); | 25 | void OUT_PORT( int port, int data ); |
26 | int IN_PORT int port ); | 26 | int IN_PORT int port ); |
27 | 27 | ||
28 | // Reference to Z80_Cpu object used for emulation | 28 | // Reference to Z80_Cpu object used for emulation |
29 | #define CPU cpu | 29 | #define CPU cpu |
30 | 30 | ||
31 | // The following can be used within macros: | 31 | // The following can be used within macros: |
32 | 32 | ||
33 | // Current time | 33 | // Current time |
34 | time_t TIME(); | 34 | time_t TIME(); |
35 | 35 | ||
36 | // Allows use of time functions | 36 | // Allows use of time functions |
37 | void FLUSH_TIME(); | 37 | void FLUSH_TIME(); |
38 | 38 | ||
39 | // Must be used before end of macro if FLUSH_TIME() was used earlier | 39 | // Must be used before end of macro if FLUSH_TIME() was used earlier |
40 | void CACHE_TIME(); | 40 | void CACHE_TIME(); |
41 | 41 | ||
42 | // Configuration (optional; commented behavior if defined) | 42 | // Configuration (optional; commented behavior if defined) |
43 | 43 | ||
44 | // Optimizes as if map_mem( 0, 0x10000, FLAT_MEM, FLAT_MEM ) is always in effect | 44 | // Optimizes as if map_mem( 0, 0x10000, FLAT_MEM, FLAT_MEM ) is always in effect |
45 | #define FLAT_MEM my_mem_array | 45 | #define FLAT_MEM my_mem_array |
46 | 46 | ||
47 | // If RST 7 ($FF) is encountered and PC = IDLE_ADDR, stops execution | 47 | // If RST 7 ($FF) is encountered and PC = IDLE_ADDR, stops execution |
48 | #define IDLE_ADDR 0x1234 | 48 | #define IDLE_ADDR 0x1234 |
49 | 49 | ||
50 | // Expanded just before beginning of code, to help debugger | 50 | // Expanded just before beginning of code, to help debugger |
51 | #define CPU_BEGIN void my_run_cpu() { | 51 | #define CPU_BEGIN void my_run_cpu() { |
52 | 52 | ||
53 | #endif | 53 | #endif |
54 | 54 | ||
55 | /* Copyright (C) 2006-2008 Shay Green. This module is free software; you | 55 | /* Copyright (C) 2006-2008 Shay Green. This module is free software; you |
56 | can redistribute it and/or modify it under the terms of the GNU Lesser | 56 | can redistribute it and/or modify it under the terms of the GNU Lesser |
57 | General Public License as published by the Free Software Foundation; either | 57 | General Public License as published by the Free Software Foundation; either |
58 | version 2.1 of the License, or (at your option) any later version. This | 58 | version 2.1 of the License, or (at your option) any later version. This |
59 | module is distributed in the hope that it will be useful, but WITHOUT ANY | 59 | module is distributed in the hope that it will be useful, but WITHOUT ANY |
60 | WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS | 60 | WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS |
61 | FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more | 61 | FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more |
62 | details. You should have received a copy of the GNU Lesser General Public | 62 | details. You should have received a copy of the GNU Lesser General Public |
63 | License along with this module; if not, write to the Free Software Foundation, | 63 | License along with this module; if not, write to the Free Software Foundation, |
64 | Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ | 64 | Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ |
65 | 65 | ||
66 | #ifdef CPU_BEGIN | 66 | #ifdef CPU_BEGIN |
67 | CPU_BEGIN | 67 | CPU_BEGIN |
68 | #endif | 68 | #endif |
69 | 69 | ||
70 | #define R cpu->r | 70 | #define R cpu->r |
71 | 71 | ||
72 | // flags, named with hex value for clarity | 72 | // flags, named with hex value for clarity |
73 | int const S80 = 0x80; | 73 | int const S80 = 0x80; |
74 | int const Z40 = 0x40; | 74 | int const Z40 = 0x40; |
75 | int const F20 = 0x20; | 75 | int const F20 = 0x20; |
76 | int const H10 = 0x10; | 76 | int const H10 = 0x10; |
77 | int const F08 = 0x08; | 77 | int const F08 = 0x08; |
78 | int const V04 = 0x04; | 78 | int const V04 = 0x04; |
79 | int const P04 = 0x04; | 79 | int const P04 = 0x04; |
80 | int const N02 = 0x02; | 80 | int const N02 = 0x02; |
81 | int const C01 = 0x01; | 81 | int const C01 = 0x01; |
82 | 82 | ||
83 | #define SZ28P( n ) cpu->szpc [n] | 83 | #define SZ28P( n ) cpu->szpc [n] |
84 | #define SZ28PC( n ) cpu->szpc [n] | 84 | #define SZ28PC( n ) cpu->szpc [n] |
85 | #define SZ28C( n ) (cpu->szpc [n] & ~P04) | 85 | #define SZ28C( n ) (cpu->szpc [n] & ~P04) |
86 | #define SZ28( n ) SZ28C( n ) | 86 | #define SZ28( n ) SZ28C( n ) |
87 | 87 | ||
88 | #define SET_R( n ) (void) (R.r = n) | 88 | #define SET_R( n ) (void) (R.r = n) |
89 | #define GET_R() (R.r) | 89 | #define GET_R() (R.r) |
90 | 90 | ||
91 | // Time | 91 | // Time |
92 | #define TIME() (s_time + s.base) | 92 | #define TIME() (s_time + s.base) |
93 | #define FLUSH_TIME() {s.time = s_time;} | 93 | #define FLUSH_TIME() {s.time = s_time;} |
94 | #define CACHE_TIME() {s_time = s.time;} | 94 | #define CACHE_TIME() {s_time = s.time;} |
95 | 95 | ||
96 | // Memory | 96 | // Memory |
97 | #define RW_MEM( addr, rw ) RW_PAGE( addr, rw ) [RW_OFFSET( addr )] | 97 | #define RW_MEM( addr, rw ) RW_PAGE( addr, rw ) [RW_OFFSET( addr )] |
98 | #define READ_CODE( addr ) RW_MEM( addr, read ) | 98 | #define READ_CODE( addr ) RW_MEM( addr, read ) |
99 | 99 | ||
100 | #ifdef FLAT_MEM | 100 | #ifdef FLAT_MEM |
101 | #define RW_PAGE( addr, rw ) FLAT_MEM | 101 | #define RW_PAGE( addr, rw ) FLAT_MEM |
102 | #define RW_OFFSET( addr ) (addr) | 102 | #define RW_OFFSET( addr ) (addr) |
103 | #define INSTR( off, addr ) READ_CODE( addr ) | 103 | #define INSTR( off, addr ) READ_CODE( addr ) |
104 | #else | 104 | #else |
105 | #define RW_PAGE( addr, rw ) s.rw [(unsigned) (addr) >> page_bits] | 105 | #define RW_PAGE( addr, rw ) s.rw [(unsigned) (addr) >> page_bits] |
106 | #define RW_OFFSET( addr ) Z80_CPU_OFFSET( addr ) | 106 | #define RW_OFFSET( addr ) Z80_CPU_OFFSET( addr ) |
107 | #define INSTR( off, addr ) instr [off] | 107 | #define INSTR( off, addr ) instr [off] |
108 | #endif | 108 | #endif |
109 | 109 | ||
110 | #ifndef READ_MEM | 110 | #ifndef READ_MEM |
111 | #define READ_MEM( addr ) RW_MEM( addr, read ) | 111 | #define READ_MEM( addr ) RW_MEM( addr, read ) |
112 | #endif | 112 | #endif |
113 | 113 | ||
114 | #ifndef WRITE_MEM | 114 | #ifndef WRITE_MEM |
115 | #define WRITE_MEM( addr, data ) (RW_MEM( addr, write ) = data) | 115 | #define WRITE_MEM( addr, data ) (RW_MEM( addr, write ) = data) |
116 | #endif | 116 | #endif |
117 | 117 | ||
118 | #define READ_WORD( addr ) GET_LE16( &RW_MEM( addr, read ) ) | 118 | #define READ_WORD( addr ) GET_LE16( &RW_MEM( addr, read ) ) |
119 | #define WRITE_WORD( addr, data ) SET_LE16( &RW_MEM( addr, write ), data ) | 119 | #define WRITE_WORD( addr, data ) SET_LE16( &RW_MEM( addr, write ), data ) |
120 | 120 | ||
121 | // Truncation | 121 | // Truncation |
122 | #define BYTE( n ) ((uint8_t ) (n)) /* (unsigned) n & 0xFF */ | 122 | #define BYTE( n ) ((uint8_t ) (n)) /* (unsigned) n & 0xFF */ |
123 | #define SBYTE( n ) ((int8_t ) (n)) /* (BYTE( n ) ^ 0x80) - 0x80 */ | 123 | #define SBYTE( n ) ((int8_t ) (n)) /* (BYTE( n ) ^ 0x80) - 0x80 */ |
124 | #define WORD( n ) ((uint16_t) (n)) /* (unsigned) n & 0xFFFF */ | 124 | #define WORD( n ) ((uint16_t) (n)) /* (unsigned) n & 0xFFFF */ |
125 | 125 | ||
126 | // Misc | 126 | // Misc |
127 | #define CASE5( a, b, c, d, e ) case 0x##a:case 0x##b:case 0x##c:case 0x##d:case 0x##e | 127 | #define CASE5( a, b, c, d, e ) case 0x##a:case 0x##b:case 0x##c:case 0x##d:case 0x##e |
128 | #define CASE6( a, b, c, d, e, f ) CASE5( a, b, c, d, e ): case 0x##f | 128 | #define CASE6( a, b, c, d, e, f ) CASE5( a, b, c, d, e ): case 0x##f |
129 | #define CASE7( a, b, c, d, e, f, g ) CASE6( a, b, c, d, e, f ): case 0x##g | 129 | #define CASE7( a, b, c, d, e, f, g ) CASE6( a, b, c, d, e, f ): case 0x##g |
130 | #define CASE8( a, b, c, d, e, f, g, h ) CASE7( a, b, c, d, e, f, g ): case 0x##h | 130 | #define CASE8( a, b, c, d, e, f, g, h ) CASE7( a, b, c, d, e, f, g ): case 0x##h |
131 | 131 | ||
132 | #ifdef BLARGG_BIG_ENDIAN | 132 | #ifdef BLARGG_BIG_ENDIAN |
133 | #define R8( n, offset ) ((r.r8_ - offset) [n]) | 133 | #define R8( n, offset ) ((r.r8_ - offset) [n]) |
134 | #elif BLARGG_LITTLE_ENDIAN | 134 | #elif BLARGG_LITTLE_ENDIAN |
135 | #define R8( n, offset ) ((r.r8_ - offset) [(n) ^ 1]) | 135 | #define R8( n, offset ) ((r.r8_ - offset) [(n) ^ 1]) |
136 | #else | 136 | #else |
137 | #error "Byte order of CPU must be known" | 137 | #error "Byte order of CPU must be known" |
138 | #endif | 138 | #endif |
139 | 139 | ||
140 | #define R16( n, shift, offset ) (r.r16_ [((unsigned) (n) >> shift) - (offset >> shift)]) | 140 | #define R16( n, shift, offset ) (r.r16_ [((unsigned) (n) >> shift) - (offset >> shift)]) |
141 | 141 | ||
142 | #define EX( x, y ) \ | 142 | #define EX( x, y ) \ |
143 | {\ | 143 | {\ |
144 | int temp = x;\ | 144 | int temp = x;\ |
145 | x = y;\ | 145 | x = y;\ |
146 | y = temp;\ | 146 | y = temp;\ |
147 | } | 147 | } |
148 | 148 | ||
149 | #define EXX( name ) \ | 149 | #define EXX( name ) \ |
150 | EX( R.alt.name, r.name ) | 150 | EX( R.alt.name, r.name ) |
151 | 151 | ||
152 | bool warning = false; | 152 | bool warning = false; |
153 | { | 153 | { |
154 | struct cpu_state_t s; | 154 | struct cpu_state_t s; |
155 | #ifdef FLAT_MEM | 155 | #ifdef FLAT_MEM |
156 | s.base = cpu->cpu_state_.base; | 156 | s.base = cpu->cpu_state_.base; |
157 | #else | 157 | #else |
158 | s = cpu->cpu_state_; | 158 | s = cpu->cpu_state_; |
159 | #endif | 159 | #endif |
160 | cpu->cpu_state = &s; | 160 | cpu->cpu_state = &s; |
161 | 161 | ||
162 | 162 | ||
163 | union r_t { | 163 | union r_t { |
164 | struct regs_t b; | 164 | struct regs_t b; |
165 | struct pairs_t w; | 165 | struct pairs_t w; |
166 | byte r8_ [8]; // indexed | 166 | byte r8_ [8]; // indexed |
167 | uint16_t r16_ [4]; | 167 | uint16_t r16_ [4]; |
168 | } r; | 168 | } r; |
169 | r.b = R.b; | 169 | r.b = R.b; |
170 | 170 | ||
171 | cpu_time_t s_time = cpu->cpu_state_.time; | 171 | cpu_time_t s_time = cpu->cpu_state_.time; |
172 | int pc = R.pc; | 172 | int pc = R.pc; |
173 | int sp = R.sp; | 173 | int sp = R.sp; |
174 | int ix = R.ix; // TODO: keep in memory for direct access? | 174 | int ix = R.ix; // TODO: keep in memory for direct access? |
175 | int iy = R.iy; | 175 | int iy = R.iy; |
176 | int flags = R.b.flags; | 176 | int flags = R.b.flags; |
177 | 177 | ||
178 | //goto loop; // confuses optimizer | 178 | //goto loop; // confuses optimizer |
179 | s_time += 7; | 179 | s_time += 7; |
180 | pc -= 2; | 180 | pc -= 2; |
181 | 181 | ||
182 | call_not_taken: | 182 | call_not_taken: |
183 | s_time -= 7; | 183 | s_time -= 7; |
184 | jp_not_taken: | 184 | jp_not_taken: |
185 | pc += 2; | 185 | pc += 2; |
186 | loop: | 186 | loop: |
187 | 187 | ||
188 | check( (unsigned) pc < 0x10000 + 1 ); // +1 so emulator can catch wrap-around | 188 | check( (unsigned) pc < 0x10000 + 1 ); // +1 so emulator can catch wrap-around |
189 | check( (unsigned) sp < 0x10000 ); | 189 | check( (unsigned) sp < 0x10000 ); |
190 | check( (unsigned) flags < 0x100 ); | 190 | check( (unsigned) flags < 0x100 ); |
191 | check( (unsigned) ix < 0x10000 ); | 191 | check( (unsigned) ix < 0x10000 ); |
192 | check( (unsigned) iy < 0x10000 ); | 192 | check( (unsigned) iy < 0x10000 ); |
193 | 193 | ||
194 | byte const* instr = RW_PAGE( pc, read ); | 194 | byte const* instr = RW_PAGE( pc, read ); |
195 | 195 | ||
196 | int opcode; | 196 | int opcode; |
197 | 197 | ||
198 | if ( RW_OFFSET( ~0 ) == ~0 ) | 198 | if ( RW_OFFSET( ~0 ) == ~0 ) |
199 | { | 199 | { |
200 | opcode = instr [RW_OFFSET( pc )]; | 200 | opcode = instr [RW_OFFSET( pc )]; |
201 | pc++; | 201 | pc++; |
202 | instr += RW_OFFSET( pc ); | 202 | instr += RW_OFFSET( pc ); |
203 | } | 203 | } |
204 | else | 204 | else |
205 | { | 205 | { |
206 | instr += RW_OFFSET( pc ); | 206 | instr += RW_OFFSET( pc ); |
207 | opcode = *instr++; | 207 | opcode = *instr++; |
208 | pc++; | 208 | pc++; |
209 | } | 209 | } |
210 | 210 | ||
211 | static byte const clock_table [256 * 2] = { | 211 | static byte const clock_table [256 * 2] = { |
212 | // 0 1 2 3 4 5 6 7 8 9 A B C D E F | 212 | // 0 1 2 3 4 5 6 7 8 9 A B C D E F |
213 | 4,10, 7, 6, 4, 4, 7, 4, 4,11, 7, 6, 4, 4, 7, 4, // 0 | 213 | 4,10, 7, 6, 4, 4, 7, 4, 4,11, 7, 6, 4, 4, 7, 4, // 0 |
214 | 8,10, 7, 6, 4, 4, 7, 4,12,11, 7, 6, 4, 4, 7, 4, // 1 | 214 | 8,10, 7, 6, 4, 4, 7, 4,12,11, 7, 6, 4, 4, 7, 4, // 1 |
215 | 7,10,16, 6, 4, 4, 7, 4, 7,11,16, 6, 4, 4, 7, 4, // 2 | 215 | 7,10,16, 6, 4, 4, 7, 4, 7,11,16, 6, 4, 4, 7, 4, // 2 |
216 | 7,10,13, 6,11,11,10, 4, 7,11,13, 6, 4, 4, 7, 4, // 3 | 216 | 7,10,13, 6,11,11,10, 4, 7,11,13, 6, 4, 4, 7, 4, // 3 |
217 | 4, 4, 4, 4, 4, 4, 7, 4, 4, 4, 4, 4, 4, 4, 7, 4, // 4 | 217 | 4, 4, 4, 4, 4, 4, 7, 4, 4, 4, 4, 4, 4, 4, 7, 4, // 4 |
218 | 4, 4, 4, 4, 4, 4, 7, 4, 4, 4, 4, 4, 4, 4, 7, 4, // 5 | 218 | 4, 4, 4, 4, 4, 4, 7, 4, 4, 4, 4, 4, 4, 4, 7, 4, // 5 |
219 | 4, 4, 4, 4, 4, 4, 7, 4, 4, 4, 4, 4, 4, 4, 7, 4, // 6 | 219 | 4, 4, 4, 4, 4, 4, 7, 4, 4, 4, 4, 4, 4, 4, 7, 4, // 6 |
220 | 7, 7, 7, 7, 7, 7, 4, 7, 4, 4, 4, 4, 4, 4, 7, 4, // 7 | 220 | 7, 7, 7, 7, 7, 7, 4, 7, 4, 4, 4, 4, 4, 4, 7, 4, // 7 |
221 | 4, 4, 4, 4, 4, 4, 7, 4, 4, 4, 4, 4, 4, 4, 7, 4, // 8 | 221 | 4, 4, 4, 4, 4, 4, 7, 4, 4, 4, 4, 4, 4, 4, 7, 4, // 8 |
222 | 4, 4, 4, 4, 4, 4, 7, 4, 4, 4, 4, 4, 4, 4, 7, 4, // 9 | 222 | 4, 4, 4, 4, 4, 4, 7, 4, 4, 4, 4, 4, 4, 4, 7, 4, // 9 |
223 | 4, 4, 4, 4, 4, 4, 7, 4, 4, 4, 4, 4, 4, 4, 7, 4, // A | 223 | 4, 4, 4, 4, 4, 4, 7, 4, 4, 4, 4, 4, 4, 4, 7, 4, // A |
224 | 4, 4, 4, 4, 4, 4, 7, 4, 4, 4, 4, 4, 4, 4, 7, 4, // B | 224 | 4, 4, 4, 4, 4, 4, 7, 4, 4, 4, 4, 4, 4, 4, 7, 4, // B |
225 | 11,10,10,10,17,11, 7,11,11,10,10, 8,17,17, 7,11, // C | 225 | 11,10,10,10,17,11, 7,11,11,10,10, 8,17,17, 7,11, // C |
226 | 11,10,10,11,17,11, 7,11,11, 4,10,11,17, 8, 7,11, // D | 226 | 11,10,10,11,17,11, 7,11,11, 4,10,11,17, 8, 7,11, // D |
227 | 11,10,10,19,17,11, 7,11,11, 4,10, 4,17, 8, 7,11, // E | 227 | 11,10,10,19,17,11, 7,11,11, 4,10, 4,17, 8, 7,11, // E |
228 | 11,10,10, 4,17,11, 7,11,11, 6,10, 4,17, 8, 7,11, // F | 228 | 11,10,10, 4,17,11, 7,11,11, 6,10, 4,17, 8, 7,11, // F |
229 | 229 | ||
230 | // high four bits are $ED time - 8, low four bits are $DD/$FD time - 8 | 230 | // high four bits are $ED time - 8, low four bits are $DD/$FD time - 8 |
231 | //0 1 2 3 4 5 6 7 8 9 A B C D E F | 231 | //0 1 2 3 4 5 6 7 8 9 A B C D E F |
232 | 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x07,0x00,0x00,0x00,0x00,0x00,0x00, | 232 | 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x07,0x00,0x00,0x00,0x00,0x00,0x00, |
233 | 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x07,0x00,0x00,0x00,0x00,0x00,0x00, | 233 | 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x07,0x00,0x00,0x00,0x00,0x00,0x00, |
234 | 0x00,0x06,0x0C,0x02,0x00,0x00,0x03,0x00,0x00,0x07,0x0C,0x02,0x00,0x00,0x03,0x00, | 234 | 0x00,0x06,0x0C,0x02,0x00,0x00,0x03,0x00,0x00,0x07,0x0C,0x02,0x00,0x00,0x03,0x00, |
235 | 0x00,0x00,0x00,0x00,0x0F,0x0F,0x0B,0x00,0x00,0x07,0x00,0x00,0x00,0x00,0x00,0x00, | 235 | 0x00,0x00,0x00,0x00,0x0F,0x0F,0x0B,0x00,0x00,0x07,0x00,0x00,0x00,0x00,0x00,0x00, |
236 | 0x40,0x40,0x70,0xC0,0x00,0x60,0x0B,0x10,0x40,0x40,0x70,0xC0,0x00,0x60,0x0B,0x10, | 236 | 0x40,0x40,0x70,0xC0,0x00,0x60,0x0B,0x10,0x40,0x40,0x70,0xC0,0x00,0x60,0x0B,0x10, |
237 | 0x40,0x40,0x70,0xC0,0x00,0x60,0x0B,0x10,0x40,0x40,0x70,0xC0,0x00,0x60,0x0B,0x10, | 237 | 0x40,0x40,0x70,0xC0,0x00,0x60,0x0B,0x10,0x40,0x40,0x70,0xC0,0x00,0x60,0x0B,0x10, |
238 | 0x40,0x40,0x70,0xC0,0x00,0x60,0x0B,0xA0,0x40,0x40,0x70,0xC0,0x00,0x60,0x0B,0xA0, | 238 | 0x40,0x40,0x70,0xC0,0x00,0x60,0x0B,0xA0,0x40,0x40,0x70,0xC0,0x00,0x60,0x0B,0xA0, |
239 | 0x4B,0x4B,0x7B,0xCB,0x0B,0x6B,0x00,0x0B,0x40,0x40,0x70,0xC0,0x00,0x60,0x0B,0x00, | 239 | 0x4B,0x4B,0x7B,0xCB,0x0B,0x6B,0x00,0x0B,0x40,0x40,0x70,0xC0,0x00,0x60,0x0B,0x00, |
240 | 0x00,0x00,0x00,0x00,0x00,0x00,0x0B,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x0B,0x00, | 240 | 0x00,0x00,0x00,0x00,0x00,0x00,0x0B,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x0B,0x00, |
241 | 0x00,0x00,0x00,0x00,0x00,0x00,0x0B,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x0B,0x00, | 241 | 0x00,0x00,0x00,0x00,0x00,0x00,0x0B,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x0B,0x00, |
242 | 0x80,0x80,0x80,0x80,0x00,0x00,0x0B,0x00,0x80,0x80,0x80,0x80,0x00,0x00,0x0B,0x00, | 242 | 0x80,0x80,0x80,0x80,0x00,0x00,0x0B,0x00,0x80,0x80,0x80,0x80,0x00,0x00,0x0B,0x00, |
243 | 0xD0,0xD0,0xD0,0xD0,0x00,0x00,0x0B,0x00,0xD0,0xD0,0xD0,0xD0,0x00,0x00,0x0B,0x00, | 243 | 0xD0,0xD0,0xD0,0xD0,0x00,0x00,0x0B,0x00,0xD0,0xD0,0xD0,0xD0,0x00,0x00,0x0B,0x00, |
244 | 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x0F,0x00,0x00,0x00,0x00, | 244 | 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x0F,0x00,0x00,0x00,0x00, |
245 | 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, | 245 | 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, |
246 | 0x00,0x06,0x00,0x0F,0x00,0x07,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, | 246 | 0x00,0x06,0x00,0x0F,0x00,0x07,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, |
247 | 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02,0x00,0x00,0x00,0x00,0x00,0x00, | 247 | 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02,0x00,0x00,0x00,0x00,0x00,0x00, |
248 | }; | 248 | }; |
249 | 249 | ||
250 | if ( s_time >= 0 ) | 250 | if ( s_time >= 0 ) |
251 | goto out_of_time; | 251 | goto out_of_time; |
252 | s_time += clock_table [opcode]; | 252 | s_time += clock_table [opcode]; |
253 | 253 | ||
254 | #ifdef Z80_CPU_LOG_H | 254 | #ifdef Z80_CPU_LOG_H |
255 | //log_opcode( opcode, READ_CODE( pc ) ); | 255 | //log_opcode( opcode, READ_CODE( pc ) ); |
256 | z80_cpu_log( "log.txt", pc - 1, opcode, READ_CODE( pc ), | 256 | z80_cpu_log( "log.txt", pc - 1, opcode, READ_CODE( pc ), |
257 | READ_CODE( pc + 1 ), READ_CODE( pc + 2 ) ); | 257 | READ_CODE( pc + 1 ), READ_CODE( pc + 2 ) ); |
258 | z80_log_regs( r.b.a, r.w.bc, r.w.de, r.w.hl, sp, ix, iy ); | 258 | z80_log_regs( r.b.a, r.w.bc, r.w.de, r.w.hl, sp, ix, iy ); |
259 | #endif | 259 | #endif |
260 | 260 | ||
261 | #define GET_ADDR() GET_LE16( &INSTR( 0, pc ) ) | 261 | #define GET_ADDR() GET_LE16( &INSTR( 0, pc ) ) |
262 | 262 | ||
263 | int data; | 263 | int data; |
264 | data = INSTR( 0, pc ); | 264 | data = INSTR( 0, pc ); |
265 | 265 | ||
266 | switch ( opcode ) | 266 | switch ( opcode ) |
267 | { | 267 | { |
268 | // Common | 268 | // Common |
269 | 269 | ||
270 | case 0x00: // NOP | 270 | case 0x00: // NOP |
271 | CASE7( 40, 49, 52, 5B, 64, 6D, 7F ): // LD B,B etc. | 271 | CASE7( 40, 49, 52, 5B, 64, 6D, 7F ): // LD B,B etc. |
272 | goto loop; | 272 | goto loop; |
273 | 273 | ||
274 | case 0x08:{// EX AF,AF' | 274 | case 0x08:{// EX AF,AF' |
275 | EXX( b.a ); | 275 | EXX( b.a ); |
276 | EX( R.alt.b.flags, flags ); | 276 | EX( R.alt.b.flags, flags ); |
277 | goto loop; | 277 | goto loop; |
278 | } | 278 | } |
279 | 279 | ||
280 | case 0xD3: // OUT (imm),A | 280 | case 0xD3: // OUT (imm),A |
281 | pc++; | 281 | pc++; |
282 | OUT_PORT( (data + r.b.a * 0x100), r.b.a ); | 282 | OUT_PORT( (data + r.b.a * 0x100), r.b.a ); |
283 | goto loop; | 283 | goto loop; |
284 | 284 | ||
285 | case 0x2E: // LD L,imm | 285 | case 0x2E: // LD L,imm |
286 | pc++; | 286 | pc++; |
287 | r.b.l = data; | 287 | r.b.l = data; |
288 | goto loop; | 288 | goto loop; |
289 | 289 | ||
290 | case 0x3E: // LD A,imm | 290 | case 0x3E: // LD A,imm |
291 | pc++; | 291 | pc++; |
292 | r.b.a = data; | 292 | r.b.a = data; |
293 | goto loop; | 293 | goto loop; |
294 | 294 | ||
295 | case 0x3A:{// LD A,(addr) | 295 | case 0x3A:{// LD A,(addr) |
296 | int addr = GET_ADDR(); | 296 | int addr = GET_ADDR(); |
297 | pc += 2; | 297 | pc += 2; |
298 | r.b.a = READ_MEM( addr ); | 298 | r.b.a = READ_MEM( addr ); |
299 | goto loop; | 299 | goto loop; |
300 | } | 300 | } |
301 | 301 | ||
302 | // Conditional | 302 | // Conditional |
303 | 303 | ||
304 | #define ZERO (flags & Z40) | 304 | #define ZERO (flags & Z40) |
305 | #define CARRY (flags & C01) | 305 | #define CARRY (flags & C01) |
306 | #define EVEN (flags & P04) | 306 | #define EVEN (flags & P04) |
307 | #define MINUS (flags & S80) | 307 | #define MINUS (flags & S80) |
308 | 308 | ||
309 | // JR | 309 | // JR |
310 | // TODO: more efficient way to handle negative branch that wraps PC around | 310 | // TODO: more efficient way to handle negative branch that wraps PC around |
311 | #define JR_( cond, clocks ) {\ | 311 | #define JR_( cond, clocks ) {\ |
312 | pc++;\ | 312 | pc++;\ |
313 | if ( !(cond) )\ | 313 | if ( !(cond) )\ |
314 | goto loop;\ | 314 | goto loop;\ |
315 | int offset = SBYTE( data );\ | 315 | int offset = SBYTE( data );\ |
316 | pc = WORD( pc + offset );\ | 316 | pc = WORD( pc + offset );\ |
317 | s_time += clocks;\ | 317 | s_time += clocks;\ |
318 | goto loop;\ | 318 | goto loop;\ |
319 | } | 319 | } |
320 | 320 | ||
321 | #define JR( cond ) JR_( cond, 5 ) | 321 | #define JR( cond ) JR_( cond, 5 ) |
322 | 322 | ||
323 | case 0x20: JR( !ZERO ) // JR NZ,disp | 323 | case 0x20: JR( !ZERO ) // JR NZ,disp |
324 | case 0x28: JR( ZERO ) // JR Z,disp | 324 | case 0x28: JR( ZERO ) // JR Z,disp |
325 | case 0x30: JR( !CARRY ) // JR NC,disp | 325 | case 0x30: JR( !CARRY ) // JR NC,disp |
326 | case 0x38: JR( CARRY ) // JR C,disp | 326 | case 0x38: JR( CARRY ) // JR C,disp |
327 | case 0x18: JR_( true,0) // JR disp | 327 | case 0x18: JR_( true,0) // JR disp |
328 | 328 | ||
329 | case 0x10:{// DJNZ disp | 329 | case 0x10:{// DJNZ disp |
330 | int temp = r.b.b - 1; | 330 | int temp = r.b.b - 1; |
331 | r.b.b = temp; | 331 | r.b.b = temp; |
332 | JR( temp ) | 332 | JR( temp ) |
333 | } | 333 | } |
334 | 334 | ||
335 | // JP | 335 | // JP |
336 | #define JP( cond ) \ | 336 | #define JP( cond ) \ |
337 | if ( !(cond) )\ | 337 | if ( !(cond) )\ |
338 | goto jp_not_taken;\ | 338 | goto jp_not_taken;\ |
339 | pc = GET_ADDR();\ | 339 | pc = GET_ADDR();\ |
340 | goto loop; | 340 | goto loop; |
341 | 341 | ||
342 | case 0xC2: JP( !ZERO ) // JP NZ,addr | 342 | case 0xC2: JP( !ZERO ) // JP NZ,addr |
343 | case 0xCA: JP( ZERO ) // JP Z,addr | 343 | case 0xCA: JP( ZERO ) // JP Z,addr |
344 | case 0xD2: JP( !CARRY ) // JP NC,addr | 344 | case 0xD2: JP( !CARRY ) // JP NC,addr |
345 | case 0xDA: JP( CARRY ) // JP C,addr | 345 | case 0xDA: JP( CARRY ) // JP C,addr |
346 | case 0xE2: JP( !EVEN ) // JP PO,addr | 346 | case 0xE2: JP( !EVEN ) // JP PO,addr |
347 | case 0xEA: JP( EVEN ) // JP PE,addr | 347 | case 0xEA: JP( EVEN ) // JP PE,addr |
348 | case 0xF2: JP( !MINUS ) // JP P,addr | 348 | case 0xF2: JP( !MINUS ) // JP P,addr |
349 | case 0xFA: JP( MINUS ) // JP M,addr | 349 | case 0xFA: JP( MINUS ) // JP M,addr |
350 | 350 | ||
351 | case 0xC3: // JP addr | 351 | case 0xC3: // JP addr |
352 | pc = GET_ADDR(); | 352 | pc = GET_ADDR(); |
353 | goto loop; | 353 | goto loop; |
354 | 354 | ||
355 | case 0xE9: // JP HL | 355 | case 0xE9: // JP HL |
356 | pc = r.w.hl; | 356 | pc = r.w.hl; |
357 | goto loop; | 357 | goto loop; |
358 | 358 | ||
359 | // RET | 359 | // RET |
360 | #define RET( cond ) \ | 360 | #define RET( cond ) \ |
361 | if ( cond )\ | 361 | if ( cond )\ |
362 | goto ret_taken;\ | 362 | goto ret_taken;\ |
363 | s_time -= 6;\ | 363 | s_time -= 6;\ |
364 | goto loop; | 364 | goto loop; |
365 | 365 | ||
366 | case 0xC0: RET( !ZERO ) // RET NZ | 366 | case 0xC0: RET( !ZERO ) // RET NZ |
367 | case 0xC8: RET( ZERO ) // RET Z | 367 | case 0xC8: RET( ZERO ) // RET Z |
368 | case 0xD0: RET( !CARRY ) // RET NC | 368 | case 0xD0: RET( !CARRY ) // RET NC |
369 | case 0xD8: RET( CARRY ) // RET C | 369 | case 0xD8: RET( CARRY ) // RET C |
370 | case 0xE0: RET( !EVEN ) // RET PO | 370 | case 0xE0: RET( !EVEN ) // RET PO |
371 | case 0xE8: RET( EVEN ) // RET PE | 371 | case 0xE8: RET( EVEN ) // RET PE |
372 | case 0xF0: RET( !MINUS ) // RET P | 372 | case 0xF0: RET( !MINUS ) // RET P |
373 | case 0xF8: RET( MINUS ) // RET M | 373 | case 0xF8: RET( MINUS ) // RET M |
374 | 374 | ||
375 | case 0xC9: // RET | 375 | case 0xC9: // RET |
376 | ret_taken: | 376 | ret_taken: |
377 | pc = READ_WORD( sp ); | 377 | pc = READ_WORD( sp ); |
378 | sp = WORD( sp + 2 ); | 378 | sp = WORD( sp + 2 ); |
379 | goto loop; | 379 | goto loop; |
380 | 380 | ||
381 | // CALL | 381 | // CALL |
382 | #define CALL( cond ) \ | 382 | #define CALL( cond ) \ |
383 | if ( cond )\ | 383 | if ( cond )\ |
384 | goto call_taken;\ | 384 | goto call_taken;\ |
385 | goto call_not_taken; | 385 | goto call_not_taken; |
386 | 386 | ||
387 | case 0xC4: CALL( !ZERO ) // CALL NZ,addr | 387 | case 0xC4: CALL( !ZERO ) // CALL NZ,addr |
388 | case 0xCC: CALL( ZERO ) // CALL Z,addr | 388 | case 0xCC: CALL( ZERO ) // CALL Z,addr |
389 | case 0xD4: CALL( !CARRY ) // CALL NC,addr | 389 | case 0xD4: CALL( !CARRY ) // CALL NC,addr |
390 | case 0xDC: CALL( CARRY ) // CALL C,addr | 390 | case 0xDC: CALL( CARRY ) // CALL C,addr |
391 | case 0xE4: CALL( !EVEN ) // CALL PO,addr | 391 | case 0xE4: CALL( !EVEN ) // CALL PO,addr |
392 | case 0xEC: CALL( EVEN ) // CALL PE,addr | 392 | case 0xEC: CALL( EVEN ) // CALL PE,addr |
393 | case 0xF4: CALL( !MINUS ) // CALL P,addr | 393 | case 0xF4: CALL( !MINUS ) // CALL P,addr |
394 | case 0xFC: CALL( MINUS ) // CALL M,addr | 394 | case 0xFC: CALL( MINUS ) // CALL M,addr |
395 | 395 | ||
396 | case 0xCD:{// CALL addr | 396 | case 0xCD:{// CALL addr |
397 | call_taken: { | 397 | call_taken: { |
398 | int addr = pc + 2; | 398 | int addr = pc + 2; |
399 | pc = GET_ADDR(); | 399 | pc = GET_ADDR(); |
400 | sp = WORD( sp - 2 ); | 400 | sp = WORD( sp - 2 ); |
401 | WRITE_WORD( sp, addr ); | 401 | WRITE_WORD( sp, addr ); |
402 | goto loop; | 402 | goto loop; |
403 | } | 403 | } |
404 | } | 404 | } |
405 | 405 | ||
406 | case 0xFF: // RST | 406 | case 0xFF: // RST |
407 | #ifdef IDLE_ADDR | 407 | #ifdef IDLE_ADDR |
408 | if ( pc == IDLE_ADDR + 1 ) | 408 | if ( pc == IDLE_ADDR + 1 ) |
409 | goto hit_idle_addr; | 409 | goto hit_idle_addr; |
410 | #else | 410 | #else |
411 | if ( pc > 0x10000 ) | 411 | if ( pc > 0x10000 ) |
412 | { | 412 | { |
413 | pc = WORD( pc - 1 ); | 413 | pc = WORD( pc - 1 ); |
414 | s_time -= 11; | 414 | s_time -= 11; |
415 | goto loop; | 415 | goto loop; |
416 | } | 416 | } |
417 | #endif | 417 | #endif |
418 | CASE7( C7, CF, D7, DF, E7, EF, F7 ): | 418 | CASE7( C7, CF, D7, DF, E7, EF, F7 ): |
419 | data = pc; | 419 | data = pc; |
420 | pc = opcode & 0x38; | 420 | pc = opcode & 0x38; |
421 | #ifdef RST_BASE | 421 | #ifdef RST_BASE |
422 | pc += RST_BASE; | 422 | pc += RST_BASE; |
423 | #endif | 423 | #endif |
424 | goto push_data; | 424 | goto push_data; |
425 | 425 | ||
426 | // PUSH/POP | 426 | // PUSH/POP |
427 | case 0xF5: // PUSH AF | 427 | case 0xF5: // PUSH AF |
428 | data = r.b.a * 0x100u + flags; | 428 | data = r.b.a * 0x100u + flags; |
429 | goto push_data; | 429 | goto push_data; |
430 | 430 | ||
431 | case 0xC5: // PUSH BC | 431 | case 0xC5: // PUSH BC |
432 | case 0xD5: // PUSH DE | 432 | case 0xD5: // PUSH DE |
433 | case 0xE5: // PUSH HL | 433 | case 0xE5: // PUSH HL |
434 | data = R16( opcode, 4, 0xC5 ); | 434 | data = R16( opcode, 4, 0xC5 ); |
435 | push_data: | 435 | push_data: |
436 | sp = WORD( sp - 2 ); | 436 | sp = WORD( sp - 2 ); |
437 | WRITE_WORD( sp, data ); | 437 | WRITE_WORD( sp, data ); |
438 | goto loop; | 438 | goto loop; |
439 | 439 | ||
440 | case 0xF1: // POP AF | 440 | case 0xF1: // POP AF |
441 | flags = READ_MEM( sp ); | 441 | flags = READ_MEM( sp ); |
442 | r.b.a = READ_MEM( (sp + 1) ); | 442 | r.b.a = READ_MEM( (sp + 1) ); |
443 | sp = WORD( sp + 2 ); | 443 | sp = WORD( sp + 2 ); |
444 | goto loop; | 444 | goto loop; |
445 | 445 | ||
446 | case 0xC1: // POP BC | 446 | case 0xC1: // POP BC |
447 | case 0xD1: // POP DE | 447 | case 0xD1: // POP DE |
448 | case 0xE1: // POP HL | 448 | case 0xE1: // POP HL |
449 | R16( opcode, 4, 0xC1 ) = READ_WORD( sp ); | 449 | R16( opcode, 4, 0xC1 ) = READ_WORD( sp ); |
450 | sp = WORD( sp + 2 ); | 450 | sp = WORD( sp + 2 ); |
451 | goto loop; | 451 | goto loop; |
452 | 452 | ||
453 | // ADC/ADD/SBC/SUB | 453 | // ADC/ADD/SBC/SUB |
454 | case 0x96: // SUB (HL) | 454 | case 0x96: // SUB (HL) |
455 | case 0x86: // ADD (HL) | 455 | case 0x86: // ADD (HL) |
456 | flags &= ~C01; | 456 | flags &= ~C01; |
457 | case 0x9E: // SBC (HL) | 457 | case 0x9E: // SBC (HL) |
458 | case 0x8E: // ADC (HL) | 458 | case 0x8E: // ADC (HL) |
459 | data = READ_MEM( r.w.hl ); | 459 | data = READ_MEM( r.w.hl ); |
460 | goto adc_data; | 460 | goto adc_data; |
461 | 461 | ||
462 | case 0xD6: // SUB A,imm | 462 | case 0xD6: // SUB A,imm |
463 | case 0xC6: // ADD imm | 463 | case 0xC6: // ADD imm |
464 | flags &= ~C01; | 464 | flags &= ~C01; |
465 | case 0xDE: // SBC A,imm | 465 | case 0xDE: // SBC A,imm |
466 | case 0xCE: // ADC imm | 466 | case 0xCE: // ADC imm |
467 | pc++; | 467 | pc++; |
468 | goto adc_data; | 468 | goto adc_data; |
469 | 469 | ||
470 | CASE7( 90, 91, 92, 93, 94, 95, 97 ): // SUB r | 470 | CASE7( 90, 91, 92, 93, 94, 95, 97 ): // SUB r |
471 | CASE7( 80, 81, 82, 83, 84, 85, 87 ): // ADD r | 471 | CASE7( 80, 81, 82, 83, 84, 85, 87 ): // ADD r |
472 | flags &= ~C01; | 472 | flags &= ~C01; |
473 | CASE7( 98, 99, 9A, 9B, 9C, 9D, 9F ): // SBC r | 473 | CASE7( 98, 99, 9A, 9B, 9C, 9D, 9F ): // SBC r |
474 | CASE7( 88, 89, 8A, 8B, 8C, 8D, 8F ): // ADC r | 474 | CASE7( 88, 89, 8A, 8B, 8C, 8D, 8F ): // ADC r |
475 | data = R8( opcode & 7, 0 ); | 475 | data = R8( opcode & 7, 0 ); |
476 | adc_data: { | 476 | adc_data: { |
477 | int result = data + (flags & C01); | 477 | int result = data + (flags & C01); |
478 | data ^= r.b.a; | 478 | data ^= r.b.a; |
479 | flags = opcode >> 3 & N02; // bit 4 is set in subtract opcodes | 479 | flags = opcode >> 3 & N02; // bit 4 is set in subtract opcodes |
480 | if ( flags ) | 480 | if ( flags ) |
481 | result = -result; | 481 | result = -result; |
482 | result += r.b.a; | 482 | result += r.b.a; |
483 | data ^= result; | 483 | data ^= result; |
484 | flags +=(data & H10) + | 484 | flags +=(data & H10) + |
485 | ((data + 0x80) >> 6 & V04) + | 485 | ((data + 0x80) >> 6 & V04) + |
486 | SZ28C( result & 0x1FF ); | 486 | SZ28C( result & 0x1FF ); |
487 | r.b.a = result; | 487 | r.b.a = result; |
488 | goto loop; | 488 | goto loop; |
489 | } | 489 | } |
490 | 490 | ||
491 | // CP | 491 | // CP |
492 | case 0xBE: // CP (HL) | 492 | case 0xBE: // CP (HL) |
493 | data = READ_MEM( r.w.hl ); | 493 | data = READ_MEM( r.w.hl ); |
494 | goto cp_data; | 494 | goto cp_data; |
495 | 495 | ||
496 | case 0xFE: // CP imm | 496 | case 0xFE: // CP imm |
497 | pc++; | 497 | pc++; |
498 | goto cp_data; | 498 | goto cp_data; |
499 | 499 | ||
500 | CASE7( B8, B9, BA, BB, BC, BD, BF ): // CP r | 500 | CASE7( B8, B9, BA, BB, BC, BD, BF ): // CP r |
501 | data = R8( opcode, 0xB8 ); | 501 | data = R8( opcode, 0xB8 ); |
502 | cp_data: { | 502 | cp_data: { |
503 | int result = r.b.a - data; | 503 | int result = r.b.a - data; |
504 | flags = N02 + (data & (F20 | F08)) + (result >> 8 & C01); | 504 | flags = N02 + (data & (F20 | F08)) + (result >> 8 & C01); |
505 | data ^= r.b.a; | 505 | data ^= r.b.a; |
506 | flags +=(((result ^ r.b.a) & data) >> 5 & V04) + | 506 | flags +=(((result ^ r.b.a) & data) >> 5 & V04) + |
507 | (((data & H10) ^ result) & (S80 | H10)); | 507 | (((data & H10) ^ result) & (S80 | H10)); |
508 | if ( BYTE( result ) ) | 508 | if ( BYTE( result ) ) |
509 | goto loop; | 509 | goto loop; |
510 | flags += Z40; | 510 | flags += Z40; |
511 | goto loop; | 511 | goto loop; |
512 | } | 512 | } |
513 | 513 | ||
514 | // ADD HL,r.w | 514 | // ADD HL,r.w |
515 | 515 | ||
516 | case 0x39: // ADD HL,SP | 516 | case 0x39: // ADD HL,SP |
517 | data = sp; | 517 | data = sp; |
518 | goto add_hl_data; | 518 | goto add_hl_data; |
519 | 519 | ||
520 | case 0x09: // ADD HL,BC | 520 | case 0x09: // ADD HL,BC |
521 | case 0x19: // ADD HL,DE | 521 | case 0x19: // ADD HL,DE |
522 | case 0x29: // ADD HL,HL | 522 | case 0x29: // ADD HL,HL |
523 | data = R16( opcode, 4, 0x09 ); | 523 | data = R16( opcode, 4, 0x09 ); |
524 | add_hl_data: { | 524 | add_hl_data: { |
525 | int sum = r.w.hl + data; | 525 | int sum = r.w.hl + data; |
526 | data ^= r.w.hl; | 526 | data ^= r.w.hl; |
527 | r.w.hl = sum; | 527 | r.w.hl = sum; |
528 | flags = (flags & (S80 | Z40 | V04)) + | 528 | flags = (flags & (S80 | Z40 | V04)) + |
529 | (sum >> 16) + | 529 | (sum >> 16) + |
530 | (sum >> 8 & (F20 | F08)) + | 530 | (sum >> 8 & (F20 | F08)) + |
531 | ((data ^ sum) >> 8 & H10); | 531 | ((data ^ sum) >> 8 & H10); |
532 | goto loop; | 532 | goto loop; |
533 | } | 533 | } |
534 | 534 | ||
535 | case 0x27:{// DAA | 535 | case 0x27:{// DAA |
536 | int a = r.b.a; | 536 | int a = r.b.a; |
537 | if ( a > 0x99 ) | 537 | if ( a > 0x99 ) |
538 | flags |= C01; | 538 | flags |= C01; |
539 | 539 | ||
540 | int adjust = 0x60 * (flags & C01); | 540 | int adjust = 0x60 * (flags & C01); |
541 | 541 | ||
542 | if ( flags & H10 || (a & 0x0F) > 9 ) | 542 | if ( flags & H10 || (a & 0x0F) > 9 ) |
543 | adjust += 0x06; | 543 | adjust += 0x06; |
544 | 544 | ||
545 | if ( flags & N02 ) | 545 | if ( flags & N02 ) |
546 | adjust = -adjust; | 546 | adjust = -adjust; |
547 | a += adjust; | 547 | a += adjust; |
548 | 548 | ||
549 | flags = (flags & (C01 | N02)) + | 549 | flags = (flags & (C01 | N02)) + |
550 | ((r.b.a ^ a) & H10) + | 550 | ((r.b.a ^ a) & H10) + |
551 | SZ28P( BYTE( a ) ); | 551 | SZ28P( BYTE( a ) ); |
552 | r.b.a = a; | 552 | r.b.a = a; |
553 | goto loop; | 553 | goto loop; |
554 | } | 554 | } |
555 | 555 | ||
556 | // INC/DEC | 556 | // INC/DEC |
557 | case 0x34: // INC (HL) | 557 | case 0x34: // INC (HL) |
558 | data = READ_MEM( r.w.hl ) + 1; | 558 | data = READ_MEM( r.w.hl ) + 1; |
559 | WRITE_MEM( r.w.hl, data ); | 559 | WRITE_MEM( r.w.hl, data ); |
560 | goto inc_set_flags; | 560 | goto inc_set_flags; |
561 | 561 | ||
562 | CASE7( 04, 0C, 14, 1C, 24, 2C, 3C ): // INC r | 562 | CASE7( 04, 0C, 14, 1C, 24, 2C, 3C ): // INC r |
563 | data = ++R8( opcode >> 3, 0 ); | 563 | data = ++R8( opcode >> 3, 0 ); |
564 | inc_set_flags: | 564 | inc_set_flags: |
565 | flags = (flags & C01) + | 565 | flags = (flags & C01) + |
566 | (((data & 0x0F) - 1) & H10) + | 566 | (((data & 0x0F) - 1) & H10) + |
567 | SZ28( BYTE( data ) ); | 567 | SZ28( BYTE( data ) ); |
568 | if ( data != 0x80 ) | 568 | if ( data != 0x80 ) |
569 | goto loop; | 569 | goto loop; |
570 | flags += V04; | 570 | flags += V04; |
571 | goto loop; | 571 | goto loop; |
572 | 572 | ||
573 | case 0x35: // DEC (HL) | 573 | case 0x35: // DEC (HL) |
574 | data = READ_MEM( r.w.hl ) - 1; | 574 | data = READ_MEM( r.w.hl ) - 1; |
575 | WRITE_MEM( r.w.hl, data ); | 575 | WRITE_MEM( r.w.hl, data ); |
576 | goto dec_set_flags; | 576 | goto dec_set_flags; |
577 | 577 | ||
578 | CASE7( 05, 0D, 15, 1D, 25, 2D, 3D ): // DEC r | 578 | CASE7( 05, 0D, 15, 1D, 25, 2D, 3D ): // DEC r |
579 | data = --R8( opcode >> 3, 0 ); | 579 | data = --R8( opcode >> 3, 0 ); |
580 | dec_set_flags: | 580 | dec_set_flags: |
581 | flags = (flags & C01) + N02 + | 581 | flags = (flags & C01) + N02 + |
582 | (((data & 0x0F) + 1) & H10) + | 582 | (((data & 0x0F) + 1) & H10) + |
583 | SZ28( BYTE( data ) ); | 583 | SZ28( BYTE( data ) ); |
584 | if ( data != 0x7F ) | 584 | if ( data != 0x7F ) |
585 | goto loop; | 585 | goto loop; |
586 | flags += V04; | 586 | flags += V04; |
587 | goto loop; | 587 | goto loop; |
588 | 588 | ||
589 | case 0x03: // INC BC | 589 | case 0x03: // INC BC |
590 | case 0x13: // INC DE | 590 | case 0x13: // INC DE |
591 | case 0x23: // INC HL | 591 | case 0x23: // INC HL |
592 | R16( opcode, 4, 0x03 )++; | 592 | R16( opcode, 4, 0x03 )++; |
593 | goto loop; | 593 | goto loop; |
594 | 594 | ||
595 | case 0x33: // INC SP | 595 | case 0x33: // INC SP |
596 | sp = WORD( sp + 1 ); | 596 | sp = WORD( sp + 1 ); |
597 | goto loop; | 597 | goto loop; |
598 | 598 | ||
599 | case 0x0B: // DEC BC | 599 | case 0x0B: // DEC BC |
600 | case 0x1B: // DEC DE | 600 | case 0x1B: // DEC DE |
601 | case 0x2B: // DEC HL | 601 | case 0x2B: // DEC HL |
602 | R16( opcode, 4, 0x0B )--; | 602 | R16( opcode, 4, 0x0B )--; |
603 | goto loop; | 603 | goto loop; |
604 | 604 | ||
605 | case 0x3B: // DEC SP | 605 | case 0x3B: // DEC SP |
606 | sp = WORD( sp - 1 ); | 606 | sp = WORD( sp - 1 ); |
607 | goto loop; | 607 | goto loop; |
608 | 608 | ||
609 | // AND | 609 | // AND |
610 | case 0xA6: // AND (HL) | 610 | case 0xA6: // AND (HL) |
611 | data = READ_MEM( r.w.hl ); | 611 | data = READ_MEM( r.w.hl ); |
612 | goto and_data; | 612 | goto and_data; |
613 | 613 | ||
614 | case 0xE6: // AND imm | 614 | case 0xE6: // AND imm |
615 | pc++; | 615 | pc++; |
616 | goto and_data; | 616 | goto and_data; |
617 | 617 | ||
618 | CASE7( A0, A1, A2, A3, A4, A5, A7 ): // AND r | 618 | CASE7( A0, A1, A2, A3, A4, A5, A7 ): // AND r |
619 | data = R8( opcode, 0xA0 ); | 619 | data = R8( opcode, 0xA0 ); |
620 | and_data: | 620 | and_data: |
621 | r.b.a &= data; | 621 | r.b.a &= data; |
622 | flags = SZ28P( r.b.a ) + H10; | 622 | flags = SZ28P( r.b.a ) + H10; |
623 | goto loop; | 623 | goto loop; |
624 | 624 | ||
625 | // OR | 625 | // OR |
626 | case 0xB6: // OR (HL) | 626 | case 0xB6: // OR (HL) |
627 | data = READ_MEM( r.w.hl ); | 627 | data = READ_MEM( r.w.hl ); |
628 | goto or_data; | 628 | goto or_data; |
629 | 629 | ||
630 | case 0xF6: // OR imm | 630 | case 0xF6: // OR imm |
631 | pc++; | 631 | pc++; |
632 | goto or_data; | 632 | goto or_data; |
633 | 633 | ||
634 | CASE7( B0, B1, B2, B3, B4, B5, B7 ): // OR r | 634 | CASE7( B0, B1, B2, B3, B4, B5, B7 ): // OR r |
635 | data = R8( opcode, 0xB0 ); | 635 | data = R8( opcode, 0xB0 ); |
636 | or_data: | 636 | or_data: |
637 | r.b.a |= data; | 637 | r.b.a |= data; |
638 | flags = SZ28P( r.b.a ); | 638 | flags = SZ28P( r.b.a ); |
639 | goto loop; | 639 | goto loop; |
640 | 640 | ||
641 | // XOR | 641 | // XOR |
642 | case 0xAE: // XOR (HL) | 642 | case 0xAE: // XOR (HL) |
643 | data = READ_MEM( r.w.hl ); | 643 | data = READ_MEM( r.w.hl ); |
644 | goto xor_data; | 644 | goto xor_data; |
645 | 645 | ||
646 | case 0xEE: // XOR imm | 646 | case 0xEE: // XOR imm |
647 | pc++; | 647 | pc++; |
648 | goto xor_data; | 648 | goto xor_data; |
649 | 649 | ||
650 | CASE7( A8, A9, AA, AB, AC, AD, AF ): // XOR r | 650 | CASE7( A8, A9, AA, AB, AC, AD, AF ): // XOR r |
651 | data = R8( opcode, 0xA8 ); | 651 | data = R8( opcode, 0xA8 ); |
652 | xor_data: | 652 | xor_data: |
653 | r.b.a ^= data; | 653 | r.b.a ^= data; |
654 | flags = SZ28P( r.b.a ); | 654 | flags = SZ28P( r.b.a ); |
655 | goto loop; | 655 | goto loop; |
656 | 656 | ||
657 | // LD | 657 | // LD |
658 | CASE7( 70, 71, 72, 73, 74, 75, 77 ): // LD (HL),r | 658 | CASE7( 70, 71, 72, 73, 74, 75, 77 ): // LD (HL),r |
659 | WRITE_MEM( r.w.hl, R8( opcode, 0x70 ) ); | 659 | WRITE_MEM( r.w.hl, R8( opcode, 0x70 ) ); |
660 | goto loop; | 660 | goto loop; |
661 | 661 | ||
662 | CASE6( 41, 42, 43, 44, 45, 47 ): // LD B,r | 662 | CASE6( 41, 42, 43, 44, 45, 47 ): // LD B,r |
663 | CASE6( 48, 4A, 4B, 4C, 4D, 4F ): // LD C,r | 663 | CASE6( 48, 4A, 4B, 4C, 4D, 4F ): // LD C,r |
664 | CASE6( 50, 51, 53, 54, 55, 57 ): // LD D,r | 664 | CASE6( 50, 51, 53, 54, 55, 57 ): // LD D,r |
665 | CASE6( 58, 59, 5A, 5C, 5D, 5F ): // LD E,r | 665 | CASE6( 58, 59, 5A, 5C, 5D, 5F ): // LD E,r |
666 | CASE6( 60, 61, 62, 63, 65, 67 ): // LD H,r | 666 | CASE6( 60, 61, 62, 63, 65, 67 ): // LD H,r |
667 | CASE6( 68, 69, 6A, 6B, 6C, 6F ): // LD L,r | 667 | CASE6( 68, 69, 6A, 6B, 6C, 6F ): // LD L,r |
668 | CASE6( 78, 79, 7A, 7B, 7C, 7D ): // LD A,r | 668 | CASE6( 78, 79, 7A, 7B, 7C, 7D ): // LD A,r |
669 | R8( opcode >> 3 & 7, 0 ) = R8( opcode & 7, 0 ); | 669 | R8( opcode >> 3 & 7, 0 ) = R8( opcode & 7, 0 ); |
670 | goto loop; | 670 | goto loop; |
671 | 671 | ||
672 | CASE5( 06, 0E, 16, 1E, 26 ): // LD r,imm | 672 | CASE5( 06, 0E, 16, 1E, 26 ): // LD r,imm |
673 | R8( opcode >> 3, 0 ) = data; | 673 | R8( opcode >> 3, 0 ) = data; |
674 | pc++; | 674 | pc++; |
675 | goto loop; | 675 | goto loop; |
676 | 676 | ||
677 | case 0x36: // LD (HL),imm | 677 | case 0x36: // LD (HL),imm |
678 | pc++; | 678 | pc++; |
679 | WRITE_MEM( r.w.hl, data ); | 679 | WRITE_MEM( r.w.hl, data ); |
680 | goto loop; | 680 | goto loop; |
681 | 681 | ||
682 | CASE7( 46, 4E, 56, 5E, 66, 6E, 7E ): // LD r,(HL) | 682 | CASE7( 46, 4E, 56, 5E, 66, 6E, 7E ): // LD r,(HL) |
683 | R8( opcode >> 3, 8 ) = READ_MEM( r.w.hl ); | 683 | R8( opcode >> 3, 8 ) = READ_MEM( r.w.hl ); |
684 | goto loop; | 684 | goto loop; |
685 | 685 | ||
686 | case 0x01: // LD r.w,imm | 686 | case 0x01: // LD r.w,imm |
687 | case 0x11: | 687 | case 0x11: |
688 | case 0x21: | 688 | case 0x21: |
689 | R16( opcode, 4, 0x01 ) = GET_ADDR(); | 689 | R16( opcode, 4, 0x01 ) = GET_ADDR(); |
690 | pc += 2; | 690 | pc += 2; |
691 | goto loop; | 691 | goto loop; |
692 | 692 | ||
693 | case 0x31: // LD sp,imm | 693 | case 0x31: // LD sp,imm |
694 | sp = GET_ADDR(); | 694 | sp = GET_ADDR(); |
695 | pc += 2; | 695 | pc += 2; |
696 | goto loop; | 696 | goto loop; |
697 | 697 | ||
698 | case 0x2A:{// LD HL,(addr) | 698 | case 0x2A:{// LD HL,(addr) |
699 | int addr = GET_ADDR(); | 699 | int addr = GET_ADDR(); |
700 | pc += 2; | 700 | pc += 2; |
701 | r.w.hl = READ_WORD( addr ); | 701 | r.w.hl = READ_WORD( addr ); |
702 | goto loop; | 702 | goto loop; |
703 | } | 703 | } |
704 | 704 | ||
705 | case 0x32:{// LD (addr),A | 705 | case 0x32:{// LD (addr),A |
706 | int addr = GET_ADDR(); | 706 | int addr = GET_ADDR(); |
707 | pc += 2; | 707 | pc += 2; |
708 | WRITE_MEM( addr, r.b.a ); | 708 | WRITE_MEM( addr, r.b.a ); |
709 | goto loop; | 709 | goto loop; |
710 | } | 710 | } |
711 | 711 | ||
712 | case 0x22:{// LD (addr),HL | 712 | case 0x22:{// LD (addr),HL |
713 | int addr = GET_ADDR(); | 713 | int addr = GET_ADDR(); |
714 | pc += 2; | 714 | pc += 2; |
715 | WRITE_WORD( addr, r.w.hl ); | 715 | WRITE_WORD( addr, r.w.hl ); |
716 | goto loop; | 716 | goto loop; |
717 | } | 717 | } |
718 | 718 | ||
719 | case 0x02: // LD (BC),A | 719 | case 0x02: // LD (BC),A |
720 | case 0x12: // LD (DE),A | 720 | case 0x12: // LD (DE),A |
721 | WRITE_MEM( R16( opcode, 4, 0x02 ), r.b.a ); | 721 | WRITE_MEM( R16( opcode, 4, 0x02 ), r.b.a ); |
722 | goto loop; | 722 | goto loop; |
723 | 723 | ||
724 | case 0x0A: // LD A,(BC) | 724 | case 0x0A: // LD A,(BC) |
725 | case 0x1A: // LD A,(DE) | 725 | case 0x1A: // LD A,(DE) |
726 | r.b.a = READ_MEM( R16( opcode, 4, 0x0A ) ); | 726 | r.b.a = READ_MEM( R16( opcode, 4, 0x0A ) ); |
727 | goto loop; | 727 | goto loop; |
728 | 728 | ||
729 | case 0xF9: // LD SP,HL | 729 | case 0xF9: // LD SP,HL |
730 | sp = r.w.hl; | 730 | sp = r.w.hl; |
731 | goto loop; | 731 | goto loop; |
732 | 732 | ||
733 | // Rotate | 733 | // Rotate |
734 | 734 | ||
735 | case 0x07:{// RLCA | 735 | case 0x07:{// RLCA |
736 | int temp = r.b.a; | 736 | int temp = r.b.a; |
737 | temp = (temp << 1) + (temp >> 7); | 737 | temp = (temp << 1) + (temp >> 7); |
738 | flags = (flags & (S80 | Z40 | P04)) + | 738 | flags = (flags & (S80 | Z40 | P04)) + |
739 | (temp & (F20 | F08 | C01)); | 739 | (temp & (F20 | F08 | C01)); |
740 | r.b.a = temp; | 740 | r.b.a = temp; |
741 | goto loop; | 741 | goto loop; |
742 | } | 742 | } |
743 | 743 | ||
744 | case 0x0F:{// RRCA | 744 | case 0x0F:{// RRCA |
745 | int temp = r.b.a; | 745 | int temp = r.b.a; |
746 | flags = (flags & (S80 | Z40 | P04)) + | 746 | flags = (flags & (S80 | Z40 | P04)) + |
747 | (temp & C01); | 747 | (temp & C01); |
748 | temp = (temp << 7) + (temp >> 1); | 748 | temp = (temp << 7) + (temp >> 1); |
749 | flags += temp & (F20 | F08); | 749 | flags += temp & (F20 | F08); |
750 | r.b.a = temp; | 750 | r.b.a = temp; |
751 | goto loop; | 751 | goto loop; |
752 | } | 752 | } |
753 | 753 | ||
754 | case 0x17:{// RLA | 754 | case 0x17:{// RLA |
755 | int temp = (r.b.a << 1) + (flags & C01); | 755 | int temp = (r.b.a << 1) + (flags & C01); |
756 | flags = (flags & (S80 | Z40 | P04)) + | 756 | flags = (flags & (S80 | Z40 | P04)) + |
757 | (temp & (F20 | F08)) + | 757 | (temp & (F20 | F08)) + |
758 | (temp >> 8); | 758 | (temp >> 8); |
759 | r.b.a = temp; | 759 | r.b.a = temp; |
760 | goto loop; | 760 | goto loop; |
761 | } | 761 | } |
762 | 762 | ||
763 | case 0x1F:{// RRA | 763 | case 0x1F:{// RRA |
764 | int temp = (flags << 7) + (r.b.a >> 1); | 764 | int temp = (flags << 7) + (r.b.a >> 1); |
765 | flags = (flags & (S80 | Z40 | P04)) + | 765 | flags = (flags & (S80 | Z40 | P04)) + |
766 | (temp & (F20 | F08)) + | 766 | (temp & (F20 | F08)) + |
767 | (r.b.a & C01); | 767 | (r.b.a & C01); |
768 | r.b.a = temp; | 768 | r.b.a = temp; |
769 | goto loop; | 769 | goto loop; |
770 | } | 770 | } |
771 | 771 | ||
772 | // Misc | 772 | // Misc |
773 | case 0x2F:{// CPL | 773 | case 0x2F:{// CPL |
774 | int temp = ~r.b.a; | 774 | int temp = ~r.b.a; |
775 | flags = (flags & (S80 | Z40 | P04 | C01)) + | 775 | flags = (flags & (S80 | Z40 | P04 | C01)) + |
776 | (temp & (F20 | F08)) + | 776 | (temp & (F20 | F08)) + |
777 | (H10 | N02); | 777 | (H10 | N02); |
778 | r.b.a = temp; | 778 | r.b.a = temp; |
779 | goto loop; | 779 | goto loop; |
780 | } | 780 | } |
781 | 781 | ||
782 | case 0x3F:{// CCF | 782 | case 0x3F:{// CCF |
783 | flags = ((flags & (S80 | Z40 | P04 | C01)) ^ C01) + | 783 | flags = ((flags & (S80 | Z40 | P04 | C01)) ^ C01) + |
784 | (flags << 4 & H10) + | 784 | (flags << 4 & H10) + |
785 | (r.b.a & (F20 | F08)); | 785 | (r.b.a & (F20 | F08)); |
786 | goto loop; | 786 | goto loop; |
787 | } | 787 | } |
788 | 788 | ||
789 | case 0x37: // SCF | 789 | case 0x37: // SCF |
790 | flags = ((flags & (S80 | Z40 | P04)) | C01) + | 790 | flags = ((flags & (S80 | Z40 | P04)) | C01) + |
791 | (r.b.a & (F20 | F08)); | 791 | (r.b.a & (F20 | F08)); |
792 | goto loop; | 792 | goto loop; |
793 | 793 | ||
794 | case 0xDB: // IN A,(imm) | 794 | case 0xDB: // IN A,(imm) |
795 | pc++; | 795 | pc++; |
796 | r.b.a = IN_PORT( (data + r.b.a * 0x100) ); | 796 | r.b.a = IN_PORT( (data + r.b.a * 0x100) ); |
797 | goto loop; | 797 | goto loop; |
798 | 798 | ||
799 | case 0xE3:{// EX (SP),HL | 799 | case 0xE3:{// EX (SP),HL |
800 | int temp = READ_WORD( sp ); | 800 | int temp = READ_WORD( sp ); |
801 | WRITE_WORD( sp, r.w.hl ); | 801 | WRITE_WORD( sp, r.w.hl ); |
802 | r.w.hl = temp; | 802 | r.w.hl = temp; |
803 | goto loop; | 803 | goto loop; |
804 | } | 804 | } |
805 | 805 | ||
806 | case 0xEB: // EX DE,HL | 806 | case 0xEB: // EX DE,HL |
807 | EX( r.w.hl, r.w.de ); | 807 | EX( r.w.hl, r.w.de ); |
808 | goto loop; | 808 | goto loop; |
809 | 809 | ||
810 | case 0xD9: // EXX DE,HL | 810 | case 0xD9: // EXX DE,HL |
811 | EXX( w.bc ); | 811 | EXX( w.bc ); |
812 | EXX( w.de ); | 812 | EXX( w.de ); |
813 | EXX( w.hl ); | 813 | EXX( w.hl ); |
814 | goto loop; | 814 | goto loop; |
815 | 815 | ||
816 | case 0xF3: // DI | 816 | case 0xF3: // DI |
817 | R.iff1 = 0; | 817 | R.iff1 = 0; |
818 | R.iff2 = 0; | 818 | R.iff2 = 0; |
819 | goto loop; | 819 | goto loop; |
820 | 820 | ||
821 | case 0xFB: // EI | 821 | case 0xFB: // EI |
822 | R.iff1 = 1; | 822 | R.iff1 = 1; |
823 | R.iff2 = 1; | 823 | R.iff2 = 1; |
824 | // TODO: delayed effect | 824 | // TODO: delayed effect |
825 | goto loop; | 825 | goto loop; |
826 | 826 | ||
827 | case 0x76: // HALT | 827 | case 0x76: // HALT |
828 | goto halt; | 828 | goto halt; |
829 | 829 | ||
830 | //////////////////////////////////////// CB prefix | 830 | //////////////////////////////////////// CB prefix |
831 | { | 831 | { |
832 | case 0xCB: | 832 | case 0xCB: |
833 | pc++; | 833 | pc++; |
834 | switch ( data ) | 834 | switch ( data ) |
835 | { | 835 | { |
836 | 836 | ||
837 | // Rotate left | 837 | // Rotate left |
838 | 838 | ||
839 | #define RLC( read, write ) {\ | 839 | #define RLC( read, write ) {\ |
840 | int result = read;\ | 840 | int result = read;\ |
841 | result = BYTE( result << 1 ) + (result >> 7);\ | 841 | result = BYTE( result << 1 ) + (result >> 7);\ |
842 | flags = SZ28P( result ) + (result & C01);\ | 842 | flags = SZ28P( result ) + (result & C01);\ |
843 | write;\ | 843 | write;\ |
844 | goto loop;\ | 844 | goto loop;\ |
845 | } | 845 | } |
846 | 846 | ||
847 | case 0x06: // RLC (HL) | 847 | case 0x06: // RLC (HL) |
848 | s_time += 7; | 848 | s_time += 7; |
849 | data = r.w.hl; | 849 | data = r.w.hl; |
850 | rlc_data_addr: | 850 | rlc_data_addr: |
851 | RLC( READ_MEM( data ), WRITE_MEM( data, result ) ) | 851 | RLC( READ_MEM( data ), WRITE_MEM( data, result ) ) |
852 | 852 | ||
853 | CASE7( 00, 01, 02, 03, 04, 05, 07 ):{// RLC r | 853 | CASE7( 00, 01, 02, 03, 04, 05, 07 ):{// RLC r |
854 | byte* reg = &R8( data, 0 ); | 854 | byte* reg = &R8( data, 0 ); |
855 | RLC( *reg, *reg = result ) | 855 | RLC( *reg, *reg = result ) |
856 | } | 856 | } |
857 | 857 | ||
858 | #define RL( read, write ) {\ | 858 | #define RL( read, write ) {\ |
859 | int result = (read << 1) + (flags & C01);\ | 859 | int result = (read << 1) + (flags & C01);\ |
860 | flags = SZ28PC( result );\ | 860 | flags = SZ28PC( result );\ |
861 | write;\ | 861 | write;\ |
862 | goto loop;\ | 862 | goto loop;\ |
863 | } | 863 | } |
864 | 864 | ||
865 | case 0x16: // RL (HL) | 865 | case 0x16: // RL (HL) |
866 | s_time += 7; | 866 | s_time += 7; |
867 | data = r.w.hl; | 867 | data = r.w.hl; |
868 | rl_data_addr: | 868 | rl_data_addr: |
869 | RL( READ_MEM( data ), WRITE_MEM( data, result ) ) | 869 | RL( READ_MEM( data ), WRITE_MEM( data, result ) ) |
870 | 870 | ||
871 | CASE7( 10, 11, 12, 13, 14, 15, 17 ):{// RL r | 871 | CASE7( 10, 11, 12, 13, 14, 15, 17 ):{// RL r |
872 | byte* reg = &R8( data, 0x10 ); | 872 | byte* reg = &R8( data, 0x10 ); |
873 | RL( *reg, *reg = result ) | 873 | RL( *reg, *reg = result ) |
874 | } | 874 | } |
875 | 875 | ||
876 | #define SLA( read, low_bit, write ) {\ | 876 | #define SLA( read, low_bit, write ) {\ |
877 | int result = (read << 1) + low_bit;\ | 877 | int result = (read << 1) + low_bit;\ |
878 | flags = SZ28PC( result );\ | 878 | flags = SZ28PC( result );\ |
879 | write;\ | 879 | write;\ |
880 | goto loop;\ | 880 | goto loop;\ |
881 | } | 881 | } |
882 | 882 | ||
883 | case 0x26: // SLA (HL) | 883 | case 0x26: // SLA (HL) |
884 | s_time += 7; | 884 | s_time += 7; |
885 | data = r.w.hl; | 885 | data = r.w.hl; |
886 | sla_data_addr: | 886 | sla_data_addr: |
887 | SLA( READ_MEM( data ), 0, WRITE_MEM( data, result ) ) | 887 | SLA( READ_MEM( data ), 0, WRITE_MEM( data, result ) ) |
888 | 888 | ||
889 | CASE7( 20, 21, 22, 23, 24, 25, 27 ):{// SLA r | 889 | CASE7( 20, 21, 22, 23, 24, 25, 27 ):{// SLA r |
890 | byte* reg = &R8( data, 0x20 ); | 890 | byte* reg = &R8( data, 0x20 ); |
891 | SLA( *reg, 0, *reg = result ) | 891 | SLA( *reg, 0, *reg = result ) |
892 | } | 892 | } |
893 | 893 | ||
894 | case 0x36: // SLL (HL) | 894 | case 0x36: // SLL (HL) |
895 | s_time += 7; | 895 | s_time += 7; |
896 | data = r.w.hl; | 896 | data = r.w.hl; |
897 | sll_data_addr: | 897 | sll_data_addr: |
898 | SLA( READ_MEM( data ), 1, WRITE_MEM( data, result ) ) | 898 | SLA( READ_MEM( data ), 1, WRITE_MEM( data, result ) ) |
899 | 899 | ||
900 | CASE7( 30, 31, 32, 33, 34, 35, 37 ):{// SLL r | 900 | CASE7( 30, 31, 32, 33, 34, 35, 37 ):{// SLL r |
901 | byte* reg = &R8( data, 0x30 ); | 901 | byte* reg = &R8( data, 0x30 ); |
902 | SLA( *reg, 1, *reg = result ) | 902 | SLA( *reg, 1, *reg = result ) |
903 | } | 903 | } |
904 | 904 | ||
905 | // Rotate right | 905 | // Rotate right |
906 | 906 | ||
907 | #define RRC( read, write ) {\ | 907 | #define RRC( read, write ) {\ |
908 | int result = read;\ | 908 | int result = read;\ |
909 | flags = result & C01;\ | 909 | flags = result & C01;\ |
910 | result = BYTE( result << 7 ) + (result >> 1);\ | 910 | result = BYTE( result << 7 ) + (result >> 1);\ |
911 | flags += SZ28P( result );\ | 911 | flags += SZ28P( result );\ |
912 | write;\ | 912 | write;\ |
913 | goto loop;\ | 913 | goto loop;\ |
914 | } | 914 | } |
915 | 915 | ||
916 | case 0x0E: // RRC (HL) | 916 | case 0x0E: // RRC (HL) |
917 | s_time += 7; | 917 | s_time += 7; |
918 | data = r.w.hl; | 918 | data = r.w.hl; |
919 | rrc_data_addr: | 919 | rrc_data_addr: |
920 | RRC( READ_MEM( data ), WRITE_MEM( data, result ) ) | 920 | RRC( READ_MEM( data ), WRITE_MEM( data, result ) ) |
921 | 921 | ||
922 | CASE7( 08, 09, 0A, 0B, 0C, 0D, 0F ):{// RRC r | 922 | CASE7( 08, 09, 0A, 0B, 0C, 0D, 0F ):{// RRC r |
923 | byte* reg = &R8( data, 0x08 ); | 923 | byte* reg = &R8( data, 0x08 ); |
924 | RRC( *reg, *reg = result ) | 924 | RRC( *reg, *reg = result ) |
925 | } | 925 | } |
926 | 926 | ||
927 | #define RR( read, write ) {\ | 927 | #define RR( read, write ) {\ |
928 | int result = read;\ | 928 | int result = read;\ |
929 | int temp = result & C01;\ | 929 | int temp = result & C01;\ |
930 | result = BYTE( flags << 7 ) + (result >> 1);\ | 930 | result = BYTE( flags << 7 ) + (result >> 1);\ |
931 | flags = SZ28P( result ) + temp;\ | 931 | flags = SZ28P( result ) + temp;\ |
932 | write;\ | 932 | write;\ |
933 | goto loop;\ | 933 | goto loop;\ |
934 | } | 934 | } |
935 | 935 | ||
936 | case 0x1E: // RR (HL) | 936 | case 0x1E: // RR (HL) |
937 | s_time += 7; | 937 | s_time += 7; |
938 | data = r.w.hl; | 938 | data = r.w.hl; |
939 | rr_data_addr: | 939 | rr_data_addr: |
940 | RR( READ_MEM( data ), WRITE_MEM( data, result ) ) | 940 | RR( READ_MEM( data ), WRITE_MEM( data, result ) ) |
941 | 941 | ||
942 | CASE7( 18, 19, 1A, 1B, 1C, 1D, 1F ):{// RR r | 942 | CASE7( 18, 19, 1A, 1B, 1C, 1D, 1F ):{// RR r |
943 | byte* reg = &R8( data, 0x18 ); | 943 | byte* reg = &R8( data, 0x18 ); |
944 | RR( *reg, *reg = result ) | 944 | RR( *reg, *reg = result ) |
945 | } | 945 | } |
946 | 946 | ||
947 | #define SRA( read, write ) {\ | 947 | #define SRA( read, write ) {\ |
948 | int result = read;\ | 948 | int result = read;\ |
949 | flags = result & C01;\ | 949 | flags = result & C01;\ |
950 | result = (result & 0x80) + (result >> 1);\ | 950 | result = (result & 0x80) + (result >> 1);\ |
951 | flags += SZ28P( result );\ | 951 | flags += SZ28P( result );\ |
952 | write;\ | 952 | write;\ |
953 | goto loop;\ | 953 | goto loop;\ |
954 | } | 954 | } |
955 | 955 | ||
956 | case 0x2E: // SRA (HL) | 956 | case 0x2E: // SRA (HL) |
957 | data = r.w.hl; | 957 | data = r.w.hl; |
958 | s_time += 7; | 958 | s_time += 7; |
959 | sra_data_addr: | 959 | sra_data_addr: |
960 | SRA( READ_MEM( data ), WRITE_MEM( data, result ) ) | 960 | SRA( READ_MEM( data ), WRITE_MEM( data, result ) ) |
961 | 961 | ||
962 | CASE7( 28, 29, 2A, 2B, 2C, 2D, 2F ):{// SRA r | 962 | CASE7( 28, 29, 2A, 2B, 2C, 2D, 2F ):{// SRA r |
963 | byte* reg = &R8( data, 0x28 ); | 963 | byte* reg = &R8( data, 0x28 ); |
964 | SRA( *reg, *reg = result ) | 964 | SRA( *reg, *reg = result ) |
965 | } | 965 | } |
966 | 966 | ||
967 | #define SRL( read, write ) {\ | 967 | #define SRL( read, write ) {\ |
968 | int result = read;\ | 968 | int result = read;\ |
969 | flags = result & C01;\ | 969 | flags = result & C01;\ |
970 | result >>= 1;\ | 970 | result >>= 1;\ |
971 | flags += SZ28P( result );\ | 971 | flags += SZ28P( result );\ |
972 | write;\ | 972 | write;\ |
973 | goto loop;\ | 973 | goto loop;\ |
974 | } | 974 | } |
975 | 975 | ||
976 | case 0x3E: // SRL (HL) | 976 | case 0x3E: // SRL (HL) |
977 | s_time += 7; | 977 | s_time += 7; |
978 | data = r.w.hl; | 978 | data = r.w.hl; |
979 | srl_data_addr: | 979 | srl_data_addr: |
980 | SRL( READ_MEM( data ), WRITE_MEM( data, result ) ) | 980 | SRL( READ_MEM( data ), WRITE_MEM( data, result ) ) |
981 | 981 | ||
982 | CASE7( 38, 39, 3A, 3B, 3C, 3D, 3F ):{// SRL r | 982 | CASE7( 38, 39, 3A, 3B, 3C, 3D, 3F ):{// SRL r |
983 | byte* reg = &R8( data, 0x38 ); | 983 | byte* reg = &R8( data, 0x38 ); |
984 | SRL( *reg, *reg = result ) | 984 | SRL( *reg, *reg = result ) |
985 | } | 985 | } |
986 | 986 | ||
987 | // BIT | 987 | // BIT |
988 | { | 988 | { |
989 | int temp; | 989 | int temp; |
990 | CASE8( 46, 4E, 56, 5E, 66, 6E, 76, 7E ): // BIT b,(HL) | 990 | CASE8( 46, 4E, 56, 5E, 66, 6E, 76, 7E ): // BIT b,(HL) |
991 | s_time += 4; | 991 | s_time += 4; |
992 | temp = READ_MEM( r.w.hl ); | 992 | temp = READ_MEM( r.w.hl ); |
993 | flags &= C01; | 993 | flags &= C01; |
994 | goto bit_temp; | 994 | goto bit_temp; |
995 | CASE7( 40, 41, 42, 43, 44, 45, 47 ): // BIT 0,r | 995 | CASE7( 40, 41, 42, 43, 44, 45, 47 ): // BIT 0,r |
996 | CASE7( 48, 49, 4A, 4B, 4C, 4D, 4F ): // BIT 1,r | 996 | CASE7( 48, 49, 4A, 4B, 4C, 4D, 4F ): // BIT 1,r |
997 | CASE7( 50, 51, 52, 53, 54, 55, 57 ): // BIT 2,r | 997 | CASE7( 50, 51, 52, 53, 54, 55, 57 ): // BIT 2,r |
998 | CASE7( 58, 59, 5A, 5B, 5C, 5D, 5F ): // BIT 3,r | 998 | CASE7( 58, 59, 5A, 5B, 5C, 5D, 5F ): // BIT 3,r |
999 | CASE7( 60, 61, 62, 63, 64, 65, 67 ): // BIT 4,r | 999 | CASE7( 60, 61, 62, 63, 64, 65, 67 ): // BIT 4,r |
1000 | CASE7( 68, 69, 6A, 6B, 6C, 6D, 6F ): // BIT 5,r | 1000 | CASE7( 68, 69, 6A, 6B, 6C, 6D, 6F ): // BIT 5,r |
1001 | CASE7( 70, 71, 72, 73, 74, 75, 77 ): // BIT 6,r | 1001 | CASE7( 70, 71, 72, 73, 74, 75, 77 ): // BIT 6,r |
1002 | CASE7( 78, 79, 7A, 7B, 7C, 7D, 7F ): // BIT 7,r | 1002 | CASE7( 78, 79, 7A, 7B, 7C, 7D, 7F ): // BIT 7,r |
1003 | temp = R8( data & 7, 0 ); | 1003 | temp = R8( data & 7, 0 ); |
1004 | flags = (flags & C01) + (temp & (F20 | F08)); | 1004 | flags = (flags & C01) + (temp & (F20 | F08)); |
1005 | bit_temp: | 1005 | bit_temp: |
1006 | temp = temp & (1 << (data >> 3 & 7)); | 1006 | temp = temp & (1 << (data >> 3 & 7)); |
1007 | flags += (temp & S80) + H10; | 1007 | flags += (temp & S80) + H10; |
1008 | flags += (unsigned) --temp >> 8 & (Z40 | P04); | 1008 | flags += (unsigned) --temp >> 8 & (Z40 | P04); |
1009 | goto loop; | 1009 | goto loop; |
1010 | } | 1010 | } |
1011 | 1011 | ||
1012 | // SET/RES | 1012 | // SET/RES |
1013 | CASE8( 86, 8E, 96, 9E, A6, AE, B6, BE ): // RES b,(HL) | 1013 | CASE8( 86, 8E, 96, 9E, A6, AE, B6, BE ): // RES b,(HL) |
1014 | CASE8( C6, CE, D6, DE, E6, EE, F6, FE ):{// SET b,(HL) | 1014 | CASE8( C6, CE, D6, DE, E6, EE, F6, FE ):{// SET b,(HL) |
1015 | s_time += 7; | 1015 | s_time += 7; |
1016 | int temp = READ_MEM( r.w.hl ); | 1016 | int temp = READ_MEM( r.w.hl ); |
1017 | int bit = 1 << (data >> 3 & 7); | 1017 | int bit = 1 << (data >> 3 & 7); |
1018 | temp |= bit; // SET | 1018 | temp |= bit; // SET |
1019 | if ( !(data & 0x40) ) | 1019 | if ( !(data & 0x40) ) |
1020 | temp ^= bit; // RES | 1020 | temp ^= bit; // RES |
1021 | WRITE_MEM( r.w.hl, temp ); | 1021 | WRITE_MEM( r.w.hl, temp ); |
1022 | goto loop; | 1022 | goto loop; |
1023 | } | 1023 | } |
1024 | 1024 | ||
1025 | CASE7( C0, C1, C2, C3, C4, C5, C7 ): // SET 0,r | 1025 | CASE7( C0, C1, C2, C3, C4, C5, C7 ): // SET 0,r |
1026 | CASE7( C8, C9, CA, CB, CC, CD, CF ): // SET 1,r | 1026 | CASE7( C8, C9, CA, CB, CC, CD, CF ): // SET 1,r |
1027 | CASE7( D0, D1, D2, D3, D4, D5, D7 ): // SET 2,r | 1027 | CASE7( D0, D1, D2, D3, D4, D5, D7 ): // SET 2,r |
1028 | CASE7( D8, D9, DA, DB, DC, DD, DF ): // SET 3,r | 1028 | CASE7( D8, D9, DA, DB, DC, DD, DF ): // SET 3,r |
1029 | CASE7( E0, E1, E2, E3, E4, E5, E7 ): // SET 4,r | 1029 | CASE7( E0, E1, E2, E3, E4, E5, E7 ): // SET 4,r |
1030 | CASE7( E8, E9, EA, EB, EC, ED, EF ): // SET 5,r | 1030 | CASE7( E8, E9, EA, EB, EC, ED, EF ): // SET 5,r |
1031 | CASE7( F0, F1, F2, F3, F4, F5, F7 ): // SET 6,r | 1031 | CASE7( F0, F1, F2, F3, F4, F5, F7 ): // SET 6,r |
1032 | CASE7( F8, F9, FA, FB, FC, FD, FF ): // SET 7,r | 1032 | CASE7( F8, F9, FA, FB, FC, FD, FF ): // SET 7,r |
1033 | R8( data & 7, 0 ) |= 1 << (data >> 3 & 7); | 1033 | R8( data & 7, 0 ) |= 1 << (data >> 3 & 7); |
1034 | goto loop; | 1034 | goto loop; |
1035 | 1035 | ||
1036 | CASE7( 80, 81, 82, 83, 84, 85, 87 ): // RES 0,r | 1036 | CASE7( 80, 81, 82, 83, 84, 85, 87 ): // RES 0,r |
1037 | CASE7( 88, 89, 8A, 8B, 8C, 8D, 8F ): // RES 1,r | 1037 | CASE7( 88, 89, 8A, 8B, 8C, 8D, 8F ): // RES 1,r |
1038 | CASE7( 90, 91, 92, 93, 94, 95, 97 ): // RES 2,r | 1038 | CASE7( 90, 91, 92, 93, 94, 95, 97 ): // RES 2,r |
1039 | CASE7( 98, 99, 9A, 9B, 9C, 9D, 9F ): // RES 3,r | 1039 | CASE7( 98, 99, 9A, 9B, 9C, 9D, 9F ): // RES 3,r |
1040 | CASE7( A0, A1, A2, A3, A4, A5, A7 ): // RES 4,r | 1040 | CASE7( A0, A1, A2, A3, A4, A5, A7 ): // RES 4,r |
1041 | CASE7( A8, A9, AA, AB, AC, AD, AF ): // RES 5,r | 1041 | CASE7( A8, A9, AA, AB, AC, AD, AF ): // RES 5,r |
1042 | CASE7( B0, B1, B2, B3, B4, B5, B7 ): // RES 6,r | 1042 | CASE7( B0, B1, B2, B3, B4, B5, B7 ): // RES 6,r |
1043 | CASE7( B8, B9, BA, BB, BC, BD, BF ): // RES 7,r | 1043 | CASE7( B8, B9, BA, BB, BC, BD, BF ): // RES 7,r |
1044 | R8( data & 7, 0 ) &= ~(1 << (data >> 3 & 7)); | 1044 | R8( data & 7, 0 ) &= ~(1 << (data >> 3 & 7)); |
1045 | goto loop; | 1045 | goto loop; |
1046 | } | 1046 | } |
1047 | assert( false ); | 1047 | assert( false ); |
1048 | } | 1048 | } |
1049 | 1049 | ||
1050 | #undef GET_ADDR | 1050 | #undef GET_ADDR |
1051 | #define GET_ADDR() GET_LE16( &INSTR( 1, pc ) ) | 1051 | #define GET_ADDR() GET_LE16( &INSTR( 1, pc ) ) |
1052 | 1052 | ||
1053 | //////////////////////////////////////// ED prefix | 1053 | //////////////////////////////////////// ED prefix |
1054 | { | 1054 | { |
1055 | case 0xED: | 1055 | case 0xED: |
1056 | pc++; | 1056 | pc++; |
1057 | s_time += (clock_table + 256) [data] >> 4; | 1057 | s_time += (clock_table + 256) [data] >> 4; |
1058 | switch ( data ) | 1058 | switch ( data ) |
1059 | { | 1059 | { |
1060 | { | 1060 | { |
1061 | int temp; | 1061 | int temp; |
1062 | case 0x72: // SBC HL,SP | 1062 | case 0x72: // SBC HL,SP |
1063 | case 0x7A: // ADC HL,SP | 1063 | case 0x7A: // ADC HL,SP |
1064 | temp = sp; | 1064 | temp = sp; |
1065 | if ( 0 ) | 1065 | if ( 0 ) |
1066 | case 0x42: // SBC HL,BC | 1066 | case 0x42: // SBC HL,BC |
1067 | case 0x52: // SBC HL,DE | 1067 | case 0x52: // SBC HL,DE |
1068 | case 0x62: // SBC HL,HL | 1068 | case 0x62: // SBC HL,HL |
1069 | case 0x4A: // ADC HL,BC | 1069 | case 0x4A: // ADC HL,BC |
1070 | case 0x5A: // ADC HL,DE | 1070 | case 0x5A: // ADC HL,DE |
1071 | case 0x6A: // ADC HL,HL | 1071 | case 0x6A: // ADC HL,HL |
1072 | temp = R16( data >> 3 & 6, 1, 0 ); | 1072 | temp = R16( data >> 3 & 6, 1, 0 ); |
1073 | int sum = temp + (flags & C01); | 1073 | int sum = temp + (flags & C01); |
1074 | flags = ~data >> 2 & N02; | 1074 | flags = ~data >> 2 & N02; |
1075 | if ( flags ) | 1075 | if ( flags ) |
1076 | sum = -sum; | 1076 | sum = -sum; |
1077 | sum += r.w.hl; | 1077 | sum += r.w.hl; |
1078 | temp ^= r.w.hl; | 1078 | temp ^= r.w.hl; |
1079 | temp ^= sum; | 1079 | temp ^= sum; |
1080 | flags +=(sum >> 16 & C01) + | 1080 | flags +=(sum >> 16 & C01) + |
1081 | (temp >> 8 & H10) + | 1081 | (temp >> 8 & H10) + |
1082 | (sum >> 8 & (S80 | F20 | F08)) + | 1082 | (sum >> 8 & (S80 | F20 | F08)) + |
1083 | ((temp + 0x8000) >> 14 & V04); | 1083 | ((temp + 0x8000) >> 14 & V04); |
1084 | r.w.hl = sum; | 1084 | r.w.hl = sum; |
1085 | if ( WORD( sum ) ) | 1085 | if ( WORD( sum ) ) |
1086 | goto loop; | 1086 | goto loop; |
1087 | flags += Z40; | 1087 | flags += Z40; |
1088 | goto loop; | 1088 | goto loop; |
1089 | } | 1089 | } |
1090 | 1090 | ||
1091 | CASE8( 40, 48, 50, 58, 60, 68, 70, 78 ):{// IN r,(C) | 1091 | CASE8( 40, 48, 50, 58, 60, 68, 70, 78 ):{// IN r,(C) |
1092 | int temp = IN_PORT( r.w.bc ); | 1092 | int temp = IN_PORT( r.w.bc ); |
1093 | R8( data >> 3, 8 ) = temp; | 1093 | R8( data >> 3, 8 ) = temp; |
1094 | flags = (flags & C01) + SZ28P( temp ); | 1094 | flags = (flags & C01) + SZ28P( temp ); |
1095 | goto loop; | 1095 | goto loop; |
1096 | } | 1096 | } |
1097 | 1097 | ||
1098 | case 0x71: // OUT (C),0 | 1098 | case 0x71: // OUT (C),0 |
1099 | r.b.flags = 0; | 1099 | r.b.flags = 0; |
1100 | CASE7( 41, 49, 51, 59, 61, 69, 79 ): // OUT (C),r | 1100 | CASE7( 41, 49, 51, 59, 61, 69, 79 ): // OUT (C),r |
1101 | OUT_PORT( r.w.bc, R8( data >> 3, 8 ) ); | 1101 | OUT_PORT( r.w.bc, R8( data >> 3, 8 ) ); |
1102 | goto loop; | 1102 | goto loop; |
1103 | 1103 | ||
1104 | { | 1104 | { |
1105 | int temp; | 1105 | int temp; |
1106 | case 0x73: // LD (ADDR),SP | 1106 | case 0x73: // LD (ADDR),SP |
1107 | temp = sp; | 1107 | temp = sp; |
1108 | if ( 0 ) | 1108 | if ( 0 ) |
1109 | case 0x43: // LD (ADDR),BC | 1109 | case 0x43: // LD (ADDR),BC |
1110 | case 0x53: // LD (ADDR),DE | 1110 | case 0x53: // LD (ADDR),DE |
1111 | temp = R16( data, 4, 0x43 ); | 1111 | temp = R16( data, 4, 0x43 ); |
1112 | int addr = GET_ADDR(); | 1112 | int addr = GET_ADDR(); |
1113 | pc += 2; | 1113 | pc += 2; |
1114 | WRITE_WORD( addr, temp ); | 1114 | WRITE_WORD( addr, temp ); |
1115 | goto loop; | 1115 | goto loop; |
1116 | } | 1116 | } |
1117 | 1117 | ||
1118 | case 0x4B: // LD BC,(ADDR) | 1118 | case 0x4B: // LD BC,(ADDR) |
1119 | case 0x5B:{// LD DE,(ADDR) | 1119 | case 0x5B:{// LD DE,(ADDR) |
1120 | int addr = GET_ADDR(); | 1120 | int addr = GET_ADDR(); |
1121 | pc += 2; | 1121 | pc += 2; |
1122 | R16( data, 4, 0x4B ) = READ_WORD( addr ); | 1122 | R16( data, 4, 0x4B ) = READ_WORD( addr ); |
1123 | goto loop; | 1123 | goto loop; |
1124 | } | 1124 | } |
1125 | 1125 | ||
1126 | case 0x7B:{// LD SP,(ADDR) | 1126 | case 0x7B:{// LD SP,(ADDR) |
1127 | int addr = GET_ADDR(); | 1127 | int addr = GET_ADDR(); |
1128 | pc += 2; | 1128 | pc += 2; |
1129 | sp = READ_WORD( addr ); | 1129 | sp = READ_WORD( addr ); |
1130 | goto loop; | 1130 | goto loop; |
1131 | } | 1131 | } |
1132 | 1132 | ||
1133 | case 0x67:{// RRD | 1133 | case 0x67:{// RRD |
1134 | int temp = READ_MEM( r.w.hl ); | 1134 | int temp = READ_MEM( r.w.hl ); |
1135 | WRITE_MEM( r.w.hl, ((r.b.a << 4) + (temp >> 4)) ); | 1135 | WRITE_MEM( r.w.hl, ((r.b.a << 4) + (temp >> 4)) ); |
1136 | temp = (r.b.a & 0xF0) + (temp & 0x0F); | 1136 | temp = (r.b.a & 0xF0) + (temp & 0x0F); |
1137 | flags = (flags & C01) + SZ28P( temp ); | 1137 | flags = (flags & C01) + SZ28P( temp ); |
1138 | r.b.a = temp; | 1138 | r.b.a = temp; |
1139 | goto loop; | 1139 | goto loop; |
1140 | } | 1140 | } |
1141 | 1141 | ||
1142 | case 0x6F:{// RLD | 1142 | case 0x6F:{// RLD |
1143 | int temp = READ_MEM( r.w.hl ); | 1143 | int temp = READ_MEM( r.w.hl ); |
1144 | WRITE_MEM( r.w.hl, ((temp << 4) + (r.b.a & 0x0F)) ); | 1144 | WRITE_MEM( r.w.hl, ((temp << 4) + (r.b.a & 0x0F)) ); |
1145 | temp = (r.b.a & 0xF0) + (temp >> 4); | 1145 | temp = (r.b.a & 0xF0) + (temp >> 4); |
1146 | flags = (flags & C01) + SZ28P( temp ); | 1146 | flags = (flags & C01) + SZ28P( temp ); |
1147 | r.b.a = temp; | 1147 | r.b.a = temp; |
1148 | goto loop; | 1148 | goto loop; |
1149 | } | 1149 | } |
1150 | 1150 | ||
1151 | CASE8( 44, 4C, 54, 5C, 64, 6C, 74, 7C ): // NEG | 1151 | CASE8( 44, 4C, 54, 5C, 64, 6C, 74, 7C ): // NEG |
1152 | opcode = 0x10; // flag to do SBC instead of ADC | 1152 | opcode = 0x10; // flag to do SBC instead of ADC |
1153 | flags &= ~C01; | 1153 | flags &= ~C01; |
1154 | data = r.b.a; | 1154 | data = r.b.a; |
1155 | r.b.a = 0; | 1155 | r.b.a = 0; |
1156 | goto adc_data; | 1156 | goto adc_data; |
1157 | 1157 | ||
1158 | { | 1158 | { |
1159 | int inc; | 1159 | int inc; |
1160 | case 0xA9: // CPD | 1160 | case 0xA9: // CPD |
1161 | case 0xB9: // CPDR | 1161 | case 0xB9: // CPDR |
1162 | inc = -1; | 1162 | inc = -1; |
1163 | if ( 0 ) | 1163 | if ( 0 ) |
1164 | case 0xA1: // CPI | 1164 | case 0xA1: // CPI |
1165 | case 0xB1: // CPIR | 1165 | case 0xB1: // CPIR |
1166 | inc = +1; | 1166 | inc = +1; |
1167 | int addr = r.w.hl; | 1167 | int addr = r.w.hl; |
1168 | r.w.hl = addr + inc; | 1168 | r.w.hl = addr + inc; |
1169 | int temp = READ_MEM( addr ); | 1169 | int temp = READ_MEM( addr ); |
1170 | 1170 | ||
1171 | int result = r.b.a - temp; | 1171 | int result = r.b.a - temp; |
1172 | flags = (flags & C01) + N02 + | 1172 | flags = (flags & C01) + N02 + |
1173 | ((((temp ^ r.b.a) & H10) ^ result) & (S80 | H10)); | 1173 | ((((temp ^ r.b.a) & H10) ^ result) & (S80 | H10)); |
1174 | 1174 | ||
1175 | if ( !BYTE( result ) ) | 1175 | if ( !BYTE( result ) ) |
1176 | flags += Z40; | 1176 | flags += Z40; |
1177 | result -= (flags & H10) >> 4; | 1177 | result -= (flags & H10) >> 4; |
1178 | flags += result & F08; | 1178 | flags += result & F08; |
1179 | flags += result << 4 & F20; | 1179 | flags += result << 4 & F20; |
1180 | if ( !--r.w.bc ) | 1180 | if ( !--r.w.bc ) |
1181 | goto loop; | 1181 | goto loop; |
1182 | 1182 | ||
1183 | flags += V04; | 1183 | flags += V04; |
1184 | if ( flags & Z40 || data < 0xB0 ) | 1184 | if ( flags & Z40 || data < 0xB0 ) |
1185 | goto loop; | 1185 | goto loop; |
1186 | 1186 | ||
1187 | pc -= 2; | 1187 | pc -= 2; |
1188 | s_time += 5; | 1188 | s_time += 5; |
1189 | goto loop; | 1189 | goto loop; |
1190 | } | 1190 | } |
1191 | 1191 | ||
1192 | { | 1192 | { |
1193 | int inc; | 1193 | int inc; |
1194 | case 0xA8: // LDD | 1194 | case 0xA8: // LDD |
1195 | case 0xB8: // LDDR | 1195 | case 0xB8: // LDDR |
1196 | inc = -1; | 1196 | inc = -1; |
1197 | if ( 0 ) | 1197 | if ( 0 ) |
1198 | case 0xA0: // LDI | 1198 | case 0xA0: // LDI |
1199 | case 0xB0: // LDIR | 1199 | case 0xB0: // LDIR |
1200 | inc = +1; | 1200 | inc = +1; |
1201 | int addr = r.w.hl; | 1201 | int addr = r.w.hl; |
1202 | r.w.hl = addr + inc; | 1202 | r.w.hl = addr + inc; |
1203 | int temp = READ_MEM( addr ); | 1203 | int temp = READ_MEM( addr ); |
1204 | 1204 | ||
1205 | addr = r.w.de; | 1205 | addr = r.w.de; |
1206 | r.w.de = addr + inc; | 1206 | r.w.de = addr + inc; |
1207 | WRITE_MEM( addr, temp ); | 1207 | WRITE_MEM( addr, temp ); |
1208 | 1208 | ||
1209 | temp += r.b.a; | 1209 | temp += r.b.a; |
1210 | flags = (flags & (S80 | Z40 | C01)) + | 1210 | flags = (flags & (S80 | Z40 | C01)) + |
1211 | (temp & F08) + (temp << 4 & F20); | 1211 | (temp & F08) + (temp << 4 & F20); |
1212 | if ( !--r.w.bc ) | 1212 | if ( !--r.w.bc ) |
1213 | goto loop; | 1213 | goto loop; |
1214 | 1214 | ||
1215 | flags += V04; | 1215 | flags += V04; |
1216 | if ( data < 0xB0 ) | 1216 | if ( data < 0xB0 ) |
1217 | goto loop; | 1217 | goto loop; |
1218 | 1218 | ||
1219 | pc -= 2; | 1219 | pc -= 2; |
1220 | s_time += 5; | 1220 | s_time += 5; |
1221 | goto loop; | 1221 | goto loop; |
1222 | } | 1222 | } |
1223 | 1223 | ||
1224 | { | 1224 | { |
1225 | int inc; | 1225 | int inc; |
1226 | case 0xAB: // OUTD | 1226 | case 0xAB: // OUTD |
1227 | case 0xBB: // OTDR | 1227 | case 0xBB: // OTDR |
1228 | inc = -1; | 1228 | inc = -1; |
1229 | if ( 0 ) | 1229 | if ( 0 ) |
1230 | case 0xA3: // OUTI | 1230 | case 0xA3: // OUTI |
1231 | case 0xB3: // OTIR | 1231 | case 0xB3: // OTIR |
1232 | inc = +1; | 1232 | inc = +1; |
1233 | int addr = r.w.hl; | 1233 | int addr = r.w.hl; |
1234 | r.w.hl = addr + inc; | 1234 | r.w.hl = addr + inc; |
1235 | int temp = READ_MEM( addr ); | 1235 | int temp = READ_MEM( addr ); |
1236 | 1236 | ||
1237 | int b = --r.b.b; | 1237 | int b = --r.b.b; |
1238 | flags = (temp >> 6 & N02) + SZ28( b ); | 1238 | flags = (temp >> 6 & N02) + SZ28( b ); |
1239 | if ( b && data >= 0xB0 ) | 1239 | if ( b && data >= 0xB0 ) |
1240 | { | 1240 | { |
1241 | pc -= 2; | 1241 | pc -= 2; |
1242 | s_time += 5; | 1242 | s_time += 5; |
1243 | } | 1243 | } |
1244 | 1244 | ||
1245 | OUT_PORT( r.w.bc, temp ); | 1245 | OUT_PORT( r.w.bc, temp ); |
1246 | goto loop; | 1246 | goto loop; |
1247 | } | 1247 | } |
1248 | 1248 | ||
1249 | { | 1249 | { |
1250 | int inc; | 1250 | int inc; |
1251 | case 0xAA: // IND | 1251 | case 0xAA: // IND |
1252 | case 0xBA: // INDR | 1252 | case 0xBA: // INDR |
1253 | inc = -1; | 1253 | inc = -1; |
1254 | if ( 0 ) | 1254 | if ( 0 ) |
1255 | case 0xA2: // INI | 1255 | case 0xA2: // INI |
1256 | case 0xB2: // INIR | 1256 | case 0xB2: // INIR |
1257 | inc = +1; | 1257 | inc = +1; |
1258 | 1258 | ||
1259 | int addr = r.w.hl; | 1259 | int addr = r.w.hl; |
1260 | r.w.hl = addr + inc; | 1260 | r.w.hl = addr + inc; |
1261 | 1261 | ||
1262 | int temp = IN_PORT( r.w.bc ); | 1262 | int temp = IN_PORT( r.w.bc ); |
1263 | 1263 | ||
1264 | int b = --r.b.b; | 1264 | int b = --r.b.b; |
1265 | flags = (temp >> 6 & N02) + SZ28( b ); | 1265 | flags = (temp >> 6 & N02) + SZ28( b ); |
1266 | if ( b && data >= 0xB0 ) | 1266 | if ( b && data >= 0xB0 ) |
1267 | { | 1267 | { |
1268 | pc -= 2; | 1268 | pc -= 2; |
1269 | s_time += 5; | 1269 | s_time += 5; |
1270 | } | 1270 | } |
1271 | 1271 | ||
1272 | WRITE_MEM( addr, temp ); | 1272 | WRITE_MEM( addr, temp ); |
1273 | goto loop; | 1273 | goto loop; |
1274 | } | 1274 | } |
1275 | 1275 | ||
1276 | case 0x47: // LD I,A | 1276 | case 0x47: // LD I,A |
1277 | R.i = r.b.a; | 1277 | R.i = r.b.a; |
1278 | goto loop; | 1278 | goto loop; |
1279 | 1279 | ||
1280 | case 0x4F: // LD R,A | 1280 | case 0x4F: // LD R,A |
1281 | SET_R( r.b.a ); | 1281 | SET_R( r.b.a ); |
1282 | dprintf( "LD R,A not supported\n" ); | 1282 | dprintf( "LD R,A not supported\n" ); |
1283 | warning = true; | 1283 | warning = true; |
1284 | goto loop; | 1284 | goto loop; |
1285 | 1285 | ||
1286 | case 0x57: // LD A,I | 1286 | case 0x57: // LD A,I |
1287 | r.b.a = R.i; | 1287 | r.b.a = R.i; |
1288 | goto ld_ai_common; | 1288 | goto ld_ai_common; |
1289 | 1289 | ||
1290 | case 0x5F: // LD A,R | 1290 | case 0x5F: // LD A,R |
1291 | r.b.a = GET_R(); | 1291 | r.b.a = GET_R(); |
1292 | dprintf( "LD A,R not supported\n" ); | 1292 | dprintf( "LD A,R not supported\n" ); |
1293 | warning = true; | 1293 | warning = true; |
1294 | ld_ai_common: | 1294 | ld_ai_common: |
1295 | flags = (flags & C01) + SZ28( r.b.a ) + (R.iff2 << 2 & V04); | 1295 | flags = (flags & C01) + SZ28( r.b.a ) + (R.iff2 << 2 & V04); |
1296 | goto loop; | 1296 | goto loop; |
1297 | 1297 | ||
1298 | CASE8( 45, 4D, 55, 5D, 65, 6D, 75, 7D ): // RETI/RETN | 1298 | CASE8( 45, 4D, 55, 5D, 65, 6D, 75, 7D ): // RETI/RETN |
1299 | R.iff1 = R.iff2; | 1299 | R.iff1 = R.iff2; |
1300 | goto ret_taken; | 1300 | goto ret_taken; |
1301 | 1301 | ||
1302 | case 0x46: case 0x4E: case 0x66: case 0x6E: // IM 0 | 1302 | case 0x46: case 0x4E: case 0x66: case 0x6E: // IM 0 |
1303 | R.im = 0; | 1303 | R.im = 0; |
1304 | goto loop; | 1304 | goto loop; |
1305 | 1305 | ||
1306 | case 0x56: case 0x76: // IM 1 | 1306 | case 0x56: case 0x76: // IM 1 |
1307 | R.im = 1; | 1307 | R.im = 1; |
1308 | goto loop; | 1308 | goto loop; |
1309 | 1309 | ||
1310 | case 0x5E: case 0x7E: // IM 2 | 1310 | case 0x5E: case 0x7E: // IM 2 |
1311 | R.im = 2; | 1311 | R.im = 2; |
1312 | goto loop; | 1312 | goto loop; |
1313 | 1313 | ||
1314 | default: | 1314 | default: |
1315 | dprintf( "Opcode $ED $%02X not supported\n", data ); | 1315 | dprintf( "Opcode $ED $%02X not supported\n", data ); |
1316 | warning = true; | 1316 | warning = true; |
1317 | goto loop; | 1317 | goto loop; |
1318 | } | 1318 | } |
1319 | assert( false ); | 1319 | assert( false ); |
1320 | } | 1320 | } |
1321 | 1321 | ||
1322 | //////////////////////////////////////// DD/FD prefix | 1322 | //////////////////////////////////////// DD/FD prefix |
1323 | { | 1323 | { |
1324 | int ixy; | 1324 | int ixy; |
1325 | case 0xDD: | 1325 | case 0xDD: |
1326 | ixy = ix; | 1326 | ixy = ix; |
1327 | goto ix_prefix; | 1327 | goto ix_prefix; |
1328 | case 0xFD: | 1328 | case 0xFD: |
1329 | ixy = iy; | 1329 | ixy = iy; |
1330 | ix_prefix: | 1330 | ix_prefix: |
1331 | pc++; | 1331 | pc++; |
1332 | int data2 = READ_CODE( pc ); | 1332 | int data2 = READ_CODE( pc ); |
1333 | s_time += (clock_table + 256) [data] & 0x0F; | 1333 | s_time += (clock_table + 256) [data] & 0x0F; |
1334 | switch ( data ) | 1334 | switch ( data ) |
1335 | { | 1335 | { |
1336 | // TODO: more efficient way of avoid negative address | 1336 | // TODO: more efficient way of avoid negative address |
1337 | // TODO: avoid using this as argument to READ_MEM() since it is evaluated twice | 1337 | // TODO: avoid using this as argument to READ_MEM() since it is evaluated twice |
1338 | #define IXY_DISP( ixy, disp ) WORD( (ixy ) + (disp)) | 1338 | #define IXY_DISP( ixy, disp ) WORD( (ixy ) + (disp)) |
1339 | 1339 | ||
1340 | #define SET_IXY( in ) if ( opcode == 0xDD ) ix = in; else iy = in; | 1340 | #define SET_IXY( in ) if ( opcode == 0xDD ) ix = in; else iy = in; |
1341 | 1341 | ||
1342 | // ADD/ADC/SUB/SBC | 1342 | // ADD/ADC/SUB/SBC |
1343 | 1343 | ||
1344 | case 0x96: // SUB (IXY+disp) | 1344 | case 0x96: // SUB (IXY+disp) |
1345 | case 0x86: // ADD (IXY+disp) | 1345 | case 0x86: // ADD (IXY+disp) |
1346 | flags &= ~C01; | 1346 | flags &= ~C01; |
1347 | case 0x9E: // SBC (IXY+disp) | 1347 | case 0x9E: // SBC (IXY+disp) |
1348 | case 0x8E: // ADC (IXY+disp) | 1348 | case 0x8E: // ADC (IXY+disp) |
1349 | pc++; | 1349 | pc++; |
1350 | opcode = data; | 1350 | opcode = data; |
1351 | data = READ_MEM( IXY_DISP( ixy, SBYTE( data2 ) ) ); | 1351 | data = READ_MEM( IXY_DISP( ixy, SBYTE( data2 ) ) ); |
1352 | goto adc_data; | 1352 | goto adc_data; |
1353 | 1353 | ||
1354 | case 0x94: // SUB HXY | 1354 | case 0x94: // SUB HXY |
1355 | case 0x84: // ADD HXY | 1355 | case 0x84: // ADD HXY |
1356 | flags &= ~C01; | 1356 | flags &= ~C01; |
1357 | case 0x9C: // SBC HXY | 1357 | case 0x9C: // SBC HXY |
1358 | case 0x8C: // ADC HXY | 1358 | case 0x8C: // ADC HXY |
1359 | opcode = data; | 1359 | opcode = data; |
1360 | data = ixy >> 8; | 1360 | data = ixy >> 8; |
1361 | goto adc_data; | 1361 | goto adc_data; |
1362 | 1362 | ||
1363 | case 0x95: // SUB LXY | 1363 | case 0x95: // SUB LXY |
1364 | case 0x85: // ADD LXY | 1364 | case 0x85: // ADD LXY |
1365 | flags &= ~C01; | 1365 | flags &= ~C01; |
1366 | case 0x9D: // SBC LXY | 1366 | case 0x9D: // SBC LXY |
1367 | case 0x8D: // ADC LXY | 1367 | case 0x8D: // ADC LXY |
1368 | opcode = data; | 1368 | opcode = data; |
1369 | data = BYTE( ixy ); | 1369 | data = BYTE( ixy ); |
1370 | goto adc_data; | 1370 | goto adc_data; |
1371 | 1371 | ||
1372 | { | 1372 | { |
1373 | int temp; | 1373 | int temp; |
1374 | case 0x39: // ADD IXY,SP | 1374 | case 0x39: // ADD IXY,SP |
1375 | temp = sp; | 1375 | temp = sp; |
1376 | goto add_ixy_data; | 1376 | goto add_ixy_data; |
1377 | 1377 | ||
1378 | case 0x29: // ADD IXY,HL | 1378 | case 0x29: // ADD IXY,HL |
1379 | temp = ixy; | 1379 | temp = ixy; |
1380 | goto add_ixy_data; | 1380 | goto add_ixy_data; |
1381 | 1381 | ||
1382 | case 0x09: // ADD IXY,BC | 1382 | case 0x09: // ADD IXY,BC |
1383 | case 0x19: // ADD IXY,DE | 1383 | case 0x19: // ADD IXY,DE |
1384 | temp = R16( data, 4, 0x09 ); | 1384 | temp = R16( data, 4, 0x09 ); |
1385 | add_ixy_data: { | 1385 | add_ixy_data: { |
1386 | int sum = ixy + temp; | 1386 | int sum = ixy + temp; |
1387 | temp ^= ixy; | 1387 | temp ^= ixy; |
1388 | ixy = WORD( sum ); | 1388 | ixy = WORD( sum ); |
1389 | flags = (flags & (S80 | Z40 | V04)) + | 1389 | flags = (flags & (S80 | Z40 | V04)) + |
1390 | (sum >> 16) + | 1390 | (sum >> 16) + |
1391 | (sum >> 8 & (F20 | F08)) + | 1391 | (sum >> 8 & (F20 | F08)) + |
1392 | ((temp ^ sum) >> 8 & H10); | 1392 | ((temp ^ sum) >> 8 & H10); |
1393 | goto set_ixy; | 1393 | goto set_ixy; |
1394 | } | 1394 | } |
1395 | } | 1395 | } |
1396 | 1396 | ||
1397 | // AND | 1397 | // AND |
1398 | case 0xA6: // AND (IXY+disp) | 1398 | case 0xA6: // AND (IXY+disp) |
1399 | pc++; | 1399 | pc++; |
1400 | data = READ_MEM( IXY_DISP( ixy, SBYTE( data2 ) ) ); | 1400 | data = READ_MEM( IXY_DISP( ixy, SBYTE( data2 ) ) ); |
1401 | goto and_data; | 1401 | goto and_data; |
1402 | 1402 | ||
1403 | case 0xA4: // AND HXY | 1403 | case 0xA4: // AND HXY |
1404 | data = ixy >> 8; | 1404 | data = ixy >> 8; |
1405 | goto and_data; | 1405 | goto and_data; |
1406 | 1406 | ||
1407 | case 0xA5: // AND LXY | 1407 | case 0xA5: // AND LXY |
1408 | data = BYTE( ixy ); | 1408 | data = BYTE( ixy ); |
1409 | goto and_data; | 1409 | goto and_data; |
1410 | 1410 | ||
1411 | // OR | 1411 | // OR |
1412 | case 0xB6: // OR (IXY+disp) | 1412 | case 0xB6: // OR (IXY+disp) |
1413 | pc++; | 1413 | pc++; |
1414 | data = READ_MEM( IXY_DISP( ixy, SBYTE( data2 ) ) ); | 1414 | data = READ_MEM( IXY_DISP( ixy, SBYTE( data2 ) ) ); |
1415 | goto or_data; | 1415 | goto or_data; |
1416 | 1416 | ||
1417 | case 0xB4: // OR HXY | 1417 | case 0xB4: // OR HXY |
1418 | data = ixy >> 8; | 1418 | data = ixy >> 8; |
1419 | goto or_data; | 1419 | goto or_data; |
1420 | 1420 | ||
1421 | case 0xB5: // OR LXY | 1421 | case 0xB5: // OR LXY |
1422 | data = BYTE( ixy ); | 1422 | data = BYTE( ixy ); |
1423 | goto or_data; | 1423 | goto or_data; |
1424 | 1424 | ||
1425 | // XOR | 1425 | // XOR |
1426 | case 0xAE: // XOR (IXY+disp) | 1426 | case 0xAE: // XOR (IXY+disp) |
1427 | pc++; | 1427 | pc++; |
1428 | data = READ_MEM( IXY_DISP( ixy, SBYTE( data2 ) ) ); | 1428 | data = READ_MEM( IXY_DISP( ixy, SBYTE( data2 ) ) ); |
1429 | goto xor_data; | 1429 | goto xor_data; |
1430 | 1430 | ||
1431 | case 0xAC: // XOR HXY | 1431 | case 0xAC: // XOR HXY |
1432 | data = ixy >> 8; | 1432 | data = ixy >> 8; |
1433 | goto xor_data; | 1433 | goto xor_data; |
1434 | 1434 | ||
1435 | case 0xAD: // XOR LXY | 1435 | case 0xAD: // XOR LXY |
1436 | data = BYTE( ixy ); | 1436 | data = BYTE( ixy ); |
1437 | goto xor_data; | 1437 | goto xor_data; |
1438 | 1438 | ||
1439 | // CP | 1439 | // CP |
1440 | case 0xBE: // CP (IXY+disp) | 1440 | case 0xBE: // CP (IXY+disp) |
1441 | pc++; | 1441 | pc++; |
1442 | data = READ_MEM( IXY_DISP( ixy, SBYTE( data2 ) ) ); | 1442 | data = READ_MEM( IXY_DISP( ixy, SBYTE( data2 ) ) ); |
1443 | goto cp_data; | 1443 | goto cp_data; |
1444 | 1444 | ||
1445 | case 0xBC: // CP HXY | 1445 | case 0xBC: // CP HXY |
1446 | data = ixy >> 8; | 1446 | data = ixy >> 8; |
1447 | goto cp_data; | 1447 | goto cp_data; |
1448 | 1448 | ||
1449 | case 0xBD: // CP LXY | 1449 | case 0xBD: // CP LXY |
1450 | data = BYTE( ixy ); | 1450 | data = BYTE( ixy ); |
1451 | goto cp_data; | 1451 | goto cp_data; |
1452 | 1452 | ||
1453 | // LD | 1453 | // LD |
1454 | CASE7( 70, 71, 72, 73, 74, 75, 77 ): // LD (IXY+disp),r | 1454 | CASE7( 70, 71, 72, 73, 74, 75, 77 ): // LD (IXY+disp),r |
1455 | data = R8( data, 0x70 ); | 1455 | data = R8( data, 0x70 ); |
1456 | if ( 0 ) | 1456 | if ( 0 ) |
1457 | case 0x36: // LD (IXY+disp),imm | 1457 | case 0x36: // LD (IXY+disp),imm |
1458 | pc++, data = READ_CODE( pc ); | 1458 | pc++, data = READ_CODE( pc ); |
1459 | pc++; | 1459 | pc++; |
1460 | WRITE_MEM( IXY_DISP( ixy, SBYTE( data2 ) ), data ); | 1460 | WRITE_MEM( IXY_DISP( ixy, SBYTE( data2 ) ), data ); |
1461 | goto loop; | 1461 | goto loop; |
1462 | 1462 | ||
1463 | CASE5( 44, 4C, 54, 5C, 7C ): // LD r,HXY | 1463 | CASE5( 44, 4C, 54, 5C, 7C ): // LD r,HXY |
1464 | R8( data >> 3, 8 ) = ixy >> 8; | 1464 | R8( data >> 3, 8 ) = ixy >> 8; |
1465 | goto loop; | 1465 | goto loop; |
1466 | 1466 | ||
1467 | case 0x64: // LD HXY,HXY | 1467 | case 0x64: // LD HXY,HXY |
1468 | case 0x6D: // LD LXY,LXY | 1468 | case 0x6D: // LD LXY,LXY |
1469 | goto loop; | 1469 | goto loop; |
1470 | 1470 | ||
1471 | CASE5( 45, 4D, 55, 5D, 7D ): // LD r,LXY | 1471 | CASE5( 45, 4D, 55, 5D, 7D ): // LD r,LXY |
1472 | R8( data >> 3, 8 ) = ixy; | 1472 | R8( data >> 3, 8 ) = ixy; |
1473 | goto loop; | 1473 | goto loop; |
1474 | 1474 | ||
1475 | CASE7( 46, 4E, 56, 5E, 66, 6E, 7E ): // LD r,(IXY+disp) | 1475 | CASE7( 46, 4E, 56, 5E, 66, 6E, 7E ): // LD r,(IXY+disp) |
1476 | pc++; | 1476 | pc++; |
1477 | R8( data >> 3, 8 ) = READ_MEM( IXY_DISP( ixy, SBYTE( data2 ) ) ); | 1477 | R8( data >> 3, 8 ) = READ_MEM( IXY_DISP( ixy, SBYTE( data2 ) ) ); |
1478 | goto loop; | 1478 | goto loop; |
1479 | 1479 | ||
1480 | case 0x26: // LD HXY,imm | 1480 | case 0x26: // LD HXY,imm |
1481 | pc++; | 1481 | pc++; |
1482 | goto ld_hxy_data; | 1482 | goto ld_hxy_data; |
1483 | 1483 | ||
1484 | case 0x65: // LD HXY,LXY | 1484 | case 0x65: // LD HXY,LXY |
1485 | data2 = BYTE( ixy ); | 1485 | data2 = BYTE( ixy ); |
1486 | goto ld_hxy_data; | 1486 | goto ld_hxy_data; |
1487 | 1487 | ||
1488 | CASE5( 60, 61, 62, 63, 67 ): // LD HXY,r | 1488 | CASE5( 60, 61, 62, 63, 67 ): // LD HXY,r |
1489 | data2 = R8( data, 0x60 ); | 1489 | data2 = R8( data, 0x60 ); |
1490 | ld_hxy_data: | 1490 | ld_hxy_data: |
1491 | ixy = BYTE( ixy ) + (data2 << 8); | 1491 | ixy = BYTE( ixy ) + (data2 << 8); |
1492 | goto set_ixy; | 1492 | goto set_ixy; |
1493 | 1493 | ||
1494 | case 0x2E: // LD LXY,imm | 1494 | case 0x2E: // LD LXY,imm |
1495 | pc++; | 1495 | pc++; |
1496 | goto ld_lxy_data; | 1496 | goto ld_lxy_data; |
1497 | 1497 | ||
1498 | case 0x6C: // LD LXY,HXY | 1498 | case 0x6C: // LD LXY,HXY |
1499 | data2 = ixy >> 8; | 1499 | data2 = ixy >> 8; |
1500 | goto ld_lxy_data; | 1500 | goto ld_lxy_data; |
1501 | 1501 | ||
1502 | CASE5( 68, 69, 6A, 6B, 6F ): // LD LXY,r | 1502 | CASE5( 68, 69, 6A, 6B, 6F ): // LD LXY,r |
1503 | data2 = R8( data, 0x68 ); | 1503 | data2 = R8( data, 0x68 ); |
1504 | ld_lxy_data: | 1504 | ld_lxy_data: |
1505 | ixy = (ixy & 0xFF00) + data2; | 1505 | ixy = (ixy & 0xFF00) + data2; |
1506 | set_ixy: | 1506 | set_ixy: |
1507 | if ( opcode == 0xDD ) | 1507 | if ( opcode == 0xDD ) |
1508 | { | 1508 | { |
1509 | ix = ixy; | 1509 | ix = ixy; |
1510 | goto loop; | 1510 | goto loop; |
1511 | } | 1511 | } |
1512 | iy = ixy; | 1512 | iy = ixy; |
1513 | goto loop; | 1513 | goto loop; |
1514 | 1514 | ||
1515 | case 0xF9: // LD SP,IXY | 1515 | case 0xF9: // LD SP,IXY |
1516 | sp = ixy; | 1516 | sp = ixy; |
1517 | goto loop; | 1517 | goto loop; |
1518 | 1518 | ||
1519 | case 0x22:{// LD (ADDR),IXY | 1519 | case 0x22:{// LD (ADDR),IXY |
1520 | int addr = GET_ADDR(); | 1520 | int addr = GET_ADDR(); |
1521 | pc += 2; | 1521 | pc += 2; |
1522 | WRITE_WORD( addr, ixy ); | 1522 | WRITE_WORD( addr, ixy ); |
1523 | goto loop; | 1523 | goto loop; |
1524 | } | 1524 | } |
1525 | 1525 | ||
1526 | case 0x21: // LD IXY,imm | 1526 | case 0x21: // LD IXY,imm |
1527 | ixy = GET_ADDR(); | 1527 | ixy = GET_ADDR(); |
1528 | pc += 2; | 1528 | pc += 2; |
1529 | goto set_ixy; | 1529 | goto set_ixy; |
1530 | 1530 | ||
1531 | case 0x2A:{// LD IXY,(addr) | 1531 | case 0x2A:{// LD IXY,(addr) |
1532 | int addr = GET_ADDR(); | 1532 | int addr = GET_ADDR(); |
1533 | ixy = READ_WORD( addr ); | 1533 | ixy = READ_WORD( addr ); |
1534 | pc += 2; | 1534 | pc += 2; |
1535 | goto set_ixy; | 1535 | goto set_ixy; |
1536 | } | 1536 | } |
1537 | 1537 | ||
1538 | // DD/FD CB prefix | 1538 | // DD/FD CB prefix |
1539 | case 0xCB: { | 1539 | case 0xCB: { |
1540 | data = IXY_DISP( ixy, SBYTE( data2 ) ); | 1540 | data = IXY_DISP( ixy, SBYTE( data2 ) ); |
1541 | pc++; | 1541 | pc++; |
1542 | data2 = READ_CODE( pc ); | 1542 | data2 = READ_CODE( pc ); |
1543 | pc++; | 1543 | pc++; |
1544 | switch ( data2 ) | 1544 | switch ( data2 ) |
1545 | { | 1545 | { |
1546 | case 0x06: goto rlc_data_addr; // RLC (IXY) | 1546 | case 0x06: goto rlc_data_addr; // RLC (IXY) |
1547 | case 0x16: goto rl_data_addr; // RL (IXY) | 1547 | case 0x16: goto rl_data_addr; // RL (IXY) |
1548 | case 0x26: goto sla_data_addr; // SLA (IXY) | 1548 | case 0x26: goto sla_data_addr; // SLA (IXY) |
1549 | case 0x36: goto sll_data_addr; // SLL (IXY) | 1549 | case 0x36: goto sll_data_addr; // SLL (IXY) |
1550 | case 0x0E: goto rrc_data_addr; // RRC (IXY) | 1550 | case 0x0E: goto rrc_data_addr; // RRC (IXY) |
1551 | case 0x1E: goto rr_data_addr; // RR (IXY) | 1551 | case 0x1E: goto rr_data_addr; // RR (IXY) |
1552 | case 0x2E: goto sra_data_addr; // SRA (IXY) | 1552 | case 0x2E: goto sra_data_addr; // SRA (IXY) |
1553 | case 0x3E: goto srl_data_addr; // SRL (IXY) | 1553 | case 0x3E: goto srl_data_addr; // SRL (IXY) |
1554 | 1554 | ||
1555 | CASE8( 46, 4E, 56, 5E, 66, 6E, 76, 7E ):{// BIT b,(IXY+disp) | 1555 | CASE8( 46, 4E, 56, 5E, 66, 6E, 76, 7E ):{// BIT b,(IXY+disp) |
1556 | int temp = READ_MEM( data ); | 1556 | int temp = READ_MEM( data ); |
1557 | temp = temp & (1 << (data2 >> 3 & 7)); | 1557 | temp = temp & (1 << (data2 >> 3 & 7)); |
1558 | flags = (flags & C01) + H10 + (temp & S80); | 1558 | flags = (flags & C01) + H10 + (temp & S80); |
1559 | flags += (unsigned) --temp >> 8 & (Z40 | P04); | 1559 | flags += (unsigned) --temp >> 8 & (Z40 | P04); |
1560 | goto loop; | 1560 | goto loop; |
1561 | } | 1561 | } |
1562 | 1562 | ||
1563 | CASE8( 86, 8E, 96, 9E, A6, AE, B6, BE ): // RES b,(IXY+disp) | 1563 | CASE8( 86, 8E, 96, 9E, A6, AE, B6, BE ): // RES b,(IXY+disp) |
1564 | CASE8( C6, CE, D6, DE, E6, EE, F6, FE ):{// SET b,(IXY+disp) | 1564 | CASE8( C6, CE, D6, DE, E6, EE, F6, FE ):{// SET b,(IXY+disp) |
1565 | int temp = READ_MEM( data ); | 1565 | int temp = READ_MEM( data ); |
1566 | int bit = 1 << (data2 >> 3 & 7); | 1566 | int bit = 1 << (data2 >> 3 & 7); |
1567 | temp |= bit; // SET | 1567 | temp |= bit; // SET |
1568 | if ( !(data2 & 0x40) ) | 1568 | if ( !(data2 & 0x40) ) |
1569 | temp ^= bit; // RES | 1569 | temp ^= bit; // RES |
1570 | WRITE_MEM( data, temp ); | 1570 | WRITE_MEM( data, temp ); |
1571 | goto loop; | 1571 | goto loop; |
1572 | } | 1572 | } |
1573 | 1573 | ||
1574 | default: | 1574 | default: |
1575 | dprintf( "Opcode $%02X $CB $%02X not supported\n", opcode, data2 ); | 1575 | dprintf( "Opcode $%02X $CB $%02X not supported\n", opcode, data2 ); |
1576 | warning = true; | 1576 | warning = true; |
1577 | goto loop; | 1577 | goto loop; |
1578 | } | 1578 | } |
1579 | assert( false ); | 1579 | assert( false ); |
1580 | } | 1580 | } |
1581 | 1581 | ||
1582 | // INC/DEC | 1582 | // INC/DEC |
1583 | case 0x23: // INC IXY | 1583 | case 0x23: // INC IXY |
1584 | ixy = WORD( ixy + 1 ); | 1584 | ixy = WORD( ixy + 1 ); |
1585 | goto set_ixy; | 1585 | goto set_ixy; |
1586 | 1586 | ||
1587 | case 0x2B: // DEC IXY | 1587 | case 0x2B: // DEC IXY |
1588 | ixy = WORD( ixy - 1 ); | 1588 | ixy = WORD( ixy - 1 ); |
1589 | goto set_ixy; | 1589 | goto set_ixy; |
1590 | 1590 | ||
1591 | case 0x34: // INC (IXY+disp) | 1591 | case 0x34: // INC (IXY+disp) |
1592 | ixy = IXY_DISP( ixy, SBYTE( data2 ) ); | 1592 | ixy = IXY_DISP( ixy, SBYTE( data2 ) ); |
1593 | pc++; | 1593 | pc++; |
1594 | data = READ_MEM( ixy ) + 1; | 1594 | data = READ_MEM( ixy ) + 1; |
1595 | WRITE_MEM( ixy, data ); | 1595 | WRITE_MEM( ixy, data ); |
1596 | goto inc_set_flags; | 1596 | goto inc_set_flags; |
1597 | 1597 | ||
1598 | case 0x35: // DEC (IXY+disp) | 1598 | case 0x35: // DEC (IXY+disp) |
1599 | ixy = IXY_DISP( ixy, SBYTE( data2 ) ); | 1599 | ixy = IXY_DISP( ixy, SBYTE( data2 ) ); |
1600 | pc++; | 1600 | pc++; |
1601 | data = READ_MEM( ixy ) - 1; | 1601 | data = READ_MEM( ixy ) - 1; |
1602 | WRITE_MEM( ixy, data ); | 1602 | WRITE_MEM( ixy, data ); |
1603 | goto dec_set_flags; | 1603 | goto dec_set_flags; |
1604 | 1604 | ||
1605 | case 0x24: // INC HXY | 1605 | case 0x24: // INC HXY |
1606 | ixy = WORD( ixy + 0x100 ); | 1606 | ixy = WORD( ixy + 0x100 ); |
1607 | data = ixy >> 8; | 1607 | data = ixy >> 8; |
1608 | goto inc_xy_common; | 1608 | goto inc_xy_common; |
1609 | 1609 | ||
1610 | case 0x2C: // INC LXY | 1610 | case 0x2C: // INC LXY |
1611 | data = BYTE( ixy + 1 ); | 1611 | data = BYTE( ixy + 1 ); |
1612 | ixy = (ixy & 0xFF00) + data; | 1612 | ixy = (ixy & 0xFF00) + data; |
1613 | inc_xy_common: | 1613 | inc_xy_common: |
1614 | if ( opcode == 0xDD ) | 1614 | if ( opcode == 0xDD ) |
1615 | { | 1615 | { |
1616 | ix = ixy; | 1616 | ix = ixy; |
1617 | goto inc_set_flags; | 1617 | goto inc_set_flags; |
1618 | } | 1618 | } |
1619 | iy = ixy; | 1619 | iy = ixy; |
1620 | goto inc_set_flags; | 1620 | goto inc_set_flags; |
1621 | 1621 | ||
1622 | case 0x25: // DEC HXY | 1622 | case 0x25: // DEC HXY |
1623 | ixy = WORD( ixy - 0x100 ); | 1623 | ixy = WORD( ixy - 0x100 ); |
1624 | data = ixy >> 8; | 1624 | data = ixy >> 8; |
1625 | goto dec_xy_common; | 1625 | goto dec_xy_common; |
1626 | 1626 | ||
1627 | case 0x2D: // DEC LXY | 1627 | case 0x2D: // DEC LXY |
1628 | data = BYTE( ixy - 1 ); | 1628 | data = BYTE( ixy - 1 ); |
1629 | ixy = (ixy & 0xFF00) + data; | 1629 | ixy = (ixy & 0xFF00) + data; |
1630 | dec_xy_common: | 1630 | dec_xy_common: |
1631 | if ( opcode == 0xDD ) | 1631 | if ( opcode == 0xDD ) |
1632 | { | 1632 | { |
1633 | ix = ixy; | 1633 | ix = ixy; |
1634 | goto dec_set_flags; | 1634 | goto dec_set_flags; |
1635 | } | 1635 | } |
1636 | iy = ixy; | 1636 | iy = ixy; |
1637 | goto dec_set_flags; | 1637 | goto dec_set_flags; |
1638 | 1638 | ||
1639 | // PUSH/POP | 1639 | // PUSH/POP |
1640 | case 0xE5: // PUSH IXY | 1640 | case 0xE5: // PUSH IXY |
1641 | data = ixy; | 1641 | data = ixy; |
1642 | goto push_data; | 1642 | goto push_data; |
1643 | 1643 | ||
1644 | case 0xE1:{// POP IXY | 1644 | case 0xE1:{// POP IXY |
1645 | ixy = READ_WORD( sp ); | 1645 | ixy = READ_WORD( sp ); |
1646 | sp = WORD( sp + 2 ); | 1646 | sp = WORD( sp + 2 ); |
1647 | goto set_ixy; | 1647 | goto set_ixy; |
1648 | } | 1648 | } |
1649 | 1649 | ||
1650 | // Misc | 1650 | // Misc |
1651 | 1651 | ||
1652 | case 0xE9: // JP (IXY) | 1652 | case 0xE9: // JP (IXY) |
1653 | pc = ixy; | 1653 | pc = ixy; |
1654 | goto loop; | 1654 | goto loop; |
1655 | 1655 | ||
1656 | case 0xE3:{// EX (SP),IXY | 1656 | case 0xE3:{// EX (SP),IXY |
1657 | int temp = READ_WORD( sp ); | 1657 | int temp = READ_WORD( sp ); |
1658 | WRITE_WORD( sp, ixy ); | 1658 | WRITE_WORD( sp, ixy ); |
1659 | ixy = temp; | 1659 | ixy = temp; |
1660 | goto set_ixy; | 1660 | goto set_ixy; |
1661 | } | 1661 | } |
1662 | 1662 | ||
1663 | default: | 1663 | default: |
1664 | dprintf( "Unnecessary DD/FD prefix encountered\n" ); | 1664 | dprintf( "Unnecessary DD/FD prefix encountered\n" ); |
1665 | warning = true; | 1665 | warning = true; |
1666 | pc--; | 1666 | pc--; |
1667 | goto loop; | 1667 | goto loop; |
1668 | } | 1668 | } |
1669 | assert( false ); | 1669 | assert( false ); |
1670 | } | 1670 | } |
1671 | 1671 | ||
1672 | } | 1672 | } |
1673 | dprintf( "Unhandled main opcode: $%02X\n", opcode ); | 1673 | dprintf( "Unhandled main opcode: $%02X\n", opcode ); |
1674 | assert( false ); | 1674 | assert( false ); |
1675 | 1675 | ||
1676 | #ifdef IDLE_ADDR | 1676 | #ifdef IDLE_ADDR |
1677 | hit_idle_addr: | 1677 | hit_idle_addr: |
1678 | s_time -= 11; | 1678 | s_time -= 11; |
1679 | goto out_of_time; | 1679 | goto out_of_time; |
1680 | #endif | 1680 | #endif |
1681 | halt: | 1681 | halt: |
1682 | s_time &= 3; // increment by multiple of 4 | 1682 | s_time &= 3; // increment by multiple of 4 |
1683 | out_of_time: | 1683 | out_of_time: |
1684 | pc--; | 1684 | pc--; |
1685 | 1685 | ||
1686 | r.b.flags = flags; | 1686 | r.b.flags = flags; |
1687 | R.ix = ix; | 1687 | R.ix = ix; |
1688 | R.iy = iy; | 1688 | R.iy = iy; |
1689 | R.sp = sp; | 1689 | R.sp = sp; |
1690 | R.pc = pc; | 1690 | R.pc = pc; |
1691 | R.b = r.b; | 1691 | R.b = r.b; |
1692 | 1692 | ||
1693 | cpu->cpu_state_.base = s.base; | 1693 | cpu->cpu_state_.base = s.base; |
1694 | cpu->cpu_state_.time = s_time; | 1694 | cpu->cpu_state_.time = s_time; |
1695 | cpu->cpu_state = &cpu->cpu_state_; | 1695 | cpu->cpu_state = &cpu->cpu_state_; |
1696 | } | 1696 | } |