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