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