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