dsp: map TEMP/MEMS/MIXS regs to sh4 and aica address space. Clean up
This commit is contained in:
parent
2a849ccba5
commit
ca17717af7
|
@ -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;
|
||||||
|
|
|
@ -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*)®base[0x2890 + timer*4];
|
data=(AicaTimerData*)®base[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
|
||||||
|
|
|
@ -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()
|
||||||
{
|
{
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
|
@ -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);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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);
|
||||||
|
|
|
@ -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++)
|
||||||
{
|
{
|
||||||
|
|
|
@ -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,
|
||||||
};
|
};
|
||||||
|
|
|
@ -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"
|
||||||
|
|
|
@ -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);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue