]> git.unchartedbackwaters.co.uk Git - francis/winuae.git/commitdiff
DSP3210
authorToni Wilen <twilen@winuae.net>
Sun, 17 Sep 2023 15:00:26 +0000 (18:00 +0300)
committerToni Wilen <twilen@winuae.net>
Sun, 17 Sep 2023 15:00:26 +0000 (18:00 +0300)
13 files changed:
a2091.cpp
devices.cpp
dsp3210/DSP3210_emulation.cpp [new file with mode: 0644]
dsp3210/DSP3210_emulation.h [new file with mode: 0644]
dsp3210/dsp_glue.cpp [new file with mode: 0644]
dsp3210/dsp_glue.h [new file with mode: 0644]
expansion.cpp
gayle.cpp
include/rommgr.h
od-win32/sysconfig.h
od-win32/win32.cpp
od-win32/winuae_msvc15/winuae_msvc.vcxproj
od-win32/winuae_msvc15/winuae_msvc.vcxproj.filters

index fb76d981911fb085a33ad1e6656bbd0f101ed893..bb6b12208bd654523f05a8bbaf33b291600444c4 100644 (file)
--- a/a2091.cpp
+++ b/a2091.cpp
@@ -45,6 +45,7 @@
 #include "cpuboard.h"
 #include "rtc.h"
 #include "devices.h"
+#include "dsp3210/dsp_glue.h"
 
 #define DMAC_8727_ROM_VECTOR 0x8000
 #define CDMAC_ROM_VECTOR 0x2000
@@ -3625,6 +3626,12 @@ static void mbdmac_write_word (struct wd_state *wd, uae_u32 addr, uae_u32 val)
        case 0x46:
                wdscsi_put(&wd->wc, wd, val);
                break;
+       case 0x5e:
+       case 0x80:
+               if (is_dsp_installed) {
+                       dsp_write(val);
+               }
+               break;
        }
 }
 
@@ -3645,6 +3652,12 @@ static void mbdmac_write_byte (struct wd_state *wd, uae_u32 addr, uae_u32 val)
        case 0x47:
                wdscsi_put (&wd->wc, wd, val);
                break;
+       case 0x5f:
+       case 0x80:
+               if (is_dsp_installed) {
+                       dsp_write(val);
+               }
+               break;
        default:
                if (addr & 1)
                        mbdmac_write_word (wd, addr, val);
@@ -3711,6 +3724,12 @@ static uae_u32 mbdmac_read_word (struct wd_state *wd, uae_u32 addr)
        case 0x46:
                v = wdscsi_get(&wd->wc, wd);
                break;
+       case 0x5e:
+       case 0x80:
+               if (is_dsp_installed) {
+                       v = dsp_read();
+               }
+               break;
        }
 #if A3000_DEBUG_IO > 1
        write_log (_T("DMAC_WREAD %08X=%04X PC=%X\n"), vaddr, v & 0xffff, M68K_GETPC);
@@ -3741,6 +3760,12 @@ static uae_u32 mbdmac_read_byte (struct wd_state *wd, uae_u32 addr)
                if (!(addr & 1))
                        v >>= 8;
                break;
+       case 0x5f:
+       case 0x80:
+               if (is_dsp_installed) {
+                       v = dsp_read();
+               }
+               break;
        }
 #if A3000_DEBUG_IO > 1
        write_log (_T("DMAC_BREAD %08X=%02X PC=%X\n"), vaddr, v & 0xff, M68K_GETPC);
index 1473677eddcd01ac44b104ab7f1ae790a96bda8a..5c111794df34d200c5b15b14eda40f476f0169b6 100644 (file)
@@ -63,6 +63,7 @@
 #ifdef RETROPLATFORM
 #include "rp.h"
 #endif
+#include "dsp3210/dsp_glue.h"
 
 #define MAX_DEVICE_ITEMS 64
 
@@ -438,6 +439,9 @@ void devices_pause(void)
 {
 #ifdef WITH_PPC
        uae_ppc_pause(1);
+#endif
+#ifdef WITH_DSP
+       dsp_pause(1);
 #endif
        blkdev_entergui();
 #ifdef RETROPLATFORM
@@ -455,6 +459,9 @@ void devices_unpause(void)
 #endif
 #ifdef WITH_PPC
        uae_ppc_pause(0);
+#endif
+#ifdef WITH_DSP
+       dsp_pause(0);
 #endif
        pausevideograb(0);
        ethernet_pause(0);
diff --git a/dsp3210/DSP3210_emulation.cpp b/dsp3210/DSP3210_emulation.cpp
new file mode 100644 (file)
index 0000000..99a0dc9
--- /dev/null
@@ -0,0 +1,2585 @@
+
+#include "stdlib.h"
+#include "stdint.h"
+#include "math.h"
+
+#include "DSP3210_emulation.h"
+
+extern void write_log(const char *, ...);
+extern void activate_debugger(void);
+
+/* Typedefs */
+typedef union 
+{
+       int32_t i;
+       float f;
+
+} intfloat;
+
+/* Variable declarations */
+static int32_t latency3[2][2];         //ticks to execution, PC address
+static int32_t K_val = -1;
+static int32_t loopcount = 0;
+static int32_t loopstart = 0;
+static int32_t bio6, bio7;                     //for M68k interrupts
+
+//externally used
+int32_t DSP_reg_r[25];
+int32_t DSP_io_r[16];
+int32_t DSP_reg_irsh;          //shadow instruction register
+char DSP_irsh_flag;                    //1 indicates instruction in irsh to be executed
+int32_t DSP_irsh_addr;
+int32_t DSP_irsh_pcw;
+float DSP_reg_a[4];
+float DSP_history_a[5][5];
+uint16_t DSP_history_CC[5];
+int32_t DSP_history_mem[5][5];
+void *DSP_onboard_RAM;
+unsigned char DSP_onboard_ROM[];
+void *DSP_MMIO;
+
+/* Defines */
+#define CC DSP_io_r[0]
+#define reg_evtp DSP_reg_r[22]
+#define reg_PC DSP_reg_r[23]
+#define reg_pcsh DSP_reg_r[24]
+#define reg(val) DSP_reg_r[DSP_regno(val)]
+#define regS(val) (int16_t)(reg(val) & 0xFFFF)
+#define io(val) DSP_io_r[DSP_regno(val)]
+#define io_emr DSP_io_r[8]             //16 bit
+#define io_pcw DSP_io_r[12]            //16 bit
+#define io_dauc DSP_io_r[14]   //8 bit
+
+//CAU field definitions
+#define Wfield(inst) (inst&0x00E00000)>>21
+#define RPfield(inst) (inst&0xF800)>>11
+#define RIfield(inst) (inst&0x1F)
+#define RHfield(inst) (inst&0x1F0000)>>16
+#define RDfield(inst) (inst&0x03E00000)>>21
+#define RSfield(inst) (inst&0x001F0000)>>16
+#define Nfield(inst) (inst&0xFFFF)
+#define NEfield(inst) (inst&0x1FE00000)>>21
+#define FCAUfield(inst) (inst&0x01E00000)>>21
+#define Cfield(inst) (inst&0x000007E0)>>5
+#define Cgotofield(inst) (inst&0x07E00000)>>21
+#define RLfield(inst) Nfield(inst)
+#define RS1field(inst) RPfield(inst)
+#define RS2field(inst) RIfield(inst)
+#define RS3field(inst) RSfield(inst)
+#define RBfield(inst) RSfield(inst)
+#define RMfield(inst) RDfield(inst)
+
+//DAU field definitions
+#define Mfield(inst) (inst&0x1C000000)>>26
+#define Ffield(inst) (inst&0x01000000)>>24
+#define Sfield(inst) (inst&0x00800000)>>23
+#define NDAUfield(inst) (inst&0x00600000)>>21
+#define Xfield(inst) (inst&0x001FC000)>>14
+#define Yfield(inst) (inst&0x00003F80)>>7
+#define Zfield(inst) (inst&0x0000007F)
+#define Gfield(inst) (inst&0x07800000)>>23
+
+#define FLOAT_TO_INT(x) ((x)>=0?(int32_t)((x)+0.5):(int32_t)((x)-0.5))
+#define Ssign(x) (Sfield(x)==0?1:-1)
+#define Fsign(x) (Ffield(x)==0?1:-1)
+
+//condition codes
+#define CCn 1
+#define CCz 2
+#define CCv 4
+#define CCc 8
+#define CCN 16
+#define CCZ 32
+#define CCU 64
+#define CCV 128
+
+#define CCnf (CC&CCn)
+#define CCzf (CC&CCz)
+#define CCvf (CC&CCv)
+#define CCcf (CC&CCc)
+#define CCNf (CC&CCN)
+#define CCZf (CC&CCZ)
+#define CCUf (CC&CCU)
+#define CCVf (CC&CCV)
+
+//latency timing
+#define DSP_reg_atime 2
+
+//for 64 bit manipulations
+#define hi32 ~(int64_t)0xFFFFFFFF
+#define bt32  (int64_t)0x80000000
+#define hi48 ~(int64_t)0xFFFF
+#define bt16  (int64_t)0x8000
+static const double max_pos_float = (2-2^-31)*2^127;
+static const double max_neg_float = -2*2^127;
+static const double min_pos_float = 2^-127;
+static const double min_neg_float = (-1+2^-31)*2^-127;
+
+//internal ROM/RAM locations
+#define map0_ROM_start 0x50030000
+#define map0_ROM_end (map0_ROM_start + 0x3FF)
+#define map0_RAM_start (map0_ROM_start + 0xE000)
+#define map0_RAM_end (map0_ROM_start + 0xFFFF)
+#define map0_MMIO_start (map0_ROM_start + 0x400)
+#define map0_MMIO_end (map0_ROM_start + 0x7FF)
+#define map1_ROM_start 0
+#define map1_ROM_end (map1_ROM_start + 0x3FF)
+#define map1_RAM_start (map1_ROM_start + 0xE000)
+#define map1_RAM_end (map1_ROM_start + 0xFFFF)
+#define map1_MMIO_start (map1_ROM_start + 0x400)
+#define map1_MMIO_end (map1_ROM_start + 0x7FF)
+
+/* Function declarations */
+static void doinst(int32_t addr);
+static int32_t DAUXYZ(int32_t incode, int32_t field, int32_t *fld2);
+static int32_t GetXYfield(int32_t fld1,int32_t fld2,int32_t incode);
+static void DoLat3(int32_t pcval);
+static void SetZfield(int32_t fld1, int32_t fld2, int32_t temp);
+static void doDAU5(int32_t incode);
+static float Mval(int32_t incode);
+static float SetCC(double dtemp);
+static int32_t SetCCCAU(int64_t res, int32_t input);
+static int32_t SetCCCAU16(int64_t res, int32_t input);
+static void SetCCnzCAU(int32_t res);
+static int32_t TestCfield(int32_t code);
+static float round_dsp(float num);
+static int32_t bitreverse(int32_t n, int32_t bits);
+static void DSP_exception_illegal();
+static void DSP_exception_UOflow();
+static void DSP_exception_NaN();
+static void DSP_undefined();
+static void DSP_breakpoint();
+static void DSP_check_interrupt(int32_t value, int32_t bitno);
+
+//externally used
+int32_t DSP_swapl(int32_t a);
+int16_t DSP_swapw(int16_t a);
+int32_t DSP_regno(int32_t r);
+int32_t DSP_float(float f);
+int32_t DSP_negfloat(int32_t f);
+int32_t DSP_dsp2ieee(int32_t f);
+int32_t DSP_get_long(int32_t addr);
+void DSP_set_long(int32_t addr, int32_t value);
+int16_t DSP_get_short(int32_t addr);
+void DSP_set_short(int32_t addr, int16_t value);
+char DSP_get_char(int32_t addr);
+void DSP_set_char(int32_t addr, char value);
+
+/********************************************************/
+/* Initialise the DSP emulator                          */
+/*                                                      */
+/********************************************************/
+void DSP_init_emu ()
+{
+       DSP_onboard_RAM = malloc(8192); //8k onboard RAM
+       DSP_MMIO = malloc(0x800);
+       reg_PC = 0;
+       return;
+}
+
+/********************************************************/
+/* Shut down the DSP emulator                           */
+/*                                                      */
+/********************************************************/
+void DSP_shutdown_emu ()
+{
+       free(DSP_MMIO);
+       free(DSP_onboard_RAM);
+       return;
+}
+
+/********************************************************/
+/* Trigger DSP reset                                    */
+/*                                                      */
+/********************************************************/
+void DSP_reset()
+{
+       int32_t i;
+       for(i=0; i<22; i++) DSP_reg_r[i]=0;
+       for(i=0; i<4; i++) DSP_reg_a[i]=0;
+       latency3[0][0]=0;
+       latency3[1][0]=0;
+       reg_pcsh = 0;
+
+       //The Information Manual only mentions the following registers being initialised
+       reg_evtp = 0;
+       DSP_reg_r[20] = reg_PC;
+       reg_PC = 0;
+       io_dauc = 0;
+       DSP_io_r[12] = 0x0F8F;  //0b0000111110001111; bio 4,5 = 0 , bio 6,7 = 1, set pcw reg
+       io_emr = 0;
+
+       //other MMUIO regs are set here too - see 7-11
+       bio6 = 1;
+       bio7 = 1;
+       DSP_irsh_flag = 0;
+       return;
+}
+
+bool DSP_int0_masked()
+{
+       return (io_emr & 0x0100) == 0;
+}
+
+bool DSP_int1_masked()
+{
+       return (io_emr & 0x8000) == 0;
+}
+
+/********************************************************/
+/* Trigger an interrupt level 0                         */
+/*                                                      */
+/********************************************************/
+bool DSP_int0()
+{
+       if(!(io_emr & 0x0100))
+               return false;   //return if int0 masked out
+       
+       //save chip state: DO loop status, a0-a3, dauc
+       //not implemented yet
+       reg_pcsh = reg_PC;      //save PC
+       reg_PC = reg_evtp + 8*8;        //INT0 entry
+       DSP_irsh_flag = 2;      //no more waiting, execute interrupt
+       return true;
+}
+
+/********************************************************/
+/* Trigger an interrupt level 1                         */
+/*                                                      */
+/********************************************************/
+bool DSP_int1()
+{
+       if(!(io_emr & 0x8000))
+               return false;   //return if int1 masked out
+
+       //save chip state: DO loop status, a0-a3, dauc
+       //not implemented yet
+       reg_pcsh = reg_PC;      //save PC
+       reg_PC = reg_evtp + 8*15;       //INT1 entry
+       DSP_irsh_flag = 2;      //no more waiting, execut interrupt
+       return true;
+}
+
+/********************************************************/
+/* DSP reaches a breakpoint                             */
+/*                                                      */
+/********************************************************/
+void DSP_breakpoint()
+{
+       //It's unspecified in the DSP3210 Instruction Manual
+       //what actually happens on a 'bkpt' instruction
+       //In fact, the instruction isn't even listed in the
+       //instruction set! It only appears in the listing for
+       //the ROM code in Appendix A
+
+       return;
+}
+
+/********************************************************/
+/* Execute a single DSP instruction, allowing for       */
+/* instruction and memory latencies                     */
+/********************************************************/
+
+void DSP_execute_insn () 
+{
+       int32_t i,j;
+       DSP_history_mem[2][0] = 0;      //no mem to write by default
+       doinst(reg_PC);
+
+       //update history of mem writes - latency 1
+       for(j=4;j>0;j--) {
+               DSP_history_mem[0][j] = DSP_history_mem[0][j-1];        //location
+               DSP_history_mem[1][j] = DSP_history_mem[1][j-1];        //value
+               DSP_history_mem[2][j] = DSP_history_mem[2][j-1];        //flag for delayed write
+       }
+       switch(DSP_history_mem[2][4])
+       {
+       case 1:
+               //do write
+               //*(int32_t *)DSP_history_mem[0][4]=DSP_history_mem[1][4];      //dummy
+               DSP_set_long(DSP_history_mem[0][4], DSP_history_mem[1][4]);
+               break;
+
+       case 2:
+               //*(int16_t *)DSP_history_mem[0][4]=DSP_history_mem[1][4];      //dummy
+               DSP_set_short(DSP_history_mem[0][4], DSP_history_mem[1][4]);
+               break;
+
+       default:
+               break;
+       }
+
+       //update history of a registers - latency 2
+       for(i=0;i<4;i++) { //step through registers
+               for(j=4;j>0;j--) 
+                       DSP_history_a[i][j] = DSP_history_a[i][j-1]; //age each entry
+               DSP_history_a[i][0] = DSP_reg_a[i];     //insert new aN values
+       }
+
+       //update history of CC - latency 4
+       for(j=4;j>0;j--)
+               DSP_history_CC[j] = DSP_history_CC[j-1];
+       DSP_history_CC[0] = CC;
+       DSP_io_r[15] = ((DSP_io_r[15] << 1) | (CCNf >> 4)) &0x3F;       //update ctr
+
+       //deal with latency 3 - delayed jumps
+       if(latency3[0][0])
+       {               //we have a latent jump in the queue
+               if(latency3[0][0]--==1)         //decrease counter
+                       reg_PC = latency3[0][1];                //process the jump
+       }
+       if(latency3[1][0])
+       {       //latent jump in 2nd slot
+               if(latency3[1][0]--==1)
+                       reg_PC = latency3[1][1];        //process the jump
+       }
+
+       //do loop
+       if(reg_PC == K_val) {
+               loopcount--;
+               if(loopcount>=0) reg_PC = loopstart; 
+       }
+}
+
+/********************************************************/
+/* Main code to execute a single DSP instruction        */
+/********************************************************/
+
+void doinst(int32_t addr)
+{
+       int32_t valX, valY, fld1, fld2, fld3, fld4,value,tempc,pinc;
+       float ftemp,fvalX,fvalY;
+       float delayvalX, delayvalY, delayM;
+       double dtemp;
+       int64_t val64;
+       intfloat conv;
+       int32_t incode;
+       int32_t baseaddr;
+
+       if(DSP_irsh_flag == 3) return;                  //nothing to do while in waiti
+       if(DSP_irsh_flag == 4) DSP_irsh_flag -= 1;      //execute one more instruction
+       //int32_t incode = swapl(*(amiga_mem_base + addr));
+       if(DSP_irsh_flag == 1) {
+               DSP_irsh_flag = 0;
+               incode = DSP_reg_irsh;
+               reg_PC = reg_PC - 4;    //undo the PC increment coming up
+       } else {
+               //DSP_irsh_flag -= 1;
+               incode = DSP_swapl(DSP_get_long(addr));
+       }
+
+       switch((incode & 0xE0000000)>>29)
+       {
+       case 1:
+       case 2:
+       case 3:
+               if((incode & 0xF8000000)>>27 != 15) {
+                       //do some preliminaries if DAU 1-4
+                       fld1=DAUXYZ(incode,1,&fld2);    //get Xfield values
+                       valX=GetXYfield(fld1,fld2,incode);              //read value from Xfield reg and post inc
+                       fld3=DAUXYZ(incode,2,&fld4);    //get Yfield values
+                       valY=GetXYfield(fld3,fld4,incode);              //read value from Yfield reg and post inc
+
+                       //convert valX,Y to floats
+                       //*(int32_t *)&fvalX=swapl(valX);       //'''
+                       conv.i = DSP_swapl(valX);
+                       fvalX = conv.f;
+
+                       //*(int32_t *)&fvalY=swapl(valY);
+                       conv.i = DSP_swapl(valY);
+                       fvalY = conv.f;
+
+                       //factor in delayed a reg updates
+                       if(!fld1&&fld2<4) delayvalX = DSP_history_a[fld2][DSP_reg_atime]; else delayvalX = fvalX;
+                       if(!fld3&&fld4<4) delayvalY = DSP_history_a[fld4][DSP_reg_atime]; else delayvalY = fvalY;
+
+                       if(Mfield(incode)<4) delayM = DSP_history_a[Mfield(incode)][DSP_reg_atime]; else delayM = Mval(incode);
+                       //can now use delayvals as multiplier inputs
+               } 
+               break;
+       }
+
+       reg_PC=reg_PC+4;        
+       switch((incode & 0xE0000000)>>29)
+       {
+       case 1:
+               //DAU 1 or 4 instruction
+               //if(Mfield(incode)!=6)
+               switch(Mfield(incode))
+               {
+               case 6: //DAU4
+                       dtemp = Fsign(incode)*fvalY+Ssign(incode)*fvalX;
+                       ftemp = SetCC(dtemp);
+                       DSP_reg_a[NDAUfield(incode)]=ftemp;     //set aN to value
+                       value = valY;   //Zfield will be set to Yfield, if required
+
+                       fld1=DAUXYZ(incode,3,&fld2);    //get Zfield values
+                       SetZfield(fld1, fld2, DSP_swapl(value));        //and set Zfield if needed      
+                       break;
+
+               case 7:
+                       DSP_exception_illegal();
+                       break;
+
+               default:
+                       //DAU1
+                       dtemp = Fsign(incode)*fvalY+Ssign(incode)*delayM*delayvalX;
+                       ftemp = SetCC(dtemp);
+                       DSP_reg_a[NDAUfield(incode)]=ftemp;     //set aN to value
+                       //value = *(int32_t *)&ftemp;   //convert to int '''
+                       conv.f = ftemp;
+                       value = conv.i;
+
+                       fld1=DAUXYZ(incode,3,&fld2);    //get Zfield values
+                       SetZfield(fld1, fld2, DSP_swapl(value));        //and set Zfield if needed
+                       break;
+               }                       
+               break;
+
+       case 2:
+               //DAU 2 instruction
+               switch(Mfield(incode))
+               {
+               case 6:
+               case 7:
+                       DSP_exception_illegal();
+                       break;
+
+               default:
+                       dtemp = Fsign(incode)*Mval(incode)+Ssign(incode)*delayvalY*delayvalX;
+                       ftemp = SetCC(dtemp);
+                       DSP_reg_a[NDAUfield(incode)]=ftemp;     //set aN to value
+                       value = valY;   //Zfield will be set to Yfield, if required
+
+                       fld1=DAUXYZ(incode,3,&fld2);    //get Zfield values
+                       SetZfield(fld1, fld2, DSP_swapl(value));        //and set Zfield if needed
+                       break;
+               }
+               break;
+
+       case 3:
+               //DAU 3 or 5 instruction
+               if(Mfield(incode)!=6 && Mfield(incode)!=7)
+               {               //DAU 3
+                       dtemp = Fsign(incode)*Mval(incode)+Ssign(incode)*delayvalY*delayvalX;
+                       ftemp = SetCC(dtemp);
+                       DSP_reg_a[NDAUfield(incode)]=ftemp;     //set aN to value
+                       //value = *(int32_t *)&ftemp;   //convert to int '''
+                       conv.f = ftemp;
+                       value = conv.i;
+
+                       fld1=DAUXYZ(incode,3,&fld2);    //get Zfield values
+                       SetZfield(fld1, fld2, DSP_swapl(value));        //and set Zfield if needed
+               } else { //DAU 5
+                       doDAU5(incode);
+               }
+               break;
+
+       case 5:
+               //Unconditional branch instruction GOTO rB+M
+               DoLat3((uint32_t)((NEfield(incode)<<16)|Nfield(incode))+4);
+               //latency 3!
+               break;
+
+       case 6:
+               //24 bit immediate load instruction SET24
+               reg(RSfield(incode)) = (uint32_t)((NEfield(incode)<<16)|Nfield(incode));
+               break;
+
+       case 7:
+               //call 24-bit immediate instruction CALL M,(rM)
+               reg(RSfield(incode)) = reg_PC+4;        //return to the instruction after the latent one
+               DoLat3((uint32_t)((NEfield(incode)<<16)|Nfield(incode))+4);
+               //latency 3!
+               break;
+
+       default:
+               switch((incode&0xF8000000)>>27)
+               {
+               case 0: //reserved
+                       DSP_exception_illegal();
+                       break;
+
+               case 16:
+                       //conditional branch
+                       switch(incode)
+                       {
+                       case 0x80000000:
+                               //nop
+                               reg_PC = reg_PC + 0;
+                               break;
+
+                       case 0x803E0000:
+                               //ireturn
+                               DSP_irsh_flag = 1;
+                               reg_PC = reg_pcsh;      //jump execution to shadown PC
+                               break;
+
+                       default:
+                               if(TestCfield(Cgotofield(incode)))
+                               {
+                                       DoLat3(reg(RBfield(incode))+(int16_t)Nfield(incode) + ((RBfield(incode)==15)?4:0));
+                                       //if(RBfield(incode)==15) reg_PC+=4;    //account for extra instr in pipeline
+                               }
+                               //latency 3!
+                               break;
+                       }
+                       break;
+
+               default:
+                       switch((incode&0xFC000000)>>26)
+                       {
+                       case 2:         //reserved
+                       case 34:        //reserved
+                               DSP_exception_illegal();
+                               break;
+
+                       case 3:
+                               //loop counter instruction GOTO-LOOP
+                               reg(RMfield(incode))-=1;
+                               if(reg(RMfield(incode))>=0)
+                               {
+                                       DoLat3(reg(RBfield(incode)) + (int16_t)Nfield(incode) + ((RBfield(incode)==15)?4:0));
+                                       //if(RBfield(incode)==15) reg_PC+=4;    //account for extra instr in pipeline
+                               }
+                               break;
+                               //latency 3!!
+
+                       case 35:
+                               //DO loops
+                               K_val = ((incode&0x3F800)>>9) + reg_PC + 4;
+                               loopstart = reg_PC;
+                               if((incode&0x02000000)>>25)
+                                       //reg
+                                       loopcount = reg(RS2field(incode));
+                               else
+                                       //immediate
+                                       loopcount = incode&0x7FF;
+                               break;
+
+                       case 4:
+                               //call reg with 16 bit N instruction CALL rB+N,(rM)
+                               reg(RMfield(incode)) = reg_PC+4;        //return to the instruction after the latent one
+                               DoLat3(reg(RSfield(incode)) + (int16_t)Nfield(incode) + ((RSfield(incode)==15)?4:0));
+                               //if(RSfield(incode)==15) reg_PC+=4;    //account for extra instr in pipeline
+                               //latency 3!
+                               break;
+
+                       case 36:
+                               //SHIFT-OR
+                               value = reg(RSfield(incode)) | (Nfield(incode)<<16);
+                               reg(RDfield(incode)) = value;
+                               SetCCnzCAU(value);
+                               break;
+
+                       case 5:
+                               //16-bit 3 operand add instruction ADD
+                               value = reg(RS3field(incode));
+                               val64 = (int64_t)value + (int64_t)((int16_t)Nfield(incode));
+                               if(RS3field(incode)==15)        //PC
+                                       val64+=4;                               //fudge
+                               reg(RDfield(incode)) = SetCCCAU(val64,value);
+                               break;
+
+                       case 37:
+                               //32-bit 3 operand add instruction ADD
+                               value = reg(RS3field(incode));
+                               val64 = (int64_t)value + (int64_t)Nfield(incode);
+                               if(RS3field(incode)==15)        //PC
+                                       val64+=4;                               //fudge
+                               reg(RDfield(incode)) = SetCCCAU(val64,value);
+
+                               break;
+
+                       case 6:
+                               //16-bit ALU instruction
+                               if((incode&0x02000000)>>25)     //indicates immediate
+                               {
+                                       switch(FCAUfield(incode))
+                                       {
+                                       case 7: //compare
+                                               value = regS(RBfield(incode));
+                                               val64 = (int64_t)value - (int64_t)((int16_t)Nfield(incode));
+                                               value = SetCCCAU16(val64,value);
+                                               break;
+
+                                       case 15: //and, no store
+                                               value = regS(RBfield(incode))&((int16_t)Nfield(incode));
+                                               SetCCnzCAU(value);
+                                               break;
+
+                                       case 1: //left shift
+                                               value = regS(RBfield(incode)) << (int16_t)Nfield(incode);
+                                               reg(RBfield(incode)) = value&0xFFFF;
+                                               SetCCnzCAU(value);
+                                               break;
+
+                                       case 12: //logical right shift
+                                               value = (int32_t)(((uint32_t)regS(RBfield(incode))) >> (int16_t)Nfield(incode));
+                                               reg(RBfield(incode)) = value&0xFFFF;
+                                               SetCCnzCAU(value);
+                                               break;
+
+                                       case 13: //arithmetic right shift
+                                               value = regS(RBfield(incode)) >> (int16_t)Nfield(incode);
+                                               reg(RBfield(incode)) = value&0xFFFF;
+                                               SetCCnzCAU(value);
+                                               break;
+
+                                       case 2: // subtract N-rD
+                                               value = (int16_t)Nfield(incode);
+                                               val64 = (int64_t)value - (int64_t)regS(RBfield(incode));
+                                               reg(RBfield(incode)) = SetCCCAU16(val64,value);
+                                               break;
+
+                                       case 4: // subtract rD-N
+                                               value = regS(RBfield(incode));
+                                               val64 = (int64_t)value - (int64_t)((int16_t)Nfield(incode));
+                                               reg(RBfield(incode)) = SetCCCAU16(val64,value);
+                                               break;
+
+                                       case 3: // reverse carry add
+                                               value = (int16_t)bitreverse(regS(RBfield(incode)), 16);
+                                               value += (int16_t)bitreverse((int32_t)Nfield(incode), 16);
+                                               value = (int16_t)bitreverse(value, 16);
+                                               reg(RBfield(incode)) = value;
+                                               SetCCnzCAU(value);
+                                               break;
+
+                                       case 6: //and with complement
+                                       case 9: //rotate right
+                                       case 11: //rotate left
+                                               //not with immediate operand
+                                               DSP_undefined();
+                                               break;
+
+                                       case 8: //exclusive or
+                                               value = regS(RBfield(incode))^(int16_t)Nfield(incode);
+                                               reg(RBfield(incode)) = value;
+                                               SetCCnzCAU(value);
+                                               break;
+
+                                       case 10: //or
+                                               value = regS(RBfield(incode))|(int16_t)Nfield(incode);
+                                               reg(RBfield(incode)) = value;
+                                               SetCCnzCAU(value);
+                                               break;
+
+                                       case 14: //and
+                                               value = regS(RBfield(incode))&(int16_t)Nfield(incode);
+                                               reg(RBfield(incode)) = value;
+                                               SetCCnzCAU(value);
+                                               break;
+
+                                       default:        //Fcode 5 is reserved
+                                               DSP_undefined();
+                                               break;
+                                       }
+                               } else {        //Reg source
+                                       if(TestCfield(Cfield(incode)))  //ie not always false
+                                       {
+                                               switch(FCAUfield(incode))
+                                               {
+                                               case 7: //compare
+                                                       value = regS(RS1field(incode));
+                                                       val64 = (int64_t)value - (int64_t)regS(RS2field(incode));
+                                                       value = SetCCCAU16(val64, value);
+                                                       break;
+
+                                               case 15: //and, no store
+                                                       value = regS(RS1field(incode))&regS(RS2field(incode));
+                                                       SetCCnzCAU(value);
+                                                       break;
+
+                                               case 0: //add
+                                                       value = regS(RS1field(incode));
+                                                       val64 = (int64_t)value + (int64_t)regS(RS2field(incode));
+                                                       reg(RBfield(incode)) = SetCCCAU16(val64, value);
+                                                       break;
+                                               
+                                               case 1: //left shift
+                                                       //no test of RS2>26
+                                                       //unclear what happens if RS2=22!
+                                                       if(RS2field(incode)==23)        //+n
+                                                               value = regS(RS1field(incode))<<1;
+                                                       else
+                                                               value = regS(RS1field(incode))<<reg(RS2field(incode));
+                                                       reg(RBfield(incode)) = value&0xFFFF;
+                                                       SetCCnzCAU(value);
+                                                       break;
+
+                                               case 12: //logical right shift
+                                                       if(RS2field(incode)==23)        //+n
+                                                               value = (int32_t)(((uint32_t)regS(RS1field(incode)))>>1);
+                                                       else
+                                                               value = (int32_t)(((uint32_t)regS(RS1field(incode)))>>reg(RS2field(incode)));
+                                                       reg(RBfield(incode)) = value&0xFFFF;
+                                                       SetCCnzCAU(value);
+                                                       break;
+
+                                               case 13: //arithmetic right shift
+                                                       if(RS2field(incode)==23)        //+n
+                                                               value = regS(RS1field(incode))>>1;
+                                                       else
+                                                               value = regS(RS1field(incode))>>reg(RS2field(incode));
+                                                       reg(RBfield(incode)) = value&0xFFFF;
+                                                       SetCCnzCAU(value);
+                                                       break;
+
+                                               case 2: // subtract N-rD
+                                                       value = regS(RS1field(incode));
+                                                       val64 = (int64_t)value - (int64_t)regS(RS2field(incode));
+                                                       reg(RBfield(incode)) = SetCCCAU16(val64, value);
+                                                       break;
+
+                                               case 4: // subtract rD-N
+                                                       value = regS(RS1field(incode));
+                                                       val64 = (int64_t)value - (int64_t)regS(RS2field(incode));
+                                                       reg(RBfield(incode)) = SetCCCAU16(val64, value);
+                                                       break;
+
+                                               case 3: // reverse carry add
+                                                       value = (int16_t)bitreverse(regS(RS1field(incode)), 16);
+                                                       value += (int16_t)bitreverse(regS(RS2field(incode)), 16);
+                                                       value = (int16_t)bitreverse(value, 16);
+                                                       reg(RBfield(incode)) = value;
+                                                       SetCCnzCAU(value);
+                                                       break;
+
+                                               case 6: //and with complement
+                                                       value = regS(RS1field(incode))&~regS(RS2field(incode));
+                                                       reg(RBfield(incode)) = value;
+                                                       SetCCnzCAU(value);
+                                                       break;
+
+                                               case 9: //rotate right through carry
+                                                       tempc = CCcf<<12; //shift c (bit 3) to bit 15
+                                                       if(reg(RS1field(incode))&1) {
+                                                               value = (int32_t)((((uint16_t)regS(RS1field(incode)))>>1)|tempc);
+                                                               CC|=CCc;        //set c
+                                                       } else {
+                                                               value = (int32_t)((((uint16_t)regS(RS1field(incode)))>>1)|tempc);
+                                                               CC&=~CCc;       //clear c
+                                                       }
+                                                       if(!value) CC|=CCz; else CC&=~CCz;      //set/clear z
+                                                       if(value<0) CC|=CCn; else CC&=~CCn; //set/clear n
+                                                       CC&=~CCv;               //clear v
+                                                       break;
+
+                                               case 11: //rotate left
+                                                       tempc = CCcf>>3; //shift c to bit 0
+                                                       value = regS(RS1field(incode));
+                                                       val64 = (int64_t)value << 1;
+                                                       value = SetCCCAU16(val64,value);
+                                                       value |= tempc;
+                                                       break;
+
+                                               case 8: //exclusive or
+                                                       value = regS(RS1field(incode))^regS(RS2field(incode));
+                                                       reg(RBfield(incode)) = value;
+                                                       SetCCnzCAU(value);
+                                                       break;
+
+                                               case 10: //or
+                                                       value = regS(RS1field(incode))|regS(RS2field(incode));
+                                                       reg(RBfield(incode)) = value;
+                                                       SetCCnzCAU(value);
+                                                       break;
+
+                                               case 14: //and
+                                                       value = regS(RS1field(incode))&regS(RS2field(incode));
+                                                       reg(RBfield(incode)) = value;
+                                                       SetCCnzCAU(value);
+                                                       break;
+
+                                               default:        //Fcode 5 is reserved
+                                                       DSP_undefined();
+                                                       break;
+                                               }
+                                       }
+                               }
+                               break;
+
+                       case 38:
+                               //32-bit ALU instruction, format 6b,6d
+                               if((incode&0x02000000)>>25)     //indicates immediate
+                               {
+                                       switch(FCAUfield(incode))
+                                       {
+                                       case 7: //compare
+                                               value = reg(RBfield(incode));
+                                               val64 = (int64_t)value - (int64_t)Nfield(incode);
+                                               value = SetCCCAU(val64,value);
+                                               break;
+
+                                       case 15: //and, no store
+                                               value = reg(RBfield(incode))&Nfield(incode);
+                                               SetCCnzCAU(value);
+                                               break;
+
+                                       case 1: //left shift
+                                               value = reg(RBfield(incode)) << Nfield(incode);
+                                               reg(RBfield(incode)) = value;
+                                               SetCCnzCAU(value);
+                                               break;
+
+                                       case 12: //logical right shift
+                                               value = (int32_t)(((uint32_t)reg(RBfield(incode))) >> Nfield(incode));
+                                               reg(RBfield(incode)) = value;
+                                               SetCCnzCAU(value);
+                                               break;
+
+                                       case 13: //arithmetic right shift
+                                               value = reg(RBfield(incode)) >> Nfield(incode);
+                                               reg(RBfield(incode)) = value;
+                                               SetCCnzCAU(value);
+                                               break;
+
+                                       case 2: // subtract N-rD
+                                               value = Nfield(incode);
+                                               val64 = (int64_t)value - (int64_t)reg(RBfield(incode));
+                                               reg(RBfield(incode)) = SetCCCAU(val64,value);
+                                               break;
+
+                                       case 4: // subtract rD-N
+                                               value = reg(RBfield(incode));
+                                               val64 = (int64_t)value - (int64_t)Nfield(incode);
+                                               reg(RBfield(incode)) = SetCCCAU(val64,value);
+                                               break;
+
+                                       case 3: // reverse carry add
+                                               //not supported
+                                               value = bitreverse(regS(RBfield(incode)), 32);
+                                               value += bitreverse((int32_t)Nfield(incode), 32);
+                                               value = bitreverse(value, 32);
+                                               reg(RBfield(incode)) = value;
+                                               SetCCnzCAU(value);
+                                               break;
+
+                                       case 6: //and with complement
+                                       case 9: //rotate right
+                                       case 11: //rotate left
+                                               //not with immediate operand
+                                               DSP_undefined();
+                                               break;
+
+                                       case 8: //exclusive or
+                                               value = reg(RBfield(incode))^Nfield(incode);
+                                               reg(RBfield(incode)) = value;
+                                               SetCCnzCAU(value);
+                                               break;
+
+                                       case 10: //or
+                                               value = reg(RBfield(incode))|Nfield(incode);
+                                               reg(RBfield(incode)) = value;
+                                               SetCCnzCAU(value);
+                                               break;
+
+                                       case 14: //and
+                                               value = reg(RBfield(incode))&Nfield(incode);
+                                               reg(RBfield(incode)) = value;
+                                               SetCCnzCAU(value);
+                                               break;
+
+                                       default:        //Fcode 5 is reserved
+                                               DSP_undefined();
+                                               break;
+                                       }
+                               } else {
+                                       if(TestCfield(Cfield(incode)))  //ie not always false
+                                       {
+                                               switch(FCAUfield(incode))
+                                               {
+                                               case 7: //compare
+                                                       value = reg(RS1field(incode));
+                                                       val64 = (int64_t)value - (int64_t)reg(RS2field(incode));
+                                                       value = SetCCCAU(val64, value);
+                                                       break;
+
+                                               case 15: //and, no store
+                                                       value = reg(RS1field(incode))&reg(RS2field(incode));
+                                                       SetCCnzCAU(value);
+                                                       break;
+
+                                               case 0: //add
+                                                       value = reg(RS1field(incode));
+                                                       val64 = (int64_t)value + (int64_t)reg(RS2field(incode));
+                                                       reg(RBfield(incode)) = SetCCCAU(val64, value);
+                                                       break;
+                                               
+                                               case 1: //left shift
+                                                       if(RS2field(incode)==23)        //+n
+                                                               value = reg(RS1field(incode))<<1;
+                                                       else
+                                                               value = reg(RS1field(incode))<<reg(RS2field(incode));
+                                                       reg(RBfield(incode)) = value;
+                                                       SetCCnzCAU(value);
+                                                       break;
+
+                                               case 12: //logical right shift
+                                                       if(RS2field(incode)==23)        //+n
+                                                               value = (int32_t)(((uint32_t)reg(RS1field(incode)))>>1);
+                                                       else
+                                                               value = (int32_t)(((uint32_t)reg(RS1field(incode)))>>reg(RS2field(incode)));
+                                                       reg(RBfield(incode)) = value;
+                                                       SetCCnzCAU(value);
+                                                       break;
+
+                                               case 13: //arithmetic right shift
+                                                       if(RS2field(incode)==23)        //+n
+                                                               value = reg(RS1field(incode))>>1;
+                                                       else
+                                                               value = reg(RS1field(incode))>>reg(RS2field(incode));
+                                                       reg(RBfield(incode)) = value;
+                                                       SetCCnzCAU(value);
+                                                       break;
+
+                                               case 2: // subtract N-rD
+                                                       value = reg(RS1field(incode));
+                                                       val64 = (int64_t)value - (int64_t)reg(RS2field(incode));
+                                                       reg(RBfield(incode)) = SetCCCAU(val64, value);
+                                                       break;
+
+                                               case 4: // subtract rD-N
+                                                       value = reg(RS1field(incode));
+                                                       val64 = (int64_t)value - (int64_t)reg(RS2field(incode));
+                                                       reg(RBfield(incode)) = SetCCCAU(val64, value);
+                                                       break;
+
+                                               case 3: // reverse carry add
+                                                       value = bitreverse(regS(RS1field(incode)), 32);
+                                                       value += bitreverse(regS(RS2field(incode)), 32);
+                                                       value = bitreverse(value, 32);
+                                                       reg(RBfield(incode)) = value;
+                                                       SetCCnzCAU(value);
+                                                       break;
+
+                                               case 6: //and with complement
+                                                       value = reg(RS1field(incode))&~reg(RS2field(incode));
+                                                       reg(RBfield(incode)) = value;
+                                                       SetCCnzCAU(value);
+                                                       break;
+
+                                               case 9: //rotate right through carry
+                                                       tempc = CCcf<<28; //shift c (bit 3) to bit 31
+                                                       if(reg(RS1field(incode))&1) {
+                                                               value = (int32_t)(((uint32_t)reg(RS1field(incode)))>>1);
+                                                               CC|=CCc;        //set c
+                                                       } else {
+                                                               value = (int32_t)(((uint32_t)reg(RS1field(incode)))>>1);
+                                                               CC&=~CCc;       //clear c
+                                                       }
+                                                       value |= tempc; //old c becomes bit 31
+                                                       if(!value) CC|=CCz; else CC&=~CCz;      //set/clear z
+                                                       if(value<0) CC|=CCn; else CC&=~CCn; //set/clear n
+                                                       CC&=~CCv;               //clear v
+                                                       break;
+
+                                               case 11: //rotate left
+                                                       tempc = CCcf>>3; //shift c to bit 0
+                                                       value = reg(RS1field(incode));
+                                                       val64 = ((int64_t)value) << 1;
+                                                       value = SetCCCAU(val64,value);
+                                                       value |= tempc;
+                                                       break;
+
+                                               case 8: //exclusive or
+                                                       value = reg(RS1field(incode))^reg(RS2field(incode));
+                                                       reg(RBfield(incode)) = value;
+                                                       SetCCnzCAU(value);
+                                                       break;
+
+                                               case 10: //or
+                                                       value = reg(RS1field(incode))|reg(RS2field(incode));
+                                                       reg(RBfield(incode)) = value;
+                                                       SetCCnzCAU(value);
+                                                       break;
+
+                                               case 14: //and
+                                                       value = reg(RS1field(incode))&reg(RS2field(incode));
+                                                       reg(RBfield(incode)) = value;
+                                                       SetCCnzCAU(value);
+                                                       break;
+
+                                               default:        //Fcode 5 is reserved
+                                                       DSP_undefined();
+                                                       break;
+                                               }
+                                       }
+                               }
+                               break;
+
+                       case 7:
+                               //move DA instruction LOAD/STORE rD=*L, *L=rS
+                               //need to set upper 16 bits of address if necessary to 0x5003 based on pcw[10]
+                               //disables interrupts for one cycle
+                               if(io_pcw & 0x0400)     //pcw bit 10
+                                       baseaddr = map1_ROM_start;
+                               else
+                                       baseaddr = map0_ROM_start;
+
+                               if((incode&0x01000000)>>24)     //From a reg
+                               {
+                                       switch(Wfield(incode))
+                                       {
+                                       case 0: //char
+                                       case 1:
+                                               DSP_set_char(baseaddr | RLfield(incode), DSP_swapl(reg(RHfield(incode))&0xFF));
+                                               break;
+
+                                       case 2: //short
+                                       case 3:
+                                               DSP_set_short(baseaddr | RLfield(incode), DSP_swapw(reg(RHfield(incode))&0xFFFF));
+                                               break;
+
+                                       case 4: //unsigned high char
+                                               DSP_set_char(baseaddr | RLfield(incode), DSP_swapl((reg(RHfield(incode))&0xFF00)>>8)<<8);
+                                               break;
+
+                                       case 7: //long
+                                               DSP_set_long(baseaddr | RLfield(incode), DSP_swapl(reg(RHfield(incode))));
+                                               break;
+
+                                       default:
+                                               DSP_undefined();
+                                               break;
+                                       }
+                                                       
+                               } else {        //To a reg
+                                       switch(Wfield(incode))
+                                       {
+                                       case 0: //unsigned char
+                                               reg(RHfield(incode)) = DSP_swapl((uint32_t)DSP_get_char(baseaddr | RLfield(incode)));
+                                               break;
+
+                                       case 1: //char
+                                               reg(RHfield(incode)) = DSP_swapl((int32_t)DSP_get_char(baseaddr | RLfield(incode)));
+                                               break;
+
+                                       case 2: //unsigned short
+                                               reg(RHfield(incode)) = DSP_swapl((uint32_t)DSP_get_short(baseaddr | RLfield(incode)));
+                                               break;
+
+                                       case 3: //short
+                                               reg(RHfield(incode)) = DSP_swapl((int32_t)DSP_get_short(baseaddr | RLfield(incode)));
+                                               break;
+
+                                       case 4: //unsigned high char
+                                               reg(RHfield(incode)) = DSP_swapl(((uint32_t)DSP_get_short(baseaddr | RLfield(incode)))<<8);
+                                               break;
+
+                                       case 7: //long
+                                               reg(RHfield(incode)) = DSP_swapl(DSP_get_long(baseaddr | RLfield(incode)));
+                                               break;
+
+                                       default:
+                                               DSP_undefined();
+                                               break;
+                                       }
+                               }
+                               break;
+
+                       case 39:
+                               //move IO/post inc/mem instruction
+                               switch((incode&0x400)>>10)
+                               {
+                               case 0: //move post inc or mem i/o
+                                       switch((incode&0x02000000)>>25)
+                                       {
+                                       case 0:  //LOAD/STORE rD=MEM, MEM=rS ie move post inc 7c
+                                               if((incode&0x01000000)>>24)     //move from reg to mem
+                                               {
+                                                       switch(Wfield(incode))
+                                                       {
+                                                       case 0: //char
+                                                       case 1:
+                                                               //*((char *)amiga_mem_base+reg(RPfield(incode))) = swapl(reg(RHfield(incode))&0xFF);
+                                                               DSP_set_char(reg(RPfield(incode)), DSP_swapl(reg(RHfield(incode))&0xFF));
+                                                               pinc=1;
+                                                               break;
+
+                                                       case 2: //short
+                                                       case 3:
+                                                               //*((int16_t*)amiga_mem_base+((reg(RPfield(incode)))>>1)) = (swapw(reg(RHfield(incode))&0xFFFF));
+                                                               DSP_set_short(reg(RPfield(incode)), DSP_swapw(reg(RHfield(incode))&0xFFFF));
+                                                               pinc=2;
+                                                               break;
+
+                                                       case 4: //unsigned high char
+                                                               //*((char *)amiga_mem_base+reg(RPfield(incode))) = swapl((reg(RHfield(incode))&0xFF00)>>8)<<8;
+                                                               DSP_set_char(reg(RPfield(incode)), DSP_swapl((reg(RHfield(incode))&0xFF00)>>8)<<8);
+                                                               pinc=1;
+                                                               break;
+
+                                                       case 7: //long
+                                                               //*(amiga_mem_base+((reg(RPfield(incode)))>>2)) = swapl(reg(RHfield(incode)));
+                                                               DSP_set_long(reg(RPfield(incode)), DSP_swapl(reg(RHfield(incode))));
+                                                               pinc=4;
+                                                               break;
+
+                                                       default:
+                                                               DSP_undefined();
+                                                               break;
+                                                       }
+                                                       //do post inc
+                                                       switch(RIfield(incode))
+                                                       {
+                                                       case 0:         //no post inc
+                                                               break;
+
+                                                       case 22:        //post dec
+                                                               reg(RPfield(incode))-=pinc;
+                                                               break;
+
+                                                       case 23:        //post inc
+                                                               reg(RPfield(incode))+=pinc;
+                                                               break;
+
+                                                       default:        //RI
+                                                               reg(RPfield(incode))+=reg(RIfield(incode));
+                                                               break;
+                                                       }
+                                               } else  {       //move to reg from mem
+                                                       switch(Wfield(incode))
+                                                       {
+                                                       case 0: //unsigned char
+                                                               //reg(RHfield(incode)) = swapl((uint32_t)(*((unsigned char *)amiga_mem_base+reg(RPfield(incode)))));
+                                                               reg(RHfield(incode)) = DSP_swapl((uint32_t)DSP_get_char(reg(RPfield(incode))));
+                                                               pinc=1;
+                                                               break;
+
+                                                       case 1: //char
+                                                               //reg(RHfield(incode)) = swapl((int32_t)(*((char *)amiga_mem_base+reg(RPfield(incode)))));
+                                                               reg(RHfield(incode)) = DSP_swapl((int32_t)DSP_get_char(reg(RPfield(incode))));
+                                                               pinc=1;
+                                                               break;
+
+                                                       case 2: //unsigned short
+                                                               //reg(RHfield(incode)) = swapl((uint32_t)(*((uint16_t *)amiga_mem_base+((reg(RPfield(incode)))>>1))));
+                                                               reg(RHfield(incode)) = DSP_swapl((uint32_t)DSP_get_short(reg(RPfield(incode))));
+                                                               pinc=2;
+                                                               break;
+
+                                                       case 3: //short
+                                                               //reg(RHfield(incode)) = swapl((int32_t)(*((int16_t *)amiga_mem_base+((reg(RPfield(incode)))>>1))));
+                                                               reg(RHfield(incode)) = DSP_swapl((int32_t)DSP_get_short(reg(RPfield(incode))));
+                                                               pinc=2;
+                                                               break;
+
+                                                       case 4: //unsigned high char
+                                                               //reg(RHfield(incode)) = swapl(((uint32_t)(*((unsigned char *)amiga_mem_base+reg(RPfield(incode)))))<<8);
+                                                               reg(RHfield(incode)) = DSP_swapl(((uint32_t)DSP_get_short(reg(RPfield(incode))))<<8);
+                                                               pinc=1;
+                                                               break;
+
+                                                       case 7: //long
+                                                               //reg(RHfield(incode)) = swapl(*(amiga_mem_base+((reg(RPfield(incode)))>>2)));
+                                                               reg(RHfield(incode)) = DSP_swapl(DSP_get_long(reg(RPfield(incode))));
+                                                               pinc=4;
+                                                               break;
+
+                                                       default:
+                                                               DSP_undefined();
+                                                               break;
+                                                       }
+                                                       //do post inc
+                                                       switch(RIfield(incode))
+                                                       {
+                                                       case 0:         //no post inc
+                                                               break;
+
+                                                       case 22:        //post dec
+                                                               reg(RPfield(incode))-=pinc;
+                                                               break;
+
+                                                       case 23:        //post inc
+                                                               reg(RPfield(incode))+=pinc;
+                                                               break;
+
+                                                       default:        //RI
+                                                               reg(RPfield(incode))+=reg(RIfield(incode));
+                                                               break;
+                                                       }
+                                               }
+                                               break; //end 7c
+
+                                       case 1: //move io 7d instruction
+                                               switch(RHfield(incode))
+                                               {
+                                               case 0:         //ps
+                                               case 8:         //emr
+                                               case 12:        //pcw
+                                               case 14:        //dauc
+                                               case 15:        //ctr
+                                                       break;
+
+                                               default:        //only the above io registers are supported by the DSP3210
+                                                       DSP_undefined();
+                                                       break;
+                                               }
+
+                                               if((incode&0x01000000)>>24)     //move from reg to mem
+                                               {
+                                                       switch(Wfield(incode))
+                                                       {
+                                                       case 0: //char
+                                                               DSP_set_char(reg(RPfield(incode)), DSP_swapl(io(RHfield(incode))&0xFF));
+                                                               pinc=1;
+                                                               break;
+
+                                                       case 2: //short
+                                                               DSP_set_short(reg(RPfield(incode)), DSP_swapw(io(RHfield(incode))&0xFFFF));
+                                                               pinc=2;
+                                                               break;
+
+                                                       case 7: //long
+                                                               DSP_set_long(reg(RPfield(incode)), DSP_swapl(io(RHfield(incode))));
+                                                               pinc=4;
+                                                               break;
+
+                                                       default:
+                                                               DSP_undefined();
+                                                               break;
+                                                       }
+                                                       //do post inc
+                                                       switch(RIfield(incode))
+                                                       {
+                                                       case 0:         //no post inc
+                                                               break;
+
+                                                       case 22:        //post dec
+                                                               reg(RPfield(incode))-=pinc;
+                                                               break;
+
+                                                       case 23:        //post inc
+                                                               reg(RPfield(incode))+=pinc;
+                                                               break;
+
+                                                       default:        //RI
+                                                               reg(RPfield(incode))+=reg(RIfield(incode));
+                                                               break;
+                                                       }
+                                               } else  {       //move to reg from mem
+                                                       if(RHfield(incode)!=15) //cannot write to ctr
+                                                       switch(Wfield(incode))
+                                                       {
+                                                       case 0: //unsigned char - do not change other bits
+                                                               io(RHfield(incode)) = (io(RHfield(incode))&0xFFFFFF00) | (DSP_swapl((uint32_t)DSP_get_char(reg(RPfield(incode)))) & 0xFF);
+                                                               pinc=1;
+                                                               break;
+
+                                                       case 2: //unsigned short - do not change high word
+                                                               io(RHfield(incode)) = (io(RHfield(incode))&0xFFFF0000) | (DSP_swapl((uint32_t)DSP_get_short(reg(RPfield(incode)))) & 0xFFFF);
+                                                               pinc=2;
+                                                               break;
+
+                                                       case 7: //long
+                                                               io(RHfield(incode)) = DSP_swapl(DSP_get_long(reg(RPfield(incode))));
+                                                               pinc=4;
+                                                               break;
+
+                                                       default:
+                                                               DSP_undefined();
+                                                               break;
+                                                       }
+                                                       //do post inc
+                                                       switch(RIfield(incode))
+                                                       {
+                                                       case 0:         //no post inc
+                                                               break;
+
+                                                       case 22:        //post dec
+                                                               reg(RPfield(incode))-=pinc;
+                                                               break;
+
+                                                       case 23:        //post inc
+                                                               reg(RPfield(incode))+=pinc;
+                                                               break;
+
+                                                       default:        //RI
+                                                               reg(RPfield(incode))+=reg(RIfield(incode));
+                                                               break;
+                                                       }
+                                               }
+                                               break; //end 7d
+                                       }
+                                       break; //end 7c and 7d
+
+                               case 1: //move io 7b instruction
+                                       switch(incode)
+                                       {
+                                       case 0x09DE0040A:
+                                               //execute waiti
+                                               DSP_reg_irsh = DSP_swapl(DSP_get_long(reg_PC + 4));
+                                               DSP_irsh_flag = 4;      //execute one more instruction, then pause DSP
+                                               DSP_irsh_addr = reg_PC + 4;
+                                               DSP_irsh_pcw = DSP_io_r[12];
+                                               break;
+
+                                       case 0x9D00040A:
+                                               //execute sftrst = reset
+                                               DSP_reset();
+                                               break;
+
+                                       case 0x9D60040A:
+                                               //execute breakpoint
+                                               DSP_breakpoint();
+                                               break;
+
+                                       default:
+                                               switch(RIfield(incode))
+                                               {
+                                               case 0:         //ps 16
+                                               case 8:         //emr 16
+                                               case 10:        //spc 32
+                                               case 12:        //pcw 16
+                                               case 14:        //dauc 8
+                                               case 15:        //ctr 8
+                                                       break;
+
+                                               default:        //only the above io registers are supported by the DSP3210
+                                                       DSP_undefined();
+                                                       break;
+                                               }
+                                               if((incode&0x01000000)>>24)     //move from reg to io, iorD = rS
+                                               {
+                                                       if(RHfield(incode)!=15) //cannot write to ctr
+                                                       {
+                                                               switch(Wfield(incode))
+                                                               {
+                                                               case 1: //char
+                                                                       io(RIfield(incode)) = (io(RIfield(incode)) & 0xFFFFFF00) | (reg(RHfield(incode)) & 0xFF);
+                                                                       break;
+
+                                                               case 3: //short
+                                                                       if(RIfield(incode)<14)
+                                                                               io(RIfield(incode)) = (io(RIfield(incode)) & 0xFFFF0000) | (reg(RHfield(incode)) & 0xFFFF);
+                                                                       else
+                                                                               //cannot read 16 bits from an 8 bit io reg
+                                                                               DSP_undefined();
+                                                                       break;
+
+                                                               case 4: //unsigned high char
+                                                                       if(RIfield(incode)<14)
+                                                                               io(RIfield(incode)) = (io(RIfield(incode)) & 0xFFFF00FF) | (reg(RHfield(incode)) & 0xFF00);
+                                                                       else
+                                                                               //cannot read 16 bits from an 8 bit io reg
+                                                                               DSP_undefined();
+                                                                       break;
+
+                                                               case 7:
+                                                                       if(RIfield(incode) == 10)
+                                                                               io(RIfield(incode)) = reg(RHfield(incode));
+                                                                       else
+                                                                               DSP_undefined();
+                                                                       break;
+
+                                                               default:
+                                                                       DSP_undefined();
+                                                                       break;
+                                                               }
+                                                       } else {
+                                                               //exception due to write to ctr attempt?
+                                                       }
+                                               } else  {       //move to reg from io rD = iorS
+                                                       switch(Wfield(incode))
+                                                       {
+                                                       case 0: //unsigned char
+                                                               reg(RHfield(incode)) = io(RIfield(incode)) & 0xFF;
+                                                               break;
+
+                                                       case 1: //signed char
+                                                               reg(RHfield(incode)) = (int32_t)((char)(io(RIfield(incode)) & 0xFF));
+                                                               break;
+
+                                                       case 2: //unsigned short
+                                                               if(RIfield(incode)<14)
+                                                                       reg(RHfield(incode)) = io(RIfield(incode)) & 0xFFFF;
+                                                               else
+                                                                       DSP_undefined();
+                                                               break;
+
+                                                       case 3: //signed short
+                                                               if(RIfield(incode)<14)
+                                                                       reg(RHfield(incode)) = (int32_t)((int16_t)(io(RIfield(incode)) & 0xFFFF));
+                                                               else
+                                                                       DSP_undefined();
+                                                               break;
+
+                                                       case 4: //high byte
+                                                               reg(RHfield(incode)) = (io(RIfield(incode)) & 0xFF) << 8;
+                                                               break;
+
+                                                       case 7: //long
+                                                               if(RIfield(incode)==10) //read from spc to reg
+                                                                       reg(RHfield(incode)) = io(RIfield(incode));
+                                                               else
+                                                                       DSP_undefined();
+                                                               break;
+
+                                                       default:
+                                                               DSP_undefined();
+                                                               break;
+                                                       }
+                                               }
+                                               break;  // end test for special instructions
+                                       }
+                                       break;  //end 7b
+                               }
+                               break; //end case 39
+
+                       default:
+                               DSP_undefined();
+                               break;
+                       }
+                       break;
+               }
+               break;
+       }       
+       return ;
+}
+
+/********************************************************/
+/* Functions to support doinst                          */
+/********************************************************/
+
+// Extract the two parts of an X, Y or Z field (depending on field)
+// into the return value (fld1) and fld2
+int32_t DAUXYZ(int32_t incode, int32_t field, int32_t *fld2)
+{
+       int32_t fld1,temp;
+       switch(field)
+       {
+       case 1:
+               fld1=Xfield(incode)>>3;
+               temp=Xfield(incode)&0x7;
+               break;
+       case 2:
+               fld1=Yfield(incode)>>3;
+               temp=Yfield(incode)&0x7;
+               break;
+       case 3:
+               fld1=Zfield(incode)>>3;
+               temp=Zfield(incode)&0x7;
+               break;
+       }
+       
+       if(fld1)
+       {
+               if(temp>0&&temp<6)
+                       *fld2=temp+14;
+               else
+                       *fld2=temp;
+       } else {
+               *fld2=temp;
+       }
+       return fld1;
+}
+
+//return the X or Y field determined by the field parameters
+// as a _BE_ value
+int32_t GetXYfield(int32_t fld1,int32_t fld2,int32_t incode)
+{
+       int32_t temp,g;
+       int32_t postinc=4;
+       intfloat conv;
+
+       if((incode&0xF8000000)>>27==15) //true if DAU5
+       {               //change size field to short on int16/float16
+               g=Gfield(incode);
+               switch(g)
+               {
+               case 2:
+               case 3:
+                       postinc=2;
+                       break;
+
+               default:
+                       break;
+               }
+       }
+
+       if(!fld1)
+       {
+               if(fld2>3)
+               {
+                       DSP_undefined();
+                       return 0;
+               }
+               //=aN
+               conv.f = DSP_reg_a[fld2];
+               temp = DSP_swapl(conv.i);
+       } else {
+               switch(fld2)
+               {
+               case 0:
+                       //=*rP
+                       temp = DSP_get_long(DSP_reg_r[fld1]);
+                       break;
+
+               case 6:
+                       //=*rP--
+                       temp = DSP_get_long(DSP_reg_r[fld1]);
+                       DSP_reg_r[fld1]-=postinc;
+                       break;
+
+               case 7:
+                       //=*rP++
+                       temp = DSP_get_long(DSP_reg_r[fld1]);
+                       DSP_reg_r[fld1]+=postinc;
+                       break;
+
+               default:
+                       //=*rP++rI
+                       temp = DSP_get_long(DSP_reg_r[fld1]);
+                       DSP_reg_r[fld1]+=DSP_reg_r[fld2];
+                       break;
+               }
+
+               if((incode>>27)!=15) 
+                       //Not DAU5
+                       //having read a BE DSP float (as an int) from mem, convert to
+                       //internal BE IEEE float (as an int)
+                       return(DSP_swapl(DSP_dsp2ieee(DSP_swapl(temp))));       
+
+               switch(Gfield(incode))
+               {
+               case 2:         //do nothing on float 16/32, dsp
+               case 8:
+               case 13:
+                       break;
+
+               default:
+                       //having read a BE DSP float (as an int) from mem, convert to
+                       //internal BE IEEE float (as an int)
+                       temp = DSP_swapl(DSP_dsp2ieee(DSP_swapl(temp)));        
+                       break;
+               }
+       }
+       return temp;
+}
+
+// Set up jump instructions with 3 clock latencies
+void DoLat3(int32_t pcval)
+{
+       int32_t lat3ptr=0;
+       if(!latency3[0][0]) lat3ptr=1;  //first slot occupied
+       latency3[lat3ptr][1]=pcval;             //new PC value
+       latency3[lat3ptr][0]=2;                 //2 ticks to execute
+       return;
+}
+
+// Set up Z-field writes with 2 instruction latency
+// and post inc/dec
+void SetZfield(int32_t fld1, int32_t fld2, int32_t temp)       
+//temp must be converted from BE IEEE to DSP BE
+{
+       int32_t postinc=4;              //postinc always 4
+       intfloat conv;
+
+       if(fld1)                                        //need to set Zfield
+       {                                                       //deal with write latency 1 here
+               int32_t temp2 = DSP_swapl(temp); //now LE
+               //float f = *((float *)&(temp2)); //input -> float (still LE IEEE) '''
+               conv.i = temp2;
+               float f = conv.f;
+               temp2 = DSP_swapl(DSP_float(f));
+               //DSP_history_mem[0][0] = (int32_t)(amiga_mem_base+(DSP_reg_r[fld1]>>2));
+               DSP_history_mem[0][0] = DSP_reg_r[fld1];        //>>2;
+               DSP_history_mem[1][0] = temp2;
+               DSP_history_mem[2][0] = 1;      //delayed write enabled
+
+               switch(fld2)
+               {
+               case 0:
+                       break;
+
+               case 6: //*rP--=
+                       DSP_reg_r[fld1]-=postinc;
+                       break;
+
+               case 7: //*rP++=
+                       DSP_reg_r[fld1]+=postinc;
+                       break;
+
+               default:        //*rP++rI=
+                       DSP_reg_r[fld1]+=DSP_reg_r[fld2];
+                       break;
+               }
+       }
+}
+
+// Execute DAU5 type instruction
+void doDAU5(int32_t incode)
+{
+       int32_t value, fld1, fld2;
+       float ftemp;
+       fld1=DAUXYZ(incode,2,&fld2);    //get Yfield values
+       value=GetXYfield(fld1,fld2,incode);             //read value from Yfield reg and post inc
+                                                                       //NB value is BE 
+       int32_t m0,m1, m2, m3;          //###
+       intfloat conv;
+
+       switch(Gfield(incode))
+       {
+       case 0: //ic
+       case 1: //oc
+               //Unsupport instruction
+               break;
+
+       case 2:
+               //float16
+               ftemp = (float)DSP_swapl((value>>16));  //want first short
+               conv.f = ftemp;
+               value = DSP_swapl(conv.i);
+               break;
+
+       case 3:
+               //int16
+               m0 = DSP_swapl(value);                  //BE to LE
+               //get float value
+               conv.i = m0;
+               ftemp = conv.f;
+               ftemp = round_dsp(ftemp);               //round
+               value = (int32_t)ftemp; //convert to int
+               if(value>0x7FFF||value<-0x8000)
+                       value=0x7FFF;
+               else
+                       value&=0xFFFF;
+               value = DSP_swapl(value);               //convert to BE
+               break;
+
+       case 4:
+               //round
+               //nothing to do as it rounds 40 bits to 32 bit
+               break;
+
+       case 5:
+               //ifalt ie do nothing if Z-flag set or N-flag not set
+               if(!(CC&CCN))
+                       return;  //Do nothing if Z-flag not set
+               //otherwise no other manipulation needed                
+               break;
+       
+       case 6:
+               //ifaeq
+               if(!(CC&CCZ))
+                       return;  //Do nothing if Z-flag not set
+               //otherwise no other manipulation needed                
+               break;
+
+       case 7:
+               //ifagt ie do nothing if Z-flag set or N-flag not set
+               if(CC&CCZ||CC&CCN) 
+                       return;  //Do nothing if Z-flag not set
+               //otherwise no other manipulation needed                
+               break;
+
+       case 8:
+               //float32
+               value = DSP_swapl(value);
+               ftemp = (float)value;
+               conv.f = ftemp;
+               value = DSP_swapl(conv.i);
+               break;
+
+       case 9:
+               //int32
+               m0 = DSP_swapl(value);                  //BE to LE IEEE
+               //get float value
+               conv.i = m0;
+               ftemp = conv.f;
+               ftemp = round_dsp(ftemp);               //round
+               value = DSP_swapl((int32_t)ftemp);      //convert to int and BE
+               break;
+
+       case 10:
+       case 11:
+               DSP_undefined();
+               break;
+
+       case 12:
+               //ieee
+               //value = swapl(DSP_dsp2ieee(swapl(value)));
+               m0 = DSP_swapl(value);
+               if(((m0 & 0x7F800000) == 0x7F800000) && ((m0 & 0x007FFFFF) != 0))
+                       DSP_exception_NaN();
+               break;
+
+       case 13:
+               //dsp
+               /*m0 = swapl(value);                                    //get BE IEEE float into LE IEEE
+               ftemp = DSP_float(*(float *)&m0);       //convert to DSP float format
+               value = swapl(*(int *)&ftemp);          //put into a BE int*/
+               break;
+
+       case 14:
+               //seed
+               m0 = DSP_swapl(value);                  //value now LE IEEE
+               //IEEE LE -> DSP LE
+               conv.i = m0;
+               m3 = DSP_float(conv.f);
+               //m1 = ((~DSP_float(*(float *)&m0))^0x80000000); //invert all bits except sign
+               m1 = ((~m3) ^ 0x80000000);
+               m2 = DSP_dsp2ieee(m1);                  //DSP LE -> IEEE LE
+               
+               value = DSP_swapl(m2);                  //value is IEEE BE
+               break;
+
+       default:
+               //reserved
+               DSP_undefined();
+               break;
+       }
+
+       if(Gfield(incode)==3 || Gfield(incode)==9)              //int16 or int32
+               DSP_reg_a[NDAUfield(incode)]=(float)DSP_swapl(value);   //set aN to int value
+       else {
+               //set aN to value
+               conv.i = DSP_swapl(value);
+               DSP_reg_a[NDAUfield(incode)] = conv.f;
+       }
+
+       switch (Gfield(incode)) //set flags on required instructions
+       {
+       case 0: //ic
+       case 2: //float16
+       case 4: //round
+       case 8: //float32
+       case 14:        //seed
+               if(DSP_swapl(value)<0) CC|=CCN; else CC&=~CCN;
+               if(!DSP_swapl(value))  CC|=CCZ; else CC&=~CCZ;
+               CC&=~CCU;
+               CC&=~CCV;
+               break;
+
+       case 13:        //dsp U and V already set
+               if(DSP_swapl(value)<0) CC|=CCN; else CC&=~CCN;  
+               if(!DSP_swapl(value))  CC|=CCZ; else CC&=~CCZ;
+               break;
+
+       default:
+               break;
+       }
+
+       fld1=DAUXYZ(incode,3,&fld2);    //get Zfield values
+       switch(Gfield(incode))
+       {
+       case 3:
+               //int16 exception here.  We need to do a version of
+               //SetZfield but without the conversion to a DSP float 
+               
+               if(fld1)                                        //need to set Zfield
+               {                                                       //deal with write latency 1 here
+                       DSP_history_mem[0][0] = DSP_reg_r[fld1];
+                       DSP_history_mem[1][0] = value;
+                       DSP_history_mem[2][0] = 2;      //delayed write enabled
+
+                       switch(fld2)
+                       {
+                       case 0:
+                               //*rP=
+                               break;
+
+                       case 6:
+                               //*rP--=
+                               DSP_reg_r[fld1]-=2;
+                               break;
+
+                       case 7:
+                               //*rP++=
+                               DSP_reg_r[fld1]+=2;
+                               break;
+
+                       default:
+                               //*rP++rI=
+                               DSP_reg_r[fld1]+=DSP_reg_r[fld2];
+                               break;
+                       }
+               }
+               break;
+       case 9:
+       case 12:
+               //int32, ieee exception here.  We need to do a version of
+               //SetZfield but without the conversion to a DSP float 
+               
+               if(fld1)                                        //need to set Zfield
+               {                                                       //deal with write latency 1 here
+                       //DSP_history_mem[0][0] = (int32_t)(amiga_mem_base+(DSP_reg_r[fld1]>>2));
+                       DSP_history_mem[0][0] = DSP_reg_r[fld1];
+                       DSP_history_mem[1][0] = value;
+                       DSP_history_mem[2][0] = 1;      //delayed write enabled
+
+                       switch(fld2)
+                       {
+                       case 0:
+                               //*rP=
+                               break;
+
+                       case 6:
+                               //*rP--=
+                               DSP_reg_r[fld1]-=4;
+                               break;
+
+                       case 7:
+                               //*rP++=
+                               DSP_reg_r[fld1]+=4;
+                               break;
+
+                       default:
+                               //*rP++rI=
+                               DSP_reg_r[fld1]+=DSP_reg_r[fld2];
+                               break;
+                       }
+               }
+               break;
+
+       default:
+               SetZfield(fld1, fld2, value);   //and set Zfield if needed
+               break;
+       } 
+}
+
+// Extract float value out of M field
+float Mval(int32_t incode)
+{
+       int32_t m = Mfield(incode);
+       switch(m)
+       {
+       case 4:
+               return 0.0;
+               break;
+
+       case 5:
+               return 1.0;
+               break;
+
+       case 0:
+       case 1:
+       case 2:
+       case 3:
+               return DSP_reg_a[m];
+
+       default:
+               return 0;
+       }
+}
+
+// Set condition codes for DAU instructions
+float SetCC(double dtemp)
+{
+       if(dtemp<0)             CC|=CCN; else CC&=~CCN;
+       if(dtemp==0)    CC|=CCZ; else CC&=~CCZ;
+
+       //test for under/overflow situations
+       if(dtemp>max_pos_float || dtemp<max_neg_float) DSP_exception_UOflow();
+       if((dtemp>0 && dtemp<min_pos_float) || (dtemp<0 && dtemp>min_neg_float)) DSP_exception_UOflow();
+
+       //test for UV flags
+       if(dtemp>3.40282e28||dtemp<-3.40282e28) { CC|=CCV; dtemp=0;} else CC&=~CCV;
+       if(dtemp<5.87747e-39&&dtemp>-5.87747e-39&&dtemp!=0) { CC|=CCU; dtemp=0;} else CC&=~CCU;
+       
+       return((float)dtemp);
+}
+
+//Set confition codes for 32 bit CAU instructions
+int32_t SetCCCAU(int64_t res, int32_t input)
+{
+       int64_t in = (int64_t)input;
+       if(res<0)       CC|=CCn; else CC&=~CCn;
+       if(res==0)      CC|=CCz; else CC&=~CCz;
+       if((res&hi32)^(in&hi32)) CC|=CCc; else CC&=~CCc;  //set c if hi-32 bits change
+       if(((res&bt32)^(in&bt32))&!CCcf) CC|=CCv; else CC&=~CCv; //set v if bit 32 changes and c unset
+       return((int32_t)res);
+}
+
+//Set condition codes for 16 bit CAU instructions
+int32_t SetCCCAU16(int64_t res, int32_t input)
+{
+       int64_t in = (int64_t)input;
+       if(res<0)       CC|=CCn; else CC&=~CCn;
+       if(res==0)      CC|=CCz; else CC&=~CCz;
+       if((res&hi48)^(in&hi48)) CC|=CCc; else CC&=~CCc;  //set c if hi-48 bits change
+       if(((res&bt16)^(in&bt16))&!CCcf) CC|=CCv; else CC&=~CCv; //set v if bit 16 changes and c unset
+       return((int32_t)res);
+}
+
+//Set n,z condition codes, clear c, v
+void SetCCnzCAU(int32_t res)
+{
+       if(res<0)       CC|=CCn; else CC&=~CCn;
+       if(res==0)      CC|=CCz; else CC&=~CCz;
+       CC&=~CCc; //clear c
+       CC&=~CCv; //clear v
+       return;
+}
+
+//Test C field
+int32_t TestCfield(int32_t code)       //test CCs but U and V not supported
+{
+       int32_t res=0;
+       switch(code)
+       {
+       case 0:  //false
+               break;
+
+       case 1: //true
+               res=1;
+               break;
+
+       case 2: //pl
+               if(!CCnf) res=1;
+               break;
+
+       case 3: //mi
+               if(CCnf) res=1;
+               break;
+
+       case 4: //ne
+               if(!CCzf) res=1;
+               break;
+
+       case 5: //eq
+               if(CCzf) res=1;
+               break;
+
+       case 6: //vc
+               if(!CCvf) res=1;
+               break;
+
+       case 7: //vs
+               if(CCvf) res=1;
+               break;  
+
+       case 8: //cc
+               if(!CCcf) res=1;
+               break;
+
+       case 9: //cs
+               if(CCcf) res=1;
+               break;
+
+       case 10: //ge
+               if(!(CCnf^CCvf)) res=1;
+               break;
+
+       case 11: //lt
+               if(CCnf^CCvf) res=1;
+               break;
+
+       case 12: //gt
+               if(!CCzf&!(CCnf^CCvf)) res=1;
+               break;
+
+       case 13: //le
+               if(CCzf|(CCnf^CCvf)) res=1;
+               break;
+
+       case 14: //hi
+               if(!CCcf&!CCzf) res=1;
+               break;
+
+       case 15: //ls
+               if(CCcf|CCzf) res=1;
+               break;
+
+       case 18: //age
+               if(!(DSP_history_CC[3]&CCN)) res=1;
+               break;
+
+       case 19: //alt
+               if(DSP_history_CC[3]&CCN) res=1;
+               break;
+
+       case 20: //ane
+               if(!(DSP_history_CC[3]&CCZ)) res=1;
+               break;
+
+       case 21: //aeq
+               if(DSP_history_CC[3]&CCZ) res=1;
+               break;
+
+       case 24: //agt
+               if(!(DSP_history_CC[3]&CCN)&!(DSP_history_CC[3]&CCZ)) res=1;
+               break;
+
+       case 25: //ale
+               if((DSP_history_CC[3]&CCN)|(DSP_history_CC[3]&CCZ)) res=1;
+               break;
+
+       }
+       return res;
+}
+
+
+
+/********************************************************/
+/* Utility functions                                    */
+/********************************************************/
+
+//BE <-> LE craziness
+int32_t DSP_swapl(int32_t a)
+{
+       return ((a & 0x000000FF) << 24) |
+      ((a & 0x0000FF00) <<  8) |
+      ((a & 0x00FF0000) >>  8) |
+      ((a & 0xFF000000) >> 24);
+}
+
+int16_t DSP_swapw(int16_t a)
+{
+       return ((a & 0x00FF) << 8) | ((a & 0xFF00) >> 8);
+}
+
+//map register code onto a uniform register number
+int32_t DSP_regno(int32_t r)
+{
+       if(r<15)
+               return r;
+       if(r==15)
+               return 23;              //map PC to reg 23
+       if(r>16&&r<22)
+               return r-2;             //map regs 15-19
+       if(r>23&&r<27)
+               return r-4;
+       if(r==30)
+               return 24;              //map pcsh to reg 24
+       return 25;                      //trap illegal
+}
+
+// LE IEEE to LE DSP
+int32_t DSP_float(float f)
+{
+       int32_t neg = 0;
+       int32_t mant, exp;
+       intfloat intf;
+
+       if(f < 0.0) {
+               f = -f;
+               neg = 1;
+       }
+       intf.f = f;
+
+       mant = intf.i & 0x007FFFFF;
+       exp = (intf.i >> 23) & 0x000000FF;
+
+       if(exp != 0)
+       {
+               exp += 1;
+               CC&=~CCU;       //clear underflow flag
+       }
+       else
+       {
+               mant = 0; // unnormalized underflows ==> 0.0
+               CC|=CCU;        //set underflow flag
+       }
+       if(exp > 0xFF) {
+               exp = 0xFF;
+               mant = 0x007FFFFFL;
+               CC|=CCV;        //set overflow flag
+       } else CC&=~CCV;        //clear overflow flag
+       mant = (mant << 8) | exp;
+
+       return neg ? DSP_negfloat(mant) : mant;
+}
+
+int32_t DSP_negfloat(int32_t f)
+{
+       int32_t mant, exp;
+       if(f == 0)
+               return f;
+
+       mant = f >> 8;
+       exp = f & 0xFF;
+
+       mant = -mant;
+       if(f > 0 && mant == 0) {
+               exp -= 1;
+               mant = 0x00800000;
+       } else if(f < 0 && mant == 0)
+               exp += 1;
+
+       return (mant<<8) | exp;
+}
+
+int32_t bitreverse(int32_t n, int32_t bits)
+{
+       int32_t rv = 0;
+       int32_t i;
+       for(i = 0; i < bits; ++i, n >>= 1) {
+               rv = (rv << 1) | (n & 0x01);
+       }
+       return rv;
+}
+
+//convert LE DSP float as int to LE IEEE float as int
+int32_t DSP_dsp2ieee(int32_t f)
+{
+       int32_t neg = 0;
+       int32_t m,e;
+       
+       if(!f) return f;
+       if(f&0x80000000)
+               neg = 1;
+
+       e = f&0xFFL;
+       m = (f>>8)&0x7FFFFF;
+
+       if(!e) return 0; //zero even if dirty zero
+
+       e-=1;
+       //cannot be a carry as e>0
+
+       if(neg) {
+               m = (-m) & 0x7FFFFF;
+               if(!m) e -= 1;
+       }
+
+       m = m|(e<<23)|(neg?0x80000000:0);
+
+       return m;
+}
+
+static float round_dsp(float num)
+{
+    float integer = ceilf(num); //smallest integer >= num (-2>-2.8)
+       switch((DSP_io_r[14]&0x30)>>4)
+       {
+       case 0: //round nearest
+       case 2:
+       default:
+               if(num > 0)
+                       return integer - num > 0.5f ? integer - 1.0f : integer;
+               return integer - num >= 0.5f ? integer - 1.0f : integer;
+               break;
+               
+       case 1:
+               return integer - 1.0f;
+               break;
+
+       case 3:
+               if(num > 0)
+                       return integer - 1.0f;
+               return integer;
+               break;
+       }
+}
+
+/********************************************************/
+/* Illegal opcode exception                             */
+/*                                                      */
+/********************************************************/
+void DSP_exception_illegal()
+{
+       //non-maskable exception
+       //if(!(io_emr & 0x8000))
+               //return;       //return if int1 masked out
+
+       //save chip state: DO loop status, a0-a3, dauc
+       //not implemented yet
+       DSP_reg_r[20] = reg_PC;
+       reg_pcsh = reg_PC;      //save PC
+       reg_PC = reg_evtp + 8*2;        //Illegal opcode entry
+       return;
+}
+
+/********************************************************/
+/* Under/overflow exception                             */
+/*                                                      */
+/********************************************************/
+void DSP_exception_UOflow()
+{
+       if(!(io_emr & 0x0020))
+               return; //return if NaN masked out
+
+       //save chip state: DO loop status, a0-a3, dauc
+       //not implemented yet
+       DSP_reg_r[20] = reg_PC;
+       reg_pcsh = reg_PC;      //save PC
+       reg_PC = reg_evtp + 8*5;        //NaN opcode entry
+       return;
+}
+
+/********************************************************/
+/* NaN opcode exception                                 */
+/*                                                      */
+/********************************************************/
+void DSP_exception_NaN()
+{
+       if(!(io_emr & 0x0040))
+               return; //return if NaN masked out
+
+       //save chip state: DO loop status, a0-a3, dauc
+       //not implemented yet
+       DSP_reg_r[20] = reg_PC;
+       reg_pcsh = reg_PC;      //save PC
+       reg_PC = reg_evtp + 8*6;        //NaN opcode entry
+       return;
+}
+
+/********************************************************/
+/* Undefined behaviour handling                         */
+/*                                                      */
+/********************************************************/
+void DSP_undefined()
+{
+       //certain instruction codes are marked as Reserved and yet
+       //aren't listed in the manual as triggering the illegal
+       //opcode exception.  It's not known what happens in all these
+       //cases.  Here they are assumed to trigger the illegal opcode
+       //exception.
+       DSP_exception_illegal();
+       return;
+}
+
+/********************************************************/
+/* Memory read/write routines                           */
+/********************************************************/
+int32_t *dsp_check_mem(int32_t addr, int32_t *flag)
+{
+       if(DSP_io_r[12] & 0x0400) {
+               //we are in memory map mode 1
+               if(addr >= map1_ROM_start && addr <= map1_ROM_end) {
+                       //we are accessing ROM
+                       *flag = 1;
+                       return (int32_t *)(DSP_onboard_ROM + addr - map1_ROM_start);
+               }
+               if(addr >= map1_RAM_start && addr <= map1_RAM_end) {
+                       //we are accessing onboard RAM
+                       *flag = 2;
+                       return (int32_t *)((int32_t)DSP_onboard_RAM + addr - map1_RAM_start);
+               }
+               if(addr >= map1_MMIO_start && addr <= map1_MMIO_end) {
+                       //access to MMIO space
+                       *flag = 4;
+                       return (int32_t *)((int32_t)DSP_MMIO + addr - map1_MMIO_start);
+               }
+               if (addr >= map1_ROM_start && addr < map1_RAM_end) {
+                       write_log("1");
+               }
+       } else {
+               //we are in memory map mode 0
+               if(addr >= map0_ROM_start && addr <= map0_ROM_end) {
+                       //we are accessing ROM
+                       *flag = 1;
+                       return (int32_t *)(DSP_onboard_ROM + addr - map0_ROM_start);
+               }
+               if(addr >= map0_RAM_start && addr <= map0_RAM_end) {
+                       //we are accessing onboard RAM
+                       *flag = 2;
+                       return (int32_t *)((int32_t)DSP_onboard_RAM + addr - map0_RAM_start);
+               }
+               if(addr >= map0_MMIO_start && addr <= map0_MMIO_end) {
+                       //access to MMIO space
+                       *flag = 3;
+                       return (int32_t *)((int32_t)DSP_MMIO + addr - map0_MMIO_start);
+               }
+               if (addr >= map0_ROM_start && addr < map0_RAM_end) {
+                       write_log("1");
+               }
+       }
+       *flag = 0;
+       return NULL;
+}
+
+extern int log_dsp;
+static const char *iotype[] = { "", "ROM", "RAM", "MMIO0", "MMIO1" };
+
+int32_t DSP_get_long(int32_t addr)
+{
+       int32_t flag;
+       int32_t *actual_addr = dsp_check_mem(addr, &flag);
+       switch(flag)
+       {
+       case 0:                 //read Amiga mem
+               return DSP_get_long_ext(addr);
+
+       default:                //read onboard ROM, RAM, MMIO
+               if (log_dsp) {
+                       write_log("LGET from DSP %s: %08x = %08x\n", iotype[flag], addr, *actual_addr);
+               }
+               return *actual_addr;
+       }
+}
+
+void DSP_set_long(int32_t addr, int32_t value)
+{
+       int32_t flag;
+       int32_t *actual_addr = dsp_check_mem(addr, &flag);
+       switch(flag)
+       {
+       case 0:
+               DSP_set_long_ext(addr, value); //write to Amiga mem
+               break;
+
+       case 1:
+               if (log_dsp) {
+                       write_log("LPUT DSP ROM %08x = %08x\n", addr, *actual_addr);
+               }
+               break;                                  //attempt to write to onboard ROM! Do nothing
+
+       case 2:
+               if (log_dsp) {
+                       write_log("LPUT DSP RAM %08x = %08x\n", addr, *actual_addr);
+               }
+               *actual_addr = value;   //write to onboard RAM
+               break;
+
+       case 3:
+               if (log_dsp) {
+                       write_log("LPUT DSP MMIO0 %08x = %08x\n", addr, *actual_addr);
+               }
+               if(addr == (0x41C + map0_ROM_start))    //write to bio reg
+                       DSP_check_interrupt(value, 28);
+               *actual_addr = value;
+               break;
+
+       case 4:
+               if (log_dsp) {
+                       write_log("LPUT DSP MMIO1 %08x = %08x\n", addr, *actual_addr);
+               }
+               if(addr == (0x41C + map1_ROM_start))
+                       DSP_check_interrupt(value, 28);
+               *actual_addr = value;
+               break;
+       }
+}
+
+int16_t DSP_get_short(int32_t addr)
+{
+       int32_t flag;
+       int16_t *actual_addr = (int16_t *)dsp_check_mem(addr, &flag);
+
+       switch(flag)
+       {
+       case 0:                 //read Amiga mem
+               return DSP_get_short_ext(addr);
+
+       default:                //read onboard ROM, RAM, MMIO
+               return *actual_addr;
+       }
+}
+
+void DSP_set_short(int32_t addr, int16_t value)
+{
+       int32_t flag;
+       int16_t *actual_addr = (int16_t *)dsp_check_mem(addr, &flag);
+
+       switch(flag)
+       {
+       case 0:
+               DSP_set_short_ext(addr, value); //write to Amiga mem
+               break;
+
+       case 1:                                 //attempt to write to onboard ROM! Do nothing
+               if (log_dsp) {
+                       write_log("WPUT DSP ROM %08x = %04x\n", addr, *actual_addr);
+               }
+               break;
+
+       case 2:                                 //write to onboard RAM
+               if (log_dsp) {
+                       write_log("WPUT DSP RAM %08x = %04x\n", addr, *actual_addr);
+               }
+               *actual_addr = value;
+               break;
+
+       case 3:                                 //write to MMIO space
+               if (log_dsp) {
+                       write_log("WPUT DSP MMIO0 %08x = %04x\n", addr, *actual_addr);
+               }
+               if(addr == 0x41E + map0_ROM_start)      //write to bio reg
+                       DSP_check_interrupt(value, 12-8);
+               *actual_addr = value;
+               break;
+
+       case 4:                                 //write to MMIO space
+               if (log_dsp) {
+                       write_log("WPUT DSP MMIO1 %08x = %04x\n", addr, *actual_addr);
+               }
+               if(addr == 0x41E + map1_ROM_start)
+                       DSP_check_interrupt(value, 12-8);
+               *actual_addr = value;
+               break;
+       }
+       return;
+}
+
+char DSP_get_char(int32_t addr)
+{
+       int32_t flag;
+       char *actual_addr = (char *)dsp_check_mem(addr, &flag);
+
+       switch(flag)
+       {
+       case 0:                 //read Amiga mem
+               return DSP_get_char_ext(addr);
+
+       default:                //read onboard ROM, RAM, MMIO
+               return *actual_addr;
+       }
+}
+
+void DSP_set_char(int32_t addr, char value)
+{
+       int32_t flag;
+       char *actual_addr = (char *)dsp_check_mem(addr, &flag);
+
+       switch(flag)
+       {
+       case 0:                                 //write to Amiga mem
+               DSP_set_char_ext(addr,value);
+               break;
+
+       case 1:                                 //attempt to write to onboard ROM! Do nothing
+               if (log_dsp) {
+                       write_log("BPUT DSP ROM %08x = %02x\n", addr, *actual_addr);
+               }
+               break;
+
+       case 2:                                 //write to onboard RAM
+               if (log_dsp) {
+                       write_log("BPUT DSP RAM %08x = %02x\n", addr, *actual_addr);
+               }
+               *actual_addr = value;
+               break;
+
+       case 3:                                 //write to MMIO space
+               if (log_dsp) {
+                       write_log("BPUT DSP MMIO0 %08x = %02x\n", addr, *actual_addr);
+               }
+               if(addr == 0x41F + map0_ROM_start)      //write to bio reg
+                       DSP_check_interrupt(value, 4);
+               *actual_addr = value;
+               break;
+
+       case 4:                                 //write to MMIO space
+               if (log_dsp) {
+                       write_log("BPUT DSP MMIO1 %08x = %02x\n", addr, *actual_addr);
+               }
+               if(addr == 0x41F + map1_ROM_start)
+                       DSP_check_interrupt(value, 4);
+               *actual_addr = value;
+               break;
+       }
+       return ;
+}
+
+void DSP_check_interrupt(int32_t value, int32_t bitno)
+{
+       int32_t mask;
+       mask = 3 << bitno;              //test for bio[6] = INT6
+       switch((value & mask) >> bitno)
+       {
+       case 0:         //no change to reg
+               break;
+
+       case 1:         //set reg to 0 = trigger int
+               bio6 = 0;
+               DSP_external_interrupt(1, 0);
+               break;
+
+       case 2:         //set reg to 1
+               bio6 = 1;
+               DSP_external_interrupt(1, 1);
+               break;
+
+       case 3:         //complement reg
+               bio6 = (1-bio6);
+               DSP_external_interrupt(1, bio6);
+               break;
+       }
+
+       mask = 3 << (bitno + 2);        //test for bio[7] = INT2
+       switch((value & mask) >> (bitno+2))
+       {
+       case 0:         //no change to reg
+               break;
+
+       case 1:         //set reg to 0 = trigger int
+               bio7 = 0;
+               DSP_external_interrupt(0, 0);
+               break;
+
+       case 2:         //set reg to 1
+               bio7 = 1;
+               DSP_external_interrupt(0, 1);
+               break;
+
+       case 3:         //complement reg
+               bio7 = (1-bio7);
+               DSP_external_interrupt(0, bio7);
+               break;
+       }
+       return;
+}
+
+/********************************************************/
+/* Onboard boot rom binary                              */
+/********************************************************/
+
+unsigned char DSP_onboard_ROM[] =
+{
+/* [0000][0001][0002][0003][0004][0005][0006][0007]*/
+/*[0000]*/ 0x80, 0x2f, 0x00, 0x80, 0x9c, 0x61, 0x04, 0x0c,
+/*[0008]*/ 0x80, 0x2f, 0x00, 0xec, 0x80, 0x00, 0x00, 0x00,
+/*[0010]*/ 0x80, 0x2f, 0x00, 0xe4, 0x80, 0x00, 0x00, 0x00,
+/*[0018]*/ 0x80, 0x2f, 0x00, 0xdc, 0x80, 0x00, 0x00, 0x00,
+/*[0020]*/ 0x80, 0x2f, 0x00, 0xd4, 0x80, 0x00, 0x00, 0x00,
+/*[0028]*/ 0x80, 0x2f, 0x00, 0xcc, 0x80, 0x00, 0x00, 0x00,
+/*[0030]*/ 0x80, 0x2f, 0x00, 0xc4, 0x80, 0x00, 0x00, 0x00,
+/*[0038]*/ 0x80, 0x2f, 0x00, 0xbc, 0x80, 0x00, 0x00, 0x00,
+/*[0040]*/ 0x80, 0x2f, 0x00, 0xb4, 0x80, 0x00, 0x00, 0x00,
+/*[0048]*/ 0x80, 0x2f, 0x00, 0xac, 0x80, 0x00, 0x00, 0x00,
+/*[0050]*/ 0x80, 0x2f, 0x00, 0xa4, 0x80, 0x00, 0x00, 0x00,
+/* [0058][0059][005a][005b][005c][005d][005e][005f]*/
+/*[0058]*/ 0x80, 0x2f, 0x00, 0xa8, 0x80, 0x00, 0x00, 0x00,
+/*[0060]*/ 0x80, 0x2f, 0x00, 0x94, 0x80, 0x00, 0x00, 0x00,
+/*[0068]*/ 0x80, 0x2f, 0x00, 0x8c, 0x80, 0x00, 0x00, 0x00,
+/*[0070]*/ 0x80, 0x2f, 0x00, 0x84, 0x80, 0x00, 0x00, 0x00,
+/*[0078]*/ 0x9c, 0xfe, 0x00, 0x00, 0x9d, 0x60, 0x04, 0x08,
+/*[0080]*/ 0x80, 0x3e, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00,
+/*[0088]*/ 0x90, 0x40, 0x60, 0x00, 0x1b, 0xe1, 0x20, 0x00,
+/*[0090]*/ 0x80, 0xaf, 0x00, 0x48, 0xc0, 0x03, 0xe0, 0x00,
+/*[0098]*/ 0x8c, 0x00, 0x38, 0x02, 0x9c, 0xe4, 0x10, 0x17,
+/*[00a0]*/ 0x80, 0x00, 0x00, 0x00, 0x9d, 0x04, 0x18, 0x17,
+/*[00a8]*/ 0x1c, 0xe5, 0xe0, 0x04, 0x1c, 0xe1, 0xe0, 0x00,
+/* [00b0][00b1][00b2][00b3][00b4][00b5][00b6][00b7]*/
+/*[00b0]*/ 0x80, 0xaf, 0x00, 0x18, 0x98, 0x03, 0x08, 0x20,
+/*[00b8]*/ 0x9a, 0x85, 0x00, 0x02, 0x9c, 0xe4, 0x10, 0x17,
+/*[00c0]*/ 0x0c, 0xaf, 0xff, 0xf4, 0x9d, 0x04, 0x18, 0x17,
+/*[00c8]*/ 0xa0, 0x01, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00,
+/*[00d0]*/ 0x80, 0xaf, 0x00, 0x30, 0x80, 0x00, 0x00, 0x00,
+/*[00d8]*/ 0xa0, 0x01, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00,
+/*[00e0]*/ 0x93, 0x40, 0x50, 0x03, 0xc0, 0x02, 0x80, 0x00,
+/*[00e8]*/ 0x9d, 0x62, 0x04, 0x08, 0x9b, 0xc1, 0xfb, 0xff,
+/*[00f0]*/ 0x9d, 0xe0, 0x04, 0x0a, 0x9d, 0x61, 0x04, 0x0c,
+/*[00f8]*/ 0x9d, 0xe0, 0x00, 0x00, 0x9d, 0x60, 0x04, 0x0a,
+/*[0100]*/ 0x80, 0x2f, 0xff, 0xf8, 0x80, 0x00, 0x00, 0x00,
+/* [0108][0109][010a][010b][010c][010d][010e][010f]*/
+/*[0108]*/ 0x94, 0xcf, 0xfe, 0xf0, 0x95, 0x06, 0x03, 0xff,
+/*[0110]*/ 0xc0, 0x07, 0xe0, 0x00, 0x98, 0x03, 0x30, 0x27,
+/*[0118]*/ 0x9d, 0xe0, 0x18, 0x00, 0x30, 0x00, 0x0c, 0x07,
+/*[0120]*/ 0x14, 0x40, 0x00, 0x01, 0x98, 0x24, 0x30, 0x20,
+/*[0128]*/ 0x8c, 0x3f, 0xf8, 0x01, 0x49, 0xa8, 0x13, 0x9f,
+/*[0130]*/ 0x99, 0xc4, 0x20, 0x28, 0x98, 0x73, 0x00, 0x20,
+/*[0138]*/ 0x99, 0x0a, 0x30, 0x27, 0x8c, 0x07, 0xf8, 0x07,
+/*[0140]*/ 0x79, 0x60, 0x2b, 0x87, 0x79, 0x40, 0x2b, 0x07,
+/*[0148]*/ 0x9c, 0x74, 0x50, 0x17, 0x9c, 0x75, 0x50, 0x17,
+/*[0150]*/ 0x34, 0x00, 0xc0, 0x07, 0x34, 0x00, 0x80, 0x07,
+/*[0158]*/ 0x98, 0x13, 0x98, 0x34, 0x98, 0x13, 0x98, 0x35,
+/* [0160][0161][0162][0163][0164][0165][0166][0167]*/
+/*[0160]*/ 0x98, 0x85, 0x00, 0x20, 0x99, 0x4b, 0x00, 0x20,
+/*[0168]*/ 0xdf, 0xf5, 0xff, 0xff, 0x9a, 0x8a, 0x04, 0x00,
+/*[0170]*/ 0x8c, 0x3f, 0xf8, 0x06, 0x9c, 0xe9, 0x50, 0x00,
+/*[0178]*/ 0x98, 0x05, 0x28, 0x2b, 0x98, 0xd4, 0x48, 0x29,
+/*[0180]*/ 0x9d, 0xf4, 0x50, 0x00, 0x9c, 0xe6, 0x50, 0x17,
+/*[0188]*/ 0x98, 0x05, 0x48, 0x25, 0x98, 0xcb, 0x30, 0x34,
+/*[0190]*/ 0x95, 0x6a, 0xe0, 0x00, 0x7c, 0xa0, 0x00, 0x58,
+/*[0198]*/ 0x1c, 0xf1, 0x04, 0x0c, 0x1c, 0xee, 0x04, 0x14,
+/*[01a0]*/ 0x9c, 0x11, 0x04, 0x0e, 0x9c, 0xec, 0x58, 0x00,
+/*[01a8]*/ 0x1c, 0xf2, 0x04, 0x20, 0x98, 0x8c, 0x60, 0x33,
+/*[01b0]*/ 0x98, 0x0c, 0x60, 0x25, 0xa0, 0x01, 0x00, 0x00,
+/* [01b8][01b9][01ba][01bb][01bc][01bd][01be][01bf]*/
+/*[01b8]*/ 0x98, 0x02, 0xb0, 0xa2, 0x87, 0x64, 0x7f, 0x67,
+};
diff --git a/dsp3210/DSP3210_emulation.h b/dsp3210/DSP3210_emulation.h
new file mode 100644 (file)
index 0000000..189e78c
--- /dev/null
@@ -0,0 +1,81 @@
+
+
+
+/********************************************************/
+/* Initialise the DSP emulator                          */
+/*                                                      */
+/********************************************************/
+void DSP_init_emu ();
+
+/********************************************************/
+/* Shut down the DSP emulator                           */
+/*                                                      */
+/********************************************************/
+void DSP_shutdown_emu ();
+
+/********************************************************/
+/* Reset the DSP                                        */
+/*                                                      */
+/********************************************************/
+void DSP_reset();
+//note this is triggered via bit 7 of 0xDD0080 going from 1 to 0
+
+/********************************************************/
+/* Trigger an interrupt level 0                         */
+/*                                                      */
+/********************************************************/
+bool DSP_int0();
+bool DSP_int0_masked();
+//note this is triggered via bit 0 of 0xDD0080 going from 1 to 0
+
+/********************************************************/
+/* Trigger an interrupt level 1                         */
+/*                                                      */
+/********************************************************/
+bool DSP_int1();
+bool DSP_int1_masked();
+//note this is triggered via bit 1 of 0xDD0080 going from 1 to 0
+
+/********************************************************/
+/* DSP has changed M68k interrupt line                  */
+/*                                                      */
+/********************************************************/
+void DSP_external_interrupt(int32_t level, int32_t state);
+//state is the state of the associated line, 0 triggers an M68k interrupt
+//level=0 corresponds to INT2, level=1 corresponds to INT6
+//this routine needs to mask interrupts 
+
+/********************************************************/
+/* Execute a single DSP instruction, allowing for       */
+/* instruction and memory latencies                     */
+/********************************************************/
+void DSP_execute_insn ();
+
+/********************************************************/
+/* Read values from the Amiga's memory space            */
+/*                                                      */
+/********************************************************/
+
+uint32_t DSP_get_long_ext(uint32_t addr);
+uint16_t DSP_get_short_ext(uint32_t addr);
+unsigned char DSP_get_char_ext(uint32_t addr);
+
+
+/********************************************************/
+/* Set values in the Amiga's memory space               */
+/*                                                      */
+/********************************************************/
+
+void DSP_set_long_ext(uint32_t addr, uint32_t value);
+void DSP_set_short_ext(uint32_t addr, uint16_t value);
+void DSP_set_char_ext(uint32_t addr, unsigned char value);
+
+extern char DSP_irsh_flag;
+
+//Notes:
+//The DSP write register is byte sized and located at 0xDD0080
+//The DSP read register (which should mirror the write register)
+//is long word sized and located at 0xDD005C
+//
+//For more details on the Amiga interface to the DSP3210, see here: 
+//http://www.devili.iki.fi/mirrors/haynie/research/a3000p/docs/dspprg.pdf
\ No newline at end of file
diff --git a/dsp3210/dsp_glue.cpp b/dsp3210/dsp_glue.cpp
new file mode 100644 (file)
index 0000000..5c9b88c
--- /dev/null
@@ -0,0 +1,353 @@
+
+#include "stdlib.h"
+#include "stdint.h"
+
+#include "dsp3210/DSP3210_emulation.h"
+
+#include "sysconfig.h"
+#include "sysdeps.h"
+#include "options.h"
+#include "memory.h"
+#include "custom.h"
+#include "devices.h"
+#include "uae.h"
+#include "autoconf.h"
+#include "debug.h"
+#include "newcpu.h"
+#include "threaddep/thread.h"
+#include "dsp_glue.h"
+
+#define DSP_INST_COUNT_WAIT 1000
+
+int log_dsp = 0;
+static volatile uae_u8 dsp_status;
+bool is_dsp_installed;
+static volatile int dsp_thread_running;
+static uae_sem_t reset_sem, pause_sem;
+static volatile uae_atomic dsp_int;
+static volatile uae_atomic dsp_int_ext;
+static int dsp_int0_delay, dsp_int1_delay;
+static volatile bool dsp_running;
+static volatile uae_u32 dsp_inst_cnt;
+static bool dsp_paused;
+
+static bool dsp_addr_check(uint32_t addr)
+{
+       addrbank *ab = &get_mem_bank(addr);
+       if ((ab->flags & ABFLAG_THREADSAFE) == 0 && ab != &dummy_bank) {
+               write_log("DSP accesses non-threadsafe address %08x!\n", addr);
+               return false;
+       }
+       return true;
+}
+static uint32_t safe_memory_read(uint32_t addr, int size)
+{
+       return 0;
+}
+static void safe_memory_write(uint32_t addr, uint32_t data, int size)
+{
+}
+
+uint32_t DSP_get_long_ext(uint32_t addr)
+{
+       int32_t v;
+       if (dsp_addr_check(addr)) {
+               v = get_long(addr);
+       } else {
+               v = safe_memory_read(addr, 4);
+       }
+       v = _byteswap_ulong(v);
+       if (log_dsp) {
+               write_log("DSP LGET %08x = %08x\n", addr, v);
+       }
+       return v;
+}
+
+uint16_t DSP_get_short_ext(uint32_t addr)
+{
+       uint16_t v;
+       if (dsp_addr_check(addr)) {
+               v = get_word(addr);
+       } else {
+               v = safe_memory_read(addr, 2);
+       }
+       v = _byteswap_ushort(v);
+       if (log_dsp) {
+               write_log("DSP WGET %08x = %04x\n", addr, v & 0xffff);
+       }
+       return v;
+}
+
+unsigned char DSP_get_char_ext(uint32_t addr)
+{
+       unsigned char v;
+       if (dsp_addr_check(addr)) {
+               v = get_byte(addr);
+       } else {
+               v = safe_memory_read(addr, 1);
+       }
+       if (log_dsp) {
+               write_log("DSP BGET %08x = %02x\n", addr, v & 0xff);
+       }
+       return v;
+}
+
+void DSP_set_long_ext(uint32_t addr, uint32_t v)
+{
+       v = _byteswap_ulong(v);
+       if (log_dsp) {
+               write_log("DSP LPUT %08x = %08x\n", addr, v);
+       }
+       if (dsp_addr_check(addr)) {
+               put_long(addr, v);
+       } else {
+               safe_memory_write(addr, v, 4);
+       }
+}
+
+void DSP_set_short_ext(uint32_t addr, uint16_t v)
+{
+       v = _byteswap_ushort(v);
+       if (log_dsp) {
+               write_log("DSP WPUT %08x = %04x\n", addr, v & 0xffff);
+       }
+       if (dsp_addr_check(addr)) {
+               put_word(addr, v);
+       } else {
+               safe_memory_write(addr, v, 2);
+       }
+}
+
+void DSP_set_char_ext(uint32_t addr, unsigned char v)
+{
+       if (log_dsp) {
+               write_log("DSP BPUT %08x = %02x\n", addr, v & 0xff);
+       }
+       if (dsp_addr_check(addr)) {
+               put_byte(addr, v);
+       } else {
+               safe_memory_write(addr, v, 1);
+       }
+}
+
+static void dsp_status_intx(void)
+{
+       dsp_status &= ~(1 | 2 | 4 | 8);
+       dsp_status |= dsp_int;
+       dsp_status |= dsp_int_ext;
+}
+
+static void dsp_rethink(void)
+{
+       dsp_status_intx();
+       if ((dsp_status & 0x20) && !(dsp_status & 8)) {
+               if (log_dsp) {
+                       write_log("DSP INTREQ level 6\n");
+               }
+               INTREQ_0(0x8000 | 0x2000);
+       }
+       if ((dsp_status & 0x10) && !(dsp_status & 4)) {
+               if (log_dsp) {
+                       write_log("DSP INTREQ level 2\n");
+               }
+               INTREQ_0(0x8000 | 0x0008);
+       }
+}
+
+static void dsp_reset(void)
+{
+       dsp_int = 0x01 | 0x02;
+       dsp_int_ext = 0x04 | 0x08;
+}
+
+static void cpu_wait(void)
+{
+       while (dsp_inst_cnt < DSP_INST_COUNT_WAIT && dsp_thread_running > 0) {
+               x_do_cycles(CYCLE_UNIT * 8);
+       }
+}
+
+// stop CPU for a while if DSP was not waiting for interrupt
+static void dsp_do_int(int i)
+{
+       int mask = ~(1 << i);
+       if (log_dsp) {
+               write_log("DSP INT%d\n", i);
+       }
+       // stop CPU if DSP is not waiting for interrupt
+       if (DSP_irsh_flag != 4) {
+               dsp_inst_cnt = 0;
+               atomic_and(&dsp_int, mask);
+               cpu_wait();
+       } else {
+               atomic_and(&dsp_int, mask);
+       }
+}
+
+void dsp_write(uae_u8 v)
+{
+       dsp_status_intx();
+       if (log_dsp) {
+               write_log("DSP write %02x (%02x) PC=%08x\n", v, dsp_status, M68K_GETPC);
+       }
+       if (!(dsp_status & 0x80) && (v & 0x80)) {
+               dsp_status |= 0x80;
+               write_log("DSP reset released\n");
+               dsp_inst_cnt = 0;
+               uae_sem_post(&reset_sem);
+               cpu_wait();
+               write_log("DSP reset delay end\n");
+       } else if ((dsp_status & 0x80) && !(v & 0x80)) {
+               write_log("DSP reset activated\n");
+               dsp_status &= ~0x80;
+               dsp_reset();
+       }
+       if ((dsp_status & 1) && !(v & 1)) {
+               dsp_do_int(0);
+       } else if (v & 1) {
+               atomic_or(&dsp_int, 1);
+       }
+       if ((dsp_status & 2) && !(v & 2)) {
+               dsp_do_int(1);
+       } else if (v & 2) {
+               atomic_or(&dsp_int, 2);
+       }
+       dsp_status = (v & (0x40 | 0x20 | 0x10)) | (dsp_status & 0x80);
+       dsp_status_intx();
+       if (log_dsp) {
+               write_log("-> %02x\n", dsp_status);
+       }
+}
+
+uae_u8 dsp_read(void)
+{
+       dsp_status_intx();
+       uae_u8 v = dsp_status;
+       if (log_dsp) {
+               write_log("DSP read %02x\n", v);
+       }
+       return v;
+}
+
+void DSP_external_interrupt(int32_t level, int32_t state)
+{
+       int32_t mask = level ? 0x08 : 0x04;
+       if (state) {
+               if (log_dsp && !(dsp_status & mask)) {
+                       write_log("DSP interrupt %d = %d\n", level, state);
+               }
+               atomic_and(&dsp_int_ext, ~mask);
+       } else {
+               if (log_dsp && (dsp_status & mask)) {
+                       write_log("DSP interrupt %d = %d\n", level, state);
+               }
+               atomic_or(&dsp_int_ext, mask);
+       }
+       atomic_or(&uae_int_requested, 0x010000);
+}
+
+static void dsp_thread(void *v)
+{
+       dsp_thread_running = 1;
+       DSP_init_emu();
+       dsp_reset();
+       dsp_int0_delay = 0;
+       dsp_int1_delay = 0;
+
+       while (dsp_thread_running > 0) {
+               if (!(dsp_status & 0x80)) {
+                       uae_sem_wait(&reset_sem);
+                       dsp_reset();
+                       DSP_reset();
+                       dsp_inst_cnt = 0;
+               }
+               if (dsp_paused) {
+                       uae_sem_wait(&pause_sem);
+                       continue;
+               }
+               if (dsp_status & 0x80) {
+                       DSP_execute_insn();
+                       dsp_inst_cnt++;
+                       if (!(dsp_int & 1)) {
+                               dsp_int0_delay++;
+                               if (DSP_int0_masked()) {
+                                       dsp_int0_delay = 0;
+                                       if (log_dsp) {
+                                               write_log("DSP interrupt 0 masked\n");
+                                       }
+                               }
+                               if (dsp_int0_delay > 2) {
+                                       if (DSP_int0()) {
+                                               if (log_dsp) {
+                                                       write_log(_T("DSP interrupt 0 started\n"));
+                                               }
+                                       }
+                                       atomic_or(&dsp_int, 1);
+                                       dsp_int0_delay = 0;
+                               }
+                       }
+                       if (!(dsp_int & 2)) {
+                               dsp_int1_delay++;
+                               if (DSP_int1_masked()) {
+                                       dsp_int1_delay = 0;
+                                       if (log_dsp) {
+                                               write_log("DSP interrupt 1 masked\n");
+                                       }
+                               }
+                               if (dsp_int1_delay > 2) {
+                                       if (DSP_int1()) {
+                                               if (log_dsp) {
+                                                       write_log(_T("DSP interrupt 1 started\n"));
+                                               }
+                                       }
+                                       atomic_or(&dsp_int, 2);
+                                       dsp_int1_delay = 0;
+                               }
+                       }
+               }
+       }
+       DSP_shutdown_emu();
+       dsp_status = 0;
+       dsp_thread_running = 0;
+}
+
+static void dsp_free(void)
+{
+       write_log("DSP free\n");
+       if (dsp_thread_running > 0) {
+               dsp_status &= ~0x80;
+               dsp_thread_running = -1;
+               uae_sem_post(&reset_sem);
+               uae_sem_post(&pause_sem);
+               while (dsp_thread_running) {
+                       sleep_millis(2);
+               }
+               uae_sem_destroy(&reset_sem);
+       }
+       is_dsp_installed = false;
+}
+
+bool dsp_init(struct autoconfig_info *aci)
+{
+       aci->start = 0xdd0000;
+       aci->size = 0x10000;
+       dsp_status = 0;
+       dsp_reset();
+       dsp_status_intx();
+       if (aci->doinit) {
+               is_dsp_installed = true;
+               write_log("DSP init\n");
+               device_add_rethink(dsp_rethink);
+               device_add_exit(NULL, dsp_free);
+               uae_sem_init(&reset_sem, 0, 0);
+               uae_sem_init(&pause_sem, 0, 0);
+               uae_start_thread(NULL, dsp_thread, NULL, NULL);
+       }
+       return true;
+}
+
+void dsp_pause(int pause)
+{
+       dsp_paused = pause;
+       uae_sem_post(&pause_sem);
+}
diff --git a/dsp3210/dsp_glue.h b/dsp3210/dsp_glue.h
new file mode 100644 (file)
index 0000000..47a4807
--- /dev/null
@@ -0,0 +1,7 @@
+
+bool dsp_init(struct autoconfig_info *aci);
+void dsp_write(uae_u8);
+uae_u8 dsp_read(void);
+void dsp_pause(int);
+
+extern bool is_dsp_installed;
index 0f9622750709bef4941ee986c4cb42bbe28f9e9a..93266a1e18ff8684b6d95a36d4d44b647190365c 100644 (file)
@@ -50,6 +50,7 @@
 #include "sana2.h"
 #include "arcadia.h"
 #include "devices.h"
+#include "dsp3210/dsp_glue.h"
 
 
 #define CARD_FLAG_CAN_Z3 1
@@ -5289,6 +5290,14 @@ const struct expansionromtype expansionroms[] = {
                NULL, 0,
                false, EXPANSIONTYPE_INTERNAL
        },
+#ifdef WITH_DSP
+       {
+               _T("dsp3210"), _T("DSP3210"), _T("AT&T"),
+               NULL, dsp_init, NULL, NULL, ROMTYPE_DSP3210 | ROMTYPE_NOT, 0, 0, BOARD_NONAUTOCONFIG_BEFORE, true,
+               NULL, 0,
+               false, EXPANSIONTYPE_INTERNAL
+       },
+#endif
 
        /* PCI Bridgeboards */
 
index 312d221040d7c4e546b14056f6634897c0097f2c..cc807fafa045e7b1bf02ebc947b58de4c37a743f 100644 (file)
--- a/gayle.cpp
+++ b/gayle.cpp
@@ -36,6 +36,7 @@
 #include "autoconf.h"
 #include "rommgr.h"
 #include "devices.h"
+#include "dsp3210/dsp_glue.h"
 
 #define PCMCIA_SRAM 1
 #define PCMCIA_IDE 2
@@ -475,6 +476,14 @@ static int gayle_read (uaecptr addr)
        uaecptr oaddr = addr;
        uae_u32 v = 0;
        int got = 0;
+
+       if (is_dsp_installed) {
+               uaecptr daddr = addr & 0xffff;
+               if (daddr == 0x5f || daddr == 0x80) {
+                       v = dsp_read();
+                       return v;
+               }
+       }
        if (currprefs.cs_ide == IDE_A600A1200) {
                if ((addr & 0xA0000) != 0xA0000)
                        return 0;
@@ -513,9 +522,17 @@ static void gayle_write (uaecptr addr, int val)
 {
        uaecptr oaddr = addr;
        int got = 0;
+
+       if (is_dsp_installed) {
+               uaecptr daddr = addr & 0xffff;
+               if (daddr  == 0x5f || daddr == 0x80) {
+                       dsp_write(val);
+               }
+       }
        if (currprefs.cs_ide == IDE_A600A1200) {
-               if ((addr & 0xA0000) != 0xA0000)
+               if ((addr & 0xA0000) != 0xA0000) {
                        return;
+               }
        }
        addr &= 0xffff;
        if (currprefs.cs_pcmcia) {
@@ -540,7 +557,6 @@ static void gayle_write (uaecptr addr, int val)
                                write_log (_T("PCMCIA CONFIG WRITE %08X=%02X PC=%08X\n"), oaddr, (uae_u32)val & 0xff, M68K_GETPC);
                }
        }
-
        if (GAYLE_LOG)
                write_log (_T("GAYLE_WRITE %08X=%02X PC=%08X\n"), oaddr, (uae_u32)val & 0xff, M68K_GETPC);
        if (!got)
index e7973aee6b3a24f6832576c0098ff82cb6bff522..ca34b6dd3dab2ff69601f568a88be986c8089ca3 100644 (file)
@@ -206,6 +206,7 @@ extern int decode_cloanto_rom_do(uae_u8 *mem, int size, int real_size);
 #define ROMTYPE_DEVHD          0x0010008c
 #define ROMTYPE_CSMK1SCSI      0x0010008d
 #define ROMTYPE_GVPA1208       0x0010008e
+#define ROMTYPE_DSP3210                0x0010008f
 
 #define ROMTYPE_NOT                    0x00800000
 #define ROMTYPE_QUAD           0x01000000
index 04e917c16dc4a79a75245302c987587041722fc3..62499a03bc907566811c9620dd6d7c7bc2fadd66 100644 (file)
 #define WITH_SOFTFLOAT
 #define FLOPPYBRIDGE
 #define WITH_MIDIEMU
+#define WITH_DSP
 
 
 #else
index 04c6008d9c357c0c37c9f5bfe3e102b90ce603c6..718b47434046c4c4c452fa8a0bdfd38005b23719 100644 (file)
@@ -125,6 +125,7 @@ extern int log_a2065, a2065_promiscuous, log_ethernet;
 extern int rawinput_enabled_hid, rawinput_log;
 extern int log_filesys;
 extern int forcedframelatency;
+extern int log_dsp;
 int log_scsi;
 int log_net;
 int log_vsync, debug_vsync_min_delay, debug_vsync_forced_delay;
@@ -6774,6 +6775,10 @@ static int parseargs(const TCHAR *argx, const TCHAR *np, const TCHAR *np2)
                log_rp = 3;
                return 1;
        }
+       if (!_tcscmp(arg, _T("dsplog"))) {
+               log_dsp = 1;
+               return 1;
+       }
        if (!_tcscmp(arg, _T("nomultidisplay"))) {
                return 1;
        }
index 35119929aed0bf1c5772f30aa025a7a611446fe0..c2a8abe15e4b8b7615385e14091cbf181d021f1e 100644 (file)
     <ClCompile Include="..\..\devices.cpp" />
     <ClCompile Include="..\..\disasm.cpp" />
     <ClCompile Include="..\..\dlopen.cpp" />
+    <ClCompile Include="..\..\dsp3210\DSP3210_emulation.cpp" />
+    <ClCompile Include="..\..\dsp3210\dsp_glue.cpp" />
     <ClCompile Include="..\..\ethernet.cpp" />
     <ClCompile Include="..\..\events.cpp" />
     <ClCompile Include="..\..\flashrom.cpp" />
index 9a92b75e22895c88077db29abd2f18cb7818c111..3cc050909d4c5b6a271c3f975510c6c40f5d74d4 100644 (file)
@@ -74,6 +74,9 @@
       <UniqueIdentifier>{5c4c971a-37b6-4c1e-82f1-d225ebb12808}</UniqueIdentifier>
       <Extensions>ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe</Extensions>
     </Filter>
+    <Filter Include="dsp3210">
+      <UniqueIdentifier>{6f046035-4e6d-4038-a65f-d789a89ee702}</UniqueIdentifier>
+    </Filter>
   </ItemGroup>
   <ItemGroup>
     <ClCompile Include="..\ahidsound_dsonly.cpp">
     <ClCompile Include="..\..\midiemu.cpp">
       <Filter>common</Filter>
     </ClCompile>
+    <ClCompile Include="..\..\dsp3210\DSP3210_emulation.cpp">
+      <Filter>dsp3210</Filter>
+    </ClCompile>
+    <ClCompile Include="..\..\dsp3210\dsp_glue.cpp">
+      <Filter>dsp3210</Filter>
+    </ClCompile>
   </ItemGroup>
   <ItemGroup>
     <None Include="..\resources\35floppy.ico">