all repos — mgba @ 039a64ee62da13d83c09c7f7f017a69358e19c71

mGBA Game Boy Advance Emulator

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};