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...
17 #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);
167 void GPUDumpDisassembly(void);
168 void GPUDumpRegisters(void);
169 void GPUDumpMemory(void);
171 static void gpu_opcode_add(void);
172 static void gpu_opcode_addc(void);
173 static void gpu_opcode_addq(void);
174 static void gpu_opcode_addqt(void);
175 static void gpu_opcode_sub(void);
176 static void gpu_opcode_subc(void);
177 static void gpu_opcode_subq(void);
178 static void gpu_opcode_subqt(void);
179 static void gpu_opcode_neg(void);
180 static void gpu_opcode_and(void);
181 static void gpu_opcode_or(void);
182 static void gpu_opcode_xor(void);
183 static void gpu_opcode_not(void);
184 static void gpu_opcode_btst(void);
185 static void gpu_opcode_bset(void);
186 static void gpu_opcode_bclr(void);
187 static void gpu_opcode_mult(void);
188 static void gpu_opcode_imult(void);
189 static void gpu_opcode_imultn(void);
190 static void gpu_opcode_resmac(void);
191 static void gpu_opcode_imacn(void);
192 static void gpu_opcode_div(void);
193 static void gpu_opcode_abs(void);
194 static void gpu_opcode_sh(void);
195 static void gpu_opcode_shlq(void);
196 static void gpu_opcode_shrq(void);
197 static void gpu_opcode_sha(void);
198 static void gpu_opcode_sharq(void);
199 static void gpu_opcode_ror(void);
200 static void gpu_opcode_rorq(void);
201 static void gpu_opcode_cmp(void);
202 static void gpu_opcode_cmpq(void);
203 static void gpu_opcode_sat8(void);
204 static void gpu_opcode_sat16(void);
205 static void gpu_opcode_move(void);
206 static void gpu_opcode_moveq(void);
207 static void gpu_opcode_moveta(void);
208 static void gpu_opcode_movefa(void);
209 static void gpu_opcode_movei(void);
210 static void gpu_opcode_loadb(void);
211 static void gpu_opcode_loadw(void);
212 static void gpu_opcode_load(void);
213 static void gpu_opcode_loadp(void);
214 static void gpu_opcode_load_r14_indexed(void);
215 static void gpu_opcode_load_r15_indexed(void);
216 static void gpu_opcode_storeb(void);
217 static void gpu_opcode_storew(void);
218 static void gpu_opcode_store(void);
219 static void gpu_opcode_storep(void);
220 static void gpu_opcode_store_r14_indexed(void);
221 static void gpu_opcode_store_r15_indexed(void);
222 static void gpu_opcode_move_pc(void);
223 static void gpu_opcode_jump(void);
224 static void gpu_opcode_jr(void);
225 static void gpu_opcode_mmult(void);
226 static void gpu_opcode_mtoi(void);
227 static void gpu_opcode_normi(void);
228 static void gpu_opcode_nop(void);
229 static void gpu_opcode_load_r14_ri(void);
230 static void gpu_opcode_load_r15_ri(void);
231 static void gpu_opcode_store_r14_ri(void);
232 static void gpu_opcode_store_r15_ri(void);
233 static void gpu_opcode_sat24(void);
234 static void gpu_opcode_pack(void);
236 // This is wrong, since it doesn't take pipeline effects into account. !!! FIX !!!
237 /*uint8 gpu_opcode_cycles[64] =
239 3, 3, 3, 3, 3, 3, 3, 3,
240 3, 3, 3, 3, 3, 3, 3, 3,
241 3, 3, 1, 3, 1, 18, 3, 3,
242 3, 3, 3, 3, 3, 3, 3, 3,
243 3, 3, 2, 2, 2, 2, 3, 4,
244 5, 4, 5, 6, 6, 1, 1, 1,
245 1, 2, 2, 2, 1, 1, 9, 3,
246 3, 1, 6, 6, 2, 2, 3, 3
248 //Here's a QnD kludge...
249 //This is wrong, wrong, WRONG, but it seems to work for the time being...
250 //(That is, it fixes Flip Out which relies on GPU timing rather than semaphores. Bad developers! Bad!)
251 //What's needed here is a way to take pipeline effects into account (including pipeline stalls!)...
252 /*uint8 gpu_opcode_cycles[64] =
254 1, 1, 1, 1, 1, 1, 1, 1,
255 1, 1, 1, 1, 1, 1, 1, 1,
256 1, 1, 1, 1, 1, 9, 1, 1,
257 1, 1, 1, 1, 1, 1, 1, 1,
258 1, 1, 1, 1, 1, 1, 1, 2,
259 2, 2, 2, 3, 3, 1, 1, 1,
260 1, 1, 1, 1, 1, 1, 4, 1,
261 1, 1, 3, 3, 1, 1, 1, 1
263 uint8 gpu_opcode_cycles[64] =
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,
272 1, 1, 1, 1, 1, 1, 1, 1
275 void (*gpu_opcode[64])()=
277 gpu_opcode_add, gpu_opcode_addc, gpu_opcode_addq, gpu_opcode_addqt,
278 gpu_opcode_sub, gpu_opcode_subc, gpu_opcode_subq, gpu_opcode_subqt,
279 gpu_opcode_neg, gpu_opcode_and, gpu_opcode_or, gpu_opcode_xor,
280 gpu_opcode_not, gpu_opcode_btst, gpu_opcode_bset, gpu_opcode_bclr,
281 gpu_opcode_mult, gpu_opcode_imult, gpu_opcode_imultn, gpu_opcode_resmac,
282 gpu_opcode_imacn, gpu_opcode_div, gpu_opcode_abs, gpu_opcode_sh,
283 gpu_opcode_shlq, gpu_opcode_shrq, gpu_opcode_sha, gpu_opcode_sharq,
284 gpu_opcode_ror, gpu_opcode_rorq, gpu_opcode_cmp, gpu_opcode_cmpq,
285 gpu_opcode_sat8, gpu_opcode_sat16, gpu_opcode_move, gpu_opcode_moveq,
286 gpu_opcode_moveta, gpu_opcode_movefa, gpu_opcode_movei, gpu_opcode_loadb,
287 gpu_opcode_loadw, gpu_opcode_load, gpu_opcode_loadp, gpu_opcode_load_r14_indexed,
288 gpu_opcode_load_r15_indexed, gpu_opcode_storeb, gpu_opcode_storew, gpu_opcode_store,
289 gpu_opcode_storep, gpu_opcode_store_r14_indexed, gpu_opcode_store_r15_indexed, gpu_opcode_move_pc,
290 gpu_opcode_jump, gpu_opcode_jr, gpu_opcode_mmult, gpu_opcode_mtoi,
291 gpu_opcode_normi, gpu_opcode_nop, gpu_opcode_load_r14_ri, gpu_opcode_load_r15_ri,
292 gpu_opcode_store_r14_ri, gpu_opcode_store_r15_ri, gpu_opcode_sat24, gpu_opcode_pack,
295 static uint8 gpu_ram_8[0x1000];
297 static uint32 gpu_acc;
298 static uint32 gpu_remain;
299 static uint32 gpu_hidata;
300 static uint32 gpu_flags;
301 static uint32 gpu_matrix_control;
302 static uint32 gpu_pointer_to_matrix;
303 static uint32 gpu_data_organization;
304 static uint32 gpu_control;
305 static uint32 gpu_div_control;
306 // There is a distinct advantage to having these separated out--there's no need to clear
307 // a bit before writing a result. I.e., if the result of an operation leaves a zero in
308 // the carry flag, you don't have to zero gpu_flag_c before you can write that zero!
309 static uint8 gpu_flag_z, gpu_flag_n, gpu_flag_c;
310 static uint32 gpu_reg_bank_0[32];
311 static uint32 gpu_reg_bank_1[32];
312 static uint32 * gpu_reg;
313 static uint32 * gpu_alternate_reg;
315 static uint32 gpu_instruction;
316 static uint32 gpu_opcode_first_parameter;
317 static uint32 gpu_opcode_second_parameter;
319 #define GPU_RUNNING (gpu_control & 0x01)
321 #define RM gpu_reg[gpu_opcode_first_parameter]
322 #define RN gpu_reg[gpu_opcode_second_parameter]
323 #define ALTERNATE_RM gpu_alternate_reg[gpu_opcode_first_parameter]
324 #define ALTERNATE_RN gpu_alternate_reg[gpu_opcode_second_parameter]
325 #define IMM_1 gpu_opcode_first_parameter
326 #define IMM_2 gpu_opcode_second_parameter
328 #define SET_FLAG_Z(r) (gpu_flag_z = ((r) == 0));
329 #define SET_FLAG_N(r) (gpu_flag_n = (((uint32)(r) >> 31) & 0x01));
331 #define RESET_FLAG_Z() gpu_flag_z = 0;
332 #define RESET_FLAG_N() gpu_flag_n = 0;
333 #define RESET_FLAG_C() gpu_flag_c = 0;
335 #define CLR_Z (gpu_flag_z = 0)
336 #define CLR_ZN (gpu_flag_z = gpu_flag_n = 0)
337 #define CLR_ZNC (gpu_flag_z = gpu_flag_n = gpu_flag_c = 0)
338 #define SET_Z(r) (gpu_flag_z = ((r) == 0))
339 #define SET_N(r) (gpu_flag_n = (((uint32)(r) >> 31) & 0x01))
340 #define SET_C_ADD(a,b) (gpu_flag_c = ((uint32)(b) > (uint32)(~(a))))
341 #define SET_C_SUB(a,b) (gpu_flag_c = ((uint32)(b) > (uint32)(a)))
342 #define SET_ZN(r) SET_N(r); SET_Z(r)
343 #define SET_ZNC_ADD(a,b,r) SET_N(r); SET_Z(r); SET_C_ADD(a,b)
344 #define SET_ZNC_SUB(a,b,r) SET_N(r); SET_Z(r); SET_C_SUB(a,b)
346 uint32 gpu_convert_zero[32] =
347 { 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 };
349 uint8 * branch_condition_table = 0;
350 #define BRANCH_CONDITION(x) branch_condition_table[(x) + ((jaguar_flags & 7) << 5)]
352 uint32 gpu_opcode_use[64];
354 const char * gpu_opcode_str[64]=
356 "add", "addc", "addq", "addqt",
357 "sub", "subc", "subq", "subqt",
358 "neg", "and", "or", "xor",
359 "not", "btst", "bset", "bclr",
360 "mult", "imult", "imultn", "resmac",
361 "imacn", "div", "abs", "sh",
362 "shlq", "shrq", "sha", "sharq",
363 "ror", "rorq", "cmp", "cmpq",
364 "sat8", "sat16", "move", "moveq",
365 "moveta", "movefa", "movei", "loadb",
366 "loadw", "load", "loadp", "load_r14_indexed",
367 "load_r15_indexed", "storeb", "storew", "store",
368 "storep", "store_r14_indexed","store_r15_indexed","move_pc",
369 "jump", "jr", "mmult", "mtoi",
370 "normi", "nop", "load_r14_ri", "load_r15_ri",
371 "store_r14_ri", "store_r15_ri", "sat24", "pack",
374 static uint32 gpu_in_exec = 0;
375 static uint32 gpu_releaseTimeSlice_flag = 0;
377 void gpu_releaseTimeslice(void)
379 gpu_releaseTimeSlice_flag = 1;
382 uint32 gpu_get_pc(void)
387 void build_branch_condition_table(void)
389 if (!branch_condition_table)
391 branch_condition_table = (uint8 *)malloc(32 * 8 * sizeof(branch_condition_table[0]));
393 if (branch_condition_table)
395 for(int i=0; i<8; i++)
397 for(int j=0; j<32; j++)
404 if (!(i & ZERO_FLAG))
407 if (i & (CARRY_FLAG << (j >> 4)))
410 if (!(i & (CARRY_FLAG << (j >> 4))))
412 branch_condition_table[i * 32 + j] = result;
420 // GPU byte access (read)
422 uint8 GPUReadByte(uint32 offset, uint32 who/*=UNKNOWN*/)
424 if (offset >= 0xF02000 && offset <= 0xF020FF)
425 WriteLog("GPU: ReadByte--Attempt to read from GPU register file by %s!\n", whoName[who]);
427 if ((offset >= GPU_WORK_RAM_BASE) && (offset < GPU_WORK_RAM_BASE+0x1000))
428 return gpu_ram_8[offset & 0xFFF];
429 else if ((offset >= GPU_CONTROL_RAM_BASE) && (offset < GPU_CONTROL_RAM_BASE+0x20))
431 uint32 data = GPUReadLong(offset & 0xFFFFFFFC, who);
433 if ((offset & 0x03) == 0)
435 else if ((offset & 0x03) == 1)
436 return (data >> 16) & 0xFF;
437 else if ((offset & 0x03) == 2)
438 return (data >> 8) & 0xFF;
439 else if ((offset & 0x03) == 3)
443 return JaguarReadByte(offset, who);
447 // GPU word access (read)
449 uint16 GPUReadWord(uint32 offset, uint32 who/*=UNKNOWN*/)
451 if (offset >= 0xF02000 && offset <= 0xF020FF)
452 WriteLog("GPU: ReadWord--Attempt to read from GPU register file by %s!\n", whoName[who]);
454 if ((offset >= GPU_WORK_RAM_BASE) && (offset < GPU_WORK_RAM_BASE+0x1000))
457 uint16 data = ((uint16)gpu_ram_8[offset] << 8) | (uint16)gpu_ram_8[offset+1];
460 else if ((offset >= GPU_CONTROL_RAM_BASE) && (offset < GPU_CONTROL_RAM_BASE+0x20))
462 // This looks and smells wrong...
463 // But it *might* be OK...
464 if (offset & 0x01) // Catch cases 1 & 3... (unaligned read)
465 return (GPUReadByte(offset, who) << 8) | GPUReadByte(offset+1, who);
467 uint32 data = GPUReadLong(offset & 0xFFFFFFFC, who);
469 if (offset & 0x02) // Cases 0 & 2...
470 return data & 0xFFFF;
475 //TEMP--Mirror of F03000? No. Writes only...
476 //if (offset >= 0xF0B000 && offset <= 0xF0BFFF)
477 //WriteLog("[GPUR16] --> Possible GPU RAM mirror access by %s!", whoName[who]);
479 return JaguarReadWord(offset, who);
483 // GPU dword access (read)
485 uint32 GPUReadLong(uint32 offset, uint32 who/*=UNKNOWN*/)
487 if (offset >= 0xF02000 && offset <= 0xF020FF)
488 WriteLog("GPU: ReadLong--Attempt to read from GPU register file by %s!\n", whoName[who]);
490 // if ((offset >= GPU_WORK_RAM_BASE) && (offset < GPU_WORK_RAM_BASE + 0x1000))
491 if ((offset >= GPU_WORK_RAM_BASE) && (offset <= GPU_WORK_RAM_BASE + 0x0FFC))
494 return ((uint32)gpu_ram_8[offset] << 24) | ((uint32)gpu_ram_8[offset+1] << 16)
495 | ((uint32)gpu_ram_8[offset+2] << 8) | (uint32)gpu_ram_8[offset+3];//*/
496 // return GET32(gpu_ram_8, offset);
498 // else if ((offset >= GPU_CONTROL_RAM_BASE) && (offset < GPU_CONTROL_RAM_BASE+0x20))
499 else if ((offset >= GPU_CONTROL_RAM_BASE) && (offset <= GPU_CONTROL_RAM_BASE + 0x1C))
505 gpu_flag_c = (gpu_flag_c ? 1 : 0);
506 gpu_flag_z = (gpu_flag_z ? 1 : 0);
507 gpu_flag_n = (gpu_flag_n ? 1 : 0);
509 gpu_flags = (gpu_flags & 0xFFFFFFF8) | (gpu_flag_n << 2) | (gpu_flag_c << 1) | gpu_flag_z;
511 return gpu_flags & 0xFFFFC1FF;
513 return gpu_matrix_control;
515 return gpu_pointer_to_matrix;
517 return gpu_data_organization;
526 default: // unaligned long read
528 WriteLog("GPU: Read32--unaligned 32 bit read at %08X by %s.\n", GPU_CONTROL_RAM_BASE + offset, whoName[who]);
533 //TEMP--Mirror of F03000? No. Writes only...
534 //if (offset >= 0xF0B000 && offset <= 0xF0BFFF)
535 // WriteLog("[GPUR32] --> Possible GPU RAM mirror access by %s!\n", whoName[who]);
536 /*if (offset >= 0xF1D000 && offset <= 0xF1DFFF)
537 WriteLog("[GPUR32] --> Reading from Wavetable ROM!\n");//*/
539 return (JaguarReadWord(offset, who) << 16) | JaguarReadWord(offset + 2, who);
543 // GPU byte access (write)
545 void GPUWriteByte(uint32 offset, uint8 data, uint32 who/*=UNKNOWN*/)
547 if (offset >= 0xF02000 && offset <= 0xF020FF)
548 WriteLog("GPU: WriteByte--Attempt to write to GPU register file by %s!\n", whoName[who]);
550 if ((offset >= GPU_WORK_RAM_BASE) && (offset <= GPU_WORK_RAM_BASE + 0x0FFF))
552 gpu_ram_8[offset & 0xFFF] = data;
554 //This is the same stupid worthless code that was in the DSP!!! AARRRGGGGHHHHH!!!!!!
557 m68k_end_timeslice();
558 dsp_releaseTimeslice();
562 else if ((offset >= GPU_CONTROL_RAM_BASE) && (offset <= GPU_CONTROL_RAM_BASE + 0x1F))
564 uint32 reg = offset & 0x1C;
565 int bytenum = offset & 0x03;
567 //This is definitely wrong!
568 if ((reg >= 0x1C) && (reg <= 0x1F))
569 gpu_div_control = (gpu_div_control & (~(0xFF << (bytenum << 3)))) | (data << (bytenum << 3));
572 uint32 old_data = GPUReadLong(offset & 0xFFFFFFC, who);
573 bytenum = 3 - bytenum; // convention motorola !!!
574 old_data = (old_data & (~(0xFF << (bytenum << 3)))) | (data << (bytenum << 3));
575 GPUWriteLong(offset & 0xFFFFFFC, old_data, who);
579 // WriteLog("gpu: writing %.2x at 0x%.8x\n",data,offset);
580 JaguarWriteByte(offset, data, who);
584 // GPU word access (write)
586 void GPUWriteWord(uint32 offset, uint16 data, uint32 who/*=UNKNOWN*/)
588 if (offset >= 0xF02000 && offset <= 0xF020FF)
589 WriteLog("GPU: WriteWord--Attempt to write to GPU register file by %s!\n", whoName[who]);
591 if ((offset >= GPU_WORK_RAM_BASE) && (offset <= GPU_WORK_RAM_BASE + 0x0FFE))
593 gpu_ram_8[offset & 0xFFF] = (data>>8) & 0xFF;
594 gpu_ram_8[(offset+1) & 0xFFF] = data & 0xFF;//*/
596 SET16(gpu_ram_8, offset, data);//*/
598 /*if (offset >= 0xF03214 && offset < 0xF0321F)
599 WriteLog("GPU: Writing WORD (%04X) to GPU RAM (%08X)...\n", data, offset);//*/
602 //This is the same stupid worthless code that was in the DSP!!! AARRRGGGGHHHHH!!!!!!
605 m68k_end_timeslice();
606 dsp_releaseTimeslice();
610 else if ((offset >= GPU_CONTROL_RAM_BASE) && (offset <= GPU_CONTROL_RAM_BASE + 0x1E))
612 if (offset & 0x01) // This is supposed to weed out unaligned writes, but does nothing...
615 WriteLog("GPU: Write16--unaligned write @ %08X [%04X]\n", offset, data);
620 //Dual locations in this range: $1C Divide unit remainder/Divide unit control (R/W)
621 //This just literally sucks.
622 if ((offset & 0x1C) == 0x1C)
624 //This doesn't look right either--handles cases 1, 2, & 3 all the same!
626 gpu_div_control = (gpu_div_control & 0xFFFF0000) | (data & 0xFFFF);
628 gpu_div_control = (gpu_div_control & 0x0000FFFF) | ((data & 0xFFFF) << 16);
632 //WriteLog("[GPU W16:%08X,%04X]", offset, data);
633 uint32 old_data = GPUReadLong(offset & 0xFFFFFFC, who);
635 old_data = (old_data & 0xFFFF0000) | (data & 0xFFFF);
637 old_data = (old_data & 0x0000FFFF) | ((data & 0xFFFF) << 16);
638 GPUWriteLong(offset & 0xFFFFFFC, old_data, who);
642 else if ((offset == GPU_WORK_RAM_BASE + 0x0FFF) || (GPU_CONTROL_RAM_BASE + 0x1F))
645 WriteLog("GPU: Write16--unaligned write @ %08X by %s [%04X]!\n", offset, whoName[who], data);
651 // Have to be careful here--this can cause an infinite loop!
652 JaguarWriteWord(offset, data, who);
656 // GPU dword access (write)
658 void GPUWriteLong(uint32 offset, uint32 data, uint32 who/*=UNKNOWN*/)
660 if (offset >= 0xF02000 && offset <= 0xF020FF)
661 WriteLog("GPU: WriteLong--Attempt to write to GPU register file by %s!\n", whoName[who]);
663 // if ((offset >= GPU_WORK_RAM_BASE) && (offset < GPU_WORK_RAM_BASE + 0x1000))
664 if ((offset >= GPU_WORK_RAM_BASE) && (offset <= GPU_WORK_RAM_BASE + 0x0FFC))
669 WriteLog("GPU: Write32--unaligned write @ %08X [%08X] by %s\n", offset, data, whoName[who]);
675 SET32(gpu_ram_8, offset, data);
678 // else if ((offset >= GPU_CONTROL_RAM_BASE) && (offset < GPU_CONTROL_RAM_BASE+0x20))
679 else if ((offset >= GPU_CONTROL_RAM_BASE) && (offset <= GPU_CONTROL_RAM_BASE + 0x1C))
686 bool IMASKCleared = (gpu_flags & IMASK) && !(data & IMASK);
688 gpu_flag_z = gpu_flags & ZERO_FLAG;
689 gpu_flag_c = (gpu_flags & CARRY_FLAG) >> 1;
690 gpu_flag_n = (gpu_flags & NEGA_FLAG) >> 2;
691 GPUUpdateRegisterBanks();
692 gpu_control &= ~((gpu_flags & CINT04FLAGS) >> 3); // Interrupt latch clear bits
693 //Writing here is only an interrupt enable--this approach is just plain wrong!
695 //This, however, is A-OK! ;-)
696 if (IMASKCleared) // If IMASK was cleared,
697 GPUHandleIRQs(); // see if any other interrupts need servicing!
699 if (gpu_flags & (INT_ENA0 | INT_ENA1 | INT_ENA2 | INT_ENA3 | INT_ENA4))
700 WriteLog("GPU: Interrupt enable set by %s! Bits: %02X\n", whoName[who], (gpu_flags >> 4) & 0x1F);
701 WriteLog("GPU: REGPAGE %s...\n", (gpu_flags & REGPAGE ? "set" : "cleared"));
706 gpu_matrix_control = data;
709 // This can only point to long aligned addresses
710 gpu_pointer_to_matrix = data & 0xFFFFFFFC;
713 gpu_data_organization = data;
718 WriteLog("GPU: %s setting GPU PC to %08X %s\n", whoName[who], gpu_pc, (GPU_RUNNING ? "(GPU is RUNNING!)" : ""));//*/
723 // uint32 gpu_was_running = GPU_RUNNING;
724 data &= ~0xF7C0; // Disable writes to INT_LAT0-4 & TOM version number
726 // check for GPU -> CPU interrupt
729 //WriteLog("GPU->CPU interrupt\n");
730 if (tom_irq_enabled(IRQ_GPU))
732 if ((tom_irq_enabled(IRQ_GPU)) && (jaguar_interrupt_handler_is_valid(64)))
734 tom_set_pending_gpu_int();
735 m68k_set_irq(7); // Set 68000 NMI
736 gpu_releaseTimeslice();
742 // check for CPU -> GPU interrupt #0
745 //WriteLog("CPU->GPU interrupt\n");
746 GPUSetIRQLine(0, ASSERT_LINE);
747 m68k_end_timeslice();
748 dsp_releaseTimeslice();
755 //WriteLog("asked to perform a single step (single step is %senabled)\n",(data&0x8)?"":"not ");
757 gpu_control = (gpu_control & 0xF7C0) | (data & (~0xF7C0));
759 // if gpu wasn't running but is now running, execute a few cycles
760 #ifndef GPU_SINGLE_STEPPING
761 /* if (!gpu_was_running && GPU_RUNNING)
764 WriteLog("GPU: Write32--About to do stupid braindead GPU execution for 200 cycles.\n");
769 #endif // GPU_DEBUG//*/
771 if (gpu_control & 0x18)
773 #endif // #ifndef GPU_SINGLE_STEPPING
775 WriteLog("Write to GPU CTRL by %s: %08X ", whoName[who], data);
777 WriteLog(" --> Starting to run at %08X by %s...", gpu_pc, whoName[who]);
779 WriteLog(" --> Stopped by %s! (GPU_PC: %08X)", whoName[who], gpu_pc);
783 // GPUDumpDisassembly();
786 if (gpu_pc == 0xF035D8)
788 // GPUDumpDisassembly();
791 gpu_control &= 0xFFFFFFFE; // Don't run it and let's see what happens!
792 //Hmm. Seems to lock up when going into the demo...
793 //Try to disable the collision altogether!
796 extern int effect_start5;
797 static bool finished = false;
798 //if (GPU_RUNNING && effect_start5 && !finished)
799 if (GPU_RUNNING && effect_start5 && gpu_pc == 0xF035D8)
801 // Let's do a dump of $6528!
802 /* uint32 numItems = JaguarReadWord(0x6BD6);
803 WriteLog("\nDump of $6528: %u items.\n\n", numItems);
804 for(int i=0; i<numItems*3*4; i+=3*4)
806 WriteLog("\t%04X: %08X %08X %08X -> ", 0x6528+i, JaguarReadLong(0x6528+i),
807 JaguarReadLong(0x6528+i+4), JaguarReadLong(0x6528+i+8));
808 uint16 link = JaguarReadWord(0x6528+i+8+2);
809 for(int j=0; j<40; j+=4)
810 WriteLog("%08X ", JaguarReadLong(link + j));
814 // Let's try a manual blit here...
815 //This isn't working the way it should! !!! FIX !!!
816 //Err, actually, it is.
817 // NOW, it works right! Problem solved!!! It's a blitter bug!
818 /* uint32 src = 0x4D54, dst = 0xF03000, width = 10 * 4;
819 for(int y=0; y<127; y++)
821 for(int x=0; x<2; x++)
823 JaguarWriteLong(dst, JaguarReadLong(src));
828 src += width - (2 * 4);
832 WriteLog("\nGPU: About to execute collision detection code.\n\n");//*/
834 /* WriteLog("\nGPU: About to execute collision detection code. Data @ 4D54:\n\n");
836 for(int i=0x004D54; i<0x004D54+2048; i++)
838 WriteLog("%02X ", JaguarReadByte(i));
846 WriteLog("\n\nData @ F03000:\n\n");
848 for(int i=0xF03000; i<0xF03200; i++)
850 WriteLog("%02X ", JaguarReadByte(i));
864 /*if (!GPU_RUNNING && finished)
866 WriteLog("\nGPU: Finished collision detection code. Exiting!\n\n");
871 // (?) If we're set running by the M68K (or DSP?) then end its timeslice to
872 // allow the GPU a chance to run...
873 // Yes! This partially fixed Trevor McFur...
875 m68k_end_timeslice();
882 gpu_div_control = data;
884 // default: // unaligned long write
891 // JaguarWriteWord(offset, (data >> 16) & 0xFFFF, who);
892 // JaguarWriteWord(offset+2, data & 0xFFFF, who);
893 // We're a 32-bit processor, we can do a long write...!
894 JaguarWriteLong(offset, data, who);
898 // Change register banks if necessary
900 void GPUUpdateRegisterBanks(void)
902 int bank = (gpu_flags & REGPAGE); // REGPAGE bit
904 if (gpu_flags & IMASK) // IMASK bit
905 bank = 0; // IMASK forces main bank to be bank 0
908 gpu_reg = gpu_reg_bank_1, gpu_alternate_reg = gpu_reg_bank_0;
910 gpu_reg = gpu_reg_bank_0, gpu_alternate_reg = gpu_reg_bank_1;
913 void GPUHandleIRQs(void)
915 // Bail out if we're already in an interrupt!
916 if (gpu_flags & IMASK)
919 // Get the interrupt latch & enable bits
920 uint32 bits = (gpu_control >> 6) & 0x1F, mask = (gpu_flags >> 4) & 0x1F;
922 // Bail out if latched interrupts aren't enabled
927 // Determine which interrupt to service
928 uint32 which = 0; //Isn't there a #pragma to disable this warning???
941 WriteLog("GPU: Generating IRQ #%i\n", which);
943 // set the interrupt flag
945 GPUUpdateRegisterBanks();
947 // subqt #4,r31 ; pre-decrement stack pointer
948 // move pc,r30 ; address of interrupted code
949 // store r30,(r31) ; store return address
951 GPUWriteLong(gpu_reg[31], gpu_pc - 2, GPU);
953 // movei #service_address,r30 ; pointer to ISR entry
954 // jump (r30) ; jump to ISR
956 gpu_pc = gpu_reg[30] = GPU_WORK_RAM_BASE + (which * 0x10);
959 void GPUSetIRQLine(int irqline, int state)
962 WriteLog("GPU: Setting GPU IRQ line #%i\n", irqline);
964 uint32 mask = 0x0040 << irqline;
965 gpu_control &= ~mask; // Clear the interrupt latch
969 gpu_control |= mask; // Assert the interrupt latch
970 GPUHandleIRQs(); // And handle the interrupt...
974 //TEMPORARY: Testing only!
980 // memory_malloc_secure((void **)&gpu_ram_8, 0x1000, "GPU work RAM");
981 // memory_malloc_secure((void **)&gpu_reg_bank_0, 32 * sizeof(int32), "GPU bank 0 regs");
982 // memory_malloc_secure((void **)&gpu_reg_bank_1, 32 * sizeof(int32), "GPU bank 1 regs");
984 build_branch_condition_table();
988 //TEMPORARY: Testing only!
995 // GPU registers (directly visible)
996 gpu_flags = 0x00000000;
997 gpu_matrix_control = 0x00000000;
998 gpu_pointer_to_matrix = 0x00000000;
999 gpu_data_organization = 0xFFFFFFFF;
1000 gpu_pc = 0x00F03000;
1001 gpu_control = 0x00002800; // Correctly sets this as TOM Rev. 2
1002 gpu_hidata = 0x00000000;
1003 gpu_remain = 0x00000000; // These two registers are RO/WO
1004 gpu_div_control = 0x00000000;
1006 // GPU internal register
1007 gpu_acc = 0x00000000;
1009 gpu_reg = gpu_reg_bank_0;
1010 gpu_alternate_reg = gpu_reg_bank_1;
1012 for(int i=0; i<32; i++)
1013 gpu_reg[i] = gpu_alternate_reg[i] = 0x00000000;
1016 memset(gpu_ram_8, 0xFF, 0x1000);
1018 //not needed GPUInterruptPending = false;
1022 uint32 gpu_read_pc(void)
1027 void gpu_reset_stats(void)
1029 for(uint32 i=0; i<64; i++)
1030 gpu_opcode_use[i] = 0;
1031 WriteLog("--> GPU stats were reset!\n");
1034 void GPUDumpDisassembly(void)
1038 WriteLog("\n---[GPU code at 00F03000]---------------------------\n");
1039 uint32 j = 0xF03000;
1040 while (j <= 0xF03FFF)
1043 j += dasmjag(JAGUAR_GPU, buffer, j);
1044 WriteLog("\t%08X: %s\n", oldj, buffer);
1048 void GPUDumpRegisters(void)
1050 WriteLog("\n---[GPU flags: NCZ %d%d%d]-----------------------\n", gpu_flag_n, gpu_flag_c, gpu_flag_z);
1051 WriteLog("\nRegisters bank 0\n");
1052 for(int j=0; j<8; j++)
1054 WriteLog("\tR%02i = %08X R%02i = %08X R%02i = %08X R%02i = %08X\n",
1055 (j << 2) + 0, gpu_reg_bank_0[(j << 2) + 0],
1056 (j << 2) + 1, gpu_reg_bank_0[(j << 2) + 1],
1057 (j << 2) + 2, gpu_reg_bank_0[(j << 2) + 2],
1058 (j << 2) + 3, gpu_reg_bank_0[(j << 2) + 3]);
1060 WriteLog("Registers bank 1\n");
1061 for(int j=0; j<8; j++)
1063 WriteLog("\tR%02i = %08X R%02i = %08X R%02i = %08X R%02i = %08X\n",
1064 (j << 2) + 0, gpu_reg_bank_1[(j << 2) + 0],
1065 (j << 2) + 1, gpu_reg_bank_1[(j << 2) + 1],
1066 (j << 2) + 2, gpu_reg_bank_1[(j << 2) + 2],
1067 (j << 2) + 3, gpu_reg_bank_1[(j << 2) + 3]);
1071 void GPUDumpMemory(void)
1073 WriteLog("\n---[GPU data at 00F03000]---------------------------\n");
1074 for(int i=0; i<0xFFF; i+=4)
1075 WriteLog("\t%08X: %02X %02X %02X %02X\n", 0xF03000+i, gpu_ram_8[i],
1076 gpu_ram_8[i+1], gpu_ram_8[i+2], gpu_ram_8[i+3]);
1081 WriteLog("GPU: Stopped at PC=%08X (GPU %s running)\n", (unsigned int)gpu_pc, GPU_RUNNING ? "was" : "wasn't");
1083 // Get the interrupt latch & enable bits
1084 uint8 bits = (gpu_control >> 6) & 0x1F, mask = (gpu_flags >> 4) & 0x1F;
1085 WriteLog("GPU: Latch bits = %02X, enable bits = %02X\n", bits, mask);
1088 GPUDumpDisassembly();
1090 WriteLog("\nGPU opcodes use:\n");
1091 for(int i=0; i<64; i++)
1093 if (gpu_opcode_use[i])
1094 WriteLog("\t%17s %lu\n", gpu_opcode_str[i], gpu_opcode_use[i]);
1098 memory_free(gpu_ram_8);
1099 memory_free(gpu_reg_bank_0);
1100 memory_free(gpu_reg_bank_1);
1104 // Main GPU execution core
1106 static int testCount = 1;
1108 static bool tripwire = false;
1109 void gpu_exec(int32 cycles)
1114 #ifdef GPU_SINGLE_STEPPING
1115 if (gpu_control & 0x18)
1118 gpu_control &= ~0x10;
1122 gpu_releaseTimeSlice_flag = 0;
1125 while (cycles > 0 && GPU_RUNNING)
1127 if (gpu_ram_8[0x054] == 0x98 && gpu_ram_8[0x055] == 0x0A && gpu_ram_8[0x056] == 0x03
1128 && gpu_ram_8[0x057] == 0x00 && gpu_ram_8[0x058] == 0x00 && gpu_ram_8[0x059] == 0x00)
1130 if (gpu_pc == 0xF03000)
1132 extern uint32 starCount;
1134 /* WriteLog("GPU: Starting starfield generator... Dump of [R03=%08X]:\n", gpu_reg_bank_0[03]);
1135 uint32 base = gpu_reg_bank_0[3];
1136 for(uint32 i=0; i<0x100; i+=16)
1138 WriteLog("%02X: ", i);
1139 for(uint32 j=0; j<16; j++)
1141 WriteLog("%02X ", JaguarReadByte(base + i + j));
1146 // if (gpu_pc == 0xF03)
1150 /*if (gpu_pc == 0xF03B9E && gpu_reg_bank_0[01] == 0)
1153 WriteLog("GPU: Starting disassembly log...\n");
1156 /*if (gpu_pc == 0xF0359A)
1161 /* gpu_flag_c = (gpu_flag_c ? 1 : 0);
1162 gpu_flag_z = (gpu_flag_z ? 1 : 0);
1163 gpu_flag_n = (gpu_flag_n ? 1 : 0);*/
1165 uint16 opcode = GPUReadWord(gpu_pc, GPU);
1166 uint32 index = opcode >> 10;
1167 gpu_instruction = opcode; // Added for GPU #3...
1168 gpu_opcode_first_parameter = (opcode >> 5) & 0x1F;
1169 gpu_opcode_second_parameter = opcode & 0x1F;
1170 /*if (gpu_pc == 0xF03BE8)
1171 WriteLog("Start of OP frame write...\n");
1172 if (gpu_pc == 0xF03EEE)
1173 WriteLog("--> Writing BRANCH object ---\n");
1174 if (gpu_pc == 0xF03F62)
1175 WriteLog("--> Writing BITMAP object ***\n");//*/
1176 /*if (gpu_pc == 0xF03546)
1178 WriteLog("\n--> GPU PC: F03546\n");
1180 GPUDumpDisassembly();
1182 /*if (gpu_pc == 0xF033F6)
1184 WriteLog("\n--> GPU PC: F033F6\n");
1186 GPUDumpDisassembly();
1188 /*if (gpu_pc == 0xF033CC)
1190 WriteLog("\n--> GPU PC: F033CC\n");
1192 GPUDumpDisassembly();
1194 /*if (gpu_pc == 0xF033D6)
1196 WriteLog("\n--> GPU PC: F033D6 (#%d)\n", testCount++);
1200 /*if (gpu_pc == 0xF033D8)
1202 WriteLog("\n--> GPU PC: F033D8 (#%d)\n", testCount++);
1206 /*if (gpu_pc == 0xF0358E)
1208 WriteLog("\n--> GPU PC: F0358E (#%d)\n", testCount++);
1212 /*if (gpu_pc == 0xF034CA)
1214 WriteLog("\n--> GPU PC: F034CA (#%d)\n", testCount++);
1217 /*if (gpu_pc == 0xF034CA)
1219 len = gpu_reg[1] + 4;//, r9save = gpu_reg[9];
1220 WriteLog("\nAbout to subtract [#%d] (R14=%08X, R15=%08X, R9=%08X):\n ", testCount++, gpu_reg[14], gpu_reg[15], gpu_reg[9]);
1221 for(int i=0; i<len; i+=4)
1222 WriteLog(" %08X", GPUReadLong(gpu_reg[15]+i));
1224 for(int i=0; i<len; i+=4)
1225 WriteLog(" %08X", GPUReadLong(gpu_reg[14]+i));
1228 if (gpu_pc == 0xF034DE)
1230 WriteLog("\nSubtracted! (R14=%08X, R15=%08X):\n ", gpu_reg[14], gpu_reg[15]);
1231 for(int i=0; i<len; i+=4)
1232 WriteLog(" %08X", GPUReadLong(gpu_reg[15]+i));
1234 for(int i=0; i<len; i+=4)
1235 WriteLog(" %08X", GPUReadLong(gpu_reg[14]+i));
1237 for(int i=0; i<len; i+=4)
1238 WriteLog(" --------");
1240 for(int i=0; i<len; i+=4)
1241 WriteLog(" %08X", GPUReadLong(gpu_reg[9]+4+i));
1244 /*if (gpu_pc == 0xF035C8)
1246 WriteLog("\n--> GPU PC: F035C8 (#%d)\n", testCount++);
1248 GPUDumpDisassembly();
1253 // gpu_reset_stats();
1254 static char buffer[512];
1255 dasmjag(JAGUAR_GPU, buffer, gpu_pc);
1256 WriteLog("GPU: [%08X] %s (RM=%08X, RN=%08X) -> ", gpu_pc, buffer, RM, RN);
1258 //$E400 -> 1110 01 -> $39 -> 57
1261 gpu_opcode[index]();
1263 // gpu2_opcode[index]();
1265 //GPU #3 (Doesn't show ATARI logo! #1 & #2 do...)
1267 // gpu3_opcode[index]();
1270 //GPU: [00F03548] jr nz,00F03560 (0xd561) (RM=00F03114, RN=00000004) -> --> JR: Branch taken.
1271 /*static bool firstTime = true;
1272 if (gpu_pc == 0xF03548 && firstTime)
1275 // firstTime = false;
1277 //static char buffer[512];
1279 //while (k<0xF0356C)
1282 //k += dasmjag(JAGUAR_GPU, buffer, k);
1283 //WriteLog("GPU: [%08X] %s\n", oldk, buffer);
1285 // gpu_start_log = 1;
1287 //GPU: [00F0354C] jump nz,(r29) (0xd3a1) (RM=00F03314, RN=00000004) -> (RM=00F03314, RN=00000004)
1288 /*if (gpu_pc == 0xF0354C)
1289 gpu_flag_z = 0;//, gpu_start_log = 1;//*/
1291 cycles -= gpu_opcode_cycles[index];
1292 gpu_opcode_use[index]++;
1294 WriteLog("(RM=%08X, RN=%08X)\n", RM, RN);//*/
1295 if ((gpu_pc < 0xF03000 || gpu_pc > 0xF03FFF) && !tripwire)
1297 WriteLog("GPU: Executing outside local RAM! GPU_PC: %08X\n", gpu_pc);
1310 GPU opcodes use (offset punch--vertically below bad guy):
1332 load_r14_indexed 1183
1333 load_r15_indexed 1125
1336 store_r14_indexed 320
1344 static void gpu_opcode_jump(void)
1347 const char * condition[32] =
1348 { "T", "nz", "z", "???", "nc", "nc nz", "nc z", "???", "c", "c nz",
1349 "c z", "???", "???", "???", "???", "???", "???", "???", "???",
1350 "???", "nn", "nn nz", "nn z", "???", "n", "n nz", "n z", "???",
1351 "???", "???", "???", "F" };
1353 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);
1356 /* gpu_flag_c = (gpu_flag_c ? 1 : 0);
1357 gpu_flag_z = (gpu_flag_z ? 1 : 0);
1358 gpu_flag_n = (gpu_flag_n ? 1 : 0);*/
1359 // KLUDGE: Used by BRANCH_CONDITION
1360 uint32 jaguar_flags = (gpu_flag_n << 2) | (gpu_flag_c << 1) | gpu_flag_z;
1362 if (BRANCH_CONDITION(IMM_2))
1366 WriteLog("Branched!\n");
1369 WriteLog(" --> JUMP: Branch taken.\n");
1370 uint32 delayed_pc = RM;
1372 gpu_pc = delayed_pc;
1373 /* uint16 opcode = GPUReadWord(gpu_pc, GPU);
1374 gpu_opcode_first_parameter = (opcode >> 5) & 0x1F;
1375 gpu_opcode_second_parameter = opcode & 0x1F;
1377 gpu_pc = delayed_pc;
1378 gpu_opcode[opcode>>10]();//*/
1383 WriteLog("Branch NOT taken.\n");
1387 static void gpu_opcode_jr(void)
1390 const char * condition[32] =
1391 { "T", "nz", "z", "???", "nc", "nc nz", "nc z", "???", "c", "c nz",
1392 "c z", "???", "???", "???", "???", "???", "???", "???", "???",
1393 "???", "nn", "nn nz", "nn z", "???", "n", "n nz", "n z", "???",
1394 "???", "???", "???", "F" };
1396 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);
1398 /* if (CONDITION(jaguar.op & 31))
1400 int32 r1 = (INT8)((jaguar.op >> 2) & 0xF8) >> 2;
1401 uint32 newpc = jaguar.PC + r1;
1403 jaguar.op = ROPCODE(jaguar.PC);
1405 (*jaguar.table[jaguar.op >> 10])();
1407 jaguar_icount -= 3; // 3 wait states guaranteed
1410 /* gpu_flag_n = (gpu_flag_n ? 1 : 0);
1411 gpu_flag_c = (gpu_flag_c ? 1 : 0);
1412 gpu_flag_z = (gpu_flag_z ? 1 : 0);*/
1413 // KLUDGE: Used by BRANCH_CONDITION
1414 uint32 jaguar_flags = (gpu_flag_n << 2) | (gpu_flag_c << 1) | gpu_flag_z;
1416 if (BRANCH_CONDITION(IMM_2))
1420 WriteLog("Branched!\n");
1423 WriteLog(" --> JR: Branch taken.\n");
1424 int32 offset = (IMM_1 & 0x10 ? 0xFFFFFFF0 | IMM_1 : IMM_1); // Sign extend IMM_1
1425 int32 delayed_pc = gpu_pc + (offset * 2);
1427 gpu_pc = delayed_pc;
1428 /* uint16 opcode = GPUReadWord(gpu_pc, GPU);
1429 gpu_opcode_first_parameter = (opcode >> 5) & 0x1F;
1430 gpu_opcode_second_parameter = opcode & 0x1F;
1432 gpu_pc = delayed_pc;
1433 gpu_opcode[opcode>>10]();//*/
1438 WriteLog("Branch NOT taken.\n");
1442 static void gpu_opcode_add(void)
1446 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);
1448 uint32 res = RN + RM;
1449 CLR_ZNC; SET_ZNC_ADD(RN, RM, res);
1453 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);
1457 static void gpu_opcode_addc(void)
1461 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);
1463 /* int dreg = jaguar.op & 31;
1464 uint32 r1 = jaguar.r[(jaguar.op >> 5) & 31];
1465 uint32 r2 = jaguar.r[dreg];
1466 uint32 res = r2 + r1 + ((jaguar.FLAGS >> 1) & 1);
1467 jaguar.r[dreg] = res;
1468 CLR_ZNC; SET_ZNC_ADD(r2,r1,res);*/
1470 uint32 res = RN + RM + gpu_flag_c;
1471 uint32 carry = gpu_flag_c;
1472 // SET_ZNC_ADD(RN, RM, res); //???BUG??? Yes!
1473 SET_ZNC_ADD(RN + carry, RM, res);
1474 // SET_ZNC_ADD(RN, RM + carry, res);
1478 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);
1482 static void gpu_opcode_addq(void)
1486 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);
1488 uint32 r1 = gpu_convert_zero[IMM_1];
1489 uint32 res = RN + r1;
1490 CLR_ZNC; SET_ZNC_ADD(RN, r1, res);
1494 WriteLog("[NCZ:%u%u%u, R%02u=%08X]\n", gpu_flag_n, gpu_flag_c, gpu_flag_z, IMM_2, RN);
1498 static void gpu_opcode_addqt(void)
1500 #ifdef GPU_DIS_ADDQT
1502 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);
1504 RN += gpu_convert_zero[IMM_1];
1505 #ifdef GPU_DIS_ADDQT
1507 WriteLog("[NCZ:%u%u%u, R%02u=%08X]\n", gpu_flag_n, gpu_flag_c, gpu_flag_z, IMM_2, RN);
1511 static void gpu_opcode_sub(void)
1515 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);
1517 uint32 res = RN - RM;
1518 SET_ZNC_SUB(RN, RM, res);
1522 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);
1526 static void gpu_opcode_subc(void)
1530 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);
1532 uint32 res = RN - RM - gpu_flag_c;
1533 uint32 borrow = gpu_flag_c;
1534 // SET_ZNC_SUB(RN, RM, res); //???BUG??? YES!!!
1535 //No matter how you do it, there is a problem. With below, it's 0-0 with carry,
1536 //and the one below it it's FFFFFFFF - FFFFFFFF with carry... !!! FIX !!!
1537 // SET_ZNC_SUB(RN - borrow, RM, res);
1538 SET_ZNC_SUB(RN, RM + borrow, res);
1542 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);
1546 N = 5, M = 3, 3 - 5 = -2, C = 1... Or, in our case:
1547 N = 0, M = 1, 0 - 1 = -1, C = 0!
1549 #define SET_C_SUB(a,b) (gpu_flag_c = ((uint32)(b) > (uint32)(a)))
1550 #define SET_ZN(r) SET_N(r); SET_Z(r)
1551 #define SET_ZNC_ADD(a,b,r) SET_N(r); SET_Z(r); SET_C_ADD(a,b)
1552 #define SET_ZNC_SUB(a,b,r) SET_N(r); SET_Z(r); SET_C_SUB(a,b)
1554 static void gpu_opcode_subq(void)
1558 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);
1560 uint32 r1 = gpu_convert_zero[IMM_1];
1561 uint32 res = RN - r1;
1562 SET_ZNC_SUB(RN, r1, res);
1566 WriteLog("[NCZ:%u%u%u, R%02u=%08X]\n", gpu_flag_n, gpu_flag_c, gpu_flag_z, IMM_2, RN);
1570 static void gpu_opcode_subqt(void)
1572 #ifdef GPU_DIS_SUBQT
1574 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);
1576 RN -= gpu_convert_zero[IMM_1];
1577 #ifdef GPU_DIS_SUBQT
1579 WriteLog("[NCZ:%u%u%u, R%02u=%08X]\n", gpu_flag_n, gpu_flag_c, gpu_flag_z, IMM_2, RN);
1583 static void gpu_opcode_cmp(void)
1587 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);
1589 uint32 res = RN - RM;
1590 SET_ZNC_SUB(RN, RM, res);
1593 WriteLog("[NCZ:%u%u%u]\n", gpu_flag_n, gpu_flag_c, gpu_flag_z);
1597 static void gpu_opcode_cmpq(void)
1599 static int32 sqtable[32] =
1600 { 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 };
1603 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);
1605 uint32 r1 = sqtable[IMM_1 & 0x1F]; // I like this better -> (INT8)(jaguar.op >> 2) >> 3;
1606 uint32 res = RN - r1;
1607 SET_ZNC_SUB(RN, r1, res);
1610 WriteLog("[NCZ:%u%u%u]\n", gpu_flag_n, gpu_flag_c, gpu_flag_z);
1614 static void gpu_opcode_and(void)
1618 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);
1624 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);
1628 static void gpu_opcode_or(void)
1632 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);
1638 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);
1642 static void gpu_opcode_xor(void)
1646 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);
1652 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);
1656 static void gpu_opcode_not(void)
1660 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);
1666 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);
1670 static void gpu_opcode_move_pc(void)
1672 #ifdef GPU_DIS_MOVEPC
1674 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);
1676 // Should be previous PC--this might not always be previous instruction!
1677 // Then again, this will point right at the *current* instruction, i.e., MOVE PC,R!
1679 #ifdef GPU_DIS_MOVEPC
1681 WriteLog("[NCZ:%u%u%u, R%02u=%08X]\n", gpu_flag_n, gpu_flag_c, gpu_flag_z, IMM_2, RN);
1685 static void gpu_opcode_sat8(void)
1689 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);
1691 RN = ((int32)RN < 0 ? 0 : (RN > 0xFF ? 0xFF : RN));
1695 WriteLog("[NCZ:%u%u%u, R%02u=%08X]\n", gpu_flag_n, gpu_flag_c, gpu_flag_z, IMM_2, RN);
1699 static void gpu_opcode_sat16(void)
1701 RN = ((int32)RN < 0 ? 0 : (RN > 0xFFFF ? 0xFFFF : RN));
1705 static void gpu_opcode_sat24(void)
1707 RN = ((int32)RN < 0 ? 0 : (RN > 0xFFFFFF ? 0xFFFFFF : RN));
1711 static void gpu_opcode_store_r14_indexed(void)
1713 #ifdef GPU_DIS_STORE14I
1715 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));
1717 GPUWriteLong(gpu_reg[14] + (gpu_convert_zero[IMM_1] << 2), RN, GPU);
1720 static void gpu_opcode_store_r15_indexed(void)
1722 #ifdef GPU_DIS_STORE15I
1724 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));
1726 GPUWriteLong(gpu_reg[15] + (gpu_convert_zero[IMM_1] << 2), RN, GPU);
1729 static void gpu_opcode_load_r14_ri(void)
1731 #ifdef GPU_DIS_LOAD14R
1733 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);
1735 RN = GPUReadLong(gpu_reg[14] + RM, GPU);
1736 #ifdef GPU_DIS_LOAD14R
1738 WriteLog("[NCZ:%u%u%u, R%02u=%08X]\n", gpu_flag_n, gpu_flag_c, gpu_flag_z, IMM_2, RN);
1742 static void gpu_opcode_load_r15_ri(void)
1744 #ifdef GPU_DIS_LOAD15R
1746 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);
1748 RN = GPUReadLong(gpu_reg[15] + RM, GPU);
1749 #ifdef GPU_DIS_LOAD15R
1751 WriteLog("[NCZ:%u%u%u, R%02u=%08X]\n", gpu_flag_n, gpu_flag_c, gpu_flag_z, IMM_2, RN);
1755 static void gpu_opcode_store_r14_ri(void)
1757 #ifdef GPU_DIS_STORE14R
1759 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]);
1761 GPUWriteLong(gpu_reg[14] + RM, RN, GPU);
1764 static void gpu_opcode_store_r15_ri(void)
1766 #ifdef GPU_DIS_STORE15R
1768 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]);
1770 GPUWriteLong(gpu_reg[15] + RM, RN, GPU);
1773 static void gpu_opcode_nop(void)
1777 WriteLog("%06X: NOP [NCZ:%u%u%u]\n", gpu_pc-2, gpu_flag_n, gpu_flag_c, gpu_flag_z);
1781 static void gpu_opcode_pack(void)
1785 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);
1789 //BUG! if (RM == 0) // Pack
1790 if (IMM_1 == 0) // Pack
1791 RN = ((val >> 10) & 0x0000F000) | ((val >> 5) & 0x00000F00) | (val & 0x000000FF);
1793 RN = ((val & 0x0000F000) << 10) | ((val & 0x00000F00) << 5) | (val & 0x000000FF);
1796 WriteLog("[NCZ:%u%u%u, R%02u=%08X]\n", gpu_flag_n, gpu_flag_c, gpu_flag_z, IMM_2, RN);
1800 static void gpu_opcode_storeb(void)
1802 #ifdef GPU_DIS_STOREB
1804 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);
1807 // Would appear to be so...!
1808 if ((RM >= 0xF03000) && (RM <= 0xF03FFF))
1809 GPUWriteLong(RM, RN & 0xFF, GPU);
1811 JaguarWriteByte(RM, RN, GPU);
1814 static void gpu_opcode_storew(void)
1816 #ifdef GPU_DIS_STOREW
1818 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);
1820 if ((RM >= 0xF03000) && (RM <= 0xF03FFF))
1821 GPUWriteLong(RM, RN & 0xFFFF, GPU);
1823 JaguarWriteWord(RM, RN, GPU);
1826 static void gpu_opcode_store(void)
1828 #ifdef GPU_DIS_STORE
1830 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);
1832 GPUWriteLong(RM, RN, GPU);
1835 static void gpu_opcode_storep(void)
1837 GPUWriteLong(RM + 0, gpu_hidata, GPU);
1838 GPUWriteLong(RM + 4, RN, GPU);
1841 static void gpu_opcode_loadb(void)
1843 #ifdef GPU_DIS_LOADB
1845 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);
1847 if ((RM >= 0xF03000) && (RM <= 0xF03FFF))
1848 RN = GPUReadLong(RM, GPU) & 0xFF;
1850 RN = JaguarReadByte(RM, GPU);
1851 #ifdef GPU_DIS_LOADB
1853 WriteLog("[NCZ:%u%u%u, R%02u=%08X]\n", gpu_flag_n, gpu_flag_c, gpu_flag_z, IMM_2, RN);
1857 static void gpu_opcode_loadw(void)
1859 #ifdef GPU_DIS_LOADW
1861 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);
1863 if ((RM >= 0xF03000) && (RM <= 0xF03FFF))
1864 RN = GPUReadLong(RM, GPU) & 0xFFFF;
1866 RN = JaguarReadWord(RM, GPU);
1867 #ifdef GPU_DIS_LOADW
1869 WriteLog("[NCZ:%u%u%u, R%02u=%08X]\n", gpu_flag_n, gpu_flag_c, gpu_flag_z, IMM_2, RN);
1873 static void gpu_opcode_load(void)
1877 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);
1879 RN = GPUReadLong(RM, GPU);
1882 WriteLog("[NCZ:%u%u%u, R%02u=%08X]\n", gpu_flag_n, gpu_flag_c, gpu_flag_z, IMM_2, RN);
1886 static void gpu_opcode_loadp(void)
1888 gpu_hidata = GPUReadLong(RM + 0, GPU);
1889 RN = GPUReadLong(RM + 4, GPU);
1892 static void gpu_opcode_load_r14_indexed(void)
1894 #ifdef GPU_DIS_LOAD14I
1896 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);
1898 RN = GPUReadLong(gpu_reg[14] + (gpu_convert_zero[IMM_1] << 2), GPU);
1899 #ifdef GPU_DIS_LOAD14I
1901 WriteLog("[NCZ:%u%u%u, R%02u=%08X]\n", gpu_flag_n, gpu_flag_c, gpu_flag_z, IMM_2, RN);
1905 static void gpu_opcode_load_r15_indexed(void)
1907 #ifdef GPU_DIS_LOAD15I
1909 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);
1911 RN = GPUReadLong(gpu_reg[15] + (gpu_convert_zero[IMM_1] << 2), GPU);
1912 #ifdef GPU_DIS_LOAD15I
1914 WriteLog("[NCZ:%u%u%u, R%02u=%08X]\n", gpu_flag_n, gpu_flag_c, gpu_flag_z, IMM_2, RN);
1918 static void gpu_opcode_movei(void)
1920 #ifdef GPU_DIS_MOVEI
1922 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);
1924 // This instruction is followed by 32-bit value in LSW / MSW format...
1925 RN = (uint32)GPUReadWord(gpu_pc, GPU) | ((uint32)GPUReadWord(gpu_pc + 2, GPU) << 16);
1927 #ifdef GPU_DIS_MOVEI
1929 WriteLog("[NCZ:%u%u%u, R%02u=%08X]\n", gpu_flag_n, gpu_flag_c, gpu_flag_z, IMM_2, RN);
1933 static void gpu_opcode_moveta(void)
1935 #ifdef GPU_DIS_MOVETA
1937 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);
1940 #ifdef GPU_DIS_MOVETA
1942 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);
1946 static void gpu_opcode_movefa(void)
1948 #ifdef GPU_DIS_MOVEFA
1950 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);
1953 #ifdef GPU_DIS_MOVEFA
1955 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);
1959 static void gpu_opcode_move(void)
1963 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);
1968 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);
1972 static void gpu_opcode_moveq(void)
1974 #ifdef GPU_DIS_MOVEQ
1976 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);
1979 #ifdef GPU_DIS_MOVEQ
1981 WriteLog("[NCZ:%u%u%u, R%02u=%08X]\n", gpu_flag_n, gpu_flag_c, gpu_flag_z, IMM_2, RN);
1985 static void gpu_opcode_resmac(void)
1990 static void gpu_opcode_imult(void)
1992 #ifdef GPU_DIS_IMULT
1994 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);
1996 RN = (int16)RN * (int16)RM;
1998 #ifdef GPU_DIS_IMULT
2000 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);
2004 static void gpu_opcode_mult(void)
2008 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);
2010 RN = (uint16)RM * (uint16)RN;
2014 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);
2018 static void gpu_opcode_bclr(void)
2022 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);
2024 uint32 res = RN & ~(1 << IMM_1);
2029 WriteLog("[NCZ:%u%u%u, R%02u=%08X]\n", gpu_flag_n, gpu_flag_c, gpu_flag_z, IMM_2, RN);
2033 static void gpu_opcode_btst(void)
2037 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);
2039 gpu_flag_z = (~RN >> IMM_1) & 1;
2042 WriteLog("[NCZ:%u%u%u, R%02u=%08X]\n", gpu_flag_n, gpu_flag_c, gpu_flag_z, IMM_2, RN);
2046 static void gpu_opcode_bset(void)
2050 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);
2052 uint32 res = RN | (1 << IMM_1);
2057 WriteLog("[NCZ:%u%u%u, R%02u=%08X]\n", gpu_flag_n, gpu_flag_c, gpu_flag_z, IMM_2, RN);
2061 static void gpu_opcode_imacn(void)
2063 uint32 res = (int16)RM * (int16)(RN);
2067 static void gpu_opcode_mtoi(void)
2070 uint32 res = RN = (((int32)_RM >> 8) & 0xFF800000) | (_RM & 0x007FFFFF);
2074 static void gpu_opcode_normi(void)
2081 while ((_RM & 0xFFC00000) == 0)
2086 while ((_RM & 0xFF800000) != 0)
2096 static void gpu_opcode_mmult(void)
2098 int count = gpu_matrix_control & 0x0F; // Matrix width
2099 uint32 addr = gpu_pointer_to_matrix; // In the GPU's RAM
2103 if (gpu_matrix_control & 0x10) // Column stepping
2105 for(int i=0; i<count; i++)
2109 a = (int16)((gpu_alternate_reg[IMM_1 + (i >> 1)] >> 16) & 0xFFFF);
2111 a = (int16)(gpu_alternate_reg[IMM_1 + (i >> 1)] & 0xFFFF);
2113 int16 b = ((int16)GPUReadWord(addr + 2, GPU));
2118 else // Row stepping
2120 for(int i=0; i<count; i++)
2124 a = (int16)((gpu_alternate_reg[IMM_1 + (i >> 1)] >> 16) & 0xFFFF);
2126 a = (int16)(gpu_alternate_reg[IMM_1 + (i >> 1)] & 0xFFFF);
2128 int16 b = ((int16)GPUReadWord(addr + 2, GPU));
2133 RN = res = (int32)accum;
2134 // carry flag to do (out of the last add)
2138 static void gpu_opcode_abs(void)
2142 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);
2144 gpu_flag_c = RN >> 31;
2145 if (RN == 0x80000000)
2146 //Is 0x80000000 a positive number? If so, then we need to set C to 0 as well!
2147 gpu_flag_n = 1, gpu_flag_z = 0;
2152 gpu_flag_n = 0; SET_FLAG_Z(RN);
2156 WriteLog("[NCZ:%u%u%u, R%02u=%08X]\n", gpu_flag_n, gpu_flag_c, gpu_flag_z, IMM_2, RN);
2160 static void gpu_opcode_div(void) // RN / RM
2164 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);
2166 // NOTE: remainder is NOT calculated correctly here!
2167 // The original tried to get it right by checking to see if the
2168 // remainder was negative, but that's too late...
2169 // The code there should do it now, but I'm not 100% sure...
2173 if (gpu_div_control & 0x01) // 16.16 division
2175 RN = ((uint64)RN << 16) / RM;
2176 gpu_remain = ((uint64)RN << 16) % RM;
2181 gpu_remain = RN % RM;
2184 if ((gpu_remain - RM) & 0x80000000) // If the result would have been negative...
2185 gpu_remain -= RM; // Then make it negative!
2195 if (gpu_div_control & 1)
2197 gpu_remain = (((uint64)_RN) << 16) % _RM;
2198 if (gpu_remain&0x80000000)
2200 RN = (((uint64)_RN) << 16) / _RM;
2204 gpu_remain = _RN % _RM;
2205 if (gpu_remain&0x80000000)
2214 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);
2218 static void gpu_opcode_imultn(void)
2220 uint32 res = (int32)((int16)RN * (int16)RM);
2221 gpu_acc = (int32)res;
2226 static void gpu_opcode_neg(void)
2230 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);
2233 SET_ZNC_SUB(0, RN, res);
2237 WriteLog("[NCZ:%u%u%u, R%02u=%08X]\n", gpu_flag_n, gpu_flag_c, gpu_flag_z, IMM_2, RN);
2241 static void gpu_opcode_shlq(void)
2245 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);
2247 // Was a bug here...
2248 // (Look at Aaron's code: If r1 = 32, then 32 - 32 = 0 which is wrong!)
2249 int32 r1 = 32 - IMM_1;
2250 uint32 res = RN << r1;
2251 SET_ZN(res); gpu_flag_c = (RN >> 31) & 1;
2255 WriteLog("[NCZ:%u%u%u, R%02u=%08X]\n", gpu_flag_n, gpu_flag_c, gpu_flag_z, IMM_2, RN);
2259 static void gpu_opcode_shrq(void)
2263 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);
2265 int32 r1 = gpu_convert_zero[IMM_1];
2266 uint32 res = RN >> r1;
2267 SET_ZN(res); gpu_flag_c = RN & 1;
2271 WriteLog("[NCZ:%u%u%u, R%02u=%08X]\n", gpu_flag_n, gpu_flag_c, gpu_flag_z, IMM_2, RN);
2275 static void gpu_opcode_ror(void)
2279 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);
2281 uint32 r1 = RM & 0x1F;
2282 uint32 res = (RN >> r1) | (RN << (32 - r1));
2283 SET_ZN(res); gpu_flag_c = (RN >> 31) & 1;
2287 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);
2291 static void gpu_opcode_rorq(void)
2295 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);
2297 uint32 r1 = gpu_convert_zero[IMM_1 & 0x1F];
2299 uint32 res = (r2 >> r1) | (r2 << (32 - r1));
2301 SET_ZN(res); gpu_flag_c = (r2 >> 31) & 0x01;
2304 WriteLog("[NCZ:%u%u%u, R%02u=%08X]\n", gpu_flag_n, gpu_flag_c, gpu_flag_z, IMM_2, RN);
2308 static void gpu_opcode_sha(void)
2310 /* int dreg = jaguar.op & 31;
2311 int32 r1 = (int32)jaguar.r[(jaguar.op >> 5) & 31];
2312 uint32 r2 = jaguar.r[dreg];
2318 res = (r1 <= -32) ? 0 : (r2 << -r1);
2319 jaguar.FLAGS |= (r2 >> 30) & 2;
2323 res = (r1 >= 32) ? ((int32)r2 >> 31) : ((int32)r2 >> r1);
2324 jaguar.FLAGS |= (r2 << 1) & 2;
2326 jaguar.r[dreg] = res;
2331 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);
2337 res = ((int32)RM <= -32) ? 0 : (RN << -(int32)RM);
2338 gpu_flag_c = RN >> 31;
2342 res = ((int32)RM >= 32) ? ((int32)RN >> 31) : ((int32)RN >> (int32)RM);
2343 gpu_flag_c = RN & 0x01;
2349 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);
2352 /* int32 sRM=(int32)RM;
2358 if (shift>=32) shift=32;
2359 gpu_flag_c=(_RN&0x80000000)>>31;
2369 if (shift>=32) shift=32;
2373 _RN=((int32)_RN)>>1;
2382 static void gpu_opcode_sharq(void)
2384 #ifdef GPU_DIS_SHARQ
2386 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);
2388 uint32 res = (int32)RN >> gpu_convert_zero[IMM_1];
2389 SET_ZN(res); gpu_flag_c = RN & 0x01;
2391 #ifdef GPU_DIS_SHARQ
2393 WriteLog("[NCZ:%u%u%u, R%02u=%08X]\n", gpu_flag_n, gpu_flag_c, gpu_flag_z, IMM_2, RN);
2397 static void gpu_opcode_sh(void)
2401 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);
2403 if (RM & 0x80000000) // Shift left
2405 gpu_flag_c = RN >> 31;
2406 RN = ((int32)RM <= -32 ? 0 : RN << -(int32)RM);
2410 gpu_flag_c = RN & 0x01;
2411 RN = (RM >= 32 ? 0 : RN >> RM);
2416 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);
2420 //Temporary: Testing only!
2421 //#include "gpu2.cpp"
2422 //#include "gpu3.cpp"