mirror of https://github.com/bsnes-emu/bsnes.git
Update to v097r08 release.
byuu says: Up to 211 opcodes implemented, with the caveat that the four opcodes that make up group 3 and group 4 don't do anything yet. Both groups seem to have some "illegal" instructions in them, so that'll be "fun". I have a new mechanic in place for opcode prefixes, but it could use some work still. I also only have it working to override ModRM mem addressing, but of course it does it in a lot of other places like the string operations. Making it about 5.5 million instructions into Gunpey now, but of course that doesn't mean much. Could be going off the rails at any point due to CPU bugs or unimplemented ports. Riviera's still crashing.
This commit is contained in:
parent
ad51f1478e
commit
71bda4144a
|
@ -6,7 +6,7 @@ using namespace nall;
|
||||||
|
|
||||||
namespace Emulator {
|
namespace Emulator {
|
||||||
static const string Name = "higan";
|
static const string Name = "higan";
|
||||||
static const string Version = "097.07";
|
static const string Version = "097.08";
|
||||||
static const string Author = "byuu";
|
static const string Author = "byuu";
|
||||||
static const string License = "GPLv3";
|
static const string License = "GPLv3";
|
||||||
static const string Website = "http://byuu.org/";
|
static const string Website = "http://byuu.org/";
|
||||||
|
|
|
@ -63,35 +63,15 @@ auto V30MZ::disassemble(uint16 cs, uint16 ip, bool registers, bool bytes) -> str
|
||||||
if((modRM & 0xc0) == 0x80) return {"[", mem[(uint3)modRM], "+", readWord(), "]"};
|
if((modRM & 0xc0) == 0x80) return {"[", mem[(uint3)modRM], "+", readWord(), "]"};
|
||||||
return {"[", mem[(uint3)modRM], "]"};
|
return {"[", mem[(uint3)modRM], "]"};
|
||||||
};
|
};
|
||||||
auto readGroup1 = [&]() -> string {
|
auto readGroup = [&](uint group) -> string {
|
||||||
uint8 modRM = fetch(false);
|
uint8 modRM = fetch(false);
|
||||||
static const string grp[] = {"add", "or ", "adc", "sbb", "and", "sub", "xor", "cmp"};
|
static const string opcode[4][8] = {
|
||||||
return grp[(uint3)(modRM >> 3)];
|
{"add ", "or ", "adc ", "sbb ", "and ", "sub ", "xor ", "cmp "},
|
||||||
|
{"rol ", "ror ", "rcl ", "rcr ", "shl ", "shr ", "sal ", "sar "},
|
||||||
|
{"test", "??? ", "not ", "neg ", "mul ", "imul", "div ", "idiv"},
|
||||||
|
{"inc ", "dec ", "??? ", "??? ", "??? ", "??? ", "??? ", "??? "},
|
||||||
};
|
};
|
||||||
auto readGroup2 = [&]() -> string {
|
return opcode[group - 3][(uint3)(modRM >> 3)];
|
||||||
uint8 modRM = fetch(false);
|
|
||||||
static const string grp[] = {"rol", "ror", "rcl", "rcr", "shl", "shr", "sal", "sar"};
|
|
||||||
return grp[(uint3)(modRM >> 3)];
|
|
||||||
};
|
|
||||||
auto readRepeat = [&]() -> string {
|
|
||||||
uint8 opcode = fetch();
|
|
||||||
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 "";
|
|
||||||
};
|
};
|
||||||
|
|
||||||
auto opcode = fetch();
|
auto opcode = fetch();
|
||||||
|
@ -102,24 +82,32 @@ auto V30MZ::disassemble(uint16 cs, uint16 ip, bool registers, bool bytes) -> str
|
||||||
case 0x03: s = {"add {0},{1}", format{readRegWord(0), readMemWord()}}; break;
|
case 0x03: s = {"add {0},{1}", format{readRegWord(0), readMemWord()}}; break;
|
||||||
case 0x04: s = {"add al,{0}", format{readByte()}}; break;
|
case 0x04: s = {"add al,{0}", format{readByte()}}; break;
|
||||||
case 0x05: s = {"add ax,{0}", format{readWord()}}; break;
|
case 0x05: s = {"add ax,{0}", format{readWord()}}; break;
|
||||||
|
case 0x06: s = {"push es"}; break;
|
||||||
|
case 0x07: s = {"pop es"}; break;
|
||||||
case 0x08: s = {"or {0},{1}", format{readMemByte(0), readRegByte()}}; break;
|
case 0x08: s = {"or {0},{1}", format{readMemByte(0), readRegByte()}}; break;
|
||||||
case 0x09: s = {"or {0},{1}", format{readMemWord(0), readRegWord()}}; break;
|
case 0x09: s = {"or {0},{1}", format{readMemWord(0), readRegWord()}}; break;
|
||||||
case 0x0a: s = {"or {0},{1}", format{readRegByte(0), readMemByte()}}; break;
|
case 0x0a: s = {"or {0},{1}", format{readRegByte(0), readMemByte()}}; break;
|
||||||
case 0x0b: s = {"or {0},{1}", format{readRegWord(0), readMemWord()}}; break;
|
case 0x0b: s = {"or {0},{1}", format{readRegWord(0), readMemWord()}}; break;
|
||||||
case 0x0c: s = {"or al,{0}", format{readByte()}}; break;
|
case 0x0c: s = {"or al,{0}", format{readByte()}}; break;
|
||||||
case 0x0d: s = {"or ax,{0}", format{readWord()}}; break;
|
case 0x0d: s = {"or ax,{0}", format{readWord()}}; break;
|
||||||
|
case 0x0e: s = {"push cs"}; break;
|
||||||
|
//case 0x0f:
|
||||||
case 0x10: s = {"adc {0},{1}", format{readMemByte(0), readRegByte()}}; break;
|
case 0x10: s = {"adc {0},{1}", format{readMemByte(0), readRegByte()}}; break;
|
||||||
case 0x11: s = {"adc {0},{1}", format{readMemWord(0), readRegWord()}}; break;
|
case 0x11: s = {"adc {0},{1}", format{readMemWord(0), readRegWord()}}; break;
|
||||||
case 0x12: s = {"adc {0},{1}", format{readRegByte(0), readMemByte()}}; break;
|
case 0x12: s = {"adc {0},{1}", format{readRegByte(0), readMemByte()}}; break;
|
||||||
case 0x13: s = {"adc {0},{1}", format{readRegWord(0), readMemWord()}}; break;
|
case 0x13: s = {"adc {0},{1}", format{readRegWord(0), readMemWord()}}; break;
|
||||||
case 0x14: s = {"adc al,{0}", format{readByte()}}; break;
|
case 0x14: s = {"adc al,{0}", format{readByte()}}; break;
|
||||||
case 0x15: s = {"adc ax,{0}", format{readWord()}}; break;
|
case 0x15: s = {"adc ax,{0}", format{readWord()}}; break;
|
||||||
|
case 0x16: s = {"push ss"}; break;
|
||||||
|
case 0x17: s = {"pop ss"}; break;
|
||||||
case 0x18: s = {"sbb {0},{1}", format{readMemByte(0), readRegByte()}}; break;
|
case 0x18: s = {"sbb {0},{1}", format{readMemByte(0), readRegByte()}}; break;
|
||||||
case 0x19: s = {"sbb {0},{1}", format{readMemWord(0), readRegWord()}}; break;
|
case 0x19: s = {"sbb {0},{1}", format{readMemWord(0), readRegWord()}}; break;
|
||||||
case 0x1a: s = {"sbb {0},{1}", format{readRegByte(0), readMemByte()}}; break;
|
case 0x1a: s = {"sbb {0},{1}", format{readRegByte(0), readMemByte()}}; break;
|
||||||
case 0x1b: s = {"sbb {0},{1}", format{readRegWord(0), readMemWord()}}; break;
|
case 0x1b: s = {"sbb {0},{1}", format{readRegWord(0), readMemWord()}}; break;
|
||||||
case 0x1c: s = {"sbb al,{0}", format{readByte()}}; break;
|
case 0x1c: s = {"sbb al,{0}", format{readByte()}}; break;
|
||||||
case 0x1d: s = {"sbb ax,{0}", format{readWord()}}; break;
|
case 0x1d: s = {"sbb ax,{0}", format{readWord()}}; break;
|
||||||
|
case 0x1e: s = {"push ds"}; break;
|
||||||
|
case 0x1f: s = {"pop ds"}; break;
|
||||||
case 0x20: s = {"and {0},{1}", format{readMemByte(0), readRegByte()}}; break;
|
case 0x20: s = {"and {0},{1}", format{readMemByte(0), readRegByte()}}; break;
|
||||||
case 0x21: s = {"and {0},{1}", format{readMemWord(0), readRegWord()}}; break;
|
case 0x21: s = {"and {0},{1}", format{readMemWord(0), readRegWord()}}; break;
|
||||||
case 0x22: s = {"and {0},{1}", format{readRegByte(0), readMemByte()}}; break;
|
case 0x22: s = {"and {0},{1}", format{readRegByte(0), readMemByte()}}; break;
|
||||||
|
@ -127,6 +115,7 @@ auto V30MZ::disassemble(uint16 cs, uint16 ip, bool registers, bool bytes) -> str
|
||||||
case 0x24: s = {"and al,{0}", format{readByte()}}; break;
|
case 0x24: s = {"and al,{0}", format{readByte()}}; break;
|
||||||
case 0x25: s = {"and ax,{0}", format{readWord()}}; break;
|
case 0x25: s = {"and ax,{0}", format{readWord()}}; break;
|
||||||
case 0x26: s = {"es: "}; break;
|
case 0x26: s = {"es: "}; break;
|
||||||
|
case 0x27: s = {"daa "}; break;
|
||||||
case 0x28: s = {"sub {0},{1}", format{readMemByte(0), readRegByte()}}; break;
|
case 0x28: s = {"sub {0},{1}", format{readMemByte(0), readRegByte()}}; break;
|
||||||
case 0x29: s = {"sub {0},{1}", format{readMemWord(0), readRegWord()}}; break;
|
case 0x29: s = {"sub {0},{1}", format{readMemWord(0), readRegWord()}}; break;
|
||||||
case 0x2a: s = {"sub {0},{1}", format{readRegByte(0), readMemByte()}}; break;
|
case 0x2a: s = {"sub {0},{1}", format{readRegByte(0), readMemByte()}}; break;
|
||||||
|
@ -134,6 +123,7 @@ auto V30MZ::disassemble(uint16 cs, uint16 ip, bool registers, bool bytes) -> str
|
||||||
case 0x2c: s = {"sub al,{0}", format{readByte()}}; break;
|
case 0x2c: s = {"sub al,{0}", format{readByte()}}; break;
|
||||||
case 0x2d: s = {"sub ax,{0}", format{readWord()}}; break;
|
case 0x2d: s = {"sub ax,{0}", format{readWord()}}; break;
|
||||||
case 0x2e: s = {"cs: "}; break;
|
case 0x2e: s = {"cs: "}; break;
|
||||||
|
case 0x2f: s = {"das "}; break;
|
||||||
case 0x30: s = {"xor {0},{1}", format{readMemByte(0), readRegByte()}}; break;
|
case 0x30: s = {"xor {0},{1}", format{readMemByte(0), readRegByte()}}; break;
|
||||||
case 0x31: s = {"xor {0},{1}", format{readMemWord(0), readRegWord()}}; break;
|
case 0x31: s = {"xor {0},{1}", format{readMemWord(0), readRegWord()}}; break;
|
||||||
case 0x32: s = {"xor {0},{1}", format{readRegByte(0), readMemByte()}}; break;
|
case 0x32: s = {"xor {0},{1}", format{readRegByte(0), readMemByte()}}; break;
|
||||||
|
@ -141,6 +131,7 @@ auto V30MZ::disassemble(uint16 cs, uint16 ip, bool registers, bool bytes) -> str
|
||||||
case 0x34: s = {"xor al,{0}", format{readByte()}}; break;
|
case 0x34: s = {"xor al,{0}", format{readByte()}}; break;
|
||||||
case 0x35: s = {"xor ax,{0}", format{readWord()}}; break;
|
case 0x35: s = {"xor ax,{0}", format{readWord()}}; break;
|
||||||
case 0x36: s = {"ss: "}; break;
|
case 0x36: s = {"ss: "}; break;
|
||||||
|
case 0x37: s = {"aaa "}; break;
|
||||||
case 0x38: s = {"cmp {0},{1}", format{readMemByte(0), readRegByte()}}; break;
|
case 0x38: s = {"cmp {0},{1}", format{readMemByte(0), readRegByte()}}; break;
|
||||||
case 0x39: s = {"cmp {0},{1}", format{readMemWord(0), readRegWord()}}; break;
|
case 0x39: s = {"cmp {0},{1}", format{readMemWord(0), readRegWord()}}; break;
|
||||||
case 0x3a: s = {"cmp {0},{1}", format{readRegByte(0), readMemByte()}}; break;
|
case 0x3a: s = {"cmp {0},{1}", format{readRegByte(0), readMemByte()}}; break;
|
||||||
|
@ -148,6 +139,7 @@ auto V30MZ::disassemble(uint16 cs, uint16 ip, bool registers, bool bytes) -> str
|
||||||
case 0x3c: s = {"cmp al,{0}", format{readByte()}}; break;
|
case 0x3c: s = {"cmp al,{0}", format{readByte()}}; break;
|
||||||
case 0x3d: s = {"cmp ax,{0}", format{readWord()}}; break;
|
case 0x3d: s = {"cmp ax,{0}", format{readWord()}}; break;
|
||||||
case 0x3e: s = {"ds: "}; break;
|
case 0x3e: s = {"ds: "}; break;
|
||||||
|
case 0x3f: s = {"aas "}; break;
|
||||||
case 0x40: s = {"inc ax"}; break;
|
case 0x40: s = {"inc ax"}; break;
|
||||||
case 0x41: s = {"inc cx"}; break;
|
case 0x41: s = {"inc cx"}; break;
|
||||||
case 0x42: s = {"inc dx"}; break;
|
case 0x42: s = {"inc dx"}; break;
|
||||||
|
@ -196,16 +188,23 @@ auto V30MZ::disassemble(uint16 cs, uint16 ip, bool registers, bool bytes) -> str
|
||||||
case 0x7d: s = {"jnl {0}", format{readRelativeByte()}}; break;
|
case 0x7d: s = {"jnl {0}", format{readRelativeByte()}}; break;
|
||||||
case 0x7e: s = {"jle {0}", format{readRelativeByte()}}; break;
|
case 0x7e: s = {"jle {0}", format{readRelativeByte()}}; break;
|
||||||
case 0x7f: s = {"jnle {0}", format{readRelativeByte()}}; break;
|
case 0x7f: s = {"jnle {0}", format{readRelativeByte()}}; break;
|
||||||
case 0x80: s = {"{0} {1},{2}", format{readGroup1(), readMemByte(), readByte()}}; break;
|
case 0x80: s = {"{0} {1},{2}", format{readGroup(1), readMemByte(), readByte()}}; break;
|
||||||
case 0x81: s = {"{0} {1},{2}", format{readGroup1(), readMemWord(), readWord()}}; break;
|
case 0x81: s = {"{0}w {1},{2}", format{readGroup(1), readMemWord(), readWord()}}; break;
|
||||||
case 0x82: s = {"{0} {1},{2}", format{readGroup1(), readMemByte(), readByteSigned()}}; break;
|
case 0x82: s = {"{0} {1},{2}", format{readGroup(1), readMemByte(), readByteSigned()}}; break;
|
||||||
case 0x83: s = {"{0} {1},{2}", format{readGroup1(), readMemWord(), readByteSigned()}}; break;
|
case 0x83: s = {"{0}w {1},{2}", format{readGroup(1), readMemWord(), readByteSigned()}}; break;
|
||||||
case 0x88: s = {"mov {0},{1}", format{readMemByte(0), readRegByte()}}; break;
|
case 0x88: s = {"mov {0},{1}", format{readMemByte(0), readRegByte()}}; break;
|
||||||
case 0x89: s = {"mov {0},{1}", format{readMemWord(0), readRegWord()}}; break;
|
case 0x89: s = {"mov {0},{1}", format{readMemWord(0), readRegWord()}}; break;
|
||||||
case 0x8a: s = {"mov {0},{1}", format{readRegByte(0), readMemByte()}}; break;
|
case 0x8a: s = {"mov {0},{1}", format{readRegByte(0), readMemByte()}}; break;
|
||||||
case 0x8b: s = {"mov {0},{1}", format{readRegWord(0), readMemWord()}}; break;
|
case 0x8b: s = {"mov {0},{1}", format{readRegWord(0), readMemWord()}}; break;
|
||||||
case 0x8e: s = {"mov {0},{1}", format{readSeg(0), readMemWord()}}; break;
|
case 0x8e: s = {"mov {0},{1}", format{readSeg(0), readMemWord()}}; break;
|
||||||
case 0x90: s = {"nop "}; break;
|
case 0x90: s = {"nop "}; break;
|
||||||
|
case 0x91: s = {"xchg ax,cx"}; break;
|
||||||
|
case 0x92: s = {"xchg ax,dx"}; break;
|
||||||
|
case 0x93: s = {"xchg ax,bx"}; break;
|
||||||
|
case 0x94: s = {"xchg ax,sp"}; break;
|
||||||
|
case 0x95: s = {"xchg ax,bp"}; break;
|
||||||
|
case 0x96: s = {"xchg ax,si"}; break;
|
||||||
|
case 0x97: s = {"xchg ax,di"}; break;
|
||||||
case 0x9a: s = {"call {1}:{0}", format{readWord(), readWord()}}; break;
|
case 0x9a: s = {"call {1}:{0}", format{readWord(), readWord()}}; break;
|
||||||
case 0xa0: s = {"mov al,[{0}]", format{readWord()}}; break;
|
case 0xa0: s = {"mov al,[{0}]", format{readWord()}}; break;
|
||||||
case 0xa1: s = {"mov ax,[{0}]", format{readWord()}}; break;
|
case 0xa1: s = {"mov ax,[{0}]", format{readWord()}}; break;
|
||||||
|
@ -213,10 +212,16 @@ auto V30MZ::disassemble(uint16 cs, uint16 ip, bool registers, bool bytes) -> str
|
||||||
case 0xa3: s = {"mov [{0}],ax", format{readWord()}}; break;
|
case 0xa3: s = {"mov [{0}],ax", format{readWord()}}; break;
|
||||||
case 0xa4: s = {"movsb "}; break;
|
case 0xa4: s = {"movsb "}; break;
|
||||||
case 0xa5: s = {"movsw "}; break;
|
case 0xa5: s = {"movsw "}; break;
|
||||||
|
case 0xa6: s = {"cmpsb "}; break;
|
||||||
|
case 0xa7: s = {"cmpsw "}; break;
|
||||||
case 0xa8: s = {"test al,{0}", format{readByte()}}; break;
|
case 0xa8: s = {"test al,{0}", format{readByte()}}; break;
|
||||||
case 0xa9: s = {"test ax,{0}", format{readWord()}}; break;
|
case 0xa9: s = {"test ax,{0}", format{readWord()}}; break;
|
||||||
case 0xaa: s = {"stosb "}; break;
|
case 0xaa: s = {"stosb "}; break;
|
||||||
case 0xab: s = {"stosw "}; break;
|
case 0xab: s = {"stosw "}; break;
|
||||||
|
case 0xac: s = {"lodsb "}; break;
|
||||||
|
case 0xad: s = {"lodsw "}; break;
|
||||||
|
case 0xae: s = {"scasb "}; break;
|
||||||
|
case 0xaf: s = {"scasw "}; break;
|
||||||
case 0xb0: s = {"mov al,{0}", format{readByte()}}; break;
|
case 0xb0: s = {"mov al,{0}", format{readByte()}}; break;
|
||||||
case 0xb1: s = {"mov cl,{0}", format{readByte()}}; break;
|
case 0xb1: s = {"mov cl,{0}", format{readByte()}}; break;
|
||||||
case 0xb2: s = {"mov dl,{0}", format{readByte()}}; break;
|
case 0xb2: s = {"mov dl,{0}", format{readByte()}}; break;
|
||||||
|
@ -233,24 +238,30 @@ auto V30MZ::disassemble(uint16 cs, uint16 ip, bool registers, bool bytes) -> str
|
||||||
case 0xbd: s = {"mov bp,{0}", format{readWord()}}; break;
|
case 0xbd: s = {"mov bp,{0}", format{readWord()}}; break;
|
||||||
case 0xbe: s = {"mov si,{0}", format{readWord()}}; break;
|
case 0xbe: s = {"mov si,{0}", format{readWord()}}; break;
|
||||||
case 0xbf: s = {"mov di,{0}", format{readWord()}}; break;
|
case 0xbf: s = {"mov di,{0}", format{readWord()}}; break;
|
||||||
case 0xc0: s = {"{0} {1},{2}", format{readGroup2(), readMemByte(), readByte()}}; break;
|
case 0xc0: s = {"{0} {1},{2}", format{readGroup(2), readMemByte(), readByte()}}; break;
|
||||||
case 0xc1: s = {"{0}w {1},{2}", format{readGroup2(), readMemWord(), readByte()}}; break;
|
case 0xc1: s = {"{0}w {1},{2}", format{readGroup(2), readMemWord(), readByte()}}; break;
|
||||||
|
case 0xc2: s = {"ret {0}", format{readWord()}}; break;
|
||||||
case 0xc3: s = {"ret "}; break;
|
case 0xc3: s = {"ret "}; break;
|
||||||
case 0xc6: s = {"mov {0},{1}", format{readMemByte(), readByte()}}; break;
|
case 0xc6: s = {"mov {0},{1}", format{readMemByte(), readByte()}}; break;
|
||||||
case 0xc7: s = {"mov {0},{1}", format{readMemWord(), readWord()}}; break;
|
case 0xc7: s = {"mov {0},{1}", format{readMemWord(), readWord()}}; break;
|
||||||
|
case 0xca: s = {"retf {0}", format{readWord()}}; break;
|
||||||
case 0xcb: s = {"retf "}; break;
|
case 0xcb: s = {"retf "}; break;
|
||||||
case 0xd0: s = {"{0} {1},1", format{readGroup2(), readMemByte()}}; break;
|
case 0xd0: s = {"{0} {1},1", format{readGroup(2), readMemByte()}}; break;
|
||||||
case 0xd1: s = {"{0}w {1},1", format{readGroup2(), readMemWord()}}; break;
|
case 0xd1: s = {"{0}w {1},1", format{readGroup(2), readMemWord()}}; break;
|
||||||
case 0xd2: s = {"{0} {1},cl", format{readGroup2(), readMemByte()}}; break;
|
case 0xd2: s = {"{0} {1},cl", format{readGroup(2), readMemByte()}}; break;
|
||||||
case 0xd3: s = {"{0}w {1},cl", format{readGroup2(), readMemWord()}}; break;
|
case 0xd3: s = {"{0}w {1},cl", format{readGroup(2), readMemWord()}}; break;
|
||||||
case 0xd8: s = {"fpo1 d8"}; break;
|
//case 0xd8:
|
||||||
case 0xd9: s = {"fpo1 d9"}; break;
|
//case 0xd9:
|
||||||
case 0xda: s = {"fpo1 da"}; break;
|
//case 0xda:
|
||||||
case 0xdb: s = {"fpo1 db"}; break;
|
//case 0xdb:
|
||||||
case 0xdc: s = {"fpo1 dc"}; break;
|
//case 0xdc:
|
||||||
case 0xdd: s = {"fpo1 dd"}; break;
|
//case 0xdd:
|
||||||
case 0xde: s = {"fpo1 de"}; break;
|
//case 0xde:
|
||||||
case 0xdf: s = {"fpo1 df"}; break;
|
//case 0xdf:
|
||||||
|
case 0xe0: s = {"loopnz "}; break;
|
||||||
|
case 0xe1: s = {"loopz "}; break;
|
||||||
|
case 0xe2: s = {"loop "}; break;
|
||||||
|
case 0xe3: s = {"jcxz {0}", format{readRelativeByte()}}; break;
|
||||||
case 0xe4: s = {"in al,{0}", format{readByte()}}; break;
|
case 0xe4: s = {"in al,{0}", format{readByte()}}; break;
|
||||||
case 0xe5: s = {"in ax,{0}", format{readByte()}}; break;
|
case 0xe5: s = {"in ax,{0}", format{readByte()}}; break;
|
||||||
case 0xe6: s = {"out {0},al", format{readByte()}}; break;
|
case 0xe6: s = {"out {0},al", format{readByte()}}; break;
|
||||||
|
@ -262,14 +273,20 @@ auto V30MZ::disassemble(uint16 cs, uint16 ip, bool registers, bool bytes) -> str
|
||||||
case 0xed: s = {"in ax,dx"}; break;
|
case 0xed: s = {"in ax,dx"}; break;
|
||||||
case 0xee: s = {"out dx,al"}; break;
|
case 0xee: s = {"out dx,al"}; break;
|
||||||
case 0xef: s = {"out dx,ax"}; break;
|
case 0xef: s = {"out dx,ax"}; break;
|
||||||
case 0xf2: s = {"repnz {0}", format{readRepeat()}}; break;
|
case 0xf0: s = {"lock: "}; break;
|
||||||
case 0xf3: s = {"repz {0}", format{readRepeat()}}; break;
|
//case 0xf1:
|
||||||
|
case 0xf2: s = {"repnz: "}; break;
|
||||||
|
case 0xf3: s = {"repz: "}; break;
|
||||||
|
case 0xf6: s = {"{0} {1},{2}", format{readGroup(3), readMemByte(), readByte()}}; break;
|
||||||
|
case 0xf7: s = {"{0}w {1},{2}", format{readGroup(3), readMemWord(), readWord()}}; break;
|
||||||
case 0xf8: s = {"clc "}; break;
|
case 0xf8: s = {"clc "}; break;
|
||||||
case 0xf9: s = {"stc "}; break;
|
case 0xf9: s = {"stc "}; break;
|
||||||
case 0xfa: s = {"cli "}; break;
|
case 0xfa: s = {"cli "}; break;
|
||||||
case 0xfb: s = {"sti "}; break;
|
case 0xfb: s = {"sti "}; break;
|
||||||
case 0xfc: s = {"cld "}; break;
|
case 0xfc: s = {"cld "}; break;
|
||||||
case 0xfd: s = {"std "}; break;
|
case 0xfd: s = {"std "}; break;
|
||||||
|
case 0xfe: s = {"{0} {1},{2}", format{readGroup(4), readMemByte(), readByte()}}; break;
|
||||||
|
case 0xff: s = {"{0}w {1},{2}", format{readGroup(4), readMemWord(), readWord()}}; break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
s = {"??? [", hex(opcode, 2L), "]"};
|
s = {"??? [", hex(opcode, 2L), "]"};
|
||||||
|
|
|
@ -98,8 +98,46 @@ auto V30MZ::opSubAccImm(Size size) {
|
||||||
//2e cs:
|
//2e cs:
|
||||||
//36 ss:
|
//36 ss:
|
||||||
//3e ds:
|
//3e ds:
|
||||||
auto V30MZ::opPrefix(uint16& segment) {
|
auto V30MZ::opPrefix(uint flag) {
|
||||||
//todo
|
prefix.hold = true;
|
||||||
|
prefix.es = flag == 0;
|
||||||
|
prefix.cs = flag == 1;
|
||||||
|
prefix.ss = flag == 2;
|
||||||
|
prefix.ds = flag == 3;
|
||||||
|
}
|
||||||
|
|
||||||
|
//27 daa
|
||||||
|
//2f das
|
||||||
|
auto V30MZ::opDecimalAdjust(bool negate) {
|
||||||
|
wait(9);
|
||||||
|
uint8 al = r.al;
|
||||||
|
if(r.f.h || ((al & 0x0f) > 0x09)) {
|
||||||
|
r.al += negate ? -0x06 : 0x06;
|
||||||
|
r.f.h = 1;
|
||||||
|
}
|
||||||
|
if(r.f.c || (al > 0x99)) {
|
||||||
|
r.al += negate ? -0x06 : 0x60;
|
||||||
|
r.f.c = 1;
|
||||||
|
}
|
||||||
|
r.f.s = r.al & 0x80;
|
||||||
|
r.f.z = r.al == 0;
|
||||||
|
r.f.p = parity(r.al);
|
||||||
|
}
|
||||||
|
|
||||||
|
//37 aaa
|
||||||
|
//3f aas
|
||||||
|
auto V30MZ::opAsciiAdjust(bool negate) {
|
||||||
|
wait(8);
|
||||||
|
if(r.f.h || ((r.al & 0x0f) > 0x09)) {
|
||||||
|
r.al += negate ? -0x06 : 0x06;
|
||||||
|
r.ah += negate ? -0x01 : 0x01;
|
||||||
|
r.f.h = 1;
|
||||||
|
r.f.c = 1;
|
||||||
|
} else {
|
||||||
|
r.f.h = 0;
|
||||||
|
r.f.c = 0;
|
||||||
|
}
|
||||||
|
r.al &= 0x0f;
|
||||||
}
|
}
|
||||||
|
|
||||||
auto V30MZ::opXorMemReg(Size size) {
|
auto V30MZ::opXorMemReg(Size size) {
|
||||||
|
@ -206,6 +244,13 @@ auto V30MZ::opMoveSegMem() {
|
||||||
auto V30MZ::opNop() {
|
auto V30MZ::opNop() {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
auto V30MZ::opExchange(uint16& x, uint16& y) {
|
||||||
|
wait(2);
|
||||||
|
uint16 z = x;
|
||||||
|
x = y;
|
||||||
|
y = z;
|
||||||
|
}
|
||||||
|
|
||||||
auto V30MZ::opCallFar() {
|
auto V30MZ::opCallFar() {
|
||||||
wait(9);
|
wait(9);
|
||||||
auto ip = fetch(Word);
|
auto ip = fetch(Word);
|
||||||
|
@ -229,6 +274,25 @@ auto V30MZ::opMoveString(Size size) {
|
||||||
write(size, r.es, r.di, read(size, r.ds, r.si));
|
write(size, r.es, r.di, read(size, r.ds, r.si));
|
||||||
r.si += r.f.d ? -size : size;
|
r.si += r.f.d ? -size : size;
|
||||||
r.di += r.f.d ? -size : size;
|
r.di += r.f.d ? -size : size;
|
||||||
|
|
||||||
|
if(prefix.repnz || prefix.repz) {
|
||||||
|
if(--r.cx) r.ip--, prefix.hold = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
auto V30MZ::opCompareString(Size size) {
|
||||||
|
wait(5);
|
||||||
|
auto x = read(size, r.ds, r.si);
|
||||||
|
auto y = read(size, r.es, r.di);
|
||||||
|
r.si += r.f.d ? -size : size;
|
||||||
|
r.di += r.f.d ? -size : size;
|
||||||
|
alSub(size, x, y);
|
||||||
|
|
||||||
|
if(prefix.repnz || prefix.repz) {
|
||||||
|
if(r.f.z == 1 && prefix.repnz) return;
|
||||||
|
if(r.f.z == 0 && prefix.repz) return;
|
||||||
|
if(--r.cx) r.ip--, prefix.hold = true;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
auto V30MZ::opTestAcc(Size size) {
|
auto V30MZ::opTestAcc(Size size) {
|
||||||
|
@ -239,6 +303,36 @@ auto V30MZ::opStoreString(Size size) {
|
||||||
wait(2);
|
wait(2);
|
||||||
write(size, r.es, r.di, getAcc(size));
|
write(size, r.es, r.di, getAcc(size));
|
||||||
r.di += r.f.d ? -size : size;
|
r.di += r.f.d ? -size : size;
|
||||||
|
|
||||||
|
if(prefix.repnz || prefix.repz) {
|
||||||
|
if(--r.cx) r.ip--, prefix.hold = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//ac lodsb
|
||||||
|
//ad lodsw
|
||||||
|
auto V30MZ::opLoadString(Size size) {
|
||||||
|
wait(2);
|
||||||
|
setAcc(size, read(size, r.ds, r.si));
|
||||||
|
|
||||||
|
if(prefix.repnz || prefix.repz) {
|
||||||
|
if(--r.cx) r.ip--, prefix.hold = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//ae scasb
|
||||||
|
//af scasw
|
||||||
|
auto V30MZ::opSubtractCompareString(Size size) {
|
||||||
|
wait(3);
|
||||||
|
auto x = getAcc(size);
|
||||||
|
auto y = read(size, r.es, r.di);
|
||||||
|
alSub(size, x, y);
|
||||||
|
|
||||||
|
if(prefix.repnz || prefix.repz) {
|
||||||
|
if(r.f.z == 1 && prefix.repnz) return;
|
||||||
|
if(r.f.z == 0 && prefix.repz) return;
|
||||||
|
if(--r.cx) r.ip--, prefix.hold = true;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
auto V30MZ::opMoveRegImm(uint8& reg) {
|
auto V30MZ::opMoveRegImm(uint8& reg) {
|
||||||
|
@ -249,6 +343,13 @@ auto V30MZ::opMoveRegImm(uint16& reg) {
|
||||||
reg = fetch(Word);
|
reg = fetch(Word);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
auto V30MZ::opReturnImm() {
|
||||||
|
wait(5);
|
||||||
|
auto offset = fetch(Word);
|
||||||
|
r.ip = pop();
|
||||||
|
r.sp += offset;
|
||||||
|
}
|
||||||
|
|
||||||
auto V30MZ::opReturn() {
|
auto V30MZ::opReturn() {
|
||||||
wait(5);
|
wait(5);
|
||||||
r.ip = pop();
|
r.ip = pop();
|
||||||
|
@ -259,12 +360,18 @@ auto V30MZ::opMoveMemImm(Size size) {
|
||||||
setMem(size, modRM, fetch(size));
|
setMem(size, modRM, fetch(size));
|
||||||
}
|
}
|
||||||
|
|
||||||
auto V30MZ::opRetFar() {
|
auto V30MZ::opReturnFarImm() {
|
||||||
|
wait(8);
|
||||||
|
auto offset = fetch(Word);
|
||||||
|
r.ip = pop();
|
||||||
|
r.cs = pop();
|
||||||
|
r.sp += offset;
|
||||||
|
}
|
||||||
|
|
||||||
|
auto V30MZ::opReturnFar() {
|
||||||
wait(7);
|
wait(7);
|
||||||
auto ip = pop();
|
r.ip = pop();
|
||||||
auto cs = pop();
|
r.cs = pop();
|
||||||
r.cs = cs;
|
|
||||||
r.ip = ip;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
auto V30MZ::opGroup2MemImm(Size size, maybe<uint8> imm) {
|
auto V30MZ::opGroup2MemImm(Size size, maybe<uint8> imm) {
|
||||||
|
@ -286,6 +393,34 @@ auto V30MZ::opGroup2MemImm(Size size, maybe<uint8> imm) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
auto V30MZ::opGroup3MemImm(Size size) {
|
||||||
|
auto modRM = fetch();
|
||||||
|
auto mem = getMem(size, modRM);
|
||||||
|
}
|
||||||
|
|
||||||
|
auto V30MZ::opGroup4MemImm(Size size) {
|
||||||
|
auto modRM = fetch();
|
||||||
|
auto mem = getMem(size, modRM);
|
||||||
|
}
|
||||||
|
|
||||||
|
auto V30MZ::opLoopWhile(bool value) {
|
||||||
|
wait(2);
|
||||||
|
auto offset = (int8)fetch();
|
||||||
|
if(--r.cx && r.f.z == value) {
|
||||||
|
wait(3);
|
||||||
|
r.ip += offset;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
auto V30MZ::opLoop() {
|
||||||
|
wait(1);
|
||||||
|
auto offset = (int8)fetch();
|
||||||
|
if(--r.cx) {
|
||||||
|
wait(3);
|
||||||
|
r.ip += offset;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
auto V30MZ::opIn(Size size) {
|
auto V30MZ::opIn(Size size) {
|
||||||
wait(5);
|
wait(5);
|
||||||
auto port = fetch();
|
auto port = fetch();
|
||||||
|
@ -337,24 +472,19 @@ auto V30MZ::opOutDX(Size size) {
|
||||||
out(r.dx + 1, r.ah);
|
out(r.dx + 1, r.ah);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//f0 lock
|
||||||
|
auto V30MZ::opLock() {
|
||||||
|
prefix.hold = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
//f2 repnz
|
||||||
|
//f3 repz
|
||||||
auto V30MZ::opRepeat(bool flag) {
|
auto V30MZ::opRepeat(bool flag) {
|
||||||
wait(4);
|
wait(4);
|
||||||
auto opcode = fetch();
|
|
||||||
if((opcode & 0xfc) != 0x6c && (opcode & 0xfc) != 0xa4
|
|
||||||
&& (opcode & 0xfe) != 0xaa && (opcode & 0xfc) != 0xac) {
|
|
||||||
//invalid argument
|
|
||||||
r.ip--;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
if(r.cx == 0) return;
|
if(r.cx == 0) return;
|
||||||
r.cx--;
|
prefix.hold = true;
|
||||||
|
prefix.repnz = flag == 0;
|
||||||
switch(opcode) {
|
prefix.repz = flag == 1;
|
||||||
case 0xa4: opMoveString(Byte); r.ip -= 2; break;
|
|
||||||
case 0xa5: opMoveString(Word); r.ip -= 2; break;
|
|
||||||
case 0xaa: opStoreString(Byte); r.ip -= 2; break;
|
|
||||||
case 0xab: opStoreString(Word); r.ip -= 2; break;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
auto V30MZ::opClearFlag(bool& flag) {
|
auto V30MZ::opClearFlag(bool& flag) {
|
||||||
|
|
|
@ -44,6 +44,11 @@ auto V30MZ::getMemAddress(uint8 modRM) -> uint32 {
|
||||||
case 7: s = r.ds; a += r.bx; break;
|
case 7: s = r.ds; a += r.bx; break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if(prefix.es) s = r.es;
|
||||||
|
if(prefix.cs) s = r.cs;
|
||||||
|
if(prefix.ss) s = r.ss;
|
||||||
|
if(prefix.ds) s = r.ds;
|
||||||
|
|
||||||
return s << 16 | a;
|
return s << 16 | a;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -15,12 +15,19 @@ const uint V30MZ::Word = 2;
|
||||||
auto V30MZ::exec() -> void {
|
auto V30MZ::exec() -> void {
|
||||||
if(halt) return wait(1);
|
if(halt) return wait(1);
|
||||||
|
|
||||||
#if 1
|
#if 0
|
||||||
static uint16 cs = 0, ip = 0;
|
static uint16 cs = 0, ip = 0;
|
||||||
if(cs != r.cs || ip != r.ip) print(disassemble(cs = r.cs, ip = r.ip), "\n");
|
if(cs != r.cs || ip != r.ip) print(disassemble(cs = r.cs, ip = r.ip), "\n");
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
execOpcode();
|
execOpcode();
|
||||||
|
|
||||||
|
if(prefix.hold) {
|
||||||
|
prefix.hold = false;
|
||||||
|
} else {
|
||||||
|
prefix.es = prefix.cs = prefix.ss = prefix.ds = false;
|
||||||
|
prefix.repnz = prefix.repz = false;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
auto V30MZ::execOpcode() -> void {
|
auto V30MZ::execOpcode() -> void {
|
||||||
|
@ -36,52 +43,64 @@ auto V30MZ::execOpcode() -> void {
|
||||||
case 0x03: return opAddRegMem(Word);
|
case 0x03: return opAddRegMem(Word);
|
||||||
case 0x04: return opAddAccImm(Byte);
|
case 0x04: return opAddAccImm(Byte);
|
||||||
case 0x05: return opAddAccImm(Word);
|
case 0x05: return opAddAccImm(Word);
|
||||||
|
case 0x06: return opPushReg(r.es);
|
||||||
|
case 0x07: return opPopReg(r.es);
|
||||||
case 0x08: return opOrMemReg(Byte);
|
case 0x08: return opOrMemReg(Byte);
|
||||||
case 0x09: return opOrMemReg(Word);
|
case 0x09: return opOrMemReg(Word);
|
||||||
case 0x0a: return opOrRegMem(Byte);
|
case 0x0a: return opOrRegMem(Byte);
|
||||||
case 0x0b: return opOrRegMem(Word);
|
case 0x0b: return opOrRegMem(Word);
|
||||||
case 0x0c: return opOrAccImm(Byte);
|
case 0x0c: return opOrAccImm(Byte);
|
||||||
case 0x0d: return opOrAccImm(Word);
|
case 0x0d: return opOrAccImm(Word);
|
||||||
|
case 0x0e: return opPushReg(r.cs);
|
||||||
|
case 0x0f: return; //pop cs
|
||||||
case 0x10: return opAdcMemReg(Byte);
|
case 0x10: return opAdcMemReg(Byte);
|
||||||
case 0x11: return opAdcMemReg(Word);
|
case 0x11: return opAdcMemReg(Word);
|
||||||
case 0x12: return opAdcRegMem(Byte);
|
case 0x12: return opAdcRegMem(Byte);
|
||||||
case 0x13: return opAdcRegMem(Word);
|
case 0x13: return opAdcRegMem(Word);
|
||||||
case 0x14: return opAdcAccImm(Byte);
|
case 0x14: return opAdcAccImm(Byte);
|
||||||
case 0x15: return opAdcAccImm(Word);
|
case 0x15: return opAdcAccImm(Word);
|
||||||
|
case 0x16: return opPushReg(r.ss);
|
||||||
|
case 0x17: return opPopReg(r.ss);
|
||||||
case 0x18: return opSbbMemReg(Byte);
|
case 0x18: return opSbbMemReg(Byte);
|
||||||
case 0x19: return opSbbMemReg(Word);
|
case 0x19: return opSbbMemReg(Word);
|
||||||
case 0x1a: return opSbbRegMem(Byte);
|
case 0x1a: return opSbbRegMem(Byte);
|
||||||
case 0x1b: return opSbbRegMem(Word);
|
case 0x1b: return opSbbRegMem(Word);
|
||||||
case 0x1c: return opSbbAccImm(Byte);
|
case 0x1c: return opSbbAccImm(Byte);
|
||||||
case 0x1d: return opSbbAccImm(Word);
|
case 0x1d: return opSbbAccImm(Word);
|
||||||
|
case 0x1e: return opPushReg(r.ds);
|
||||||
|
case 0x1f: return opPopReg(r.cs);
|
||||||
case 0x20: return opAndMemReg(Byte);
|
case 0x20: return opAndMemReg(Byte);
|
||||||
case 0x21: return opAndMemReg(Word);
|
case 0x21: return opAndMemReg(Word);
|
||||||
case 0x22: return opAndRegMem(Byte);
|
case 0x22: return opAndRegMem(Byte);
|
||||||
case 0x23: return opAndRegMem(Word);
|
case 0x23: return opAndRegMem(Word);
|
||||||
case 0x24: return opAndAccImm(Byte);
|
case 0x24: return opAndAccImm(Byte);
|
||||||
case 0x25: return opAndAccImm(Word);
|
case 0x25: return opAndAccImm(Word);
|
||||||
case 0x26: return opPrefix(r.es);
|
case 0x26: return opPrefix(0); //es:
|
||||||
|
case 0x27: return opDecimalAdjust(0); //daa
|
||||||
case 0x28: return opSubMemReg(Byte);
|
case 0x28: return opSubMemReg(Byte);
|
||||||
case 0x29: return opSubMemReg(Word);
|
case 0x29: return opSubMemReg(Word);
|
||||||
case 0x2a: return opSubRegMem(Byte);
|
case 0x2a: return opSubRegMem(Byte);
|
||||||
case 0x2b: return opSubRegMem(Word);
|
case 0x2b: return opSubRegMem(Word);
|
||||||
case 0x2c: return opSubAccImm(Byte);
|
case 0x2c: return opSubAccImm(Byte);
|
||||||
case 0x2d: return opSubAccImm(Word);
|
case 0x2d: return opSubAccImm(Word);
|
||||||
case 0x2e: return opPrefix(r.cs);
|
case 0x2e: return opPrefix(1); //cs:
|
||||||
|
case 0x2f: return opDecimalAdjust(1); //das
|
||||||
case 0x30: return opXorMemReg(Byte);
|
case 0x30: return opXorMemReg(Byte);
|
||||||
case 0x31: return opXorMemReg(Word);
|
case 0x31: return opXorMemReg(Word);
|
||||||
case 0x32: return opXorRegMem(Byte);
|
case 0x32: return opXorRegMem(Byte);
|
||||||
case 0x33: return opXorRegMem(Word);
|
case 0x33: return opXorRegMem(Word);
|
||||||
case 0x34: return opXorAccImm(Byte);
|
case 0x34: return opXorAccImm(Byte);
|
||||||
case 0x35: return opXorAccImm(Word);
|
case 0x35: return opXorAccImm(Word);
|
||||||
case 0x36: return opPrefix(r.ss);
|
case 0x36: return opPrefix(2); //ss:
|
||||||
|
case 0x37: return opAsciiAdjust(0); //aaa
|
||||||
case 0x38: return opCmpMemReg(Byte);
|
case 0x38: return opCmpMemReg(Byte);
|
||||||
case 0x39: return opCmpMemReg(Word);
|
case 0x39: return opCmpMemReg(Word);
|
||||||
case 0x3a: return opCmpRegMem(Byte);
|
case 0x3a: return opCmpRegMem(Byte);
|
||||||
case 0x3b: return opCmpRegMem(Word);
|
case 0x3b: return opCmpRegMem(Word);
|
||||||
case 0x3c: return opCmpAccImm(Byte);
|
case 0x3c: return opCmpAccImm(Byte);
|
||||||
case 0x3d: return opCmpAccImm(Word);
|
case 0x3d: return opCmpAccImm(Word);
|
||||||
case 0x3e: return opPrefix(r.ds);
|
case 0x3e: return opPrefix(3); //ds:
|
||||||
|
case 0x3f: return opAsciiAdjust(1); //aas
|
||||||
case 0x40: return opIncReg(r.ax);
|
case 0x40: return opIncReg(r.ax);
|
||||||
case 0x41: return opIncReg(r.cx);
|
case 0x41: return opIncReg(r.cx);
|
||||||
case 0x42: return opIncReg(r.dx);
|
case 0x42: return opIncReg(r.dx);
|
||||||
|
@ -114,6 +133,7 @@ auto V30MZ::execOpcode() -> void {
|
||||||
case 0x5d: return opPopReg(r.bp);
|
case 0x5d: return opPopReg(r.bp);
|
||||||
case 0x5e: return opPopReg(r.si);
|
case 0x5e: return opPopReg(r.si);
|
||||||
case 0x5f: return opPopReg(r.di);
|
case 0x5f: return opPopReg(r.di);
|
||||||
|
//60-62,68-6f
|
||||||
case 0x70: return opJumpIf(r.f.v == 1);
|
case 0x70: return opJumpIf(r.f.v == 1);
|
||||||
case 0x71: return opJumpIf(r.f.v == 0);
|
case 0x71: return opJumpIf(r.f.v == 0);
|
||||||
case 0x72: return opJumpIf(r.f.c == 1);
|
case 0x72: return opJumpIf(r.f.c == 1);
|
||||||
|
@ -134,23 +154,41 @@ auto V30MZ::execOpcode() -> void {
|
||||||
case 0x81: return opGroup1MemImm(Word, 0);
|
case 0x81: return opGroup1MemImm(Word, 0);
|
||||||
case 0x82: return opGroup1MemImm(Byte, 1);
|
case 0x82: return opGroup1MemImm(Byte, 1);
|
||||||
case 0x83: return opGroup1MemImm(Word, 1);
|
case 0x83: return opGroup1MemImm(Word, 1);
|
||||||
|
//84-87
|
||||||
case 0x88: return opMoveMemReg(Byte);
|
case 0x88: return opMoveMemReg(Byte);
|
||||||
case 0x89: return opMoveMemReg(Word);
|
case 0x89: return opMoveMemReg(Word);
|
||||||
case 0x8a: return opMoveRegMem(Byte);
|
case 0x8a: return opMoveRegMem(Byte);
|
||||||
case 0x8b: return opMoveRegMem(Word);
|
case 0x8b: return opMoveRegMem(Word);
|
||||||
|
//8c,8d
|
||||||
case 0x8e: return opMoveSegMem();
|
case 0x8e: return opMoveSegMem();
|
||||||
|
//8f
|
||||||
case 0x90: return opNop();
|
case 0x90: return opNop();
|
||||||
|
case 0x91: return opExchange(r.ax, r.cx);
|
||||||
|
case 0x92: return opExchange(r.ax, r.dx);
|
||||||
|
case 0x93: return opExchange(r.ax, r.bx);
|
||||||
|
case 0x94: return opExchange(r.ax, r.sp);
|
||||||
|
case 0x95: return opExchange(r.ax, r.bp);
|
||||||
|
case 0x96: return opExchange(r.ax, r.si);
|
||||||
|
case 0x97: return opExchange(r.ax, r.di);
|
||||||
|
//98-99
|
||||||
case 0x9a: return opCallFar();
|
case 0x9a: return opCallFar();
|
||||||
|
//9b-9f
|
||||||
case 0xa0: return opMoveAccMem(Byte);
|
case 0xa0: return opMoveAccMem(Byte);
|
||||||
case 0xa1: return opMoveAccMem(Word);
|
case 0xa1: return opMoveAccMem(Word);
|
||||||
case 0xa2: return opMoveMemAcc(Byte);
|
case 0xa2: return opMoveMemAcc(Byte);
|
||||||
case 0xa3: return opMoveMemAcc(Word);
|
case 0xa3: return opMoveMemAcc(Word);
|
||||||
case 0xa4: return opMoveString(Byte);
|
case 0xa4: return opMoveString(Byte);
|
||||||
case 0xa5: return opMoveString(Word);
|
case 0xa5: return opMoveString(Word);
|
||||||
|
case 0xa6: return opCompareString(Byte);
|
||||||
|
case 0xa7: return opCompareString(Word);
|
||||||
case 0xa8: return opTestAcc(Byte);
|
case 0xa8: return opTestAcc(Byte);
|
||||||
case 0xa9: return opTestAcc(Word);
|
case 0xa9: return opTestAcc(Word);
|
||||||
case 0xaa: return opStoreString(Byte);
|
case 0xaa: return opStoreString(Byte);
|
||||||
case 0xab: return opStoreString(Word);
|
case 0xab: return opStoreString(Word);
|
||||||
|
case 0xac: return opLoadString(Byte);
|
||||||
|
case 0xad: return opLoadString(Word);
|
||||||
|
case 0xae: return opSubtractCompareString(Byte);
|
||||||
|
case 0xaf: return opSubtractCompareString(Word);
|
||||||
case 0xb0: return opMoveRegImm(r.al);
|
case 0xb0: return opMoveRegImm(r.al);
|
||||||
case 0xb1: return opMoveRegImm(r.cl);
|
case 0xb1: return opMoveRegImm(r.cl);
|
||||||
case 0xb2: return opMoveRegImm(r.dl);
|
case 0xb2: return opMoveRegImm(r.dl);
|
||||||
|
@ -169,41 +207,59 @@ auto V30MZ::execOpcode() -> void {
|
||||||
case 0xbf: return opMoveRegImm(r.di);
|
case 0xbf: return opMoveRegImm(r.di);
|
||||||
case 0xc0: return opGroup2MemImm(Byte);
|
case 0xc0: return opGroup2MemImm(Byte);
|
||||||
case 0xc1: return opGroup2MemImm(Word);
|
case 0xc1: return opGroup2MemImm(Word);
|
||||||
|
case 0xc2: return opReturnImm();
|
||||||
case 0xc3: return opReturn();
|
case 0xc3: return opReturn();
|
||||||
|
//c4,c5
|
||||||
case 0xc6: return opMoveMemImm(Byte);
|
case 0xc6: return opMoveMemImm(Byte);
|
||||||
case 0xc7: return opMoveMemImm(Word);
|
case 0xc7: return opMoveMemImm(Word);
|
||||||
case 0xcb: return opRetFar();
|
//c8,c9
|
||||||
|
case 0xca: return opReturnFarImm();
|
||||||
|
case 0xcb: return opReturnFar();
|
||||||
|
//cc-cf
|
||||||
case 0xd0: return opGroup2MemImm(Byte, 1);
|
case 0xd0: return opGroup2MemImm(Byte, 1);
|
||||||
case 0xd1: return opGroup2MemImm(Word, 1);
|
case 0xd1: return opGroup2MemImm(Word, 1);
|
||||||
case 0xd2: return opGroup2MemImm(Byte, r.cl);
|
case 0xd2: return opGroup2MemImm(Byte, r.cl);
|
||||||
case 0xd3: return opGroup2MemImm(Word, r.cl);
|
case 0xd3: return opGroup2MemImm(Word, r.cl);
|
||||||
case 0xd8: return opNop(); //FPO1
|
//d4,d5,d7
|
||||||
case 0xd9: return opNop(); //FPO1
|
case 0xd8: return; //fpo1
|
||||||
case 0xda: return opNop(); //FPO1
|
case 0xd9: return; //fpo1
|
||||||
case 0xdb: return opNop(); //FPO1
|
case 0xda: return; //fpo1
|
||||||
case 0xdc: return opNop(); //FPO1
|
case 0xdb: return; //fpo1
|
||||||
case 0xdd: return opNop(); //FPO1
|
case 0xdc: return; //fpo1
|
||||||
case 0xde: return opNop(); //FPO1
|
case 0xdd: return; //fpo1
|
||||||
case 0xdf: return opNop(); //FPO1
|
case 0xde: return; //fpo1
|
||||||
|
case 0xdf: return; //fpo1
|
||||||
|
case 0xe0: return opLoopWhile(0); //loopnz
|
||||||
|
case 0xe1: return opLoopWhile(1); //loopz
|
||||||
|
case 0xe2: return opLoop();
|
||||||
|
case 0xe3: return opJumpIf(r.cx == 0);
|
||||||
case 0xe4: return opIn(Byte);
|
case 0xe4: return opIn(Byte);
|
||||||
case 0xe5: return opIn(Word);
|
case 0xe5: return opIn(Word);
|
||||||
case 0xe6: return opOut(Byte);
|
case 0xe6: return opOut(Byte);
|
||||||
case 0xe7: return opOut(Word);
|
case 0xe7: return opOut(Word);
|
||||||
case 0xe8: return opCallNear();
|
case 0xe8: return opCallNear();
|
||||||
|
//e9
|
||||||
case 0xea: return opJumpFar();
|
case 0xea: return opJumpFar();
|
||||||
case 0xeb: return opJumpShort();
|
case 0xeb: return opJumpShort();
|
||||||
case 0xec: return opInDX(Byte);
|
case 0xec: return opInDX(Byte);
|
||||||
case 0xed: return opInDX(Word);
|
case 0xed: return opInDX(Word);
|
||||||
case 0xee: return opOutDX(Byte);
|
case 0xee: return opOutDX(Byte);
|
||||||
case 0xef: return opOutDX(Word);
|
case 0xef: return opOutDX(Word);
|
||||||
case 0xf2: return opRepeat(1);
|
case 0xf0: return opLock();
|
||||||
case 0xf3: return opRepeat(0);
|
case 0xf1: return;
|
||||||
|
case 0xf2: return opRepeat(0); //repnz
|
||||||
|
case 0xf3: return opRepeat(1); //repz
|
||||||
|
//f4-f5
|
||||||
|
case 0xf6: return opGroup3MemImm(Byte);
|
||||||
|
case 0xf7: return opGroup3MemImm(Word);
|
||||||
case 0xf8: return opClearFlag(r.f.c);
|
case 0xf8: return opClearFlag(r.f.c);
|
||||||
case 0xf9: return opSetFlag(r.f.c);
|
case 0xf9: return opSetFlag(r.f.c);
|
||||||
case 0xfa: return opClearFlag(r.f.i);
|
case 0xfa: return opClearFlag(r.f.i);
|
||||||
case 0xfb: return opSetFlag(r.f.i);
|
case 0xfb: return opSetFlag(r.f.i);
|
||||||
case 0xfc: return opClearFlag(r.f.d);
|
case 0xfc: return opClearFlag(r.f.d);
|
||||||
case 0xfd: return opSetFlag(r.f.d);
|
case 0xfd: return opSetFlag(r.f.d);
|
||||||
|
case 0xfe: return opGroup4MemImm(Byte);
|
||||||
|
case 0xff: return opGroup4MemImm(Word);
|
||||||
}
|
}
|
||||||
|
|
||||||
print("error: unknown opcode: ", hex(opcode, 2L), "\n");
|
print("error: unknown opcode: ", hex(opcode, 2L), "\n");
|
||||||
|
@ -215,6 +271,10 @@ auto V30MZ::power() -> void {
|
||||||
halt = false;
|
halt = false;
|
||||||
executed = 0;
|
executed = 0;
|
||||||
|
|
||||||
|
prefix.hold = false;
|
||||||
|
prefix.es = prefix.cs = prefix.ss = prefix.ds = false;
|
||||||
|
prefix.repz = prefix.repnz = false;
|
||||||
|
|
||||||
r.ip = 0x0000;
|
r.ip = 0x0000;
|
||||||
r.ax = 0x0000;
|
r.ax = 0x0000;
|
||||||
r.bx = 0x0000;
|
r.bx = 0x0000;
|
||||||
|
|
|
@ -76,7 +76,9 @@ struct V30MZ {
|
||||||
auto opAndMemReg(Size);
|
auto opAndMemReg(Size);
|
||||||
auto opAndRegMem(Size);
|
auto opAndRegMem(Size);
|
||||||
auto opAndAccImm(Size);
|
auto opAndAccImm(Size);
|
||||||
auto opPrefix(uint16&);
|
auto opPrefix(uint);
|
||||||
|
auto opDecimalAdjust(bool);
|
||||||
|
auto opAsciiAdjust(bool);
|
||||||
auto opSubMemReg(Size);
|
auto opSubMemReg(Size);
|
||||||
auto opSubRegMem(Size);
|
auto opSubRegMem(Size);
|
||||||
auto opSubAccImm(Size);
|
auto opSubAccImm(Size);
|
||||||
|
@ -96,18 +98,28 @@ struct V30MZ {
|
||||||
auto opMoveRegMem(Size);
|
auto opMoveRegMem(Size);
|
||||||
auto opMoveSegMem();
|
auto opMoveSegMem();
|
||||||
auto opNop();
|
auto opNop();
|
||||||
|
auto opExchange(uint16&, uint16&);
|
||||||
auto opCallFar();
|
auto opCallFar();
|
||||||
auto opMoveAccMem(Size);
|
auto opMoveAccMem(Size);
|
||||||
auto opMoveMemAcc(Size);
|
auto opMoveMemAcc(Size);
|
||||||
auto opMoveString(Size);
|
auto opMoveString(Size);
|
||||||
|
auto opCompareString(Size);
|
||||||
auto opTestAcc(Size);
|
auto opTestAcc(Size);
|
||||||
auto opStoreString(Size);
|
auto opStoreString(Size);
|
||||||
|
auto opLoadString(Size);
|
||||||
|
auto opSubtractCompareString(Size);
|
||||||
auto opMoveRegImm(uint8&);
|
auto opMoveRegImm(uint8&);
|
||||||
auto opMoveRegImm(uint16&);
|
auto opMoveRegImm(uint16&);
|
||||||
|
auto opReturnImm();
|
||||||
auto opReturn();
|
auto opReturn();
|
||||||
auto opMoveMemImm(Size);
|
auto opMoveMemImm(Size);
|
||||||
auto opRetFar();
|
auto opReturnFarImm();
|
||||||
|
auto opReturnFar();
|
||||||
auto opGroup2MemImm(Size, maybe<uint8> = {});
|
auto opGroup2MemImm(Size, maybe<uint8> = {});
|
||||||
|
auto opGroup3MemImm(Size);
|
||||||
|
auto opGroup4MemImm(Size);
|
||||||
|
auto opLoopWhile(bool);
|
||||||
|
auto opLoop();
|
||||||
auto opIn(Size);
|
auto opIn(Size);
|
||||||
auto opOut(Size);
|
auto opOut(Size);
|
||||||
auto opCallNear();
|
auto opCallNear();
|
||||||
|
@ -115,6 +127,7 @@ struct V30MZ {
|
||||||
auto opJumpShort();
|
auto opJumpShort();
|
||||||
auto opInDX(Size);
|
auto opInDX(Size);
|
||||||
auto opOutDX(Size);
|
auto opOutDX(Size);
|
||||||
|
auto opLock();
|
||||||
auto opRepeat(bool);
|
auto opRepeat(bool);
|
||||||
auto opClearFlag(bool&);
|
auto opClearFlag(bool&);
|
||||||
auto opSetFlag(bool&);
|
auto opSetFlag(bool&);
|
||||||
|
@ -126,6 +139,12 @@ struct V30MZ {
|
||||||
bool halt = false;
|
bool halt = false;
|
||||||
uint executed = 0;
|
uint executed = 0;
|
||||||
|
|
||||||
|
struct Prefix {
|
||||||
|
bool hold;
|
||||||
|
bool es, cs, ss, ds;
|
||||||
|
bool repnz, repz;
|
||||||
|
} prefix;
|
||||||
|
|
||||||
struct Registers {
|
struct Registers {
|
||||||
//registers.cpp
|
//registers.cpp
|
||||||
auto byte(uint3) -> uint8&;
|
auto byte(uint3) -> uint8&;
|
||||||
|
|
|
@ -12,12 +12,12 @@ auto IO::power() -> void {
|
||||||
}
|
}
|
||||||
|
|
||||||
auto IO::portRead(uint16 addr) -> uint8 {
|
auto IO::portRead(uint16 addr) -> uint8 {
|
||||||
print("[", hex(addr, 4L), "]: port unmapped\n");
|
//print("[", hex(addr, 4L), "]: port unmapped\n");
|
||||||
return 0x00;
|
return 0x00;
|
||||||
}
|
}
|
||||||
|
|
||||||
auto IO::portWrite(uint16 addr, uint8 data) -> void {
|
auto IO::portWrite(uint16 addr, uint8 data) -> void {
|
||||||
print("[", hex(addr, 4L), "] = ", hex(data, 2L), ": port unmapped\n");
|
//print("[", hex(addr, 4L), "] = ", hex(data, 2L), ": port unmapped\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
auto Bus::read(uint20 addr) -> uint8 {
|
auto Bus::read(uint20 addr) -> uint8 {
|
||||||
|
|
Loading…
Reference in New Issue