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 // Private function prototypes
150 void GPUUpdateRegisterBanks(void);
152 void GPUDumpDisassembly(void);
153 void GPUDumpRegisters(void);
154 void GPUDumpMemory(void);
156 // External global variables
158 extern int start_logging;
159 extern int gpu_start_log;
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 >= GPU_WORK_RAM_BASE) && (offset < GPU_WORK_RAM_BASE+0x1000))
388 return gpu_ram_8[offset & 0xFFF];
389 else if ((offset >= GPU_CONTROL_RAM_BASE) && (offset < GPU_CONTROL_RAM_BASE+0x20))
391 uint32 data = GPUReadLong(offset & 0xFFFFFFFC, who);
393 if ((offset & 0x03) == 0)
395 else if ((offset & 0x03) == 1)
396 return (data >> 16) & 0xFF;
397 else if ((offset & 0x03) == 2)
398 return (data >> 8) & 0xFF;
399 else if ((offset & 0x03) == 3)
403 return JaguarReadByte(offset, who);
407 // GPU word access (read)
409 uint16 GPUReadWord(uint32 offset, uint32 who/*=UNKNOWN*/)
411 if ((offset >= GPU_WORK_RAM_BASE) && (offset < GPU_WORK_RAM_BASE+0x1000))
414 uint16 data = ((uint16)gpu_ram_8[offset] << 8) | (uint16)gpu_ram_8[offset+1];
417 else if ((offset >= GPU_CONTROL_RAM_BASE) && (offset < GPU_CONTROL_RAM_BASE+0x20))
419 // This looks and smells wrong...
420 // But it *might* be OK...
421 if (offset & 0x01) // Catch cases 1 & 3... (unaligned read)
422 return (GPUReadByte(offset, who) << 8) | GPUReadByte(offset+1, who);
424 uint32 data = GPUReadLong(offset & 0xFFFFFFFC, who);
426 if (offset & 0x02) // Cases 0 & 2...
427 return data & 0xFFFF;
432 //TEMP--Mirror of F03000?
433 if (offset >= 0xF0B000 && offset <= 0xF0BFFF)
434 WriteLog("[GPUR16] --> Possible GPU RAM mirror access by %s!", whoName[who]);
436 return JaguarReadWord(offset, who);
440 // GPU dword access (read)
442 uint32 GPUReadLong(uint32 offset, uint32 who/*=UNKNOWN*/)
444 // if ((offset >= GPU_WORK_RAM_BASE) && (offset < GPU_WORK_RAM_BASE + 0x1000))
445 if ((offset >= GPU_WORK_RAM_BASE) && (offset <= GPU_WORK_RAM_BASE + 0x0FFC))
448 return ((uint32)gpu_ram_8[offset] << 24) | ((uint32)gpu_ram_8[offset+1] << 16)
449 | ((uint32)gpu_ram_8[offset+2] << 8) | (uint32)gpu_ram_8[offset+3];//*/
450 // return GET32(gpu_ram_8, offset);
452 // else if ((offset >= GPU_CONTROL_RAM_BASE) && (offset < GPU_CONTROL_RAM_BASE+0x20))
453 else if ((offset >= GPU_CONTROL_RAM_BASE) && (offset <= GPU_CONTROL_RAM_BASE + 0x1C))
459 gpu_flag_c = (gpu_flag_c ? 1 : 0);
460 gpu_flag_z = (gpu_flag_z ? 1 : 0);
461 gpu_flag_n = (gpu_flag_n ? 1 : 0);
463 gpu_flags = (gpu_flags & 0xFFFFFFF8) | (gpu_flag_n << 2) | (gpu_flag_c << 1) | gpu_flag_z;
465 return gpu_flags & 0xFFFFC1FF;
467 return gpu_matrix_control;
469 return gpu_pointer_to_matrix;
471 return gpu_data_organization;
480 default: // unaligned long read
482 WriteLog("GPU: Read32--unaligned 32 bit read at %08X by %s.\n", GPU_CONTROL_RAM_BASE + offset, whoName[who]);
487 //TEMP--Mirror of F03000?
488 if (offset >= 0xF0B000 && offset <= 0xF0BFFF)
489 WriteLog("[GPUR32] --> Possible GPU RAM mirror access by %s!\n", whoName[who]);
490 /*if (offset >= 0xF1D000 && offset <= 0xF1DFFF)
491 WriteLog("[GPUR32] --> Reading from Wavetable ROM!\n");//*/
493 return (JaguarReadWord(offset, who) << 16) | JaguarReadWord(offset + 2, who);
497 // GPU byte access (write)
499 void GPUWriteByte(uint32 offset, uint8 data, uint32 who/*=UNKNOWN*/)
501 if ((offset >= GPU_WORK_RAM_BASE) && (offset <= GPU_WORK_RAM_BASE + 0x0FFF))
503 gpu_ram_8[offset & 0xFFF] = data;
505 //This is the same stupid worthless code that was in the DSP!!! AARRRGGGGHHHHH!!!!!!
508 m68k_end_timeslice();
509 dsp_releaseTimeslice();
513 else if ((offset >= GPU_CONTROL_RAM_BASE) && (offset <= GPU_CONTROL_RAM_BASE + 0x1F))
515 uint32 reg = offset & 0x1C;
516 int bytenum = offset & 0x03;
518 //This is definitely wrong!
519 if ((reg >= 0x1C) && (reg <= 0x1F))
520 gpu_div_control = (gpu_div_control & (~(0xFF << (bytenum << 3)))) | (data << (bytenum << 3));
523 uint32 old_data = GPUReadLong(offset & 0xFFFFFFC, who);
524 bytenum = 3 - bytenum; // convention motorola !!!
525 old_data = (old_data & (~(0xFF << (bytenum << 3)))) | (data << (bytenum << 3));
526 GPUWriteLong(offset & 0xFFFFFFC, old_data, who);
530 // WriteLog("gpu: writing %.2x at 0x%.8x\n",data,offset);
531 JaguarWriteByte(offset, data, who);
535 // GPU word access (write)
537 void GPUWriteWord(uint32 offset, uint16 data, uint32 who/*=UNKNOWN*/)
539 if ((offset >= GPU_WORK_RAM_BASE) && (offset <= GPU_WORK_RAM_BASE + 0x0FFE))
541 gpu_ram_8[offset & 0xFFF] = (data>>8) & 0xFF;
542 gpu_ram_8[(offset+1) & 0xFFF] = data & 0xFF;//*/
544 SET16(gpu_ram_8, offset, data);//*/
546 //This is the same stupid worthless code that was in the DSP!!! AARRRGGGGHHHHH!!!!!!
549 m68k_end_timeslice();
550 dsp_releaseTimeslice();
554 else if ((offset >= GPU_CONTROL_RAM_BASE) && (offset <= GPU_CONTROL_RAM_BASE + 0x1E))
556 if (offset & 0x01) // This is supposed to weed out unaligned writes, but does nothing...
559 WriteLog("GPU: Write16--unaligned write @ %08X [%04X]\n", offset, data);
564 //Dual locations in this range: $1C Divide unit remainder/Divide unit control (R/W)
565 //This just literally sucks.
566 if ((offset & 0x1C) == 0x1C)
568 //This doesn't look right either--handles cases 1, 2, & 3 all the same!
570 gpu_div_control = (gpu_div_control & 0xFFFF0000) | (data & 0xFFFF);
572 gpu_div_control = (gpu_div_control & 0x0000FFFF) | ((data & 0xFFFF) << 16);
576 //WriteLog("[GPU W16:%08X,%04X]", offset, data);
577 uint32 old_data = GPUReadLong(offset & 0xFFFFFFC, who);
579 old_data = (old_data & 0xFFFF0000) | (data & 0xFFFF);
581 old_data = (old_data & 0x0000FFFF) | ((data & 0xFFFF) << 16);
582 GPUWriteLong(offset & 0xFFFFFFC, old_data, who);
586 else if ((offset == GPU_WORK_RAM_BASE + 0x0FFF) || (GPU_CONTROL_RAM_BASE + 0x1F))
589 WriteLog("GPU: Write16--unaligned write @ %08X by %s [%04X]!\n", offset, whoName[who], data);
595 // Have to be careful here--this can cause an infinite loop!
596 JaguarWriteWord(offset, data, who);
600 // GPU dword access (write)
602 void GPUWriteLong(uint32 offset, uint32 data, uint32 who/*=UNKNOWN*/)
604 // if ((offset >= GPU_WORK_RAM_BASE) && (offset < GPU_WORK_RAM_BASE + 0x1000))
605 if ((offset >= GPU_WORK_RAM_BASE) && (offset <= GPU_WORK_RAM_BASE + 0x0FFC))
610 WriteLog("GPU: Write32--unaligned write @ %08X [%08X]\n", offset, data);
615 /* gpu_ram_8[offset & 0xFFF] = (data >> 24) & 0xFF,
616 gpu_ram_8[(offset+1) & 0xFFF] = (data >> 16) & 0xFF,
617 gpu_ram_8[(offset+2) & 0xFFF] = (data >> 8) & 0xFF,
618 gpu_ram_8[(offset+3) & 0xFFF] = data & 0xFF;//*/
620 SET32(gpu_ram_8, offset, data);//*/
623 // else if ((offset >= GPU_CONTROL_RAM_BASE) && (offset < GPU_CONTROL_RAM_BASE+0x20))
624 else if ((offset >= GPU_CONTROL_RAM_BASE) && (offset <= GPU_CONTROL_RAM_BASE + 0x1C))
631 bool IMASKCleared = (gpu_flags & IMASK) && !(data & IMASK);
633 gpu_flag_z = gpu_flags & ZERO_FLAG;
634 gpu_flag_c = (gpu_flags & CARRY_FLAG) >> 1;
635 gpu_flag_n = (gpu_flags & NEGA_FLAG) >> 2;
636 GPUUpdateRegisterBanks();
637 gpu_control &= ~((gpu_flags & CINT04FLAGS) >> 3); // Interrupt latch clear bits
638 //Writing here is only an interrupt enable--this approach is just plain wrong!
640 //This, however, is A-OK! ;-)
641 if (IMASKCleared) // If IMASK was cleared,
642 GPUHandleIRQs(); // see if any other interrupts need servicing!
644 if (gpu_flags & (INT_ENA0 | INT_ENA1 | INT_ENA2 | INT_ENA3 | INT_ENA4))
645 WriteLog("GPU: Interrupt enable set by %s! Bits: %02X\n", whoName[who], (gpu_flags >> 4) & 0x1F);
646 WriteLog("GPU: REGPAGE %s...\n", (gpu_flags & REGPAGE ? "set" : "cleared"));
651 gpu_matrix_control = data;
654 // Can only point to long aligned addresses
655 gpu_pointer_to_matrix = data & 0xFFFFFFFC;
658 gpu_data_organization = data;
663 WriteLog("GPU: %s setting GPU PC to %08X %s\n", whoName[who], gpu_pc, (GPU_RUNNING ? "(GPU is RUNNING!)" : ""));//*/
668 // uint32 gpu_was_running = GPU_RUNNING;
669 data &= ~0xF7C0; // Disable writes to INT_LAT0-4 & TOM version number
671 // check for GPU -> CPU interrupt
674 //WriteLog("GPU->CPU interrupt\n");
675 if (tom_irq_enabled(IRQ_GPU))
677 if ((tom_irq_enabled(IRQ_GPU)) && (jaguar_interrupt_handler_is_valid(64)))
679 tom_set_pending_gpu_int();
680 m68k_set_irq(7); // Set 68000 NMI
681 gpu_releaseTimeslice();
687 // check for CPU -> GPU interrupt #0
690 //WriteLog("CPU->GPU interrupt\n");
691 GPUSetIRQLine(0, ASSERT_LINE);
692 m68k_end_timeslice();
693 dsp_releaseTimeslice();
700 //WriteLog("asked to perform a single step (single step is %senabled)\n",(data&0x8)?"":"not ");
702 // gpu_control = (gpu_control & 0x107C0) | (data & (~0x107C0));
703 gpu_control = (gpu_control & 0xF7C0) | (data & (~0xF7C0));
705 // if gpu wasn't running but is now running, execute a few cycles
706 #ifndef GPU_SINGLE_STEPPING
707 /* if (!gpu_was_running && GPU_RUNNING)
710 WriteLog("GPU: Write32--About to do stupid braindead GPU execution for 200 cycles.\n");
715 #endif // GPU_DEBUG//*/
717 if (gpu_control & 0x18)
719 #endif // #ifndef GPU_SINGLE_STEPPING
721 WriteLog("Write to GPU CTRL by %s: %08X ", whoName[who], data);
723 WriteLog(" --> Starting to run at %08X by %s...", gpu_pc, whoName[who]);
725 WriteLog(" --> Stopped by %s! (GPU_PC: %08X)", whoName[who], gpu_pc);
729 // GPUDumpDisassembly();
730 // (?) If we're set running by the M68K (or DSP?) then end its timeslice to
731 // allow the GPU a chance to run...
732 // Yes! This partially fixed Trevor McFur...
734 m68k_end_timeslice();
741 gpu_div_control = data;
743 // default: // unaligned long write
750 // JaguarWriteWord(offset, (data >> 16) & 0xFFFF, who);
751 // JaguarWriteWord(offset+2, data & 0xFFFF, who);
752 JaguarWriteLong(offset, data, who);
756 // Change register banks if necessary
758 void GPUUpdateRegisterBanks(void)
760 int bank = (gpu_flags & REGPAGE); // REGPAGE bit
762 if (gpu_flags & IMASK) // IMASK bit
763 bank = 0; // IMASK forces main bank to be bank 0
766 gpu_reg = gpu_reg_bank_1, gpu_alternate_reg = gpu_reg_bank_0;
768 gpu_reg = gpu_reg_bank_0, gpu_alternate_reg = gpu_reg_bank_1;
771 void GPUHandleIRQs(void)
773 // Bail out if we're already in an interrupt!
774 if (gpu_flags & IMASK)
777 // Get the interrupt latch & enable bits
778 uint32 bits = (gpu_control >> 6) & 0x1F, mask = (gpu_flags >> 4) & 0x1F;
780 // Bail out if latched interrupts aren't enabled
785 // Determine which interrupt to service
786 uint32 which = 0; //Isn't there a #pragma to disable this warning???
799 WriteLog("GPU: Generating IRQ #%i\n", which);
801 // set the interrupt flag
803 GPUUpdateRegisterBanks();
805 // subqt #4,r31 ; pre-decrement stack pointer
806 // move pc,r30 ; address of interrupted code
807 // store r30,(r31) ; store return address
809 GPUWriteLong(gpu_reg[31], gpu_pc - 2, GPU);
811 // movei #service_address,r30 ; pointer to ISR entry
812 // jump (r30) ; jump to ISR
814 gpu_pc = gpu_reg[30] = GPU_WORK_RAM_BASE + (which * 0x10);
817 void GPUSetIRQLine(int irqline, int state)
820 WriteLog("GPU: Setting GPU IRQ line #%i\n", irqline);
822 uint32 mask = 0x0040 << irqline;
823 gpu_control &= ~mask; // Clear the interrupt latch
827 gpu_control |= mask; // Assert the interrupt latch
828 GPUHandleIRQs(); // And handle the interrupt...
832 //TEMPORARY: Testing only!
838 memory_malloc_secure((void **)&gpu_ram_8, 0x1000, "GPU work RAM");
839 // memory_malloc_secure((void **)&gpu_reg, 32*sizeof(int32), "GPU bank 0 regs");
840 // memory_malloc_secure((void **)&gpu_alternate_reg, 32*sizeof(int32), "GPU bank 1 regs");
841 memory_malloc_secure((void **)&gpu_reg_bank_0, 32 * sizeof(int32), "GPU bank 0 regs");
842 memory_malloc_secure((void **)&gpu_reg_bank_1, 32 * sizeof(int32), "GPU bank 1 regs");
844 build_branch_condition_table();
848 //TEMPORARY: Testing only!
855 // GPU registers (directly visible)
856 gpu_flags = 0x00000000;
857 gpu_matrix_control = 0x00000000;
858 gpu_pointer_to_matrix = 0x00000000;
859 gpu_data_organization = 0xFFFFFFFF;
861 gpu_control = 0x00002800; // Correctly sets this as TOM Rev. 2
862 gpu_hidata = 0x00000000;
863 gpu_remain = 0x00000000; // These two registers are RO/WO
864 gpu_div_control = 0x00000000;
866 // GPU internal register
867 gpu_acc = 0x00000000;
869 gpu_reg = gpu_reg_bank_0;
870 gpu_alternate_reg = gpu_reg_bank_1;
872 for(int i=0; i<32; i++)
873 gpu_reg[i] = gpu_alternate_reg[i] = 0x00000000;
876 memset(gpu_ram_8, 0xFF, 0x1000);
878 //not needed GPUInterruptPending = false;
882 uint32 gpu_read_pc(void)
887 void gpu_reset_stats(void)
889 for(uint32 i=0; i<64; i++)
890 gpu_opcode_use[i] = 0;
891 WriteLog("--> GPU stats were reset!\n");
894 void GPUDumpDisassembly(void)
898 WriteLog("\n---[GPU code at 00F03000]---------------------------\n");
900 while (j <= 0xF03FFF)
903 j += dasmjag(JAGUAR_GPU, buffer, j);
904 WriteLog("\t%08X: %s\n", oldj, buffer);
908 void GPUDumpRegisters(void)
910 WriteLog("\n---[GPU flags: NCZ %d%d%d]-----------------------\n", gpu_flag_n, gpu_flag_c, gpu_flag_z);
911 WriteLog("\nRegisters bank 0\n");
912 for(int j=0; j<8; j++)
914 WriteLog("\tR%02i = %08X R%02i = %08X R%02i = %08X R%02i = %08X\n",
915 (j << 2) + 0, gpu_reg_bank_0[(j << 2) + 0],
916 (j << 2) + 1, gpu_reg_bank_0[(j << 2) + 1],
917 (j << 2) + 2, gpu_reg_bank_0[(j << 2) + 2],
918 (j << 2) + 3, gpu_reg_bank_0[(j << 2) + 3]);
920 WriteLog("Registers bank 1\n");
921 for(int j=0; j<8; j++)
923 WriteLog("\tR%02i = %08X R%02i = %08X R%02i = %08X R%02i = %08X\n",
924 (j << 2) + 0, gpu_reg_bank_1[(j << 2) + 0],
925 (j << 2) + 1, gpu_reg_bank_1[(j << 2) + 1],
926 (j << 2) + 2, gpu_reg_bank_1[(j << 2) + 2],
927 (j << 2) + 3, gpu_reg_bank_1[(j << 2) + 3]);
931 void GPUDumpMemory(void)
933 WriteLog("\n---[GPU data at 00F03000]---------------------------\n");
934 for(int i=0; i<0xFFF; i+=4)
935 WriteLog("\t%08X: %02X %02X %02X %02X\n", 0xF03000+i, gpu_ram_8[i],
936 gpu_ram_8[i+1], gpu_ram_8[i+2], gpu_ram_8[i+3]);
941 WriteLog("GPU: stopped at PC=%08X (GPU %s running)\n", (unsigned int)gpu_pc, GPU_RUNNING ? "was" : "wasn't");
943 // Get the interrupt latch & enable bits
944 uint8 bits = (gpu_control >> 6) & 0x1F, mask = (gpu_flags >> 4) & 0x1F;
945 WriteLog("GPU: Latch bits = %02X, enable bits = %02X\n", bits, mask);
948 GPUDumpDisassembly();
950 /* WriteLog("---[GPU code at %08X]---------------------------\n", gpu_pc);
952 for(int i=0; i<4096; i++)
955 j += dasmjag(JAGUAR_GPU, buffer, j);
956 WriteLog("\t%08X: %s\n", oldj, buffer);
959 WriteLog("\nGPU opcodes use:\n");
960 for(int i=0; i<64; i++)
962 if (gpu_opcode_use[i])
963 WriteLog("\t%17s %lu\n", gpu_opcode_str[i], gpu_opcode_use[i]);
967 memory_free(gpu_ram_8);
971 // Main GPU execution core
973 static int testCount = 1;
975 static bool tripwire = false;
976 void gpu_exec(int32 cycles)
981 #ifdef GPU_SINGLE_STEPPING
982 if (gpu_control & 0x18)
985 gpu_control &= ~0x10;
989 gpu_releaseTimeSlice_flag = 0;
992 while (cycles > 0 && GPU_RUNNING)
994 /*if (gpu_pc == 0xF0359A)
999 /* gpu_flag_c = (gpu_flag_c ? 1 : 0);
1000 gpu_flag_z = (gpu_flag_z ? 1 : 0);
1001 gpu_flag_n = (gpu_flag_n ? 1 : 0);*/
1003 uint16 opcode = GPUReadWord(gpu_pc, GPU);
1004 uint32 index = opcode >> 10;
1005 gpu_instruction = opcode; // Added for GPU #3...
1006 gpu_opcode_first_parameter = (opcode >> 5) & 0x1F;
1007 gpu_opcode_second_parameter = opcode & 0x1F;
1008 /*if (gpu_pc == 0xF03BE8)
1009 WriteLog("Start of OP frame write...\n");
1010 if (gpu_pc == 0xF03EEE)
1011 WriteLog("--> Writing BRANCH object ---\n");
1012 if (gpu_pc == 0xF03F62)
1013 WriteLog("--> Writing BITMAP object ***\n");//*/
1014 /*if (gpu_pc == 0xF03546)
1016 WriteLog("\n--> GPU PC: F03546\n");
1018 GPUDumpDisassembly();
1020 /*if (gpu_pc == 0xF033F6)
1022 WriteLog("\n--> GPU PC: F033F6\n");
1024 GPUDumpDisassembly();
1026 /*if (gpu_pc == 0xF033CC)
1028 WriteLog("\n--> GPU PC: F033CC\n");
1030 GPUDumpDisassembly();
1032 /*if (gpu_pc == 0xF033D6)
1034 WriteLog("\n--> GPU PC: F033D6 (#%d)\n", testCount++);
1038 /*if (gpu_pc == 0xF033D8)
1040 WriteLog("\n--> GPU PC: F033D8 (#%d)\n", testCount++);
1044 /*if (gpu_pc == 0xF0358E)
1046 WriteLog("\n--> GPU PC: F0358E (#%d)\n", testCount++);
1050 /*if (gpu_pc == 0xF034CA)
1052 WriteLog("\n--> GPU PC: F034CA (#%d)\n", testCount++);
1055 /*if (gpu_pc == 0xF034CA)
1057 len = gpu_reg[1] + 4;//, r9save = gpu_reg[9];
1058 WriteLog("\nAbout to subtract [#%d] (R14=%08X, R15=%08X, R9=%08X):\n ", testCount++, gpu_reg[14], gpu_reg[15], gpu_reg[9]);
1059 for(int i=0; i<len; i+=4)
1060 WriteLog(" %08X", GPUReadLong(gpu_reg[15]+i));
1062 for(int i=0; i<len; i+=4)
1063 WriteLog(" %08X", GPUReadLong(gpu_reg[14]+i));
1066 if (gpu_pc == 0xF034DE)
1068 WriteLog("\nSubtracted! (R14=%08X, R15=%08X):\n ", gpu_reg[14], gpu_reg[15]);
1069 for(int i=0; i<len; i+=4)
1070 WriteLog(" %08X", GPUReadLong(gpu_reg[15]+i));
1072 for(int i=0; i<len; i+=4)
1073 WriteLog(" %08X", GPUReadLong(gpu_reg[14]+i));
1075 for(int i=0; i<len; i+=4)
1076 WriteLog(" --------");
1078 for(int i=0; i<len; i+=4)
1079 WriteLog(" %08X", GPUReadLong(gpu_reg[9]+4+i));
1082 /*if (gpu_pc == 0xF035C8)
1084 WriteLog("\n--> GPU PC: F035C8 (#%d)\n", testCount++);
1086 GPUDumpDisassembly();
1091 // gpu_reset_stats();
1092 static char buffer[512];
1093 dasmjag(JAGUAR_GPU, buffer, gpu_pc);
1094 WriteLog("GPU: [%08X] %s (RM=%08X, RN=%08X) -> ", gpu_pc, buffer, RM, RN);
1096 //$E400 -> 1110 01 -> $39 -> 57
1099 gpu_opcode[index]();
1101 // gpu2_opcode[index]();
1103 //GPU #3 (Doesn't show ATARI logo! #1 & #2 do...)
1105 // gpu3_opcode[index]();
1108 //GPU: [00F03548] jr nz,00F03560 (0xd561) (RM=00F03114, RN=00000004) -> --> JR: Branch taken.
1109 /*static bool firstTime = true;
1110 if (gpu_pc == 0xF03548 && firstTime)
1113 // firstTime = false;
1115 //static char buffer[512];
1117 //while (k<0xF0356C)
1120 //k += dasmjag(JAGUAR_GPU, buffer, k);
1121 //WriteLog("GPU: [%08X] %s\n", oldk, buffer);
1123 // gpu_start_log = 1;
1125 //GPU: [00F0354C] jump nz,(r29) (0xd3a1) (RM=00F03314, RN=00000004) -> (RM=00F03314, RN=00000004)
1126 /*if (gpu_pc == 0xF0354C)
1127 gpu_flag_z = 0;//, gpu_start_log = 1;//*/
1129 cycles -= gpu_opcode_cycles[index];
1130 gpu_opcode_use[index]++;
1132 WriteLog("(RM=%08X, RN=%08X)\n", RM, RN);//*/
1133 if ((gpu_pc < 0xF03000 || gpu_pc > 0xF03FFF) && !tripwire)
1135 WriteLog("GPU: Executing outside local RAM!\n");
1148 GPU opcodes use (offset punch--vertically below bad guy):
1170 load_r14_indexed 1183
1171 load_r15_indexed 1125
1174 store_r14_indexed 320
1182 static void gpu_opcode_jump(void)
1185 char * condition[32] =
1186 { "T", "nz", "z", "???", "nc", "nc nz", "nc z", "???", "c", "c nz",
1187 "c z", "???", "???", "???", "???", "???", "???", "???", "???",
1188 "???", "nn", "nn nz", "nn z", "???", "n", "n nz", "n z", "???",
1189 "???", "???", "???", "F" };
1191 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);
1194 /* gpu_flag_c = (gpu_flag_c ? 1 : 0);
1195 gpu_flag_z = (gpu_flag_z ? 1 : 0);
1196 gpu_flag_n = (gpu_flag_n ? 1 : 0);*/
1197 // KLUDGE: Used by BRANCH_CONDITION
1198 uint32 jaguar_flags = (gpu_flag_n << 2) | (gpu_flag_c << 1) | gpu_flag_z;
1200 if (BRANCH_CONDITION(IMM_2))
1204 WriteLog("Branched!\n");
1207 WriteLog(" --> JUMP: Branch taken.\n");
1208 uint32 delayed_pc = RM;
1210 gpu_pc = delayed_pc;
1211 /* uint16 opcode = GPUReadWord(gpu_pc, GPU);
1212 gpu_opcode_first_parameter = (opcode >> 5) & 0x1F;
1213 gpu_opcode_second_parameter = opcode & 0x1F;
1215 gpu_pc = delayed_pc;
1216 gpu_opcode[opcode>>10]();//*/
1221 WriteLog("Branch NOT taken.\n");
1225 static void gpu_opcode_jr(void)
1228 char * condition[32] =
1229 { "T", "nz", "z", "???", "nc", "nc nz", "nc z", "???", "c", "c nz",
1230 "c z", "???", "???", "???", "???", "???", "???", "???", "???",
1231 "???", "nn", "nn nz", "nn z", "???", "n", "n nz", "n z", "???",
1232 "???", "???", "???", "F" };
1234 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);
1236 /* if (CONDITION(jaguar.op & 31))
1238 INT32 r1 = (INT8)((jaguar.op >> 2) & 0xF8) >> 2;
1239 UINT32 newpc = jaguar.PC + r1;
1241 jaguar.op = ROPCODE(jaguar.PC);
1243 (*jaguar.table[jaguar.op >> 10])();
1245 jaguar_icount -= 3; // 3 wait states guaranteed
1248 /* gpu_flag_n = (gpu_flag_n ? 1 : 0);
1249 gpu_flag_c = (gpu_flag_c ? 1 : 0);
1250 gpu_flag_z = (gpu_flag_z ? 1 : 0);*/
1251 // KLUDGE: Used by BRANCH_CONDITION
1252 uint32 jaguar_flags = (gpu_flag_n << 2) | (gpu_flag_c << 1) | gpu_flag_z;
1254 if (BRANCH_CONDITION(IMM_2))
1258 WriteLog("Branched!\n");
1261 WriteLog(" --> JR: Branch taken.\n");
1262 int32 offset = (IMM_1 & 0x10 ? 0xFFFFFFF0 | IMM_1 : IMM_1); // Sign extend IMM_1
1263 int32 delayed_pc = gpu_pc + (offset * 2);
1265 gpu_pc = delayed_pc;
1266 /* uint16 opcode = GPUReadWord(gpu_pc, GPU);
1267 gpu_opcode_first_parameter = (opcode >> 5) & 0x1F;
1268 gpu_opcode_second_parameter = opcode & 0x1F;
1270 gpu_pc = delayed_pc;
1271 gpu_opcode[opcode>>10]();//*/
1276 WriteLog("Branch NOT taken.\n");
1280 static void gpu_opcode_add(void)
1284 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);
1286 UINT32 res = RN + RM;
1287 CLR_ZNC; SET_ZNC_ADD(RN, RM, res);
1291 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);
1295 static void gpu_opcode_addc(void)
1299 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);
1301 /* int dreg = jaguar.op & 31;
1302 UINT32 r1 = jaguar.r[(jaguar.op >> 5) & 31];
1303 UINT32 r2 = jaguar.r[dreg];
1304 UINT32 res = r2 + r1 + ((jaguar.FLAGS >> 1) & 1);
1305 jaguar.r[dreg] = res;
1306 CLR_ZNC; SET_ZNC_ADD(r2,r1,res);*/
1308 UINT32 res = RN + RM + gpu_flag_c;
1309 UINT32 carry = gpu_flag_c;
1310 // SET_ZNC_ADD(RN, RM, res); //???BUG??? Yes!
1311 SET_ZNC_ADD(RN + carry, RM, res);
1312 // SET_ZNC_ADD(RN, RM + carry, res);
1316 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);
1320 static void gpu_opcode_addq(void)
1324 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);
1326 UINT32 r1 = gpu_convert_zero[IMM_1];
1327 UINT32 res = RN + r1;
1328 CLR_ZNC; SET_ZNC_ADD(RN, r1, res);
1332 WriteLog("[NCZ:%u%u%u, R%02u=%08X]\n", gpu_flag_n, gpu_flag_c, gpu_flag_z, IMM_2, RN);
1336 static void gpu_opcode_addqt(void)
1338 #ifdef GPU_DIS_ADDQT
1340 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);
1342 RN += gpu_convert_zero[IMM_1];
1343 #ifdef GPU_DIS_ADDQT
1345 WriteLog("[NCZ:%u%u%u, R%02u=%08X]\n", gpu_flag_n, gpu_flag_c, gpu_flag_z, IMM_2, RN);
1349 static void gpu_opcode_sub(void)
1353 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);
1355 UINT32 res = RN - RM;
1356 SET_ZNC_SUB(RN, RM, res);
1360 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);
1364 static void gpu_opcode_subc(void)
1368 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);
1370 UINT32 res = RN - RM - gpu_flag_c;
1371 UINT32 borrow = gpu_flag_c;
1372 // SET_ZNC_SUB(RN, RM, res); //???BUG??? YES!!!
1373 SET_ZNC_SUB(RN - borrow, RM, res);
1377 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);
1381 static void gpu_opcode_subq(void)
1385 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);
1387 UINT32 r1 = gpu_convert_zero[IMM_1];
1388 UINT32 res = RN - r1;
1389 SET_ZNC_SUB(RN, r1, res);
1393 WriteLog("[NCZ:%u%u%u, R%02u=%08X]\n", gpu_flag_n, gpu_flag_c, gpu_flag_z, IMM_2, RN);
1397 static void gpu_opcode_subqt(void)
1399 #ifdef GPU_DIS_SUBQT
1401 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);
1403 RN -= gpu_convert_zero[IMM_1];
1404 #ifdef GPU_DIS_SUBQT
1406 WriteLog("[NCZ:%u%u%u, R%02u=%08X]\n", gpu_flag_n, gpu_flag_c, gpu_flag_z, IMM_2, RN);
1410 static void gpu_opcode_cmp(void)
1414 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);
1416 UINT32 res = RN - RM;
1417 SET_ZNC_SUB(RN, RM, res);
1420 WriteLog("[NCZ:%u%u%u]\n", gpu_flag_n, gpu_flag_c, gpu_flag_z);
1424 static void gpu_opcode_cmpq(void)
1426 static int32 sqtable[32] =
1427 { 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 };
1430 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);
1432 UINT32 r1 = sqtable[IMM_1 & 0x1F]; // I like this better -> (INT8)(jaguar.op >> 2) >> 3;
1433 UINT32 res = RN - r1;
1434 SET_ZNC_SUB(RN, r1, res);
1437 WriteLog("[NCZ:%u%u%u]\n", gpu_flag_n, gpu_flag_c, gpu_flag_z);
1441 static void gpu_opcode_and(void)
1445 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);
1451 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);
1455 static void gpu_opcode_or(void)
1459 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);
1465 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);
1469 static void gpu_opcode_xor(void)
1473 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);
1479 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);
1483 static void gpu_opcode_not(void)
1487 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);
1493 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);
1497 static void gpu_opcode_move_pc(void)
1499 #ifdef GPU_DIS_MOVEPC
1501 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);
1503 // Should be previous PC--this might not always be previous instruction!
1504 // Then again, this will point right at the *current* instruction, i.e., MOVE PC,R!
1506 #ifdef GPU_DIS_MOVEPC
1508 WriteLog("[NCZ:%u%u%u, R%02u=%08X]\n", gpu_flag_n, gpu_flag_c, gpu_flag_z, IMM_2, RN);
1512 static void gpu_opcode_sat8(void)
1516 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);
1518 RN = ((int32)RN < 0 ? 0 : (RN > 0xFF ? 0xFF : RN));
1522 WriteLog("[NCZ:%u%u%u, R%02u=%08X]\n", gpu_flag_n, gpu_flag_c, gpu_flag_z, IMM_2, RN);
1526 static void gpu_opcode_sat16(void)
1528 RN = ((int32)RN < 0 ? 0 : (RN > 0xFFFF ? 0xFFFF : RN));
1532 static void gpu_opcode_sat24(void)
1534 RN = ((int32)RN < 0 ? 0 : (RN > 0xFFFFFF ? 0xFFFFFF : RN));
1538 static void gpu_opcode_store_r14_indexed(void)
1540 #ifdef GPU_DIS_STORE14I
1542 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));
1544 GPUWriteLong(gpu_reg[14] + (gpu_convert_zero[IMM_1] << 2), RN, GPU);
1547 static void gpu_opcode_store_r15_indexed(void)
1549 #ifdef GPU_DIS_STORE15I
1551 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));
1553 GPUWriteLong(gpu_reg[15] + (gpu_convert_zero[IMM_1] << 2), RN, GPU);
1556 static void gpu_opcode_load_r14_ri(void)
1558 #ifdef GPU_DIS_LOAD14R
1560 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);
1562 RN = GPUReadLong(gpu_reg[14] + RM, GPU);
1563 #ifdef GPU_DIS_LOAD14R
1565 WriteLog("[NCZ:%u%u%u, R%02u=%08X]\n", gpu_flag_n, gpu_flag_c, gpu_flag_z, IMM_2, RN);
1569 static void gpu_opcode_load_r15_ri(void)
1571 #ifdef GPU_DIS_LOAD15R
1573 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);
1575 RN = GPUReadLong(gpu_reg[15] + RM, GPU);
1576 #ifdef GPU_DIS_LOAD15R
1578 WriteLog("[NCZ:%u%u%u, R%02u=%08X]\n", gpu_flag_n, gpu_flag_c, gpu_flag_z, IMM_2, RN);
1582 static void gpu_opcode_store_r14_ri(void)
1584 #ifdef GPU_DIS_STORE14R
1586 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]);
1588 GPUWriteLong(gpu_reg[14] + RM, RN, GPU);
1591 static void gpu_opcode_store_r15_ri(void)
1593 #ifdef GPU_DIS_STORE15R
1595 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]);
1597 GPUWriteLong(gpu_reg[15] + RM, RN, GPU);
1600 static void gpu_opcode_nop(void)
1604 WriteLog("%06X: NOP [NCZ:%u%u%u]\n", gpu_pc-2, gpu_flag_n, gpu_flag_c, gpu_flag_z);
1608 static void gpu_opcode_pack(void)
1612 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);
1616 //BUG! if (RM == 0) // Pack
1617 if (IMM_1 == 0) // Pack
1618 RN = ((val >> 10) & 0x0000F000) | ((val >> 5) & 0x00000F00) | (val & 0x000000FF);
1620 RN = ((val & 0x0000F000) << 10) | ((val & 0x00000F00) << 5) | (val & 0x000000FF);
1623 WriteLog("[NCZ:%u%u%u, R%02u=%08X]\n", gpu_flag_n, gpu_flag_c, gpu_flag_z, IMM_2, RN);
1627 static void gpu_opcode_storeb(void)
1629 #ifdef GPU_DIS_STOREB
1631 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);
1634 // Would appear to be so...!
1635 if ((RM >= 0xF03000) && (RM <= 0xF03FFF))
1636 GPUWriteLong(RM, RN & 0xFF, GPU);
1638 JaguarWriteByte(RM, RN, GPU);
1641 static void gpu_opcode_storew(void)
1643 #ifdef GPU_DIS_STOREW
1645 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);
1647 if ((RM >= 0xF03000) && (RM <= 0xF03FFF))
1648 GPUWriteLong(RM, RN & 0xFFFF, GPU);
1650 JaguarWriteWord(RM, RN, GPU);
1653 static void gpu_opcode_store(void)
1655 #ifdef GPU_DIS_STORE
1657 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);
1659 GPUWriteLong(RM, RN, GPU);
1662 static void gpu_opcode_storep(void)
1664 GPUWriteLong(RM + 0, gpu_hidata, GPU);
1665 GPUWriteLong(RM + 4, RN, GPU);
1668 static void gpu_opcode_loadb(void)
1670 #ifdef GPU_DIS_LOADB
1672 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);
1674 if ((RM >= 0xF03000) && (RM <= 0xF03FFF))
1675 RN = GPUReadLong(RM, GPU) & 0xFF;
1677 RN = JaguarReadByte(RM, GPU);
1678 #ifdef GPU_DIS_LOADB
1680 WriteLog("[NCZ:%u%u%u, R%02u=%08X]\n", gpu_flag_n, gpu_flag_c, gpu_flag_z, IMM_2, RN);
1684 static void gpu_opcode_loadw(void)
1686 #ifdef GPU_DIS_LOADW
1688 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);
1690 if ((RM >= 0xF03000) && (RM <= 0xF03FFF))
1691 RN = GPUReadLong(RM, GPU) & 0xFFFF;
1693 RN = JaguarReadWord(RM, GPU);
1694 #ifdef GPU_DIS_LOADW
1696 WriteLog("[NCZ:%u%u%u, R%02u=%08X]\n", gpu_flag_n, gpu_flag_c, gpu_flag_z, IMM_2, RN);
1700 static void gpu_opcode_load(void)
1704 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);
1706 RN = GPUReadLong(RM, GPU);
1709 WriteLog("[NCZ:%u%u%u, R%02u=%08X]\n", gpu_flag_n, gpu_flag_c, gpu_flag_z, IMM_2, RN);
1713 static void gpu_opcode_loadp(void)
1715 gpu_hidata = GPUReadLong(RM + 0, GPU);
1716 RN = GPUReadLong(RM + 4, GPU);
1719 static void gpu_opcode_load_r14_indexed(void)
1721 #ifdef GPU_DIS_LOAD14I
1723 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);
1725 RN = GPUReadLong(gpu_reg[14] + (gpu_convert_zero[IMM_1] << 2), GPU);
1726 #ifdef GPU_DIS_LOAD14I
1728 WriteLog("[NCZ:%u%u%u, R%02u=%08X]\n", gpu_flag_n, gpu_flag_c, gpu_flag_z, IMM_2, RN);
1732 static void gpu_opcode_load_r15_indexed(void)
1734 #ifdef GPU_DIS_LOAD15I
1736 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);
1738 RN = GPUReadLong(gpu_reg[15] + (gpu_convert_zero[IMM_1] << 2), GPU);
1739 #ifdef GPU_DIS_LOAD15I
1741 WriteLog("[NCZ:%u%u%u, R%02u=%08X]\n", gpu_flag_n, gpu_flag_c, gpu_flag_z, IMM_2, RN);
1745 static void gpu_opcode_movei(void)
1747 #ifdef GPU_DIS_MOVEI
1749 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);
1751 // This instruction is followed by 32-bit value in LSW / MSW format...
1752 RN = (uint32)GPUReadWord(gpu_pc, GPU) | ((uint32)GPUReadWord(gpu_pc + 2, GPU) << 16);
1754 #ifdef GPU_DIS_MOVEI
1756 WriteLog("[NCZ:%u%u%u, R%02u=%08X]\n", gpu_flag_n, gpu_flag_c, gpu_flag_z, IMM_2, RN);
1760 static void gpu_opcode_moveta(void)
1762 #ifdef GPU_DIS_MOVETA
1764 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);
1767 #ifdef GPU_DIS_MOVETA
1769 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);
1773 static void gpu_opcode_movefa(void)
1775 #ifdef GPU_DIS_MOVEFA
1777 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);
1780 #ifdef GPU_DIS_MOVEFA
1782 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);
1786 static void gpu_opcode_move(void)
1790 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);
1795 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);
1799 static void gpu_opcode_moveq(void)
1801 #ifdef GPU_DIS_MOVEQ
1803 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);
1806 #ifdef GPU_DIS_MOVEQ
1808 WriteLog("[NCZ:%u%u%u, R%02u=%08X]\n", gpu_flag_n, gpu_flag_c, gpu_flag_z, IMM_2, RN);
1812 static void gpu_opcode_resmac(void)
1817 static void gpu_opcode_imult(void)
1819 #ifdef GPU_DIS_IMULT
1821 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);
1823 RN = (int16)RN * (int16)RM;
1825 #ifdef GPU_DIS_IMULT
1827 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);
1831 static void gpu_opcode_mult(void)
1835 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);
1837 RN = (uint16)RM * (uint16)RN;
1841 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);
1845 static void gpu_opcode_bclr(void)
1849 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);
1851 UINT32 res = RN & ~(1 << IMM_1);
1856 WriteLog("[NCZ:%u%u%u, R%02u=%08X]\n", gpu_flag_n, gpu_flag_c, gpu_flag_z, IMM_2, RN);
1860 static void gpu_opcode_btst(void)
1864 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);
1866 gpu_flag_z = (~RN >> IMM_1) & 1;
1869 WriteLog("[NCZ:%u%u%u, R%02u=%08X]\n", gpu_flag_n, gpu_flag_c, gpu_flag_z, IMM_2, RN);
1873 static void gpu_opcode_bset(void)
1877 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);
1879 UINT32 res = RN | (1 << IMM_1);
1884 WriteLog("[NCZ:%u%u%u, R%02u=%08X]\n", gpu_flag_n, gpu_flag_c, gpu_flag_z, IMM_2, RN);
1888 static void gpu_opcode_imacn(void)
1890 uint32 res = (int16)RM * (int16)(RN);
1894 static void gpu_opcode_mtoi(void)
1897 uint32 res = RN = (((INT32)_RM >> 8) & 0xFF800000) | (_RM & 0x007FFFFF);
1901 static void gpu_opcode_normi(void)
1908 while ((_RM & 0xFFC00000) == 0)
1913 while ((_RM & 0xFF800000) != 0)
1923 static void gpu_opcode_mmult(void)
1925 int count = gpu_matrix_control & 0x0F; // Matrix width
1926 uint32 addr = gpu_pointer_to_matrix; // In the GPU's RAM
1930 if (gpu_matrix_control & 0x10) // Column stepping
1932 for(int i=0; i<count; i++)
1936 a = (int16)((gpu_alternate_reg[IMM_1 + (i >> 1)] >> 16) & 0xFFFF);
1938 a = (int16)(gpu_alternate_reg[IMM_1 + (i >> 1)] & 0xFFFF);
1940 int16 b = ((int16)GPUReadWord(addr + 2, GPU));
1945 else // Row stepping
1947 for(int i=0; i<count; i++)
1951 a = (int16)((gpu_alternate_reg[IMM_1 + (i >> 1)] >> 16) & 0xFFFF);
1953 a = (int16)(gpu_alternate_reg[IMM_1 + (i >> 1)] & 0xFFFF);
1955 int16 b = ((int16)GPUReadWord(addr + 2, GPU));
1960 RN = res = (int32)accum;
1961 // carry flag to do (out of the last add)
1965 static void gpu_opcode_abs(void)
1969 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);
1971 gpu_flag_c = RN >> 31;
1972 if (RN == 0x80000000)
1973 //Is 0x80000000 a positive number? If so, then we need to set C to 0 as well!
1974 gpu_flag_n = 1, gpu_flag_z = 0;
1979 gpu_flag_n = 0; SET_FLAG_Z(RN);
1983 WriteLog("[NCZ:%u%u%u, R%02u=%08X]\n", gpu_flag_n, gpu_flag_c, gpu_flag_z, IMM_2, RN);
1987 static void gpu_opcode_div(void) // RN / RM
1991 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);
1993 // NOTE: remainder is NOT calculated correctly here!
1994 // The original tried to get it right by checking to see if the
1995 // remainder was negative, but that's too late...
1996 // The code there should do it now, but I'm not 100% sure...
2000 if (gpu_div_control & 0x01) // 16.16 division
2002 RN = ((UINT64)RN << 16) / RM;
2003 gpu_remain = ((UINT64)RN << 16) % RM;
2008 gpu_remain = RN % RM;
2011 if ((gpu_remain - RM) & 0x80000000) // If the result would have been negative...
2012 gpu_remain -= RM; // Then make it negative!
2022 if (gpu_div_control & 1)
2024 gpu_remain = (((uint64)_RN) << 16) % _RM;
2025 if (gpu_remain&0x80000000)
2027 RN = (((uint64)_RN) << 16) / _RM;
2031 gpu_remain = _RN % _RM;
2032 if (gpu_remain&0x80000000)
2041 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);
2045 static void gpu_opcode_imultn(void)
2047 uint32 res = (int32)((int16)RN * (int16)RM);
2048 gpu_acc = (int32)res;
2053 static void gpu_opcode_neg(void)
2057 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);
2060 SET_ZNC_SUB(0, RN, res);
2064 WriteLog("[NCZ:%u%u%u, R%02u=%08X]\n", gpu_flag_n, gpu_flag_c, gpu_flag_z, IMM_2, RN);
2068 static void gpu_opcode_shlq(void)
2072 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);
2074 // Was a bug here...
2075 // (Look at Aaron's code: If r1 = 32, then 32 - 32 = 0 which is wrong!)
2076 INT32 r1 = 32 - IMM_1;
2077 UINT32 res = RN << r1;
2078 SET_ZN(res); gpu_flag_c = (RN >> 31) & 1;
2082 WriteLog("[NCZ:%u%u%u, R%02u=%08X]\n", gpu_flag_n, gpu_flag_c, gpu_flag_z, IMM_2, RN);
2086 static void gpu_opcode_shrq(void)
2090 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);
2092 INT32 r1 = gpu_convert_zero[IMM_1];
2093 UINT32 res = RN >> r1;
2094 SET_ZN(res); gpu_flag_c = RN & 1;
2098 WriteLog("[NCZ:%u%u%u, R%02u=%08X]\n", gpu_flag_n, gpu_flag_c, gpu_flag_z, IMM_2, RN);
2102 static void gpu_opcode_ror(void)
2106 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);
2108 UINT32 r1 = RM & 0x1F;
2109 UINT32 res = (RN >> r1) | (RN << (32 - r1));
2110 SET_ZN(res); gpu_flag_c = (RN >> 31) & 1;
2114 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);
2118 static void gpu_opcode_rorq(void)
2122 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);
2124 UINT32 r1 = gpu_convert_zero[IMM_1 & 0x1F];
2126 UINT32 res = (r2 >> r1) | (r2 << (32 - r1));
2128 SET_ZN(res); gpu_flag_c = (r2 >> 31) & 0x01;
2131 WriteLog("[NCZ:%u%u%u, R%02u=%08X]\n", gpu_flag_n, gpu_flag_c, gpu_flag_z, IMM_2, RN);
2135 static void gpu_opcode_sha(void)
2137 /* int dreg = jaguar.op & 31;
2138 INT32 r1 = (INT32)jaguar.r[(jaguar.op >> 5) & 31];
2139 UINT32 r2 = jaguar.r[dreg];
2145 res = (r1 <= -32) ? 0 : (r2 << -r1);
2146 jaguar.FLAGS |= (r2 >> 30) & 2;
2150 res = (r1 >= 32) ? ((INT32)r2 >> 31) : ((INT32)r2 >> r1);
2151 jaguar.FLAGS |= (r2 << 1) & 2;
2153 jaguar.r[dreg] = res;
2158 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);
2164 res = ((INT32)RM <= -32) ? 0 : (RN << -(INT32)RM);
2165 gpu_flag_c = RN >> 31;
2169 res = ((INT32)RM >= 32) ? ((INT32)RN >> 31) : ((INT32)RN >> (INT32)RM);
2170 gpu_flag_c = RN & 0x01;
2176 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);
2179 /* int32 sRM=(int32)RM;
2185 if (shift>=32) shift=32;
2186 gpu_flag_c=(_RN&0x80000000)>>31;
2196 if (shift>=32) shift=32;
2200 _RN=((int32)_RN)>>1;
2209 static void gpu_opcode_sharq(void)
2211 #ifdef GPU_DIS_SHARQ
2213 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);
2215 UINT32 res = (INT32)RN >> gpu_convert_zero[IMM_1];
2216 SET_ZN(res); gpu_flag_c = RN & 0x01;
2218 #ifdef GPU_DIS_SHARQ
2220 WriteLog("[NCZ:%u%u%u, R%02u=%08X]\n", gpu_flag_n, gpu_flag_c, gpu_flag_z, IMM_2, RN);
2224 static void gpu_opcode_sh(void)
2228 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);
2230 if (RM & 0x80000000) // Shift left
2232 gpu_flag_c = RN >> 31;
2233 RN = ((int32)RM <= -32 ? 0 : RN << -(int32)RM);
2237 gpu_flag_c = RN & 0x01;
2238 RN = (RM >= 32 ? 0 : RN >> RM);
2243 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);
2247 //Temporary: Testing only!
2248 //#include "gpu2.cpp"
2249 //#include "gpu3.cpp"