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...
18 #include <string.h> // For memset
29 // For GPU dissasembly...
49 #define GPU_DIS_LOAD14I
50 #define GPU_DIS_LOAD14R
51 #define GPU_DIS_LOAD15I
52 #define GPU_DIS_LOAD15R
54 #define GPU_DIS_MOVEFA
56 #define GPU_DIS_MOVEPC
57 #define GPU_DIS_MOVETA
74 #define GPU_DIS_STOREB
75 #define GPU_DIS_STOREW
76 #define GPU_DIS_STORE14I
77 #define GPU_DIS_STORE14R
78 #define GPU_DIS_STORE15I
79 #define GPU_DIS_STORE15R
86 bool doGPUDis = false;
87 //bool doGPUDis = true;
90 GPU opcodes use (BIOS flying ATARI logo):
132 #define CINT0FLAG 0x0200
133 #define CINT1FLAG 0x0400
134 #define CINT2FLAG 0x0800
135 #define CINT3FLAG 0x1000
136 #define CINT4FLAG 0x2000
137 #define CINT04FLAGS (CINT0FLAG | CINT1FLAG | CINT2FLAG | CINT3FLAG | CINT4FLAG)
141 #define ZERO_FLAG 0x0001
142 #define CARRY_FLAG 0x0002
143 #define NEGA_FLAG 0x0004
145 #define INT_ENA0 0x0010
146 #define INT_ENA1 0x0020
147 #define INT_ENA2 0x0040
148 #define INT_ENA3 0x0080
149 #define INT_ENA4 0x0100
150 #define INT_CLR0 0x0200
151 #define INT_CLR1 0x0400
152 #define INT_CLR2 0x0800
153 #define INT_CLR3 0x1000
154 #define INT_CLR4 0x2000
155 #define REGPAGE 0x4000
158 // External global variables
160 extern int start_logging;
161 extern int gpu_start_log;
163 // Private function prototypes
165 void GPUUpdateRegisterBanks(void);
166 void GPUDumpDisassembly(void);
167 void GPUDumpRegisters(void);
168 void GPUDumpMemory(void);
170 static void gpu_opcode_add(void);
171 static void gpu_opcode_addc(void);
172 static void gpu_opcode_addq(void);
173 static void gpu_opcode_addqt(void);
174 static void gpu_opcode_sub(void);
175 static void gpu_opcode_subc(void);
176 static void gpu_opcode_subq(void);
177 static void gpu_opcode_subqt(void);
178 static void gpu_opcode_neg(void);
179 static void gpu_opcode_and(void);
180 static void gpu_opcode_or(void);
181 static void gpu_opcode_xor(void);
182 static void gpu_opcode_not(void);
183 static void gpu_opcode_btst(void);
184 static void gpu_opcode_bset(void);
185 static void gpu_opcode_bclr(void);
186 static void gpu_opcode_mult(void);
187 static void gpu_opcode_imult(void);
188 static void gpu_opcode_imultn(void);
189 static void gpu_opcode_resmac(void);
190 static void gpu_opcode_imacn(void);
191 static void gpu_opcode_div(void);
192 static void gpu_opcode_abs(void);
193 static void gpu_opcode_sh(void);
194 static void gpu_opcode_shlq(void);
195 static void gpu_opcode_shrq(void);
196 static void gpu_opcode_sha(void);
197 static void gpu_opcode_sharq(void);
198 static void gpu_opcode_ror(void);
199 static void gpu_opcode_rorq(void);
200 static void gpu_opcode_cmp(void);
201 static void gpu_opcode_cmpq(void);
202 static void gpu_opcode_sat8(void);
203 static void gpu_opcode_sat16(void);
204 static void gpu_opcode_move(void);
205 static void gpu_opcode_moveq(void);
206 static void gpu_opcode_moveta(void);
207 static void gpu_opcode_movefa(void);
208 static void gpu_opcode_movei(void);
209 static void gpu_opcode_loadb(void);
210 static void gpu_opcode_loadw(void);
211 static void gpu_opcode_load(void);
212 static void gpu_opcode_loadp(void);
213 static void gpu_opcode_load_r14_indexed(void);
214 static void gpu_opcode_load_r15_indexed(void);
215 static void gpu_opcode_storeb(void);
216 static void gpu_opcode_storew(void);
217 static void gpu_opcode_store(void);
218 static void gpu_opcode_storep(void);
219 static void gpu_opcode_store_r14_indexed(void);
220 static void gpu_opcode_store_r15_indexed(void);
221 static void gpu_opcode_move_pc(void);
222 static void gpu_opcode_jump(void);
223 static void gpu_opcode_jr(void);
224 static void gpu_opcode_mmult(void);
225 static void gpu_opcode_mtoi(void);
226 static void gpu_opcode_normi(void);
227 static void gpu_opcode_nop(void);
228 static void gpu_opcode_load_r14_ri(void);
229 static void gpu_opcode_load_r15_ri(void);
230 static void gpu_opcode_store_r14_ri(void);
231 static void gpu_opcode_store_r15_ri(void);
232 static void gpu_opcode_sat24(void);
233 static void gpu_opcode_pack(void);
235 // This is wrong, since it doesn't take pipeline effects into account. !!! FIX !!!
236 /*uint8 gpu_opcode_cycles[64] =
238 3, 3, 3, 3, 3, 3, 3, 3,
239 3, 3, 3, 3, 3, 3, 3, 3,
240 3, 3, 1, 3, 1, 18, 3, 3,
241 3, 3, 3, 3, 3, 3, 3, 3,
242 3, 3, 2, 2, 2, 2, 3, 4,
243 5, 4, 5, 6, 6, 1, 1, 1,
244 1, 2, 2, 2, 1, 1, 9, 3,
245 3, 1, 6, 6, 2, 2, 3, 3
247 //Here's a QnD kludge...
248 //This is wrong, wrong, WRONG, but it seems to work for the time being...
249 //(That is, it fixes Flip Out which relies on GPU timing rather than semaphores. Bad developers! Bad!)
250 //What's needed here is a way to take pipeline effects into account (including pipeline stalls!)...
251 /*uint8 gpu_opcode_cycles[64] =
253 1, 1, 1, 1, 1, 1, 1, 1,
254 1, 1, 1, 1, 1, 1, 1, 1,
255 1, 1, 1, 1, 1, 9, 1, 1,
256 1, 1, 1, 1, 1, 1, 1, 1,
257 1, 1, 1, 1, 1, 1, 1, 2,
258 2, 2, 2, 3, 3, 1, 1, 1,
259 1, 1, 1, 1, 1, 1, 4, 1,
260 1, 1, 3, 3, 1, 1, 1, 1
262 uint8 gpu_opcode_cycles[64] =
264 1, 1, 1, 1, 1, 1, 1, 1,
265 1, 1, 1, 1, 1, 1, 1, 1,
266 1, 1, 1, 1, 1, 1, 1, 1,
267 1, 1, 1, 1, 1, 1, 1, 1,
268 1, 1, 1, 1, 1, 1, 1, 1,
269 1, 1, 1, 1, 1, 1, 1, 1,
270 1, 1, 1, 1, 1, 1, 1, 1,
271 1, 1, 1, 1, 1, 1, 1, 1
274 void (*gpu_opcode[64])()=
276 gpu_opcode_add, gpu_opcode_addc, gpu_opcode_addq, gpu_opcode_addqt,
277 gpu_opcode_sub, gpu_opcode_subc, gpu_opcode_subq, gpu_opcode_subqt,
278 gpu_opcode_neg, gpu_opcode_and, gpu_opcode_or, gpu_opcode_xor,
279 gpu_opcode_not, gpu_opcode_btst, gpu_opcode_bset, gpu_opcode_bclr,
280 gpu_opcode_mult, gpu_opcode_imult, gpu_opcode_imultn, gpu_opcode_resmac,
281 gpu_opcode_imacn, gpu_opcode_div, gpu_opcode_abs, gpu_opcode_sh,
282 gpu_opcode_shlq, gpu_opcode_shrq, gpu_opcode_sha, gpu_opcode_sharq,
283 gpu_opcode_ror, gpu_opcode_rorq, gpu_opcode_cmp, gpu_opcode_cmpq,
284 gpu_opcode_sat8, gpu_opcode_sat16, gpu_opcode_move, gpu_opcode_moveq,
285 gpu_opcode_moveta, gpu_opcode_movefa, gpu_opcode_movei, gpu_opcode_loadb,
286 gpu_opcode_loadw, gpu_opcode_load, gpu_opcode_loadp, gpu_opcode_load_r14_indexed,
287 gpu_opcode_load_r15_indexed, gpu_opcode_storeb, gpu_opcode_storew, gpu_opcode_store,
288 gpu_opcode_storep, gpu_opcode_store_r14_indexed, gpu_opcode_store_r15_indexed, gpu_opcode_move_pc,
289 gpu_opcode_jump, gpu_opcode_jr, gpu_opcode_mmult, gpu_opcode_mtoi,
290 gpu_opcode_normi, gpu_opcode_nop, gpu_opcode_load_r14_ri, gpu_opcode_load_r15_ri,
291 gpu_opcode_store_r14_ri, gpu_opcode_store_r15_ri, gpu_opcode_sat24, gpu_opcode_pack,
294 static uint8 gpu_ram_8[0x1000];
296 static uint32 gpu_acc;
297 static uint32 gpu_remain;
298 static uint32 gpu_hidata;
299 static uint32 gpu_flags;
300 static uint32 gpu_matrix_control;
301 static uint32 gpu_pointer_to_matrix;
302 static uint32 gpu_data_organization;
303 static uint32 gpu_control;
304 static uint32 gpu_div_control;
305 // There is a distinct advantage to having these separated out--there's no need to clear
306 // a bit before writing a result. I.e., if the result of an operation leaves a zero in
307 // the carry flag, you don't have to zero gpu_flag_c before you can write that zero!
308 static uint8 gpu_flag_z, gpu_flag_n, gpu_flag_c;
309 static uint32 gpu_reg_bank_0[32];
310 static uint32 gpu_reg_bank_1[32];
311 static uint32 * gpu_reg;
312 static uint32 * gpu_alternate_reg;
314 static uint32 gpu_instruction;
315 static uint32 gpu_opcode_first_parameter;
316 static uint32 gpu_opcode_second_parameter;
318 #define GPU_RUNNING (gpu_control & 0x01)
320 #define RM gpu_reg[gpu_opcode_first_parameter]
321 #define RN gpu_reg[gpu_opcode_second_parameter]
322 #define ALTERNATE_RM gpu_alternate_reg[gpu_opcode_first_parameter]
323 #define ALTERNATE_RN gpu_alternate_reg[gpu_opcode_second_parameter]
324 #define IMM_1 gpu_opcode_first_parameter
325 #define IMM_2 gpu_opcode_second_parameter
327 #define SET_FLAG_Z(r) (gpu_flag_z = ((r) == 0));
328 #define SET_FLAG_N(r) (gpu_flag_n = (((uint32)(r) >> 31) & 0x01));
330 #define RESET_FLAG_Z() gpu_flag_z = 0;
331 #define RESET_FLAG_N() gpu_flag_n = 0;
332 #define RESET_FLAG_C() gpu_flag_c = 0;
334 #define CLR_Z (gpu_flag_z = 0)
335 #define CLR_ZN (gpu_flag_z = gpu_flag_n = 0)
336 #define CLR_ZNC (gpu_flag_z = gpu_flag_n = gpu_flag_c = 0)
337 #define SET_Z(r) (gpu_flag_z = ((r) == 0))
338 #define SET_N(r) (gpu_flag_n = (((uint32)(r) >> 31) & 0x01))
339 #define SET_C_ADD(a,b) (gpu_flag_c = ((uint32)(b) > (uint32)(~(a))))
340 #define SET_C_SUB(a,b) (gpu_flag_c = ((uint32)(b) > (uint32)(a)))
341 #define SET_ZN(r) SET_N(r); SET_Z(r)
342 #define SET_ZNC_ADD(a,b,r) SET_N(r); SET_Z(r); SET_C_ADD(a,b)
343 #define SET_ZNC_SUB(a,b,r) SET_N(r); SET_Z(r); SET_C_SUB(a,b)
345 uint32 gpu_convert_zero[32] =
346 { 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 };
348 uint8 * branch_condition_table = 0;
349 #define BRANCH_CONDITION(x) branch_condition_table[(x) + ((jaguar_flags & 7) << 5)]
351 uint32 gpu_opcode_use[64];
353 const char * gpu_opcode_str[64]=
355 "add", "addc", "addq", "addqt",
356 "sub", "subc", "subq", "subqt",
357 "neg", "and", "or", "xor",
358 "not", "btst", "bset", "bclr",
359 "mult", "imult", "imultn", "resmac",
360 "imacn", "div", "abs", "sh",
361 "shlq", "shrq", "sha", "sharq",
362 "ror", "rorq", "cmp", "cmpq",
363 "sat8", "sat16", "move", "moveq",
364 "moveta", "movefa", "movei", "loadb",
365 "loadw", "load", "loadp", "load_r14_indexed",
366 "load_r15_indexed", "storeb", "storew", "store",
367 "storep", "store_r14_indexed","store_r15_indexed","move_pc",
368 "jump", "jr", "mmult", "mtoi",
369 "normi", "nop", "load_r14_ri", "load_r15_ri",
370 "store_r14_ri", "store_r15_ri", "sat24", "pack",
373 static uint32 gpu_in_exec = 0;
374 static uint32 gpu_releaseTimeSlice_flag = 0;
376 void GPUReleaseTimeslice(void)
378 gpu_releaseTimeSlice_flag = 1;
381 uint32 GPUGetPC(void)
386 void build_branch_condition_table(void)
388 if (!branch_condition_table)
390 branch_condition_table = (uint8 *)malloc(32 * 8 * sizeof(branch_condition_table[0]));
392 if (branch_condition_table)
394 for(int i=0; i<8; i++)
396 for(int j=0; j<32; j++)
403 if (!(i & ZERO_FLAG))
406 if (i & (CARRY_FLAG << (j >> 4)))
409 if (!(i & (CARRY_FLAG << (j >> 4))))
411 branch_condition_table[i * 32 + j] = result;
419 // GPU byte access (read)
421 uint8 GPUReadByte(uint32 offset, uint32 who/*=UNKNOWN*/)
423 if (offset >= 0xF02000 && offset <= 0xF020FF)
424 WriteLog("GPU: ReadByte--Attempt to read from GPU register file by %s!\n", whoName[who]);
426 if ((offset >= GPU_WORK_RAM_BASE) && (offset < GPU_WORK_RAM_BASE+0x1000))
427 return gpu_ram_8[offset & 0xFFF];
428 else if ((offset >= GPU_CONTROL_RAM_BASE) && (offset < GPU_CONTROL_RAM_BASE+0x20))
430 uint32 data = GPUReadLong(offset & 0xFFFFFFFC, who);
432 if ((offset & 0x03) == 0)
434 else if ((offset & 0x03) == 1)
435 return (data >> 16) & 0xFF;
436 else if ((offset & 0x03) == 2)
437 return (data >> 8) & 0xFF;
438 else if ((offset & 0x03) == 3)
442 return JaguarReadByte(offset, who);
446 // GPU word access (read)
448 uint16 GPUReadWord(uint32 offset, uint32 who/*=UNKNOWN*/)
450 if (offset >= 0xF02000 && offset <= 0xF020FF)
451 WriteLog("GPU: ReadWord--Attempt to read from GPU register file by %s!\n", whoName[who]);
453 if ((offset >= GPU_WORK_RAM_BASE) && (offset < GPU_WORK_RAM_BASE+0x1000))
456 uint16 data = ((uint16)gpu_ram_8[offset] << 8) | (uint16)gpu_ram_8[offset+1];
459 else if ((offset >= GPU_CONTROL_RAM_BASE) && (offset < GPU_CONTROL_RAM_BASE+0x20))
461 // This looks and smells wrong...
462 // But it *might* be OK...
463 if (offset & 0x01) // Catch cases 1 & 3... (unaligned read)
464 return (GPUReadByte(offset, who) << 8) | GPUReadByte(offset+1, who);
466 uint32 data = GPUReadLong(offset & 0xFFFFFFFC, who);
468 if (offset & 0x02) // Cases 0 & 2...
469 return data & 0xFFFF;
474 //TEMP--Mirror of F03000? No. Writes only...
475 //if (offset >= 0xF0B000 && offset <= 0xF0BFFF)
476 //WriteLog("[GPUR16] --> Possible GPU RAM mirror access by %s!", whoName[who]);
478 return JaguarReadWord(offset, who);
482 // GPU dword access (read)
484 uint32 GPUReadLong(uint32 offset, uint32 who/*=UNKNOWN*/)
486 if (offset >= 0xF02000 && offset <= 0xF020FF)
487 WriteLog("GPU: ReadLong--Attempt to read from GPU register file by %s!\n", whoName[who]);
489 // if ((offset >= GPU_WORK_RAM_BASE) && (offset < GPU_WORK_RAM_BASE + 0x1000))
490 if ((offset >= GPU_WORK_RAM_BASE) && (offset <= GPU_WORK_RAM_BASE + 0x0FFC))
493 return ((uint32)gpu_ram_8[offset] << 24) | ((uint32)gpu_ram_8[offset+1] << 16)
494 | ((uint32)gpu_ram_8[offset+2] << 8) | (uint32)gpu_ram_8[offset+3];//*/
495 // return GET32(gpu_ram_8, offset);
497 // else if ((offset >= GPU_CONTROL_RAM_BASE) && (offset < GPU_CONTROL_RAM_BASE+0x20))
498 else if ((offset >= GPU_CONTROL_RAM_BASE) && (offset <= GPU_CONTROL_RAM_BASE + 0x1C))
504 gpu_flag_c = (gpu_flag_c ? 1 : 0);
505 gpu_flag_z = (gpu_flag_z ? 1 : 0);
506 gpu_flag_n = (gpu_flag_n ? 1 : 0);
508 gpu_flags = (gpu_flags & 0xFFFFFFF8) | (gpu_flag_n << 2) | (gpu_flag_c << 1) | gpu_flag_z;
510 return gpu_flags & 0xFFFFC1FF;
512 return gpu_matrix_control;
514 return gpu_pointer_to_matrix;
516 return gpu_data_organization;
525 default: // unaligned long read
527 WriteLog("GPU: Read32--unaligned 32 bit read at %08X by %s.\n", GPU_CONTROL_RAM_BASE + offset, whoName[who]);
532 //TEMP--Mirror of F03000? No. Writes only...
533 //if (offset >= 0xF0B000 && offset <= 0xF0BFFF)
534 // WriteLog("[GPUR32] --> Possible GPU RAM mirror access by %s!\n", whoName[who]);
535 /*if (offset >= 0xF1D000 && offset <= 0xF1DFFF)
536 WriteLog("[GPUR32] --> Reading from Wavetable ROM!\n");//*/
538 return (JaguarReadWord(offset, who) << 16) | JaguarReadWord(offset + 2, who);
542 // GPU byte access (write)
544 void GPUWriteByte(uint32 offset, uint8 data, uint32 who/*=UNKNOWN*/)
546 if (offset >= 0xF02000 && offset <= 0xF020FF)
547 WriteLog("GPU: WriteByte--Attempt to write to GPU register file by %s!\n", whoName[who]);
549 if ((offset >= GPU_WORK_RAM_BASE) && (offset <= GPU_WORK_RAM_BASE + 0x0FFF))
551 gpu_ram_8[offset & 0xFFF] = data;
553 //This is the same stupid worthless code that was in the DSP!!! AARRRGGGGHHHHH!!!!!!
556 m68k_end_timeslice();
557 dsp_releaseTimeslice();
561 else if ((offset >= GPU_CONTROL_RAM_BASE) && (offset <= GPU_CONTROL_RAM_BASE + 0x1F))
563 uint32 reg = offset & 0x1C;
564 int bytenum = offset & 0x03;
566 //This is definitely wrong!
567 if ((reg >= 0x1C) && (reg <= 0x1F))
568 gpu_div_control = (gpu_div_control & (~(0xFF << (bytenum << 3)))) | (data << (bytenum << 3));
571 uint32 old_data = GPUReadLong(offset & 0xFFFFFFC, who);
572 bytenum = 3 - bytenum; // convention motorola !!!
573 old_data = (old_data & (~(0xFF << (bytenum << 3)))) | (data << (bytenum << 3));
574 GPUWriteLong(offset & 0xFFFFFFC, old_data, who);
578 // WriteLog("gpu: writing %.2x at 0x%.8x\n",data,offset);
579 JaguarWriteByte(offset, data, who);
583 // GPU word access (write)
585 void GPUWriteWord(uint32 offset, uint16 data, uint32 who/*=UNKNOWN*/)
587 if (offset >= 0xF02000 && offset <= 0xF020FF)
588 WriteLog("GPU: WriteWord--Attempt to write to GPU register file by %s!\n", whoName[who]);
590 if ((offset >= GPU_WORK_RAM_BASE) && (offset <= GPU_WORK_RAM_BASE + 0x0FFE))
592 gpu_ram_8[offset & 0xFFF] = (data>>8) & 0xFF;
593 gpu_ram_8[(offset+1) & 0xFFF] = data & 0xFF;//*/
595 SET16(gpu_ram_8, offset, data);//*/
597 /*if (offset >= 0xF03214 && offset < 0xF0321F)
598 WriteLog("GPU: Writing WORD (%04X) to GPU RAM (%08X)...\n", data, offset);//*/
601 //This is the same stupid worthless code that was in the DSP!!! AARRRGGGGHHHHH!!!!!!
604 m68k_end_timeslice();
605 dsp_releaseTimeslice();
609 else if ((offset >= GPU_CONTROL_RAM_BASE) && (offset <= GPU_CONTROL_RAM_BASE + 0x1E))
611 if (offset & 0x01) // This is supposed to weed out unaligned writes, but does nothing...
614 WriteLog("GPU: Write16--unaligned write @ %08X [%04X]\n", offset, data);
619 //Dual locations in this range: $1C Divide unit remainder/Divide unit control (R/W)
620 //This just literally sucks.
621 if ((offset & 0x1C) == 0x1C)
623 //This doesn't look right either--handles cases 1, 2, & 3 all the same!
625 gpu_div_control = (gpu_div_control & 0xFFFF0000) | (data & 0xFFFF);
627 gpu_div_control = (gpu_div_control & 0x0000FFFF) | ((data & 0xFFFF) << 16);
631 //WriteLog("[GPU W16:%08X,%04X]", offset, data);
632 uint32 old_data = GPUReadLong(offset & 0xFFFFFFC, who);
634 old_data = (old_data & 0xFFFF0000) | (data & 0xFFFF);
636 old_data = (old_data & 0x0000FFFF) | ((data & 0xFFFF) << 16);
637 GPUWriteLong(offset & 0xFFFFFFC, old_data, who);
641 else if ((offset == GPU_WORK_RAM_BASE + 0x0FFF) || (GPU_CONTROL_RAM_BASE + 0x1F))
644 WriteLog("GPU: Write16--unaligned write @ %08X by %s [%04X]!\n", offset, whoName[who], data);
650 // Have to be careful here--this can cause an infinite loop!
651 JaguarWriteWord(offset, data, who);
655 // GPU dword access (write)
657 void GPUWriteLong(uint32 offset, uint32 data, uint32 who/*=UNKNOWN*/)
659 if (offset >= 0xF02000 && offset <= 0xF020FF)
660 WriteLog("GPU: WriteLong--Attempt to write to GPU register file by %s!\n", whoName[who]);
662 // if ((offset >= GPU_WORK_RAM_BASE) && (offset < GPU_WORK_RAM_BASE + 0x1000))
663 if ((offset >= GPU_WORK_RAM_BASE) && (offset <= GPU_WORK_RAM_BASE + 0x0FFC))
668 WriteLog("GPU: Write32--unaligned write @ %08X [%08X] by %s\n", offset, data, whoName[who]);
674 SET32(gpu_ram_8, offset, data);
677 // else if ((offset >= GPU_CONTROL_RAM_BASE) && (offset < GPU_CONTROL_RAM_BASE+0x20))
678 else if ((offset >= GPU_CONTROL_RAM_BASE) && (offset <= GPU_CONTROL_RAM_BASE + 0x1C))
685 bool IMASKCleared = (gpu_flags & IMASK) && !(data & IMASK);
687 gpu_flag_z = gpu_flags & ZERO_FLAG;
688 gpu_flag_c = (gpu_flags & CARRY_FLAG) >> 1;
689 gpu_flag_n = (gpu_flags & NEGA_FLAG) >> 2;
690 GPUUpdateRegisterBanks();
691 gpu_control &= ~((gpu_flags & CINT04FLAGS) >> 3); // Interrupt latch clear bits
692 //Writing here is only an interrupt enable--this approach is just plain wrong!
694 //This, however, is A-OK! ;-)
695 if (IMASKCleared) // If IMASK was cleared,
696 GPUHandleIRQs(); // see if any other interrupts need servicing!
698 if (gpu_flags & (INT_ENA0 | INT_ENA1 | INT_ENA2 | INT_ENA3 | INT_ENA4))
699 WriteLog("GPU: Interrupt enable set by %s! Bits: %02X\n", whoName[who], (gpu_flags >> 4) & 0x1F);
700 WriteLog("GPU: REGPAGE %s...\n", (gpu_flags & REGPAGE ? "set" : "cleared"));
705 gpu_matrix_control = data;
708 // This can only point to long aligned addresses
709 gpu_pointer_to_matrix = data & 0xFFFFFFFC;
712 gpu_data_organization = data;
717 WriteLog("GPU: %s setting GPU PC to %08X %s\n", whoName[who], gpu_pc, (GPU_RUNNING ? "(GPU is RUNNING!)" : ""));//*/
722 // uint32 gpu_was_running = GPU_RUNNING;
723 data &= ~0xF7C0; // Disable writes to INT_LAT0-4 & TOM version number
725 // check for GPU -> CPU interrupt
728 //WriteLog("GPU->CPU interrupt\n");
729 if (TOMIRQEnabled(IRQ_GPU))
731 if ((TOMIRQEnabled(IRQ_GPU)) && (JaguarInterruptHandlerIsValid(64)))
733 TOMSetPendingGPUInt();
734 m68k_set_irq(7); // Set 68000 NMI
735 GPUReleaseTimeslice();
741 // check for CPU -> GPU interrupt #0
744 //WriteLog("CPU->GPU interrupt\n");
745 GPUSetIRQLine(0, ASSERT_LINE);
746 m68k_end_timeslice();
747 DSPReleaseTimeslice();
754 //WriteLog("asked to perform a single step (single step is %senabled)\n",(data&0x8)?"":"not ");
756 gpu_control = (gpu_control & 0xF7C0) | (data & (~0xF7C0));
758 // if gpu wasn't running but is now running, execute a few cycles
759 #ifndef GPU_SINGLE_STEPPING
760 /* if (!gpu_was_running && GPU_RUNNING)
763 WriteLog("GPU: Write32--About to do stupid braindead GPU execution for 200 cycles.\n");
768 #endif // GPU_DEBUG//*/
770 if (gpu_control & 0x18)
772 #endif // #ifndef GPU_SINGLE_STEPPING
774 WriteLog("Write to GPU CTRL by %s: %08X ", whoName[who], data);
776 WriteLog(" --> Starting to run at %08X by %s...", gpu_pc, whoName[who]);
778 WriteLog(" --> Stopped by %s! (GPU_PC: %08X)", whoName[who], gpu_pc);
782 // GPUDumpDisassembly();
785 if (gpu_pc == 0xF035D8)
787 // GPUDumpDisassembly();
790 gpu_control &= 0xFFFFFFFE; // Don't run it and let's see what happens!
791 //Hmm. Seems to lock up when going into the demo...
792 //Try to disable the collision altogether!
795 extern int effect_start5;
796 static bool finished = false;
797 //if (GPU_RUNNING && effect_start5 && !finished)
798 if (GPU_RUNNING && effect_start5 && gpu_pc == 0xF035D8)
800 // Let's do a dump of $6528!
801 /* uint32 numItems = JaguarReadWord(0x6BD6);
802 WriteLog("\nDump of $6528: %u items.\n\n", numItems);
803 for(int i=0; i<numItems*3*4; i+=3*4)
805 WriteLog("\t%04X: %08X %08X %08X -> ", 0x6528+i, JaguarReadLong(0x6528+i),
806 JaguarReadLong(0x6528+i+4), JaguarReadLong(0x6528+i+8));
807 uint16 link = JaguarReadWord(0x6528+i+8+2);
808 for(int j=0; j<40; j+=4)
809 WriteLog("%08X ", JaguarReadLong(link + j));
813 // Let's try a manual blit here...
814 //This isn't working the way it should! !!! FIX !!!
815 //Err, actually, it is.
816 // NOW, it works right! Problem solved!!! It's a blitter bug!
817 /* uint32 src = 0x4D54, dst = 0xF03000, width = 10 * 4;
818 for(int y=0; y<127; y++)
820 for(int x=0; x<2; x++)
822 JaguarWriteLong(dst, JaguarReadLong(src));
827 src += width - (2 * 4);
831 WriteLog("\nGPU: About to execute collision detection code.\n\n");//*/
833 /* WriteLog("\nGPU: About to execute collision detection code. Data @ 4D54:\n\n");
835 for(int i=0x004D54; i<0x004D54+2048; i++)
837 WriteLog("%02X ", JaguarReadByte(i));
845 WriteLog("\n\nData @ F03000:\n\n");
847 for(int i=0xF03000; i<0xF03200; i++)
849 WriteLog("%02X ", JaguarReadByte(i));
863 /*if (!GPU_RUNNING && finished)
865 WriteLog("\nGPU: Finished collision detection code. Exiting!\n\n");
870 // (?) If we're set running by the M68K (or DSP?) then end its timeslice to
871 // allow the GPU a chance to run...
872 // Yes! This partially fixed Trevor McFur...
874 m68k_end_timeslice();
881 gpu_div_control = data;
883 // default: // unaligned long write
890 // JaguarWriteWord(offset, (data >> 16) & 0xFFFF, who);
891 // JaguarWriteWord(offset+2, data & 0xFFFF, who);
892 // We're a 32-bit processor, we can do a long write...!
893 JaguarWriteLong(offset, data, who);
897 // Change register banks if necessary
899 void GPUUpdateRegisterBanks(void)
901 int bank = (gpu_flags & REGPAGE); // REGPAGE bit
903 if (gpu_flags & IMASK) // IMASK bit
904 bank = 0; // IMASK forces main bank to be bank 0
907 gpu_reg = gpu_reg_bank_1, gpu_alternate_reg = gpu_reg_bank_0;
909 gpu_reg = gpu_reg_bank_0, gpu_alternate_reg = gpu_reg_bank_1;
912 void GPUHandleIRQs(void)
914 // Bail out if we're already in an interrupt!
915 if (gpu_flags & IMASK)
918 // Get the interrupt latch & enable bits
919 uint32 bits = (gpu_control >> 6) & 0x1F, mask = (gpu_flags >> 4) & 0x1F;
921 // Bail out if latched interrupts aren't enabled
926 // Determine which interrupt to service
927 uint32 which = 0; //Isn't there a #pragma to disable this warning???
940 WriteLog("GPU: Generating IRQ #%i\n", which);
942 // set the interrupt flag
944 GPUUpdateRegisterBanks();
946 // subqt #4,r31 ; pre-decrement stack pointer
947 // move pc,r30 ; address of interrupted code
948 // store r30,(r31) ; store return address
950 GPUWriteLong(gpu_reg[31], gpu_pc - 2, GPU);
952 // movei #service_address,r30 ; pointer to ISR entry
953 // jump (r30) ; jump to ISR
955 gpu_pc = gpu_reg[30] = GPU_WORK_RAM_BASE + (which * 0x10);
958 void GPUSetIRQLine(int irqline, int state)
961 WriteLog("GPU: Setting GPU IRQ line #%i\n", irqline);
963 uint32 mask = 0x0040 << irqline;
964 gpu_control &= ~mask; // Clear the interrupt latch
968 gpu_control |= mask; // Assert the interrupt latch
969 GPUHandleIRQs(); // And handle the interrupt...
973 //TEMPORARY: Testing only!
979 // memory_malloc_secure((void **)&gpu_ram_8, 0x1000, "GPU work RAM");
980 // memory_malloc_secure((void **)&gpu_reg_bank_0, 32 * sizeof(int32), "GPU bank 0 regs");
981 // memory_malloc_secure((void **)&gpu_reg_bank_1, 32 * sizeof(int32), "GPU bank 1 regs");
983 build_branch_condition_table();
987 //TEMPORARY: Testing only!
994 // GPU registers (directly visible)
995 gpu_flags = 0x00000000;
996 gpu_matrix_control = 0x00000000;
997 gpu_pointer_to_matrix = 0x00000000;
998 gpu_data_organization = 0xFFFFFFFF;
1000 gpu_control = 0x00002800; // Correctly sets this as TOM Rev. 2
1001 gpu_hidata = 0x00000000;
1002 gpu_remain = 0x00000000; // These two registers are RO/WO
1003 gpu_div_control = 0x00000000;
1005 // GPU internal register
1006 gpu_acc = 0x00000000;
1008 gpu_reg = gpu_reg_bank_0;
1009 gpu_alternate_reg = gpu_reg_bank_1;
1011 for(int i=0; i<32; i++)
1012 gpu_reg[i] = gpu_alternate_reg[i] = 0x00000000;
1015 memset(gpu_ram_8, 0xFF, 0x1000);
1017 //not needed GPUInterruptPending = false;
1021 uint32 GPUReadPC(void)
1026 void GPUResetStats(void)
1028 for(uint32 i=0; i<64; i++)
1029 gpu_opcode_use[i] = 0;
1030 WriteLog("--> GPU stats were reset!\n");
1033 void GPUDumpDisassembly(void)
1037 WriteLog("\n---[GPU code at 00F03000]---------------------------\n");
1038 uint32 j = 0xF03000;
1039 while (j <= 0xF03FFF)
1042 j += dasmjag(JAGUAR_GPU, buffer, j);
1043 WriteLog("\t%08X: %s\n", oldj, buffer);
1047 void GPUDumpRegisters(void)
1049 WriteLog("\n---[GPU flags: NCZ %d%d%d]-----------------------\n", gpu_flag_n, gpu_flag_c, gpu_flag_z);
1050 WriteLog("\nRegisters bank 0\n");
1051 for(int j=0; j<8; j++)
1053 WriteLog("\tR%02i = %08X R%02i = %08X R%02i = %08X R%02i = %08X\n",
1054 (j << 2) + 0, gpu_reg_bank_0[(j << 2) + 0],
1055 (j << 2) + 1, gpu_reg_bank_0[(j << 2) + 1],
1056 (j << 2) + 2, gpu_reg_bank_0[(j << 2) + 2],
1057 (j << 2) + 3, gpu_reg_bank_0[(j << 2) + 3]);
1059 WriteLog("Registers bank 1\n");
1060 for(int j=0; j<8; j++)
1062 WriteLog("\tR%02i = %08X R%02i = %08X R%02i = %08X R%02i = %08X\n",
1063 (j << 2) + 0, gpu_reg_bank_1[(j << 2) + 0],
1064 (j << 2) + 1, gpu_reg_bank_1[(j << 2) + 1],
1065 (j << 2) + 2, gpu_reg_bank_1[(j << 2) + 2],
1066 (j << 2) + 3, gpu_reg_bank_1[(j << 2) + 3]);
1070 void GPUDumpMemory(void)
1072 WriteLog("\n---[GPU data at 00F03000]---------------------------\n");
1073 for(int i=0; i<0xFFF; i+=4)
1074 WriteLog("\t%08X: %02X %02X %02X %02X\n", 0xF03000+i, gpu_ram_8[i],
1075 gpu_ram_8[i+1], gpu_ram_8[i+2], gpu_ram_8[i+3]);
1080 WriteLog("GPU: Stopped at PC=%08X (GPU %s running)\n", (unsigned int)gpu_pc, GPU_RUNNING ? "was" : "wasn't");
1082 // Get the interrupt latch & enable bits
1083 uint8 bits = (gpu_control >> 6) & 0x1F, mask = (gpu_flags >> 4) & 0x1F;
1084 WriteLog("GPU: Latch bits = %02X, enable bits = %02X\n", bits, mask);
1087 GPUDumpDisassembly();
1089 WriteLog("\nGPU opcodes use:\n");
1090 for(int i=0; i<64; i++)
1092 if (gpu_opcode_use[i])
1093 WriteLog("\t%17s %lu\n", gpu_opcode_str[i], gpu_opcode_use[i]);
1097 // memory_free(gpu_ram_8);
1098 // memory_free(gpu_reg_bank_0);
1099 // memory_free(gpu_reg_bank_1);
1103 // Main GPU execution core
1105 static int testCount = 1;
1107 static bool tripwire = false;
1108 void GPUExec(int32 cycles)
1113 #ifdef GPU_SINGLE_STEPPING
1114 if (gpu_control & 0x18)
1117 gpu_control &= ~0x10;
1121 gpu_releaseTimeSlice_flag = 0;
1124 while (cycles > 0 && GPU_RUNNING)
1126 if (gpu_ram_8[0x054] == 0x98 && gpu_ram_8[0x055] == 0x0A && gpu_ram_8[0x056] == 0x03
1127 && gpu_ram_8[0x057] == 0x00 && gpu_ram_8[0x058] == 0x00 && gpu_ram_8[0x059] == 0x00)
1129 if (gpu_pc == 0xF03000)
1131 extern uint32 starCount;
1133 /* WriteLog("GPU: Starting starfield generator... Dump of [R03=%08X]:\n", gpu_reg_bank_0[03]);
1134 uint32 base = gpu_reg_bank_0[3];
1135 for(uint32 i=0; i<0x100; i+=16)
1137 WriteLog("%02X: ", i);
1138 for(uint32 j=0; j<16; j++)
1140 WriteLog("%02X ", JaguarReadByte(base + i + j));
1145 // if (gpu_pc == 0xF03)
1149 /*if (gpu_pc == 0xF03B9E && gpu_reg_bank_0[01] == 0)
1152 WriteLog("GPU: Starting disassembly log...\n");
1155 /*if (gpu_pc == 0xF0359A)
1160 /* gpu_flag_c = (gpu_flag_c ? 1 : 0);
1161 gpu_flag_z = (gpu_flag_z ? 1 : 0);
1162 gpu_flag_n = (gpu_flag_n ? 1 : 0);*/
1164 uint16 opcode = GPUReadWord(gpu_pc, GPU);
1165 uint32 index = opcode >> 10;
1166 gpu_instruction = opcode; // Added for GPU #3...
1167 gpu_opcode_first_parameter = (opcode >> 5) & 0x1F;
1168 gpu_opcode_second_parameter = opcode & 0x1F;
1169 /*if (gpu_pc == 0xF03BE8)
1170 WriteLog("Start of OP frame write...\n");
1171 if (gpu_pc == 0xF03EEE)
1172 WriteLog("--> Writing BRANCH object ---\n");
1173 if (gpu_pc == 0xF03F62)
1174 WriteLog("--> Writing BITMAP object ***\n");//*/
1175 /*if (gpu_pc == 0xF03546)
1177 WriteLog("\n--> GPU PC: F03546\n");
1179 GPUDumpDisassembly();
1181 /*if (gpu_pc == 0xF033F6)
1183 WriteLog("\n--> GPU PC: F033F6\n");
1185 GPUDumpDisassembly();
1187 /*if (gpu_pc == 0xF033CC)
1189 WriteLog("\n--> GPU PC: F033CC\n");
1191 GPUDumpDisassembly();
1193 /*if (gpu_pc == 0xF033D6)
1195 WriteLog("\n--> GPU PC: F033D6 (#%d)\n", testCount++);
1199 /*if (gpu_pc == 0xF033D8)
1201 WriteLog("\n--> GPU PC: F033D8 (#%d)\n", testCount++);
1205 /*if (gpu_pc == 0xF0358E)
1207 WriteLog("\n--> GPU PC: F0358E (#%d)\n", testCount++);
1211 /*if (gpu_pc == 0xF034CA)
1213 WriteLog("\n--> GPU PC: F034CA (#%d)\n", testCount++);
1216 /*if (gpu_pc == 0xF034CA)
1218 len = gpu_reg[1] + 4;//, r9save = gpu_reg[9];
1219 WriteLog("\nAbout to subtract [#%d] (R14=%08X, R15=%08X, R9=%08X):\n ", testCount++, gpu_reg[14], gpu_reg[15], gpu_reg[9]);
1220 for(int i=0; i<len; i+=4)
1221 WriteLog(" %08X", GPUReadLong(gpu_reg[15]+i));
1223 for(int i=0; i<len; i+=4)
1224 WriteLog(" %08X", GPUReadLong(gpu_reg[14]+i));
1227 if (gpu_pc == 0xF034DE)
1229 WriteLog("\nSubtracted! (R14=%08X, R15=%08X):\n ", gpu_reg[14], gpu_reg[15]);
1230 for(int i=0; i<len; i+=4)
1231 WriteLog(" %08X", GPUReadLong(gpu_reg[15]+i));
1233 for(int i=0; i<len; i+=4)
1234 WriteLog(" %08X", GPUReadLong(gpu_reg[14]+i));
1236 for(int i=0; i<len; i+=4)
1237 WriteLog(" --------");
1239 for(int i=0; i<len; i+=4)
1240 WriteLog(" %08X", GPUReadLong(gpu_reg[9]+4+i));
1243 /*if (gpu_pc == 0xF035C8)
1245 WriteLog("\n--> GPU PC: F035C8 (#%d)\n", testCount++);
1247 GPUDumpDisassembly();
1252 // gpu_reset_stats();
1253 static char buffer[512];
1254 dasmjag(JAGUAR_GPU, buffer, gpu_pc);
1255 WriteLog("GPU: [%08X] %s (RM=%08X, RN=%08X) -> ", gpu_pc, buffer, RM, RN);
1257 //$E400 -> 1110 01 -> $39 -> 57
1260 gpu_opcode[index]();
1262 // gpu2_opcode[index]();
1264 //GPU #3 (Doesn't show ATARI logo! #1 & #2 do...)
1266 // gpu3_opcode[index]();
1269 //GPU: [00F03548] jr nz,00F03560 (0xd561) (RM=00F03114, RN=00000004) -> --> JR: Branch taken.
1270 /*static bool firstTime = true;
1271 if (gpu_pc == 0xF03548 && firstTime)
1274 // firstTime = false;
1276 //static char buffer[512];
1278 //while (k<0xF0356C)
1281 //k += dasmjag(JAGUAR_GPU, buffer, k);
1282 //WriteLog("GPU: [%08X] %s\n", oldk, buffer);
1284 // gpu_start_log = 1;
1286 //GPU: [00F0354C] jump nz,(r29) (0xd3a1) (RM=00F03314, RN=00000004) -> (RM=00F03314, RN=00000004)
1287 /*if (gpu_pc == 0xF0354C)
1288 gpu_flag_z = 0;//, gpu_start_log = 1;//*/
1290 cycles -= gpu_opcode_cycles[index];
1291 gpu_opcode_use[index]++;
1293 WriteLog("(RM=%08X, RN=%08X)\n", RM, RN);//*/
1294 if ((gpu_pc < 0xF03000 || gpu_pc > 0xF03FFF) && !tripwire)
1296 WriteLog("GPU: Executing outside local RAM! GPU_PC: %08X\n", gpu_pc);
1309 GPU opcodes use (offset punch--vertically below bad guy):
1331 load_r14_indexed 1183
1332 load_r15_indexed 1125
1335 store_r14_indexed 320
1343 static void gpu_opcode_jump(void)
1346 const char * condition[32] =
1347 { "T", "nz", "z", "???", "nc", "nc nz", "nc z", "???", "c", "c nz",
1348 "c z", "???", "???", "???", "???", "???", "???", "???", "???",
1349 "???", "nn", "nn nz", "nn z", "???", "n", "n nz", "n z", "???",
1350 "???", "???", "???", "F" };
1352 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);
1355 /* gpu_flag_c = (gpu_flag_c ? 1 : 0);
1356 gpu_flag_z = (gpu_flag_z ? 1 : 0);
1357 gpu_flag_n = (gpu_flag_n ? 1 : 0);*/
1358 // KLUDGE: Used by BRANCH_CONDITION
1359 uint32 jaguar_flags = (gpu_flag_n << 2) | (gpu_flag_c << 1) | gpu_flag_z;
1361 if (BRANCH_CONDITION(IMM_2))
1365 WriteLog("Branched!\n");
1368 WriteLog(" --> JUMP: Branch taken.\n");
1369 uint32 delayed_pc = RM;
1371 gpu_pc = delayed_pc;
1372 /* uint16 opcode = GPUReadWord(gpu_pc, GPU);
1373 gpu_opcode_first_parameter = (opcode >> 5) & 0x1F;
1374 gpu_opcode_second_parameter = opcode & 0x1F;
1376 gpu_pc = delayed_pc;
1377 gpu_opcode[opcode>>10]();//*/
1382 WriteLog("Branch NOT taken.\n");
1386 static void gpu_opcode_jr(void)
1389 const char * condition[32] =
1390 { "T", "nz", "z", "???", "nc", "nc nz", "nc z", "???", "c", "c nz",
1391 "c z", "???", "???", "???", "???", "???", "???", "???", "???",
1392 "???", "nn", "nn nz", "nn z", "???", "n", "n nz", "n z", "???",
1393 "???", "???", "???", "F" };
1395 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);
1397 /* if (CONDITION(jaguar.op & 31))
1399 int32 r1 = (INT8)((jaguar.op >> 2) & 0xF8) >> 2;
1400 uint32 newpc = jaguar.PC + r1;
1402 jaguar.op = ROPCODE(jaguar.PC);
1404 (*jaguar.table[jaguar.op >> 10])();
1406 jaguar_icount -= 3; // 3 wait states guaranteed
1409 /* gpu_flag_n = (gpu_flag_n ? 1 : 0);
1410 gpu_flag_c = (gpu_flag_c ? 1 : 0);
1411 gpu_flag_z = (gpu_flag_z ? 1 : 0);*/
1412 // KLUDGE: Used by BRANCH_CONDITION
1413 uint32 jaguar_flags = (gpu_flag_n << 2) | (gpu_flag_c << 1) | gpu_flag_z;
1415 if (BRANCH_CONDITION(IMM_2))
1419 WriteLog("Branched!\n");
1422 WriteLog(" --> JR: Branch taken.\n");
1423 int32 offset = (IMM_1 & 0x10 ? 0xFFFFFFF0 | IMM_1 : IMM_1); // Sign extend IMM_1
1424 int32 delayed_pc = gpu_pc + (offset * 2);
1426 gpu_pc = delayed_pc;
1427 /* uint16 opcode = GPUReadWord(gpu_pc, GPU);
1428 gpu_opcode_first_parameter = (opcode >> 5) & 0x1F;
1429 gpu_opcode_second_parameter = opcode & 0x1F;
1431 gpu_pc = delayed_pc;
1432 gpu_opcode[opcode>>10]();//*/
1437 WriteLog("Branch NOT taken.\n");
1441 static void gpu_opcode_add(void)
1445 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);
1447 uint32 res = RN + RM;
1448 CLR_ZNC; SET_ZNC_ADD(RN, RM, res);
1452 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);
1456 static void gpu_opcode_addc(void)
1460 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);
1462 /* int dreg = jaguar.op & 31;
1463 uint32 r1 = jaguar.r[(jaguar.op >> 5) & 31];
1464 uint32 r2 = jaguar.r[dreg];
1465 uint32 res = r2 + r1 + ((jaguar.FLAGS >> 1) & 1);
1466 jaguar.r[dreg] = res;
1467 CLR_ZNC; SET_ZNC_ADD(r2,r1,res);*/
1469 uint32 res = RN + RM + gpu_flag_c;
1470 uint32 carry = gpu_flag_c;
1471 // SET_ZNC_ADD(RN, RM, res); //???BUG??? Yes!
1472 SET_ZNC_ADD(RN + carry, RM, res);
1473 // SET_ZNC_ADD(RN, RM + carry, res);
1477 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);
1481 static void gpu_opcode_addq(void)
1485 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);
1487 uint32 r1 = gpu_convert_zero[IMM_1];
1488 uint32 res = RN + r1;
1489 CLR_ZNC; SET_ZNC_ADD(RN, r1, res);
1493 WriteLog("[NCZ:%u%u%u, R%02u=%08X]\n", gpu_flag_n, gpu_flag_c, gpu_flag_z, IMM_2, RN);
1497 static void gpu_opcode_addqt(void)
1499 #ifdef GPU_DIS_ADDQT
1501 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);
1503 RN += gpu_convert_zero[IMM_1];
1504 #ifdef GPU_DIS_ADDQT
1506 WriteLog("[NCZ:%u%u%u, R%02u=%08X]\n", gpu_flag_n, gpu_flag_c, gpu_flag_z, IMM_2, RN);
1510 static void gpu_opcode_sub(void)
1514 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);
1516 uint32 res = RN - RM;
1517 SET_ZNC_SUB(RN, RM, 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 static void gpu_opcode_subc(void)
1529 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);
1531 uint32 res = RN - RM - gpu_flag_c;
1532 uint32 borrow = gpu_flag_c;
1533 // SET_ZNC_SUB(RN, RM, res); //???BUG??? YES!!!
1534 //No matter how you do it, there is a problem. With below, it's 0-0 with carry,
1535 //and the one below it it's FFFFFFFF - FFFFFFFF with carry... !!! FIX !!!
1536 // SET_ZNC_SUB(RN - borrow, RM, res);
1537 SET_ZNC_SUB(RN, RM + borrow, res);
1541 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);
1545 N = 5, M = 3, 3 - 5 = -2, C = 1... Or, in our case:
1546 N = 0, M = 1, 0 - 1 = -1, C = 0!
1548 #define SET_C_SUB(a,b) (gpu_flag_c = ((uint32)(b) > (uint32)(a)))
1549 #define SET_ZN(r) SET_N(r); SET_Z(r)
1550 #define SET_ZNC_ADD(a,b,r) SET_N(r); SET_Z(r); SET_C_ADD(a,b)
1551 #define SET_ZNC_SUB(a,b,r) SET_N(r); SET_Z(r); SET_C_SUB(a,b)
1553 static void gpu_opcode_subq(void)
1557 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);
1559 uint32 r1 = gpu_convert_zero[IMM_1];
1560 uint32 res = RN - r1;
1561 SET_ZNC_SUB(RN, r1, res);
1565 WriteLog("[NCZ:%u%u%u, R%02u=%08X]\n", gpu_flag_n, gpu_flag_c, gpu_flag_z, IMM_2, RN);
1569 static void gpu_opcode_subqt(void)
1571 #ifdef GPU_DIS_SUBQT
1573 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);
1575 RN -= gpu_convert_zero[IMM_1];
1576 #ifdef GPU_DIS_SUBQT
1578 WriteLog("[NCZ:%u%u%u, R%02u=%08X]\n", gpu_flag_n, gpu_flag_c, gpu_flag_z, IMM_2, RN);
1582 static void gpu_opcode_cmp(void)
1586 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);
1588 uint32 res = RN - RM;
1589 SET_ZNC_SUB(RN, RM, res);
1592 WriteLog("[NCZ:%u%u%u]\n", gpu_flag_n, gpu_flag_c, gpu_flag_z);
1596 static void gpu_opcode_cmpq(void)
1598 static int32 sqtable[32] =
1599 { 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 };
1602 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);
1604 uint32 r1 = sqtable[IMM_1 & 0x1F]; // I like this better -> (INT8)(jaguar.op >> 2) >> 3;
1605 uint32 res = RN - r1;
1606 SET_ZNC_SUB(RN, r1, res);
1609 WriteLog("[NCZ:%u%u%u]\n", gpu_flag_n, gpu_flag_c, gpu_flag_z);
1613 static void gpu_opcode_and(void)
1617 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);
1623 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);
1627 static void gpu_opcode_or(void)
1631 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);
1637 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);
1641 static void gpu_opcode_xor(void)
1645 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);
1651 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);
1655 static void gpu_opcode_not(void)
1659 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);
1665 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);
1669 static void gpu_opcode_move_pc(void)
1671 #ifdef GPU_DIS_MOVEPC
1673 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);
1675 // Should be previous PC--this might not always be previous instruction!
1676 // Then again, this will point right at the *current* instruction, i.e., MOVE PC,R!
1678 #ifdef GPU_DIS_MOVEPC
1680 WriteLog("[NCZ:%u%u%u, R%02u=%08X]\n", gpu_flag_n, gpu_flag_c, gpu_flag_z, IMM_2, RN);
1684 static void gpu_opcode_sat8(void)
1688 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);
1690 RN = ((int32)RN < 0 ? 0 : (RN > 0xFF ? 0xFF : RN));
1694 WriteLog("[NCZ:%u%u%u, R%02u=%08X]\n", gpu_flag_n, gpu_flag_c, gpu_flag_z, IMM_2, RN);
1698 static void gpu_opcode_sat16(void)
1700 RN = ((int32)RN < 0 ? 0 : (RN > 0xFFFF ? 0xFFFF : RN));
1704 static void gpu_opcode_sat24(void)
1706 RN = ((int32)RN < 0 ? 0 : (RN > 0xFFFFFF ? 0xFFFFFF : RN));
1710 static void gpu_opcode_store_r14_indexed(void)
1712 #ifdef GPU_DIS_STORE14I
1714 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));
1716 GPUWriteLong(gpu_reg[14] + (gpu_convert_zero[IMM_1] << 2), RN, GPU);
1719 static void gpu_opcode_store_r15_indexed(void)
1721 #ifdef GPU_DIS_STORE15I
1723 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));
1725 GPUWriteLong(gpu_reg[15] + (gpu_convert_zero[IMM_1] << 2), RN, GPU);
1728 static void gpu_opcode_load_r14_ri(void)
1730 #ifdef GPU_DIS_LOAD14R
1732 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);
1734 RN = GPUReadLong(gpu_reg[14] + RM, GPU);
1735 #ifdef GPU_DIS_LOAD14R
1737 WriteLog("[NCZ:%u%u%u, R%02u=%08X]\n", gpu_flag_n, gpu_flag_c, gpu_flag_z, IMM_2, RN);
1741 static void gpu_opcode_load_r15_ri(void)
1743 #ifdef GPU_DIS_LOAD15R
1745 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);
1747 RN = GPUReadLong(gpu_reg[15] + RM, GPU);
1748 #ifdef GPU_DIS_LOAD15R
1750 WriteLog("[NCZ:%u%u%u, R%02u=%08X]\n", gpu_flag_n, gpu_flag_c, gpu_flag_z, IMM_2, RN);
1754 static void gpu_opcode_store_r14_ri(void)
1756 #ifdef GPU_DIS_STORE14R
1758 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]);
1760 GPUWriteLong(gpu_reg[14] + RM, RN, GPU);
1763 static void gpu_opcode_store_r15_ri(void)
1765 #ifdef GPU_DIS_STORE15R
1767 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]);
1769 GPUWriteLong(gpu_reg[15] + RM, RN, GPU);
1772 static void gpu_opcode_nop(void)
1776 WriteLog("%06X: NOP [NCZ:%u%u%u]\n", gpu_pc-2, gpu_flag_n, gpu_flag_c, gpu_flag_z);
1780 static void gpu_opcode_pack(void)
1784 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);
1788 //BUG! if (RM == 0) // Pack
1789 if (IMM_1 == 0) // Pack
1790 RN = ((val >> 10) & 0x0000F000) | ((val >> 5) & 0x00000F00) | (val & 0x000000FF);
1792 RN = ((val & 0x0000F000) << 10) | ((val & 0x00000F00) << 5) | (val & 0x000000FF);
1795 WriteLog("[NCZ:%u%u%u, R%02u=%08X]\n", gpu_flag_n, gpu_flag_c, gpu_flag_z, IMM_2, RN);
1799 static void gpu_opcode_storeb(void)
1801 #ifdef GPU_DIS_STOREB
1803 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);
1806 // Would appear to be so...!
1807 if ((RM >= 0xF03000) && (RM <= 0xF03FFF))
1808 GPUWriteLong(RM, RN & 0xFF, GPU);
1810 JaguarWriteByte(RM, RN, GPU);
1813 static void gpu_opcode_storew(void)
1815 #ifdef GPU_DIS_STOREW
1817 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);
1819 if ((RM >= 0xF03000) && (RM <= 0xF03FFF))
1820 GPUWriteLong(RM, RN & 0xFFFF, GPU);
1822 JaguarWriteWord(RM, RN, GPU);
1825 static void gpu_opcode_store(void)
1827 #ifdef GPU_DIS_STORE
1829 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);
1831 GPUWriteLong(RM, RN, GPU);
1834 static void gpu_opcode_storep(void)
1836 GPUWriteLong(RM + 0, gpu_hidata, GPU);
1837 GPUWriteLong(RM + 4, RN, GPU);
1840 static void gpu_opcode_loadb(void)
1842 #ifdef GPU_DIS_LOADB
1844 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);
1846 if ((RM >= 0xF03000) && (RM <= 0xF03FFF))
1847 RN = GPUReadLong(RM, GPU) & 0xFF;
1849 RN = JaguarReadByte(RM, GPU);
1850 #ifdef GPU_DIS_LOADB
1852 WriteLog("[NCZ:%u%u%u, R%02u=%08X]\n", gpu_flag_n, gpu_flag_c, gpu_flag_z, IMM_2, RN);
1856 static void gpu_opcode_loadw(void)
1858 #ifdef GPU_DIS_LOADW
1860 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);
1862 if ((RM >= 0xF03000) && (RM <= 0xF03FFF))
1863 RN = GPUReadLong(RM, GPU) & 0xFFFF;
1865 RN = JaguarReadWord(RM, GPU);
1866 #ifdef GPU_DIS_LOADW
1868 WriteLog("[NCZ:%u%u%u, R%02u=%08X]\n", gpu_flag_n, gpu_flag_c, gpu_flag_z, IMM_2, RN);
1872 static void gpu_opcode_load(void)
1876 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);
1878 RN = GPUReadLong(RM, GPU);
1881 WriteLog("[NCZ:%u%u%u, R%02u=%08X]\n", gpu_flag_n, gpu_flag_c, gpu_flag_z, IMM_2, RN);
1885 static void gpu_opcode_loadp(void)
1887 gpu_hidata = GPUReadLong(RM + 0, GPU);
1888 RN = GPUReadLong(RM + 4, GPU);
1891 static void gpu_opcode_load_r14_indexed(void)
1893 #ifdef GPU_DIS_LOAD14I
1895 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);
1897 RN = GPUReadLong(gpu_reg[14] + (gpu_convert_zero[IMM_1] << 2), GPU);
1898 #ifdef GPU_DIS_LOAD14I
1900 WriteLog("[NCZ:%u%u%u, R%02u=%08X]\n", gpu_flag_n, gpu_flag_c, gpu_flag_z, IMM_2, RN);
1904 static void gpu_opcode_load_r15_indexed(void)
1906 #ifdef GPU_DIS_LOAD15I
1908 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);
1910 RN = GPUReadLong(gpu_reg[15] + (gpu_convert_zero[IMM_1] << 2), GPU);
1911 #ifdef GPU_DIS_LOAD15I
1913 WriteLog("[NCZ:%u%u%u, R%02u=%08X]\n", gpu_flag_n, gpu_flag_c, gpu_flag_z, IMM_2, RN);
1917 static void gpu_opcode_movei(void)
1919 #ifdef GPU_DIS_MOVEI
1921 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);
1923 // This instruction is followed by 32-bit value in LSW / MSW format...
1924 RN = (uint32)GPUReadWord(gpu_pc, GPU) | ((uint32)GPUReadWord(gpu_pc + 2, GPU) << 16);
1926 #ifdef GPU_DIS_MOVEI
1928 WriteLog("[NCZ:%u%u%u, R%02u=%08X]\n", gpu_flag_n, gpu_flag_c, gpu_flag_z, IMM_2, RN);
1932 static void gpu_opcode_moveta(void)
1934 #ifdef GPU_DIS_MOVETA
1936 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);
1939 #ifdef GPU_DIS_MOVETA
1941 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);
1945 static void gpu_opcode_movefa(void)
1947 #ifdef GPU_DIS_MOVEFA
1949 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);
1952 #ifdef GPU_DIS_MOVEFA
1954 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);
1958 static void gpu_opcode_move(void)
1962 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);
1967 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);
1971 static void gpu_opcode_moveq(void)
1973 #ifdef GPU_DIS_MOVEQ
1975 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);
1978 #ifdef GPU_DIS_MOVEQ
1980 WriteLog("[NCZ:%u%u%u, R%02u=%08X]\n", gpu_flag_n, gpu_flag_c, gpu_flag_z, IMM_2, RN);
1984 static void gpu_opcode_resmac(void)
1989 static void gpu_opcode_imult(void)
1991 #ifdef GPU_DIS_IMULT
1993 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);
1995 RN = (int16)RN * (int16)RM;
1997 #ifdef GPU_DIS_IMULT
1999 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);
2003 static void gpu_opcode_mult(void)
2007 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);
2009 RN = (uint16)RM * (uint16)RN;
2013 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);
2017 static void gpu_opcode_bclr(void)
2021 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);
2023 uint32 res = RN & ~(1 << IMM_1);
2028 WriteLog("[NCZ:%u%u%u, R%02u=%08X]\n", gpu_flag_n, gpu_flag_c, gpu_flag_z, IMM_2, RN);
2032 static void gpu_opcode_btst(void)
2036 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);
2038 gpu_flag_z = (~RN >> IMM_1) & 1;
2041 WriteLog("[NCZ:%u%u%u, R%02u=%08X]\n", gpu_flag_n, gpu_flag_c, gpu_flag_z, IMM_2, RN);
2045 static void gpu_opcode_bset(void)
2049 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);
2051 uint32 res = RN | (1 << IMM_1);
2056 WriteLog("[NCZ:%u%u%u, R%02u=%08X]\n", gpu_flag_n, gpu_flag_c, gpu_flag_z, IMM_2, RN);
2060 static void gpu_opcode_imacn(void)
2062 uint32 res = (int16)RM * (int16)(RN);
2066 static void gpu_opcode_mtoi(void)
2069 uint32 res = RN = (((int32)_RM >> 8) & 0xFF800000) | (_RM & 0x007FFFFF);
2073 static void gpu_opcode_normi(void)
2080 while ((_RM & 0xFFC00000) == 0)
2085 while ((_RM & 0xFF800000) != 0)
2095 static void gpu_opcode_mmult(void)
2097 int count = gpu_matrix_control & 0x0F; // Matrix width
2098 uint32 addr = gpu_pointer_to_matrix; // In the GPU's RAM
2102 if (gpu_matrix_control & 0x10) // Column stepping
2104 for(int i=0; i<count; i++)
2108 a = (int16)((gpu_alternate_reg[IMM_1 + (i >> 1)] >> 16) & 0xFFFF);
2110 a = (int16)(gpu_alternate_reg[IMM_1 + (i >> 1)] & 0xFFFF);
2112 int16 b = ((int16)GPUReadWord(addr + 2, GPU));
2117 else // Row stepping
2119 for(int i=0; i<count; i++)
2123 a = (int16)((gpu_alternate_reg[IMM_1 + (i >> 1)] >> 16) & 0xFFFF);
2125 a = (int16)(gpu_alternate_reg[IMM_1 + (i >> 1)] & 0xFFFF);
2127 int16 b = ((int16)GPUReadWord(addr + 2, GPU));
2132 RN = res = (int32)accum;
2133 // carry flag to do (out of the last add)
2137 static void gpu_opcode_abs(void)
2141 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);
2143 gpu_flag_c = RN >> 31;
2144 if (RN == 0x80000000)
2145 //Is 0x80000000 a positive number? If so, then we need to set C to 0 as well!
2146 gpu_flag_n = 1, gpu_flag_z = 0;
2151 gpu_flag_n = 0; SET_FLAG_Z(RN);
2155 WriteLog("[NCZ:%u%u%u, R%02u=%08X]\n", gpu_flag_n, gpu_flag_c, gpu_flag_z, IMM_2, RN);
2159 static void gpu_opcode_div(void) // RN / RM
2163 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);
2165 // NOTE: remainder is NOT calculated correctly here!
2166 // The original tried to get it right by checking to see if the
2167 // remainder was negative, but that's too late...
2168 // The code there should do it now, but I'm not 100% sure...
2172 if (gpu_div_control & 0x01) // 16.16 division
2174 RN = ((uint64)RN << 16) / RM;
2175 gpu_remain = ((uint64)RN << 16) % RM;
2180 gpu_remain = RN % RM;
2183 if ((gpu_remain - RM) & 0x80000000) // If the result would have been negative...
2184 gpu_remain -= RM; // Then make it negative!
2194 if (gpu_div_control & 1)
2196 gpu_remain = (((uint64)_RN) << 16) % _RM;
2197 if (gpu_remain&0x80000000)
2199 RN = (((uint64)_RN) << 16) / _RM;
2203 gpu_remain = _RN % _RM;
2204 if (gpu_remain&0x80000000)
2213 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);
2217 static void gpu_opcode_imultn(void)
2219 uint32 res = (int32)((int16)RN * (int16)RM);
2220 gpu_acc = (int32)res;
2225 static void gpu_opcode_neg(void)
2229 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);
2232 SET_ZNC_SUB(0, RN, res);
2236 WriteLog("[NCZ:%u%u%u, R%02u=%08X]\n", gpu_flag_n, gpu_flag_c, gpu_flag_z, IMM_2, RN);
2240 static void gpu_opcode_shlq(void)
2244 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);
2246 // Was a bug here...
2247 // (Look at Aaron's code: If r1 = 32, then 32 - 32 = 0 which is wrong!)
2248 int32 r1 = 32 - IMM_1;
2249 uint32 res = RN << r1;
2250 SET_ZN(res); gpu_flag_c = (RN >> 31) & 1;
2254 WriteLog("[NCZ:%u%u%u, R%02u=%08X]\n", gpu_flag_n, gpu_flag_c, gpu_flag_z, IMM_2, RN);
2258 static void gpu_opcode_shrq(void)
2262 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);
2264 int32 r1 = gpu_convert_zero[IMM_1];
2265 uint32 res = RN >> r1;
2266 SET_ZN(res); gpu_flag_c = RN & 1;
2270 WriteLog("[NCZ:%u%u%u, R%02u=%08X]\n", gpu_flag_n, gpu_flag_c, gpu_flag_z, IMM_2, RN);
2274 static void gpu_opcode_ror(void)
2278 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);
2280 uint32 r1 = RM & 0x1F;
2281 uint32 res = (RN >> r1) | (RN << (32 - r1));
2282 SET_ZN(res); gpu_flag_c = (RN >> 31) & 1;
2286 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);
2290 static void gpu_opcode_rorq(void)
2294 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);
2296 uint32 r1 = gpu_convert_zero[IMM_1 & 0x1F];
2298 uint32 res = (r2 >> r1) | (r2 << (32 - r1));
2300 SET_ZN(res); gpu_flag_c = (r2 >> 31) & 0x01;
2303 WriteLog("[NCZ:%u%u%u, R%02u=%08X]\n", gpu_flag_n, gpu_flag_c, gpu_flag_z, IMM_2, RN);
2307 static void gpu_opcode_sha(void)
2309 /* int dreg = jaguar.op & 31;
2310 int32 r1 = (int32)jaguar.r[(jaguar.op >> 5) & 31];
2311 uint32 r2 = jaguar.r[dreg];
2317 res = (r1 <= -32) ? 0 : (r2 << -r1);
2318 jaguar.FLAGS |= (r2 >> 30) & 2;
2322 res = (r1 >= 32) ? ((int32)r2 >> 31) : ((int32)r2 >> r1);
2323 jaguar.FLAGS |= (r2 << 1) & 2;
2325 jaguar.r[dreg] = res;
2330 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);
2336 res = ((int32)RM <= -32) ? 0 : (RN << -(int32)RM);
2337 gpu_flag_c = RN >> 31;
2341 res = ((int32)RM >= 32) ? ((int32)RN >> 31) : ((int32)RN >> (int32)RM);
2342 gpu_flag_c = RN & 0x01;
2348 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);
2351 /* int32 sRM=(int32)RM;
2357 if (shift>=32) shift=32;
2358 gpu_flag_c=(_RN&0x80000000)>>31;
2368 if (shift>=32) shift=32;
2372 _RN=((int32)_RN)>>1;
2381 static void gpu_opcode_sharq(void)
2383 #ifdef GPU_DIS_SHARQ
2385 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);
2387 uint32 res = (int32)RN >> gpu_convert_zero[IMM_1];
2388 SET_ZN(res); gpu_flag_c = RN & 0x01;
2390 #ifdef GPU_DIS_SHARQ
2392 WriteLog("[NCZ:%u%u%u, R%02u=%08X]\n", gpu_flag_n, gpu_flag_c, gpu_flag_z, IMM_2, RN);
2396 static void gpu_opcode_sh(void)
2400 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);
2402 if (RM & 0x80000000) // Shift left
2404 gpu_flag_c = RN >> 31;
2405 RN = ((int32)RM <= -32 ? 0 : RN << -(int32)RM);
2409 gpu_flag_c = RN & 0x01;
2410 RN = (RM >= 32 ? 0 : RN >> RM);
2415 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);
2419 //Temporary: Testing only!
2420 //#include "gpu2.cpp"
2421 //#include "gpu3.cpp"