diff --git a/higan/emulator/emulator.hpp b/higan/emulator/emulator.hpp index 09a4a082..d1a2855a 100644 --- a/higan/emulator/emulator.hpp +++ b/higan/emulator/emulator.hpp @@ -12,7 +12,7 @@ using namespace nall; namespace Emulator { static const string Name = "higan"; - static const string Version = "103.25"; + static const string Version = "103.26"; static const string Author = "byuu"; static const string License = "GPLv3"; static const string Website = "http://byuu.org/"; diff --git a/higan/processor/lr35902-legacy/disassembler.cpp b/higan/processor/lr35902-legacy/disassembler.cpp index c8293530..c59f998e 100644 --- a/higan/processor/lr35902-legacy/disassembler.cpp +++ b/higan/processor/lr35902-legacy/disassembler.cpp @@ -1,556 +1,533 @@ auto LR35902::disassemble(uint16 pc) -> string { - char output[80]; - memory::fill(output, sizeof output, ' '); - output[79] = 0; - - string opcode = disassembleOpcode(pc); - string registers = { + return { + hex(pc, 4L), " ", + pad(disassembleOpcode(pc), -16, ' '), " ", " AF:", hex(r[AF], 4L), " BC:", hex(r[BC], 4L), " DE:", hex(r[DE], 4L), " HL:", hex(r[HL], 4L), " SP:", hex(r[SP], 4L) }; - - memory::copy(output + 0, hex(pc, 4L).data(), 4); - memory::copy(output + 6, opcode.data(), opcode.length()); - memory::copy(output + 23, registers.data(), registers.length()); - output[63] = 0; - return output; } auto LR35902::disassembleOpcode(uint16 pc) -> string { - uint8 opcode = readDebugger(pc); - uint8 p0 = readDebugger(pc + 1); - uint8 p1 = readDebugger(pc + 2); - uint8 p2 = readDebugger(pc + 3); + auto opcode = readDebugger(pc); + auto lo = readDebugger(pc + 1); + auto hi = readDebugger(pc + 2); + auto word = hi << 8 | lo << 0; switch(opcode) { - case 0x00: return { "nop" }; - case 0x01: return { "ld bc,$", hex(p1, 2L), hex(p0, 2L) }; - case 0x02: return { "ld (bc),a" }; - case 0x03: return { "inc bc" }; - case 0x04: return { "inc b" }; - case 0x05: return { "dec b" }; - case 0x06: return { "ld b,$", hex(p0, 2L) }; - case 0x07: return { "rlc a" }; - case 0x08: return { "ld ($", hex(p1, 2L), hex(p0, 2L), "),sp" }; - case 0x09: return { "add hl,bc" }; - case 0x0a: return { "ld a,(bc)" }; - case 0x0b: return { "dec bc" }; - case 0x0c: return { "inc c" }; - case 0x0d: return { "dec c" }; - case 0x0e: return { "ld c,$", hex(p0, 2L) }; - case 0x0f: return { "rrc a" }; - case 0x10: return { "stop" }; - case 0x11: return { "ld de,$", hex(p1, 2L), hex(p0, 2L) }; - case 0x12: return { "ld (de),a" }; - case 0x13: return { "inc de" }; - case 0x14: return { "inc d" }; - case 0x15: return { "dec d" }; - case 0x16: return { "ld d,$", hex(p0, 2L) }; - case 0x17: return { "rl a" }; - case 0x18: return { "jr $", hex(r[PC] + 2 + (int8)p0, 4L) }; - case 0x19: return { "add hl,de" }; - case 0x1a: return { "ld a,(de)" }; - case 0x1b: return { "dec de" }; - case 0x1c: return { "inc e" }; - case 0x1d: return { "dec e" }; - case 0x1e: return { "ld e,$", hex(p0, 2L) }; - case 0x1f: return { "rr a" }; - case 0x20: return { "jr nz,$", hex(r[PC] + 2 + (int8)p0, 4L) }; - case 0x21: return { "ld hl,$", hex(p1, 2L), hex(p0, 2L) }; - case 0x22: return { "ldi (hl),a" }; - case 0x23: return { "inc hl" }; - case 0x24: return { "inc h" }; - case 0x25: return { "dec h" }; - case 0x26: return { "ld h,$", hex(p0, 2L) }; - case 0x27: return { "daa" }; - case 0x28: return { "jr z,$", hex(r[PC] + 2 + (int8)p0, 4L) }; - case 0x29: return { "add hl,hl" }; - case 0x2a: return { "ldi a,(hl)" }; - case 0x2b: return { "dec hl" }; - case 0x2c: return { "inc l" }; - case 0x2d: return { "dec l" }; - case 0x2e: return { "ld l,$", hex(p0, 2L) }; - case 0x2f: return { "cpl" }; - case 0x30: return { "jr nc,$", hex(r[PC] + 2 + (int8)p0, 4L) }; - case 0x31: return { "ld sp,$", hex(p1, 2L), hex(p0, 2L) }; - case 0x32: return { "ldd (hl),a" }; - case 0x33: return { "inc sp" }; - case 0x34: return { "inc (hl)" }; - case 0x35: return { "dec (hl)" }; - case 0x36: return { "ld (hl),$", hex(p0, 2L) }; - case 0x37: return { "scf" }; - case 0x38: return { "jr c,$", hex(r[PC] + 2 + (int8)p0, 4L) }; - case 0x39: return { "add hl,sp" }; - case 0x3a: return { "ldd a,(hl)" }; - case 0x3b: return { "dec sp" }; - case 0x3c: return { "inc a" }; - case 0x3d: return { "dec a" }; - case 0x3e: return { "ld a,$", hex(p0, 2L) }; - case 0x3f: return { "ccf" }; - case 0x40: return { "ld b,b" }; - case 0x41: return { "ld b,c" }; - case 0x42: return { "ld b,d" }; - case 0x43: return { "ld b,e" }; - case 0x44: return { "ld b,h" }; - case 0x45: return { "ld b,l" }; - case 0x46: return { "ld b,(hl)" }; - case 0x47: return { "ld b,a" }; - case 0x48: return { "ld c,b" }; - case 0x49: return { "ld c,c" }; - case 0x4a: return { "ld c,d" }; - case 0x4b: return { "ld c,e" }; - case 0x4c: return { "ld c,h" }; - case 0x4d: return { "ld c,l" }; - case 0x4e: return { "ld c,(hl)" }; - case 0x4f: return { "ld c,a" }; - case 0x50: return { "ld d,b" }; - case 0x51: return { "ld d,c" }; - case 0x52: return { "ld d,d" }; - case 0x53: return { "ld d,e" }; - case 0x54: return { "ld d,h" }; - case 0x55: return { "ld d,l" }; - case 0x56: return { "ld d,(hl)" }; - case 0x57: return { "ld d,a" }; - case 0x58: return { "ld e,b" }; - case 0x59: return { "ld e,c" }; - case 0x5a: return { "ld e,d" }; - case 0x5b: return { "ld e,e" }; - case 0x5c: return { "ld e,h" }; - case 0x5d: return { "ld e,l" }; - case 0x5e: return { "ld e,(hl)" }; - case 0x5f: return { "ld e,a" }; - case 0x60: return { "ld h,b" }; - case 0x61: return { "ld h,c" }; - case 0x62: return { "ld h,d" }; - case 0x63: return { "ld h,e" }; - case 0x64: return { "ld h,h" }; - case 0x65: return { "ld h,l" }; - case 0x66: return { "ld h,(hl)" }; - case 0x67: return { "ld h,a" }; - case 0x68: return { "ld l,b" }; - case 0x69: return { "ld l,c" }; - case 0x6a: return { "ld l,d" }; - case 0x6b: return { "ld l,e" }; - case 0x6c: return { "ld l,h" }; - case 0x6d: return { "ld l,l" }; - case 0x6e: return { "ld l,(hl)" }; - case 0x6f: return { "ld l,a" }; - case 0x70: return { "ld (hl),b" }; - case 0x71: return { "ld (hl),c" }; - case 0x72: return { "ld (hl),d" }; - case 0x73: return { "ld (hl),e" }; - case 0x74: return { "ld (hl),h" }; - case 0x75: return { "ld (hl),l" }; - case 0x76: return { "halt" }; - case 0x77: return { "ld (hl),a" }; - case 0x78: return { "ld a,b" }; - case 0x79: return { "ld a,c" }; - case 0x7a: return { "ld a,d" }; - case 0x7b: return { "ld a,e" }; - case 0x7c: return { "ld a,h" }; - case 0x7d: return { "ld a,l" }; - case 0x7e: return { "ld a,(hl)" }; - case 0x7f: return { "ld a,a" }; - case 0x80: return { "add a,b" }; - case 0x81: return { "add a,c" }; - case 0x82: return { "add a,d" }; - case 0x83: return { "add a,e" }; - case 0x84: return { "add a,h" }; - case 0x85: return { "add a,l" }; - case 0x86: return { "add a,(hl)" }; - case 0x87: return { "add a,a" }; - case 0x88: return { "adc a,b" }; - case 0x89: return { "adc a,c" }; - case 0x8a: return { "adc a,d" }; - case 0x8b: return { "adc a,e" }; - case 0x8c: return { "adc a,h" }; - case 0x8d: return { "adc a,l" }; - case 0x8e: return { "adc a,(hl)" }; - case 0x8f: return { "adc a,a" }; - case 0x90: return { "sub a,b" }; - case 0x91: return { "sub a,c" }; - case 0x92: return { "sub a,d" }; - case 0x93: return { "sub a,e" }; - case 0x94: return { "sub a,h" }; - case 0x95: return { "sub a,l" }; - case 0x96: return { "sub a,(hl)" }; - case 0x97: return { "sub a,a" }; - case 0x98: return { "sbc a,b" }; - case 0x99: return { "sbc a,c" }; - case 0x9a: return { "sbc a,d" }; - case 0x9b: return { "sbc a,e" }; - case 0x9c: return { "sbc a,h" }; - case 0x9d: return { "sbc a,l" }; - case 0x9e: return { "sbc a,(hl)" }; - case 0x9f: return { "sbc a,a" }; - case 0xa0: return { "and a,b" }; - case 0xa1: return { "and a,c" }; - case 0xa2: return { "and a,d" }; - case 0xa3: return { "and a,e" }; - case 0xa4: return { "and a,h" }; - case 0xa5: return { "and a,l" }; - case 0xa6: return { "and a,(hl)" }; - case 0xa7: return { "and a,a" }; - case 0xa8: return { "xor a,b" }; - case 0xa9: return { "xor a,c" }; - case 0xaa: return { "xor a,d" }; - case 0xab: return { "xor a,e" }; - case 0xac: return { "xor a,h" }; - case 0xad: return { "xor a,l" }; - case 0xae: return { "xor a,(hl)" }; - case 0xaf: return { "xor a,a" }; - case 0xb0: return { "or a,b" }; - case 0xb1: return { "or a,c" }; - case 0xb2: return { "or a,d" }; - case 0xb3: return { "or a,e" }; - case 0xb4: return { "or a,h" }; - case 0xb5: return { "or a,l" }; - case 0xb6: return { "or a,(hl)" }; - case 0xb7: return { "or a,a" }; - case 0xb8: return { "cp a,b" }; - case 0xb9: return { "cp a,c" }; - case 0xba: return { "cp a,d" }; - case 0xbb: return { "cp a,e" }; - case 0xbc: return { "cp a,h" }; - case 0xbd: return { "cp a,l" }; - case 0xbe: return { "cp a,(hl)" }; - case 0xbf: return { "cp a,a" }; - case 0xc0: return { "ret nz" }; - case 0xc1: return { "pop bc" }; - case 0xc2: return { "jp nz,$", hex(p1, 2L), hex(p0, 2L) }; - case 0xc3: return { "jp $", hex(p1, 2L), hex(p0, 2L) }; - case 0xc4: return { "call nz,$", hex(p1, 2L), hex(p0, 2L) }; - case 0xc5: return { "push bc" }; - case 0xc6: return { "add a,$", hex(p0, 2L) }; - case 0xc7: return { "rst $0000" }; - case 0xc8: return { "ret z" }; - case 0xc9: return { "ret" }; - case 0xca: return { "jp z,$", hex(p1, 2L), hex(p0, 2L) }; + case 0x00: return {"nop"}; + case 0x01: return {"ld bc,$", hex(word, 4L)}; + case 0x02: return {"ld (bc),a"}; + case 0x03: return {"inc bc"}; + case 0x04: return {"inc b"}; + case 0x05: return {"dec b"}; + case 0x06: return {"ld b,$", hex(lo, 2L)}; + case 0x07: return {"rlca"}; + case 0x08: return {"ld ($", hex(word, 4L), "),sp"}; + case 0x09: return {"add hl,bc"}; + case 0x0a: return {"ld a,(bc)"}; + case 0x0b: return {"dec bc"}; + case 0x0c: return {"inc c"}; + case 0x0d: return {"dec c"}; + case 0x0e: return {"ld c,$", hex(lo, 2L)}; + case 0x0f: return {"rrca"}; + case 0x10: return {"stop"}; + case 0x11: return {"ld de,$", hex(word, 4L)}; + case 0x12: return {"ld (de),a"}; + case 0x13: return {"inc de"}; + case 0x14: return {"inc d"}; + case 0x15: return {"dec d"}; + case 0x16: return {"ld d,$", hex(lo, 2L)}; + case 0x17: return {"rla"}; + case 0x18: return {"jr $", hex(pc + 2 + (int8)lo, 4L)}; + case 0x19: return {"add hl,de"}; + case 0x1a: return {"ld a,(de)"}; + case 0x1b: return {"dec de"}; + case 0x1c: return {"inc e"}; + case 0x1d: return {"dec e"}; + case 0x1e: return {"ld e,$", hex(lo, 2L)}; + case 0x1f: return {"rra"}; + case 0x20: return {"jr nz,$", hex(pc + 2 + (int8)lo, 4L)}; + case 0x21: return {"ld hl,$", hex(word, 4L)}; + case 0x22: return {"ldi (hl),a"}; + case 0x23: return {"inc hl"}; + case 0x24: return {"inc h"}; + case 0x25: return {"dec h"}; + case 0x26: return {"ld h,$", hex(lo, 2L)}; + case 0x27: return {"daa"}; + case 0x28: return {"jr z,$", hex(pc + 2 + (int8)lo, 4L)}; + case 0x29: return {"add hl,hl"}; + case 0x2a: return {"ldi a,(hl)"}; + case 0x2b: return {"dec hl"}; + case 0x2c: return {"inc l"}; + case 0x2d: return {"dec l"}; + case 0x2e: return {"ld l,$", hex(lo, 2L)}; + case 0x2f: return {"cpl"}; + case 0x30: return {"jr nc,$", hex(pc + 2 + (int8)lo, 4L)}; + case 0x31: return {"ld sp,$", hex(word, 4L)}; + case 0x32: return {"ldd (hl),a"}; + case 0x33: return {"inc sp"}; + case 0x34: return {"inc (hl)"}; + case 0x35: return {"dec (hl)"}; + case 0x36: return {"ld (hl),$", hex(lo, 2L)}; + case 0x37: return {"scf"}; + case 0x38: return {"jr c,$", hex(pc + 2 + (int8)lo, 4L)}; + case 0x39: return {"add hl,sp"}; + case 0x3a: return {"ldd a,(hl)"}; + case 0x3b: return {"dec sp"}; + case 0x3c: return {"inc a"}; + case 0x3d: return {"dec a"}; + case 0x3e: return {"ld a,$", hex(lo, 2L)}; + case 0x3f: return {"ccf"}; + case 0x40: return {"ld b,b"}; + case 0x41: return {"ld b,c"}; + case 0x42: return {"ld b,d"}; + case 0x43: return {"ld b,e"}; + case 0x44: return {"ld b,h"}; + case 0x45: return {"ld b,l"}; + case 0x46: return {"ld b,(hl)"}; + case 0x47: return {"ld b,a"}; + case 0x48: return {"ld c,b"}; + case 0x49: return {"ld c,c"}; + case 0x4a: return {"ld c,d"}; + case 0x4b: return {"ld c,e"}; + case 0x4c: return {"ld c,h"}; + case 0x4d: return {"ld c,l"}; + case 0x4e: return {"ld c,(hl)"}; + case 0x4f: return {"ld c,a"}; + case 0x50: return {"ld d,b"}; + case 0x51: return {"ld d,c"}; + case 0x52: return {"ld d,d"}; + case 0x53: return {"ld d,e"}; + case 0x54: return {"ld d,h"}; + case 0x55: return {"ld d,l"}; + case 0x56: return {"ld d,(hl)"}; + case 0x57: return {"ld d,a"}; + case 0x58: return {"ld e,b"}; + case 0x59: return {"ld e,c"}; + case 0x5a: return {"ld e,d"}; + case 0x5b: return {"ld e,e"}; + case 0x5c: return {"ld e,h"}; + case 0x5d: return {"ld e,l"}; + case 0x5e: return {"ld e,(hl)"}; + case 0x5f: return {"ld e,a"}; + case 0x60: return {"ld h,b"}; + case 0x61: return {"ld h,c"}; + case 0x62: return {"ld h,d"}; + case 0x63: return {"ld h,e"}; + case 0x64: return {"ld h,h"}; + case 0x65: return {"ld h,l"}; + case 0x66: return {"ld h,(hl)"}; + case 0x67: return {"ld h,a"}; + case 0x68: return {"ld l,b"}; + case 0x69: return {"ld l,c"}; + case 0x6a: return {"ld l,d"}; + case 0x6b: return {"ld l,e"}; + case 0x6c: return {"ld l,h"}; + case 0x6d: return {"ld l,l"}; + case 0x6e: return {"ld l,(hl)"}; + case 0x6f: return {"ld l,a"}; + case 0x70: return {"ld (hl),b"}; + case 0x71: return {"ld (hl),c"}; + case 0x72: return {"ld (hl),d"}; + case 0x73: return {"ld (hl),e"}; + case 0x74: return {"ld (hl),h"}; + case 0x75: return {"ld (hl),l"}; + case 0x76: return {"halt"}; + case 0x77: return {"ld (hl),a"}; + case 0x78: return {"ld a,b"}; + case 0x79: return {"ld a,c"}; + case 0x7a: return {"ld a,d"}; + case 0x7b: return {"ld a,e"}; + case 0x7c: return {"ld a,h"}; + case 0x7d: return {"ld a,l"}; + case 0x7e: return {"ld a,(hl)"}; + case 0x7f: return {"ld a,a"}; + case 0x80: return {"add a,b"}; + case 0x81: return {"add a,c"}; + case 0x82: return {"add a,d"}; + case 0x83: return {"add a,e"}; + case 0x84: return {"add a,h"}; + case 0x85: return {"add a,l"}; + case 0x86: return {"add a,(hl)"}; + case 0x87: return {"add a,a"}; + case 0x88: return {"adc a,b"}; + case 0x89: return {"adc a,c"}; + case 0x8a: return {"adc a,d"}; + case 0x8b: return {"adc a,e"}; + case 0x8c: return {"adc a,h"}; + case 0x8d: return {"adc a,l"}; + case 0x8e: return {"adc a,(hl)"}; + case 0x8f: return {"adc a,a"}; + case 0x90: return {"sub a,b"}; + case 0x91: return {"sub a,c"}; + case 0x92: return {"sub a,d"}; + case 0x93: return {"sub a,e"}; + case 0x94: return {"sub a,h"}; + case 0x95: return {"sub a,l"}; + case 0x96: return {"sub a,(hl)"}; + case 0x97: return {"sub a,a"}; + case 0x98: return {"sbc a,b"}; + case 0x99: return {"sbc a,c"}; + case 0x9a: return {"sbc a,d"}; + case 0x9b: return {"sbc a,e"}; + case 0x9c: return {"sbc a,h"}; + case 0x9d: return {"sbc a,l"}; + case 0x9e: return {"sbc a,(hl)"}; + case 0x9f: return {"sbc a,a"}; + case 0xa0: return {"and a,b"}; + case 0xa1: return {"and a,c"}; + case 0xa2: return {"and a,d"}; + case 0xa3: return {"and a,e"}; + case 0xa4: return {"and a,h"}; + case 0xa5: return {"and a,l"}; + case 0xa6: return {"and a,(hl)"}; + case 0xa7: return {"and a,a"}; + case 0xa8: return {"xor a,b"}; + case 0xa9: return {"xor a,c"}; + case 0xaa: return {"xor a,d"}; + case 0xab: return {"xor a,e"}; + case 0xac: return {"xor a,h"}; + case 0xad: return {"xor a,l"}; + case 0xae: return {"xor a,(hl)"}; + case 0xaf: return {"xor a,a"}; + case 0xb0: return {"or a,b"}; + case 0xb1: return {"or a,c"}; + case 0xb2: return {"or a,d"}; + case 0xb3: return {"or a,e"}; + case 0xb4: return {"or a,h"}; + case 0xb5: return {"or a,l"}; + case 0xb6: return {"or a,(hl)"}; + case 0xb7: return {"or a,a"}; + case 0xb8: return {"cp a,b"}; + case 0xb9: return {"cp a,c"}; + case 0xba: return {"cp a,d"}; + case 0xbb: return {"cp a,e"}; + case 0xbc: return {"cp a,h"}; + case 0xbd: return {"cp a,l"}; + case 0xbe: return {"cp a,(hl)"}; + case 0xbf: return {"cp a,a"}; + case 0xc0: return {"ret nz"}; + case 0xc1: return {"pop bc"}; + case 0xc2: return {"jp nz,$", hex(word, 4L)}; + case 0xc3: return {"jp $", hex(word, 4L)}; + case 0xc4: return {"call nz,$", hex(word, 4L)}; + case 0xc5: return {"push bc"}; + case 0xc6: return {"add a,$", hex(lo, 2L)}; + case 0xc7: return {"rst $0000"}; + case 0xc8: return {"ret z"}; + case 0xc9: return {"ret"}; + case 0xca: return {"jp z,$", hex(word, 4L)}; case 0xcb: return disassembleOpcodeCB(pc + 1); - case 0xcc: return { "call z,$", hex(p1, 2L), hex(p0, 2L) }; - case 0xcd: return { "call $", hex(p1, 2L), hex(p0, 2L) }; - case 0xce: return { "adc a,$", hex(p0, 2L) }; - case 0xcf: return { "rst $0008" }; - case 0xd0: return { "ret nc" }; - case 0xd1: return { "pop de" }; - case 0xd2: return { "jp nc,$", hex(p1, 2L), hex(p0, 2L) }; - case 0xd3: return { "xx" }; - case 0xd4: return { "call nc,$", hex(p1, 2L), hex(p0, 2L) }; - case 0xd5: return { "push de" }; - case 0xd6: return { "sub a,$", hex(p0, 2L) }; - case 0xd7: return { "rst $0010" }; - case 0xd8: return { "ret c" }; - case 0xd9: return { "reti" }; - case 0xda: return { "jp c,$", hex(p1, 2L), hex(p0, 2L) }; - case 0xdb: return { "xx" }; - case 0xdc: return { "call c,$", hex(p1, 2L), hex(p0, 2L) }; - case 0xdd: return { "xx" }; - case 0xde: return { "sbc a,$", hex(p0, 2L) }; - case 0xdf: return { "rst $0018" }; - case 0xe0: return { "ld ($ff", hex(p0, 2L), "),a" }; - case 0xe1: return { "pop hl" }; - case 0xe2: return { "ld ($ff00+c),a" }; - case 0xe3: return { "xx" }; - case 0xe4: return { "xx" }; - case 0xe5: return { "push hl" }; - case 0xe6: return { "and a,$", hex(p0, 2L) }; - case 0xe7: return { "rst $0020" }; - case 0xe8: return { "add sp,$", hex((int8)p0, 4L) }; - case 0xe9: return { "jp hl" }; - case 0xea: return { "ld ($", hex(p1, 2L), hex(p0, 2L), "),a" }; - case 0xeb: return { "xx" }; - case 0xec: return { "xx" }; - case 0xed: return { "xx" }; - case 0xee: return { "xor a,$", hex(p0, 2L) }; - case 0xef: return { "rst $0028" }; - case 0xf0: return { "ld a,($ff", hex(p0, 2L), ")" }; - case 0xf1: return { "pop af" }; - case 0xf2: return { "ld a,($ff00+c)" }; - case 0xf3: return { "di" }; - case 0xf4: return { "xx" }; - case 0xf5: return { "push af" }; - case 0xf6: return { "or a,$", hex(p0, 2L) }; - case 0xf7: return { "rst $0030" }; - case 0xf8: return { "ld hl,sp+$", hex((int8)p0, 4L) }; - case 0xf9: return { "ld sp,hl" }; - case 0xfa: return { "ld a,($", hex(p1, 2L), hex(p0, 2L), ")" }; - case 0xfb: return { "ei" }; - case 0xfc: return { "xx" }; - case 0xfd: return { "xx" }; - case 0xfe: return { "cp a,$", hex(p0, 2L) }; - case 0xff: return { "rst $0038" }; + case 0xcc: return {"call z,$", hex(word, 4L)}; + case 0xcd: return {"call $", hex(word, 4L)}; + case 0xce: return {"adc a,$", hex(lo, 2L)}; + case 0xcf: return {"rst $0008"}; + case 0xd0: return {"ret nc"}; + case 0xd1: return {"pop de"}; + case 0xd2: return {"jp nc,$", hex(word, 4L)}; + case 0xd4: return {"call nc,$", hex(word, 4L)}; + case 0xd5: return {"push de"}; + case 0xd6: return {"sub a,$", hex(lo, 2L)}; + case 0xd7: return {"rst $0010"}; + case 0xd8: return {"ret c"}; + case 0xd9: return {"reti"}; + case 0xda: return {"jp c,$", hex(word, 4L)}; + case 0xdc: return {"call c,$", hex(word, 4L)}; + case 0xde: return {"sbc a,$", hex(lo, 2L)}; + case 0xdf: return {"rst $0018"}; + case 0xe0: return {"ldh ($ff", hex(lo, 2L), "),a"}; + case 0xe1: return {"pop hl"}; + case 0xe2: return {"ldh ($ff00+c),a"}; + case 0xe5: return {"push hl"}; + case 0xe6: return {"and a,$", hex(lo, 2L)}; + case 0xe7: return {"rst $0020"}; + case 0xe8: return {"add sp,$", hex((int8)lo, 4L)}; + case 0xe9: return {"jp hl"}; + case 0xea: return {"ld ($", hex(word, 4L), "),a"}; + case 0xee: return {"xor a,$", hex(lo, 2L)}; + case 0xef: return {"rst $0028"}; + case 0xf0: return {"ldh a,($ff", hex(lo, 2L), ")"}; + case 0xf1: return {"pop af"}; + case 0xf2: return {"ldh a,($ff00+c)"}; + case 0xf3: return {"di"}; + case 0xf5: return {"push af"}; + case 0xf6: return {"or a,$", hex(lo, 2L)}; + case 0xf7: return {"rst $0030"}; + case 0xf8: return {"ld hl,sp+$", hex((int8)lo, 4L)}; + case 0xf9: return {"ld sp,hl"}; + case 0xfa: return {"ld a,($", hex(word, 4L), ")"}; + case 0xfb: return {"ei"}; + case 0xfe: return {"cp a,$", hex(lo, 2L)}; + case 0xff: return {"rst $0038"}; } - return ""; + return "xx"; } auto LR35902::disassembleOpcodeCB(uint16 pc) -> string { - uint8 opcode = readDebugger(pc); - uint8 p0 = readDebugger(pc + 1); - uint8 p1 = readDebugger(pc + 2); - uint8 p2 = readDebugger(pc + 3); + auto opcode = readDebugger(pc); switch(opcode) { - case 0x00: return { "rlc b" }; - case 0x01: return { "rlc c" }; - case 0x02: return { "rlc d" }; - case 0x03: return { "rlc e" }; - case 0x04: return { "rlc h" }; - case 0x05: return { "rlc l" }; - case 0x06: return { "rlc (hl)" }; - case 0x07: return { "rlc a" }; - case 0x08: return { "rrc b" }; - case 0x09: return { "rrc c" }; - case 0x0a: return { "rrc d" }; - case 0x0b: return { "rrc e" }; - case 0x0c: return { "rrc h" }; - case 0x0d: return { "rrc l" }; - case 0x0e: return { "rrc (hl)" }; - case 0x0f: return { "rrc a" }; - case 0x10: return { "rl b" }; - case 0x11: return { "rl c" }; - case 0x12: return { "rl d" }; - case 0x13: return { "rl e" }; - case 0x14: return { "rl h" }; - case 0x15: return { "rl l" }; - case 0x16: return { "rl (hl)" }; - case 0x17: return { "rl a" }; - case 0x18: return { "rr b" }; - case 0x19: return { "rr c" }; - case 0x1a: return { "rr d" }; - case 0x1b: return { "rr e" }; - case 0x1c: return { "rr h" }; - case 0x1d: return { "rr l" }; - case 0x1e: return { "rr (hl)" }; - case 0x1f: return { "rr a" }; - case 0x20: return { "sla b" }; - case 0x21: return { "sla c" }; - case 0x22: return { "sla d" }; - case 0x23: return { "sla e" }; - case 0x24: return { "sla h" }; - case 0x25: return { "sla l" }; - case 0x26: return { "sla (hl)" }; - case 0x27: return { "sla a" }; - case 0x28: return { "sra b" }; - case 0x29: return { "sra c" }; - case 0x2a: return { "sra d" }; - case 0x2b: return { "sra e" }; - case 0x2c: return { "sra h" }; - case 0x2d: return { "sra l" }; - case 0x2e: return { "sra (hl)" }; - case 0x2f: return { "sra a" }; - case 0x30: return { "swap b" }; - case 0x31: return { "swap c" }; - case 0x32: return { "swap d" }; - case 0x33: return { "swap e" }; - case 0x34: return { "swap h" }; - case 0x35: return { "swap l" }; - case 0x36: return { "swap (hl)" }; - case 0x37: return { "swap a" }; - case 0x38: return { "srl b" }; - case 0x39: return { "srl c" }; - case 0x3a: return { "srl d" }; - case 0x3b: return { "srl e" }; - case 0x3c: return { "srl h" }; - case 0x3d: return { "srl l" }; - case 0x3e: return { "srl (hl)" }; - case 0x3f: return { "srl a" }; - case 0x40: return { "bit 0,b" }; - case 0x41: return { "bit 0,c" }; - case 0x42: return { "bit 0,d" }; - case 0x43: return { "bit 0,e" }; - case 0x44: return { "bit 0,h" }; - case 0x45: return { "bit 0,l" }; - case 0x46: return { "bit 0,(hl)" }; - case 0x47: return { "bit 0,a" }; - case 0x48: return { "bit 1,b" }; - case 0x49: return { "bit 1,c" }; - case 0x4a: return { "bit 1,d" }; - case 0x4b: return { "bit 1,e" }; - case 0x4c: return { "bit 1,h" }; - case 0x4d: return { "bit 1,l" }; - case 0x4e: return { "bit 1,(hl)" }; - case 0x4f: return { "bit 1,a" }; - case 0x50: return { "bit 2,b" }; - case 0x51: return { "bit 2,c" }; - case 0x52: return { "bit 2,d" }; - case 0x53: return { "bit 2,e" }; - case 0x54: return { "bit 2,h" }; - case 0x55: return { "bit 2,l" }; - case 0x56: return { "bit 2,(hl)" }; - case 0x57: return { "bit 2,a" }; - case 0x58: return { "bit 3,b" }; - case 0x59: return { "bit 3,c" }; - case 0x5a: return { "bit 3,d" }; - case 0x5b: return { "bit 3,e" }; - case 0x5c: return { "bit 3,h" }; - case 0x5d: return { "bit 3,l" }; - case 0x5e: return { "bit 3,(hl)" }; - case 0x5f: return { "bit 3,a" }; - case 0x60: return { "bit 4,b" }; - case 0x61: return { "bit 4,c" }; - case 0x62: return { "bit 4,d" }; - case 0x63: return { "bit 4,e" }; - case 0x64: return { "bit 4,h" }; - case 0x65: return { "bit 4,l" }; - case 0x66: return { "bit 4,(hl)" }; - case 0x67: return { "bit 4,a" }; - case 0x68: return { "bit 5,b" }; - case 0x69: return { "bit 5,c" }; - case 0x6a: return { "bit 5,d" }; - case 0x6b: return { "bit 5,e" }; - case 0x6c: return { "bit 5,h" }; - case 0x6d: return { "bit 5,l" }; - case 0x6e: return { "bit 5,(hl)" }; - case 0x6f: return { "bit 5,a" }; - case 0x70: return { "bit 6,b" }; - case 0x71: return { "bit 6,c" }; - case 0x72: return { "bit 6,d" }; - case 0x73: return { "bit 6,e" }; - case 0x74: return { "bit 6,h" }; - case 0x75: return { "bit 6,l" }; - case 0x76: return { "bit 6,(hl)" }; - case 0x77: return { "bit 6,a" }; - case 0x78: return { "bit 7,b" }; - case 0x79: return { "bit 7,c" }; - case 0x7a: return { "bit 7,d" }; - case 0x7b: return { "bit 7,e" }; - case 0x7c: return { "bit 7,h" }; - case 0x7d: return { "bit 7,l" }; - case 0x7e: return { "bit 7,(hl)" }; - case 0x7f: return { "bit 7,a" }; - case 0x80: return { "res 0,b" }; - case 0x81: return { "res 0,c" }; - case 0x82: return { "res 0,d" }; - case 0x83: return { "res 0,e" }; - case 0x84: return { "res 0,h" }; - case 0x85: return { "res 0,l" }; - case 0x86: return { "res 0,(hl)" }; - case 0x87: return { "res 0,a" }; - case 0x88: return { "res 1,b" }; - case 0x89: return { "res 1,c" }; - case 0x8a: return { "res 1,d" }; - case 0x8b: return { "res 1,e" }; - case 0x8c: return { "res 1,h" }; - case 0x8d: return { "res 1,l" }; - case 0x8e: return { "res 1,(hl)" }; - case 0x8f: return { "res 1,a" }; - case 0x90: return { "res 2,b" }; - case 0x91: return { "res 2,c" }; - case 0x92: return { "res 2,d" }; - case 0x93: return { "res 2,e" }; - case 0x94: return { "res 2,h" }; - case 0x95: return { "res 2,l" }; - case 0x96: return { "res 2,(hl)" }; - case 0x97: return { "res 2,a" }; - case 0x98: return { "res 3,b" }; - case 0x99: return { "res 3,c" }; - case 0x9a: return { "res 3,d" }; - case 0x9b: return { "res 3,e" }; - case 0x9c: return { "res 3,h" }; - case 0x9d: return { "res 3,l" }; - case 0x9e: return { "res 3,(hl)" }; - case 0x9f: return { "res 3,a" }; - case 0xa0: return { "res 4,b" }; - case 0xa1: return { "res 4,c" }; - case 0xa2: return { "res 4,d" }; - case 0xa3: return { "res 4,e" }; - case 0xa4: return { "res 4,h" }; - case 0xa5: return { "res 4,l" }; - case 0xa6: return { "res 4,(hl)" }; - case 0xa7: return { "res 4,a" }; - case 0xa8: return { "res 5,b" }; - case 0xa9: return { "res 5,c" }; - case 0xaa: return { "res 5,d" }; - case 0xab: return { "res 5,e" }; - case 0xac: return { "res 5,h" }; - case 0xad: return { "res 5,l" }; - case 0xae: return { "res 5,(hl)" }; - case 0xaf: return { "res 5,a" }; - case 0xb0: return { "res 6,b" }; - case 0xb1: return { "res 6,c" }; - case 0xb2: return { "res 6,d" }; - case 0xb3: return { "res 6,e" }; - case 0xb4: return { "res 6,h" }; - case 0xb5: return { "res 6,l" }; - case 0xb6: return { "res 6,(hl)" }; - case 0xb7: return { "res 6,a" }; - case 0xb8: return { "res 7,b" }; - case 0xb9: return { "res 7,c" }; - case 0xba: return { "res 7,d" }; - case 0xbb: return { "res 7,e" }; - case 0xbc: return { "res 7,h" }; - case 0xbd: return { "res 7,l" }; - case 0xbe: return { "res 7,(hl)" }; - case 0xbf: return { "res 7,a" }; - case 0xc0: return { "set 0,b" }; - case 0xc1: return { "set 0,c" }; - case 0xc2: return { "set 0,d" }; - case 0xc3: return { "set 0,e" }; - case 0xc4: return { "set 0,h" }; - case 0xc5: return { "set 0,l" }; - case 0xc6: return { "set 0,(hl)" }; - case 0xc7: return { "set 0,a" }; - case 0xc8: return { "set 1,b" }; - case 0xc9: return { "set 1,c" }; - case 0xca: return { "set 1,d" }; - case 0xcb: return { "set 1,e" }; - case 0xcc: return { "set 1,h" }; - case 0xcd: return { "set 1,l" }; - case 0xce: return { "set 1,(hl)" }; - case 0xcf: return { "set 1,a" }; - case 0xd0: return { "set 2,b" }; - case 0xd1: return { "set 2,c" }; - case 0xd2: return { "set 2,d" }; - case 0xd3: return { "set 2,e" }; - case 0xd4: return { "set 2,h" }; - case 0xd5: return { "set 2,l" }; - case 0xd6: return { "set 2,(hl)" }; - case 0xd7: return { "set 2,a" }; - case 0xd8: return { "set 3,b" }; - case 0xd9: return { "set 3,c" }; - case 0xda: return { "set 3,d" }; - case 0xdb: return { "set 3,e" }; - case 0xdc: return { "set 3,h" }; - case 0xdd: return { "set 3,l" }; - case 0xde: return { "set 3,(hl)" }; - case 0xdf: return { "set 3,a" }; - case 0xe0: return { "set 4,b" }; - case 0xe1: return { "set 4,c" }; - case 0xe2: return { "set 4,d" }; - case 0xe3: return { "set 4,e" }; - case 0xe4: return { "set 4,h" }; - case 0xe5: return { "set 4,l" }; - case 0xe6: return { "set 4,(hl)" }; - case 0xe7: return { "set 4,a" }; - case 0xe8: return { "set 5,b" }; - case 0xe9: return { "set 5,c" }; - case 0xea: return { "set 5,d" }; - case 0xeb: return { "set 5,e" }; - case 0xec: return { "set 5,h" }; - case 0xed: return { "set 5,l" }; - case 0xee: return { "set 5,(hl)" }; - case 0xef: return { "set 5,a" }; - case 0xf0: return { "set 6,b" }; - case 0xf1: return { "set 6,c" }; - case 0xf2: return { "set 6,d" }; - case 0xf3: return { "set 6,e" }; - case 0xf4: return { "set 6,h" }; - case 0xf5: return { "set 6,l" }; - case 0xf6: return { "set 6,(hl)" }; - case 0xf7: return { "set 6,a" }; - case 0xf8: return { "set 7,b" }; - case 0xf9: return { "set 7,c" }; - case 0xfa: return { "set 7,d" }; - case 0xfb: return { "set 7,e" }; - case 0xfc: return { "set 7,h" }; - case 0xfd: return { "set 7,l" }; - case 0xfe: return { "set 7,(hl)" }; - case 0xff: return { "set 7,a" }; + case 0x00: return {"rlc b"}; + case 0x01: return {"rlc c"}; + case 0x02: return {"rlc d"}; + case 0x03: return {"rlc e"}; + case 0x04: return {"rlc h"}; + case 0x05: return {"rlc l"}; + case 0x06: return {"rlc (hl)"}; + case 0x07: return {"rlc a"}; + case 0x08: return {"rrc b"}; + case 0x09: return {"rrc c"}; + case 0x0a: return {"rrc d"}; + case 0x0b: return {"rrc e"}; + case 0x0c: return {"rrc h"}; + case 0x0d: return {"rrc l"}; + case 0x0e: return {"rrc (hl)"}; + case 0x0f: return {"rrc a"}; + case 0x10: return {"rl b"}; + case 0x11: return {"rl c"}; + case 0x12: return {"rl d"}; + case 0x13: return {"rl e"}; + case 0x14: return {"rl h"}; + case 0x15: return {"rl l"}; + case 0x16: return {"rl (hl)"}; + case 0x17: return {"rl a"}; + case 0x18: return {"rr b"}; + case 0x19: return {"rr c"}; + case 0x1a: return {"rr d"}; + case 0x1b: return {"rr e"}; + case 0x1c: return {"rr h"}; + case 0x1d: return {"rr l"}; + case 0x1e: return {"rr (hl)"}; + case 0x1f: return {"rr a"}; + case 0x20: return {"sla b"}; + case 0x21: return {"sla c"}; + case 0x22: return {"sla d"}; + case 0x23: return {"sla e"}; + case 0x24: return {"sla h"}; + case 0x25: return {"sla l"}; + case 0x26: return {"sla (hl)"}; + case 0x27: return {"sla a"}; + case 0x28: return {"sra b"}; + case 0x29: return {"sra c"}; + case 0x2a: return {"sra d"}; + case 0x2b: return {"sra e"}; + case 0x2c: return {"sra h"}; + case 0x2d: return {"sra l"}; + case 0x2e: return {"sra (hl)"}; + case 0x2f: return {"sra a"}; + case 0x30: return {"swap b"}; + case 0x31: return {"swap c"}; + case 0x32: return {"swap d"}; + case 0x33: return {"swap e"}; + case 0x34: return {"swap h"}; + case 0x35: return {"swap l"}; + case 0x36: return {"swap (hl)"}; + case 0x37: return {"swap a"}; + case 0x38: return {"srl b"}; + case 0x39: return {"srl c"}; + case 0x3a: return {"srl d"}; + case 0x3b: return {"srl e"}; + case 0x3c: return {"srl h"}; + case 0x3d: return {"srl l"}; + case 0x3e: return {"srl (hl)"}; + case 0x3f: return {"srl a"}; + case 0x40: return {"bit 0,b"}; + case 0x41: return {"bit 0,c"}; + case 0x42: return {"bit 0,d"}; + case 0x43: return {"bit 0,e"}; + case 0x44: return {"bit 0,h"}; + case 0x45: return {"bit 0,l"}; + case 0x46: return {"bit 0,(hl)"}; + case 0x47: return {"bit 0,a"}; + case 0x48: return {"bit 1,b"}; + case 0x49: return {"bit 1,c"}; + case 0x4a: return {"bit 1,d"}; + case 0x4b: return {"bit 1,e"}; + case 0x4c: return {"bit 1,h"}; + case 0x4d: return {"bit 1,l"}; + case 0x4e: return {"bit 1,(hl)"}; + case 0x4f: return {"bit 1,a"}; + case 0x50: return {"bit 2,b"}; + case 0x51: return {"bit 2,c"}; + case 0x52: return {"bit 2,d"}; + case 0x53: return {"bit 2,e"}; + case 0x54: return {"bit 2,h"}; + case 0x55: return {"bit 2,l"}; + case 0x56: return {"bit 2,(hl)"}; + case 0x57: return {"bit 2,a"}; + case 0x58: return {"bit 3,b"}; + case 0x59: return {"bit 3,c"}; + case 0x5a: return {"bit 3,d"}; + case 0x5b: return {"bit 3,e"}; + case 0x5c: return {"bit 3,h"}; + case 0x5d: return {"bit 3,l"}; + case 0x5e: return {"bit 3,(hl)"}; + case 0x5f: return {"bit 3,a"}; + case 0x60: return {"bit 4,b"}; + case 0x61: return {"bit 4,c"}; + case 0x62: return {"bit 4,d"}; + case 0x63: return {"bit 4,e"}; + case 0x64: return {"bit 4,h"}; + case 0x65: return {"bit 4,l"}; + case 0x66: return {"bit 4,(hl)"}; + case 0x67: return {"bit 4,a"}; + case 0x68: return {"bit 5,b"}; + case 0x69: return {"bit 5,c"}; + case 0x6a: return {"bit 5,d"}; + case 0x6b: return {"bit 5,e"}; + case 0x6c: return {"bit 5,h"}; + case 0x6d: return {"bit 5,l"}; + case 0x6e: return {"bit 5,(hl)"}; + case 0x6f: return {"bit 5,a"}; + case 0x70: return {"bit 6,b"}; + case 0x71: return {"bit 6,c"}; + case 0x72: return {"bit 6,d"}; + case 0x73: return {"bit 6,e"}; + case 0x74: return {"bit 6,h"}; + case 0x75: return {"bit 6,l"}; + case 0x76: return {"bit 6,(hl)"}; + case 0x77: return {"bit 6,a"}; + case 0x78: return {"bit 7,b"}; + case 0x79: return {"bit 7,c"}; + case 0x7a: return {"bit 7,d"}; + case 0x7b: return {"bit 7,e"}; + case 0x7c: return {"bit 7,h"}; + case 0x7d: return {"bit 7,l"}; + case 0x7e: return {"bit 7,(hl)"}; + case 0x7f: return {"bit 7,a"}; + case 0x80: return {"res 0,b"}; + case 0x81: return {"res 0,c"}; + case 0x82: return {"res 0,d"}; + case 0x83: return {"res 0,e"}; + case 0x84: return {"res 0,h"}; + case 0x85: return {"res 0,l"}; + case 0x86: return {"res 0,(hl)"}; + case 0x87: return {"res 0,a"}; + case 0x88: return {"res 1,b"}; + case 0x89: return {"res 1,c"}; + case 0x8a: return {"res 1,d"}; + case 0x8b: return {"res 1,e"}; + case 0x8c: return {"res 1,h"}; + case 0x8d: return {"res 1,l"}; + case 0x8e: return {"res 1,(hl)"}; + case 0x8f: return {"res 1,a"}; + case 0x90: return {"res 2,b"}; + case 0x91: return {"res 2,c"}; + case 0x92: return {"res 2,d"}; + case 0x93: return {"res 2,e"}; + case 0x94: return {"res 2,h"}; + case 0x95: return {"res 2,l"}; + case 0x96: return {"res 2,(hl)"}; + case 0x97: return {"res 2,a"}; + case 0x98: return {"res 3,b"}; + case 0x99: return {"res 3,c"}; + case 0x9a: return {"res 3,d"}; + case 0x9b: return {"res 3,e"}; + case 0x9c: return {"res 3,h"}; + case 0x9d: return {"res 3,l"}; + case 0x9e: return {"res 3,(hl)"}; + case 0x9f: return {"res 3,a"}; + case 0xa0: return {"res 4,b"}; + case 0xa1: return {"res 4,c"}; + case 0xa2: return {"res 4,d"}; + case 0xa3: return {"res 4,e"}; + case 0xa4: return {"res 4,h"}; + case 0xa5: return {"res 4,l"}; + case 0xa6: return {"res 4,(hl)"}; + case 0xa7: return {"res 4,a"}; + case 0xa8: return {"res 5,b"}; + case 0xa9: return {"res 5,c"}; + case 0xaa: return {"res 5,d"}; + case 0xab: return {"res 5,e"}; + case 0xac: return {"res 5,h"}; + case 0xad: return {"res 5,l"}; + case 0xae: return {"res 5,(hl)"}; + case 0xaf: return {"res 5,a"}; + case 0xb0: return {"res 6,b"}; + case 0xb1: return {"res 6,c"}; + case 0xb2: return {"res 6,d"}; + case 0xb3: return {"res 6,e"}; + case 0xb4: return {"res 6,h"}; + case 0xb5: return {"res 6,l"}; + case 0xb6: return {"res 6,(hl)"}; + case 0xb7: return {"res 6,a"}; + case 0xb8: return {"res 7,b"}; + case 0xb9: return {"res 7,c"}; + case 0xba: return {"res 7,d"}; + case 0xbb: return {"res 7,e"}; + case 0xbc: return {"res 7,h"}; + case 0xbd: return {"res 7,l"}; + case 0xbe: return {"res 7,(hl)"}; + case 0xbf: return {"res 7,a"}; + case 0xc0: return {"set 0,b"}; + case 0xc1: return {"set 0,c"}; + case 0xc2: return {"set 0,d"}; + case 0xc3: return {"set 0,e"}; + case 0xc4: return {"set 0,h"}; + case 0xc5: return {"set 0,l"}; + case 0xc6: return {"set 0,(hl)"}; + case 0xc7: return {"set 0,a"}; + case 0xc8: return {"set 1,b"}; + case 0xc9: return {"set 1,c"}; + case 0xca: return {"set 1,d"}; + case 0xcb: return {"set 1,e"}; + case 0xcc: return {"set 1,h"}; + case 0xcd: return {"set 1,l"}; + case 0xce: return {"set 1,(hl)"}; + case 0xcf: return {"set 1,a"}; + case 0xd0: return {"set 2,b"}; + case 0xd1: return {"set 2,c"}; + case 0xd2: return {"set 2,d"}; + case 0xd3: return {"set 2,e"}; + case 0xd4: return {"set 2,h"}; + case 0xd5: return {"set 2,l"}; + case 0xd6: return {"set 2,(hl)"}; + case 0xd7: return {"set 2,a"}; + case 0xd8: return {"set 3,b"}; + case 0xd9: return {"set 3,c"}; + case 0xda: return {"set 3,d"}; + case 0xdb: return {"set 3,e"}; + case 0xdc: return {"set 3,h"}; + case 0xdd: return {"set 3,l"}; + case 0xde: return {"set 3,(hl)"}; + case 0xdf: return {"set 3,a"}; + case 0xe0: return {"set 4,b"}; + case 0xe1: return {"set 4,c"}; + case 0xe2: return {"set 4,d"}; + case 0xe3: return {"set 4,e"}; + case 0xe4: return {"set 4,h"}; + case 0xe5: return {"set 4,l"}; + case 0xe6: return {"set 4,(hl)"}; + case 0xe7: return {"set 4,a"}; + case 0xe8: return {"set 5,b"}; + case 0xe9: return {"set 5,c"}; + case 0xea: return {"set 5,d"}; + case 0xeb: return {"set 5,e"}; + case 0xec: return {"set 5,h"}; + case 0xed: return {"set 5,l"}; + case 0xee: return {"set 5,(hl)"}; + case 0xef: return {"set 5,a"}; + case 0xf0: return {"set 6,b"}; + case 0xf1: return {"set 6,c"}; + case 0xf2: return {"set 6,d"}; + case 0xf3: return {"set 6,e"}; + case 0xf4: return {"set 6,h"}; + case 0xf5: return {"set 6,l"}; + case 0xf6: return {"set 6,(hl)"}; + case 0xf7: return {"set 6,a"}; + case 0xf8: return {"set 7,b"}; + case 0xf9: return {"set 7,c"}; + case 0xfa: return {"set 7,d"}; + case 0xfb: return {"set 7,e"}; + case 0xfc: return {"set 7,h"}; + case 0xfd: return {"set 7,l"}; + case 0xfe: return {"set 7,(hl)"}; + case 0xff: return {"set 7,a"}; } - return ""; + unreachable; } diff --git a/higan/processor/lr35902-legacy/lr35902.cpp b/higan/processor/lr35902-legacy/lr35902.cpp index b26bccba..c37e705c 100644 --- a/higan/processor/lr35902-legacy/lr35902.cpp +++ b/higan/processor/lr35902-legacy/lr35902.cpp @@ -9,6 +9,13 @@ namespace Processor { #include "disassembler.cpp" auto LR35902::power() -> void { + r[AF] = 0x0000; + r[BC] = 0x0000; + r[DE] = 0x0000; + r[HL] = 0x0000; + r[SP] = 0x0000; + r[PC] = 0x0000; + r.halt = false; r.stop = false; r.ei = false; diff --git a/higan/processor/lr35902-legacy/lr35902.hpp b/higan/processor/lr35902-legacy/lr35902.hpp index 069f8b89..0535d1ef 100644 --- a/higan/processor/lr35902-legacy/lr35902.hpp +++ b/higan/processor/lr35902-legacy/lr35902.hpp @@ -5,11 +5,13 @@ namespace Processor { struct LR35902 { - virtual auto io() -> void = 0; + virtual auto idle() -> void = 0; virtual auto read(uint16 addr) -> uint8 = 0; virtual auto write(uint16 addr, uint8 data) -> void = 0; virtual auto stop() -> bool = 0; + auto io() -> void { idle(); } + //lr35902.cpp auto power() -> void; diff --git a/higan/processor/lr35902-legacy/registers.hpp b/higan/processor/lr35902-legacy/registers.hpp index 4b6e5ed5..785ce77b 100644 --- a/higan/processor/lr35902-legacy/registers.hpp +++ b/higan/processor/lr35902-legacy/registers.hpp @@ -98,7 +98,7 @@ struct Registers { bool ei; bool ime; - Register& operator[](uint r) { + auto operator[](uint r) -> Register& { static Register* const table[] = {&a, &f, &af, &b, &c, &bc, &d, &e, &de, &h, &l, &hl, &sp, &pc}; return *table[r]; } diff --git a/higan/processor/lr35902/algorithms.cpp b/higan/processor/lr35902/algorithms.cpp index ee28c18f..54805f66 100644 --- a/higan/processor/lr35902/algorithms.cpp +++ b/higan/processor/lr35902/algorithms.cpp @@ -1,16 +1,6 @@ -auto LR35902::ADC(uint8 target, uint8 source) -> uint8 { - uint16 x = target + source + CF; - uint16 y = (uint4)target + (uint4)source + CF; - CF = x > 0xff; - HF = y > 0x0f; - NF = 0; - ZF = (uint8)x == 0; - return x; -} - -auto LR35902::ADD(uint8 target, uint8 source) -> uint8 { - uint16 x = target + source; - uint16 y = (uint4)target + (uint4)source; +auto LR35902::ADD(uint8 target, uint8 source, bool carry) -> uint8 { + uint16 x = target + source + carry; + uint16 y = (uint4)target + (uint4)source + carry; CF = x > 0xff; HF = y > 0x0f; NF = 0; @@ -20,11 +10,19 @@ auto LR35902::ADD(uint8 target, uint8 source) -> uint8 { auto LR35902::AND(uint8 target, uint8 source) -> uint8 { target &= source; - CF = HF = NF = 0; + CF = 0; + HF = 1; + NF = 0; ZF = target == 0; return target; } +auto LR35902::BIT(uint3 index, uint8 target) -> void { + HF = 1; + NF = 0; + ZF = target.bit(index) == 0; +} + auto LR35902::CP(uint8 target, uint8 source) -> void { uint16 x = target - source; uint16 y = (uint4)target - (uint4)source; @@ -34,6 +32,22 @@ auto LR35902::CP(uint8 target, uint8 source) -> void { ZF = (uint8)x == 0; } +auto LR35902::DEC(uint8 target) -> uint8 { + target--; + HF = (uint4)target == 0x0f; + NF = 1; + ZF = target == 0; + return target; +} + +auto LR35902::INC(uint8 target) -> uint8 { + target++; + HF = (uint4)target == 0x00; + NF = 0; + ZF = target == 0; + return target; +} + auto LR35902::OR(uint8 target, uint8 source) -> uint8 { target |= source; CF = HF = NF = 0; @@ -41,9 +55,70 @@ auto LR35902::OR(uint8 target, uint8 source) -> uint8 { return target; } -auto LR35902::SBC(uint8 target, uint8 source) -> uint8 { - uint16 x = target - source - CF; - uint16 y = (uint4)target - (uint4)source - CF; +auto LR35902::RL(uint8 target) -> uint8 { + bool carry = target.bit(7); + target = target << 1 | CF; + CF = carry; + HF = NF = 0; + ZF = target == 0; + return target; +} + +auto LR35902::RLC(uint8 target) -> uint8 { + target = target << 1 | target >> 7; + CF = target.bit(0); + HF = NF = 0; + ZF = target == 0; + return target; +} + +auto LR35902::RR(uint8 target) -> uint8 { + bool carry = target.bit(0); + target = CF << 7 | target >> 1; + CF = carry; + HF = NF = 0; + ZF = target == 0; + return target; +} + +auto LR35902::RRC(uint8 target) -> uint8 { + target = target << 7 | target >> 1; + CF = target.bit(7); + HF = NF = 0; + ZF = target == 0; + return target; +} + +auto LR35902::SLA(uint8 target) -> uint8 { + bool carry = target.bit(7); + target <<= 1; + CF = carry; + HF = NF = 0; + ZF = target == 0; + return target; +} + +auto LR35902::SRA(uint8 target) -> uint8 { + bool carry = target.bit(0); + target = (int8)target >> 1; + CF = carry; + HF = NF = 0; + ZF = target == 0; + return target; +} + +auto LR35902::SRL(uint8 target) -> uint8 { + bool carry = target.bit(0); + target >>= 1; + CF = carry; + HF = NF = 0; + ZF = target == 0; + return target; +} + +auto LR35902::SUB(uint8 target, uint8 source, bool carry) -> uint8 { + uint16 x = target - source - carry; + uint16 y = (uint4)target - (uint4)source - carry; CF = x > 0xff; HF = y > 0x0f; NF = 1; @@ -51,14 +126,11 @@ auto LR35902::SBC(uint8 target, uint8 source) -> uint8 { return x; } -auto LR35902::SUB(uint8 target, uint8 source) -> uint8 { - uint16 x = target - source; - uint16 y = (uint4)target - (uint4)source; - CF = x > 0xff; - HF = y > 0x0f; - NF = 1; - ZF = (uint8)x == 0; - return x; +auto LR35902::SWAP(uint8 target) -> uint8 { + target = target << 4 | target >> 4; + CF = HF = NF = 0; + ZF = target == 0; + return target; } auto LR35902::XOR(uint8 target, uint8 source) -> uint8 { diff --git a/higan/processor/lr35902/disassembler.cpp b/higan/processor/lr35902/disassembler.cpp new file mode 100644 index 00000000..0a1540e1 --- /dev/null +++ b/higan/processor/lr35902/disassembler.cpp @@ -0,0 +1,533 @@ +auto LR35902::disassemble(uint16 pc) -> string { + return { + hex(pc, 4L), " ", + pad(disassembleOpcode(pc), -16, ' '), " ", + " AF:", hex(AF, 4L), + " BC:", hex(BC, 4L), + " DE:", hex(DE, 4L), + " HL:", hex(HL, 4L), + " SP:", hex(SP, 4L) + }; +} + +auto LR35902::disassembleOpcode(uint16 pc) -> string { + auto opcode = readDebugger(pc); + auto lo = readDebugger(pc + 1); + auto hi = readDebugger(pc + 2); + auto word = hi << 8 | lo << 0; + + switch(opcode) { + case 0x00: return {"nop"}; + case 0x01: return {"ld bc,$", hex(word, 4L)}; + case 0x02: return {"ld (bc),a"}; + case 0x03: return {"inc bc"}; + case 0x04: return {"inc b"}; + case 0x05: return {"dec b"}; + case 0x06: return {"ld b,$", hex(lo, 2L)}; + case 0x07: return {"rlca"}; + case 0x08: return {"ld ($", hex(word, 4L), "),sp"}; + case 0x09: return {"add hl,bc"}; + case 0x0a: return {"ld a,(bc)"}; + case 0x0b: return {"dec bc"}; + case 0x0c: return {"inc c"}; + case 0x0d: return {"dec c"}; + case 0x0e: return {"ld c,$", hex(lo, 2L)}; + case 0x0f: return {"rrca"}; + case 0x10: return {"stop"}; + case 0x11: return {"ld de,$", hex(word, 4L)}; + case 0x12: return {"ld (de),a"}; + case 0x13: return {"inc de"}; + case 0x14: return {"inc d"}; + case 0x15: return {"dec d"}; + case 0x16: return {"ld d,$", hex(lo, 2L)}; + case 0x17: return {"rla"}; + case 0x18: return {"jr $", hex(pc + 2 + (int8)lo, 4L)}; + case 0x19: return {"add hl,de"}; + case 0x1a: return {"ld a,(de)"}; + case 0x1b: return {"dec de"}; + case 0x1c: return {"inc e"}; + case 0x1d: return {"dec e"}; + case 0x1e: return {"ld e,$", hex(lo, 2L)}; + case 0x1f: return {"rra"}; + case 0x20: return {"jr nz,$", hex(pc + 2 + (int8)lo, 4L)}; + case 0x21: return {"ld hl,$", hex(word, 4L)}; + case 0x22: return {"ldi (hl),a"}; + case 0x23: return {"inc hl"}; + case 0x24: return {"inc h"}; + case 0x25: return {"dec h"}; + case 0x26: return {"ld h,$", hex(lo, 2L)}; + case 0x27: return {"daa"}; + case 0x28: return {"jr z,$", hex(pc + 2 + (int8)lo, 4L)}; + case 0x29: return {"add hl,hl"}; + case 0x2a: return {"ldi a,(hl)"}; + case 0x2b: return {"dec hl"}; + case 0x2c: return {"inc l"}; + case 0x2d: return {"dec l"}; + case 0x2e: return {"ld l,$", hex(lo, 2L)}; + case 0x2f: return {"cpl"}; + case 0x30: return {"jr nc,$", hex(pc + 2 + (int8)lo, 4L)}; + case 0x31: return {"ld sp,$", hex(word, 4L)}; + case 0x32: return {"ldd (hl),a"}; + case 0x33: return {"inc sp"}; + case 0x34: return {"inc (hl)"}; + case 0x35: return {"dec (hl)"}; + case 0x36: return {"ld (hl),$", hex(lo, 2L)}; + case 0x37: return {"scf"}; + case 0x38: return {"jr c,$", hex(pc + 2 + (int8)lo, 4L)}; + case 0x39: return {"add hl,sp"}; + case 0x3a: return {"ldd a,(hl)"}; + case 0x3b: return {"dec sp"}; + case 0x3c: return {"inc a"}; + case 0x3d: return {"dec a"}; + case 0x3e: return {"ld a,$", hex(lo, 2L)}; + case 0x3f: return {"ccf"}; + case 0x40: return {"ld b,b"}; + case 0x41: return {"ld b,c"}; + case 0x42: return {"ld b,d"}; + case 0x43: return {"ld b,e"}; + case 0x44: return {"ld b,h"}; + case 0x45: return {"ld b,l"}; + case 0x46: return {"ld b,(hl)"}; + case 0x47: return {"ld b,a"}; + case 0x48: return {"ld c,b"}; + case 0x49: return {"ld c,c"}; + case 0x4a: return {"ld c,d"}; + case 0x4b: return {"ld c,e"}; + case 0x4c: return {"ld c,h"}; + case 0x4d: return {"ld c,l"}; + case 0x4e: return {"ld c,(hl)"}; + case 0x4f: return {"ld c,a"}; + case 0x50: return {"ld d,b"}; + case 0x51: return {"ld d,c"}; + case 0x52: return {"ld d,d"}; + case 0x53: return {"ld d,e"}; + case 0x54: return {"ld d,h"}; + case 0x55: return {"ld d,l"}; + case 0x56: return {"ld d,(hl)"}; + case 0x57: return {"ld d,a"}; + case 0x58: return {"ld e,b"}; + case 0x59: return {"ld e,c"}; + case 0x5a: return {"ld e,d"}; + case 0x5b: return {"ld e,e"}; + case 0x5c: return {"ld e,h"}; + case 0x5d: return {"ld e,l"}; + case 0x5e: return {"ld e,(hl)"}; + case 0x5f: return {"ld e,a"}; + case 0x60: return {"ld h,b"}; + case 0x61: return {"ld h,c"}; + case 0x62: return {"ld h,d"}; + case 0x63: return {"ld h,e"}; + case 0x64: return {"ld h,h"}; + case 0x65: return {"ld h,l"}; + case 0x66: return {"ld h,(hl)"}; + case 0x67: return {"ld h,a"}; + case 0x68: return {"ld l,b"}; + case 0x69: return {"ld l,c"}; + case 0x6a: return {"ld l,d"}; + case 0x6b: return {"ld l,e"}; + case 0x6c: return {"ld l,h"}; + case 0x6d: return {"ld l,l"}; + case 0x6e: return {"ld l,(hl)"}; + case 0x6f: return {"ld l,a"}; + case 0x70: return {"ld (hl),b"}; + case 0x71: return {"ld (hl),c"}; + case 0x72: return {"ld (hl),d"}; + case 0x73: return {"ld (hl),e"}; + case 0x74: return {"ld (hl),h"}; + case 0x75: return {"ld (hl),l"}; + case 0x76: return {"halt"}; + case 0x77: return {"ld (hl),a"}; + case 0x78: return {"ld a,b"}; + case 0x79: return {"ld a,c"}; + case 0x7a: return {"ld a,d"}; + case 0x7b: return {"ld a,e"}; + case 0x7c: return {"ld a,h"}; + case 0x7d: return {"ld a,l"}; + case 0x7e: return {"ld a,(hl)"}; + case 0x7f: return {"ld a,a"}; + case 0x80: return {"add a,b"}; + case 0x81: return {"add a,c"}; + case 0x82: return {"add a,d"}; + case 0x83: return {"add a,e"}; + case 0x84: return {"add a,h"}; + case 0x85: return {"add a,l"}; + case 0x86: return {"add a,(hl)"}; + case 0x87: return {"add a,a"}; + case 0x88: return {"adc a,b"}; + case 0x89: return {"adc a,c"}; + case 0x8a: return {"adc a,d"}; + case 0x8b: return {"adc a,e"}; + case 0x8c: return {"adc a,h"}; + case 0x8d: return {"adc a,l"}; + case 0x8e: return {"adc a,(hl)"}; + case 0x8f: return {"adc a,a"}; + case 0x90: return {"sub a,b"}; + case 0x91: return {"sub a,c"}; + case 0x92: return {"sub a,d"}; + case 0x93: return {"sub a,e"}; + case 0x94: return {"sub a,h"}; + case 0x95: return {"sub a,l"}; + case 0x96: return {"sub a,(hl)"}; + case 0x97: return {"sub a,a"}; + case 0x98: return {"sbc a,b"}; + case 0x99: return {"sbc a,c"}; + case 0x9a: return {"sbc a,d"}; + case 0x9b: return {"sbc a,e"}; + case 0x9c: return {"sbc a,h"}; + case 0x9d: return {"sbc a,l"}; + case 0x9e: return {"sbc a,(hl)"}; + case 0x9f: return {"sbc a,a"}; + case 0xa0: return {"and a,b"}; + case 0xa1: return {"and a,c"}; + case 0xa2: return {"and a,d"}; + case 0xa3: return {"and a,e"}; + case 0xa4: return {"and a,h"}; + case 0xa5: return {"and a,l"}; + case 0xa6: return {"and a,(hl)"}; + case 0xa7: return {"and a,a"}; + case 0xa8: return {"xor a,b"}; + case 0xa9: return {"xor a,c"}; + case 0xaa: return {"xor a,d"}; + case 0xab: return {"xor a,e"}; + case 0xac: return {"xor a,h"}; + case 0xad: return {"xor a,l"}; + case 0xae: return {"xor a,(hl)"}; + case 0xaf: return {"xor a,a"}; + case 0xb0: return {"or a,b"}; + case 0xb1: return {"or a,c"}; + case 0xb2: return {"or a,d"}; + case 0xb3: return {"or a,e"}; + case 0xb4: return {"or a,h"}; + case 0xb5: return {"or a,l"}; + case 0xb6: return {"or a,(hl)"}; + case 0xb7: return {"or a,a"}; + case 0xb8: return {"cp a,b"}; + case 0xb9: return {"cp a,c"}; + case 0xba: return {"cp a,d"}; + case 0xbb: return {"cp a,e"}; + case 0xbc: return {"cp a,h"}; + case 0xbd: return {"cp a,l"}; + case 0xbe: return {"cp a,(hl)"}; + case 0xbf: return {"cp a,a"}; + case 0xc0: return {"ret nz"}; + case 0xc1: return {"pop bc"}; + case 0xc2: return {"jp nz,$", hex(word, 4L)}; + case 0xc3: return {"jp $", hex(word, 4L)}; + case 0xc4: return {"call nz,$", hex(word, 4L)}; + case 0xc5: return {"push bc"}; + case 0xc6: return {"add a,$", hex(lo, 2L)}; + case 0xc7: return {"rst $0000"}; + case 0xc8: return {"ret z"}; + case 0xc9: return {"ret"}; + case 0xca: return {"jp z,$", hex(word, 4L)}; + case 0xcb: return disassembleOpcodeCB(pc + 1); + case 0xcc: return {"call z,$", hex(word, 4L)}; + case 0xcd: return {"call $", hex(word, 4L)}; + case 0xce: return {"adc a,$", hex(lo, 2L)}; + case 0xcf: return {"rst $0008"}; + case 0xd0: return {"ret nc"}; + case 0xd1: return {"pop de"}; + case 0xd2: return {"jp nc,$", hex(word, 4L)}; + case 0xd4: return {"call nc,$", hex(word, 4L)}; + case 0xd5: return {"push de"}; + case 0xd6: return {"sub a,$", hex(lo, 2L)}; + case 0xd7: return {"rst $0010"}; + case 0xd8: return {"ret c"}; + case 0xd9: return {"reti"}; + case 0xda: return {"jp c,$", hex(word, 4L)}; + case 0xdc: return {"call c,$", hex(word, 4L)}; + case 0xde: return {"sbc a,$", hex(lo, 2L)}; + case 0xdf: return {"rst $0018"}; + case 0xe0: return {"ldh ($ff", hex(lo, 2L), "),a"}; + case 0xe1: return {"pop hl"}; + case 0xe2: return {"ldh ($ff00+c),a"}; + case 0xe5: return {"push hl"}; + case 0xe6: return {"and a,$", hex(lo, 2L)}; + case 0xe7: return {"rst $0020"}; + case 0xe8: return {"add sp,$", hex((int8)lo, 4L)}; + case 0xe9: return {"jp hl"}; + case 0xea: return {"ld ($", hex(word, 4L), "),a"}; + case 0xee: return {"xor a,$", hex(lo, 2L)}; + case 0xef: return {"rst $0028"}; + case 0xf0: return {"ldh a,($ff", hex(lo, 2L), ")"}; + case 0xf1: return {"pop af"}; + case 0xf2: return {"ldh a,($ff00+c)"}; + case 0xf3: return {"di"}; + case 0xf5: return {"push af"}; + case 0xf6: return {"or a,$", hex(lo, 2L)}; + case 0xf7: return {"rst $0030"}; + case 0xf8: return {"ld hl,sp+$", hex((int8)lo, 4L)}; + case 0xf9: return {"ld sp,hl"}; + case 0xfa: return {"ld a,($", hex(word, 4L), ")"}; + case 0xfb: return {"ei"}; + case 0xfe: return {"cp a,$", hex(lo, 2L)}; + case 0xff: return {"rst $0038"}; + } + + return {"xx"}; +} + +auto LR35902::disassembleOpcodeCB(uint16 pc) -> string { + auto opcode = readDebugger(pc); + + switch(opcode) { + case 0x00: return {"rlc b"}; + case 0x01: return {"rlc c"}; + case 0x02: return {"rlc d"}; + case 0x03: return {"rlc e"}; + case 0x04: return {"rlc h"}; + case 0x05: return {"rlc l"}; + case 0x06: return {"rlc (hl)"}; + case 0x07: return {"rlc a"}; + case 0x08: return {"rrc b"}; + case 0x09: return {"rrc c"}; + case 0x0a: return {"rrc d"}; + case 0x0b: return {"rrc e"}; + case 0x0c: return {"rrc h"}; + case 0x0d: return {"rrc l"}; + case 0x0e: return {"rrc (hl)"}; + case 0x0f: return {"rrc a"}; + case 0x10: return {"rl b"}; + case 0x11: return {"rl c"}; + case 0x12: return {"rl d"}; + case 0x13: return {"rl e"}; + case 0x14: return {"rl h"}; + case 0x15: return {"rl l"}; + case 0x16: return {"rl (hl)"}; + case 0x17: return {"rl a"}; + case 0x18: return {"rr b"}; + case 0x19: return {"rr c"}; + case 0x1a: return {"rr d"}; + case 0x1b: return {"rr e"}; + case 0x1c: return {"rr h"}; + case 0x1d: return {"rr l"}; + case 0x1e: return {"rr (hl)"}; + case 0x1f: return {"rr a"}; + case 0x20: return {"sla b"}; + case 0x21: return {"sla c"}; + case 0x22: return {"sla d"}; + case 0x23: return {"sla e"}; + case 0x24: return {"sla h"}; + case 0x25: return {"sla l"}; + case 0x26: return {"sla (hl)"}; + case 0x27: return {"sla a"}; + case 0x28: return {"sra b"}; + case 0x29: return {"sra c"}; + case 0x2a: return {"sra d"}; + case 0x2b: return {"sra e"}; + case 0x2c: return {"sra h"}; + case 0x2d: return {"sra l"}; + case 0x2e: return {"sra (hl)"}; + case 0x2f: return {"sra a"}; + case 0x30: return {"swap b"}; + case 0x31: return {"swap c"}; + case 0x32: return {"swap d"}; + case 0x33: return {"swap e"}; + case 0x34: return {"swap h"}; + case 0x35: return {"swap l"}; + case 0x36: return {"swap (hl)"}; + case 0x37: return {"swap a"}; + case 0x38: return {"srl b"}; + case 0x39: return {"srl c"}; + case 0x3a: return {"srl d"}; + case 0x3b: return {"srl e"}; + case 0x3c: return {"srl h"}; + case 0x3d: return {"srl l"}; + case 0x3e: return {"srl (hl)"}; + case 0x3f: return {"srl a"}; + case 0x40: return {"bit 0,b"}; + case 0x41: return {"bit 0,c"}; + case 0x42: return {"bit 0,d"}; + case 0x43: return {"bit 0,e"}; + case 0x44: return {"bit 0,h"}; + case 0x45: return {"bit 0,l"}; + case 0x46: return {"bit 0,(hl)"}; + case 0x47: return {"bit 0,a"}; + case 0x48: return {"bit 1,b"}; + case 0x49: return {"bit 1,c"}; + case 0x4a: return {"bit 1,d"}; + case 0x4b: return {"bit 1,e"}; + case 0x4c: return {"bit 1,h"}; + case 0x4d: return {"bit 1,l"}; + case 0x4e: return {"bit 1,(hl)"}; + case 0x4f: return {"bit 1,a"}; + case 0x50: return {"bit 2,b"}; + case 0x51: return {"bit 2,c"}; + case 0x52: return {"bit 2,d"}; + case 0x53: return {"bit 2,e"}; + case 0x54: return {"bit 2,h"}; + case 0x55: return {"bit 2,l"}; + case 0x56: return {"bit 2,(hl)"}; + case 0x57: return {"bit 2,a"}; + case 0x58: return {"bit 3,b"}; + case 0x59: return {"bit 3,c"}; + case 0x5a: return {"bit 3,d"}; + case 0x5b: return {"bit 3,e"}; + case 0x5c: return {"bit 3,h"}; + case 0x5d: return {"bit 3,l"}; + case 0x5e: return {"bit 3,(hl)"}; + case 0x5f: return {"bit 3,a"}; + case 0x60: return {"bit 4,b"}; + case 0x61: return {"bit 4,c"}; + case 0x62: return {"bit 4,d"}; + case 0x63: return {"bit 4,e"}; + case 0x64: return {"bit 4,h"}; + case 0x65: return {"bit 4,l"}; + case 0x66: return {"bit 4,(hl)"}; + case 0x67: return {"bit 4,a"}; + case 0x68: return {"bit 5,b"}; + case 0x69: return {"bit 5,c"}; + case 0x6a: return {"bit 5,d"}; + case 0x6b: return {"bit 5,e"}; + case 0x6c: return {"bit 5,h"}; + case 0x6d: return {"bit 5,l"}; + case 0x6e: return {"bit 5,(hl)"}; + case 0x6f: return {"bit 5,a"}; + case 0x70: return {"bit 6,b"}; + case 0x71: return {"bit 6,c"}; + case 0x72: return {"bit 6,d"}; + case 0x73: return {"bit 6,e"}; + case 0x74: return {"bit 6,h"}; + case 0x75: return {"bit 6,l"}; + case 0x76: return {"bit 6,(hl)"}; + case 0x77: return {"bit 6,a"}; + case 0x78: return {"bit 7,b"}; + case 0x79: return {"bit 7,c"}; + case 0x7a: return {"bit 7,d"}; + case 0x7b: return {"bit 7,e"}; + case 0x7c: return {"bit 7,h"}; + case 0x7d: return {"bit 7,l"}; + case 0x7e: return {"bit 7,(hl)"}; + case 0x7f: return {"bit 7,a"}; + case 0x80: return {"res 0,b"}; + case 0x81: return {"res 0,c"}; + case 0x82: return {"res 0,d"}; + case 0x83: return {"res 0,e"}; + case 0x84: return {"res 0,h"}; + case 0x85: return {"res 0,l"}; + case 0x86: return {"res 0,(hl)"}; + case 0x87: return {"res 0,a"}; + case 0x88: return {"res 1,b"}; + case 0x89: return {"res 1,c"}; + case 0x8a: return {"res 1,d"}; + case 0x8b: return {"res 1,e"}; + case 0x8c: return {"res 1,h"}; + case 0x8d: return {"res 1,l"}; + case 0x8e: return {"res 1,(hl)"}; + case 0x8f: return {"res 1,a"}; + case 0x90: return {"res 2,b"}; + case 0x91: return {"res 2,c"}; + case 0x92: return {"res 2,d"}; + case 0x93: return {"res 2,e"}; + case 0x94: return {"res 2,h"}; + case 0x95: return {"res 2,l"}; + case 0x96: return {"res 2,(hl)"}; + case 0x97: return {"res 2,a"}; + case 0x98: return {"res 3,b"}; + case 0x99: return {"res 3,c"}; + case 0x9a: return {"res 3,d"}; + case 0x9b: return {"res 3,e"}; + case 0x9c: return {"res 3,h"}; + case 0x9d: return {"res 3,l"}; + case 0x9e: return {"res 3,(hl)"}; + case 0x9f: return {"res 3,a"}; + case 0xa0: return {"res 4,b"}; + case 0xa1: return {"res 4,c"}; + case 0xa2: return {"res 4,d"}; + case 0xa3: return {"res 4,e"}; + case 0xa4: return {"res 4,h"}; + case 0xa5: return {"res 4,l"}; + case 0xa6: return {"res 4,(hl)"}; + case 0xa7: return {"res 4,a"}; + case 0xa8: return {"res 5,b"}; + case 0xa9: return {"res 5,c"}; + case 0xaa: return {"res 5,d"}; + case 0xab: return {"res 5,e"}; + case 0xac: return {"res 5,h"}; + case 0xad: return {"res 5,l"}; + case 0xae: return {"res 5,(hl)"}; + case 0xaf: return {"res 5,a"}; + case 0xb0: return {"res 6,b"}; + case 0xb1: return {"res 6,c"}; + case 0xb2: return {"res 6,d"}; + case 0xb3: return {"res 6,e"}; + case 0xb4: return {"res 6,h"}; + case 0xb5: return {"res 6,l"}; + case 0xb6: return {"res 6,(hl)"}; + case 0xb7: return {"res 6,a"}; + case 0xb8: return {"res 7,b"}; + case 0xb9: return {"res 7,c"}; + case 0xba: return {"res 7,d"}; + case 0xbb: return {"res 7,e"}; + case 0xbc: return {"res 7,h"}; + case 0xbd: return {"res 7,l"}; + case 0xbe: return {"res 7,(hl)"}; + case 0xbf: return {"res 7,a"}; + case 0xc0: return {"set 0,b"}; + case 0xc1: return {"set 0,c"}; + case 0xc2: return {"set 0,d"}; + case 0xc3: return {"set 0,e"}; + case 0xc4: return {"set 0,h"}; + case 0xc5: return {"set 0,l"}; + case 0xc6: return {"set 0,(hl)"}; + case 0xc7: return {"set 0,a"}; + case 0xc8: return {"set 1,b"}; + case 0xc9: return {"set 1,c"}; + case 0xca: return {"set 1,d"}; + case 0xcb: return {"set 1,e"}; + case 0xcc: return {"set 1,h"}; + case 0xcd: return {"set 1,l"}; + case 0xce: return {"set 1,(hl)"}; + case 0xcf: return {"set 1,a"}; + case 0xd0: return {"set 2,b"}; + case 0xd1: return {"set 2,c"}; + case 0xd2: return {"set 2,d"}; + case 0xd3: return {"set 2,e"}; + case 0xd4: return {"set 2,h"}; + case 0xd5: return {"set 2,l"}; + case 0xd6: return {"set 2,(hl)"}; + case 0xd7: return {"set 2,a"}; + case 0xd8: return {"set 3,b"}; + case 0xd9: return {"set 3,c"}; + case 0xda: return {"set 3,d"}; + case 0xdb: return {"set 3,e"}; + case 0xdc: return {"set 3,h"}; + case 0xdd: return {"set 3,l"}; + case 0xde: return {"set 3,(hl)"}; + case 0xdf: return {"set 3,a"}; + case 0xe0: return {"set 4,b"}; + case 0xe1: return {"set 4,c"}; + case 0xe2: return {"set 4,d"}; + case 0xe3: return {"set 4,e"}; + case 0xe4: return {"set 4,h"}; + case 0xe5: return {"set 4,l"}; + case 0xe6: return {"set 4,(hl)"}; + case 0xe7: return {"set 4,a"}; + case 0xe8: return {"set 5,b"}; + case 0xe9: return {"set 5,c"}; + case 0xea: return {"set 5,d"}; + case 0xeb: return {"set 5,e"}; + case 0xec: return {"set 5,h"}; + case 0xed: return {"set 5,l"}; + case 0xee: return {"set 5,(hl)"}; + case 0xef: return {"set 5,a"}; + case 0xf0: return {"set 6,b"}; + case 0xf1: return {"set 6,c"}; + case 0xf2: return {"set 6,d"}; + case 0xf3: return {"set 6,e"}; + case 0xf4: return {"set 6,h"}; + case 0xf5: return {"set 6,l"}; + case 0xf6: return {"set 6,(hl)"}; + case 0xf7: return {"set 6,a"}; + case 0xf8: return {"set 7,b"}; + case 0xf9: return {"set 7,c"}; + case 0xfa: return {"set 7,d"}; + case 0xfb: return {"set 7,e"}; + case 0xfc: return {"set 7,h"}; + case 0xfd: return {"set 7,l"}; + case 0xfe: return {"set 7,(hl)"}; + case 0xff: return {"set 7,a"}; + } + + unreachable; +} diff --git a/higan/processor/lr35902/instruction.cpp b/higan/processor/lr35902/instruction.cpp index 8264cd78..dc803e0d 100644 --- a/higan/processor/lr35902/instruction.cpp +++ b/higan/processor/lr35902/instruction.cpp @@ -1,10 +1,18 @@ auto LR35902::interrupt(uint16 vector) -> void { + idle(); + idle(); + idle(); + r.ime = 0; + push(PC); + PC = vector; } #define op(id, name, ...) case id: return instruction##name(__VA_ARGS__); auto LR35902::instruction() -> void { - switch(auto opcode = operand()) { + auto opcode = operand(); + + switch(opcode) { op(0x00, NOP) op(0x01, LD_Direct_Data, BC) op(0x02, LD_Indirect_Direct, BC, A) @@ -12,7 +20,7 @@ auto LR35902::instruction() -> void { op(0x04, INC_Direct, B) op(0x05, DEC_Direct, B) op(0x06, LD_Direct_Data, B) - op(0x07, RLC_Direct, A) + op(0x07, RLCA) op(0x08, LD_Address_Direct, SP) op(0x09, ADD_Direct_Direct, HL, BC) op(0x0a, LD_Direct_Indirect, A, BC) @@ -20,7 +28,7 @@ auto LR35902::instruction() -> void { op(0x0c, INC_Direct, C) op(0x0d, DEC_Direct, C) op(0x0e, LD_Direct_Data, C) - op(0x0f, RRC_Direct, A) + op(0x0f, RRCA) op(0x10, STOP) op(0x11, LD_Direct_Data, DE) op(0x12, LD_Indirect_Direct, DE, A) @@ -28,7 +36,7 @@ auto LR35902::instruction() -> void { op(0x14, INC_Direct, D) op(0x15, DEC_Direct, D) op(0x16, LD_Direct_Data, D) - op(0x17, RL_Direct, A) + op(0x17, RLA) op(0x18, JR_Condition_Relative, 1) op(0x19, ADD_Direct_Direct, HL, DE) op(0x1a, LD_Direct_Indirect, A, DE) @@ -36,7 +44,7 @@ auto LR35902::instruction() -> void { op(0x1c, INC_Direct, E) op(0x1d, DEC_Direct, E) op(0x1e, LD_Direct_Data, E) - op(0x1f, RR_Direct, A) + op(0x1f, RRA) op(0x20, JR_Condition_Relative, ZF == 0) op(0x21, LD_Direct_Data, HL) op(0x22, LD_IndirectIncrement_Direct, HL, A) @@ -198,27 +206,158 @@ auto LR35902::instruction() -> void { op(0xbe, CP_Direct_Indirect, A, HL) op(0xbf, CP_Direct_Direct, A, A) op(0xc0, RET_Condition, ZF == 0) + op(0xc1, POP_Direct, BC) + op(0xc2, JP_Condition_Address, ZF == 0) + op(0xc3, JP_Condition_Address, 1) + op(0xc4, CALL_Condition_Address, ZF == 0) + op(0xc5, PUSH_Direct, BC) op(0xc6, ADD_Direct_Data, A) + op(0xc7, RST_Implied, 0x00) op(0xc8, RET_Condition, ZF == 1) + op(0xc9, RET) + op(0xca, JP_Condition_Address, ZF == 1) op(0xcb, CB) + op(0xcc, CALL_Condition_Address, ZF == 1) + op(0xcd, CALL_Condition_Address, 1) op(0xce, ADC_Direct_Data, A) + op(0xcf, RST_Implied, 0x08) op(0xd0, RET_Condition, CF == 0) + op(0xd1, POP_Direct, DE) + op(0xd2, JP_Condition_Address, CF == 0) + op(0xd4, CALL_Condition_Address, CF == 0) + op(0xd5, PUSH_Direct, DE) op(0xd6, SUB_Direct_Data, A) + op(0xd7, RST_Implied, 0x10) op(0xd8, RET_Condition, CF == 1) + op(0xd9, RETI) + op(0xda, JP_Condition_Address, CF == 1) + op(0xdc, CALL_Condition_Address, CF == 1) op(0xde, SBC_Direct_Data, A) - op(0xe2, LD_Indirect_Direct, C, A) + op(0xdf, RST_Implied, 0x18) + op(0xe0, LDH_Address_Direct, A) + op(0xe1, POP_Direct, HL) + op(0xe2, LDH_Indirect_Direct, C, A) + op(0xe5, PUSH_Direct, HL) op(0xe6, AND_Direct_Data, A) + op(0xe7, RST_Implied, 0x20) + op(0xe8, ADD_Direct_Relative, SP) + op(0xe9, JP_Direct, HL) + op(0xea, LD_Address_Direct, A) op(0xee, XOR_Direct_Data, A) - op(0xf2, LD_Direct_Indirect, A, C) + op(0xef, RST_Implied, 0x28) + op(0xf0, LDH_Direct_Address, A) + op(0xf1, POP_Direct, AF) + op(0xf2, LDH_Direct_Indirect, A, C) op(0xf3, DI) + op(0xf5, PUSH_Direct, AF) op(0xf6, OR_Direct_Data, A) + op(0xf7, RST_Implied, 0x30) + op(0xf8, LD_Direct_DirectRelative, HL, SP) + op(0xf9, LD_Direct_Direct, SP, HL) + op(0xfa, LD_Direct_Address, A) op(0xfb, EI) op(0xfe, CP_Direct_Data, A) + op(0xff, RST_Implied, 0x38) } } auto LR35902::instructionCB() -> void { - switch(auto opcode = operand()) { + auto opcode = operand(); + + switch(opcode) { + op(0x00, RLC_Direct, B) + op(0x01, RLC_Direct, C) + op(0x02, RLC_Direct, D) + op(0x03, RLC_Direct, E) + op(0x04, RLC_Direct, H) + op(0x05, RLC_Direct, L) + op(0x06, RLC_Indirect, HL) + op(0x07, RLC_Direct, A) + op(0x08, RRC_Direct, B) + op(0x09, RRC_Direct, C) + op(0x0a, RRC_Direct, D) + op(0x0b, RRC_Direct, E) + op(0x0c, RRC_Direct, H) + op(0x0d, RRC_Direct, L) + op(0x0e, RRC_Indirect, HL) + op(0x0f, RRC_Direct, A) + op(0x10, RL_Direct, B) + op(0x11, RL_Direct, C) + op(0x12, RL_Direct, D) + op(0x13, RL_Direct, E) + op(0x14, RL_Direct, H) + op(0x15, RL_Direct, L) + op(0x16, RL_Indirect, HL) + op(0x17, RL_Direct, A) + op(0x18, RR_Direct, B) + op(0x19, RR_Direct, C) + op(0x1a, RR_Direct, D) + op(0x1b, RR_Direct, E) + op(0x1c, RR_Direct, H) + op(0x1d, RR_Direct, L) + op(0x1e, RR_Indirect, HL) + op(0x1f, RR_Direct, A) + op(0x20, SLA_Direct, B) + op(0x21, SLA_Direct, C) + op(0x22, SLA_Direct, D) + op(0x23, SLA_Direct, E) + op(0x24, SLA_Direct, H) + op(0x25, SLA_Direct, L) + op(0x26, SLA_Indirect, HL) + op(0x27, SLA_Direct, A) + op(0x28, SRA_Direct, B) + op(0x29, SRA_Direct, C) + op(0x2a, SRA_Direct, D) + op(0x2b, SRA_Direct, E) + op(0x2c, SRA_Direct, H) + op(0x2d, SRA_Direct, L) + op(0x2e, SRA_Indirect, HL) + op(0x2f, SRA_Direct, A) + op(0x30, SWAP_Direct, B) + op(0x31, SWAP_Direct, C) + op(0x32, SWAP_Direct, D) + op(0x33, SWAP_Direct, E) + op(0x34, SWAP_Direct, H) + op(0x35, SWAP_Direct, L) + op(0x36, SWAP_Indirect, HL) + op(0x37, SWAP_Direct, A) + op(0x38, SRL_Direct, B) + op(0x39, SRL_Direct, C) + op(0x3a, SRL_Direct, D) + op(0x3b, SRL_Direct, E) + op(0x3c, SRL_Direct, H) + op(0x3d, SRL_Direct, L) + op(0x3e, SRL_Indirect, HL) + op(0x3f, SRL_Direct, A) + } + + //opcodes 0x40-0xff [op(0x00 - 0x07) declared above] + uint3 bit = opcode.bits(3,5); + switch(opcode.bits(6,7) << 3 | opcode.bits(0,2)) { + op(0x08, BIT_Index_Direct, bit, B) + op(0x09, BIT_Index_Direct, bit, C) + op(0x0a, BIT_Index_Direct, bit, D) + op(0x0b, BIT_Index_Direct, bit, E) + op(0x0c, BIT_Index_Direct, bit, H) + op(0x0d, BIT_Index_Direct, bit, L) + op(0x0e, BIT_Index_Indirect, bit, HL) + op(0x0f, BIT_Index_Direct, bit, A) + op(0x10, RES_Index_Direct, bit, B) + op(0x11, RES_Index_Direct, bit, C) + op(0x12, RES_Index_Direct, bit, D) + op(0x13, RES_Index_Direct, bit, E) + op(0x14, RES_Index_Direct, bit, H) + op(0x15, RES_Index_Direct, bit, L) + op(0x16, RES_Index_Indirect, bit, HL) + op(0x17, RES_Index_Direct, bit, A) + op(0x18, SET_Index_Direct, bit, B) + op(0x19, SET_Index_Direct, bit, C) + op(0x1a, SET_Index_Direct, bit, D) + op(0x1b, SET_Index_Direct, bit, E) + op(0x1c, SET_Index_Direct, bit, H) + op(0x1d, SET_Index_Direct, bit, L) + op(0x1e, SET_Index_Indirect, bit, HL) + op(0x1f, SET_Index_Direct, bit, A) } } diff --git a/higan/processor/lr35902/instructions.cpp b/higan/processor/lr35902/instructions.cpp index ac574c71..8050c2c5 100644 --- a/higan/processor/lr35902/instructions.cpp +++ b/higan/processor/lr35902/instructions.cpp @@ -1,13 +1,13 @@ auto LR35902::instructionADC_Direct_Data(uint8& target) -> void { - target = ADC(target, operand()); + target = ADD(target, operand(), CF); } auto LR35902::instructionADC_Direct_Direct(uint8& target, uint8& source) -> void { - target = ADC(target, source); + target = ADD(target, source, CF); } auto LR35902::instructionADC_Direct_Indirect(uint8& target, uint16& source) -> void { - target = ADC(target, read(source)); + target = ADD(target, read(source), CF); } auto LR35902::instructionADD_Direct_Data(uint8& target) -> void { @@ -32,6 +32,16 @@ auto LR35902::instructionADD_Direct_Indirect(uint8& target, uint16& source) -> v target = ADD(target, read(source)); } +auto LR35902::instructionADD_Direct_Relative(uint16& target) -> void { + auto data = operand(); + idle(); + idle(); + CF = (uint8)target + (uint8)data > 0xff; + HF = (uint4)target + (uint4)data > 0x0f; + NF = ZF = 0; + target += (int8)data; +} + auto LR35902::instructionAND_Direct_Data(uint8& target) -> void { target = AND(target, operand()); } @@ -44,6 +54,23 @@ auto LR35902::instructionAND_Direct_Indirect(uint8& target, uint16& source) -> v target = AND(target, read(source)); } +auto LR35902::instructionBIT_Index_Direct(uint3 index, uint8& data) -> void { + BIT(index, data); +} + +auto LR35902::instructionBIT_Index_Indirect(uint3 index, uint16& address) -> void { + auto data = read(address); + BIT(index, data); +} + +auto LR35902::instructionCALL_Condition_Address(bool take) -> void { + auto address = operands(); + if(!take) return; + idle(); + push(PC); + PC = address; +} + auto LR35902::instructionCCF() -> void { CF = !CF; HF = NF = 0; @@ -84,24 +111,18 @@ auto LR35902::instructionDAA() -> void { ZF = A == 0; } -auto LR35902::instructionDEC_Direct(uint8& target) -> void { - target--; - HF = (uint4)target == 15; - NF = 0; - ZF = target == 0; +auto LR35902::instructionDEC_Direct(uint8& data) -> void { + data = DEC(data); } -auto LR35902::instructionDEC_Direct(uint16& target) -> void { +auto LR35902::instructionDEC_Direct(uint16& data) -> void { idle(); - target--; + data--; } -auto LR35902::instructionDEC_Indirect(uint16& target) -> void { - auto data = read(target); - write(target, ++data); - HF = (uint4)data == 15; - NF = 0; - ZF = data == 0; +auto LR35902::instructionDEC_Indirect(uint16& address) -> void { + auto data = read(address); + write(address, DEC(data)); } auto LR35902::instructionDI() -> void { @@ -117,24 +138,29 @@ auto LR35902::instructionHALT() -> void { while(r.halt) idle(); } -auto LR35902::instructionINC_Direct(uint8& target) -> void { - target++; - HF = (uint4)target == 0; - NF = 0; - ZF = target == 0; +auto LR35902::instructionINC_Direct(uint8& data) -> void { + data = INC(data); } -auto LR35902::instructionINC_Direct(uint16& target) -> void { +auto LR35902::instructionINC_Direct(uint16& data) -> void { idle(); - target++; + data++; } -auto LR35902::instructionINC_Indirect(uint16& target) -> void { - auto data = read(target); - write(target, ++data); - HF = (uint4)data == 0; - NF = 0; - ZF = data == 0; +auto LR35902::instructionINC_Indirect(uint16& address) -> void { + auto data = read(address); + write(address, INC(data)); +} + +auto LR35902::instructionJP_Condition_Address(bool take) -> void { + auto address = operands(); + if(!take) return; + idle(); + PC = address; +} + +auto LR35902::instructionJP_Direct(uint16& data) -> void { + PC = data; } auto LR35902::instructionJR_Condition_Relative(bool take) -> void { @@ -144,10 +170,18 @@ auto LR35902::instructionJR_Condition_Relative(bool take) -> void { PC += (int8)data; } +auto LR35902::instructionLD_Address_Direct(uint8& data) -> void { + write(operands(), data); +} + auto LR35902::instructionLD_Address_Direct(uint16& data) -> void { store(operands(), data); } +auto LR35902::instructionLD_Direct_Address(uint8& data) -> void { + data = read(operands()); +} + auto LR35902::instructionLD_Direct_Data(uint8& target) -> void { target = operand(); } @@ -160,8 +194,18 @@ auto LR35902::instructionLD_Direct_Direct(uint8& target, uint8& source) -> void target = source; } -auto LR35902::instructionLD_Direct_Indirect(uint8& target, uint8& source) -> void { - target = read(0xff00 | source); +auto LR35902::instructionLD_Direct_Direct(uint16& target, uint16& source) -> void { + idle(); + target = source; +} + +auto LR35902::instructionLD_Direct_DirectRelative(uint16& target, uint16& source) -> void { + auto data = operand(); + idle(); + CF = (uint8)source + (uint8)data > 0xff; + HF = (uint4)source + (uint4)data > 0x0f; + NF = ZF = 0; + target = source + (int8)data; } auto LR35902::instructionLD_Direct_Indirect(uint8& target, uint16& source) -> void { @@ -180,10 +224,6 @@ auto LR35902::instructionLD_Indirect_Data(uint16& target) -> void { write(target, operand()); } -auto LR35902::instructionLD_Indirect_Direct(uint8& target, uint8& source) -> void { - write(0xff00 | target, source); -} - auto LR35902::instructionLD_Indirect_Direct(uint16& target, uint8& source) -> void { write(target, source); } @@ -196,6 +236,22 @@ auto LR35902::instructionLD_IndirectIncrement_Direct(uint16& target, uint8& sour write(target++, source); } +auto LR35902::instructionLDH_Address_Direct(uint8& data) -> void { + write(0xff00 | operand(), data); +} + +auto LR35902::instructionLDH_Direct_Address(uint8& data) -> void { + data = read(0xff00 | operand()); +} + +auto LR35902::instructionLDH_Direct_Indirect(uint8& target, uint8& source) -> void { + target = read(0xff00 | source); +} + +auto LR35902::instructionLDH_Indirect_Direct(uint8& target, uint8& source) -> void { + write(0xff00 | target, source); +} + auto LR35902::instructionNOP() -> void { } @@ -211,6 +267,31 @@ auto LR35902::instructionOR_Direct_Indirect(uint8& target, uint16& source) -> vo target = OR(target, read(source)); } +auto LR35902::instructionPOP_Direct(uint16& data) -> void { + data = pop(); +} + +auto LR35902::instructionPUSH_Direct(uint16& data) -> void { + idle(); + push(data); +} + +auto LR35902::instructionRES_Index_Direct(uint3 index, uint8& data) -> void { + data.bit(index) = 0; +} + +auto LR35902::instructionRES_Index_Indirect(uint3 index, uint16& address) -> void { + auto data = read(address); + data.bit(index) = 0; + write(address, data); +} + +auto LR35902::instructionRET() -> void { + auto address = pop(); + idle(); + PC = address; +} + auto LR35902::instructionRET_Condition(bool take) -> void { idle(); if(!take) return; @@ -218,42 +299,85 @@ auto LR35902::instructionRET_Condition(bool take) -> void { idle(); } +auto LR35902::instructionRETI() -> void { + auto address = pop(); + idle(); + PC = address; + r.ime = 1; +} + auto LR35902::instructionRL_Direct(uint8& data) -> void { - bool carry = data.bit(7); - data = data << 1 | CF; - CF = carry; - HF = NF = ZF = 0; + data = RL(data); +} + +auto LR35902::instructionRL_Indirect(uint16& address) -> void { + auto data = read(address); + write(address, RL(data)); +} + +auto LR35902::instructionRLA() -> void { + A = RL(A); + ZF = 0; } auto LR35902::instructionRLC_Direct(uint8& data) -> void { - data = data << 1 | data >> 7; - CF = data.bit(0); - HF = NF = ZF = 0; + data = RLC(data); +} + +auto LR35902::instructionRLC_Indirect(uint16& address) -> void { + auto data = read(address); + write(address, RLC(data)); +} + +auto LR35902::instructionRLCA() -> void { + A = RLC(A); + ZF = 0; } auto LR35902::instructionRR_Direct(uint8& data) -> void { - bool carry = data.bit(0); - data = data >> 1 | CF << 7; - CF = carry; - HF = NF = ZF = 0; + data = RR(data); +} + +auto LR35902::instructionRR_Indirect(uint16& address) -> void { + auto data = read(address); + write(address, RR(data)); +} + +auto LR35902::instructionRRA() -> void { + A = RR(A); + ZF = 0; } auto LR35902::instructionRRC_Direct(uint8& data) -> void { - data = data >> 1 | data << 7; - CF = data.bit(7); - HF = NF = ZF = 0; + data = RRC(data); +} + +auto LR35902::instructionRRC_Indirect(uint16& address) -> void { + auto data = read(address); + write(address, RRC(data)); +} + +auto LR35902::instructionRRCA() -> void { + A = RRC(A); + ZF = 0; +} + +auto LR35902::instructionRST_Implied(uint8 vector) -> void { + idle(); + push(PC); + PC = vector; } auto LR35902::instructionSBC_Direct_Data(uint8& target) -> void { - target = SBC(target, operand()); + target = SUB(target, operand(), CF); } auto LR35902::instructionSBC_Direct_Direct(uint8& target, uint8& source) -> void { - target = SBC(target, source); + target = SUB(target, source, CF); } auto LR35902::instructionSBC_Direct_Indirect(uint8& target, uint16& source) -> void { - target = SBC(target, read(source)); + target = SUB(target, read(source), CF); } auto LR35902::instructionSCF() -> void { @@ -261,6 +385,43 @@ auto LR35902::instructionSCF() -> void { HF = NF = 0; } +auto LR35902::instructionSET_Index_Direct(uint3 index, uint8& data) -> void { + data.bit(index) = 1; +} + +auto LR35902::instructionSET_Index_Indirect(uint3 index, uint16& address) -> void { + auto data = read(address); + data.bit(index) = 1; + write(address, data); +} + +auto LR35902::instructionSLA_Direct(uint8& data) -> void { + data = SLA(data); +} + +auto LR35902::instructionSLA_Indirect(uint16& address) -> void { + auto data = read(address); + write(address, SLA(data)); +} + +auto LR35902::instructionSRA_Direct(uint8& data) -> void { + data = SRA(data); +} + +auto LR35902::instructionSRA_Indirect(uint16& address) -> void { + auto data = read(address); + write(address, SRA(data)); +} + +auto LR35902::instructionSRL_Direct(uint8& data) -> void { + data = SRL(data); +} + +auto LR35902::instructionSRL_Indirect(uint16& address) -> void { + auto data = read(address); + write(address, SRL(data)); +} + auto LR35902::instructionSTOP() -> void { if(stop()) return; r.stop = 1; @@ -279,6 +440,15 @@ auto LR35902::instructionSUB_Direct_Indirect(uint8& target, uint16& source) -> v target = SUB(target, read(source)); } +auto LR35902::instructionSWAP_Direct(uint8& data) -> void { + data = SWAP(data); +} + +auto LR35902::instructionSWAP_Indirect(uint16& address) -> void { + auto data = read(address); + write(address, SWAP(data)); +} + auto LR35902::instructionXOR_Direct_Data(uint8& target) -> void { target = XOR(target, operand()); } diff --git a/higan/processor/lr35902/lr35902.cpp b/higan/processor/lr35902/lr35902.cpp index f3d6a5d5..c16ef803 100644 --- a/higan/processor/lr35902/lr35902.cpp +++ b/higan/processor/lr35902/lr35902.cpp @@ -9,6 +9,7 @@ namespace Processor { #include "instruction.cpp" #include "instructions.cpp" #include "serialization.cpp" +#include "disassembler.cpp" auto LR35902::power() -> void { r = {}; diff --git a/higan/processor/lr35902/lr35902.hpp b/higan/processor/lr35902/lr35902.hpp index 9bf60d37..323e431c 100644 --- a/higan/processor/lr35902/lr35902.hpp +++ b/higan/processor/lr35902/lr35902.hpp @@ -23,7 +23,7 @@ struct LR35902 { //disassembler.cpp virtual auto readDebugger(uint16 address) -> uint8 { return 0; } - auto disassemble() -> string { return ""; } + auto disassemble(uint16 pc) -> string; //memory.cpp auto operand() -> uint8; @@ -34,13 +34,22 @@ struct LR35902 { auto push(uint16 data) -> void; //algorithms.cpp - auto ADC(uint8, uint8) -> uint8; - auto ADD(uint8, uint8) -> uint8; + auto ADD(uint8, uint8, bool = 0) -> uint8; auto AND(uint8, uint8) -> uint8; + auto BIT(uint3, uint8) -> void; auto CP(uint8, uint8) -> void; + auto DEC(uint8) -> uint8; + auto INC(uint8) -> uint8; auto OR(uint8, uint8) -> uint8; - auto SBC(uint8, uint8) -> uint8; - auto SUB(uint8, uint8) -> uint8; + auto RL(uint8) -> uint8; + auto RLC(uint8) -> uint8; + auto RR(uint8) -> uint8; + auto RRC(uint8) -> uint8; + auto SLA(uint8) -> uint8; + auto SRA(uint8) -> uint8; + auto SRL(uint8) -> uint8; + auto SUB(uint8, uint8, bool = 0) -> uint8; + auto SWAP(uint8) -> uint8; auto XOR(uint8, uint8) -> uint8; //instructions.cpp @@ -51,9 +60,13 @@ struct LR35902 { auto instructionADD_Direct_Direct(uint8&, uint8&) -> void; auto instructionADD_Direct_Direct(uint16&, uint16&) -> void; auto instructionADD_Direct_Indirect(uint8&, uint16&) -> void; + auto instructionADD_Direct_Relative(uint16&) -> void; auto instructionAND_Direct_Data(uint8&) -> void; auto instructionAND_Direct_Direct(uint8&, uint8&) -> void; auto instructionAND_Direct_Indirect(uint8&, uint16&) -> void; + auto instructionBIT_Index_Direct(uint3, uint8&) -> void; + auto instructionBIT_Index_Indirect(uint3, uint16&) -> void; + auto instructionCALL_Condition_Address(bool) -> void; auto instructionCCF() -> void; auto instructionCP_Direct_Data(uint8&) -> void; auto instructionCP_Direct_Direct(uint8&, uint8&) -> void; @@ -69,36 +82,69 @@ struct LR35902 { auto instructionINC_Direct(uint8&) -> void; auto instructionINC_Direct(uint16&) -> void; auto instructionINC_Indirect(uint16&) -> void; + auto instructionJP_Condition_Address(bool) -> void; + auto instructionJP_Direct(uint16&) -> void; auto instructionJR_Condition_Relative(bool) -> void; + auto instructionLD_Address_Direct(uint8&) -> void; auto instructionLD_Address_Direct(uint16&) -> void; + auto instructionLD_Direct_Address(uint8&) -> void; auto instructionLD_Direct_Data(uint8&) -> void; auto instructionLD_Direct_Data(uint16&) -> void; auto instructionLD_Direct_Direct(uint8&, uint8&) -> void; - auto instructionLD_Direct_Indirect(uint8&, uint8&) -> void; + auto instructionLD_Direct_Direct(uint16&, uint16&) -> void; + auto instructionLD_Direct_DirectRelative(uint16&, uint16&) -> void; auto instructionLD_Direct_Indirect(uint8&, uint16&) -> void; auto instructionLD_Direct_IndirectDecrement(uint8&, uint16&) -> void; auto instructionLD_Direct_IndirectIncrement(uint8&, uint16&) -> void; auto instructionLD_Indirect_Data(uint16&) -> void; - auto instructionLD_Indirect_Direct(uint8&, uint8&) -> void; auto instructionLD_Indirect_Direct(uint16&, uint8&) -> void; auto instructionLD_IndirectDecrement_Direct(uint16&, uint8&) -> void; auto instructionLD_IndirectIncrement_Direct(uint16&, uint8&) -> void; + auto instructionLDH_Address_Direct(uint8&) -> void; + auto instructionLDH_Direct_Address(uint8&) -> void; + auto instructionLDH_Direct_Indirect(uint8&, uint8&) -> void; + auto instructionLDH_Indirect_Direct(uint8&, uint8&) -> void; auto instructionNOP() -> void; auto instructionOR_Direct_Data(uint8&) -> void; auto instructionOR_Direct_Direct(uint8&, uint8&) -> void; auto instructionOR_Direct_Indirect(uint8&, uint16&) -> void; + auto instructionPOP_Direct(uint16&) -> void; + auto instructionPUSH_Direct(uint16&) -> void; + auto instructionRES_Index_Direct(uint3, uint8&) -> void; + auto instructionRES_Index_Indirect(uint3, uint16&) -> void; + auto instructionRET() -> void; auto instructionRET_Condition(bool) -> void; + auto instructionRETI() -> void; auto instructionRL_Direct(uint8&) -> void; + auto instructionRL_Indirect(uint16&) -> void; + auto instructionRLA() -> void; auto instructionRLC_Direct(uint8&) -> void; + auto instructionRLC_Indirect(uint16&) -> void; + auto instructionRLCA() -> void; auto instructionRR_Direct(uint8&) -> void; + auto instructionRR_Indirect(uint16&) -> void; + auto instructionRRA() -> void; auto instructionRRC_Direct(uint8&) -> void; + auto instructionRRC_Indirect(uint16&) -> void; + auto instructionRRCA() -> void; + auto instructionRST_Implied(uint8) -> void; auto instructionSBC_Direct_Data(uint8&) -> void; auto instructionSBC_Direct_Direct(uint8&, uint8&) -> void; auto instructionSBC_Direct_Indirect(uint8&, uint16&) -> void; auto instructionSCF() -> void; + auto instructionSET_Index_Direct(uint3, uint8&) -> void; + auto instructionSET_Index_Indirect(uint3, uint16&) -> void; + auto instructionSLA_Direct(uint8&) -> void; + auto instructionSLA_Indirect(uint16&) -> void; + auto instructionSRA_Direct(uint8&) -> void; + auto instructionSRA_Indirect(uint16&) -> void; + auto instructionSRL_Direct(uint8&) -> void; + auto instructionSRL_Indirect(uint16&) -> void; auto instructionSUB_Direct_Data(uint8&) -> void; auto instructionSUB_Direct_Direct(uint8&, uint8&) -> void; auto instructionSUB_Direct_Indirect(uint8&, uint16&) -> void; + auto instructionSWAP_Direct(uint8& data) -> void; + auto instructionSWAP_Indirect(uint16& address) -> void; auto instructionSTOP() -> void; auto instructionXOR_Direct_Data(uint8&) -> void; auto instructionXOR_Direct_Direct(uint8&, uint8&) -> void; @@ -123,6 +169,10 @@ struct LR35902 { uint1 stop; uint1 ime; } r; + + //disassembler.cpp + auto disassembleOpcode(uint16 pc) -> string; + auto disassembleOpcodeCB(uint16 pc) -> string; }; }