nop 41362
*/
+
static void gpu_opcode_jump(void)
{
#ifdef GPU_DIS_JUMP
#endif
}
+
static void gpu_opcode_jr(void)
{
#ifdef GPU_DIS_JR
#endif
}
+
static void gpu_opcode_add(void)
{
#ifdef GPU_DIS_ADD
#endif
}
+
static void gpu_opcode_addc(void)
{
#ifdef GPU_DIS_ADDC
#endif
}
+
static void gpu_opcode_addq(void)
{
#ifdef GPU_DIS_ADDQ
#endif
}
+
static void gpu_opcode_addqt(void)
{
#ifdef GPU_DIS_ADDQT
#endif
}
+
static void gpu_opcode_sub(void)
{
#ifdef GPU_DIS_SUB
#endif
}
+
static void gpu_opcode_subc(void)
{
#ifdef GPU_DIS_SUBC
if (doGPUDis)
WriteLog("%06X: SUBC R%02u, R%02u [NCZ:%u%u%u, R%02u=%08X, R%02u=%08X] -> ", gpu_pc-2, IMM_1, IMM_2, gpu_flag_n, gpu_flag_c, gpu_flag_z, IMM_1, RM, IMM_2, RN);
#endif
- uint32_t res = RN - RM - gpu_flag_c;
- uint32_t borrow = gpu_flag_c;
-// SET_ZNC_SUB(RN, RM, res); //???BUG??? YES!!!
-//No matter how you do it, there is a problem. With below, it's 0-0 with carry,
-//and the one below it it's FFFFFFFF - FFFFFFFF with carry... !!! FIX !!!
-// SET_ZNC_SUB(RN - borrow, RM, res);
- SET_ZNC_SUB(RN, RM + borrow, res);
- RN = res;
+ // This is how the GPU ALU does it--Two's complement with inverted carry
+ uint64_t res = (uint64_t)RN + (uint64_t)(RM ^ 0xFFFFFFFF) + (gpu_flag_c ^ 1);
+ // Carry out of the result is inverted too
+ gpu_flag_c = ((res >> 32) & 0x01) ^ 1;
+ RN = (res & 0xFFFFFFFF);
+ SET_ZN(RN);
#ifdef GPU_DIS_SUBC
if (doGPUDis)
WriteLog("[NCZ:%u%u%u, R%02u=%08X, R%02u=%08X]\n", gpu_flag_n, gpu_flag_c, gpu_flag_z, IMM_1, RM, IMM_2, RN);
#endif
}
-/*
-N = 5, M = 3, 3 - 5 = -2, C = 1... Or, in our case:
-N = 0, M = 1, 0 - 1 = -1, C = 0!
-#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)
-*/
+
static void gpu_opcode_subq(void)
{
#ifdef GPU_DIS_SUBQ
#endif
}
+
static void gpu_opcode_subqt(void)
{
#ifdef GPU_DIS_SUBQT
#endif
}
+
static void gpu_opcode_cmp(void)
{
#ifdef GPU_DIS_CMP
#endif
}
+
static void gpu_opcode_cmpq(void)
{
static int32_t sqtable[32] =
#endif
}
+
static void gpu_opcode_and(void)
{
#ifdef GPU_DIS_AND
#endif
}
+
static void gpu_opcode_or(void)
{
#ifdef GPU_DIS_OR
#endif
}
+
static void gpu_opcode_xor(void)
{
#ifdef GPU_DIS_XOR
#endif
}
+
static void gpu_opcode_not(void)
{
#ifdef GPU_DIS_NOT
#endif
}
+
static void gpu_opcode_move_pc(void)
{
#ifdef GPU_DIS_MOVEPC
#endif
}
+
static void gpu_opcode_sat8(void)
{
#ifdef GPU_DIS_SAT8
#endif
}
+
static void gpu_opcode_sat16(void)
{
RN = ((int32_t)RN < 0 ? 0 : (RN > 0xFFFF ? 0xFFFF : RN));
SET_ZN(RN);
}
+
static void gpu_opcode_store_r14_indexed(void)
{
#ifdef GPU_DIS_STORE14I
#endif
}
+
static void gpu_opcode_store_r15_indexed(void)
{
#ifdef GPU_DIS_STORE15I
#endif
}
+
static void gpu_opcode_load_r14_ri(void)
{
#ifdef GPU_DIS_LOAD14R
#endif
}
+
static void gpu_opcode_load_r15_ri(void)
{
#ifdef GPU_DIS_LOAD15R
#endif
}
+
static void gpu_opcode_store_r14_ri(void)
{
#ifdef GPU_DIS_STORE14R
#endif
}
+
static void gpu_opcode_store_r15_ri(void)
{
#ifdef GPU_DIS_STORE15R
#endif
}
+
static void gpu_opcode_nop(void)
{
#ifdef GPU_DIS_NOP
#endif
}
+
static void gpu_opcode_pack(void)
{
#ifdef GPU_DIS_PACK
#endif
}
+
static void gpu_opcode_storeb(void)
{
#ifdef GPU_DIS_STOREB
JaguarWriteByte(RM, RN, GPU);
}
+
static void gpu_opcode_storew(void)
{
#ifdef GPU_DIS_STOREW
#endif
}
+
static void gpu_opcode_store(void)
{
#ifdef GPU_DIS_STORE
#endif
}
+
static void gpu_opcode_storep(void)
{
#ifdef GPU_CORRECT_ALIGNMENT
#endif
}
+
static void gpu_opcode_loadw(void)
{
#ifdef GPU_DIS_LOADW
#endif
}
+
// According to the docs, & "Do The Same", this address is long aligned...
// So let's try it:
// And it works!!! Need to fix all instances...
#endif
}
+
static void gpu_opcode_loadp(void)
{
#ifdef GPU_CORRECT_ALIGNMENT
#endif
}
+
static void gpu_opcode_load_r14_indexed(void)
{
#ifdef GPU_DIS_LOAD14I
#endif
}
+
static void gpu_opcode_load_r15_indexed(void)
{
#ifdef GPU_DIS_LOAD15I
#endif
}
+
static void gpu_opcode_movei(void)
{
#ifdef GPU_DIS_MOVEI
#endif
}
+
static void gpu_opcode_moveta(void)
{
#ifdef GPU_DIS_MOVETA
#endif
}
+
static void gpu_opcode_movefa(void)
{
#ifdef GPU_DIS_MOVEFA
#endif
}
+
static void gpu_opcode_move(void)
{
#ifdef GPU_DIS_MOVE
#endif
}
+
static void gpu_opcode_moveq(void)
{
#ifdef GPU_DIS_MOVEQ
#endif
}
+
static void gpu_opcode_resmac(void)
{
RN = gpu_acc;
}
+
static void gpu_opcode_imult(void)
{
#ifdef GPU_DIS_IMULT
#endif
}
+
static void gpu_opcode_mult(void)
{
#ifdef GPU_DIS_MULT
#endif
}
+
static void gpu_opcode_bclr(void)
{
#ifdef GPU_DIS_BCLR
#endif
}
+
static void gpu_opcode_btst(void)
{
#ifdef GPU_DIS_BTST
#endif
}
+
static void gpu_opcode_bset(void)
{
#ifdef GPU_DIS_BSET
#endif
}
+
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;
SET_ZN(res);
}
+
static void gpu_opcode_normi(void)
{
uint32_t _RM = RM;
SET_ZN(res);
}
+
static void gpu_opcode_abs(void)
{
#ifdef GPU_DIS_ABS
#endif
}
+
static void gpu_opcode_div(void) // RN / RM
{
#ifdef GPU_DIS_DIV
if (doGPUDis)
WriteLog("%06X: DIV R%02u, R%02u (%s) [NCZ:%u%u%u, R%02u=%08X, R%02u=%08X] -> ", gpu_pc-2, IMM_1, IMM_2, (gpu_div_control & 0x01 ? "16.16" : "32"), gpu_flag_n, gpu_flag_c, gpu_flag_z, IMM_1, RM, IMM_2, RN);
#endif
-// NOTE: remainder is NOT calculated correctly here!
-// The original tried to get it right by checking to see if the
-// remainder was negative, but that's too late...
-// The code there should do it now, but I'm not 100% sure...
-// [Now it should be correct, but not displaying correct behavior of the actual
-// hardware. A step in the right direction.]
-
+#if 0
if (RM)
{
if (gpu_div_control & 0x01) // 16.16 division
gpu_remain = RN % RM;
RN = RN / RM;
}
-
-// What we really should do here is figure out why this condition
-// happens in the real divide unit and emulate *that* behavior.
-#if 0
- if ((gpu_remain - RM) & 0x80000000) // If the result would have been negative...
- gpu_remain -= RM; // Then make it negative!
-#endif
}
else
+ {
+ // This is what happens according to SCPCD. NYAN!
RN = 0xFFFFFFFF;
+ gpu_remain = 0;
+ }
+#else
+ // Real algorithm, courtesy of SCPCD: NYAN!
+ uint32_t q = RN;
+ uint32_t r = 0;
+
+ // If 16.16 division, stuff top 16 bits of RN into remainder and put the
+ // bottom 16 of RN in top 16 of quotient
+ if (gpu_div_control & 0x01)
+ q <<= 16, r = RN >> 16;
+
+ for(int i=0; i<32; i++)
+ {
+// uint32_t sign = (r >> 31) & 0x01;
+ 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;
+#endif
#ifdef GPU_DIS_DIV
if (doGPUDis)
#endif
}
+
static void gpu_opcode_imultn(void)
{
uint32_t res = (int32_t)((int16_t)RN * (int16_t)RM);
SET_FLAG_N(res);
}
+
static void gpu_opcode_neg(void)
{
#ifdef GPU_DIS_NEG
#endif
}
+
static void gpu_opcode_shlq(void)
{
#ifdef GPU_DIS_SHLQ
#endif
}
+
static void gpu_opcode_shrq(void)
{
#ifdef GPU_DIS_SHRQ
#endif
}
+
static void gpu_opcode_ror(void)
{
#ifdef GPU_DIS_ROR
#endif
}
+
static void gpu_opcode_rorq(void)
{
#ifdef GPU_DIS_RORQ
#endif
}
+
static void gpu_opcode_sha(void)
{
/* int dreg = jaguar.op & 31;
SET_FLAG_N(_RN);*/
}
+
static void gpu_opcode_sharq(void)
{
#ifdef GPU_DIS_SHARQ
#endif
}
+
static void gpu_opcode_sh(void)
{
#ifdef GPU_DIS_SH
#endif
}
+
//Temporary: Testing only!
//#include "gpu2.cpp"
//#include "gpu3.cpp"
#else
+
// New thread-safe GPU core
int GPUCore(void * data)
}
#endif
+