convert over to using re::delegate for dynamic memory handlers

This commit is contained in:
Anthony Pesch 2016-02-14 13:03:21 -08:00
parent bf7999d0ae
commit b6731d3df6
20 changed files with 405 additions and 347 deletions

102
src/core/delegate.h Normal file
View File

@ -0,0 +1,102 @@
#ifndef DELEGATE_H
#define DELEGATE_H
#include <stdint.h>
#include <type_traits>
namespace re {
template <typename F>
class delegate;
template <typename R, typename... A>
class delegate<R(A...)> {
typedef R (*thunk_type)(void *, A...);
template <typename T>
struct const_member_data {
T *callee;
R (T::*func)(A...) const;
};
template <typename T>
struct member_data {
T *callee;
R (T::*func)(A...);
};
typedef R (*func_data)(A...);
public:
delegate() : thunk_(nullptr), data_() {}
template <typename T>
delegate(T *callee, R (T::*func)(A...) const) {
static_assert(sizeof(const_member_data<T>) < sizeof(data_),
"data not large enough to hold member function pointer");
thunk_ = reinterpret_cast<thunk_type>(&const_member_thunk<T>);
*reinterpret_cast<const_member_data<T> *>(data_) = {callee, func};
}
template <typename T>
delegate(T *callee, R (T::*func)(A...)) {
static_assert(sizeof(member_data<T>) < sizeof(data_),
"data not large enough to hold member function pointer");
thunk_ = reinterpret_cast<thunk_type>(&member_thunk<T>);
*reinterpret_cast<member_data<T> *>(data_) = {callee, func};
}
delegate(R (*func)(A...)) {
thunk_ = reinterpret_cast<thunk_type>(&func_thunk);
*reinterpret_cast<func_data *>(data_) = func;
}
bool operator==(const delegate &rhs) const noexcept {
return (thunk_ == rhs.thunk_) && !memcmp(data_, rhs.data_, sizeof(data_));
}
bool operator!=(const delegate &rhs) const noexcept {
return !operator==(rhs);
}
R operator()(A... args) { return thunk_(data_, args...); }
private:
template <typename T>
static R const_member_thunk(const_member_data<T> *data, A... args) {
return (data->callee->*data->func)(args...);
}
template <typename T>
static R member_thunk(member_data<T> *data, A... args) {
return (data->callee->*data->func)(args...);
}
static R func_thunk(func_data *data, A... args) { return (*data)(args...); }
thunk_type thunk_;
uint8_t data_[32];
};
template <typename T, typename R, typename... A>
delegate<R(A...)> make_delegate(R (T::*func)(A...) const, T *callee) {
return delegate<R(A...)>(callee, func);
}
template <typename T, typename R, typename... A>
delegate<R(A...)> make_delegate(R (T::*func)(A...), T *callee) {
return delegate<R(A...)>(callee, func);
}
template <typename R, typename... A>
delegate<R(A...)> make_delegate(R (*func)(A...)) {
return delegate<R(A...)>(func);
}
}
#endif

View File

@ -40,13 +40,11 @@ bool AICA::Init() {
// re::store(&self->aica_regs_[addr], value);
// }
template uint8_t AICA::ReadWave(void *ctx, uint32_t addr);
template uint16_t AICA::ReadWave(void *ctx, uint32_t addr);
template uint32_t AICA::ReadWave(void *ctx, uint32_t addr);
template uint8_t AICA::ReadWave(uint32_t addr);
template uint16_t AICA::ReadWave(uint32_t addr);
template uint32_t AICA::ReadWave(uint32_t addr);
template <typename T>
T AICA::ReadWave(void *ctx, uint32_t addr) {
AICA *self = reinterpret_cast<AICA *>(ctx);
T AICA::ReadWave(uint32_t addr) {
if (sizeof(T) == 4) {
// FIXME temp hacks to get Crazy Taxi 1 booting
if (addr == 0x104 || addr == 0x284 || addr == 0x288) {
@ -58,14 +56,13 @@ T AICA::ReadWave(void *ctx, uint32_t addr) {
}
}
return re::load<T>(&self->wave_ram_[addr]);
return re::load<T>(&wave_ram_[addr]);
}
template void AICA::WriteWave(void *ctx, uint32_t addr, uint8_t value);
template void AICA::WriteWave(void *ctx, uint32_t addr, uint16_t value);
template void AICA::WriteWave(void *ctx, uint32_t addr, uint32_t value);
template void AICA::WriteWave(uint32_t addr, uint8_t value);
template void AICA::WriteWave(uint32_t addr, uint16_t value);
template void AICA::WriteWave(uint32_t addr, uint32_t value);
template <typename T>
void AICA::WriteWave(void *ctx, uint32_t addr, T value) {
AICA *self = reinterpret_cast<AICA *>(ctx);
re::store(&self->wave_ram_[addr], value);
void AICA::WriteWave(uint32_t addr, T value) {
re::store(&wave_ram_[addr], value);
}

View File

@ -11,7 +11,7 @@ namespace aica {
class AICA {
public:
AICA(hw::Dreamcast *dc);
AICA(Dreamcast *dc);
bool Init();
@ -19,13 +19,13 @@ class AICA {
// static void WriteRegister(void *ctx, uint32_t addr, uint32_t value);
template <typename T>
static T ReadWave(void *ctx, uint32_t addr);
T ReadWave(uint32_t addr);
template <typename T>
static void WriteWave(void *ctx, uint32_t addr, T value);
void WriteWave(uint32_t addr, T value);
private:
hw::Dreamcast *dc_;
Dreamcast *dc_;
// uint8_t *aica_regs_;
uint8_t *wave_ram_;
};

View File

@ -47,24 +47,24 @@ static bool MapMemory(Dreamcast &dc) {
// second, allocate dynamic regions that overlap static regions
RegionHandle holly_handle = memory->AllocRegion(
HOLLY_REG_START, HOLLY_REG_SIZE, dc.holly,
&Holly::ReadRegister<uint8_t>,
&Holly::ReadRegister<uint16_t>,
&Holly::ReadRegister<uint32_t>,
HOLLY_REG_START, HOLLY_REG_SIZE,
make_delegate(&Holly::ReadRegister<uint8_t>, dc.holly),
make_delegate(&Holly::ReadRegister<uint16_t>, dc.holly),
make_delegate(&Holly::ReadRegister<uint32_t>, dc.holly),
nullptr,
&Holly::WriteRegister<uint8_t>,
&Holly::WriteRegister<uint16_t>,
&Holly::WriteRegister<uint32_t>,
make_delegate(&Holly::WriteRegister<uint8_t>, dc.holly),
make_delegate(&Holly::WriteRegister<uint16_t>, dc.holly),
make_delegate(&Holly::WriteRegister<uint32_t>, dc.holly),
nullptr);
RegionHandle pvr_reg_handle = memory->AllocRegion(
PVR_REG_START, PVR_REG_SIZE, dc.pvr,
PVR_REG_START, PVR_REG_SIZE,
nullptr,
nullptr,
&PVR2::ReadRegister,
make_delegate(&PVR2::ReadRegister, dc.pvr),
nullptr,
nullptr,
nullptr,
&PVR2::WriteRegister,
make_delegate(&PVR2::WriteRegister, dc.pvr),
nullptr);
// RegionHandle aica_reg_handle = memory->AllocRegion(
// AICA_REG_START, AICA_REG_SIZE, aica(),
@ -77,74 +77,74 @@ static bool MapMemory(Dreamcast &dc) {
// &AICA::WriteRegister,
// nullptr);
RegionHandle wave_ram_handle = memory->AllocRegion(
WAVE_RAM_START, WAVE_RAM_SIZE, dc.aica,
&AICA::ReadWave<uint8_t>,
&AICA::ReadWave<uint16_t>,
&AICA::ReadWave<uint32_t>,
WAVE_RAM_START, WAVE_RAM_SIZE,
make_delegate(&AICA::ReadWave<uint8_t>, dc.aica),
make_delegate(&AICA::ReadWave<uint16_t>, dc.aica),
make_delegate(&AICA::ReadWave<uint32_t>, dc.aica),
nullptr,
&AICA::WriteWave<uint8_t>,
&AICA::WriteWave<uint16_t>,
&AICA::WriteWave<uint32_t>,
make_delegate(&AICA::WriteWave<uint8_t>, dc.aica),
make_delegate(&AICA::WriteWave<uint16_t>, dc.aica),
make_delegate(&AICA::WriteWave<uint32_t>, dc.aica),
nullptr);
RegionHandle pvr_vram64_handle = memory->AllocRegion(
PVR_VRAM64_START, PVR_VRAM64_SIZE, dc.pvr,
&PVR2::ReadVRamInterleaved<uint8_t>,
&PVR2::ReadVRamInterleaved<uint16_t>,
&PVR2::ReadVRamInterleaved<uint32_t>,
PVR_VRAM64_START, PVR_VRAM64_SIZE,
make_delegate(&PVR2::ReadVRamInterleaved<uint8_t>, dc.pvr),
make_delegate(&PVR2::ReadVRamInterleaved<uint16_t>, dc.pvr),
make_delegate(&PVR2::ReadVRamInterleaved<uint32_t>, dc.pvr),
nullptr,
nullptr,
&PVR2::WriteVRamInterleaved<uint16_t>,
&PVR2::WriteVRamInterleaved<uint32_t>,
make_delegate(&PVR2::WriteVRamInterleaved<uint16_t>, dc.pvr),
make_delegate(&PVR2::WriteVRamInterleaved<uint32_t>, dc.pvr),
nullptr);
RegionHandle ta_cmd_handle = memory->AllocRegion(
TA_CMD_START, TA_CMD_SIZE, dc.ta,
TA_CMD_START, TA_CMD_SIZE,
nullptr,
nullptr,
nullptr,
nullptr,
nullptr,
nullptr,
&TileAccelerator::WriteCommand,
make_delegate(&TileAccelerator::WriteCommand, dc.ta),
nullptr);
RegionHandle ta_texture_handle = memory->AllocRegion(
TA_TEXTURE_START, TA_TEXTURE_SIZE, dc.ta,
TA_TEXTURE_START, TA_TEXTURE_SIZE,
nullptr,
nullptr,
nullptr,
nullptr,
nullptr,
nullptr,
&TileAccelerator::WriteTexture,
make_delegate(&TileAccelerator::WriteTexture, dc.ta),
nullptr);
RegionHandle sh4_reg_handle = memory->AllocRegion(
SH4_REG_START, SH4_REG_SIZE, dc.sh4,
&SH4::ReadRegister<uint8_t>,
&SH4::ReadRegister<uint16_t>,
&SH4::ReadRegister<uint32_t>,
SH4_REG_START, SH4_REG_SIZE,
make_delegate(&SH4::ReadRegister<uint8_t>, dc.sh4),
make_delegate(&SH4::ReadRegister<uint16_t>, dc.sh4),
make_delegate(&SH4::ReadRegister<uint32_t>, dc.sh4),
nullptr,
&SH4::WriteRegister<uint8_t>,
&SH4::WriteRegister<uint16_t>,
&SH4::WriteRegister<uint32_t>,
make_delegate(&SH4::WriteRegister<uint8_t>, dc.sh4),
make_delegate(&SH4::WriteRegister<uint16_t>, dc.sh4),
make_delegate(&SH4::WriteRegister<uint32_t>, dc.sh4),
nullptr);
RegionHandle sh4_cache_handle = memory->AllocRegion(
SH4_CACHE_START, SH4_CACHE_SIZE, dc.sh4,
&SH4::ReadCache<uint8_t>,
&SH4::ReadCache<uint16_t>,
&SH4::ReadCache<uint32_t>,
&SH4::ReadCache<uint64_t>,
&SH4::WriteCache<uint8_t>,
&SH4::WriteCache<uint16_t>,
&SH4::WriteCache<uint32_t>,
&SH4::WriteCache<uint64_t>);
SH4_CACHE_START, SH4_CACHE_SIZE,
make_delegate(&SH4::ReadCache<uint8_t>, dc.sh4),
make_delegate(&SH4::ReadCache<uint16_t>, dc.sh4),
make_delegate(&SH4::ReadCache<uint32_t>, dc.sh4),
make_delegate(&SH4::ReadCache<uint64_t>, dc.sh4),
make_delegate(&SH4::WriteCache<uint8_t>, dc.sh4),
make_delegate(&SH4::WriteCache<uint16_t>, dc.sh4),
make_delegate(&SH4::WriteCache<uint32_t>, dc.sh4),
make_delegate(&SH4::WriteCache<uint64_t>, dc.sh4));
RegionHandle sh4_sq_handle = memory->AllocRegion(
SH4_SQ_START, SH4_SQ_SIZE, dc.sh4,
&SH4::ReadSQ<uint8_t>,
&SH4::ReadSQ<uint16_t>,
&SH4::ReadSQ<uint32_t>,
SH4_SQ_START, SH4_SQ_SIZE,
make_delegate(&SH4::ReadSQ<uint8_t>, dc.sh4),
make_delegate(&SH4::ReadSQ<uint16_t>, dc.sh4),
make_delegate(&SH4::ReadSQ<uint32_t>, dc.sh4),
nullptr,
&SH4::WriteSQ<uint8_t>,
&SH4::WriteSQ<uint16_t>,
&SH4::WriteSQ<uint32_t>,
make_delegate(&SH4::WriteSQ<uint8_t>, dc.sh4),
make_delegate(&SH4::WriteSQ<uint16_t>, dc.sh4),
make_delegate(&SH4::WriteSQ<uint32_t>, dc.sh4),
nullptr);
// setup memory mapping for the allocated regions

View File

@ -50,15 +50,13 @@ void GDROM::SetDisc(std::unique_ptr<Disc> disc) {
status_.BSY = 0;
}
template uint8_t GDROM::ReadRegister(void *ctx, uint32_t addr);
template uint16_t GDROM::ReadRegister(void *ctx, uint32_t addr);
template uint32_t GDROM::ReadRegister(void *ctx, uint32_t addr);
template uint8_t GDROM::ReadRegister(uint32_t addr);
template uint16_t GDROM::ReadRegister(uint32_t addr);
template uint32_t GDROM::ReadRegister(uint32_t addr);
template <typename T>
T GDROM::ReadRegister(void *ctx, uint32_t addr) {
GDROM *self = reinterpret_cast<GDROM *>(ctx);
T GDROM::ReadRegister(uint32_t addr) {
uint32_t offset = addr >> 2;
Register &reg = self->holly_regs_[offset];
Register &reg = holly_regs_[offset];
if (!(reg.flags & R)) {
LOG_WARNING("Invalid read access at 0x%x", addr);
@ -70,14 +68,14 @@ T GDROM::ReadRegister(void *ctx, uint32_t addr) {
case GD_ALTSTAT_DEVCTRL_OFFSET:
// this register is the same as the status register, but it does not
// clear DMA status information when it is accessed
return self->status_.full;
return status_.full;
case GD_DATA_OFFSET: {
// TODO add ReadData function
uint16_t v = *(uint16_t *)&self->pio_buffer_[self->pio_idx_];
self->pio_idx_ += 2;
if (self->pio_idx_ == self->pio_size_) {
self->TriggerEvent(EV_SPI_WRITE_END);
uint16_t v = *(uint16_t *)&pio_buffer_[pio_idx_];
pio_idx_ += 2;
if (pio_idx_ == pio_size_) {
TriggerEvent(EV_SPI_WRITE_END);
}
return static_cast<T>(v);
}
@ -87,24 +85,24 @@ T GDROM::ReadRegister(void *ctx, uint32_t addr) {
return 0;
case GD_INTREASON_SECTCNT_OFFSET:
return self->intreason_.full;
return intreason_.full;
case GD_SECTNUM_OFFSET:
return self->sectnum_.full;
return sectnum_.full;
case GD_BYCTLLO_OFFSET:
return self->byte_count_.lo;
return byte_count_.lo;
case GD_BYCTLHI_OFFSET:
return self->byte_count_.hi;
return byte_count_.hi;
case GD_DRVSEL_OFFSET:
// LOG_INFO("GD_DRVSEL");
return 0;
case GD_STATUS_COMMAND_OFFSET:
self->holly_->UnrequestInterrupt(HOLLY_INTC_G1GDINT);
return self->status_.full;
holly_->UnrequestInterrupt(HOLLY_INTC_G1GDINT);
return status_.full;
// g1 bus regs
}
@ -112,15 +110,13 @@ T GDROM::ReadRegister(void *ctx, uint32_t addr) {
return reg.value;
}
template void GDROM::WriteRegister(void *ctx, uint32_t addr, uint8_t value);
template void GDROM::WriteRegister(void *ctx, uint32_t addr, uint16_t value);
template void GDROM::WriteRegister(void *ctx, uint32_t addr, uint32_t value);
template void GDROM::WriteRegister(uint32_t addr, uint8_t value);
template void GDROM::WriteRegister(uint32_t addr, uint16_t value);
template void GDROM::WriteRegister(uint32_t addr, uint32_t value);
template <typename T>
void GDROM::WriteRegister(void *ctx, uint32_t addr, T value) {
GDROM *self = reinterpret_cast<GDROM *>(ctx);
void GDROM::WriteRegister(uint32_t addr, T value) {
uint32_t offset = addr >> 2;
Register &reg = self->holly_regs_[offset];
Register &reg = holly_regs_[offset];
if (!(reg.flags & W)) {
LOG_WARNING("Invalid write access at 0x%x", addr);
@ -138,17 +134,17 @@ void GDROM::WriteRegister(void *ctx, uint32_t addr, T value) {
case GD_DATA_OFFSET: {
// TODO add WriteData function
*(uint16_t *)(&self->pio_buffer_[self->pio_idx_]) = reg.value & 0xffff;
self->pio_idx_ += 2;
if ((self->state_ == STATE_SPI_READ_CMD && self->pio_idx_ == 12) ||
(self->state_ == STATE_SPI_READ_DATA &&
self->pio_idx_ == self->pio_size_)) {
self->TriggerEvent(EV_SPI_READ_END);
*(uint16_t *)(&pio_buffer_[pio_idx_]) = reg.value & 0xffff;
pio_idx_ += 2;
if ((state_ == STATE_SPI_READ_CMD && pio_idx_ == 12) ||
(state_ == STATE_SPI_READ_DATA &&
pio_idx_ == pio_size_)) {
TriggerEvent(EV_SPI_READ_END);
}
} break;
case GD_ERROR_FEATURES_OFFSET:
self->features_.full = reg.value;
features_.full = reg.value;
break;
case GD_INTREASON_SECTCNT_OFFSET:
@ -156,15 +152,15 @@ void GDROM::WriteRegister(void *ctx, uint32_t addr, T value) {
break;
case GD_SECTNUM_OFFSET:
self->sectnum_.full = reg.value;
sectnum_.full = reg.value;
break;
case GD_BYCTLLO_OFFSET:
self->byte_count_.lo = reg.value;
byte_count_.lo = reg.value;
break;
case GD_BYCTLHI_OFFSET:
self->byte_count_.hi = reg.value;
byte_count_.hi = reg.value;
break;
case GD_DRVSEL_OFFSET:
@ -172,7 +168,7 @@ void GDROM::WriteRegister(void *ctx, uint32_t addr, T value) {
break;
case GD_STATUS_COMMAND_OFFSET:
self->ProcessATACommand((ATACommand)reg.value);
ProcessATACommand((ATACommand)reg.value);
break;
// g1 bus regs
@ -194,26 +190,26 @@ void GDROM::WriteRegister(void *ctx, uint32_t addr, T value) {
// SB_GDSTAR, SB_GDLEN, or SB_GDDIR register is overwritten while a DMA
// operation is in progress, the new setting has no effect on the
// current DMA operation.
CHECK_EQ(self->dc_->SB_GDEN, 1); // dma enabled
CHECK_EQ(self->dc_->SB_GDDIR, 1); // gd-rom -> system memory
CHECK_EQ(self->dc_->SB_GDLEN, (uint32_t)self->dma_size_);
CHECK_EQ(dc_->SB_GDEN, 1); // dma enabled
CHECK_EQ(dc_->SB_GDDIR, 1); // gd-rom -> system memory
CHECK_EQ(dc_->SB_GDLEN, (uint32_t)dma_size_);
int transfer_size = self->dc_->SB_GDLEN;
uint32_t start = self->dc_->SB_GDSTAR;
int transfer_size = dc_->SB_GDLEN;
uint32_t start = dc_->SB_GDSTAR;
printf("GD DMA START 0x%x -> 0x%x, 0x%x bytes\n", start,
start + transfer_size, transfer_size);
self->memory_->Memcpy(start, self->dma_buffer_, transfer_size);
memory_->Memcpy(start, dma_buffer_, transfer_size);
// done
self->dc_->SB_GDSTARD = start + transfer_size;
self->dc_->SB_GDLEND = transfer_size;
self->dc_->SB_GDST = 0;
self->holly_->RequestInterrupt(HOLLY_INTC_G1DEINT);
dc_->SB_GDSTARD = start + transfer_size;
dc_->SB_GDLEND = transfer_size;
dc_->SB_GDST = 0;
holly_->RequestInterrupt(HOLLY_INTC_G1DEINT);
// finish off CD_READ command
self->TriggerEvent(EV_SPI_CMD_DONE);
TriggerEvent(EV_SPI_CMD_DONE);
}
break;
}

View File

@ -204,7 +204,7 @@ enum DataMask {
class GDROM {
public:
GDROM(hw::Dreamcast *dc);
GDROM(Dreamcast *dc);
~GDROM();
bool Init();
@ -212,9 +212,9 @@ class GDROM {
void SetDisc(std::unique_ptr<Disc> disc);
template <typename T>
static T ReadRegister(void *ctx, uint32_t addr);
T ReadRegister(uint32_t addr);
template <typename T>
static void WriteRegister(void *ctx, uint32_t addr, T value);
void WriteRegister(uint32_t addr, T value);
private:
void TriggerEvent(GDEvent ev);
@ -228,10 +228,10 @@ class GDROM {
int ReadSectors(int fad, SectorFormat format, DataMask mask, int num_sectors,
uint8_t *dst);
hw::Dreamcast *dc_;
hw::Memory *memory_;
hw::holly::Holly *holly_;
hw::Register *holly_regs_;
Dreamcast *dc_;
Memory *memory_;
holly::Holly *holly_;
Register *holly_regs_;
GD_FEATURES_T features_;
GD_INTREASON_T intreason_;

View File

@ -77,23 +77,21 @@ void Holly::UnrequestInterrupt(HollyInterrupt intr) {
ForwardRequestInterrupts();
}
template uint8_t Holly::ReadRegister(void *ctx, uint32_t addr);
template uint16_t Holly::ReadRegister(void *ctx, uint32_t addr);
template uint32_t Holly::ReadRegister(void *ctx, uint32_t addr);
template uint8_t Holly::ReadRegister(uint32_t addr);
template uint16_t Holly::ReadRegister(uint32_t addr);
template uint32_t Holly::ReadRegister(uint32_t addr);
template <typename T>
T Holly::ReadRegister(void *ctx, uint32_t addr) {
Holly *self = reinterpret_cast<Holly *>(ctx);
T Holly::ReadRegister(uint32_t addr) {
// service all devices connected through the system bus
uint32_t offset = addr >> 2;
if (offset >= SB_MDSTAR_OFFSET && offset <= SB_MRXDBD_OFFSET) {
return Maple::ReadRegister<T>(self->maple_, addr);
return maple_->ReadRegister<T>(addr);
}
if (offset >= GD_ALTSTAT_DEVCTRL_OFFSET && offset <= SB_GDLEND_OFFSET) {
return GDROM::ReadRegister<T>(self->gdrom_, addr);
return gdrom_->ReadRegister<T>(addr);
}
Register &reg = self->holly_regs_[offset];
Register &reg = holly_regs_[offset];
if (!(reg.flags & R)) {
LOG_WARNING("Invalid read access at 0x%x", addr);
@ -106,10 +104,10 @@ T Holly::ReadRegister(void *ctx, uint32_t addr) {
// bits in SB_ISTEXT and SB_ISTERR, respectively, and writes to these two
// bits are ignored.
uint32_t v = reg.value & 0x3fffffff;
if (self->dc_->SB_ISTEXT) {
if (dc_->SB_ISTEXT) {
v |= 0x40000000;
}
if (self->dc_->SB_ISTERR) {
if (dc_->SB_ISTERR) {
v |= 0x80000000;
}
return static_cast<T>(v);
@ -119,25 +117,23 @@ T Holly::ReadRegister(void *ctx, uint32_t addr) {
return static_cast<T>(reg.value);
}
template void Holly::WriteRegister(void *ctx, uint32_t addr, uint8_t value);
template void Holly::WriteRegister(void *ctx, uint32_t addr, uint16_t value);
template void Holly::WriteRegister(void *ctx, uint32_t addr, uint32_t value);
template void Holly::WriteRegister(uint32_t addr, uint8_t value);
template void Holly::WriteRegister(uint32_t addr, uint16_t value);
template void Holly::WriteRegister(uint32_t addr, uint32_t value);
template <typename T>
void Holly::WriteRegister(void *ctx, uint32_t addr, T value) {
Holly *self = reinterpret_cast<Holly *>(ctx);
void Holly::WriteRegister(uint32_t addr, T value) {
// service all devices connected through the system bus
uint32_t offset = addr >> 2;
if (offset >= SB_MDSTAR_OFFSET && offset <= SB_MRXDBD_OFFSET) {
Maple::WriteRegister<T>(self->maple_, addr, value);
maple_->WriteRegister<T>(addr, value);
return;
}
if (offset >= GD_ALTSTAT_DEVCTRL_OFFSET && offset <= SB_GDLEND_OFFSET) {
GDROM::WriteRegister<T>(self->gdrom_, addr, value);
gdrom_->WriteRegister<T>(addr, value);
return;
}
Register &reg = self->holly_regs_[offset];
Register &reg = holly_regs_[offset];
if (!(reg.flags & W)) {
LOG_WARNING("Invalid write access at 0x%x", addr);
@ -153,7 +149,7 @@ void Holly::WriteRegister(void *ctx, uint32_t addr, T value) {
case SB_ISTERR_OFFSET: {
// writing a 1 clears the interrupt
reg.value = old & ~value;
self->ForwardRequestInterrupts();
ForwardRequestInterrupts();
} break;
case SB_IML2NRM_OFFSET:
@ -165,18 +161,18 @@ void Holly::WriteRegister(void *ctx, uint32_t addr, T value) {
case SB_IML6NRM_OFFSET:
case SB_IML6EXT_OFFSET:
case SB_IML6ERR_OFFSET:
self->ForwardRequestInterrupts();
ForwardRequestInterrupts();
break;
case SB_C2DST_OFFSET:
if (value) {
self->CH2DMATransfer();
CH2DMATransfer();
}
break;
case SB_SDST_OFFSET:
if (value) {
self->SortDMATransfer();
SortDMATransfer();
}
break;

View File

@ -157,7 +157,7 @@ enum HollyInterrupt : uint64_t {
class Holly {
public:
Holly(hw::Dreamcast *dc);
Holly(Dreamcast *dc);
bool Init();
@ -165,20 +165,20 @@ class Holly {
void UnrequestInterrupt(HollyInterrupt intr);
template <typename T>
static T ReadRegister(void *ctx, uint32_t addr);
T ReadRegister(uint32_t addr);
template <typename T>
static void WriteRegister(void *ctx, uint32_t addr, T value);
void WriteRegister(uint32_t addr, T value);
private:
void CH2DMATransfer();
void SortDMATransfer();
void ForwardRequestInterrupts();
hw::Dreamcast *dc_;
hw::Register *holly_regs_;
hw::gdrom::GDROM *gdrom_;
hw::maple::Maple *maple_;
hw::sh4::SH4 *sh4_;
Dreamcast *dc_;
Register *holly_regs_;
gdrom::GDROM *gdrom_;
maple::Maple *maple_;
sh4::SH4 *sh4_;
};
}
}

View File

@ -31,11 +31,9 @@ bool PVR2::Init() {
return true;
}
uint32_t PVR2::ReadRegister(void *ctx, uint32_t addr) {
PVR2 *self = reinterpret_cast<PVR2 *>(ctx);
uint32_t PVR2::ReadRegister(uint32_t addr) {
uint32_t offset = addr >> 2;
Register &reg = self->pvr_regs_[offset];
Register &reg = pvr_regs_[offset];
if (!(reg.flags & R)) {
LOG_WARNING("Invalid read access at 0x%x", addr);
@ -45,11 +43,9 @@ uint32_t PVR2::ReadRegister(void *ctx, uint32_t addr) {
return reg.value;
}
void PVR2::WriteRegister(void *ctx, uint32_t addr, uint32_t value) {
PVR2 *self = reinterpret_cast<PVR2 *>(ctx);
void PVR2::WriteRegister(uint32_t addr, uint32_t value) {
uint32_t offset = addr >> 2;
Register &reg = self->pvr_regs_[offset];
Register &reg = pvr_regs_[offset];
if (!(reg.flags & W)) {
LOG_WARNING("Invalid write access at 0x%x", addr);
@ -62,12 +58,12 @@ void PVR2::WriteRegister(void *ctx, uint32_t addr, uint32_t value) {
case SOFTRESET_OFFSET: {
bool reset_ta = value & 0x1;
if (reset_ta) {
self->ta_->SoftReset();
ta_->SoftReset();
}
} break;
case TA_LIST_INIT_OFFSET: {
self->ta_->InitContext(self->dc_->TA_ISP_BASE.base_address);
ta_->InitContext(dc_->TA_ISP_BASE.base_address);
} break;
case STARTRENDER_OFFSET: {
@ -75,17 +71,17 @@ void PVR2::WriteRegister(void *ctx, uint32_t addr, uint32_t value) {
{
auto now = std::chrono::high_resolution_clock::now();
auto delta = std::chrono::duration_cast<std::chrono::nanoseconds>(
now - self->last_render_);
self->last_render_ = now;
self->rps_ = 1000000000.0f / delta.count();
now - last_render_);
last_render_ = now;
rps_ = 1000000000.0f / delta.count();
}
self->ta_->FinalizeContext(self->dc_->PARAM_BASE.base_address);
ta_->FinalizeContext(dc_->PARAM_BASE.base_address);
} break;
case SPG_LOAD_OFFSET:
case FB_R_CTRL_OFFSET: {
self->ReconfigureSPG();
ReconfigureSPG();
} break;
}
}
@ -111,29 +107,21 @@ static uint32_t MAP64(uint32_t addr) {
(addr & 0x3));
}
template uint8_t PVR2::ReadVRamInterleaved(void *ctx, uint32_t addr);
template uint16_t PVR2::ReadVRamInterleaved(void *ctx, uint32_t addr);
template uint32_t PVR2::ReadVRamInterleaved(void *ctx, uint32_t addr);
template uint8_t PVR2::ReadVRamInterleaved(uint32_t addr);
template uint16_t PVR2::ReadVRamInterleaved(uint32_t addr);
template uint32_t PVR2::ReadVRamInterleaved(uint32_t addr);
template <typename T>
T PVR2::ReadVRamInterleaved(void *ctx, uint32_t addr) {
PVR2 *self = reinterpret_cast<PVR2 *>(ctx);
T PVR2::ReadVRamInterleaved(uint32_t addr) {
addr = MAP64(addr);
return re::load<T>(&self->video_ram_[addr]);
return re::load<T>(&video_ram_[addr]);
}
template void PVR2::WriteVRamInterleaved(void *ctx, uint32_t addr,
uint16_t value);
template void PVR2::WriteVRamInterleaved(void *ctx, uint32_t addr,
uint32_t value);
template void PVR2::WriteVRamInterleaved(uint32_t addr, uint16_t value);
template void PVR2::WriteVRamInterleaved(uint32_t addr, uint32_t value);
template <typename T>
void PVR2::WriteVRamInterleaved(void *ctx, uint32_t addr, T value) {
PVR2 *self = reinterpret_cast<PVR2 *>(ctx);
void PVR2::WriteVRamInterleaved(uint32_t addr, T value) {
addr = MAP64(addr);
re::store(&self->video_ram_[addr], value);
re::store(&video_ram_[addr], value);
}
void PVR2::ReconfigureSPG() {

View File

@ -198,34 +198,34 @@ union TA_ISP_BASE_T {
class PVR2 {
public:
PVR2(hw::Dreamcast *dc);
PVR2(Dreamcast *dc);
float rps() { return rps_; }
bool Init();
static uint32_t ReadRegister(void *ctx, uint32_t addr);
static void WriteRegister(void *ctx, uint32_t addr, uint32_t value);
uint32_t ReadRegister(uint32_t addr);
void WriteRegister(uint32_t addr, uint32_t value);
template <typename T>
static T ReadVRamInterleaved(void *ctx, uint32_t addr);
T ReadVRamInterleaved(uint32_t addr);
template <typename T>
static void WriteVRamInterleaved(void *ctx, uint32_t addr, T value);
void WriteVRamInterleaved(uint32_t addr, T value);
private:
void ReconfigureSPG();
void NextScanline();
hw::Dreamcast *dc_;
hw::Scheduler *scheduler_;
hw::holly::Holly *holly_;
hw::holly::TileAccelerator *ta_;
hw::holly::TextureCache *texcache_;
hw::Register *pvr_regs_;
Dreamcast *dc_;
Scheduler *scheduler_;
holly::Holly *holly_;
holly::TileAccelerator *ta_;
holly::TextureCache *texcache_;
Register *pvr_regs_;
uint8_t *palette_ram_;
uint8_t *video_ram_;
hw::TimerHandle line_timer_;
TimerHandle line_timer_;
uint32_t current_scanline_;
std::chrono::high_resolution_clock::time_point last_render_;

View File

@ -347,18 +347,14 @@ TileContext *TileAccelerator::GetLastContext() {
return pending_contexts_.front();
}
void TileAccelerator::WriteCommand(void *ctx, uint32_t addr, uint32_t value) {
TileAccelerator *self = reinterpret_cast<TileAccelerator *>(ctx);
self->WriteContext(self->dc_->TA_ISP_BASE.base_address, value);
void TileAccelerator::WriteCommand(uint32_t addr, uint32_t value) {
WriteContext(dc_->TA_ISP_BASE.base_address, value);
}
void TileAccelerator::WriteTexture(void *ctx, uint32_t addr, uint32_t value) {
TileAccelerator *self = reinterpret_cast<TileAccelerator *>(ctx);
void TileAccelerator::WriteTexture(uint32_t addr, uint32_t value) {
addr &= 0xeeffffff;
re::store(&self->video_ram_[addr], value);
re::store(&video_ram_[addr], value);
}
void TileAccelerator::WritePVRState(TileContext *tactx) {

View File

@ -486,7 +486,7 @@ class TileAccelerator {
static int GetPolyType(const PCW &pcw);
static int GetVertexType(const PCW &pcw);
TileAccelerator(hw::Dreamcast *dc);
TileAccelerator(Dreamcast *dc);
bool Init();
@ -497,17 +497,17 @@ class TileAccelerator {
TileContext *GetLastContext();
static void WriteCommand(void *ctx, uint32_t addr, uint32_t value);
static void WriteTexture(void *ctx, uint32_t addr, uint32_t value);
void WriteCommand(uint32_t addr, uint32_t value);
void WriteTexture(uint32_t addr, uint32_t value);
private:
void WritePVRState(TileContext *tactx);
void WriteBackgroundState(TileContext *tactx);
hw::Dreamcast *dc_;
hw::Memory *memory_;
hw::holly::Holly *holly_;
hw::holly::TextureCache *texcache_;
Dreamcast *dc_;
Memory *memory_;
holly::Holly *holly_;
holly::TextureCache *texcache_;
uint8_t *video_ram_;
std::mutex context_mutex_;

View File

@ -814,7 +814,8 @@ TextureHandle TileRenderer::RegisterTexture(const TileContext *tactx,
break;
default:
LOG_FATAL("Unsupported 4bpp palette pixel format %d", tactx->pal_pxl_format);
LOG_FATAL("Unsupported 4bpp palette pixel format %d",
tactx->pal_pxl_format);
break;
}
break;
@ -838,7 +839,8 @@ TextureHandle TileRenderer::RegisterTexture(const TileContext *tactx,
break;
default:
LOG_FATAL("Unsupported 8bpp palette pixel format %d", tactx->pal_pxl_format);
LOG_FATAL("Unsupported 8bpp palette pixel format %d",
tactx->pal_pxl_format);
break;
}
break;

View File

@ -46,15 +46,13 @@ void Maple::VBlank() {
// TODO maple vblank interrupt?
}
template uint8_t Maple::ReadRegister(void *ctx, uint32_t addr);
template uint16_t Maple::ReadRegister(void *ctx, uint32_t addr);
template uint32_t Maple::ReadRegister(void *ctx, uint32_t addr);
template uint8_t Maple::ReadRegister(uint32_t addr);
template uint16_t Maple::ReadRegister(uint32_t addr);
template uint32_t Maple::ReadRegister(uint32_t addr);
template <typename T>
T Maple::ReadRegister(void *ctx, uint32_t addr) {
Maple *self = reinterpret_cast<Maple *>(ctx);
T Maple::ReadRegister(uint32_t addr) {
uint32_t offset = addr >> 2;
Register &reg = self->holly_regs_[offset];
Register &reg = holly_regs_[offset];
if (!(reg.flags & R)) {
LOG_WARNING("Invalid read access at 0x%x", addr);
@ -64,15 +62,13 @@ T Maple::ReadRegister(void *ctx, uint32_t addr) {
return static_cast<T>(reg.value);
}
template void Maple::WriteRegister(void *ctx, uint32_t addr, uint8_t value);
template void Maple::WriteRegister(void *ctx, uint32_t addr, uint16_t value);
template void Maple::WriteRegister(void *ctx, uint32_t addr, uint32_t value);
template void Maple::WriteRegister(uint32_t addr, uint8_t value);
template void Maple::WriteRegister(uint32_t addr, uint16_t value);
template void Maple::WriteRegister(uint32_t addr, uint32_t value);
template <typename T>
void Maple::WriteRegister(void *ctx, uint32_t addr, T value) {
Maple *self = reinterpret_cast<Maple *>(ctx);
void Maple::WriteRegister(uint32_t addr, T value) {
uint32_t offset = addr >> 2;
Register &reg = self->holly_regs_[offset];
Register &reg = holly_regs_[offset];
if (!(reg.flags & W)) {
LOG_WARNING("Invalid write access at 0x%x", addr);
@ -84,10 +80,10 @@ void Maple::WriteRegister(void *ctx, uint32_t addr, T value) {
switch (offset) {
case SB_MDST_OFFSET: {
uint32_t enabled = self->dc_->SB_MDEN;
uint32_t enabled = dc_->SB_MDEN;
if (enabled) {
if (value) {
self->StartDMA();
StartDMA();
}
} else {
reg.value = 0;

View File

@ -101,7 +101,7 @@ class MapleDevice {
class Maple {
public:
Maple(hw::Dreamcast *dc);
Maple(Dreamcast *dc);
bool Init();
@ -109,18 +109,18 @@ class Maple {
void VBlank();
template <typename T>
static T ReadRegister(void *ctx, uint32_t addr);
T ReadRegister(uint32_t addr);
template <typename T>
static void WriteRegister(void *ctx, uint32_t addr, T value);
void WriteRegister(uint32_t addr, T value);
private:
bool HandleFrame(const MapleFrame &frame, MapleFrame &res);
void StartDMA();
hw::Dreamcast *dc_;
hw::Memory *memory_;
hw::holly::Holly *holly_;
hw::Register *holly_regs_;
Dreamcast *dc_;
Memory *memory_;
holly::Holly *holly_;
Register *holly_regs_;
std::unique_ptr<MapleDevice> devices_[MAX_PORTS];
};

View File

@ -247,15 +247,14 @@ RegionHandle Memory::AllocRegion(uint32_t physical_addr, uint32_t size) {
}
RegionHandle Memory::AllocRegion(uint32_t physical_addr, uint32_t size,
void *ctx, R8Handler r8, R16Handler r16,
R32Handler r32, R64Handler r64, W8Handler w8,
W16Handler w16, W32Handler w32,
W64Handler w64) {
R8Delegate r8, R16Delegate r16,
R32Delegate r32, R64Delegate r64,
W8Delegate w8, W16Delegate w16,
W32Delegate w32, W64Delegate w64) {
MemoryRegion *region = AllocRegion();
region->dynamic = true;
region->physical_addr = physical_addr;
region->size = size;
region->ctx = ctx;
region->r8 = r8;
region->r16 = r16;
region->r32 = r32;
@ -536,7 +535,7 @@ void Memory::UnmapVirtualSpace() {
unmap_virtual(protected_base_);
}
template <typename INT, INT (*MemoryRegion::*HANDLER)(void *, uint32_t)>
template <typename INT, delegate<INT(uint32_t)> MemoryRegion::*DELEGATE>
inline INT Memory::ReadBytes(uint32_t addr) {
PageEntry page = pages_[PageIndex(addr)];
uint32_t page_offset = PageOffset(addr);
@ -547,16 +546,11 @@ inline INT Memory::ReadBytes(uint32_t addr) {
}
MemoryRegion &region = regions_[RegionIndex(page)];
if (!(region.*HANDLER)) {
LOG_WARNING("Unmapped read at 0x%08x", addr);
return 0;
}
uint32_t region_offset = RegionOffset(page);
return (region.*HANDLER)(region.ctx, region_offset + page_offset);
return (region.*DELEGATE)(region_offset + page_offset);
}
template <typename INT, void (*MemoryRegion::*HANDLER)(void *, uint32_t, INT)>
template <typename INT, delegate<void(uint32_t, INT)> MemoryRegion::*DELEGATE>
inline void Memory::WriteBytes(uint32_t addr, INT value) {
PageEntry page = pages_[PageIndex(addr)];
uint32_t page_offset = PageOffset(addr);
@ -568,11 +562,6 @@ inline void Memory::WriteBytes(uint32_t addr, INT value) {
}
MemoryRegion &region = regions_[RegionIndex(page)];
if (!(region.*HANDLER)) {
LOG_WARNING("Unmapped write at 0x%08x", addr);
return;
}
uint32_t region_offset = RegionOffset(page);
(region.*HANDLER)(region.ctx, region_offset + page_offset, value);
(region.*DELEGATE)(region_offset + page_offset, value);
}

View File

@ -1,6 +1,8 @@
#ifndef MEMORY_H
#define MEMORY_H
#include <functional>
#include "core/delegate.h"
#include "sys/exception_handler.h"
#include "sys/memory.h"
@ -86,14 +88,15 @@ class MemoryMap {
// entries are always non-zero
typedef uintptr_t PageEntry;
typedef uint8_t (*R8Handler)(void *, uint32_t);
typedef uint16_t (*R16Handler)(void *, uint32_t);
typedef uint32_t (*R32Handler)(void *, uint32_t);
typedef uint64_t (*R64Handler)(void *, uint32_t);
typedef void (*W8Handler)(void *, uint32_t, uint8_t);
typedef void (*W16Handler)(void *, uint32_t, uint16_t);
typedef void (*W32Handler)(void *, uint32_t, uint32_t);
typedef void (*W64Handler)(void *, uint32_t, uint64_t);
typedef delegate<uint8_t(uint32_t)> R8Delegate;
typedef delegate<uint16_t(uint32_t)> R16Delegate;
typedef delegate<uint32_t(uint32_t)> R32Delegate;
typedef delegate<uint64_t(uint32_t)> R64Delegate;
typedef delegate<void(uint32_t, uint8_t)> W8Delegate;
typedef delegate<void(uint32_t, uint16_t)> W16Delegate;
typedef delegate<void(uint32_t, uint32_t)> W32Delegate;
typedef delegate<void(uint32_t, uint64_t)> W64Delegate;
enum {
PAGE_BITS = 20,
@ -131,14 +134,15 @@ struct MemoryRegion {
uint32_t physical_addr;
uint32_t size;
void *ctx;
R8Handler r8;
R16Handler r16;
R32Handler r32;
R64Handler r64;
W8Handler w8;
W16Handler w16;
W32Handler w32;
W64Handler w64;
R8Delegate r8;
R16Delegate r16;
R32Delegate r32;
R64Delegate r64;
W8Delegate w8;
W16Delegate w16;
W32Delegate w32;
W64Delegate w64;
};
class Memory {
@ -162,10 +166,10 @@ class Memory {
bool Init();
RegionHandle AllocRegion(uint32_t physical_addr, uint32_t size);
RegionHandle AllocRegion(uint32_t physical_addr, uint32_t size, void *ctx,
R8Handler r8, R16Handler r16, R32Handler r32,
R64Handler r64, W8Handler w8, W16Handler w16,
W32Handler w32, W64Handler w64);
RegionHandle AllocRegion(uint32_t physical_addr, uint32_t size, R8Delegate r8,
R16Delegate r16, R32Delegate r32, R64Delegate r64,
W8Delegate w8, W16Delegate w16, W32Delegate w32,
W64Delegate w64);
bool Map(const MemoryMap &map);
@ -203,9 +207,9 @@ class Memory {
bool MapVirtualSpace();
void UnmapVirtualSpace();
template <typename INT, INT (*MemoryRegion::*HANDLER)(void *, uint32_t)>
template <typename INT, delegate<INT(uint32_t)> MemoryRegion::*DELEGATE>
INT ReadBytes(uint32_t addr);
template <typename INT, void (*MemoryRegion::*HANDLER)(void *, uint32_t, INT)>
template <typename INT, delegate<void(uint32_t, INT)> MemoryRegion::*DELEGATE>
void WriteBytes(uint32_t addr, INT value);
// shared memory object where all physical data is written to

View File

@ -138,13 +138,11 @@ void SH4::UnrequestInterrupt(Interrupt intr) {
UpdatePendingInterrupts();
}
template uint8_t SH4::ReadRegister(void *ctx, uint32_t addr);
template uint16_t SH4::ReadRegister(void *ctx, uint32_t addr);
template uint32_t SH4::ReadRegister(void *ctx, uint32_t addr);
template uint8_t SH4::ReadRegister(uint32_t addr);
template uint16_t SH4::ReadRegister(uint32_t addr);
template uint32_t SH4::ReadRegister(uint32_t addr);
template <typename T>
T SH4::ReadRegister(void *ctx, uint32_t addr) {
SH4 *self = reinterpret_cast<SH4 *>(ctx);
T SH4::ReadRegister(uint32_t addr) {
// translate from 64mb space to our 16kb space
addr = ((addr & 0x1fe0000) >> 11) | ((addr & 0xfc) >> 2);
@ -177,8 +175,8 @@ T SH4::ReadRegister(void *ctx, uint32_t addr) {
// reg[PDTRA] = reg[PDTRA] & 0xfffd;
// _8c00b92c(0);
// reg[PCTRA] = old_PCTRA;
uint32_t pctra = self->PCTRA;
uint32_t pdtra = self->PDTRA;
uint32_t pctra = PCTRA;
uint32_t pdtra = PDTRA;
uint32_t v = 0;
if ((pctra & 0xf) == 0x8 ||
((pctra & 0xf) == 0xb && (pdtra & 0xf) != 0x2) ||
@ -218,29 +216,27 @@ T SH4::ReadRegister(void *ctx, uint32_t addr) {
}
case TCNT0_OFFSET:
return self->TimerCount(0);
return TimerCount(0);
case TCNT1_OFFSET:
return self->TimerCount(1);
return TimerCount(1);
case TCNT2_OFFSET:
return self->TimerCount(2);
return TimerCount(2);
}
return static_cast<T>(self->area7_[addr]);
return static_cast<T>(area7_[addr]);
}
template void SH4::WriteRegister(void *ctx, uint32_t addr, uint8_t value);
template void SH4::WriteRegister(void *ctx, uint32_t addr, uint16_t value);
template void SH4::WriteRegister(void *ctx, uint32_t addr, uint32_t value);
template void SH4::WriteRegister(uint32_t addr, uint8_t value);
template void SH4::WriteRegister(uint32_t addr, uint16_t value);
template void SH4::WriteRegister(uint32_t addr, uint32_t value);
template <typename T>
void SH4::WriteRegister(void *ctx, uint32_t addr, T value) {
SH4 *self = reinterpret_cast<SH4 *>(ctx);
void SH4::WriteRegister(uint32_t addr, T value) {
// translate from 64mb space to our 16kb space
addr = ((addr & 0x1fe0000) >> 11) | ((addr & 0xfc) >> 2);
self->area7_[addr] = static_cast<uint32_t>(value);
area7_[addr] = static_cast<uint32_t>(value);
switch (addr) {
case MMUCR_OFFSET: {
@ -252,35 +248,35 @@ void SH4::WriteRegister(void *ctx, uint32_t addr, T value) {
// it seems the only aspect of the cache control register that needs to be
// emulated is the instruction cache invalidation
case CCR_OFFSET: {
if (self->CCR.ICI) {
self->ResetCache();
if (CCR.ICI) {
ResetCache();
}
} break;
case IPRA_OFFSET:
case IPRB_OFFSET:
case IPRC_OFFSET: {
self->ReprioritizeInterrupts();
ReprioritizeInterrupts();
} break;
// TODO UnrequestInterrupt on TCR write
case TSTR_OFFSET: {
self->ScheduleTimer(0);
self->ScheduleTimer(1);
self->ScheduleTimer(2);
ScheduleTimer(0);
ScheduleTimer(1);
ScheduleTimer(2);
} break;
case TCNT0_OFFSET: {
self->ScheduleTimer(0);
ScheduleTimer(0);
} break;
case TCNT1_OFFSET: {
self->ScheduleTimer(1);
ScheduleTimer(1);
} break;
case TCNT2_OFFSET: {
self->ScheduleTimer(2);
ScheduleTimer(2);
} break;
}
}
@ -289,50 +285,46 @@ void SH4::WriteRegister(void *ctx, uint32_t addr, T value) {
#define CACHE_OFFSET(addr, OIX) \
((OIX ? ((addr & 0x2000000) >> 13) : ((addr & 0x2000) >> 1)) | (addr & 0xfff))
template uint8_t SH4::ReadCache(void *ctx, uint32_t addr);
template uint16_t SH4::ReadCache(void *ctx, uint32_t addr);
template uint32_t SH4::ReadCache(void *ctx, uint32_t addr);
template uint64_t SH4::ReadCache(void *ctx, uint32_t addr);
template uint8_t SH4::ReadCache(uint32_t addr);
template uint16_t SH4::ReadCache(uint32_t addr);
template uint32_t SH4::ReadCache(uint32_t addr);
template uint64_t SH4::ReadCache(uint32_t addr);
template <typename T>
T SH4::ReadCache(void *ctx, uint32_t addr) {
SH4 *self = reinterpret_cast<SH4 *>(ctx);
CHECK_EQ(self->CCR.ORA, 1u);
addr = CACHE_OFFSET(addr, self->CCR.OIX);
return re::load<T>(&self->cache_[addr]);
T SH4::ReadCache(uint32_t addr) {
CHECK_EQ(CCR.ORA, 1u);
addr = CACHE_OFFSET(addr, CCR.OIX);
return re::load<T>(&cache_[addr]);
}
template void SH4::WriteCache(void *ctx, uint32_t addr, uint8_t value);
template void SH4::WriteCache(void *ctx, uint32_t addr, uint16_t value);
template void SH4::WriteCache(void *ctx, uint32_t addr, uint32_t value);
template void SH4::WriteCache(void *ctx, uint32_t addr, uint64_t value);
template void SH4::WriteCache(uint32_t addr, uint8_t value);
template void SH4::WriteCache(uint32_t addr, uint16_t value);
template void SH4::WriteCache(uint32_t addr, uint32_t value);
template void SH4::WriteCache(uint32_t addr, uint64_t value);
template <typename T>
void SH4::WriteCache(void *ctx, uint32_t addr, T value) {
SH4 *self = reinterpret_cast<SH4 *>(ctx);
CHECK_EQ(self->CCR.ORA, 1u);
addr = CACHE_OFFSET(addr, self->CCR.OIX);
re::store(&self->cache_[addr], value);
void SH4::WriteCache(uint32_t addr, T value) {
CHECK_EQ(CCR.ORA, 1u);
addr = CACHE_OFFSET(addr, CCR.OIX);
re::store(&cache_[addr], value);
}
template uint8_t SH4::ReadSQ(void *ctx, uint32_t addr);
template uint16_t SH4::ReadSQ(void *ctx, uint32_t addr);
template uint32_t SH4::ReadSQ(void *ctx, uint32_t addr);
template uint8_t SH4::ReadSQ(uint32_t addr);
template uint16_t SH4::ReadSQ(uint32_t addr);
template uint32_t SH4::ReadSQ(uint32_t addr);
template <typename T>
T SH4::ReadSQ(void *ctx, uint32_t addr) {
SH4 *self = reinterpret_cast<SH4 *>(ctx);
T SH4::ReadSQ(uint32_t addr) {
uint32_t sqi = (addr & 0x20) >> 5;
unsigned idx = (addr & 0x1c) >> 2;
return static_cast<T>(self->ctx_.sq[sqi][idx]);
return static_cast<T>(ctx_.sq[sqi][idx]);
}
template void SH4::WriteSQ(void *ctx, uint32_t addr, uint8_t value);
template void SH4::WriteSQ(void *ctx, uint32_t addr, uint16_t value);
template void SH4::WriteSQ(void *ctx, uint32_t addr, uint32_t value);
template void SH4::WriteSQ(uint32_t addr, uint8_t value);
template void SH4::WriteSQ(uint32_t addr, uint16_t value);
template void SH4::WriteSQ(uint32_t addr, uint32_t value);
template <typename T>
void SH4::WriteSQ(void *ctx, uint32_t addr, T value) {
SH4 *self = reinterpret_cast<SH4 *>(ctx);
void SH4::WriteSQ(uint32_t addr, T value) {
uint32_t sqi = (addr & 0x20) >> 5;
uint32_t idx = (addr & 0x1c) >> 2;
self->ctx_.sq[sqi][idx] = static_cast<uint32_t>(value);
ctx_.sq[sqi][idx] = static_cast<uint32_t>(value);
}
uint32_t SH4::CompilePC() {

View File

@ -110,7 +110,7 @@ class SH4 {
friend void RunSH4Test(const SH4Test &);
public:
SH4(hw::Dreamcast *dc);
SH4(Dreamcast *dc);
~SH4();
bool Init();
@ -125,19 +125,19 @@ class SH4 {
void UnrequestInterrupt(Interrupt intr);
template <typename T>
static T ReadRegister(void *ctx, uint32_t addr);
T ReadRegister(uint32_t addr);
template <typename T>
static void WriteRegister(void *ctx, uint32_t addr, T value);
void WriteRegister(uint32_t addr, T value);
template <typename T>
static T ReadCache(void *ctx, uint32_t addr);
T ReadCache(uint32_t addr);
template <typename T>
static void WriteCache(void *ctx, uint32_t addr, T value);
void WriteCache(uint32_t addr, T value);
template <typename T>
static T ReadSQ(void *ctx, uint32_t addr);
T ReadSQ(uint32_t addr);
template <typename T>
static void WriteSQ(void *ctx, uint32_t addr, T value);
void WriteSQ(uint32_t addr, T value);
private:
static uint32_t CompilePC();
@ -164,9 +164,9 @@ class SH4 {
void ScheduleTimer(int n);
void ExpireTimer(int n);
hw::Dreamcast *dc_;
hw::Memory *memory_;
hw::Scheduler *scheduler_;
Dreamcast *dc_;
Memory *memory_;
Scheduler *scheduler_;
SH4CodeCache *code_cache_;
jit::frontend::sh4::SH4Context ctx_;

View File

@ -1610,7 +1610,7 @@ EMITTER(FMOV_INDEX_LOAD) {
EMITTER(FMOV_STORE) {
Value *addr = b.LoadRegister(i.Rn, VALUE_I32);
if (fpu.double_sz) {
if (fpu.double_sz) {
if (i.Rm & 1) {
b.StoreGuest(addr, b.LoadRegisterXF(i.Rm & 0xe, VALUE_I32));
b.StoreGuest(b.Add(addr, b.AllocConstant(4)),