all repos — mgba @ fb0555e4fb08c414b59ab7b25c8eeeafbe45dfdd

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