all repos — mgba @ 84000ed7fc093021721021735f79f7074bcf54c5

mGBA Game Boy Advance Emulator

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