6 // Originally by David Raingeard (Cal2)
7 // GCC/SDL port by Niels Wagenaar (Linux/WIN32) and Caz (BeOS)
8 // Cleanups, endian wrongness, and bad ASM amelioration by James L. Hammons
9 // (C) 2010 Underground Software
11 // JLH = James L. Hammons <jlhamm@acm.org>
14 // --- ---------- -------------------------------------------------------------
15 // JLH 01/16/2010 Created this log ;-)
16 // JLH 11/26/2011 Added fixes for LOAD/STORE alignment issues
19 // Note: Endian wrongness probably stems from the MAME origins of this emu and
20 // the braindead way in which MAME handles memory. :-)
22 // Problem with not booting the BIOS was the incorrect way that the
23 // SUBC instruction set the carry when the carry was set going in...
24 // Same problem with ADDC...
30 #include <string.h> // For memset
40 // Seems alignment in loads & stores was off...
41 #define GPU_CORRECT_ALIGNMENT
42 //#define GPU_CORRECT_ALIGNMENT_STORE
45 // For GPU dissasembly...
66 #define GPU_DIS_LOAD14I
67 #define GPU_DIS_LOAD14R
68 #define GPU_DIS_LOAD15I
69 #define GPU_DIS_LOAD15R
71 #define GPU_DIS_MOVEFA
73 #define GPU_DIS_MOVEPC
74 #define GPU_DIS_MOVETA
91 #define GPU_DIS_STOREB
92 #define GPU_DIS_STOREW
93 #define GPU_DIS_STORE14I
94 #define GPU_DIS_STORE14R
95 #define GPU_DIS_STORE15I
96 #define GPU_DIS_STORE15R
100 #define GPU_DIS_SUBQT
103 //bool doGPUDis = false;
104 bool doGPUDis = true;
108 GPU opcodes use (BIOS flying ATARI logo):
150 #define CINT0FLAG 0x0200
151 #define CINT1FLAG 0x0400
152 #define CINT2FLAG 0x0800
153 #define CINT3FLAG 0x1000
154 #define CINT4FLAG 0x2000
155 #define CINT04FLAGS (CINT0FLAG | CINT1FLAG | CINT2FLAG | CINT3FLAG | CINT4FLAG)
159 #define ZERO_FLAG 0x0001
160 #define CARRY_FLAG 0x0002
161 #define NEGA_FLAG 0x0004
163 #define INT_ENA0 0x0010
164 #define INT_ENA1 0x0020
165 #define INT_ENA2 0x0040
166 #define INT_ENA3 0x0080
167 #define INT_ENA4 0x0100
168 #define INT_CLR0 0x0200
169 #define INT_CLR1 0x0400
170 #define INT_CLR2 0x0800
171 #define INT_CLR3 0x1000
172 #define INT_CLR4 0x2000
173 #define REGPAGE 0x4000
176 // External global variables
178 extern int start_logging;
179 extern int gpu_start_log;
181 // Private function prototypes
183 void GPUUpdateRegisterBanks(void);
184 void GPUDumpDisassembly(void);
185 void GPUDumpRegisters(void);
186 void GPUDumpMemory(void);
188 static void gpu_opcode_add(void);
189 static void gpu_opcode_addc(void);
190 static void gpu_opcode_addq(void);
191 static void gpu_opcode_addqt(void);
192 static void gpu_opcode_sub(void);
193 static void gpu_opcode_subc(void);
194 static void gpu_opcode_subq(void);
195 static void gpu_opcode_subqt(void);
196 static void gpu_opcode_neg(void);
197 static void gpu_opcode_and(void);
198 static void gpu_opcode_or(void);
199 static void gpu_opcode_xor(void);
200 static void gpu_opcode_not(void);
201 static void gpu_opcode_btst(void);
202 static void gpu_opcode_bset(void);
203 static void gpu_opcode_bclr(void);
204 static void gpu_opcode_mult(void);
205 static void gpu_opcode_imult(void);
206 static void gpu_opcode_imultn(void);
207 static void gpu_opcode_resmac(void);
208 static void gpu_opcode_imacn(void);
209 static void gpu_opcode_div(void);
210 static void gpu_opcode_abs(void);
211 static void gpu_opcode_sh(void);
212 static void gpu_opcode_shlq(void);
213 static void gpu_opcode_shrq(void);
214 static void gpu_opcode_sha(void);
215 static void gpu_opcode_sharq(void);
216 static void gpu_opcode_ror(void);
217 static void gpu_opcode_rorq(void);
218 static void gpu_opcode_cmp(void);
219 static void gpu_opcode_cmpq(void);
220 static void gpu_opcode_sat8(void);
221 static void gpu_opcode_sat16(void);
222 static void gpu_opcode_move(void);
223 static void gpu_opcode_moveq(void);
224 static void gpu_opcode_moveta(void);
225 static void gpu_opcode_movefa(void);
226 static void gpu_opcode_movei(void);
227 static void gpu_opcode_loadb(void);
228 static void gpu_opcode_loadw(void);
229 static void gpu_opcode_load(void);
230 static void gpu_opcode_loadp(void);
231 static void gpu_opcode_load_r14_indexed(void);
232 static void gpu_opcode_load_r15_indexed(void);
233 static void gpu_opcode_storeb(void);
234 static void gpu_opcode_storew(void);
235 static void gpu_opcode_store(void);
236 static void gpu_opcode_storep(void);
237 static void gpu_opcode_store_r14_indexed(void);
238 static void gpu_opcode_store_r15_indexed(void);
239 static void gpu_opcode_move_pc(void);
240 static void gpu_opcode_jump(void);
241 static void gpu_opcode_jr(void);
242 static void gpu_opcode_mmult(void);
243 static void gpu_opcode_mtoi(void);
244 static void gpu_opcode_normi(void);
245 static void gpu_opcode_nop(void);
246 static void gpu_opcode_load_r14_ri(void);
247 static void gpu_opcode_load_r15_ri(void);
248 static void gpu_opcode_store_r14_ri(void);
249 static void gpu_opcode_store_r15_ri(void);
250 static void gpu_opcode_sat24(void);
251 static void gpu_opcode_pack(void);
253 // This is wrong, since it doesn't take pipeline effects into account. !!! FIX !!!
254 /*uint8 gpu_opcode_cycles[64] =
256 3, 3, 3, 3, 3, 3, 3, 3,
257 3, 3, 3, 3, 3, 3, 3, 3,
258 3, 3, 1, 3, 1, 18, 3, 3,
259 3, 3, 3, 3, 3, 3, 3, 3,
260 3, 3, 2, 2, 2, 2, 3, 4,
261 5, 4, 5, 6, 6, 1, 1, 1,
262 1, 2, 2, 2, 1, 1, 9, 3,
263 3, 1, 6, 6, 2, 2, 3, 3
265 //Here's a QnD kludge...
266 //This is wrong, wrong, WRONG, but it seems to work for the time being...
267 //(That is, it fixes Flip Out which relies on GPU timing rather than semaphores. Bad developers! Bad!)
268 //What's needed here is a way to take pipeline effects into account (including pipeline stalls!)...
269 /*uint8 gpu_opcode_cycles[64] =
271 1, 1, 1, 1, 1, 1, 1, 1,
272 1, 1, 1, 1, 1, 1, 1, 1,
273 1, 1, 1, 1, 1, 9, 1, 1,
274 1, 1, 1, 1, 1, 1, 1, 1,
275 1, 1, 1, 1, 1, 1, 1, 2,
276 2, 2, 2, 3, 3, 1, 1, 1,
277 1, 1, 1, 1, 1, 1, 4, 1,
278 1, 1, 3, 3, 1, 1, 1, 1
280 uint8 gpu_opcode_cycles[64] =
282 1, 1, 1, 1, 1, 1, 1, 1,
283 1, 1, 1, 1, 1, 1, 1, 1,
284 1, 1, 1, 1, 1, 1, 1, 1,
285 1, 1, 1, 1, 1, 1, 1, 1,
286 1, 1, 1, 1, 1, 1, 1, 1,
287 1, 1, 1, 1, 1, 1, 1, 1,
288 1, 1, 1, 1, 1, 1, 1, 1,
289 1, 1, 1, 1, 1, 1, 1, 1
292 void (*gpu_opcode[64])()=
294 gpu_opcode_add, gpu_opcode_addc, gpu_opcode_addq, gpu_opcode_addqt,
295 gpu_opcode_sub, gpu_opcode_subc, gpu_opcode_subq, gpu_opcode_subqt,
296 gpu_opcode_neg, gpu_opcode_and, gpu_opcode_or, gpu_opcode_xor,
297 gpu_opcode_not, gpu_opcode_btst, gpu_opcode_bset, gpu_opcode_bclr,
298 gpu_opcode_mult, gpu_opcode_imult, gpu_opcode_imultn, gpu_opcode_resmac,
299 gpu_opcode_imacn, gpu_opcode_div, gpu_opcode_abs, gpu_opcode_sh,
300 gpu_opcode_shlq, gpu_opcode_shrq, gpu_opcode_sha, gpu_opcode_sharq,
301 gpu_opcode_ror, gpu_opcode_rorq, gpu_opcode_cmp, gpu_opcode_cmpq,
302 gpu_opcode_sat8, gpu_opcode_sat16, gpu_opcode_move, gpu_opcode_moveq,
303 gpu_opcode_moveta, gpu_opcode_movefa, gpu_opcode_movei, gpu_opcode_loadb,
304 gpu_opcode_loadw, gpu_opcode_load, gpu_opcode_loadp, gpu_opcode_load_r14_indexed,
305 gpu_opcode_load_r15_indexed, gpu_opcode_storeb, gpu_opcode_storew, gpu_opcode_store,
306 gpu_opcode_storep, gpu_opcode_store_r14_indexed, gpu_opcode_store_r15_indexed, gpu_opcode_move_pc,
307 gpu_opcode_jump, gpu_opcode_jr, gpu_opcode_mmult, gpu_opcode_mtoi,
308 gpu_opcode_normi, gpu_opcode_nop, gpu_opcode_load_r14_ri, gpu_opcode_load_r15_ri,
309 gpu_opcode_store_r14_ri, gpu_opcode_store_r15_ri, gpu_opcode_sat24, gpu_opcode_pack,
312 static uint8 gpu_ram_8[0x1000];
314 static uint32 gpu_acc;
315 static uint32 gpu_remain;
316 static uint32 gpu_hidata;
317 static uint32 gpu_flags;
318 static uint32 gpu_matrix_control;
319 static uint32 gpu_pointer_to_matrix;
320 static uint32 gpu_data_organization;
321 static uint32 gpu_control;
322 static uint32 gpu_div_control;
323 // There is a distinct advantage to having these separated out--there's no need to clear
324 // a bit before writing a result. I.e., if the result of an operation leaves a zero in
325 // the carry flag, you don't have to zero gpu_flag_c before you can write that zero!
326 static uint8 gpu_flag_z, gpu_flag_n, gpu_flag_c;
327 static uint32 gpu_reg_bank_0[32];
328 static uint32 gpu_reg_bank_1[32];
329 static uint32 * gpu_reg;
330 static uint32 * gpu_alternate_reg;
332 static uint32 gpu_instruction;
333 static uint32 gpu_opcode_first_parameter;
334 static uint32 gpu_opcode_second_parameter;
336 #define GPU_RUNNING (gpu_control & 0x01)
338 #define RM gpu_reg[gpu_opcode_first_parameter]
339 #define RN gpu_reg[gpu_opcode_second_parameter]
340 #define ALTERNATE_RM gpu_alternate_reg[gpu_opcode_first_parameter]
341 #define ALTERNATE_RN gpu_alternate_reg[gpu_opcode_second_parameter]
342 #define IMM_1 gpu_opcode_first_parameter
343 #define IMM_2 gpu_opcode_second_parameter
345 #define SET_FLAG_Z(r) (gpu_flag_z = ((r) == 0));
346 #define SET_FLAG_N(r) (gpu_flag_n = (((uint32)(r) >> 31) & 0x01));
348 #define RESET_FLAG_Z() gpu_flag_z = 0;
349 #define RESET_FLAG_N() gpu_flag_n = 0;
350 #define RESET_FLAG_C() gpu_flag_c = 0;
352 #define CLR_Z (gpu_flag_z = 0)
353 #define CLR_ZN (gpu_flag_z = gpu_flag_n = 0)
354 #define CLR_ZNC (gpu_flag_z = gpu_flag_n = gpu_flag_c = 0)
355 #define SET_Z(r) (gpu_flag_z = ((r) == 0))
356 #define SET_N(r) (gpu_flag_n = (((uint32)(r) >> 31) & 0x01))
357 #define SET_C_ADD(a,b) (gpu_flag_c = ((uint32)(b) > (uint32)(~(a))))
358 #define SET_C_SUB(a,b) (gpu_flag_c = ((uint32)(b) > (uint32)(a)))
359 #define SET_ZN(r) SET_N(r); SET_Z(r)
360 #define SET_ZNC_ADD(a,b,r) SET_N(r); SET_Z(r); SET_C_ADD(a,b)
361 #define SET_ZNC_SUB(a,b,r) SET_N(r); SET_Z(r); SET_C_SUB(a,b)
363 uint32 gpu_convert_zero[32] =
364 { 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 };
366 uint8 * branch_condition_table = 0;
367 #define BRANCH_CONDITION(x) branch_condition_table[(x) + ((jaguar_flags & 7) << 5)]
369 uint32 gpu_opcode_use[64];
371 const char * gpu_opcode_str[64]=
373 "add", "addc", "addq", "addqt",
374 "sub", "subc", "subq", "subqt",
375 "neg", "and", "or", "xor",
376 "not", "btst", "bset", "bclr",
377 "mult", "imult", "imultn", "resmac",
378 "imacn", "div", "abs", "sh",
379 "shlq", "shrq", "sha", "sharq",
380 "ror", "rorq", "cmp", "cmpq",
381 "sat8", "sat16", "move", "moveq",
382 "moveta", "movefa", "movei", "loadb",
383 "loadw", "load", "loadp", "load_r14_indexed",
384 "load_r15_indexed", "storeb", "storew", "store",
385 "storep", "store_r14_indexed","store_r15_indexed","move_pc",
386 "jump", "jr", "mmult", "mtoi",
387 "normi", "nop", "load_r14_ri", "load_r15_ri",
388 "store_r14_ri", "store_r15_ri", "sat24", "pack",
391 static uint32 gpu_in_exec = 0;
392 static uint32 gpu_releaseTimeSlice_flag = 0;
394 void GPUReleaseTimeslice(void)
396 gpu_releaseTimeSlice_flag = 1;
399 uint32 GPUGetPC(void)
404 void build_branch_condition_table(void)
406 if (!branch_condition_table)
408 branch_condition_table = (uint8 *)malloc(32 * 8 * sizeof(branch_condition_table[0]));
410 if (branch_condition_table)
412 for(int i=0; i<8; i++)
414 for(int j=0; j<32; j++)
421 if (!(i & ZERO_FLAG))
424 if (i & (CARRY_FLAG << (j >> 4)))
427 if (!(i & (CARRY_FLAG << (j >> 4))))
429 branch_condition_table[i * 32 + j] = result;
437 // GPU byte access (read)
439 uint8 GPUReadByte(uint32 offset, uint32 who/*=UNKNOWN*/)
441 if (offset >= 0xF02000 && offset <= 0xF020FF)
442 WriteLog("GPU: ReadByte--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))
445 return gpu_ram_8[offset & 0xFFF];
446 else if ((offset >= GPU_CONTROL_RAM_BASE) && (offset < GPU_CONTROL_RAM_BASE+0x20))
448 uint32 data = GPUReadLong(offset & 0xFFFFFFFC, who);
450 if ((offset & 0x03) == 0)
452 else if ((offset & 0x03) == 1)
453 return (data >> 16) & 0xFF;
454 else if ((offset & 0x03) == 2)
455 return (data >> 8) & 0xFF;
456 else if ((offset & 0x03) == 3)
460 return JaguarReadByte(offset, who);
464 // GPU word access (read)
466 uint16 GPUReadWord(uint32 offset, uint32 who/*=UNKNOWN*/)
468 if (offset >= 0xF02000 && offset <= 0xF020FF)
469 WriteLog("GPU: ReadWord--Attempt to read from GPU register file by %s!\n", whoName[who]);
471 if ((offset >= GPU_WORK_RAM_BASE) && (offset < GPU_WORK_RAM_BASE+0x1000))
474 uint16 data = ((uint16)gpu_ram_8[offset] << 8) | (uint16)gpu_ram_8[offset+1];
477 else if ((offset >= GPU_CONTROL_RAM_BASE) && (offset < GPU_CONTROL_RAM_BASE+0x20))
479 // This looks and smells wrong...
480 // But it *might* be OK...
481 if (offset & 0x01) // Catch cases 1 & 3... (unaligned read)
482 return (GPUReadByte(offset, who) << 8) | GPUReadByte(offset+1, who);
484 uint32 data = GPUReadLong(offset & 0xFFFFFFFC, who);
486 if (offset & 0x02) // Cases 0 & 2...
487 return data & 0xFFFF;
492 //TEMP--Mirror of F03000? No. Writes only...
493 //if (offset >= 0xF0B000 && offset <= 0xF0BFFF)
494 //WriteLog("[GPUR16] --> Possible GPU RAM mirror access by %s!", whoName[who]);
496 return JaguarReadWord(offset, who);
500 // GPU dword access (read)
502 uint32 GPUReadLong(uint32 offset, uint32 who/*=UNKNOWN*/)
504 if (offset >= 0xF02000 && offset <= 0xF020FF)
505 WriteLog("GPU: ReadLong--Attempt to read from GPU register file by %s!\n", whoName[who]);
507 // if ((offset >= GPU_WORK_RAM_BASE) && (offset < GPU_WORK_RAM_BASE + 0x1000))
508 if ((offset >= GPU_WORK_RAM_BASE) && (offset <= GPU_WORK_RAM_BASE + 0x0FFC))
511 return ((uint32)gpu_ram_8[offset] << 24) | ((uint32)gpu_ram_8[offset+1] << 16)
512 | ((uint32)gpu_ram_8[offset+2] << 8) | (uint32)gpu_ram_8[offset+3];//*/
513 // return GET32(gpu_ram_8, offset);
515 // else if ((offset >= GPU_CONTROL_RAM_BASE) && (offset < GPU_CONTROL_RAM_BASE+0x20))
516 else if ((offset >= GPU_CONTROL_RAM_BASE) && (offset <= GPU_CONTROL_RAM_BASE + 0x1C))
522 gpu_flag_c = (gpu_flag_c ? 1 : 0);
523 gpu_flag_z = (gpu_flag_z ? 1 : 0);
524 gpu_flag_n = (gpu_flag_n ? 1 : 0);
526 gpu_flags = (gpu_flags & 0xFFFFFFF8) | (gpu_flag_n << 2) | (gpu_flag_c << 1) | gpu_flag_z;
528 return gpu_flags & 0xFFFFC1FF;
530 return gpu_matrix_control;
532 return gpu_pointer_to_matrix;
534 return gpu_data_organization;
543 default: // unaligned long read
545 WriteLog("GPU: Read32--unaligned 32 bit read at %08X by %s.\n", GPU_CONTROL_RAM_BASE + offset, whoName[who]);
550 //TEMP--Mirror of F03000? No. Writes only...
551 //if (offset >= 0xF0B000 && offset <= 0xF0BFFF)
552 // WriteLog("[GPUR32] --> Possible GPU RAM mirror access by %s!\n", whoName[who]);
553 /*if (offset >= 0xF1D000 && offset <= 0xF1DFFF)
554 WriteLog("[GPUR32] --> Reading from Wavetable ROM!\n");//*/
556 return (JaguarReadWord(offset, who) << 16) | JaguarReadWord(offset + 2, who);
560 // GPU byte access (write)
562 void GPUWriteByte(uint32 offset, uint8 data, uint32 who/*=UNKNOWN*/)
564 if (offset >= 0xF02000 && offset <= 0xF020FF)
565 WriteLog("GPU: WriteByte--Attempt to write to GPU register file by %s!\n", whoName[who]);
567 if ((offset >= GPU_WORK_RAM_BASE) && (offset <= GPU_WORK_RAM_BASE + 0x0FFF))
569 gpu_ram_8[offset & 0xFFF] = data;
571 //This is the same stupid worthless code that was in the DSP!!! AARRRGGGGHHHHH!!!!!!
574 m68k_end_timeslice();
575 dsp_releaseTimeslice();
579 else if ((offset >= GPU_CONTROL_RAM_BASE) && (offset <= GPU_CONTROL_RAM_BASE + 0x1F))
581 uint32 reg = offset & 0x1C;
582 int bytenum = offset & 0x03;
584 //This is definitely wrong!
585 if ((reg >= 0x1C) && (reg <= 0x1F))
586 gpu_div_control = (gpu_div_control & (~(0xFF << (bytenum << 3)))) | (data << (bytenum << 3));
589 uint32 old_data = GPUReadLong(offset & 0xFFFFFFC, who);
590 bytenum = 3 - bytenum; // convention motorola !!!
591 old_data = (old_data & (~(0xFF << (bytenum << 3)))) | (data << (bytenum << 3));
592 GPUWriteLong(offset & 0xFFFFFFC, old_data, who);
596 // WriteLog("gpu: writing %.2x at 0x%.8x\n",data,offset);
597 JaguarWriteByte(offset, data, who);
601 // GPU word access (write)
603 void GPUWriteWord(uint32 offset, uint16 data, uint32 who/*=UNKNOWN*/)
605 if (offset >= 0xF02000 && offset <= 0xF020FF)
606 WriteLog("GPU: WriteWord--Attempt to write to GPU register file by %s!\n", whoName[who]);
608 if ((offset >= GPU_WORK_RAM_BASE) && (offset <= GPU_WORK_RAM_BASE + 0x0FFE))
610 gpu_ram_8[offset & 0xFFF] = (data>>8) & 0xFF;
611 gpu_ram_8[(offset+1) & 0xFFF] = data & 0xFF;//*/
613 SET16(gpu_ram_8, offset, data);//*/
615 /*if (offset >= 0xF03214 && offset < 0xF0321F)
616 WriteLog("GPU: Writing WORD (%04X) to GPU RAM (%08X)...\n", data, offset);//*/
619 //This is the same stupid worthless code that was in the DSP!!! AARRRGGGGHHHHH!!!!!!
622 m68k_end_timeslice();
623 dsp_releaseTimeslice();
627 else if ((offset >= GPU_CONTROL_RAM_BASE) && (offset <= GPU_CONTROL_RAM_BASE + 0x1E))
629 if (offset & 0x01) // This is supposed to weed out unaligned writes, but does nothing...
632 WriteLog("GPU: Write16--unaligned write @ %08X [%04X]\n", offset, data);
637 //Dual locations in this range: $1C Divide unit remainder/Divide unit control (R/W)
638 //This just literally sucks.
639 if ((offset & 0x1C) == 0x1C)
641 //This doesn't look right either--handles cases 1, 2, & 3 all the same!
643 gpu_div_control = (gpu_div_control & 0xFFFF0000) | (data & 0xFFFF);
645 gpu_div_control = (gpu_div_control & 0x0000FFFF) | ((data & 0xFFFF) << 16);
649 //WriteLog("[GPU W16:%08X,%04X]", offset, data);
650 uint32 old_data = GPUReadLong(offset & 0xFFFFFFC, who);
652 old_data = (old_data & 0xFFFF0000) | (data & 0xFFFF);
654 old_data = (old_data & 0x0000FFFF) | ((data & 0xFFFF) << 16);
655 GPUWriteLong(offset & 0xFFFFFFC, old_data, who);
659 else if ((offset == GPU_WORK_RAM_BASE + 0x0FFF) || (GPU_CONTROL_RAM_BASE + 0x1F))
662 WriteLog("GPU: Write16--unaligned write @ %08X by %s [%04X]!\n", offset, whoName[who], data);
668 // Have to be careful here--this can cause an infinite loop!
669 JaguarWriteWord(offset, data, who);
673 // GPU dword access (write)
675 void GPUWriteLong(uint32 offset, uint32 data, uint32 who/*=UNKNOWN*/)
677 if (offset >= 0xF02000 && offset <= 0xF020FF)
678 WriteLog("GPU: WriteLong--Attempt to write to GPU register file by %s!\n", whoName[who]);
680 // if ((offset >= GPU_WORK_RAM_BASE) && (offset < GPU_WORK_RAM_BASE + 0x1000))
681 if ((offset >= GPU_WORK_RAM_BASE) && (offset <= GPU_WORK_RAM_BASE + 0x0FFC))
686 WriteLog("GPU: Write32--unaligned write @ %08X [%08X] by %s\n", offset, data, whoName[who]);
692 SET32(gpu_ram_8, offset, data);
695 // else if ((offset >= GPU_CONTROL_RAM_BASE) && (offset < GPU_CONTROL_RAM_BASE+0x20))
696 else if ((offset >= GPU_CONTROL_RAM_BASE) && (offset <= GPU_CONTROL_RAM_BASE + 0x1C))
703 bool IMASKCleared = (gpu_flags & IMASK) && !(data & IMASK);
705 gpu_flag_z = gpu_flags & ZERO_FLAG;
706 gpu_flag_c = (gpu_flags & CARRY_FLAG) >> 1;
707 gpu_flag_n = (gpu_flags & NEGA_FLAG) >> 2;
708 GPUUpdateRegisterBanks();
709 gpu_control &= ~((gpu_flags & CINT04FLAGS) >> 3); // Interrupt latch clear bits
710 //Writing here is only an interrupt enable--this approach is just plain wrong!
712 //This, however, is A-OK! ;-)
713 if (IMASKCleared) // If IMASK was cleared,
714 GPUHandleIRQs(); // see if any other interrupts need servicing!
716 if (gpu_flags & (INT_ENA0 | INT_ENA1 | INT_ENA2 | INT_ENA3 | INT_ENA4))
717 WriteLog("GPU: Interrupt enable set by %s! Bits: %02X\n", whoName[who], (gpu_flags >> 4) & 0x1F);
718 WriteLog("GPU: REGPAGE %s...\n", (gpu_flags & REGPAGE ? "set" : "cleared"));
723 gpu_matrix_control = data;
726 // This can only point to long aligned addresses
727 gpu_pointer_to_matrix = data & 0xFFFFFFFC;
730 gpu_data_organization = data;
735 WriteLog("GPU: %s setting GPU PC to %08X %s\n", whoName[who], gpu_pc, (GPU_RUNNING ? "(GPU is RUNNING!)" : ""));//*/
740 // uint32 gpu_was_running = GPU_RUNNING;
741 data &= ~0xF7C0; // Disable writes to INT_LAT0-4 & TOM version number
743 // check for GPU -> CPU interrupt
746 //WriteLog("GPU->CPU interrupt\n");
747 if (TOMIRQEnabled(IRQ_GPU))
749 //This is the programmer's responsibility, to make sure the handler is valid, not ours!
750 // if ((TOMIRQEnabled(IRQ_GPU))// && (JaguarInterruptHandlerIsValid(64)))
752 TOMSetPendingGPUInt();
753 m68k_set_irq(2); // Set 68000 IPL 2
754 GPUReleaseTimeslice();
760 // check for CPU -> GPU interrupt #0
763 //WriteLog("CPU->GPU interrupt\n");
764 GPUSetIRQLine(0, ASSERT_LINE);
765 m68k_end_timeslice();
766 DSPReleaseTimeslice();
773 //WriteLog("asked to perform a single step (single step is %senabled)\n",(data&0x8)?"":"not ");
775 gpu_control = (gpu_control & 0xF7C0) | (data & (~0xF7C0));
777 // if gpu wasn't running but is now running, execute a few cycles
778 #ifndef GPU_SINGLE_STEPPING
779 /* if (!gpu_was_running && GPU_RUNNING)
782 WriteLog("GPU: Write32--About to do stupid braindead GPU execution for 200 cycles.\n");
787 #endif // GPU_DEBUG//*/
789 if (gpu_control & 0x18)
791 #endif // #ifndef GPU_SINGLE_STEPPING
793 WriteLog("Write to GPU CTRL by %s: %08X ", whoName[who], data);
795 WriteLog(" --> Starting to run at %08X by %s...", gpu_pc, whoName[who]);
797 WriteLog(" --> Stopped by %s! (GPU_PC: %08X)", whoName[who], gpu_pc);
801 // GPUDumpDisassembly();
804 if (gpu_pc == 0xF035D8)
806 // GPUDumpDisassembly();
809 gpu_control &= 0xFFFFFFFE; // Don't run it and let's see what happens!
810 //Hmm. Seems to lock up when going into the demo...
811 //Try to disable the collision altogether!
814 extern int effect_start5;
815 static bool finished = false;
816 //if (GPU_RUNNING && effect_start5 && !finished)
817 if (GPU_RUNNING && effect_start5 && gpu_pc == 0xF035D8)
819 // Let's do a dump of $6528!
820 /* uint32 numItems = JaguarReadWord(0x6BD6);
821 WriteLog("\nDump of $6528: %u items.\n\n", numItems);
822 for(int i=0; i<numItems*3*4; i+=3*4)
824 WriteLog("\t%04X: %08X %08X %08X -> ", 0x6528+i, JaguarReadLong(0x6528+i),
825 JaguarReadLong(0x6528+i+4), JaguarReadLong(0x6528+i+8));
826 uint16 link = JaguarReadWord(0x6528+i+8+2);
827 for(int j=0; j<40; j+=4)
828 WriteLog("%08X ", JaguarReadLong(link + j));
832 // Let's try a manual blit here...
833 //This isn't working the way it should! !!! FIX !!!
834 //Err, actually, it is.
835 // NOW, it works right! Problem solved!!! It's a blitter bug!
836 /* uint32 src = 0x4D54, dst = 0xF03000, width = 10 * 4;
837 for(int y=0; y<127; y++)
839 for(int x=0; x<2; x++)
841 JaguarWriteLong(dst, JaguarReadLong(src));
846 src += width - (2 * 4);
850 WriteLog("\nGPU: About to execute collision detection code.\n\n");//*/
852 /* WriteLog("\nGPU: About to execute collision detection code. Data @ 4D54:\n\n");
854 for(int i=0x004D54; i<0x004D54+2048; i++)
856 WriteLog("%02X ", JaguarReadByte(i));
864 WriteLog("\n\nData @ F03000:\n\n");
866 for(int i=0xF03000; i<0xF03200; i++)
868 WriteLog("%02X ", JaguarReadByte(i));
882 /*if (!GPU_RUNNING && finished)
884 WriteLog("\nGPU: Finished collision detection code. Exiting!\n\n");
889 // (?) If we're set running by the M68K (or DSP?) then end its timeslice to
890 // allow the GPU a chance to run...
891 // Yes! This partially fixed Trevor McFur...
893 m68k_end_timeslice();
900 gpu_div_control = data;
902 // default: // unaligned long write
909 // JaguarWriteWord(offset, (data >> 16) & 0xFFFF, who);
910 // JaguarWriteWord(offset+2, data & 0xFFFF, who);
911 // We're a 32-bit processor, we can do a long write...!
912 JaguarWriteLong(offset, data, who);
916 // Change register banks if necessary
918 void GPUUpdateRegisterBanks(void)
920 int bank = (gpu_flags & REGPAGE); // REGPAGE bit
922 if (gpu_flags & IMASK) // IMASK bit
923 bank = 0; // IMASK forces main bank to be bank 0
926 gpu_reg = gpu_reg_bank_1, gpu_alternate_reg = gpu_reg_bank_0;
928 gpu_reg = gpu_reg_bank_0, gpu_alternate_reg = gpu_reg_bank_1;
931 void GPUHandleIRQs(void)
933 // Bail out if we're already in an interrupt!
934 if (gpu_flags & IMASK)
937 // Get the interrupt latch & enable bits
938 uint32 bits = (gpu_control >> 6) & 0x1F, mask = (gpu_flags >> 4) & 0x1F;
940 // Bail out if latched interrupts aren't enabled
945 // Determine which interrupt to service
946 uint32 which = 0; //Isn't there a #pragma to disable this warning???
959 WriteLog("GPU: Generating IRQ #%i\n", which);
961 // set the interrupt flag
963 GPUUpdateRegisterBanks();
965 // subqt #4,r31 ; pre-decrement stack pointer
966 // move pc,r30 ; address of interrupted code
967 // store r30,(r31) ; store return address
969 GPUWriteLong(gpu_reg[31], gpu_pc - 2, GPU);
971 // movei #service_address,r30 ; pointer to ISR entry
972 // jump (r30) ; jump to ISR
974 gpu_pc = gpu_reg[30] = GPU_WORK_RAM_BASE + (which * 0x10);
977 void GPUSetIRQLine(int irqline, int state)
980 WriteLog("GPU: Setting GPU IRQ line #%i\n", irqline);
982 uint32 mask = 0x0040 << irqline;
983 gpu_control &= ~mask; // Clear the interrupt latch
987 gpu_control |= mask; // Assert the interrupt latch
988 GPUHandleIRQs(); // And handle the interrupt...
992 //TEMPORARY: Testing only!
998 // memory_malloc_secure((void **)&gpu_ram_8, 0x1000, "GPU work RAM");
999 // memory_malloc_secure((void **)&gpu_reg_bank_0, 32 * sizeof(int32), "GPU bank 0 regs");
1000 // memory_malloc_secure((void **)&gpu_reg_bank_1, 32 * sizeof(int32), "GPU bank 1 regs");
1002 build_branch_condition_table();
1006 //TEMPORARY: Testing only!
1013 // GPU registers (directly visible)
1014 gpu_flags = 0x00000000;
1015 gpu_matrix_control = 0x00000000;
1016 gpu_pointer_to_matrix = 0x00000000;
1017 gpu_data_organization = 0xFFFFFFFF;
1018 gpu_pc = 0x00F03000;
1019 gpu_control = 0x00002800; // Correctly sets this as TOM Rev. 2
1020 gpu_hidata = 0x00000000;
1021 gpu_remain = 0x00000000; // These two registers are RO/WO
1022 gpu_div_control = 0x00000000;
1024 // GPU internal register
1025 gpu_acc = 0x00000000;
1027 gpu_reg = gpu_reg_bank_0;
1028 gpu_alternate_reg = gpu_reg_bank_1;
1030 for(int i=0; i<32; i++)
1031 gpu_reg[i] = gpu_alternate_reg[i] = 0x00000000;
1034 memset(gpu_ram_8, 0xFF, 0x1000);
1036 //not needed GPUInterruptPending = false;
1040 uint32 GPUReadPC(void)
1045 void GPUResetStats(void)
1047 for(uint32 i=0; i<64; i++)
1048 gpu_opcode_use[i] = 0;
1049 WriteLog("--> GPU stats were reset!\n");
1052 void GPUDumpDisassembly(void)
1056 WriteLog("\n---[GPU code at 00F03000]---------------------------\n");
1057 uint32 j = 0xF03000;
1058 while (j <= 0xF03FFF)
1061 j += dasmjag(JAGUAR_GPU, buffer, j);
1062 WriteLog("\t%08X: %s\n", oldj, buffer);
1066 void GPUDumpRegisters(void)
1068 WriteLog("\n---[GPU flags: NCZ %d%d%d]-----------------------\n", gpu_flag_n, gpu_flag_c, gpu_flag_z);
1069 WriteLog("\nRegisters bank 0\n");
1070 for(int j=0; j<8; j++)
1072 WriteLog("\tR%02i = %08X R%02i = %08X R%02i = %08X R%02i = %08X\n",
1073 (j << 2) + 0, gpu_reg_bank_0[(j << 2) + 0],
1074 (j << 2) + 1, gpu_reg_bank_0[(j << 2) + 1],
1075 (j << 2) + 2, gpu_reg_bank_0[(j << 2) + 2],
1076 (j << 2) + 3, gpu_reg_bank_0[(j << 2) + 3]);
1078 WriteLog("Registers bank 1\n");
1079 for(int j=0; j<8; j++)
1081 WriteLog("\tR%02i = %08X R%02i = %08X R%02i = %08X R%02i = %08X\n",
1082 (j << 2) + 0, gpu_reg_bank_1[(j << 2) + 0],
1083 (j << 2) + 1, gpu_reg_bank_1[(j << 2) + 1],
1084 (j << 2) + 2, gpu_reg_bank_1[(j << 2) + 2],
1085 (j << 2) + 3, gpu_reg_bank_1[(j << 2) + 3]);
1089 void GPUDumpMemory(void)
1091 WriteLog("\n---[GPU data at 00F03000]---------------------------\n");
1092 for(int i=0; i<0xFFF; i+=4)
1093 WriteLog("\t%08X: %02X %02X %02X %02X\n", 0xF03000+i, gpu_ram_8[i],
1094 gpu_ram_8[i+1], gpu_ram_8[i+2], gpu_ram_8[i+3]);
1099 WriteLog("GPU: Stopped at PC=%08X (GPU %s running)\n", (unsigned int)gpu_pc, GPU_RUNNING ? "was" : "wasn't");
1101 // Get the interrupt latch & enable bits
1102 uint8 bits = (gpu_control >> 6) & 0x1F, mask = (gpu_flags >> 4) & 0x1F;
1103 WriteLog("GPU: Latch bits = %02X, enable bits = %02X\n", bits, mask);
1106 GPUDumpDisassembly();
1108 WriteLog("\nGPU opcodes use:\n");
1109 for(int i=0; i<64; i++)
1111 if (gpu_opcode_use[i])
1112 WriteLog("\t%17s %lu\n", gpu_opcode_str[i], gpu_opcode_use[i]);
1116 // memory_free(gpu_ram_8);
1117 // memory_free(gpu_reg_bank_0);
1118 // memory_free(gpu_reg_bank_1);
1122 // Main GPU execution core
1124 static int testCount = 1;
1126 static bool tripwire = false;
1127 void GPUExec(int32 cycles)
1132 #ifdef GPU_SINGLE_STEPPING
1133 if (gpu_control & 0x18)
1136 gpu_control &= ~0x10;
1140 gpu_releaseTimeSlice_flag = 0;
1143 while (cycles > 0 && GPU_RUNNING)
1145 if (gpu_ram_8[0x054] == 0x98 && gpu_ram_8[0x055] == 0x0A && gpu_ram_8[0x056] == 0x03
1146 && gpu_ram_8[0x057] == 0x00 && gpu_ram_8[0x058] == 0x00 && gpu_ram_8[0x059] == 0x00)
1148 if (gpu_pc == 0xF03000)
1150 extern uint32 starCount;
1152 /* WriteLog("GPU: Starting starfield generator... Dump of [R03=%08X]:\n", gpu_reg_bank_0[03]);
1153 uint32 base = gpu_reg_bank_0[3];
1154 for(uint32 i=0; i<0x100; i+=16)
1156 WriteLog("%02X: ", i);
1157 for(uint32 j=0; j<16; j++)
1159 WriteLog("%02X ", JaguarReadByte(base + i + j));
1164 // if (gpu_pc == 0xF03)
1168 /*if (gpu_pc == 0xF03B9E && gpu_reg_bank_0[01] == 0)
1171 WriteLog("GPU: Starting disassembly log...\n");
1174 /*if (gpu_pc == 0xF0359A)
1179 /* gpu_flag_c = (gpu_flag_c ? 1 : 0);
1180 gpu_flag_z = (gpu_flag_z ? 1 : 0);
1181 gpu_flag_n = (gpu_flag_n ? 1 : 0);*/
1183 uint16 opcode = GPUReadWord(gpu_pc, GPU);
1184 uint32 index = opcode >> 10;
1185 gpu_instruction = opcode; // Added for GPU #3...
1186 gpu_opcode_first_parameter = (opcode >> 5) & 0x1F;
1187 gpu_opcode_second_parameter = opcode & 0x1F;
1188 /*if (gpu_pc == 0xF03BE8)
1189 WriteLog("Start of OP frame write...\n");
1190 if (gpu_pc == 0xF03EEE)
1191 WriteLog("--> Writing BRANCH object ---\n");
1192 if (gpu_pc == 0xF03F62)
1193 WriteLog("--> Writing BITMAP object ***\n");//*/
1194 /*if (gpu_pc == 0xF03546)
1196 WriteLog("\n--> GPU PC: F03546\n");
1198 GPUDumpDisassembly();
1200 /*if (gpu_pc == 0xF033F6)
1202 WriteLog("\n--> GPU PC: F033F6\n");
1204 GPUDumpDisassembly();
1206 /*if (gpu_pc == 0xF033CC)
1208 WriteLog("\n--> GPU PC: F033CC\n");
1210 GPUDumpDisassembly();
1212 /*if (gpu_pc == 0xF033D6)
1214 WriteLog("\n--> GPU PC: F033D6 (#%d)\n", testCount++);
1218 /*if (gpu_pc == 0xF033D8)
1220 WriteLog("\n--> GPU PC: F033D8 (#%d)\n", testCount++);
1224 /*if (gpu_pc == 0xF0358E)
1226 WriteLog("\n--> GPU PC: F0358E (#%d)\n", testCount++);
1230 /*if (gpu_pc == 0xF034CA)
1232 WriteLog("\n--> GPU PC: F034CA (#%d)\n", testCount++);
1235 /*if (gpu_pc == 0xF034CA)
1237 len = gpu_reg[1] + 4;//, r9save = gpu_reg[9];
1238 WriteLog("\nAbout to subtract [#%d] (R14=%08X, R15=%08X, R9=%08X):\n ", testCount++, gpu_reg[14], gpu_reg[15], gpu_reg[9]);
1239 for(int i=0; i<len; i+=4)
1240 WriteLog(" %08X", GPUReadLong(gpu_reg[15]+i));
1242 for(int i=0; i<len; i+=4)
1243 WriteLog(" %08X", GPUReadLong(gpu_reg[14]+i));
1246 if (gpu_pc == 0xF034DE)
1248 WriteLog("\nSubtracted! (R14=%08X, R15=%08X):\n ", gpu_reg[14], gpu_reg[15]);
1249 for(int i=0; i<len; i+=4)
1250 WriteLog(" %08X", GPUReadLong(gpu_reg[15]+i));
1252 for(int i=0; i<len; i+=4)
1253 WriteLog(" %08X", GPUReadLong(gpu_reg[14]+i));
1255 for(int i=0; i<len; i+=4)
1256 WriteLog(" --------");
1258 for(int i=0; i<len; i+=4)
1259 WriteLog(" %08X", GPUReadLong(gpu_reg[9]+4+i));
1262 /*if (gpu_pc == 0xF035C8)
1264 WriteLog("\n--> GPU PC: F035C8 (#%d)\n", testCount++);
1266 GPUDumpDisassembly();
1271 // gpu_reset_stats();
1272 static char buffer[512];
1273 dasmjag(JAGUAR_GPU, buffer, gpu_pc);
1274 WriteLog("GPU: [%08X] %s (RM=%08X, RN=%08X) -> ", gpu_pc, buffer, RM, RN);
1276 //$E400 -> 1110 01 -> $39 -> 57
1279 gpu_opcode[index]();
1281 // gpu2_opcode[index]();
1283 //GPU #3 (Doesn't show ATARI logo! #1 & #2 do...)
1285 // gpu3_opcode[index]();
1288 //GPU: [00F03548] jr nz,00F03560 (0xd561) (RM=00F03114, RN=00000004) -> --> JR: Branch taken.
1289 /*static bool firstTime = true;
1290 if (gpu_pc == 0xF03548 && firstTime)
1293 // firstTime = false;
1295 //static char buffer[512];
1297 //while (k<0xF0356C)
1300 //k += dasmjag(JAGUAR_GPU, buffer, k);
1301 //WriteLog("GPU: [%08X] %s\n", oldk, buffer);
1303 // gpu_start_log = 1;
1305 //GPU: [00F0354C] jump nz,(r29) (0xd3a1) (RM=00F03314, RN=00000004) -> (RM=00F03314, RN=00000004)
1306 /*if (gpu_pc == 0xF0354C)
1307 gpu_flag_z = 0;//, gpu_start_log = 1;//*/
1309 cycles -= gpu_opcode_cycles[index];
1310 gpu_opcode_use[index]++;
1312 WriteLog("(RM=%08X, RN=%08X)\n", RM, RN);//*/
1313 if ((gpu_pc < 0xF03000 || gpu_pc > 0xF03FFF) && !tripwire)
1315 WriteLog("GPU: Executing outside local RAM! GPU_PC: %08X\n", gpu_pc);
1328 GPU opcodes use (offset punch--vertically below bad guy):
1350 load_r14_indexed 1183
1351 load_r15_indexed 1125
1354 store_r14_indexed 320
1362 static void gpu_opcode_jump(void)
1365 const char * condition[32] =
1366 { "T", "nz", "z", "???", "nc", "nc nz", "nc z", "???", "c", "c nz",
1367 "c z", "???", "???", "???", "???", "???", "???", "???", "???",
1368 "???", "nn", "nn nz", "nn z", "???", "n", "n nz", "n z", "???",
1369 "???", "???", "???", "F" };
1371 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);
1374 /* gpu_flag_c = (gpu_flag_c ? 1 : 0);
1375 gpu_flag_z = (gpu_flag_z ? 1 : 0);
1376 gpu_flag_n = (gpu_flag_n ? 1 : 0);*/
1377 // KLUDGE: Used by BRANCH_CONDITION
1378 uint32 jaguar_flags = (gpu_flag_n << 2) | (gpu_flag_c << 1) | gpu_flag_z;
1380 if (BRANCH_CONDITION(IMM_2))
1384 WriteLog("Branched!\n");
1387 WriteLog(" --> JUMP: Branch taken.\n");
1388 uint32 delayed_pc = RM;
1390 gpu_pc = delayed_pc;
1391 /* uint16 opcode = GPUReadWord(gpu_pc, GPU);
1392 gpu_opcode_first_parameter = (opcode >> 5) & 0x1F;
1393 gpu_opcode_second_parameter = opcode & 0x1F;
1395 gpu_pc = delayed_pc;
1396 gpu_opcode[opcode>>10]();//*/
1401 WriteLog("Branch NOT taken.\n");
1405 static void gpu_opcode_jr(void)
1408 const char * condition[32] =
1409 { "T", "nz", "z", "???", "nc", "nc nz", "nc z", "???", "c", "c nz",
1410 "c z", "???", "???", "???", "???", "???", "???", "???", "???",
1411 "???", "nn", "nn nz", "nn z", "???", "n", "n nz", "n z", "???",
1412 "???", "???", "???", "F" };
1414 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);
1416 /* if (CONDITION(jaguar.op & 31))
1418 int32 r1 = (INT8)((jaguar.op >> 2) & 0xF8) >> 2;
1419 uint32 newpc = jaguar.PC + r1;
1421 jaguar.op = ROPCODE(jaguar.PC);
1423 (*jaguar.table[jaguar.op >> 10])();
1425 jaguar_icount -= 3; // 3 wait states guaranteed
1428 /* gpu_flag_n = (gpu_flag_n ? 1 : 0);
1429 gpu_flag_c = (gpu_flag_c ? 1 : 0);
1430 gpu_flag_z = (gpu_flag_z ? 1 : 0);*/
1431 // KLUDGE: Used by BRANCH_CONDITION
1432 uint32 jaguar_flags = (gpu_flag_n << 2) | (gpu_flag_c << 1) | gpu_flag_z;
1434 if (BRANCH_CONDITION(IMM_2))
1438 WriteLog("Branched!\n");
1441 WriteLog(" --> JR: Branch taken.\n");
1442 int32 offset = (IMM_1 & 0x10 ? 0xFFFFFFF0 | IMM_1 : IMM_1); // Sign extend IMM_1
1443 int32 delayed_pc = gpu_pc + (offset * 2);
1445 gpu_pc = delayed_pc;
1446 /* uint16 opcode = GPUReadWord(gpu_pc, GPU);
1447 gpu_opcode_first_parameter = (opcode >> 5) & 0x1F;
1448 gpu_opcode_second_parameter = opcode & 0x1F;
1450 gpu_pc = delayed_pc;
1451 gpu_opcode[opcode>>10]();//*/
1456 WriteLog("Branch NOT taken.\n");
1460 static void gpu_opcode_add(void)
1464 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);
1466 uint32 res = RN + RM;
1467 CLR_ZNC; SET_ZNC_ADD(RN, RM, res);
1471 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);
1475 static void gpu_opcode_addc(void)
1479 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);
1481 /* int dreg = jaguar.op & 31;
1482 uint32 r1 = jaguar.r[(jaguar.op >> 5) & 31];
1483 uint32 r2 = jaguar.r[dreg];
1484 uint32 res = r2 + r1 + ((jaguar.FLAGS >> 1) & 1);
1485 jaguar.r[dreg] = res;
1486 CLR_ZNC; SET_ZNC_ADD(r2,r1,res);*/
1488 uint32 res = RN + RM + gpu_flag_c;
1489 uint32 carry = gpu_flag_c;
1490 // SET_ZNC_ADD(RN, RM, res); //???BUG??? Yes!
1491 SET_ZNC_ADD(RN + carry, RM, res);
1492 // SET_ZNC_ADD(RN, RM + carry, res);
1496 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);
1500 static void gpu_opcode_addq(void)
1504 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);
1506 uint32 r1 = gpu_convert_zero[IMM_1];
1507 uint32 res = RN + r1;
1508 CLR_ZNC; SET_ZNC_ADD(RN, r1, res);
1512 WriteLog("[NCZ:%u%u%u, R%02u=%08X]\n", gpu_flag_n, gpu_flag_c, gpu_flag_z, IMM_2, RN);
1516 static void gpu_opcode_addqt(void)
1518 #ifdef GPU_DIS_ADDQT
1520 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);
1522 RN += gpu_convert_zero[IMM_1];
1523 #ifdef GPU_DIS_ADDQT
1525 WriteLog("[NCZ:%u%u%u, R%02u=%08X]\n", gpu_flag_n, gpu_flag_c, gpu_flag_z, IMM_2, RN);
1529 static void gpu_opcode_sub(void)
1533 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);
1535 uint32 res = RN - RM;
1536 SET_ZNC_SUB(RN, RM, res);
1540 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);
1544 static void gpu_opcode_subc(void)
1548 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);
1550 uint32 res = RN - RM - gpu_flag_c;
1551 uint32 borrow = gpu_flag_c;
1552 // SET_ZNC_SUB(RN, RM, res); //???BUG??? YES!!!
1553 //No matter how you do it, there is a problem. With below, it's 0-0 with carry,
1554 //and the one below it it's FFFFFFFF - FFFFFFFF with carry... !!! FIX !!!
1555 // SET_ZNC_SUB(RN - borrow, RM, res);
1556 SET_ZNC_SUB(RN, RM + borrow, res);
1560 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);
1564 N = 5, M = 3, 3 - 5 = -2, C = 1... Or, in our case:
1565 N = 0, M = 1, 0 - 1 = -1, C = 0!
1567 #define SET_C_SUB(a,b) (gpu_flag_c = ((uint32)(b) > (uint32)(a)))
1568 #define SET_ZN(r) SET_N(r); SET_Z(r)
1569 #define SET_ZNC_ADD(a,b,r) SET_N(r); SET_Z(r); SET_C_ADD(a,b)
1570 #define SET_ZNC_SUB(a,b,r) SET_N(r); SET_Z(r); SET_C_SUB(a,b)
1572 static void gpu_opcode_subq(void)
1576 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);
1578 uint32 r1 = gpu_convert_zero[IMM_1];
1579 uint32 res = RN - r1;
1580 SET_ZNC_SUB(RN, r1, res);
1584 WriteLog("[NCZ:%u%u%u, R%02u=%08X]\n", gpu_flag_n, gpu_flag_c, gpu_flag_z, IMM_2, RN);
1588 static void gpu_opcode_subqt(void)
1590 #ifdef GPU_DIS_SUBQT
1592 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);
1594 RN -= gpu_convert_zero[IMM_1];
1595 #ifdef GPU_DIS_SUBQT
1597 WriteLog("[NCZ:%u%u%u, R%02u=%08X]\n", gpu_flag_n, gpu_flag_c, gpu_flag_z, IMM_2, RN);
1601 static void gpu_opcode_cmp(void)
1605 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);
1607 uint32 res = RN - RM;
1608 SET_ZNC_SUB(RN, RM, res);
1611 WriteLog("[NCZ:%u%u%u]\n", gpu_flag_n, gpu_flag_c, gpu_flag_z);
1615 static void gpu_opcode_cmpq(void)
1617 static int32 sqtable[32] =
1618 { 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 };
1621 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);
1623 uint32 r1 = sqtable[IMM_1 & 0x1F]; // I like this better -> (INT8)(jaguar.op >> 2) >> 3;
1624 uint32 res = RN - r1;
1625 SET_ZNC_SUB(RN, r1, res);
1628 WriteLog("[NCZ:%u%u%u]\n", gpu_flag_n, gpu_flag_c, gpu_flag_z);
1632 static void gpu_opcode_and(void)
1636 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);
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_or(void)
1650 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);
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_xor(void)
1664 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);
1670 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);
1674 static void gpu_opcode_not(void)
1678 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);
1684 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);
1688 static void gpu_opcode_move_pc(void)
1690 #ifdef GPU_DIS_MOVEPC
1692 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);
1694 // Should be previous PC--this might not always be previous instruction!
1695 // Then again, this will point right at the *current* instruction, i.e., MOVE PC,R!
1697 #ifdef GPU_DIS_MOVEPC
1699 WriteLog("[NCZ:%u%u%u, R%02u=%08X]\n", gpu_flag_n, gpu_flag_c, gpu_flag_z, IMM_2, RN);
1703 static void gpu_opcode_sat8(void)
1707 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);
1709 RN = ((int32)RN < 0 ? 0 : (RN > 0xFF ? 0xFF : RN));
1713 WriteLog("[NCZ:%u%u%u, R%02u=%08X]\n", gpu_flag_n, gpu_flag_c, gpu_flag_z, IMM_2, RN);
1717 static void gpu_opcode_sat16(void)
1719 RN = ((int32)RN < 0 ? 0 : (RN > 0xFFFF ? 0xFFFF : RN));
1723 static void gpu_opcode_sat24(void)
1725 RN = ((int32)RN < 0 ? 0 : (RN > 0xFFFFFF ? 0xFFFFFF : RN));
1729 static void gpu_opcode_store_r14_indexed(void)
1731 #ifdef GPU_DIS_STORE14I
1733 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));
1735 #ifdef GPU_CORRECT_ALIGNMENT_STORE
1736 GPUWriteLong((gpu_reg[14] & 0xFFFFFFFC) + (gpu_convert_zero[IMM_1] << 2), RN, GPU);
1738 GPUWriteLong(gpu_reg[14] + (gpu_convert_zero[IMM_1] << 2), RN, GPU);
1742 static void gpu_opcode_store_r15_indexed(void)
1744 #ifdef GPU_DIS_STORE15I
1746 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));
1748 #ifdef GPU_CORRECT_ALIGNMENT_STORE
1749 GPUWriteLong((gpu_reg[15] & 0xFFFFFFFC) + (gpu_convert_zero[IMM_1] << 2), RN, GPU);
1751 GPUWriteLong(gpu_reg[15] + (gpu_convert_zero[IMM_1] << 2), RN, GPU);
1755 static void gpu_opcode_load_r14_ri(void)
1757 #ifdef GPU_DIS_LOAD14R
1759 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);
1761 #ifdef GPU_CORRECT_ALIGNMENT
1762 RN = GPUReadLong((gpu_reg[14] + RM) & 0xFFFFFFFC, GPU);
1764 RN = GPUReadLong(gpu_reg[14] + RM, GPU);
1766 #ifdef GPU_DIS_LOAD14R
1768 WriteLog("[NCZ:%u%u%u, R%02u=%08X]\n", gpu_flag_n, gpu_flag_c, gpu_flag_z, IMM_2, RN);
1772 static void gpu_opcode_load_r15_ri(void)
1774 #ifdef GPU_DIS_LOAD15R
1776 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);
1778 #ifdef GPU_CORRECT_ALIGNMENT
1779 RN = GPUReadLong((gpu_reg[15] + RM) & 0xFFFFFFFC, GPU);
1781 RN = GPUReadLong(gpu_reg[15] + RM, GPU);
1783 #ifdef GPU_DIS_LOAD15R
1785 WriteLog("[NCZ:%u%u%u, R%02u=%08X]\n", gpu_flag_n, gpu_flag_c, gpu_flag_z, IMM_2, RN);
1789 static void gpu_opcode_store_r14_ri(void)
1791 #ifdef GPU_DIS_STORE14R
1793 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]);
1795 #ifdef GPU_CORRECT_ALIGNMENT_STORE
1796 GPUWriteLong((gpu_reg[14] + RM) & 0xFFFFFFFC, RN, GPU);
1798 GPUWriteLong(gpu_reg[14] + RM, RN, GPU);
1802 static void gpu_opcode_store_r15_ri(void)
1804 #ifdef GPU_DIS_STORE15R
1806 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]);
1808 #ifdef GPU_CORRECT_ALIGNMENT_STORE
1809 GPUWriteLong((gpu_reg[15] + RM) & 0xFFFFFFFC, RN, GPU);
1811 GPUWriteLong(gpu_reg[15] + RM, RN, GPU);
1815 static void gpu_opcode_nop(void)
1819 WriteLog("%06X: NOP [NCZ:%u%u%u]\n", gpu_pc-2, gpu_flag_n, gpu_flag_c, gpu_flag_z);
1823 static void gpu_opcode_pack(void)
1827 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);
1831 //BUG! if (RM == 0) // Pack
1832 if (IMM_1 == 0) // Pack
1833 RN = ((val >> 10) & 0x0000F000) | ((val >> 5) & 0x00000F00) | (val & 0x000000FF);
1835 RN = ((val & 0x0000F000) << 10) | ((val & 0x00000F00) << 5) | (val & 0x000000FF);
1838 WriteLog("[NCZ:%u%u%u, R%02u=%08X]\n", gpu_flag_n, gpu_flag_c, gpu_flag_z, IMM_2, RN);
1842 static void gpu_opcode_storeb(void)
1844 #ifdef GPU_DIS_STOREB
1846 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);
1849 // Would appear to be so...!
1850 if ((RM >= 0xF03000) && (RM <= 0xF03FFF))
1851 GPUWriteLong(RM, RN & 0xFF, GPU);
1853 JaguarWriteByte(RM, RN, GPU);
1856 static void gpu_opcode_storew(void)
1858 #ifdef GPU_DIS_STOREW
1860 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);
1862 #ifdef GPU_CORRECT_ALIGNMENT_STORE
1863 if ((RM >= 0xF03000) && (RM <= 0xF03FFF))
1864 GPUWriteLong(RM & 0xFFFFFFFE, RN & 0xFFFF, GPU);
1866 JaguarWriteWord(RM & 0xFFFFFFFE, RN, GPU);
1868 if ((RM >= 0xF03000) && (RM <= 0xF03FFF))
1869 GPUWriteLong(RM, RN & 0xFFFF, GPU);
1871 JaguarWriteWord(RM, RN, GPU);
1875 static void gpu_opcode_store(void)
1877 #ifdef GPU_DIS_STORE
1879 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);
1881 #ifdef GPU_CORRECT_ALIGNMENT_STORE
1882 GPUWriteLong(RM & 0xFFFFFFFC, RN, GPU);
1884 GPUWriteLong(RM, RN, GPU);
1888 static void gpu_opcode_storep(void)
1890 #ifdef GPU_CORRECT_ALIGNMENT_STORE
1891 GPUWriteLong((RM & 0xFFFFFFF8) + 0, gpu_hidata, GPU);
1892 GPUWriteLong((RM & 0xFFFFFFF8) + 4, RN, GPU);
1894 GPUWriteLong(RM + 0, gpu_hidata, GPU);
1895 GPUWriteLong(RM + 4, RN, GPU);
1899 static void gpu_opcode_loadb(void)
1901 #ifdef GPU_DIS_LOADB
1903 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);
1905 if ((RM >= 0xF03000) && (RM <= 0xF03FFF))
1906 RN = GPUReadLong(RM, GPU) & 0xFF;
1908 RN = JaguarReadByte(RM, GPU);
1909 #ifdef GPU_DIS_LOADB
1911 WriteLog("[NCZ:%u%u%u, R%02u=%08X]\n", gpu_flag_n, gpu_flag_c, gpu_flag_z, IMM_2, RN);
1915 static void gpu_opcode_loadw(void)
1917 #ifdef GPU_DIS_LOADW
1919 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);
1921 #ifdef GPU_CORRECT_ALIGNMENT
1922 if ((RM >= 0xF03000) && (RM <= 0xF03FFF))
1923 RN = GPUReadLong(RM & 0xFFFFFFFE, GPU) & 0xFFFF;
1925 RN = JaguarReadWord(RM & 0xFFFFFFFE, GPU);
1927 if ((RM >= 0xF03000) && (RM <= 0xF03FFF))
1928 RN = GPUReadLong(RM, GPU) & 0xFFFF;
1930 RN = JaguarReadWord(RM, GPU);
1932 #ifdef GPU_DIS_LOADW
1934 WriteLog("[NCZ:%u%u%u, R%02u=%08X]\n", gpu_flag_n, gpu_flag_c, gpu_flag_z, IMM_2, RN);
1938 // According to the docs, & "Do The Same", this address is long aligned...
1940 // And it works!!! Need to fix all instances...
1941 static void gpu_opcode_load(void)
1945 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);
1947 #ifdef GPU_CORRECT_ALIGNMENT
1948 RN = GPUReadLong(RM & 0xFFFFFFFC, GPU);
1950 RN = GPUReadLong(RM, GPU);
1954 WriteLog("[NCZ:%u%u%u, R%02u=%08X]\n", gpu_flag_n, gpu_flag_c, gpu_flag_z, IMM_2, RN);
1958 static void gpu_opcode_loadp(void)
1960 #ifdef GPU_CORRECT_ALIGNMENT
1961 gpu_hidata = GPUReadLong((RM & 0xFFFFFFF8) + 0, GPU);
1962 RN = GPUReadLong((RM & 0xFFFFFFF8) + 4, GPU);
1964 gpu_hidata = GPUReadLong(RM + 0, GPU);
1965 RN = GPUReadLong(RM + 4, GPU);
1969 static void gpu_opcode_load_r14_indexed(void)
1971 #ifdef GPU_DIS_LOAD14I
1973 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);
1975 #ifdef GPU_CORRECT_ALIGNMENT
1976 RN = GPUReadLong((gpu_reg[14] & 0xFFFFFFFC) + (gpu_convert_zero[IMM_1] << 2), GPU);
1978 RN = GPUReadLong(gpu_reg[14] + (gpu_convert_zero[IMM_1] << 2), GPU);
1980 #ifdef GPU_DIS_LOAD14I
1982 WriteLog("[NCZ:%u%u%u, R%02u=%08X]\n", gpu_flag_n, gpu_flag_c, gpu_flag_z, IMM_2, RN);
1986 static void gpu_opcode_load_r15_indexed(void)
1988 #ifdef GPU_DIS_LOAD15I
1990 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);
1992 #ifdef GPU_CORRECT_ALIGNMENT
1993 RN = GPUReadLong((gpu_reg[15] & 0xFFFFFFFC) + (gpu_convert_zero[IMM_1] << 2), GPU);
1995 RN = GPUReadLong(gpu_reg[15] + (gpu_convert_zero[IMM_1] << 2), GPU);
1997 #ifdef GPU_DIS_LOAD15I
1999 WriteLog("[NCZ:%u%u%u, R%02u=%08X]\n", gpu_flag_n, gpu_flag_c, gpu_flag_z, IMM_2, RN);
2003 static void gpu_opcode_movei(void)
2005 #ifdef GPU_DIS_MOVEI
2007 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);
2009 // This instruction is followed by 32-bit value in LSW / MSW format...
2010 RN = (uint32)GPUReadWord(gpu_pc, GPU) | ((uint32)GPUReadWord(gpu_pc + 2, GPU) << 16);
2012 #ifdef GPU_DIS_MOVEI
2014 WriteLog("[NCZ:%u%u%u, R%02u=%08X]\n", gpu_flag_n, gpu_flag_c, gpu_flag_z, IMM_2, RN);
2018 static void gpu_opcode_moveta(void)
2020 #ifdef GPU_DIS_MOVETA
2022 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);
2025 #ifdef GPU_DIS_MOVETA
2027 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);
2031 static void gpu_opcode_movefa(void)
2033 #ifdef GPU_DIS_MOVEFA
2035 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);
2038 #ifdef GPU_DIS_MOVEFA
2040 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);
2044 static void gpu_opcode_move(void)
2048 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);
2053 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);
2057 static void gpu_opcode_moveq(void)
2059 #ifdef GPU_DIS_MOVEQ
2061 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);
2064 #ifdef GPU_DIS_MOVEQ
2066 WriteLog("[NCZ:%u%u%u, R%02u=%08X]\n", gpu_flag_n, gpu_flag_c, gpu_flag_z, IMM_2, RN);
2070 static void gpu_opcode_resmac(void)
2075 static void gpu_opcode_imult(void)
2077 #ifdef GPU_DIS_IMULT
2079 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);
2081 RN = (int16)RN * (int16)RM;
2083 #ifdef GPU_DIS_IMULT
2085 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);
2089 static void gpu_opcode_mult(void)
2093 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);
2095 RN = (uint16)RM * (uint16)RN;
2099 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);
2103 static void gpu_opcode_bclr(void)
2107 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);
2109 uint32 res = RN & ~(1 << IMM_1);
2114 WriteLog("[NCZ:%u%u%u, R%02u=%08X]\n", gpu_flag_n, gpu_flag_c, gpu_flag_z, IMM_2, RN);
2118 static void gpu_opcode_btst(void)
2122 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);
2124 gpu_flag_z = (~RN >> IMM_1) & 1;
2127 WriteLog("[NCZ:%u%u%u, R%02u=%08X]\n", gpu_flag_n, gpu_flag_c, gpu_flag_z, IMM_2, RN);
2131 static void gpu_opcode_bset(void)
2135 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);
2137 uint32 res = RN | (1 << IMM_1);
2142 WriteLog("[NCZ:%u%u%u, R%02u=%08X]\n", gpu_flag_n, gpu_flag_c, gpu_flag_z, IMM_2, RN);
2146 static void gpu_opcode_imacn(void)
2148 uint32 res = (int16)RM * (int16)(RN);
2152 static void gpu_opcode_mtoi(void)
2155 uint32 res = RN = (((int32)_RM >> 8) & 0xFF800000) | (_RM & 0x007FFFFF);
2159 static void gpu_opcode_normi(void)
2166 while ((_RM & 0xFFC00000) == 0)
2171 while ((_RM & 0xFF800000) != 0)
2181 static void gpu_opcode_mmult(void)
2183 int count = gpu_matrix_control & 0x0F; // Matrix width
2184 uint32 addr = gpu_pointer_to_matrix; // In the GPU's RAM
2188 if (gpu_matrix_control & 0x10) // Column stepping
2190 for(int i=0; i<count; i++)
2194 a = (int16)((gpu_alternate_reg[IMM_1 + (i >> 1)] >> 16) & 0xFFFF);
2196 a = (int16)(gpu_alternate_reg[IMM_1 + (i >> 1)] & 0xFFFF);
2198 int16 b = ((int16)GPUReadWord(addr + 2, GPU));
2203 else // Row stepping
2205 for(int i=0; i<count; i++)
2209 a = (int16)((gpu_alternate_reg[IMM_1 + (i >> 1)] >> 16) & 0xFFFF);
2211 a = (int16)(gpu_alternate_reg[IMM_1 + (i >> 1)] & 0xFFFF);
2213 int16 b = ((int16)GPUReadWord(addr + 2, GPU));
2218 RN = res = (int32)accum;
2219 // carry flag to do (out of the last add)
2223 static void gpu_opcode_abs(void)
2227 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);
2229 gpu_flag_c = RN >> 31;
2230 if (RN == 0x80000000)
2231 //Is 0x80000000 a positive number? If so, then we need to set C to 0 as well!
2232 gpu_flag_n = 1, gpu_flag_z = 0;
2237 gpu_flag_n = 0; SET_FLAG_Z(RN);
2241 WriteLog("[NCZ:%u%u%u, R%02u=%08X]\n", gpu_flag_n, gpu_flag_c, gpu_flag_z, IMM_2, RN);
2245 static void gpu_opcode_div(void) // RN / RM
2249 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);
2251 // NOTE: remainder is NOT calculated correctly here!
2252 // The original tried to get it right by checking to see if the
2253 // remainder was negative, but that's too late...
2254 // The code there should do it now, but I'm not 100% sure...
2258 if (gpu_div_control & 0x01) // 16.16 division
2260 RN = ((uint64)RN << 16) / RM;
2261 gpu_remain = ((uint64)RN << 16) % RM;
2266 gpu_remain = RN % RM;
2269 if ((gpu_remain - RM) & 0x80000000) // If the result would have been negative...
2270 gpu_remain -= RM; // Then make it negative!
2280 if (gpu_div_control & 1)
2282 gpu_remain = (((uint64)_RN) << 16) % _RM;
2283 if (gpu_remain&0x80000000)
2285 RN = (((uint64)_RN) << 16) / _RM;
2289 gpu_remain = _RN % _RM;
2290 if (gpu_remain&0x80000000)
2299 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);
2303 static void gpu_opcode_imultn(void)
2305 uint32 res = (int32)((int16)RN * (int16)RM);
2306 gpu_acc = (int32)res;
2311 static void gpu_opcode_neg(void)
2315 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);
2318 SET_ZNC_SUB(0, RN, res);
2322 WriteLog("[NCZ:%u%u%u, R%02u=%08X]\n", gpu_flag_n, gpu_flag_c, gpu_flag_z, IMM_2, RN);
2326 static void gpu_opcode_shlq(void)
2330 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);
2332 // Was a bug here...
2333 // (Look at Aaron's code: If r1 = 32, then 32 - 32 = 0 which is wrong!)
2334 int32 r1 = 32 - IMM_1;
2335 uint32 res = RN << r1;
2336 SET_ZN(res); gpu_flag_c = (RN >> 31) & 1;
2340 WriteLog("[NCZ:%u%u%u, R%02u=%08X]\n", gpu_flag_n, gpu_flag_c, gpu_flag_z, IMM_2, RN);
2344 static void gpu_opcode_shrq(void)
2348 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);
2350 int32 r1 = gpu_convert_zero[IMM_1];
2351 uint32 res = RN >> r1;
2352 SET_ZN(res); gpu_flag_c = RN & 1;
2356 WriteLog("[NCZ:%u%u%u, R%02u=%08X]\n", gpu_flag_n, gpu_flag_c, gpu_flag_z, IMM_2, RN);
2360 static void gpu_opcode_ror(void)
2364 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);
2366 uint32 r1 = RM & 0x1F;
2367 uint32 res = (RN >> r1) | (RN << (32 - r1));
2368 SET_ZN(res); gpu_flag_c = (RN >> 31) & 1;
2372 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);
2376 static void gpu_opcode_rorq(void)
2380 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);
2382 uint32 r1 = gpu_convert_zero[IMM_1 & 0x1F];
2384 uint32 res = (r2 >> r1) | (r2 << (32 - r1));
2386 SET_ZN(res); gpu_flag_c = (r2 >> 31) & 0x01;
2389 WriteLog("[NCZ:%u%u%u, R%02u=%08X]\n", gpu_flag_n, gpu_flag_c, gpu_flag_z, IMM_2, RN);
2393 static void gpu_opcode_sha(void)
2395 /* int dreg = jaguar.op & 31;
2396 int32 r1 = (int32)jaguar.r[(jaguar.op >> 5) & 31];
2397 uint32 r2 = jaguar.r[dreg];
2403 res = (r1 <= -32) ? 0 : (r2 << -r1);
2404 jaguar.FLAGS |= (r2 >> 30) & 2;
2408 res = (r1 >= 32) ? ((int32)r2 >> 31) : ((int32)r2 >> r1);
2409 jaguar.FLAGS |= (r2 << 1) & 2;
2411 jaguar.r[dreg] = res;
2416 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);
2422 res = ((int32)RM <= -32) ? 0 : (RN << -(int32)RM);
2423 gpu_flag_c = RN >> 31;
2427 res = ((int32)RM >= 32) ? ((int32)RN >> 31) : ((int32)RN >> (int32)RM);
2428 gpu_flag_c = RN & 0x01;
2434 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);
2437 /* int32 sRM=(int32)RM;
2443 if (shift>=32) shift=32;
2444 gpu_flag_c=(_RN&0x80000000)>>31;
2454 if (shift>=32) shift=32;
2458 _RN=((int32)_RN)>>1;
2467 static void gpu_opcode_sharq(void)
2469 #ifdef GPU_DIS_SHARQ
2471 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);
2473 uint32 res = (int32)RN >> gpu_convert_zero[IMM_1];
2474 SET_ZN(res); gpu_flag_c = RN & 0x01;
2476 #ifdef GPU_DIS_SHARQ
2478 WriteLog("[NCZ:%u%u%u, R%02u=%08X]\n", gpu_flag_n, gpu_flag_c, gpu_flag_z, IMM_2, RN);
2482 static void gpu_opcode_sh(void)
2486 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);
2488 if (RM & 0x80000000) // Shift left
2490 gpu_flag_c = RN >> 31;
2491 RN = ((int32)RM <= -32 ? 0 : RN << -(int32)RM);
2495 gpu_flag_c = RN & 0x01;
2496 RN = (RM >= 32 ? 0 : RN >> RM);
2501 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);
2505 //Temporary: Testing only!
2506 //#include "gpu2.cpp"
2507 //#include "gpu3.cpp"
2511 // New thread-safe GPU core
2513 int GPUCore(void * data)