2018-07-29 19:47:30 +00:00
|
|
|
//
|
|
|
|
// Audio Overload SDK
|
|
|
|
//
|
|
|
|
// Copyright (c) 2007-2009 R. Belmont and Richard Bannister, and others.
|
|
|
|
// All rights reserved.
|
|
|
|
//
|
2020-03-28 16:58:01 +00:00
|
|
|
|
|
|
|
#include "build.h"
|
2018-07-29 19:47:30 +00:00
|
|
|
|
2019-01-23 21:59:00 +00:00
|
|
|
#if FEAT_DSPREC != DYNAREC_JIT
|
2018-07-29 19:47:30 +00:00
|
|
|
|
2020-03-28 16:58:01 +00:00
|
|
|
#include "dsp.h"
|
|
|
|
#include "aica.h"
|
|
|
|
#include "aica_if.h"
|
|
|
|
|
2021-08-26 08:16:07 +00:00
|
|
|
namespace dsp
|
2018-07-29 19:47:30 +00:00
|
|
|
{
|
|
|
|
|
2021-08-26 08:16:07 +00:00
|
|
|
void runStep()
|
2018-07-29 19:47:30 +00:00
|
|
|
{
|
2021-08-26 08:16:07 +00:00
|
|
|
if (state.stopped)
|
|
|
|
return;
|
|
|
|
|
2018-07-29 19:47:30 +00:00
|
|
|
s32 ACC = 0; //26 bit
|
|
|
|
s32 SHIFTED = 0; //24 bit
|
|
|
|
s32 X = 0; //24 bit
|
|
|
|
s32 Y = 0; //13 bit
|
|
|
|
s32 B = 0; //26 bit
|
|
|
|
s32 INPUTS = 0; //24 bit
|
|
|
|
s32 MEMVAL[4] = {0};
|
|
|
|
s32 FRC_REG = 0; //13 bit
|
|
|
|
s32 Y_REG = 0; //24 bit
|
|
|
|
u32 ADRS_REG = 0; //13 bit
|
|
|
|
|
2020-08-31 19:53:33 +00:00
|
|
|
for (int step = 0; step < 128; ++step)
|
2018-07-29 19:47:30 +00:00
|
|
|
{
|
|
|
|
u32 *IPtr = DSPData->MPRO + step * 4;
|
|
|
|
|
2018-08-13 22:59:34 +00:00
|
|
|
if (IPtr[0] == 0 && IPtr[1] == 0 && IPtr[2] == 0 && IPtr[3] == 0)
|
|
|
|
{
|
|
|
|
// Empty instruction shortcut
|
2021-08-26 08:16:07 +00:00
|
|
|
X = state.TEMP[state.MDEC_CT & 0x7F];
|
2018-08-13 22:59:34 +00:00
|
|
|
Y = FRC_REG;
|
|
|
|
|
2020-08-31 19:53:33 +00:00
|
|
|
ACC = (((s64)X * (s64)Y) >> 12) + X;
|
2018-08-13 22:59:34 +00:00
|
|
|
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
2018-07-29 19:47:30 +00:00
|
|
|
u32 TRA = (IPtr[0] >> 9) & 0x7F;
|
2020-08-31 19:53:33 +00:00
|
|
|
bool TWT = IPtr[0] & 0x100;
|
2018-07-29 19:47:30 +00:00
|
|
|
|
2020-08-31 19:53:33 +00:00
|
|
|
bool XSEL = IPtr[1] & 0x8000;
|
|
|
|
u32 YSEL = (IPtr[1] >> 13) & 3;
|
2018-07-29 19:47:30 +00:00
|
|
|
u32 IRA = (IPtr[1] >> 7) & 0x3F;
|
2020-08-31 19:53:33 +00:00
|
|
|
bool IWT = IPtr[1] & 0x40;
|
2018-07-29 19:47:30 +00:00
|
|
|
|
2020-08-31 19:53:33 +00:00
|
|
|
bool EWT = IPtr[2] & 0x1000;
|
|
|
|
bool ADRL = IPtr[2] & 0x80;
|
|
|
|
bool FRCL = IPtr[2] & 0x40;
|
|
|
|
u32 SHIFT = (IPtr[2] >> 4) & 3;
|
|
|
|
bool YRL = IPtr[2] & 8;
|
|
|
|
bool NEGB = IPtr[2] & 4;
|
|
|
|
bool ZERO = IPtr[2] & 2;
|
|
|
|
bool BSEL = IPtr[2] & 1;
|
2018-07-29 19:47:30 +00:00
|
|
|
|
|
|
|
u32 COEF = step;
|
|
|
|
|
|
|
|
// operations are done at 24 bit precision
|
|
|
|
|
|
|
|
// INPUTS RW
|
|
|
|
if (IRA <= 0x1f)
|
2021-08-26 08:16:07 +00:00
|
|
|
INPUTS = state.MEMS[IRA];
|
2018-07-29 19:47:30 +00:00
|
|
|
else if (IRA <= 0x2F)
|
2021-08-26 08:16:07 +00:00
|
|
|
INPUTS = state.MIXS[IRA - 0x20] << 4; // MIXS is 20 bit
|
2018-07-29 19:47:30 +00:00
|
|
|
else if (IRA <= 0x31)
|
|
|
|
INPUTS = DSPData->EXTS[IRA - 0x30] << 8; // EXTS is 16 bits
|
|
|
|
else
|
|
|
|
INPUTS = 0;
|
|
|
|
|
|
|
|
if (IWT)
|
|
|
|
{
|
2018-08-13 22:59:34 +00:00
|
|
|
u32 IWA = (IPtr[1] >> 1) & 0x1F;
|
2021-08-26 08:16:07 +00:00
|
|
|
state.MEMS[IWA] = MEMVAL[step & 3]; // MEMVAL was selected in previous MRD
|
2018-07-29 19:47:30 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
// Operand sel
|
|
|
|
// B
|
|
|
|
if (!ZERO)
|
|
|
|
{
|
|
|
|
if (BSEL)
|
|
|
|
B = ACC;
|
|
|
|
else
|
2021-08-26 08:16:07 +00:00
|
|
|
B = state.TEMP[(TRA + state.MDEC_CT) & 0x7F];
|
2018-07-29 19:47:30 +00:00
|
|
|
if (NEGB)
|
2019-09-05 13:41:16 +00:00
|
|
|
B = -B;
|
2018-07-29 19:47:30 +00:00
|
|
|
}
|
|
|
|
else
|
2019-09-05 13:41:16 +00:00
|
|
|
{
|
2018-07-29 19:47:30 +00:00
|
|
|
B = 0;
|
2019-09-05 13:41:16 +00:00
|
|
|
}
|
2018-07-29 19:47:30 +00:00
|
|
|
|
|
|
|
// X
|
|
|
|
if (XSEL)
|
|
|
|
X = INPUTS;
|
|
|
|
else
|
2021-08-26 08:16:07 +00:00
|
|
|
X = state.TEMP[(TRA + state.MDEC_CT) & 0x7F];
|
2018-07-29 19:47:30 +00:00
|
|
|
|
|
|
|
// Y
|
|
|
|
if (YSEL == 0)
|
|
|
|
Y = FRC_REG;
|
|
|
|
else if (YSEL == 1)
|
2019-09-05 13:41:16 +00:00
|
|
|
Y = ((s32)(s16)DSPData->COEF[COEF]) >> 3; //COEF is 16 bits
|
2018-07-29 19:47:30 +00:00
|
|
|
else if (YSEL == 2)
|
2019-09-05 13:41:16 +00:00
|
|
|
Y = Y_REG >> 11;
|
2018-07-29 19:47:30 +00:00
|
|
|
else if (YSEL == 3)
|
|
|
|
Y = (Y_REG >> 4) & 0x0FFF;
|
|
|
|
|
|
|
|
if (YRL)
|
|
|
|
Y_REG = INPUTS;
|
|
|
|
|
|
|
|
// Shifter
|
|
|
|
// There's a 1-step delay at the output of the X*Y + B adder. So we use the ACC value from the previous step.
|
2020-08-31 19:53:33 +00:00
|
|
|
if (SHIFT == 0 || SHIFT == 3)
|
2019-09-05 13:41:16 +00:00
|
|
|
SHIFTED = ACC;
|
2020-08-31 19:53:33 +00:00
|
|
|
else
|
2019-09-05 13:41:16 +00:00
|
|
|
SHIFTED = ACC << 1; // x2 scale
|
2020-08-31 19:53:33 +00:00
|
|
|
|
|
|
|
if (SHIFT < 2)
|
|
|
|
SHIFTED = std::min(std::max(SHIFTED, -0x00800000), 0x007FFFFF);
|
2018-07-29 19:47:30 +00:00
|
|
|
|
|
|
|
// ACCUM
|
2019-09-05 13:41:16 +00:00
|
|
|
ACC = (((s64)X * (s64)Y) >> 12) + B;
|
2018-07-29 19:47:30 +00:00
|
|
|
|
|
|
|
if (TWT)
|
2018-08-13 22:59:34 +00:00
|
|
|
{
|
|
|
|
u32 TWA = (IPtr[0] >> 1) & 0x7F;
|
2021-08-26 08:16:07 +00:00
|
|
|
state.TEMP[(TWA + state.MDEC_CT) & 0x7F] = SHIFTED;
|
2018-08-13 22:59:34 +00:00
|
|
|
}
|
2018-07-29 19:47:30 +00:00
|
|
|
|
|
|
|
if (FRCL)
|
|
|
|
{
|
|
|
|
if (SHIFT == 3)
|
|
|
|
FRC_REG = SHIFTED & 0x0FFF;
|
|
|
|
else
|
2019-09-05 13:41:16 +00:00
|
|
|
FRC_REG = SHIFTED >> 11;
|
2018-07-29 19:47:30 +00:00
|
|
|
}
|
|
|
|
|
2018-08-13 22:59:34 +00:00
|
|
|
if (step & 1)
|
2018-07-29 19:47:30 +00:00
|
|
|
{
|
2020-08-31 19:53:33 +00:00
|
|
|
bool MWT = IPtr[2] & 0x4000;
|
|
|
|
bool MRD = IPtr[2] & 0x2000;
|
2018-08-13 22:59:34 +00:00
|
|
|
|
|
|
|
if (MRD || MWT)
|
2018-07-29 19:47:30 +00:00
|
|
|
{
|
2020-08-31 19:53:33 +00:00
|
|
|
bool TABLE = IPtr[2] & 0x8000;
|
2018-08-13 22:59:34 +00:00
|
|
|
|
2020-08-31 19:53:33 +00:00
|
|
|
//bool NOFL = IPtr[3] & 0x8000;
|
|
|
|
//verify(!NOFL);
|
|
|
|
u32 MASA = (IPtr[3] >> 9) & 0x3f;
|
|
|
|
bool ADREB = IPtr[3] & 0x100;
|
|
|
|
bool NXADR = IPtr[3] & 0x80;
|
2018-08-13 22:59:34 +00:00
|
|
|
|
|
|
|
u32 ADDR = DSPData->MADRS[MASA];
|
|
|
|
if (ADREB)
|
|
|
|
ADDR += ADRS_REG & 0x0FFF;
|
|
|
|
if (NXADR)
|
|
|
|
ADDR++;
|
|
|
|
if (!TABLE)
|
|
|
|
{
|
2021-08-26 08:16:07 +00:00
|
|
|
ADDR += state.MDEC_CT;
|
|
|
|
ADDR &= state.RBL; // RBL is ring buffer length - 1
|
2018-08-13 22:59:34 +00:00
|
|
|
}
|
2018-07-29 19:47:30 +00:00
|
|
|
else
|
2018-08-13 22:59:34 +00:00
|
|
|
ADDR &= 0xFFFF;
|
|
|
|
|
|
|
|
ADDR <<= 1; // Word -> byte address
|
2021-08-26 08:16:07 +00:00
|
|
|
ADDR += state.RBP; // RBP is already a byte address
|
2018-08-13 22:59:34 +00:00
|
|
|
if (MRD) // memory only allowed on odd. DoA inserts NOPs on even
|
|
|
|
{
|
|
|
|
//if (NOFL)
|
|
|
|
// MEMVAL[(step + 2) & 3] = (*(s16 *)&aica_ram[ADDR]) << 8;
|
|
|
|
//else
|
2018-11-15 20:58:04 +00:00
|
|
|
MEMVAL[(step + 2) & 3] = UNPACK(*(u16 *)&aica_ram[ADDR & ARAM_MASK]);
|
2018-08-13 22:59:34 +00:00
|
|
|
}
|
|
|
|
if (MWT)
|
|
|
|
{
|
|
|
|
// FIXME We should wait for the next step to copy stuff to SRAM (same as read)
|
|
|
|
//if (NOFL)
|
|
|
|
// *(s16 *)&aica_ram[ADDR] = SHIFTED >> 8;
|
|
|
|
//else
|
2018-11-15 20:58:04 +00:00
|
|
|
*(u16 *)&aica_ram[ADDR & ARAM_MASK] = PACK(SHIFTED);
|
2018-08-13 22:59:34 +00:00
|
|
|
}
|
2018-07-29 19:47:30 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (ADRL)
|
|
|
|
{
|
|
|
|
if (SHIFT == 3)
|
2019-09-05 13:41:16 +00:00
|
|
|
ADRS_REG = SHIFTED >> 12;
|
2018-07-29 19:47:30 +00:00
|
|
|
else
|
2019-09-05 13:41:16 +00:00
|
|
|
ADRS_REG = INPUTS >> 16;
|
2018-07-29 19:47:30 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
if (EWT)
|
2018-08-13 22:59:34 +00:00
|
|
|
{
|
|
|
|
u32 EWA = (IPtr[2] >> 8) & 0x0F;
|
2020-04-17 16:04:58 +00:00
|
|
|
DSPData->EFREG[EWA] = SHIFTED >> 8;
|
2018-08-13 22:59:34 +00:00
|
|
|
}
|
2018-07-29 19:47:30 +00:00
|
|
|
|
|
|
|
}
|
2021-08-26 08:16:07 +00:00
|
|
|
--state.MDEC_CT;
|
|
|
|
if (state.MDEC_CT == 0)
|
|
|
|
state.MDEC_CT = state.RBL + 1; // RBL is ring buffer length - 1
|
2018-07-29 19:47:30 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
#endif
|