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
77 GPU opcodes use (BIOS flying ATARI logo):
119 #define CINT0FLAG 0x0200
120 #define CINT1FLAG 0x0400
121 #define CINT2FLAG 0x0800
122 #define CINT3FLAG 0x1000
123 #define CINT4FLAG 0x2000
124 #define CINT04FLAGS (CINT0FLAG | CINT1FLAG | CINT2FLAG | CINT3FLAG | CINT4FLAG)
128 #define ZERO_FLAG 0x0001
129 #define CARRY_FLAG 0x0002
130 #define NEGA_FLAG 0x0004
132 #define INT_ENA0 0x0010
133 #define INT_ENA1 0x0020
134 #define INT_ENA2 0x0040
135 #define INT_ENA3 0x0080
136 #define INT_ENA4 0x0100
137 #define INT_CLR0 0x0200
138 #define INT_CLR1 0x0400
139 #define INT_CLR2 0x0800
140 #define INT_CLR3 0x1000
141 #define INT_CLR4 0x2000
142 #define REGPAGE 0x4000
145 // Private function prototypes
147 void GPUUpdateRegisterBanks(void);
149 void gpu_dump_disassembly(void);
150 void gpu_dump_registers(void);
151 void gpu_dump_memory(void);
153 extern int start_logging;
154 extern int gpu_start_log;
156 static void gpu_opcode_add(void);
157 static void gpu_opcode_addc(void);
158 static void gpu_opcode_addq(void);
159 static void gpu_opcode_addqt(void);
160 static void gpu_opcode_sub(void);
161 static void gpu_opcode_subc(void);
162 static void gpu_opcode_subq(void);
163 static void gpu_opcode_subqt(void);
164 static void gpu_opcode_neg(void);
165 static void gpu_opcode_and(void);
166 static void gpu_opcode_or(void);
167 static void gpu_opcode_xor(void);
168 static void gpu_opcode_not(void);
169 static void gpu_opcode_btst(void);
170 static void gpu_opcode_bset(void);
171 static void gpu_opcode_bclr(void);
172 static void gpu_opcode_mult(void);
173 static void gpu_opcode_imult(void);
174 static void gpu_opcode_imultn(void);
175 static void gpu_opcode_resmac(void);
176 static void gpu_opcode_imacn(void);
177 static void gpu_opcode_div(void);
178 static void gpu_opcode_abs(void);
179 static void gpu_opcode_sh(void);
180 static void gpu_opcode_shlq(void);
181 static void gpu_opcode_shrq(void);
182 static void gpu_opcode_sha(void);
183 static void gpu_opcode_sharq(void);
184 static void gpu_opcode_ror(void);
185 static void gpu_opcode_rorq(void);
186 static void gpu_opcode_cmp(void);
187 static void gpu_opcode_cmpq(void);
188 static void gpu_opcode_sat8(void);
189 static void gpu_opcode_sat16(void);
190 static void gpu_opcode_move(void);
191 static void gpu_opcode_moveq(void);
192 static void gpu_opcode_moveta(void);
193 static void gpu_opcode_movefa(void);
194 static void gpu_opcode_movei(void);
195 static void gpu_opcode_loadb(void);
196 static void gpu_opcode_loadw(void);
197 static void gpu_opcode_load(void);
198 static void gpu_opcode_loadp(void);
199 static void gpu_opcode_load_r14_indexed(void);
200 static void gpu_opcode_load_r15_indexed(void);
201 static void gpu_opcode_storeb(void);
202 static void gpu_opcode_storew(void);
203 static void gpu_opcode_store(void);
204 static void gpu_opcode_storep(void);
205 static void gpu_opcode_store_r14_indexed(void);
206 static void gpu_opcode_store_r15_indexed(void);
207 static void gpu_opcode_move_pc(void);
208 static void gpu_opcode_jump(void);
209 static void gpu_opcode_jr(void);
210 static void gpu_opcode_mmult(void);
211 static void gpu_opcode_mtoi(void);
212 static void gpu_opcode_normi(void);
213 static void gpu_opcode_nop(void);
214 static void gpu_opcode_load_r14_ri(void);
215 static void gpu_opcode_load_r15_ri(void);
216 static void gpu_opcode_store_r14_ri(void);
217 static void gpu_opcode_store_r15_ri(void);
218 static void gpu_opcode_sat24(void);
219 static void gpu_opcode_pack(void);
221 uint8 gpu_opcode_cycles[64] =
223 3, 3, 3, 3, 3, 3, 3, 3,
224 3, 3, 3, 3, 3, 3, 3, 3,
225 3, 3, 1, 3, 1, 18, 3, 3,
226 3, 3, 3, 3, 3, 3, 3, 3,
227 3, 3, 2, 2, 2, 2, 3, 4,
228 5, 4, 5, 6, 6, 1, 1, 1,
229 1, 2, 2, 2, 1, 1, 9, 3,
230 3, 1, 6, 6, 2, 2, 3, 3
233 void (*gpu_opcode[64])()=
235 gpu_opcode_add, gpu_opcode_addc, gpu_opcode_addq, gpu_opcode_addqt,
236 gpu_opcode_sub, gpu_opcode_subc, gpu_opcode_subq, gpu_opcode_subqt,
237 gpu_opcode_neg, gpu_opcode_and, gpu_opcode_or, gpu_opcode_xor,
238 gpu_opcode_not, gpu_opcode_btst, gpu_opcode_bset, gpu_opcode_bclr,
239 gpu_opcode_mult, gpu_opcode_imult, gpu_opcode_imultn, gpu_opcode_resmac,
240 gpu_opcode_imacn, gpu_opcode_div, gpu_opcode_abs, gpu_opcode_sh,
241 gpu_opcode_shlq, gpu_opcode_shrq, gpu_opcode_sha, gpu_opcode_sharq,
242 gpu_opcode_ror, gpu_opcode_rorq, gpu_opcode_cmp, gpu_opcode_cmpq,
243 gpu_opcode_sat8, gpu_opcode_sat16, gpu_opcode_move, gpu_opcode_moveq,
244 gpu_opcode_moveta, gpu_opcode_movefa, gpu_opcode_movei, gpu_opcode_loadb,
245 gpu_opcode_loadw, gpu_opcode_load, gpu_opcode_loadp, gpu_opcode_load_r14_indexed,
246 gpu_opcode_load_r15_indexed, gpu_opcode_storeb, gpu_opcode_storew, gpu_opcode_store,
247 gpu_opcode_storep, gpu_opcode_store_r14_indexed, gpu_opcode_store_r15_indexed, gpu_opcode_move_pc,
248 gpu_opcode_jump, gpu_opcode_jr, gpu_opcode_mmult, gpu_opcode_mtoi,
249 gpu_opcode_normi, gpu_opcode_nop, gpu_opcode_load_r14_ri, gpu_opcode_load_r15_ri,
250 gpu_opcode_store_r14_ri, gpu_opcode_store_r15_ri, gpu_opcode_sat24, gpu_opcode_pack,
253 static uint8 * gpu_ram_8;
254 static uint32 gpu_pc;
255 static uint32 gpu_acc;
256 static uint32 gpu_remain;
257 static uint32 gpu_hidata;
258 static uint32 gpu_flags;
259 static uint32 gpu_matrix_control;
260 static uint32 gpu_pointer_to_matrix;
261 static uint32 gpu_data_organization;
262 static uint32 gpu_control;
263 static uint32 gpu_div_control;
264 // There is a distinct advantage to having these separated out--there's no need to clear
265 // a bit before writing a result. I.e., if the result of an operation leaves a zero in
266 // the carry flag, you don't have to zero gpu_flag_c before you can write that zero!
267 static uint8 gpu_flag_z, gpu_flag_n, gpu_flag_c;
268 static uint32 * gpu_reg_bank_0;
269 static uint32 * gpu_reg_bank_1;
270 static uint32 * gpu_reg;
271 static uint32 * gpu_alternate_reg;
273 static uint32 gpu_instruction;
274 static uint32 gpu_opcode_first_parameter;
275 static uint32 gpu_opcode_second_parameter;
277 #define GPU_RUNNING (gpu_control & 0x01)
279 #define RM gpu_reg[gpu_opcode_first_parameter]
280 #define RN gpu_reg[gpu_opcode_second_parameter]
281 #define ALTERNATE_RM gpu_alternate_reg[gpu_opcode_first_parameter]
282 #define ALTERNATE_RN gpu_alternate_reg[gpu_opcode_second_parameter]
283 #define IMM_1 gpu_opcode_first_parameter
284 #define IMM_2 gpu_opcode_second_parameter
286 #define SET_FLAG_Z(r) (gpu_flag_z = ((r) == 0));
287 #define SET_FLAG_N(r) (gpu_flag_n = (((UINT32)(r) >> 31) & 0x01));
289 #define RESET_FLAG_Z() gpu_flag_z = 0;
290 #define RESET_FLAG_N() gpu_flag_n = 0;
291 #define RESET_FLAG_C() gpu_flag_c = 0;
293 #define CLR_Z (gpu_flag_z = 0)
294 #define CLR_ZN (gpu_flag_z = gpu_flag_n = 0)
295 #define CLR_ZNC (gpu_flag_z = gpu_flag_n = gpu_flag_c = 0)
296 #define SET_Z(r) (gpu_flag_z = ((r) == 0))
297 #define SET_N(r) (gpu_flag_n = (((UINT32)(r) >> 31) & 0x01))
298 #define SET_C_ADD(a,b) (gpu_flag_c = ((UINT32)(b) > (UINT32)(~(a))))
299 #define SET_C_SUB(a,b) (gpu_flag_c = ((UINT32)(b) > (UINT32)(a)))
300 #define SET_ZN(r) SET_N(r); SET_Z(r)
301 #define SET_ZNC_ADD(a,b,r) SET_N(r); SET_Z(r); SET_C_ADD(a,b)
302 #define SET_ZNC_SUB(a,b,r) SET_N(r); SET_Z(r); SET_C_SUB(a,b)
304 uint32 gpu_convert_zero[32] =
305 { 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 };
307 uint8 * branch_condition_table = 0;
308 #define BRANCH_CONDITION(x) branch_condition_table[(x) + ((jaguar_flags & 7) << 5)]
310 uint32 gpu_opcode_use[64];
312 char * gpu_opcode_str[64]=
314 "add", "addc", "addq", "addqt",
315 "sub", "subc", "subq", "subqt",
316 "neg", "and", "or", "xor",
317 "not", "btst", "bset", "bclr",
318 "mult", "imult", "imultn", "resmac",
319 "imacn", "div", "abs", "sh",
320 "shlq", "shrq", "sha", "sharq",
321 "ror", "rorq", "cmp", "cmpq",
322 "sat8", "sat16", "move", "moveq",
323 "moveta", "movefa", "movei", "loadb",
324 "loadw", "load", "loadp", "load_r14_indexed",
325 "load_r15_indexed", "storeb", "storew", "store",
326 "storep", "store_r14_indexed","store_r15_indexed","move_pc",
327 "jump", "jr", "mmult", "mtoi",
328 "normi", "nop", "load_r14_ri", "load_r15_ri",
329 "store_r14_ri", "store_r15_ri", "sat24", "pack",
332 static uint32 gpu_in_exec = 0;
333 static uint32 gpu_releaseTimeSlice_flag = 0;
334 bool GPUInterruptPending = false;
336 void gpu_releaseTimeslice(void)
338 gpu_releaseTimeSlice_flag = 1;
341 uint32 gpu_get_pc(void)
346 /*#define ZFLAG 0x00001
347 #define CFLAG 0x00002
348 #define NFLAG 0x00004*/
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 //unsigned gpu_byte_read(unsigned int offset, uint32 calledBy)
386 unsigned gpu_byte_read(unsigned int offset)
388 if ((offset >= GPU_WORK_RAM_BASE) && (offset < GPU_WORK_RAM_BASE+0x1000))
389 return gpu_ram_8[offset & 0xFFF];
390 else if ((offset >= GPU_CONTROL_RAM_BASE) && (offset < GPU_CONTROL_RAM_BASE+0x20))
392 uint32 data = gpu_long_read(offset & 0xFFFFFFFC);
394 if ((offset & 0x03) == 0)
396 else if ((offset & 0x03) == 1)
397 return (data >> 16) & 0xFF;
398 else if ((offset & 0x03) == 2)
399 return (data >> 8) & 0xFF;
400 else if ((offset & 0x03) == 3)
404 return jaguar_byte_read(offset);
408 // GPU word access (read)
410 unsigned gpu_word_read(unsigned int offset)
412 if ((offset >= GPU_WORK_RAM_BASE) && (offset < GPU_WORK_RAM_BASE+0x1000))
415 uint16 data = ((uint16)gpu_ram_8[offset] << 8) | (uint16)gpu_ram_8[offset+1];
418 else if ((offset >= GPU_CONTROL_RAM_BASE) && (offset < GPU_CONTROL_RAM_BASE+0x20))
420 // This looks and smells wrong...
421 // But it *might* be OK...
422 if (offset & 0x01) // Catch cases 1 & 3... (unaligned read)
423 return (gpu_byte_read(offset) << 8) | gpu_byte_read(offset+1);
425 uint32 data = gpu_long_read(offset & 0xFFFFFFFC);
427 if (offset & 0x02) // Cases 0 & 2...
428 return data & 0xFFFF;
433 //TEMP--Mirror of F03000?
434 if (offset >= 0xF0B000 && offset <= 0xF0BFFF)
435 WriteLog("[GPUR16] --> Possible GPU RAM mirror access!");
437 return jaguar_word_read(offset);
441 // GPU dword access (read)
443 unsigned gpu_long_read(unsigned int offset)
445 // if ((offset >= GPU_WORK_RAM_BASE) && (offset < GPU_WORK_RAM_BASE + 0x1000))
446 if ((offset >= GPU_WORK_RAM_BASE) && (offset <= GPU_WORK_RAM_BASE + 0x0FFC))
449 return ((uint32)gpu_ram_8[offset] << 24) | ((uint32)gpu_ram_8[offset+1] << 16)
450 | ((uint32)gpu_ram_8[offset+2] << 8) | (uint32)gpu_ram_8[offset+3];//*/
451 // return GET32(gpu_ram_8, offset);
453 // else if ((offset >= GPU_CONTROL_RAM_BASE) && (offset < GPU_CONTROL_RAM_BASE+0x20))
454 else if ((offset >= GPU_CONTROL_RAM_BASE) && (offset <= GPU_CONTROL_RAM_BASE + 0x1C))
460 gpu_flag_c = (gpu_flag_c ? 1 : 0);
461 gpu_flag_z = (gpu_flag_z ? 1 : 0);
462 gpu_flag_n = (gpu_flag_n ? 1 : 0);
464 gpu_flags = (gpu_flags & 0xFFFFFFF8) | (gpu_flag_n << 2) | (gpu_flag_c << 1) | gpu_flag_z;
466 return gpu_flags & 0xFFFFC1FF;
468 return gpu_matrix_control;
470 return gpu_pointer_to_matrix;
472 return gpu_data_organization;
481 default: // unaligned long read
483 WriteLog("GPU: Read32--unaligned 32 bit read at %08X.\n", GPU_CONTROL_RAM_BASE + offset);
488 //TEMP--Mirror of F03000?
489 if (offset >= 0xF0B000 && offset <= 0xF0BFFF)
490 WriteLog("[GPUR32] --> Possible GPU RAM mirror access!\n");
491 /*if (offset >= 0xF1D000 && offset <= 0xF1DFFF)
492 WriteLog("[GPUR32] --> Reading from Wavetable ROM!\n");//*/
494 return (jaguar_word_read(offset) << 16) | jaguar_word_read(offset + 2);
498 // GPU byte access (write)
500 void gpu_byte_write(unsigned offset, unsigned data)
502 if ((offset >= GPU_WORK_RAM_BASE) && (offset <= GPU_WORK_RAM_BASE + 0x0FFF))
504 gpu_ram_8[offset & 0xFFF] = data;
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 = gpu_long_read(offset & 0xFFFFFFC);
524 bytenum = 3 - bytenum; // convention motorola !!!
525 old_data = (old_data & (~(0xFF << (bytenum << 3)))) | (data << (bytenum << 3));
526 gpu_long_write(offset & 0xFFFFFFC, old_data);
530 // WriteLog("gpu: writing %.2x at 0x%.8x\n",data,offset);
531 jaguar_byte_write(offset, data);
535 // GPU word access (write)
537 void gpu_word_write(unsigned offset, unsigned data)
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);//*/
548 m68k_end_timeslice();
549 dsp_releaseTimeslice();
553 else if ((offset >= GPU_CONTROL_RAM_BASE) && (offset <= GPU_CONTROL_RAM_BASE + 0x1E))
555 if (offset & 0x01) // This is supposed to weed out unaligned writes, but does nothing...
558 WriteLog("GPU: Write16--unaligned write @ %08X [%04X]\n", offset, data);
559 gpu_dump_registers();
563 //Dual locations in this range: $1C Divide unit remainder/Divide unit control (R/W)
564 //This just literally sucks.
565 if ((offset & 0x1C) == 0x1C)
567 //This doesn't look right either--handles cases 1, 2, & 3 all the same!
569 gpu_div_control = (gpu_div_control & 0xFFFF0000) | (data & 0xFFFF);
571 gpu_div_control = (gpu_div_control & 0x0000FFFF) | ((data & 0xFFFF) << 16);
575 //WriteLog("[GPU W16:%08X,%04X]", offset, data);
576 uint32 old_data = gpu_long_read(offset & 0xFFFFFFC);
578 old_data = (old_data & 0xFFFF0000) | (data & 0xFFFF);
580 old_data = (old_data & 0x0000FFFF) | ((data & 0xFFFF) << 16);
581 gpu_long_write(offset & 0xFFFFFFC, old_data);
585 else if ((offset == GPU_WORK_RAM_BASE + 0x0FFF) || (GPU_CONTROL_RAM_BASE + 0x1F))
588 WriteLog("GPU: Write16--unaligned write @ %08X [%04X]\n", offset, data);
589 gpu_dump_registers();
594 // Have to be careful here--this can cause an infinite loop!
595 jaguar_word_write(offset, data);
599 // GPU dword access (write)
601 void gpu_long_write(unsigned offset, unsigned data)
603 // if ((offset >= GPU_WORK_RAM_BASE) && (offset < GPU_WORK_RAM_BASE + 0x1000))
604 if ((offset >= GPU_WORK_RAM_BASE) && (offset <= GPU_WORK_RAM_BASE + 0x0FFC))
609 WriteLog("GPU: Write32--unaligned write @ %08X [%08X]\n", offset, data);
610 gpu_dump_registers();
614 /* gpu_ram_8[offset & 0xFFF] = (data >> 24) & 0xFF,
615 gpu_ram_8[(offset+1) & 0xFFF] = (data >> 16) & 0xFF,
616 gpu_ram_8[(offset+2) & 0xFFF] = (data >> 8) & 0xFF,
617 gpu_ram_8[(offset+3) & 0xFFF] = data & 0xFF;//*/
619 SET32(gpu_ram_8, offset, data);//*/
622 // else if ((offset >= GPU_CONTROL_RAM_BASE) && (offset < GPU_CONTROL_RAM_BASE+0x20))
623 else if ((offset >= GPU_CONTROL_RAM_BASE) && (offset <= GPU_CONTROL_RAM_BASE + 0x1C))
630 gpu_flag_z = gpu_flags & ZERO_FLAG;
631 gpu_flag_c = (gpu_flags & CARRY_FLAG) >> 1;
632 gpu_flag_n = (gpu_flags & NEGA_FLAG) >> 2;
633 GPUUpdateRegisterBanks();
634 gpu_control &= ~((gpu_flags & CINT04FLAGS) >> 3); // Interrupt latch clear bits
635 //Writing here is only an interrupt enable--this approach is just plain wrong!
637 //This, however, is A-OK! ;-)
638 if (!(gpu_flags & IMASK) && GPUInterruptPending) // IMASK was cleared
640 GPUInterruptPending = false;
644 if (gpu_flags & (INT_ENA0 | INT_ENA1 | INT_ENA2 | INT_ENA3 | INT_ENA4))
645 WriteLog("GPU: Setting interrupt enable! Bits: %02X\n", (gpu_flags >> 4) & 0x1F);
646 WriteLog("GPU: REGPAGE %s...\n", (gpu_flags & REGPAGE ? "set" : "cleared"));
650 gpu_matrix_control = data;
653 // Can only point to long aligned addresses
654 gpu_pointer_to_matrix = data & 0xFFFFFFFC;
657 gpu_data_organization = data;
662 WriteLog("GPU: Setting GPU PC to %08X %s\n", gpu_pc, (GPU_RUNNING ? "(GPU is RUNNING!)" : ""));//*/
667 // uint32 gpu_was_running = GPU_RUNNING;
668 data &= ~0xF7C0; // Disable writes to INT_LAT0-4 & TOM version number
670 // check for GPU -> CPU interrupt
673 //WriteLog("GPU->CPU interrupt\n");
674 if (tom_irq_enabled(IRQ_GPU))
676 if ((tom_irq_enabled(IRQ_GPU)) && (jaguar_interrupt_handler_is_valid(64)))
678 tom_set_pending_gpu_int();
679 m68k_set_irq(7); // Set 68000 NMI
680 gpu_releaseTimeslice();
686 // check for CPU -> GPU interrupt #0
689 //WriteLog("CPU->GPU interrupt\n");
690 GPUSetIRQLine(0, ASSERT_LINE);
691 m68k_end_timeslice();
692 dsp_releaseTimeslice();
699 //WriteLog("asked to perform a single step (single step is %senabled)\n",(data&0x8)?"":"not ");
701 // gpu_control = (gpu_control & 0x107C0) | (data & (~0x107C0));
702 gpu_control = (gpu_control & 0xF7C0) | (data & (~0xF7C0));
704 // if gpu wasn't running but is now running, execute a few cycles
705 #ifndef GPU_SINGLE_STEPPING
706 /* if (!gpu_was_running && GPU_RUNNING)
709 WriteLog("GPU: Write32--About to do stupid braindead GPU execution for 200 cycles.\n");
714 #endif // GPU_DEBUG//*/
716 if (gpu_control & 0x18)
718 #endif // #ifndef GPU_SINGLE_STEPPING
720 WriteLog("Write to GPU CTRL: %08X ", data);
722 WriteLog(" --> Starting to run at %08X...", gpu_pc);
724 WriteLog(" --> Stopped! (GPU_PC: %08X)", gpu_pc);
728 // gpu_dump_disassembly();
729 // (?) If we're set running by the M68K (or DSP?) then end its timeslice to
730 // allow the GPU a chance to run...
731 // Yes! This partially fixed Trevor McFur...
733 m68k_end_timeslice();
740 gpu_div_control = data;
742 // default: // unaligned long write
749 jaguar_word_write(offset, (data >> 16) & 0xFFFF);
750 jaguar_word_write(offset+2, data & 0xFFFF);
754 // Change register banks if necessary
756 void GPUUpdateRegisterBanks(void)
758 int bank = (gpu_flags & 0x4000); // REGPAGE bit
760 if (gpu_flags & 0x0008) // IMASK bit
761 bank = 0; // IMASK forces main bank to be bank 0
764 gpu_reg = gpu_reg_bank_1, gpu_alternate_reg = gpu_reg_bank_0;
766 gpu_reg = gpu_reg_bank_0, gpu_alternate_reg = gpu_reg_bank_1;
769 void GPUHandleIRQs(void)
771 // Get the interrupt latch & enable bits
772 uint32 bits = (gpu_control >> 6) & 0x1F, mask = (gpu_flags >> 4) & 0x1F;
774 // Bail out if latched interrupts aren't enabled
779 // Bail out if we're already in an interrupt! (Note that the order this executes
780 // in is critical--we don't have a pending interrupt unless it's been enabled!)
781 if (gpu_flags & IMASK)
783 GPUInterruptPending = true;
787 // Determine which interrupt to service
788 uint32 which = 0; //Isn't there a #pragma to disable this warning???
801 WriteLog("GPU: Generating IRQ #%i\n", which);
803 // set the interrupt flag
805 GPUUpdateRegisterBanks();
807 // subqt #4,r31 ; pre-decrement stack pointer
808 // move pc,r30 ; address of interrupted code
809 // store r30,(r31) ; store return address
811 gpu_reg[30] = gpu_pc - 2;
812 gpu_long_write(gpu_reg[31], gpu_pc - 2);
814 // movei #service_address,r30 ; pointer to ISR entry
815 // jump (r30) ; jump to ISR
817 gpu_pc = GPU_WORK_RAM_BASE + (which * 0x10);
818 gpu_reg[30] = gpu_pc;
821 void GPUSetIRQLine(int irqline, int state)
824 WriteLog("GPU: Setting GPU IRQ line #%i\n", irqline);
826 uint32 mask = 0x0040 << irqline;
827 gpu_control &= ~mask; // Clear the interrupt latch
831 gpu_control |= mask; // Assert the interrupt latch
832 GPUHandleIRQs(); // And handle the interrupt...
836 //TEMPORARY: Testing only!
842 memory_malloc_secure((void **)&gpu_ram_8, 0x1000, "GPU work RAM");
843 // memory_malloc_secure((void **)&gpu_reg, 32*sizeof(int32), "GPU bank 0 regs");
844 // memory_malloc_secure((void **)&gpu_alternate_reg, 32*sizeof(int32), "GPU bank 1 regs");
845 memory_malloc_secure((void **)&gpu_reg_bank_0, 32 * sizeof(int32), "GPU bank 0 regs");
846 memory_malloc_secure((void **)&gpu_reg_bank_1, 32 * sizeof(int32), "GPU bank 1 regs");
848 build_branch_condition_table();
852 //TEMPORARY: Testing only!
859 // GPU registers (directly visible)
860 gpu_flags = 0x00000000;
861 gpu_matrix_control = 0x00000000;
862 gpu_pointer_to_matrix = 0x00000000;
863 gpu_data_organization = 0xFFFFFFFF;
865 gpu_control = 0x00002800; // Correctly sets this as TOM Rev. 2
866 gpu_hidata = 0x00000000;
867 gpu_remain = 0x00000000; // These two registers are RO/WO
868 gpu_div_control = 0x00000000;
870 // GPU internal register
871 gpu_acc = 0x00000000;
873 gpu_reg = gpu_reg_bank_0;
874 gpu_alternate_reg = gpu_reg_bank_1;
876 for(int i=0; i<32; i++)
877 gpu_reg[i] = gpu_alternate_reg[i] = 0x00000000;
880 memset(gpu_ram_8, 0xFF, 0x1000);
882 GPUInterruptPending = false;
886 uint32 gpu_read_pc(void)
891 void gpu_reset_stats(void)
893 for(uint32 i=0; i<64; i++)
894 gpu_opcode_use[i] = 0;
895 WriteLog("--> GPU stats were reset!\n");
898 void gpu_dump_disassembly(void)
902 WriteLog("\n---[GPU code at 00F03000]---------------------------\n");
904 while (j <= 0xF03FFF)
907 j += dasmjag(JAGUAR_GPU, buffer, j);
908 WriteLog("\t%08X: %s\n", oldj, buffer);
912 void gpu_dump_registers(void)
914 WriteLog("\n---[GPU flags: NCZ %d%d%d]-----------------------\n", gpu_flag_n, gpu_flag_c, gpu_flag_z);
915 WriteLog("\nRegisters bank 0\n");
916 for(int j=0; j<8; j++)
918 WriteLog("\tr%2i = %08X r%2i = %08X r%2i = %08X r%2i = %08X\n",
919 (j << 2) + 0, gpu_reg[(j << 2) + 0],
920 (j << 2) + 1, gpu_reg[(j << 2) + 1],
921 (j << 2) + 2, gpu_reg[(j << 2) + 2],
922 (j << 2) + 3, gpu_reg[(j << 2) + 3]);
924 WriteLog("Registers bank 1\n");
925 for(int j=0; j<8; j++)
927 WriteLog("\tr%2i = %08X r%2i = %08X r%2i = %08X r%2i = %08X\n",
928 (j << 2) + 0, gpu_alternate_reg[(j << 2) + 0],
929 (j << 2) + 1, gpu_alternate_reg[(j << 2) + 1],
930 (j << 2) + 2, gpu_alternate_reg[(j << 2) + 2],
931 (j << 2) + 3, gpu_alternate_reg[(j << 2) + 3]);
935 void gpu_dump_memory(void)
937 WriteLog("\n---[GPU data at 00F03000]---------------------------\n");
938 for(int i=0; i<0xFFF; i+=4)
939 WriteLog("\t%08X: %02X %02X %02X %02X\n", 0xF03000+i, gpu_ram_8[i],
940 gpu_ram_8[i+1], gpu_ram_8[i+2], gpu_ram_8[i+3]);
945 WriteLog("GPU: stopped at PC=%08X (GPU %s running)\n", (unsigned int)gpu_pc, GPU_RUNNING ? "was" : "wasn't");
947 // Get the interrupt latch & enable bits
948 uint8 bits = (gpu_control >> 6) & 0x1F, mask = (gpu_flags >> 4) & 0x1F;
949 WriteLog("GPU: Latch bits = %02X, enable bits = %02X\n", bits, mask);
951 // WriteLog("\nregisters bank 0\n");
952 // for (int j=0;j<8;j++)
954 // WriteLog("\tr%2i=0x%.8x r%2i=0x%.8x r%2i=0x%.8x r%2i=0x%.8x\n",
955 // (j<<2)+0,gpu_reg[(j<<2)+0],
956 // (j<<2)+1,gpu_reg[(j<<2)+1],
957 // (j<<2)+2,gpu_reg[(j<<2)+2],
958 // (j<<2)+3,gpu_reg[(j<<2)+3]);
961 // WriteLog("registers bank 1\n");
964 // WriteLog("\tr%2i=0x%.8x r%2i=0x%.8x r%2i=0x%.8x r%2i=0x%.8x\n",
965 // (j<<2)+0,gpu_alternate_reg[(j<<2)+0],
966 // (j<<2)+1,gpu_alternate_reg[(j<<2)+1],
967 // (j<<2)+2,gpu_alternate_reg[(j<<2)+2],
968 // (j<<2)+3,gpu_alternate_reg[(j<<2)+3]);
971 WriteLog("\n---[GPU code at 00F03000]---------------------------\n");
972 static char buffer[512];
974 // for(int i=0; i<4096; i++)
975 while (j <= 0xF03FFF)
978 j += dasmjag(JAGUAR_GPU, buffer, j);
979 WriteLog("\t%08X: %s\n", oldj, buffer);
982 /* WriteLog("---[GPU code at %08X]---------------------------\n", gpu_pc);
984 for(int i=0; i<4096; i++)
987 j += dasmjag(JAGUAR_GPU, buffer, j);
988 WriteLog("\t%08X: %s\n", oldj, buffer);
991 WriteLog("\nGPU opcodes use:\n");
992 for(int i=0; i<64; i++)
994 if (gpu_opcode_use[i])
995 WriteLog("\t%17s %lu\n", gpu_opcode_str[i], gpu_opcode_use[i]);
999 memory_free(gpu_ram_8);
1003 // Main GPU execution core
1005 static int testCount = 1;
1007 void gpu_exec(int32 cycles)
1012 #ifdef GPU_SINGLE_STEPPING
1013 if (gpu_control & 0x18)
1016 gpu_control &= ~0x10;
1020 gpu_releaseTimeSlice_flag = 0;
1023 while ((cycles > 0) && GPU_RUNNING)
1025 gpu_flag_c = (gpu_flag_c ? 1 : 0);
1026 gpu_flag_z = (gpu_flag_z ? 1 : 0);
1027 gpu_flag_n = (gpu_flag_n ? 1 : 0);
1029 uint16 opcode = gpu_word_read(gpu_pc);
1031 uint32 index = opcode >> 10;
1032 gpu_instruction = opcode; // Added for GPU #3...
1033 gpu_opcode_first_parameter = (opcode >> 5) & 0x1F;
1034 gpu_opcode_second_parameter = opcode & 0x1F;
1035 /*if (gpu_pc == 0xF03BE8)
1036 WriteLog("Start of OP frame write...\n");
1037 if (gpu_pc == 0xF03EEE)
1038 WriteLog("--> Writing BRANCH object ---\n");
1039 if (gpu_pc == 0xF03F62)
1040 WriteLog("--> Writing BITMAP object ***\n");//*/
1041 /*if (gpu_pc == 0xF03546)
1043 WriteLog("\n--> GPU PC: F03546\n");
1044 gpu_dump_registers();
1045 gpu_dump_disassembly();
1047 /*if (gpu_pc == 0xF033F6)
1049 WriteLog("\n--> GPU PC: F033F6\n");
1050 gpu_dump_registers();
1051 gpu_dump_disassembly();
1053 /*if (gpu_pc == 0xF033CC)
1055 WriteLog("\n--> GPU PC: F033CC\n");
1056 gpu_dump_registers();
1057 gpu_dump_disassembly();
1059 /*if (gpu_pc == 0xF033D6)
1061 WriteLog("\n--> GPU PC: F033D6 (#%d)\n", testCount++);
1062 gpu_dump_registers();
1065 /*if (gpu_pc == 0xF033D8)
1067 WriteLog("\n--> GPU PC: F033D8 (#%d)\n", testCount++);
1068 gpu_dump_registers();
1071 /*if (gpu_pc == 0xF0358E)
1073 WriteLog("\n--> GPU PC: F0358E (#%d)\n", testCount++);
1074 gpu_dump_registers();
1077 /*if (gpu_pc == 0xF034CA)
1079 WriteLog("\n--> GPU PC: F034CA (#%d)\n", testCount++);
1080 gpu_dump_registers();
1082 /*if (gpu_pc == 0xF034CA)
1084 len = gpu_reg[1] + 4;//, r9save = gpu_reg[9];
1085 WriteLog("\nAbout to subtract [#%d] (R14=%08X, R15=%08X, R9=%08X):\n ", testCount++, gpu_reg[14], gpu_reg[15], gpu_reg[9]);
1086 for(int i=0; i<len; i+=4)
1087 WriteLog(" %08X", gpu_long_read(gpu_reg[15]+i));
1089 for(int i=0; i<len; i+=4)
1090 WriteLog(" %08X", gpu_long_read(gpu_reg[14]+i));
1093 if (gpu_pc == 0xF034DE)
1095 WriteLog("\nSubtracted! (R14=%08X, R15=%08X):\n ", gpu_reg[14], gpu_reg[15]);
1096 for(int i=0; i<len; i+=4)
1097 WriteLog(" %08X", gpu_long_read(gpu_reg[15]+i));
1099 for(int i=0; i<len; i+=4)
1100 WriteLog(" %08X", gpu_long_read(gpu_reg[14]+i));
1102 for(int i=0; i<len; i+=4)
1103 WriteLog(" --------");
1105 for(int i=0; i<len; i+=4)
1106 WriteLog(" %08X", gpu_long_read(gpu_reg[9]+4+i));
1109 /*if (gpu_pc == 0xF035C8)
1111 WriteLog("\n--> GPU PC: F035C8 (#%d)\n", testCount++);
1112 gpu_dump_registers();
1113 gpu_dump_disassembly();
1118 // gpu_reset_stats();
1119 static char buffer[512];
1120 dasmjag(JAGUAR_GPU, buffer, gpu_pc);
1121 WriteLog("GPU: [%08X] %s (RM=%08X, RN=%08X) -> ", gpu_pc, buffer, RM, RN);
1123 //$E400 -> 1110 01 -> $39 -> 57
1126 gpu_opcode[index]();
1128 // gpu2_opcode[index]();
1130 //GPU #3 (Doesn't show ATARI logo! #1 & #2 do...)
1132 // gpu3_opcode[index]();
1135 //GPU: [00F03548] jr nz,00F03560 (0xd561) (RM=00F03114, RN=00000004) -> --> JR: Branch taken.
1136 /*static bool firstTime = true;
1137 if (gpu_pc == 0xF03548 && firstTime)
1140 // firstTime = false;
1142 //static char buffer[512];
1144 //while (k<0xF0356C)
1147 //k += dasmjag(JAGUAR_GPU, buffer, k);
1148 //WriteLog("GPU: [%08X] %s\n", oldk, buffer);
1150 // gpu_start_log = 1;
1152 //GPU: [00F0354C] jump nz,(r29) (0xd3a1) (RM=00F03314, RN=00000004) -> (RM=00F03314, RN=00000004)
1153 /*if (gpu_pc == 0xF0354C)
1154 gpu_flag_z = 0;//, gpu_start_log = 1;//*/
1156 cycles -= gpu_opcode_cycles[index];
1157 gpu_opcode_use[index]++;
1159 WriteLog("(RM=%08X, RN=%08X)\n", RM, RN);//*/
1170 GPU opcodes use (offset punch--vertically below bad guy):
1192 load_r14_indexed 1183
1193 load_r15_indexed 1125
1196 store_r14_indexed 320
1204 static void gpu_opcode_jump(void)
1207 char * condition[32] =
1208 { "T", "nz", "z", "???", "nc", "nc nz", "nc z", "???", "c", "c nz",
1209 "c z", "???", "???", "???", "???", "???", "???", "???", "???",
1210 "???", "nn", "nn nz", "nn z", "???", "n", "n nz", "n z", "???",
1211 "???", "???", "???", "F" };
1212 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);
1215 /* gpu_flag_c = (gpu_flag_c ? 1 : 0);
1216 gpu_flag_z = (gpu_flag_z ? 1 : 0);
1217 gpu_flag_n = (gpu_flag_n ? 1 : 0);*/
1218 // KLUDGE: Used by BRANCH_CONDITION
1219 uint32 jaguar_flags = (gpu_flag_n << 2) | (gpu_flag_c << 1) | gpu_flag_z;
1221 if (BRANCH_CONDITION(IMM_2))
1224 WriteLog("Branched!\n");
1227 WriteLog(" --> JUMP: Branch taken.\n");
1228 uint32 delayed_pc = RM;
1231 gpu_pc = delayed_pc;
1232 /* uint16 opcode = gpu_word_read(gpu_pc);
1233 gpu_opcode_first_parameter = (opcode >> 5) & 0x1F;
1234 gpu_opcode_second_parameter = opcode & 0x1F;
1236 gpu_pc = delayed_pc;
1237 gpu_opcode[opcode>>10]();//*/
1241 WriteLog("Branch NOT taken.\n");
1245 static void gpu_opcode_jr(void)
1248 char * condition[32] =
1249 { "T", "nz", "z", "???", "nc", "nc nz", "nc z", "???", "c", "c nz",
1250 "c z", "???", "???", "???", "???", "???", "???", "???", "???",
1251 "???", "nn", "nn nz", "nn z", "???", "n", "n nz", "n z", "???",
1252 "???", "???", "???", "F" };
1253 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);
1255 /* if (CONDITION(jaguar.op & 31))
1257 INT32 r1 = (INT8)((jaguar.op >> 2) & 0xF8) >> 2;
1258 UINT32 newpc = jaguar.PC + r1;
1260 jaguar.op = ROPCODE(jaguar.PC);
1262 (*jaguar.table[jaguar.op >> 10])();
1264 jaguar_icount -= 3; // 3 wait states guaranteed
1267 /* gpu_flag_n = (gpu_flag_n ? 1 : 0);
1268 gpu_flag_c = (gpu_flag_c ? 1 : 0);
1269 gpu_flag_z = (gpu_flag_z ? 1 : 0);*/
1270 // KLUDGE: Used by BRANCH_CONDITION
1271 uint32 jaguar_flags = (gpu_flag_n << 2) | (gpu_flag_c << 1) | gpu_flag_z;
1273 if (BRANCH_CONDITION(IMM_2))
1276 WriteLog("Branched!\n");
1279 WriteLog(" --> JR: Branch taken.\n");
1280 int32 offset = (IMM_1 & 0x10 ? 0xFFFFFFF0 | IMM_1 : IMM_1); // Sign extend IMM_1
1281 int32 delayed_pc = gpu_pc + (offset * 2);
1284 gpu_pc = delayed_pc;
1285 /* uint16 opcode = gpu_word_read(gpu_pc);
1286 gpu_opcode_first_parameter = (opcode >> 5) & 0x1F;
1287 gpu_opcode_second_parameter = opcode & 0x1F;
1289 gpu_pc = delayed_pc;
1290 gpu_opcode[opcode>>10]();//*/
1294 WriteLog("Branch NOT taken.\n");
1298 static void gpu_opcode_add(void)
1301 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);
1303 UINT32 res = RN + RM;
1304 CLR_ZNC; SET_ZNC_ADD(RN, RM, res);
1307 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);
1311 static void gpu_opcode_addc(void)
1314 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);
1316 /* int dreg = jaguar.op & 31;
1317 UINT32 r1 = jaguar.r[(jaguar.op >> 5) & 31];
1318 UINT32 r2 = jaguar.r[dreg];
1319 UINT32 res = r2 + r1 + ((jaguar.FLAGS >> 1) & 1);
1320 jaguar.r[dreg] = res;
1321 CLR_ZNC; SET_ZNC_ADD(r2,r1,res);*/
1323 UINT32 res = RN + RM + gpu_flag_c;
1324 UINT32 carry = gpu_flag_c;
1325 // SET_ZNC_ADD(RN, RM, res); //???BUG???
1326 SET_ZNC_ADD(RN + carry, RM, res);
1327 // SET_ZNC_ADD(RN, RM + carry, res);
1330 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);
1334 static void gpu_opcode_addq(void)
1337 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);
1339 UINT32 r1 = gpu_convert_zero[IMM_1];
1340 UINT32 res = RN + r1;
1341 CLR_ZNC; SET_ZNC_ADD(RN, r1, res);
1344 WriteLog("[NCZ:%u%u%u, R%02u=%08X]\n", gpu_flag_n, gpu_flag_c, gpu_flag_z, IMM_2, RN);
1348 static void gpu_opcode_addqt(void)
1350 #ifdef GPU_DIS_ADDQT
1351 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);
1353 RN += gpu_convert_zero[IMM_1];
1354 #ifdef GPU_DIS_ADDQT
1355 WriteLog("[NCZ:%u%u%u, R%02u=%08X]\n", gpu_flag_n, gpu_flag_c, gpu_flag_z, IMM_2, RN);
1359 static void gpu_opcode_sub(void)
1362 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);
1364 UINT32 res = RN - RM;
1365 SET_ZNC_SUB(RN, RM, res);
1368 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);
1372 static void gpu_opcode_subc(void)
1375 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);
1377 UINT32 res = RN - RM - gpu_flag_c;
1378 UINT32 borrow = gpu_flag_c;
1379 // SET_ZNC_SUB(RN, RM, res); //???BUG??? YES!!!
1380 SET_ZNC_SUB(RN - borrow, RM, res);
1383 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);
1387 static void gpu_opcode_subq(void)
1390 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);
1392 UINT32 r1 = gpu_convert_zero[IMM_1];
1393 UINT32 res = RN - r1;
1394 SET_ZNC_SUB(RN, r1, res);
1397 WriteLog("[NCZ:%u%u%u, R%02u=%08X]\n", gpu_flag_n, gpu_flag_c, gpu_flag_z, IMM_2, RN);
1401 static void gpu_opcode_subqt(void)
1403 #ifdef GPU_DIS_SUBQT
1404 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);
1406 RN -= gpu_convert_zero[IMM_1];
1407 #ifdef GPU_DIS_SUBQT
1408 WriteLog("[NCZ:%u%u%u, R%02u=%08X]\n", gpu_flag_n, gpu_flag_c, gpu_flag_z, IMM_2, RN);
1412 static void gpu_opcode_cmp(void)
1415 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);
1417 UINT32 res = RN - RM;
1418 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 };
1429 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);
1431 UINT32 r1 = sqtable[IMM_1 & 0x1F]; // I like this better -> (INT8)(jaguar.op >> 2) >> 3;
1432 UINT32 res = RN - r1;
1433 SET_ZNC_SUB(RN, r1, res);
1435 WriteLog("[NCZ:%u%u%u]\n", gpu_flag_n, gpu_flag_c, gpu_flag_z);
1439 static void gpu_opcode_and(void)
1442 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);
1447 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);
1451 static void gpu_opcode_or(void)
1454 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);
1459 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);
1463 static void gpu_opcode_xor(void)
1466 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);
1471 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);
1475 static void gpu_opcode_not(void)
1478 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);
1483 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);
1487 static void gpu_opcode_move_pc(void)
1489 #ifdef GPU_DIS_MOVEPC
1490 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);
1492 // Should be previous PC--this might not always be previous instruction!
1493 // Then again, this will point right at the *current* instruction, i.e., MOVE PC,R!
1495 #ifdef GPU_DIS_MOVEPC
1496 WriteLog("[NCZ:%u%u%u, R%02u=%08X]\n", gpu_flag_n, gpu_flag_c, gpu_flag_z, IMM_2, RN);
1500 static void gpu_opcode_sat8(void)
1503 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);
1505 RN = ((int32)RN < 0 ? 0 : (RN > 0xFF ? 0xFF : RN));
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_sat16(void)
1514 RN = ((int32)RN < 0 ? 0 : (RN > 0xFFFF ? 0xFFFF : RN));
1518 static void gpu_opcode_sat24(void)
1520 RN = ((int32)RN < 0 ? 0 : (RN > 0xFFFFFF ? 0xFFFFFF : RN));
1524 static void gpu_opcode_store_r14_indexed(void)
1526 #ifdef GPU_DIS_STORE14I
1527 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));
1529 gpu_long_write(gpu_reg[14] + (gpu_convert_zero[IMM_1] << 2), RN);
1532 static void gpu_opcode_store_r15_indexed(void)
1534 #ifdef GPU_DIS_STORE15I
1535 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));
1537 gpu_long_write(gpu_reg[15] + (gpu_convert_zero[IMM_1] << 2), RN);
1540 static void gpu_opcode_load_r14_ri(void)
1542 #ifdef GPU_DIS_LOAD14R
1543 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);
1545 RN = gpu_long_read(gpu_reg[14] + RM);
1546 #ifdef GPU_DIS_LOAD14R
1547 WriteLog("[NCZ:%u%u%u, R%02u=%08X]\n", gpu_flag_n, gpu_flag_c, gpu_flag_z, IMM_2, RN);
1551 static void gpu_opcode_load_r15_ri(void)
1553 #ifdef GPU_DIS_LOAD15R
1554 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);
1556 RN = gpu_long_read(gpu_reg[15] + RM);
1557 #ifdef GPU_DIS_LOAD15R
1558 WriteLog("[NCZ:%u%u%u, R%02u=%08X]\n", gpu_flag_n, gpu_flag_c, gpu_flag_z, IMM_2, RN);
1562 static void gpu_opcode_store_r14_ri(void)
1564 #ifdef GPU_DIS_STORE14R
1565 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]);
1567 gpu_long_write(gpu_reg[14] + RM, RN);
1570 static void gpu_opcode_store_r15_ri(void)
1572 #ifdef GPU_DIS_STORE15R
1573 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]);
1575 gpu_long_write(gpu_reg[15] + RM, RN);
1578 static void gpu_opcode_nop(void)
1581 WriteLog("%06X: NOP [NCZ:%u%u%u]\n", gpu_pc-2, gpu_flag_n, gpu_flag_c, gpu_flag_z);
1585 static void gpu_opcode_pack(void)
1588 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);
1592 //BUG! if (RM == 0) // Pack
1593 if (IMM_1 == 0) // Pack
1594 RN = ((val >> 10) & 0x0000F000) | ((val >> 5) & 0x00000F00) | (val & 0x000000FF);
1596 RN = ((val & 0x0000F000) << 10) | ((val & 0x00000F00) << 5) | (val & 0x000000FF);
1598 WriteLog("[NCZ:%u%u%u, R%02u=%08X]\n", gpu_flag_n, gpu_flag_c, gpu_flag_z, IMM_2, RN);
1602 static void gpu_opcode_storeb(void)
1604 #ifdef GPU_DIS_STOREB
1605 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);
1608 // Would appear to be so...!
1609 if ((RM >= 0xF03000) && (RM <= 0xF03FFF))
1610 gpu_long_write(RM, RN & 0xFF);
1612 jaguar_byte_write(RM, RN);
1615 static void gpu_opcode_storew(void)
1617 #ifdef GPU_DIS_STOREW
1618 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);
1620 if ((RM >= 0xF03000) && (RM <= 0xF03FFF))
1621 gpu_long_write(RM, RN & 0xFFFF);
1623 jaguar_word_write(RM, RN);
1626 static void gpu_opcode_store(void)
1628 #ifdef GPU_DIS_STORE
1629 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);
1631 gpu_long_write(RM, RN);
1634 static void gpu_opcode_storep(void)
1636 gpu_long_write(RM + 0, gpu_hidata);
1637 gpu_long_write(RM + 4, RN);
1640 static void gpu_opcode_loadb(void)
1642 #ifdef GPU_DIS_LOADB
1643 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);
1645 if ((RM >= 0xF03000) && (RM <= 0xF03FFF))
1646 RN = gpu_long_read(RM) & 0xFF;
1648 RN = jaguar_byte_read(RM);
1649 #ifdef GPU_DIS_LOADB
1650 WriteLog("[NCZ:%u%u%u, R%02u=%08X]\n", gpu_flag_n, gpu_flag_c, gpu_flag_z, IMM_2, RN);
1654 static void gpu_opcode_loadw(void)
1656 #ifdef GPU_DIS_LOADW
1657 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);
1659 if ((RM >= 0xF03000) && (RM <= 0xF03FFF))
1660 RN = gpu_long_read(RM) & 0xFFFF;
1662 RN = jaguar_word_read(RM);
1663 #ifdef GPU_DIS_LOADW
1664 WriteLog("[NCZ:%u%u%u, R%02u=%08X]\n", gpu_flag_n, gpu_flag_c, gpu_flag_z, IMM_2, RN);
1668 static void gpu_opcode_load(void)
1671 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);
1673 RN = gpu_long_read(RM);
1675 WriteLog("[NCZ:%u%u%u, R%02u=%08X]\n", gpu_flag_n, gpu_flag_c, gpu_flag_z, IMM_2, RN);
1679 static void gpu_opcode_loadp(void)
1681 gpu_hidata = gpu_long_read(RM + 0);
1682 RN = gpu_long_read(RM + 4);
1685 static void gpu_opcode_load_r14_indexed(void)
1687 #ifdef GPU_DIS_LOAD14I
1688 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);
1690 RN = gpu_long_read(gpu_reg[14] + (gpu_convert_zero[IMM_1] << 2));
1691 #ifdef GPU_DIS_LOAD14I
1692 WriteLog("[NCZ:%u%u%u, R%02u=%08X]\n", gpu_flag_n, gpu_flag_c, gpu_flag_z, IMM_2, RN);
1696 static void gpu_opcode_load_r15_indexed(void)
1698 #ifdef GPU_DIS_LOAD15I
1699 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);
1701 RN = gpu_long_read(gpu_reg[15] + (gpu_convert_zero[IMM_1] << 2));
1702 #ifdef GPU_DIS_LOAD15I
1703 WriteLog("[NCZ:%u%u%u, R%02u=%08X]\n", gpu_flag_n, gpu_flag_c, gpu_flag_z, IMM_2, RN);
1707 static void gpu_opcode_movei(void)
1709 #ifdef GPU_DIS_MOVEI
1710 WriteLog("%06X: MOVEI #$%08X, R%02u [NCZ:%u%u%u, R%02u=%08X] -> ", gpu_pc-2, (uint32)gpu_word_read(gpu_pc) | ((uint32)gpu_word_read(gpu_pc + 2) << 16), IMM_2, gpu_flag_n, gpu_flag_c, gpu_flag_z, IMM_2, RN);
1712 // This instruction is followed by 32-bit value in LSW / MSW format...
1713 RN = (uint32)gpu_word_read(gpu_pc) | ((uint32)gpu_word_read(gpu_pc + 2) << 16);
1715 #ifdef GPU_DIS_MOVEI
1716 WriteLog("[NCZ:%u%u%u, R%02u=%08X]\n", gpu_flag_n, gpu_flag_c, gpu_flag_z, IMM_2, RN);
1720 static void gpu_opcode_moveta(void)
1722 #ifdef GPU_DIS_MOVETA
1723 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);
1726 #ifdef GPU_DIS_MOVETA
1727 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);
1731 static void gpu_opcode_movefa(void)
1733 #ifdef GPU_DIS_MOVEFA
1734 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);
1737 #ifdef GPU_DIS_MOVEFA
1738 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);
1742 static void gpu_opcode_move(void)
1745 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);
1749 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);
1753 static void gpu_opcode_moveq(void)
1755 #ifdef GPU_DIS_MOVEQ
1756 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);
1759 #ifdef GPU_DIS_MOVEQ
1760 WriteLog("[NCZ:%u%u%u, R%02u=%08X]\n", gpu_flag_n, gpu_flag_c, gpu_flag_z, IMM_2, RN);
1764 static void gpu_opcode_resmac(void)
1769 static void gpu_opcode_imult(void)
1771 #ifdef GPU_DIS_IMULT
1772 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);
1774 RN = (int16)RN * (int16)RM;
1776 #ifdef GPU_DIS_IMULT
1777 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);
1781 static void gpu_opcode_mult(void)
1784 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);
1786 RN = (uint16)RM * (uint16)RN;
1789 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);
1793 static void gpu_opcode_bclr(void)
1796 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);
1798 UINT32 res = RN & ~(1 << IMM_1);
1802 WriteLog("[NCZ:%u%u%u, R%02u=%08X]\n", gpu_flag_n, gpu_flag_c, gpu_flag_z, IMM_2, RN);
1806 static void gpu_opcode_btst(void)
1809 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);
1811 gpu_flag_z = (~RN >> IMM_1) & 1;
1813 WriteLog("[NCZ:%u%u%u, R%02u=%08X]\n", gpu_flag_n, gpu_flag_c, gpu_flag_z, IMM_2, RN);
1817 static void gpu_opcode_bset(void)
1820 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);
1822 UINT32 res = RN | (1 << IMM_1);
1826 WriteLog("[NCZ:%u%u%u, R%02u=%08X]\n", gpu_flag_n, gpu_flag_c, gpu_flag_z, IMM_2, RN);
1830 static void gpu_opcode_imacn(void)
1832 uint32 res = (int16)RM * (int16)(RN);
1836 static void gpu_opcode_mtoi(void)
1839 uint32 res = RN = (((INT32)_RM >> 8) & 0xFF800000) | (_RM & 0x007FFFFF);
1843 static void gpu_opcode_normi(void)
1850 while ((_RM & 0xFFC00000) == 0)
1855 while ((_RM & 0xFF800000) != 0)
1865 static void gpu_opcode_mmult(void)
1867 int count = gpu_matrix_control & 0x0F; // Matrix width
1868 uint32 addr = gpu_pointer_to_matrix; // In the GPU's RAM
1872 if (gpu_matrix_control & 0x10) // Column stepping
1874 for(int i=0; i<count; i++)
1878 a = (int16)((gpu_alternate_reg[IMM_1 + (i >> 1)] >> 16) & 0xFFFF);
1880 a = (int16)(gpu_alternate_reg[IMM_1 + (i >> 1)] & 0xFFFF);
1882 int16 b = ((int16)gpu_word_read(addr + 2));
1887 else // Row stepping
1889 for(int i=0; i<count; i++)
1893 a = (int16)((gpu_alternate_reg[IMM_1 + (i >> 1)] >> 16) & 0xFFFF);
1895 a = (int16)(gpu_alternate_reg[IMM_1 + (i >> 1)] & 0xFFFF);
1897 int16 b = ((int16)gpu_word_read(addr + 2));
1902 RN = res = (int32)accum;
1903 // carry flag to do (out of the last add)
1907 static void gpu_opcode_abs(void)
1910 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);
1912 gpu_flag_c = RN >> 31;
1913 if (RN == 0x80000000)
1914 //Is 0x80000000 a positive number? If so, then we need to set C to 0 as well!
1915 gpu_flag_n = 1, gpu_flag_z = 0;
1920 gpu_flag_n = 0; SET_FLAG_Z(RN);
1923 WriteLog("[NCZ:%u%u%u, R%02u=%08X]\n", gpu_flag_n, gpu_flag_c, gpu_flag_z, IMM_2, RN);
1927 static void gpu_opcode_div(void) // RN / RM
1930 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);
1932 // NOTE: remainder is NOT calculated correctly here!
1933 // The original tried to get it right by checking to see if the
1934 // remainder was negative, but that's too late...
1935 // The code there should do it now, but I'm not 100% sure...
1939 if (gpu_div_control & 0x01) // 16.16 division
1941 RN = ((UINT64)RN << 16) / RM;
1942 gpu_remain = ((UINT64)RN << 16) % RM;
1947 gpu_remain = RN % RM;
1950 if ((gpu_remain - RM) & 0x80000000) // If the result would have been negative...
1951 gpu_remain -= RM; // Then make it negative!
1961 if (gpu_div_control & 1)
1963 gpu_remain = (((uint64)_RN) << 16) % _RM;
1964 if (gpu_remain&0x80000000)
1966 RN = (((uint64)_RN) << 16) / _RM;
1970 gpu_remain = _RN % _RM;
1971 if (gpu_remain&0x80000000)
1979 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);
1983 static void gpu_opcode_imultn(void)
1985 uint32 res = (int32)((int16)RN * (int16)RM);
1986 gpu_acc = (int32)res;
1991 static void gpu_opcode_neg(void)
1994 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);
1997 SET_ZNC_SUB(0, RN, res);
2000 WriteLog("[NCZ:%u%u%u, R%02u=%08X]\n", gpu_flag_n, gpu_flag_c, gpu_flag_z, IMM_2, RN);
2004 static void gpu_opcode_shlq(void)
2006 /* int dreg = jaguar.op & 31;
2007 INT32 r1 = convert_zero[(jaguar.op >> 5) & 31];
2008 UINT32 r2 = jaguar.r[dreg];
2009 UINT32 res = r2 << (32 - r1);
2010 jaguar.r[dreg] = res;
2011 CLR_ZNC; SET_ZN(res); jaguar.FLAGS |= (r2 >> 30) & 2;*/
2014 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);
2016 // Was a bug here...
2017 // (Look at Aaron's code: If r1 = 32, then 32 - 32 = 0 which is wrong!)
2018 INT32 r1 = 32 - IMM_1;
2019 UINT32 res = RN << r1;
2020 SET_ZN(res); gpu_flag_c = (RN >> 31) & 1;
2023 WriteLog("[NCZ:%u%u%u, R%02u=%08X]\n", gpu_flag_n, gpu_flag_c, gpu_flag_z, IMM_2, RN);
2027 static void gpu_opcode_shrq(void)
2029 /* int dreg = jaguar.op & 31;
2030 INT32 r1 = convert_zero[(jaguar.op >> 5) & 31];
2031 UINT32 r2 = jaguar.r[dreg];
2032 UINT32 res = r2 >> r1;
2033 jaguar.r[dreg] = res;
2034 CLR_ZNC; SET_ZN(res); jaguar.FLAGS |= (r2 << 1) & 2;*/
2037 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);
2039 INT32 r1 = gpu_convert_zero[IMM_1];
2040 UINT32 res = RN >> r1;
2041 SET_ZN(res); gpu_flag_c = RN & 1;
2044 WriteLog("[NCZ:%u%u%u, R%02u=%08X]\n", gpu_flag_n, gpu_flag_c, gpu_flag_z, IMM_2, RN);
2048 static void gpu_opcode_ror(void)
2050 /* int dreg = jaguar.op & 31;
2051 UINT32 r1 = jaguar.r[(jaguar.op >> 5) & 31] & 31;
2052 UINT32 r2 = jaguar.r[dreg];
2053 UINT32 res = (r2 >> r1) | (r2 << (32 - r1));
2054 jaguar.r[dreg] = res;
2055 CLR_ZNC; SET_ZN(res); jaguar.FLAGS |= (r2 >> 30) & 2;*/
2058 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);
2060 UINT32 r1 = RM & 0x1F;
2061 UINT32 res = (RN >> r1) | (RN << (32 - r1));
2062 SET_ZN(res); gpu_flag_c = (RN >> 31) & 1;
2065 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);
2069 static void gpu_opcode_rorq(void)
2071 /* int dreg = jaguar.op & 31;
2072 UINT32 r1 = convert_zero[(jaguar.op >> 5) & 31];
2073 UINT32 r2 = jaguar.r[dreg];
2074 UINT32 res = (r2 >> r1) | (r2 << (32 - r1));
2075 jaguar.r[dreg] = res;
2076 CLR_ZNC; SET_ZN(res); jaguar.FLAGS |= (r2 >> 30) & 2;*/
2079 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);
2081 UINT32 r1 = gpu_convert_zero[IMM_1 & 0x1F];
2083 UINT32 res = (r2 >> r1) | (r2 << (32 - r1));
2085 SET_ZN(res); gpu_flag_c = (r2 >> 31) & 0x01;
2087 WriteLog("[NCZ:%u%u%u, R%02u=%08X]\n", gpu_flag_n, gpu_flag_c, gpu_flag_z, IMM_2, RN);
2091 static void gpu_opcode_sha(void)
2093 /* int dreg = jaguar.op & 31;
2094 INT32 r1 = (INT32)jaguar.r[(jaguar.op >> 5) & 31];
2095 UINT32 r2 = jaguar.r[dreg];
2101 res = (r1 <= -32) ? 0 : (r2 << -r1);
2102 jaguar.FLAGS |= (r2 >> 30) & 2;
2106 res = (r1 >= 32) ? ((INT32)r2 >> 31) : ((INT32)r2 >> r1);
2107 jaguar.FLAGS |= (r2 << 1) & 2;
2109 jaguar.r[dreg] = res;
2113 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);
2119 res = ((INT32)RM <= -32) ? 0 : (RN << -(INT32)RM);
2120 gpu_flag_c = RN >> 31;
2124 res = ((INT32)RM >= 32) ? ((INT32)RN >> 31) : ((INT32)RN >> (INT32)RM);
2125 gpu_flag_c = RN & 0x01;
2130 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);
2133 /* int32 sRM=(int32)RM;
2139 if (shift>=32) shift=32;
2140 gpu_flag_c=(_RN&0x80000000)>>31;
2150 if (shift>=32) shift=32;
2154 _RN=((int32)_RN)>>1;
2163 static void gpu_opcode_sharq(void)
2165 /* int dreg = jaguar.op & 31;
2166 INT32 r1 = convert_zero[(jaguar.op >> 5) & 31];
2167 UINT32 r2 = jaguar.r[dreg];
2168 UINT32 res = (INT32)r2 >> r1;
2169 jaguar.r[dreg] = res;
2170 CLR_ZNC; SET_ZN(res); jaguar.FLAGS |= (r2 << 1) & 2;*/
2172 #ifdef GPU_DIS_SHARQ
2173 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);
2175 UINT32 res = (INT32)RN >> gpu_convert_zero[IMM_1];
2176 SET_ZN(res); gpu_flag_c = RN & 0x01;
2178 #ifdef GPU_DIS_SHARQ
2179 WriteLog("[NCZ:%u%u%u, R%02u=%08X]\n", gpu_flag_n, gpu_flag_c, gpu_flag_z, IMM_2, RN);
2183 /* uint32 shift = gpu_convert_zero[IMM_1];
2186 gpu_flag_c = (_RN & 0x01);
2189 _RN = ((int32)_RN) >> 1;
2197 static void gpu_opcode_sh(void)
2200 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);
2202 if (RM & 0x80000000) // Shift left
2204 gpu_flag_c = RN >> 31;
2205 RN = ((int32)RM <= -32 ? 0 : RN << -(int32)RM);
2209 gpu_flag_c = RN & 0x01;
2210 RN = (RM >= 32 ? 0 : RN >> RM);
2214 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);
2218 //Temporary: Testing only!