diff --git a/Assets/dll/virtualjaguar.wbx.zst b/Assets/dll/virtualjaguar.wbx.zst index 7b2d90225f..fe6ed4b1df 100644 Binary files a/Assets/dll/virtualjaguar.wbx.zst and b/Assets/dll/virtualjaguar.wbx.zst differ diff --git a/waterbox/virtualjaguar/Makefile b/waterbox/virtualjaguar/Makefile index 4a8481255d..c8ecf9a7a1 100644 --- a/waterbox/virtualjaguar/Makefile +++ b/waterbox/virtualjaguar/Makefile @@ -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 diff --git a/waterbox/virtualjaguar/src/dsp.cpp b/waterbox/virtualjaguar/src/dsp.cpp index 9d997ffdc5..df2643439d 100644 --- a/waterbox/virtualjaguar/src/dsp.cpp +++ b/waterbox/virtualjaguar/src/dsp.cpp @@ -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" diff --git a/waterbox/virtualjaguar/src/gpu.cpp b/waterbox/virtualjaguar/src/gpu.cpp index c3cc625698..36d0c60824 100644 --- a/waterbox/virtualjaguar/src/gpu.cpp +++ b/waterbox/virtualjaguar/src/gpu.cpp @@ -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> 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> 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" diff --git a/waterbox/virtualjaguar/src/risc_opcodes.h b/waterbox/virtualjaguar/src/risc_opcodes.h new file mode 100644 index 0000000000..3009caeb54 --- /dev/null +++ b/waterbox/virtualjaguar/src/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 +#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