home *** CD-ROM | disk | FTP | other *** search
/ ST-Computer Leser 2002 January / STC_CD_01_2002.iso / JAGUAR / JAG_SRC / SOURCE / GPU.C < prev    next >
C/C++ Source or Header  |  2001-08-11  |  45KB  |  1,541 lines

  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.    }
  1541.