annotate src/gb/gbDis.cpp @ 17:75e5bb1e0aa1

going to now integrate the gb src tree since it has no dependencies
author Robert McIntyre <rlm@mit.edu>
date Sat, 03 Mar 2012 11:44:47 -0600
parents f9f4f1b99eed
children
rev   line source
rlm@1 1 #include <cstdio>
rlm@1 2 #include <cstring>
rlm@1 3
rlm@1 4 #include "gbGlobals.h"
rlm@1 5
rlm@1 6 typedef struct
rlm@1 7 {
rlm@1 8 u8 mask;
rlm@1 9 u8 value;
rlm@1 10 char *mnen;
rlm@1 11 } GBOPCODE;
rlm@1 12
rlm@1 13 static char *registers[] =
rlm@1 14 { "B", "C", "D", "E", "H", "L", "(HL)", "A" };
rlm@1 15
rlm@1 16 static char *registers16[] =
rlm@1 17 { "BC", "DE", "HL", "SP", // for some operations
rlm@1 18 "BC", "DE", "HL", "AF" }; // for push/pop
rlm@1 19
rlm@1 20 static char *cond[] =
rlm@1 21 { "NZ", "Z", "NC", "C" };
rlm@1 22
rlm@1 23 static char hexDigits[16] = {
rlm@1 24 '0', '1', '2', '3', '4', '5', '6', '7',
rlm@1 25 '8', '9', 'A', 'B', 'C', 'D', 'E', 'F'
rlm@1 26 };
rlm@1 27
rlm@1 28 static GBOPCODE opcodes[] = {
rlm@1 29 { 0xff, 0x00, "NOP" },
rlm@1 30 { 0xcf, 0x01, "LD %R4,%W" },
rlm@1 31 { 0xff, 0x02, "LD (BC),A" },
rlm@1 32 { 0xcf, 0x03, "INC %R4" },
rlm@1 33 { 0xc7, 0x04, "INC %r3" },
rlm@1 34 { 0xc7, 0x05, "DEC %r3" },
rlm@1 35 { 0xc7, 0x06, "LD %r3,%B" },
rlm@1 36 { 0xff, 0x07, "RLCA" },
rlm@1 37 { 0xff, 0x08, "LD (%W),SP" },
rlm@1 38 { 0xcf, 0x09, "ADD HL,%R4" },
rlm@1 39 { 0xff, 0x0a, "LD A,(BC)" },
rlm@1 40 { 0xcf, 0x0b, "DEC %R4" },
rlm@1 41 { 0xff, 0x0f, "RRCA" },
rlm@1 42 { 0xff, 0x10, "STOP" },
rlm@1 43 { 0xff, 0x12, "LD (DE),A" },
rlm@1 44 { 0xff, 0x17, "RLA" },
rlm@1 45 { 0xff, 0x18, "JR %d" },
rlm@1 46 { 0xff, 0x1a, "LD A,(DE)" },
rlm@1 47 { 0xff, 0x1f, "RRA" },
rlm@1 48 { 0xe7, 0x20, "JR %c3,%d" },
rlm@1 49 { 0xff, 0x22, "LDI (HL),A" },
rlm@1 50 { 0xff, 0x27, "DAA" },
rlm@1 51 { 0xff, 0x2a, "LDI A,(HL)" },
rlm@1 52 { 0xff, 0x2f, "CPL" },
rlm@1 53 { 0xff, 0x32, "LDD (HL),A" },
rlm@1 54 { 0xff, 0x37, "SCF" },
rlm@1 55 { 0xff, 0x3a, "LDD A,(HL)" },
rlm@1 56 { 0xff, 0x3f, "CCF" },
rlm@1 57 { 0xff, 0x76, "HALT" },
rlm@1 58 { 0xc0, 0x40, "LD %r3,%r0" },
rlm@1 59 { 0xf8, 0x80, "ADD A,%r0" },
rlm@1 60 { 0xf8, 0x88, "ADC A,%r0" },
rlm@1 61 { 0xf8, 0x90, "SUB %r0" },
rlm@1 62 { 0xf8, 0x98, "SBC A,%r0" },
rlm@1 63 { 0xf8, 0xa0, "AND %r0" },
rlm@1 64 { 0xf8, 0xa8, "XOR %r0" },
rlm@1 65 { 0xf8, 0xb0, "OR %r0" },
rlm@1 66 { 0xf8, 0xb8, "CP %r0" },
rlm@1 67 { 0xe7, 0xc0, "RET %c3" },
rlm@1 68 { 0xcf, 0xc1, "POP %t4" },
rlm@1 69 { 0xe7, 0xc2, "JP %c3,%W" },
rlm@1 70 { 0xff, 0xc3, "JP %W" },
rlm@1 71 { 0xe7, 0xc4, "CALL %c3,%W" },
rlm@1 72 { 0xcf, 0xc5, "PUSH %t4" },
rlm@1 73 { 0xff, 0xc6, "ADD A,%B" },
rlm@1 74 { 0xc7, 0xc7, "RST %P" },
rlm@1 75 { 0xff, 0xc9, "RET" },
rlm@1 76 { 0xff, 0xcd, "CALL %W" },
rlm@1 77 { 0xff, 0xce, "ADC %B" },
rlm@1 78 { 0xff, 0xd6, "SUB %B" },
rlm@1 79 { 0xff, 0xd9, "RETI" },
rlm@1 80 { 0xff, 0xde, "SBC %B" },
rlm@1 81 { 0xff, 0xe0, "LD (FF%B),A" },
rlm@1 82 { 0xff, 0xe2, "LD (FF00h+C),A" },
rlm@1 83 { 0xff, 0xe6, "AND %B" },
rlm@1 84 { 0xff, 0xe8, "ADD SP,%D" },
rlm@1 85 { 0xff, 0xe9, "LD PC,HL" },
rlm@1 86 { 0xff, 0xea, "LD (%W),A" },
rlm@1 87 { 0xff, 0xee, "XOR %B" },
rlm@1 88 { 0xff, 0xf0, "LD A,(FF%B)" },
rlm@1 89 { 0xff, 0xf2, "LD A,(FF00h+C)" },
rlm@1 90 { 0xff, 0xf3, "DI" },
rlm@1 91 { 0xff, 0xf6, "OR %B" },
rlm@1 92 { 0xff, 0xf8, "LD HL,SP%D" },
rlm@1 93 { 0xff, 0xf9, "LD SP,HL" },
rlm@1 94 { 0xff, 0xfa, "LD A,(%W)" },
rlm@1 95 { 0xff, 0xfb, "EI" },
rlm@1 96 { 0xff, 0xfe, "CP %B" },
rlm@1 97 { 0x00, 0x00, "DB %B" }
rlm@1 98 };
rlm@1 99
rlm@1 100 static GBOPCODE cbOpcodes[] = {
rlm@1 101 { 0xf8, 0x00, "RLC %r0" },
rlm@1 102 { 0xf8, 0x08, "RRC %r0" },
rlm@1 103 { 0xf8, 0x10, "RL %r0" },
rlm@1 104 { 0xf8, 0x18, "RR %r0" },
rlm@1 105 { 0xf8, 0x20, "SLA %r0" },
rlm@1 106 { 0xf8, 0x28, "SRA %r0" },
rlm@1 107 { 0xf8, 0x30, "SWAP %r0" },
rlm@1 108 { 0xf8, 0x38, "SRL %r0" },
rlm@1 109 { 0xc0, 0x40, "BIT %b,%r0" },
rlm@1 110 { 0xc0, 0x80, "RES %b,%r0" },
rlm@1 111 { 0xc0, 0xc0, "SET %b,%r0" },
rlm@1 112 { 0x00, 0x00, "DB CBh,%B" }
rlm@1 113 };
rlm@1 114
rlm@1 115 static char *addHex(char *p, u8 value)
rlm@1 116 {
rlm@1 117 *p++ = hexDigits[value >> 4];
rlm@1 118 *p++ = hexDigits[value & 15];
rlm@1 119 return p;
rlm@1 120 }
rlm@1 121
rlm@1 122 static char *addHex16(char *p, u16 value)
rlm@1 123 {
rlm@1 124 p = addHex(p, value>>8);
rlm@1 125 return addHex(p, value & 255);
rlm@1 126 }
rlm@1 127
rlm@1 128 static char *addStr(char *p, char *s)
rlm@1 129 {
rlm@1 130 while (*s)
rlm@1 131 {
rlm@1 132 *p++ = *s++;
rlm@1 133 }
rlm@1 134 return p;
rlm@1 135 }
rlm@1 136
rlm@1 137 int gbDis(char *buffer, u16 address)
rlm@1 138 {
rlm@1 139 char *p = buffer;
rlm@1 140 int instr = 1;
rlm@1 141 u16 addr = address;
rlm@1 142 sprintf(p, "%04x ", address);
rlm@1 143 p += 12;
rlm@1 144
rlm@1 145 u8 opcode = gbReadMemoryQuick(address);
rlm@1 146 address++;
rlm@1 147 char * mnen;
rlm@1 148 GBOPCODE *op;
rlm@1 149 if (opcode == 0xcb)
rlm@1 150 {
rlm@1 151 opcode = gbReadMemoryQuick(address);
rlm@1 152 address++;
rlm@1 153 instr++;
rlm@1 154 op = cbOpcodes;
rlm@1 155 }
rlm@1 156 else
rlm@1 157 {
rlm@1 158 op = opcodes;
rlm@1 159 }
rlm@1 160 while (op->value != (opcode & op->mask))
rlm@1 161 op++;
rlm@1 162 mnen = op->mnen;
rlm@1 163
rlm@1 164 u8 b0, b1;
rlm@1 165 s8 disp;
rlm@1 166 int shift;
rlm@1 167
rlm@1 168 while (*mnen)
rlm@1 169 {
rlm@1 170 if (*mnen == '%')
rlm@1 171 {
rlm@1 172 mnen++;
rlm@1 173 switch (*mnen++)
rlm@1 174 {
rlm@1 175 case 'W':
rlm@1 176 b0 = gbReadMemoryQuick(address);
rlm@1 177 address++;
rlm@1 178 b1 = gbReadMemoryQuick(address);
rlm@1 179 address++;
rlm@1 180 p = addHex16(p, b0|b1<<8);
rlm@1 181 instr += 2;
rlm@1 182 *p++ = 'h';
rlm@1 183 break;
rlm@1 184 case 'B':
rlm@1 185 p = addHex(p, gbReadMemoryQuick(address));
rlm@1 186 *p++ = 'h';
rlm@1 187 address++;
rlm@1 188 instr++;
rlm@1 189 break;
rlm@1 190 case 'D':
rlm@1 191 disp = gbReadMemoryQuick(address);
rlm@1 192 if (disp >= 0)
rlm@1 193 *p++ = '+';
rlm@1 194 p += sprintf(p, "%d", disp);
rlm@1 195 instr++;
rlm@1 196 break;
rlm@1 197 case 'd':
rlm@1 198 disp = gbReadMemoryQuick(address);
rlm@1 199 address++;
rlm@1 200 p = addHex16(p, address+disp);
rlm@1 201 *p++ = 'h';
rlm@1 202 instr++;
rlm@1 203 break;
rlm@1 204 case 'b':
rlm@1 205 // kind of a hack, but it works :-)
rlm@1 206 *p++ = hexDigits[(opcode >> 3) & 7];
rlm@1 207 break;
rlm@1 208 case 'r':
rlm@1 209 shift = *mnen++ - '0';
rlm@1 210 p = addStr(p, registers[(opcode >> shift) & 7]);
rlm@1 211 break;
rlm@1 212 case 'R':
rlm@1 213 shift = *mnen++ - '0';
rlm@1 214 p = addStr(p, registers16[(opcode >> shift) & 3]);
rlm@1 215 break;
rlm@1 216 case 't':
rlm@1 217 shift = *mnen++ - '0';
rlm@1 218 p = addStr(p, registers16[4+((opcode >> shift) & 3)]);
rlm@1 219 break;
rlm@1 220 case 'P':
rlm@1 221 p = addHex(p, ((opcode >> 3) & 7) * 8);
rlm@1 222 break;
rlm@1 223 case 'c':
rlm@1 224 shift = *mnen++ - '0';
rlm@1 225 p = addStr(p, cond[(opcode >> shift) & 3]);
rlm@1 226 break;
rlm@1 227 }
rlm@1 228 }
rlm@1 229 else
rlm@1 230 *p++ = *mnen++;
rlm@1 231 }
rlm@1 232 for (int i = 0; i < instr; i++)
rlm@1 233 {
rlm@1 234 u16 a = addr + i;
rlm@1 235 addHex(buffer+5+i*2, gbReadMemoryQuick(a));
rlm@1 236 }
rlm@1 237 *p = 0;
rlm@1 238 return instr;
rlm@1 239 }