diff --git a/higan/emulator/emulator.hpp b/higan/emulator/emulator.hpp index 4a87e31e..3b9c6a7c 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.06"; + static const string Version = "097.07"; static const string Author = "byuu"; static const string License = "GPLv3"; static const string Website = "http://byuu.org/"; diff --git a/higan/processor/arm/arm.hpp b/higan/processor/arm/arm.hpp index 44f6f332..bea10663 100644 --- a/higan/processor/arm/arm.hpp +++ b/higan/processor/arm/arm.hpp @@ -1,5 +1,4 @@ -#ifndef PROCESSOR_ARM_HPP -#define PROCESSOR_ARM_HPP +#pragma once namespace Processor { @@ -65,5 +64,3 @@ struct ARM { }; } - -#endif diff --git a/higan/processor/arm/disassembler.cpp b/higan/processor/arm/disassembler.cpp index eb0728a3..6019b8eb 100644 --- a/higan/processor/arm/disassembler.cpp +++ b/higan/processor/arm/disassembler.cpp @@ -1,5 +1,3 @@ -#ifdef PROCESSOR_ARM_HPP - auto ARM::disassemble_arm_instruction(uint32 pc) -> string { static string conditions[] = { "eq", "ne", "cs", "cc", @@ -777,5 +775,3 @@ auto ARM::disassemble_registers() -> string { output.append("/", hex(spsr().m, 2L)); return output; } - -#endif diff --git a/higan/processor/arm/instructions-arm.cpp b/higan/processor/arm/instructions-arm.cpp index 77722e0f..2e735758 100644 --- a/higan/processor/arm/instructions-arm.cpp +++ b/higan/processor/arm/instructions-arm.cpp @@ -1,5 +1,3 @@ -#ifdef PROCESSOR_ARM_HPP - auto ARM::arm_opcode(uint32 rm) { uint4 opcode = instruction() >> 21; uint1 save = instruction() >> 20; @@ -585,5 +583,3 @@ auto ARM::arm_op_software_interrupt() { vector(0x00000008, Processor::Mode::SVC); } - -#endif diff --git a/higan/processor/arm/instructions-thumb.cpp b/higan/processor/arm/instructions-thumb.cpp index c5891c3f..8a5ec7a2 100644 --- a/higan/processor/arm/instructions-thumb.cpp +++ b/higan/processor/arm/instructions-thumb.cpp @@ -1,5 +1,3 @@ -#ifdef PROCESSOR_ARM_HPP - auto ARM::thumb_opcode(uint4 opcode, uint4 d, uint4 m) { switch(opcode) { case 0: r(d) = bit(r(d) & r(m)); break; //AND @@ -372,5 +370,3 @@ auto ARM::thumb_op_branch_long_suffix() { r(15) = r(14) + (offsetlo * 2); r(14) = pipeline.decode.address | 1; } - -#endif diff --git a/higan/processor/arm/registers.cpp b/higan/processor/arm/registers.cpp index da91d6f3..3e29dd18 100644 --- a/higan/processor/arm/registers.cpp +++ b/higan/processor/arm/registers.cpp @@ -1,5 +1,3 @@ -#ifdef PROCESSOR_ARM_HPP - auto ARM::Processor::power() -> void { r0 = r1 = r2 = r3 = r4 = r5 = r6 = r7 = 0; usr.r8 = usr.r9 = usr.r10 = usr.r11 = usr.r12 = usr.sp = usr.lr = 0; @@ -59,5 +57,3 @@ auto ARM::Processor::setMode(Mode mode) -> void { default: r[13] = &usr.sp; r[14] = &usr.lr; spsr = nullptr; break; } } - -#endif diff --git a/higan/processor/gsu/gsu.hpp b/higan/processor/gsu/gsu.hpp index 99b06beb..dbf146a8 100644 --- a/higan/processor/gsu/gsu.hpp +++ b/higan/processor/gsu/gsu.hpp @@ -1,5 +1,4 @@ -#ifndef PROCESSOR_GSU_HPP -#define PROCESSOR_GSU_HPP +#pragma once namespace Processor { @@ -117,5 +116,3 @@ struct GSU { }; } - -#endif diff --git a/higan/processor/hg51b/hg51b.hpp b/higan/processor/hg51b/hg51b.hpp index 7b13807f..3bf2150d 100644 --- a/higan/processor/hg51b/hg51b.hpp +++ b/higan/processor/hg51b/hg51b.hpp @@ -1,7 +1,6 @@ //Hitachi HG51B169 (HG51BS family/derivative?) -#ifndef PROCESSOR_HG51B_HPP -#define PROCESSOR_HG51B_HPP +#pragma once namespace Processor { @@ -54,5 +53,3 @@ protected: }; } - -#endif diff --git a/higan/processor/hg51b/instructions.cpp b/higan/processor/hg51b/instructions.cpp index 05d492d3..dc215f82 100644 --- a/higan/processor/hg51b/instructions.cpp +++ b/higan/processor/hg51b/instructions.cpp @@ -1,5 +1,3 @@ -#ifdef PROCESSOR_HG51B_HPP - auto HG51B::push() -> void { stack[7] = stack[6]; stack[6] = stack[5]; @@ -352,5 +350,3 @@ auto HG51B::instruction() -> void { regs.halt = true; } } - -#endif diff --git a/higan/processor/hg51b/registers.cpp b/higan/processor/hg51b/registers.cpp index d4521a50..82f9698e 100644 --- a/higan/processor/hg51b/registers.cpp +++ b/higan/processor/hg51b/registers.cpp @@ -1,5 +1,3 @@ -#ifdef PROCESSOR_HG51B_HPP - auto HG51B::reg_read(uint8 addr) const -> uint24 { switch(addr) { case 0x00: return regs.a; @@ -74,5 +72,3 @@ auto HG51B::reg_write(uint8 addr, uint24 data) -> void { case 0x6f: regs.gpr[15] = data; return; } } - -#endif diff --git a/higan/processor/hg51b/serialization.cpp b/higan/processor/hg51b/serialization.cpp index 6b1c6579..b79cc7c3 100644 --- a/higan/processor/hg51b/serialization.cpp +++ b/higan/processor/hg51b/serialization.cpp @@ -1,5 +1,3 @@ -#ifdef PROCESSOR_HG51B_HPP - auto HG51B::serialize(serializer& s) -> void { s.array(dataRAM); for(auto& n : stack) s.integer(n); @@ -23,5 +21,3 @@ auto HG51B::serialize(serializer& s) -> void { s.integer(regs.ramaddr); for(auto& n : regs.gpr) s.integer(n); } - -#endif diff --git a/higan/processor/lr35902/lr35902.hpp b/higan/processor/lr35902/lr35902.hpp index 490f0956..f980655d 100644 --- a/higan/processor/lr35902/lr35902.hpp +++ b/higan/processor/lr35902/lr35902.hpp @@ -1,7 +1,6 @@ //Sharp LR35902 (Game Boy Z80-derivative) -#ifndef PROCESSOR_LR35902_HPP -#define PROCESSOR_LR35902_HPP +#pragma once namespace Processor { @@ -164,5 +163,3 @@ privileged: }; } - -#endif diff --git a/higan/processor/r6502/r6502.hpp b/higan/processor/r6502/r6502.hpp index 5c9147f5..bdf3c629 100644 --- a/higan/processor/r6502/r6502.hpp +++ b/higan/processor/r6502/r6502.hpp @@ -2,8 +2,7 @@ //* Ricoh 2A03 //* Ricoh 2A07 -#ifndef PROCESSOR_R6502_HPP -#define PROCESSOR_R6502_HPP +#pragma once namespace Processor { @@ -114,5 +113,3 @@ struct R6502 { }; } - -#endif diff --git a/higan/processor/r65816/r65816.hpp b/higan/processor/r65816/r65816.hpp index 88ac1c33..f63e9c55 100644 --- a/higan/processor/r65816/r65816.hpp +++ b/higan/processor/r65816/r65816.hpp @@ -1,12 +1,11 @@ -#ifndef PROCESSOR_R65816_HPP -#define PROCESSOR_R65816_HPP - -namespace Processor { - //WDC 65C816 CPU core //* Ricoh 5A22 //* Nintendo SA-1 +#pragma once + +namespace Processor { + struct R65816 { #include "registers.hpp" #include "memory.hpp" @@ -227,5 +226,3 @@ struct R65816 { }; } - -#endif diff --git a/higan/processor/spc700/spc700.hpp b/higan/processor/spc700/spc700.hpp index 02605715..95a477bd 100644 --- a/higan/processor/spc700/spc700.hpp +++ b/higan/processor/spc700/spc700.hpp @@ -1,5 +1,4 @@ -#ifndef PROCESSOR_SPC700_HPP -#define PROCESSOR_SPC700_HPP +#pragma once namespace Processor { @@ -104,5 +103,3 @@ protected: }; } - -#endif diff --git a/higan/processor/upd96050/upd96050.hpp b/higan/processor/upd96050/upd96050.hpp index dcede251..baa59fd8 100644 --- a/higan/processor/upd96050/upd96050.hpp +++ b/higan/processor/upd96050/upd96050.hpp @@ -2,8 +2,7 @@ //NEC uPD7725 //NEC uPD96050 -#ifndef PROCESSOR_UPD96050_HPP -#define PROCESSOR_UPD96050_HPP +#pragma once namespace Processor { @@ -72,5 +71,3 @@ struct uPD96050 { }; } - -#endif diff --git a/higan/processor/v30mz/algorithms.cpp b/higan/processor/v30mz/algorithms.cpp index 4af15058..f4f6e263 100644 --- a/higan/processor/v30mz/algorithms.cpp +++ b/higan/processor/v30mz/algorithms.cpp @@ -7,15 +7,153 @@ auto V30MZ::parity(uint16 value) const -> bool { return !(value & 1); } +#define bits (size == Byte ? 8 : 16) +#define mask (size == Byte ? 0xff : 0xffff) +#define sign (size == Byte ? 0x80 : 0xffff) + +auto V30MZ::alAdc(Size size, uint16 x, uint16 y) -> uint16 { + return alAdd(size, x, y + r.f.c); +} + +auto V30MZ::alAdd(Size size, uint16 x, uint16 y) -> uint16 { + uint16 result = (x + y) & mask; + r.f.c = x + y > mask; + r.f.p = parity(result); + r.f.h = (uint4)x + (uint4)y >= 16; + r.f.z = result == 0; + r.f.s = result & sign; + r.f.v = (result ^ x) & (result ^ y) & sign; + return result; +} + 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; + uint16 result = (x & y) & mask; r.f.c = 0; r.f.p = parity(result); r.f.h = 0; r.f.z = result == 0; - r.f.s = result & mask; + r.f.s = result & sign; r.f.v = 0; return result; } + +auto V30MZ::alOr(Size size, uint16 x, uint16 y) -> uint16 { + uint16 result = (x | y) & mask; + r.f.c = 0; + r.f.p = parity(result); + r.f.h = 0; + r.f.z = result == 0; + r.f.s = result & sign; + r.f.v = 0; + return result; +} + +auto V30MZ::alRcl(Size size, uint16 x, uint5 y) -> uint16 { + uint16 result = x; + for(uint n = 0; n < y; n++) { + bool carry = result & sign; + result = (result << 1) | carry; + r.f.c = carry; + } + r.f.v = (x ^ result) & sign; + return result & mask; +} + +auto V30MZ::alRcr(Size size, uint16 x, uint5 y) -> uint16 { + uint16 result = x; + for(uint n = 0; n < y; n++) { + bool carry = result & 1; + result = (carry ? sign : 0) | (result >> 1); + r.f.c = carry; + } + r.f.v = (x ^ result) & sign; + return result & mask; +} + +auto V30MZ::alRol(Size size, uint16 x, uint4 y) -> uint16 { + r.f.c = (x << y) & (1 << bits); + uint16 result = ((x << y) | (x >> (bits - y))) & mask; + r.f.v = (x ^ result) & sign; + return result; +} + +auto V30MZ::alRor(Size size, uint16 x, uint4 y) -> uint16 { + r.f.c = (x >> (y - 1)) & 1; + uint16 result = ((x >> y) | (x << (bits - y))) & mask; + r.f.v = (x ^ result) & sign; + return result; +} + +auto V30MZ::alSal(Size size, uint16 x, uint5 y) -> uint16 { + r.f.c = (x << y) & (1 << bits); + uint16 result = (x << y) & mask; + r.f.p = parity(result); + r.f.z = result == 0; + r.f.s = result & sign; + r.f.v = 0; + return result; +} + +auto V30MZ::alSar(Size size, uint16 x, uint5 y) -> uint16 { + if(y & 16) { + r.f.c = x & sign; + return 0 - r.f.c; + } + r.f.c = (x >> (y - 1)) & 1; + uint16 result = (x >> y) & mask; + if(x & sign) result |= mask << (bits - y); + r.f.p = parity(result); + r.f.z = result == 0; + r.f.s = result & sign; + r.f.v = 0; + return result; +} + +auto V30MZ::alSbb(Size size, uint16 x, uint16 y) -> uint16 { + return alSub(size, x, y + r.f.c); +} + +auto V30MZ::alShl(Size size, uint16 x, uint5 y) -> uint16 { + r.f.c = (x << y) & (1 << bits); + uint16 result = (x << y) & mask; + r.f.p = parity(result); + r.f.z = result == 0; + r.f.s = result & sign; + r.f.v = (x ^ result) & sign; + return result; +} + +auto V30MZ::alShr(Size size, uint16 x, uint5 y) -> uint16 { + r.f.c = (x >> (y - 1)) & 1; + uint16 result = (x >> y) & mask; + r.f.p = parity(result); + r.f.z = result == 0; + r.f.s = result & sign; + r.f.v = (x ^ result) & sign; + return result; +} + +auto V30MZ::alSub(Size size, uint16 x, uint16 y) -> uint16 { + uint16 result = (x - y) & mask; + r.f.c = y > x; + r.f.p = parity(result); + r.f.h = (uint4)y > (uint4)x; + r.f.z = result == 0; + r.f.s = result & sign; + r.f.v = (x ^ y) & (x ^ result) & sign; + return result; +} + +auto V30MZ::alXor(Size size, uint16 x, uint16 y) -> uint16 { + uint16 result = (x ^ y) & mask; + r.f.c = 0; + r.f.p = parity(result); + r.f.h = 0; + r.f.z = result == 0; + r.f.s = result & sign; + r.f.v = 0; + return result; +} + +#undef mask +#undef sign diff --git a/higan/processor/v30mz/disassembler.cpp b/higan/processor/v30mz/disassembler.cpp index 80599369..f0b3e798 100644 --- a/higan/processor/v30mz/disassembler.cpp +++ b/higan/processor/v30mz/disassembler.cpp @@ -1,43 +1,80 @@ -auto V30MZ::disassemble(uint16 cs, uint16 ip, bool registers) -> string { +auto V30MZ::disassemble(uint16 cs, uint16 ip, bool registers, bool bytes) -> string { string s; - uint20 ea = (cs << 4) + ip; + uint20 ea = cs * 16 + ip; + vector bytesRead; - enum : uint { Byte, Word, Segment }; - auto readByte = [&](uint offset) -> string { - uint8 byte = read((cs << 4) + (uint16)(ip + offset++)); + auto fetch = [&](bool inc = true) -> uint8 { + uint8 data = read(cs * 16 + ip); + if(inc) ip++, bytesRead.append(data); + return data; + }; + auto readByte = [&]() -> string { + uint8 byte = fetch(); return {"$", hex(byte, 2L)}; }; - auto readWord = [&](uint offset) -> string { - uint16 word = read((cs << 4) + (uint16)(ip + offset++)) << 0; - word |= read((cs << 4) + (uint16)(ip + offset++)) << 8; + auto readWord = [&]() -> string { + uint16 word = fetch(); word |= fetch() << 8; return {"$", hex(word, 4L)}; }; - auto readRelativeByte = [&](uint offset, uint displacement) -> string { - uint8 byte = read((cs << 4) + (uint16)(ip + offset++)); - return {"$", hex(ip + displacement + (int8)byte, 4L)}; + auto readByteSigned = [&]() -> string { + uint8 byte = fetch(); + return {"$", byte & 0x80 ? "-" : "+", hex(byte & 0x80 ? 256 - byte : byte, 2L)}; }; - auto readRelativeWord = [&](uint offset, uint displacement) -> string { - uint16 word = read((cs << 4) + (uint16)(ip + offset++)) << 0; - word |= read((cs << 4) + (uint16)(ip + offset++)) << 8; - return {"$", hex(ip + displacement + (int16)word, 4L)}; + auto readRelativeByte = [&]() -> string { + uint8 byte = fetch(); + return {"$", hex(ip + (int8)byte, 4L)}; }; - auto readModRM = [&](uint offset, uint mode) -> string { - uint8 modRM = read((cs << 4) + (uint16)(ip + offset++)); - static const string reg[3][8] = { - {"al", "cl", "dl", "bl", "ah", "ch", "dh", "bh"}, - {"ax", "cx", "dx", "bx", "sp", "bp", "si", "di"}, - {"es", "cs", "ss", "ds", "es", "cs", "ss", "ds"}, - }; - string d = reg[mode][(uint3)(modRM >> 3)]; - if(modRM >= 0xc0) return {d, ",", reg[Word][modRM & 7]}; - if((modRM & 0xc7) == 0x06) return {d, ",[", readWord(offset), "]"}; - static const string mem[8] = {"bx+si", "bx+di", "bp+si", "bp+di", "si", "di", "bp", "bx"}; - if((modRM & 0xc0) == 0x40) return {d, ",[", mem[modRM & 7], "+", readByte(offset), "]"}; - if((modRM & 0xc0) == 0x80) return {d, ",[", mem[modRM & 7], "+", readWord(offset), "]"}; - return {d, ",[", mem[modRM & 7], "]"}; + auto readRelativeWord = [&]() -> string { + uint16 word = fetch(); word |= fetch() << 8; + return {"$", hex(ip + (int16)word, 4L)}; }; - auto readRepeat = [&](uint offset) -> string { - uint8 opcode = read((cs << 4) + (uint16)(ip + offset++)); + auto readRegByte = [&](bool inc = true) -> string { + uint8 modRM = fetch(inc); + static const string reg[] = {"al", "cl", "dl", "bl", "ah", "ch", "dh", "bh"}; + return reg[(uint3)(modRM >> 3)]; + }; + auto readRegWord = [&](bool inc = true) -> string { + uint8 modRM = fetch(inc); + static const string reg[] = {"ax", "cx", "dx", "bx", "sp", "bp", "si", "di"}; + return reg[(uint3)(modRM >> 3)]; + }; + auto readSeg = [&](bool inc = true) -> string { + uint8 modRM = fetch(inc); + static const string seg[] = {"es", "cs", "ss", "ds"}; + return seg[(uint2)(modRM >> 3)]; + }; + auto readMemByte = [&](bool inc = true) -> string { + uint8 modRM = fetch(inc); + static const string reg[] = {"al", "cl", "dl", "bl", "ah", "ch", "dh", "bh"}; + if(modRM >= 0xc0) return reg[(uint3)modRM]; + if((modRM & 0xc7) == 0x06) return {"[", readWord(), "]"}; + static const string mem[] = {"bx+si", "bx+di", "bp+si", "bp+di", "si", "di", "bp", "bx"}; + if((modRM & 0xc0) == 0x40) return {"[", mem[(uint3)modRM], "+", readByte(), "]"}; + if((modRM & 0xc0) == 0x80) return {"[", mem[(uint3)modRM], "+", readWord(), "]"}; + return {"[", mem[(uint3)modRM], "]"}; + }; + auto readMemWord = [&](bool inc = true) -> string { + uint8 modRM = fetch(inc); + static const string reg[] = {"ax", "cx", "dx", "bx", "sp", "bp", "si", "di"}; + if(modRM >= 0xc0) return reg[(uint3)modRM]; + if((modRM & 0xc7) == 0x06) return {"[", readWord(), "]"}; + static const string mem[] = {"bx+si", "bx+di", "bp+si", "bp+di", "si", "di", "bp", "bx"}; + if((modRM & 0xc0) == 0x40) return {"[", mem[(uint3)modRM], "+", readByte(), "]"}; + if((modRM & 0xc0) == 0x80) return {"[", mem[(uint3)modRM], "+", readWord(), "]"}; + return {"[", mem[(uint3)modRM], "]"}; + }; + auto readGroup1 = [&]() -> string { + uint8 modRM = fetch(false); + static const string grp[] = {"add", "or ", "adc", "sbb", "and", "sub", "xor", "cmp"}; + return grp[(uint3)(modRM >> 3)]; + }; + auto readGroup2 = [&]() -> string { + 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"; @@ -57,63 +94,176 @@ auto V30MZ::disassemble(uint16 cs, uint16 ip, bool registers) -> string { return ""; }; - auto opcode = read(ea); + auto opcode = fetch(); 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 0x00: s = {"add {0},{1}", format{readMemByte(0), readRegByte()}}; break; + case 0x01: s = {"add {0},{1}", format{readMemWord(0), readRegWord()}}; break; + case 0x02: s = {"add {0},{1}", format{readRegByte(0), readMemByte()}}; break; + case 0x03: s = {"add {0},{1}", format{readRegWord(0), readMemWord()}}; break; + case 0x04: s = {"add al,{0}", format{readByte()}}; break; + case 0x05: s = {"add ax,{0}", format{readWord()}}; break; + case 0x08: s = {"or {0},{1}", format{readMemByte(0), readRegByte()}}; break; + case 0x09: s = {"or {0},{1}", format{readMemWord(0), readRegWord()}}; break; + case 0x0a: s = {"or {0},{1}", format{readRegByte(0), readMemByte()}}; break; + case 0x0b: s = {"or {0},{1}", format{readRegWord(0), readMemWord()}}; break; + case 0x0c: s = {"or al,{0}", format{readByte()}}; break; + case 0x0d: s = {"or ax,{0}", format{readWord()}}; break; + case 0x10: s = {"adc {0},{1}", format{readMemByte(0), readRegByte()}}; break; + case 0x11: s = {"adc {0},{1}", format{readMemWord(0), readRegWord()}}; break; + case 0x12: s = {"adc {0},{1}", format{readRegByte(0), readMemByte()}}; break; + case 0x13: s = {"adc {0},{1}", format{readRegWord(0), readMemWord()}}; break; + case 0x14: s = {"adc al,{0}", format{readByte()}}; break; + case 0x15: s = {"adc ax,{0}", format{readWord()}}; break; + case 0x18: s = {"sbb {0},{1}", format{readMemByte(0), readRegByte()}}; break; + case 0x19: s = {"sbb {0},{1}", format{readMemWord(0), readRegWord()}}; break; + case 0x1a: s = {"sbb {0},{1}", format{readRegByte(0), readMemByte()}}; break; + case 0x1b: s = {"sbb {0},{1}", format{readRegWord(0), readMemWord()}}; break; + case 0x1c: s = {"sbb al,{0}", format{readByte()}}; break; + case 0x1d: s = {"sbb ax,{0}", format{readWord()}}; break; + case 0x20: s = {"and {0},{1}", format{readMemByte(0), readRegByte()}}; break; + case 0x21: s = {"and {0},{1}", format{readMemWord(0), readRegWord()}}; break; + case 0x22: s = {"and {0},{1}", format{readRegByte(0), readMemByte()}}; break; + case 0x23: s = {"and {0},{1}", format{readRegWord(0), readMemWord()}}; break; + case 0x24: s = {"and al,{0}", format{readByte()}}; break; + case 0x25: s = {"and ax,{0}", format{readWord()}}; break; + case 0x26: s = {"es: "}; break; + case 0x28: s = {"sub {0},{1}", format{readMemByte(0), readRegByte()}}; break; + case 0x29: s = {"sub {0},{1}", format{readMemWord(0), readRegWord()}}; break; + case 0x2a: s = {"sub {0},{1}", format{readRegByte(0), readMemByte()}}; break; + case 0x2b: s = {"sub {0},{1}", format{readRegWord(0), readMemWord()}}; break; + case 0x2c: s = {"sub al,{0}", format{readByte()}}; break; + case 0x2d: s = {"sub ax,{0}", format{readWord()}}; break; + case 0x2e: s = {"cs: "}; break; + case 0x30: s = {"xor {0},{1}", format{readMemByte(0), readRegByte()}}; break; + case 0x31: s = {"xor {0},{1}", format{readMemWord(0), readRegWord()}}; break; + case 0x32: s = {"xor {0},{1}", format{readRegByte(0), readMemByte()}}; break; + case 0x33: s = {"xor {0},{1}", format{readRegWord(0), readMemWord()}}; break; + case 0x34: s = {"xor al,{0}", format{readByte()}}; break; + case 0x35: s = {"xor ax,{0}", format{readWord()}}; break; + case 0x36: s = {"ss: "}; break; + case 0x38: s = {"cmp {0},{1}", format{readMemByte(0), readRegByte()}}; break; + case 0x39: s = {"cmp {0},{1}", format{readMemWord(0), readRegWord()}}; break; + case 0x3a: s = {"cmp {0},{1}", format{readRegByte(0), readMemByte()}}; break; + case 0x3b: s = {"cmp {0},{1}", format{readRegWord(0), readMemWord()}}; break; + case 0x3c: s = {"cmp al,{0}", format{readByte()}}; break; + case 0x3d: s = {"cmp ax,{0}", format{readWord()}}; break; + case 0x3e: s = {"ds: "}; break; + case 0x40: s = {"inc ax"}; break; + case 0x41: s = {"inc cx"}; break; + case 0x42: s = {"inc dx"}; break; + case 0x43: s = {"inc bx"}; break; + case 0x44: s = {"inc sp"}; break; + case 0x45: s = {"inc bp"}; break; + case 0x46: s = {"inc si"}; break; + case 0x47: s = {"inc di"}; break; + case 0x48: s = {"dec ax"}; break; + case 0x49: s = {"dec cx"}; break; + case 0x4a: s = {"dec dx"}; break; + case 0x4b: s = {"dec bx"}; break; + case 0x4c: s = {"dec sp"}; break; + case 0x4d: s = {"dec bp"}; break; + case 0x4e: s = {"dec si"}; break; + case 0x4f: s = {"dec di"}; break; + case 0x50: s = {"push ax"}; break; + case 0x51: s = {"push cx"}; break; + case 0x52: s = {"push dx"}; break; + case 0x53: s = {"push bx"}; break; + case 0x54: s = {"push sp"}; break; + case 0x55: s = {"push bp"}; break; + case 0x56: s = {"push si"}; break; + case 0x57: s = {"push di"}; break; + case 0x58: s = {"pop ax"}; break; + case 0x59: s = {"pop cx"}; break; + case 0x5a: s = {"pop dx"}; break; + case 0x5b: s = {"pop bx"}; break; + case 0x5c: s = {"pop sp"}; break; + case 0x5d: s = {"pop bp"}; break; + case 0x5e: s = {"pop si"}; break; + case 0x5f: s = {"pop di"}; break; + case 0x70: s = {"jo {0}", format{readRelativeByte()}}; break; + case 0x71: s = {"jno {0}", format{readRelativeByte()}}; break; + case 0x72: s = {"jc {0}", format{readRelativeByte()}}; break; + case 0x73: s = {"jnc {0}", format{readRelativeByte()}}; break; + case 0x74: s = {"jz {0}", format{readRelativeByte()}}; break; + case 0x75: s = {"jnz {0}", format{readRelativeByte()}}; break; + case 0x76: s = {"jcz {0}", format{readRelativeByte()}}; break; + case 0x77: s = {"jncz {0}", format{readRelativeByte()}}; break; + case 0x78: s = {"js {0}", format{readRelativeByte()}}; break; + case 0x79: s = {"jns {0}", format{readRelativeByte()}}; break; + case 0x7a: s = {"jp {0}", format{readRelativeByte()}}; break; + case 0x7b: s = {"jnp {0}", format{readRelativeByte()}}; break; + case 0x7c: s = {"jl {0}", format{readRelativeByte()}}; break; + case 0x7d: s = {"jnl {0}", format{readRelativeByte()}}; break; + case 0x7e: s = {"jle {0}", format{readRelativeByte()}}; break; + case 0x7f: s = {"jnle {0}", format{readRelativeByte()}}; break; + case 0x80: s = {"{0} {1},{2}", format{readGroup1(), readMemByte(), readByte()}}; break; + case 0x81: s = {"{0} {1},{2}", format{readGroup1(), readMemWord(), readWord()}}; break; + case 0x82: s = {"{0} {1},{2}", format{readGroup1(), readMemByte(), readByteSigned()}}; break; + case 0x83: s = {"{0} {1},{2}", format{readGroup1(), readMemWord(), readByteSigned()}}; break; + case 0x88: s = {"mov {0},{1}", format{readMemByte(0), readRegByte()}}; break; + case 0x89: s = {"mov {0},{1}", format{readMemWord(0), readRegWord()}}; break; + case 0x8a: s = {"mov {0},{1}", format{readRegByte(0), readMemByte()}}; break; + case 0x8b: s = {"mov {0},{1}", format{readRegWord(0), readMemWord()}}; break; + case 0x8e: s = {"mov {0},{1}", format{readSeg(0), readMemWord()}}; break; case 0x90: s = {"nop "}; break; + case 0x9a: s = {"call {1}:{0}", format{readWord(), readWord()}}; break; + case 0xa0: s = {"mov al,[{0}]", format{readWord()}}; break; + case 0xa1: s = {"mov ax,[{0}]", format{readWord()}}; break; + case 0xa2: s = {"mov [{0}],al", format{readWord()}}; break; + case 0xa3: s = {"mov [{0}],ax", format{readWord()}}; 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 0xa8: s = {"test al,{0}", format{readByte()}}; break; + case 0xa9: s = {"test ax,{0}", format{readWord()}}; break; + case 0xaa: s = {"stosb "}; break; + case 0xab: s = {"stosw "}; break; + case 0xb0: s = {"mov al,{0}", format{readByte()}}; break; + case 0xb1: s = {"mov cl,{0}", format{readByte()}}; break; + case 0xb2: s = {"mov dl,{0}", format{readByte()}}; break; + case 0xb3: s = {"mov bl,{0}", format{readByte()}}; break; + case 0xb4: s = {"mov ah,{0}", format{readByte()}}; break; + case 0xb5: s = {"mov ch,{0}", format{readByte()}}; break; + case 0xb6: s = {"mov dh,{0}", format{readByte()}}; break; + case 0xb7: s = {"mov bh,{0}", format{readByte()}}; break; + case 0xb8: s = {"mov ax,{0}", format{readWord()}}; break; + case 0xb9: s = {"mov cx,{0}", format{readWord()}}; break; + case 0xba: s = {"mov dx,{0}", format{readWord()}}; break; + case 0xbb: s = {"mov bx,{0}", format{readWord()}}; break; + case 0xbc: s = {"mov sp,{0}", format{readWord()}}; break; + case 0xbd: s = {"mov bp,{0}", format{readWord()}}; break; + case 0xbe: s = {"mov si,{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 0xc1: s = {"{0}w {1},{2}", format{readGroup2(), readMemWord(), readByte()}}; 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 0xc6: s = {"mov {0},{1}", format{readMemByte(), readByte()}}; break; + case 0xc7: s = {"mov {0},{1}", format{readMemWord(), readWord()}}; break; + case 0xcb: s = {"retf "}; break; + case 0xd0: s = {"{0} {1},1", format{readGroup2(), readMemByte()}}; break; + case 0xd1: s = {"{0}w {1},1", format{readGroup2(), readMemWord()}}; break; + case 0xd2: s = {"{0} {1},cl", format{readGroup2(), readMemByte()}}; break; + case 0xd3: s = {"{0}w {1},cl", format{readGroup2(), readMemWord()}}; break; + case 0xd8: s = {"fpo1 d8"}; break; + case 0xd9: s = {"fpo1 d9"}; break; + case 0xda: s = {"fpo1 da"}; break; + case 0xdb: s = {"fpo1 db"}; break; + case 0xdc: s = {"fpo1 dc"}; break; + case 0xdd: s = {"fpo1 dd"}; break; + case 0xde: s = {"fpo1 de"}; break; + case 0xdf: s = {"fpo1 df"}; break; + case 0xe4: s = {"in al,{0}", format{readByte()}}; break; + case 0xe5: s = {"in ax,{0}", format{readByte()}}; break; + case 0xe6: s = {"out {0},al", format{readByte()}}; break; + case 0xe7: s = {"out {0},ax", format{readByte()}}; break; + case 0xe8: s = {"call {0}", format{readRelativeWord()}}; break; + case 0xea: s = {"jmp {1}:{0}", format{readWord(), readWord()}}; break; + case 0xeb: s = {"jmp {0}", format{readRelativeByte()}}; 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 0xf2: s = {"repnz {0}", format{readRepeat()}}; break; + case 0xf3: s = {"repz {0}", format{readRepeat()}}; break; case 0xf8: s = {"clc "}; break; case 0xf9: s = {"stc "}; break; case 0xfa: s = {"cli "}; break; @@ -124,34 +274,45 @@ auto V30MZ::disassemble(uint16 cs, uint16 ip, bool registers) -> string { default: s = {"??? [", hex(opcode, 2L), "]"}; } - while(s.size() < 20) s.append(" "); + while(s.size() < 24) s.append(" "); - if(!registers) return {hex(ea, 5L), " ", s}; + string l; + if(registers) { + l = { + " ax:", hex(r.ax, 4L), + " bx:", hex(r.bx, 4L), + " cx:", hex(r.cx, 4L), + " dx:", hex(r.dx, 4L), + " si:", hex(r.si, 4L), + " di:", hex(r.di, 4L), + " bp:", hex(r.bp, 4L), + " sp:", hex(r.sp, 4L), + " ip:", hex(r.ip, 4L), + " cs:", hex(r.cs, 4L), + " ds:", hex(r.ds, 4L), + " es:", hex(r.es, 4L), + " ss:", hex(r.ss, 4L), " ", + r.f.m ? "M" : "m", + r.f.v ? "V" : "v", + r.f.d ? "D" : "d", + r.f.i ? "I" : "i", + r.f.b ? "B" : "b", + r.f.s ? "S" : "s", + r.f.z ? "Z" : "z", + r.f.h ? "H" : "h", + r.f.p ? "P" : "p", + r.f.c ? "C" : "c" + }; + } - return { - hex(ea, 5L), " ", s, - " ax:", hex(r.ax, 4L), - " bx:", hex(r.bx, 4L), - " cx:", hex(r.cx, 4L), - " dx:", hex(r.dx, 4L), - " si:", hex(r.si, 4L), - " di:", hex(r.di, 4L), - " bp:", hex(r.bp, 4L), - " sp:", hex(r.sp, 4L), - " ip:", hex(r.ip, 4L), - " cs:", hex(r.cs, 4L), - " ds:", hex(r.ds, 4L), - " es:", hex(r.es, 4L), - " ss:", hex(r.ss, 4L), " ", - r.f.m ? "M" : "m", - r.f.v ? "V" : "v", - r.f.d ? "D" : "d", - r.f.i ? "I" : "i", - r.f.b ? "B" : "b", - r.f.s ? "S" : "s", - r.f.z ? "Z" : "z", - r.f.h ? "H" : "h", - r.f.p ? "P" : "p", - r.f.c ? "C" : "c" - }; + string b; + if(bytes) { + b = " "; + while(bytesRead) { + b.append(hex(bytesRead.takeFirst(), 2L), " "); + } + b.rstrip(); + } + + return {hex(ea, 5L), " ", s, l, b}; } diff --git a/higan/processor/v30mz/instructions.cpp b/higan/processor/v30mz/instructions.cpp index 183f9e93..f6f22a5f 100644 --- a/higan/processor/v30mz/instructions.cpp +++ b/higan/processor/v30mz/instructions.cpp @@ -1,25 +1,227 @@ -auto V30MZ::opXorRegisterModRM(Size size) { - auto modRM = readIP(); - setRegister(size, modRM, getRegister(size, modRM) ^ readModRM(size, modRM)); +//00 addb mem,reg +//01 addw mem,reg +auto V30MZ::opAddMemReg(Size size) { + auto modRM = fetch(); + setMem(size, modRM, alAdd(size, getMem(size, modRM), getReg(size, modRM))); +} + +//02 addb reg,mem +//03 addw reg,mem +auto V30MZ::opAddRegMem(Size size) { + auto modRM = fetch(); + setReg(size, modRM, alAdd(size, getReg(size, modRM), getMem(size, modRM))); +} + +//04 add al,#imm +//05 add ax,#imm +auto V30MZ::opAddAccImm(Size size) { + setAcc(size, alAdd(size, getAcc(size), fetch(size))); +} + +//08 orb mem,reg +//09 orb mem,reg +auto V30MZ::opOrMemReg(Size size) { + auto modRM = fetch(); + setMem(size, modRM, alOr(size, getMem(size, modRM), getReg(size, modRM))); +} + +//0a orb reg,mem +//0b orb reg,mem +auto V30MZ::opOrRegMem(Size size) { + auto modRM = fetch(); + setReg(size, modRM, alOr(size, getReg(size, modRM), getMem(size, modRM))); +} + +//0c or al,#imm +//0d or ax,#imm +auto V30MZ::opOrAccImm(Size size) { + setAcc(size, alOr(size, getAcc(size), fetch(size))); +} + +auto V30MZ::opAdcMemReg(Size size) { + auto modRM = fetch(); + setMem(size, modRM, alAdc(size, getMem(size, modRM), getReg(size, modRM))); +} + +auto V30MZ::opAdcRegMem(Size size) { + auto modRM = fetch(); + setReg(size, modRM, alAdc(size, getReg(size, modRM), getMem(size, modRM))); +} + +auto V30MZ::opAdcAccImm(Size size) { + setAcc(size, alAdc(size, getAcc(size), fetch(size))); +} + +auto V30MZ::opSbbMemReg(Size size) { + auto modRM = fetch(); + setMem(size, modRM, alSbb(size, getMem(size, modRM), getReg(size, modRM))); +} + +auto V30MZ::opSbbRegMem(Size size) { + auto modRM = fetch(); + setReg(size, modRM, alSbb(size, getReg(size, modRM), getMem(size, modRM))); +} + +auto V30MZ::opSbbAccImm(Size size) { + setAcc(size, alSbb(size, getAcc(size), fetch(size))); +} + +auto V30MZ::opAndMemReg(Size size) { + auto modRM = fetch(); + setMem(size, modRM, alAnd(size, getMem(size, modRM), getReg(size, modRM))); +} + +auto V30MZ::opAndRegMem(Size size) { + auto modRM = fetch(); + setReg(size, modRM, alAnd(size, getReg(size, modRM), getMem(size, modRM))); +} + +auto V30MZ::opAndAccImm(Size size) { + setAcc(size, alAnd(size, getAcc(size), fetch(size))); +} + +auto V30MZ::opSubMemReg(Size size) { + auto modRM = fetch(); + setMem(size, modRM, alSub(size, getMem(size, modRM), getReg(size, modRM))); +} + +auto V30MZ::opSubRegMem(Size size) { + auto modRM = fetch(); + setReg(size, modRM, alSub(size, getReg(size, modRM), getMem(size, modRM))); +} + +auto V30MZ::opSubAccImm(Size size) { + setAcc(size, alSub(size, getAcc(size), fetch(size))); +} + +//26 es: +//2e cs: +//36 ss: +//3e ds: +auto V30MZ::opPrefix(uint16& segment) { + //todo +} + +auto V30MZ::opXorMemReg(Size size) { + auto modRM = fetch(); + setMem(size, modRM, alXor(size, getMem(size, modRM), getReg(size, modRM))); +} + +auto V30MZ::opXorRegMem(Size size) { + auto modRM = fetch(); + setReg(size, modRM, alXor(size, getReg(size, modRM), getMem(size, modRM))); +} + +auto V30MZ::opXorAccImm(Size size) { + setAcc(size, alXor(size, getAcc(size), fetch(size))); +} + +auto V30MZ::opCmpMemReg(Size size) { + auto modRM = fetch(); + alSub(size, getMem(size, modRM), getReg(size, modRM)); +} + +auto V30MZ::opCmpRegMem(Size size) { + auto modRM = fetch(); + alSub(size, getReg(size, modRM), getMem(size, modRM)); +} + +auto V30MZ::opCmpAccImm(Size size) { + alSub(size, getAcc(size), fetch(size)); +} + +//40 inc ax +//41 inc cx +//42 inc dx +//43 inc bx +//44 inc sp +//45 inc bp +//46 inc si +//47 inc di +auto V30MZ::opIncReg(uint16& reg) { + reg++; +} + +//48 dec ax +//49 dec cx +//4a dec dx +//4b dec bx +//4c dec sp +//4d dec bp +//4e dec si +//4f dec di +auto V30MZ::opDecReg(uint16& reg) { + reg--; +} + +auto V30MZ::opPushReg(uint16& reg) { + push(reg); +} + +auto V30MZ::opPopReg(uint16& reg) { + reg = pop(); } auto V30MZ::opJumpIf(bool condition) { - auto displacement = (int8)readIP(); - if(condition) r.ip += displacement; + auto offset = (int8)fetch(); + if(condition) r.ip += offset; } -auto V30MZ::opMoveRegisterModRM(Size size) { - auto modRM = readIP(); - setRegister(size, modRM, readModRM(size, modRM)); +//80 grp1 memb,imm8 +//81 grp1 memw,imm16 +//82 grp1 memb,imm8s +//83 grp1 memw,imm8s +auto V30MZ::opGroup1MemImm(Size size, bool sign) { + auto modRM = fetch(); + auto imm = sign ? (int8)fetch() : size == Byte ? fetch() : fetch(Word); + auto mem = getMem(size, modRM); + switch((uint3)(modRM >> 3)) { + case 0: setMem(size, modRM, alAdd(size, mem, imm)); break; + case 1: setMem(size, modRM, alOr (size, mem, imm)); break; + case 2: setMem(size, modRM, alAdc(size, mem, imm)); break; + case 3: setMem(size, modRM, alSbb(size, mem, imm)); break; + case 4: setMem(size, modRM, alAnd(size, mem, imm)); break; + case 5: setMem(size, modRM, alSub(size, mem, imm)); break; + case 6: setMem(size, modRM, alXor(size, mem, imm)); break; + case 7: alSub(size, mem, imm); break; + } } -auto V30MZ::opMoveSegmentRegisterModRM() { +auto V30MZ::opMoveMemReg(Size size) { + auto modRM = fetch(); + setMem(size, modRM, getReg(size, modRM)); +} + +auto V30MZ::opMoveRegMem(Size size) { + auto modRM = fetch(); + setReg(size, modRM, getMem(size, modRM)); +} + +auto V30MZ::opMoveSegMem() { wait(1); - auto modRM = readIP(); - setSegment(modRM, readModRM(Word, modRM)); + auto modRM = fetch(); + setSeg(modRM, getMem(Word, modRM)); } -auto V30MZ::opNoOperation() { +auto V30MZ::opNop() { +} + +auto V30MZ::opCallFar() { + wait(9); + auto ip = fetch(Word); + auto cs = fetch(Word); + push(r.cs); + push(r.ip); + r.cs = cs; + r.ip = ip; +} + +auto V30MZ::opMoveAccMem(Size size) { + setAcc(size, read(size, r.ds, fetch(Word))); +} + +auto V30MZ::opMoveMemAcc(Size size) { + write(size, r.ds, fetch(Word), getAcc(size)); } auto V30MZ::opMoveString(Size size) { @@ -29,26 +231,64 @@ auto V30MZ::opMoveString(Size size) { r.di += r.f.d ? -size : size; } -auto V30MZ::opTestAX(Size size) { - alAnd(size, r.ax, readIP(size)); +auto V30MZ::opTestAcc(Size size) { + alAnd(size, getAcc(size), fetch(size)); } -auto V30MZ::opMoveRegisterImmediate(uint8& rd) { - rd = readIP(Byte); +auto V30MZ::opStoreString(Size size) { + wait(2); + write(size, r.es, r.di, getAcc(size)); + r.di += r.f.d ? -size : size; } -auto V30MZ::opMoveRegisterImmediate(uint16& rd) { - rd = readIP(Word); +auto V30MZ::opMoveRegImm(uint8& reg) { + reg = fetch(Byte); +} + +auto V30MZ::opMoveRegImm(uint16& reg) { + reg = fetch(Word); } auto V30MZ::opReturn() { wait(5); - r.ip = readSP(); + r.ip = pop(); +} + +auto V30MZ::opMoveMemImm(Size size) { + auto modRM = fetch(); + setMem(size, modRM, fetch(size)); +} + +auto V30MZ::opRetFar() { + wait(7); + auto ip = pop(); + auto cs = pop(); + r.cs = cs; + r.ip = ip; +} + +auto V30MZ::opGroup2MemImm(Size size, maybe imm) { + auto modRM = fetch(); + if(!imm) { + wait(2); + imm = fetch(); + } + auto mem = getMem(size, modRM); + switch((uint3)(modRM >> 3)) { + case 0: setMem(size, modRM, alRol(size, mem, *imm)); break; + case 1: setMem(size, modRM, alRor(size, mem, *imm)); break; + case 2: setMem(size, modRM, alRcl(size, mem, *imm)); break; + case 3: setMem(size, modRM, alRcr(size, mem, *imm)); break; + case 4: setMem(size, modRM, alShl(size, mem, *imm)); break; + case 5: setMem(size, modRM, alShr(size, mem, *imm)); break; + case 6: setMem(size, modRM, alSal(size, mem, *imm)); break; + case 7: setMem(size, modRM, alSar(size, mem, *imm)); break; + } } auto V30MZ::opIn(Size size) { wait(5); - auto port = readIP(); + auto port = fetch(); r.al = in(port++); if(size != Word) return; r.ah = in(port++); @@ -56,7 +296,7 @@ auto V30MZ::opIn(Size size) { auto V30MZ::opOut(Size size) { wait(5); - auto port = readIP(); + auto port = fetch(); out(port++, r.al); if(size != Word) return; out(port++, r.ah); @@ -64,17 +304,23 @@ auto V30MZ::opOut(Size size) { auto V30MZ::opCallNear() { wait(4); - auto displacement = (int16)readIP(Word); - writeSP(r.ip); - r.ip += displacement; + auto offset = (int16)fetch(Word); + push(r.ip); + r.ip += offset; } auto V30MZ::opJumpFar() { wait(6); - auto ip = readIP(Word); - auto cs = readIP(Word); - r.ip = ip; + auto ip = fetch(Word); + auto cs = fetch(Word); r.cs = cs; + r.ip = ip; +} + +auto V30MZ::opJumpShort() { + wait(3); + auto offset = (int8)fetch(); + r.ip += offset; } auto V30MZ::opInDX(Size size) { @@ -93,7 +339,7 @@ auto V30MZ::opOutDX(Size size) { auto V30MZ::opRepeat(bool flag) { wait(4); - auto opcode = readIP(); + auto opcode = fetch(); if((opcode & 0xfc) != 0x6c && (opcode & 0xfc) != 0xa4 && (opcode & 0xfe) != 0xaa && (opcode & 0xfc) != 0xac) { //invalid argument @@ -106,6 +352,8 @@ auto V30MZ::opRepeat(bool flag) { switch(opcode) { 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; } } diff --git a/higan/processor/v30mz/memory.cpp b/higan/processor/v30mz/memory.cpp index c3cb70e6..5f4b4051 100644 --- a/higan/processor/v30mz/memory.cpp +++ b/higan/processor/v30mz/memory.cpp @@ -11,48 +11,19 @@ auto V30MZ::write(Size size, uint16 segment, uint16 address, uint16 data) -> voi // -auto V30MZ::readIP(Size size) -> uint16 { +auto V30MZ::fetch(Size size) -> uint16 { uint16 data = read(size, r.cs, r.ip); return r.ip += size, data; } // -auto V30MZ::readSP() -> uint16 { +auto V30MZ::pop() -> uint16 { uint16 data = read(Word, r.ss, r.sp); return r.sp += Word, data; } -auto V30MZ::writeSP(uint16 data) -> void { +auto V30MZ::push(uint16 data) -> void { r.sp -= Word; write(Word, r.ss, r.sp, data); } - -// - -auto V30MZ::readModRM(uint8 modRM) -> uint32 { - if((modRM & 0xc7) == 0x06) return r.ds << 16 | readIP(Word); - - 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: 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; - } - - return s << 16 | a; -} - -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/modrm.cpp b/higan/processor/v30mz/modrm.cpp new file mode 100644 index 00000000..97ad47fa --- /dev/null +++ b/higan/processor/v30mz/modrm.cpp @@ -0,0 +1,60 @@ +//ModRM functions +//d7-d6 => mod +//d5-d3 => reg +//d2-d0 => mem + +auto V30MZ::getReg(Size size, uint8 modRM) -> uint16 { + if(size == Byte) return r.byte(modRM >> 3); + if(size == Word) return r.word(modRM >> 3); + unreachable; +} + +auto V30MZ::setReg(Size size, uint8 modRM, uint16 data) -> void { + if(size == Byte) r.byte(modRM >> 3) = data; + if(size == Word) r.word(modRM >> 3) = data; +} + +// + +auto V30MZ::getSeg(uint8 modRM) -> uint16 { + return r.segment(modRM >> 3); +} + +auto V30MZ::setSeg(uint8 modRM, uint16 data) -> void { + r.segment(modRM >> 3) = data; +} + +// + +auto V30MZ::getMemAddress(uint8 modRM) -> uint32 { + if((modRM & 0xc7) == 0x06) return r.ds << 16 | fetch(Word); + + uint16 s = 0, a = 0; + if((modRM & 0xc0) == 0x40) a = (int8)fetch(Byte); + if((modRM & 0xc0) == 0x80) a = (int16)fetch(Word); + + switch(modRM & 7) { + 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; + } + + return s << 16 | a; +} + +auto V30MZ::getMem(Size size, uint8 modRM) -> uint16 { + if(modRM >= 0xc0) return getReg(size, modRM << 3); + auto addr = getMemAddress(modRM); + return read(size, addr >> 16, addr); +} + +auto V30MZ::setMem(Size size, uint8 modRM, uint16 data) -> void { + if(modRM >= 0xc0) return setReg(size, modRM << 3, data); + auto addr = getMemAddress(modRM); + return write(size, addr >> 16, addr, data); +} diff --git a/higan/processor/v30mz/registers.cpp b/higan/processor/v30mz/registers.cpp index 92921a2a..b7df7f3d 100644 --- a/higan/processor/v30mz/registers.cpp +++ b/higan/processor/v30mz/registers.cpp @@ -1,28 +1,47 @@ -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::getAcc(Size size) -> uint16 { + if(size == Byte) return r.al; + if(size == Word) return r.ax; + unreachable; } -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::setAcc(Size size, uint16 data) -> void { + if(size == Byte) r.al = data; + if(size == Word) r.ax = data; } -// - -auto V30MZ::getSegment(uint8 modRM) -> uint16 { - static uint16* word[] = {&r.es, &r.cs, &r.ss, &r.ds}; - return *word[(modRM >> 3) & 3]; +auto V30MZ::Registers::byte(uint3 r) -> uint8& { + switch(r) { + case 0: return al; + case 1: return cl; + case 2: return dl; + case 3: return bl; + case 4: return ah; + case 5: return ch; + case 6: return dh; + case 7: return bh; + } unreachable; } -auto V30MZ::setSegment(uint8 modRM, uint16 data) -> void { - static uint16* word[] = {&r.es, &r.cs, &r.ss, &r.ds}; - *word[(modRM >> 3) & 3] = data; +auto V30MZ::Registers::word(uint3 r) -> uint16& { + switch(r) { + case 0: return ax; + case 1: return cx; + case 2: return dx; + case 3: return bx; + case 4: return sp; + case 5: return bp; + case 6: return si; + case 7: return di; + } unreachable; +} + +auto V30MZ::Registers::segment(uint2 r) -> uint16& { + switch(r) { + case 0: return es; + case 1: return cs; + case 2: return ss; + case 3: return ds; + } unreachable; } // diff --git a/higan/processor/v30mz/v30mz.cpp b/higan/processor/v30mz/v30mz.cpp index 027d0588..10b29426 100644 --- a/higan/processor/v30mz/v30mz.cpp +++ b/higan/processor/v30mz/v30mz.cpp @@ -6,6 +6,7 @@ namespace Processor { const uint V30MZ::Byte = 1; const uint V30MZ::Word = 2; #include "registers.cpp" +#include "modrm.cpp" #include "memory.cpp" #include "algorithms.cpp" #include "instructions.cpp" @@ -15,7 +16,8 @@ auto V30MZ::exec() -> void { if(halt) return wait(1); #if 1 - print(disassemble(r.cs, r.ip), "\n"); + static uint16 cs = 0, ip = 0; + if(cs != r.cs || ip != r.ip) print(disassemble(cs = r.cs, ip = r.ip), "\n"); #endif execOpcode(); @@ -24,12 +26,94 @@ auto V30MZ::exec() -> void { auto V30MZ::execOpcode() -> void { executed++; - auto opcode = readIP(); + auto opcode = fetch(); wait(1); switch(opcode) { - case 0x32: return opXorRegisterModRM(Byte); - case 0x33: return opXorRegisterModRM(Word); + case 0x00: return opAddMemReg(Byte); + case 0x01: return opAddMemReg(Word); + case 0x02: return opAddRegMem(Byte); + case 0x03: return opAddRegMem(Word); + case 0x04: return opAddAccImm(Byte); + case 0x05: return opAddAccImm(Word); + case 0x08: return opOrMemReg(Byte); + case 0x09: return opOrMemReg(Word); + case 0x0a: return opOrRegMem(Byte); + case 0x0b: return opOrRegMem(Word); + case 0x0c: return opOrAccImm(Byte); + case 0x0d: return opOrAccImm(Word); + case 0x10: return opAdcMemReg(Byte); + case 0x11: return opAdcMemReg(Word); + case 0x12: return opAdcRegMem(Byte); + case 0x13: return opAdcRegMem(Word); + case 0x14: return opAdcAccImm(Byte); + case 0x15: return opAdcAccImm(Word); + case 0x18: return opSbbMemReg(Byte); + case 0x19: return opSbbMemReg(Word); + case 0x1a: return opSbbRegMem(Byte); + case 0x1b: return opSbbRegMem(Word); + case 0x1c: return opSbbAccImm(Byte); + case 0x1d: return opSbbAccImm(Word); + case 0x20: return opAndMemReg(Byte); + case 0x21: return opAndMemReg(Word); + case 0x22: return opAndRegMem(Byte); + case 0x23: return opAndRegMem(Word); + case 0x24: return opAndAccImm(Byte); + case 0x25: return opAndAccImm(Word); + case 0x26: return opPrefix(r.es); + case 0x28: return opSubMemReg(Byte); + case 0x29: return opSubMemReg(Word); + case 0x2a: return opSubRegMem(Byte); + case 0x2b: return opSubRegMem(Word); + case 0x2c: return opSubAccImm(Byte); + case 0x2d: return opSubAccImm(Word); + case 0x2e: return opPrefix(r.cs); + case 0x30: return opXorMemReg(Byte); + case 0x31: return opXorMemReg(Word); + case 0x32: return opXorRegMem(Byte); + case 0x33: return opXorRegMem(Word); + case 0x34: return opXorAccImm(Byte); + case 0x35: return opXorAccImm(Word); + case 0x36: return opPrefix(r.ss); + case 0x38: return opCmpMemReg(Byte); + case 0x39: return opCmpMemReg(Word); + case 0x3a: return opCmpRegMem(Byte); + case 0x3b: return opCmpRegMem(Word); + case 0x3c: return opCmpAccImm(Byte); + case 0x3d: return opCmpAccImm(Word); + case 0x3e: return opPrefix(r.ds); + case 0x40: return opIncReg(r.ax); + case 0x41: return opIncReg(r.cx); + case 0x42: return opIncReg(r.dx); + case 0x43: return opIncReg(r.bx); + case 0x44: return opIncReg(r.sp); + case 0x45: return opIncReg(r.bp); + case 0x46: return opIncReg(r.si); + case 0x47: return opIncReg(r.di); + case 0x48: return opDecReg(r.ax); + case 0x49: return opDecReg(r.cx); + case 0x4a: return opDecReg(r.dx); + case 0x4b: return opDecReg(r.bx); + case 0x4c: return opDecReg(r.sp); + case 0x4d: return opDecReg(r.bp); + case 0x4e: return opDecReg(r.si); + case 0x4f: return opDecReg(r.di); + case 0x50: return opPushReg(r.ax); + case 0x51: return opPushReg(r.cx); + case 0x52: return opPushReg(r.dx); + case 0x53: return opPushReg(r.bx); + case 0x54: return opPushReg(r.sp); + case 0x55: return opPushReg(r.bp); + case 0x56: return opPushReg(r.si); + case 0x57: return opPushReg(r.di); + case 0x58: return opPopReg(r.ax); + case 0x59: return opPopReg(r.cx); + case 0x5a: return opPopReg(r.dx); + case 0x5b: return opPopReg(r.bx); + case 0x5c: return opPopReg(r.sp); + case 0x5d: return opPopReg(r.bp); + case 0x5e: return opPopReg(r.si); + case 0x5f: return opPopReg(r.di); case 0x70: return opJumpIf(r.f.v == 1); case 0x71: return opJumpIf(r.f.v == 0); case 0x72: return opJumpIf(r.f.c == 1); @@ -46,37 +130,68 @@ 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 opMoveRegisterModRM(Byte); - case 0x8b: return opMoveRegisterModRM(Word); - case 0x8e: return opMoveSegmentRegisterModRM(); - case 0x90: return opNoOperation(); + case 0x80: return opGroup1MemImm(Byte, 0); + case 0x81: return opGroup1MemImm(Word, 0); + case 0x82: return opGroup1MemImm(Byte, 1); + case 0x83: return opGroup1MemImm(Word, 1); + case 0x88: return opMoveMemReg(Byte); + case 0x89: return opMoveMemReg(Word); + case 0x8a: return opMoveRegMem(Byte); + case 0x8b: return opMoveRegMem(Word); + case 0x8e: return opMoveSegMem(); + case 0x90: return opNop(); + case 0x9a: return opCallFar(); + case 0xa0: return opMoveAccMem(Byte); + case 0xa1: return opMoveAccMem(Word); + case 0xa2: return opMoveMemAcc(Byte); + case 0xa3: return opMoveMemAcc(Word); 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 0xa8: return opTestAcc(Byte); + case 0xa9: return opTestAcc(Word); + case 0xaa: return opStoreString(Byte); + case 0xab: return opStoreString(Word); + case 0xb0: return opMoveRegImm(r.al); + case 0xb1: return opMoveRegImm(r.cl); + case 0xb2: return opMoveRegImm(r.dl); + case 0xb3: return opMoveRegImm(r.bl); + case 0xb4: return opMoveRegImm(r.ah); + case 0xb5: return opMoveRegImm(r.ch); + case 0xb6: return opMoveRegImm(r.dh); + case 0xb7: return opMoveRegImm(r.bh); + case 0xb8: return opMoveRegImm(r.ax); + case 0xb9: return opMoveRegImm(r.cx); + case 0xba: return opMoveRegImm(r.dx); + case 0xbb: return opMoveRegImm(r.bx); + case 0xbc: return opMoveRegImm(r.sp); + case 0xbd: return opMoveRegImm(r.bp); + case 0xbe: return opMoveRegImm(r.si); + case 0xbf: return opMoveRegImm(r.di); + case 0xc0: return opGroup2MemImm(Byte); + case 0xc1: return opGroup2MemImm(Word); case 0xc3: return opReturn(); + case 0xc6: return opMoveMemImm(Byte); + case 0xc7: return opMoveMemImm(Word); + case 0xcb: return opRetFar(); + case 0xd0: return opGroup2MemImm(Byte, 1); + case 0xd1: return opGroup2MemImm(Word, 1); + case 0xd2: return opGroup2MemImm(Byte, r.cl); + case 0xd3: return opGroup2MemImm(Word, r.cl); + case 0xd8: return opNop(); //FPO1 + case 0xd9: return opNop(); //FPO1 + case 0xda: return opNop(); //FPO1 + case 0xdb: return opNop(); //FPO1 + case 0xdc: return opNop(); //FPO1 + case 0xdd: return opNop(); //FPO1 + case 0xde: return opNop(); //FPO1 + case 0xdf: return opNop(); //FPO1 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 0xeb: return opJumpShort(); case 0xec: return opInDX(Byte); case 0xed: return opInDX(Word); case 0xee: return opOutDX(Byte); diff --git a/higan/processor/v30mz/v30mz.hpp b/higan/processor/v30mz/v30mz.hpp index bb2869fe..c08e4270 100644 --- a/higan/processor/v30mz/v30mz.hpp +++ b/higan/processor/v30mz/v30mz.hpp @@ -6,8 +6,8 @@ namespace Processor { struct V30MZ { using Size = const uint&; - static const uint Byte; - static const uint Word; + static const uint Byte; //= 1 + static const uint Word; //= 2 virtual auto wait(uint clocks = 1) -> void = 0; virtual auto read(uint20 addr) -> uint8 = 0; @@ -20,43 +20,99 @@ struct V30MZ { auto power() -> void; //registers.cpp - auto getRegister(Size, uint8) -> uint16; - auto setRegister(Size, uint8, uint16) -> void; + auto getAcc(Size) -> uint16; + auto setAcc(Size, uint16) -> void; - auto getSegment(uint8) -> uint16; - auto setSegment(uint8, uint16) -> void; + //modrm.cpp + auto getReg(Size, uint8) -> uint16; + auto setReg(Size, uint8, uint16) -> void; + + auto getSeg(uint8) -> uint16; + auto setSeg(uint8, uint16) -> void; + + auto getMemAddress(uint8) -> uint32; + auto getMem(Size, uint8) -> uint16; + auto setMem(Size, uint8, uint16) -> void; //memory.cpp 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 readModRM(uint8) -> uint32; - auto readModRM(Size, uint8) -> uint16; + auto fetch(Size = Byte) -> uint16; + auto pop() -> uint16; + auto push(uint16) -> void; //algorithms.cpp auto parity(uint16) const -> bool; + auto alAdc(Size, uint16, uint16) -> uint16; + auto alAdd(Size, uint16, uint16) -> uint16; auto alAnd(Size, uint16, uint16) -> uint16; + auto alOr (Size, uint16, uint16) -> uint16; + auto alRcl(Size, uint16, uint5 ) -> uint16; + auto alRcr(Size, uint16, uint5 ) -> uint16; + auto alRol(Size, uint16, uint4 ) -> uint16; + auto alRor(Size, uint16, uint4 ) -> uint16; + auto alSal(Size, uint16, uint5 ) -> uint16; + auto alSar(Size, uint16, uint5 ) -> uint16; + auto alSbb(Size, uint16, uint16) -> uint16; + auto alSub(Size, uint16, uint16) -> uint16; + auto alShl(Size, uint16, uint5 ) -> uint16; + auto alShr(Size, uint16, uint5 ) -> uint16; + auto alXor(Size, uint16, uint16) -> uint16; //instructions.cpp - auto opXorRegisterModRM(Size); + auto opAddMemReg(Size); + auto opAddRegMem(Size); + auto opAddAccImm(Size); + auto opOrMemReg(Size); + auto opOrRegMem(Size); + auto opOrAccImm(Size); + auto opAdcMemReg(Size); + auto opAdcRegMem(Size); + auto opAdcAccImm(Size); + auto opSbbMemReg(Size); + auto opSbbRegMem(Size); + auto opSbbAccImm(Size); + auto opAndMemReg(Size); + auto opAndRegMem(Size); + auto opAndAccImm(Size); + auto opPrefix(uint16&); + auto opSubMemReg(Size); + auto opSubRegMem(Size); + auto opSubAccImm(Size); + auto opXorMemReg(Size); + auto opXorRegMem(Size); + auto opXorAccImm(Size); + auto opCmpMemReg(Size); + auto opCmpRegMem(Size); + auto opCmpAccImm(Size); + auto opIncReg(uint16&); + auto opDecReg(uint16&); + auto opPushReg(uint16&); + auto opPopReg(uint16&); auto opJumpIf(bool); - auto opMoveRegisterModRM(Size); - auto opMoveSegmentRegisterModRM(); - auto opNoOperation(); + auto opGroup1MemImm(Size, bool); + auto opMoveMemReg(Size); + auto opMoveRegMem(Size); + auto opMoveSegMem(); + auto opNop(); + auto opCallFar(); + auto opMoveAccMem(Size); + auto opMoveMemAcc(Size); auto opMoveString(Size); - auto opTestAX(Size); - auto opMoveRegisterImmediate(uint8&); - auto opMoveRegisterImmediate(uint16&); + auto opTestAcc(Size); + auto opStoreString(Size); + auto opMoveRegImm(uint8&); + auto opMoveRegImm(uint16&); auto opReturn(); + auto opMoveMemImm(Size); + auto opRetFar(); + auto opGroup2MemImm(Size, maybe = {}); auto opIn(Size); auto opOut(Size); auto opCallNear(); auto opJumpFar(); + auto opJumpShort(); auto opInDX(Size); auto opOutDX(Size); auto opRepeat(bool); @@ -64,13 +120,18 @@ struct V30MZ { auto opSetFlag(bool&); //disassembler.cpp - auto disassemble(uint16 cs, uint16 ip, bool registers = true) -> string; + auto disassemble(uint16 cs, uint16 ip, bool registers = true, bool bytes = true) -> string; //state bool halt = false; uint executed = 0; struct Registers { + //registers.cpp + auto byte(uint3) -> uint8&; + auto word(uint3) -> uint16&; + auto segment(uint2) -> uint16&; + uint16 ip; union { uint16 ax; struct { uint8 order_lsb2(al, ah); }; }; union { uint16 bx; struct { uint8 order_lsb2(bl, bh); }; }; @@ -86,6 +147,7 @@ struct V30MZ { uint16 ss; struct Flags { + //registers.cpp operator uint16() const; auto operator=(uint16 data);