2018-07-29 19:47:30 +00:00
|
|
|
#include "dsp.h"
|
2013-12-19 17:10:14 +00:00
|
|
|
|
2014-12-17 06:12:08 +00:00
|
|
|
/*
|
|
|
|
DSP rec_v1
|
|
|
|
|
|
|
|
Tries to emulate a guesstimation of the aica dsp, by directly emitting x86 opcodes.
|
|
|
|
|
|
|
|
This was my first dsp implementation, as implemented for nullDC 1.0.3.
|
|
|
|
|
|
|
|
This was derived from a schematic I drew for the dsp, based on
|
|
|
|
liberal interpretation of known specs, the saturn dsp, digital
|
|
|
|
electronics assumptions, as well as "best-fitted" my typical
|
|
|
|
test game suite.
|
|
|
|
|
|
|
|
|
2019-09-30 13:36:39 +00:00
|
|
|
Initial code by skmp, now part of the reicast project.
|
2014-12-17 06:12:08 +00:00
|
|
|
See LICENSE & COPYRIGHT files further details
|
|
|
|
*/
|
|
|
|
|
2020-02-19 22:20:32 +00:00
|
|
|
alignas(4096) dsp_t dsp;
|
2013-12-19 17:10:14 +00:00
|
|
|
|
2018-07-29 19:47:30 +00:00
|
|
|
//float format is ?
|
|
|
|
u16 DYNACALL PACK(s32 val)
|
|
|
|
{
|
2020-02-26 17:38:05 +00:00
|
|
|
int sign = (val >> 23) & 0x1;
|
|
|
|
u32 temp = (val ^ (val << 1)) & 0xFFFFFF;
|
|
|
|
int exponent = 0;
|
|
|
|
for (int k = 0; k < 12; k++)
|
2018-07-29 19:47:30 +00:00
|
|
|
{
|
|
|
|
if (temp & 0x800000)
|
|
|
|
break;
|
|
|
|
temp <<= 1;
|
|
|
|
exponent += 1;
|
|
|
|
}
|
|
|
|
if (exponent < 12)
|
2019-09-05 09:57:35 +00:00
|
|
|
val <<= exponent;
|
2018-07-29 19:47:30 +00:00
|
|
|
else
|
|
|
|
val <<= 11;
|
2019-09-05 09:57:35 +00:00
|
|
|
val = (val >> 11) & 0x7FF; // avoid sign extension of mantissa
|
2018-07-29 19:47:30 +00:00
|
|
|
val |= sign << 15;
|
|
|
|
val |= exponent << 11;
|
|
|
|
|
|
|
|
return (u16)val;
|
|
|
|
}
|
|
|
|
|
|
|
|
s32 DYNACALL UNPACK(u16 val)
|
|
|
|
{
|
2020-02-26 17:38:05 +00:00
|
|
|
int sign = (val >> 15) & 0x1;
|
|
|
|
int exponent = (val >> 11) & 0xF;
|
|
|
|
int mantissa = val & 0x7FF;
|
|
|
|
s32 uval = mantissa << 11;
|
2019-09-05 09:57:35 +00:00
|
|
|
uval |= sign << 22; // take the sign in bit 22
|
2018-07-29 19:47:30 +00:00
|
|
|
if (exponent > 11)
|
2019-09-05 09:57:35 +00:00
|
|
|
exponent = 11; // cap exponent to 11 for denormals
|
2018-07-29 19:47:30 +00:00
|
|
|
else
|
2019-09-05 09:57:35 +00:00
|
|
|
uval ^= 1 << 22; // reverse bit 22 for normals
|
|
|
|
uval |= sign << 23; // actual sign bit
|
2018-07-29 19:47:30 +00:00
|
|
|
uval <<= 8;
|
|
|
|
uval >>= 8;
|
|
|
|
uval >>= exponent;
|
|
|
|
|
|
|
|
return uval;
|
|
|
|
}
|
|
|
|
|
2021-03-14 19:32:14 +00:00
|
|
|
void DecodeInst(const u32 *IPtr, _INST *i)
|
2019-01-23 20:14:51 +00:00
|
|
|
{
|
2020-08-31 19:53:33 +00:00
|
|
|
i->TRA = (IPtr[0] >> 9) & 0x7F;
|
|
|
|
i->TWT = IPtr[0] & 0x100;
|
|
|
|
i->TWA = (IPtr[0] >> 1) & 0x7F;
|
|
|
|
|
|
|
|
i->XSEL = IPtr[1] & 0x8000;
|
|
|
|
i->YSEL = (IPtr[1] >> 13) & 3;
|
|
|
|
i->IRA = (IPtr[1] >> 7) & 0x3F;
|
|
|
|
i->IWT = IPtr[1] & 0x40;
|
|
|
|
i->IWA = (IPtr[1] >> 1) & 0x1F;
|
|
|
|
|
|
|
|
i->TABLE = IPtr[2] & 0x8000;
|
|
|
|
i->MWT = IPtr[2] & 0x4000;
|
|
|
|
i->MRD = IPtr[2] & 0x2000;
|
|
|
|
i->EWT = IPtr[2] & 0x1000;
|
|
|
|
i->EWA = (IPtr[2] >> 8) & 0x0F;
|
|
|
|
i->ADRL = IPtr[2] & 0x80;
|
|
|
|
i->FRCL = IPtr[2] & 0x40;
|
|
|
|
i->SHIFT = (IPtr[2] >> 4) & 3;
|
|
|
|
i->YRL = IPtr[2] & 8;
|
|
|
|
i->NEGB = IPtr[2] & 4;
|
|
|
|
i->ZERO = IPtr[2] & 2;
|
|
|
|
i->BSEL = IPtr[2] & 1;
|
|
|
|
|
|
|
|
i->NOFL = IPtr[3] & 0x8000;
|
|
|
|
i->MASA = (IPtr[3] >> 9) & 0x3f;
|
|
|
|
i->ADREB = IPtr[3] & 0x100;
|
|
|
|
i->NXADR = IPtr[3] & 0x80;
|
2019-01-23 20:14:51 +00:00
|
|
|
}
|
|
|
|
|
2021-01-26 17:48:17 +00:00
|
|
|
#if FEAT_DSPREC != DYNAREC_NONE
|
2013-12-19 17:10:14 +00:00
|
|
|
|
|
|
|
void dsp_init()
|
|
|
|
{
|
2021-01-26 17:48:17 +00:00
|
|
|
memset(&dsp, 0, sizeof(dsp));
|
|
|
|
dsp.RBL = 0x8000 - 1;
|
|
|
|
dsp.RBP = 0;
|
|
|
|
dsp.regs.MDEC_CT = 1;
|
|
|
|
dsp.dyndirty = true;
|
2013-12-19 17:10:14 +00:00
|
|
|
|
2021-01-26 17:48:17 +00:00
|
|
|
dsp_rec_init();
|
2013-12-19 17:10:14 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void dsp_step()
|
|
|
|
{
|
|
|
|
if (dsp.dyndirty)
|
|
|
|
{
|
2021-01-26 17:48:17 +00:00
|
|
|
dsp.dyndirty = false;
|
2013-12-19 17:10:14 +00:00
|
|
|
dsp_recompile();
|
|
|
|
}
|
2020-12-20 22:19:24 +00:00
|
|
|
if (dsp.Stopped)
|
|
|
|
return;
|
2021-01-26 17:48:17 +00:00
|
|
|
dsp_rec_step();
|
2013-12-19 17:10:14 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void dsp_writenmem(u32 addr)
|
|
|
|
{
|
2021-01-26 17:48:17 +00:00
|
|
|
if (addr >= 0x3400 && addr < 0x3C00)
|
2013-12-19 17:10:14 +00:00
|
|
|
{
|
2021-01-26 17:48:17 +00:00
|
|
|
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));
|
2013-12-19 17:10:14 +00:00
|
|
|
}
|
|
|
|
}
|
2018-08-13 16:05:56 +00:00
|
|
|
|
|
|
|
void dsp_term()
|
|
|
|
{
|
|
|
|
}
|
2021-01-26 17:48:17 +00:00
|
|
|
|
2018-07-29 19:47:30 +00:00
|
|
|
#endif
|