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 // (C) 2010 Underground Software
11 // JLH = James L. Hammons <jlhamm@acm.org>
14 // --- ---------- -------------------------------------------------------------
15 // JLH 01/16/2010 Created this log ;-)
18 // Note: Endian wrongness probably stems from the MAME origins of this emu and
19 // the braindead way in which MAME handles memory. :-)
21 // Problem with not booting the BIOS was the incorrect way that the
22 // SUBC instruction set the carry when the carry was set going in...
23 // Same problem with ADDC...
29 #include <string.h> // For memset
40 // For GPU dissasembly...
60 #define GPU_DIS_LOAD14I
61 #define GPU_DIS_LOAD14R
62 #define GPU_DIS_LOAD15I
63 #define GPU_DIS_LOAD15R
65 #define GPU_DIS_MOVEFA
67 #define GPU_DIS_MOVEPC
68 #define GPU_DIS_MOVETA
85 #define GPU_DIS_STOREB
86 #define GPU_DIS_STOREW
87 #define GPU_DIS_STORE14I
88 #define GPU_DIS_STORE14R
89 #define GPU_DIS_STORE15I
90 #define GPU_DIS_STORE15R
97 bool doGPUDis = false;
98 //bool doGPUDis = true;
101 GPU opcodes use (BIOS flying ATARI logo):
143 #define CINT0FLAG 0x0200
144 #define CINT1FLAG 0x0400
145 #define CINT2FLAG 0x0800
146 #define CINT3FLAG 0x1000
147 #define CINT4FLAG 0x2000
148 #define CINT04FLAGS (CINT0FLAG | CINT1FLAG | CINT2FLAG | CINT3FLAG | CINT4FLAG)
152 #define ZERO_FLAG 0x0001
153 #define CARRY_FLAG 0x0002
154 #define NEGA_FLAG 0x0004
156 #define INT_ENA0 0x0010
157 #define INT_ENA1 0x0020
158 #define INT_ENA2 0x0040
159 #define INT_ENA3 0x0080
160 #define INT_ENA4 0x0100
161 #define INT_CLR0 0x0200
162 #define INT_CLR1 0x0400
163 #define INT_CLR2 0x0800
164 #define INT_CLR3 0x1000
165 #define INT_CLR4 0x2000
166 #define REGPAGE 0x4000
169 // External global variables
171 extern int start_logging;
172 extern int gpu_start_log;
174 // Private function prototypes
176 void GPUUpdateRegisterBanks(void);
177 void GPUDumpDisassembly(void);
178 void GPUDumpRegisters(void);
179 void GPUDumpMemory(void);
181 static void gpu_opcode_add(void);
182 static void gpu_opcode_addc(void);
183 static void gpu_opcode_addq(void);
184 static void gpu_opcode_addqt(void);
185 static void gpu_opcode_sub(void);
186 static void gpu_opcode_subc(void);
187 static void gpu_opcode_subq(void);
188 static void gpu_opcode_subqt(void);
189 static void gpu_opcode_neg(void);
190 static void gpu_opcode_and(void);
191 static void gpu_opcode_or(void);
192 static void gpu_opcode_xor(void);
193 static void gpu_opcode_not(void);
194 static void gpu_opcode_btst(void);
195 static void gpu_opcode_bset(void);
196 static void gpu_opcode_bclr(void);
197 static void gpu_opcode_mult(void);
198 static void gpu_opcode_imult(void);
199 static void gpu_opcode_imultn(void);
200 static void gpu_opcode_resmac(void);
201 static void gpu_opcode_imacn(void);
202 static void gpu_opcode_div(void);
203 static void gpu_opcode_abs(void);
204 static void gpu_opcode_sh(void);
205 static void gpu_opcode_shlq(void);
206 static void gpu_opcode_shrq(void);
207 static void gpu_opcode_sha(void);
208 static void gpu_opcode_sharq(void);
209 static void gpu_opcode_ror(void);
210 static void gpu_opcode_rorq(void);
211 static void gpu_opcode_cmp(void);
212 static void gpu_opcode_cmpq(void);
213 static void gpu_opcode_sat8(void);
214 static void gpu_opcode_sat16(void);
215 static void gpu_opcode_move(void);
216 static void gpu_opcode_moveq(void);
217 static void gpu_opcode_moveta(void);
218 static void gpu_opcode_movefa(void);
219 static void gpu_opcode_movei(void);
220 static void gpu_opcode_loadb(void);
221 static void gpu_opcode_loadw(void);
222 static void gpu_opcode_load(void);
223 static void gpu_opcode_loadp(void);
224 static void gpu_opcode_load_r14_indexed(void);
225 static void gpu_opcode_load_r15_indexed(void);
226 static void gpu_opcode_storeb(void);
227 static void gpu_opcode_storew(void);
228 static void gpu_opcode_store(void);
229 static void gpu_opcode_storep(void);
230 static void gpu_opcode_store_r14_indexed(void);
231 static void gpu_opcode_store_r15_indexed(void);
232 static void gpu_opcode_move_pc(void);
233 static void gpu_opcode_jump(void);
234 static void gpu_opcode_jr(void);
235 static void gpu_opcode_mmult(void);
236 static void gpu_opcode_mtoi(void);
237 static void gpu_opcode_normi(void);
238 static void gpu_opcode_nop(void);
239 static void gpu_opcode_load_r14_ri(void);
240 static void gpu_opcode_load_r15_ri(void);
241 static void gpu_opcode_store_r14_ri(void);
242 static void gpu_opcode_store_r15_ri(void);
243 static void gpu_opcode_sat24(void);
244 static void gpu_opcode_pack(void);
246 // This is wrong, since it doesn't take pipeline effects into account. !!! FIX !!!
247 /*uint8 gpu_opcode_cycles[64] =
249 3, 3, 3, 3, 3, 3, 3, 3,
250 3, 3, 3, 3, 3, 3, 3, 3,
251 3, 3, 1, 3, 1, 18, 3, 3,
252 3, 3, 3, 3, 3, 3, 3, 3,
253 3, 3, 2, 2, 2, 2, 3, 4,
254 5, 4, 5, 6, 6, 1, 1, 1,
255 1, 2, 2, 2, 1, 1, 9, 3,
256 3, 1, 6, 6, 2, 2, 3, 3
258 //Here's a QnD kludge...
259 //This is wrong, wrong, WRONG, but it seems to work for the time being...
260 //(That is, it fixes Flip Out which relies on GPU timing rather than semaphores. Bad developers! Bad!)
261 //What's needed here is a way to take pipeline effects into account (including pipeline stalls!)...
262 /*uint8 gpu_opcode_cycles[64] =
264 1, 1, 1, 1, 1, 1, 1, 1,
265 1, 1, 1, 1, 1, 1, 1, 1,
266 1, 1, 1, 1, 1, 9, 1, 1,
267 1, 1, 1, 1, 1, 1, 1, 1,
268 1, 1, 1, 1, 1, 1, 1, 2,
269 2, 2, 2, 3, 3, 1, 1, 1,
270 1, 1, 1, 1, 1, 1, 4, 1,
271 1, 1, 3, 3, 1, 1, 1, 1
273 uint8 gpu_opcode_cycles[64] =
275 1, 1, 1, 1, 1, 1, 1, 1,
276 1, 1, 1, 1, 1, 1, 1, 1,
277 1, 1, 1, 1, 1, 1, 1, 1,
278 1, 1, 1, 1, 1, 1, 1, 1,
279 1, 1, 1, 1, 1, 1, 1, 1,
280 1, 1, 1, 1, 1, 1, 1, 1,
281 1, 1, 1, 1, 1, 1, 1, 1,
282 1, 1, 1, 1, 1, 1, 1, 1
285 void (*gpu_opcode[64])()=
287 gpu_opcode_add, gpu_opcode_addc, gpu_opcode_addq, gpu_opcode_addqt,
288 gpu_opcode_sub, gpu_opcode_subc, gpu_opcode_subq, gpu_opcode_subqt,
289 gpu_opcode_neg, gpu_opcode_and, gpu_opcode_or, gpu_opcode_xor,
290 gpu_opcode_not, gpu_opcode_btst, gpu_opcode_bset, gpu_opcode_bclr,
291 gpu_opcode_mult, gpu_opcode_imult, gpu_opcode_imultn, gpu_opcode_resmac,
292 gpu_opcode_imacn, gpu_opcode_div, gpu_opcode_abs, gpu_opcode_sh,
293 gpu_opcode_shlq, gpu_opcode_shrq, gpu_opcode_sha, gpu_opcode_sharq,
294 gpu_opcode_ror, gpu_opcode_rorq, gpu_opcode_cmp, gpu_opcode_cmpq,
295 gpu_opcode_sat8, gpu_opcode_sat16, gpu_opcode_move, gpu_opcode_moveq,
296 gpu_opcode_moveta, gpu_opcode_movefa, gpu_opcode_movei, gpu_opcode_loadb,
297 gpu_opcode_loadw, gpu_opcode_load, gpu_opcode_loadp, gpu_opcode_load_r14_indexed,
298 gpu_opcode_load_r15_indexed, gpu_opcode_storeb, gpu_opcode_storew, gpu_opcode_store,
299 gpu_opcode_storep, gpu_opcode_store_r14_indexed, gpu_opcode_store_r15_indexed, gpu_opcode_move_pc,
300 gpu_opcode_jump, gpu_opcode_jr, gpu_opcode_mmult, gpu_opcode_mtoi,
301 gpu_opcode_normi, gpu_opcode_nop, gpu_opcode_load_r14_ri, gpu_opcode_load_r15_ri,
302 gpu_opcode_store_r14_ri, gpu_opcode_store_r15_ri, gpu_opcode_sat24, gpu_opcode_pack,
305 static uint8 gpu_ram_8[0x1000];
307 static uint32 gpu_acc;
308 static uint32 gpu_remain;
309 static uint32 gpu_hidata;
310 static uint32 gpu_flags;
311 static uint32 gpu_matrix_control;
312 static uint32 gpu_pointer_to_matrix;
313 static uint32 gpu_data_organization;
314 static uint32 gpu_control;
315 static uint32 gpu_div_control;
316 // There is a distinct advantage to having these separated out--there's no need to clear
317 // a bit before writing a result. I.e., if the result of an operation leaves a zero in
318 // the carry flag, you don't have to zero gpu_flag_c before you can write that zero!
319 static uint8 gpu_flag_z, gpu_flag_n, gpu_flag_c;
320 static uint32 gpu_reg_bank_0[32];
321 static uint32 gpu_reg_bank_1[32];
322 static uint32 * gpu_reg;
323 static uint32 * gpu_alternate_reg;
325 static uint32 gpu_instruction;
326 static uint32 gpu_opcode_first_parameter;
327 static uint32 gpu_opcode_second_parameter;
329 #define GPU_RUNNING (gpu_control & 0x01)
331 #define RM gpu_reg[gpu_opcode_first_parameter]
332 #define RN gpu_reg[gpu_opcode_second_parameter]
333 #define ALTERNATE_RM gpu_alternate_reg[gpu_opcode_first_parameter]
334 #define ALTERNATE_RN gpu_alternate_reg[gpu_opcode_second_parameter]
335 #define IMM_1 gpu_opcode_first_parameter
336 #define IMM_2 gpu_opcode_second_parameter
338 #define SET_FLAG_Z(r) (gpu_flag_z = ((r) == 0));
339 #define SET_FLAG_N(r) (gpu_flag_n = (((uint32)(r) >> 31) & 0x01));
341 #define RESET_FLAG_Z() gpu_flag_z = 0;
342 #define RESET_FLAG_N() gpu_flag_n = 0;
343 #define RESET_FLAG_C() gpu_flag_c = 0;
345 #define CLR_Z (gpu_flag_z = 0)
346 #define CLR_ZN (gpu_flag_z = gpu_flag_n = 0)
347 #define CLR_ZNC (gpu_flag_z = gpu_flag_n = gpu_flag_c = 0)
348 #define SET_Z(r) (gpu_flag_z = ((r) == 0))
349 #define SET_N(r) (gpu_flag_n = (((uint32)(r) >> 31) & 0x01))
350 #define SET_C_ADD(a,b) (gpu_flag_c = ((uint32)(b) > (uint32)(~(a))))
351 #define SET_C_SUB(a,b) (gpu_flag_c = ((uint32)(b) > (uint32)(a)))
352 #define SET_ZN(r) SET_N(r); SET_Z(r)
353 #define SET_ZNC_ADD(a,b,r) SET_N(r); SET_Z(r); SET_C_ADD(a,b)
354 #define SET_ZNC_SUB(a,b,r) SET_N(r); SET_Z(r); SET_C_SUB(a,b)
356 uint32 gpu_convert_zero[32] =
357 { 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 };
359 uint8 * branch_condition_table = 0;
360 #define BRANCH_CONDITION(x) branch_condition_table[(x) + ((jaguar_flags & 7) << 5)]
362 uint32 gpu_opcode_use[64];
364 const char * gpu_opcode_str[64]=
366 "add", "addc", "addq", "addqt",
367 "sub", "subc", "subq", "subqt",
368 "neg", "and", "or", "xor",
369 "not", "btst", "bset", "bclr",
370 "mult", "imult", "imultn", "resmac",
371 "imacn", "div", "abs", "sh",
372 "shlq", "shrq", "sha", "sharq",
373 "ror", "rorq", "cmp", "cmpq",
374 "sat8", "sat16", "move", "moveq",
375 "moveta", "movefa", "movei", "loadb",
376 "loadw", "load", "loadp", "load_r14_indexed",
377 "load_r15_indexed", "storeb", "storew", "store",
378 "storep", "store_r14_indexed","store_r15_indexed","move_pc",
379 "jump", "jr", "mmult", "mtoi",
380 "normi", "nop", "load_r14_ri", "load_r15_ri",
381 "store_r14_ri", "store_r15_ri", "sat24", "pack",
384 static uint32 gpu_in_exec = 0;
385 static uint32 gpu_releaseTimeSlice_flag = 0;
387 void GPUReleaseTimeslice(void)
389 gpu_releaseTimeSlice_flag = 1;
392 uint32 GPUGetPC(void)
397 void build_branch_condition_table(void)
399 if (!branch_condition_table)
401 branch_condition_table = (uint8 *)malloc(32 * 8 * sizeof(branch_condition_table[0]));
403 if (branch_condition_table)
405 for(int i=0; i<8; i++)
407 for(int j=0; j<32; j++)
414 if (!(i & ZERO_FLAG))
417 if (i & (CARRY_FLAG << (j >> 4)))
420 if (!(i & (CARRY_FLAG << (j >> 4))))
422 branch_condition_table[i * 32 + j] = result;
430 // GPU byte access (read)
432 uint8 GPUReadByte(uint32 offset, uint32 who/*=UNKNOWN*/)
434 if (offset >= 0xF02000 && offset <= 0xF020FF)
435 WriteLog("GPU: ReadByte--Attempt to read from GPU register file by %s!\n", whoName[who]);
437 if ((offset >= GPU_WORK_RAM_BASE) && (offset < GPU_WORK_RAM_BASE+0x1000))
438 return gpu_ram_8[offset & 0xFFF];
439 else if ((offset >= GPU_CONTROL_RAM_BASE) && (offset < GPU_CONTROL_RAM_BASE+0x20))
441 uint32 data = GPUReadLong(offset & 0xFFFFFFFC, who);
443 if ((offset & 0x03) == 0)
445 else if ((offset & 0x03) == 1)
446 return (data >> 16) & 0xFF;
447 else if ((offset & 0x03) == 2)
448 return (data >> 8) & 0xFF;
449 else if ((offset & 0x03) == 3)
453 return JaguarReadByte(offset, who);
457 // GPU word access (read)
459 uint16 GPUReadWord(uint32 offset, uint32 who/*=UNKNOWN*/)
461 if (offset >= 0xF02000 && offset <= 0xF020FF)
462 WriteLog("GPU: ReadWord--Attempt to read from GPU register file by %s!\n", whoName[who]);
464 if ((offset >= GPU_WORK_RAM_BASE) && (offset < GPU_WORK_RAM_BASE+0x1000))
467 uint16 data = ((uint16)gpu_ram_8[offset] << 8) | (uint16)gpu_ram_8[offset+1];
470 else if ((offset >= GPU_CONTROL_RAM_BASE) && (offset < GPU_CONTROL_RAM_BASE+0x20))
472 // This looks and smells wrong...
473 // But it *might* be OK...
474 if (offset & 0x01) // Catch cases 1 & 3... (unaligned read)
475 return (GPUReadByte(offset, who) << 8) | GPUReadByte(offset+1, who);
477 uint32 data = GPUReadLong(offset & 0xFFFFFFFC, who);
479 if (offset & 0x02) // Cases 0 & 2...
480 return data & 0xFFFF;
485 //TEMP--Mirror of F03000? No. Writes only...
486 //if (offset >= 0xF0B000 && offset <= 0xF0BFFF)
487 //WriteLog("[GPUR16] --> Possible GPU RAM mirror access by %s!", whoName[who]);
489 return JaguarReadWord(offset, who);
493 // GPU dword access (read)
495 uint32 GPUReadLong(uint32 offset, uint32 who/*=UNKNOWN*/)
497 if (offset >= 0xF02000 && offset <= 0xF020FF)
498 WriteLog("GPU: ReadLong--Attempt to read from GPU register file by %s!\n", whoName[who]);
500 // if ((offset >= GPU_WORK_RAM_BASE) && (offset < GPU_WORK_RAM_BASE + 0x1000))
501 if ((offset >= GPU_WORK_RAM_BASE) && (offset <= GPU_WORK_RAM_BASE + 0x0FFC))
504 return ((uint32)gpu_ram_8[offset] << 24) | ((uint32)gpu_ram_8[offset+1] << 16)
505 | ((uint32)gpu_ram_8[offset+2] << 8) | (uint32)gpu_ram_8[offset+3];//*/
506 // return GET32(gpu_ram_8, offset);
508 // else if ((offset >= GPU_CONTROL_RAM_BASE) && (offset < GPU_CONTROL_RAM_BASE+0x20))
509 else if ((offset >= GPU_CONTROL_RAM_BASE) && (offset <= GPU_CONTROL_RAM_BASE + 0x1C))
515 gpu_flag_c = (gpu_flag_c ? 1 : 0);
516 gpu_flag_z = (gpu_flag_z ? 1 : 0);
517 gpu_flag_n = (gpu_flag_n ? 1 : 0);
519 gpu_flags = (gpu_flags & 0xFFFFFFF8) | (gpu_flag_n << 2) | (gpu_flag_c << 1) | gpu_flag_z;
521 return gpu_flags & 0xFFFFC1FF;
523 return gpu_matrix_control;
525 return gpu_pointer_to_matrix;
527 return gpu_data_organization;
536 default: // unaligned long read
538 WriteLog("GPU: Read32--unaligned 32 bit read at %08X by %s.\n", GPU_CONTROL_RAM_BASE + offset, whoName[who]);
543 //TEMP--Mirror of F03000? No. Writes only...
544 //if (offset >= 0xF0B000 && offset <= 0xF0BFFF)
545 // WriteLog("[GPUR32] --> Possible GPU RAM mirror access by %s!\n", whoName[who]);
546 /*if (offset >= 0xF1D000 && offset <= 0xF1DFFF)
547 WriteLog("[GPUR32] --> Reading from Wavetable ROM!\n");//*/
549 return (JaguarReadWord(offset, who) << 16) | JaguarReadWord(offset + 2, who);
553 // GPU byte access (write)
555 void GPUWriteByte(uint32 offset, uint8 data, uint32 who/*=UNKNOWN*/)
557 if (offset >= 0xF02000 && offset <= 0xF020FF)
558 WriteLog("GPU: WriteByte--Attempt to write to GPU register file by %s!\n", whoName[who]);
560 if ((offset >= GPU_WORK_RAM_BASE) && (offset <= GPU_WORK_RAM_BASE + 0x0FFF))
562 gpu_ram_8[offset & 0xFFF] = data;
564 //This is the same stupid worthless code that was in the DSP!!! AARRRGGGGHHHHH!!!!!!
567 m68k_end_timeslice();
568 dsp_releaseTimeslice();
572 else if ((offset >= GPU_CONTROL_RAM_BASE) && (offset <= GPU_CONTROL_RAM_BASE + 0x1F))
574 uint32 reg = offset & 0x1C;
575 int bytenum = offset & 0x03;
577 //This is definitely wrong!
578 if ((reg >= 0x1C) && (reg <= 0x1F))
579 gpu_div_control = (gpu_div_control & (~(0xFF << (bytenum << 3)))) | (data << (bytenum << 3));
582 uint32 old_data = GPUReadLong(offset & 0xFFFFFFC, who);
583 bytenum = 3 - bytenum; // convention motorola !!!
584 old_data = (old_data & (~(0xFF << (bytenum << 3)))) | (data << (bytenum << 3));
585 GPUWriteLong(offset & 0xFFFFFFC, old_data, who);
589 // WriteLog("gpu: writing %.2x at 0x%.8x\n",data,offset);
590 JaguarWriteByte(offset, data, who);
594 // GPU word access (write)
596 void GPUWriteWord(uint32 offset, uint16 data, uint32 who/*=UNKNOWN*/)
598 if (offset >= 0xF02000 && offset <= 0xF020FF)
599 WriteLog("GPU: WriteWord--Attempt to write to GPU register file by %s!\n", whoName[who]);
601 if ((offset >= GPU_WORK_RAM_BASE) && (offset <= GPU_WORK_RAM_BASE + 0x0FFE))
603 gpu_ram_8[offset & 0xFFF] = (data>>8) & 0xFF;
604 gpu_ram_8[(offset+1) & 0xFFF] = data & 0xFF;//*/
606 SET16(gpu_ram_8, offset, data);//*/
608 /*if (offset >= 0xF03214 && offset < 0xF0321F)
609 WriteLog("GPU: Writing WORD (%04X) to GPU RAM (%08X)...\n", data, offset);//*/
612 //This is the same stupid worthless code that was in the DSP!!! AARRRGGGGHHHHH!!!!!!
615 m68k_end_timeslice();
616 dsp_releaseTimeslice();
620 else if ((offset >= GPU_CONTROL_RAM_BASE) && (offset <= GPU_CONTROL_RAM_BASE + 0x1E))
622 if (offset & 0x01) // This is supposed to weed out unaligned writes, but does nothing...
625 WriteLog("GPU: Write16--unaligned write @ %08X [%04X]\n", offset, data);
630 //Dual locations in this range: $1C Divide unit remainder/Divide unit control (R/W)
631 //This just literally sucks.
632 if ((offset & 0x1C) == 0x1C)
634 //This doesn't look right either--handles cases 1, 2, & 3 all the same!
636 gpu_div_control = (gpu_div_control & 0xFFFF0000) | (data & 0xFFFF);
638 gpu_div_control = (gpu_div_control & 0x0000FFFF) | ((data & 0xFFFF) << 16);
642 //WriteLog("[GPU W16:%08X,%04X]", offset, data);
643 uint32 old_data = GPUReadLong(offset & 0xFFFFFFC, who);
645 old_data = (old_data & 0xFFFF0000) | (data & 0xFFFF);
647 old_data = (old_data & 0x0000FFFF) | ((data & 0xFFFF) << 16);
648 GPUWriteLong(offset & 0xFFFFFFC, old_data, who);
652 else if ((offset == GPU_WORK_RAM_BASE + 0x0FFF) || (GPU_CONTROL_RAM_BASE + 0x1F))
655 WriteLog("GPU: Write16--unaligned write @ %08X by %s [%04X]!\n", offset, whoName[who], data);
661 // Have to be careful here--this can cause an infinite loop!
662 JaguarWriteWord(offset, data, who);
666 // GPU dword access (write)
668 void GPUWriteLong(uint32 offset, uint32 data, uint32 who/*=UNKNOWN*/)
670 if (offset >= 0xF02000 && offset <= 0xF020FF)
671 WriteLog("GPU: WriteLong--Attempt to write to GPU register file by %s!\n", whoName[who]);
673 // if ((offset >= GPU_WORK_RAM_BASE) && (offset < GPU_WORK_RAM_BASE + 0x1000))
674 if ((offset >= GPU_WORK_RAM_BASE) && (offset <= GPU_WORK_RAM_BASE + 0x0FFC))
679 WriteLog("GPU: Write32--unaligned write @ %08X [%08X] by %s\n", offset, data, whoName[who]);
685 SET32(gpu_ram_8, offset, data);
688 // else if ((offset >= GPU_CONTROL_RAM_BASE) && (offset < GPU_CONTROL_RAM_BASE+0x20))
689 else if ((offset >= GPU_CONTROL_RAM_BASE) && (offset <= GPU_CONTROL_RAM_BASE + 0x1C))
696 bool IMASKCleared = (gpu_flags & IMASK) && !(data & IMASK);
698 gpu_flag_z = gpu_flags & ZERO_FLAG;
699 gpu_flag_c = (gpu_flags & CARRY_FLAG) >> 1;
700 gpu_flag_n = (gpu_flags & NEGA_FLAG) >> 2;
701 GPUUpdateRegisterBanks();
702 gpu_control &= ~((gpu_flags & CINT04FLAGS) >> 3); // Interrupt latch clear bits
703 //Writing here is only an interrupt enable--this approach is just plain wrong!
705 //This, however, is A-OK! ;-)
706 if (IMASKCleared) // If IMASK was cleared,
707 GPUHandleIRQs(); // see if any other interrupts need servicing!
709 if (gpu_flags & (INT_ENA0 | INT_ENA1 | INT_ENA2 | INT_ENA3 | INT_ENA4))
710 WriteLog("GPU: Interrupt enable set by %s! Bits: %02X\n", whoName[who], (gpu_flags >> 4) & 0x1F);
711 WriteLog("GPU: REGPAGE %s...\n", (gpu_flags & REGPAGE ? "set" : "cleared"));
716 gpu_matrix_control = data;
719 // This can only point to long aligned addresses
720 gpu_pointer_to_matrix = data & 0xFFFFFFFC;
723 gpu_data_organization = data;
728 WriteLog("GPU: %s setting GPU PC to %08X %s\n", whoName[who], gpu_pc, (GPU_RUNNING ? "(GPU is RUNNING!)" : ""));//*/
733 // uint32 gpu_was_running = GPU_RUNNING;
734 data &= ~0xF7C0; // Disable writes to INT_LAT0-4 & TOM version number
736 // check for GPU -> CPU interrupt
739 //WriteLog("GPU->CPU interrupt\n");
740 if (TOMIRQEnabled(IRQ_GPU))
742 //This is the programmer's responsibility, to make sure the handler is valid, not ours!
743 // if ((TOMIRQEnabled(IRQ_GPU))// && (JaguarInterruptHandlerIsValid(64)))
745 TOMSetPendingGPUInt();
746 m68k_set_irq(2); // Set 68000 IPL 2
747 GPUReleaseTimeslice();
753 // check for CPU -> GPU interrupt #0
756 //WriteLog("CPU->GPU interrupt\n");
757 GPUSetIRQLine(0, ASSERT_LINE);
758 m68k_end_timeslice();
759 DSPReleaseTimeslice();
766 //WriteLog("asked to perform a single step (single step is %senabled)\n",(data&0x8)?"":"not ");
768 gpu_control = (gpu_control & 0xF7C0) | (data & (~0xF7C0));
770 // if gpu wasn't running but is now running, execute a few cycles
771 #ifndef GPU_SINGLE_STEPPING
772 /* if (!gpu_was_running && GPU_RUNNING)
775 WriteLog("GPU: Write32--About to do stupid braindead GPU execution for 200 cycles.\n");
780 #endif // GPU_DEBUG//*/
782 if (gpu_control & 0x18)
784 #endif // #ifndef GPU_SINGLE_STEPPING
786 WriteLog("Write to GPU CTRL by %s: %08X ", whoName[who], data);
788 WriteLog(" --> Starting to run at %08X by %s...", gpu_pc, whoName[who]);
790 WriteLog(" --> Stopped by %s! (GPU_PC: %08X)", whoName[who], gpu_pc);
794 // GPUDumpDisassembly();
797 if (gpu_pc == 0xF035D8)
799 // GPUDumpDisassembly();
802 gpu_control &= 0xFFFFFFFE; // Don't run it and let's see what happens!
803 //Hmm. Seems to lock up when going into the demo...
804 //Try to disable the collision altogether!
807 extern int effect_start5;
808 static bool finished = false;
809 //if (GPU_RUNNING && effect_start5 && !finished)
810 if (GPU_RUNNING && effect_start5 && gpu_pc == 0xF035D8)
812 // Let's do a dump of $6528!
813 /* uint32 numItems = JaguarReadWord(0x6BD6);
814 WriteLog("\nDump of $6528: %u items.\n\n", numItems);
815 for(int i=0; i<numItems*3*4; i+=3*4)
817 WriteLog("\t%04X: %08X %08X %08X -> ", 0x6528+i, JaguarReadLong(0x6528+i),
818 JaguarReadLong(0x6528+i+4), JaguarReadLong(0x6528+i+8));
819 uint16 link = JaguarReadWord(0x6528+i+8+2);
820 for(int j=0; j<40; j+=4)
821 WriteLog("%08X ", JaguarReadLong(link + j));
825 // Let's try a manual blit here...
826 //This isn't working the way it should! !!! FIX !!!
827 //Err, actually, it is.
828 // NOW, it works right! Problem solved!!! It's a blitter bug!
829 /* uint32 src = 0x4D54, dst = 0xF03000, width = 10 * 4;
830 for(int y=0; y<127; y++)
832 for(int x=0; x<2; x++)
834 JaguarWriteLong(dst, JaguarReadLong(src));
839 src += width - (2 * 4);
843 WriteLog("\nGPU: About to execute collision detection code.\n\n");//*/
845 /* WriteLog("\nGPU: About to execute collision detection code. Data @ 4D54:\n\n");
847 for(int i=0x004D54; i<0x004D54+2048; i++)
849 WriteLog("%02X ", JaguarReadByte(i));
857 WriteLog("\n\nData @ F03000:\n\n");
859 for(int i=0xF03000; i<0xF03200; i++)
861 WriteLog("%02X ", JaguarReadByte(i));
875 /*if (!GPU_RUNNING && finished)
877 WriteLog("\nGPU: Finished collision detection code. Exiting!\n\n");
882 // (?) If we're set running by the M68K (or DSP?) then end its timeslice to
883 // allow the GPU a chance to run...
884 // Yes! This partially fixed Trevor McFur...
886 m68k_end_timeslice();
893 gpu_div_control = data;
895 // default: // unaligned long write
902 // JaguarWriteWord(offset, (data >> 16) & 0xFFFF, who);
903 // JaguarWriteWord(offset+2, data & 0xFFFF, who);
904 // We're a 32-bit processor, we can do a long write...!
905 JaguarWriteLong(offset, data, who);
909 // Change register banks if necessary
911 void GPUUpdateRegisterBanks(void)
913 int bank = (gpu_flags & REGPAGE); // REGPAGE bit
915 if (gpu_flags & IMASK) // IMASK bit
916 bank = 0; // IMASK forces main bank to be bank 0
919 gpu_reg = gpu_reg_bank_1, gpu_alternate_reg = gpu_reg_bank_0;
921 gpu_reg = gpu_reg_bank_0, gpu_alternate_reg = gpu_reg_bank_1;
924 void GPUHandleIRQs(void)
926 // Bail out if we're already in an interrupt!
927 if (gpu_flags & IMASK)
930 // Get the interrupt latch & enable bits
931 uint32 bits = (gpu_control >> 6) & 0x1F, mask = (gpu_flags >> 4) & 0x1F;
933 // Bail out if latched interrupts aren't enabled
938 // Determine which interrupt to service
939 uint32 which = 0; //Isn't there a #pragma to disable this warning???
952 WriteLog("GPU: Generating IRQ #%i\n", which);
954 // set the interrupt flag
956 GPUUpdateRegisterBanks();
958 // subqt #4,r31 ; pre-decrement stack pointer
959 // move pc,r30 ; address of interrupted code
960 // store r30,(r31) ; store return address
962 GPUWriteLong(gpu_reg[31], gpu_pc - 2, GPU);
964 // movei #service_address,r30 ; pointer to ISR entry
965 // jump (r30) ; jump to ISR
967 gpu_pc = gpu_reg[30] = GPU_WORK_RAM_BASE + (which * 0x10);
970 void GPUSetIRQLine(int irqline, int state)
973 WriteLog("GPU: Setting GPU IRQ line #%i\n", irqline);
975 uint32 mask = 0x0040 << irqline;
976 gpu_control &= ~mask; // Clear the interrupt latch
980 gpu_control |= mask; // Assert the interrupt latch
981 GPUHandleIRQs(); // And handle the interrupt...
985 //TEMPORARY: Testing only!
991 // memory_malloc_secure((void **)&gpu_ram_8, 0x1000, "GPU work RAM");
992 // memory_malloc_secure((void **)&gpu_reg_bank_0, 32 * sizeof(int32), "GPU bank 0 regs");
993 // memory_malloc_secure((void **)&gpu_reg_bank_1, 32 * sizeof(int32), "GPU bank 1 regs");
995 build_branch_condition_table();
999 //TEMPORARY: Testing only!
1006 // GPU registers (directly visible)
1007 gpu_flags = 0x00000000;
1008 gpu_matrix_control = 0x00000000;
1009 gpu_pointer_to_matrix = 0x00000000;
1010 gpu_data_organization = 0xFFFFFFFF;
1011 gpu_pc = 0x00F03000;
1012 gpu_control = 0x00002800; // Correctly sets this as TOM Rev. 2
1013 gpu_hidata = 0x00000000;
1014 gpu_remain = 0x00000000; // These two registers are RO/WO
1015 gpu_div_control = 0x00000000;
1017 // GPU internal register
1018 gpu_acc = 0x00000000;
1020 gpu_reg = gpu_reg_bank_0;
1021 gpu_alternate_reg = gpu_reg_bank_1;
1023 for(int i=0; i<32; i++)
1024 gpu_reg[i] = gpu_alternate_reg[i] = 0x00000000;
1027 memset(gpu_ram_8, 0xFF, 0x1000);
1029 //not needed GPUInterruptPending = false;
1033 uint32 GPUReadPC(void)
1038 void GPUResetStats(void)
1040 for(uint32 i=0; i<64; i++)
1041 gpu_opcode_use[i] = 0;
1042 WriteLog("--> GPU stats were reset!\n");
1045 void GPUDumpDisassembly(void)
1049 WriteLog("\n---[GPU code at 00F03000]---------------------------\n");
1050 uint32 j = 0xF03000;
1051 while (j <= 0xF03FFF)
1054 j += dasmjag(JAGUAR_GPU, buffer, j);
1055 WriteLog("\t%08X: %s\n", oldj, buffer);
1059 void GPUDumpRegisters(void)
1061 WriteLog("\n---[GPU flags: NCZ %d%d%d]-----------------------\n", gpu_flag_n, gpu_flag_c, gpu_flag_z);
1062 WriteLog("\nRegisters bank 0\n");
1063 for(int j=0; j<8; j++)
1065 WriteLog("\tR%02i = %08X R%02i = %08X R%02i = %08X R%02i = %08X\n",
1066 (j << 2) + 0, gpu_reg_bank_0[(j << 2) + 0],
1067 (j << 2) + 1, gpu_reg_bank_0[(j << 2) + 1],
1068 (j << 2) + 2, gpu_reg_bank_0[(j << 2) + 2],
1069 (j << 2) + 3, gpu_reg_bank_0[(j << 2) + 3]);
1071 WriteLog("Registers bank 1\n");
1072 for(int j=0; j<8; j++)
1074 WriteLog("\tR%02i = %08X R%02i = %08X R%02i = %08X R%02i = %08X\n",
1075 (j << 2) + 0, gpu_reg_bank_1[(j << 2) + 0],
1076 (j << 2) + 1, gpu_reg_bank_1[(j << 2) + 1],
1077 (j << 2) + 2, gpu_reg_bank_1[(j << 2) + 2],
1078 (j << 2) + 3, gpu_reg_bank_1[(j << 2) + 3]);
1082 void GPUDumpMemory(void)
1084 WriteLog("\n---[GPU data at 00F03000]---------------------------\n");
1085 for(int i=0; i<0xFFF; i+=4)
1086 WriteLog("\t%08X: %02X %02X %02X %02X\n", 0xF03000+i, gpu_ram_8[i],
1087 gpu_ram_8[i+1], gpu_ram_8[i+2], gpu_ram_8[i+3]);
1092 WriteLog("GPU: Stopped at PC=%08X (GPU %s running)\n", (unsigned int)gpu_pc, GPU_RUNNING ? "was" : "wasn't");
1094 // Get the interrupt latch & enable bits
1095 uint8 bits = (gpu_control >> 6) & 0x1F, mask = (gpu_flags >> 4) & 0x1F;
1096 WriteLog("GPU: Latch bits = %02X, enable bits = %02X\n", bits, mask);
1099 GPUDumpDisassembly();
1101 WriteLog("\nGPU opcodes use:\n");
1102 for(int i=0; i<64; i++)
1104 if (gpu_opcode_use[i])
1105 WriteLog("\t%17s %lu\n", gpu_opcode_str[i], gpu_opcode_use[i]);
1109 // memory_free(gpu_ram_8);
1110 // memory_free(gpu_reg_bank_0);
1111 // memory_free(gpu_reg_bank_1);
1115 // Main GPU execution core
1117 static int testCount = 1;
1119 static bool tripwire = false;
1120 void GPUExec(int32 cycles)
1125 #ifdef GPU_SINGLE_STEPPING
1126 if (gpu_control & 0x18)
1129 gpu_control &= ~0x10;
1133 gpu_releaseTimeSlice_flag = 0;
1136 while (cycles > 0 && GPU_RUNNING)
1138 if (gpu_ram_8[0x054] == 0x98 && gpu_ram_8[0x055] == 0x0A && gpu_ram_8[0x056] == 0x03
1139 && gpu_ram_8[0x057] == 0x00 && gpu_ram_8[0x058] == 0x00 && gpu_ram_8[0x059] == 0x00)
1141 if (gpu_pc == 0xF03000)
1143 extern uint32 starCount;
1145 /* WriteLog("GPU: Starting starfield generator... Dump of [R03=%08X]:\n", gpu_reg_bank_0[03]);
1146 uint32 base = gpu_reg_bank_0[3];
1147 for(uint32 i=0; i<0x100; i+=16)
1149 WriteLog("%02X: ", i);
1150 for(uint32 j=0; j<16; j++)
1152 WriteLog("%02X ", JaguarReadByte(base + i + j));
1157 // if (gpu_pc == 0xF03)
1161 /*if (gpu_pc == 0xF03B9E && gpu_reg_bank_0[01] == 0)
1164 WriteLog("GPU: Starting disassembly log...\n");
1167 /*if (gpu_pc == 0xF0359A)
1172 /* gpu_flag_c = (gpu_flag_c ? 1 : 0);
1173 gpu_flag_z = (gpu_flag_z ? 1 : 0);
1174 gpu_flag_n = (gpu_flag_n ? 1 : 0);*/
1176 uint16 opcode = GPUReadWord(gpu_pc, GPU);
1177 uint32 index = opcode >> 10;
1178 gpu_instruction = opcode; // Added for GPU #3...
1179 gpu_opcode_first_parameter = (opcode >> 5) & 0x1F;
1180 gpu_opcode_second_parameter = opcode & 0x1F;
1181 /*if (gpu_pc == 0xF03BE8)
1182 WriteLog("Start of OP frame write...\n");
1183 if (gpu_pc == 0xF03EEE)
1184 WriteLog("--> Writing BRANCH object ---\n");
1185 if (gpu_pc == 0xF03F62)
1186 WriteLog("--> Writing BITMAP object ***\n");//*/
1187 /*if (gpu_pc == 0xF03546)
1189 WriteLog("\n--> GPU PC: F03546\n");
1191 GPUDumpDisassembly();
1193 /*if (gpu_pc == 0xF033F6)
1195 WriteLog("\n--> GPU PC: F033F6\n");
1197 GPUDumpDisassembly();
1199 /*if (gpu_pc == 0xF033CC)
1201 WriteLog("\n--> GPU PC: F033CC\n");
1203 GPUDumpDisassembly();
1205 /*if (gpu_pc == 0xF033D6)
1207 WriteLog("\n--> GPU PC: F033D6 (#%d)\n", testCount++);
1211 /*if (gpu_pc == 0xF033D8)
1213 WriteLog("\n--> GPU PC: F033D8 (#%d)\n", testCount++);
1217 /*if (gpu_pc == 0xF0358E)
1219 WriteLog("\n--> GPU PC: F0358E (#%d)\n", testCount++);
1223 /*if (gpu_pc == 0xF034CA)
1225 WriteLog("\n--> GPU PC: F034CA (#%d)\n", testCount++);
1228 /*if (gpu_pc == 0xF034CA)
1230 len = gpu_reg[1] + 4;//, r9save = gpu_reg[9];
1231 WriteLog("\nAbout to subtract [#%d] (R14=%08X, R15=%08X, R9=%08X):\n ", testCount++, gpu_reg[14], gpu_reg[15], gpu_reg[9]);
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));
1239 if (gpu_pc == 0xF034DE)
1241 WriteLog("\nSubtracted! (R14=%08X, R15=%08X):\n ", gpu_reg[14], gpu_reg[15]);
1242 for(int i=0; i<len; i+=4)
1243 WriteLog(" %08X", GPUReadLong(gpu_reg[15]+i));
1245 for(int i=0; i<len; i+=4)
1246 WriteLog(" %08X", GPUReadLong(gpu_reg[14]+i));
1248 for(int i=0; i<len; i+=4)
1249 WriteLog(" --------");
1251 for(int i=0; i<len; i+=4)
1252 WriteLog(" %08X", GPUReadLong(gpu_reg[9]+4+i));
1255 /*if (gpu_pc == 0xF035C8)
1257 WriteLog("\n--> GPU PC: F035C8 (#%d)\n", testCount++);
1259 GPUDumpDisassembly();
1264 // gpu_reset_stats();
1265 static char buffer[512];
1266 dasmjag(JAGUAR_GPU, buffer, gpu_pc);
1267 WriteLog("GPU: [%08X] %s (RM=%08X, RN=%08X) -> ", gpu_pc, buffer, RM, RN);
1269 //$E400 -> 1110 01 -> $39 -> 57
1272 gpu_opcode[index]();
1274 // gpu2_opcode[index]();
1276 //GPU #3 (Doesn't show ATARI logo! #1 & #2 do...)
1278 // gpu3_opcode[index]();
1281 //GPU: [00F03548] jr nz,00F03560 (0xd561) (RM=00F03114, RN=00000004) -> --> JR: Branch taken.
1282 /*static bool firstTime = true;
1283 if (gpu_pc == 0xF03548 && firstTime)
1286 // firstTime = false;
1288 //static char buffer[512];
1290 //while (k<0xF0356C)
1293 //k += dasmjag(JAGUAR_GPU, buffer, k);
1294 //WriteLog("GPU: [%08X] %s\n", oldk, buffer);
1296 // gpu_start_log = 1;
1298 //GPU: [00F0354C] jump nz,(r29) (0xd3a1) (RM=00F03314, RN=00000004) -> (RM=00F03314, RN=00000004)
1299 /*if (gpu_pc == 0xF0354C)
1300 gpu_flag_z = 0;//, gpu_start_log = 1;//*/
1302 cycles -= gpu_opcode_cycles[index];
1303 gpu_opcode_use[index]++;
1305 WriteLog("(RM=%08X, RN=%08X)\n", RM, RN);//*/
1306 if ((gpu_pc < 0xF03000 || gpu_pc > 0xF03FFF) && !tripwire)
1308 WriteLog("GPU: Executing outside local RAM! GPU_PC: %08X\n", gpu_pc);
1321 GPU opcodes use (offset punch--vertically below bad guy):
1343 load_r14_indexed 1183
1344 load_r15_indexed 1125
1347 store_r14_indexed 320
1355 static void gpu_opcode_jump(void)
1358 const char * condition[32] =
1359 { "T", "nz", "z", "???", "nc", "nc nz", "nc z", "???", "c", "c nz",
1360 "c z", "???", "???", "???", "???", "???", "???", "???", "???",
1361 "???", "nn", "nn nz", "nn z", "???", "n", "n nz", "n z", "???",
1362 "???", "???", "???", "F" };
1364 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);
1367 /* gpu_flag_c = (gpu_flag_c ? 1 : 0);
1368 gpu_flag_z = (gpu_flag_z ? 1 : 0);
1369 gpu_flag_n = (gpu_flag_n ? 1 : 0);*/
1370 // KLUDGE: Used by BRANCH_CONDITION
1371 uint32 jaguar_flags = (gpu_flag_n << 2) | (gpu_flag_c << 1) | gpu_flag_z;
1373 if (BRANCH_CONDITION(IMM_2))
1377 WriteLog("Branched!\n");
1380 WriteLog(" --> JUMP: Branch taken.\n");
1381 uint32 delayed_pc = RM;
1383 gpu_pc = delayed_pc;
1384 /* uint16 opcode = GPUReadWord(gpu_pc, GPU);
1385 gpu_opcode_first_parameter = (opcode >> 5) & 0x1F;
1386 gpu_opcode_second_parameter = opcode & 0x1F;
1388 gpu_pc = delayed_pc;
1389 gpu_opcode[opcode>>10]();//*/
1394 WriteLog("Branch NOT taken.\n");
1398 static void gpu_opcode_jr(void)
1401 const char * condition[32] =
1402 { "T", "nz", "z", "???", "nc", "nc nz", "nc z", "???", "c", "c nz",
1403 "c z", "???", "???", "???", "???", "???", "???", "???", "???",
1404 "???", "nn", "nn nz", "nn z", "???", "n", "n nz", "n z", "???",
1405 "???", "???", "???", "F" };
1407 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);
1409 /* if (CONDITION(jaguar.op & 31))
1411 int32 r1 = (INT8)((jaguar.op >> 2) & 0xF8) >> 2;
1412 uint32 newpc = jaguar.PC + r1;
1414 jaguar.op = ROPCODE(jaguar.PC);
1416 (*jaguar.table[jaguar.op >> 10])();
1418 jaguar_icount -= 3; // 3 wait states guaranteed
1421 /* gpu_flag_n = (gpu_flag_n ? 1 : 0);
1422 gpu_flag_c = (gpu_flag_c ? 1 : 0);
1423 gpu_flag_z = (gpu_flag_z ? 1 : 0);*/
1424 // KLUDGE: Used by BRANCH_CONDITION
1425 uint32 jaguar_flags = (gpu_flag_n << 2) | (gpu_flag_c << 1) | gpu_flag_z;
1427 if (BRANCH_CONDITION(IMM_2))
1431 WriteLog("Branched!\n");
1434 WriteLog(" --> JR: Branch taken.\n");
1435 int32 offset = (IMM_1 & 0x10 ? 0xFFFFFFF0 | IMM_1 : IMM_1); // Sign extend IMM_1
1436 int32 delayed_pc = gpu_pc + (offset * 2);
1438 gpu_pc = delayed_pc;
1439 /* uint16 opcode = GPUReadWord(gpu_pc, GPU);
1440 gpu_opcode_first_parameter = (opcode >> 5) & 0x1F;
1441 gpu_opcode_second_parameter = opcode & 0x1F;
1443 gpu_pc = delayed_pc;
1444 gpu_opcode[opcode>>10]();//*/
1449 WriteLog("Branch NOT taken.\n");
1453 static void gpu_opcode_add(void)
1457 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);
1459 uint32 res = RN + RM;
1460 CLR_ZNC; SET_ZNC_ADD(RN, RM, res);
1464 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);
1468 static void gpu_opcode_addc(void)
1472 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);
1474 /* int dreg = jaguar.op & 31;
1475 uint32 r1 = jaguar.r[(jaguar.op >> 5) & 31];
1476 uint32 r2 = jaguar.r[dreg];
1477 uint32 res = r2 + r1 + ((jaguar.FLAGS >> 1) & 1);
1478 jaguar.r[dreg] = res;
1479 CLR_ZNC; SET_ZNC_ADD(r2,r1,res);*/
1481 uint32 res = RN + RM + gpu_flag_c;
1482 uint32 carry = gpu_flag_c;
1483 // SET_ZNC_ADD(RN, RM, res); //???BUG??? Yes!
1484 SET_ZNC_ADD(RN + carry, RM, res);
1485 // SET_ZNC_ADD(RN, RM + carry, res);
1489 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);
1493 static void gpu_opcode_addq(void)
1497 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);
1499 uint32 r1 = gpu_convert_zero[IMM_1];
1500 uint32 res = RN + r1;
1501 CLR_ZNC; SET_ZNC_ADD(RN, r1, res);
1505 WriteLog("[NCZ:%u%u%u, R%02u=%08X]\n", gpu_flag_n, gpu_flag_c, gpu_flag_z, IMM_2, RN);
1509 static void gpu_opcode_addqt(void)
1511 #ifdef GPU_DIS_ADDQT
1513 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);
1515 RN += gpu_convert_zero[IMM_1];
1516 #ifdef GPU_DIS_ADDQT
1518 WriteLog("[NCZ:%u%u%u, R%02u=%08X]\n", gpu_flag_n, gpu_flag_c, gpu_flag_z, IMM_2, RN);
1522 static void gpu_opcode_sub(void)
1526 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);
1528 uint32 res = RN - RM;
1529 SET_ZNC_SUB(RN, RM, res);
1533 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);
1537 static void gpu_opcode_subc(void)
1541 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);
1543 uint32 res = RN - RM - gpu_flag_c;
1544 uint32 borrow = gpu_flag_c;
1545 // SET_ZNC_SUB(RN, RM, res); //???BUG??? YES!!!
1546 //No matter how you do it, there is a problem. With below, it's 0-0 with carry,
1547 //and the one below it it's FFFFFFFF - FFFFFFFF with carry... !!! FIX !!!
1548 // SET_ZNC_SUB(RN - borrow, RM, res);
1549 SET_ZNC_SUB(RN, RM + borrow, res);
1553 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);
1557 N = 5, M = 3, 3 - 5 = -2, C = 1... Or, in our case:
1558 N = 0, M = 1, 0 - 1 = -1, C = 0!
1560 #define SET_C_SUB(a,b) (gpu_flag_c = ((uint32)(b) > (uint32)(a)))
1561 #define SET_ZN(r) SET_N(r); SET_Z(r)
1562 #define SET_ZNC_ADD(a,b,r) SET_N(r); SET_Z(r); SET_C_ADD(a,b)
1563 #define SET_ZNC_SUB(a,b,r) SET_N(r); SET_Z(r); SET_C_SUB(a,b)
1565 static void gpu_opcode_subq(void)
1569 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);
1571 uint32 r1 = gpu_convert_zero[IMM_1];
1572 uint32 res = RN - r1;
1573 SET_ZNC_SUB(RN, r1, res);
1577 WriteLog("[NCZ:%u%u%u, R%02u=%08X]\n", gpu_flag_n, gpu_flag_c, gpu_flag_z, IMM_2, RN);
1581 static void gpu_opcode_subqt(void)
1583 #ifdef GPU_DIS_SUBQT
1585 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);
1587 RN -= gpu_convert_zero[IMM_1];
1588 #ifdef GPU_DIS_SUBQT
1590 WriteLog("[NCZ:%u%u%u, R%02u=%08X]\n", gpu_flag_n, gpu_flag_c, gpu_flag_z, IMM_2, RN);
1594 static void gpu_opcode_cmp(void)
1598 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);
1600 uint32 res = RN - RM;
1601 SET_ZNC_SUB(RN, RM, res);
1604 WriteLog("[NCZ:%u%u%u]\n", gpu_flag_n, gpu_flag_c, gpu_flag_z);
1608 static void gpu_opcode_cmpq(void)
1610 static int32 sqtable[32] =
1611 { 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 };
1614 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);
1616 uint32 r1 = sqtable[IMM_1 & 0x1F]; // I like this better -> (INT8)(jaguar.op >> 2) >> 3;
1617 uint32 res = RN - r1;
1618 SET_ZNC_SUB(RN, r1, res);
1621 WriteLog("[NCZ:%u%u%u]\n", gpu_flag_n, gpu_flag_c, gpu_flag_z);
1625 static void gpu_opcode_and(void)
1629 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);
1635 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);
1639 static void gpu_opcode_or(void)
1643 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);
1649 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);
1653 static void gpu_opcode_xor(void)
1657 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);
1663 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);
1667 static void gpu_opcode_not(void)
1671 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);
1677 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);
1681 static void gpu_opcode_move_pc(void)
1683 #ifdef GPU_DIS_MOVEPC
1685 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);
1687 // Should be previous PC--this might not always be previous instruction!
1688 // Then again, this will point right at the *current* instruction, i.e., MOVE PC,R!
1690 #ifdef GPU_DIS_MOVEPC
1692 WriteLog("[NCZ:%u%u%u, R%02u=%08X]\n", gpu_flag_n, gpu_flag_c, gpu_flag_z, IMM_2, RN);
1696 static void gpu_opcode_sat8(void)
1700 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);
1702 RN = ((int32)RN < 0 ? 0 : (RN > 0xFF ? 0xFF : RN));
1706 WriteLog("[NCZ:%u%u%u, R%02u=%08X]\n", gpu_flag_n, gpu_flag_c, gpu_flag_z, IMM_2, RN);
1710 static void gpu_opcode_sat16(void)
1712 RN = ((int32)RN < 0 ? 0 : (RN > 0xFFFF ? 0xFFFF : RN));
1716 static void gpu_opcode_sat24(void)
1718 RN = ((int32)RN < 0 ? 0 : (RN > 0xFFFFFF ? 0xFFFFFF : RN));
1722 static void gpu_opcode_store_r14_indexed(void)
1724 #ifdef GPU_DIS_STORE14I
1726 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));
1728 GPUWriteLong(gpu_reg[14] + (gpu_convert_zero[IMM_1] << 2), RN, GPU);
1731 static void gpu_opcode_store_r15_indexed(void)
1733 #ifdef GPU_DIS_STORE15I
1735 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));
1737 GPUWriteLong(gpu_reg[15] + (gpu_convert_zero[IMM_1] << 2), RN, GPU);
1740 static void gpu_opcode_load_r14_ri(void)
1742 #ifdef GPU_DIS_LOAD14R
1744 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);
1746 RN = GPUReadLong(gpu_reg[14] + RM, GPU);
1747 #ifdef GPU_DIS_LOAD14R
1749 WriteLog("[NCZ:%u%u%u, R%02u=%08X]\n", gpu_flag_n, gpu_flag_c, gpu_flag_z, IMM_2, RN);
1753 static void gpu_opcode_load_r15_ri(void)
1755 #ifdef GPU_DIS_LOAD15R
1757 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);
1759 RN = GPUReadLong(gpu_reg[15] + RM, GPU);
1760 #ifdef GPU_DIS_LOAD15R
1762 WriteLog("[NCZ:%u%u%u, R%02u=%08X]\n", gpu_flag_n, gpu_flag_c, gpu_flag_z, IMM_2, RN);
1766 static void gpu_opcode_store_r14_ri(void)
1768 #ifdef GPU_DIS_STORE14R
1770 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]);
1772 GPUWriteLong(gpu_reg[14] + RM, RN, GPU);
1775 static void gpu_opcode_store_r15_ri(void)
1777 #ifdef GPU_DIS_STORE15R
1779 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]);
1781 GPUWriteLong(gpu_reg[15] + RM, RN, GPU);
1784 static void gpu_opcode_nop(void)
1788 WriteLog("%06X: NOP [NCZ:%u%u%u]\n", gpu_pc-2, gpu_flag_n, gpu_flag_c, gpu_flag_z);
1792 static void gpu_opcode_pack(void)
1796 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);
1800 //BUG! if (RM == 0) // Pack
1801 if (IMM_1 == 0) // Pack
1802 RN = ((val >> 10) & 0x0000F000) | ((val >> 5) & 0x00000F00) | (val & 0x000000FF);
1804 RN = ((val & 0x0000F000) << 10) | ((val & 0x00000F00) << 5) | (val & 0x000000FF);
1807 WriteLog("[NCZ:%u%u%u, R%02u=%08X]\n", gpu_flag_n, gpu_flag_c, gpu_flag_z, IMM_2, RN);
1811 static void gpu_opcode_storeb(void)
1813 #ifdef GPU_DIS_STOREB
1815 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);
1818 // Would appear to be so...!
1819 if ((RM >= 0xF03000) && (RM <= 0xF03FFF))
1820 GPUWriteLong(RM, RN & 0xFF, GPU);
1822 JaguarWriteByte(RM, RN, GPU);
1825 static void gpu_opcode_storew(void)
1827 #ifdef GPU_DIS_STOREW
1829 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);
1831 if ((RM >= 0xF03000) && (RM <= 0xF03FFF))
1832 GPUWriteLong(RM, RN & 0xFFFF, GPU);
1834 JaguarWriteWord(RM, RN, GPU);
1837 static void gpu_opcode_store(void)
1839 #ifdef GPU_DIS_STORE
1841 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);
1843 GPUWriteLong(RM, RN, GPU);
1846 static void gpu_opcode_storep(void)
1848 GPUWriteLong(RM + 0, gpu_hidata, GPU);
1849 GPUWriteLong(RM + 4, RN, GPU);
1852 static void gpu_opcode_loadb(void)
1854 #ifdef GPU_DIS_LOADB
1856 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);
1858 if ((RM >= 0xF03000) && (RM <= 0xF03FFF))
1859 RN = GPUReadLong(RM, GPU) & 0xFF;
1861 RN = JaguarReadByte(RM, GPU);
1862 #ifdef GPU_DIS_LOADB
1864 WriteLog("[NCZ:%u%u%u, R%02u=%08X]\n", gpu_flag_n, gpu_flag_c, gpu_flag_z, IMM_2, RN);
1868 static void gpu_opcode_loadw(void)
1870 #ifdef GPU_DIS_LOADW
1872 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);
1874 if ((RM >= 0xF03000) && (RM <= 0xF03FFF))
1875 RN = GPUReadLong(RM, GPU) & 0xFFFF;
1877 RN = JaguarReadWord(RM, GPU);
1878 #ifdef GPU_DIS_LOADW
1880 WriteLog("[NCZ:%u%u%u, R%02u=%08X]\n", gpu_flag_n, gpu_flag_c, gpu_flag_z, IMM_2, RN);
1884 static void gpu_opcode_load(void)
1888 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);
1890 RN = GPUReadLong(RM, GPU);
1893 WriteLog("[NCZ:%u%u%u, R%02u=%08X]\n", gpu_flag_n, gpu_flag_c, gpu_flag_z, IMM_2, RN);
1897 static void gpu_opcode_loadp(void)
1899 gpu_hidata = GPUReadLong(RM + 0, GPU);
1900 RN = GPUReadLong(RM + 4, GPU);
1903 static void gpu_opcode_load_r14_indexed(void)
1905 #ifdef GPU_DIS_LOAD14I
1907 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);
1909 RN = GPUReadLong(gpu_reg[14] + (gpu_convert_zero[IMM_1] << 2), GPU);
1910 #ifdef GPU_DIS_LOAD14I
1912 WriteLog("[NCZ:%u%u%u, R%02u=%08X]\n", gpu_flag_n, gpu_flag_c, gpu_flag_z, IMM_2, RN);
1916 static void gpu_opcode_load_r15_indexed(void)
1918 #ifdef GPU_DIS_LOAD15I
1920 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);
1922 RN = GPUReadLong(gpu_reg[15] + (gpu_convert_zero[IMM_1] << 2), GPU);
1923 #ifdef GPU_DIS_LOAD15I
1925 WriteLog("[NCZ:%u%u%u, R%02u=%08X]\n", gpu_flag_n, gpu_flag_c, gpu_flag_z, IMM_2, RN);
1929 static void gpu_opcode_movei(void)
1931 #ifdef GPU_DIS_MOVEI
1933 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);
1935 // This instruction is followed by 32-bit value in LSW / MSW format...
1936 RN = (uint32)GPUReadWord(gpu_pc, GPU) | ((uint32)GPUReadWord(gpu_pc + 2, GPU) << 16);
1938 #ifdef GPU_DIS_MOVEI
1940 WriteLog("[NCZ:%u%u%u, R%02u=%08X]\n", gpu_flag_n, gpu_flag_c, gpu_flag_z, IMM_2, RN);
1944 static void gpu_opcode_moveta(void)
1946 #ifdef GPU_DIS_MOVETA
1948 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);
1951 #ifdef GPU_DIS_MOVETA
1953 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);
1957 static void gpu_opcode_movefa(void)
1959 #ifdef GPU_DIS_MOVEFA
1961 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);
1964 #ifdef GPU_DIS_MOVEFA
1966 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);
1970 static void gpu_opcode_move(void)
1974 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);
1979 WriteLog("[NCZ:%u%u%u, R%02u=%08X, R%02u=%08X]\n", gpu_flag_n, gpu_flag_c, gpu_flag_z, IMM_1, RM, IMM_2, RN);
1983 static void gpu_opcode_moveq(void)
1985 #ifdef GPU_DIS_MOVEQ
1987 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);
1990 #ifdef GPU_DIS_MOVEQ
1992 WriteLog("[NCZ:%u%u%u, R%02u=%08X]\n", gpu_flag_n, gpu_flag_c, gpu_flag_z, IMM_2, RN);
1996 static void gpu_opcode_resmac(void)
2001 static void gpu_opcode_imult(void)
2003 #ifdef GPU_DIS_IMULT
2005 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);
2007 RN = (int16)RN * (int16)RM;
2009 #ifdef GPU_DIS_IMULT
2011 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);
2015 static void gpu_opcode_mult(void)
2019 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);
2021 RN = (uint16)RM * (uint16)RN;
2025 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);
2029 static void gpu_opcode_bclr(void)
2033 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);
2035 uint32 res = RN & ~(1 << IMM_1);
2040 WriteLog("[NCZ:%u%u%u, R%02u=%08X]\n", gpu_flag_n, gpu_flag_c, gpu_flag_z, IMM_2, RN);
2044 static void gpu_opcode_btst(void)
2048 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);
2050 gpu_flag_z = (~RN >> IMM_1) & 1;
2053 WriteLog("[NCZ:%u%u%u, R%02u=%08X]\n", gpu_flag_n, gpu_flag_c, gpu_flag_z, IMM_2, RN);
2057 static void gpu_opcode_bset(void)
2061 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);
2063 uint32 res = RN | (1 << IMM_1);
2068 WriteLog("[NCZ:%u%u%u, R%02u=%08X]\n", gpu_flag_n, gpu_flag_c, gpu_flag_z, IMM_2, RN);
2072 static void gpu_opcode_imacn(void)
2074 uint32 res = (int16)RM * (int16)(RN);
2078 static void gpu_opcode_mtoi(void)
2081 uint32 res = RN = (((int32)_RM >> 8) & 0xFF800000) | (_RM & 0x007FFFFF);
2085 static void gpu_opcode_normi(void)
2092 while ((_RM & 0xFFC00000) == 0)
2097 while ((_RM & 0xFF800000) != 0)
2107 static void gpu_opcode_mmult(void)
2109 int count = gpu_matrix_control & 0x0F; // Matrix width
2110 uint32 addr = gpu_pointer_to_matrix; // In the GPU's RAM
2114 if (gpu_matrix_control & 0x10) // Column stepping
2116 for(int i=0; i<count; i++)
2120 a = (int16)((gpu_alternate_reg[IMM_1 + (i >> 1)] >> 16) & 0xFFFF);
2122 a = (int16)(gpu_alternate_reg[IMM_1 + (i >> 1)] & 0xFFFF);
2124 int16 b = ((int16)GPUReadWord(addr + 2, GPU));
2129 else // Row stepping
2131 for(int i=0; i<count; i++)
2135 a = (int16)((gpu_alternate_reg[IMM_1 + (i >> 1)] >> 16) & 0xFFFF);
2137 a = (int16)(gpu_alternate_reg[IMM_1 + (i >> 1)] & 0xFFFF);
2139 int16 b = ((int16)GPUReadWord(addr + 2, GPU));
2144 RN = res = (int32)accum;
2145 // carry flag to do (out of the last add)
2149 static void gpu_opcode_abs(void)
2153 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);
2155 gpu_flag_c = RN >> 31;
2156 if (RN == 0x80000000)
2157 //Is 0x80000000 a positive number? If so, then we need to set C to 0 as well!
2158 gpu_flag_n = 1, gpu_flag_z = 0;
2163 gpu_flag_n = 0; SET_FLAG_Z(RN);
2167 WriteLog("[NCZ:%u%u%u, R%02u=%08X]\n", gpu_flag_n, gpu_flag_c, gpu_flag_z, IMM_2, RN);
2171 static void gpu_opcode_div(void) // RN / RM
2175 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);
2177 // NOTE: remainder is NOT calculated correctly here!
2178 // The original tried to get it right by checking to see if the
2179 // remainder was negative, but that's too late...
2180 // The code there should do it now, but I'm not 100% sure...
2184 if (gpu_div_control & 0x01) // 16.16 division
2186 RN = ((uint64)RN << 16) / RM;
2187 gpu_remain = ((uint64)RN << 16) % RM;
2192 gpu_remain = RN % RM;
2195 if ((gpu_remain - RM) & 0x80000000) // If the result would have been negative...
2196 gpu_remain -= RM; // Then make it negative!
2206 if (gpu_div_control & 1)
2208 gpu_remain = (((uint64)_RN) << 16) % _RM;
2209 if (gpu_remain&0x80000000)
2211 RN = (((uint64)_RN) << 16) / _RM;
2215 gpu_remain = _RN % _RM;
2216 if (gpu_remain&0x80000000)
2225 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);
2229 static void gpu_opcode_imultn(void)
2231 uint32 res = (int32)((int16)RN * (int16)RM);
2232 gpu_acc = (int32)res;
2237 static void gpu_opcode_neg(void)
2241 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);
2244 SET_ZNC_SUB(0, RN, res);
2248 WriteLog("[NCZ:%u%u%u, R%02u=%08X]\n", gpu_flag_n, gpu_flag_c, gpu_flag_z, IMM_2, RN);
2252 static void gpu_opcode_shlq(void)
2256 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);
2258 // Was a bug here...
2259 // (Look at Aaron's code: If r1 = 32, then 32 - 32 = 0 which is wrong!)
2260 int32 r1 = 32 - IMM_1;
2261 uint32 res = RN << r1;
2262 SET_ZN(res); gpu_flag_c = (RN >> 31) & 1;
2266 WriteLog("[NCZ:%u%u%u, R%02u=%08X]\n", gpu_flag_n, gpu_flag_c, gpu_flag_z, IMM_2, RN);
2270 static void gpu_opcode_shrq(void)
2274 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);
2276 int32 r1 = gpu_convert_zero[IMM_1];
2277 uint32 res = RN >> r1;
2278 SET_ZN(res); gpu_flag_c = RN & 1;
2282 WriteLog("[NCZ:%u%u%u, R%02u=%08X]\n", gpu_flag_n, gpu_flag_c, gpu_flag_z, IMM_2, RN);
2286 static void gpu_opcode_ror(void)
2290 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);
2292 uint32 r1 = RM & 0x1F;
2293 uint32 res = (RN >> r1) | (RN << (32 - r1));
2294 SET_ZN(res); gpu_flag_c = (RN >> 31) & 1;
2298 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);
2302 static void gpu_opcode_rorq(void)
2306 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);
2308 uint32 r1 = gpu_convert_zero[IMM_1 & 0x1F];
2310 uint32 res = (r2 >> r1) | (r2 << (32 - r1));
2312 SET_ZN(res); gpu_flag_c = (r2 >> 31) & 0x01;
2315 WriteLog("[NCZ:%u%u%u, R%02u=%08X]\n", gpu_flag_n, gpu_flag_c, gpu_flag_z, IMM_2, RN);
2319 static void gpu_opcode_sha(void)
2321 /* int dreg = jaguar.op & 31;
2322 int32 r1 = (int32)jaguar.r[(jaguar.op >> 5) & 31];
2323 uint32 r2 = jaguar.r[dreg];
2329 res = (r1 <= -32) ? 0 : (r2 << -r1);
2330 jaguar.FLAGS |= (r2 >> 30) & 2;
2334 res = (r1 >= 32) ? ((int32)r2 >> 31) : ((int32)r2 >> r1);
2335 jaguar.FLAGS |= (r2 << 1) & 2;
2337 jaguar.r[dreg] = res;
2342 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);
2348 res = ((int32)RM <= -32) ? 0 : (RN << -(int32)RM);
2349 gpu_flag_c = RN >> 31;
2353 res = ((int32)RM >= 32) ? ((int32)RN >> 31) : ((int32)RN >> (int32)RM);
2354 gpu_flag_c = RN & 0x01;
2360 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);
2363 /* int32 sRM=(int32)RM;
2369 if (shift>=32) shift=32;
2370 gpu_flag_c=(_RN&0x80000000)>>31;
2380 if (shift>=32) shift=32;
2384 _RN=((int32)_RN)>>1;
2393 static void gpu_opcode_sharq(void)
2395 #ifdef GPU_DIS_SHARQ
2397 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);
2399 uint32 res = (int32)RN >> gpu_convert_zero[IMM_1];
2400 SET_ZN(res); gpu_flag_c = RN & 0x01;
2402 #ifdef GPU_DIS_SHARQ
2404 WriteLog("[NCZ:%u%u%u, R%02u=%08X]\n", gpu_flag_n, gpu_flag_c, gpu_flag_z, IMM_2, RN);
2408 static void gpu_opcode_sh(void)
2412 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);
2414 if (RM & 0x80000000) // Shift left
2416 gpu_flag_c = RN >> 31;
2417 RN = ((int32)RM <= -32 ? 0 : RN << -(int32)RM);
2421 gpu_flag_c = RN & 0x01;
2422 RN = (RM >= 32 ? 0 : RN >> RM);
2427 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);
2431 //Temporary: Testing only!
2432 //#include "gpu2.cpp"
2433 //#include "gpu3.cpp"
2437 // New thread-safe GPU core
2439 int GPUCore(void * data)