Files
gb-emu/src/gb_disas.c
Max Regan c4ded6d077 cpu: get blarg CPU instruction test 6 passing
Its been too long since a checkin, but here's some of the
improvements:

- Support for diffing with other emulators
- Better disassmbed output
- New CPU instructions implemented
- Lots of CPU fixes
2018-08-26 22:57:35 -07:00

433 lines
6.7 KiB
C

/*TODO: This is hacky and has some bugs but whatever*/
#include <stdint.h>
#include <string.h>
#include <stdio.h>
#include <stdlib.h>
#include "gb_disas.h"
static const char *opcodes[256] = {
//0
"NOP",
"LD BC,d16",
"LD (BC),A",
"INC BC",
"INC B",
"DEC B",
"LD B,d8",
"RLCA",
"LD (a16),SP",
"ADD HL,BC",
"LD A,(BC)",
"DEC BC",
"INC C",
"DEC C",
"LD C,d8",
"RRCA",
//1
"STOP",
"LD DE,d16",
"LD (DE),A",
"INC DE",
"INC D",
"DEC D",
"LD D,d8",
"RLA",
"JR r8",
"ADD HL,DE",
"LD A,(DE)",
"DEC DE",
"INC E",
"DEC E",
"LD E,d8",
"RRA",
//2
"JR NZ,r8",
"LD HL,d16",
"LD (HL+),A",
"INC HL",
"INC H",
"DEC H",
"LD H,d8",
"DAA",
"JR Z,r8",
"ADD HL,HL",
"LD A,(HL+)",
"DEC HL",
"INC L",
"DEC L",
"LD L,d8",
"CPL",
//3
"JR NC,r8",
"LD SP,d16",
"LD (HL-),A",
"INC SP",
"INC (HL)",
"DEC (HL)",
"LD (HL),d8",
"SCF",
"JR C,r8",
"ADD HL,SP",
"LD A,(HL-)",
"DEC SP",
"INC A",
"DEC A",
"LD A,d8",
"CCF",
//4
"LD B,B",
"LD B,C",
"LD B,D",
"LD B,E",
"LD B,H",
"LD B,L",
"LD B,(HL)",
"LD B,A",
"LD C,B",
"LD C,C",
"LD C,D",
"LD C,E",
"LD C,H",
"LD C,L",
"LD C,(HL)",
"LD C,A",
//5
"LD D,B",
"LD D,C",
"LD D,D",
"LD D,E",
"LD D,H",
"LD D,L",
"LD D,(HL)",
"LD D,A",
"LD E,B",
"LD E,C",
"LD E,D",
"LD E,E",
"LD E,H",
"LD E,L",
"LD E,(HL)",
"LD E,A",
//6
"LD H,B",
"LD H,C",
"LD H,D",
"LD H,E",
"LD H,H",
"LD H,L",
"LD H,(HL)",
"LD H,A",
"LD L,B",
"LD L,C",
"LD L,D",
"LD L,E",
"LD L,H",
"LD L,L",
"LD L,(HL)",
"LD L,A",
//7
"LD (HL),B",
"LD (HL),C",
"LD (HL),D",
"LD (HL),E",
"LD (HL),H",
"LD (HL),L",
"HALT",
"LD (HL),A",
"LD A,B",
"LD A,C",
"LD A,D",
"LD A,E",
"LD A,H",
"LD A,L",
"LD A,(HL)",
"LD A,A",
//8
"ADD A,B",
"ADD A,C",
"ADD A,D",
"ADD A,E",
"ADD A,H",
"ADD A,L",
"ADD A,(HL)",
"ADD A,A",
"ADC A,B",
"ADC A,C",
"ADC A,D",
"ADC A,E",
"ADC A,H",
"ADC A,L",
"ADC A,(HL)",
"ADC A,A",
//9
"SUB B",
"SUB C",
"SUB D",
"SUB E",
"SUB H",
"SUB L",
"SUB (HL)",
"SUB A",
"SBC A,B",
"SBC A,C",
"SBC A,D",
"SBC A,E",
"SBC A,H",
"SBC A,L",
"SBC A,(HL)",
"SBC A,A",
//10
"AND B",
"AND C",
"AND D",
"AND E",
"AND H",
"AND L",
"AND (HL)",
"AND A",
"XOR B",
"XOR C",
"XOR D",
"XOR E",
"XOR H",
"XOR L",
"XOR (HL)",
"XOR A",
//11
"OR B",
"OR C",
"OR D",
"OR E",
"OR H",
"OR L",
"OR (HL)",
"OR A",
"CP B",
"CP C",
"CP D",
"CP E",
"CP H",
"CP L",
"CP (HL)",
"CP A",
//12
"RET NZ",
"POP BC",
"JP NZ,a16",
"JP a16",
"CALL NZ,a16",
"PUSH BC",
"ADD A,d8",
"RST 00H",
"RET Z",
"RET",
"JP Z,a16",
"PREFIX CB",
"CALL Z,a16",
"CALL a16",
"ADC A,d8",
"RST",
//13
"RET NC",
"POP DE",
"JP NC,a16",
"*UNDEF*",
"CALL NC,a16",
"PUSH DE",
"SUB d8",
"RST 10H",
"RET C",
"RETI",
"JP C,a16",
"UNDEF*",
"CALL C,a16",
"*UNDEF*",
"SBC A,d8",
"RST 18H",
//14
"LDH (a8),A",
"POP HL",
"LD (0xff00 + C),A",
"*UNDEF*",
"*UNDEF*",
"PUSH HL",
"AND d8",
"RST 20H",
"ADD SP,r8",
"JP (HL)",
"LD (a16),A",
"*UNDEF*",
"*UNDEF*",
"*UNDEF*",
"XOR d8",
"RST 28H",
//15
"LDH A,(a8)",
"POP AF",
"LD A,(0xff00 + C)",
"DI",
"*UNDEF*",
"PUSH AF",
"OR d8",
"RST 30H",
"LD HL,SP+r8",
"LD SP,HL",
"LD A,(a16)",
"EI",
"*UNDEF*",
"*UNDEF*",
"CP d8",
"RST 38H"
};
static const char *ioreg[] = {
[0] = "P1",
[1] = "SB",
[2] = "SC",
[4] = "DIV",
[5] = "TIMA",
[6] = "TMA",
[7] = "TAC",
[0x0f] = "IF",
[0x10] = "NR 10",
[0x11] = "NR 11",
[0x12] = "NR 12",
[0x13] = "NR 13",
[0x14] = "NR 14",
[0x16] = "NR 21",
[0x17] = "NR 22",
[0x18] = "NR 23",
[0x19] = "NR 24",
[0x1A] = "NR 30",
[0x1B] = "NR 31",
[0x1C] = "NR 32",
[0x1D] = "NR 33",
[0x1E] = "NR 34",
[0x20] = "NR 41",
[0x21] = "NR 42",
[0x22] = "NR 43",
[0x23] = "NR 44",
[0x24] = "NR 50",
[0x25] = "NR 51",
[0x26] = "NR 52",
[0x30] = "WavePatternRam[0x0]",
[0x31] = "WavePatternRam[0x1]",
[0x32] = "WavePatternRam[0x2]",
[0x33] = "WavePatternRam[0x3]",
[0x34] = "WavePatternRam[0x4]",
[0x35] = "WavePatternRam[0x5]",
[0x36] = "WavePatternRam[0x6]",
[0x37] = "WavePatternRam[0x7]",
[0x38] = "WavePatternRam[0x8]",
[0x39] = "WavePatternRam[0x9]",
[0x3A] = "WavePatternRam[0xA]",
[0x3B] = "WavePatternRam[0xB]",
[0x3C] = "WavePatternRam[0xC]",
[0x3D] = "WavePatternRam[0xD]",
[0x3E] = "WavePatternRam[0xE]",
[0x3F] = "WavePatternRam[0xF]",
[0x40] = "LCDC",
[0x41] = "STAT",
[0x42] = "SCY",
[0x43] = "SCX",
[0x44] = "LC",
[0x45] = "LYC",
[0x46] = "DMA",
[0x47] = "BGP",
[0x48] = "OBP0",
[0x49] = "OBP1",
[0x4A] = "WY",
[0x4B] = "WX",
[0xFF] = "IE",
};
static const char *ioreg_str(uint16_t addr)
{
unsigned int offset;
if (addr > 0xff00) {
offset = addr & 0xff;
if (ioreg[offset] != NULL) {
return ioreg[offset];
}
}
return NULL;
}
const char *gb_byte_to_opcode(uint16_t *addr, gb_byte_fetch_fn fetch, void *opaque)
{
char *buf = malloc(32);
uint8_t inst = fetch(opaque, (*addr)++);
const char *immediate;
uint8_t val;
size_t len;
const char *opcode = opcodes[inst];
/* TODO: DRY this code up a bit */
if (inst == 0xcb) {
/* CB-prefix instruction */
/* TODO: Right now, this does almost nothing */
strncpy(buf, opcode, 32);
(*addr)++;
} else if ((immediate = strstr(opcode, "d8")) != NULL) {
uint8_t val = fetch(opaque, (*addr)++);
len = immediate - opcode;
strncpy(buf, opcode, len);
snprintf(buf + len, 32 - len, "0x%02x", val);
strncat(buf, opcode + len + strlen("d8"), 32);
} else if ((immediate = strstr(opcode, "a8")) != NULL) {
uint16_t val = ((uint16_t)fetch(opaque, (*addr)++)) + 0xff00;
len = immediate - opcode;
strncpy(buf, opcode, len);
if (ioreg_str(val)) {
snprintf(buf + len, 32 - len, "0x%04x=%s", val, ioreg_str(val));
} else {
snprintf(buf + len, 32 - len, "0x%04x", val);
}
strncat(buf, opcode + len + strlen("a8"), 32);
} else if ((immediate = strstr(opcode, "r8")) != NULL) {
int16_t val = fetch(opaque, (*addr)++);
if (val & (1 << 7)) {
val |= 0xFF00;
}
len = immediate - opcode;
strncpy(buf, opcode, len);
snprintf(buf + len, 32 - len, "0x%04x", *addr + val);
strncat(buf, opcode + len + strlen("r8"), 32);
} else if ((immediate = strstr(opcode, "d16")) != NULL) {
uint16_t val = fetch(opaque, (*addr)++);
val |= ((uint16_t) fetch(opaque, (*addr)++)) << 8;
len = immediate - opcode;
strncpy(buf, opcode, len);
if (ioreg_str(val)) {
snprintf(buf + len, 32 - len, "0x%04x=%s", val, ioreg_str(val));
} else {
snprintf(buf + len, 32 - len, "0x%04x", val);
}
strncat(buf, opcode + len + strlen("a16"), 32);
} else if ((immediate = strstr(opcode, "a16")) != NULL) {
uint16_t val = fetch(opaque, (*addr)++);
val |= ((uint16_t) fetch(opaque, (*addr)++)) << 8;
len = immediate - opcode;
strncpy(buf, opcode, len);
snprintf(buf + len, 32 - len, "0x%04x", val);
strncat(buf, opcode + len + strlen("a16"), 32);
} else {
strncpy(buf, opcode, 32);
}
return buf;
}