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