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
253 uint8 gpu_opcode_cycles[64] =
255 1, 1, 1, 1, 1, 1, 1, 1,
256 1, 1, 1, 1, 1, 1, 1, 1,
257 1, 1, 1, 1, 1, 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
265 void (*gpu_opcode[64])()=
267 gpu_opcode_add, gpu_opcode_addc, gpu_opcode_addq, gpu_opcode_addqt,
268 gpu_opcode_sub, gpu_opcode_subc, gpu_opcode_subq, gpu_opcode_subqt,
269 gpu_opcode_neg, gpu_opcode_and, gpu_opcode_or, gpu_opcode_xor,
270 gpu_opcode_not, gpu_opcode_btst, gpu_opcode_bset, gpu_opcode_bclr,
271 gpu_opcode_mult, gpu_opcode_imult, gpu_opcode_imultn, gpu_opcode_resmac,
272 gpu_opcode_imacn, gpu_opcode_div, gpu_opcode_abs, gpu_opcode_sh,
273 gpu_opcode_shlq, gpu_opcode_shrq, gpu_opcode_sha, gpu_opcode_sharq,
274 gpu_opcode_ror, gpu_opcode_rorq, gpu_opcode_cmp, gpu_opcode_cmpq,
275 gpu_opcode_sat8, gpu_opcode_sat16, gpu_opcode_move, gpu_opcode_moveq,
276 gpu_opcode_moveta, gpu_opcode_movefa, gpu_opcode_movei, gpu_opcode_loadb,
277 gpu_opcode_loadw, gpu_opcode_load, gpu_opcode_loadp, gpu_opcode_load_r14_indexed,
278 gpu_opcode_load_r15_indexed, gpu_opcode_storeb, gpu_opcode_storew, gpu_opcode_store,
279 gpu_opcode_storep, gpu_opcode_store_r14_indexed, gpu_opcode_store_r15_indexed, gpu_opcode_move_pc,
280 gpu_opcode_jump, gpu_opcode_jr, gpu_opcode_mmult, gpu_opcode_mtoi,
281 gpu_opcode_normi, gpu_opcode_nop, gpu_opcode_load_r14_ri, gpu_opcode_load_r15_ri,
282 gpu_opcode_store_r14_ri, gpu_opcode_store_r15_ri, gpu_opcode_sat24, gpu_opcode_pack,
285 static uint8 * gpu_ram_8;
287 static uint32 gpu_acc;
288 static uint32 gpu_remain;
289 static uint32 gpu_hidata;
290 static uint32 gpu_flags;
291 static uint32 gpu_matrix_control;
292 static uint32 gpu_pointer_to_matrix;
293 static uint32 gpu_data_organization;
294 static uint32 gpu_control;
295 static uint32 gpu_div_control;
296 // There is a distinct advantage to having these separated out--there's no need to clear
297 // a bit before writing a result. I.e., if the result of an operation leaves a zero in
298 // the carry flag, you don't have to zero gpu_flag_c before you can write that zero!
299 static uint8 gpu_flag_z, gpu_flag_n, gpu_flag_c;
300 static uint32 * gpu_reg_bank_0;
301 static uint32 * gpu_reg_bank_1;
302 static uint32 * gpu_reg;
303 static uint32 * gpu_alternate_reg;
305 static uint32 gpu_instruction;
306 static uint32 gpu_opcode_first_parameter;
307 static uint32 gpu_opcode_second_parameter;
309 #define GPU_RUNNING (gpu_control & 0x01)
311 #define RM gpu_reg[gpu_opcode_first_parameter]
312 #define RN gpu_reg[gpu_opcode_second_parameter]
313 #define ALTERNATE_RM gpu_alternate_reg[gpu_opcode_first_parameter]
314 #define ALTERNATE_RN gpu_alternate_reg[gpu_opcode_second_parameter]
315 #define IMM_1 gpu_opcode_first_parameter
316 #define IMM_2 gpu_opcode_second_parameter
318 #define SET_FLAG_Z(r) (gpu_flag_z = ((r) == 0));
319 #define SET_FLAG_N(r) (gpu_flag_n = (((UINT32)(r) >> 31) & 0x01));
321 #define RESET_FLAG_Z() gpu_flag_z = 0;
322 #define RESET_FLAG_N() gpu_flag_n = 0;
323 #define RESET_FLAG_C() gpu_flag_c = 0;
325 #define CLR_Z (gpu_flag_z = 0)
326 #define CLR_ZN (gpu_flag_z = gpu_flag_n = 0)
327 #define CLR_ZNC (gpu_flag_z = gpu_flag_n = gpu_flag_c = 0)
328 #define SET_Z(r) (gpu_flag_z = ((r) == 0))
329 #define SET_N(r) (gpu_flag_n = (((UINT32)(r) >> 31) & 0x01))
330 #define SET_C_ADD(a,b) (gpu_flag_c = ((UINT32)(b) > (UINT32)(~(a))))
331 #define SET_C_SUB(a,b) (gpu_flag_c = ((UINT32)(b) > (UINT32)(a)))
332 #define SET_ZN(r) SET_N(r); SET_Z(r)
333 #define SET_ZNC_ADD(a,b,r) SET_N(r); SET_Z(r); SET_C_ADD(a,b)
334 #define SET_ZNC_SUB(a,b,r) SET_N(r); SET_Z(r); SET_C_SUB(a,b)
336 uint32 gpu_convert_zero[32] =
337 { 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 };
339 uint8 * branch_condition_table = 0;
340 #define BRANCH_CONDITION(x) branch_condition_table[(x) + ((jaguar_flags & 7) << 5)]
342 uint32 gpu_opcode_use[64];
344 char * gpu_opcode_str[64]=
346 "add", "addc", "addq", "addqt",
347 "sub", "subc", "subq", "subqt",
348 "neg", "and", "or", "xor",
349 "not", "btst", "bset", "bclr",
350 "mult", "imult", "imultn", "resmac",
351 "imacn", "div", "abs", "sh",
352 "shlq", "shrq", "sha", "sharq",
353 "ror", "rorq", "cmp", "cmpq",
354 "sat8", "sat16", "move", "moveq",
355 "moveta", "movefa", "movei", "loadb",
356 "loadw", "load", "loadp", "load_r14_indexed",
357 "load_r15_indexed", "storeb", "storew", "store",
358 "storep", "store_r14_indexed","store_r15_indexed","move_pc",
359 "jump", "jr", "mmult", "mtoi",
360 "normi", "nop", "load_r14_ri", "load_r15_ri",
361 "store_r14_ri", "store_r15_ri", "sat24", "pack",
364 static uint32 gpu_in_exec = 0;
365 static uint32 gpu_releaseTimeSlice_flag = 0;
367 void gpu_releaseTimeslice(void)
369 gpu_releaseTimeSlice_flag = 1;
372 uint32 gpu_get_pc(void)
377 void build_branch_condition_table(void)
379 if (!branch_condition_table)
381 branch_condition_table = (uint8 *)malloc(32 * 8 * sizeof(branch_condition_table[0]));
383 if (branch_condition_table)
385 for(int i=0; i<8; i++)
387 for(int j=0; j<32; j++)
394 if (!(i & ZERO_FLAG))
397 if (i & (CARRY_FLAG << (j >> 4)))
400 if (!(i & (CARRY_FLAG << (j >> 4))))
402 branch_condition_table[i * 32 + j] = result;
410 // GPU byte access (read)
412 uint8 GPUReadByte(uint32 offset, uint32 who/*=UNKNOWN*/)
414 if (offset >= 0xF02000 && offset <= 0xF020FF)
415 WriteLog("GPU: ReadByte--Attempt to read from GPU register file by %s!\n", whoName[who]);
417 if ((offset >= GPU_WORK_RAM_BASE) && (offset < GPU_WORK_RAM_BASE+0x1000))
418 return gpu_ram_8[offset & 0xFFF];
419 else if ((offset >= GPU_CONTROL_RAM_BASE) && (offset < GPU_CONTROL_RAM_BASE+0x20))
421 uint32 data = GPUReadLong(offset & 0xFFFFFFFC, who);
423 if ((offset & 0x03) == 0)
425 else if ((offset & 0x03) == 1)
426 return (data >> 16) & 0xFF;
427 else if ((offset & 0x03) == 2)
428 return (data >> 8) & 0xFF;
429 else if ((offset & 0x03) == 3)
433 return JaguarReadByte(offset, who);
437 // GPU word access (read)
439 uint16 GPUReadWord(uint32 offset, uint32 who/*=UNKNOWN*/)
441 if (offset >= 0xF02000 && offset <= 0xF020FF)
442 WriteLog("GPU: ReadWord--Attempt to read from GPU register file by %s!\n", whoName[who]);
444 if ((offset >= GPU_WORK_RAM_BASE) && (offset < GPU_WORK_RAM_BASE+0x1000))
447 uint16 data = ((uint16)gpu_ram_8[offset] << 8) | (uint16)gpu_ram_8[offset+1];
450 else if ((offset >= GPU_CONTROL_RAM_BASE) && (offset < GPU_CONTROL_RAM_BASE+0x20))
452 // This looks and smells wrong...
453 // But it *might* be OK...
454 if (offset & 0x01) // Catch cases 1 & 3... (unaligned read)
455 return (GPUReadByte(offset, who) << 8) | GPUReadByte(offset+1, who);
457 uint32 data = GPUReadLong(offset & 0xFFFFFFFC, who);
459 if (offset & 0x02) // Cases 0 & 2...
460 return data & 0xFFFF;
465 //TEMP--Mirror of F03000? No. Writes only...
466 //if (offset >= 0xF0B000 && offset <= 0xF0BFFF)
467 //WriteLog("[GPUR16] --> Possible GPU RAM mirror access by %s!", whoName[who]);
469 return JaguarReadWord(offset, who);
473 // GPU dword access (read)
475 uint32 GPUReadLong(uint32 offset, uint32 who/*=UNKNOWN*/)
477 if (offset >= 0xF02000 && offset <= 0xF020FF)
478 WriteLog("GPU: ReadLong--Attempt to read from GPU register file by %s!\n", whoName[who]);
480 // if ((offset >= GPU_WORK_RAM_BASE) && (offset < GPU_WORK_RAM_BASE + 0x1000))
481 if ((offset >= GPU_WORK_RAM_BASE) && (offset <= GPU_WORK_RAM_BASE + 0x0FFC))
484 return ((uint32)gpu_ram_8[offset] << 24) | ((uint32)gpu_ram_8[offset+1] << 16)
485 | ((uint32)gpu_ram_8[offset+2] << 8) | (uint32)gpu_ram_8[offset+3];//*/
486 // return GET32(gpu_ram_8, offset);
488 // else if ((offset >= GPU_CONTROL_RAM_BASE) && (offset < GPU_CONTROL_RAM_BASE+0x20))
489 else if ((offset >= GPU_CONTROL_RAM_BASE) && (offset <= GPU_CONTROL_RAM_BASE + 0x1C))
495 gpu_flag_c = (gpu_flag_c ? 1 : 0);
496 gpu_flag_z = (gpu_flag_z ? 1 : 0);
497 gpu_flag_n = (gpu_flag_n ? 1 : 0);
499 gpu_flags = (gpu_flags & 0xFFFFFFF8) | (gpu_flag_n << 2) | (gpu_flag_c << 1) | gpu_flag_z;
501 return gpu_flags & 0xFFFFC1FF;
503 return gpu_matrix_control;
505 return gpu_pointer_to_matrix;
507 return gpu_data_organization;
516 default: // unaligned long read
518 WriteLog("GPU: Read32--unaligned 32 bit read at %08X by %s.\n", GPU_CONTROL_RAM_BASE + offset, whoName[who]);
523 //TEMP--Mirror of F03000? No. Writes only...
524 //if (offset >= 0xF0B000 && offset <= 0xF0BFFF)
525 // WriteLog("[GPUR32] --> Possible GPU RAM mirror access by %s!\n", whoName[who]);
526 /*if (offset >= 0xF1D000 && offset <= 0xF1DFFF)
527 WriteLog("[GPUR32] --> Reading from Wavetable ROM!\n");//*/
529 return (JaguarReadWord(offset, who) << 16) | JaguarReadWord(offset + 2, who);
533 // GPU byte access (write)
535 void GPUWriteByte(uint32 offset, uint8 data, uint32 who/*=UNKNOWN*/)
537 if (offset >= 0xF02000 && offset <= 0xF020FF)
538 WriteLog("GPU: WriteByte--Attempt to write to GPU register file by %s!\n", whoName[who]);
540 if ((offset >= GPU_WORK_RAM_BASE) && (offset <= GPU_WORK_RAM_BASE + 0x0FFF))
542 gpu_ram_8[offset & 0xFFF] = data;
544 //This is the same stupid worthless code that was in the DSP!!! AARRRGGGGHHHHH!!!!!!
547 m68k_end_timeslice();
548 dsp_releaseTimeslice();
552 else if ((offset >= GPU_CONTROL_RAM_BASE) && (offset <= GPU_CONTROL_RAM_BASE + 0x1F))
554 uint32 reg = offset & 0x1C;
555 int bytenum = offset & 0x03;
557 //This is definitely wrong!
558 if ((reg >= 0x1C) && (reg <= 0x1F))
559 gpu_div_control = (gpu_div_control & (~(0xFF << (bytenum << 3)))) | (data << (bytenum << 3));
562 uint32 old_data = GPUReadLong(offset & 0xFFFFFFC, who);
563 bytenum = 3 - bytenum; // convention motorola !!!
564 old_data = (old_data & (~(0xFF << (bytenum << 3)))) | (data << (bytenum << 3));
565 GPUWriteLong(offset & 0xFFFFFFC, old_data, who);
569 // WriteLog("gpu: writing %.2x at 0x%.8x\n",data,offset);
570 JaguarWriteByte(offset, data, who);
574 // GPU word access (write)
576 void GPUWriteWord(uint32 offset, uint16 data, uint32 who/*=UNKNOWN*/)
578 if (offset >= 0xF02000 && offset <= 0xF020FF)
579 WriteLog("GPU: WriteWord--Attempt to write to GPU register file by %s!\n", whoName[who]);
581 if ((offset >= GPU_WORK_RAM_BASE) && (offset <= GPU_WORK_RAM_BASE + 0x0FFE))
583 gpu_ram_8[offset & 0xFFF] = (data>>8) & 0xFF;
584 gpu_ram_8[(offset+1) & 0xFFF] = data & 0xFF;//*/
586 SET16(gpu_ram_8, offset, data);//*/
588 /*if (offset >= 0xF03214 && offset < 0xF0321F)
589 WriteLog("GPU: Writing WORD (%04X) to GPU RAM (%08X)...\n", data, offset);//*/
592 //This is the same stupid worthless code that was in the DSP!!! AARRRGGGGHHHHH!!!!!!
595 m68k_end_timeslice();
596 dsp_releaseTimeslice();
600 else if ((offset >= GPU_CONTROL_RAM_BASE) && (offset <= GPU_CONTROL_RAM_BASE + 0x1E))
602 if (offset & 0x01) // This is supposed to weed out unaligned writes, but does nothing...
605 WriteLog("GPU: Write16--unaligned write @ %08X [%04X]\n", offset, data);
610 //Dual locations in this range: $1C Divide unit remainder/Divide unit control (R/W)
611 //This just literally sucks.
612 if ((offset & 0x1C) == 0x1C)
614 //This doesn't look right either--handles cases 1, 2, & 3 all the same!
616 gpu_div_control = (gpu_div_control & 0xFFFF0000) | (data & 0xFFFF);
618 gpu_div_control = (gpu_div_control & 0x0000FFFF) | ((data & 0xFFFF) << 16);
622 //WriteLog("[GPU W16:%08X,%04X]", offset, data);
623 uint32 old_data = GPUReadLong(offset & 0xFFFFFFC, who);
625 old_data = (old_data & 0xFFFF0000) | (data & 0xFFFF);
627 old_data = (old_data & 0x0000FFFF) | ((data & 0xFFFF) << 16);
628 GPUWriteLong(offset & 0xFFFFFFC, old_data, who);
632 else if ((offset == GPU_WORK_RAM_BASE + 0x0FFF) || (GPU_CONTROL_RAM_BASE + 0x1F))
635 WriteLog("GPU: Write16--unaligned write @ %08X by %s [%04X]!\n", offset, whoName[who], data);
641 // Have to be careful here--this can cause an infinite loop!
642 JaguarWriteWord(offset, data, who);
646 // GPU dword access (write)
648 void GPUWriteLong(uint32 offset, uint32 data, uint32 who/*=UNKNOWN*/)
650 if (offset >= 0xF02000 && offset <= 0xF020FF)
651 WriteLog("GPU: WriteLong--Attempt to write to GPU register file by %s!\n", whoName[who]);
653 // if ((offset >= GPU_WORK_RAM_BASE) && (offset < GPU_WORK_RAM_BASE + 0x1000))
654 if ((offset >= GPU_WORK_RAM_BASE) && (offset <= GPU_WORK_RAM_BASE + 0x0FFC))
659 WriteLog("GPU: Write32--unaligned write @ %08X [%08X] by %s\n", offset, data, whoName[who]);
665 SET32(gpu_ram_8, offset, data);
668 // else if ((offset >= GPU_CONTROL_RAM_BASE) && (offset < GPU_CONTROL_RAM_BASE+0x20))
669 else if ((offset >= GPU_CONTROL_RAM_BASE) && (offset <= GPU_CONTROL_RAM_BASE + 0x1C))
676 bool IMASKCleared = (gpu_flags & IMASK) && !(data & IMASK);
678 gpu_flag_z = gpu_flags & ZERO_FLAG;
679 gpu_flag_c = (gpu_flags & CARRY_FLAG) >> 1;
680 gpu_flag_n = (gpu_flags & NEGA_FLAG) >> 2;
681 GPUUpdateRegisterBanks();
682 gpu_control &= ~((gpu_flags & CINT04FLAGS) >> 3); // Interrupt latch clear bits
683 //Writing here is only an interrupt enable--this approach is just plain wrong!
685 //This, however, is A-OK! ;-)
686 if (IMASKCleared) // If IMASK was cleared,
687 GPUHandleIRQs(); // see if any other interrupts need servicing!
689 if (gpu_flags & (INT_ENA0 | INT_ENA1 | INT_ENA2 | INT_ENA3 | INT_ENA4))
690 WriteLog("GPU: Interrupt enable set by %s! Bits: %02X\n", whoName[who], (gpu_flags >> 4) & 0x1F);
691 WriteLog("GPU: REGPAGE %s...\n", (gpu_flags & REGPAGE ? "set" : "cleared"));
696 gpu_matrix_control = data;
699 // This can only point to long aligned addresses
700 gpu_pointer_to_matrix = data & 0xFFFFFFFC;
703 gpu_data_organization = data;
708 WriteLog("GPU: %s setting GPU PC to %08X %s\n", whoName[who], gpu_pc, (GPU_RUNNING ? "(GPU is RUNNING!)" : ""));//*/
713 // uint32 gpu_was_running = GPU_RUNNING;
714 data &= ~0xF7C0; // Disable writes to INT_LAT0-4 & TOM version number
716 // check for GPU -> CPU interrupt
719 //WriteLog("GPU->CPU interrupt\n");
720 if (tom_irq_enabled(IRQ_GPU))
722 if ((tom_irq_enabled(IRQ_GPU)) && (jaguar_interrupt_handler_is_valid(64)))
724 tom_set_pending_gpu_int();
725 m68k_set_irq(7); // Set 68000 NMI
726 gpu_releaseTimeslice();
732 // check for CPU -> GPU interrupt #0
735 //WriteLog("CPU->GPU interrupt\n");
736 GPUSetIRQLine(0, ASSERT_LINE);
737 m68k_end_timeslice();
738 dsp_releaseTimeslice();
745 //WriteLog("asked to perform a single step (single step is %senabled)\n",(data&0x8)?"":"not ");
747 gpu_control = (gpu_control & 0xF7C0) | (data & (~0xF7C0));
749 // if gpu wasn't running but is now running, execute a few cycles
750 #ifndef GPU_SINGLE_STEPPING
751 /* if (!gpu_was_running && GPU_RUNNING)
754 WriteLog("GPU: Write32--About to do stupid braindead GPU execution for 200 cycles.\n");
759 #endif // GPU_DEBUG//*/
761 if (gpu_control & 0x18)
763 #endif // #ifndef GPU_SINGLE_STEPPING
765 WriteLog("Write to GPU CTRL by %s: %08X ", whoName[who], data);
767 WriteLog(" --> Starting to run at %08X by %s...", gpu_pc, whoName[who]);
769 WriteLog(" --> Stopped by %s! (GPU_PC: %08X)", whoName[who], gpu_pc);
773 // GPUDumpDisassembly();
776 if (gpu_pc == 0xF035D8)
778 // GPUDumpDisassembly();
781 gpu_control &= 0xFFFFFFFE; // Don't run it and let's see what happens!
782 //Hmm. Seems to lock up when going into the demo...
783 //Try to disable the collision altogether!
786 extern int effect_start5;
787 static bool finished = false;
788 //if (GPU_RUNNING && effect_start5 && !finished)
789 if (GPU_RUNNING && effect_start5 && gpu_pc == 0xF035D8)
791 // Let's do a dump of $6528!
792 /* uint32 numItems = JaguarReadWord(0x6BD6);
793 WriteLog("\nDump of $6528: %u items.\n\n", numItems);
794 for(int i=0; i<numItems*3*4; i+=3*4)
796 WriteLog("\t%04X: %08X %08X %08X -> ", 0x6528+i, JaguarReadLong(0x6528+i),
797 JaguarReadLong(0x6528+i+4), JaguarReadLong(0x6528+i+8));
798 uint16 link = JaguarReadWord(0x6528+i+8+2);
799 for(int j=0; j<40; j+=4)
800 WriteLog("%08X ", JaguarReadLong(link + j));
804 // Let's try a manual blit here...
805 //This isn't working the way it should! !!! FIX !!!
806 //Err, actually, it is.
807 // NOW, it works right! Problem solved!!! It's a blitter bug!
808 /* uint32 src = 0x4D54, dst = 0xF03000, width = 10 * 4;
809 for(int y=0; y<127; y++)
811 for(int x=0; x<2; x++)
813 JaguarWriteLong(dst, JaguarReadLong(src));
818 src += width - (2 * 4);
822 WriteLog("\nGPU: About to execute collision detection code.\n\n");//*/
824 /* WriteLog("\nGPU: About to execute collision detection code. Data @ 4D54:\n\n");
826 for(int i=0x004D54; i<0x004D54+2048; i++)
828 WriteLog("%02X ", JaguarReadByte(i));
836 WriteLog("\n\nData @ F03000:\n\n");
838 for(int i=0xF03000; i<0xF03200; i++)
840 WriteLog("%02X ", JaguarReadByte(i));
854 /*if (!GPU_RUNNING && finished)
856 WriteLog("\nGPU: Finished collision detection code. Exiting!\n\n");
861 // (?) If we're set running by the M68K (or DSP?) then end its timeslice to
862 // allow the GPU a chance to run...
863 // Yes! This partially fixed Trevor McFur...
865 m68k_end_timeslice();
872 gpu_div_control = data;
874 // default: // unaligned long write
881 // JaguarWriteWord(offset, (data >> 16) & 0xFFFF, who);
882 // JaguarWriteWord(offset+2, data & 0xFFFF, who);
883 // We're a 32-bit processor, we can do a long write...!
884 JaguarWriteLong(offset, data, who);
888 // Change register banks if necessary
890 void GPUUpdateRegisterBanks(void)
892 int bank = (gpu_flags & REGPAGE); // REGPAGE bit
894 if (gpu_flags & IMASK) // IMASK bit
895 bank = 0; // IMASK forces main bank to be bank 0
898 gpu_reg = gpu_reg_bank_1, gpu_alternate_reg = gpu_reg_bank_0;
900 gpu_reg = gpu_reg_bank_0, gpu_alternate_reg = gpu_reg_bank_1;
903 void GPUHandleIRQs(void)
905 // Bail out if we're already in an interrupt!
906 if (gpu_flags & IMASK)
909 // Get the interrupt latch & enable bits
910 uint32 bits = (gpu_control >> 6) & 0x1F, mask = (gpu_flags >> 4) & 0x1F;
912 // Bail out if latched interrupts aren't enabled
917 // Determine which interrupt to service
918 uint32 which = 0; //Isn't there a #pragma to disable this warning???
931 WriteLog("GPU: Generating IRQ #%i\n", which);
933 // set the interrupt flag
935 GPUUpdateRegisterBanks();
937 // subqt #4,r31 ; pre-decrement stack pointer
938 // move pc,r30 ; address of interrupted code
939 // store r30,(r31) ; store return address
941 GPUWriteLong(gpu_reg[31], gpu_pc - 2, GPU);
943 // movei #service_address,r30 ; pointer to ISR entry
944 // jump (r30) ; jump to ISR
946 gpu_pc = gpu_reg[30] = GPU_WORK_RAM_BASE + (which * 0x10);
949 void GPUSetIRQLine(int irqline, int state)
952 WriteLog("GPU: Setting GPU IRQ line #%i\n", irqline);
954 uint32 mask = 0x0040 << irqline;
955 gpu_control &= ~mask; // Clear the interrupt latch
959 gpu_control |= mask; // Assert the interrupt latch
960 GPUHandleIRQs(); // And handle the interrupt...
964 //TEMPORARY: Testing only!
970 memory_malloc_secure((void **)&gpu_ram_8, 0x1000, "GPU work RAM");
971 memory_malloc_secure((void **)&gpu_reg_bank_0, 32 * sizeof(int32), "GPU bank 0 regs");
972 memory_malloc_secure((void **)&gpu_reg_bank_1, 32 * sizeof(int32), "GPU bank 1 regs");
974 build_branch_condition_table();
978 //TEMPORARY: Testing only!
985 // GPU registers (directly visible)
986 gpu_flags = 0x00000000;
987 gpu_matrix_control = 0x00000000;
988 gpu_pointer_to_matrix = 0x00000000;
989 gpu_data_organization = 0xFFFFFFFF;
991 gpu_control = 0x00002800; // Correctly sets this as TOM Rev. 2
992 gpu_hidata = 0x00000000;
993 gpu_remain = 0x00000000; // These two registers are RO/WO
994 gpu_div_control = 0x00000000;
996 // GPU internal register
997 gpu_acc = 0x00000000;
999 gpu_reg = gpu_reg_bank_0;
1000 gpu_alternate_reg = gpu_reg_bank_1;
1002 for(int i=0; i<32; i++)
1003 gpu_reg[i] = gpu_alternate_reg[i] = 0x00000000;
1006 memset(gpu_ram_8, 0xFF, 0x1000);
1008 //not needed GPUInterruptPending = false;
1012 uint32 gpu_read_pc(void)
1017 void gpu_reset_stats(void)
1019 for(uint32 i=0; i<64; i++)
1020 gpu_opcode_use[i] = 0;
1021 WriteLog("--> GPU stats were reset!\n");
1024 void GPUDumpDisassembly(void)
1028 WriteLog("\n---[GPU code at 00F03000]---------------------------\n");
1029 uint32 j = 0xF03000;
1030 while (j <= 0xF03FFF)
1033 j += dasmjag(JAGUAR_GPU, buffer, j);
1034 WriteLog("\t%08X: %s\n", oldj, buffer);
1038 void GPUDumpRegisters(void)
1040 WriteLog("\n---[GPU flags: NCZ %d%d%d]-----------------------\n", gpu_flag_n, gpu_flag_c, gpu_flag_z);
1041 WriteLog("\nRegisters bank 0\n");
1042 for(int j=0; j<8; j++)
1044 WriteLog("\tR%02i = %08X R%02i = %08X R%02i = %08X R%02i = %08X\n",
1045 (j << 2) + 0, gpu_reg_bank_0[(j << 2) + 0],
1046 (j << 2) + 1, gpu_reg_bank_0[(j << 2) + 1],
1047 (j << 2) + 2, gpu_reg_bank_0[(j << 2) + 2],
1048 (j << 2) + 3, gpu_reg_bank_0[(j << 2) + 3]);
1050 WriteLog("Registers bank 1\n");
1051 for(int j=0; j<8; j++)
1053 WriteLog("\tR%02i = %08X R%02i = %08X R%02i = %08X R%02i = %08X\n",
1054 (j << 2) + 0, gpu_reg_bank_1[(j << 2) + 0],
1055 (j << 2) + 1, gpu_reg_bank_1[(j << 2) + 1],
1056 (j << 2) + 2, gpu_reg_bank_1[(j << 2) + 2],
1057 (j << 2) + 3, gpu_reg_bank_1[(j << 2) + 3]);
1061 void GPUDumpMemory(void)
1063 WriteLog("\n---[GPU data at 00F03000]---------------------------\n");
1064 for(int i=0; i<0xFFF; i+=4)
1065 WriteLog("\t%08X: %02X %02X %02X %02X\n", 0xF03000+i, gpu_ram_8[i],
1066 gpu_ram_8[i+1], gpu_ram_8[i+2], gpu_ram_8[i+3]);
1071 WriteLog("GPU: Stopped at PC=%08X (GPU %s running)\n", (unsigned int)gpu_pc, GPU_RUNNING ? "was" : "wasn't");
1073 // Get the interrupt latch & enable bits
1074 uint8 bits = (gpu_control >> 6) & 0x1F, mask = (gpu_flags >> 4) & 0x1F;
1075 WriteLog("GPU: Latch bits = %02X, enable bits = %02X\n", bits, mask);
1078 GPUDumpDisassembly();
1080 WriteLog("\nGPU opcodes use:\n");
1081 for(int i=0; i<64; i++)
1083 if (gpu_opcode_use[i])
1084 WriteLog("\t%17s %lu\n", gpu_opcode_str[i], gpu_opcode_use[i]);
1088 memory_free(gpu_ram_8);
1089 memory_free(gpu_reg_bank_0);
1090 memory_free(gpu_reg_bank_1);
1094 // Main GPU execution core
1096 static int testCount = 1;
1098 static bool tripwire = false;
1099 void gpu_exec(int32 cycles)
1104 #ifdef GPU_SINGLE_STEPPING
1105 if (gpu_control & 0x18)
1108 gpu_control &= ~0x10;
1112 gpu_releaseTimeSlice_flag = 0;
1115 while (cycles > 0 && GPU_RUNNING)
1117 if (gpu_ram_8[0x054] == 0x98 && gpu_ram_8[0x055] == 0x0A && gpu_ram_8[0x056] == 0x03
1118 && gpu_ram_8[0x057] == 0x00 && gpu_ram_8[0x058] == 0x00 && gpu_ram_8[0x059] == 0x00)
1120 if (gpu_pc == 0xF03000)
1122 extern uint32 starCount;
1124 /* WriteLog("GPU: Starting starfield generator... Dump of [R03=%08X]:\n", gpu_reg_bank_0[03]);
1125 uint32 base = gpu_reg_bank_0[3];
1126 for(uint32 i=0; i<0x100; i+=16)
1128 WriteLog("%02X: ", i);
1129 for(uint32 j=0; j<16; j++)
1131 WriteLog("%02X ", JaguarReadByte(base + i + j));
1136 // if (gpu_pc == 0xF03)
1140 /*if (gpu_pc == 0xF03B9E && gpu_reg_bank_0[01] == 0)
1143 WriteLog("GPU: Starting disassembly log...\n");
1146 /*if (gpu_pc == 0xF0359A)
1151 /* gpu_flag_c = (gpu_flag_c ? 1 : 0);
1152 gpu_flag_z = (gpu_flag_z ? 1 : 0);
1153 gpu_flag_n = (gpu_flag_n ? 1 : 0);*/
1155 uint16 opcode = GPUReadWord(gpu_pc, GPU);
1156 uint32 index = opcode >> 10;
1157 gpu_instruction = opcode; // Added for GPU #3...
1158 gpu_opcode_first_parameter = (opcode >> 5) & 0x1F;
1159 gpu_opcode_second_parameter = opcode & 0x1F;
1160 /*if (gpu_pc == 0xF03BE8)
1161 WriteLog("Start of OP frame write...\n");
1162 if (gpu_pc == 0xF03EEE)
1163 WriteLog("--> Writing BRANCH object ---\n");
1164 if (gpu_pc == 0xF03F62)
1165 WriteLog("--> Writing BITMAP object ***\n");//*/
1166 /*if (gpu_pc == 0xF03546)
1168 WriteLog("\n--> GPU PC: F03546\n");
1170 GPUDumpDisassembly();
1172 /*if (gpu_pc == 0xF033F6)
1174 WriteLog("\n--> GPU PC: F033F6\n");
1176 GPUDumpDisassembly();
1178 /*if (gpu_pc == 0xF033CC)
1180 WriteLog("\n--> GPU PC: F033CC\n");
1182 GPUDumpDisassembly();
1184 /*if (gpu_pc == 0xF033D6)
1186 WriteLog("\n--> GPU PC: F033D6 (#%d)\n", testCount++);
1190 /*if (gpu_pc == 0xF033D8)
1192 WriteLog("\n--> GPU PC: F033D8 (#%d)\n", testCount++);
1196 /*if (gpu_pc == 0xF0358E)
1198 WriteLog("\n--> GPU PC: F0358E (#%d)\n", testCount++);
1202 /*if (gpu_pc == 0xF034CA)
1204 WriteLog("\n--> GPU PC: F034CA (#%d)\n", testCount++);
1207 /*if (gpu_pc == 0xF034CA)
1209 len = gpu_reg[1] + 4;//, r9save = gpu_reg[9];
1210 WriteLog("\nAbout to subtract [#%d] (R14=%08X, R15=%08X, R9=%08X):\n ", testCount++, gpu_reg[14], gpu_reg[15], gpu_reg[9]);
1211 for(int i=0; i<len; i+=4)
1212 WriteLog(" %08X", GPUReadLong(gpu_reg[15]+i));
1214 for(int i=0; i<len; i+=4)
1215 WriteLog(" %08X", GPUReadLong(gpu_reg[14]+i));
1218 if (gpu_pc == 0xF034DE)
1220 WriteLog("\nSubtracted! (R14=%08X, R15=%08X):\n ", gpu_reg[14], gpu_reg[15]);
1221 for(int i=0; i<len; i+=4)
1222 WriteLog(" %08X", GPUReadLong(gpu_reg[15]+i));
1224 for(int i=0; i<len; i+=4)
1225 WriteLog(" %08X", GPUReadLong(gpu_reg[14]+i));
1227 for(int i=0; i<len; i+=4)
1228 WriteLog(" --------");
1230 for(int i=0; i<len; i+=4)
1231 WriteLog(" %08X", GPUReadLong(gpu_reg[9]+4+i));
1234 /*if (gpu_pc == 0xF035C8)
1236 WriteLog("\n--> GPU PC: F035C8 (#%d)\n", testCount++);
1238 GPUDumpDisassembly();
1243 // gpu_reset_stats();
1244 static char buffer[512];
1245 dasmjag(JAGUAR_GPU, buffer, gpu_pc);
1246 WriteLog("GPU: [%08X] %s (RM=%08X, RN=%08X) -> ", gpu_pc, buffer, RM, RN);
1248 //$E400 -> 1110 01 -> $39 -> 57
1251 gpu_opcode[index]();
1253 // gpu2_opcode[index]();
1255 //GPU #3 (Doesn't show ATARI logo! #1 & #2 do...)
1257 // gpu3_opcode[index]();
1260 //GPU: [00F03548] jr nz,00F03560 (0xd561) (RM=00F03114, RN=00000004) -> --> JR: Branch taken.
1261 /*static bool firstTime = true;
1262 if (gpu_pc == 0xF03548 && firstTime)
1265 // firstTime = false;
1267 //static char buffer[512];
1269 //while (k<0xF0356C)
1272 //k += dasmjag(JAGUAR_GPU, buffer, k);
1273 //WriteLog("GPU: [%08X] %s\n", oldk, buffer);
1275 // gpu_start_log = 1;
1277 //GPU: [00F0354C] jump nz,(r29) (0xd3a1) (RM=00F03314, RN=00000004) -> (RM=00F03314, RN=00000004)
1278 /*if (gpu_pc == 0xF0354C)
1279 gpu_flag_z = 0;//, gpu_start_log = 1;//*/
1281 cycles -= gpu_opcode_cycles[index];
1282 gpu_opcode_use[index]++;
1284 WriteLog("(RM=%08X, RN=%08X)\n", RM, RN);//*/
1285 if ((gpu_pc < 0xF03000 || gpu_pc > 0xF03FFF) && !tripwire)
1287 WriteLog("GPU: Executing outside local RAM! GPU_PC: %08X\n", gpu_pc);
1300 GPU opcodes use (offset punch--vertically below bad guy):
1322 load_r14_indexed 1183
1323 load_r15_indexed 1125
1326 store_r14_indexed 320
1334 static void gpu_opcode_jump(void)
1337 char * condition[32] =
1338 { "T", "nz", "z", "???", "nc", "nc nz", "nc z", "???", "c", "c nz",
1339 "c z", "???", "???", "???", "???", "???", "???", "???", "???",
1340 "???", "nn", "nn nz", "nn z", "???", "n", "n nz", "n z", "???",
1341 "???", "???", "???", "F" };
1343 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);
1346 /* gpu_flag_c = (gpu_flag_c ? 1 : 0);
1347 gpu_flag_z = (gpu_flag_z ? 1 : 0);
1348 gpu_flag_n = (gpu_flag_n ? 1 : 0);*/
1349 // KLUDGE: Used by BRANCH_CONDITION
1350 uint32 jaguar_flags = (gpu_flag_n << 2) | (gpu_flag_c << 1) | gpu_flag_z;
1352 if (BRANCH_CONDITION(IMM_2))
1356 WriteLog("Branched!\n");
1359 WriteLog(" --> JUMP: Branch taken.\n");
1360 uint32 delayed_pc = RM;
1362 gpu_pc = delayed_pc;
1363 /* uint16 opcode = GPUReadWord(gpu_pc, GPU);
1364 gpu_opcode_first_parameter = (opcode >> 5) & 0x1F;
1365 gpu_opcode_second_parameter = opcode & 0x1F;
1367 gpu_pc = delayed_pc;
1368 gpu_opcode[opcode>>10]();//*/
1373 WriteLog("Branch NOT taken.\n");
1377 static void gpu_opcode_jr(void)
1380 char * condition[32] =
1381 { "T", "nz", "z", "???", "nc", "nc nz", "nc z", "???", "c", "c nz",
1382 "c z", "???", "???", "???", "???", "???", "???", "???", "???",
1383 "???", "nn", "nn nz", "nn z", "???", "n", "n nz", "n z", "???",
1384 "???", "???", "???", "F" };
1386 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);
1388 /* if (CONDITION(jaguar.op & 31))
1390 INT32 r1 = (INT8)((jaguar.op >> 2) & 0xF8) >> 2;
1391 UINT32 newpc = jaguar.PC + r1;
1393 jaguar.op = ROPCODE(jaguar.PC);
1395 (*jaguar.table[jaguar.op >> 10])();
1397 jaguar_icount -= 3; // 3 wait states guaranteed
1400 /* gpu_flag_n = (gpu_flag_n ? 1 : 0);
1401 gpu_flag_c = (gpu_flag_c ? 1 : 0);
1402 gpu_flag_z = (gpu_flag_z ? 1 : 0);*/
1403 // KLUDGE: Used by BRANCH_CONDITION
1404 uint32 jaguar_flags = (gpu_flag_n << 2) | (gpu_flag_c << 1) | gpu_flag_z;
1406 if (BRANCH_CONDITION(IMM_2))
1410 WriteLog("Branched!\n");
1413 WriteLog(" --> JR: Branch taken.\n");
1414 int32 offset = (IMM_1 & 0x10 ? 0xFFFFFFF0 | IMM_1 : IMM_1); // Sign extend IMM_1
1415 int32 delayed_pc = gpu_pc + (offset * 2);
1417 gpu_pc = delayed_pc;
1418 /* uint16 opcode = GPUReadWord(gpu_pc, GPU);
1419 gpu_opcode_first_parameter = (opcode >> 5) & 0x1F;
1420 gpu_opcode_second_parameter = opcode & 0x1F;
1422 gpu_pc = delayed_pc;
1423 gpu_opcode[opcode>>10]();//*/
1428 WriteLog("Branch NOT taken.\n");
1432 static void gpu_opcode_add(void)
1436 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);
1438 UINT32 res = RN + RM;
1439 CLR_ZNC; SET_ZNC_ADD(RN, RM, res);
1443 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);
1447 static void gpu_opcode_addc(void)
1451 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);
1453 /* int dreg = jaguar.op & 31;
1454 UINT32 r1 = jaguar.r[(jaguar.op >> 5) & 31];
1455 UINT32 r2 = jaguar.r[dreg];
1456 UINT32 res = r2 + r1 + ((jaguar.FLAGS >> 1) & 1);
1457 jaguar.r[dreg] = res;
1458 CLR_ZNC; SET_ZNC_ADD(r2,r1,res);*/
1460 UINT32 res = RN + RM + gpu_flag_c;
1461 UINT32 carry = gpu_flag_c;
1462 // SET_ZNC_ADD(RN, RM, res); //???BUG??? Yes!
1463 SET_ZNC_ADD(RN + carry, RM, res);
1464 // SET_ZNC_ADD(RN, RM + carry, res);
1468 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);
1472 static void gpu_opcode_addq(void)
1476 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);
1478 UINT32 r1 = gpu_convert_zero[IMM_1];
1479 UINT32 res = RN + r1;
1480 CLR_ZNC; SET_ZNC_ADD(RN, r1, res);
1484 WriteLog("[NCZ:%u%u%u, R%02u=%08X]\n", gpu_flag_n, gpu_flag_c, gpu_flag_z, IMM_2, RN);
1488 static void gpu_opcode_addqt(void)
1490 #ifdef GPU_DIS_ADDQT
1492 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);
1494 RN += gpu_convert_zero[IMM_1];
1495 #ifdef GPU_DIS_ADDQT
1497 WriteLog("[NCZ:%u%u%u, R%02u=%08X]\n", gpu_flag_n, gpu_flag_c, gpu_flag_z, IMM_2, RN);
1501 static void gpu_opcode_sub(void)
1505 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);
1507 UINT32 res = RN - RM;
1508 SET_ZNC_SUB(RN, RM, res);
1512 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);
1516 static void gpu_opcode_subc(void)
1520 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);
1522 UINT32 res = RN - RM - gpu_flag_c;
1523 UINT32 borrow = gpu_flag_c;
1524 // SET_ZNC_SUB(RN, RM, res); //???BUG??? YES!!!
1525 //No matter how you do it, there is a problem. With below, it's 0-0 with carry,
1526 //and the one below it it's FFFFFFFF - FFFFFFFF with carry... !!! FIX !!!
1527 // SET_ZNC_SUB(RN - borrow, RM, res);
1528 SET_ZNC_SUB(RN, RM + borrow, res);
1532 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);
1536 N = 5, M = 3, 3 - 5 = -2, C = 1... Or, in our case:
1537 N = 0, M = 1, 0 - 1 = -1, C = 0!
1539 #define SET_C_SUB(a,b) (gpu_flag_c = ((UINT32)(b) > (UINT32)(a)))
1540 #define SET_ZN(r) SET_N(r); SET_Z(r)
1541 #define SET_ZNC_ADD(a,b,r) SET_N(r); SET_Z(r); SET_C_ADD(a,b)
1542 #define SET_ZNC_SUB(a,b,r) SET_N(r); SET_Z(r); SET_C_SUB(a,b)
1544 static void gpu_opcode_subq(void)
1548 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);
1550 UINT32 r1 = gpu_convert_zero[IMM_1];
1551 UINT32 res = RN - r1;
1552 SET_ZNC_SUB(RN, r1, res);
1556 WriteLog("[NCZ:%u%u%u, R%02u=%08X]\n", gpu_flag_n, gpu_flag_c, gpu_flag_z, IMM_2, RN);
1560 static void gpu_opcode_subqt(void)
1562 #ifdef GPU_DIS_SUBQT
1564 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);
1566 RN -= gpu_convert_zero[IMM_1];
1567 #ifdef GPU_DIS_SUBQT
1569 WriteLog("[NCZ:%u%u%u, R%02u=%08X]\n", gpu_flag_n, gpu_flag_c, gpu_flag_z, IMM_2, RN);
1573 static void gpu_opcode_cmp(void)
1577 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);
1579 UINT32 res = RN - RM;
1580 SET_ZNC_SUB(RN, RM, res);
1583 WriteLog("[NCZ:%u%u%u]\n", gpu_flag_n, gpu_flag_c, gpu_flag_z);
1587 static void gpu_opcode_cmpq(void)
1589 static int32 sqtable[32] =
1590 { 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 };
1593 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);
1595 UINT32 r1 = sqtable[IMM_1 & 0x1F]; // I like this better -> (INT8)(jaguar.op >> 2) >> 3;
1596 UINT32 res = RN - r1;
1597 SET_ZNC_SUB(RN, r1, res);
1600 WriteLog("[NCZ:%u%u%u]\n", gpu_flag_n, gpu_flag_c, gpu_flag_z);
1604 static void gpu_opcode_and(void)
1608 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);
1614 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);
1618 static void gpu_opcode_or(void)
1622 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);
1628 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);
1632 static void gpu_opcode_xor(void)
1636 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);
1642 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);
1646 static void gpu_opcode_not(void)
1650 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);
1656 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);
1660 static void gpu_opcode_move_pc(void)
1662 #ifdef GPU_DIS_MOVEPC
1664 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);
1666 // Should be previous PC--this might not always be previous instruction!
1667 // Then again, this will point right at the *current* instruction, i.e., MOVE PC,R!
1669 #ifdef GPU_DIS_MOVEPC
1671 WriteLog("[NCZ:%u%u%u, R%02u=%08X]\n", gpu_flag_n, gpu_flag_c, gpu_flag_z, IMM_2, RN);
1675 static void gpu_opcode_sat8(void)
1679 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);
1681 RN = ((int32)RN < 0 ? 0 : (RN > 0xFF ? 0xFF : RN));
1685 WriteLog("[NCZ:%u%u%u, R%02u=%08X]\n", gpu_flag_n, gpu_flag_c, gpu_flag_z, IMM_2, RN);
1689 static void gpu_opcode_sat16(void)
1691 RN = ((int32)RN < 0 ? 0 : (RN > 0xFFFF ? 0xFFFF : RN));
1695 static void gpu_opcode_sat24(void)
1697 RN = ((int32)RN < 0 ? 0 : (RN > 0xFFFFFF ? 0xFFFFFF : RN));
1701 static void gpu_opcode_store_r14_indexed(void)
1703 #ifdef GPU_DIS_STORE14I
1705 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));
1707 GPUWriteLong(gpu_reg[14] + (gpu_convert_zero[IMM_1] << 2), RN, GPU);
1710 static void gpu_opcode_store_r15_indexed(void)
1712 #ifdef GPU_DIS_STORE15I
1714 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));
1716 GPUWriteLong(gpu_reg[15] + (gpu_convert_zero[IMM_1] << 2), RN, GPU);
1719 static void gpu_opcode_load_r14_ri(void)
1721 #ifdef GPU_DIS_LOAD14R
1723 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);
1725 RN = GPUReadLong(gpu_reg[14] + RM, GPU);
1726 #ifdef GPU_DIS_LOAD14R
1728 WriteLog("[NCZ:%u%u%u, R%02u=%08X]\n", gpu_flag_n, gpu_flag_c, gpu_flag_z, IMM_2, RN);
1732 static void gpu_opcode_load_r15_ri(void)
1734 #ifdef GPU_DIS_LOAD15R
1736 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);
1738 RN = GPUReadLong(gpu_reg[15] + RM, GPU);
1739 #ifdef GPU_DIS_LOAD15R
1741 WriteLog("[NCZ:%u%u%u, R%02u=%08X]\n", gpu_flag_n, gpu_flag_c, gpu_flag_z, IMM_2, RN);
1745 static void gpu_opcode_store_r14_ri(void)
1747 #ifdef GPU_DIS_STORE14R
1749 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]);
1751 GPUWriteLong(gpu_reg[14] + RM, RN, GPU);
1754 static void gpu_opcode_store_r15_ri(void)
1756 #ifdef GPU_DIS_STORE15R
1758 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]);
1760 GPUWriteLong(gpu_reg[15] + RM, RN, GPU);
1763 static void gpu_opcode_nop(void)
1767 WriteLog("%06X: NOP [NCZ:%u%u%u]\n", gpu_pc-2, gpu_flag_n, gpu_flag_c, gpu_flag_z);
1771 static void gpu_opcode_pack(void)
1775 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);
1779 //BUG! if (RM == 0) // Pack
1780 if (IMM_1 == 0) // Pack
1781 RN = ((val >> 10) & 0x0000F000) | ((val >> 5) & 0x00000F00) | (val & 0x000000FF);
1783 RN = ((val & 0x0000F000) << 10) | ((val & 0x00000F00) << 5) | (val & 0x000000FF);
1786 WriteLog("[NCZ:%u%u%u, R%02u=%08X]\n", gpu_flag_n, gpu_flag_c, gpu_flag_z, IMM_2, RN);
1790 static void gpu_opcode_storeb(void)
1792 #ifdef GPU_DIS_STOREB
1794 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);
1797 // Would appear to be so...!
1798 if ((RM >= 0xF03000) && (RM <= 0xF03FFF))
1799 GPUWriteLong(RM, RN & 0xFF, GPU);
1801 JaguarWriteByte(RM, RN, GPU);
1804 static void gpu_opcode_storew(void)
1806 #ifdef GPU_DIS_STOREW
1808 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);
1810 if ((RM >= 0xF03000) && (RM <= 0xF03FFF))
1811 GPUWriteLong(RM, RN & 0xFFFF, GPU);
1813 JaguarWriteWord(RM, RN, GPU);
1816 static void gpu_opcode_store(void)
1818 #ifdef GPU_DIS_STORE
1820 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);
1822 GPUWriteLong(RM, RN, GPU);
1825 static void gpu_opcode_storep(void)
1827 GPUWriteLong(RM + 0, gpu_hidata, GPU);
1828 GPUWriteLong(RM + 4, RN, GPU);
1831 static void gpu_opcode_loadb(void)
1833 #ifdef GPU_DIS_LOADB
1835 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);
1837 if ((RM >= 0xF03000) && (RM <= 0xF03FFF))
1838 RN = GPUReadLong(RM, GPU) & 0xFF;
1840 RN = JaguarReadByte(RM, GPU);
1841 #ifdef GPU_DIS_LOADB
1843 WriteLog("[NCZ:%u%u%u, R%02u=%08X]\n", gpu_flag_n, gpu_flag_c, gpu_flag_z, IMM_2, RN);
1847 static void gpu_opcode_loadw(void)
1849 #ifdef GPU_DIS_LOADW
1851 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);
1853 if ((RM >= 0xF03000) && (RM <= 0xF03FFF))
1854 RN = GPUReadLong(RM, GPU) & 0xFFFF;
1856 RN = JaguarReadWord(RM, GPU);
1857 #ifdef GPU_DIS_LOADW
1859 WriteLog("[NCZ:%u%u%u, R%02u=%08X]\n", gpu_flag_n, gpu_flag_c, gpu_flag_z, IMM_2, RN);
1863 static void gpu_opcode_load(void)
1867 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);
1869 RN = GPUReadLong(RM, GPU);
1872 WriteLog("[NCZ:%u%u%u, R%02u=%08X]\n", gpu_flag_n, gpu_flag_c, gpu_flag_z, IMM_2, RN);
1876 static void gpu_opcode_loadp(void)
1878 gpu_hidata = GPUReadLong(RM + 0, GPU);
1879 RN = GPUReadLong(RM + 4, GPU);
1882 static void gpu_opcode_load_r14_indexed(void)
1884 #ifdef GPU_DIS_LOAD14I
1886 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);
1888 RN = GPUReadLong(gpu_reg[14] + (gpu_convert_zero[IMM_1] << 2), GPU);
1889 #ifdef GPU_DIS_LOAD14I
1891 WriteLog("[NCZ:%u%u%u, R%02u=%08X]\n", gpu_flag_n, gpu_flag_c, gpu_flag_z, IMM_2, RN);
1895 static void gpu_opcode_load_r15_indexed(void)
1897 #ifdef GPU_DIS_LOAD15I
1899 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);
1901 RN = GPUReadLong(gpu_reg[15] + (gpu_convert_zero[IMM_1] << 2), GPU);
1902 #ifdef GPU_DIS_LOAD15I
1904 WriteLog("[NCZ:%u%u%u, R%02u=%08X]\n", gpu_flag_n, gpu_flag_c, gpu_flag_z, IMM_2, RN);
1908 static void gpu_opcode_movei(void)
1910 #ifdef GPU_DIS_MOVEI
1912 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);
1914 // This instruction is followed by 32-bit value in LSW / MSW format...
1915 RN = (uint32)GPUReadWord(gpu_pc, GPU) | ((uint32)GPUReadWord(gpu_pc + 2, GPU) << 16);
1917 #ifdef GPU_DIS_MOVEI
1919 WriteLog("[NCZ:%u%u%u, R%02u=%08X]\n", gpu_flag_n, gpu_flag_c, gpu_flag_z, IMM_2, RN);
1923 static void gpu_opcode_moveta(void)
1925 #ifdef GPU_DIS_MOVETA
1927 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);
1930 #ifdef GPU_DIS_MOVETA
1932 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);
1936 static void gpu_opcode_movefa(void)
1938 #ifdef GPU_DIS_MOVEFA
1940 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);
1943 #ifdef GPU_DIS_MOVEFA
1945 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);
1949 static void gpu_opcode_move(void)
1953 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);
1958 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);
1962 static void gpu_opcode_moveq(void)
1964 #ifdef GPU_DIS_MOVEQ
1966 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);
1969 #ifdef GPU_DIS_MOVEQ
1971 WriteLog("[NCZ:%u%u%u, R%02u=%08X]\n", gpu_flag_n, gpu_flag_c, gpu_flag_z, IMM_2, RN);
1975 static void gpu_opcode_resmac(void)
1980 static void gpu_opcode_imult(void)
1982 #ifdef GPU_DIS_IMULT
1984 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);
1986 RN = (int16)RN * (int16)RM;
1988 #ifdef GPU_DIS_IMULT
1990 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);
1994 static void gpu_opcode_mult(void)
1998 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);
2000 RN = (uint16)RM * (uint16)RN;
2004 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);
2008 static void gpu_opcode_bclr(void)
2012 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);
2014 UINT32 res = RN & ~(1 << IMM_1);
2019 WriteLog("[NCZ:%u%u%u, R%02u=%08X]\n", gpu_flag_n, gpu_flag_c, gpu_flag_z, IMM_2, RN);
2023 static void gpu_opcode_btst(void)
2027 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);
2029 gpu_flag_z = (~RN >> IMM_1) & 1;
2032 WriteLog("[NCZ:%u%u%u, R%02u=%08X]\n", gpu_flag_n, gpu_flag_c, gpu_flag_z, IMM_2, RN);
2036 static void gpu_opcode_bset(void)
2040 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);
2042 UINT32 res = RN | (1 << IMM_1);
2047 WriteLog("[NCZ:%u%u%u, R%02u=%08X]\n", gpu_flag_n, gpu_flag_c, gpu_flag_z, IMM_2, RN);
2051 static void gpu_opcode_imacn(void)
2053 uint32 res = (int16)RM * (int16)(RN);
2057 static void gpu_opcode_mtoi(void)
2060 uint32 res = RN = (((INT32)_RM >> 8) & 0xFF800000) | (_RM & 0x007FFFFF);
2064 static void gpu_opcode_normi(void)
2071 while ((_RM & 0xFFC00000) == 0)
2076 while ((_RM & 0xFF800000) != 0)
2086 static void gpu_opcode_mmult(void)
2088 int count = gpu_matrix_control & 0x0F; // Matrix width
2089 uint32 addr = gpu_pointer_to_matrix; // In the GPU's RAM
2093 if (gpu_matrix_control & 0x10) // Column stepping
2095 for(int i=0; i<count; i++)
2099 a = (int16)((gpu_alternate_reg[IMM_1 + (i >> 1)] >> 16) & 0xFFFF);
2101 a = (int16)(gpu_alternate_reg[IMM_1 + (i >> 1)] & 0xFFFF);
2103 int16 b = ((int16)GPUReadWord(addr + 2, GPU));
2108 else // Row stepping
2110 for(int i=0; i<count; i++)
2114 a = (int16)((gpu_alternate_reg[IMM_1 + (i >> 1)] >> 16) & 0xFFFF);
2116 a = (int16)(gpu_alternate_reg[IMM_1 + (i >> 1)] & 0xFFFF);
2118 int16 b = ((int16)GPUReadWord(addr + 2, GPU));
2123 RN = res = (int32)accum;
2124 // carry flag to do (out of the last add)
2128 static void gpu_opcode_abs(void)
2132 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);
2134 gpu_flag_c = RN >> 31;
2135 if (RN == 0x80000000)
2136 //Is 0x80000000 a positive number? If so, then we need to set C to 0 as well!
2137 gpu_flag_n = 1, gpu_flag_z = 0;
2142 gpu_flag_n = 0; SET_FLAG_Z(RN);
2146 WriteLog("[NCZ:%u%u%u, R%02u=%08X]\n", gpu_flag_n, gpu_flag_c, gpu_flag_z, IMM_2, RN);
2150 static void gpu_opcode_div(void) // RN / RM
2154 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);
2156 // NOTE: remainder is NOT calculated correctly here!
2157 // The original tried to get it right by checking to see if the
2158 // remainder was negative, but that's too late...
2159 // The code there should do it now, but I'm not 100% sure...
2163 if (gpu_div_control & 0x01) // 16.16 division
2165 RN = ((UINT64)RN << 16) / RM;
2166 gpu_remain = ((UINT64)RN << 16) % RM;
2171 gpu_remain = RN % RM;
2174 if ((gpu_remain - RM) & 0x80000000) // If the result would have been negative...
2175 gpu_remain -= RM; // Then make it negative!
2185 if (gpu_div_control & 1)
2187 gpu_remain = (((uint64)_RN) << 16) % _RM;
2188 if (gpu_remain&0x80000000)
2190 RN = (((uint64)_RN) << 16) / _RM;
2194 gpu_remain = _RN % _RM;
2195 if (gpu_remain&0x80000000)
2204 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);
2208 static void gpu_opcode_imultn(void)
2210 uint32 res = (int32)((int16)RN * (int16)RM);
2211 gpu_acc = (int32)res;
2216 static void gpu_opcode_neg(void)
2220 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);
2223 SET_ZNC_SUB(0, RN, res);
2227 WriteLog("[NCZ:%u%u%u, R%02u=%08X]\n", gpu_flag_n, gpu_flag_c, gpu_flag_z, IMM_2, RN);
2231 static void gpu_opcode_shlq(void)
2235 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);
2237 // Was a bug here...
2238 // (Look at Aaron's code: If r1 = 32, then 32 - 32 = 0 which is wrong!)
2239 INT32 r1 = 32 - IMM_1;
2240 UINT32 res = RN << r1;
2241 SET_ZN(res); gpu_flag_c = (RN >> 31) & 1;
2245 WriteLog("[NCZ:%u%u%u, R%02u=%08X]\n", gpu_flag_n, gpu_flag_c, gpu_flag_z, IMM_2, RN);
2249 static void gpu_opcode_shrq(void)
2253 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);
2255 INT32 r1 = gpu_convert_zero[IMM_1];
2256 UINT32 res = RN >> r1;
2257 SET_ZN(res); gpu_flag_c = RN & 1;
2261 WriteLog("[NCZ:%u%u%u, R%02u=%08X]\n", gpu_flag_n, gpu_flag_c, gpu_flag_z, IMM_2, RN);
2265 static void gpu_opcode_ror(void)
2269 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);
2271 UINT32 r1 = RM & 0x1F;
2272 UINT32 res = (RN >> r1) | (RN << (32 - r1));
2273 SET_ZN(res); gpu_flag_c = (RN >> 31) & 1;
2277 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);
2281 static void gpu_opcode_rorq(void)
2285 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);
2287 UINT32 r1 = gpu_convert_zero[IMM_1 & 0x1F];
2289 UINT32 res = (r2 >> r1) | (r2 << (32 - r1));
2291 SET_ZN(res); gpu_flag_c = (r2 >> 31) & 0x01;
2294 WriteLog("[NCZ:%u%u%u, R%02u=%08X]\n", gpu_flag_n, gpu_flag_c, gpu_flag_z, IMM_2, RN);
2298 static void gpu_opcode_sha(void)
2300 /* int dreg = jaguar.op & 31;
2301 INT32 r1 = (INT32)jaguar.r[(jaguar.op >> 5) & 31];
2302 UINT32 r2 = jaguar.r[dreg];
2308 res = (r1 <= -32) ? 0 : (r2 << -r1);
2309 jaguar.FLAGS |= (r2 >> 30) & 2;
2313 res = (r1 >= 32) ? ((INT32)r2 >> 31) : ((INT32)r2 >> r1);
2314 jaguar.FLAGS |= (r2 << 1) & 2;
2316 jaguar.r[dreg] = res;
2321 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);
2327 res = ((INT32)RM <= -32) ? 0 : (RN << -(INT32)RM);
2328 gpu_flag_c = RN >> 31;
2332 res = ((INT32)RM >= 32) ? ((INT32)RN >> 31) : ((INT32)RN >> (INT32)RM);
2333 gpu_flag_c = RN & 0x01;
2339 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);
2342 /* int32 sRM=(int32)RM;
2348 if (shift>=32) shift=32;
2349 gpu_flag_c=(_RN&0x80000000)>>31;
2359 if (shift>=32) shift=32;
2363 _RN=((int32)_RN)>>1;
2372 static void gpu_opcode_sharq(void)
2374 #ifdef GPU_DIS_SHARQ
2376 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);
2378 UINT32 res = (INT32)RN >> gpu_convert_zero[IMM_1];
2379 SET_ZN(res); gpu_flag_c = RN & 0x01;
2381 #ifdef GPU_DIS_SHARQ
2383 WriteLog("[NCZ:%u%u%u, R%02u=%08X]\n", gpu_flag_n, gpu_flag_c, gpu_flag_z, IMM_2, RN);
2387 static void gpu_opcode_sh(void)
2391 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);
2393 if (RM & 0x80000000) // Shift left
2395 gpu_flag_c = RN >> 31;
2396 RN = ((int32)RM <= -32 ? 0 : RN << -(int32)RM);
2400 gpu_flag_c = RN & 0x01;
2401 RN = (RM >= 32 ? 0 : RN >> RM);
2406 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);
2410 //Temporary: Testing only!
2411 //#include "gpu2.cpp"
2412 //#include "gpu3.cpp"