Update to v097r15 release.

byuu says:

Changelog:
- higan now uses Natural<Size>/Integer<Size> for its internal types
- Super Famicom emulation now uses uint24 instead of uint for bus
  addresses (it's a 24-bit bus)
- cleaned up gb/apu MMIO writes
- cleaned up sfc/coprocessor/msu1 MMIO writes
- ~3% speed penalty

I've wanted to do that 24-bit bus thing for so long, but have always
been afraid of the speed impact. It's probably going to hurt
balanced/performance once they compile again, but it wasn't significant
enough to harm the accuracy core's frame rate, thankfully. Only lost one
frame per second.

The GBA core handlers are clearly going to take a lot more work. The
bit-ranges will make it substantially easier to handle, though. Lots of
32-bit registers where certain values span multiple bytes, but we have
to be able to read/write at byte-granularity.
This commit is contained in:
Tim Allen 2016-02-16 20:32:49 +11:00
parent ef65bb862a
commit 4b29f4bad7
61 changed files with 366 additions and 413 deletions

View File

@ -66,16 +66,16 @@ auto APU::Noise::write(uint16 addr, uint8 data) -> void {
}
if(addr == 0xff21) { //NR42
envelopeVolume = data >> 4;
envelopeDirection = data & 0x08;
envelopeFrequency = data & 0x07;
envelopeVolume = data.bits(7,4);
envelopeDirection = data.bit (3);
envelopeFrequency = data.bits(2,0);
if(!dacEnable()) enable = false;
}
if(addr == 0xff22) { //NR43
frequency = data >> 4;
narrow = data & 0x08;
divisor = data & 0x07;
frequency = data.bits(7,4);
narrow = data.bit (3);
divisor = data.bits(2,0);
period = getPeriod();
}
@ -84,10 +84,9 @@ auto APU::Noise::write(uint16 addr, uint8 data) -> void {
if(length && --length == 0) enable = false;
}
bool initialize = data & 0x80;
counter = data & 0x40;
counter = data.bit(6);
if(initialize) {
if(data.bit(7)) {
enable = dacEnable();
lfsr = -1;
envelopePeriod = envelopeFrequency ? (uint)envelopeFrequency : 8;
@ -95,7 +94,7 @@ auto APU::Noise::write(uint16 addr, uint8 data) -> void {
if(!length) {
length = 64;
if((apu.phase & 1) && counter) length--;
if(apu.phase.bit(0) && counter) length--;
}
}
}

View File

@ -68,26 +68,26 @@ auto APU::Sequencer::read(uint16 addr) -> uint8 {
auto APU::Sequencer::write(uint16 addr, uint8 data) -> void {
if(addr == 0xff24) { //NR50
leftEnable = (uint1)(data >> 7);
leftVolume = (uint3)(data >> 4);
rightEnable = (uint1)(data >> 3);
rightVolume = (uint3)(data >> 0);
leftEnable = data.bit (7);
leftVolume = data.bits(6,4);
rightEnable = data.bit (3);
rightVolume = data.bits(2,0);
}
if(addr == 0xff25) { //NR51
noise.leftEnable = data & 0x80;
wave.leftEnable = data & 0x40;
square2.leftEnable = data & 0x20;
square1.leftEnable = data & 0x10;
noise.rightEnable = data & 0x08;
wave.rightEnable = data & 0x04;
square2.rightEnable = data & 0x02;
square1.rightEnable = data & 0x01;
noise.leftEnable = data.bit(7);
wave.leftEnable = data.bit(6);
square2.leftEnable = data.bit(5);
square1.leftEnable = data.bit(4);
noise.rightEnable = data.bit(3);
wave.rightEnable = data.bit(2);
square2.rightEnable = data.bit(1);
square1.rightEnable = data.bit(0);
}
if(addr == 0xff26) { //NR52
if(enable != (bool)(data & 0x80)) {
enable = data & 0x80;
if(enable != data.bit(7)) {
enable = data.bit(7);
if(!enable) {
//power(bool) resets length counters when true (eg for CGB only)

View File

@ -86,38 +86,37 @@ auto APU::Square1::read(uint16 addr) -> uint8 {
auto APU::Square1::write(uint16 addr, uint8 data) -> void {
if(addr == 0xff10) { //NR10
if(sweepEnable && sweepNegate && !(data & 0x08)) enable = false;
sweepFrequency = (data >> 4) & 7;
sweepDirection = data & 0x08;
sweepShift = data & 0x07;
if(sweepEnable && sweepNegate && !data.bit(3)) enable = false;
sweepFrequency = data.bits(6,4);
sweepDirection = data.bit (3);
sweepShift = data.bits(2,0);
}
if(addr == 0xff11) { //NR11
duty = data >> 6;
length = 64 - (data & 0x3f);
duty = data.bits(7,6);
length = 64 - data.bits(5,0);
}
if(addr == 0xff12) { //NR12
envelopeVolume = data >> 4;
envelopeDirection = data & 0x08;
envelopeFrequency = data & 0x07;
envelopeVolume = data.bits(7,4);
envelopeDirection = data.bit (3);
envelopeFrequency = data.bits(2,0);
if(!dacEnable()) enable = false;
}
if(addr == 0xff13) { //NR13
frequency = (frequency & 0x0700) | data;
frequency.bits(7,0) = data;
}
if(addr == 0xff14) { //NR14
if((apu.phase & 1) && !counter && (data & 0x40)) {
if(apu.phase.bit(0) && !counter && data.bit(6)) {
if(length && --length == 0) enable = false;
}
bool initialize = data & 0x80;
counter = data & 0x40;
frequency = ((data & 7) << 8) | (frequency & 0x00ff);
counter = data.bit(6);
frequency.bits(10,8) = data.bits(2,0);
if(initialize) {
if(data.bit(7)) {
enable = dacEnable();
period = 2 * (2048 - frequency);
envelopePeriod = envelopeFrequency ? (uint)envelopeFrequency : 8;
@ -125,7 +124,7 @@ auto APU::Square1::write(uint16 addr, uint8 data) -> void {
if(!length) {
length = 64;
if((apu.phase & 1) && counter) length--;
if(apu.phase.bit(0) && counter) length--;
}
frequencyShadow = frequency;

View File

@ -60,31 +60,30 @@ auto APU::Square2::read(uint16 addr) -> uint8 {
auto APU::Square2::write(uint16 addr, uint8 data) -> void {
if(addr == 0xff16) { //NR21
duty = data >> 6;
length = 64 - (data & 0x3f);
duty = data.bits(7,6);
length = 64 - data.bits(5,0);
}
if(addr == 0xff17) { //NR22
envelopeVolume = data >> 4;
envelopeDirection = data & 0x08;
envelopeFrequency = data & 0x07;
envelopeVolume = data.bits(7,4);
envelopeDirection = data.bit (3);
envelopeFrequency = data.bits(2,0);
if(!dacEnable()) enable = false;
}
if(addr == 0xff18) { //NR23
frequency = (frequency & 0x0700) | data;
frequency.bits(7,0) = data;
}
if(addr == 0xff19) { //NR24
if((apu.phase & 1) && !counter && (data & 0x40)) {
if(apu.phase.bit(0) && !counter && data.bit(6)) {
if(length && --length == 0) enable = false;
}
bool initialize = data & 0x80;
counter = data & 0x40;
frequency = ((data & 7) << 8) | (frequency & 0x00ff);
counter = data.bit(6);
frequency.bits(10,8) = data.bits(2,0);
if(initialize) {
if(data.bit(7)) {
enable = dacEnable();
period = 2 * (2048 - frequency);
envelopePeriod = envelopeFrequency ? (uint)envelopeFrequency : 8;
@ -92,7 +91,7 @@ auto APU::Square2::write(uint16 addr, uint8 data) -> void {
if(!length) {
length = 64;
if((apu.phase & 1) && counter) length--;
if(apu.phase.bit(0) && counter) length--;
}
}
}

View File

@ -59,7 +59,7 @@ auto APU::Wave::read(uint16 addr) -> uint8 {
auto APU::Wave::write(uint16 addr, uint8 data) -> void {
if(addr == 0xff1a) { //NR30
dacEnable = data & 0x80;
dacEnable = data.bit(7);
if(!dacEnable) enable = false;
}
@ -68,23 +68,22 @@ auto APU::Wave::write(uint16 addr, uint8 data) -> void {
}
if(addr == 0xff1c) { //NR32
volume = data >> 5;
volume = data.bits(6,5);
}
if(addr == 0xff1d) { //NR33
frequency = (frequency & 0x0700) | data;
frequency.bits(7,0) = data;
}
if(addr == 0xff1e) { //NR34
if((apu.phase & 1) && !counter && (data & 0x40)) {
if(apu.phase.bit(0) && !counter && data.bit(6)) {
if(length && --length == 0) enable = false;
}
bool initialize = data & 0x80;
counter = data & 0x40;
frequency = ((data & 7) << 8) | (frequency & 0x00ff);
counter = data.bit(6);
frequency.bits(10,8) = data.bits(2,0);
if(initialize) {
if(data.bit(7)) {
if(!system.cgb() && patternHold) {
//DMG,SGB trigger while channel is being read corrupts wave RAM
if((patternOffset >> 1) <= 3) {
@ -107,7 +106,7 @@ auto APU::Wave::write(uint16 addr, uint8 data) -> void {
if(!length) {
length = 256;
if((apu.phase & 1) && counter) length--;
if(apu.phase.bit(0) && counter) length--;
}
}
}

View File

@ -65,8 +65,8 @@ auto CPU::read(uint32 addr) -> uint8 {
case 0x04000130:
if(auto result = player.keyinput()) return result() >> 0;
for(unsigned n = 0; n < 8; n++) result |= interface->inputPoll(0, 0, n) << n;
if((result & 0xc0) == 0xc0) result &= ~0xc0; //up+down cannot be pressed simultaneously
if((result & 0x30) == 0x30) result &= ~0x30; //left+right cannot be pressed simultaneously
if((result & 0xc0) == 0xc0) result &= (uint8)~0xc0; //up+down cannot be pressed simultaneously
if((result & 0x30) == 0x30) result &= (uint8)~0x30; //left+right cannot be pressed simultaneously
return result ^ 0xff;
case 0x04000131:
if(auto result = player.keyinput()) return result() >> 8;

View File

@ -537,7 +537,7 @@ template<uint b, uint x> auto LR35902::op_res_n_r() {
}
template<uint b> auto LR35902::op_res_n_hl() {
uint8 n = op_read(r[HL]);
uint n = op_read(r[HL]);
n &= ~(1 << b);
op_write(r[HL], n);
}

View File

@ -14,13 +14,13 @@ struct R65816 {
using fp = auto (R65816::*)() -> void;
virtual auto op_io() -> void = 0;
virtual auto op_read(uint32 addr) -> uint8 = 0;
virtual auto op_write(uint32 addr, uint8 data) -> void = 0;
virtual auto op_read(uint24 addr) -> uint8 = 0;
virtual auto op_write(uint24 addr, uint8 data) -> void = 0;
virtual auto last_cycle() -> void = 0;
virtual auto interrupt_pending() -> bool = 0;
virtual auto op_irq() -> void;
virtual auto disassembler_read(uint32 addr) -> uint8 { return 0u; }
virtual auto disassembler_read(uint24 addr) -> uint8 { return 0u; }
//r65816.cpp
alwaysinline auto op_io_irq() -> void;

View File

@ -36,15 +36,15 @@ struct Cartridge : property<Cartridge> {
MappedRAM ram;
struct Mapping {
function<auto (uint, uint8) -> uint8> reader;
function<auto (uint, uint8) -> void> writer;
function<auto (uint24, uint8) -> uint8> reader;
function<auto (uint24, uint8) -> void> writer;
string addr;
uint size = 0;
uint base = 0;
uint mask = 0;
Mapping() = default;
Mapping(const function<uint8 (uint, uint8)>&, const function<void (uint, uint8)>&);
Mapping(const function<uint8 (uint24, uint8)>&, const function<void (uint24, uint8)>&);
Mapping(SuperFamicom::Memory&);
};
vector<Mapping> mapping;
@ -84,7 +84,7 @@ private:
//markup.cpp
auto parseMarkup(const string&) -> void;
auto parseMarkupMap(Markup::Node, SuperFamicom::Memory&) -> void;
auto parseMarkupMap(Markup::Node, const function<uint8 (uint, uint8)>&, const function<void (uint, uint8)>&) -> void;
auto parseMarkupMap(Markup::Node, const function<uint8 (uint24, uint8)>&, const function<void (uint24, uint8)>&) -> void;
auto parseMarkupMemory(MappedRAM&, Markup::Node, uint id, bool writable) -> void;
auto parseMarkupROM(Markup::Node) -> void;

View File

@ -3,7 +3,7 @@ Cartridge::Mapping::Mapping(SuperFamicom::Memory& memory) {
this->writer = {&SuperFamicom::Memory::write, &memory};
}
Cartridge::Mapping::Mapping(const function<uint8 (uint, uint8)>& reader, const function<void (uint, uint8)>& writer) {
Cartridge::Mapping::Mapping(const function<uint8 (uint24, uint8)>& reader, const function<void (uint24, uint8)>& writer) {
this->reader = reader;
this->writer = writer;
}
@ -51,8 +51,8 @@ auto Cartridge::parseMarkupMap(Markup::Node map, SuperFamicom::Memory& memory) -
auto Cartridge::parseMarkupMap(
Markup::Node map,
const function<uint8 (uint, uint8)>& reader,
const function<void (uint, uint8)>& writer
const function<uint8 (uint24, uint8)>& reader,
const function<void (uint24, uint8)>& writer
) -> void {
Mapping m{reader, writer};
m.addr = map["address"].text();

View File

@ -58,7 +58,7 @@ auto ArmDSP::step(uint clocks) -> void {
//3800-3807 mirrored throughout
//a0 ignored
auto ArmDSP::mmio_read(uint addr, uint8) -> uint8 {
auto ArmDSP::mmio_read(uint24 addr, uint8) -> uint8 {
cpu.synchronizeCoprocessors();
uint8 data = 0x00;
@ -82,7 +82,7 @@ auto ArmDSP::mmio_read(uint addr, uint8) -> uint8 {
return data;
}
auto ArmDSP::mmio_write(uint addr, uint8 data) -> void {
auto ArmDSP::mmio_write(uint24 addr, uint8 data) -> void {
cpu.synchronizeCoprocessors();
addr &= 0xff06;

View File

@ -15,8 +15,8 @@ struct ArmDSP : Processor::ARM, Coprocessor {
auto bus_read(uint mode, uint32 addr) -> uint32 override;
auto bus_write(uint mode, uint32 addr, uint32 word) -> void override;
auto mmio_read(uint addr, uint8 data) -> uint8;
auto mmio_write(uint addr, uint8 data) -> void;
auto mmio_read(uint24 addr, uint8 data) -> uint8;
auto mmio_write(uint24 addr, uint8 data) -> void;
auto init() -> void;
auto load() -> void;

View File

@ -135,7 +135,7 @@ auto EpsonRTC::sync() -> void {
resync = true; //alert program that time has changed
}
auto EpsonRTC::read(uint addr, uint8 data) -> uint8 {
auto EpsonRTC::read(uint24 addr, uint8 data) -> uint8 {
cpu.synchronizeCoprocessors();
addr &= 3;
@ -160,7 +160,7 @@ auto EpsonRTC::read(uint addr, uint8 data) -> uint8 {
return data;
}
auto EpsonRTC::write(uint addr, uint8 data) -> void {
auto EpsonRTC::write(uint24 addr, uint8 data) -> void {
cpu.synchronizeCoprocessors();
addr &= 3, data &= 15;

View File

@ -11,8 +11,8 @@ struct EpsonRTC : Coprocessor {
auto reset() -> void;
auto sync() -> void;
auto read(uint addr, uint8 data) -> uint8;
auto write(uint addr, uint8 data) -> void;
auto read(uint24 addr, uint8 data) -> uint8;
auto write(uint24 addr, uint8 data) -> void;
auto serialize(serializer&) -> void;

View File

@ -56,7 +56,7 @@ auto Event::reset() -> void {
scoreSecondsRemaining = 0;
}
auto Event::mcuRead(uint addr, uint8 data) -> uint8 {
auto Event::mcuRead(uint24 addr, uint8 data) -> uint8 {
if(board == Board::CampusChallenge92) {
uint id = 0;
if(select == 0x09) id = 1;
@ -92,17 +92,17 @@ auto Event::mcuRead(uint addr, uint8 data) -> uint8 {
return data;
}
auto Event::mcuWrite(uint addr, uint8 data) -> void {
auto Event::mcuWrite(uint24 addr, uint8 data) -> void {
}
auto Event::read(uint addr, uint8 data) -> uint8 {
auto Event::read(uint24 addr, uint8 data) -> uint8 {
if(addr == 0x106000 || addr == 0xc00000) {
return status;
}
return data;
}
auto Event::write(uint addr, uint8 data) -> void {
auto Event::write(uint24 addr, uint8 data) -> void {
if(addr == 0x206000 || addr == 0xe00000) {
select = data;
if(timer && data == 0x09) {

View File

@ -11,11 +11,11 @@ struct Event : Coprocessor {
auto power() -> void;
auto reset() -> void;
auto mcuRead(uint addr, uint8) -> uint8;
auto mcuWrite(uint addr, uint8) -> void;
auto mcuRead(uint24 addr, uint8) -> uint8;
auto mcuWrite(uint24 addr, uint8) -> void;
auto read(uint addr, uint8 data) -> uint8;
auto write(uint addr, uint8 data) -> void;
auto read(uint24 addr, uint8 data) -> uint8;
auto write(uint24 addr, uint8 data) -> void;
auto serialize(serializer&) -> void;

View File

@ -18,20 +18,20 @@ struct HitachiDSP : Processor::HG51B, Coprocessor {
auto bus_write(uint24 addr, uint8 data) -> void;
//CPU ROM read/write
auto rom_read(uint addr, uint8 data) -> uint8;
auto rom_write(uint addr, uint8 data) -> void;
auto rom_read(uint24 addr, uint8 data) -> uint8;
auto rom_write(uint24 addr, uint8 data) -> void;
//CPU RAM read/write
auto ram_read(uint addr, uint8 data) -> uint8;
auto ram_write(uint addr, uint8 data) -> void;
auto ram_read(uint24 addr, uint8 data) -> uint8;
auto ram_write(uint24 addr, uint8 data) -> void;
//HG51B data RAM read/write
auto dram_read(uint addr, uint8 data) -> uint8;
auto dram_write(uint addr, uint8 data) -> void;
auto dram_read(uint24 addr, uint8 data) -> uint8;
auto dram_write(uint24 addr, uint8 data) -> void;
//CPU MMIO read/write
auto dsp_read(uint addr, uint8 data) -> uint8;
auto dsp_write(uint addr, uint8 data) -> void;
auto dsp_read(uint24 addr, uint8 data) -> uint8;
auto dsp_write(uint24 addr, uint8 data) -> void;
auto firmware() const -> vector<uint8>;
auto serialize(serializer&) -> void;

View File

@ -35,7 +35,7 @@ auto HitachiDSP::bus_write(uint24 addr, uint8 data) -> void {
}
}
auto HitachiDSP::rom_read(uint addr, uint8 data) -> uint8 {
auto HitachiDSP::rom_read(uint24 addr, uint8 data) -> uint8 {
if(co_active() == hitachidsp.thread || regs.halt) {
addr = Bus::mirror(addr, rom.size());
//if(Roms == 2 && mmio.r1f52 == 1 && addr >= (bit::round(rom.size()) >> 1)) return 0x00;
@ -45,32 +45,32 @@ auto HitachiDSP::rom_read(uint addr, uint8 data) -> uint8 {
return data;
}
auto HitachiDSP::rom_write(uint addr, uint8 data) -> void {
auto HitachiDSP::rom_write(uint24 addr, uint8 data) -> void {
}
auto HitachiDSP::ram_read(uint addr, uint8 data) -> uint8 {
auto HitachiDSP::ram_read(uint24 addr, uint8 data) -> uint8 {
if(ram.size() == 0) return 0x00; //not open bus
return ram.read(Bus::mirror(addr, ram.size()), data);
}
auto HitachiDSP::ram_write(uint addr, uint8 data) -> void {
auto HitachiDSP::ram_write(uint24 addr, uint8 data) -> void {
if(ram.size() == 0) return;
return ram.write(Bus::mirror(addr, ram.size()), data);
}
auto HitachiDSP::dram_read(uint addr, uint8 data) -> uint8 {
auto HitachiDSP::dram_read(uint24 addr, uint8 data) -> uint8 {
addr &= 0xfff;
if(addr >= 0xc00) return data;
return dataRAM[addr];
}
auto HitachiDSP::dram_write(uint addr, uint8 data) -> void {
auto HitachiDSP::dram_write(uint24 addr, uint8 data) -> void {
addr &= 0xfff;
if(addr >= 0xc00) return;
dataRAM[addr] = data;
}
auto HitachiDSP::dsp_read(uint addr, uint8) -> uint8 {
auto HitachiDSP::dsp_read(uint24 addr, uint8) -> uint8 {
addr = 0x7c00 | (addr & 0x03ff);
//MMIO
@ -115,7 +115,7 @@ auto HitachiDSP::dsp_read(uint addr, uint8) -> uint8 {
return 0x00;
}
auto HitachiDSP::dsp_write(uint addr, uint8 data) -> void {
auto HitachiDSP::dsp_write(uint24 addr, uint8 data) -> void {
addr = 0x7c00 | (addr & 0x03ff);
//MMIO

View File

@ -8,8 +8,8 @@ struct ICD2 : Emulator::Interface::Bind, GameBoy::Interface::Hook, Coprocessor {
auto power() -> void;
auto reset() -> void;
auto read(uint addr, uint8 data) -> uint8;
auto write(uint addr, uint8 data) -> void;
auto read(uint24 addr, uint8 data) -> uint8;
auto write(uint24 addr, uint8 data) -> void;
auto serialize(serializer&) -> void;

View File

@ -1,4 +1,4 @@
auto ICD2::read(uint addr, uint8 data) -> uint8 {
auto ICD2::read(uint24 addr, uint8 data) -> uint8 {
addr &= 0x40ffff;
//LY counter
@ -38,7 +38,7 @@ auto ICD2::read(uint addr, uint8 data) -> uint8 {
return 0x00;
}
auto ICD2::write(uint addr, uint8 data) -> void {
auto ICD2::write(uint24 addr, uint8 data) -> void {
addr &= 0xffff;
//VRAM port

View File

@ -26,7 +26,7 @@ auto MCC::reset() -> void {
commit();
}
auto MCC::memory_access(bool write, Memory& memory, uint addr, uint8 data) -> uint8 {
auto MCC::memory_access(bool write, Memory& memory, uint24 addr, uint8 data) -> uint8 {
addr = bus.mirror(addr, memory.size());
if(!write) {
return memory.read(addr, data);
@ -37,7 +37,7 @@ auto MCC::memory_access(bool write, Memory& memory, uint addr, uint8 data) -> ui
//map address=00-3f,80-bf:8000-ffff mask=0x408000
//map address=40-7d,c0-ff:0000-ffff
auto MCC::mcu_access(bool write, uint addr, uint8 data) -> uint8 {
auto MCC::mcu_access(bool write, uint24 addr, uint8 data) -> uint8 {
if(addr < 0x400000) {
//note: manifest maps 00-3f,80-bf:8000-ffff mask=0x408000 => 00-3f:0000-ffff
//the intention is consistency in pre-decoding as much as possible
@ -88,15 +88,15 @@ auto MCC::mcu_access(bool write, uint addr, uint8 data) -> uint8 {
return 0x00;
}
auto MCC::mcu_read(uint addr, uint8 data) -> uint8 {
auto MCC::mcu_read(uint24 addr, uint8 data) -> uint8 {
return mcu_access(false, addr, data);
}
auto MCC::mcu_write(uint addr, uint8 data) -> void {
auto MCC::mcu_write(uint24 addr, uint8 data) -> void {
mcu_access(true, addr, data);
}
auto MCC::read(uint addr, uint8 data) -> uint8 {
auto MCC::read(uint24 addr, uint8 data) -> uint8 {
if((addr & 0xf0ffff) == 0x005000) { //$00-0f:5000
uint8 n = (addr >> 16) & 15;
return r[n];
@ -105,7 +105,7 @@ auto MCC::read(uint addr, uint8 data) -> uint8 {
return data;
}
auto MCC::write(uint addr, uint8 data) -> void {
auto MCC::write(uint24 addr, uint8 data) -> void {
if((addr & 0xf0ffff) == 0x005000) { //$00-0f:5000
uint8 n = (addr >> 16) & 15;
r[n] = data;

View File

@ -10,14 +10,14 @@ struct MCC {
auto power() -> void;
auto reset() -> void;
auto memory_access(bool write, Memory& memory, uint addr, uint8 data) -> uint8;
auto mcu_access(bool write, uint addr, uint8 data) -> uint8;
auto memory_access(bool write, Memory& memory, uint24 addr, uint8 data) -> uint8;
auto mcu_access(bool write, uint24 addr, uint8 data) -> uint8;
auto mcu_read(uint addr, uint8 data) -> uint8;
auto mcu_write(uint addr, uint8 data) -> void;
auto mcu_read(uint24 addr, uint8 data) -> uint8;
auto mcu_write(uint24 addr, uint8 data) -> void;
auto read(uint addr, uint8 data) -> uint8;
auto write(uint addr, uint8 data) -> void;
auto read(uint24 addr, uint8 data) -> uint8;
auto write(uint24 addr, uint8 data) -> void;
auto commit() -> void;

View File

@ -119,18 +119,20 @@ auto MSU1::audioOpen() -> void {
mmio.audioError = true;
}
auto MSU1::mmioRead(uint addr, uint8) -> uint8 {
auto MSU1::mmioRead(uint24 addr, uint8) -> uint8 {
cpu.synchronizeCoprocessors();
addr = 0x2000 | (addr & 7);
switch(addr) {
case 0x2000:
return (mmio.dataBusy << 7)
| (mmio.audioBusy << 6)
| (mmio.audioRepeat << 5)
| (mmio.audioPlay << 4)
| (mmio.audioError << 3)
| (Revision << 0);
return (
mmio.dataBusy << 7
| mmio.audioBusy << 6
| mmio.audioRepeat << 5
| mmio.audioPlay << 4
| mmio.audioError << 3
| Revision << 0
);
case 0x2001:
if(mmio.dataBusy) return 0x00;
if(dataFile.end()) return 0x00;
@ -145,20 +147,20 @@ auto MSU1::mmioRead(uint addr, uint8) -> uint8 {
}
}
auto MSU1::mmioWrite(uint addr, uint8 data) -> void {
auto MSU1::mmioWrite(uint24 addr, uint8 data) -> void {
cpu.synchronizeCoprocessors();
addr = 0x2000 | (addr & 7);
switch(addr) {
case 0x2000: mmio.dataSeekOffset = (mmio.dataSeekOffset & 0xffffff00) | (data << 0); break;
case 0x2001: mmio.dataSeekOffset = (mmio.dataSeekOffset & 0xffff00ff) | (data << 8); break;
case 0x2002: mmio.dataSeekOffset = (mmio.dataSeekOffset & 0xff00ffff) | (data << 16); break;
case 0x2003: mmio.dataSeekOffset = (mmio.dataSeekOffset & 0x00ffffff) | (data << 24);
case 0x2000: mmio.dataSeekOffset.byte(0) = data; break;
case 0x2001: mmio.dataSeekOffset.byte(1) = data; break;
case 0x2002: mmio.dataSeekOffset.byte(2) = data; break;
case 0x2003: mmio.dataSeekOffset.byte(3) = data;
mmio.dataReadOffset = mmio.dataSeekOffset;
dataOpen();
break;
case 0x2004: mmio.audioTrack = (mmio.audioTrack & 0xff00) | (data << 0); break;
case 0x2005: mmio.audioTrack = (mmio.audioTrack & 0x00ff) | (data << 8);
case 0x2004: mmio.audioTrack.byte(0) = data; break;
case 0x2005: mmio.audioTrack.byte(1) = data;
mmio.audioPlayOffset = 8;
if(mmio.audioTrack == mmio.audioResumeTrack) {
mmio.audioPlayOffset = mmio.audioResumeOffset;
@ -173,9 +175,9 @@ auto MSU1::mmioWrite(uint addr, uint8 data) -> void {
case 0x2007:
if(mmio.audioBusy) break;
if(mmio.audioError) break;
bool audioResume = data & 4;
mmio.audioRepeat = data & 2;
mmio.audioPlay = data & 1;
bool audioResume = data.bit(2);
mmio.audioRepeat = data.bit(1);
mmio.audioPlay = data.bit(0);
if(!mmio.audioPlay && audioResume) {
mmio.audioResumeTrack = mmio.audioTrack;
mmio.audioResumeOffset = mmio.audioPlayOffset;

View File

@ -10,8 +10,8 @@ struct MSU1 : Coprocessor {
auto dataOpen() -> void;
auto audioOpen() -> void;
auto mmioRead(uint addr, uint8 data) -> uint8;
auto mmioWrite(uint addr, uint8 data) -> void;
auto mmioRead(uint24 addr, uint8 data) -> uint8;
auto mmioWrite(uint24 addr, uint8 data) -> void;
auto serialize(serializer&) -> void;

View File

@ -15,7 +15,7 @@ auto NECDSP::main() -> void {
synchronizeCPU();
}
auto NECDSP::read(uint addr, uint8) -> uint8 {
auto NECDSP::read(uint24 addr, uint8) -> uint8 {
cpu.synchronizeCoprocessors();
if(addr & 1) {
return uPD96050::readSR();
@ -24,7 +24,7 @@ auto NECDSP::read(uint addr, uint8) -> uint8 {
}
}
auto NECDSP::write(uint addr, uint8 data) -> void {
auto NECDSP::write(uint24 addr, uint8 data) -> void {
cpu.synchronizeCoprocessors();
if(addr & 1) {
return uPD96050::writeSR(data);
@ -33,12 +33,12 @@ auto NECDSP::write(uint addr, uint8 data) -> void {
}
}
auto NECDSP::readRAM(uint addr, uint8) -> uint8 {
auto NECDSP::readRAM(uint24 addr, uint8) -> uint8 {
cpu.synchronizeCoprocessors();
return uPD96050::readDP(addr);
}
auto NECDSP::writeRAM(uint addr, uint8 data) -> void {
auto NECDSP::writeRAM(uint24 addr, uint8 data) -> void {
cpu.synchronizeCoprocessors();
return uPD96050::writeDP(addr, data);
}

View File

@ -2,11 +2,11 @@ struct NECDSP : Processor::uPD96050, Coprocessor {
static auto Enter() -> void;
auto main() -> void;
auto read(uint addr, uint8 data) -> uint8;
auto write(uint addr, uint8 data) -> void;
auto read(uint24 addr, uint8 data) -> uint8;
auto write(uint24 addr, uint8 data) -> void;
auto readRAM(uint addr, uint8 data) -> uint8;
auto writeRAM(uint addr, uint8 data) -> void;
auto readRAM(uint24 addr, uint8 data) -> uint8;
auto writeRAM(uint24 addr, uint8 data) -> void;
auto init() -> void;
auto load() -> void;

View File

@ -23,11 +23,11 @@ auto NSS::set_dip(uint16 dip) -> void {
this->dip = dip;
}
auto NSS::read(uint, uint8) -> uint8 {
auto NSS::read(uint24, uint8) -> uint8 {
return dip;
}
auto NSS::write(uint, uint8) -> void {
auto NSS::write(uint24, uint8) -> void {
}
}

View File

@ -6,8 +6,8 @@ struct NSS {
auto reset() -> void;
auto set_dip(uint16 dip) -> void;
auto read(uint addr, uint8 data) -> uint8;
auto write(uint addr, uint8 data) -> void;
auto read(uint24 addr, uint8 data) -> uint8;
auto write(uint24 addr, uint8 data) -> void;
uint8 dip = 0x00;
};

View File

@ -24,7 +24,7 @@ auto OBC1::reset() -> void {
status.shift = (ramRead(0x1ff6) & 3) << 1;
}
auto OBC1::read(uint addr, uint8) -> uint8 {
auto OBC1::read(uint24 addr, uint8) -> uint8 {
addr &= 0x1fff;
switch(addr) {
@ -38,7 +38,7 @@ auto OBC1::read(uint addr, uint8) -> uint8 {
return ramRead(addr);
}
auto OBC1::write(uint addr, uint8 data) -> void {
auto OBC1::write(uint24 addr, uint8 data) -> void {
addr &= 0x1fff;
switch(addr) {

View File

@ -5,8 +5,8 @@ struct OBC1 {
auto power() -> void;
auto reset() -> void;
auto read(uint addr, uint8 data) -> uint8;
auto write(uint addr, uint8 data) -> void;
auto read(uint24 addr, uint8 data) -> uint8;
auto write(uint24 addr, uint8 data) -> void;
auto serialize(serializer&) -> void;

View File

@ -4,12 +4,12 @@ auto SA1::CPUIRAM::size() const -> uint {
return sa1.iram.size();
}
auto SA1::CPUIRAM::read(uint addr, uint8) -> uint8 {
auto SA1::CPUIRAM::read(uint24 addr, uint8) -> uint8 {
cpu.synchronizeCoprocessors();
return sa1.iram.read(addr & 0x07ff);
}
auto SA1::CPUIRAM::write(uint addr, uint8 data) -> void {
auto SA1::CPUIRAM::write(uint24 addr, uint8 data) -> void {
cpu.synchronizeCoprocessors();
sa1.iram.write(addr & 0x07ff, data);
}
@ -18,13 +18,13 @@ auto SA1::CPUBWRAM::size() const -> uint {
return sa1.bwram.size();
}
auto SA1::CPUBWRAM::read(uint addr, uint8) -> uint8 {
auto SA1::CPUBWRAM::read(uint24 addr, uint8) -> uint8 {
cpu.synchronizeCoprocessors();
if(dma) return sa1.dma_cc1_read(addr);
return sa1.bwram.read(addr);
}
auto SA1::CPUBWRAM::write(uint addr, uint8 data) -> void {
auto SA1::CPUBWRAM::write(uint24 addr, uint8 data) -> void {
cpu.synchronizeCoprocessors();
sa1.bwram.write(addr, data);
}

View File

@ -1,12 +1,12 @@
struct CPUIRAM : Memory {
auto size() const -> uint;
alwaysinline auto read(uint, uint8 = 0) -> uint8;
alwaysinline auto write(uint, uint8) -> void;
alwaysinline auto read(uint24, uint8 = 0) -> uint8;
alwaysinline auto write(uint24, uint8) -> void;
} cpuiram;
struct CPUBWRAM : Memory {
auto size() const -> uint;
alwaysinline auto read(uint, uint8 = 0) -> uint8;
alwaysinline auto write(uint, uint8) -> void;
alwaysinline auto read(uint24, uint8 = 0) -> uint8;
alwaysinline auto write(uint24, uint8) -> void;
bool dma;
} cpubwram;

View File

@ -1,4 +1,4 @@
auto SA1::bus_read(uint addr, uint8 data) -> uint8 {
auto SA1::bus_read(uint24 addr, uint8 data) -> uint8 {
if((addr & 0x40fe00) == 0x002200) { //$00-3f,80-bf:2200-23ff
return mmio_read(addr, data);
}
@ -40,7 +40,7 @@ auto SA1::bus_read(uint addr, uint8 data) -> uint8 {
return data;
}
auto SA1::bus_write(uint addr, uint8 data) -> void {
auto SA1::bus_write(uint24 addr, uint8 data) -> void {
if((addr & 0x40fe00) == 0x002200) { //$00-3f,80-bf:2200-23ff
return mmio_write(addr, data);
}
@ -74,7 +74,7 @@ auto SA1::bus_write(uint addr, uint8 data) -> void {
//this is used both to keep VBR-reads from accessing MMIO registers, and
//to avoid syncing the S-CPU and SA-1*; as both chips are able to access
//these ports.
auto SA1::vbr_read(uint addr, uint8 data) -> uint8 {
auto SA1::vbr_read(uint24 addr, uint8 data) -> uint8 {
if((addr & 0x408000) == 0x008000) { //$00-3f,80-bf:8000-ffff
addr = ((addr & 0x800000) >> 2) | ((addr & 0x3f0000) >> 1) | (addr & 0x7fff);
return mmcrom_read(addr, data);
@ -112,13 +112,13 @@ auto SA1::op_io() -> void {
tick();
}
auto SA1::op_read(uint32 addr) -> uint8 {
auto SA1::op_read(uint24 addr) -> uint8 {
tick();
if(((addr & 0x40e000) == 0x006000) || ((addr & 0xd00000) == 0x400000)) tick();
return bus_read(addr, regs.mdr);
}
auto SA1::op_write(uint32 addr, uint8 data) -> void {
auto SA1::op_write(uint24 addr, uint8 data) -> void {
tick();
if(((addr & 0x40e000) == 0x006000) || ((addr & 0xd00000) == 0x400000)) tick();
bus_write(addr, regs.mdr = data);
@ -127,7 +127,7 @@ auto SA1::op_write(uint32 addr, uint8 data) -> void {
//note: addresses are translated prior to invoking this function:
//$00-3f,80-bf:8000-ffff mask=0x408000 => $00-3f:0000-ffff
//$c0-ff:0000-ffff mask=0
auto SA1::mmcrom_read(uint addr, uint8) -> uint8 {
auto SA1::mmcrom_read(uint24 addr, uint8) -> uint8 {
//reset vector overrides
if((addr & 0xffffe0) == 0x007fe0) { //$00:ffe0-ffef
if(addr == 0x7fea && sa1.mmio.cpu_nvsw) return sa1.mmio.snv >> 0;
@ -166,10 +166,10 @@ auto SA1::mmcrom_read(uint addr, uint8) -> uint8 {
return 0x00;
}
auto SA1::mmcrom_write(uint addr, uint8 data) -> void {
auto SA1::mmcrom_write(uint24 addr, uint8 data) -> void {
}
auto SA1::mmcbwram_read(uint addr, uint8 data) -> uint8 {
auto SA1::mmcbwram_read(uint24 addr, uint8 data) -> uint8 {
if(addr < 0x2000) { //$00-3f,80-bf:6000-7fff
cpu.synchronizeCoprocessors();
addr = bus.mirror(mmio.sbm * 0x2000 + (addr & 0x1fff), cpubwram.size());
@ -183,7 +183,7 @@ auto SA1::mmcbwram_read(uint addr, uint8 data) -> uint8 {
return data;
}
auto SA1::mmcbwram_write(uint addr, uint8 data) -> void {
auto SA1::mmcbwram_write(uint24 addr, uint8 data) -> void {
if(addr < 0x2000) { //$00-3f,80-bf:6000-7fff
cpu.synchronizeCoprocessors();
addr = bus.mirror(mmio.sbm * 0x2000 + (addr & 0x1fff), cpubwram.size());

View File

@ -1,16 +1,16 @@
auto bus_read(uint addr, uint8 data) -> uint8;
auto bus_write(uint addr, uint8 data) -> void;
auto vbr_read(uint addr, uint8 data = 0) -> uint8;
auto bus_read(uint24 addr, uint8 data) -> uint8;
auto bus_write(uint24 addr, uint8 data) -> void;
auto vbr_read(uint24 addr, uint8 data = 0) -> uint8;
alwaysinline auto op_io() -> void;
alwaysinline auto op_read(uint32 addr) -> uint8;
alwaysinline auto op_write(uint32 addr, uint8 data) -> void;
alwaysinline auto op_io() -> void override;
alwaysinline auto op_read(uint24 addr) -> uint8 override;
alwaysinline auto op_write(uint24 addr, uint8 data) -> void override;
auto mmcrom_read(uint addr, uint8 data) -> uint8;
auto mmcrom_write(uint addr, uint8 data) -> void;
auto mmcrom_read(uint24 addr, uint8 data) -> uint8;
auto mmcrom_write(uint24 addr, uint8 data) -> void;
auto mmcbwram_read(uint addr, uint8 data) -> uint8;
auto mmcbwram_write(uint addr, uint8 data) -> void;
auto mmcbwram_read(uint24 addr, uint8 data) -> uint8;
auto mmcbwram_write(uint24 addr, uint8 data) -> void;
auto mmc_sa1_read(uint addr, uint8 data) -> uint8;
auto mmc_sa1_write(uint addr, uint8 data) -> void;

View File

@ -445,7 +445,7 @@ auto SA1::mmio_r230e() -> uint8 {
return 0x01; //true value unknown
}
auto SA1::mmio_read(uint addr, uint8) -> uint8 {
auto SA1::mmio_read(uint24 addr, uint8) -> uint8 {
(co_active() == cpu.thread ? cpu.synchronizeCoprocessors() : synchronizeCPU());
addr &= 0xffff;
@ -470,7 +470,7 @@ auto SA1::mmio_read(uint addr, uint8) -> uint8 {
return 0x00;
}
auto SA1::mmio_write(uint addr, uint8 data) -> void {
auto SA1::mmio_write(uint24 addr, uint8 data) -> void {
(co_active() == cpu.thread ? cpu.synchronizeCoprocessors() : synchronizeCPU());
addr &= 0xffff;

View File

@ -1,5 +1,5 @@
auto mmio_read(uint addr, uint8 data) -> uint8;
auto mmio_write(uint addr, uint8 data) -> void;
auto mmio_read(uint24 addr, uint8 data) -> uint8;
auto mmio_write(uint24 addr, uint8 data) -> void;
struct MMIO {
//$2200 CCNT

View File

@ -17,11 +17,11 @@ struct SA1 : Processor::R65816, public Coprocessor {
static auto Enter() -> void;
auto main() -> void;
auto tick() -> void;
auto op_irq() -> void;
auto op_irq() -> void override;
alwaysinline auto trigger_irq() -> void;
alwaysinline auto last_cycle() -> void;
alwaysinline auto interrupt_pending() -> bool;
alwaysinline auto last_cycle() -> void override;
alwaysinline auto interrupt_pending() -> bool override;
auto init() -> void;
auto load() -> void;

View File

@ -41,7 +41,7 @@ auto SDD1::reset() -> void {
}
}
auto SDD1::read(uint addr, uint8 data) -> uint8 {
auto SDD1::read(uint24 addr, uint8 data) -> uint8 {
addr = 0x4800 | (addr & 7);
switch(addr) {
@ -54,7 +54,7 @@ auto SDD1::read(uint addr, uint8 data) -> uint8 {
return data;
}
auto SDD1::write(uint addr, uint8 data) -> void {
auto SDD1::write(uint24 addr, uint8 data) -> void {
addr = 0x4800 | (addr & 7);
switch(addr) {
@ -68,11 +68,11 @@ auto SDD1::write(uint addr, uint8 data) -> void {
}
}
auto SDD1::dma_read(uint addr, uint8 data) -> uint8 {
auto SDD1::dma_read(uint24 addr, uint8 data) -> uint8 {
return cpu.mmio_read(addr, data);
}
auto SDD1::dma_write(uint addr, uint8 data) -> void {
auto SDD1::dma_write(uint24 addr, uint8 data) -> void {
uint channel = (addr >> 4) & 7;
switch(addr & 15) {
case 2: dma[channel].addr = (dma[channel].addr & 0xffff00) + (data << 0); break;
@ -85,7 +85,7 @@ auto SDD1::dma_write(uint addr, uint8 data) -> void {
return cpu.mmio_write(addr, data);
}
auto SDD1::mmc_read(uint addr) -> uint8 {
auto SDD1::mmc_read(uint24 addr) -> uint8 {
return rom.read(mmc[(addr >> 20) & 3] + (addr & 0x0fffff));
}
@ -107,7 +107,7 @@ auto SDD1::mmc_read(uint addr) -> uint8 {
//
//the actual S-DD1 transfer can occur on any channel, but it is most likely limited to
//one transfer per $420b write (for spooling purposes). however, this is not known for certain.
auto SDD1::mcurom_read(uint addr, uint8) -> uint8 {
auto SDD1::mcurom_read(uint24 addr, uint8) -> uint8 {
//map address=00-3f,80-bf:8000-ffff mask=0x808000 => 00-1f:0000-ffff
if(addr < 0x200000) {
return rom.read(addr);
@ -143,16 +143,16 @@ auto SDD1::mcurom_read(uint addr, uint8) -> uint8 {
return mmc_read(addr);
}
auto SDD1::mcurom_write(uint addr, uint8 data) -> void {
auto SDD1::mcurom_write(uint24 addr, uint8 data) -> void {
}
//map address=00-3f,80-bf:6000-7fff mask=0xe000
//map address=70-7d:0000-7fff mask=0x8000
auto SDD1::mcuram_read(uint addr, uint8 data) -> uint8 {
auto SDD1::mcuram_read(uint24 addr, uint8 data) -> uint8 {
return ram.read(addr & 0x1fff, data);
}
auto SDD1::mcuram_write(uint addr, uint8 data) -> void {
auto SDD1::mcuram_write(uint24 addr, uint8 data) -> void {
return ram.write(addr & 0x1fff, data);
}

View File

@ -5,19 +5,19 @@ struct SDD1 {
auto power() -> void;
auto reset() -> void;
auto read(uint addr, uint8 data) -> uint8;
auto write(uint addr, uint8 data) -> void;
auto read(uint24 addr, uint8 data) -> uint8;
auto write(uint24 addr, uint8 data) -> void;
auto dma_read(uint addr, uint8 data) -> uint8;
auto dma_write(uint addr, uint8 data) -> void;
auto dma_read(uint24 addr, uint8 data) -> uint8;
auto dma_write(uint24 addr, uint8 data) -> void;
auto mmc_read(uint addr) -> uint8;
auto mmc_read(uint24 addr) -> uint8;
auto mcurom_read(uint addr, uint8 data) -> uint8;
auto mcurom_write(uint addr, uint8 data) -> void;
auto mcurom_read(uint24 addr, uint8 data) -> uint8;
auto mcurom_write(uint24 addr, uint8 data) -> void;
auto mcuram_read(uint addr, uint8 data) -> uint8;
auto mcuram_write(uint addr, uint8 data) -> void;
auto mcuram_read(uint24 addr, uint8 data) -> uint8;
auto mcuram_write(uint24 addr, uint8 data) -> void;
auto serialize(serializer&) -> void;

View File

@ -59,7 +59,7 @@ auto SharpRTC::sync() -> void {
weekday = timeinfo->tm_wday;
}
auto SharpRTC::read(uint addr, uint8 data) -> uint8 {
auto SharpRTC::read(uint24 addr, uint8 data) -> uint8 {
addr &= 1;
if(addr == 0) {
@ -79,7 +79,7 @@ auto SharpRTC::read(uint addr, uint8 data) -> uint8 {
return data;
}
auto SharpRTC::write(uint addr, uint8 data) -> void {
auto SharpRTC::write(uint24 addr, uint8 data) -> void {
addr &= 1, data &= 15;
if(addr == 1) {

View File

@ -9,8 +9,8 @@ struct SharpRTC : Coprocessor {
auto reset() -> void;
auto sync() -> void;
auto read(uint addr, uint8 data) -> uint8;
auto write(uint addr, uint8 data) -> void;
auto read(uint24 addr, uint8 data) -> uint8;
auto write(uint24 addr, uint8 data) -> void;
auto serialize(serializer&) -> void;

View File

@ -104,7 +104,7 @@ auto SPC7110::reset() -> void {
r4834 = 0x00;
}
auto SPC7110::read(uint addr, uint8 data) -> uint8 {
auto SPC7110::read(uint24 addr, uint8 data) -> uint8 {
cpu.synchronizeCoprocessors();
if((addr & 0xff0000) == 0x500000) addr = 0x4800; //$50:0000-ffff == $4800
if((addr & 0xff0000) == 0x580000) addr = 0x4808; //$58:0000-ffff == $4808
@ -188,7 +188,7 @@ auto SPC7110::read(uint addr, uint8 data) -> uint8 {
return data;
}
auto SPC7110::write(uint addr, uint8 data) -> void {
auto SPC7110::write(uint24 addr, uint8 data) -> void {
cpu.synchronizeCoprocessors();
if((addr & 0xff0000) == 0x500000) addr = 0x4800; //$50:0000-ffff == $4800
if((addr & 0xff0000) == 0x580000) addr = 0x4808; //$58:0000-ffff == $4808
@ -252,7 +252,7 @@ auto SPC7110::write(uint addr, uint8 data) -> void {
//map address=00-3f,80-bf:8000-ffff mask=0x800000 => 00-3f:8000-ffff
//map address=c0-ff:0000-ffff mask=0xc00000 => c0-ff:0000-ffff
auto SPC7110::mcurom_read(uint addr, uint8 data) -> uint8 {
auto SPC7110::mcurom_read(uint24 addr, uint8 data) -> uint8 {
uint mask = (1 << (r4834 & 3)) - 1; //8mbit, 16mbit, 32mbit, 64mbit DROM
if(addr < 0x100000) { //$00-0f,80-8f:8000-ffff; $c0-cf:0000-ffff
@ -288,7 +288,7 @@ auto SPC7110::mcurom_read(uint addr, uint8 data) -> uint8 {
return data;
}
auto SPC7110::mcurom_write(uint addr, uint8 data) -> void {
auto SPC7110::mcurom_write(uint24 addr, uint8 data) -> void {
}
//===============
@ -296,7 +296,7 @@ auto SPC7110::mcurom_write(uint addr, uint8 data) -> void {
//===============
//map address=00-3f,80-bf:6000-7fff mask=0x80e000 => 00-07:0000-ffff
auto SPC7110::mcuram_read(uint addr, uint8) -> uint8 {
auto SPC7110::mcuram_read(uint24 addr, uint8) -> uint8 {
if(r4830 & 0x80) {
addr = bus.mirror(addr, ram.size());
return ram.read(addr);
@ -304,7 +304,7 @@ auto SPC7110::mcuram_read(uint addr, uint8) -> uint8 {
return 0x00;
}
auto SPC7110::mcuram_write(uint addr, uint8 data) -> void {
auto SPC7110::mcuram_write(uint24 addr, uint8 data) -> void {
if(r4830 & 0x80) {
addr = bus.mirror(addr, ram.size());
ram.write(addr, data);

View File

@ -14,14 +14,14 @@ struct SPC7110 : Coprocessor {
auto add_clocks(uint clocks) -> void;
auto read(uint addr, uint8 data) -> uint8;
auto write(uint addr, uint8 data) -> void;
auto read(uint24 addr, uint8 data) -> uint8;
auto write(uint24 addr, uint8 data) -> void;
auto mcurom_read(uint addr, uint8 data) -> uint8;
auto mcurom_write(uint addr, uint8 data) -> void;
auto mcurom_read(uint24 addr, uint8 data) -> uint8;
auto mcurom_write(uint24 addr, uint8 data) -> void;
auto mcuram_read(uint addr, uint8 data) -> uint8;
auto mcuram_write(uint addr, uint8 data) -> void;
auto mcuram_read(uint24 addr, uint8 data) -> uint8;
auto mcuram_write(uint24 addr, uint8 data) -> void;
auto serialize(serializer&) -> void;

View File

@ -4,7 +4,7 @@ auto SuperFX::CPUROM::size() const -> uint {
return superfx.rom.size();
}
auto SuperFX::CPUROM::read(uint addr, uint8 data) -> uint8 {
auto SuperFX::CPUROM::read(uint24 addr, uint8 data) -> uint8 {
if(superfx.regs.sfr.g && superfx.regs.scmr.ron) {
static const uint8 vector[16] = {
0x00, 0x01, 0x00, 0x01, 0x04, 0x01, 0x00, 0x01,
@ -15,7 +15,7 @@ auto SuperFX::CPUROM::read(uint addr, uint8 data) -> uint8 {
return superfx.rom.read(addr, data);
}
auto SuperFX::CPUROM::write(uint addr, uint8 data) -> void {
auto SuperFX::CPUROM::write(uint24 addr, uint8 data) -> void {
superfx.rom.write(addr, data);
}
@ -23,11 +23,11 @@ auto SuperFX::CPURAM::size() const -> uint {
return superfx.ram.size();
}
auto SuperFX::CPURAM::read(uint addr, uint8 data) -> uint8 {
auto SuperFX::CPURAM::read(uint24 addr, uint8 data) -> uint8 {
if(superfx.regs.sfr.g && superfx.regs.scmr.ran) return data;
return superfx.ram.read(addr, data);
}
auto SuperFX::CPURAM::write(uint addr, uint8 data) -> void {
auto SuperFX::CPURAM::write(uint24 addr, uint8 data) -> void {
superfx.ram.write(addr, data);
}

View File

@ -1,11 +1,11 @@
struct CPUROM : Memory {
auto size() const -> uint;
auto read(uint, uint8) -> uint8;
auto write(uint, uint8) -> void;
auto read(uint24, uint8) -> uint8;
auto write(uint24, uint8) -> void;
} cpurom;
struct CPURAM : Memory {
auto size() const -> uint;
auto read(uint, uint8) -> uint8;
auto write(uint, uint8) -> void;
auto read(uint24, uint8) -> uint8;
auto write(uint24, uint8) -> void;
} cpuram;

View File

@ -1,4 +1,4 @@
auto SuperFX::mmio_read(uint addr, uint8) -> uint8 {
auto SuperFX::mmio_read(uint24 addr, uint8) -> uint8 {
cpu.synchronizeCoprocessors();
addr &= 0xffff;
@ -50,7 +50,7 @@ auto SuperFX::mmio_read(uint addr, uint8) -> uint8 {
return 0x00;
}
auto SuperFX::mmio_write(uint addr, uint8 data) -> void {
auto SuperFX::mmio_write(uint24 addr, uint8 data) -> void {
cpu.synchronizeCoprocessors();
addr &= 0xffff;

View File

@ -1,2 +1,2 @@
auto mmio_read(uint addr, uint8 data) -> uint8;
auto mmio_write(uint addr, uint8 data) -> void;
auto mmio_read(uint24 addr, uint8 data) -> uint8;
auto mmio_write(uint24 addr, uint8 data) -> void;

View File

@ -13,7 +13,7 @@ auto CPU::op_io() -> void {
alu_edge();
}
auto CPU::op_read(uint32 addr) -> uint8 {
auto CPU::op_read(uint24 addr) -> uint8 {
status.clock_count = speed(addr);
dma_edge();
add_clocks(status.clock_count - 4);
@ -24,7 +24,7 @@ auto CPU::op_read(uint32 addr) -> uint8 {
return regs.mdr;
}
auto CPU::op_write(uint32 addr, uint8 data) -> void {
auto CPU::op_write(uint24 addr, uint8 data) -> void {
alu_edge();
status.clock_count = speed(addr);
dma_edge();
@ -33,7 +33,7 @@ auto CPU::op_write(uint32 addr, uint8 data) -> void {
debugger.op_write(addr, regs.mdr);
}
auto CPU::speed(uint addr) const -> uint {
auto CPU::speed(uint24 addr) const -> uint {
if(addr & 0x408000) {
if(addr & 0x800000) return status.rom_speed;
return 8;
@ -43,6 +43,6 @@ auto CPU::speed(uint addr) const -> uint {
return 12;
}
auto CPU::disassembler_read(uint32 addr) -> uint8 {
auto CPU::disassembler_read(uint24 addr) -> uint8 {
return bus.read(addr, regs.mdr);
}

View File

@ -1,6 +1,6 @@
auto op_io() -> void;
auto op_read(uint32 addr) -> uint8;
auto op_write(uint32 addr, uint8 data) -> void;
alwaysinline auto speed(uint addr) const -> uint;
auto op_io() -> void override;
auto op_read(uint24 addr) -> uint8 override;
auto op_write(uint24 addr, uint8 data) -> void override;
alwaysinline auto speed(uint24 addr) const -> uint;
auto disassembler_read(uint32 addr) -> uint8;
auto disassembler_read(uint24 addr) -> uint8 override;

View File

@ -8,8 +8,8 @@ auto eBoot::init() -> void {
}
auto eBoot::load() -> void {
resetVector = bus.read(0xfffc, 0x00) << 0;
resetVector |= bus.read(0xfffd, 0x00) << 8;
resetVector.byte(0) = bus.read(0xfffc, 0x00);
resetVector.byte(1) = bus.read(0xfffd, 0x00);
for(auto& byte : ram) byte = 0xdb; //stp
ram[0] = 0x6c; //jmp ($fffc)
@ -35,15 +35,15 @@ auto eBoot::reset() -> void {
booted = false;
}
auto eBoot::read(uint addr, uint8 data) -> uint8 {
auto eBoot::read(uint24 addr, uint8 data) -> uint8 {
addr &= 0x40ffff;
if(addr == 0xfffc) return booted ? resetVector >> 0 : 0x84;
if(addr == 0xfffd) return booted ? resetVector >> 8 : (booted = true, 0x21);
if(addr == 0xfffc) return booted ? resetVector.byte(0) : (uint8)0x84;
if(addr == 0xfffd) return booted ? resetVector.byte(1) : (booted = true, (uint8)0x21);
if(addr >= 0x2184 && addr <= 0x21ff) return ram[addr - 0x2184];
return data;
}
auto eBoot::write(uint addr, uint8 data) -> void {
auto eBoot::write(uint24 addr, uint8 data) -> void {
}
}

View File

@ -5,13 +5,13 @@ struct eBoot : Memory {
auto power() -> void;
auto reset() -> void;
auto read(uint addr, uint8 data) -> uint8;
auto write(uint addr, uint8 data) -> void;
auto read(uint24 addr, uint8 data) -> uint8;
auto write(uint24 addr, uint8 data) -> void;
private:
bool booted = false;
uint16 resetVector = 0;
uint8 ram[124] = {0};
uint16 resetVector;
uint8 ram[124];
};
extern eBoot eboot;

View File

@ -22,7 +22,7 @@ auto Satellaview::reset() -> void {
memory::fill(&regs, sizeof regs);
}
auto Satellaview::read(uint addr, uint8 data) -> uint8 {
auto Satellaview::read(uint24 addr, uint8 data) -> uint8 {
addr &= 0xffff;
switch(addr) {
@ -80,7 +80,7 @@ auto Satellaview::read(uint addr, uint8 data) -> uint8 {
return data;
}
auto Satellaview::write(uint addr, uint8 data) -> void {
auto Satellaview::write(uint24 addr, uint8 data) -> void {
addr &= 0xffff;
switch(addr) {

View File

@ -5,8 +5,8 @@ struct Satellaview : Memory {
auto power() -> void;
auto reset() -> void;
auto read(uint addr, uint8 data) -> uint8;
auto write(uint addr, uint8 data) -> void;
auto read(uint24 addr, uint8 data) -> uint8;
auto write(uint24 addr, uint8 data) -> void;
private:
struct {

View File

@ -10,10 +10,10 @@ StaticRAM::~StaticRAM() { delete[] data_; }
auto StaticRAM::data() -> uint8* { return data_; }
auto StaticRAM::size() const -> uint { return size_; }
auto StaticRAM::read(uint addr, uint8) -> uint8 { return data_[addr]; }
auto StaticRAM::write(uint addr, uint8 data) -> void { data_[addr] = data; }
auto StaticRAM::operator[](uint addr) -> uint8& { return data_[addr]; }
auto StaticRAM::operator[](uint addr) const -> const uint8& { return data_[addr]; }
auto StaticRAM::read(uint24 addr, uint8) -> uint8 { return data_[addr]; }
auto StaticRAM::write(uint24 addr, uint8 data) -> void { data_[addr] = data; }
auto StaticRAM::operator[](uint24 addr) -> uint8& { return data_[addr]; }
auto StaticRAM::operator[](uint24 addr) const -> const uint8& { return data_[addr]; }
//MappedRAM
@ -48,9 +48,9 @@ auto MappedRAM::write_protect(bool status) -> void { write_protect_ = status; }
auto MappedRAM::data() -> uint8* { return data_; }
auto MappedRAM::size() const -> uint { return size_; }
auto MappedRAM::read(uint addr, uint8) -> uint8 { return data_[addr]; }
auto MappedRAM::write(uint addr, uint8 data) -> void { if(!write_protect_) data_[addr] = data; }
auto MappedRAM::operator[](uint addr) const -> const uint8& { return data_[addr]; }
auto MappedRAM::read(uint24 addr, uint8) -> uint8 { return data_[addr]; }
auto MappedRAM::write(uint24 addr, uint8 data) -> void { if(!write_protect_) data_[addr] = data; }
auto MappedRAM::operator[](uint24 addr) const -> const uint8& { return data_[addr]; }
//Bus
@ -79,16 +79,14 @@ auto Bus::reduce(uint addr, uint mask) -> uint {
return addr;
}
auto Bus::read(uint addr, uint8 data) -> uint8 {
auto Bus::read(uint24 addr, uint8 data) -> uint8 {
data = reader[lookup[addr]](target[addr], data);
if(cheat.enable()) {
if(auto result = cheat.find(addr, data)) return result();
}
return data;
}
auto Bus::write(uint addr, uint8 data) -> void {
auto Bus::write(uint24 addr, uint8 data) -> void {
return writer[lookup[addr]](target[addr], data);
}

View File

@ -15,8 +15,8 @@ Bus::~Bus() {
}
auto Bus::reset() -> void {
function<auto (uint, uint8) -> uint8> reader = [](uint, uint8 data) { return data; };
function<auto (uint, uint8) -> void> writer = [](uint, uint8) {};
function<auto (uint24, uint8) -> uint8> reader = [](uint24, uint8 data) { return data; };
function<auto (uint24, uint8) -> void> writer = [](uint24, uint8) {};
idcount = 0;
map(reader, writer, 0x00, 0xff, 0x0000, 0xffff);
@ -42,13 +42,13 @@ auto Bus::map() -> void {
}
auto Bus::map(
const function<uint8 (uint, uint8)>& reader,
const function<void (uint, uint8)>& writer,
uint banklo, uint bankhi, uint addrlo, uint addrhi,
const function<uint8 (uint24, uint8)>& reader,
const function<void (uint24, uint8)>& writer,
uint8 banklo, uint8 bankhi, uint16 addrlo, uint16 addrhi,
uint size, uint base, uint mask
) -> void {
assert(banklo <= bankhi && bankhi <= 0xff);
assert(addrlo <= addrhi && addrhi <= 0xffff);
assert(banklo <= bankhi);
assert(addrlo <= addrhi);
assert(idcount < 255);
uint id = idcount++;

View File

@ -1,7 +1,7 @@
struct Memory {
virtual inline auto size() const -> uint;
virtual auto read(uint addr, uint8 data = 0) -> uint8 = 0;
virtual auto write(uint addr, uint8 data) -> void = 0;
virtual auto read(uint24 addr, uint8 data = 0) -> uint8 = 0;
virtual auto write(uint24 addr, uint8 data) -> void = 0;
};
struct StaticRAM : Memory {
@ -11,10 +11,10 @@ struct StaticRAM : Memory {
inline auto data() -> uint8*;
inline auto size() const -> uint;
inline auto read(uint addr, uint8 data = 0) -> uint8;
inline auto write(uint addr, uint8 data) -> void;
inline auto operator[](uint addr) -> uint8&;
inline auto operator[](uint addr) const -> const uint8&;
inline auto read(uint24 addr, uint8 data = 0) -> uint8;
inline auto write(uint24 addr, uint8 data) -> void;
inline auto operator[](uint24 addr) -> uint8&;
inline auto operator[](uint24 addr) const -> const uint8&;
private:
uint8* data_ = nullptr;
@ -31,9 +31,9 @@ struct MappedRAM : Memory {
inline auto data() -> uint8*;
inline auto size() const -> uint;
inline auto read(uint addr, uint8 data = 0) -> uint8;
inline auto write(uint addr, uint8 data) -> void;
inline auto operator[](uint addr) const -> const uint8&;
inline auto read(uint24 addr, uint8 data = 0) -> uint8;
inline auto write(uint24 addr, uint8 data) -> void;
inline auto operator[](uint24 addr) const -> const uint8&;
private:
uint8* data_ = nullptr;
@ -48,15 +48,15 @@ struct Bus {
Bus();
~Bus();
alwaysinline auto read(uint addr, uint8 data) -> uint8;
alwaysinline auto write(uint addr, uint8 data) -> void;
alwaysinline auto read(uint24 addr, uint8 data) -> uint8;
alwaysinline auto write(uint24 addr, uint8 data) -> void;
auto reset() -> void;
auto map() -> void;
auto map(
const function<uint8 (uint, uint8)>& reader,
const function<void (uint, uint8)>& writer,
uint banklo, uint bankhi, uint addrlo, uint addrhi,
const function<uint8 (uint24, uint8)>& reader,
const function<void (uint24, uint8)>& writer,
uint8 banklo, uint8 bankhi, uint16 addrlo, uint16 addrhi,
uint size = 0, uint base = 0, uint mask = 0
) -> void;
@ -64,8 +64,8 @@ struct Bus {
uint32* target = nullptr;
uint idcount = 0;
function<auto (uint, uint8) -> uint8> reader[256];
function<auto (uint, uint8) -> void> writer[256];
function<auto (uint24, uint8) -> uint8> reader[256];
function<auto (uint24, uint8) -> void> writer[256];
};
extern Bus bus;

View File

@ -35,7 +35,7 @@ auto BSMemory::size() const -> uint {
return memory.size();
}
auto BSMemory::read(uint addr, uint8 data) -> uint8 {
auto BSMemory::read(uint24 addr, uint8 data) -> uint8 {
if(readonly) {
return memory.read(bus.mirror(addr, memory.size()), data);
}
@ -66,7 +66,7 @@ auto BSMemory::read(uint addr, uint8 data) -> uint8 {
return memory.read(addr, data);
}
auto BSMemory::write(uint addr, uint8 data) -> void {
auto BSMemory::write(uint24 addr, uint8 data) -> void {
if(readonly) {
return;
}

View File

@ -6,8 +6,8 @@ struct BSMemory : Memory {
auto reset() -> void;
auto size() const -> uint;
auto read(uint addr, uint8) -> uint8;
auto write(uint addr, uint8 data) -> void;
auto read(uint24 addr, uint8) -> uint8;
auto write(uint24 addr, uint8 data) -> void;
MappedRAM memory;
bool readonly;

View File

@ -1,6 +1,6 @@
auto CPU::dmaTransfer() -> void {
//length of 0 or SRAM source address cause immediate termination
if(r.dmaLength == 0 || r.dmaSource.b2 == 1) {
if(r.dmaLength == 0 || r.dmaSource.byte(2) == 1) {
r.dmaEnable = false;
return;
}
@ -10,7 +10,7 @@ auto CPU::dmaTransfer() -> void {
wait(2);
uint16 data = 0;
//once DMA is started; SRAM reads still incur time penalty, but do not transfer
if(r.dmaSource.b2 != 1) {
if(r.dmaSource.byte(2) != 1) {
data |= read(r.dmaSource + 0) << 0;
data |= read(r.dmaSource + 1) << 8;
write(r.dmaTarget + 0, data >> 0);

View File

@ -14,6 +14,7 @@ struct Boolean {
inline auto serialize(serializer& s) { s(data); }
private:
bool data;
};
@ -28,32 +29,32 @@ template<uint Bits> struct Natural {
enum : type { Mask = ~0ull >> (64 - Bits) };
inline Natural() : data(0) {}
template<typename T> inline Natural(const T& value) : data(clip(value)) {}
template<typename T> inline Natural(const T& value) { assign(value); }
inline operator type() const { return data; }
template<typename T> inline auto& operator=(const T& value) { data = clip(value); return *this; }
template<typename T> inline auto& operator=(const T& value) { assign(value); return *this; }
inline auto operator++(int) { type value = data; data = clip(data + 1); return value; }
inline auto operator--(int) { type value = data; data = clip(data - 1); return value; }
inline auto operator++(int) { type value = data; assign(data + 1); return value; }
inline auto operator--(int) { type value = data; assign(data - 1); return value; }
inline auto& operator++() { data = clip(data + 1); return *this; }
inline auto& operator--() { data = clip(data - 1); return *this; }
inline auto& operator++() { assign(data + 1); return *this; }
inline auto& operator--() { assign(data - 1); return *this; }
inline auto& operator &=(const type value) { data = clip(data & value); return *this; }
inline auto& operator |=(const type value) { data = clip(data | value); return *this; }
inline auto& operator ^=(const type value) { data = clip(data ^ value); return *this; }
inline auto& operator<<=(const type value) { data = clip(data << value); return *this; }
inline auto& operator>>=(const type value) { data = clip(data >> value); return *this; }
inline auto& operator +=(const type value) { data = clip(data + value); return *this; }
inline auto& operator -=(const type value) { data = clip(data - value); return *this; }
inline auto& operator *=(const type value) { data = clip(data * value); return *this; }
inline auto& operator /=(const type value) { data = clip(data / value); return *this; }
inline auto& operator %=(const type value) { data = clip(data % value); return *this; }
inline auto& operator &=(const type value) { assign(data & value); return *this; }
inline auto& operator |=(const type value) { assign(data | value); return *this; }
inline auto& operator ^=(const type value) { assign(data ^ value); return *this; }
inline auto& operator<<=(const type value) { assign(data << value); return *this; }
inline auto& operator>>=(const type value) { assign(data >> value); return *this; }
inline auto& operator +=(const type value) { assign(data + value); return *this; }
inline auto& operator -=(const type value) { assign(data - value); return *this; }
inline auto& operator *=(const type value) { assign(data * value); return *this; }
inline auto& operator /=(const type value) { assign(data / value); return *this; }
inline auto& operator %=(const type value) { assign(data % value); return *this; }
inline auto serialize(serializer& s) { s(data); }
struct Reference {
inline Reference(Natural& source, uint Lo, uint Hi) : source(source), Lo(Lo), Hi(Hi) {}
inline Reference(Natural& source, uint lo, uint hi) : source(source), Lo(lo), Hi(hi) {}
inline operator type() const {
const type RangeBits = Hi - Lo + 1;
@ -70,55 +71,32 @@ template<uint Bits> struct Natural {
private:
Natural& source;
const uint Lo;
const uint Hi;
const type Lo;
const type Hi;
};
inline auto bits(uint lo, uint hi) -> Reference { return {*this, lo, hi}; }
inline auto bits(uint lo, uint hi) -> Reference { return {*this, lo < hi ? lo : hi, hi > lo ? hi : lo}; }
inline auto bit(uint index) -> Reference { return {*this, index, index}; }
inline auto byte(uint index) -> Reference { return {*this, index * 8 + 0, index * 8 + 7}; }
template<uint Lo, uint Hi> struct Range {
enum : type { RangeBits = Hi - Lo + 1, RangeMask = (((1ull << RangeBits) - 1) << Lo) & Mask };
inline auto clamp(uint bits) -> uintmax {
const uintmax b = 1ull << (bits - 1);
const uintmax m = b * 2 - 1;
return data < m ? data : m;
}
inline operator type() const {
return (self() & RangeMask) >> Lo;
}
inline auto& operator=(const type value) {
self() = (self() & ~RangeMask) | ((value << Lo) & RangeMask);
return *this;
}
private:
inline auto self() const -> type& { return *(type*)this; }
};
union {
type data;
Range< 0, 7> b0;
Range< 8, 15> b1;
Range<16, 23> b2;
Range<24, 31> b3;
Range<32, 39> b4;
Range<40, 47> b5;
Range<48, 55> b6;
Range<56, 63> b7;
Range< 0, 15> h0;
Range<16, 31> h1;
Range<32, 47> h2;
Range<48, 63> h3;
Range< 0, 31> w0;
Range<32, 63> w1;
};
inline auto clip(uint bits) -> uintmax {
const uintmax b = 1ull << (bits - 1);
const uintmax m = b * 2 - 1;
return data & m;
}
private:
auto clip(type value) const -> type {
return value & Mask;
auto assign(type value) -> void {
data = value & Mask;
}
type data;
};
template<uint Bits> struct Integer {
@ -133,32 +111,32 @@ template<uint Bits> struct Integer {
enum : utype { Mask = ~0ull >> (64 - Bits), Sign = 1ull << (Bits - 1) };
inline Integer() : data(0) {}
template<typename T> inline Integer(const T& value) : data(clip(value)) {}
template<typename T> inline Integer(const T& value) { assign(value); }
inline operator type() const { return data; }
template<typename T> inline auto& operator=(const T& value) { data = clip(value); return *this; }
template<typename T> inline auto& operator=(const T& value) { assign(value); return *this; }
inline auto operator++(int) { type value = data; data = clip(data + 1); return value; }
inline auto operator--(int) { type value = data; data = clip(data - 1); return value; }
inline auto operator++(int) { type value = data; assign(data + 1); return value; }
inline auto operator--(int) { type value = data; assign(data - 1); return value; }
inline auto& operator++() { data = clip(data + 1); return *this; }
inline auto& operator--() { data = clip(data - 1); return *this; }
inline auto& operator++() { assign(data + 1); return *this; }
inline auto& operator--() { assign(data - 1); return *this; }
inline auto& operator &=(const type value) { data = clip(data & value); return *this; }
inline auto& operator |=(const type value) { data = clip(data | value); return *this; }
inline auto& operator ^=(const type value) { data = clip(data ^ value); return *this; }
inline auto& operator<<=(const type value) { data = clip(data << value); return *this; }
inline auto& operator>>=(const type value) { data = clip(data >> value); return *this; }
inline auto& operator +=(const type value) { data = clip(data + value); return *this; }
inline auto& operator -=(const type value) { data = clip(data - value); return *this; }
inline auto& operator *=(const type value) { data = clip(data * value); return *this; }
inline auto& operator /=(const type value) { data = clip(data / value); return *this; }
inline auto& operator %=(const type value) { data = clip(data % value); return *this; }
inline auto& operator &=(const type value) { assign(data & value); return *this; }
inline auto& operator |=(const type value) { assign(data | value); return *this; }
inline auto& operator ^=(const type value) { assign(data ^ value); return *this; }
inline auto& operator<<=(const type value) { assign(data << value); return *this; }
inline auto& operator>>=(const type value) { assign(data >> value); return *this; }
inline auto& operator +=(const type value) { assign(data + value); return *this; }
inline auto& operator -=(const type value) { assign(data - value); return *this; }
inline auto& operator *=(const type value) { assign(data * value); return *this; }
inline auto& operator /=(const type value) { assign(data / value); return *this; }
inline auto& operator %=(const type value) { assign(data % value); return *this; }
inline auto serialize(serializer& s) { s(data); }
struct Reference {
inline Reference(Integer& source, uint Lo, uint Hi) : source(source), Lo(Lo), Hi(Hi) {}
inline Reference(Integer& source, uint lo, uint hi) : source(source), Lo(lo), Hi(hi) {}
inline operator utype() const {
const type RangeBits = Hi - Lo + 1;
@ -175,55 +153,32 @@ template<uint Bits> struct Integer {
private:
Integer& source;
uint Lo;
uint Hi;
const uint Lo;
const uint Hi;
};
inline auto bits(uint lo, uint hi) -> Reference { return {*this, lo, hi}; }
inline auto bit(uint index) -> Reference { return {*this, index, index}; }
inline auto byte(uint index) -> Reference { return {*this, index * 8 + 0, index * 8 + 7}; }
template<uint Lo, uint Hi> struct Range {
enum : utype { RangeBits = Hi - Lo + 1, RangeMask = (((1ull << RangeBits) - 1) << Lo) & Mask };
inline auto clamp(uint bits) -> intmax {
const intmax b = 1ull << (bits - 1);
const intmax m = b - 1;
return data > m ? m : data < -b ? -b : data;
}
inline operator utype() const {
return ((utype)self() & RangeMask) >> Lo;
}
inline auto& operator=(const utype value) {
self() = ((((utype)self() & ~RangeMask) | ((value << Lo) & RangeMask)) ^ Sign) - Sign;
return *this;
}
private:
inline auto self() const -> utype& { return *(utype*)this; }
};
union {
type data;
Range< 0, 7> b0;
Range< 8, 15> b1;
Range<16, 23> b2;
Range<24, 31> b3;
Range<32, 39> b4;
Range<40, 47> b5;
Range<48, 55> b6;
Range<56, 63> b7;
Range< 0, 15> h0;
Range<16, 31> h1;
Range<32, 47> h2;
Range<48, 63> h3;
Range< 0, 31> w0;
Range<32, 63> w1;
};
inline auto clip(uint bits) -> intmax {
const uintmax b = 1ull << (bits - 1);
const uintmax m = b * 2 - 1;
return ((data & m) ^ b) - b;
}
private:
auto clip(type value) const -> type {
return ((value & Mask) ^ Sign) - Sign;
auto assign(type value) -> void {
data = ((value & Mask) ^ Sign) - Sign;
}
type data;
};
template<uint Bits> struct Real {

View File

@ -79,6 +79,8 @@ private:
}
using boolean = nall::Boolean;
using int1 = nall::Integer< 1>;
using int2 = nall::Integer< 2>;
using int3 = nall::Integer< 3>;