all repos — mgba @ d13e186f9177519a261b7a74c9a3520607a91f55

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