5 // GCC/SDL port by Niels Wagenaar (Linux/WIN32) and Caz (BeOS)
6 // Cleanups, endian wrongness, and bad ASM amelioration by James L. Hammons
7 // Note: Endian wrongness probably stems from the MAME origins of this emu and
8 // the braindead way in which MAME handles memory. :-)
10 // Problem with not booting the BIOS was the incorrect way that the
11 // SUBC instruction set the carry when the carry was set going in...
12 // Same problem with ADDC...
19 // For GPU dissasembly...
39 #define GPU_DIS_LOAD14I
40 #define GPU_DIS_LOAD14R
41 #define GPU_DIS_LOAD15I
42 #define GPU_DIS_LOAD15R
44 #define GPU_DIS_MOVEFA
46 #define GPU_DIS_MOVEPC
47 #define GPU_DIS_MOVETA
64 #define GPU_DIS_STOREB
65 #define GPU_DIS_STOREW
66 #define GPU_DIS_STORE14I
67 #define GPU_DIS_STORE14R
68 #define GPU_DIS_STORE15I
69 #define GPU_DIS_STORE15R
76 bool doGPUDis = false;
77 //bool doGPUDis = true;
80 GPU opcodes use (BIOS flying ATARI logo):
122 #define CINT0FLAG 0x0200
123 #define CINT1FLAG 0x0400
124 #define CINT2FLAG 0x0800
125 #define CINT3FLAG 0x1000
126 #define CINT4FLAG 0x2000
127 #define CINT04FLAGS (CINT0FLAG | CINT1FLAG | CINT2FLAG | CINT3FLAG | CINT4FLAG)
131 #define ZERO_FLAG 0x0001
132 #define CARRY_FLAG 0x0002
133 #define NEGA_FLAG 0x0004
135 #define INT_ENA0 0x0010
136 #define INT_ENA1 0x0020
137 #define INT_ENA2 0x0040
138 #define INT_ENA3 0x0080
139 #define INT_ENA4 0x0100
140 #define INT_CLR0 0x0200
141 #define INT_CLR1 0x0400
142 #define INT_CLR2 0x0800
143 #define INT_CLR3 0x1000
144 #define INT_CLR4 0x2000
145 #define REGPAGE 0x4000
148 // External global variables
150 extern int start_logging;
151 extern int gpu_start_log;
153 // Private function prototypes
155 void GPUUpdateRegisterBanks(void);
157 void GPUDumpDisassembly(void);
158 void GPUDumpRegisters(void);
159 void GPUDumpMemory(void);
161 static void gpu_opcode_add(void);
162 static void gpu_opcode_addc(void);
163 static void gpu_opcode_addq(void);
164 static void gpu_opcode_addqt(void);
165 static void gpu_opcode_sub(void);
166 static void gpu_opcode_subc(void);
167 static void gpu_opcode_subq(void);
168 static void gpu_opcode_subqt(void);
169 static void gpu_opcode_neg(void);
170 static void gpu_opcode_and(void);
171 static void gpu_opcode_or(void);
172 static void gpu_opcode_xor(void);
173 static void gpu_opcode_not(void);
174 static void gpu_opcode_btst(void);
175 static void gpu_opcode_bset(void);
176 static void gpu_opcode_bclr(void);
177 static void gpu_opcode_mult(void);
178 static void gpu_opcode_imult(void);
179 static void gpu_opcode_imultn(void);
180 static void gpu_opcode_resmac(void);
181 static void gpu_opcode_imacn(void);
182 static void gpu_opcode_div(void);
183 static void gpu_opcode_abs(void);
184 static void gpu_opcode_sh(void);
185 static void gpu_opcode_shlq(void);
186 static void gpu_opcode_shrq(void);
187 static void gpu_opcode_sha(void);
188 static void gpu_opcode_sharq(void);
189 static void gpu_opcode_ror(void);
190 static void gpu_opcode_rorq(void);
191 static void gpu_opcode_cmp(void);
192 static void gpu_opcode_cmpq(void);
193 static void gpu_opcode_sat8(void);
194 static void gpu_opcode_sat16(void);
195 static void gpu_opcode_move(void);
196 static void gpu_opcode_moveq(void);
197 static void gpu_opcode_moveta(void);
198 static void gpu_opcode_movefa(void);
199 static void gpu_opcode_movei(void);
200 static void gpu_opcode_loadb(void);
201 static void gpu_opcode_loadw(void);
202 static void gpu_opcode_load(void);
203 static void gpu_opcode_loadp(void);
204 static void gpu_opcode_load_r14_indexed(void);
205 static void gpu_opcode_load_r15_indexed(void);
206 static void gpu_opcode_storeb(void);
207 static void gpu_opcode_storew(void);
208 static void gpu_opcode_store(void);
209 static void gpu_opcode_storep(void);
210 static void gpu_opcode_store_r14_indexed(void);
211 static void gpu_opcode_store_r15_indexed(void);
212 static void gpu_opcode_move_pc(void);
213 static void gpu_opcode_jump(void);
214 static void gpu_opcode_jr(void);
215 static void gpu_opcode_mmult(void);
216 static void gpu_opcode_mtoi(void);
217 static void gpu_opcode_normi(void);
218 static void gpu_opcode_nop(void);
219 static void gpu_opcode_load_r14_ri(void);
220 static void gpu_opcode_load_r15_ri(void);
221 static void gpu_opcode_store_r14_ri(void);
222 static void gpu_opcode_store_r15_ri(void);
223 static void gpu_opcode_sat24(void);
224 static void gpu_opcode_pack(void);
226 uint8 gpu_opcode_cycles[64] =
228 3, 3, 3, 3, 3, 3, 3, 3,
229 3, 3, 3, 3, 3, 3, 3, 3,
230 3, 3, 1, 3, 1, 18, 3, 3,
231 3, 3, 3, 3, 3, 3, 3, 3,
232 3, 3, 2, 2, 2, 2, 3, 4,
233 5, 4, 5, 6, 6, 1, 1, 1,
234 1, 2, 2, 2, 1, 1, 9, 3,
235 3, 1, 6, 6, 2, 2, 3, 3
238 void (*gpu_opcode[64])()=
240 gpu_opcode_add, gpu_opcode_addc, gpu_opcode_addq, gpu_opcode_addqt,
241 gpu_opcode_sub, gpu_opcode_subc, gpu_opcode_subq, gpu_opcode_subqt,
242 gpu_opcode_neg, gpu_opcode_and, gpu_opcode_or, gpu_opcode_xor,
243 gpu_opcode_not, gpu_opcode_btst, gpu_opcode_bset, gpu_opcode_bclr,
244 gpu_opcode_mult, gpu_opcode_imult, gpu_opcode_imultn, gpu_opcode_resmac,
245 gpu_opcode_imacn, gpu_opcode_div, gpu_opcode_abs, gpu_opcode_sh,
246 gpu_opcode_shlq, gpu_opcode_shrq, gpu_opcode_sha, gpu_opcode_sharq,
247 gpu_opcode_ror, gpu_opcode_rorq, gpu_opcode_cmp, gpu_opcode_cmpq,
248 gpu_opcode_sat8, gpu_opcode_sat16, gpu_opcode_move, gpu_opcode_moveq,
249 gpu_opcode_moveta, gpu_opcode_movefa, gpu_opcode_movei, gpu_opcode_loadb,
250 gpu_opcode_loadw, gpu_opcode_load, gpu_opcode_loadp, gpu_opcode_load_r14_indexed,
251 gpu_opcode_load_r15_indexed, gpu_opcode_storeb, gpu_opcode_storew, gpu_opcode_store,
252 gpu_opcode_storep, gpu_opcode_store_r14_indexed, gpu_opcode_store_r15_indexed, gpu_opcode_move_pc,
253 gpu_opcode_jump, gpu_opcode_jr, gpu_opcode_mmult, gpu_opcode_mtoi,
254 gpu_opcode_normi, gpu_opcode_nop, gpu_opcode_load_r14_ri, gpu_opcode_load_r15_ri,
255 gpu_opcode_store_r14_ri, gpu_opcode_store_r15_ri, gpu_opcode_sat24, gpu_opcode_pack,
258 static uint8 * gpu_ram_8;
260 static uint32 gpu_acc;
261 static uint32 gpu_remain;
262 static uint32 gpu_hidata;
263 static uint32 gpu_flags;
264 static uint32 gpu_matrix_control;
265 static uint32 gpu_pointer_to_matrix;
266 static uint32 gpu_data_organization;
267 static uint32 gpu_control;
268 static uint32 gpu_div_control;
269 // There is a distinct advantage to having these separated out--there's no need to clear
270 // a bit before writing a result. I.e., if the result of an operation leaves a zero in
271 // the carry flag, you don't have to zero gpu_flag_c before you can write that zero!
272 static uint8 gpu_flag_z, gpu_flag_n, gpu_flag_c;
273 static uint32 * gpu_reg_bank_0;
274 static uint32 * gpu_reg_bank_1;
275 static uint32 * gpu_reg;
276 static uint32 * gpu_alternate_reg;
278 static uint32 gpu_instruction;
279 static uint32 gpu_opcode_first_parameter;
280 static uint32 gpu_opcode_second_parameter;
282 #define GPU_RUNNING (gpu_control & 0x01)
284 #define RM gpu_reg[gpu_opcode_first_parameter]
285 #define RN gpu_reg[gpu_opcode_second_parameter]
286 #define ALTERNATE_RM gpu_alternate_reg[gpu_opcode_first_parameter]
287 #define ALTERNATE_RN gpu_alternate_reg[gpu_opcode_second_parameter]
288 #define IMM_1 gpu_opcode_first_parameter
289 #define IMM_2 gpu_opcode_second_parameter
291 #define SET_FLAG_Z(r) (gpu_flag_z = ((r) == 0));
292 #define SET_FLAG_N(r) (gpu_flag_n = (((UINT32)(r) >> 31) & 0x01));
294 #define RESET_FLAG_Z() gpu_flag_z = 0;
295 #define RESET_FLAG_N() gpu_flag_n = 0;
296 #define RESET_FLAG_C() gpu_flag_c = 0;
298 #define CLR_Z (gpu_flag_z = 0)
299 #define CLR_ZN (gpu_flag_z = gpu_flag_n = 0)
300 #define CLR_ZNC (gpu_flag_z = gpu_flag_n = gpu_flag_c = 0)
301 #define SET_Z(r) (gpu_flag_z = ((r) == 0))
302 #define SET_N(r) (gpu_flag_n = (((UINT32)(r) >> 31) & 0x01))
303 #define SET_C_ADD(a,b) (gpu_flag_c = ((UINT32)(b) > (UINT32)(~(a))))
304 #define SET_C_SUB(a,b) (gpu_flag_c = ((UINT32)(b) > (UINT32)(a)))
305 #define SET_ZN(r) SET_N(r); SET_Z(r)
306 #define SET_ZNC_ADD(a,b,r) SET_N(r); SET_Z(r); SET_C_ADD(a,b)
307 #define SET_ZNC_SUB(a,b,r) SET_N(r); SET_Z(r); SET_C_SUB(a,b)
309 uint32 gpu_convert_zero[32] =
310 { 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 };
312 uint8 * branch_condition_table = 0;
313 #define BRANCH_CONDITION(x) branch_condition_table[(x) + ((jaguar_flags & 7) << 5)]
315 uint32 gpu_opcode_use[64];
317 char * gpu_opcode_str[64]=
319 "add", "addc", "addq", "addqt",
320 "sub", "subc", "subq", "subqt",
321 "neg", "and", "or", "xor",
322 "not", "btst", "bset", "bclr",
323 "mult", "imult", "imultn", "resmac",
324 "imacn", "div", "abs", "sh",
325 "shlq", "shrq", "sha", "sharq",
326 "ror", "rorq", "cmp", "cmpq",
327 "sat8", "sat16", "move", "moveq",
328 "moveta", "movefa", "movei", "loadb",
329 "loadw", "load", "loadp", "load_r14_indexed",
330 "load_r15_indexed", "storeb", "storew", "store",
331 "storep", "store_r14_indexed","store_r15_indexed","move_pc",
332 "jump", "jr", "mmult", "mtoi",
333 "normi", "nop", "load_r14_ri", "load_r15_ri",
334 "store_r14_ri", "store_r15_ri", "sat24", "pack",
337 static uint32 gpu_in_exec = 0;
338 static uint32 gpu_releaseTimeSlice_flag = 0;
340 void gpu_releaseTimeslice(void)
342 gpu_releaseTimeSlice_flag = 1;
345 uint32 gpu_get_pc(void)
350 void build_branch_condition_table(void)
352 if (!branch_condition_table)
354 branch_condition_table = (uint8 *)malloc(32 * 8 * sizeof(branch_condition_table[0]));
356 if (branch_condition_table)
358 for(int i=0; i<8; i++)
360 for(int j=0; j<32; j++)
367 if (!(i & ZERO_FLAG))
370 if (i & (CARRY_FLAG << (j >> 4)))
373 if (!(i & (CARRY_FLAG << (j >> 4))))
375 branch_condition_table[i * 32 + j] = result;
383 // GPU byte access (read)
385 uint8 GPUReadByte(uint32 offset, uint32 who/*=UNKNOWN*/)
387 if (offset >= 0xF02000 && offset <= 0xF020FF)
388 WriteLog("GPU: ReadByte--Attempt to read from GPU register file by %s!\n", whoName[who]);
390 if ((offset >= GPU_WORK_RAM_BASE) && (offset < GPU_WORK_RAM_BASE+0x1000))
391 return gpu_ram_8[offset & 0xFFF];
392 else if ((offset >= GPU_CONTROL_RAM_BASE) && (offset < GPU_CONTROL_RAM_BASE+0x20))
394 uint32 data = GPUReadLong(offset & 0xFFFFFFFC, who);
396 if ((offset & 0x03) == 0)
398 else if ((offset & 0x03) == 1)
399 return (data >> 16) & 0xFF;
400 else if ((offset & 0x03) == 2)
401 return (data >> 8) & 0xFF;
402 else if ((offset & 0x03) == 3)
406 return JaguarReadByte(offset, who);
410 // GPU word access (read)
412 uint16 GPUReadWord(uint32 offset, uint32 who/*=UNKNOWN*/)
414 if (offset >= 0xF02000 && offset <= 0xF020FF)
415 WriteLog("GPU: ReadWord--Attempt to read from GPU register file by %s!\n", whoName[who]);
417 if ((offset >= GPU_WORK_RAM_BASE) && (offset < GPU_WORK_RAM_BASE+0x1000))
420 uint16 data = ((uint16)gpu_ram_8[offset] << 8) | (uint16)gpu_ram_8[offset+1];
423 else if ((offset >= GPU_CONTROL_RAM_BASE) && (offset < GPU_CONTROL_RAM_BASE+0x20))
425 // This looks and smells wrong...
426 // But it *might* be OK...
427 if (offset & 0x01) // Catch cases 1 & 3... (unaligned read)
428 return (GPUReadByte(offset, who) << 8) | GPUReadByte(offset+1, who);
430 uint32 data = GPUReadLong(offset & 0xFFFFFFFC, who);
432 if (offset & 0x02) // Cases 0 & 2...
433 return data & 0xFFFF;
438 //TEMP--Mirror of F03000? No. Writes only...
439 //if (offset >= 0xF0B000 && offset <= 0xF0BFFF)
440 //WriteLog("[GPUR16] --> Possible GPU RAM mirror access by %s!", whoName[who]);
442 return JaguarReadWord(offset, who);
446 // GPU dword access (read)
448 uint32 GPUReadLong(uint32 offset, uint32 who/*=UNKNOWN*/)
450 if (offset >= 0xF02000 && offset <= 0xF020FF)
451 WriteLog("GPU: ReadLong--Attempt to read from GPU register file by %s!\n", whoName[who]);
453 // if ((offset >= GPU_WORK_RAM_BASE) && (offset < GPU_WORK_RAM_BASE + 0x1000))
454 if ((offset >= GPU_WORK_RAM_BASE) && (offset <= GPU_WORK_RAM_BASE + 0x0FFC))
457 return ((uint32)gpu_ram_8[offset] << 24) | ((uint32)gpu_ram_8[offset+1] << 16)
458 | ((uint32)gpu_ram_8[offset+2] << 8) | (uint32)gpu_ram_8[offset+3];//*/
459 // return GET32(gpu_ram_8, offset);
461 // else if ((offset >= GPU_CONTROL_RAM_BASE) && (offset < GPU_CONTROL_RAM_BASE+0x20))
462 else if ((offset >= GPU_CONTROL_RAM_BASE) && (offset <= GPU_CONTROL_RAM_BASE + 0x1C))
468 gpu_flag_c = (gpu_flag_c ? 1 : 0);
469 gpu_flag_z = (gpu_flag_z ? 1 : 0);
470 gpu_flag_n = (gpu_flag_n ? 1 : 0);
472 gpu_flags = (gpu_flags & 0xFFFFFFF8) | (gpu_flag_n << 2) | (gpu_flag_c << 1) | gpu_flag_z;
474 return gpu_flags & 0xFFFFC1FF;
476 return gpu_matrix_control;
478 return gpu_pointer_to_matrix;
480 return gpu_data_organization;
489 default: // unaligned long read
491 WriteLog("GPU: Read32--unaligned 32 bit read at %08X by %s.\n", GPU_CONTROL_RAM_BASE + offset, whoName[who]);
496 //TEMP--Mirror of F03000? No. Writes only...
497 //if (offset >= 0xF0B000 && offset <= 0xF0BFFF)
498 // WriteLog("[GPUR32] --> Possible GPU RAM mirror access by %s!\n", whoName[who]);
499 /*if (offset >= 0xF1D000 && offset <= 0xF1DFFF)
500 WriteLog("[GPUR32] --> Reading from Wavetable ROM!\n");//*/
502 return (JaguarReadWord(offset, who) << 16) | JaguarReadWord(offset + 2, who);
506 // GPU byte access (write)
508 void GPUWriteByte(uint32 offset, uint8 data, uint32 who/*=UNKNOWN*/)
510 if (offset >= 0xF02000 && offset <= 0xF020FF)
511 WriteLog("GPU: WriteByte--Attempt to write to GPU register file by %s!\n", whoName[who]);
513 if ((offset >= GPU_WORK_RAM_BASE) && (offset <= GPU_WORK_RAM_BASE + 0x0FFF))
515 gpu_ram_8[offset & 0xFFF] = data;
517 //This is the same stupid worthless code that was in the DSP!!! AARRRGGGGHHHHH!!!!!!
520 m68k_end_timeslice();
521 dsp_releaseTimeslice();
525 else if ((offset >= GPU_CONTROL_RAM_BASE) && (offset <= GPU_CONTROL_RAM_BASE + 0x1F))
527 uint32 reg = offset & 0x1C;
528 int bytenum = offset & 0x03;
530 //This is definitely wrong!
531 if ((reg >= 0x1C) && (reg <= 0x1F))
532 gpu_div_control = (gpu_div_control & (~(0xFF << (bytenum << 3)))) | (data << (bytenum << 3));
535 uint32 old_data = GPUReadLong(offset & 0xFFFFFFC, who);
536 bytenum = 3 - bytenum; // convention motorola !!!
537 old_data = (old_data & (~(0xFF << (bytenum << 3)))) | (data << (bytenum << 3));
538 GPUWriteLong(offset & 0xFFFFFFC, old_data, who);
542 // WriteLog("gpu: writing %.2x at 0x%.8x\n",data,offset);
543 JaguarWriteByte(offset, data, who);
547 // GPU word access (write)
549 void GPUWriteWord(uint32 offset, uint16 data, uint32 who/*=UNKNOWN*/)
551 if (offset >= 0xF02000 && offset <= 0xF020FF)
552 WriteLog("GPU: WriteWord--Attempt to write to GPU register file by %s!\n", whoName[who]);
554 if ((offset >= GPU_WORK_RAM_BASE) && (offset <= GPU_WORK_RAM_BASE + 0x0FFE))
556 gpu_ram_8[offset & 0xFFF] = (data>>8) & 0xFF;
557 gpu_ram_8[(offset+1) & 0xFFF] = data & 0xFF;//*/
559 SET16(gpu_ram_8, offset, data);//*/
561 //This is the same stupid worthless code that was in the DSP!!! AARRRGGGGHHHHH!!!!!!
564 m68k_end_timeslice();
565 dsp_releaseTimeslice();
569 else if ((offset >= GPU_CONTROL_RAM_BASE) && (offset <= GPU_CONTROL_RAM_BASE + 0x1E))
571 if (offset & 0x01) // This is supposed to weed out unaligned writes, but does nothing...
574 WriteLog("GPU: Write16--unaligned write @ %08X [%04X]\n", offset, data);
579 //Dual locations in this range: $1C Divide unit remainder/Divide unit control (R/W)
580 //This just literally sucks.
581 if ((offset & 0x1C) == 0x1C)
583 //This doesn't look right either--handles cases 1, 2, & 3 all the same!
585 gpu_div_control = (gpu_div_control & 0xFFFF0000) | (data & 0xFFFF);
587 gpu_div_control = (gpu_div_control & 0x0000FFFF) | ((data & 0xFFFF) << 16);
591 //WriteLog("[GPU W16:%08X,%04X]", offset, data);
592 uint32 old_data = GPUReadLong(offset & 0xFFFFFFC, who);
594 old_data = (old_data & 0xFFFF0000) | (data & 0xFFFF);
596 old_data = (old_data & 0x0000FFFF) | ((data & 0xFFFF) << 16);
597 GPUWriteLong(offset & 0xFFFFFFC, old_data, who);
601 else if ((offset == GPU_WORK_RAM_BASE + 0x0FFF) || (GPU_CONTROL_RAM_BASE + 0x1F))
604 WriteLog("GPU: Write16--unaligned write @ %08X by %s [%04X]!\n", offset, whoName[who], data);
610 // Have to be careful here--this can cause an infinite loop!
611 JaguarWriteWord(offset, data, who);
615 // GPU dword access (write)
617 void GPUWriteLong(uint32 offset, uint32 data, uint32 who/*=UNKNOWN*/)
619 if (offset >= 0xF02000 && offset <= 0xF020FF)
620 WriteLog("GPU: WriteLong--Attempt to write to GPU register file by %s!\n", whoName[who]);
622 // if ((offset >= GPU_WORK_RAM_BASE) && (offset < GPU_WORK_RAM_BASE + 0x1000))
623 if ((offset >= GPU_WORK_RAM_BASE) && (offset <= GPU_WORK_RAM_BASE + 0x0FFC))
628 WriteLog("GPU: Write32--unaligned write @ %08X [%08X] by %s\n", offset, data, whoName[who]);
633 /* gpu_ram_8[offset & 0xFFF] = (data >> 24) & 0xFF,
634 gpu_ram_8[(offset+1) & 0xFFF] = (data >> 16) & 0xFF,
635 gpu_ram_8[(offset+2) & 0xFFF] = (data >> 8) & 0xFF,
636 gpu_ram_8[(offset+3) & 0xFFF] = data & 0xFF;//*/
638 SET32(gpu_ram_8, offset, data);//*/
641 // else if ((offset >= GPU_CONTROL_RAM_BASE) && (offset < GPU_CONTROL_RAM_BASE+0x20))
642 else if ((offset >= GPU_CONTROL_RAM_BASE) && (offset <= GPU_CONTROL_RAM_BASE + 0x1C))
649 bool IMASKCleared = (gpu_flags & IMASK) && !(data & IMASK);
651 gpu_flag_z = gpu_flags & ZERO_FLAG;
652 gpu_flag_c = (gpu_flags & CARRY_FLAG) >> 1;
653 gpu_flag_n = (gpu_flags & NEGA_FLAG) >> 2;
654 GPUUpdateRegisterBanks();
655 gpu_control &= ~((gpu_flags & CINT04FLAGS) >> 3); // Interrupt latch clear bits
656 //Writing here is only an interrupt enable--this approach is just plain wrong!
658 //This, however, is A-OK! ;-)
659 if (IMASKCleared) // If IMASK was cleared,
660 GPUHandleIRQs(); // see if any other interrupts need servicing!
662 if (gpu_flags & (INT_ENA0 | INT_ENA1 | INT_ENA2 | INT_ENA3 | INT_ENA4))
663 WriteLog("GPU: Interrupt enable set by %s! Bits: %02X\n", whoName[who], (gpu_flags >> 4) & 0x1F);
664 WriteLog("GPU: REGPAGE %s...\n", (gpu_flags & REGPAGE ? "set" : "cleared"));
669 gpu_matrix_control = data;
672 // This can only point to long aligned addresses
673 gpu_pointer_to_matrix = data & 0xFFFFFFFC;
676 gpu_data_organization = data;
681 WriteLog("GPU: %s setting GPU PC to %08X %s\n", whoName[who], gpu_pc, (GPU_RUNNING ? "(GPU is RUNNING!)" : ""));//*/
686 // uint32 gpu_was_running = GPU_RUNNING;
687 data &= ~0xF7C0; // Disable writes to INT_LAT0-4 & TOM version number
689 // check for GPU -> CPU interrupt
692 //WriteLog("GPU->CPU interrupt\n");
693 if (tom_irq_enabled(IRQ_GPU))
695 if ((tom_irq_enabled(IRQ_GPU)) && (jaguar_interrupt_handler_is_valid(64)))
697 tom_set_pending_gpu_int();
698 m68k_set_irq(7); // Set 68000 NMI
699 gpu_releaseTimeslice();
705 // check for CPU -> GPU interrupt #0
708 //WriteLog("CPU->GPU interrupt\n");
709 GPUSetIRQLine(0, ASSERT_LINE);
710 m68k_end_timeslice();
711 dsp_releaseTimeslice();
718 //WriteLog("asked to perform a single step (single step is %senabled)\n",(data&0x8)?"":"not ");
720 gpu_control = (gpu_control & 0xF7C0) | (data & (~0xF7C0));
722 // if gpu wasn't running but is now running, execute a few cycles
723 #ifndef GPU_SINGLE_STEPPING
724 /* if (!gpu_was_running && GPU_RUNNING)
727 WriteLog("GPU: Write32--About to do stupid braindead GPU execution for 200 cycles.\n");
732 #endif // GPU_DEBUG//*/
734 if (gpu_control & 0x18)
736 #endif // #ifndef GPU_SINGLE_STEPPING
738 WriteLog("Write to GPU CTRL by %s: %08X ", whoName[who], data);
740 WriteLog(" --> Starting to run at %08X by %s...", gpu_pc, whoName[who]);
742 WriteLog(" --> Stopped by %s! (GPU_PC: %08X)", whoName[who], gpu_pc);
746 // GPUDumpDisassembly();
749 if (gpu_pc == 0xF035D8)
751 // GPUDumpDisassembly();
754 gpu_control &= 0xFFFFFFFE; // Don't run it and let's see what happens!
755 //Hmm. Seems to lock up when going into the demo...
756 //Try to disable the collision altogether!
759 extern int effect_start5;
760 static bool finished = false;
761 //if (GPU_RUNNING && effect_start5 && !finished)
762 if (GPU_RUNNING && effect_start5 && gpu_pc == 0xF035D8)
764 // Let's do a dump of $6528!
765 /* uint32 numItems = JaguarReadWord(0x6BD6);
766 WriteLog("\nDump of $6528: %u items.\n\n", numItems);
767 for(int i=0; i<numItems*3*4; i+=3*4)
769 WriteLog("\t%04X: %08X %08X %08X -> ", 0x6528+i, JaguarReadLong(0x6528+i),
770 JaguarReadLong(0x6528+i+4), JaguarReadLong(0x6528+i+8));
771 uint16 link = JaguarReadWord(0x6528+i+8+2);
772 for(int j=0; j<40; j+=4)
773 WriteLog("%08X ", JaguarReadLong(link + j));
777 // Let's try a manual blit here...
778 //This isn't working the way it should! !!! FIX !!!
779 //Err, actually, it is.
780 // NOW, it works right! Problem solved!!! It's a blitter bug!
781 /* uint32 src = 0x4D54, dst = 0xF03000, width = 10 * 4;
782 for(int y=0; y<127; y++)
784 for(int x=0; x<2; x++)
786 JaguarWriteLong(dst, JaguarReadLong(src));
791 src += width - (2 * 4);
795 WriteLog("\nGPU: About to execute collision detection code.\n\n");//*/
797 /* WriteLog("\nGPU: About to execute collision detection code. Data @ 4D54:\n\n");
799 for(int i=0x004D54; i<0x004D54+2048; i++)
801 WriteLog("%02X ", JaguarReadByte(i));
809 WriteLog("\n\nData @ F03000:\n\n");
811 for(int i=0xF03000; i<0xF03200; i++)
813 WriteLog("%02X ", JaguarReadByte(i));
827 /*if (!GPU_RUNNING && finished)
829 WriteLog("\nGPU: Finished collision detection code. Exiting!\n\n");
834 // (?) If we're set running by the M68K (or DSP?) then end its timeslice to
835 // allow the GPU a chance to run...
836 // Yes! This partially fixed Trevor McFur...
838 m68k_end_timeslice();
845 gpu_div_control = data;
847 // default: // unaligned long write
854 // JaguarWriteWord(offset, (data >> 16) & 0xFFFF, who);
855 // JaguarWriteWord(offset+2, data & 0xFFFF, who);
856 JaguarWriteLong(offset, data, who);
860 // Change register banks if necessary
862 void GPUUpdateRegisterBanks(void)
864 int bank = (gpu_flags & REGPAGE); // REGPAGE bit
866 if (gpu_flags & IMASK) // IMASK bit
867 bank = 0; // IMASK forces main bank to be bank 0
870 gpu_reg = gpu_reg_bank_1, gpu_alternate_reg = gpu_reg_bank_0;
872 gpu_reg = gpu_reg_bank_0, gpu_alternate_reg = gpu_reg_bank_1;
875 void GPUHandleIRQs(void)
877 // Bail out if we're already in an interrupt!
878 if (gpu_flags & IMASK)
881 // Get the interrupt latch & enable bits
882 uint32 bits = (gpu_control >> 6) & 0x1F, mask = (gpu_flags >> 4) & 0x1F;
884 // Bail out if latched interrupts aren't enabled
889 // Determine which interrupt to service
890 uint32 which = 0; //Isn't there a #pragma to disable this warning???
903 WriteLog("GPU: Generating IRQ #%i\n", which);
905 // set the interrupt flag
907 GPUUpdateRegisterBanks();
909 // subqt #4,r31 ; pre-decrement stack pointer
910 // move pc,r30 ; address of interrupted code
911 // store r30,(r31) ; store return address
913 GPUWriteLong(gpu_reg[31], gpu_pc - 2, GPU);
915 // movei #service_address,r30 ; pointer to ISR entry
916 // jump (r30) ; jump to ISR
918 gpu_pc = gpu_reg[30] = GPU_WORK_RAM_BASE + (which * 0x10);
921 void GPUSetIRQLine(int irqline, int state)
924 WriteLog("GPU: Setting GPU IRQ line #%i\n", irqline);
926 uint32 mask = 0x0040 << irqline;
927 gpu_control &= ~mask; // Clear the interrupt latch
931 gpu_control |= mask; // Assert the interrupt latch
932 GPUHandleIRQs(); // And handle the interrupt...
936 //TEMPORARY: Testing only!
942 memory_malloc_secure((void **)&gpu_ram_8, 0x1000, "GPU work RAM");
943 // memory_malloc_secure((void **)&gpu_reg, 32*sizeof(int32), "GPU bank 0 regs");
944 // memory_malloc_secure((void **)&gpu_alternate_reg, 32*sizeof(int32), "GPU bank 1 regs");
945 memory_malloc_secure((void **)&gpu_reg_bank_0, 32 * sizeof(int32), "GPU bank 0 regs");
946 memory_malloc_secure((void **)&gpu_reg_bank_1, 32 * sizeof(int32), "GPU bank 1 regs");
948 build_branch_condition_table();
952 //TEMPORARY: Testing only!
959 // GPU registers (directly visible)
960 gpu_flags = 0x00000000;
961 gpu_matrix_control = 0x00000000;
962 gpu_pointer_to_matrix = 0x00000000;
963 gpu_data_organization = 0xFFFFFFFF;
965 gpu_control = 0x00002800; // Correctly sets this as TOM Rev. 2
966 gpu_hidata = 0x00000000;
967 gpu_remain = 0x00000000; // These two registers are RO/WO
968 gpu_div_control = 0x00000000;
970 // GPU internal register
971 gpu_acc = 0x00000000;
973 gpu_reg = gpu_reg_bank_0;
974 gpu_alternate_reg = gpu_reg_bank_1;
976 for(int i=0; i<32; i++)
977 gpu_reg[i] = gpu_alternate_reg[i] = 0x00000000;
980 memset(gpu_ram_8, 0xFF, 0x1000);
982 //not needed GPUInterruptPending = false;
986 uint32 gpu_read_pc(void)
991 void gpu_reset_stats(void)
993 for(uint32 i=0; i<64; i++)
994 gpu_opcode_use[i] = 0;
995 WriteLog("--> GPU stats were reset!\n");
998 void GPUDumpDisassembly(void)
1002 WriteLog("\n---[GPU code at 00F03000]---------------------------\n");
1003 uint32 j = 0xF03000;
1004 while (j <= 0xF03FFF)
1007 j += dasmjag(JAGUAR_GPU, buffer, j);
1008 WriteLog("\t%08X: %s\n", oldj, buffer);
1012 void GPUDumpRegisters(void)
1014 WriteLog("\n---[GPU flags: NCZ %d%d%d]-----------------------\n", gpu_flag_n, gpu_flag_c, gpu_flag_z);
1015 WriteLog("\nRegisters bank 0\n");
1016 for(int j=0; j<8; j++)
1018 WriteLog("\tR%02i = %08X R%02i = %08X R%02i = %08X R%02i = %08X\n",
1019 (j << 2) + 0, gpu_reg_bank_0[(j << 2) + 0],
1020 (j << 2) + 1, gpu_reg_bank_0[(j << 2) + 1],
1021 (j << 2) + 2, gpu_reg_bank_0[(j << 2) + 2],
1022 (j << 2) + 3, gpu_reg_bank_0[(j << 2) + 3]);
1024 WriteLog("Registers bank 1\n");
1025 for(int j=0; j<8; j++)
1027 WriteLog("\tR%02i = %08X R%02i = %08X R%02i = %08X R%02i = %08X\n",
1028 (j << 2) + 0, gpu_reg_bank_1[(j << 2) + 0],
1029 (j << 2) + 1, gpu_reg_bank_1[(j << 2) + 1],
1030 (j << 2) + 2, gpu_reg_bank_1[(j << 2) + 2],
1031 (j << 2) + 3, gpu_reg_bank_1[(j << 2) + 3]);
1035 void GPUDumpMemory(void)
1037 WriteLog("\n---[GPU data at 00F03000]---------------------------\n");
1038 for(int i=0; i<0xFFF; i+=4)
1039 WriteLog("\t%08X: %02X %02X %02X %02X\n", 0xF03000+i, gpu_ram_8[i],
1040 gpu_ram_8[i+1], gpu_ram_8[i+2], gpu_ram_8[i+3]);
1045 WriteLog("GPU: Stopped at PC=%08X (GPU %s running)\n", (unsigned int)gpu_pc, GPU_RUNNING ? "was" : "wasn't");
1047 // Get the interrupt latch & enable bits
1048 uint8 bits = (gpu_control >> 6) & 0x1F, mask = (gpu_flags >> 4) & 0x1F;
1049 WriteLog("GPU: Latch bits = %02X, enable bits = %02X\n", bits, mask);
1052 GPUDumpDisassembly();
1054 WriteLog("\nGPU opcodes use:\n");
1055 for(int i=0; i<64; i++)
1057 if (gpu_opcode_use[i])
1058 WriteLog("\t%17s %lu\n", gpu_opcode_str[i], gpu_opcode_use[i]);
1062 memory_free(gpu_ram_8);
1066 // Main GPU execution core
1068 static int testCount = 1;
1070 static bool tripwire = false;
1071 void gpu_exec(int32 cycles)
1076 #ifdef GPU_SINGLE_STEPPING
1077 if (gpu_control & 0x18)
1080 gpu_control &= ~0x10;
1084 gpu_releaseTimeSlice_flag = 0;
1087 while (cycles > 0 && GPU_RUNNING)
1089 /*if (gpu_pc == 0xF0359A)
1094 /* gpu_flag_c = (gpu_flag_c ? 1 : 0);
1095 gpu_flag_z = (gpu_flag_z ? 1 : 0);
1096 gpu_flag_n = (gpu_flag_n ? 1 : 0);*/
1098 uint16 opcode = GPUReadWord(gpu_pc, GPU);
1099 uint32 index = opcode >> 10;
1100 gpu_instruction = opcode; // Added for GPU #3...
1101 gpu_opcode_first_parameter = (opcode >> 5) & 0x1F;
1102 gpu_opcode_second_parameter = opcode & 0x1F;
1103 /*if (gpu_pc == 0xF03BE8)
1104 WriteLog("Start of OP frame write...\n");
1105 if (gpu_pc == 0xF03EEE)
1106 WriteLog("--> Writing BRANCH object ---\n");
1107 if (gpu_pc == 0xF03F62)
1108 WriteLog("--> Writing BITMAP object ***\n");//*/
1109 /*if (gpu_pc == 0xF03546)
1111 WriteLog("\n--> GPU PC: F03546\n");
1113 GPUDumpDisassembly();
1115 /*if (gpu_pc == 0xF033F6)
1117 WriteLog("\n--> GPU PC: F033F6\n");
1119 GPUDumpDisassembly();
1121 /*if (gpu_pc == 0xF033CC)
1123 WriteLog("\n--> GPU PC: F033CC\n");
1125 GPUDumpDisassembly();
1127 /*if (gpu_pc == 0xF033D6)
1129 WriteLog("\n--> GPU PC: F033D6 (#%d)\n", testCount++);
1133 /*if (gpu_pc == 0xF033D8)
1135 WriteLog("\n--> GPU PC: F033D8 (#%d)\n", testCount++);
1139 /*if (gpu_pc == 0xF0358E)
1141 WriteLog("\n--> GPU PC: F0358E (#%d)\n", testCount++);
1145 /*if (gpu_pc == 0xF034CA)
1147 WriteLog("\n--> GPU PC: F034CA (#%d)\n", testCount++);
1150 /*if (gpu_pc == 0xF034CA)
1152 len = gpu_reg[1] + 4;//, r9save = gpu_reg[9];
1153 WriteLog("\nAbout to subtract [#%d] (R14=%08X, R15=%08X, R9=%08X):\n ", testCount++, gpu_reg[14], gpu_reg[15], gpu_reg[9]);
1154 for(int i=0; i<len; i+=4)
1155 WriteLog(" %08X", GPUReadLong(gpu_reg[15]+i));
1157 for(int i=0; i<len; i+=4)
1158 WriteLog(" %08X", GPUReadLong(gpu_reg[14]+i));
1161 if (gpu_pc == 0xF034DE)
1163 WriteLog("\nSubtracted! (R14=%08X, R15=%08X):\n ", gpu_reg[14], gpu_reg[15]);
1164 for(int i=0; i<len; i+=4)
1165 WriteLog(" %08X", GPUReadLong(gpu_reg[15]+i));
1167 for(int i=0; i<len; i+=4)
1168 WriteLog(" %08X", GPUReadLong(gpu_reg[14]+i));
1170 for(int i=0; i<len; i+=4)
1171 WriteLog(" --------");
1173 for(int i=0; i<len; i+=4)
1174 WriteLog(" %08X", GPUReadLong(gpu_reg[9]+4+i));
1177 /*if (gpu_pc == 0xF035C8)
1179 WriteLog("\n--> GPU PC: F035C8 (#%d)\n", testCount++);
1181 GPUDumpDisassembly();
1186 // gpu_reset_stats();
1187 static char buffer[512];
1188 dasmjag(JAGUAR_GPU, buffer, gpu_pc);
1189 WriteLog("GPU: [%08X] %s (RM=%08X, RN=%08X) -> ", gpu_pc, buffer, RM, RN);
1191 //$E400 -> 1110 01 -> $39 -> 57
1194 gpu_opcode[index]();
1196 // gpu2_opcode[index]();
1198 //GPU #3 (Doesn't show ATARI logo! #1 & #2 do...)
1200 // gpu3_opcode[index]();
1203 //GPU: [00F03548] jr nz,00F03560 (0xd561) (RM=00F03114, RN=00000004) -> --> JR: Branch taken.
1204 /*static bool firstTime = true;
1205 if (gpu_pc == 0xF03548 && firstTime)
1208 // firstTime = false;
1210 //static char buffer[512];
1212 //while (k<0xF0356C)
1215 //k += dasmjag(JAGUAR_GPU, buffer, k);
1216 //WriteLog("GPU: [%08X] %s\n", oldk, buffer);
1218 // gpu_start_log = 1;
1220 //GPU: [00F0354C] jump nz,(r29) (0xd3a1) (RM=00F03314, RN=00000004) -> (RM=00F03314, RN=00000004)
1221 /*if (gpu_pc == 0xF0354C)
1222 gpu_flag_z = 0;//, gpu_start_log = 1;//*/
1224 cycles -= gpu_opcode_cycles[index];
1225 gpu_opcode_use[index]++;
1227 WriteLog("(RM=%08X, RN=%08X)\n", RM, RN);//*/
1228 if ((gpu_pc < 0xF03000 || gpu_pc > 0xF03FFF) && !tripwire)
1230 WriteLog("GPU: Executing outside local RAM! GPU_PC: %08X\n", gpu_pc);
1243 GPU opcodes use (offset punch--vertically below bad guy):
1265 load_r14_indexed 1183
1266 load_r15_indexed 1125
1269 store_r14_indexed 320
1277 static void gpu_opcode_jump(void)
1280 char * condition[32] =
1281 { "T", "nz", "z", "???", "nc", "nc nz", "nc z", "???", "c", "c nz",
1282 "c z", "???", "???", "???", "???", "???", "???", "???", "???",
1283 "???", "nn", "nn nz", "nn z", "???", "n", "n nz", "n z", "???",
1284 "???", "???", "???", "F" };
1286 WriteLog("%06X: JUMP %s, (R%02u) [NCZ:%u%u%u, R%02u=%08X] ", gpu_pc-2, condition[IMM_2], IMM_1, gpu_flag_n, gpu_flag_c, gpu_flag_z, IMM_1, RM);
1289 /* gpu_flag_c = (gpu_flag_c ? 1 : 0);
1290 gpu_flag_z = (gpu_flag_z ? 1 : 0);
1291 gpu_flag_n = (gpu_flag_n ? 1 : 0);*/
1292 // KLUDGE: Used by BRANCH_CONDITION
1293 uint32 jaguar_flags = (gpu_flag_n << 2) | (gpu_flag_c << 1) | gpu_flag_z;
1295 if (BRANCH_CONDITION(IMM_2))
1299 WriteLog("Branched!\n");
1302 WriteLog(" --> JUMP: Branch taken.\n");
1303 uint32 delayed_pc = RM;
1305 gpu_pc = delayed_pc;
1306 /* uint16 opcode = GPUReadWord(gpu_pc, GPU);
1307 gpu_opcode_first_parameter = (opcode >> 5) & 0x1F;
1308 gpu_opcode_second_parameter = opcode & 0x1F;
1310 gpu_pc = delayed_pc;
1311 gpu_opcode[opcode>>10]();//*/
1316 WriteLog("Branch NOT taken.\n");
1320 static void gpu_opcode_jr(void)
1323 char * condition[32] =
1324 { "T", "nz", "z", "???", "nc", "nc nz", "nc z", "???", "c", "c nz",
1325 "c z", "???", "???", "???", "???", "???", "???", "???", "???",
1326 "???", "nn", "nn nz", "nn z", "???", "n", "n nz", "n z", "???",
1327 "???", "???", "???", "F" };
1329 WriteLog("%06X: JR %s, %06X [NCZ:%u%u%u] ", gpu_pc-2, condition[IMM_2], gpu_pc+((IMM_1 & 0x10 ? 0xFFFFFFF0 | IMM_1 : IMM_1) * 2), gpu_flag_n, gpu_flag_c, gpu_flag_z);
1331 /* if (CONDITION(jaguar.op & 31))
1333 INT32 r1 = (INT8)((jaguar.op >> 2) & 0xF8) >> 2;
1334 UINT32 newpc = jaguar.PC + r1;
1336 jaguar.op = ROPCODE(jaguar.PC);
1338 (*jaguar.table[jaguar.op >> 10])();
1340 jaguar_icount -= 3; // 3 wait states guaranteed
1343 /* gpu_flag_n = (gpu_flag_n ? 1 : 0);
1344 gpu_flag_c = (gpu_flag_c ? 1 : 0);
1345 gpu_flag_z = (gpu_flag_z ? 1 : 0);*/
1346 // KLUDGE: Used by BRANCH_CONDITION
1347 uint32 jaguar_flags = (gpu_flag_n << 2) | (gpu_flag_c << 1) | gpu_flag_z;
1349 if (BRANCH_CONDITION(IMM_2))
1353 WriteLog("Branched!\n");
1356 WriteLog(" --> JR: Branch taken.\n");
1357 int32 offset = (IMM_1 & 0x10 ? 0xFFFFFFF0 | IMM_1 : IMM_1); // Sign extend IMM_1
1358 int32 delayed_pc = gpu_pc + (offset * 2);
1360 gpu_pc = delayed_pc;
1361 /* uint16 opcode = GPUReadWord(gpu_pc, GPU);
1362 gpu_opcode_first_parameter = (opcode >> 5) & 0x1F;
1363 gpu_opcode_second_parameter = opcode & 0x1F;
1365 gpu_pc = delayed_pc;
1366 gpu_opcode[opcode>>10]();//*/
1371 WriteLog("Branch NOT taken.\n");
1375 static void gpu_opcode_add(void)
1379 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);
1381 UINT32 res = RN + RM;
1382 CLR_ZNC; SET_ZNC_ADD(RN, RM, res);
1386 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);
1390 static void gpu_opcode_addc(void)
1394 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);
1396 /* int dreg = jaguar.op & 31;
1397 UINT32 r1 = jaguar.r[(jaguar.op >> 5) & 31];
1398 UINT32 r2 = jaguar.r[dreg];
1399 UINT32 res = r2 + r1 + ((jaguar.FLAGS >> 1) & 1);
1400 jaguar.r[dreg] = res;
1401 CLR_ZNC; SET_ZNC_ADD(r2,r1,res);*/
1403 UINT32 res = RN + RM + gpu_flag_c;
1404 UINT32 carry = gpu_flag_c;
1405 // SET_ZNC_ADD(RN, RM, res); //???BUG??? Yes!
1406 SET_ZNC_ADD(RN + carry, RM, res);
1407 // SET_ZNC_ADD(RN, RM + carry, res);
1411 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);
1415 static void gpu_opcode_addq(void)
1419 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);
1421 UINT32 r1 = gpu_convert_zero[IMM_1];
1422 UINT32 res = RN + r1;
1423 CLR_ZNC; SET_ZNC_ADD(RN, r1, res);
1427 WriteLog("[NCZ:%u%u%u, R%02u=%08X]\n", gpu_flag_n, gpu_flag_c, gpu_flag_z, IMM_2, RN);
1431 static void gpu_opcode_addqt(void)
1433 #ifdef GPU_DIS_ADDQT
1435 WriteLog("%06X: ADDQT #%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);
1437 RN += gpu_convert_zero[IMM_1];
1438 #ifdef GPU_DIS_ADDQT
1440 WriteLog("[NCZ:%u%u%u, R%02u=%08X]\n", gpu_flag_n, gpu_flag_c, gpu_flag_z, IMM_2, RN);
1444 static void gpu_opcode_sub(void)
1448 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);
1450 UINT32 res = RN - RM;
1451 SET_ZNC_SUB(RN, RM, res);
1455 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);
1459 static void gpu_opcode_subc(void)
1463 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);
1465 UINT32 res = RN - RM - gpu_flag_c;
1466 UINT32 borrow = gpu_flag_c;
1467 // SET_ZNC_SUB(RN, RM, res); //???BUG??? YES!!!
1468 SET_ZNC_SUB(RN - borrow, RM, res);
1472 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);
1476 static void gpu_opcode_subq(void)
1480 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);
1482 UINT32 r1 = gpu_convert_zero[IMM_1];
1483 UINT32 res = RN - r1;
1484 SET_ZNC_SUB(RN, r1, res);
1488 WriteLog("[NCZ:%u%u%u, R%02u=%08X]\n", gpu_flag_n, gpu_flag_c, gpu_flag_z, IMM_2, RN);
1492 static void gpu_opcode_subqt(void)
1494 #ifdef GPU_DIS_SUBQT
1496 WriteLog("%06X: SUBQT #%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);
1498 RN -= gpu_convert_zero[IMM_1];
1499 #ifdef GPU_DIS_SUBQT
1501 WriteLog("[NCZ:%u%u%u, R%02u=%08X]\n", gpu_flag_n, gpu_flag_c, gpu_flag_z, IMM_2, RN);
1505 static void gpu_opcode_cmp(void)
1509 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);
1511 UINT32 res = RN - RM;
1512 SET_ZNC_SUB(RN, RM, res);
1515 WriteLog("[NCZ:%u%u%u]\n", gpu_flag_n, gpu_flag_c, gpu_flag_z);
1519 static void gpu_opcode_cmpq(void)
1521 static int32 sqtable[32] =
1522 { 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 };
1525 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);
1527 UINT32 r1 = sqtable[IMM_1 & 0x1F]; // I like this better -> (INT8)(jaguar.op >> 2) >> 3;
1528 UINT32 res = RN - r1;
1529 SET_ZNC_SUB(RN, r1, res);
1532 WriteLog("[NCZ:%u%u%u]\n", gpu_flag_n, gpu_flag_c, gpu_flag_z);
1536 static void gpu_opcode_and(void)
1540 WriteLog("%06X: AND 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);
1546 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);
1550 static void gpu_opcode_or(void)
1554 WriteLog("%06X: OR 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);
1560 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);
1564 static void gpu_opcode_xor(void)
1568 WriteLog("%06X: XOR 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);
1574 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);
1578 static void gpu_opcode_not(void)
1582 WriteLog("%06X: NOT 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);
1588 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);
1592 static void gpu_opcode_move_pc(void)
1594 #ifdef GPU_DIS_MOVEPC
1596 WriteLog("%06X: MOVE PC, R%02u [NCZ:%u%u%u, PC=%08X, R%02u=%08X] -> ", gpu_pc-2, IMM_1, IMM_2, gpu_flag_n, gpu_flag_c, gpu_flag_z, gpu_pc-2, IMM_2, RN);
1598 // Should be previous PC--this might not always be previous instruction!
1599 // Then again, this will point right at the *current* instruction, i.e., MOVE PC,R!
1601 #ifdef GPU_DIS_MOVEPC
1603 WriteLog("[NCZ:%u%u%u, R%02u=%08X]\n", gpu_flag_n, gpu_flag_c, gpu_flag_z, IMM_2, RN);
1607 static void gpu_opcode_sat8(void)
1611 WriteLog("%06X: SAT8 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);
1613 RN = ((int32)RN < 0 ? 0 : (RN > 0xFF ? 0xFF : RN));
1617 WriteLog("[NCZ:%u%u%u, R%02u=%08X]\n", gpu_flag_n, gpu_flag_c, gpu_flag_z, IMM_2, RN);
1621 static void gpu_opcode_sat16(void)
1623 RN = ((int32)RN < 0 ? 0 : (RN > 0xFFFF ? 0xFFFF : RN));
1627 static void gpu_opcode_sat24(void)
1629 RN = ((int32)RN < 0 ? 0 : (RN > 0xFFFFFF ? 0xFFFFFF : RN));
1633 static void gpu_opcode_store_r14_indexed(void)
1635 #ifdef GPU_DIS_STORE14I
1637 WriteLog("%06X: STORE R%02u, (R14+$%02X) [NCZ:%u%u%u, R%02u=%08X, R14+$%02X=%08X]\n", gpu_pc-2, IMM_2, gpu_convert_zero[IMM_1] << 2, gpu_flag_n, gpu_flag_c, gpu_flag_z, IMM_2, RN, gpu_convert_zero[IMM_1] << 2, gpu_reg[14]+(gpu_convert_zero[IMM_1] << 2));
1639 GPUWriteLong(gpu_reg[14] + (gpu_convert_zero[IMM_1] << 2), RN, GPU);
1642 static void gpu_opcode_store_r15_indexed(void)
1644 #ifdef GPU_DIS_STORE15I
1646 WriteLog("%06X: STORE R%02u, (R15+$%02X) [NCZ:%u%u%u, R%02u=%08X, R15+$%02X=%08X]\n", gpu_pc-2, IMM_2, gpu_convert_zero[IMM_1] << 2, gpu_flag_n, gpu_flag_c, gpu_flag_z, IMM_2, RN, gpu_convert_zero[IMM_1] << 2, gpu_reg[15]+(gpu_convert_zero[IMM_1] << 2));
1648 GPUWriteLong(gpu_reg[15] + (gpu_convert_zero[IMM_1] << 2), RN, GPU);
1651 static void gpu_opcode_load_r14_ri(void)
1653 #ifdef GPU_DIS_LOAD14R
1655 WriteLog("%06X: LOAD (R14+R%02u), R%02u [NCZ:%u%u%u, R14+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+gpu_reg[14], IMM_2, RN);
1657 RN = GPUReadLong(gpu_reg[14] + RM, GPU);
1658 #ifdef GPU_DIS_LOAD14R
1660 WriteLog("[NCZ:%u%u%u, R%02u=%08X]\n", gpu_flag_n, gpu_flag_c, gpu_flag_z, IMM_2, RN);
1664 static void gpu_opcode_load_r15_ri(void)
1666 #ifdef GPU_DIS_LOAD15R
1668 WriteLog("%06X: LOAD (R15+R%02u), R%02u [NCZ:%u%u%u, R15+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+gpu_reg[15], IMM_2, RN);
1670 RN = GPUReadLong(gpu_reg[15] + RM, GPU);
1671 #ifdef GPU_DIS_LOAD15R
1673 WriteLog("[NCZ:%u%u%u, R%02u=%08X]\n", gpu_flag_n, gpu_flag_c, gpu_flag_z, IMM_2, RN);
1677 static void gpu_opcode_store_r14_ri(void)
1679 #ifdef GPU_DIS_STORE14R
1681 WriteLog("%06X: STORE R%02u, (R14+R%02u) [NCZ:%u%u%u, R%02u=%08X, R14+R%02u=%08X]\n", gpu_pc-2, IMM_2, IMM_1, gpu_flag_n, gpu_flag_c, gpu_flag_z, IMM_2, RN, IMM_1, RM+gpu_reg[14]);
1683 GPUWriteLong(gpu_reg[14] + RM, RN, GPU);
1686 static void gpu_opcode_store_r15_ri(void)
1688 #ifdef GPU_DIS_STORE15R
1690 WriteLog("%06X: STORE R%02u, (R15+R%02u) [NCZ:%u%u%u, R%02u=%08X, R15+R%02u=%08X]\n", gpu_pc-2, IMM_2, IMM_1, gpu_flag_n, gpu_flag_c, gpu_flag_z, IMM_2, RN, IMM_1, RM+gpu_reg[15]);
1692 GPUWriteLong(gpu_reg[15] + RM, RN, GPU);
1695 static void gpu_opcode_nop(void)
1699 WriteLog("%06X: NOP [NCZ:%u%u%u]\n", gpu_pc-2, gpu_flag_n, gpu_flag_c, gpu_flag_z);
1703 static void gpu_opcode_pack(void)
1707 WriteLog("%06X: %s R%02u [NCZ:%u%u%u, R%02u=%08X, R%02u=%08X] -> ", gpu_pc-2, (!IMM_1 ? "PACK " : "UNPACK"), IMM_2, gpu_flag_n, gpu_flag_c, gpu_flag_z, IMM_2, RN);
1711 //BUG! if (RM == 0) // Pack
1712 if (IMM_1 == 0) // Pack
1713 RN = ((val >> 10) & 0x0000F000) | ((val >> 5) & 0x00000F00) | (val & 0x000000FF);
1715 RN = ((val & 0x0000F000) << 10) | ((val & 0x00000F00) << 5) | (val & 0x000000FF);
1718 WriteLog("[NCZ:%u%u%u, R%02u=%08X]\n", gpu_flag_n, gpu_flag_c, gpu_flag_z, IMM_2, RN);
1722 static void gpu_opcode_storeb(void)
1724 #ifdef GPU_DIS_STOREB
1726 WriteLog("%06X: STOREB R%02u, (R%02u) [NCZ:%u%u%u, R%02u=%08X, R%02u=%08X]\n", gpu_pc-2, IMM_2, IMM_1, gpu_flag_n, gpu_flag_c, gpu_flag_z, IMM_2, RN, IMM_1, RM);
1729 // Would appear to be so...!
1730 if ((RM >= 0xF03000) && (RM <= 0xF03FFF))
1731 GPUWriteLong(RM, RN & 0xFF, GPU);
1733 JaguarWriteByte(RM, RN, GPU);
1736 static void gpu_opcode_storew(void)
1738 #ifdef GPU_DIS_STOREW
1740 WriteLog("%06X: STOREW R%02u, (R%02u) [NCZ:%u%u%u, R%02u=%08X, R%02u=%08X]\n", gpu_pc-2, IMM_2, IMM_1, gpu_flag_n, gpu_flag_c, gpu_flag_z, IMM_2, RN, IMM_1, RM);
1742 if ((RM >= 0xF03000) && (RM <= 0xF03FFF))
1743 GPUWriteLong(RM, RN & 0xFFFF, GPU);
1745 JaguarWriteWord(RM, RN, GPU);
1748 static void gpu_opcode_store(void)
1750 #ifdef GPU_DIS_STORE
1752 WriteLog("%06X: STORE R%02u, (R%02u) [NCZ:%u%u%u, R%02u=%08X, R%02u=%08X]\n", gpu_pc-2, IMM_2, IMM_1, gpu_flag_n, gpu_flag_c, gpu_flag_z, IMM_2, RN, IMM_1, RM);
1754 GPUWriteLong(RM, RN, GPU);
1757 static void gpu_opcode_storep(void)
1759 GPUWriteLong(RM + 0, gpu_hidata, GPU);
1760 GPUWriteLong(RM + 4, RN, GPU);
1763 static void gpu_opcode_loadb(void)
1765 #ifdef GPU_DIS_LOADB
1767 WriteLog("%06X: LOADB (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);
1769 if ((RM >= 0xF03000) && (RM <= 0xF03FFF))
1770 RN = GPUReadLong(RM, GPU) & 0xFF;
1772 RN = JaguarReadByte(RM, GPU);
1773 #ifdef GPU_DIS_LOADB
1775 WriteLog("[NCZ:%u%u%u, R%02u=%08X]\n", gpu_flag_n, gpu_flag_c, gpu_flag_z, IMM_2, RN);
1779 static void gpu_opcode_loadw(void)
1781 #ifdef GPU_DIS_LOADW
1783 WriteLog("%06X: LOADW (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);
1785 if ((RM >= 0xF03000) && (RM <= 0xF03FFF))
1786 RN = GPUReadLong(RM, GPU) & 0xFFFF;
1788 RN = JaguarReadWord(RM, GPU);
1789 #ifdef GPU_DIS_LOADW
1791 WriteLog("[NCZ:%u%u%u, R%02u=%08X]\n", gpu_flag_n, gpu_flag_c, gpu_flag_z, IMM_2, RN);
1795 static void gpu_opcode_load(void)
1799 WriteLog("%06X: LOAD (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);
1801 RN = GPUReadLong(RM, GPU);
1804 WriteLog("[NCZ:%u%u%u, R%02u=%08X]\n", gpu_flag_n, gpu_flag_c, gpu_flag_z, IMM_2, RN);
1808 static void gpu_opcode_loadp(void)
1810 gpu_hidata = GPUReadLong(RM + 0, GPU);
1811 RN = GPUReadLong(RM + 4, GPU);
1814 static void gpu_opcode_load_r14_indexed(void)
1816 #ifdef GPU_DIS_LOAD14I
1818 WriteLog("%06X: LOAD (R14+$%02X), R%02u [NCZ:%u%u%u, R14+$%02X=%08X, R%02u=%08X] -> ", gpu_pc-2, gpu_convert_zero[IMM_1] << 2, IMM_2, gpu_flag_n, gpu_flag_c, gpu_flag_z, gpu_convert_zero[IMM_1] << 2, gpu_reg[14]+(gpu_convert_zero[IMM_1] << 2), IMM_2, RN);
1820 RN = GPUReadLong(gpu_reg[14] + (gpu_convert_zero[IMM_1] << 2), GPU);
1821 #ifdef GPU_DIS_LOAD14I
1823 WriteLog("[NCZ:%u%u%u, R%02u=%08X]\n", gpu_flag_n, gpu_flag_c, gpu_flag_z, IMM_2, RN);
1827 static void gpu_opcode_load_r15_indexed(void)
1829 #ifdef GPU_DIS_LOAD15I
1831 WriteLog("%06X: LOAD (R15+$%02X), R%02u [NCZ:%u%u%u, R15+$%02X=%08X, R%02u=%08X] -> ", gpu_pc-2, gpu_convert_zero[IMM_1] << 2, IMM_2, gpu_flag_n, gpu_flag_c, gpu_flag_z, gpu_convert_zero[IMM_1] << 2, gpu_reg[15]+(gpu_convert_zero[IMM_1] << 2), IMM_2, RN);
1833 RN = GPUReadLong(gpu_reg[15] + (gpu_convert_zero[IMM_1] << 2), GPU);
1834 #ifdef GPU_DIS_LOAD15I
1836 WriteLog("[NCZ:%u%u%u, R%02u=%08X]\n", gpu_flag_n, gpu_flag_c, gpu_flag_z, IMM_2, RN);
1840 static void gpu_opcode_movei(void)
1842 #ifdef GPU_DIS_MOVEI
1844 WriteLog("%06X: MOVEI #$%08X, R%02u [NCZ:%u%u%u, R%02u=%08X] -> ", gpu_pc-2, (uint32)GPUReadWord(gpu_pc) | ((uint32)GPUReadWord(gpu_pc + 2) << 16), IMM_2, gpu_flag_n, gpu_flag_c, gpu_flag_z, IMM_2, RN);
1846 // This instruction is followed by 32-bit value in LSW / MSW format...
1847 RN = (uint32)GPUReadWord(gpu_pc, GPU) | ((uint32)GPUReadWord(gpu_pc + 2, GPU) << 16);
1849 #ifdef GPU_DIS_MOVEI
1851 WriteLog("[NCZ:%u%u%u, R%02u=%08X]\n", gpu_flag_n, gpu_flag_c, gpu_flag_z, IMM_2, RN);
1855 static void gpu_opcode_moveta(void)
1857 #ifdef GPU_DIS_MOVETA
1859 WriteLog("%06X: MOVETA R%02u, R%02u [NCZ:%u%u%u, R%02u=%08X, R%02u(alt)=%08X] -> ", gpu_pc-2, IMM_1, IMM_2, gpu_flag_n, gpu_flag_c, gpu_flag_z, IMM_1, RM, IMM_2, ALTERNATE_RN);
1862 #ifdef GPU_DIS_MOVETA
1864 WriteLog("[NCZ:%u%u%u, R%02u=%08X, R%02u(alt)=%08X]\n", gpu_flag_n, gpu_flag_c, gpu_flag_z, IMM_1, RM, IMM_2, ALTERNATE_RN);
1868 static void gpu_opcode_movefa(void)
1870 #ifdef GPU_DIS_MOVEFA
1872 WriteLog("%06X: MOVEFA R%02u, R%02u [NCZ:%u%u%u, R%02u(alt)=%08X, R%02u=%08X] -> ", gpu_pc-2, IMM_1, IMM_2, gpu_flag_n, gpu_flag_c, gpu_flag_z, IMM_1, ALTERNATE_RM, IMM_2, RN);
1875 #ifdef GPU_DIS_MOVEFA
1877 WriteLog("[NCZ:%u%u%u, R%02u(alt)=%08X, R%02u=%08X]\n", gpu_flag_n, gpu_flag_c, gpu_flag_z, IMM_1, ALTERNATE_RM, IMM_2, RN);
1881 static void gpu_opcode_move(void)
1885 WriteLog("%06X: MOVE 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);
1890 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);
1894 static void gpu_opcode_moveq(void)
1896 #ifdef GPU_DIS_MOVEQ
1898 WriteLog("%06X: MOVEQ #%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);
1901 #ifdef GPU_DIS_MOVEQ
1903 WriteLog("[NCZ:%u%u%u, R%02u=%08X]\n", gpu_flag_n, gpu_flag_c, gpu_flag_z, IMM_2, RN);
1907 static void gpu_opcode_resmac(void)
1912 static void gpu_opcode_imult(void)
1914 #ifdef GPU_DIS_IMULT
1916 WriteLog("%06X: IMULT 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);
1918 RN = (int16)RN * (int16)RM;
1920 #ifdef GPU_DIS_IMULT
1922 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);
1926 static void gpu_opcode_mult(void)
1930 WriteLog("%06X: MULT 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);
1932 RN = (uint16)RM * (uint16)RN;
1936 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);
1940 static void gpu_opcode_bclr(void)
1944 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);
1946 UINT32 res = RN & ~(1 << IMM_1);
1951 WriteLog("[NCZ:%u%u%u, R%02u=%08X]\n", gpu_flag_n, gpu_flag_c, gpu_flag_z, IMM_2, RN);
1955 static void gpu_opcode_btst(void)
1959 WriteLog("%06X: BTST #%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);
1961 gpu_flag_z = (~RN >> IMM_1) & 1;
1964 WriteLog("[NCZ:%u%u%u, R%02u=%08X]\n", gpu_flag_n, gpu_flag_c, gpu_flag_z, IMM_2, RN);
1968 static void gpu_opcode_bset(void)
1972 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);
1974 UINT32 res = RN | (1 << IMM_1);
1979 WriteLog("[NCZ:%u%u%u, R%02u=%08X]\n", gpu_flag_n, gpu_flag_c, gpu_flag_z, IMM_2, RN);
1983 static void gpu_opcode_imacn(void)
1985 uint32 res = (int16)RM * (int16)(RN);
1989 static void gpu_opcode_mtoi(void)
1992 uint32 res = RN = (((INT32)_RM >> 8) & 0xFF800000) | (_RM & 0x007FFFFF);
1996 static void gpu_opcode_normi(void)
2003 while ((_RM & 0xFFC00000) == 0)
2008 while ((_RM & 0xFF800000) != 0)
2018 static void gpu_opcode_mmult(void)
2020 int count = gpu_matrix_control & 0x0F; // Matrix width
2021 uint32 addr = gpu_pointer_to_matrix; // In the GPU's RAM
2025 if (gpu_matrix_control & 0x10) // Column stepping
2027 for(int i=0; i<count; i++)
2031 a = (int16)((gpu_alternate_reg[IMM_1 + (i >> 1)] >> 16) & 0xFFFF);
2033 a = (int16)(gpu_alternate_reg[IMM_1 + (i >> 1)] & 0xFFFF);
2035 int16 b = ((int16)GPUReadWord(addr + 2, GPU));
2040 else // Row stepping
2042 for(int i=0; i<count; i++)
2046 a = (int16)((gpu_alternate_reg[IMM_1 + (i >> 1)] >> 16) & 0xFFFF);
2048 a = (int16)(gpu_alternate_reg[IMM_1 + (i >> 1)] & 0xFFFF);
2050 int16 b = ((int16)GPUReadWord(addr + 2, GPU));
2055 RN = res = (int32)accum;
2056 // carry flag to do (out of the last add)
2060 static void gpu_opcode_abs(void)
2064 WriteLog("%06X: ABS 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);
2066 gpu_flag_c = RN >> 31;
2067 if (RN == 0x80000000)
2068 //Is 0x80000000 a positive number? If so, then we need to set C to 0 as well!
2069 gpu_flag_n = 1, gpu_flag_z = 0;
2074 gpu_flag_n = 0; SET_FLAG_Z(RN);
2078 WriteLog("[NCZ:%u%u%u, R%02u=%08X]\n", gpu_flag_n, gpu_flag_c, gpu_flag_z, IMM_2, RN);
2082 static void gpu_opcode_div(void) // RN / RM
2086 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);
2088 // NOTE: remainder is NOT calculated correctly here!
2089 // The original tried to get it right by checking to see if the
2090 // remainder was negative, but that's too late...
2091 // The code there should do it now, but I'm not 100% sure...
2095 if (gpu_div_control & 0x01) // 16.16 division
2097 RN = ((UINT64)RN << 16) / RM;
2098 gpu_remain = ((UINT64)RN << 16) % RM;
2103 gpu_remain = RN % RM;
2106 if ((gpu_remain - RM) & 0x80000000) // If the result would have been negative...
2107 gpu_remain -= RM; // Then make it negative!
2117 if (gpu_div_control & 1)
2119 gpu_remain = (((uint64)_RN) << 16) % _RM;
2120 if (gpu_remain&0x80000000)
2122 RN = (((uint64)_RN) << 16) / _RM;
2126 gpu_remain = _RN % _RM;
2127 if (gpu_remain&0x80000000)
2136 WriteLog("[NCZ:%u%u%u, R%02u=%08X, R%02u=%08X] Remainder: %08X\n", gpu_flag_n, gpu_flag_c, gpu_flag_z, IMM_1, RM, IMM_2, RN, gpu_remain);
2140 static void gpu_opcode_imultn(void)
2142 uint32 res = (int32)((int16)RN * (int16)RM);
2143 gpu_acc = (int32)res;
2148 static void gpu_opcode_neg(void)
2152 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);
2155 SET_ZNC_SUB(0, RN, res);
2159 WriteLog("[NCZ:%u%u%u, R%02u=%08X]\n", gpu_flag_n, gpu_flag_c, gpu_flag_z, IMM_2, RN);
2163 static void gpu_opcode_shlq(void)
2167 WriteLog("%06X: SHLQ #%u, R%02u [NCZ:%u%u%u, R%02u=%08X] -> ", gpu_pc-2, 32 - IMM_1, IMM_2, gpu_flag_n, gpu_flag_c, gpu_flag_z, IMM_2, RN);
2169 // Was a bug here...
2170 // (Look at Aaron's code: If r1 = 32, then 32 - 32 = 0 which is wrong!)
2171 INT32 r1 = 32 - IMM_1;
2172 UINT32 res = RN << r1;
2173 SET_ZN(res); gpu_flag_c = (RN >> 31) & 1;
2177 WriteLog("[NCZ:%u%u%u, R%02u=%08X]\n", gpu_flag_n, gpu_flag_c, gpu_flag_z, IMM_2, RN);
2181 static void gpu_opcode_shrq(void)
2185 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);
2187 INT32 r1 = gpu_convert_zero[IMM_1];
2188 UINT32 res = RN >> r1;
2189 SET_ZN(res); gpu_flag_c = RN & 1;
2193 WriteLog("[NCZ:%u%u%u, R%02u=%08X]\n", gpu_flag_n, gpu_flag_c, gpu_flag_z, IMM_2, RN);
2197 static void gpu_opcode_ror(void)
2201 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);
2203 UINT32 r1 = RM & 0x1F;
2204 UINT32 res = (RN >> r1) | (RN << (32 - r1));
2205 SET_ZN(res); gpu_flag_c = (RN >> 31) & 1;
2209 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);
2213 static void gpu_opcode_rorq(void)
2217 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);
2219 UINT32 r1 = gpu_convert_zero[IMM_1 & 0x1F];
2221 UINT32 res = (r2 >> r1) | (r2 << (32 - r1));
2223 SET_ZN(res); gpu_flag_c = (r2 >> 31) & 0x01;
2226 WriteLog("[NCZ:%u%u%u, R%02u=%08X]\n", gpu_flag_n, gpu_flag_c, gpu_flag_z, IMM_2, RN);
2230 static void gpu_opcode_sha(void)
2232 /* int dreg = jaguar.op & 31;
2233 INT32 r1 = (INT32)jaguar.r[(jaguar.op >> 5) & 31];
2234 UINT32 r2 = jaguar.r[dreg];
2240 res = (r1 <= -32) ? 0 : (r2 << -r1);
2241 jaguar.FLAGS |= (r2 >> 30) & 2;
2245 res = (r1 >= 32) ? ((INT32)r2 >> 31) : ((INT32)r2 >> r1);
2246 jaguar.FLAGS |= (r2 << 1) & 2;
2248 jaguar.r[dreg] = res;
2253 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);
2259 res = ((INT32)RM <= -32) ? 0 : (RN << -(INT32)RM);
2260 gpu_flag_c = RN >> 31;
2264 res = ((INT32)RM >= 32) ? ((INT32)RN >> 31) : ((INT32)RN >> (INT32)RM);
2265 gpu_flag_c = RN & 0x01;
2271 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);
2274 /* int32 sRM=(int32)RM;
2280 if (shift>=32) shift=32;
2281 gpu_flag_c=(_RN&0x80000000)>>31;
2291 if (shift>=32) shift=32;
2295 _RN=((int32)_RN)>>1;
2304 static void gpu_opcode_sharq(void)
2306 #ifdef GPU_DIS_SHARQ
2308 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);
2310 UINT32 res = (INT32)RN >> gpu_convert_zero[IMM_1];
2311 SET_ZN(res); gpu_flag_c = RN & 0x01;
2313 #ifdef GPU_DIS_SHARQ
2315 WriteLog("[NCZ:%u%u%u, R%02u=%08X]\n", gpu_flag_n, gpu_flag_c, gpu_flag_z, IMM_2, RN);
2319 static void gpu_opcode_sh(void)
2323 WriteLog("%06X: SH 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);
2325 if (RM & 0x80000000) // Shift left
2327 gpu_flag_c = RN >> 31;
2328 RN = ((int32)RM <= -32 ? 0 : RN << -(int32)RM);
2332 gpu_flag_c = RN & 0x01;
2333 RN = (RM >= 32 ? 0 : RN >> RM);
2338 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);
2342 //Temporary: Testing only!
2343 //#include "gpu2.cpp"
2344 //#include "gpu3.cpp"