Update to v100r05 release.

byuu says:

Alright, I'm definitely going to need to find some people willing to
tolerate my questions on this chip, so I'm going to go ahead and announce
I'm working on this I guess.

This core is way too big for a surprise like the NES and WS cores
were. It'll probably even span multiple v10x releases before it's
even ready.
This commit is contained in:
Tim Allen 2016-07-13 08:47:04 +10:00
parent 1c0ef793fe
commit b72f35a13e
9 changed files with 228 additions and 58 deletions

View File

@ -11,7 +11,7 @@ using namespace nall;
namespace Emulator {
static const string Name = "higan";
static const string Version = "100.04";
static const string Version = "100.05";
static const string Author = "byuu";
static const string License = "GPLv3";
static const string Website = "http://byuu.org/";

View File

@ -20,7 +20,7 @@ auto M68K::disassemble(uint32 pc) -> string {
return data |= readWordPC() << 0;
};
auto suffix = [&](uint2 size) -> string {
auto size = [&](uint2 size) -> string {
if(size == 0) return ".b";
if(size == 1) return ".w";
if(size == 2) return ".l";
@ -56,15 +56,28 @@ auto M68K::disassemble(uint32 pc) -> string {
};
auto ea = [&](uint2 size, uint3 mode, uint3 reg) -> string {
if(mode == 3) return {"(a", reg, ")+"};
if(mode == 7) {
if(reg == 0) return {"($", hex((int16)readWordPC(), 6L), ")", suffix(size)};
if(reg == 1) return {"($", hex(readLongPC(), 6L), ")", suffix(size)};
if(reg == 0) return {"($", hex((int16)readWordPC(), 6L), ")"};
if(reg == 1) return {"($", hex(readLongPC(), 6L), ")"};
if(reg == 2) return {"($", hex(pc + (int16)readWordPC(), 6L), ")"};
}
return "???";
};
string s, op;
auto rd = [&](uint3 reg) -> string {
static const string name[8] = {"d0", "d1", "d2", "d3", "d4", "d5", "d6", "d7"};
return name[reg];
};
auto ra = [&](uint3 reg) -> string {
static const string name[8] = {"a0", "a1", "a2", "a3", "a4", "a5", "a6", "sp"};
return name[reg];
};
string s, name, args;
s.append(hex(pc, 6L), " ");
auto opcode = readWordPC();
@ -72,25 +85,76 @@ auto M68K::disassemble(uint32 pc) -> string {
if(0);
//bcc
else if(opcode >> 12 == 0b0110) {
op = {"b", cc(opcode >> 8), " ", branch(opcode >> 0)};
#define match(pattern) else if( \
(opcode & std::integral_constant<uint16_t, bit::mask(pattern)>::value) \
== std::integral_constant<uint16_t, bit::test(pattern)>::value \
)
#define bit(n) (opcode >> n & 1)
#define bits(hi, lo) ((opcode >> lo) & ((1 << (hi - lo + 1)) - 1))
//NOP
match("0100 1110 0111 0001") {
name = {"nop"};
}
//nop
else if(opcode == 0b0100'1110'0111'0001) {
op = {"nop"};
//MOVEM
match("0100 1-00 1--- ----") {
name = {"movem", size(1 + bit(6))};
bool direction = bit(10);
uint16 list = readWordPC();
string regs;
for(auto n : range(8)) if(list & 1 << (0 + n)) regs.append("d", n, ",");
for(auto n : range(8)) if(list & 1 << (8 + n)) regs.append("a", n, ",");
regs.trimRight(",");
if(direction == 0) {
args = {regs, ",", ea(1 + bit(6), bits(5,3), bits(2,0))};
} else {
args = {ea(1 + bit(6), bits(5,3), bits(2,0)), ",", regs};
}
}
//tst
else if(opcode >> 8 == 0b0100'1010) {
op = {"tst", suffix(opcode >> 6), " ", ea(opcode >> 6, opcode >> 3, opcode >> 0)};
//TST
match("0100 1010 ---- ----") {
name = {"tst", size(bits(7,6))};
args = {ea(bits(7,6), bits(5,3), bits(2,0))};
}
//LEA
match("0100 ---1 11-- ----") {
name = {"lea"};
args = {ea(Long, bits(5,3), bits(2,0)), ",", ra(bits(11,9))};
}
//BCC
match("0110 ---- ---- ----") {
name = {"b", cc(bits(11,8))};
args = {branch(bits(7,0))};
}
#undef match
#undef bit
#undef bits
else {
op = {"???"};
name = {"???"};
}
s.append(op);
s.append(name.size(-8), args);
return s;
}
auto M68K::disassembleRegisters() -> string {
return {
hex(r.d0, 8L), " ", hex(r.d1, 8L), " ", hex(r.d2, 8L), " ", hex(r.d3, 8L), " ",
hex(r.d4, 8L), " ", hex(r.d5, 8L), " ", hex(r.d6, 8L), " ", hex(r.d7, 8L), " ",
r.c ? "C" : "c",
r.v ? "V" : "v",
r.z ? "Z" : "z",
r.n ? "N" : "n",
r.x ? "X" : "x", "\n",
hex(r.a0, 8L), " ", hex(r.a1, 8L), " ", hex(r.a2, 8L), " ", hex(r.a3, 8L), " ",
hex(r.a4, 8L), " ", hex(r.a5, 8L), " ", hex(r.a6, 8L), " ", hex(r.usp, 8L), " ", hex(r.ssp, 8L)
};
}

View File

@ -5,21 +5,30 @@ auto M68K::signExtend(uint2 size, uint32 data) -> int32 {
return 0;
}
auto M68K::readEA(uint2 size, uint3 mode, uint3 reg) -> uint32 {
if(mode == 7) {
if(reg == 0) {
uint32 addr = (int16)readWordPC();
return readAbsolute(size, addr);
}
//
if(reg == 1) {
uint32 addr = readLongPC();
return readAbsolute(size, addr);
}
auto M68K::address(EA& ea) -> uint32 {
if(ea.valid) return ea.address;
ea.valid = true;
if(ea.mode == 0) return ea.address = r.d(ea.reg);
if(ea.mode == 1) return ea.address = r.a(ea.reg);
if(ea.mode == 7) {
if(ea.reg == 0) return ea.address = (int16)readWordPC();
if(ea.reg == 1) return ea.address = readLongPC();
if(ea.reg == 2) return ea.address = r.pc, ea.address += (int16)readWordPC();
}
return 0;
return ea.address = 0;
}
auto M68K::writeEA(uint2 size, uint3 mode, uint3 reg, uint32 data) -> void {
auto M68K::read(EA& ea) -> uint32 {
address(ea);
if(ea.mode < 2 || (ea.mode == 7 && ea.reg == 4)) return ea.address;
return readAbsolute(ea.size, ea.address);
}
auto M68K::write(EA& ea, uint32 data) -> void {
address(ea);
}

View File

@ -8,27 +8,52 @@ auto M68K::trap() -> void {
auto M68K::instruction() -> void {
instructionsExecuted++;
print(disassemble(r.pc), "\n");
print(disassembleRegisters(), "\n", disassemble(r.pc), "\n\n");
opcode = readWordPC();
//bcc
//0110 cccc dddd dddd
if(opcode >> 12 == 0b0110) {
return instructionBCC(opcode >> 8, opcode >> 0);
}
//nop
//0100 1110 0111 0001
if(opcode == 0b0100'1110'0111'0001) {
return instructionNOP();
}
//tst
//0100 1010 ssmm mrrr
if(opcode >> 8 == 0b0100'1010) {
return instructionTST(opcode >> 6, opcode >> 3, opcode >> 0);
}
trap();
return instructionTable[opcode]();
}
M68K::M68K() {
for(uint opcode : range(65536)) instructionTable[opcode] = [=] { trap(); };
#define match(pattern) else if( \
(opcode & std::integral_constant<uint16_t, bit::mask(pattern)>::value) \
== std::integral_constant<uint16_t, bit::test(pattern)>::value \
) instructionTable[opcode] = [=]
#define bit(n) (opcode >> n & 1)
#define bits(hi, lo) ((opcode >> lo) & ((1 << (hi - lo + 1)) - 1))
for(uint opcode : range(65536)) {
if(0);
//NOP
match("0100 1110 0111 0001") {
instructionNOP();
};
//MOVEM (direction, size, mode, register)
match("0100 1-00 1--- ----") {
instructionMOVEM(bit(10), EA{1 + bit(6), bits(5,3), bits(2,0)});
};
//TST (size, mode, register)
match("0100 1010 ---- ----") {
instructionTST(EA{bits(7,6), bits(5,3), bits(2,0)});
};
//LEA (An, mode, register)
match("0100 ---1 11-- ----") {
instructionLEA(bits(11,9), EA{Long, bits(5,3), bits(2,0)});
};
//BCC (condition, displacement)
match("0110 ---- ---- ----") {
instructionBCC(bits(11,8), bits(7,0));
};
}
#undef match
#undef bit
#undef bits
}

View File

@ -34,14 +34,22 @@ auto M68K::instructionBCC(uint4 condition, uint8 displacementByte) -> void {
}
}
auto M68K::instructionLEA(uint3 wr, EA ea) -> void {
r.a(wr) = address(ea);
}
auto M68K::instructionMOVEM(uint1 direction, EA ea) -> void {
auto list = readWordPC();
}
auto M68K::instructionNOP() -> void {
}
auto M68K::instructionTST(uint2 size, uint3 rdMode, uint3 rdReg) -> void {
auto data = readEA(size, rdMode, rdReg);
auto M68K::instructionTST(EA ea) -> void {
auto data = read(ea);
r.c = 0;
r.v = 0;
r.z = data == 0;
r.n = signExtend(size, data) < 0;
r.n = signExtend(ea.size, data) < 0;
}

View File

@ -21,4 +21,34 @@ auto M68K::reset() -> void {
r.ccr = 0;
}
//
auto M68K::Registers::d(uint3 reg) -> uint32& {
switch(reg) {
case 0: return d0;
case 1: return d1;
case 2: return d2;
case 3: return d3;
case 4: return d4;
case 5: return d5;
case 6: return d6;
case 7: return d7;
}
unreachable;
}
auto M68K::Registers::a(uint3 reg) -> uint32& {
switch(reg) {
case 0: return a0;
case 1: return a1;
case 2: return a2;
case 3: return a3;
case 4: return a4;
case 5: return a5;
case 6: return a6;
case 7: return ssp;
}
unreachable;
}
}

View File

@ -5,6 +5,8 @@
namespace Processor {
struct M68K {
M68K();
virtual auto step(uint clocks) -> void = 0;
virtual auto read(uint32 addr) -> uint8 = 0;
virtual auto write(uint32 addr, uint8 data) -> void = 0;
@ -23,9 +25,22 @@ struct M68K {
auto readAbsolute(uint2 size, uint32 addr) -> uint32;
//ea.cpp
struct EA {
EA(uint2 size, uint3 mode, uint3 reg) : size(size), mode(mode), reg(reg) {}
uint2 size;
uint3 mode;
uint3 reg;
boolean valid;
uint32 address;
};
auto signExtend(uint2 size, uint32 data) -> int32;
auto readEA(uint2 size, uint3 mode, uint3 reg) -> uint32;
auto writeEA(uint2 size, uint3 mode, uint3 reg, uint32 data) -> void;
auto address(EA& ea) -> uint32;
auto read(EA& ea) -> uint32;
auto write(EA& ea, uint32 data) -> void;
//instruction.cpp
auto trap() -> void;
@ -33,14 +48,23 @@ struct M68K {
//instructions.cpp
auto testCondition(uint4 condition) -> bool;
auto instructionBCC(uint4 condition, uint8 displacementByte) -> void;
auto instructionLEA(uint3 wr, EA ea) -> void;
auto instructionMOVEM(uint1 direction, EA ea) -> void;
auto instructionNOP() -> void;
auto instructionTST(uint2 size, uint3 rdMode, uint3 rdReg) -> void;
auto instructionTST(EA ea) -> void;
//disassembler.cpp
auto disassemble(uint32 pc) -> string;
auto disassembleRegisters() -> string;
enum : uint { Byte = 0, Word = 1, Long = 2 };
struct Registers {
auto d(uint3 reg) -> uint32&;
auto a(uint3 reg) -> uint32&;
uint32 d0, d1, d2, d3, d4, d5, d6, d7;
uint32 a0, a1, a2, a3, a4, a5, a6, usp, ssp;
uint32 pc;
@ -59,6 +83,8 @@ struct M68K {
uint16 opcode = 0;
uint instructionsExecuted = 0;
function<void ()> instructionTable[65536];
};
}

View File

@ -35,8 +35,8 @@ auto CPU::write(uint24 addr, uint8 data) -> void {
auto CPU::speed(uint24 addr) const -> uint {
if(addr & 0x408000) return addr & 0x800000 ? io.romSpeed : 8;
if((addr + 0x6000) & 0x4000) return 8;
if((addr - 0x4000) & 0x7e00) return 6;
if(addr + 0x6000 & 0x4000) return 8;
if(addr - 0x4000 & 0x7e00) return 6;
return 12;
}

View File

@ -79,6 +79,10 @@ template<uint Bits> struct Natural {
inline auto bit(uint index) -> Reference { return {*this, index, index}; }
inline auto byte(uint index) -> Reference { return {*this, index * 8 + 0, index * 8 + 7}; }
inline auto bits(uint lo, uint hi) const -> const Reference { return {(Natural&)*this, lo < hi ? lo : hi, hi > lo ? hi : lo}; }
inline auto bit(uint index) const -> const Reference { return {(Natural&)*this, index, index}; }
inline auto byte(uint index) const -> const Reference { return {(Natural&)*this, index * 8 + 0, index * 8 + 7}; }
inline auto clamp(uint bits) -> uintmax_t {
const uintmax_t b = 1ull << (bits - 1);
const uintmax_t m = b * 2 - 1;
@ -157,10 +161,14 @@ template<uint Bits> struct Integer {
const uint Hi;
};
inline auto bits(uint lo, uint hi) -> Reference { return {*this, lo, hi}; }
inline auto bits(uint lo, uint hi) -> Reference { return {*this, lo < hi ? lo : hi, hi > lo ? hi : lo}; }
inline auto bit(uint index) -> Reference { return {*this, index, index}; }
inline auto byte(uint index) -> Reference { return {*this, index * 8 + 0, index * 8 + 7}; }
inline auto bits(uint lo, uint hi) const -> const Reference { return {(Integer&)*this, lo < hi ? lo : hi, hi > lo ? hi : lo}; }
inline auto bit(uint index) const -> const Reference { return {(Integer&)*this, index, index}; }
inline auto byte(uint index) const -> const Reference { return {(Integer&)*this, index * 8 + 0, index * 8 + 7}; }
inline auto clamp(uint bits) -> intmax_t {
const intmax_t b = 1ull << (bits - 1);
const intmax_t m = b - 1;