mirror of
https://github.com/libretro/bsnes-libretro.git
synced 2024-11-23 08:59:40 +00:00
Update to v101r08 release.
byuu says: Changelog: - 68K: fixed read-modify-write instructions - 68K: fixed ADDX bug (using wrong target) - 68K: fixed major bug with SUB using wrong argument ordering - 68K: fixed sign extension when reading address registers from effective addressing - 68K: fixed sign extension on CMPA, SUBA instructions - VDP: improved OAM sprite attribute table caching behavior - VDP: improved DMA fill operation behavior - added Master System / Game Gear stubs (needed for developing the Z80 core)
This commit is contained in:
parent
ffd150735b
commit
043f6a8b33
@ -12,7 +12,7 @@ using namespace nall;
|
||||
|
||||
namespace Emulator {
|
||||
static const string Name = "higan";
|
||||
static const string Version = "101.07";
|
||||
static const string Version = "101.08";
|
||||
static const string Author = "byuu";
|
||||
static const string License = "GPLv3";
|
||||
static const string Website = "http://byuu.org/";
|
||||
|
@ -23,15 +23,17 @@ auto CPU::main() -> void {
|
||||
|
||||
if(state.interruptPending) {
|
||||
if(state.interruptPending.bit((uint)Interrupt::HorizontalBlank)) {
|
||||
state.interruptPending.bit((uint)Interrupt::HorizontalBlank) = 0;
|
||||
r.i = 4;
|
||||
return exception(Exception::Interrupt, Vector::HorizontalBlank);
|
||||
if(4 > r.i) {
|
||||
state.interruptPending.bit((uint)Interrupt::HorizontalBlank) = 0;
|
||||
return exception(Exception::Interrupt, Vector::HorizontalBlank, 4);
|
||||
}
|
||||
}
|
||||
|
||||
if(state.interruptPending.bit((uint)Interrupt::VerticalBlank)) {
|
||||
state.interruptPending.bit((uint)Interrupt::VerticalBlank) = 0;
|
||||
r.i = 6;
|
||||
return exception(Exception::Interrupt, Vector::VerticalBlank);
|
||||
if(6 > r.i) {
|
||||
state.interruptPending.bit((uint)Interrupt::VerticalBlank) = 0;
|
||||
return exception(Exception::Interrupt, Vector::VerticalBlank, 6);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -64,6 +66,7 @@ auto CPU::raise(Interrupt interrupt) -> void {
|
||||
|
||||
auto CPU::lower(Interrupt interrupt) -> void {
|
||||
state.interruptLine.bit((uint)interrupt) = 0;
|
||||
state.interruptPending.bit((uint)interrupt) = 0;
|
||||
}
|
||||
|
||||
auto CPU::power() -> void {
|
||||
@ -81,14 +84,16 @@ auto CPU::reset() -> void {
|
||||
|
||||
auto CPU::readByte(uint24 addr) -> uint8 {
|
||||
if(addr < 0x400000) return cartridge.readByte(addr);
|
||||
if(addr < 0xc00000) return 0x00;
|
||||
if(addr < 0xa00000) return 0x00;
|
||||
if(addr < 0xc00000) return rand();
|
||||
if(addr < 0xe00000) return vdp.readByte(addr);
|
||||
return ram[addr & 0xffff];
|
||||
}
|
||||
|
||||
auto CPU::readWord(uint24 addr) -> uint16 {
|
||||
if(addr < 0x400000) return cartridge.readWord(addr);
|
||||
if(addr < 0xc00000) return 0x0000;
|
||||
if(addr < 0xa00000) return 0x0000;
|
||||
if(addr < 0xc00000) return rand();
|
||||
if(addr < 0xe00000) return vdp.readWord(addr);
|
||||
uint16 data = ram[addr + 0 & 65535] << 8;
|
||||
return data | ram[addr + 1 & 65535] << 0;
|
||||
|
@ -23,11 +23,11 @@ auto VDP::dmaLoad() -> void {
|
||||
auto VDP::dmaFill() -> void {
|
||||
if(io.dmaFillWait) return;
|
||||
|
||||
auto data = io.dmaFillWord;
|
||||
writeDataPort(data);
|
||||
auto data = io.dmaFillByte;
|
||||
writeDataPort(data << 8 | data << 0);
|
||||
|
||||
io.dmaSource.bits(0,15) += 2;
|
||||
if(--io.dmaLength == 0 || --io.dmaLength == 0) {
|
||||
io.dmaSource.bits(0,15)++;
|
||||
if(--io.dmaLength == 0) {
|
||||
io.command.bit(5) = 0;
|
||||
}
|
||||
}
|
||||
|
@ -73,8 +73,7 @@ auto VDP::writeDataPort(uint16 data) -> void {
|
||||
|
||||
//DMA VRAM fill
|
||||
if(io.dmaFillWait.lower()) {
|
||||
io.dmaFillWord = data;
|
||||
return;
|
||||
io.dmaFillByte = data >> 8;
|
||||
}
|
||||
|
||||
//VRAM write
|
||||
@ -82,6 +81,9 @@ auto VDP::writeDataPort(uint16 data) -> void {
|
||||
auto address = io.address.bits(1,15);
|
||||
if(io.address.bit(0)) data = data >> 8 | data << 8;
|
||||
vram[address] = data;
|
||||
if(address >= sprite.io.attributeAddress && address < sprite.io.attributeAddress + 320) {
|
||||
sprite.write(address, data);
|
||||
}
|
||||
io.address += io.dataIncrement;
|
||||
return;
|
||||
}
|
||||
|
@ -1,11 +1,6 @@
|
||||
auto VDP::scanline() -> void {
|
||||
state.x = 0;
|
||||
if(++state.y >= 262) state.y = 0;
|
||||
if(state.y == 0) scheduler.exit(Scheduler::Event::Frame);
|
||||
|
||||
if(state.y == 0) {
|
||||
sprite.frame();
|
||||
}
|
||||
|
||||
if(state.y < 240) {
|
||||
planeA.scanline(state.y);
|
||||
@ -14,6 +9,8 @@ auto VDP::scanline() -> void {
|
||||
sprite.scanline(state.y);
|
||||
}
|
||||
|
||||
if(state.y == 240) scheduler.exit(Scheduler::Event::Frame);
|
||||
|
||||
state.output = buffer + (state.y * 2 + 0) * 1280;
|
||||
}
|
||||
|
||||
|
@ -1,40 +1,54 @@
|
||||
auto VDP::Sprite::frame() -> void {
|
||||
uint15 address = io.attributeAddress;
|
||||
uint7 link = 0;
|
||||
auto VDP::Sprite::write(uint9 address, uint16 data) -> void {
|
||||
if(address > 320) return;
|
||||
|
||||
oam.reset();
|
||||
while(oam.size() < 80) {
|
||||
uint64 attributes;
|
||||
attributes |= (uint64)vdp.vram[address + (link << 2) + 0] << 48;
|
||||
attributes |= (uint64)vdp.vram[address + (link << 2) + 1] << 32;
|
||||
attributes |= (uint64)vdp.vram[address + (link << 2) + 2] << 16;
|
||||
attributes |= (uint64)vdp.vram[address + (link << 2) + 3] << 0;
|
||||
auto& object = oam[address >> 2];
|
||||
switch(address.bits(0,1)) {
|
||||
|
||||
auto& object = oam.append();
|
||||
object.x = attributes.bits( 0, 9) - 128;
|
||||
object.address = attributes.bits(16,26) << 4;
|
||||
object.horizontalFlip = attributes.bit (27);
|
||||
object.verticalFlip = attributes.bit (28);
|
||||
object.palette = attributes.bits(29,30);
|
||||
object.priority = attributes.bit (31);
|
||||
object.height = attributes.bits(40,41) << 3;
|
||||
object.width = attributes.bits(42,43) << 3;
|
||||
object.y = attributes.bits(48,57) - 128;
|
||||
case 0: {
|
||||
object.y = data.bits(0,9) - 128;
|
||||
break;
|
||||
}
|
||||
|
||||
case 1: {
|
||||
object.link = data.bits(0,6);
|
||||
object.height = data.bits(8,9) << 3;
|
||||
object.width = data.bits(10,11) << 3;
|
||||
break;
|
||||
}
|
||||
|
||||
case 2: {
|
||||
object.address = data.bits(0,10) << 4;
|
||||
object.horizontalFlip = data.bit(11);
|
||||
object.verticalFlip = data.bit(12);
|
||||
object.palette = data.bits(13,14);
|
||||
object.priority = data.bit(15);
|
||||
break;
|
||||
}
|
||||
|
||||
case 3: {
|
||||
object.x = data.bits(0,9) - 128;
|
||||
break;
|
||||
}
|
||||
|
||||
link = attributes.bits(32,38);
|
||||
if(!link) break;
|
||||
}
|
||||
}
|
||||
|
||||
auto VDP::Sprite::scanline(uint y) -> void {
|
||||
object.reset();
|
||||
for(auto& o : oam) {
|
||||
|
||||
uint7 link = 0;
|
||||
while(link) {
|
||||
auto& o = oam[link];
|
||||
|
||||
if((uint9)(o.y + o.height - 1) < y) continue;
|
||||
if((uint9)(y + o.height - 1) < o.y) continue;
|
||||
if(o.x == 0) break;
|
||||
|
||||
object.append(o);
|
||||
if(object.size() >= object.capacity()) break;
|
||||
if(object.size() >= 20) break;
|
||||
|
||||
link = o.link;
|
||||
if(!link || link >= 80) break;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -58,7 +58,7 @@ struct VDP : Thread {
|
||||
|
||||
//sprite.cpp
|
||||
struct Sprite {
|
||||
auto frame() -> void;
|
||||
auto write(uint9 addr, uint16 data) -> void;
|
||||
auto scanline(uint y) -> void;
|
||||
auto run(uint x, uint y) -> void;
|
||||
|
||||
@ -80,6 +80,7 @@ struct VDP : Thread {
|
||||
uint2 palette;
|
||||
uint1 priority;
|
||||
uint15 address;
|
||||
uint7 link;
|
||||
};
|
||||
|
||||
struct Output {
|
||||
@ -101,7 +102,7 @@ private:
|
||||
struct IO {
|
||||
//internal state
|
||||
boolean dmaFillWait;
|
||||
uint8 dmaFillWord;
|
||||
uint8 dmaFillByte;
|
||||
|
||||
//command
|
||||
uint6 command;
|
||||
|
12
higan/ms/GNUmakefile
Normal file
12
higan/ms/GNUmakefile
Normal file
@ -0,0 +1,12 @@
|
||||
processors += z80
|
||||
|
||||
objects += ms-interface
|
||||
objects += ms-cpu ms-vdp ms-psg
|
||||
objects += ms-system ms-cartridge
|
||||
|
||||
obj/ms-interface.o: ms/interface/interface.cpp $(call rwildcard,ms/interface)
|
||||
obj/ms-cpu.o: ms/cpu/cpu.cpp $(call rwildcard,ms/cpu)
|
||||
obj/ms-vdp.o: ms/vdp/vdp.cpp $(call rwildcard,ms/vdp)
|
||||
obj/ms-psg.o: ms/psg/psg.cpp $(call rwildcard,ms/psg)
|
||||
obj/ms-system.o: ms/system/system.cpp $(call rwildcard,ms/system)
|
||||
obj/ms-cartridge.o: ms/cartridge/cartridge.cpp $(call rwildcard,ms/cartridge)
|
7
higan/ms/cartridge/cartridge.cpp
Normal file
7
higan/ms/cartridge/cartridge.cpp
Normal file
@ -0,0 +1,7 @@
|
||||
#include <ms/ms.hpp>
|
||||
|
||||
namespace MasterSystem {
|
||||
|
||||
Cartridge cartridge;
|
||||
|
||||
}
|
4
higan/ms/cartridge/cartridge.hpp
Normal file
4
higan/ms/cartridge/cartridge.hpp
Normal file
@ -0,0 +1,4 @@
|
||||
struct Cartridge {
|
||||
};
|
||||
|
||||
extern Cartridge cartridge;
|
18
higan/ms/cpu/cpu.cpp
Normal file
18
higan/ms/cpu/cpu.cpp
Normal file
@ -0,0 +1,18 @@
|
||||
#include <ms/ms.hpp>
|
||||
|
||||
namespace MasterSystem {
|
||||
|
||||
CPU cpu;
|
||||
|
||||
auto CPU::Enter() -> void {
|
||||
while(true) scheduler.synchronize(), cpu.main();
|
||||
}
|
||||
|
||||
auto CPU::main() -> void {
|
||||
}
|
||||
|
||||
auto CPU::step(uint clocks) -> void {
|
||||
Thread::step(clocks);
|
||||
}
|
||||
|
||||
}
|
9
higan/ms/cpu/cpu.hpp
Normal file
9
higan/ms/cpu/cpu.hpp
Normal file
@ -0,0 +1,9 @@
|
||||
//Zilog Z80
|
||||
|
||||
struct CPU : Processor::Z80, Thread {
|
||||
static auto Enter() -> void;
|
||||
auto main() -> void;
|
||||
auto step(uint clocks) -> void;
|
||||
};
|
||||
|
||||
extern CPU cpu;
|
115
higan/ms/interface/interface.cpp
Normal file
115
higan/ms/interface/interface.cpp
Normal file
@ -0,0 +1,115 @@
|
||||
#include <ms/ms.hpp>
|
||||
|
||||
namespace MasterSystem {
|
||||
|
||||
Interface* interface = nullptr;
|
||||
Settings settings;
|
||||
|
||||
Interface::Interface() {
|
||||
interface = this;
|
||||
|
||||
information.manufacturer = "Sega";
|
||||
information.name = "Master System";
|
||||
information.overscan = true;
|
||||
information.resettable = true;
|
||||
|
||||
information.capability.states = false;
|
||||
information.capability.cheats = false;
|
||||
|
||||
media.append({ID::MasterSystem, "Master System", "ms"});
|
||||
media.append({ID::GameGear, "Game Gear", "gg"});
|
||||
|
||||
Port controllerPort1{ID::Port::Controller1, "Controller Port 1"};
|
||||
Port controllerPort2{ID::Port::Controller2, "Controller Port 2"};
|
||||
|
||||
{ Device device{ID::Device::Gamepad, "Gamepad"};
|
||||
device.inputs.append({0, "Up"});
|
||||
device.inputs.append({0, "Down"});
|
||||
device.inputs.append({0, "Left"});
|
||||
device.inputs.append({0, "Right"});
|
||||
device.inputs.append({0, "1"});
|
||||
device.inputs.append({0, "2"});
|
||||
controllerPort1.devices.append(device);
|
||||
controllerPort2.devices.append(device);
|
||||
}
|
||||
}
|
||||
|
||||
auto Interface::manifest() -> string {
|
||||
return "";
|
||||
}
|
||||
|
||||
auto Interface::title() -> string {
|
||||
return "";
|
||||
}
|
||||
|
||||
auto Interface::videoSize() -> VideoSize {
|
||||
return {256, 192};
|
||||
}
|
||||
|
||||
auto Interface::videoSize(uint width, uint height, bool arc) -> VideoSize {
|
||||
uint w = 256;
|
||||
uint h = 192;
|
||||
uint m = min(width / w, height / h);
|
||||
return {w * m, h * m};
|
||||
}
|
||||
|
||||
auto Interface::videoFrequency() -> double {
|
||||
return 60.0;
|
||||
}
|
||||
|
||||
auto Interface::videoColors() -> uint32 {
|
||||
return 1 << 6;
|
||||
}
|
||||
|
||||
auto Interface::videoColor(uint32 color) -> uint64 {
|
||||
return 0;
|
||||
}
|
||||
|
||||
auto Interface::audioFrequency() -> double {
|
||||
return 44'100.0;
|
||||
}
|
||||
|
||||
auto Interface::loaded() -> bool {
|
||||
return false;
|
||||
}
|
||||
|
||||
auto Interface::load(uint id) -> bool {
|
||||
return false;
|
||||
}
|
||||
|
||||
auto Interface::save() -> void {
|
||||
}
|
||||
|
||||
auto Interface::unload() -> void {
|
||||
}
|
||||
|
||||
auto Interface::power() -> void {
|
||||
}
|
||||
|
||||
auto Interface::reset() -> void {
|
||||
}
|
||||
|
||||
auto Interface::run() -> void {
|
||||
}
|
||||
|
||||
auto Interface::serialize() -> serializer {
|
||||
return {};
|
||||
}
|
||||
|
||||
auto Interface::unserialize(serializer& s) -> bool {
|
||||
return false;
|
||||
}
|
||||
|
||||
auto Interface::cap(const string& name) -> bool {
|
||||
return false;
|
||||
}
|
||||
|
||||
auto Interface::get(const string& name) -> any {
|
||||
return {};
|
||||
}
|
||||
|
||||
auto Interface::set(const string& name, const any& value) -> bool {
|
||||
return false;
|
||||
}
|
||||
|
||||
}
|
59
higan/ms/interface/interface.hpp
Normal file
59
higan/ms/interface/interface.hpp
Normal file
@ -0,0 +1,59 @@
|
||||
namespace MasterSystem {
|
||||
|
||||
struct ID {
|
||||
enum : uint {
|
||||
System,
|
||||
MasterSystem,
|
||||
GameGear,
|
||||
};
|
||||
|
||||
struct Port { enum : uint {
|
||||
Controller1,
|
||||
Controller2,
|
||||
};};
|
||||
|
||||
struct Device { enum : uint {
|
||||
Gamepad,
|
||||
};};
|
||||
};
|
||||
|
||||
struct Interface : Emulator::Interface {
|
||||
using Emulator::Interface::load;
|
||||
|
||||
Interface();
|
||||
|
||||
auto manifest() -> string override;
|
||||
auto title() -> string override;
|
||||
|
||||
auto videoSize() -> VideoSize override;
|
||||
auto videoSize(uint width, uint height, bool arc) -> VideoSize override;
|
||||
auto videoFrequency() -> double override;
|
||||
auto videoColors() -> uint32 override;
|
||||
auto videoColor(uint32 color) -> uint64 override;
|
||||
|
||||
auto audioFrequency() -> double override;
|
||||
|
||||
auto loaded() -> bool override;
|
||||
auto load(uint id) -> bool override;
|
||||
auto save() -> void override;
|
||||
auto unload() -> void override;
|
||||
|
||||
auto power() -> void override;
|
||||
auto reset() -> void override;
|
||||
auto run() -> void override;
|
||||
|
||||
auto serialize() -> serializer override;
|
||||
auto unserialize(serializer&) -> bool override;
|
||||
|
||||
auto cap(const string& name) -> bool override;
|
||||
auto get(const string& name) -> any override;
|
||||
auto set(const string& name, const any& value) -> bool override;
|
||||
};
|
||||
|
||||
struct Settings {
|
||||
};
|
||||
|
||||
extern Interface* interface;
|
||||
extern Settings settings;
|
||||
|
||||
}
|
36
higan/ms/ms.hpp
Normal file
36
higan/ms/ms.hpp
Normal file
@ -0,0 +1,36 @@
|
||||
#pragma once
|
||||
|
||||
//license: GPLv3
|
||||
//started: 2016-08-17
|
||||
|
||||
#include <emulator/emulator.hpp>
|
||||
#include <emulator/thread.hpp>
|
||||
#include <emulator/scheduler.hpp>
|
||||
|
||||
#include <processor/z80/z80.hpp>
|
||||
|
||||
namespace MasterSystem {
|
||||
using File = Emulator::File;
|
||||
using Scheduler = Emulator::Scheduler;
|
||||
extern Scheduler scheduler;
|
||||
|
||||
struct Thread : Emulator::Thread {
|
||||
auto create(auto (*entrypoint)() -> void, double frequency) -> void {
|
||||
Emulator::Thread::create(entrypoint, frequency);
|
||||
scheduler.append(*this);
|
||||
}
|
||||
|
||||
inline auto synchronize(Thread& thread) -> void {
|
||||
if(clock() >= thread.clock()) scheduler.resume(thread);
|
||||
}
|
||||
};
|
||||
|
||||
#include <ms/cpu/cpu.hpp>
|
||||
#include <ms/vdp/vdp.hpp>
|
||||
#include <ms/psg/psg.hpp>
|
||||
|
||||
#include <ms/system/system.hpp>
|
||||
#include <ms/cartridge/cartridge.hpp>
|
||||
}
|
||||
|
||||
#include <ms/interface/interface.hpp>
|
18
higan/ms/psg/psg.cpp
Normal file
18
higan/ms/psg/psg.cpp
Normal file
@ -0,0 +1,18 @@
|
||||
#include <ms/ms.hpp>
|
||||
|
||||
namespace MasterSystem {
|
||||
|
||||
PSG psg;
|
||||
|
||||
auto PSG::Enter() -> void {
|
||||
while(true) scheduler.synchronize(), psg.main();
|
||||
}
|
||||
|
||||
auto PSG::main() -> void {
|
||||
}
|
||||
|
||||
auto PSG::step(uint clocks) -> void {
|
||||
Thread::step(clocks);
|
||||
}
|
||||
|
||||
}
|
9
higan/ms/psg/psg.hpp
Normal file
9
higan/ms/psg/psg.hpp
Normal file
@ -0,0 +1,9 @@
|
||||
//TI SN76489
|
||||
|
||||
struct PSG : Thread {
|
||||
static auto Enter() -> void;
|
||||
auto main() -> void;
|
||||
auto step(uint clocks) -> void;
|
||||
};
|
||||
|
||||
extern PSG psg;
|
27
higan/ms/system/system.cpp
Normal file
27
higan/ms/system/system.cpp
Normal file
@ -0,0 +1,27 @@
|
||||
#include <ms/ms.hpp>
|
||||
|
||||
namespace MasterSystem {
|
||||
|
||||
System system;
|
||||
Scheduler scheduler;
|
||||
|
||||
auto System::run() -> void {
|
||||
}
|
||||
|
||||
auto System::load() -> bool {
|
||||
return false;
|
||||
}
|
||||
|
||||
auto System::save() -> void {
|
||||
}
|
||||
|
||||
auto System::unload() -> void {
|
||||
}
|
||||
|
||||
auto System::power() -> void {
|
||||
}
|
||||
|
||||
auto System::reset() -> void {
|
||||
}
|
||||
|
||||
}
|
15
higan/ms/system/system.hpp
Normal file
15
higan/ms/system/system.hpp
Normal file
@ -0,0 +1,15 @@
|
||||
struct System {
|
||||
auto loaded() const -> bool { return false; }
|
||||
auto colorburst() const -> double { return 0.0; }
|
||||
|
||||
auto run() -> void;
|
||||
|
||||
auto load() -> bool;
|
||||
auto save() -> void;
|
||||
auto unload() -> void;
|
||||
|
||||
auto power() -> void;
|
||||
auto reset() -> void;
|
||||
};
|
||||
|
||||
extern System system;
|
18
higan/ms/vdp/vdp.cpp
Normal file
18
higan/ms/vdp/vdp.cpp
Normal file
@ -0,0 +1,18 @@
|
||||
#include <ms/ms.hpp>
|
||||
|
||||
namespace MasterSystem {
|
||||
|
||||
VDP vdp;
|
||||
|
||||
auto VDP::Enter() -> void {
|
||||
while(true) scheduler.synchronize(), vdp.main();
|
||||
}
|
||||
|
||||
auto VDP::main() -> void {
|
||||
}
|
||||
|
||||
auto VDP::step(uint clocks) -> void {
|
||||
Thread::step(clocks);
|
||||
}
|
||||
|
||||
}
|
9
higan/ms/vdp/vdp.hpp
Normal file
9
higan/ms/vdp/vdp.hpp
Normal file
@ -0,0 +1,9 @@
|
||||
//...
|
||||
|
||||
struct VDP : Thread {
|
||||
static auto Enter() -> void;
|
||||
auto main() -> void;
|
||||
auto step(uint clocks) -> void;
|
||||
};
|
||||
|
||||
extern VDP vdp;
|
@ -130,8 +130,8 @@ template<uint Size> auto M68K::disassembleADDQ(uint4 immediate, EffectiveAddress
|
||||
return {"addq", _suffix<Size>(), " #", immediate, ",", _effectiveAddress<Size>(modify)};
|
||||
}
|
||||
|
||||
template<uint Size> auto M68K::disassembleADDX(EffectiveAddress target, EffectiveAddress source) -> string {
|
||||
return {"addx", _suffix<Size>(), " ", _effectiveAddress<Size>(target), ",", _effectiveAddress<Size>(source)};
|
||||
template<uint Size> auto M68K::disassembleADDX(EffectiveAddress with, EffectiveAddress from) -> string {
|
||||
return {"addx", _suffix<Size>(), " ", _effectiveAddress<Size>(from), ",", _effectiveAddress<Size>(with)};
|
||||
}
|
||||
|
||||
template<uint Size> auto M68K::disassembleAND(EffectiveAddress from, DataRegister with) -> string {
|
||||
@ -544,11 +544,11 @@ template<uint Size> auto M68K::disassembleSUBI(EffectiveAddress with) -> string
|
||||
}
|
||||
|
||||
template<uint Size> auto M68K::disassembleSUBQ(uint4 immediate, EffectiveAddress ea) -> string {
|
||||
return {"subq", _suffix<Size>(), " #", immediate, _effectiveAddress<Size>(ea)};
|
||||
return {"subq", _suffix<Size>(), " #", immediate, ",", _effectiveAddress<Size>(ea)};
|
||||
}
|
||||
|
||||
template<uint Size> auto M68K::disassembleSUBX(EffectiveAddress with, EffectiveAddress from) -> string {
|
||||
return {"subx", _suffix<Size>(), " ", _effectiveAddress<Size>(with), ",", _effectiveAddress<Size>(from)};
|
||||
return {"subx", _suffix<Size>(), " ", _effectiveAddress<Size>(from), ",", _effectiveAddress<Size>(with)};
|
||||
}
|
||||
|
||||
auto M68K::disassembleSWAP(DataRegister with) -> string {
|
||||
|
@ -68,7 +68,7 @@ template<uint Size> auto M68K::fetch(EffectiveAddress& ea) -> uint32 {
|
||||
return 0;
|
||||
}
|
||||
|
||||
template<uint Size, bool Update> auto M68K::read(EffectiveAddress& ea) -> uint32 {
|
||||
template<uint Size, bool Hold> auto M68K::read(EffectiveAddress& ea) -> uint32 {
|
||||
ea.address = fetch<Size>(ea);
|
||||
|
||||
switch(ea.mode) {
|
||||
@ -78,7 +78,7 @@ template<uint Size, bool Update> auto M68K::read(EffectiveAddress& ea) -> uint32
|
||||
}
|
||||
|
||||
case AddressRegisterDirect: {
|
||||
return clip<Size>(ea.address);
|
||||
return sign<Size>(ea.address);
|
||||
}
|
||||
|
||||
case AddressRegisterIndirect: {
|
||||
@ -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 += bytes<Size>());
|
||||
if(!Hold) write(AddressRegister{ea.reg}, ea.address += bytes<Size>());
|
||||
return data;
|
||||
}
|
||||
|
||||
case AddressRegisterIndirectWithPreDecrement: {
|
||||
auto data = read<Size>(ea.address - bytes<Size>());
|
||||
if(Update) write(AddressRegister{ea.reg}, ea.address -= bytes<Size>());
|
||||
if(!Hold) write(AddressRegister{ea.reg}, ea.address -= bytes<Size>());
|
||||
return data;
|
||||
}
|
||||
|
||||
@ -130,7 +130,7 @@ template<uint Size, bool Update> auto M68K::read(EffectiveAddress& ea) -> uint32
|
||||
return 0;
|
||||
}
|
||||
|
||||
template<uint Size, bool Update> auto M68K::write(EffectiveAddress& ea, uint32 data) -> void {
|
||||
template<uint Size, bool Hold> auto M68K::write(EffectiveAddress& ea, uint32 data) -> void {
|
||||
ea.address = fetch<Size>(ea);
|
||||
|
||||
switch(ea.mode) {
|
||||
@ -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 += bytes<Size>());
|
||||
if(!Hold) write(AddressRegister{ea.reg}, ea.address += bytes<Size>());
|
||||
return;
|
||||
}
|
||||
|
||||
case AddressRegisterIndirectWithPreDecrement: {
|
||||
write<Size, Reverse>(ea.address - bytes<Size>(), data);
|
||||
if(Update) write(AddressRegister{ea.reg}, ea.address -= bytes<Size>());
|
||||
if(!Hold) write(AddressRegister{ea.reg}, ea.address -= bytes<Size>());
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -115,21 +115,21 @@ M68K::M68K() {
|
||||
}
|
||||
|
||||
//ADDX
|
||||
for(uint3 treg : range(8))
|
||||
for(uint3 sreg : range(8)) {
|
||||
auto opcode = pattern("1101 ---1 ++00 ----") | treg << 9 | sreg << 0;
|
||||
for(uint3 xreg : range(8))
|
||||
for(uint3 yreg : range(8)) {
|
||||
auto opcode = pattern("1101 ---1 ++00 ----") | xreg << 9 | yreg << 0;
|
||||
|
||||
EffectiveAddress dataTarget{DataRegisterDirect, treg};
|
||||
EffectiveAddress dataSource{DataRegisterDirect, sreg};
|
||||
bind(opcode | 0 << 6 | 0 << 3, ADDX<Byte>, dataTarget, dataSource);
|
||||
bind(opcode | 1 << 6 | 0 << 3, ADDX<Word>, dataTarget, dataSource);
|
||||
bind(opcode | 2 << 6 | 0 << 3, ADDX<Long>, dataTarget, dataSource);
|
||||
EffectiveAddress dataWith{DataRegisterDirect, xreg};
|
||||
EffectiveAddress dataFrom{DataRegisterDirect, yreg};
|
||||
bind(opcode | 0 << 6 | 0 << 3, ADDX<Byte>, dataWith, dataFrom);
|
||||
bind(opcode | 1 << 6 | 0 << 3, ADDX<Word>, dataWith, dataFrom);
|
||||
bind(opcode | 2 << 6 | 0 << 3, ADDX<Long>, dataWith, dataFrom);
|
||||
|
||||
EffectiveAddress addressTarget{AddressRegisterIndirectWithPreDecrement, treg};
|
||||
EffectiveAddress addressSource{AddressRegisterIndirectWithPreDecrement, sreg};
|
||||
bind(opcode | 0 << 6 | 1 << 3, ADDX<Byte>, addressTarget, addressSource);
|
||||
bind(opcode | 1 << 6 | 1 << 3, ADDX<Word>, addressTarget, addressSource);
|
||||
bind(opcode | 2 << 6 | 1 << 3, ADDX<Long>, addressTarget, addressSource);
|
||||
EffectiveAddress addressWith{AddressRegisterIndirectWithPreDecrement, xreg};
|
||||
EffectiveAddress addressFrom{AddressRegisterIndirectWithPreDecrement, yreg};
|
||||
bind(opcode | 0 << 6 | 1 << 3, ADDX<Byte>, addressWith, addressFrom);
|
||||
bind(opcode | 1 << 6 | 1 << 3, ADDX<Word>, addressWith, addressFrom);
|
||||
bind(opcode | 2 << 6 | 1 << 3, ADDX<Long>, addressWith, addressFrom);
|
||||
}
|
||||
|
||||
//AND
|
||||
@ -166,10 +166,10 @@ M68K::M68K() {
|
||||
auto opcode = pattern("0000 0010 ++-- ----") | mode << 3 | reg << 0;
|
||||
if(mode == 1 || (mode == 7 && reg >= 2)) continue;
|
||||
|
||||
EffectiveAddress ea{mode, reg};
|
||||
bind(opcode | 0 << 6, ANDI<Byte>, ea);
|
||||
bind(opcode | 1 << 6, ANDI<Word>, ea);
|
||||
bind(opcode | 2 << 6, ANDI<Long>, ea);
|
||||
EffectiveAddress with{mode, reg};
|
||||
bind(opcode | 0 << 6, ANDI<Byte>, with);
|
||||
bind(opcode | 1 << 6, ANDI<Word>, with);
|
||||
bind(opcode | 2 << 6, ANDI<Long>, with);
|
||||
}
|
||||
|
||||
//ANDI_TO_CCR
|
||||
|
@ -52,7 +52,7 @@ template<> auto M68K::sign<Long>(uint32 data) -> int32 { return (int32)data; }
|
||||
|
||||
auto M68K::instructionABCD(EffectiveAddress with, EffectiveAddress from) -> void {
|
||||
auto source = read<Byte>(from);
|
||||
auto target = read<Byte, NoUpdate>(with);
|
||||
auto target = read<Byte, Hold>(with);
|
||||
auto result = source + target + r.x;
|
||||
bool v = false;
|
||||
|
||||
@ -72,19 +72,18 @@ auto M68K::instructionABCD(EffectiveAddress with, EffectiveAddress from) -> void
|
||||
|
||||
r.c = sign<Byte>(result >> 1) < 0;
|
||||
r.v = v;
|
||||
r.z = clip<Byte>(result) == 0 ? 0 : r.z;
|
||||
r.z = clip<Byte>(result) ? 0 : r.z;
|
||||
r.n = sign<Byte>(result) < 0;
|
||||
r.x = r.c;
|
||||
}
|
||||
|
||||
template<uint Size, bool Extend> auto M68K::ADD(uint32 source, uint32 target) -> uint32 {
|
||||
uint64 result = (uint64)source + (uint64)target;
|
||||
auto result = (uint64)source + target;
|
||||
if(Extend) result += r.x;
|
||||
|
||||
r.c = sign<Size>(result >> 1) < 0;
|
||||
r.v = sign<Size>(~(target ^ source) & (target ^ result)) < 0;
|
||||
if(Extend == 0) r.z = clip<Size>(result) == 0;
|
||||
if(Extend == 1) if(clip<Size>(result)) r.z = 0;
|
||||
r.z = clip<Size>(result) ? 0 : (Extend ? r.z : 1);
|
||||
r.n = sign<Size>(result) < 0;
|
||||
r.x = r.c;
|
||||
|
||||
@ -100,7 +99,7 @@ template<uint Size> auto M68K::instructionADD(EffectiveAddress from, DataRegiste
|
||||
|
||||
template<uint Size> auto M68K::instructionADD(DataRegister from, EffectiveAddress with) -> void {
|
||||
auto source = read<Size>(from);
|
||||
auto target = read<Size>(with);
|
||||
auto target = read<Size, Hold>(with);
|
||||
auto result = ADD<Size>(source, target);
|
||||
write<Size>(with, result);
|
||||
}
|
||||
@ -113,23 +112,23 @@ template<uint Size> auto M68K::instructionADDA(AddressRegister ar, EffectiveAddr
|
||||
|
||||
template<uint Size> auto M68K::instructionADDI(EffectiveAddress modify) -> void {
|
||||
auto source = readPC<Size>();
|
||||
auto target = read<Size>(modify);
|
||||
auto target = read<Size, Hold>(modify);
|
||||
auto result = ADD<Size>(source, target);
|
||||
write<Size>(modify, result);
|
||||
}
|
||||
|
||||
template<uint Size> auto M68K::instructionADDQ(uint4 immediate, EffectiveAddress modify) -> void {
|
||||
auto source = read<Size>(modify);
|
||||
auto source = read<Size, Hold>(modify);
|
||||
auto target = immediate;
|
||||
auto result = ADD<Size>(source, target);
|
||||
write<Size>(modify, result);
|
||||
}
|
||||
|
||||
template<uint Size> auto M68K::instructionADDX(EffectiveAddress target_, EffectiveAddress source_) -> void {
|
||||
auto source = read<Size>(source_);
|
||||
auto target = read<Size>(target_);
|
||||
template<uint Size> auto M68K::instructionADDX(EffectiveAddress with, EffectiveAddress from) -> void {
|
||||
auto source = read<Size>(from);
|
||||
auto target = read<Size, Hold>(with);
|
||||
auto result = ADD<Size, Extend>(source, target);
|
||||
write<Size>(target, result);
|
||||
write<Size>(with, result);
|
||||
}
|
||||
|
||||
template<uint Size> auto M68K::AND(uint32 source, uint32 target) -> uint32 {
|
||||
@ -152,16 +151,16 @@ template<uint Size> auto M68K::instructionAND(EffectiveAddress from, DataRegiste
|
||||
|
||||
template<uint Size> auto M68K::instructionAND(DataRegister from, EffectiveAddress with) -> void {
|
||||
auto source = read<Size>(from);
|
||||
auto target = read<Size>(with);
|
||||
auto target = read<Size, Hold>(with);
|
||||
auto result = AND<Size>(source, target);
|
||||
write<Size>(with, result);
|
||||
}
|
||||
|
||||
template<uint Size> auto M68K::instructionANDI(EffectiveAddress ea) -> void {
|
||||
template<uint Size> auto M68K::instructionANDI(EffectiveAddress with) -> void {
|
||||
auto source = readPC<Size>();
|
||||
auto target = read<Size, NoUpdate>(ea);
|
||||
auto target = read<Size, Hold>(with);
|
||||
auto result = AND<Size>(source, target);
|
||||
write<Size>(ea, result);
|
||||
write<Size>(with, result);
|
||||
}
|
||||
|
||||
auto M68K::instructionANDI_TO_CCR() -> void {
|
||||
@ -207,7 +206,7 @@ template<uint Size> auto M68K::instructionASL(DataRegister shift, DataRegister m
|
||||
}
|
||||
|
||||
auto M68K::instructionASL(EffectiveAddress modify) -> void {
|
||||
auto result = ASL<Word>(read<Word, NoUpdate>(modify), 1);
|
||||
auto result = ASL<Word>(read<Word, Hold>(modify), 1);
|
||||
write<Word>(modify, result);
|
||||
}
|
||||
|
||||
@ -242,7 +241,7 @@ template<uint Size> auto M68K::instructionASR(DataRegister shift, DataRegister m
|
||||
}
|
||||
|
||||
auto M68K::instructionASR(EffectiveAddress modify) -> void {
|
||||
auto result = ASR<Word>(read<Word, NoUpdate>(modify), 1);
|
||||
auto result = ASR<Word>(read<Word, Hold>(modify), 1);
|
||||
write<Word>(modify, result);
|
||||
}
|
||||
|
||||
@ -256,7 +255,7 @@ auto M68K::instructionBCC(uint4 condition, uint8 displacement) -> void {
|
||||
|
||||
template<uint Size> auto M68K::instructionBCHG(DataRegister bit, EffectiveAddress with) -> void {
|
||||
auto index = read<Size>(bit) & bits<Size>() - 1;
|
||||
auto test = read<Size>(with);
|
||||
auto test = read<Size, Hold>(with);
|
||||
r.z = test.bit(index) == 0;
|
||||
test.bit(index) ^= 1;
|
||||
write<Size>(with, test);
|
||||
@ -264,7 +263,7 @@ template<uint Size> auto M68K::instructionBCHG(DataRegister bit, EffectiveAddres
|
||||
|
||||
template<uint Size> auto M68K::instructionBCHG(EffectiveAddress with) -> void {
|
||||
auto index = readPC<Word>() & bits<Size>() - 1;
|
||||
auto test = read<Size>(with);
|
||||
auto test = read<Size, Hold>(with);
|
||||
r.z = test.bit(index) == 0;
|
||||
test.bit(index) ^= 1;
|
||||
write<Size>(with, test);
|
||||
@ -272,7 +271,7 @@ template<uint Size> auto M68K::instructionBCHG(EffectiveAddress with) -> void {
|
||||
|
||||
template<uint Size> auto M68K::instructionBCLR(DataRegister bit, EffectiveAddress with) -> void {
|
||||
auto index = read<Size>(bit) & bits<Size>() - 1;
|
||||
auto test = read<Size>(with);
|
||||
auto test = read<Size, Hold>(with);
|
||||
r.z = test.bit(index) == 0;
|
||||
test.bit(index) = 0;
|
||||
write<Size>(with, test);
|
||||
@ -280,7 +279,7 @@ template<uint Size> auto M68K::instructionBCLR(DataRegister bit, EffectiveAddres
|
||||
|
||||
template<uint Size> auto M68K::instructionBCLR(EffectiveAddress with) -> void {
|
||||
auto index = readPC<Word>() & bits<Size>() - 1;
|
||||
auto test = read<Size>(with);
|
||||
auto test = read<Size, Hold>(with);
|
||||
r.z = test.bit(index) == 0;
|
||||
test.bit(index) = 0;
|
||||
write<Size>(with, test);
|
||||
@ -288,7 +287,7 @@ template<uint Size> auto M68K::instructionBCLR(EffectiveAddress with) -> void {
|
||||
|
||||
template<uint Size> auto M68K::instructionBSET(DataRegister bit, EffectiveAddress with) -> void {
|
||||
auto index = read<Size>(bit) & bits<Size>() - 1;
|
||||
auto test = read<Size>(with);
|
||||
auto test = read<Size, Hold>(with);
|
||||
r.z = test.bit(index) == 0;
|
||||
test.bit(index) = 1;
|
||||
write<Size>(with, test);
|
||||
@ -296,7 +295,7 @@ template<uint Size> auto M68K::instructionBSET(DataRegister bit, EffectiveAddres
|
||||
|
||||
template<uint Size> auto M68K::instructionBSET(EffectiveAddress with) -> void {
|
||||
auto index = readPC<Word>() & bits<Size>() - 1;
|
||||
auto test = read<Size>(with);
|
||||
auto test = read<Size, Hold>(with);
|
||||
r.z = test.bit(index) == 0;
|
||||
test.bit(index) = 1;
|
||||
write<Size>(with, test);
|
||||
@ -322,7 +321,7 @@ auto M68K::instructionCHK(DataRegister compare, EffectiveAddress maximum) -> voi
|
||||
r.n = sign<Word>(target) < 0;
|
||||
if(r.n) return exception(Exception::BoundsCheck, Vector::BoundsCheck);
|
||||
|
||||
auto result = target - source;
|
||||
auto result = (uint64)target - source;
|
||||
r.c = sign<Word>(result >> 1) < 0;
|
||||
r.v = sign<Word>((target ^ source) & (target ^ result)) < 0;
|
||||
r.z = clip<Word>(result) == 0;
|
||||
@ -331,7 +330,7 @@ auto M68K::instructionCHK(DataRegister compare, EffectiveAddress maximum) -> voi
|
||||
}
|
||||
|
||||
template<uint Size> auto M68K::instructionCLR(EffectiveAddress ea) -> void {
|
||||
read<Size>(ea);
|
||||
read<Size, Hold>(ea);
|
||||
write<Size>(ea, 0);
|
||||
|
||||
r.c = 0;
|
||||
@ -341,7 +340,7 @@ template<uint Size> auto M68K::instructionCLR(EffectiveAddress ea) -> void {
|
||||
}
|
||||
|
||||
template<uint Size> auto M68K::CMP(uint32 source, uint32 target) -> uint32 {
|
||||
uint64 result = (uint64)target - (uint64)source;
|
||||
auto result = (uint64)target - source;
|
||||
|
||||
r.c = sign<Size>(result >> 1) < 0;
|
||||
r.v = sign<Size>((target ^ source) & (target ^ result)) < 0;
|
||||
@ -358,7 +357,7 @@ template<uint Size> auto M68K::instructionCMP(DataRegister dr, EffectiveAddress
|
||||
}
|
||||
|
||||
template<uint Size> auto M68K::instructionCMPA(AddressRegister ar, EffectiveAddress ea) -> void {
|
||||
auto source = read<Size>(ea);
|
||||
auto source = sign<Size>(read<Size>(ea));
|
||||
auto target = read<Size>(ar);
|
||||
CMP<Size>(source, target);
|
||||
}
|
||||
@ -452,14 +451,14 @@ template<uint Size> auto M68K::EOR(uint32 source, uint32 target) -> uint32 {
|
||||
|
||||
template<uint Size> auto M68K::instructionEOR(DataRegister from, EffectiveAddress with) -> void {
|
||||
auto source = read<Size>(from);
|
||||
auto target = read<Size>(with);
|
||||
auto target = read<Size, Hold>(with);
|
||||
auto result = EOR<Size>(source, target);
|
||||
write<Size>(with, result);
|
||||
}
|
||||
|
||||
template<uint Size> auto M68K::instructionEORI(EffectiveAddress with) -> void {
|
||||
auto source = readPC<Size>();
|
||||
auto target = read<Size, NoUpdate>(with);
|
||||
auto target = read<Size, Hold>(with);
|
||||
auto result = EOR<Size>(source, target);
|
||||
write<Size>(with, result);
|
||||
}
|
||||
@ -570,7 +569,7 @@ template<uint Size> auto M68K::instructionLSL(DataRegister sr, DataRegister dr)
|
||||
}
|
||||
|
||||
auto M68K::instructionLSL(EffectiveAddress ea) -> void {
|
||||
auto result = LSL<Word>(read<Word, NoUpdate>(ea), 1);
|
||||
auto result = LSL<Word>(read<Word, Hold>(ea), 1);
|
||||
write<Word>(ea, result);
|
||||
}
|
||||
|
||||
@ -602,7 +601,7 @@ template<uint Size> auto M68K::instructionLSR(DataRegister shift, DataRegister d
|
||||
}
|
||||
|
||||
auto M68K::instructionLSR(EffectiveAddress ea) -> void {
|
||||
auto result = LSR<Word>(read<Word, NoUpdate>(ea), 1);
|
||||
auto result = LSR<Word>(read<Word, Hold>(ea), 1);
|
||||
write<Word>(ea, result);
|
||||
}
|
||||
|
||||
@ -745,8 +744,8 @@ auto M68K::instructionMULU(DataRegister with, EffectiveAddress from) -> void {
|
||||
|
||||
auto M68K::instructionNBCD(EffectiveAddress with) -> void {
|
||||
auto source = 0u;
|
||||
auto target = read<Byte, NoUpdate>(with);
|
||||
auto result = source - target - r.x;
|
||||
auto target = read<Byte, Hold>(with);
|
||||
auto result = (uint64)target - source - r.x;
|
||||
bool v = false;
|
||||
|
||||
const bool adjustLo = (target ^ source ^ result) & 0x10;
|
||||
@ -768,18 +767,18 @@ auto M68K::instructionNBCD(EffectiveAddress with) -> void {
|
||||
|
||||
r.c = sign<Byte>(result >> 1) < 0;
|
||||
r.v = v;
|
||||
r.z = clip<Byte>(result) == 0 ? 0 : r.z;
|
||||
r.z = clip<Byte>(result) ? 0 : r.z;
|
||||
r.n = sign<Byte>(result) < 0;
|
||||
}
|
||||
|
||||
template<uint Size> auto M68K::instructionNEG(EffectiveAddress with) -> void {
|
||||
auto source = read<Size>(with);
|
||||
auto source = read<Size, Hold>(with);
|
||||
auto result = SUB<Size>(0, source);
|
||||
write<Size>(with, result);
|
||||
}
|
||||
|
||||
template<uint Size> auto M68K::instructionNEGX(EffectiveAddress with) -> void {
|
||||
auto source = read<Size>(with);
|
||||
auto source = read<Size, Hold>(with);
|
||||
auto result = SUB<Size, Extend>(0, source);
|
||||
write<Size>(with, result);
|
||||
}
|
||||
@ -788,7 +787,7 @@ auto M68K::instructionNOP() -> void {
|
||||
}
|
||||
|
||||
template<uint Size> auto M68K::instructionNOT(EffectiveAddress with) -> void {
|
||||
auto result = ~read<Size>(with);
|
||||
auto result = ~read<Size, Hold>(with);
|
||||
write<Size>(with, result);
|
||||
|
||||
r.c = 0;
|
||||
@ -817,14 +816,14 @@ template<uint Size> auto M68K::instructionOR(EffectiveAddress from, DataRegister
|
||||
|
||||
template<uint Size> auto M68K::instructionOR(DataRegister from, EffectiveAddress with) -> void {
|
||||
auto source = read<Size>(from);
|
||||
auto target = read<Size>(with);
|
||||
auto target = read<Size, Hold>(with);
|
||||
auto result = OR<Size>(source, target);
|
||||
write<Size>(with, result);
|
||||
}
|
||||
|
||||
template<uint Size> auto M68K::instructionORI(EffectiveAddress with) -> void {
|
||||
auto source = readPC<Size>();
|
||||
auto target = read<Size, NoUpdate>(with);
|
||||
auto target = read<Size, Hold>(with);
|
||||
auto result = OR<Size>(source, target);
|
||||
write<Size>(with, result);
|
||||
}
|
||||
@ -879,7 +878,7 @@ template<uint Size> auto M68K::instructionROL(DataRegister shift, DataRegister m
|
||||
}
|
||||
|
||||
auto M68K::instructionROL(EffectiveAddress modify) -> void {
|
||||
auto result = ROL<Word>(read<Word, NoUpdate>(modify), 1);
|
||||
auto result = ROL<Word>(read<Word, Hold>(modify), 1);
|
||||
write<Word>(modify, result);
|
||||
}
|
||||
|
||||
@ -911,7 +910,7 @@ template<uint Size> auto M68K::instructionROR(DataRegister shift, DataRegister m
|
||||
}
|
||||
|
||||
auto M68K::instructionROR(EffectiveAddress modify) -> void {
|
||||
auto result = ROR<Word>(read<Word, NoUpdate>(modify), 1);
|
||||
auto result = ROR<Word>(read<Word, Hold>(modify), 1);
|
||||
write<Word>(modify, result);
|
||||
}
|
||||
|
||||
@ -944,7 +943,7 @@ template<uint Size> auto M68K::instructionROXL(DataRegister shift, DataRegister
|
||||
}
|
||||
|
||||
auto M68K::instructionROXL(EffectiveAddress modify) -> void {
|
||||
auto result = ROXL<Word>(read<Word, NoUpdate>(modify), 1);
|
||||
auto result = ROXL<Word>(read<Word, Hold>(modify), 1);
|
||||
write<Word>(modify, result);
|
||||
}
|
||||
|
||||
@ -978,7 +977,7 @@ template<uint Size> auto M68K::instructionROXR(DataRegister shift, DataRegister
|
||||
}
|
||||
|
||||
auto M68K::instructionROXR(EffectiveAddress modify) -> void {
|
||||
auto result = ROXR<Word>(read<Word, NoUpdate>(modify), 1);
|
||||
auto result = ROXR<Word>(read<Word, Hold>(modify), 1);
|
||||
write<Word>(modify, result);
|
||||
}
|
||||
|
||||
@ -1001,8 +1000,8 @@ auto M68K::instructionRTS() -> void {
|
||||
|
||||
auto M68K::instructionSBCD(EffectiveAddress with, EffectiveAddress from) -> void {
|
||||
auto source = read<Byte>(from);
|
||||
auto target = read<Byte, NoUpdate>(with);
|
||||
auto result = target - source - r.x;
|
||||
auto target = read<Byte, Hold>(with);
|
||||
auto result = (uint64)target - source - r.x;
|
||||
bool v = false;
|
||||
|
||||
const bool adjustLo = (target ^ source ^ result) & 0x10;
|
||||
@ -1024,7 +1023,7 @@ auto M68K::instructionSBCD(EffectiveAddress with, EffectiveAddress from) -> void
|
||||
|
||||
r.c = sign<Byte>(result >> 1) < 0;
|
||||
r.v = v;
|
||||
r.z = clip<Byte>(result) == 0 ? 0 : r.z;
|
||||
r.z = clip<Byte>(result) ? 0 : r.z;
|
||||
r.n = sign<Byte>(result) < 0;
|
||||
}
|
||||
|
||||
@ -1042,13 +1041,12 @@ auto M68K::instructionSTOP() -> void {
|
||||
}
|
||||
|
||||
template<uint Size, bool Extend> auto M68K::SUB(uint32 source, uint32 target) -> uint32 {
|
||||
uint64 result = source - target;
|
||||
auto result = (uint64)target - source;
|
||||
if(Extend) result -= r.x;
|
||||
|
||||
r.c = sign<Size>(result >> 1) < 0;
|
||||
r.v = sign<Size>((target ^ source) & (target ^ result)) < 0;
|
||||
if(Extend == 0) r.z = clip<Size>(result == 0);
|
||||
if(Extend == 1) if(clip<Size>(result)) r.z = 0;
|
||||
r.z = clip<Size>(result) ? 0 : (Extend ? r.z : 1);
|
||||
r.n = sign<Size>(result) < 0;
|
||||
r.x = r.c;
|
||||
|
||||
@ -1064,34 +1062,34 @@ template<uint Size> auto M68K::instructionSUB(EffectiveAddress source_, DataRegi
|
||||
|
||||
template<uint Size> auto M68K::instructionSUB(DataRegister source_, EffectiveAddress target_) -> void {
|
||||
auto source = read<Size>(source_);
|
||||
auto target = read<Size>(target_);
|
||||
auto target = read<Size, Hold>(target_);
|
||||
auto result = SUB<Size>(source, target);
|
||||
write<Size>(target_, result);
|
||||
}
|
||||
|
||||
template<uint Size> auto M68K::instructionSUBA(AddressRegister to, EffectiveAddress from) -> void {
|
||||
auto source = read<Size>(from);
|
||||
auto source = sign<Size>(read<Size>(from));
|
||||
auto target = read<Size>(to);
|
||||
write<Long>(to, target - source);
|
||||
}
|
||||
|
||||
template<uint Size> auto M68K::instructionSUBI(EffectiveAddress with) -> void {
|
||||
auto source = readPC<Size>();
|
||||
auto target = read<Size>(with);
|
||||
auto target = read<Size, Hold>(with);
|
||||
auto result = SUB<Size>(source, target);
|
||||
write<Size>(with, result);
|
||||
}
|
||||
|
||||
template<uint Size> auto M68K::instructionSUBQ(uint4 immediate, EffectiveAddress ea) -> void {
|
||||
auto source = immediate;
|
||||
auto target = read<Size, NoUpdate>(ea);
|
||||
auto target = read<Size, Hold>(ea);
|
||||
auto result = SUB<Size>(source, target);
|
||||
write<Size>(ea, result);
|
||||
}
|
||||
|
||||
template<uint Size> auto M68K::instructionSUBX(EffectiveAddress with, EffectiveAddress from) -> void {
|
||||
auto source = read<Size>(from);
|
||||
auto target = read<Size>(with);
|
||||
auto target = read<Size, Hold>(with);
|
||||
auto result = SUB<Size, Extend>(source, target);
|
||||
write<Size>(with, result);
|
||||
}
|
||||
@ -1108,7 +1106,7 @@ auto M68K::instructionSWAP(DataRegister with) -> void {
|
||||
}
|
||||
|
||||
auto M68K::instructionTAS(EffectiveAddress with) -> void {
|
||||
auto data = read<Byte, NoUpdate>(with);
|
||||
auto data = read<Byte, Hold>(with);
|
||||
write<Byte>(with, data | 0x80);
|
||||
|
||||
r.c = 0;
|
||||
|
@ -45,10 +45,11 @@ auto M68K::supervisor() -> bool {
|
||||
return false;
|
||||
}
|
||||
|
||||
auto M68K::exception(uint exception, uint vector) -> void {
|
||||
auto M68K::exception(uint exception, uint vector, uint priority) -> void {
|
||||
auto pc = r.pc;
|
||||
auto sr = readSR();
|
||||
|
||||
r.i = priority;
|
||||
r.s = 1;
|
||||
r.t = 0;
|
||||
|
||||
|
@ -7,7 +7,7 @@ namespace Processor {
|
||||
struct M68K {
|
||||
enum : bool { User, Supervisor };
|
||||
enum : uint { Byte, Word, Long };
|
||||
enum : bool { NoUpdate = 0, Reverse = 1, Extend = 1 };
|
||||
enum : bool { Reverse = 1, Extend = 1, Hold = 1 };
|
||||
|
||||
enum : uint {
|
||||
DataRegisterDirect,
|
||||
@ -58,7 +58,7 @@ struct M68K {
|
||||
auto power() -> void;
|
||||
auto reset() -> void;
|
||||
auto supervisor() -> bool;
|
||||
auto exception(uint exception, uint vector) -> void;
|
||||
auto exception(uint exception, uint vector, uint priority = 7) -> void;
|
||||
|
||||
//registers.cpp
|
||||
struct DataRegister {
|
||||
@ -101,8 +101,8 @@ struct M68K {
|
||||
};
|
||||
|
||||
template<uint Size> auto fetch(EffectiveAddress& ea) -> uint32;
|
||||
template<uint Size, bool Update = 1> auto read(EffectiveAddress& ea) -> uint32;
|
||||
template<uint Size, bool Update = 1> auto write(EffectiveAddress& ea, uint32 data) -> void;
|
||||
template<uint Size, bool Hold = 0> auto read(EffectiveAddress& ea) -> uint32;
|
||||
template<uint Size, bool Hold = 0> auto write(EffectiveAddress& ea, uint32 data) -> void;
|
||||
template<uint Size> auto flush(EffectiveAddress& ea, uint32 data) -> void;
|
||||
|
||||
//instruction.cpp
|
||||
@ -126,11 +126,11 @@ struct M68K {
|
||||
template<uint Size> auto instructionADDA(AddressRegister ar, EffectiveAddress ea) -> void;
|
||||
template<uint Size> auto instructionADDI(EffectiveAddress modify) -> void;
|
||||
template<uint Size> auto instructionADDQ(uint4 immediate, EffectiveAddress modify) -> void;
|
||||
template<uint Size> auto instructionADDX(EffectiveAddress target, EffectiveAddress source) -> void;
|
||||
template<uint Size> auto instructionADDX(EffectiveAddress with, EffectiveAddress from) -> void;
|
||||
template<uint Size> auto AND(uint32 source, uint32 target) -> uint32;
|
||||
template<uint Size> auto instructionAND(EffectiveAddress from, DataRegister with) -> void;
|
||||
template<uint Size> auto instructionAND(DataRegister from, EffectiveAddress with) -> void;
|
||||
template<uint Size> auto instructionANDI(EffectiveAddress ea) -> void;
|
||||
template<uint Size> auto instructionANDI(EffectiveAddress with) -> void;
|
||||
auto instructionANDI_TO_CCR() -> void;
|
||||
auto instructionANDI_TO_SR() -> void;
|
||||
template<uint Size> auto ASL(uint32 result, uint shift) -> uint32;
|
||||
@ -282,10 +282,10 @@ private:
|
||||
template<uint Size> auto disassembleADDA(AddressRegister ar, EffectiveAddress ea) -> string;
|
||||
template<uint Size> auto disassembleADDI(EffectiveAddress modify) -> string;
|
||||
template<uint Size> auto disassembleADDQ(uint4 immediate, EffectiveAddress modify) -> string;
|
||||
template<uint Size> auto disassembleADDX(EffectiveAddress target, EffectiveAddress source) -> string;
|
||||
template<uint Size> auto disassembleADDX(EffectiveAddress with, EffectiveAddress from) -> string;
|
||||
template<uint Size> auto disassembleAND(EffectiveAddress from, DataRegister with) -> string;
|
||||
template<uint Size> auto disassembleAND(DataRegister from, EffectiveAddress with) -> string;
|
||||
template<uint Size> auto disassembleANDI(EffectiveAddress ea) -> string;
|
||||
template<uint Size> auto disassembleANDI(EffectiveAddress with) -> string;
|
||||
auto disassembleANDI_TO_CCR() -> string;
|
||||
auto disassembleANDI_TO_SR() -> string;
|
||||
template<uint Size> auto disassembleASL(uint4 shift, DataRegister modify) -> string;
|
||||
|
1
higan/systems/Game Gear.sys/manifest.bml
Normal file
1
higan/systems/Game Gear.sys/manifest.bml
Normal file
@ -0,0 +1 @@
|
||||
system name:Game Gear
|
1
higan/systems/Master System.sys/manifest.bml
Normal file
1
higan/systems/Master System.sys/manifest.bml
Normal file
@ -0,0 +1 @@
|
||||
system name:Master System
|
@ -3,6 +3,7 @@ flags += -DSFC_SUPERGAMEBOY
|
||||
|
||||
include fc/GNUmakefile
|
||||
include sfc/GNUmakefile
|
||||
include ms/GNUmakefile
|
||||
include md/GNUmakefile
|
||||
include gb/GNUmakefile
|
||||
include gba/GNUmakefile
|
||||
|
@ -1,6 +1,7 @@
|
||||
#include "../tomoko.hpp"
|
||||
#include <fc/interface/interface.hpp>
|
||||
#include <sfc/interface/interface.hpp>
|
||||
#include <ms/interface/interface.hpp>
|
||||
#include <md/interface/interface.hpp>
|
||||
#include <gb/interface/interface.hpp>
|
||||
#include <gba/interface/interface.hpp>
|
||||
@ -17,6 +18,7 @@ Program::Program(string_vector args) {
|
||||
|
||||
emulators.append(new Famicom::Interface);
|
||||
emulators.append(new SuperFamicom::Interface);
|
||||
emulators.append(new MasterSystem::Interface);
|
||||
emulators.append(new MegaDrive::Interface);
|
||||
emulators.append(new GameBoy::Interface);
|
||||
emulators.append(new GameBoyAdvance::Interface);
|
||||
|
@ -86,8 +86,8 @@ template<uint Bits> struct Natural {
|
||||
inline auto& operator *=(const type value) { return set(get() * value); }
|
||||
inline auto& operator /=(const type value) { return set(get() / value); }
|
||||
inline auto& operator %=(const type value) { return set(get() % value); }
|
||||
inline auto& operator++(int) { auto value = get(); set(value + 1); return value; }
|
||||
inline auto& operator--(int) { auto value = get(); set(value - 1); return value; }
|
||||
inline auto operator++(int) { auto value = get(); set(value + 1); return value; }
|
||||
inline auto operator--(int) { auto value = get(); set(value - 1); return value; }
|
||||
inline auto& operator++() { return set(get() + 1); }
|
||||
inline auto& operator--() { return set(get() - 1); }
|
||||
|
||||
@ -190,8 +190,8 @@ template<uint Bits> struct Integer {
|
||||
inline auto& operator *=(const utype value) { return set(get() * value); }
|
||||
inline auto& operator /=(const utype value) { return set(get() / value); }
|
||||
inline auto& operator %=(const utype value) { return set(get() % value); }
|
||||
inline auto& operator++(int) { auto value = get(); set(value + 1); return value; }
|
||||
inline auto& operator--(int) { auto value = get(); set(value - 1); return value; }
|
||||
inline auto operator++(int) { auto value = get(); set(value + 1); return value; }
|
||||
inline auto operator--(int) { auto value = get(); set(value - 1); return value; }
|
||||
inline auto& operator++() { return set(get() + 1); }
|
||||
inline auto& operator--() { return set(get() - 1); }
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user