[virtualjaguar] rework dsp and gpu opcodes to come from the same source, fix some wrong opcodes (partially fixes Club Drive and Baldies music)
This commit is contained in:
parent
7b060bada4
commit
baa3bdf948
Binary file not shown.
|
@ -1,7 +1,7 @@
|
|||
COMMON_FLAGS := -fno-strict-aliasing -fwrapv -I./src/ -I./src/m68000 \
|
||||
-Werror=int-to-pointer-cast -Wno-unused-variable -Wno-cpp \
|
||||
-Wno-unused-but-set-variable -Wno-return-type -Wno-misleading-indentation \
|
||||
-Wno-parentheses -Wno-unused-label
|
||||
-Wno-parentheses -Wno-unused-label -Wfatal-errors
|
||||
|
||||
CCFLAGS := -std=c11 $(COMMON_FLAGS) -Wno-implicit-function-declaration
|
||||
|
||||
|
|
|
@ -138,7 +138,7 @@ static void dsp_opcode_subqmod(void);
|
|||
static void dsp_opcode_subqt(void);
|
||||
static void dsp_opcode_illegal(void);
|
||||
|
||||
uint8_t dsp_opcode_cycles[64] =
|
||||
static const uint8_t dsp_opcode_cycles[64] =
|
||||
{
|
||||
1, 1, 1, 1, 1, 1, 1, 1,
|
||||
1, 1, 1, 1, 1, 1, 1, 1,
|
||||
|
@ -150,7 +150,7 @@ uint8_t dsp_opcode_cycles[64] =
|
|||
1, 1, 3, 3, 1, 1, 1, 1
|
||||
};
|
||||
|
||||
void (* dsp_opcode[64])() =
|
||||
static void (* dsp_opcode[64])() =
|
||||
{
|
||||
dsp_opcode_add, dsp_opcode_addc, dsp_opcode_addq, dsp_opcode_addqt,
|
||||
dsp_opcode_sub, dsp_opcode_subc, dsp_opcode_subq, dsp_opcode_subqt,
|
||||
|
@ -187,37 +187,12 @@ uint32_t dsp_reg_bank_0[32], dsp_reg_bank_1[32];
|
|||
static uint32_t dsp_opcode_first_parameter;
|
||||
static uint32_t dsp_opcode_second_parameter;
|
||||
|
||||
#define DSP_RUNNING (dsp_control & 0x01)
|
||||
#define DSP_RUNNING (dsp_control & 0x01)
|
||||
|
||||
#define RM dsp_reg[dsp_opcode_first_parameter]
|
||||
#define RN dsp_reg[dsp_opcode_second_parameter]
|
||||
#define ALTERNATE_RM dsp_alternate_reg[dsp_opcode_first_parameter]
|
||||
#define ALTERNATE_RN dsp_alternate_reg[dsp_opcode_second_parameter]
|
||||
#define IMM_1 dsp_opcode_first_parameter
|
||||
#define IMM_2 dsp_opcode_second_parameter
|
||||
|
||||
#define CLR_Z (dsp_flag_z = 0)
|
||||
#define CLR_ZN (dsp_flag_z = dsp_flag_n = 0)
|
||||
#define CLR_ZNC (dsp_flag_z = dsp_flag_n = dsp_flag_c = 0)
|
||||
#define SET_Z(r) (dsp_flag_z = ((r) == 0))
|
||||
#define SET_N(r) (dsp_flag_n = (((uint32_t)(r) >> 31) & 0x01))
|
||||
#define SET_C_ADD(a,b) (dsp_flag_c = ((uint32_t)(b) > (uint32_t)(~(a))))
|
||||
#define SET_C_SUB(a,b) (dsp_flag_c = ((uint32_t)(b) > (uint32_t)(a)))
|
||||
#define SET_ZN(r) SET_N(r); SET_Z(r)
|
||||
#define SET_ZNC_ADD(a,b,r) SET_N(r); SET_Z(r); SET_C_ADD(a,b)
|
||||
#define SET_ZNC_SUB(a,b,r) SET_N(r); SET_Z(r); SET_C_SUB(a,b)
|
||||
|
||||
uint32_t dsp_convert_zero[32] = {
|
||||
32, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16,
|
||||
17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31
|
||||
};
|
||||
|
||||
uint8_t dsp_branch_condition_table[32 * 8];
|
||||
static uint8_t branch_condition_table[32 * 8];
|
||||
static uint16_t mirror_table[65536];
|
||||
uint8_t dsp_ram_8[0x2000];
|
||||
|
||||
#define BRANCH_CONDITION(x) dsp_branch_condition_table[(x) + ((jaguar_flags & 7) << 5)]
|
||||
|
||||
void dsp_build_branch_condition_table(void)
|
||||
{
|
||||
for(int i=0; i<65536; i++)
|
||||
|
@ -250,7 +225,7 @@ void dsp_build_branch_condition_table(void)
|
|||
if ((j & 8) && (!(i & (CARRY_FLAG << (j >> 4)))))
|
||||
result = 0;
|
||||
|
||||
dsp_branch_condition_table[i * 32 + j] = result;
|
||||
branch_condition_table[i * 32 + j] = result;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -587,7 +562,7 @@ void DSPReset(void)
|
|||
for(int i=0; i<32; i++)
|
||||
dsp_reg[i] = dsp_alternate_reg[i] = 0x00000000;
|
||||
|
||||
CLR_ZNC;
|
||||
dsp_flag_z = dsp_flag_n = dsp_flag_c = 0;
|
||||
IMASKCleared = false;
|
||||
|
||||
for(uint32_t i=0; i<8192; i+=4)
|
||||
|
@ -624,559 +599,9 @@ void DSPExec(int32_t cycles)
|
|||
}
|
||||
|
||||
//
|
||||
// DSP opcode handlers
|
||||
// DSP opcodes
|
||||
//
|
||||
|
||||
static void dsp_opcode_jump(void)
|
||||
{
|
||||
uint32_t jaguar_flags = (dsp_flag_n << 2) | (dsp_flag_c << 1) | dsp_flag_z;
|
||||
#define RISC 2
|
||||
|
||||
if (BRANCH_CONDITION(IMM_2))
|
||||
{
|
||||
uint32_t delayed_pc = RM;
|
||||
DSPExec(1);
|
||||
dsp_pc = delayed_pc;
|
||||
}
|
||||
}
|
||||
|
||||
static void dsp_opcode_jr(void)
|
||||
{
|
||||
uint32_t jaguar_flags = (dsp_flag_n << 2) | (dsp_flag_c << 1) | dsp_flag_z;
|
||||
|
||||
if (BRANCH_CONDITION(IMM_2))
|
||||
{
|
||||
int32_t offset = (IMM_1 & 0x10 ? 0xFFFFFFF0 | IMM_1 : IMM_1);
|
||||
int32_t delayed_pc = dsp_pc + (offset * 2);
|
||||
DSPExec(1);
|
||||
dsp_pc = delayed_pc;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static void dsp_opcode_add(void)
|
||||
{
|
||||
uint32_t res = RN + RM;
|
||||
SET_ZNC_ADD(RN, RM, res);
|
||||
RN = res;
|
||||
}
|
||||
|
||||
|
||||
static void dsp_opcode_addc(void)
|
||||
{
|
||||
uint32_t res = RN + RM + dsp_flag_c;
|
||||
uint32_t carry = dsp_flag_c;
|
||||
SET_ZNC_ADD(RN + carry, RM, res);
|
||||
RN = res;
|
||||
}
|
||||
|
||||
static void dsp_opcode_addq(void)
|
||||
{
|
||||
uint32_t r1 = dsp_convert_zero[IMM_1];
|
||||
uint32_t res = RN + r1;
|
||||
CLR_ZNC; SET_ZNC_ADD(RN, r1, res);
|
||||
RN = res;
|
||||
}
|
||||
|
||||
static void dsp_opcode_sub(void)
|
||||
{
|
||||
uint32_t res = RN - RM;
|
||||
SET_ZNC_SUB(RN, RM, res);
|
||||
RN = res;
|
||||
}
|
||||
|
||||
static void dsp_opcode_subc(void)
|
||||
{
|
||||
uint64_t res = (uint64_t)RN + (uint64_t)(RM ^ 0xFFFFFFFF) + (dsp_flag_c ^ 1);
|
||||
dsp_flag_c = ((res >> 32) & 0x01) ^ 1;
|
||||
RN = (res & 0xFFFFFFFF);
|
||||
SET_ZN(RN);
|
||||
}
|
||||
|
||||
|
||||
static void dsp_opcode_subq(void)
|
||||
{
|
||||
uint32_t r1 = dsp_convert_zero[IMM_1];
|
||||
uint32_t res = RN - r1;
|
||||
SET_ZNC_SUB(RN, r1, res);
|
||||
RN = res;
|
||||
}
|
||||
|
||||
static void dsp_opcode_cmp(void)
|
||||
{
|
||||
uint32_t res = RN - RM;
|
||||
SET_ZNC_SUB(RN, RM, res);
|
||||
}
|
||||
|
||||
static void dsp_opcode_cmpq(void)
|
||||
{
|
||||
static int32_t sqtable[32] =
|
||||
{ 0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,-16,-15,-14,-13,-12,-11,-10,-9,-8,-7,-6,-5,-4,-3,-2,-1 };
|
||||
|
||||
uint32_t r1 = sqtable[IMM_1 & 0x1F];
|
||||
uint32_t res = RN - r1;
|
||||
SET_ZNC_SUB(RN, r1, res);
|
||||
}
|
||||
|
||||
static void dsp_opcode_and(void)
|
||||
{
|
||||
RN = RN & RM;
|
||||
SET_ZN(RN);
|
||||
}
|
||||
|
||||
static void dsp_opcode_or(void)
|
||||
{
|
||||
RN = RN | RM;
|
||||
SET_ZN(RN);
|
||||
}
|
||||
|
||||
static void dsp_opcode_xor(void)
|
||||
{
|
||||
RN = RN ^ RM;
|
||||
SET_ZN(RN);
|
||||
}
|
||||
|
||||
static void dsp_opcode_not(void)
|
||||
{
|
||||
RN = ~RN;
|
||||
SET_ZN(RN);
|
||||
}
|
||||
|
||||
static void dsp_opcode_move_pc(void)
|
||||
{
|
||||
RN = dsp_pc - 2;
|
||||
}
|
||||
|
||||
static void dsp_opcode_store_r14_indexed(void)
|
||||
{
|
||||
DSPWriteLong(dsp_reg[14] + (dsp_convert_zero[IMM_1] << 2), RN, DSP);
|
||||
}
|
||||
|
||||
static void dsp_opcode_store_r15_indexed(void)
|
||||
{
|
||||
DSPWriteLong(dsp_reg[15] + (dsp_convert_zero[IMM_1] << 2), RN, DSP);
|
||||
}
|
||||
|
||||
static void dsp_opcode_load_r14_ri(void)
|
||||
{
|
||||
RN = DSPReadLong((dsp_reg[14] + RM) & 0xFFFFFFFC, DSP);
|
||||
}
|
||||
|
||||
static void dsp_opcode_load_r15_ri(void)
|
||||
{
|
||||
RN = DSPReadLong((dsp_reg[15] + RM) & 0xFFFFFFFC, DSP);
|
||||
}
|
||||
|
||||
static void dsp_opcode_store_r14_ri(void)
|
||||
{
|
||||
DSPWriteLong(dsp_reg[14] + RM, RN, DSP);
|
||||
}
|
||||
|
||||
static void dsp_opcode_store_r15_ri(void)
|
||||
{
|
||||
DSPWriteLong(dsp_reg[15] + RM, RN, DSP);
|
||||
}
|
||||
|
||||
static void dsp_opcode_nop(void)
|
||||
{
|
||||
}
|
||||
|
||||
static void dsp_opcode_storeb(void)
|
||||
{
|
||||
if (RM >= DSP_WORK_RAM_BASE && RM <= (DSP_WORK_RAM_BASE + 0x1FFF))
|
||||
DSPWriteLong(RM & 0xFFFFFFFC, RN, DSP);
|
||||
else
|
||||
JaguarWriteByte(RM, RN, DSP);
|
||||
}
|
||||
|
||||
static void dsp_opcode_storew(void)
|
||||
{
|
||||
if (RM >= DSP_WORK_RAM_BASE && RM <= (DSP_WORK_RAM_BASE + 0x1FFF))
|
||||
DSPWriteLong(RM & 0xFFFFFFFC, RN, DSP);
|
||||
else
|
||||
JaguarWriteWord(RM, RN, DSP);
|
||||
}
|
||||
|
||||
static void dsp_opcode_store(void)
|
||||
{
|
||||
DSPWriteLong(RM, RN, DSP);
|
||||
}
|
||||
|
||||
static void dsp_opcode_loadb(void)
|
||||
{
|
||||
if (RM >= DSP_WORK_RAM_BASE && RM <= (DSP_WORK_RAM_BASE + 0x1FFF))
|
||||
RN = DSPReadLong(RM & 0xFFFFFFFC, DSP);
|
||||
else
|
||||
RN = JaguarReadByte(RM, DSP);
|
||||
}
|
||||
|
||||
static void dsp_opcode_loadw(void)
|
||||
{
|
||||
if (RM >= DSP_WORK_RAM_BASE && RM <= (DSP_WORK_RAM_BASE + 0x1FFF))
|
||||
RN = DSPReadLong(RM & 0xFFFFFFFC, DSP);
|
||||
else
|
||||
RN = JaguarReadWord(RM & 0xFFFFFFFE, DSP);
|
||||
}
|
||||
|
||||
static void dsp_opcode_load(void)
|
||||
{
|
||||
RN = DSPReadLong(RM & 0xFFFFFFFC, DSP);
|
||||
}
|
||||
|
||||
static void dsp_opcode_load_r14_indexed(void)
|
||||
{
|
||||
RN = DSPReadLong((dsp_reg[14] & 0xFFFFFFFC) + (dsp_convert_zero[IMM_1] << 2), DSP);
|
||||
}
|
||||
|
||||
static void dsp_opcode_load_r15_indexed(void)
|
||||
{
|
||||
RN = DSPReadLong((dsp_reg[15] & 0xFFFFFFFC) + (dsp_convert_zero[IMM_1] << 2), DSP);
|
||||
}
|
||||
|
||||
static void dsp_opcode_movei(void)
|
||||
{
|
||||
RN = (uint32_t)DSPReadWord(dsp_pc, DSP) | ((uint32_t)DSPReadWord(dsp_pc + 2, DSP) << 16);
|
||||
dsp_pc += 4;
|
||||
}
|
||||
|
||||
static void dsp_opcode_moveta(void)
|
||||
{
|
||||
ALTERNATE_RN = RM;
|
||||
}
|
||||
|
||||
static void dsp_opcode_movefa(void)
|
||||
{
|
||||
RN = ALTERNATE_RM;
|
||||
}
|
||||
|
||||
static void dsp_opcode_move(void)
|
||||
{
|
||||
RN = RM;
|
||||
}
|
||||
|
||||
static void dsp_opcode_moveq(void)
|
||||
{
|
||||
RN = IMM_1;
|
||||
}
|
||||
|
||||
static void dsp_opcode_resmac(void)
|
||||
{
|
||||
RN = (uint32_t)dsp_acc;
|
||||
}
|
||||
|
||||
static void dsp_opcode_imult(void)
|
||||
{
|
||||
RN = (int16_t)RN * (int16_t)RM;
|
||||
SET_ZN(RN);
|
||||
}
|
||||
|
||||
static void dsp_opcode_mult(void)
|
||||
{
|
||||
RN = (uint16_t)RM * (uint16_t)RN;
|
||||
SET_ZN(RN);
|
||||
}
|
||||
|
||||
static void dsp_opcode_bclr(void)
|
||||
{
|
||||
uint32_t res = RN & ~(1 << IMM_1);
|
||||
RN = res;
|
||||
SET_ZN(res);
|
||||
}
|
||||
|
||||
static void dsp_opcode_btst(void)
|
||||
{
|
||||
dsp_flag_z = (~RN >> IMM_1) & 1;
|
||||
}
|
||||
|
||||
static void dsp_opcode_bset(void)
|
||||
{
|
||||
uint32_t res = RN | (1 << IMM_1);
|
||||
RN = res;
|
||||
SET_ZN(res);
|
||||
}
|
||||
|
||||
static void dsp_opcode_subqt(void)
|
||||
{
|
||||
RN -= dsp_convert_zero[IMM_1];
|
||||
}
|
||||
|
||||
static void dsp_opcode_addqt(void)
|
||||
{
|
||||
RN += dsp_convert_zero[IMM_1];
|
||||
}
|
||||
|
||||
static void dsp_opcode_imacn(void)
|
||||
{
|
||||
int32_t res = (int16_t)RM * (int16_t)RN;
|
||||
dsp_acc += (int64_t)res;
|
||||
}
|
||||
|
||||
static void dsp_opcode_mtoi(void)
|
||||
{
|
||||
RN = (((int32_t)RM >> 8) & 0xFF800000) | (RM & 0x007FFFFF);
|
||||
SET_ZN(RN);
|
||||
}
|
||||
|
||||
static void dsp_opcode_normi(void)
|
||||
{
|
||||
uint32_t _Rm = RM;
|
||||
uint32_t res = 0;
|
||||
|
||||
if (_Rm)
|
||||
{
|
||||
while ((_Rm & 0xffc00000) == 0)
|
||||
{
|
||||
_Rm <<= 1;
|
||||
res--;
|
||||
}
|
||||
while ((_Rm & 0xff800000) != 0)
|
||||
{
|
||||
_Rm >>= 1;
|
||||
res++;
|
||||
}
|
||||
}
|
||||
|
||||
RN = res;
|
||||
SET_ZN(RN);
|
||||
}
|
||||
|
||||
static void dsp_opcode_mmult(void)
|
||||
{
|
||||
int count = dsp_matrix_control&0x0f;
|
||||
uint32_t addr = dsp_pointer_to_matrix;
|
||||
int64_t accum = 0;
|
||||
uint32_t res;
|
||||
|
||||
if (!(dsp_matrix_control & 0x10))
|
||||
{
|
||||
for (int i = 0; i < count; i++)
|
||||
{
|
||||
int16_t a;
|
||||
if (i&0x01)
|
||||
a=(int16_t)((dsp_alternate_reg[dsp_opcode_first_parameter + (i>>1)]>>16)&0xffff);
|
||||
else
|
||||
a=(int16_t)(dsp_alternate_reg[dsp_opcode_first_parameter + (i>>1)]&0xffff);
|
||||
int16_t b=((int16_t)DSPReadWord(addr + 2, DSP));
|
||||
accum += a*b;
|
||||
addr += 4;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
for (int i = 0; i < count; i++)
|
||||
{
|
||||
int16_t a;
|
||||
if (i&0x01)
|
||||
a=(int16_t)((dsp_alternate_reg[dsp_opcode_first_parameter + (i>>1)]>>16)&0xffff);
|
||||
else
|
||||
a=(int16_t)(dsp_alternate_reg[dsp_opcode_first_parameter + (i>>1)]&0xffff);
|
||||
int16_t b=((int16_t)DSPReadWord(addr + 2, DSP));
|
||||
accum += a*b;
|
||||
addr += 4 * count;
|
||||
}
|
||||
}
|
||||
|
||||
RN = res = (int32_t)accum;
|
||||
SET_ZN(RN);
|
||||
}
|
||||
|
||||
static void dsp_opcode_abs(void)
|
||||
{
|
||||
uint32_t _Rn = RN;
|
||||
uint32_t res;
|
||||
|
||||
if (_Rn == 0x80000000)
|
||||
dsp_flag_n = 1;
|
||||
else
|
||||
{
|
||||
dsp_flag_c = ((_Rn & 0x80000000) >> 31);
|
||||
res = RN = (_Rn & 0x80000000 ? -_Rn : _Rn);
|
||||
CLR_ZN; SET_Z(res);
|
||||
}
|
||||
}
|
||||
|
||||
static void dsp_opcode_div(void)
|
||||
{
|
||||
uint32_t q = RN;
|
||||
uint32_t r = 0;
|
||||
|
||||
if (dsp_div_control & 0x01)
|
||||
q <<= 16, r = RN >> 16;
|
||||
|
||||
for(int i=0; i<32; i++)
|
||||
{
|
||||
uint32_t sign = r & 0x80000000;
|
||||
r = (r << 1) | ((q >> 31) & 0x01);
|
||||
r += (sign ? RM : -RM);
|
||||
q = (q << 1) | (((~r) >> 31) & 0x01);
|
||||
}
|
||||
|
||||
RN = q;
|
||||
dsp_remain = r;
|
||||
}
|
||||
|
||||
static void dsp_opcode_imultn(void)
|
||||
{
|
||||
int32_t res = (int32_t)((int16_t)RN * (int16_t)RM);
|
||||
dsp_acc = (int64_t)res;
|
||||
SET_ZN(res);
|
||||
}
|
||||
|
||||
static void dsp_opcode_neg(void)
|
||||
{
|
||||
uint32_t res = -RN;
|
||||
SET_ZNC_SUB(0, RN, res);
|
||||
RN = res;
|
||||
}
|
||||
|
||||
static void dsp_opcode_shlq(void)
|
||||
{
|
||||
int32_t r1 = 32 - IMM_1;
|
||||
uint32_t res = RN << r1;
|
||||
SET_ZN(res); dsp_flag_c = (RN >> 31) & 1;
|
||||
RN = res;
|
||||
}
|
||||
|
||||
static void dsp_opcode_shrq(void)
|
||||
{
|
||||
int32_t r1 = dsp_convert_zero[IMM_1];
|
||||
uint32_t res = RN >> r1;
|
||||
SET_ZN(res); dsp_flag_c = RN & 1;
|
||||
RN = res;
|
||||
}
|
||||
|
||||
static void dsp_opcode_ror(void)
|
||||
{
|
||||
uint32_t r1 = RM & 0x1F;
|
||||
uint32_t res = (RN >> r1) | (RN << (32 - r1));
|
||||
SET_ZN(res); dsp_flag_c = (RN >> 31) & 1;
|
||||
RN = res;
|
||||
}
|
||||
|
||||
static void dsp_opcode_rorq(void)
|
||||
{
|
||||
uint32_t r1 = dsp_convert_zero[IMM_1 & 0x1F];
|
||||
uint32_t r2 = RN;
|
||||
uint32_t res = (r2 >> r1) | (r2 << (32 - r1));
|
||||
RN = res;
|
||||
SET_ZN(res); dsp_flag_c = (r2 >> 31) & 0x01;
|
||||
}
|
||||
|
||||
static void dsp_opcode_sha(void)
|
||||
{
|
||||
int32_t sRm=(int32_t)RM;
|
||||
uint32_t _Rn=RN;
|
||||
|
||||
if (sRm<0)
|
||||
{
|
||||
uint32_t shift=-sRm;
|
||||
if (shift>=32) shift=32;
|
||||
dsp_flag_c=(_Rn&0x80000000)>>31;
|
||||
while (shift)
|
||||
{
|
||||
_Rn<<=1;
|
||||
shift--;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
uint32_t shift=sRm;
|
||||
if (shift>=32) shift=32;
|
||||
dsp_flag_c=_Rn&0x1;
|
||||
while (shift)
|
||||
{
|
||||
_Rn=((int32_t)_Rn)>>1;
|
||||
shift--;
|
||||
}
|
||||
}
|
||||
|
||||
RN = _Rn;
|
||||
SET_ZN(RN);
|
||||
}
|
||||
|
||||
static void dsp_opcode_sharq(void)
|
||||
{
|
||||
uint32_t res = (int32_t)RN >> dsp_convert_zero[IMM_1];
|
||||
SET_ZN(res); dsp_flag_c = RN & 0x01;
|
||||
RN = res;
|
||||
}
|
||||
|
||||
static void dsp_opcode_sh(void)
|
||||
{
|
||||
int32_t sRm=(int32_t)RM;
|
||||
uint32_t _Rn=RN;
|
||||
|
||||
if (sRm<0)
|
||||
{
|
||||
uint32_t shift=(-sRm);
|
||||
if (shift>=32) shift=32;
|
||||
dsp_flag_c=(_Rn&0x80000000)>>31;
|
||||
while (shift)
|
||||
{
|
||||
_Rn<<=1;
|
||||
shift--;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
uint32_t shift=sRm;
|
||||
if (shift>=32) shift=32;
|
||||
dsp_flag_c=_Rn&0x1;
|
||||
while (shift)
|
||||
{
|
||||
_Rn>>=1;
|
||||
shift--;
|
||||
}
|
||||
}
|
||||
|
||||
RN = _Rn;
|
||||
SET_ZN(RN);
|
||||
}
|
||||
|
||||
void dsp_opcode_addqmod(void)
|
||||
{
|
||||
uint32_t r1 = dsp_convert_zero[IMM_1];
|
||||
uint32_t r2 = RN;
|
||||
uint32_t res = r2 + r1;
|
||||
res = (res & (~dsp_modulo)) | (r2 & dsp_modulo);
|
||||
RN = res;
|
||||
SET_ZNC_ADD(r2, r1, res);
|
||||
}
|
||||
|
||||
void dsp_opcode_subqmod(void)
|
||||
{
|
||||
uint32_t r1 = dsp_convert_zero[IMM_1];
|
||||
uint32_t r2 = RN;
|
||||
uint32_t res = r2 - r1;
|
||||
res = (res & (~dsp_modulo)) | (r2 & dsp_modulo);
|
||||
RN = res;
|
||||
|
||||
SET_ZNC_SUB(r2, r1, res);
|
||||
}
|
||||
|
||||
void dsp_opcode_mirror(void)
|
||||
{
|
||||
uint32_t r1 = RN;
|
||||
RN = (mirror_table[r1 & 0xFFFF] << 16) | mirror_table[r1 >> 16];
|
||||
SET_ZN(RN);
|
||||
}
|
||||
|
||||
void dsp_opcode_sat32s(void)
|
||||
{
|
||||
int32_t r2 = (uint32_t)RN;
|
||||
int32_t temp = dsp_acc >> 32;
|
||||
uint32_t res = (temp < -1) ? (int32_t)0x80000000 : (temp > 0) ? (int32_t)0x7FFFFFFF : r2;
|
||||
RN = res;
|
||||
SET_ZN(res);
|
||||
}
|
||||
|
||||
void dsp_opcode_sat16s(void)
|
||||
{
|
||||
int32_t r2 = RN;
|
||||
uint32_t res = (r2 < -32768) ? -32768 : (r2 > 32767) ? 32767 : r2;
|
||||
RN = res;
|
||||
SET_ZN(res);
|
||||
}
|
||||
|
||||
void dsp_opcode_illegal(void)
|
||||
{
|
||||
}
|
||||
#include "risc_opcodes.h"
|
||||
|
|
|
@ -130,7 +130,7 @@ static void gpu_opcode_store_r15_ri(void);
|
|||
static void gpu_opcode_sat24(void);
|
||||
static void gpu_opcode_pack(void);
|
||||
|
||||
uint8_t gpu_opcode_cycles[64] =
|
||||
static const uint8_t gpu_opcode_cycles[64] =
|
||||
{
|
||||
1, 1, 1, 1, 1, 1, 1, 1,
|
||||
1, 1, 1, 1, 1, 1, 1, 1,
|
||||
|
@ -142,7 +142,7 @@ uint8_t gpu_opcode_cycles[64] =
|
|||
1, 1, 1, 1, 1, 1, 1, 1
|
||||
};
|
||||
|
||||
void (*gpu_opcode[64])()=
|
||||
static void (*gpu_opcode[64])()=
|
||||
{
|
||||
gpu_opcode_add, gpu_opcode_addc, gpu_opcode_addq, gpu_opcode_addqt,
|
||||
gpu_opcode_sub, gpu_opcode_subc, gpu_opcode_subq, gpu_opcode_subqt,
|
||||
|
@ -184,36 +184,7 @@ static uint32_t gpu_opcode_second_parameter;
|
|||
|
||||
#define GPU_RUNNING (gpu_control & 0x01)
|
||||
|
||||
#define RM gpu_reg[gpu_opcode_first_parameter]
|
||||
#define RN gpu_reg[gpu_opcode_second_parameter]
|
||||
#define ALTERNATE_RM gpu_alternate_reg[gpu_opcode_first_parameter]
|
||||
#define ALTERNATE_RN gpu_alternate_reg[gpu_opcode_second_parameter]
|
||||
#define IMM_1 gpu_opcode_first_parameter
|
||||
#define IMM_2 gpu_opcode_second_parameter
|
||||
|
||||
#define SET_FLAG_Z(r) (gpu_flag_z = ((r) == 0));
|
||||
#define SET_FLAG_N(r) (gpu_flag_n = (((uint32_t)(r) >> 31) & 0x01));
|
||||
|
||||
#define RESET_FLAG_Z() gpu_flag_z = 0;
|
||||
#define RESET_FLAG_N() gpu_flag_n = 0;
|
||||
#define RESET_FLAG_C() gpu_flag_c = 0;
|
||||
|
||||
#define CLR_Z (gpu_flag_z = 0)
|
||||
#define CLR_ZN (gpu_flag_z = gpu_flag_n = 0)
|
||||
#define CLR_ZNC (gpu_flag_z = gpu_flag_n = gpu_flag_c = 0)
|
||||
#define SET_Z(r) (gpu_flag_z = ((r) == 0))
|
||||
#define SET_N(r) (gpu_flag_n = (((uint32_t)(r) >> 31) & 0x01))
|
||||
#define SET_C_ADD(a,b) (gpu_flag_c = ((uint32_t)(b) > (uint32_t)(~(a))))
|
||||
#define SET_C_SUB(a,b) (gpu_flag_c = ((uint32_t)(b) > (uint32_t)(a)))
|
||||
#define SET_ZN(r) SET_N(r); SET_Z(r)
|
||||
#define SET_ZNC_ADD(a,b,r) SET_N(r); SET_Z(r); SET_C_ADD(a,b)
|
||||
#define SET_ZNC_SUB(a,b,r) SET_N(r); SET_Z(r); SET_C_SUB(a,b)
|
||||
|
||||
uint32_t gpu_convert_zero[32] =
|
||||
{ 32,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31 };
|
||||
|
||||
uint8_t * branch_condition_table = 0;
|
||||
#define BRANCH_CONDITION(x) branch_condition_table[(x) + ((jaguar_flags & 7) << 5)]
|
||||
static uint8_t branch_condition_table[32 * 8];
|
||||
|
||||
bool GPURunning(void)
|
||||
{
|
||||
|
@ -222,32 +193,25 @@ bool GPURunning(void)
|
|||
|
||||
void build_branch_condition_table(void)
|
||||
{
|
||||
if (!branch_condition_table)
|
||||
for(int i=0; i<8; i++)
|
||||
{
|
||||
branch_condition_table = (uint8_t *)malloc(32 * 8 * sizeof(branch_condition_table[0]));
|
||||
|
||||
if (branch_condition_table)
|
||||
for(int j=0; j<32; j++)
|
||||
{
|
||||
for(int i=0; i<8; i++)
|
||||
{
|
||||
for(int j=0; j<32; j++)
|
||||
{
|
||||
int result = 1;
|
||||
if (j & 1)
|
||||
if (i & ZERO_FLAG)
|
||||
result = 0;
|
||||
if (j & 2)
|
||||
if (!(i & ZERO_FLAG))
|
||||
result = 0;
|
||||
if (j & 4)
|
||||
if (i & (CARRY_FLAG << (j >> 4)))
|
||||
result = 0;
|
||||
if (j & 8)
|
||||
if (!(i & (CARRY_FLAG << (j >> 4))))
|
||||
result = 0;
|
||||
branch_condition_table[i * 32 + j] = result;
|
||||
}
|
||||
}
|
||||
int result = 1;
|
||||
|
||||
if ((j & 1) && (i & ZERO_FLAG))
|
||||
result = 0;
|
||||
|
||||
if ((j & 2) && (!(i & ZERO_FLAG)))
|
||||
result = 0;
|
||||
|
||||
if ((j & 4) && (i & (CARRY_FLAG << (j >> 4))))
|
||||
result = 0;
|
||||
|
||||
if ((j & 8) && (!(i & (CARRY_FLAG << (j >> 4)))))
|
||||
result = 0;
|
||||
|
||||
branch_condition_table[i * 32 + j] = result;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -601,7 +565,7 @@ void GPUReset(void)
|
|||
for(int i=0; i<32; i++)
|
||||
gpu_reg[i] = gpu_alternate_reg[i] = 0x00000000;
|
||||
|
||||
CLR_ZNC;
|
||||
gpu_flag_z = gpu_flag_n = gpu_flag_c = 0;
|
||||
memset(gpu_ram_8, 0xFF, 0x1000);
|
||||
|
||||
for(uint32_t i=0; i<4096; i+=4)
|
||||
|
@ -643,565 +607,6 @@ void GPUExec(int32_t cycles)
|
|||
// GPU opcodes
|
||||
//
|
||||
|
||||
static void gpu_opcode_jump(void)
|
||||
{
|
||||
uint32_t jaguar_flags = (gpu_flag_n << 2) | (gpu_flag_c << 1) | gpu_flag_z;
|
||||
#define RISC 3
|
||||
|
||||
if (BRANCH_CONDITION(IMM_2))
|
||||
{
|
||||
uint32_t delayed_pc = RM;
|
||||
GPUExec(1);
|
||||
gpu_pc = delayed_pc;
|
||||
}
|
||||
}
|
||||
|
||||
static void gpu_opcode_jr(void)
|
||||
{
|
||||
uint32_t jaguar_flags = (gpu_flag_n << 2) | (gpu_flag_c << 1) | gpu_flag_z;
|
||||
|
||||
if (BRANCH_CONDITION(IMM_2))
|
||||
{
|
||||
int32_t offset = (IMM_1 & 0x10 ? 0xFFFFFFF0 | IMM_1 : IMM_1);
|
||||
int32_t delayed_pc = gpu_pc + (offset * 2);
|
||||
GPUExec(1);
|
||||
gpu_pc = delayed_pc;
|
||||
}
|
||||
}
|
||||
|
||||
static void gpu_opcode_add(void)
|
||||
{
|
||||
uint32_t res = RN + RM;
|
||||
CLR_ZNC; SET_ZNC_ADD(RN, RM, res);
|
||||
RN = res;
|
||||
}
|
||||
|
||||
static void gpu_opcode_addc(void)
|
||||
{
|
||||
uint32_t res = RN + RM + gpu_flag_c;
|
||||
uint32_t carry = gpu_flag_c;
|
||||
SET_ZNC_ADD(RN + carry, RM, res);
|
||||
RN = res;
|
||||
}
|
||||
|
||||
static void gpu_opcode_addq(void)
|
||||
{
|
||||
uint32_t r1 = gpu_convert_zero[IMM_1];
|
||||
uint32_t res = RN + r1;
|
||||
CLR_ZNC; SET_ZNC_ADD(RN, r1, res);
|
||||
RN = res;
|
||||
}
|
||||
|
||||
static void gpu_opcode_addqt(void)
|
||||
{
|
||||
RN += gpu_convert_zero[IMM_1];
|
||||
}
|
||||
|
||||
static void gpu_opcode_sub(void)
|
||||
{
|
||||
uint32_t res = RN - RM;
|
||||
SET_ZNC_SUB(RN, RM, res);
|
||||
RN = res;
|
||||
}
|
||||
|
||||
static void gpu_opcode_subc(void)
|
||||
{
|
||||
uint64_t res = (uint64_t)RN + (uint64_t)(RM ^ 0xFFFFFFFF) + (gpu_flag_c ^ 1);
|
||||
gpu_flag_c = ((res >> 32) & 0x01) ^ 1;
|
||||
RN = (res & 0xFFFFFFFF);
|
||||
SET_ZN(RN);
|
||||
}
|
||||
|
||||
static void gpu_opcode_subq(void)
|
||||
{
|
||||
uint32_t r1 = gpu_convert_zero[IMM_1];
|
||||
uint32_t res = RN - r1;
|
||||
SET_ZNC_SUB(RN, r1, res);
|
||||
RN = res;
|
||||
}
|
||||
|
||||
static void gpu_opcode_subqt(void)
|
||||
{
|
||||
RN -= gpu_convert_zero[IMM_1];
|
||||
}
|
||||
|
||||
static void gpu_opcode_cmp(void)
|
||||
{
|
||||
uint32_t res = RN - RM;
|
||||
SET_ZNC_SUB(RN, RM, res);
|
||||
}
|
||||
|
||||
static void gpu_opcode_cmpq(void)
|
||||
{
|
||||
static int32_t sqtable[32] =
|
||||
{ 0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,-16,-15,-14,-13,-12,-11,-10,-9,-8,-7,-6,-5,-4,-3,-2,-1 };
|
||||
|
||||
uint32_t r1 = sqtable[IMM_1 & 0x1F];
|
||||
uint32_t res = RN - r1;
|
||||
SET_ZNC_SUB(RN, r1, res);
|
||||
}
|
||||
|
||||
static void gpu_opcode_and(void)
|
||||
{
|
||||
RN = RN & RM;
|
||||
SET_ZN(RN);
|
||||
}
|
||||
|
||||
static void gpu_opcode_or(void)
|
||||
{
|
||||
RN = RN | RM;
|
||||
SET_ZN(RN);
|
||||
}
|
||||
|
||||
static void gpu_opcode_xor(void)
|
||||
{
|
||||
RN = RN ^ RM;
|
||||
SET_ZN(RN);
|
||||
}
|
||||
|
||||
static void gpu_opcode_not(void)
|
||||
{
|
||||
RN = ~RN;
|
||||
SET_ZN(RN);
|
||||
}
|
||||
|
||||
static void gpu_opcode_move_pc(void)
|
||||
{
|
||||
RN = gpu_pc - 2;
|
||||
}
|
||||
|
||||
static void gpu_opcode_sat8(void)
|
||||
{
|
||||
RN = ((int32_t)RN < 0 ? 0 : (RN > 0xFF ? 0xFF : RN));
|
||||
SET_ZN(RN);
|
||||
}
|
||||
|
||||
static void gpu_opcode_sat16(void)
|
||||
{
|
||||
RN = ((int32_t)RN < 0 ? 0 : (RN > 0xFFFF ? 0xFFFF : RN));
|
||||
SET_ZN(RN);
|
||||
}
|
||||
|
||||
static void gpu_opcode_sat24(void)
|
||||
{
|
||||
RN = ((int32_t)RN < 0 ? 0 : (RN > 0xFFFFFF ? 0xFFFFFF : RN));
|
||||
SET_ZN(RN);
|
||||
}
|
||||
|
||||
static void gpu_opcode_store_r14_indexed(void)
|
||||
{
|
||||
uint32_t address = gpu_reg[14] + (gpu_convert_zero[IMM_1] << 2);
|
||||
|
||||
if (address >= 0xF03000 && address <= 0xF03FFF)
|
||||
GPUWriteLong(address & 0xFFFFFFFC, RN, GPU);
|
||||
else
|
||||
GPUWriteLong(address, RN, GPU);
|
||||
}
|
||||
|
||||
static void gpu_opcode_store_r15_indexed(void)
|
||||
{
|
||||
uint32_t address = gpu_reg[15] + (gpu_convert_zero[IMM_1] << 2);
|
||||
|
||||
if (address >= 0xF03000 && address <= 0xF03FFF)
|
||||
GPUWriteLong(address & 0xFFFFFFFC, RN, GPU);
|
||||
else
|
||||
GPUWriteLong(address, RN, GPU);
|
||||
}
|
||||
|
||||
static void gpu_opcode_load_r14_ri(void)
|
||||
{
|
||||
uint32_t address = gpu_reg[14] + RM;
|
||||
|
||||
if (address >= 0xF03000 && address <= 0xF03FFF)
|
||||
RN = GPUReadLong(address & 0xFFFFFFFC, GPU);
|
||||
else
|
||||
RN = GPUReadLong(address, GPU);
|
||||
}
|
||||
|
||||
static void gpu_opcode_load_r15_ri(void)
|
||||
{
|
||||
uint32_t address = gpu_reg[15] + RM;
|
||||
|
||||
if (address >= 0xF03000 && address <= 0xF03FFF)
|
||||
RN = GPUReadLong(address & 0xFFFFFFFC, GPU);
|
||||
else
|
||||
RN = GPUReadLong(address, GPU);
|
||||
}
|
||||
|
||||
static void gpu_opcode_store_r14_ri(void)
|
||||
{
|
||||
uint32_t address = gpu_reg[14] + RM;
|
||||
|
||||
if (address >= 0xF03000 && address <= 0xF03FFF)
|
||||
GPUWriteLong(address & 0xFFFFFFFC, RN, GPU);
|
||||
else
|
||||
GPUWriteLong(address, RN, GPU);
|
||||
}
|
||||
|
||||
static void gpu_opcode_store_r15_ri(void)
|
||||
{
|
||||
GPUWriteLong(gpu_reg[15] + RM, RN, GPU);
|
||||
}
|
||||
|
||||
static void gpu_opcode_nop(void)
|
||||
{
|
||||
}
|
||||
|
||||
static void gpu_opcode_pack(void)
|
||||
{
|
||||
uint32_t val = RN;
|
||||
|
||||
if (IMM_1 == 0)
|
||||
RN = ((val >> 10) & 0x0000F000) | ((val >> 5) & 0x00000F00) | (val & 0x000000FF);
|
||||
else
|
||||
RN = ((val & 0x0000F000) << 10) | ((val & 0x00000F00) << 5) | (val & 0x000000FF);
|
||||
}
|
||||
|
||||
static void gpu_opcode_storeb(void)
|
||||
{
|
||||
if ((RM >= 0xF03000) && (RM <= 0xF03FFF))
|
||||
GPUWriteLong(RM & 0xFFFFFFFC, RN, GPU);
|
||||
else
|
||||
JaguarWriteByte(RM, RN, GPU);
|
||||
}
|
||||
|
||||
static void gpu_opcode_storew(void)
|
||||
{
|
||||
if ((RM >= 0xF03000) && (RM <= 0xF03FFF))
|
||||
GPUWriteLong(RM & 0xFFFFFFFC, RN, GPU);
|
||||
else
|
||||
JaguarWriteWord(RM, RN, GPU);
|
||||
}
|
||||
|
||||
static void gpu_opcode_store(void)
|
||||
{
|
||||
if ((RM >= 0xF03000) && (RM <= 0xF03FFF))
|
||||
GPUWriteLong(RM & 0xFFFFFFFC, RN, GPU);
|
||||
else
|
||||
GPUWriteLong(RM, RN, GPU);
|
||||
}
|
||||
|
||||
static void gpu_opcode_storep(void)
|
||||
{
|
||||
if ((RM >= 0xF03000) && (RM <= 0xF03FFF))
|
||||
{
|
||||
GPUWriteLong(RM & 0xFFFFFFFC, RN, GPU);
|
||||
}
|
||||
else
|
||||
{
|
||||
GPUWriteLong(RM + 0, gpu_hidata, GPU);
|
||||
GPUWriteLong(RM + 4, RN, GPU);
|
||||
}
|
||||
}
|
||||
|
||||
static void gpu_opcode_loadb(void)
|
||||
{
|
||||
if ((RM >= 0xF03000) && (RM <= 0xF03FFF))
|
||||
RN = GPUReadLong(RM & 0xFFFFFFFC, GPU);
|
||||
else
|
||||
RN = JaguarReadByte(RM, GPU);
|
||||
}
|
||||
|
||||
static void gpu_opcode_loadw(void)
|
||||
{
|
||||
if ((RM >= 0xF03000) && (RM <= 0xF03FFF))
|
||||
RN = GPUReadLong(RM & 0xFFFFFFFC, GPU);
|
||||
else
|
||||
RN = JaguarReadWord(RM, GPU);
|
||||
}
|
||||
|
||||
static void gpu_opcode_load(void)
|
||||
{
|
||||
RN = GPUReadLong(RM & 0xFFFFFFFC, GPU);
|
||||
}
|
||||
|
||||
static void gpu_opcode_loadp(void)
|
||||
{
|
||||
if ((RM >= 0xF03000) && (RM <= 0xF03FFF))
|
||||
{
|
||||
RN = GPUReadLong(RM & 0xFFFFFFFC, GPU);
|
||||
}
|
||||
else
|
||||
{
|
||||
gpu_hidata = GPUReadLong(RM + 0, GPU);
|
||||
RN = GPUReadLong(RM + 4, GPU);
|
||||
}
|
||||
}
|
||||
|
||||
static void gpu_opcode_load_r14_indexed(void)
|
||||
{
|
||||
uint32_t address = gpu_reg[14] + (gpu_convert_zero[IMM_1] << 2);
|
||||
|
||||
if ((RM >= 0xF03000) && (RM <= 0xF03FFF))
|
||||
RN = GPUReadLong(address & 0xFFFFFFFC, GPU);
|
||||
else
|
||||
RN = GPUReadLong(address, GPU);
|
||||
}
|
||||
|
||||
static void gpu_opcode_load_r15_indexed(void)
|
||||
{
|
||||
uint32_t address = gpu_reg[15] + (gpu_convert_zero[IMM_1] << 2);
|
||||
|
||||
if ((RM >= 0xF03000) && (RM <= 0xF03FFF))
|
||||
RN = GPUReadLong(address & 0xFFFFFFFC, GPU);
|
||||
else
|
||||
RN = GPUReadLong(address, GPU);
|
||||
}
|
||||
|
||||
static void gpu_opcode_movei(void)
|
||||
{
|
||||
RN = (uint32_t)GPUReadWord(gpu_pc, GPU) | ((uint32_t)GPUReadWord(gpu_pc + 2, GPU) << 16);
|
||||
gpu_pc += 4;
|
||||
}
|
||||
|
||||
static void gpu_opcode_moveta(void)
|
||||
{
|
||||
ALTERNATE_RN = RM;
|
||||
}
|
||||
|
||||
static void gpu_opcode_movefa(void)
|
||||
{
|
||||
RN = ALTERNATE_RM;
|
||||
}
|
||||
|
||||
static void gpu_opcode_move(void)
|
||||
{
|
||||
RN = RM;
|
||||
}
|
||||
|
||||
static void gpu_opcode_moveq(void)
|
||||
{
|
||||
RN = IMM_1;
|
||||
}
|
||||
|
||||
static void gpu_opcode_resmac(void)
|
||||
{
|
||||
RN = gpu_acc;
|
||||
}
|
||||
|
||||
static void gpu_opcode_imult(void)
|
||||
{
|
||||
RN = (int16_t)RN * (int16_t)RM;
|
||||
SET_ZN(RN);
|
||||
}
|
||||
|
||||
static void gpu_opcode_mult(void)
|
||||
{
|
||||
RN = (uint16_t)RM * (uint16_t)RN;
|
||||
SET_ZN(RN);
|
||||
}
|
||||
|
||||
static void gpu_opcode_bclr(void)
|
||||
{
|
||||
uint32_t res = RN & ~(1 << IMM_1);
|
||||
RN = res;
|
||||
SET_ZN(res);
|
||||
}
|
||||
|
||||
static void gpu_opcode_btst(void)
|
||||
{
|
||||
gpu_flag_z = (~RN >> IMM_1) & 1;
|
||||
}
|
||||
|
||||
static void gpu_opcode_bset(void)
|
||||
{
|
||||
uint32_t res = RN | (1 << IMM_1);
|
||||
RN = res;
|
||||
SET_ZN(res);
|
||||
}
|
||||
|
||||
static void gpu_opcode_imacn(void)
|
||||
{
|
||||
uint32_t res = (int16_t)RM * (int16_t)(RN);
|
||||
gpu_acc += res;
|
||||
}
|
||||
|
||||
static void gpu_opcode_mtoi(void)
|
||||
{
|
||||
uint32_t _RM = RM;
|
||||
uint32_t res = RN = (((int32_t)_RM >> 8) & 0xFF800000) | (_RM & 0x007FFFFF);
|
||||
SET_ZN(res);
|
||||
}
|
||||
|
||||
static void gpu_opcode_normi(void)
|
||||
{
|
||||
uint32_t _RM = RM;
|
||||
uint32_t res = 0;
|
||||
|
||||
if (_RM)
|
||||
{
|
||||
while ((_RM & 0xFFC00000) == 0)
|
||||
{
|
||||
_RM <<= 1;
|
||||
res--;
|
||||
}
|
||||
while ((_RM & 0xFF800000) != 0)
|
||||
{
|
||||
_RM >>= 1;
|
||||
res++;
|
||||
}
|
||||
}
|
||||
RN = res;
|
||||
SET_ZN(res);
|
||||
}
|
||||
|
||||
static void gpu_opcode_mmult(void)
|
||||
{
|
||||
int count = gpu_matrix_control & 0x0F;
|
||||
uint32_t addr = gpu_pointer_to_matrix;
|
||||
int64_t accum = 0;
|
||||
uint32_t res;
|
||||
|
||||
if (gpu_matrix_control & 0x10)
|
||||
{
|
||||
for(int i=0; i<count; i++)
|
||||
{
|
||||
int16_t a;
|
||||
if (i & 0x01)
|
||||
a = (int16_t)((gpu_alternate_reg[IMM_1 + (i >> 1)] >> 16) & 0xFFFF);
|
||||
else
|
||||
a = (int16_t)(gpu_alternate_reg[IMM_1 + (i >> 1)] & 0xFFFF);
|
||||
|
||||
int16_t b = ((int16_t)GPUReadWord(addr + 2, GPU));
|
||||
accum += a * b;
|
||||
addr += 4 * count;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
for(int i=0; i<count; i++)
|
||||
{
|
||||
int16_t a;
|
||||
if (i & 0x01)
|
||||
a = (int16_t)((gpu_alternate_reg[IMM_1 + (i >> 1)] >> 16) & 0xFFFF);
|
||||
else
|
||||
a = (int16_t)(gpu_alternate_reg[IMM_1 + (i >> 1)] & 0xFFFF);
|
||||
|
||||
int16_t b = ((int16_t)GPUReadWord(addr + 2, GPU));
|
||||
accum += a * b;
|
||||
addr += 4;
|
||||
}
|
||||
}
|
||||
RN = res = (int32_t)accum;
|
||||
SET_ZN(res);
|
||||
}
|
||||
|
||||
static void gpu_opcode_abs(void)
|
||||
{
|
||||
gpu_flag_c = RN >> 31;
|
||||
if (RN == 0x80000000)
|
||||
gpu_flag_n = 1, gpu_flag_z = 0;
|
||||
else
|
||||
{
|
||||
if (gpu_flag_c)
|
||||
RN = -RN;
|
||||
gpu_flag_n = 0; SET_FLAG_Z(RN);
|
||||
}
|
||||
}
|
||||
|
||||
static void gpu_opcode_div(void)
|
||||
{
|
||||
uint32_t q = RN;
|
||||
uint32_t r = 0;
|
||||
|
||||
if (gpu_div_control & 0x01)
|
||||
q <<= 16, r = RN >> 16;
|
||||
|
||||
for(int i=0; i<32; i++)
|
||||
{
|
||||
uint32_t sign = r & 0x80000000;
|
||||
r = (r << 1) | ((q >> 31) & 0x01);
|
||||
r += (sign ? RM : -RM);
|
||||
q = (q << 1) | (((~r) >> 31) & 0x01);
|
||||
}
|
||||
|
||||
RN = q;
|
||||
gpu_remain = r;
|
||||
}
|
||||
|
||||
static void gpu_opcode_imultn(void)
|
||||
{
|
||||
uint32_t res = (int32_t)((int16_t)RN * (int16_t)RM);
|
||||
gpu_acc = (int32_t)res;
|
||||
SET_FLAG_Z(res);
|
||||
SET_FLAG_N(res);
|
||||
}
|
||||
|
||||
static void gpu_opcode_neg(void)
|
||||
{
|
||||
uint32_t res = -RN;
|
||||
SET_ZNC_SUB(0, RN, res);
|
||||
RN = res;
|
||||
}
|
||||
|
||||
static void gpu_opcode_shlq(void)
|
||||
{
|
||||
int32_t r1 = 32 - IMM_1;
|
||||
uint32_t res = RN << r1;
|
||||
SET_ZN(res); gpu_flag_c = (RN >> 31) & 1;
|
||||
RN = res;
|
||||
}
|
||||
|
||||
static void gpu_opcode_shrq(void)
|
||||
{
|
||||
int32_t r1 = gpu_convert_zero[IMM_1];
|
||||
uint32_t res = RN >> r1;
|
||||
SET_ZN(res); gpu_flag_c = RN & 1;
|
||||
RN = res;
|
||||
}
|
||||
|
||||
static void gpu_opcode_ror(void)
|
||||
{
|
||||
uint32_t r1 = RM & 0x1F;
|
||||
uint32_t res = (RN >> r1) | (RN << (32 - r1));
|
||||
SET_ZN(res); gpu_flag_c = (RN >> 31) & 1;
|
||||
RN = res;
|
||||
}
|
||||
|
||||
static void gpu_opcode_rorq(void)
|
||||
{
|
||||
uint32_t r1 = gpu_convert_zero[IMM_1 & 0x1F];
|
||||
uint32_t r2 = RN;
|
||||
uint32_t res = (r2 >> r1) | (r2 << (32 - r1));
|
||||
RN = res;
|
||||
SET_ZN(res); gpu_flag_c = (r2 >> 31) & 0x01;
|
||||
}
|
||||
|
||||
static void gpu_opcode_sha(void)
|
||||
{
|
||||
uint32_t res;
|
||||
|
||||
if ((int32_t)RM < 0)
|
||||
{
|
||||
res = ((int32_t)RM <= -32) ? 0 : (RN << -(int32_t)RM);
|
||||
gpu_flag_c = RN >> 31;
|
||||
}
|
||||
else
|
||||
{
|
||||
res = ((int32_t)RM >= 32) ? ((int32_t)RN >> 31) : ((int32_t)RN >> (int32_t)RM);
|
||||
gpu_flag_c = RN & 0x01;
|
||||
}
|
||||
RN = res;
|
||||
SET_ZN(res);
|
||||
}
|
||||
|
||||
static void gpu_opcode_sharq(void)
|
||||
{
|
||||
uint32_t res = (int32_t)RN >> gpu_convert_zero[IMM_1];
|
||||
SET_ZN(res); gpu_flag_c = RN & 0x01;
|
||||
RN = res;
|
||||
}
|
||||
|
||||
static void gpu_opcode_sh(void)
|
||||
{
|
||||
if (RM & 0x80000000)
|
||||
{
|
||||
gpu_flag_c = RN >> 31;
|
||||
RN = ((int32_t)RM <= -32 ? 0 : RN << -(int32_t)RM);
|
||||
}
|
||||
else
|
||||
{
|
||||
gpu_flag_c = RN & 0x01;
|
||||
RN = (RM >= 32 ? 0 : RN >> RM);
|
||||
}
|
||||
SET_ZN(RN);
|
||||
}
|
||||
#include "risc_opcodes.h"
|
||||
|
|
|
@ -0,0 +1,706 @@
|
|||
// memory.h has GPU == 3 and DSP == 2
|
||||
|
||||
#if RISC == 3
|
||||
#define RISC_OPCODE(op) static void gpu_opcode_##op(void)
|
||||
#define risc_opcode gpu_opcode
|
||||
#define IMM_1 gpu_opcode_first_parameter
|
||||
#define IMM_2 gpu_opcode_second_parameter
|
||||
#define risc_flag_n gpu_flag_n
|
||||
#define risc_flag_c gpu_flag_c
|
||||
#define risc_flag_z gpu_flag_z
|
||||
#define risc_pc gpu_pc
|
||||
#define risc_reg gpu_reg
|
||||
#define risc_alternate_reg gpu_alternate_reg
|
||||
#define risc_acc gpu_acc
|
||||
#define risc_matrix_control gpu_matrix_control
|
||||
#define risc_pointer_to_matrix gpu_pointer_to_matrix
|
||||
#define risc_div_control gpu_div_control
|
||||
#define risc_remain gpu_remain
|
||||
#define IS_RISC_RAM(x) x >= GPU_WORK_RAM_BASE && x <= (GPU_WORK_RAM_BASE + 0xFFF)
|
||||
#define RISCReadWord(x, y) GPUReadWord(x, y)
|
||||
#define RISCReadLong(x, y) GPUReadLong(x, y)
|
||||
#define RISCWriteLong(x, y, z) GPUWriteLong(x, y, z)
|
||||
#elif RISC == 2
|
||||
#define RISC_OPCODE(op) static void dsp_opcode_##op(void)
|
||||
#define risc_opcode dsp_opcode
|
||||
#define IMM_1 dsp_opcode_first_parameter
|
||||
#define IMM_2 dsp_opcode_second_parameter
|
||||
#define risc_flag_n dsp_flag_n
|
||||
#define risc_flag_c dsp_flag_c
|
||||
#define risc_flag_z dsp_flag_z
|
||||
#define risc_pc dsp_pc
|
||||
#define risc_reg dsp_reg
|
||||
#define risc_alternate_reg dsp_alternate_reg
|
||||
#define risc_acc dsp_acc
|
||||
#define risc_matrix_control dsp_matrix_control
|
||||
#define risc_pointer_to_matrix dsp_pointer_to_matrix
|
||||
#define risc_div_control dsp_div_control
|
||||
#define risc_remain dsp_remain
|
||||
#define IS_RISC_RAM(x) x >= DSP_WORK_RAM_BASE && x <= (DSP_WORK_RAM_BASE + 0x1FFF)
|
||||
#define RISCReadWord(x, y) DSPReadWord(x, y)
|
||||
#define RISCReadLong(x, y) DSPReadLong(x, y)
|
||||
#define RISCWriteLong(x, y, z) DSPWriteLong(x, y, z)
|
||||
#else
|
||||
#error RISC improperly defined
|
||||
#endif
|
||||
|
||||
#define RM risc_reg[IMM_1]
|
||||
#define RN risc_reg[IMM_2]
|
||||
#define ALTERNATE_RM risc_alternate_reg[IMM_1]
|
||||
#define ALTERNATE_RN risc_alternate_reg[IMM_2]
|
||||
|
||||
#define CLR_Z (risc_flag_z = 0)
|
||||
#define CLR_ZN (risc_flag_z = risc_flag_n = 0)
|
||||
#define CLR_ZNC (risc_flag_z = risc_flag_n = risc_flag_c = 0)
|
||||
#define SET_Z(r) (risc_flag_z = ((r) == 0))
|
||||
#define SET_N(r) (risc_flag_n = (((uint32_t)(r) >> 31) & 0x01))
|
||||
#define SET_C_ADD(a,b) (risc_flag_c = ((uint32_t)(b) > (uint32_t)(~(a))))
|
||||
#define SET_C_SUB(a,b) (risc_flag_c = ((uint32_t)(b) > (uint32_t)(a)))
|
||||
#define SET_ZN(r) SET_N(r); SET_Z(r)
|
||||
#define SET_ZNC_ADD(a,b,r) SET_N(r); SET_Z(r); SET_C_ADD(a,b)
|
||||
#define SET_ZNC_SUB(a,b,r) SET_N(r); SET_Z(r); SET_C_SUB(a,b)
|
||||
|
||||
#define BRANCH_CONDITION(x) branch_condition_table[(x) + ((risc_flags & 7) << 5)]
|
||||
|
||||
#if 0
|
||||
#include <stdio.h>
|
||||
#define ALERT_UNALIGNED_LONG(x) if (x & 3) fprintf(stderr, "unaligned long access in %s\n", __func__)
|
||||
#define ALERT_UNALIGNED_WORD(x) if (x & 1) fprintf(stderr, "unaligned word access in %s\n", __func__)
|
||||
#else
|
||||
#define ALERT_UNALIGNED_LONG(x)
|
||||
#define ALERT_UNALIGNED_WORD(x)
|
||||
#endif
|
||||
|
||||
static const uint32_t risc_convert_zero[32] = {
|
||||
32, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16,
|
||||
17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31
|
||||
};
|
||||
|
||||
RISC_OPCODE(jump)
|
||||
{
|
||||
uint32_t risc_flags = (risc_flag_n << 2) | (risc_flag_c << 1) | risc_flag_z;
|
||||
|
||||
if (BRANCH_CONDITION(IMM_2))
|
||||
{
|
||||
uint32_t delayed_pc = RM;
|
||||
uint16_t opcode = RISCReadWord(risc_pc, RISC);
|
||||
IMM_1 = (opcode >> 5) & 0x1F;
|
||||
IMM_2 = opcode & 0x1F;
|
||||
risc_opcode[opcode >> 10]();
|
||||
risc_pc = delayed_pc;
|
||||
}
|
||||
}
|
||||
|
||||
RISC_OPCODE(jr)
|
||||
{
|
||||
uint32_t risc_flags = (risc_flag_n << 2) | (risc_flag_c << 1) | risc_flag_z;
|
||||
|
||||
if (BRANCH_CONDITION(IMM_2))
|
||||
{
|
||||
int32_t offset = (IMM_1 > 0x10 ? 0xFFFFFFF0 | IMM_1 : IMM_1);
|
||||
int32_t delayed_pc = risc_pc + (offset * 2);
|
||||
uint16_t opcode = RISCReadWord(risc_pc, RISC);
|
||||
IMM_1 = (opcode >> 5) & 0x1F;
|
||||
IMM_2 = opcode & 0x1F;
|
||||
risc_opcode[opcode >> 10]();
|
||||
risc_pc = delayed_pc;
|
||||
}
|
||||
}
|
||||
|
||||
RISC_OPCODE(add)
|
||||
{
|
||||
uint32_t res = RN + RM;
|
||||
SET_ZNC_ADD(RN, RM, res);
|
||||
RN = res;
|
||||
}
|
||||
|
||||
RISC_OPCODE(addc)
|
||||
{
|
||||
uint32_t res = RN + RM + risc_flag_c;
|
||||
uint32_t carry = risc_flag_c;
|
||||
SET_ZNC_ADD(RN, RM + carry, res);
|
||||
RN = res;
|
||||
}
|
||||
|
||||
RISC_OPCODE(addq)
|
||||
{
|
||||
uint32_t r1 = risc_convert_zero[IMM_1];
|
||||
uint32_t res = RN + r1;
|
||||
SET_ZNC_ADD(RN, r1, res);
|
||||
RN = res;
|
||||
}
|
||||
|
||||
RISC_OPCODE(sub)
|
||||
{
|
||||
uint32_t res = RN - RM;
|
||||
SET_ZNC_SUB(RN, RM, res);
|
||||
RN = res;
|
||||
}
|
||||
|
||||
RISC_OPCODE(subc)
|
||||
{
|
||||
uint64_t res = (uint64_t)RN + (uint64_t)(RM ^ 0xFFFFFFFF) + (risc_flag_c ^ 1);
|
||||
risc_flag_c = ((res >> 32) & 0x01) ^ 1;
|
||||
RN = (res & 0xFFFFFFFF);
|
||||
SET_ZN(RN);
|
||||
}
|
||||
|
||||
RISC_OPCODE(subq)
|
||||
{
|
||||
uint32_t r1 = risc_convert_zero[IMM_1];
|
||||
uint32_t res = RN - r1;
|
||||
SET_ZNC_SUB(RN, r1, res);
|
||||
RN = res;
|
||||
}
|
||||
|
||||
RISC_OPCODE(cmp)
|
||||
{
|
||||
uint32_t res = RN - RM;
|
||||
SET_ZNC_SUB(RN, RM, res);
|
||||
}
|
||||
|
||||
RISC_OPCODE(cmpq)
|
||||
{
|
||||
static const int32_t sqtable[32] =
|
||||
{ 0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,-16,-15,-14,-13,-12,-11,-10,-9,-8,-7,-6,-5,-4,-3,-2,-1 };
|
||||
|
||||
uint32_t r1 = sqtable[IMM_1 & 0x1F];
|
||||
uint32_t res = RN - r1;
|
||||
SET_ZNC_SUB(RN, r1, res);
|
||||
}
|
||||
|
||||
RISC_OPCODE(and)
|
||||
{
|
||||
RN = RN & RM;
|
||||
SET_ZN(RN);
|
||||
}
|
||||
|
||||
RISC_OPCODE(or)
|
||||
{
|
||||
RN = RN | RM;
|
||||
SET_ZN(RN);
|
||||
}
|
||||
|
||||
RISC_OPCODE(xor)
|
||||
{
|
||||
RN = RN ^ RM;
|
||||
SET_ZN(RN);
|
||||
}
|
||||
|
||||
RISC_OPCODE(not)
|
||||
{
|
||||
RN = ~RN;
|
||||
SET_ZN(RN);
|
||||
}
|
||||
|
||||
RISC_OPCODE(move_pc)
|
||||
{
|
||||
RN = risc_pc - 2;
|
||||
}
|
||||
|
||||
RISC_OPCODE(store_r14_indexed)
|
||||
{
|
||||
uint32_t address = risc_reg[14] + (risc_convert_zero[IMM_1] << 2);
|
||||
ALERT_UNALIGNED_LONG(address);
|
||||
RISCWriteLong(address & 0xFFFFFFFC, RN, RISC);
|
||||
}
|
||||
|
||||
RISC_OPCODE(store_r15_indexed)
|
||||
{
|
||||
uint32_t address = risc_reg[15] + (risc_convert_zero[IMM_1] << 2);
|
||||
ALERT_UNALIGNED_LONG(address);
|
||||
RISCWriteLong(address & 0xFFFFFFFC, RN, RISC);
|
||||
}
|
||||
|
||||
RISC_OPCODE(load_r14_ri)
|
||||
{
|
||||
uint32_t address = risc_reg[14] + RM;
|
||||
ALERT_UNALIGNED_LONG(address);
|
||||
RN = RISCReadLong(address & 0xFFFFFFFC, RISC);
|
||||
}
|
||||
|
||||
RISC_OPCODE(load_r15_ri)
|
||||
{
|
||||
uint32_t address = risc_reg[15] + RM;
|
||||
ALERT_UNALIGNED_LONG(address);
|
||||
RN = RISCReadLong(address & 0xFFFFFFFC, RISC);
|
||||
}
|
||||
|
||||
RISC_OPCODE(store_r14_ri)
|
||||
{
|
||||
uint32_t address = risc_reg[14] + RM;
|
||||
ALERT_UNALIGNED_LONG(address);
|
||||
RISCWriteLong(address & 0xFFFFFFFC, RN, RISC);
|
||||
}
|
||||
|
||||
RISC_OPCODE(store_r15_ri)
|
||||
{
|
||||
uint32_t address = risc_reg[15] + RM;
|
||||
ALERT_UNALIGNED_LONG(address);
|
||||
RISCWriteLong(address & 0xFFFFFFFC, RN, RISC);
|
||||
}
|
||||
|
||||
RISC_OPCODE(nop)
|
||||
{
|
||||
}
|
||||
|
||||
RISC_OPCODE(storeb)
|
||||
{
|
||||
if (IS_RISC_RAM(RM))
|
||||
RISCWriteLong(RM & 0xFFFFFFFC, RN, RISC);
|
||||
else
|
||||
JaguarWriteByte(RM, RN, RISC);
|
||||
}
|
||||
|
||||
RISC_OPCODE(storew)
|
||||
{
|
||||
ALERT_UNALIGNED_WORD(RM);
|
||||
|
||||
if (IS_RISC_RAM(RM))
|
||||
RISCWriteLong(RM & 0xFFFFFFFC, RN, RISC);
|
||||
else
|
||||
JaguarWriteWord(RM & 0xFFFFFFFE, RN, RISC);
|
||||
}
|
||||
|
||||
RISC_OPCODE(store)
|
||||
{
|
||||
ALERT_UNALIGNED_LONG(RM);
|
||||
RISCWriteLong(RM & 0xFFFFFFFC, RN, RISC);
|
||||
}
|
||||
|
||||
RISC_OPCODE(loadb)
|
||||
{
|
||||
if (IS_RISC_RAM(RM))
|
||||
RN = RISCReadLong(RM & 0xFFFFFFFC, RISC);
|
||||
else
|
||||
RN = JaguarReadByte(RM, RISC);
|
||||
}
|
||||
|
||||
RISC_OPCODE(loadw)
|
||||
{
|
||||
ALERT_UNALIGNED_WORD(RM);
|
||||
|
||||
if (IS_RISC_RAM(RM))
|
||||
RN = RISCReadLong(RM & 0xFFFFFFFC, RISC);
|
||||
else
|
||||
RN = JaguarReadWord(RM & 0xFFFFFFFE, RISC);
|
||||
}
|
||||
|
||||
RISC_OPCODE(load)
|
||||
{
|
||||
ALERT_UNALIGNED_LONG(RM);
|
||||
RN = RISCReadLong(RM & 0xFFFFFFFC, RISC);
|
||||
}
|
||||
|
||||
RISC_OPCODE(load_r14_indexed)
|
||||
{
|
||||
uint32_t address = risc_reg[14] + (risc_convert_zero[IMM_1] << 2);
|
||||
ALERT_UNALIGNED_LONG(address);
|
||||
RN = RISCReadLong(address & 0xFFFFFFFC, RISC);
|
||||
}
|
||||
|
||||
RISC_OPCODE(load_r15_indexed)
|
||||
{
|
||||
uint32_t address = risc_reg[15] + (risc_convert_zero[IMM_1] << 2);
|
||||
ALERT_UNALIGNED_LONG(address);
|
||||
RN = RISCReadLong(address & 0xFFFFFFFC, RISC);
|
||||
}
|
||||
|
||||
RISC_OPCODE(movei)
|
||||
{
|
||||
RN = (uint32_t)RISCReadWord(risc_pc, RISC) | ((uint32_t)RISCReadWord(risc_pc + 2, RISC) << 16);
|
||||
risc_pc += 4;
|
||||
}
|
||||
|
||||
RISC_OPCODE(moveta)
|
||||
{
|
||||
ALTERNATE_RN = RM;
|
||||
}
|
||||
|
||||
RISC_OPCODE(movefa)
|
||||
{
|
||||
RN = ALTERNATE_RM;
|
||||
}
|
||||
|
||||
RISC_OPCODE(move)
|
||||
{
|
||||
RN = RM;
|
||||
}
|
||||
|
||||
RISC_OPCODE(moveq)
|
||||
{
|
||||
RN = IMM_1;
|
||||
}
|
||||
|
||||
RISC_OPCODE(resmac)
|
||||
{
|
||||
RN = risc_acc;
|
||||
}
|
||||
|
||||
RISC_OPCODE(imult)
|
||||
{
|
||||
RN = (int16_t)RN * (int16_t)RM;
|
||||
SET_ZN(RN);
|
||||
}
|
||||
|
||||
RISC_OPCODE(mult)
|
||||
{
|
||||
RN = (uint16_t)RM * (uint16_t)RN;
|
||||
SET_ZN(RN);
|
||||
}
|
||||
|
||||
RISC_OPCODE(bclr)
|
||||
{
|
||||
uint32_t res = RN & ~(1 << IMM_1);
|
||||
RN = res;
|
||||
SET_ZN(res);
|
||||
}
|
||||
|
||||
RISC_OPCODE(btst)
|
||||
{
|
||||
risc_flag_z = (~RN >> IMM_1) & 1;
|
||||
}
|
||||
|
||||
RISC_OPCODE(bset)
|
||||
{
|
||||
uint32_t res = RN | (1 << IMM_1);
|
||||
RN = res;
|
||||
SET_ZN(res);
|
||||
}
|
||||
|
||||
RISC_OPCODE(subqt)
|
||||
{
|
||||
RN -= risc_convert_zero[IMM_1];
|
||||
}
|
||||
|
||||
RISC_OPCODE(addqt)
|
||||
{
|
||||
RN += risc_convert_zero[IMM_1];
|
||||
}
|
||||
|
||||
RISC_OPCODE(imacn)
|
||||
{
|
||||
int32_t res = (int16_t)RM * (int16_t)RN;
|
||||
risc_acc += res;
|
||||
}
|
||||
|
||||
RISC_OPCODE(mtoi)
|
||||
{
|
||||
uint32_t _RM = RM;
|
||||
uint32_t res = RN = (((int32_t)_RM >> 8) & 0xFF800000) | (_RM & 0x007FFFFF);
|
||||
SET_ZN(res);
|
||||
}
|
||||
|
||||
RISC_OPCODE(normi)
|
||||
{
|
||||
uint32_t _Rm = RM;
|
||||
uint32_t res = 0;
|
||||
|
||||
if (_Rm)
|
||||
{
|
||||
while ((_Rm & 0xffc00000) == 0)
|
||||
{
|
||||
_Rm <<= 1;
|
||||
res--;
|
||||
}
|
||||
while ((_Rm & 0xff800000) != 0)
|
||||
{
|
||||
_Rm >>= 1;
|
||||
res++;
|
||||
}
|
||||
}
|
||||
|
||||
RN = res;
|
||||
SET_ZN(RN);
|
||||
}
|
||||
|
||||
RISC_OPCODE(mmult)
|
||||
{
|
||||
int count = risc_matrix_control&0x0f;
|
||||
uint32_t addr = risc_pointer_to_matrix;
|
||||
int64_t accum = 0;
|
||||
uint32_t res;
|
||||
|
||||
if (!(risc_matrix_control & 0x10))
|
||||
{
|
||||
for (int i = 0; i < count; i++)
|
||||
{
|
||||
int16_t a;
|
||||
if (i & 0x01)
|
||||
a = (int16_t)((risc_alternate_reg[IMM_1 + (i >> 1)] >> 16) & 0xffff);
|
||||
else
|
||||
a = (int16_t)(risc_alternate_reg[IMM_1 + (i >> 1)] & 0xffff);
|
||||
|
||||
int16_t b = (int16_t)RISCReadWord(addr, RISC);
|
||||
accum += a * b;
|
||||
addr += 2;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
for (int i = 0; i < count; i++)
|
||||
{
|
||||
int16_t a;
|
||||
if (i & 0x01)
|
||||
a = (int16_t)((risc_alternate_reg[IMM_1 + (i >> 1)] >> 16) & 0xffff);
|
||||
else
|
||||
a = (int16_t)(risc_alternate_reg[IMM_1 + (i >> 1)] & 0xffff);
|
||||
|
||||
int16_t b = (int16_t)RISCReadWord(addr, RISC);
|
||||
accum += a * b;
|
||||
addr += 2 * count;
|
||||
}
|
||||
}
|
||||
|
||||
RN = res = (uint32_t)accum;
|
||||
SET_ZN(RN);
|
||||
}
|
||||
|
||||
RISC_OPCODE(abs)
|
||||
{
|
||||
uint32_t _Rn = RN;
|
||||
uint32_t res;
|
||||
|
||||
risc_flag_c = ((_Rn & 0x80000000) >> 31);
|
||||
res = RN = (_Rn > 0x80000000 ? -_Rn : _Rn);
|
||||
CLR_ZN; SET_Z(res);
|
||||
}
|
||||
|
||||
RISC_OPCODE(div)
|
||||
{
|
||||
uint32_t q = RN;
|
||||
uint32_t r = 0;
|
||||
|
||||
if (risc_div_control & 0x01)
|
||||
q <<= 16, r = RN >> 16;
|
||||
|
||||
for(int i=0; i<32; i++)
|
||||
{
|
||||
uint32_t sign = r & 0x80000000;
|
||||
r = (r << 1) | ((q >> 31) & 0x01);
|
||||
r += (sign ? RM : -RM);
|
||||
q = (q << 1) | (((~r) >> 31) & 0x01);
|
||||
}
|
||||
|
||||
RN = q;
|
||||
risc_remain = r;
|
||||
}
|
||||
|
||||
RISC_OPCODE(imultn)
|
||||
{
|
||||
uint32_t res = (int16_t)RN * (int16_t)RM;
|
||||
risc_acc = (int32_t)res;
|
||||
SET_ZN(res);
|
||||
|
||||
uint16_t opcode = RISCReadWord(risc_pc, RISC);
|
||||
while ((opcode >> 10) == 20)
|
||||
{
|
||||
IMM_1 = (opcode >> 5) & 0x1F;
|
||||
IMM_2 = opcode & 0x1F;
|
||||
risc_acc += (int32_t)((int16_t)RN * (int16_t)RM);
|
||||
risc_pc += 2;
|
||||
opcode = RISCReadWord(risc_pc, RISC);
|
||||
}
|
||||
if ((opcode >> 10) == 19)
|
||||
{
|
||||
RN = risc_acc;
|
||||
risc_pc += 2;
|
||||
}
|
||||
}
|
||||
|
||||
RISC_OPCODE(neg)
|
||||
{
|
||||
uint32_t res = -RN;
|
||||
SET_ZNC_SUB(0, RN, res);
|
||||
RN = res;
|
||||
}
|
||||
|
||||
RISC_OPCODE(shlq)
|
||||
{
|
||||
int32_t r1 = 32 - IMM_1;
|
||||
uint32_t res = RN << r1;
|
||||
SET_ZN(res); risc_flag_c = (RN >> 31) & 1;
|
||||
RN = res;
|
||||
}
|
||||
|
||||
RISC_OPCODE(shrq)
|
||||
{
|
||||
int32_t r1 = risc_convert_zero[IMM_1];
|
||||
uint32_t res = RN >> r1;
|
||||
SET_ZN(res); risc_flag_c = RN & 1;
|
||||
RN = res;
|
||||
}
|
||||
|
||||
RISC_OPCODE(ror)
|
||||
{
|
||||
uint32_t r1 = RM & 0x1F;
|
||||
uint32_t res = (RN >> r1) | (RN << (32 - r1));
|
||||
SET_ZN(res); risc_flag_c = (RN >> 31) & 1;
|
||||
RN = res;
|
||||
}
|
||||
|
||||
RISC_OPCODE(rorq)
|
||||
{
|
||||
uint32_t r1 = risc_convert_zero[IMM_1 & 0x1F];
|
||||
uint32_t r2 = RN;
|
||||
uint32_t res = (r2 >> r1) | (r2 << (32 - r1));
|
||||
RN = res;
|
||||
SET_ZN(res); risc_flag_c = (r2 >> 31) & 0x01;
|
||||
}
|
||||
|
||||
RISC_OPCODE(sha)
|
||||
{
|
||||
uint32_t res;
|
||||
|
||||
if (RM & 0x80000000)
|
||||
{
|
||||
res = ((int32_t)RM <= -32) ? 0 : (RN << -(int32_t)RM);
|
||||
risc_flag_c = RN >> 31;
|
||||
}
|
||||
else
|
||||
{
|
||||
res = ((int32_t)RM >= 32) ? ((int32_t)RN >> 31) : ((int32_t)RN >> (int32_t)RM);
|
||||
risc_flag_c = RN & 0x01;
|
||||
}
|
||||
|
||||
RN = res;
|
||||
SET_ZN(res);
|
||||
}
|
||||
|
||||
RISC_OPCODE(sharq)
|
||||
{
|
||||
uint32_t res = (int32_t)RN >> risc_convert_zero[IMM_1];
|
||||
SET_ZN(res); risc_flag_c = RN & 0x01;
|
||||
RN = res;
|
||||
}
|
||||
|
||||
RISC_OPCODE(sh)
|
||||
{
|
||||
if (RM & 0x80000000)
|
||||
{
|
||||
RN = ((int32_t)RM <= -32) ? 0 : (RN << -(int32_t)RM);
|
||||
risc_flag_c = RN >> 31;
|
||||
}
|
||||
else
|
||||
{
|
||||
RN = ((int32_t)RM >= 32) ? 0 : (RN >> RM);
|
||||
risc_flag_c = RN & 0x01;
|
||||
}
|
||||
|
||||
SET_ZN(RN);
|
||||
}
|
||||
|
||||
#if RISC == 3
|
||||
|
||||
RISC_OPCODE(sat8)
|
||||
{
|
||||
RN = ((int32_t)RN < 0 ? 0 : (RN > 0xFF ? 0xFF : RN));
|
||||
SET_ZN(RN);
|
||||
}
|
||||
|
||||
RISC_OPCODE(sat16)
|
||||
{
|
||||
RN = ((int32_t)RN < 0 ? 0 : (RN > 0xFFFF ? 0xFFFF : RN));
|
||||
SET_ZN(RN);
|
||||
}
|
||||
|
||||
RISC_OPCODE(sat24)
|
||||
{
|
||||
RN = ((int32_t)RN < 0 ? 0 : (RN > 0xFFFFFF ? 0xFFFFFF : RN));
|
||||
SET_ZN(RN);
|
||||
}
|
||||
|
||||
RISC_OPCODE(pack)
|
||||
{
|
||||
uint32_t val = RN;
|
||||
|
||||
if (IMM_1 == 0)
|
||||
RN = ((val >> 10) & 0x0000F000) | ((val >> 5) & 0x00000F00) | (val & 0x000000FF);
|
||||
else
|
||||
RN = ((val & 0x0000F000) << 10) | ((val & 0x00000F00) << 5) | (val & 0x000000FF);
|
||||
}
|
||||
|
||||
RISC_OPCODE(storep)
|
||||
{
|
||||
ALERT_UNALIGNED_LONG(RM);
|
||||
|
||||
if (IS_RISC_RAM(RM))
|
||||
{
|
||||
RISCWriteLong(RM & 0xFFFFFFFC, RN, RISC);
|
||||
}
|
||||
else
|
||||
{
|
||||
RISCWriteLong((RM + 0) & 0xFFFFFFFC, gpu_hidata, RISC);
|
||||
RISCWriteLong((RM + 4) & 0xFFFFFFFC, RN, RISC);
|
||||
}
|
||||
}
|
||||
|
||||
RISC_OPCODE(loadp)
|
||||
{
|
||||
ALERT_UNALIGNED_LONG(RM);
|
||||
|
||||
if (IS_RISC_RAM(RM))
|
||||
{
|
||||
RN = RISCReadLong(RM & 0xFFFFFFFC, RISC);
|
||||
}
|
||||
else
|
||||
{
|
||||
gpu_hidata = RISCReadLong((RM + 0) & 0xFFFFFFFC, RISC);
|
||||
RN = RISCReadLong((RM + 4) & 0xFFFFFFFC, RISC);
|
||||
}
|
||||
}
|
||||
|
||||
#elif RISC == 2
|
||||
|
||||
RISC_OPCODE(addqmod)
|
||||
{
|
||||
uint32_t r1 = risc_convert_zero[IMM_1];
|
||||
uint32_t r2 = RN;
|
||||
uint32_t res = r2 + r1;
|
||||
res = (res & (~dsp_modulo)) | (r2 & dsp_modulo);
|
||||
RN = res;
|
||||
SET_ZNC_ADD(r2, r1, res);
|
||||
}
|
||||
|
||||
RISC_OPCODE(subqmod)
|
||||
{
|
||||
uint32_t r1 = risc_convert_zero[IMM_1];
|
||||
uint32_t r2 = RN;
|
||||
uint32_t res = r2 - r1;
|
||||
res = (res & (~dsp_modulo)) | (r2 & dsp_modulo);
|
||||
RN = res;
|
||||
|
||||
SET_ZNC_SUB(r2, r1, res);
|
||||
}
|
||||
|
||||
RISC_OPCODE(mirror)
|
||||
{
|
||||
uint32_t r1 = RN;
|
||||
RN = (mirror_table[r1 & 0xFFFF] << 16) | mirror_table[r1 >> 16];
|
||||
SET_ZN(RN);
|
||||
}
|
||||
|
||||
RISC_OPCODE(sat32s)
|
||||
{
|
||||
int32_t r2 = (uint32_t)RN;
|
||||
int32_t temp = risc_acc >> 32;
|
||||
uint32_t res = (temp < -1) ? (int32_t)0x80000000 : (temp > 0) ? (int32_t)0x7FFFFFFF : r2;
|
||||
RN = res;
|
||||
SET_ZN(res);
|
||||
}
|
||||
|
||||
RISC_OPCODE(sat16s)
|
||||
{
|
||||
int32_t r2 = RN;
|
||||
uint32_t res = (r2 < -32768) ? -32768 : (r2 > 32767) ? 32767 : r2;
|
||||
RN = res;
|
||||
SET_ZN(res);
|
||||
}
|
||||
|
||||
RISC_OPCODE(illegal)
|
||||
{
|
||||
}
|
||||
|
||||
#else
|
||||
#error How did this happen?
|
||||
#endif
|
Loading…
Reference in New Issue