src/lr35902/isa-lr35902.c (view raw)
1/* Copyright (c) 2013-2016 Jeffrey Pfau
2 *
3 * This Source Code Form is subject to the terms of the Mozilla Public
4 * License, v. 2.0. If a copy of the MPL was not distributed with this
5 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
6#include "isa-lr35902.h"
7
8#include "lr35902/emitter-lr35902.h"
9#include "lr35902/lr35902.h"
10
11#define DEFINE_INSTRUCTION_LR35902(NAME, BODY) \
12 static void _LR35902Instruction ## NAME (struct LR35902Core* cpu) { \
13 UNUSED(cpu); \
14 BODY; \
15 }
16
17DEFINE_INSTRUCTION_LR35902(NOP,);
18
19#define DEFINE_CONDITIONAL_ONLY_INSTRUCTION_LR35902(NAME) \
20 DEFINE_ ## NAME ## _INSTRUCTION_LR35902(C, cpu->f.c) \
21 DEFINE_ ## NAME ## _INSTRUCTION_LR35902(Z, cpu->f.z) \
22 DEFINE_ ## NAME ## _INSTRUCTION_LR35902(NC, !cpu->f.c) \
23 DEFINE_ ## NAME ## _INSTRUCTION_LR35902(NZ, !cpu->f.z)
24
25#define DEFINE_CONDITIONAL_INSTRUCTION_LR35902(NAME) \
26 DEFINE_ ## NAME ## _INSTRUCTION_LR35902(, true) \
27 DEFINE_CONDITIONAL_ONLY_INSTRUCTION_LR35902(NAME)
28
29DEFINE_INSTRUCTION_LR35902(JPFinish,
30 if (cpu->condition) {
31 cpu->pc = (cpu->bus << 8) | cpu->index;
32 cpu->memory.setActiveRegion(cpu, cpu->pc);
33 cpu->executionState = LR35902_CORE_STALL;
34 })
35
36DEFINE_INSTRUCTION_LR35902(JPDelay,
37 cpu->executionState = LR35902_CORE_READ_PC;
38 cpu->instruction = _LR35902InstructionJPFinish;
39 cpu->index = cpu->bus;)
40
41#define DEFINE_JP_INSTRUCTION_LR35902(CONDITION_NAME, CONDITION) \
42 DEFINE_INSTRUCTION_LR35902(JP ## CONDITION_NAME, \
43 cpu->executionState = LR35902_CORE_READ_PC; \
44 cpu->instruction = _LR35902InstructionJPDelay; \
45 cpu->condition = CONDITION;)
46
47DEFINE_CONDITIONAL_INSTRUCTION_LR35902(JP);
48
49DEFINE_INSTRUCTION_LR35902(JPHL,
50 cpu->pc = LR35902ReadHL(cpu);
51 cpu->memory.setActiveRegion(cpu, cpu->pc);)
52
53DEFINE_INSTRUCTION_LR35902(JRFinish,
54 if (cpu->condition) {
55 cpu->pc += (int8_t) cpu->bus;
56 cpu->memory.setActiveRegion(cpu, cpu->pc);
57 cpu->executionState = LR35902_CORE_STALL;
58 })
59
60#define DEFINE_JR_INSTRUCTION_LR35902(CONDITION_NAME, CONDITION) \
61 DEFINE_INSTRUCTION_LR35902(JR ## CONDITION_NAME, \
62 cpu->executionState = LR35902_CORE_READ_PC; \
63 cpu->instruction = _LR35902InstructionJRFinish; \
64 cpu->condition = CONDITION;)
65
66DEFINE_CONDITIONAL_INSTRUCTION_LR35902(JR);
67
68DEFINE_INSTRUCTION_LR35902(CALLUpdateSPL,
69 --cpu->index;
70 cpu->bus = cpu->sp;
71 cpu->sp = cpu->index;
72 cpu->executionState = LR35902_CORE_MEMORY_STORE;
73 cpu->instruction = _LR35902InstructionNOP;)
74
75DEFINE_INSTRUCTION_LR35902(CALLUpdateSPH,
76 cpu->executionState = LR35902_CORE_MEMORY_STORE;
77 cpu->instruction = _LR35902InstructionCALLUpdateSPL;)
78
79DEFINE_INSTRUCTION_LR35902(CALLUpdatePCH,
80 if (cpu->condition) {
81 int newPc = (cpu->bus << 8) | cpu->index;
82 cpu->bus = cpu->pc >> 8;
83 cpu->index = cpu->sp - 1;
84 cpu->sp = cpu->pc; // GROSS
85 cpu->pc = newPc;
86 cpu->memory.setActiveRegion(cpu, cpu->pc);
87 cpu->executionState = LR35902_CORE_OP2;
88 cpu->instruction = _LR35902InstructionCALLUpdateSPH;
89 })
90
91DEFINE_INSTRUCTION_LR35902(CALLUpdatePCL,
92 cpu->executionState = LR35902_CORE_READ_PC;
93 cpu->index = cpu->bus;
94 cpu->instruction = _LR35902InstructionCALLUpdatePCH)
95
96#define DEFINE_CALL_INSTRUCTION_LR35902(CONDITION_NAME, CONDITION) \
97 DEFINE_INSTRUCTION_LR35902(CALL ## CONDITION_NAME, \
98 cpu->condition = CONDITION; \
99 cpu->executionState = LR35902_CORE_READ_PC; \
100 cpu->instruction = _LR35902InstructionCALLUpdatePCL;)
101
102DEFINE_CONDITIONAL_INSTRUCTION_LR35902(CALL)
103
104DEFINE_INSTRUCTION_LR35902(RETFinish,
105 cpu->sp += 2; /* TODO: Atomic incrementing? */
106 cpu->pc |= cpu->bus << 8;
107 cpu->memory.setActiveRegion(cpu, cpu->pc);
108 cpu->executionState = LR35902_CORE_STALL;)
109
110DEFINE_INSTRUCTION_LR35902(RETUpdateSPL,
111 cpu->index = cpu->sp + 1;
112 cpu->pc = cpu->bus;
113 cpu->executionState = LR35902_CORE_MEMORY_LOAD;
114 cpu->instruction = _LR35902InstructionRETFinish;)
115
116DEFINE_INSTRUCTION_LR35902(RETUpdateSPH,
117 if (cpu->condition) {
118 cpu->index = cpu->sp;
119 cpu->executionState = LR35902_CORE_MEMORY_LOAD;
120 cpu->instruction = _LR35902InstructionRETUpdateSPL;
121 })
122
123#define DEFINE_RET_INSTRUCTION_LR35902(CONDITION_NAME, CONDITION) \
124 DEFINE_INSTRUCTION_LR35902(RET ## CONDITION_NAME, \
125 cpu->condition = CONDITION; \
126 cpu->executionState = LR35902_CORE_OP2; \
127 cpu->instruction = _LR35902InstructionRETUpdateSPH;)
128
129DEFINE_INSTRUCTION_LR35902(RET,
130 cpu->condition = true;
131 _LR35902InstructionRETUpdateSPH(cpu);)
132
133DEFINE_INSTRUCTION_LR35902(RETI,
134 cpu->condition = true;
135 cpu->irqh.setInterrupts(cpu, true);
136 _LR35902InstructionRETUpdateSPH(cpu);)
137
138DEFINE_CONDITIONAL_ONLY_INSTRUCTION_LR35902(RET)
139
140#define DEFINE_AND_INSTRUCTION_LR35902(NAME, OPERAND) \
141 DEFINE_INSTRUCTION_LR35902(AND ## NAME, \
142 cpu->a &= OPERAND; \
143 cpu->f.z = !cpu->a; \
144 cpu->f.n = 0; \
145 cpu->f.c = 0; \
146 cpu->f.h = 1;)
147
148#define DEFINE_XOR_INSTRUCTION_LR35902(NAME, OPERAND) \
149 DEFINE_INSTRUCTION_LR35902(XOR ## NAME, \
150 cpu->a ^= OPERAND; \
151 cpu->f.z = !cpu->a; \
152 cpu->f.n = 0; \
153 cpu->f.c = 0; \
154 cpu->f.h = 0;)
155
156#define DEFINE_OR_INSTRUCTION_LR35902(NAME, OPERAND) \
157 DEFINE_INSTRUCTION_LR35902(OR ## NAME, \
158 cpu->a |= OPERAND; \
159 cpu->f.z = !cpu->a; \
160 cpu->f.n = 0; \
161 cpu->f.c = 0; \
162 cpu->f.h = 0;)
163
164#define DEFINE_CP_INSTRUCTION_LR35902(NAME, OPERAND) \
165 DEFINE_INSTRUCTION_LR35902(CP ## NAME, \
166 int diff = cpu->a - OPERAND; \
167 cpu->f.n = 1; \
168 cpu->f.z = !(diff & 0xFF); \
169 cpu->f.h = (cpu->a & 0xF) - (OPERAND & 0xF) < 0; \
170 cpu->f.c = diff < 0;)
171
172#define DEFINE_LDB__INSTRUCTION_LR35902(NAME, OPERAND) \
173 DEFINE_INSTRUCTION_LR35902(LDB_ ## NAME, \
174 cpu->b = OPERAND;)
175
176#define DEFINE_LDC__INSTRUCTION_LR35902(NAME, OPERAND) \
177 DEFINE_INSTRUCTION_LR35902(LDC_ ## NAME, \
178 cpu->c = OPERAND;)
179
180#define DEFINE_LDD__INSTRUCTION_LR35902(NAME, OPERAND) \
181 DEFINE_INSTRUCTION_LR35902(LDD_ ## NAME, \
182 cpu->d = OPERAND;)
183
184#define DEFINE_LDE__INSTRUCTION_LR35902(NAME, OPERAND) \
185 DEFINE_INSTRUCTION_LR35902(LDE_ ## NAME, \
186 cpu->e = OPERAND;)
187
188#define DEFINE_LDH__INSTRUCTION_LR35902(NAME, OPERAND) \
189 DEFINE_INSTRUCTION_LR35902(LDH_ ## NAME, \
190 cpu->h = OPERAND;)
191
192#define DEFINE_LDL__INSTRUCTION_LR35902(NAME, OPERAND) \
193 DEFINE_INSTRUCTION_LR35902(LDL_ ## NAME, \
194 cpu->l = OPERAND;)
195
196#define DEFINE_LDHL__INSTRUCTION_LR35902(NAME, OPERAND) \
197 DEFINE_INSTRUCTION_LR35902(LDHL_ ## NAME, \
198 cpu->bus = OPERAND; \
199 cpu->index = LR35902ReadHL(cpu); \
200 cpu->executionState = LR35902_CORE_MEMORY_STORE; \
201 cpu->instruction = _LR35902InstructionNOP;)
202
203#define DEFINE_LDA__INSTRUCTION_LR35902(NAME, OPERAND) \
204 DEFINE_INSTRUCTION_LR35902(LDA_ ## NAME, \
205 cpu->a = OPERAND;)
206
207#define DEFINE_ALU_INSTRUCTION_LR35902_NOHL(NAME) \
208 DEFINE_ ## NAME ## _INSTRUCTION_LR35902(A, cpu->a); \
209 DEFINE_ ## NAME ## _INSTRUCTION_LR35902(B, cpu->b); \
210 DEFINE_ ## NAME ## _INSTRUCTION_LR35902(C, cpu->c); \
211 DEFINE_ ## NAME ## _INSTRUCTION_LR35902(D, cpu->d); \
212 DEFINE_ ## NAME ## _INSTRUCTION_LR35902(E, cpu->e); \
213 DEFINE_ ## NAME ## _INSTRUCTION_LR35902(H, cpu->h); \
214 DEFINE_ ## NAME ## _INSTRUCTION_LR35902(L, cpu->l);
215
216DEFINE_INSTRUCTION_LR35902(LDHL_Bus, \
217 cpu->index = LR35902ReadHL(cpu); \
218 cpu->executionState = LR35902_CORE_MEMORY_STORE; \
219 cpu->instruction = _LR35902InstructionNOP;)
220
221DEFINE_INSTRUCTION_LR35902(LDHL_, \
222 cpu->executionState = LR35902_CORE_READ_PC; \
223 cpu->instruction = _LR35902InstructionLDHL_Bus;)
224
225DEFINE_INSTRUCTION_LR35902(LDHL_SPDelay,
226 int diff = (int8_t) cpu->bus;
227 int sum = cpu->sp + diff;
228 LR35902WriteHL(cpu, sum);
229 cpu->executionState = LR35902_CORE_STALL;
230 cpu->f.z = 0;
231 cpu->f.n = 0;
232 cpu->f.c = (diff & 0xFF) + (cpu->sp & 0xFF) >= 0x100;
233 cpu->f.h = (diff & 0xF) + (cpu->sp & 0xF) >= 0x10;)
234
235DEFINE_INSTRUCTION_LR35902(LDHL_SP,
236 cpu->executionState = LR35902_CORE_READ_PC;
237 cpu->instruction = _LR35902InstructionLDHL_SPDelay;)
238
239DEFINE_INSTRUCTION_LR35902(LDSP_HL,
240 cpu->sp = LR35902ReadHL(cpu);
241 cpu->executionState = LR35902_CORE_STALL;)
242
243#define DEFINE_ALU_INSTRUCTION_LR35902_MEM(NAME, REG) \
244 DEFINE_INSTRUCTION_LR35902(NAME ## REG, \
245 cpu->executionState = LR35902_CORE_MEMORY_LOAD; \
246 cpu->index = LR35902Read ## REG (cpu); \
247 cpu->instruction = _LR35902Instruction ## NAME ## Bus;)
248
249#define DEFINE_ALU_INSTRUCTION_LR35902(NAME) \
250 DEFINE_ ## NAME ## _INSTRUCTION_LR35902(Bus, cpu->bus); \
251 DEFINE_ALU_INSTRUCTION_LR35902_MEM(NAME, HL) \
252 DEFINE_INSTRUCTION_LR35902(NAME, \
253 cpu->executionState = LR35902_CORE_READ_PC; \
254 cpu->instruction = _LR35902Instruction ## NAME ## Bus;) \
255 DEFINE_ALU_INSTRUCTION_LR35902_NOHL(NAME)
256
257DEFINE_ALU_INSTRUCTION_LR35902(AND);
258DEFINE_ALU_INSTRUCTION_LR35902(XOR);
259DEFINE_ALU_INSTRUCTION_LR35902(OR);
260DEFINE_ALU_INSTRUCTION_LR35902(CP);
261
262static void _LR35902InstructionLDB_Bus(struct LR35902Core*);
263static void _LR35902InstructionLDC_Bus(struct LR35902Core*);
264static void _LR35902InstructionLDD_Bus(struct LR35902Core*);
265static void _LR35902InstructionLDE_Bus(struct LR35902Core*);
266static void _LR35902InstructionLDH_Bus(struct LR35902Core*);
267static void _LR35902InstructionLDL_Bus(struct LR35902Core*);
268static void _LR35902InstructionLDHL_Bus(struct LR35902Core*);
269static void _LR35902InstructionLDA_Bus(struct LR35902Core*);
270
271#define DEFINE_ADD_INSTRUCTION_LR35902(NAME, OPERAND) \
272 DEFINE_INSTRUCTION_LR35902(ADD ## NAME, \
273 int diff = cpu->a + OPERAND; \
274 cpu->f.n = 0; \
275 cpu->f.h = (cpu->a & 0xF) + (OPERAND & 0xF) >= 0x10; \
276 cpu->f.c = diff >= 0x100; \
277 cpu->a = diff; \
278 cpu->f.z = !cpu->a;)
279
280#define DEFINE_ADC_INSTRUCTION_LR35902(NAME, OPERAND) \
281 DEFINE_INSTRUCTION_LR35902(ADC ## NAME, \
282 int diff = cpu->a + OPERAND + cpu->f.c; \
283 cpu->f.n = 0; \
284 cpu->f.h = (cpu->a & 0xF) + (OPERAND & 0xF) + cpu->f.c >= 0x10; \
285 cpu->f.c = diff >= 0x100; \
286 cpu->a = diff; \
287 cpu->f.z = !cpu->a;)
288
289#define DEFINE_SUB_INSTRUCTION_LR35902(NAME, OPERAND) \
290 DEFINE_INSTRUCTION_LR35902(SUB ## NAME, \
291 int diff = cpu->a - OPERAND; \
292 cpu->f.n = 1; \
293 cpu->f.h = (cpu->a & 0xF) - (OPERAND & 0xF) < 0; \
294 cpu->f.c = diff < 0; \
295 cpu->a = diff; \
296 cpu->f.z = !cpu->a;)
297
298#define DEFINE_SBC_INSTRUCTION_LR35902(NAME, OPERAND) \
299 DEFINE_INSTRUCTION_LR35902(SBC ## NAME, \
300 int diff = cpu->a - OPERAND - cpu->f.c; \
301 cpu->f.n = 1; \
302 cpu->f.h = (cpu->a & 0xF) - (OPERAND & 0xF) - cpu->f.c < 0; \
303 cpu->f.c = diff < 0; \
304 cpu->a = diff; \
305 cpu->f.z = !cpu->a;)
306
307DEFINE_ALU_INSTRUCTION_LR35902(LDB_);
308DEFINE_ALU_INSTRUCTION_LR35902(LDC_);
309DEFINE_ALU_INSTRUCTION_LR35902(LDD_);
310DEFINE_ALU_INSTRUCTION_LR35902(LDE_);
311DEFINE_ALU_INSTRUCTION_LR35902(LDH_);
312DEFINE_ALU_INSTRUCTION_LR35902(LDL_);
313DEFINE_ALU_INSTRUCTION_LR35902_NOHL(LDHL_);
314DEFINE_ALU_INSTRUCTION_LR35902(LDA_);
315DEFINE_ALU_INSTRUCTION_LR35902_MEM(LDA_, BC);
316DEFINE_ALU_INSTRUCTION_LR35902_MEM(LDA_, DE);
317DEFINE_ALU_INSTRUCTION_LR35902(ADD);
318DEFINE_ALU_INSTRUCTION_LR35902(ADC);
319DEFINE_ALU_INSTRUCTION_LR35902(SUB);
320DEFINE_ALU_INSTRUCTION_LR35902(SBC);
321
322DEFINE_INSTRUCTION_LR35902(ADDSPFinish,
323 cpu->sp = cpu->index;
324 cpu->executionState = LR35902_CORE_STALL;)
325
326DEFINE_INSTRUCTION_LR35902(ADDSPDelay,
327 int diff = (int8_t) cpu->bus;
328 int sum = cpu->sp + diff;
329 cpu->index = sum;
330 cpu->executionState = LR35902_CORE_OP2;
331 cpu->instruction = _LR35902InstructionADDSPFinish;
332 cpu->f.z = 0;
333 cpu->f.n = 0;
334 cpu->f.c = (diff & 0xFF) + (cpu->sp & 0xFF) >= 0x100;
335 cpu->f.h = (diff & 0xF) + (cpu->sp & 0xF) >= 0x10;)
336
337DEFINE_INSTRUCTION_LR35902(ADDSP,
338 cpu->executionState = LR35902_CORE_READ_PC;
339 cpu->instruction = _LR35902InstructionADDSPDelay;)
340
341DEFINE_INSTRUCTION_LR35902(LDBCDelay, \
342 cpu->c = cpu->bus; \
343 cpu->executionState = LR35902_CORE_READ_PC; \
344 cpu->instruction = _LR35902InstructionLDB_Bus;)
345
346DEFINE_INSTRUCTION_LR35902(LDBC, \
347 cpu->executionState = LR35902_CORE_READ_PC; \
348 cpu->instruction = _LR35902InstructionLDBCDelay;)
349
350DEFINE_INSTRUCTION_LR35902(LDBC_A, \
351 cpu->index = LR35902ReadBC(cpu); \
352 cpu->bus = cpu->a; \
353 cpu->executionState = LR35902_CORE_MEMORY_STORE; \
354 cpu->instruction = _LR35902InstructionNOP;)
355
356DEFINE_INSTRUCTION_LR35902(LDDEDelay, \
357 cpu->e = cpu->bus; \
358 cpu->executionState = LR35902_CORE_READ_PC; \
359 cpu->instruction = _LR35902InstructionLDD_Bus;)
360
361DEFINE_INSTRUCTION_LR35902(LDDE, \
362 cpu->executionState = LR35902_CORE_READ_PC; \
363 cpu->instruction = _LR35902InstructionLDDEDelay;)
364
365DEFINE_INSTRUCTION_LR35902(LDDE_A, \
366 cpu->index = LR35902ReadDE(cpu); \
367 cpu->bus = cpu->a; \
368 cpu->executionState = LR35902_CORE_MEMORY_STORE; \
369 cpu->instruction = _LR35902InstructionNOP;)
370
371DEFINE_INSTRUCTION_LR35902(LDHLDelay, \
372 cpu->l = cpu->bus; \
373 cpu->executionState = LR35902_CORE_READ_PC; \
374 cpu->instruction = _LR35902InstructionLDH_Bus;)
375
376DEFINE_INSTRUCTION_LR35902(LDHL, \
377 cpu->executionState = LR35902_CORE_READ_PC; \
378 cpu->instruction = _LR35902InstructionLDHLDelay;)
379
380DEFINE_INSTRUCTION_LR35902(LDSPFinish, cpu->sp |= cpu->bus << 8;)
381
382DEFINE_INSTRUCTION_LR35902(LDSPDelay, \
383 cpu->sp = cpu->bus; \
384 cpu->executionState = LR35902_CORE_READ_PC; \
385 cpu->instruction = _LR35902InstructionLDSPFinish;)
386
387DEFINE_INSTRUCTION_LR35902(LDSP, \
388 cpu->executionState = LR35902_CORE_READ_PC; \
389 cpu->instruction = _LR35902InstructionLDSPDelay;)
390
391DEFINE_INSTRUCTION_LR35902(LDIHLA, \
392 cpu->index = LR35902ReadHL(cpu); \
393 LR35902WriteHL(cpu, cpu->index + 1); \
394 cpu->bus = cpu->a; \
395 cpu->executionState = LR35902_CORE_MEMORY_STORE; \
396 cpu->instruction = _LR35902InstructionNOP;)
397
398DEFINE_INSTRUCTION_LR35902(LDDHLA, \
399 cpu->index = LR35902ReadHL(cpu); \
400 LR35902WriteHL(cpu, cpu->index - 1); \
401 cpu->bus = cpu->a; \
402 cpu->executionState = LR35902_CORE_MEMORY_STORE; \
403 cpu->instruction = _LR35902InstructionNOP;)
404
405DEFINE_INSTRUCTION_LR35902(LDA_IHL, \
406 cpu->index = LR35902ReadHL(cpu); \
407 LR35902WriteHL(cpu, cpu->index + 1); \
408 cpu->executionState = LR35902_CORE_MEMORY_LOAD; \
409 cpu->instruction = _LR35902InstructionLDA_Bus;)
410
411DEFINE_INSTRUCTION_LR35902(LDA_DHL, \
412 cpu->index = LR35902ReadHL(cpu); \
413 LR35902WriteHL(cpu, cpu->index - 1); \
414 cpu->executionState = LR35902_CORE_MEMORY_LOAD; \
415 cpu->instruction = _LR35902InstructionLDA_Bus;)
416
417DEFINE_INSTRUCTION_LR35902(LDIAFinish, \
418 cpu->index |= cpu->bus << 8;
419 cpu->bus = cpu->a; \
420 cpu->executionState = LR35902_CORE_MEMORY_STORE; \
421 cpu->instruction = _LR35902InstructionNOP;)
422
423DEFINE_INSTRUCTION_LR35902(LDIADelay, \
424 cpu->index = cpu->bus;
425 cpu->executionState = LR35902_CORE_READ_PC; \
426 cpu->instruction = _LR35902InstructionLDIAFinish;)
427
428DEFINE_INSTRUCTION_LR35902(LDIA, \
429 cpu->executionState = LR35902_CORE_READ_PC; \
430 cpu->instruction = _LR35902InstructionLDIADelay;)
431
432DEFINE_INSTRUCTION_LR35902(LDAIFinish, \
433 cpu->index |= cpu->bus << 8;
434 cpu->executionState = LR35902_CORE_MEMORY_LOAD; \
435 cpu->instruction = _LR35902InstructionLDA_Bus;)
436
437DEFINE_INSTRUCTION_LR35902(LDAIDelay, \
438 cpu->index = cpu->bus;
439 cpu->executionState = LR35902_CORE_READ_PC; \
440 cpu->instruction = _LR35902InstructionLDAIFinish;)
441
442DEFINE_INSTRUCTION_LR35902(LDAI, \
443 cpu->executionState = LR35902_CORE_READ_PC; \
444 cpu->instruction = _LR35902InstructionLDAIDelay;)
445
446DEFINE_INSTRUCTION_LR35902(LDAIOC, \
447 cpu->index = 0xFF00 | cpu->c; \
448 cpu->executionState = LR35902_CORE_MEMORY_LOAD; \
449 cpu->instruction = _LR35902InstructionLDA_Bus;)
450
451DEFINE_INSTRUCTION_LR35902(LDIOCA, \
452 cpu->index = 0xFF00 | cpu->c; \
453 cpu->bus = cpu->a; \
454 cpu->executionState = LR35902_CORE_MEMORY_STORE; \
455 cpu->instruction = _LR35902InstructionNOP;)
456
457DEFINE_INSTRUCTION_LR35902(LDAIODelay, \
458 cpu->index = 0xFF00 | cpu->bus; \
459 cpu->executionState = LR35902_CORE_MEMORY_LOAD; \
460 cpu->instruction = _LR35902InstructionLDA_Bus;)
461
462DEFINE_INSTRUCTION_LR35902(LDAIO, \
463 cpu->executionState = LR35902_CORE_READ_PC; \
464 cpu->instruction = _LR35902InstructionLDAIODelay;)
465
466DEFINE_INSTRUCTION_LR35902(LDIOADelay, \
467 cpu->index = 0xFF00 | cpu->bus; \
468 cpu->bus = cpu->a; \
469 cpu->executionState = LR35902_CORE_MEMORY_STORE; \
470 cpu->instruction = _LR35902InstructionNOP;)
471
472DEFINE_INSTRUCTION_LR35902(LDIOA, \
473 cpu->executionState = LR35902_CORE_READ_PC; \
474 cpu->instruction = _LR35902InstructionLDIOADelay;)
475
476DEFINE_INSTRUCTION_LR35902(LDISPStoreH,
477 ++cpu->index;
478 cpu->bus = cpu->sp >> 8;
479 cpu->executionState = LR35902_CORE_MEMORY_STORE;
480 cpu->instruction = _LR35902InstructionNOP;)
481
482DEFINE_INSTRUCTION_LR35902(LDISPStoreL,
483 cpu->index |= cpu->bus << 8;
484 cpu->bus = cpu->sp;
485 cpu->executionState = LR35902_CORE_MEMORY_STORE;
486 cpu->instruction = _LR35902InstructionLDISPStoreH;)
487
488DEFINE_INSTRUCTION_LR35902(LDISPReadAddr,
489 cpu->index = cpu->bus;
490 cpu->executionState = LR35902_CORE_READ_PC;
491 cpu->instruction = _LR35902InstructionLDISPStoreL;)
492
493DEFINE_INSTRUCTION_LR35902(LDISP,
494 cpu->executionState = LR35902_CORE_READ_PC;
495 cpu->instruction = _LR35902InstructionLDISPReadAddr;)
496
497#define DEFINE_INCDEC_WIDE_INSTRUCTION_LR35902(REG) \
498 DEFINE_INSTRUCTION_LR35902(INC ## REG, \
499 uint16_t reg = LR35902Read ## REG (cpu); \
500 LR35902Write ## REG (cpu, reg + 1); \
501 cpu->executionState = LR35902_CORE_STALL;) \
502 DEFINE_INSTRUCTION_LR35902(DEC ## REG, \
503 uint16_t reg = LR35902Read ## REG (cpu); \
504 LR35902Write ## REG (cpu, reg - 1); \
505 cpu->executionState = LR35902_CORE_STALL;)
506
507DEFINE_INCDEC_WIDE_INSTRUCTION_LR35902(BC);
508DEFINE_INCDEC_WIDE_INSTRUCTION_LR35902(DE);
509DEFINE_INCDEC_WIDE_INSTRUCTION_LR35902(HL);
510
511#define DEFINE_ADD_HL_INSTRUCTION_LR35902(REG, L, H) \
512 DEFINE_INSTRUCTION_LR35902(ADDHL_ ## REG ## Finish, \
513 int diff = H + cpu->h + cpu->f.c; \
514 cpu->f.n = 0; \
515 cpu->f.h = (H & 0xF) + (cpu->h & 0xF) + cpu->f.c >= 0x10; \
516 cpu->f.c = diff >= 0x100; \
517 cpu->h = diff;) \
518 DEFINE_INSTRUCTION_LR35902(ADDHL_ ## REG, \
519 int diff = L + cpu->l; \
520 cpu->l = diff; \
521 cpu->f.c = diff >= 0x100; \
522 cpu->executionState = LR35902_CORE_OP2; \
523 cpu->instruction = _LR35902InstructionADDHL_ ## REG ## Finish;)
524
525DEFINE_ADD_HL_INSTRUCTION_LR35902(BC, cpu->c, cpu->b);
526DEFINE_ADD_HL_INSTRUCTION_LR35902(DE, cpu->e, cpu->d);
527DEFINE_ADD_HL_INSTRUCTION_LR35902(HL, cpu->l, cpu->h);
528DEFINE_ADD_HL_INSTRUCTION_LR35902(SP, (cpu->sp & 0xFF), (cpu->sp >> 8));
529
530
531#define DEFINE_INC_INSTRUCTION_LR35902(NAME, OPERAND) \
532 DEFINE_INSTRUCTION_LR35902(INC ## NAME, \
533 int diff = OPERAND + 1; \
534 cpu->f.h = (OPERAND & 0xF) == 0xF; \
535 OPERAND = diff; \
536 cpu->f.n = 0; \
537 cpu->f.z = !OPERAND;)
538
539#define DEFINE_DEC_INSTRUCTION_LR35902(NAME, OPERAND) \
540 DEFINE_INSTRUCTION_LR35902(DEC ## NAME, \
541 int diff = OPERAND - 1; \
542 cpu->f.h = (OPERAND & 0xF) == 0x0; \
543 OPERAND = diff; \
544 cpu->f.n = 1; \
545 cpu->f.z = !OPERAND;)
546
547DEFINE_ALU_INSTRUCTION_LR35902_NOHL(INC);
548DEFINE_ALU_INSTRUCTION_LR35902_NOHL(DEC);
549
550DEFINE_INSTRUCTION_LR35902(INC_HLDelay,
551 int diff = cpu->bus + 1;
552 cpu->f.n = 0;
553 cpu->f.h = (cpu->bus & 0xF) == 0xF;
554 cpu->bus = diff;
555 cpu->f.z = !cpu->bus;
556 cpu->instruction = _LR35902InstructionNOP;
557 cpu->executionState = LR35902_CORE_MEMORY_STORE;)
558
559DEFINE_INSTRUCTION_LR35902(INC_HL,
560 cpu->index = LR35902ReadHL(cpu);
561 cpu->instruction = _LR35902InstructionINC_HLDelay;
562 cpu->executionState = LR35902_CORE_MEMORY_LOAD;)
563
564DEFINE_INSTRUCTION_LR35902(DEC_HLDelay,
565 int diff = cpu->bus - 1;
566 cpu->f.n = 1;
567 cpu->f.h = (cpu->bus & 0xF) == 0;
568 cpu->bus = diff;
569 cpu->f.z = !cpu->bus;
570 cpu->instruction = _LR35902InstructionNOP;
571 cpu->executionState = LR35902_CORE_MEMORY_STORE;)
572
573DEFINE_INSTRUCTION_LR35902(DEC_HL,
574 cpu->index = LR35902ReadHL(cpu);
575 cpu->instruction = _LR35902InstructionDEC_HLDelay;
576 cpu->executionState = LR35902_CORE_MEMORY_LOAD;)
577
578DEFINE_INSTRUCTION_LR35902(INCSP,
579 ++cpu->sp;
580 cpu->executionState = LR35902_CORE_STALL;)
581
582DEFINE_INSTRUCTION_LR35902(DECSP,
583 --cpu->sp;
584 cpu->executionState = LR35902_CORE_STALL;)
585
586DEFINE_INSTRUCTION_LR35902(SCF,
587 cpu->f.c = 1;
588 cpu->f.h = 0;
589 cpu->f.n = 0;)
590
591DEFINE_INSTRUCTION_LR35902(CCF,
592 cpu->f.c ^= 1;
593 cpu->f.h = 0;
594 cpu->f.n = 0;)
595
596DEFINE_INSTRUCTION_LR35902(CPL_,
597 cpu->a ^= 0xFF;
598 cpu->f.h = 1;
599 cpu->f.n = 1;)
600
601DEFINE_INSTRUCTION_LR35902(DAA,
602 if (cpu->f.n) {
603 if (cpu->f.h) {
604 cpu->a += 0xFA;
605 }
606 if (cpu->f.c) {
607 cpu->a += 0xA0;
608 }
609 } else {
610 int a = cpu->a;
611 if ((cpu->a & 0xF) > 0x9 || cpu->f.h) {
612 a += 0x6;
613 }
614 if ((a & 0x1F0) > 0x90 || cpu->f.c) {
615 a += 0x60;
616 cpu->f.c = 1;
617 } else {
618 cpu->f.c = 0;
619 }
620 cpu->a = a;
621 }
622 cpu->f.h = 0;
623 cpu->f.z = !cpu->a;)
624
625#define DEFINE_POPPUSH_INSTRUCTION_LR35902(REG, HH, H, L) \
626 DEFINE_INSTRUCTION_LR35902(POP ## REG ## Delay, \
627 cpu-> L = cpu->bus; \
628 cpu->f.packed &= 0xF0; \
629 cpu->index = cpu->sp; \
630 ++cpu->sp; \
631 cpu->instruction = _LR35902InstructionLD ## HH ## _Bus; \
632 cpu->executionState = LR35902_CORE_MEMORY_LOAD;) \
633 DEFINE_INSTRUCTION_LR35902(POP ## REG, \
634 cpu->index = cpu->sp; \
635 ++cpu->sp; \
636 cpu->instruction = _LR35902InstructionPOP ## REG ## Delay; \
637 cpu->executionState = LR35902_CORE_MEMORY_LOAD;) \
638 DEFINE_INSTRUCTION_LR35902(PUSH ## REG ## Finish, \
639 cpu->executionState = LR35902_CORE_STALL;) \
640 DEFINE_INSTRUCTION_LR35902(PUSH ## REG ## Delay, \
641 --cpu->sp; \
642 cpu->index = cpu->sp; \
643 cpu->bus = cpu-> L; \
644 cpu->instruction = _LR35902InstructionPUSH ## REG ## Finish; \
645 cpu->executionState = LR35902_CORE_MEMORY_STORE;) \
646 DEFINE_INSTRUCTION_LR35902(PUSH ## REG, \
647 --cpu->sp; \
648 cpu->index = cpu->sp; \
649 cpu->bus = cpu-> H; \
650 cpu->instruction = _LR35902InstructionPUSH ## REG ## Delay; \
651 cpu->executionState = LR35902_CORE_MEMORY_STORE;)
652
653DEFINE_POPPUSH_INSTRUCTION_LR35902(BC, B, b, c);
654DEFINE_POPPUSH_INSTRUCTION_LR35902(DE, D, d, e);
655DEFINE_POPPUSH_INSTRUCTION_LR35902(HL, H, h, l);
656DEFINE_POPPUSH_INSTRUCTION_LR35902(AF, A, a, f.packed);
657
658#define DEFINE_CB_2_INSTRUCTION_LR35902(NAME, WB, BODY) \
659 DEFINE_INSTRUCTION_LR35902(NAME ## B, uint8_t reg = cpu->b; BODY; cpu->b = reg) \
660 DEFINE_INSTRUCTION_LR35902(NAME ## C, uint8_t reg = cpu->c; BODY; cpu->c = reg) \
661 DEFINE_INSTRUCTION_LR35902(NAME ## D, uint8_t reg = cpu->d; BODY; cpu->d = reg) \
662 DEFINE_INSTRUCTION_LR35902(NAME ## E, uint8_t reg = cpu->e; BODY; cpu->e = reg) \
663 DEFINE_INSTRUCTION_LR35902(NAME ## H, uint8_t reg = cpu->h; BODY; cpu->h = reg) \
664 DEFINE_INSTRUCTION_LR35902(NAME ## L, uint8_t reg = cpu->l; BODY; cpu->l = reg) \
665 DEFINE_INSTRUCTION_LR35902(NAME ## HLDelay, \
666 uint8_t reg = cpu->bus; \
667 BODY; \
668 cpu->bus = reg; \
669 cpu->executionState = WB; \
670 cpu->instruction = _LR35902InstructionNOP;) \
671 DEFINE_INSTRUCTION_LR35902(NAME ## HL, \
672 cpu->index = LR35902ReadHL(cpu); \
673 cpu->executionState = LR35902_CORE_MEMORY_LOAD; \
674 cpu->instruction = _LR35902Instruction ## NAME ## HLDelay;) \
675 DEFINE_INSTRUCTION_LR35902(NAME ## A, uint8_t reg = cpu->a; BODY; cpu->a = reg)
676
677#define DEFINE_CB_INSTRUCTION_LR35902(NAME, WB, BODY) \
678 DEFINE_CB_2_INSTRUCTION_LR35902(NAME ## 0, WB, uint8_t bit = 1; BODY) \
679 DEFINE_CB_2_INSTRUCTION_LR35902(NAME ## 1, WB, uint8_t bit = 2; BODY) \
680 DEFINE_CB_2_INSTRUCTION_LR35902(NAME ## 2, WB, uint8_t bit = 4; BODY) \
681 DEFINE_CB_2_INSTRUCTION_LR35902(NAME ## 3, WB, uint8_t bit = 8; BODY) \
682 DEFINE_CB_2_INSTRUCTION_LR35902(NAME ## 4, WB, uint8_t bit = 16; BODY) \
683 DEFINE_CB_2_INSTRUCTION_LR35902(NAME ## 5, WB, uint8_t bit = 32; BODY) \
684 DEFINE_CB_2_INSTRUCTION_LR35902(NAME ## 6, WB, uint8_t bit = 64; BODY) \
685 DEFINE_CB_2_INSTRUCTION_LR35902(NAME ## 7, WB, uint8_t bit = 128; BODY)
686
687DEFINE_CB_INSTRUCTION_LR35902(BIT, LR35902_CORE_FETCH, cpu->f.n = 0; cpu->f.h = 1; cpu->f.z = !(reg & bit))
688DEFINE_CB_INSTRUCTION_LR35902(RES, LR35902_CORE_MEMORY_STORE, reg &= ~bit)
689DEFINE_CB_INSTRUCTION_LR35902(SET, LR35902_CORE_MEMORY_STORE, reg |= bit)
690
691#define DEFINE_CB_ALU_INSTRUCTION_LR35902(NAME, BODY) \
692 DEFINE_CB_2_INSTRUCTION_LR35902(NAME, LR35902_CORE_MEMORY_STORE, \
693 BODY; \
694 cpu->f.n = 0; \
695 cpu->f.h = 0; \
696 cpu->f.z = !reg;)
697
698DEFINE_CB_ALU_INSTRUCTION_LR35902(RL, int wide = (reg << 1) | cpu->f.c; reg = wide; cpu->f.c = wide >> 8)
699DEFINE_CB_ALU_INSTRUCTION_LR35902(RLC, reg = (reg << 1) | (reg >> 7); cpu->f.c = reg & 1)
700DEFINE_CB_ALU_INSTRUCTION_LR35902(RR, int low = reg & 1; reg = (reg >> 1) | (cpu->f.c << 7); cpu->f.c = low)
701DEFINE_CB_ALU_INSTRUCTION_LR35902(RRC, int low = reg & 1; reg = (reg >> 1) | (low << 7); cpu->f.c = low)
702DEFINE_CB_ALU_INSTRUCTION_LR35902(SLA, cpu->f.c = reg >> 7; reg <<= 1)
703DEFINE_CB_ALU_INSTRUCTION_LR35902(SRA, cpu->f.c = reg & 1; reg = ((int8_t) reg) >> 1)
704DEFINE_CB_ALU_INSTRUCTION_LR35902(SRL, cpu->f.c = reg & 1; reg >>= 1)
705DEFINE_CB_ALU_INSTRUCTION_LR35902(SWAP, reg = (reg << 4) | (reg >> 4); cpu->f.c = 0)
706
707DEFINE_INSTRUCTION_LR35902(RLA_,
708 int wide = (cpu->a << 1) | cpu->f.c;
709 cpu->a = wide;
710 cpu->f.z = 0;
711 cpu->f.h = 0;
712 cpu->f.n = 0;
713 cpu->f.c = wide >> 8;)
714
715DEFINE_INSTRUCTION_LR35902(RLCA_,
716 cpu->a = (cpu->a << 1) | (cpu->a >> 7);
717 cpu->f.z = 0;
718 cpu->f.h = 0;
719 cpu->f.n = 0;
720 cpu->f.c = cpu->a & 1;)
721
722DEFINE_INSTRUCTION_LR35902(RRA_,
723 int low = cpu->a & 1;
724 cpu->a = (cpu->a >> 1) | (cpu->f.c << 7);
725 cpu->f.z = 0;
726 cpu->f.h = 0;
727 cpu->f.n = 0;
728 cpu->f.c = low;)
729
730DEFINE_INSTRUCTION_LR35902(RRCA_,
731 int low = cpu->a & 1;
732 cpu->a = (cpu->a >> 1) | (low << 7);
733 cpu->f.z = 0;
734 cpu->f.h = 0;
735 cpu->f.n = 0;
736 cpu->f.c = low;)
737
738DEFINE_INSTRUCTION_LR35902(DI, cpu->irqh.setInterrupts(cpu, false));
739DEFINE_INSTRUCTION_LR35902(EI, cpu->irqh.setInterrupts(cpu, true));
740DEFINE_INSTRUCTION_LR35902(HALT, cpu->irqh.halt(cpu));
741
742#define DEFINE_RST_INSTRUCTION_LR35902(VEC) \
743 DEFINE_INSTRUCTION_LR35902(RST ## VEC ## UpdateSPL, \
744 --cpu->sp; \
745 cpu->index = cpu->sp; \
746 cpu->bus = cpu->pc; \
747 cpu->pc = 0x ## VEC; \
748 cpu->memory.setActiveRegion(cpu, cpu->pc); \
749 cpu->executionState = LR35902_CORE_MEMORY_STORE; \
750 cpu->instruction = _LR35902InstructionNOP;) \
751 DEFINE_INSTRUCTION_LR35902(RST ## VEC ## UpdateSPH, \
752 --cpu->sp;\
753 cpu->index = cpu->sp; \
754 cpu->bus = cpu->pc >> 8; \
755 cpu->executionState = LR35902_CORE_MEMORY_STORE; \
756 cpu->instruction = _LR35902InstructionRST ## VEC ## UpdateSPL;) \
757 DEFINE_INSTRUCTION_LR35902(RST ## VEC, \
758 cpu->executionState = LR35902_CORE_OP2; \
759 cpu->instruction = _LR35902InstructionRST ## VEC ## UpdateSPH;)
760
761DEFINE_RST_INSTRUCTION_LR35902(00);
762DEFINE_RST_INSTRUCTION_LR35902(08);
763DEFINE_RST_INSTRUCTION_LR35902(10);
764DEFINE_RST_INSTRUCTION_LR35902(18);
765DEFINE_RST_INSTRUCTION_LR35902(20);
766DEFINE_RST_INSTRUCTION_LR35902(28);
767DEFINE_RST_INSTRUCTION_LR35902(30);
768DEFINE_RST_INSTRUCTION_LR35902(38);
769
770DEFINE_INSTRUCTION_LR35902(ILL, cpu->irqh.hitIllegal(cpu));
771
772DEFINE_INSTRUCTION_LR35902(STOP2, cpu->irqh.stop(cpu));
773
774DEFINE_INSTRUCTION_LR35902(STOP, \
775 cpu->executionState = LR35902_CORE_READ_PC; \
776 cpu->instruction = _LR35902InstructionSTOP2;)
777
778static const LR35902Instruction _lr35902CBInstructionTable[0x100] = {
779 DECLARE_LR35902_CB_EMITTER_BLOCK(_LR35902Instruction)
780};
781
782DEFINE_INSTRUCTION_LR35902(CBDelegate, _lr35902CBInstructionTable[cpu->bus](cpu))
783
784DEFINE_INSTRUCTION_LR35902(CB, \
785 cpu->executionState = LR35902_CORE_READ_PC; \
786 cpu->instruction = _LR35902InstructionCBDelegate;)
787
788const LR35902Instruction _lr35902InstructionTable[0x100] = {
789 DECLARE_LR35902_EMITTER_BLOCK(_LR35902Instruction)
790};