6 // Originally by David Raingeard (Cal2)
7 // GCC/SDL port by Niels Wagenaar (Linux/WIN32) and Caz (BeOS)
8 // Cleanups, endian wrongness, and bad ASM amelioration by James L. Hammons
9 // Note: Endian wrongness probably stems from the MAME origins of this emu and
10 // the braindead way in which MAME handles memory. :-)
12 // Problem with not booting the BIOS was the incorrect way that the
13 // SUBC instruction set the carry when the carry was set going in...
14 // Same problem with ADDC...
20 #include <string.h> // For memset
31 // For GPU dissasembly...
51 #define GPU_DIS_LOAD14I
52 #define GPU_DIS_LOAD14R
53 #define GPU_DIS_LOAD15I
54 #define GPU_DIS_LOAD15R
56 #define GPU_DIS_MOVEFA
58 #define GPU_DIS_MOVEPC
59 #define GPU_DIS_MOVETA
76 #define GPU_DIS_STOREB
77 #define GPU_DIS_STOREW
78 #define GPU_DIS_STORE14I
79 #define GPU_DIS_STORE14R
80 #define GPU_DIS_STORE15I
81 #define GPU_DIS_STORE15R
88 bool doGPUDis = false;
89 //bool doGPUDis = true;
92 GPU opcodes use (BIOS flying ATARI logo):
134 #define CINT0FLAG 0x0200
135 #define CINT1FLAG 0x0400
136 #define CINT2FLAG 0x0800
137 #define CINT3FLAG 0x1000
138 #define CINT4FLAG 0x2000
139 #define CINT04FLAGS (CINT0FLAG | CINT1FLAG | CINT2FLAG | CINT3FLAG | CINT4FLAG)
143 #define ZERO_FLAG 0x0001
144 #define CARRY_FLAG 0x0002
145 #define NEGA_FLAG 0x0004
147 #define INT_ENA0 0x0010
148 #define INT_ENA1 0x0020
149 #define INT_ENA2 0x0040
150 #define INT_ENA3 0x0080
151 #define INT_ENA4 0x0100
152 #define INT_CLR0 0x0200
153 #define INT_CLR1 0x0400
154 #define INT_CLR2 0x0800
155 #define INT_CLR3 0x1000
156 #define INT_CLR4 0x2000
157 #define REGPAGE 0x4000
160 // External global variables
162 extern int start_logging;
163 extern int gpu_start_log;
165 // Private function prototypes
167 void GPUUpdateRegisterBanks(void);
168 void GPUDumpDisassembly(void);
169 void GPUDumpRegisters(void);
170 void GPUDumpMemory(void);
172 static void gpu_opcode_add(void);
173 static void gpu_opcode_addc(void);
174 static void gpu_opcode_addq(void);
175 static void gpu_opcode_addqt(void);
176 static void gpu_opcode_sub(void);
177 static void gpu_opcode_subc(void);
178 static void gpu_opcode_subq(void);
179 static void gpu_opcode_subqt(void);
180 static void gpu_opcode_neg(void);
181 static void gpu_opcode_and(void);
182 static void gpu_opcode_or(void);
183 static void gpu_opcode_xor(void);
184 static void gpu_opcode_not(void);
185 static void gpu_opcode_btst(void);
186 static void gpu_opcode_bset(void);
187 static void gpu_opcode_bclr(void);
188 static void gpu_opcode_mult(void);
189 static void gpu_opcode_imult(void);
190 static void gpu_opcode_imultn(void);
191 static void gpu_opcode_resmac(void);
192 static void gpu_opcode_imacn(void);
193 static void gpu_opcode_div(void);
194 static void gpu_opcode_abs(void);
195 static void gpu_opcode_sh(void);
196 static void gpu_opcode_shlq(void);
197 static void gpu_opcode_shrq(void);
198 static void gpu_opcode_sha(void);
199 static void gpu_opcode_sharq(void);
200 static void gpu_opcode_ror(void);
201 static void gpu_opcode_rorq(void);
202 static void gpu_opcode_cmp(void);
203 static void gpu_opcode_cmpq(void);
204 static void gpu_opcode_sat8(void);
205 static void gpu_opcode_sat16(void);
206 static void gpu_opcode_move(void);
207 static void gpu_opcode_moveq(void);
208 static void gpu_opcode_moveta(void);
209 static void gpu_opcode_movefa(void);
210 static void gpu_opcode_movei(void);
211 static void gpu_opcode_loadb(void);
212 static void gpu_opcode_loadw(void);
213 static void gpu_opcode_load(void);
214 static void gpu_opcode_loadp(void);
215 static void gpu_opcode_load_r14_indexed(void);
216 static void gpu_opcode_load_r15_indexed(void);
217 static void gpu_opcode_storeb(void);
218 static void gpu_opcode_storew(void);
219 static void gpu_opcode_store(void);
220 static void gpu_opcode_storep(void);
221 static void gpu_opcode_store_r14_indexed(void);
222 static void gpu_opcode_store_r15_indexed(void);
223 static void gpu_opcode_move_pc(void);
224 static void gpu_opcode_jump(void);
225 static void gpu_opcode_jr(void);
226 static void gpu_opcode_mmult(void);
227 static void gpu_opcode_mtoi(void);
228 static void gpu_opcode_normi(void);
229 static void gpu_opcode_nop(void);
230 static void gpu_opcode_load_r14_ri(void);
231 static void gpu_opcode_load_r15_ri(void);
232 static void gpu_opcode_store_r14_ri(void);
233 static void gpu_opcode_store_r15_ri(void);
234 static void gpu_opcode_sat24(void);
235 static void gpu_opcode_pack(void);
237 // This is wrong, since it doesn't take pipeline effects into account. !!! FIX !!!
238 /*uint8 gpu_opcode_cycles[64] =
240 3, 3, 3, 3, 3, 3, 3, 3,
241 3, 3, 3, 3, 3, 3, 3, 3,
242 3, 3, 1, 3, 1, 18, 3, 3,
243 3, 3, 3, 3, 3, 3, 3, 3,
244 3, 3, 2, 2, 2, 2, 3, 4,
245 5, 4, 5, 6, 6, 1, 1, 1,
246 1, 2, 2, 2, 1, 1, 9, 3,
247 3, 1, 6, 6, 2, 2, 3, 3
249 //Here's a QnD kludge...
250 //This is wrong, wrong, WRONG, but it seems to work for the time being...
251 //(That is, it fixes Flip Out which relies on GPU timing rather than semaphores. Bad developers! Bad!)
252 //What's needed here is a way to take pipeline effects into account (including pipeline stalls!)...
253 /*uint8 gpu_opcode_cycles[64] =
255 1, 1, 1, 1, 1, 1, 1, 1,
256 1, 1, 1, 1, 1, 1, 1, 1,
257 1, 1, 1, 1, 1, 9, 1, 1,
258 1, 1, 1, 1, 1, 1, 1, 1,
259 1, 1, 1, 1, 1, 1, 1, 2,
260 2, 2, 2, 3, 3, 1, 1, 1,
261 1, 1, 1, 1, 1, 1, 4, 1,
262 1, 1, 3, 3, 1, 1, 1, 1
264 uint8 gpu_opcode_cycles[64] =
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,
272 1, 1, 1, 1, 1, 1, 1, 1,
273 1, 1, 1, 1, 1, 1, 1, 1
276 void (*gpu_opcode[64])()=
278 gpu_opcode_add, gpu_opcode_addc, gpu_opcode_addq, gpu_opcode_addqt,
279 gpu_opcode_sub, gpu_opcode_subc, gpu_opcode_subq, gpu_opcode_subqt,
280 gpu_opcode_neg, gpu_opcode_and, gpu_opcode_or, gpu_opcode_xor,
281 gpu_opcode_not, gpu_opcode_btst, gpu_opcode_bset, gpu_opcode_bclr,
282 gpu_opcode_mult, gpu_opcode_imult, gpu_opcode_imultn, gpu_opcode_resmac,
283 gpu_opcode_imacn, gpu_opcode_div, gpu_opcode_abs, gpu_opcode_sh,
284 gpu_opcode_shlq, gpu_opcode_shrq, gpu_opcode_sha, gpu_opcode_sharq,
285 gpu_opcode_ror, gpu_opcode_rorq, gpu_opcode_cmp, gpu_opcode_cmpq,
286 gpu_opcode_sat8, gpu_opcode_sat16, gpu_opcode_move, gpu_opcode_moveq,
287 gpu_opcode_moveta, gpu_opcode_movefa, gpu_opcode_movei, gpu_opcode_loadb,
288 gpu_opcode_loadw, gpu_opcode_load, gpu_opcode_loadp, gpu_opcode_load_r14_indexed,
289 gpu_opcode_load_r15_indexed, gpu_opcode_storeb, gpu_opcode_storew, gpu_opcode_store,
290 gpu_opcode_storep, gpu_opcode_store_r14_indexed, gpu_opcode_store_r15_indexed, gpu_opcode_move_pc,
291 gpu_opcode_jump, gpu_opcode_jr, gpu_opcode_mmult, gpu_opcode_mtoi,
292 gpu_opcode_normi, gpu_opcode_nop, gpu_opcode_load_r14_ri, gpu_opcode_load_r15_ri,
293 gpu_opcode_store_r14_ri, gpu_opcode_store_r15_ri, gpu_opcode_sat24, gpu_opcode_pack,
296 static uint8 gpu_ram_8[0x1000];
298 static uint32 gpu_acc;
299 static uint32 gpu_remain;
300 static uint32 gpu_hidata;
301 static uint32 gpu_flags;
302 static uint32 gpu_matrix_control;
303 static uint32 gpu_pointer_to_matrix;
304 static uint32 gpu_data_organization;
305 static uint32 gpu_control;
306 static uint32 gpu_div_control;
307 // There is a distinct advantage to having these separated out--there's no need to clear
308 // a bit before writing a result. I.e., if the result of an operation leaves a zero in
309 // the carry flag, you don't have to zero gpu_flag_c before you can write that zero!
310 static uint8 gpu_flag_z, gpu_flag_n, gpu_flag_c;
311 static uint32 gpu_reg_bank_0[32];
312 static uint32 gpu_reg_bank_1[32];
313 static uint32 * gpu_reg;
314 static uint32 * gpu_alternate_reg;
316 static uint32 gpu_instruction;
317 static uint32 gpu_opcode_first_parameter;
318 static uint32 gpu_opcode_second_parameter;
320 #define GPU_RUNNING (gpu_control & 0x01)
322 #define RM gpu_reg[gpu_opcode_first_parameter]
323 #define RN gpu_reg[gpu_opcode_second_parameter]
324 #define ALTERNATE_RM gpu_alternate_reg[gpu_opcode_first_parameter]
325 #define ALTERNATE_RN gpu_alternate_reg[gpu_opcode_second_parameter]
326 #define IMM_1 gpu_opcode_first_parameter
327 #define IMM_2 gpu_opcode_second_parameter
329 #define SET_FLAG_Z(r) (gpu_flag_z = ((r) == 0));
330 #define SET_FLAG_N(r) (gpu_flag_n = (((uint32)(r) >> 31) & 0x01));
332 #define RESET_FLAG_Z() gpu_flag_z = 0;
333 #define RESET_FLAG_N() gpu_flag_n = 0;
334 #define RESET_FLAG_C() gpu_flag_c = 0;
336 #define CLR_Z (gpu_flag_z = 0)
337 #define CLR_ZN (gpu_flag_z = gpu_flag_n = 0)
338 #define CLR_ZNC (gpu_flag_z = gpu_flag_n = gpu_flag_c = 0)
339 #define SET_Z(r) (gpu_flag_z = ((r) == 0))
340 #define SET_N(r) (gpu_flag_n = (((uint32)(r) >> 31) & 0x01))
341 #define SET_C_ADD(a,b) (gpu_flag_c = ((uint32)(b) > (uint32)(~(a))))
342 #define SET_C_SUB(a,b) (gpu_flag_c = ((uint32)(b) > (uint32)(a)))
343 #define SET_ZN(r) SET_N(r); SET_Z(r)
344 #define SET_ZNC_ADD(a,b,r) SET_N(r); SET_Z(r); SET_C_ADD(a,b)
345 #define SET_ZNC_SUB(a,b,r) SET_N(r); SET_Z(r); SET_C_SUB(a,b)
347 uint32 gpu_convert_zero[32] =
348 { 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 };
350 uint8 * branch_condition_table = 0;
351 #define BRANCH_CONDITION(x) branch_condition_table[(x) + ((jaguar_flags & 7) << 5)]
353 uint32 gpu_opcode_use[64];
355 const char * gpu_opcode_str[64]=
357 "add", "addc", "addq", "addqt",
358 "sub", "subc", "subq", "subqt",
359 "neg", "and", "or", "xor",
360 "not", "btst", "bset", "bclr",
361 "mult", "imult", "imultn", "resmac",
362 "imacn", "div", "abs", "sh",
363 "shlq", "shrq", "sha", "sharq",
364 "ror", "rorq", "cmp", "cmpq",
365 "sat8", "sat16", "move", "moveq",
366 "moveta", "movefa", "movei", "loadb",
367 "loadw", "load", "loadp", "load_r14_indexed",
368 "load_r15_indexed", "storeb", "storew", "store",
369 "storep", "store_r14_indexed","store_r15_indexed","move_pc",
370 "jump", "jr", "mmult", "mtoi",
371 "normi", "nop", "load_r14_ri", "load_r15_ri",
372 "store_r14_ri", "store_r15_ri", "sat24", "pack",
375 static uint32 gpu_in_exec = 0;
376 static uint32 gpu_releaseTimeSlice_flag = 0;
378 void GPUReleaseTimeslice(void)
380 gpu_releaseTimeSlice_flag = 1;
383 uint32 GPUGetPC(void)
388 void build_branch_condition_table(void)
390 if (!branch_condition_table)
392 branch_condition_table = (uint8 *)malloc(32 * 8 * sizeof(branch_condition_table[0]));
394 if (branch_condition_table)
396 for(int i=0; i<8; i++)
398 for(int j=0; j<32; j++)
405 if (!(i & ZERO_FLAG))
408 if (i & (CARRY_FLAG << (j >> 4)))
411 if (!(i & (CARRY_FLAG << (j >> 4))))
413 branch_condition_table[i * 32 + j] = result;
421 // GPU byte access (read)
423 uint8 GPUReadByte(uint32 offset, uint32 who/*=UNKNOWN*/)
425 if (offset >= 0xF02000 && offset <= 0xF020FF)
426 WriteLog("GPU: ReadByte--Attempt to read from GPU register file by %s!\n", whoName[who]);
428 if ((offset >= GPU_WORK_RAM_BASE) && (offset < GPU_WORK_RAM_BASE+0x1000))
429 return gpu_ram_8[offset & 0xFFF];
430 else if ((offset >= GPU_CONTROL_RAM_BASE) && (offset < GPU_CONTROL_RAM_BASE+0x20))
432 uint32 data = GPUReadLong(offset & 0xFFFFFFFC, who);
434 if ((offset & 0x03) == 0)
436 else if ((offset & 0x03) == 1)
437 return (data >> 16) & 0xFF;
438 else if ((offset & 0x03) == 2)
439 return (data >> 8) & 0xFF;
440 else if ((offset & 0x03) == 3)
444 return JaguarReadByte(offset, who);
448 // GPU word access (read)
450 uint16 GPUReadWord(uint32 offset, uint32 who/*=UNKNOWN*/)
452 if (offset >= 0xF02000 && offset <= 0xF020FF)
453 WriteLog("GPU: ReadWord--Attempt to read from GPU register file by %s!\n", whoName[who]);
455 if ((offset >= GPU_WORK_RAM_BASE) && (offset < GPU_WORK_RAM_BASE+0x1000))
458 uint16 data = ((uint16)gpu_ram_8[offset] << 8) | (uint16)gpu_ram_8[offset+1];
461 else if ((offset >= GPU_CONTROL_RAM_BASE) && (offset < GPU_CONTROL_RAM_BASE+0x20))
463 // This looks and smells wrong...
464 // But it *might* be OK...
465 if (offset & 0x01) // Catch cases 1 & 3... (unaligned read)
466 return (GPUReadByte(offset, who) << 8) | GPUReadByte(offset+1, who);
468 uint32 data = GPUReadLong(offset & 0xFFFFFFFC, who);
470 if (offset & 0x02) // Cases 0 & 2...
471 return data & 0xFFFF;
476 //TEMP--Mirror of F03000? No. Writes only...
477 //if (offset >= 0xF0B000 && offset <= 0xF0BFFF)
478 //WriteLog("[GPUR16] --> Possible GPU RAM mirror access by %s!", whoName[who]);
480 return JaguarReadWord(offset, who);
484 // GPU dword access (read)
486 uint32 GPUReadLong(uint32 offset, uint32 who/*=UNKNOWN*/)
488 if (offset >= 0xF02000 && offset <= 0xF020FF)
489 WriteLog("GPU: ReadLong--Attempt to read from GPU register file by %s!\n", whoName[who]);
491 // if ((offset >= GPU_WORK_RAM_BASE) && (offset < GPU_WORK_RAM_BASE + 0x1000))
492 if ((offset >= GPU_WORK_RAM_BASE) && (offset <= GPU_WORK_RAM_BASE + 0x0FFC))
495 return ((uint32)gpu_ram_8[offset] << 24) | ((uint32)gpu_ram_8[offset+1] << 16)
496 | ((uint32)gpu_ram_8[offset+2] << 8) | (uint32)gpu_ram_8[offset+3];//*/
497 // return GET32(gpu_ram_8, offset);
499 // else if ((offset >= GPU_CONTROL_RAM_BASE) && (offset < GPU_CONTROL_RAM_BASE+0x20))
500 else if ((offset >= GPU_CONTROL_RAM_BASE) && (offset <= GPU_CONTROL_RAM_BASE + 0x1C))
506 gpu_flag_c = (gpu_flag_c ? 1 : 0);
507 gpu_flag_z = (gpu_flag_z ? 1 : 0);
508 gpu_flag_n = (gpu_flag_n ? 1 : 0);
510 gpu_flags = (gpu_flags & 0xFFFFFFF8) | (gpu_flag_n << 2) | (gpu_flag_c << 1) | gpu_flag_z;
512 return gpu_flags & 0xFFFFC1FF;
514 return gpu_matrix_control;
516 return gpu_pointer_to_matrix;
518 return gpu_data_organization;
527 default: // unaligned long read
529 WriteLog("GPU: Read32--unaligned 32 bit read at %08X by %s.\n", GPU_CONTROL_RAM_BASE + offset, whoName[who]);
534 //TEMP--Mirror of F03000? No. Writes only...
535 //if (offset >= 0xF0B000 && offset <= 0xF0BFFF)
536 // WriteLog("[GPUR32] --> Possible GPU RAM mirror access by %s!\n", whoName[who]);
537 /*if (offset >= 0xF1D000 && offset <= 0xF1DFFF)
538 WriteLog("[GPUR32] --> Reading from Wavetable ROM!\n");//*/
540 return (JaguarReadWord(offset, who) << 16) | JaguarReadWord(offset + 2, who);
544 // GPU byte access (write)
546 void GPUWriteByte(uint32 offset, uint8 data, uint32 who/*=UNKNOWN*/)
548 if (offset >= 0xF02000 && offset <= 0xF020FF)
549 WriteLog("GPU: WriteByte--Attempt to write to GPU register file by %s!\n", whoName[who]);
551 if ((offset >= GPU_WORK_RAM_BASE) && (offset <= GPU_WORK_RAM_BASE + 0x0FFF))
553 gpu_ram_8[offset & 0xFFF] = data;
555 //This is the same stupid worthless code that was in the DSP!!! AARRRGGGGHHHHH!!!!!!
558 m68k_end_timeslice();
559 dsp_releaseTimeslice();
563 else if ((offset >= GPU_CONTROL_RAM_BASE) && (offset <= GPU_CONTROL_RAM_BASE + 0x1F))
565 uint32 reg = offset & 0x1C;
566 int bytenum = offset & 0x03;
568 //This is definitely wrong!
569 if ((reg >= 0x1C) && (reg <= 0x1F))
570 gpu_div_control = (gpu_div_control & (~(0xFF << (bytenum << 3)))) | (data << (bytenum << 3));
573 uint32 old_data = GPUReadLong(offset & 0xFFFFFFC, who);
574 bytenum = 3 - bytenum; // convention motorola !!!
575 old_data = (old_data & (~(0xFF << (bytenum << 3)))) | (data << (bytenum << 3));
576 GPUWriteLong(offset & 0xFFFFFFC, old_data, who);
580 // WriteLog("gpu: writing %.2x at 0x%.8x\n",data,offset);
581 JaguarWriteByte(offset, data, who);
585 // GPU word access (write)
587 void GPUWriteWord(uint32 offset, uint16 data, uint32 who/*=UNKNOWN*/)
589 if (offset >= 0xF02000 && offset <= 0xF020FF)
590 WriteLog("GPU: WriteWord--Attempt to write to GPU register file by %s!\n", whoName[who]);
592 if ((offset >= GPU_WORK_RAM_BASE) && (offset <= GPU_WORK_RAM_BASE + 0x0FFE))
594 gpu_ram_8[offset & 0xFFF] = (data>>8) & 0xFF;
595 gpu_ram_8[(offset+1) & 0xFFF] = data & 0xFF;//*/
597 SET16(gpu_ram_8, offset, data);//*/
599 /*if (offset >= 0xF03214 && offset < 0xF0321F)
600 WriteLog("GPU: Writing WORD (%04X) to GPU RAM (%08X)...\n", data, offset);//*/
603 //This is the same stupid worthless code that was in the DSP!!! AARRRGGGGHHHHH!!!!!!
606 m68k_end_timeslice();
607 dsp_releaseTimeslice();
611 else if ((offset >= GPU_CONTROL_RAM_BASE) && (offset <= GPU_CONTROL_RAM_BASE + 0x1E))
613 if (offset & 0x01) // This is supposed to weed out unaligned writes, but does nothing...
616 WriteLog("GPU: Write16--unaligned write @ %08X [%04X]\n", offset, data);
621 //Dual locations in this range: $1C Divide unit remainder/Divide unit control (R/W)
622 //This just literally sucks.
623 if ((offset & 0x1C) == 0x1C)
625 //This doesn't look right either--handles cases 1, 2, & 3 all the same!
627 gpu_div_control = (gpu_div_control & 0xFFFF0000) | (data & 0xFFFF);
629 gpu_div_control = (gpu_div_control & 0x0000FFFF) | ((data & 0xFFFF) << 16);
633 //WriteLog("[GPU W16:%08X,%04X]", offset, data);
634 uint32 old_data = GPUReadLong(offset & 0xFFFFFFC, who);
636 old_data = (old_data & 0xFFFF0000) | (data & 0xFFFF);
638 old_data = (old_data & 0x0000FFFF) | ((data & 0xFFFF) << 16);
639 GPUWriteLong(offset & 0xFFFFFFC, old_data, who);
643 else if ((offset == GPU_WORK_RAM_BASE + 0x0FFF) || (GPU_CONTROL_RAM_BASE + 0x1F))
646 WriteLog("GPU: Write16--unaligned write @ %08X by %s [%04X]!\n", offset, whoName[who], data);
652 // Have to be careful here--this can cause an infinite loop!
653 JaguarWriteWord(offset, data, who);
657 // GPU dword access (write)
659 void GPUWriteLong(uint32 offset, uint32 data, uint32 who/*=UNKNOWN*/)
661 if (offset >= 0xF02000 && offset <= 0xF020FF)
662 WriteLog("GPU: WriteLong--Attempt to write to GPU register file by %s!\n", whoName[who]);
664 // if ((offset >= GPU_WORK_RAM_BASE) && (offset < GPU_WORK_RAM_BASE + 0x1000))
665 if ((offset >= GPU_WORK_RAM_BASE) && (offset <= GPU_WORK_RAM_BASE + 0x0FFC))
670 WriteLog("GPU: Write32--unaligned write @ %08X [%08X] by %s\n", offset, data, whoName[who]);
676 SET32(gpu_ram_8, offset, data);
679 // else if ((offset >= GPU_CONTROL_RAM_BASE) && (offset < GPU_CONTROL_RAM_BASE+0x20))
680 else if ((offset >= GPU_CONTROL_RAM_BASE) && (offset <= GPU_CONTROL_RAM_BASE + 0x1C))
687 bool IMASKCleared = (gpu_flags & IMASK) && !(data & IMASK);
689 gpu_flag_z = gpu_flags & ZERO_FLAG;
690 gpu_flag_c = (gpu_flags & CARRY_FLAG) >> 1;
691 gpu_flag_n = (gpu_flags & NEGA_FLAG) >> 2;
692 GPUUpdateRegisterBanks();
693 gpu_control &= ~((gpu_flags & CINT04FLAGS) >> 3); // Interrupt latch clear bits
694 //Writing here is only an interrupt enable--this approach is just plain wrong!
696 //This, however, is A-OK! ;-)
697 if (IMASKCleared) // If IMASK was cleared,
698 GPUHandleIRQs(); // see if any other interrupts need servicing!
700 if (gpu_flags & (INT_ENA0 | INT_ENA1 | INT_ENA2 | INT_ENA3 | INT_ENA4))
701 WriteLog("GPU: Interrupt enable set by %s! Bits: %02X\n", whoName[who], (gpu_flags >> 4) & 0x1F);
702 WriteLog("GPU: REGPAGE %s...\n", (gpu_flags & REGPAGE ? "set" : "cleared"));
707 gpu_matrix_control = data;
710 // This can only point to long aligned addresses
711 gpu_pointer_to_matrix = data & 0xFFFFFFFC;
714 gpu_data_organization = data;
719 WriteLog("GPU: %s setting GPU PC to %08X %s\n", whoName[who], gpu_pc, (GPU_RUNNING ? "(GPU is RUNNING!)" : ""));//*/
724 // uint32 gpu_was_running = GPU_RUNNING;
725 data &= ~0xF7C0; // Disable writes to INT_LAT0-4 & TOM version number
727 // check for GPU -> CPU interrupt
730 //WriteLog("GPU->CPU interrupt\n");
731 if (TOMIRQEnabled(IRQ_GPU))
733 if ((TOMIRQEnabled(IRQ_GPU)) && (JaguarInterruptHandlerIsValid(64)))
735 TOMSetPendingGPUInt();
736 m68k_set_irq(7); // Set 68000 NMI
737 GPUReleaseTimeslice();
743 // check for CPU -> GPU interrupt #0
746 //WriteLog("CPU->GPU interrupt\n");
747 GPUSetIRQLine(0, ASSERT_LINE);
748 m68k_end_timeslice();
749 DSPReleaseTimeslice();
756 //WriteLog("asked to perform a single step (single step is %senabled)\n",(data&0x8)?"":"not ");
758 gpu_control = (gpu_control & 0xF7C0) | (data & (~0xF7C0));
760 // if gpu wasn't running but is now running, execute a few cycles
761 #ifndef GPU_SINGLE_STEPPING
762 /* if (!gpu_was_running && GPU_RUNNING)
765 WriteLog("GPU: Write32--About to do stupid braindead GPU execution for 200 cycles.\n");
770 #endif // GPU_DEBUG//*/
772 if (gpu_control & 0x18)
774 #endif // #ifndef GPU_SINGLE_STEPPING
776 WriteLog("Write to GPU CTRL by %s: %08X ", whoName[who], data);
778 WriteLog(" --> Starting to run at %08X by %s...", gpu_pc, whoName[who]);
780 WriteLog(" --> Stopped by %s! (GPU_PC: %08X)", whoName[who], gpu_pc);
784 // GPUDumpDisassembly();
787 if (gpu_pc == 0xF035D8)
789 // GPUDumpDisassembly();
792 gpu_control &= 0xFFFFFFFE; // Don't run it and let's see what happens!
793 //Hmm. Seems to lock up when going into the demo...
794 //Try to disable the collision altogether!
797 extern int effect_start5;
798 static bool finished = false;
799 //if (GPU_RUNNING && effect_start5 && !finished)
800 if (GPU_RUNNING && effect_start5 && gpu_pc == 0xF035D8)
802 // Let's do a dump of $6528!
803 /* uint32 numItems = JaguarReadWord(0x6BD6);
804 WriteLog("\nDump of $6528: %u items.\n\n", numItems);
805 for(int i=0; i<numItems*3*4; i+=3*4)
807 WriteLog("\t%04X: %08X %08X %08X -> ", 0x6528+i, JaguarReadLong(0x6528+i),
808 JaguarReadLong(0x6528+i+4), JaguarReadLong(0x6528+i+8));
809 uint16 link = JaguarReadWord(0x6528+i+8+2);
810 for(int j=0; j<40; j+=4)
811 WriteLog("%08X ", JaguarReadLong(link + j));
815 // Let's try a manual blit here...
816 //This isn't working the way it should! !!! FIX !!!
817 //Err, actually, it is.
818 // NOW, it works right! Problem solved!!! It's a blitter bug!
819 /* uint32 src = 0x4D54, dst = 0xF03000, width = 10 * 4;
820 for(int y=0; y<127; y++)
822 for(int x=0; x<2; x++)
824 JaguarWriteLong(dst, JaguarReadLong(src));
829 src += width - (2 * 4);
833 WriteLog("\nGPU: About to execute collision detection code.\n\n");//*/
835 /* WriteLog("\nGPU: About to execute collision detection code. Data @ 4D54:\n\n");
837 for(int i=0x004D54; i<0x004D54+2048; i++)
839 WriteLog("%02X ", JaguarReadByte(i));
847 WriteLog("\n\nData @ F03000:\n\n");
849 for(int i=0xF03000; i<0xF03200; i++)
851 WriteLog("%02X ", JaguarReadByte(i));
865 /*if (!GPU_RUNNING && finished)
867 WriteLog("\nGPU: Finished collision detection code. Exiting!\n\n");
872 // (?) If we're set running by the M68K (or DSP?) then end its timeslice to
873 // allow the GPU a chance to run...
874 // Yes! This partially fixed Trevor McFur...
876 m68k_end_timeslice();
883 gpu_div_control = data;
885 // default: // unaligned long write
892 // JaguarWriteWord(offset, (data >> 16) & 0xFFFF, who);
893 // JaguarWriteWord(offset+2, data & 0xFFFF, who);
894 // We're a 32-bit processor, we can do a long write...!
895 JaguarWriteLong(offset, data, who);
899 // Change register banks if necessary
901 void GPUUpdateRegisterBanks(void)
903 int bank = (gpu_flags & REGPAGE); // REGPAGE bit
905 if (gpu_flags & IMASK) // IMASK bit
906 bank = 0; // IMASK forces main bank to be bank 0
909 gpu_reg = gpu_reg_bank_1, gpu_alternate_reg = gpu_reg_bank_0;
911 gpu_reg = gpu_reg_bank_0, gpu_alternate_reg = gpu_reg_bank_1;
914 void GPUHandleIRQs(void)
916 // Bail out if we're already in an interrupt!
917 if (gpu_flags & IMASK)
920 // Get the interrupt latch & enable bits
921 uint32 bits = (gpu_control >> 6) & 0x1F, mask = (gpu_flags >> 4) & 0x1F;
923 // Bail out if latched interrupts aren't enabled
928 // Determine which interrupt to service
929 uint32 which = 0; //Isn't there a #pragma to disable this warning???
942 WriteLog("GPU: Generating IRQ #%i\n", which);
944 // set the interrupt flag
946 GPUUpdateRegisterBanks();
948 // subqt #4,r31 ; pre-decrement stack pointer
949 // move pc,r30 ; address of interrupted code
950 // store r30,(r31) ; store return address
952 GPUWriteLong(gpu_reg[31], gpu_pc - 2, GPU);
954 // movei #service_address,r30 ; pointer to ISR entry
955 // jump (r30) ; jump to ISR
957 gpu_pc = gpu_reg[30] = GPU_WORK_RAM_BASE + (which * 0x10);
960 void GPUSetIRQLine(int irqline, int state)
963 WriteLog("GPU: Setting GPU IRQ line #%i\n", irqline);
965 uint32 mask = 0x0040 << irqline;
966 gpu_control &= ~mask; // Clear the interrupt latch
970 gpu_control |= mask; // Assert the interrupt latch
971 GPUHandleIRQs(); // And handle the interrupt...
975 //TEMPORARY: Testing only!
981 // memory_malloc_secure((void **)&gpu_ram_8, 0x1000, "GPU work RAM");
982 // memory_malloc_secure((void **)&gpu_reg_bank_0, 32 * sizeof(int32), "GPU bank 0 regs");
983 // memory_malloc_secure((void **)&gpu_reg_bank_1, 32 * sizeof(int32), "GPU bank 1 regs");
985 build_branch_condition_table();
989 //TEMPORARY: Testing only!
996 // GPU registers (directly visible)
997 gpu_flags = 0x00000000;
998 gpu_matrix_control = 0x00000000;
999 gpu_pointer_to_matrix = 0x00000000;
1000 gpu_data_organization = 0xFFFFFFFF;
1001 gpu_pc = 0x00F03000;
1002 gpu_control = 0x00002800; // Correctly sets this as TOM Rev. 2
1003 gpu_hidata = 0x00000000;
1004 gpu_remain = 0x00000000; // These two registers are RO/WO
1005 gpu_div_control = 0x00000000;
1007 // GPU internal register
1008 gpu_acc = 0x00000000;
1010 gpu_reg = gpu_reg_bank_0;
1011 gpu_alternate_reg = gpu_reg_bank_1;
1013 for(int i=0; i<32; i++)
1014 gpu_reg[i] = gpu_alternate_reg[i] = 0x00000000;
1017 memset(gpu_ram_8, 0xFF, 0x1000);
1019 //not needed GPUInterruptPending = false;
1023 uint32 GPUReadPC(void)
1028 void GPUResetStats(void)
1030 for(uint32 i=0; i<64; i++)
1031 gpu_opcode_use[i] = 0;
1032 WriteLog("--> GPU stats were reset!\n");
1035 void GPUDumpDisassembly(void)
1039 WriteLog("\n---[GPU code at 00F03000]---------------------------\n");
1040 uint32 j = 0xF03000;
1041 while (j <= 0xF03FFF)
1044 j += dasmjag(JAGUAR_GPU, buffer, j);
1045 WriteLog("\t%08X: %s\n", oldj, buffer);
1049 void GPUDumpRegisters(void)
1051 WriteLog("\n---[GPU flags: NCZ %d%d%d]-----------------------\n", gpu_flag_n, gpu_flag_c, gpu_flag_z);
1052 WriteLog("\nRegisters bank 0\n");
1053 for(int j=0; j<8; j++)
1055 WriteLog("\tR%02i = %08X R%02i = %08X R%02i = %08X R%02i = %08X\n",
1056 (j << 2) + 0, gpu_reg_bank_0[(j << 2) + 0],
1057 (j << 2) + 1, gpu_reg_bank_0[(j << 2) + 1],
1058 (j << 2) + 2, gpu_reg_bank_0[(j << 2) + 2],
1059 (j << 2) + 3, gpu_reg_bank_0[(j << 2) + 3]);
1061 WriteLog("Registers bank 1\n");
1062 for(int j=0; j<8; j++)
1064 WriteLog("\tR%02i = %08X R%02i = %08X R%02i = %08X R%02i = %08X\n",
1065 (j << 2) + 0, gpu_reg_bank_1[(j << 2) + 0],
1066 (j << 2) + 1, gpu_reg_bank_1[(j << 2) + 1],
1067 (j << 2) + 2, gpu_reg_bank_1[(j << 2) + 2],
1068 (j << 2) + 3, gpu_reg_bank_1[(j << 2) + 3]);
1072 void GPUDumpMemory(void)
1074 WriteLog("\n---[GPU data at 00F03000]---------------------------\n");
1075 for(int i=0; i<0xFFF; i+=4)
1076 WriteLog("\t%08X: %02X %02X %02X %02X\n", 0xF03000+i, gpu_ram_8[i],
1077 gpu_ram_8[i+1], gpu_ram_8[i+2], gpu_ram_8[i+3]);
1082 WriteLog("GPU: Stopped at PC=%08X (GPU %s running)\n", (unsigned int)gpu_pc, GPU_RUNNING ? "was" : "wasn't");
1084 // Get the interrupt latch & enable bits
1085 uint8 bits = (gpu_control >> 6) & 0x1F, mask = (gpu_flags >> 4) & 0x1F;
1086 WriteLog("GPU: Latch bits = %02X, enable bits = %02X\n", bits, mask);
1089 GPUDumpDisassembly();
1091 WriteLog("\nGPU opcodes use:\n");
1092 for(int i=0; i<64; i++)
1094 if (gpu_opcode_use[i])
1095 WriteLog("\t%17s %lu\n", gpu_opcode_str[i], gpu_opcode_use[i]);
1099 // memory_free(gpu_ram_8);
1100 // memory_free(gpu_reg_bank_0);
1101 // memory_free(gpu_reg_bank_1);
1105 // Main GPU execution core
1107 static int testCount = 1;
1109 static bool tripwire = false;
1110 void GPUExec(int32 cycles)
1115 #ifdef GPU_SINGLE_STEPPING
1116 if (gpu_control & 0x18)
1119 gpu_control &= ~0x10;
1123 gpu_releaseTimeSlice_flag = 0;
1126 while (cycles > 0 && GPU_RUNNING)
1128 if (gpu_ram_8[0x054] == 0x98 && gpu_ram_8[0x055] == 0x0A && gpu_ram_8[0x056] == 0x03
1129 && gpu_ram_8[0x057] == 0x00 && gpu_ram_8[0x058] == 0x00 && gpu_ram_8[0x059] == 0x00)
1131 if (gpu_pc == 0xF03000)
1133 extern uint32 starCount;
1135 /* WriteLog("GPU: Starting starfield generator... Dump of [R03=%08X]:\n", gpu_reg_bank_0[03]);
1136 uint32 base = gpu_reg_bank_0[3];
1137 for(uint32 i=0; i<0x100; i+=16)
1139 WriteLog("%02X: ", i);
1140 for(uint32 j=0; j<16; j++)
1142 WriteLog("%02X ", JaguarReadByte(base + i + j));
1147 // if (gpu_pc == 0xF03)
1151 /*if (gpu_pc == 0xF03B9E && gpu_reg_bank_0[01] == 0)
1154 WriteLog("GPU: Starting disassembly log...\n");
1157 /*if (gpu_pc == 0xF0359A)
1162 /* gpu_flag_c = (gpu_flag_c ? 1 : 0);
1163 gpu_flag_z = (gpu_flag_z ? 1 : 0);
1164 gpu_flag_n = (gpu_flag_n ? 1 : 0);*/
1166 uint16 opcode = GPUReadWord(gpu_pc, GPU);
1167 uint32 index = opcode >> 10;
1168 gpu_instruction = opcode; // Added for GPU #3...
1169 gpu_opcode_first_parameter = (opcode >> 5) & 0x1F;
1170 gpu_opcode_second_parameter = opcode & 0x1F;
1171 /*if (gpu_pc == 0xF03BE8)
1172 WriteLog("Start of OP frame write...\n");
1173 if (gpu_pc == 0xF03EEE)
1174 WriteLog("--> Writing BRANCH object ---\n");
1175 if (gpu_pc == 0xF03F62)
1176 WriteLog("--> Writing BITMAP object ***\n");//*/
1177 /*if (gpu_pc == 0xF03546)
1179 WriteLog("\n--> GPU PC: F03546\n");
1181 GPUDumpDisassembly();
1183 /*if (gpu_pc == 0xF033F6)
1185 WriteLog("\n--> GPU PC: F033F6\n");
1187 GPUDumpDisassembly();
1189 /*if (gpu_pc == 0xF033CC)
1191 WriteLog("\n--> GPU PC: F033CC\n");
1193 GPUDumpDisassembly();
1195 /*if (gpu_pc == 0xF033D6)
1197 WriteLog("\n--> GPU PC: F033D6 (#%d)\n", testCount++);
1201 /*if (gpu_pc == 0xF033D8)
1203 WriteLog("\n--> GPU PC: F033D8 (#%d)\n", testCount++);
1207 /*if (gpu_pc == 0xF0358E)
1209 WriteLog("\n--> GPU PC: F0358E (#%d)\n", testCount++);
1213 /*if (gpu_pc == 0xF034CA)
1215 WriteLog("\n--> GPU PC: F034CA (#%d)\n", testCount++);
1218 /*if (gpu_pc == 0xF034CA)
1220 len = gpu_reg[1] + 4;//, r9save = gpu_reg[9];
1221 WriteLog("\nAbout to subtract [#%d] (R14=%08X, R15=%08X, R9=%08X):\n ", testCount++, gpu_reg[14], gpu_reg[15], gpu_reg[9]);
1222 for(int i=0; i<len; i+=4)
1223 WriteLog(" %08X", GPUReadLong(gpu_reg[15]+i));
1225 for(int i=0; i<len; i+=4)
1226 WriteLog(" %08X", GPUReadLong(gpu_reg[14]+i));
1229 if (gpu_pc == 0xF034DE)
1231 WriteLog("\nSubtracted! (R14=%08X, R15=%08X):\n ", gpu_reg[14], gpu_reg[15]);
1232 for(int i=0; i<len; i+=4)
1233 WriteLog(" %08X", GPUReadLong(gpu_reg[15]+i));
1235 for(int i=0; i<len; i+=4)
1236 WriteLog(" %08X", GPUReadLong(gpu_reg[14]+i));
1238 for(int i=0; i<len; i+=4)
1239 WriteLog(" --------");
1241 for(int i=0; i<len; i+=4)
1242 WriteLog(" %08X", GPUReadLong(gpu_reg[9]+4+i));
1245 /*if (gpu_pc == 0xF035C8)
1247 WriteLog("\n--> GPU PC: F035C8 (#%d)\n", testCount++);
1249 GPUDumpDisassembly();
1254 // gpu_reset_stats();
1255 static char buffer[512];
1256 dasmjag(JAGUAR_GPU, buffer, gpu_pc);
1257 WriteLog("GPU: [%08X] %s (RM=%08X, RN=%08X) -> ", gpu_pc, buffer, RM, RN);
1259 //$E400 -> 1110 01 -> $39 -> 57
1262 gpu_opcode[index]();
1264 // gpu2_opcode[index]();
1266 //GPU #3 (Doesn't show ATARI logo! #1 & #2 do...)
1268 // gpu3_opcode[index]();
1271 //GPU: [00F03548] jr nz,00F03560 (0xd561) (RM=00F03114, RN=00000004) -> --> JR: Branch taken.
1272 /*static bool firstTime = true;
1273 if (gpu_pc == 0xF03548 && firstTime)
1276 // firstTime = false;
1278 //static char buffer[512];
1280 //while (k<0xF0356C)
1283 //k += dasmjag(JAGUAR_GPU, buffer, k);
1284 //WriteLog("GPU: [%08X] %s\n", oldk, buffer);
1286 // gpu_start_log = 1;
1288 //GPU: [00F0354C] jump nz,(r29) (0xd3a1) (RM=00F03314, RN=00000004) -> (RM=00F03314, RN=00000004)
1289 /*if (gpu_pc == 0xF0354C)
1290 gpu_flag_z = 0;//, gpu_start_log = 1;//*/
1292 cycles -= gpu_opcode_cycles[index];
1293 gpu_opcode_use[index]++;
1295 WriteLog("(RM=%08X, RN=%08X)\n", RM, RN);//*/
1296 if ((gpu_pc < 0xF03000 || gpu_pc > 0xF03FFF) && !tripwire)
1298 WriteLog("GPU: Executing outside local RAM! GPU_PC: %08X\n", gpu_pc);
1311 GPU opcodes use (offset punch--vertically below bad guy):
1333 load_r14_indexed 1183
1334 load_r15_indexed 1125
1337 store_r14_indexed 320
1345 static void gpu_opcode_jump(void)
1348 const char * condition[32] =
1349 { "T", "nz", "z", "???", "nc", "nc nz", "nc z", "???", "c", "c nz",
1350 "c z", "???", "???", "???", "???", "???", "???", "???", "???",
1351 "???", "nn", "nn nz", "nn z", "???", "n", "n nz", "n z", "???",
1352 "???", "???", "???", "F" };
1354 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);
1357 /* gpu_flag_c = (gpu_flag_c ? 1 : 0);
1358 gpu_flag_z = (gpu_flag_z ? 1 : 0);
1359 gpu_flag_n = (gpu_flag_n ? 1 : 0);*/
1360 // KLUDGE: Used by BRANCH_CONDITION
1361 uint32 jaguar_flags = (gpu_flag_n << 2) | (gpu_flag_c << 1) | gpu_flag_z;
1363 if (BRANCH_CONDITION(IMM_2))
1367 WriteLog("Branched!\n");
1370 WriteLog(" --> JUMP: Branch taken.\n");
1371 uint32 delayed_pc = RM;
1373 gpu_pc = delayed_pc;
1374 /* uint16 opcode = GPUReadWord(gpu_pc, GPU);
1375 gpu_opcode_first_parameter = (opcode >> 5) & 0x1F;
1376 gpu_opcode_second_parameter = opcode & 0x1F;
1378 gpu_pc = delayed_pc;
1379 gpu_opcode[opcode>>10]();//*/
1384 WriteLog("Branch NOT taken.\n");
1388 static void gpu_opcode_jr(void)
1391 const char * condition[32] =
1392 { "T", "nz", "z", "???", "nc", "nc nz", "nc z", "???", "c", "c nz",
1393 "c z", "???", "???", "???", "???", "???", "???", "???", "???",
1394 "???", "nn", "nn nz", "nn z", "???", "n", "n nz", "n z", "???",
1395 "???", "???", "???", "F" };
1397 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);
1399 /* if (CONDITION(jaguar.op & 31))
1401 int32 r1 = (INT8)((jaguar.op >> 2) & 0xF8) >> 2;
1402 uint32 newpc = jaguar.PC + r1;
1404 jaguar.op = ROPCODE(jaguar.PC);
1406 (*jaguar.table[jaguar.op >> 10])();
1408 jaguar_icount -= 3; // 3 wait states guaranteed
1411 /* gpu_flag_n = (gpu_flag_n ? 1 : 0);
1412 gpu_flag_c = (gpu_flag_c ? 1 : 0);
1413 gpu_flag_z = (gpu_flag_z ? 1 : 0);*/
1414 // KLUDGE: Used by BRANCH_CONDITION
1415 uint32 jaguar_flags = (gpu_flag_n << 2) | (gpu_flag_c << 1) | gpu_flag_z;
1417 if (BRANCH_CONDITION(IMM_2))
1421 WriteLog("Branched!\n");
1424 WriteLog(" --> JR: Branch taken.\n");
1425 int32 offset = (IMM_1 & 0x10 ? 0xFFFFFFF0 | IMM_1 : IMM_1); // Sign extend IMM_1
1426 int32 delayed_pc = gpu_pc + (offset * 2);
1428 gpu_pc = delayed_pc;
1429 /* uint16 opcode = GPUReadWord(gpu_pc, GPU);
1430 gpu_opcode_first_parameter = (opcode >> 5) & 0x1F;
1431 gpu_opcode_second_parameter = opcode & 0x1F;
1433 gpu_pc = delayed_pc;
1434 gpu_opcode[opcode>>10]();//*/
1439 WriteLog("Branch NOT taken.\n");
1443 static void gpu_opcode_add(void)
1447 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);
1449 uint32 res = RN + RM;
1450 CLR_ZNC; SET_ZNC_ADD(RN, RM, res);
1454 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);
1458 static void gpu_opcode_addc(void)
1462 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);
1464 /* int dreg = jaguar.op & 31;
1465 uint32 r1 = jaguar.r[(jaguar.op >> 5) & 31];
1466 uint32 r2 = jaguar.r[dreg];
1467 uint32 res = r2 + r1 + ((jaguar.FLAGS >> 1) & 1);
1468 jaguar.r[dreg] = res;
1469 CLR_ZNC; SET_ZNC_ADD(r2,r1,res);*/
1471 uint32 res = RN + RM + gpu_flag_c;
1472 uint32 carry = gpu_flag_c;
1473 // SET_ZNC_ADD(RN, RM, res); //???BUG??? Yes!
1474 SET_ZNC_ADD(RN + carry, RM, res);
1475 // SET_ZNC_ADD(RN, RM + carry, res);
1479 WriteLog("[NCZ:%u%u%u, R%02u=%08X, R%02u=%08X]\n", gpu_flag_n, gpu_flag_c, gpu_flag_z, IMM_1, RM, IMM_2, RN);
1483 static void gpu_opcode_addq(void)
1487 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);
1489 uint32 r1 = gpu_convert_zero[IMM_1];
1490 uint32 res = RN + r1;
1491 CLR_ZNC; SET_ZNC_ADD(RN, r1, res);
1495 WriteLog("[NCZ:%u%u%u, R%02u=%08X]\n", gpu_flag_n, gpu_flag_c, gpu_flag_z, IMM_2, RN);
1499 static void gpu_opcode_addqt(void)
1501 #ifdef GPU_DIS_ADDQT
1503 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);
1505 RN += gpu_convert_zero[IMM_1];
1506 #ifdef GPU_DIS_ADDQT
1508 WriteLog("[NCZ:%u%u%u, R%02u=%08X]\n", gpu_flag_n, gpu_flag_c, gpu_flag_z, IMM_2, RN);
1512 static void gpu_opcode_sub(void)
1516 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);
1518 uint32 res = RN - RM;
1519 SET_ZNC_SUB(RN, RM, res);
1523 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);
1527 static void gpu_opcode_subc(void)
1531 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);
1533 uint32 res = RN - RM - gpu_flag_c;
1534 uint32 borrow = gpu_flag_c;
1535 // SET_ZNC_SUB(RN, RM, res); //???BUG??? YES!!!
1536 //No matter how you do it, there is a problem. With below, it's 0-0 with carry,
1537 //and the one below it it's FFFFFFFF - FFFFFFFF with carry... !!! FIX !!!
1538 // SET_ZNC_SUB(RN - borrow, RM, res);
1539 SET_ZNC_SUB(RN, RM + borrow, res);
1543 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);
1547 N = 5, M = 3, 3 - 5 = -2, C = 1... Or, in our case:
1548 N = 0, M = 1, 0 - 1 = -1, C = 0!
1550 #define SET_C_SUB(a,b) (gpu_flag_c = ((uint32)(b) > (uint32)(a)))
1551 #define SET_ZN(r) SET_N(r); SET_Z(r)
1552 #define SET_ZNC_ADD(a,b,r) SET_N(r); SET_Z(r); SET_C_ADD(a,b)
1553 #define SET_ZNC_SUB(a,b,r) SET_N(r); SET_Z(r); SET_C_SUB(a,b)
1555 static void gpu_opcode_subq(void)
1559 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);
1561 uint32 r1 = gpu_convert_zero[IMM_1];
1562 uint32 res = RN - r1;
1563 SET_ZNC_SUB(RN, r1, res);
1567 WriteLog("[NCZ:%u%u%u, R%02u=%08X]\n", gpu_flag_n, gpu_flag_c, gpu_flag_z, IMM_2, RN);
1571 static void gpu_opcode_subqt(void)
1573 #ifdef GPU_DIS_SUBQT
1575 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);
1577 RN -= gpu_convert_zero[IMM_1];
1578 #ifdef GPU_DIS_SUBQT
1580 WriteLog("[NCZ:%u%u%u, R%02u=%08X]\n", gpu_flag_n, gpu_flag_c, gpu_flag_z, IMM_2, RN);
1584 static void gpu_opcode_cmp(void)
1588 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);
1590 uint32 res = RN - RM;
1591 SET_ZNC_SUB(RN, RM, res);
1594 WriteLog("[NCZ:%u%u%u]\n", gpu_flag_n, gpu_flag_c, gpu_flag_z);
1598 static void gpu_opcode_cmpq(void)
1600 static int32 sqtable[32] =
1601 { 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 };
1604 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);
1606 uint32 r1 = sqtable[IMM_1 & 0x1F]; // I like this better -> (INT8)(jaguar.op >> 2) >> 3;
1607 uint32 res = RN - r1;
1608 SET_ZNC_SUB(RN, r1, res);
1611 WriteLog("[NCZ:%u%u%u]\n", gpu_flag_n, gpu_flag_c, gpu_flag_z);
1615 static void gpu_opcode_and(void)
1619 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);
1625 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);
1629 static void gpu_opcode_or(void)
1633 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);
1639 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);
1643 static void gpu_opcode_xor(void)
1647 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);
1653 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);
1657 static void gpu_opcode_not(void)
1661 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);
1667 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);
1671 static void gpu_opcode_move_pc(void)
1673 #ifdef GPU_DIS_MOVEPC
1675 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);
1677 // Should be previous PC--this might not always be previous instruction!
1678 // Then again, this will point right at the *current* instruction, i.e., MOVE PC,R!
1680 #ifdef GPU_DIS_MOVEPC
1682 WriteLog("[NCZ:%u%u%u, R%02u=%08X]\n", gpu_flag_n, gpu_flag_c, gpu_flag_z, IMM_2, RN);
1686 static void gpu_opcode_sat8(void)
1690 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);
1692 RN = ((int32)RN < 0 ? 0 : (RN > 0xFF ? 0xFF : RN));
1696 WriteLog("[NCZ:%u%u%u, R%02u=%08X]\n", gpu_flag_n, gpu_flag_c, gpu_flag_z, IMM_2, RN);
1700 static void gpu_opcode_sat16(void)
1702 RN = ((int32)RN < 0 ? 0 : (RN > 0xFFFF ? 0xFFFF : RN));
1706 static void gpu_opcode_sat24(void)
1708 RN = ((int32)RN < 0 ? 0 : (RN > 0xFFFFFF ? 0xFFFFFF : RN));
1712 static void gpu_opcode_store_r14_indexed(void)
1714 #ifdef GPU_DIS_STORE14I
1716 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));
1718 GPUWriteLong(gpu_reg[14] + (gpu_convert_zero[IMM_1] << 2), RN, GPU);
1721 static void gpu_opcode_store_r15_indexed(void)
1723 #ifdef GPU_DIS_STORE15I
1725 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));
1727 GPUWriteLong(gpu_reg[15] + (gpu_convert_zero[IMM_1] << 2), RN, GPU);
1730 static void gpu_opcode_load_r14_ri(void)
1732 #ifdef GPU_DIS_LOAD14R
1734 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);
1736 RN = GPUReadLong(gpu_reg[14] + RM, GPU);
1737 #ifdef GPU_DIS_LOAD14R
1739 WriteLog("[NCZ:%u%u%u, R%02u=%08X]\n", gpu_flag_n, gpu_flag_c, gpu_flag_z, IMM_2, RN);
1743 static void gpu_opcode_load_r15_ri(void)
1745 #ifdef GPU_DIS_LOAD15R
1747 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);
1749 RN = GPUReadLong(gpu_reg[15] + RM, GPU);
1750 #ifdef GPU_DIS_LOAD15R
1752 WriteLog("[NCZ:%u%u%u, R%02u=%08X]\n", gpu_flag_n, gpu_flag_c, gpu_flag_z, IMM_2, RN);
1756 static void gpu_opcode_store_r14_ri(void)
1758 #ifdef GPU_DIS_STORE14R
1760 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]);
1762 GPUWriteLong(gpu_reg[14] + RM, RN, GPU);
1765 static void gpu_opcode_store_r15_ri(void)
1767 #ifdef GPU_DIS_STORE15R
1769 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]);
1771 GPUWriteLong(gpu_reg[15] + RM, RN, GPU);
1774 static void gpu_opcode_nop(void)
1778 WriteLog("%06X: NOP [NCZ:%u%u%u]\n", gpu_pc-2, gpu_flag_n, gpu_flag_c, gpu_flag_z);
1782 static void gpu_opcode_pack(void)
1786 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);
1790 //BUG! if (RM == 0) // Pack
1791 if (IMM_1 == 0) // Pack
1792 RN = ((val >> 10) & 0x0000F000) | ((val >> 5) & 0x00000F00) | (val & 0x000000FF);
1794 RN = ((val & 0x0000F000) << 10) | ((val & 0x00000F00) << 5) | (val & 0x000000FF);
1797 WriteLog("[NCZ:%u%u%u, R%02u=%08X]\n", gpu_flag_n, gpu_flag_c, gpu_flag_z, IMM_2, RN);
1801 static void gpu_opcode_storeb(void)
1803 #ifdef GPU_DIS_STOREB
1805 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);
1808 // Would appear to be so...!
1809 if ((RM >= 0xF03000) && (RM <= 0xF03FFF))
1810 GPUWriteLong(RM, RN & 0xFF, GPU);
1812 JaguarWriteByte(RM, RN, GPU);
1815 static void gpu_opcode_storew(void)
1817 #ifdef GPU_DIS_STOREW
1819 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);
1821 if ((RM >= 0xF03000) && (RM <= 0xF03FFF))
1822 GPUWriteLong(RM, RN & 0xFFFF, GPU);
1824 JaguarWriteWord(RM, RN, GPU);
1827 static void gpu_opcode_store(void)
1829 #ifdef GPU_DIS_STORE
1831 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);
1833 GPUWriteLong(RM, RN, GPU);
1836 static void gpu_opcode_storep(void)
1838 GPUWriteLong(RM + 0, gpu_hidata, GPU);
1839 GPUWriteLong(RM + 4, RN, GPU);
1842 static void gpu_opcode_loadb(void)
1844 #ifdef GPU_DIS_LOADB
1846 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);
1848 if ((RM >= 0xF03000) && (RM <= 0xF03FFF))
1849 RN = GPUReadLong(RM, GPU) & 0xFF;
1851 RN = JaguarReadByte(RM, GPU);
1852 #ifdef GPU_DIS_LOADB
1854 WriteLog("[NCZ:%u%u%u, R%02u=%08X]\n", gpu_flag_n, gpu_flag_c, gpu_flag_z, IMM_2, RN);
1858 static void gpu_opcode_loadw(void)
1860 #ifdef GPU_DIS_LOADW
1862 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);
1864 if ((RM >= 0xF03000) && (RM <= 0xF03FFF))
1865 RN = GPUReadLong(RM, GPU) & 0xFFFF;
1867 RN = JaguarReadWord(RM, GPU);
1868 #ifdef GPU_DIS_LOADW
1870 WriteLog("[NCZ:%u%u%u, R%02u=%08X]\n", gpu_flag_n, gpu_flag_c, gpu_flag_z, IMM_2, RN);
1874 static void gpu_opcode_load(void)
1878 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);
1880 RN = GPUReadLong(RM, GPU);
1883 WriteLog("[NCZ:%u%u%u, R%02u=%08X]\n", gpu_flag_n, gpu_flag_c, gpu_flag_z, IMM_2, RN);
1887 static void gpu_opcode_loadp(void)
1889 gpu_hidata = GPUReadLong(RM + 0, GPU);
1890 RN = GPUReadLong(RM + 4, GPU);
1893 static void gpu_opcode_load_r14_indexed(void)
1895 #ifdef GPU_DIS_LOAD14I
1897 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);
1899 RN = GPUReadLong(gpu_reg[14] + (gpu_convert_zero[IMM_1] << 2), GPU);
1900 #ifdef GPU_DIS_LOAD14I
1902 WriteLog("[NCZ:%u%u%u, R%02u=%08X]\n", gpu_flag_n, gpu_flag_c, gpu_flag_z, IMM_2, RN);
1906 static void gpu_opcode_load_r15_indexed(void)
1908 #ifdef GPU_DIS_LOAD15I
1910 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);
1912 RN = GPUReadLong(gpu_reg[15] + (gpu_convert_zero[IMM_1] << 2), GPU);
1913 #ifdef GPU_DIS_LOAD15I
1915 WriteLog("[NCZ:%u%u%u, R%02u=%08X]\n", gpu_flag_n, gpu_flag_c, gpu_flag_z, IMM_2, RN);
1919 static void gpu_opcode_movei(void)
1921 #ifdef GPU_DIS_MOVEI
1923 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);
1925 // This instruction is followed by 32-bit value in LSW / MSW format...
1926 RN = (uint32)GPUReadWord(gpu_pc, GPU) | ((uint32)GPUReadWord(gpu_pc + 2, GPU) << 16);
1928 #ifdef GPU_DIS_MOVEI
1930 WriteLog("[NCZ:%u%u%u, R%02u=%08X]\n", gpu_flag_n, gpu_flag_c, gpu_flag_z, IMM_2, RN);
1934 static void gpu_opcode_moveta(void)
1936 #ifdef GPU_DIS_MOVETA
1938 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);
1941 #ifdef GPU_DIS_MOVETA
1943 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);
1947 static void gpu_opcode_movefa(void)
1949 #ifdef GPU_DIS_MOVEFA
1951 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);
1954 #ifdef GPU_DIS_MOVEFA
1956 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);
1960 static void gpu_opcode_move(void)
1964 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);
1969 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);
1973 static void gpu_opcode_moveq(void)
1975 #ifdef GPU_DIS_MOVEQ
1977 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);
1980 #ifdef GPU_DIS_MOVEQ
1982 WriteLog("[NCZ:%u%u%u, R%02u=%08X]\n", gpu_flag_n, gpu_flag_c, gpu_flag_z, IMM_2, RN);
1986 static void gpu_opcode_resmac(void)
1991 static void gpu_opcode_imult(void)
1993 #ifdef GPU_DIS_IMULT
1995 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);
1997 RN = (int16)RN * (int16)RM;
1999 #ifdef GPU_DIS_IMULT
2001 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);
2005 static void gpu_opcode_mult(void)
2009 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);
2011 RN = (uint16)RM * (uint16)RN;
2015 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);
2019 static void gpu_opcode_bclr(void)
2023 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);
2025 uint32 res = RN & ~(1 << IMM_1);
2030 WriteLog("[NCZ:%u%u%u, R%02u=%08X]\n", gpu_flag_n, gpu_flag_c, gpu_flag_z, IMM_2, RN);
2034 static void gpu_opcode_btst(void)
2038 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);
2040 gpu_flag_z = (~RN >> IMM_1) & 1;
2043 WriteLog("[NCZ:%u%u%u, R%02u=%08X]\n", gpu_flag_n, gpu_flag_c, gpu_flag_z, IMM_2, RN);
2047 static void gpu_opcode_bset(void)
2051 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);
2053 uint32 res = RN | (1 << IMM_1);
2058 WriteLog("[NCZ:%u%u%u, R%02u=%08X]\n", gpu_flag_n, gpu_flag_c, gpu_flag_z, IMM_2, RN);
2062 static void gpu_opcode_imacn(void)
2064 uint32 res = (int16)RM * (int16)(RN);
2068 static void gpu_opcode_mtoi(void)
2071 uint32 res = RN = (((int32)_RM >> 8) & 0xFF800000) | (_RM & 0x007FFFFF);
2075 static void gpu_opcode_normi(void)
2082 while ((_RM & 0xFFC00000) == 0)
2087 while ((_RM & 0xFF800000) != 0)
2097 static void gpu_opcode_mmult(void)
2099 int count = gpu_matrix_control & 0x0F; // Matrix width
2100 uint32 addr = gpu_pointer_to_matrix; // In the GPU's RAM
2104 if (gpu_matrix_control & 0x10) // Column stepping
2106 for(int i=0; i<count; i++)
2110 a = (int16)((gpu_alternate_reg[IMM_1 + (i >> 1)] >> 16) & 0xFFFF);
2112 a = (int16)(gpu_alternate_reg[IMM_1 + (i >> 1)] & 0xFFFF);
2114 int16 b = ((int16)GPUReadWord(addr + 2, GPU));
2119 else // Row stepping
2121 for(int i=0; i<count; i++)
2125 a = (int16)((gpu_alternate_reg[IMM_1 + (i >> 1)] >> 16) & 0xFFFF);
2127 a = (int16)(gpu_alternate_reg[IMM_1 + (i >> 1)] & 0xFFFF);
2129 int16 b = ((int16)GPUReadWord(addr + 2, GPU));
2134 RN = res = (int32)accum;
2135 // carry flag to do (out of the last add)
2139 static void gpu_opcode_abs(void)
2143 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);
2145 gpu_flag_c = RN >> 31;
2146 if (RN == 0x80000000)
2147 //Is 0x80000000 a positive number? If so, then we need to set C to 0 as well!
2148 gpu_flag_n = 1, gpu_flag_z = 0;
2153 gpu_flag_n = 0; SET_FLAG_Z(RN);
2157 WriteLog("[NCZ:%u%u%u, R%02u=%08X]\n", gpu_flag_n, gpu_flag_c, gpu_flag_z, IMM_2, RN);
2161 static void gpu_opcode_div(void) // RN / RM
2165 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);
2167 // NOTE: remainder is NOT calculated correctly here!
2168 // The original tried to get it right by checking to see if the
2169 // remainder was negative, but that's too late...
2170 // The code there should do it now, but I'm not 100% sure...
2174 if (gpu_div_control & 0x01) // 16.16 division
2176 RN = ((uint64)RN << 16) / RM;
2177 gpu_remain = ((uint64)RN << 16) % RM;
2182 gpu_remain = RN % RM;
2185 if ((gpu_remain - RM) & 0x80000000) // If the result would have been negative...
2186 gpu_remain -= RM; // Then make it negative!
2196 if (gpu_div_control & 1)
2198 gpu_remain = (((uint64)_RN) << 16) % _RM;
2199 if (gpu_remain&0x80000000)
2201 RN = (((uint64)_RN) << 16) / _RM;
2205 gpu_remain = _RN % _RM;
2206 if (gpu_remain&0x80000000)
2215 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);
2219 static void gpu_opcode_imultn(void)
2221 uint32 res = (int32)((int16)RN * (int16)RM);
2222 gpu_acc = (int32)res;
2227 static void gpu_opcode_neg(void)
2231 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);
2234 SET_ZNC_SUB(0, RN, res);
2238 WriteLog("[NCZ:%u%u%u, R%02u=%08X]\n", gpu_flag_n, gpu_flag_c, gpu_flag_z, IMM_2, RN);
2242 static void gpu_opcode_shlq(void)
2246 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);
2248 // Was a bug here...
2249 // (Look at Aaron's code: If r1 = 32, then 32 - 32 = 0 which is wrong!)
2250 int32 r1 = 32 - IMM_1;
2251 uint32 res = RN << r1;
2252 SET_ZN(res); gpu_flag_c = (RN >> 31) & 1;
2256 WriteLog("[NCZ:%u%u%u, R%02u=%08X]\n", gpu_flag_n, gpu_flag_c, gpu_flag_z, IMM_2, RN);
2260 static void gpu_opcode_shrq(void)
2264 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);
2266 int32 r1 = gpu_convert_zero[IMM_1];
2267 uint32 res = RN >> r1;
2268 SET_ZN(res); gpu_flag_c = RN & 1;
2272 WriteLog("[NCZ:%u%u%u, R%02u=%08X]\n", gpu_flag_n, gpu_flag_c, gpu_flag_z, IMM_2, RN);
2276 static void gpu_opcode_ror(void)
2280 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);
2282 uint32 r1 = RM & 0x1F;
2283 uint32 res = (RN >> r1) | (RN << (32 - r1));
2284 SET_ZN(res); gpu_flag_c = (RN >> 31) & 1;
2288 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);
2292 static void gpu_opcode_rorq(void)
2296 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);
2298 uint32 r1 = gpu_convert_zero[IMM_1 & 0x1F];
2300 uint32 res = (r2 >> r1) | (r2 << (32 - r1));
2302 SET_ZN(res); gpu_flag_c = (r2 >> 31) & 0x01;
2305 WriteLog("[NCZ:%u%u%u, R%02u=%08X]\n", gpu_flag_n, gpu_flag_c, gpu_flag_z, IMM_2, RN);
2309 static void gpu_opcode_sha(void)
2311 /* int dreg = jaguar.op & 31;
2312 int32 r1 = (int32)jaguar.r[(jaguar.op >> 5) & 31];
2313 uint32 r2 = jaguar.r[dreg];
2319 res = (r1 <= -32) ? 0 : (r2 << -r1);
2320 jaguar.FLAGS |= (r2 >> 30) & 2;
2324 res = (r1 >= 32) ? ((int32)r2 >> 31) : ((int32)r2 >> r1);
2325 jaguar.FLAGS |= (r2 << 1) & 2;
2327 jaguar.r[dreg] = res;
2332 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);
2338 res = ((int32)RM <= -32) ? 0 : (RN << -(int32)RM);
2339 gpu_flag_c = RN >> 31;
2343 res = ((int32)RM >= 32) ? ((int32)RN >> 31) : ((int32)RN >> (int32)RM);
2344 gpu_flag_c = RN & 0x01;
2350 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);
2353 /* int32 sRM=(int32)RM;
2359 if (shift>=32) shift=32;
2360 gpu_flag_c=(_RN&0x80000000)>>31;
2370 if (shift>=32) shift=32;
2374 _RN=((int32)_RN)>>1;
2383 static void gpu_opcode_sharq(void)
2385 #ifdef GPU_DIS_SHARQ
2387 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);
2389 uint32 res = (int32)RN >> gpu_convert_zero[IMM_1];
2390 SET_ZN(res); gpu_flag_c = RN & 0x01;
2392 #ifdef GPU_DIS_SHARQ
2394 WriteLog("[NCZ:%u%u%u, R%02u=%08X]\n", gpu_flag_n, gpu_flag_c, gpu_flag_z, IMM_2, RN);
2398 static void gpu_opcode_sh(void)
2402 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);
2404 if (RM & 0x80000000) // Shift left
2406 gpu_flag_c = RN >> 31;
2407 RN = ((int32)RM <= -32 ? 0 : RN << -(int32)RM);
2411 gpu_flag_c = RN & 0x01;
2412 RN = (RM >= 32 ? 0 : RN >> RM);
2417 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);
2421 //Temporary: Testing only!
2422 //#include "gpu2.cpp"
2423 //#include "gpu3.cpp"
2427 // New thread-safe GPU core
2429 int GPUCore(void * data)