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_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_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_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_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_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_ALU_INSTRUCTION_LR35902_NOHL(NAME) \
193 DEFINE_ ## NAME ## _INSTRUCTION_LR35902(A, cpu->a); \
194 DEFINE_ ## NAME ## _INSTRUCTION_LR35902(B, cpu->b); \
195 DEFINE_ ## NAME ## _INSTRUCTION_LR35902(C, cpu->c); \
196 DEFINE_ ## NAME ## _INSTRUCTION_LR35902(D, cpu->d); \
197 DEFINE_ ## NAME ## _INSTRUCTION_LR35902(E, cpu->e); \
198 DEFINE_ ## NAME ## _INSTRUCTION_LR35902(H, cpu->h); \
199 DEFINE_ ## NAME ## _INSTRUCTION_LR35902(L, cpu->l);
200
201DEFINE_INSTRUCTION_LR35902(LDHL_Bus, \
202 cpu->index = LR35902ReadHL(cpu); \
203 cpu->executionState = LR35902_CORE_MEMORY_STORE; \
204 cpu->instruction = _LR35902InstructionNOP;)
205
206DEFINE_INSTRUCTION_LR35902(LDHL_, \
207 cpu->executionState = LR35902_CORE_READ_PC; \
208 cpu->instruction = _LR35902InstructionLDHL_Bus;)
209
210#define DEFINE_ALU_INSTRUCTION_LR35902(NAME) \
211 DEFINE_ ## NAME ## _INSTRUCTION_LR35902(Bus, cpu->bus); \
212 DEFINE_INSTRUCTION_LR35902(NAME ## HL, \
213 cpu->executionState = LR35902_CORE_MEMORY_LOAD; \
214 cpu->index = LR35902ReadHL(cpu); \
215 cpu->instruction = _LR35902Instruction ## NAME ## Bus;) \
216 DEFINE_INSTRUCTION_LR35902(NAME, \
217 cpu->executionState = LR35902_CORE_READ_PC; \
218 cpu->instruction = _LR35902Instruction ## NAME ## Bus;) \
219 DEFINE_ALU_INSTRUCTION_LR35902_NOHL(NAME)
220
221DEFINE_ALU_INSTRUCTION_LR35902(AND);
222DEFINE_ALU_INSTRUCTION_LR35902(XOR);
223DEFINE_ALU_INSTRUCTION_LR35902(OR);
224DEFINE_ALU_INSTRUCTION_LR35902(CP);
225
226static void _LR35902InstructionLDB_Bus(struct LR35902Core*);
227static void _LR35902InstructionLDC_Bus(struct LR35902Core*);
228static void _LR35902InstructionLDD_Bus(struct LR35902Core*);
229static void _LR35902InstructionLDE_Bus(struct LR35902Core*);
230static void _LR35902InstructionLDH_Bus(struct LR35902Core*);
231static void _LR35902InstructionLDL_Bus(struct LR35902Core*);
232static void _LR35902InstructionLDHL_Bus(struct LR35902Core*);
233static void _LR35902InstructionLDA_Bus(struct LR35902Core*);
234
235DEFINE_ALU_INSTRUCTION_LR35902(LDB_);
236DEFINE_ALU_INSTRUCTION_LR35902(LDC_);
237DEFINE_ALU_INSTRUCTION_LR35902(LDD_);
238DEFINE_ALU_INSTRUCTION_LR35902(LDE_);
239DEFINE_ALU_INSTRUCTION_LR35902(LDH_);
240DEFINE_ALU_INSTRUCTION_LR35902(LDL_);
241DEFINE_ALU_INSTRUCTION_LR35902_NOHL(LDHL_);
242DEFINE_ALU_INSTRUCTION_LR35902(LDA_);
243
244DEFINE_INSTRUCTION_LR35902(LDBCDelay, \
245 cpu->c = cpu->bus; \
246 cpu->executionState = LR35902_CORE_READ_PC; \
247 cpu->instruction = _LR35902InstructionLDB_Bus;)
248
249DEFINE_INSTRUCTION_LR35902(LDBC, \
250 cpu->executionState = LR35902_CORE_READ_PC; \
251 cpu->instruction = _LR35902InstructionLDBCDelay;)
252
253DEFINE_INSTRUCTION_LR35902(LDBC_A, \
254 cpu->index = LR35902ReadBC(cpu); \
255 cpu->bus = cpu->a; \
256 cpu->executionState = LR35902_CORE_MEMORY_STORE; \
257 cpu->instruction = _LR35902InstructionNOP;)
258
259DEFINE_INSTRUCTION_LR35902(LDDEDelay, \
260 cpu->e = cpu->bus; \
261 cpu->executionState = LR35902_CORE_READ_PC; \
262 cpu->instruction = _LR35902InstructionLDD_Bus;)
263
264DEFINE_INSTRUCTION_LR35902(LDDE, \
265 cpu->executionState = LR35902_CORE_READ_PC; \
266 cpu->instruction = _LR35902InstructionLDDEDelay;)
267
268DEFINE_INSTRUCTION_LR35902(LDDE_A, \
269 cpu->index = LR35902ReadDE(cpu); \
270 cpu->bus = cpu->a; \
271 cpu->executionState = LR35902_CORE_MEMORY_STORE; \
272 cpu->instruction = _LR35902InstructionNOP;)
273
274DEFINE_INSTRUCTION_LR35902(LDHLDelay, \
275 cpu->l = cpu->bus; \
276 cpu->executionState = LR35902_CORE_READ_PC; \
277 cpu->instruction = _LR35902InstructionLDH_Bus;)
278
279DEFINE_INSTRUCTION_LR35902(LDHL, \
280 cpu->executionState = LR35902_CORE_READ_PC; \
281 cpu->instruction = _LR35902InstructionLDHLDelay;)
282
283DEFINE_INSTRUCTION_LR35902(LDSPFinish, cpu->sp |= cpu->bus << 8;)
284
285DEFINE_INSTRUCTION_LR35902(LDSPDelay, \
286 cpu->sp = cpu->bus; \
287 cpu->executionState = LR35902_CORE_READ_PC; \
288 cpu->instruction = _LR35902InstructionLDSPFinish;)
289
290DEFINE_INSTRUCTION_LR35902(LDSP, \
291 cpu->executionState = LR35902_CORE_READ_PC; \
292 cpu->instruction = _LR35902InstructionLDSPDelay;)
293
294DEFINE_INSTRUCTION_LR35902(LDIHLA, \
295 cpu->index = LR35902ReadHL(cpu); \
296 LR35902WriteHL(cpu, cpu->index + 1); \
297 cpu->bus = cpu->a; \
298 cpu->executionState = LR35902_CORE_MEMORY_STORE; \
299 cpu->instruction = _LR35902InstructionNOP;)
300
301DEFINE_INSTRUCTION_LR35902(LDDHLA, \
302 cpu->index = LR35902ReadHL(cpu); \
303 LR35902WriteHL(cpu, cpu->index - 1); \
304 cpu->bus = cpu->a; \
305 cpu->executionState = LR35902_CORE_MEMORY_STORE; \
306 cpu->instruction = _LR35902InstructionNOP;)
307
308DEFINE_INSTRUCTION_LR35902(LDIAFinish, \
309 cpu->index |= cpu->bus << 8;
310 cpu->bus = cpu->a; \
311 cpu->executionState = LR35902_CORE_MEMORY_STORE; \
312 cpu->instruction = _LR35902InstructionNOP;)
313
314DEFINE_INSTRUCTION_LR35902(LDIADelay, \
315 cpu->index = cpu->bus;
316 cpu->executionState = LR35902_CORE_READ_PC; \
317 cpu->instruction = _LR35902InstructionLDIAFinish;)
318
319DEFINE_INSTRUCTION_LR35902(LDIA, \
320 cpu->executionState = LR35902_CORE_READ_PC; \
321 cpu->instruction = _LR35902InstructionLDIADelay;)
322
323DEFINE_INSTRUCTION_LR35902(LDAIFinish, \
324 cpu->index |= cpu->bus << 8;
325 cpu->executionState = LR35902_CORE_MEMORY_LOAD; \
326 cpu->instruction = _LR35902InstructionLDA_Bus;)
327
328DEFINE_INSTRUCTION_LR35902(LDAIDelay, \
329 cpu->index = cpu->bus;
330 cpu->executionState = LR35902_CORE_READ_PC; \
331 cpu->instruction = _LR35902InstructionLDAIFinish;)
332
333DEFINE_INSTRUCTION_LR35902(LDAI, \
334 cpu->executionState = LR35902_CORE_READ_PC; \
335 cpu->instruction = _LR35902InstructionLDAIDelay;)
336
337DEFINE_INSTRUCTION_LR35902(LDAIOC, \
338 cpu->index = 0xFF00 | cpu->c; \
339 cpu->executionState = LR35902_CORE_MEMORY_LOAD; \
340 cpu->instruction = _LR35902InstructionLDA_Bus;)
341
342DEFINE_INSTRUCTION_LR35902(LDIOCA, \
343 cpu->index = 0xFF00 | cpu->c; \
344 cpu->bus = cpu->a; \
345 cpu->executionState = LR35902_CORE_MEMORY_STORE; \
346 cpu->instruction = _LR35902InstructionNOP;)
347
348DEFINE_INSTRUCTION_LR35902(LDAIODelay, \
349 cpu->index = 0xFF00 | cpu->bus; \
350 cpu->executionState = LR35902_CORE_MEMORY_LOAD; \
351 cpu->instruction = _LR35902InstructionLDA_Bus;)
352
353DEFINE_INSTRUCTION_LR35902(LDAIO, \
354 cpu->executionState = LR35902_CORE_READ_PC; \
355 cpu->instruction = _LR35902InstructionLDAIODelay;)
356
357DEFINE_INSTRUCTION_LR35902(LDIOADelay, \
358 cpu->index = 0xFF00 | cpu->bus; \
359 cpu->bus = cpu->a; \
360 cpu->executionState = LR35902_CORE_MEMORY_STORE; \
361 cpu->instruction = _LR35902InstructionNOP;)
362
363DEFINE_INSTRUCTION_LR35902(LDIOA, \
364 cpu->executionState = LR35902_CORE_READ_PC; \
365 cpu->instruction = _LR35902InstructionLDIOADelay;)
366
367#define DEFINE_INCDEC_INSTRUCTION_LR35902(REG) \
368 DEFINE_INSTRUCTION_LR35902(INC ## REG, \
369 uint16_t reg = LR35902Read ## REG (cpu); \
370 LR35902Write ## REG (cpu, reg + 1); \
371 /* TODO: Stall properly */ \
372 cpu->cycles += 4;) \
373 DEFINE_INSTRUCTION_LR35902(DEC ## REG, \
374 uint16_t reg = LR35902Read ## REG (cpu); \
375 LR35902Write ## REG (cpu, reg - 1); \
376 /* TODO: Stall properly */ \
377 cpu->cycles += 4;) \
378
379
380DEFINE_INCDEC_INSTRUCTION_LR35902(BC);
381DEFINE_INCDEC_INSTRUCTION_LR35902(DE);
382DEFINE_INCDEC_INSTRUCTION_LR35902(HL);
383
384DEFINE_INSTRUCTION_LR35902(INCSP,
385 ++cpu->sp;
386 // TODO: Stall properly
387 cpu->cycles += 4;)
388
389DEFINE_INSTRUCTION_LR35902(DECSP,
390 --cpu->sp;
391 // TODO: Stall properly
392 cpu->cycles += 4;)
393
394DEFINE_INSTRUCTION_LR35902(DI, cpu->irqh.setInterrupts(cpu, false));
395DEFINE_INSTRUCTION_LR35902(EI, cpu->irqh.setInterrupts(cpu, true));
396
397DEFINE_INSTRUCTION_LR35902(STUB, cpu->irqh.hitStub(cpu));
398
399static const LR35902Instruction _lr35902CBInstructionTable[0x100] = {
400 DECLARE_LR35902_CB_EMITTER_BLOCK(_LR35902Instruction)
401};
402
403DEFINE_INSTRUCTION_LR35902(CBDelegate, _lr35902CBInstructionTable[cpu->bus](cpu))
404
405DEFINE_INSTRUCTION_LR35902(CB, \
406 cpu->executionState = LR35902_CORE_READ_PC; \
407 cpu->instruction = _LR35902InstructionCBDelegate;)
408
409const LR35902Instruction _lr35902InstructionTable[0x100] = {
410 DECLARE_LR35902_EMITTER_BLOCK(_LR35902Instruction)
411};