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...
20 // For GPU dissasembly...
40 #define GPU_DIS_LOAD14I
41 #define GPU_DIS_LOAD14R
42 #define GPU_DIS_LOAD15I
43 #define GPU_DIS_LOAD15R
45 #define GPU_DIS_MOVEFA
47 #define GPU_DIS_MOVEPC
48 #define GPU_DIS_MOVETA
65 #define GPU_DIS_STOREB
66 #define GPU_DIS_STOREW
67 #define GPU_DIS_STORE14I
68 #define GPU_DIS_STORE14R
69 #define GPU_DIS_STORE15I
70 #define GPU_DIS_STORE15R
77 bool doGPUDis = false;
78 //bool doGPUDis = true;
81 GPU opcodes use (BIOS flying ATARI logo):
123 #define CINT0FLAG 0x0200
124 #define CINT1FLAG 0x0400
125 #define CINT2FLAG 0x0800
126 #define CINT3FLAG 0x1000
127 #define CINT4FLAG 0x2000
128 #define CINT04FLAGS (CINT0FLAG | CINT1FLAG | CINT2FLAG | CINT3FLAG | CINT4FLAG)
132 #define ZERO_FLAG 0x0001
133 #define CARRY_FLAG 0x0002
134 #define NEGA_FLAG 0x0004
136 #define INT_ENA0 0x0010
137 #define INT_ENA1 0x0020
138 #define INT_ENA2 0x0040
139 #define INT_ENA3 0x0080
140 #define INT_ENA4 0x0100
141 #define INT_CLR0 0x0200
142 #define INT_CLR1 0x0400
143 #define INT_CLR2 0x0800
144 #define INT_CLR3 0x1000
145 #define INT_CLR4 0x2000
146 #define REGPAGE 0x4000
149 // External global variables
151 extern int start_logging;
152 extern int gpu_start_log;
154 // Private function prototypes
156 void GPUUpdateRegisterBanks(void);
158 void GPUDumpDisassembly(void);
159 void GPUDumpRegisters(void);
160 void GPUDumpMemory(void);
162 static void gpu_opcode_add(void);
163 static void gpu_opcode_addc(void);
164 static void gpu_opcode_addq(void);
165 static void gpu_opcode_addqt(void);
166 static void gpu_opcode_sub(void);
167 static void gpu_opcode_subc(void);
168 static void gpu_opcode_subq(void);
169 static void gpu_opcode_subqt(void);
170 static void gpu_opcode_neg(void);
171 static void gpu_opcode_and(void);
172 static void gpu_opcode_or(void);
173 static void gpu_opcode_xor(void);
174 static void gpu_opcode_not(void);
175 static void gpu_opcode_btst(void);
176 static void gpu_opcode_bset(void);
177 static void gpu_opcode_bclr(void);
178 static void gpu_opcode_mult(void);
179 static void gpu_opcode_imult(void);
180 static void gpu_opcode_imultn(void);
181 static void gpu_opcode_resmac(void);
182 static void gpu_opcode_imacn(void);
183 static void gpu_opcode_div(void);
184 static void gpu_opcode_abs(void);
185 static void gpu_opcode_sh(void);
186 static void gpu_opcode_shlq(void);
187 static void gpu_opcode_shrq(void);
188 static void gpu_opcode_sha(void);
189 static void gpu_opcode_sharq(void);
190 static void gpu_opcode_ror(void);
191 static void gpu_opcode_rorq(void);
192 static void gpu_opcode_cmp(void);
193 static void gpu_opcode_cmpq(void);
194 static void gpu_opcode_sat8(void);
195 static void gpu_opcode_sat16(void);
196 static void gpu_opcode_move(void);
197 static void gpu_opcode_moveq(void);
198 static void gpu_opcode_moveta(void);
199 static void gpu_opcode_movefa(void);
200 static void gpu_opcode_movei(void);
201 static void gpu_opcode_loadb(void);
202 static void gpu_opcode_loadw(void);
203 static void gpu_opcode_load(void);
204 static void gpu_opcode_loadp(void);
205 static void gpu_opcode_load_r14_indexed(void);
206 static void gpu_opcode_load_r15_indexed(void);
207 static void gpu_opcode_storeb(void);
208 static void gpu_opcode_storew(void);
209 static void gpu_opcode_store(void);
210 static void gpu_opcode_storep(void);
211 static void gpu_opcode_store_r14_indexed(void);
212 static void gpu_opcode_store_r15_indexed(void);
213 static void gpu_opcode_move_pc(void);
214 static void gpu_opcode_jump(void);
215 static void gpu_opcode_jr(void);
216 static void gpu_opcode_mmult(void);
217 static void gpu_opcode_mtoi(void);
218 static void gpu_opcode_normi(void);
219 static void gpu_opcode_nop(void);
220 static void gpu_opcode_load_r14_ri(void);
221 static void gpu_opcode_load_r15_ri(void);
222 static void gpu_opcode_store_r14_ri(void);
223 static void gpu_opcode_store_r15_ri(void);
224 static void gpu_opcode_sat24(void);
225 static void gpu_opcode_pack(void);
227 // This is wrong, since it doesn't take pipeline effects into account. !!! FIX !!!
228 /*uint8 gpu_opcode_cycles[64] =
230 3, 3, 3, 3, 3, 3, 3, 3,
231 3, 3, 3, 3, 3, 3, 3, 3,
232 3, 3, 1, 3, 1, 18, 3, 3,
233 3, 3, 3, 3, 3, 3, 3, 3,
234 3, 3, 2, 2, 2, 2, 3, 4,
235 5, 4, 5, 6, 6, 1, 1, 1,
236 1, 2, 2, 2, 1, 1, 9, 3,
237 3, 1, 6, 6, 2, 2, 3, 3
239 //Here's a QnD kludge...
240 //This is wrong, wrong, WRONG, but it seems to work for the time being...
241 //(That is, it fixes Flip Out which relies on GPU timing rather than semaphores. Bad developers! Bad!)
242 //What's needed here is a way to take pipeline effects into account (including pipeline stalls!)...
243 /*uint8 gpu_opcode_cycles[64] =
245 1, 1, 1, 1, 1, 1, 1, 1,
246 1, 1, 1, 1, 1, 1, 1, 1,
247 1, 1, 1, 1, 1, 9, 1, 1,
248 1, 1, 1, 1, 1, 1, 1, 1,
249 1, 1, 1, 1, 1, 1, 1, 2,
250 2, 2, 2, 3, 3, 1, 1, 1,
251 1, 1, 1, 1, 1, 1, 4, 1,
252 1, 1, 3, 3, 1, 1, 1, 1
254 uint8 gpu_opcode_cycles[64] =
256 1, 1, 1, 1, 1, 1, 1, 1,
257 1, 1, 1, 1, 1, 1, 1, 1,
258 1, 1, 1, 1, 1, 1, 1, 1,
259 1, 1, 1, 1, 1, 1, 1, 1,
260 1, 1, 1, 1, 1, 1, 1, 1,
261 1, 1, 1, 1, 1, 1, 1, 1,
262 1, 1, 1, 1, 1, 1, 1, 1,
263 1, 1, 1, 1, 1, 1, 1, 1
266 void (*gpu_opcode[64])()=
268 gpu_opcode_add, gpu_opcode_addc, gpu_opcode_addq, gpu_opcode_addqt,
269 gpu_opcode_sub, gpu_opcode_subc, gpu_opcode_subq, gpu_opcode_subqt,
270 gpu_opcode_neg, gpu_opcode_and, gpu_opcode_or, gpu_opcode_xor,
271 gpu_opcode_not, gpu_opcode_btst, gpu_opcode_bset, gpu_opcode_bclr,
272 gpu_opcode_mult, gpu_opcode_imult, gpu_opcode_imultn, gpu_opcode_resmac,
273 gpu_opcode_imacn, gpu_opcode_div, gpu_opcode_abs, gpu_opcode_sh,
274 gpu_opcode_shlq, gpu_opcode_shrq, gpu_opcode_sha, gpu_opcode_sharq,
275 gpu_opcode_ror, gpu_opcode_rorq, gpu_opcode_cmp, gpu_opcode_cmpq,
276 gpu_opcode_sat8, gpu_opcode_sat16, gpu_opcode_move, gpu_opcode_moveq,
277 gpu_opcode_moveta, gpu_opcode_movefa, gpu_opcode_movei, gpu_opcode_loadb,
278 gpu_opcode_loadw, gpu_opcode_load, gpu_opcode_loadp, gpu_opcode_load_r14_indexed,
279 gpu_opcode_load_r15_indexed, gpu_opcode_storeb, gpu_opcode_storew, gpu_opcode_store,
280 gpu_opcode_storep, gpu_opcode_store_r14_indexed, gpu_opcode_store_r15_indexed, gpu_opcode_move_pc,
281 gpu_opcode_jump, gpu_opcode_jr, gpu_opcode_mmult, gpu_opcode_mtoi,
282 gpu_opcode_normi, gpu_opcode_nop, gpu_opcode_load_r14_ri, gpu_opcode_load_r15_ri,
283 gpu_opcode_store_r14_ri, gpu_opcode_store_r15_ri, gpu_opcode_sat24, gpu_opcode_pack,
286 static uint8 * gpu_ram_8;
288 static uint32 gpu_acc;
289 static uint32 gpu_remain;
290 static uint32 gpu_hidata;
291 static uint32 gpu_flags;
292 static uint32 gpu_matrix_control;
293 static uint32 gpu_pointer_to_matrix;
294 static uint32 gpu_data_organization;
295 static uint32 gpu_control;
296 static uint32 gpu_div_control;
297 // There is a distinct advantage to having these separated out--there's no need to clear
298 // a bit before writing a result. I.e., if the result of an operation leaves a zero in
299 // the carry flag, you don't have to zero gpu_flag_c before you can write that zero!
300 static uint8 gpu_flag_z, gpu_flag_n, gpu_flag_c;
301 static uint32 * gpu_reg_bank_0;
302 static uint32 * gpu_reg_bank_1;
303 static uint32 * gpu_reg;
304 static uint32 * gpu_alternate_reg;
306 static uint32 gpu_instruction;
307 static uint32 gpu_opcode_first_parameter;
308 static uint32 gpu_opcode_second_parameter;
310 #define GPU_RUNNING (gpu_control & 0x01)
312 #define RM gpu_reg[gpu_opcode_first_parameter]
313 #define RN gpu_reg[gpu_opcode_second_parameter]
314 #define ALTERNATE_RM gpu_alternate_reg[gpu_opcode_first_parameter]
315 #define ALTERNATE_RN gpu_alternate_reg[gpu_opcode_second_parameter]
316 #define IMM_1 gpu_opcode_first_parameter
317 #define IMM_2 gpu_opcode_second_parameter
319 #define SET_FLAG_Z(r) (gpu_flag_z = ((r) == 0));
320 #define SET_FLAG_N(r) (gpu_flag_n = (((UINT32)(r) >> 31) & 0x01));
322 #define RESET_FLAG_Z() gpu_flag_z = 0;
323 #define RESET_FLAG_N() gpu_flag_n = 0;
324 #define RESET_FLAG_C() gpu_flag_c = 0;
326 #define CLR_Z (gpu_flag_z = 0)
327 #define CLR_ZN (gpu_flag_z = gpu_flag_n = 0)
328 #define CLR_ZNC (gpu_flag_z = gpu_flag_n = gpu_flag_c = 0)
329 #define SET_Z(r) (gpu_flag_z = ((r) == 0))
330 #define SET_N(r) (gpu_flag_n = (((UINT32)(r) >> 31) & 0x01))
331 #define SET_C_ADD(a,b) (gpu_flag_c = ((UINT32)(b) > (UINT32)(~(a))))
332 #define SET_C_SUB(a,b) (gpu_flag_c = ((UINT32)(b) > (UINT32)(a)))
333 #define SET_ZN(r) SET_N(r); SET_Z(r)
334 #define SET_ZNC_ADD(a,b,r) SET_N(r); SET_Z(r); SET_C_ADD(a,b)
335 #define SET_ZNC_SUB(a,b,r) SET_N(r); SET_Z(r); SET_C_SUB(a,b)
337 uint32 gpu_convert_zero[32] =
338 { 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 };
340 uint8 * branch_condition_table = 0;
341 #define BRANCH_CONDITION(x) branch_condition_table[(x) + ((jaguar_flags & 7) << 5)]
343 uint32 gpu_opcode_use[64];
345 char * gpu_opcode_str[64]=
347 "add", "addc", "addq", "addqt",
348 "sub", "subc", "subq", "subqt",
349 "neg", "and", "or", "xor",
350 "not", "btst", "bset", "bclr",
351 "mult", "imult", "imultn", "resmac",
352 "imacn", "div", "abs", "sh",
353 "shlq", "shrq", "sha", "sharq",
354 "ror", "rorq", "cmp", "cmpq",
355 "sat8", "sat16", "move", "moveq",
356 "moveta", "movefa", "movei", "loadb",
357 "loadw", "load", "loadp", "load_r14_indexed",
358 "load_r15_indexed", "storeb", "storew", "store",
359 "storep", "store_r14_indexed","store_r15_indexed","move_pc",
360 "jump", "jr", "mmult", "mtoi",
361 "normi", "nop", "load_r14_ri", "load_r15_ri",
362 "store_r14_ri", "store_r15_ri", "sat24", "pack",
365 static uint32 gpu_in_exec = 0;
366 static uint32 gpu_releaseTimeSlice_flag = 0;
368 void gpu_releaseTimeslice(void)
370 gpu_releaseTimeSlice_flag = 1;
373 uint32 gpu_get_pc(void)
378 void build_branch_condition_table(void)
380 if (!branch_condition_table)
382 branch_condition_table = (uint8 *)malloc(32 * 8 * sizeof(branch_condition_table[0]));
384 if (branch_condition_table)
386 for(int i=0; i<8; i++)
388 for(int j=0; j<32; j++)
395 if (!(i & ZERO_FLAG))
398 if (i & (CARRY_FLAG << (j >> 4)))
401 if (!(i & (CARRY_FLAG << (j >> 4))))
403 branch_condition_table[i * 32 + j] = result;
411 // GPU byte access (read)
413 uint8 GPUReadByte(uint32 offset, uint32 who/*=UNKNOWN*/)
415 if (offset >= 0xF02000 && offset <= 0xF020FF)
416 WriteLog("GPU: ReadByte--Attempt to read from GPU register file by %s!\n", whoName[who]);
418 if ((offset >= GPU_WORK_RAM_BASE) && (offset < GPU_WORK_RAM_BASE+0x1000))
419 return gpu_ram_8[offset & 0xFFF];
420 else if ((offset >= GPU_CONTROL_RAM_BASE) && (offset < GPU_CONTROL_RAM_BASE+0x20))
422 uint32 data = GPUReadLong(offset & 0xFFFFFFFC, who);
424 if ((offset & 0x03) == 0)
426 else if ((offset & 0x03) == 1)
427 return (data >> 16) & 0xFF;
428 else if ((offset & 0x03) == 2)
429 return (data >> 8) & 0xFF;
430 else if ((offset & 0x03) == 3)
434 return JaguarReadByte(offset, who);
438 // GPU word access (read)
440 uint16 GPUReadWord(uint32 offset, uint32 who/*=UNKNOWN*/)
442 if (offset >= 0xF02000 && offset <= 0xF020FF)
443 WriteLog("GPU: ReadWord--Attempt to read from GPU register file by %s!\n", whoName[who]);
445 if ((offset >= GPU_WORK_RAM_BASE) && (offset < GPU_WORK_RAM_BASE+0x1000))
448 uint16 data = ((uint16)gpu_ram_8[offset] << 8) | (uint16)gpu_ram_8[offset+1];
451 else if ((offset >= GPU_CONTROL_RAM_BASE) && (offset < GPU_CONTROL_RAM_BASE+0x20))
453 // This looks and smells wrong...
454 // But it *might* be OK...
455 if (offset & 0x01) // Catch cases 1 & 3... (unaligned read)
456 return (GPUReadByte(offset, who) << 8) | GPUReadByte(offset+1, who);
458 uint32 data = GPUReadLong(offset & 0xFFFFFFFC, who);
460 if (offset & 0x02) // Cases 0 & 2...
461 return data & 0xFFFF;
466 //TEMP--Mirror of F03000? No. Writes only...
467 //if (offset >= 0xF0B000 && offset <= 0xF0BFFF)
468 //WriteLog("[GPUR16] --> Possible GPU RAM mirror access by %s!", whoName[who]);
470 return JaguarReadWord(offset, who);
474 // GPU dword access (read)
476 uint32 GPUReadLong(uint32 offset, uint32 who/*=UNKNOWN*/)
478 if (offset >= 0xF02000 && offset <= 0xF020FF)
479 WriteLog("GPU: ReadLong--Attempt to read from GPU register file by %s!\n", whoName[who]);
481 // if ((offset >= GPU_WORK_RAM_BASE) && (offset < GPU_WORK_RAM_BASE + 0x1000))
482 if ((offset >= GPU_WORK_RAM_BASE) && (offset <= GPU_WORK_RAM_BASE + 0x0FFC))
485 return ((uint32)gpu_ram_8[offset] << 24) | ((uint32)gpu_ram_8[offset+1] << 16)
486 | ((uint32)gpu_ram_8[offset+2] << 8) | (uint32)gpu_ram_8[offset+3];//*/
487 // return GET32(gpu_ram_8, offset);
489 // else if ((offset >= GPU_CONTROL_RAM_BASE) && (offset < GPU_CONTROL_RAM_BASE+0x20))
490 else if ((offset >= GPU_CONTROL_RAM_BASE) && (offset <= GPU_CONTROL_RAM_BASE + 0x1C))
496 gpu_flag_c = (gpu_flag_c ? 1 : 0);
497 gpu_flag_z = (gpu_flag_z ? 1 : 0);
498 gpu_flag_n = (gpu_flag_n ? 1 : 0);
500 gpu_flags = (gpu_flags & 0xFFFFFFF8) | (gpu_flag_n << 2) | (gpu_flag_c << 1) | gpu_flag_z;
502 return gpu_flags & 0xFFFFC1FF;
504 return gpu_matrix_control;
506 return gpu_pointer_to_matrix;
508 return gpu_data_organization;
517 default: // unaligned long read
519 WriteLog("GPU: Read32--unaligned 32 bit read at %08X by %s.\n", GPU_CONTROL_RAM_BASE + offset, whoName[who]);
524 //TEMP--Mirror of F03000? No. Writes only...
525 //if (offset >= 0xF0B000 && offset <= 0xF0BFFF)
526 // WriteLog("[GPUR32] --> Possible GPU RAM mirror access by %s!\n", whoName[who]);
527 /*if (offset >= 0xF1D000 && offset <= 0xF1DFFF)
528 WriteLog("[GPUR32] --> Reading from Wavetable ROM!\n");//*/
530 return (JaguarReadWord(offset, who) << 16) | JaguarReadWord(offset + 2, who);
534 // GPU byte access (write)
536 void GPUWriteByte(uint32 offset, uint8 data, uint32 who/*=UNKNOWN*/)
538 if (offset >= 0xF02000 && offset <= 0xF020FF)
539 WriteLog("GPU: WriteByte--Attempt to write to GPU register file by %s!\n", whoName[who]);
541 if ((offset >= GPU_WORK_RAM_BASE) && (offset <= GPU_WORK_RAM_BASE + 0x0FFF))
543 gpu_ram_8[offset & 0xFFF] = data;
545 //This is the same stupid worthless code that was in the DSP!!! AARRRGGGGHHHHH!!!!!!
548 m68k_end_timeslice();
549 dsp_releaseTimeslice();
553 else if ((offset >= GPU_CONTROL_RAM_BASE) && (offset <= GPU_CONTROL_RAM_BASE + 0x1F))
555 uint32 reg = offset & 0x1C;
556 int bytenum = offset & 0x03;
558 //This is definitely wrong!
559 if ((reg >= 0x1C) && (reg <= 0x1F))
560 gpu_div_control = (gpu_div_control & (~(0xFF << (bytenum << 3)))) | (data << (bytenum << 3));
563 uint32 old_data = GPUReadLong(offset & 0xFFFFFFC, who);
564 bytenum = 3 - bytenum; // convention motorola !!!
565 old_data = (old_data & (~(0xFF << (bytenum << 3)))) | (data << (bytenum << 3));
566 GPUWriteLong(offset & 0xFFFFFFC, old_data, who);
570 // WriteLog("gpu: writing %.2x at 0x%.8x\n",data,offset);
571 JaguarWriteByte(offset, data, who);
575 // GPU word access (write)
577 void GPUWriteWord(uint32 offset, uint16 data, uint32 who/*=UNKNOWN*/)
579 if (offset >= 0xF02000 && offset <= 0xF020FF)
580 WriteLog("GPU: WriteWord--Attempt to write to GPU register file by %s!\n", whoName[who]);
582 if ((offset >= GPU_WORK_RAM_BASE) && (offset <= GPU_WORK_RAM_BASE + 0x0FFE))
584 gpu_ram_8[offset & 0xFFF] = (data>>8) & 0xFF;
585 gpu_ram_8[(offset+1) & 0xFFF] = data & 0xFF;//*/
587 SET16(gpu_ram_8, offset, data);//*/
589 /*if (offset >= 0xF03214 && offset < 0xF0321F)
590 WriteLog("GPU: Writing WORD (%04X) to GPU RAM (%08X)...\n", data, offset);//*/
593 //This is the same stupid worthless code that was in the DSP!!! AARRRGGGGHHHHH!!!!!!
596 m68k_end_timeslice();
597 dsp_releaseTimeslice();
601 else if ((offset >= GPU_CONTROL_RAM_BASE) && (offset <= GPU_CONTROL_RAM_BASE + 0x1E))
603 if (offset & 0x01) // This is supposed to weed out unaligned writes, but does nothing...
606 WriteLog("GPU: Write16--unaligned write @ %08X [%04X]\n", offset, data);
611 //Dual locations in this range: $1C Divide unit remainder/Divide unit control (R/W)
612 //This just literally sucks.
613 if ((offset & 0x1C) == 0x1C)
615 //This doesn't look right either--handles cases 1, 2, & 3 all the same!
617 gpu_div_control = (gpu_div_control & 0xFFFF0000) | (data & 0xFFFF);
619 gpu_div_control = (gpu_div_control & 0x0000FFFF) | ((data & 0xFFFF) << 16);
623 //WriteLog("[GPU W16:%08X,%04X]", offset, data);
624 uint32 old_data = GPUReadLong(offset & 0xFFFFFFC, who);
626 old_data = (old_data & 0xFFFF0000) | (data & 0xFFFF);
628 old_data = (old_data & 0x0000FFFF) | ((data & 0xFFFF) << 16);
629 GPUWriteLong(offset & 0xFFFFFFC, old_data, who);
633 else if ((offset == GPU_WORK_RAM_BASE + 0x0FFF) || (GPU_CONTROL_RAM_BASE + 0x1F))
636 WriteLog("GPU: Write16--unaligned write @ %08X by %s [%04X]!\n", offset, whoName[who], data);
642 // Have to be careful here--this can cause an infinite loop!
643 JaguarWriteWord(offset, data, who);
647 // GPU dword access (write)
649 void GPUWriteLong(uint32 offset, uint32 data, uint32 who/*=UNKNOWN*/)
651 if (offset >= 0xF02000 && offset <= 0xF020FF)
652 WriteLog("GPU: WriteLong--Attempt to write to GPU register file by %s!\n", whoName[who]);
654 // if ((offset >= GPU_WORK_RAM_BASE) && (offset < GPU_WORK_RAM_BASE + 0x1000))
655 if ((offset >= GPU_WORK_RAM_BASE) && (offset <= GPU_WORK_RAM_BASE + 0x0FFC))
660 WriteLog("GPU: Write32--unaligned write @ %08X [%08X] by %s\n", offset, data, whoName[who]);
666 SET32(gpu_ram_8, offset, data);
669 // else if ((offset >= GPU_CONTROL_RAM_BASE) && (offset < GPU_CONTROL_RAM_BASE+0x20))
670 else if ((offset >= GPU_CONTROL_RAM_BASE) && (offset <= GPU_CONTROL_RAM_BASE + 0x1C))
677 bool IMASKCleared = (gpu_flags & IMASK) && !(data & IMASK);
679 gpu_flag_z = gpu_flags & ZERO_FLAG;
680 gpu_flag_c = (gpu_flags & CARRY_FLAG) >> 1;
681 gpu_flag_n = (gpu_flags & NEGA_FLAG) >> 2;
682 GPUUpdateRegisterBanks();
683 gpu_control &= ~((gpu_flags & CINT04FLAGS) >> 3); // Interrupt latch clear bits
684 //Writing here is only an interrupt enable--this approach is just plain wrong!
686 //This, however, is A-OK! ;-)
687 if (IMASKCleared) // If IMASK was cleared,
688 GPUHandleIRQs(); // see if any other interrupts need servicing!
690 if (gpu_flags & (INT_ENA0 | INT_ENA1 | INT_ENA2 | INT_ENA3 | INT_ENA4))
691 WriteLog("GPU: Interrupt enable set by %s! Bits: %02X\n", whoName[who], (gpu_flags >> 4) & 0x1F);
692 WriteLog("GPU: REGPAGE %s...\n", (gpu_flags & REGPAGE ? "set" : "cleared"));
697 gpu_matrix_control = data;
700 // This can only point to long aligned addresses
701 gpu_pointer_to_matrix = data & 0xFFFFFFFC;
704 gpu_data_organization = data;
709 WriteLog("GPU: %s setting GPU PC to %08X %s\n", whoName[who], gpu_pc, (GPU_RUNNING ? "(GPU is RUNNING!)" : ""));//*/
714 // uint32 gpu_was_running = GPU_RUNNING;
715 data &= ~0xF7C0; // Disable writes to INT_LAT0-4 & TOM version number
717 // check for GPU -> CPU interrupt
720 //WriteLog("GPU->CPU interrupt\n");
721 if (tom_irq_enabled(IRQ_GPU))
723 if ((tom_irq_enabled(IRQ_GPU)) && (jaguar_interrupt_handler_is_valid(64)))
725 tom_set_pending_gpu_int();
726 m68k_set_irq(7); // Set 68000 NMI
727 gpu_releaseTimeslice();
733 // check for CPU -> GPU interrupt #0
736 //WriteLog("CPU->GPU interrupt\n");
737 GPUSetIRQLine(0, ASSERT_LINE);
738 m68k_end_timeslice();
739 dsp_releaseTimeslice();
746 //WriteLog("asked to perform a single step (single step is %senabled)\n",(data&0x8)?"":"not ");
748 gpu_control = (gpu_control & 0xF7C0) | (data & (~0xF7C0));
750 // if gpu wasn't running but is now running, execute a few cycles
751 #ifndef GPU_SINGLE_STEPPING
752 /* if (!gpu_was_running && GPU_RUNNING)
755 WriteLog("GPU: Write32--About to do stupid braindead GPU execution for 200 cycles.\n");
760 #endif // GPU_DEBUG//*/
762 if (gpu_control & 0x18)
764 #endif // #ifndef GPU_SINGLE_STEPPING
766 WriteLog("Write to GPU CTRL by %s: %08X ", whoName[who], data);
768 WriteLog(" --> Starting to run at %08X by %s...", gpu_pc, whoName[who]);
770 WriteLog(" --> Stopped by %s! (GPU_PC: %08X)", whoName[who], gpu_pc);
774 // GPUDumpDisassembly();
777 if (gpu_pc == 0xF035D8)
779 // GPUDumpDisassembly();
782 gpu_control &= 0xFFFFFFFE; // Don't run it and let's see what happens!
783 //Hmm. Seems to lock up when going into the demo...
784 //Try to disable the collision altogether!
787 extern int effect_start5;
788 static bool finished = false;
789 //if (GPU_RUNNING && effect_start5 && !finished)
790 if (GPU_RUNNING && effect_start5 && gpu_pc == 0xF035D8)
792 // Let's do a dump of $6528!
793 /* uint32 numItems = JaguarReadWord(0x6BD6);
794 WriteLog("\nDump of $6528: %u items.\n\n", numItems);
795 for(int i=0; i<numItems*3*4; i+=3*4)
797 WriteLog("\t%04X: %08X %08X %08X -> ", 0x6528+i, JaguarReadLong(0x6528+i),
798 JaguarReadLong(0x6528+i+4), JaguarReadLong(0x6528+i+8));
799 uint16 link = JaguarReadWord(0x6528+i+8+2);
800 for(int j=0; j<40; j+=4)
801 WriteLog("%08X ", JaguarReadLong(link + j));
805 // Let's try a manual blit here...
806 //This isn't working the way it should! !!! FIX !!!
807 //Err, actually, it is.
808 // NOW, it works right! Problem solved!!! It's a blitter bug!
809 /* uint32 src = 0x4D54, dst = 0xF03000, width = 10 * 4;
810 for(int y=0; y<127; y++)
812 for(int x=0; x<2; x++)
814 JaguarWriteLong(dst, JaguarReadLong(src));
819 src += width - (2 * 4);
823 WriteLog("\nGPU: About to execute collision detection code.\n\n");//*/
825 /* WriteLog("\nGPU: About to execute collision detection code. Data @ 4D54:\n\n");
827 for(int i=0x004D54; i<0x004D54+2048; i++)
829 WriteLog("%02X ", JaguarReadByte(i));
837 WriteLog("\n\nData @ F03000:\n\n");
839 for(int i=0xF03000; i<0xF03200; i++)
841 WriteLog("%02X ", JaguarReadByte(i));
855 /*if (!GPU_RUNNING && finished)
857 WriteLog("\nGPU: Finished collision detection code. Exiting!\n\n");
862 // (?) If we're set running by the M68K (or DSP?) then end its timeslice to
863 // allow the GPU a chance to run...
864 // Yes! This partially fixed Trevor McFur...
866 m68k_end_timeslice();
873 gpu_div_control = data;
875 // default: // unaligned long write
882 // JaguarWriteWord(offset, (data >> 16) & 0xFFFF, who);
883 // JaguarWriteWord(offset+2, data & 0xFFFF, who);
884 // We're a 32-bit processor, we can do a long write...!
885 JaguarWriteLong(offset, data, who);
889 // Change register banks if necessary
891 void GPUUpdateRegisterBanks(void)
893 int bank = (gpu_flags & REGPAGE); // REGPAGE bit
895 if (gpu_flags & IMASK) // IMASK bit
896 bank = 0; // IMASK forces main bank to be bank 0
899 gpu_reg = gpu_reg_bank_1, gpu_alternate_reg = gpu_reg_bank_0;
901 gpu_reg = gpu_reg_bank_0, gpu_alternate_reg = gpu_reg_bank_1;
904 void GPUHandleIRQs(void)
906 // Bail out if we're already in an interrupt!
907 if (gpu_flags & IMASK)
910 // Get the interrupt latch & enable bits
911 uint32 bits = (gpu_control >> 6) & 0x1F, mask = (gpu_flags >> 4) & 0x1F;
913 // Bail out if latched interrupts aren't enabled
918 // Determine which interrupt to service
919 uint32 which = 0; //Isn't there a #pragma to disable this warning???
932 WriteLog("GPU: Generating IRQ #%i\n", which);
934 // set the interrupt flag
936 GPUUpdateRegisterBanks();
938 // subqt #4,r31 ; pre-decrement stack pointer
939 // move pc,r30 ; address of interrupted code
940 // store r30,(r31) ; store return address
942 GPUWriteLong(gpu_reg[31], gpu_pc - 2, GPU);
944 // movei #service_address,r30 ; pointer to ISR entry
945 // jump (r30) ; jump to ISR
947 gpu_pc = gpu_reg[30] = GPU_WORK_RAM_BASE + (which * 0x10);
950 void GPUSetIRQLine(int irqline, int state)
953 WriteLog("GPU: Setting GPU IRQ line #%i\n", irqline);
955 uint32 mask = 0x0040 << irqline;
956 gpu_control &= ~mask; // Clear the interrupt latch
960 gpu_control |= mask; // Assert the interrupt latch
961 GPUHandleIRQs(); // And handle the interrupt...
965 //TEMPORARY: Testing only!
971 memory_malloc_secure((void **)&gpu_ram_8, 0x1000, "GPU work RAM");
972 memory_malloc_secure((void **)&gpu_reg_bank_0, 32 * sizeof(int32), "GPU bank 0 regs");
973 memory_malloc_secure((void **)&gpu_reg_bank_1, 32 * sizeof(int32), "GPU bank 1 regs");
975 build_branch_condition_table();
979 //TEMPORARY: Testing only!
986 // GPU registers (directly visible)
987 gpu_flags = 0x00000000;
988 gpu_matrix_control = 0x00000000;
989 gpu_pointer_to_matrix = 0x00000000;
990 gpu_data_organization = 0xFFFFFFFF;
992 gpu_control = 0x00002800; // Correctly sets this as TOM Rev. 2
993 gpu_hidata = 0x00000000;
994 gpu_remain = 0x00000000; // These two registers are RO/WO
995 gpu_div_control = 0x00000000;
997 // GPU internal register
998 gpu_acc = 0x00000000;
1000 gpu_reg = gpu_reg_bank_0;
1001 gpu_alternate_reg = gpu_reg_bank_1;
1003 for(int i=0; i<32; i++)
1004 gpu_reg[i] = gpu_alternate_reg[i] = 0x00000000;
1007 memset(gpu_ram_8, 0xFF, 0x1000);
1009 //not needed GPUInterruptPending = false;
1013 uint32 gpu_read_pc(void)
1018 void gpu_reset_stats(void)
1020 for(uint32 i=0; i<64; i++)
1021 gpu_opcode_use[i] = 0;
1022 WriteLog("--> GPU stats were reset!\n");
1025 void GPUDumpDisassembly(void)
1029 WriteLog("\n---[GPU code at 00F03000]---------------------------\n");
1030 uint32 j = 0xF03000;
1031 while (j <= 0xF03FFF)
1034 j += dasmjag(JAGUAR_GPU, buffer, j);
1035 WriteLog("\t%08X: %s\n", oldj, buffer);
1039 void GPUDumpRegisters(void)
1041 WriteLog("\n---[GPU flags: NCZ %d%d%d]-----------------------\n", gpu_flag_n, gpu_flag_c, gpu_flag_z);
1042 WriteLog("\nRegisters bank 0\n");
1043 for(int j=0; j<8; j++)
1045 WriteLog("\tR%02i = %08X R%02i = %08X R%02i = %08X R%02i = %08X\n",
1046 (j << 2) + 0, gpu_reg_bank_0[(j << 2) + 0],
1047 (j << 2) + 1, gpu_reg_bank_0[(j << 2) + 1],
1048 (j << 2) + 2, gpu_reg_bank_0[(j << 2) + 2],
1049 (j << 2) + 3, gpu_reg_bank_0[(j << 2) + 3]);
1051 WriteLog("Registers bank 1\n");
1052 for(int j=0; j<8; j++)
1054 WriteLog("\tR%02i = %08X R%02i = %08X R%02i = %08X R%02i = %08X\n",
1055 (j << 2) + 0, gpu_reg_bank_1[(j << 2) + 0],
1056 (j << 2) + 1, gpu_reg_bank_1[(j << 2) + 1],
1057 (j << 2) + 2, gpu_reg_bank_1[(j << 2) + 2],
1058 (j << 2) + 3, gpu_reg_bank_1[(j << 2) + 3]);
1062 void GPUDumpMemory(void)
1064 WriteLog("\n---[GPU data at 00F03000]---------------------------\n");
1065 for(int i=0; i<0xFFF; i+=4)
1066 WriteLog("\t%08X: %02X %02X %02X %02X\n", 0xF03000+i, gpu_ram_8[i],
1067 gpu_ram_8[i+1], gpu_ram_8[i+2], gpu_ram_8[i+3]);
1072 WriteLog("GPU: Stopped at PC=%08X (GPU %s running)\n", (unsigned int)gpu_pc, GPU_RUNNING ? "was" : "wasn't");
1074 // Get the interrupt latch & enable bits
1075 uint8 bits = (gpu_control >> 6) & 0x1F, mask = (gpu_flags >> 4) & 0x1F;
1076 WriteLog("GPU: Latch bits = %02X, enable bits = %02X\n", bits, mask);
1079 GPUDumpDisassembly();
1081 WriteLog("\nGPU opcodes use:\n");
1082 for(int i=0; i<64; i++)
1084 if (gpu_opcode_use[i])
1085 WriteLog("\t%17s %lu\n", gpu_opcode_str[i], gpu_opcode_use[i]);
1089 memory_free(gpu_ram_8);
1090 memory_free(gpu_reg_bank_0);
1091 memory_free(gpu_reg_bank_1);
1095 // Main GPU execution core
1097 static int testCount = 1;
1099 static bool tripwire = false;
1100 void gpu_exec(int32 cycles)
1105 #ifdef GPU_SINGLE_STEPPING
1106 if (gpu_control & 0x18)
1109 gpu_control &= ~0x10;
1113 gpu_releaseTimeSlice_flag = 0;
1116 while (cycles > 0 && GPU_RUNNING)
1118 if (gpu_ram_8[0x054] == 0x98 && gpu_ram_8[0x055] == 0x0A && gpu_ram_8[0x056] == 0x03
1119 && gpu_ram_8[0x057] == 0x00 && gpu_ram_8[0x058] == 0x00 && gpu_ram_8[0x059] == 0x00)
1121 if (gpu_pc == 0xF03000)
1123 extern uint32 starCount;
1125 /* WriteLog("GPU: Starting starfield generator... Dump of [R03=%08X]:\n", gpu_reg_bank_0[03]);
1126 uint32 base = gpu_reg_bank_0[3];
1127 for(uint32 i=0; i<0x100; i+=16)
1129 WriteLog("%02X: ", i);
1130 for(uint32 j=0; j<16; j++)
1132 WriteLog("%02X ", JaguarReadByte(base + i + j));
1137 // if (gpu_pc == 0xF03)
1141 /*if (gpu_pc == 0xF03B9E && gpu_reg_bank_0[01] == 0)
1144 WriteLog("GPU: Starting disassembly log...\n");
1147 /*if (gpu_pc == 0xF0359A)
1152 /* gpu_flag_c = (gpu_flag_c ? 1 : 0);
1153 gpu_flag_z = (gpu_flag_z ? 1 : 0);
1154 gpu_flag_n = (gpu_flag_n ? 1 : 0);*/
1156 uint16 opcode = GPUReadWord(gpu_pc, GPU);
1157 uint32 index = opcode >> 10;
1158 gpu_instruction = opcode; // Added for GPU #3...
1159 gpu_opcode_first_parameter = (opcode >> 5) & 0x1F;
1160 gpu_opcode_second_parameter = opcode & 0x1F;
1161 /*if (gpu_pc == 0xF03BE8)
1162 WriteLog("Start of OP frame write...\n");
1163 if (gpu_pc == 0xF03EEE)
1164 WriteLog("--> Writing BRANCH object ---\n");
1165 if (gpu_pc == 0xF03F62)
1166 WriteLog("--> Writing BITMAP object ***\n");//*/
1167 /*if (gpu_pc == 0xF03546)
1169 WriteLog("\n--> GPU PC: F03546\n");
1171 GPUDumpDisassembly();
1173 /*if (gpu_pc == 0xF033F6)
1175 WriteLog("\n--> GPU PC: F033F6\n");
1177 GPUDumpDisassembly();
1179 /*if (gpu_pc == 0xF033CC)
1181 WriteLog("\n--> GPU PC: F033CC\n");
1183 GPUDumpDisassembly();
1185 /*if (gpu_pc == 0xF033D6)
1187 WriteLog("\n--> GPU PC: F033D6 (#%d)\n", testCount++);
1191 /*if (gpu_pc == 0xF033D8)
1193 WriteLog("\n--> GPU PC: F033D8 (#%d)\n", testCount++);
1197 /*if (gpu_pc == 0xF0358E)
1199 WriteLog("\n--> GPU PC: F0358E (#%d)\n", testCount++);
1203 /*if (gpu_pc == 0xF034CA)
1205 WriteLog("\n--> GPU PC: F034CA (#%d)\n", testCount++);
1208 /*if (gpu_pc == 0xF034CA)
1210 len = gpu_reg[1] + 4;//, r9save = gpu_reg[9];
1211 WriteLog("\nAbout to subtract [#%d] (R14=%08X, R15=%08X, R9=%08X):\n ", testCount++, gpu_reg[14], gpu_reg[15], gpu_reg[9]);
1212 for(int i=0; i<len; i+=4)
1213 WriteLog(" %08X", GPUReadLong(gpu_reg[15]+i));
1215 for(int i=0; i<len; i+=4)
1216 WriteLog(" %08X", GPUReadLong(gpu_reg[14]+i));
1219 if (gpu_pc == 0xF034DE)
1221 WriteLog("\nSubtracted! (R14=%08X, R15=%08X):\n ", gpu_reg[14], gpu_reg[15]);
1222 for(int i=0; i<len; i+=4)
1223 WriteLog(" %08X", GPUReadLong(gpu_reg[15]+i));
1225 for(int i=0; i<len; i+=4)
1226 WriteLog(" %08X", GPUReadLong(gpu_reg[14]+i));
1228 for(int i=0; i<len; i+=4)
1229 WriteLog(" --------");
1231 for(int i=0; i<len; i+=4)
1232 WriteLog(" %08X", GPUReadLong(gpu_reg[9]+4+i));
1235 /*if (gpu_pc == 0xF035C8)
1237 WriteLog("\n--> GPU PC: F035C8 (#%d)\n", testCount++);
1239 GPUDumpDisassembly();
1244 // gpu_reset_stats();
1245 static char buffer[512];
1246 dasmjag(JAGUAR_GPU, buffer, gpu_pc);
1247 WriteLog("GPU: [%08X] %s (RM=%08X, RN=%08X) -> ", gpu_pc, buffer, RM, RN);
1249 //$E400 -> 1110 01 -> $39 -> 57
1252 gpu_opcode[index]();
1254 // gpu2_opcode[index]();
1256 //GPU #3 (Doesn't show ATARI logo! #1 & #2 do...)
1258 // gpu3_opcode[index]();
1261 //GPU: [00F03548] jr nz,00F03560 (0xd561) (RM=00F03114, RN=00000004) -> --> JR: Branch taken.
1262 /*static bool firstTime = true;
1263 if (gpu_pc == 0xF03548 && firstTime)
1266 // firstTime = false;
1268 //static char buffer[512];
1270 //while (k<0xF0356C)
1273 //k += dasmjag(JAGUAR_GPU, buffer, k);
1274 //WriteLog("GPU: [%08X] %s\n", oldk, buffer);
1276 // gpu_start_log = 1;
1278 //GPU: [00F0354C] jump nz,(r29) (0xd3a1) (RM=00F03314, RN=00000004) -> (RM=00F03314, RN=00000004)
1279 /*if (gpu_pc == 0xF0354C)
1280 gpu_flag_z = 0;//, gpu_start_log = 1;//*/
1282 cycles -= gpu_opcode_cycles[index];
1283 gpu_opcode_use[index]++;
1285 WriteLog("(RM=%08X, RN=%08X)\n", RM, RN);//*/
1286 if ((gpu_pc < 0xF03000 || gpu_pc > 0xF03FFF) && !tripwire)
1288 WriteLog("GPU: Executing outside local RAM! GPU_PC: %08X\n", gpu_pc);
1301 GPU opcodes use (offset punch--vertically below bad guy):
1323 load_r14_indexed 1183
1324 load_r15_indexed 1125
1327 store_r14_indexed 320
1335 static void gpu_opcode_jump(void)
1338 char * condition[32] =
1339 { "T", "nz", "z", "???", "nc", "nc nz", "nc z", "???", "c", "c nz",
1340 "c z", "???", "???", "???", "???", "???", "???", "???", "???",
1341 "???", "nn", "nn nz", "nn z", "???", "n", "n nz", "n z", "???",
1342 "???", "???", "???", "F" };
1344 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);
1347 /* gpu_flag_c = (gpu_flag_c ? 1 : 0);
1348 gpu_flag_z = (gpu_flag_z ? 1 : 0);
1349 gpu_flag_n = (gpu_flag_n ? 1 : 0);*/
1350 // KLUDGE: Used by BRANCH_CONDITION
1351 uint32 jaguar_flags = (gpu_flag_n << 2) | (gpu_flag_c << 1) | gpu_flag_z;
1353 if (BRANCH_CONDITION(IMM_2))
1357 WriteLog("Branched!\n");
1360 WriteLog(" --> JUMP: Branch taken.\n");
1361 uint32 delayed_pc = RM;
1363 gpu_pc = delayed_pc;
1364 /* uint16 opcode = GPUReadWord(gpu_pc, GPU);
1365 gpu_opcode_first_parameter = (opcode >> 5) & 0x1F;
1366 gpu_opcode_second_parameter = opcode & 0x1F;
1368 gpu_pc = delayed_pc;
1369 gpu_opcode[opcode>>10]();//*/
1374 WriteLog("Branch NOT taken.\n");
1378 static void gpu_opcode_jr(void)
1381 char * condition[32] =
1382 { "T", "nz", "z", "???", "nc", "nc nz", "nc z", "???", "c", "c nz",
1383 "c z", "???", "???", "???", "???", "???", "???", "???", "???",
1384 "???", "nn", "nn nz", "nn z", "???", "n", "n nz", "n z", "???",
1385 "???", "???", "???", "F" };
1387 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);
1389 /* if (CONDITION(jaguar.op & 31))
1391 INT32 r1 = (INT8)((jaguar.op >> 2) & 0xF8) >> 2;
1392 UINT32 newpc = jaguar.PC + r1;
1394 jaguar.op = ROPCODE(jaguar.PC);
1396 (*jaguar.table[jaguar.op >> 10])();
1398 jaguar_icount -= 3; // 3 wait states guaranteed
1401 /* gpu_flag_n = (gpu_flag_n ? 1 : 0);
1402 gpu_flag_c = (gpu_flag_c ? 1 : 0);
1403 gpu_flag_z = (gpu_flag_z ? 1 : 0);*/
1404 // KLUDGE: Used by BRANCH_CONDITION
1405 uint32 jaguar_flags = (gpu_flag_n << 2) | (gpu_flag_c << 1) | gpu_flag_z;
1407 if (BRANCH_CONDITION(IMM_2))
1411 WriteLog("Branched!\n");
1414 WriteLog(" --> JR: Branch taken.\n");
1415 int32 offset = (IMM_1 & 0x10 ? 0xFFFFFFF0 | IMM_1 : IMM_1); // Sign extend IMM_1
1416 int32 delayed_pc = gpu_pc + (offset * 2);
1418 gpu_pc = delayed_pc;
1419 /* uint16 opcode = GPUReadWord(gpu_pc, GPU);
1420 gpu_opcode_first_parameter = (opcode >> 5) & 0x1F;
1421 gpu_opcode_second_parameter = opcode & 0x1F;
1423 gpu_pc = delayed_pc;
1424 gpu_opcode[opcode>>10]();//*/
1429 WriteLog("Branch NOT taken.\n");
1433 static void gpu_opcode_add(void)
1437 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);
1439 UINT32 res = RN + RM;
1440 CLR_ZNC; SET_ZNC_ADD(RN, RM, res);
1444 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);
1448 static void gpu_opcode_addc(void)
1452 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);
1454 /* int dreg = jaguar.op & 31;
1455 UINT32 r1 = jaguar.r[(jaguar.op >> 5) & 31];
1456 UINT32 r2 = jaguar.r[dreg];
1457 UINT32 res = r2 + r1 + ((jaguar.FLAGS >> 1) & 1);
1458 jaguar.r[dreg] = res;
1459 CLR_ZNC; SET_ZNC_ADD(r2,r1,res);*/
1461 UINT32 res = RN + RM + gpu_flag_c;
1462 UINT32 carry = gpu_flag_c;
1463 // SET_ZNC_ADD(RN, RM, res); //???BUG??? Yes!
1464 SET_ZNC_ADD(RN + carry, RM, res);
1465 // SET_ZNC_ADD(RN, RM + carry, res);
1469 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);
1473 static void gpu_opcode_addq(void)
1477 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);
1479 UINT32 r1 = gpu_convert_zero[IMM_1];
1480 UINT32 res = RN + r1;
1481 CLR_ZNC; SET_ZNC_ADD(RN, r1, res);
1485 WriteLog("[NCZ:%u%u%u, R%02u=%08X]\n", gpu_flag_n, gpu_flag_c, gpu_flag_z, IMM_2, RN);
1489 static void gpu_opcode_addqt(void)
1491 #ifdef GPU_DIS_ADDQT
1493 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);
1495 RN += gpu_convert_zero[IMM_1];
1496 #ifdef GPU_DIS_ADDQT
1498 WriteLog("[NCZ:%u%u%u, R%02u=%08X]\n", gpu_flag_n, gpu_flag_c, gpu_flag_z, IMM_2, RN);
1502 static void gpu_opcode_sub(void)
1506 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);
1508 UINT32 res = RN - RM;
1509 SET_ZNC_SUB(RN, RM, res);
1513 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);
1517 static void gpu_opcode_subc(void)
1521 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);
1523 UINT32 res = RN - RM - gpu_flag_c;
1524 UINT32 borrow = gpu_flag_c;
1525 // SET_ZNC_SUB(RN, RM, res); //???BUG??? YES!!!
1526 //No matter how you do it, there is a problem. With below, it's 0-0 with carry,
1527 //and the one below it it's FFFFFFFF - FFFFFFFF with carry... !!! FIX !!!
1528 // SET_ZNC_SUB(RN - borrow, RM, res);
1529 SET_ZNC_SUB(RN, RM + borrow, 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 N = 5, M = 3, 3 - 5 = -2, C = 1... Or, in our case:
1538 N = 0, M = 1, 0 - 1 = -1, C = 0!
1540 #define SET_C_SUB(a,b) (gpu_flag_c = ((UINT32)(b) > (UINT32)(a)))
1541 #define SET_ZN(r) SET_N(r); SET_Z(r)
1542 #define SET_ZNC_ADD(a,b,r) SET_N(r); SET_Z(r); SET_C_ADD(a,b)
1543 #define SET_ZNC_SUB(a,b,r) SET_N(r); SET_Z(r); SET_C_SUB(a,b)
1545 static void gpu_opcode_subq(void)
1549 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);
1551 UINT32 r1 = gpu_convert_zero[IMM_1];
1552 UINT32 res = RN - r1;
1553 SET_ZNC_SUB(RN, r1, res);
1557 WriteLog("[NCZ:%u%u%u, R%02u=%08X]\n", gpu_flag_n, gpu_flag_c, gpu_flag_z, IMM_2, RN);
1561 static void gpu_opcode_subqt(void)
1563 #ifdef GPU_DIS_SUBQT
1565 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);
1567 RN -= gpu_convert_zero[IMM_1];
1568 #ifdef GPU_DIS_SUBQT
1570 WriteLog("[NCZ:%u%u%u, R%02u=%08X]\n", gpu_flag_n, gpu_flag_c, gpu_flag_z, IMM_2, RN);
1574 static void gpu_opcode_cmp(void)
1578 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);
1580 UINT32 res = RN - RM;
1581 SET_ZNC_SUB(RN, RM, res);
1584 WriteLog("[NCZ:%u%u%u]\n", gpu_flag_n, gpu_flag_c, gpu_flag_z);
1588 static void gpu_opcode_cmpq(void)
1590 static int32 sqtable[32] =
1591 { 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 };
1594 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);
1596 UINT32 r1 = sqtable[IMM_1 & 0x1F]; // I like this better -> (INT8)(jaguar.op >> 2) >> 3;
1597 UINT32 res = RN - r1;
1598 SET_ZNC_SUB(RN, r1, res);
1601 WriteLog("[NCZ:%u%u%u]\n", gpu_flag_n, gpu_flag_c, gpu_flag_z);
1605 static void gpu_opcode_and(void)
1609 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);
1615 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);
1619 static void gpu_opcode_or(void)
1623 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);
1629 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);
1633 static void gpu_opcode_xor(void)
1637 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);
1643 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);
1647 static void gpu_opcode_not(void)
1651 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);
1657 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);
1661 static void gpu_opcode_move_pc(void)
1663 #ifdef GPU_DIS_MOVEPC
1665 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);
1667 // Should be previous PC--this might not always be previous instruction!
1668 // Then again, this will point right at the *current* instruction, i.e., MOVE PC,R!
1670 #ifdef GPU_DIS_MOVEPC
1672 WriteLog("[NCZ:%u%u%u, R%02u=%08X]\n", gpu_flag_n, gpu_flag_c, gpu_flag_z, IMM_2, RN);
1676 static void gpu_opcode_sat8(void)
1680 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);
1682 RN = ((int32)RN < 0 ? 0 : (RN > 0xFF ? 0xFF : RN));
1686 WriteLog("[NCZ:%u%u%u, R%02u=%08X]\n", gpu_flag_n, gpu_flag_c, gpu_flag_z, IMM_2, RN);
1690 static void gpu_opcode_sat16(void)
1692 RN = ((int32)RN < 0 ? 0 : (RN > 0xFFFF ? 0xFFFF : RN));
1696 static void gpu_opcode_sat24(void)
1698 RN = ((int32)RN < 0 ? 0 : (RN > 0xFFFFFF ? 0xFFFFFF : RN));
1702 static void gpu_opcode_store_r14_indexed(void)
1704 #ifdef GPU_DIS_STORE14I
1706 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));
1708 GPUWriteLong(gpu_reg[14] + (gpu_convert_zero[IMM_1] << 2), RN, GPU);
1711 static void gpu_opcode_store_r15_indexed(void)
1713 #ifdef GPU_DIS_STORE15I
1715 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));
1717 GPUWriteLong(gpu_reg[15] + (gpu_convert_zero[IMM_1] << 2), RN, GPU);
1720 static void gpu_opcode_load_r14_ri(void)
1722 #ifdef GPU_DIS_LOAD14R
1724 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);
1726 RN = GPUReadLong(gpu_reg[14] + RM, GPU);
1727 #ifdef GPU_DIS_LOAD14R
1729 WriteLog("[NCZ:%u%u%u, R%02u=%08X]\n", gpu_flag_n, gpu_flag_c, gpu_flag_z, IMM_2, RN);
1733 static void gpu_opcode_load_r15_ri(void)
1735 #ifdef GPU_DIS_LOAD15R
1737 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);
1739 RN = GPUReadLong(gpu_reg[15] + RM, GPU);
1740 #ifdef GPU_DIS_LOAD15R
1742 WriteLog("[NCZ:%u%u%u, R%02u=%08X]\n", gpu_flag_n, gpu_flag_c, gpu_flag_z, IMM_2, RN);
1746 static void gpu_opcode_store_r14_ri(void)
1748 #ifdef GPU_DIS_STORE14R
1750 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]);
1752 GPUWriteLong(gpu_reg[14] + RM, RN, GPU);
1755 static void gpu_opcode_store_r15_ri(void)
1757 #ifdef GPU_DIS_STORE15R
1759 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]);
1761 GPUWriteLong(gpu_reg[15] + RM, RN, GPU);
1764 static void gpu_opcode_nop(void)
1768 WriteLog("%06X: NOP [NCZ:%u%u%u]\n", gpu_pc-2, gpu_flag_n, gpu_flag_c, gpu_flag_z);
1772 static void gpu_opcode_pack(void)
1776 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);
1780 //BUG! if (RM == 0) // Pack
1781 if (IMM_1 == 0) // Pack
1782 RN = ((val >> 10) & 0x0000F000) | ((val >> 5) & 0x00000F00) | (val & 0x000000FF);
1784 RN = ((val & 0x0000F000) << 10) | ((val & 0x00000F00) << 5) | (val & 0x000000FF);
1787 WriteLog("[NCZ:%u%u%u, R%02u=%08X]\n", gpu_flag_n, gpu_flag_c, gpu_flag_z, IMM_2, RN);
1791 static void gpu_opcode_storeb(void)
1793 #ifdef GPU_DIS_STOREB
1795 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);
1798 // Would appear to be so...!
1799 if ((RM >= 0xF03000) && (RM <= 0xF03FFF))
1800 GPUWriteLong(RM, RN & 0xFF, GPU);
1802 JaguarWriteByte(RM, RN, GPU);
1805 static void gpu_opcode_storew(void)
1807 #ifdef GPU_DIS_STOREW
1809 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);
1811 if ((RM >= 0xF03000) && (RM <= 0xF03FFF))
1812 GPUWriteLong(RM, RN & 0xFFFF, GPU);
1814 JaguarWriteWord(RM, RN, GPU);
1817 static void gpu_opcode_store(void)
1819 #ifdef GPU_DIS_STORE
1821 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);
1823 GPUWriteLong(RM, RN, GPU);
1826 static void gpu_opcode_storep(void)
1828 GPUWriteLong(RM + 0, gpu_hidata, GPU);
1829 GPUWriteLong(RM + 4, RN, GPU);
1832 static void gpu_opcode_loadb(void)
1834 #ifdef GPU_DIS_LOADB
1836 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);
1838 if ((RM >= 0xF03000) && (RM <= 0xF03FFF))
1839 RN = GPUReadLong(RM, GPU) & 0xFF;
1841 RN = JaguarReadByte(RM, GPU);
1842 #ifdef GPU_DIS_LOADB
1844 WriteLog("[NCZ:%u%u%u, R%02u=%08X]\n", gpu_flag_n, gpu_flag_c, gpu_flag_z, IMM_2, RN);
1848 static void gpu_opcode_loadw(void)
1850 #ifdef GPU_DIS_LOADW
1852 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);
1854 if ((RM >= 0xF03000) && (RM <= 0xF03FFF))
1855 RN = GPUReadLong(RM, GPU) & 0xFFFF;
1857 RN = JaguarReadWord(RM, GPU);
1858 #ifdef GPU_DIS_LOADW
1860 WriteLog("[NCZ:%u%u%u, R%02u=%08X]\n", gpu_flag_n, gpu_flag_c, gpu_flag_z, IMM_2, RN);
1864 static void gpu_opcode_load(void)
1868 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);
1870 RN = GPUReadLong(RM, GPU);
1873 WriteLog("[NCZ:%u%u%u, R%02u=%08X]\n", gpu_flag_n, gpu_flag_c, gpu_flag_z, IMM_2, RN);
1877 static void gpu_opcode_loadp(void)
1879 gpu_hidata = GPUReadLong(RM + 0, GPU);
1880 RN = GPUReadLong(RM + 4, GPU);
1883 static void gpu_opcode_load_r14_indexed(void)
1885 #ifdef GPU_DIS_LOAD14I
1887 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);
1889 RN = GPUReadLong(gpu_reg[14] + (gpu_convert_zero[IMM_1] << 2), GPU);
1890 #ifdef GPU_DIS_LOAD14I
1892 WriteLog("[NCZ:%u%u%u, R%02u=%08X]\n", gpu_flag_n, gpu_flag_c, gpu_flag_z, IMM_2, RN);
1896 static void gpu_opcode_load_r15_indexed(void)
1898 #ifdef GPU_DIS_LOAD15I
1900 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);
1902 RN = GPUReadLong(gpu_reg[15] + (gpu_convert_zero[IMM_1] << 2), GPU);
1903 #ifdef GPU_DIS_LOAD15I
1905 WriteLog("[NCZ:%u%u%u, R%02u=%08X]\n", gpu_flag_n, gpu_flag_c, gpu_flag_z, IMM_2, RN);
1909 static void gpu_opcode_movei(void)
1911 #ifdef GPU_DIS_MOVEI
1913 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);
1915 // This instruction is followed by 32-bit value in LSW / MSW format...
1916 RN = (uint32)GPUReadWord(gpu_pc, GPU) | ((uint32)GPUReadWord(gpu_pc + 2, GPU) << 16);
1918 #ifdef GPU_DIS_MOVEI
1920 WriteLog("[NCZ:%u%u%u, R%02u=%08X]\n", gpu_flag_n, gpu_flag_c, gpu_flag_z, IMM_2, RN);
1924 static void gpu_opcode_moveta(void)
1926 #ifdef GPU_DIS_MOVETA
1928 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);
1931 #ifdef GPU_DIS_MOVETA
1933 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);
1937 static void gpu_opcode_movefa(void)
1939 #ifdef GPU_DIS_MOVEFA
1941 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);
1944 #ifdef GPU_DIS_MOVEFA
1946 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);
1950 static void gpu_opcode_move(void)
1954 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);
1959 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);
1963 static void gpu_opcode_moveq(void)
1965 #ifdef GPU_DIS_MOVEQ
1967 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);
1970 #ifdef GPU_DIS_MOVEQ
1972 WriteLog("[NCZ:%u%u%u, R%02u=%08X]\n", gpu_flag_n, gpu_flag_c, gpu_flag_z, IMM_2, RN);
1976 static void gpu_opcode_resmac(void)
1981 static void gpu_opcode_imult(void)
1983 #ifdef GPU_DIS_IMULT
1985 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);
1987 RN = (int16)RN * (int16)RM;
1989 #ifdef GPU_DIS_IMULT
1991 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);
1995 static void gpu_opcode_mult(void)
1999 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);
2001 RN = (uint16)RM * (uint16)RN;
2005 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);
2009 static void gpu_opcode_bclr(void)
2013 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);
2015 UINT32 res = RN & ~(1 << IMM_1);
2020 WriteLog("[NCZ:%u%u%u, R%02u=%08X]\n", gpu_flag_n, gpu_flag_c, gpu_flag_z, IMM_2, RN);
2024 static void gpu_opcode_btst(void)
2028 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);
2030 gpu_flag_z = (~RN >> IMM_1) & 1;
2033 WriteLog("[NCZ:%u%u%u, R%02u=%08X]\n", gpu_flag_n, gpu_flag_c, gpu_flag_z, IMM_2, RN);
2037 static void gpu_opcode_bset(void)
2041 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);
2043 UINT32 res = RN | (1 << IMM_1);
2048 WriteLog("[NCZ:%u%u%u, R%02u=%08X]\n", gpu_flag_n, gpu_flag_c, gpu_flag_z, IMM_2, RN);
2052 static void gpu_opcode_imacn(void)
2054 uint32 res = (int16)RM * (int16)(RN);
2058 static void gpu_opcode_mtoi(void)
2061 uint32 res = RN = (((INT32)_RM >> 8) & 0xFF800000) | (_RM & 0x007FFFFF);
2065 static void gpu_opcode_normi(void)
2072 while ((_RM & 0xFFC00000) == 0)
2077 while ((_RM & 0xFF800000) != 0)
2087 static void gpu_opcode_mmult(void)
2089 int count = gpu_matrix_control & 0x0F; // Matrix width
2090 uint32 addr = gpu_pointer_to_matrix; // In the GPU's RAM
2094 if (gpu_matrix_control & 0x10) // Column stepping
2096 for(int i=0; i<count; i++)
2100 a = (int16)((gpu_alternate_reg[IMM_1 + (i >> 1)] >> 16) & 0xFFFF);
2102 a = (int16)(gpu_alternate_reg[IMM_1 + (i >> 1)] & 0xFFFF);
2104 int16 b = ((int16)GPUReadWord(addr + 2, GPU));
2109 else // Row stepping
2111 for(int i=0; i<count; i++)
2115 a = (int16)((gpu_alternate_reg[IMM_1 + (i >> 1)] >> 16) & 0xFFFF);
2117 a = (int16)(gpu_alternate_reg[IMM_1 + (i >> 1)] & 0xFFFF);
2119 int16 b = ((int16)GPUReadWord(addr + 2, GPU));
2124 RN = res = (int32)accum;
2125 // carry flag to do (out of the last add)
2129 static void gpu_opcode_abs(void)
2133 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);
2135 gpu_flag_c = RN >> 31;
2136 if (RN == 0x80000000)
2137 //Is 0x80000000 a positive number? If so, then we need to set C to 0 as well!
2138 gpu_flag_n = 1, gpu_flag_z = 0;
2143 gpu_flag_n = 0; SET_FLAG_Z(RN);
2147 WriteLog("[NCZ:%u%u%u, R%02u=%08X]\n", gpu_flag_n, gpu_flag_c, gpu_flag_z, IMM_2, RN);
2151 static void gpu_opcode_div(void) // RN / RM
2155 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);
2157 // NOTE: remainder is NOT calculated correctly here!
2158 // The original tried to get it right by checking to see if the
2159 // remainder was negative, but that's too late...
2160 // The code there should do it now, but I'm not 100% sure...
2164 if (gpu_div_control & 0x01) // 16.16 division
2166 RN = ((UINT64)RN << 16) / RM;
2167 gpu_remain = ((UINT64)RN << 16) % RM;
2172 gpu_remain = RN % RM;
2175 if ((gpu_remain - RM) & 0x80000000) // If the result would have been negative...
2176 gpu_remain -= RM; // Then make it negative!
2186 if (gpu_div_control & 1)
2188 gpu_remain = (((uint64)_RN) << 16) % _RM;
2189 if (gpu_remain&0x80000000)
2191 RN = (((uint64)_RN) << 16) / _RM;
2195 gpu_remain = _RN % _RM;
2196 if (gpu_remain&0x80000000)
2205 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);
2209 static void gpu_opcode_imultn(void)
2211 uint32 res = (int32)((int16)RN * (int16)RM);
2212 gpu_acc = (int32)res;
2217 static void gpu_opcode_neg(void)
2221 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);
2224 SET_ZNC_SUB(0, RN, res);
2228 WriteLog("[NCZ:%u%u%u, R%02u=%08X]\n", gpu_flag_n, gpu_flag_c, gpu_flag_z, IMM_2, RN);
2232 static void gpu_opcode_shlq(void)
2236 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);
2238 // Was a bug here...
2239 // (Look at Aaron's code: If r1 = 32, then 32 - 32 = 0 which is wrong!)
2240 INT32 r1 = 32 - IMM_1;
2241 UINT32 res = RN << r1;
2242 SET_ZN(res); gpu_flag_c = (RN >> 31) & 1;
2246 WriteLog("[NCZ:%u%u%u, R%02u=%08X]\n", gpu_flag_n, gpu_flag_c, gpu_flag_z, IMM_2, RN);
2250 static void gpu_opcode_shrq(void)
2254 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);
2256 INT32 r1 = gpu_convert_zero[IMM_1];
2257 UINT32 res = RN >> r1;
2258 SET_ZN(res); gpu_flag_c = RN & 1;
2262 WriteLog("[NCZ:%u%u%u, R%02u=%08X]\n", gpu_flag_n, gpu_flag_c, gpu_flag_z, IMM_2, RN);
2266 static void gpu_opcode_ror(void)
2270 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);
2272 UINT32 r1 = RM & 0x1F;
2273 UINT32 res = (RN >> r1) | (RN << (32 - r1));
2274 SET_ZN(res); gpu_flag_c = (RN >> 31) & 1;
2278 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);
2282 static void gpu_opcode_rorq(void)
2286 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);
2288 UINT32 r1 = gpu_convert_zero[IMM_1 & 0x1F];
2290 UINT32 res = (r2 >> r1) | (r2 << (32 - r1));
2292 SET_ZN(res); gpu_flag_c = (r2 >> 31) & 0x01;
2295 WriteLog("[NCZ:%u%u%u, R%02u=%08X]\n", gpu_flag_n, gpu_flag_c, gpu_flag_z, IMM_2, RN);
2299 static void gpu_opcode_sha(void)
2301 /* int dreg = jaguar.op & 31;
2302 INT32 r1 = (INT32)jaguar.r[(jaguar.op >> 5) & 31];
2303 UINT32 r2 = jaguar.r[dreg];
2309 res = (r1 <= -32) ? 0 : (r2 << -r1);
2310 jaguar.FLAGS |= (r2 >> 30) & 2;
2314 res = (r1 >= 32) ? ((INT32)r2 >> 31) : ((INT32)r2 >> r1);
2315 jaguar.FLAGS |= (r2 << 1) & 2;
2317 jaguar.r[dreg] = res;
2322 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);
2328 res = ((INT32)RM <= -32) ? 0 : (RN << -(INT32)RM);
2329 gpu_flag_c = RN >> 31;
2333 res = ((INT32)RM >= 32) ? ((INT32)RN >> 31) : ((INT32)RN >> (INT32)RM);
2334 gpu_flag_c = RN & 0x01;
2340 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);
2343 /* int32 sRM=(int32)RM;
2349 if (shift>=32) shift=32;
2350 gpu_flag_c=(_RN&0x80000000)>>31;
2360 if (shift>=32) shift=32;
2364 _RN=((int32)_RN)>>1;
2373 static void gpu_opcode_sharq(void)
2375 #ifdef GPU_DIS_SHARQ
2377 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);
2379 UINT32 res = (INT32)RN >> gpu_convert_zero[IMM_1];
2380 SET_ZN(res); gpu_flag_c = RN & 0x01;
2382 #ifdef GPU_DIS_SHARQ
2384 WriteLog("[NCZ:%u%u%u, R%02u=%08X]\n", gpu_flag_n, gpu_flag_c, gpu_flag_z, IMM_2, RN);
2388 static void gpu_opcode_sh(void)
2392 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);
2394 if (RM & 0x80000000) // Shift left
2396 gpu_flag_c = RN >> 31;
2397 RN = ((int32)RM <= -32 ? 0 : RN << -(int32)RM);
2401 gpu_flag_c = RN & 0x01;
2402 RN = (RM >= 32 ? 0 : RN >> RM);
2407 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);
2411 //Temporary: Testing only!
2412 //#include "gpu2.cpp"
2413 //#include "gpu3.cpp"