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