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