dsp: map TEMP/MEMS/MIXS regs to sh4 and aica address space. Clean up

This commit is contained in:
Flyinghead 2021-08-26 10:16:07 +02:00
parent 2a849ccba5
commit ca17717af7
15 changed files with 399 additions and 464 deletions

View File

@ -35,7 +35,6 @@
#include "hw/pvr/Renderer_if.h" #include "hw/pvr/Renderer_if.h"
#include "rend/CustomTexture.h" #include "rend/CustomTexture.h"
#include "hw/arm7/arm7_rec.h" #include "hw/arm7/arm7_rec.h"
#include "hw/aica/dsp.h"
extern int screen_width, screen_height; extern int screen_width, screen_height;
@ -721,7 +720,6 @@ bool dc_loadstate(const void **data, u32 size)
mmu_set_state(); mmu_set_state();
sh4_cpu.ResetCache(); sh4_cpu.ResetCache();
dsp.dyndirty = true;
sh4_sched_ffts(); sh4_sched_ffts();
return true; return true;

View File

@ -212,7 +212,6 @@ struct CommonData_struct
u32 :16; u32 :16;
}; };
//should be 0x15C8 in size
struct DSPData_struct struct DSPData_struct
{ {
//+0x000 //+0x000
@ -222,13 +221,13 @@ struct DSPData_struct
u32 MADRS[64]; //15:0 u32 MADRS[64]; //15:0
//+0x300 //+0x300
u8 PAD0[0x100]; u8 _PAD0[0x100];
//+0x400 //+0x400
u32 MPRO[128*4]; //15:0 u32 MPRO[128*4]; //15:0
//+0xC00 //+0xC00
u8 PAD1[0x400]; u8 _PAD1[0x400];
//+0x1000 //+0x1000
struct struct
@ -260,6 +259,8 @@ struct DSPData_struct
//+0x15C0 //+0x15C0
u32 EXTS[2]; //15:0 u32 EXTS[2]; //15:0
}; };
static_assert(sizeof(DSPData_struct) == 0x15C8, "Wrong DSPData size");
union InterruptInfo union InterruptInfo
{ {
struct struct
@ -305,28 +306,29 @@ extern DSPData_struct* DSPData;
template<u32 sz> template<u32 sz>
void WriteAicaReg(u32 reg,u32 data); void WriteAicaReg(u32 reg,u32 data);
//Timers :)
struct AicaTimerData
{
union
{
struct
{
u32 count:8;
u32 md:3;
u32 nil:5;
u32 pad:16;
};
u32 data;
};
};
class AicaTimer class AicaTimer
{ {
public: struct AicaTimerData
{
union
{
struct
{
u32 count:8;
u32 md:3;
u32 nil:5;
u32 pad:16;
};
u32 data;
};
};
AicaTimerData* data; AicaTimerData* data;
u32 id;
public:
s32 c_step; s32 c_step;
u32 m_step; u32 m_step;
u32 id;
void Init(u8* regbase,u32 timer) void Init(u8* regbase,u32 timer)
{ {
data=(AicaTimerData*)&regbase[0x2890 + timer*4]; data=(AicaTimerData*)&regbase[0x2890 + timer*4];
@ -334,6 +336,7 @@ public:
m_step=1<<(data->md); m_step=1<<(data->md);
c_step=m_step; c_step=m_step;
} }
void StepTimer(u32 samples) void StepTimer(u32 samples)
{ {
do do

View File

@ -20,6 +20,42 @@ u32 ReadReg(u32 addr)
else else
ReadCommonReg(addr, false); ReadCommonReg(addr, false);
} }
else if (addr >= 0x4000 && addr < 0x4580)
{
if (addr & 2)
{
INFO_LOG(AICA, "Unaligned DSP register read @ %x", addr);
return 0;
}
DEBUG_LOG(AICA, "DSP register read @ %x", addr);
// DSP TEMP/MEMS
u32 v;
if (addr < 0x4500)
{
v = addr < 0x4400 ? dsp::state.TEMP[(addr - 0x4000) / 8] : dsp::state.MEMS[(addr - 0x4400) / 8];
if (addr & 4)
v = (v >> 8) & 0xffff;
else
v &= 0xff;
}
// DSP MIXS
else
{
v = dsp::state.MIXS[(addr - 0x4500) / 8];
if (addr & 4)
v = (v >> 4) & 0xffff;
else
v &= 0xf;
}
if (sz == 1)
{
if (addr & 1)
v >>= 8;
else
v &= 0xff;
}
return v;
}
return ReadMemArr<sz>(aica_reg, addr); return ReadMemArr<sz>(aica_reg, addr);
} }
@ -36,9 +72,9 @@ void WriteReg(u32 addr,u32 data)
return; return;
} }
if (addr<0x2800) if (addr < 0x2800)
{ {
if (sz==1) if (sz == 1)
WriteMemArr<1>(aica_reg, addr, data); WriteMemArr<1>(aica_reg, addr, data);
else else
WriteMemArr<2>(aica_reg, addr, data); WriteMemArr<2>(aica_reg, addr, data);
@ -47,38 +83,101 @@ void WriteReg(u32 addr,u32 data)
if (addr < 0x2818) if (addr < 0x2818)
{ {
if (sz==1) if (sz == 1)
{ {
WriteCommonReg8(addr,data); WriteCommonReg8(addr, data);
} }
else else
{ {
WriteCommonReg8(addr,data&0xFF); WriteCommonReg8(addr, data & 0xFF);
WriteCommonReg8(addr+1,data>>8); WriteCommonReg8(addr + 1, data >> 8);
} }
return; return;
} }
if (addr>=0x3000) if (addr >= 0x3000)
{ {
if (sz==1) if (addr & 2)
{
INFO_LOG(AICA, "Unaligned DSP register write @ %x", addr);
return;
}
if (addr >= 0x4000 && addr < 0x4580)
{
// DSP TEMP/MEMS
if (addr < 0x4500)
{
s32 &v = addr < 0x4400 ? dsp::state.TEMP[(addr - 0x4000) / 8] : dsp::state.MEMS[(addr - 0x4400) / 8];
if (addr & 4)
{
if (sz == 1)
{
if (addr & 1)
v = (v & 0x0000ffff) | (((s32)data << 24) >> 8);
else
v = (v & 0xffff00ff) | ((data & 0xff) << 8);
}
else
{
v = (v & 0xff) | (((s32)data << 16) >> 8);
}
}
else
{
if (sz != 1 || (addr & 1) == 0)
v = (v & ~0xff) | (data & 0xff);
// else ignored
}
DEBUG_LOG(AICA, "DSP TEMP/MEMS register write<%d> @ %x = %d", sz, addr, v);
}
// DSP MIXS
else
{
s32 &v = dsp::state.MIXS[(addr - 0x4500) / 8];
if (addr & 4)
{
if (sz == 1)
{
if (addr & 1)
v = (v & 0x00000fff) | (((s32)data << 24) >> 12);
else
v = (v & 0xfffff00f) | ((data & 0xff) << 4);
}
else
{
v = (v & 0xf) | (((s32)data << 16) >> 12);
}
}
else
{
if (sz != 1 || (addr & 1) == 0)
v = (v & ~0xf) | (data & 0xf);
// else ignored
}
DEBUG_LOG(AICA, "DSP MIXS register write<%d> @ %x = %d", sz, addr, v);
}
return;
}
if (sz == 1)
{ {
WriteMemArr<1>(aica_reg, addr, data); WriteMemArr<1>(aica_reg, addr, data);
dsp_writenmem(addr); dsp::writeProg(addr);
} }
else else
{ {
WriteMemArr<2>(aica_reg, addr, data); WriteMemArr<2>(aica_reg, addr, data);
dsp_writenmem(addr); dsp::writeProg(addr);
dsp_writenmem(addr+1); dsp::writeProg(addr + 1);
} }
return; return;
} }
if (sz==1) if (sz == 1)
WriteAicaReg<1>(addr,data); WriteAicaReg<1>(addr, data);
else else
WriteAicaReg<2>(addr,data); WriteAicaReg<2>(addr, data);
} }
//Aica reads (both sh4&arm) //Aica reads (both sh4&arm)
u32 libAICA_ReadReg(u32 addr, u32 size) u32 libAICA_ReadReg(u32 addr, u32 size)
{ {
@ -88,24 +187,22 @@ u32 libAICA_ReadReg(u32 addr, u32 size)
return ReadReg<2>(addr & 0x7FFF); return ReadReg<2>(addr & 0x7FFF);
} }
void libAICA_WriteReg(u32 addr,u32 data,u32 size) void libAICA_WriteReg(u32 addr, u32 data, u32 size)
{ {
if (size==1) if (size == 1)
WriteReg<1>(addr & 0x7FFF,data); WriteReg<1>(addr & 0x7FFF, data);
else else
WriteReg<2>(addr & 0x7FFF,data); WriteReg<2>(addr & 0x7FFF, data);
} }
//Map using _vmem .. yay
void init_mem() void init_mem()
{ {
memset(aica_reg,0,sizeof(aica_reg)); memset(aica_reg, 0, sizeof(aica_reg));
aica_ram.data[ARAM_SIZE-1]=1; aica_ram.data[ARAM_SIZE - 1] = 1;
aica_ram.Zero(); aica_ram.Zero();
} }
//kill mem map & free used mem ;)
void term_mem() void term_mem()
{ {
} }

View File

@ -1,5 +1,5 @@
#include "dsp.h" #include "dsp.h"
#include "aica.h"
/* /*
DSP rec_v1 DSP rec_v1
@ -17,7 +17,10 @@
See LICENSE & COPYRIGHT files further details See LICENSE & COPYRIGHT files further details
*/ */
alignas(4096) dsp_t dsp; namespace dsp
{
DSPState state;
//float format is ? //float format is ?
u16 DYNACALL PACK(s32 val) u16 DYNACALL PACK(s32 val)
@ -62,7 +65,7 @@ s32 DYNACALL UNPACK(u16 val)
return uval; return uval;
} }
void DecodeInst(const u32 *IPtr, _INST *i) void DecodeInst(const u32 *IPtr, Instruction *i)
{ {
i->TRA = (IPtr[0] >> 9) & 0x7F; i->TRA = (IPtr[0] >> 9) & 0x7F;
i->TWT = IPtr[0] & 0x100; i->TWT = IPtr[0] & 0x100;
@ -93,51 +96,54 @@ void DecodeInst(const u32 *IPtr, _INST *i)
i->NXADR = IPtr[3] & 0x80; i->NXADR = IPtr[3] & 0x80;
} }
#if FEAT_DSPREC != DYNAREC_NONE #if FEAT_DSPREC == DYNAREC_NONE
void recInit() {
void dsp_init()
{
memset(&dsp, 0, sizeof(dsp));
dsp.RBL = 0x8000 - 1;
dsp.RBP = 0;
dsp.regs.MDEC_CT = 1;
dsp.dyndirty = true;
dsp_rec_init();
} }
void dsp_step() void recompile() {
}
#endif
void init()
{ {
if (dsp.dyndirty) memset(&state, 0, sizeof(state));
{ state.RBL = 0x8000 - 1;
dsp.dyndirty = false; state.RBP = 0;
dsp_recompile(); state.MDEC_CT = 1;
} state.dirty = true;
if (dsp.Stopped)
return; recInit();
dsp_rec_step();
} }
void dsp_writenmem(u32 addr) void writeProg(u32 addr)
{ {
if (addr >= 0x3400 && addr < 0x3C00) if (addr >= 0x3400 && addr < 0x3C00)
{ state.dirty = true;
dsp.dyndirty = true;
}
else if (addr >= 0x4000 && addr < 0x4400)
{
// TODO proper sharing of memory with sh4 through DSPData
memset(dsp.TEMP, 0, sizeof(dsp.TEMP));
}
else if (addr >= 0x4400 && addr < 0x4500)
{
// TODO proper sharing of memory with sh4 through DSPData
memset(dsp.MEMS, 0, sizeof(dsp.MEMS));
}
} }
void dsp_term() void term()
{ {
state.stopped = true;
} }
#endif void step()
{
if (state.dirty)
{
state.dirty = false;
state.stopped = true;
for (u32 instr : DSPData->MPRO)
if (instr != 0)
{
state.stopped = false;
break;
}
if (!state.stopped)
recompile();
}
if (state.stopped)
return;
runStep();
}
}

View File

@ -1,102 +1,77 @@
#pragma once #pragma once
#include "types.h" #include "types.h"
struct dsp_t namespace dsp
{ {
//Dynarec
u8 DynCode[4096*8]; //32 kb, 8 pages
//buffered DSP state struct DSPState
//24 bit wide {
s32 TEMP[128]; // buffered DSP state
//24 bit wide s32 TEMP[128]; // 24 bits
s32 MEMS[32]; s32 MEMS[32]; // 24 bits
//20 bit wide s32 MIXS[16]; // 20 bits
s32 MIXS[16];
//RBL/RBP (decoded) // RBL/RBP (decoded, from aica common regs)
u32 RBP; u32 RBP;
u32 RBL; u32 RBL;
struct u32 MDEC_CT;
// volatile dsp regs
int SHIFTED; // 24 bit
int B; // 26 bit
int MEMVAL[4];
int FRC_REG; // 13 bit
int Y_REG; // 24 bit
u32 ADRS_REG; // 13 bit
bool stopped; // DSP program is a no-op
bool dirty; // DSP program has changed
bool serialize(void **data, unsigned int *total_size)
{ {
bool MAD_OUT; REICAST_S(TEMP);
bool MEM_ADDR; REICAST_S(MEMS);
bool MEM_RD_DATA; REICAST_S(MIXS);
bool MEM_WT_DATA; REICAST_S(RBP);
bool FRC_REG; REICAST_S(RBL);
bool ADRS_REG; REICAST_S(MDEC_CT);
bool Y_REG;
bool MDEC_CT; return true;
bool MWT_1; }
bool MRD_1;
//bool MADRS;
bool MEMS;
bool NOFL_1;
bool NOFL_2;
bool TEMPS; bool deserialize(void **data, unsigned int *total_size, serialize_version_enum version)
bool EFREG;
}regs_init;
//s32 -> stored as signed extended to 32 bits
struct
{ {
s32 MAD_OUT; if (version < V18)
s32 MEM_ADDR; REICAST_SKIP(4096 * 8); // DynCode
s32 MEM_RD_DATA; REICAST_US(TEMP);
s32 MEM_WT_DATA; REICAST_US(MEMS);
s32 FRC_REG; REICAST_US(MIXS);
s32 ADRS_REG; REICAST_US(RBP);
s32 Y_REG; REICAST_US(RBL);
if (version < V18)
REICAST_SKIP(44);
REICAST_US(MDEC_CT);
if (version < V18)
REICAST_SKIP(33596 - 4096 * 8 - sizeof(TEMP) - sizeof(MEMS) - sizeof(MIXS) - 4 * 3 - 44); // other dsp stuff
dirty = true;
u32 MDEC_CT; return true;
u32 MWT_1; }
u32 MRD_1;
u32 MADRS;
u32 NOFL_1;
u32 NOFL_2;
}regs;
//DEC counter :)
//u32 DEC;
//various dsp regs
signed int ACC; //26 bit
signed int SHIFTED; //24 bit
signed int B; //26 bit
signed int MEMVAL[4];
signed int FRC_REG; //13 bit
signed int Y_REG; //24 bit
unsigned int ADDR;
unsigned int ADRS_REG; //13 bit
//Direct Mapped data :
//COEF *128
//MADRS *64
//MPRO(dsp code) *4 *128
//EFREG *16
//EXTS *2
// Interpreter flags
bool Stopped;
//Dynarec flags
bool dyndirty;
}; };
alignas(4096) extern dsp_t dsp; extern DSPState state;
void dsp_init(); void init();
void dsp_term(); void term();
void dsp_step(); void step();
void dsp_writenmem(u32 addr); void writeProg(u32 addr);
void dsp_rec_init(); void recInit();
void dsp_rec_step(); void runStep();
void dsp_recompile(); void recompile();
struct _INST struct Instruction
{ {
u8 TRA; u8 TRA;
bool TWT; bool TWT;
@ -127,6 +102,8 @@ struct _INST
bool NXADR; //MRQ set bool NXADR; //MRQ set
}; };
void DecodeInst(const u32 *IPtr, _INST *i); void DecodeInst(const u32 *IPtr, Instruction *i);
u16 DYNACALL PACK(s32 val); u16 DYNACALL PACK(s32 val);
s32 DYNACALL UNPACK(u16 val); s32 DYNACALL UNPACK(u16 val);
}

View File

@ -27,6 +27,9 @@
#include <aarch32/macro-assembler-aarch32.h> #include <aarch32/macro-assembler-aarch32.h>
using namespace vixl::aarch32; using namespace vixl::aarch32;
namespace dsp
{
constexpr size_t CodeSize = 4096 * 8; //32 kb, 8 pages constexpr size_t CodeSize = 4096 * 8; //32 kb, 8 pages
#if defined(__unix__) #if defined(__unix__)
@ -40,7 +43,7 @@ class DSPAssembler : public MacroAssembler
public: public:
DSPAssembler(u8 *code_buffer, size_t size) : MacroAssembler(code_buffer, size, A32) {} DSPAssembler(u8 *code_buffer, size_t size) : MacroAssembler(code_buffer, size, A32) {}
void compile(dsp_t *DSP) void compile(DSPState *DSP)
{ {
this->DSP = DSP; this->DSP = DSP;
DEBUG_LOG(AICA_ARM, "DSPAssembler::compile recompiling for arm32 at %p", GetBuffer()->GetStartAddress<void*>()); DEBUG_LOG(AICA_ARM, "DSPAssembler::compile recompiling for arm32 at %p", GetBuffer()->GetStartAddress<void*>());
@ -66,7 +69,7 @@ public:
for (int step = 0; step < 128; ++step) for (int step = 0; step < 128; ++step)
{ {
u32 *mpro = &DSPData->MPRO[step * 4]; u32 *mpro = &DSPData->MPRO[step * 4];
_INST op; Instruction op;
DecodeInst(mpro, &op); DecodeInst(mpro, &op);
const u32 COEF = step; const u32 COEF = step;
@ -109,8 +112,8 @@ public:
Mov(B, ACC); Mov(B, ACC);
else else
{ {
//B = DSP->TEMP[(TRA + DSP->regs.MDEC_CT) & 0x7F]; //B = DSP->TEMP[(TRA + DSP->MDEC_CT) & 0x7F];
Ldr(r1, dsp_operand(&DSP->regs.MDEC_CT)); Ldr(r1, dsp_operand(&DSP->MDEC_CT));
if (op.TRA) if (op.TRA)
Add(r1, r1, op.TRA); Add(r1, r1, op.TRA);
Bfc(r1, 7, 25); Bfc(r1, 7, 25);
@ -128,12 +131,12 @@ public:
X_alias = &INPUTS; X_alias = &INPUTS;
else else
{ {
//X = DSP->TEMP[(TRA + DSP->regs.MDEC_CT) & 0x7F]; //X = DSP->TEMP[(TRA + DSP->MDEC_CT) & 0x7F];
if (!op.ZERO && !op.BSEL && !op.NEGB) if (!op.ZERO && !op.BSEL && !op.NEGB)
X_alias = &B; X_alias = &B;
else else
{ {
Ldr(r1, dsp_operand(&DSP->regs.MDEC_CT)); Ldr(r1, dsp_operand(&DSP->MDEC_CT));
if (op.TRA) if (op.TRA)
Add(r1, r1, op.TRA); Add(r1, r1, op.TRA);
Bfc(r1, 7, 25); Bfc(r1, 7, 25);
@ -208,9 +211,9 @@ public:
if (op.TWT) if (op.TWT)
{ {
//DSP->TEMP[(op.TWA + DSP->regs.MDEC_CT) & 0x7F] = SHIFTED; //DSP->TEMP[(op.TWA + DSP->MDEC_CT) & 0x7F] = SHIFTED;
Ldr(r2, dsp_operand(&DSP->SHIFTED)); Ldr(r2, dsp_operand(&DSP->SHIFTED));
Ldr(r1, dsp_operand(&DSP->regs.MDEC_CT)); Ldr(r1, dsp_operand(&DSP->MDEC_CT));
if (op.TWA) if (op.TWA)
Add(r1, r1, op.TWA); Add(r1, r1, op.TWA);
Bfc(r1, 7, 25); Bfc(r1, 7, 25);
@ -279,13 +282,13 @@ public:
Str(r1, dspdata_operand(DSPData->EFREG, op.EWA)); Str(r1, dspdata_operand(DSPData->EFREG, op.EWA));
} }
} }
Ldr(r1, dsp_operand(&DSP->regs.MDEC_CT)); Ldr(r1, dsp_operand(&DSP->MDEC_CT));
// DSP->regs.MDEC_CT-- // DSP->MDEC_CT--
Subs(r1, r1, 1); Subs(r1, r1, 1);
//if (dsp.regs.MDEC_CT == 0) //if (dsp.MDEC_CT == 0)
// dsp.regs.MDEC_CT = dsp.RBL + 1; // RBL is ring buffer length - 1 // dsp.MDEC_CT = dsp.RBL + 1; // RBL is ring buffer length - 1
Mov(eq, r1, dsp.RBL + 1); Mov(eq, r1, DSP->RBL + 1);
Str(r1, dsp_operand(&DSP->regs.MDEC_CT)); Str(r1, dsp_operand(&DSP->MDEC_CT));
Pop(regList); Pop(regList);
Mov(pc, lr); Mov(pc, lr);
@ -300,7 +303,7 @@ public:
private: private:
MemOperand dsp_operand(void *data, int index = 0, u32 element_size = 4) MemOperand dsp_operand(void *data, int index = 0, u32 element_size = 4)
{ {
ptrdiff_t offset = ((u8*)data - (u8*)DSP) - offsetof(dsp_t, TEMP) + index * element_size; ptrdiff_t offset = ((u8*)data - (u8*)DSP) - offsetof(DSPState, TEMP) + index * element_size;
if (offset <= 4095) if (offset <= 4095)
return MemOperand(r8, offset); return MemOperand(r8, offset);
Mov(r0, offset); Mov(r0, offset);
@ -309,7 +312,7 @@ private:
MemOperand dsp_operand(void *data, const Register& offset_reg, u32 element_size = 4) MemOperand dsp_operand(void *data, const Register& offset_reg, u32 element_size = 4)
{ {
ptrdiff_t offset = ((u8*)data - (u8*)DSP) - offsetof(dsp_t, TEMP); ptrdiff_t offset = ((u8*)data - (u8*)DSP) - offsetof(DSPState, TEMP);
if (offset == 0) if (offset == 0)
return MemOperand(r8, offset_reg, LSL, element_size == 4 ? 2 : element_size == 2 ? 1 : 0); return MemOperand(r8, offset_reg, LSL, element_size == 4 ? 2 : element_size == 2 ? 1 : 0);
@ -344,7 +347,7 @@ private:
} }
} }
void calculateADDR(const Register& ADDR, const _INST& op) void calculateADDR(const Register& ADDR, const Instruction& op)
{ {
//u32 ADDR = DSPData->MADRS[op.MASA]; //u32 ADDR = DSPData->MADRS[op.MASA];
Ldr(ADDR, dspdata_operand(DSPData->MADRS, op.MASA)); Ldr(ADDR, dspdata_operand(DSPData->MADRS, op.MASA));
@ -360,8 +363,8 @@ private:
Add(ADDR, ADDR, 1); Add(ADDR, ADDR, 1);
if (!op.TABLE) if (!op.TABLE)
{ {
//ADDR += DSP->regs.MDEC_CT; //ADDR += DSP->MDEC_CT;
Ldr(r1, dsp_operand(&DSP->regs.MDEC_CT)); Ldr(r1, dsp_operand(&DSP->MDEC_CT));
Add(ADDR, ADDR, r1); Add(ADDR, ADDR, r1);
//ADDR &= DSP->RBL; //ADDR &= DSP->RBL;
// RBL is constant for this program // RBL is constant for this program
@ -387,40 +390,30 @@ private:
uintptr_t getAicaRam() uintptr_t getAicaRam()
{ {
return (uintptr_t)&aica_ram[0]; return reinterpret_cast<uintptr_t>(&aica_ram[0]);
} }
dsp_t *DSP = nullptr; DSPState *DSP = nullptr;
}; };
void dsp_recompile() void recompile()
{ {
dsp.Stopped = true;
for (int i = 127; i >= 0; --i)
{
u32 *IPtr = DSPData->MPRO + i * 4;
if (IPtr[0] != 0 || IPtr[1] != 0 || IPtr[2 ]!= 0 || IPtr[3] != 0)
{
dsp.Stopped = false;
break;
}
}
JITWriteProtect(false); JITWriteProtect(false);
DSPAssembler assembler(DynCode, CodeSize); DSPAssembler assembler(DynCode, CodeSize);
assembler.compile(&dsp); assembler.compile(&state);
JITWriteProtect(true); JITWriteProtect(true);
} }
void dsp_rec_init() void recInit()
{ {
u8 *pCodeBuffer; u8 *pCodeBuffer;
verify(vmem_platform_prepare_jit_block(DynCode, CodeSize, (void**)&pCodeBuffer)); verify(vmem_platform_prepare_jit_block(DynCode, CodeSize, (void**)&pCodeBuffer));
} }
void dsp_rec_step() void runStep()
{ {
((void (*)())(DynCode))(); ((void (*)())DynCode)();
} }
}
#endif #endif

View File

@ -28,6 +28,9 @@
#include <aarch64/macro-assembler-aarch64.h> #include <aarch64/macro-assembler-aarch64.h>
using namespace vixl::aarch64; using namespace vixl::aarch64;
namespace dsp
{
constexpr size_t CodeSize = 4096 * 8; //32 kb, 8 pages constexpr size_t CodeSize = 4096 * 8; //32 kb, 8 pages
#if defined(__unix__) || defined(__SWITCH__) #if defined(__unix__) || defined(__SWITCH__)
@ -62,13 +65,11 @@ class DSPAssembler : public MacroAssembler
public: public:
DSPAssembler(u8 *code_buffer, size_t size) : MacroAssembler(code_buffer, size), aica_ram_lit(NULL) {} DSPAssembler(u8 *code_buffer, size_t size) : MacroAssembler(code_buffer, size), aica_ram_lit(NULL) {}
void Compile(struct dsp_t *DSP) void Compile(DSPState *DSP)
{ {
this->DSP = DSP; this->DSP = DSP;
DEBUG_LOG(AICA_ARM, "DSPAssembler::DSPCompile recompiling for arm64 at %p", GetBuffer()->GetStartAddress<void*>()); DEBUG_LOG(AICA_ARM, "DSPAssembler::DSPCompile recompiling for arm64 at %p", GetBuffer()->GetStartAddress<void*>());
Instruction* instr_start = GetBuffer()->GetStartAddress<Instruction*>();
Stp(x29, x30, MemOperand(sp, -96, PreIndex)); Stp(x29, x30, MemOperand(sp, -96, PreIndex));
Stp(x21, x22, MemOperand(sp, 16)); Stp(x21, x22, MemOperand(sp, 16));
Stp(x23, x24, MemOperand(sp, 32)); Stp(x23, x24, MemOperand(sp, 32));
@ -93,18 +94,12 @@ public:
Mov(FRC_REG, 0); Mov(FRC_REG, 0);
Mov(Y_REG, 0); Mov(Y_REG, 0);
Mov(ADRS_REG, 0); Mov(ADRS_REG, 0);
Ldr(MDEC_CT, dsp_operand(&DSP->regs.MDEC_CT)); Ldr(MDEC_CT, dsp_operand(&DSP->MDEC_CT));
#if 0
Instruction* instr_cur = GetBuffer()->GetEndAddress<Instruction*>();
DEBUG_LOG(AICA_ARM, "DSP PROLOGUE");
Disassemble(instr_start, instr_cur);
instr_start = instr_cur;
#endif
for (int step = 0; step < 128; ++step) for (int step = 0; step < 128; ++step)
{ {
u32 *mpro = &DSPData->MPRO[step * 4]; u32 *mpro = &DSPData->MPRO[step * 4];
_INST op; Instruction op;
DecodeInst(mpro, &op); DecodeInst(mpro, &op);
const u32 COEF = step; const u32 COEF = step;
@ -147,7 +142,7 @@ public:
Mov(B, ACC); Mov(B, ACC);
else else
{ {
//B = DSP->TEMP[(TRA + DSP->regs.MDEC_CT) & 0x7F]; //B = DSP->TEMP[(TRA + DSP->MDEC_CT) & 0x7F];
if (op.TRA) if (op.TRA)
Add(w1, MDEC_CT, op.TRA); Add(w1, MDEC_CT, op.TRA);
else else
@ -167,7 +162,7 @@ public:
X_alias = &INPUTS; X_alias = &INPUTS;
else else
{ {
//X = DSP->TEMP[(TRA + DSP->regs.MDEC_CT) & 0x7F]; //X = DSP->TEMP[(TRA + DSP->MDEC_CT) & 0x7F];
if (!op.ZERO && !op.BSEL && !op.NEGB) if (!op.ZERO && !op.BSEL && !op.NEGB)
X_alias = &B; X_alias = &B;
else else
@ -259,7 +254,7 @@ public:
if (op.TWT) if (op.TWT)
{ {
//DSP->TEMP[(op.TWA + DSP->regs.MDEC_CT) & 0x7F] = SHIFTED; //DSP->TEMP[(op.TWA + DSP->MDEC_CT) & 0x7F] = SHIFTED;
if (op.TWA) if (op.TWA)
Add(w1, MDEC_CT, op.TWA); Add(w1, MDEC_CT, op.TWA);
else else
@ -323,20 +318,14 @@ public:
Asr(w1, SHIFTED, 8); Asr(w1, SHIFTED, 8);
Str(w1, mem_operand); Str(w1, mem_operand);
} }
#if 0
instr_cur = GetBuffer()->GetEndAddress<Instruction*>();
DEBUG_LOG(AICA_ARM, "DSP STEP %d: %04x %04x %04x %04x", step, mpro[0], mpro[1], mpro[2], mpro[3]);
Disassemble(instr_start, instr_cur);
instr_start = instr_cur;
#endif
} }
// DSP->regs.MDEC_CT-- // DSP->MDEC_CT--
Subs(MDEC_CT, MDEC_CT, 1); Subs(MDEC_CT, MDEC_CT, 1);
//if (dsp.regs.MDEC_CT == 0) //if (dsp.MDEC_CT == 0)
// dsp.regs.MDEC_CT = dsp.RBL + 1; // RBL is ring buffer length - 1 // dsp.MDEC_CT = dsp.RBL + 1; // RBL is ring buffer length - 1
Mov(w0, dsp.RBL + 1); Mov(w0, DSP->RBL + 1);
Csel(MDEC_CT, w0, MDEC_CT, eq); Csel(MDEC_CT, w0, MDEC_CT, eq);
Str(MDEC_CT, dsp_operand(&DSP->regs.MDEC_CT)); Str(MDEC_CT, dsp_operand(&DSP->MDEC_CT));
Ldp(x21, x22, MemOperand(sp, 16)); Ldp(x21, x22, MemOperand(sp, 16));
Ldp(x23, x24, MemOperand(sp, 32)); Ldp(x23, x24, MemOperand(sp, 32));
@ -345,12 +334,7 @@ public:
Ldp(x19, x20, MemOperand(sp, 80)); Ldp(x19, x20, MemOperand(sp, 80));
Ldp(x29, x30, MemOperand(sp, 96, PostIndex)); Ldp(x29, x30, MemOperand(sp, 96, PostIndex));
Ret(); Ret();
#if 0
instr_cur = GetBuffer()->GetEndAddress<Instruction*>();
DEBUG_LOG(AICA_ARM, "DSP EPILOGUE");
Disassemble(instr_start, instr_cur);
instr_start = instr_cur;
#endif
FinalizeCode(); FinalizeCode();
vmem_platform_flush_cache( vmem_platform_flush_cache(
@ -361,7 +345,7 @@ public:
private: private:
MemOperand dsp_operand(void *data, int index = 0, u32 element_size = 4) MemOperand dsp_operand(void *data, int index = 0, u32 element_size = 4)
{ {
ptrdiff_t offset = ((u8*)data - (u8*)DSP) - offsetof(dsp_t, TEMP) + index * element_size; ptrdiff_t offset = ((u8*)data - (u8*)DSP) - offsetof(DSPState, TEMP) + index * element_size;
if (offset < 16384) if (offset < 16384)
return MemOperand(x28, offset); return MemOperand(x28, offset);
Mov(x0, offset); Mov(x0, offset);
@ -370,7 +354,7 @@ private:
MemOperand dsp_operand(void *data, const Register& offset_reg, u32 element_size = 4) MemOperand dsp_operand(void *data, const Register& offset_reg, u32 element_size = 4)
{ {
ptrdiff_t offset = ((u8*)data - (u8*)DSP) - offsetof(dsp_t, TEMP); ptrdiff_t offset = ((u8*)data - (u8*)DSP) - offsetof(DSPState, TEMP);
if (offset == 0) if (offset == 0)
return MemOperand(x28, offset_reg, LSL, element_size == 4 ? 2 : element_size == 2 ? 1 : 0); return MemOperand(x28, offset_reg, LSL, element_size == 4 ? 2 : element_size == 2 ? 1 : 0);
@ -406,7 +390,7 @@ private:
} }
} }
void CalculateADDR(const Register& ADDR, const _INST& op, const Register& ADRS_REG, const Register& MDEC_CT) void CalculateADDR(const Register& ADDR, const Instruction& op, const Register& ADRS_REG, const Register& MDEC_CT)
{ {
//u32 ADDR = DSPData->MADRS[op.MASA]; //u32 ADDR = DSPData->MADRS[op.MASA];
Ldr(ADDR, dspdata_operand(DSPData->MADRS, op.MASA)); Ldr(ADDR, dspdata_operand(DSPData->MADRS, op.MASA));
@ -421,7 +405,7 @@ private:
Add(ADDR, ADDR, 1); Add(ADDR, ADDR, 1);
if (!op.TABLE) if (!op.TABLE)
{ {
//ADDR += DSP->regs.MDEC_CT; //ADDR += DSP->MDEC_CT;
Add(ADDR, ADDR, MDEC_CT); Add(ADDR, ADDR, MDEC_CT);
//ADDR &= DSP->RBL; //ADDR &= DSP->RBL;
// RBL is constant for this program // RBL is constant for this program
@ -452,42 +436,19 @@ private:
return aica_ram_lit; return aica_ram_lit;
} }
void Disassemble(Instruction* instr_start, Instruction* instr_end) DSPState *DSP;
{
Decoder decoder;
Disassembler disasm;
decoder.AppendVisitor(&disasm);
Instruction* instr;
for (instr = instr_start; instr < instr_end; instr += kInstructionSize) {
decoder.Decode(instr);
DEBUG_LOG(AICA_ARM, " %p:\t%s", reinterpret_cast<void*>(instr), disasm.GetOutput());
}
}
struct dsp_t *DSP;
Literal<u8*> *aica_ram_lit; Literal<u8*> *aica_ram_lit;
}; };
void dsp_recompile() void recompile()
{ {
dsp.Stopped = true;
for (int i = 127; i >= 0; --i)
{
u32 *IPtr = DSPData->MPRO + i * 4;
if (IPtr[0] != 0 || IPtr[1] != 0 || IPtr[2 ]!= 0 || IPtr[3] != 0)
{
dsp.Stopped = false;
break;
}
}
JITWriteProtect(false); JITWriteProtect(false);
DSPAssembler assembler(pCodeBuffer, CodeSize); DSPAssembler assembler(pCodeBuffer, CodeSize);
assembler.Compile(&dsp); assembler.Compile(&state);
JITWriteProtect(true); JITWriteProtect(true);
} }
void dsp_rec_init() void recInit()
{ {
#ifdef FEAT_NO_RWX_PAGES #ifdef FEAT_NO_RWX_PAGES
verify(vmem_platform_prepare_jit_block(DynCode, CodeSize, (void**)&pCodeBuffer, &rx_offset)); verify(vmem_platform_prepare_jit_block(DynCode, CodeSize, (void**)&pCodeBuffer, &rx_offset));
@ -500,8 +461,10 @@ void dsp_rec_init()
#endif #endif
} }
void dsp_rec_step() void runStep()
{ {
((void (*)())(DynCode))(); ((void (*)())DynCode)();
}
} }
#endif #endif

View File

@ -13,21 +13,14 @@
#include "aica.h" #include "aica.h"
#include "aica_if.h" #include "aica_if.h"
#ifdef NDEBUG namespace dsp
#undef verify
#define verify(...)
#endif
void AICADSP_Init(struct dsp_t *DSP)
{ {
memset(DSP, 0, sizeof(*DSP));
DSP->RBL = 0x8000 - 1;
DSP->Stopped = 1;
dsp.regs.MDEC_CT = 1;
}
void AICADSP_Step(struct dsp_t *DSP) void runStep()
{ {
if (state.stopped)
return;
s32 ACC = 0; //26 bit s32 ACC = 0; //26 bit
s32 SHIFTED = 0; //24 bit s32 SHIFTED = 0; //24 bit
s32 X = 0; //24 bit s32 X = 0; //24 bit
@ -39,16 +32,6 @@ void AICADSP_Step(struct dsp_t *DSP)
s32 Y_REG = 0; //24 bit s32 Y_REG = 0; //24 bit
u32 ADRS_REG = 0; //13 bit u32 ADRS_REG = 0; //13 bit
if (DSP->Stopped)
return;
#if 0
int dump = 0;
FILE *f = NULL;
if (dump)
f = fopen("dsp.txt", "wt");
#endif
for (int step = 0; step < 128; ++step) for (int step = 0; step < 128; ++step)
{ {
u32 *IPtr = DSPData->MPRO + step * 4; u32 *IPtr = DSPData->MPRO + step * 4;
@ -56,7 +39,7 @@ void AICADSP_Step(struct dsp_t *DSP)
if (IPtr[0] == 0 && IPtr[1] == 0 && IPtr[2] == 0 && IPtr[3] == 0) if (IPtr[0] == 0 && IPtr[1] == 0 && IPtr[2] == 0 && IPtr[3] == 0)
{ {
// Empty instruction shortcut // Empty instruction shortcut
X = DSP->TEMP[DSP->regs.MDEC_CT & 0x7F]; X = state.TEMP[state.MDEC_CT & 0x7F];
Y = FRC_REG; Y = FRC_REG;
ACC = (((s64)X * (s64)Y) >> 12) + X; ACC = (((s64)X * (s64)Y) >> 12) + X;
@ -84,29 +67,12 @@ void AICADSP_Step(struct dsp_t *DSP)
u32 COEF = step; u32 COEF = step;
// operations are done at 24 bit precision // operations are done at 24 bit precision
#if 0
#define DUMP(v) printf(" " #v ": %04X",v);
printf("%d: ",step);
DUMP(ACC);
DUMP(SHIFTED);
DUMP(X);
DUMP(Y);
DUMP(B);
DUMP(INPUTS);
DUMP(MEMVAL);
DUMP(FRC_REG);
DUMP(Y_REG);
DUMP(ADDR);
DUMP(ADRS_REG);
printf("\n");
#endif
// INPUTS RW // INPUTS RW
if (IRA <= 0x1f) if (IRA <= 0x1f)
INPUTS = DSP->MEMS[IRA]; INPUTS = state.MEMS[IRA];
else if (IRA <= 0x2F) else if (IRA <= 0x2F)
INPUTS = DSP->MIXS[IRA - 0x20] << 4; // MIXS is 20 bit INPUTS = state.MIXS[IRA - 0x20] << 4; // MIXS is 20 bit
else if (IRA <= 0x31) else if (IRA <= 0x31)
INPUTS = DSPData->EXTS[IRA - 0x30] << 8; // EXTS is 16 bits INPUTS = DSPData->EXTS[IRA - 0x30] << 8; // EXTS is 16 bits
else else
@ -115,7 +81,7 @@ void AICADSP_Step(struct dsp_t *DSP)
if (IWT) if (IWT)
{ {
u32 IWA = (IPtr[1] >> 1) & 0x1F; u32 IWA = (IPtr[1] >> 1) & 0x1F;
DSP->MEMS[IWA] = MEMVAL[step & 3]; // MEMVAL was selected in previous MRD state.MEMS[IWA] = MEMVAL[step & 3]; // MEMVAL was selected in previous MRD
} }
// Operand sel // Operand sel
@ -125,7 +91,7 @@ void AICADSP_Step(struct dsp_t *DSP)
if (BSEL) if (BSEL)
B = ACC; B = ACC;
else else
B = DSP->TEMP[(TRA + DSP->regs.MDEC_CT) & 0x7F]; B = state.TEMP[(TRA + state.MDEC_CT) & 0x7F];
if (NEGB) if (NEGB)
B = -B; B = -B;
} }
@ -138,7 +104,7 @@ void AICADSP_Step(struct dsp_t *DSP)
if (XSEL) if (XSEL)
X = INPUTS; X = INPUTS;
else else
X = DSP->TEMP[(TRA + DSP->regs.MDEC_CT) & 0x7F]; X = state.TEMP[(TRA + state.MDEC_CT) & 0x7F];
// Y // Y
if (YSEL == 0) if (YSEL == 0)
@ -169,7 +135,7 @@ void AICADSP_Step(struct dsp_t *DSP)
if (TWT) if (TWT)
{ {
u32 TWA = (IPtr[0] >> 1) & 0x7F; u32 TWA = (IPtr[0] >> 1) & 0x7F;
DSP->TEMP[(TWA + DSP->regs.MDEC_CT) & 0x7F] = SHIFTED; state.TEMP[(TWA + state.MDEC_CT) & 0x7F] = SHIFTED;
} }
if (FRCL) if (FRCL)
@ -202,14 +168,14 @@ void AICADSP_Step(struct dsp_t *DSP)
ADDR++; ADDR++;
if (!TABLE) if (!TABLE)
{ {
ADDR += DSP->regs.MDEC_CT; ADDR += state.MDEC_CT;
ADDR &= DSP->RBL; // RBL is ring buffer length - 1 ADDR &= state.RBL; // RBL is ring buffer length - 1
} }
else else
ADDR &= 0xFFFF; ADDR &= 0xFFFF;
ADDR <<= 1; // Word -> byte address ADDR <<= 1; // Word -> byte address
ADDR += DSP->RBP; // RBP is already a byte address ADDR += state.RBP; // RBP is already a byte address
if (MRD) // memory only allowed on odd. DoA inserts NOPs on even if (MRD) // memory only allowed on odd. DoA inserts NOPs on even
{ {
//if (NOFL) //if (NOFL)
@ -243,64 +209,10 @@ void AICADSP_Step(struct dsp_t *DSP)
} }
} }
--DSP->regs.MDEC_CT; --state.MDEC_CT;
if (dsp.regs.MDEC_CT == 0) if (state.MDEC_CT == 0)
dsp.regs.MDEC_CT = dsp.RBL + 1; // RBL is ring buffer length - 1 state.MDEC_CT = state.RBL + 1; // RBL is ring buffer length - 1
// memset(DSP->MIXS, 0, sizeof(DSP->MIXS));
// if(f)
// fclose(f);
} }
void AICADSP_Start(struct dsp_t *DSP)
{
dsp.Stopped = 1;
for (int i = 127; i >= 0; --i)
{
u32 *IPtr = DSPData->MPRO + i * 4;
if (IPtr[0] != 0 || IPtr[1] != 0 || IPtr[2 ]!= 0 || IPtr[3] != 0)
{
DSP->Stopped = 0;
//printf("DSP: starting %d steps\n", i + 1);
break;
}
}
} }
void dsp_init()
{
AICADSP_Init(&dsp);
AICADSP_Start(&dsp);
}
void dsp_term()
{
dsp.Stopped = 1;
}
void dsp_step()
{
AICADSP_Step(&dsp);
}
void dsp_writenmem(u32 addr)
{
if (addr >= 0x3400 && addr < 0x3C00)
{
AICADSP_Start(&dsp);
}
else if (addr >= 0x4000 && addr < 0x4400)
{
// TODO proper sharing of memory with sh4 through DSPData
memset(dsp.TEMP, 0, sizeof(dsp.TEMP));
}
else if (addr >= 0x4400 && addr < 0x4500)
{
// TODO proper sharing of memory with sh4 through DSPData
memset(dsp.MEMS, 0, sizeof(dsp.MEMS));
}
}
#endif #endif

View File

@ -27,8 +27,8 @@
#include "aica_if.h" #include "aica_if.h"
#include "hw/mem/_vmem.h" #include "hw/mem/_vmem.h"
#define CC_RW2RX(ptr) (ptr) namespace dsp
#define CC_RX2RW(ptr) (ptr) {
alignas(4096) static u8 CodeBuffer[32 * 1024] alignas(4096) static u8 CodeBuffer[32 * 1024]
#if defined(_WIN32) #if defined(_WIN32)
@ -41,13 +41,14 @@ alignas(4096) static u8 CodeBuffer[32 * 1024]
#error CodeBuffer code section unknown #error CodeBuffer code section unknown
#endif #endif
static u8 *pCodeBuffer; static u8 *pCodeBuffer;
static ptrdiff_t rx_offset;
class X64DSPAssembler : public Xbyak::CodeGenerator class X64DSPAssembler : public Xbyak::CodeGenerator
{ {
public: public:
X64DSPAssembler(u8 *code_buffer, size_t size) : Xbyak::CodeGenerator(size, code_buffer) {} X64DSPAssembler(u8 *code_buffer, size_t size) : Xbyak::CodeGenerator(size, code_buffer) {}
void Compile(struct dsp_t *DSP) void Compile(DSPState *DSP)
{ {
this->DSP = DSP; this->DSP = DSP;
DEBUG_LOG(AICA_ARM, "DSPAssembler::DSPCompile recompiling for x86/64 at %p", this->getCode()); DEBUG_LOG(AICA_ARM, "DSPAssembler::DSPCompile recompiling for x86/64 at %p", this->getCode());
@ -83,12 +84,12 @@ public:
mov(dword[rbx + dsp_operand(&DSP->FRC_REG)], 0); mov(dword[rbx + dsp_operand(&DSP->FRC_REG)], 0);
xor_(Y_REG, Y_REG); xor_(Y_REG, Y_REG);
xor_(ADRS_REG, ADRS_REG); xor_(ADRS_REG, ADRS_REG);
mov(MDEC_CT, dword[rbx + dsp_operand(&DSP->regs.MDEC_CT)]); mov(MDEC_CT, dword[rbx + dsp_operand(&DSP->MDEC_CT)]);
for (int step = 0; step < 128; ++step) for (int step = 0; step < 128; ++step)
{ {
u32 *mpro = &DSPData->MPRO[step * 4]; u32 *mpro = &DSPData->MPRO[step * 4];
_INST op; Instruction op;
DecodeInst(mpro, &op); DecodeInst(mpro, &op);
const u32 COEF = step; const u32 COEF = step;
@ -131,7 +132,7 @@ public:
mov(B, ACC); mov(B, ACC);
else else
{ {
//B = DSP->TEMP[(TRA + DSP->regs.MDEC_CT) & 0x7F]; //B = DSP->TEMP[(TRA + DSP->MDEC_CT) & 0x7F];
mov(eax, MDEC_CT); mov(eax, MDEC_CT);
if (op.TRA) if (op.TRA)
add(eax, op.TRA); add(eax, op.TRA);
@ -150,7 +151,7 @@ public:
X_alias = INPUTS; X_alias = INPUTS;
else else
{ {
//X = DSP->TEMP[(TRA + DSP->regs.MDEC_CT) & 0x7F]; //X = DSP->TEMP[(TRA + DSP->MDEC_CT) & 0x7F];
if (!op.ZERO && !op.BSEL && !op.NEGB) if (!op.ZERO && !op.BSEL && !op.NEGB)
X_alias = B; X_alias = B;
else else
@ -247,7 +248,7 @@ public:
if (op.TWT) if (op.TWT)
{ {
//DSP->TEMP[(op.TWA + DSP->regs.MDEC_CT) & 0x7F] = SHIFTED; //DSP->TEMP[(op.TWA + DSP->MDEC_CT) & 0x7F] = SHIFTED;
mov(ecx, MDEC_CT); mov(ecx, MDEC_CT);
if (op.TWA) if (op.TWA)
add(ecx, op.TWA); add(ecx, op.TWA);
@ -328,13 +329,13 @@ public:
mov(dword[rbp + dspdata_operand(DSPData->EFREG, op.EWA)], edx); mov(dword[rbp + dspdata_operand(DSPData->EFREG, op.EWA)], edx);
} }
} }
// DSP->regs.MDEC_CT-- // DSP->MDEC_CT--
mov(eax, dsp.RBL + 1); mov(eax, DSP->RBL + 1);
sub(MDEC_CT, 1); sub(MDEC_CT, 1);
//if (dsp.regs.MDEC_CT == 0) //if (dsp.MDEC_CT == 0)
// dsp.regs.MDEC_CT = dsp.RBL + 1; // RBL is ring buffer length - 1 // dsp.MDEC_CT = dsp.RBL + 1; // RBL is ring buffer length - 1
cmove(MDEC_CT, eax); cmove(MDEC_CT, eax);
mov(dword[rbx + dsp_operand(&DSP->regs.MDEC_CT)], MDEC_CT); mov(dword[rbx + dsp_operand(&DSP->MDEC_CT)], MDEC_CT);
#ifdef _WIN32 #ifdef _WIN32
add(rsp, 40); add(rsp, 40);
@ -355,14 +356,14 @@ public:
private: private:
ptrdiff_t dsp_operand(void *data, int index = 0, u32 element_size = 4) ptrdiff_t dsp_operand(void *data, int index = 0, u32 element_size = 4)
{ {
return ((u8*)data - (u8*)DSP) - offsetof(dsp_t, TEMP) + index * element_size; return ((u8*)data - (u8*)DSP) - offsetof(DSPState, TEMP) + index * element_size;
} }
ptrdiff_t dspdata_operand(void *data, int index = 0, u32 element_size = 4) ptrdiff_t dspdata_operand(void *data, int index = 0, u32 element_size = 4)
{ {
return ((u8*)data - (u8*)DSPData) + index * element_size; return ((u8*)data - (u8*)DSPData) + index * element_size;
} }
void CalculateADDR(const Xbyak::Reg32 ADDR, const _INST& op, const Xbyak::Reg32 ADRS_REG, const Xbyak::Reg32 MDEC_CT) void CalculateADDR(const Xbyak::Reg32 ADDR, const Instruction& op, const Xbyak::Reg32 ADRS_REG, const Xbyak::Reg32 MDEC_CT)
{ {
//u32 ADDR = DSPData->MADRS[op.MASA]; //u32 ADDR = DSPData->MADRS[op.MASA];
mov(ADDR, dword[rbp + dspdata_operand(DSPData->MADRS, op.MASA)]); mov(ADDR, dword[rbp + dspdata_operand(DSPData->MADRS, op.MASA)]);
@ -378,7 +379,7 @@ private:
add(ADDR, 1); add(ADDR, 1);
if (!op.TABLE) if (!op.TABLE)
{ {
//ADDR += DSP->regs.MDEC_CT; //ADDR += DSP->MDEC_CT;
add(ADDR, MDEC_CT); add(ADDR, MDEC_CT);
//ADDR &= DSP->RBL; //ADDR &= DSP->RBL;
// RBL is constant for this program // RBL is constant for this program
@ -400,37 +401,32 @@ private:
template<class Ret, class... Params> template<class Ret, class... Params>
void GenCall(Ret(*function)(Params...)) void GenCall(Ret(*function)(Params...))
{ {
call(CC_RX2RW(function)); call(reinterpret_cast<void *>(reinterpret_cast<uintptr_t>(function) - rx_offset));
} }
struct dsp_t *DSP = nullptr; DSPState *DSP = nullptr;
}; };
void dsp_recompile() void recompile()
{ {
dsp.Stopped = true;
for (int i = 127; i >= 0; --i)
{
u32 *IPtr = DSPData->MPRO + i * 4;
if (IPtr[0] != 0 || IPtr[1] != 0 || IPtr[2 ]!= 0 || IPtr[3] != 0)
{
dsp.Stopped = false;
break;
}
}
X64DSPAssembler assembler(pCodeBuffer, sizeof(CodeBuffer)); X64DSPAssembler assembler(pCodeBuffer, sizeof(CodeBuffer));
assembler.Compile(&dsp); assembler.Compile(&state);
} }
void dsp_rec_init() void recInit()
{ {
#ifdef FEAT_NO_RWX_PAGES
if (!vmem_platform_prepare_jit_block(CodeBuffer, sizeof(CodeBuffer), (void**)&pCodeBuffer, &rx_offset))
#else
if (!vmem_platform_prepare_jit_block(CodeBuffer, sizeof(CodeBuffer), (void**)&pCodeBuffer)) if (!vmem_platform_prepare_jit_block(CodeBuffer, sizeof(CodeBuffer), (void**)&pCodeBuffer))
die("mprotect failed in x64 dsp"); #endif
die("vmem_platform_prepare_jit_block failed in x64 dsp");
} }
void dsp_rec_step() void runStep()
{ {
((void (*)())&pCodeBuffer[0])(); ((void (*)())CodeBuffer)();
}
} }
#endif #endif

View File

@ -27,8 +27,8 @@
#include "aica_if.h" #include "aica_if.h"
#include "hw/mem/_vmem.h" #include "hw/mem/_vmem.h"
#define CC_RW2RX(ptr) (ptr) namespace dsp
#define CC_RX2RW(ptr) (ptr) {
alignas(4096) static u8 CodeBuffer[32 * 1024] alignas(4096) static u8 CodeBuffer[32 * 1024]
#if defined(_WIN32) #if defined(_WIN32)
@ -47,7 +47,7 @@ class X86DSPAssembler : public Xbyak::CodeGenerator
public: public:
X86DSPAssembler(u8 *code_buffer, size_t size) : Xbyak::CodeGenerator(size, code_buffer) {} X86DSPAssembler(u8 *code_buffer, size_t size) : Xbyak::CodeGenerator(size, code_buffer) {}
void Compile(struct dsp_t *DSP) void Compile(DSPState *DSP)
{ {
this->DSP = DSP; this->DSP = DSP;
DEBUG_LOG(AICA_ARM, "X86DSPAssembler::Compile recompiling for x86 at %p", this->getCode()); DEBUG_LOG(AICA_ARM, "X86DSPAssembler::Compile recompiling for x86 at %p", this->getCode());
@ -73,7 +73,7 @@ public:
for (int step = 0; step < 128; ++step) for (int step = 0; step < 128; ++step)
{ {
u32 *mpro = &DSPData->MPRO[step * 4]; u32 *mpro = &DSPData->MPRO[step * 4];
_INST op; Instruction op;
DecodeInst(mpro, &op); DecodeInst(mpro, &op);
const u32 COEF = step; const u32 COEF = step;
@ -116,8 +116,8 @@ public:
mov(dword[&DSP->B], ACC); mov(dword[&DSP->B], ACC);
else else
{ {
//B = DSP->TEMP[(TRA + DSP->regs.MDEC_CT) & 0x7F]; //B = DSP->TEMP[(TRA + DSP->MDEC_CT) & 0x7F];
mov(eax, dword[&DSP->regs.MDEC_CT]); mov(eax, dword[&DSP->MDEC_CT]);
if (op.TRA) if (op.TRA)
add(eax, op.TRA); add(eax, op.TRA);
and_(eax, 0x7f); and_(eax, 0x7f);
@ -136,12 +136,12 @@ public:
X_alias = INPUTS; X_alias = INPUTS;
else else
{ {
//X = DSP->TEMP[(TRA + DSP->regs.MDEC_CT) & 0x7F]; //X = DSP->TEMP[(TRA + DSP->MDEC_CT) & 0x7F];
if (!op.ZERO && !op.BSEL && !op.NEGB) if (!op.ZERO && !op.BSEL && !op.NEGB)
mov(X, dword[&DSP->B]); mov(X, dword[&DSP->B]);
else else
{ {
mov(eax, dword[&DSP->regs.MDEC_CT]); mov(eax, dword[&DSP->MDEC_CT]);
if (op.TRA) if (op.TRA)
add(eax, op.TRA); add(eax, op.TRA);
and_(eax, 0x7f); and_(eax, 0x7f);
@ -233,8 +233,8 @@ public:
if (op.TWT) if (op.TWT)
{ {
//DSP->TEMP[(op.TWA + DSP->regs.MDEC_CT) & 0x7F] = SHIFTED; //DSP->TEMP[(op.TWA + DSP->MDEC_CT) & 0x7F] = SHIFTED;
mov(edx, dword[&DSP->regs.MDEC_CT]); mov(edx, dword[&DSP->MDEC_CT]);
if (op.TWA) if (op.TWA)
add(edx, op.TWA); add(edx, op.TWA);
and_(edx, 0x7f); and_(edx, 0x7f);
@ -265,7 +265,7 @@ public:
{ {
// *(u16 *)&aica_ram[ADDR & ARAM_MASK] = PACK(SHIFTED); // *(u16 *)&aica_ram[ADDR & ARAM_MASK] = PACK(SHIFTED);
// SHIFTED is in ecx // SHIFTED is in ecx
call(CC_RW2RX((const void *)PACK)); call((const void *)PACK);
CalculateADDR(ADDR, op); CalculateADDR(ADDR, op);
mov(ecx, (uintptr_t)&aica_ram[0]); mov(ecx, (uintptr_t)&aica_ram[0]);
@ -277,7 +277,7 @@ public:
CalculateADDR(ADDR, op); CalculateADDR(ADDR, op);
mov(ecx, (uintptr_t)&aica_ram[0]); mov(ecx, (uintptr_t)&aica_ram[0]);
movzx(ecx, word[ecx + ADDR]); movzx(ecx, word[ecx + ADDR]);
call(CC_RW2RX((const void *)UNPACK)); call((const void *)UNPACK);
mov(dword[&DSP->MEMVAL[(step + 2) & 3]], eax); mov(dword[&DSP->MEMVAL[(step + 2) & 3]], eax);
} }
if (op.MRD || op.MWT) if (op.MRD || op.MWT)
@ -310,14 +310,14 @@ public:
mov(dword[&DSPData->EFREG[op.EWA]], ecx); mov(dword[&DSPData->EFREG[op.EWA]], ecx);
} }
} }
// DSP->regs.MDEC_CT-- // DSP->MDEC_CT--
mov(eax, dsp.RBL + 1); mov(eax, DSP->RBL + 1);
mov(ecx, dword[&DSP->regs.MDEC_CT]); mov(ecx, dword[&DSP->MDEC_CT]);
sub(ecx, 1); sub(ecx, 1);
//if (dsp.regs.MDEC_CT == 0) //if (dsp.MDEC_CT == 0)
// dsp.regs.MDEC_CT = dsp.RBL + 1; // RBL is ring buffer length - 1 // dsp.MDEC_CT = dsp.RBL + 1; // RBL is ring buffer length - 1
cmove(ecx, eax); cmove(ecx, eax);
mov(dword[&DSP->regs.MDEC_CT], ecx); mov(dword[&DSP->MDEC_CT], ecx);
#ifndef _WIN32 #ifndef _WIN32
// 16-byte alignment // 16-byte alignment
@ -333,7 +333,7 @@ public:
} }
private: private:
void CalculateADDR(const Xbyak::Reg32 ADDR, const _INST& op) void CalculateADDR(const Xbyak::Reg32 ADDR, const Instruction& op)
{ {
//u32 ADDR = DSPData->MADRS[op.MASA]; //u32 ADDR = DSPData->MADRS[op.MASA];
mov(ADDR, dword[&DSPData->MADRS[op.MASA]]); mov(ADDR, dword[&DSPData->MADRS[op.MASA]]);
@ -349,8 +349,8 @@ private:
add(ADDR, 1); add(ADDR, 1);
if (!op.TABLE) if (!op.TABLE)
{ {
//ADDR += DSP->regs.MDEC_CT; //ADDR += DSP->MDEC_CT;
add(ADDR, dword[&DSP->regs.MDEC_CT]); add(ADDR, dword[&DSP->MDEC_CT]);
//ADDR &= DSP->RBL; //ADDR &= DSP->RBL;
// RBL is constant for this program // RBL is constant for this program
and_(ADDR, DSP->RBL); and_(ADDR, DSP->RBL);
@ -368,34 +368,25 @@ private:
and_(ADDR, ARAM_MASK); and_(ADDR, ARAM_MASK);
} }
struct dsp_t *DSP = nullptr; DSPState *DSP = nullptr;
}; };
void dsp_recompile() void recompile()
{ {
dsp.Stopped = true;
for (int i = 127; i >= 0; --i)
{
u32 *IPtr = DSPData->MPRO + i * 4;
if (IPtr[0] != 0 || IPtr[1] != 0 || IPtr[2 ]!= 0 || IPtr[3] != 0)
{
dsp.Stopped = false;
break;
}
}
X86DSPAssembler assembler(pCodeBuffer, sizeof(CodeBuffer)); X86DSPAssembler assembler(pCodeBuffer, sizeof(CodeBuffer));
assembler.Compile(&dsp); assembler.Compile(&state);
} }
void dsp_rec_init() void recInit()
{ {
if (!vmem_platform_prepare_jit_block(CodeBuffer, sizeof(CodeBuffer), (void**)&pCodeBuffer)) if (!vmem_platform_prepare_jit_block(CodeBuffer, sizeof(CodeBuffer), (void**)&pCodeBuffer))
die("mprotect failed in x86 dsp"); die("mprotect failed in x86 dsp");
} }
void dsp_rec_step() void runStep()
{ {
((void (*)())&pCodeBuffer[0])(); ((void (*)())CodeBuffer)();
}
} }
#endif #endif

View File

@ -711,7 +711,7 @@ struct ChannelEx
//ISEL //ISEL
void UpdateDSPMIX() void UpdateDSPMIX()
{ {
VolMix.DSPOut = &dsp.MIXS[ccd->ISEL]; VolMix.DSPOut = &dsp::state.MIXS[ccd->ISEL];
} }
//TL,DISDL,DIPAN,IMXL //TL,DISDL,DIPAN,IMXL
void UpdateAtts() void UpdateAtts()
@ -1286,12 +1286,12 @@ void sgc_Init()
PLFO_Scales[s][i + 128] = (u32)((1 << 10) * powf(2.0f, limit * i / 128.0f / 1200.0f)); PLFO_Scales[s][i + 128] = (u32)((1 << 10) * powf(2.0f, limit * i / 128.0f / 1200.0f));
} }
dsp_init(); dsp::init();
} }
void sgc_Term() void sgc_Term()
{ {
dsp_term(); dsp::term();
} }
void WriteChannelReg(u32 channel, u32 reg, int size) void WriteChannelReg(u32 channel, u32 reg, int size)
@ -1343,11 +1343,12 @@ void ReadCommonReg(u32 reg,bool byte)
void WriteCommonReg8(u32 reg,u32 data) void WriteCommonReg8(u32 reg,u32 data)
{ {
WriteMemArr<1>(aica_reg, reg, data); WriteMemArr<1>(aica_reg, reg, data);
if (reg==0x2804 || reg==0x2805) if (reg == 0x2804 || reg == 0x2805)
{ {
dsp.RBL = (8192 << CommonData->RBL) - 1; using namespace dsp;
dsp.RBP = (CommonData->RBP * 2048) & ARAM_MASK; state.RBL = (8192 << CommonData->RBL) - 1;
dsp.dyndirty=true; state.RBP = (CommonData->RBP * 2048) & ARAM_MASK;
state.dirty = true;
} }
} }
@ -1409,7 +1410,7 @@ void AICA_Sample32()
no dsp for now -- needs special handling of oDSP for ch paraller version ... no dsp for now -- needs special handling of oDSP for ch paraller version ...
if (config::DSPEnabled) if (config::DSPEnabled)
{ {
dsp_step(); dsp::step();
for (int i=0;i<16;i++) for (int i=0;i<16;i++)
{ {
@ -1463,7 +1464,7 @@ void AICA_Sample()
SampleType mixl,mixr; SampleType mixl,mixr;
mixl = 0; mixl = 0;
mixr = 0; mixr = 0;
memset(dsp.MIXS,0,sizeof(dsp.MIXS)); memset(dsp::state.MIXS, 0, sizeof(dsp::state.MIXS));
ChannelEx::StepAll(mixl,mixr); ChannelEx::StepAll(mixl,mixr);
@ -1491,7 +1492,7 @@ void AICA_Sample()
if (config::DSPEnabled) if (config::DSPEnabled)
{ {
dsp_step(); dsp::step();
for (int i=0;i<16;i++) for (int i=0;i<16;i++)
VOLPAN(*(s16*)&DSPData->EFREG[i], dsp_out_vol[i].EFSDL, dsp_out_vol[i].EFPAN, mixl, mixr); VOLPAN(*(s16*)&DSPData->EFREG[i], dsp_out_vol[i].EFSDL, dsp_out_vol[i].EFPAN, mixl, mixr);

View File

@ -36,9 +36,7 @@ extern bool armFiqEnable;
extern int armMode; extern int armMode;
extern bool Arm7Enabled; extern bool Arm7Enabled;
//./core/hw/aica/dsp.o //./core/hw/aica/aica.o
alignas(4096) extern dsp_t dsp;
extern AicaTimer timers[3]; extern AicaTimer timers[3];
//./core/hw/aica/aica_if.o //./core/hw/aica/aica_if.o
@ -263,7 +261,7 @@ bool dc_serialize(void **data, unsigned int *total_size)
REICAST_S(armMode); REICAST_S(armMode);
REICAST_S(Arm7Enabled); REICAST_S(Arm7Enabled);
REICAST_S(dsp); // FIXME could save 32KB dsp::state.serialize(data, total_size);
for ( i = 0 ; i < 3 ; i++) for ( i = 0 ; i < 3 ; i++)
{ {
@ -496,7 +494,7 @@ static bool dc_unserialize_libretro(void **data, unsigned int *total_size, seria
REICAST_SKIP(1); // holdState REICAST_SKIP(1); // holdState
} }
REICAST_US(dsp); dsp::state.deserialize(data, total_size, version);
for ( i = 0 ; i < 3 ; i++) for ( i = 0 ; i < 3 ; i++)
{ {
@ -904,7 +902,7 @@ bool dc_unserialize(void **data, unsigned int *total_size)
if (version < V5) if (version < V5)
REICAST_SKIP(256 + 3); REICAST_SKIP(256 + 3);
REICAST_US(dsp); dsp::state.deserialize(data, total_size, version);
for ( i = 0 ; i < 3 ; i++) for ( i = 0 ; i < 3 ; i++)
{ {

View File

@ -473,5 +473,6 @@ enum serialize_version_enum {
V15 = 810, V15 = 810,
V16 = 811, V16 = 811,
V17 = 812, V17 = 812,
VCUR_FLYCAST = V17, V18 = 813,
VCUR_FLYCAST = V18,
}; };

View File

@ -51,7 +51,6 @@
#include "hw/pvr/spg.h" #include "hw/pvr/spg.h"
#include "hw/naomi/naomi_cart.h" #include "hw/naomi/naomi_cart.h"
#include "imgread/common.h" #include "imgread/common.h"
#include "hw/aica/dsp.h"
#include "LogManager.h" #include "LogManager.h"
#include "cheats.h" #include "cheats.h"
#include "rend/CustomTexture.h" #include "rend/CustomTexture.h"

View File

@ -31,7 +31,7 @@ TEST_F(SerializeTest, SizeTest)
unsigned int total_size = 0; unsigned int total_size = 0;
void *data = nullptr; void *data = nullptr;
ASSERT_TRUE(dc_serialize(&data, &total_size)); ASSERT_TRUE(dc_serialize(&data, &total_size));
ASSERT_EQ(28220759u, total_size); ASSERT_EQ(28187879u, total_size);
} }