all repos — mgba @ c3abc16a94a021cb6dc111834d3672ffd2fa9f00

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		// TODO: Stall properly
 31		cpu->cycles += 4;
 32	})
 33
 34DEFINE_INSTRUCTION_LR35902(JPDelay,
 35	cpu->executionState = LR35902_CORE_READ_PC;
 36	cpu->instruction = _LR35902InstructionJPFinish;
 37	cpu->index = cpu->bus;)
 38
 39#define DEFINE_JP_INSTRUCTION_LR35902(CONDITION_NAME, CONDITION) \
 40	DEFINE_INSTRUCTION_LR35902(JP ## CONDITION_NAME, \
 41		cpu->executionState = LR35902_CORE_READ_PC; \
 42		cpu->instruction = _LR35902InstructionJPDelay; \
 43		cpu->condition = CONDITION;)
 44
 45DEFINE_CONDITIONAL_INSTRUCTION_LR35902(JP);
 46
 47DEFINE_INSTRUCTION_LR35902(JRFinish,
 48	if (cpu->condition) {
 49		cpu->pc += (int8_t) cpu->bus;
 50		cpu->memory.setActiveRegion(cpu, cpu->pc);
 51		// TODO: Stall properly
 52		cpu->cycles += 4;
 53	})
 54
 55#define DEFINE_JR_INSTRUCTION_LR35902(CONDITION_NAME, CONDITION) \
 56	DEFINE_INSTRUCTION_LR35902(JR ## CONDITION_NAME, \
 57		cpu->executionState = LR35902_CORE_READ_PC; \
 58		cpu->instruction = _LR35902InstructionJRFinish; \
 59		cpu->condition = CONDITION;)
 60
 61DEFINE_CONDITIONAL_INSTRUCTION_LR35902(JR);
 62
 63DEFINE_INSTRUCTION_LR35902(CALLFinish,
 64	if (cpu->condition) {
 65		cpu->pc = (cpu->bus << 8) | cpu->index;
 66		cpu->memory.setActiveRegion(cpu, cpu->pc);
 67		// TODO: Stall properly
 68		cpu->cycles += 4;
 69	})
 70
 71DEFINE_INSTRUCTION_LR35902(CALLUpdatePC,
 72	cpu->executionState = LR35902_CORE_READ_PC;
 73	cpu->index = cpu->bus;
 74	cpu->instruction = _LR35902InstructionCALLFinish;)
 75
 76DEFINE_INSTRUCTION_LR35902(CALLUpdateSPL,
 77	cpu->executionState = LR35902_CORE_READ_PC; \
 78	cpu->instruction = _LR35902InstructionCALLUpdatePC;)
 79
 80DEFINE_INSTRUCTION_LR35902(CALLUpdateSPH,
 81	cpu->index = cpu->sp + 1;
 82	cpu->bus = (cpu->pc + 2) >> 8;
 83	cpu->executionState = LR35902_CORE_MEMORY_MOVE_INDEX_STORE;
 84	cpu->instruction = _LR35902InstructionCALLUpdateSPL;)
 85
 86#define DEFINE_CALL_INSTRUCTION_LR35902(CONDITION_NAME, CONDITION) \
 87	DEFINE_INSTRUCTION_LR35902(CALL ## CONDITION_NAME, \
 88		cpu->condition = CONDITION; \
 89		if (CONDITION) { \
 90			cpu->sp -= 2; \
 91			cpu->index = cpu->sp; \
 92			cpu->bus = cpu->pc + 2; \
 93			cpu->executionState = LR35902_CORE_MEMORY_MOVE_INDEX_STORE; \
 94			cpu->instruction = _LR35902InstructionCALLUpdateSPH; \
 95		} else { \
 96			cpu->executionState = LR35902_CORE_READ_PC; \
 97			cpu->instruction = _LR35902InstructionCALLUpdatePC; \
 98		})
 99
100DEFINE_CONDITIONAL_INSTRUCTION_LR35902(CALL)
101
102DEFINE_INSTRUCTION_LR35902(RETUpdateSPL,
103	cpu->pc |= cpu->bus << 8;
104	cpu->sp += 2;
105	cpu->memory.setActiveRegion(cpu, cpu->pc);
106	// TODO: Stall properly
107	cpu->cycles += 4;)
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_MOVE_INDEX_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_MOVE_INDEX_LOAD; \
122		cpu->instruction = _LR35902InstructionRETUpdateSPH;)
123
124DEFINE_CONDITIONAL_INSTRUCTION_LR35902(RET)
125
126#define DEFINE_AND_INSTRUCTION_LR35902(NAME, OPERAND) \
127	DEFINE_INSTRUCTION_LR35902(AND ## NAME, \
128		cpu->a &= OPERAND; \
129		cpu->f.z = !cpu->a; \
130		cpu->f.n = 0; \
131		cpu->f.c = 0; \
132		cpu->f.h = 1;)
133
134#define DEFINE_XOR_INSTRUCTION_LR35902(NAME, OPERAND) \
135	DEFINE_INSTRUCTION_LR35902(XOR ## NAME, \
136		cpu->a ^= OPERAND; \
137		cpu->f.z = !cpu->a; \
138		cpu->f.n = 0; \
139		cpu->f.c = 0; \
140		cpu->f.h = 0;)
141
142#define DEFINE_OR_INSTRUCTION_LR35902(NAME, OPERAND) \
143	DEFINE_INSTRUCTION_LR35902(OR ## NAME, \
144		cpu->a |= OPERAND; \
145		cpu->f.z = !cpu->a; \
146		cpu->f.n = 0; \
147		cpu->f.c = 0; \
148		cpu->f.h = 0;)
149
150#define DEFINE_CP_INSTRUCTION_LR35902(NAME, OPERAND) \
151	DEFINE_INSTRUCTION_LR35902(CP ## NAME, \
152		int diff = cpu->a - OPERAND; \
153		cpu->f.n = 1; \
154		cpu->f.z = !diff; \
155		cpu->f.c = diff < 0; \
156		/* TODO: Find explanation of H flag */)
157
158#define DEFINE_LDB__INSTRUCTION_LR35902(NAME, OPERAND) \
159	DEFINE_INSTRUCTION_LR35902(LDB_ ## NAME, \
160		cpu->b = OPERAND;)
161
162#define DEFINE_LDC__INSTRUCTION_LR35902(NAME, OPERAND) \
163	DEFINE_INSTRUCTION_LR35902(LDC_ ## NAME, \
164		cpu->c = OPERAND;)
165
166#define DEFINE_LDD__INSTRUCTION_LR35902(NAME, OPERAND) \
167	DEFINE_INSTRUCTION_LR35902(LDD_ ## NAME, \
168		cpu->d = OPERAND;)
169
170#define DEFINE_LDE__INSTRUCTION_LR35902(NAME, OPERAND) \
171	DEFINE_INSTRUCTION_LR35902(LDE_ ## NAME, \
172		cpu->e = OPERAND;)
173
174#define DEFINE_LDH__INSTRUCTION_LR35902(NAME, OPERAND) \
175	DEFINE_INSTRUCTION_LR35902(LDH_ ## NAME, \
176		cpu->h = OPERAND;)
177
178#define DEFINE_LDL__INSTRUCTION_LR35902(NAME, OPERAND) \
179	DEFINE_INSTRUCTION_LR35902(LDL_ ## NAME, \
180		cpu->l = OPERAND;)
181
182#define DEFINE_LDHL__INSTRUCTION_LR35902(NAME, OPERAND) \
183	DEFINE_INSTRUCTION_LR35902(LDHL_ ## NAME, \
184		cpu->bus = OPERAND; \
185		cpu->executionState = LR35902_CORE_MEMORY_MOVE_INDEX_STORE; \
186		cpu->instruction = _LR35902InstructionLDHL_Bus;)
187
188#define DEFINE_LDA__INSTRUCTION_LR35902(NAME, OPERAND) \
189	DEFINE_INSTRUCTION_LR35902(LDA_ ## NAME, \
190		cpu->a = OPERAND;)
191
192#define DEFINE_LD_INSTRUCTION_LR35902(NAME, OPERAND) \
193	DEFINE_INSTRUCTION_LR35902(LD ## NAME, \
194		cpu->executionState = LR35902_CORE_READ_PC; \
195		cpu->instruction = _LR35902InstructionLD ## NAME ## _Bus;)
196
197#define DEFINE_ALU_INSTRUCTION_LR35902_NOHL(NAME) \
198	DEFINE_ ## NAME ## _INSTRUCTION_LR35902(A, cpu->a); \
199	DEFINE_ ## NAME ## _INSTRUCTION_LR35902(B, cpu->b); \
200	DEFINE_ ## NAME ## _INSTRUCTION_LR35902(C, cpu->c); \
201	DEFINE_ ## NAME ## _INSTRUCTION_LR35902(D, cpu->d); \
202	DEFINE_ ## NAME ## _INSTRUCTION_LR35902(E, cpu->e); \
203	DEFINE_ ## NAME ## _INSTRUCTION_LR35902(H, cpu->h); \
204	DEFINE_ ## NAME ## _INSTRUCTION_LR35902(L, cpu->l);
205
206DEFINE_INSTRUCTION_LR35902(LDHL_Bus, \
207	cpu->index = LR35902ReadHL(cpu); \
208	cpu->executionState = LR35902_CORE_MEMORY_MOVE_INDEX_STORE; \
209	cpu->instruction = _LR35902InstructionNOP;)
210
211DEFINE_INSTRUCTION_LR35902(LDHL, \
212	cpu->executionState = LR35902_CORE_READ_PC; \
213	cpu->instruction = _LR35902InstructionLDHL_Bus;)
214
215#define DEFINE_ALU_INSTRUCTION_LR35902(NAME) \
216	DEFINE_ ## NAME ## _INSTRUCTION_LR35902(Bus, cpu->bus); \
217	DEFINE_INSTRUCTION_LR35902(NAME ## HL, \
218		cpu->executionState = LR35902_CORE_MEMORY_MOVE_INDEX_LOAD; \
219		cpu->index = LR35902ReadHL(cpu); \
220		cpu->instruction = _LR35902Instruction ## NAME ## Bus;) \
221	DEFINE_INSTRUCTION_LR35902(NAME, \
222		cpu->executionState = LR35902_CORE_READ_PC; \
223		cpu->instruction = _LR35902Instruction ## NAME ## Bus;) \
224	DEFINE_ALU_INSTRUCTION_LR35902_NOHL(NAME)
225
226DEFINE_ALU_INSTRUCTION_LR35902(AND);
227DEFINE_ALU_INSTRUCTION_LR35902(XOR);
228DEFINE_ALU_INSTRUCTION_LR35902(OR);
229DEFINE_ALU_INSTRUCTION_LR35902(CP);
230
231static void _LR35902InstructionLDB_Bus(struct LR35902Core*);
232static void _LR35902InstructionLDC_Bus(struct LR35902Core*);
233static void _LR35902InstructionLDD_Bus(struct LR35902Core*);
234static void _LR35902InstructionLDE_Bus(struct LR35902Core*);
235static void _LR35902InstructionLDH_Bus(struct LR35902Core*);
236static void _LR35902InstructionLDL_Bus(struct LR35902Core*);
237static void _LR35902InstructionLDHL_Bus(struct LR35902Core*);
238static void _LR35902InstructionLDA_Bus(struct LR35902Core*);
239
240DEFINE_ALU_INSTRUCTION_LR35902(LDB_);
241DEFINE_ALU_INSTRUCTION_LR35902(LDC_);
242DEFINE_ALU_INSTRUCTION_LR35902(LDD_);
243DEFINE_ALU_INSTRUCTION_LR35902(LDE_);
244DEFINE_ALU_INSTRUCTION_LR35902(LDH_);
245DEFINE_ALU_INSTRUCTION_LR35902(LDL_);
246DEFINE_ALU_INSTRUCTION_LR35902_NOHL(LDHL_);
247DEFINE_ALU_INSTRUCTION_LR35902(LDA_);
248
249DEFINE_INSTRUCTION_LR35902(LDIAFinish, \
250	cpu->index |= cpu->bus << 8;
251	cpu->bus = cpu->a; \
252	cpu->executionState = LR35902_CORE_MEMORY_MOVE_INDEX_STORE; \
253	cpu->instruction = _LR35902InstructionNOP;)
254
255DEFINE_INSTRUCTION_LR35902(LDIADelay, \
256	cpu->index = cpu->bus;
257	cpu->executionState = LR35902_CORE_READ_PC; \
258	cpu->instruction = _LR35902InstructionLDIAFinish;)
259
260DEFINE_INSTRUCTION_LR35902(LDIA, \
261	cpu->executionState = LR35902_CORE_READ_PC; \
262	cpu->instruction = _LR35902InstructionLDIADelay;)
263
264DEFINE_INSTRUCTION_LR35902(LDAIFinish, \
265	cpu->index |= cpu->bus << 8;
266	cpu->executionState = LR35902_CORE_MEMORY_MOVE_INDEX_LOAD; \
267	cpu->instruction = _LR35902InstructionLDA_Bus;)
268
269DEFINE_INSTRUCTION_LR35902(LDAIDelay, \
270	cpu->index = cpu->bus;
271	cpu->executionState = LR35902_CORE_READ_PC; \
272	cpu->instruction = _LR35902InstructionLDAIFinish;)
273
274DEFINE_INSTRUCTION_LR35902(LDAI, \
275	cpu->executionState = LR35902_CORE_READ_PC; \
276	cpu->instruction = _LR35902InstructionLDAIDelay;)
277
278DEFINE_INSTRUCTION_LR35902(LDAIOC, \
279	cpu->index = 0xFF00 | cpu->c; \
280	cpu->executionState = LR35902_CORE_MEMORY_MOVE_INDEX_LOAD; \
281	cpu->instruction = _LR35902InstructionLDA_Bus;)
282
283DEFINE_INSTRUCTION_LR35902(LDIOCA, \
284	cpu->index = 0xFF00 | cpu->c; \
285	cpu->bus = cpu->a; \
286	cpu->executionState = LR35902_CORE_MEMORY_MOVE_INDEX_STORE; \
287	cpu->instruction = _LR35902InstructionNOP;)
288
289DEFINE_INSTRUCTION_LR35902(LDAIODelay, \
290	cpu->index = 0xFF00 | cpu->bus; \
291	cpu->executionState = LR35902_CORE_MEMORY_MOVE_INDEX_LOAD; \
292	cpu->instruction = _LR35902InstructionLDA_Bus;)
293
294DEFINE_INSTRUCTION_LR35902(LDAIO, \
295	cpu->executionState = LR35902_CORE_READ_PC; \
296	cpu->instruction = _LR35902InstructionLDAIODelay;)
297
298DEFINE_INSTRUCTION_LR35902(LDIOADelay, \
299	cpu->index = 0xFF00 | cpu->bus; \
300	cpu->bus = cpu->a; \
301	cpu->executionState = LR35902_CORE_MEMORY_MOVE_INDEX_STORE; \
302	cpu->instruction = _LR35902InstructionNOP;)
303
304DEFINE_INSTRUCTION_LR35902(LDIOA, \
305	cpu->executionState = LR35902_CORE_READ_PC; \
306	cpu->instruction = _LR35902InstructionLDIOADelay;)
307
308DEFINE_INSTRUCTION_LR35902(DI, cpu->irqh.setInterrupts(cpu, false));
309DEFINE_INSTRUCTION_LR35902(EI, cpu->irqh.setInterrupts(cpu, true));
310
311DEFINE_INSTRUCTION_LR35902(STUB, cpu->irqh.hitStub(cpu));
312
313static const LR35902Instruction _lr35902CBInstructionTable[0x100] = {
314	DECLARE_LR35902_CB_EMITTER_BLOCK(_LR35902Instruction)
315};
316
317DEFINE_INSTRUCTION_LR35902(CBDelegate, _lr35902CBInstructionTable[cpu->bus](cpu))
318
319DEFINE_INSTRUCTION_LR35902(CB, \
320	cpu->executionState = LR35902_CORE_READ_PC; \
321	cpu->instruction = _LR35902InstructionCBDelegate;)
322
323const LR35902Instruction _lr35902InstructionTable[0x100] = {
324	DECLARE_LR35902_EMITTER_BLOCK(_LR35902Instruction)
325};