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 Hammons
9 // (C) 2010 Underground Software
11 // JLH = James Hammons <jlhamm@acm.org>
12 // JPM = Jean-Paul Mari <djipi.mari@gmail.com>
15 // --- ---------- -------------------------------------------------------------
16 // JLH 01/16/2010 Created this log ;-)
17 // JLH 11/26/2011 Added fixes for LOAD/STORE alignment issues
18 // JPM 06/06/2016 Visual Studio support
21 // Note: Endian wrongness probably stems from the MAME origins of this emu and
22 // the braindead way in which MAME handles memory. :-)
24 // Problem with not booting the BIOS was the incorrect way that the
25 // SUBC instruction set the carry when the carry was set going in...
26 // Same problem with ADDC...
32 #include <string.h> // For memset
37 #include "m68000/m68kinterface.h"
42 // Seems alignment in loads & stores was off...
43 #define GPU_CORRECT_ALIGNMENT
46 // For GPU dissasembly...
67 #define GPU_DIS_LOAD14I
68 #define GPU_DIS_LOAD14R
69 #define GPU_DIS_LOAD15I
70 #define GPU_DIS_LOAD15R
72 #define GPU_DIS_MOVEFA
74 #define GPU_DIS_MOVEPC
75 #define GPU_DIS_MOVETA
92 #define GPU_DIS_STOREB
93 #define GPU_DIS_STOREW
94 #define GPU_DIS_STORE14I
95 #define GPU_DIS_STORE14R
96 #define GPU_DIS_STORE15I
97 #define GPU_DIS_STORE15R
101 #define GPU_DIS_SUBQT
104 bool doGPUDis
= false;
105 //bool doGPUDis = true;
109 GPU opcodes use (BIOS flying ATARI logo):
151 #define CINT0FLAG 0x0200
152 #define CINT1FLAG 0x0400
153 #define CINT2FLAG 0x0800
154 #define CINT3FLAG 0x1000
155 #define CINT4FLAG 0x2000
156 #define CINT04FLAGS (CINT0FLAG | CINT1FLAG | CINT2FLAG | CINT3FLAG | CINT4FLAG)
160 #define ZERO_FLAG 0x0001
161 #define CARRY_FLAG 0x0002
162 #define NEGA_FLAG 0x0004
164 #define INT_ENA0 0x0010
165 #define INT_ENA1 0x0020
166 #define INT_ENA2 0x0040
167 #define INT_ENA3 0x0080
168 #define INT_ENA4 0x0100
169 #define INT_CLR0 0x0200
170 #define INT_CLR1 0x0400
171 #define INT_CLR2 0x0800
172 #define INT_CLR3 0x1000
173 #define INT_CLR4 0x2000
174 #define REGPAGE 0x4000
177 // External global variables
179 extern int start_logging
;
180 extern int gpu_start_log
;
182 // Private function prototypes
184 void GPUUpdateRegisterBanks(void);
185 void GPUDumpDisassembly(void);
186 void GPUDumpRegisters(void);
187 void GPUDumpMemory(void);
189 static void gpu_opcode_add(void);
190 static void gpu_opcode_addc(void);
191 static void gpu_opcode_addq(void);
192 static void gpu_opcode_addqt(void);
193 static void gpu_opcode_sub(void);
194 static void gpu_opcode_subc(void);
195 static void gpu_opcode_subq(void);
196 static void gpu_opcode_subqt(void);
197 static void gpu_opcode_neg(void);
198 static void gpu_opcode_and(void);
199 static void gpu_opcode_or(void);
200 static void gpu_opcode_xor(void);
201 static void gpu_opcode_not(void);
202 static void gpu_opcode_btst(void);
203 static void gpu_opcode_bset(void);
204 static void gpu_opcode_bclr(void);
205 static void gpu_opcode_mult(void);
206 static void gpu_opcode_imult(void);
207 static void gpu_opcode_imultn(void);
208 static void gpu_opcode_resmac(void);
209 static void gpu_opcode_imacn(void);
210 static void gpu_opcode_div(void);
211 static void gpu_opcode_abs(void);
212 static void gpu_opcode_sh(void);
213 static void gpu_opcode_shlq(void);
214 static void gpu_opcode_shrq(void);
215 static void gpu_opcode_sha(void);
216 static void gpu_opcode_sharq(void);
217 static void gpu_opcode_ror(void);
218 static void gpu_opcode_rorq(void);
219 static void gpu_opcode_cmp(void);
220 static void gpu_opcode_cmpq(void);
221 static void gpu_opcode_sat8(void);
222 static void gpu_opcode_sat16(void);
223 static void gpu_opcode_move(void);
224 static void gpu_opcode_moveq(void);
225 static void gpu_opcode_moveta(void);
226 static void gpu_opcode_movefa(void);
227 static void gpu_opcode_movei(void);
228 static void gpu_opcode_loadb(void);
229 static void gpu_opcode_loadw(void);
230 static void gpu_opcode_load(void);
231 static void gpu_opcode_loadp(void);
232 static void gpu_opcode_load_r14_indexed(void);
233 static void gpu_opcode_load_r15_indexed(void);
234 static void gpu_opcode_storeb(void);
235 static void gpu_opcode_storew(void);
236 static void gpu_opcode_store(void);
237 static void gpu_opcode_storep(void);
238 static void gpu_opcode_store_r14_indexed(void);
239 static void gpu_opcode_store_r15_indexed(void);
240 static void gpu_opcode_move_pc(void);
241 static void gpu_opcode_jump(void);
242 static void gpu_opcode_jr(void);
243 static void gpu_opcode_mmult(void);
244 static void gpu_opcode_mtoi(void);
245 static void gpu_opcode_normi(void);
246 static void gpu_opcode_nop(void);
247 static void gpu_opcode_load_r14_ri(void);
248 static void gpu_opcode_load_r15_ri(void);
249 static void gpu_opcode_store_r14_ri(void);
250 static void gpu_opcode_store_r15_ri(void);
251 static void gpu_opcode_sat24(void);
252 static void gpu_opcode_pack(void);
254 // This is wrong, since it doesn't take pipeline effects into account. !!! FIX !!!
255 /*uint8_t gpu_opcode_cycles[64] =
257 3, 3, 3, 3, 3, 3, 3, 3,
258 3, 3, 3, 3, 3, 3, 3, 3,
259 3, 3, 1, 3, 1, 18, 3, 3,
260 3, 3, 3, 3, 3, 3, 3, 3,
261 3, 3, 2, 2, 2, 2, 3, 4,
262 5, 4, 5, 6, 6, 1, 1, 1,
263 1, 2, 2, 2, 1, 1, 9, 3,
264 3, 1, 6, 6, 2, 2, 3, 3
266 //Here's a QnD kludge...
267 //This is wrong, wrong, WRONG, but it seems to work for the time being...
268 //(That is, it fixes Flip Out which relies on GPU timing rather than semaphores. Bad developers! Bad!)
269 //What's needed here is a way to take pipeline effects into account (including pipeline stalls!)...
270 /*uint8_t gpu_opcode_cycles[64] =
272 1, 1, 1, 1, 1, 1, 1, 1,
273 1, 1, 1, 1, 1, 1, 1, 1,
274 1, 1, 1, 1, 1, 9, 1, 1,
275 1, 1, 1, 1, 1, 1, 1, 1,
276 1, 1, 1, 1, 1, 1, 1, 2,
277 2, 2, 2, 3, 3, 1, 1, 1,
278 1, 1, 1, 1, 1, 1, 4, 1,
279 1, 1, 3, 3, 1, 1, 1, 1
281 uint8_t gpu_opcode_cycles
[64] =
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,
290 1, 1, 1, 1, 1, 1, 1, 1
293 void (*gpu_opcode
[64])()=
295 gpu_opcode_add
, gpu_opcode_addc
, gpu_opcode_addq
, gpu_opcode_addqt
,
296 gpu_opcode_sub
, gpu_opcode_subc
, gpu_opcode_subq
, gpu_opcode_subqt
,
297 gpu_opcode_neg
, gpu_opcode_and
, gpu_opcode_or
, gpu_opcode_xor
,
298 gpu_opcode_not
, gpu_opcode_btst
, gpu_opcode_bset
, gpu_opcode_bclr
,
299 gpu_opcode_mult
, gpu_opcode_imult
, gpu_opcode_imultn
, gpu_opcode_resmac
,
300 gpu_opcode_imacn
, gpu_opcode_div
, gpu_opcode_abs
, gpu_opcode_sh
,
301 gpu_opcode_shlq
, gpu_opcode_shrq
, gpu_opcode_sha
, gpu_opcode_sharq
,
302 gpu_opcode_ror
, gpu_opcode_rorq
, gpu_opcode_cmp
, gpu_opcode_cmpq
,
303 gpu_opcode_sat8
, gpu_opcode_sat16
, gpu_opcode_move
, gpu_opcode_moveq
,
304 gpu_opcode_moveta
, gpu_opcode_movefa
, gpu_opcode_movei
, gpu_opcode_loadb
,
305 gpu_opcode_loadw
, gpu_opcode_load
, gpu_opcode_loadp
, gpu_opcode_load_r14_indexed
,
306 gpu_opcode_load_r15_indexed
, gpu_opcode_storeb
, gpu_opcode_storew
, gpu_opcode_store
,
307 gpu_opcode_storep
, gpu_opcode_store_r14_indexed
, gpu_opcode_store_r15_indexed
, gpu_opcode_move_pc
,
308 gpu_opcode_jump
, gpu_opcode_jr
, gpu_opcode_mmult
, gpu_opcode_mtoi
,
309 gpu_opcode_normi
, gpu_opcode_nop
, gpu_opcode_load_r14_ri
, gpu_opcode_load_r15_ri
,
310 gpu_opcode_store_r14_ri
, gpu_opcode_store_r15_ri
, gpu_opcode_sat24
, gpu_opcode_pack
,
313 static uint8_t gpu_ram_8
[0x1000];
315 static uint32_t gpu_acc
;
316 static uint32_t gpu_remain
;
317 static uint32_t gpu_hidata
;
318 static uint32_t gpu_flags
;
319 static uint32_t gpu_matrix_control
;
320 static uint32_t gpu_pointer_to_matrix
;
321 static uint32_t gpu_data_organization
;
322 static uint32_t gpu_control
;
323 static uint32_t gpu_div_control
;
324 // There is a distinct advantage to having these separated out--there's no need
325 // to clear a bit before writing a result. I.e., if the result of an operation
326 // leaves a zero in the carry flag, you don't have to zero gpu_flag_c before
327 // you can write that zero!
328 static uint8_t gpu_flag_z
, gpu_flag_n
, gpu_flag_c
;
329 uint32_t gpu_reg_bank_0
[32];
330 uint32_t gpu_reg_bank_1
[32];
331 static uint32_t * gpu_reg
;
332 static uint32_t * gpu_alternate_reg
;
334 static uint32_t gpu_instruction
;
335 static uint32_t gpu_opcode_first_parameter
;
336 static uint32_t gpu_opcode_second_parameter
;
338 #define GPU_RUNNING (gpu_control & 0x01)
340 #define RM gpu_reg[gpu_opcode_first_parameter]
341 #define RN gpu_reg[gpu_opcode_second_parameter]
342 #define ALTERNATE_RM gpu_alternate_reg[gpu_opcode_first_parameter]
343 #define ALTERNATE_RN gpu_alternate_reg[gpu_opcode_second_parameter]
344 #define IMM_1 gpu_opcode_first_parameter
345 #define IMM_2 gpu_opcode_second_parameter
347 #define SET_FLAG_Z(r) (gpu_flag_z = ((r) == 0));
348 #define SET_FLAG_N(r) (gpu_flag_n = (((uint32_t)(r) >> 31) & 0x01));
350 #define RESET_FLAG_Z() gpu_flag_z = 0;
351 #define RESET_FLAG_N() gpu_flag_n = 0;
352 #define RESET_FLAG_C() gpu_flag_c = 0;
354 #define CLR_Z (gpu_flag_z = 0)
355 #define CLR_ZN (gpu_flag_z = gpu_flag_n = 0)
356 #define CLR_ZNC (gpu_flag_z = gpu_flag_n = gpu_flag_c = 0)
357 #define SET_Z(r) (gpu_flag_z = ((r) == 0))
358 #define SET_N(r) (gpu_flag_n = (((uint32_t)(r) >> 31) & 0x01))
359 #define SET_C_ADD(a,b) (gpu_flag_c = ((uint32_t)(b) > (uint32_t)(~(a))))
360 #define SET_C_SUB(a,b) (gpu_flag_c = ((uint32_t)(b) > (uint32_t)(a)))
361 #define SET_ZN(r) SET_N(r); SET_Z(r)
362 #define SET_ZNC_ADD(a,b,r) SET_N(r); SET_Z(r); SET_C_ADD(a,b)
363 #define SET_ZNC_SUB(a,b,r) SET_N(r); SET_Z(r); SET_C_SUB(a,b)
365 uint32_t gpu_convert_zero
[32] =
366 { 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 };
368 uint8_t * branch_condition_table
= 0;
369 #define BRANCH_CONDITION(x) branch_condition_table[(x) + ((jaguar_flags & 7) << 5)]
371 uint32_t gpu_opcode_use
[64];
373 const char * gpu_opcode_str
[64]=
375 "add", "addc", "addq", "addqt",
376 "sub", "subc", "subq", "subqt",
377 "neg", "and", "or", "xor",
378 "not", "btst", "bset", "bclr",
379 "mult", "imult", "imultn", "resmac",
380 "imacn", "div", "abs", "sh",
381 "shlq", "shrq", "sha", "sharq",
382 "ror", "rorq", "cmp", "cmpq",
383 "sat8", "sat16", "move", "moveq",
384 "moveta", "movefa", "movei", "loadb",
385 "loadw", "load", "loadp", "load_r14_indexed",
386 "load_r15_indexed", "storeb", "storew", "store",
387 "storep", "store_r14_indexed","store_r15_indexed","move_pc",
388 "jump", "jr", "mmult", "mtoi",
389 "normi", "nop", "load_r14_ri", "load_r15_ri",
390 "store_r14_ri", "store_r15_ri", "sat24", "pack",
393 static uint32_t gpu_in_exec
= 0;
394 static uint32_t gpu_releaseTimeSlice_flag
= 0;
396 void GPUReleaseTimeslice(void)
398 gpu_releaseTimeSlice_flag
= 1;
401 bool GPUIsRunning(void)
406 uint32_t GPUGetPC(void)
411 void build_branch_condition_table(void)
413 if (!branch_condition_table
)
415 branch_condition_table
= (uint8_t *)malloc(32 * 8 * sizeof(branch_condition_table
[0]));
417 if (branch_condition_table
)
419 for(int i
=0; i
<8; i
++)
421 for(int j
=0; j
<32; j
++)
428 if (!(i
& ZERO_FLAG
))
431 if (i
& (CARRY_FLAG
<< (j
>> 4)))
434 if (!(i
& (CARRY_FLAG
<< (j
>> 4))))
436 branch_condition_table
[i
* 32 + j
] = result
;
444 // GPU byte access (read)
446 uint8_t GPUReadByte(uint32_t offset
, uint32_t who
/*=UNKNOWN*/)
448 if (offset
>= 0xF02000 && offset
<= 0xF020FF)
449 WriteLog("GPU: ReadByte--Attempt to read from GPU register file by %s!\n", whoName
[who
]);
451 if ((offset
>= GPU_WORK_RAM_BASE
) && (offset
< GPU_WORK_RAM_BASE
+0x1000))
452 return gpu_ram_8
[offset
& 0xFFF];
453 else if ((offset
>= GPU_CONTROL_RAM_BASE
) && (offset
< GPU_CONTROL_RAM_BASE
+0x20))
455 uint32_t data
= GPUReadLong(offset
& 0xFFFFFFFC, who
);
457 if ((offset
& 0x03) == 0)
459 else if ((offset
& 0x03) == 1)
460 return (data
>> 16) & 0xFF;
461 else if ((offset
& 0x03) == 2)
462 return (data
>> 8) & 0xFF;
463 else if ((offset
& 0x03) == 3)
467 return JaguarReadByte(offset
, who
);
471 // GPU word access (read)
473 uint16_t GPUReadWord(uint32_t offset
, uint32_t who
/*=UNKNOWN*/)
475 if (offset
>= 0xF02000 && offset
<= 0xF020FF)
476 WriteLog("GPU: ReadWord--Attempt to read from GPU register file by %s!\n", whoName
[who
]);
478 if ((offset
>= GPU_WORK_RAM_BASE
) && (offset
< GPU_WORK_RAM_BASE
+0x1000))
481 uint16_t data
= ((uint16_t)gpu_ram_8
[offset
] << 8) | (uint16_t)gpu_ram_8
[offset
+1];
484 else if ((offset
>= GPU_CONTROL_RAM_BASE
) && (offset
< GPU_CONTROL_RAM_BASE
+0x20))
486 // This looks and smells wrong...
487 // But it *might* be OK...
488 if (offset
& 0x01) // Catch cases 1 & 3... (unaligned read)
489 return (GPUReadByte(offset
, who
) << 8) | GPUReadByte(offset
+1, who
);
491 uint32_t data
= GPUReadLong(offset
& 0xFFFFFFFC, who
);
493 if (offset
& 0x02) // Cases 0 & 2...
494 return data
& 0xFFFF;
499 //TEMP--Mirror of F03000? No. Writes only...
500 //if (offset >= 0xF0B000 && offset <= 0xF0BFFF)
501 //WriteLog("[GPUR16] --> Possible GPU RAM mirror access by %s!", whoName[who]);
503 return JaguarReadWord(offset
, who
);
507 // GPU dword access (read)
509 uint32_t GPUReadLong(uint32_t offset
, uint32_t who
/*=UNKNOWN*/)
511 if (offset
>= 0xF02000 && offset
<= 0xF020FF)
513 WriteLog("GPU: ReadLong--Attempt to read from GPU register file (%X) by %s!\n", offset
, whoName
[who
]);
514 uint32_t reg
= (offset
& 0xFC) >> 2;
515 return (reg
< 32 ? gpu_reg_bank_0
[reg
] : gpu_reg_bank_1
[reg
- 32]);
518 // if ((offset >= GPU_WORK_RAM_BASE) && (offset < GPU_WORK_RAM_BASE + 0x1000))
519 if ((offset
>= GPU_WORK_RAM_BASE
) && (offset
<= GPU_WORK_RAM_BASE
+ 0x0FFC))
522 return ((uint32_t)gpu_ram_8
[offset
] << 24) | ((uint32_t)gpu_ram_8
[offset
+1] << 16)
523 | ((uint32_t)gpu_ram_8
[offset
+2] << 8) | (uint32_t)gpu_ram_8
[offset
+3];//*/
524 // return GET32(gpu_ram_8, offset);
526 // else if ((offset >= GPU_CONTROL_RAM_BASE) && (offset < GPU_CONTROL_RAM_BASE+0x20))
527 else if ((offset
>= GPU_CONTROL_RAM_BASE
) && (offset
<= GPU_CONTROL_RAM_BASE
+ 0x1C))
533 gpu_flag_c
= (gpu_flag_c
? 1 : 0);
534 gpu_flag_z
= (gpu_flag_z
? 1 : 0);
535 gpu_flag_n
= (gpu_flag_n
? 1 : 0);
537 gpu_flags
= (gpu_flags
& 0xFFFFFFF8) | (gpu_flag_n
<< 2) | (gpu_flag_c
<< 1) | gpu_flag_z
;
539 return gpu_flags
& 0xFFFFC1FF;
541 return gpu_matrix_control
;
543 return gpu_pointer_to_matrix
;
545 return gpu_data_organization
;
554 default: // unaligned long read
556 WriteLog("GPU: Read32--unaligned 32 bit read at %08X by %s.\n", GPU_CONTROL_RAM_BASE
+ offset
, whoName
[who
]);
561 //TEMP--Mirror of F03000? No. Writes only...
562 //if (offset >= 0xF0B000 && offset <= 0xF0BFFF)
563 // WriteLog("[GPUR32] --> Possible GPU RAM mirror access by %s!\n", whoName[who]);
564 /*if (offset >= 0xF1D000 && offset <= 0xF1DFFF)
565 WriteLog("[GPUR32] --> Reading from Wavetable ROM!\n");//*/
567 return (JaguarReadWord(offset
, who
) << 16) | JaguarReadWord(offset
+ 2, who
);
571 // GPU byte access (write)
573 void GPUWriteByte(uint32_t offset
, uint8_t data
, uint32_t who
/*=UNKNOWN*/)
575 if (offset
>= 0xF02000 && offset
<= 0xF020FF)
576 WriteLog("GPU: WriteByte--Attempt to write to GPU register file by %s!\n", whoName
[who
]);
578 if ((offset
>= GPU_WORK_RAM_BASE
) && (offset
<= GPU_WORK_RAM_BASE
+ 0x0FFF))
580 gpu_ram_8
[offset
& 0xFFF] = data
;
582 //This is the same stupid worthless code that was in the DSP!!! AARRRGGGGHHHHH!!!!!!
585 m68k_end_timeslice();
586 dsp_releaseTimeslice();
590 else if ((offset
>= GPU_CONTROL_RAM_BASE
) && (offset
<= GPU_CONTROL_RAM_BASE
+ 0x1F))
592 uint32_t reg
= offset
& 0x1C;
593 int bytenum
= offset
& 0x03;
595 //This is definitely wrong!
596 if ((reg
>= 0x1C) && (reg
<= 0x1F))
597 gpu_div_control
= (gpu_div_control
& (~(0xFF << (bytenum
<< 3)))) | (data
<< (bytenum
<< 3));
600 uint32_t old_data
= GPUReadLong(offset
& 0xFFFFFFC, who
);
601 bytenum
= 3 - bytenum
; // convention motorola !!!
602 old_data
= (old_data
& (~(0xFF << (bytenum
<< 3)))) | (data
<< (bytenum
<< 3));
603 GPUWriteLong(offset
& 0xFFFFFFC, old_data
, who
);
607 // WriteLog("gpu: writing %.2x at 0x%.8x\n",data,offset);
608 JaguarWriteByte(offset
, data
, who
);
612 // GPU word access (write)
614 void GPUWriteWord(uint32_t offset
, uint16_t data
, uint32_t who
/*=UNKNOWN*/)
616 if (offset
>= 0xF02000 && offset
<= 0xF020FF)
617 WriteLog("GPU: WriteWord--Attempt to write to GPU register file by %s!\n", whoName
[who
]);
619 if ((offset
>= GPU_WORK_RAM_BASE
) && (offset
<= GPU_WORK_RAM_BASE
+ 0x0FFE))
621 gpu_ram_8
[offset
& 0xFFF] = (data
>>8) & 0xFF;
622 gpu_ram_8
[(offset
+1) & 0xFFF] = data
& 0xFF;//*/
624 SET16(gpu_ram_8, offset, data);//*/
626 /*if (offset >= 0xF03214 && offset < 0xF0321F)
627 WriteLog("GPU: Writing WORD (%04X) to GPU RAM (%08X)...\n", data, offset);//*/
630 //This is the same stupid worthless code that was in the DSP!!! AARRRGGGGHHHHH!!!!!!
633 m68k_end_timeslice();
634 dsp_releaseTimeslice();
638 else if ((offset
>= GPU_CONTROL_RAM_BASE
) && (offset
<= GPU_CONTROL_RAM_BASE
+ 0x1E))
640 if (offset
& 0x01) // This is supposed to weed out unaligned writes, but does nothing...
643 WriteLog("GPU: Write16--unaligned write @ %08X [%04X]\n", offset
, data
);
648 //Dual locations in this range: $1C Divide unit remainder/Divide unit control (R/W)
649 //This just literally sucks.
650 if ((offset
& 0x1C) == 0x1C)
652 //This doesn't look right either--handles cases 1, 2, & 3 all the same!
654 gpu_div_control
= (gpu_div_control
& 0xFFFF0000) | (data
& 0xFFFF);
656 gpu_div_control
= (gpu_div_control
& 0x0000FFFF) | ((data
& 0xFFFF) << 16);
660 //WriteLog("[GPU W16:%08X,%04X]", offset, data);
661 uint32_t old_data
= GPUReadLong(offset
& 0xFFFFFFC, who
);
664 old_data
= (old_data
& 0xFFFF0000) | (data
& 0xFFFF);
666 old_data
= (old_data
& 0x0000FFFF) | ((data
& 0xFFFF) << 16);
668 GPUWriteLong(offset
& 0xFFFFFFC, old_data
, who
);
673 else if ((offset
== GPU_WORK_RAM_BASE
+ 0x0FFF) || (GPU_CONTROL_RAM_BASE
+ 0x1F))
676 WriteLog("GPU: Write16--unaligned write @ %08X by %s [%04X]!\n", offset
, whoName
[who
], data
);
682 // Have to be careful here--this can cause an infinite loop!
683 JaguarWriteWord(offset
, data
, who
);
687 // GPU dword access (write)
689 void GPUWriteLong(uint32_t offset
, uint32_t data
, uint32_t who
/*=UNKNOWN*/)
691 if (offset
>= 0xF02000 && offset
<= 0xF020FF)
692 WriteLog("GPU: WriteLong--Attempt to write to GPU register file by %s!\n", whoName
[who
]);
694 // if ((offset >= GPU_WORK_RAM_BASE) && (offset < GPU_WORK_RAM_BASE + 0x1000))
695 if ((offset
>= GPU_WORK_RAM_BASE
) && (offset
<= GPU_WORK_RAM_BASE
+ 0x0FFC))
700 WriteLog("GPU: Write32--unaligned write @ %08X [%08X] by %s\n", offset
, data
, whoName
[who
]);
706 SET32(gpu_ram_8
, offset
, data
);
709 // else if ((offset >= GPU_CONTROL_RAM_BASE) && (offset < GPU_CONTROL_RAM_BASE+0x20))
710 else if ((offset
>= GPU_CONTROL_RAM_BASE
) && (offset
<= GPU_CONTROL_RAM_BASE
+ 0x1C))
717 bool IMASKCleared
= (gpu_flags
& IMASK
) && !(data
& IMASK
);
718 // NOTE: According to the JTRM, writing a 1 to IMASK has no effect; only the
719 // IRQ logic can set it. So we mask it out here to prevent problems...
720 gpu_flags
= data
& (~IMASK
);
721 gpu_flag_z
= gpu_flags
& ZERO_FLAG
;
722 gpu_flag_c
= (gpu_flags
& CARRY_FLAG
) >> 1;
723 gpu_flag_n
= (gpu_flags
& NEGA_FLAG
) >> 2;
724 GPUUpdateRegisterBanks();
725 gpu_control
&= ~((gpu_flags
& CINT04FLAGS
) >> 3); // Interrupt latch clear bits
726 //Writing here is only an interrupt enable--this approach is just plain wrong!
728 //This, however, is A-OK! ;-)
729 if (IMASKCleared
) // If IMASK was cleared,
730 GPUHandleIRQs(); // see if any other interrupts need servicing!
732 if (gpu_flags
& (INT_ENA0
| INT_ENA1
| INT_ENA2
| INT_ENA3
| INT_ENA4
))
733 WriteLog("GPU: Interrupt enable set by %s! Bits: %02X\n", whoName
[who
], (gpu_flags
>> 4) & 0x1F);
734 WriteLog("GPU: REGPAGE %s...\n", (gpu_flags
& REGPAGE
? "set" : "cleared"));
739 gpu_matrix_control
= data
;
742 // This can only point to long aligned addresses
743 gpu_pointer_to_matrix
= data
& 0xFFFFFFFC;
746 gpu_data_organization
= data
;
751 WriteLog("GPU: %s setting GPU PC to %08X %s\n", whoName
[who
], gpu_pc
, (GPU_RUNNING
? "(GPU is RUNNING!)" : ""));//*/
756 // uint32_t gpu_was_running = GPU_RUNNING;
757 data
&= ~0xF7C0; // Disable writes to INT_LAT0-4 & TOM version number
759 // check for GPU -> CPU interrupt
762 //WriteLog("GPU->CPU interrupt\n");
763 if (TOMIRQEnabled(IRQ_GPU
))
765 //This is the programmer's responsibility, to make sure the handler is valid, not ours!
766 // if ((TOMIRQEnabled(IRQ_GPU))// && (JaguarInterruptHandlerIsValid(64)))
768 TOMSetPendingGPUInt();
769 m68k_set_irq(2); // Set 68000 IPL 2
770 GPUReleaseTimeslice();
776 // check for CPU -> GPU interrupt #0
779 //WriteLog("CPU->GPU interrupt\n");
780 GPUSetIRQLine(0, ASSERT_LINE
);
781 m68k_end_timeslice();
782 DSPReleaseTimeslice();
789 //WriteLog("asked to perform a single step (single step is %senabled)\n",(data&0x8)?"":"not ");
792 gpu_control
= (gpu_control
& 0xF7C0) | (data
& (~0xF7C0));
794 // if gpu wasn't running but is now running, execute a few cycles
795 #ifndef GPU_SINGLE_STEPPING
796 /* if (!gpu_was_running && GPU_RUNNING)
799 WriteLog("GPU: Write32--About to do stupid braindead GPU execution for 200 cycles.\n");
804 #endif // GPU_DEBUG//*/
806 if (gpu_control
& 0x18)
808 #endif // #ifndef GPU_SINGLE_STEPPING
810 WriteLog("Write to GPU CTRL by %s: %08X ", whoName
[who
], data
);
812 WriteLog(" --> Starting to run at %08X by %s...", gpu_pc
, whoName
[who
]);
814 WriteLog(" --> Stopped by %s! (GPU_PC: %08X)", whoName
[who
], gpu_pc
);
818 // GPUDumpDisassembly();
821 if (gpu_pc == 0xF035D8)
823 // GPUDumpDisassembly();
826 gpu_control &= 0xFFFFFFFE; // Don't run it and let's see what happens!
827 //Hmm. Seems to lock up when going into the demo...
828 //Try to disable the collision altogether!
831 extern int effect_start5
;
832 static bool finished
= false;
833 //if (GPU_RUNNING && effect_start5 && !finished)
834 if (GPU_RUNNING
&& effect_start5
&& gpu_pc
== 0xF035D8)
836 // Let's do a dump of $6528!
837 /* uint32_t numItems = JaguarReadWord(0x6BD6);
838 WriteLog("\nDump of $6528: %u items.\n\n", numItems);
839 for(int i=0; i<numItems*3*4; i+=3*4)
841 WriteLog("\t%04X: %08X %08X %08X -> ", 0x6528+i, JaguarReadLong(0x6528+i),
842 JaguarReadLong(0x6528+i+4), JaguarReadLong(0x6528+i+8));
843 uint16_t link = JaguarReadWord(0x6528+i+8+2);
844 for(int j=0; j<40; j+=4)
845 WriteLog("%08X ", JaguarReadLong(link + j));
849 // Let's try a manual blit here...
850 //This isn't working the way it should! !!! FIX !!!
851 //Err, actually, it is.
852 // NOW, it works right! Problem solved!!! It's a blitter bug!
853 /* uint32_t src = 0x4D54, dst = 0xF03000, width = 10 * 4;
854 for(int y=0; y<127; y++)
856 for(int x=0; x<2; x++)
858 JaguarWriteLong(dst, JaguarReadLong(src));
863 src += width - (2 * 4);
867 WriteLog("\nGPU: About to execute collision detection code.\n\n");//*/
869 /* WriteLog("\nGPU: About to execute collision detection code. Data @ 4D54:\n\n");
871 for(int i=0x004D54; i<0x004D54+2048; i++)
873 WriteLog("%02X ", JaguarReadByte(i));
881 WriteLog("\n\nData @ F03000:\n\n");
883 for(int i=0xF03000; i<0xF03200; i++)
885 WriteLog("%02X ", JaguarReadByte(i));
899 /*if (!GPU_RUNNING && finished)
901 WriteLog("\nGPU: Finished collision detection code. Exiting!\n\n");
906 // (?) If we're set running by the M68K (or DSP?) then end its timeslice to
907 // allow the GPU a chance to run...
908 // Yes! This partially fixed Trevor McFur...
910 m68k_end_timeslice();
917 gpu_div_control
= data
;
919 // default: // unaligned long write
926 // JaguarWriteWord(offset, (data >> 16) & 0xFFFF, who);
927 // JaguarWriteWord(offset+2, data & 0xFFFF, who);
928 // We're a 32-bit processor, we can do a long write...!
929 JaguarWriteLong(offset
, data
, who
);
933 // Change register banks if necessary
935 void GPUUpdateRegisterBanks(void)
937 int bank
= (gpu_flags
& REGPAGE
); // REGPAGE bit
939 if (gpu_flags
& IMASK
) // IMASK bit
940 bank
= 0; // IMASK forces main bank to be bank 0
943 gpu_reg
= gpu_reg_bank_1
, gpu_alternate_reg
= gpu_reg_bank_0
;
945 gpu_reg
= gpu_reg_bank_0
, gpu_alternate_reg
= gpu_reg_bank_1
;
948 void GPUHandleIRQs(void)
950 // Bail out if we're already in an interrupt!
951 if (gpu_flags
& IMASK
)
954 // Get the interrupt latch & enable bits
955 uint32_t bits
= (gpu_control
>> 6) & 0x1F, mask
= (gpu_flags
>> 4) & 0x1F;
957 // Bail out if latched interrupts aren't enabled
962 // Determine which interrupt to service
963 uint32_t which
= 0; //Isn't there a #pragma to disable this warning???
976 WriteLog("GPU: Generating IRQ #%i\n", which
);
978 // set the interrupt flag
980 GPUUpdateRegisterBanks();
982 // subqt #4,r31 ; pre-decrement stack pointer
983 // move pc,r30 ; address of interrupted code
984 // store r30,(r31) ; store return address
986 GPUWriteLong(gpu_reg
[31], gpu_pc
- 2, GPU
);
988 // movei #service_address,r30 ; pointer to ISR entry
989 // jump (r30) ; jump to ISR
991 gpu_pc
= gpu_reg
[30] = GPU_WORK_RAM_BASE
+ (which
* 0x10);
994 void GPUSetIRQLine(int irqline
, int state
)
997 WriteLog("GPU: Setting GPU IRQ line #%i\n", irqline
);
999 uint32_t mask
= 0x0040 << irqline
;
1000 gpu_control
&= ~mask
; // Clear the interrupt latch
1004 gpu_control
|= mask
; // Assert the interrupt latch
1005 GPUHandleIRQs(); // And handle the interrupt...
1009 //TEMPORARY: Testing only!
1015 // memory_malloc_secure((void **)&gpu_ram_8, 0x1000, "GPU work RAM");
1016 // memory_malloc_secure((void **)&gpu_reg_bank_0, 32 * sizeof(int32_t), "GPU bank 0 regs");
1017 // memory_malloc_secure((void **)&gpu_reg_bank_1, 32 * sizeof(int32_t), "GPU bank 1 regs");
1019 build_branch_condition_table();
1023 //TEMPORARY: Testing only!
1030 // GPU registers (directly visible)
1031 gpu_flags
= 0x00000000;
1032 gpu_matrix_control
= 0x00000000;
1033 gpu_pointer_to_matrix
= 0x00000000;
1034 gpu_data_organization
= 0xFFFFFFFF;
1035 gpu_pc
= 0x00F03000;
1036 gpu_control
= 0x00002800; // Correctly sets this as TOM Rev. 2
1037 gpu_hidata
= 0x00000000;
1038 gpu_remain
= 0x00000000; // These two registers are RO/WO
1039 gpu_div_control
= 0x00000000;
1041 // GPU internal register
1042 gpu_acc
= 0x00000000;
1044 gpu_reg
= gpu_reg_bank_0
;
1045 gpu_alternate_reg
= gpu_reg_bank_1
;
1047 for(int i
=0; i
<32; i
++)
1048 gpu_reg
[i
] = gpu_alternate_reg
[i
] = 0x00000000;
1051 memset(gpu_ram_8
, 0xFF, 0x1000);
1053 //not needed GPUInterruptPending = false;
1056 // Contents of local RAM are quasi-stable; we simulate this by randomizing RAM contents
1057 for(uint32_t i
=0; i
<4096; i
+=4)
1058 *((uint32_t *)(&gpu_ram_8
[i
])) = rand();
1062 uint32_t GPUReadPC(void)
1068 void GPUResetStats(void)
1070 for(uint32_t i
=0; i
<64; i
++)
1071 gpu_opcode_use
[i
] = 0;
1072 WriteLog("--> GPU stats were reset!\n");
1076 void GPUDumpDisassembly(void)
1080 WriteLog("\n---[GPU code at 00F03000]---------------------------\n");
1081 uint32_t j
= 0xF03000;
1082 while (j
<= 0xF03FFF)
1085 j
+= dasmjag(JAGUAR_GPU
, buffer
, j
);
1086 WriteLog("\t%08X: %s\n", oldj
, buffer
);
1091 void GPUDumpRegisters(void)
1093 WriteLog("\n---[GPU flags: NCZ %d%d%d]-----------------------\n", gpu_flag_n
, gpu_flag_c
, gpu_flag_z
);
1094 WriteLog("\nRegisters bank 0\n");
1095 for(int j
=0; j
<8; j
++)
1097 WriteLog("\tR%02i = %08X R%02i = %08X R%02i = %08X R%02i = %08X\n",
1098 (j
<< 2) + 0, gpu_reg_bank_0
[(j
<< 2) + 0],
1099 (j
<< 2) + 1, gpu_reg_bank_0
[(j
<< 2) + 1],
1100 (j
<< 2) + 2, gpu_reg_bank_0
[(j
<< 2) + 2],
1101 (j
<< 2) + 3, gpu_reg_bank_0
[(j
<< 2) + 3]);
1103 WriteLog("Registers bank 1\n");
1104 for(int j
=0; j
<8; j
++)
1106 WriteLog("\tR%02i = %08X R%02i = %08X R%02i = %08X R%02i = %08X\n",
1107 (j
<< 2) + 0, gpu_reg_bank_1
[(j
<< 2) + 0],
1108 (j
<< 2) + 1, gpu_reg_bank_1
[(j
<< 2) + 1],
1109 (j
<< 2) + 2, gpu_reg_bank_1
[(j
<< 2) + 2],
1110 (j
<< 2) + 3, gpu_reg_bank_1
[(j
<< 2) + 3]);
1115 void GPUDumpMemory(void)
1117 WriteLog("\n---[GPU data at 00F03000]---------------------------\n");
1118 for(int i
=0; i
<0xFFF; i
+=4)
1119 WriteLog("\t%08X: %02X %02X %02X %02X\n", 0xF03000+i
, gpu_ram_8
[i
],
1120 gpu_ram_8
[i
+1], gpu_ram_8
[i
+2], gpu_ram_8
[i
+3]);
1126 WriteLog("\n\n---------------------------------------------------------------------\n");
1127 WriteLog("GPU I/O Registers\n");
1128 WriteLog("---------------------------------------------------------------------\n");
1129 WriteLog("F0%04X (G_FLAGS): $%06X\n", 0x2100, (gpu_flags
& 0xFFFFFFF8) | (gpu_flag_n
<< 2) | (gpu_flag_c
<< 1) | gpu_flag_z
);
1130 WriteLog("F0%04X (G_MTXC): $%04X\n", 0x2104, gpu_matrix_control
);
1131 WriteLog("F0%04X (G_MTXA): $%04X\n", 0x2108, gpu_pointer_to_matrix
);
1132 WriteLog("F0%04X (G_END): $%02X\n", 0x210C, gpu_data_organization
);
1133 WriteLog("F0%04X (G_PC): $%06X\n", 0x2110, gpu_pc
);
1134 WriteLog("F0%04X (G_CTRL): $%06X\n", 0x2114, gpu_control
);
1135 WriteLog("F0%04X (G_HIDATA): $%08X\n", 0x2118, gpu_hidata
);
1136 WriteLog("F0%04X (G_REMAIN): $%08X\n", 0x211C, gpu_remain
);
1137 WriteLog("F0%04X (G_DIVCTRL): $%02X\n", 0x211C, gpu_div_control
);
1138 WriteLog("---------------------------------------------------------------------\n\n\n");
1140 WriteLog("GPU: Stopped at PC=%08X (GPU %s running)\n", (unsigned int)gpu_pc
, GPU_RUNNING
? "was" : "wasn't");
1142 // Get the interrupt latch & enable bits
1143 uint8_t bits
= (gpu_control
>> 6) & 0x1F, mask
= (gpu_flags
>> 4) & 0x1F;
1144 WriteLog("GPU: Latch bits = %02X, enable bits = %02X\n", bits
, mask
);
1147 GPUDumpDisassembly();
1149 WriteLog("\nGPU opcodes use:\n");
1150 for(int i
=0; i
<64; i
++)
1152 if (gpu_opcode_use
[i
])
1153 WriteLog("\t%17s %lu\n", gpu_opcode_str
[i
], gpu_opcode_use
[i
]);
1160 // Main GPU execution core
1162 static int testCount
= 1;
1164 static bool tripwire
= false;
1165 void GPUExec(int32_t cycles
)
1170 #ifdef GPU_SINGLE_STEPPING
1171 if (gpu_control
& 0x18)
1174 gpu_control
&= ~0x10;
1178 gpu_releaseTimeSlice_flag
= 0;
1181 while (cycles
> 0 && GPU_RUNNING
)
1183 if (gpu_ram_8
[0x054] == 0x98 && gpu_ram_8
[0x055] == 0x0A && gpu_ram_8
[0x056] == 0x03
1184 && gpu_ram_8
[0x057] == 0x00 && gpu_ram_8
[0x058] == 0x00 && gpu_ram_8
[0x059] == 0x00)
1186 if (gpu_pc
== 0xF03000)
1188 extern uint32_t starCount
;
1190 /* WriteLog("GPU: Starting starfield generator... Dump of [R03=%08X]:\n", gpu_reg_bank_0[03]);
1191 uint32_t base = gpu_reg_bank_0[3];
1192 for(uint32_t i=0; i<0x100; i+=16)
1194 WriteLog("%02X: ", i);
1195 for(uint32_t j=0; j<16; j++)
1197 WriteLog("%02X ", JaguarReadByte(base + i + j));
1202 // if (gpu_pc == 0xF03)
1206 /*if (gpu_pc == 0xF03B9E && gpu_reg_bank_0[01] == 0)
1209 WriteLog("GPU: Starting disassembly log...\n");
1212 /*if (gpu_pc == 0xF0359A)
1217 /* gpu_flag_c = (gpu_flag_c ? 1 : 0);
1218 gpu_flag_z = (gpu_flag_z ? 1 : 0);
1219 gpu_flag_n = (gpu_flag_n ? 1 : 0);*/
1221 if (gpu_pc
== 0xF03200)
1225 uint16_t opcode
= GPUReadWord(gpu_pc
, GPU
);
1226 uint32_t index
= opcode
>> 10;
1227 gpu_instruction
= opcode
; // Added for GPU #3...
1228 gpu_opcode_first_parameter
= (opcode
>> 5) & 0x1F;
1229 gpu_opcode_second_parameter
= opcode
& 0x1F;
1230 /*if (gpu_pc == 0xF03BE8)
1231 WriteLog("Start of OP frame write...\n");
1232 if (gpu_pc == 0xF03EEE)
1233 WriteLog("--> Writing BRANCH object ---\n");
1234 if (gpu_pc == 0xF03F62)
1235 WriteLog("--> Writing BITMAP object ***\n");//*/
1236 /*if (gpu_pc == 0xF03546)
1238 WriteLog("\n--> GPU PC: F03546\n");
1240 GPUDumpDisassembly();
1242 /*if (gpu_pc == 0xF033F6)
1244 WriteLog("\n--> GPU PC: F033F6\n");
1246 GPUDumpDisassembly();
1248 /*if (gpu_pc == 0xF033CC)
1250 WriteLog("\n--> GPU PC: F033CC\n");
1252 GPUDumpDisassembly();
1254 /*if (gpu_pc == 0xF033D6)
1256 WriteLog("\n--> GPU PC: F033D6 (#%d)\n", testCount++);
1260 /*if (gpu_pc == 0xF033D8)
1262 WriteLog("\n--> GPU PC: F033D8 (#%d)\n", testCount++);
1266 /*if (gpu_pc == 0xF0358E)
1268 WriteLog("\n--> GPU PC: F0358E (#%d)\n", testCount++);
1272 /*if (gpu_pc == 0xF034CA)
1274 WriteLog("\n--> GPU PC: F034CA (#%d)\n", testCount++);
1277 /*if (gpu_pc == 0xF034CA)
1279 len = gpu_reg[1] + 4;//, r9save = gpu_reg[9];
1280 WriteLog("\nAbout to subtract [#%d] (R14=%08X, R15=%08X, R9=%08X):\n ", testCount++, gpu_reg[14], gpu_reg[15], gpu_reg[9]);
1281 for(int i=0; i<len; i+=4)
1282 WriteLog(" %08X", GPUReadLong(gpu_reg[15]+i));
1284 for(int i=0; i<len; i+=4)
1285 WriteLog(" %08X", GPUReadLong(gpu_reg[14]+i));
1288 if (gpu_pc == 0xF034DE)
1290 WriteLog("\nSubtracted! (R14=%08X, R15=%08X):\n ", gpu_reg[14], gpu_reg[15]);
1291 for(int i=0; i<len; i+=4)
1292 WriteLog(" %08X", GPUReadLong(gpu_reg[15]+i));
1294 for(int i=0; i<len; i+=4)
1295 WriteLog(" %08X", GPUReadLong(gpu_reg[14]+i));
1297 for(int i=0; i<len; i+=4)
1298 WriteLog(" --------");
1300 for(int i=0; i<len; i+=4)
1301 WriteLog(" %08X", GPUReadLong(gpu_reg[9]+4+i));
1304 /*if (gpu_pc == 0xF035C8)
1306 WriteLog("\n--> GPU PC: F035C8 (#%d)\n", testCount++);
1308 GPUDumpDisassembly();
1313 // gpu_reset_stats();
1314 static char buffer
[512];
1315 dasmjag(JAGUAR_GPU
, buffer
, gpu_pc
);
1316 WriteLog("GPU: [%08X] %s (RM=%08X, RN=%08X) -> ", gpu_pc
, buffer
, RM
, RN
);
1318 //$E400 -> 1110 01 -> $39 -> 57
1321 gpu_opcode
[index
]();
1323 // gpu2_opcode[index]();
1325 //GPU #3 (Doesn't show ATARI logo! #1 & #2 do...)
1327 // gpu3_opcode[index]();
1330 //GPU: [00F03548] jr nz,00F03560 (0xd561) (RM=00F03114, RN=00000004) -> --> JR: Branch taken.
1331 /*static bool firstTime = true;
1332 if (gpu_pc == 0xF03548 && firstTime)
1335 // firstTime = false;
1337 //static char buffer[512];
1339 //while (k<0xF0356C)
1342 //k += dasmjag(JAGUAR_GPU, buffer, k);
1343 //WriteLog("GPU: [%08X] %s\n", oldk, buffer);
1345 // gpu_start_log = 1;
1347 //GPU: [00F0354C] jump nz,(r29) (0xd3a1) (RM=00F03314, RN=00000004) -> (RM=00F03314, RN=00000004)
1348 /*if (gpu_pc == 0xF0354C)
1349 gpu_flag_z = 0;//, gpu_start_log = 1;//*/
1351 cycles
-= gpu_opcode_cycles
[index
];
1352 gpu_opcode_use
[index
]++;
1354 WriteLog("(RM=%08X, RN=%08X)\n", RM
, RN
);//*/
1355 if ((gpu_pc
< 0xF03000 || gpu_pc
> 0xF03FFF) && !tripwire
)
1357 WriteLog("GPU: Executing outside local RAM! GPU_PC: %08X\n", gpu_pc
);
1370 GPU opcodes use (offset punch--vertically below bad guy):
1392 load_r14_indexed 1183
1393 load_r15_indexed 1125
1396 store_r14_indexed 320
1405 static void gpu_opcode_jump(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: 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
);
1417 /* gpu_flag_c = (gpu_flag_c ? 1 : 0);
1418 gpu_flag_z = (gpu_flag_z ? 1 : 0);
1419 gpu_flag_n = (gpu_flag_n ? 1 : 0);*/
1420 // KLUDGE: Used by BRANCH_CONDITION
1421 uint32_t jaguar_flags
= (gpu_flag_n
<< 2) | (gpu_flag_c
<< 1) | gpu_flag_z
;
1423 if (BRANCH_CONDITION(IMM_2
))
1427 WriteLog("Branched!\n");
1430 WriteLog(" --> JUMP: Branch taken.\n");
1431 uint32_t delayed_pc
= RM
;
1433 gpu_pc
= delayed_pc
;
1434 /* uint16_t opcode = GPUReadWord(gpu_pc, GPU);
1435 gpu_opcode_first_parameter = (opcode >> 5) & 0x1F;
1436 gpu_opcode_second_parameter = opcode & 0x1F;
1438 gpu_pc = delayed_pc;
1439 gpu_opcode[opcode>>10]();//*/
1444 WriteLog("Branch NOT taken.\n");
1449 static void gpu_opcode_jr(void)
1452 const char * condition
[32] =
1453 { "T", "nz", "z", "???", "nc", "nc nz", "nc z", "???", "c", "c nz",
1454 "c z", "???", "???", "???", "???", "???", "???", "???", "???",
1455 "???", "nn", "nn nz", "nn z", "???", "n", "n nz", "n z", "???",
1456 "???", "???", "???", "F" };
1458 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
);
1460 /* if (CONDITION(jaguar.op & 31))
1462 int32_t r1 = (INT8)((jaguar.op >> 2) & 0xF8) >> 2;
1463 uint32_t newpc = jaguar.PC + r1;
1465 jaguar.op = ROPCODE(jaguar.PC);
1467 (*jaguar.table[jaguar.op >> 10])();
1469 jaguar_icount -= 3; // 3 wait states guaranteed
1472 /* gpu_flag_n = (gpu_flag_n ? 1 : 0);
1473 gpu_flag_c = (gpu_flag_c ? 1 : 0);
1474 gpu_flag_z = (gpu_flag_z ? 1 : 0);*/
1475 // KLUDGE: Used by BRANCH_CONDITION
1476 uint32_t jaguar_flags
= (gpu_flag_n
<< 2) | (gpu_flag_c
<< 1) | gpu_flag_z
;
1478 if (BRANCH_CONDITION(IMM_2
))
1482 WriteLog("Branched!\n");
1485 WriteLog(" --> JR: Branch taken.\n");
1486 int32_t offset
= (IMM_1
& 0x10 ? 0xFFFFFFF0 | IMM_1
: IMM_1
); // Sign extend IMM_1
1487 int32_t delayed_pc
= gpu_pc
+ (offset
* 2);
1489 gpu_pc
= delayed_pc
;
1490 /* uint16_t opcode = GPUReadWord(gpu_pc, GPU);
1491 gpu_opcode_first_parameter = (opcode >> 5) & 0x1F;
1492 gpu_opcode_second_parameter = opcode & 0x1F;
1494 gpu_pc = delayed_pc;
1495 gpu_opcode[opcode>>10]();//*/
1500 WriteLog("Branch NOT taken.\n");
1505 static void gpu_opcode_add(void)
1509 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
);
1511 uint32_t res
= RN
+ RM
;
1512 CLR_ZNC
; SET_ZNC_ADD(RN
, RM
, res
);
1516 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
);
1521 static void gpu_opcode_addc(void)
1525 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
);
1527 /* int dreg = jaguar.op & 31;
1528 uint32_t r1 = jaguar.r[(jaguar.op >> 5) & 31];
1529 uint32_t r2 = jaguar.r[dreg];
1530 uint32_t res = r2 + r1 + ((jaguar.FLAGS >> 1) & 1);
1531 jaguar.r[dreg] = res;
1532 CLR_ZNC; SET_ZNC_ADD(r2,r1,res);*/
1534 uint32_t res
= RN
+ RM
+ gpu_flag_c
;
1535 uint32_t carry
= gpu_flag_c
;
1536 // SET_ZNC_ADD(RN, RM, res); //???BUG??? Yes!
1537 SET_ZNC_ADD(RN
+ carry
, RM
, res
);
1538 // SET_ZNC_ADD(RN, RM + carry, res);
1542 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
);
1547 static void gpu_opcode_addq(void)
1551 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
);
1553 uint32_t r1
= gpu_convert_zero
[IMM_1
];
1554 uint32_t res
= RN
+ r1
;
1555 CLR_ZNC
; SET_ZNC_ADD(RN
, r1
, res
);
1559 WriteLog("[NCZ:%u%u%u, R%02u=%08X]\n", gpu_flag_n
, gpu_flag_c
, gpu_flag_z
, IMM_2
, RN
);
1564 static void gpu_opcode_addqt(void)
1566 #ifdef GPU_DIS_ADDQT
1568 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
);
1570 RN
+= gpu_convert_zero
[IMM_1
];
1571 #ifdef GPU_DIS_ADDQT
1573 WriteLog("[NCZ:%u%u%u, R%02u=%08X]\n", gpu_flag_n
, gpu_flag_c
, gpu_flag_z
, IMM_2
, RN
);
1578 static void gpu_opcode_sub(void)
1582 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
);
1584 uint32_t res
= RN
- RM
;
1585 SET_ZNC_SUB(RN
, RM
, res
);
1589 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
);
1594 static void gpu_opcode_subc(void)
1598 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
);
1600 // This is how the GPU ALU does it--Two's complement with inverted carry
1601 uint64_t res
= (uint64_t)RN
+ (uint64_t)(RM
^ 0xFFFFFFFF) + (gpu_flag_c
^ 1);
1602 // Carry out of the result is inverted too
1603 gpu_flag_c
= ((res
>> 32) & 0x01) ^ 1;
1604 RN
= (res
& 0xFFFFFFFF);
1608 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
);
1613 static void gpu_opcode_subq(void)
1617 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
);
1619 uint32_t r1
= gpu_convert_zero
[IMM_1
];
1620 uint32_t res
= RN
- r1
;
1621 SET_ZNC_SUB(RN
, r1
, res
);
1625 WriteLog("[NCZ:%u%u%u, R%02u=%08X]\n", gpu_flag_n
, gpu_flag_c
, gpu_flag_z
, IMM_2
, RN
);
1630 static void gpu_opcode_subqt(void)
1632 #ifdef GPU_DIS_SUBQT
1634 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
);
1636 RN
-= gpu_convert_zero
[IMM_1
];
1637 #ifdef GPU_DIS_SUBQT
1639 WriteLog("[NCZ:%u%u%u, R%02u=%08X]\n", gpu_flag_n
, gpu_flag_c
, gpu_flag_z
, IMM_2
, RN
);
1644 static void gpu_opcode_cmp(void)
1648 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
);
1650 uint32_t res
= RN
- RM
;
1651 SET_ZNC_SUB(RN
, RM
, res
);
1654 WriteLog("[NCZ:%u%u%u]\n", gpu_flag_n
, gpu_flag_c
, gpu_flag_z
);
1659 static void gpu_opcode_cmpq(void)
1661 static int32_t sqtable
[32] =
1662 { 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 };
1665 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
);
1667 uint32_t r1
= sqtable
[IMM_1
& 0x1F]; // I like this better -> (INT8)(jaguar.op >> 2) >> 3;
1668 uint32_t res
= RN
- r1
;
1669 SET_ZNC_SUB(RN
, r1
, res
);
1672 WriteLog("[NCZ:%u%u%u]\n", gpu_flag_n
, gpu_flag_c
, gpu_flag_z
);
1677 static void gpu_opcode_and(void)
1681 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
);
1687 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
);
1692 static void gpu_opcode_or(void)
1696 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
);
1702 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
);
1707 static void gpu_opcode_xor(void)
1711 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
);
1717 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
);
1722 static void gpu_opcode_not(void)
1726 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
);
1732 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
);
1737 static void gpu_opcode_move_pc(void)
1739 #ifdef GPU_DIS_MOVEPC
1741 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
);
1743 // Should be previous PC--this might not always be previous instruction!
1744 // Then again, this will point right at the *current* instruction, i.e., MOVE PC,R!
1746 #ifdef GPU_DIS_MOVEPC
1748 WriteLog("[NCZ:%u%u%u, R%02u=%08X]\n", gpu_flag_n
, gpu_flag_c
, gpu_flag_z
, IMM_2
, RN
);
1753 static void gpu_opcode_sat8(void)
1757 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
);
1759 RN
= ((int32_t)RN
< 0 ? 0 : (RN
> 0xFF ? 0xFF : RN
));
1763 WriteLog("[NCZ:%u%u%u, R%02u=%08X]\n", gpu_flag_n
, gpu_flag_c
, gpu_flag_z
, IMM_2
, RN
);
1768 static void gpu_opcode_sat16(void)
1770 RN
= ((int32_t)RN
< 0 ? 0 : (RN
> 0xFFFF ? 0xFFFF : RN
));
1774 static void gpu_opcode_sat24(void)
1776 RN
= ((int32_t)RN
< 0 ? 0 : (RN
> 0xFFFFFF ? 0xFFFFFF : RN
));
1781 static void gpu_opcode_store_r14_indexed(void)
1783 #ifdef GPU_DIS_STORE14I
1785 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));
1787 #ifdef GPU_CORRECT_ALIGNMENT
1788 uint32_t address
= gpu_reg
[14] + (gpu_convert_zero
[IMM_1
] << 2);
1790 if (address
>= 0xF03000 && address
<= 0xF03FFF)
1791 GPUWriteLong(address
& 0xFFFFFFFC, RN
, GPU
);
1793 GPUWriteLong(address
, RN
, GPU
);
1795 GPUWriteLong(gpu_reg
[14] + (gpu_convert_zero
[IMM_1
] << 2), RN
, GPU
);
1800 static void gpu_opcode_store_r15_indexed(void)
1802 #ifdef GPU_DIS_STORE15I
1804 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));
1806 #ifdef GPU_CORRECT_ALIGNMENT
1807 uint32_t address
= gpu_reg
[15] + (gpu_convert_zero
[IMM_1
] << 2);
1809 if (address
>= 0xF03000 && address
<= 0xF03FFF)
1810 GPUWriteLong(address
& 0xFFFFFFFC, RN
, GPU
);
1812 GPUWriteLong(address
, RN
, GPU
);
1814 GPUWriteLong(gpu_reg
[15] + (gpu_convert_zero
[IMM_1
] << 2), RN
, GPU
);
1819 static void gpu_opcode_load_r14_ri(void)
1821 #ifdef GPU_DIS_LOAD14R
1823 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
);
1825 #ifdef GPU_CORRECT_ALIGNMENT
1826 uint32_t address
= gpu_reg
[14] + RM
;
1828 if (address
>= 0xF03000 && address
<= 0xF03FFF)
1829 RN
= GPUReadLong(address
& 0xFFFFFFFC, GPU
);
1831 RN
= GPUReadLong(address
, GPU
);
1833 RN
= GPUReadLong(gpu_reg
[14] + RM
, GPU
);
1835 #ifdef GPU_DIS_LOAD14R
1837 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_load_r15_ri(void)
1844 #ifdef GPU_DIS_LOAD15R
1846 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
);
1848 #ifdef GPU_CORRECT_ALIGNMENT
1849 uint32_t address
= gpu_reg
[15] + RM
;
1851 if (address
>= 0xF03000 && address
<= 0xF03FFF)
1852 RN
= GPUReadLong(address
& 0xFFFFFFFC, GPU
);
1854 RN
= GPUReadLong(address
, GPU
);
1856 RN
= GPUReadLong(gpu_reg
[15] + RM
, GPU
);
1858 #ifdef GPU_DIS_LOAD15R
1860 WriteLog("[NCZ:%u%u%u, R%02u=%08X]\n", gpu_flag_n
, gpu_flag_c
, gpu_flag_z
, IMM_2
, RN
);
1865 static void gpu_opcode_store_r14_ri(void)
1867 #ifdef GPU_DIS_STORE14R
1869 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]);
1871 #ifdef GPU_CORRECT_ALIGNMENT
1872 uint32_t address
= gpu_reg
[14] + RM
;
1874 if (address
>= 0xF03000 && address
<= 0xF03FFF)
1875 GPUWriteLong(address
& 0xFFFFFFFC, RN
, GPU
);
1877 GPUWriteLong(address
, RN
, GPU
);
1879 GPUWriteLong(gpu_reg
[14] + RM
, RN
, GPU
);
1884 static void gpu_opcode_store_r15_ri(void)
1886 #ifdef GPU_DIS_STORE15R
1888 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]);
1890 #ifdef GPU_CORRECT_ALIGNMENT_STORE
1891 uint32_t address
= gpu_reg
[15] + RM
;
1893 if (address
>= 0xF03000 && address
<= 0xF03FFF)
1894 GPUWriteLong(address
& 0xFFFFFFFC, RN
, GPU
);
1896 GPUWriteLong(address
, RN
, GPU
);
1898 GPUWriteLong(gpu_reg
[15] + RM
, RN
, GPU
);
1903 static void gpu_opcode_nop(void)
1907 WriteLog("%06X: NOP [NCZ:%u%u%u]\n", gpu_pc
-2, gpu_flag_n
, gpu_flag_c
, gpu_flag_z
);
1912 static void gpu_opcode_pack(void)
1916 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
);
1920 //BUG! if (RM == 0) // Pack
1921 if (IMM_1
== 0) // Pack
1922 RN
= ((val
>> 10) & 0x0000F000) | ((val
>> 5) & 0x00000F00) | (val
& 0x000000FF);
1924 RN
= ((val
& 0x0000F000) << 10) | ((val
& 0x00000F00) << 5) | (val
& 0x000000FF);
1927 WriteLog("[NCZ:%u%u%u, R%02u=%08X]\n", gpu_flag_n
, gpu_flag_c
, gpu_flag_z
, IMM_2
, RN
);
1932 static void gpu_opcode_storeb(void)
1934 #ifdef GPU_DIS_STOREB
1936 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
);
1939 // Would appear to be so...!
1940 if ((RM
>= 0xF03000) && (RM
<= 0xF03FFF))
1941 GPUWriteLong(RM
, RN
& 0xFF, GPU
);
1943 JaguarWriteByte(RM
, RN
, GPU
);
1947 static void gpu_opcode_storew(void)
1949 #ifdef GPU_DIS_STOREW
1951 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
);
1953 #ifdef GPU_CORRECT_ALIGNMENT
1954 if ((RM
>= 0xF03000) && (RM
<= 0xF03FFF))
1955 GPUWriteLong(RM
& 0xFFFFFFFE, RN
& 0xFFFF, GPU
);
1957 JaguarWriteWord(RM
, RN
, GPU
);
1959 if ((RM
>= 0xF03000) && (RM
<= 0xF03FFF))
1960 GPUWriteLong(RM
, RN
& 0xFFFF, GPU
);
1962 JaguarWriteWord(RM
, RN
, GPU
);
1967 static void gpu_opcode_store(void)
1969 #ifdef GPU_DIS_STORE
1971 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
);
1973 #ifdef GPU_CORRECT_ALIGNMENT
1974 if ((RM
>= 0xF03000) && (RM
<= 0xF03FFF))
1975 GPUWriteLong(RM
& 0xFFFFFFFC, RN
, GPU
);
1977 GPUWriteLong(RM
, RN
, GPU
);
1979 GPUWriteLong(RM
, RN
, GPU
);
1984 static void gpu_opcode_storep(void)
1986 #ifdef GPU_CORRECT_ALIGNMENT
1987 if ((RM
>= 0xF03000) && (RM
<= 0xF03FFF))
1989 GPUWriteLong((RM
& 0xFFFFFFF8) + 0, gpu_hidata
, GPU
);
1990 GPUWriteLong((RM
& 0xFFFFFFF8) + 4, RN
, GPU
);
1994 GPUWriteLong(RM
+ 0, gpu_hidata
, GPU
);
1995 GPUWriteLong(RM
+ 4, RN
, GPU
);
1998 GPUWriteLong(RM
+ 0, gpu_hidata
, GPU
);
1999 GPUWriteLong(RM
+ 4, RN
, GPU
);
2003 static void gpu_opcode_loadb(void)
2005 #ifdef GPU_DIS_LOADB
2007 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
);
2009 if ((RM
>= 0xF03000) && (RM
<= 0xF03FFF))
2010 RN
= GPUReadLong(RM
, GPU
) & 0xFF;
2012 RN
= JaguarReadByte(RM
, GPU
);
2013 #ifdef GPU_DIS_LOADB
2015 WriteLog("[NCZ:%u%u%u, R%02u=%08X]\n", gpu_flag_n
, gpu_flag_c
, gpu_flag_z
, IMM_2
, RN
);
2020 static void gpu_opcode_loadw(void)
2022 #ifdef GPU_DIS_LOADW
2024 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
);
2026 #ifdef GPU_CORRECT_ALIGNMENT
2027 if ((RM
>= 0xF03000) && (RM
<= 0xF03FFF))
2028 RN
= GPUReadLong(RM
& 0xFFFFFFFE, GPU
) & 0xFFFF;
2030 RN
= JaguarReadWord(RM
, GPU
);
2032 if ((RM
>= 0xF03000) && (RM
<= 0xF03FFF))
2033 RN
= GPUReadLong(RM
, GPU
) & 0xFFFF;
2035 RN
= JaguarReadWord(RM
, GPU
);
2037 #ifdef GPU_DIS_LOADW
2039 WriteLog("[NCZ:%u%u%u, R%02u=%08X]\n", gpu_flag_n
, gpu_flag_c
, gpu_flag_z
, IMM_2
, RN
);
2044 // According to the docs, & "Do The Same", this address is long aligned...
2046 // And it works!!! Need to fix all instances...
2047 // Also, Power Drive Rally seems to contradict the idea that only LOADs in
2048 // the $F03000-$F03FFF range are aligned...
2050 #pragma message("Warning: !!! Alignment issues, need to find definitive final word on this !!!")
2052 #warning "!!! Alignment issues, need to find definitive final word on this !!!"
2055 Preliminary testing on real hardware seems to confirm that something strange goes on
2056 with unaligned reads in main memory. When the address is off by 1, the result is the
2057 same as the long address with the top byte replaced by something. So if the read is
2058 from $401, and $400 has 12 34 56 78, the value read will be $nn345678, where nn is a currently unknown vlaue.
2059 When the address is off by 2, the result would be $nnnn5678, where nnnn is unknown.
2060 When the address is off by 3, the result would be $nnnnnn78, where nnnnnn is unknown.
2061 It may be that the "unknown" values come from the prefetch queue, but not sure how
2062 to test that. They seem to be stable, though, which would indicate such a mechanism.
2063 Sometimes, however, the off by 2 case returns $12345678!
2065 static void gpu_opcode_load(void)
2069 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
);
2071 #ifdef GPU_CORRECT_ALIGNMENT
2072 uint32_t mask
[4] = { 0x00000000, 0xFF000000, 0xFFFF0000, 0xFFFFFF00 };
2073 // if ((RM >= 0xF03000) && (RM <= 0xF03FFF))
2074 RN
= GPUReadLong(RM
& 0xFFFFFFFC, GPU
);
2075 // RN = GPUReadLong(RM & 0x00FFFFFC, GPU);
2077 // RN = GPUReadLong(RM, GPU);
2078 // Simulate garbage in unaligned reads...
2079 //seems that this behavior is different in GPU mem vs. main mem...
2080 // if ((RM < 0xF03000) || (RM > 0xF0BFFF))
2081 // RN |= mask[RM & 0x03];
2083 RN
= GPUReadLong(RM
, GPU
);
2087 WriteLog("[NCZ:%u%u%u, R%02u=%08X]\n", gpu_flag_n
, gpu_flag_c
, gpu_flag_z
, IMM_2
, RN
);
2092 static void gpu_opcode_loadp(void)
2094 #ifdef GPU_CORRECT_ALIGNMENT
2095 if ((RM
>= 0xF03000) && (RM
<= 0xF03FFF))
2097 gpu_hidata
= GPUReadLong((RM
& 0xFFFFFFF8) + 0, GPU
);
2098 RN
= GPUReadLong((RM
& 0xFFFFFFF8) + 4, GPU
);
2102 gpu_hidata
= GPUReadLong(RM
+ 0, GPU
);
2103 RN
= GPUReadLong(RM
+ 4, GPU
);
2106 gpu_hidata
= GPUReadLong(RM
+ 0, GPU
);
2107 RN
= GPUReadLong(RM
+ 4, GPU
);
2112 static void gpu_opcode_load_r14_indexed(void)
2114 #ifdef GPU_DIS_LOAD14I
2116 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
);
2118 #ifdef GPU_CORRECT_ALIGNMENT
2119 uint32_t address
= gpu_reg
[14] + (gpu_convert_zero
[IMM_1
] << 2);
2121 if ((RM
>= 0xF03000) && (RM
<= 0xF03FFF))
2122 RN
= GPUReadLong(address
& 0xFFFFFFFC, GPU
);
2124 RN
= GPUReadLong(address
, GPU
);
2126 RN
= GPUReadLong(gpu_reg
[14] + (gpu_convert_zero
[IMM_1
] << 2), GPU
);
2128 #ifdef GPU_DIS_LOAD14I
2130 WriteLog("[NCZ:%u%u%u, R%02u=%08X]\n", gpu_flag_n
, gpu_flag_c
, gpu_flag_z
, IMM_2
, RN
);
2135 static void gpu_opcode_load_r15_indexed(void)
2137 #ifdef GPU_DIS_LOAD15I
2139 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
);
2141 #ifdef GPU_CORRECT_ALIGNMENT
2142 uint32_t address
= gpu_reg
[15] + (gpu_convert_zero
[IMM_1
] << 2);
2144 if ((RM
>= 0xF03000) && (RM
<= 0xF03FFF))
2145 RN
= GPUReadLong(address
& 0xFFFFFFFC, GPU
);
2147 RN
= GPUReadLong(address
, GPU
);
2149 RN
= GPUReadLong(gpu_reg
[15] + (gpu_convert_zero
[IMM_1
] << 2), GPU
);
2151 #ifdef GPU_DIS_LOAD15I
2153 WriteLog("[NCZ:%u%u%u, R%02u=%08X]\n", gpu_flag_n
, gpu_flag_c
, gpu_flag_z
, IMM_2
, RN
);
2158 static void gpu_opcode_movei(void)
2160 #ifdef GPU_DIS_MOVEI
2162 WriteLog("%06X: MOVEI #$%08X, R%02u [NCZ:%u%u%u, R%02u=%08X] -> ", gpu_pc
-2, (uint32_t)GPUReadWord(gpu_pc
) | ((uint32_t)GPUReadWord(gpu_pc
+ 2) << 16), IMM_2
, gpu_flag_n
, gpu_flag_c
, gpu_flag_z
, IMM_2
, RN
);
2164 // This instruction is followed by 32-bit value in LSW / MSW format...
2165 RN
= (uint32_t)GPUReadWord(gpu_pc
, GPU
) | ((uint32_t)GPUReadWord(gpu_pc
+ 2, GPU
) << 16);
2167 #ifdef GPU_DIS_MOVEI
2169 WriteLog("[NCZ:%u%u%u, R%02u=%08X]\n", gpu_flag_n
, gpu_flag_c
, gpu_flag_z
, IMM_2
, RN
);
2174 static void gpu_opcode_moveta(void)
2176 #ifdef GPU_DIS_MOVETA
2178 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
);
2181 #ifdef GPU_DIS_MOVETA
2183 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
);
2188 static void gpu_opcode_movefa(void)
2190 #ifdef GPU_DIS_MOVEFA
2192 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
);
2195 #ifdef GPU_DIS_MOVEFA
2197 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
);
2202 static void gpu_opcode_move(void)
2206 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
);
2211 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
);
2216 static void gpu_opcode_moveq(void)
2218 #ifdef GPU_DIS_MOVEQ
2220 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
);
2223 #ifdef GPU_DIS_MOVEQ
2225 WriteLog("[NCZ:%u%u%u, R%02u=%08X]\n", gpu_flag_n
, gpu_flag_c
, gpu_flag_z
, IMM_2
, RN
);
2230 static void gpu_opcode_resmac(void)
2236 static void gpu_opcode_imult(void)
2238 #ifdef GPU_DIS_IMULT
2240 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
);
2242 RN
= (int16_t)RN
* (int16_t)RM
;
2244 #ifdef GPU_DIS_IMULT
2246 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
);
2251 static void gpu_opcode_mult(void)
2255 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
);
2257 RN
= (uint16_t)RM
* (uint16_t)RN
;
2258 // RN = (RM & 0xFFFF) * (RN & 0xFFFF);
2262 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
);
2267 static void gpu_opcode_bclr(void)
2271 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
);
2273 uint32_t res
= RN
& ~(1 << IMM_1
);
2278 WriteLog("[NCZ:%u%u%u, R%02u=%08X]\n", gpu_flag_n
, gpu_flag_c
, gpu_flag_z
, IMM_2
, RN
);
2283 static void gpu_opcode_btst(void)
2287 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
);
2289 gpu_flag_z
= (~RN
>> IMM_1
) & 1;
2292 WriteLog("[NCZ:%u%u%u, R%02u=%08X]\n", gpu_flag_n
, gpu_flag_c
, gpu_flag_z
, IMM_2
, RN
);
2297 static void gpu_opcode_bset(void)
2301 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
);
2303 uint32_t res
= RN
| (1 << IMM_1
);
2308 WriteLog("[NCZ:%u%u%u, R%02u=%08X]\n", gpu_flag_n
, gpu_flag_c
, gpu_flag_z
, IMM_2
, RN
);
2313 static void gpu_opcode_imacn(void)
2315 uint32_t res
= (int16_t)RM
* (int16_t)(RN
);
2320 static void gpu_opcode_mtoi(void)
2323 uint32_t res
= RN
= (((int32_t)_RM
>> 8) & 0xFF800000) | (_RM
& 0x007FFFFF);
2328 static void gpu_opcode_normi(void)
2335 while ((_RM
& 0xFFC00000) == 0)
2340 while ((_RM
& 0xFF800000) != 0)
2350 static void gpu_opcode_mmult(void)
2352 int count
= gpu_matrix_control
& 0x0F; // Matrix width
2353 uint32_t addr
= gpu_pointer_to_matrix
; // In the GPU's RAM
2357 if (gpu_matrix_control
& 0x10) // Column stepping
2359 for(int i
=0; i
<count
; i
++)
2363 a
= (int16_t)((gpu_alternate_reg
[IMM_1
+ (i
>> 1)] >> 16) & 0xFFFF);
2365 a
= (int16_t)(gpu_alternate_reg
[IMM_1
+ (i
>> 1)] & 0xFFFF);
2367 int16_t b
= ((int16_t)GPUReadWord(addr
+ 2, GPU
));
2372 else // Row stepping
2374 for(int i
=0; i
<count
; i
++)
2378 a
= (int16_t)((gpu_alternate_reg
[IMM_1
+ (i
>> 1)] >> 16) & 0xFFFF);
2380 a
= (int16_t)(gpu_alternate_reg
[IMM_1
+ (i
>> 1)] & 0xFFFF);
2382 int16_t b
= ((int16_t)GPUReadWord(addr
+ 2, GPU
));
2387 RN
= res
= (int32_t)accum
;
2388 // carry flag to do (out of the last add)
2393 static void gpu_opcode_abs(void)
2397 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
);
2399 gpu_flag_c
= RN
>> 31;
2400 if (RN
== 0x80000000)
2401 //Is 0x80000000 a positive number? If so, then we need to set C to 0 as well!
2402 gpu_flag_n
= 1, gpu_flag_z
= 0;
2407 gpu_flag_n
= 0; SET_FLAG_Z(RN
);
2411 WriteLog("[NCZ:%u%u%u, R%02u=%08X]\n", gpu_flag_n
, gpu_flag_c
, gpu_flag_z
, IMM_2
, RN
);
2416 static void gpu_opcode_div(void) // RN / RM
2420 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
);
2425 if (gpu_div_control
& 0x01) // 16.16 division
2427 gpu_remain
= ((uint64_t)RN
<< 16) % RM
;
2428 RN
= ((uint64_t)RN
<< 16) / RM
;
2432 // We calculate the remainder first because we destroy RN after
2433 // this by assigning it to itself.
2434 gpu_remain
= RN
% RM
;
2440 // This is what happens according to SCPCD. NYAN!
2445 // Real algorithm, courtesy of SCPCD: NYAN!
2449 // If 16.16 division, stuff top 16 bits of RN into remainder and put the
2450 // bottom 16 of RN in top 16 of quotient
2451 if (gpu_div_control
& 0x01)
2452 q
<<= 16, r
= RN
>> 16;
2454 for(int i
=0; i
<32; i
++)
2456 // uint32_t sign = (r >> 31) & 0x01;
2457 uint32_t sign
= r
& 0x80000000;
2458 r
= (r
<< 1) | ((q
>> 31) & 0x01);
2459 r
+= (sign
? RM
: -RM
);
2460 q
= (q
<< 1) | (((~r
) >> 31) & 0x01);
2469 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
);
2474 static void gpu_opcode_imultn(void)
2476 uint32_t res
= (int32_t)((int16_t)RN
* (int16_t)RM
);
2477 gpu_acc
= (int32_t)res
;
2483 static void gpu_opcode_neg(void)
2487 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
);
2490 SET_ZNC_SUB(0, RN
, res
);
2494 WriteLog("[NCZ:%u%u%u, R%02u=%08X]\n", gpu_flag_n
, gpu_flag_c
, gpu_flag_z
, IMM_2
, RN
);
2499 static void gpu_opcode_shlq(void)
2503 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
);
2505 // Was a bug here...
2506 // (Look at Aaron's code: If r1 = 32, then 32 - 32 = 0 which is wrong!)
2507 int32_t r1
= 32 - IMM_1
;
2508 uint32_t res
= RN
<< r1
;
2509 SET_ZN(res
); gpu_flag_c
= (RN
>> 31) & 1;
2513 WriteLog("[NCZ:%u%u%u, R%02u=%08X]\n", gpu_flag_n
, gpu_flag_c
, gpu_flag_z
, IMM_2
, RN
);
2518 static void gpu_opcode_shrq(void)
2522 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
);
2524 int32_t r1
= gpu_convert_zero
[IMM_1
];
2525 uint32_t res
= RN
>> r1
;
2526 SET_ZN(res
); gpu_flag_c
= RN
& 1;
2530 WriteLog("[NCZ:%u%u%u, R%02u=%08X]\n", gpu_flag_n
, gpu_flag_c
, gpu_flag_z
, IMM_2
, RN
);
2535 static void gpu_opcode_ror(void)
2539 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
);
2541 uint32_t r1
= RM
& 0x1F;
2542 uint32_t res
= (RN
>> r1
) | (RN
<< (32 - r1
));
2543 SET_ZN(res
); gpu_flag_c
= (RN
>> 31) & 1;
2547 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
);
2552 static void gpu_opcode_rorq(void)
2556 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
);
2558 uint32_t r1
= gpu_convert_zero
[IMM_1
& 0x1F];
2560 uint32_t res
= (r2
>> r1
) | (r2
<< (32 - r1
));
2562 SET_ZN(res
); gpu_flag_c
= (r2
>> 31) & 0x01;
2565 WriteLog("[NCZ:%u%u%u, R%02u=%08X]\n", gpu_flag_n
, gpu_flag_c
, gpu_flag_z
, IMM_2
, RN
);
2570 static void gpu_opcode_sha(void)
2572 /* int dreg = jaguar.op & 31;
2573 int32_t r1 = (int32_t)jaguar.r[(jaguar.op >> 5) & 31];
2574 uint32_t r2 = jaguar.r[dreg];
2580 res = (r1 <= -32) ? 0 : (r2 << -r1);
2581 jaguar.FLAGS |= (r2 >> 30) & 2;
2585 res = (r1 >= 32) ? ((int32_t)r2 >> 31) : ((int32_t)r2 >> r1);
2586 jaguar.FLAGS |= (r2 << 1) & 2;
2588 jaguar.r[dreg] = res;
2593 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
);
2597 if ((int32_t)RM
< 0)
2599 res
= ((int32_t)RM
<= -32) ? 0 : (RN
<< -(int32_t)RM
);
2600 gpu_flag_c
= RN
>> 31;
2604 res
= ((int32_t)RM
>= 32) ? ((int32_t)RN
>> 31) : ((int32_t)RN
>> (int32_t)RM
);
2605 gpu_flag_c
= RN
& 0x01;
2611 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
);
2614 /* int32_t sRM=(int32_t)RM;
2619 uint32_t shift=-sRM;
2620 if (shift>=32) shift=32;
2621 gpu_flag_c=(_RN&0x80000000)>>31;
2631 if (shift>=32) shift=32;
2635 _RN=((int32_t)_RN)>>1;
2645 static void gpu_opcode_sharq(void)
2647 #ifdef GPU_DIS_SHARQ
2649 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
);
2651 uint32_t res
= (int32_t)RN
>> gpu_convert_zero
[IMM_1
];
2652 SET_ZN(res
); gpu_flag_c
= RN
& 0x01;
2654 #ifdef GPU_DIS_SHARQ
2656 WriteLog("[NCZ:%u%u%u, R%02u=%08X]\n", gpu_flag_n
, gpu_flag_c
, gpu_flag_z
, IMM_2
, RN
);
2661 static void gpu_opcode_sh(void)
2665 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
);
2667 if (RM
& 0x80000000) // Shift left
2669 gpu_flag_c
= RN
>> 31;
2670 RN
= ((int32_t)RM
<= -32 ? 0 : RN
<< -(int32_t)RM
);
2674 gpu_flag_c
= RN
& 0x01;
2675 RN
= (RM
>= 32 ? 0 : RN
>> RM
);
2680 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
);
2685 //Temporary: Testing only!
2686 //#include "gpu2.cpp"
2687 //#include "gpu3.cpp"
2692 // New thread-safe GPU core
2694 int GPUCore(void * data
)