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