all repos — mgba @ 6d898542c765f4efc4a094c5ebd3f3465c36f417

mGBA Game Boy Advance Emulator

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