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