all repos — mgba @ 3603958e02f2ad89f6c675432254991778161d83

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(JRFinish,
 47	if (cpu->condition) {
 48		cpu->pc += (int8_t) cpu->bus;
 49		cpu->memory.setActiveRegion(cpu, cpu->pc);
 50		cpu->executionState = LR35902_CORE_STALL;
 51	})
 52
 53#define DEFINE_JR_INSTRUCTION_LR35902(CONDITION_NAME, CONDITION) \
 54	DEFINE_INSTRUCTION_LR35902(JR ## CONDITION_NAME, \
 55		cpu->executionState = LR35902_CORE_READ_PC; \
 56		cpu->instruction = _LR35902InstructionJRFinish; \
 57		cpu->condition = CONDITION;)
 58
 59DEFINE_CONDITIONAL_INSTRUCTION_LR35902(JR);
 60
 61DEFINE_INSTRUCTION_LR35902(CALLFinish,
 62	if (cpu->condition) {
 63		cpu->pc = (cpu->bus << 8) | cpu->index;
 64		cpu->memory.setActiveRegion(cpu, cpu->pc);
 65		cpu->executionState = LR35902_CORE_STALL;
 66	})
 67
 68DEFINE_INSTRUCTION_LR35902(CALLUpdatePC,
 69	cpu->executionState = LR35902_CORE_READ_PC;
 70	cpu->index = cpu->bus;
 71	cpu->instruction = _LR35902InstructionCALLFinish;)
 72
 73DEFINE_INSTRUCTION_LR35902(CALLUpdateSPL,
 74	cpu->executionState = LR35902_CORE_READ_PC; \
 75	cpu->instruction = _LR35902InstructionCALLUpdatePC;)
 76
 77DEFINE_INSTRUCTION_LR35902(CALLUpdateSPH,
 78	cpu->index = cpu->sp + 1;
 79	cpu->bus = (cpu->pc + 2) >> 8;
 80	cpu->executionState = LR35902_CORE_MEMORY_STORE;
 81	cpu->instruction = _LR35902InstructionCALLUpdateSPL;)
 82
 83#define DEFINE_CALL_INSTRUCTION_LR35902(CONDITION_NAME, CONDITION) \
 84	DEFINE_INSTRUCTION_LR35902(CALL ## CONDITION_NAME, \
 85		cpu->condition = CONDITION; \
 86		if (CONDITION) { \
 87			cpu->sp -= 2; /* TODO: Atomic incrementing? */ \
 88			cpu->index = cpu->sp; \
 89			cpu->bus = cpu->pc + 2; \
 90			cpu->executionState = LR35902_CORE_MEMORY_STORE; \
 91			cpu->instruction = _LR35902InstructionCALLUpdateSPH; \
 92		} else { \
 93			cpu->executionState = LR35902_CORE_READ_PC; \
 94			cpu->instruction = _LR35902InstructionCALLUpdatePC; \
 95		})
 96
 97DEFINE_CONDITIONAL_INSTRUCTION_LR35902(CALL)
 98
 99DEFINE_INSTRUCTION_LR35902(RETUpdateSPL,
100	cpu->pc |= cpu->bus << 8;
101	cpu->sp += 2;  /* TODO: Atomic incrementing? */
102	cpu->memory.setActiveRegion(cpu, cpu->pc);
103	cpu->executionState = LR35902_CORE_STALL;)
104
105DEFINE_INSTRUCTION_LR35902(RETUpdateSPH,
106	if (cpu->condition) {
107		cpu->index = cpu->sp + 1;
108		cpu->pc = cpu->bus;
109		cpu->executionState = LR35902_CORE_MEMORY_LOAD;
110		cpu->instruction = _LR35902InstructionRETUpdateSPL;
111	})
112
113#define DEFINE_RET_INSTRUCTION_LR35902(CONDITION_NAME, CONDITION) \
114	DEFINE_INSTRUCTION_LR35902(RET ## CONDITION_NAME, \
115		cpu->condition = CONDITION; \
116		cpu->index = cpu->sp; \
117		cpu->executionState = LR35902_CORE_MEMORY_LOAD; \
118		cpu->instruction = _LR35902InstructionRETUpdateSPH;)
119
120DEFINE_CONDITIONAL_INSTRUCTION_LR35902(RET)
121
122#define DEFINE_AND_INSTRUCTION_LR35902(NAME, OPERAND) \
123	DEFINE_INSTRUCTION_LR35902(AND ## NAME, \
124		cpu->a &= OPERAND; \
125		cpu->f.z = !cpu->a; \
126		cpu->f.n = 0; \
127		cpu->f.c = 0; \
128		cpu->f.h = 1;)
129
130#define DEFINE_XOR_INSTRUCTION_LR35902(NAME, OPERAND) \
131	DEFINE_INSTRUCTION_LR35902(XOR ## NAME, \
132		cpu->a ^= OPERAND; \
133		cpu->f.z = !cpu->a; \
134		cpu->f.n = 0; \
135		cpu->f.c = 0; \
136		cpu->f.h = 0;)
137
138#define DEFINE_OR_INSTRUCTION_LR35902(NAME, OPERAND) \
139	DEFINE_INSTRUCTION_LR35902(OR ## NAME, \
140		cpu->a |= OPERAND; \
141		cpu->f.z = !cpu->a; \
142		cpu->f.n = 0; \
143		cpu->f.c = 0; \
144		cpu->f.h = 0;)
145
146#define DEFINE_CP_INSTRUCTION_LR35902(NAME, OPERAND) \
147	DEFINE_INSTRUCTION_LR35902(CP ## NAME, \
148		int diff = cpu->a - OPERAND; \
149		cpu->f.n = 1; \
150		cpu->f.z = !diff; \
151		cpu->f.c = diff < 0; \
152		/* TODO: Find explanation of H flag */)
153
154#define DEFINE_LDB__INSTRUCTION_LR35902(NAME, OPERAND) \
155	DEFINE_INSTRUCTION_LR35902(LDB_ ## NAME, \
156		cpu->b = OPERAND;)
157
158#define DEFINE_LDC__INSTRUCTION_LR35902(NAME, OPERAND) \
159	DEFINE_INSTRUCTION_LR35902(LDC_ ## NAME, \
160		cpu->c = OPERAND;)
161
162#define DEFINE_LDD__INSTRUCTION_LR35902(NAME, OPERAND) \
163	DEFINE_INSTRUCTION_LR35902(LDD_ ## NAME, \
164		cpu->d = OPERAND;)
165
166#define DEFINE_LDE__INSTRUCTION_LR35902(NAME, OPERAND) \
167	DEFINE_INSTRUCTION_LR35902(LDE_ ## NAME, \
168		cpu->e = OPERAND;)
169
170#define DEFINE_LDH__INSTRUCTION_LR35902(NAME, OPERAND) \
171	DEFINE_INSTRUCTION_LR35902(LDH_ ## NAME, \
172		cpu->h = OPERAND;)
173
174#define DEFINE_LDL__INSTRUCTION_LR35902(NAME, OPERAND) \
175	DEFINE_INSTRUCTION_LR35902(LDL_ ## NAME, \
176		cpu->l = OPERAND;)
177
178#define DEFINE_LDHL__INSTRUCTION_LR35902(NAME, OPERAND) \
179	DEFINE_INSTRUCTION_LR35902(LDHL_ ## NAME, \
180		cpu->bus = OPERAND; \
181		cpu->executionState = LR35902_CORE_MEMORY_STORE; \
182		cpu->instruction = _LR35902InstructionLDHL_Bus;)
183
184#define DEFINE_LDA__INSTRUCTION_LR35902(NAME, OPERAND) \
185	DEFINE_INSTRUCTION_LR35902(LDA_ ## NAME, \
186		cpu->a = OPERAND;)
187
188#define DEFINE_ALU_INSTRUCTION_LR35902_NOHL(NAME) \
189	DEFINE_ ## NAME ## _INSTRUCTION_LR35902(A, cpu->a); \
190	DEFINE_ ## NAME ## _INSTRUCTION_LR35902(B, cpu->b); \
191	DEFINE_ ## NAME ## _INSTRUCTION_LR35902(C, cpu->c); \
192	DEFINE_ ## NAME ## _INSTRUCTION_LR35902(D, cpu->d); \
193	DEFINE_ ## NAME ## _INSTRUCTION_LR35902(E, cpu->e); \
194	DEFINE_ ## NAME ## _INSTRUCTION_LR35902(H, cpu->h); \
195	DEFINE_ ## NAME ## _INSTRUCTION_LR35902(L, cpu->l);
196
197DEFINE_INSTRUCTION_LR35902(LDHL_Bus, \
198	cpu->index = LR35902ReadHL(cpu); \
199	cpu->executionState = LR35902_CORE_MEMORY_STORE; \
200	cpu->instruction = _LR35902InstructionNOP;)
201
202DEFINE_INSTRUCTION_LR35902(LDHL_, \
203	cpu->executionState = LR35902_CORE_READ_PC; \
204	cpu->instruction = _LR35902InstructionLDHL_Bus;)
205
206#define DEFINE_ALU_INSTRUCTION_LR35902(NAME) \
207	DEFINE_ ## NAME ## _INSTRUCTION_LR35902(Bus, cpu->bus); \
208	DEFINE_INSTRUCTION_LR35902(NAME ## HL, \
209		cpu->executionState = LR35902_CORE_MEMORY_LOAD; \
210		cpu->index = LR35902ReadHL(cpu); \
211		cpu->instruction = _LR35902Instruction ## NAME ## Bus;) \
212	DEFINE_INSTRUCTION_LR35902(NAME, \
213		cpu->executionState = LR35902_CORE_READ_PC; \
214		cpu->instruction = _LR35902Instruction ## NAME ## Bus;) \
215	DEFINE_ALU_INSTRUCTION_LR35902_NOHL(NAME)
216
217DEFINE_ALU_INSTRUCTION_LR35902(AND);
218DEFINE_ALU_INSTRUCTION_LR35902(XOR);
219DEFINE_ALU_INSTRUCTION_LR35902(OR);
220DEFINE_ALU_INSTRUCTION_LR35902(CP);
221
222static void _LR35902InstructionLDB_Bus(struct LR35902Core*);
223static void _LR35902InstructionLDC_Bus(struct LR35902Core*);
224static void _LR35902InstructionLDD_Bus(struct LR35902Core*);
225static void _LR35902InstructionLDE_Bus(struct LR35902Core*);
226static void _LR35902InstructionLDH_Bus(struct LR35902Core*);
227static void _LR35902InstructionLDL_Bus(struct LR35902Core*);
228static void _LR35902InstructionLDHL_Bus(struct LR35902Core*);
229static void _LR35902InstructionLDA_Bus(struct LR35902Core*);
230
231DEFINE_ALU_INSTRUCTION_LR35902(LDB_);
232DEFINE_ALU_INSTRUCTION_LR35902(LDC_);
233DEFINE_ALU_INSTRUCTION_LR35902(LDD_);
234DEFINE_ALU_INSTRUCTION_LR35902(LDE_);
235DEFINE_ALU_INSTRUCTION_LR35902(LDH_);
236DEFINE_ALU_INSTRUCTION_LR35902(LDL_);
237DEFINE_ALU_INSTRUCTION_LR35902_NOHL(LDHL_);
238DEFINE_ALU_INSTRUCTION_LR35902(LDA_);
239
240DEFINE_INSTRUCTION_LR35902(LDBCDelay, \
241	cpu->c = cpu->bus; \
242	cpu->executionState = LR35902_CORE_READ_PC; \
243	cpu->instruction = _LR35902InstructionLDB_Bus;)
244
245DEFINE_INSTRUCTION_LR35902(LDBC, \
246	cpu->executionState = LR35902_CORE_READ_PC; \
247	cpu->instruction = _LR35902InstructionLDBCDelay;)
248
249DEFINE_INSTRUCTION_LR35902(LDBC_A, \
250	cpu->index = LR35902ReadBC(cpu); \
251	cpu->bus = cpu->a; \
252	cpu->executionState = LR35902_CORE_MEMORY_STORE; \
253	cpu->instruction = _LR35902InstructionNOP;)
254
255DEFINE_INSTRUCTION_LR35902(LDDEDelay, \
256	cpu->e = cpu->bus; \
257	cpu->executionState = LR35902_CORE_READ_PC; \
258	cpu->instruction = _LR35902InstructionLDD_Bus;)
259
260DEFINE_INSTRUCTION_LR35902(LDDE, \
261	cpu->executionState = LR35902_CORE_READ_PC; \
262	cpu->instruction = _LR35902InstructionLDDEDelay;)
263
264DEFINE_INSTRUCTION_LR35902(LDDE_A, \
265	cpu->index = LR35902ReadDE(cpu); \
266	cpu->bus = cpu->a; \
267	cpu->executionState = LR35902_CORE_MEMORY_STORE; \
268	cpu->instruction = _LR35902InstructionNOP;)
269
270DEFINE_INSTRUCTION_LR35902(LDHLDelay, \
271	cpu->l = cpu->bus; \
272	cpu->executionState = LR35902_CORE_READ_PC; \
273	cpu->instruction = _LR35902InstructionLDH_Bus;)
274
275DEFINE_INSTRUCTION_LR35902(LDHL, \
276	cpu->executionState = LR35902_CORE_READ_PC; \
277	cpu->instruction = _LR35902InstructionLDHLDelay;)
278
279DEFINE_INSTRUCTION_LR35902(LDSPFinish, cpu->sp |= cpu->bus << 8;)
280
281DEFINE_INSTRUCTION_LR35902(LDSPDelay, \
282	cpu->sp = cpu->bus; \
283	cpu->executionState = LR35902_CORE_READ_PC; \
284	cpu->instruction = _LR35902InstructionLDSPFinish;)
285
286DEFINE_INSTRUCTION_LR35902(LDSP, \
287	cpu->executionState = LR35902_CORE_READ_PC; \
288	cpu->instruction = _LR35902InstructionLDSPDelay;)
289
290DEFINE_INSTRUCTION_LR35902(LDIHLA, \
291	cpu->index = LR35902ReadHL(cpu); \
292	LR35902WriteHL(cpu, cpu->index + 1); \
293	cpu->bus = cpu->a; \
294	cpu->executionState = LR35902_CORE_MEMORY_STORE; \
295	cpu->instruction = _LR35902InstructionNOP;)
296
297DEFINE_INSTRUCTION_LR35902(LDDHLA, \
298	cpu->index = LR35902ReadHL(cpu); \
299	LR35902WriteHL(cpu, cpu->index - 1); \
300	cpu->bus = cpu->a; \
301	cpu->executionState = LR35902_CORE_MEMORY_STORE; \
302	cpu->instruction = _LR35902InstructionNOP;)
303
304DEFINE_INSTRUCTION_LR35902(LDIAFinish, \
305	cpu->index |= cpu->bus << 8;
306	cpu->bus = cpu->a; \
307	cpu->executionState = LR35902_CORE_MEMORY_STORE; \
308	cpu->instruction = _LR35902InstructionNOP;)
309
310DEFINE_INSTRUCTION_LR35902(LDIADelay, \
311	cpu->index = cpu->bus;
312	cpu->executionState = LR35902_CORE_READ_PC; \
313	cpu->instruction = _LR35902InstructionLDIAFinish;)
314
315DEFINE_INSTRUCTION_LR35902(LDIA, \
316	cpu->executionState = LR35902_CORE_READ_PC; \
317	cpu->instruction = _LR35902InstructionLDIADelay;)
318
319DEFINE_INSTRUCTION_LR35902(LDAIFinish, \
320	cpu->index |= cpu->bus << 8;
321	cpu->executionState = LR35902_CORE_MEMORY_LOAD; \
322	cpu->instruction = _LR35902InstructionLDA_Bus;)
323
324DEFINE_INSTRUCTION_LR35902(LDAIDelay, \
325	cpu->index = cpu->bus;
326	cpu->executionState = LR35902_CORE_READ_PC; \
327	cpu->instruction = _LR35902InstructionLDAIFinish;)
328
329DEFINE_INSTRUCTION_LR35902(LDAI, \
330	cpu->executionState = LR35902_CORE_READ_PC; \
331	cpu->instruction = _LR35902InstructionLDAIDelay;)
332
333DEFINE_INSTRUCTION_LR35902(LDAIOC, \
334	cpu->index = 0xFF00 | cpu->c; \
335	cpu->executionState = LR35902_CORE_MEMORY_LOAD; \
336	cpu->instruction = _LR35902InstructionLDA_Bus;)
337
338DEFINE_INSTRUCTION_LR35902(LDIOCA, \
339	cpu->index = 0xFF00 | cpu->c; \
340	cpu->bus = cpu->a; \
341	cpu->executionState = LR35902_CORE_MEMORY_STORE; \
342	cpu->instruction = _LR35902InstructionNOP;)
343
344DEFINE_INSTRUCTION_LR35902(LDAIODelay, \
345	cpu->index = 0xFF00 | cpu->bus; \
346	cpu->executionState = LR35902_CORE_MEMORY_LOAD; \
347	cpu->instruction = _LR35902InstructionLDA_Bus;)
348
349DEFINE_INSTRUCTION_LR35902(LDAIO, \
350	cpu->executionState = LR35902_CORE_READ_PC; \
351	cpu->instruction = _LR35902InstructionLDAIODelay;)
352
353DEFINE_INSTRUCTION_LR35902(LDIOADelay, \
354	cpu->index = 0xFF00 | cpu->bus; \
355	cpu->bus = cpu->a; \
356	cpu->executionState = LR35902_CORE_MEMORY_STORE; \
357	cpu->instruction = _LR35902InstructionNOP;)
358
359DEFINE_INSTRUCTION_LR35902(LDIOA, \
360	cpu->executionState = LR35902_CORE_READ_PC; \
361	cpu->instruction = _LR35902InstructionLDIOADelay;)
362
363#define DEFINE_INCDEC_INSTRUCTION_LR35902(REG) \
364	DEFINE_INSTRUCTION_LR35902(INC ## REG, \
365		uint16_t reg = LR35902Read ## REG (cpu); \
366		LR35902Write ## REG (cpu, reg + 1); \
367		cpu->executionState = LR35902_CORE_STALL;) \
368	DEFINE_INSTRUCTION_LR35902(DEC ## REG, \
369		uint16_t reg = LR35902Read ## REG (cpu); \
370		LR35902Write ## REG (cpu, reg - 1); \
371		cpu->executionState = LR35902_CORE_STALL;)
372
373DEFINE_INCDEC_INSTRUCTION_LR35902(BC);
374DEFINE_INCDEC_INSTRUCTION_LR35902(DE);
375DEFINE_INCDEC_INSTRUCTION_LR35902(HL);
376
377DEFINE_INSTRUCTION_LR35902(INCSP,
378	++cpu->sp;
379	cpu->executionState = LR35902_CORE_STALL;)
380
381DEFINE_INSTRUCTION_LR35902(DECSP,
382	--cpu->sp;
383	cpu->executionState = LR35902_CORE_STALL;)
384
385
386#define DEFINE_POPPUSH_INSTRUCTION_LR35902(REG, HH, H, L) \
387	DEFINE_INSTRUCTION_LR35902(POP ## REG ## Delay, \
388		cpu-> L = cpu->bus; \
389		cpu->index = cpu->sp; \
390		++cpu->sp; \
391		cpu->instruction = _LR35902InstructionLD ## HH ## _Bus; \
392		cpu->executionState = LR35902_CORE_MEMORY_LOAD;) \
393	DEFINE_INSTRUCTION_LR35902(POP ## REG, \
394		cpu->index = cpu->sp; \
395		++cpu->sp; \
396		cpu->instruction = _LR35902InstructionPOP ## REG ## Delay; \
397		cpu->executionState = LR35902_CORE_MEMORY_LOAD;) \
398	DEFINE_INSTRUCTION_LR35902(PUSH ## REG ## Finish, \
399		cpu->instruction = _LR35902InstructionNOP; \
400		cpu->executionState = LR35902_CORE_STALL;) \
401	DEFINE_INSTRUCTION_LR35902(PUSH ## REG ## Delay, \
402		--cpu->sp; \
403		cpu->index = cpu->sp; \
404		cpu->bus = cpu-> L; \
405		cpu->instruction = _LR35902InstructionPUSH ## REG ## Finish; \
406		cpu->executionState = LR35902_CORE_MEMORY_STORE;) \
407	DEFINE_INSTRUCTION_LR35902(PUSH ## REG, \
408		--cpu->sp; \
409		cpu->index = cpu->sp; \
410		cpu->bus = cpu-> H; \
411		cpu->instruction = _LR35902InstructionPUSH ## REG ## Delay; \
412		cpu->executionState = LR35902_CORE_MEMORY_STORE;)
413
414DEFINE_POPPUSH_INSTRUCTION_LR35902(BC, B, b, c);
415DEFINE_POPPUSH_INSTRUCTION_LR35902(DE, D, d, e);
416DEFINE_POPPUSH_INSTRUCTION_LR35902(HL, H, h, l);
417DEFINE_POPPUSH_INSTRUCTION_LR35902(AF, A, a, f.packed);
418
419DEFINE_INSTRUCTION_LR35902(DI, cpu->irqh.setInterrupts(cpu, false));
420DEFINE_INSTRUCTION_LR35902(EI, cpu->irqh.setInterrupts(cpu, true));
421
422DEFINE_INSTRUCTION_LR35902(STUB, cpu->irqh.hitStub(cpu));
423
424static const LR35902Instruction _lr35902CBInstructionTable[0x100] = {
425	DECLARE_LR35902_CB_EMITTER_BLOCK(_LR35902Instruction)
426};
427
428DEFINE_INSTRUCTION_LR35902(CBDelegate, _lr35902CBInstructionTable[cpu->bus](cpu))
429
430DEFINE_INSTRUCTION_LR35902(CB, \
431	cpu->executionState = LR35902_CORE_READ_PC; \
432	cpu->instruction = _LR35902InstructionCBDelegate;)
433
434const LR35902Instruction _lr35902InstructionTable[0x100] = {
435	DECLARE_LR35902_EMITTER_BLOCK(_LR35902Instruction)
436};