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