316 lines
7.9 KiB
C
316 lines
7.9 KiB
C
// SPDX-FileCopyrightText: 2013-2014 condret <condret@runas-racer.com>
|
|
// SPDX-License-Identifier: LGPL-3.0-only
|
|
|
|
#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 enum {
|
|
GB_REG_A,
|
|
GB_REG_B,
|
|
GB_REG_C,
|
|
GB_REG_D,
|
|
GB_REG_E,
|
|
GB_REG_H,
|
|
GB_REG_L,
|
|
GB_REG_AF,
|
|
GB_REG_BC,
|
|
GB_REG_DE,
|
|
GB_REG_HL,
|
|
GB_REG_SP
|
|
} gb_reg;
|
|
|
|
typedef enum {
|
|
GB_FLAG_Z,
|
|
GB_FLAG_N,
|
|
GB_FLAG_H,
|
|
GB_FLAG_C
|
|
} gb_flag;
|
|
|
|
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 },
|
|
};
|