src/sm83/decoder.c (view raw)
1/* Copyright (c) 2013-2017 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 <mgba/internal/sm83/decoder.h>
7
8#include <mgba/internal/sm83/emitter-sm83.h>
9#include <mgba/internal/sm83/sm83.h>
10#include <mgba-util/string.h>
11
12typedef size_t (*SM83Decoder)(uint8_t opcode, struct SM83InstructionInfo* info);
13
14#define DEFINE_DECODER_SM83(NAME, BODY) \
15 static size_t _SM83Decode ## NAME (uint8_t opcode, struct SM83InstructionInfo* info) { \
16 UNUSED(opcode); \
17 info->mnemonic = SM83_MN_RST; \
18 BODY; \
19 return 0; \
20 }
21
22DEFINE_DECODER_SM83(NOP, info->mnemonic = SM83_MN_NOP;)
23
24#define DEFINE_LD_DECODER_SM83_NOHL(NAME) \
25 DEFINE_DECODER_SM83(LD ## NAME ## _A, \
26 info->mnemonic = SM83_MN_LD; \
27 info->op1.reg = SM83_REG_ ## NAME; \
28 info->op2.reg = SM83_REG_A) \
29 DEFINE_DECODER_SM83(LD ## NAME ## _B, \
30 info->mnemonic = SM83_MN_LD; \
31 info->op1.reg = SM83_REG_ ## NAME; \
32 info->op2.reg = SM83_REG_B) \
33 DEFINE_DECODER_SM83(LD ## NAME ## _C, \
34 info->mnemonic = SM83_MN_LD; \
35 info->op1.reg = SM83_REG_ ## NAME; \
36 info->op2.reg = SM83_REG_C) \
37 DEFINE_DECODER_SM83(LD ## NAME ## _D, \
38 info->mnemonic = SM83_MN_LD; \
39 info->op1.reg = SM83_REG_ ## NAME; \
40 info->op2.reg = SM83_REG_D) \
41 DEFINE_DECODER_SM83(LD ## NAME ## _E, \
42 info->mnemonic = SM83_MN_LD; \
43 info->op1.reg = SM83_REG_ ## NAME; \
44 info->op2.reg = SM83_REG_E) \
45 DEFINE_DECODER_SM83(LD ## NAME ## _H, \
46 info->mnemonic = SM83_MN_LD; \
47 info->op1.reg = SM83_REG_ ## NAME; \
48 info->op2.reg = SM83_REG_H) \
49 DEFINE_DECODER_SM83(LD ## NAME ## _L, \
50 info->mnemonic = SM83_MN_LD; \
51 info->op1.reg = SM83_REG_ ## NAME; \
52 info->op2.reg = SM83_REG_L)
53
54#define DEFINE_LD_DECODER_SM83_MEM(NAME, REG) \
55 DEFINE_DECODER_SM83(LD ## NAME ## _ ## REG, info->mnemonic = SM83_MN_LD; \
56 info->op1.reg = SM83_REG_ ## NAME; \
57 info->op2.reg = SM83_REG_ ## REG; \
58 info->op2.flags = SM83_OP_FLAG_MEMORY;)
59
60#define DEFINE_LD_DECODER_SM83_MEM_2(NAME, REG) \
61 DEFINE_DECODER_SM83(LD ## REG ## _ ## NAME, info->mnemonic = SM83_MN_LD; \
62 info->op1.reg = SM83_REG_ ## REG; \
63 info->op1.flags = SM83_OP_FLAG_MEMORY; \
64 info->op2.reg = SM83_REG_ ## NAME;)
65
66#define DEFINE_LD_DECODER_SM83(NAME) \
67 DEFINE_LD_DECODER_SM83_MEM(NAME, HL) \
68 DEFINE_LD_DECODER_SM83_MEM_2(NAME, HL) \
69 DEFINE_DECODER_SM83(LD ## NAME ## _, info->mnemonic = SM83_MN_LD; \
70 info->op1.reg = SM83_REG_ ## NAME; \
71 return 1;) \
72 DEFINE_LD_DECODER_SM83_NOHL(NAME)
73
74#define DEFINE_LD_2_DECODER_SM83(NAME) \
75 DEFINE_DECODER_SM83(LD ## NAME, info->mnemonic = SM83_MN_LD; \
76 info->op1.reg = SM83_REG_ ## NAME; \
77 return 2;)
78
79DEFINE_LD_DECODER_SM83(B);
80DEFINE_LD_DECODER_SM83(C);
81DEFINE_LD_DECODER_SM83(D);
82DEFINE_LD_DECODER_SM83(E);
83DEFINE_LD_DECODER_SM83(H);
84DEFINE_LD_DECODER_SM83(L);
85DEFINE_LD_DECODER_SM83(A);
86DEFINE_LD_DECODER_SM83_MEM(A, BC);
87DEFINE_LD_DECODER_SM83_MEM(A, DE);
88
89DEFINE_LD_2_DECODER_SM83(BC);
90DEFINE_LD_2_DECODER_SM83(DE);
91DEFINE_LD_2_DECODER_SM83(HL);
92DEFINE_LD_2_DECODER_SM83(SP);
93
94DEFINE_DECODER_SM83(LDHL_, \
95 info->mnemonic = SM83_MN_LD; \
96 info->op1.reg = SM83_REG_HL; \
97 info->op1.flags = SM83_OP_FLAG_MEMORY; \
98 return 1;)
99
100DEFINE_DECODER_SM83(LDHL_SP, \
101 info->mnemonic = SM83_MN_LD; \
102 info->op1.reg = SM83_REG_HL; \
103 info->op2.reg = SM83_REG_SP; \
104 return 1;)
105
106DEFINE_DECODER_SM83(LDSP_HL, \
107 info->mnemonic = SM83_MN_LD; \
108 info->op1.reg = SM83_REG_SP; \
109 info->op2.reg = SM83_REG_HL;)
110
111DEFINE_DECODER_SM83(LDAIOC, \
112 info->mnemonic = SM83_MN_LD; \
113 info->op1.reg = SM83_REG_A; \
114 info->op2.reg = SM83_REG_C; \
115 info->op2.immediate = 0xFF00; \
116 info->op2.flags = SM83_OP_FLAG_MEMORY;)
117
118DEFINE_DECODER_SM83(LDIOCA, \
119 info->mnemonic = SM83_MN_LD; \
120 info->op1.reg = SM83_REG_C; \
121 info->op1.immediate = 0xFF00; \
122 info->op1.flags = SM83_OP_FLAG_MEMORY; \
123 info->op2.reg = SM83_REG_A;)
124
125DEFINE_DECODER_SM83(LDAIO, \
126 info->mnemonic = SM83_MN_LD; \
127 info->op1.reg = SM83_REG_A; \
128 info->op2.immediate = 0xFF00; \
129 info->op2.flags = SM83_OP_FLAG_MEMORY; \
130 return 1;)
131
132DEFINE_DECODER_SM83(LDIOA, \
133 info->mnemonic = SM83_MN_LD; \
134 info->op1.immediate = 0xFF00; \
135 info->op1.flags = SM83_OP_FLAG_MEMORY; \
136 info->op2.reg = SM83_REG_A; \
137 return 1;)
138
139#define DEFINE_ALU_DECODER_SM83_NOHL(NAME) \
140 DEFINE_DECODER_SM83(NAME ## A, info->mnemonic = SM83_MN_ ## NAME; info->op1.reg = SM83_REG_A) \
141 DEFINE_DECODER_SM83(NAME ## B, info->mnemonic = SM83_MN_ ## NAME; info->op1.reg = SM83_REG_B) \
142 DEFINE_DECODER_SM83(NAME ## C, info->mnemonic = SM83_MN_ ## NAME; info->op1.reg = SM83_REG_C) \
143 DEFINE_DECODER_SM83(NAME ## D, info->mnemonic = SM83_MN_ ## NAME; info->op1.reg = SM83_REG_D) \
144 DEFINE_DECODER_SM83(NAME ## E, info->mnemonic = SM83_MN_ ## NAME; info->op1.reg = SM83_REG_E) \
145 DEFINE_DECODER_SM83(NAME ## H, info->mnemonic = SM83_MN_ ## NAME; info->op1.reg = SM83_REG_H) \
146 DEFINE_DECODER_SM83(NAME ## L, info->mnemonic = SM83_MN_ ## NAME; info->op1.reg = SM83_REG_L)
147
148#define DEFINE_ALU_DECODER_SM83_MEM(NAME, REG) \
149 DEFINE_DECODER_SM83(NAME ## REG, info->mnemonic = SM83_MN_ ## NAME; \
150 info->op1.reg = SM83_REG_HL; \
151 info->op1.flags = SM83_OP_FLAG_MEMORY;)
152
153#define DEFINE_ALU_DECODER_SM83(NAME) \
154 DEFINE_ALU_DECODER_SM83_MEM(NAME, HL) \
155 DEFINE_DECODER_SM83(NAME, info->mnemonic = SM83_MN_ ## NAME; \
156 info->op1.reg = SM83_REG_A; \
157 info->op1.flags = SM83_OP_FLAG_IMPLICIT; \
158 return 1;) \
159 DEFINE_ALU_DECODER_SM83_NOHL(NAME)
160
161DEFINE_ALU_DECODER_SM83_NOHL(INC);
162DEFINE_ALU_DECODER_SM83_NOHL(DEC);
163DEFINE_ALU_DECODER_SM83(AND);
164DEFINE_ALU_DECODER_SM83(XOR);
165DEFINE_ALU_DECODER_SM83(OR);
166DEFINE_ALU_DECODER_SM83(CP);
167DEFINE_ALU_DECODER_SM83(ADD);
168DEFINE_ALU_DECODER_SM83(ADC);
169DEFINE_ALU_DECODER_SM83(SUB);
170DEFINE_ALU_DECODER_SM83(SBC);
171
172#define DEFINE_ALU_DECODER_SM83_ADD_HL(REG) \
173 DEFINE_DECODER_SM83(ADDHL_ ## REG, info->mnemonic = SM83_MN_ADD; \
174 info->op1.reg = SM83_REG_HL; \
175 info->op2.reg = SM83_REG_ ## REG;)
176
177DEFINE_ALU_DECODER_SM83_ADD_HL(BC)
178DEFINE_ALU_DECODER_SM83_ADD_HL(DE)
179DEFINE_ALU_DECODER_SM83_ADD_HL(HL)
180DEFINE_ALU_DECODER_SM83_ADD_HL(SP)
181
182DEFINE_DECODER_SM83(ADDSP, info->mnemonic = SM83_MN_ADD; \
183 info->op1.reg = SM83_REG_SP; \
184 return 1;)
185
186#define DEFINE_CONDITIONAL_DECODER_SM83(NAME) \
187 DEFINE_ ## NAME ## _INSTRUCTION_SM83(, 0) \
188 DEFINE_ ## NAME ## _INSTRUCTION_SM83(C, SM83_COND_C) \
189 DEFINE_ ## NAME ## _INSTRUCTION_SM83(Z, SM83_COND_Z) \
190 DEFINE_ ## NAME ## _INSTRUCTION_SM83(NC, SM83_COND_NC) \
191 DEFINE_ ## NAME ## _INSTRUCTION_SM83(NZ, SM83_COND_NZ)
192
193#define DEFINE_JP_INSTRUCTION_SM83(CONDITION_NAME, CONDITION) \
194 DEFINE_DECODER_SM83(JP ## CONDITION_NAME, \
195 info->mnemonic = SM83_MN_JP; \
196 info->condition = CONDITION; \
197 return 2;)
198
199#define DEFINE_JR_INSTRUCTION_SM83(CONDITION_NAME, CONDITION) \
200 DEFINE_DECODER_SM83(JR ## CONDITION_NAME, \
201 info->mnemonic = SM83_MN_JR; \
202 info->condition = CONDITION; \
203 info->op1.flags = SM83_OP_FLAG_RELATIVE; \
204 return 1;)
205
206#define DEFINE_CALL_INSTRUCTION_SM83(CONDITION_NAME, CONDITION) \
207 DEFINE_DECODER_SM83(CALL ## CONDITION_NAME, \
208 info->mnemonic = SM83_MN_CALL; \
209 info->condition = CONDITION; \
210 return 2;)
211
212#define DEFINE_RET_INSTRUCTION_SM83(CONDITION_NAME, CONDITION) \
213 DEFINE_DECODER_SM83(RET ## CONDITION_NAME, \
214 info->mnemonic = SM83_MN_RET; \
215 info->condition = CONDITION;)
216
217DEFINE_CONDITIONAL_DECODER_SM83(JP);
218DEFINE_CONDITIONAL_DECODER_SM83(JR);
219DEFINE_CONDITIONAL_DECODER_SM83(CALL);
220DEFINE_CONDITIONAL_DECODER_SM83(RET);
221
222DEFINE_DECODER_SM83(JPHL, \
223 info->mnemonic = SM83_MN_JP; \
224 info->op1.reg = SM83_REG_HL)
225
226DEFINE_DECODER_SM83(RETI, info->mnemonic = SM83_MN_RETI)
227
228DEFINE_DECODER_SM83(LDBC_A, \
229 info->mnemonic = SM83_MN_LD; \
230 info->op1.reg = SM83_REG_BC; \
231 info->op1.flags = SM83_OP_FLAG_MEMORY; \
232 info->op2.reg = SM83_REG_A;)
233
234DEFINE_DECODER_SM83(LDDE_A, \
235 info->mnemonic = SM83_MN_LD; \
236 info->op1.reg = SM83_REG_DE; \
237 info->op1.flags = SM83_OP_FLAG_MEMORY; \
238 info->op2.reg = SM83_REG_A;)
239
240DEFINE_DECODER_SM83(LDIA, \
241 info->mnemonic = SM83_MN_LD; \
242 info->op1.flags = SM83_OP_FLAG_MEMORY; \
243 info->op2.reg = SM83_REG_A; \
244 return 2;)
245
246DEFINE_DECODER_SM83(LDAI, \
247 info->mnemonic = SM83_MN_LD; \
248 info->op1.reg = SM83_REG_A; \
249 info->op2.flags = SM83_OP_FLAG_MEMORY; \
250 return 2;)
251
252DEFINE_DECODER_SM83(LDISP, \
253 info->mnemonic = SM83_MN_LD; \
254 info->op1.flags = SM83_OP_FLAG_MEMORY; \
255 info->op2.reg = SM83_REG_SP; \
256 return 2;)
257
258DEFINE_DECODER_SM83(LDIHLA, \
259 info->mnemonic = SM83_MN_LD; \
260 info->op1.reg = SM83_REG_HL; \
261 info->op1.flags = SM83_OP_FLAG_INCREMENT | SM83_OP_FLAG_MEMORY; \
262 info->op2.reg = SM83_REG_A;)
263
264DEFINE_DECODER_SM83(LDDHLA, \
265 info->mnemonic = SM83_MN_LD; \
266 info->op1.reg = SM83_REG_HL; \
267 info->op1.flags = SM83_OP_FLAG_DECREMENT | SM83_OP_FLAG_MEMORY; \
268 info->op2.reg = SM83_REG_A;)
269
270DEFINE_DECODER_SM83(LDA_IHL, \
271 info->mnemonic = SM83_MN_LD; \
272 info->op1.reg = SM83_REG_A; \
273 info->op2.reg = SM83_REG_HL; \
274 info->op2.flags = SM83_OP_FLAG_INCREMENT | SM83_OP_FLAG_MEMORY;)
275
276DEFINE_DECODER_SM83(LDA_DHL, \
277 info->mnemonic = SM83_MN_LD; \
278 info->op1.reg = SM83_REG_A; \
279 info->op2.reg = SM83_REG_HL; \
280 info->op2.flags = SM83_OP_FLAG_DECREMENT | SM83_OP_FLAG_MEMORY;)
281
282#define DEFINE_INCDEC_WIDE_INSTRUCTION_SM83(REG) \
283 DEFINE_DECODER_SM83(INC ## REG, info->mnemonic = SM83_MN_INC; info->op1.reg = SM83_REG_ ## REG) \
284 DEFINE_DECODER_SM83(DEC ## REG, info->mnemonic = SM83_MN_DEC; info->op1.reg = SM83_REG_ ## REG)
285
286DEFINE_INCDEC_WIDE_INSTRUCTION_SM83(BC);
287DEFINE_INCDEC_WIDE_INSTRUCTION_SM83(DE);
288DEFINE_INCDEC_WIDE_INSTRUCTION_SM83(HL);
289DEFINE_INCDEC_WIDE_INSTRUCTION_SM83(SP);
290
291DEFINE_DECODER_SM83(INC_HL,
292 info->mnemonic = SM83_MN_INC;
293 info->op1.reg = SM83_REG_HL;
294 info->op1.flags = SM83_OP_FLAG_MEMORY;)
295
296DEFINE_DECODER_SM83(DEC_HL,
297 info->mnemonic = SM83_MN_DEC;
298 info->op1.reg = SM83_REG_HL;
299 info->op1.flags = SM83_OP_FLAG_MEMORY;)
300
301DEFINE_DECODER_SM83(SCF, info->mnemonic = SM83_MN_SCF)
302DEFINE_DECODER_SM83(CCF, info->mnemonic = SM83_MN_CCF)
303DEFINE_DECODER_SM83(CPL_, info->mnemonic = SM83_MN_CPL)
304DEFINE_DECODER_SM83(DAA, info->mnemonic = SM83_MN_DAA)
305
306#define DEFINE_POPPUSH_DECODER_SM83(REG) \
307 DEFINE_DECODER_SM83(POP ## REG, \
308 info->mnemonic = SM83_MN_POP; \
309 info->op1.reg = SM83_REG_ ## REG;) \
310 DEFINE_DECODER_SM83(PUSH ## REG, \
311 info->mnemonic = SM83_MN_PUSH; \
312 info->op1.reg = SM83_REG_ ## REG;) \
313
314DEFINE_POPPUSH_DECODER_SM83(BC);
315DEFINE_POPPUSH_DECODER_SM83(DE);
316DEFINE_POPPUSH_DECODER_SM83(HL);
317DEFINE_POPPUSH_DECODER_SM83(AF);
318
319#define DEFINE_CB_OP_DECODER_SM83(NAME, BODY, OP) \
320 DEFINE_DECODER_SM83(NAME ## B, info->OP.reg = SM83_REG_B; BODY) \
321 DEFINE_DECODER_SM83(NAME ## C, info->OP.reg = SM83_REG_C; BODY) \
322 DEFINE_DECODER_SM83(NAME ## D, info->OP.reg = SM83_REG_D; BODY) \
323 DEFINE_DECODER_SM83(NAME ## E, info->OP.reg = SM83_REG_E; BODY) \
324 DEFINE_DECODER_SM83(NAME ## H, info->OP.reg = SM83_REG_H; BODY) \
325 DEFINE_DECODER_SM83(NAME ## L, info->OP.reg = SM83_REG_L; BODY) \
326 DEFINE_DECODER_SM83(NAME ## HL, info->OP.reg = SM83_REG_HL; info->OP.flags = SM83_OP_FLAG_MEMORY; BODY) \
327 DEFINE_DECODER_SM83(NAME ## A, info->OP.reg = SM83_REG_A; BODY)
328
329#define DEFINE_CB_2_DECODER_SM83(NAME, BODY) \
330 DEFINE_CB_OP_DECODER_SM83(NAME, BODY, op2)
331
332#define DEFINE_CB_1_DECODER_SM83(NAME, BODY) \
333 DEFINE_CB_OP_DECODER_SM83(NAME, BODY, op1)
334
335#define DEFINE_CB_DECODER_SM83(NAME, BODY) \
336 DEFINE_CB_2_DECODER_SM83(NAME ## 0, info->op1.immediate = 0; BODY) \
337 DEFINE_CB_2_DECODER_SM83(NAME ## 1, info->op1.immediate = 1; BODY) \
338 DEFINE_CB_2_DECODER_SM83(NAME ## 2, info->op1.immediate = 2; BODY) \
339 DEFINE_CB_2_DECODER_SM83(NAME ## 3, info->op1.immediate = 3; BODY) \
340 DEFINE_CB_2_DECODER_SM83(NAME ## 4, info->op1.immediate = 4; BODY) \
341 DEFINE_CB_2_DECODER_SM83(NAME ## 5, info->op1.immediate = 5; BODY) \
342 DEFINE_CB_2_DECODER_SM83(NAME ## 6, info->op1.immediate = 6; BODY) \
343 DEFINE_CB_2_DECODER_SM83(NAME ## 7, info->op1.immediate = 7; BODY)
344
345DEFINE_CB_DECODER_SM83(BIT, info->mnemonic = SM83_MN_BIT)
346DEFINE_CB_DECODER_SM83(RES, info->mnemonic = SM83_MN_RES)
347DEFINE_CB_DECODER_SM83(SET, info->mnemonic = SM83_MN_SET)
348
349#define DEFINE_CB_X_DECODER_SM83(NAME) \
350 DEFINE_CB_1_DECODER_SM83(NAME, info->mnemonic = SM83_MN_ ## NAME) \
351 DEFINE_DECODER_SM83(NAME ## A_, info->mnemonic = SM83_MN_ ## NAME; \
352 info->op1.flags = SM83_OP_FLAG_IMPLICIT; \
353 info->op1.reg = SM83_REG_A;)
354
355DEFINE_CB_X_DECODER_SM83(RL)
356DEFINE_CB_X_DECODER_SM83(RLC)
357DEFINE_CB_X_DECODER_SM83(RR)
358DEFINE_CB_X_DECODER_SM83(RRC)
359DEFINE_CB_1_DECODER_SM83(SLA, info->mnemonic = SM83_MN_SLA)
360DEFINE_CB_1_DECODER_SM83(SRA, info->mnemonic = SM83_MN_SRA)
361DEFINE_CB_1_DECODER_SM83(SRL, info->mnemonic = SM83_MN_SRL)
362DEFINE_CB_1_DECODER_SM83(SWAP, info->mnemonic = SM83_MN_SWAP)
363
364DEFINE_DECODER_SM83(DI, info->mnemonic = SM83_MN_DI)
365DEFINE_DECODER_SM83(EI, info->mnemonic = SM83_MN_EI)
366DEFINE_DECODER_SM83(HALT, info->mnemonic = SM83_MN_HALT)
367DEFINE_DECODER_SM83(ILL, info->mnemonic = SM83_MN_ILL)
368DEFINE_DECODER_SM83(STOP, info->mnemonic = SM83_MN_STOP; return 1)
369
370#define DEFINE_RST_DECODER_SM83(VEC) \
371 DEFINE_DECODER_SM83(RST ## VEC, info->op1.immediate = 0x ## VEC;)
372
373DEFINE_RST_DECODER_SM83(00);
374DEFINE_RST_DECODER_SM83(08);
375DEFINE_RST_DECODER_SM83(10);
376DEFINE_RST_DECODER_SM83(18);
377DEFINE_RST_DECODER_SM83(20);
378DEFINE_RST_DECODER_SM83(28);
379DEFINE_RST_DECODER_SM83(30);
380DEFINE_RST_DECODER_SM83(38);
381
382DEFINE_DECODER_SM83(CB, return 1)
383
384const SM83Decoder _sm83DecoderTable[0x100] = {
385 DECLARE_SM83_EMITTER_BLOCK(_SM83Decode)
386};
387
388const SM83Decoder _sm83CBDecoderTable[0x100] = {
389 DECLARE_SM83_CB_EMITTER_BLOCK(_SM83Decode)
390};
391
392size_t SM83Decode(uint8_t opcode, struct SM83InstructionInfo* info) {
393 if (info->opcodeSize == sizeof(info->opcode)) {
394 return 0;
395 }
396 info->opcode[info->opcodeSize] = opcode;
397 SM83Decoder decoder;
398 switch (info->opcodeSize) {
399 case 0:
400 decoder = _sm83DecoderTable[opcode];
401 break;
402 case 1:
403 if (info->opcode[0] == 0xCB) {
404 decoder = _sm83CBDecoderTable[opcode];
405 break;
406 }
407 // Fall through
408 case 2:
409 ++info->opcodeSize;
410 if (info->op1.reg) {
411 info->op2.immediate |= opcode << ((info->opcodeSize - 2) * 8);
412 } else {
413 info->op1.immediate |= opcode << ((info->opcodeSize - 2) * 8);
414 }
415 return 0;
416 }
417 ++info->opcodeSize;
418 return decoder(opcode, info);
419}
420
421#define ADVANCE(AMOUNT) \
422 if (AMOUNT >= blen) { \
423 buffer[blen - 1] = '\0'; \
424 return total; \
425 } \
426 total += AMOUNT; \
427 buffer += AMOUNT; \
428 blen -= AMOUNT;
429
430static const char* _sm83Conditions[] = {
431 NULL,
432 "c",
433 "z",
434 "nc",
435 "nz",
436};
437
438static const char* _sm83Registers[] = {
439 "",
440 "b",
441 "c",
442 "d",
443 "e",
444 "h",
445 "l",
446 "a",
447 "f",
448 "bc",
449 "de",
450 "hl",
451 "af",
452 "sp",
453 "pc",
454};
455
456static const char* _sm83MnemonicStrings[] = {
457 "--",
458 "adc",
459 "add",
460 "and",
461 "bit",
462 "call",
463 "ccf",
464 "cp",
465 "cpl",
466 "daa",
467 "dec",
468 "di",
469 "ei",
470 "halt",
471 "inc",
472 "jp",
473 "jr",
474 "ld",
475 "nop",
476 "or",
477 "pop",
478 "push",
479 "res",
480 "ret",
481 "reti",
482 "rl",
483 "rlc",
484 "rr",
485 "rrc",
486 "rst",
487 "sbc",
488 "scf",
489 "set",
490 "sla",
491 "sra",
492 "srl",
493 "stop",
494 "sub",
495 "swap",
496 "xor",
497
498 "ill"
499};
500
501
502static int _decodeOperand(struct SM83Operand op, uint16_t pc, char* buffer, int blen) {
503 int total = 0;
504 if (op.flags & SM83_OP_FLAG_IMPLICIT) {
505 return 0;
506 }
507
508 strlcpy(buffer, " ", blen);
509 ADVANCE(1);
510
511 if (op.flags & SM83_OP_FLAG_MEMORY) {
512 strlcpy(buffer, "[", blen);
513 ADVANCE(1);
514 }
515 if (op.reg) {
516 int written = snprintf(buffer, blen, "%s", _sm83Registers[op.reg]);
517 ADVANCE(written);
518 } else {
519 int written;
520 if (op.flags & SM83_OP_FLAG_RELATIVE) {
521 written = snprintf(buffer, blen, "$%04X", pc + (int8_t) op.immediate);
522 } else {
523 written = snprintf(buffer, blen, "$%02X", op.immediate);
524 }
525 ADVANCE(written);
526 if (op.reg) {
527 strlcpy(buffer, "+", blen);
528 ADVANCE(1);
529 }
530 }
531 if (op.flags & SM83_OP_FLAG_INCREMENT) {
532 strlcpy(buffer, "+", blen);
533 ADVANCE(1);
534 }
535 if (op.flags & SM83_OP_FLAG_DECREMENT) {
536 strlcpy(buffer, "-", blen);
537 ADVANCE(1);
538 }
539 if (op.flags & SM83_OP_FLAG_MEMORY) {
540 strlcpy(buffer, "]", blen);
541 ADVANCE(1);
542 }
543 return total;
544}
545
546int SM83Disassemble(struct SM83InstructionInfo* info, uint16_t pc, char* buffer, int blen) {
547 const char* mnemonic = _sm83MnemonicStrings[info->mnemonic];
548 int written;
549 int total = 0;
550 const char* cond = _sm83Conditions[info->condition];
551
552 written = snprintf(buffer, blen, "%s", mnemonic);
553 ADVANCE(written);
554
555 if (cond) {
556 written = snprintf(buffer, blen, " %s", cond);
557 ADVANCE(written);
558
559 if (info->op1.reg || info->op1.immediate || info->op2.reg || info->op2.immediate) {
560 strlcpy(buffer, ",", blen);
561 ADVANCE(1);
562 }
563 }
564
565 if (info->op1.reg || info->op1.immediate || info->op2.reg || info->op2.immediate) {
566 written = _decodeOperand(info->op1, pc, buffer, blen);
567 ADVANCE(written);
568 }
569
570 if (info->op2.reg || (!info->op1.immediate && info->opcodeSize > 1 && info->opcode[0] != 0xCB)) {
571 if (written) {
572 strlcpy(buffer, ",", blen);
573 ADVANCE(1);
574 }
575 written = _decodeOperand(info->op2, pc, buffer, blen);
576 ADVANCE(written);
577 }
578
579 buffer[blen - 1] = '\0';
580 return total;
581}