mirror of https://github.com/bsnes-emu/bsnes.git
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:
parent
1c0ef793fe
commit
b72f35a13e
|
@ -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/";
|
||||
|
|
|
@ -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)
|
||||
};
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -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];
|
||||
};
|
||||
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
|
Loading…
Reference in New Issue