/* radare - LGPL - Copyright 2013-2022 - condret */

#define GB_8BIT	1
#define	GB_16BIT 2
#define ARG_8 4
#define	ARG_16 8
#define GB_IO 16 //	Most io (Joypad, Sound, Screen ...)

typedef struct {
	const char *name;
	const int type;
} gb_opcode;

static const char *cb_ops[] = {
	"rlc", "rrc", "rl", "rr", "sla", "sra", "swap", "srl",
	"bit 0,", "bit 1,", "bit 2,", "bit 3,", "bit 4,", "bit 5,", "bit 6,", "bit 7,",
	"res 0,", "res 1,", "res 2,", "res 3,", "res 4,", "res 5,", "res 6,", "res 7,",
	"set 0,", "set 1,", "set 2,", "set 3,", "set 4,", "set 5,", "set 6,", "set 7,"
};

static const char *cb_regs[]= { "b", "c", "d", "e", "h", "l", "[hl]", "a" };

static gb_opcode gb_op[] = {
	{ "nop", GB_8BIT }, //0x00
	{ "ld bc, 0x%04x", GB_8BIT + ARG_16},
	{ "ld [bc], a", GB_8BIT },
	{ "inc bc", GB_8BIT },
	{ "inc b", GB_8BIT },
	{ "dec b", GB_8BIT },
	{ "ld b, 0x%02x", GB_8BIT + ARG_8 },
	{ "rlca", GB_8BIT },
	{ "ld [0x%04x], sp", GB_8BIT + ARG_16},		//word or byte?
	{ "add hl, bc", GB_8BIT },
	{ "ld a, [bc]", GB_8BIT },
	{ "dec bc", GB_8BIT },
	{ "inc c", GB_8BIT },
	{ "dec c", GB_8BIT },
	{ "ld c, 0x%02x", GB_8BIT + ARG_8 },
	{ "rrca", GB_8BIT },
	{ "stop", GB_8BIT },			//0x10
	{ "ld de, 0x%04x"	,GB_8BIT+ARG_16},
	{ "ld [de], a"		,GB_8BIT },
	{ "inc de", GB_8BIT },
	{ "inc d", GB_8BIT },
	{ "dec d", GB_8BIT },
	{ "ld d, 0x%02x"		,GB_8BIT+ARG_8 },
	{ "rla", GB_8BIT },
	{ "jr 0x%02x", GB_8BIT+ARG_8 },		//signed
	{ "add hl, de"		,GB_8BIT },
	{ "ld a, [de]"		,GB_8BIT },
	{ "dec de", GB_8BIT },
	{ "inc e", GB_8BIT },
	{ "dec e", GB_8BIT },
	{ "ld e, 0x%02x"		,GB_8BIT+ARG_8 },
	{ "rra", GB_8BIT },

	{ "jr nZ, 0x%02x"	,GB_8BIT+ARG_8 },		//0x20 //signed
	{ "ld hl, 0x%04x"	,GB_8BIT+ARG_16},
	{ "ldi [hl], a"		,GB_8BIT },
	{ "inc hl", GB_8BIT },
	{ "inc h", GB_8BIT },
	{ "dec h", GB_8BIT },
	{ "ld h, 0x%02x"		,GB_8BIT+ARG_8 },
	{ "daa", GB_8BIT },
	{ "jr Z, 0x%02x"		,GB_8BIT+ARG_8 },		//signed
	{ "add hl, hl"		,GB_8BIT },
	{ "ldi a, [hl]"		,GB_8BIT },
	{ "dec hl", GB_8BIT },
	{ "inc l", GB_8BIT },
	{ "dec l", GB_8BIT },
	{ "ld l, 0x%02x"		,GB_8BIT+ARG_8 },
	{ "cpl", GB_8BIT },

	{ "jr nC, 0x%02x"	,GB_8BIT+ARG_8 },		//0x30 //signed
	{ "ld sp, 0x%04x"	,GB_8BIT+ARG_16},
	{ "ldd [hl], a"		,GB_8BIT },
	{ "inc sp", GB_8BIT },
	{ "inc [hl]", GB_8BIT },
	{ "dec [hl]", GB_8BIT },
	{ "ld [hl], 0x%02x"	,GB_8BIT+ARG_8 },
	{ "scf", GB_8BIT },
	{ "jr C, 0x%02x"		,GB_8BIT+ARG_8 },		//signed
	{ "add hl, sp"		,GB_8BIT },
	{ "ldd a, [hl]"		,GB_8BIT },
	{ "dec sp", GB_8BIT },
	{ "inc a", GB_8BIT },
	{ "dec a", GB_8BIT },
	{ "ld a, 0x%02x"		,GB_8BIT+ARG_8 },
	{ "ccf", GB_8BIT },

	{ "ld b, b"		,GB_8BIT },			//0x40
	{ "ld b, c"		,GB_8BIT },
	{ "ld b, d"		,GB_8BIT },
	{ "ld b, e"		,GB_8BIT },
	{ "ld b, h"		,GB_8BIT },
	{ "ld b, l"		,GB_8BIT },
	{ "ld b, [hl]"		,GB_8BIT },
	{ "ld b, a"		,GB_8BIT },
	{ "ld c, b"		,GB_8BIT },
	{ "ld c, c"		,GB_8BIT },
	{ "ld c, d"		,GB_8BIT },
	{ "ld c, e"		,GB_8BIT },
	{ "ld c, h"		,GB_8BIT },
	{ "ld c, l"		,GB_8BIT },
	{ "ld c, [hl]"		,GB_8BIT },
	{ "ld c, a"		,GB_8BIT },

	{ "ld d, b"		,GB_8BIT },			//0x50
	{ "ld d, c"		,GB_8BIT },
	{ "ld d, d"		,GB_8BIT },
	{ "ld d, e"		,GB_8BIT },
	{ "ld d, h"		,GB_8BIT },
	{ "ld d, l"		,GB_8BIT },
	{ "ld d, [hl]"		,GB_8BIT },
	{ "ld d, a"		,GB_8BIT },
	{ "ld e, b"		,GB_8BIT },
	{ "ld e, c"		,GB_8BIT },
	{ "ld e, d"		,GB_8BIT },
	{ "ld e, e"		,GB_8BIT },
	{ "ld e, h"		,GB_8BIT },
	{ "ld e, l"		,GB_8BIT },
	{ "ld e, [hl]"		,GB_8BIT },
	{ "ld e, a"		,GB_8BIT },

	{ "ld h, b"		,GB_8BIT }, //0x60
	{ "ld h, c"		,GB_8BIT },
	{ "ld h, d"		,GB_8BIT },
	{ "ld h, e"		,GB_8BIT },
	{ "ld h, h"		,GB_8BIT },
	{ "ld h, l"		,GB_8BIT },
	{ "ld h, [hl]"		,GB_8BIT },
	{ "ld h, a"		,GB_8BIT },
	{ "ld l, b"		,GB_8BIT },
	{ "ld l, c"		,GB_8BIT },
	{ "ld l, d"		,GB_8BIT },
	{ "ld l, e"		,GB_8BIT },
	{ "ld l, h"		,GB_8BIT },
	{ "ld l, l"		,GB_8BIT },
	{ "ld l, [hl]"		,GB_8BIT },
	{ "ld l, a"		,GB_8BIT },

	{ "ld [hl], b"		,GB_8BIT },//0X70
	{ "ld [hl], c"		,GB_8BIT },
	{ "ld [hl], d"		,GB_8BIT },
	{ "ld [hl], e"		,GB_8BIT },
	{ "ld [hl], h"		,GB_8BIT },
	{ "ld [hl], l"		,GB_8BIT },
	{ "halt", GB_8BIT },
	{ "ld [hl], a"		,GB_8BIT },
	{ "ld a, b"		,GB_8BIT },
	{ "ld a, c"		,GB_8BIT },
	{ "ld a, d"		,GB_8BIT },
	{ "ld a, e"		,GB_8BIT },
	{ "ld a, h"		,GB_8BIT },
	{ "ld a, l"		,GB_8BIT },
	{ "ld a, [hl]"		,GB_8BIT },
	{ "ld a, a"		,GB_8BIT },

	{ "add b", GB_8BIT },			//0x80
	{ "add c", GB_8BIT },
	{ "add d", GB_8BIT },
	{ "add e", GB_8BIT },
	{ "add h", GB_8BIT },
	{ "add l", GB_8BIT },
	{ "add [hl]", GB_8BIT },
	{ "add a", GB_8BIT },
	{ "adc b", GB_8BIT },
	{ "adc c", GB_8BIT },
	{ "adc d", GB_8BIT },
	{ "adc e", GB_8BIT },
	{ "adc h", GB_8BIT },
	{ "adc l", GB_8BIT },
	{ "adc [hl]", GB_8BIT },
	{ "adc a", GB_8BIT },

	{ "sub b", GB_8BIT },			//0x90
	{ "sub c", GB_8BIT },
	{ "sub d", GB_8BIT },
	{ "sub e", GB_8BIT },
	{ "sub h", GB_8BIT },
	{ "sub l", GB_8BIT },
	{ "sub [hl]", GB_8BIT },
	{ "sub a", GB_8BIT },
	{ "sbc b", GB_8BIT },
	{ "sbc c", GB_8BIT },
	{ "sbc d", GB_8BIT },
	{ "sbc e", GB_8BIT },
	{ "sbc h", GB_8BIT },
	{ "sbc l", GB_8BIT },
	{ "sbc [hl]", GB_8BIT },
	{ "sbc a", GB_8BIT },

	{ "and b", GB_8BIT },			//0xa0
	{ "and c", GB_8BIT },
	{ "and d", GB_8BIT },
	{ "and e", GB_8BIT },
	{ "and h", GB_8BIT },
	{ "and l", GB_8BIT },
	{ "and [hl]", GB_8BIT },
	{ "and a", GB_8BIT },
	{ "xor b", GB_8BIT },
	{ "xor c", GB_8BIT },
	{ "xor d", GB_8BIT },
	{ "xor e", GB_8BIT },
	{ "xor h", GB_8BIT },
	{ "xor l", GB_8BIT },
	{ "xor [hl]", GB_8BIT },
	{ "xor a", GB_8BIT },

	{ "or b", GB_8BIT },			//0xb0
	{ "or c", GB_8BIT },
	{ "or d", GB_8BIT },
	{ "or e", GB_8BIT },
	{ "or h", GB_8BIT },
	{ "or l", GB_8BIT },
	{ "or [hl]", GB_8BIT },
	{ "or a", GB_8BIT },
	{ "cp b", GB_8BIT },
	{ "cp c", GB_8BIT },
	{ "cp d", GB_8BIT },
	{ "cp e", GB_8BIT },
	{ "cp h", GB_8BIT },
	{ "cp l", GB_8BIT },
	{ "cp [hl]", GB_8BIT },
	{ "cp a", GB_8BIT },

	{ "ret nZ", GB_8BIT },			//0xc0
	{ "pop bc", GB_8BIT },
	{ "jp nZ, 0x%04x", GB_8BIT+ARG_16},
	{ "jp 0x%04x", GB_8BIT+ARG_16},
	{ "call nZ, 0x%04x", GB_8BIT+ARG_16},
	{ "push bc", GB_8BIT },
	{ "add 0x%02x", GB_8BIT+ARG_8 },
	{ "rst 0", GB_8BIT },
	{ "ret Z", GB_8BIT },
	{ "ret", GB_8BIT },
	{ "jp Z, 0x%04x", GB_8BIT+ARG_16},
	{ "", GB_16BIT },
	{ "call Z, 0x%04x"	,GB_8BIT+ARG_16},
	{ "call 0x%04x", GB_8BIT+ARG_16},
	{ "adc 0x%02x", GB_8BIT+ARG_8 },
	{ "rst 8", GB_8BIT },

	{ "ret nC", GB_8BIT },			//0xd0
	{ "pop de", GB_8BIT },
	{ "jp nC, 0x%04x"	,GB_8BIT+ARG_16},
	{ "invalid", GB_8BIT },
	{ "call nC, 0x%04x"	,GB_8BIT+ARG_16},
	{ "push de", GB_8BIT },
	{ "sub 0x%02x", GB_8BIT+ARG_8 },
	{ "rst 16", GB_8BIT },
	{ "ret C", GB_8BIT },
	{ "reti", GB_8BIT },
	{ "jp C, 0x%04x"		,GB_8BIT+ARG_16},
	{ "invalid", GB_8BIT },
	{ "call C, 0x%04x"	,GB_8BIT+ARG_16},
	{ "invalid", GB_8BIT },
	{ "sbc 0x%02x", GB_8BIT+ARG_8 },
	{ "rst 24", GB_8BIT },

	{ "ld [%s], a"		,GB_8BIT+ARG_8+GB_IO },	//0xe0
	{ "pop hl", GB_8BIT },
	{ "ld [0xff00 + c], a"	,GB_8BIT },
	{ "invalid", GB_8BIT },
	{ "invalid", GB_8BIT },
	{ "push hl", GB_8BIT },
	{ "and 0x%02x", GB_8BIT+ARG_8 },
	{ "rst 32", GB_8BIT },
	{ "add sp, 0x%02x"	,GB_8BIT+ARG_8 },		//signed
	{ "jp hl", GB_8BIT },
	{ "ld [0x%04x], a"	,GB_8BIT+ARG_16},		//signed
	{ "invalid", GB_8BIT },
	{ "invalid", GB_8BIT },
	{ "invalid", GB_8BIT },
	{ "xor 0x%02x", GB_8BIT+ARG_8 },
	{ "rst 40", GB_8BIT },

	{ "ld a, [%s]"	,GB_8BIT+ARG_8+GB_IO },	//0xf0
	{ "pop af", GB_8BIT },
	{ "ld a, [0xff00 + c]"	,GB_8BIT },
	{ "di", GB_8BIT },
	{ "invalid", GB_8BIT },
	{ "push af", GB_8BIT },
	{ "or 0x%02x", GB_8BIT+ARG_8 },
	{ "rst 48", GB_8BIT },
	{ "ld hl, sp + 0x%02x"	,GB_8BIT+ARG_8 },		//signed
	{ "ld sp, hl", GB_8BIT },
	{ "ld a, [0x%04x]", GB_8BIT+ARG_16},
	{ "ei", GB_8BIT },
	{ "invalid", GB_8BIT },
	{ "invalid", GB_8BIT },
	{ "cp 0x%02x", GB_8BIT+ARG_8 },
	{ "rst 56", GB_8BIT },
};
