Update to v100r12 release.

byuu says:

All of the above fixes, plus I added all 24 variations on the shift
opcodes, plus SUBQ, plus fixes to the BCC instruction.

I can now run 851,767 instructions into Sonic the Hedgehog before hitting
an unimplemented instruction (SUB).

The 68K core is probably only ~35% complete, and yet it's already within
4KiB of being the largest CPU core, code size wise, in all of higan. Fuck
this chip.
This commit is contained in:
Tim Allen 2016-07-25 23:15:54 +10:00
parent 7ccfbe0206
commit f230d144b5
10 changed files with 859 additions and 107 deletions

View File

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

View File

@ -28,6 +28,8 @@ auto CPU::step(uint clocks) -> void {
auto CPU::power() -> void {
M68K::power();
for(auto& byte : ram) byte = 0x00;
}
auto CPU::reset() -> void {
@ -37,11 +39,23 @@ auto CPU::reset() -> void {
auto CPU::read(bool word, uint24 addr) -> uint16 {
if(addr < 0x400000) return cartridge.read(word, addr);
return 0x0000;
if(addr < 0xe00000) return 0x0000;
uint16 data = ram[addr & 65535];
if(word) data = data << 8 | ram[addr + 1 & 65535];
return data;
}
auto CPU::write(bool word, uint24 addr, uint16 data) -> void {
if(addr < 0x400000) return cartridge.write(word, addr, data);
if(addr < 0xe00000) return;
if(!word) {
ram[addr & 65535] = data;
} else {
ram[addr + 0 & 65535] = data >> 8;
ram[addr + 1 & 65535] = data >> 0;
}
}
}

View File

@ -11,6 +11,9 @@ struct CPU : Processor::M68K, Thread {
auto read(bool word, uint24 addr) -> uint16 override;
auto write(bool word, uint24 addr, uint16 data) -> void override;
private:
uint8 ram[64 * 1024];
};
extern CPU cpu;

View File

@ -17,11 +17,11 @@ template<uint Size> auto M68K::_readPC() -> uint32 {
return clip<Size>(data);
}
auto M68K::_register(DataRegister dr) -> string {
auto M68K::_dataRegister(DataRegister dr) -> string {
return {"d", dr.number};
}
auto M68K::_register(AddressRegister ar) -> string {
auto M68K::_addressRegister(AddressRegister ar) -> string {
return {"a", ar.number};
}
@ -34,27 +34,23 @@ template<uint Size> auto M68K::_address(EffectiveAddress& ea) -> string {
return "???";
}
template<uint Size> auto M68K::_read(EffectiveAddress& ea) -> string {
if(ea.mode == 0) return {_register(DataRegister{ea.reg})};
if(ea.mode == 1) return {_register(AddressRegister{ea.reg})};
if(ea.mode == 2) return {"(", _register(AddressRegister{ea.reg}), ")"};
if(ea.mode == 3) return {"(", _register(AddressRegister{ea.reg}), ")+"};
if(ea.mode == 4) return {"-(", _register(AddressRegister{ea.reg}), ")"};
template<uint Size> auto M68K::_effectiveAddress(EffectiveAddress& ea) -> string {
if(ea.mode == 0) return {_dataRegister(DataRegister{ea.reg})};
if(ea.mode == 1) return {_addressRegister(AddressRegister{ea.reg})};
if(ea.mode == 2) return {"(", _addressRegister(AddressRegister{ea.reg}), ")"};
if(ea.mode == 3) return {"(", _addressRegister(AddressRegister{ea.reg}), ")+"};
if(ea.mode == 4) return {"-(", _addressRegister(AddressRegister{ea.reg}), ")"};
if(ea.mode == 5) return {"($", hex(read(AddressRegister{ea.reg}) + (int16)_readPC(), 6L), ")"};
if(ea.mode == 8) return {"($", hex(_readPC<Long>(), 6L), ")"};
if(ea.mode == 11) return {"#$", hex(_readPC<Size>(), 2 << Size)};
return "???";
}
template<uint Size> auto M68K::_write(EffectiveAddress& ea) -> string {
return _read<Size>(ea);
}
auto M68K::_branch(uint8 displacement) -> string {
uint16 word = _readPC();
if(displacement) displacement = (int8)displacement, _pc -= 2;
else displacement = (int16)displacement;
return {"$", hex(_pc + displacement, 6L)};
uint16 extension = _readPC();
_pc -= 2;
int32 offset = displacement ? sign<Byte>(displacement) : sign<Word>(extension);
return {"$", hex(_pc + offset, 6L)};
}
template<uint Size> auto M68K::_suffix() -> string {
@ -97,14 +93,14 @@ template<uint Size> auto M68K::disassembleADD(DataRegister dr, uint1 direction,
string op{"add", _suffix<Size>(), " "};
if(direction == 0) {
return {op, _read<Size>(ea), ",", _register(dr)};
return {op, _effectiveAddress<Size>(ea), ",", _dataRegister(dr)};
} else {
return {op, "", _register(dr), ",", _read<Size>(ea)};
return {op, "", _dataRegister(dr), ",", _effectiveAddress<Size>(ea)};
}
}
template<uint Size> auto M68K::disassembleANDI(EffectiveAddress ea) -> string {
return {"andi", _suffix<Size>(), " ", _immediate<Size>(), ",", _read<Size>(ea)};
return {"andi", _suffix<Size>(), " ", _immediate<Size>(), ",", _effectiveAddress<Size>(ea)};
}
auto M68K::disassembleANDI_TO_CCR() -> string {
@ -115,6 +111,30 @@ auto M68K::disassembleANDI_TO_SR() -> string {
return {"andi ", _immediate<Word>(), ",sr"};
}
template<uint Size> auto M68K::disassembleASL(uint4 shift, DataRegister modify) -> string {
return {"asl", _suffix<Size>(), " #", shift, ",", _dataRegister(modify)};
}
template<uint Size> auto M68K::disassembleASL(DataRegister shift, DataRegister modify) -> string {
return {"asl", _suffix<Size>(), " ", _dataRegister(shift), ",", _dataRegister(modify)};
}
auto M68K::disassembleASL(EffectiveAddress modify) -> string {
return {"asl", _suffix<Word>(), " ", _effectiveAddress<Word>(modify)};
}
template<uint Size> auto M68K::disassembleASR(uint4 shift, DataRegister modify) -> string {
return {"asr", _suffix<Size>(), " #", shift, ",", _dataRegister(modify)};
}
template<uint Size> auto M68K::disassembleASR(DataRegister shift, DataRegister modify) -> string {
return {"asr", _suffix<Size>(), " ", _dataRegister(shift), ",", _dataRegister(modify)};
}
auto M68K::disassembleASR(EffectiveAddress modify) -> string {
return {"asr", _suffix<Word>(), " ", _effectiveAddress<Word>(modify)};
}
auto M68K::disassembleBCC(uint4 condition, uint8 displacement) -> string {
auto cc = _condition(condition);
if(condition == 0) cc = "ra";
@ -123,25 +143,25 @@ auto M68K::disassembleBCC(uint4 condition, uint8 displacement) -> string {
}
template<uint Size> auto M68K::disassembleBTST(DataRegister dr, EffectiveAddress ea) -> string {
return {"btst ", _register(dr), ",", _read<Size>(ea)};
return {"btst ", _dataRegister(dr), ",", _effectiveAddress<Size>(ea)};
}
template<uint Size> auto M68K::disassembleBTST(EffectiveAddress ea) -> string {
return {"btst ", _immediate<Byte>(), ",", _read<Size>(ea)};
return {"btst ", _immediate<Byte>(), ",", _effectiveAddress<Size>(ea)};
}
template<uint Size> auto M68K::disassembleCLR(EffectiveAddress ea) -> string {
return {"clr", _suffix<Size>(), " ", _read<Size>(ea)};
return {"clr", _suffix<Size>(), " ", _effectiveAddress<Size>(ea)};
}
template<uint Size> auto M68K::disassembleCMP(DataRegister dr, EffectiveAddress ea) -> string {
return {"cmp", _suffix<Size>(), " ", _read<Word>(ea), ",", _register(dr)};
return {"cmp", _suffix<Size>(), " ", _effectiveAddress<Word>(ea), ",", _dataRegister(dr)};
}
auto M68K::disassembleDBCC(uint4 condition, DataRegister dr) -> string {
auto base = _pc;
auto displacement = (int16)_readPC();
return {"db", _condition(condition), " ", _register(dr), ",$", hex(base + displacement, 6L)};
return {"db", _condition(condition), " ", _dataRegister(dr), ",$", hex(base + displacement, 6L)};
}
auto M68K::disassembleEORI_TO_CCR() -> string {
@ -153,15 +173,39 @@ auto M68K::disassembleEORI_TO_SR() -> string {
}
auto M68K::disassembleLEA(AddressRegister ar, EffectiveAddress ea) -> string {
return {"lea ", _address<Long>(ea), ",", _register(ar)};
return {"lea ", _address<Long>(ea), ",", _addressRegister(ar)};
}
template<uint Size> auto M68K::disassembleLSL(uint4 immediate, DataRegister dr) -> string {
return {"lsl", _suffix<Size>(), " #", immediate, ",", _dataRegister(dr)};
}
template<uint Size> auto M68K::disassembleLSL(DataRegister sr, DataRegister dr) -> string {
return {"lsl", _suffix<Size>(), " ", _dataRegister(sr), ",", _dataRegister(dr)};
}
auto M68K::disassembleLSL(EffectiveAddress ea) -> string {
return {"lsl", _suffix<Word>(), " ", _effectiveAddress<Word>(ea)};
}
template<uint Size> auto M68K::disassembleLSR(uint4 immediate, DataRegister dr) -> string {
return {"lsr", _suffix<Size>(), " #", immediate, ",", _dataRegister(dr)};
}
template<uint Size> auto M68K::disassembleLSR(DataRegister shift, DataRegister dr) -> string {
return {"lsr", _suffix<Size>(), " ", _dataRegister(shift), ",", _dataRegister(dr)};
}
auto M68K::disassembleLSR(EffectiveAddress ea) -> string {
return {"lsr", _suffix<Word>(), " ", _effectiveAddress<Word>(ea)};
}
template<uint Size> auto M68K::disassembleMOVE(EffectiveAddress to, EffectiveAddress from) -> string {
return {"move", _suffix<Size>(), " ", _read<Size>(from), ",", _write<Size>(to)};
return {"move", _suffix<Size>(), " ", _effectiveAddress<Size>(from), ",", _effectiveAddress<Size>(to)};
}
template<uint Size> auto M68K::disassembleMOVEA(AddressRegister ar, EffectiveAddress ea) -> string {
return {"movea ", _read<Size>(ea), ",", _register(ar)};
return {"movea ", _effectiveAddress<Size>(ea), ",", _addressRegister(ar)};
}
template<uint Size> auto M68K::disassembleMOVEM(uint1 direction, EffectiveAddress ea) -> string {
@ -169,40 +213,40 @@ template<uint Size> auto M68K::disassembleMOVEM(uint1 direction, EffectiveAddres
uint16 list = _readPC();
string regs;
for(uint n : range(8)) if(list.bit(0 + n)) regs.append(_register(DataRegister{n}), ",");
for(uint n : range(8)) if(list.bit(0 + n)) regs.append(_dataRegister(DataRegister{n}), ",");
regs.trimRight(",");
if(regs && list >> 8) regs.append("/");
for(uint n : range(8)) if(list.bit(8 + n)) regs.append(_register(AddressRegister{n}), ",");
for(uint n : range(8)) if(list.bit(8 + n)) regs.append(_addressRegister(AddressRegister{n}), ",");
regs.trimRight(",");
if(direction == 0) {
return {op, regs, ",", _read<Size>(ea)};
return {op, regs, ",", _effectiveAddress<Size>(ea)};
} else {
return {op, _read<Size>(ea), ",", regs};
return {op, _effectiveAddress<Size>(ea), ",", regs};
}
}
auto M68K::disassembleMOVEQ(DataRegister dr, uint8 immediate) -> string {
return {"moveq #$", hex(immediate, 2L), ",", _register(dr)};
return {"moveq #$", hex(immediate, 2L), ",", _dataRegister(dr)};
}
auto M68K::disassembleMOVE_FROM_SR(EffectiveAddress ea) -> string {
return {"move sr,", _read<Word>(ea)};
return {"move sr,", _effectiveAddress<Word>(ea)};
}
auto M68K::disassembleMOVE_TO_CCR(EffectiveAddress ea) -> string {
return {"move ", _read<Byte>(ea), ",ccr"};
return {"move ", _effectiveAddress<Byte>(ea), ",ccr"};
}
auto M68K::disassembleMOVE_TO_SR(EffectiveAddress ea) -> string {
return {"move ", _read<Word>(ea), ",sr"};
return {"move ", _effectiveAddress<Word>(ea), ",sr"};
}
auto M68K::disassembleMOVE_USP(uint1 direction, AddressRegister ar) -> string {
if(direction == 0) {
return {"move ", _register(ar), ",usp"};
return {"move ", _addressRegister(ar), ",usp"};
} else {
return {"move usp,", _register(ar)};
return {"move usp,", _addressRegister(ar)};
}
}
@ -218,10 +262,62 @@ auto M68K::disassembleORI_TO_SR() -> string {
return {"ori ", _immediate<Word>(), ",sr"};
}
template<uint Size> auto M68K::disassembleROL(uint4 shift, DataRegister modify) -> string {
return {"rol", _suffix<Size>(), " #", shift, ",", _dataRegister(modify)};
}
template<uint Size> auto M68K::disassembleROL(DataRegister shift, DataRegister modify) -> string {
return {"rol", _suffix<Size>(), " ", _dataRegister(shift), ",", _dataRegister(modify)};
}
auto M68K::disassembleROL(EffectiveAddress modify) -> string {
return {"rol", _suffix<Word>(), " ", _effectiveAddress<Word>(modify)};
}
template<uint Size> auto M68K::disassembleROR(uint4 shift, DataRegister modify) -> string {
return {"ror", _suffix<Size>(), " #", shift, ",", _dataRegister(modify)};
}
template<uint Size> auto M68K::disassembleROR(DataRegister shift, DataRegister modify) -> string {
return {"ror", _suffix<Size>(), " ", _dataRegister(shift) ,",", _dataRegister(modify)};
}
auto M68K::disassembleROR(EffectiveAddress modify) -> string {
return {"ror", _suffix<Word>(), " ", _effectiveAddress<Word>(modify)};
}
template<uint Size> auto M68K::disassembleROXL(uint4 shift, DataRegister modify) -> string {
return {"roxl", _suffix<Size>(), " #", shift, ",", _dataRegister(modify)};
}
template<uint Size> auto M68K::disassembleROXL(DataRegister shift, DataRegister modify) -> string {
return {"roxl", _suffix<Size>(), " ", _dataRegister(shift), ",", _dataRegister(modify)};
}
auto M68K::disassembleROXL(EffectiveAddress modify) -> string {
return {"roxl", _suffix<Word>(), " ", _effectiveAddress<Word>(modify)};
}
template<uint Size> auto M68K::disassembleROXR(uint4 shift, DataRegister modify) -> string {
return {"roxr", _suffix<Size>(), " #", shift, ",", _dataRegister(modify)};
}
template<uint Size> auto M68K::disassembleROXR(DataRegister shift, DataRegister modify) -> string {
return {"roxr", _suffix<Size>(), " ", _dataRegister(shift), ",", _dataRegister(modify)};
}
auto M68K::disassembleROXR(EffectiveAddress modify) -> string {
return {"roxr", _suffix<Word>(), " ", _effectiveAddress<Word>(modify)};
}
auto M68K::disassembleRTS() -> string {
return {"rts "};
}
template<uint Size> auto M68K::disassembleTST(EffectiveAddress ea) -> string {
return {"tst", _suffix<Size>(), " ", _read<Size>(ea)};
template<uint Size> auto M68K::disassembleSUBQ(uint4 immediate, EffectiveAddress ea) -> string {
return {"subq", _suffix<Size>(), " #", immediate, _effectiveAddress<Size>(ea)};
}
template<uint Size> auto M68K::disassembleTST(EffectiveAddress ea) -> string {
return {"tst", _suffix<Size>(), " ", _effectiveAddress<Size>(ea)};
}

View File

@ -87,13 +87,13 @@ template<uint Size, bool Update> auto M68K::read(EffectiveAddress& ea) -> uint32
case AddressRegisterIndirectWithPostIncrement: {
auto data = read<Size>(ea.address);
if(Update) write(AddressRegister{ea.reg}, ea.address += (Size == Long ? 4 : 2));
if(Update) write(AddressRegister{ea.reg}, ea.address += bytes<Size>());
return data;
}
case AddressRegisterIndirectWithPreDecrement: {
auto data = read<Size>(ea.address - (Size == Long ? 4 : 2));
if(Update) write(AddressRegister{ea.reg}, ea.address -= (Size == Long ? 4 : 2));
auto data = read<Size>(ea.address - bytes<Size>());
if(Update) write(AddressRegister{ea.reg}, ea.address -= bytes<Size>());
return data;
}
@ -149,13 +149,13 @@ template<uint Size, bool Update> auto M68K::write(EffectiveAddress& ea, uint32 d
case AddressRegisterIndirectWithPostIncrement: {
write<Size>(ea.address, data);
if(Update) write(AddressRegister{ea.reg}, ea.address += (Size == Long ? 4 : 2));
if(Update) write(AddressRegister{ea.reg}, ea.address += bytes<Size>());
return;
}
case AddressRegisterIndirectWithPreDecrement: {
write<Size, Reverse>(ea.address - (Size == Long ? 4 : 2), data);
if(Update) write(AddressRegister{ea.reg}, ea.address -= (Size == Long ? 4 : 2));
write<Size, Reverse>(ea.address - bytes<Size>(), data);
if(Update) write(AddressRegister{ea.reg}, ea.address -= bytes<Size>());
return;
}

View File

@ -9,11 +9,13 @@ auto M68K::trap() -> void {
auto M68K::instruction() -> void {
instructionsExecuted++;
if(instructionsExecuted >= 20) trap();
// if(instructionsExecuted >= 851570) trap();
print(disassembleRegisters(), "\n");
print(disassemble(r.pc), "\n");
print("\n");
// if(instructionsExecuted >= 851530) {
// print(disassembleRegisters(), "\n");
// print(disassemble(r.pc), "\n");
// print("\n");
// }
opcode = readPC();
return instructionTable[opcode]();
@ -75,6 +77,74 @@ M68K::M68K() {
bind(opcode, ANDI_TO_SR);
}
//ASL (immediate)
for(uint3 count : range(8))
for(uint3 dreg : range(8)) {
auto opcode = pattern("1110 ---1 ++00 0---") | count << 9 | dreg << 0;
auto shift = count ? (uint4)count : (uint4)8;
DataRegister modify{dreg};
bind(opcode | 0 << 6, ASL<Byte>, shift, modify);
bind(opcode | 1 << 6, ASL<Word>, shift, modify);
bind(opcode | 2 << 6, ASL<Long>, shift, modify);
}
//ASL (register)
for(uint3 sreg : range(8))
for(uint3 dreg : range(8)) {
auto opcode = pattern("1110 ---1 ++10 0---") | sreg << 9 | dreg << 0;
DataRegister shift{sreg};
DataRegister modify{dreg};
bind(opcode | 0 << 6, ASL<Byte>, shift, modify);
bind(opcode | 1 << 6, ASL<Word>, shift, modify);
bind(opcode | 2 << 6, ASL<Long>, shift, modify);
}
//ASL (effective address)
for(uint3 mode : range(8))
for(uint3 reg : range(8)) {
auto opcode = pattern("1110 0001 11-- ----") | mode << 3 | reg << 0;
if(mode <= 1 || (mode == 7 && reg >= 2)) continue;
EffectiveAddress modify{mode, reg};
bind(opcode, ASL, modify);
}
//ASR (immediate)
for(uint3 count : range(8))
for(uint3 dreg : range(8)) {
auto opcode = pattern("1110 ---0 ++00 0---") | count << 9 | dreg << 0;
auto shift = count ? (uint4)count : (uint4)8;
DataRegister modify{dreg};
bind(opcode | 0 << 6, ASR<Byte>, shift, modify);
bind(opcode | 1 << 6, ASR<Word>, shift, modify);
bind(opcode | 2 << 6, ASR<Long>, shift, modify);
}
//ASR (register)
for(uint3 sreg : range(8))
for(uint3 dreg : range(8)) {
auto opcode = pattern("1110 ---0 ++10 0---") | sreg << 9 | dreg << 0;
DataRegister shift{sreg};
DataRegister modify{dreg};
bind(opcode | 0 << 6, ASR<Byte>, shift, modify);
bind(opcode | 1 << 6, ASR<Word>, shift, modify);
bind(opcode | 2 << 6, ASR<Long>, shift, modify);
}
//ASR (effective address)
for(uint3 mode : range(8))
for(uint3 reg : range(8)) {
auto opcode = pattern("1110 0000 11-- ----") | mode << 3 | reg << 0;
if(mode <= 1 || (mode == 7 && reg >= 2)) continue;
EffectiveAddress modify{mode, reg};
bind(opcode, ASR, modify);
}
//BCC
for(uint4 condition : range( 16))
for(uint8 displacement : range(256)) {
@ -88,7 +158,7 @@ M68K::M68K() {
for(uint3 mode : range(8))
for(uint3 reg : range(8)) {
auto opcode = pattern("0000 ---1 00-- ----") | dreg << 9 | mode << 3 | reg << 0;
if(mode == 1) continue;
if(mode == 1 || (mode == 7 && reg >= 5)) continue;
DataRegister dr{dreg};
EffectiveAddress ea{mode, reg};
@ -100,7 +170,7 @@ M68K::M68K() {
for(uint3 mode : range(8))
for(uint3 reg : range(8)) {
auto opcode = pattern("0000 1000 00-- ----") | mode << 3 | reg << 0;
if(mode == 1 || (mode == 7 && reg == 2)) continue;
if(mode == 1 || (mode == 7 && (reg == 2 || reg >= 5))) continue;
EffectiveAddress ea{mode, reg};
if(mode == 0) bind(opcode, BTST<Long>, ea);
@ -124,6 +194,7 @@ M68K::M68K() {
for(uint3 mode : range(8))
for(uint3 reg : range(8)) {
auto opcode = pattern("1011 ---0 ++-- ----") | dreg << 9 | mode << 3 | reg << 0;
if(mode == 7 && reg >= 5) continue;
DataRegister dr{dreg};
EffectiveAddress ea{mode, reg};
@ -160,13 +231,81 @@ M68K::M68K() {
for(uint3 mode : range(8))
for(uint3 reg : range(8)) {
auto opcode = pattern("0100 ---1 11-- ----") | areg << 9 | mode << 3 | reg << 0;
if(mode <= 1 || mode == 3 || mode == 4 || (mode == 7 && reg == 4)) continue;
if(mode <= 1 || mode == 3 || mode == 4 || (mode == 7 && reg >= 4)) continue;
AddressRegister ar{areg};
EffectiveAddress ea{mode, reg};
bind(opcode, LEA, ar, ea);
}
//LSL (immediate)
for(uint3 data : range(8))
for(uint3 dreg : range(8)) {
auto opcode = pattern("1110 ---1 ++00 1---") | data << 9 | dreg << 0;
auto immediate = data ? (uint4)data : (uint4)8;
DataRegister dr{dreg};
bind(opcode | 0 << 6, LSL<Byte>, immediate, dr);
bind(opcode | 1 << 6, LSL<Word>, immediate, dr);
bind(opcode | 2 << 6, LSL<Long>, immediate, dr);
}
//LSL (register)
for(uint3 sreg : range(8))
for(uint3 dreg : range(8)) {
auto opcode = pattern("1110 ---1 ++10 1---") | sreg << 9 | dreg << 0;
DataRegister sr{sreg};
DataRegister dr{dreg};
bind(opcode | 0 << 6, LSL<Byte>, sr, dr);
bind(opcode | 1 << 6, LSL<Word>, sr, dr);
bind(opcode | 2 << 6, LSL<Long>, sr, dr);
}
//LSL (effective address)
for(uint3 mode : range(8))
for(uint3 reg : range(8)) {
auto opcode = pattern("1110 0011 11-- ----") | mode << 3 | reg << 0;
if(mode <= 1 || (mode == 7 && reg >= 2)) continue;
EffectiveAddress ea{mode, reg};
bind(opcode, LSL, ea);
}
//LSR (immediate)
for(uint3 data : range(8))
for(uint3 dreg : range(8)) {
auto opcode = pattern("1110 ---0 ++00 1---") | data << 9 | dreg << 0;
auto immediate = data ? (uint4)data : (uint4)8;
DataRegister dr{dreg};
bind(opcode | 0 << 6, LSR<Byte>, immediate, dr);
bind(opcode | 1 << 6, LSR<Word>, immediate, dr);
bind(opcode | 2 << 6, LSR<Long>, immediate, dr);
}
//LSR (register)
for(uint3 count : range(8))
for(uint3 dreg : range(8)) {
auto opcode = pattern("1110 ---0 ++10 1---") | count << 9 | dreg << 0;
DataRegister shift{count};
DataRegister dr{dreg};
bind(opcode | 0 << 6, LSR<Byte>, shift, dr);
bind(opcode | 1 << 6, LSR<Word>, shift, dr);
bind(opcode | 2 << 6, LSR<Long>, shift, dr);
}
//LSR (effective address)
for(uint3 mode : range(8))
for(uint3 reg : range(8)) {
auto opcode = pattern("1110 0010 11-- ----") | mode << 3 | reg << 0;
if(mode <= 1 || (mode == 7 && reg >= 2)) continue;
EffectiveAddress ea{mode, reg};
bind(opcode, LSR, ea);
}
//MOVE
for(uint3 toReg : range(8))
for(uint3 toMode : range(8))
@ -174,6 +313,7 @@ M68K::M68K() {
for(uint3 fromReg : range(8)) {
auto opcode = pattern("00++ ---- ---- ----") | toReg << 9 | toMode << 6 | fromMode << 3 | fromReg << 0;
if(toMode == 1 || (toMode == 7 && toReg >= 2)) continue;
if(fromMode == 7 && fromReg >= 5) continue;
EffectiveAddress to{toMode, toReg};
EffectiveAddress from{fromMode, fromReg};
@ -189,6 +329,7 @@ M68K::M68K() {
for(uint3 mode : range(8))
for(uint3 reg : range(8)) {
auto opcode = pattern("00++ ---0 01-- ----") | areg << 9 | mode << 3 | reg << 0;
if(mode == 7 && reg >= 5) continue;
AddressRegister ar{areg};
EffectiveAddress ea{mode, reg};
@ -202,7 +343,7 @@ M68K::M68K() {
for(uint3 reg : range(8)) {
auto opcode = pattern("0100 1-00 1+-- ----") | direction << 10 | mode << 3 | reg << 0;
if(direction == 0 && (mode <= 1 || mode == 3 || (mode == 7 && reg >= 2)));
if(direction == 1 && (mode <= 1 || mode == 4 || (mode == 7 && reg == 4)));
if(direction == 1 && (mode <= 1 || mode == 4 || (mode == 7 && reg >= 4)));
EffectiveAddress ea{mode, reg};
bind(opcode | 0 << 6, MOVEM<Word>, direction, ea);
@ -232,7 +373,7 @@ M68K::M68K() {
for(uint3 mode : range(8))
for(uint3 reg : range(8)) {
auto opcode = pattern("0100 0100 11-- ----") | mode << 3 | reg << 0;
if(mode == 1) continue;
if(mode == 1 || (mode == 7 && reg >= 5)) continue;
EffectiveAddress ea{mode, reg};
bind(opcode, MOVE_TO_CCR, ea);
@ -242,7 +383,7 @@ M68K::M68K() {
for(uint3 mode : range(8))
for(uint3 reg : range(8)) {
auto opcode = pattern("0100 0110 11-- ----") | mode << 3 | reg << 0;
if(mode == 1) continue;
if(mode == 1 || (mode == 7 && reg >= 5)) continue;
EffectiveAddress ea{mode, reg};
bind(opcode, MOVE_TO_SR, ea);
@ -275,12 +416,164 @@ M68K::M68K() {
bind(opcode, ORI_TO_SR);
}
//ROL (immediate)
for(uint3 count : range(8))
for(uint3 dreg : range(8)) {
auto opcode = pattern("1110 ---1 ++01 1---") | count << 9 | dreg << 0;
auto shift = count ? (uint4)count : (uint4)8;
DataRegister modify{dreg};
bind(opcode | 0 << 6, ROL<Byte>, shift, modify);
bind(opcode | 1 << 6, ROL<Word>, shift, modify);
bind(opcode | 2 << 6, ROL<Long>, shift, modify);
}
//ROL (register)
for(uint3 sreg : range(8))
for(uint3 dreg : range(8)) {
auto opcode = pattern("1110 ---1 ++11 1---") | sreg << 9 | dreg << 0;
DataRegister shift{sreg};
DataRegister modify{dreg};
bind(opcode | 0 << 6, ROL<Byte>, shift, modify);
bind(opcode | 1 << 6, ROL<Word>, shift, modify);
bind(opcode | 2 << 6, ROL<Long>, shift, modify);
}
//ROL (effective address)
for(uint3 mode : range(8))
for(uint3 reg : range(8)) {
auto opcode = pattern("1110 0111 11-- ----") | mode << 3 | reg << 0;
if(mode <= 1 || (mode == 7 && reg >= 2)) continue;
EffectiveAddress modify{mode, reg};
bind(opcode, ROL, modify);
}
//ROR (immediate)
for(uint3 count : range(8))
for(uint3 dreg : range(8)) {
auto opcode = pattern("1110 ---0 ++01 1---") | count << 9 | dreg << 0;
auto shift = count ? (uint4)count : (uint4)8;
DataRegister modify{dreg};
bind(opcode | 0 << 6, ROR<Byte>, shift, modify);
bind(opcode | 1 << 6, ROR<Word>, shift, modify);
bind(opcode | 2 << 6, ROR<Long>, shift, modify);
}
//ROR (register)
for(uint3 sreg : range(8))
for(uint3 dreg : range(8)) {
auto opcode = pattern("1110 ---0 ++11 1---") | sreg << 9 | dreg << 0;
DataRegister shift{sreg};
DataRegister modify{dreg};
bind(opcode | 0 << 6, ROR<Byte>, shift, modify);
bind(opcode | 1 << 6, ROR<Word>, shift, modify);
bind(opcode | 2 << 6, ROR<Long>, shift, modify);
}
//ROR (effective address)
for(uint3 mode : range(8))
for(uint3 reg : range(8)) {
auto opcode = pattern("1110 0110 11-- ----") | mode << 3 | reg << 0;
if(mode <= 1 || (mode == 7 && reg >= 2)) continue;
EffectiveAddress modify{mode, reg};
bind(opcode, ROR, modify);
}
//ROXL (immediate)
for(uint3 count : range(8))
for(uint3 dreg : range(8)) {
auto opcode = pattern("1110 ---1 ++01 0---") | count << 9 | dreg << 0;
auto shift = count ? (uint4)count : (uint4)8;
DataRegister modify{dreg};
bind(opcode | 0 << 6, ROXL<Byte>, shift, modify);
bind(opcode | 1 << 6, ROXL<Word>, shift, modify);
bind(opcode | 2 << 6, ROXL<Long>, shift, modify);
}
//ROXL (register)
for(uint3 sreg : range(8))
for(uint3 dreg : range(8)) {
auto opcode = pattern("1110 ---1 ++11 0---") | sreg << 9 | dreg << 0;
DataRegister shift{sreg};
DataRegister modify{dreg};
bind(opcode | 0 << 6, ROXL<Byte>, shift, modify);
bind(opcode | 1 << 6, ROXL<Word>, shift, modify);
bind(opcode | 2 << 6, ROXL<Long>, shift, modify);
}
//ROXL (effective address)
for(uint3 mode : range(8))
for(uint3 reg : range(8)) {
auto opcode = pattern("1110 0101 11-- ----") | mode << 3 | reg << 0;
if(mode <= 1 || (mode == 7 && reg >= 2)) continue;
EffectiveAddress modify{mode, reg};
bind(opcode, ROXL, modify);
}
//ROXR (immediate)
for(uint3 count : range(8))
for(uint3 dreg : range(8)) {
auto opcode = pattern("1110 ---0 ++01 0---") | count << 9 | dreg << 0;
auto shift = count ? (uint4)count : (uint4)8;
DataRegister modify{dreg};
bind(opcode | 0 << 6, ROXR<Byte>, shift, modify);
bind(opcode | 1 << 6, ROXR<Word>, shift, modify);
bind(opcode | 2 << 6, ROXR<Long>, shift, modify);
}
//ROXR (register)
for(uint3 sreg : range(8))
for(uint3 dreg : range(8)) {
auto opcode = pattern("1110 ---0 ++11 0---") | sreg << 9 | dreg << 0;
DataRegister shift{sreg};
DataRegister modify{dreg};
bind(opcode | 0 << 6, ROXR<Byte>, shift, modify);
bind(opcode | 1 << 6, ROXR<Word>, shift, modify);
bind(opcode | 2 << 6, ROXR<Long>, shift, modify);
}
//ROXR (effective address)
for(uint3 mode : range(8))
for(uint3 reg : range(8)) {
auto opcode = pattern("1110 0100 11-- ----") | mode << 3 | reg << 0;
if(mode <= 1 || (mode == 7 && reg >= 2)) continue;
EffectiveAddress modify{mode, reg};
bind(opcode, ROXR, modify);
}
//RTS
{ auto opcode = pattern("0100 1110 0111 0101");
bind(opcode, RTS);
}
//SUBQ
for(uint3 data : range(8))
for(uint3 mode : range(8))
for(uint3 reg : range(8)) {
auto opcode = pattern("0101 ---1 ++-- ----") | data << 9 | mode << 3 | reg << 0;
if(mode == 7 && reg >= 2) continue;
auto immediate = data ? (uint4)data : (uint4)8;
EffectiveAddress ea{mode, reg};
bind(opcode | 0 << 6, SUBQ<Byte>, immediate, ea);
bind(opcode | 1 << 6, SUBQ<Word>, immediate, ea);
bind(opcode | 2 << 6, SUBQ<Long>, immediate, ea);
if(mode == 1) unbind(opcode | 0 << 6);
}
//TST
for(uint3 mode : range(8))
for(uint3 reg : range(8)) {

View File

@ -22,10 +22,20 @@ auto M68K::testCondition(uint4 condition) -> bool {
//
template<> auto M68K::bytes<Byte>() -> uint { return 1; }
template<> auto M68K::bytes<Word>() -> uint { return 2; }
template<> auto M68K::bytes<Long>() -> uint { return 4; }
template<> auto M68K::bits<Byte>() -> uint { return 8; }
template<> auto M68K::bits<Word>() -> uint { return 16; }
template<> auto M68K::bits<Long>() -> uint { return 32; }
template<uint Size> auto M68K::lsb() -> uint32 { return 1; }
template<> auto M68K::msb<Byte>() -> uint32 { return 0x80; }
template<> auto M68K::msb<Word>() -> uint32 { return 0x8000; }
template<> auto M68K::msb<Long>() -> uint32 { return 0x80000000; }
template<> auto M68K::mask<Byte>() -> uint32 { return 0xff; }
template<> auto M68K::mask<Word>() -> uint32 { return 0xffff; }
template<> auto M68K::mask<Long>() -> uint32 { return 0xffffffff; }
@ -38,14 +48,6 @@ template<> auto M68K::sign<Byte>(uint32 data) -> int32 { return (int8)data; }
template<> auto M68K::sign<Word>(uint32 data) -> int32 { return (int16)data; }
template<> auto M68K::sign<Long>(uint32 data) -> int32 { return (int32)data; }
template<uint Size> auto M68K::carry(uint32 result, uint32 source) -> bool {
return clip<Size>(result) < clip<Size>(source);
}
template<uint Size> auto M68K::overflow(uint32 result, uint32 source, uint32 target) -> bool {
return sign<Size>((target ^ source) & (target ^ result)) < 0;
}
template<uint Size> auto M68K::zero(uint32 result) -> bool {
return clip<Size>(result) == 0;
}
@ -57,9 +59,7 @@ template<uint Size> auto M68K::negative(uint32 result) -> bool {
//
template<uint Size> auto M68K::instructionADD(DataRegister dr, uint1 direction, EffectiveAddress ea) -> void {
uint32 source;
uint32 target;
uint32 result;
uint64 source, target, result;
if(direction == 0) {
source = read<Size>(ea);
@ -73,10 +73,10 @@ template<uint Size> auto M68K::instructionADD(DataRegister dr, uint1 direction,
write<Size>(ea, result);
}
r.c = carry<Size>(result, source);
r.v = overflow<Size>(result, source, target);
r.z = zero<Size>(result);
r.n = negative<Size>(result);
r.c = sign<Size>(result >> 1) < 0;
r.v = sign<Size>(~(target ^ source) & (target ^ result)) < 0;
r.z = clip<Size>(result) == 0;
r.n = sign<Size>(result) < 0;
r.x = r.c;
}
@ -104,12 +104,85 @@ auto M68K::instructionANDI_TO_SR() -> void {
writeSR(readSR() & data);
}
template<uint Size> auto M68K::ASL(uint32 result, uint shift) -> uint32 {
bool carry = false;
uint32 overflow = 0;
for(auto _ : range(shift)) {
carry = result & msb<Size>();
uint32 before = result;
result <<= 1;
overflow |= before ^ result;
}
r.c = carry;
r.v = sign<Size>(overflow) < 0;
r.z = clip<Size>(result) == 0;
r.n = sign<Size>(result) < 0;
if(shift) r.x = r.c;
return clip<Size>(result);
}
template<uint Size> auto M68K::instructionASL(uint4 shift, DataRegister modify) -> void {
auto result = ASL<Size>(read<Size>(modify), shift);
write<Size>(modify, result);
}
template<uint Size> auto M68K::instructionASL(DataRegister shift, DataRegister modify) -> void {
auto count = read<Long>(shift) & 63;
auto result = ASL<Size>(read<Size>(modify), count);
write<Size>(modify, result);
}
auto M68K::instructionASL(EffectiveAddress modify) -> void {
auto result = ASL<Word>(read<Word, NoUpdate>(modify), 1);
write<Word>(modify, result);
}
template<uint Size> auto M68K::ASR(uint32 result, uint shift) -> uint32 {
bool carry = false;
uint32 overflow = 0;
for(auto _ : range(shift)) {
carry = result & lsb<Size>();
uint32 before = result;
result = sign<Size>(result) >> 1;
overflow |= before ^ result;
}
r.c = carry;
r.v = sign<Size>(overflow) < 0;
r.z = clip<Size>(result) == 0;
r.n = sign<Size>(result) < 0;
if(shift) r.x = r.c;
return clip<Size>(result);
}
template<uint Size> auto M68K::instructionASR(uint4 shift, DataRegister modify) -> void {
auto result = ASR<Size>(read<Size>(modify), shift);
write<Size>(modify, result);
}
template<uint Size> auto M68K::instructionASR(DataRegister shift, DataRegister modify) -> void {
auto count = read<Long>(shift) & 63;
auto result = ASR<Size>(read<Size>(modify), count);
write<Size>(modify, result);
}
auto M68K::instructionASR(EffectiveAddress modify) -> void {
auto result = ASR<Word>(read<Word, NoUpdate>(modify), 1);
write<Word>(modify, result);
}
auto M68K::instructionBCC(uint4 condition, uint8 displacement) -> void {
auto extension = readPC();
auto extension = readPC<Word>();
if(condition == 1) push<Long>(r.pc);
r.pc -= 2;
if(condition >= 2 && !testCondition(condition)) return; //0 = BRA; 1 = BSR
r.pc += displacement ? sign<Byte>(displacement) : sign<Word>(extension);
if(condition >= 2 && !testCondition(condition)) { //0 = BRA; 1 = BSR
if(displacement) r.pc -= 2;
} else {
r.pc -= 2;
r.pc += displacement ? sign<Byte>(displacement) : sign<Word>(extension);
}
}
template<uint Size> auto M68K::instructionBTST(DataRegister dr, EffectiveAddress ea) -> void {
@ -139,22 +212,22 @@ template<uint Size> auto M68K::instructionCLR(EffectiveAddress ea) -> void {
}
template<uint Size> auto M68K::instructionCMP(DataRegister dr, EffectiveAddress ea) -> void {
auto source = read<Size>(ea);
auto target = read<Size>(dr);
auto result = target - source;
uint64 source = read<Size>(ea);
uint64 target = read<Size>(dr);
uint64 result = target - source;
r.c = carry<Size>(result, source);
r.v = overflow<Size>(result, source, target);
r.z = zero<Size>(result);
r.n = negative<Size>(result);
r.c = sign<Size>(result >> 1) < 0;
r.v = sign<Size>((target ^ source) & (target ^ result)) < 0;
r.z = clip<Size>(result) == 0;
r.n = sign<Size>(result) < 0;
}
auto M68K::instructionDBCC(uint4 condition, DataRegister dr) -> void {
auto displacement = (int16)readPC();
auto displacement = readPC<Word>();
if(!testCondition(condition)) {
uint16 result = read<Word>(dr);
write<Word>(dr, result - 1);
if(result) r.pc -= 2, r.pc += displacement;
if(result) r.pc -= 2, r.pc += sign<Word>(displacement);
}
}
@ -174,6 +247,70 @@ auto M68K::instructionLEA(AddressRegister ar, EffectiveAddress ea) -> void {
write<Long>(ar, fetch<Long>(ea));
}
template<uint Size> auto M68K::LSL(uint32 result, uint shift) -> uint32 {
bool carry = false;
for(auto _ : range(shift)) {
carry = result & msb<Size>();
result <<= 1;
}
r.c = carry;
r.v = 0;
r.z = clip<Size>(result) == 0;
r.n = sign<Size>(result) < 0;
if(shift) r.x = r.c;
return clip<Size>(result);
}
template<uint Size> auto M68K::instructionLSL(uint4 immediate, DataRegister dr) -> void {
auto result = LSL<Size>(read<Size>(dr), immediate);
write<Size>(dr, result);
}
template<uint Size> auto M68K::instructionLSL(DataRegister sr, DataRegister dr) -> void {
auto shift = read<Long>(sr) & 63;
auto result = LSL<Size>(read<Size>(dr), shift);
write<Size>(dr, result);
}
auto M68K::instructionLSL(EffectiveAddress ea) -> void {
auto result = LSL<Word>(read<Word, NoUpdate>(ea), 1);
write<Word>(ea, result);
}
template<uint Size> auto M68K::LSR(uint32 result, uint shift) -> uint32 {
bool carry = false;
for(auto _ : range(shift)) {
carry = result & lsb<Size>();
result >>= 1;
}
r.c = carry;
r.v = 0;
r.z = clip<Size>(result) == 0;
r.n = sign<Size>(result) < 0;
if(shift) r.x = r.c;
return clip<Size>(result);
}
template<uint Size> auto M68K::instructionLSR(uint4 immediate, DataRegister dr) -> void {
auto result = LSR<Size>(read<Size>(dr), immediate);
write<Size>(dr, result);
}
template<uint Size> auto M68K::instructionLSR(DataRegister shift, DataRegister dr) -> void {
auto count = read<Long>(shift) & 63;
auto result = LSR<Size>(read<Size>(dr), count);
write<Size>(dr, result);
}
auto M68K::instructionLSR(EffectiveAddress ea) -> void {
auto result = LSR<Word>(read<Word, NoUpdate>(ea), 1);
write<Word>(ea, result);
}
template<uint Size> auto M68K::instructionMOVE(EffectiveAddress to, EffectiveAddress from) -> void {
auto data = read<Size>(from);
write<Size>(to, data);
@ -191,25 +328,33 @@ template<uint Size> auto M68K::instructionMOVEA(AddressRegister ar, EffectiveAdd
template<uint Size> auto M68K::instructionMOVEM(uint1 direction, EffectiveAddress ea) -> void {
auto list = readPC();
auto addr = fetch<Size>(ea);
auto addr = fetch<Long>(ea);
for(uint n : range(8)) {
if(!list.bit(0 + n)) continue;
write<Size>(DataRegister{n}, read<Size>(addr));
addr += Size == Long ? 4 : 2;
for(uint n : range(16)) {
if(!list.bit(n)) continue;
//pre-decrement mode traverses registers in reverse order {A7-A0, D7-D0}
uint index = ea.mode == AddressRegisterIndirectWithPreDecrement ? 15 - n : n;
if(ea.mode == AddressRegisterIndirectWithPreDecrement) addr -= bytes<Size>();
if(direction == 0) {
auto data = index < 8 ? read<Size>(DataRegister{index}) : read<Size>(AddressRegister{index});
write<Size>(addr, data);
} else {
auto data = read<Size>(addr);
data = sign<Size>(data);
index < 8 ? write<Long>(DataRegister{index}, data) : write<Long>(AddressRegister{index}, data);
}
if(ea.mode == AddressRegisterIndirectWithPostIncrement) addr += bytes<Size>();
}
for(uint n : range(8)) {
if(!list.bit(8 + n)) continue;
write<Size>(AddressRegister{n}, read<Size>(addr));
addr += Size == Long ? 4 : 2;
}
flush<Size>(ea, addr);
flush<Long>(ea, addr);
}
auto M68K::instructionMOVEQ(DataRegister dr, uint8 immediate) -> void {
write<Byte>(dr, immediate);
write<Long>(dr, immediate);
r.c = 0;
r.v = 0;
@ -259,10 +404,153 @@ auto M68K::instructionORI_TO_SR() -> void {
writeSR(readSR() | data);
}
template<uint Size> auto M68K::ROL(uint32 result, uint shift) -> uint32 {
bool carry = false;
for(auto _ : range(shift)) {
carry = result & msb<Size>();
result = result << 1 | carry;
}
r.c = carry;
r.v = 0;
r.z = clip<Size>(result) == 0;
r.n = sign<Size>(result) < 0;
return clip<Size>(result);
}
template<uint Size> auto M68K::instructionROL(uint4 shift, DataRegister modify) -> void {
auto result = ROL<Size>(read<Size>(modify), shift);
write<Size>(modify, result);
}
template<uint Size> auto M68K::instructionROL(DataRegister shift, DataRegister modify) -> void {
auto count = read<Long>(shift) & 63;
auto result = ROL<Size>(read<Size>(modify), count);
write<Size>(modify, result);
}
auto M68K::instructionROL(EffectiveAddress modify) -> void {
auto result = ROL<Word>(read<Word, NoUpdate>(modify), 1);
write<Word>(modify, result);
}
template<uint Size> auto M68K::ROR(uint32 result, uint shift) -> uint32 {
bool carry = false;
for(auto _ : range(shift)) {
carry = result & lsb<Size>();
result >>= 1;
if(carry) result |= msb<Size>();
}
r.c = carry;
r.v = 0;
r.z = clip<Size>(result) == 0;
r.n = sign<Size>(result) < 0;
return clip<Size>(result);
}
template<uint Size> auto M68K::instructionROR(uint4 shift, DataRegister modify) -> void {
auto result = ROR<Size>(read<Size>(modify), shift);
write<Size>(modify, result);
}
template<uint Size> auto M68K::instructionROR(DataRegister shift, DataRegister modify) -> void {
auto count = read<Long>(shift) & 63;
auto result = ROR<Size>(read<Size>(modify), count);
write<Size>(modify, result);
}
auto M68K::instructionROR(EffectiveAddress modify) -> void {
auto result = ROR<Word>(read<Word, NoUpdate>(modify), 1);
write<Word>(modify, result);
}
template<uint Size> auto M68K::ROXL(uint32 result, uint shift) -> uint32 {
bool carry = r.x;
for(auto _ : range(shift)) {
bool extend = carry;
carry = result & msb<Size>();
result = result << 1 | extend;
}
r.c = carry;
r.v = 0;
r.z = clip<Size>(result) == 0;
r.n = sign<Size>(result) < 0;
r.x = r.c;
return clip<Size>(result);
}
template<uint Size> auto M68K::instructionROXL(uint4 shift, DataRegister modify) -> void {
auto result = ROXL<Size>(read<Size>(modify), shift);
write<Size>(modify, result);
}
template<uint Size> auto M68K::instructionROXL(DataRegister shift, DataRegister modify) -> void {
auto count = read<Long>(shift) & 63;
auto result = ROXL<Size>(read<Size>(modify), count);
write<Size>(modify, result);
}
auto M68K::instructionROXL(EffectiveAddress modify) -> void {
auto result = ROXL<Word>(read<Word, NoUpdate>(modify), 1);
write<Word>(modify, result);
}
template<uint Size> auto M68K::ROXR(uint32 result, uint shift) -> uint32 {
bool carry = r.x;
for(auto _ : range(shift)) {
bool extend = carry;
carry = result & lsb<Size>();
result >>= 1;
if(extend) result |= msb<Size>();
}
r.c = carry;
r.v = 0;
r.z = clip<Size>(result) == 0;
r.n = sign<Size>(result) < 0;
r.x = r.c;
return clip<Size>(result);
}
template<uint Size> auto M68K::instructionROXR(uint4 shift, DataRegister modify) -> void {
auto result = ROXR<Size>(read<Size>(modify), shift);
write<Size>(modify, result);
}
template<uint Size> auto M68K::instructionROXR(DataRegister shift, DataRegister modify) -> void {
auto count = read<Long>(shift) & 63;
auto result = ROXR<Size>(read<Size>(modify), count);
write<Size>(modify, result);
}
auto M68K::instructionROXR(EffectiveAddress modify) -> void {
auto result = ROXR<Word>(read<Word, NoUpdate>(modify), 1);
write<Word>(modify, result);
}
auto M68K::instructionRTS() -> void {
r.pc = pop<Long>();
}
template<uint Size> auto M68K::instructionSUBQ(uint4 immediate, EffectiveAddress ea) -> void {
uint64 target = read<Size, NoUpdate>(ea);
uint64 source = immediate;
uint64 result = target - source;
write<Size>(ea, result);
r.c = sign<Size>(result >> 1) < 0;
r.v = sign<Size>((target ^ source) & (target ^ result)) < 0;
r.z = clip<Size>(result) == 0;
r.n = sign<Size>(result) < 0;
r.x = r.c;
}
template<uint Size> auto M68K::instructionTST(EffectiveAddress ea) -> void {
auto data = read<Size>(ea);

View File

@ -29,7 +29,7 @@ auto M68K::reset() -> void {
r.z = 0;
r.n = 0;
r.x = 0;
r.i = 0;
r.i = 7;
r.s = 1;
r.t = 0;
}

View File

@ -86,13 +86,14 @@ struct M68K {
//instructions.cpp
auto testCondition(uint4 condition) -> bool;
template<uint Size> auto bytes() -> uint;
template<uint Size> auto bits() -> uint;
template<uint Size> auto lsb() -> uint32;
template<uint Size> auto msb() -> uint32;
template<uint Size> auto mask() -> uint32;
template<uint Size> auto clip(uint32 data) -> uint32;
template<uint Size> auto sign(uint32 data) -> int32;
template<uint Size> auto carry(uint32 result, uint32 source) -> bool;
template<uint Size> auto overflow(uint32 result, uint32 source, uint32 target) -> bool;
template<uint Size> auto zero(uint32 result) -> bool;
template<uint Size> auto negative(uint32 result) -> bool;
@ -100,6 +101,14 @@ struct M68K {
template<uint Size> auto instructionANDI(EffectiveAddress ea) -> void;
auto instructionANDI_TO_CCR() -> void;
auto instructionANDI_TO_SR() -> void;
template<uint Size> auto ASL(uint32 result, uint shift) -> uint32;
template<uint Size> auto instructionASL(uint4 shift, DataRegister modify) -> void;
template<uint Size> auto instructionASL(DataRegister shift, DataRegister modify) -> void;
auto instructionASL(EffectiveAddress modify) -> void;
template<uint Size> auto ASR(uint32 result, uint shift) -> uint32;
template<uint Size> auto instructionASR(uint4 shift, DataRegister modify) -> void;
template<uint Size> auto instructionASR(DataRegister shift, DataRegister modify) -> void;
auto instructionASR(EffectiveAddress modify) -> void;
auto instructionBCC(uint4 condition, uint8 displacement) -> void;
template<uint Size> auto instructionBTST(DataRegister dr, EffectiveAddress ea) -> void;
template<uint Size> auto instructionBTST(EffectiveAddress ea) -> void;
@ -109,6 +118,14 @@ struct M68K {
auto instructionEORI_TO_CCR() -> void;
auto instructionEORI_TO_SR() -> void;
auto instructionLEA(AddressRegister ar, EffectiveAddress ea) -> void;
template<uint Size> auto LSL(uint32 result, uint shift) -> uint32;
template<uint Size> auto instructionLSL(uint4 immediate, DataRegister dr) -> void;
template<uint Size> auto instructionLSL(DataRegister sr, DataRegister dr) -> void;
auto instructionLSL(EffectiveAddress ea) -> void;
template<uint Size> auto LSR(uint32 result, uint shift) -> uint32;
template<uint Size> auto instructionLSR(uint4 immediate, DataRegister dr) -> void;
template<uint Size> auto instructionLSR(DataRegister shift, DataRegister dr) -> void;
auto instructionLSR(EffectiveAddress ea) -> void;
template<uint Size> auto instructionMOVE(EffectiveAddress to, EffectiveAddress from) -> void;
template<uint Size> auto instructionMOVEA(AddressRegister ar, EffectiveAddress ea) -> void;
template<uint Size> auto instructionMOVEM(uint1 direction, EffectiveAddress ea) -> void;
@ -120,7 +137,24 @@ struct M68K {
auto instructionNOP() -> void;
auto instructionORI_TO_CCR() -> void;
auto instructionORI_TO_SR() -> void;
template<uint Size> auto ROL(uint32 result, uint shift) -> uint32;
template<uint Size> auto instructionROL(uint4 shift, DataRegister modify) -> void;
template<uint Size> auto instructionROL(DataRegister shift, DataRegister modify) -> void;
auto instructionROL(EffectiveAddress modify) -> void;
template<uint Size> auto ROR(uint32 result, uint shift) -> uint32;
template<uint Size> auto instructionROR(uint4 shift, DataRegister modify) -> void;
template<uint Size> auto instructionROR(DataRegister shift, DataRegister modify) -> void;
auto instructionROR(EffectiveAddress modify) -> void;
template<uint Size> auto ROXL(uint32 result, uint shift) -> uint32;
template<uint Size> auto instructionROXL(uint4 shift, DataRegister modify) -> void;
template<uint Size> auto instructionROXL(DataRegister shift, DataRegister modify) -> void;
auto instructionROXL(EffectiveAddress modify) -> void;
template<uint Size> auto ROXR(uint32 result, uint shift) -> uint32;
template<uint Size> auto instructionROXR(uint4 shift, DataRegister modify) -> void;
template<uint Size> auto instructionROXR(DataRegister shift, DataRegister modify) -> void;
auto instructionROXR(EffectiveAddress modify) -> void;
auto instructionRTS() -> void;
template<uint Size> auto instructionSUBQ(uint4 immediate, EffectiveAddress ea) -> void;
template<uint Size> auto instructionTST(EffectiveAddress ea) -> void;
//disassembler.cpp
@ -154,6 +188,12 @@ private:
template<uint Size> auto disassembleANDI(EffectiveAddress ea) -> string;
auto disassembleANDI_TO_CCR() -> string;
auto disassembleANDI_TO_SR() -> string;
template<uint Size> auto disassembleASL(uint4 shift, DataRegister modify) -> string;
template<uint Size> auto disassembleASL(DataRegister shift, DataRegister modify) -> string;
auto disassembleASL(EffectiveAddress modify) -> string;
template<uint Size> auto disassembleASR(uint4 shift, DataRegister modify) -> string;
template<uint Size> auto disassembleASR(DataRegister shift, DataRegister modify) -> string;
auto disassembleASR(EffectiveAddress modify) -> string;
auto disassembleBCC(uint4 condition, uint8 displacement) -> string;
template<uint Size> auto disassembleBTST(DataRegister dr, EffectiveAddress ea) -> string;
template<uint Size> auto disassembleBTST(EffectiveAddress ea) -> string;
@ -163,6 +203,12 @@ private:
auto disassembleEORI_TO_CCR() -> string;
auto disassembleEORI_TO_SR() -> string;
auto disassembleLEA(AddressRegister ar, EffectiveAddress ea) -> string;
template<uint Size> auto disassembleLSL(uint4 immediate, DataRegister dr) -> string;
template<uint Size> auto disassembleLSL(DataRegister sr, DataRegister dr) -> string;
auto disassembleLSL(EffectiveAddress ea) -> string;
template<uint Size> auto disassembleLSR(uint4 immediate, DataRegister dr) -> string;
template<uint Size> auto disassembleLSR(DataRegister shift, DataRegister dr) -> string;
auto disassembleLSR(EffectiveAddress ea) -> string;
template<uint Size> auto disassembleMOVE(EffectiveAddress to, EffectiveAddress from) -> string;
template<uint Size> auto disassembleMOVEA(AddressRegister ar, EffectiveAddress ea) -> string;
template<uint Size> auto disassembleMOVEM(uint1 direction, EffectiveAddress ea) -> string;
@ -174,17 +220,29 @@ private:
auto disassembleNOP() -> string;
auto disassembleORI_TO_CCR() -> string;
auto disassembleORI_TO_SR() -> string;
template<uint Size> auto disassembleROL(uint4 shift, DataRegister modify) -> string;
template<uint Size> auto disassembleROL(DataRegister shift, DataRegister modify) -> string;
auto disassembleROL(EffectiveAddress modify) -> string;
template<uint Size> auto disassembleROR(uint4 shift, DataRegister modify) -> string;
template<uint Size> auto disassembleROR(DataRegister shift, DataRegister modify) -> string;
auto disassembleROR(EffectiveAddress modify) -> string;
template<uint Size> auto disassembleROXL(uint4 shift, DataRegister modify) -> string;
template<uint Size> auto disassembleROXL(DataRegister shift, DataRegister modify) -> string;
auto disassembleROXL(EffectiveAddress modify) -> string;
template<uint Size> auto disassembleROXR(uint4 shift, DataRegister modify) -> string;
template<uint Size> auto disassembleROXR(DataRegister shift, DataRegister modify) -> string;
auto disassembleROXR(EffectiveAddress modify) -> string;
auto disassembleRTS() -> string;
template<uint Size> auto disassembleSUBQ(uint4 immediate, EffectiveAddress ea) -> string;
template<uint Size> auto disassembleTST(EffectiveAddress ea) -> string;
template<uint Size> auto _read(uint32 addr) -> uint32;
template<uint Size = Word> auto _readPC() -> uint32;
auto _register(DataRegister dr) -> string;
auto _register(AddressRegister ar) -> string;
auto _dataRegister(DataRegister dr) -> string;
auto _addressRegister(AddressRegister ar) -> string;
template<uint Size> auto _immediate() -> string;
template<uint Size> auto _address(EffectiveAddress& ea) -> string;
template<uint Size> auto _read(EffectiveAddress& ea) -> string;
template<uint Size> auto _write(EffectiveAddress& ea) -> string;
template<uint Size> auto _effectiveAddress(EffectiveAddress& ea) -> string;
auto _branch(uint8 displacement) -> string;
template<uint Size> auto _suffix() -> string;
auto _condition(uint4 condition) -> string;

View File

@ -81,11 +81,11 @@ template<> auto M68K::readPC<Long>() -> uint32 {
template<uint Size> auto M68K::pop() -> uint32 {
auto data = read<Size>((uint32)r.a[7]);
r.a[7] += Size == Long ? 4 : 2;
r.a[7] += bytes<Size>();
return data;
}
template<uint Size> auto M68K::push(uint32 data) -> void {
r.a[7] -= Size == Long ? 4 : 2;
r.a[7] -= bytes<Size>();
return write<Size, Reverse>((uint32)r.a[7], data);
}