Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Structs - gpu #69

Closed
wants to merge 7 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
116 changes: 61 additions & 55 deletions src/gpu.c
Original file line number Diff line number Diff line change
Expand Up @@ -177,7 +177,8 @@ static uint32_t gpu_flags;
static uint32_t gpu_matrix_control;
static uint32_t gpu_pointer_to_matrix;
static uint32_t gpu_data_organization;
static uint32_t gpu_control;
static GPUControl gpu_control;

static uint32_t gpu_div_control;
// There is a distinct advantage to having these separated out--there's no need to clear
// a bit before writing a result. I.e., if the result of an operation leaves a zero in
Expand All @@ -192,7 +193,7 @@ static uint32_t gpu_instruction;
static uint32_t gpu_opcode_first_parameter;
static uint32_t gpu_opcode_second_parameter;

#define GPU_RUNNING (gpu_control & 0x01)
#define GPU_RUNNING (gpu_control.bits.b0)

#define RM gpu_reg[gpu_opcode_first_parameter]
#define RN gpu_reg[gpu_opcode_second_parameter]
Expand Down Expand Up @@ -295,14 +296,15 @@ uint8_t GPUReadByte(uint32_t offset, uint32_t who/*=UNKNOWN*/)
}

// GPU word access (read)
uint16_t GPUReadWord(uint32_t offset, uint32_t who/*=UNKNOWN*/)
INLINE uint16_t GPUReadWord(uint32_t offset, uint32_t who/*=UNKNOWN*/)
{
if ((offset >= GPU_WORK_RAM_BASE) && (offset < GPU_WORK_RAM_BASE+0x1000))
{
uint16_t data;
offset &= 0xFFF;
data = ((uint16_t)gpu_ram_8[offset] << 8) | (uint16_t)gpu_ram_8[offset+1];
return data;
offset &= 0xFFF;
OpCode data;
data.Bytes.UBYTE = (uint16_t)gpu_ram_8[offset];
data.Bytes.LBYTE = (uint16_t)gpu_ram_8[offset+1];
return data.WORD;
}
else if ((offset >= GPU_CONTROL_RAM_BASE) && (offset < GPU_CONTROL_RAM_BASE+0x20))
{
Expand All @@ -324,7 +326,7 @@ uint16_t GPUReadWord(uint32_t offset, uint32_t who/*=UNKNOWN*/)
}

// GPU dword access (read)
uint32_t GPUReadLong(uint32_t offset, uint32_t who/*=UNKNOWN*/)
INLINE uint32_t GPUReadLong(uint32_t offset, uint32_t who/*=UNKNOWN*/)
{
if (offset >= 0xF02000 && offset <= 0xF020FF)
{
Expand All @@ -342,34 +344,33 @@ uint32_t GPUReadLong(uint32_t offset, uint32_t who/*=UNKNOWN*/)
{
offset &= 0x1F;
switch (offset)
{
case 0x00:
gpu_flag_c = (gpu_flag_c ? 1 : 0);
gpu_flag_z = (gpu_flag_z ? 1 : 0);
gpu_flag_n = (gpu_flag_n ? 1 : 0);

gpu_flags = (gpu_flags & 0xFFFFFFF8) | (gpu_flag_n << 2) | (gpu_flag_c << 1) | gpu_flag_z;

return gpu_flags & 0xFFFFC1FF;
case 0x04:
return gpu_matrix_control;
case 0x08:
return gpu_pointer_to_matrix;
case 0x0C:
return gpu_data_organization;
case 0x10:
return gpu_pc;
case 0x14:
return gpu_control;
case 0x18:
return gpu_hidata;
case 0x1C:
return gpu_remain;
default: // unaligned long read
break;
}

return 0;
{
case 0x00:
gpu_flag_c = (gpu_flag_c ? 1 : 0);
gpu_flag_z = (gpu_flag_z ? 1 : 0);
gpu_flag_n = (gpu_flag_n ? 1 : 0);

gpu_flags = (gpu_flags & 0xFFFFFFF8) | (gpu_flag_n << 2) | (gpu_flag_c << 1) | gpu_flag_z;

return gpu_flags & 0xFFFFC1FF;
case 0x04:
return gpu_matrix_control;
case 0x08:
return gpu_pointer_to_matrix;
case 0x0C:
return gpu_data_organization;
case 0x10:
return gpu_pc;
case 0x14:
return gpu_control.WORD;
case 0x18:
return gpu_hidata;
case 0x1C:
return gpu_remain;
default: // unaligned long read
break;
}
return 0;
}

return (JaguarReadWord(offset, who) << 16) | JaguarReadWord(offset + 2, who);
Expand Down Expand Up @@ -442,7 +443,7 @@ void GPUWriteWord(uint32_t offset, uint16_t data, uint32_t who/*=UNKNOWN*/)

return;
}
else if ((offset == GPU_WORK_RAM_BASE + 0x0FFF) || (GPU_CONTROL_RAM_BASE + 0x1F))
else if ((offset == GPU_WORK_RAM_BASE + 0x0FFF) || (offset == GPU_CONTROL_RAM_BASE + 0x1F))
return;

// Have to be careful here--this can cause an infinite loop!
Expand Down Expand Up @@ -473,7 +474,7 @@ void GPUWriteLong(uint32_t offset, uint32_t data, uint32_t who/*=UNKNOWN*/)
gpu_flag_c = (gpu_flags & CARRY_FLAG) >> 1;
gpu_flag_n = (gpu_flags & NEGA_FLAG) >> 2;
GPUUpdateRegisterBanks();
gpu_control &= ~((gpu_flags & CINT04FLAGS) >> 3); // Interrupt latch clear bits
gpu_control.WORD &= ~((gpu_flags & CINT04FLAGS) >> 3); // Interrupt latch clear bits
//Writing here is only an interrupt enable--this approach is just plain wrong!
// GPUHandleIRQs();
//This, however, is A-OK! ;-)
Expand Down Expand Up @@ -523,7 +524,7 @@ void GPUWriteLong(uint32_t offset, uint32_t data, uint32_t who/*=UNKNOWN*/)
data &= ~0x04;
}

gpu_control = (gpu_control & 0xF7C0) | (data & (~0xF7C0));
gpu_control.WORD = (gpu_control.WORD & 0xF7C0) | (data & (~0xF7C0));

// if gpu wasn't running but is now running, execute a few cycles
#ifdef GPU_SINGLE_STEPPING
Expand Down Expand Up @@ -579,7 +580,7 @@ void GPUHandleIRQs(void)
return;

// Get the interrupt latch & enable bits
bits = (gpu_control >> 6) & 0x1F;
bits = gpu_control.gpuIRQ.irqMask; //(gpu_control >> 6) & 0x1F;
mask = (gpu_flags >> 4) & 0x1F;

// Bail out if latched interrupts aren't enabled
Expand Down Expand Up @@ -618,11 +619,11 @@ void GPUHandleIRQs(void)
void GPUSetIRQLine(int irqline, int state)
{
uint32_t mask = 0x0040 << irqline;
gpu_control &= ~mask; // Clear the interrupt latch
gpu_control.WORD &= ~mask; // Clear the interrupt latch

if (state)
{
gpu_control |= mask; // Assert the interrupt latch
gpu_control.WORD |= mask; // Assert the interrupt latch
GPUHandleIRQs(); // And handle the interrupt...
}
}
Expand All @@ -644,7 +645,7 @@ void GPUReset(void)
gpu_pointer_to_matrix = 0x00000000;
gpu_data_organization = 0xFFFFFFFF;
gpu_pc = 0x00F03000;
gpu_control = 0x00002800; // Correctly sets this as TOM Rev. 2
gpu_control.WORD = 0x00002800; // Correctly sets this as TOM Rev. 2
gpu_hidata = 0x00000000;
gpu_remain = 0x00000000; // These two registers are RO/WO
gpu_div_control = 0x00000000;
Expand Down Expand Up @@ -1572,30 +1573,35 @@ INLINE static void gpu_opcode_abs(void)

INLINE static void gpu_opcode_div(void) // RN / RM
{

unsigned i;
// Real algorithm, courtesy of SCPCD: NYAN!
uint32_t q = RN;
uint32_t r = 0;
Bits32 q;
q.WORD = RN;

Bits32 r;
r.WORD = 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;
if (gpu_div_control & 0x01) {
r.WORD = q.words.UWORD;
q.words.UWORD = q.words.LWORD;
q.words.LWORD = 0;
}

for(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);
uint32_t sign = r.bits.b31;
r.WORD = (r.WORD << 1) | q.bits.b31;
r.WORD += (sign ? RM : -RM);
q.WORD = (q.WORD << 1) | !r.bits.b31; // (((~r) >> 31) & 0x01);
}

RN = q;
gpu_remain = r;

RN = q.WORD;
gpu_remain = r.WORD;
}


INLINE static void gpu_opcode_imultn(void)
{
uint32_t res = (int32_t)((int16_t)RN * (int16_t)RM);
Expand Down
Loading