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 & 0xFF); \
162 cpu->f.h = (cpu->a & 0xF) - (OPERAND & 0xF) < 0; \
163 cpu->f.c = diff < 0;)
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 = (int8_t) cpu->bus;
220 int sum = cpu->sp + diff;
221 LR35902WriteHL(cpu, sum);
222 cpu->executionState = LR35902_CORE_STALL;
223 cpu->f.z = 0;
224 cpu->f.n = 0;
225 cpu->f.c = (diff & 0xFF) + (cpu->sp & 0xFF) >= 0x100;
226 cpu->f.h = (diff & 0xF) + (cpu->sp & 0xF) >= 0x10;)
227
228DEFINE_INSTRUCTION_LR35902(LDHL_SP,
229 cpu->executionState = LR35902_CORE_READ_PC;
230 cpu->instruction = _LR35902InstructionLDHL_SPDelay;)
231
232DEFINE_INSTRUCTION_LR35902(LDSP_HL,
233 cpu->sp = LR35902ReadHL(cpu);
234 cpu->executionState = LR35902_CORE_STALL;)
235
236#define DEFINE_ALU_INSTRUCTION_LR35902_MEM(NAME, REG) \
237 DEFINE_INSTRUCTION_LR35902(NAME ## REG, \
238 cpu->executionState = LR35902_CORE_MEMORY_LOAD; \
239 cpu->index = LR35902Read ## REG (cpu); \
240 cpu->instruction = _LR35902Instruction ## NAME ## Bus;)
241
242#define DEFINE_ALU_INSTRUCTION_LR35902(NAME) \
243 DEFINE_ ## NAME ## _INSTRUCTION_LR35902(Bus, cpu->bus); \
244 DEFINE_ALU_INSTRUCTION_LR35902_MEM(NAME, HL) \
245 DEFINE_INSTRUCTION_LR35902(NAME, \
246 cpu->executionState = LR35902_CORE_READ_PC; \
247 cpu->instruction = _LR35902Instruction ## NAME ## Bus;) \
248 DEFINE_ALU_INSTRUCTION_LR35902_NOHL(NAME)
249
250DEFINE_ALU_INSTRUCTION_LR35902(AND);
251DEFINE_ALU_INSTRUCTION_LR35902(XOR);
252DEFINE_ALU_INSTRUCTION_LR35902(OR);
253DEFINE_ALU_INSTRUCTION_LR35902(CP);
254
255static void _LR35902InstructionLDB_Bus(struct LR35902Core*);
256static void _LR35902InstructionLDC_Bus(struct LR35902Core*);
257static void _LR35902InstructionLDD_Bus(struct LR35902Core*);
258static void _LR35902InstructionLDE_Bus(struct LR35902Core*);
259static void _LR35902InstructionLDH_Bus(struct LR35902Core*);
260static void _LR35902InstructionLDL_Bus(struct LR35902Core*);
261static void _LR35902InstructionLDHL_Bus(struct LR35902Core*);
262static void _LR35902InstructionLDA_Bus(struct LR35902Core*);
263
264#define DEFINE_ADD_INSTRUCTION_LR35902(NAME, OPERAND) \
265 DEFINE_INSTRUCTION_LR35902(ADD ## NAME, \
266 int diff = cpu->a + OPERAND; \
267 cpu->f.n = 0; \
268 cpu->f.h = (cpu->a & 0xF) + (OPERAND & 0xF) >= 0x10; \
269 cpu->f.c = diff >= 0x100; \
270 cpu->a = diff; \
271 cpu->f.z = !cpu->a;)
272
273#define DEFINE_ADC_INSTRUCTION_LR35902(NAME, OPERAND) \
274 DEFINE_INSTRUCTION_LR35902(ADC ## NAME, \
275 int diff = cpu->a + OPERAND + cpu->f.c; \
276 cpu->f.n = 0; \
277 cpu->f.h = (cpu->a & 0xF) + (OPERAND & 0xF) + cpu->f.c >= 0x10; \
278 cpu->f.c = diff >= 0x100; \
279 cpu->a = diff; \
280 cpu->f.z = !cpu->a;)
281
282#define DEFINE_SUB_INSTRUCTION_LR35902(NAME, OPERAND) \
283 DEFINE_INSTRUCTION_LR35902(SUB ## NAME, \
284 int diff = cpu->a - OPERAND; \
285 cpu->f.n = 1; \
286 cpu->f.h = (cpu->a & 0xF) - (OPERAND & 0xF) < 0; \
287 cpu->f.c = diff < 0; \
288 cpu->a = diff; \
289 cpu->f.z = !cpu->a;)
290
291#define DEFINE_SBC_INSTRUCTION_LR35902(NAME, OPERAND) \
292 DEFINE_INSTRUCTION_LR35902(SBC ## NAME, \
293 int diff = cpu->a - OPERAND - cpu->f.c; \
294 cpu->f.n = 1; \
295 cpu->f.h = (cpu->a & 0xF) - (OPERAND & 0xF) - cpu->f.c < 0; \
296 cpu->f.c = diff < 0; \
297 cpu->a = diff; \
298 cpu->f.z = !cpu->a;)
299
300DEFINE_ALU_INSTRUCTION_LR35902(LDB_);
301DEFINE_ALU_INSTRUCTION_LR35902(LDC_);
302DEFINE_ALU_INSTRUCTION_LR35902(LDD_);
303DEFINE_ALU_INSTRUCTION_LR35902(LDE_);
304DEFINE_ALU_INSTRUCTION_LR35902(LDH_);
305DEFINE_ALU_INSTRUCTION_LR35902(LDL_);
306DEFINE_ALU_INSTRUCTION_LR35902_NOHL(LDHL_);
307DEFINE_ALU_INSTRUCTION_LR35902(LDA_);
308DEFINE_ALU_INSTRUCTION_LR35902_MEM(LDA_, BC);
309DEFINE_ALU_INSTRUCTION_LR35902_MEM(LDA_, DE);
310DEFINE_ALU_INSTRUCTION_LR35902(ADD);
311DEFINE_ALU_INSTRUCTION_LR35902(ADC);
312DEFINE_ALU_INSTRUCTION_LR35902(SUB);
313DEFINE_ALU_INSTRUCTION_LR35902(SBC);
314
315DEFINE_INSTRUCTION_LR35902(ADDSPFinish,
316 cpu->sp = cpu->index;
317 cpu->executionState = LR35902_CORE_STALL;)
318
319DEFINE_INSTRUCTION_LR35902(ADDSPDelay,
320 int diff = (int8_t) cpu->bus;
321 int sum = cpu->sp + diff;
322 cpu->index = sum;
323 cpu->executionState = LR35902_CORE_OP2;
324 cpu->instruction = _LR35902InstructionADDSPFinish;
325 cpu->f.z = 0;
326 cpu->f.n = 0;
327 cpu->f.c = (diff & 0xFF) + (cpu->sp & 0xFF) >= 0x100;
328 cpu->f.h = (diff & 0xF) + (cpu->sp & 0xF) >= 0x10;)
329
330DEFINE_INSTRUCTION_LR35902(ADDSP,
331 cpu->executionState = LR35902_CORE_READ_PC;
332 cpu->instruction = _LR35902InstructionADDSPDelay;)
333
334DEFINE_INSTRUCTION_LR35902(LDBCDelay, \
335 cpu->c = cpu->bus; \
336 cpu->executionState = LR35902_CORE_READ_PC; \
337 cpu->instruction = _LR35902InstructionLDB_Bus;)
338
339DEFINE_INSTRUCTION_LR35902(LDBC, \
340 cpu->executionState = LR35902_CORE_READ_PC; \
341 cpu->instruction = _LR35902InstructionLDBCDelay;)
342
343DEFINE_INSTRUCTION_LR35902(LDBC_A, \
344 cpu->index = LR35902ReadBC(cpu); \
345 cpu->bus = cpu->a; \
346 cpu->executionState = LR35902_CORE_MEMORY_STORE; \
347 cpu->instruction = _LR35902InstructionNOP;)
348
349DEFINE_INSTRUCTION_LR35902(LDDEDelay, \
350 cpu->e = cpu->bus; \
351 cpu->executionState = LR35902_CORE_READ_PC; \
352 cpu->instruction = _LR35902InstructionLDD_Bus;)
353
354DEFINE_INSTRUCTION_LR35902(LDDE, \
355 cpu->executionState = LR35902_CORE_READ_PC; \
356 cpu->instruction = _LR35902InstructionLDDEDelay;)
357
358DEFINE_INSTRUCTION_LR35902(LDDE_A, \
359 cpu->index = LR35902ReadDE(cpu); \
360 cpu->bus = cpu->a; \
361 cpu->executionState = LR35902_CORE_MEMORY_STORE; \
362 cpu->instruction = _LR35902InstructionNOP;)
363
364DEFINE_INSTRUCTION_LR35902(LDHLDelay, \
365 cpu->l = cpu->bus; \
366 cpu->executionState = LR35902_CORE_READ_PC; \
367 cpu->instruction = _LR35902InstructionLDH_Bus;)
368
369DEFINE_INSTRUCTION_LR35902(LDHL, \
370 cpu->executionState = LR35902_CORE_READ_PC; \
371 cpu->instruction = _LR35902InstructionLDHLDelay;)
372
373DEFINE_INSTRUCTION_LR35902(LDSPFinish, cpu->sp |= cpu->bus << 8;)
374
375DEFINE_INSTRUCTION_LR35902(LDSPDelay, \
376 cpu->sp = cpu->bus; \
377 cpu->executionState = LR35902_CORE_READ_PC; \
378 cpu->instruction = _LR35902InstructionLDSPFinish;)
379
380DEFINE_INSTRUCTION_LR35902(LDSP, \
381 cpu->executionState = LR35902_CORE_READ_PC; \
382 cpu->instruction = _LR35902InstructionLDSPDelay;)
383
384DEFINE_INSTRUCTION_LR35902(LDIHLA, \
385 cpu->index = LR35902ReadHL(cpu); \
386 LR35902WriteHL(cpu, cpu->index + 1); \
387 cpu->bus = cpu->a; \
388 cpu->executionState = LR35902_CORE_MEMORY_STORE; \
389 cpu->instruction = _LR35902InstructionNOP;)
390
391DEFINE_INSTRUCTION_LR35902(LDDHLA, \
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(LDA_IHL, \
399 cpu->index = LR35902ReadHL(cpu); \
400 LR35902WriteHL(cpu, cpu->index + 1); \
401 cpu->executionState = LR35902_CORE_MEMORY_LOAD; \
402 cpu->instruction = _LR35902InstructionLDA_Bus;)
403
404DEFINE_INSTRUCTION_LR35902(LDA_DHL, \
405 cpu->index = LR35902ReadHL(cpu); \
406 LR35902WriteHL(cpu, cpu->index - 1); \
407 cpu->executionState = LR35902_CORE_MEMORY_LOAD; \
408 cpu->instruction = _LR35902InstructionLDA_Bus;)
409
410DEFINE_INSTRUCTION_LR35902(LDIAFinish, \
411 cpu->index |= cpu->bus << 8;
412 cpu->bus = cpu->a; \
413 cpu->executionState = LR35902_CORE_MEMORY_STORE; \
414 cpu->instruction = _LR35902InstructionNOP;)
415
416DEFINE_INSTRUCTION_LR35902(LDIADelay, \
417 cpu->index = cpu->bus;
418 cpu->executionState = LR35902_CORE_READ_PC; \
419 cpu->instruction = _LR35902InstructionLDIAFinish;)
420
421DEFINE_INSTRUCTION_LR35902(LDIA, \
422 cpu->executionState = LR35902_CORE_READ_PC; \
423 cpu->instruction = _LR35902InstructionLDIADelay;)
424
425DEFINE_INSTRUCTION_LR35902(LDAIFinish, \
426 cpu->index |= cpu->bus << 8;
427 cpu->executionState = LR35902_CORE_MEMORY_LOAD; \
428 cpu->instruction = _LR35902InstructionLDA_Bus;)
429
430DEFINE_INSTRUCTION_LR35902(LDAIDelay, \
431 cpu->index = cpu->bus;
432 cpu->executionState = LR35902_CORE_READ_PC; \
433 cpu->instruction = _LR35902InstructionLDAIFinish;)
434
435DEFINE_INSTRUCTION_LR35902(LDAI, \
436 cpu->executionState = LR35902_CORE_READ_PC; \
437 cpu->instruction = _LR35902InstructionLDAIDelay;)
438
439DEFINE_INSTRUCTION_LR35902(LDAIOC, \
440 cpu->index = 0xFF00 | cpu->c; \
441 cpu->executionState = LR35902_CORE_MEMORY_LOAD; \
442 cpu->instruction = _LR35902InstructionLDA_Bus;)
443
444DEFINE_INSTRUCTION_LR35902(LDIOCA, \
445 cpu->index = 0xFF00 | cpu->c; \
446 cpu->bus = cpu->a; \
447 cpu->executionState = LR35902_CORE_MEMORY_STORE; \
448 cpu->instruction = _LR35902InstructionNOP;)
449
450DEFINE_INSTRUCTION_LR35902(LDAIODelay, \
451 cpu->index = 0xFF00 | cpu->bus; \
452 cpu->executionState = LR35902_CORE_MEMORY_LOAD; \
453 cpu->instruction = _LR35902InstructionLDA_Bus;)
454
455DEFINE_INSTRUCTION_LR35902(LDAIO, \
456 cpu->executionState = LR35902_CORE_READ_PC; \
457 cpu->instruction = _LR35902InstructionLDAIODelay;)
458
459DEFINE_INSTRUCTION_LR35902(LDIOADelay, \
460 cpu->index = 0xFF00 | cpu->bus; \
461 cpu->bus = cpu->a; \
462 cpu->executionState = LR35902_CORE_MEMORY_STORE; \
463 cpu->instruction = _LR35902InstructionNOP;)
464
465DEFINE_INSTRUCTION_LR35902(LDIOA, \
466 cpu->executionState = LR35902_CORE_READ_PC; \
467 cpu->instruction = _LR35902InstructionLDIOADelay;)
468
469DEFINE_INSTRUCTION_LR35902(LDISPStoreH,
470 ++cpu->index;
471 cpu->bus = cpu->sp >> 8;
472 cpu->executionState = LR35902_CORE_MEMORY_STORE;
473 cpu->instruction = _LR35902InstructionNOP;)
474
475DEFINE_INSTRUCTION_LR35902(LDISPStoreL,
476 cpu->index |= cpu->bus << 8;
477 cpu->bus = cpu->sp;
478 cpu->executionState = LR35902_CORE_MEMORY_STORE;
479 cpu->instruction = _LR35902InstructionLDISPStoreH;)
480
481DEFINE_INSTRUCTION_LR35902(LDISPReadAddr,
482 cpu->index = cpu->bus;
483 cpu->executionState = LR35902_CORE_READ_PC;
484 cpu->instruction = _LR35902InstructionLDISPStoreL;)
485
486DEFINE_INSTRUCTION_LR35902(LDISP,
487 cpu->executionState = LR35902_CORE_READ_PC;
488 cpu->instruction = _LR35902InstructionLDISPReadAddr;)
489
490#define DEFINE_INCDEC_WIDE_INSTRUCTION_LR35902(REG) \
491 DEFINE_INSTRUCTION_LR35902(INC ## REG, \
492 uint16_t reg = LR35902Read ## REG (cpu); \
493 LR35902Write ## REG (cpu, reg + 1); \
494 cpu->executionState = LR35902_CORE_STALL;) \
495 DEFINE_INSTRUCTION_LR35902(DEC ## REG, \
496 uint16_t reg = LR35902Read ## REG (cpu); \
497 LR35902Write ## REG (cpu, reg - 1); \
498 cpu->executionState = LR35902_CORE_STALL;)
499
500DEFINE_INCDEC_WIDE_INSTRUCTION_LR35902(BC);
501DEFINE_INCDEC_WIDE_INSTRUCTION_LR35902(DE);
502DEFINE_INCDEC_WIDE_INSTRUCTION_LR35902(HL);
503
504#define DEFINE_ADD_HL_INSTRUCTION_LR35902(REG, L, H) \
505 DEFINE_INSTRUCTION_LR35902(ADDHL_ ## REG ## Finish, \
506 int diff = H + cpu->h + cpu->f.c; \
507 cpu->f.n = 0; \
508 cpu->f.h = (H & 0xF) + (cpu->h & 0xF) + cpu->f.c >= 0x10; \
509 cpu->f.c = diff >= 0x100; \
510 cpu->h = diff;) \
511 DEFINE_INSTRUCTION_LR35902(ADDHL_ ## REG, \
512 int diff = L + cpu->l; \
513 cpu->l = diff; \
514 cpu->f.c = diff >= 0x100; \
515 cpu->executionState = LR35902_CORE_OP2; \
516 cpu->instruction = _LR35902InstructionADDHL_ ## REG ## Finish;)
517
518DEFINE_ADD_HL_INSTRUCTION_LR35902(BC, cpu->c, cpu->b);
519DEFINE_ADD_HL_INSTRUCTION_LR35902(DE, cpu->e, cpu->d);
520DEFINE_ADD_HL_INSTRUCTION_LR35902(HL, cpu->l, cpu->h);
521DEFINE_ADD_HL_INSTRUCTION_LR35902(SP, (cpu->sp & 0xFF), (cpu->sp >> 8));
522
523
524#define DEFINE_INC_INSTRUCTION_LR35902(NAME, OPERAND) \
525 DEFINE_INSTRUCTION_LR35902(INC ## NAME, \
526 int diff = OPERAND + 1; \
527 cpu->f.h = (OPERAND & 0xF) == 0xF; \
528 OPERAND = diff; \
529 cpu->f.n = 0; \
530 cpu->f.z = !OPERAND;)
531
532#define DEFINE_DEC_INSTRUCTION_LR35902(NAME, OPERAND) \
533 DEFINE_INSTRUCTION_LR35902(DEC ## NAME, \
534 int diff = OPERAND - 1; \
535 cpu->f.h = (OPERAND & 0xF) == 0x0; \
536 OPERAND = diff; \
537 cpu->f.n = 1; \
538 cpu->f.z = !OPERAND;)
539
540DEFINE_ALU_INSTRUCTION_LR35902_NOHL(INC);
541DEFINE_ALU_INSTRUCTION_LR35902_NOHL(DEC);
542
543DEFINE_INSTRUCTION_LR35902(INC_HLDelay,
544 int diff = cpu->bus + 1;
545 cpu->f.n = 0;
546 cpu->f.h = (cpu->bus & 0xF) == 0xF;
547 cpu->bus = diff;
548 cpu->f.z = !cpu->bus;
549 cpu->instruction = _LR35902InstructionNOP;
550 cpu->executionState = LR35902_CORE_MEMORY_STORE;)
551
552DEFINE_INSTRUCTION_LR35902(INC_HL,
553 cpu->index = LR35902ReadHL(cpu);
554 cpu->instruction = _LR35902InstructionINC_HLDelay;
555 cpu->executionState = LR35902_CORE_MEMORY_LOAD;)
556
557DEFINE_INSTRUCTION_LR35902(DEC_HLDelay,
558 int diff = cpu->bus - 1;
559 cpu->f.n = 1;
560 cpu->f.h = (cpu->bus & 0xF) == 0;
561 cpu->bus = diff;
562 cpu->f.z = !cpu->bus;
563 cpu->instruction = _LR35902InstructionNOP;
564 cpu->executionState = LR35902_CORE_MEMORY_STORE;)
565
566DEFINE_INSTRUCTION_LR35902(DEC_HL,
567 cpu->index = LR35902ReadHL(cpu);
568 cpu->instruction = _LR35902InstructionDEC_HLDelay;
569 cpu->executionState = LR35902_CORE_MEMORY_LOAD;)
570
571DEFINE_INSTRUCTION_LR35902(INCSP,
572 ++cpu->sp;
573 cpu->executionState = LR35902_CORE_STALL;)
574
575DEFINE_INSTRUCTION_LR35902(DECSP,
576 --cpu->sp;
577 cpu->executionState = LR35902_CORE_STALL;)
578
579DEFINE_INSTRUCTION_LR35902(SCF,
580 cpu->f.c = 1;
581 cpu->f.h = 0;
582 cpu->f.n = 0;)
583
584DEFINE_INSTRUCTION_LR35902(CCF,
585 cpu->f.c ^= 1;
586 cpu->f.h = 0;
587 cpu->f.n = 0;)
588
589DEFINE_INSTRUCTION_LR35902(CPL_,
590 cpu->a ^= 0xFF;
591 cpu->f.h = 1;
592 cpu->f.n = 1;)
593
594DEFINE_INSTRUCTION_LR35902(DAA,
595 if (cpu->f.n) {
596 if (cpu->f.h) {
597 cpu->a += 0xFA;
598 }
599 if (cpu->f.c) {
600 cpu->a += 0xA0;
601 }
602 } else {
603 int a = cpu->a;
604 if ((cpu->a & 0xF) > 0x9 || cpu->f.h) {
605 a += 0x6;
606 }
607 if ((a & 0x1F0) > 0x90 || cpu->f.c) {
608 a += 0x60;
609 cpu->f.c = 1;
610 } else {
611 cpu->f.c = 0;
612 }
613 cpu->a = a;
614 }
615 cpu->f.h = 0;
616 cpu->f.z = !cpu->a;)
617
618#define DEFINE_POPPUSH_INSTRUCTION_LR35902(REG, HH, H, L) \
619 DEFINE_INSTRUCTION_LR35902(POP ## REG ## Delay, \
620 cpu-> L = cpu->bus; \
621 cpu->f.packed &= 0xF0; \
622 cpu->index = cpu->sp; \
623 ++cpu->sp; \
624 cpu->instruction = _LR35902InstructionLD ## HH ## _Bus; \
625 cpu->executionState = LR35902_CORE_MEMORY_LOAD;) \
626 DEFINE_INSTRUCTION_LR35902(POP ## REG, \
627 cpu->index = cpu->sp; \
628 ++cpu->sp; \
629 cpu->instruction = _LR35902InstructionPOP ## REG ## Delay; \
630 cpu->executionState = LR35902_CORE_MEMORY_LOAD;) \
631 DEFINE_INSTRUCTION_LR35902(PUSH ## REG ## Finish, \
632 cpu->executionState = LR35902_CORE_STALL;) \
633 DEFINE_INSTRUCTION_LR35902(PUSH ## REG ## Delay, \
634 --cpu->sp; \
635 cpu->index = cpu->sp; \
636 cpu->bus = cpu-> L; \
637 cpu->instruction = _LR35902InstructionPUSH ## REG ## Finish; \
638 cpu->executionState = LR35902_CORE_MEMORY_STORE;) \
639 DEFINE_INSTRUCTION_LR35902(PUSH ## REG, \
640 --cpu->sp; \
641 cpu->index = cpu->sp; \
642 cpu->bus = cpu-> H; \
643 cpu->instruction = _LR35902InstructionPUSH ## REG ## Delay; \
644 cpu->executionState = LR35902_CORE_MEMORY_STORE;)
645
646DEFINE_POPPUSH_INSTRUCTION_LR35902(BC, B, b, c);
647DEFINE_POPPUSH_INSTRUCTION_LR35902(DE, D, d, e);
648DEFINE_POPPUSH_INSTRUCTION_LR35902(HL, H, h, l);
649DEFINE_POPPUSH_INSTRUCTION_LR35902(AF, A, a, f.packed);
650
651#define DEFINE_CB_2_INSTRUCTION_LR35902(NAME, WB, BODY) \
652 DEFINE_INSTRUCTION_LR35902(NAME ## B, uint8_t reg = cpu->b; BODY; cpu->b = reg) \
653 DEFINE_INSTRUCTION_LR35902(NAME ## C, uint8_t reg = cpu->c; BODY; cpu->c = reg) \
654 DEFINE_INSTRUCTION_LR35902(NAME ## D, uint8_t reg = cpu->d; BODY; cpu->d = reg) \
655 DEFINE_INSTRUCTION_LR35902(NAME ## E, uint8_t reg = cpu->e; BODY; cpu->e = reg) \
656 DEFINE_INSTRUCTION_LR35902(NAME ## H, uint8_t reg = cpu->h; BODY; cpu->h = reg) \
657 DEFINE_INSTRUCTION_LR35902(NAME ## L, uint8_t reg = cpu->l; BODY; cpu->l = reg) \
658 DEFINE_INSTRUCTION_LR35902(NAME ## HLDelay, \
659 uint8_t reg = cpu->bus; \
660 BODY; \
661 cpu->bus = reg; \
662 cpu->executionState = WB; \
663 cpu->instruction = _LR35902InstructionNOP;) \
664 DEFINE_INSTRUCTION_LR35902(NAME ## HL, \
665 cpu->index = LR35902ReadHL(cpu); \
666 cpu->executionState = LR35902_CORE_MEMORY_LOAD; \
667 cpu->instruction = _LR35902Instruction ## NAME ## HLDelay;) \
668 DEFINE_INSTRUCTION_LR35902(NAME ## A, uint8_t reg = cpu->a; BODY; cpu->a = reg)
669
670#define DEFINE_CB_INSTRUCTION_LR35902(NAME, WB, BODY) \
671 DEFINE_CB_2_INSTRUCTION_LR35902(NAME ## 0, WB, uint8_t bit = 1; BODY) \
672 DEFINE_CB_2_INSTRUCTION_LR35902(NAME ## 1, WB, uint8_t bit = 2; BODY) \
673 DEFINE_CB_2_INSTRUCTION_LR35902(NAME ## 2, WB, uint8_t bit = 4; BODY) \
674 DEFINE_CB_2_INSTRUCTION_LR35902(NAME ## 3, WB, uint8_t bit = 8; BODY) \
675 DEFINE_CB_2_INSTRUCTION_LR35902(NAME ## 4, WB, uint8_t bit = 16; BODY) \
676 DEFINE_CB_2_INSTRUCTION_LR35902(NAME ## 5, WB, uint8_t bit = 32; BODY) \
677 DEFINE_CB_2_INSTRUCTION_LR35902(NAME ## 6, WB, uint8_t bit = 64; BODY) \
678 DEFINE_CB_2_INSTRUCTION_LR35902(NAME ## 7, WB, uint8_t bit = 128; BODY)
679
680DEFINE_CB_INSTRUCTION_LR35902(BIT, LR35902_CORE_STALL, cpu->f.n = 0; cpu->f.h = 1; cpu->f.z = !(reg & bit))
681DEFINE_CB_INSTRUCTION_LR35902(RES, LR35902_CORE_MEMORY_STORE, reg &= ~bit)
682DEFINE_CB_INSTRUCTION_LR35902(SET, LR35902_CORE_MEMORY_STORE, reg |= bit)
683
684#define DEFINE_CB_ALU_INSTRUCTION_LR35902(NAME, BODY) \
685 DEFINE_CB_2_INSTRUCTION_LR35902(NAME, LR35902_CORE_MEMORY_STORE, \
686 BODY; \
687 cpu->f.n = 0; \
688 cpu->f.h = 0; \
689 cpu->f.z = !reg;)
690
691DEFINE_CB_ALU_INSTRUCTION_LR35902(RL, int wide = (reg << 1) | cpu->f.c; reg = wide; cpu->f.c = wide >> 8)
692DEFINE_CB_ALU_INSTRUCTION_LR35902(RLC, reg = (reg << 1) | (reg >> 7); cpu->f.c = reg & 1)
693DEFINE_CB_ALU_INSTRUCTION_LR35902(RR, int low = reg & 1; reg = (reg >> 1) | (cpu->f.c << 7); cpu->f.c = low)
694DEFINE_CB_ALU_INSTRUCTION_LR35902(RRC, int low = reg & 1; reg = (reg >> 1) | (low << 7); cpu->f.c = low)
695DEFINE_CB_ALU_INSTRUCTION_LR35902(SLA, cpu->f.c = reg >> 7; reg <<= 1)
696DEFINE_CB_ALU_INSTRUCTION_LR35902(SRA, cpu->f.c = reg & 1; reg = ((int8_t) reg) >> 1)
697DEFINE_CB_ALU_INSTRUCTION_LR35902(SRL, cpu->f.c = reg & 1; reg >>= 1)
698DEFINE_CB_ALU_INSTRUCTION_LR35902(SWAP, reg = (reg << 4) | (reg >> 4); cpu->f.c = 0)
699
700DEFINE_INSTRUCTION_LR35902(RLA_,
701 int wide = (cpu->a << 1) | cpu->f.c;
702 cpu->a = wide;
703 cpu->f.z = 0;
704 cpu->f.h = 0;
705 cpu->f.n = 0;
706 cpu->f.c = wide >> 8;)
707
708DEFINE_INSTRUCTION_LR35902(RLCA_,
709 cpu->a = (cpu->a << 1) | (cpu->a >> 7);
710 cpu->f.z = 0;
711 cpu->f.h = 0;
712 cpu->f.n = 0;
713 cpu->f.c = cpu->a & 1;)
714
715DEFINE_INSTRUCTION_LR35902(RRA_,
716 int low = cpu->a & 1;
717 cpu->a = (cpu->a >> 1) | (cpu->f.c << 7);
718 cpu->f.z = 0;
719 cpu->f.h = 0;
720 cpu->f.n = 0;
721 cpu->f.c = low;)
722
723DEFINE_INSTRUCTION_LR35902(RRCA_,
724 int low = cpu->a & 1;
725 cpu->a = (cpu->a >> 1) | (low << 7);
726 cpu->f.z = 0;
727 cpu->f.h = 0;
728 cpu->f.n = 0;
729 cpu->f.c = low;)
730
731DEFINE_INSTRUCTION_LR35902(DI, cpu->irqh.setInterrupts(cpu, false));
732DEFINE_INSTRUCTION_LR35902(EI, cpu->irqh.setInterrupts(cpu, true));
733DEFINE_INSTRUCTION_LR35902(HALT, cpu->cycles = cpu->nextEvent);
734
735DEFINE_INSTRUCTION_LR35902(RST00, LR35902RaiseIRQ(cpu, 0x00));
736DEFINE_INSTRUCTION_LR35902(RST08, LR35902RaiseIRQ(cpu, 0x08));
737DEFINE_INSTRUCTION_LR35902(RST10, LR35902RaiseIRQ(cpu, 0x10));
738DEFINE_INSTRUCTION_LR35902(RST18, LR35902RaiseIRQ(cpu, 0x18));
739DEFINE_INSTRUCTION_LR35902(RST20, LR35902RaiseIRQ(cpu, 0x20));
740DEFINE_INSTRUCTION_LR35902(RST28, LR35902RaiseIRQ(cpu, 0x28));
741DEFINE_INSTRUCTION_LR35902(RST30, LR35902RaiseIRQ(cpu, 0x30));
742DEFINE_INSTRUCTION_LR35902(RST38, LR35902RaiseIRQ(cpu, 0x38));
743
744DEFINE_INSTRUCTION_LR35902(STUB, cpu->irqh.hitStub(cpu));
745
746static const LR35902Instruction _lr35902CBInstructionTable[0x100] = {
747 DECLARE_LR35902_CB_EMITTER_BLOCK(_LR35902Instruction)
748};
749
750DEFINE_INSTRUCTION_LR35902(CBDelegate, _lr35902CBInstructionTable[cpu->bus](cpu))
751
752DEFINE_INSTRUCTION_LR35902(CB, \
753 cpu->executionState = LR35902_CORE_READ_PC; \
754 cpu->instruction = _LR35902InstructionCBDelegate;)
755
756const LR35902Instruction _lr35902InstructionTable[0x100] = {
757 DECLARE_LR35902_EMITTER_BLOCK(_LR35902Instruction)
758};