]> Shamusworld >> Repos - virtualjaguar/blob - src/gpu4.cpp
Added some dependency info/removed stuff no longer needed
[virtualjaguar] / src / gpu4.cpp
1 #include "core.h"
2
3 //#define  DEBUG_GPU
4
5 #define J_ALWAYS        0x00
6 #define J_NZ            0x01
7 #define J_Z             0x02
8 #define J_NC            0x04
9 #define J_NC_NZ         0x05
10 #define J_NC_Z          0x06
11 #define J_C             0x08
12 #define J_C_NZ          0x09
13 #define J_C_Z           0x0A
14 #define J_NN            0x14
15 #define J_NN_NZ         0x15
16 #define J_NN_Z          0x16
17 #define J_N             0x18
18 #define J_N_NZ          0x19
19 #define J_N_Z           0x1A
20 #define J_NEVER         0x1F
21
22    // Opcode Function Prototypes
23
24    void G_ADD( void );          void G_ADDC( void );            
25    void G_ADDQ( void );         void G_ADDQT( void );
26    void G_SUB( void );          void G_SUBC( void );
27    void G_SUBQ( void );         void G_SUBQT( void );
28    void G_NEG( void );          void G_AND( void );
29    void G_OR( void );           void G_XOR( void );
30    void G_NOT( void );          void G_BTST( void );
31    void G_BSET( void );         void G_BCLR( void );
32    void G_MULT( void );         void G_IMULT( void );
33    void G_IMULTN( void );       void G_RESMAC( void );
34    void G_IMACN( void );        void G_DIV( void );
35    void G_ABS( void );          void G_SH( void );
36    void G_SHLQ( void );         void G_SHRQ( void );
37    void G_SHA( void );          void G_SHARQ( void );
38    void G_ROR( void );          void G_RORQ( void );
39    void G_CMP( void );          void G_CMPQ( void );
40    void G_SAT8( void );         void G_SAT16( void );        
41    void G_MOVE( void );         void G_MOVEQ( void );
42    void G_MOVETA( void );       void G_MOVEFA( void );
43    void G_MOVEI( void );        void G_LOADB( void );
44    void G_LOADW( void );        void G_LOAD( void );
45    void G_LOADP( void );        void G_STORE_14I( void );
46    void G_LOAD_14I( void );     void G_LOAD_15I( void );
47    void G_STOREB( void );       void G_STOREW( void );
48    void G_STORE( void );        void G_STOREP( void );
49    void G_STORE_15I( void );    void G_MOVE_PC( void );
50    void G_JUMP( void );         void G_JR( void );
51    void G_MMULT( void );        void G_MTOI( void );
52    void G_NORMI( void );        void G_NOP( void );
53    void G_LOAD_14R( void );     void G_LOAD_15R( void );
54    void G_STORE_14R( void );    void G_STORE_15R( void );
55    void G_SAT24( void );        void G_PACK_UNPACK( void );
56
57    // Other Prototypes
58
59    unsigned mem_readword( unsigned );
60    unsigned mem_readbyte( unsigned );
61    void mem_writeword( unsigned, unsigned );
62    void mem_writebyte( unsigned, unsigned );
63
64    // CPU Cycles for Each GPU Opcode
65
66    byte gpuCycles[64] = {
67       3,  3,  3,  3,  3,  3,  3,  3,  3,  3,  3,  3,  3,  3,  3,  3,
68       3,  3,  1,  3,  1, 18,  3,  3,  3,  3,  3,  3,  3,  3,  3,  3,
69       3,  3,  2,  2,  2,  2,  3,  4,  5,  4,  5,  6,  6,  1,  1,  1,
70       1,  2,  2,  2,  1,  1,  9,  3,  3,  0,  6,  6,  2,  2,  3,  3
71
72    };
73
74    // GPU Opcode Function Table
75
76    void (*gpuOp[64])()= {       
77       G_ADD,        G_ADDC,        G_ADDQ,       G_ADDQT,
78       G_SUB,        G_SUBC,        G_SUBQ,       G_SUBQT,
79       G_NEG,        G_AND,         G_OR,         G_XOR,
80       G_NOT,        G_BTST,        G_BSET,       G_BCLR,
81       G_MULT,       G_IMULT,       G_IMULTN,     G_RESMAC,
82       G_IMACN,      G_DIV,         G_ABS,        G_SH,
83       G_SHLQ,       G_SHRQ,        G_SHA,        G_SHARQ,
84       G_ROR,        G_RORQ,        G_CMP,        G_CMPQ,
85       G_SAT8,       G_SAT16,       G_MOVE,       G_MOVEQ,
86       G_MOVETA,     G_MOVEFA,      G_MOVEI,      G_LOADB,
87       G_LOADW,      G_LOAD,        G_LOADP,      G_LOAD_14I,
88       G_LOAD_15I,   G_STOREB,      G_STOREW,     G_STORE,
89       G_STOREP,     G_STORE_14I,   G_STORE_15I,  G_MOVE_PC,
90       G_JUMP,       G_JR,          G_MMULT,      G_MTOI,
91       G_NORMI,      G_NOP,         G_LOAD_14R,   G_LOAD_15R,
92       G_STORE_14R,  G_STORE_15R,   G_SAT24,      G_PACK_UNPACK
93    };
94
95    GPUSTATE gst;                       // GPU State Information
96    dword GincPC;                       // PC Increment Flag
97    dword GjmpPC;                       // PC Jump gdstination
98    dword Gbranch;                      // Branch Flag
99
100 #ifdef DEBUG_GPU
101    FILE *oo;
102 #endif
103 /*
104       sdword arb[32];                  // GPU Active Register Bank
105       sdword srb[32];                  // GPU Secondary Register Bank
106       dword  acc;                      // Accumulator
107       dword  pc;                       // Program Counter
108       dword  src;                      // Source Register
109       dword  dst;                      // Destination Register
110       BOOL   z;                        // Zero Flag
111       BOOL   n;                        // Negative Flag
112       BOOL   c;                        // Carry Flag
113       dword  ctrl;                     // GPU Control Word    (0xF02114 RW)
114       BOOL   div16;                    // 16.16 Division Flag (0xF0211C WO)
115       dword  divrem;                   // Division Remainder  (0xF0211C RO)
116 */
117
118    dword gpc;                          // Program Counter
119    dword gsrc;                         // Instruction Word Source       
120    dword gdst;                         // Instruction Word Destination
121    BOOL gz;                            // Zero Flag
122    BOOL gn;                            // Negative Flag
123    BOOL gc;                            // Carry Flag
124
125
126    // GPU Processor Emulation
127
128    DWORD gpu_exec( LPVOID lpParam )
129    {
130       dword iw;                        // Instruction Word
131
132 #ifdef DEBUG_GPU
133          oo = fopen( "gpudbg.out", "w" );
134
135          {
136             FILE *f;
137             int i;
138
139             f = fopen( "gpudump.bin", "wb" );
140             for( i = 0x3000; i < 0x4000; i += 2 )  // Dump GPU RAM
141             {
142                fwrite( &st.tom[i+1], 1, 1, f );
143                fwrite( &st.tom[i],   1, 1, f );
144             }
145             fclose( f );
146          }
147 #endif
148
149       // Counter = InterruptPeriod;
150
151       while( gst.gpuActive )
152       {
153          if( gst.step )                // While Single Step Enabled
154          {
155             while( !gst.stepgo ) ;     // Wait Until StepGo Issued   
156             printf( "   GPU Released for One Instruction (SINGLE STEP)\n" );
157          }
158
159          iw = mem_readword( gpc );       // Get Instruction Word
160          gsrc = (iw & 0x03E0) >> 5;  // Get Source
161          gdst = (iw & 0x001F);       // Get Destination
162
163          gpuOp[iw >> 10]();            // Jump to and Execute Opcode Routine
164
165 #ifdef DEBUG_GPU
166             fflush( oo );
167 #endif
168
169          // Counter -= Cycles[Opcode];
170
171          // if( Counter <= 0 )
172          // {
173          //    /* Check for Interrupts and do Other Cyclic tasks here 
174          //    Counter += InterruptPeriod
175          // }
176
177          switch( Gbranch )             // Increment Program Counter
178          {
179             case 2:                    // Next Instruction is the Branch Address
180                Gbranch = 0;
181                gpc = GjmpPC;
182                break;
183          
184             // A Branch Address was Stored in the Branch Program Counter.
185             // The Next Instruction is a PC + 4 (Case 0 is Executed).
186             // The Next Instruction is at the Branch Program Counter
187
188             case 1:
189                Gbranch = 2;
190             case 0:                    // Normal Execution
191                switch( GincPC )
192                {
193                   case 1:              // Opcode Used a 32-Bit Word
194                      gpc += 6;
195                      GincPC = 0;
196                      break;
197                   case 0:              // Normal Execution
198                      gpc += 2;
199                      break;
200                }
201                break;
202          } 
203
204          if( gst.step )                // If Single Step Mode Enabled
205          {
206             gst.stepgo = 0;            // Reset StepGo Flag
207             printf( "   GPU Paused Until New SINGLE_GO (SINGLE STEP)\n" );
208          }
209       }
210
211       #ifdef DEBUG_GPU
212          fclose( oo );
213       #endif
214
215       return( TRUE );
216    }
217
218    void G_ABS( void )
219    {
220       if( gst.arb[gdst] == 0x80000000 )
221          gn = 1;
222       else
223          if( gst.arb[gdst] < 0 )
224          {
225             __asm {
226                mov   ecx,[gdst]
227                mov   eax,[ecx*4+gst.arb]  
228                neg   eax
229                mov   [ecx*4+gst.arb],eax  
230             };
231
232             gz = (gst.arb[gdst] == 0) ? 1 : 0;
233             gn = 0;
234             gc = 1;
235          }
236
237       #ifdef DEBUG_GPU
238          fprintf( oo, "0x%06X ABS R%i\t\t\tR%02i = 0x%08X  Z:%i N:%i C:%i\n",
239                  gpc, gdst, gdst, gst.arb[gdst],
240                  gz, gn, gc );
241       #endif
242    }
243
244    void G_ADD( void )
245    {
246       __asm {
247          mov   ecx,[gsrc]
248          mov   edx,[ecx*4+gst.arb]
249          mov   ecx,[gdst]
250          mov   eax,[ecx*4+gst.arb]
251          add   eax,edx
252          mov   [ecx*4+gst.arb],eax
253          mov   ecx,1
254          jc    addend
255          mov   ecx,0
256       addend:
257          mov   [gc],ecx
258       };
259
260       gz = (gst.arb[gdst] == 0) ? 1 : 0;
261       gn = (gst.arb[gdst] <  0) ? 1 : 0;
262
263       #ifdef DEBUG_GPU
264          fprintf( oo, "0x%06X ADD R%i,R%i\t\tR%02i = 0x%08X  Z:%i N:%i C:%i\n",
265                  gpc, gsrc, gdst, gdst, gst.arb[gdst],
266                  gz, gn, gc );
267       #endif
268    }
269
270    void G_ADDC( void )
271    {
272       __asm {
273          clc
274          mov   ecx,[gc]
275          jcxz  addc
276          stc                     
277       addc:
278          mov   ecx,[gsrc]
279          mov   edx,[ecx*4+gst.arb]  
280          mov   ecx,[gdst]
281          mov   eax,[ecx*4+gst.arb]  
282          adc   eax,edx
283          mov   [ecx*4+gst.arb],eax  
284          mov   ecx,1
285          jc    addcend
286          mov   ecx,0
287       addcend:
288          mov   [gc],ecx
289       };
290
291       gz = (gst.arb[gdst] == 0) ? 1 : 0;
292       gn = (gst.arb[gdst] <  0) ? 1 : 0;
293
294       #ifdef DEBUG_GPU
295          fprintf( oo, "0x%06X ADDC R%i,R%i\t\tR%02i = 0x%08X  "
296                  "Z:%i N:%i C:%i\n", gpc, gsrc, gdst, gdst, 
297                  gst.arb[gdst], gz, gn, gc );
298       #endif
299    }
300     
301    void G_ADDQ( void )
302    {
303       __asm {
304          mov   ecx,[gdst]
305          mov   eax,[ecx*4+gst.arb]
306          mov   edx,[gsrc]         
307          add   eax,edx
308          mov   [ecx*4+gst.arb],eax
309          mov   ecx,1
310          jc    addqend
311          mov   ecx,0
312       addqend:
313          mov   [gc],ecx
314       };
315
316       gz = (gst.arb[gdst] == 0) ? 1 : 0;
317       gn = (gst.arb[gdst] <  0) ? 1 : 0;
318
319       #ifdef DEBUG_GPU
320          fprintf( oo, "0x%06X ADDQ 0x%02X,R%i\t\tR%02i = 0x%08X  "
321                  "Z:%i N:%i C:%i\n", gpc, gsrc, gdst, gdst, 
322                  gst.arb[gdst], gz, gn, gc );
323       #endif
324    }
325
326    void G_ADDQT( void )
327    {
328       __asm {
329          mov   ecx,[gdst]
330          mov   eax,[ecx*4+gst.arb]  
331          mov   edx,[gsrc]        
332          add   eax,edx
333          mov   [ecx*4+gst.arb],eax  
334       };
335
336       #ifdef DEBUG_GPU
337          fprintf( oo, "0x%06X ADDQT 0x%02X,R%i\t\tR%02i = 0x%08X\n",
338                  gpc, gsrc, gdst, gdst, gst.arb[gdst] );
339       #endif
340    }
341
342    void G_AND( void )
343    {
344       gst.arb[gdst] &= gst.arb[gsrc];
345       gz = (gst.arb[gdst] == 0) ? 1 : 0;
346       gn = (gst.arb[gdst] <  0) ? 1 : 0;
347
348       #ifdef DEBUG_GPU
349          fprintf( oo, "0x%06X AND R%i,R%i\t\tR%02i = 0x%08X  Z:%i N:%i C:%i\n",
350                  gpc, gsrc, gdst, gdst, gst.arb[gdst],
351                  gz, gn, gc );
352       #endif
353    }
354
355    void G_BCLR( void )
356    {
357       __asm {
358          mov   ecx,[gdst]
359          mov   eax,[ecx*4+gst.arb]
360          mov   edx,[gsrc]
361          btr   eax,edx           
362          mov   [ecx*4+gst.arb],eax 
363       };
364
365       gz = (gst.arb[gdst] == 0) ? 1 : 0;
366       gn = (gst.arb[gdst] <  0) ? 1 : 0;
367
368       #ifdef DEBUG_GPU
369          fprintf( oo, "0x%06X BCLR 0x%04X,R%i\t\t\t                  "
370                  "Z:%i N:%i C:%i\n", 
371                  gpc, gsrc, gdst, gz, gn, gc );
372       #endif
373    }
374
375    void G_BSET( void )
376    {
377       __asm {
378          mov   ecx,[gdst]
379          mov   eax,[ecx*4+gst.arb]  
380          mov   edx,[gsrc]
381          bts   eax,edx          
382          mov   [ecx*4+gst.arb],eax 
383       };
384
385       gz = (gst.arb[gdst] == 0) ? 1 : 0;
386       gn = (gst.arb[gdst] <  0) ? 1 : 0;
387
388       #ifdef DEBUG_GPU
389          fprintf( oo, "0x%06X BSET 0x%04X,R%i\t\t\t                  "
390                  "Z:%i N:%i C:%i\n", 
391                  gpc, gsrc, gdst, gz, gn, gc );
392       #endif
393    }
394
395    void G_BTST( void )
396    {
397       __asm {
398          mov   ecx,[gdst]
399          mov   eax,[ecx*4+gst.arb] 
400          mov   ecx,[gsrc]
401          bt    eax,ecx           
402          mov   ecx,1
403          jc    btstend
404          mov   ecx,0
405       btstend:
406          mov   [gz],ecx
407       };
408
409       #ifdef DEBUG_GPU
410          fprintf( oo, "0x%06X BTST 0x%04X,R%i\t\t\t                  "
411                  "Z:%i N:%i C:%i\n", 
412                  gpc, gsrc, gdst, gz, gn, gc );
413       #endif
414    }
415                
416    void G_CMP( void )
417    {
418       sdword tmpW;
419
420       __asm {
421          mov   ecx,[gsrc]
422          mov   edx,[ecx*4+gst.arb]  
423          mov   ecx,[gdst]
424          mov   eax,[ecx*4+gst.arb]  
425          sub   eax,edx
426          lahf                    
427          mov   [tmpW],eax
428       };
429
430       gc = (tmpW & 0x0100) ? 1 : 0;
431       gz = (tmpW & 0x4000) ? 1 : 0;
432       gn = (tmpW & 0x8000) ? 1 : 0;
433                
434       #ifdef DEBUG_GPU
435          fprintf( oo, "0x%06X CMP R%i,R%i\t\t                  "
436                  "Z:%i N:%i C:%i\n",
437                  gpc, gsrc, gdst, gz, gn, gc );
438       #endif
439    }
440
441    void G_CMPQ( void )
442    {
443       sdword tmpW;
444
445       __asm {
446          mov   edx,[gsrc]
447          bt    edx,4
448          jnc   cmpq
449          bts   edx,31
450       cmpq:
451          mov   ecx,[gdst]
452          mov   eax,[ecx*4+gst.arb]  
453          sub   eax,edx
454          lahf                    
455          mov   [tmpW],eax
456       };
457
458       gc = (tmpW & 0x0100) ? 1 : 0;
459       gz = (tmpW & 0x4000) ? 1 : 0;
460       gn = (tmpW & 0x8000) ? 1 : 0;
461                
462       #ifdef DEBUG_GPU
463          fprintf( oo, "0x%06X CMPQ 0x%02X,R%i\t\t                  "
464                  "Z:%i N:%i C:%i\n",
465                  gpc, gsrc, gdst, gz, gn, gc );
466       #endif*/
467    }
468
469    void G_DIV( void )
470    {
471       if( gst.div16 )
472          printf( "GPU DIVIDE 16.16 REQUIRED !!!!\n" );
473       else
474       {
475          (dword)gst.arb[gdst] = (dword)gst.arb[gdst] / 
476                                    (dword)gst.arb[gsrc];
477
478          gst.divrem = (dword)gst.arb[gdst] % (dword)gst.arb[gsrc];
479       }
480
481       #ifdef DEBUG_GPU
482          fprintf( oo, "0x%06X DIV R%i,R%i\t\tR%02i = 0x%08X  ",
483                   gpc, gsrc, gdst, gdst, gst.arb[gdst] );
484       #endif
485    }
486
487    void G_IMACN( void )
488    {
489       // Like IMULT but product is added to the previous arithmetic operation.
490       // Intended to be used after IMULTN.
491
492       gst.acc += (sdword)((sword)gst.arb[gsrc] * 
493                           (sword)gst.arb[gdst] );
494
495       #ifdef DEBUG_GPU
496          fprintf( oo, "0x%06X IMACN R%i,R%i\t\tACC = 0x%08X\n",
497                  gpc, gsrc, gdst, gst.acc );
498       #endif
499    }
500
501    void G_IMULT( void )
502    {
503       gst.arb[gdst] = (sdword)((sword)gst.arb[gsrc] * 
504                                   (sword)gst.arb[gdst] );
505
506       gz = (gst.arb[gdst] == 0) ? 1 : 0;
507       gn = (gst.arb[gdst] <  0) ? 1 : 0;
508
509       #ifdef DEBUG_GPU
510          fprintf( oo, "0x%06X IMULT R%i,R%i\t\tR%02i = 0x%08X  "
511                  "Z:%i N:%i C:%i\n", gpc, gsrc, gdst, gdst, 
512                  gst.arb[gdst], gz, gn, gc );
513       #endif
514    }
515     
516    void G_IMULTN( void )
517    {
518       // Like IMULT but result not written back to gst.arb[gdst]
519       // but to an accumulator. Used as first part of multiply/accumulate group.
520
521       gst.acc = (sdword)((sword)gst.arb[gsrc] * 
522                          (sword)gst.arb[gdst] );
523
524       gz = (gst.arb[gdst] == 0) ? 1 : 0;
525       gn = (gst.arb[gdst] <  0) ? 1 : 0;
526
527       #ifdef DEBUG_GPU
528          fprintf( oo, "0x%06X IMULTN R%i,R%i\t\tACC = 0x%08X  "
529                  "Z:%i N:%i C:%i\n", gpc, gsrc, gdst, gst.acc,
530                   gz, gn, gc );
531       #endif
532    }
533
534    void G_JR( void )
535    {
536       if( gsrc >= 16 )         // Set Jump Direction
537          gsrc -= 32;
538
539       GjmpPC = (gpc + 2) + (gsrc * 2);
540
541       switch( gdst )
542       {
543          case 0x00:           // No Conditions
544             Gbranch = 1;
545             #ifdef DEBUG_GPU
546                fprintf( oo, "0x%06X JR 0x%08X\n", gpc, GjmpPC );
547             #endif
548             break;
549
550          case 0x01:           // NE - Not Equal
551             if( !gz )  // Zero Flag Unset
552                Gbranch = 1;
553             #ifdef DEBUG_GPU
554                fprintf( oo, "0x%06X JR NE,0x%08X\n",gpc, GjmpPC );
555             #endif
556             break;
557
558          case 0x02:           // EQ - Equal
559             if( gz)    // Zero Flag Set
560                Gbranch = 1;
561             #ifdef DEBUG_GPU
562                fprintf( oo, "0x%06X JR EQ,0x%08X\n", gpc, GjmpPC );
563             #endif
564             break;
565
566          case 0x04:           // Flag Selected Cleared to Jump
567             if( !gc ) Gbranch = 1; else Gbranch = 0;
568             #ifdef DEBUG_GPU
569                fprintf( oo, "0x%06X JR CC,0x%08X\n", gpc, GjmpPC );
570             #endif
571             break;
572
573          case 0x08:           // Flag Selected Set to Jump
574             if( gc ) Gbranch = 1; else Gbranch = 0;
575             #ifdef DEBUG_GPU
576                fprintf( oo, "0x%06X JR CS,0x%08X\n", gpc, GjmpPC );
577             #endif
578             break;
579
580          case 0x14:
581             if( !gn ) Gbranch = 1; else Gbranch = 0;
582             #ifdef DEBUG_GPU
583                fprintf( oo, "0x%06X JR NN,0x%08X\n", gpc, GjmpPC );
584             #endif
585             break;
586
587          case 0x18:
588             if( gn ) Gbranch = 1; else Gbranch = 0;
589             #ifdef DEBUG_GPU
590                fprintf( oo, "0x%06X JR N,0x%08X\n", gpc, GjmpPC );
591             #endif
592             break;
593
594          default:
595             #ifdef DEBUG_GPU
596                fprintf( oo, "Unknown JR Condition at 0x%08X\n", gpc );
597             #endif
598             break;
599                
600       }
601    }
602
603    void G_JUMP( void )
604    {
605       GjmpPC = gst.arb[gsrc];
606
607       switch( gdst )
608       {
609          case J_ALWAYS:
610             Gbranch = 1;
611             #ifdef DEBUG_GPU
612                fprintf( oo, "0x%06X JUMP (R%02i)                    DEST = 0x%08X\n",
613                        gpc, gsrc, GjmpPC );
614             #endif
615             break;
616
617          case J_NZ:
618             if( !gz ) Gbranch = 1;
619             else         Gbranch = 0;
620             #ifdef DEBUG_GPU
621                fprintf( oo, "0x%06X JUMP NZ,(R%02i)                 DEST = 0x%08X\n",
622                         gpc, gsrc, GjmpPC );
623             #endif
624             break;
625
626          case J_Z:
627             if( gz) Gbranch = 1;
628             else       Gbranch = 0;
629             #ifdef DEBUG_GPU
630                fprintf( oo, "0x%06X JUMP Z,(R%02i)                  DEST = 0x%08X\n",
631                         gpc, gsrc, GjmpPC );
632             #endif
633             break;
634
635          case J_NC:
636                if( !gc ) Gbranch = 1; 
637                else         Gbranch = 0;
638             #ifdef DEBUG_GPU
639                fprintf( oo, "0x%06X JUMP NC,(R%02i)                 DEST = 0x%08X\n",
640                         gpc, gsrc, GjmpPC );
641             #endif
642             break;
643
644          case J_NC_NZ:
645                if( !gc && !gz ) Gbranch = 1; 
646                else                   Gbranch = 0;
647             #ifdef DEBUG_GPU
648                fprintf( oo, "0x%06X JUMP NC_NZ,(R%02i)              DEST = 0x%08X\n",
649                         gpc, gsrc, GjmpPC );
650             #endif
651             break;
652
653          case J_NC_Z:
654                if( !gc && gz ) Gbranch = 1; 
655                else                  Gbranch = 0;
656             #ifdef DEBUG_GPU
657                fprintf( oo, "0x%06X JUMP NC_Z,(R%02i)               DEST = 0x%08X\n",
658                         gpc, gsrc, GjmpPC );
659             #endif
660             break;
661
662          case J_C:
663                if( gc ) Gbranch = 1; 
664                else        Gbranch = 0;
665             #ifdef DEBUG_GPU
666                fprintf( oo, "0x%06X JUMP C,(R%02i)                  DEST = 0x%08X\n",
667                         gpc, gsrc, GjmpPC );
668             #endif
669             break;
670
671          case J_C_NZ:
672                if( gc && !gz ) Gbranch = 1; 
673                else                  Gbranch = 0;
674             #ifdef DEBUG_GPU
675                fprintf( oo, "0x%06X JUMP C_NZ,(R%02i)               DEST = 0x%08X\n",
676                         gpc, gsrc, GjmpPC );
677             #endif
678             break;
679
680          case J_C_Z:
681                if( gc && gz ) Gbranch = 1; 
682                else                 Gbranch = 0;
683             #ifdef DEBUG_GPU
684                fprintf( oo, "0x%06X JUMP C_Z,(R%02i)                DEST = 0x%08X\n",
685                         gpc, gsrc, GjmpPC );
686             #endif
687             break;
688
689          case J_NN:
690             if( !gn ) Gbranch = 1; 
691             else         Gbranch = 0;                     
692             #ifdef DEBUG_GPU
693                fprintf( oo, "0x%06X JUMP NN,(R%02i)                 DEST = 0x%08X\n",
694                         gpc, gsrc, GjmpPC );
695             #endif
696             break;
697
698          case J_NN_NZ:
699             if( !gn && !gz ) Gbranch = 1; 
700             else                   Gbranch = 0;                     
701             #ifdef DEBUG_GPU
702                fprintf( oo, "0x%06X JUMP NN_NZ,(R%02i)              DEST = 0x%08X\n",
703                         gpc, gsrc, GjmpPC );
704             #endif
705             break;
706
707          case J_NN_Z:
708             if( !gn && gz ) Gbranch = 1; 
709             else                  Gbranch = 0;                     
710             #ifdef DEBUG_GPU
711                fprintf( oo, "0x%06X JUMP NN_Z,(R%02i)               DEST = 0x%08X\n",
712                         gpc, gsrc, GjmpPC );
713             #endif
714             break;
715
716          case J_N:
717             if( gn ) Gbranch = 1; 
718             else        Gbranch = 0;
719             #ifdef DEBUG_GPU
720                fprintf( oo, "0x%06X JUMP N,(R%02i)                  DEST = 0x%08X\n",
721                         gpc, gsrc, GjmpPC );
722             #endif
723             break;
724
725          case J_N_NZ:
726             if( gn && !gz ) Gbranch = 1; 
727             else                  Gbranch = 0;
728             #ifdef DEBUG_GPU
729                fprintf( oo, "0x%06X JUMP N_NZ,(R%02i)               DEST = 0x%08X\n",
730                         gpc, gsrc, GjmpPC );
731             #endif
732             break;
733
734          case J_N_Z:
735             if( gn && gz ) Gbranch = 1; 
736             else                 Gbranch = 0;
737             #ifdef DEBUG_GPU
738                fprintf( oo, "0x%06X JUMP N_Z,(R%02i)                DEST = 0x%08X\n",
739                         gpc, gsrc, GjmpPC );
740             #endif
741             break;
742
743          case J_NEVER:
744             Gbranch = 0;
745             #ifdef DEBUG_GPU
746                fprintf( oo, "0x%06X JUMP NEVER (R%02i)              DEST = 0x%08X\n",
747                        gpc, gsrc, GjmpPC );
748             #endif
749             break;
750
751          default:
752             #ifdef DEBUG_GPU
753                fprintf( oo, "Unknown JUMP Condition\n" );
754             #endif
755             break;
756       }
757    }
758
759    void G_LOAD( void )
760    {
761       gst.arb[gdst]  = mem_readword( gst.arb[gsrc] ) << 16;
762       gst.arb[gdst] |= mem_readword( gst.arb[gsrc] + 2 );
763
764       #ifdef DEBUG_GPU
765          fprintf( oo, "0x%06X LOAD (R%i),R%i\t\tR%02i = 0x%08X\n",
766                  gpc, gsrc, gdst, gdst, gst.arb[gdst] );
767       #endif
768    }
769
770    void G_LOAD_14I( void )
771    {
772       sdword tmpW;
773
774       tmpW = gst.arb[0x0E] + (gsrc * 4);
775       gst.arb[gdst]  = mem_readword( tmpW ) << 16;
776       gst.arb[gdst] |= mem_readword( tmpW + 2 );
777
778       #ifdef DEBUG_GPU
779          fprintf( oo, "0x%06X LOAD (R14+%02i),R%i\t\tR%02i = 0x%08X\n",
780                  gpc, gsrc, gdst, gdst, gst.arb[gdst] );
781       #endif
782    }
783
784    void G_LOAD_15I( void )
785    {
786       sdword tmpW;
787
788       tmpW = gst.arb[0x0F] + (gsrc * 4);
789       gst.arb[gdst]  = mem_readword( tmpW ) << 16;
790       gst.arb[gdst] |= mem_readword( tmpW + 2 );
791
792       #ifdef DEBUG_GPU
793          fprintf( oo, "0x%06X LOAD (R15+%02i),R%i\t\tR%02i = 0x%08X\n",
794                  gpc, gsrc, gdst, gdst, gst.arb[gdst] );
795       #endif
796    }
797                
798    void G_LOAD_14R( void )
799    {               
800       sdword tmpW;
801
802       tmpW = gst.arb[0x0E] + gst.arb[gsrc];
803       gst.arb[gdst]  = mem_readword( tmpW ) << 16;
804       gst.arb[gdst] |= mem_readword( tmpW + 2 );
805
806       #ifdef DEBUG_GPU
807          fprintf( oo, "0x%06X LOAD (R14+R%i),R%i\tR%02i = 0x%08X\n",
808                  gpc, gsrc, gdst, gdst, gst.arb[gdst] );
809       #endif
810    }
811
812    void G_LOAD_15R( void )
813    {
814       sdword tmpW;
815
816       // NOTE: Manual seems to indicate that this opcode 
817       // uses Register 14 as the base offset address.
818
819       tmpW = gst.arb[0x0E] + gst.arb[gsrc];
820       gst.arb[gdst]  = mem_readword( tmpW ) << 16;
821       gst.arb[gdst] |= mem_readword( tmpW + 2 );
822
823       #ifdef DEBUG_GPU
824          fprintf( oo, "0x%06X LOAD (R15+R%i),R%i\tR%02i = 0x%08X\n",
825                  gpc, gsrc, gdst, gdst, gst.arb[gdst] );
826       #endif
827    }
828
829    void G_LOADB( void )
830    {
831       if( gst.arb[gsrc] >= 0xF03000 && gst.arb[gsrc] < 0xF04000 )
832       {
833          gst.arb[gdst]  = mem_readword( gst.arb[gsrc] ) << 16;
834          gst.arb[gdst] |= mem_readword( gst.arb[gsrc] + 2 );
835       }
836       else
837          gst.arb[gdst] = mem_readbyte( gst.arb[gsrc] );
838
839       #ifdef DEBUG_GPU
840          fprintf( oo, "0x%06X LOADB (R%i),R%i\t\tR%02i = 0x%08X\n",
841                  gpc, gsrc, gdst, gdst, gst.arb[gdst] );
842       #endif
843    }
844
845    void G_LOADW( void )
846    {
847       if( gst.arb[gsrc] >= 0xF03000 && gst.arb[gsrc] < 0xF04000 )
848       {
849          gst.arb[gdst]  = mem_readword( gst.arb[gsrc] ) << 16;
850          gst.arb[gdst] |= mem_readword( gst.arb[gsrc] + 2 );
851       }
852       else
853          gst.arb[gdst] = mem_readword( gst.arb[gsrc] );
854
855       #ifdef DEBUG_GPU
856          fprintf( oo, "0x%06X LOADW (R%i),R%i\t\tR%02i = 0x%08X\n",
857                  gpc, gsrc, gdst, gdst, gst.arb[gdst] );
858       #endif
859    }
860
861    void G_LOADP( void )
862    {/*
863          phr.hi  = mem_readword( tolp ) << 16;          
864          phr.hi |= mem_readword( tolp + 0x02 );             
865          phr.lo  = mem_readword( tolp + 0x04 ) << 16;       
866          phr.lo |= mem_readword( tolp + 0x06 );             
867 */
868       #ifdef DEBUG_GPU
869          fprintf( oo, "GPU - Unimplemented Opcode (LOADP)\n" );
870       #endif
871
872       gst.gpuActive = FALSE;      
873    }
874
875    void G_MMULT( void )
876    {
877       #ifdef DEBUG_GPU
878          fprintf( oo, "GPU - Unimplemented Opcode (MMULT)\n" );
879       #endif
880       gst.gpuActive = FALSE;      
881    }
882
883    void G_MOVE( void )
884    {
885       gst.arb[gdst] = gst.arb[gsrc];
886
887       #ifdef DEBUG_GPU
888          fprintf( oo, "0x%06X MOVE R%i,R%i\t\tR%02i = 0x%08X\n",
889                  gpc, gsrc, gdst, gdst, gst.arb[gdst] );
890       #endif
891    }
892
893    void G_MOVE_PC( void )
894    {
895       gst.arb[gdst] = gpc;
896
897       #ifdef DEBUG_GPU
898          fprintf( oo, "0x%06X MOVE PC,R%i\t\tR%02i = 0x%08X\n",
899                   gpc, gdst, gdst, gst.arb[gdst] );
900       #endif
901    }
902
903    void G_MOVEFA( void )
904    {
905       gst.arb[gdst] = gst.srb[gsrc];
906
907       #ifdef DEBUG_GPU
908          fprintf( oo, "0x%06X MOVEFA R%i,R%i\t\tR%02i = 0x%08X\n",
909                  gpc, gsrc, gdst, gdst, gst.arb[gdst] );
910       #endif
911    }
912
913    void G_MOVEI( void )
914    {
915       gst.arb[gdst]  = mem_readword(gpc + 2);
916       gst.arb[gdst] |= mem_readword(gpc + 4) << 16;
917                               
918       GincPC = 1;
919
920       #ifdef DEBUG_GPU
921          fprintf( oo, "0x%06X MOVEI 0x%08X,R%i\tR%02i = 0x%08X\n",
922                  gpc, gst.arb[gdst], gdst, gdst, gst.arb[gdst] );
923       #endif
924    }
925
926    void G_MOVEQ( void )
927    {
928       gst.arb[gdst] = gsrc;
929
930       #ifdef DEBUG_GPU
931          fprintf( oo, "0x%06X MOVEQ 0x%02X,R%i\t\tR%02i = 0x%08X\n",
932                  gpc, gsrc, gdst, gdst, gst.arb[gdst] );
933       #endif
934    }
935
936    void G_MOVETA( void )
937    {
938       gst.srb[gdst] = gst.arb[gsrc];
939
940       #ifdef DEBUG_GPU
941          fprintf( oo, "0x%06X MOVETA R%i,R%i\t\tR%02i = 0x%08X(0)\n",
942                  gpc, gsrc, gdst, gdst, gst.srb[gdst] );
943       #endif
944    }
945
946    void G_MTOI( void )
947    {
948       #ifdef DEBUG_GPU
949          fprintf( oo, "GPU - Unimplemented Opcode (MTOI)\n" );
950       #endif
951       gst.gpuActive = FALSE;      
952    }
953
954    void G_MULT( void )
955    {
956       gst.arb[gdst] = (sdword)((word)gst.arb[gsrc] * 
957                                   (word)gst.arb[gdst] );
958
959       gz = (gst.arb[gdst] == 0) ? 1 : 0;
960       gn = (gst.arb[gdst] <  0) ? 1 : 0;
961
962       #ifdef DEBUG_GPU
963          fprintf( oo, "0x%06X MULT R%i,R%i\t\tR%02i = 0x%08X  "
964                  "Z:%i N:%i C:%i\n", gpc, gsrc, gdst, gdst, 
965                  gst.arb[gdst], gz, gn, gc );
966       #endif
967    }
968
969    void G_NEG( void )
970    {
971       __asm {
972          mov   ecx,[gdst]
973          mov   eax,[ecx*4+gst.arb]  
974          neg   eax
975          mov   [ecx*4+gst.arb],eax  
976          mov   ecx,1
977          jc    negend
978          mov   ecx,0
979       negend:
980          mov   [gc],ecx
981       };
982
983       gz = (gst.arb[gdst] == 0) ? 1 : 0;
984       gn = (gst.arb[gdst] <  0) ? 1 : 0;
985
986       #ifdef DEBUG_GPU
987          fprintf( oo, "0x%06X NEG R%i\t\t\tR%02i = 0x%08X  Z:%i N:%i C:%i\n",
988                  gpc, gdst, gdst, gst.arb[gdst],
989                  gz, gn, gc );
990       #endif
991    }
992
993    void G_NOP( void )
994    {
995       #ifdef DEBUG_GPU
996          fprintf( oo, "0x%06X NOP\n", gpc );
997       #endif
998    }
999
1000    void G_NORMI( void )
1001    {
1002       #ifdef DEBUG_GPU
1003          fprintf( oo, "GPU - Unimplemented Opcode (NORMI)\n" );
1004       #endif
1005       gst.gpuActive = FALSE;      
1006    }
1007
1008    void G_NOT( void )                  // Fix donated by YaK
1009    {
1010       gst.arb[gdst] = gst.arb[gdst] ^ 0xFFFFFFFF;
1011       gz = (gst.arb[gdst] == 0) ? 1 : 0;
1012       gn = (gst.arb[gdst] <  0) ? 1 : 0;
1013
1014       #ifdef DEBUG_GPU
1015          fprintf( oo, "0x%06X NOT R%i\t\t\tR%02i = 0x%08X  Z:%i N:%i C:%i\n",
1016                  gpc, gdst, gdst, gst.arb[gdst],
1017                  gz, gn, gc );
1018       #endif
1019    }
1020
1021    void G_OR( void )
1022    {
1023       gst.arb[gdst] |= gst.arb[gsrc];
1024       gz = (gst.arb[gdst] == 0) ? 1 : 0;
1025       gn = (gst.arb[gdst] <  0) ? 1 : 0;
1026
1027       #ifdef DEBUG_GPU
1028          fprintf( oo, "0x%06X OR R%i,R%i\t\tR%02i = 0x%08X  Z:%i N:%i C:%i\n",
1029                  gpc, gsrc, gdst, gdst, gst.arb[gdst],
1030                  gz, gn, gc );
1031       #endif
1032    }
1033
1034    void G_PACK_UNPACK( void )
1035    {
1036       dword tmpW;
1037
1038       tmpW = gst.arb[gdst];
1039
1040       if( gsrc )                    // UNPACK
1041       {
1042          gst.arb[gdst]  = (tmpW & 0x000000FF);
1043          gst.arb[gdst] |= (tmpW & 0x00000F00) << 5;
1044          gst.arb[gdst] |= (tmpW & 0x0000F000) << 10;
1045
1046          #ifdef DEBUG_GPU
1047             fprintf( oo, "0x%06X UNPACK R%i\t\t\tR%02i = 0x%08X\n",
1048                     gpc, gdst, gdst, gst.arb[gdst] );
1049          #endif
1050       }
1051       else                             // PACK
1052       {
1053          gst.arb[gdst]  = (tmpW & 0x000000FF);
1054          gst.arb[gdst] |= (tmpW & 0x0001E000) >> 5;
1055          gst.arb[gdst] |= (tmpW & 0x03C00000) >> 10;
1056
1057          #ifdef DEBUG_GPU
1058             fprintf( oo, "0x%06X PACK R%i\t\t\tR%02i = 0x%08X\n",
1059                     gpc, gdst, gdst, gst.arb[gdst] );
1060          #endif
1061       }
1062    }
1063
1064    void G_RESMAC( void )
1065    {
1066       // Write result register to Register Rn
1067       // Used as last part of multiply/accumulate group.
1068
1069       gst.arb[gdst] = gst.acc;
1070                
1071       #ifdef DEBUG_GPU
1072          fprintf( oo, "0x%06X RESMAC R%i\t\tR%02X = 0x%08X\n",
1073                   gpc, gdst, gdst, gst.arb[gdst] );
1074       #endif
1075    }
1076
1077    void G_ROR( void )
1078    {
1079       gc = (gst.arb[gdst] >> 31) & 0x01;
1080
1081       __asm {
1082          mov   ecx,[gdst]
1083          mov   eax,[ecx*4+gst.arb]
1084          mov   edx,[gsrc]
1085          mov   ecx,[edx*4+gst.arb]
1086          and   ecx,0x1F
1087          ror   eax,cl
1088          mov   ecx,[gdst]
1089          mov   [ecx*4+gst.arb],eax
1090       };
1091
1092       gz = (gst.arb[gdst] == 0) ? 1 : 0;
1093       gn = (gst.arb[gdst] <  0) ? 1 : 0;
1094
1095       #ifdef DEBUG_GPU
1096          fprintf( oo, "0x%06X ROR R%i,R%i\t\tR%02i = 0x%08X  Z:%i N:%i C:%i\n",
1097                  gpc, gsrc, gdst, gdst, gst.arb[gdst],
1098                  gz, gn, gc );
1099       #endif
1100    }
1101
1102    void G_RORQ( void )
1103    {
1104       sdword tmpW;
1105
1106       gc = (gst.arb[gdst] >> 31) & 0x01;
1107       tmpW = gst.arb[gdst];
1108       
1109       __asm {
1110          mov   eax,[tmpW]
1111          mov   ecx,[gsrc]
1112          ror   eax,cl
1113          mov   [tmpW],eax
1114       };
1115
1116       gst.arb[gdst] = tmpW;
1117
1118       gz = (gst.arb[gdst] == 0) ? 1 : 0;
1119       gn = (gst.arb[gdst] <  0) ? 1 : 0;
1120
1121       #ifdef DEBUG_GPU
1122          fprintf( oo, "0x%06X RORQ 0x%02X,R%i\t\tR%02i = 0x%08X  "
1123                  "Z:%i N:%i C:%i\n",
1124                  gpc, gsrc, gdst, gdst, gst.arb[gdst],
1125                  gz, gn, gc );
1126       #endif
1127    }
1128
1129    void G_SAT8( void )
1130    {
1131       if( gst.arb[gdst] < 0   ) gst.arb[gdst] =0x00000000;
1132       if( gst.arb[gdst] > 255 ) gst.arb[gdst] =0x000000FF;
1133
1134       gn = 0;
1135       gz = (gst.arb[gdst] == 0) ? 1 : 0;
1136
1137       #ifdef DEBUG_GPU
1138          fprintf( oo, "0x%06X SAT8 R%02i\t\t\tR%02i = 0x%08X  "
1139                  "Z:%i N:%i C:%i\n",
1140                  gpc, gdst, gdst, gst.arb[gdst],
1141                  gz, gn, gc );
1142       #endif
1143    }
1144
1145    void G_SAT16( void )
1146    {
1147       if( gst.arb[gdst] < 0     ) gst.arb[gdst] =0x00000000;
1148       if( gst.arb[gdst] > 65535 ) gst.arb[gdst] =0x0000FFFF;
1149
1150       gn = 0;
1151       gz = (gst.arb[gdst] == 0) ? 1 : 0;
1152
1153       #ifdef DEBUG_GPU
1154          fprintf( oo, "0x%06X SAT16 R%02i\t\t\tR%02i = 0x%08X  "
1155                  "Z:%i N:%i C:%i\n",
1156                  gpc, gdst, gdst, gst.arb[gdst],
1157                  gz, gn, gc );
1158       #endif
1159    }
1160
1161    void G_SAT24( void )
1162    {
1163       if( gst.arb[gdst] < 0        ) gst.arb[gdst] =0x00000000;
1164       if( gst.arb[gdst] > 16777215 ) gst.arb[gdst] =0x00FFFFFF;
1165
1166       gn = 0;
1167       gz = (gst.arb[gdst] == 0) ? 1 : 0;
1168
1169       #ifdef DEBUG_GPU
1170          fprintf( oo, "0x%06X SAT24 R%02i\t\t\tR%02i = 0x%08X  "
1171                  "Z:%i N:%i C:%i\n",
1172                  gpc, gdst, gdst, gst.arb[gdst],
1173                  gz, gn, gc );
1174       #endif
1175    }
1176
1177    void G_SH( void )
1178    {
1179       sdword tmpW;
1180
1181       // NOTE: Watch the values here carefully
1182
1183       if( gst.arb[gsrc] >= 0 )    // Shift Right
1184       {
1185          gc = gst.arb[gdst] & 0x01;
1186          tmpW = gst.arb[gsrc];
1187          __asm {
1188             mov   edx,[gdst]
1189             mov   eax,[edx*4+gst.arb] 
1190             mov   ecx,[tmpW]
1191             shr   eax,cl
1192             mov   [edx*4+gst.arb],eax 
1193          };
1194       }
1195       else                    // Shift Left
1196       {
1197          gc = (gst.arb[gdst] >> 31) & 0x01;
1198          // Fix donated by YaK
1199          tmpW = (0xFFFFFFFF - gst.arb[gsrc]) + 1;
1200          __asm {
1201             mov   edx,[gdst]
1202             mov   eax,[edx*4+gst.arb] 
1203             mov   ecx,[tmpW]
1204             shl   eax,cl
1205             mov   [edx*4+gst.arb],eax 
1206          };
1207       }
1208
1209       gz = (gst.arb[gdst] == 0) ? 1 : 0;
1210       gn = (gst.arb[gdst] <  0) ? 1 : 0;
1211
1212       #ifdef DEBUG_GPU
1213          fprintf( oo, "0x%06X SH R%i,R%i\t\tR%02i = 0x%08X  "
1214                  "Z:%i N:%i C:%i\n",
1215                  gpc, gsrc, gdst, gdst, gst.arb[gdst],
1216                  gz, gn, gc );
1217       #endif*/
1218    }
1219
1220    void G_SHA( void )
1221    {
1222       sdword tmpW;
1223
1224       // NOTE: Watch the values here carefully
1225
1226       if( gst.arb[gsrc] >= 0 )    // Shift Right
1227       {
1228          gc = gst.arb[gdst] & 0x01;
1229          tmpW = gst.arb[gsrc];
1230          __asm {
1231             mov   edx,[gdst]
1232             mov   eax,[edx*4+gst.arb] 
1233             mov   ecx,[tmpW]
1234             sar   eax,cl
1235             mov   [edx*4+gst.arb],eax 
1236          };
1237       }
1238       else                    // Shift Left
1239       {
1240          gc = (gst.arb[gdst] >> 31) & 0x01;
1241          // Fix donated by YaK
1242          tmpW = (0xFFFFFFFF - gst.arb[gsrc]) + 1;
1243          __asm {
1244             mov   edx,[gdst]
1245             mov   eax,[edx*4+gst.arb] 
1246             mov   ecx,[tmpW]
1247             shl   eax,cl
1248             mov   [edx*4+gst.arb],eax 
1249          };
1250       }
1251
1252       gz = (gst.arb[gdst] == 0) ? 1 : 0;
1253       gn = (gst.arb[gdst] <  0) ? 1 : 0;
1254
1255       #ifdef DEBUG_GPU
1256          fprintf( oo, "0x%06X SHA R%i,R%i\t\tR%02i = 0x%08X  "
1257                  "Z:%i N:%i C:%i\n",
1258                  gpc, gsrc, gdst, gdst, gst.arb[gdst],
1259                  gz, gn, gc );
1260       #endif*/
1261    }
1262
1263    void G_SHARQ( void )
1264    {
1265       sdword tmpW;
1266
1267       gc = (gst.arb[gdst] & 0x01);
1268       tmpW = gst.arb[gdst];
1269       
1270       __asm {
1271          mov   eax,[tmpW]
1272          mov   ecx,[gsrc]
1273          sar   eax,cl
1274          mov   [tmpW],eax
1275       };
1276       
1277       gst.arb[gdst] = tmpW;
1278
1279       gz = (gst.arb[gdst] == 0) ? 1 : 0;
1280       gn = (gst.arb[gdst] <  0) ? 1 : 0;
1281
1282       #ifdef DEBUG_GPU
1283          fprintf( oo, "0x%06X SHARQ 0x%02X,R%i\t\tR%02i = 0x%08X  "
1284                  "Z:%i N:%i C:%i\n", gpc, gsrc, gdst, gdst, 
1285                  gst.arb[gdst], gz, gn, gc );
1286       #endif
1287    }
1288                
1289    void G_SHLQ( void )
1290    {
1291       gc = (gst.arb[gdst] >> 31) & 0x01;
1292       gst.arb[gdst] <<= (32 - gsrc);
1293
1294       gz = (gst.arb[gdst] == 0) ? 1 : 0;
1295       gn = (gst.arb[gdst] <  0) ? 1 : 0;
1296
1297       #ifdef DEBUG_GPU
1298          fprintf( oo, "0x%06X SHLQ 0x%02X,R%i\t\tR%02i = 0x%08X  "
1299                  "Z:%i N:%i C:%i\n", gpc, gsrc, gdst, gdst, 
1300                  gst.arb[gdst], gz, gn, gc );
1301       #endif
1302    }
1303
1304    void G_SHRQ( void )
1305    {
1306       gc = gst.arb[gdst] & 0x01;
1307       gst.arb[gdst] >>= (32 - gsrc);
1308
1309       gz = (gst.arb[gdst] == 0) ? 1 : 0;
1310       gn = (gst.arb[gdst] <  0) ? 1 : 0;
1311
1312       #ifdef DEBUG_GPU
1313          fprintf( oo, "0x%06X SHRQ 0x%02X,R%i\t\tR%02i = 0x%08X  "
1314                  "Z:%i N:%i C:%i\n", gpc, gsrc, gdst, gdst, 
1315                  gst.arb[gdst], gz, gn, gc );
1316       #endif
1317    }
1318                
1319    void G_STORE( void )
1320    {
1321       mem_writeword( gst.arb[gsrc],     (gst.arb[gdst] >> 16)    );
1322       mem_writeword( gst.arb[gsrc] + 2, (gst.arb[gdst] & 0xFFFF) );
1323
1324       #ifdef DEBUG_GPU
1325          fprintf( oo, "0x%06X STORE R%i,(R%i)\t\tgdst = 0x%08X\n",
1326                  gpc, gdst, gsrc, gst.arb[gsrc] );
1327       #endif
1328    }
1329
1330    void G_STORE_14I( void )
1331    {
1332       sdword tmpW;
1333
1334       tmpW = gst.arb[0x0E] + (gsrc * 4);
1335
1336       mem_writeword( tmpW,     (gst.arb[gdst] >> 16)    );
1337       mem_writeword( tmpW + 2, (gst.arb[gdst] & 0xFFFF) );
1338
1339       #ifdef DEBUG_GPU
1340          fprintf( oo, "0x%06X STORE R%i,(R14+%02i)\t\tgdst = 0x%08X\n",
1341                  gpc, gsrc, gdst, tmpW );
1342       #endif
1343    }
1344
1345    void G_STORE_15I( void )
1346    {
1347       sdword tmpW;
1348
1349       tmpW = gst.arb[0x0F] + (gsrc * 4);
1350
1351       mem_writeword( tmpW,     (gst.arb[gdst] >> 16)    );
1352       mem_writeword( tmpW + 2, (gst.arb[gdst] & 0xFFFF) );
1353
1354       #ifdef DEBUG_GPU
1355          fprintf( oo, "0x%06X STORE R%i,(R15+%02i)\t\tgdst = 0x%08X\n",
1356                  gpc, gsrc, gdst, tmpW );
1357       #endif
1358    }
1359
1360    void G_STORE_14R( void )
1361    {
1362       sdword tmpW;
1363
1364       tmpW = gst.arb[0x0E] + gst.arb[gsrc];
1365       mem_writeword( tmpW,     (gst.arb[gdst] >> 16)    );
1366       mem_writeword( tmpW + 2, (gst.arb[gdst] & 0xFFFF) );
1367
1368       #ifdef DEBUG_GPU
1369          fprintf( oo, "0x%06X STORE R%i,(R14+R%i)\tgdst = 0x%08X\n",
1370                   gpc, gdst, gsrc, tmpW );
1371       #endif
1372    }
1373
1374    void G_STORE_15R( void )
1375    {
1376       sdword tmpW;
1377
1378       // NOTE: Manual seems to indicate that this opcode
1379       // uses Register 14 as the base offset address.
1380
1381       tmpW = gst.arb[0x0E] + gst.arb[gsrc];
1382       mem_writeword( tmpW,     (gst.arb[gdst] >> 16)    );
1383       mem_writeword( tmpW + 2, (gst.arb[gdst] & 0xFFFF) );
1384
1385       #ifdef DEBUG_GPU
1386          fprintf( oo, "0x%06X STORE R%i,(R14+R%i)\tgdst = 0x%08X\n",
1387                  gpc, gdst, gsrc, tmpW );
1388       #endif
1389    }
1390
1391    void G_STOREB( void )
1392    {
1393       if( gst.arb[gsrc] >= 0xF03000 && gst.arb[gsrc] < 0xF04000 )
1394       {
1395          mem_writeword( gst.arb[gsrc],     (gst.arb[gdst] >> 16)     );
1396          mem_writeword( gst.arb[gsrc] + 2, (gst.arb[gdst] & 0xFFFF) );
1397       }
1398       else
1399          mem_writebyte( gst.arb[gsrc], (gst.arb[gdst] & 0xFF) );
1400
1401       #ifdef DEBUG_GPU
1402          fprintf( oo, "0x%06X STOREB R%i,(R%i)\tgdst = 0x%08X\n",
1403                  gpc, gdst, gsrc, gsrc );
1404       #endif
1405    }
1406
1407    void G_STOREW( void )
1408    {
1409       if( gst.arb[gsrc] >= 0xF03000 && gst.arb[gsrc] < 0xF04000 )
1410       {
1411          mem_writeword( gst.arb[gsrc],     (gst.arb[gdst] >> 16)     );
1412          mem_writeword( gst.arb[gsrc] + 2, (gst.arb[gdst] & 0xFFFF) );
1413       }
1414       else
1415          mem_writeword( gst.arb[gsrc], (gst.arb[gdst] & 0xFFFF) );
1416
1417       #ifdef DEBUG_GPU
1418          fprintf( oo, "0x%06X STOREW R%i,(R%i)\tgdst = 0x%08X\n",
1419                  gpc, gdst, gsrc, gsrc );
1420       #endif
1421    }
1422
1423    void G_STOREP( void )
1424    {
1425       #ifdef DEBUG_GPU
1426          fprintf( oo, "GPU - Unimplemented Opcode (STOREP)\n" );
1427       #endif
1428       gst.gpuActive = FALSE;      
1429    }
1430
1431    void G_SUB( void )
1432    {
1433       __asm {
1434          mov   ecx,[gsrc]
1435          mov   edx,[ecx*4+gst.arb]  
1436          mov   ecx,[gdst]
1437          mov   eax,[ecx*4+gst.arb]  
1438          sub   eax,edx
1439          mov   [ecx*4+gst.arb],eax  
1440          mov   ecx,1
1441          jc    subend
1442          mov   ecx,0
1443       subend:
1444          mov   [gc],ecx
1445       };
1446
1447       gz = (gst.arb[gdst] == 0) ? 1 : 0;
1448       gn = (gst.arb[gdst] <  0) ? 1 : 0;
1449
1450       #ifdef DEBUG_GPU
1451          fprintf( oo, "0x%06X SUB R%i,R%i\t\tR%02i = 0x%08X  Z:%i N:%i C:%i\n",
1452                  gpc, gsrc, gdst, gdst, gst.arb[gdst],
1453                  gz, gn, gc );
1454       #endif
1455    }
1456
1457    void G_SUBC( void )
1458    {
1459       __asm {
1460          clc
1461          mov   ecx,[gc]
1462          jcxz  subc
1463          stc                     
1464       subc:
1465          mov   ecx,[gsrc]
1466          mov   edx,[ecx*4+gst.arb]
1467          mov   ecx,[gdst]
1468          mov   eax,[ecx*4+gst.arb]
1469          sbb   eax,edx
1470          mov   [ecx*4+gst.arb],eax
1471          mov   ecx,1
1472          jc    subcend
1473          mov   ecx,0
1474       subcend:
1475          mov   [gc],ecx
1476       };
1477
1478       gz = (gst.arb[gdst] == 0) ? 1 : 0;
1479       gn = (gst.arb[gdst] <  0) ? 1 : 0;
1480
1481       #ifdef DEBUG_GPU
1482           fprintf( oo, "0x%06X SUBC R%i,R%i\t\tR%02i = 0x%08X  "
1483                   "Z:%i N:%i C:%i\n", gpc, gsrc, gdst, gdst, 
1484                   gst.arb[gdst], gz, gn, gc );
1485       #endif
1486    }
1487
1488    void G_SUBQ( void )
1489    {
1490       __asm {
1491          mov   ecx,[gdst]
1492          mov   eax,[ecx*4+gst.arb]  
1493          mov   edx,[gsrc]         
1494          sub   eax,edx
1495          mov   [ecx*4+gst.arb],eax
1496          mov   ecx,1
1497          jc    subqend
1498          mov   ecx,0
1499       subqend:
1500          mov   [gc],ecx
1501       };
1502
1503       gz = (gst.arb[gdst] == 0) ? 1 : 0;
1504       gn = (gst.arb[gdst] <  0) ? 1 : 0;
1505
1506       #ifdef DEBUG_GPU
1507          fprintf( oo, "0x%06X SUBQ 0x%02X,R%i\t\tR%02i = 0x%08X  "
1508                  "Z:%i N:%i C:%i\n", gpc, gsrc, gdst, gdst, 
1509                  gst.arb[gdst], gz, gn, gc );
1510       #endif
1511    }
1512
1513    void G_SUBQT( void )
1514    {
1515       __asm {
1516          mov   ecx,[gdst]
1517          mov   eax,[ecx*4+gst.arb]
1518          mov   edx,[gsrc]         
1519          sub   eax,edx
1520          mov   [ecx*4+gst.arb],eax  
1521       };
1522
1523       #ifdef DEBUG_GPU
1524          fprintf( oo, "0x%06X SUBQT 0x%02X,R%i\t\tR%02i = 0x%08X\n",
1525                  gpc, gsrc, gdst, gdst, gst.arb[gdst] );
1526       #endif
1527    }
1528
1529    void G_XOR( void )
1530    {
1531       gst.arb[gdst] ^= gst.arb[gsrc];
1532       gz = (gst.arb[gdst] == 0) ? 1 : 0;
1533       gn = (gst.arb[gdst] <  0) ? 1 : 0;
1534
1535       #ifdef DEBUG_GPU
1536          fprintf( oo, "0x%06X XOR R%i,R%i\t\tR%02i = 0x%08X  Z:%i N:%i C:%i\n",
1537                  gpc, gsrc, gdst, gdst, gst.arb[gdst],
1538                  gz, gn, gc );
1539       #endif
1540    }