]> Shamusworld >> Repos - virtualjaguar/blob - src/gpu.cpp
1.0.7 update
[virtualjaguar] / src / gpu.cpp
1 //
2 // GPU Core
3 //
4 // Originally by David Raingeard (Cal2)
5 // GCC/SDL port by Niels Wagenaar (Linux/WIN32) and Caz (BeOS)
6 // Cleanups, endian wrongness, and bad ASM amelioration by James L. Hammons
7 // Note: Endian wrongness probably stems from the MAME origins of this emu and
8 //       the braindead way in which MAME handles memory. :-)
9 //
10 // Problem with not booting the BIOS was the incorrect way that the
11 // SUBC instruction set the carry when the carry was set going in...
12 // Same problem with ADDC...
13 //
14
15 #include "gpu.h"
16
17 //#define GPU_DEBUG
18
19 // For GPU dissasembly...
20
21 #define GPU_DIS_ABS
22 #define GPU_DIS_ADD
23 #define GPU_DIS_ADDC
24 #define GPU_DIS_ADDQ
25 #define GPU_DIS_ADDQT
26 #define GPU_DIS_AND
27 #define GPU_DIS_BCLR
28 #define GPU_DIS_BSET
29 #define GPU_DIS_BTST
30 #define GPU_DIS_CMP
31 #define GPU_DIS_CMPQ
32 #define GPU_DIS_DIV
33 #define GPU_DIS_IMULT
34 #define GPU_DIS_JUMP
35 #define GPU_DIS_JR
36 #define GPU_DIS_LOAD
37 #define GPU_DIS_LOADB
38 #define GPU_DIS_LOADW
39 #define GPU_DIS_LOAD14I
40 #define GPU_DIS_LOAD14R
41 #define GPU_DIS_LOAD15I
42 #define GPU_DIS_LOAD15R
43 #define GPU_DIS_MOVE
44 #define GPU_DIS_MOVEFA
45 #define GPU_DIS_MOVEI
46 #define GPU_DIS_MOVEPC
47 #define GPU_DIS_MOVETA
48 #define GPU_DIS_MOVEQ
49 #define GPU_DIS_MULT
50 #define GPU_DIS_NEG
51 #define GPU_DIS_NOP
52 #define GPU_DIS_NOT
53 #define GPU_DIS_OR
54 #define GPU_DIS_PACK
55 #define GPU_DIS_ROR
56 #define GPU_DIS_RORQ
57 #define GPU_DIS_SAT8
58 #define GPU_DIS_SH
59 #define GPU_DIS_SHA
60 #define GPU_DIS_SHARQ
61 #define GPU_DIS_SHLQ
62 #define GPU_DIS_SHRQ
63 #define GPU_DIS_STORE
64 #define GPU_DIS_STOREB
65 #define GPU_DIS_STOREW
66 #define GPU_DIS_STORE14I
67 #define GPU_DIS_STORE14R
68 #define GPU_DIS_STORE15I
69 #define GPU_DIS_STORE15R
70 #define GPU_DIS_SUB
71 #define GPU_DIS_SUBC
72 #define GPU_DIS_SUBQ
73 #define GPU_DIS_SUBQT
74 #define GPU_DIS_XOR
75
76 bool doGPUDis = false;
77 //bool doGPUDis = true;
78 //*/
79 /*
80 GPU opcodes use (BIOS flying ATARI logo):
81 +                     add 357416
82 +                    addq 538030
83 +                   addqt 6999
84 +                     sub 116663
85 +                    subq 188059
86 +                   subqt 15086
87 +                     neg 36097
88 +                     and 233993
89 +                      or 109332
90 +                     xor 1384
91 +                    btst 111924
92 +                    bset 25029
93 +                    bclr 10551
94 +                    mult 28147
95 +                   imult 69148
96 +                     div 64102
97 +                     abs 159394
98 +                    shlq 194690
99 +                    shrq 292587
100 +                   sharq 192649
101 +                    rorq 58672
102 +                     cmp 244963
103 +                    cmpq 114834
104 +                    move 833472
105 +                   moveq 56427
106 +                  moveta 220814
107 +                  movefa 170678
108 +                   movei 152025
109 +                   loadw 108220
110 +                    load 430936
111 +                  storew 3036
112 +                   store 372490
113 +                 move_pc 2330
114 +                    jump 349134
115 +                      jr 529171
116                     mmult 64904
117 +                     nop 432179
118 */
119
120 // Various bits
121
122 #define CINT0FLAG                       0x0200
123 #define CINT1FLAG                       0x0400
124 #define CINT2FLAG                       0x0800
125 #define CINT3FLAG                       0x1000
126 #define CINT4FLAG                       0x2000
127 #define CINT04FLAGS                     (CINT0FLAG | CINT1FLAG | CINT2FLAG | CINT3FLAG | CINT4FLAG)
128
129 // GPU_FLAGS bits
130
131 #define ZERO_FLAG               0x0001
132 #define CARRY_FLAG              0x0002
133 #define NEGA_FLAG               0x0004
134 #define IMASK                   0x0008
135 #define INT_ENA0                0x0010
136 #define INT_ENA1                0x0020
137 #define INT_ENA2                0x0040
138 #define INT_ENA3                0x0080
139 #define INT_ENA4                0x0100
140 #define INT_CLR0                0x0200
141 #define INT_CLR1                0x0400
142 #define INT_CLR2                0x0800
143 #define INT_CLR3                0x1000
144 #define INT_CLR4                0x2000
145 #define REGPAGE                 0x4000
146 #define DMAEN                   0x8000
147
148 // External global variables
149
150 extern int start_logging;
151 extern int gpu_start_log;
152
153 // Private function prototypes
154
155 void GPUUpdateRegisterBanks(void);
156
157 void GPUDumpDisassembly(void);
158 void GPUDumpRegisters(void);
159 void GPUDumpMemory(void);
160
161 static void gpu_opcode_add(void);
162 static void gpu_opcode_addc(void);
163 static void gpu_opcode_addq(void);
164 static void gpu_opcode_addqt(void);
165 static void gpu_opcode_sub(void);
166 static void gpu_opcode_subc(void);
167 static void gpu_opcode_subq(void);
168 static void gpu_opcode_subqt(void);
169 static void gpu_opcode_neg(void);
170 static void gpu_opcode_and(void);
171 static void gpu_opcode_or(void);
172 static void gpu_opcode_xor(void);
173 static void gpu_opcode_not(void);
174 static void gpu_opcode_btst(void);
175 static void gpu_opcode_bset(void);
176 static void gpu_opcode_bclr(void);
177 static void gpu_opcode_mult(void);
178 static void gpu_opcode_imult(void);
179 static void gpu_opcode_imultn(void);
180 static void gpu_opcode_resmac(void);
181 static void gpu_opcode_imacn(void);
182 static void gpu_opcode_div(void);
183 static void gpu_opcode_abs(void);
184 static void gpu_opcode_sh(void);
185 static void gpu_opcode_shlq(void);
186 static void gpu_opcode_shrq(void);
187 static void gpu_opcode_sha(void);
188 static void gpu_opcode_sharq(void);
189 static void gpu_opcode_ror(void);
190 static void gpu_opcode_rorq(void);
191 static void gpu_opcode_cmp(void);
192 static void gpu_opcode_cmpq(void);
193 static void gpu_opcode_sat8(void);
194 static void gpu_opcode_sat16(void);
195 static void gpu_opcode_move(void);
196 static void gpu_opcode_moveq(void);
197 static void gpu_opcode_moveta(void);
198 static void gpu_opcode_movefa(void);
199 static void gpu_opcode_movei(void);
200 static void gpu_opcode_loadb(void);
201 static void gpu_opcode_loadw(void);
202 static void gpu_opcode_load(void);
203 static void gpu_opcode_loadp(void);
204 static void gpu_opcode_load_r14_indexed(void);
205 static void gpu_opcode_load_r15_indexed(void);
206 static void gpu_opcode_storeb(void);
207 static void gpu_opcode_storew(void);
208 static void gpu_opcode_store(void);
209 static void gpu_opcode_storep(void);
210 static void gpu_opcode_store_r14_indexed(void);
211 static void gpu_opcode_store_r15_indexed(void);
212 static void gpu_opcode_move_pc(void);
213 static void gpu_opcode_jump(void);
214 static void gpu_opcode_jr(void);
215 static void gpu_opcode_mmult(void);
216 static void gpu_opcode_mtoi(void);
217 static void gpu_opcode_normi(void);
218 static void gpu_opcode_nop(void);
219 static void gpu_opcode_load_r14_ri(void);
220 static void gpu_opcode_load_r15_ri(void);
221 static void gpu_opcode_store_r14_ri(void);
222 static void gpu_opcode_store_r15_ri(void);
223 static void gpu_opcode_sat24(void);
224 static void gpu_opcode_pack(void);
225
226 uint8 gpu_opcode_cycles[64] = 
227 {
228         3,  3,  3,  3,  3,  3,  3,  3,
229         3,  3,  3,  3,  3,  3,  3,  3,
230         3,  3,  1,  3,  1, 18,  3,  3,
231         3,  3,  3,  3,  3,  3,  3,  3,
232         3,  3,  2,  2,  2,  2,  3,  4,
233         5,  4,  5,  6,  6,  1,  1,  1,
234         1,  2,  2,  2,  1,  1,  9,  3,
235         3,  1,  6,  6,  2,  2,  3,  3
236 };
237
238 void (*gpu_opcode[64])()= 
239 {       
240         gpu_opcode_add,                                 gpu_opcode_addc,                                gpu_opcode_addq,                                gpu_opcode_addqt,
241         gpu_opcode_sub,                                 gpu_opcode_subc,                                gpu_opcode_subq,                                gpu_opcode_subqt,
242         gpu_opcode_neg,                                 gpu_opcode_and,                                 gpu_opcode_or,                                  gpu_opcode_xor,
243         gpu_opcode_not,                                 gpu_opcode_btst,                                gpu_opcode_bset,                                gpu_opcode_bclr,
244         gpu_opcode_mult,                                gpu_opcode_imult,                               gpu_opcode_imultn,                              gpu_opcode_resmac,
245         gpu_opcode_imacn,                               gpu_opcode_div,                                 gpu_opcode_abs,                                 gpu_opcode_sh,
246         gpu_opcode_shlq,                                gpu_opcode_shrq,                                gpu_opcode_sha,                                 gpu_opcode_sharq,
247         gpu_opcode_ror,                                 gpu_opcode_rorq,                                gpu_opcode_cmp,                                 gpu_opcode_cmpq,
248         gpu_opcode_sat8,                                gpu_opcode_sat16,                               gpu_opcode_move,                                gpu_opcode_moveq,
249         gpu_opcode_moveta,                              gpu_opcode_movefa,                              gpu_opcode_movei,                               gpu_opcode_loadb,
250         gpu_opcode_loadw,                               gpu_opcode_load,                                gpu_opcode_loadp,                               gpu_opcode_load_r14_indexed,
251         gpu_opcode_load_r15_indexed,    gpu_opcode_storeb,                              gpu_opcode_storew,                              gpu_opcode_store,
252         gpu_opcode_storep,                              gpu_opcode_store_r14_indexed,   gpu_opcode_store_r15_indexed,   gpu_opcode_move_pc,
253         gpu_opcode_jump,                                gpu_opcode_jr,                                  gpu_opcode_mmult,                               gpu_opcode_mtoi,
254         gpu_opcode_normi,                               gpu_opcode_nop,                                 gpu_opcode_load_r14_ri,                 gpu_opcode_load_r15_ri,
255         gpu_opcode_store_r14_ri,                gpu_opcode_store_r15_ri,                gpu_opcode_sat24,                               gpu_opcode_pack,
256 };
257
258 static uint8 * gpu_ram_8;
259 uint32 gpu_pc;
260 static uint32 gpu_acc;
261 static uint32 gpu_remain;
262 static uint32 gpu_hidata;
263 static uint32 gpu_flags;
264 static uint32 gpu_matrix_control;
265 static uint32 gpu_pointer_to_matrix;
266 static uint32 gpu_data_organization;
267 static uint32 gpu_control;
268 static uint32 gpu_div_control;
269 // There is a distinct advantage to having these separated out--there's no need to clear
270 // a bit before writing a result. I.e., if the result of an operation leaves a zero in
271 // the carry flag, you don't have to zero gpu_flag_c before you can write that zero!
272 static uint8 gpu_flag_z, gpu_flag_n, gpu_flag_c;
273 static uint32 * gpu_reg_bank_0;
274 static uint32 * gpu_reg_bank_1;
275 static uint32 * gpu_reg;
276 static uint32 * gpu_alternate_reg;
277
278 static uint32 gpu_instruction;
279 static uint32 gpu_opcode_first_parameter;
280 static uint32 gpu_opcode_second_parameter;
281
282 #define GPU_RUNNING             (gpu_control & 0x01)
283
284 #define RM                              gpu_reg[gpu_opcode_first_parameter]
285 #define RN                              gpu_reg[gpu_opcode_second_parameter]
286 #define ALTERNATE_RM    gpu_alternate_reg[gpu_opcode_first_parameter]
287 #define ALTERNATE_RN    gpu_alternate_reg[gpu_opcode_second_parameter]
288 #define IMM_1                   gpu_opcode_first_parameter
289 #define IMM_2                   gpu_opcode_second_parameter
290
291 #define SET_FLAG_Z(r)   (gpu_flag_z = ((r) == 0));
292 #define SET_FLAG_N(r)   (gpu_flag_n = (((UINT32)(r) >> 31) & 0x01));
293
294 #define RESET_FLAG_Z()  gpu_flag_z = 0;
295 #define RESET_FLAG_N()  gpu_flag_n = 0;
296 #define RESET_FLAG_C()  gpu_flag_c = 0;    
297
298 #define CLR_Z                           (gpu_flag_z = 0)
299 #define CLR_ZN                          (gpu_flag_z = gpu_flag_n = 0)
300 #define CLR_ZNC                         (gpu_flag_z = gpu_flag_n = gpu_flag_c = 0)
301 #define SET_Z(r)                        (gpu_flag_z = ((r) == 0))
302 #define SET_N(r)                        (gpu_flag_n = (((UINT32)(r) >> 31) & 0x01))
303 #define SET_C_ADD(a,b)          (gpu_flag_c = ((UINT32)(b) > (UINT32)(~(a))))
304 #define SET_C_SUB(a,b)          (gpu_flag_c = ((UINT32)(b) > (UINT32)(a)))
305 #define SET_ZN(r)                       SET_N(r); SET_Z(r)
306 #define SET_ZNC_ADD(a,b,r)      SET_N(r); SET_Z(r); SET_C_ADD(a,b)
307 #define SET_ZNC_SUB(a,b,r)      SET_N(r); SET_Z(r); SET_C_SUB(a,b)
308
309 uint32 gpu_convert_zero[32] =
310         { 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 };
311
312 uint8 * branch_condition_table = 0;
313 #define BRANCH_CONDITION(x)     branch_condition_table[(x) + ((jaguar_flags & 7) << 5)]
314
315 uint32 gpu_opcode_use[64];
316
317 char * gpu_opcode_str[64]= 
318 {       
319         "add",                          "addc",                         "addq",                         "addqt",
320         "sub",                          "subc",                         "subq",                         "subqt",
321         "neg",                          "and",                          "or",                           "xor",
322         "not",                          "btst",                         "bset",                         "bclr",
323         "mult",                         "imult",                        "imultn",                       "resmac",
324         "imacn",                        "div",                          "abs",                          "sh",
325         "shlq",                         "shrq",                         "sha",                          "sharq",
326         "ror",                          "rorq",                         "cmp",                          "cmpq",
327         "sat8",                         "sat16",                        "move",                         "moveq",
328         "moveta",                       "movefa",                       "movei",                        "loadb",
329         "loadw",                        "load",                         "loadp",                        "load_r14_indexed",
330         "load_r15_indexed",     "storeb",                       "storew",                       "store",
331         "storep",                       "store_r14_indexed","store_r15_indexed","move_pc",
332         "jump",                         "jr",                           "mmult",                        "mtoi",
333         "normi",                        "nop",                          "load_r14_ri",          "load_r15_ri",
334         "store_r14_ri",         "store_r15_ri",         "sat24",                        "pack",
335 };
336
337 static uint32 gpu_in_exec = 0;
338 static uint32 gpu_releaseTimeSlice_flag = 0;
339
340 void gpu_releaseTimeslice(void)
341 {
342         gpu_releaseTimeSlice_flag = 1;
343 }
344
345 uint32 gpu_get_pc(void)
346 {
347         return gpu_pc;
348 }
349
350 void build_branch_condition_table(void)
351 {
352         if (!branch_condition_table)
353         {
354                 branch_condition_table = (uint8 *)malloc(32 * 8 * sizeof(branch_condition_table[0]));
355
356                 if (branch_condition_table)
357                 {
358                         for(int i=0; i<8; i++)
359                         {
360                                 for(int j=0; j<32; j++)
361                                 {
362                                         int result = 1;
363                                         if (j & 1)
364                                                 if (i & ZERO_FLAG)
365                                                         result = 0;
366                                         if (j & 2)
367                                                 if (!(i & ZERO_FLAG))
368                                                         result = 0;
369                                         if (j & 4)
370                                                 if (i & (CARRY_FLAG << (j >> 4)))
371                                                         result = 0;
372                                         if (j & 8)
373                                                 if (!(i & (CARRY_FLAG << (j >> 4))))
374                                                         result = 0;
375                                         branch_condition_table[i * 32 + j] = result;
376                                 }
377                         }
378                 }
379         }
380 }
381
382 //
383 // GPU byte access (read)
384 //
385 uint8 GPUReadByte(uint32 offset, uint32 who/*=UNKNOWN*/)
386 {
387         if (offset >= 0xF02000 && offset <= 0xF020FF)
388                 WriteLog("GPU: ReadByte--Attempt to read from GPU register file by %s!\n", whoName[who]);
389
390         if ((offset >= GPU_WORK_RAM_BASE) && (offset < GPU_WORK_RAM_BASE+0x1000))
391                 return gpu_ram_8[offset & 0xFFF];
392         else if ((offset >= GPU_CONTROL_RAM_BASE) && (offset < GPU_CONTROL_RAM_BASE+0x20))
393         {
394                 uint32 data = GPUReadLong(offset & 0xFFFFFFFC, who);
395
396                 if ((offset & 0x03) == 0)
397                         return data >> 24;
398                 else if ((offset & 0x03) == 1)
399                         return (data >> 16) & 0xFF;
400                 else if ((offset & 0x03) == 2)
401                         return (data >> 8) & 0xFF;
402                 else if ((offset & 0x03) == 3)
403                         return data & 0xFF;
404         }
405
406         return JaguarReadByte(offset, who);
407 }
408
409 //
410 // GPU word access (read)
411 //
412 uint16 GPUReadWord(uint32 offset, uint32 who/*=UNKNOWN*/)
413 {
414         if (offset >= 0xF02000 && offset <= 0xF020FF)
415                 WriteLog("GPU: ReadWord--Attempt to read from GPU register file by %s!\n", whoName[who]);
416
417         if ((offset >= GPU_WORK_RAM_BASE) && (offset < GPU_WORK_RAM_BASE+0x1000))
418         {
419                 offset &= 0xFFF;
420                 uint16 data = ((uint16)gpu_ram_8[offset] << 8) | (uint16)gpu_ram_8[offset+1];
421                 return data;
422         }
423         else if ((offset >= GPU_CONTROL_RAM_BASE) && (offset < GPU_CONTROL_RAM_BASE+0x20))
424         {
425 // This looks and smells wrong...
426 // But it *might* be OK...
427                 if (offset & 0x01)                      // Catch cases 1 & 3... (unaligned read)
428                         return (GPUReadByte(offset, who) << 8) | GPUReadByte(offset+1, who);
429
430                 uint32 data = GPUReadLong(offset & 0xFFFFFFFC, who);
431
432                 if (offset & 0x02)                      // Cases 0 & 2...
433                         return data & 0xFFFF;
434                 else
435                         return data >> 16;
436         }
437
438 //TEMP--Mirror of F03000? No. Writes only...
439 //if (offset >= 0xF0B000 && offset <= 0xF0BFFF)
440 //WriteLog("[GPUR16] --> Possible GPU RAM mirror access by %s!", whoName[who]);
441
442         return JaguarReadWord(offset, who);
443 }
444
445 //
446 // GPU dword access (read)
447 //
448 uint32 GPUReadLong(uint32 offset, uint32 who/*=UNKNOWN*/)
449 {
450         if (offset >= 0xF02000 && offset <= 0xF020FF)
451                 WriteLog("GPU: ReadLong--Attempt to read from GPU register file by %s!\n", whoName[who]);
452
453 //      if ((offset >= GPU_WORK_RAM_BASE) && (offset < GPU_WORK_RAM_BASE + 0x1000))
454         if ((offset >= GPU_WORK_RAM_BASE) && (offset <= GPU_WORK_RAM_BASE + 0x0FFC))
455         {
456                 offset &= 0xFFF;
457                 return ((uint32)gpu_ram_8[offset] << 24) | ((uint32)gpu_ram_8[offset+1] << 16)
458                         | ((uint32)gpu_ram_8[offset+2] << 8) | (uint32)gpu_ram_8[offset+3];//*/
459 //              return GET32(gpu_ram_8, offset);
460         }
461 //      else if ((offset >= GPU_CONTROL_RAM_BASE) && (offset < GPU_CONTROL_RAM_BASE+0x20))
462         else if ((offset >= GPU_CONTROL_RAM_BASE) && (offset <= GPU_CONTROL_RAM_BASE + 0x1C))
463         {
464                 offset &= 0x1F;
465                 switch (offset)
466                 {
467                 case 0x00:
468                         gpu_flag_c = (gpu_flag_c ? 1 : 0);
469                         gpu_flag_z = (gpu_flag_z ? 1 : 0);
470                         gpu_flag_n = (gpu_flag_n ? 1 : 0);
471
472                         gpu_flags = (gpu_flags & 0xFFFFFFF8) | (gpu_flag_n << 2) | (gpu_flag_c << 1) | gpu_flag_z;
473                                         
474                         return gpu_flags & 0xFFFFC1FF;
475                 case 0x04:
476                         return gpu_matrix_control;
477                 case 0x08:
478                         return gpu_pointer_to_matrix;
479                 case 0x0C:
480                         return gpu_data_organization;
481                 case 0x10:
482                         return gpu_pc;
483                 case 0x14:
484                         return gpu_control;
485                 case 0x18:
486                         return gpu_hidata;
487                 case 0x1C:
488                         return gpu_remain;
489                 default:                                                                // unaligned long read
490 #ifdef GPU_DEBUG
491                         WriteLog("GPU: Read32--unaligned 32 bit read at %08X by %s.\n", GPU_CONTROL_RAM_BASE + offset, whoName[who]);
492 #endif  // GPU_DEBUG
493                         return 0;
494                 }
495         }
496 //TEMP--Mirror of F03000? No. Writes only...
497 //if (offset >= 0xF0B000 && offset <= 0xF0BFFF)
498 //      WriteLog("[GPUR32] --> Possible GPU RAM mirror access by %s!\n", whoName[who]);
499 /*if (offset >= 0xF1D000 && offset <= 0xF1DFFF)
500         WriteLog("[GPUR32] --> Reading from Wavetable ROM!\n");//*/
501
502         return (JaguarReadWord(offset, who) << 16) | JaguarReadWord(offset + 2, who);
503 }
504
505 //
506 // GPU byte access (write)
507 //
508 void GPUWriteByte(uint32 offset, uint8 data, uint32 who/*=UNKNOWN*/)
509 {
510         if (offset >= 0xF02000 && offset <= 0xF020FF)
511                 WriteLog("GPU: WriteByte--Attempt to write to GPU register file by %s!\n", whoName[who]);
512
513         if ((offset >= GPU_WORK_RAM_BASE) && (offset <= GPU_WORK_RAM_BASE + 0x0FFF))
514         {
515                 gpu_ram_8[offset & 0xFFF] = data;
516
517 //This is the same stupid worthless code that was in the DSP!!! AARRRGGGGHHHHH!!!!!!
518 /*              if (!gpu_in_exec)
519                 {
520                         m68k_end_timeslice();
521                         dsp_releaseTimeslice();
522                 }*/
523                 return;
524         }
525         else if ((offset >= GPU_CONTROL_RAM_BASE) && (offset <= GPU_CONTROL_RAM_BASE + 0x1F))
526         {
527                 uint32 reg = offset & 0x1C;
528                 int bytenum = offset & 0x03;
529
530 //This is definitely wrong!
531                 if ((reg >= 0x1C) && (reg <= 0x1F))
532                         gpu_div_control = (gpu_div_control & (~(0xFF << (bytenum << 3)))) | (data << (bytenum << 3));
533                 else
534                 {
535                         uint32 old_data = GPUReadLong(offset & 0xFFFFFFC, who);
536                         bytenum = 3 - bytenum; // convention motorola !!!
537                         old_data = (old_data & (~(0xFF << (bytenum << 3)))) | (data << (bytenum << 3));
538                         GPUWriteLong(offset & 0xFFFFFFC, old_data, who);
539                 }
540                 return;
541         }
542 //      WriteLog("gpu: writing %.2x at 0x%.8x\n",data,offset);
543         JaguarWriteByte(offset, data, who);
544 }
545
546 //
547 // GPU word access (write)
548 //
549 void GPUWriteWord(uint32 offset, uint16 data, uint32 who/*=UNKNOWN*/)
550 {
551         if (offset >= 0xF02000 && offset <= 0xF020FF)
552                 WriteLog("GPU: WriteWord--Attempt to write to GPU register file by %s!\n", whoName[who]);
553
554         if ((offset >= GPU_WORK_RAM_BASE) && (offset <= GPU_WORK_RAM_BASE + 0x0FFE))
555         {
556                 gpu_ram_8[offset & 0xFFF] = (data>>8) & 0xFF;
557                 gpu_ram_8[(offset+1) & 0xFFF] = data & 0xFF;//*/
558 /*              offset &= 0xFFF;
559                 SET16(gpu_ram_8, offset, data);//*/
560
561 //This is the same stupid worthless code that was in the DSP!!! AARRRGGGGHHHHH!!!!!!
562 /*              if (!gpu_in_exec)
563                 {
564                         m68k_end_timeslice();
565                         dsp_releaseTimeslice();
566                 }*/
567                 return;
568         }
569         else if ((offset >= GPU_CONTROL_RAM_BASE) && (offset <= GPU_CONTROL_RAM_BASE + 0x1E))
570         {
571                 if (offset & 0x01)              // This is supposed to weed out unaligned writes, but does nothing...
572                 {
573 #ifdef GPU_DEBUG
574                         WriteLog("GPU: Write16--unaligned write @ %08X [%04X]\n", offset, data);
575                         GPUDumpRegisters();
576 #endif  // GPU_DEBUG
577                         return;
578                 }
579 //Dual locations in this range: $1C Divide unit remainder/Divide unit control (R/W)
580 //This just literally sucks.
581                 if ((offset & 0x1C) == 0x1C)
582                 {
583 //This doesn't look right either--handles cases 1, 2, & 3 all the same!
584                         if (offset & 0x02)
585                                 gpu_div_control = (gpu_div_control & 0xFFFF0000) | (data & 0xFFFF);
586                         else
587                                 gpu_div_control = (gpu_div_control & 0x0000FFFF) | ((data & 0xFFFF) << 16);
588                 }
589                 else 
590                 {
591 //WriteLog("[GPU W16:%08X,%04X]", offset, data);
592                         uint32 old_data = GPUReadLong(offset & 0xFFFFFFC, who);
593                         if (offset & 0x02)
594                                 old_data = (old_data & 0xFFFF0000) | (data & 0xFFFF);
595                         else
596                                 old_data = (old_data & 0x0000FFFF) | ((data & 0xFFFF) << 16);
597                         GPUWriteLong(offset & 0xFFFFFFC, old_data, who);
598                 }
599                 return;
600         }
601         else if ((offset == GPU_WORK_RAM_BASE + 0x0FFF) || (GPU_CONTROL_RAM_BASE + 0x1F))
602         {
603 #ifdef GPU_DEBUG
604                         WriteLog("GPU: Write16--unaligned write @ %08X by %s [%04X]!\n", offset, whoName[who], data);
605                         GPUDumpRegisters();
606 #endif  // GPU_DEBUG
607                 return;
608         }
609
610         // Have to be careful here--this can cause an infinite loop!
611         JaguarWriteWord(offset, data, who);
612 }
613
614 //
615 // GPU dword access (write)
616 //
617 void GPUWriteLong(uint32 offset, uint32 data, uint32 who/*=UNKNOWN*/)
618 {
619         if (offset >= 0xF02000 && offset <= 0xF020FF)
620                 WriteLog("GPU: WriteLong--Attempt to write to GPU register file by %s!\n", whoName[who]);
621
622 //      if ((offset >= GPU_WORK_RAM_BASE) && (offset < GPU_WORK_RAM_BASE + 0x1000))
623         if ((offset >= GPU_WORK_RAM_BASE) && (offset <= GPU_WORK_RAM_BASE + 0x0FFC))
624         {
625 #ifdef GPU_DEBUG
626                 if (offset & 0x03)
627                 {
628                         WriteLog("GPU: Write32--unaligned write @ %08X [%08X] by %s\n", offset, data, whoName[who]);
629                         GPUDumpRegisters();
630                 }
631 #endif  // GPU_DEBUG
632
633 /*              gpu_ram_8[offset & 0xFFF] = (data >> 24) & 0xFF,
634                 gpu_ram_8[(offset+1) & 0xFFF] = (data >> 16) & 0xFF,
635                 gpu_ram_8[(offset+2) & 0xFFF] = (data >> 8) & 0xFF,
636                 gpu_ram_8[(offset+3) & 0xFFF] = data & 0xFF;//*/
637                 offset &= 0xFFF;
638                 SET32(gpu_ram_8, offset, data);//*/
639                 return;
640         }
641 //      else if ((offset >= GPU_CONTROL_RAM_BASE) && (offset < GPU_CONTROL_RAM_BASE+0x20))
642         else if ((offset >= GPU_CONTROL_RAM_BASE) && (offset <= GPU_CONTROL_RAM_BASE + 0x1C))
643         {
644                 offset &= 0x1F;
645                 switch (offset)
646                 {
647                 case 0x00:
648                 {
649                         bool IMASKCleared = (gpu_flags & IMASK) && !(data & IMASK);
650                         gpu_flags = data;
651                         gpu_flag_z = gpu_flags & ZERO_FLAG;
652                         gpu_flag_c = (gpu_flags & CARRY_FLAG) >> 1;
653                         gpu_flag_n = (gpu_flags & NEGA_FLAG) >> 2;
654                         GPUUpdateRegisterBanks();
655                         gpu_control &= ~((gpu_flags & CINT04FLAGS) >> 3);       // Interrupt latch clear bits
656 //Writing here is only an interrupt enable--this approach is just plain wrong!
657 //                      GPUHandleIRQs();
658 //This, however, is A-OK! ;-)
659                         if (IMASKCleared)                                               // If IMASK was cleared,
660                                 GPUHandleIRQs();                                        // see if any other interrupts need servicing!
661 #ifdef GPU_DEBUG
662                         if (gpu_flags & (INT_ENA0 | INT_ENA1 | INT_ENA2 | INT_ENA3 | INT_ENA4))
663                                 WriteLog("GPU: Interrupt enable set by %s! Bits: %02X\n", whoName[who], (gpu_flags >> 4) & 0x1F);
664                         WriteLog("GPU: REGPAGE %s...\n", (gpu_flags & REGPAGE ? "set" : "cleared"));
665 #endif  // GPU_DEBUG
666                         break;
667                 }
668                 case 0x04:
669                         gpu_matrix_control = data;
670                         break;
671                 case 0x08:
672                         // This can only point to long aligned addresses
673                         gpu_pointer_to_matrix = data & 0xFFFFFFFC;
674                         break;
675                 case 0x0C:
676                         gpu_data_organization = data;
677                         break;
678                 case 0x10:
679                         gpu_pc = data;
680 #ifdef GPU_DEBUG
681 WriteLog("GPU: %s setting GPU PC to %08X %s\n", whoName[who], gpu_pc, (GPU_RUNNING ? "(GPU is RUNNING!)" : ""));//*/
682 #endif  // GPU_DEBUG
683                         break;
684                 case 0x14:
685                 {       
686 //                      uint32 gpu_was_running = GPU_RUNNING;
687                         data &= ~0xF7C0;                // Disable writes to INT_LAT0-4 & TOM version number
688
689                         // check for GPU -> CPU interrupt
690                         if (data & 0x02)
691                         {
692 //WriteLog("GPU->CPU interrupt\n");
693                                 if (tom_irq_enabled(IRQ_GPU))
694                                 {
695                                         if ((tom_irq_enabled(IRQ_GPU)) && (jaguar_interrupt_handler_is_valid(64)))
696                                         {
697                                                 tom_set_pending_gpu_int();
698                                                 m68k_set_irq(7);                        // Set 68000 NMI
699                                                 gpu_releaseTimeslice();
700                                         }
701                                 }
702                                 data &= ~0x02;
703                         }
704
705                         // check for CPU -> GPU interrupt #0
706                         if (data & 0x04)
707                         {
708 //WriteLog("CPU->GPU interrupt\n");
709                                 GPUSetIRQLine(0, ASSERT_LINE);
710                                 m68k_end_timeslice();
711                                 dsp_releaseTimeslice();
712                                 data &= ~0x04;
713                         }
714
715                         // single stepping
716                         if (data & 0x10)
717                         {
718                                 //WriteLog("asked to perform a single step (single step is %senabled)\n",(data&0x8)?"":"not ");
719                         }
720                         gpu_control = (gpu_control & 0xF7C0) | (data & (~0xF7C0));
721
722                         // if gpu wasn't running but is now running, execute a few cycles
723 #ifndef GPU_SINGLE_STEPPING
724 /*                      if (!gpu_was_running && GPU_RUNNING)
725 #ifdef GPU_DEBUG
726                         {
727                                 WriteLog("GPU: Write32--About to do stupid braindead GPU execution for 200 cycles.\n");
728 #endif  // GPU_DEBUG
729                                 gpu_exec(200);
730 #ifdef GPU_DEBUG
731                         }
732 #endif  // GPU_DEBUG//*/
733 #else
734                         if (gpu_control & 0x18)
735                                 gpu_exec(1);
736 #endif  // #ifndef GPU_SINGLE_STEPPING
737 #ifdef GPU_DEBUG
738 WriteLog("Write to GPU CTRL by %s: %08X ", whoName[who], data);
739 if (GPU_RUNNING)
740         WriteLog(" --> Starting to run at %08X by %s...", gpu_pc, whoName[who]);
741 else
742         WriteLog(" --> Stopped by %s! (GPU_PC: %08X)", whoName[who], gpu_pc);
743 WriteLog("\n");
744 #endif  // GPU_DEBUG
745 //if (GPU_RUNNING)
746 //      GPUDumpDisassembly();
747 /*if (GPU_RUNNING)
748 {
749         if (gpu_pc == 0xF035D8)
750         {
751 //              GPUDumpDisassembly();
752 //              log_done();
753 //              exit(1);
754                 gpu_control &= 0xFFFFFFFE;      // Don't run it and let's see what happens!
755 //Hmm. Seems to lock up when going into the demo...
756 //Try to disable the collision altogether!
757         }
758 }//*/
759 extern int effect_start5;
760 static bool finished = false;
761 //if (GPU_RUNNING && effect_start5 && !finished)
762 if (GPU_RUNNING && effect_start5 && gpu_pc == 0xF035D8)
763 {
764         // Let's do a dump of $6528!
765 /*      uint32 numItems = JaguarReadWord(0x6BD6);
766         WriteLog("\nDump of $6528: %u items.\n\n", numItems);
767         for(int i=0; i<numItems*3*4; i+=3*4)
768         {
769                 WriteLog("\t%04X: %08X %08X %08X -> ", 0x6528+i, JaguarReadLong(0x6528+i),
770                         JaguarReadLong(0x6528+i+4), JaguarReadLong(0x6528+i+8));
771                 uint16 link = JaguarReadWord(0x6528+i+8+2);
772                 for(int j=0; j<40; j+=4)
773                         WriteLog("%08X ", JaguarReadLong(link + j));
774                 WriteLog("\n");
775         }
776         WriteLog("\n");//*/
777         // Let's try a manual blit here...
778 //This isn't working the way it should! !!! FIX !!!
779 //Err, actually, it is.
780 // NOW, it works right! Problem solved!!! It's a blitter bug!
781 /*      uint32 src = 0x4D54, dst = 0xF03000, width = 10 * 4;
782         for(int y=0; y<127; y++)
783         {
784                 for(int x=0; x<2; x++)
785                 {
786                         JaguarWriteLong(dst, JaguarReadLong(src));
787                         
788                         src += 4;
789                         dst += 4;
790                 }
791                 src += width - (2 * 4);
792         }//*/
793 /*      finished = true;
794         doGPUDis = true;
795         WriteLog("\nGPU: About to execute collision detection code.\n\n");//*/
796
797 /*      WriteLog("\nGPU: About to execute collision detection code. Data @ 4D54:\n\n");
798         int count = 0;
799         for(int i=0x004D54; i<0x004D54+2048; i++)
800         {
801                 WriteLog("%02X ", JaguarReadByte(i));
802                 count++;
803                 if (count == 32)
804                 {
805                         count = 0;
806                         WriteLog("\n");
807                 }
808         }
809         WriteLog("\n\nData @ F03000:\n\n");
810         count = 0;
811         for(int i=0xF03000; i<0xF03200; i++)
812         {
813                 WriteLog("%02X ", JaguarReadByte(i));
814                 count++;
815                 if (count == 32)
816                 {
817                         count = 0;
818                         WriteLog("\n");
819                 }
820         }
821         WriteLog("\n\n");
822         log_done();
823         exit(0);//*/
824 }
825 //if (!GPU_RUNNING)
826 //      doGPUDis = false;
827 /*if (!GPU_RUNNING && finished)
828 {
829         WriteLog("\nGPU: Finished collision detection code. Exiting!\n\n");
830         GPUDumpRegisters();
831         log_done();
832         exit(0);
833 }//*/
834                         // (?) If we're set running by the M68K (or DSP?) then end its timeslice to
835                         // allow the GPU a chance to run...
836                         // Yes! This partially fixed Trevor McFur...
837                         if (GPU_RUNNING)
838                                 m68k_end_timeslice();
839                         break;
840                 }
841                 case 0x18:
842                         gpu_hidata = data;
843                         break;
844                 case 0x1C:
845                         gpu_div_control = data;
846                         break;
847 //              default:   // unaligned long write
848                         //exit(0);
849                         //__asm int 3
850                 }
851                 return;
852         }
853
854 //      JaguarWriteWord(offset, (data >> 16) & 0xFFFF, who);
855 //      JaguarWriteWord(offset+2, data & 0xFFFF, who);
856         JaguarWriteLong(offset, data, who);
857 }
858
859 //
860 // Change register banks if necessary
861 //
862 void GPUUpdateRegisterBanks(void)
863 {
864         int bank = (gpu_flags & REGPAGE);               // REGPAGE bit
865
866         if (gpu_flags & IMASK)                                  // IMASK bit
867                 bank = 0;                                                       // IMASK forces main bank to be bank 0
868
869         if (bank)
870                 gpu_reg = gpu_reg_bank_1, gpu_alternate_reg = gpu_reg_bank_0;
871         else
872                 gpu_reg = gpu_reg_bank_0, gpu_alternate_reg = gpu_reg_bank_1;
873 }
874
875 void GPUHandleIRQs(void)
876 {
877         // Bail out if we're already in an interrupt!
878         if (gpu_flags & IMASK)
879                 return;
880
881         // Get the interrupt latch & enable bits
882         uint32 bits = (gpu_control >> 6) & 0x1F, mask = (gpu_flags >> 4) & 0x1F;
883         
884         // Bail out if latched interrupts aren't enabled
885         bits &= mask;
886         if (!bits)
887                 return;
888         
889         // Determine which interrupt to service
890         uint32 which = 0; //Isn't there a #pragma to disable this warning???
891         if (bits & 0x01)
892                 which = 0;
893         if (bits & 0x02)
894                 which = 1;
895         if (bits & 0x04)
896                 which = 2;
897         if (bits & 0x08)
898                 which = 3;
899         if (bits & 0x10)
900                 which = 4;
901
902         if (start_logging)
903                 WriteLog("GPU: Generating IRQ #%i\n", which);
904
905         // set the interrupt flag 
906         gpu_flags |= IMASK;
907         GPUUpdateRegisterBanks();
908
909         // subqt  #4,r31                ; pre-decrement stack pointer 
910         // move  pc,r30                 ; address of interrupted code 
911         // store  r30,(r31)     ; store return address
912         gpu_reg[31] -= 4;
913         GPUWriteLong(gpu_reg[31], gpu_pc - 2, GPU);
914         
915         // movei  #service_address,r30  ; pointer to ISR entry 
916         // jump  (r30)                                  ; jump to ISR 
917         // nop
918         gpu_pc = gpu_reg[30] = GPU_WORK_RAM_BASE + (which * 0x10);
919 }
920
921 void GPUSetIRQLine(int irqline, int state)
922 {
923         if (start_logging)
924                 WriteLog("GPU: Setting GPU IRQ line #%i\n", irqline);
925
926         uint32 mask = 0x0040 << irqline;
927         gpu_control &= ~mask;                           // Clear the interrupt latch
928
929         if (state)
930         {
931                 gpu_control |= mask;                    // Assert the interrupt latch
932                 GPUHandleIRQs();                                // And handle the interrupt...
933         }
934 }
935
936 //TEMPORARY: Testing only!
937 //#include "gpu2.h"
938 //#include "gpu3.h"
939
940 void gpu_init(void)
941 {
942         memory_malloc_secure((void **)&gpu_ram_8, 0x1000, "GPU work RAM");
943 //      memory_malloc_secure((void **)&gpu_reg, 32*sizeof(int32), "GPU bank 0 regs");
944 //      memory_malloc_secure((void **)&gpu_alternate_reg, 32*sizeof(int32), "GPU bank 1 regs");
945         memory_malloc_secure((void **)&gpu_reg_bank_0, 32 * sizeof(int32), "GPU bank 0 regs");
946         memory_malloc_secure((void **)&gpu_reg_bank_1, 32 * sizeof(int32), "GPU bank 1 regs");
947
948         build_branch_condition_table();
949
950         gpu_reset();
951
952 //TEMPORARY: Testing only!
953 //      gpu2_init();
954 //      gpu3_init();
955 }
956
957 void gpu_reset(void)
958 {
959         // GPU registers (directly visible)
960         gpu_flags                         = 0x00000000;
961         gpu_matrix_control    = 0x00000000;
962         gpu_pointer_to_matrix = 0x00000000;
963         gpu_data_organization = 0xFFFFFFFF;
964         gpu_pc                            = 0x00F03000;
965         gpu_control                       = 0x00002800;                 // Correctly sets this as TOM Rev. 2
966         gpu_hidata                        = 0x00000000;
967         gpu_remain                        = 0x00000000;                 // These two registers are RO/WO
968         gpu_div_control           = 0x00000000;
969
970         // GPU internal register
971         gpu_acc                           = 0x00000000;
972
973         gpu_reg = gpu_reg_bank_0;
974         gpu_alternate_reg = gpu_reg_bank_1;
975
976         for(int i=0; i<32; i++)
977                 gpu_reg[i] = gpu_alternate_reg[i] = 0x00000000;
978
979         CLR_ZNC;
980         memset(gpu_ram_8, 0xFF, 0x1000);
981         gpu_in_exec = 0;
982 //not needed    GPUInterruptPending = false;
983         gpu_reset_stats();
984 }
985
986 uint32 gpu_read_pc(void)
987 {
988         return gpu_pc;
989 }
990
991 void gpu_reset_stats(void)
992 {
993         for(uint32 i=0; i<64; i++)
994                 gpu_opcode_use[i] = 0;
995         WriteLog("--> GPU stats were reset!\n");
996 }
997
998 void GPUDumpDisassembly(void)
999 {
1000         char buffer[512];
1001
1002         WriteLog("\n---[GPU code at 00F03000]---------------------------\n");
1003         uint32 j = 0xF03000;
1004         while (j <= 0xF03FFF)
1005         {
1006                 uint32 oldj = j;
1007                 j += dasmjag(JAGUAR_GPU, buffer, j);
1008                 WriteLog("\t%08X: %s\n", oldj, buffer);
1009         }
1010 }
1011
1012 void GPUDumpRegisters(void)
1013 {
1014         WriteLog("\n---[GPU flags: NCZ %d%d%d]-----------------------\n", gpu_flag_n, gpu_flag_c, gpu_flag_z);
1015         WriteLog("\nRegisters bank 0\n");
1016         for(int j=0; j<8; j++)
1017         {
1018                 WriteLog("\tR%02i = %08X R%02i = %08X R%02i = %08X R%02i = %08X\n",
1019                                                   (j << 2) + 0, gpu_reg_bank_0[(j << 2) + 0],
1020                                                   (j << 2) + 1, gpu_reg_bank_0[(j << 2) + 1],
1021                                                   (j << 2) + 2, gpu_reg_bank_0[(j << 2) + 2],
1022                                                   (j << 2) + 3, gpu_reg_bank_0[(j << 2) + 3]);
1023         }
1024         WriteLog("Registers bank 1\n");
1025         for(int j=0; j<8; j++)
1026         {
1027                 WriteLog("\tR%02i = %08X R%02i = %08X R%02i = %08X R%02i = %08X\n",
1028                                                   (j << 2) + 0, gpu_reg_bank_1[(j << 2) + 0],
1029                                                   (j << 2) + 1, gpu_reg_bank_1[(j << 2) + 1],
1030                                                   (j << 2) + 2, gpu_reg_bank_1[(j << 2) + 2],
1031                                                   (j << 2) + 3, gpu_reg_bank_1[(j << 2) + 3]);
1032         }
1033 }
1034
1035 void GPUDumpMemory(void)
1036 {
1037         WriteLog("\n---[GPU data at 00F03000]---------------------------\n");
1038         for(int i=0; i<0xFFF; i+=4)
1039                 WriteLog("\t%08X: %02X %02X %02X %02X\n", 0xF03000+i, gpu_ram_8[i],
1040                         gpu_ram_8[i+1], gpu_ram_8[i+2], gpu_ram_8[i+3]);
1041 }
1042
1043 void gpu_done(void)
1044
1045         WriteLog("GPU: Stopped at PC=%08X (GPU %s running)\n", (unsigned int)gpu_pc, GPU_RUNNING ? "was" : "wasn't");
1046
1047         // Get the interrupt latch & enable bits 
1048         uint8 bits = (gpu_control >> 6) & 0x1F, mask = (gpu_flags >> 4) & 0x1F;
1049         WriteLog("GPU: Latch bits = %02X, enable bits = %02X\n", bits, mask);
1050
1051         GPUDumpRegisters();
1052         GPUDumpDisassembly();
1053
1054         WriteLog("\nGPU opcodes use:\n");
1055         for(int i=0; i<64; i++)
1056         {
1057                 if (gpu_opcode_use[i])
1058                         WriteLog("\t%17s %lu\n", gpu_opcode_str[i], gpu_opcode_use[i]);
1059         }
1060         WriteLog("\n");
1061
1062         memory_free(gpu_ram_8);
1063 }
1064
1065 //
1066 // Main GPU execution core
1067 //
1068 static int testCount = 1;
1069 static int len = 0;
1070 static bool tripwire = false;
1071 void gpu_exec(int32 cycles)
1072 {
1073         if (!GPU_RUNNING)
1074                 return;
1075
1076 #ifdef GPU_SINGLE_STEPPING
1077         if (gpu_control & 0x18)
1078         {
1079                 cycles = 1;
1080                 gpu_control &= ~0x10;
1081         }
1082 #endif
1083         GPUHandleIRQs();
1084         gpu_releaseTimeSlice_flag = 0;
1085         gpu_in_exec++;
1086
1087         while (cycles > 0 && GPU_RUNNING)
1088         {
1089 /*if (gpu_pc == 0xF0359A)
1090 {
1091         doGPUDis = true;
1092         GPUDumpRegisters();
1093 }*/
1094 /*              gpu_flag_c = (gpu_flag_c ? 1 : 0);
1095                 gpu_flag_z = (gpu_flag_z ? 1 : 0);
1096                 gpu_flag_n = (gpu_flag_n ? 1 : 0);*/
1097         
1098                 uint16 opcode = GPUReadWord(gpu_pc, GPU);
1099                 uint32 index = opcode >> 10;
1100                 gpu_instruction = opcode;                               // Added for GPU #3...
1101                 gpu_opcode_first_parameter = (opcode >> 5) & 0x1F;
1102                 gpu_opcode_second_parameter = opcode & 0x1F;
1103 /*if (gpu_pc == 0xF03BE8)
1104 WriteLog("Start of OP frame write...\n");
1105 if (gpu_pc == 0xF03EEE)
1106 WriteLog("--> Writing BRANCH object ---\n");
1107 if (gpu_pc == 0xF03F62)
1108 WriteLog("--> Writing BITMAP object ***\n");//*/
1109 /*if (gpu_pc == 0xF03546)
1110 {
1111         WriteLog("\n--> GPU PC: F03546\n");
1112         GPUDumpRegisters();
1113         GPUDumpDisassembly();
1114 }//*/
1115 /*if (gpu_pc == 0xF033F6)
1116 {
1117         WriteLog("\n--> GPU PC: F033F6\n");
1118         GPUDumpRegisters();
1119         GPUDumpDisassembly();
1120 }//*/
1121 /*if (gpu_pc == 0xF033CC)
1122 {
1123         WriteLog("\n--> GPU PC: F033CC\n");
1124         GPUDumpRegisters();
1125         GPUDumpDisassembly();
1126 }//*/
1127 /*if (gpu_pc == 0xF033D6)
1128 {
1129         WriteLog("\n--> GPU PC: F033D6 (#%d)\n", testCount++);
1130         GPUDumpRegisters();
1131         GPUDumpMemory();
1132 }//*/
1133 /*if (gpu_pc == 0xF033D8)
1134 {
1135         WriteLog("\n--> GPU PC: F033D8 (#%d)\n", testCount++);
1136         GPUDumpRegisters();
1137         GPUDumpMemory();
1138 }//*/
1139 /*if (gpu_pc == 0xF0358E)
1140 {
1141         WriteLog("\n--> GPU PC: F0358E (#%d)\n", testCount++);
1142         GPUDumpRegisters();
1143         GPUDumpMemory();
1144 }//*/
1145 /*if (gpu_pc == 0xF034CA)
1146 {
1147         WriteLog("\n--> GPU PC: F034CA (#%d)\n", testCount++);
1148         GPUDumpRegisters();
1149 }//*/
1150 /*if (gpu_pc == 0xF034CA)
1151 {
1152         len = gpu_reg[1] + 4;//, r9save = gpu_reg[9];
1153         WriteLog("\nAbout to subtract [#%d] (R14=%08X, R15=%08X, R9=%08X):\n   ", testCount++, gpu_reg[14], gpu_reg[15], gpu_reg[9]);
1154         for(int i=0; i<len; i+=4)
1155                 WriteLog(" %08X", GPUReadLong(gpu_reg[15]+i));
1156         WriteLog("\n   ");
1157         for(int i=0; i<len; i+=4)
1158                 WriteLog(" %08X", GPUReadLong(gpu_reg[14]+i));
1159         WriteLog("\n\n");
1160 }
1161 if (gpu_pc == 0xF034DE)
1162 {
1163         WriteLog("\nSubtracted! (R14=%08X, R15=%08X):\n   ", gpu_reg[14], gpu_reg[15]);
1164         for(int i=0; i<len; i+=4)
1165                 WriteLog(" %08X", GPUReadLong(gpu_reg[15]+i));
1166         WriteLog("\n   ");
1167         for(int i=0; i<len; i+=4)
1168                 WriteLog(" %08X", GPUReadLong(gpu_reg[14]+i));
1169         WriteLog("\n   ");
1170         for(int i=0; i<len; i+=4)
1171                 WriteLog(" --------");
1172         WriteLog("\n   ");
1173         for(int i=0; i<len; i+=4)
1174                 WriteLog(" %08X", GPUReadLong(gpu_reg[9]+4+i));
1175         WriteLog("\n\n");
1176 }//*/
1177 /*if (gpu_pc == 0xF035C8)
1178 {
1179         WriteLog("\n--> GPU PC: F035C8 (#%d)\n", testCount++);
1180         GPUDumpRegisters();
1181         GPUDumpDisassembly();
1182 }//*/
1183
1184 if (gpu_start_log)
1185 {
1186 //      gpu_reset_stats();
1187 static char buffer[512];
1188 dasmjag(JAGUAR_GPU, buffer, gpu_pc);
1189 WriteLog("GPU: [%08X] %s (RM=%08X, RN=%08X) -> ", gpu_pc, buffer, RM, RN);
1190 }//*/
1191 //$E400 -> 1110 01 -> $39 -> 57
1192 //GPU #1
1193                 gpu_pc += 2;
1194                 gpu_opcode[index]();
1195 //GPU #2
1196 //              gpu2_opcode[index]();
1197 //              gpu_pc += 2;
1198 //GPU #3                                (Doesn't show ATARI logo! #1 & #2 do...)
1199 //              gpu_pc += 2;
1200 //              gpu3_opcode[index]();
1201
1202 // BIOS hacking
1203 //GPU: [00F03548] jr      nz,00F03560 (0xd561) (RM=00F03114, RN=00000004) ->     --> JR: Branch taken. 
1204 /*static bool firstTime = true;
1205 if (gpu_pc == 0xF03548 && firstTime)
1206 {
1207         gpu_flag_z = 1;
1208 //      firstTime = false;
1209
1210 //static char buffer[512];
1211 //int k=0xF03548;
1212 //while (k<0xF0356C)
1213 //{
1214 //int oldk = k;
1215 //k += dasmjag(JAGUAR_GPU, buffer, k);
1216 //WriteLog("GPU: [%08X] %s\n", oldk, buffer);
1217 //}
1218 //      gpu_start_log = 1;
1219 }//*/
1220 //GPU: [00F0354C] jump    nz,(r29) (0xd3a1) (RM=00F03314, RN=00000004) -> (RM=00F03314, RN=00000004)
1221 /*if (gpu_pc == 0xF0354C)
1222         gpu_flag_z = 0;//, gpu_start_log = 1;//*/
1223
1224                 cycles -= gpu_opcode_cycles[index];
1225                 gpu_opcode_use[index]++;
1226 if (gpu_start_log)
1227         WriteLog("(RM=%08X, RN=%08X)\n", RM, RN);//*/
1228 if ((gpu_pc < 0xF03000 || gpu_pc > 0xF03FFF) && !tripwire)
1229 {
1230         WriteLog("GPU: Executing outside local RAM! GPU_PC: %08X\n", gpu_pc);
1231         tripwire = true;
1232 }
1233         }
1234
1235         gpu_in_exec--;
1236 }
1237
1238 //
1239 // GPU opcodes
1240 //
1241
1242 /*
1243 GPU opcodes use (offset punch--vertically below bad guy):
1244                       add 18686
1245                      addq 32621
1246                       sub 7483
1247                      subq 10252
1248                       and 21229
1249                        or 15003
1250                      btst 1822
1251                      bset 2072
1252                      mult 141
1253                       div 2392
1254                      shlq 13449
1255                      shrq 10297
1256                     sharq 11104
1257                       cmp 6775
1258                      cmpq 5944
1259                      move 31259
1260                     moveq 4473
1261                     movei 23277
1262                     loadb 46
1263                     loadw 4201
1264                      load 28580
1265          load_r14_indexed 1183
1266          load_r15_indexed 1125
1267                    storew 178
1268                     store 10144
1269         store_r14_indexed 320
1270         store_r15_indexed 1
1271                   move_pc 1742
1272                      jump 24467
1273                        jr 18090
1274                       nop 41362
1275 */
1276
1277 static void gpu_opcode_jump(void)
1278 {
1279 #ifdef GPU_DIS_JUMP
1280 char * condition[32] =
1281 {       "T", "nz", "z", "???", "nc", "nc nz", "nc z", "???", "c", "c nz",
1282         "c z", "???", "???", "???", "???", "???", "???", "???", "???",
1283         "???", "nn", "nn nz", "nn z", "???", "n", "n nz", "n z", "???",
1284         "???", "???", "???", "F" };
1285         if (doGPUDis)
1286                 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);
1287 #endif
1288         // normalize flags
1289 /*      gpu_flag_c = (gpu_flag_c ? 1 : 0);
1290         gpu_flag_z = (gpu_flag_z ? 1 : 0);
1291         gpu_flag_n = (gpu_flag_n ? 1 : 0);*/
1292         // KLUDGE: Used by BRANCH_CONDITION
1293         uint32 jaguar_flags = (gpu_flag_n << 2) | (gpu_flag_c << 1) | gpu_flag_z;
1294
1295         if (BRANCH_CONDITION(IMM_2))
1296         {
1297 #ifdef GPU_DIS_JUMP
1298         if (doGPUDis)
1299                 WriteLog("Branched!\n");
1300 #endif
1301 if (gpu_start_log)
1302         WriteLog("    --> JUMP: Branch taken.\n");
1303                 uint32 delayed_pc = RM;
1304                 gpu_exec(1);
1305                 gpu_pc = delayed_pc;
1306 /*              uint16 opcode = GPUReadWord(gpu_pc, GPU);
1307                 gpu_opcode_first_parameter = (opcode >> 5) & 0x1F;
1308                 gpu_opcode_second_parameter = opcode & 0x1F;
1309
1310                 gpu_pc = delayed_pc;
1311                 gpu_opcode[opcode>>10]();//*/
1312         }
1313 #ifdef GPU_DIS_JUMP
1314         else
1315                 if (doGPUDis)
1316                         WriteLog("Branch NOT taken.\n");
1317 #endif
1318 }
1319
1320 static void gpu_opcode_jr(void)
1321 {
1322 #ifdef GPU_DIS_JR
1323 char * condition[32] =
1324 {       "T", "nz", "z", "???", "nc", "nc nz", "nc z", "???", "c", "c nz",
1325         "c z", "???", "???", "???", "???", "???", "???", "???", "???",
1326         "???", "nn", "nn nz", "nn z", "???", "n", "n nz", "n z", "???",
1327         "???", "???", "???", "F" };
1328         if (doGPUDis)
1329                 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);
1330 #endif
1331 /*      if (CONDITION(jaguar.op & 31))
1332         {
1333                 INT32 r1 = (INT8)((jaguar.op >> 2) & 0xF8) >> 2;
1334                 UINT32 newpc = jaguar.PC + r1;
1335                 CALL_MAME_DEBUG;
1336                 jaguar.op = ROPCODE(jaguar.PC);
1337                 jaguar.PC = newpc;
1338                 (*jaguar.table[jaguar.op >> 10])();
1339
1340                 jaguar_icount -= 3;     // 3 wait states guaranteed
1341         }*/
1342         // normalize flags
1343 /*      gpu_flag_n = (gpu_flag_n ? 1 : 0);
1344         gpu_flag_c = (gpu_flag_c ? 1 : 0);
1345         gpu_flag_z = (gpu_flag_z ? 1 : 0);*/
1346         // KLUDGE: Used by BRANCH_CONDITION
1347         uint32 jaguar_flags = (gpu_flag_n << 2) | (gpu_flag_c << 1) | gpu_flag_z;
1348
1349         if (BRANCH_CONDITION(IMM_2))
1350         {
1351 #ifdef GPU_DIS_JR
1352         if (doGPUDis)
1353                 WriteLog("Branched!\n");
1354 #endif
1355 if (gpu_start_log)
1356         WriteLog("    --> JR: Branch taken.\n");
1357                 int32 offset = (IMM_1 & 0x10 ? 0xFFFFFFF0 | IMM_1 : IMM_1);             // Sign extend IMM_1
1358                 int32 delayed_pc = gpu_pc + (offset * 2);
1359                 gpu_exec(1);
1360                 gpu_pc = delayed_pc;
1361 /*              uint16 opcode = GPUReadWord(gpu_pc, GPU);
1362                 gpu_opcode_first_parameter = (opcode >> 5) & 0x1F;
1363                 gpu_opcode_second_parameter = opcode & 0x1F;
1364
1365                 gpu_pc = delayed_pc;
1366                 gpu_opcode[opcode>>10]();//*/
1367         }
1368 #ifdef GPU_DIS_JR
1369         else
1370                 if (doGPUDis)
1371                         WriteLog("Branch NOT taken.\n");
1372 #endif
1373 }
1374
1375 static void gpu_opcode_add(void)
1376 {
1377 #ifdef GPU_DIS_ADD
1378         if (doGPUDis)
1379                 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);
1380 #endif
1381         UINT32 res = RN + RM;
1382         CLR_ZNC; SET_ZNC_ADD(RN, RM, res);
1383         RN = res;
1384 #ifdef GPU_DIS_ADD
1385         if (doGPUDis)
1386                 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);
1387 #endif
1388 }
1389
1390 static void gpu_opcode_addc(void)
1391 {
1392 #ifdef GPU_DIS_ADDC
1393         if (doGPUDis)
1394                 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);
1395 #endif
1396 /*      int dreg = jaguar.op & 31;
1397         UINT32 r1 = jaguar.r[(jaguar.op >> 5) & 31];
1398         UINT32 r2 = jaguar.r[dreg];
1399         UINT32 res = r2 + r1 + ((jaguar.FLAGS >> 1) & 1);
1400         jaguar.r[dreg] = res;
1401         CLR_ZNC; SET_ZNC_ADD(r2,r1,res);*/
1402
1403         UINT32 res = RN + RM + gpu_flag_c;
1404         UINT32 carry = gpu_flag_c;
1405 //      SET_ZNC_ADD(RN, RM, res); //???BUG??? Yes!
1406         SET_ZNC_ADD(RN + carry, RM, res);
1407 //      SET_ZNC_ADD(RN, RM + carry, res);
1408         RN = res;
1409 #ifdef GPU_DIS_ADDC
1410         if (doGPUDis)
1411                 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);
1412 #endif
1413 }
1414
1415 static void gpu_opcode_addq(void)
1416 {
1417 #ifdef GPU_DIS_ADDQ
1418         if (doGPUDis)
1419                 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);
1420 #endif
1421         UINT32 r1 = gpu_convert_zero[IMM_1];
1422         UINT32 res = RN + r1;
1423         CLR_ZNC; SET_ZNC_ADD(RN, r1, res);
1424         RN = res;
1425 #ifdef GPU_DIS_ADDQ
1426         if (doGPUDis)
1427                 WriteLog("[NCZ:%u%u%u, R%02u=%08X]\n", gpu_flag_n, gpu_flag_c, gpu_flag_z, IMM_2, RN);
1428 #endif
1429 }
1430
1431 static void gpu_opcode_addqt(void)
1432 {
1433 #ifdef GPU_DIS_ADDQT
1434         if (doGPUDis)
1435                 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);
1436 #endif
1437         RN += gpu_convert_zero[IMM_1];
1438 #ifdef GPU_DIS_ADDQT
1439         if (doGPUDis)
1440                 WriteLog("[NCZ:%u%u%u, R%02u=%08X]\n", gpu_flag_n, gpu_flag_c, gpu_flag_z, IMM_2, RN);
1441 #endif
1442 }
1443
1444 static void gpu_opcode_sub(void)
1445 {
1446 #ifdef GPU_DIS_SUB
1447         if (doGPUDis)
1448                 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);
1449 #endif
1450         UINT32 res = RN - RM;
1451         SET_ZNC_SUB(RN, RM, res);
1452         RN = res;
1453 #ifdef GPU_DIS_SUB
1454         if (doGPUDis)
1455                 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);
1456 #endif
1457 }
1458
1459 static void gpu_opcode_subc(void)
1460 {
1461 #ifdef GPU_DIS_SUBC
1462         if (doGPUDis)
1463                 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);
1464 #endif
1465         UINT32 res = RN - RM - gpu_flag_c;
1466         UINT32 borrow = gpu_flag_c;
1467 //      SET_ZNC_SUB(RN, RM, res); //???BUG??? YES!!!
1468         SET_ZNC_SUB(RN - borrow, RM, res);
1469         RN = res;
1470 #ifdef GPU_DIS_SUBC
1471         if (doGPUDis)
1472                 WriteLog("[NCZ:%u%u%u, R%02u=%08X, R%02u=%08X]\n", gpu_flag_n, gpu_flag_c, gpu_flag_z, IMM_1, RM, IMM_2, RN);
1473 #endif
1474 }
1475
1476 static void gpu_opcode_subq(void)
1477 {
1478 #ifdef GPU_DIS_SUBQ
1479         if (doGPUDis)
1480                 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);
1481 #endif
1482         UINT32 r1 = gpu_convert_zero[IMM_1];
1483         UINT32 res = RN - r1;
1484         SET_ZNC_SUB(RN, r1, res);
1485         RN = res;
1486 #ifdef GPU_DIS_SUBQ
1487         if (doGPUDis)
1488                 WriteLog("[NCZ:%u%u%u, R%02u=%08X]\n", gpu_flag_n, gpu_flag_c, gpu_flag_z, IMM_2, RN);
1489 #endif
1490 }
1491
1492 static void gpu_opcode_subqt(void)
1493 {
1494 #ifdef GPU_DIS_SUBQT
1495         if (doGPUDis)
1496                 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);
1497 #endif
1498         RN -= gpu_convert_zero[IMM_1];
1499 #ifdef GPU_DIS_SUBQT
1500         if (doGPUDis)
1501                 WriteLog("[NCZ:%u%u%u, R%02u=%08X]\n", gpu_flag_n, gpu_flag_c, gpu_flag_z, IMM_2, RN);
1502 #endif
1503 }
1504
1505 static void gpu_opcode_cmp(void)
1506 {
1507 #ifdef GPU_DIS_CMP
1508         if (doGPUDis)
1509                 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);
1510 #endif
1511         UINT32 res = RN - RM;
1512         SET_ZNC_SUB(RN, RM, res);
1513 #ifdef GPU_DIS_CMP
1514         if (doGPUDis)
1515                 WriteLog("[NCZ:%u%u%u]\n", gpu_flag_n, gpu_flag_c, gpu_flag_z);
1516 #endif
1517 }
1518
1519 static void gpu_opcode_cmpq(void)
1520 {
1521         static int32 sqtable[32] =
1522                 { 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 };
1523 #ifdef GPU_DIS_CMPQ
1524         if (doGPUDis)
1525                 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);
1526 #endif
1527         UINT32 r1 = sqtable[IMM_1 & 0x1F]; // I like this better -> (INT8)(jaguar.op >> 2) >> 3;
1528         UINT32 res = RN - r1;
1529         SET_ZNC_SUB(RN, r1, res);
1530 #ifdef GPU_DIS_CMPQ
1531         if (doGPUDis)
1532                 WriteLog("[NCZ:%u%u%u]\n", gpu_flag_n, gpu_flag_c, gpu_flag_z);
1533 #endif
1534 }
1535
1536 static void gpu_opcode_and(void)
1537 {
1538 #ifdef GPU_DIS_AND
1539         if (doGPUDis)
1540                 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);
1541 #endif
1542         RN = RN & RM;
1543         SET_ZN(RN);
1544 #ifdef GPU_DIS_AND
1545         if (doGPUDis)
1546                 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 #endif
1548 }
1549
1550 static void gpu_opcode_or(void)
1551 {
1552 #ifdef GPU_DIS_OR
1553         if (doGPUDis)
1554                 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);
1555 #endif
1556         RN = RN | RM;
1557         SET_ZN(RN);
1558 #ifdef GPU_DIS_OR
1559         if (doGPUDis)
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);
1561 #endif
1562 }
1563
1564 static void gpu_opcode_xor(void)
1565 {
1566 #ifdef GPU_DIS_XOR
1567         if (doGPUDis)
1568                 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);
1569 #endif
1570         RN = RN ^ RM;
1571         SET_ZN(RN);
1572 #ifdef GPU_DIS_XOR
1573         if (doGPUDis)
1574                 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);
1575 #endif
1576 }
1577
1578 static void gpu_opcode_not(void)
1579 {
1580 #ifdef GPU_DIS_NOT
1581         if (doGPUDis)
1582                 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);
1583 #endif
1584         RN = ~RN;
1585         SET_ZN(RN);
1586 #ifdef GPU_DIS_NOT
1587         if (doGPUDis)
1588                 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);
1589 #endif
1590 }
1591
1592 static void gpu_opcode_move_pc(void)
1593 {
1594 #ifdef GPU_DIS_MOVEPC
1595         if (doGPUDis)
1596                 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);
1597 #endif
1598         // Should be previous PC--this might not always be previous instruction!
1599         // Then again, this will point right at the *current* instruction, i.e., MOVE PC,R!
1600         RN = gpu_pc - 2;
1601 #ifdef GPU_DIS_MOVEPC
1602         if (doGPUDis)
1603                 WriteLog("[NCZ:%u%u%u, R%02u=%08X]\n", gpu_flag_n, gpu_flag_c, gpu_flag_z, IMM_2, RN);
1604 #endif
1605 }
1606
1607 static void gpu_opcode_sat8(void)
1608 {
1609 #ifdef GPU_DIS_SAT8
1610         if (doGPUDis)
1611                 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);
1612 #endif
1613         RN = ((int32)RN < 0 ? 0 : (RN > 0xFF ? 0xFF : RN));
1614         SET_ZN(RN);
1615 #ifdef GPU_DIS_SAT8
1616         if (doGPUDis)
1617                 WriteLog("[NCZ:%u%u%u, R%02u=%08X]\n", gpu_flag_n, gpu_flag_c, gpu_flag_z, IMM_2, RN);
1618 #endif
1619 }
1620
1621 static void gpu_opcode_sat16(void)
1622 {
1623         RN = ((int32)RN < 0 ? 0 : (RN > 0xFFFF ? 0xFFFF : RN));
1624         SET_ZN(RN);
1625 }
1626
1627 static void gpu_opcode_sat24(void)
1628 {
1629         RN = ((int32)RN < 0 ? 0 : (RN > 0xFFFFFF ? 0xFFFFFF : RN));
1630         SET_ZN(RN);
1631 }
1632
1633 static void gpu_opcode_store_r14_indexed(void)
1634 {
1635 #ifdef GPU_DIS_STORE14I
1636         if (doGPUDis)
1637                 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));
1638 #endif
1639         GPUWriteLong(gpu_reg[14] + (gpu_convert_zero[IMM_1] << 2), RN, GPU);
1640 }
1641
1642 static void gpu_opcode_store_r15_indexed(void)
1643 {
1644 #ifdef GPU_DIS_STORE15I
1645         if (doGPUDis)
1646                 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));
1647 #endif
1648         GPUWriteLong(gpu_reg[15] + (gpu_convert_zero[IMM_1] << 2), RN, GPU);
1649 }
1650
1651 static void gpu_opcode_load_r14_ri(void)
1652 {
1653 #ifdef GPU_DIS_LOAD14R
1654         if (doGPUDis)
1655                 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);
1656 #endif
1657         RN = GPUReadLong(gpu_reg[14] + RM, GPU);
1658 #ifdef GPU_DIS_LOAD14R
1659         if (doGPUDis)
1660                 WriteLog("[NCZ:%u%u%u, R%02u=%08X]\n", gpu_flag_n, gpu_flag_c, gpu_flag_z, IMM_2, RN);
1661 #endif
1662 }
1663
1664 static void gpu_opcode_load_r15_ri(void)
1665 {
1666 #ifdef GPU_DIS_LOAD15R
1667         if (doGPUDis)
1668                 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);
1669 #endif
1670         RN = GPUReadLong(gpu_reg[15] + RM, GPU);
1671 #ifdef GPU_DIS_LOAD15R
1672         if (doGPUDis)
1673                 WriteLog("[NCZ:%u%u%u, R%02u=%08X]\n", gpu_flag_n, gpu_flag_c, gpu_flag_z, IMM_2, RN);
1674 #endif
1675 }
1676
1677 static void gpu_opcode_store_r14_ri(void)
1678 {
1679 #ifdef GPU_DIS_STORE14R
1680         if (doGPUDis)
1681                 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]);
1682 #endif
1683         GPUWriteLong(gpu_reg[14] + RM, RN, GPU);
1684 }
1685
1686 static void gpu_opcode_store_r15_ri(void)
1687 {
1688 #ifdef GPU_DIS_STORE15R
1689         if (doGPUDis)
1690                 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]);
1691 #endif
1692         GPUWriteLong(gpu_reg[15] + RM, RN, GPU);
1693 }
1694
1695 static void gpu_opcode_nop(void)
1696 {
1697 #ifdef GPU_DIS_NOP
1698         if (doGPUDis)
1699                 WriteLog("%06X: NOP    [NCZ:%u%u%u]\n", gpu_pc-2, gpu_flag_n, gpu_flag_c, gpu_flag_z);
1700 #endif
1701 }
1702
1703 static void gpu_opcode_pack(void)
1704 {
1705 #ifdef GPU_DIS_PACK
1706         if (doGPUDis)
1707                 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);
1708 #endif
1709         uint32 val = RN;
1710
1711 //BUG!  if (RM == 0)                            // Pack
1712         if (IMM_1 == 0)                         // Pack
1713                 RN = ((val >> 10) & 0x0000F000) | ((val >> 5) & 0x00000F00) | (val & 0x000000FF);
1714         else                                            // Unpack
1715                 RN = ((val & 0x0000F000) << 10) | ((val & 0x00000F00) << 5) | (val & 0x000000FF);
1716 #ifdef GPU_DIS_PACK
1717         if (doGPUDis)
1718                 WriteLog("[NCZ:%u%u%u, R%02u=%08X]\n", gpu_flag_n, gpu_flag_c, gpu_flag_z, IMM_2, RN);
1719 #endif
1720 }
1721
1722 static void gpu_opcode_storeb(void)
1723 {
1724 #ifdef GPU_DIS_STOREB
1725         if (doGPUDis)
1726                 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);
1727 #endif
1728 //Is this right???
1729 // Would appear to be so...!
1730         if ((RM >= 0xF03000) && (RM <= 0xF03FFF))
1731                 GPUWriteLong(RM, RN & 0xFF, GPU);
1732         else
1733                 JaguarWriteByte(RM, RN, GPU);
1734 }
1735
1736 static void gpu_opcode_storew(void)
1737 {
1738 #ifdef GPU_DIS_STOREW
1739         if (doGPUDis)
1740                 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);
1741 #endif
1742         if ((RM >= 0xF03000) && (RM <= 0xF03FFF))
1743                 GPUWriteLong(RM, RN & 0xFFFF, GPU);
1744         else
1745                 JaguarWriteWord(RM, RN, GPU);
1746 }
1747
1748 static void gpu_opcode_store(void)
1749 {
1750 #ifdef GPU_DIS_STORE
1751         if (doGPUDis)
1752                 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);
1753 #endif
1754         GPUWriteLong(RM, RN, GPU);
1755 }
1756
1757 static void gpu_opcode_storep(void)
1758 {
1759         GPUWriteLong(RM + 0, gpu_hidata, GPU);
1760         GPUWriteLong(RM + 4, RN, GPU);
1761 }
1762
1763 static void gpu_opcode_loadb(void)
1764 {
1765 #ifdef GPU_DIS_LOADB
1766         if (doGPUDis)
1767                 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);
1768 #endif
1769         if ((RM >= 0xF03000) && (RM <= 0xF03FFF))
1770                 RN = GPUReadLong(RM, GPU) & 0xFF;
1771         else
1772                 RN = JaguarReadByte(RM, GPU);
1773 #ifdef GPU_DIS_LOADB
1774         if (doGPUDis)
1775                 WriteLog("[NCZ:%u%u%u, R%02u=%08X]\n", gpu_flag_n, gpu_flag_c, gpu_flag_z, IMM_2, RN);
1776 #endif
1777 }
1778
1779 static void gpu_opcode_loadw(void)
1780 {
1781 #ifdef GPU_DIS_LOADW
1782         if (doGPUDis)
1783                 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);
1784 #endif
1785         if ((RM >= 0xF03000) && (RM <= 0xF03FFF))
1786                 RN = GPUReadLong(RM, GPU) & 0xFFFF;
1787         else
1788                 RN = JaguarReadWord(RM, GPU);
1789 #ifdef GPU_DIS_LOADW
1790         if (doGPUDis)
1791                 WriteLog("[NCZ:%u%u%u, R%02u=%08X]\n", gpu_flag_n, gpu_flag_c, gpu_flag_z, IMM_2, RN);
1792 #endif
1793 }
1794
1795 static void gpu_opcode_load(void)
1796 {
1797 #ifdef GPU_DIS_LOAD
1798         if (doGPUDis)
1799                 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);
1800 #endif
1801         RN = GPUReadLong(RM, GPU);
1802 #ifdef GPU_DIS_LOAD
1803         if (doGPUDis)
1804                 WriteLog("[NCZ:%u%u%u, R%02u=%08X]\n", gpu_flag_n, gpu_flag_c, gpu_flag_z, IMM_2, RN);
1805 #endif
1806 }
1807
1808 static void gpu_opcode_loadp(void)
1809 {
1810         gpu_hidata = GPUReadLong(RM + 0, GPU);
1811         RN                 = GPUReadLong(RM + 4, GPU);
1812 }
1813
1814 static void gpu_opcode_load_r14_indexed(void)
1815 {
1816 #ifdef GPU_DIS_LOAD14I
1817         if (doGPUDis)
1818                 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);
1819 #endif
1820         RN = GPUReadLong(gpu_reg[14] + (gpu_convert_zero[IMM_1] << 2), GPU);
1821 #ifdef GPU_DIS_LOAD14I
1822         if (doGPUDis)
1823                 WriteLog("[NCZ:%u%u%u, R%02u=%08X]\n", gpu_flag_n, gpu_flag_c, gpu_flag_z, IMM_2, RN);
1824 #endif
1825 }
1826
1827 static void gpu_opcode_load_r15_indexed(void)
1828 {
1829 #ifdef GPU_DIS_LOAD15I
1830         if (doGPUDis)
1831                 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);
1832 #endif
1833         RN = GPUReadLong(gpu_reg[15] + (gpu_convert_zero[IMM_1] << 2), GPU);
1834 #ifdef GPU_DIS_LOAD15I
1835         if (doGPUDis)
1836                 WriteLog("[NCZ:%u%u%u, R%02u=%08X]\n", gpu_flag_n, gpu_flag_c, gpu_flag_z, IMM_2, RN);
1837 #endif
1838 }
1839
1840 static void gpu_opcode_movei(void)
1841 {
1842 #ifdef GPU_DIS_MOVEI
1843         if (doGPUDis)
1844                 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);
1845 #endif
1846         // This instruction is followed by 32-bit value in LSW / MSW format...
1847         RN = (uint32)GPUReadWord(gpu_pc, GPU) | ((uint32)GPUReadWord(gpu_pc + 2, GPU) << 16);
1848         gpu_pc += 4;
1849 #ifdef GPU_DIS_MOVEI
1850         if (doGPUDis)
1851                 WriteLog("[NCZ:%u%u%u, R%02u=%08X]\n", gpu_flag_n, gpu_flag_c, gpu_flag_z, IMM_2, RN);
1852 #endif
1853 }
1854
1855 static void gpu_opcode_moveta(void)
1856 {
1857 #ifdef GPU_DIS_MOVETA
1858         if (doGPUDis)
1859                 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);
1860 #endif
1861         ALTERNATE_RN = RM;
1862 #ifdef GPU_DIS_MOVETA
1863         if (doGPUDis)
1864                 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);
1865 #endif
1866 }
1867
1868 static void gpu_opcode_movefa(void)
1869 {
1870 #ifdef GPU_DIS_MOVEFA
1871         if (doGPUDis)
1872                 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);
1873 #endif
1874         RN = ALTERNATE_RM;
1875 #ifdef GPU_DIS_MOVEFA
1876         if (doGPUDis)
1877                 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);
1878 #endif
1879 }
1880
1881 static void gpu_opcode_move(void)
1882 {
1883 #ifdef GPU_DIS_MOVE
1884         if (doGPUDis)
1885                 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);
1886 #endif
1887         RN = RM;
1888 #ifdef GPU_DIS_MOVE
1889         if (doGPUDis)
1890                 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);
1891 #endif
1892 }
1893
1894 static void gpu_opcode_moveq(void)
1895 {
1896 #ifdef GPU_DIS_MOVEQ
1897         if (doGPUDis)
1898                 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);
1899 #endif
1900         RN = IMM_1;
1901 #ifdef GPU_DIS_MOVEQ
1902         if (doGPUDis)
1903                 WriteLog("[NCZ:%u%u%u, R%02u=%08X]\n", gpu_flag_n, gpu_flag_c, gpu_flag_z, IMM_2, RN);
1904 #endif
1905 }
1906
1907 static void gpu_opcode_resmac(void)
1908 {
1909         RN = gpu_acc;
1910 }
1911
1912 static void gpu_opcode_imult(void)
1913 {
1914 #ifdef GPU_DIS_IMULT
1915         if (doGPUDis)
1916                 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);
1917 #endif
1918         RN = (int16)RN * (int16)RM;
1919         SET_ZN(RN);
1920 #ifdef GPU_DIS_IMULT
1921         if (doGPUDis)
1922                 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);
1923 #endif
1924 }
1925
1926 static void gpu_opcode_mult(void)
1927 {
1928 #ifdef GPU_DIS_MULT
1929         if (doGPUDis)
1930                 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);
1931 #endif
1932         RN = (uint16)RM * (uint16)RN;
1933         SET_ZN(RN);
1934 #ifdef GPU_DIS_MULT
1935         if (doGPUDis)
1936                 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);
1937 #endif
1938 }
1939
1940 static void gpu_opcode_bclr(void)
1941 {
1942 #ifdef GPU_DIS_BCLR
1943         if (doGPUDis)
1944                 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);
1945 #endif
1946         UINT32 res = RN & ~(1 << IMM_1);
1947         RN = res;
1948         SET_ZN(res);
1949 #ifdef GPU_DIS_BCLR
1950         if (doGPUDis)
1951                 WriteLog("[NCZ:%u%u%u, R%02u=%08X]\n", gpu_flag_n, gpu_flag_c, gpu_flag_z, IMM_2, RN);
1952 #endif
1953 }
1954
1955 static void gpu_opcode_btst(void)
1956 {
1957 #ifdef GPU_DIS_BTST
1958         if (doGPUDis)
1959                 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);
1960 #endif
1961         gpu_flag_z = (~RN >> IMM_1) & 1;
1962 #ifdef GPU_DIS_BTST
1963         if (doGPUDis)
1964                 WriteLog("[NCZ:%u%u%u, R%02u=%08X]\n", gpu_flag_n, gpu_flag_c, gpu_flag_z, IMM_2, RN);
1965 #endif
1966 }
1967
1968 static void gpu_opcode_bset(void)
1969 {
1970 #ifdef GPU_DIS_BSET
1971         if (doGPUDis)
1972                 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);
1973 #endif
1974         UINT32 res = RN | (1 << IMM_1);
1975         RN = res;
1976         SET_ZN(res);
1977 #ifdef GPU_DIS_BSET
1978         if (doGPUDis)
1979                 WriteLog("[NCZ:%u%u%u, R%02u=%08X]\n", gpu_flag_n, gpu_flag_c, gpu_flag_z, IMM_2, RN);
1980 #endif
1981 }
1982
1983 static void gpu_opcode_imacn(void)
1984 {
1985         uint32 res = (int16)RM * (int16)(RN);
1986         gpu_acc += res;
1987 }
1988
1989 static void gpu_opcode_mtoi(void)
1990 {
1991         uint32 _RM = RM;
1992         uint32 res = RN = (((INT32)_RM >> 8) & 0xFF800000) | (_RM & 0x007FFFFF);
1993         SET_ZN(res);
1994 }
1995
1996 static void gpu_opcode_normi(void)
1997 {
1998         uint32 _RM = RM;
1999         uint32 res = 0;
2000
2001         if (_RM)
2002         {
2003                 while ((_RM & 0xFFC00000) == 0)
2004                 {
2005                         _RM <<= 1;
2006                         res--;
2007                 }
2008                 while ((_RM & 0xFF800000) != 0)
2009                 {
2010                         _RM >>= 1;
2011                         res++;
2012                 }
2013         }
2014         RN = res;
2015         SET_ZN(res);
2016 }
2017
2018 static void gpu_opcode_mmult(void)
2019 {
2020         int count       = gpu_matrix_control & 0x0F;    // Matrix width
2021         uint32 addr = gpu_pointer_to_matrix;            // In the GPU's RAM
2022         int64 accum = 0;
2023         uint32 res;
2024
2025         if (gpu_matrix_control & 0x10)                          // Column stepping
2026         {
2027                 for(int i=0; i<count; i++)
2028                 { 
2029                         int16 a;
2030                         if (i & 0x01)
2031                                 a = (int16)((gpu_alternate_reg[IMM_1 + (i >> 1)] >> 16) & 0xFFFF);
2032                         else
2033                                 a = (int16)(gpu_alternate_reg[IMM_1 + (i >> 1)] & 0xFFFF);
2034
2035                         int16 b = ((int16)GPUReadWord(addr + 2, GPU));
2036                         accum += a * b;
2037                         addr += 4 * count;
2038                 }
2039         }
2040         else                                                                            // Row stepping
2041         {
2042                 for(int i=0; i<count; i++)
2043                 {
2044                         int16 a;
2045                         if (i & 0x01)
2046                                 a = (int16)((gpu_alternate_reg[IMM_1 + (i >> 1)] >> 16) & 0xFFFF);
2047                         else
2048                                 a = (int16)(gpu_alternate_reg[IMM_1 + (i >> 1)] & 0xFFFF);
2049
2050                         int16 b = ((int16)GPUReadWord(addr + 2, GPU));
2051                         accum += a * b;
2052                         addr += 4;
2053                 }
2054         }
2055         RN = res = (int32)accum;
2056         // carry flag to do (out of the last add)
2057         SET_ZN(res);
2058 }
2059
2060 static void gpu_opcode_abs(void)
2061 {
2062 #ifdef GPU_DIS_ABS
2063         if (doGPUDis)
2064                 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);
2065 #endif
2066         gpu_flag_c = RN >> 31;
2067         if (RN == 0x80000000)
2068         //Is 0x80000000 a positive number? If so, then we need to set C to 0 as well!
2069                 gpu_flag_n = 1, gpu_flag_z = 0;
2070         else
2071         {
2072                 if (gpu_flag_c)
2073                         RN = -RN;
2074                 gpu_flag_n = 0; SET_FLAG_Z(RN);
2075         }
2076 #ifdef GPU_DIS_ABS
2077         if (doGPUDis)
2078                 WriteLog("[NCZ:%u%u%u, R%02u=%08X]\n", gpu_flag_n, gpu_flag_c, gpu_flag_z, IMM_2, RN);
2079 #endif
2080 }
2081
2082 static void gpu_opcode_div(void)        // RN / RM
2083 {
2084 #ifdef GPU_DIS_DIV
2085         if (doGPUDis)
2086                 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);
2087 #endif
2088 // NOTE: remainder is NOT calculated correctly here!
2089 //       The original tried to get it right by checking to see if the
2090 //       remainder was negative, but that's too late...
2091 // The code there should do it now, but I'm not 100% sure...
2092
2093         if (RM)
2094         {
2095                 if (gpu_div_control & 0x01)             // 16.16 division
2096                 {
2097                         RN = ((UINT64)RN << 16) / RM;
2098                         gpu_remain = ((UINT64)RN << 16) % RM;
2099                 }
2100                 else
2101                 {
2102                         RN = RN / RM;
2103                         gpu_remain = RN % RM;
2104                 }
2105
2106                 if ((gpu_remain - RM) & 0x80000000)     // If the result would have been negative...
2107                         gpu_remain -= RM;                       // Then make it negative!
2108         }
2109         else
2110                 RN = 0xFFFFFFFF;
2111
2112 /*      uint32 _RM=RM;
2113         uint32 _RN=RN;
2114
2115         if (_RM)
2116         {
2117                 if (gpu_div_control & 1)
2118                 {
2119                         gpu_remain = (((uint64)_RN) << 16) % _RM;
2120                         if (gpu_remain&0x80000000)
2121                                 gpu_remain-=_RM;
2122                         RN = (((uint64)_RN) << 16) / _RM;
2123                 }
2124                 else
2125                 {
2126                         gpu_remain = _RN % _RM;
2127                         if (gpu_remain&0x80000000)
2128                                 gpu_remain-=_RM;
2129                         RN/=_RM;
2130                 }
2131         }
2132         else
2133                 RN=0xffffffff;*/
2134 #ifdef GPU_DIS_DIV
2135         if (doGPUDis)
2136                 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);
2137 #endif
2138 }
2139
2140 static void gpu_opcode_imultn(void)
2141 {
2142         uint32 res = (int32)((int16)RN * (int16)RM);
2143         gpu_acc = (int32)res;
2144         SET_FLAG_Z(res);
2145         SET_FLAG_N(res);
2146 }
2147
2148 static void gpu_opcode_neg(void)
2149 {
2150 #ifdef GPU_DIS_NEG
2151         if (doGPUDis)
2152                 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);
2153 #endif
2154         UINT32 res = -RN;
2155         SET_ZNC_SUB(0, RN, res);
2156         RN = res;
2157 #ifdef GPU_DIS_NEG
2158         if (doGPUDis)
2159                 WriteLog("[NCZ:%u%u%u, R%02u=%08X]\n", gpu_flag_n, gpu_flag_c, gpu_flag_z, IMM_2, RN);
2160 #endif
2161 }
2162
2163 static void gpu_opcode_shlq(void)
2164 {
2165 #ifdef GPU_DIS_SHLQ
2166         if (doGPUDis)
2167                 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);
2168 #endif
2169 // Was a bug here...
2170 // (Look at Aaron's code: If r1 = 32, then 32 - 32 = 0 which is wrong!)
2171         INT32 r1 = 32 - IMM_1;
2172         UINT32 res = RN << r1;
2173         SET_ZN(res); gpu_flag_c = (RN >> 31) & 1;
2174         RN = res;
2175 #ifdef GPU_DIS_SHLQ
2176         if (doGPUDis)
2177                 WriteLog("[NCZ:%u%u%u, R%02u=%08X]\n", gpu_flag_n, gpu_flag_c, gpu_flag_z, IMM_2, RN);
2178 #endif
2179 }
2180
2181 static void gpu_opcode_shrq(void)
2182 {
2183 #ifdef GPU_DIS_SHRQ
2184         if (doGPUDis)
2185                 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);
2186 #endif
2187         INT32 r1 = gpu_convert_zero[IMM_1];
2188         UINT32 res = RN >> r1;
2189         SET_ZN(res); gpu_flag_c = RN & 1;
2190         RN = res;
2191 #ifdef GPU_DIS_SHRQ
2192         if (doGPUDis)
2193                 WriteLog("[NCZ:%u%u%u, R%02u=%08X]\n", gpu_flag_n, gpu_flag_c, gpu_flag_z, IMM_2, RN);
2194 #endif
2195 }
2196
2197 static void gpu_opcode_ror(void)
2198 {
2199 #ifdef GPU_DIS_ROR
2200         if (doGPUDis)
2201                 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);
2202 #endif
2203         UINT32 r1 = RM & 0x1F;
2204         UINT32 res = (RN >> r1) | (RN << (32 - r1));
2205         SET_ZN(res); gpu_flag_c = (RN >> 31) & 1;
2206         RN = res;
2207 #ifdef GPU_DIS_ROR
2208         if (doGPUDis)
2209                 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);
2210 #endif
2211 }
2212
2213 static void gpu_opcode_rorq(void)
2214 {
2215 #ifdef GPU_DIS_RORQ
2216         if (doGPUDis)
2217                 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);
2218 #endif
2219         UINT32 r1 = gpu_convert_zero[IMM_1 & 0x1F];
2220         UINT32 r2 = RN;
2221         UINT32 res = (r2 >> r1) | (r2 << (32 - r1));
2222         RN = res;
2223         SET_ZN(res); gpu_flag_c = (r2 >> 31) & 0x01;
2224 #ifdef GPU_DIS_RORQ
2225         if (doGPUDis)
2226                 WriteLog("[NCZ:%u%u%u, R%02u=%08X]\n", gpu_flag_n, gpu_flag_c, gpu_flag_z, IMM_2, RN);
2227 #endif
2228 }
2229
2230 static void gpu_opcode_sha(void)
2231 {
2232 /*      int dreg = jaguar.op & 31;
2233         INT32 r1 = (INT32)jaguar.r[(jaguar.op >> 5) & 31];
2234         UINT32 r2 = jaguar.r[dreg];
2235         UINT32 res;
2236
2237         CLR_ZNC;
2238         if (r1 < 0)
2239         {
2240                 res = (r1 <= -32) ? 0 : (r2 << -r1);
2241                 jaguar.FLAGS |= (r2 >> 30) & 2;
2242         }
2243         else
2244         {
2245                 res = (r1 >= 32) ? ((INT32)r2 >> 31) : ((INT32)r2 >> r1);
2246                 jaguar.FLAGS |= (r2 << 1) & 2;
2247         }
2248         jaguar.r[dreg] = res;
2249         SET_ZN(res);*/
2250
2251 #ifdef GPU_DIS_SHA
2252         if (doGPUDis)
2253                 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);
2254 #endif
2255         UINT32 res;
2256
2257         if ((INT32)RM < 0)
2258         {
2259                 res = ((INT32)RM <= -32) ? 0 : (RN << -(INT32)RM);
2260                 gpu_flag_c = RN >> 31;
2261         }
2262         else
2263         {
2264                 res = ((INT32)RM >= 32) ? ((INT32)RN >> 31) : ((INT32)RN >> (INT32)RM);
2265                 gpu_flag_c = RN & 0x01;
2266         }
2267         RN = res;
2268         SET_ZN(res);
2269 #ifdef GPU_DIS_SHA
2270         if (doGPUDis)
2271                 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);
2272 #endif
2273
2274 /*      int32 sRM=(int32)RM;
2275         uint32 _RN=RN;
2276
2277         if (sRM<0)
2278         {
2279                 uint32 shift=-sRM;
2280                 if (shift>=32) shift=32;
2281                 gpu_flag_c=(_RN&0x80000000)>>31;
2282                 while (shift)
2283                 {
2284                         _RN<<=1;
2285                         shift--;
2286                 }
2287         }
2288         else
2289         {
2290                 uint32 shift=sRM;
2291                 if (shift>=32) shift=32;
2292                 gpu_flag_c=_RN&0x1;
2293                 while (shift)
2294                 {
2295                         _RN=((int32)_RN)>>1;
2296                         shift--;
2297                 }
2298         }
2299         RN=_RN;
2300         SET_FLAG_Z(_RN);
2301         SET_FLAG_N(_RN);*/
2302 }
2303
2304 static void gpu_opcode_sharq(void)
2305 {
2306 #ifdef GPU_DIS_SHARQ
2307         if (doGPUDis)
2308                 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);
2309 #endif
2310         UINT32 res = (INT32)RN >> gpu_convert_zero[IMM_1];
2311         SET_ZN(res); gpu_flag_c = RN & 0x01;
2312         RN = res;
2313 #ifdef GPU_DIS_SHARQ
2314         if (doGPUDis)
2315                 WriteLog("[NCZ:%u%u%u, R%02u=%08X]\n", gpu_flag_n, gpu_flag_c, gpu_flag_z, IMM_2, RN);
2316 #endif
2317 }
2318
2319 static void gpu_opcode_sh(void)
2320 {
2321 #ifdef GPU_DIS_SH
2322         if (doGPUDis)
2323                 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);
2324 #endif
2325         if (RM & 0x80000000)            // Shift left
2326         {
2327                 gpu_flag_c = RN >> 31;
2328                 RN = ((int32)RM <= -32 ? 0 : RN << -(int32)RM);
2329         }
2330         else                                            // Shift right
2331         {
2332                 gpu_flag_c = RN & 0x01;
2333                 RN = (RM >= 32 ? 0 : RN >> RM);
2334         }
2335         SET_ZN(RN);
2336 #ifdef GPU_DIS_SH
2337         if (doGPUDis)
2338                 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);
2339 #endif
2340 }
2341
2342 //Temporary: Testing only!
2343 //#include "gpu2.cpp"
2344 //#include "gpu3.cpp"