all repos — mgba @ 2f066a979031136e7686ceee91af9e8a2e7cc754

mGBA Game Boy Advance Emulator

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}