4 // Originally by David Raingeard (Cal2)
5 // GCC/SDL port by Niels Wagenaar (Linux/WIN32) and Caz (BeOS)
6 // Cleanups, endian wrongness, and bad ASM amelioration by James L. Hammons
7 // Note: Endian wrongness probably stems from the MAME origins of this emu and
8 // the braindead way in which MAME handles memory. :-)
10 // Problem with not booting the BIOS was the incorrect way that the
11 // SUBC instruction set the carry when the carry was set going in...
12 // Same problem with ADDC...
19 // For GPU dissasembly...
39 #define GPU_DIS_LOAD14I
40 #define GPU_DIS_LOAD14R
41 #define GPU_DIS_LOAD15I
42 #define GPU_DIS_LOAD15R
44 #define GPU_DIS_MOVEFA
46 #define GPU_DIS_MOVEPC
47 #define GPU_DIS_MOVETA
64 #define GPU_DIS_STOREB
65 #define GPU_DIS_STOREW
66 #define GPU_DIS_STORE14I
67 #define GPU_DIS_STORE14R
68 #define GPU_DIS_STORE15I
69 #define GPU_DIS_STORE15R
76 bool doGPUDis = false;
77 //bool doGPUDis = true;
80 GPU opcodes use (BIOS flying ATARI logo):
122 #define CINT0FLAG 0x0200
123 #define CINT1FLAG 0x0400
124 #define CINT2FLAG 0x0800
125 #define CINT3FLAG 0x1000
126 #define CINT4FLAG 0x2000
127 #define CINT04FLAGS (CINT0FLAG | CINT1FLAG | CINT2FLAG | CINT3FLAG | CINT4FLAG)
131 #define ZERO_FLAG 0x0001
132 #define CARRY_FLAG 0x0002
133 #define NEGA_FLAG 0x0004
135 #define INT_ENA0 0x0010
136 #define INT_ENA1 0x0020
137 #define INT_ENA2 0x0040
138 #define INT_ENA3 0x0080
139 #define INT_ENA4 0x0100
140 #define INT_CLR0 0x0200
141 #define INT_CLR1 0x0400
142 #define INT_CLR2 0x0800
143 #define INT_CLR3 0x1000
144 #define INT_CLR4 0x2000
145 #define REGPAGE 0x4000
148 // External global variables
150 extern int start_logging;
151 extern int gpu_start_log;
153 // Private function prototypes
155 void GPUUpdateRegisterBanks(void);
157 void GPUDumpDisassembly(void);
158 void GPUDumpRegisters(void);
159 void GPUDumpMemory(void);
161 static void gpu_opcode_add(void);
162 static void gpu_opcode_addc(void);
163 static void gpu_opcode_addq(void);
164 static void gpu_opcode_addqt(void);
165 static void gpu_opcode_sub(void);
166 static void gpu_opcode_subc(void);
167 static void gpu_opcode_subq(void);
168 static void gpu_opcode_subqt(void);
169 static void gpu_opcode_neg(void);
170 static void gpu_opcode_and(void);
171 static void gpu_opcode_or(void);
172 static void gpu_opcode_xor(void);
173 static void gpu_opcode_not(void);
174 static void gpu_opcode_btst(void);
175 static void gpu_opcode_bset(void);
176 static void gpu_opcode_bclr(void);
177 static void gpu_opcode_mult(void);
178 static void gpu_opcode_imult(void);
179 static void gpu_opcode_imultn(void);
180 static void gpu_opcode_resmac(void);
181 static void gpu_opcode_imacn(void);
182 static void gpu_opcode_div(void);
183 static void gpu_opcode_abs(void);
184 static void gpu_opcode_sh(void);
185 static void gpu_opcode_shlq(void);
186 static void gpu_opcode_shrq(void);
187 static void gpu_opcode_sha(void);
188 static void gpu_opcode_sharq(void);
189 static void gpu_opcode_ror(void);
190 static void gpu_opcode_rorq(void);
191 static void gpu_opcode_cmp(void);
192 static void gpu_opcode_cmpq(void);
193 static void gpu_opcode_sat8(void);
194 static void gpu_opcode_sat16(void);
195 static void gpu_opcode_move(void);
196 static void gpu_opcode_moveq(void);
197 static void gpu_opcode_moveta(void);
198 static void gpu_opcode_movefa(void);
199 static void gpu_opcode_movei(void);
200 static void gpu_opcode_loadb(void);
201 static void gpu_opcode_loadw(void);
202 static void gpu_opcode_load(void);
203 static void gpu_opcode_loadp(void);
204 static void gpu_opcode_load_r14_indexed(void);
205 static void gpu_opcode_load_r15_indexed(void);
206 static void gpu_opcode_storeb(void);
207 static void gpu_opcode_storew(void);
208 static void gpu_opcode_store(void);
209 static void gpu_opcode_storep(void);
210 static void gpu_opcode_store_r14_indexed(void);
211 static void gpu_opcode_store_r15_indexed(void);
212 static void gpu_opcode_move_pc(void);
213 static void gpu_opcode_jump(void);
214 static void gpu_opcode_jr(void);
215 static void gpu_opcode_mmult(void);
216 static void gpu_opcode_mtoi(void);
217 static void gpu_opcode_normi(void);
218 static void gpu_opcode_nop(void);
219 static void gpu_opcode_load_r14_ri(void);
220 static void gpu_opcode_load_r15_ri(void);
221 static void gpu_opcode_store_r14_ri(void);
222 static void gpu_opcode_store_r15_ri(void);
223 static void gpu_opcode_sat24(void);
224 static void gpu_opcode_pack(void);
226 // This is wrong, since it doesn't take pipeline effects into account. !!! FIX !!!
227 /*uint8 gpu_opcode_cycles[64] =
229 3, 3, 3, 3, 3, 3, 3, 3,
230 3, 3, 3, 3, 3, 3, 3, 3,
231 3, 3, 1, 3, 1, 18, 3, 3,
232 3, 3, 3, 3, 3, 3, 3, 3,
233 3, 3, 2, 2, 2, 2, 3, 4,
234 5, 4, 5, 6, 6, 1, 1, 1,
235 1, 2, 2, 2, 1, 1, 9, 3,
236 3, 1, 6, 6, 2, 2, 3, 3
238 //Here's a QnD kludge...
239 //This is wrong, wrong, WRONG, but it seems to work for the time being...
240 //(That is, it fixes Flip Out which relies on GPU timing rather than semaphores. Bad developers! Bad!)
241 //What's needed here is a way to take pipeline effects into account (including pipeline stalls!)...
242 uint8 gpu_opcode_cycles[64] =
244 1, 1, 1, 1, 1, 1, 1, 1,
245 1, 1, 1, 1, 1, 1, 1, 1,
246 1, 1, 1, 1, 1, 9, 1, 1,
247 1, 1, 1, 1, 1, 1, 1, 1,
248 1, 1, 1, 1, 1, 1, 1, 2,
249 2, 2, 2, 3, 3, 1, 1, 1,
250 1, 1, 1, 1, 1, 1, 4, 1,
251 1, 1, 3, 3, 1, 1, 1, 1
254 void (*gpu_opcode[64])()=
256 gpu_opcode_add, gpu_opcode_addc, gpu_opcode_addq, gpu_opcode_addqt,
257 gpu_opcode_sub, gpu_opcode_subc, gpu_opcode_subq, gpu_opcode_subqt,
258 gpu_opcode_neg, gpu_opcode_and, gpu_opcode_or, gpu_opcode_xor,
259 gpu_opcode_not, gpu_opcode_btst, gpu_opcode_bset, gpu_opcode_bclr,
260 gpu_opcode_mult, gpu_opcode_imult, gpu_opcode_imultn, gpu_opcode_resmac,
261 gpu_opcode_imacn, gpu_opcode_div, gpu_opcode_abs, gpu_opcode_sh,
262 gpu_opcode_shlq, gpu_opcode_shrq, gpu_opcode_sha, gpu_opcode_sharq,
263 gpu_opcode_ror, gpu_opcode_rorq, gpu_opcode_cmp, gpu_opcode_cmpq,
264 gpu_opcode_sat8, gpu_opcode_sat16, gpu_opcode_move, gpu_opcode_moveq,
265 gpu_opcode_moveta, gpu_opcode_movefa, gpu_opcode_movei, gpu_opcode_loadb,
266 gpu_opcode_loadw, gpu_opcode_load, gpu_opcode_loadp, gpu_opcode_load_r14_indexed,
267 gpu_opcode_load_r15_indexed, gpu_opcode_storeb, gpu_opcode_storew, gpu_opcode_store,
268 gpu_opcode_storep, gpu_opcode_store_r14_indexed, gpu_opcode_store_r15_indexed, gpu_opcode_move_pc,
269 gpu_opcode_jump, gpu_opcode_jr, gpu_opcode_mmult, gpu_opcode_mtoi,
270 gpu_opcode_normi, gpu_opcode_nop, gpu_opcode_load_r14_ri, gpu_opcode_load_r15_ri,
271 gpu_opcode_store_r14_ri, gpu_opcode_store_r15_ri, gpu_opcode_sat24, gpu_opcode_pack,
274 static uint8 * gpu_ram_8;
276 static uint32 gpu_acc;
277 static uint32 gpu_remain;
278 static uint32 gpu_hidata;
279 static uint32 gpu_flags;
280 static uint32 gpu_matrix_control;
281 static uint32 gpu_pointer_to_matrix;
282 static uint32 gpu_data_organization;
283 static uint32 gpu_control;
284 static uint32 gpu_div_control;
285 // There is a distinct advantage to having these separated out--there's no need to clear
286 // a bit before writing a result. I.e., if the result of an operation leaves a zero in
287 // the carry flag, you don't have to zero gpu_flag_c before you can write that zero!
288 static uint8 gpu_flag_z, gpu_flag_n, gpu_flag_c;
289 static uint32 * gpu_reg_bank_0;
290 static uint32 * gpu_reg_bank_1;
291 static uint32 * gpu_reg;
292 static uint32 * gpu_alternate_reg;
294 static uint32 gpu_instruction;
295 static uint32 gpu_opcode_first_parameter;
296 static uint32 gpu_opcode_second_parameter;
298 #define GPU_RUNNING (gpu_control & 0x01)
300 #define RM gpu_reg[gpu_opcode_first_parameter]
301 #define RN gpu_reg[gpu_opcode_second_parameter]
302 #define ALTERNATE_RM gpu_alternate_reg[gpu_opcode_first_parameter]
303 #define ALTERNATE_RN gpu_alternate_reg[gpu_opcode_second_parameter]
304 #define IMM_1 gpu_opcode_first_parameter
305 #define IMM_2 gpu_opcode_second_parameter
307 #define SET_FLAG_Z(r) (gpu_flag_z = ((r) == 0));
308 #define SET_FLAG_N(r) (gpu_flag_n = (((UINT32)(r) >> 31) & 0x01));
310 #define RESET_FLAG_Z() gpu_flag_z = 0;
311 #define RESET_FLAG_N() gpu_flag_n = 0;
312 #define RESET_FLAG_C() gpu_flag_c = 0;
314 #define CLR_Z (gpu_flag_z = 0)
315 #define CLR_ZN (gpu_flag_z = gpu_flag_n = 0)
316 #define CLR_ZNC (gpu_flag_z = gpu_flag_n = gpu_flag_c = 0)
317 #define SET_Z(r) (gpu_flag_z = ((r) == 0))
318 #define SET_N(r) (gpu_flag_n = (((UINT32)(r) >> 31) & 0x01))
319 #define SET_C_ADD(a,b) (gpu_flag_c = ((UINT32)(b) > (UINT32)(~(a))))
320 #define SET_C_SUB(a,b) (gpu_flag_c = ((UINT32)(b) > (UINT32)(a)))
321 #define SET_ZN(r) SET_N(r); SET_Z(r)
322 #define SET_ZNC_ADD(a,b,r) SET_N(r); SET_Z(r); SET_C_ADD(a,b)
323 #define SET_ZNC_SUB(a,b,r) SET_N(r); SET_Z(r); SET_C_SUB(a,b)
325 uint32 gpu_convert_zero[32] =
326 { 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 };
328 uint8 * branch_condition_table = 0;
329 #define BRANCH_CONDITION(x) branch_condition_table[(x) + ((jaguar_flags & 7) << 5)]
331 uint32 gpu_opcode_use[64];
333 char * gpu_opcode_str[64]=
335 "add", "addc", "addq", "addqt",
336 "sub", "subc", "subq", "subqt",
337 "neg", "and", "or", "xor",
338 "not", "btst", "bset", "bclr",
339 "mult", "imult", "imultn", "resmac",
340 "imacn", "div", "abs", "sh",
341 "shlq", "shrq", "sha", "sharq",
342 "ror", "rorq", "cmp", "cmpq",
343 "sat8", "sat16", "move", "moveq",
344 "moveta", "movefa", "movei", "loadb",
345 "loadw", "load", "loadp", "load_r14_indexed",
346 "load_r15_indexed", "storeb", "storew", "store",
347 "storep", "store_r14_indexed","store_r15_indexed","move_pc",
348 "jump", "jr", "mmult", "mtoi",
349 "normi", "nop", "load_r14_ri", "load_r15_ri",
350 "store_r14_ri", "store_r15_ri", "sat24", "pack",
353 static uint32 gpu_in_exec = 0;
354 static uint32 gpu_releaseTimeSlice_flag = 0;
356 void gpu_releaseTimeslice(void)
358 gpu_releaseTimeSlice_flag = 1;
361 uint32 gpu_get_pc(void)
366 void build_branch_condition_table(void)
368 if (!branch_condition_table)
370 branch_condition_table = (uint8 *)malloc(32 * 8 * sizeof(branch_condition_table[0]));
372 if (branch_condition_table)
374 for(int i=0; i<8; i++)
376 for(int j=0; j<32; j++)
383 if (!(i & ZERO_FLAG))
386 if (i & (CARRY_FLAG << (j >> 4)))
389 if (!(i & (CARRY_FLAG << (j >> 4))))
391 branch_condition_table[i * 32 + j] = result;
399 // GPU byte access (read)
401 uint8 GPUReadByte(uint32 offset, uint32 who/*=UNKNOWN*/)
403 if (offset >= 0xF02000 && offset <= 0xF020FF)
404 WriteLog("GPU: ReadByte--Attempt to read from GPU register file by %s!\n", whoName[who]);
406 if ((offset >= GPU_WORK_RAM_BASE) && (offset < GPU_WORK_RAM_BASE+0x1000))
407 return gpu_ram_8[offset & 0xFFF];
408 else if ((offset >= GPU_CONTROL_RAM_BASE) && (offset < GPU_CONTROL_RAM_BASE+0x20))
410 uint32 data = GPUReadLong(offset & 0xFFFFFFFC, who);
412 if ((offset & 0x03) == 0)
414 else if ((offset & 0x03) == 1)
415 return (data >> 16) & 0xFF;
416 else if ((offset & 0x03) == 2)
417 return (data >> 8) & 0xFF;
418 else if ((offset & 0x03) == 3)
422 return JaguarReadByte(offset, who);
426 // GPU word access (read)
428 uint16 GPUReadWord(uint32 offset, uint32 who/*=UNKNOWN*/)
430 if (offset >= 0xF02000 && offset <= 0xF020FF)
431 WriteLog("GPU: ReadWord--Attempt to read from GPU register file by %s!\n", whoName[who]);
433 if ((offset >= GPU_WORK_RAM_BASE) && (offset < GPU_WORK_RAM_BASE+0x1000))
436 uint16 data = ((uint16)gpu_ram_8[offset] << 8) | (uint16)gpu_ram_8[offset+1];
439 else if ((offset >= GPU_CONTROL_RAM_BASE) && (offset < GPU_CONTROL_RAM_BASE+0x20))
441 // This looks and smells wrong...
442 // But it *might* be OK...
443 if (offset & 0x01) // Catch cases 1 & 3... (unaligned read)
444 return (GPUReadByte(offset, who) << 8) | GPUReadByte(offset+1, who);
446 uint32 data = GPUReadLong(offset & 0xFFFFFFFC, who);
448 if (offset & 0x02) // Cases 0 & 2...
449 return data & 0xFFFF;
454 //TEMP--Mirror of F03000? No. Writes only...
455 //if (offset >= 0xF0B000 && offset <= 0xF0BFFF)
456 //WriteLog("[GPUR16] --> Possible GPU RAM mirror access by %s!", whoName[who]);
458 return JaguarReadWord(offset, who);
462 // GPU dword access (read)
464 uint32 GPUReadLong(uint32 offset, uint32 who/*=UNKNOWN*/)
466 if (offset >= 0xF02000 && offset <= 0xF020FF)
467 WriteLog("GPU: ReadLong--Attempt to read from GPU register file by %s!\n", whoName[who]);
469 // if ((offset >= GPU_WORK_RAM_BASE) && (offset < GPU_WORK_RAM_BASE + 0x1000))
470 if ((offset >= GPU_WORK_RAM_BASE) && (offset <= GPU_WORK_RAM_BASE + 0x0FFC))
473 return ((uint32)gpu_ram_8[offset] << 24) | ((uint32)gpu_ram_8[offset+1] << 16)
474 | ((uint32)gpu_ram_8[offset+2] << 8) | (uint32)gpu_ram_8[offset+3];//*/
475 // return GET32(gpu_ram_8, offset);
477 // else if ((offset >= GPU_CONTROL_RAM_BASE) && (offset < GPU_CONTROL_RAM_BASE+0x20))
478 else if ((offset >= GPU_CONTROL_RAM_BASE) && (offset <= GPU_CONTROL_RAM_BASE + 0x1C))
484 gpu_flag_c = (gpu_flag_c ? 1 : 0);
485 gpu_flag_z = (gpu_flag_z ? 1 : 0);
486 gpu_flag_n = (gpu_flag_n ? 1 : 0);
488 gpu_flags = (gpu_flags & 0xFFFFFFF8) | (gpu_flag_n << 2) | (gpu_flag_c << 1) | gpu_flag_z;
490 return gpu_flags & 0xFFFFC1FF;
492 return gpu_matrix_control;
494 return gpu_pointer_to_matrix;
496 return gpu_data_organization;
505 default: // unaligned long read
507 WriteLog("GPU: Read32--unaligned 32 bit read at %08X by %s.\n", GPU_CONTROL_RAM_BASE + offset, whoName[who]);
512 //TEMP--Mirror of F03000? No. Writes only...
513 //if (offset >= 0xF0B000 && offset <= 0xF0BFFF)
514 // WriteLog("[GPUR32] --> Possible GPU RAM mirror access by %s!\n", whoName[who]);
515 /*if (offset >= 0xF1D000 && offset <= 0xF1DFFF)
516 WriteLog("[GPUR32] --> Reading from Wavetable ROM!\n");//*/
518 return (JaguarReadWord(offset, who) << 16) | JaguarReadWord(offset + 2, who);
522 // GPU byte access (write)
524 void GPUWriteByte(uint32 offset, uint8 data, uint32 who/*=UNKNOWN*/)
526 if (offset >= 0xF02000 && offset <= 0xF020FF)
527 WriteLog("GPU: WriteByte--Attempt to write to GPU register file by %s!\n", whoName[who]);
529 if ((offset >= GPU_WORK_RAM_BASE) && (offset <= GPU_WORK_RAM_BASE + 0x0FFF))
531 gpu_ram_8[offset & 0xFFF] = data;
533 //This is the same stupid worthless code that was in the DSP!!! AARRRGGGGHHHHH!!!!!!
536 m68k_end_timeslice();
537 dsp_releaseTimeslice();
541 else if ((offset >= GPU_CONTROL_RAM_BASE) && (offset <= GPU_CONTROL_RAM_BASE + 0x1F))
543 uint32 reg = offset & 0x1C;
544 int bytenum = offset & 0x03;
546 //This is definitely wrong!
547 if ((reg >= 0x1C) && (reg <= 0x1F))
548 gpu_div_control = (gpu_div_control & (~(0xFF << (bytenum << 3)))) | (data << (bytenum << 3));
551 uint32 old_data = GPUReadLong(offset & 0xFFFFFFC, who);
552 bytenum = 3 - bytenum; // convention motorola !!!
553 old_data = (old_data & (~(0xFF << (bytenum << 3)))) | (data << (bytenum << 3));
554 GPUWriteLong(offset & 0xFFFFFFC, old_data, who);
558 // WriteLog("gpu: writing %.2x at 0x%.8x\n",data,offset);
559 JaguarWriteByte(offset, data, who);
563 // GPU word access (write)
565 void GPUWriteWord(uint32 offset, uint16 data, uint32 who/*=UNKNOWN*/)
567 if (offset >= 0xF02000 && offset <= 0xF020FF)
568 WriteLog("GPU: WriteWord--Attempt to write to GPU register file by %s!\n", whoName[who]);
570 if ((offset >= GPU_WORK_RAM_BASE) && (offset <= GPU_WORK_RAM_BASE + 0x0FFE))
572 gpu_ram_8[offset & 0xFFF] = (data>>8) & 0xFF;
573 gpu_ram_8[(offset+1) & 0xFFF] = data & 0xFF;//*/
575 SET16(gpu_ram_8, offset, data);//*/
577 /*if (offset >= 0xF03214 && offset < 0xF0321F)
578 WriteLog("GPU: Writing WORD (%04X) to GPU RAM (%08X)...\n", data, offset);//*/
581 //This is the same stupid worthless code that was in the DSP!!! AARRRGGGGHHHHH!!!!!!
584 m68k_end_timeslice();
585 dsp_releaseTimeslice();
589 else if ((offset >= GPU_CONTROL_RAM_BASE) && (offset <= GPU_CONTROL_RAM_BASE + 0x1E))
591 if (offset & 0x01) // This is supposed to weed out unaligned writes, but does nothing...
594 WriteLog("GPU: Write16--unaligned write @ %08X [%04X]\n", offset, data);
599 //Dual locations in this range: $1C Divide unit remainder/Divide unit control (R/W)
600 //This just literally sucks.
601 if ((offset & 0x1C) == 0x1C)
603 //This doesn't look right either--handles cases 1, 2, & 3 all the same!
605 gpu_div_control = (gpu_div_control & 0xFFFF0000) | (data & 0xFFFF);
607 gpu_div_control = (gpu_div_control & 0x0000FFFF) | ((data & 0xFFFF) << 16);
611 //WriteLog("[GPU W16:%08X,%04X]", offset, data);
612 uint32 old_data = GPUReadLong(offset & 0xFFFFFFC, who);
614 old_data = (old_data & 0xFFFF0000) | (data & 0xFFFF);
616 old_data = (old_data & 0x0000FFFF) | ((data & 0xFFFF) << 16);
617 GPUWriteLong(offset & 0xFFFFFFC, old_data, who);
621 else if ((offset == GPU_WORK_RAM_BASE + 0x0FFF) || (GPU_CONTROL_RAM_BASE + 0x1F))
624 WriteLog("GPU: Write16--unaligned write @ %08X by %s [%04X]!\n", offset, whoName[who], data);
630 // Have to be careful here--this can cause an infinite loop!
631 JaguarWriteWord(offset, data, who);
635 // GPU dword access (write)
637 void GPUWriteLong(uint32 offset, uint32 data, uint32 who/*=UNKNOWN*/)
639 if (offset >= 0xF02000 && offset <= 0xF020FF)
640 WriteLog("GPU: WriteLong--Attempt to write to GPU register file by %s!\n", whoName[who]);
642 // if ((offset >= GPU_WORK_RAM_BASE) && (offset < GPU_WORK_RAM_BASE + 0x1000))
643 if ((offset >= GPU_WORK_RAM_BASE) && (offset <= GPU_WORK_RAM_BASE + 0x0FFC))
648 WriteLog("GPU: Write32--unaligned write @ %08X [%08X] by %s\n", offset, data, whoName[who]);
654 SET32(gpu_ram_8, offset, data);
657 // else if ((offset >= GPU_CONTROL_RAM_BASE) && (offset < GPU_CONTROL_RAM_BASE+0x20))
658 else if ((offset >= GPU_CONTROL_RAM_BASE) && (offset <= GPU_CONTROL_RAM_BASE + 0x1C))
665 bool IMASKCleared = (gpu_flags & IMASK) && !(data & IMASK);
667 gpu_flag_z = gpu_flags & ZERO_FLAG;
668 gpu_flag_c = (gpu_flags & CARRY_FLAG) >> 1;
669 gpu_flag_n = (gpu_flags & NEGA_FLAG) >> 2;
670 GPUUpdateRegisterBanks();
671 gpu_control &= ~((gpu_flags & CINT04FLAGS) >> 3); // Interrupt latch clear bits
672 //Writing here is only an interrupt enable--this approach is just plain wrong!
674 //This, however, is A-OK! ;-)
675 if (IMASKCleared) // If IMASK was cleared,
676 GPUHandleIRQs(); // see if any other interrupts need servicing!
678 if (gpu_flags & (INT_ENA0 | INT_ENA1 | INT_ENA2 | INT_ENA3 | INT_ENA4))
679 WriteLog("GPU: Interrupt enable set by %s! Bits: %02X\n", whoName[who], (gpu_flags >> 4) & 0x1F);
680 WriteLog("GPU: REGPAGE %s...\n", (gpu_flags & REGPAGE ? "set" : "cleared"));
685 gpu_matrix_control = data;
688 // This can only point to long aligned addresses
689 gpu_pointer_to_matrix = data & 0xFFFFFFFC;
692 gpu_data_organization = data;
697 WriteLog("GPU: %s setting GPU PC to %08X %s\n", whoName[who], gpu_pc, (GPU_RUNNING ? "(GPU is RUNNING!)" : ""));//*/
702 // uint32 gpu_was_running = GPU_RUNNING;
703 data &= ~0xF7C0; // Disable writes to INT_LAT0-4 & TOM version number
705 // check for GPU -> CPU interrupt
708 //WriteLog("GPU->CPU interrupt\n");
709 if (tom_irq_enabled(IRQ_GPU))
711 if ((tom_irq_enabled(IRQ_GPU)) && (jaguar_interrupt_handler_is_valid(64)))
713 tom_set_pending_gpu_int();
714 m68k_set_irq(7); // Set 68000 NMI
715 gpu_releaseTimeslice();
721 // check for CPU -> GPU interrupt #0
724 //WriteLog("CPU->GPU interrupt\n");
725 GPUSetIRQLine(0, ASSERT_LINE);
726 m68k_end_timeslice();
727 dsp_releaseTimeslice();
734 //WriteLog("asked to perform a single step (single step is %senabled)\n",(data&0x8)?"":"not ");
736 gpu_control = (gpu_control & 0xF7C0) | (data & (~0xF7C0));
738 // if gpu wasn't running but is now running, execute a few cycles
739 #ifndef GPU_SINGLE_STEPPING
740 /* if (!gpu_was_running && GPU_RUNNING)
743 WriteLog("GPU: Write32--About to do stupid braindead GPU execution for 200 cycles.\n");
748 #endif // GPU_DEBUG//*/
750 if (gpu_control & 0x18)
752 #endif // #ifndef GPU_SINGLE_STEPPING
754 WriteLog("Write to GPU CTRL by %s: %08X ", whoName[who], data);
756 WriteLog(" --> Starting to run at %08X by %s...", gpu_pc, whoName[who]);
758 WriteLog(" --> Stopped by %s! (GPU_PC: %08X)", whoName[who], gpu_pc);
762 // GPUDumpDisassembly();
765 if (gpu_pc == 0xF035D8)
767 // GPUDumpDisassembly();
770 gpu_control &= 0xFFFFFFFE; // Don't run it and let's see what happens!
771 //Hmm. Seems to lock up when going into the demo...
772 //Try to disable the collision altogether!
775 extern int effect_start5;
776 static bool finished = false;
777 //if (GPU_RUNNING && effect_start5 && !finished)
778 if (GPU_RUNNING && effect_start5 && gpu_pc == 0xF035D8)
780 // Let's do a dump of $6528!
781 /* uint32 numItems = JaguarReadWord(0x6BD6);
782 WriteLog("\nDump of $6528: %u items.\n\n", numItems);
783 for(int i=0; i<numItems*3*4; i+=3*4)
785 WriteLog("\t%04X: %08X %08X %08X -> ", 0x6528+i, JaguarReadLong(0x6528+i),
786 JaguarReadLong(0x6528+i+4), JaguarReadLong(0x6528+i+8));
787 uint16 link = JaguarReadWord(0x6528+i+8+2);
788 for(int j=0; j<40; j+=4)
789 WriteLog("%08X ", JaguarReadLong(link + j));
793 // Let's try a manual blit here...
794 //This isn't working the way it should! !!! FIX !!!
795 //Err, actually, it is.
796 // NOW, it works right! Problem solved!!! It's a blitter bug!
797 /* uint32 src = 0x4D54, dst = 0xF03000, width = 10 * 4;
798 for(int y=0; y<127; y++)
800 for(int x=0; x<2; x++)
802 JaguarWriteLong(dst, JaguarReadLong(src));
807 src += width - (2 * 4);
811 WriteLog("\nGPU: About to execute collision detection code.\n\n");//*/
813 /* WriteLog("\nGPU: About to execute collision detection code. Data @ 4D54:\n\n");
815 for(int i=0x004D54; i<0x004D54+2048; i++)
817 WriteLog("%02X ", JaguarReadByte(i));
825 WriteLog("\n\nData @ F03000:\n\n");
827 for(int i=0xF03000; i<0xF03200; i++)
829 WriteLog("%02X ", JaguarReadByte(i));
843 /*if (!GPU_RUNNING && finished)
845 WriteLog("\nGPU: Finished collision detection code. Exiting!\n\n");
850 // (?) If we're set running by the M68K (or DSP?) then end its timeslice to
851 // allow the GPU a chance to run...
852 // Yes! This partially fixed Trevor McFur...
854 m68k_end_timeslice();
861 gpu_div_control = data;
863 // default: // unaligned long write
870 // JaguarWriteWord(offset, (data >> 16) & 0xFFFF, who);
871 // JaguarWriteWord(offset+2, data & 0xFFFF, who);
872 // We're a 32-bit processor, we can do a long write...!
873 JaguarWriteLong(offset, data, who);
877 // Change register banks if necessary
879 void GPUUpdateRegisterBanks(void)
881 int bank = (gpu_flags & REGPAGE); // REGPAGE bit
883 if (gpu_flags & IMASK) // IMASK bit
884 bank = 0; // IMASK forces main bank to be bank 0
887 gpu_reg = gpu_reg_bank_1, gpu_alternate_reg = gpu_reg_bank_0;
889 gpu_reg = gpu_reg_bank_0, gpu_alternate_reg = gpu_reg_bank_1;
892 void GPUHandleIRQs(void)
894 // Bail out if we're already in an interrupt!
895 if (gpu_flags & IMASK)
898 // Get the interrupt latch & enable bits
899 uint32 bits = (gpu_control >> 6) & 0x1F, mask = (gpu_flags >> 4) & 0x1F;
901 // Bail out if latched interrupts aren't enabled
906 // Determine which interrupt to service
907 uint32 which = 0; //Isn't there a #pragma to disable this warning???
920 WriteLog("GPU: Generating IRQ #%i\n", which);
922 // set the interrupt flag
924 GPUUpdateRegisterBanks();
926 // subqt #4,r31 ; pre-decrement stack pointer
927 // move pc,r30 ; address of interrupted code
928 // store r30,(r31) ; store return address
930 GPUWriteLong(gpu_reg[31], gpu_pc - 2, GPU);
932 // movei #service_address,r30 ; pointer to ISR entry
933 // jump (r30) ; jump to ISR
935 gpu_pc = gpu_reg[30] = GPU_WORK_RAM_BASE + (which * 0x10);
938 void GPUSetIRQLine(int irqline, int state)
941 WriteLog("GPU: Setting GPU IRQ line #%i\n", irqline);
943 uint32 mask = 0x0040 << irqline;
944 gpu_control &= ~mask; // Clear the interrupt latch
948 gpu_control |= mask; // Assert the interrupt latch
949 GPUHandleIRQs(); // And handle the interrupt...
953 //TEMPORARY: Testing only!
959 memory_malloc_secure((void **)&gpu_ram_8, 0x1000, "GPU work RAM");
960 memory_malloc_secure((void **)&gpu_reg_bank_0, 32 * sizeof(int32), "GPU bank 0 regs");
961 memory_malloc_secure((void **)&gpu_reg_bank_1, 32 * sizeof(int32), "GPU bank 1 regs");
963 build_branch_condition_table();
967 //TEMPORARY: Testing only!
974 // GPU registers (directly visible)
975 gpu_flags = 0x00000000;
976 gpu_matrix_control = 0x00000000;
977 gpu_pointer_to_matrix = 0x00000000;
978 gpu_data_organization = 0xFFFFFFFF;
980 gpu_control = 0x00002800; // Correctly sets this as TOM Rev. 2
981 gpu_hidata = 0x00000000;
982 gpu_remain = 0x00000000; // These two registers are RO/WO
983 gpu_div_control = 0x00000000;
985 // GPU internal register
986 gpu_acc = 0x00000000;
988 gpu_reg = gpu_reg_bank_0;
989 gpu_alternate_reg = gpu_reg_bank_1;
991 for(int i=0; i<32; i++)
992 gpu_reg[i] = gpu_alternate_reg[i] = 0x00000000;
995 memset(gpu_ram_8, 0xFF, 0x1000);
997 //not needed GPUInterruptPending = false;
1001 uint32 gpu_read_pc(void)
1006 void gpu_reset_stats(void)
1008 for(uint32 i=0; i<64; i++)
1009 gpu_opcode_use[i] = 0;
1010 WriteLog("--> GPU stats were reset!\n");
1013 void GPUDumpDisassembly(void)
1017 WriteLog("\n---[GPU code at 00F03000]---------------------------\n");
1018 uint32 j = 0xF03000;
1019 while (j <= 0xF03FFF)
1022 j += dasmjag(JAGUAR_GPU, buffer, j);
1023 WriteLog("\t%08X: %s\n", oldj, buffer);
1027 void GPUDumpRegisters(void)
1029 WriteLog("\n---[GPU flags: NCZ %d%d%d]-----------------------\n", gpu_flag_n, gpu_flag_c, gpu_flag_z);
1030 WriteLog("\nRegisters bank 0\n");
1031 for(int j=0; j<8; j++)
1033 WriteLog("\tR%02i = %08X R%02i = %08X R%02i = %08X R%02i = %08X\n",
1034 (j << 2) + 0, gpu_reg_bank_0[(j << 2) + 0],
1035 (j << 2) + 1, gpu_reg_bank_0[(j << 2) + 1],
1036 (j << 2) + 2, gpu_reg_bank_0[(j << 2) + 2],
1037 (j << 2) + 3, gpu_reg_bank_0[(j << 2) + 3]);
1039 WriteLog("Registers bank 1\n");
1040 for(int j=0; j<8; j++)
1042 WriteLog("\tR%02i = %08X R%02i = %08X R%02i = %08X R%02i = %08X\n",
1043 (j << 2) + 0, gpu_reg_bank_1[(j << 2) + 0],
1044 (j << 2) + 1, gpu_reg_bank_1[(j << 2) + 1],
1045 (j << 2) + 2, gpu_reg_bank_1[(j << 2) + 2],
1046 (j << 2) + 3, gpu_reg_bank_1[(j << 2) + 3]);
1050 void GPUDumpMemory(void)
1052 WriteLog("\n---[GPU data at 00F03000]---------------------------\n");
1053 for(int i=0; i<0xFFF; i+=4)
1054 WriteLog("\t%08X: %02X %02X %02X %02X\n", 0xF03000+i, gpu_ram_8[i],
1055 gpu_ram_8[i+1], gpu_ram_8[i+2], gpu_ram_8[i+3]);
1060 WriteLog("GPU: Stopped at PC=%08X (GPU %s running)\n", (unsigned int)gpu_pc, GPU_RUNNING ? "was" : "wasn't");
1062 // Get the interrupt latch & enable bits
1063 uint8 bits = (gpu_control >> 6) & 0x1F, mask = (gpu_flags >> 4) & 0x1F;
1064 WriteLog("GPU: Latch bits = %02X, enable bits = %02X\n", bits, mask);
1067 GPUDumpDisassembly();
1069 WriteLog("\nGPU opcodes use:\n");
1070 for(int i=0; i<64; i++)
1072 if (gpu_opcode_use[i])
1073 WriteLog("\t%17s %lu\n", gpu_opcode_str[i], gpu_opcode_use[i]);
1077 memory_free(gpu_ram_8);
1078 memory_free(gpu_reg_bank_0);
1079 memory_free(gpu_reg_bank_1);
1083 // Main GPU execution core
1085 static int testCount = 1;
1087 static bool tripwire = false;
1088 void gpu_exec(int32 cycles)
1093 #ifdef GPU_SINGLE_STEPPING
1094 if (gpu_control & 0x18)
1097 gpu_control &= ~0x10;
1101 gpu_releaseTimeSlice_flag = 0;
1104 while (cycles > 0 && GPU_RUNNING)
1106 if (gpu_ram_8[0x054] == 0x98 && gpu_ram_8[0x055] == 0x0A && gpu_ram_8[0x056] == 0x03
1107 && gpu_ram_8[0x057] == 0x00 && gpu_ram_8[0x058] == 0x00 && gpu_ram_8[0x059] == 0x00)
1109 if (gpu_pc == 0xF03000)
1111 extern uint32 starCount;
1113 /* WriteLog("GPU: Starting starfield generator... Dump of [R03=%08X]:\n", gpu_reg_bank_0[03]);
1114 uint32 base = gpu_reg_bank_0[3];
1115 for(uint32 i=0; i<0x100; i+=16)
1117 WriteLog("%02X: ", i);
1118 for(uint32 j=0; j<16; j++)
1120 WriteLog("%02X ", JaguarReadByte(base + i + j));
1125 // if (gpu_pc == 0xF03)
1129 /*if (gpu_pc == 0xF03B9E && gpu_reg_bank_0[01] == 0)
1132 WriteLog("GPU: Starting disassembly log...\n");
1135 /*if (gpu_pc == 0xF0359A)
1140 /* gpu_flag_c = (gpu_flag_c ? 1 : 0);
1141 gpu_flag_z = (gpu_flag_z ? 1 : 0);
1142 gpu_flag_n = (gpu_flag_n ? 1 : 0);*/
1144 uint16 opcode = GPUReadWord(gpu_pc, GPU);
1145 uint32 index = opcode >> 10;
1146 gpu_instruction = opcode; // Added for GPU #3...
1147 gpu_opcode_first_parameter = (opcode >> 5) & 0x1F;
1148 gpu_opcode_second_parameter = opcode & 0x1F;
1149 /*if (gpu_pc == 0xF03BE8)
1150 WriteLog("Start of OP frame write...\n");
1151 if (gpu_pc == 0xF03EEE)
1152 WriteLog("--> Writing BRANCH object ---\n");
1153 if (gpu_pc == 0xF03F62)
1154 WriteLog("--> Writing BITMAP object ***\n");//*/
1155 /*if (gpu_pc == 0xF03546)
1157 WriteLog("\n--> GPU PC: F03546\n");
1159 GPUDumpDisassembly();
1161 /*if (gpu_pc == 0xF033F6)
1163 WriteLog("\n--> GPU PC: F033F6\n");
1165 GPUDumpDisassembly();
1167 /*if (gpu_pc == 0xF033CC)
1169 WriteLog("\n--> GPU PC: F033CC\n");
1171 GPUDumpDisassembly();
1173 /*if (gpu_pc == 0xF033D6)
1175 WriteLog("\n--> GPU PC: F033D6 (#%d)\n", testCount++);
1179 /*if (gpu_pc == 0xF033D8)
1181 WriteLog("\n--> GPU PC: F033D8 (#%d)\n", testCount++);
1185 /*if (gpu_pc == 0xF0358E)
1187 WriteLog("\n--> GPU PC: F0358E (#%d)\n", testCount++);
1191 /*if (gpu_pc == 0xF034CA)
1193 WriteLog("\n--> GPU PC: F034CA (#%d)\n", testCount++);
1196 /*if (gpu_pc == 0xF034CA)
1198 len = gpu_reg[1] + 4;//, r9save = gpu_reg[9];
1199 WriteLog("\nAbout to subtract [#%d] (R14=%08X, R15=%08X, R9=%08X):\n ", testCount++, gpu_reg[14], gpu_reg[15], gpu_reg[9]);
1200 for(int i=0; i<len; i+=4)
1201 WriteLog(" %08X", GPUReadLong(gpu_reg[15]+i));
1203 for(int i=0; i<len; i+=4)
1204 WriteLog(" %08X", GPUReadLong(gpu_reg[14]+i));
1207 if (gpu_pc == 0xF034DE)
1209 WriteLog("\nSubtracted! (R14=%08X, R15=%08X):\n ", gpu_reg[14], gpu_reg[15]);
1210 for(int i=0; i<len; i+=4)
1211 WriteLog(" %08X", GPUReadLong(gpu_reg[15]+i));
1213 for(int i=0; i<len; i+=4)
1214 WriteLog(" %08X", GPUReadLong(gpu_reg[14]+i));
1216 for(int i=0; i<len; i+=4)
1217 WriteLog(" --------");
1219 for(int i=0; i<len; i+=4)
1220 WriteLog(" %08X", GPUReadLong(gpu_reg[9]+4+i));
1223 /*if (gpu_pc == 0xF035C8)
1225 WriteLog("\n--> GPU PC: F035C8 (#%d)\n", testCount++);
1227 GPUDumpDisassembly();
1232 // gpu_reset_stats();
1233 static char buffer[512];
1234 dasmjag(JAGUAR_GPU, buffer, gpu_pc);
1235 WriteLog("GPU: [%08X] %s (RM=%08X, RN=%08X) -> ", gpu_pc, buffer, RM, RN);
1237 //$E400 -> 1110 01 -> $39 -> 57
1240 gpu_opcode[index]();
1242 // gpu2_opcode[index]();
1244 //GPU #3 (Doesn't show ATARI logo! #1 & #2 do...)
1246 // gpu3_opcode[index]();
1249 //GPU: [00F03548] jr nz,00F03560 (0xd561) (RM=00F03114, RN=00000004) -> --> JR: Branch taken.
1250 /*static bool firstTime = true;
1251 if (gpu_pc == 0xF03548 && firstTime)
1254 // firstTime = false;
1256 //static char buffer[512];
1258 //while (k<0xF0356C)
1261 //k += dasmjag(JAGUAR_GPU, buffer, k);
1262 //WriteLog("GPU: [%08X] %s\n", oldk, buffer);
1264 // gpu_start_log = 1;
1266 //GPU: [00F0354C] jump nz,(r29) (0xd3a1) (RM=00F03314, RN=00000004) -> (RM=00F03314, RN=00000004)
1267 /*if (gpu_pc == 0xF0354C)
1268 gpu_flag_z = 0;//, gpu_start_log = 1;//*/
1270 cycles -= gpu_opcode_cycles[index];
1271 gpu_opcode_use[index]++;
1273 WriteLog("(RM=%08X, RN=%08X)\n", RM, RN);//*/
1274 if ((gpu_pc < 0xF03000 || gpu_pc > 0xF03FFF) && !tripwire)
1276 WriteLog("GPU: Executing outside local RAM! GPU_PC: %08X\n", gpu_pc);
1289 GPU opcodes use (offset punch--vertically below bad guy):
1311 load_r14_indexed 1183
1312 load_r15_indexed 1125
1315 store_r14_indexed 320
1323 static void gpu_opcode_jump(void)
1326 char * condition[32] =
1327 { "T", "nz", "z", "???", "nc", "nc nz", "nc z", "???", "c", "c nz",
1328 "c z", "???", "???", "???", "???", "???", "???", "???", "???",
1329 "???", "nn", "nn nz", "nn z", "???", "n", "n nz", "n z", "???",
1330 "???", "???", "???", "F" };
1332 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);
1335 /* gpu_flag_c = (gpu_flag_c ? 1 : 0);
1336 gpu_flag_z = (gpu_flag_z ? 1 : 0);
1337 gpu_flag_n = (gpu_flag_n ? 1 : 0);*/
1338 // KLUDGE: Used by BRANCH_CONDITION
1339 uint32 jaguar_flags = (gpu_flag_n << 2) | (gpu_flag_c << 1) | gpu_flag_z;
1341 if (BRANCH_CONDITION(IMM_2))
1345 WriteLog("Branched!\n");
1348 WriteLog(" --> JUMP: Branch taken.\n");
1349 uint32 delayed_pc = RM;
1351 gpu_pc = delayed_pc;
1352 /* uint16 opcode = GPUReadWord(gpu_pc, GPU);
1353 gpu_opcode_first_parameter = (opcode >> 5) & 0x1F;
1354 gpu_opcode_second_parameter = opcode & 0x1F;
1356 gpu_pc = delayed_pc;
1357 gpu_opcode[opcode>>10]();//*/
1362 WriteLog("Branch NOT taken.\n");
1366 static void gpu_opcode_jr(void)
1369 char * condition[32] =
1370 { "T", "nz", "z", "???", "nc", "nc nz", "nc z", "???", "c", "c nz",
1371 "c z", "???", "???", "???", "???", "???", "???", "???", "???",
1372 "???", "nn", "nn nz", "nn z", "???", "n", "n nz", "n z", "???",
1373 "???", "???", "???", "F" };
1375 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);
1377 /* if (CONDITION(jaguar.op & 31))
1379 INT32 r1 = (INT8)((jaguar.op >> 2) & 0xF8) >> 2;
1380 UINT32 newpc = jaguar.PC + r1;
1382 jaguar.op = ROPCODE(jaguar.PC);
1384 (*jaguar.table[jaguar.op >> 10])();
1386 jaguar_icount -= 3; // 3 wait states guaranteed
1389 /* gpu_flag_n = (gpu_flag_n ? 1 : 0);
1390 gpu_flag_c = (gpu_flag_c ? 1 : 0);
1391 gpu_flag_z = (gpu_flag_z ? 1 : 0);*/
1392 // KLUDGE: Used by BRANCH_CONDITION
1393 uint32 jaguar_flags = (gpu_flag_n << 2) | (gpu_flag_c << 1) | gpu_flag_z;
1395 if (BRANCH_CONDITION(IMM_2))
1399 WriteLog("Branched!\n");
1402 WriteLog(" --> JR: Branch taken.\n");
1403 int32 offset = (IMM_1 & 0x10 ? 0xFFFFFFF0 | IMM_1 : IMM_1); // Sign extend IMM_1
1404 int32 delayed_pc = gpu_pc + (offset * 2);
1406 gpu_pc = delayed_pc;
1407 /* uint16 opcode = GPUReadWord(gpu_pc, GPU);
1408 gpu_opcode_first_parameter = (opcode >> 5) & 0x1F;
1409 gpu_opcode_second_parameter = opcode & 0x1F;
1411 gpu_pc = delayed_pc;
1412 gpu_opcode[opcode>>10]();//*/
1417 WriteLog("Branch NOT taken.\n");
1421 static void gpu_opcode_add(void)
1425 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);
1427 UINT32 res = RN + RM;
1428 CLR_ZNC; SET_ZNC_ADD(RN, RM, res);
1432 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);
1436 static void gpu_opcode_addc(void)
1440 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);
1442 /* int dreg = jaguar.op & 31;
1443 UINT32 r1 = jaguar.r[(jaguar.op >> 5) & 31];
1444 UINT32 r2 = jaguar.r[dreg];
1445 UINT32 res = r2 + r1 + ((jaguar.FLAGS >> 1) & 1);
1446 jaguar.r[dreg] = res;
1447 CLR_ZNC; SET_ZNC_ADD(r2,r1,res);*/
1449 UINT32 res = RN + RM + gpu_flag_c;
1450 UINT32 carry = gpu_flag_c;
1451 // SET_ZNC_ADD(RN, RM, res); //???BUG??? Yes!
1452 SET_ZNC_ADD(RN + carry, RM, res);
1453 // SET_ZNC_ADD(RN, RM + carry, res);
1457 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);
1461 static void gpu_opcode_addq(void)
1465 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);
1467 UINT32 r1 = gpu_convert_zero[IMM_1];
1468 UINT32 res = RN + r1;
1469 CLR_ZNC; SET_ZNC_ADD(RN, r1, res);
1473 WriteLog("[NCZ:%u%u%u, R%02u=%08X]\n", gpu_flag_n, gpu_flag_c, gpu_flag_z, IMM_2, RN);
1477 static void gpu_opcode_addqt(void)
1479 #ifdef GPU_DIS_ADDQT
1481 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);
1483 RN += gpu_convert_zero[IMM_1];
1484 #ifdef GPU_DIS_ADDQT
1486 WriteLog("[NCZ:%u%u%u, R%02u=%08X]\n", gpu_flag_n, gpu_flag_c, gpu_flag_z, IMM_2, RN);
1490 static void gpu_opcode_sub(void)
1494 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);
1496 UINT32 res = RN - RM;
1497 SET_ZNC_SUB(RN, RM, res);
1501 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);
1505 static void gpu_opcode_subc(void)
1509 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);
1511 UINT32 res = RN - RM - gpu_flag_c;
1512 UINT32 borrow = gpu_flag_c;
1513 // SET_ZNC_SUB(RN, RM, res); //???BUG??? YES!!!
1514 //No matter how you do it, there is a problem. With below, it's 0-0 with carry,
1515 //and the one below it it's FFFFFFFF - FFFFFFFF with carry... !!! FIX !!!
1516 // SET_ZNC_SUB(RN - borrow, RM, res);
1517 SET_ZNC_SUB(RN, RM + borrow, res);
1521 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);
1525 N = 5, M = 3, 3 - 5 = -2, C = 1... Or, in our case:
1526 N = 0, M = 1, 0 - 1 = -1, C = 0!
1528 #define SET_C_SUB(a,b) (gpu_flag_c = ((UINT32)(b) > (UINT32)(a)))
1529 #define SET_ZN(r) SET_N(r); SET_Z(r)
1530 #define SET_ZNC_ADD(a,b,r) SET_N(r); SET_Z(r); SET_C_ADD(a,b)
1531 #define SET_ZNC_SUB(a,b,r) SET_N(r); SET_Z(r); SET_C_SUB(a,b)
1533 static void gpu_opcode_subq(void)
1537 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);
1539 UINT32 r1 = gpu_convert_zero[IMM_1];
1540 UINT32 res = RN - r1;
1541 SET_ZNC_SUB(RN, r1, res);
1545 WriteLog("[NCZ:%u%u%u, R%02u=%08X]\n", gpu_flag_n, gpu_flag_c, gpu_flag_z, IMM_2, RN);
1549 static void gpu_opcode_subqt(void)
1551 #ifdef GPU_DIS_SUBQT
1553 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);
1555 RN -= gpu_convert_zero[IMM_1];
1556 #ifdef GPU_DIS_SUBQT
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_cmp(void)
1566 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);
1568 UINT32 res = RN - RM;
1569 SET_ZNC_SUB(RN, RM, res);
1572 WriteLog("[NCZ:%u%u%u]\n", gpu_flag_n, gpu_flag_c, gpu_flag_z);
1576 static void gpu_opcode_cmpq(void)
1578 static int32 sqtable[32] =
1579 { 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 };
1582 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);
1584 UINT32 r1 = sqtable[IMM_1 & 0x1F]; // I like this better -> (INT8)(jaguar.op >> 2) >> 3;
1585 UINT32 res = RN - r1;
1586 SET_ZNC_SUB(RN, r1, res);
1589 WriteLog("[NCZ:%u%u%u]\n", gpu_flag_n, gpu_flag_c, gpu_flag_z);
1593 static void gpu_opcode_and(void)
1597 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);
1603 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);
1607 static void gpu_opcode_or(void)
1611 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);
1617 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);
1621 static void gpu_opcode_xor(void)
1625 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);
1631 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);
1635 static void gpu_opcode_not(void)
1639 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);
1645 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);
1649 static void gpu_opcode_move_pc(void)
1651 #ifdef GPU_DIS_MOVEPC
1653 WriteLog("%06X: MOVE PC, R%02u [NCZ:%u%u%u, PC=%08X, R%02u=%08X] -> ", gpu_pc-2, IMM_2, gpu_flag_n, gpu_flag_c, gpu_flag_z, gpu_pc-2, IMM_2, RN);
1655 // Should be previous PC--this might not always be previous instruction!
1656 // Then again, this will point right at the *current* instruction, i.e., MOVE PC,R!
1658 #ifdef GPU_DIS_MOVEPC
1660 WriteLog("[NCZ:%u%u%u, R%02u=%08X]\n", gpu_flag_n, gpu_flag_c, gpu_flag_z, IMM_2, RN);
1664 static void gpu_opcode_sat8(void)
1668 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);
1670 RN = ((int32)RN < 0 ? 0 : (RN > 0xFF ? 0xFF : RN));
1674 WriteLog("[NCZ:%u%u%u, R%02u=%08X]\n", gpu_flag_n, gpu_flag_c, gpu_flag_z, IMM_2, RN);
1678 static void gpu_opcode_sat16(void)
1680 RN = ((int32)RN < 0 ? 0 : (RN > 0xFFFF ? 0xFFFF : RN));
1684 static void gpu_opcode_sat24(void)
1686 RN = ((int32)RN < 0 ? 0 : (RN > 0xFFFFFF ? 0xFFFFFF : RN));
1690 static void gpu_opcode_store_r14_indexed(void)
1692 #ifdef GPU_DIS_STORE14I
1694 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));
1696 GPUWriteLong(gpu_reg[14] + (gpu_convert_zero[IMM_1] << 2), RN, GPU);
1699 static void gpu_opcode_store_r15_indexed(void)
1701 #ifdef GPU_DIS_STORE15I
1703 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));
1705 GPUWriteLong(gpu_reg[15] + (gpu_convert_zero[IMM_1] << 2), RN, GPU);
1708 static void gpu_opcode_load_r14_ri(void)
1710 #ifdef GPU_DIS_LOAD14R
1712 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);
1714 RN = GPUReadLong(gpu_reg[14] + RM, GPU);
1715 #ifdef GPU_DIS_LOAD14R
1717 WriteLog("[NCZ:%u%u%u, R%02u=%08X]\n", gpu_flag_n, gpu_flag_c, gpu_flag_z, IMM_2, RN);
1721 static void gpu_opcode_load_r15_ri(void)
1723 #ifdef GPU_DIS_LOAD15R
1725 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);
1727 RN = GPUReadLong(gpu_reg[15] + RM, GPU);
1728 #ifdef GPU_DIS_LOAD15R
1730 WriteLog("[NCZ:%u%u%u, R%02u=%08X]\n", gpu_flag_n, gpu_flag_c, gpu_flag_z, IMM_2, RN);
1734 static void gpu_opcode_store_r14_ri(void)
1736 #ifdef GPU_DIS_STORE14R
1738 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]);
1740 GPUWriteLong(gpu_reg[14] + RM, RN, GPU);
1743 static void gpu_opcode_store_r15_ri(void)
1745 #ifdef GPU_DIS_STORE15R
1747 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]);
1749 GPUWriteLong(gpu_reg[15] + RM, RN, GPU);
1752 static void gpu_opcode_nop(void)
1756 WriteLog("%06X: NOP [NCZ:%u%u%u]\n", gpu_pc-2, gpu_flag_n, gpu_flag_c, gpu_flag_z);
1760 static void gpu_opcode_pack(void)
1764 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);
1768 //BUG! if (RM == 0) // Pack
1769 if (IMM_1 == 0) // Pack
1770 RN = ((val >> 10) & 0x0000F000) | ((val >> 5) & 0x00000F00) | (val & 0x000000FF);
1772 RN = ((val & 0x0000F000) << 10) | ((val & 0x00000F00) << 5) | (val & 0x000000FF);
1775 WriteLog("[NCZ:%u%u%u, R%02u=%08X]\n", gpu_flag_n, gpu_flag_c, gpu_flag_z, IMM_2, RN);
1779 static void gpu_opcode_storeb(void)
1781 #ifdef GPU_DIS_STOREB
1783 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);
1786 // Would appear to be so...!
1787 if ((RM >= 0xF03000) && (RM <= 0xF03FFF))
1788 GPUWriteLong(RM, RN & 0xFF, GPU);
1790 JaguarWriteByte(RM, RN, GPU);
1793 static void gpu_opcode_storew(void)
1795 #ifdef GPU_DIS_STOREW
1797 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);
1799 if ((RM >= 0xF03000) && (RM <= 0xF03FFF))
1800 GPUWriteLong(RM, RN & 0xFFFF, GPU);
1802 JaguarWriteWord(RM, RN, GPU);
1805 static void gpu_opcode_store(void)
1807 #ifdef GPU_DIS_STORE
1809 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);
1811 GPUWriteLong(RM, RN, GPU);
1814 static void gpu_opcode_storep(void)
1816 GPUWriteLong(RM + 0, gpu_hidata, GPU);
1817 GPUWriteLong(RM + 4, RN, GPU);
1820 static void gpu_opcode_loadb(void)
1822 #ifdef GPU_DIS_LOADB
1824 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);
1826 if ((RM >= 0xF03000) && (RM <= 0xF03FFF))
1827 RN = GPUReadLong(RM, GPU) & 0xFF;
1829 RN = JaguarReadByte(RM, GPU);
1830 #ifdef GPU_DIS_LOADB
1832 WriteLog("[NCZ:%u%u%u, R%02u=%08X]\n", gpu_flag_n, gpu_flag_c, gpu_flag_z, IMM_2, RN);
1836 static void gpu_opcode_loadw(void)
1838 #ifdef GPU_DIS_LOADW
1840 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);
1842 if ((RM >= 0xF03000) && (RM <= 0xF03FFF))
1843 RN = GPUReadLong(RM, GPU) & 0xFFFF;
1845 RN = JaguarReadWord(RM, GPU);
1846 #ifdef GPU_DIS_LOADW
1848 WriteLog("[NCZ:%u%u%u, R%02u=%08X]\n", gpu_flag_n, gpu_flag_c, gpu_flag_z, IMM_2, RN);
1852 static void gpu_opcode_load(void)
1856 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);
1858 RN = GPUReadLong(RM, GPU);
1861 WriteLog("[NCZ:%u%u%u, R%02u=%08X]\n", gpu_flag_n, gpu_flag_c, gpu_flag_z, IMM_2, RN);
1865 static void gpu_opcode_loadp(void)
1867 gpu_hidata = GPUReadLong(RM + 0, GPU);
1868 RN = GPUReadLong(RM + 4, GPU);
1871 static void gpu_opcode_load_r14_indexed(void)
1873 #ifdef GPU_DIS_LOAD14I
1875 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);
1877 RN = GPUReadLong(gpu_reg[14] + (gpu_convert_zero[IMM_1] << 2), GPU);
1878 #ifdef GPU_DIS_LOAD14I
1880 WriteLog("[NCZ:%u%u%u, R%02u=%08X]\n", gpu_flag_n, gpu_flag_c, gpu_flag_z, IMM_2, RN);
1884 static void gpu_opcode_load_r15_indexed(void)
1886 #ifdef GPU_DIS_LOAD15I
1888 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);
1890 RN = GPUReadLong(gpu_reg[15] + (gpu_convert_zero[IMM_1] << 2), GPU);
1891 #ifdef GPU_DIS_LOAD15I
1893 WriteLog("[NCZ:%u%u%u, R%02u=%08X]\n", gpu_flag_n, gpu_flag_c, gpu_flag_z, IMM_2, RN);
1897 static void gpu_opcode_movei(void)
1899 #ifdef GPU_DIS_MOVEI
1901 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);
1903 // This instruction is followed by 32-bit value in LSW / MSW format...
1904 RN = (uint32)GPUReadWord(gpu_pc, GPU) | ((uint32)GPUReadWord(gpu_pc + 2, GPU) << 16);
1906 #ifdef GPU_DIS_MOVEI
1908 WriteLog("[NCZ:%u%u%u, R%02u=%08X]\n", gpu_flag_n, gpu_flag_c, gpu_flag_z, IMM_2, RN);
1912 static void gpu_opcode_moveta(void)
1914 #ifdef GPU_DIS_MOVETA
1916 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);
1919 #ifdef GPU_DIS_MOVETA
1921 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);
1925 static void gpu_opcode_movefa(void)
1927 #ifdef GPU_DIS_MOVEFA
1929 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);
1932 #ifdef GPU_DIS_MOVEFA
1934 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);
1938 static void gpu_opcode_move(void)
1942 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);
1947 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);
1951 static void gpu_opcode_moveq(void)
1953 #ifdef GPU_DIS_MOVEQ
1955 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);
1958 #ifdef GPU_DIS_MOVEQ
1960 WriteLog("[NCZ:%u%u%u, R%02u=%08X]\n", gpu_flag_n, gpu_flag_c, gpu_flag_z, IMM_2, RN);
1964 static void gpu_opcode_resmac(void)
1969 static void gpu_opcode_imult(void)
1971 #ifdef GPU_DIS_IMULT
1973 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);
1975 RN = (int16)RN * (int16)RM;
1977 #ifdef GPU_DIS_IMULT
1979 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);
1983 static void gpu_opcode_mult(void)
1987 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);
1989 RN = (uint16)RM * (uint16)RN;
1993 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);
1997 static void gpu_opcode_bclr(void)
2001 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);
2003 UINT32 res = RN & ~(1 << IMM_1);
2008 WriteLog("[NCZ:%u%u%u, R%02u=%08X]\n", gpu_flag_n, gpu_flag_c, gpu_flag_z, IMM_2, RN);
2012 static void gpu_opcode_btst(void)
2016 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);
2018 gpu_flag_z = (~RN >> IMM_1) & 1;
2021 WriteLog("[NCZ:%u%u%u, R%02u=%08X]\n", gpu_flag_n, gpu_flag_c, gpu_flag_z, IMM_2, RN);
2025 static void gpu_opcode_bset(void)
2029 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);
2031 UINT32 res = RN | (1 << IMM_1);
2036 WriteLog("[NCZ:%u%u%u, R%02u=%08X]\n", gpu_flag_n, gpu_flag_c, gpu_flag_z, IMM_2, RN);
2040 static void gpu_opcode_imacn(void)
2042 uint32 res = (int16)RM * (int16)(RN);
2046 static void gpu_opcode_mtoi(void)
2049 uint32 res = RN = (((INT32)_RM >> 8) & 0xFF800000) | (_RM & 0x007FFFFF);
2053 static void gpu_opcode_normi(void)
2060 while ((_RM & 0xFFC00000) == 0)
2065 while ((_RM & 0xFF800000) != 0)
2075 static void gpu_opcode_mmult(void)
2077 int count = gpu_matrix_control & 0x0F; // Matrix width
2078 uint32 addr = gpu_pointer_to_matrix; // In the GPU's RAM
2082 if (gpu_matrix_control & 0x10) // Column stepping
2084 for(int i=0; i<count; i++)
2088 a = (int16)((gpu_alternate_reg[IMM_1 + (i >> 1)] >> 16) & 0xFFFF);
2090 a = (int16)(gpu_alternate_reg[IMM_1 + (i >> 1)] & 0xFFFF);
2092 int16 b = ((int16)GPUReadWord(addr + 2, GPU));
2097 else // Row stepping
2099 for(int i=0; i<count; i++)
2103 a = (int16)((gpu_alternate_reg[IMM_1 + (i >> 1)] >> 16) & 0xFFFF);
2105 a = (int16)(gpu_alternate_reg[IMM_1 + (i >> 1)] & 0xFFFF);
2107 int16 b = ((int16)GPUReadWord(addr + 2, GPU));
2112 RN = res = (int32)accum;
2113 // carry flag to do (out of the last add)
2117 static void gpu_opcode_abs(void)
2121 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);
2123 gpu_flag_c = RN >> 31;
2124 if (RN == 0x80000000)
2125 //Is 0x80000000 a positive number? If so, then we need to set C to 0 as well!
2126 gpu_flag_n = 1, gpu_flag_z = 0;
2131 gpu_flag_n = 0; SET_FLAG_Z(RN);
2135 WriteLog("[NCZ:%u%u%u, R%02u=%08X]\n", gpu_flag_n, gpu_flag_c, gpu_flag_z, IMM_2, RN);
2139 static void gpu_opcode_div(void) // RN / RM
2143 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);
2145 // NOTE: remainder is NOT calculated correctly here!
2146 // The original tried to get it right by checking to see if the
2147 // remainder was negative, but that's too late...
2148 // The code there should do it now, but I'm not 100% sure...
2152 if (gpu_div_control & 0x01) // 16.16 division
2154 RN = ((UINT64)RN << 16) / RM;
2155 gpu_remain = ((UINT64)RN << 16) % RM;
2160 gpu_remain = RN % RM;
2163 if ((gpu_remain - RM) & 0x80000000) // If the result would have been negative...
2164 gpu_remain -= RM; // Then make it negative!
2174 if (gpu_div_control & 1)
2176 gpu_remain = (((uint64)_RN) << 16) % _RM;
2177 if (gpu_remain&0x80000000)
2179 RN = (((uint64)_RN) << 16) / _RM;
2183 gpu_remain = _RN % _RM;
2184 if (gpu_remain&0x80000000)
2193 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);
2197 static void gpu_opcode_imultn(void)
2199 uint32 res = (int32)((int16)RN * (int16)RM);
2200 gpu_acc = (int32)res;
2205 static void gpu_opcode_neg(void)
2209 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);
2212 SET_ZNC_SUB(0, RN, res);
2216 WriteLog("[NCZ:%u%u%u, R%02u=%08X]\n", gpu_flag_n, gpu_flag_c, gpu_flag_z, IMM_2, RN);
2220 static void gpu_opcode_shlq(void)
2224 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);
2226 // Was a bug here...
2227 // (Look at Aaron's code: If r1 = 32, then 32 - 32 = 0 which is wrong!)
2228 INT32 r1 = 32 - IMM_1;
2229 UINT32 res = RN << r1;
2230 SET_ZN(res); gpu_flag_c = (RN >> 31) & 1;
2234 WriteLog("[NCZ:%u%u%u, R%02u=%08X]\n", gpu_flag_n, gpu_flag_c, gpu_flag_z, IMM_2, RN);
2238 static void gpu_opcode_shrq(void)
2242 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);
2244 INT32 r1 = gpu_convert_zero[IMM_1];
2245 UINT32 res = RN >> r1;
2246 SET_ZN(res); gpu_flag_c = RN & 1;
2250 WriteLog("[NCZ:%u%u%u, R%02u=%08X]\n", gpu_flag_n, gpu_flag_c, gpu_flag_z, IMM_2, RN);
2254 static void gpu_opcode_ror(void)
2258 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);
2260 UINT32 r1 = RM & 0x1F;
2261 UINT32 res = (RN >> r1) | (RN << (32 - r1));
2262 SET_ZN(res); gpu_flag_c = (RN >> 31) & 1;
2266 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);
2270 static void gpu_opcode_rorq(void)
2274 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);
2276 UINT32 r1 = gpu_convert_zero[IMM_1 & 0x1F];
2278 UINT32 res = (r2 >> r1) | (r2 << (32 - r1));
2280 SET_ZN(res); gpu_flag_c = (r2 >> 31) & 0x01;
2283 WriteLog("[NCZ:%u%u%u, R%02u=%08X]\n", gpu_flag_n, gpu_flag_c, gpu_flag_z, IMM_2, RN);
2287 static void gpu_opcode_sha(void)
2289 /* int dreg = jaguar.op & 31;
2290 INT32 r1 = (INT32)jaguar.r[(jaguar.op >> 5) & 31];
2291 UINT32 r2 = jaguar.r[dreg];
2297 res = (r1 <= -32) ? 0 : (r2 << -r1);
2298 jaguar.FLAGS |= (r2 >> 30) & 2;
2302 res = (r1 >= 32) ? ((INT32)r2 >> 31) : ((INT32)r2 >> r1);
2303 jaguar.FLAGS |= (r2 << 1) & 2;
2305 jaguar.r[dreg] = res;
2310 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);
2316 res = ((INT32)RM <= -32) ? 0 : (RN << -(INT32)RM);
2317 gpu_flag_c = RN >> 31;
2321 res = ((INT32)RM >= 32) ? ((INT32)RN >> 31) : ((INT32)RN >> (INT32)RM);
2322 gpu_flag_c = RN & 0x01;
2328 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);
2331 /* int32 sRM=(int32)RM;
2337 if (shift>=32) shift=32;
2338 gpu_flag_c=(_RN&0x80000000)>>31;
2348 if (shift>=32) shift=32;
2352 _RN=((int32)_RN)>>1;
2361 static void gpu_opcode_sharq(void)
2363 #ifdef GPU_DIS_SHARQ
2365 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);
2367 UINT32 res = (INT32)RN >> gpu_convert_zero[IMM_1];
2368 SET_ZN(res); gpu_flag_c = RN & 0x01;
2370 #ifdef GPU_DIS_SHARQ
2372 WriteLog("[NCZ:%u%u%u, R%02u=%08X]\n", gpu_flag_n, gpu_flag_c, gpu_flag_z, IMM_2, RN);
2376 static void gpu_opcode_sh(void)
2380 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);
2382 if (RM & 0x80000000) // Shift left
2384 gpu_flag_c = RN >> 31;
2385 RN = ((int32)RM <= -32 ? 0 : RN << -(int32)RM);
2389 gpu_flag_c = RN & 0x01;
2390 RN = (RM >= 32 ? 0 : RN >> RM);
2395 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);
2399 //Temporary: Testing only!
2400 //#include "gpu2.cpp"
2401 //#include "gpu3.cpp"