4 // Originally by David Raingeard (Cal2)
5 // GCC/SDL port by Niels Wagenaar (Linux/WIN32) and Caz (BeOS)
6 // Cleanups, endian wrongness, and bad ASM amelioration by James L. Hammons
7 // Note: Endian wrongness probably stems from the MAME origins of this emu and
8 // the braindead way in which MAME handles memory. :-)
10 // Problem with not booting the BIOS was the incorrect way that the
11 // SUBC instruction set the carry when the carry was set going in...
12 // Same problem with ADDC...
19 // For GPU dissasembly...
39 #define GPU_DIS_LOAD14I
40 #define GPU_DIS_LOAD14R
41 #define GPU_DIS_LOAD15I
42 #define GPU_DIS_LOAD15R
44 #define GPU_DIS_MOVEFA
46 #define GPU_DIS_MOVEPC
47 #define GPU_DIS_MOVETA
64 #define GPU_DIS_STOREB
65 #define GPU_DIS_STOREW
66 #define GPU_DIS_STORE14I
67 #define GPU_DIS_STORE14R
68 #define GPU_DIS_STORE15I
69 #define GPU_DIS_STORE15R
76 bool doGPUDis = false;
77 //bool doGPUDis = true;
80 GPU opcodes use (BIOS flying ATARI logo):
122 #define CINT0FLAG 0x0200
123 #define CINT1FLAG 0x0400
124 #define CINT2FLAG 0x0800
125 #define CINT3FLAG 0x1000
126 #define CINT4FLAG 0x2000
127 #define CINT04FLAGS (CINT0FLAG | CINT1FLAG | CINT2FLAG | CINT3FLAG | CINT4FLAG)
131 #define ZERO_FLAG 0x0001
132 #define CARRY_FLAG 0x0002
133 #define NEGA_FLAG 0x0004
135 #define INT_ENA0 0x0010
136 #define INT_ENA1 0x0020
137 #define INT_ENA2 0x0040
138 #define INT_ENA3 0x0080
139 #define INT_ENA4 0x0100
140 #define INT_CLR0 0x0200
141 #define INT_CLR1 0x0400
142 #define INT_CLR2 0x0800
143 #define INT_CLR3 0x1000
144 #define INT_CLR4 0x2000
145 #define REGPAGE 0x4000
148 // External global variables
150 extern int start_logging;
151 extern int gpu_start_log;
153 // Private function prototypes
155 void GPUUpdateRegisterBanks(void);
157 void GPUDumpDisassembly(void);
158 void GPUDumpRegisters(void);
159 void GPUDumpMemory(void);
161 static void gpu_opcode_add(void);
162 static void gpu_opcode_addc(void);
163 static void gpu_opcode_addq(void);
164 static void gpu_opcode_addqt(void);
165 static void gpu_opcode_sub(void);
166 static void gpu_opcode_subc(void);
167 static void gpu_opcode_subq(void);
168 static void gpu_opcode_subqt(void);
169 static void gpu_opcode_neg(void);
170 static void gpu_opcode_and(void);
171 static void gpu_opcode_or(void);
172 static void gpu_opcode_xor(void);
173 static void gpu_opcode_not(void);
174 static void gpu_opcode_btst(void);
175 static void gpu_opcode_bset(void);
176 static void gpu_opcode_bclr(void);
177 static void gpu_opcode_mult(void);
178 static void gpu_opcode_imult(void);
179 static void gpu_opcode_imultn(void);
180 static void gpu_opcode_resmac(void);
181 static void gpu_opcode_imacn(void);
182 static void gpu_opcode_div(void);
183 static void gpu_opcode_abs(void);
184 static void gpu_opcode_sh(void);
185 static void gpu_opcode_shlq(void);
186 static void gpu_opcode_shrq(void);
187 static void gpu_opcode_sha(void);
188 static void gpu_opcode_sharq(void);
189 static void gpu_opcode_ror(void);
190 static void gpu_opcode_rorq(void);
191 static void gpu_opcode_cmp(void);
192 static void gpu_opcode_cmpq(void);
193 static void gpu_opcode_sat8(void);
194 static void gpu_opcode_sat16(void);
195 static void gpu_opcode_move(void);
196 static void gpu_opcode_moveq(void);
197 static void gpu_opcode_moveta(void);
198 static void gpu_opcode_movefa(void);
199 static void gpu_opcode_movei(void);
200 static void gpu_opcode_loadb(void);
201 static void gpu_opcode_loadw(void);
202 static void gpu_opcode_load(void);
203 static void gpu_opcode_loadp(void);
204 static void gpu_opcode_load_r14_indexed(void);
205 static void gpu_opcode_load_r15_indexed(void);
206 static void gpu_opcode_storeb(void);
207 static void gpu_opcode_storew(void);
208 static void gpu_opcode_store(void);
209 static void gpu_opcode_storep(void);
210 static void gpu_opcode_store_r14_indexed(void);
211 static void gpu_opcode_store_r15_indexed(void);
212 static void gpu_opcode_move_pc(void);
213 static void gpu_opcode_jump(void);
214 static void gpu_opcode_jr(void);
215 static void gpu_opcode_mmult(void);
216 static void gpu_opcode_mtoi(void);
217 static void gpu_opcode_normi(void);
218 static void gpu_opcode_nop(void);
219 static void gpu_opcode_load_r14_ri(void);
220 static void gpu_opcode_load_r15_ri(void);
221 static void gpu_opcode_store_r14_ri(void);
222 static void gpu_opcode_store_r15_ri(void);
223 static void gpu_opcode_sat24(void);
224 static void gpu_opcode_pack(void);
226 // This is wrong, since it doesn't take pipeline effects into account. !!! FIX !!!
227 /*uint8 gpu_opcode_cycles[64] =
229 3, 3, 3, 3, 3, 3, 3, 3,
230 3, 3, 3, 3, 3, 3, 3, 3,
231 3, 3, 1, 3, 1, 18, 3, 3,
232 3, 3, 3, 3, 3, 3, 3, 3,
233 3, 3, 2, 2, 2, 2, 3, 4,
234 5, 4, 5, 6, 6, 1, 1, 1,
235 1, 2, 2, 2, 1, 1, 9, 3,
236 3, 1, 6, 6, 2, 2, 3, 3
238 //Here's a QnD kludge...
239 //This is wrong, wrong, WRONG, but it seems to work for the time being...
240 //(That is, it fixes Flip Out which relies on GPU timing rather than semaphores. Bad developers! Bad!)
241 //What's needed here is a way to take pipeline effects into account (including pipeline stalls!)...
242 uint8 gpu_opcode_cycles[64] =
244 1, 1, 1, 1, 1, 1, 1, 1,
245 1, 1, 1, 1, 1, 1, 1, 1,
246 1, 1, 1, 1, 1, 9, 1, 1,
247 1, 1, 1, 1, 1, 1, 1, 1,
248 1, 1, 1, 1, 1, 1, 1, 2,
249 2, 2, 2, 3, 3, 1, 1, 1,
250 1, 1, 1, 1, 1, 1, 4, 1,
251 1, 1, 3, 3, 1, 1, 1, 1
254 void (*gpu_opcode[64])()=
256 gpu_opcode_add, gpu_opcode_addc, gpu_opcode_addq, gpu_opcode_addqt,
257 gpu_opcode_sub, gpu_opcode_subc, gpu_opcode_subq, gpu_opcode_subqt,
258 gpu_opcode_neg, gpu_opcode_and, gpu_opcode_or, gpu_opcode_xor,
259 gpu_opcode_not, gpu_opcode_btst, gpu_opcode_bset, gpu_opcode_bclr,
260 gpu_opcode_mult, gpu_opcode_imult, gpu_opcode_imultn, gpu_opcode_resmac,
261 gpu_opcode_imacn, gpu_opcode_div, gpu_opcode_abs, gpu_opcode_sh,
262 gpu_opcode_shlq, gpu_opcode_shrq, gpu_opcode_sha, gpu_opcode_sharq,
263 gpu_opcode_ror, gpu_opcode_rorq, gpu_opcode_cmp, gpu_opcode_cmpq,
264 gpu_opcode_sat8, gpu_opcode_sat16, gpu_opcode_move, gpu_opcode_moveq,
265 gpu_opcode_moveta, gpu_opcode_movefa, gpu_opcode_movei, gpu_opcode_loadb,
266 gpu_opcode_loadw, gpu_opcode_load, gpu_opcode_loadp, gpu_opcode_load_r14_indexed,
267 gpu_opcode_load_r15_indexed, gpu_opcode_storeb, gpu_opcode_storew, gpu_opcode_store,
268 gpu_opcode_storep, gpu_opcode_store_r14_indexed, gpu_opcode_store_r15_indexed, gpu_opcode_move_pc,
269 gpu_opcode_jump, gpu_opcode_jr, gpu_opcode_mmult, gpu_opcode_mtoi,
270 gpu_opcode_normi, gpu_opcode_nop, gpu_opcode_load_r14_ri, gpu_opcode_load_r15_ri,
271 gpu_opcode_store_r14_ri, gpu_opcode_store_r15_ri, gpu_opcode_sat24, gpu_opcode_pack,
274 static uint8 * gpu_ram_8;
276 static uint32 gpu_acc;
277 static uint32 gpu_remain;
278 static uint32 gpu_hidata;
279 static uint32 gpu_flags;
280 static uint32 gpu_matrix_control;
281 static uint32 gpu_pointer_to_matrix;
282 static uint32 gpu_data_organization;
283 static uint32 gpu_control;
284 static uint32 gpu_div_control;
285 // There is a distinct advantage to having these separated out--there's no need to clear
286 // a bit before writing a result. I.e., if the result of an operation leaves a zero in
287 // the carry flag, you don't have to zero gpu_flag_c before you can write that zero!
288 static uint8 gpu_flag_z, gpu_flag_n, gpu_flag_c;
289 static uint32 * gpu_reg_bank_0;
290 static uint32 * gpu_reg_bank_1;
291 static uint32 * gpu_reg;
292 static uint32 * gpu_alternate_reg;
294 static uint32 gpu_instruction;
295 static uint32 gpu_opcode_first_parameter;
296 static uint32 gpu_opcode_second_parameter;
298 #define GPU_RUNNING (gpu_control & 0x01)
300 #define RM gpu_reg[gpu_opcode_first_parameter]
301 #define RN gpu_reg[gpu_opcode_second_parameter]
302 #define ALTERNATE_RM gpu_alternate_reg[gpu_opcode_first_parameter]
303 #define ALTERNATE_RN gpu_alternate_reg[gpu_opcode_second_parameter]
304 #define IMM_1 gpu_opcode_first_parameter
305 #define IMM_2 gpu_opcode_second_parameter
307 #define SET_FLAG_Z(r) (gpu_flag_z = ((r) == 0));
308 #define SET_FLAG_N(r) (gpu_flag_n = (((UINT32)(r) >> 31) & 0x01));
310 #define RESET_FLAG_Z() gpu_flag_z = 0;
311 #define RESET_FLAG_N() gpu_flag_n = 0;
312 #define RESET_FLAG_C() gpu_flag_c = 0;
314 #define CLR_Z (gpu_flag_z = 0)
315 #define CLR_ZN (gpu_flag_z = gpu_flag_n = 0)
316 #define CLR_ZNC (gpu_flag_z = gpu_flag_n = gpu_flag_c = 0)
317 #define SET_Z(r) (gpu_flag_z = ((r) == 0))
318 #define SET_N(r) (gpu_flag_n = (((UINT32)(r) >> 31) & 0x01))
319 #define SET_C_ADD(a,b) (gpu_flag_c = ((UINT32)(b) > (UINT32)(~(a))))
320 #define SET_C_SUB(a,b) (gpu_flag_c = ((UINT32)(b) > (UINT32)(a)))
321 #define SET_ZN(r) SET_N(r); SET_Z(r)
322 #define SET_ZNC_ADD(a,b,r) SET_N(r); SET_Z(r); SET_C_ADD(a,b)
323 #define SET_ZNC_SUB(a,b,r) SET_N(r); SET_Z(r); SET_C_SUB(a,b)
325 uint32 gpu_convert_zero[32] =
326 { 32,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31 };
328 uint8 * branch_condition_table = 0;
329 #define BRANCH_CONDITION(x) branch_condition_table[(x) + ((jaguar_flags & 7) << 5)]
331 uint32 gpu_opcode_use[64];
333 char * gpu_opcode_str[64]=
335 "add", "addc", "addq", "addqt",
336 "sub", "subc", "subq", "subqt",
337 "neg", "and", "or", "xor",
338 "not", "btst", "bset", "bclr",
339 "mult", "imult", "imultn", "resmac",
340 "imacn", "div", "abs", "sh",
341 "shlq", "shrq", "sha", "sharq",
342 "ror", "rorq", "cmp", "cmpq",
343 "sat8", "sat16", "move", "moveq",
344 "moveta", "movefa", "movei", "loadb",
345 "loadw", "load", "loadp", "load_r14_indexed",
346 "load_r15_indexed", "storeb", "storew", "store",
347 "storep", "store_r14_indexed","store_r15_indexed","move_pc",
348 "jump", "jr", "mmult", "mtoi",
349 "normi", "nop", "load_r14_ri", "load_r15_ri",
350 "store_r14_ri", "store_r15_ri", "sat24", "pack",
353 static uint32 gpu_in_exec = 0;
354 static uint32 gpu_releaseTimeSlice_flag = 0;
356 void gpu_releaseTimeslice(void)
358 gpu_releaseTimeSlice_flag = 1;
361 uint32 gpu_get_pc(void)
366 void build_branch_condition_table(void)
368 if (!branch_condition_table)
370 branch_condition_table = (uint8 *)malloc(32 * 8 * sizeof(branch_condition_table[0]));
372 if (branch_condition_table)
374 for(int i=0; i<8; i++)
376 for(int j=0; j<32; j++)
383 if (!(i & ZERO_FLAG))
386 if (i & (CARRY_FLAG << (j >> 4)))
389 if (!(i & (CARRY_FLAG << (j >> 4))))
391 branch_condition_table[i * 32 + j] = result;
399 // GPU byte access (read)
401 uint8 GPUReadByte(uint32 offset, uint32 who/*=UNKNOWN*/)
403 if (offset >= 0xF02000 && offset <= 0xF020FF)
404 WriteLog("GPU: ReadByte--Attempt to read from GPU register file by %s!\n", whoName[who]);
406 if ((offset >= GPU_WORK_RAM_BASE) && (offset < GPU_WORK_RAM_BASE+0x1000))
407 return gpu_ram_8[offset & 0xFFF];
408 else if ((offset >= GPU_CONTROL_RAM_BASE) && (offset < GPU_CONTROL_RAM_BASE+0x20))
410 uint32 data = GPUReadLong(offset & 0xFFFFFFFC, who);
412 if ((offset & 0x03) == 0)
414 else if ((offset & 0x03) == 1)
415 return (data >> 16) & 0xFF;
416 else if ((offset & 0x03) == 2)
417 return (data >> 8) & 0xFF;
418 else if ((offset & 0x03) == 3)
422 return JaguarReadByte(offset, who);
426 // GPU word access (read)
428 uint16 GPUReadWord(uint32 offset, uint32 who/*=UNKNOWN*/)
430 if (offset >= 0xF02000 && offset <= 0xF020FF)
431 WriteLog("GPU: ReadWord--Attempt to read from GPU register file by %s!\n", whoName[who]);
433 if ((offset >= GPU_WORK_RAM_BASE) && (offset < GPU_WORK_RAM_BASE+0x1000))
436 uint16 data = ((uint16)gpu_ram_8[offset] << 8) | (uint16)gpu_ram_8[offset+1];
439 else if ((offset >= GPU_CONTROL_RAM_BASE) && (offset < GPU_CONTROL_RAM_BASE+0x20))
441 // This looks and smells wrong...
442 // But it *might* be OK...
443 if (offset & 0x01) // Catch cases 1 & 3... (unaligned read)
444 return (GPUReadByte(offset, who) << 8) | GPUReadByte(offset+1, who);
446 uint32 data = GPUReadLong(offset & 0xFFFFFFFC, who);
448 if (offset & 0x02) // Cases 0 & 2...
449 return data & 0xFFFF;
454 //TEMP--Mirror of F03000? No. Writes only...
455 //if (offset >= 0xF0B000 && offset <= 0xF0BFFF)
456 //WriteLog("[GPUR16] --> Possible GPU RAM mirror access by %s!", whoName[who]);
458 return JaguarReadWord(offset, who);
462 // GPU dword access (read)
464 uint32 GPUReadLong(uint32 offset, uint32 who/*=UNKNOWN*/)
466 if (offset >= 0xF02000 && offset <= 0xF020FF)
467 WriteLog("GPU: ReadLong--Attempt to read from GPU register file by %s!\n", whoName[who]);
469 // if ((offset >= GPU_WORK_RAM_BASE) && (offset < GPU_WORK_RAM_BASE + 0x1000))
470 if ((offset >= GPU_WORK_RAM_BASE) && (offset <= GPU_WORK_RAM_BASE + 0x0FFC))
473 return ((uint32)gpu_ram_8[offset] << 24) | ((uint32)gpu_ram_8[offset+1] << 16)
474 | ((uint32)gpu_ram_8[offset+2] << 8) | (uint32)gpu_ram_8[offset+3];//*/
475 // return GET32(gpu_ram_8, offset);
477 // else if ((offset >= GPU_CONTROL_RAM_BASE) && (offset < GPU_CONTROL_RAM_BASE+0x20))
478 else if ((offset >= GPU_CONTROL_RAM_BASE) && (offset <= GPU_CONTROL_RAM_BASE + 0x1C))
484 gpu_flag_c = (gpu_flag_c ? 1 : 0);
485 gpu_flag_z = (gpu_flag_z ? 1 : 0);
486 gpu_flag_n = (gpu_flag_n ? 1 : 0);
488 gpu_flags = (gpu_flags & 0xFFFFFFF8) | (gpu_flag_n << 2) | (gpu_flag_c << 1) | gpu_flag_z;
490 return gpu_flags & 0xFFFFC1FF;
492 return gpu_matrix_control;
494 return gpu_pointer_to_matrix;
496 return gpu_data_organization;
505 default: // unaligned long read
507 WriteLog("GPU: Read32--unaligned 32 bit read at %08X by %s.\n", GPU_CONTROL_RAM_BASE + offset, whoName[who]);
512 //TEMP--Mirror of F03000? No. Writes only...
513 //if (offset >= 0xF0B000 && offset <= 0xF0BFFF)
514 // WriteLog("[GPUR32] --> Possible GPU RAM mirror access by %s!\n", whoName[who]);
515 /*if (offset >= 0xF1D000 && offset <= 0xF1DFFF)
516 WriteLog("[GPUR32] --> Reading from Wavetable ROM!\n");//*/
518 return (JaguarReadWord(offset, who) << 16) | JaguarReadWord(offset + 2, who);
522 // GPU byte access (write)
524 void GPUWriteByte(uint32 offset, uint8 data, uint32 who/*=UNKNOWN*/)
526 if (offset >= 0xF02000 && offset <= 0xF020FF)
527 WriteLog("GPU: WriteByte--Attempt to write to GPU register file by %s!\n", whoName[who]);
529 if ((offset >= GPU_WORK_RAM_BASE) && (offset <= GPU_WORK_RAM_BASE + 0x0FFF))
531 gpu_ram_8[offset & 0xFFF] = data;
533 //This is the same stupid worthless code that was in the DSP!!! AARRRGGGGHHHHH!!!!!!
536 m68k_end_timeslice();
537 dsp_releaseTimeslice();
541 else if ((offset >= GPU_CONTROL_RAM_BASE) && (offset <= GPU_CONTROL_RAM_BASE + 0x1F))
543 uint32 reg = offset & 0x1C;
544 int bytenum = offset & 0x03;
546 //This is definitely wrong!
547 if ((reg >= 0x1C) && (reg <= 0x1F))
548 gpu_div_control = (gpu_div_control & (~(0xFF << (bytenum << 3)))) | (data << (bytenum << 3));
551 uint32 old_data = GPUReadLong(offset & 0xFFFFFFC, who);
552 bytenum = 3 - bytenum; // convention motorola !!!
553 old_data = (old_data & (~(0xFF << (bytenum << 3)))) | (data << (bytenum << 3));
554 GPUWriteLong(offset & 0xFFFFFFC, old_data, who);
558 // WriteLog("gpu: writing %.2x at 0x%.8x\n",data,offset);
559 JaguarWriteByte(offset, data, who);
563 // GPU word access (write)
565 void GPUWriteWord(uint32 offset, uint16 data, uint32 who/*=UNKNOWN*/)
567 if (offset >= 0xF02000 && offset <= 0xF020FF)
568 WriteLog("GPU: WriteWord--Attempt to write to GPU register file by %s!\n", whoName[who]);
570 if ((offset >= GPU_WORK_RAM_BASE) && (offset <= GPU_WORK_RAM_BASE + 0x0FFE))
572 gpu_ram_8[offset & 0xFFF] = (data>>8) & 0xFF;
573 gpu_ram_8[(offset+1) & 0xFFF] = data & 0xFF;//*/
575 SET16(gpu_ram_8, offset, data);//*/
577 /*if (offset >= 0xF03214 && offset < 0xF0321F)
578 WriteLog("GPU: Writing WORD (%04X) to GPU RAM (%08X)...\n", data, offset);//*/
581 //This is the same stupid worthless code that was in the DSP!!! AARRRGGGGHHHHH!!!!!!
584 m68k_end_timeslice();
585 dsp_releaseTimeslice();
589 else if ((offset >= GPU_CONTROL_RAM_BASE) && (offset <= GPU_CONTROL_RAM_BASE + 0x1E))
591 if (offset & 0x01) // This is supposed to weed out unaligned writes, but does nothing...
594 WriteLog("GPU: Write16--unaligned write @ %08X [%04X]\n", offset, data);
599 //Dual locations in this range: $1C Divide unit remainder/Divide unit control (R/W)
600 //This just literally sucks.
601 if ((offset & 0x1C) == 0x1C)
603 //This doesn't look right either--handles cases 1, 2, & 3 all the same!
605 gpu_div_control = (gpu_div_control & 0xFFFF0000) | (data & 0xFFFF);
607 gpu_div_control = (gpu_div_control & 0x0000FFFF) | ((data & 0xFFFF) << 16);
611 //WriteLog("[GPU W16:%08X,%04X]", offset, data);
612 uint32 old_data = GPUReadLong(offset & 0xFFFFFFC, who);
614 old_data = (old_data & 0xFFFF0000) | (data & 0xFFFF);
616 old_data = (old_data & 0x0000FFFF) | ((data & 0xFFFF) << 16);
617 GPUWriteLong(offset & 0xFFFFFFC, old_data, who);
621 else if ((offset == GPU_WORK_RAM_BASE + 0x0FFF) || (GPU_CONTROL_RAM_BASE + 0x1F))
624 WriteLog("GPU: Write16--unaligned write @ %08X by %s [%04X]!\n", offset, whoName[who], data);
630 // Have to be careful here--this can cause an infinite loop!
631 JaguarWriteWord(offset, data, who);
635 // GPU dword access (write)
637 void GPUWriteLong(uint32 offset, uint32 data, uint32 who/*=UNKNOWN*/)
639 if (offset >= 0xF02000 && offset <= 0xF020FF)
640 WriteLog("GPU: WriteLong--Attempt to write to GPU register file by %s!\n", whoName[who]);
642 // if ((offset >= GPU_WORK_RAM_BASE) && (offset < GPU_WORK_RAM_BASE + 0x1000))
643 if ((offset >= GPU_WORK_RAM_BASE) && (offset <= GPU_WORK_RAM_BASE + 0x0FFC))
648 WriteLog("GPU: Write32--unaligned write @ %08X [%08X] by %s\n", offset, data, whoName[who]);
653 /* gpu_ram_8[offset & 0xFFF] = (data >> 24) & 0xFF,
654 gpu_ram_8[(offset+1) & 0xFFF] = (data >> 16) & 0xFF,
655 gpu_ram_8[(offset+2) & 0xFFF] = (data >> 8) & 0xFF,
656 gpu_ram_8[(offset+3) & 0xFFF] = data & 0xFF;//*/
658 SET32(gpu_ram_8, offset, data);//*/
661 // else if ((offset >= GPU_CONTROL_RAM_BASE) && (offset < GPU_CONTROL_RAM_BASE+0x20))
662 else if ((offset >= GPU_CONTROL_RAM_BASE) && (offset <= GPU_CONTROL_RAM_BASE + 0x1C))
669 bool IMASKCleared = (gpu_flags & IMASK) && !(data & IMASK);
671 gpu_flag_z = gpu_flags & ZERO_FLAG;
672 gpu_flag_c = (gpu_flags & CARRY_FLAG) >> 1;
673 gpu_flag_n = (gpu_flags & NEGA_FLAG) >> 2;
674 GPUUpdateRegisterBanks();
675 gpu_control &= ~((gpu_flags & CINT04FLAGS) >> 3); // Interrupt latch clear bits
676 //Writing here is only an interrupt enable--this approach is just plain wrong!
678 //This, however, is A-OK! ;-)
679 if (IMASKCleared) // If IMASK was cleared,
680 GPUHandleIRQs(); // see if any other interrupts need servicing!
682 if (gpu_flags & (INT_ENA0 | INT_ENA1 | INT_ENA2 | INT_ENA3 | INT_ENA4))
683 WriteLog("GPU: Interrupt enable set by %s! Bits: %02X\n", whoName[who], (gpu_flags >> 4) & 0x1F);
684 WriteLog("GPU: REGPAGE %s...\n", (gpu_flags & REGPAGE ? "set" : "cleared"));
689 gpu_matrix_control = data;
692 // This can only point to long aligned addresses
693 gpu_pointer_to_matrix = data & 0xFFFFFFFC;
696 gpu_data_organization = data;
701 WriteLog("GPU: %s setting GPU PC to %08X %s\n", whoName[who], gpu_pc, (GPU_RUNNING ? "(GPU is RUNNING!)" : ""));//*/
706 // uint32 gpu_was_running = GPU_RUNNING;
707 data &= ~0xF7C0; // Disable writes to INT_LAT0-4 & TOM version number
709 // check for GPU -> CPU interrupt
712 //WriteLog("GPU->CPU interrupt\n");
713 if (tom_irq_enabled(IRQ_GPU))
715 if ((tom_irq_enabled(IRQ_GPU)) && (jaguar_interrupt_handler_is_valid(64)))
717 tom_set_pending_gpu_int();
718 m68k_set_irq(7); // Set 68000 NMI
719 gpu_releaseTimeslice();
725 // check for CPU -> GPU interrupt #0
728 //WriteLog("CPU->GPU interrupt\n");
729 GPUSetIRQLine(0, ASSERT_LINE);
730 m68k_end_timeslice();
731 dsp_releaseTimeslice();
738 //WriteLog("asked to perform a single step (single step is %senabled)\n",(data&0x8)?"":"not ");
740 gpu_control = (gpu_control & 0xF7C0) | (data & (~0xF7C0));
742 // if gpu wasn't running but is now running, execute a few cycles
743 #ifndef GPU_SINGLE_STEPPING
744 /* if (!gpu_was_running && GPU_RUNNING)
747 WriteLog("GPU: Write32--About to do stupid braindead GPU execution for 200 cycles.\n");
752 #endif // GPU_DEBUG//*/
754 if (gpu_control & 0x18)
756 #endif // #ifndef GPU_SINGLE_STEPPING
758 WriteLog("Write to GPU CTRL by %s: %08X ", whoName[who], data);
760 WriteLog(" --> Starting to run at %08X by %s...", gpu_pc, whoName[who]);
762 WriteLog(" --> Stopped by %s! (GPU_PC: %08X)", whoName[who], gpu_pc);
766 // GPUDumpDisassembly();
769 if (gpu_pc == 0xF035D8)
771 // GPUDumpDisassembly();
774 gpu_control &= 0xFFFFFFFE; // Don't run it and let's see what happens!
775 //Hmm. Seems to lock up when going into the demo...
776 //Try to disable the collision altogether!
779 extern int effect_start5;
780 static bool finished = false;
781 //if (GPU_RUNNING && effect_start5 && !finished)
782 if (GPU_RUNNING && effect_start5 && gpu_pc == 0xF035D8)
784 // Let's do a dump of $6528!
785 /* uint32 numItems = JaguarReadWord(0x6BD6);
786 WriteLog("\nDump of $6528: %u items.\n\n", numItems);
787 for(int i=0; i<numItems*3*4; i+=3*4)
789 WriteLog("\t%04X: %08X %08X %08X -> ", 0x6528+i, JaguarReadLong(0x6528+i),
790 JaguarReadLong(0x6528+i+4), JaguarReadLong(0x6528+i+8));
791 uint16 link = JaguarReadWord(0x6528+i+8+2);
792 for(int j=0; j<40; j+=4)
793 WriteLog("%08X ", JaguarReadLong(link + j));
797 // Let's try a manual blit here...
798 //This isn't working the way it should! !!! FIX !!!
799 //Err, actually, it is.
800 // NOW, it works right! Problem solved!!! It's a blitter bug!
801 /* uint32 src = 0x4D54, dst = 0xF03000, width = 10 * 4;
802 for(int y=0; y<127; y++)
804 for(int x=0; x<2; x++)
806 JaguarWriteLong(dst, JaguarReadLong(src));
811 src += width - (2 * 4);
815 WriteLog("\nGPU: About to execute collision detection code.\n\n");//*/
817 /* WriteLog("\nGPU: About to execute collision detection code. Data @ 4D54:\n\n");
819 for(int i=0x004D54; i<0x004D54+2048; i++)
821 WriteLog("%02X ", JaguarReadByte(i));
829 WriteLog("\n\nData @ F03000:\n\n");
831 for(int i=0xF03000; i<0xF03200; i++)
833 WriteLog("%02X ", JaguarReadByte(i));
847 /*if (!GPU_RUNNING && finished)
849 WriteLog("\nGPU: Finished collision detection code. Exiting!\n\n");
854 // (?) If we're set running by the M68K (or DSP?) then end its timeslice to
855 // allow the GPU a chance to run...
856 // Yes! This partially fixed Trevor McFur...
858 m68k_end_timeslice();
865 gpu_div_control = data;
867 // default: // unaligned long write
874 // JaguarWriteWord(offset, (data >> 16) & 0xFFFF, who);
875 // JaguarWriteWord(offset+2, data & 0xFFFF, who);
876 JaguarWriteLong(offset, data, who);
880 // Change register banks if necessary
882 void GPUUpdateRegisterBanks(void)
884 int bank = (gpu_flags & REGPAGE); // REGPAGE bit
886 if (gpu_flags & IMASK) // IMASK bit
887 bank = 0; // IMASK forces main bank to be bank 0
890 gpu_reg = gpu_reg_bank_1, gpu_alternate_reg = gpu_reg_bank_0;
892 gpu_reg = gpu_reg_bank_0, gpu_alternate_reg = gpu_reg_bank_1;
895 void GPUHandleIRQs(void)
897 // Bail out if we're already in an interrupt!
898 if (gpu_flags & IMASK)
901 // Get the interrupt latch & enable bits
902 uint32 bits = (gpu_control >> 6) & 0x1F, mask = (gpu_flags >> 4) & 0x1F;
904 // Bail out if latched interrupts aren't enabled
909 // Determine which interrupt to service
910 uint32 which = 0; //Isn't there a #pragma to disable this warning???
923 WriteLog("GPU: Generating IRQ #%i\n", which);
925 // set the interrupt flag
927 GPUUpdateRegisterBanks();
929 // subqt #4,r31 ; pre-decrement stack pointer
930 // move pc,r30 ; address of interrupted code
931 // store r30,(r31) ; store return address
933 GPUWriteLong(gpu_reg[31], gpu_pc - 2, GPU);
935 // movei #service_address,r30 ; pointer to ISR entry
936 // jump (r30) ; jump to ISR
938 gpu_pc = gpu_reg[30] = GPU_WORK_RAM_BASE + (which * 0x10);
941 void GPUSetIRQLine(int irqline, int state)
944 WriteLog("GPU: Setting GPU IRQ line #%i\n", irqline);
946 uint32 mask = 0x0040 << irqline;
947 gpu_control &= ~mask; // Clear the interrupt latch
951 gpu_control |= mask; // Assert the interrupt latch
952 GPUHandleIRQs(); // And handle the interrupt...
956 //TEMPORARY: Testing only!
962 memory_malloc_secure((void **)&gpu_ram_8, 0x1000, "GPU work RAM");
963 // memory_malloc_secure((void **)&gpu_reg, 32*sizeof(int32), "GPU bank 0 regs");
964 // memory_malloc_secure((void **)&gpu_alternate_reg, 32*sizeof(int32), "GPU bank 1 regs");
965 memory_malloc_secure((void **)&gpu_reg_bank_0, 32 * sizeof(int32), "GPU bank 0 regs");
966 memory_malloc_secure((void **)&gpu_reg_bank_1, 32 * sizeof(int32), "GPU bank 1 regs");
968 build_branch_condition_table();
972 //TEMPORARY: Testing only!
979 // GPU registers (directly visible)
980 gpu_flags = 0x00000000;
981 gpu_matrix_control = 0x00000000;
982 gpu_pointer_to_matrix = 0x00000000;
983 gpu_data_organization = 0xFFFFFFFF;
985 gpu_control = 0x00002800; // Correctly sets this as TOM Rev. 2
986 gpu_hidata = 0x00000000;
987 gpu_remain = 0x00000000; // These two registers are RO/WO
988 gpu_div_control = 0x00000000;
990 // GPU internal register
991 gpu_acc = 0x00000000;
993 gpu_reg = gpu_reg_bank_0;
994 gpu_alternate_reg = gpu_reg_bank_1;
996 for(int i=0; i<32; i++)
997 gpu_reg[i] = gpu_alternate_reg[i] = 0x00000000;
1000 memset(gpu_ram_8, 0xFF, 0x1000);
1002 //not needed GPUInterruptPending = false;
1006 uint32 gpu_read_pc(void)
1011 void gpu_reset_stats(void)
1013 for(uint32 i=0; i<64; i++)
1014 gpu_opcode_use[i] = 0;
1015 WriteLog("--> GPU stats were reset!\n");
1018 void GPUDumpDisassembly(void)
1022 WriteLog("\n---[GPU code at 00F03000]---------------------------\n");
1023 uint32 j = 0xF03000;
1024 while (j <= 0xF03FFF)
1027 j += dasmjag(JAGUAR_GPU, buffer, j);
1028 WriteLog("\t%08X: %s\n", oldj, buffer);
1032 void GPUDumpRegisters(void)
1034 WriteLog("\n---[GPU flags: NCZ %d%d%d]-----------------------\n", gpu_flag_n, gpu_flag_c, gpu_flag_z);
1035 WriteLog("\nRegisters bank 0\n");
1036 for(int j=0; j<8; j++)
1038 WriteLog("\tR%02i = %08X R%02i = %08X R%02i = %08X R%02i = %08X\n",
1039 (j << 2) + 0, gpu_reg_bank_0[(j << 2) + 0],
1040 (j << 2) + 1, gpu_reg_bank_0[(j << 2) + 1],
1041 (j << 2) + 2, gpu_reg_bank_0[(j << 2) + 2],
1042 (j << 2) + 3, gpu_reg_bank_0[(j << 2) + 3]);
1044 WriteLog("Registers bank 1\n");
1045 for(int j=0; j<8; j++)
1047 WriteLog("\tR%02i = %08X R%02i = %08X R%02i = %08X R%02i = %08X\n",
1048 (j << 2) + 0, gpu_reg_bank_1[(j << 2) + 0],
1049 (j << 2) + 1, gpu_reg_bank_1[(j << 2) + 1],
1050 (j << 2) + 2, gpu_reg_bank_1[(j << 2) + 2],
1051 (j << 2) + 3, gpu_reg_bank_1[(j << 2) + 3]);
1055 void GPUDumpMemory(void)
1057 WriteLog("\n---[GPU data at 00F03000]---------------------------\n");
1058 for(int i=0; i<0xFFF; i+=4)
1059 WriteLog("\t%08X: %02X %02X %02X %02X\n", 0xF03000+i, gpu_ram_8[i],
1060 gpu_ram_8[i+1], gpu_ram_8[i+2], gpu_ram_8[i+3]);
1065 WriteLog("GPU: Stopped at PC=%08X (GPU %s running)\n", (unsigned int)gpu_pc, GPU_RUNNING ? "was" : "wasn't");
1067 // Get the interrupt latch & enable bits
1068 uint8 bits = (gpu_control >> 6) & 0x1F, mask = (gpu_flags >> 4) & 0x1F;
1069 WriteLog("GPU: Latch bits = %02X, enable bits = %02X\n", bits, mask);
1072 GPUDumpDisassembly();
1074 WriteLog("\nGPU opcodes use:\n");
1075 for(int i=0; i<64; i++)
1077 if (gpu_opcode_use[i])
1078 WriteLog("\t%17s %lu\n", gpu_opcode_str[i], gpu_opcode_use[i]);
1082 memory_free(gpu_ram_8);
1086 // Main GPU execution core
1088 static int testCount = 1;
1090 static bool tripwire = false;
1091 void gpu_exec(int32 cycles)
1096 #ifdef GPU_SINGLE_STEPPING
1097 if (gpu_control & 0x18)
1100 gpu_control &= ~0x10;
1104 gpu_releaseTimeSlice_flag = 0;
1107 while (cycles > 0 && GPU_RUNNING)
1109 /*if (gpu_pc == 0xF0359A)
1114 /* gpu_flag_c = (gpu_flag_c ? 1 : 0);
1115 gpu_flag_z = (gpu_flag_z ? 1 : 0);
1116 gpu_flag_n = (gpu_flag_n ? 1 : 0);*/
1118 uint16 opcode = GPUReadWord(gpu_pc, GPU);
1119 uint32 index = opcode >> 10;
1120 gpu_instruction = opcode; // Added for GPU #3...
1121 gpu_opcode_first_parameter = (opcode >> 5) & 0x1F;
1122 gpu_opcode_second_parameter = opcode & 0x1F;
1123 /*if (gpu_pc == 0xF03BE8)
1124 WriteLog("Start of OP frame write...\n");
1125 if (gpu_pc == 0xF03EEE)
1126 WriteLog("--> Writing BRANCH object ---\n");
1127 if (gpu_pc == 0xF03F62)
1128 WriteLog("--> Writing BITMAP object ***\n");//*/
1129 /*if (gpu_pc == 0xF03546)
1131 WriteLog("\n--> GPU PC: F03546\n");
1133 GPUDumpDisassembly();
1135 /*if (gpu_pc == 0xF033F6)
1137 WriteLog("\n--> GPU PC: F033F6\n");
1139 GPUDumpDisassembly();
1141 /*if (gpu_pc == 0xF033CC)
1143 WriteLog("\n--> GPU PC: F033CC\n");
1145 GPUDumpDisassembly();
1147 /*if (gpu_pc == 0xF033D6)
1149 WriteLog("\n--> GPU PC: F033D6 (#%d)\n", testCount++);
1153 /*if (gpu_pc == 0xF033D8)
1155 WriteLog("\n--> GPU PC: F033D8 (#%d)\n", testCount++);
1159 /*if (gpu_pc == 0xF0358E)
1161 WriteLog("\n--> GPU PC: F0358E (#%d)\n", testCount++);
1165 /*if (gpu_pc == 0xF034CA)
1167 WriteLog("\n--> GPU PC: F034CA (#%d)\n", testCount++);
1170 /*if (gpu_pc == 0xF034CA)
1172 len = gpu_reg[1] + 4;//, r9save = gpu_reg[9];
1173 WriteLog("\nAbout to subtract [#%d] (R14=%08X, R15=%08X, R9=%08X):\n ", testCount++, gpu_reg[14], gpu_reg[15], gpu_reg[9]);
1174 for(int i=0; i<len; i+=4)
1175 WriteLog(" %08X", GPUReadLong(gpu_reg[15]+i));
1177 for(int i=0; i<len; i+=4)
1178 WriteLog(" %08X", GPUReadLong(gpu_reg[14]+i));
1181 if (gpu_pc == 0xF034DE)
1183 WriteLog("\nSubtracted! (R14=%08X, R15=%08X):\n ", gpu_reg[14], gpu_reg[15]);
1184 for(int i=0; i<len; i+=4)
1185 WriteLog(" %08X", GPUReadLong(gpu_reg[15]+i));
1187 for(int i=0; i<len; i+=4)
1188 WriteLog(" %08X", GPUReadLong(gpu_reg[14]+i));
1190 for(int i=0; i<len; i+=4)
1191 WriteLog(" --------");
1193 for(int i=0; i<len; i+=4)
1194 WriteLog(" %08X", GPUReadLong(gpu_reg[9]+4+i));
1197 /*if (gpu_pc == 0xF035C8)
1199 WriteLog("\n--> GPU PC: F035C8 (#%d)\n", testCount++);
1201 GPUDumpDisassembly();
1206 // gpu_reset_stats();
1207 static char buffer[512];
1208 dasmjag(JAGUAR_GPU, buffer, gpu_pc);
1209 WriteLog("GPU: [%08X] %s (RM=%08X, RN=%08X) -> ", gpu_pc, buffer, RM, RN);
1211 //$E400 -> 1110 01 -> $39 -> 57
1214 gpu_opcode[index]();
1216 // gpu2_opcode[index]();
1218 //GPU #3 (Doesn't show ATARI logo! #1 & #2 do...)
1220 // gpu3_opcode[index]();
1223 //GPU: [00F03548] jr nz,00F03560 (0xd561) (RM=00F03114, RN=00000004) -> --> JR: Branch taken.
1224 /*static bool firstTime = true;
1225 if (gpu_pc == 0xF03548 && firstTime)
1228 // firstTime = false;
1230 //static char buffer[512];
1232 //while (k<0xF0356C)
1235 //k += dasmjag(JAGUAR_GPU, buffer, k);
1236 //WriteLog("GPU: [%08X] %s\n", oldk, buffer);
1238 // gpu_start_log = 1;
1240 //GPU: [00F0354C] jump nz,(r29) (0xd3a1) (RM=00F03314, RN=00000004) -> (RM=00F03314, RN=00000004)
1241 /*if (gpu_pc == 0xF0354C)
1242 gpu_flag_z = 0;//, gpu_start_log = 1;//*/
1244 cycles -= gpu_opcode_cycles[index];
1245 gpu_opcode_use[index]++;
1247 WriteLog("(RM=%08X, RN=%08X)\n", RM, RN);//*/
1248 if ((gpu_pc < 0xF03000 || gpu_pc > 0xF03FFF) && !tripwire)
1250 WriteLog("GPU: Executing outside local RAM! GPU_PC: %08X\n", gpu_pc);
1263 GPU opcodes use (offset punch--vertically below bad guy):
1285 load_r14_indexed 1183
1286 load_r15_indexed 1125
1289 store_r14_indexed 320
1297 static void gpu_opcode_jump(void)
1300 char * condition[32] =
1301 { "T", "nz", "z", "???", "nc", "nc nz", "nc z", "???", "c", "c nz",
1302 "c z", "???", "???", "???", "???", "???", "???", "???", "???",
1303 "???", "nn", "nn nz", "nn z", "???", "n", "n nz", "n z", "???",
1304 "???", "???", "???", "F" };
1306 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);
1309 /* gpu_flag_c = (gpu_flag_c ? 1 : 0);
1310 gpu_flag_z = (gpu_flag_z ? 1 : 0);
1311 gpu_flag_n = (gpu_flag_n ? 1 : 0);*/
1312 // KLUDGE: Used by BRANCH_CONDITION
1313 uint32 jaguar_flags = (gpu_flag_n << 2) | (gpu_flag_c << 1) | gpu_flag_z;
1315 if (BRANCH_CONDITION(IMM_2))
1319 WriteLog("Branched!\n");
1322 WriteLog(" --> JUMP: Branch taken.\n");
1323 uint32 delayed_pc = RM;
1325 gpu_pc = delayed_pc;
1326 /* uint16 opcode = GPUReadWord(gpu_pc, GPU);
1327 gpu_opcode_first_parameter = (opcode >> 5) & 0x1F;
1328 gpu_opcode_second_parameter = opcode & 0x1F;
1330 gpu_pc = delayed_pc;
1331 gpu_opcode[opcode>>10]();//*/
1336 WriteLog("Branch NOT taken.\n");
1340 static void gpu_opcode_jr(void)
1343 char * condition[32] =
1344 { "T", "nz", "z", "???", "nc", "nc nz", "nc z", "???", "c", "c nz",
1345 "c z", "???", "???", "???", "???", "???", "???", "???", "???",
1346 "???", "nn", "nn nz", "nn z", "???", "n", "n nz", "n z", "???",
1347 "???", "???", "???", "F" };
1349 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);
1351 /* if (CONDITION(jaguar.op & 31))
1353 INT32 r1 = (INT8)((jaguar.op >> 2) & 0xF8) >> 2;
1354 UINT32 newpc = jaguar.PC + r1;
1356 jaguar.op = ROPCODE(jaguar.PC);
1358 (*jaguar.table[jaguar.op >> 10])();
1360 jaguar_icount -= 3; // 3 wait states guaranteed
1363 /* gpu_flag_n = (gpu_flag_n ? 1 : 0);
1364 gpu_flag_c = (gpu_flag_c ? 1 : 0);
1365 gpu_flag_z = (gpu_flag_z ? 1 : 0);*/
1366 // KLUDGE: Used by BRANCH_CONDITION
1367 uint32 jaguar_flags = (gpu_flag_n << 2) | (gpu_flag_c << 1) | gpu_flag_z;
1369 if (BRANCH_CONDITION(IMM_2))
1373 WriteLog("Branched!\n");
1376 WriteLog(" --> JR: Branch taken.\n");
1377 int32 offset = (IMM_1 & 0x10 ? 0xFFFFFFF0 | IMM_1 : IMM_1); // Sign extend IMM_1
1378 int32 delayed_pc = gpu_pc + (offset * 2);
1380 gpu_pc = delayed_pc;
1381 /* uint16 opcode = GPUReadWord(gpu_pc, GPU);
1382 gpu_opcode_first_parameter = (opcode >> 5) & 0x1F;
1383 gpu_opcode_second_parameter = opcode & 0x1F;
1385 gpu_pc = delayed_pc;
1386 gpu_opcode[opcode>>10]();//*/
1391 WriteLog("Branch NOT taken.\n");
1395 static void gpu_opcode_add(void)
1399 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);
1401 UINT32 res = RN + RM;
1402 CLR_ZNC; SET_ZNC_ADD(RN, RM, res);
1406 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);
1410 static void gpu_opcode_addc(void)
1414 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);
1416 /* int dreg = jaguar.op & 31;
1417 UINT32 r1 = jaguar.r[(jaguar.op >> 5) & 31];
1418 UINT32 r2 = jaguar.r[dreg];
1419 UINT32 res = r2 + r1 + ((jaguar.FLAGS >> 1) & 1);
1420 jaguar.r[dreg] = res;
1421 CLR_ZNC; SET_ZNC_ADD(r2,r1,res);*/
1423 UINT32 res = RN + RM + gpu_flag_c;
1424 UINT32 carry = gpu_flag_c;
1425 // SET_ZNC_ADD(RN, RM, res); //???BUG??? Yes!
1426 SET_ZNC_ADD(RN + carry, RM, res);
1427 // SET_ZNC_ADD(RN, RM + carry, res);
1431 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);
1435 static void gpu_opcode_addq(void)
1439 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);
1441 UINT32 r1 = gpu_convert_zero[IMM_1];
1442 UINT32 res = RN + r1;
1443 CLR_ZNC; SET_ZNC_ADD(RN, r1, res);
1447 WriteLog("[NCZ:%u%u%u, R%02u=%08X]\n", gpu_flag_n, gpu_flag_c, gpu_flag_z, IMM_2, RN);
1451 static void gpu_opcode_addqt(void)
1453 #ifdef GPU_DIS_ADDQT
1455 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);
1457 RN += gpu_convert_zero[IMM_1];
1458 #ifdef GPU_DIS_ADDQT
1460 WriteLog("[NCZ:%u%u%u, R%02u=%08X]\n", gpu_flag_n, gpu_flag_c, gpu_flag_z, IMM_2, RN);
1464 static void gpu_opcode_sub(void)
1468 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);
1470 UINT32 res = RN - RM;
1471 SET_ZNC_SUB(RN, RM, res);
1475 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);
1479 static void gpu_opcode_subc(void)
1483 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);
1485 UINT32 res = RN - RM - gpu_flag_c;
1486 UINT32 borrow = gpu_flag_c;
1487 // SET_ZNC_SUB(RN, RM, res); //???BUG??? YES!!!
1488 //No matter how you do it, there is a problem. With below, it's 0-0 with carry,
1489 //and the one below it it's FFFFFFFF - FFFFFFFF with carry... !!! FIX !!!
1490 // SET_ZNC_SUB(RN - borrow, RM, res);
1491 SET_ZNC_SUB(RN, RM + borrow, res);
1495 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);
1499 N = 5, M = 3, 3 - 5 = -2, C = 1... Or, in our case:
1500 N = 0, M = 1, 0 - 1 = -1, C = 0!
1502 #define SET_C_SUB(a,b) (gpu_flag_c = ((UINT32)(b) > (UINT32)(a)))
1503 #define SET_ZN(r) SET_N(r); SET_Z(r)
1504 #define SET_ZNC_ADD(a,b,r) SET_N(r); SET_Z(r); SET_C_ADD(a,b)
1505 #define SET_ZNC_SUB(a,b,r) SET_N(r); SET_Z(r); SET_C_SUB(a,b)
1507 static void gpu_opcode_subq(void)
1511 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);
1513 UINT32 r1 = gpu_convert_zero[IMM_1];
1514 UINT32 res = RN - r1;
1515 SET_ZNC_SUB(RN, r1, res);
1519 WriteLog("[NCZ:%u%u%u, R%02u=%08X]\n", gpu_flag_n, gpu_flag_c, gpu_flag_z, IMM_2, RN);
1523 static void gpu_opcode_subqt(void)
1525 #ifdef GPU_DIS_SUBQT
1527 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);
1529 RN -= gpu_convert_zero[IMM_1];
1530 #ifdef GPU_DIS_SUBQT
1532 WriteLog("[NCZ:%u%u%u, R%02u=%08X]\n", gpu_flag_n, gpu_flag_c, gpu_flag_z, IMM_2, RN);
1536 static void gpu_opcode_cmp(void)
1540 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);
1542 UINT32 res = RN - RM;
1543 SET_ZNC_SUB(RN, RM, res);
1546 WriteLog("[NCZ:%u%u%u]\n", gpu_flag_n, gpu_flag_c, gpu_flag_z);
1550 static void gpu_opcode_cmpq(void)
1552 static int32 sqtable[32] =
1553 { 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 };
1556 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);
1558 UINT32 r1 = sqtable[IMM_1 & 0x1F]; // I like this better -> (INT8)(jaguar.op >> 2) >> 3;
1559 UINT32 res = RN - r1;
1560 SET_ZNC_SUB(RN, r1, res);
1563 WriteLog("[NCZ:%u%u%u]\n", gpu_flag_n, gpu_flag_c, gpu_flag_z);
1567 static void gpu_opcode_and(void)
1571 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);
1577 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);
1581 static void gpu_opcode_or(void)
1585 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);
1591 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);
1595 static void gpu_opcode_xor(void)
1599 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);
1605 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);
1609 static void gpu_opcode_not(void)
1613 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);
1619 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);
1623 static void gpu_opcode_move_pc(void)
1625 #ifdef GPU_DIS_MOVEPC
1627 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);
1629 // Should be previous PC--this might not always be previous instruction!
1630 // Then again, this will point right at the *current* instruction, i.e., MOVE PC,R!
1632 #ifdef GPU_DIS_MOVEPC
1634 WriteLog("[NCZ:%u%u%u, R%02u=%08X]\n", gpu_flag_n, gpu_flag_c, gpu_flag_z, IMM_2, RN);
1638 static void gpu_opcode_sat8(void)
1642 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);
1644 RN = ((int32)RN < 0 ? 0 : (RN > 0xFF ? 0xFF : RN));
1648 WriteLog("[NCZ:%u%u%u, R%02u=%08X]\n", gpu_flag_n, gpu_flag_c, gpu_flag_z, IMM_2, RN);
1652 static void gpu_opcode_sat16(void)
1654 RN = ((int32)RN < 0 ? 0 : (RN > 0xFFFF ? 0xFFFF : RN));
1658 static void gpu_opcode_sat24(void)
1660 RN = ((int32)RN < 0 ? 0 : (RN > 0xFFFFFF ? 0xFFFFFF : RN));
1664 static void gpu_opcode_store_r14_indexed(void)
1666 #ifdef GPU_DIS_STORE14I
1668 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));
1670 GPUWriteLong(gpu_reg[14] + (gpu_convert_zero[IMM_1] << 2), RN, GPU);
1673 static void gpu_opcode_store_r15_indexed(void)
1675 #ifdef GPU_DIS_STORE15I
1677 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));
1679 GPUWriteLong(gpu_reg[15] + (gpu_convert_zero[IMM_1] << 2), RN, GPU);
1682 static void gpu_opcode_load_r14_ri(void)
1684 #ifdef GPU_DIS_LOAD14R
1686 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);
1688 RN = GPUReadLong(gpu_reg[14] + RM, GPU);
1689 #ifdef GPU_DIS_LOAD14R
1691 WriteLog("[NCZ:%u%u%u, R%02u=%08X]\n", gpu_flag_n, gpu_flag_c, gpu_flag_z, IMM_2, RN);
1695 static void gpu_opcode_load_r15_ri(void)
1697 #ifdef GPU_DIS_LOAD15R
1699 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);
1701 RN = GPUReadLong(gpu_reg[15] + RM, GPU);
1702 #ifdef GPU_DIS_LOAD15R
1704 WriteLog("[NCZ:%u%u%u, R%02u=%08X]\n", gpu_flag_n, gpu_flag_c, gpu_flag_z, IMM_2, RN);
1708 static void gpu_opcode_store_r14_ri(void)
1710 #ifdef GPU_DIS_STORE14R
1712 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]);
1714 GPUWriteLong(gpu_reg[14] + RM, RN, GPU);
1717 static void gpu_opcode_store_r15_ri(void)
1719 #ifdef GPU_DIS_STORE15R
1721 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]);
1723 GPUWriteLong(gpu_reg[15] + RM, RN, GPU);
1726 static void gpu_opcode_nop(void)
1730 WriteLog("%06X: NOP [NCZ:%u%u%u]\n", gpu_pc-2, gpu_flag_n, gpu_flag_c, gpu_flag_z);
1734 static void gpu_opcode_pack(void)
1738 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);
1742 //BUG! if (RM == 0) // Pack
1743 if (IMM_1 == 0) // Pack
1744 RN = ((val >> 10) & 0x0000F000) | ((val >> 5) & 0x00000F00) | (val & 0x000000FF);
1746 RN = ((val & 0x0000F000) << 10) | ((val & 0x00000F00) << 5) | (val & 0x000000FF);
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_storeb(void)
1755 #ifdef GPU_DIS_STOREB
1757 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);
1760 // Would appear to be so...!
1761 if ((RM >= 0xF03000) && (RM <= 0xF03FFF))
1762 GPUWriteLong(RM, RN & 0xFF, GPU);
1764 JaguarWriteByte(RM, RN, GPU);
1767 static void gpu_opcode_storew(void)
1769 #ifdef GPU_DIS_STOREW
1771 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);
1773 if ((RM >= 0xF03000) && (RM <= 0xF03FFF))
1774 GPUWriteLong(RM, RN & 0xFFFF, GPU);
1776 JaguarWriteWord(RM, RN, GPU);
1779 static void gpu_opcode_store(void)
1781 #ifdef GPU_DIS_STORE
1783 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);
1785 GPUWriteLong(RM, RN, GPU);
1788 static void gpu_opcode_storep(void)
1790 GPUWriteLong(RM + 0, gpu_hidata, GPU);
1791 GPUWriteLong(RM + 4, RN, GPU);
1794 static void gpu_opcode_loadb(void)
1796 #ifdef GPU_DIS_LOADB
1798 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);
1800 if ((RM >= 0xF03000) && (RM <= 0xF03FFF))
1801 RN = GPUReadLong(RM, GPU) & 0xFF;
1803 RN = JaguarReadByte(RM, GPU);
1804 #ifdef GPU_DIS_LOADB
1806 WriteLog("[NCZ:%u%u%u, R%02u=%08X]\n", gpu_flag_n, gpu_flag_c, gpu_flag_z, IMM_2, RN);
1810 static void gpu_opcode_loadw(void)
1812 #ifdef GPU_DIS_LOADW
1814 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);
1816 if ((RM >= 0xF03000) && (RM <= 0xF03FFF))
1817 RN = GPUReadLong(RM, GPU) & 0xFFFF;
1819 RN = JaguarReadWord(RM, GPU);
1820 #ifdef GPU_DIS_LOADW
1822 WriteLog("[NCZ:%u%u%u, R%02u=%08X]\n", gpu_flag_n, gpu_flag_c, gpu_flag_z, IMM_2, RN);
1826 static void gpu_opcode_load(void)
1830 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);
1832 RN = GPUReadLong(RM, GPU);
1835 WriteLog("[NCZ:%u%u%u, R%02u=%08X]\n", gpu_flag_n, gpu_flag_c, gpu_flag_z, IMM_2, RN);
1839 static void gpu_opcode_loadp(void)
1841 gpu_hidata = GPUReadLong(RM + 0, GPU);
1842 RN = GPUReadLong(RM + 4, GPU);
1845 static void gpu_opcode_load_r14_indexed(void)
1847 #ifdef GPU_DIS_LOAD14I
1849 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);
1851 RN = GPUReadLong(gpu_reg[14] + (gpu_convert_zero[IMM_1] << 2), GPU);
1852 #ifdef GPU_DIS_LOAD14I
1854 WriteLog("[NCZ:%u%u%u, R%02u=%08X]\n", gpu_flag_n, gpu_flag_c, gpu_flag_z, IMM_2, RN);
1858 static void gpu_opcode_load_r15_indexed(void)
1860 #ifdef GPU_DIS_LOAD15I
1862 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);
1864 RN = GPUReadLong(gpu_reg[15] + (gpu_convert_zero[IMM_1] << 2), GPU);
1865 #ifdef GPU_DIS_LOAD15I
1867 WriteLog("[NCZ:%u%u%u, R%02u=%08X]\n", gpu_flag_n, gpu_flag_c, gpu_flag_z, IMM_2, RN);
1871 static void gpu_opcode_movei(void)
1873 #ifdef GPU_DIS_MOVEI
1875 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);
1877 // This instruction is followed by 32-bit value in LSW / MSW format...
1878 RN = (uint32)GPUReadWord(gpu_pc, GPU) | ((uint32)GPUReadWord(gpu_pc + 2, GPU) << 16);
1880 #ifdef GPU_DIS_MOVEI
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_moveta(void)
1888 #ifdef GPU_DIS_MOVETA
1890 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);
1893 #ifdef GPU_DIS_MOVETA
1895 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);
1899 static void gpu_opcode_movefa(void)
1901 #ifdef GPU_DIS_MOVEFA
1903 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);
1906 #ifdef GPU_DIS_MOVEFA
1908 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);
1912 static void gpu_opcode_move(void)
1916 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);
1921 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);
1925 static void gpu_opcode_moveq(void)
1927 #ifdef GPU_DIS_MOVEQ
1929 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);
1932 #ifdef GPU_DIS_MOVEQ
1934 WriteLog("[NCZ:%u%u%u, R%02u=%08X]\n", gpu_flag_n, gpu_flag_c, gpu_flag_z, IMM_2, RN);
1938 static void gpu_opcode_resmac(void)
1943 static void gpu_opcode_imult(void)
1945 #ifdef GPU_DIS_IMULT
1947 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);
1949 RN = (int16)RN * (int16)RM;
1951 #ifdef GPU_DIS_IMULT
1953 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);
1957 static void gpu_opcode_mult(void)
1961 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);
1963 RN = (uint16)RM * (uint16)RN;
1967 WriteLog("[NCZ:%u%u%u, R%02u=%08X, R%02u=%08X]\n", gpu_flag_n, gpu_flag_c, gpu_flag_z, IMM_1, RM, IMM_2, RN);
1971 static void gpu_opcode_bclr(void)
1975 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);
1977 UINT32 res = RN & ~(1 << IMM_1);
1982 WriteLog("[NCZ:%u%u%u, R%02u=%08X]\n", gpu_flag_n, gpu_flag_c, gpu_flag_z, IMM_2, RN);
1986 static void gpu_opcode_btst(void)
1990 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);
1992 gpu_flag_z = (~RN >> IMM_1) & 1;
1995 WriteLog("[NCZ:%u%u%u, R%02u=%08X]\n", gpu_flag_n, gpu_flag_c, gpu_flag_z, IMM_2, RN);
1999 static void gpu_opcode_bset(void)
2003 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);
2005 UINT32 res = RN | (1 << IMM_1);
2010 WriteLog("[NCZ:%u%u%u, R%02u=%08X]\n", gpu_flag_n, gpu_flag_c, gpu_flag_z, IMM_2, RN);
2014 static void gpu_opcode_imacn(void)
2016 uint32 res = (int16)RM * (int16)(RN);
2020 static void gpu_opcode_mtoi(void)
2023 uint32 res = RN = (((INT32)_RM >> 8) & 0xFF800000) | (_RM & 0x007FFFFF);
2027 static void gpu_opcode_normi(void)
2034 while ((_RM & 0xFFC00000) == 0)
2039 while ((_RM & 0xFF800000) != 0)
2049 static void gpu_opcode_mmult(void)
2051 int count = gpu_matrix_control & 0x0F; // Matrix width
2052 uint32 addr = gpu_pointer_to_matrix; // In the GPU's RAM
2056 if (gpu_matrix_control & 0x10) // Column stepping
2058 for(int i=0; i<count; i++)
2062 a = (int16)((gpu_alternate_reg[IMM_1 + (i >> 1)] >> 16) & 0xFFFF);
2064 a = (int16)(gpu_alternate_reg[IMM_1 + (i >> 1)] & 0xFFFF);
2066 int16 b = ((int16)GPUReadWord(addr + 2, GPU));
2071 else // Row stepping
2073 for(int i=0; i<count; i++)
2077 a = (int16)((gpu_alternate_reg[IMM_1 + (i >> 1)] >> 16) & 0xFFFF);
2079 a = (int16)(gpu_alternate_reg[IMM_1 + (i >> 1)] & 0xFFFF);
2081 int16 b = ((int16)GPUReadWord(addr + 2, GPU));
2086 RN = res = (int32)accum;
2087 // carry flag to do (out of the last add)
2091 static void gpu_opcode_abs(void)
2095 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);
2097 gpu_flag_c = RN >> 31;
2098 if (RN == 0x80000000)
2099 //Is 0x80000000 a positive number? If so, then we need to set C to 0 as well!
2100 gpu_flag_n = 1, gpu_flag_z = 0;
2105 gpu_flag_n = 0; SET_FLAG_Z(RN);
2109 WriteLog("[NCZ:%u%u%u, R%02u=%08X]\n", gpu_flag_n, gpu_flag_c, gpu_flag_z, IMM_2, RN);
2113 static void gpu_opcode_div(void) // RN / RM
2117 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);
2119 // NOTE: remainder is NOT calculated correctly here!
2120 // The original tried to get it right by checking to see if the
2121 // remainder was negative, but that's too late...
2122 // The code there should do it now, but I'm not 100% sure...
2126 if (gpu_div_control & 0x01) // 16.16 division
2128 RN = ((UINT64)RN << 16) / RM;
2129 gpu_remain = ((UINT64)RN << 16) % RM;
2134 gpu_remain = RN % RM;
2137 if ((gpu_remain - RM) & 0x80000000) // If the result would have been negative...
2138 gpu_remain -= RM; // Then make it negative!
2148 if (gpu_div_control & 1)
2150 gpu_remain = (((uint64)_RN) << 16) % _RM;
2151 if (gpu_remain&0x80000000)
2153 RN = (((uint64)_RN) << 16) / _RM;
2157 gpu_remain = _RN % _RM;
2158 if (gpu_remain&0x80000000)
2167 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);
2171 static void gpu_opcode_imultn(void)
2173 uint32 res = (int32)((int16)RN * (int16)RM);
2174 gpu_acc = (int32)res;
2179 static void gpu_opcode_neg(void)
2183 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);
2186 SET_ZNC_SUB(0, RN, res);
2190 WriteLog("[NCZ:%u%u%u, R%02u=%08X]\n", gpu_flag_n, gpu_flag_c, gpu_flag_z, IMM_2, RN);
2194 static void gpu_opcode_shlq(void)
2198 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);
2200 // Was a bug here...
2201 // (Look at Aaron's code: If r1 = 32, then 32 - 32 = 0 which is wrong!)
2202 INT32 r1 = 32 - IMM_1;
2203 UINT32 res = RN << r1;
2204 SET_ZN(res); gpu_flag_c = (RN >> 31) & 1;
2208 WriteLog("[NCZ:%u%u%u, R%02u=%08X]\n", gpu_flag_n, gpu_flag_c, gpu_flag_z, IMM_2, RN);
2212 static void gpu_opcode_shrq(void)
2216 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);
2218 INT32 r1 = gpu_convert_zero[IMM_1];
2219 UINT32 res = RN >> r1;
2220 SET_ZN(res); gpu_flag_c = RN & 1;
2224 WriteLog("[NCZ:%u%u%u, R%02u=%08X]\n", gpu_flag_n, gpu_flag_c, gpu_flag_z, IMM_2, RN);
2228 static void gpu_opcode_ror(void)
2232 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);
2234 UINT32 r1 = RM & 0x1F;
2235 UINT32 res = (RN >> r1) | (RN << (32 - r1));
2236 SET_ZN(res); gpu_flag_c = (RN >> 31) & 1;
2240 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);
2244 static void gpu_opcode_rorq(void)
2248 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);
2250 UINT32 r1 = gpu_convert_zero[IMM_1 & 0x1F];
2252 UINT32 res = (r2 >> r1) | (r2 << (32 - r1));
2254 SET_ZN(res); gpu_flag_c = (r2 >> 31) & 0x01;
2257 WriteLog("[NCZ:%u%u%u, R%02u=%08X]\n", gpu_flag_n, gpu_flag_c, gpu_flag_z, IMM_2, RN);
2261 static void gpu_opcode_sha(void)
2263 /* int dreg = jaguar.op & 31;
2264 INT32 r1 = (INT32)jaguar.r[(jaguar.op >> 5) & 31];
2265 UINT32 r2 = jaguar.r[dreg];
2271 res = (r1 <= -32) ? 0 : (r2 << -r1);
2272 jaguar.FLAGS |= (r2 >> 30) & 2;
2276 res = (r1 >= 32) ? ((INT32)r2 >> 31) : ((INT32)r2 >> r1);
2277 jaguar.FLAGS |= (r2 << 1) & 2;
2279 jaguar.r[dreg] = res;
2284 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);
2290 res = ((INT32)RM <= -32) ? 0 : (RN << -(INT32)RM);
2291 gpu_flag_c = RN >> 31;
2295 res = ((INT32)RM >= 32) ? ((INT32)RN >> 31) : ((INT32)RN >> (INT32)RM);
2296 gpu_flag_c = RN & 0x01;
2302 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);
2305 /* int32 sRM=(int32)RM;
2311 if (shift>=32) shift=32;
2312 gpu_flag_c=(_RN&0x80000000)>>31;
2322 if (shift>=32) shift=32;
2326 _RN=((int32)_RN)>>1;
2335 static void gpu_opcode_sharq(void)
2337 #ifdef GPU_DIS_SHARQ
2339 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);
2341 UINT32 res = (INT32)RN >> gpu_convert_zero[IMM_1];
2342 SET_ZN(res); gpu_flag_c = RN & 0x01;
2344 #ifdef GPU_DIS_SHARQ
2346 WriteLog("[NCZ:%u%u%u, R%02u=%08X]\n", gpu_flag_n, gpu_flag_c, gpu_flag_z, IMM_2, RN);
2350 static void gpu_opcode_sh(void)
2354 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);
2356 if (RM & 0x80000000) // Shift left
2358 gpu_flag_c = RN >> 31;
2359 RN = ((int32)RM <= -32 ? 0 : RN << -(int32)RM);
2363 gpu_flag_c = RN & 0x01;
2364 RN = (RM >= 32 ? 0 : RN >> RM);
2369 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);
2373 //Temporary: Testing only!
2374 //#include "gpu2.cpp"
2375 //#include "gpu3.cpp"