home *** CD-ROM | disk | FTP | other *** search
/ ST-Computer Leser 2002 January / STC_CD_01_2002.iso / JAGUAR / JAG_SRC / SOURCE / DSP.C < prev    next >
C/C++ Source or Header  |  2001-07-13  |  29KB  |  817 lines

  1. ////////////////////////////////////////////////////////////////////////////////
  2. // Jagulator: Atari Jaguar Console Emulation Project (dsp.c)
  3. // -----------------------------------------------------------------------------
  4. // Jagulator is the Copyright (c) RealityMan 1998-2001 and is provided "as is" 
  5. // without any expressed or implied warranty. I have no Trademarks, Legal or 
  6. // otherwise. Atari, Jaguar and the Atari Logo are copyright Hasbro Inc. All 
  7. // other Copyrights and Trademarks are acknowledged. This project is in no way 
  8. // linked to Atari/Hasbro or other associated Atari companies.                
  9. //
  10. // 07-07-2001 GH: New Source, Rewritten for Release 1.5.0
  11. // 00-00-0000 GH: All Previous Source Considered as Development Code Only
  12.  
  13. #include "core.h"
  14.  
  15. ////////////////////////////////////////////////////////////////////////////////
  16. // Globals
  17.  
  18.    DSPSTATE dst;                       // DSP State Information
  19.    dword DincPC;                       // PC Increment Flag
  20.    dword DjmpPC;                       // PC Jump dst.destination
  21.    dword Dbranch;                      // Branch Flag
  22.  
  23. ////////////////////////////////////////////////////////////////////////////////
  24. // DSP Processor Emulation
  25.  
  26.    DWORD ExecDSP( LPVOID lpParam )
  27.    {
  28.       dword iw;                        // Instruction Word
  29.       sdword tmpW;
  30.  
  31.       // The DSP Program Counter is directly set via the memory routines
  32.       // so it does not explicitly need to be obtained here.
  33.  
  34.       while( dst.dspActive )
  35.       {
  36.  
  37.          iw = mem_readword( dst.pc ); 
  38.          dst.src = (iw & 0x03E0) >> 5;  // Get Source
  39.          dst.dest = (iw & 0x001F);       // Get Destination
  40.  
  41.          switch( iw >> 10 )
  42.          {
  43.             case ADD:
  44.                __asm {
  45.                   mov   ecx,[dst.src]
  46.                   mov   edx,[ecx*4+dst.arb]
  47.                   mov   ecx,[dst.dest]
  48.                   mov   eax,[ecx*4+dst.arb]
  49.                   add   eax,edx
  50.                   mov   [ecx*4+dst.arb],eax
  51.                   mov   ecx,1
  52.                   jc    d_addend
  53.                   mov   ecx,0
  54.                d_addend:
  55.                   mov   [dst.c],ecx
  56.                };
  57.  
  58.                dst.z = (dst.arb[dst.dest] == 0) ? 1 : 0;
  59.                dst.n = (dst.arb[dst.dest] <  0) ? 1 : 0;
  60.                break;
  61.  
  62.             case ADDC:
  63.                __asm {
  64.                   clc
  65.                   mov   ecx,[dst.c]
  66.                   jcxz  d_addc
  67.                   stc                     
  68.                d_addc:
  69.                   mov   ecx,[dst.src]
  70.                   mov   edx,[ecx*4+dst.arb]  
  71.                   mov   ecx,[dst.dest]
  72.                   mov   eax,[ecx*4+dst.arb]  
  73.                   adc   eax,edx
  74.                   mov   [ecx*4+dst.arb],eax  
  75.                   mov   ecx,1
  76.                   jc    d_addcend
  77.                   mov   ecx,0
  78.                d_addcend:
  79.                   mov   [dst.c],ecx
  80.                };
  81.          
  82.                dst.z = (dst.arb[dst.dest] == 0) ? 1 : 0;
  83.                dst.n = (dst.arb[dst.dest] <  0) ? 1 : 0;
  84.                break;
  85.  
  86.             case ADDQ:
  87.                __asm {
  88.                   mov   ecx,[dst.dest]
  89.                   mov   eax,[ecx*4+dst.arb]
  90.                   mov   edx,[dst.src]         
  91.                   add   eax,edx
  92.                   mov   [ecx*4+dst.arb],eax
  93.                   mov   ecx,1
  94.                   jc    d_addqend
  95.                   mov   ecx,0
  96.                d_addqend:
  97.                   mov   [dst.c],ecx
  98.                };
  99.          
  100.                dst.z = (dst.arb[dst.dest] == 0) ? 1 : 0;
  101.                dst.n = (dst.arb[dst.dest] <  0) ? 1 : 0;
  102.                break;
  103.  
  104.             case ADDQT:
  105.                __asm {
  106.                   mov   ecx,[dst.dest]
  107.                   mov   eax,[ecx*4+dst.arb]  
  108.                   mov   edx,[dst.src]        
  109.                   add   eax,edx
  110.                   mov   [ecx*4+dst.arb],eax  
  111.                };
  112.                break;
  113.  
  114.             case SUB:
  115.                __asm {
  116.                   mov   ecx,[dst.src]
  117.                   mov   edx,[ecx*4+dst.arb]  
  118.                   mov   ecx,[dst.dest]
  119.                   mov   eax,[ecx*4+dst.arb]  
  120.                   sub   eax,edx
  121.                   mov   [ecx*4+dst.arb],eax  
  122.                   mov   ecx,1
  123.                   jc    d_subend
  124.                   mov   ecx,0
  125.                d_subend:
  126.                   mov   [dst.c],ecx
  127.                };
  128.  
  129.                dst.z = (dst.arb[dst.dest] == 0) ? 1 : 0;
  130.                dst.n = (dst.arb[dst.dest] <  0) ? 1 : 0;
  131.                break;
  132.  
  133.             case SUBC:
  134.                __asm {
  135.                   clc
  136.                   mov   ecx,[dst.c]
  137.                   jcxz  d_subc
  138.                   stc                     
  139.                d_subc:
  140.                   mov   ecx,[dst.src]
  141.                   mov   edx,[ecx*4+dst.arb]
  142.                   mov   ecx,[dst.dest]
  143.                   mov   eax,[ecx*4+dst.arb]
  144.                   sbb   eax,edx
  145.                   mov   [ecx*4+dst.arb],eax
  146.                   mov   ecx,1
  147.                   jc    d_subcend
  148.                   mov   ecx,0
  149.                d_subcend:
  150.                   mov   [dst.c],ecx
  151.                };
  152.    
  153.                dst.z = (dst.arb[dst.dest] == 0) ? 1 : 0;
  154.                dst.n = (dst.arb[dst.dest] <  0) ? 1 : 0;
  155.                break;
  156.  
  157.             case SUBQ:
  158.                __asm {
  159.                   mov   ecx,[dst.dest]
  160.                   mov   eax,[ecx*4+dst.arb]  
  161.                   mov   edx,[dst.src]         
  162.                   sub   eax,edx
  163.                   mov   [ecx*4+dst.arb],eax
  164.                   mov   ecx,1
  165.                   jc    d_subqend
  166.                   mov   ecx,0
  167.                d_subqend:
  168.                   mov   [dst.c],ecx
  169.                };
  170.  
  171.                dst.z = (dst.arb[dst.dest] == 0) ? 1 : 0;
  172.                dst.n = (dst.arb[dst.dest] <  0) ? 1 : 0;
  173.                break;
  174.  
  175.             case SUBQT:
  176.                __asm {
  177.                   mov   ecx,[dst.dest]
  178.                   mov   eax,[ecx*4+dst.arb]
  179.                   mov   edx,[dst.src]         
  180.                   sub   eax,edx
  181.                   mov   [ecx*4+dst.arb],eax  
  182.                };
  183.                break;
  184.  
  185.             case NEG:
  186.                __asm {
  187.                   mov   ecx,[dst.dest]
  188.                   mov   eax,[ecx*4+dst.arb]  
  189.                   neg   eax
  190.                   mov   [ecx*4+dst.arb],eax  
  191.                   mov   ecx,1
  192.                   jc    d_negend
  193.                   mov   ecx,0
  194.                d_negend:
  195.                   mov   [dst.c],ecx
  196.                };
  197.  
  198.                dst.z = (dst.arb[dst.dest] == 0) ? 1 : 0;
  199.                dst.n = (dst.arb[dst.dest] <  0) ? 1 : 0;
  200.                break;
  201.  
  202.             case AND:
  203.                dst.arb[dst.dest] &= dst.arb[dst.src];
  204.                dst.z = (dst.arb[dst.dest] == 0) ? 1 : 0;
  205.                dst.n = (dst.arb[dst.dest] <  0) ? 1 : 0;
  206.                break;
  207.  
  208.             case OR:
  209.                dst.arb[dst.dest] |= dst.arb[dst.src];
  210.                dst.z = (dst.arb[dst.dest] == 0) ? 1 : 0;
  211.                dst.n = (dst.arb[dst.dest] <  0) ? 1 : 0;
  212.                break;
  213.  
  214.             case XOR:
  215.                dst.arb[dst.dest] ^= dst.arb[dst.src];
  216.                dst.z = (dst.arb[dst.dest] == 0) ? 1 : 0;
  217.                dst.n = (dst.arb[dst.dest] <  0) ? 1 : 0;
  218.                break;
  219.  
  220.             case NOT:
  221.                dst.arb[dst.dest] = dst.arb[dst.dest] ^ 0xFFFFFFFF;
  222.                dst.z = (dst.arb[dst.dest] == 0) ? 1 : 0;
  223.                dst.n = (dst.arb[dst.dest] <  0) ? 1 : 0;
  224.                break;
  225.  
  226.             case BTST:
  227.                __asm {
  228.                   mov   ecx,[dst.dest]
  229.                   mov   eax,[ecx*4+dst.arb] 
  230.                   mov   ecx,[dst.src]
  231.                   bt    eax,ecx           
  232.                   mov   ecx,1
  233.                   jc    d_btstend
  234.                   mov   ecx,0
  235.                d_btstend:
  236.                   mov   [dst.z],ecx
  237.                };
  238.                break;
  239.  
  240.             case BSET:
  241.                __asm {
  242.                   mov   ecx,[dst.dest]
  243.                   mov   eax,[ecx*4+dst.arb]  
  244.                   mov   edx,[dst.src]
  245.                   bts   eax,edx          
  246.                   mov   [ecx*4+dst.arb],eax 
  247.                };
  248.  
  249.                dst.z = (dst.arb[dst.dest] == 0) ? 1 : 0;
  250.                dst.n = (dst.arb[dst.dest] <  0) ? 1 : 0;
  251.                break;
  252.  
  253.             case BCLR:
  254.                __asm {
  255.                   mov   ecx,[dst.dest]
  256.                   mov   eax,[ecx*4+dst.arb]
  257.                   mov   edx,[dst.src]
  258.                   btr   eax,edx           
  259.                   mov   [ecx*4+dst.arb],eax 
  260.                };
  261.  
  262.                dst.z = (dst.arb[dst.dest] == 0) ? 1 : 0;
  263.                dst.n = (dst.arb[dst.dest] <  0) ? 1 : 0;
  264.                break;
  265.  
  266.             case MULT:
  267.                dst.arb[dst.dest] = (sdword)((word)dst.arb[dst.src] * 
  268.                                             (word)dst.arb[dst.dest] );
  269.  
  270.                dst.z = (dst.arb[dst.dest] == 0) ? 1 : 0;
  271.                dst.n = (dst.arb[dst.dest] <  0) ? 1 : 0;
  272.                break;
  273.  
  274.             case IMULT:
  275.                dst.arb[dst.dest] = (sdword)((sword)dst.arb[dst.src] * 
  276.                                            (sword)dst.arb[dst.dest] );
  277.  
  278.                dst.z = (dst.arb[dst.dest] == 0) ? 1 : 0;
  279.                dst.n = (dst.arb[dst.dest] <  0) ? 1 : 0;
  280.                break;
  281.  
  282.             case IMULTN:
  283.                // Like IMULT but result not written back to dst.arb[dst.dest]
  284.                // but to an accumulator. Used as first part of multiply/accumulate group.
  285.                dst.acc = (sdword)((sword)dst.arb[dst.src] * 
  286.                                   (sword)dst.arb[dst.dest] );
  287.  
  288.                dst.z = (dst.arb[dst.dest] == 0) ? 1 : 0;
  289.                dst.n = (dst.arb[dst.dest] <  0) ? 1 : 0;
  290.                break;
  291.  
  292.             case RESMAC:
  293.                // Write result register to Register Rn
  294.                // Used as last part of multiply/accumulate group.
  295.                dst.arb[dst.dest] = dst.acc;
  296.                break;
  297.  
  298.             case IMACN:
  299.                // Like IMULT but product is added to the previous arithmetic operation.
  300.                // Intended to be used after IMULTN.
  301.                dst.acc += (sdword)((sword)dst.arb[dst.src] * 
  302.                                    (sword)dst.arb[dst.dest] );
  303.                break;
  304.  
  305.             case DIV:
  306.                if( dst.div16 )
  307.                {
  308.                   #ifdef DEBUG
  309.                   print( YEL"DSP DIVIDE 16.16 REQUIRED !!!!\n" );
  310.                   #endif
  311.                }
  312.                else
  313.                {
  314.                   (dword)dst.arb[dst.dest] = (dword)dst.arb[dst.dest] / 
  315.                                              (dword)dst.arb[dst.src];
  316.  
  317.                   dst.divrem = (dword)dst.arb[dst.dest] % (dword)dst.arb[dst.src];
  318.                }
  319.                break;
  320.  
  321.             case ABS:
  322.                if( dst.arb[dst.dest] == 0x80000000 )
  323.                   dst.n = 1;
  324.                else
  325.                {
  326.                   if( dst.arb[dst.dest] < 0 )
  327.                   {
  328.                      __asm {
  329.                         mov   ecx,[dst.dest]
  330.                         mov   eax,[ecx*4+dst.arb]  
  331.                         neg   eax
  332.                         mov   [ecx*4+dst.arb],eax  
  333.                      };
  334.  
  335.                      dst.z = (dst.arb[dst.dest] == 0) ? 1 : 0;
  336.                      dst.n = 0;
  337.                      dst.c = 1;
  338.                   }
  339.                }
  340.                break;
  341.  
  342.             case SH:
  343.                // NOTE: Watch the values here carefully
  344.                if( dst.arb[dst.src] >= 0 )    // Shift Right
  345.                {
  346.                   dst.c = dst.arb[dst.dest] & 0x01;
  347.                   tmpW = dst.arb[dst.src];
  348.                   __asm {
  349.                      mov   edx,[dst.dest]
  350.                      mov   eax,[edx*4+dst.arb] 
  351.                      mov   ecx,[tmpW]
  352.                      shr   eax,cl
  353.                      mov   [edx*4+dst.arb],eax 
  354.                   };
  355.                }
  356.                else                    // Shift Left
  357.                {
  358.                   dst.c = (dst.arb[dst.dest] >> 31) & 0x01;
  359.                   // Fix donated by YaK
  360.                   tmpW = (0xFFFFFFFF - dst.arb[dst.src]) + 1;
  361.                   __asm {
  362.                      mov   edx,[dst.dest]
  363.                      mov   eax,[edx*4+dst.arb] 
  364.                      mov   ecx,[tmpW]
  365.                      shl   eax,cl
  366.                      mov   [edx*4+dst.arb],eax 
  367.                   };
  368.                }
  369.          
  370.                dst.z = (dst.arb[dst.dest] == 0) ? 1 : 0;
  371.                dst.n = (dst.arb[dst.dest] <  0) ? 1 : 0;
  372.                break;
  373.  
  374.             case SHLQ:
  375.                dst.c = (dst.arb[dst.dest] >> 31) & 0x01;
  376.                dst.arb[dst.dest] <<= (32 - dst.src);
  377.  
  378.                dst.z = (dst.arb[dst.dest] == 0) ? 1 : 0;
  379.                dst.n = (dst.arb[dst.dest] <  0) ? 1 : 0;
  380.                break;
  381.  
  382.             case SHRQ:
  383.                dst.c = dst.arb[dst.dest] & 0x01;
  384.                dst.arb[dst.dest] >>= (32 - dst.src);
  385.  
  386.                dst.z = (dst.arb[dst.dest] == 0) ? 1 : 0;
  387.                dst.n = (dst.arb[dst.dest] <  0) ? 1 : 0;
  388.                break;
  389.  
  390.             case SHA:
  391.                // NOTE: Watch the values here carefully
  392.  
  393.                if( dst.arb[dst.src] >= 0 )    // Shift Right
  394.                {
  395.                   dst.c = dst.arb[dst.dest] & 0x01;
  396.                   tmpW = dst.arb[dst.src];
  397.                   __asm {
  398.                      mov   edx,[dst.dest]
  399.                      mov   eax,[edx*4+dst.arb] 
  400.                      mov   ecx,[tmpW]
  401.                      sar   eax,cl
  402.                      mov   [edx*4+dst.arb],eax 
  403.                   };
  404.                }
  405.                else                    // Shift Left
  406.                {
  407.                   dst.c = (dst.arb[dst.dest] >> 31) & 0x01;
  408.                   // Fix donated by YaK
  409.                   tmpW = (0xFFFFFFFF - dst.arb[dst.src]) + 1;
  410.                   __asm {
  411.                      mov   edx,[dst.dest]
  412.                      mov   eax,[edx*4+dst.arb] 
  413.                      mov   ecx,[tmpW]
  414.                      shl   eax,cl
  415.                      mov   [edx*4+dst.arb],eax 
  416.                   };
  417.                }
  418.          
  419.                dst.z = (dst.arb[dst.dest] == 0) ? 1 : 0;
  420.                dst.n = (dst.arb[dst.dest] <  0) ? 1 : 0;
  421.                break;
  422.  
  423.             case SHARQ:
  424.                dst.c = (dst.arb[dst.dest] & 0x01);
  425.                tmpW = dst.arb[dst.dest];
  426.       
  427.                __asm {
  428.                   mov   eax,[tmpW]
  429.                   mov   ecx,[dst.src]
  430.                   sar   eax,cl
  431.                   mov   [tmpW],eax
  432.                };
  433.       
  434.                dst.arb[dst.dest] = tmpW;
  435.  
  436.                dst.z = (dst.arb[dst.dest] == 0) ? 1 : 0;
  437.                dst.n = (dst.arb[dst.dest] <  0) ? 1 : 0;
  438.                break;
  439.  
  440.             case ROR:            
  441.                dst.c = (dst.arb[dst.dest] >> 31) & 0x01;
  442.  
  443.                __asm {
  444.                   mov   ecx,[dst.dest]
  445.                   mov   eax,[ecx*4+dst.arb]
  446.                   mov   edx,[dst.src]
  447.                   mov   ecx,[edx*4+dst.arb]
  448.                   and   ecx,0x1F
  449.                   ror   eax,cl
  450.                   mov   ecx,[dst.dest]
  451.                   mov   [ecx*4+dst.arb],eax
  452.                };
  453.  
  454.                dst.z = (dst.arb[dst.dest] == 0) ? 1 : 0;
  455.                dst.n = (dst.arb[dst.dest] <  0) ? 1 : 0;
  456.                break;
  457.  
  458.             case RORQ:
  459.                dst.c = (dst.arb[dst.dest] >> 31) & 0x01;
  460.                tmpW = dst.arb[dst.dest];
  461.       
  462.                __asm {
  463.                   mov   eax,[tmpW]
  464.                   mov   ecx,[dst.src]
  465.                   ror   eax,cl
  466.                   mov   [tmpW],eax
  467.                };
  468.  
  469.                dst.arb[dst.dest] = tmpW;
  470.    
  471.                dst.z = (dst.arb[dst.dest] == 0) ? 1 : 0;
  472.                dst.n = (dst.arb[dst.dest] <  0) ? 1 : 0;
  473.                break;
  474.  
  475.             case CMP:
  476.                __asm {
  477.                   mov   ecx,[dst.src]
  478.                   mov   edx,[ecx*4+dst.arb]  
  479.                   mov   ecx,[dst.dest]
  480.                   mov   eax,[ecx*4+dst.arb]  
  481.                   sub   eax,edx
  482.                   lahf                    
  483.                   mov   [tmpW],eax
  484.                };
  485.  
  486.                dst.c = (tmpW & 0x0100) ? 1 : 0;
  487.                dst.z = (tmpW & 0x4000) ? 1 : 0;
  488.                dst.n = (tmpW & 0x8000) ? 1 : 0;
  489.                break;
  490.  
  491.             case CMPQ:
  492.                __asm {
  493.                   mov   edx,[dst.src]
  494.                   bt    edx,4
  495.                   jnc   d_cmpq
  496.                   bts   edx,31
  497.                d_cmpq:
  498.                   mov   ecx,[dst.dest]
  499.                   mov   eax,[ecx*4+dst.arb]  
  500.                   sub   eax,edx
  501.                   lahf                    
  502.                   mov   [tmpW],eax
  503.                };
  504.  
  505.                dst.c = (tmpW & 0x0100) ? 1 : 0;
  506.                dst.z = (tmpW & 0x4000) ? 1 : 0;
  507.                dst.n = (tmpW & 0x8000) ? 1 : 0;
  508.                break;
  509.  
  510.             case SUBQMOD:
  511.                #ifdef DEBUG
  512.                error( "DSP - Invalid Opcode (SUBQMOD)" );
  513.                #endif
  514.                break;
  515.  
  516.             case SAT16S:
  517.                #ifdef DEBUG
  518.                error( "DSP - Invalid Opcode (SAT16S)" );
  519.                #endif
  520.                break;
  521.  
  522.             case MOVE:
  523.                dst.arb[dst.dest] = dst.arb[dst.src];
  524.                break;
  525.  
  526.             case MOVEQ:
  527.                dst.arb[dst.dest] = dst.src;
  528.                break;
  529.  
  530.             case MOVETA:
  531.                dst.srb[dst.dest] = dst.arb[dst.src];
  532.                break;
  533.  
  534.             case MOVEFA:
  535.                dst.arb[dst.dest] = dst.srb[dst.src];
  536.                break;
  537.  
  538.             case MOVEI:
  539.                dst.arb[dst.dest]  = mem_readword(dst.pc + 2);
  540.                dst.arb[dst.dest] |= mem_readword(dst.pc + 4) << 16;
  541.  
  542.                DincPC = 1;
  543.                break;
  544.  
  545.             case LOADB:
  546.                if( dst.arb[dst.src] >= 0xF1B000 && dst.arb[dst.src] < 0xF1D000 )
  547.                {
  548.                   dst.arb[dst.dest]  = mem_readword( dst.arb[dst.src] ) << 16;
  549.                   dst.arb[dst.dest] |= mem_readword( dst.arb[dst.src] + 2 );
  550.                }
  551.                else
  552.                   dst.arb[dst.dest] = mem_readbyte( dst.arb[dst.src] );
  553.                break;
  554.  
  555.             case LOADW:
  556.                if( dst.arb[dst.src] >= 0xF1B000 && dst.arb[dst.src] < 0xF1D000 )
  557.                {
  558.                   dst.arb[dst.dest]  = mem_readword( dst.arb[dst.src] ) << 16;
  559.                   dst.arb[dst.dest] |= mem_readword( dst.arb[dst.src] + 2 );
  560.                }
  561.                else
  562.                   dst.arb[dst.dest] = mem_readword( dst.arb[dst.src] );
  563.                break;
  564.  
  565.             case LOAD:
  566.                dst.arb[dst.dest]  = mem_readword( dst.arb[dst.src] ) << 16;
  567.                dst.arb[dst.dest] |= mem_readword( dst.arb[dst.src] + 2 );
  568.                break;
  569.  
  570.             case SAT32S:
  571.                #ifdef DEBUG
  572.                error( "DSP - Invalid Opcode (SAT32S)" );
  573.                #endif
  574.                break;
  575.  
  576.             case LOAD_14I:
  577.                tmpW = dst.arb[0x0E] + (dst.src * 4);
  578.                dst.arb[dst.dest]  = mem_readword( tmpW ) << 16;
  579.                dst.arb[dst.dest] |= mem_readword( tmpW + 2 );
  580.                break;
  581.  
  582.             case LOAD_15I:
  583.                tmpW = dst.arb[0x0F] + (dst.src * 4);
  584.                dst.arb[dst.dest]  = mem_readword( tmpW ) << 16;
  585.                dst.arb[dst.dest] |= mem_readword( tmpW + 2 );
  586.                break;
  587.  
  588.             case STOREB:
  589.                if( dst.arb[dst.src] >= 0xF1B000 && dst.arb[dst.src] < 0xF1D000 )
  590.                {
  591.                   mem_writeword( dst.arb[dst.src],     (dst.arb[dst.dest] >> 16)     );
  592.                   mem_writeword( dst.arb[dst.src] + 2, (dst.arb[dst.dest] & 0xFFFF) );
  593.                }
  594.                else
  595.                   mem_writebyte( dst.arb[dst.src], (dst.arb[dst.dest] & 0xFF) );
  596.                break;
  597.  
  598.             case STOREW:
  599.                if( dst.arb[dst.src] >= 0xF1B000 && dst.arb[dst.src] < 0xF1D000 )
  600.                {
  601.                   mem_writeword( dst.arb[dst.src],     (dst.arb[dst.dest] >> 16)     );
  602.                   mem_writeword( dst.arb[dst.src] + 2, (dst.arb[dst.dest] & 0xFFFF) );
  603.                }
  604.                else
  605.                   mem_writeword( dst.arb[dst.src], (dst.arb[dst.dest] & 0xFFFF) );
  606.                break;
  607.  
  608.             case STORE:
  609.                mem_writeword( dst.arb[dst.src],     (dst.arb[dst.dest] >> 16)    );
  610.                mem_writeword( dst.arb[dst.src] + 2, (dst.arb[dst.dest] & 0xFFFF) );
  611.                break;
  612.  
  613.             case MIRROR:
  614.                #ifdef DEBUG
  615.                error( "DSP - Invalid Opcode (MIRROR)" );
  616.                #endif
  617.                break;
  618.  
  619.             case STORE_14I:
  620.                tmpW = dst.arb[0x0E] + (dst.src * 4);
  621.          
  622.                mem_writeword( tmpW,     (dst.arb[dst.dest] >> 16)    );
  623.                mem_writeword( tmpW + 2, (dst.arb[dst.dest] & 0xFFFF) );
  624.                break;
  625.  
  626.             case STORE_15I:
  627.                tmpW = dst.arb[0x0F] + (dst.src * 4);
  628.          
  629.                mem_writeword( tmpW,     (dst.arb[dst.dest] >> 16)    );
  630.                mem_writeword( tmpW + 2, (dst.arb[dst.dest] & 0xFFFF) );
  631.                break;
  632.  
  633.             case MOVE_PC:
  634.                dst.arb[dst.dest] = dst.pc;
  635.                break;
  636.  
  637.             case JUMP:
  638.                DjmpPC = dst.arb[dst.src];
  639.  
  640.                switch( dst.dest )
  641.                {
  642.                   case 0:              // No Conditions
  643.                      Dbranch = 1;
  644.                      break;
  645.                   case 1:              // NE - Not Equal
  646.                      if( !dst.z )  // Zero Flag Unset
  647.                         Dbranch = 1;
  648.                      break;
  649.                   case 2:              // EQ - Equal
  650.                      if( dst.z)        // Zero Flag Set
  651.                         Dbranch = 1;
  652.                      break;
  653.                   case 4:                    // Flag Selected Cleared to Jump
  654.                      if( dst.dest & 0x10 )    // Negative Flag
  655.                         if( !dst.n ) Dbranch = 1; else Dbranch = 0;
  656.                      else                    // Carry Flag
  657.                         if( !dst.c ) Dbranch = 1; else Dbranch = 0;
  658.                      break;
  659.                   case 8:                    // Flag Selected Set to Jump
  660.                      if( dst.dest & 0x10 )    // Negative Flag
  661.                      {
  662.                         if( dst.n ) Dbranch = 1; else Dbranch = 0;
  663.                      }
  664.                      else                    // Carry Flag
  665.                      {
  666.                         if( dst.c ) Dbranch = 1; else Dbranch = 0;
  667.                      }
  668.                      break;
  669.                   case 0x14:
  670.                      if( !dst.n ) Dbranch = 1; else Dbranch = 0;                     
  671.                      break;
  672.                   case 0x18:
  673.                      if( dst.n ) Dbranch = 1; else Dbranch = 0;
  674.                      break;
  675.                   default:
  676.                      #ifdef DEBUG
  677.                      print( "Unknown JUMP Condition\n" );
  678.                      #endif
  679.                      break;
  680.                }
  681.                break;
  682.  
  683.             case JR:
  684.                if( dst.src >= 16 )         // Set Jump Direction
  685.                   dst.src -= 32;
  686.  
  687.                DjmpPC = (dst.pc + 2) + (dst.src * 2);
  688.          
  689.                switch( dst.dest )
  690.                {
  691.                   case 0x00:           // No Conditions
  692.                      Dbranch = 1;
  693.                      break;
  694.                   case 0x01:           // NE - Not Equal
  695.                      if( !dst.z )  // Zero Flag Unset
  696.                         Dbranch = 1;
  697.                      break;
  698.                   case 0x02:           // EQ - Equal
  699.                      if( dst.z)    // Zero Flag Set
  700.                         Dbranch = 1;
  701.                      break;
  702.                   case 0x04:           // Flag Selected Cleared to Jump
  703.                      if( !dst.c ) Dbranch = 1; else Dbranch = 0;
  704.                      break;
  705.                   case 0x08:           // Flag Selected Set to Jump
  706.                      if( dst.c ) Dbranch = 1; else Dbranch = 0;
  707.                      break;
  708.                   case 0x14:
  709.                      if( !dst.n ) Dbranch = 1; else Dbranch = 0;
  710.                      break;
  711.                   case 0x18:
  712.                      if( dst.n ) Dbranch = 1; else Dbranch = 0;
  713.                      break;
  714.                   default:
  715.                      #ifdef DEBUG
  716.                      print( "Unknown JR Condition at 0x%08X\n", dst.pc );
  717.                      #endif
  718.                      break;
  719.                }
  720.                break;
  721.  
  722.             case MMULT:
  723.                #ifdef DEBUG
  724.                error( "DSP - Invalid Opcode (MMULT)" );
  725.                #endif
  726.                break;
  727.  
  728.             case MTOI:
  729.                #ifdef DEBUG
  730.                error( "DSP - Invalid Opcode (MTOI)" );
  731.                #endif
  732.                break;
  733.  
  734.             case NORMI:
  735.                #ifdef DEBUG
  736.                error( "DSP - Invalid Opcode (NORMI)" );
  737.                #endif
  738.                break;
  739.  
  740.             case NOP:
  741.                break;
  742.  
  743.             case LOAD_14R:
  744.                tmpW = dst.arb[0x0E] + dst.arb[dst.src];
  745.                dst.arb[dst.dest]  = mem_readword( tmpW ) << 16;
  746.                dst.arb[dst.dest] |= mem_readword( tmpW + 2 );
  747.                break;
  748.  
  749.             case LOAD_15R:
  750.                // NOTE: Manual seems to indicate that this opcode 
  751.                // uses Register 14 as the base offset address.
  752.          
  753.                tmpW = dst.arb[0x0E] + dst.arb[dst.src];
  754.                dst.arb[dst.dest]  = mem_readword( tmpW ) << 16;
  755.                dst.arb[dst.dest] |= mem_readword( tmpW + 2 );
  756.                break;
  757.  
  758.             case STORE_14R:
  759.                tmpW = dst.arb[0x0E] + dst.arb[dst.src];
  760.                mem_writeword( tmpW,     (dst.arb[dst.dest] >> 16)    );
  761.                mem_writeword( tmpW + 2, (dst.arb[dst.dest] & 0xFFFF) );
  762.                break;
  763.  
  764.             case STORE_15R:
  765.                // NOTE: Manual seems to indicate that this opcode
  766.                // uses Register 14 as the base offset address.
  767.  
  768.                tmpW = dst.arb[0x0E] + dst.arb[dst.src];
  769.                mem_writeword( tmpW,     (dst.arb[dst.dest] >> 16)    );
  770.                mem_writeword( tmpW + 2, (dst.arb[dst.dest] & 0xFFFF) );
  771.                break;
  772.  
  773.             case ADDQMOD:
  774.                #ifdef DEBUG
  775.                error( "DSP - Invalid Opcode (ADDQMOD)" );
  776.                #endif
  777.                break;
  778.  
  779.             default:
  780.                #ifdef DEBUG
  781.                error( "DSP - Invalid Opcode" );
  782.                #endif
  783.                dst.dspActive = FALSE;
  784.                break;
  785.          }
  786.  
  787.          switch( Dbranch )             // Increment Program Counter
  788.          {
  789.             case 2:                    // Next Instruction is the Branch Address
  790.                Dbranch = 0;
  791.                dst.pc = DjmpPC;
  792.                break;
  793.          
  794.             // A Branch Address was Stored in the Branch Program Counter.
  795.             // The Next Instruction is a PC + 4 (Case 0 is Executed).
  796.             // The Next Instruction is at the Branch Program Counter
  797.  
  798.             case 1:
  799.                Dbranch = 2;
  800.             case 0:                    // Normal Execution
  801.                switch( DincPC )
  802.                {
  803.                   case 1:              // Opcode Used a 32-Bit Word
  804.                      dst.pc += 6;
  805.                      DincPC = 0;
  806.                      break;
  807.                   case 0:              // Normal Execution
  808.                      dst.pc += 2;
  809.                      break;
  810.                }
  811.                break;
  812.          } 
  813.       }
  814.          
  815.       return( TRUE );
  816.    }
  817.