[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:
CasualPokePlayer 2022-09-29 21:53:14 -07:00
parent 7b060bada4
commit baa3bdf948
5 changed files with 739 additions and 1203 deletions

Binary file not shown.

View File

@ -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

View File

@ -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"

View File

@ -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"

View File

@ -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