]> git.unchartedbackwaters.co.uk Git - francis/winuae.git/commitdiff
2820b5
authorToni Wilen <twilen@winuae.net>
Fri, 25 Jul 2014 08:49:34 +0000 (11:49 +0300)
committerToni Wilen <twilen@winuae.net>
Fri, 25 Jul 2014 08:49:34 +0000 (11:49 +0300)
47 files changed:
cfgfile.cpp
cpuboard.cpp
cpummu.cpp
cpummu30.cpp
custom.cpp
disk.cpp
expansion.cpp
filesys.cpp
flashrom.cpp [new file with mode: 0644]
fpp.cpp
gayle.cpp
gencpu.cpp
hardfile.cpp
include/cpu_prefetch.h
include/cpuboard.h
include/cpummu.h
include/cpummu030.h
include/filesys.h
include/flashrom.h [new file with mode: 0644]
include/gui.h
include/mmu_common.h
include/ncr_scsi.h
include/newcpu.h
include/options.h
jit/gencomp.cpp
main.cpp
memory.cpp
ncr_scsi.cpp
newcpu.cpp
newcpu_common.cpp
od-win32/hardfile_win32.cpp
od-win32/md-fpp.h
od-win32/mman.cpp
od-win32/resources/winuae.rc
od-win32/serial_win32.cpp
od-win32/statusline_win32.cpp
od-win32/sysconfig.h
od-win32/win32.h
od-win32/win32gui.cpp
od-win32/winuae_msvc11/winuae_msvc.vcxproj
od-win32/winuae_msvc11/winuae_msvc.vcxproj.filters
od-win32/winuaechangelog.txt
qemuvga/lsi53c710.cpp [new file with mode: 0644]
qemuvga/lsi53c895a.cpp
qemuvga/qemuuaeglue.h
qemuvga/scsi/scsi.h
statusline.cpp

index 99fb6086b4d9b44522ae0b14a2a72aada2580bdb..ea613798306b0dc45a7b9a58bb91cbe0559d3fa9 100644 (file)
@@ -205,7 +205,7 @@ static const TCHAR *rtgtype[] = {
        _T("Spectrum28/24_Z2"), _T("Spectrum28/24_Z3"),
        _T("PicassoIV_Z2"), _T("PicassoIV_Z3"),
        0 };
-static const TCHAR *cpuboards[] = {    _T("none"), _T("Blizzard1230IV"), _T("Blizzard1260"), _T("Blizzard2060"), _T("WarpEngineA4000"), NULL };
+static const TCHAR *cpuboards[] = {    _T("none"), _T("Blizzard1230IV"), _T("Blizzard1260"), _T("Blizzard2060"), _T("CyberStormMK3"), _T("CyberStormPPC"), _T("BlizzardPPC"), _T("WarpEngineA4000"), NULL };
 static const TCHAR *waitblits[] = { _T("disabled"), _T("automatic"), _T("noidleonly"), _T("always"), 0 };
 static const TCHAR *autoext2[] = { _T("disabled"), _T("copy"), _T("replace"), 0 };
 static const TCHAR *leds[] = { _T("power"), _T("df0"), _T("df1"), _T("df2"), _T("df3"), _T("hd"), _T("cd"), _T("fps"), _T("cpu"), _T("snd"), _T("md"), 0 };
@@ -215,7 +215,7 @@ static const TCHAR *hdcontrollers[] = {
        _T("uae"),
        _T("ide%d"),
        _T("scsi%d"), _T("scsi%d_a2091"),  _T("scsi%d_a2091-2"), _T("scsi%d_a4091"),  _T("scsi%d_a4091-2"),
-       _T("scsi%d_a3000"),  _T("scsi%d_a4000t"),  _T("scsi%d_cdtv"), _T("scsi%d_warpengine"),
+       _T("scsi%d_a3000"),  _T("scsi%d_a4000t"),  _T("scsi%d_cdtv"), _T("scsi%d_cpuboard"),
        _T("scsram"), _T("scide")
 };
 static const TCHAR *obsolete[] = {
@@ -1072,10 +1072,8 @@ void cfgfile_save_options (struct zfile *f, struct uae_prefs *p, int type)
        cfgfile_write_bool (f, _T("comp_nf"), p->compnf);
        cfgfile_write_bool (f, _T("comp_constjump"), p->comp_constjump);
        cfgfile_write_bool (f, _T("comp_oldsegv"), p->comp_oldsegv);
-
        cfgfile_write_str (f, _T("comp_flushmode"), flushmode[p->comp_hardflush]);
        cfgfile_write_bool (f, _T("compfpu"), p->compfpu);
-       cfgfile_write_bool (f, _T("fpu_strict"), p->fpu_strict);
        cfgfile_write_bool (f, _T("comp_midopt"), p->comp_midopt);
        cfgfile_write_bool (f, _T("comp_lowopt"), p->comp_lowopt);
        cfgfile_write_bool (f, _T("avoid_cmov"), p->avoid_cmov);
@@ -1483,6 +1481,8 @@ void cfgfile_save_options (struct zfile *f, struct uae_prefs *p, int type)
        cfgfile_write_bool (f, _T("cycle_exact"), p->cpu_cycle_exact && p->blitter_cycle_exact ? 1 : 0);
        cfgfile_dwrite_bool (f, _T("fpu_no_unimplemented"), p->fpu_no_unimplemented);
        cfgfile_dwrite_bool (f, _T("cpu_no_unimplemented"), p->int_no_unimplemented);
+       cfgfile_write_bool (f, _T("fpu_strict"), p->fpu_strict);
+       cfgfile_dwrite_bool (f, _T("fpu_softfloat"), p->fpu_softfloat);
 
        cfgfile_write_bool (f, _T("rtg_nocustom"), p->picasso96_nocustom);
        cfgfile_write (f, _T("rtg_modes"), _T("0x%x"), p->picasso96_modeflags);
@@ -3037,8 +3037,8 @@ static void get_filesys_controller (const TCHAR *hdc, int *type, int *num)
                                hdcv = HD_CONTROLLER_TYPE_SCSI_A4000T;
                        if (!_tcsicmp(ext, _T("cdtv")))
                                hdcv = HD_CONTROLLER_TYPE_SCSI_CDTV;
-                       if (!_tcsicmp(ext, _T("warpengine")))
-                               hdcv = HD_CONTROLLER_TYPE_SCSI_WARPENGINE;
+                       if (!_tcsicmp(ext, _T("cpuboard")))
+                               hdcv = HD_CONTROLLER_TYPE_SCSI_CPUBOARD;
                }
        } else if (_tcslen (hdc) >= 6 && !_tcsncmp (hdc, _T("scsram"), 6)) {
                hdcv = HD_CONTROLLER_TYPE_PCMCIA_SRAM;
@@ -3561,12 +3561,13 @@ static int cfgfile_parse_hardware (struct uae_prefs *p, const TCHAR *option, TCH
                || cfgfile_yesno (option, value, _T("serial_on_demand"), &p->serial_demand)
                || cfgfile_yesno (option, value, _T("serial_hardware_ctsrts"), &p->serial_hwctsrts)
                || cfgfile_yesno (option, value, _T("serial_direct"), &p->serial_direct)
+               || cfgfile_yesno (option, value, _T("fpu_strict"), &p->fpu_strict)
+               || cfgfile_yesno (option, value, _T("fpu_softfloat"), &p->fpu_softfloat)
                || cfgfile_yesno (option, value, _T("comp_nf"), &p->compnf)
                || cfgfile_yesno (option, value, _T("comp_constjump"), &p->comp_constjump)
                || cfgfile_yesno (option, value, _T("comp_oldsegv"), &p->comp_oldsegv)
                || cfgfile_yesno (option, value, _T("compforcesettings"), &dummybool)
                || cfgfile_yesno (option, value, _T("compfpu"), &p->compfpu)
-               || cfgfile_yesno (option, value, _T("fpu_strict"), &p->fpu_strict)
                || cfgfile_yesno (option, value, _T("comp_midopt"), &p->comp_midopt)
                || cfgfile_yesno (option, value, _T("comp_lowopt"), &p->comp_lowopt)
                || cfgfile_yesno (option, value, _T("rtg_nocustom"), &p->picasso96_nocustom)
@@ -5240,7 +5241,6 @@ void default_prefs (struct uae_prefs *p, int type)
        p->comp_constjump = 1;
        p->comp_oldsegv = 0;
        p->compfpu = 1;
-       p->fpu_strict = 0;
        p->cachesize = 0;
        p->avoid_cmov = 0;
        p->comp_midopt = 0;
@@ -5388,6 +5388,8 @@ void default_prefs (struct uae_prefs *p, int type)
        p->fpu_revision = 0;
        p->fpu_no_unimplemented = false;
        p->int_no_unimplemented = false;
+       p->fpu_strict = 0;
+       p->fpu_softfloat = 0;
        p->m68k_speed = 0;
        p->cpu_compatible = 1;
        p->address_space_24 = 1;
index ed20bc491ccdedc1e2bab8f3288f84a406321b28..8681f1648296aadc5d7929418c32da31bbc605c6 100644 (file)
 #include "cpuboard.h"
 #include "custom.h"
 #include "newcpu.h"
+#include "ncr_scsi.h"
+#include "debug.h"
+#include "flashrom.h"
+#include "uae.h"
+
+#define F0_WAITSTATES (2 * CYCLE_UNIT)
+
+// CS MK3
+#define CYBERSTORM_MAPROM_BASE 0xfff00000
+#define CSIII_NCR                      0xf40000
+#define CSIII_BASE                     0xf60000
+#define CSIII_REG_RESET                0x00 // 0x00
+#define CSIII_REG_IRQ          0x01 // 0x08
+#define CSIII_REG_WAITSTATE    0x02 // 0x10
+#define CSIII_REG_SHADOW       0x03 // 0x18
+#define CSIII_REG_LOCK         0x04 // 0x20
+#define CSIII_REG_INT          0x05 // 0x28
+#define CSIII_IPL_EMU          0x06 // 0x30
+#define CSIII_INT_LVL          0x07 // 0x38
+#define BPPC_MAGIC                     0x13
+
+/* bit definitions */
+#define        P5_SET_CLEAR    0x80
+/* REQ_RESET */
+#define        P5_PPC_RESET    0x10
+#define        P5_M68K_RESET   0x08
+#define        P5_AMIGA_RESET  0x04
+#define        P5_AUX_RESET    0x02
+#define        P5_SCSI_RESET   0x01
+/* REG_WAITSTATE */
+#define        P5_PPC_WRITE    0x08
+#define        P5_PPC_READ     0x04
+#define        P5_M68K_WRITE   0x02
+#define        P5_M68K_READ    0x01
+/* REG_SHADOW */
+#define        P5_SELF_RESET   0x40
+#define        P5_SHADOW       0x01
+/* REG_LOCK */
+#define        P5_MAGIC1       0x60
+#define        P5_MAGIC2       0x50
+#define        P5_MAGIC3       0x30
+#define        P5_MAGIC4       0x70
+/* REG_INT */
+#define        P5_ENABLE_IPL   0x02
+#define        P5_INT_MASTER   0x01
+/* IPL_EMU */
+#define        P5_DISABLE_INT  0x40
+#define        P5_M68K_IPL2    0x20
+#define        P5_M68K_IPL1    0x10
+#define        P5_M68K_IPL0    0x08
+#define        P5_PPC_IPL2     0x04
+#define        P5_PPC_IPL1     0x02
+#define        P5_PPC_IPL0     0x01
+#define P5_IPL_MASK    0x07
+/* INT_LVL */
+#define        P5_LVL7         0x40
+#define        P5_LVL6         0x20
+#define        P5_LVL5         0x10
+#define        P5_LVL4         0x08
+#define        P5_LVL3         0x04
+#define        P5_LVL2         0x02
+#define        P5_LVL1         0x01
+
+#define CS_RAM_BASE 0x0c000000
 
 #define BLIZZARD_RAM_BASE 0x68000000
 #define BLIZZARD_RAM_ALIAS_BASE 0x48000000
@@ -33,11 +97,23 @@ static int maprom_state;
 static uae_u32 maprom_base;
 static int delayed_rom_protect;
 static int f0rom_size, earom_size;
+static uae_u8 io_reg[64];
+static void *flashrom;
+static struct zfile *flashrom_file;
+static int flash_unlocked;
 
 static bool is_blizzard(void)
 {
        return currprefs.cpuboard_type == BOARD_BLIZZARD_1230_IV || currprefs.cpuboard_type == BOARD_BLIZZARD_1260 || currprefs.cpuboard_type == BOARD_BLIZZARD_2060; 
 }
+static bool is_cs(void)
+{
+       return currprefs.cpuboard_type == BOARD_CSMK3 || currprefs.cpuboard_type == BOARD_CSPPC;
+}
+static bool is_blizzardppc(void)
+{
+       return currprefs.cpuboard_type == BOARD_BLIZZARDPPC;
+}
 
 extern addrbank blizzardram_bank;
 extern addrbank blizzardram_nojit_bank;
@@ -50,7 +126,7 @@ MEMORY_FUNCTIONS(blizzardram);
 addrbank blizzardram_bank = {
        blizzardram_lget, blizzardram_wget, blizzardram_bget,
        blizzardram_lput, blizzardram_wput, blizzardram_bput,
-       blizzardram_xlate, blizzardram_check, NULL, _T("Blizzard RAM"),
+       blizzardram_xlate, blizzardram_check, NULL, _T("CPUBoard RAM"),
        blizzardram_lget, blizzardram_wget, ABFLAG_RAM
 };
 
@@ -100,7 +176,7 @@ static void REGPARAM2 blizzardram_nojit_bput(uaecptr addr, uae_u32 b)
 static addrbank blizzardram_nojit_bank = {
        blizzardram_nojit_lget, blizzardram_nojit_wget, blizzardram_nojit_bget,
        blizzardram_nojit_lput, blizzardram_nojit_wput, blizzardram_nojit_bput,
-       blizzardram_nojit_xlate, blizzardram_nojit_check, NULL, _T("Blizzard RAM"),
+       blizzardram_nojit_xlate, blizzardram_nojit_check, NULL, _T("CPUBoard RAM"),
        blizzardram_nojit_lget, blizzardram_nojit_wget, ABFLAG_RAM
 };
 
@@ -160,10 +236,11 @@ static void REGPARAM2 blizzardmaprom_bput(uaecptr addr, uae_u32 b)
                kickmem_bank.baseaddr[addr] = b;
        }
 }
+
 static addrbank blizzardmaprom_bank = {
        blizzardmaprom_lget, blizzardmaprom_wget, blizzardmaprom_bget,
        blizzardmaprom_lput, blizzardmaprom_wput, blizzardmaprom_bput,
-       blizzardmaprom_xlate, blizzardmaprom_check, NULL, _T("Blizzard MAPROM"),
+       blizzardmaprom_xlate, blizzardmaprom_check, NULL, _T("CPUBoard MAPROM"),
        blizzardmaprom_lget, blizzardmaprom_wget, ABFLAG_RAM
 };
 
@@ -206,8 +283,6 @@ static addrbank blizzarde8_bank = {
        blizzarde8_lget, blizzarde8_wget, ABFLAG_IO | ABFLAG_SAFE
 };
 
-// Blizzard F0 ROM is really slow, shoud slow it down to see color flashing..
-
 static uae_u32 REGPARAM2 blizzardf0_lget(uaecptr addr)
 {
 #ifdef JIT
@@ -215,6 +290,11 @@ static uae_u32 REGPARAM2 blizzardf0_lget(uaecptr addr)
 #endif
        uae_u32 *m;
 
+       regs.memory_waitstate_cycles += F0_WAITSTATES * 6;
+
+       if (is_blizzardppc() && (flash_unlocked & 2))
+               addr += 262144;
+
        addr &= blizzardf0_bank.mask;
        m = (uae_u32 *)(blizzardf0_bank.baseaddr + addr);
        return do_get_mem_long(m);
@@ -226,6 +306,11 @@ static uae_u32 REGPARAM2 blizzardf0_wget(uaecptr addr)
 #endif
        uae_u16 *m, v;
 
+       regs.memory_waitstate_cycles += F0_WAITSTATES * 3;
+
+       if (is_blizzardppc() && (flash_unlocked & 2))
+               addr += 262144;
+
        addr &= blizzardf0_bank.mask;
        m = (uae_u16 *)(blizzardf0_bank.baseaddr + addr);
        v = do_get_mem_word(m);
@@ -237,18 +322,85 @@ static uae_u32 REGPARAM2 blizzardf0_bget(uaecptr addr)
        special_mem |= S_READ;
 #endif
        uae_u8 v;
+
+       regs.memory_waitstate_cycles += F0_WAITSTATES * 1;
+
+       if (is_cs() || is_blizzardppc()) {
+               if (is_blizzardppc() && (flash_unlocked & 2))
+                       addr += 262144;
+               if (flash_unlocked) {
+                       return flash_read(flashrom, addr);
+               }
+       }
        addr &= blizzardf0_bank.mask;
        v = blizzardf0_bank.baseaddr[addr];
        return v;
 }
 
+// hack to map F41000 SCSI SCRIPTS RAM to JIT friendly address
+void cyberstorm_scsi_ram_put(uaecptr addr, uae_u32 v)
+{
+       addr &= 0xffff;
+       addr += (CSIII_NCR & 0x7ffff);
+       blizzardf0_bank.baseaddr[addr] = v;
+}
+uae_u32 cyberstorm_scsi_ram_get(uaecptr addr)
+{
+       uae_u32 v;
+       addr &= 0xffff;
+       addr += (CSIII_NCR & 0x7ffff);
+       v = blizzardf0_bank.baseaddr[addr];
+       return v;
+}
+uae_u8 *REGPARAM2 cyberstorm_scsi_ram_xlate (uaecptr addr)
+{
+       addr &= 0xffff;
+       addr += (CSIII_NCR & 0x7ffff);
+       return blizzardf0_bank.baseaddr + addr;
+}
+int REGPARAM2 cyberstorm_scsi_ram_check (uaecptr a, uae_u32 b)
+{
+       a &= 0xffff;
+       return a >= 0x1000 && a + b < 0x3000;
+}
+
+static void REGPARAM2 blizzardf0_lput(uaecptr addr, uae_u32 b)
+{
+#ifdef JIT
+       special_mem |= S_WRITE;
+#endif
+       regs.memory_waitstate_cycles += F0_WAITSTATES * 6;
+}
+static void REGPARAM2 blizzardf0_wput(uaecptr addr, uae_u32 b)
+{
+#ifdef JIT
+       special_mem |= S_WRITE;
+#endif
+       regs.memory_waitstate_cycles += F0_WAITSTATES * 3;
+}
+static void REGPARAM2 blizzardf0_bput(uaecptr addr, uae_u32 b)
+{
+#ifdef JIT
+       special_mem |= S_WRITE;
+#endif
+       regs.memory_waitstate_cycles += F0_WAITSTATES * 1;
+
+       if (is_cs() || is_blizzardppc()) {
+               if (flash_unlocked) {
+                       if (is_blizzardppc() && (flash_unlocked & 2))
+                               addr += 262144;
+                       flash_write(flashrom, addr, b);
+               }
+       }
+}
+
 MEMORY_CHECK(blizzardf0);
 MEMORY_XLATE(blizzardf0);
 
 static addrbank blizzardf0_bank = {
        blizzardf0_lget, blizzardf0_wget, blizzardf0_bget,
-       blizzardea_lput, blizzardea_wput, blizzardea_bput,
-       blizzardf0_xlate, blizzardf0_check, NULL, _T("Blizzard F00000"),
+       blizzardf0_lput, blizzardf0_wput, blizzardf0_bput,
+       blizzardf0_xlate, blizzardf0_check, NULL, _T("CPUBoard F00000"),
        blizzardf0_lget, blizzardf0_wget, ABFLAG_ROM
 };
 
@@ -332,7 +484,7 @@ static uae_u32 REGPARAM2 blizzarde8_lget(uaecptr addr)
        return v;
 }
 
-static void copymaprom(void)
+static void blizzard_copymaprom(void)
 {
        uae_u8 *src = get_real_address(BLIZZARD_MAPROM_BASE);
        uae_u8 *dst = get_real_address(0xf80000);
@@ -340,36 +492,204 @@ static void copymaprom(void)
        memcpy(dst, src, 524288);
        protect_roms(true);
 }
+static void cyberstorm_copymaprom(void)
+{
+       if (blizzardmaprom_bank.baseaddr) {
+               uae_u8 *src = blizzardmaprom_bank.baseaddr;
+               uae_u8 *dst = get_real_address(0xf80000);
+               protect_roms(false);
+               memcpy(dst, src, 524288);
+               protect_roms(true);
+       }
+}
+
+void cpuboard_rethink(void)
+{
+       if (is_cs() || is_blizzardppc()) {
+               if (!(io_reg[CSIII_REG_IRQ] & 3))
+                       INTREQ(0x8000 | 0x0008);
+       }
+}
+
+static void cyberstorm_maprom(void)
+{
+       map_banks(&blizzardmaprom_bank, CYBERSTORM_MAPROM_BASE >> 16, 524288 >> 16, 0);
+}
+
+void cyberstorm_irq(int level)
+{
+       if (level)
+               io_reg[CSIII_REG_IRQ] &= ~1;
+       else
+               io_reg[CSIII_REG_IRQ] |= 1;
+       cpuboard_rethink();
+}
+
+void blizzardppc_irq(int level)
+{
+       if (level)
+               io_reg[CSIII_REG_IRQ] &= ~1;
+       else
+               io_reg[CSIII_REG_IRQ] |= 1;
+       cpuboard_rethink();
+}
+
 
 static uae_u32 REGPARAM2 blizzardio_bget(uaecptr addr)
 {
+       uae_u8 v = 0;
+#ifdef JIT
+       special_mem |= S_READ;
+#endif
+       if (is_cs() || is_blizzardppc()) {
+               uae_u32 bank = addr & 0x10000;
+               if (bank == 0) {
+                       int reg = (addr & 0xff) / 8;
+                       v = io_reg[reg];
+                       if (reg == CSIII_REG_LOCK && is_blizzardppc())
+                               v |= 0x08;
+                       if (reg != CSIII_REG_IRQ)
+                               write_log(_T("CS IO BGET %08x=%02X PC=%08x\n"), addr, v & 0xff, M68K_GETPC);
+               } else {
+                       write_log(_T("CS IO BGET %08x=%02X PC=%08x\n"), addr, v & 0xff, M68K_GETPC);
+               }
+       }
+       return v;
+}
+static uae_u32 REGPARAM2 blizzardio_wget(uaecptr addr)
+{
+#ifdef JIT
+       special_mem |= S_READ;
+#endif
+       if (is_cs() || is_blizzardppc()) {
+               ;//write_log(_T("CS IO WGET %08x\n"), addr);
+               //activate_debugger();
+       }
+       return 0;
+}
+static uae_u32 REGPARAM2 blizzardio_lget(uaecptr addr)
+{
+#ifdef JIT
+       special_mem |= S_READ;
+#endif
+       if (is_cs() || is_blizzardppc()) {
+               write_log(_T("CS IO LGET %08x PC=%08x\n"), addr, M68K_GETPC);
+               //activate_debugger();
+       }
        return 0;
 }
 static void REGPARAM2 blizzardio_bput(uaecptr addr, uae_u32 v)
 {
-       if ((addr & 65535) == (BLIZZARD_MAPROM_ENABLE & 65535)) {
-               if (v != 0x42 || maprom_state || !currprefs.maprom)
-                       return;
-               maprom_state = 1;
-               write_log(_T("Blizzard MAPROM enabled\n"));
-               copymaprom();
+#ifdef JIT
+       special_mem |= S_WRITE;
+#endif
+       if (is_blizzard()) {
+               if ((addr & 65535) == (BLIZZARD_MAPROM_ENABLE & 65535)) {
+                       if (v != 0x42 || maprom_state || !currprefs.maprom)
+                               return;
+                       maprom_state = 1;
+                       write_log(_T("Blizzard MAPROM enabled\n"));
+                       blizzard_copymaprom();
+               }
+       } else if (is_cs() || is_blizzardppc()) {
+               write_log(_T("CS IO BPUT %08x %02x PC=%08x\n"), addr, v & 0xff, M68K_GETPC);
+               uae_u32 bank = addr & 0x10000;
+               if (bank == 0) {
+                       addr &= 0xff;
+                       if (is_blizzardppc()) {
+                               if (addr == 0x92 && v == 0x42)
+                                       flash_unlocked |= 1;
+                               if (addr == 0x93)
+                                       flash_unlocked &= ~1;
+                               if (addr == 0x12) {
+                                       maprom_state = 1;
+                                       cyberstorm_copymaprom();
+                               }
+                       }
+                       addr /= 8;
+                       uae_u8 oldval = io_reg[addr];
+                       if (addr == CSIII_REG_LOCK) {
+                               if (v == P5_MAGIC1)
+                                       io_reg[CSIII_REG_LOCK] = v;
+                               else if (v == P5_MAGIC2 && io_reg[CSIII_REG_LOCK] == P5_MAGIC1)
+                                       io_reg[CSIII_REG_LOCK] = v;
+                               else if (v == P5_MAGIC3 && io_reg[CSIII_REG_LOCK] == P5_MAGIC2)
+                                       io_reg[CSIII_REG_LOCK] = v;
+                               else if (v == P5_MAGIC4 && io_reg[CSIII_REG_LOCK] == P5_MAGIC3)
+                                       io_reg[CSIII_REG_LOCK] = v;
+                               else
+                                       io_reg[CSIII_REG_LOCK] = 0;
+                               if (io_reg[CSIII_REG_LOCK] == P5_MAGIC3)
+                                       flash_unlocked |= 2;
+                               else
+                                       flash_unlocked &= ~2;
+                       } else {
+                               uae_u32 regval;
+                               if (addr == CSIII_REG_SHADOW && io_reg[CSIII_REG_LOCK] != P5_MAGIC3)
+                                       return;
+                               if (v & 0x80)
+                                       io_reg[addr] |= v & 0x7f;
+                               else
+                                       io_reg[addr] &= ~v;
+                               regval = io_reg[addr];
+                               if (addr == CSIII_REG_RESET) {
+                                       if (regval & P5_SCSI_RESET) {
+                                               if (is_blizzardppc())
+                                                       map_banks(&ncr_bank_blizzardppc, 0xf40000 >> 16, 65536 >> 16, 0);
+                                               else
+                                                       map_banks(&ncr_bank_cyberstorm, 0xf40000 >> 16, 65536 >> 16, 0);
+                                       } else {
+                                               map_banks(&dummy_bank, 0xf40000 >> 16, 65536 >> 16, 0);
+                                       }
+                                       if (!(regval & P5_AMIGA_RESET)) {
+                                               uae_reset(0, 0);
+                                               io_reg[addr] |= P5_AMIGA_RESET;
+                                       }
+                                       if (!(regval & P5_M68K_RESET)) {
+                                               m68k_reset();
+                                               io_reg[addr] |= P5_M68K_RESET;
+                                       }
+                               } else if (addr == CSIII_REG_SHADOW) {
+                                       if (is_cs() && ((oldval ^ regval) & 1)) {
+                                               maprom_state = (regval & 1) ? 0 : 1;
+                                               cyberstorm_copymaprom();
+                                       }
+                               }
+                               cpuboard_rethink();
+                       }
+               }
        }
 }
 static void REGPARAM2 blizzardio_wput(uaecptr addr, uae_u32 v)
 {
-       if((addr & 65535) == (BLIZZARD_BOARD_DISABLE & 65535)) {
-               if (v != 0xcafe)
-                       return;
-               write_log(_T("Blizzard board disable!\n"));
-               cpu_halt(4); // not much choice..
+#ifdef JIT
+       special_mem |= S_WRITE;
+#endif
+       if (is_blizzard()) {
+               if((addr & 65535) == (BLIZZARD_BOARD_DISABLE & 65535)) {
+                       if (v != 0xcafe)
+                               return;
+                       write_log(_T("Blizzard board disable!\n"));
+                       cpu_halt(4); // not much choice..
+               }
+       } else if (is_cs() || is_blizzardppc()) {
+               write_log(_T("CS IO WPUT %08x %04x\n"), addr, v);
+       }
+}
+static void REGPARAM2 blizzardio_lput(uaecptr addr, uae_u32 v)
+{
+#ifdef JIT
+       special_mem |= S_WRITE;
+#endif
+       if (is_cs() || is_blizzardppc()) {
+               write_log(_T("CS IO LPUT %08x %08x\n"), addr, v);
        }
 }
-
 static addrbank blizzardio_bank = {
-       blizzardio_bget, blizzardio_bget, blizzardio_bget,
-       blizzardio_wput, blizzardio_wput, blizzardio_bput,
-       default_xlate, default_check, NULL, _T("Blizzard IO"),
-       blizzardio_bget, blizzardio_bget, ABFLAG_IO
+       blizzardio_lget, blizzardio_wget, blizzardio_bget,
+       blizzardio_lput, blizzardio_wput, blizzardio_bput,
+       default_xlate, default_check, NULL, _T("CPUBoard IO"),
+       blizzardio_wget, blizzardio_bget, ABFLAG_IO
 };
 
 void cpuboard_vsync(void)
@@ -385,39 +705,64 @@ void cpuboard_map(void)
 {
        if (!currprefs.cpuboard_type)
                return;
-       if (cpuboard_size) {
-               if (blizzard_jit) {
-                       map_banks(&blizzardram_bank, blizzardram_bank.start >> 16, cpuboard_size >> 16, 0);
-                       map_banks(&blizzardram_bank, BLIZZARD_RAM_BASE >> 16, cpuboard_size >> 16, 0);
-               } else {
-                       for (int i = 0; i < 0x08000000; i += cpuboard_size) {
-                               map_banks_nojitdirect(&blizzardram_nojit_bank, (BLIZZARD_RAM_ALIAS_BASE + i)  >> 16, cpuboard_size >> 16, 0);
-                               map_banks_nojitdirect(&blizzardram_nojit_bank, (BLIZZARD_RAM_BASE + i) >> 16, cpuboard_size >> 16, 0);
-                       }
-                       if (currprefs.maprom) {
+       if (is_blizzard() || is_blizzardppc()) {
+               if (cpuboard_size) {
+                       if (blizzard_jit) {
+                               map_banks(&blizzardram_bank, blizzardram_bank.start >> 16, cpuboard_size >> 16, 0);
+                               map_banks(&blizzardram_bank, BLIZZARD_RAM_BASE >> 16, cpuboard_size >> 16, 0);
+                       } else {
                                for (int i = 0; i < 0x08000000; i += cpuboard_size) {
-                                       map_banks_nojitdirect(&blizzardmaprom_bank, (BLIZZARD_RAM_ALIAS_BASE + i + cpuboard_size - 524288) >> 16, 524288 >> 16, 0);
-                                       map_banks_nojitdirect(&blizzardmaprom_bank, (BLIZZARD_RAM_BASE + i + cpuboard_size - 524288) >> 16, 524288 >> 16, 0);
+                                       map_banks_nojitdirect(&blizzardram_nojit_bank, (BLIZZARD_RAM_ALIAS_BASE + i)  >> 16, cpuboard_size >> 16, 0);
+                                       map_banks_nojitdirect(&blizzardram_nojit_bank, (BLIZZARD_RAM_BASE + i) >> 16, cpuboard_size >> 16, 0);
+                               }
+                               if (currprefs.maprom && !is_blizzardppc()) {
+                                       for (int i = 0; i < 0x08000000; i += cpuboard_size) {
+                                               map_banks_nojitdirect(&blizzardmaprom_bank, (BLIZZARD_RAM_ALIAS_BASE + i + cpuboard_size - 524288) >> 16, 524288 >> 16, 0);
+                                               map_banks_nojitdirect(&blizzardmaprom_bank, (BLIZZARD_RAM_BASE + i + cpuboard_size - 524288) >> 16, 524288 >> 16, 0);
+                                       }
                                }
                        }
                }
+               if (!is_blizzardppc()) {
+                       map_banks(&blizzardf0_bank, 0xf00000 >> 16, 65536 >> 16, 0);
+                       map_banks(&blizzardio_bank, BLIZZARD_MAPROM_ENABLE >> 16, 65536 >> 16, 0);
+                       map_banks(&blizzardio_bank, BLIZZARD_BOARD_DISABLE >> 16, 65536 >> 16, 0);
+               } else {
+                       map_banks(&blizzardf0_bank, 0xf00000 >> 16, 0x60000 >> 16, 0);
+                       map_banks(&blizzardio_bank, 0xf60000 >> 16, (2 * 65536) >> 16, 0);
+                       map_banks(&blizzardf0_bank, 0xf70000 >> 16, 0x10000 >> 16, 0);
+                       cyberstorm_maprom();
+               }
        }
-       if (f0rom_size)
-               map_banks(&blizzardf0_bank, 0xf00000 >> 16, f0rom_size >> 16, 0);
-       if (is_blizzard()) {
-               map_banks(&blizzardio_bank, BLIZZARD_MAPROM_ENABLE >> 16, 65536 >> 16, 0);
-               map_banks(&blizzardio_bank, BLIZZARD_BOARD_DISABLE >> 16, 65536 >> 16, 0);
+       if (is_cs()) {
+               map_banks(&blizzardf0_bank, 0xf00000 >> 16, 262144 >> 16, 0);
+               map_banks(&blizzardio_bank, 0xf50000 >> 16, (3 * 65536) >> 16, 0);
+               cyberstorm_maprom();
        }
 }
 
 void cpuboard_reset(bool hardreset)
 {
-       canbang = 0;
+       if (is_blizzard() || is_blizzardppc())
+               canbang = 0;
        configured = false;
        delayed_rom_protect = 0;
        currprefs.cpuboardmem1_size = changed_prefs.cpuboardmem1_size;
        if (hardreset || !currprefs.maprom)
                maprom_state = 0;
+       if (is_cs() || is_blizzardppc()) {
+               if (hardreset)
+                       memset(io_reg, 0x7f, sizeof io_reg);
+               io_reg[CSIII_REG_RESET] = 0x7f;
+               io_reg[CSIII_REG_IRQ] = 0x7f;
+               maprom_state = 0;
+       }
+       flash_unlocked = 0;
+
+       flash_free(flashrom);
+       flashrom = NULL;
+       zfile_fclose(flashrom_file);
+       flashrom_file = NULL;
 }
 
 void cpuboard_cleanup(void)
@@ -425,6 +770,11 @@ void cpuboard_cleanup(void)
        configured = false;
        maprom_state = 0;
 
+       flash_free(flashrom);
+       flashrom = NULL;
+       zfile_fclose(flashrom_file);
+       flashrom_file = NULL;
+
        if (blizzard_jit) {
                mapped_free(blizzardram_bank.baseaddr);
        } else {
@@ -441,6 +791,7 @@ void cpuboard_cleanup(void)
        blizzardea_bank.baseaddr = NULL;
 
        cpuboard_size = cpuboard2_size = -1;
+
 }
 
 void cpuboard_init(void)
@@ -455,7 +806,7 @@ void cpuboard_init(void)
 
        cpuboard_size = currprefs.cpuboardmem1_size;
 
-       if (is_blizzard()) {
+       if (is_blizzard() || is_blizzardppc()) {
                blizzardram_bank.start = BLIZZARD_RAM_ALIAS_BASE;
                blizzardram_bank.allocated = cpuboard_size;
                blizzardram_bank.mask = blizzardram_bank.allocated - 1;
@@ -483,14 +834,34 @@ void cpuboard_init(void)
                maprom_base = blizzardram_bank.allocated - 524288;
 
                blizzardf0_bank.start = 0x00f00000;
-               blizzardf0_bank.allocated = 262144;
+               blizzardf0_bank.allocated = 524288;
                blizzardf0_bank.mask = blizzardf0_bank.allocated - 1;
                blizzardf0_bank.baseaddr = mapped_malloc(blizzardf0_bank.allocated, _T("rom_f0"));
 
-               blizzardea_bank.allocated = 2 * 65536;
-               blizzardea_bank.mask = blizzardea_bank.allocated - 1;
-               // Blizzard 12xx autoconfig ROM must be mapped at $ea0000-$ebffff, board requires it.
-               blizzardea_bank.baseaddr = mapped_malloc(blizzardea_bank.allocated, _T("rom_ea"));
+               if (!is_blizzardppc()) {
+                       blizzardea_bank.allocated = 2 * 65536;
+                       blizzardea_bank.mask = blizzardea_bank.allocated - 1;
+                       // Blizzard 12xx autoconfig ROM must be mapped at $ea0000-$ebffff, board requires it.
+                       blizzardea_bank.baseaddr = mapped_malloc(blizzardea_bank.allocated, _T("rom_ea"));
+               }
+
+       } else if (is_cs()) {
+       
+               blizzardram_bank.start = CS_RAM_BASE;
+               blizzardram_bank.allocated = cpuboard_size;
+               blizzardram_bank.mask = blizzardram_bank.allocated - 1;
+               if (cpuboard_size)
+                       blizzardram_bank.baseaddr = mapped_malloc(blizzardram_bank.allocated, _T("cyberstorm"));
+
+               blizzardf0_bank.start = 0x00f00000;
+               blizzardf0_bank.allocated = 524288;
+               blizzardf0_bank.mask = blizzardf0_bank.allocated - 1;
+               blizzardf0_bank.baseaddr = mapped_malloc(blizzardf0_bank.allocated, _T("rom_f0"));
+
+               blizzardmaprom_bank.baseaddr = a3000hmem_bank.baseaddr + a3000hmem_bank.allocated - 524288;
+               blizzardmaprom_bank.start = CYBERSTORM_MAPROM_BASE;
+               blizzardmaprom_bank.allocated = 524288;
+               blizzardmaprom_bank.mask = 524288 - 1;
        }
 }
 
@@ -502,17 +873,38 @@ bool cpuboard_maprom(void)
 {
        if (!currprefs.cpuboard_type || !cpuboard_size)
                return false;
-       if (maprom_state)
-               copymaprom();
+       if (is_blizzard() || is_blizzardppc()) {
+               if (maprom_state)
+                       blizzard_copymaprom();
+       } else if (is_cs()) {
+               if (!(io_reg[CSIII_REG_SHADOW] & P5_SHADOW))
+                       cyberstorm_copymaprom();
+       }
        return true;
 }
 
+static struct zfile *flashfile_open(const TCHAR *name)
+{
+       struct zfile *f;
+       TCHAR path[MAX_DPATH];
+
+       fetch_rompath(path, sizeof path / sizeof(TCHAR));
+       _tcscat(path, name);
+       f = zfile_fopen(path, _T("rb+"), ZFD_NONE);
+       if (!f)
+               f = zfile_fopen(path, _T("rb"), ZFD_NORMAL);
+       return f;
+}
+
 addrbank *cpuboard_autoconfig_init(void)
 {
        struct zfile *autoconfig_rom = NULL;
        int roms[2];
        bool autoconf = true;
+       const TCHAR *romname = NULL;
 
+       roms[0] = -1;
+       roms[1] = -1;
        switch (currprefs.cpuboard_type)
        {
        case BOARD_BLIZZARD_1230_IV:
@@ -525,19 +917,42 @@ addrbank *cpuboard_autoconfig_init(void)
                roms[0] = 91;
                break;
        case BOARD_WARPENGINE_A4000:
-               roms[0] = 93;
+               expamem_next();
+               return NULL;
+       case BOARD_CSMK3:
+       case BOARD_CSPPC:
+       case BOARD_BLIZZARDPPC:
                break;
        default:
                expamem_next();
                return NULL;
        }
-       roms[1] = -1;
 
        struct romlist *rl = getromlistbyids(roms);
        if (rl) {
                autoconfig_rom = read_rom(rl->rd);
        }
-       if (!autoconfig_rom) {
+
+       if (currprefs.cpuboard_type == BOARD_CSMK3) {
+               romname = _T("cyberstormmk3.rom");
+       }
+       if (currprefs.cpuboard_type == BOARD_CSPPC) {
+               romname = _T("cyberstormppc.rom");
+       }
+       if (currprefs.cpuboard_type == BOARD_BLIZZARDPPC) {
+               romname = _T("blizzardppc.rom");
+       }
+
+       if (romname != NULL) {
+               autoconfig_rom = flashfile_open(romname);
+               if (!autoconfig_rom) {
+                       write_log(_T("Couldn't open CPU board rom '%s'\n"), romname);
+                       expamem_next();
+                       return NULL;
+               }
+       }
+
+       if (!autoconfig_rom && roms[0] != -1) {
                write_log (_T("ROM id %d not found for CPU board emulation\n"));
                expamem_next();
                return NULL;
@@ -558,11 +973,19 @@ addrbank *cpuboard_autoconfig_init(void)
                        zfile_fread(&b, 1, 1, autoconfig_rom);
                        blizzardea_bank.baseaddr[i * 2 + 0] = b;
                }
-       } else if (currprefs.cpuboard_type == BOARD_WARPENGINE_A4000) {
-               f0rom_size = 0;
+       } else if (is_cs() || is_blizzardppc()) {
+               f0rom_size = is_blizzardppc() ? 524288 : 131072;
                earom_size = 0;
+               memset(blizzardf0_bank.baseaddr, 0xff, f0rom_size);
+               zfile_fread(blizzardf0_bank.baseaddr, f0rom_size, 1, autoconfig_rom);
                autoconf = false;
-       } else {
+               if (zfile_needwrite(autoconfig_rom)) {
+                       flashrom_file = autoconfig_rom;
+                       autoconfig_rom = NULL;
+               }
+               flashrom = flash_new(blizzardf0_bank.baseaddr, f0rom_size, f0rom_size, flashrom_file);
+       }
+       else {
                f0rom_size = 65536;
                earom_size = 131072;
                // 12xx = 1x32k
@@ -578,7 +1001,7 @@ addrbank *cpuboard_autoconfig_init(void)
        zfile_fclose(autoconfig_rom);
 
        if (f0rom_size)
-               map_banks(&blizzardf0_bank, 0xf00000 >> 16, f0rom_size >> 16, 0);
+               map_banks(&blizzardf0_bank, 0xf00000 >> 16, 262144 >> 16, 0);
        if (!autoconf) {
                expamem_next();
                return NULL;
index 4fc9c54ae5594ef248fe689c0a387dff40953e12..c5ee841b386cc4b63d11ff0d764c2b35a2f9c8ed 100644 (file)
@@ -33,6 +33,8 @@
 #include "cpummu.h"
 #include "debug.h"
 
+#define MMUDUMP 0
+
 #define DBG_MMU_VERBOSE        1
 #define DBG_MMU_SANITY 1
 #if 0
@@ -41,7 +43,6 @@
 
 #ifdef FULLMMU
 
-
 uae_u32 mmu_is_super;
 uae_u32 mmu_tagmask, mmu_pagemask, mmu_pagemaski;
 struct mmu_atc_line mmu_atc_array[ATC_TYPE][ATC_WAYS][ATC_SLOTS];
@@ -108,7 +109,7 @@ void mmu_tt_modified (void)
 }
 
 
-#if 0
+#if MMUDUMP
 /* {{{ mmu_dump_table */
 static void mmu_dump_table(const char * label, uaecptr root_ptr)
 {
@@ -124,7 +125,7 @@ static void mmu_dump_table(const char * label, uaecptr root_ptr)
        uaecptr ptr_des_addr, page_addr,
                root_log, ptr_log, page_log;
 
-       write_log(_T("%s: root=%lx\n", label, root_ptr);
+       write_log(_T("%s: root=%lx\n"), label, root_ptr);
 
        for (root_idx = 0; root_idx < ROOT_TABLE_SIZE; root_idx++) {
                root_des = phys_get_long(root_ptr + root_idx);
@@ -132,7 +133,7 @@ static void mmu_dump_table(const char * label, uaecptr root_ptr)
                if ((root_des & 2) == 0)
                        continue;       /* invalid */
 
-               write_log(_T("ROOT: %03d U=%d W=%d UDT=%02d\n", root_idx,
+               write_log(_T("ROOT: %03d U=%d W=%d UDT=%02d\n"), root_idx,
                                root_des & 8 ? 1 : 0,
                                root_des & 4 ? 1 : 0,
                                root_des & 3
@@ -187,7 +188,7 @@ static void mmu_dump_table(const char * label, uaecptr root_ptr)
                        if (n_pages_used == -1)
                                continue;
 
-                       write_log(_T(" PTR: %03d U=%d W=%d UDT=%02d\n", ptr_idx,
+                       write_log(_T(" PTR: %03d U=%d W=%d UDT=%02d\n"), ptr_idx,
                                ptr_des & 8 ? 1 : 0,
                                ptr_des & 4 ? 1 : 0,
                                ptr_des & 3
@@ -198,7 +199,7 @@ static void mmu_dump_table(const char * label, uaecptr root_ptr)
                                page_des = page_info[page_idx].match;
 
                                if ((page_des & MMU_PDT_MASK) == 2) {
-                                       write_log(_T("  PAGE: %03d-%03d log=%08lx INDIRECT --> addr=%08lx\n",
+                                       write_log(_T("  PAGE: %03d-%03d log=%08lx INDIRECT --> addr=%08lx\n"),
                                                        page_info[page_idx].start_idx,
                                                        page_info[page_idx].start_idx + page_info[page_idx].n_pages - 1,
                                                        page_info[page_idx].log,
@@ -206,7 +207,7 @@ static void mmu_dump_table(const char * label, uaecptr root_ptr)
                                                  );
 
                                } else {
-                                       write_log(_T("  PAGE: %03d-%03d log=%08lx addr=%08lx UR=%02d G=%d U1/0=%d S=%d CM=%d M=%d U=%d W=%d\n",
+                                       write_log(_T("  PAGE: %03d-%03d log=%08lx addr=%08lx UR=%02d G=%d U1/0=%d S=%d CM=%d M=%d U=%d W=%d\n"),
                                                        page_info[page_idx].start_idx,
                                                        page_info[page_idx].start_idx + page_info[page_idx].n_pages - 1,
                                                        page_info[page_idx].log,
@@ -245,8 +246,8 @@ void mmu_dump_tables(void)
        mmu_dump_ttr(_T("ITT0"), regs.itt0);
        mmu_dump_ttr(_T("ITT1"), regs.itt1);
        mmu_dump_atc();
-#if MMUDEBUG
-       // mmu_dump_table("SRP", regs.srp);
+#if MMUDUMP
+       mmu_dump_table("SRP", regs.srp);
 #endif
 }
 /* }}} */
@@ -665,6 +666,26 @@ uae_u32 REGPARAM2 mmu_get_long_unaligned(uaecptr addr, bool data, bool rmw)
        return res;
 }
 
+uae_u32 REGPARAM2 mmu_get_ilong_unaligned(uaecptr addr)
+{
+       uae_u32 res;
+
+       if (likely(!(addr & 1))) {
+               res = (uae_u32)mmu_get_iword(addr, sz_long) << 16;
+               SAVE_EXCEPTION;
+               TRY(prb) {
+                       res |= mmu_get_iword(addr + 2, sz_long);
+                       RESTORE_EXCEPTION;
+               }
+               CATCH(prb) {
+                       RESTORE_EXCEPTION;
+                       misalignednotfirst(addr);
+                       THROW_AGAIN(prb);
+               } ENDTRY
+       }
+       return res;
+}
+
 uae_u16 REGPARAM2 mmu_get_lrmw_word_unaligned(uaecptr addr)
 {
        uae_u16 res;
@@ -724,7 +745,7 @@ uae_u8 REGPARAM2 mmu_get_byte_slow(uaecptr addr, bool super, bool data,
                mmu_bus_error(addr, mmu_get_fc(super, data), 0, size, rmw, status);
                return 0;
        }
-       return phys_get_byte(mmu_get_real_address(addr, cl));
+       return x_phys_get_byte(mmu_get_real_address(addr, cl));
 }
 
 uae_u16 REGPARAM2 mmu_get_word_slow(uaecptr addr, bool super, bool data,
@@ -735,7 +756,17 @@ uae_u16 REGPARAM2 mmu_get_word_slow(uaecptr addr, bool super, bool data,
                mmu_bus_error(addr, mmu_get_fc(super, data), 0, size, rmw, status);
                return 0;
        }
-       return phys_get_word(mmu_get_real_address(addr, cl));
+       return x_phys_get_word(mmu_get_real_address(addr, cl));
+}
+uae_u16 REGPARAM2 mmu_get_iword_slow(uaecptr addr, bool super,
+       int size, struct mmu_atc_line *cl)
+{
+       uae_u32 status;
+       if (!mmu_fill_atc_try(addr, super, false, 0, cl, &status)) {
+               mmu_bus_error(addr, mmu_get_fc(super, false), 0, size, false, status);
+               return 0;
+       }
+       return x_phys_get_iword(mmu_get_real_address(addr, cl));
 }
 
 uae_u32 REGPARAM2 mmu_get_long_slow(uaecptr addr, bool super, bool data,
@@ -746,7 +777,17 @@ uae_u32 REGPARAM2 mmu_get_long_slow(uaecptr addr, bool super, bool data,
                mmu_bus_error(addr, mmu_get_fc(super, data), 0, size, rmw, status);
                return 0;
        }
-       return phys_get_long(mmu_get_real_address(addr, cl));
+       return x_phys_get_long(mmu_get_real_address(addr, cl));
+}
+uae_u32 REGPARAM2 mmu_get_ilong_slow(uaecptr addr, bool super,
+       int size, struct mmu_atc_line *cl)
+{
+       uae_u32 status;
+       if (!mmu_fill_atc_try(addr, super, false, 0, cl, &status)) {
+               mmu_bus_error(addr, mmu_get_fc(super, false), 0, size, false, status);
+               return 0;
+       }
+       return x_phys_get_ilong(mmu_get_real_address(addr, cl));
 }
 
 void REGPARAM2 mmu_put_long_unaligned(uaecptr addr, uae_u32 val, bool data, bool rmw)
@@ -797,7 +838,7 @@ void REGPARAM2 mmu_put_byte_slow(uaecptr addr, uae_u8 val, bool super, bool data
                mmu_bus_error(addr, mmu_get_fc(super, data), 1, size, rmw, status);
                return;
        }
-       phys_put_byte(mmu_get_real_address(addr, cl), val);
+       x_phys_put_byte(mmu_get_real_address(addr, cl), val);
 }
 
 void REGPARAM2 mmu_put_word_slow(uaecptr addr, uae_u16 val, bool super, bool data,
@@ -809,7 +850,7 @@ void REGPARAM2 mmu_put_word_slow(uaecptr addr, uae_u16 val, bool super, bool dat
                mmu_bus_error(addr, mmu_get_fc(super, data), 1, size, rmw, status);
                return;
        }
-       phys_put_word(mmu_get_real_address(addr, cl), val);
+       x_phys_put_word(mmu_get_real_address(addr, cl), val);
 }
 
 void REGPARAM2 mmu_put_long_slow(uaecptr addr, uae_u32 val, bool super, bool data,
@@ -821,7 +862,7 @@ void REGPARAM2 mmu_put_long_slow(uaecptr addr, uae_u32 val, bool super, bool dat
                mmu_bus_error(addr, mmu_get_fc(super, data), 1, size, rmw, status);
                return;
        }
-       phys_put_long(mmu_get_real_address(addr, cl), val);
+       x_phys_put_long(mmu_get_real_address(addr, cl), val);
 }
 
 uae_u32 REGPARAM2 sfc_get_long(uaecptr addr)
@@ -987,9 +1028,9 @@ void mmu_get_move16(uaecptr addr, uae_u32 *v, bool data, int size)
                uaecptr addr2 = addr + i * 4;
                //                                       addr,super,data
                if ((!regs.mmu_enabled) || (mmu_match_ttr(addr2,regs.s != 0,data,false)!=TTR_NO_MATCH))
-                       v[i] = phys_get_long(addr2);
+                       v[i] = x_phys_get_long(addr2);
                else if (likely(mmu_lookup(addr2, data, false, &cl)))
-                       v[i] = phys_get_long(mmu_get_real_address(addr2, cl));
+                       v[i] = x_phys_get_long(mmu_get_real_address(addr2, cl));
                else
                        v[i] = mmu_get_long_slow(addr2, regs.s != 0, data, size, false, cl);
        }
@@ -1003,9 +1044,9 @@ void mmu_put_move16(uaecptr addr, uae_u32 *val, bool data, int size)
                uaecptr addr2 = addr + i * 4;
                //                                        addr,super,data
                if ((!regs.mmu_enabled) || (mmu_match_ttr_write(addr2,regs.s != 0,data,val[i],size,false)==TTR_OK_MATCH))
-                       phys_put_long(addr2,val[i]);
+                       x_phys_put_long(addr2,val[i]);
                else if (likely(mmu_lookup(addr2, data, true, &cl)))
-                       phys_put_long(mmu_get_real_address(addr2, cl), val[i]);
+                       x_phys_put_long(mmu_get_real_address(addr2, cl), val[i]);
                else
                        mmu_put_long_slow(addr2, val[i], regs.s != 0, data, size, false, cl);
        }
@@ -1140,6 +1181,26 @@ void REGPARAM2 mmu_flush_atc_all(bool global)
 void REGPARAM2 mmu_reset(void)
 {
        mmu_flush_atc_all(true);
+
+       if (currprefs.cpu_cycle_exact || currprefs.cpu_compatible) {
+               x_phys_get_iword = get_word_icache040;
+               x_phys_get_ilong = get_long_icache040;
+               x_phys_get_byte = get_byte_cache_040;
+               x_phys_get_word = get_word_cache_040;
+               x_phys_get_long = get_long_cache_040;
+               x_phys_put_byte = put_byte_cache_040;
+               x_phys_put_word = put_word_cache_040;
+               x_phys_put_long = put_long_cache_040;
+       } else {
+               x_phys_get_iword = phys_get_word;
+               x_phys_get_ilong = phys_get_long;
+               x_phys_get_byte = phys_get_byte;
+               x_phys_get_word = phys_get_word;
+               x_phys_get_long = phys_get_long;
+               x_phys_put_byte = phys_put_byte;
+               x_phys_put_word = phys_put_word;
+               x_phys_put_long = phys_put_long;
+       }
 }
 
 
@@ -1154,7 +1215,11 @@ void REGPARAM2 mmu_set_tc(uae_u16 tc)
 
        mmu_flush_atc_all(true);
 
-       write_log(_T("%d MMU: enabled=%d page8k=%d\n"), currprefs.mmu_model, regs.mmu_enabled, mmu_pagesize_8k);
+       write_log(_T("%d MMU: enabled=%d page8k=%d PC=%08x\n"), currprefs.mmu_model, regs.mmu_enabled, mmu_pagesize_8k, m68k_getpc());
+#if MMUDUMP
+       if (regs.mmu_enabled)
+               mmu_dump_tables();
+#endif
 }
 
 void REGPARAM2 mmu_set_super(bool super)
index c120b5a18d0f3809c9f4804c2f9c0ca3b1d99fa1..054852596a2eedafa7b2303c461e1b3f8b645c83 100644 (file)
@@ -1601,7 +1601,7 @@ void mmu030_put_long_atc(uaecptr addr, uae_u32 val, int l, uae_u32 fc) {
         return;
     }
 
-    phys_put_long(physical_addr, val);
+    x_phys_put_long(physical_addr, val);
 }
 
 void mmu030_put_word_atc(uaecptr addr, uae_u16 val, int l, uae_u32 fc) {
@@ -1620,7 +1620,7 @@ void mmu030_put_word_atc(uaecptr addr, uae_u16 val, int l, uae_u32 fc) {
         return;
     }
 
-    phys_put_word(physical_addr, val);
+    x_phys_put_word(physical_addr, val);
 }
 
 void mmu030_put_byte_atc(uaecptr addr, uae_u8 val, int l, uae_u32 fc) {
@@ -1639,7 +1639,7 @@ void mmu030_put_byte_atc(uaecptr addr, uae_u8 val, int l, uae_u32 fc) {
         return;
     }
 
-    phys_put_byte(physical_addr, val);
+    x_phys_put_byte(physical_addr, val);
 }
 
 uae_u32 mmu030_get_long_atc(uaecptr addr, int l, uae_u32 fc) {
@@ -1658,7 +1658,25 @@ uae_u32 mmu030_get_long_atc(uaecptr addr, int l, uae_u32 fc) {
         return 0;
     }
 
-    return phys_get_long(physical_addr);
+    return x_phys_get_long(physical_addr);
+}
+uae_u32 mmu030_get_ilong_atc(uaecptr addr, int l, uae_u32 fc) {
+       uae_u32 page_index = addr & mmu030.translation.page.mask;
+       uae_u32 addr_mask = mmu030.translation.page.imask;
+
+       uae_u32 physical_addr = mmu030.atc[l].physical.addr&addr_mask;
+#if MMU030_ATC_DBG_MSG
+       write_log(_T("ATC match(%i): page addr = %08X, index = %08X (lget %08X)\n"), l,
+               physical_addr, page_index, phys_get_long(physical_addr + page_index));
+#endif
+       physical_addr += page_index;
+
+       if (mmu030.atc[l].physical.bus_error) {
+               mmu030_page_fault(addr, true, MMU030_SSW_SIZE_L, fc);
+               return 0;
+       }
+
+       return x_phys_get_ilong(physical_addr);
 }
 
 uae_u16 mmu030_get_word_atc(uaecptr addr, int l, uae_u32 fc) {
@@ -1677,7 +1695,26 @@ uae_u16 mmu030_get_word_atc(uaecptr addr, int l, uae_u32 fc) {
         return 0;
     }
     
-    return phys_get_word(physical_addr);
+    return x_phys_get_word(physical_addr);
+}
+
+uae_u16 mmu030_get_iword_atc(uaecptr addr, int l, uae_u32 fc) {
+       uae_u32 page_index = addr & mmu030.translation.page.mask;
+       uae_u32 addr_mask = mmu030.translation.page.imask;
+
+       uae_u32 physical_addr = mmu030.atc[l].physical.addr&addr_mask;
+#if MMU030_ATC_DBG_MSG
+       write_log(_T("ATC match(%i): page addr = %08X, index = %08X (wget %04X)\n"), l,
+               physical_addr, page_index, phys_get_word(physical_addr + page_index));
+#endif
+       physical_addr += page_index;
+
+       if (mmu030.atc[l].physical.bus_error) {
+               mmu030_page_fault(addr, true, MMU030_SSW_SIZE_W, fc);
+               return 0;
+       }
+
+       return x_phys_get_iword(physical_addr);
 }
 
 uae_u8 mmu030_get_byte_atc(uaecptr addr, int l, uae_u32 fc) {
@@ -1696,7 +1733,7 @@ uae_u8 mmu030_get_byte_atc(uaecptr addr, int l, uae_u32 fc) {
         return 0;
     }
 
-    return phys_get_byte(physical_addr);
+    return x_phys_get_byte(physical_addr);
 }
 
 /* Generic versions of above */
@@ -1716,11 +1753,11 @@ void mmu030_put_atc_generic(uaecptr addr, uae_u32 val, int l, uae_u32 fc, int si
         return;
     }
        if (size == sz_byte)
-           phys_put_byte(physical_addr, val);
+           x_phys_put_byte(physical_addr, val);
        else if (size == sz_word)
-           phys_put_word(physical_addr, val);
+           x_phys_put_word(physical_addr, val);
        else
-           phys_put_long(physical_addr, val);
+           x_phys_put_long(physical_addr, val);
 
 }
 uae_u32 mmu030_get_atc_generic(uaecptr addr, int l, uae_u32 fc, int size, int flags, bool checkwrite) {
@@ -1739,10 +1776,10 @@ uae_u32 mmu030_get_atc_generic(uaecptr addr, int l, uae_u32 fc, int size, int fl
         return 0;
     }
        if (size == sz_byte)
-               return phys_get_byte(physical_addr);
+               return x_phys_get_byte(physical_addr);
        else if (size == sz_word)
-               return phys_get_word(physical_addr);
-       return phys_get_long(physical_addr);
+               return x_phys_get_word(physical_addr);
+       return x_phys_get_long(physical_addr);
 }
 
 
@@ -1815,7 +1852,7 @@ void mmu030_put_long(uaecptr addr, uae_u32 val, uae_u32 fc) {
     
        //                                        addr,super,write
        if ((!mmu030.enabled) || (mmu030_match_ttr_access(addr,fc,true)) || (fc==7)) {
-               phys_put_long(addr,val);
+               x_phys_put_long(addr,val);
                return;
     }
 
@@ -1833,7 +1870,7 @@ void mmu030_put_word(uaecptr addr, uae_u16 val, uae_u32 fc) {
     
        //                                        addr,super,write
        if ((!mmu030.enabled) || (mmu030_match_ttr_access(addr,fc,true)) || (fc==7)) {
-               phys_put_word(addr,val);
+               x_phys_put_word(addr,val);
                return;
     }
     
@@ -1851,7 +1888,7 @@ void mmu030_put_byte(uaecptr addr, uae_u8 val, uae_u32 fc) {
     
        //                                        addr,super,write
        if ((!mmu030.enabled) || (mmu030_match_ttr_access(addr, fc, true)) || (fc==7)) {
-               phys_put_byte(addr,val);
+               x_phys_put_byte(addr,val);
                return;
     }
     
@@ -1865,6 +1902,23 @@ void mmu030_put_byte(uaecptr addr, uae_u8 val, uae_u32 fc) {
     }
 }
 
+uae_u32 mmu030_get_ilong(uaecptr addr, uae_u32 fc) {
+
+       //                                        addr,super,write
+       if ((!mmu030.enabled) || (mmu030_match_ttr_access(addr, fc, false)) || (fc == 7)) {
+               return x_phys_get_ilong(addr);
+       }
+
+       int atc_line_num = mmu030_logical_is_in_atc(addr, fc, false);
+
+       if (atc_line_num >= 0) {
+               return mmu030_get_ilong_atc(addr, atc_line_num, fc);
+       }
+       else {
+               mmu030_table_search(addr, fc, false, 0);
+               return mmu030_get_ilong_atc(addr, mmu030_logical_is_in_atc(addr, fc, false), fc);
+       }
+}
 uae_u32 mmu030_get_long(uaecptr addr, uae_u32 fc) {
     
        //                                        addr,super,write
@@ -1882,6 +1936,23 @@ uae_u32 mmu030_get_long(uaecptr addr, uae_u32 fc) {
     }
 }
 
+uae_u16 mmu030_get_iword(uaecptr addr, uae_u32 fc) {
+
+       //                                        addr,super,write
+       if ((!mmu030.enabled) || (mmu030_match_ttr_access(addr, fc, false)) || (fc == 7)) {
+               return x_phys_get_iword(addr);
+       }
+
+       int atc_line_num = mmu030_logical_is_in_atc(addr, fc, false);
+
+       if (atc_line_num >= 0) {
+               return mmu030_get_iword_atc(addr, atc_line_num, fc);
+       }
+       else {
+               mmu030_table_search(addr, fc, false, 0);
+               return mmu030_get_iword_atc(addr, mmu030_logical_is_in_atc(addr, fc, false), fc);
+       }
+}
 uae_u16 mmu030_get_word(uaecptr addr, uae_u32 fc) {
     
        //                                        addr,super,write
@@ -1903,7 +1974,7 @@ uae_u8 mmu030_get_byte(uaecptr addr, uae_u32 fc) {
     
        //                                        addr,super,write
        if ((!mmu030.enabled) || (mmu030_match_ttr_access(addr,fc,false)) || (fc==7)) {
-               return phys_get_byte(addr);
+               return x_phys_get_byte(addr);
     }
     
     int atc_line_num = mmu030_logical_is_in_atc(addr, fc, false);
@@ -1923,11 +1994,11 @@ void mmu030_put_generic(uaecptr addr, uae_u32 val, uae_u32 fc, int size, int acc
        //                                        addr,super,write
        if ((!mmu030.enabled) || (mmu030_match_ttr_access(addr, fc, true)) || (fc==7)) {
                if (size == sz_byte)
-                       phys_put_byte(addr, val);
+                       x_phys_put_byte(addr, val);
                else if (size == sz_word)
-                       phys_put_word(addr, val);
+                       x_phys_put_word(addr, val);
                else
-                       phys_put_long(addr, val);
+                       x_phys_put_long(addr, val);
                return;
     }
     
@@ -2048,6 +2119,23 @@ uae_u16 REGPARAM2 mmu030_get_word_unaligned(uaecptr addr, uae_u32 fc, int flags)
        return res;
 }
 
+uae_u32 REGPARAM2 mmu030_get_ilong_unaligned(uaecptr addr, uae_u32 fc, int flags)
+{
+       uae_u32 res;
+
+       res = (uae_u32)mmu030_get_iword(addr, fc) << 16;
+       SAVE_EXCEPTION;
+       TRY(prb) {
+               res |= mmu030_get_iword(addr + 2, fc);
+               RESTORE_EXCEPTION;
+       }
+       CATCH(prb) {
+               RESTORE_EXCEPTION;
+               THROW_AGAIN(prb);
+       } ENDTRY
+       return res;
+}
+
 uae_u32 REGPARAM2 mmu030_get_long_unaligned(uaecptr addr, uae_u32 fc, int flags)
 {
        uae_u32 res;
@@ -2150,6 +2238,31 @@ uaecptr mmu030_translate(uaecptr addr, bool super, bool data, bool write)
     }
 }
 
+static uae_u32 get_dcache_byte(uaecptr addr)
+{
+       return read_dcache030(addr, 0);
+}
+static uae_u32 get_dcache_word(uaecptr addr)
+{
+       return read_dcache030(addr, 1);
+}
+static uae_u32 get_dcache_long(uaecptr addr)
+{
+       return read_dcache030(addr, 2);
+}
+static void put_dcache_byte(uaecptr addr, uae_u32 v)
+{
+       write_dcache030(addr, v, 0);
+}
+static void put_dcache_word(uaecptr addr, uae_u32 v)
+{
+       write_dcache030(addr, v, 1);
+}
+static void put_dcache_long(uaecptr addr, uae_u32 v)
+{
+       write_dcache030(addr, v, 2);
+}
+
 /* MMU Reset */
 void mmu030_reset(int hardreset)
 {
@@ -2165,6 +2278,25 @@ void mmu030_reset(int hardreset)
         mmusr_030 = 0;
         mmu030_flush_atc_all();
        }
+       if (currprefs.cpu_cycle_exact || currprefs.cpu_compatible) {
+               x_phys_get_iword = get_word_icache030;
+               x_phys_get_ilong = get_long_icache030;
+               x_phys_get_byte = get_dcache_byte;
+               x_phys_get_word = get_dcache_word;
+               x_phys_get_long = get_dcache_long;
+               x_phys_put_byte = put_dcache_byte;
+               x_phys_put_word = put_dcache_word;
+               x_phys_put_long = put_dcache_long;
+       } else {
+               x_phys_get_iword = phys_get_word;
+               x_phys_get_ilong = phys_get_long;
+               x_phys_get_byte = phys_get_byte;
+               x_phys_get_word = phys_get_word;
+               x_phys_get_long = phys_get_long;
+               x_phys_put_byte = phys_put_byte;
+               x_phys_put_word = phys_put_word;
+               x_phys_put_long = phys_put_long;
+       }
 }
 
 
index 0d782dc17096adf4f5499a5c72fd5043f120dec8..f15328a7f583dd970d7fd990491dce79f62e10a7 100644 (file)
@@ -4623,6 +4623,10 @@ static void rethink_intreq (void)
        rethink_akiko ();
        rethink_cd32fmv();
 #endif
+#ifdef NCR
+       ncr_rethink();
+#endif
+       cpuboard_rethink();
        rethink_gayle ();
 }
 
@@ -8028,7 +8032,8 @@ void custom_reset (bool hardreset, bool keyboardreset)
        gfxboard_reset ();
 #endif
 #ifdef NCR
-       ncr_reset ();
+       ncr710_reset();
+       ncr_reset();
 #endif
 #ifdef JIT
        compemu_reset ();
index 6c2edbf8695abb6418c3dd6b43cee26da91431ee..31ee02e91b9f0a5ed4330977a6da142b00cda524 100644 (file)
--- a/disk.cpp
+++ b/disk.cpp
@@ -2299,7 +2299,7 @@ static void drive_eject (drive * drv)
        if (isfloppysound (drv))
                driveclick_insert (drv - floppy, 1);
 #endif
-       if (drv->diskfile || drv->filetype)
+       if (drv->diskfile || drv->filetype >= 0)
                statusline_add_message(_T("DF%d: -"), drv - floppy);
        gui_disk_image_change(drv - floppy, NULL, drv->wrprot);
        drive_image_free (drv);
index 92bb49df423b27e9bc7914a777595c91919a3cc3..f60d79f2e26cbe57ac776ebabb96c29e6c77f019 100644 (file)
@@ -1433,9 +1433,10 @@ uaecptr need_uae_boot_rom (void)
 static addrbank *expamem_init_a2065(void)
 {
 #ifdef A2065
-       a2065_init ();
-#endif
+       return a2065_init ();
+#else
        return NULL;
+#endif
 }
 static addrbank *expamem_init_cdtv(void)
 {
@@ -1463,7 +1464,7 @@ static addrbank *expamem_init_a2091_2(void)
 static addrbank *expamem_init_a4091(void)
 {
 #ifdef NCR
-       return ncr_a4091_autoconfig_init (0);
+       return ncr710_a4091_autoconfig_init (0);
 #else
        return NULL;
 #endif
@@ -1471,7 +1472,7 @@ static addrbank *expamem_init_a4091(void)
 static addrbank *expamem_init_a4091_2(void)
 {
 #ifdef NCR
-       return ncr_a4091_autoconfig_init (1);
+       return ncr710_a4091_autoconfig_init (1);
 #else
        return NULL;
 #endif
@@ -1479,7 +1480,7 @@ static addrbank *expamem_init_a4091_2(void)
 static addrbank *expamem_init_warpengine(void)
 {
 #ifdef NCR
-       return ncr_warpengine_autoconfig_init();
+       return ncr710_warpengine_autoconfig_init();
 #else
        return NULL;
 #endif
@@ -1531,7 +1532,7 @@ void expamem_reset (void)
        if (need_uae_boot_rom () == 0)
                do_mount = 0;
 
-       if (currprefs.cpuboard_type == BOARD_BLIZZARD_1230_IV || currprefs.cpuboard_type == BOARD_BLIZZARD_1260) {
+       if (currprefs.cpuboard_type) {
                // This requires first 128k slot.
                card_flags[cardno] = 1;
                card_name[cardno] = _T("Blizzard");
index 6e6b475ef7e2381dc3bb2efc6aae59f20561af4b..b4ddfdc704610ff6bc43a276097b36a32c772b76 100644 (file)
@@ -870,11 +870,17 @@ static void initialize_mountinfo (void)
                                added = true;
                        }
 #endif
-               } else if (type == HD_CONTROLLER_TYPE_SCSI_WARPENGINE) {
+               } else if (type == HD_CONTROLLER_TYPE_SCSI_CPUBOARD) {
 #ifdef NCR
                        if (currprefs.cpuboard_type == BOARD_WARPENGINE_A4000) {
                                warpengine_add_scsi_unit(unit, uci);
                                added = true;
+                       } else if (currprefs.cpuboard_type == BOARD_CSMK3 || currprefs.cpuboard_type == BOARD_CSPPC) {
+                               cyberstorm_add_scsi_unit(unit, uci);
+                               added = true;
+                       } else if (currprefs.cpuboard_type == BOARD_BLIZZARDPPC) {
+                               blizzardppc_add_scsi_unit(unit, uci);
+                               added = true;
                        }
 #endif
                } else if (type == HD_CONTROLLER_TYPE_SCSI_A4000T) {
@@ -2619,7 +2625,7 @@ static a_inode *lookup_child_aino_for_exnext (Unit *unit, a_inode *base, TCHAR *
        init_child_aino (unit, base, c);
 
        recycle_aino (unit, c);
-       TRACE((_T("created aino %x, exnext\n"), c->uniq));
+       TRACE((_T("created aino %s:%d, exnext\n"), c->nname, c->uniq));
 
        return c;
 }
@@ -3642,91 +3648,18 @@ static void
        action_dup_lock_2 (unit, packet, k->aino->uniq);
 }
 
-static void free_exkey (Unit *unit, ExamineKey *ek)
+static void free_exkey (Unit *unit, a_inode *aino)
 {
-       if (--ek->aino->exnext_count == 0) {
+       if (--aino->exnext_count == 0) {
                TRACE ((_T("Freeing ExKey and reducing total_locked from %d by %d\n"),
-                       unit->total_locked_ainos, ek->aino->locked_children));
-               unit->total_locked_ainos -= ek->aino->locked_children;
-               ek->aino->locked_children = 0;
-       }
-       ek->aino = 0;
-       ek->uniq = 0;
-}
-
-static ExamineKey *lookup_exkey (Unit *unit, uae_u32 uniq)
-{
-       ExamineKey *ek;
-       int i;
-
-       ek = unit->examine_keys;
-       for (i = 0; i < EXKEYS; i++, ek++) {
-               /* Did we find a free one? */
-               if (ek->uniq == uniq)
-                       return ek;
-       }
-       write_log (_T("Houston, we have a BIG problem.\n"));
-       return 0;
-}
-
-/* This is so sick... who invented ACTION_EXAMINE_NEXT? What did he THINK??? */
-static ExamineKey *new_exkey (Unit *unit, a_inode *aino)
-{
-       uae_u32 uniq;
-       uae_u32 oldest = 0xFFFFFFFE;
-       ExamineKey *ek, *oldest_ek = 0;
-       int i;
-
-       ek = unit->examine_keys;
-       for (i = 0; i < EXKEYS; i++, ek++) {
-               /* Did we find a free one? */
-               if (ek->aino == 0)
-                       continue;
-               if (ek->uniq < oldest)
-                       oldest = (oldest_ek = ek)->uniq;
-       }
-       ek = unit->examine_keys;
-       for (i = 0; i < EXKEYS; i++, ek++) {
-               /* Did we find a free one? */
-               if (ek->aino == 0)
-                       goto found;
-       }
-       /* This message should usually be harmless. */
-       write_log (_T("Houston, we have a problem (%s).\n"), aino->nname);
-       free_exkey (unit, oldest_ek);
-       ek = oldest_ek;
-found:
-
-       uniq = aino->uniq;
-#if 0
-       if (uniq >= 0xFFFFFFFE) {
-               /* Things will probably go wrong, but most likely the Amiga will crash
-               * before this happens because of something else. */
-               uniq = 1;
+                       unit->total_locked_ainos, aino->locked_children));
+               unit->total_locked_ainos -= aino->locked_children;
+               aino->locked_children = 0;
        }
-       unit->next_exkey = uniq + 1;
-#endif
-       ek->aino = aino;
-       ek->curr_file = 0;
-       ek->uniq = uniq;
-       return ek;
 }
 
 static void move_exkeys (Unit *unit, a_inode *from, a_inode *to)
 {
-       int i;
-       unsigned long tmp = 0;
-       for (i = 0; i < EXKEYS; i++) {
-               ExamineKey *k = unit->examine_keys + i;
-               if (k->uniq == 0)
-                       continue;
-               if (k->aino == from) {
-                       k->aino = to;
-                       tmp++;
-               }
-       }
-       if (tmp != from->exnext_count)
-               write_log (_T("filesys.c: Bug in ExNext bookkeeping.  BAD.\n"));
        to->exnext_count = from->exnext_count;
        to->locked_children = from->locked_children;
        from->exnext_count = 0;
@@ -4473,8 +4406,8 @@ static void populate_directory (Unit *unit, a_inode *base)
                base->locked_children++;
                unit->total_locked_ainos++;
        }
-       TRACE3((_T("Populating directory, child %p, locked_children %d\n"),
-               base->child, base->locked_children));
+       TRACE3((_T("Populating directory, child %s, locked_children %d\n"),
+               base->child->nname, base->locked_children));
        for (;;) {
                uae_u64 uniq = 0;
                TCHAR fn[MAX_DPATH];
@@ -4502,35 +4435,32 @@ static void populate_directory (Unit *unit, a_inode *base)
        fs_closedir (d);
 }
 
-static void do_examine (Unit *unit, dpacket packet, ExamineKey *ek, uaecptr info, bool longfilesize)
+static bool do_examine (Unit *unit, dpacket packet, a_inode *aino, uaecptr info, bool longfilesize)
 {
        for (;;) {
                TCHAR *name;
-               if (ek->curr_file == 0)
+               if (!aino)
                        break;
-               name = ek->curr_file->nname;
-               get_fileinfo (unit, packet, info, ek->curr_file, longfilesize);
-               ek->curr_file = ek->curr_file->sibling;
+               name = aino->nname;
+               get_fileinfo (unit, packet, info, aino, longfilesize);
                if (!(unit->volflags & (MYVOLUMEINFO_ARCHIVE | MYVOLUMEINFO_CDFS)) && !fsdb_exists(name)) {
                        TRACE ((_T("%s orphaned"), name));
-                       continue;
+                       return false;
                }
-               TRACE ((_T("curr_file set to %p %s\n"), ek->curr_file,
-                       ek->curr_file ? ek->curr_file->aname : _T("NULL")));
-               return;
+               return true;
        }
        TRACE((_T("no more entries\n")));
-       free_exkey (unit, ek);
+       free_exkey (unit, aino->parent);
        PUT_PCK_RES1 (packet, DOS_FALSE);
        PUT_PCK_RES2 (packet, ERROR_NO_MORE_ENTRIES);
+       return true;
 }
 
 static void action_examine_next (Unit *unit, dpacket packet, bool largefilesize)
 {
        uaecptr lock = GET_PCK_ARG1 (packet) << 2;
        uaecptr info = GET_PCK_ARG2 (packet) << 2;
-       a_inode *aino = 0;
-       ExamineKey *ek;
+       a_inode *aino = 0, *daino = 0;
        uae_u32 uniq;
 
        TRACE((_T("ACTION_EXAMINE_NEXT(0x%lx,0x%lx,%d)\n"), lock, info, largefilesize));
@@ -4541,47 +4471,48 @@ static void action_examine_next (Unit *unit, dpacket packet, bool largefilesize)
                aino = aino_from_lock (unit, lock);
        if (aino == 0)
                aino = &unit->rootnode;
-       for(;;) {
-               uniq = get_long (info);
+       uniq = get_long(info);
+       for (;;) {
                if (uniq == aino->uniq) {
                        // first exnext
                        if (!aino->dir) {
-                               write_log (_T("ExNext called for a file! (Houston?)\n"));
+                               write_log (_T("ExNext called for a file! %s:%d (Houston?)\n"), aino->nname, uniq);
                                goto no_more_entries;
                        }
-                       TRACE((_T("Creating new ExKey\n")));
-                       ek = new_exkey (unit, aino);
-                       if (ek) {
-                               if (aino->exnext_count++ == 0)
-                                       populate_directory (unit, aino);
-                               if (!aino->child) {
-                                       free_exkey (unit, ek);
-                                       goto no_more_entries;
+                       if (aino->exnext_count++ == 0)
+                               populate_directory (unit, aino);
+                       if (!aino->child)
+                               goto no_more_entries;
+                       daino = aino->child;
+               } else {
+                       daino = lookup_aino(unit, uniq);
+                       if (!daino) {
+                               // deleted? Look for next larger uniq in same directory
+                               daino = aino->child;
+                               while (daino && daino->uniq < uniq) {
+                                       daino = daino->sibling;
                                }
-                               ek->curr_file = aino->child;
-                               TRACE((_T("Initial curr_file: %p %s\n"), ek->curr_file,
-                                       ek->curr_file ? ek->curr_file->aname : _T("NULL")));
-                               uniq = ek->curr_file->uniq;
+                       } else {
+                               daino = daino->sibling;
                        }
-               } else {
-                       TRACE((_T("Looking up ExKey\n")));
-                       ek = lookup_exkey(unit, aino->uniq);
                }
-               if (ek == 0) {
-                       write_log (_T("Couldn't find a matching ExKey. Prepare for trouble.\n"));
+               if (!daino)
                        goto no_more_entries;
-               }
-               if (!ek->curr_file || ek->curr_file->mountcount == unit->mountcount)
-                       break;
-               ek->curr_file = ek->curr_file->sibling;
-               if (!ek->curr_file)
+               if (daino->parent != aino) {
+                       write_log(_T("Houston, we have a BIG problem. %s is not parent of %s\n"), daino->nname, aino->nname);
                        goto no_more_entries;
+               }
+               uniq = daino->uniq;
+               if (daino->mountcount != unit->mountcount)
+                       continue;
+               if (!do_examine (unit, packet, daino, info, largefilesize))
+                       continue;
+               return;
        }
-       do_examine (unit, packet, ek, info, largefilesize);
-       return;
 
 no_more_entries:
-       PUT_PCK_RES1 (packet, DOS_FALSE);
+       free_exkey(unit, aino);
+       PUT_PCK_RES1(packet, DOS_FALSE);
        PUT_PCK_RES2 (packet, ERROR_NO_MORE_ENTRIES);
 }
 
@@ -7854,7 +7785,7 @@ static uae_u8 *restore_filesys_hardfile (UnitInfo *ui, uae_u8 *src)
        _tcscpy (hfd->product_rev, s);
        xfree (s);
        s = restore_string ();
-       _tcscpy (hfd->device_name, s);
+       _tcscpy (hfd->ci.devname, s);
        xfree (s);
        return src;
 }
@@ -7878,7 +7809,7 @@ static uae_u8 *save_filesys_hardfile (UnitInfo *ui, uae_u8 *dst)
        save_string (hfd->vendor_id);
        save_string (hfd->product_id);
        save_string (hfd->product_rev);
-       save_string (hfd->device_name);
+       save_string (hfd->ci.devname);
        return dst;
 }
 
diff --git a/flashrom.cpp b/flashrom.cpp
new file mode 100644 (file)
index 0000000..f9fcc19
--- /dev/null
@@ -0,0 +1,155 @@
+/*
+* UAE - The Un*x Amiga Emulator
+*
+* Simple 29F010 flash ROM chip emulator
+*
+* (c) 2014 Toni Wilen
+*/
+
+#include "sysconfig.h"
+#include "sysdeps.h"
+
+#include "zfile.h"
+#include "flashrom.h"
+
+#define FLASH_LOG 0
+
+struct flashrom_data
+{
+       uae_u8 *rom;
+       int flashsize;
+       int allocsize;
+       int mask;
+       int state;
+       int modified;
+       struct zfile *zf;
+};
+
+void *flash_new(uae_u8 *rom, int flashsize, int allocsize, struct zfile *zf)
+{
+       struct flashrom_data *fd = xcalloc(struct flashrom_data, 1);
+       fd->flashsize = flashsize;
+       fd->allocsize = allocsize;
+       fd->mask = fd->flashsize - 1;
+       fd->zf = zf;
+       fd->rom = rom;
+       return fd;
+}
+
+void flash_free(void *fdv)
+{
+       struct flashrom_data *fd = (struct flashrom_data*)fdv;
+       if (!fd)
+               return;
+       if (fd->zf && fd->modified) {
+               zfile_fseek(fd->zf, 0, SEEK_SET);
+               zfile_fwrite(fd->rom, fd->allocsize, 1, fd->zf);
+       }
+       xfree(fdv);
+}
+
+bool flash_active(void *fdv, uaecptr addr)
+{
+       struct flashrom_data *fd = (struct flashrom_data*)fdv;
+
+       return fd->state != 0;
+}
+
+bool flash_write(void *fdv, uaecptr addr, uae_u8 v)
+{
+       struct flashrom_data *fd = (struct flashrom_data*)fdv;
+       int oldstate = fd->state;
+       uae_u32 addr2;
+
+#if FLASH_LOG
+       write_log(_T("flash write %08x %02x\n"), addr, v);
+#endif
+
+       addr &= fd->mask;
+       addr2 = addr & 0xffff;
+
+       if (fd->state == 7) {
+               fd->state = 0;
+               if (addr >= fd->allocsize)
+                       return false;
+               if (fd->rom[addr] != v)
+                       fd->modified = 1;
+               fd->rom[addr] = v;
+               return true;
+       }
+
+       if (v == 0xf0) {
+               fd->state = 0;
+               return false;
+       }
+
+       // unlock
+       if (addr2 == 0x5555 && fd->state == 0 && v == 0xaa)
+               fd->state = 1;
+       if (addr2 == 0x2aaa && fd->state == 1 && v == 0x55)
+               fd->state = 2;
+
+       // autoselect
+       if (addr2 == 0x5555 && fd->state == 2 && v == 0x90)
+               fd->state = 3;
+
+       // program
+       if (addr2 == 0x5555 && fd->state == 2 && v == 0xa0)
+               fd->state = 7;
+
+       // chip/sector erase
+       if (addr2 == 0x5555 && fd->state == 2 && v == 0x80)
+               fd->state = 4;
+       if (addr2 == 0x5555 && fd->state == 4 && v == 0xaa)
+               fd->state = 5;
+       if (addr2 == 0x2aaa && fd->state == 5 && v == 0x55)
+               fd->state = 6;
+       if (addr2 == 0x5555 && fd->state == 6 && v == 0x10) {
+               memset(fd->rom, 0xff, fd->allocsize);
+               fd->state = 0;
+               fd->modified = 1;
+#if FLASH_LOG
+               write_log(_T("flash chip erased\n"), addr);
+#endif
+               return true;
+       } else if (fd->state == 6 && v == 0x30) {
+               int saddr = addr & ~0x3fff;
+               if (saddr < fd->allocsize)
+                       memset(fd->rom + saddr, 0xff, 0x4000);
+               fd->state = 0;
+               fd->modified = 1;
+#if FLASH_LOG
+               write_log(_T("flash sector %d erased\n"), saddr / 0x4000);
+#endif
+               return true;
+       }
+
+       if (fd->state == oldstate)
+               fd->state = 0;
+       return false;
+}
+
+uae_u32 flash_read(void *fdv, uaecptr addr)
+{
+       struct flashrom_data *fd = (struct flashrom_data*)fdv;
+       uae_u8 v = 0xff;
+
+#if FLASH_LOG
+       write_log(_T("flash read %08x\n"), addr);
+#endif
+
+       addr &= fd->mask;
+       if (fd->state == 3) {
+               uae_u8 a = addr & 0xff;
+               if (a == 0)
+                       return 0x01;
+               if (a == 1)
+                       return 0x20;
+               if (a == 2)
+                       return 0x00;
+       }
+       fd->state = 0;
+       if (addr >= fd->allocsize)
+               return 0xff;
+       return fd->rom[addr];
+}
diff --git a/fpp.cpp b/fpp.cpp
index 078de3e93c5759b91bf82e89ac20f456268c5a42..6f14b41d2aee1304f13a72d3bd888de09e36acdb 100644 (file)
--- a/fpp.cpp
+++ b/fpp.cpp
@@ -33,6 +33,8 @@
 #include "cpummu030.h"
 #include "debug.h"
 
+#include "softfloatx80.h"
+
 #ifdef X86_MSVC_ASSEMBLY
 #define X86_MSVC_ASSEMBLY_FPU
 #define NATIVE_FPUCW
@@ -64,6 +66,7 @@ uae_u32 xhex_1e2048[]={0xc53d5de5, 0x9e8b3b5d, 0x5a92};
 uae_u32 xhex_1e4096[]={0x8a20979b, 0xc4605202, 0x7525};
 static uae_u32 xhex_inf[]   ={0x00000000, 0x00000000, 0x7fff};
 static uae_u32 xhex_nan[]   ={0xffffffff, 0xffffffff, 0x7fff};
+static uae_u32 xhex_snan[]  ={0xffffffff, 0xbfffffff, 0x7fff};
 #if USE_LONG_DOUBLE
 static long double *fp_pi     = (long double *)xhex_pi;
 static long double *fp_exp_1  = (long double *)xhex_exp_1;
@@ -125,44 +128,181 @@ static bool fpu_mmu_fixup;
 #define FFLAG_N            0x0100
 #define FFLAG_NAN   0x0400
 
+
+#ifdef WITH_SOFTFLOAT
+static floatx80 fxsizes[6] = { 0 };
+static floatx80 fxzero;
+static floatx80 fx_1e0, fx_1e1, fx_1e2, fx_1e4, fx_1e8;
+struct float_status_t fxstatus;
+#endif
+static fptype fsizes[] = { -128.0, 127.0, -32768.0, 32767.0, -2147483648.0, 2147483647.0 };
+
+#define FP_INEXACT (1 << 9)
+#define FP_DIVBYZERO (1 << 10)
+#define FP_UNDERFLOW (1 << 11)
+#define FP_OVERFLOW (1 << 12)
+#define FP_OPERAND (1 << 13)
+#define FP_SNAN (1 << 14)
+#define FP_BSUN (1 << 15)
+
 STATIC_INLINE void MAKE_FPSR (fptype *fp)
 {
+#ifdef WITH_SOFTFLOAT
+       if (currprefs.fpu_softfloat)
+               return;
+#endif
        int status = fetestexcept (FE_ALL_EXCEPT);
-       if (status)
-               regs.fp_result_status |= status;
+       if (status) {
+               if (status & FE_INEXACT)
+                       regs.fp_result_status |= FP_INEXACT;
+               if (status & FE_DIVBYZERO)
+                       regs.fp_result_status |= FP_DIVBYZERO;
+               if (status & FE_UNDERFLOW)
+                       regs.fp_result_status |= FP_UNDERFLOW;
+               if (status & FE_OVERFLOW)
+                       regs.fp_result_status |= FP_OVERFLOW;
+               if (status & FE_INVALID)
+                       regs.fp_result_status |= FP_OPERAND;
+       }
        regs.fp_result.fp = *fp;
 }
 
+#ifdef WITH_SOFTFLOAT
+STATIC_INLINE void MAKE_FPSR_SOFTFLOAT(floatx80 fx)
+{
+       if (fxstatus.float_exception_flags & float_flag_invalid)
+               regs.fp_result_status |= FP_OPERAND;
+       if (fxstatus.float_exception_flags & float_flag_divbyzero)
+               regs.fp_result_status |= FP_DIVBYZERO;
+       if (fxstatus.float_exception_flags & float_flag_overflow)
+               regs.fp_result_status |= FP_OVERFLOW;
+       if (fxstatus.float_exception_flags & float_flag_underflow)
+               regs.fp_result_status |= FP_UNDERFLOW;
+       if (fxstatus.float_exception_flags & float_flag_inexact)
+               regs.fp_result_status |= FP_INEXACT;
+       regs.fp_result.fpx = fx;
+}
+#endif
+
 STATIC_INLINE void CLEAR_STATUS (void)
 {
+#ifdef WITH_SOFTFLOAT
+       if (currprefs.fpu_softfloat)
+               return;
+#endif
        feclearexcept (FE_ALL_EXCEPT);
 }
 
+#ifdef WITH_SOFTFLOAT
+static void softfloat_set(floatx80 *fx, uae_u32 *f)
+{
+       fx->exp = (uae_u16)f[2];
+       fx->fraction = ((uae_u64)f[1] << 32) | f[0];
+}
+static void softfloat_get(floatx80 *fx, uae_u32 *f)
+{
+       f[2] = fx->exp;
+       f[1] = fx->fraction >> 32;
+       f[0] = (uae_u32)fx->fraction;
+}
+#endif
+
 static void fpnan (fpdata *fpd)
 {
        fpd->fp = *fp_nan;
-#ifdef USE_SOFT_LONG_DOUBLE
-       fpd->fpe = ((uae_u64)xhex_nan[0] << 32) | xhex_nan[1];
-       fpd->fpm = xhex_nan[2];
+#ifdef WITH_SOFTFLOAT
+       softfloat_set(&fpd->fpx, xhex_nan);
 #endif
 }
 
 static void fpclear (fpdata *fpd)
 {
        fpd->fp = 0;
-#ifdef USE_SOFT_LONG_DOUBLE
-       fpd->fpe = 0;
-       fpd->fpm = 0;
+#ifdef WITH_SOFTFLOAT
+       fpd->fpx = int32_to_floatx80(0);
+#endif
+}
+static void fpset (fpdata *fpd, uae_s32 val)
+{
+       fpd->fp = (fptype)val;
+#ifdef WITH_SOFTFLOAT
+       fpd->fpx = int32_to_floatx80(val);
+#endif
+}
+
+void to_single(fpdata *fpd, uae_u32 value)
+{
+#ifdef WITH_SOFTFLOAT
+       if (currprefs.fpu_softfloat) {
+               float32 f = value;
+               fpd->fpx = float32_to_floatx80(f, fxstatus);
+       } else
 #endif
+               fpd->fp = to_single_x(value);
 }
-static void fpset (fpdata *fpd, fptype f)
+static uae_u32 from_single(fpdata *fpd)
 {
-       fpd->fp = f;
-#ifdef USE_SOFT_LONG_DOUBLE
-       fpd->fpe = 0;
-       fpd->fpm = 0;
+#ifdef WITH_SOFTFLOAT
+       if (currprefs.fpu_softfloat) {
+               float32 f = floatx80_to_float32(fpd->fpx, fxstatus);
+               return f;
+       } else
 #endif
+               return from_single_x(fpd->fp);
 }
+void to_double(fpdata *fpd, uae_u32 wrd1, uae_u32 wrd2)
+{
+#ifdef WITH_SOFTFLOAT
+       if (currprefs.fpu_softfloat) {
+               float64 f = ((float64)wrd1 << 32) | wrd2;
+               fpd->fpx = float64_to_floatx80(f, fxstatus);
+       } else
+#endif
+               fpd->fp = to_double_x(wrd1, wrd2);
+}
+static void from_double(fpdata *fpd, uae_u32 *wrd1, uae_u32 *wrd2)
+{
+#ifdef WITH_SOFTFLOAT
+       if (currprefs.fpu_softfloat) {
+               float64 f = floatx80_to_float64(fpd->fpx, fxstatus);
+               *wrd1 = f >> 32;
+               *wrd2 = (uae_u32)f;
+               return;
+       } else
+#endif
+               return from_double_x(fpd->fp, wrd1, wrd2);
+}
+void to_exten(fpdata *fpd, uae_u32 wrd1, uae_u32 wrd2, uae_u32 wrd3)
+{
+#ifdef WITH_SOFTFLOAT
+       if (currprefs.fpu_softfloat) {
+               fpd->fpx.exp = wrd1 >> 16;
+               fpd->fpx.fraction = ((uae_u64)wrd2 << 32) | wrd3;
+#if 0
+               if ((currprefs.fpu_model == 68881 || currprefs.fpu_model == 68882) || currprefs.fpu_no_unimplemented) {
+                       // automatically fix denormals if 6888x or no implemented emulation
+                       Bit64u Sig = extractFloatx80Frac(fpd->fpx);
+                       Bit32s Exp = extractFloatx80Exp(fpd->fpx);
+                       if (Exp == 0 && Sig != 0)
+                               normalizeFloatx80Subnormal(Sig, &Exp, &Sig);
+               }
+#endif
+       } else
+#endif
+               to_exten_x(&fpd->fp, wrd1, wrd2, wrd3);
+}
+static void from_exten(fpdata *fpd, uae_u32 * wrd1, uae_u32 * wrd2, uae_u32 * wrd3)
+{
+#ifdef WITH_SOFTFLOAT
+       if (currprefs.fpu_softfloat) {
+               *wrd1 = fpd->fpx.exp << 16;
+               *wrd2 = fpd->fpx.fraction >> 32;
+               *wrd3 = (uae_u32)fpd->fpx.fraction;
+       } else
+#endif
+               from_exten_x(fpd->fp, wrd1, wrd2, wrd3);
+}
+
 
 #if 0
 static void normalize(uae_u32 *pwrd1, uae_u32 *pwrd2, uae_u32 *pwrd3)
@@ -191,7 +331,7 @@ static void normalize(uae_u32 *pwrd1, uae_u32 *pwrd2, uae_u32 *pwrd3)
 }
 #endif
 
-bool fpu_get_constant(fpdata *fp, int cr)
+static bool fpu_get_constant_fp(fpdata *fp, int cr)
 {
        fptype f;
        switch (cr & 0x7f)
@@ -269,41 +409,168 @@ bool fpu_get_constant(fpdata *fp, int cr)
        return true;
 }
 
-static __inline__ void native_set_fpucw (uae_u32 m68k_cw)
+#ifdef WITH_SOFTFLOAT
+static bool fpu_get_constant_softfloat(fpdata *fp, int cr)
 {
+       uae_u32 *f = NULL;
+       floatx80 fx;
+
+       switch (cr & 0x7f)
+       {
+               case 0x00:
+               f = xhex_pi;
+               break;
+               case 0x0b:
+               f = xhex_l10_2;
+               break;
+               case 0x0c:
+               f = xhex_exp_1;
+               break;
+               case 0x0d:
+               f = xhex_l2_e;
+               break;
+               case 0x0e:
+               f = xhex_l10_e;
+               break;
+               case 0x0f:
+               fx = fxzero;
+               break;
+               case 0x30:
+               f = xhex_ln_2;
+               break;
+               case 0x31:
+               f = xhex_ln_10;
+               break;
+               case 0x32:
+               fx = fx_1e0;
+               break;
+               case 0x33:
+               fx = fx_1e1;
+               break;
+               case 0x34:
+               fx = fx_1e2;
+               break;
+               case 0x35:
+               fx = fx_1e4;
+               break;
+               case 0x36:
+               fx = fx_1e8;
+               break;
+               case 0x37:
+               f = xhex_1e16;
+               break;
+               case 0x38:
+               f = xhex_1e32;
+               break;
+               case 0x39:
+               f = xhex_1e64;
+               break;
+               case 0x3a:
+               f = xhex_1e128;
+               break;
+               case 0x3b:
+               f = xhex_1e256;
+               break;
+               case 0x3c:
+               f = xhex_1e512;
+               break;
+               case 0x3d:
+               f = xhex_1e1024;
+               break;
+               case 0x3e:
+               f = xhex_1e2048;
+               break;
+               case 0x3f:
+               f = xhex_1e4096;
+               break;
+               default:
+               return false;
+       }
+       if (f)
+               softfloat_set(&fp->fpx, f);
+       else
+               fp->fpx = fx;
+       return true;
+}
+#endif
+
+bool fpu_get_constant(fpdata *fp, int cr)
+{
+#ifdef WITH_SOFTFLOAT
+       if (currprefs.fpu_softfloat)
+               return fpu_get_constant_softfloat(fp, cr);
+#endif
+       return fpu_get_constant_fp(fp, cr);
+}
+
+static void native_set_fpucw (uae_u32 m68k_cw)
+{
+#ifdef WITH_SOFTFLOAT
+       if (currprefs.fpu_softfloat) {
+               switch((m68k_cw >> 6) & 3)
+               {
+                       case 0: // X
+                       default: // undefined
+                               fxstatus.float_rounding_precision = 80;
+                       break;
+                       case 1: // S
+                               fxstatus.float_rounding_precision = 32;
+                       break;
+                       case 2: // D
+                               fxstatus.float_rounding_precision = 64;
+                       break;
+               }
+               switch((m68k_cw >> 4) & 3)
+               {
+                       case 0: // to neareset
+                               fxstatus.float_rounding_precision = float_round_nearest_even;
+                       break;
+                       case 1: // to zero
+                               fxstatus.float_rounding_mode = float_round_to_zero;
+                       break;
+                       case 2: // to minus
+                               fxstatus.float_rounding_mode = float_round_down;
+                       break;
+                       case 3: // to plus
+                               fxstatus.float_rounding_mode = float_round_up;
+                       break;
+               }
+       } else
+#endif
+       {
 #ifdef NATIVE_FPUCW
 #ifdef _WIN32
-       static int ex = 0;
-       // RN, RZ, RM, RP
-       static const unsigned int fp87_round[4] = { _RC_NEAR, _RC_CHOP, _RC_DOWN, _RC_UP };
-       // Extend X, Single S, Double D, Undefined
-       static const unsigned int fp87_prec[4] = { _PC_64 , _PC_24 , _PC_53, 0 };
-       
+               static int ex = 0;
+               // RN, RZ, RM, RP
+               static const unsigned int fp87_round[4] = { _RC_NEAR, _RC_CHOP, _RC_DOWN, _RC_UP };
+               // Extend X, Single S, Double D, Undefined
+               static const unsigned int fp87_prec[4] = { _PC_64 , _PC_24 , _PC_53, 0 };
 #ifdef WIN64
-       _controlfp (ex | fp87_round[(m68k_cw >> 4) & 3], _MCW_RC);
+               _controlfp (ex | fp87_round[(m68k_cw >> 4) & 3], _MCW_RC);
 #else
-       _control87 (ex | fp87_round[(m68k_cw >> 4) & 3] | fp87_prec[(m68k_cw >> 6) & 3], _MCW_RC | _MCW_PC);
+               _control87 (ex | fp87_round[(m68k_cw >> 4) & 3] | fp87_prec[(m68k_cw >> 6) & 3], _MCW_RC | _MCW_PC);
 #endif
 #else
-static const uae_u16 x87_cw_tab[] = {
-       0x137f, 0x1f7f, 0x177f, 0x1b7f, /* Extended */
-       0x107f, 0x1c7f, 0x147f, 0x187f, /* Single */
-       0x127f, 0x1e7f, 0x167f, 0x1a7f, /* Double */
-       0x137f, 0x1f7f, 0x177f, 0x1b7f  /* undefined */
-};
+       static const uae_u16 x87_cw_tab[] = {
+               0x137f, 0x1f7f, 0x177f, 0x1b7f, /* Extended */
+               0x107f, 0x1c7f, 0x147f, 0x187f, /* Single */
+               0x127f, 0x1e7f, 0x167f, 0x1a7f, /* Double */
+               0x137f, 0x1f7f, 0x177f, 0x1b7f  /* undefined */
+       };
 #if USE_X86_FPUCW
-       uae_u16 x87_cw = x87_cw_tab[(m68k_cw >> 4) & 0xf];
+               uae_u16 x87_cw = x87_cw_tab[(m68k_cw >> 4) & 0xf];
 
 #if defined(X86_MSVC_ASSEMBLY)
-       __asm {
-               fldcw word ptr x87_cw
-       }
+               __asm {
+                       fldcw word ptr x87_cw
+               }
 #elif defined(X86_ASSEMBLY)
-       __asm__ ("fldcw %0" : : "m" (*&x87_cw));
+               __asm__ ("fldcw %0" : : "m" (*&x87_cw));
 #endif
 #endif
 #endif
 #endif
+       }
 }
 
 #if defined(uae_s64) /* Close enough for government work? */
@@ -338,16 +605,18 @@ static void fpu_format_error (void)
 
 #define FPU_EXP_UNIMP_INS 0
 #define FPU_EXP_DISABLED 1
-#define FPU_EXP_UNIMP_DATATYPE_PACKED_PRE 2
-#define FPU_EXP_UNIMP_DATATYPE_PACKED_POST 3
-#define FPU_EXP_UNIMP_EA 4
+#define FPU_EXP_UNIMP_DATATYPE_PRE 2
+#define FPU_EXP_UNIMP_DATATYPE_POST 3
+#define FPU_EXP_UNIMP_DATATYPE_PACKED_PRE 4
+#define FPU_EXP_UNIMP_DATATYPE_PACKED_POST 5
+#define FPU_EXP_UNIMP_EA 6
 
 static void fpu_arithmetic_exception (uae_u16 opcode, uae_u16 extra, uae_u32 ea, uaecptr oldpc, int type, fpdata *src, int reg)
 {
        // TODO
 }
 
-static void fpu_op_unimp (uae_u16 opcode, uae_u16 extra, uae_u32 ea, uaecptr oldpc, int type, fpdata *src, int reg)
+static void fpu_op_unimp (uae_u16 opcode, uae_u16 extra, uae_u32 ea, uaecptr oldpc, int type, fpdata *src, int reg, int size)
 {
        /* 68040 unimplemented/68060 FPU disabled exception.
        * Line F exception with different stack frame.. */
@@ -375,6 +644,7 @@ static void fpu_op_unimp (uae_u16 opcode, uae_u16 extra, uae_u32 ea, uaecptr old
                regs.fpiar = oldpc;
                regs.exp_extra = extra;
                regs.exp_opcode = opcode;
+               regs.exp_size = size;
                if (src)
                        regs.exp_src1 = *src;
                regs.exp_type = type;
@@ -393,7 +663,7 @@ static void fpu_op_unimp (uae_u16 opcode, uae_u16 extra, uae_u32 ea, uaecptr old
                        x_put_long (m68k_areg (regs, 7), ea);
                        m68k_areg (regs, 7) -= 2;
                        x_put_word (m68k_areg (regs, 7), 0x2000 + vector * 4);
-               } else if (type == FPU_EXP_UNIMP_DATATYPE_PACKED_PRE || type == FPU_EXP_UNIMP_DATATYPE_PACKED_POST) {
+               } else if (type == FPU_EXP_UNIMP_DATATYPE_PACKED_PRE || type == FPU_EXP_UNIMP_DATATYPE_PACKED_POST || type == FPU_EXP_UNIMP_DATATYPE_PRE || type == FPU_EXP_UNIMP_DATATYPE_POST) {
                        regs.fpu_exp_state = 2; // EXC frame
                        // PC = next instruction
                        vector = 55;
@@ -412,6 +682,7 @@ static void fpu_op_unimp (uae_u16 opcode, uae_u16 extra, uae_u32 ea, uaecptr old
                regs.fpiar = oldpc;
                regs.exp_extra = extra;
                regs.exp_opcode = opcode;
+               regs.exp_size = size;
                if (src)
                        regs.exp_src1 = *src;
                regs.exp_type = type;
@@ -425,7 +696,7 @@ static void fpu_op_unimp (uae_u16 opcode, uae_u16 extra, uae_u32 ea, uaecptr old
                        x_put_long (m68k_areg (regs, 7), ea);
                        m68k_areg (regs, 7) -= 2;
                        x_put_word (m68k_areg (regs, 7), 0x2000 + vector * 4);
-               } else if (type == FPU_EXP_UNIMP_DATATYPE_PACKED_PRE || type == FPU_EXP_UNIMP_DATATYPE_PACKED_POST) {
+               } else if (type == FPU_EXP_UNIMP_DATATYPE_PACKED_PRE || type == FPU_EXP_UNIMP_DATATYPE_PACKED_POST || type == FPU_EXP_UNIMP_DATATYPE_PRE || type == FPU_EXP_UNIMP_DATATYPE_POST) {
                        // PC = next instruction
                        vector = 55;
                        m68k_areg (regs, 7) -= 4;
@@ -458,7 +729,7 @@ static void fpu_op_illg2 (uae_u16 opcode, uae_u16 extra, uae_u32 ea, uaecptr old
 {
        if ((currprefs.cpu_model == 68060 && (currprefs.fpu_model == 0 || (regs.pcr & 2)))
                || (currprefs.cpu_model == 68040 && currprefs.fpu_model == 0)) {
-                       fpu_op_unimp (opcode, extra, ea, oldpc, FPU_EXP_DISABLED, NULL, -1);
+                       fpu_op_unimp (opcode, extra, ea, oldpc, FPU_EXP_DISABLED, NULL, -1, -1);
                        return;
        }
        regs.fp_exception = true;
@@ -503,7 +774,7 @@ static bool fault_if_unimplemented_680x0 (uae_u16 opcode, uae_u16 extra, uaecptr
                        return false;
                if ((extra & 0xfc00) == 0x5c00) {
                        // FMOVECR
-                       fpu_op_unimp (opcode, extra, ea, oldpc, FPU_EXP_UNIMP_INS, src, reg);
+                       fpu_op_unimp (opcode, extra, ea, oldpc, FPU_EXP_UNIMP_INS, src, reg, -1);
                        return true;
                }
                uae_u16 v = extra & 0x7f;
@@ -513,7 +784,7 @@ static bool fault_if_unimplemented_680x0 (uae_u16 opcode, uae_u16 extra, uaecptr
                        case 0x03: /* FINTRZ */
                        // Unimplemented only in 68040.
                        if (currprefs.cpu_model == 68040) {
-                               fpu_op_unimp (opcode, extra, ea, oldpc, FPU_EXP_UNIMP_INS, src, reg);
+                               fpu_op_unimp (opcode, extra, ea, oldpc, FPU_EXP_UNIMP_INS, src, reg, -1);
                                return true;
                        }
                        return false;
@@ -548,7 +819,7 @@ static bool fault_if_unimplemented_680x0 (uae_u16 opcode, uae_u16 extra, uaecptr
                        case 0x21: /* FMOD */
                        case 0x25: /* FREM */
                        case 0x26: /* FSCALE */
-                       fpu_op_unimp (opcode, extra, ea, oldpc, FPU_EXP_UNIMP_INS, src, reg);
+                       fpu_op_unimp (opcode, extra, ea, oldpc, FPU_EXP_UNIMP_INS, src, reg, -1);
                        return true;
                }
        }
@@ -584,7 +855,7 @@ static bool fault_if_unimplemented_6888x (uae_u16 opcode, uae_u16 extra, uaecptr
 static bool fault_if_60 (uae_u16 opcode, uae_u16 extra, uaecptr ea, uaecptr oldpc, int type)
 {
        if (currprefs.cpu_model == 68060 && currprefs.fpu_model && currprefs.fpu_no_unimplemented) {
-               fpu_op_unimp (opcode, extra, ea, oldpc, type, NULL, -1);
+               fpu_op_unimp (opcode, extra, ea, oldpc, type, NULL, -1, -1);
                return true;
        }
        return false;
@@ -598,7 +869,7 @@ static bool fault_if_4060 (uae_u16 opcode, uae_u16 extra, uaecptr ea, uaecptr ol
                        regs.exp_pack[1] = pack[1];
                        regs.exp_pack[2] = pack[2];
                }
-               fpu_op_unimp (opcode, extra, ea, oldpc, type, src, -1);
+               fpu_op_unimp (opcode, extra, ea, oldpc, type, src, -1, -1);
                return true;
        }
        return false;
@@ -610,7 +881,7 @@ static bool fault_if_no_fpu_u (uae_u16 opcode, uae_u16 extra, uaecptr ea, uaecpt
                return true;
        if (currprefs.cpu_model == 68060 && currprefs.fpu_model && currprefs.fpu_no_unimplemented) {
                // 68060 FTRAP, FDBcc or FScc are not implemented.
-               fpu_op_unimp (opcode, extra, ea, oldpc, FPU_EXP_UNIMP_INS, NULL, -1);
+               fpu_op_unimp (opcode, extra, ea, oldpc, FPU_EXP_UNIMP_INS, NULL, -1, -1);
                return true;
        }
        return false;
@@ -669,79 +940,118 @@ static void fpu_null (void)
 #define fp_round_to_zero(x)    ((x) >= 0.0 ? floor(x) : ceil(x))
 #define fp_round_to_nearest(x) ((x) >= 0.0 ? (int)((x) + 0.5) : (int)((x) - 0.5))
 
-STATIC_INLINE tointtype toint (fptype src, fptype minval, fptype maxval)
+static tointtype toint(fpdata *src, int size)
 {
-       if (src < minval)
-               src = minval;
-       if (src > maxval)
-               src = maxval;
-#if defined(X86_MSVC_ASSEMBLY_FPU)
+#ifdef WITH_SOFTFLOAT
+       if (currprefs.fpu_softfloat) {
+               if (floatx80_compare(src->fpx, fxsizes[size * 2 + 0], fxstatus) == float_relation_greater)
+                       return floatx80_to_int32(fxsizes[size * 2 + 0], fxstatus);      
+               if (floatx80_compare(src->fpx, fxsizes[size * 2 + 1], fxstatus) == float_relation_less)
+                       return floatx80_to_int32(fxsizes[size * 2 + 1], fxstatus);
+               return floatx80_to_int32(src->fpx, fxstatus);
+       } else
+#endif
        {
-               fptype tmp_fp;
-               __asm {
-                       fld  LDPTR src
+               fptype fp = src->fp;
+               if (fp < fsizes[size * 2 + 0])
+                       fp = fsizes[size * 2 + 0];
+               if (fp > fsizes[size * 2 + 1])
+                       fp = fsizes[size * 2 + 1];
+       #if defined(X86_MSVC_ASSEMBLY_FPU)
+               {
+                       fptype tmp_fp;
+                       __asm {
+                               fld  LDPTR fp
                                frndint
                                fstp LDPTR tmp_fp
+                       }
+                       return (tointtype)tmp_fp;
                }
-               return (tointtype)tmp_fp;
-       }
-#else /* no X86_MSVC */
-       {
-               int result = (int)src;
-               switch (regs.fpcr & 0x30)
+       #else /* no X86_MSVC */
                {
-                       case FPCR_ROUND_ZERO:
-                               result = (int)fp_round_to_zero (src);
-                               break;
-                       case FPCR_ROUND_MINF:
-                               result = (int)fp_round_to_minus_infinity (src);
-                               break;
-                       case FPCR_ROUND_NEAR:
-                               result = fp_round_to_nearest (src);
-                               break;
-                       case FPCR_ROUND_PINF:
-                               result = (int)fp_round_to_plus_infinity (src);
-                               break;
+                       int result = (int)fp;
+                       switch (regs.fpcr & 0x30)
+                       {
+                               case FPCR_ROUND_ZERO:
+                                       result = (int)fp_round_to_zero (fp);
+                                       break;
+                               case FPCR_ROUND_MINF:
+                                       result = (int)fp_round_to_minus_infinity (fp);
+                                       break;
+                               case FPCR_ROUND_NEAR:
+                                       result = fp_round_to_nearest (fp);
+                                       break;
+                               case FPCR_ROUND_PINF:
+                                       result = (int)fp_round_to_plus_infinity (fp);
+                                       break;
+                       }
+                       return result;
                }
-               return result;
+       #endif
        }
-#endif
 }
 
-static bool fpu_isnan (fptype fp)
+static bool fp_is_snan(fpdata *fpd)
+{
+#ifdef WITH_SOFTFLOAT
+       if (currprefs.fpu_softfloat)
+               return floatx80_is_signaling_nan(fpd->fpx) != 0;
+#endif
+       return false;
+}
+static bool fp_is_nan (fpdata *fpd)
 {
+#ifdef WITH_SOFTFLOAT
+       if (currprefs.fpu_softfloat)
+               return floatx80_is_nan(fpd->fpx) != 0;
+#endif
 #ifdef HAVE_ISNAN
-       return isnan (fp) != 0;
+       return isnan(fpd->fp) != 0;
 #else
        return false;
 #endif
 }
-static bool fpu_isinfinity (fptype fp)
+static bool fp_is_infinity (fpdata *fpd)
 {
+#ifdef WITH_SOFTFLOAT
+       if (currprefs.fpu_softfloat) {
+               float_class_t fc = floatx80_class(fpd->fpx);
+               return fc == float_negative_inf || fc == float_positive_inf;
+       }
+#endif
 #ifdef _MSC_VER
-       return !_finite (fp);
+       return !_finite (fpd->fp);
 #elif defined(HAVE_ISINF)
-       return _isinf (fp);
+       return _isinf (fpd->fp);
 #else
        return false;
 #endif
 }
+static bool fp_is_zero(fpdata *fpd)
+{
+#ifdef WITH_SOFTFLOAT
+       if (currprefs.fpu_softfloat)
+               return floatx80_compare_quiet(fpd->fpx, fxzero, fxstatus) == float_relation_equal;
+#endif
+       return fpd->fp == 0.0;
+}
+static bool fp_is_neg(fpdata *fpd)
+{
+#ifdef WITH_SOFTFLOAT
+       if (currprefs.fpu_softfloat)
+               return extractFloatx80Sign(fpd->fpx) != 0;
+#endif
+       return fpd->fp < 0.0;
+}
 
 uae_u32 get_fpsr (void)
 {
        uae_u32 answer = regs.fpsr & 0x00ff00f8;
 
        // exception status byte
-       if (regs.fp_result_status & FE_INEXACT)
-               answer |= 1 << 9;
-       if (regs.fp_result_status & FE_DIVBYZERO)
-               answer |= 1 << 10;
-       if (regs.fp_result_status & FE_UNDERFLOW)
-               answer |= 1 << 11;
-       if (regs.fp_result_status & FE_OVERFLOW)
-               answer |= 1 << 12;
-       if (regs.fp_result_status & FE_INVALID)
-               answer |= 1 << 13;
+       answer |= regs.fp_result_status;
+       if (fp_is_snan(&regs.fp_result))
+               answer |= 1 << 14;
 
        // accrued exception byte
        if (answer & ((1 << 14)  | (1 << 13)))
@@ -758,23 +1068,22 @@ uae_u32 get_fpsr (void)
        regs.fpsr = answer;
 
        // condition code byte
-       if (fpu_isnan (regs.fp_result.fp))
+       if (fp_is_nan (&regs.fp_result)) {
                answer |= 1 << 24;
-       else
-       {
-               if (regs.fp_result.fp == 0)
+       } else {
+               if (fp_is_zero(&regs.fp_result))
                        answer |= 1 << 26;
-               else if (regs.fp_result.fp < 0)
-                       answer |= 1 << 27;
-               if (fpu_isinfinity (regs.fp_result.fp))
+               if (fp_is_infinity (&regs.fp_result))
                        answer |= 1 << 25;
        }
+       if (fp_is_neg(&regs.fp_result))
+               answer |= 1 << 27;
        return answer;
 }
 
 static void update_fpsr (uae_u32 v)
 {
-       regs.fp_result_status = FE_INVALID;
+       regs.fp_result_status = v;
        get_fpsr ();
 }
 
@@ -784,7 +1093,7 @@ STATIC_INLINE void set_fpsr (uae_u32 x)
        regs.fp_result_status = 0;
 
        if (x & 0x01000000)
-               fpset (&regs.fp_result, *fp_nan);
+               fpnan (&regs.fp_result);
        else if (x & 0x04000000)
                fpset (&regs.fp_result, 0);
        else if (x & 0x08000000)
@@ -793,14 +1102,16 @@ STATIC_INLINE void set_fpsr (uae_u32 x)
                fpset (&regs.fp_result, 1);
 }
 
-uae_u32 get_ftag (uae_u32 w1, uae_u32 w2, uae_u32 w3)
+uae_u32 get_ftag (uae_u32 w1, uae_u32 w2, uae_u32 w3, int size)
 {
        int exp = (w1 >> 16) & 0x7fff;
        
        if (exp == 0) {
                if (!w2 && !w3)
                        return 1; // ZERO
-               return 4; // DENORMAL or UNNORMAL
+               if (size == 0 || size == 1)
+                       return 5; // Single/double DENORMAL
+               return 4; // Extended DENORMAL or UNNORMAL
        } else if (exp == 0x7fff)  {
                int s = w2 >> 30;
                int z = (w2 & 0x3fffffff) == 0 && w3 == 0;
@@ -809,7 +1120,7 @@ uae_u32 get_ftag (uae_u32 w1, uae_u32 w2, uae_u32 w3)
                return 3; // NAN
        } else {
                if (!(w2 & 0x80000000))
-                       return 4; // UNNORMAL
+                       return 4; // Extended UNNORMAL
                return 0; // NORMAL
        }
 }
@@ -822,7 +1133,7 @@ uae_u32 get_ftag (uae_u32 w1, uae_u32 w2, uae_u32 w3)
 /* E = MAX & F # 0 -> NotANumber */
 /* E = biased by 127 (single) ,1023 (double) ,16383 (extended) */
 
-static fptype to_pack (uae_u32 *wrd)
+static void to_pack (fpdata *fpd, uae_u32 *wrd)
 {
        fptype d;
        char *cp;
@@ -861,30 +1172,47 @@ static fptype to_pack (uae_u32 *wrd)
 #else
        sscanf (str, "%le", &d);
 #endif
-       return d;
+#ifdef WITH_SOFTFLOAT
+       if (currprefs.fpu_softfloat) {
+               uae_u32 wrd[3];
+               from_exten_x(d, &wrd[0], &wrd[1], &wrd[2]);
+               softfloat_set(&fpd->fpx, wrd);
+       } else
+#endif
+               fpd->fp = d;
 }
 
-void from_pack (fptype src, uae_u32 *wrd, int kfactor)
+void from_pack (fpdata *src, uae_u32 *wrd, int kfactor)
 {
        int i, j, t;
        int exp;
        int ndigits;
        char *cp, *strp;
        char str[100];
+       fptype fp;
 
        wrd[0] = wrd[1] = wrd[2] = 0;
 
-       if (fpu_isnan (src) || fpu_isinfinity (src)) {
+       if (fp_is_nan (src) || fp_is_infinity (src)) {
                wrd[0] |= (1 << 30) | (1 << 29) | (1 << 30); // YY=1
                wrd[0] |= 0xfff << 16; // Exponent=FFF
                // TODO: mantissa should be set if NAN
                return;
        }
 
+#ifdef WITH_SOFTFLOAT
+       if (currprefs.fpu_softfloat) {
+               uae_u32 out[3];
+               softfloat_get(&src->fpx, out);
+               to_exten_x(&fp, out[0], out[1], out[2]);
+       } else
+#endif
+               fp = src->fp;
+
 #if USE_LONG_DOUBLE
-       sprintf (str, "%#.17Le", src);
+       sprintf (str, "%#.17Le", fp);
 #else
-       sprintf (str, "%#.17e", src);
+       sprintf (str, "%#.17e", fp);
 #endif
        
        // get exponent
@@ -1002,10 +1330,40 @@ void from_pack (fptype src, uae_u32 *wrd, int kfactor)
        wrd[0] |= t << 16;
 }
 
+// 68040/060 does not support denormals
+static bool fault_if_no_denormal_support_pre(uae_u16 opcode, uae_u16 extra, uaecptr ea, uaecptr oldpc, fpdata *fpd, int size)
+{
+#ifdef WITH_SOFTFLOAT
+       if (currprefs.cpu_model >= 68040 && currprefs.fpu_model && currprefs.fpu_no_unimplemented && currprefs.fpu_softfloat) {
+               Bit64u Sig = extractFloatx80Frac(fpd->fpx);
+               Bit32s Exp = extractFloatx80Exp(fpd->fpx);
+               if (Exp == 0 && Sig != 0) {
+                       fpu_op_unimp(opcode, extra, ea, oldpc, FPU_EXP_UNIMP_DATATYPE_PRE, fpd, -1, size);
+                       return true;
+               }
+       }
+#endif
+       return false;
+}
+static bool fault_if_no_denormal_support_post(uae_u16 opcode, uae_u16 extra, uaecptr ea, uaecptr oldpc, fpdata *fpd, int size)
+{
+#ifdef WITH_SOFTFLOAT
+       if (currprefs.fpu_softfloat && currprefs.cpu_model >= 68040 && currprefs.fpu_model && currprefs.fpu_no_unimplemented) {
+               Bit64u Sig = extractFloatx80Frac(fpd->fpx);
+               Bit32s Exp = extractFloatx80Exp(fpd->fpx);
+               if (Exp == 0 && Sig != 0) {
+                       fpu_op_unimp(opcode, extra, ea, oldpc, FPU_EXP_UNIMP_DATATYPE_POST, fpd, -1, size);
+                       return true;
+               }
+       }
+#endif
+       return false;
+}
+
 static int get_fp_value (uae_u32 opcode, uae_u16 extra, fpdata *src, uaecptr oldpc, uae_u32 *adp)
 {
        int size, mode, reg;
-       uae_u32 ad = 0;
+       uae_u32 ad = 0, ad2;
        static const int sz1[8] = { 4, 4, 12, 12, 2, 8, 1, 0 };
        static const int sz2[8] = { 4, 4, 12, 12, 2, 8, 2, 0 };
        uae_u32 exts[3];
@@ -1015,6 +1373,8 @@ static int get_fp_value (uae_u32 opcode, uae_u16 extra, fpdata *src, uaecptr old
                if (fault_if_no_fpu (opcode, extra, 0, oldpc))
                        return -1;
                *src = regs.fp[(extra >> 10) & 7];
+               if (fault_if_no_denormal_support_pre(opcode, extra, 0, oldpc, src, 2))
+                       return -1;
                return 1;
        }
        mode = (opcode >> 3) & 7;
@@ -1026,16 +1386,18 @@ static int get_fp_value (uae_u32 opcode, uae_u16 extra, fpdata *src, uaecptr old
                        switch (size)
                        {
                                case 6:
-                                       src->fp = (fptype) (uae_s8) m68k_dreg (regs, reg);
+                                       fpset(src, (uae_s8) m68k_dreg (regs, reg));
                                        break;
                                case 4:
-                                       src->fp = (fptype) (uae_s16) m68k_dreg (regs, reg);
+                                       fpset(src, (uae_s16) m68k_dreg (regs, reg));
                                        break;
                                case 0:
-                                       src->fp = (fptype) (uae_s32) m68k_dreg (regs, reg);
+                                       fpset(src, (uae_s32) m68k_dreg (regs, reg));
                                        break;
                                case 1:
-                                       src->fp = to_single (m68k_dreg (regs, reg));
+                                       to_single (src, m68k_dreg (regs, reg));
+                                       if (fault_if_no_denormal_support_pre(opcode, extra, 0, oldpc, src, 0))
+                                               return -1;
                                        break;
                                default:
                                        return 0;
@@ -1121,6 +1483,7 @@ static int get_fp_value (uae_u32 opcode, uae_u16 extra, fpdata *src, uaecptr old
        }
 
        *adp = ad;
+       ad2 = ad;
 
        if (currprefs.fpu_model == 68060 && fault_if_unimplemented_680x0 (opcode, extra, ad, oldpc, src, -1))
                return -1;
@@ -1128,10 +1491,12 @@ static int get_fp_value (uae_u32 opcode, uae_u16 extra, fpdata *src, uaecptr old
        switch (size)
        {
                case 0:
-                       src->fp = (fptype) (uae_s32) (doext ? exts[0] : x_cp_get_long (ad));
+                       fpset(src, (uae_s32) (doext ? exts[0] : x_cp_get_long (ad)));
                        break;
                case 1:
-                       src->fp = to_single ((doext ? exts[0] : x_cp_get_long (ad)));
+                       to_single (src, (doext ? exts[0] : x_cp_get_long (ad)));
+                       if (fault_if_no_denormal_support_pre(opcode, extra, 0, oldpc, src, 0))
+                               return -1;
                        break;
                case 2:
                        {
@@ -1142,6 +1507,8 @@ static int get_fp_value (uae_u32 opcode, uae_u16 extra, fpdata *src, uaecptr old
                                ad += 4;
                                wrd3 = (doext ? exts[2] : x_cp_get_long (ad));
                                to_exten (src, wrd1, wrd2, wrd3);
+                               if (fault_if_no_denormal_support_pre(opcode, extra, 0, oldpc, src, 2))
+                                       return -1;
                        }
                        break;
                case 3:
@@ -1159,11 +1526,12 @@ static int get_fp_value (uae_u32 opcode, uae_u16 extra, fpdata *src, uaecptr old
                                wrd[2] = (doext ? exts[2] : x_cp_get_long (ad));
                                if (fault_if_4060 (opcode, extra, adold, oldpc, FPU_EXP_UNIMP_DATATYPE_PACKED_PRE, NULL, wrd))
                                        return -1;
-                               src->fp = to_pack (wrd);
+                               to_pack (src, wrd);
+                               return 1;
                        }
                        break;
                case 4:
-                       src->fp = (fptype) (uae_s16) (doext ? exts[0] : x_cp_get_word (ad));
+                       fpset(src, (uae_s16) (doext ? exts[0] : x_cp_get_word (ad)));
                        break;
                case 5:
                        {
@@ -1171,11 +1539,13 @@ static int get_fp_value (uae_u32 opcode, uae_u16 extra, fpdata *src, uaecptr old
                                wrd1 = (doext ? exts[0] : x_cp_get_long (ad));
                                ad += 4;
                                wrd2 = (doext ? exts[1] : x_cp_get_long (ad));
-                               src->fp = to_double (wrd1, wrd2);
+                               to_double (src, wrd1, wrd2);
+                               if (fault_if_no_denormal_support_pre(opcode, extra, 0, oldpc, src, 1))
+                                       return -1;
                        }
                        break;
                case 6:
-                       src->fp = (fptype) (uae_s8) (doext ? exts[0] : x_cp_get_byte (ad));
+                       fpset(src, (uae_s8) (doext ? exts[0] : x_cp_get_byte (ad)));
                        break;
                default:
                        return 0;
@@ -1193,9 +1563,6 @@ static int put_fp_value (fpdata *value, uae_u32 opcode, uae_u16 extra, uaecptr o
 #if DEBUG_FPP
        if (!isinrom ())
                write_log (_T("PUTFP: %f %04X %04X\n"), value, opcode, extra);
-#endif
-#ifdef USE_SOFT_LONG_DOUBLE
-       value->fpx = false;
 #endif
        if (!(extra & 0x4000)) {
                if (fault_if_no_fpu (opcode, extra, 0, oldpc))
@@ -1213,18 +1580,18 @@ static int put_fp_value (fpdata *value, uae_u32 opcode, uae_u16 extra, uaecptr o
                        switch (size)
                        {
                                case 6:
-                                       m68k_dreg (regs, reg) = (uae_u32)(((toint (value->fp, -128.0, 127.0) & 0xff)
+                                       m68k_dreg (regs, reg) = (uae_u32)(((toint (value0) & 0xff)
                                                | (m68k_dreg (regs, reg) & ~0xff)));
                                        break;
                                case 4:
-                                       m68k_dreg (regs, reg) = (uae_u32)(((toint (value->fp, -32768.0, 32767.0) & 0xffff)
+                                       m68k_dreg (regs, reg) = (uae_u32)(((toint (value, 1) & 0xffff)
                                                | (m68k_dreg (regs, reg) & ~0xffff)));
                                        break;
                                case 0:
-                                       m68k_dreg (regs, reg) = (uae_u32)toint (value->fp, -2147483648.0, 2147483647.0);
+                                       m68k_dreg (regs, reg) = (uae_u32)toint (value, 2);
                                        break;
                                case 1:
-                                       m68k_dreg (regs, reg) = from_single (value->fp);
+                                       m68k_dreg (regs, reg) = from_single (value);
                                        break;
                                default:
                                        return 0;
@@ -1286,15 +1653,21 @@ static int put_fp_value (fpdata *value, uae_u32 opcode, uae_u16 extra, uaecptr o
        switch (size)
        {
                case 0:
-                       x_cp_put_long (ad, (uae_u32)toint (value->fp, -2147483648.0, 2147483647.0));
+                       if (fault_if_no_denormal_support_post(opcode, extra, ad, oldpc, value, 2))
+                               return 1;
+                       x_cp_put_long(ad, (uae_u32)toint(value, 2));
                        break;
                case 1:
-                       x_cp_put_long (ad, from_single (value->fp));
+                       if (fault_if_no_denormal_support_post(opcode, extra, ad, oldpc, value, 2))
+                               return -1;
+                       x_cp_put_long(ad, from_single(value));
                        break;
                case 2:
                        {
                                uae_u32 wrd1, wrd2, wrd3;
-                               from_exten (value, &wrd1, &wrd2, &wrd3);
+                               if (fault_if_no_denormal_support_post(opcode, extra, ad, oldpc, value, 2))
+                                       return 1;
+                               from_exten(value, &wrd1, &wrd2, &wrd3);
                                x_cp_put_long (ad, wrd1);
                                ad += 4;
                                x_cp_put_long (ad, wrd2);
@@ -1308,12 +1681,12 @@ static int put_fp_value (fpdata *value, uae_u32 opcode, uae_u16 extra, uaecptr o
                                uae_u32 wrd[3];
                                int kfactor;
                                if (fault_if_4060 (opcode, extra, ad, oldpc, FPU_EXP_UNIMP_DATATYPE_PACKED_POST, value, NULL))
-                                       return -1;
+                                       return 1;
                                kfactor = size == 7 ? m68k_dreg (regs, (extra >> 4) & 7) : extra;
                                kfactor &= 127;
                                if (kfactor & 64)
                                        kfactor |= ~63;
-                               from_pack (value->fp, wrd, kfactor);
+                               from_pack (value, wrd, kfactor);
                                x_cp_put_long (ad, wrd[0]);
                                ad += 4;
                                x_cp_put_long (ad, wrd[1]);
@@ -1322,19 +1695,25 @@ static int put_fp_value (fpdata *value, uae_u32 opcode, uae_u16 extra, uaecptr o
                        }
                        break;
                case 4:
-                       x_cp_put_word (ad, (uae_s16) toint (value->fp, -32768.0, 32767.0));
+                       if (fault_if_no_denormal_support_post(opcode, extra, ad, oldpc, value, 2))
+                               return 1;
+                       x_cp_put_word(ad, (uae_s16)toint(value, 1));
                        break;
                case 5:
                        {
                                uae_u32 wrd1, wrd2;
-                               from_double (value->fp, &wrd1, &wrd2);
+                               if (fault_if_no_denormal_support_post(opcode, extra, ad, oldpc, value, 1))
+                                       return -1;
+                               from_double(value, &wrd1, &wrd2);
                                x_cp_put_long (ad, wrd1);
                                ad += 4;
                                x_cp_put_long (ad, wrd2);
                        }
                        break;
                case 6:
-                       x_cp_put_byte (ad, (uae_s8)toint (value->fp, -128.0, 127.0));
+                       if (fault_if_no_denormal_support_post(opcode, extra, ad, oldpc, value, 2))
+                               return 1;
+                       x_cp_put_byte(ad, (uae_s8)toint(value, 0));
                        break;
                default:
                        return 0;
@@ -1394,16 +1773,14 @@ STATIC_INLINE int get_fp_ad (uae_u32 opcode, uae_u32 * ad)
 
 int fpp_cond (int condition)
 {
-       int N = (regs.fp_result.fp < 0.0);
-       int Z = (regs.fp_result.fp == 0.0);
-       int NotANumber = 0;
+       int NotANumber, Z, N;
 
-#ifdef HAVE_ISNAN
-       NotANumber = isnan (regs.fp_result.fp);
-#endif
+       NotANumber = fp_is_nan(&regs.fp_result);
+       N = fp_is_neg(&regs.fp_result);
+       Z = fp_is_zero(&regs.fp_result);
 
-       if (NotANumber)
-               N=Z=0;
+       if ((condition & 0x10) && NotANumber)
+               regs.fp_result_status |= FP_BSUN;
 
        switch (condition)
        {
@@ -1680,8 +2057,8 @@ void fpuop_save (uae_u32 opcode)
 
                        from_exten(&regs.exp_src1, &src1[0], &src1[1], &src1[2]);
                        from_exten(&regs.exp_src2, &src2[0], &src2[1], &src2[2]);
-                       stag = get_ftag(src1[0], src1[1], src1[2]);
-                       dtag = get_ftag(src2[0], src2[1], src2[2]);
+                       stag = get_ftag(src1[0], src1[1], src1[2], regs.exp_size);
+                       dtag = get_ftag(src2[0], src2[1], src2[2], -1);
                        if ((extra & 0x7f) == 4) // FSQRT 4->5
                                extra |= 1;
 
@@ -1689,7 +2066,7 @@ void fpuop_save (uae_u32 opcode)
                        write_log(_T("68040 FSAVE %d (%d), CMDREG=%04X"), regs.exp_type, frame_size, extra);
                        if (regs.exp_type == FPU_EXP_UNIMP_DATATYPE_PACKED_PRE) {
                                write_log(_T(" PACKED %08x-%08x-%08x"), regs.exp_pack[0], regs.exp_pack[1], regs.exp_pack[2]);
-                       } else {
+                       } else if (regs.exp_type == FPU_EXP_UNIMP_DATATYPE_PACKED_POST) {
 #if USE_LONG_DOUBLE
                                write_log(_T(" SRC=%Le (%08x-%08x-%08x %d), DST=%Le (%08x-%08x-%08x %d)"), regs.exp_src1.fp, src1[0], src1[1], src1[2], stag, regs.exp_src2.fp, src2[0], src2[1], src2[2], dtag);
 #else
@@ -1916,11 +2293,6 @@ void fpuop_restore (uae_u32 opcode)
                m68k_areg (regs, opcode & 7) = ad;
 }
 
-static void fround (int reg)
-{
-       regs.fp[reg].fp = (float)regs.fp[reg].fp;
-}
-
 static uaecptr fmovem2mem (uaecptr ad, uae_u32 list, int incr, int regdir)
 {
        int reg;
@@ -2045,15 +2417,393 @@ static uaecptr fmovem2fpp (uaecptr ad, uae_u32 list, int incr, int regdir)
        return ad;
 }
 
+// round to float
+static void fround (int reg)
+{
+#ifdef WITH_SOFTFLOAT
+       if (currprefs.fpu_softfloat) {
+               float32 f = floatx80_to_float32(regs.fp[reg].fpx, fxstatus);
+               regs.fp[reg].fpx = float32_to_floatx80(f, fxstatus);
+       } else
+#endif
+               regs.fp[reg].fp = (float)regs.fp[reg].fp;
+}
+
+static bool arithmetic_fp(fptype src, int reg, int extra)
+{
+       bool sgl = false;
+       switch (extra & 0x7f)
+       {
+               case 0x00: /* FMOVE */
+               case 0x40: /* Explicit rounding. This is just a quick fix. */
+               case 0x44: /* Same for all other cases that have three choices */
+                       regs.fp[reg].fp = src;        /* Brian King was here. */
+                       /*<ea> to register needs FPSR updated. See Motorola 68K Manual. */
+                       break;
+               case 0x01: /* FINT */
+                       /* need to take the current rounding mode into account */
+#if defined(X86_MSVC_ASSEMBLY_FPU)
+                       {
+                               fptype tmp_fp;
+                               __asm {
+                                       fld  LDPTR src
+                                       frndint
+                                       fstp LDPTR tmp_fp
+                               }
+                               regs.fp[reg].fp = tmp_fp;
+                       }
+#else /* no X86_MSVC */
+                       switch (regs.fpcr & 0x30)
+                       {
+                               case FPCR_ROUND_NEAR:
+                                       regs.fp[reg].fp = fp_round_to_nearest(src);
+                                       break;
+                               case FPCR_ROUND_ZERO:
+                                       regs.fp[reg].fp = fp_round_to_zero(src);
+                                       break;
+                               case FPCR_ROUND_MINF:
+                                       regs.fp[reg].fp = fp_round_to_minus_infinity(src);
+                                       break;
+                               case FPCR_ROUND_PINF:
+                                       regs.fp[reg].fp = fp_round_to_plus_infinity(src);
+                                       break;
+                               default: /* never reached */
+                                       regs.fp[reg].fp = src;
+                                       break;
+                       }
+#endif /* X86_MSVC */
+                       break;
+               case 0x02: /* FSINH */
+                       regs.fp[reg].fp = sinh (src);
+                       break;
+               case 0x03: /* FINTRZ */
+                       regs.fp[reg].fp = fp_round_to_zero (src);
+                       break;
+               case 0x04: /* FSQRT */
+               case 0x41: /* FSSQRT */
+               case 0x45: /* FDSQRT */
+                       regs.fp[reg].fp = sqrt (src);
+                       break;
+               case 0x06: /* FLOGNP1 */
+                       regs.fp[reg].fp = log (src + 1.0);
+                       break;
+               case 0x08: /* FETOXM1 */
+                       regs.fp[reg].fp = exp (src) - 1.0;
+                       break;
+               case 0x09: /* FTANH */
+                       regs.fp[reg].fp = tanh (src);
+                       break;
+               case 0x0a: /* FATAN */
+                       regs.fp[reg].fp = atan (src);
+                       break;
+               case 0x0c: /* FASIN */
+                       regs.fp[reg].fp = asin (src);
+                       break;
+               case 0x0d: /* FATANH */
+                       regs.fp[reg].fp = atanh (src);
+                       break;
+               case 0x0e: /* FSIN */
+                       regs.fp[reg].fp = sin (src);
+                       break;
+               case 0x0f: /* FTAN */
+                       regs.fp[reg].fp = tan (src);
+                       break;
+               case 0x10: /* FETOX */
+                       regs.fp[reg].fp = exp (src);
+                       break;
+               case 0x11: /* FTWOTOX */
+                       regs.fp[reg].fp = pow (2.0, src);
+                       break;
+               case 0x12: /* FTENTOX */
+                       regs.fp[reg].fp = pow (10.0, src);
+                       break;
+               case 0x14: /* FLOGN */
+                       regs.fp[reg].fp = log (src);
+                       break;
+               case 0x15: /* FLOG10 */
+                       regs.fp[reg].fp = log10 (src);
+                       break;
+               case 0x16: /* FLOG2 */
+                       regs.fp[reg].fp = *fp_l2_e * log (src);
+                       break;
+               case 0x18: /* FABS */
+               case 0x58: /* FSABS */
+               case 0x5c: /* FDABS */
+                       regs.fp[reg].fp = src < 0 ? -src : src;
+                       break;
+               case 0x19: /* FCOSH */
+                       regs.fp[reg].fp = cosh (src);
+                       break;
+               case 0x1a: /* FNEG */
+               case 0x5a: /* FSNEG */
+               case 0x5e: /* FDNEG */
+                       regs.fp[reg].fp = -src;
+                       break;
+               case 0x1c: /* FACOS */
+                       regs.fp[reg].fp = acos (src);
+                       break;
+               case 0x1d: /* FCOS */
+                       regs.fp[reg].fp = cos (src);
+                       break;
+               case 0x1e: /* FGETEXP */
+                       {
+                               if (src == 0) {
+                                       regs.fp[reg].fp = 0;
+                               } else {
+                                       int expon;
+                                       frexp (src, &expon);
+                                       regs.fp[reg].fp = (double) (expon - 1);
+                               }
+                       }
+                       break;
+               case 0x1f: /* FGETMAN */
+                       {
+                               if (src == 0) {
+                                       regs.fp[reg].fp = 0;
+                               } else {
+                                       int expon;
+                                       regs.fp[reg].fp = frexp (src, &expon) * 2.0;
+                               }
+                       }
+                       break;
+               case 0x20: /* FDIV */
+               case 0x60: /* FSDIV */
+               case 0x64: /* FDDIV */
+                       regs.fp[reg].fp /= src;
+                       break;
+               case 0x21: /* FMOD */
+                       {
+                               fptype quot = fp_round_to_zero(regs.fp[reg].fp / src);
+                               regs.fp[reg].fp = regs.fp[reg].fp - quot * src;
+                       }
+                       break;
+               case 0x22: /* FADD */
+               case 0x62: /* FSADD */
+               case 0x66: /* FDADD */
+                       regs.fp[reg].fp += src;
+                       break;
+               case 0x23: /* FMUL */
+               case 0x63: /* FSMUL */
+               case 0x67: /* FDMUL */
+                       regs.fp[reg].fp *= src;
+                       break;
+               case 0x24: /* FSGLDIV */
+                       regs.fp[reg].fp /= src;
+                       sgl = true;
+                       break;
+               case 0x25: /* FREM */
+                       {
+                               fptype quot = fp_round_to_nearest(regs.fp[reg].fp / src);
+                               regs.fp[reg].fp = regs.fp[reg].fp - quot * src;
+                       }
+                       break;
+               case 0x26: /* FSCALE */
+                       if (src != 0) {
+#ifdef ldexp
+                               regs.fp[reg] = ldexp (regs.fp[reg], (int) src);
+#else
+                               regs.fp[reg].fp *= exp (*fp_ln_2 * (int) src);
+#endif
+                       }
+                       break;
+               case 0x27: /* FSGLMUL */
+                       regs.fp[reg].fp *= src;
+                       sgl = true;
+                       break;
+               case 0x28: /* FSUB */
+               case 0x68: /* FSSUB */
+               case 0x6c: /* FDSUB */
+                       regs.fp[reg].fp -= src;
+                       break;
+               case 0x30: /* FSINCOS */
+               case 0x31:
+               case 0x32:
+               case 0x33:
+               case 0x34:
+               case 0x35:
+               case 0x36:
+               case 0x37:
+                       regs.fp[extra & 7].fp = cos (src);
+                       regs.fp[reg].fp = sin (src);
+                       break;
+               case 0x38: /* FCMP */
+                       {
+                               fptype tmp = regs.fp[reg].fp - src;
+                               regs.fpsr = 0;
+                               MAKE_FPSR (&tmp);
+                       }
+                       return true;
+               case 0x3a: /* FTST */
+                       regs.fpsr = 0;
+                       MAKE_FPSR (&src);
+                       return true;
+               default:
+                       return false;
+       }
+       // round to float?
+       if (sgl || (extra & 0x44) == 0x40)
+               fround (reg);
+       MAKE_FPSR (&regs.fp[reg].fp);
+       return true;
+}
+
+#ifdef WITH_SOFTFLOAT
+static bool arithmetic_softfloat(floatx80 *srcd, int reg, int extra)
+{
+       floatx80 fx = *srcd;
+       floatx80 f = regs.fp[reg].fpx;
+       int float_rounding_mode;
+       bool sgl = false;
+       Bit64u q;
+
+       // SNAN -> QNAN if SNAN interrupt is not enabled
+       if (floatx80_is_signaling_nan(fx) && !(regs.fpcr & 0x4000)) {
+               fx.fraction |= 0x40000000;
+       }
+
+       switch (extra & 0x7f)
+       {
+               case 0x00: /* FMOVE */
+               case 0x40:
+               case 0x44:
+                       regs.fp[reg].fpx = fx;  
+                       break;
+               case 0x01: /* FINT */
+                       regs.fp[reg].fpx = floatx80_round_to_int(fx, fxstatus);
+                       break;
+               case 0x03: /* FINTRZ */
+                       float_rounding_mode = fxstatus.float_rounding_mode;
+                       fxstatus.float_rounding_mode = float_round_to_zero;
+                       regs.fp[reg].fpx = floatx80_round_to_int(fx, fxstatus);
+                       float_rounding_mode = fxstatus.float_rounding_mode;
+                       break;
+               case 0x04: /* FSQRT */
+               case 0x41: /* FSSQRT */
+               case 0x45: /* FDSQRT */
+                       regs.fp[reg].fpx = floatx80_sqrt(fx, fxstatus);
+                       break;
+               case 0x18: /* FABS */
+               case 0x58: /* FSABS */
+               case 0x5c: /* FDABS */
+                       regs.fp[reg].fpx = floatx80_abs(fx);
+                       break;
+               case 0x1a: /* FNEG */
+               case 0x5a: /* FSNEG */
+               case 0x5e: /* FDNEG */
+                       // same here..
+                       regs.fp[reg].fpx = floatx80_chs(fx);
+                       break;
+               case 0x20: /* FDIV */
+               case 0x60: /* FSDIV */
+               case 0x64: /* FDDIV */
+                       regs.fp[reg].fpx = floatx80_div(f, fx, fxstatus);
+                       break;
+               case 0x22: /* FADD */
+               case 0x62: /* FSADD */
+               case 0x66: /* FDADD */
+                       regs.fp[reg].fpx = floatx80_add(f, fx, fxstatus);
+                       break;
+               case 0x23: /* FMUL */
+               case 0x63: /* FSMUL */
+               case 0x67: /* FDMUL */
+                       regs.fp[reg].fpx = floatx80_mul(f, fx, fxstatus);
+                       break;
+               case 0x24: /* FSGLDIV */
+                       regs.fp[reg].fpx = floatx80_div(f, fx, fxstatus);
+                       sgl = true;
+                       break;
+               case 0x25: /* FREM */
+                       floatx80_ieee754_remainder(f, fx, regs.fp[reg].fpx, q, fxstatus);
+                       break;
+               case 0x27: /* FSGLMUL */
+                       regs.fp[reg].fpx = floatx80_mul(f, fx, fxstatus);
+                       sgl = true;
+                       break;
+               case 0x28: /* FSUB */
+               case 0x68: /* FSSUB */
+               case 0x6c: /* FDSUB */
+                       regs.fp[reg].fpx = floatx80_sub(f, fx, fxstatus);
+                       break;
+               case 0x38: /* FCMP */
+                       f = floatx80_sub(f, fx, fxstatus);
+                       regs.fpsr = 0;
+                       MAKE_FPSR_SOFTFLOAT(f);
+                       return true;
+               case 0x3a: /* FTST */
+                       regs.fpsr = 0;
+                       MAKE_FPSR_SOFTFLOAT(f);
+                       return true;
+
+               case 0x1d: /* FCOS */
+                       fcos(f, fxstatus);
+                       regs.fp[reg].fpx = f;
+                       break;
+               case 0x0e: /* FSIN */
+                       fsin(f, fxstatus);
+                       regs.fp[reg].fpx = f;
+                       break;
+               case 0x0f: /* FTAN */
+                       ftan(f, fxstatus);
+                       regs.fp[reg].fpx = f;
+                       break;
+               case 0x30: /* FSINCOS */
+               case 0x31: /* FSINCOS */
+               case 0x32: /* FSINCOS */
+               case 0x33: /* FSINCOS */
+               case 0x34: /* FSINCOS */
+               case 0x35: /* FSINCOS */
+               case 0x36: /* FSINCOS */
+               case 0x37: /* FSINCOS */
+                       fsincos(f, &regs.fp[extra & 7].fpx, &regs.fp[reg].fpx, fxstatus);
+                       break;
+
+                       // some of following are supported by softfloat, later..
+               case 0x06: /* FLOGNP1 */
+               case 0x08: /* FETOXM1 */
+               case 0x09: /* FTANH */
+               case 0x0a: /* FATAN */
+               case 0x0c: /* FASIN */
+               case 0x0d: /* FATANH */
+               case 0x10: /* FETOX */
+               case 0x11: /* FTWOTOX */
+               case 0x12: /* FTENTOX */
+               case 0x14: /* FLOGN */
+               case 0x15: /* FLOG10 */
+               case 0x16: /* FLOG2 */
+               case 0x19: /* FCOSH */
+               case 0x1c: /* FACOS */
+               case 0x1e: /* FGETEXP */
+               case 0x1f: /* FGETMAN */
+                       {
+                               // This is horribly ineffective..
+                               fptype fp;
+                               uae_u32 out[3];
+                               // convert softfloat to raw words
+                               softfloat_get(&fx, out);
+                               // convert to double/long double
+                               to_exten_x(&fp, out[0], out[1], out[2]);
+                               // emulate instruction using normal fpu code
+                               if (!arithmetic_fp(fp, reg, extra))
+                                       return false;
+                               // convert back to raw
+                               from_exten_x(regs.fp[reg].fp, &out[0], &out[1], &out[2]);
+                               // convert to softfloat internal format
+                               softfloat_set(&regs.fp[reg].fpx, out);
+                               MAKE_FPSR_SOFTFLOAT(regs.fp[reg].fpx);
+                       }
+                       break;
+       }
+       return true;
+}
+#endif
+
 static void fpuop_arithmetic2 (uae_u32 opcode, uae_u16 extra)
 {
        int reg = -1;
        int v;
-       fptype src;
        fpdata srcd;
        uaecptr pc = m68k_getpc () - 4;
        uaecptr ad = 0;
-       bool sgl;
 
 #if DEBUG_FPP
        if (!isinrom ())
@@ -2269,9 +3019,6 @@ static void fpuop_arithmetic2 (uae_u32 opcode, uae_u16 extra)
                case 2: /* Extremely common */
                        regs.fpiar = pc;
                        reg = (extra >> 7) & 7;
-#ifdef USE_SOFT_LONG_DOUBLE
-                       regs.fp[reg].fpx = false;
-#endif
                        if ((extra & 0xfc00) == 0x5c00) {
                                if (fault_if_no_fpu (opcode, extra, 0, pc))
                                        return;
@@ -2296,7 +3043,6 @@ static void fpuop_arithmetic2 (uae_u32 opcode, uae_u16 extra)
                                        fpu_noinst (opcode, pc);
                                return;
                        }
-                       src = srcd.fp;
 
                        // get_fp_value() checked this, but only if EA was nonzero (non-register)
                        if (fault_if_unimplemented_680x0 (opcode, extra, ad, pc, &srcd, reg))
@@ -2305,221 +3051,14 @@ static void fpuop_arithmetic2 (uae_u32 opcode, uae_u16 extra)
                        regs.fpiar =  pc;
 
                        CLEAR_STATUS ();
-                       sgl = false;
-                       switch (extra & 0x7f)
-                       {
-                               case 0x00: /* FMOVE */
-                               case 0x40: /* Explicit rounding. This is just a quick fix. */
-                               case 0x44: /* Same for all other cases that have three choices */
-                                       regs.fp[reg].fp = src;        /* Brian King was here. */
-                                       /*<ea> to register needs FPSR updated. See Motorola 68K Manual. */
-                                       break;
-                               case 0x01: /* FINT */
-                                       /* need to take the current rounding mode into account */
-#if defined(X86_MSVC_ASSEMBLY_FPU)
-                                       {
-                                               fptype tmp_fp;
-
-                                               __asm {
-                                                       fld  LDPTR src
-                                                       frndint
-                                                       fstp LDPTR tmp_fp
-                                               }
-                                               regs.fp[reg].fp = tmp_fp;
-                                       }
-#else /* no X86_MSVC */
-                                       switch (regs.fpcr & 0x30)
-                                       {
-                                               case FPCR_ROUND_NEAR:
-                                                       regs.fp[reg].fp = fp_round_to_nearest(src);
-                                                       break;
-                                               case FPCR_ROUND_ZERO:
-                                                       regs.fp[reg].fp = fp_round_to_zero(src);
-                                                       break;
-                                               case FPCR_ROUND_MINF:
-                                                       regs.fp[reg].fp = fp_round_to_minus_infinity(src);
-                                                       break;
-                                               case FPCR_ROUND_PINF:
-                                                       regs.fp[reg].fp = fp_round_to_plus_infinity(src);
-                                                       break;
-                                               default: /* never reached */
-                                                       regs.fp[reg].fp = src;
-                                                       break;
-                                       }
-#endif /* X86_MSVC */
-                                       break;
-                               case 0x02: /* FSINH */
-                                       regs.fp[reg].fp = sinh (src);
-                                       break;
-                               case 0x03: /* FINTRZ */
-                                       regs.fp[reg].fp = fp_round_to_zero (src);
-                                       break;
-                               case 0x04: /* FSQRT */
-                               case 0x41: /* FSSQRT */
-                               case 0x45: /* FDSQRT */
-                                       regs.fp[reg].fp = sqrt (src);
-                                       break;
-                               case 0x06: /* FLOGNP1 */
-                                       regs.fp[reg].fp = log (src + 1.0);
-                                       break;
-                               case 0x08: /* FETOXM1 */
-                                       regs.fp[reg].fp = exp (src) - 1.0;
-                                       break;
-                               case 0x09: /* FTANH */
-                                       regs.fp[reg].fp = tanh (src);
-                                       break;
-                               case 0x0a: /* FATAN */
-                                       regs.fp[reg].fp = atan (src);
-                                       break;
-                               case 0x0c: /* FASIN */
-                                       regs.fp[reg].fp = asin (src);
-                                       break;
-                               case 0x0d: /* FATANH */
-                                       regs.fp[reg].fp = atanh (src);
-                                       break;
-                               case 0x0e: /* FSIN */
-                                       regs.fp[reg].fp = sin (src);
-                                       break;
-                               case 0x0f: /* FTAN */
-                                       regs.fp[reg].fp = tan (src);
-                                       break;
-                               case 0x10: /* FETOX */
-                                       regs.fp[reg].fp = exp (src);
-                                       break;
-                               case 0x11: /* FTWOTOX */
-                                       regs.fp[reg].fp = pow (2.0, src);
-                                       break;
-                               case 0x12: /* FTENTOX */
-                                       regs.fp[reg].fp = pow (10.0, src);
-                                       break;
-                               case 0x14: /* FLOGN */
-                                       regs.fp[reg].fp = log (src);
-                                       break;
-                               case 0x15: /* FLOG10 */
-                                       regs.fp[reg].fp = log10 (src);
-                                       break;
-                               case 0x16: /* FLOG2 */
-                                       regs.fp[reg].fp = *fp_l2_e * log (src);
-                                       break;
-                               case 0x18: /* FABS */
-                               case 0x58: /* FSABS */
-                               case 0x5c: /* FDABS */
-                                       regs.fp[reg].fp = src < 0 ? -src : src;
-                                       break;
-                               case 0x19: /* FCOSH */
-                                       regs.fp[reg].fp = cosh (src);
-                                       break;
-                               case 0x1a: /* FNEG */
-                               case 0x5a: /* FSNEG */
-                               case 0x5e: /* FDNEG */
-                                       regs.fp[reg].fp = -src;
-                                       break;
-                               case 0x1c: /* FACOS */
-                                       regs.fp[reg].fp = acos (src);
-                                       break;
-                               case 0x1d: /* FCOS */
-                                       regs.fp[reg].fp = cos (src);
-                                       break;
-                               case 0x1e: /* FGETEXP */
-                                       {
-                                               if (src == 0) {
-                                                       regs.fp[reg].fp = 0;
-                                               } else {
-                                                       int expon;
-                                                       frexp (src, &expon);
-                                                       regs.fp[reg].fp = (double) (expon - 1);
-                                               }
-                                       }
-                                       break;
-                               case 0x1f: /* FGETMAN */
-                                       {
-                                               if (src == 0) {
-                                                       regs.fp[reg].fp = 0;
-                                               } else {
-                                                       int expon;
-                                                       regs.fp[reg].fp = frexp (src, &expon) * 2.0;
-                                               }
-                                       }
-                                       break;
-                               case 0x20: /* FDIV */
-                               case 0x60: /* FSDIV */
-                               case 0x64: /* FDDIV */
-                                       regs.fp[reg].fp /= src;
-                                       break;
-                               case 0x21: /* FMOD */
-                                       {
-                                               fptype quot = fp_round_to_zero(regs.fp[reg].fp / src);
-                                               regs.fp[reg].fp = regs.fp[reg].fp - quot * src;
-                                       }
-                                       break;
-                               case 0x22: /* FADD */
-                               case 0x62: /* FSADD */
-                               case 0x66: /* FDADD */
-                                       regs.fp[reg].fp += src;
-                                       break;
-                               case 0x23: /* FMUL */
-                               case 0x63: /* FSMUL */
-                               case 0x67: /* FDMUL */
-                                       regs.fp[reg].fp *= src;
-                                       break;
-                               case 0x24: /* FSGLDIV */
-                                       regs.fp[reg].fp /= src;
-                                       sgl = true;
-                                       break;
-                               case 0x25: /* FREM */
-                                       {
-                                               fptype quot = fp_round_to_nearest(regs.fp[reg].fp / src);
-                                               regs.fp[reg].fp = regs.fp[reg].fp - quot * src;
-                                       }
-                                       break;
-                               case 0x26: /* FSCALE */
-                                       if (src != 0) {
-#ifdef ldexp
-                                               regs.fp[reg] = ldexp (regs.fp[reg], (int) src);
-#else
-                                               regs.fp[reg].fp *= exp (*fp_ln_2 * (int) src);
+#ifdef WITH_SOFTFLOAT
+                       if (currprefs.fpu_softfloat)
+                               v = arithmetic_softfloat(&srcd.fpx, reg, extra);
+                       else
 #endif
-                                       }
-                                       break;
-                               case 0x27: /* FSGLMUL */
-                                       regs.fp[reg].fp *= src;
-                                       sgl = true;
-                                       break;
-                               case 0x28: /* FSUB */
-                               case 0x68: /* FSSUB */
-                               case 0x6c: /* FDSUB */
-                                       regs.fp[reg].fp -= src;
-                                       break;
-                               case 0x30: /* FSINCOS */
-                               case 0x31:
-                               case 0x32:
-                               case 0x33:
-                               case 0x34:
-                               case 0x35:
-                               case 0x36:
-                               case 0x37:
-                                       regs.fp[extra & 7].fp = cos (src);
-                                       regs.fp[reg].fp = sin (src);
-                                       break;
-                               case 0x38: /* FCMP */
-                                       {
-                                               fptype tmp = regs.fp[reg].fp - src;
-                                               regs.fpsr = 0;
-                                               MAKE_FPSR (&tmp);
-                                       }
-                                       return;
-                               case 0x3a: /* FTST */
-                                       regs.fpsr = 0;
-                                       MAKE_FPSR (&src);
-                                       return;
-                               default:
-                                       fpu_noinst (opcode, pc);
-                                       return;
-                       }
-                       // round to float?
-                       if (sgl || (extra & 0x44) == 0x40)
-                               fround (reg);
-                       MAKE_FPSR (&regs.fp[reg].fp);
+                               v = arithmetic_fp(srcd.fp, reg, extra);
+                       if (!v)
+                               fpu_noinst (opcode, pc);
                        return;
                default:
                break;
@@ -2536,21 +3075,23 @@ void fpuop_arithmetic (uae_u32 opcode, uae_u16 extra)
        if (fpu_mmu_fixup) {
                mmufixup[0].reg = -1;
        }
-#if 0
-       // Any exception status bit and matching exception enable bits set?
-       if ((regs.fpcr >> 8) & (regs.fpsr >> 8)) {
-               uae_u32 mask = regs.fpcr >> 8;
-               int vector = 0;
-               for (int i = 7; i >= 0; i--) {
-                       if (mask & (1 << i)) {
-                               if (i > 0)
-                                       i--;
-                               vector = i + 48;
-                               break;
+#ifdef WITH_SOFTFLOAT
+       if (currprefs.fpu_softfloat) {
+               // Any exception status bit and matching exception enable bits set?
+               if ((regs.fpcr >> 8) & (regs.fpsr >> 8)) {
+                       uae_u32 mask = regs.fpcr >> 8;
+                       int vector = 0;
+                       for (int i = 7; i >= 0; i--) {
+                               if (mask & (1 << i)) {
+                                       if (i > 0)
+                                               i--;
+                                       vector = i + 48;
+                                       break;
+                               }
                        }
+                       // logging only so far
+                       write_log (_T("FPU exception: %08x %d!\n"), regs.fpsr, vector);
                }
-               // logging only so far
-               write_log (_T("FPU exception: %08x %d!\n"), regs.fpsr, vector);
        }
 #endif
 }
@@ -2562,6 +3103,21 @@ void fpu_reset (void)
        fpset (&regs.fp_result, 1);
        native_set_fpucw (regs.fpcr);
        fpux_restore (NULL);
+
+#ifdef WITH_SOFTFLOAT
+       fxsizes[0] = int32_to_floatx80(-128);
+       fxsizes[1] = int32_to_floatx80(127);
+       fxsizes[2] = int32_to_floatx80(-32768);
+       fxsizes[3] = int32_to_floatx80(32767);
+       fxsizes[4] = int32_to_floatx80(-2147483648);
+       fxsizes[5] = int32_to_floatx80(2147483647);
+       fxzero = int32_to_floatx80(0);
+       fx_1e0 = int32_to_floatx80(1);
+       fx_1e1 = int32_to_floatx80(10);
+       fx_1e2 = int32_to_floatx80(100);
+       fx_1e4 = int32_to_floatx80(10000);
+       fx_1e8 = int32_to_floatx80(100000000);
+#endif
 }
 
 uae_u8 *restore_fpu (uae_u8 *src)
@@ -2573,9 +3129,9 @@ uae_u8 *restore_fpu (uae_u8 *src)
        changed_prefs.fpu_model = currprefs.fpu_model = restore_u32 ();
        flags = restore_u32 ();
        for (i = 0; i < 8; i++) {
-               w1 = restore_u32 ();
+               w1 = restore_u16 () << 16;
                w2 = restore_u32 ();
-               w3 = restore_u16 ();
+               w3 = restore_u32 ();
                to_exten (&regs.fp[i], w1, w2, w3);
        }
        regs.fpcr = restore_u32 ();
@@ -2587,13 +3143,13 @@ uae_u8 *restore_fpu (uae_u8 *src)
                restore_u32 ();
        }
        if (flags & 0x40000000) {
-               w1 = restore_u32();
+               w1 = restore_u16() << 16;
                w2 = restore_u32();
-               w3 = restore_u16();
+               w3 = restore_u32();
                to_exten(&regs.exp_src1, w1, w2, w3);
-               w1 = restore_u32();
+               w1 = restore_u16() << 16;
                w2 = restore_u32();
-               w3 = restore_u16();
+               w3 = restore_u32();
                to_exten(&regs.exp_src2, w1, w2, w3);
                regs.exp_pack[0] = restore_u32();
                regs.exp_pack[1] = restore_u32();
@@ -2627,9 +3183,9 @@ uae_u8 *save_fpu (int *len, uae_u8 *dstptr)
        save_u32 (0x80000000 | 0x40000000 | (regs.fpu_state == 0 ? 1 : 0) | (regs.fpu_exp_state ? 2 : 0) | (regs.fpu_exp_state > 1 ? 4 : 0));
        for (i = 0; i < 8; i++) {
                from_exten (&regs.fp[i], &w1, &w2, &w3);
-               save_u32 (w1);
+               save_u16 (w1 >> 16);
                save_u32 (w2);
-               save_u16 (w3);
+               save_u32 (w3);
        }
        save_u32 (regs.fpcr);
        save_u32 (regs.fpsr);
@@ -2639,13 +3195,13 @@ uae_u8 *save_fpu (int *len, uae_u8 *dstptr)
        save_u32 (0);
 
        from_exten(&regs.exp_src1, &w1, &w2, &w3);
-       save_u32(w1);
+       save_u16(w1 >> 16);
        save_u32(w2);
-       save_u16(w3);
+       save_u32(w3);
        from_exten(&regs.exp_src2, &w1, &w2, &w3);
-       save_u32(w1);
+       save_u16(w1 >> 16);
        save_u32(w2);
-       save_u16(w3);
+       save_u32(w3);
        save_u32(regs.exp_pack[0]);
        save_u32(regs.exp_pack[1]);
        save_u32(regs.exp_pack[2]);
index a8ca55f817637521619832a241ed7045a9da86ef..54420a8daf1fec34d57b68017451e8e89fa7c02f 100644 (file)
--- a/gayle.cpp
+++ b/gayle.cpp
@@ -1557,12 +1557,12 @@ static uae_u32 REGPARAM2 gayle_lget (uaecptr addr)
        if (isa4000t (&addr)) {
                if (addr >= NCR_ALT_OFFSET) {
                        addr &= NCR_MASK;
-                       v = (ncr_io_bget_a4000t (addr + 3) << 0) | (ncr_io_bget_a4000t (addr + 2) << 8) |
-                               (ncr_io_bget_a4000t (addr + 1) << 16) | (ncr_io_bget_a4000t (addr + 0) << 24);
+                       v = (ncr710_io_bget_a4000t(addr + 3) << 0) | (ncr710_io_bget_a4000t(addr + 2) << 8) |
+                               (ncr710_io_bget_a4000t(addr + 1) << 16) | (ncr710_io_bget_a4000t(addr + 0) << 24);
                } else if (addr >= NCR_OFFSET) {
                        addr &= NCR_MASK;
-                       v = (ncr_io_bget_a4000t (addr + 3) << 0) | (ncr_io_bget_a4000t (addr + 2) << 8) |
-                               (ncr_io_bget_a4000t (addr + 1) << 16) | (ncr_io_bget_a4000t (addr + 0) << 24);
+                       v = (ncr710_io_bget_a4000t(addr + 3) << 0) | (ncr710_io_bget_a4000t(addr + 2) << 8) |
+                               (ncr710_io_bget_a4000t(addr + 1) << 16) | (ncr710_io_bget_a4000t(addr + 0) << 24);
                }
                return v;
        }
@@ -1591,7 +1591,7 @@ static uae_u32 REGPARAM2 gayle_wget (uaecptr addr)
        if (isa4000t (&addr)) {
                if (addr >= NCR_OFFSET) {
                        addr &= NCR_MASK;
-                       v = (ncr_io_bget_a4000t (addr) << 8) | ncr_io_bget_a4000t (addr + 1);
+                       v = (ncr710_io_bget_a4000t(addr) << 8) | ncr710_io_bget_a4000t(addr + 1);
                }
                return v;
        }
@@ -1614,7 +1614,7 @@ static uae_u32 REGPARAM2 gayle_bget (uaecptr addr)
        if (isa4000t (&addr)) {
                if (addr >= NCR_OFFSET) {
                        addr &= NCR_MASK;
-                       return ncr_io_bget_a4000t (addr);
+                       return ncr710_io_bget_a4000t(addr);
                }
                return 0;
        }
@@ -1632,16 +1632,16 @@ static void REGPARAM2 gayle_lput (uaecptr addr, uae_u32 value)
        if (isa4000t (&addr)) {
                if (addr >= NCR_ALT_OFFSET) {
                        addr &= NCR_MASK;
-                       ncr_io_bput_a4000t (addr + 3, value >> 0);
-                       ncr_io_bput_a4000t (addr + 2, value >> 8);
-                       ncr_io_bput_a4000t (addr + 1, value >> 16);
-                       ncr_io_bput_a4000t (addr + 0, value >> 24);
+                       ncr710_io_bput_a4000t(addr + 3, value >> 0);
+                       ncr710_io_bput_a4000t(addr + 2, value >> 8);
+                       ncr710_io_bput_a4000t(addr + 1, value >> 16);
+                       ncr710_io_bput_a4000t(addr + 0, value >> 24);
                } else if (addr >= NCR_OFFSET) {
                        addr &= NCR_MASK;
-                       ncr_io_bput_a4000t (addr + 3, value >> 0);
-                       ncr_io_bput_a4000t (addr + 2, value >> 8);
-                       ncr_io_bput_a4000t (addr + 1, value >> 16);
-                       ncr_io_bput_a4000t (addr + 0, value >> 24);
+                       ncr710_io_bput_a4000t(addr + 3, value >> 0);
+                       ncr710_io_bput_a4000t(addr + 2, value >> 8);
+                       ncr710_io_bput_a4000t(addr + 1, value >> 16);
+                       ncr710_io_bput_a4000t(addr + 0, value >> 24);
                }
                return;
        }
@@ -1665,8 +1665,8 @@ static void REGPARAM2 gayle_wput (uaecptr addr, uae_u32 value)
        if (isa4000t (&addr)) {
                if (addr >= NCR_OFFSET) {
                        addr &= NCR_MASK;
-                       ncr_io_bput_a4000t (addr, value >> 8);
-                       ncr_io_bput_a4000t (addr + 1, value);
+                       ncr710_io_bput_a4000t(addr, value >> 8);
+                       ncr710_io_bput_a4000t(addr + 1, value);
                }
                return;
        }
@@ -1689,7 +1689,7 @@ static void REGPARAM2 gayle_bput (uaecptr addr, uae_u32 value)
        if (isa4000t (&addr)) {
                if (addr >= NCR_OFFSET) {
                        addr &= NCR_MASK;
-                       ncr_io_bput_a4000t (addr, value);
+                       ncr710_io_bput_a4000t(addr, value);
                }
                return;
        }
@@ -2287,9 +2287,9 @@ static void initsramattr (int size, int readonly)
        *p++= 4; /* PCMCIA 2.1 */
        *p++= 1;
        if (real) {
-               ua_copy ((char*)p, -1, hfd->product_id);
+               ua_copy ((char*)p, 8, hfd->product_id);
                p += strlen ((char*)p) + 1;
-               ua_copy ((char*)p, -1, hfd->product_rev);
+               ua_copy ((char*)p, 16, hfd->product_rev);
        } else {
                strcpy ((char*)p, "UAE");
                p += strlen ((char*)p) + 1;
@@ -2841,8 +2841,8 @@ void gayle_reset (int hardreset)
 #ifdef NCR
        if (currprefs.cs_mbdmac == 2) {
                _tcscat (bankname, _T(" + NCR53C710 SCSI"));
-               ncr_init ();
-               ncr_reset ();
+               ncr710_init();
+               ncr710_reset();
        }
 #endif
        gayle_bank.name = bankname;
index b0a66ad48ed16968acfc7818b2673eb9985c559f..ed27dc6261933a6336a34006ec3aff01ebb8a1e4 100644 (file)
@@ -181,10 +181,26 @@ static void cpulimit (void)
        printf ("#ifndef CPUEMU_68000_ONLY\n");
 }
 
+static bool isce020(void)
+{
+       if (!using_ce020)
+               return false;
+       if (using_ce020 >= 3)
+               return false;
+       return true;
+}
+static bool isprefetch020(void)
+{
+       if (!using_prefetch_020)
+               return false;
+       if (using_prefetch_020 >= 3)
+               return false;
+       return true;
+}
 
 static void addcycles_ce020 (int cycles, char *s)
 {
-       if (!using_ce020)
+       if (!isce020())
                return;
        if (cycles > 0) {
                if (s == NULL)
@@ -202,21 +218,21 @@ static void addcycles_ce020 (int cycles)
 
 static void get_prefetch_020 (void)
 {
-       if (!using_prefetch_020 || no_prefetch_ce020)
+       if (!isprefetch020() || no_prefetch_ce020)
                return;
        printf ("\tregs.irc = %s (%d);\n", prefetch_word, m68k_pc_offset);
 }
 static void get_prefetch_020_0 (void)
 {
-       if (!using_prefetch_020 || no_prefetch_ce020)
+       if (!isprefetch020() || no_prefetch_ce020)
                return;
        printf ("\tregs.irc = %s (0);\n", prefetch_word);
 }
 
 static void returntail (bool iswrite)
 {
-       if (!using_ce020) {
-               if (using_prefetch_020) {
+       if (!isce020()) {
+               if (isprefetch020()) {
                        if (!tail_ce020_done) {
                                if (!did_prefetch)
                                        get_prefetch_020 ();
@@ -285,7 +301,7 @@ static void returncycles (char *s, int cycles)
 
 static void addcycles_ce020 (char *name, int head, int tail, int cycles)
 {
-       if (!using_ce020)
+       if (!isce020())
                return;
        if (!head && !tail && !cycles)
                return;
@@ -293,7 +309,7 @@ static void addcycles_ce020 (char *name, int head, int tail, int cycles)
 }
 static void addcycles_ce020 (char *name, int head, int tail, int cycles, int ophead)
 {
-       if (!using_ce020)
+       if (!isce020())
                return;
        if (!head && !tail && !cycles && !ophead) {
                printf ("\t/* OP zero */\n");
@@ -512,7 +528,7 @@ static const char *gen_nextibyte (int flags)
 static void makefromsr (void)
 {
        printf ("\tMakeFromSR();\n");
-       if (using_ce || using_ce020)
+       if (using_ce || isce020())
                printf ("\tregs.ipl_pin = intlev ();\n");
 }
 
@@ -520,7 +536,7 @@ static void check_ipl (void)
 {
        if (ipl_fetched)
                return;
-       if (using_ce || using_ce020)
+       if (using_ce || isce020())
                printf ("\tipl_fetch ();\n");
        ipl_fetched = true;
 }
@@ -570,7 +586,7 @@ static void fill_prefetch_full (void)
                fill_prefetch_1 (0);
                irc2ir ();
                fill_prefetch_1 (2);
-       } else if (using_prefetch_020) {
+       } else if (isprefetch020()) {
                did_prefetch = 2;
                total_ce020 -= 4;
                returntail (false);
@@ -749,7 +765,7 @@ static void head_cycs (int h)
 
 static void add_head_cycs (int h)
 {
-       if (!using_ce020)
+       if (!isce020())
                return;
        head_ce020_cycs_done = false;
        head_cycs (h);
@@ -842,7 +858,7 @@ static void addopcycles_ce20 (int h, int t, int c, int subhead)
 
 static void addop_ce020 (instr *curi, int subhead)
 {
-       if (!using_ce020)
+       if (!isce020())
                return;
        int h = curi->head;
        int t = curi->tail;
@@ -1555,7 +1571,7 @@ static void genamode (instr *curi, amodes mode, char *reg, wordsizes size, char
 {
        int oldfixup = mmufixupstate;
        int subhead = 0;
-       if (using_ce020 && curi) {
+       if (isce020() && curi) {
                switch (curi->fetchmode)
                {
                case fetchmode_fea:
@@ -1576,7 +1592,7 @@ static void genamode (instr *curi, amodes mode, char *reg, wordsizes size, char
                // we have fixup already active = this genamode call is destination mode and we can now clear previous source fixup.
                clearmmufixup (0);
        }
-       if (using_ce020 && curi)
+       if (isce020() && curi)
                addop_ce020 (curi, subhead);
 }
 
@@ -1596,7 +1612,7 @@ static void genamodedual (instr *curi, amodes smode, char *sreg, wordsizes ssize
        int subhead = 0;
        bool eadmode = false;
 
-       if (using_ce020) {
+       if (isce020()) {
                switch (curi->fetchmode)
                {
                case fetchmode_fea:
@@ -2578,6 +2594,23 @@ static void resetvars (void)
                        do_cycles = "do_cycles_ce020";
                        nextw = "next_iword_030ce";
                        nextl = "next_ilong_030ce";
+               } else if (using_ce020 == 3) {
+                       // 68040/060 CE
+                       disp020 = "x_get_disp_ea_040";
+                       prefetch_long = "get_ilong_cache_040";
+                       prefetch_word = "get_iword_cache_040";
+                       srcli = "x_get_ilong";
+                       srcwi = "x_get_iword";
+                       srcbi = "x_get_ibyte";
+                       srcl = "x_get_long";
+                       dstl = "x_put_long";
+                       srcw = "x_get_word";
+                       dstw = "x_put_word";
+                       srcb = "x_get_byte";
+                       dstb = "x_put_byte";
+                       do_cycles = "do_cycles_ce020";
+                       nextw = "next_iword_cache040";
+                       nextl = "next_ilong_cache040";
                } else if (using_prefetch_020) {
                        disp020 = "x_get_disp_ea_020";
                        prefetch_word = "get_word_020_prefetch";
@@ -3229,7 +3262,7 @@ static void gen_opcode (unsigned long int opcode)
                        * - move.x xxx,[at least 1 extension word here] = fetch 1 extension word before (xxx)
                        *
                        */
-                       if (using_ce020) {
+                       if (isce020()) {
                                // MOVE is too complex to handle in table68k
                                int h = 0, t = 0, c = 0, subhead = 0;
                                bool fea = false;
@@ -3749,7 +3782,7 @@ static void gen_opcode (unsigned long int opcode)
                break;
        case i_BSR:
                // .b/.w = idle cycle, store high, store low, 2xprefetch
-               if (using_ce020)
+               if (isce020())
                        no_prefetch_ce020 = true;
                printf ("\tuae_s32 s;\n");
                if (curi->size == sz_long) {
@@ -5402,7 +5435,7 @@ static void generate_cpu (int id, int mode)
        }
 
        postfix = id;
-       if (id == 0 || id == 11 || id == 13 || id == 20 || id == 21 || id == 22 || id == 31 || id == 32 || id == 33) {
+       if (id == 0 || id == 11 || id == 13 || id == 20 || id == 21 || id == 22 || id == 23 || id == 31 || id == 32 || id == 33) {
                if (generate_stbl)
                        fprintf (stblfile, "#ifdef CPUEMU_%d%s\n", postfix, extraup);
                postfix2 = postfix;
@@ -5457,13 +5490,21 @@ static void generate_cpu (int id, int mode)
                read_counts ();
                for (rp = 0; rp < nr_cpuop_funcs; rp++)
                        opcode_next_clev[rp] = cpu_level;
-       } else if (id == 22 || id == 23 || id == 24) { // 68030/040/60 "cycle-exact"
-               cpu_level = 3 + (24 - id);
+       } else if (id == 22) { // 68030 "cycle-exact"
+               cpu_level = 3;
                using_ce020 = 2;
                using_prefetch_020 = 2;
                memory_cycle_cnt = 2;
-               if (id == 22) {
-                       read_counts ();
+               read_counts ();
+               for (rp = 0; rp < nr_cpuop_funcs; rp++)
+                       opcode_next_clev[rp] = cpu_level;
+       } else if (id == 23 || id == 24) { // 68040/060 "cycle-exact"
+               cpu_level = id == 23 ? 5 : 4;
+               using_ce020 = 3;
+               using_prefetch_020 = 3;
+               memory_cycle_cnt = 0;
+               if (id == 23) {
+                       read_counts();
                        for (rp = 0; rp < nr_cpuop_funcs; rp++)
                                opcode_next_clev[rp] = cpu_level;
                }
index 4b244496781da79ce08a2b2257870178cc198b82..cee0469a278eaf20c008bfa24b3cbc5636fe8599 100644 (file)
@@ -341,9 +341,9 @@ static void create_virtual_rdb (struct hardfiledata *hfd)
        pl(rdb, 37, 0); // autopark
        pl(rdb, 38, 2); // highrdskblock
        pl(rdb, 39, -1); // res
-       ua_copy ((char*)rdb + 40 * 4, -1, hfd->vendor_id);
-       ua_copy ((char*)rdb + 42 * 4, -1, hfd->product_id);
-       ua_copy ((char*)rdb + 46 * 4, -1, _T("UAE"));
+       ua_copy ((char*)rdb + 40 * 4, 8, hfd->vendor_id);
+       ua_copy ((char*)rdb + 42 * 4, 16, hfd->product_id);
+       ua_copy ((char*)rdb + 46 * 4, 4, _T("UAE"));
        rdb_crc (rdb);
 
        pl(part, 0, 0x50415254);
@@ -355,8 +355,8 @@ static void create_virtual_rdb (struct hardfiledata *hfd)
        pl(part, 6, -1);
        pl(part, 7, -1);
        pl(part, 8, 0); // devflags
-       part[9 * 4] = _tcslen (hfd->device_name);
-       ua_copy ((char*)part + 9 * 4 + 1, -1, hfd->device_name);
+       part[9 * 4] = _tcslen (hfd->ci.devname);
+       ua_copy ((char*)part + 9 * 4 + 1, 30, hfd->ci.devname);
 
        denv = part + 128;
        pl(denv, 0, 80);
index 22517d40ef35f39414815f6fd14f8270558a2765..3c14ef3fcce7a3d1ca868dca0d5e68b3b916cf0b 100644 (file)
@@ -147,24 +147,19 @@ STATIC_INLINE void m68k_do_rts_ce020 (void)
 
 #ifdef CPUEMU_22
 
-extern uae_u32 get_word_ce030_prefetch (int);
-extern void write_dcache030 (uaecptr, uae_u32, int);
-extern uae_u32 read_dcache030 (uaecptr, int);
+extern uae_u32 get_word_ce030_prefetch(int);
 
 STATIC_INLINE void put_long_ce030 (uaecptr addr, uae_u32 v)
 {
        write_dcache030 (addr, v, 2);
-       mem_access_delay_long_write_ce020 (addr, v);
 }
 STATIC_INLINE void put_word_ce030 (uaecptr addr, uae_u32 v)
 {
        write_dcache030 (addr, v, 1);
-       mem_access_delay_word_write_ce020 (addr, v);
 }
 STATIC_INLINE void put_byte_ce030 (uaecptr addr, uae_u32 v)
 {
        write_dcache030 (addr, v, 0);
-       mem_access_delay_byte_write_ce020 (addr, v);
 }
 STATIC_INLINE uae_u32 get_long_ce030 (uaecptr addr)
 {
@@ -212,8 +207,6 @@ STATIC_INLINE void m68k_do_rts_ce030 (void)
        m68k_areg (regs, 7) += 4;
 }
 
-extern uae_u32 get_word_ce040_prefetch (int);
-
 #endif
 
 #ifdef CPUEMU_11
index ce5e5771941f050754d919f1d85be118f2b2676e..884852103b082983848658182354d0329fc814ea 100644 (file)
@@ -7,10 +7,20 @@ extern void cpuboard_cleanup(void);
 extern void cpuboard_init(void);
 extern void cpuboard_clear(void);
 extern void cpuboard_vsync(void);
+extern void cpuboard_rethink(void);
+
+extern void cyberstorm_scsi_ram_put(uaecptr addr, uae_u32);
+extern uae_u32 cyberstorm_scsi_ram_get(uaecptr addr);
+extern int REGPARAM3 cyberstorm_scsi_ram_check(uaecptr addr, uae_u32 size) REGPARAM;
+extern uae_u8 *REGPARAM3 cyberstorm_scsi_ram_xlate(uaecptr addr) REGPARAM;
 
 extern addrbank blizzardram_bank;
 
 #define BOARD_BLIZZARD_1230_IV 1
 #define BOARD_BLIZZARD_1260 2
 #define BOARD_BLIZZARD_2060 3
-#define BOARD_WARPENGINE_A4000 4
+#define BOARD_CSMK3 4
+#define BOARD_CSPPC 5
+#define BOARD_BLIZZARDPPC 6
+#define BOARD_WARPENGINE_A4000 7
+
index 458b1972a880ce5a982b33516da834ac57848abe..542643962e38a4880f68c1e9effeb0caf69a86a9 100644 (file)
@@ -323,6 +323,8 @@ extern void REGPARAM3 mmu060_put_rmw_bitfield (uae_u32 dst, uae_u32 bdata[2], ua
 extern uae_u16 REGPARAM3 mmu_get_word_unaligned(uaecptr addr, bool data, bool rmw) REGPARAM;
 extern uae_u32 REGPARAM3 mmu_get_long_unaligned(uaecptr addr, bool data, bool rmw) REGPARAM;
 
+extern uae_u32 REGPARAM3 mmu_get_ilong_unaligned(uaecptr addr) REGPARAM;
+
 extern uae_u8 REGPARAM3 mmu_get_byte_slow(uaecptr addr, bool super, bool data,
                                                                                  int size, bool rmw, struct mmu_atc_line *cl) REGPARAM;
 extern uae_u16 REGPARAM3 mmu_get_word_slow(uaecptr addr, bool super, bool data,
@@ -330,6 +332,11 @@ extern uae_u16 REGPARAM3 mmu_get_word_slow(uaecptr addr, bool super, bool data,
 extern uae_u32 REGPARAM3 mmu_get_long_slow(uaecptr addr, bool super, bool data,
                                                                                   int size, bool rmw, struct mmu_atc_line *cl) REGPARAM;
 
+extern uae_u16 REGPARAM3 mmu_get_iword_slow(uaecptr addr, bool super,
+                                                                                  int size, struct mmu_atc_line *cl) REGPARAM;
+extern uae_u32 REGPARAM3 mmu_get_ilong_slow(uaecptr addr, bool super,
+                                                                                  int size, struct mmu_atc_line *cl) REGPARAM;
+
 extern void REGPARAM3 mmu_put_word_unaligned(uaecptr addr, uae_u16 val, bool data, bool rmw) REGPARAM;
 extern void REGPARAM3 mmu_put_long_unaligned(uaecptr addr, uae_u32 val, bool data, bool rmw) REGPARAM;
 
@@ -394,33 +401,57 @@ static ALWAYS_INLINE uae_u32 mmu_get_long(uaecptr addr, bool data, int size, boo
 
        //                                       addr,super,data
        if ((!regs.mmu_enabled) || (mmu_match_ttr(addr,regs.s != 0,data,rmw)!=TTR_NO_MATCH))
-               return phys_get_long(addr);
+               return x_phys_get_long(addr);
        if (likely(mmu_lookup(addr, data, false, &cl)))
-               return phys_get_long(mmu_get_real_address(addr, cl));
+               return x_phys_get_long(mmu_get_real_address(addr, cl));
        return mmu_get_long_slow(addr, regs.s != 0, data, size, rmw, cl);
 }
 
+static ALWAYS_INLINE uae_u32 mmu_get_ilong(uaecptr addr, int size)
+{
+       struct mmu_atc_line *cl;
+
+       //                                       addr,super,data
+       if ((!regs.mmu_enabled) || (mmu_match_ttr(addr, regs.s != 0, false, false) != TTR_NO_MATCH))
+               return x_phys_get_ilong(addr);
+       if (likely(mmu_lookup(addr, false, false, &cl)))
+               return x_phys_get_ilong(mmu_get_real_address(addr, cl));
+       return mmu_get_ilong_slow(addr, regs.s != 0, size, cl);
+}
+
 static ALWAYS_INLINE uae_u16 mmu_get_word(uaecptr addr, bool data, int size, bool rmw)
 {
        struct mmu_atc_line *cl;
 
        //                                       addr,super,data
        if ((!regs.mmu_enabled) || (mmu_match_ttr(addr,regs.s != 0,data,rmw)!=TTR_NO_MATCH))
-               return phys_get_word(addr);
+               return x_phys_get_word(addr);
        if (likely(mmu_lookup(addr, data, false, &cl)))
-               return phys_get_word(mmu_get_real_address(addr, cl));
+               return x_phys_get_word(mmu_get_real_address(addr, cl));
        return mmu_get_word_slow(addr, regs.s != 0, data, size, rmw, cl);
 }
 
+static ALWAYS_INLINE uae_u16 mmu_get_iword(uaecptr addr, int size)
+{
+       struct mmu_atc_line *cl;
+
+       //                                       addr,super,data
+       if ((!regs.mmu_enabled) || (mmu_match_ttr(addr, regs.s != 0, false, false) != TTR_NO_MATCH))
+               return x_phys_get_iword(addr);
+       if (likely(mmu_lookup(addr, false, false, &cl)))
+               return x_phys_get_iword(mmu_get_real_address(addr, cl));
+       return mmu_get_iword_slow(addr, regs.s != 0, size, cl);
+}
+
 static ALWAYS_INLINE uae_u8 mmu_get_byte(uaecptr addr, bool data, int size, bool rmw)
 {
        struct mmu_atc_line *cl;
 
        //                                       addr,super,data
        if ((!regs.mmu_enabled) || (mmu_match_ttr(addr,regs.s != 0,data,rmw)!=TTR_NO_MATCH))
-               return phys_get_byte(addr);
+               return x_phys_get_byte(addr);
        if (likely(mmu_lookup(addr, data, false, &cl)))
-               return phys_get_byte(mmu_get_real_address(addr, cl));
+               return x_phys_get_byte(mmu_get_real_address(addr, cl));
        return mmu_get_byte_slow(addr, regs.s != 0, data, size, rmw, cl);
 }
 
@@ -430,11 +461,11 @@ static ALWAYS_INLINE void mmu_put_long(uaecptr addr, uae_u32 val, bool data, int
 
        //                                        addr,super,data
        if ((!regs.mmu_enabled) || mmu_match_ttr_write(addr,regs.s != 0,data,val,size,rmw)==TTR_OK_MATCH) {
-               phys_put_long(addr,val);
+               x_phys_put_long(addr,val);
                return;
        }
        if (likely(mmu_lookup(addr, data, true, &cl)))
-               phys_put_long(mmu_get_real_address(addr, cl), val);
+               x_phys_put_long(mmu_get_real_address(addr, cl), val);
        else
                mmu_put_long_slow(addr, val, regs.s != 0, data, size, rmw, cl);
 }
@@ -445,11 +476,11 @@ static ALWAYS_INLINE void mmu_put_word(uaecptr addr, uae_u16 val, bool data, int
 
        //                                        addr,super,data
        if ((!regs.mmu_enabled) || (mmu_match_ttr_write(addr,regs.s != 0,data,val,size,rmw)==TTR_OK_MATCH)) {
-               phys_put_word(addr,val);
+               x_phys_put_word(addr,val);
                return;
        }
        if (likely(mmu_lookup(addr, data, true, &cl)))
-               phys_put_word(mmu_get_real_address(addr, cl), val);
+               x_phys_put_word(mmu_get_real_address(addr, cl), val);
        else
                mmu_put_word_slow(addr, val, regs.s != 0, data, size, rmw, cl);
 }
@@ -460,11 +491,11 @@ static ALWAYS_INLINE void mmu_put_byte(uaecptr addr, uae_u8 val, bool data, int
 
        //                                        addr,super,data
        if ((!regs.mmu_enabled) || (mmu_match_ttr_write(addr,regs.s != 0,data,val,size,rmw)==TTR_OK_MATCH)) {
-               phys_put_byte(addr,val);
+               x_phys_put_byte(addr,val);
                return;
        }
        if (likely(mmu_lookup(addr, data, true, &cl)))
-               phys_put_byte(mmu_get_real_address(addr, cl), val);
+               x_phys_put_byte(mmu_get_real_address(addr, cl), val);
        else
                mmu_put_byte_slow(addr, val, regs.s != 0, data, size, rmw, cl);
 }
@@ -475,9 +506,9 @@ static ALWAYS_INLINE uae_u32 mmu_get_user_long(uaecptr addr, bool super, bool da
 
        //                                       addr,super,data
        if ((!regs.mmu_enabled) || (mmu_match_ttr(addr,super,data,false)!=TTR_NO_MATCH))
-               return phys_get_long(addr);
+               return x_phys_get_long(addr);
        if (likely(mmu_user_lookup(addr, super, data, write, &cl)))
-               return phys_get_long(mmu_get_real_address(addr, cl));
+               return x_phys_get_long(mmu_get_real_address(addr, cl));
        return mmu_get_long_slow(addr, super, data, size, false, cl);
 }
 
@@ -487,9 +518,9 @@ static ALWAYS_INLINE uae_u16 mmu_get_user_word(uaecptr addr, bool super, bool da
 
        //                                       addr,super,data
        if ((!regs.mmu_enabled) || (mmu_match_ttr(addr,super,data,false)!=TTR_NO_MATCH))
-               return phys_get_word(addr);
+               return x_phys_get_word(addr);
        if (likely(mmu_user_lookup(addr, super, data, write, &cl)))
-               return phys_get_word(mmu_get_real_address(addr, cl));
+               return x_phys_get_word(mmu_get_real_address(addr, cl));
        return mmu_get_word_slow(addr, super, data, size, false, cl);
 }
 
@@ -499,9 +530,9 @@ static ALWAYS_INLINE uae_u8 mmu_get_user_byte(uaecptr addr, bool super, bool dat
 
        //                                       addr,super,data
        if ((!regs.mmu_enabled) || (mmu_match_ttr(addr,super,data,false)!=TTR_NO_MATCH))
-               return phys_get_byte(addr);
+               return x_phys_get_byte(addr);
        if (likely(mmu_user_lookup(addr, super, data, write, &cl)))
-               return phys_get_byte(mmu_get_real_address(addr, cl));
+               return x_phys_get_byte(mmu_get_real_address(addr, cl));
        return mmu_get_byte_slow(addr, super, data, size, false, cl);
 }
 
@@ -511,11 +542,11 @@ static ALWAYS_INLINE void mmu_put_user_long(uaecptr addr, uae_u32 val, bool supe
 
        //                                        addr,super,data
        if ((!regs.mmu_enabled) || (mmu_match_ttr(addr,super,data,false)==TTR_OK_MATCH)) {
-               phys_put_long(addr,val);
+               x_phys_put_long(addr,val);
                return;
        }
        if (likely(mmu_user_lookup(addr, super, data, true, &cl)))
-               phys_put_long(mmu_get_real_address(addr, cl), val);
+               x_phys_put_long(mmu_get_real_address(addr, cl), val);
        else
                mmu_put_long_slow(addr, val, super, data, size, false, cl);
 }
@@ -526,11 +557,11 @@ static ALWAYS_INLINE void mmu_put_user_word(uaecptr addr, uae_u16 val, bool supe
 
        //                                        addr,super,data
        if ((!regs.mmu_enabled) || (mmu_match_ttr(addr,super,data,false)==TTR_OK_MATCH)) {
-               phys_put_word(addr,val);
+               x_phys_put_word(addr,val);
                return;
        }
        if (likely(mmu_user_lookup(addr, super, data, true, &cl)))
-               phys_put_word(mmu_get_real_address(addr, cl), val);
+               x_phys_put_word(mmu_get_real_address(addr, cl), val);
        else
                mmu_put_word_slow(addr, val, super, data, size, false, cl);
 }
@@ -541,11 +572,11 @@ static ALWAYS_INLINE void mmu_put_user_byte(uaecptr addr, uae_u8 val, bool super
 
        //                                        addr,super,data
        if ((!regs.mmu_enabled) || (mmu_match_ttr(addr,super,data,false)==TTR_OK_MATCH)) {
-               phys_put_byte(addr,val);
+               x_phys_put_byte(addr,val);
                return;
        }
        if (likely(mmu_user_lookup(addr, super, data, true, &cl)))
-               phys_put_byte(mmu_get_real_address(addr, cl), val);
+               x_phys_put_byte(mmu_get_real_address(addr, cl), val);
        else
                mmu_put_byte_slow(addr, val, super, data, size, false, cl);
 }
@@ -579,14 +610,12 @@ static ALWAYS_INLINE uae_u32 HWget_b(uaecptr addr)
 static ALWAYS_INLINE uae_u32 uae_mmu040_get_ilong(uaecptr addr)
 {
        if (unlikely(is_unaligned(addr, 4)))
-               return mmu_get_long_unaligned(addr, false, false);
-       return mmu_get_long(addr, false, sz_long, false);
+               return mmu_get_ilong_unaligned(addr);
+       return mmu_get_ilong(addr, sz_long);
 }
 static ALWAYS_INLINE uae_u16 uae_mmu040_get_iword(uaecptr addr)
 {
-       if (unlikely(is_unaligned(addr, 2)))
-               return mmu_get_word_unaligned(addr, false, false);
-       return mmu_get_word(addr, false, sz_word, false);
+       return mmu_get_iword(addr, sz_word);
 }
 static ALWAYS_INLINE uae_u16 uae_mmu040_get_ibyte(uaecptr addr)
 {
@@ -632,14 +661,12 @@ static ALWAYS_INLINE void uae_mmu040_put_long(uaecptr addr, uae_u32 val)
 static ALWAYS_INLINE uae_u32 uae_mmu060_get_ilong(uaecptr addr)
 {
        if (unlikely(is_unaligned(addr, 4)))
-               return mmu_get_long_unaligned(addr, false, false);
-       return mmu_get_long(addr, false, sz_long, false);
+               return mmu_get_ilong_unaligned(addr);
+       return mmu_get_ilong(addr, sz_long);
 }
 static ALWAYS_INLINE uae_u16 uae_mmu060_get_iword(uaecptr addr)
 {
-       if (unlikely(is_unaligned(addr, 2)))
-               return mmu_get_word_unaligned(addr, false, false);
-       return mmu_get_word(addr, false, sz_word, false);
+       return mmu_get_iword(addr, sz_word);
 }
 static ALWAYS_INLINE uae_u16 uae_mmu060_get_ibyte(uaecptr addr)
 {
index 7f3ebb8b7cb3db4c6e6dfcc01d47fe5bcc0fd20a..6eebf99e16c70d6c94be9ba9cec378b06426ba58 100644 (file)
@@ -85,6 +85,8 @@ void mmu030_put_byte(uaecptr addr, uae_u8  val, uae_u32 fc);
 uae_u32 mmu030_get_long(uaecptr addr, uae_u32 fc);
 uae_u16 mmu030_get_word(uaecptr addr, uae_u32 fc);
 uae_u8  mmu030_get_byte(uaecptr addr, uae_u32 fc);
+uae_u32 mmu030_get_ilong(uaecptr addr, uae_u32 fc);
+uae_u16 mmu030_get_iword(uaecptr addr, uae_u32 fc);
 
 uae_u32 uae_mmu030_get_lrmw(uaecptr addr, int size);
 void uae_mmu030_put_lrmw(uaecptr addr, uae_u32 val, int size);
@@ -93,6 +95,7 @@ uae_u32 mmu030_get_generic(uaecptr addr, uae_u32 fc, int size, int accesssize, i
 
 extern uae_u16 REGPARAM3 mmu030_get_word_unaligned(uaecptr addr, uae_u32 fc, int flags) REGPARAM;
 extern uae_u32 REGPARAM3 mmu030_get_long_unaligned(uaecptr addr, uae_u32 fc, int flags) REGPARAM;
+extern uae_u32 REGPARAM3 mmu030_get_ilong_unaligned(uaecptr addr, uae_u32 fc, int flags) REGPARAM;
 extern uae_u16 REGPARAM3 mmu030_get_lrmw_word_unaligned(uaecptr addr, uae_u32 fc, int flags) REGPARAM;
 extern uae_u32 REGPARAM3 mmu030_get_lrmw_long_unaligned(uaecptr addr, uae_u32 fc, int flags) REGPARAM;
 extern void REGPARAM3 mmu030_put_word_unaligned(uaecptr addr, uae_u16 val, uae_u32 fc, int flags) REGPARAM;
@@ -103,16 +106,13 @@ static ALWAYS_INLINE uae_u32 uae_mmu030_get_ilong(uaecptr addr)
     uae_u32 fc = (regs.s ? 4 : 0) | 2;
 
        if (unlikely(is_unaligned(addr, 4)))
-               return mmu030_get_long_unaligned(addr, fc, 0);
-       return mmu030_get_long(addr, fc);
+               return mmu030_get_ilong_unaligned(addr, fc, 0);
+       return mmu030_get_ilong(addr, fc);
 }
 static ALWAYS_INLINE uae_u16 uae_mmu030_get_iword(uaecptr addr)
 {
     uae_u32 fc = (regs.s ? 4 : 0) | 2;
-
-       if (unlikely(is_unaligned(addr, 2)))
-               return mmu030_get_word_unaligned(addr, fc, 0);
-       return mmu030_get_word(addr, fc);
+       return mmu030_get_iword(addr, fc);
 }
 static ALWAYS_INLINE uae_u16 uae_mmu030_get_ibyte(uaecptr addr)
 {
index 73f38d015958a4f9fd0b46105fd175a4ec732974..009d0a8203579526a08c9012874623df01d00a59 100644 (file)
@@ -39,7 +39,6 @@ struct hardfiledata {
     TCHAR vendor_id[8 + 1];
     TCHAR product_id[16 + 1];
     TCHAR product_rev[4 + 1];
-    TCHAR device_name[256];
     /* geometry from possible RDSK block */
     int rdbcylinders;
     int rdbsectors;
@@ -99,7 +98,7 @@ struct hd_hardfiledata {
 #define HD_CONTROLLER_TYPE_SCSI_A3000 7
 #define HD_CONTROLLER_TYPE_SCSI_A4000T 8
 #define HD_CONTROLLER_TYPE_SCSI_CDTV 9
-#define HD_CONTROLLER_TYPE_SCSI_WARPENGINE 10
+#define HD_CONTROLLER_TYPE_SCSI_CPUBOARD 10
 #define HD_CONTROLLER_TYPE_PCMCIA_SRAM 11
 #define HD_CONTROLLER_TYPE_PCMCIA_IDE 12
 
diff --git a/include/flashrom.h b/include/flashrom.h
new file mode 100644 (file)
index 0000000..64609f2
--- /dev/null
@@ -0,0 +1,7 @@
+
+void *flash_new(uae_u8 *rom, int flashsize, int allocsize, struct zfile *zf);
+void flash_free(void *fdv);
+
+bool flash_write(void *fdv, uaecptr addr, uae_u8 v);
+uae_u32 flash_read(void *fdv, uaecptr addr);
+bool flash_active(void *fdv, uaecptr addr);
index fe7a03428c9344fd7c93703c263a049687733037..12df295fe1be700d74d6a093b4cab87c9535c702 100644 (file)
@@ -55,7 +55,7 @@ struct gui_info
     uae_s8 hd;                                 /* harddrive */
     uae_s8 cd;                                 /* CD */
        uae_s8 md;                                      /* CD32 or CDTV internal storage */
-    bool cpu_halted;
+    int cpu_halted;
        int fps, idle;
        int fps_color;
     int sndbuf, sndbuf_status;
index 50241798dfd0f14fa94cc11b7a3b066798bd888d..f3effca4885c4cdfd6ce15ae1f1085e39a4f074f 100644 (file)
@@ -147,4 +147,13 @@ static ALWAYS_INLINE uae_u32 phys_get_byte(uaecptr addr)
     return byteget (addr);
 }
 
+extern uae_u32(*x_phys_get_iword)(uaecptr);
+extern uae_u32(*x_phys_get_ilong)(uaecptr);
+extern uae_u32(*x_phys_get_byte)(uaecptr);
+extern uae_u32(*x_phys_get_word)(uaecptr);
+extern uae_u32(*x_phys_get_long)(uaecptr);
+extern void(*x_phys_put_byte)(uaecptr, uae_u32);
+extern void(*x_phys_put_word)(uaecptr, uae_u32);
+extern void(*x_phys_put_long)(uaecptr, uae_u32);
+
 #endif
index 18b05589f02cfc8ff48c1691e364a2937db7de13..c056647507f41b115799d96bcb8341b58bda7019 100644 (file)
@@ -1,14 +1,23 @@
 
-void ncr_io_bput_a4000t(uaecptr, uae_u32);
-uae_u32 ncr_io_bget_a4000t(uaecptr);
+void ncr710_io_bput_a4000t(uaecptr, uae_u32);
+uae_u32 ncr710_io_bget_a4000t(uaecptr);
+
+extern addrbank ncr_bank_cyberstorm;
+extern addrbank ncr_bank_blizzardppc;
 
 extern void ncr_init(void);
-extern addrbank *ncr_a4091_autoconfig_init(int devnum);
-extern addrbank *ncr_warpengine_autoconfig_init(void);
 extern void ncr_free(void);
 extern void ncr_reset(void);
 
-extern int a4000t_add_scsi_unit (int ch, struct uaedev_config_info *ci);
-extern int warpengine_add_scsi_unit (int ch, struct uaedev_config_info *ci);
-extern int a4091_add_scsi_unit (int ch, struct uaedev_config_info *ci, int devnum);
+extern void ncr710_init(void);
+extern addrbank *ncr710_a4091_autoconfig_init(int devnum);
+extern addrbank *ncr710_warpengine_autoconfig_init(void);
+extern void ncr710_free(void);
+extern void ncr710_reset(void);
+extern void ncr_rethink(void);
 
+extern int a4000t_add_scsi_unit (int ch, struct uaedev_config_info *ci);
+extern int warpengine_add_scsi_unit(int ch, struct uaedev_config_info *ci);
+extern int cyberstorm_add_scsi_unit(int ch, struct uaedev_config_info *ci);
+extern int blizzardppc_add_scsi_unit(int ch, struct uaedev_config_info *ci);
+extern int a4091_add_scsi_unit(int ch, struct uaedev_config_info *ci, int devnum);
index ccb61dedff9197680896998b289c4bb260196d49..8fd416fde6b2d4576b439a2a706239c81c0cfd1a 100644 (file)
 #include "machdep/m68k.h"
 #include "events.h"
 
+#ifdef WITH_SOFTFLOAT
+#include <softfloat.h>
+#endif
+
 #ifndef SET_CFLG
 
 #define SET_CFLG(x) (CFLG() = (x))
@@ -72,7 +76,7 @@ typedef uae_u8 flagtype;
 
 #ifdef FPUEMU
 
-#if USE_LONG_DOUBLE
+#ifdef USE_LONG_DOUBLE
 typedef long double fptype;
 #define LDPTR tbyte ptr
 #else
@@ -105,16 +109,15 @@ struct cache030
        uae_u32 tag;
 };
 
-#if 0
 #define CACHESETS040 64
 #define CACHELINES040 4
 struct cache040
 {
        uae_u32 data[CACHELINES040][4];
+       bool dirty[CACHELINES040][4];
        bool valid[CACHELINES040];
        uae_u32 tag[CACHELINES040];
 };
-#endif
 
 struct mmufixup
 {
@@ -126,10 +129,8 @@ extern struct mmufixup mmufixup[2];
 typedef struct
 {
        fptype fp;
-#ifdef USE_SOFT_LONG_DOUBLE
-       bool fpx;
-       uae_u32 fpm;
-       uae_u64 fpe;
+#ifdef WITH_SOFTFLOAT
+       floatx80 fpx;
 #endif
 } fpdata;
 
@@ -174,6 +175,7 @@ struct regstruct
        fpdata exp_src1, exp_src2;
        uae_u32 exp_pack[3];
        uae_u16 exp_opcode, exp_extra, exp_type;
+       uae_u16 exp_size;
        bool fp_exception;
 #endif
 #ifndef CPUEMU_68000_ONLY
@@ -204,6 +206,7 @@ struct regstruct
        bool ce020memcycle_data;
        int ce020_tail;
        frame_time_t ce020_tail_cycles;
+       int memory_waitstate_cycles;
 };
 
 extern struct regstruct regs;
@@ -439,6 +442,25 @@ extern uae_u32 (*x_cp_next_ilong)(void);
 
 extern uae_u32 (REGPARAM3 *x_cp_get_disp_ea_020)(uae_u32 base, int idx) REGPARAM;
 
+extern void write_dcache030(uaecptr, uae_u32, int);
+extern uae_u32 read_dcache030(uaecptr, int);
+extern uae_u32 get_word_icache030(uaecptr addr);
+extern uae_u32 get_long_icache030(uaecptr addr);
+
+uae_u32 fill_icache040(uae_u32 addr);
+extern void put_long_cache_040(uaecptr, uae_u32);
+extern void put_word_cache_040(uaecptr, uae_u32);
+extern void put_byte_cache_040(uaecptr, uae_u32);
+extern uae_u32 get_ilong_cache_040(int);
+extern uae_u32 get_iword_cache_040(int);
+extern uae_u32 get_long_cache_040(uaecptr);
+extern uae_u32 get_word_cache_040(uaecptr);
+extern uae_u32 get_byte_cache_040(uaecptr);
+extern uae_u32 next_iword_cache040(void);
+extern uae_u32 next_ilong_cache040(void);
+extern uae_u32 get_word_icache040(uaecptr addr);
+extern uae_u32 get_long_icache040(uaecptr addr);
+
 extern void (*x_do_cycles)(unsigned long);
 extern void (*x_do_cycles_pre)(unsigned long);
 extern void (*x_do_cycles_post)(unsigned long, uae_u32);
@@ -446,6 +468,7 @@ extern void (*x_do_cycles_post)(unsigned long, uae_u32);
 extern uae_u32 REGPARAM3 x_get_disp_ea_020 (uae_u32 base, int idx) REGPARAM;
 extern uae_u32 REGPARAM3 x_get_disp_ea_ce020 (uae_u32 base, int idx) REGPARAM;
 extern uae_u32 REGPARAM3 x_get_disp_ea_ce030 (uae_u32 base, int idx) REGPARAM;
+extern uae_u32 REGPARAM3 x_get_disp_ea_040(uae_u32 base, int idx) REGPARAM;
 extern uae_u32 REGPARAM3 x_get_bitfield (uae_u32 src, uae_u32 bdata[2], uae_s32 offset, int width) REGPARAM;
 extern void REGPARAM3 x_put_bitfield (uae_u32 dst, uae_u32 bdata[2], uae_u32 val, uae_s32 offset, int width) REGPARAM;
 
@@ -511,6 +534,7 @@ extern void exception3i (uae_u32 opcode, uaecptr addr);
 extern void exception3b (uae_u32 opcode, uaecptr addr, bool w, bool i, uaecptr pc);
 extern void exception2 (uaecptr addr, bool read, int size, uae_u32 fc);
 extern void exception2_fake (uaecptr addr);
+extern void m68k_reset (void);
 extern void cpureset (void);
 extern void cpu_halt (int id);
 
@@ -522,15 +546,15 @@ extern void fill_prefetch_030 (void);
 
 /* 68060 */
 extern const struct cputbl op_smalltbl_0_ff[];
-extern const struct cputbl op_smalltbl_22_ff[]; // CE
+extern const struct cputbl op_smalltbl_23_ff[]; // CE
 extern const struct cputbl op_smalltbl_33_ff[]; // MMU
 /* 68040 */
 extern const struct cputbl op_smalltbl_1_ff[];
-extern const struct cputbl op_smalltbl_23_ff[]; // CE
+extern const struct cputbl op_smalltbl_24_ff[]; // CE
 extern const struct cputbl op_smalltbl_31_ff[]; // MMU
 /* 68030 */
 extern const struct cputbl op_smalltbl_2_ff[];
-extern const struct cputbl op_smalltbl_24_ff[]; // CE
+extern const struct cputbl op_smalltbl_22_ff[]; // CE
 extern const struct cputbl op_smalltbl_32_ff[]; // MMU
 /* 68020 */
 extern const struct cputbl op_smalltbl_3_ff[];
index 27691cfe9d5f60c67f1eb43fbdb7606dd19bfa78..1c5306b31cb8dc47cf594cd67f5e5c5787a2d8b2 100644 (file)
@@ -329,6 +329,7 @@ struct uae_prefs {
        bool comp_midopt;
        bool comp_lowopt;
        bool fpu_strict;
+       bool fpu_softfloat;
 
        bool comp_hardflush;
        bool comp_constjump;
index d4baf31ee8770d6727c477a7bdb08f8784ecae5a..6750279cf5510db14fb66b0bc86675dad400f5c7 100644 (file)
@@ -715,60 +715,60 @@ genmovemel (uae_u16 opcode)
     comprintf ("\tint offset=0;\n");
     genamode (table68k[opcode].dmode, "dstreg", table68k[opcode].size, "src", 2, 1);
        if (table68k[opcode].size == sz_long)
-           comprintf("\tif (!currprefs.comptrustlong && !special_mem) {\n");
+           comprintf("\tif (1 && !special_mem) {\n");
        else
-           comprintf("\tif (!currprefs.comptrustword && !special_mem) {\n");
+           comprintf("\tif (1 && !special_mem) {\n");
 
     /* Fast but unsafe...  */
-    comprintf("\tget_n_addr(srca,native,scratchie);\n");
+    comprintf("\t\tget_n_addr(srca,native,scratchie);\n");
 
 
-    comprintf("\tfor (i=0;i<16;i++) {\n"
-             "\t\tif ((mask>>i)&1) {\n");
+    comprintf("\t\tfor (i=0;i<16;i++) {\n"
+             "\t\t\tif ((mask>>i)&1) {\n");
     switch(table68k[opcode].size) {
      case sz_long:
-       comprintf("\t\t\tmov_l_rR(i,native,offset);\n"
-                 "\t\t\tgen_bswap_32(i);\n"
-                 "\t\t\toffset+=4;\n");
+       comprintf("\t\t\t\tmov_l_rR(i,native,offset);\n"
+                 "\t\t\t\tgen_bswap_32(i);\n"
+                 "\t\t\t\toffset+=4;\n");
        break;
      case sz_word:
-       comprintf("\t\t\tmov_w_rR(i,native,offset);\n"
-                 "\t\t\tgen_bswap_16(i);\n"
-                 "\t\t\tsign_extend_16_rr(i,i);\n"
-                 "\t\t\toffset+=2;\n");
+       comprintf("\t\t\t\tmov_w_rR(i,native,offset);\n"
+                 "\t\t\t\tgen_bswap_16(i);\n"
+                 "\t\t\t\tsign_extend_16_rr(i,i);\n"
+                 "\t\t\t\toffset+=2;\n");
        break;
      default: abort();
     }
-    comprintf("\t\t}\n"
-             "\t}");
+    comprintf("\t\t\t}\n"
+             "\t\t}\n");
     if (table68k[opcode].dmode == Aipi) {
-       comprintf("\t\t\tlea_l_brr(8+dstreg,srca,offset);\n");
+       comprintf("\t\tlea_l_brr(8+dstreg,srca,offset);\n");
     }
     /* End fast but unsafe.   */
 
     comprintf("\t} else {\n");
 
-    comprintf ("\tint tmp=scratchie++;\n");
+    comprintf ("\t\tint tmp=scratchie++;\n");
 
-    comprintf("\tmov_l_rr(tmp,srca);\n");
-    comprintf("\tfor (i=0;i<16;i++) {\n"
-             "\t\tif ((mask>>i)&1) {\n");
+    comprintf("\t\tmov_l_rr(tmp,srca);\n");
+    comprintf("\t\tfor (i=0;i<16;i++) {\n"
+             "\t\t\tif ((mask>>i)&1) {\n");
     switch(table68k[opcode].size) {
     case sz_long:
-       comprintf("\t\t\treadlong(tmp,i,scratchie);\n"
-                 "\t\t\tadd_l_ri(tmp,4);\n");
+       comprintf("\t\t\t\treadlong(tmp,i,scratchie);\n"
+                 "\t\t\t\tadd_l_ri(tmp,4);\n");
        break;
     case sz_word:
-       comprintf("\t\t\treadword(tmp,i,scratchie);\n"
-                 "\t\t\tadd_l_ri(tmp,2);\n");
+       comprintf("\t\t\t\treadword(tmp,i,scratchie);\n"
+                 "\t\t\t\tadd_l_ri(tmp,2);\n");
        break;
     default: abort();
     }
 
-    comprintf("\t\t}\n"
-             "\t}");
+    comprintf("\t\t\t}\n"
+             "\t\t}\n");
     if (table68k[opcode].dmode == Aipi) {
-       comprintf("\t\t\tmov_l_rr(8+dstreg,tmp);\n");
+       comprintf("\t\tmov_l_rr(8+dstreg,tmp);\n");
     }
     comprintf("\t}\n");
 
@@ -791,9 +791,9 @@ genmovemle (uae_u16 opcode)
        act of cleverness means that movmle must pay attention to special_mem,
        or Genetic Species is a rather boring-looking game ;-) */
        if (table68k[opcode].size == sz_long)
-           comprintf("\tif (!currprefs.comptrustlong && !special_mem) {\n");
+           comprintf("\tif (1 && !special_mem) {\n");
        else
-           comprintf("\tif (!currprefs.comptrustword && !special_mem) {\n");
+           comprintf("\tif (1 && !special_mem) {\n");
     comprintf("\tget_n_addr(srca,native,scratchie);\n");
 
     if (table68k[opcode].dmode!=Apdi) {
index 7ac6f51c8b81dc4a9da87cc28c3e466ec3a8e078..12b0d6a9e860b9fd041ffb29f1d6c122cd2379c8 100644 (file)
--- a/main.cpp
+++ b/main.cpp
@@ -263,11 +263,6 @@ void fixup_cpu (struct uae_prefs *p)
        if (p->cpu_model >= 68040 && p->cachesize && p->cpu_compatible)
                p->cpu_compatible = false;
 
-       if (p->cpu_model >= 68040 && p->cpu_cycle_exact) {
-               p->cpu_cycle_exact = 0;
-               error_log (_T("68040/060 cycle-exact is not supported."));
-       }
-
        if ((p->cpu_model < 68030 || p->cachesize) && p->mmu_model) {
                error_log (_T("MMU emulation requires 68030/040/060 and it is not JIT compatible."));
                p->mmu_model = 0;
@@ -282,8 +277,10 @@ void fixup_cpu (struct uae_prefs *p)
                p->fpu_no_unimplemented = p->int_no_unimplemented = false;
        }
 
-       if (p->cpu_cycle_exact && p->m68k_speed < 0)
+#if 0
+       if (p->cpu_cycle_exact && p->m68k_speed < 0 && currprefs.cpu_model <= 68020)
                p->m68k_speed = 0;
+#endif
 
        if (p->immediate_blits && p->blitter_cycle_exact) {
                error_log (_T("Cycle-exact and immediate blitter can't be enabled simultaneously.\n"));
@@ -613,10 +610,12 @@ void fixup_prefs (struct uae_prefs *p)
                        error_log (_T("Cycle-exact and JIT can't be active simultaneously."));
                        p->cachesize = 0;
                }
+#if 0
                if (p->m68k_speed) {
                        error_log (_T("Adjustable CPU speed is not available in cycle-exact mode."));
                        p->m68k_speed = 0;
                }
+#endif
        }
 #endif
        if (p->maprom && !p->address_space_24)
@@ -972,7 +971,8 @@ void do_leave_program (void)
        a3000scsi_free ();
 #endif
 #ifdef NCR
-       ncr_free ();
+       ncr710_free();
+       ncr_free();
 #endif
 #ifdef CD32
        akiko_free ();
@@ -1052,6 +1052,10 @@ void virtualdevice_init (void)
 #ifdef WITH_TABLETLIBRARY
        tabletlib_install ();
 #endif
+#ifdef NCR
+       ncr710_init();
+       ncr_init();
+#endif
 }
 
 static int real_main2 (int argc, TCHAR **argv)
index 94367d1af31d528cbcf32fcde88b4542d16f68c4..62637a14557e08d94faafb0c1fdd70e3b5ef0cb7 100644 (file)
@@ -45,6 +45,8 @@ int special_mem;
 #endif
 static int mem_hardreset;
 
+#define FLASHEMU 0
+
 static bool isdirectjit (void)
 {
        return currprefs.cachesize && !currprefs.comptrustbyte;
@@ -216,6 +218,10 @@ static bool gary_nonrange(uaecptr addr)
 
 void dummy_put (uaecptr addr, int size, uae_u32 val)
 {
+#if FLASHEMU
+       if (addr >= 0xf00000 && addr < 0xf80000 && size < 2)
+               flash_write(addr, val);
+#endif
        if (gary_nonrange(addr) || (size > 1 && gary_nonrange(addr + size - 1))) {
                if (gary_timeout)
                        gary_wait (addr, size, true);
@@ -228,15 +234,11 @@ uae_u32 dummy_get (uaecptr addr, int size, bool inst)
 {
        uae_u32 v = NONEXISTINGDATA;
 
-#if 0
-       if (addr == 0xf00000 && size < 2) {
-               return 0xff;
-       }
-       if (addr >= 0xf60000 && addr < 0xf80000 && size < 2) {
-               //activate_debugger();
-               if (addr == 0xf60020)
-                       return 0x8;
-               return v;
+#if FLASHEMU
+       if (addr >= 0xf00000 && addr < 0xf80000 && size < 2) {
+               if (addr < 0xf60000)
+                       return flash_read(addr);
+               return 8;
        }
 #endif
 
@@ -977,7 +979,6 @@ uae_u8 *REGPARAM2 default_xlate (uaecptr a)
 #if defined(ENFORCER)
                        enforcer_disable ();
 #endif
-
                        if (be_cnt < 3) {
                                int i, j;
                                uaecptr a2 = a - 32;
index 4256fb9bfd64000d43f34a7f9648738588c90794..14fced0770a827a4011ec25b1ae575943c60307d 100644 (file)
@@ -24,6 +24,7 @@
 #include "filesys.h"
 #include "zfile.h"
 #include "blkdev.h"
+#include "cpuboard.h"
 #include "qemuvga\qemuuaeglue.h"
 #include "qemuvga\queue.h"
 #include "qemuvga\scsi\scsi.h"
 #define WARP_ENGINE_IO_OFFSET 0x40000
 #define WARP_ENGINE_IO_END 0x80000
 
+#define CYBERSTORM_SCSI_RAM_OFFSET 0x1000
+#define CYBERSTORM_SCSI_RAM_SIZE 0x2000
+#define CYBERSTORM_SCSI_RAM_MASK 0x1fff
+
 struct ncr_state
 {
+       bool newncr;
        TCHAR *name;
        DeviceState devobject;
        SCSIDevice *scsid[8];
        SCSIBus scsibus;
        uae_u32 board_mask;
        uae_u8 *rom;
+       int ramsize;
        uae_u8 acmemory[128];
        uae_u32 expamem_hi;
        uae_u32 expamem_lo;
@@ -61,6 +68,8 @@ struct ncr_state
        int rom_start, rom_end, rom_offset;
        int io_start, io_end;
        addrbank *bank;
+       bool irq;
+       void (*irq_func)(int);
 };
 
 static struct ncr_state ncr_a4091;
@@ -68,12 +77,16 @@ static struct ncr_state ncr_a4091_2;
 static struct ncr_state ncr_a4000t;
 static struct ncr_state ncr_we;
 
+static struct ncr_state ncr_cs;
+static struct ncr_state ncr_bppc;
+
 static struct ncr_state *ncrs[] =
 {
        &ncr_a4091,
        &ncr_a4091_2,
        &ncr_a4000t,
        &ncr_we,
+       &ncr_bppc,
        NULL
 };
 
@@ -83,24 +96,47 @@ static struct ncr_state *ncra4091[] =
        &ncr_a4091_2
 };
 
+extern void cyberstorm_irq(int);
+extern void blizzardppc_irq(int);
+
+static void set_irq2(int level)
+{
+       if (level)
+               INTREQ(0x8000 | 0x0008);
+}
+
+void ncr_rethink(void)
+{
+       for (int i = 0; ncrs[i]; i++) {
+               if (ncrs[i]->irq)
+                       INTREQ(0x8000 | 0x0008);
+       }
+       if (ncr_cs.irq)
+               cyberstorm_irq(1);
+}
+
+/* 720+ */
+
 void pci_set_irq(PCIDevice *pci_dev, int level)
 {
-       if (!level)
-               return;
-       INTREQ (0x8000 | 0x0008);
+       struct ncr_state *ncr = (struct ncr_state*)pci_dev;
+       ncr->irq = level != 0;
+       ncr->irq_func(ncr->irq);
 }
 
 void scsi_req_continue(SCSIRequest *req)
 {
        struct scsi_data *sd = (struct scsi_data*)req->dev->handle;
        if (sd->data_len < 0) {
-               lsi_command_complete (req, sd->status, 0);
-       } else if (sd->data_len) {
-               lsi_transfer_data (req, sd->data_len);
-       } else {
+               lsi_command_complete(req, sd->status, 0);
+       }
+       else if (sd->data_len) {
+               lsi_transfer_data(req, sd->data_len);
+       }
+       else {
                if (sd->direction > 0)
                        scsi_emulate_cmd(sd);
-               lsi_command_complete (req, sd->status, 0);
+               lsi_command_complete(req, sd->status, 0);
        }
 }
 SCSIRequest *scsi_req_new(SCSIDevice *d, uint32_t tag, uint32_t lun, uint8_t *buf, int len, void *hba_private)
@@ -113,8 +149,8 @@ SCSIRequest *scsi_req_new(SCSIDevice *d, uint32_t tag, uint32_t lun, uint8_t *bu
        req->hba_private = hba_private;
        req->bus = &ncr->scsibus;
        req->bus->qbus.parent = &ncr->devobject;
-       
-       memcpy (sd->cmd, buf, len);
+
+       memcpy(sd->cmd, buf, len);
        sd->cmd_len = len;
        return req;
 }
@@ -123,10 +159,10 @@ int32_t scsi_req_enqueue(SCSIRequest *req)
        struct scsi_data *sd = (struct scsi_data*)req->dev->handle;
 
        sd->data_len = 0;
-       scsi_start_transfer (sd);
-       scsi_emulate_analyze (sd);
+       scsi_start_transfer(sd);
+       scsi_emulate_analyze(sd);
        //write_log (_T("%02x.%02x.%02x.%02x.%02x.%02x\n"), sd->cmd[0], sd->cmd[1], sd->cmd[2], sd->cmd[3], sd->cmd[4], sd->cmd[5]);
-       
+
        if (sd->direction < 0)
                scsi_emulate_cmd(sd);
        if (sd->direction == 0)
@@ -135,7 +171,7 @@ int32_t scsi_req_enqueue(SCSIRequest *req)
 }
 void scsi_req_unref(SCSIRequest *req)
 {
-       xfree (req);
+       xfree(req);
 }
 uint8_t *scsi_req_get_buf(SCSIRequest *req)
 {
@@ -152,17 +188,101 @@ SCSIDevice *scsi_device_find(SCSIBus *bus, int channel, int target, int lun)
 }
 void scsi_req_cancel(SCSIRequest *req)
 {
-       write_log (_T("scsi_req_cancel\n"));
+       write_log(_T("scsi_req_cancel\n"));
 }
 
-static uae_u8 read_rombyte (struct ncr_state *ncr, uaecptr addr)
+int pci_dma_rw(PCIDevice *dev, dma_addr_t addr, void *buf, dma_addr_t len, DMADirection dir)
 {
-       uae_u8 v = ncr->rom[addr];
-       //write_log (_T("%08X = %02X PC=%08X\n"), addr, v, M68K_GETPC);
-       return v;
+       int i = 0;
+       uae_u8 *p = (uae_u8*)buf;
+       while (len > 0) {
+               if (!dir) {
+                       *p = get_byte(addr);
+               }
+               else {
+                       put_byte(addr, *p);
+               }
+               p++;
+               len--;
+               addr++;
+       }
+       return 0;
 }
+/* 710 */
 
-int pci_dma_rw(PCIDevice *dev, dma_addr_t addr, void *buf, dma_addr_t len, DMADirection dir)
+void pci710_set_irq(PCIDevice *pci_dev, int level)
+{
+       struct ncr_state *ncr = (struct ncr_state*)pci_dev;
+       ncr->irq = level != 0;
+       ncr->irq_func(ncr->irq);
+}
+
+void scsi710_req_continue(SCSIRequest *req)
+{
+       struct scsi_data *sd = (struct scsi_data*)req->dev->handle;
+       if (sd->data_len < 0) {
+               lsi710_command_complete(req, sd->status, 0);
+       } else if (sd->data_len) {
+               lsi710_transfer_data(req, sd->data_len);
+       } else {
+               if (sd->direction > 0)
+                       scsi_emulate_cmd(sd);
+               lsi710_command_complete(req, sd->status, 0);
+       }
+}
+SCSIRequest *scsi710_req_new(SCSIDevice *d, uint32_t tag, uint32_t lun, uint8_t *buf, int len, void *hba_private)
+{
+       SCSIRequest *req = xcalloc(SCSIRequest, 1);
+       struct scsi_data *sd = (struct scsi_data*)d->handle;
+       struct ncr_state *ncr = (struct ncr_state*)sd->privdata;
+
+       req->dev = d;
+       req->hba_private = hba_private;
+       req->bus = &ncr->scsibus;
+       req->bus->qbus.parent = &ncr->devobject;
+       
+       memcpy (sd->cmd, buf, len);
+       sd->cmd_len = len;
+       return req;
+}
+int32_t scsi710_req_enqueue(SCSIRequest *req)
+{
+       struct scsi_data *sd = (struct scsi_data*)req->dev->handle;
+
+       sd->data_len = 0;
+       scsi_start_transfer (sd);
+       scsi_emulate_analyze (sd);
+       //write_log (_T("%02x.%02x.%02x.%02x.%02x.%02x\n"), sd->cmd[0], sd->cmd[1], sd->cmd[2], sd->cmd[3], sd->cmd[4], sd->cmd[5]);
+       
+       if (sd->direction < 0)
+               scsi_emulate_cmd(sd);
+       if (sd->direction == 0)
+               return 1;
+       return -sd->direction;
+}
+void scsi710_req_unref(SCSIRequest *req)
+{
+       xfree (req);
+}
+uint8_t *scsi710_req_get_buf(SCSIRequest *req)
+{
+       struct scsi_data *sd = (struct scsi_data*)req->dev->handle;
+       sd->data_len = 0;
+       return sd->buffer;
+}
+SCSIDevice *scsi710_device_find(SCSIBus *bus, int channel, int target, int lun)
+{
+       struct ncr_state *ncr = (struct ncr_state*)bus->privdata;
+       if (lun != 0 || target < 0 || target >= 8)
+               return NULL;
+       return ncr->scsid[target];
+}
+void scsi710_req_cancel(SCSIRequest *req)
+{
+       write_log (_T("scsi_req_cancel\n"));
+}
+
+int pci710_dma_rw(PCIDevice *dev, dma_addr_t addr, void *buf, dma_addr_t len, DMADirection dir)
 {
        int i = 0;
        uae_u8 *p = (uae_u8*)buf;
@@ -179,30 +299,56 @@ int pci_dma_rw(PCIDevice *dev, dma_addr_t addr, void *buf, dma_addr_t len, DMADi
        return 0;
 }
 
-static uaecptr beswap (uaecptr addr)
+static uae_u8 read_rombyte(struct ncr_state *ncr, uaecptr addr)
+{
+       uae_u8 v = ncr->rom[addr];
+       //write_log (_T("%08X = %02X PC=%08X\n"), addr, v, M68K_GETPC);
+       return v;
+}
+
+static uaecptr beswap(uaecptr addr)
 {
        return (addr & ~3) | (3 - (addr & 3));
 }
 
-void ncr_io_bput (struct ncr_state *ncr, uaecptr addr, uae_u32 val)
+void ncr_io_bput(struct ncr_state *ncr, uaecptr addr, uae_u32 val)
 {
+       if (addr >= CYBERSTORM_SCSI_RAM_OFFSET && ncr->ramsize) {
+               cyberstorm_scsi_ram_put(addr, val);
+               return;
+       }
        addr &= IO_MASK;
-       lsi_mmio_write (ncr->devobject.lsistate, beswap (addr), val, 1);
+       lsi_mmio_write(ncr->devobject.lsistate, beswap(addr), val, 1);
+}
+void ncr710_io_bput(struct ncr_state *ncr, uaecptr addr, uae_u32 val)
+{
+       addr &= IO_MASK;
+       lsi710_mmio_write(ncr->devobject.lsistate, beswap(addr), val, 1);
 }
 
 static void ncr_bput2 (struct ncr_state *ncr, uaecptr addr, uae_u32 val)
 {
        uae_u32 v = val;
        addr &= ncr->board_mask;
-       if (addr < ncr->io_start || addr >= ncr->io_end)
+       if (ncr->io_end && (addr < ncr->io_start || addr >= ncr->io_end))
                return;
-       ncr_io_bput (ncr, addr, val);
+       if (ncr->newncr)
+               ncr_io_bput(ncr, addr, val);
+       else
+               ncr710_io_bput(ncr, addr, val);
 }
 
-uae_u32 ncr_io_bget (struct ncr_state *ncr, uaecptr addr)
+uae_u32 ncr_io_bget(struct ncr_state *ncr, uaecptr addr)
+{
+       if (addr >= CYBERSTORM_SCSI_RAM_OFFSET && ncr->ramsize)
+               return cyberstorm_scsi_ram_get(addr);
+       addr &= IO_MASK;
+       return lsi_mmio_read(ncr->devobject.lsistate, beswap(addr), 1);
+}
+uae_u32 ncr710_io_bget(struct ncr_state *ncr, uaecptr addr)
 {
        addr &= IO_MASK;
-       return lsi_mmio_read (ncr->devobject.lsistate, beswap (addr), 1);
+       return lsi710_mmio_read(ncr->devobject.lsistate, beswap(addr), 1);
 }
 
 static uae_u32 ncr_bget2 (struct ncr_state *ncr, uaecptr addr)
@@ -214,10 +360,12 @@ static uae_u32 ncr_bget2 (struct ncr_state *ncr, uaecptr addr)
                return read_rombyte (ncr, addr - ncr->rom_offset);
        if (addr == A4091_DIP_OFFSET)
                return 0xff;
-       if (addr < ncr->io_start || addr >= ncr->io_end)
+       if (ncr->io_end && (addr < ncr->io_start || addr >= ncr->io_end))
                return v;
-       addr &= IO_MASK;
-       return ncr_io_bget (ncr, addr);
+       if (ncr->newncr)
+               return ncr_io_bget(ncr, addr);
+       else
+               return ncr710_io_bget(ncr, addr);
 }
 
 static uae_u32 REGPARAM2 ncr_lget (struct ncr_state *ncr, uaecptr addr)
@@ -243,6 +391,8 @@ static uae_u32 REGPARAM2 ncr_wget (struct ncr_state *ncr, uaecptr addr)
 #ifdef JIT
        special_mem |= S_READ;
 #endif
+       if (ncr->newncr)
+               return 0;
        addr &= ncr->board_mask;
        v = (ncr_bget2 (ncr, addr) << 8) | ncr_bget2 (ncr, addr + 1);
        return v;
@@ -328,7 +478,9 @@ static void REGPARAM2 ncr_wput (struct ncr_state *ncr, uaecptr addr, uae_u32 w)
                }
                return;
        }
-       ncr_bput2 (ncr, addr, w >> 8);
+       if (ncr->newncr)
+               return;
+       ncr_bput2(ncr, addr, w >> 8);
        ncr_bput2 (ncr, addr + 1, w);
 }
 
@@ -356,13 +508,13 @@ static void REGPARAM2 ncr_bput (struct ncr_state *ncr, uaecptr addr, uae_u32 b)
        ncr_bput2 (ncr, addr, b);
 }
 
-void ncr_io_bput_a4000t(uaecptr addr, uae_u32 v)
+void ncr710_io_bput_a4000t(uaecptr addr, uae_u32 v)
 {
-       ncr_io_bput(&ncr_a4000t, addr, v);
+       ncr710_io_bput(&ncr_a4000t, addr, v);
 }
-uae_u32 ncr_io_bget_a4000t(uaecptr addr)
+uae_u32 ncr710_io_bget_a4000t(uaecptr addr)
 {
-       return ncr_io_bget(&ncr_a4000t, addr);
+       return ncr710_io_bget(&ncr_a4000t, addr);
 }
 
 static void REGPARAM2 ncr4_bput (uaecptr addr, uae_u32 b)
@@ -440,6 +592,57 @@ static uae_u32 REGPARAM2 we_lget (uaecptr addr)
        return ncr_lget(&ncr_we, addr);
 }
 
+static void REGPARAM2 cs_bput(uaecptr addr, uae_u32 b)
+{
+       ncr_bput(&ncr_cs, addr, b);
+}
+static void REGPARAM2 cs_wput(uaecptr addr, uae_u32 b)
+{
+       ncr_wput(&ncr_cs, addr, b);
+}
+static void REGPARAM2 cs_lput(uaecptr addr, uae_u32 b)
+{
+       ncr_lput(&ncr_cs, addr, b);
+}
+static uae_u32 REGPARAM2 cs_bget(uaecptr addr)
+{
+       return ncr_bget(&ncr_cs, addr);
+}
+static uae_u32 REGPARAM2 cs_wget(uaecptr addr)
+{
+       return ncr_wget(&ncr_cs, addr);
+}
+static uae_u32 REGPARAM2 cs_lget(uaecptr addr)
+{
+       return ncr_lget(&ncr_cs, addr);
+}
+
+
+static void REGPARAM2 bppc_bput(uaecptr addr, uae_u32 b)
+{
+       ncr_bput(&ncr_bppc, addr, b);
+}
+static void REGPARAM2 bppc_wput(uaecptr addr, uae_u32 b)
+{
+       ncr_wput(&ncr_bppc, addr, b);
+}
+static void REGPARAM2 bppc_lput(uaecptr addr, uae_u32 b)
+{
+       ncr_lput(&ncr_bppc, addr, b);
+}
+static uae_u32 REGPARAM2 bppc_bget(uaecptr addr)
+{
+       return ncr_bget(&ncr_bppc, addr);
+}
+static uae_u32 REGPARAM2 bppc_wget(uaecptr addr)
+{
+       return ncr_wget(&ncr_bppc, addr);
+}
+static uae_u32 REGPARAM2 bppc_lget(uaecptr addr)
+{
+       return ncr_lget(&ncr_bppc, addr);
+}
+
 static addrbank ncr_bank_a4091 = {
        ncr4_lget, ncr4_wget, ncr4_bget,
        ncr4_lput, ncr4_wput, ncr4_bput,
@@ -457,10 +660,25 @@ static addrbank ncr_bank_a4091_2 = {
 static addrbank ncr_bank_warpengine = {
        we_lget, we_wget, we_bget,
        we_lput, we_wput, we_bput,
-       default_xlate, default_check, NULL, _T("Warp Engine"),
+       default_xlate, default_check, NULL, _T("Warp Engine SCSI"),
        dummy_lgeti, dummy_wgeti, ABFLAG_IO
 };
 
+addrbank ncr_bank_cyberstorm = {
+       cs_lget, cs_wget, cs_bget,
+       cs_lput, cs_wput, cs_bput,
+       cyberstorm_scsi_ram_xlate, cyberstorm_scsi_ram_check, NULL, _T("CyberStorm SCSI"),
+       dummy_lgeti, dummy_wgeti, ABFLAG_IO
+};
+
+addrbank ncr_bank_blizzardppc = {
+       bppc_lget, bppc_wget, bppc_bget,
+       bppc_lput, bppc_wput, bppc_bput,
+       default_xlate, default_check, NULL, _T("Blizzard PPC SCSI"),
+       dummy_lgeti, dummy_wgeti, ABFLAG_IO
+};
+
+
 
 static void ew (struct ncr_state *ncr, int addr, uae_u8 value)
 {
@@ -473,20 +691,42 @@ static void ew (struct ncr_state *ncr, int addr, uae_u8 value)
        }
 }
 
-void ncr_init (void)
+void ncr_init(void)
+{
+       ncr_cs.newncr = true;
+       if (!ncr_cs.devobject.lsistate)
+               lsi_scsi_init(&ncr_cs.devobject);
+       ncr_cs.ramsize = CYBERSTORM_SCSI_RAM_SIZE;
+}
+
+void ncr710_init (void)
 {
        for (int i = 0; ncrs[i]; i++) {
+               ncrs[i]->newncr = false;
                if (!ncrs[i]->devobject.lsistate)
-                       lsi_scsi_init (&ncrs[i]->devobject);
+                       lsi710_scsi_init (&ncrs[i]->devobject);
        }
 }
 
-static void ncr_reset_board (struct ncr_state *ncr)
+static void ncr_reset_board(struct ncr_state *ncr)
 {
        ncr->configured = 0;
        ncr->board_mask = 0xffff;
+       ncr->irq = false;
        if (ncr->devobject.lsistate)
-               lsi_scsi_reset (&ncr->devobject, ncr);
+               lsi_scsi_reset(&ncr->devobject, ncr);
+       ncr->bank = &ncr_bank_cyberstorm;
+       ncr->irq_func = cyberstorm_irq;
+}
+
+static void ncr710_reset_board (struct ncr_state *ncr)
+{
+       ncr->configured = 0;
+       ncr->board_mask = 0xffff;
+       ncr->irq = false;
+       ncr->irq_func = set_irq2;
+       if (ncr->devobject.lsistate)
+               lsi710_scsi_reset (&ncr->devobject, ncr);
        if (ncr == &ncr_a4000t) {
                ncr->name = _T("A4000T NCR SCSI");
                ncr->bank = NULL;
@@ -500,9 +740,14 @@ static void ncr_reset_board (struct ncr_state *ncr)
                ncr->bank = &ncr_bank_a4091_2;
        }
        if (ncr == &ncr_we) {
-               ncr->name = _T("Warp Engine");
+               ncr->name = _T("Warp Engine SCSI");
                ncr->bank = &ncr_bank_warpengine;
        }
+       if (ncr == &ncr_bppc) {
+               ncr->name = _T("Blizzard PPC SCSI");
+               ncr->bank = &ncr_bank_blizzardppc;
+               ncr->irq_func = blizzardppc_irq;
+       }
 }
 
 static const uae_u8 warpengine_a4000_autoconfig[16] = {
@@ -510,7 +755,7 @@ static const uae_u8 warpengine_a4000_autoconfig[16] = {
 };
 #define WARP_ENGINE_ROM_SIZE 32768
 
-addrbank *ncr_warpengine_autoconfig_init(void)
+addrbank *ncr710_warpengine_autoconfig_init(void)
 {
        int roms[2];
        struct ncr_state *ncr = &ncr_we;
@@ -551,13 +796,13 @@ addrbank *ncr_warpengine_autoconfig_init(void)
                romwarning (roms);
        }
 
-       ncr_init ();
-       ncr_reset_board(ncr);
+       ncr710_init ();
+       ncr710_reset_board(ncr);
 
        return &ncr_bank_warpengine;
 }
 
-addrbank *ncr_a4091_autoconfig_init (int devnum)
+addrbank *ncr710_a4091_autoconfig_init (int devnum)
 {
        struct ncr_state *ncr = ncra4091[devnum];
        int roms[3];
@@ -606,8 +851,8 @@ addrbank *ncr_a4091_autoconfig_init (int devnum)
                romwarning (roms);
        }
 
-       ncr_init ();
-       ncr_reset_board(ncr);
+       ncr710_init ();
+       ncr710_reset_board(ncr);
 
        return ncr == &ncr_a4091 ? &ncr_bank_a4091 : &ncr_bank_a4091_2;
 }
@@ -628,7 +873,7 @@ static void freescsi (SCSIDevice *scsi)
        }
 }
 
-void ncr_free2(struct ncr_state *ncr)
+static void ncr_free2(struct ncr_state *ncr)
 {
        for (int ch = 0; ch < 8; ch++) {
                freescsi (ncr->scsid[ch]);
@@ -636,22 +881,38 @@ void ncr_free2(struct ncr_state *ncr)
        }
 }
 
-void ncr_free(void)
+void ncr710_free(void)
 {
        for (int i = 0; ncrs[i]; i++) {
                ncr_free2(ncrs[i]);
        }
 }
 
-void ncr_reset (void)
+void ncr_free(void)
+{
+       ncr_free2(&ncr_cs);
+}
+
+void ncr710_reset(void)
 {
        for (int i = 0; ncrs[i]; i++) {
-               ncr_reset_board(ncrs[i]);
+               ncr710_reset_board(ncrs[i]);
        }
        if (currprefs.cs_mbdmac & 2) {
                ncr_a4000t.configured = -1;
                ncr_a4000t.enabled = true;
        }
+       if (currprefs.cpuboard_type == BOARD_BLIZZARDPPC) {
+               ncr_bppc.configured = -1;
+               ncr_bppc.enabled = true;
+       }
+}
+
+void ncr_reset(void)
+{
+       ncr_reset_board(&ncr_cs);
+       ncr_cs.configured = -1;
+       ncr_cs.enabled = true;
 }
 
 static int add_ncr_scsi_hd (struct ncr_state *ncr, int ch, struct hd_hardfiledata *hfd, struct uaedev_config_info *ci, int scsi_level)
@@ -739,6 +1000,25 @@ int a4091_add_scsi_unit (int ch, struct uaedev_config_info *ci, int devnum)
                return add_ncr_scsi_hd (ncr, ch, NULL, ci, 1);
 }
 
+int cyberstorm_add_scsi_unit(int ch, struct uaedev_config_info *ci)
+{
+       if (ci->type == UAEDEV_CD)
+               return add_ncr_scsi_cd(&ncr_cs, ch, ci->device_emu_unit);
+       else if (ci->type == UAEDEV_TAPE)
+               return add_ncr_scsi_tape(&ncr_cs, ch, ci->rootdir, ci->readonly);
+       else
+               return add_ncr_scsi_hd(&ncr_cs, ch, NULL, ci, 1);
+}
+
+int blizzardppc_add_scsi_unit(int ch, struct uaedev_config_info *ci)
+{
+       if (ci->type == UAEDEV_CD)
+               return add_ncr_scsi_cd(&ncr_bppc, ch, ci->device_emu_unit);
+       else if (ci->type == UAEDEV_TAPE)
+               return add_ncr_scsi_tape(&ncr_bppc, ch, ci->rootdir, ci->readonly);
+       else
+               return add_ncr_scsi_hd(&ncr_bppc, ch, NULL, ci, 1);
+}
 
 
 #endif
index 1d88a40c2695a9b7d2f30438709567a88772a167..a4f3081843ba4bad8ca6066eec37afa48f07a72a 100644 (file)
@@ -61,6 +61,7 @@ int mmu_enabled, mmu_triggered;
 int cpu_cycles;
 static int baseclock;
 bool m68k_pc_indirect;
+bool m68k_interrupt_delay;
 static int cpu_prefs_changed_flag;
 
 int cpucycleunit;
@@ -90,9 +91,9 @@ static uae_u16 fake_mmusr_030;
 static struct cache020 caches020[CACHELINES020];
 static struct cache030 icaches030[CACHELINES030];
 static struct cache030 dcaches030[CACHELINES030];
-#if 0
-static struct cache040 caches040[CACHESETS040];
-#endif
+static int icachelinecnt, dcachelinecnt;
+static struct cache040 icaches040[CACHESETS040];
+static struct cache040 dcaches040[CACHESETS040];
 
 #if COUNT_INSTRS
 static unsigned long int instrcount[65536];
@@ -195,6 +196,15 @@ void (*x_do_cycles)(unsigned long);
 void (*x_do_cycles_pre)(unsigned long);
 void (*x_do_cycles_post)(unsigned long, uae_u32);
 
+uae_u32(*x_phys_get_iword)(uaecptr);
+uae_u32(*x_phys_get_ilong)(uaecptr);
+uae_u32(*x_phys_get_byte)(uaecptr);
+uae_u32(*x_phys_get_word)(uaecptr);
+uae_u32(*x_phys_get_long)(uaecptr);
+void(*x_phys_put_byte)(uaecptr, uae_u32);
+void(*x_phys_put_word)(uaecptr, uae_u32);
+void(*x_phys_put_long)(uaecptr, uae_u32);
+
 static void set_x_cp_funcs(void)
 {
        x_cp_put_long = x_put_long;
@@ -813,7 +823,7 @@ static void set_x_funcs (void)
                                x_do_cycles = do_cycles;
                                x_do_cycles_pre = do_cycles;
                                x_do_cycles_post = do_cycles_post;
-                       } else {
+                       } else if (currprefs.cpu_model < 68040) {
                                // JIT or 68030+ does not have real prefetch only emulation
                                x_prefetch = NULL;
                                x_get_ilong = get_dilong;
@@ -830,6 +840,22 @@ static void set_x_funcs (void)
                                x_do_cycles = do_cycles;
                                x_do_cycles_pre = do_cycles;
                                x_do_cycles_post = do_cycles_post;
+                       } else {
+                               x_prefetch = NULL;
+                               x_get_ilong = get_ilong_cache_040;
+                               x_get_iword = get_iword_cache_040;
+                               x_get_ibyte = NULL;
+                               x_next_iword = next_iword_cache040;
+                               x_next_ilong = next_ilong_cache040;
+                               x_put_long = put_long_cache_040;
+                               x_put_word = put_word_cache_040;
+                               x_put_byte = put_byte_cache_040;
+                               x_get_long = get_long_cache_040;
+                               x_get_word = get_word_cache_040;
+                               x_get_byte = get_byte_cache_040;
+                               x_do_cycles = do_cycles;
+                               x_do_cycles_pre = do_cycles;
+                               x_do_cycles_post = do_cycles_post;
                        }
                } else {
                        x_prefetch = NULL;
@@ -865,7 +891,7 @@ static void set_x_funcs (void)
                x_do_cycles = do_cycles_ce020;
                x_do_cycles_pre = do_cycles_ce020;
                x_do_cycles_post = do_cycles_ce020_post;
-       } else {
+       } else if (currprefs.cpu_model == 68030) {
                x_prefetch = get_word_ce030_prefetch;
                x_get_ilong = get_long_ce030_prefetch;
                x_get_iword = get_word_ce030_prefetch;
@@ -881,6 +907,22 @@ static void set_x_funcs (void)
                x_do_cycles = do_cycles_ce020;
                x_do_cycles_pre = do_cycles_ce020;
                x_do_cycles_post = do_cycles_ce020_post;
+       } else if (currprefs.cpu_model >= 68040) {
+               x_prefetch = NULL;
+               x_get_ilong = get_ilong_cache_040;
+               x_get_iword = get_iword_cache_040;
+               x_get_ibyte = NULL;
+               x_next_iword = next_iword_cache040;
+               x_next_ilong = next_ilong_cache040;
+               x_put_long = put_long_cache_040;
+               x_put_word = put_word_cache_040;
+               x_put_byte = put_byte_cache_040;
+               x_get_long = get_long_cache_040;
+               x_get_word = get_word_cache_040;
+               x_get_byte = get_byte_cache_040;
+               x_do_cycles = do_cycles_ce020;
+               x_do_cycles_pre = do_cycles_ce020;
+               x_do_cycles_post = do_cycles_ce020_post;
        }
        x2_prefetch = x_prefetch;
        x2_get_ilong = x_get_ilong;
@@ -1023,17 +1065,17 @@ void set_cpu_caches (bool flush)
                        dcaches030[(regs.caar >> 4) & (CACHELINES030 - 1)].valid[(regs.caar >> 2) & 3] = 0;
                        regs.cacr &= ~0x400;
                }
-#if 0
        } else if (currprefs.cpu_model == 68040) {
+               icachelinecnt = 0;
+               dcachelinecnt = 0;
                if (!(regs.cacr & 0x8000)) {
                        for (i = 0; i < CACHESETS040; i++) {
-                               caches040[i].valid[0] = 0;
-                               caches040[i].valid[1] = 0;
-                               caches040[i].valid[2] = 0;
-                               caches040[i].valid[3] = 0;
+                               icaches040[i].valid[0] = 0;
+                               icaches040[i].valid[1] = 0;
+                               icaches040[i].valid[2] = 0;
+                               icaches040[i].valid[3] = 0;
                        }
                }
-#endif
        }
 }
 
@@ -1071,7 +1113,9 @@ static void build_cpufunctbl (void)
                tbl = op_smalltbl_0_ff;
                if (!currprefs.cachesize) {
                        if (currprefs.cpu_cycle_exact)
-                               tbl = op_smalltbl_22_ff;
+                               tbl = op_smalltbl_23_ff;
+                       if (currprefs.cpu_compatible)
+                               tbl = op_smalltbl_23_ff;
                        if (currprefs.mmu_model)
                                tbl = op_smalltbl_33_ff;
                }
@@ -1081,7 +1125,9 @@ static void build_cpufunctbl (void)
                tbl = op_smalltbl_1_ff;
                if (!currprefs.cachesize) {
                        if (currprefs.cpu_cycle_exact)
-                               tbl = op_smalltbl_23_ff;
+                               tbl = op_smalltbl_24_ff;
+                       if (currprefs.cpu_compatible)
+                               tbl = op_smalltbl_24_ff;
                        if (currprefs.mmu_model)
                                tbl = op_smalltbl_31_ff;
                }
@@ -1091,7 +1137,7 @@ static void build_cpufunctbl (void)
                tbl = op_smalltbl_2_ff;
                if (!currprefs.cachesize) {
                        if (currprefs.cpu_cycle_exact)
-                               tbl = op_smalltbl_24_ff;
+                               tbl = op_smalltbl_22_ff;
                        if (currprefs.mmu_model)
                                tbl = op_smalltbl_32_ff;
                }
@@ -1214,6 +1260,12 @@ static void build_cpufunctbl (void)
                if (currprefs.address_space_24 && currprefs.cpu_model >= 68030)
                        currprefs.address_space_24 = false;
        }
+       m68k_interrupt_delay = false;
+       if (currprefs.cpu_cycle_exact) {
+               if (tbl == op_smalltbl_13_ff || tbl == op_smalltbl_21_ff || tbl == op_smalltbl_22_ff)
+                       m68k_interrupt_delay = true;
+       }
+
        if (currprefs.cpu_cycle_exact) {
                if (currprefs.cpu_model == 68000)
                        write_log(_T(" prefetch and cycle-exact"));
@@ -1558,12 +1610,20 @@ static uaecptr ShowEA (void *f, uaecptr pc, uae_u16 opcode, int reg, amodes mode
                        pc += 4;
                        break;
                case sz_single:
-                       _stprintf(buffer, _T("#%e"), to_single(get_ilong_debug(pc)));
-                       pc += 4;
+                       {
+                               fpdata fp;
+                               to_single(&fp, get_ilong_debug(pc));
+                               _stprintf(buffer, _T("#%e"), fp.fp);
+                               pc += 4;
+                       }
                        break;
                case sz_double:
-                       _stprintf(buffer, _T("#%e"), to_double(get_ilong_debug(pc), get_ilong_debug(pc + 4)));
-                       pc += 8;
+                       {
+                               fpdata fp;
+                               to_double(&fp, get_ilong_debug(pc), get_ilong_debug(pc + 4));
+                               _stprintf(buffer, _T("#%e"), fp.fp);
+                               pc += 8;
+                       }
                        break;
                case sz_extended:
                {
@@ -2628,7 +2688,7 @@ void NMI (void)
 }
 
 
-static void m68k_reset (bool hardreset)
+static void m68k_reset2(bool hardreset)
 {
        uae_u32 v;
 
@@ -2721,6 +2781,11 @@ static void m68k_reset (bool hardreset)
        regs.ce020memcycles = 0;
        fill_prefetch ();
 }
+void m68k_reset(void)
+{
+       m68k_reset2(false);
+}
+
 
 void REGPARAM2 op_unimpl (uae_u16 opcode)
 {
@@ -3071,7 +3136,6 @@ static void do_trace (void)
        }
 }
 
-
 // handle interrupt delay (few cycles)
 STATIC_INLINE bool time_for_interrupt (void)
 {
@@ -3080,7 +3144,7 @@ STATIC_INLINE bool time_for_interrupt (void)
 
 void doint (void)
 {
-       if (currprefs.cpu_cycle_exact) {
+       if (m68k_interrupt_delay) {
                regs.ipl_pin = intlev ();
                unset_special (SPCFLAG_INT);
                return;
@@ -3191,7 +3255,7 @@ static int do_specialties (int cycles)
                if (regs.spcflags & SPCFLAG_COPPER)
                        do_copper ();
 
-               if (currprefs.cpu_cycle_exact) {
+               if (m68k_interrupt_delay) {
                        ipl_fetch ();
                        if (time_for_interrupt ()) {
                                do_interrupt (regs.ipl);
@@ -3240,7 +3304,7 @@ static int do_specialties (int cycles)
        if (regs.spcflags & SPCFLAG_TRACE)
                do_trace ();
 
-       if (currprefs.cpu_cycle_exact) {
+       if (m68k_interrupt_delay) {
                if (time_for_interrupt ()) {
                        do_interrupt (regs.ipl);
                }
@@ -3353,13 +3417,23 @@ static void out_cd32io (uae_u32 pc)
 
 #endif
 
+STATIC_INLINE void wait_memory_cycles (void)
+{
+       if (regs.memory_waitstate_cycles) {
+               x_do_cycles(regs.memory_waitstate_cycles);
+               regs.memory_waitstate_cycles = 0;
+       }
+}
+
 STATIC_INLINE int adjust_cycles (int cycles)
 {
+       int mc = regs.memory_waitstate_cycles;
+       regs.memory_waitstate_cycles = 0;
        if (currprefs.m68k_speed < 0 || cycles_mult == 0)
-               return cycles;
+               return cycles + mc;
        cpu_cycles *= cycles_mult;
        cpu_cycles /= CYCLES_DIV;
-       return cpu_cycles;
+       return cpu_cycles + mc;
 }
 
 #ifndef CPUEMU_11
@@ -3491,6 +3565,7 @@ static void m68k_run_1_ce (void)
 
                r->instruction_pc = m68k_getpc ();
                (*cpufunctbl[opcode])(opcode);
+               wait_memory_cycles();
                if (cpu_tracer) {
                        cputrace.state = 0;
                }
@@ -3680,7 +3755,7 @@ void cpu_halt (int id)
        if (!regs.halted) {
                write_log (_T("CPU halted: reason = %d\n"), id);
                regs.halted = id;
-               gui_data.cpu_halted = true;
+               gui_data.cpu_halted = id;
                gui_led (LED_CPU, 0);
                regs.intmask = 7;
                MakeSR ();
@@ -3902,7 +3977,6 @@ insretry:
 #endif
 
 
-#if 0
 /* "cycle exact" 68040+ */
 
 static void m68k_run_3ce (void)
@@ -3910,26 +3984,62 @@ static void m68k_run_3ce (void)
        struct regstruct *r = &regs;
        uae_u16 opcode;
        bool exit = false;
+       int cycles;
 
        for (;;) {
-               r->instruction_pc = m68k_getpc ();
-               opcode = get_word_ce040_prefetch (0);
+               r->instruction_pc = m68k_getpc();
+               opcode = get_iword_cache_040(0);
+               // "prefetch"
+               if (regs.cacr & 0x8000)
+                       fill_icache040(r->instruction_pc + 16);
 
                (*cpufunctbl[opcode])(opcode);
 
-               if (r->spcflags || time_for_interrupt ()) {
+               cpu_cycles = 4 * CYCLE_UNIT;
+               cycles = adjust_cycles(cpu_cycles);
+               do_cycles(cycles);
+
+               if (r->spcflags) {
                        if (do_specialties (0))
                                exit = true;
                }
 
-               regs.ipl = regs.ipl_pin;
-
                if (exit)
                        return;
        }
 }
-#endif
 
+/* "prefetch" 68040+ */
+
+static void m68k_run_3p(void)
+{
+       struct regstruct *r = &regs;
+       uae_u16 opcode;
+       bool exit = false;
+       int cycles;
+
+       for (;;) {
+               r->instruction_pc = m68k_getpc();
+               opcode = get_iword_cache_040(0);
+               // "prefetch"
+               if (regs.cacr & 0x8000)
+                       fill_icache040(r->instruction_pc + 16);
+
+               (*cpufunctbl[opcode])(opcode);
+
+               cpu_cycles = 4 * CYCLE_UNIT;
+               cycles = adjust_cycles(cpu_cycles);
+               do_cycles(cycles);
+
+               if (r->spcflags) {
+                       if (do_specialties(0))
+                               exit = true;
+               }
+
+               if (exit)
+                       return;
+       }
+}
 /* "cycle exact" 68020/030  */
 
 
@@ -4034,6 +4144,8 @@ static void m68k_run_2ce (void)
                }
 
                (*cpufunctbl[opcode])(opcode);
+               
+               wait_memory_cycles();
 
 cont:
                if (r->spcflags || time_for_interrupt ()) {
@@ -4232,7 +4344,7 @@ void m68k_go (int may_quit)
 #endif
                        set_cycles (start_cycles);
                        custom_reset (hardreset != 0, kbreset);
-                       m68k_reset (hardreset != 0);
+                       m68k_reset2 (hardreset != 0);
                        if (hardreset) {
                                memory_clear ();
                                write_log (_T("hardreset, memory cleared\n"));
@@ -4341,11 +4453,14 @@ void m68k_go (int may_quit)
                                currprefs.cpu_model == 68030 && currprefs.mmu_model ? m68k_run_mmu030 :
                                currprefs.cpu_model == 68040 && currprefs.mmu_model ? m68k_run_mmu040 :
                                currprefs.cpu_model == 68060 && currprefs.mmu_model ? m68k_run_mmu060 :
-#if 0
+
                                currprefs.cpu_model >= 68040 && currprefs.cpu_cycle_exact ? m68k_run_3ce :
-#endif
                                currprefs.cpu_model >= 68020 && currprefs.cpu_cycle_exact ? m68k_run_2ce :
-                               currprefs.cpu_compatible ? (currprefs.cpu_model <= 68020 ? m68k_run_2p : m68k_run_2pf) : m68k_run_2;
+
+                               currprefs.cpu_model <= 68020 && currprefs.cpu_compatible ? m68k_run_2p :
+                               currprefs.cpu_model >= 68040 && currprefs.cpu_compatible ? m68k_run_3p :
+
+                               m68k_run_2;
 #if 0
                }
 #endif
@@ -5258,6 +5373,24 @@ uae_u8 *restore_cpu (uae_u8 *src)
                        }
                        for (int i = 0; i < CPU_PIPELINE_MAX; i++)
                                regs.prefetch020[i] = restore_u32 ();
+               } else if (model == 68040) {
+                       if (flags & 0x8000000) {
+                               for (int i = 0; i < CACHESETS040; i++) {
+                                       for (int j = 0; j < CACHELINES040; j++) {
+                                               icaches040[i].data[j][0] = restore_u32();
+                                               icaches040[i].data[j][1] = restore_u32();
+                                               icaches040[i].data[j][2] = restore_u32();
+                                               icaches040[i].data[j][3] = restore_u32();
+                                               icaches040[i].tag[j] = restore_u32();
+                                               icaches040[i].valid[j] = restore_u16() & 1;
+                                       }
+                               }
+                               regs.prefetch020addr = restore_u32();
+                               regs.cacheholdingaddr020 = restore_u32();
+                               regs.cacheholdingdata020 = restore_u32();
+                               for (int i = 0; i < CPU_PIPELINE_MAX; i++)
+                                       regs.prefetch020[i] = restore_u32();
+                       }
                }
                if (model >= 68020) {
                        regs.ce020memcycles = restore_u32 ();
@@ -5493,7 +5626,7 @@ uae_u8 *save_cpu (int *len, uae_u8 *dstptr)
                dstbak = dst = xmalloc (uae_u8, 1000);
        model = currprefs.cpu_model;
        save_u32 (model);                                       /* MODEL */
-       save_u32 (0x80000000 | 0x40000000 | 0x20000000 | 0x10000000 | (currprefs.address_space_24 ? 1 : 0)); /* FLAGS */
+       save_u32(0x80000000 | 0x40000000 | 0x20000000 | 0x10000000 | 0x8000000 |(currprefs.address_space_24 ? 1 : 0)); /* FLAGS */
        for (i = 0;i < 15; i++)
                save_u32 (regs.regs[i]);                /* D0-D7 A0-A6 */
        save_u32 (m68k_getpc ());                       /* PC */
@@ -5583,6 +5716,22 @@ uae_u8 *save_cpu (int *len, uae_u8 *dstptr)
                save_u32 (regs.cacheholdingdata020);
                for (int i = 0; i < CPU_PIPELINE_MAX; i++)
                        save_u32 (regs.prefetch020[i]);
+       } else if (model >= 68040) {
+               for (int i = 0; i < CACHESETS040; i++) {
+                       for (int j = 0; j < CACHELINES040; j++) {
+                               save_u32(icaches040[i].data[j][0]);
+                               save_u32(icaches040[i].data[j][1]);
+                               save_u32(icaches040[i].data[j][2]);
+                               save_u32(icaches040[i].data[j][3]);
+                               save_u32(icaches040[i].tag[j]);
+                               save_u16(icaches040[i].valid[j] ? 1 : 0);
+                       }
+               }
+               save_u32(regs.prefetch020addr);
+               save_u32(regs.cacheholdingaddr020);
+               save_u32(regs.cacheholdingdata020);
+               for (int i = 0; i < CPU_PIPELINE_MAX; i++)
+                       save_u32(regs.prefetch020[i]);
        }
        if (currprefs.cpu_model >= 68020) {
                save_u32 (regs.ce020memcycles);
@@ -5756,44 +5905,6 @@ void m68k_resumestopped (void)
        unset_special (SPCFLAG_STOP);
 }
 
-#if 0
-STATIC_INLINE void fill_cache040 (uae_u32 addr)
-{
-       int index, i, lws;
-       uae_u32 tag;
-       uae_u32 data;
-       struct cache040 *c;
-       static int linecnt;
-
-       addr &= ~15;
-       index = (addr >> 4) & (CACHESETS040 - 1);
-       tag = regs.s | (addr & ~((CACHESETS040 << 4) - 1));
-       lws = (addr >> 2) & 3;
-       c = &caches040[index];
-       for (i = 0; i < CACHELINES040; i++) {
-               if (c->valid[i] && c->tag[i] == tag) {
-                       // cache hit
-                       regs.cacheholdingaddr020 = addr;
-                       regs.cacheholdingdata020 = c->data[i][lws];
-                       return;
-               }
-       }
-       // cache miss
-       data = mem_access_delay_longi_read_ce020 (addr);
-       int line = linecnt;
-       for (i = 0; i < CACHELINES040; i++) {
-               int line = (linecnt + i) & (CACHELINES040 - 1);
-               if (c->tag[i] != tag || c->valid[i] == false) {
-                       c->tag[i] = tag;
-                       c->valid[i] = true;
-                       c->data[i][0] = data;
-               }
-       }
-       regs.cacheholdingaddr020 = addr;
-       regs.cacheholdingdata020 = data;
-}
-#endif
-
 // this one is really simple and easy
 static void fill_icache020 (uae_u32 addr, uae_u32 (*fetch)(uaecptr))
 {
@@ -6162,7 +6273,8 @@ static void fill_icache030 (uae_u32 addr)
                c->data[1] = get_longi (addr + 4);
                c->data[2] = get_longi (addr + 8);
                c->data[3] = get_longi (addr + 12);
-               do_cycles_ce020_mem (3 * (CPU020_MEM_CYCLE - 1), c->data[3]);
+               if (currprefs.cpu_cycle_exact)
+                       do_cycles_ce020_mem (3 * (CPU020_MEM_CYCLE - 1), c->data[3]);
                c->valid[1] = c->valid[2] = c->valid[3] = true;
        }
        regs.cacheholdingaddr020 = addr;
@@ -6175,14 +6287,14 @@ STATIC_INLINE bool cancache030 (uaecptr addr)
 }
 
 // and finally the worst part, 68030 data cache..
-void write_dcache030 (uaecptr addr, uae_u32 val, int size)
+static void write_dcache030x (uaecptr addr, uae_u32 val, int size)
 {
        struct cache030 *c1, *c2;
        int lws1, lws2;
        uae_u32 tag1, tag2;
        int aligned = addr & 3;
 
-       if (!(regs.cacr & 0x100) || currprefs.cpu_model == 68040) // data cache disabled? 68040 shares this too.
+       if (1 || !(regs.cacr & 0x100)) // data cache disabled?
                return;
        if (!cancache030 (addr))
                return;
@@ -6226,6 +6338,25 @@ void write_dcache030 (uaecptr addr, uae_u32 val, int size)
                }
        }
 }
+void write_dcache030(uaecptr addr, uae_u32 v, int size)
+{
+       write_dcache030x(addr, v, size);
+       if (currprefs.cpu_cycle_exact) {
+               if (size == 2)
+                       mem_access_delay_long_write_ce020(addr, v);
+               else if (size == 1)
+                       mem_access_delay_word_write_ce020(addr, v);
+               else
+                       mem_access_delay_byte_write_ce020(addr, v);
+       } else {
+               if (size == 2)
+                       put_long(addr, v);
+               else if (size == 1)
+                       put_word(addr, v);
+               else
+                       put_byte(addr, v);
+       }
+}
 
 uae_u32 read_dcache030 (uaecptr addr, int size)
 {
@@ -6236,7 +6367,7 @@ uae_u32 read_dcache030 (uaecptr addr, int size)
        int len = (1 << size) * 8;
        uae_u32 v1, v2;
 
-       if (!(regs.cacr & 0x100) || currprefs.cpu_model == 68040 || !cancache030 (addr)) { // data cache disabled? shared with 68040 "ce"
+       if (1 || !(regs.cacr & 0x100) || !cancache030 (addr)) { // data cache disabled?
                if (currprefs.cpu_cycle_exact) {
                        if (size == 2)
                                return mem_access_delay_long_read_ce020 (addr);
@@ -6332,9 +6463,372 @@ uae_u32 get_word_ce030_prefetch (int o)
        return v;
 }
 
+uae_u32 get_word_icache030(uaecptr addr)
+{
+       fill_icache030(addr);
+       return regs.cacheholdingdata020 >> ((addr & 2) ? 0 : 16);
+}
+uae_u32 get_long_icache030(uaecptr addr)
+{
+       uae_u32 v;
+       fill_icache030(addr);
+       if ((addr & 2) == 0)
+               return regs.cacheholdingdata020;
+       v = regs.cacheholdingdata020 << 16;
+       fill_icache030(addr + 4);
+       v |= regs.cacheholdingdata020 >> 16;
+       return v;
+}
+
+uae_u32 fill_icache040(uae_u32 addr)
+{
+       int index, i, lws;
+       uae_u32 tag;
+       struct cache040 *c;
+       int line;
+
+       if (!(regs.cacr & 0x8000)) {
+               uae_u32 addr2 = addr & ~15;
+               lws = (addr >> 2) & 3;
+               addr &= ~3;
+               if (regs.prefetch020addr == addr2)
+                       return regs.prefetch020[lws];
+               regs.prefetch020addr = addr2;
+               if (currprefs.cpu_cycle_exact) {
+                       regs.prefetch020[0] = mem_access_delay_longi_read_ce020(addr2 +  0);
+                       regs.prefetch020[1] = mem_access_delay_longi_read_ce020(addr2 +  4);
+                       regs.prefetch020[2] = mem_access_delay_longi_read_ce020(addr2 +  8);
+                       regs.prefetch020[3] = mem_access_delay_longi_read_ce020(addr2 + 12);
+               } else {
+                       regs.prefetch020[0] = get_longi(addr2 +  0);
+                       regs.prefetch020[1] = get_longi(addr2 +  4);
+                       regs.prefetch020[2] = get_longi(addr2 +  8);
+                       regs.prefetch020[3] = get_longi(addr2 + 12);
+               }
+               return regs.prefetch020[lws];
+       }
+
+       index = (addr >> 4) & (CACHESETS040 - 1);
+       tag = regs.s | (addr & ~((CACHESETS040 << 4) - 1));
+       lws = (addr >> 2) & 3;
+       addr &= ~15;
+       c = &icaches040[index];
+       for (i = 0; i < CACHELINES040; i++) {
+               if (c->valid[i] && c->tag[i] == tag) {
+                       // cache hit
+                       icachelinecnt++;
+                       return c->data[i][lws];
+               }
+       }
+       // cache miss
+       if (c->valid[0] && c->valid[1] && c->valid[2] && c->valid[3]) {
+               line = (icachelinecnt >> 1) & (CACHELINES040 - 1);
+       }
+       else {
+               for (line = 0; line < CACHELINES040; line++) {
+                       if (c->valid[line] == false)
+                               break;
+               }
+       }
+       c->tag[line] = tag;
+       c->valid[line] = true;
+       if (currprefs.cpu_cycle_exact) {
+               c->data[line][0] = mem_access_delay_longi_read_ce020(addr +  0);
+               c->data[line][1] = mem_access_delay_longi_read_ce020(addr +  4);
+               c->data[line][2] = mem_access_delay_longi_read_ce020(addr +  8);
+               c->data[line][3] = mem_access_delay_longi_read_ce020(addr + 12);
+       } else {
+               c->data[line][0] = get_longi(addr +  0);
+               c->data[line][1] = get_longi(addr +  4);
+               c->data[line][2] = get_longi(addr +  8);
+               c->data[line][3] = get_longi(addr + 12);
+       }
+       return c->data[line][lws];
+}
+
+#if 0
+static bool is_dcache040(uae_u32 addr)
+{
+       int index, i, lws;
+       uae_u32 tag;
+       struct cache040 *c;
+
+       addr &= ~15;
+       index = (addr >> 4) & (CACHESETS040 - 1);
+       tag = regs.s | (addr & ~((CACHESETS040 << 4) - 1));
+       lws = (addr >> 2) & 3;
+       c = &dcaches040[index];
+       for (i = 0; i < CACHELINES040; i++) {
+               if (c->valid[i] && c->tag[i] == tag) {
+                       return true;
+               }
+       }
+       return false;
+}
+
+uae_u32 read_dcache040(uae_u32 addr)
+{
+       int index, i, lws;
+       uae_u32 tag;
+       struct cache040 *c;
+       int line;
+
+       addr &= ~15;
+       index = (addr >> 4) & (CACHESETS040 - 1);
+       tag = regs.s | (addr & ~((CACHESETS040 << 4) - 1));
+       lws = (addr >> 2) & 3;
+       c = &dcaches040[index];
+       for (i = 0; i < CACHELINES040; i++) {
+               if (c->valid[i] && c->tag[i] == tag) {
+                       // cache hit
+                       dcachelinecnt++;
+                       return c->data[i][lws];
+               }
+       }
+       // cache miss
+       if (c->valid[0] && c->valid[1] && c->valid[2] && c->valid[3]) {
+               line = (icachelinecnt >> 1) & (CACHELINES040 - 1);
+               for (i = 0; i < 4; i++) {
+                       if (c->dirty[line][i]) {
+                               c->dirty[line][i] = false;
+                               mem_access_delay_long_write_ce020(addr + i * 4, c->data[line][i]);
+                       }
+               }
+       }
+       else {
+               for (line = 0; line < CACHELINES040; line++) {
+                       if (c->valid[line] == false)
+                               break;
+               }
+       }
+       c->tag[line] = tag;
+       c->valid[line] = true;
+       c->data[line][0] = mem_access_delay_long_read_ce020(addr + 0);
+       c->data[line][1] = mem_access_delay_long_read_ce020(addr + 4);
+       c->data[line][2] = mem_access_delay_long_read_ce020(addr + 8);
+       c->data[line][3] = mem_access_delay_long_read_ce020(addr + 12);
+       regs.cacheholdingaddr020 = addr;
+}
+
+void write_dcache040(uae_u32 addr, uae_u32 val)
+{
+       int index, i, lws;
+       uae_u32 tag;
+       struct cache040 *c;
+       int line;
+
+       addr &= ~15;
+       index = (addr >> 4) & (CACHESETS040 - 1);
+       tag = regs.s | (addr & ~((CACHESETS040 << 4) - 1));
+       lws = (addr >> 2) & 3;
+       c = &dcaches040[index];
+       for (i = 0; i < CACHELINES040; i++) {
+               if (c->valid[i] && c->tag[i] == tag) {
+                       // cache hit
+                       dcachelinecnt++;
+                       c->data[i][lws] = val;
+                       mem_access_delay_long_write_ce020(addr + i * 4, c->data[i][lws]);
+                       //c->dirty[i][lws] = true;
+               }
+       }
+#if 0
+       // cache miss
+       if (c->valid[0] && c->valid[1] && c->valid[2] && c->valid[3]) {
+               line = (icachelinecnt >> 1) & (CACHELINES040 - 1);
+               for (i = 0; i < 4; i++) {
+                       if (c->dirty[line][i]) {
+                               c->dirty[line][i] = false;
+                               mem_access_delay_long_write_ce020(addr + i * 4, c->data[line][i]);
+                       }
+               }
+       }
+       else {
+               for (line = 0; line < CACHELINES040; line++) {
+                       if (c->valid[line] == false)
+                               break;
+               }
+       }
+       c->tag[line] = tag;
+       c->valid[line] = true;
+       c->data[line][0] = mem_access_delay_long_read_ce020(addr + 0);
+       c->data[line][1] = mem_access_delay_long_read_ce020(addr + 4);
+       c->data[line][2] = mem_access_delay_long_read_ce020(addr + 8);
+       c->data[line][3] = mem_access_delay_long_read_ce020(addr + 12);
+       c->data[line][lws] = val;
+       c->dirty[line][lws] = true;
+#endif
+}
+#endif
+
+// really unoptimized
+uae_u32 get_word_icache040(uaecptr addr)
+{
+       uae_u32 v = fill_icache040(addr);
+       return v >> ((addr & 2) ? 0 : 16);
+}
+uae_u32 get_long_icache040(uaecptr addr)
+{
+       uae_u32 v1, v2;
+       v1 = fill_icache040(addr);
+       if ((addr & 2) == 0)
+               return v1;
+       v2 = fill_icache040(addr + 4);
+       return (v2 >> 16) | (v1 << 16);
+}
+uae_u32 get_ilong_cache_040(int o)
+{
+       return get_long_icache040(m68k_getpci() + o);
+}
+uae_u32 get_iword_cache_040(int o)
+{
+       return get_word_icache040(m68k_getpci() + o);
+}
+
+void put_long_cache_040(uaecptr addr, uae_u32 v)
+{
+#if 1
+       if (currprefs.cpu_cycle_exact)
+               mem_access_delay_long_write_ce020(addr, v);
+       else
+               put_long(addr, v);
+#else
+       if ((addr & 2) == 0) {
+               if (is_dcache040(addr))
+                       write_dcache040(addr, v);
+               else if (currprefs.cpu_cycle_exact)
+                       mem_access_delay_long_write_ce020(addr, v);
+               else
+                       put_long(addr, v);
+       } else {
+               uae_u32 vp;
+               if (is_dcache040(addr)) {
+                       vp = read_dcache040(addr);
+                       vp &= 0xffff0000;
+                       vp |= v >> 16;
+                       write_dcache040(addr, vp);
+               } else if (currprefs.cpu_cycle_exact) {
+                       mem_access_delay_word_write_ce020(addr + 0, v >> 16);
+               } else {
+                       put_word(addr + 0, v >> 16);
+               }
+               if (is_dcache040(addr + 4)) {
+                       vp = read_dcache040(addr + 4);
+                       vp &= 0x0000ffff;
+                       vp |= v << 16;
+                       write_dcache040(addr + 4, vp);
+               } else if (currprefs.cpu_cycle_exact) {
+                       mem_access_delay_word_write_ce020(addr + 2, v);
+               } else {
+                       put_word(addr + 2, v);
+               }
+       }
+#endif
+}
+void put_word_cache_040(uaecptr addr, uae_u32 v)
+{
+#if 1
+       if (currprefs.cpu_cycle_exact)
+               mem_access_delay_word_write_ce020(addr, v);
+       else
+               put_word(addr, v);
+#else
+       if (is_dcache040(addr)) {
+               uae_u32 vp;
+               vp = read_dcache040(addr);
+               if (addr & 2) {
+                       vp &= 0xffff0000;
+                       vp |= v & 0xffff;
+               } else {
+                       vp &= 0x0000ffff;
+                       vp |= v << 16;
+               }
+               write_dcache040(addr, vp);
+       } else if (currprefs.cpu_cycle_exact) {
+               mem_access_delay_word_write_ce020(addr, v);
+       } else {
+               put_word(addr, v);
+       }
+#endif
+}
+void put_byte_cache_040(uaecptr addr, uae_u32 v)
+{
+#if 1
+       if (currprefs.cpu_cycle_exact)
+               mem_access_delay_byte_write_ce020(addr, v);
+       else
+               put_byte(addr, v);
+#else
+       if (is_dcache040(addr)) {
+               uae_u32 vp;
+               uae_u32 mask = 0xff000000 >> (addr & 3);
+               vp = read_dcache040(addr);
+               vp &= ~mask;
+               vp |= (v << (3 - (addr & 3))) & mask;
+               write_dcache040(addr, vp);
+       } else if (currprefs.cpu_cycle_exact) {
+               mem_access_delay_byte_write_ce020(addr, v);
+       } else {
+               put_byte(addr, v);
+       }
+#endif
+}
+
+uae_u32 get_long_cache_040(uaecptr addr)
+{
+#if 1
+       if (currprefs.cpu_cycle_exact)
+               return mem_access_delay_long_read_ce020(addr);
+       else
+               return get_long(addr);
+#else
+       uae_u32 v1, v2;
+       v1 = read_dcache040(addr);
+       if ((addr & 2) == 0)
+               return v1;
+       v2 = read_dcache040(addr + 4);
+       return (v2 >> 16) | (v1 << 16);
+#endif
+}
+uae_u32 get_word_cache_040(uaecptr addr)
+{
+#if 1
+       if (currprefs.cpu_cycle_exact)
+               return mem_access_delay_word_read_ce020(addr);
+       else
+               return get_word(addr);
+#else
+       uae_u32 v = read_dcache040(addr);
+       return v >> ((addr & 2) ? 0 : 16);
+#endif
+}
+uae_u32 get_byte_cache_040(uaecptr addr)
+{
+#if 1
+       if (currprefs.cpu_cycle_exact)
+               return mem_access_delay_byte_read_ce020(addr);
+       else
+               return get_byte(addr);
+#else
+       uae_u32 v = read_dcache040(addr);
+       return v >> (8 * (3 - (addr & 3)));
+#endif
+}
+uae_u32 next_iword_cache040(void)
+{
+       uae_u32 r = get_word_icache040(m68k_getpci());
+       m68k_incpci(2);
+       return r;
+}
+uae_u32 next_ilong_cache040(void)
+{
+       uae_u32 r = get_long_icache040(m68k_getpci());
+       m68k_incpci(4);
+       return r;
+}
+
 void flush_dcache (uaecptr addr, int size)
 {
-       if (!currprefs.cpu_cycle_exact)
+       if (!currprefs.cpu_cycle_exact && !currprefs.cpu_compatible)
                return;
        if (currprefs.cpu_model >= 68030) {
                for (int i = 0; i < CACHELINES030; i++) {
@@ -6384,7 +6878,12 @@ void fill_prefetch (void)
 {
        if (currprefs.cachesize)
                return;
-       if (currprefs.cpu_model == 68020) {
+       if (currprefs.cpu_model >= 68040) {
+               if (currprefs.cpu_compatible || currprefs.cpu_cycle_exact) {
+                       fill_icache040(m68k_getpc() + 16);
+                       fill_icache040(m68k_getpc());
+               }
+       } else if (currprefs.cpu_model == 68020) {
                fill_prefetch_020 ();
        } else if (currprefs.cpu_model == 68030) {
                if (!currprefs.cpu_cycle_exact)
index 6196d0aac05616002554fa46905d4f5775c89031..9121d6c9b5f8c2e808e64101548222d893a8a956 100644 (file)
@@ -575,6 +575,42 @@ uae_u32 REGPARAM2 x_get_disp_ea_ce020 (uae_u32 base, int idx)
        return v;
 }
 
+uae_u32 REGPARAM2 x_get_disp_ea_040(uae_u32 base, int idx)
+{
+       uae_u16 dp = next_iword_cache040();
+       int reg = (dp >> 12) & 15;
+       uae_s32 regd = regs.regs[reg];
+       if ((dp & 0x800) == 0)
+               regd = (uae_s32)(uae_s16)regd;
+       regd <<= (dp >> 9) & 3;
+       if (dp & 0x100) {
+               uae_s32 outer = 0;
+               if (dp & 0x80) base = 0;
+               if (dp & 0x40) regd = 0;
+
+               if ((dp & 0x30) == 0x20)
+                       base += (uae_s32)(uae_s16)next_iword_cache040();
+               if ((dp & 0x30) == 0x30)
+                       base += next_ilong_cache040();
+
+               if ((dp & 0x3) == 0x2)
+                       outer = (uae_s32)(uae_s16)next_iword_cache040();
+               if ((dp & 0x3) == 0x3)
+                       outer = next_ilong_cache040();
+
+               if ((dp & 0x4) == 0)
+                       base += regd;
+               if (dp & 0x3)
+                       base = x_get_long(base);
+               if (dp & 0x4)
+                       base += regd;
+
+               return base + outer;
+       }
+       else {
+               return base + (uae_s32)((uae_s8)dp) + regd;
+       }
+}
 
 /*
 * Compute exact number of CPU cycles taken
index 25bc03cf2bc1d1873c78a4b4f32dbf609c78c12a..7fa9f89b74e54d7bd7149de3b4c04854fbd1f835 100644 (file)
@@ -1111,7 +1111,7 @@ static int hdf_write_2 (struct hardfiledata *hfd, void *buffer, uae_u64 offset,
                if (offset == 0) {
                        if (!hfd->handle->firstwrite && (hfd->flags & HFD_FLAGS_REALDRIVE) && !(hfd->flags & HFD_FLAGS_REALDRIVEPARTITION)) {
                                hfd->handle->firstwrite = true;
-                               if (ismounted (hfd->device_name, hfd->handle->h)) {
+                               if (ismounted (hfd->ci.devname, hfd->handle->h)) {
                                        gui_message (_T("\"%s\"\n\nBlock zero write attempt but drive has one or more mounted PC partitions or WinUAE does not have Administrator privileges. Erase the drive or unmount all PC partitions first."), name);
                                        hfd->ci.readonly = true;
                                        return 0;
index 8b93ed9350b37c79621d743f25f1b23f5fe8d76e..d7cb7885c789e29b8c9e0f20432fdbafad3b0758 100644 (file)
 #define        FPCR_PRECISION_DOUBLE   0x00000080
 #define FPCR_PRECISION_EXTENDED        0x00000000
 
+extern void to_single(fpdata *fpd, uae_u32 value);
+extern void to_double(fpdata *fpd, uae_u32 wrd1, uae_u32 wrd2);
+extern void to_exten(fpdata *fpd, uae_u32 wrd1, uae_u32 wrd2, uae_u32 wrd3);
+
 STATIC_INLINE void exten_zeronormalize(uae_u32 *pwrd1, uae_u32 *pwrd2, uae_u32 *pwrd3)
 {
        uae_u32 wrd1 = *pwrd1;
@@ -35,7 +39,7 @@ STATIC_INLINE void exten_zeronormalize(uae_u32 *pwrd1, uae_u32 *pwrd2, uae_u32 *
 }
 
 #if USE_LONG_DOUBLE
-STATIC_INLINE void to_exten(fpdata *dst, uae_u32 wrd1, uae_u32 wrd2, uae_u32 wrd3)
+STATIC_INLINE void to_exten_x(fptype *fp, uae_u32 wrd1, uae_u32 wrd2, uae_u32 wrd3)
 {
        // force correct long double alignment
        union
@@ -49,14 +53,14 @@ STATIC_INLINE void to_exten(fpdata *dst, uae_u32 wrd1, uae_u32 wrd2, uae_u32 wrd
        uld.longarray[1] = wrd2;
        uld.longarray[2] = wrd1 >> 16;
        long double *longdoublewords = (long double *)uld.longarray;
-       dst->fp = *longdoublewords;
+       *fp = *longdoublewords;
 }
 #define HAVE_to_exten
 
-STATIC_INLINE void from_exten(fpdata *src, uae_u32 * wrd1, uae_u32 * wrd2, uae_u32 * wrd3)
+STATIC_INLINE void from_exten_x(fptype fp, uae_u32 * wrd1, uae_u32 * wrd2, uae_u32 * wrd3)
 {
-       uae_u32 *longarray = (uae_u32 *)&src->fp;
-       uae_u16 *finalword = (uae_u16 *)(((uae_u8*)&src->fp) + 8);
+       uae_u32 *longarray = (uae_u32 *)&fp;
+       uae_u16 *finalword = (uae_u16 *)(((uae_u8*)&fp) + 8);
 
        *wrd1 = finalword[0] << 16;
        *wrd2 = longarray[1];
@@ -68,7 +72,7 @@ STATIC_INLINE void from_exten(fpdata *src, uae_u32 * wrd1, uae_u32 * wrd2, uae_u
 #if defined(X86_MSVC_ASSEMBLY_FPU)
 #ifndef HAVE_to_single
 #define HAVE_to_single
-STATIC_INLINE double to_single (uae_u32 longvalue)
+STATIC_INLINE double to_single_x (uae_u32 longvalue)
 {
        double floatfake;
 
@@ -82,7 +86,7 @@ STATIC_INLINE double to_single (uae_u32 longvalue)
 
 #ifndef HAVE_from_single
 #define HAVE_from_single
-STATIC_INLINE uae_u32 from_single (double floatfake)
+STATIC_INLINE uae_u32 from_single_x (double floatfake)
 {
        uae_u32 longvalue;
 
@@ -96,7 +100,7 @@ STATIC_INLINE uae_u32 from_single (double floatfake)
 
 #ifndef HAVE_to_exten
 #define HAVE_to_exten
-STATIC_INLINE void to_exten(fpdata *fpd, uae_u32 wrd1, uae_u32 wrd2, uae_u32 wrd3)
+STATIC_INLINE void to_exten_x(fptype *fp, uae_u32 wrd1, uae_u32 wrd2, uae_u32 wrd3)
 {
        uae_u32 longarray[3];
        double  extenfake;
@@ -110,46 +114,32 @@ STATIC_INLINE void to_exten(fpdata *fpd, uae_u32 wrd1, uae_u32 wrd2, uae_u32 wrd
                fld tbyte ptr longarray;
                fstp qword ptr extenfake;
        }
-       fpd->fp = extenfake;
-#ifdef USE_SOFT_LONG_DOUBLE
-       fpd->fpe = ((uae_u64)wrd2 << 32) | wrd3;
-       fpd->fpm = wrd1;
-       fpd->fpx = true;
-#endif
+       *fp = extenfake;
 }
 #endif
 
 #ifndef HAVE_from_exten
 #define HAVE_from_exten
-STATIC_INLINE void from_exten(fpdata *fpd, uae_u32 * wrd1, uae_u32 * wrd2, uae_u32 * wrd3)
+STATIC_INLINE void from_exten_x(fptype fp, uae_u32 * wrd1, uae_u32 * wrd2, uae_u32 * wrd3)
 {
-#ifdef USE_SOFT_LONG_DOUBLE
-       if (fpd->fpx) {
-               *wrd1 = fpd->fpm;
-               *wrd2 = fpd->fpe >> 32;
-               *wrd3 = (uae_u32)fpd->fpe;
-       } else
-#endif
-       {
-               fptype src = fpd->fp;
-               uae_u32 longarray[3], *srcarray = (uae_u32 *)&src;
-               __asm {
-                       fld qword ptr src;
-                       fstp tbyte ptr longarray;
-               }
-               *wrd1 = (longarray[2] & 0xffff) <<16;
-               *wrd2 =  longarray[1];
-               *wrd3 =  longarray[0]; // little endian
-               if (!srcarray[0] && (srcarray[1] == 0x7ff00000 || srcarray[1] == 0xfff00000))
-                       *wrd2 = 0; // The MSB of the mantissa was set wrongly for infinity, causing a NaN
+       fptype src = fp;
+       uae_u32 longarray[3], *srcarray = (uae_u32 *)&src;
+       __asm {
+               fld qword ptr src;
+               fstp tbyte ptr longarray;
        }
+       *wrd1 = (longarray[2] & 0xffff) <<16;
+       *wrd2 =  longarray[1];
+       *wrd3 =  longarray[0]; // little endian
+       if (!srcarray[0] && (srcarray[1] == 0x7ff00000 || srcarray[1] == 0xfff00000))
+               *wrd2 = 0; // The MSB of the mantissa was set wrongly for infinity, causing a NaN
 }
 #endif
 #endif /* X86_MSVC_ASSEMBLY */
 
 #ifndef HAVE_to_single
 #define HAVE_to_single
-STATIC_INLINE double to_single (uae_u32 value)
+STATIC_INLINE double to_single_x (uae_u32 value)
 {
        union {
                float f;
@@ -163,7 +153,7 @@ STATIC_INLINE double to_single (uae_u32 value)
 
 #ifndef HAVE_from_single
 #define HAVE_from_single
-STATIC_INLINE uae_u32 from_single (double src)
+STATIC_INLINE uae_u32 from_single_x (double src)
 {
        union {
                float f;
@@ -177,7 +167,7 @@ STATIC_INLINE uae_u32 from_single (double src)
 
 #ifndef HAVE_to_double
 #define HAVE_to_double
-STATIC_INLINE double to_double(uae_u32 wrd1, uae_u32 wrd2)
+STATIC_INLINE double to_double_x(uae_u32 wrd1, uae_u32 wrd2)
 {
        union {
                double d;
@@ -192,7 +182,7 @@ STATIC_INLINE double to_double(uae_u32 wrd1, uae_u32 wrd2)
 
 #ifndef HAVE_from_double
 #define HAVE_from_double
-STATIC_INLINE void from_double(double src, uae_u32 * wrd1, uae_u32 * wrd2)
+STATIC_INLINE void from_double_x(double src, uae_u32 * wrd1, uae_u32 * wrd2)
 {
        uae_u32 *longarray = (uae_u32 *)&src;
 
@@ -204,65 +194,50 @@ STATIC_INLINE void from_double(double src, uae_u32 * wrd1, uae_u32 * wrd2)
 static const double twoto32 = 4294967296.0;
 #ifndef HAVE_to_exten
 #define HAVE_to_exten
-STATIC_INLINE void to_exten(fpdata *fpd, uae_u32 wrd1, uae_u32 wrd2, uae_u32 wrd3)
+STATIC_INLINE void to_exten_x(fptype *fp, uae_u32 wrd1, uae_u32 wrd2, uae_u32 wrd3)
 {
        double frac;
-
-#ifdef USE_SOFT_LONG_DOUBLE
-       fpd->fpe = ((uae_u64)wrd2 << 32) | wrd3;
-       fpd->fpm = wrd1;
-       fpd->fpx = true;
-#endif
        exten_zeronormalize(&wrd1, &wrd2, &wrd3);
        if ((wrd1 & 0x7fff0000) == 0 && wrd2 == 0 && wrd3 == 0) {
-               fpd->fp = (wrd1 & 0x80000000) ? -0.0 : +0.0;
+               *fp = (wrd1 & 0x80000000) ? -0.0 : +0.0;
                return;
        }
        frac = ((double)wrd2 + ((double)wrd3 / twoto32)) / 2147483648.0;
        if (wrd1 & 0x80000000)
                frac = -frac;
-       fpd->fp = ldexp (frac, ((wrd1 >> 16) & 0x7fff) - 16383);
+       *fp = ldexp (frac, ((wrd1 >> 16) & 0x7fff) - 16383);
 }
 #endif
 
 #ifndef HAVE_from_exten
 #define HAVE_from_exten
-STATIC_INLINE void from_exten(fpdata *fpd, uae_u32 * wrd1, uae_u32 * wrd2, uae_u32 * wrd3)
+STATIC_INLINE void from_exten_x(fptype fp, uae_u32 * wrd1, uae_u32 * wrd2, uae_u32 * wrd3)
 {
        int expon;
        double frac;
        fptype v;
 
-#ifdef USE_SOFT_LONG_DOUBLE
-       if (fpd->fpx) {
-               *wrd1 = fpd->fpm;
-               *wrd2 = fpd->fpe >> 32;
-               *wrd3 = (uae_u32)fpd->fpe;
-       } else
-#endif
-       {
-               v = fpd->fp;
-               if (v == 0.0) {
-                       *wrd1 = signbit(v) ? 0x80000000 : 0;
-                       *wrd2 = 0;
-                       *wrd3 = 0;
-                       return;
-               }
-               if (v < 0) {
-                       *wrd1 = 0x80000000;
-                       v = -v;
-               } else {
-                       *wrd1 = 0;
-               }
-               frac = frexp (v, &expon);
-               frac += 0.5 / (twoto32 * twoto32);
-               if (frac >= 1.0) {
-                       frac /= 2.0;
-                       expon++;
-               }
-               *wrd1 |= (((expon + 16383 - 1) & 0x7fff) << 16);
-               *wrd2 = (uae_u32) (frac * twoto32);
-               *wrd3 = (uae_u32) ((frac * twoto32 - *wrd2) * twoto32);
+       v = fp;
+       if (v == 0.0) {
+               *wrd1 = signbit(v) ? 0x80000000 : 0;
+               *wrd2 = 0;
+               *wrd3 = 0;
+               return;
+       }
+       if (v < 0) {
+               *wrd1 = 0x80000000;
+               v = -v;
+       } else {
+               *wrd1 = 0;
+       }
+       frac = frexp (v, &expon);
+       frac += 0.5 / (twoto32 * twoto32);
+       if (frac >= 1.0) {
+               frac /= 2.0;
+               expon++;
        }
+       *wrd1 |= (((expon + 16383 - 1) & 0x7fff) << 16);
+       *wrd2 = (uae_u32) (frac * twoto32);
+       *wrd3 = (uae_u32) ((frac * twoto32 - *wrd2) * twoto32);
 }
 #endif
index e3d3c71ead97c73eee16e84a16c9f407cedbad86..de26a45c17dd122149f9d63a7b0d10741de5a3d2 100644 (file)
@@ -588,10 +588,13 @@ void *shmat (int shmid, void *shmaddr, int shmflg)
                        if (!a3000hmem_bank.start)
                                size += BARRIER;
                        got = TRUE;
-               } else if(!_tcscmp (shmids[shmid].name, _T("ramsey_high"))) {
-                       shmaddr=natmem_offset + a3000hmem_bank.start;
+               } else if (!_tcscmp(shmids[shmid].name, _T("cyberstorm"))) {
+                       shmaddr = natmem_offset + 0x0c000000;
                        got = TRUE;
-               } else if(!_tcscmp (shmids[shmid].name, _T("z3"))) {
+               } else if (!_tcscmp(shmids[shmid].name, _T("cyberstormmaprom"))) {
+                       shmaddr = natmem_offset + 0xfff00000;
+                       got = TRUE;
+               } else if (!_tcscmp(shmids[shmid].name, _T("z3"))) {
                        shmaddr=natmem_offset + z3fastmem_bank.start;
                        if (!currprefs.z3fastmem2_size)
                                size += BARRIER;
index 582f25c859f5981dee0682a1b992abd80aada06c..e3b2a454ccf7bfe543f43faf5bff33f64123a1cb 100644 (file)
@@ -204,9 +204,9 @@ BEGIN
     EDITTEXT        IDC_FASTRAM2,326,196,40,12,ES_CENTER | ES_READONLY
     CONTROL         "JIT Direct compatible Z3 memory mapping",IDC_Z3REALMAPPING,
                     "Button",BS_AUTOCHECKBOX | WS_TABSTOP,180,220,186,10
-    COMBOBOX        IDC_CPUBOARD_TYPE,25,257,89,75,CBS_DROPDOWNLIST | WS_VSCROLL | WS_TABSTOP
+    COMBOBOX        IDC_CPUBOARD_TYPE,8,257,117,75,CBS_DROPDOWNLIST | WS_VSCROLL | WS_TABSTOP
     RTEXT           "Second Z2 Fast RAM board:",IDC_STATIC,129,194,116,15,SS_CENTERIMAGE
-    RTEXT           "Accelerator board memory:",IDC_STATIC,129,257,116,15,SS_CENTERIMAGE
+    RTEXT           "Accelerator board memory:",IDC_STATIC,138,257,104,15,SS_CENTERIMAGE
     CONTROL         "",IDC_CPUBOARDMEM,"msctls_trackbar32",TBS_AUTOTICKS | TBS_TOP | WS_TABSTOP,251,253,68,20
     EDITTEXT        IDC_CPUBOARDRAM,326,256,40,12,ES_CENTER | ES_READONLY
     CTEXT           "Accelerator board emulation is not JIT Direct compatible.",IDC_STATIC,25,238,341,15,SS_CENTERIMAGE
index e4633b64d90b68abbb5adaa30ea7b99e99a2af45..002bee096d2a2b1c570c340e40d2246bcc0d368a 100644 (file)
@@ -385,9 +385,9 @@ static void serdatcopy(void)
                per = ((serper & 0x7fff) + 1) * (bits - 1);
                if (lastbitcycle_active_hsyncs) {
                        // if last bit still transmitting, add remaining time.
-                       int extraper = (lastbitcycle - get_cycles()) / CYCLE_UNIT;
+                       int extraper = lastbitcycle - get_cycles();
                        if (extraper > 0)
-                               per += extraper;
+                               per += extraper / CYCLE_UNIT;
                }
                if (per < 4)
                        per = 4;
index de9d344d36ea6df803bea7856780cbfeb10e482b..6b5638f703a1b9b5581e6395f33db68ac89ad0a0 100644 (file)
@@ -11,6 +11,8 @@
 #include "picasso96_win.h"
 #include "win32gfx.h"
 #include "statusline.h"
+#include "gui.h"
+#include "xwin.h"
 
 static HDC statusline_hdc;
 static HBITMAP statusline_bitmap;
@@ -112,22 +114,32 @@ void statusline_render(uae_u8 *buf, int bpp, int pitch, int width, int height, u
        uae_u32 white = rc[0xff] | gc[0xff] | bc[0xff] | (alpha ? alpha[0xff] : 0);
        uae_u32 back = rc[0x00] | gc[0x00] | bc[0x00] | (alpha ? alpha[0xa0] : 0);
        const TCHAR *text;
-       int y = -1;
-       int x = 10;
+       int y = -1, x = 10, textwidth = 0;
+       int bar_xstart;
 
-       if (currprefs.gf[WIN32GFX_IsPicassoScreen()].gfx_filter == 0)
+       if (currprefs.gf[WIN32GFX_IsPicassoScreen()].gfx_filter == 0 && !currprefs.gfx_api)
                return;
        text = statusline_fetch();
        //text = _T("Testing string 123!");
        if (!text)
                return;
        BitBlt(statusline_hdc, 0, 0, statusline_width, statusline_height, NULL, 0, 0, BLACKNESS);
-#if 0
+
        SIZE size;
        if (GetTextExtentPoint32(statusline_hdc, text, _tcslen(text), &size)) {
-               int w = size.cx;
+               textwidth = size.cx;
+               if (isfullscreen()) {
+                       if (td_pos & TD_RIGHT) {
+                               bar_xstart = width - TD_PADX - VISIBLE_LEDS * TD_WIDTH;
+                               x = bar_xstart - textwidth - TD_LED_WIDTH;
+                       } else {
+                               bar_xstart = TD_PADX;
+                               x = bar_xstart + textwidth + TD_LED_WIDTH;
+                       }
+               }
        }
-#endif
+       if (x < 0)
+               x = 0;
        TextOut(statusline_hdc, x, y, text, _tcslen(text));
 
        for (int y = 0; y < height && y < statusline_height; y++) {
index 9396ab1ae125f8e255e99c2a4b2c824788e3bc89..37dd182fa02701bd1dccadc37e3a04fe63e63ac3 100644 (file)
@@ -47,7 +47,7 @@
 #define UAESERIAL /* uaeserial.device emulation */
 #define FPUEMU /* FPU emulation */
 #define FPU_UAE
-#define USE_LONG_DOUBLE 0
+#define WITH_SOFTFLOAT
 #define MMUEMU /* Aranym 68040 MMU */
 #define FULLMMU /* Aranym 68040 MMU */
 #define CPUEMU_0 /* generic 680x0 emulation */
@@ -55,7 +55,8 @@
 #define CPUEMU_13 /* 68000/68010 cycle-exact cpu&blitter */
 #define CPUEMU_20 /* 68020 prefetch */
 #define CPUEMU_21 /* 68020 "cycle-exact" + blitter */
-#define CPUEMU_22 /* 68030 (040/060) "cycle-exact" + blitter */
+#define CPUEMU_22 /* 68030 "cycle-exact" + blitter */
+#define CPUEMU_23 /* 68040/060 "cycle-exact" + blitter */
 #define CPUEMU_31 /* Aranym 68040 MMU */
 #define CPUEMU_32 /* Previous 68030 MMU */
 #define CPUEMU_33 /* 68060 MMU */
index 56bf8b6641d780e2447904f28c5791fbbb32e83b..6da4505208544920565176697cb251314633e307 100644 (file)
 #define LANG_DLL_FULL_VERSION_MATCH 1
 
 #if WINUAEPUBLICBETA
-#define WINUAEBETA _T("4")
+#define WINUAEBETA _T("5")
 #else
 #define WINUAEBETA _T("")
 #endif
 
-#define WINUAEDATE MAKEBD(2014, 7, 20)
+#define WINUAEDATE MAKEBD(2014, 7, 25)
 
 //#define WINUAEEXTRA _T("AmiKit Preview")
 //#define WINUAEEXTRA _T("Amiga Forever Edition")
index 92e1442761a7673695b41227340aaaee78d9ac49..de7827d8c0d14970ce8104c970e86ed0535881d3 100644 (file)
@@ -4222,7 +4222,7 @@ void InitializeListView (HWND hDlg)
                                        _T("A3000:%s"),
                                        _T("A4000T:%s"),
                                        _T("CDTV:%s"),
-                                       _T("WarpEngine:%s")
+                                       _T("Accelerator:%s")
                                };
                                if (ci->controller_unit == 7 && (ctype == HD_CONTROLLER_TYPE_SCSI_A2091 || ctype == HD_CONTROLLER_TYPE_SCSI_A2091_2))
                                        _tcscpy(sid, _T("XT"));
@@ -7659,6 +7659,7 @@ static void values_to_memorydlg (HWND hDlg)
        case 0x02000000: mem_size = 6; break;
        case 0x04000000: mem_size = 7; break;
        case 0x08000000: mem_size = 8; break;
+       case 0x10000000: mem_size = 9; break;
        }
        SendDlgItemMessage (hDlg, IDC_CPUBOARDMEM, TBM_SETPOS, TRUE, mem_size);
        SetDlgItemText (hDlg, IDC_CPUBOARDRAM, memsize_names[msi_gfx[mem_size]]);
@@ -8154,8 +8155,11 @@ static INT_PTR CALLBACK MemoryDlgProc (HWND hDlg, UINT msg, WPARAM wParam, LPARA
                SendDlgItemMessage (hDlg, IDC_CPUBOARD_TYPE, CB_ADDSTRING, 0, (LPARAM)_T("-"));
                SendDlgItemMessage (hDlg, IDC_CPUBOARD_TYPE, CB_ADDSTRING, 0, (LPARAM)_T("Blizzard 1230 IV"));
                SendDlgItemMessage (hDlg, IDC_CPUBOARD_TYPE, CB_ADDSTRING, 0, (LPARAM)_T("Blizzard 1260"));
-               SendDlgItemMessage (hDlg, IDC_CPUBOARD_TYPE, CB_ADDSTRING, 0, (LPARAM)_T("Blizzard 2060 (Do not use)"));
-               SendDlgItemMessage (hDlg, IDC_CPUBOARD_TYPE, CB_ADDSTRING, 0, (LPARAM)_T("Warp Engine A4000"));
+               SendDlgItemMessage(hDlg, IDC_CPUBOARD_TYPE, CB_ADDSTRING, 0, (LPARAM)_T("Blizzard 2060 (Do not use)"));
+               SendDlgItemMessage(hDlg, IDC_CPUBOARD_TYPE, CB_ADDSTRING, 0, (LPARAM)_T("CyberStorm MK III"));
+               SendDlgItemMessage(hDlg, IDC_CPUBOARD_TYPE, CB_ADDSTRING, 0, (LPARAM)_T("CyberStorm PPC (NO PPC CPU!)"));
+               SendDlgItemMessage(hDlg, IDC_CPUBOARD_TYPE, CB_ADDSTRING, 0, (LPARAM)_T("Blizzard PPC (NO PPC CPU!)"));
+               SendDlgItemMessage(hDlg, IDC_CPUBOARD_TYPE, CB_ADDSTRING, 0, (LPARAM)_T("Warp Engine A4000"));
 
        case WM_USER:
                workprefs.fastmem_autoconfig = ischecked (hDlg, IDC_FASTMEMAUTOCONFIG);
@@ -9019,9 +9023,9 @@ static void enable_for_cpudlg (HWND hDlg)
 
        ew (hDlg, IDC_SPEED, !workprefs.cpu_cycle_exact);
        ew (hDlg, IDC_COMPATIBLE24, workprefs.cpu_model == 68020);
-       ew (hDlg, IDC_CS_HOST, !workprefs.cpu_cycle_exact);
-       ew (hDlg, IDC_CS_68000, !workprefs.cpu_cycle_exact);
-       ew (hDlg, IDC_CS_ADJUSTABLE, !workprefs.cpu_cycle_exact);
+       //ew (hDlg, IDC_CS_HOST, !workprefs.cpu_cycle_exact);
+       //ew (hDlg, IDC_CS_68000, !workprefs.cpu_cycle_exact);
+       //ew (hDlg, IDC_CS_ADJUSTABLE, !workprefs.cpu_cycle_exact);
        ew (hDlg, IDC_CPUIDLE, workprefs.m68k_speed != 0 ? TRUE : FALSE);
 #if !defined(CPUEMU_0) || defined(CPUEMU_68000_ONLY)
        ew (hDlg, IDC_CPU1, FALSE);
@@ -9168,8 +9172,8 @@ static void values_from_cpudlg (HWND hDlg)
                if (workprefs.cpu_compatible || workprefs.cpu_cycle_exact)
                        workprefs.fpu_model = 0;
                workprefs.address_space_24 = 1;
-               if (newcpu == 0 && workprefs.cpu_cycle_exact)
-                       workprefs.m68k_speed = 0;
+//             if (newcpu == 0 && workprefs.cpu_cycle_exact)
+//                     workprefs.m68k_speed = 0;
                break;
        case 68020:
                workprefs.fpu_model = newfpu == 0 ? 0 : (newfpu == 2 ? 68882 : 68881);
@@ -10099,8 +10103,8 @@ static void inithdcontroller (HWND hDlg, int ctype, int devtype)
        SendDlgItemMessage (hDlg, IDC_HDF_CONTROLLER, CB_ADDSTRING, 0, (LPARAM)_T("A3000 SCSI"));
        SendDlgItemMessage (hDlg, IDC_HDF_CONTROLLER, CB_ADDSTRING, 0, (LPARAM)_T("A4000T SCSI"));
        SendDlgItemMessage (hDlg, IDC_HDF_CONTROLLER, CB_ADDSTRING, 0, (LPARAM)_T("CDTV SCSI"));
-       SendDlgItemMessage (hDlg, IDC_HDF_CONTROLLER, CB_ADDSTRING, 0, (LPARAM)_T("Warp Engine SCSI"));
-       SendDlgItemMessage (hDlg, IDC_HDF_CONTROLLER, CB_ADDSTRING, 0, (LPARAM)_T("PCMCIA SRAM"));
+       SendDlgItemMessage(hDlg, IDC_HDF_CONTROLLER, CB_ADDSTRING, 0, (LPARAM)_T("Accelerator board SCSI"));
+       SendDlgItemMessage(hDlg, IDC_HDF_CONTROLLER, CB_ADDSTRING, 0, (LPARAM)_T("PCMCIA SRAM"));
        SendDlgItemMessage (hDlg, IDC_HDF_CONTROLLER, CB_ADDSTRING, 0, (LPARAM)_T("PCMCIA IDE"));
        SendDlgItemMessage (hDlg, IDC_HDF_CONTROLLER, CB_SETCURSEL, ctype, 0);
 
index 404b20e4678e56f02ed76aeb9584fb6e65c2377d..6d07e2d18472b5873a7a1cca2a784dac276f0f55 100644 (file)
       <Culture>0x0409</Culture>
     </ResourceCompile>
     <Link>
-      <AdditionalDependencies>ws2_32.lib;ddraw.lib;dxguid.lib;winmm.lib;comctl32.lib;version.lib;msacm32.lib;dsound.lib;dinput8.lib;d3d9.lib;d3dx9.lib;winio.lib;setupapi.lib;wininet.lib;dxerr.lib;shlwapi.lib;libpng15.lib;lglcd.lib;wpcap.lib;packet.lib;openal32.lib;portaudio_x86.lib;vfw32.lib;wtsapi32.lib;enet.lib;lzmalib.lib;prowizard.lib;libFLAC_static.lib;Avrt.lib;hid.lib;zlibstat.lib;Iphlpapi.lib;luastatic.lib;libmpeg2_ff.lib;%(AdditionalDependencies)</AdditionalDependencies>
+      <AdditionalDependencies>ws2_32.lib;ddraw.lib;dxguid.lib;winmm.lib;comctl32.lib;version.lib;msacm32.lib;dsound.lib;dinput8.lib;d3d9.lib;d3dx9.lib;winio.lib;setupapi.lib;wininet.lib;dxerr.lib;shlwapi.lib;libpng15.lib;lglcd.lib;wpcap.lib;packet.lib;openal32.lib;portaudio_x86.lib;vfw32.lib;wtsapi32.lib;enet.lib;lzmalib.lib;prowizard.lib;libFLAC_static.lib;Avrt.lib;hid.lib;zlibstat.lib;Iphlpapi.lib;luastatic.lib;libmpeg2_ff.lib;softfloat.lib;%(AdditionalDependencies)</AdditionalDependencies>
       <OutputFile>$(OutDir)$(TargetName)$(TargetExt)</OutputFile>
       <SuppressStartupBanner>true</SuppressStartupBanner>
       <AdditionalLibraryDirectories>%(AdditionalLibraryDirectories);$(SolutionDir)\..\lib\</AdditionalLibraryDirectories>
       <Culture>0x0409</Culture>
     </ResourceCompile>
     <Link>
-      <AdditionalDependencies>ws2_32.lib;ddraw.lib;dxguid.lib;winmm.lib;comctl32.lib;version.lib;msacm32.lib;dsound.lib;dinput8.lib;d3d9.lib;d3dx9.lib;winio.lib;setupapi.lib;wininet.lib;dxerr.lib;shlwapi.lib;libpng15.lib;lglcd.lib;wpcap.lib;packet.lib;openal32.lib;portaudio_x86.lib;vfw32.lib;wtsapi32.lib;enet.lib;lzmalib.lib;prowizard.lib;libFLAC_static.lib;Avrt.lib;hid.lib;zlibstat.lib;Iphlpapi.lib;luastatic.lib;libmpeg2_ff.lib;%(AdditionalDependencies)</AdditionalDependencies>
+      <AdditionalDependencies>ws2_32.lib;ddraw.lib;dxguid.lib;winmm.lib;comctl32.lib;version.lib;msacm32.lib;dsound.lib;dinput8.lib;d3d9.lib;d3dx9.lib;winio.lib;setupapi.lib;wininet.lib;dxerr.lib;shlwapi.lib;libpng15.lib;lglcd.lib;wpcap.lib;packet.lib;openal32.lib;portaudio_x86.lib;vfw32.lib;wtsapi32.lib;enet.lib;lzmalib.lib;prowizard.lib;libFLAC_static.lib;Avrt.lib;hid.lib;zlibstat.lib;Iphlpapi.lib;luastatic.lib;libmpeg2_ff.lib;softfloat.lib;%(AdditionalDependencies)</AdditionalDependencies>
       <OutputFile>$(OutDir)$(TargetName)$(TargetExt)</OutputFile>
       <SuppressStartupBanner>true</SuppressStartupBanner>
       <AdditionalLibraryDirectories>%(AdditionalLibraryDirectories);$(SolutionDir)\..\lib\</AdditionalLibraryDirectories>
       <Culture>0x0409</Culture>
     </ResourceCompile>
     <Link>
-      <AdditionalDependencies>ws2_32.lib;ddraw.lib;dxguid.lib;winmm.lib;comctl32.lib;version.lib;msacm32.lib;dsound.lib;dinput8.lib;d3d9.lib;d3dx9.lib;winio.lib;setupapi.lib;wininet.lib;dxerr.lib;shlwapi.lib;zlibstat.lib;libpng15.lib;lglcd.lib;wpcap.lib;packet.lib;openal32.lib;portaudio_x86.lib;vfw32.lib;wtsapi32.lib;avrt.lib;enet.lib;prowizard.lib;lzmalib.lib;libFLAC_static.lib;Avrt.lib;hid.lib;Iphlpapi.lib;luastatic.lib;libmpeg2_ff.lib;%(AdditionalDependencies)</AdditionalDependencies>
+      <AdditionalDependencies>ws2_32.lib;ddraw.lib;dxguid.lib;winmm.lib;comctl32.lib;version.lib;msacm32.lib;dsound.lib;dinput8.lib;d3d9.lib;d3dx9.lib;winio.lib;setupapi.lib;wininet.lib;dxerr.lib;shlwapi.lib;zlibstat.lib;libpng15.lib;lglcd.lib;wpcap.lib;packet.lib;openal32.lib;portaudio_x86.lib;vfw32.lib;wtsapi32.lib;avrt.lib;enet.lib;prowizard.lib;lzmalib.lib;libFLAC_static.lib;Avrt.lib;hid.lib;Iphlpapi.lib;luastatic.lib;libmpeg2_ff.lib;softfloat.lib;%(AdditionalDependencies)</AdditionalDependencies>
       <OutputFile>$(OutDir)$(TargetName)$(TargetExt)</OutputFile>
       <SuppressStartupBanner>true</SuppressStartupBanner>
       <AdditionalLibraryDirectories>%(AdditionalLibraryDirectories);$(SolutionDir)\..\lib\</AdditionalLibraryDirectories>
     <ClCompile Include="..\..\cpuemu_13.cpp" />
     <ClCompile Include="..\..\cpuemu_21.cpp" />
     <ClCompile Include="..\..\cpuemu_22.cpp" />
+    <ClCompile Include="..\..\cpuemu_23.cpp" />
     <ClCompile Include="..\..\cpuemu_32.cpp" />
     <ClCompile Include="..\..\cpuemu_33.cpp" />
     <ClCompile Include="..\..\cpummu30.cpp" />
     <ClCompile Include="..\..\ethernet.cpp" />
     <ClCompile Include="..\..\events.cpp" />
+    <ClCompile Include="..\..\flashrom.cpp" />
     <ClCompile Include="..\..\gfxboard.cpp" />
     <ClCompile Include="..\..\hrtmon.rom.cpp" />
     <ClCompile Include="..\..\inputrecord.cpp" />
     <ClCompile Include="..\..\luascript.cpp" />
     <ClCompile Include="..\..\newcpu_common.cpp" />
     <ClCompile Include="..\..\qemuvga\cirrus_vga.cpp" />
+    <ClCompile Include="..\..\qemuvga\lsi53c710.cpp" />
     <ClCompile Include="..\..\qemuvga\lsi53c895a.cpp" />
     <ClCompile Include="..\..\qemuvga\qemuuaeglue.cpp" />
     <ClCompile Include="..\..\qemuvga\vga.cpp" />
index 3fb0ad54aff0cc2f8a20523ccfc8fdac2296021d..72f3243b022ce438f678ffedab36285623498aef 100644 (file)
     <ClCompile Include="..\statusline_win32.cpp">
       <Filter>win32</Filter>
     </ClCompile>
+    <ClCompile Include="..\..\cpuemu_23.cpp">
+      <Filter>common</Filter>
+    </ClCompile>
+    <ClCompile Include="..\..\flashrom.cpp">
+      <Filter>common</Filter>
+    </ClCompile>
+    <ClCompile Include="..\..\qemuvga\lsi53c710.cpp">
+      <Filter>qemu</Filter>
+    </ClCompile>
   </ItemGroup>
   <ItemGroup>
     <None Include="..\resources\35floppy.ico">
index 96d0d017212bae807ca466a0772c012df1561c3e..bff519e62904e7762fff3a6452ac03d10eb37af7 100644 (file)
@@ -18,6 +18,53 @@ Things that may happen in 2015:
 
 - restore only single input target to default.
 
+- New statusline showed disk eject messages even if drive was already empty.
+- Added optional FPU emulation that uses softfloat library, another feature not for normal use.
+  Full 80-bit FP accuracy, bit-perfect results (not including trigonometric functions), supports FPU
+  arithmetic exceptions, much slower (Uses integer algorithms, host FPU is not used).
+- 270b6 "JIT MOVEM used direct mode if memory was direct capable but direct mode was disabled." was wrong
+  fix, original code probably was done to work around some JIT indirect bug.. (AmiKit crash during boot
+  if JIT is in indirect mode)
+
+
+Beta 4:
+
+- Added Blizzard 1230-IV and Blizzard 1260 board options. Do not use if you only want to run
+  WB and other programs, it is not JIT direct compatible due to memory address space aliasing.
+  Only emulates memory layout (which is Blizzard unique), matching CPU is not 100% required if you want to try
+  weird configs. Map ROM is also emulated, old map rom checkbox in ROM panel enables Blizzard hardware maprom
+  if Blizzard board is selected. Requires matching Blizzard flash ROM images. (Only difference between 1230IV
+  and 1240/1260 is slightly different boot rom, hardware ram addresses appear to be exact same)
+  Mostly useless, mainly meant to help development and testing. (Useful for aros m68k testing for me at least)
+- Added Warp Engine board emulation (It has already emulated 53C710 SCSI), autoconfig works, ROM code runs,
+  SCSI (53C710) does not work yet, not yet sure how jumpers are mapped to board address space.
+- Really fixed CD32 data track checks. (CD32 Commodore Demo Disc 2.0 MPEG tracks)
+- Disk Swapper panel drag'n'drop or file dialog multiselect mangled file names strangely.
+- Added A590 XT drive emulation. A590 emulation is now complete :)
+  WARNING: XT drives use real physical CHS geometry, don't attempt to use hardfiles formatted using other
+  controller, it won't work in real world. (Emulation includes work around hack) Largest XT
+  drive was 40M and protocol max limit is 511 cylinders, 15 heads and 63 sectors = ~235M.
+  Both SCSI and XT drive can be active at the same time in same controller.
+  Interesting fact about ROM xt.device: It uses WD33C93 Translate Address command to convert LBA to CHS
+  which means WD33C93 chip needs to be inserted and working or XT (which has nothing to with SCSI) port
+  won't work.
+- Fixed A590/A2091 SCSI emulation crash if SCSI ID was non-zero.
+- Z3 autoconfig was broken (b1).
+- Serial port data rate register (SERPER) was not saved correctly to statefile.
+- Serial port transmit interrupt and transmit related status bits are now more accurately timed in cycle-exact
+  CPU modes. (If some software really cares, probably not)
+- Inter-process serial port emulation added, when selected, automatically creates virtual null modem cable
+  between two winuae processes. Uses shared memory, no latency. (Says "Master" in serial port selection menu
+  if WinUAE instance created shared memory and "Slave" if shared memory was already created by some other instance.
+  If nothing = something failed)
+- Added support for short text messages, appears in OSD bar's unused space and windowed mode bottom bar. Currently
+  only shows disk image eject/insert and input device autoswitch information.
+  OSD messages won't appear in following configurations: native mode + DirectDraw + no filter and RTG
+  mode + DirectDraw. (In DirectDraw mode status bar is drawn directly to target surface, erasing gets annoying
+  because it should not be read. In D3D mode it is another texture, hardware does the rest)
+- Added remove all button to Disk Swapper panel.
+- Game controllers can be now optionally kept active when winuae window is not active or minimized.
+
 Beta 3:
 
 - Selected chipset extra didn't match what dialog box shows (b2). This broke many configs..
diff --git a/qemuvga/lsi53c710.cpp b/qemuvga/lsi53c710.cpp
new file mode 100644 (file)
index 0000000..3c46995
--- /dev/null
@@ -0,0 +1,2437 @@
+/*
+ * QEMU LSI53C895A SCSI Host Bus Adapter emulation
+ *
+ * Copyright (c) 2006 CodeSourcery.
+ * Written by Paul Brook
+ *
+ * This code is licensed under the LGPL.
+ */
+
+/* Note:
+ * LSI53C810 emulation is incorrect, in the sense that it supports
+ * features added in later evolutions. This should not be a problem,
+ * as well-behaved operating systems will not try to use them.
+ */
+
+/* Hacked to support LSI53C710 for UAE by Toni Wilen */
+
+#include <assert.h>
+
+#include "qemuuaeglue.h"
+#include "queue.h"
+
+//#include "hw/hw.h"
+//#include "hw/pci/pci.h"
+#include "scsi/scsi.h"
+//#include "sysemu/dma.h"
+
+//#define DEBUG_LSI
+//#define DEBUG_LSI_REG
+
+#ifdef DEBUG_LSI
+#define DPRINTF(fmt, ...) \
+do { write_log("lsi_scsi: " fmt , ## __VA_ARGS__); } while (0)
+#define BADF(fmt, ...) \
+do { write_log("lsi_scsi: error: " fmt , ## __VA_ARGS__); } while (0)
+#else
+#define DPRINTF(fmt, ...) do {} while(0)
+#define BADF(fmt, ...) \
+do { write_log("lsi_scsi: error: " fmt , ## __VA_ARGS__); assert(false);} while (0)
+#endif
+
+#define LSI_MAX_DEVS 7
+
+#define LSI_SCNTL0_TRG    0x01
+#define LSI_SCNTL0_AAP    0x02
+#define LSI_SCNTL0_EPG    0x08
+#define LSI_SCNTL0_EPC    0x08
+#define LSI_SCNTL0_WATN   0x10,
+#define LSI_SCNTL0_START  0x20
+
+#define LSI_SCNTL1_RCV    0x01
+#define LSI_SCNTL1_SND   0x02
+#define LSI_SCNTL1_AESP   0x04
+#define LSI_SCNTL1_RST    0x08
+#define LSI_SCNTL1_CON    0x10
+#define LSI_SCNTL1_ESR    0x20
+#define LSI_SCNTL1_ADB    0x40
+#define LSI_SCNTL1_EXC    0x80
+
+#define LSI_SCNTL2_WSR    0x01
+#define LSI_SCNTL2_VUE0   0x02
+#define LSI_SCNTL2_VUE1   0x04
+#define LSI_SCNTL2_WSS    0x08
+#define LSI_SCNTL2_SLPHBEN 0x10
+#define LSI_SCNTL2_SLPMD  0x20
+#define LSI_SCNTL2_CHM    0x40
+#define LSI_SCNTL2_SDU    0x80
+
+#define LSI_ISTAT_DIP    0x01
+#define LSI_ISTAT_SIP    0x02
+//#define LSI_ISTAT0_INTF   0x04
+#define LSI_ISTAT_CON    0x08
+//#define LSI_ISTAT0_SEM    0x10
+#define LSI_ISTAT_SIGP   0x20
+#define LSI_ISTAT_RST    0x40
+#define LSI_ISTAT_ABRT   0x80
+
+#define LSI_SSTAT1_WOA    0x04
+
+#define LSI_SSTAT0_PAR    0x01
+#define LSI_SSTAT0_RST    0x02
+#define LSI_SSTAT0_UDC    0x04
+#define LSI_SSTAT0_SGE    0x08
+#define LSI_SSTAT0_SEL    0x10
+#define LSI_SSTAT0_STO    0x20
+#define LSI_SSTAT0_FCMP   0x40
+#define LSI_SSTAT0_MA     0x80
+
+//#define LSI_SIST0_PAR     0x01
+//#define LSI_SIST0_RST     0x02
+//#define LSI_SIST0_UDC     0x04
+//#define LSI_SIST0_SGE     0x08
+//#define LSI_SIST0_RSL     0x10
+//#define LSI_SIST0_SEL     0x20
+//#define LSI_SIST0_CMP     0x40
+//#define LSI_SIST0_MA      0x80
+
+//#define LSI_SIST1_HTH     0x01
+//#define LSI_SIST1_GEN     0x02
+//#define LSI_SIST1_STO     0x04
+//#define LSI_SIST1_SBMC    0x10
+
+#define LSI_SOCL_IO       0x01
+#define LSI_SOCL_CD       0x02
+#define LSI_SOCL_MSG      0x04
+#define LSI_SOCL_ATN      0x08
+#define LSI_SOCL_SEL      0x10
+#define LSI_SOCL_BSY      0x20
+#define LSI_SOCL_ACK      0x40
+#define LSI_SOCL_REQ      0x80
+
+#define LSI_DSTAT_IID     0x01
+#define LSI_DSTAT_SIR     0x04
+#define LSI_DSTAT_SSI     0x08
+#define LSI_DSTAT_ABRT    0x10
+#define LSI_DSTAT_BF      0x20
+#define LSI_DSTAT_MDPE    0x40
+#define LSI_DSTAT_DFE     0x80
+
+#define LSI_DCNTL_COM     0x01
+#define LSI_DCNTL_IRQD    0x02
+#define LSI_DCNTL_STD     0x04
+#define LSI_DCNTL_IRQM    0x08
+#define LSI_DCNTL_SSM     0x10
+#define LSI_DCNTL_PFEN    0x20
+#define LSI_DCNTL_PFF     0x40
+#define LSI_DCNTL_CLSE    0x80
+
+#define LSI_DMODE_MAN     0x01
+#define LSI_DMODE_UO      0x02
+#define LSI_DMODE_FAM     0x04
+#define LSI_DMODE_PD      0x08
+
+#define LSI_CTEST2_DACK   0x01
+#define LSI_CTEST2_DREQ   0x02
+#define LSI_CTEST2_TEOP   0x04
+#define LSI_CTEST2_PCICIE 0x08
+#define LSI_CTEST2_CM     0x10
+#define LSI_CTEST2_CIO    0x20
+#define LSI_CTEST2_SIGP   0x40
+#define LSI_CTEST2_DDIR   0x80
+
+#define LSI_CTEST5_BL2    0x04
+#define LSI_CTEST5_DDIR   0x08
+#define LSI_CTEST5_MASR   0x10
+#define LSI_CTEST5_DFSN   0x20
+#define LSI_CTEST5_BBCK   0x40
+#define LSI_CTEST5_ADCK   0x80
+
+#define LSI_CCNTL0_DILS   0x01
+#define LSI_CCNTL0_DISFC  0x10
+#define LSI_CCNTL0_ENNDJ  0x20
+#define LSI_CCNTL0_PMJCTL 0x40
+#define LSI_CCNTL0_ENPMJ  0x80
+
+#define LSI_CCNTL1_EN64DBMV  0x01
+#define LSI_CCNTL1_EN64TIBMV 0x02
+#define LSI_CCNTL1_64TIMOD   0x04
+#define LSI_CCNTL1_DDAC      0x08
+#define LSI_CCNTL1_ZMOD      0x80
+
+#define LSI_SBCL_IO  0x01
+#define LSI_SBCL_CD  0x02
+#define LSI_SBCL_MSG 0x04
+#define LSI_SBCL_ATN 0x08
+#define LSI_SBCL_SEL 0x10
+#define LSI_SBCL_BSY 0x20
+#define LSI_SBCL_ACK 0x40
+#define LSI_SBCL_REQ 0x80
+
+/* Enable Response to Reselection */
+#define LSI_SCID_RRE      0x60
+
+#define PHASE_DO          0
+#define PHASE_DI          1
+#define PHASE_CMD         2
+#define PHASE_ST          3
+#define PHASE_MO          6
+#define PHASE_MI          7
+#define PHASE_MASK        7
+
+/* Maximum length of MSG IN data.  */
+#define LSI_MAX_MSGIN_LEN 8
+
+/* Flag set if this is a tagged command.  */
+#define LSI_TAG_VALID     (1 << 16)
+
+typedef struct lsi_request {
+    SCSIRequest *req;
+    uint32_t tag;
+    uint32_t dma_len;
+    uint8_t *dma_buf;
+    uint32_t pending;
+    int out;
+    QTAILQ_ENTRY(lsi_request) next;
+} lsi_request;
+
+typedef struct {
+    /*< private >*/
+    //PCIDevice parent_obj;
+    /*< public >*/
+
+    //MemoryRegion mmio_io;
+    //MemoryRegion ram_io;
+    //MemoryRegion io_io;
+
+    int carry; /* ??? Should this be an a visible register somewhere?  */
+    int status;
+    /* Action to take at the end of a MSG IN phase.
+       0 = COMMAND, 1 = disconnect, 2 = DATA OUT, 3 = DATA IN.  */
+    int msg_action;
+    int msg_len;
+    uint8_t msg[LSI_MAX_MSGIN_LEN];
+    /* 0 if SCRIPTS are running or stopped.
+     * 1 if a Wait Reselect instruction has been issued.
+     * 2 if processing DMA from lsi_execute_script.
+     * 3 if a DMA operation is in progress.  */
+    int waiting;
+    SCSIBus bus;
+    int current_lun;
+    /* The tag is a combination of the device ID and the SCSI tag.  */
+    uint32_t select_tag;
+    int command_complete;
+    QTAILQ_HEAD(, lsi_request) queue;
+    lsi_request *current;
+
+    uint32_t dsa;
+    uint32_t temp;
+    uint32_t dnad;
+    uint32_t dbc;
+    uint8_t istat;
+    uint8_t dcmd;
+    uint8_t dstat;
+    uint8_t dien;
+//    uint8_t sist0;
+//    uint8_t sist1;
+    uint8_t sien0;
+    uint8_t ctest2;
+    uint8_t ctest3;
+    uint8_t ctest4;
+    uint8_t ctest5;
+    uint32_t dsp;
+    uint32_t dsps;
+    uint8_t dmode;
+    uint8_t dcntl;
+    uint8_t scntl0;
+    uint8_t scntl1;
+    uint8_t sstat0;
+    uint8_t sstat1;
+    uint8_t scid;
+    uint8_t sxfer;
+    uint8_t socl;
+    uint8_t sdid;
+    uint8_t sfbr;
+    uint8_t sidl;
+    uint32_t sbc;
+    uint32_t scratch;
+    uint8_t sbr;
+
+       uint8_t ctest0;
+       uint8_t ctest1;
+       uint8_t ctest6;
+       uint8_t ctest7;
+       uint8_t ctest8;
+       uint8_t lcrc;
+       uint8_t sstat2;
+       uint8_t dwt;
+       uint8_t sbcl;
+       uint8_t script_active;
+} LSIState;
+
+//#define TYPE_LSI53C810  "lsi53c810"
+//#define TYPE_LSI53C895A "lsi53c895a"
+
+#define LSI53C895A(obj) (LSIState*)obj->lsistate
+ //((LSIState*)(OBJECT_CHECK(LSIState, (obj), TYPE_LSI53C895A)))
+
+static inline int lsi_irq_on_rsl(LSIState *s)
+{
+       return 0; //return (s->sien0 & LSI_SIST0_RSL) && (s->scid & LSI_SCID_RRE);
+}
+
+static void lsi_soft_reset(LSIState *s)
+{
+    DPRINTF("Reset\n");
+    s->carry = 0;
+       memset (s, 0, sizeof LSIState);
+
+    s->msg_action = 0;
+    s->msg_len = 0;
+    s->waiting = 0;
+    s->dsa = 0;
+    s->dnad = 0;
+    s->dbc = 0;
+    s->temp = 0;
+       s->scratch = 0;
+    s->istat = 0;
+    s->dcmd = 0x40;
+    s->dstat = LSI_DSTAT_DFE;
+    s->dien = 0;
+//    s->sist0 = 0;
+//    s->sist1 = 0;
+    s->sien0 = 0;
+//    s->sien1 = 0;
+    s->ctest2 = LSI_CTEST2_DACK;
+    s->ctest3 = 0;
+    s->ctest4 = 0;
+    s->ctest5 = 0;
+    s->dsp = 0;
+    s->dsps = 0;
+    s->dmode = 0;
+    s->dcntl = 0;
+    s->scntl0 = 0xc0;
+    s->scntl1 = 0;
+    s->sstat0 = 0;
+    s->sstat1 = 0;
+       s->sstat2 = 0;
+    s->scid = 0x80;
+    s->sxfer = 0;
+    s->socl = 0;
+    s->sdid = 0;
+    s->sidl = 0;
+    s->sbc = 0;
+    s->sbr = 0;
+    assert(QTAILQ_EMPTY(&s->queue));
+    assert(!s->current);
+}
+
+#if 0
+static int lsi_dma_40bit(LSIState *s)
+{
+    if ((s->ccntl1 & LSI_CCNTL1_40BIT) == LSI_CCNTL1_40BIT)
+        return 1;
+    return 0;
+}
+
+static int lsi_dma_ti64bit(LSIState *s)
+{
+    if ((s->ccntl1 & LSI_CCNTL1_EN64TIBMV) == LSI_CCNTL1_EN64TIBMV)
+        return 1;
+    return 0;
+}
+
+static int lsi_dma_64bit(LSIState *s)
+{
+    if ((s->ccntl1 & LSI_CCNTL1_EN64DBMV) == LSI_CCNTL1_EN64DBMV)
+        return 1;
+    return 0;
+}
+#endif
+
+static uint8_t lsi_reg_readb(LSIState *s, int offset);
+static void lsi_reg_writeb(LSIState *s, int offset, uint8_t val);
+static void lsi_execute_script(LSIState *s);
+static void lsi_reselect(LSIState *s, lsi_request *p);
+
+static inline uint32_t read_dword(LSIState *s, uint32_t addr)
+{
+    uint32_t buf;
+
+       pci710_dma_read(PCI_DEVICE(s), addr, &buf, 4);
+    return cpu_to_le32(buf);
+}
+
+static void lsi_stop_script(LSIState *s)
+{
+    s->script_active = 0;
+}
+
+static void lsi_update_irq(LSIState *s)
+{
+    PCIDevice *d = PCI_DEVICE(s);
+    int level;
+    static int last_level;
+    lsi_request *p;
+
+    /* It's unclear whether the DIP/SIP bits should be cleared when the
+       Interrupt Status Registers are cleared or when istat0 is read.
+       We currently do the formwer, which seems to work.  */
+    level = 0;
+    if (s->dstat) {
+        if (s->dstat & s->dien)
+            level = 1;
+        s->istat |= LSI_ISTAT_DIP;
+    } else {
+        s->istat &= ~LSI_ISTAT_DIP;
+    }
+
+    if (s->sstat0) {
+        if ((s->sstat0 & s->sien0))
+            level = 1;
+        s->istat |= LSI_ISTAT_SIP;
+    } else {
+        s->istat &= ~LSI_ISTAT_SIP;
+    }
+
+    if (level != last_level) {
+        DPRINTF("Update IRQ level %d dstat %02x sist %02x%02x\n",
+                level, s->dstat, s->sstat0, s->sstat1);
+        last_level = level;
+    }
+    pci710_set_irq(d, level);
+
+    if (!level && lsi_irq_on_rsl(s) && !(s->scntl1 & LSI_SCNTL1_CON)) {
+        DPRINTF("Handled IRQs & disconnected, looking for pending "
+                "processes\n");
+        QTAILQ_FOREACH(p, &s->queue, next) {
+            if (p->pending) {
+                lsi_reselect(s, p);
+                break;
+            }
+        }
+    }
+}
+
+/* Stop SCRIPTS execution and raise a SCSI interrupt.  */
+static void lsi_script_scsi_interrupt(LSIState *s, int stat0)
+{
+    uint32_t mask0;
+    //uint32_t mask1;
+
+    DPRINTF("SCSI Interrupt 0x%02x%02x prev 0x%02x%02x\n",
+            stat0, s->sstat0);
+    s->sstat0 |= stat0;
+    //s->sist1 |= stat1;
+    /* Stop processor on fatal or unmasked interrupt.  As a special hack
+       we don't stop processing when raising STO.  Instead continue
+       execution and stop at the next insn that accesses the SCSI bus.  */
+    mask0 = s->sien0 | ~(LSI_SSTAT0_FCMP | LSI_SSTAT0_SEL); // | LSI_SIST1_RSL);
+    //mask1 = s->sien1 | ~(LSI_SIST1_GEN | LSI_SIST1_HTH);
+    //mask1 &= ~LSI_SIST1_STO;
+    if (s->sstat0 & mask0) { // || s->sist1 & mask1) {
+        lsi_stop_script(s);
+    }
+    lsi_update_irq(s);
+}
+
+/* Stop SCRIPTS execution and raise a DMA interrupt.  */
+static void lsi_script_dma_interrupt(LSIState *s, int stat)
+{
+    DPRINTF("DMA Interrupt 0x%x prev 0x%x\n", stat, s->dstat);
+    s->dstat |= stat;
+    lsi_update_irq(s);
+    lsi_stop_script(s);
+}
+
+static inline void lsi_set_phase(LSIState *s, int phase)
+{
+    s->sstat2 = (s->sstat2 & ~PHASE_MASK) | phase;
+       s->ctest0 &= ~1;
+       if (phase == PHASE_DI)
+               s->ctest0 |= 1;
+       s->sbcl &= ~LSI_SBCL_REQ;
+}
+
+static void lsi_bad_phase(LSIState *s, int out, int new_phase)
+{
+    /* Trigger a phase mismatch.  */
+    DPRINTF("Phase mismatch interrupt\n");
+    lsi_script_scsi_interrupt(s, LSI_SSTAT0_MA);
+    lsi_stop_script(s);
+    lsi_set_phase(s, new_phase);
+       s->sbcl |= LSI_SBCL_REQ;
+}
+
+
+/* Resume SCRIPTS execution after a DMA operation.  */
+static void lsi_resume_script(LSIState *s)
+{
+    if (s->waiting != 2) {
+        s->waiting = 0;
+        lsi_execute_script(s);
+    } else {
+        s->waiting = 0;
+    }
+}
+
+static void lsi_disconnect(LSIState *s)
+{
+    s->scntl1 &= ~LSI_SCNTL1_CON;
+    s->sstat2 &= ~PHASE_MASK;
+}
+
+static void lsi_bad_selection(LSIState *s, uint32_t id)
+{
+    DPRINTF("Selected absent target %d\n", id);
+    lsi_script_scsi_interrupt(s, LSI_SSTAT0_STO);
+    lsi_disconnect(s);
+}
+
+/* Initiate a SCSI layer data transfer.  */
+static void lsi_do_dma(LSIState *s, int out)
+{
+    PCIDevice *pci_dev;
+    uint32_t count;
+    dma_addr_t addr;
+    SCSIDevice *dev;
+
+    assert(s->current);
+    if (!s->current->dma_len) {
+        /* Wait until data is available.  */
+        DPRINTF("DMA no data available\n");
+        return;
+    }
+
+    pci_dev = PCI_DEVICE(s);
+    dev = s->current->req->dev;
+    assert(dev);
+
+    count = s->dbc;
+    if (count > s->current->dma_len)
+        count = s->current->dma_len;
+
+    addr = s->dnad;
+#if 0
+       /* both 40 and Table Indirect 64-bit DMAs store upper bits in dnad64 */
+    if (lsi_dma_40bit(s) || lsi_dma_ti64bit(s))
+        addr |= ((uint64_t)s->dnad64 << 32);
+    else if (s->dbms)
+        addr |= ((uint64_t)s->dbms << 32);
+    else if (s->sbms)
+        addr |= ((uint64_t)s->sbms << 32);
+#endif
+
+    DPRINTF("DMA addr=0x" DMA_ADDR_FMT " len=%d\n", addr, count);
+    s->dnad += count;
+    s->dbc -= count;
+     if (s->current->dma_buf == NULL) {
+                s->current->dma_buf = scsi710_req_get_buf(s->current->req);
+    }
+    /* ??? Set SFBR to first data byte.  */
+    if (out) {
+               pci710_dma_read(pci_dev, addr, s->current->dma_buf, count);
+    } else {
+               pci710_dma_write(pci_dev, addr, s->current->dma_buf, count);
+    }
+    s->current->dma_len -= count;
+    if (s->current->dma_len == 0) {
+        s->current->dma_buf = NULL;
+               scsi710_req_continue(s->current->req);
+    } else {
+        s->current->dma_buf += count;
+        lsi_resume_script(s);
+    }
+}
+
+
+/* Add a command to the queue.  */
+static void lsi_queue_command(LSIState *s)
+{
+    lsi_request *p = s->current;
+
+    DPRINTF("Queueing tag=0x%x\n", p->tag);
+    assert(s->current != NULL);
+    assert(s->current->dma_len == 0);
+    QTAILQ_INSERT_TAIL(&s->queue, s->current, next);
+    s->current = NULL;
+
+    p->pending = 0;
+    p->out = (s->sstat2 & PHASE_MASK) == PHASE_DO;
+}
+
+/* Queue a byte for a MSG IN phase.  */
+static void lsi_add_msg_byte(LSIState *s, uint8_t data)
+{
+    if (s->msg_len >= LSI_MAX_MSGIN_LEN) {
+        BADF("MSG IN data too long\n");
+    } else {
+        DPRINTF("MSG IN 0x%02x\n", data);
+        s->msg[s->msg_len++] = data;
+    }
+}
+
+/* Perform reselection to continue a command.  */
+static void lsi_reselect(LSIState *s, lsi_request *p)
+{
+    int id;
+
+    assert(s->current == NULL);
+    QTAILQ_REMOVE(&s->queue, p, next);
+    s->current = p;
+
+    id = (p->tag >> 8) & 0xf;
+    /* LSI53C700 Family Compatibility, see LSI53C895A 4-73 */
+    if (!(s->dcntl & LSI_DCNTL_COM)) {
+        s->sfbr = 1 << (id & 0x7);
+    }
+       s->lcrc = 0;
+    DPRINTF("Reselected target %d\n", id);
+    s->scntl1 |= LSI_SCNTL1_CON;
+    lsi_set_phase(s, PHASE_MI);
+    s->msg_action = p->out ? 2 : 3;
+    s->current->dma_len = p->pending;
+    lsi_add_msg_byte(s, 0x80);
+    if (s->current->tag & LSI_TAG_VALID) {
+        lsi_add_msg_byte(s, 0x20);
+        lsi_add_msg_byte(s, p->tag & 0xff);
+    }
+
+    if (lsi_irq_on_rsl(s)) {
+        lsi_script_scsi_interrupt(s, LSI_SSTAT0_SEL);
+    }
+}
+
+static lsi_request *lsi_find_by_tag(LSIState *s, uint32_t tag)
+{
+    lsi_request *p;
+
+    QTAILQ_FOREACH(p, &s->queue, next) {
+        if (p->tag == tag) {
+            return p;
+        }
+    }
+
+    return NULL;
+}
+
+static void lsi_request_free(LSIState *s, lsi_request *p)
+{
+    if (p == s->current) {
+        s->current = NULL;
+    } else {
+        QTAILQ_REMOVE(&s->queue, p, next);
+    }
+    g_free(p);
+}
+
+void lsi_request_cancelled(SCSIRequest *req)
+{
+    LSIState *s = LSI53C895A(req->bus->qbus.parent);
+    lsi_request *p = (lsi_request*)req->hba_private;
+
+    req->hba_private = NULL;
+    lsi_request_free(s, p);
+       scsi710_req_unref(req);
+}
+
+/* Record that data is available for a queued command.  Returns zero if
+   the device was reselected, nonzero if the IO is deferred.  */
+static int lsi_queue_req(LSIState *s, SCSIRequest *req, uint32_t len)
+{
+    lsi_request *p = (lsi_request*)req->hba_private;
+
+    if (p->pending) {
+        BADF("Multiple IO pending for request %p\n", p);
+    }
+    p->pending = len;
+    /* Reselect if waiting for it, or if reselection triggers an IRQ
+       and the bus is free.
+       Since no interrupt stacking is implemented in the emulation, it
+       is also required that there are no pending interrupts waiting
+       for service from the device driver. */
+    if (s->waiting == 1 ||
+        (lsi_irq_on_rsl(s) && !(s->scntl1 & LSI_SCNTL1_CON) &&
+         !(s->istat & (LSI_ISTAT_SIP | LSI_ISTAT_DIP)))) {
+        /* Reselect device.  */
+        lsi_reselect(s, p);
+        return 0;
+    } else {
+        DPRINTF("Queueing IO tag=0x%x\n", p->tag);
+        p->pending = len;
+        return 1;
+    }
+}
+
+ /* Callback to indicate that the SCSI layer has completed a command.  */
+void lsi710_command_complete(SCSIRequest *req, uint32_t status, size_t resid)
+{
+    LSIState *s = LSI53C895A(req->bus->qbus.parent);
+    int out;
+
+    out = (s->sstat2 & PHASE_MASK) == PHASE_DO;
+    DPRINTF("Command complete status=%d\n", (int)status);
+       s->lcrc = 0;
+    s->status = status;
+    s->command_complete = 2;
+    if (s->waiting && s->dbc != 0) {
+        /* Raise phase mismatch for short transfers.  */
+        lsi_bad_phase(s, out, PHASE_ST);
+    } else {
+        lsi_set_phase(s, PHASE_ST);
+    }
+
+    if (req->hba_private == s->current) {
+        req->hba_private = NULL;
+        lsi_request_free(s, s->current);
+               scsi710_req_unref(req);
+    }
+    lsi_resume_script(s);
+}
+
+ /* Callback to indicate that the SCSI layer has completed a transfer.  */
+void lsi710_transfer_data(SCSIRequest *req, uint32_t len)
+{
+    LSIState *s = LSI53C895A(req->bus->qbus.parent);
+    int out;
+
+    assert(req->hba_private);
+    if (s->waiting == 1 || req->hba_private != s->current ||
+        (lsi_irq_on_rsl(s) && !(s->scntl1 & LSI_SCNTL1_CON))) {
+        if (lsi_queue_req(s, req, len)) {
+            return;
+        }
+    }
+
+    out = (s->sstat2 & PHASE_MASK) == PHASE_DO;
+
+    /* host adapter (re)connected */
+    DPRINTF("Data ready tag=0x%x len=%d\n", req->tag, len);
+    s->current->dma_len = len;
+    s->command_complete = 1;
+    if (s->waiting) {
+        if (s->waiting == 1 || s->dbc == 0) {
+            lsi_resume_script(s);
+        } else {
+            lsi_do_dma(s, out);
+        }
+    }
+}
+
+static int idbitstonum(int id)
+{
+       int num = 0;
+       while (id > 1) {
+               num++;
+               id >>= 1;
+       }
+       if (num > 7)
+               num = -1;
+       return num;
+}
+
+static void lsi_do_command(LSIState *s)
+{
+    SCSIDevice *dev;
+    uint8_t buf[16];
+    uint32_t id;
+    int n;
+
+    DPRINTF("Send command len=%d\n", s->dbc);
+    if (s->dbc > 16)
+        s->dbc = 16;
+       pci710_dma_read(PCI_DEVICE(s), s->dnad, buf, s->dbc);
+    DPRINTF("Send command len=%d %02x.%02x.%02x.%02x.%02x.%02x\n", s->dbc, buf[0], buf[1], buf[2], buf[3], buf[4], buf[5]);
+    s->sfbr = buf[0];
+    s->command_complete = 0;
+
+    id = (s->select_tag >> 8) & 0xff;
+       s->lcrc = id; //1 << (id & 0x7);
+       dev = scsi710_device_find(&s->bus, 0, idbitstonum(id), s->current_lun);
+    if (!dev) {
+        lsi_bad_selection(s, id);
+        return;
+    }
+
+    assert(s->current == NULL);
+    s->current = (lsi_request*)calloc(sizeof(lsi_request), 1);
+    s->current->tag = s->select_tag;
+       s->current->req = scsi710_req_new(dev, s->current->tag, s->current_lun, buf, s->dbc, s->current);
+
+       n = scsi710_req_enqueue(s->current->req);
+    if (n) {
+        if (n > 0) {
+            lsi_set_phase(s, PHASE_DI);
+        } else if (n < 0) {
+            lsi_set_phase(s, PHASE_DO);
+        }
+               scsi710_req_continue(s->current->req);
+    }
+    if (!s->command_complete) {
+        if (n) {
+            /* Command did not complete immediately so disconnect.  */
+            lsi_add_msg_byte(s, 2); /* SAVE DATA POINTER */
+            lsi_add_msg_byte(s, 4); /* DISCONNECT */
+            /* wait data */
+            lsi_set_phase(s, PHASE_MI);
+            s->msg_action = 1;
+            lsi_queue_command(s);
+        } else {
+            /* wait command complete */
+            lsi_set_phase(s, PHASE_DI);
+        }
+    }
+}
+
+static void lsi_do_status(LSIState *s)
+{
+    uint8_t status;
+    DPRINTF("Get status len=%d status=%d\n", s->dbc, s->status);
+    if (s->dbc != 1)
+        BADF("Bad Status move\n");
+    s->dbc = 1;
+    status = s->status;
+    s->sfbr = status;
+       pci710_dma_write(PCI_DEVICE(s), s->dnad, &status, 1);
+    lsi_set_phase(s, PHASE_MI);
+    s->msg_action = 1;
+    lsi_add_msg_byte(s, 0); /* COMMAND COMPLETE */
+}
+
+static void lsi_do_msgin(LSIState *s)
+{
+    int len;
+    DPRINTF("Message in len=%d/%d\n", s->dbc, s->msg_len);
+    s->sfbr = s->msg[0];
+    len = s->msg_len;
+    if (len > s->dbc)
+        len = s->dbc;
+       pci710_dma_write(PCI_DEVICE(s), s->dnad, s->msg, len);
+    /* Linux drivers rely on the last byte being in the SIDL.  */
+    s->sidl = s->msg[len - 1];
+    s->msg_len -= len;
+    if (s->msg_len) {
+        memmove(s->msg, s->msg + len, s->msg_len);
+    } else {
+        /* ??? Check if ATN (not yet implemented) is asserted and maybe
+           switch to PHASE_MO.  */
+        switch (s->msg_action) {
+        case 0:
+            lsi_set_phase(s, PHASE_CMD);
+            break;
+        case 1:
+            lsi_disconnect(s);
+            break;
+        case 2:
+            lsi_set_phase(s, PHASE_DO);
+            break;
+        case 3:
+            lsi_set_phase(s, PHASE_DI);
+            break;
+        default:
+            abort();
+        }
+    }
+}
+
+/* Read the next byte during a MSGOUT phase.  */
+static uint8_t lsi_get_msgbyte(LSIState *s)
+{
+    uint8_t data;
+       pci710_dma_read(PCI_DEVICE(s), s->dnad, &data, 1);
+    s->dnad++;
+    s->dbc--;
+    return data;
+}
+
+/* Skip the next n bytes during a MSGOUT phase. */
+static void lsi_skip_msgbytes(LSIState *s, unsigned int n)
+{
+    s->dnad += n;
+    s->dbc  -= n;
+}
+
+static void lsi_do_msgout(LSIState *s)
+{
+    uint8_t msg;
+    int len;
+    uint32_t current_tag;
+    lsi_request *current_req, *p, *p_next;
+
+    if (s->current) {
+        current_tag = s->current->tag;
+        current_req = s->current;
+    } else {
+        current_tag = s->select_tag;
+        current_req = lsi_find_by_tag(s, current_tag);
+    }
+
+    DPRINTF("MSG out len=%d\n", s->dbc);
+    while (s->dbc) {
+        msg = lsi_get_msgbyte(s);
+        s->sfbr = msg;
+
+        switch (msg) {
+        case 0x04:
+            DPRINTF("MSG: Disconnect\n");
+            lsi_disconnect(s);
+            break;
+        case 0x08:
+            DPRINTF("MSG: No Operation\n");
+            lsi_set_phase(s, PHASE_CMD);
+            break;
+        case 0x01:
+            len = lsi_get_msgbyte(s);
+            msg = lsi_get_msgbyte(s);
+            (void)len; /* avoid a warning about unused variable*/
+            DPRINTF("Extended message 0x%x (len %d)\n", msg, len);
+            switch (msg) {
+            case 1:
+                DPRINTF("SDTR (ignored)\n");
+                lsi_skip_msgbytes(s, 2);
+                break;
+            case 3:
+                DPRINTF("WDTR (ignored)\n");
+                lsi_skip_msgbytes(s, 1);
+                break;
+            default:
+                goto bad;
+            }
+            break;
+        case 0x20: /* SIMPLE queue */
+            s->select_tag |= lsi_get_msgbyte(s) | LSI_TAG_VALID;
+            DPRINTF("SIMPLE queue tag=0x%x\n", s->select_tag & 0xff);
+            break;
+        case 0x21: /* HEAD of queue */
+            BADF("HEAD queue not implemented\n");
+            s->select_tag |= lsi_get_msgbyte(s) | LSI_TAG_VALID;
+            break;
+        case 0x22: /* ORDERED queue */
+            BADF("ORDERED queue not implemented\n");
+            s->select_tag |= lsi_get_msgbyte(s) | LSI_TAG_VALID;
+            break;
+        case 0x0d:
+            /* The ABORT TAG message clears the current I/O process only. */
+            DPRINTF("MSG: ABORT TAG tag=0x%x\n", current_tag);
+            if (current_req) {
+                               scsi710_req_cancel(current_req->req);
+            }
+            lsi_disconnect(s);
+            break;
+        case 0x06:
+        case 0x0e:
+        case 0x0c:
+            /* The ABORT message clears all I/O processes for the selecting
+               initiator on the specified logical unit of the target. */
+            if (msg == 0x06) {
+                DPRINTF("MSG: ABORT tag=0x%x\n", current_tag);
+            }
+            /* The CLEAR QUEUE message clears all I/O processes for all
+               initiators on the specified logical unit of the target. */
+            if (msg == 0x0e) {
+                DPRINTF("MSG: CLEAR QUEUE tag=0x%x\n", current_tag);
+            }
+            /* The BUS DEVICE RESET message clears all I/O processes for all
+               initiators on all logical units of the target. */
+            if (msg == 0x0c) {
+                DPRINTF("MSG: BUS DEVICE RESET tag=0x%x\n", current_tag);
+            }
+
+            /* clear the current I/O process */
+            if (s->current) {
+                               scsi710_req_cancel(s->current->req);
+            }
+
+            /* As the current implemented devices scsi_disk and scsi_generic
+               only support one LUN, we don't need to keep track of LUNs.
+               Clearing I/O processes for other initiators could be possible
+               for scsi_generic by sending a SG_SCSI_RESET to the /dev/sgX
+               device, but this is currently not implemented (and seems not
+               to be really necessary). So let's simply clear all queued
+               commands for the current device: */
+            QTAILQ_FOREACH_SAFE(p, &s->queue, next, p_next) {
+                if ((p->tag & 0x0000ff00) == (current_tag & 0x0000ff00)) {
+                                       scsi710_req_cancel(p->req);
+                }
+            }
+
+            lsi_disconnect(s);
+            break;
+        default:
+            if ((msg & 0x80) == 0) {
+                goto bad;
+            }
+            s->current_lun = msg & 7;
+            DPRINTF("Select LUN %d\n", s->current_lun);
+            lsi_set_phase(s, PHASE_CMD);
+            break;
+        }
+    }
+    return;
+bad:
+    BADF("Unimplemented message 0x%02x\n", msg);
+    lsi_set_phase(s, PHASE_MI);
+    lsi_add_msg_byte(s, 7); /* MESSAGE REJECT */
+    s->msg_action = 0;
+}
+
+#define LSI_BUF_SIZE 4096
+static void lsi_memcpy(LSIState *s, uint32_t dest, uint32_t src, int count)
+{
+    PCIDevice *d = PCI_DEVICE(s);
+    int n;
+    uint8_t buf[LSI_BUF_SIZE];
+
+    DPRINTF("memcpy dest 0x%08x src 0x%08x count %d\n", dest, src, count);
+    while (count) {
+        n = (count > LSI_BUF_SIZE) ? LSI_BUF_SIZE : count;
+               pci710_dma_read(d, src, buf, n);
+               pci710_dma_write(d, dest, buf, n);
+        src += n;
+        dest += n;
+        count -= n;
+    }
+}
+
+static void lsi_wait_reselect(LSIState *s)
+{
+    lsi_request *p;
+
+    DPRINTF("Wait Reselect\n");
+
+    QTAILQ_FOREACH(p, &s->queue, next) {
+        if (p->pending) {
+            lsi_reselect(s, p);
+            break;
+        }
+    }
+    if (s->current == NULL) {
+        s->waiting = 1;
+    }
+}
+
+static void lsi_execute_script(LSIState *s)
+{
+    PCIDevice *pci_dev = PCI_DEVICE(s);
+    uint32_t insn;
+    uint32_t addr;
+    int opcode;
+    int insn_processed = 0;
+
+    s->script_active = 1;
+again:
+    insn_processed++;
+    insn = read_dword(s, s->dsp);
+    if (!insn) {
+        /* If we receive an empty opcode increment the DSP by 4 bytes
+           instead of 8 and execute the next opcode at that location */
+        s->dsp += 4;
+        goto again;
+    }
+    addr = read_dword(s, s->dsp + 4);
+    DPRINTF("SCRIPTS dsp=%08x opcode %08x arg %08x\n", s->dsp, insn, addr);
+    s->dsps = addr;
+    s->dcmd = insn >> 24;
+    s->dsp += 8;
+    switch (insn >> 30) {
+    case 0: /* Block move.  */
+        if (s->sstat0 & LSI_SSTAT0_STO) {
+            DPRINTF("Delayed select timeout\n");
+            lsi_stop_script(s);
+            break;
+        }
+        s->dbc = insn & 0xffffff;
+        if (insn & (1 << 29)) {
+            /* Indirect addressing.  */
+            addr = read_dword(s, addr);
+        } else if (insn & (1 << 28)) {
+            uint32_t buf[2];
+            int32_t offset;
+            /* Table indirect addressing.  */
+
+            /* 32-bit Table indirect */
+            offset = sextract32(addr, 0, 24);
+                       pci710_dma_read(pci_dev, s->dsa + offset, buf, 8);
+            /* byte count is stored in bits 0:23 only */
+            s->dbc = cpu_to_le32(buf[0]) & 0xffffff;
+            addr = cpu_to_le32(buf[1]);
+
+#if 0
+                       /* 40-bit DMA, upper addr bits [39:32] stored in first DWORD of
+             * table, bits [31:24] */
+            if (lsi_dma_40bit(s))
+                addr_high = cpu_to_le32(buf[0]) >> 24;
+            else if (lsi_dma_ti64bit(s)) {
+                int selector = (cpu_to_le32(buf[0]) >> 24) & 0x1f;
+                switch (selector) {
+                               case 0x00:
+                               case 0x01:
+                               case 0x02:
+                               case 0x03:
+                               case 0x04:
+                               case 0x05:
+                               case 0x06:
+                               case 0x07:
+                               case 0x08:
+                               case 0x09:
+                               case 0x0a:
+                               case 0x0b:
+                               case 0x0c:
+                               case 0x0d:
+                               case 0x0e:
+                               case 0x0f:
+                    /* offset index into scratch registers since
+                     * TI64 mode can use registers C to R */
+                    addr_high = s->scratch[2 + selector];
+                    break;
+                case 0x10:
+                    addr_high = s->mmrs;
+                    break;
+                case 0x11:
+                    addr_high = s->mmws;
+                    break;
+                case 0x12:
+                    addr_high = s->sfs;
+                    break;
+                case 0x13:
+                    addr_high = s->drs;
+                    break;
+                case 0x14:
+                    addr_high = s->sbms;
+                    break;
+                case 0x15:
+                    addr_high = s->dbms;
+                    break;
+                default:
+                    BADF("Illegal selector specified (0x%x > 0x15)"
+                         " for 64-bit DMA block move", selector);
+                    break;
+                }
+            }
+        } else if (lsi_dma_64bit(s)) {
+            /* fetch a 3rd dword if 64-bit direct move is enabled and
+               only if we're not doing table indirect or indirect addressing */
+            s->dbms = read_dword(s, s->dsp);
+            s->dsp += 4;
+            s->ia = s->dsp - 12;
+#endif
+        }
+        if ((s->sstat2 & PHASE_MASK) != ((insn >> 24) & 7)) {
+            DPRINTF("Wrong phase got %d expected %d\n",
+                    s->sstat2 & PHASE_MASK, (insn >> 24) & 7);
+            lsi_script_scsi_interrupt(s, LSI_SSTAT0_MA);
+                       s->sbcl |= LSI_SBCL_REQ;
+            break;
+        }
+        s->dnad = addr;
+        switch (s->sstat2 & 0x7) {
+        case PHASE_DO:
+            s->waiting = 2;
+            lsi_do_dma(s, 1);
+            if (s->waiting)
+                s->waiting = 3;
+            break;
+        case PHASE_DI:
+            s->waiting = 2;
+            lsi_do_dma(s, 0);
+            if (s->waiting)
+                s->waiting = 3;
+            break;
+        case PHASE_CMD:
+            lsi_do_command(s);
+            break;
+        case PHASE_ST:
+            lsi_do_status(s);
+            break;
+        case PHASE_MO:
+            lsi_do_msgout(s);
+            break;
+        case PHASE_MI:
+            lsi_do_msgin(s);
+            break;
+        default:
+            BADF("Unimplemented phase %d\n", s->sstat2 & PHASE_MASK);
+        }
+        s->ctest5 = (s->ctest5 & 0xfc) | ((s->dbc >> 8) & 3);
+        s->sbc = s->dbc;
+        break;
+
+    case 1: /* IO or Read/Write instruction.  */
+        opcode = (insn >> 27) & 7;
+        if (opcode < 5) {
+            uint32_t id;
+
+            if (insn & (1 << 25)) {
+                id = read_dword(s, s->dsa + sextract32(insn, 0, 24));
+            } else {
+                id = insn;
+            }
+            id = (id >> 16) & 0xff;
+            if (insn & (1 << 26)) {
+                addr = s->dsp + sextract32(addr, 0, 24);
+            }
+            s->dnad = addr;
+            switch (opcode) {
+            case 0: /* Select */
+                s->sdid = id;
+                if (s->scntl1 & LSI_SCNTL1_CON) {
+                    DPRINTF("Already reselected, jumping to alternative address\n");
+                    s->dsp = s->dnad;
+                    break;
+                }
+                s->sstat1 |= LSI_SSTAT1_WOA;
+//                s->scntl1 &= ~LSI_SCNTL1_IARB;
+                               if (!scsi710_device_find(&s->bus, 0, idbitstonum(id), 0)) {
+                    lsi_bad_selection(s, id);
+                    break;
+                }
+                DPRINTF("Selected target %d%s\n",
+                        id, insn & (1 << 24) ? " ATN" : "");
+                /* ??? Linux drivers compain when this is set.  Maybe
+                   it only applies in low-level mode (unimplemented).
+                lsi_script_scsi_interrupt(s, LSI_SIST0_CMP, 0); */
+                s->select_tag = id << 8;
+                s->scntl1 |= LSI_SCNTL1_CON;
+                if (insn & (1 << 24)) {
+                    s->socl |= LSI_SOCL_ATN;
+                }
+                lsi_set_phase(s, PHASE_MO);
+                break;
+            case 1: /* Disconnect */
+                DPRINTF("Wait Disconnect\n");
+                s->scntl1 &= ~LSI_SCNTL1_CON;
+                break;
+            case 2: /* Wait Reselect */
+                if (!lsi_irq_on_rsl(s)) {
+                    lsi_wait_reselect(s);
+                }
+                break;
+            case 3: /* Set */
+                DPRINTF("Set%s%s%s%s\n",
+                        insn & (1 << 3) ? " ATN" : "",
+                        insn & (1 << 6) ? " ACK" : "",
+                        insn & (1 << 9) ? " TM" : "",
+                        insn & (1 << 10) ? " CC" : "");
+                if (insn & (1 << 3)) {
+                    s->socl |= LSI_SOCL_ATN;
+                    lsi_set_phase(s, PHASE_MO);
+                }
+                if (insn & (1 << 9)) {
+                    BADF("Target mode not implemented\n");
+                }
+                if (insn & (1 << 10))
+                    s->carry = 1;
+                break;
+            case 4: /* Clear */
+                DPRINTF("Clear%s%s%s%s\n",
+                        insn & (1 << 3) ? " ATN" : "",
+                        insn & (1 << 6) ? " ACK" : "",
+                        insn & (1 << 9) ? " TM" : "",
+                        insn & (1 << 10) ? " CC" : "");
+                if (insn & (1 << 3)) {
+                    s->socl &= ~LSI_SOCL_ATN;
+                }
+                if (insn & (1 << 10))
+                    s->carry = 0;
+                break;
+            }
+        } else {
+            uint8_t op0;
+            uint8_t op1;
+            uint8_t data8;
+            int reg;
+            int xoperator;
+#ifdef DEBUG_LSI
+            static const char *opcode_names[3] =
+                {"Write", "Read", "Read-Modify-Write"};
+            static const char *operator_names[8] =
+                {"MOV", "SHL", "OR", "XOR", "AND", "SHR", "ADD", "ADC"};
+#endif
+
+            reg = ((insn >> 16) & 0x7f) | (insn & 0x80);
+            data8 = (insn >> 8) & 0xff;
+            opcode = (insn >> 27) & 7;
+            xoperator = (insn >> 24) & 7;
+            DPRINTF("%s reg 0x%x %s data8=0x%02x sfbr=0x%02x%s\n",
+                    opcode_names[opcode - 5], reg,
+                    operator_names[xoperator], data8, s->sfbr,
+                    (insn & (1 << 23)) ? " SFBR" : "");
+            op0 = op1 = 0;
+            switch (opcode) {
+            case 5: /* From SFBR */
+                op0 = s->sfbr;
+                op1 = data8;
+                break;
+            case 6: /* To SFBR */
+                if (xoperator)
+                    op0 = lsi_reg_readb(s, reg);
+                op1 = data8;
+                break;
+            case 7: /* Read-modify-write */
+                if (xoperator)
+                    op0 = lsi_reg_readb(s, reg);
+                if (insn & (1 << 23)) {
+                    op1 = s->sfbr;
+                } else {
+                    op1 = data8;
+                }
+                break;
+            }
+
+            switch (xoperator) {
+            case 0: /* move */
+                op0 = op1;
+                break;
+            case 1: /* Shift left */
+                op1 = op0 >> 7;
+                op0 = (op0 << 1) | s->carry;
+                s->carry = op1;
+                break;
+            case 2: /* OR */
+                op0 |= op1;
+                break;
+            case 3: /* XOR */
+                op0 ^= op1;
+                break;
+            case 4: /* AND */
+                op0 &= op1;
+                break;
+            case 5: /* SHR */
+                op1 = op0 & 1;
+                op0 = (op0 >> 1) | (s->carry << 7);
+                s->carry = op1;
+                break;
+            case 6: /* ADD */
+                op0 += op1;
+                s->carry = op0 < op1;
+                break;
+            case 7: /* ADC */
+                op0 += op1 + s->carry;
+                if (s->carry)
+                    s->carry = op0 <= op1;
+                else
+                    s->carry = op0 < op1;
+                break;
+            }
+
+            switch (opcode) {
+            case 5: /* From SFBR */
+            case 7: /* Read-modify-write */
+                lsi_reg_writeb(s, reg, op0);
+                break;
+            case 6: /* To SFBR */
+                s->sfbr = op0;
+                break;
+            }
+        }
+        break;
+
+    case 2: /* Transfer Control.  */
+        {
+            int cond;
+            int jmp;
+
+            if ((insn & 0x002e0000) == 0) {
+                DPRINTF("NOP\n");
+                break;
+            }
+            if (s->sstat0 & LSI_SSTAT0_STO) {
+                DPRINTF("Delayed select timeout\n");
+                lsi_stop_script(s);
+                break;
+            }
+            cond = jmp = (insn & (1 << 19)) != 0;
+            if (cond == jmp && (insn & (1 << 21))) {
+                DPRINTF("Compare carry %d\n", s->carry == jmp);
+                cond = s->carry != 0;
+            }
+            if (cond == jmp && (insn & (1 << 17))) {
+                DPRINTF("Compare phase %d %c= %d\n",
+                        (s->sstat2 & PHASE_MASK),
+                        jmp ? '=' : '!',
+                        ((insn >> 24) & 7));
+                cond = (s->sstat2 & PHASE_MASK) == ((insn >> 24) & 7);
+            }
+            if (cond == jmp && (insn & (1 << 18))) {
+                uint8_t mask;
+
+                mask = (~insn >> 8) & 0xff;
+                DPRINTF("Compare data 0x%x & 0x%x %c= 0x%x\n",
+                        s->sfbr, mask, jmp ? '=' : '!', insn & mask);
+                cond = (s->sfbr & mask) == (insn & mask);
+            }
+            if (cond == jmp) {
+                if (insn & (1 << 23)) {
+                    /* Relative address.  */
+                    addr = s->dsp + sextract32(addr, 0, 24);
+                }
+                switch ((insn >> 27) & 7) {
+                case 0: /* Jump */
+                    DPRINTF("Jump to 0x%08x\n", addr);
+                    s->dsp = addr;
+                    break;
+                case 1: /* Call */
+                    DPRINTF("Call 0x%08x\n", addr);
+                    s->temp = s->dsp;
+                    s->dsp = addr;
+                    break;
+                case 2: /* Return */
+                    DPRINTF("Return to 0x%08x\n", s->temp);
+                    s->dsp = s->temp;
+                    break;
+                case 3: /* Interrupt */
+                    DPRINTF("Interrupt 0x%08x\n", s->dsps);
+                    if ((insn & (1 << 20)) != 0) {
+                        lsi_update_irq(s);
+                    } else {
+                        lsi_script_dma_interrupt(s, LSI_DSTAT_SIR);
+                    }
+                    break;
+                default:
+                    DPRINTF("Illegal transfer control\n");
+                    lsi_script_dma_interrupt(s, LSI_DSTAT_IID);
+                    break;
+                }
+            } else {
+                DPRINTF("Control condition failed\n");
+            }
+        }
+        break;
+
+    case 3:
+        if ((insn & (1 << 29)) == 0) {
+            /* Memory move.  */
+            uint32_t dest;
+            /* ??? The docs imply the destination address is loaded into
+               the TEMP register.  However the Linux drivers rely on
+               the value being presrved.  */
+            dest = read_dword(s, s->dsp);
+            s->dsp += 4;
+            lsi_memcpy(s, dest, addr, insn & 0xffffff);
+        } else {
+            uint8_t data[7];
+            int reg;
+            int n;
+            int i;
+
+            if (insn & (1 << 28)) {
+                addr = s->dsa + sextract32(addr, 0, 24);
+            }
+            n = (insn & 7);
+            reg = (insn >> 16) & 0xff;
+            if (insn & (1 << 24)) {
+                               pci710_dma_read(pci_dev, addr, data, n);
+                DPRINTF("Load reg 0x%x size %d addr 0x%08x = %08x\n", reg, n,
+                        addr, *(int *)data);
+                for (i = 0; i < n; i++) {
+                    lsi_reg_writeb(s, reg + i, data[i]);
+                }
+            } else {
+                DPRINTF("Store reg 0x%x size %d addr 0x%08x\n", reg, n, addr);
+                for (i = 0; i < n; i++) {
+                    data[i] = lsi_reg_readb(s, reg + i);
+                }
+                               pci710_dma_write(pci_dev, addr, data, n);
+            }
+        }
+    }
+    if (insn_processed > 10000 && !s->waiting) {
+        /* Some windows drivers make the device spin waiting for a memory
+           location to change.  If we have been executed a lot of code then
+           assume this is the case and force an unexpected device disconnect.
+           This is apparently sufficient to beat the drivers into submission.
+         */
+        if (!(s->sien0 & LSI_SSTAT0_UDC))
+            fprintf(stderr, "inf. loop with UDC masked\n");
+        lsi_script_scsi_interrupt(s, LSI_SSTAT0_UDC);
+        lsi_disconnect(s);
+    } else if (s->script_active && !s->waiting) {
+        if (s->dcntl & LSI_DCNTL_SSM) {
+            lsi_script_dma_interrupt(s, LSI_DSTAT_SSI);
+        } else {
+            goto again;
+        }
+    }
+    DPRINTF("SCRIPTS execution stopped\n");
+}
+
+#if 0
+static uint8_t lsi_reg_readb(LSIState *s, int offset)
+{
+    uint8_t tmp;
+#define CASE_GET_REG24(name, addr) \
+    case addr: return s->name & 0xff; \
+    case addr + 1: return (s->name >> 8) & 0xff; \
+    case addr + 2: return (s->name >> 16) & 0xff;
+
+#define CASE_GET_REG32(name, addr) \
+    case addr: return s->name & 0xff; \
+    case addr + 1: return (s->name >> 8) & 0xff; \
+    case addr + 2: return (s->name >> 16) & 0xff; \
+    case addr + 3: return (s->name >> 24) & 0xff;
+
+#ifdef DEBUG_LSI_REG
+    DPRINTF("Read reg %x\n", offset);
+#endif
+    switch (offset) {
+    case 0x00: /* SCNTL0 */
+        return s->scntl0;
+    case 0x01: /* SCNTL1 */
+        return s->scntl1;
+    case 0x02: /* SCNTL2 */
+        return s->scntl2;
+    case 0x03: /* SCNTL3 */
+        return s->scntl3;
+    case 0x04: /* SCID */
+        return s->scid;
+    case 0x05: /* SXFER */
+        return s->sxfer;
+    case 0x06: /* SDID */
+        return s->sdid;
+    case 0x07: /* GPREG0 */
+        return 0x7f;
+    case 0x08: /* Revision ID */
+        return 0x00;
+    case 0xa: /* SSID */
+        return s->ssid;
+    case 0xb: /* SBCL */
+        /* ??? This is not correct. However it's (hopefully) only
+           used for diagnostics, so should be ok.  */
+        return 0;
+    case 0xc: /* DSTAT */
+        tmp = s->dstat | LSI_DSTAT_DFE;
+        if ((s->istat0 & LSI_ISTAT0_INTF) == 0)
+            s->dstat = 0;
+        lsi_update_irq(s);
+        return tmp;
+    case 0x0d: /* SSTAT0 */
+        return s->sstat0;
+    case 0x0e: /* SSTAT1 */
+        return s->sstat1;
+    case 0x0f: /* SSTAT2 */
+        return s->scntl1 & LSI_SCNTL1_CON ? 0 : 2;
+    CASE_GET_REG32(dsa, 0x10)
+    case 0x14: /* ISTAT0 */
+        return s->istat0;
+    case 0x15: /* ISTAT1 */
+        return s->istat1;
+    case 0x16: /* MBOX0 */
+        return s->mbox0;
+    case 0x17: /* MBOX1 */
+        return s->mbox1;
+    case 0x18: /* CTEST0 */
+        return 0xff;
+    case 0x19: /* CTEST1 */
+        return 0;
+    case 0x1a: /* CTEST2 */
+        tmp = s->ctest2 | LSI_CTEST2_DACK | LSI_CTEST2_CM;
+        if (s->istat0 & LSI_ISTAT0_SIGP) {
+            s->istat0 &= ~LSI_ISTAT0_SIGP;
+            tmp |= LSI_CTEST2_SIGP;
+        }
+        return tmp;
+    case 0x1b: /* CTEST3 */
+        return s->ctest3;
+    CASE_GET_REG32(temp, 0x1c)
+    case 0x20: /* DFIFO */
+        return 0;
+    case 0x21: /* CTEST4 */
+        return s->ctest4;
+    case 0x22: /* CTEST5 */
+        return s->ctest5;
+    case 0x23: /* CTEST6 */
+         return 0;
+    CASE_GET_REG24(dbc, 0x24)
+    case 0x27: /* DCMD */
+        return s->dcmd;
+    CASE_GET_REG32(dnad, 0x28)
+    CASE_GET_REG32(dsp, 0x2c)
+    CASE_GET_REG32(dsps, 0x30)
+    CASE_GET_REG32(scratch[0], 0x34)
+    case 0x38: /* DMODE */
+        return s->dmode;
+    case 0x39: /* DIEN */
+        return s->dien;
+    case 0x3a: /* SBR */
+        return s->sbr;
+    case 0x3b: /* DCNTL */
+        return s->dcntl;
+    case 0x40: /* SIEN0 */
+        return s->sien0;
+    case 0x41: /* SIEN1 */
+        return s->sien1;
+    case 0x42: /* SIST0 */
+        tmp = s->sist0;
+        s->sist0 = 0;
+        lsi_update_irq(s);
+        return tmp;
+    case 0x43: /* SIST1 */
+        tmp = s->sist1;
+        s->sist1 = 0;
+        lsi_update_irq(s);
+        return tmp;
+    case 0x46: /* MACNTL */
+        return 0x0f;
+    case 0x47: /* GPCNTL0 */
+        return 0x0f;
+    case 0x48: /* STIME0 */
+        return s->stime0;
+    case 0x4a: /* RESPID0 */
+        return s->respid0;
+    case 0x4b: /* RESPID1 */
+        return s->respid1;
+    case 0x4d: /* STEST1 */
+        return s->stest1;
+    case 0x4e: /* STEST2 */
+        return s->stest2;
+    case 0x4f: /* STEST3 */
+        return s->stest3;
+    case 0x50: /* SIDL */
+        /* This is needed by the linux drivers.  We currently only update it
+           during the MSG IN phase.  */
+        return s->sidl;
+    case 0x52: /* STEST4 */
+        return 0xe0;
+    case 0x56: /* CCNTL0 */
+        return s->ccntl0;
+    case 0x57: /* CCNTL1 */
+        return s->ccntl1;
+    case 0x58: /* SBDL */
+        /* Some drivers peek at the data bus during the MSG IN phase.  */
+        if ((s->sstat1 & PHASE_MASK) == PHASE_MI)
+            return s->msg[0];
+        return 0;
+    case 0x59: /* SBDL high */
+        return 0;
+    CASE_GET_REG32(mmrs, 0xa0)
+    CASE_GET_REG32(mmws, 0xa4)
+    CASE_GET_REG32(sfs, 0xa8)
+    CASE_GET_REG32(drs, 0xac)
+    CASE_GET_REG32(sbms, 0xb0)
+    CASE_GET_REG32(dbms, 0xb4)
+    CASE_GET_REG32(dnad64, 0xb8)
+    CASE_GET_REG32(pmjad1, 0xc0)
+    CASE_GET_REG32(pmjad2, 0xc4)
+    CASE_GET_REG32(rbc, 0xc8)
+    CASE_GET_REG32(ua, 0xcc)
+    CASE_GET_REG32(ia, 0xd4)
+    CASE_GET_REG32(sbc, 0xd8)
+    CASE_GET_REG32(csbc, 0xdc)
+    }
+    if (offset >= 0x5c && offset < 0xa0) {
+        int n;
+        int shift;
+        n = (offset - 0x58) >> 2;
+        shift = (offset & 3) * 8;
+        return (s->scratch[n] >> shift) & 0xff;
+    }
+    BADF("readb 0x%x\n", offset);
+#undef CASE_GET_REG24
+#undef CASE_GET_REG32
+}
+#endif
+
+static uint8_t lsi_reg_readb2(LSIState *s, int offset)
+{
+    uint8_t tmp;
+#define CASE_GET_REG24(name, addr) \
+    case addr: return s->name & 0xff; \
+    case addr + 1: return (s->name >> 8) & 0xff; \
+    case addr + 2: return (s->name >> 16) & 0xff;
+
+#define CASE_GET_REG32(name, addr) \
+    case addr: return s->name & 0xff; \
+    case addr + 1: return (s->name >> 8) & 0xff; \
+    case addr + 2: return (s->name >> 16) & 0xff; \
+    case addr + 3: return (s->name >> 24) & 0xff;
+
+    switch (offset)
+       {
+    case 0x00: /* SCNTL0 */
+        return s->scntl0;
+    case 0x01: /* SCNTL1 */
+        return s->scntl1;
+    case 0x02: /* SDID */
+        return s->sdid;
+    case 0x03: /* SIEN */
+        return s->sien0;
+       case 0x04: /* SCID */
+               return s->scid;
+       case 0x05: /* SXFER */
+        return s->sxfer;
+    case 0x09: /* SIDL */
+        /* This is needed by the linux drivers.  We currently only update it
+           during the MSG IN phase.  */
+        return s->sidl;
+    case 0xb: /* SBCL */
+               tmp = 0;
+               if (s->scntl1 & LSI_SCNTL1_CON) {
+                       /* NetBSD 1.x checks for REQ */
+                       tmp = s->sstat2 & PHASE_MASK;
+                       /* if phase mismatch, REQ is also active */
+                       tmp |= s->sbcl;
+                       if (s->socl & LSI_SOCL_ATN)
+                               tmp |= LSI_SBCL_ATN;
+               }
+        return tmp;
+    case 0xc: /* DSTAT */
+        tmp = s->dstat | LSI_DSTAT_DFE;
+               s->dstat = 0;
+//        if ((s->istat0 & LSI_ISTAT0_INTF) == 0)
+//            s->dstat = 0;
+        lsi_update_irq(s);
+        return tmp;
+   case 0x0d: /* SSTAT0 */
+               tmp = s->sstat0;
+               s->sstat0 = 0;
+        lsi_update_irq(s);
+       return tmp;
+    case 0x0e: /* SSTAT1 */
+        return s->sstat1;
+    case 0x0f: /* SSTAT2 */
+        return s->sstat2;
+    CASE_GET_REG32(dsa, 0x10)
+       case 0x14: /* CTEST0 */
+        return s->ctest0;
+       case 0x15: /* CTEST1 */
+        return 0xf0; // FMT and FFL are always empty
+       case 0x16: /* CTEST2 */
+        tmp = s->ctest2 | LSI_CTEST2_DACK;
+        if (s->istat & LSI_ISTAT_SIGP) {
+            s->istat &= ~LSI_ISTAT_SIGP;
+            tmp |= LSI_CTEST2_SIGP;
+        }
+        return tmp;
+       case 0x17: /* CTEST3 */
+               return s->ctest3;
+       case 0x18: /* CTEST4 */
+               return s->ctest4;
+       case 0x19: /* CTEST5 */
+               return s->ctest5;
+       case 0x1a: /* CTEST6 */
+               return s->ctest6;
+       case 0x1b: /* CTEST7 */
+               return s->ctest7;
+    CASE_GET_REG32(temp, 0x1c)
+    case 0x20: /* DFIFO */
+        return 0;
+       case 0x21: /* ISTAT */
+               return s->istat;
+       case 0x22: /* CTEST8 */
+               return (s->ctest8 | (2 << 4)) & ~0x08; // clear CLF
+       case 0x23: /* LCRC */
+               return s->lcrc;
+    CASE_GET_REG24(dbc, 0x24)
+    case 0x27: /* DCMD */
+        return s->dcmd;
+    CASE_GET_REG32(dnad, 0x28)
+    CASE_GET_REG32(dsp, 0x2c)
+    CASE_GET_REG32(dsps, 0x30)
+    CASE_GET_REG32(scratch, 0x34)
+       case 0x38: /* DMODE */
+        return s->dmode;
+       case 0x3a: /* DWT */
+               return s->dwt;
+    case 0x3b: /* DCNTL */
+        return s->dcntl;
+       }
+#undef CASE_GET_REG24
+#undef CASE_GET_REG32
+       write_log ("read unknown register %02X\n", offset);
+       return 0;
+}
+static uint8_t lsi_reg_readb(LSIState *s, int offset)
+{
+       uint8_t v = lsi_reg_readb2(s, offset);
+#ifdef DEBUG_LSI_REG
+    DPRINTF("Read reg %x: %02X\n", offset, v);
+#endif
+       return v;
+}
+
+static void lsi_reg_writeb(LSIState *s, int offset, uint8_t val)
+{
+#define CASE_SET_REG24(name, addr) \
+    case addr    : s->name &= 0xffffff00; s->name |= val;       break; \
+    case addr + 1: s->name &= 0xffff00ff; s->name |= val << 8;  break; \
+    case addr + 2: s->name &= 0xff00ffff; s->name |= val << 16; break;
+
+#define CASE_SET_REG32(name, addr) \
+    case addr    : s->name &= 0xffffff00; s->name |= val;       break; \
+    case addr + 1: s->name &= 0xffff00ff; s->name |= val << 8;  break; \
+    case addr + 2: s->name &= 0xff00ffff; s->name |= val << 16; break; \
+    case addr + 3: s->name &= 0x00ffffff; s->name |= val << 24; break;
+
+#ifdef DEBUG_LSI_REG
+    DPRINTF("Write reg %x = %02x\n", offset, val);
+#endif
+    switch (offset) {
+    case 0x00: /* SCNTL0 */
+        s->scntl0 = val;
+        if (val & LSI_SCNTL0_START) {
+            BADF("Start sequence not implemented\n");
+        }
+        break;
+    case 0x01: /* SCNTL1 */
+        s->scntl1 = val;
+        if (val & LSI_SCNTL1_ADB) {
+            BADF("Immediate Arbritration not implemented\n");
+        }
+        if (val & LSI_SCNTL1_RST) {
+            if (!(s->sstat0 & LSI_SSTAT0_RST)) {
+//                qbus_reset_all(&s->bus.qbus);
+                s->sstat0 |= LSI_SSTAT0_RST;
+                lsi_script_scsi_interrupt(s, LSI_SSTAT0_RST);
+            }
+        } else {
+            s->sstat0 &= ~LSI_SSTAT0_RST;
+        }
+        break;
+    case 0x03: /* SIEN */
+        s->sien0 = val;
+        lsi_update_irq(s);
+        break;
+    case 0x04: /* SCID */
+        s->scid = val;
+        break;
+    case 0x05: /* SXFER */
+        s->sxfer = val;
+        break;
+       case 0x0b: /* SBCL */
+               lsi_set_phase (s, val & PHASE_MASK);
+               break;
+    case 0x0c: case 0x0d: case 0x0e: case 0x0f:
+        /* Linux writes to these readonly registers on startup.  */
+        return;
+    CASE_SET_REG32(dsa, 0x10)
+       case 0x14: /* CTEST0 */
+        s->ctest0 = (val & 0xfe) | (s->ctest0 & 1);
+        break;
+       case 0x15: /* CTEST1, read-only */
+               break;
+       case 0x16: /* CTEST2, read-only */
+               break;
+       case 0x17: /* CTEST3 */
+               s->ctest3 = val;
+               break;
+       case 0x18: /* CTEST4 */
+        s->ctest4 = val;
+        break;
+       case 0x19: /* CTEST5 */
+        s->ctest5 = val;
+        break;
+       case 0x1a: /* CTEST6 */
+        s->ctest6 = val;
+        break;
+       case 0x1b: /* CTEST7 */
+               s->ctest7 = val;
+               break;
+    CASE_SET_REG32(temp, 0x1c)
+       
+       case 0x21: /* ISTAT */
+        s->istat = (s->istat & 0x0f) | (val & 0xf0);
+        if (val & LSI_ISTAT_ABRT) {
+            lsi_script_dma_interrupt(s, LSI_DSTAT_ABRT);
+        }
+        if (s->waiting == 1 && (val & LSI_ISTAT_SIGP)) {
+            DPRINTF("Woken by SIGP\n");
+            s->waiting = 0;
+            s->dsp = s->dnad;
+            lsi_execute_script(s);
+        }
+        if (val & LSI_ISTAT_RST) {
+            ;//qdev_reset_all(DEVICE(s));
+        }
+        break;
+       case 0x22: /* CTEST8 */
+               s->ctest8 = val;
+       break;
+       case 0x23: /* LCRC */
+               s->lcrc = 0;
+       break;
+    CASE_SET_REG24(dbc, 0x24)
+    CASE_SET_REG32(dnad, 0x28)
+    case 0x2c: /* DSP[0:7] */
+        s->dsp &= 0xffffff00;
+        s->dsp |= val;
+        break;
+    case 0x2d: /* DSP[8:15] */
+        s->dsp &= 0xffff00ff;
+        s->dsp |= val << 8;
+        break;
+    case 0x2e: /* DSP[16:23] */
+        s->dsp &= 0xff00ffff;
+        s->dsp |= val << 16;
+        break;
+    case 0x2f: /* DSP[24:31] */
+        s->dsp &= 0x00ffffff;
+        s->dsp |= val << 24;
+        if ((s->dmode & LSI_DMODE_MAN) == 0) {
+                       s->waiting = 0;
+            lsi_execute_script(s);
+               }
+        break;
+    CASE_SET_REG32(scratch, 0x34)
+       case 0x38: /* DMODE */
+#if 0
+               if (val & (LSI_DMODE_SIOM | LSI_DMODE_DIOM)) {
+            BADF("IO mappings not implemented\n");
+        }
+#endif
+               s->dmode = val;
+        break;
+    case 0x39: /* DIEN */
+        s->dien = val;
+        lsi_update_irq(s);
+        break;
+       case 0x3a: /* DWT */
+               s->dwt = val;
+               break;
+    case 0x3b: /* DCNTL */
+        s->dcntl = val & ~(LSI_DCNTL_PFF | LSI_DCNTL_STD);
+               if ((val & LSI_DCNTL_STD) && (s->dmode & LSI_DMODE_MAN) == 0)
+            lsi_execute_script(s);
+        break;
+       default:
+               write_log ("write unknown register %02X\n", offset);
+       break;
+       }
+#undef CASE_SET_REG24
+#undef CASE_SET_REG32
+}
+
+#if 0
+static void lsi_reg_writeb(LSIState *s, int offset, uint8_t val)
+{
+#define CASE_SET_REG24(name, addr) \
+    case addr    : s->name &= 0xffffff00; s->name |= val;       break; \
+    case addr + 1: s->name &= 0xffff00ff; s->name |= val << 8;  break; \
+    case addr + 2: s->name &= 0xff00ffff; s->name |= val << 16; break;
+
+#define CASE_SET_REG32(name, addr) \
+    case addr    : s->name &= 0xffffff00; s->name |= val;       break; \
+    case addr + 1: s->name &= 0xffff00ff; s->name |= val << 8;  break; \
+    case addr + 2: s->name &= 0xff00ffff; s->name |= val << 16; break; \
+    case addr + 3: s->name &= 0x00ffffff; s->name |= val << 24; break;
+
+#ifdef DEBUG_LSI_REG
+    DPRINTF("Write reg %x = %02x\n", offset, val);
+#endif
+    switch (offset) {
+    case 0x00: /* SCNTL0 */
+        s->scntl0 = val;
+        if (val & LSI_SCNTL0_START) {
+            BADF("Start sequence not implemented\n");
+        }
+        break;
+    case 0x01: /* SCNTL1 */
+        s->scntl1 = val & ~LSI_SCNTL1_SST;
+        if (val & LSI_SCNTL1_IARB) {
+            BADF("Immediate Arbritration not implemented\n");
+        }
+        if (val & LSI_SCNTL1_RST) {
+            if (!(s->sstat0 & LSI_SSTAT0_RST)) {
+//                qbus_reset_all(&s->bus.qbus);
+                s->sstat0 |= LSI_SSTAT0_RST;
+                lsi_script_scsi_interrupt(s, LSI_SIST0_RST, 0);
+            }
+        } else {
+            s->sstat0 &= ~LSI_SSTAT0_RST;
+        }
+        break;
+    case 0x02: /* SCNTL2 */
+        val &= ~(LSI_SCNTL2_WSR | LSI_SCNTL2_WSS);
+        s->scntl2 = val;
+        break;
+    case 0x03: /* SCNTL3 */
+        s->scntl3 = val;
+        break;
+    case 0x04: /* SCID */
+        s->scid = val;
+        break;
+    case 0x05: /* SXFER */
+        s->sxfer = val;
+        break;
+    case 0x06: /* SDID */
+        if ((s->ssid & 0x80) && (val & 0xf) != (s->ssid & 0xf)) {
+            BADF("Destination ID does not match SSID\n");
+        }
+        s->sdid = val & 0xf;
+        break;
+    case 0x07: /* GPREG0 */
+        break;
+    case 0x08: /* SFBR */
+        /* The CPU is not allowed to write to this register.  However the
+           SCRIPTS register move instructions are.  */
+        s->sfbr = val;
+        break;
+    case 0x0a: case 0x0b:
+        /* Openserver writes to these readonly registers on startup */
+       return;
+    case 0x0c: case 0x0d: case 0x0e: case 0x0f:
+        /* Linux writes to these readonly registers on startup.  */
+        return;
+    CASE_SET_REG32(dsa, 0x10)
+    case 0x14: /* ISTAT0 */
+        s->istat0 = (s->istat0 & 0x0f) | (val & 0xf0);
+        if (val & LSI_ISTAT0_ABRT) {
+            lsi_script_dma_interrupt(s, LSI_DSTAT_ABRT);
+        }
+        if (val & LSI_ISTAT0_INTF) {
+            s->istat0 &= ~LSI_ISTAT0_INTF;
+            lsi_update_irq(s);
+        }
+        if (s->waiting == 1 && val & LSI_ISTAT0_SIGP) {
+            DPRINTF("Woken by SIGP\n");
+            s->waiting = 0;
+            s->dsp = s->dnad;
+            lsi_execute_script(s);
+        }
+//        if (val & LSI_ISTAT0_SRST) {
+//            qdev_reset_all(DEVICE(s));
+//        }
+        break;
+    case 0x16: /* MBOX0 */
+        s->mbox0 = val;
+        break;
+    case 0x17: /* MBOX1 */
+        s->mbox1 = val;
+        break;
+    case 0x18: /* CTEST0 */
+        /* nothing to do */
+        break;
+    case 0x1a: /* CTEST2 */
+       s->ctest2 = val & LSI_CTEST2_PCICIE;
+       break;
+    case 0x1b: /* CTEST3 */
+        s->ctest3 = val & 0x0f;
+        break;
+    CASE_SET_REG32(temp, 0x1c)
+    case 0x21: /* CTEST4 */
+        if (val & 7) {
+           BADF("Unimplemented CTEST4-FBL 0x%x\n", val);
+        }
+        s->ctest4 = val;
+        break;
+    case 0x22: /* CTEST5 */
+        if (val & (LSI_CTEST5_ADCK | LSI_CTEST5_BBCK)) {
+            BADF("CTEST5 DMA increment not implemented\n");
+                       val &= ~(LSI_CTEST5_ADCK | LSI_CTEST5_BBCK);
+        }
+        s->ctest5 = val;
+        break;
+    CASE_SET_REG24(dbc, 0x24)
+    CASE_SET_REG32(dnad, 0x28)
+    case 0x2c: /* DSP[0:7] */
+        s->dsp &= 0xffffff00;
+        s->dsp |= val;
+        break;
+    case 0x2d: /* DSP[8:15] */
+        s->dsp &= 0xffff00ff;
+        s->dsp |= val << 8;
+        break;
+    case 0x2e: /* DSP[16:23] */
+        s->dsp &= 0xff00ffff;
+        s->dsp |= val << 16;
+        break;
+    case 0x2f: /* DSP[24:31] */
+        s->dsp &= 0x00ffffff;
+        s->dsp |= val << 24;
+        if ((s->dmode & LSI_DMODE_MAN) == 0
+            && (s->istat1 & LSI_ISTAT1_SRUN) == 0)
+            lsi_execute_script(s);
+        break;
+    CASE_SET_REG32(dsps, 0x30)
+    CASE_SET_REG32(scratch[0], 0x34)
+    case 0x38: /* DMODE */
+        if (val & (LSI_DMODE_SIOM | LSI_DMODE_DIOM)) {
+            BADF("IO mappings not implemented\n");
+        }
+        s->dmode = val;
+        break;
+    case 0x39: /* DIEN */
+        s->dien = val;
+        lsi_update_irq(s);
+        break;
+    case 0x3a: /* SBR */
+        s->sbr = val;
+        break;
+    case 0x3b: /* DCNTL */
+        s->dcntl = val & ~(LSI_DCNTL_PFF | LSI_DCNTL_STD);
+        if ((val & LSI_DCNTL_STD) && (s->istat1 & LSI_ISTAT1_SRUN) == 0)
+            lsi_execute_script(s);
+        break;
+    case 0x40: /* SIEN0 */
+        s->sien0 = val;
+        lsi_update_irq(s);
+        break;
+    case 0x41: /* SIEN1 */
+        s->sien1 = val;
+        lsi_update_irq(s);
+        break;
+    case 0x47: /* GPCNTL0 */
+        break;
+    case 0x48: /* STIME0 */
+        s->stime0 = val;
+        break;
+    case 0x49: /* STIME1 */
+        if (val & 0xf) {
+            DPRINTF("General purpose timer not implemented\n");
+            /* ??? Raising the interrupt immediately seems to be sufficient
+               to keep the FreeBSD driver happy.  */
+            lsi_script_scsi_interrupt(s, 0, LSI_SIST1_GEN);
+        }
+        break;
+    case 0x4a: /* RESPID0 */
+        s->respid0 = val;
+        break;
+    case 0x4b: /* RESPID1 */
+        s->respid1 = val;
+        break;
+    case 0x4d: /* STEST1 */
+        s->stest1 = val;
+        break;
+    case 0x4e: /* STEST2 */
+        if (val & 1) {
+            BADF("Low level mode not implemented\n");
+        }
+        s->stest2 = val;
+        break;
+    case 0x4f: /* STEST3 */
+        if (val & 0x41) {
+            BADF("SCSI FIFO test mode not implemented\n");
+        }
+        s->stest3 = val;
+        break;
+    case 0x56: /* CCNTL0 */
+        s->ccntl0 = val;
+        break;
+    case 0x57: /* CCNTL1 */
+        s->ccntl1 = val;
+        break;
+    CASE_SET_REG32(mmrs, 0xa0)
+    CASE_SET_REG32(mmws, 0xa4)
+    CASE_SET_REG32(sfs, 0xa8)
+    CASE_SET_REG32(drs, 0xac)
+    CASE_SET_REG32(sbms, 0xb0)
+    CASE_SET_REG32(dbms, 0xb4)
+    CASE_SET_REG32(dnad64, 0xb8)
+    CASE_SET_REG32(pmjad1, 0xc0)
+    CASE_SET_REG32(pmjad2, 0xc4)
+    CASE_SET_REG32(rbc, 0xc8)
+    CASE_SET_REG32(ua, 0xcc)
+    CASE_SET_REG32(ia, 0xd4)
+    CASE_SET_REG32(sbc, 0xd8)
+    CASE_SET_REG32(csbc, 0xdc)
+    default:
+        if (offset >= 0x5c && offset < 0xa0) {
+            int n;
+            int shift;
+            n = (offset - 0x58) >> 2;
+            shift = (offset & 3) * 8;
+            s->scratch[n] = deposit32(s->scratch[n], shift, 8, val);
+        } else {
+            BADF("Unhandled writeb 0x%x = 0x%x\n", offset, val);
+        }
+    }
+#undef CASE_SET_REG24
+#undef CASE_SET_REG32
+}
+#endif
+
+void lsi710_mmio_write(void *opaque, hwaddr addr,
+                           uint64_t val, unsigned size)
+{
+    LSIState *s = (LSIState*)opaque;
+
+    lsi_reg_writeb(s, addr & 0xff, val);
+}
+
+uint64_t lsi710_mmio_read(void *opaque, hwaddr addr,
+                              unsigned size)
+{
+    LSIState *s = (LSIState*)opaque;
+
+    return lsi_reg_readb(s, addr & 0xff);
+}
+
+#if 0
+static const MemoryRegionOps lsi_mmio_ops = {
+    lsi_mmio_read,
+    lsi_mmio_write,
+    DEVICE_NATIVE_ENDIAN,
+    {
+        1,
+        1,
+    },
+};
+
+static void lsi_ram_write(void *opaque, hwaddr addr,
+                          uint64_t val, unsigned size)
+{
+    LSIState *s = (LSIState*)opaque;
+    uint32_t newval;
+    uint32_t mask;
+    int shift;
+
+    newval = s->script_ram[addr >> 2];
+    shift = (addr & 3) * 8;
+    mask = ((uint64_t)1 << (size * 8)) - 1;
+    newval &= ~(mask << shift);
+    newval |= val << shift;
+    s->script_ram[addr >> 2] = newval;
+}
+
+static uint64_t lsi_ram_read(void *opaque, hwaddr addr,
+                             unsigned size)
+{
+    LSIState *s = (LSIState*)opaque;
+    uint32_t val;
+    uint32_t mask;
+
+    val = s->script_ram[addr >> 2];
+    mask = ((uint64_t)1 << (size * 8)) - 1;
+    val >>= (addr & 3) * 8;
+    return val & mask;
+}
+
+static const MemoryRegionOps lsi_ram_ops = {
+    lsi_ram_read,
+    lsi_ram_write,
+    DEVICE_NATIVE_ENDIAN,
+};
+
+static uint64_t lsi_io_read(void *opaque, hwaddr addr,
+                            unsigned size)
+{
+    LSIState *s = (LSIState*)opaque;
+    return lsi_reg_readb(s, addr & 0xff);
+}
+
+static void lsi_io_write(void *opaque, hwaddr addr,
+                         uint64_t val, unsigned size)
+{
+    LSIState *s = (LSIState*)opaque;
+    lsi_reg_writeb(s, addr & 0xff, val);
+}
+
+static const MemoryRegionOps lsi_io_ops = {
+    lsi_io_read,
+    lsi_io_write,
+    DEVICE_NATIVE_ENDIAN,
+    {
+        1,
+        1,
+    },
+};
+#endif
+
+void lsi710_scsi_reset(DeviceState *dev, void *privdata)
+{
+    LSIState *s = LSI53C895A(dev);
+
+    lsi_soft_reset(s);
+       s->bus.privdata = privdata;
+}
+
+void lsi710_scsi_init(DeviceState *dev)
+{
+       dev->lsistate = calloc (sizeof(LSIState), 1);
+}
+
+#if 0
+static void lsi_pre_save(void *opaque)
+{
+    LSIState *s = opaque;
+
+    if (s->current) {
+        assert(s->current->dma_buf == NULL);
+        assert(s->current->dma_len == 0);
+    }
+    assert(QTAILQ_EMPTY(&s->queue));
+}
+
+static const VMStateDescription vmstate_lsi_scsi = {
+    .name = "lsiscsi",
+    .version_id = 0,
+    .minimum_version_id = 0,
+    .minimum_version_id_old = 0,
+    .pre_save = lsi_pre_save,
+    .fields      = (VMStateField []) {
+        VMSTATE_PCI_DEVICE(parent_obj, LSIState),
+
+        VMSTATE_INT32(carry, LSIState),
+        VMSTATE_INT32(status, LSIState),
+        VMSTATE_INT32(msg_action, LSIState),
+        VMSTATE_INT32(msg_len, LSIState),
+        VMSTATE_BUFFER(msg, LSIState),
+        VMSTATE_INT32(waiting, LSIState),
+
+        VMSTATE_UINT32(dsa, LSIState),
+        VMSTATE_UINT32(temp, LSIState),
+        VMSTATE_UINT32(dnad, LSIState),
+        VMSTATE_UINT32(dbc, LSIState),
+        VMSTATE_UINT8(istat0, LSIState),
+        VMSTATE_UINT8(istat1, LSIState),
+        VMSTATE_UINT8(dcmd, LSIState),
+        VMSTATE_UINT8(dstat, LSIState),
+        VMSTATE_UINT8(dien, LSIState),
+        VMSTATE_UINT8(sist0, LSIState),
+        VMSTATE_UINT8(sist1, LSIState),
+        VMSTATE_UINT8(sien0, LSIState),
+        VMSTATE_UINT8(sien1, LSIState),
+        VMSTATE_UINT8(mbox0, LSIState),
+        VMSTATE_UINT8(mbox1, LSIState),
+        VMSTATE_UINT8(dfifo, LSIState),
+        VMSTATE_UINT8(ctest2, LSIState),
+        VMSTATE_UINT8(ctest3, LSIState),
+        VMSTATE_UINT8(ctest4, LSIState),
+        VMSTATE_UINT8(ctest5, LSIState),
+        VMSTATE_UINT8(ccntl0, LSIState),
+        VMSTATE_UINT8(ccntl1, LSIState),
+        VMSTATE_UINT32(dsp, LSIState),
+        VMSTATE_UINT32(dsps, LSIState),
+        VMSTATE_UINT8(dmode, LSIState),
+        VMSTATE_UINT8(dcntl, LSIState),
+        VMSTATE_UINT8(scntl0, LSIState),
+        VMSTATE_UINT8(scntl1, LSIState),
+        VMSTATE_UINT8(scntl2, LSIState),
+        VMSTATE_UINT8(scntl3, LSIState),
+        VMSTATE_UINT8(sstat0, LSIState),
+        VMSTATE_UINT8(sstat1, LSIState),
+        VMSTATE_UINT8(scid, LSIState),
+        VMSTATE_UINT8(sxfer, LSIState),
+        VMSTATE_UINT8(socl, LSIState),
+        VMSTATE_UINT8(sdid, LSIState),
+        VMSTATE_UINT8(ssid, LSIState),
+        VMSTATE_UINT8(sfbr, LSIState),
+        VMSTATE_UINT8(stest1, LSIState),
+        VMSTATE_UINT8(stest2, LSIState),
+        VMSTATE_UINT8(stest3, LSIState),
+        VMSTATE_UINT8(sidl, LSIState),
+        VMSTATE_UINT8(stime0, LSIState),
+        VMSTATE_UINT8(respid0, LSIState),
+        VMSTATE_UINT8(respid1, LSIState),
+        VMSTATE_UINT32(mmrs, LSIState),
+        VMSTATE_UINT32(mmws, LSIState),
+        VMSTATE_UINT32(sfs, LSIState),
+        VMSTATE_UINT32(drs, LSIState),
+        VMSTATE_UINT32(sbms, LSIState),
+        VMSTATE_UINT32(dbms, LSIState),
+        VMSTATE_UINT32(dnad64, LSIState),
+        VMSTATE_UINT32(pmjad1, LSIState),
+        VMSTATE_UINT32(pmjad2, LSIState),
+        VMSTATE_UINT32(rbc, LSIState),
+        VMSTATE_UINT32(ua, LSIState),
+        VMSTATE_UINT32(ia, LSIState),
+        VMSTATE_UINT32(sbc, LSIState),
+        VMSTATE_UINT32(csbc, LSIState),
+        VMSTATE_BUFFER_UNSAFE(scratch, LSIState, 0, 18 * sizeof(uint32_t)),
+        VMSTATE_UINT8(sbr, LSIState),
+
+        VMSTATE_BUFFER_UNSAFE(script_ram, LSIState, 0, 2048 * sizeof(uint32_t)),
+        VMSTATE_END_OF_LIST()
+    }
+};
+
+static void lsi_scsi_uninit(PCIDevice *d)
+{
+    LSIState *s = LSI53C895A(d);
+
+    memory_region_destroy(&s->mmio_io);
+    memory_region_destroy(&s->ram_io);
+    memory_region_destroy(&s->io_io);
+}
+
+static const struct SCSIBusInfo lsi_scsi_info = {
+    .tcq = true,
+    .max_target = LSI_MAX_DEVS,
+    .max_lun = 0,  /* LUN support is buggy */
+
+    .transfer_data = lsi_transfer_data,
+    .complete = lsi_command_complete,
+    .cancel = lsi_request_cancelled
+};
+
+static int lsi_scsi_init(PCIDevice *dev)
+{
+    LSIState *s = LSI53C895A(dev);
+    DeviceState *d = DEVICE(dev);
+    uint8_t *pci_conf;
+    Error *err = NULL;
+
+    pci_conf = dev->config;
+
+    /* PCI latency timer = 255 */
+    pci_conf[PCI_LATENCY_TIMER] = 0xff;
+    /* Interrupt pin A */
+    pci_conf[PCI_INTERRUPT_PIN] = 0x01;
+
+    memory_region_init_io(&s->mmio_io, OBJECT(s), &lsi_mmio_ops, s,
+                          "lsi-mmio", 0x400);
+    memory_region_init_io(&s->ram_io, OBJECT(s), &lsi_ram_ops, s,
+                          "lsi-ram", 0x2000);
+    memory_region_init_io(&s->io_io, OBJECT(s), &lsi_io_ops, s,
+                          "lsi-io", 256);
+
+    pci_register_bar(dev, 0, PCI_BASE_ADDRESS_SPACE_IO, &s->io_io);
+    pci_register_bar(dev, 1, PCI_BASE_ADDRESS_SPACE_MEMORY, &s->mmio_io);
+    pci_register_bar(dev, 2, PCI_BASE_ADDRESS_SPACE_MEMORY, &s->ram_io);
+    QTAILQ_INIT(&s->queue);
+
+    scsi_bus_new(&s->bus, sizeof(s->bus), d, &lsi_scsi_info, NULL);
+    if (!d->hotplugged) {
+        scsi_bus_legacy_handle_cmdline(&s->bus, &err);
+        if (err != NULL) {
+            error_free(err);
+            return -1;
+        }
+    }
+    return 0;
+}
+
+static void lsi_class_init(ObjectClass *klass, void *data)
+{
+    DeviceClass *dc = DEVICE_CLASS(klass);
+    PCIDeviceClass *k = PCI_DEVICE_CLASS(klass);
+
+    k->init = lsi_scsi_init;
+    k->exit = lsi_scsi_uninit;
+    k->vendor_id = PCI_VENDOR_ID_LSI_LOGIC;
+    k->device_id = PCI_DEVICE_ID_LSI_53C895A;
+    k->class_id = PCI_CLASS_STORAGE_SCSI;
+    k->subsystem_id = 0x1000;
+    dc->reset = lsi_scsi_reset;
+    dc->vmsd = &vmstate_lsi_scsi;
+    set_bit(DEVICE_CATEGORY_STORAGE, dc->categories);
+}
+
+static const TypeInfo lsi_info = {
+    .name          = TYPE_LSI53C895A,
+    .parent        = TYPE_PCI_DEVICE,
+    .instance_size = sizeof(LSIState),
+    .class_init    = lsi_class_init,
+};
+
+static void lsi53c810_class_init(ObjectClass *klass, void *data)
+{
+    PCIDeviceClass *k = PCI_DEVICE_CLASS(klass);
+
+    k->device_id = PCI_DEVICE_ID_LSI_53C810;
+}
+
+static TypeInfo lsi53c810_info = {
+    .name          = TYPE_LSI53C810,
+    .parent        = TYPE_LSI53C895A,
+    .class_init    = lsi53c810_class_init,
+};
+
+static void lsi53c895a_register_types(void)
+{
+    type_register_static(&lsi_info);
+    type_register_static(&lsi53c810_info);
+}
+
+type_init(lsi53c895a_register_types)
+#endif
index 59724161a4bdb068d99a06ba2cc41f8ee8f7e877..5be343e1f172a0f82a61e4544056e886a54642f9 100644 (file)
@@ -13,8 +13,6 @@
  * as well-behaved operating systems will not try to use them.
  */
 
-/* Hacked to support LSI53C710 for UAE by Toni Wilen */
-
 #include <assert.h>
 
 #include "qemuuaeglue.h"
@@ -36,24 +34,23 @@ do { write_log("lsi_scsi: error: " fmt , ## __VA_ARGS__); } while (0)
 #else
 #define DPRINTF(fmt, ...) do {} while(0)
 #define BADF(fmt, ...) \
-do { write_log("lsi_scsi: error: " fmt , ## __VA_ARGS__);} while (0)
+do { write_log("lsi_scsi: error: " fmt , ## __VA_ARGS__); activate_debugger();} while (0)
 #endif
 
 #define LSI_MAX_DEVS 7
 
 #define LSI_SCNTL0_TRG    0x01
 #define LSI_SCNTL0_AAP    0x02
-#define LSI_SCNTL0_EPG    0x08
 #define LSI_SCNTL0_EPC    0x08
-#define LSI_SCNTL0_WATN   0x10,
+#define LSI_SCNTL0_WATN   0x10
 #define LSI_SCNTL0_START  0x20
 
-#define LSI_SCNTL1_RCV    0x01
-#define LSI_SCNTL1_SND   0x02
+#define LSI_SCNTL1_SST    0x01
+#define LSI_SCNTL1_IARB   0x02
 #define LSI_SCNTL1_AESP   0x04
 #define LSI_SCNTL1_RST    0x08
 #define LSI_SCNTL1_CON    0x10
-#define LSI_SCNTL1_ESR    0x20
+#define LSI_SCNTL1_DHP    0x20
 #define LSI_SCNTL1_ADB    0x40
 #define LSI_SCNTL1_EXC    0x80
 
@@ -66,39 +63,41 @@ do { write_log("lsi_scsi: error: " fmt , ## __VA_ARGS__);} while (0)
 #define LSI_SCNTL2_CHM    0x40
 #define LSI_SCNTL2_SDU    0x80
 
-#define LSI_ISTAT_DIP    0x01
-#define LSI_ISTAT_SIP    0x02
-//#define LSI_ISTAT0_INTF   0x04
-#define LSI_ISTAT_CON    0x08
-//#define LSI_ISTAT0_SEM    0x10
-#define LSI_ISTAT_SIGP   0x20
-#define LSI_ISTAT_RST    0x40
-#define LSI_ISTAT_ABRT   0x80
+#define LSI_ISTAT0_DIP    0x01
+#define LSI_ISTAT0_SIP    0x02
+#define LSI_ISTAT0_INTF   0x04
+#define LSI_ISTAT0_CON    0x08
+#define LSI_ISTAT0_SEM    0x10
+#define LSI_ISTAT0_SIGP   0x20
+#define LSI_ISTAT0_SRST   0x40
+#define LSI_ISTAT0_ABRT   0x80
 
-#define LSI_SSTAT1_WOA    0x04
+#define LSI_ISTAT1_SI     0x01
+#define LSI_ISTAT1_SRUN   0x02
+#define LSI_ISTAT1_FLSH   0x04
 
-#define LSI_SSTAT0_PAR    0x01
+#define LSI_SSTAT0_SDP0   0x01
 #define LSI_SSTAT0_RST    0x02
-#define LSI_SSTAT0_UDC    0x04
-#define LSI_SSTAT0_SGE    0x08
-#define LSI_SSTAT0_SEL    0x10
-#define LSI_SSTAT0_STO    0x20
-#define LSI_SSTAT0_FCMP   0x40
-#define LSI_SSTAT0_MA     0x80
-
-//#define LSI_SIST0_PAR     0x01
-//#define LSI_SIST0_RST     0x02
-//#define LSI_SIST0_UDC     0x04
-//#define LSI_SIST0_SGE     0x08
-//#define LSI_SIST0_RSL     0x10
-//#define LSI_SIST0_SEL     0x20
-//#define LSI_SIST0_CMP     0x40
-//#define LSI_SIST0_MA      0x80
-
-//#define LSI_SIST1_HTH     0x01
-//#define LSI_SIST1_GEN     0x02
-//#define LSI_SIST1_STO     0x04
-//#define LSI_SIST1_SBMC    0x10
+#define LSI_SSTAT0_WOA    0x04
+#define LSI_SSTAT0_LOA    0x08
+#define LSI_SSTAT0_AIP    0x10
+#define LSI_SSTAT0_OLF    0x20
+#define LSI_SSTAT0_ORF    0x40
+#define LSI_SSTAT0_ILF    0x80
+
+#define LSI_SIST0_PAR     0x01
+#define LSI_SIST0_RST     0x02
+#define LSI_SIST0_UDC     0x04
+#define LSI_SIST0_SGE     0x08
+#define LSI_SIST0_RSL     0x10
+#define LSI_SIST0_SEL     0x20
+#define LSI_SIST0_CMP     0x40
+#define LSI_SIST0_MA      0x80
+
+#define LSI_SIST1_HTH     0x01
+#define LSI_SIST1_GEN     0x02
+#define LSI_SIST1_STO     0x04
+#define LSI_SIST1_SBMC    0x10
 
 #define LSI_SOCL_IO       0x01
 #define LSI_SOCL_CD       0x02
@@ -127,9 +126,11 @@ do { write_log("lsi_scsi: error: " fmt , ## __VA_ARGS__);} while (0)
 #define LSI_DCNTL_CLSE    0x80
 
 #define LSI_DMODE_MAN     0x01
-#define LSI_DMODE_UO      0x02
-#define LSI_DMODE_FAM     0x04
-#define LSI_DMODE_PD      0x08
+#define LSI_DMODE_BOF     0x02
+#define LSI_DMODE_ERMP    0x04
+#define LSI_DMODE_ERL     0x08
+#define LSI_DMODE_DIOM    0x10
+#define LSI_DMODE_SIOM    0x20
 
 #define LSI_CTEST2_DACK   0x01
 #define LSI_CTEST2_DREQ   0x02
@@ -159,18 +160,11 @@ do { write_log("lsi_scsi: error: " fmt , ## __VA_ARGS__);} while (0)
 #define LSI_CCNTL1_DDAC      0x08
 #define LSI_CCNTL1_ZMOD      0x80
 
-#define LSI_SBCL_IO  0x01
-#define LSI_SBCL_CD  0x02
-#define LSI_SBCL_MSG 0x04
-#define LSI_SBCL_ATN 0x08
-#define LSI_SBCL_SEL 0x10
-#define LSI_SBCL_BSY 0x20
-#define LSI_SBCL_ACK 0x40
-#define LSI_SBCL_REQ 0x80
-
 /* Enable Response to Reselection */
 #define LSI_SCID_RRE      0x60
 
+#define LSI_CCNTL1_40BIT (LSI_CCNTL1_EN64TIBMV|LSI_CCNTL1_64TIMOD)
+
 #define PHASE_DO          0
 #define PHASE_DI          1
 #define PHASE_CMD         2
@@ -197,7 +191,7 @@ typedef struct lsi_request {
 
 typedef struct {
     /*< private >*/
-    //PCIDevice parent_obj;
+   // PCIDevice parent_obj;
     /*< public >*/
 
     //MemoryRegion mmio_io;
@@ -228,63 +222,83 @@ typedef struct {
     uint32_t temp;
     uint32_t dnad;
     uint32_t dbc;
-    uint8_t istat;
+    uint8_t istat0;
+    uint8_t istat1;
     uint8_t dcmd;
     uint8_t dstat;
     uint8_t dien;
-//    uint8_t sist0;
-//    uint8_t sist1;
+    uint8_t sist0;
+    uint8_t sist1;
     uint8_t sien0;
+    uint8_t sien1;
+    uint8_t mbox0;
+    uint8_t mbox1;
+    uint8_t dfifo;
     uint8_t ctest2;
     uint8_t ctest3;
     uint8_t ctest4;
     uint8_t ctest5;
+    uint8_t ccntl0;
+    uint8_t ccntl1;
     uint32_t dsp;
     uint32_t dsps;
     uint8_t dmode;
     uint8_t dcntl;
     uint8_t scntl0;
     uint8_t scntl1;
+    uint8_t scntl2;
+    uint8_t scntl3;
     uint8_t sstat0;
     uint8_t sstat1;
     uint8_t scid;
     uint8_t sxfer;
     uint8_t socl;
     uint8_t sdid;
+    uint8_t ssid;
     uint8_t sfbr;
+    uint8_t stest1;
+    uint8_t stest2;
+    uint8_t stest3;
     uint8_t sidl;
+    uint8_t stime0;
+    uint8_t respid0;
+    uint8_t respid1;
+    uint32_t mmrs;
+    uint32_t mmws;
+    uint32_t sfs;
+    uint32_t drs;
+    uint32_t sbms;
+    uint32_t dbms;
+    uint32_t dnad64;
+    uint32_t pmjad1;
+    uint32_t pmjad2;
+    uint32_t rbc;
+    uint32_t ua;
+    uint32_t ia;
     uint32_t sbc;
-    uint32_t scratch;
+    uint32_t csbc;
+    uint32_t scratch[18]; /* SCRATCHA-SCRATCHR */
     uint8_t sbr;
 
-       uint8_t ctest0;
-       uint8_t ctest1;
-       uint8_t ctest6;
-       uint8_t ctest7;
-       uint8_t ctest8;
-       uint8_t lcrc;
-       uint8_t sstat2;
-       uint8_t dwt;
-       uint8_t sbcl;
-       uint8_t script_active;
+    /* Script ram is stored as 32-bit words in host byteorder.  */
+    uint32_t script_ram[2048];
 } LSIState;
 
-//#define TYPE_LSI53C810  "lsi53c810"
-//#define TYPE_LSI53C895A "lsi53c895a"
+#define TYPE_LSI53C810  "lsi53c810"
+#define TYPE_LSI53C895A "lsi53c895a"
 
 #define LSI53C895A(obj) (LSIState*)obj->lsistate
- //((LSIState*)(OBJECT_CHECK(LSIState, (obj), TYPE_LSI53C895A)))
+//    OBJECT_CHECK(LSIState, (obj), TYPE_LSI53C895A)
 
 static inline int lsi_irq_on_rsl(LSIState *s)
 {
-       return 0; //return (s->sien0 & LSI_SIST0_RSL) && (s->scid & LSI_SCID_RRE);
+    return (s->sien0 & LSI_SIST0_RSL) && (s->scid & LSI_SCID_RRE);
 }
 
 static void lsi_soft_reset(LSIState *s)
 {
     DPRINTF("Reset\n");
     s->carry = 0;
-       memset (s, 0, sizeof LSIState);
 
     s->msg_action = 0;
     s->msg_len = 0;
@@ -293,40 +307,66 @@ static void lsi_soft_reset(LSIState *s)
     s->dnad = 0;
     s->dbc = 0;
     s->temp = 0;
-       s->scratch = 0;
-    s->istat = 0;
+    memset(s->scratch, 0, sizeof(s->scratch));
+    s->istat0 = 0;
+    s->istat1 = 0;
     s->dcmd = 0x40;
     s->dstat = LSI_DSTAT_DFE;
     s->dien = 0;
-//    s->sist0 = 0;
-//    s->sist1 = 0;
+    s->sist0 = 0;
+    s->sist1 = 0;
     s->sien0 = 0;
-//    s->sien1 = 0;
+    s->sien1 = 0;
+    s->mbox0 = 0;
+    s->mbox1 = 0;
+    s->dfifo = 0;
     s->ctest2 = LSI_CTEST2_DACK;
     s->ctest3 = 0;
     s->ctest4 = 0;
     s->ctest5 = 0;
+    s->ccntl0 = 0;
+    s->ccntl1 = 0;
     s->dsp = 0;
     s->dsps = 0;
     s->dmode = 0;
     s->dcntl = 0;
     s->scntl0 = 0xc0;
     s->scntl1 = 0;
+    s->scntl2 = 0;
+    s->scntl3 = 0;
     s->sstat0 = 0;
     s->sstat1 = 0;
-       s->sstat2 = 0;
-    s->scid = 0x80;
+    s->scid = 7;
     s->sxfer = 0;
     s->socl = 0;
     s->sdid = 0;
+    s->ssid = 0;
+    s->stest1 = 0;
+    s->stest2 = 0;
+    s->stest3 = 0;
     s->sidl = 0;
+    s->stime0 = 0;
+    s->respid0 = 0x80;
+    s->respid1 = 0;
+    s->mmrs = 0;
+    s->mmws = 0;
+    s->sfs = 0;
+    s->drs = 0;
+    s->sbms = 0;
+    s->dbms = 0;
+    s->dnad64 = 0;
+    s->pmjad1 = 0;
+    s->pmjad2 = 0;
+    s->rbc = 0;
+    s->ua = 0;
+    s->ia = 0;
     s->sbc = 0;
+    s->csbc = 0;
     s->sbr = 0;
     assert(QTAILQ_EMPTY(&s->queue));
     assert(!s->current);
 }
 
-#if 0
 static int lsi_dma_40bit(LSIState *s)
 {
     if ((s->ccntl1 & LSI_CCNTL1_40BIT) == LSI_CCNTL1_40BIT)
@@ -347,7 +387,6 @@ static int lsi_dma_64bit(LSIState *s)
         return 1;
     return 0;
 }
-#endif
 
 static uint8_t lsi_reg_readb(LSIState *s, int offset);
 static void lsi_reg_writeb(LSIState *s, int offset, uint8_t val);
@@ -364,7 +403,7 @@ static inline uint32_t read_dword(LSIState *s, uint32_t addr)
 
 static void lsi_stop_script(LSIState *s)
 {
-    s->script_active = 0;
+    s->istat1 &= ~LSI_ISTAT1_SRUN;
 }
 
 static void lsi_update_irq(LSIState *s)
@@ -381,22 +420,24 @@ static void lsi_update_irq(LSIState *s)
     if (s->dstat) {
         if (s->dstat & s->dien)
             level = 1;
-        s->istat |= LSI_ISTAT_DIP;
+        s->istat0 |= LSI_ISTAT0_DIP;
     } else {
-        s->istat &= ~LSI_ISTAT_DIP;
+        s->istat0 &= ~LSI_ISTAT0_DIP;
     }
 
-    if (s->sstat0) {
-        if ((s->sstat0 & s->sien0))
+    if (s->sist0 || s->sist1) {
+        if ((s->sist0 & s->sien0) || (s->sist1 & s->sien1))
             level = 1;
-        s->istat |= LSI_ISTAT_SIP;
+        s->istat0 |= LSI_ISTAT0_SIP;
     } else {
-        s->istat &= ~LSI_ISTAT_SIP;
+        s->istat0 &= ~LSI_ISTAT0_SIP;
     }
+    if (s->istat0 & LSI_ISTAT0_INTF)
+        level = 1;
 
     if (level != last_level) {
         DPRINTF("Update IRQ level %d dstat %02x sist %02x%02x\n",
-                level, s->dstat, s->sstat0, s->sstat1);
+                level, s->dstat, s->sist1, s->sist0);
         last_level = level;
     }
     pci_set_irq(d, level);
@@ -414,22 +455,22 @@ static void lsi_update_irq(LSIState *s)
 }
 
 /* Stop SCRIPTS execution and raise a SCSI interrupt.  */
-static void lsi_script_scsi_interrupt(LSIState *s, int stat0)
+static void lsi_script_scsi_interrupt(LSIState *s, int stat0, int stat1)
 {
     uint32_t mask0;
-    //uint32_t mask1;
+    uint32_t mask1;
 
     DPRINTF("SCSI Interrupt 0x%02x%02x prev 0x%02x%02x\n",
-            stat0, s->sstat0);
-    s->sstat0 |= stat0;
-    //s->sist1 |= stat1;
+            stat1, stat0, s->sist1, s->sist0);
+    s->sist0 |= stat0;
+    s->sist1 |= stat1;
     /* Stop processor on fatal or unmasked interrupt.  As a special hack
        we don't stop processing when raising STO.  Instead continue
        execution and stop at the next insn that accesses the SCSI bus.  */
-    mask0 = s->sien0 | ~(LSI_SSTAT0_FCMP | LSI_SSTAT0_SEL); // | LSI_SIST1_RSL);
-    //mask1 = s->sien1 | ~(LSI_SIST1_GEN | LSI_SIST1_HTH);
-    //mask1 &= ~LSI_SIST1_STO;
-    if (s->sstat0 & mask0) { // || s->sist1 & mask1) {
+    mask0 = s->sien0 | ~(LSI_SIST0_CMP | LSI_SIST0_SEL | LSI_SIST0_RSL);
+    mask1 = s->sien1 | ~(LSI_SIST1_GEN | LSI_SIST1_HTH);
+    mask1 &= ~LSI_SIST1_STO;
+    if (s->sist0 & mask0 || s->sist1 & mask1) {
         lsi_stop_script(s);
     }
     lsi_update_irq(s);
@@ -446,21 +487,25 @@ static void lsi_script_dma_interrupt(LSIState *s, int stat)
 
 static inline void lsi_set_phase(LSIState *s, int phase)
 {
-    s->sstat2 = (s->sstat2 & ~PHASE_MASK) | phase;
-       s->ctest0 &= ~1;
-       if (phase == PHASE_DI)
-               s->ctest0 |= 1;
-       s->sbcl &= ~LSI_SBCL_REQ;
+    s->sstat1 = (s->sstat1 & ~PHASE_MASK) | phase;
 }
 
 static void lsi_bad_phase(LSIState *s, int out, int new_phase)
 {
     /* Trigger a phase mismatch.  */
-    DPRINTF("Phase mismatch interrupt\n");
-    lsi_script_scsi_interrupt(s, LSI_SSTAT0_MA);
-    lsi_stop_script(s);
+    if (s->ccntl0 & LSI_CCNTL0_ENPMJ) {
+        if ((s->ccntl0 & LSI_CCNTL0_PMJCTL)) {
+            s->dsp = out ? s->pmjad1 : s->pmjad2;
+        } else {
+            s->dsp = (s->scntl2 & LSI_SCNTL2_WSR ? s->pmjad2 : s->pmjad1);
+        }
+        DPRINTF("Data phase mismatch jump to %08x\n", s->dsp);
+    } else {
+        DPRINTF("Phase mismatch interrupt\n");
+        lsi_script_scsi_interrupt(s, LSI_SIST0_MA, 0);
+        lsi_stop_script(s);
+    }
     lsi_set_phase(s, new_phase);
-       s->sbcl |= LSI_SBCL_REQ;
 }
 
 
@@ -478,13 +523,13 @@ static void lsi_resume_script(LSIState *s)
 static void lsi_disconnect(LSIState *s)
 {
     s->scntl1 &= ~LSI_SCNTL1_CON;
-    s->sstat2 &= ~PHASE_MASK;
+    s->sstat1 &= ~PHASE_MASK;
 }
 
 static void lsi_bad_selection(LSIState *s, uint32_t id)
 {
     DPRINTF("Selected absent target %d\n", id);
-    lsi_script_scsi_interrupt(s, LSI_SSTAT0_STO);
+    lsi_script_scsi_interrupt(s, 0, LSI_SIST1_STO);
     lsi_disconnect(s);
 }
 
@@ -512,17 +557,16 @@ static void lsi_do_dma(LSIState *s, int out)
         count = s->current->dma_len;
 
     addr = s->dnad;
-#if 0
-       /* both 40 and Table Indirect 64-bit DMAs store upper bits in dnad64 */
+    /* both 40 and Table Indirect 64-bit DMAs store upper bits in dnad64 */
     if (lsi_dma_40bit(s) || lsi_dma_ti64bit(s))
         addr |= ((uint64_t)s->dnad64 << 32);
     else if (s->dbms)
         addr |= ((uint64_t)s->dbms << 32);
     else if (s->sbms)
         addr |= ((uint64_t)s->sbms << 32);
-#endif
 
     DPRINTF("DMA addr=0x" DMA_ADDR_FMT " len=%d\n", addr, count);
+    s->csbc += count;
     s->dnad += count;
     s->dbc -= count;
      if (s->current->dma_buf == NULL) {
@@ -557,7 +601,7 @@ static void lsi_queue_command(LSIState *s)
     s->current = NULL;
 
     p->pending = 0;
-    p->out = (s->sstat2 & PHASE_MASK) == PHASE_DO;
+    p->out = (s->sstat1 & PHASE_MASK) == PHASE_DO;
 }
 
 /* Queue a byte for a MSG IN phase.  */
@@ -581,11 +625,11 @@ static void lsi_reselect(LSIState *s, lsi_request *p)
     s->current = p;
 
     id = (p->tag >> 8) & 0xf;
+    s->ssid = id | 0x80;
     /* LSI53C700 Family Compatibility, see LSI53C895A 4-73 */
     if (!(s->dcntl & LSI_DCNTL_COM)) {
         s->sfbr = 1 << (id & 0x7);
     }
-       s->lcrc = 0;
     DPRINTF("Reselected target %d\n", id);
     s->scntl1 |= LSI_SCNTL1_CON;
     lsi_set_phase(s, PHASE_MI);
@@ -598,7 +642,7 @@ static void lsi_reselect(LSIState *s, lsi_request *p)
     }
 
     if (lsi_irq_on_rsl(s)) {
-        lsi_script_scsi_interrupt(s, LSI_SSTAT0_SEL);
+        lsi_script_scsi_interrupt(s, LSI_SIST0_RSL, 0);
     }
 }
 
@@ -625,10 +669,10 @@ static void lsi_request_free(LSIState *s, lsi_request *p)
     g_free(p);
 }
 
-void lsi_request_cancelled(SCSIRequest *req)
+static void lsi_request_cancelled(SCSIRequest *req)
 {
     LSIState *s = LSI53C895A(req->bus->qbus.parent);
-    lsi_request *p = (lsi_request*)req->hba_private;
+       lsi_request *p = (lsi_request*)req->hba_private;
 
     req->hba_private = NULL;
     lsi_request_free(s, p);
@@ -652,7 +696,7 @@ static int lsi_queue_req(LSIState *s, SCSIRequest *req, uint32_t len)
        for service from the device driver. */
     if (s->waiting == 1 ||
         (lsi_irq_on_rsl(s) && !(s->scntl1 & LSI_SCNTL1_CON) &&
-         !(s->istat & (LSI_ISTAT_SIP | LSI_ISTAT_DIP)))) {
+         !(s->istat0 & (LSI_ISTAT0_SIP | LSI_ISTAT0_DIP)))) {
         /* Reselect device.  */
         lsi_reselect(s, p);
         return 0;
@@ -669,9 +713,8 @@ void lsi_command_complete(SCSIRequest *req, uint32_t status, size_t resid)
     LSIState *s = LSI53C895A(req->bus->qbus.parent);
     int out;
 
-    out = (s->sstat2 & PHASE_MASK) == PHASE_DO;
+    out = (s->sstat1 & PHASE_MASK) == PHASE_DO;
     DPRINTF("Command complete status=%d\n", (int)status);
-       s->lcrc = 0;
     s->status = status;
     s->command_complete = 2;
     if (s->waiting && s->dbc != 0) {
@@ -703,7 +746,7 @@ void lsi_transfer_data(SCSIRequest *req, uint32_t len)
         }
     }
 
-    out = (s->sstat2 & PHASE_MASK) == PHASE_DO;
+    out = (s->sstat1 & PHASE_MASK) == PHASE_DO;
 
     /* host adapter (re)connected */
     DPRINTF("Data ready tag=0x%x len=%d\n", req->tag, len);
@@ -718,18 +761,6 @@ void lsi_transfer_data(SCSIRequest *req, uint32_t len)
     }
 }
 
-static int idbitstonum(int id)
-{
-       int num = 0;
-       while (id > 1) {
-               num++;
-               id >>= 1;
-       }
-       if (num > 7)
-               num = -1;
-       return num;
-}
-
 static void lsi_do_command(LSIState *s)
 {
     SCSIDevice *dev;
@@ -741,13 +772,11 @@ static void lsi_do_command(LSIState *s)
     if (s->dbc > 16)
         s->dbc = 16;
     pci_dma_read(PCI_DEVICE(s), s->dnad, buf, s->dbc);
-    DPRINTF("Send command len=%d %02x.%02x.%02x.%02x.%02x.%02x\n", s->dbc, buf[0], buf[1], buf[2], buf[3], buf[4], buf[5]);
     s->sfbr = buf[0];
     s->command_complete = 0;
 
-    id = (s->select_tag >> 8) & 0xff;
-       s->lcrc = id; //1 << (id & 0x7);
-    dev = scsi_device_find(&s->bus, 0, idbitstonum(id), s->current_lun);
+    id = (s->select_tag >> 8) & 0xf;
+    dev = scsi_device_find(&s->bus, 0, id, s->current_lun);
     if (!dev) {
         lsi_bad_selection(s, id);
         return;
@@ -1014,11 +1043,11 @@ static void lsi_execute_script(LSIState *s)
 {
     PCIDevice *pci_dev = PCI_DEVICE(s);
     uint32_t insn;
-    uint32_t addr;
+    uint32_t addr, addr_high;
     int opcode;
     int insn_processed = 0;
 
-    s->script_active = 1;
+    s->istat1 |= LSI_ISTAT1_SRUN;
 again:
     insn_processed++;
     insn = read_dword(s, s->dsp);
@@ -1029,18 +1058,22 @@ again:
         goto again;
     }
     addr = read_dword(s, s->dsp + 4);
+    addr_high = 0;
     DPRINTF("SCRIPTS dsp=%08x opcode %08x arg %08x\n", s->dsp, insn, addr);
     s->dsps = addr;
     s->dcmd = insn >> 24;
     s->dsp += 8;
     switch (insn >> 30) {
     case 0: /* Block move.  */
-        if (s->sstat0 & LSI_SSTAT0_STO) {
+        if (s->sist1 & LSI_SIST1_STO) {
             DPRINTF("Delayed select timeout\n");
             lsi_stop_script(s);
             break;
         }
         s->dbc = insn & 0xffffff;
+        s->rbc = s->dbc;
+        /* ??? Set ESA.  */
+        s->ia = s->dsp - 8;
         if (insn & (1 << 29)) {
             /* Indirect addressing.  */
             addr = read_dword(s, addr);
@@ -1054,33 +1087,33 @@ again:
             pci_dma_read(pci_dev, s->dsa + offset, buf, 8);
             /* byte count is stored in bits 0:23 only */
             s->dbc = cpu_to_le32(buf[0]) & 0xffffff;
+            s->rbc = s->dbc;
             addr = cpu_to_le32(buf[1]);
 
-#if 0
-                       /* 40-bit DMA, upper addr bits [39:32] stored in first DWORD of
+            /* 40-bit DMA, upper addr bits [39:32] stored in first DWORD of
              * table, bits [31:24] */
             if (lsi_dma_40bit(s))
                 addr_high = cpu_to_le32(buf[0]) >> 24;
             else if (lsi_dma_ti64bit(s)) {
                 int selector = (cpu_to_le32(buf[0]) >> 24) & 0x1f;
                 switch (selector) {
-                               case 0x00:
-                               case 0x01:
-                               case 0x02:
-                               case 0x03:
-                               case 0x04:
-                               case 0x05:
-                               case 0x06:
-                               case 0x07:
-                               case 0x08:
-                               case 0x09:
-                               case 0x0a:
-                               case 0x0b:
-                               case 0x0c:
-                               case 0x0d:
-                               case 0x0e:
-                               case 0x0f:
-                    /* offset index into scratch registers since
+                               case 0:
+                               case 1:
+                               case 2:
+                               case 3:
+                               case 4:
+                               case 5:
+                               case 6:
+                               case 7:
+                               case 8:
+                               case 9:
+                               case 10:
+                               case 11:
+                               case 12:
+                               case 13:
+                               case 14:
+                               case 15:
+                                       /* offset index into scratch registers since
                      * TI64 mode can use registers C to R */
                     addr_high = s->scratch[2 + selector];
                     break;
@@ -1114,17 +1147,16 @@ again:
             s->dbms = read_dword(s, s->dsp);
             s->dsp += 4;
             s->ia = s->dsp - 12;
-#endif
         }
-        if ((s->sstat2 & PHASE_MASK) != ((insn >> 24) & 7)) {
+        if ((s->sstat1 & PHASE_MASK) != ((insn >> 24) & 7)) {
             DPRINTF("Wrong phase got %d expected %d\n",
-                    s->sstat2 & PHASE_MASK, (insn >> 24) & 7);
-            lsi_script_scsi_interrupt(s, LSI_SSTAT0_MA);
-                       s->sbcl |= LSI_SBCL_REQ;
+                    s->sstat1 & PHASE_MASK, (insn >> 24) & 7);
+            lsi_script_scsi_interrupt(s, LSI_SIST0_MA, 0);
             break;
         }
         s->dnad = addr;
-        switch (s->sstat2 & 0x7) {
+        s->dnad64 = addr_high;
+        switch (s->sstat1 & 0x7) {
         case PHASE_DO:
             s->waiting = 2;
             lsi_do_dma(s, 1);
@@ -1150,11 +1182,13 @@ again:
             lsi_do_msgin(s);
             break;
         default:
-            BADF("Unimplemented phase %d\n", s->sstat2 & PHASE_MASK);
-            exit(1);
+            BADF("Unimplemented phase %d\n", s->sstat1 & PHASE_MASK);
         }
+        s->dfifo = s->dbc & 0xff;
         s->ctest5 = (s->ctest5 & 0xfc) | ((s->dbc >> 8) & 3);
         s->sbc = s->dbc;
+        s->rbc -= s->dbc;
+        s->ua = addr + s->dbc;
         break;
 
     case 1: /* IO or Read/Write instruction.  */
@@ -1167,7 +1201,7 @@ again:
             } else {
                 id = insn;
             }
-            id = (id >> 16) & 0xff;
+            id = (id >> 16) & 0xf;
             if (insn & (1 << 26)) {
                 addr = s->dsp + sextract32(addr, 0, 24);
             }
@@ -1180,20 +1214,20 @@ again:
                     s->dsp = s->dnad;
                     break;
                 }
-                s->sstat1 |= LSI_SSTAT1_WOA;
-//                s->scntl1 &= ~LSI_SCNTL1_IARB;
-                if (!scsi_device_find(&s->bus, 0, idbitstonum(id), 0)) {
+                s->sstat0 |= LSI_SSTAT0_WOA;
+                s->scntl1 &= ~LSI_SCNTL1_IARB;
+                if (!scsi_device_find(&s->bus, 0, id, 0)) {
                     lsi_bad_selection(s, id);
                     break;
                 }
                 DPRINTF("Selected target %d%s\n",
-                        id, insn & (1 << 24) ? " ATN" : "");
+                        id, insn & (1 << 3) ? " ATN" : "");
                 /* ??? Linux drivers compain when this is set.  Maybe
                    it only applies in low-level mode (unimplemented).
                 lsi_script_scsi_interrupt(s, LSI_SIST0_CMP, 0); */
                 s->select_tag = id << 8;
                 s->scntl1 |= LSI_SCNTL1_CON;
-                if (insn & (1 << 24)) {
+                if (insn & (1 << 3)) {
                     s->socl |= LSI_SOCL_ATN;
                 }
                 lsi_set_phase(s, PHASE_MO);
@@ -1219,7 +1253,6 @@ again:
                 }
                 if (insn & (1 << 9)) {
                     BADF("Target mode not implemented\n");
-                    exit(1);
                 }
                 if (insn & (1 << 10))
                     s->carry = 1;
@@ -1242,7 +1275,7 @@ again:
             uint8_t op1;
             uint8_t data8;
             int reg;
-            int xoperator;
+            int oper;
 #ifdef DEBUG_LSI
             static const char *opcode_names[3] =
                 {"Write", "Read", "Read-Modify-Write"};
@@ -1253,10 +1286,10 @@ again:
             reg = ((insn >> 16) & 0x7f) | (insn & 0x80);
             data8 = (insn >> 8) & 0xff;
             opcode = (insn >> 27) & 7;
-            xoperator = (insn >> 24) & 7;
+                       oper = (insn >> 24) & 7;
             DPRINTF("%s reg 0x%x %s data8=0x%02x sfbr=0x%02x%s\n",
                     opcode_names[opcode - 5], reg,
-                    operator_names[xoperator], data8, s->sfbr,
+                                       operator_names[oper], data8, s->sfbr,
                     (insn & (1 << 23)) ? " SFBR" : "");
             op0 = op1 = 0;
             switch (opcode) {
@@ -1265,12 +1298,12 @@ again:
                 op1 = data8;
                 break;
             case 6: /* To SFBR */
-                if (xoperator)
+                               if (oper)
                     op0 = lsi_reg_readb(s, reg);
                 op1 = data8;
                 break;
             case 7: /* Read-modify-write */
-                if (xoperator)
+                               if (oper)
                     op0 = lsi_reg_readb(s, reg);
                 if (insn & (1 << 23)) {
                     op1 = s->sfbr;
@@ -1280,7 +1313,7 @@ again:
                 break;
             }
 
-            switch (xoperator) {
+                       switch (oper) {
             case 0: /* move */
                 op0 = op1;
                 break;
@@ -1337,7 +1370,7 @@ again:
                 DPRINTF("NOP\n");
                 break;
             }
-            if (s->sstat0 & LSI_SSTAT0_STO) {
+            if (s->sist1 & LSI_SIST1_STO) {
                 DPRINTF("Delayed select timeout\n");
                 lsi_stop_script(s);
                 break;
@@ -1349,10 +1382,10 @@ again:
             }
             if (cond == jmp && (insn & (1 << 17))) {
                 DPRINTF("Compare phase %d %c= %d\n",
-                        (s->sstat2 & PHASE_MASK),
+                        (s->sstat1 & PHASE_MASK),
                         jmp ? '=' : '!',
                         ((insn >> 24) & 7));
-                cond = (s->sstat2 & PHASE_MASK) == ((insn >> 24) & 7);
+                cond = (s->sstat1 & PHASE_MASK) == ((insn >> 24) & 7);
             }
             if (cond == jmp && (insn & (1 << 18))) {
                 uint8_t mask;
@@ -1384,6 +1417,7 @@ again:
                 case 3: /* Interrupt */
                     DPRINTF("Interrupt 0x%08x\n", s->dsps);
                     if ((insn & (1 << 20)) != 0) {
+                        s->istat0 |= LSI_ISTAT0_INTF;
                         lsi_update_irq(s);
                     } else {
                         lsi_script_dma_interrupt(s, LSI_DSTAT_SIR);
@@ -1443,11 +1477,11 @@ again:
            assume this is the case and force an unexpected device disconnect.
            This is apparently sufficient to beat the drivers into submission.
          */
-        if (!(s->sien0 & LSI_SSTAT0_UDC))
+        if (!(s->sien0 & LSI_SIST0_UDC))
             fprintf(stderr, "inf. loop with UDC masked\n");
-        lsi_script_scsi_interrupt(s, LSI_SSTAT0_UDC);
+        lsi_script_scsi_interrupt(s, LSI_SIST0_UDC, 0);
         lsi_disconnect(s);
-    } else if (s->script_active && !s->waiting) {
+    } else if (s->istat1 & LSI_ISTAT1_SRUN && !s->waiting) {
         if (s->dcntl & LSI_DCNTL_SSM) {
             lsi_script_dma_interrupt(s, LSI_DSTAT_SSI);
         } else {
@@ -1457,7 +1491,6 @@ again:
     DPRINTF("SCRIPTS execution stopped\n");
 }
 
-#if 0
 static uint8_t lsi_reg_readb(LSIState *s, int offset)
 {
     uint8_t tmp;
@@ -1628,271 +1661,11 @@ static uint8_t lsi_reg_readb(LSIState *s, int offset)
         return (s->scratch[n] >> shift) & 0xff;
     }
     BADF("readb 0x%x\n", offset);
-    exit(1);
-#undef CASE_GET_REG24
-#undef CASE_GET_REG32
-}
-#endif
-
-static uint8_t lsi_reg_readb2(LSIState *s, int offset)
-{
-    uint8_t tmp;
-#define CASE_GET_REG24(name, addr) \
-    case addr: return s->name & 0xff; \
-    case addr + 1: return (s->name >> 8) & 0xff; \
-    case addr + 2: return (s->name >> 16) & 0xff;
-
-#define CASE_GET_REG32(name, addr) \
-    case addr: return s->name & 0xff; \
-    case addr + 1: return (s->name >> 8) & 0xff; \
-    case addr + 2: return (s->name >> 16) & 0xff; \
-    case addr + 3: return (s->name >> 24) & 0xff;
-
-    switch (offset)
-       {
-    case 0x00: /* SCNTL0 */
-        return s->scntl0;
-    case 0x01: /* SCNTL1 */
-        return s->scntl1;
-    case 0x02: /* SDID */
-        return s->sdid;
-    case 0x03: /* SIEN */
-        return s->sien0;
-       case 0x05: /* SXFER */
-        return s->sxfer;
-    case 0x09: /* SIDL */
-        /* This is needed by the linux drivers.  We currently only update it
-           during the MSG IN phase.  */
-        return s->sidl;
-    case 0xb: /* SBCL */
-               /* NetBSD 1.x checks for REQ */
-           tmp = s->sstat2 & PHASE_MASK;
-               /* if phase mismatch, REQ is also active */
-               tmp |= s->sbcl;
-               if (s->socl & LSI_SOCL_ATN)
-                       tmp |= LSI_SBCL_ATN;
-        return tmp;
-    case 0xc: /* DSTAT */
-        tmp = s->dstat | LSI_DSTAT_DFE;
-               s->dstat = 0;
-//        if ((s->istat0 & LSI_ISTAT0_INTF) == 0)
-//            s->dstat = 0;
-        lsi_update_irq(s);
-        return tmp;
-   case 0x0d: /* SSTAT0 */
-               tmp = s->sstat0;
-               s->sstat0 = 0;
-        lsi_update_irq(s);
-       return tmp;
-    case 0x0e: /* SSTAT1 */
-        return s->sstat1;
-    case 0x0f: /* SSTAT2 */
-        return s->sstat2;
-    CASE_GET_REG32(dsa, 0x10)
-       case 0x14: /* CTEST0 */
-        return s->ctest0;
-       case 0x15: /* CTEST1 */
-        return 0xf0; // FMT and FFL are always empty
-       case 0x16: /* CTEST2 */
-        tmp = s->ctest2 | LSI_CTEST2_DACK;
-        if (s->istat & LSI_ISTAT_SIGP) {
-            s->istat &= ~LSI_ISTAT_SIGP;
-            tmp |= LSI_CTEST2_SIGP;
-        }
-        return tmp;
-       case 0x17: /* CTEST3 */
-               return s->ctest3;
-       case 0x18: /* CTEST4 */
-               return s->ctest4;
-       case 0x19: /* CTEST5 */
-               return s->ctest5;
-       case 0x1a: /* CTEST6 */
-               return s->ctest6;
-       case 0x1b: /* CTEST7 */
-               return s->ctest7;
-    CASE_GET_REG32(temp, 0x1c)
-    case 0x20: /* DFIFO */
-        return 0;
-       case 0x21: /* ISTAT */
-               return s->istat;
-       case 0x22: /* CTEST8 */
-               return (s->ctest8 | (2 << 4)) & ~0x08; // clear CLF
-       case 0x23: /* LCRC */
-               return s->lcrc;
-    CASE_GET_REG24(dbc, 0x24)
-    case 0x27: /* DCMD */
-        return s->dcmd;
-    CASE_GET_REG32(dnad, 0x28)
-    CASE_GET_REG32(dsp, 0x2c)
-    CASE_GET_REG32(dsps, 0x30)
-    CASE_GET_REG32(scratch, 0x34)
-       case 0x38: /* DMODE */
-        return s->dmode;
-       case 0x3a: /* DWT */
-               return s->dwt;
-    case 0x3b: /* DCNTL */
-        return s->dcntl;
-       }
+       return 0;
 #undef CASE_GET_REG24
 #undef CASE_GET_REG32
-       write_log ("read unknown register %02X\n", offset);
-       return 0;
-}
-static uint8_t lsi_reg_readb(LSIState *s, int offset)
-{
-       uint8_t v = lsi_reg_readb2(s, offset);
-#ifdef DEBUG_LSI_REG
-    DPRINTF("Read reg %x: %02X\n", offset, v);
-#endif
-       return v;
-}
-
-static void lsi_reg_writeb(LSIState *s, int offset, uint8_t val)
-{
-#define CASE_SET_REG24(name, addr) \
-    case addr    : s->name &= 0xffffff00; s->name |= val;       break; \
-    case addr + 1: s->name &= 0xffff00ff; s->name |= val << 8;  break; \
-    case addr + 2: s->name &= 0xff00ffff; s->name |= val << 16; break;
-
-#define CASE_SET_REG32(name, addr) \
-    case addr    : s->name &= 0xffffff00; s->name |= val;       break; \
-    case addr + 1: s->name &= 0xffff00ff; s->name |= val << 8;  break; \
-    case addr + 2: s->name &= 0xff00ffff; s->name |= val << 16; break; \
-    case addr + 3: s->name &= 0x00ffffff; s->name |= val << 24; break;
-
-#ifdef DEBUG_LSI_REG
-    DPRINTF("Write reg %x = %02x\n", offset, val);
-#endif
-    switch (offset) {
-    case 0x00: /* SCNTL0 */
-        s->scntl0 = val;
-        if (val & LSI_SCNTL0_START) {
-            BADF("Start sequence not implemented\n");
-        }
-        break;
-    case 0x01: /* SCNTL1 */
-        s->scntl1 = val;
-        if (val & LSI_SCNTL1_ADB) {
-            BADF("Immediate Arbritration not implemented\n");
-        }
-        if (val & LSI_SCNTL1_RST) {
-            if (!(s->sstat0 & LSI_SSTAT0_RST)) {
-//                qbus_reset_all(&s->bus.qbus);
-                s->sstat0 |= LSI_SSTAT0_RST;
-                lsi_script_scsi_interrupt(s, LSI_SSTAT0_RST);
-            }
-        } else {
-            s->sstat0 &= ~LSI_SSTAT0_RST;
-        }
-        break;
-    case 0x03: /* SIEN */
-        s->sien0 = val;
-        lsi_update_irq(s);
-        break;
-    case 0x04: /* SCID */
-        s->scid = val;
-        break;
-    case 0x05: /* SXFER */
-        s->sxfer = val;
-        break;
-       case 0x0b: /* SBCL */
-               lsi_set_phase (s, val & PHASE_MASK);
-               break;
-    case 0x0c: case 0x0d: case 0x0e: case 0x0f:
-        /* Linux writes to these readonly registers on startup.  */
-        return;
-    CASE_SET_REG32(dsa, 0x10)
-       case 0x14: /* CTEST0 */
-        s->ctest0 = (val & 0xfe) | (s->ctest0 & 1);
-        break;
-       case 0x18: /* CTEST4 */
-        s->ctest4 = val;
-        break;
-       case 0x19: /* CTEST5 */
-        s->ctest5 = val;
-        break;
-       case 0x1a: /* CTEST6 */
-        s->ctest6 = val;
-        break;
-       case 0x1b: /* CTEST7 */
-               s->ctest7 = val;
-               break;
-    CASE_SET_REG32(temp, 0x1c)
-       
-       case 0x21: /* ISTAT */
-        s->istat = (s->istat & 0x0f) | (val & 0xf0);
-        if (val & LSI_ISTAT_ABRT) {
-            lsi_script_dma_interrupt(s, LSI_DSTAT_ABRT);
-        }
-        if (s->waiting == 1 && (val & LSI_ISTAT_SIGP)) {
-            DPRINTF("Woken by SIGP\n");
-            s->waiting = 0;
-            s->dsp = s->dnad;
-            lsi_execute_script(s);
-        }
-        if (val & LSI_ISTAT_RST) {
-            ;//qdev_reset_all(DEVICE(s));
-        }
-        break;
-       case 0x22: /* CTEST8 */
-               s->ctest8 = val;
-       break;
-       case 0x23: /* LCRC */
-               s->lcrc = 0;
-       break;
-    CASE_SET_REG24(dbc, 0x24)
-    CASE_SET_REG32(dnad, 0x28)
-    case 0x2c: /* DSP[0:7] */
-        s->dsp &= 0xffffff00;
-        s->dsp |= val;
-        break;
-    case 0x2d: /* DSP[8:15] */
-        s->dsp &= 0xffff00ff;
-        s->dsp |= val << 8;
-        break;
-    case 0x2e: /* DSP[16:23] */
-        s->dsp &= 0xff00ffff;
-        s->dsp |= val << 16;
-        break;
-    case 0x2f: /* DSP[24:31] */
-        s->dsp &= 0x00ffffff;
-        s->dsp |= val << 24;
-        if ((s->dmode & LSI_DMODE_MAN) == 0) {
-                       s->waiting = 0;
-            lsi_execute_script(s);
-               }
-        break;
-    CASE_SET_REG32(scratch, 0x34)
-       case 0x38: /* DMODE */
-#if 0
-               if (val & (LSI_DMODE_SIOM | LSI_DMODE_DIOM)) {
-            BADF("IO mappings not implemented\n");
-        }
-#endif
-               s->dmode = val;
-        break;
-    case 0x39: /* DIEN */
-        s->dien = val;
-        lsi_update_irq(s);
-        break;
-       case 0x3a: /* DWT */
-               s->dwt = val;
-               break;
-    case 0x3b: /* DCNTL */
-        s->dcntl = val & ~(LSI_DCNTL_PFF | LSI_DCNTL_STD);
-               if ((val & LSI_DCNTL_STD) && (s->dmode & LSI_DMODE_MAN) == 0)
-            lsi_execute_script(s);
-        break;
-       default:
-               write_log ("write unknown register %02X\n", offset);
-       break;
-       }
-#undef CASE_SET_REG24
-#undef CASE_SET_REG32
 }
 
-#if 0
 static void lsi_reg_writeb(LSIState *s, int offset, uint8_t val)
 {
 #define CASE_SET_REG24(name, addr) \
@@ -1923,7 +1696,7 @@ static void lsi_reg_writeb(LSIState *s, int offset, uint8_t val)
         }
         if (val & LSI_SCNTL1_RST) {
             if (!(s->sstat0 & LSI_SSTAT0_RST)) {
-//                qbus_reset_all(&s->bus.qbus);
+                ;//qbus_reset_all(&s->bus.qbus);
                 s->sstat0 |= LSI_SSTAT0_RST;
                 lsi_script_scsi_interrupt(s, LSI_SIST0_RST, 0);
             }
@@ -1979,9 +1752,9 @@ static void lsi_reg_writeb(LSIState *s, int offset, uint8_t val)
             s->dsp = s->dnad;
             lsi_execute_script(s);
         }
-//        if (val & LSI_ISTAT0_SRST) {
-//            qdev_reset_all(DEVICE(s));
-//        }
+        if (val & LSI_ISTAT0_SRST) {
+            ;//qdev_reset_all(DEVICE(s));
+        }
         break;
     case 0x16: /* MBOX0 */
         s->mbox0 = val;
@@ -1989,10 +1762,13 @@ static void lsi_reg_writeb(LSIState *s, int offset, uint8_t val)
     case 0x17: /* MBOX1 */
         s->mbox1 = val;
         break;
-    case 0x18: /* CTEST0 */
-        /* nothing to do */
-        break;
-    case 0x1a: /* CTEST2 */
+       case 0x18: /* CTEST0 */
+               /* nothing to do */
+               break;
+       case 0x19: /* CTEST1 */
+               /* nothing to do */
+               break;
+       case 0x1a: /* CTEST2 */
        s->ctest2 = val & LSI_CTEST2_PCICIE;
        break;
     case 0x1b: /* CTEST3 */
@@ -2008,7 +1784,6 @@ static void lsi_reg_writeb(LSIState *s, int offset, uint8_t val)
     case 0x22: /* CTEST5 */
         if (val & (LSI_CTEST5_ADCK | LSI_CTEST5_BBCK)) {
             BADF("CTEST5 DMA increment not implemented\n");
-                       val &= ~(LSI_CTEST5_ADCK | LSI_CTEST5_BBCK);
         }
         s->ctest5 = val;
         break;
@@ -2129,7 +1904,6 @@ static void lsi_reg_writeb(LSIState *s, int offset, uint8_t val)
 #undef CASE_SET_REG24
 #undef CASE_SET_REG32
 }
-#endif
 
 void lsi_mmio_write(void *opaque, hwaddr addr,
                            uint64_t val, unsigned size)
@@ -2149,19 +1923,19 @@ uint64_t lsi_mmio_read(void *opaque, hwaddr addr,
 
 #if 0
 static const MemoryRegionOps lsi_mmio_ops = {
-    lsi_mmio_read,
-    lsi_mmio_write,
-    DEVICE_NATIVE_ENDIAN,
-    {
-        1,
-        1,
+    .read = lsi_mmio_read,
+    .write = lsi_mmio_write,
+    .endianness = DEVICE_NATIVE_ENDIAN,
+    .impl = {
+        .min_access_size = 1,
+        .max_access_size = 1,
     },
 };
 
 static void lsi_ram_write(void *opaque, hwaddr addr,
                           uint64_t val, unsigned size)
 {
-    LSIState *s = (LSIState*)opaque;
+    LSIState *s = opaque;
     uint32_t newval;
     uint32_t mask;
     int shift;
@@ -2177,7 +1951,7 @@ static void lsi_ram_write(void *opaque, hwaddr addr,
 static uint64_t lsi_ram_read(void *opaque, hwaddr addr,
                              unsigned size)
 {
-    LSIState *s = (LSIState*)opaque;
+    LSIState *s = opaque;
     uint32_t val;
     uint32_t mask;
 
@@ -2188,32 +1962,32 @@ static uint64_t lsi_ram_read(void *opaque, hwaddr addr,
 }
 
 static const MemoryRegionOps lsi_ram_ops = {
-    lsi_ram_read,
-    lsi_ram_write,
-    DEVICE_NATIVE_ENDIAN,
+    .read = lsi_ram_read,
+    .write = lsi_ram_write,
+    .endianness = DEVICE_NATIVE_ENDIAN,
 };
 
 static uint64_t lsi_io_read(void *opaque, hwaddr addr,
                             unsigned size)
 {
-    LSIState *s = (LSIState*)opaque;
+    LSIState *s = opaque;
     return lsi_reg_readb(s, addr & 0xff);
 }
 
 static void lsi_io_write(void *opaque, hwaddr addr,
                          uint64_t val, unsigned size)
 {
-    LSIState *s = (LSIState*)opaque;
+    LSIState *s = opaque;
     lsi_reg_writeb(s, addr & 0xff, val);
 }
 
 static const MemoryRegionOps lsi_io_ops = {
-    lsi_io_read,
-    lsi_io_write,
-    DEVICE_NATIVE_ENDIAN,
-    {
-        1,
-        1,
+    .read = lsi_io_read,
+    .write = lsi_io_write,
+    .endianness = DEVICE_NATIVE_ENDIAN,
+    .impl = {
+        .min_access_size = 1,
+        .max_access_size = 1,
     },
 };
 #endif
@@ -2425,4 +2199,4 @@ static void lsi53c895a_register_types(void)
 }
 
 type_init(lsi53c895a_register_types)
-#endif
\ No newline at end of file
+#endif
index d689072a96b112fa65a92e0d22707ca4108ffc8e..af143a0af533f8bef4390f0cf9f2b4a41b68a1ef 100644 (file)
@@ -292,11 +292,15 @@ struct DeviceState
 };
 
 #define QEMUFile void*
-#define PCIDevice void*
+#define PCIDevice void
 typedef unsigned long dma_addr_t;
-#define PCI_DEVICE(s) (void**)s
+#define PCI_DEVICE(s) ((void*)(s->bus.privdata))
 #define DMA_ADDR_FMT "%08x"
 
+void pci710_set_irq(PCIDevice *pci_dev, int level);
+void lsi710_scsi_init(DeviceState *dev);
+void lsi710_scsi_reset(DeviceState *dev, void*);
+
 void pci_set_irq(PCIDevice *pci_dev, int level);
 void lsi_scsi_init(DeviceState *dev);
 void lsi_scsi_reset(DeviceState *dev, void*);
@@ -328,18 +332,30 @@ typedef enum {
     DMA_DIRECTION_FROM_DEVICE = 1,
 } DMADirection;
 
-int pci_dma_rw(PCIDevice *dev, dma_addr_t addr, void *buf, dma_addr_t len, DMADirection dir);
+int pci710_dma_rw(PCIDevice *dev, dma_addr_t addr, void *buf, dma_addr_t len, DMADirection dir);
 
-static inline int pci_dma_read(PCIDevice *dev, dma_addr_t addr,
+static inline int pci710_dma_read(PCIDevice *dev, dma_addr_t addr,
                                void *buf, dma_addr_t len)
 {
-    return pci_dma_rw(dev, addr, buf, len, DMA_DIRECTION_TO_DEVICE);
+    return pci710_dma_rw(dev, addr, buf, len, DMA_DIRECTION_TO_DEVICE);
+}
+static inline int pci710_dma_write(PCIDevice *dev, dma_addr_t addr,
+                                const void *buf, dma_addr_t len)
+{
+    return pci710_dma_rw(dev, addr, (void *) buf, len, DMA_DIRECTION_FROM_DEVICE);
 }
 
+int pci_dma_rw(PCIDevice *dev, dma_addr_t addr, void *buf, dma_addr_t len, DMADirection dir);
+
+static inline int pci_dma_read(PCIDevice *dev, dma_addr_t addr,
+       void *buf, dma_addr_t len)
+{
+       return pci_dma_rw(dev, addr, buf, len, DMA_DIRECTION_TO_DEVICE);
+}
 static inline int pci_dma_write(PCIDevice *dev, dma_addr_t addr,
-                                const void *buf, dma_addr_t len)
+       const void *buf, dma_addr_t len)
 {
-    return pci_dma_rw(dev, addr, (void *) buf, len, DMA_DIRECTION_FROM_DEVICE);
+       return pci_dma_rw(dev, addr, (void *)buf, len, DMA_DIRECTION_FROM_DEVICE);
 }
 
 struct BusState {
@@ -353,5 +369,8 @@ struct BusState {
 };
 
 
+extern void lsi710_mmio_write(void *opaque, hwaddr addr, uint64_t val, unsigned size);
+extern uint64_t lsi710_mmio_read(void *opaque, hwaddr addr, unsigned size);
+
 extern void lsi_mmio_write(void *opaque, hwaddr addr, uint64_t val, unsigned size);
 extern uint64_t lsi_mmio_read(void *opaque, hwaddr addr, unsigned size);
index 04c8cda228540352b2b4ff35bf3bec8def88a62d..f4d73215cf6681aa2786afae22af0861e0e5cb0a 100644 (file)
@@ -136,7 +136,7 @@ struct SCSIBus {
 //void scsi_bus_new(SCSIBus *bus, size_t bus_size, DeviceState *host,
 //                  const SCSIBusInfo *info, const char *bus_name);
 
-static inline SCSIBus *scsi_bus_from_device(SCSIDevice *d)
+static inline SCSIBus *scsi710_bus_from_device(SCSIDevice *d)
 {
     return NULL; //return DO_UPCAST(SCSIBus, qbus, d->qdev.parent_bus);
 }
@@ -205,12 +205,12 @@ uint32_t scsi_data_cdb_length(uint8_t *buf);
 uint32_t scsi_cdb_length(uint8_t *buf);
 int scsi_sense_valid(SCSISense sense);
 int scsi_build_sense(uint8_t *in_buf, int in_len,
-                     uint8_t *buf, int len, bool fixed);
+       uint8_t *buf, int len, bool fixed);
 
 SCSIRequest *scsi_req_alloc(const SCSIReqOps *reqops, SCSIDevice *d,
-                            uint32_t tag, uint32_t lun, void *hba_private);
+       uint32_t tag, uint32_t lun, void *hba_private);
 SCSIRequest *scsi_req_new(SCSIDevice *d, uint32_t tag, uint32_t lun,
-                          uint8_t *buf, int len, void *hba_private);
+       uint8_t *buf, int len, void *hba_private);
 int32_t scsi_req_enqueue(SCSIRequest *req);
 void scsi_req_free(SCSIRequest *req);
 SCSIRequest *scsi_req_ref(SCSIRequest *req);
@@ -233,11 +233,50 @@ int scsi_device_get_sense(SCSIDevice *dev, uint8_t *buf, int len, bool fixed);
 SCSIDevice *scsi_device_find(SCSIBus *bus, int channel, int target, int lun);
 
 /* scsi-generic.c. */
-extern const SCSIReqOps scsi_generic_req_ops;
+extern const SCSIReqOps scsi710_generic_req_ops;
 
 void lsi_request_cancelled(SCSIRequest *req);
 void lsi_command_complete(SCSIRequest *req, uint32_t status, size_t resid);
 void lsi_transfer_data(SCSIRequest *req, uint32_t len);
 
 
+uint32_t scsi710_data_cdb_length(uint8_t *buf);
+uint32_t scsi710_cdb_length(uint8_t *buf);
+int scsi710_sense_valid(SCSISense sense);
+int scsi710_build_sense(uint8_t *in_buf, int in_len,
+                     uint8_t *buf, int len, bool fixed);
+
+SCSIRequest *scsi710_req_alloc(const SCSIReqOps *reqops, SCSIDevice *d,
+                            uint32_t tag, uint32_t lun, void *hba_private);
+SCSIRequest *scsi710_req_new(SCSIDevice *d, uint32_t tag, uint32_t lun,
+                          uint8_t *buf, int len, void *hba_private);
+int32_t scsi710_req_enqueue(SCSIRequest *req);
+void scsi710_req_free(SCSIRequest *req);
+SCSIRequest *scsi710_req_ref(SCSIRequest *req);
+void scsi710_req_unref(SCSIRequest *req);
+
+void scsi710_req_build_sense(SCSIRequest *req, SCSISense sense);
+void scsi710_req_print(SCSIRequest *req);
+void scsi710_req_continue(SCSIRequest *req);
+void scsi710_req_data(SCSIRequest *req, int len);
+void scsi710_req_complete(SCSIRequest *req, int status);
+uint8_t *scsi710_req_get_buf(SCSIRequest *req);
+int scsi710_req_get_sense(SCSIRequest *req, uint8_t *buf, int len);
+void scs710i_req_abort(SCSIRequest *req, int status);
+void scsi710_req_cancel(SCSIRequest *req);
+void scsi710_req_retry(SCSIRequest *req);
+void scsi710_device_purge_requests(SCSIDevice *sdev, SCSISense sense);
+void scsi710_device_set_ua(SCSIDevice *sdev, SCSISense sense);
+void scsi710_device_report_change(SCSIDevice *dev, SCSISense sense);
+int scsi710_device_get_sense(SCSIDevice *dev, uint8_t *buf, int len, bool fixed);
+SCSIDevice *scsi710_device_find(SCSIBus *bus, int channel, int target, int lun);
+
+/* scsi-generic.c. */
+extern const SCSIReqOps scsi710_generic_req_ops;
+
+void lsi710_request_cancelled(SCSIRequest *req);
+void lsi710_command_complete(SCSIRequest *req, uint32_t status, size_t resid);
+void lsi710_transfer_data(SCSIRequest *req, uint32_t len);
+
+
 #endif
index 67979552b6e9858d660b331040b86ec1333b685c..4a695c0cada1e5cec3168c9831b2aa32dc650d8f 100644 (file)
@@ -353,8 +353,8 @@ void statusline_vsync(void)
                statusline_delay = STATUSLINE_MS * vblank_hz / (1000 * 1);
        if (statusline_delay > STATUSLINE_MS * vblank_hz / (1000 * 1))
                statusline_delay = STATUSLINE_MS * vblank_hz / (1000 * 1);
-       if (statusline_delay > STATUSLINE_MS * vblank_hz / (1000 * 2) && statusline_text[1])
-               statusline_delay = STATUSLINE_MS * vblank_hz / (1000 * 2);
+       if (statusline_delay > STATUSLINE_MS * vblank_hz / (1000 * 3) && statusline_text[1])
+               statusline_delay = STATUSLINE_MS * vblank_hz / (1000 * 3);
        statusline_delay--;
        if (statusline_delay)
                return;