diff --git a/higan/data/higan.plist b/higan/data/higan.plist index 6d59f131..53d81b52 100644 --- a/higan/data/higan.plist +++ b/higan/data/higan.plist @@ -11,7 +11,7 @@ CFBundleIconFile higan.icns NSHighResolutionCapable - + NSSupportsAutomaticGraphicsSwitching diff --git a/higan/emulator/emulator.hpp b/higan/emulator/emulator.hpp index afc938af..4a87e31e 100644 --- a/higan/emulator/emulator.hpp +++ b/higan/emulator/emulator.hpp @@ -6,7 +6,7 @@ using namespace nall; namespace Emulator { static const string Name = "higan"; - static const string Version = "097.05"; + static const string Version = "097.06"; static const string Author = "byuu"; static const string License = "GPLv3"; static const string Website = "http://byuu.org/"; diff --git a/higan/processor/v30mz/algorithms.cpp b/higan/processor/v30mz/algorithms.cpp index a1e2f784..4af15058 100644 --- a/higan/processor/v30mz/algorithms.cpp +++ b/higan/processor/v30mz/algorithms.cpp @@ -7,24 +7,15 @@ auto V30MZ::parity(uint16 value) const -> bool { return !(value & 1); } -auto V30MZ::albAnd(uint8 x, uint8 y) -> uint8 { - uint8 result = x & y; +auto V30MZ::alAnd(Size size, uint16 x, uint16 y) -> uint16 { + uint16 bits = size == Byte ? 0xff : 0xffff; + uint16 mask = size == Byte ? 0x80 : 0x8000; + uint16 result = (x & y) & bits; r.f.c = 0; r.f.p = parity(result); r.f.h = 0; r.f.z = result == 0; - r.f.s = result & 0x80; - r.f.v = 0; - return result; -} - -auto V30MZ::alwAnd(uint16 x, uint16 y) -> uint16 { - uint16 result = x & y; - r.f.c = 0; - r.f.p = parity(result); - r.f.h = 0; - r.f.z = result == 0; - r.f.s = result & 0x8000; + r.f.s = result & mask; r.f.v = 0; return result; } diff --git a/higan/processor/v30mz/disassembler.cpp b/higan/processor/v30mz/disassembler.cpp index 7a87fdf1..80599369 100644 --- a/higan/processor/v30mz/disassembler.cpp +++ b/higan/processor/v30mz/disassembler.cpp @@ -36,66 +36,90 @@ auto V30MZ::disassemble(uint16 cs, uint16 ip, bool registers) -> string { if((modRM & 0xc0) == 0x80) return {d, ",[", mem[modRM & 7], "+", readWord(offset), "]"}; return {d, ",[", mem[modRM & 7], "]"}; }; + auto readRepeat = [&](uint offset) -> string { + uint8 opcode = read((cs << 4) + (uint16)(ip + offset++)); + switch(opcode) { + case 0x6c: return "insb"; + case 0x6d: return "insw"; + case 0x6e: return "outsb"; + case 0x6f: return "outsw"; + case 0xa4: return "movsb"; + case 0xa5: return "movsw"; + case 0xa6: return "cmpsb"; + case 0xa7: return "cmpsw"; + case 0xaa: return "stosb"; + case 0xab: return "stosw"; + case 0xac: return "lodsb"; + case 0xad: return "lodsw"; + case 0xae: return "scasb"; + case 0xaf: return "scasw"; + } + return ""; + }; - uint8 opcode = read(ea); + auto opcode = read(ea); switch(opcode) { - case 0x22: s = {"xor ", readModRM(1, Byte)}; break; - case 0x33: s = {"xor ", readModRM(1, Word)}; break; - case 0x70: s = {"jo ", readRelativeByte(1, 2)}; break; - case 0x71: s = {"jno ", readRelativeByte(1, 2)}; break; - case 0x72: s = {"jc ", readRelativeByte(1, 2)}; break; - case 0x73: s = {"jnc ", readRelativeByte(1, 2)}; break; - case 0x74: s = {"jz ", readRelativeByte(1, 2)}; break; - case 0x75: s = {"jnz ", readRelativeByte(1, 2)}; break; - case 0x76: s = {"jcz ", readRelativeByte(1, 2)}; break; - case 0x77: s = {"jncz ", readRelativeByte(1, 2)}; break; - case 0x78: s = {"js ", readRelativeByte(1, 2)}; break; - case 0x79: s = {"jns ", readRelativeByte(1, 2)}; break; - case 0x7a: s = {"jp ", readRelativeByte(1, 2)}; break; - case 0x7b: s = {"jnp ", readRelativeByte(1, 2)}; break; - case 0x7c: s = {"jl ", readRelativeByte(1, 2)}; break; - case 0x7d: s = {"jnl ", readRelativeByte(1, 2)}; break; - case 0x7e: s = {"jle ", readRelativeByte(1, 2)}; break; - case 0x7f: s = {"jnle ", readRelativeByte(1, 2)}; break; - case 0x8a: s = {"mov ", readModRM(1, Byte)}; break; - case 0x8b: s = {"mov ", readModRM(1, Word)}; break; - case 0x8e: s = {"mov ", readModRM(1, Segment)}; break; - case 0x90: s = {"nop "}; break; - case 0xa8: s = {"test al,", readByte(1)}; break; - case 0xa9: s = {"test ax,", readWord(1)}; break; - case 0xb0: s = {"mov al,", readByte(1)}; break; - case 0xb1: s = {"mov cl,", readByte(1)}; break; - case 0xb2: s = {"mov dl,", readByte(1)}; break; - case 0xb3: s = {"mov bl,", readByte(1)}; break; - case 0xb4: s = {"mov ah,", readByte(1)}; break; - case 0xb5: s = {"mov ch,", readByte(1)}; break; - case 0xb6: s = {"mov dh,", readByte(1)}; break; - case 0xb7: s = {"mov bh,", readByte(1)}; break; - case 0xb8: s = {"mov ax,", readWord(1)}; break; - case 0xb9: s = {"mov cx,", readWord(1)}; break; - case 0xba: s = {"mov dx,", readWord(1)}; break; - case 0xbb: s = {"mov bx,", readWord(1)}; break; - case 0xbc: s = {"mov sp,", readWord(1)}; break; - case 0xbd: s = {"mov bp,", readWord(1)}; break; - case 0xbe: s = {"mov si,", readWord(1)}; break; - case 0xbf: s = {"mov di,", readWord(1)}; break; - case 0xc3: s = {"ret "}; break; - case 0xe4: s = {"in al,", readByte(1)}; break; - case 0xe5: s = {"in ax,", readByte(1)}; break; - case 0xe6: s = {"out ", readByte(1), ",al"}; break; - case 0xe7: s = {"out ", readByte(1), ",ax"}; break; - case 0xe8: s = {"call ", readRelativeWord(1, 3)}; break; - case 0xea: s = {"jmp ", readWord(3), ":", readWord(1)}; break; - case 0xec: s = {"in al,dx"}; break; - case 0xed: s = {"in ax,dx"}; break; - case 0xee: s = {"out dx,al"}; break; - case 0xef: s = {"out dx,ax"}; break; - case 0xf8: s = {"clc "}; break; - case 0xf9: s = {"stc "}; break; - case 0xfa: s = {"cli "}; break; - case 0xfb: s = {"sti "}; break; - case 0xfc: s = {"cld "}; break; - case 0xfd: s = {"std "}; break; + case 0x22: s = {"xor ", readModRM(1, Byte)}; break; + case 0x33: s = {"xor ", readModRM(1, Word)}; break; + case 0x70: s = {"jo ", readRelativeByte(1, 2)}; break; + case 0x71: s = {"jno ", readRelativeByte(1, 2)}; break; + case 0x72: s = {"jc ", readRelativeByte(1, 2)}; break; + case 0x73: s = {"jnc ", readRelativeByte(1, 2)}; break; + case 0x74: s = {"jz ", readRelativeByte(1, 2)}; break; + case 0x75: s = {"jnz ", readRelativeByte(1, 2)}; break; + case 0x76: s = {"jcz ", readRelativeByte(1, 2)}; break; + case 0x77: s = {"jncz ", readRelativeByte(1, 2)}; break; + case 0x78: s = {"js ", readRelativeByte(1, 2)}; break; + case 0x79: s = {"jns ", readRelativeByte(1, 2)}; break; + case 0x7a: s = {"jp ", readRelativeByte(1, 2)}; break; + case 0x7b: s = {"jnp ", readRelativeByte(1, 2)}; break; + case 0x7c: s = {"jl ", readRelativeByte(1, 2)}; break; + case 0x7d: s = {"jnl ", readRelativeByte(1, 2)}; break; + case 0x7e: s = {"jle ", readRelativeByte(1, 2)}; break; + case 0x7f: s = {"jnle ", readRelativeByte(1, 2)}; break; + case 0x8a: s = {"mov ", readModRM(1, Byte)}; break; + case 0x8b: s = {"mov ", readModRM(1, Word)}; break; + case 0x8e: s = {"mov ", readModRM(1, Segment)}; break; + case 0x90: s = {"nop "}; break; + case 0xa4: s = {"movsb "}; break; + case 0xa5: s = {"movsw "}; break; + case 0xa8: s = {"test al,", readByte(1)}; break; + case 0xa9: s = {"test ax,", readWord(1)}; break; + case 0xb0: s = {"mov al,", readByte(1)}; break; + case 0xb1: s = {"mov cl,", readByte(1)}; break; + case 0xb2: s = {"mov dl,", readByte(1)}; break; + case 0xb3: s = {"mov bl,", readByte(1)}; break; + case 0xb4: s = {"mov ah,", readByte(1)}; break; + case 0xb5: s = {"mov ch,", readByte(1)}; break; + case 0xb6: s = {"mov dh,", readByte(1)}; break; + case 0xb7: s = {"mov bh,", readByte(1)}; break; + case 0xb8: s = {"mov ax,", readWord(1)}; break; + case 0xb9: s = {"mov cx,", readWord(1)}; break; + case 0xba: s = {"mov dx,", readWord(1)}; break; + case 0xbb: s = {"mov bx,", readWord(1)}; break; + case 0xbc: s = {"mov sp,", readWord(1)}; break; + case 0xbd: s = {"mov bp,", readWord(1)}; break; + case 0xbe: s = {"mov si,", readWord(1)}; break; + case 0xbf: s = {"mov di,", readWord(1)}; break; + case 0xc3: s = {"ret "}; break; + case 0xe4: s = {"in al,", readByte(1)}; break; + case 0xe5: s = {"in ax,", readByte(1)}; break; + case 0xe6: s = {"out ", readByte(1), ",al"}; break; + case 0xe7: s = {"out ", readByte(1), ",ax"}; break; + case 0xe8: s = {"call ", readRelativeWord(1, 3)}; break; + case 0xea: s = {"jmp ", readWord(3), ":", readWord(1)}; break; + case 0xec: s = {"in al,dx"}; break; + case 0xed: s = {"in ax,dx"}; break; + case 0xee: s = {"out dx,al"}; break; + case 0xef: s = {"out dx,ax"}; break; + case 0xf2: s = {"repnz ", readRepeat(1)}; break; + case 0xf3: s = {"repz ", readRepeat(1)}; break; + case 0xf8: s = {"clc "}; break; + case 0xf9: s = {"stc "}; break; + case 0xfa: s = {"cli "}; break; + case 0xfb: s = {"sti "}; break; + case 0xfc: s = {"cld "}; break; + case 0xfd: s = {"std "}; break; default: s = {"??? [", hex(opcode, 2L), "]"}; diff --git a/higan/processor/v30mz/instructions.cpp b/higan/processor/v30mz/instructions.cpp index 500b8d57..183f9e93 100644 --- a/higan/processor/v30mz/instructions.cpp +++ b/higan/processor/v30mz/instructions.cpp @@ -1,51 +1,44 @@ -auto V30MZ::opbXorRegisterModRM() { - auto md = readbIP(); - regb(md) ^= readbModRM(md); -} - -auto V30MZ::opwXorRegisterModRM() { - auto md = readbIP(); - regw(md) ^= readwModRM(md); +auto V30MZ::opXorRegisterModRM(Size size) { + auto modRM = readIP(); + setRegister(size, modRM, getRegister(size, modRM) ^ readModRM(size, modRM)); } auto V30MZ::opJumpIf(bool condition) { - auto displacement = (int8)readbIP(); + auto displacement = (int8)readIP(); if(condition) r.ip += displacement; } -auto V30MZ::opbMoveRegisterModRM() { - auto md = readbIP(); - regb(md) = readbModRM(md); -} - -auto V30MZ::opwMoveRegisterModRM() { - auto md = readbIP(); - regw(md) = readwModRM(md); +auto V30MZ::opMoveRegisterModRM(Size size) { + auto modRM = readIP(); + setRegister(size, modRM, readModRM(size, modRM)); } auto V30MZ::opMoveSegmentRegisterModRM() { wait(1); - auto md = readbIP(); - sreg(md) = readwModRM(md); + auto modRM = readIP(); + setSegment(modRM, readModRM(Word, modRM)); } auto V30MZ::opNoOperation() { } -auto V30MZ::opTestAL() { - albAnd(r.al, readbIP()); +auto V30MZ::opMoveString(Size size) { + wait(4); + write(size, r.es, r.di, read(size, r.ds, r.si)); + r.si += r.f.d ? -size : size; + r.di += r.f.d ? -size : size; } -auto V30MZ::opTestAX() { - alwAnd(r.ax, readwIP()); +auto V30MZ::opTestAX(Size size) { + alAnd(size, r.ax, readIP(size)); } -auto V30MZ::opbMoveRegisterImmediate(uint8& rd) { - rd = readbIP(); +auto V30MZ::opMoveRegisterImmediate(uint8& rd) { + rd = readIP(Byte); } -auto V30MZ::opwMoveRegisterImmediate(uint16& rd) { - rd = readwIP(); +auto V30MZ::opMoveRegisterImmediate(uint16& rd) { + rd = readIP(Word); } auto V30MZ::opReturn() { @@ -53,69 +46,69 @@ auto V30MZ::opReturn() { r.ip = readSP(); } -auto V30MZ::opbIn() { +auto V30MZ::opIn(Size size) { wait(5); - auto port = readbIP(); - r.al = in(port); + auto port = readIP(); + r.al = in(port++); + if(size != Word) return; + r.ah = in(port++); } -auto V30MZ::opwIn() { +auto V30MZ::opOut(Size size) { wait(5); - auto port = readbIP(); - r.al = in(port + 0); - r.ah = in(port + 1); -} - -auto V30MZ::opbOut() { - wait(5); - auto port = readbIP(); - out(port, r.al); -} - -auto V30MZ::opwOut() { - wait(5); - auto port = readbIP(); - out(port + 0, r.al); - out(port + 1, r.ah); + auto port = readIP(); + out(port++, r.al); + if(size != Word) return; + out(port++, r.ah); } auto V30MZ::opCallNear() { wait(4); - auto displacement = (int16)readwIP(); + auto displacement = (int16)readIP(Word); writeSP(r.ip); r.ip += displacement; } auto V30MZ::opJumpFar() { wait(6); - auto ip = readwIP(); - auto cs = readwIP(); + auto ip = readIP(Word); + auto cs = readIP(Word); r.ip = ip; r.cs = cs; } -auto V30MZ::opbInDX() { - wait(5); - r.al = in(r.dx); -} - -auto V30MZ::opwInDX() { +auto V30MZ::opInDX(Size size) { wait(5); r.al = in(r.dx + 0); + if(size != Word) return; r.ah = in(r.dx + 1); } -auto V30MZ::opbOutDX() { - wait(5); - out(r.dx, r.al); -} - -auto V30MZ::opwOutDX() { +auto V30MZ::opOutDX(Size size) { wait(5); out(r.dx + 0, r.al); + if(size != Word) return; out(r.dx + 1, r.ah); } +auto V30MZ::opRepeat(bool flag) { + wait(4); + auto opcode = readIP(); + if((opcode & 0xfc) != 0x6c && (opcode & 0xfc) != 0xa4 + && (opcode & 0xfe) != 0xaa && (opcode & 0xfc) != 0xac) { + //invalid argument + r.ip--; + return; + } + if(r.cx == 0) return; + r.cx--; + + switch(opcode) { + case 0xa4: opMoveString(Byte); r.ip -= 2; break; + case 0xa5: opMoveString(Word); r.ip -= 2; break; + } +} + auto V30MZ::opClearFlag(bool& flag) { wait(3); flag = false; diff --git a/higan/processor/v30mz/memory.cpp b/higan/processor/v30mz/memory.cpp index e9c11013..c3cb70e6 100644 --- a/higan/processor/v30mz/memory.cpp +++ b/higan/processor/v30mz/memory.cpp @@ -1,75 +1,58 @@ -auto V30MZ::readbIP() -> uint8 { - return read((r.cs << 4) + r.ip++); +auto V30MZ::read(Size size, uint16 segment, uint16 address) -> uint16 { + uint16 data = read(segment * 16 + address); + if(size == Word) data |= read(segment * 16 + ++address) << 8; + return data; } -auto V30MZ::readwIP() -> uint16 { - uint16 word = read((r.cs << 4) + r.ip++) << 0; - return word | read((r.cs << 4) + r.ip++) << 8; +auto V30MZ::write(Size size, uint16 segment, uint16 address, uint16 data) -> void { + write(segment * 16 + address, data); + if(size == Word) write(segment * 16 + ++address, data >> 8); +} + +// + +auto V30MZ::readIP(Size size) -> uint16 { + uint16 data = read(size, r.cs, r.ip); + return r.ip += size, data; } // auto V30MZ::readSP() -> uint16 { - uint16 word = read((r.ss << 4) + r.sp++) << 0; - return word | read((r.ss << 4) + r.sp++) << 8; + uint16 data = read(Word, r.ss, r.sp); + return r.sp += Word, data; } auto V30MZ::writeSP(uint16 data) -> void { - write((r.ss << 4) + --r.sp, data >> 8); - write((r.ss << 4) + --r.sp, data >> 0); + r.sp -= Word; + write(Word, r.ss, r.sp, data); } // -auto V30MZ::readb(uint20 ea) -> uint8 { - return read(ea++); -} +auto V30MZ::readModRM(uint8 modRM) -> uint32 { + if((modRM & 0xc7) == 0x06) return r.ds << 16 | readIP(Word); -auto V30MZ::readw(uint20 ea) -> uint16 { - uint16 word = read(ea++) << 0; - return word | read(ea++) << 8; -} - -// - -auto V30MZ::readb(uint16 rs, uint16 ea) -> uint8 { - return read((rs << 4) + ea++); -} - -auto V30MZ::readw(uint16 rs, uint16 ea) -> uint16 { - uint16 word = read((rs << 4) + ea++) << 0; - return word | read((rs << 4) + ea++) << 8; -} - -// - -//todo: return tuple -auto V30MZ::readModRM(uint8 modRM) -> uint20 { - if((modRM & 0xc7) == 0x06) return (r.ds << 4) + (int16)readwIP(); - - int16 displacement = 0; - if((modRM & 0xc0) == 0x40) displacement = (int8)readbIP(); - if((modRM & 0xc0) == 0x80) displacement = (int16)readwIP(); + uint16 s = 0, a = 0; + if((modRM & 0xc0) == 0x40) a = (int8)readIP(Byte); + if((modRM & 0xc0) == 0x80) a = (int16)readIP(Word); switch(modRM & 7) { - case 0: return (r.ds << 4) + r.bx + r.si + displacement; - case 1: return (r.ds << 4) + r.bx + r.di + displacement; - case 2: return (r.ss << 4) + r.bp + r.si + displacement; - case 3: return (r.ss << 4) + r.bp + r.di + displacement; - case 4: return (r.ds << 4) + r.si + displacement; - case 5: return (r.ds << 4) + r.di + displacement; - case 6: return (r.ss << 4) + r.bp + displacement; - case 7: return (r.ds << 4) + r.bx + displacement; + case 0: s = r.ds; a += r.bx + r.si; break; + case 1: s = r.ds; a += r.bx + r.di; break; + case 2: s = r.ss; a += r.bp + r.si; break; + case 3: s = r.ss; a += r.bp + r.di; break; + case 4: s = r.ds; a += r.si; break; + case 5: s = r.ds; a += r.di; break; + case 6: s = r.ss; a += r.bp; break; + case 7: s = r.ds; a += r.bx; break; } - unreachable; + + return s << 16 | a; } -auto V30MZ::readbModRM(uint8 modRM) -> uint8 { - if(modRM >= 0xc0) return regb(modRM); - return readb(readModRM(modRM)); -} - -auto V30MZ::readwModRM(uint8 modRM) -> uint16 { - if(modRM >= 0xc0) return regw(modRM); - return readw(readModRM(modRM)); +auto V30MZ::readModRM(Size size, uint8 modRM) -> uint16 { + if(modRM >= 0xc0) return getRegister(size, modRM); + auto addr = readModRM(modRM); + return read(size, addr >> 16, addr); } diff --git a/higan/processor/v30mz/registers.cpp b/higan/processor/v30mz/registers.cpp index c1771054..92921a2a 100644 --- a/higan/processor/v30mz/registers.cpp +++ b/higan/processor/v30mz/registers.cpp @@ -1,18 +1,32 @@ -auto V30MZ::regb(uint8 modRM) -> uint8& { - static uint8* p[] = {&r.al, &r.cl, &r.dl, &r.bl, &r.ah, &r.ch, &r.dh, &r.bh}; - return *p[(modRM >> 3) & 7]; +auto V30MZ::getRegister(Size size, uint8 modRM) -> uint16 { + static uint8* byte[] = {&r.al, &r.cl, &r.dl, &r.bl, &r.ah, &r.ch, &r.dh, &r.bh}; + static uint16* word[] = {&r.ax, &r.cx, &r.dx, &r.bx, &r.sp, &r.bp, &r.si, &r.di}; + if(size == Byte) return *byte[(modRM >> 3) & 7]; + if(size == Word) return *word[(modRM >> 3) & 7]; + throw; } -auto V30MZ::regw(uint8 modRM) -> uint16& { - static uint16* p[] = {&r.ax, &r.cx, &r.dx, &r.bx, &r.sp, &r.bp, &r.si, &r.di}; - return *p[(modRM >> 3) & 7]; +auto V30MZ::setRegister(Size size, uint8 modRM, uint16 data) -> void { + static uint8* byte[] = {&r.al, &r.cl, &r.dl, &r.bl, &r.ah, &r.ch, &r.dh, &r.bh}; + static uint16* word[] = {&r.ax, &r.cx, &r.dx, &r.bx, &r.sp, &r.bp, &r.si, &r.di}; + if(size == Byte) *byte[(modRM >> 3) & 7] = data; + if(size == Word) *word[(modRM >> 3) & 7] = data; } -auto V30MZ::sreg(uint8 modRM) -> uint16& { - static uint16* p[] = {&r.es, &r.cs, &r.ss, &r.ds}; - return *p[(modRM >> 3) & 3]; +// + +auto V30MZ::getSegment(uint8 modRM) -> uint16 { + static uint16* word[] = {&r.es, &r.cs, &r.ss, &r.ds}; + return *word[(modRM >> 3) & 3]; } +auto V30MZ::setSegment(uint8 modRM, uint16 data) -> void { + static uint16* word[] = {&r.es, &r.cs, &r.ss, &r.ds}; + *word[(modRM >> 3) & 3] = data; +} + +// + V30MZ::Registers::Flags::operator uint16() const { return m << 15 | 1 << 14 | 1 << 13 | 1 << 12 | v << 11 | d << 10 | i << 9 | b << 8 diff --git a/higan/processor/v30mz/v30mz.cpp b/higan/processor/v30mz/v30mz.cpp index 608ea94e..027d0588 100644 --- a/higan/processor/v30mz/v30mz.cpp +++ b/higan/processor/v30mz/v30mz.cpp @@ -3,6 +3,8 @@ namespace Processor { +const uint V30MZ::Byte = 1; +const uint V30MZ::Word = 2; #include "registers.cpp" #include "memory.cpp" #include "algorithms.cpp" @@ -22,12 +24,12 @@ auto V30MZ::exec() -> void { auto V30MZ::execOpcode() -> void { executed++; - uint8 opcode = readbIP(); + auto opcode = readIP(); wait(1); switch(opcode) { - case 0x32: return opbXorRegisterModRM(); - case 0x33: return opwXorRegisterModRM(); + case 0x32: return opXorRegisterModRM(Byte); + case 0x33: return opXorRegisterModRM(Word); case 0x70: return opJumpIf(r.f.v == 1); case 0x71: return opJumpIf(r.f.v == 0); case 0x72: return opJumpIf(r.f.c == 1); @@ -44,39 +46,43 @@ auto V30MZ::execOpcode() -> void { case 0x7d: return opJumpIf(r.f.s == r.f.v || r.f.z == 1); case 0x7e: return opJumpIf(r.f.s != r.f.v || r.f.z == 1); case 0x7f: return opJumpIf(r.f.s == r.f.v && r.f.z == 0); - case 0x8a: return opbMoveRegisterModRM(); - case 0x8b: return opwMoveRegisterModRM(); + case 0x8a: return opMoveRegisterModRM(Byte); + case 0x8b: return opMoveRegisterModRM(Word); case 0x8e: return opMoveSegmentRegisterModRM(); case 0x90: return opNoOperation(); - case 0xa8: return opTestAL(); - case 0xa9: return opTestAX(); - case 0xb0: return opbMoveRegisterImmediate(r.al); - case 0xb1: return opbMoveRegisterImmediate(r.cl); - case 0xb2: return opbMoveRegisterImmediate(r.dl); - case 0xb3: return opbMoveRegisterImmediate(r.bl); - case 0xb4: return opbMoveRegisterImmediate(r.ah); - case 0xb5: return opbMoveRegisterImmediate(r.ch); - case 0xb6: return opbMoveRegisterImmediate(r.dh); - case 0xb7: return opbMoveRegisterImmediate(r.bh); - case 0xb8: return opwMoveRegisterImmediate(r.ax); - case 0xb9: return opwMoveRegisterImmediate(r.cx); - case 0xba: return opwMoveRegisterImmediate(r.dx); - case 0xbb: return opwMoveRegisterImmediate(r.bx); - case 0xbc: return opwMoveRegisterImmediate(r.sp); - case 0xbd: return opwMoveRegisterImmediate(r.bp); - case 0xbe: return opwMoveRegisterImmediate(r.si); - case 0xbf: return opwMoveRegisterImmediate(r.di); + case 0xa4: return opMoveString(Byte); + case 0xa5: return opMoveString(Word); + case 0xa8: return opTestAX(Byte); + case 0xa9: return opTestAX(Word); + case 0xb0: return opMoveRegisterImmediate(r.al); + case 0xb1: return opMoveRegisterImmediate(r.cl); + case 0xb2: return opMoveRegisterImmediate(r.dl); + case 0xb3: return opMoveRegisterImmediate(r.bl); + case 0xb4: return opMoveRegisterImmediate(r.ah); + case 0xb5: return opMoveRegisterImmediate(r.ch); + case 0xb6: return opMoveRegisterImmediate(r.dh); + case 0xb7: return opMoveRegisterImmediate(r.bh); + case 0xb8: return opMoveRegisterImmediate(r.ax); + case 0xb9: return opMoveRegisterImmediate(r.cx); + case 0xba: return opMoveRegisterImmediate(r.dx); + case 0xbb: return opMoveRegisterImmediate(r.bx); + case 0xbc: return opMoveRegisterImmediate(r.sp); + case 0xbd: return opMoveRegisterImmediate(r.bp); + case 0xbe: return opMoveRegisterImmediate(r.si); + case 0xbf: return opMoveRegisterImmediate(r.di); case 0xc3: return opReturn(); - case 0xe4: return opbIn(); - case 0xe5: return opwIn(); - case 0xe6: return opbOut(); - case 0xe7: return opwOut(); + case 0xe4: return opIn(Byte); + case 0xe5: return opIn(Word); + case 0xe6: return opOut(Byte); + case 0xe7: return opOut(Word); case 0xe8: return opCallNear(); case 0xea: return opJumpFar(); - case 0xec: return opbInDX(); - case 0xed: return opwInDX(); - case 0xee: return opbOutDX(); - case 0xef: return opwOutDX(); + case 0xec: return opInDX(Byte); + case 0xed: return opInDX(Word); + case 0xee: return opOutDX(Byte); + case 0xef: return opOutDX(Word); + case 0xf2: return opRepeat(1); + case 0xf3: return opRepeat(0); case 0xf8: return opClearFlag(r.f.c); case 0xf9: return opSetFlag(r.f.c); case 0xfa: return opClearFlag(r.f.i); diff --git a/higan/processor/v30mz/v30mz.hpp b/higan/processor/v30mz/v30mz.hpp index af41e9b2..bb2869fe 100644 --- a/higan/processor/v30mz/v30mz.hpp +++ b/higan/processor/v30mz/v30mz.hpp @@ -5,6 +5,10 @@ namespace Processor { struct V30MZ { + using Size = const uint&; + static const uint Byte; + static const uint Word; + virtual auto wait(uint clocks = 1) -> void = 0; virtual auto read(uint20 addr) -> uint8 = 0; virtual auto write(uint20 addr, uint8 data) -> void = 0; @@ -16,56 +20,46 @@ struct V30MZ { auto power() -> void; //registers.cpp - auto regb(uint8) -> uint8&; - auto regw(uint8) -> uint16&; - auto sreg(uint8) -> uint16&; + auto getRegister(Size, uint8) -> uint16; + auto setRegister(Size, uint8, uint16) -> void; + + auto getSegment(uint8) -> uint16; + auto setSegment(uint8, uint16) -> void; //memory.cpp - auto readbIP() -> uint8; - auto readwIP() -> uint16; + auto read(Size, uint16, uint16) -> uint16; + auto write(Size, uint16, uint16, uint16) -> void; + + auto readIP(Size = Byte) -> uint16; auto readSP() -> uint16; auto writeSP(uint16) -> void; - auto readb(uint20 ea) -> uint8; - auto readw(uint20 ea) -> uint16; - - auto readb(uint16 rs, uint16 ea) -> uint8; - auto readw(uint16 rs, uint16 ea) -> uint16; - - auto readModRM(uint8) -> uint20; - auto readbModRM(uint8) -> uint8; - auto readwModRM(uint8) -> uint16; + auto readModRM(uint8) -> uint32; + auto readModRM(Size, uint8) -> uint16; //algorithms.cpp auto parity(uint16) const -> bool; - - auto albAnd(uint8, uint8) -> uint8; - auto alwAnd(uint16, uint16) -> uint16; + auto alAnd(Size, uint16, uint16) -> uint16; //instructions.cpp - auto opbXorRegisterModRM(); - auto opwXorRegisterModRM(); + auto opXorRegisterModRM(Size); auto opJumpIf(bool); - auto opbMoveRegisterModRM(); - auto opwMoveRegisterModRM(); + auto opMoveRegisterModRM(Size); auto opMoveSegmentRegisterModRM(); auto opNoOperation(); - auto opTestAL(); - auto opTestAX(); - auto opbMoveRegisterImmediate(uint8&); - auto opwMoveRegisterImmediate(uint16&); + auto opMoveString(Size); + auto opTestAX(Size); + auto opMoveRegisterImmediate(uint8&); + auto opMoveRegisterImmediate(uint16&); auto opReturn(); - auto opbIn(); - auto opwIn(); - auto opbOut(); - auto opwOut(); + auto opIn(Size); + auto opOut(Size); auto opCallNear(); auto opJumpFar(); - auto opbInDX(); - auto opwInDX(); - auto opbOutDX(); - auto opwOutDX(); + auto opInDX(Size); + auto opOutDX(Size); + auto opRepeat(bool); auto opClearFlag(bool&); auto opSetFlag(bool&);