#include "gpu.h"
+#include <string.h> // For memset
+#include <stdlib.h>
+#include "log.h"
+#include "jaguar.h"
+#include "m68k.h"
+#include "tom.h"
+#include "memory.h"
+#include "jagdasm.h"
+#include "dsp.h"
+
//#define GPU_DEBUG
// For GPU dissasembly...
//This is wrong, wrong, WRONG, but it seems to work for the time being...
//(That is, it fixes Flip Out which relies on GPU timing rather than semaphores. Bad developers! Bad!)
//What's needed here is a way to take pipeline effects into account (including pipeline stalls!)...
-uint8 gpu_opcode_cycles[64] =
+/*uint8 gpu_opcode_cycles[64] =
{
1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
2, 2, 2, 3, 3, 1, 1, 1,
1, 1, 1, 1, 1, 1, 4, 1,
1, 1, 3, 3, 1, 1, 1, 1
-};
+};//*/
+uint8 gpu_opcode_cycles[64] =
+{
+ 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1
+};//*/
void (*gpu_opcode[64])()=
{
gpu_opcode_store_r14_ri, gpu_opcode_store_r15_ri, gpu_opcode_sat24, gpu_opcode_pack,
};
-static uint8 * gpu_ram_8;
+static uint8 gpu_ram_8[0x1000];
uint32 gpu_pc;
static uint32 gpu_acc;
static uint32 gpu_remain;
// a bit before writing a result. I.e., if the result of an operation leaves a zero in
// the carry flag, you don't have to zero gpu_flag_c before you can write that zero!
static uint8 gpu_flag_z, gpu_flag_n, gpu_flag_c;
-static uint32 * gpu_reg_bank_0;
-static uint32 * gpu_reg_bank_1;
+static uint32 gpu_reg_bank_0[32];
+static uint32 gpu_reg_bank_1[32];
static uint32 * gpu_reg;
static uint32 * gpu_alternate_reg;
#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)(r) >> 31) & 0x01));
+#define SET_FLAG_N(r) (gpu_flag_n = (((uint32)(r) >> 31) & 0x01));
#define RESET_FLAG_Z() gpu_flag_z = 0;
#define RESET_FLAG_N() gpu_flag_n = 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)(r) >> 31) & 0x01))
-#define SET_C_ADD(a,b) (gpu_flag_c = ((UINT32)(b) > (UINT32)(~(a))))
-#define SET_C_SUB(a,b) (gpu_flag_c = ((UINT32)(b) > (UINT32)(a)))
+#define SET_N(r) (gpu_flag_n = (((uint32)(r) >> 31) & 0x01))
+#define SET_C_ADD(a,b) (gpu_flag_c = ((uint32)(b) > (uint32)(~(a))))
+#define SET_C_SUB(a,b) (gpu_flag_c = ((uint32)(b) > (uint32)(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 gpu_opcode_use[64];
-char * gpu_opcode_str[64]=
+const char * gpu_opcode_str[64]=
{
"add", "addc", "addq", "addqt",
"sub", "subc", "subq", "subqt",
}
#endif // GPU_DEBUG
-/* gpu_ram_8[offset & 0xFFF] = (data >> 24) & 0xFF,
- gpu_ram_8[(offset+1) & 0xFFF] = (data >> 16) & 0xFF,
- gpu_ram_8[(offset+2) & 0xFFF] = (data >> 8) & 0xFF,
- gpu_ram_8[(offset+3) & 0xFFF] = data & 0xFF;//*/
offset &= 0xFFF;
- SET32(gpu_ram_8, offset, data);//*/
+ SET32(gpu_ram_8, offset, data);
return;
}
// else if ((offset >= GPU_CONTROL_RAM_BASE) && (offset < GPU_CONTROL_RAM_BASE+0x20))
// JaguarWriteWord(offset, (data >> 16) & 0xFFFF, who);
// JaguarWriteWord(offset+2, data & 0xFFFF, who);
+// We're a 32-bit processor, we can do a long write...!
JaguarWriteLong(offset, data, who);
}
void gpu_init(void)
{
- memory_malloc_secure((void **)&gpu_ram_8, 0x1000, "GPU work RAM");
-// memory_malloc_secure((void **)&gpu_reg, 32*sizeof(int32), "GPU bank 0 regs");
-// memory_malloc_secure((void **)&gpu_alternate_reg, 32*sizeof(int32), "GPU bank 1 regs");
- memory_malloc_secure((void **)&gpu_reg_bank_0, 32 * sizeof(int32), "GPU bank 0 regs");
- memory_malloc_secure((void **)&gpu_reg_bank_1, 32 * sizeof(int32), "GPU bank 1 regs");
+// memory_malloc_secure((void **)&gpu_ram_8, 0x1000, "GPU work RAM");
+// memory_malloc_secure((void **)&gpu_reg_bank_0, 32 * sizeof(int32), "GPU bank 0 regs");
+// memory_malloc_secure((void **)&gpu_reg_bank_1, 32 * sizeof(int32), "GPU bank 1 regs");
build_branch_condition_table();
}
WriteLog("\n");
- memory_free(gpu_ram_8);
+// memory_free(gpu_ram_8);
+// memory_free(gpu_reg_bank_0);
+// memory_free(gpu_reg_bank_1);
}
//
while (cycles > 0 && GPU_RUNNING)
{
+if (gpu_ram_8[0x054] == 0x98 && gpu_ram_8[0x055] == 0x0A && gpu_ram_8[0x056] == 0x03
+ && gpu_ram_8[0x057] == 0x00 && gpu_ram_8[0x058] == 0x00 && gpu_ram_8[0x059] == 0x00)
+{
+ if (gpu_pc == 0xF03000)
+ {
+ extern uint32 starCount;
+ starCount = 0;
+/* WriteLog("GPU: Starting starfield generator... Dump of [R03=%08X]:\n", gpu_reg_bank_0[03]);
+ uint32 base = gpu_reg_bank_0[3];
+ for(uint32 i=0; i<0x100; i+=16)
+ {
+ WriteLog("%02X: ", i);
+ for(uint32 j=0; j<16; j++)
+ {
+ WriteLog("%02X ", JaguarReadByte(base + i + j));
+ }
+ WriteLog("\n");
+ }*/
+ }
+// if (gpu_pc == 0xF03)
+ {
+ }
+}//*/
+/*if (gpu_pc == 0xF03B9E && gpu_reg_bank_0[01] == 0)
+{
+ GPUDumpRegisters();
+ WriteLog("GPU: Starting disassembly log...\n");
+ doGPUDis = true;
+}//*/
/*if (gpu_pc == 0xF0359A)
{
doGPUDis = true;
static void gpu_opcode_jump(void)
{
#ifdef GPU_DIS_JUMP
-char * condition[32] =
+const char * condition[32] =
{ "T", "nz", "z", "???", "nc", "nc nz", "nc z", "???", "c", "c nz",
"c z", "???", "???", "???", "???", "???", "???", "???", "???",
"???", "nn", "nn nz", "nn z", "???", "n", "n nz", "n z", "???",
static void gpu_opcode_jr(void)
{
#ifdef GPU_DIS_JR
-char * condition[32] =
+const char * condition[32] =
{ "T", "nz", "z", "???", "nc", "nc nz", "nc z", "???", "c", "c nz",
"c z", "???", "???", "???", "???", "???", "???", "???", "???",
"???", "nn", "nn nz", "nn z", "???", "n", "n nz", "n z", "???",
#endif
/* if (CONDITION(jaguar.op & 31))
{
- INT32 r1 = (INT8)((jaguar.op >> 2) & 0xF8) >> 2;
- UINT32 newpc = jaguar.PC + r1;
+ int32 r1 = (INT8)((jaguar.op >> 2) & 0xF8) >> 2;
+ uint32 newpc = jaguar.PC + r1;
CALL_MAME_DEBUG;
jaguar.op = ROPCODE(jaguar.PC);
jaguar.PC = newpc;
if (doGPUDis)
WriteLog("%06X: ADD 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 res = RN + RM;
+ uint32 res = RN + RM;
CLR_ZNC; SET_ZNC_ADD(RN, RM, res);
RN = res;
#ifdef GPU_DIS_ADD
WriteLog("%06X: ADDC 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
/* int dreg = jaguar.op & 31;
- UINT32 r1 = jaguar.r[(jaguar.op >> 5) & 31];
- UINT32 r2 = jaguar.r[dreg];
- UINT32 res = r2 + r1 + ((jaguar.FLAGS >> 1) & 1);
+ uint32 r1 = jaguar.r[(jaguar.op >> 5) & 31];
+ uint32 r2 = jaguar.r[dreg];
+ uint32 res = r2 + r1 + ((jaguar.FLAGS >> 1) & 1);
jaguar.r[dreg] = res;
CLR_ZNC; SET_ZNC_ADD(r2,r1,res);*/
- UINT32 res = RN + RM + gpu_flag_c;
- UINT32 carry = gpu_flag_c;
+ uint32 res = RN + RM + gpu_flag_c;
+ uint32 carry = gpu_flag_c;
// SET_ZNC_ADD(RN, RM, res); //???BUG??? Yes!
SET_ZNC_ADD(RN + carry, RM, res);
// SET_ZNC_ADD(RN, RM + carry, res);
if (doGPUDis)
WriteLog("%06X: ADDQ #%u, R%02u [NCZ:%u%u%u, R%02u=%08X] -> ", gpu_pc-2, gpu_convert_zero[IMM_1], IMM_2, gpu_flag_n, gpu_flag_c, gpu_flag_z, IMM_2, RN);
#endif
- UINT32 r1 = gpu_convert_zero[IMM_1];
- UINT32 res = RN + r1;
+ uint32 r1 = gpu_convert_zero[IMM_1];
+ uint32 res = RN + r1;
CLR_ZNC; SET_ZNC_ADD(RN, r1, res);
RN = res;
#ifdef GPU_DIS_ADDQ
if (doGPUDis)
WriteLog("%06X: SUB 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 res = RN - RM;
+ uint32 res = RN - RM;
SET_ZNC_SUB(RN, RM, res);
RN = res;
#ifdef GPU_DIS_SUB
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 res = RN - RM - gpu_flag_c;
- UINT32 borrow = gpu_flag_c;
+ uint32 res = RN - RM - gpu_flag_c;
+ uint32 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 !!!
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)(b) > (UINT32)(a)))
+#define SET_C_SUB(a,b) (gpu_flag_c = ((uint32)(b) > (uint32)(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)
if (doGPUDis)
WriteLog("%06X: SUBQ #%u, R%02u [NCZ:%u%u%u, R%02u=%08X] -> ", gpu_pc-2, gpu_convert_zero[IMM_1], IMM_2, gpu_flag_n, gpu_flag_c, gpu_flag_z, IMM_2, RN);
#endif
- UINT32 r1 = gpu_convert_zero[IMM_1];
- UINT32 res = RN - r1;
+ uint32 r1 = gpu_convert_zero[IMM_1];
+ uint32 res = RN - r1;
SET_ZNC_SUB(RN, r1, res);
RN = res;
#ifdef GPU_DIS_SUBQ
if (doGPUDis)
WriteLog("%06X: CMP 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 res = RN - RM;
+ uint32 res = RN - RM;
SET_ZNC_SUB(RN, RM, res);
#ifdef GPU_DIS_CMP
if (doGPUDis)
if (doGPUDis)
WriteLog("%06X: CMPQ #%d, R%02u [NCZ:%u%u%u, R%02u=%08X] -> ", gpu_pc-2, sqtable[IMM_1], IMM_2, gpu_flag_n, gpu_flag_c, gpu_flag_z, IMM_2, RN);
#endif
- UINT32 r1 = sqtable[IMM_1 & 0x1F]; // I like this better -> (INT8)(jaguar.op >> 2) >> 3;
- UINT32 res = RN - r1;
+ uint32 r1 = sqtable[IMM_1 & 0x1F]; // I like this better -> (INT8)(jaguar.op >> 2) >> 3;
+ uint32 res = RN - r1;
SET_ZNC_SUB(RN, r1, res);
#ifdef GPU_DIS_CMPQ
if (doGPUDis)
if (doGPUDis)
WriteLog("%06X: BCLR #%u, R%02u [NCZ:%u%u%u, R%02u=%08X] -> ", gpu_pc-2, IMM_1, IMM_2, gpu_flag_n, gpu_flag_c, gpu_flag_z, IMM_2, RN);
#endif
- UINT32 res = RN & ~(1 << IMM_1);
+ uint32 res = RN & ~(1 << IMM_1);
RN = res;
SET_ZN(res);
#ifdef GPU_DIS_BCLR
if (doGPUDis)
WriteLog("%06X: BSET #%u, R%02u [NCZ:%u%u%u, R%02u=%08X] -> ", gpu_pc-2, IMM_1, IMM_2, gpu_flag_n, gpu_flag_c, gpu_flag_z, IMM_2, RN);
#endif
- UINT32 res = RN | (1 << IMM_1);
+ uint32 res = RN | (1 << IMM_1);
RN = res;
SET_ZN(res);
#ifdef GPU_DIS_BSET
static void gpu_opcode_mtoi(void)
{
uint32 _RM = RM;
- uint32 res = RN = (((INT32)_RM >> 8) & 0xFF800000) | (_RM & 0x007FFFFF);
+ uint32 res = RN = (((int32)_RM >> 8) & 0xFF800000) | (_RM & 0x007FFFFF);
SET_ZN(res);
}
{
if (gpu_div_control & 0x01) // 16.16 division
{
- RN = ((UINT64)RN << 16) / RM;
- gpu_remain = ((UINT64)RN << 16) % RM;
+ RN = ((uint64)RN << 16) / RM;
+ gpu_remain = ((uint64)RN << 16) % RM;
}
else
{
if (doGPUDis)
WriteLog("%06X: NEG R%02u [NCZ:%u%u%u, R%02u=%08X] -> ", gpu_pc-2, IMM_2, gpu_flag_n, gpu_flag_c, gpu_flag_z, IMM_2, RN);
#endif
- UINT32 res = -RN;
+ uint32 res = -RN;
SET_ZNC_SUB(0, RN, res);
RN = res;
#ifdef GPU_DIS_NEG
#endif
// Was a bug here...
// (Look at Aaron's code: If r1 = 32, then 32 - 32 = 0 which is wrong!)
- INT32 r1 = 32 - IMM_1;
- UINT32 res = RN << r1;
+ int32 r1 = 32 - IMM_1;
+ uint32 res = RN << r1;
SET_ZN(res); gpu_flag_c = (RN >> 31) & 1;
RN = res;
#ifdef GPU_DIS_SHLQ
if (doGPUDis)
WriteLog("%06X: SHRQ #%u, R%02u [NCZ:%u%u%u, R%02u=%08X] -> ", gpu_pc-2, gpu_convert_zero[IMM_1], IMM_2, gpu_flag_n, gpu_flag_c, gpu_flag_z, IMM_2, RN);
#endif
- INT32 r1 = gpu_convert_zero[IMM_1];
- UINT32 res = RN >> r1;
+ int32 r1 = gpu_convert_zero[IMM_1];
+ uint32 res = RN >> r1;
SET_ZN(res); gpu_flag_c = RN & 1;
RN = res;
#ifdef GPU_DIS_SHRQ
if (doGPUDis)
WriteLog("%06X: ROR 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 r1 = RM & 0x1F;
- UINT32 res = (RN >> r1) | (RN << (32 - r1));
+ uint32 r1 = RM & 0x1F;
+ uint32 res = (RN >> r1) | (RN << (32 - r1));
SET_ZN(res); gpu_flag_c = (RN >> 31) & 1;
RN = res;
#ifdef GPU_DIS_ROR
if (doGPUDis)
WriteLog("%06X: RORQ #%u, R%02u [NCZ:%u%u%u, R%02u=%08X] -> ", gpu_pc-2, gpu_convert_zero[IMM_1], IMM_2, gpu_flag_n, gpu_flag_c, gpu_flag_z, IMM_2, RN);
#endif
- UINT32 r1 = gpu_convert_zero[IMM_1 & 0x1F];
- UINT32 r2 = RN;
- UINT32 res = (r2 >> r1) | (r2 << (32 - r1));
+ uint32 r1 = gpu_convert_zero[IMM_1 & 0x1F];
+ uint32 r2 = RN;
+ uint32 res = (r2 >> r1) | (r2 << (32 - r1));
RN = res;
SET_ZN(res); gpu_flag_c = (r2 >> 31) & 0x01;
#ifdef GPU_DIS_RORQ
static void gpu_opcode_sha(void)
{
/* int dreg = jaguar.op & 31;
- INT32 r1 = (INT32)jaguar.r[(jaguar.op >> 5) & 31];
- UINT32 r2 = jaguar.r[dreg];
- UINT32 res;
+ int32 r1 = (int32)jaguar.r[(jaguar.op >> 5) & 31];
+ uint32 r2 = jaguar.r[dreg];
+ uint32 res;
CLR_ZNC;
if (r1 < 0)
}
else
{
- res = (r1 >= 32) ? ((INT32)r2 >> 31) : ((INT32)r2 >> r1);
+ res = (r1 >= 32) ? ((int32)r2 >> 31) : ((int32)r2 >> r1);
jaguar.FLAGS |= (r2 << 1) & 2;
}
jaguar.r[dreg] = res;
if (doGPUDis)
WriteLog("%06X: SHA 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 res;
+ uint32 res;
- if ((INT32)RM < 0)
+ if ((int32)RM < 0)
{
- res = ((INT32)RM <= -32) ? 0 : (RN << -(INT32)RM);
+ res = ((int32)RM <= -32) ? 0 : (RN << -(int32)RM);
gpu_flag_c = RN >> 31;
}
else
{
- res = ((INT32)RM >= 32) ? ((INT32)RN >> 31) : ((INT32)RN >> (INT32)RM);
+ res = ((int32)RM >= 32) ? ((int32)RN >> 31) : ((int32)RN >> (int32)RM);
gpu_flag_c = RN & 0x01;
}
RN = res;
if (doGPUDis)
WriteLog("%06X: SHARQ #%u, R%02u [NCZ:%u%u%u, R%02u=%08X] -> ", gpu_pc-2, gpu_convert_zero[IMM_1], IMM_2, gpu_flag_n, gpu_flag_c, gpu_flag_z, IMM_2, RN);
#endif
- UINT32 res = (INT32)RN >> gpu_convert_zero[IMM_1];
+ uint32 res = (int32)RN >> gpu_convert_zero[IMM_1];
SET_ZN(res); gpu_flag_c = RN & 0x01;
RN = res;
#ifdef GPU_DIS_SHARQ