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