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