r3778 - in trunk/src/host/qemu-neo1973: . fpu hw linux-user pc-bios target-mips target-sparc
andrew at sita.openmoko.org
andrew at sita.openmoko.org
Mon Jan 7 08:18:02 CET 2008
Author: andrew
Date: 2008-01-07 08:17:44 +0100 (Mon, 07 Jan 2008)
New Revision: 3778
Added:
trunk/src/host/qemu-neo1973/hw/sbi.c
trunk/src/host/qemu-neo1973/hw/sun4c_intctl.c
Modified:
trunk/src/host/qemu-neo1973/Changelog
trunk/src/host/qemu-neo1973/Makefile
trunk/src/host/qemu-neo1973/Makefile.target
trunk/src/host/qemu-neo1973/VERSION
trunk/src/host/qemu-neo1973/block-raw-posix.c
trunk/src/host/qemu-neo1973/configure
trunk/src/host/qemu-neo1973/cpu-all.h
trunk/src/host/qemu-neo1973/disas.c
trunk/src/host/qemu-neo1973/dyngen-exec.h
trunk/src/host/qemu-neo1973/exec.c
trunk/src/host/qemu-neo1973/fpu/softfloat-specialize.h
trunk/src/host/qemu-neo1973/hw/boards.h
trunk/src/host/qemu-neo1973/hw/eccmemctl.c
trunk/src/host/qemu-neo1973/hw/esp.c
trunk/src/host/qemu-neo1973/hw/fdc.c
trunk/src/host/qemu-neo1973/hw/iommu.c
trunk/src/host/qemu-neo1973/hw/m48t59.c
trunk/src/host/qemu-neo1973/hw/mainstone.c
trunk/src/host/qemu-neo1973/hw/mips_malta.c
trunk/src/host/qemu-neo1973/hw/pcnet.c
trunk/src/host/qemu-neo1973/hw/pflash_cfi01.c
trunk/src/host/qemu-neo1973/hw/slavio_intctl.c
trunk/src/host/qemu-neo1973/hw/slavio_misc.c
trunk/src/host/qemu-neo1973/hw/slavio_serial.c
trunk/src/host/qemu-neo1973/hw/slavio_timer.c
trunk/src/host/qemu-neo1973/hw/sparc32_dma.c
trunk/src/host/qemu-neo1973/hw/sun4m.c
trunk/src/host/qemu-neo1973/hw/sun4m.h
trunk/src/host/qemu-neo1973/hw/tcx.c
trunk/src/host/qemu-neo1973/linux-user/main.c
trunk/src/host/qemu-neo1973/pc-bios/README
trunk/src/host/qemu-neo1973/pc-bios/openbios-sparc32
trunk/src/host/qemu-neo1973/qemu-doc.texi
trunk/src/host/qemu-neo1973/qemu-img.c
trunk/src/host/qemu-neo1973/target-mips/cpu.h
trunk/src/host/qemu-neo1973/target-mips/exec.h
trunk/src/host/qemu-neo1973/target-mips/helper.c
trunk/src/host/qemu-neo1973/target-mips/mips-defs.h
trunk/src/host/qemu-neo1973/target-mips/op.c
trunk/src/host/qemu-neo1973/target-mips/op_helper.c
trunk/src/host/qemu-neo1973/target-mips/translate.c
trunk/src/host/qemu-neo1973/target-mips/translate_init.c
trunk/src/host/qemu-neo1973/target-sparc/helper.c
trunk/src/host/qemu-neo1973/target-sparc/op_helper.c
trunk/src/host/qemu-neo1973/vl.c
Log:
Update tree to qemu-0.9.1.
Modified: trunk/src/host/qemu-neo1973/Changelog
===================================================================
--- trunk/src/host/qemu-neo1973/Changelog 2008-01-06 01:02:26 UTC (rev 3777)
+++ trunk/src/host/qemu-neo1973/Changelog 2008-01-07 07:17:44 UTC (rev 3778)
@@ -1,3 +1,5 @@
+version 0.9.1:
+
- TFTP booting from host directory (Anthony Liguori, Erwan Velu)
- Tap device emulation for Solaris (Sittichai Palanisong)
- Monitor multiplexing to several I/O channels (Jason Wessel)
@@ -18,6 +20,9 @@
- Strace for Linux userland emulation (Stuart Anderson, Thayne Harbaugh)
- OMAP310 MPU emulation plus Palm T|E machine (Andrzej Zaborowski)
- ARM v6, v7, NEON SIMD and SMP emulation (Paul Brook/CodeSourcery)
+ - Gumstix boards: connex and verdex emulation (Thorsten Zitterell)
+ - Intel mainstone II board emulation (Armin Kuster)
+ - VMware SVGA II graphics card support (Andrzej Zaborowski)
version 0.9.0:
Modified: trunk/src/host/qemu-neo1973/Makefile
===================================================================
--- trunk/src/host/qemu-neo1973/Makefile 2008-01-06 01:02:26 UTC (rev 3777)
+++ trunk/src/host/qemu-neo1973/Makefile 2008-01-07 07:17:44 UTC (rev 3778)
@@ -273,22 +273,24 @@
$(bindir)/qemu-system-m68k \
$(bindir)/qemu-system-sh4 \
$(bindir)/qemu-system-sh4eb \
+ $(bindir)/qemu-system-cris \
$(bindir)/qemu-i386 \
+ $(bindir)/qemu-x86_64 \
$(bindir)/qemu-arm \
$(bindir)/qemu-armeb \
$(bindir)/qemu-sparc \
+ $(bindir)/qemu-sparc32plus \
+ $(bindir)/qemu-sparc64 \
$(bindir)/qemu-ppc \
$(bindir)/qemu-ppc64 \
+ $(bindir)/qemu-ppc64abi32 \
$(bindir)/qemu-mips \
$(bindir)/qemu-mipsel \
- $(bindir)/qemu-mipsn32 \
- $(bindir)/qemu-mipsn32el \
- $(bindir)/qemu-mips64 \
- $(bindir)/qemu-mips64el \
$(bindir)/qemu-alpha \
$(bindir)/qemu-m68k \
$(bindir)/qemu-sh4 \
$(bindir)/qemu-sh4eb \
+ $(bindir)/qemu-cris \
$(bindir)/qemu-img \
$(datadir)/bios.bin \
$(datadir)/vgabios.bin \
Modified: trunk/src/host/qemu-neo1973/Makefile.target
===================================================================
--- trunk/src/host/qemu-neo1973/Makefile.target 2008-01-06 01:02:26 UTC (rev 3777)
+++ trunk/src/host/qemu-neo1973/Makefile.target 2008-01-07 07:17:44 UTC (rev 3778)
@@ -43,7 +43,9 @@
HELPER_CFLAGS=$(CFLAGS)
DYNGEN=../dyngen$(EXESUF)
# user emulator name
+ifndef TARGET_ARCH2
TARGET_ARCH2=$(TARGET_ARCH)
+endif
ifeq ($(TARGET_ARCH),arm)
ifeq ($(TARGET_WORDS_BIGENDIAN),yes)
TARGET_ARCH2=armeb
@@ -69,11 +71,6 @@
TARGET_ARCH2=mips64el
endif
endif
-ifeq ($(TARGET_ARCH),sparc64)
- ifeq ($(TARGET_ABI_DIR),sparc)
- TARGET_ARCH2=sparc32plus
- endif
-endif
QEMU_USER=qemu-$(TARGET_ARCH2)
# system emulator name
ifdef CONFIG_SOFTMMU
@@ -478,6 +475,7 @@
VL_OBJS+= ide.o gt64xxx.o pckbd.o ps2.o fdc.o mc146818rtc.o usb-uhci.o acpi.o ds1225y.o
VL_OBJS+= piix_pci.o parallel.o cirrus_vga.o $(SOUND_HW)
VL_OBJS+= mipsnet.o
+VL_OBJS+= pflash_cfi01.o
CPPFLAGS += -DHAS_AUDIO
endif
ifeq ($(TARGET_BASE_ARCH), cris)
@@ -494,7 +492,7 @@
else
VL_OBJS+= sun4m.o tcx.o pcnet.o iommu.o m48t59.o slavio_intctl.o
VL_OBJS+= slavio_timer.o slavio_serial.o slavio_misc.o fdc.o esp.o sparc32_dma.o
-VL_OBJS+= cs4231.o ptimer.o eccmemctl.o
+VL_OBJS+= cs4231.o ptimer.o eccmemctl.o sbi.o sun4c_intctl.o
endif
endif
ifeq ($(TARGET_BASE_ARCH), arm)
Modified: trunk/src/host/qemu-neo1973/VERSION
===================================================================
--- trunk/src/host/qemu-neo1973/VERSION 2008-01-06 01:02:26 UTC (rev 3777)
+++ trunk/src/host/qemu-neo1973/VERSION 2008-01-07 07:17:44 UTC (rev 3778)
@@ -1 +1 @@
-0.9.0-openmoko-svn
+0.9.1-openmoko-svn
Modified: trunk/src/host/qemu-neo1973/block-raw-posix.c
===================================================================
--- trunk/src/host/qemu-neo1973/block-raw-posix.c 2008-01-06 01:02:26 UTC (rev 3777)
+++ trunk/src/host/qemu-neo1973/block-raw-posix.c 2008-01-07 07:17:44 UTC (rev 3778)
@@ -276,8 +276,8 @@
seems to fix the problem. */
struct aioinit ai;
memset(&ai, 0, sizeof(ai));
- ai.aio_threads = 16;
- ai.aio_num = 16;
+ ai.aio_threads = 1;
+ ai.aio_num = 1;
ai.aio_idle_time = 365 * 100000;
aio_init(&ai);
}
Modified: trunk/src/host/qemu-neo1973/configure
===================================================================
--- trunk/src/host/qemu-neo1973/configure 2008-01-06 01:02:26 UTC (rev 3777)
+++ trunk/src/host/qemu-neo1973/configure 2008-01-07 07:17:44 UTC (rev 3778)
@@ -1133,6 +1133,7 @@
elif test "$target_cpu" = "sparc32plus" ; then
echo "TARGET_ARCH=sparc64" >> $config_mak
echo "TARGET_ABI_DIR=sparc" >> $config_mak
+ echo "TARGET_ARCH2=sparc32plus" >> $config_mak
echo "#define TARGET_ARCH \"sparc64\"" >> $config_h
echo "#define TARGET_SPARC 1" >> $config_h
echo "#define TARGET_SPARC64 1" >> $config_h
@@ -1156,6 +1157,7 @@
elif test "$target_cpu" = "ppc64abi32" ; then
echo "TARGET_ARCH=ppc64" >> $config_mak
echo "TARGET_ABI_DIR=ppc" >> $config_mak
+ echo "TARGET_ARCH2=ppc64abi32" >> $config_mak
echo "#define TARGET_ARCH \"ppc64\"" >> $config_h
echo "#define TARGET_PPC 1" >> $config_h
echo "#define TARGET_PPC64 1" >> $config_h
Modified: trunk/src/host/qemu-neo1973/cpu-all.h
===================================================================
--- trunk/src/host/qemu-neo1973/cpu-all.h 2008-01-06 01:02:26 UTC (rev 3777)
+++ trunk/src/host/qemu-neo1973/cpu-all.h 2008-01-07 07:17:44 UTC (rev 3778)
@@ -821,6 +821,7 @@
the physical address */
#define IO_MEM_ROMD (1)
#define IO_MEM_SUBPAGE (2)
+#define IO_MEM_SUBWIDTH (4)
typedef void CPUWriteMemoryFunc(void *opaque, target_phys_addr_t addr, uint32_t value);
typedef uint32_t CPUReadMemoryFunc(void *opaque, target_phys_addr_t addr);
Modified: trunk/src/host/qemu-neo1973/disas.c
===================================================================
--- trunk/src/host/qemu-neo1973/disas.c 2008-01-06 01:02:26 UTC (rev 3777)
+++ trunk/src/host/qemu-neo1973/disas.c 2008-01-07 07:17:44 UTC (rev 3778)
@@ -392,6 +392,8 @@
print_insn = print_insn_i386;
#elif defined(TARGET_ARM)
print_insn = print_insn_arm;
+#elif defined(TARGET_ALPHA)
+ print_insn = print_insn_alpha;
#elif defined(TARGET_SPARC)
print_insn = print_insn_sparc;
#ifdef TARGET_SPARC64
Modified: trunk/src/host/qemu-neo1973/dyngen-exec.h
===================================================================
--- trunk/src/host/qemu-neo1973/dyngen-exec.h 2008-01-06 01:02:26 UTC (rev 3777)
+++ trunk/src/host/qemu-neo1973/dyngen-exec.h 2008-01-07 07:17:44 UTC (rev 3778)
@@ -38,7 +38,7 @@
// Linux/Sparc64 defines uint64_t
#if !(defined (__sparc_v9__) && defined(__linux__))
/* XXX may be done for all 64 bits targets ? */
-#if defined (__x86_64__) || defined(__ia64) || defined(__s390x__)
+#if defined (__x86_64__) || defined(__ia64) || defined(__s390x__) || defined(__alpha__)
typedef unsigned long uint64_t;
#else
typedef unsigned long long uint64_t;
@@ -55,7 +55,7 @@
typedef signed int int32_t;
// Linux/Sparc64 defines int64_t
#if !(defined (__sparc_v9__) && defined(__linux__))
-#if defined (__x86_64__) || defined(__ia64) || defined(__s390x__)
+#if defined (__x86_64__) || defined(__ia64) || defined(__s390x__) || defined(__alpha__)
typedef signed long int64_t;
#else
typedef signed long long int64_t;
Modified: trunk/src/host/qemu-neo1973/exec.c
===================================================================
--- trunk/src/host/qemu-neo1973/exec.c 2008-01-06 01:02:26 UTC (rev 3777)
+++ trunk/src/host/qemu-neo1973/exec.c 2008-01-07 07:17:44 UTC (rev 3778)
@@ -163,9 +163,9 @@
#define SUBPAGE_IDX(addr) ((addr) & ~TARGET_PAGE_MASK)
typedef struct subpage_t {
target_phys_addr_t base;
- CPUReadMemoryFunc **mem_read[TARGET_PAGE_SIZE];
- CPUWriteMemoryFunc **mem_write[TARGET_PAGE_SIZE];
- void *opaque[TARGET_PAGE_SIZE];
+ CPUReadMemoryFunc **mem_read[TARGET_PAGE_SIZE][4];
+ CPUWriteMemoryFunc **mem_write[TARGET_PAGE_SIZE][4];
+ void *opaque[TARGET_PAGE_SIZE][2][4];
} subpage_t;
static void page_init(void)
@@ -2025,7 +2025,7 @@
CHECK_SUBPAGE(addr, start_addr, start_addr2, end_addr, end_addr2,
need_subpage);
- if (need_subpage) {
+ if (need_subpage || phys_offset & IO_MEM_SUBWIDTH) {
if (!(orig_memory & IO_MEM_SUBPAGE)) {
subpage = subpage_init((addr & TARGET_PAGE_MASK),
&p->phys_offset, orig_memory);
@@ -2053,7 +2053,7 @@
CHECK_SUBPAGE(addr, start_addr, start_addr2, end_addr,
end_addr2, need_subpage);
- if (need_subpage) {
+ if (need_subpage || phys_offset & IO_MEM_SUBWIDTH) {
subpage = subpage_init((addr & TARGET_PAGE_MASK),
&p->phys_offset, IO_MEM_UNASSIGNED);
subpage_register(subpage, start_addr2, end_addr2,
@@ -2308,7 +2308,6 @@
static inline uint32_t subpage_readlen (subpage_t *mmio, target_phys_addr_t addr,
unsigned int len)
{
- CPUReadMemoryFunc **mem_read;
uint32_t ret;
unsigned int idx;
@@ -2317,8 +2316,7 @@
printf("%s: subpage %p len %d addr " TARGET_FMT_plx " idx %d\n", __func__,
mmio, len, addr, idx);
#endif
- mem_read = mmio->mem_read[idx];
- ret = (*mem_read[len])(mmio->opaque[idx], addr);
+ ret = (**mmio->mem_read[idx][len])(mmio->opaque[idx][0][len], addr);
return ret;
}
@@ -2326,7 +2324,6 @@
static inline void subpage_writelen (subpage_t *mmio, target_phys_addr_t addr,
uint32_t value, unsigned int len)
{
- CPUWriteMemoryFunc **mem_write;
unsigned int idx;
idx = SUBPAGE_IDX(addr - mmio->base);
@@ -2334,8 +2331,7 @@
printf("%s: subpage %p len %d addr " TARGET_FMT_plx " idx %d value %08x\n", __func__,
mmio, len, addr, idx, value);
#endif
- mem_write = mmio->mem_write[idx];
- (*mem_write[len])(mmio->opaque[idx], addr, value);
+ (**mmio->mem_write[idx][len])(mmio->opaque[idx][1][len], addr, value);
}
static uint32_t subpage_readb (void *opaque, target_phys_addr_t addr)
@@ -2408,6 +2404,7 @@
int memory)
{
int idx, eidx;
+ unsigned int i;
if (start >= TARGET_PAGE_SIZE || end >= TARGET_PAGE_SIZE)
return -1;
@@ -2419,9 +2416,16 @@
#endif
memory >>= IO_MEM_SHIFT;
for (; idx <= eidx; idx++) {
- mmio->mem_read[idx] = io_mem_read[memory];
- mmio->mem_write[idx] = io_mem_write[memory];
- mmio->opaque[idx] = io_mem_opaque[memory];
+ for (i = 0; i < 4; i++) {
+ if (io_mem_read[memory][i]) {
+ mmio->mem_read[idx][i] = &io_mem_read[memory][i];
+ mmio->opaque[idx][0][i] = io_mem_opaque[memory];
+ }
+ if (io_mem_write[memory][i]) {
+ mmio->mem_write[idx][i] = &io_mem_write[memory][i];
+ mmio->opaque[idx][1][i] = io_mem_opaque[memory];
+ }
+ }
}
return 0;
@@ -2466,16 +2470,18 @@
/* mem_read and mem_write are arrays of functions containing the
function to access byte (index 0), word (index 1) and dword (index
- 2). All functions must be supplied. If io_index is non zero, the
- corresponding io zone is modified. If it is zero, a new io zone is
- allocated. The return value can be used with
- cpu_register_physical_memory(). (-1) is returned if error. */
+ 2). Functions can be omitted with a NULL function pointer. The
+ registered functions may be modified dynamically later.
+ If io_index is non zero, the corresponding io zone is
+ modified. If it is zero, a new io zone is allocated. The return
+ value can be used with cpu_register_physical_memory(). (-1) is
+ returned if error. */
int cpu_register_io_memory(int io_index,
CPUReadMemoryFunc **mem_read,
CPUWriteMemoryFunc **mem_write,
void *opaque)
{
- int i;
+ int i, subwidth = 0;
if (io_index <= 0) {
if (io_mem_nb >= IO_MEM_NB_ENTRIES)
@@ -2487,11 +2493,13 @@
}
for(i = 0;i < 3; i++) {
+ if (!mem_read[i] || !mem_write[i])
+ subwidth = IO_MEM_SUBWIDTH;
io_mem_read[io_index][i] = mem_read[i];
io_mem_write[io_index][i] = mem_write[i];
}
io_mem_opaque[io_index] = opaque;
- return io_index << IO_MEM_SHIFT;
+ return (io_index << IO_MEM_SHIFT) | subwidth;
}
CPUWriteMemoryFunc **cpu_get_io_memory_write(int io_index)
Modified: trunk/src/host/qemu-neo1973/fpu/softfloat-specialize.h
===================================================================
--- trunk/src/host/qemu-neo1973/fpu/softfloat-specialize.h 2008-01-06 01:02:26 UTC (rev 3777)
+++ trunk/src/host/qemu-neo1973/fpu/softfloat-specialize.h 2008-01-07 07:17:44 UTC (rev 3778)
@@ -65,7 +65,13 @@
/*----------------------------------------------------------------------------
| The pattern for a default generated single-precision NaN.
*----------------------------------------------------------------------------*/
-#if SNAN_BIT_IS_ONE
+#if defined(TARGET_SPARC)
+#define float32_default_nan make_float32(0x7FFFFFFF)
+#elif defined(TARGET_POWERPC)
+#define float32_default_nan make_float32(0x7FC00000)
+#elif defined(TARGET_HPPA)
+#define float32_default_nan make_float32(0x7FA00000)
+#elif SNAN_BIT_IS_ONE
#define float32_default_nan make_float32(0x7FBFFFFF)
#else
#define float32_default_nan make_float32(0xFFC00000)
@@ -125,8 +131,12 @@
static float32 commonNaNToFloat32( commonNaNT a )
{
- return make_float32(
- ( ( (bits32) a.sign )<<31 ) | 0x7FC00000 | ( a.high>>41 ) );
+ bits32 mantissa = a.high>>41;
+ if ( mantissa )
+ return make_float32(
+ ( ( (bits32) a.sign )<<31 ) | 0x7F800000 | ( a.high>>41 ) );
+ else
+ return float32_default_nan;
}
/*----------------------------------------------------------------------------
@@ -180,7 +190,13 @@
/*----------------------------------------------------------------------------
| The pattern for a default generated double-precision NaN.
*----------------------------------------------------------------------------*/
-#if SNAN_BIT_IS_ONE
+#if defined(TARGET_SPARC)
+#define float64_default_nan make_float64(LIT64( 0x7FFFFFFFFFFFFFFF ))
+#elif defined(TARGET_POWERPC)
+#define float64_default_nan make_float64(LIT64( 0x7FF8000000000000 ))
+#elif defined(TARGET_HPPA)
+#define float64_default_nan make_float64(LIT64( 0x7FF4000000000000 ))
+#elif SNAN_BIT_IS_ONE
#define float64_default_nan make_float64(LIT64( 0x7FF7FFFFFFFFFFFF ))
#else
#define float64_default_nan make_float64(LIT64( 0xFFF8000000000000 ))
@@ -244,10 +260,15 @@
static float64 commonNaNToFloat64( commonNaNT a )
{
- return make_float64(
- ( ( (bits64) a.sign )<<63 )
- | LIT64( 0x7FF8000000000000 )
- | ( a.high>>12 ));
+ bits64 mantissa = a.high>>12;
+
+ if ( mantissa )
+ return make_float64(
+ ( ( (bits64) a.sign )<<63 )
+ | LIT64( 0x7FF0000000000000 )
+ | ( a.high>>12 ));
+ else
+ return float64_default_nan;
}
/*----------------------------------------------------------------------------
@@ -366,7 +387,7 @@
if ( floatx80_is_signaling_nan( a ) ) float_raise( float_flag_invalid STATUS_VAR);
z.sign = a.high>>15;
z.low = 0;
- z.high = a.low<<1;
+ z.high = a.low;
return z;
}
@@ -379,7 +400,10 @@
{
floatx80 z;
- z.low = LIT64( 0xC000000000000000 ) | ( a.high>>1 );
+ if (a.high)
+ z.low = a.high;
+ else
+ z.low = floatx80_default_nan_low;
z.high = ( ( (bits16) a.sign )<<15 ) | 0x7FFF;
return z;
}
@@ -500,7 +524,7 @@
float128 z;
shift128Right( a.high, a.low, 16, &z.high, &z.low );
- z.high |= ( ( (bits64) a.sign )<<63 ) | LIT64( 0x7FFF800000000000 );
+ z.high |= ( ( (bits64) a.sign )<<63 ) | LIT64( 0x7FFF000000000000 );
return z;
}
Modified: trunk/src/host/qemu-neo1973/hw/boards.h
===================================================================
--- trunk/src/host/qemu-neo1973/hw/boards.h 2008-01-06 01:02:26 UTC (rev 3777)
+++ trunk/src/host/qemu-neo1973/hw/boards.h 2008-01-07 07:17:44 UTC (rev 3778)
@@ -53,6 +53,8 @@
/* sun4m.c */
extern QEMUMachine ss5_machine, ss10_machine, ss600mp_machine, ss20_machine;
+extern QEMUMachine ss2_machine;
+extern QEMUMachine ss1000_machine, ss2000_machine;
/* sun4u.c */
extern QEMUMachine sun4u_machine;
Modified: trunk/src/host/qemu-neo1973/hw/eccmemctl.c
===================================================================
--- trunk/src/host/qemu-neo1973/hw/eccmemctl.c 2008-01-06 01:02:26 UTC (rev 3777)
+++ trunk/src/host/qemu-neo1973/hw/eccmemctl.c 2008-01-07 07:17:44 UTC (rev 3778)
@@ -93,30 +93,6 @@
uint32_t regs[ECC_NREGS];
} ECCState;
-static void ecc_mem_writeb(void *opaque, target_phys_addr_t addr, uint32_t val)
-{
- printf("ECC: Unsupported write 0x" TARGET_FMT_plx " %02x\n",
- addr, val & 0xff);
-}
-
-static uint32_t ecc_mem_readb(void *opaque, target_phys_addr_t addr)
-{
- printf("ECC: Unsupported read 0x" TARGET_FMT_plx " 00\n", addr);
- return 0;
-}
-
-static void ecc_mem_writew(void *opaque, target_phys_addr_t addr, uint32_t val)
-{
- printf("ECC: Unsupported write 0x" TARGET_FMT_plx " %04x\n",
- addr, val & 0xffff);
-}
-
-static uint32_t ecc_mem_readw(void *opaque, target_phys_addr_t addr)
-{
- printf("ECC: Unsupported read 0x" TARGET_FMT_plx " 0000\n", addr);
- return 0;
-}
-
static void ecc_mem_writel(void *opaque, target_phys_addr_t addr, uint32_t val)
{
ECCState *s = opaque;
@@ -201,14 +177,14 @@
}
static CPUReadMemoryFunc *ecc_mem_read[3] = {
- ecc_mem_readb,
- ecc_mem_readw,
+ NULL,
+ NULL,
ecc_mem_readl,
};
static CPUWriteMemoryFunc *ecc_mem_write[3] = {
- ecc_mem_writeb,
- ecc_mem_writew,
+ NULL,
+ NULL,
ecc_mem_writel,
};
Modified: trunk/src/host/qemu-neo1973/hw/esp.c
===================================================================
--- trunk/src/host/qemu-neo1973/hw/esp.c 2008-01-06 01:02:26 UTC (rev 3777)
+++ trunk/src/host/qemu-neo1973/hw/esp.c 2008-01-07 07:17:44 UTC (rev 3778)
@@ -543,14 +543,14 @@
static CPUReadMemoryFunc *esp_mem_read[3] = {
esp_mem_readb,
- esp_mem_readb,
- esp_mem_readb,
+ NULL,
+ NULL,
};
static CPUWriteMemoryFunc *esp_mem_write[3] = {
esp_mem_writeb,
- esp_mem_writeb,
- esp_mem_writeb,
+ NULL,
+ NULL,
};
static void esp_save(QEMUFile *f, void *opaque)
Modified: trunk/src/host/qemu-neo1973/hw/fdc.c
===================================================================
--- trunk/src/host/qemu-neo1973/hw/fdc.c 2008-01-06 01:02:26 UTC (rev 3777)
+++ trunk/src/host/qemu-neo1973/hw/fdc.c 2008-01-07 07:17:44 UTC (rev 3778)
@@ -493,6 +493,18 @@
fdctrl_write_mem,
};
+static CPUReadMemoryFunc *fdctrl_mem_read_strict[3] = {
+ fdctrl_read_mem,
+ NULL,
+ NULL,
+};
+
+static CPUWriteMemoryFunc *fdctrl_mem_write_strict[3] = {
+ fdctrl_write_mem,
+ NULL,
+ NULL,
+};
+
static void fd_save (QEMUFile *f, fdrive_t *fd)
{
uint8_t tmp;
@@ -586,12 +598,11 @@
fdctrl_reset(s, 0);
}
-fdctrl_t *fdctrl_init (qemu_irq irq, int dma_chann, int mem_mapped,
- target_phys_addr_t io_base,
- BlockDriverState **fds)
+static fdctrl_t *fdctrl_init_common (qemu_irq irq, int dma_chann,
+ target_phys_addr_t io_base,
+ BlockDriverState **fds)
{
fdctrl_t *fdctrl;
- int io_mem;
int i;
FLOPPY_DPRINTF("init controller\n");
@@ -611,7 +622,6 @@
fdctrl->dma_chann = dma_chann;
fdctrl->io_base = io_base;
fdctrl->config = 0x60; /* Implicit seek, polling & FIFO enabled */
- fdctrl->sun4m = 0;
if (fdctrl->dma_chann != -1) {
fdctrl->dma_en = 1;
DMA_register_channel(dma_chann, &fdctrl_transfer_handler, fdctrl);
@@ -623,6 +633,25 @@
}
fdctrl_reset(fdctrl, 0);
fdctrl->state = FD_CTRL_ACTIVE;
+ register_savevm("fdc", io_base, 1, fdc_save, fdc_load, fdctrl);
+ qemu_register_reset(fdctrl_external_reset, fdctrl);
+ for (i = 0; i < 2; i++) {
+ fd_revalidate(&fdctrl->drives[i]);
+ }
+
+ return fdctrl;
+}
+
+fdctrl_t *fdctrl_init (qemu_irq irq, int dma_chann, int mem_mapped,
+ target_phys_addr_t io_base,
+ BlockDriverState **fds)
+{
+ fdctrl_t *fdctrl;
+ int io_mem;
+
+ fdctrl = fdctrl_init_common(irq, dma_chann, io_base, fds);
+
+ fdctrl->sun4m = 0;
if (mem_mapped) {
io_mem = cpu_register_io_memory(0, fdctrl_mem_read, fdctrl_mem_write,
fdctrl);
@@ -637,11 +666,6 @@
register_ioport_write((uint32_t)io_base + 0x07, 1, 1, &fdctrl_write,
fdctrl);
}
- register_savevm("fdc", io_base, 1, fdc_save, fdc_load, fdctrl);
- qemu_register_reset(fdctrl_external_reset, fdctrl);
- for (i = 0; i < 2; i++) {
- fd_revalidate(&fdctrl->drives[i]);
- }
return fdctrl;
}
@@ -650,9 +674,14 @@
BlockDriverState **fds)
{
fdctrl_t *fdctrl;
+ int io_mem;
- fdctrl = fdctrl_init(irq, 0, 1, io_base, fds);
+ fdctrl = fdctrl_init_common(irq, 0, io_base, fds);
fdctrl->sun4m = 1;
+ io_mem = cpu_register_io_memory(0, fdctrl_mem_read_strict,
+ fdctrl_mem_write_strict,
+ fdctrl);
+ cpu_register_physical_memory(io_base, 0x08, io_mem);
return fdctrl;
}
Modified: trunk/src/host/qemu-neo1973/hw/iommu.c
===================================================================
--- trunk/src/host/qemu-neo1973/hw/iommu.c 2008-01-06 01:02:26 UTC (rev 3777)
+++ trunk/src/host/qemu-neo1973/hw/iommu.c 2008-01-07 07:17:44 UTC (rev 3778)
@@ -112,24 +112,31 @@
uint32_t regs[IOMMU_NREGS];
target_phys_addr_t iostart;
uint32_t version;
+ qemu_irq irq;
} IOMMUState;
-static uint32_t iommu_mem_readw(void *opaque, target_phys_addr_t addr)
+static uint32_t iommu_mem_readl(void *opaque, target_phys_addr_t addr)
{
IOMMUState *s = opaque;
target_phys_addr_t saddr;
+ uint32_t ret;
saddr = (addr - s->addr) >> 2;
switch (saddr) {
default:
- DPRINTF("read reg[%d] = %x\n", (int)saddr, s->regs[saddr]);
- return s->regs[saddr];
+ ret = s->regs[saddr];
break;
+ case IOMMU_AFAR:
+ case IOMMU_AFSR:
+ ret = s->regs[saddr];
+ qemu_irq_lower(s->irq);
+ break;
}
- return 0;
+ DPRINTF("read reg[%d] = %x\n", (int)saddr, ret);
+ return ret;
}
-static void iommu_mem_writew(void *opaque, target_phys_addr_t addr,
+static void iommu_mem_writel(void *opaque, target_phys_addr_t addr,
uint32_t val)
{
IOMMUState *s = opaque;
@@ -180,8 +187,13 @@
DPRINTF("page flush %x\n", val);
s->regs[saddr] = val & IOMMU_PGFLUSH_MASK;
break;
+ case IOMMU_AFAR:
+ s->regs[saddr] = val;
+ qemu_irq_lower(s->irq);
+ break;
case IOMMU_AFSR:
s->regs[saddr] = (val & IOMMU_AFSR_MASK) | IOMMU_AFSR_RESV;
+ qemu_irq_lower(s->irq);
break;
case IOMMU_SBCFG0:
case IOMMU_SBCFG1:
@@ -201,15 +213,15 @@
}
static CPUReadMemoryFunc *iommu_mem_read[3] = {
- iommu_mem_readw,
- iommu_mem_readw,
- iommu_mem_readw,
+ NULL,
+ NULL,
+ iommu_mem_readl,
};
static CPUWriteMemoryFunc *iommu_mem_write[3] = {
- iommu_mem_writew,
- iommu_mem_writew,
- iommu_mem_writew,
+ NULL,
+ NULL,
+ iommu_mem_writel,
};
static uint32_t iommu_page_get_flags(IOMMUState *s, target_phys_addr_t addr)
@@ -255,6 +267,7 @@
if (!is_write)
s->regs[IOMMU_AFSR] |= IOMMU_AFSR_RD;
s->regs[IOMMU_AFAR] = addr;
+ qemu_irq_raise(s->irq);
}
void sparc_iommu_memory_rw(void *opaque, target_phys_addr_t addr,
@@ -324,9 +337,10 @@
s->regs[IOMMU_CTRL] = s->version;
s->regs[IOMMU_ARBEN] = IOMMU_MID;
s->regs[IOMMU_AFSR] = IOMMU_AFSR_RESV;
+ qemu_irq_lower(s->irq);
}
-void *iommu_init(target_phys_addr_t addr, uint32_t version)
+void *iommu_init(target_phys_addr_t addr, uint32_t version, qemu_irq irq)
{
IOMMUState *s;
int iommu_io_memory;
@@ -337,6 +351,7 @@
s->addr = addr;
s->version = version;
+ s->irq = irq;
iommu_io_memory = cpu_register_io_memory(0, iommu_mem_read,
iommu_mem_write, s);
Modified: trunk/src/host/qemu-neo1973/hw/m48t59.c
===================================================================
--- trunk/src/host/qemu-neo1973/hw/m48t59.c 2008-01-06 01:02:26 UTC (rev 3777)
+++ trunk/src/host/qemu-neo1973/hw/m48t59.c 2008-01-07 07:17:44 UTC (rev 3778)
@@ -36,13 +36,13 @@
#endif
/*
- * The M48T08 and M48T59 chips are very similar. The newer '59 has
+ * The M48T02, M48T08 and M48T59 chips are very similar. The newer '59 has
* alarm and a watchdog timer and related control registers. In the
* PPC platform there is also a nvram lock function.
*/
struct m48t59_t {
/* Model parameters */
- int type; // 8 = m48t08, 59 = m48t59
+ int type; // 2 = m48t02, 8 = m48t08, 59 = m48t59
/* Hardware parameters */
qemu_irq IRQ;
int mem_index;
@@ -210,9 +210,14 @@
if (addr > 0x1FF8 && addr < 0x2000)
NVRAM_PRINTF("%s: 0x%08x => 0x%08x\n", __func__, addr, val);
- if (NVRAM->type == 8 &&
- (addr >= 0x1ff0 && addr <= 0x1ff7))
+
+ /* check for NVRAM access */
+ if ((NVRAM->type == 2 && addr < 0x7f8) ||
+ (NVRAM->type == 8 && addr < 0x1ff8) ||
+ (NVRAM->type == 59 && addr < 0x1ff0))
goto do_write;
+
+ /* TOD access */
switch (addr) {
case 0x1FF0:
/* flags register : read-only */
@@ -270,10 +275,12 @@
set_up_watchdog(NVRAM, val);
break;
case 0x1FF8:
+ case 0x07F8:
/* control */
- NVRAM->buffer[0x1FF8] = (val & ~0xA0) | 0x90;
+ NVRAM->buffer[addr] = (val & ~0xA0) | 0x90;
break;
case 0x1FF9:
+ case 0x07F9:
/* seconds (BCD) */
tmp = fromBCD(val & 0x7F);
if (tmp >= 0 && tmp <= 59) {
@@ -281,7 +288,7 @@
tm.tm_sec = tmp;
set_time(NVRAM, &tm);
}
- if ((val & 0x80) ^ (NVRAM->buffer[0x1FF9] & 0x80)) {
+ if ((val & 0x80) ^ (NVRAM->buffer[addr] & 0x80)) {
if (val & 0x80) {
NVRAM->stop_time = time(NULL);
} else {
@@ -289,9 +296,10 @@
NVRAM->stop_time = 0;
}
}
- NVRAM->buffer[0x1FF9] = val & 0x80;
+ NVRAM->buffer[addr] = val & 0x80;
break;
case 0x1FFA:
+ case 0x07FA:
/* minutes (BCD) */
tmp = fromBCD(val & 0x7F);
if (tmp >= 0 && tmp <= 59) {
@@ -301,6 +309,7 @@
}
break;
case 0x1FFB:
+ case 0x07FB:
/* hours (BCD) */
tmp = fromBCD(val & 0x3F);
if (tmp >= 0 && tmp <= 23) {
@@ -310,14 +319,16 @@
}
break;
case 0x1FFC:
+ case 0x07FC:
/* day of the week / century */
tmp = fromBCD(val & 0x07);
get_time(NVRAM, &tm);
tm.tm_wday = tmp;
set_time(NVRAM, &tm);
- NVRAM->buffer[0x1FFC] = val & 0x40;
+ NVRAM->buffer[addr] = val & 0x40;
break;
case 0x1FFD:
+ case 0x07FD:
/* date */
tmp = fromBCD(val & 0x1F);
if (tmp != 0) {
@@ -327,6 +338,7 @@
}
break;
case 0x1FFE:
+ case 0x07FE:
/* month */
tmp = fromBCD(val & 0x1F);
if (tmp >= 1 && tmp <= 12) {
@@ -336,6 +348,7 @@
}
break;
case 0x1FFF:
+ case 0x07FF:
/* year */
tmp = fromBCD(val);
if (tmp >= 0 && tmp <= 99) {
@@ -367,9 +380,13 @@
struct tm tm;
uint32_t retval = 0xFF;
- if (NVRAM->type == 8 &&
- (addr >= 0x1ff0 && addr <= 0x1ff7))
+ /* check for NVRAM access */
+ if ((NVRAM->type == 2 && addr < 0x078f) ||
+ (NVRAM->type == 8 && addr < 0x1ff8) ||
+ (NVRAM->type == 59 && addr < 0x1ff0))
goto do_read;
+
+ /* TOD access */
switch (addr) {
case 0x1FF0:
/* flags register */
@@ -398,39 +415,47 @@
set_up_watchdog(NVRAM, NVRAM->buffer[0x1FF7]);
goto do_read;
case 0x1FF8:
+ case 0x07F8:
/* control */
goto do_read;
case 0x1FF9:
+ case 0x07F9:
/* seconds (BCD) */
get_time(NVRAM, &tm);
- retval = (NVRAM->buffer[0x1FF9] & 0x80) | toBCD(tm.tm_sec);
+ retval = (NVRAM->buffer[addr] & 0x80) | toBCD(tm.tm_sec);
break;
case 0x1FFA:
+ case 0x07FA:
/* minutes (BCD) */
get_time(NVRAM, &tm);
retval = toBCD(tm.tm_min);
break;
case 0x1FFB:
+ case 0x07FB:
/* hours (BCD) */
get_time(NVRAM, &tm);
retval = toBCD(tm.tm_hour);
break;
case 0x1FFC:
+ case 0x07FC:
/* day of the week / century */
get_time(NVRAM, &tm);
- retval = NVRAM->buffer[0x1FFC] | tm.tm_wday;
+ retval = NVRAM->buffer[addr] | tm.tm_wday;
break;
case 0x1FFD:
+ case 0x07FD:
/* date */
get_time(NVRAM, &tm);
retval = toBCD(tm.tm_mday);
break;
case 0x1FFE:
+ case 0x07FE:
/* month */
get_time(NVRAM, &tm);
retval = toBCD(tm.tm_mon + 1);
break;
case 0x1FFF:
+ case 0x07FF:
/* year */
get_time(NVRAM, &tm);
if (NVRAM->type == 8)
@@ -451,7 +476,7 @@
break;
}
if (addr > 0x1FF9 && addr < 0x2000)
- NVRAM_PRINTF("0x%08x <= 0x%08x\n", addr, retval);
+ NVRAM_PRINTF("%s: 0x%08x <= 0x%08x\n", __func__, addr, retval);
return retval;
}
@@ -476,7 +501,7 @@
m48t59_t *NVRAM = opaque;
addr -= NVRAM->io_base;
- NVRAM_PRINTF("0x%08x => 0x%08x\n", addr, val);
+ NVRAM_PRINTF("%s: 0x%08x => 0x%08x\n", __func__, addr, val);
switch (addr) {
case 0:
NVRAM->addr &= ~0x00FF;
@@ -509,7 +534,7 @@
retval = -1;
break;
}
- NVRAM_PRINTF("0x%08x <= 0x%08x\n", addr, retval);
+ NVRAM_PRINTF("%s: 0x%08x <= 0x%08x\n", __func__, addr, retval);
return retval;
}
@@ -650,7 +675,7 @@
}
if (mem_base != 0) {
s->mem_index = cpu_register_io_memory(0, nvram_read, nvram_write, s);
- cpu_register_physical_memory(mem_base, 0x4000, s->mem_index);
+ cpu_register_physical_memory(mem_base, size, s->mem_index);
}
if (type == 59) {
s->alrm_timer = qemu_new_timer(vm_clock, &alarm_cb, s);
Modified: trunk/src/host/qemu-neo1973/hw/mainstone.c
===================================================================
--- trunk/src/host/qemu-neo1973/hw/mainstone.c 2008-01-06 01:02:26 UTC (rev 3777)
+++ trunk/src/host/qemu-neo1973/hw/mainstone.c 2008-01-07 07:17:44 UTC (rev 3778)
@@ -64,19 +64,24 @@
const char *kernel_cmdline, const char *initrd_filename,
const char *cpu_model, enum mainstone_model_e model, int arm_id)
{
- uint32_t mainstone_ram = 0x04000000;
- uint32_t mainstone_rom = 0x00800000;
+ uint32_t mainstone_ram = 0x04000000;
+ uint32_t mainstone_rom = 0x00800000;
+ uint32_t mainstone_flash = 0x02000000;
+ uint32_t sector_len = 256 * 1024;
+ target_phys_addr_t mainstone_flash_base[] = { MST_FLASH_0, MST_FLASH_1 };
struct pxa2xx_state_s *cpu;
qemu_irq *mst_irq;
- int index;
+ int i, index;
if (!cpu_model)
cpu_model = "pxa270-c5";
/* Setup CPU & memory */
- if (ram_size < mainstone_ram + mainstone_rom + PXA2XX_INTERNAL_SIZE) {
+ if (ram_size < mainstone_ram + mainstone_rom + 2 * mainstone_flash +
+ PXA2XX_INTERNAL_SIZE) {
fprintf(stderr, "This platform requires %i bytes of memory\n",
- mainstone_ram + mainstone_rom + PXA2XX_INTERNAL_SIZE);
+ mainstone_ram + mainstone_rom + 2 * mainstone_flash +
+ PXA2XX_INTERNAL_SIZE);
exit(1);
}
@@ -88,33 +93,22 @@
cpu->env->regs[15] = PXA2XX_SDRAM_BASE;
/* There are two 32MiB flash devices on the board */
- index = drive_get_index(IF_PFLASH, 0, 0);
- if (index == -1) {
- fprintf(stderr, "Two flash images must be given with the "
- "'pflash' parameter\n");
- exit(1);
- }
- if (!pflash_cfi01_register(MST_FLASH_0,
- mainstone_ram + PXA2XX_INTERNAL_SIZE,
- drives_table[index].bdrv,
- 256 * 1024, 128, 4, 0, 0, 0, 0)) {
- fprintf(stderr, "qemu: Error registering flash memory.\n");
- exit(1);
- }
+ for (i = 0; i < 2; i ++) {
+ index = drive_get_index(IF_PFLASH, 0, i);
+ if (index == -1) {
+ fprintf(stderr, "Two flash images must be given with the "
+ "'pflash' parameter\n");
+ exit(1);
+ }
- index = drive_get_index(IF_PFLASH, 0, 1);
- if (index == -1) {
- fprintf(stderr, "Two flash images must be given with the "
- "'pflash' parameter\n");
- exit(1);
+ if (!pflash_cfi01_register(mainstone_flash_base[i],
+ qemu_ram_alloc(mainstone_flash),
+ drives_table[index].bdrv, sector_len,
+ mainstone_flash / sector_len, 4, 0, 0, 0, 0)) {
+ fprintf(stderr, "qemu: Error registering flash memory.\n");
+ exit(1);
+ }
}
- if (!pflash_cfi01_register(MST_FLASH_1,
- mainstone_ram + PXA2XX_INTERNAL_SIZE,
- drives_table[index].bdrv,
- 256 * 1024, 128, 4, 0, 0, 0, 0)) {
- fprintf(stderr, "qemu: Error registering flash memory.\n");
- exit(1);
- }
mst_irq = mst_irq_init(cpu, MST_FPGA_PHYS, PXA2XX_PIC_GPIO_0);
Modified: trunk/src/host/qemu-neo1973/hw/mips_malta.c
===================================================================
--- trunk/src/host/qemu-neo1973/hw/mips_malta.c 2008-01-06 01:02:26 UTC (rev 3777)
+++ trunk/src/host/qemu-neo1973/hw/mips_malta.c 2008-01-07 07:17:44 UTC (rev 3778)
@@ -28,6 +28,8 @@
#include "net.h"
#include "boards.h"
#include "smbus.h"
+#include "block.h"
+#include "flash.h"
#include "mips.h"
#include "pci.h"
#include "qemu-char.h"
@@ -35,6 +37,8 @@
#include "audio/audio.h"
#include "boards.h"
+//#define DEBUG_BOARD_INIT
+
#ifdef TARGET_WORDS_BIGENDIAN
#define BIOS_FILENAME "mips_bios.bin"
#else
@@ -766,13 +770,13 @@
{
char buf[1024];
unsigned long bios_offset;
+ target_long bios_size;
int64_t kernel_entry;
PCIBus *pci_bus;
CPUState *env;
RTCState *rtc_state;
fdctrl_t *floppy_controller;
MaltaFPGAState *malta_fpga;
- int ret;
qemu_irq *i8259;
int piix4_devfn;
uint8_t *eeprom_buf;
@@ -781,6 +785,8 @@
int index;
BlockDriverState *hd[MAX_IDE_BUS * MAX_IDE_DEVS];
BlockDriverState *fd[MAX_FD];
+ int fl_idx = 0;
+ int fl_sectors = 0;
/* init CPUs */
if (cpu_model == NULL) {
@@ -801,7 +807,7 @@
/* allocate RAM */
cpu_register_physical_memory(0, ram_size, IO_MEM_RAM);
- /* Map the bios at two physical locations, as on the real board */
+ /* Map the bios at two physical locations, as on the real board. */
bios_offset = ram_size + vga_ram_size;
cpu_register_physical_memory(0x1e000000LL,
BIOS_SIZE, bios_offset | IO_MEM_ROM);
@@ -811,17 +817,44 @@
/* FPGA */
malta_fpga = malta_fpga_init(0x1f000000LL, env);
- /* Load a BIOS image unless a kernel image has been specified. */
- if (!kernel_filename) {
- if (bios_name == NULL)
- bios_name = BIOS_FILENAME;
- snprintf(buf, sizeof(buf), "%s/%s", bios_dir, bios_name);
- ret = load_image(buf, phys_ram_base + bios_offset);
- if (ret < 0 || ret > BIOS_SIZE) {
- fprintf(stderr,
- "qemu: Could not load MIPS bios '%s', and no -kernel argument was specified\n",
- buf);
- exit(1);
+ /* Load firmware in flash / BIOS unless we boot directly into a kernel. */
+ if (kernel_filename) {
+ /* Write a small bootloader to the flash location. */
+ loaderparams.ram_size = ram_size;
+ loaderparams.kernel_filename = kernel_filename;
+ loaderparams.kernel_cmdline = kernel_cmdline;
+ loaderparams.initrd_filename = initrd_filename;
+ kernel_entry = load_kernel(env);
+ env->CP0_Status &= ~((1 << CP0St_BEV) | (1 << CP0St_ERL));
+ write_bootloader(env, bios_offset, kernel_entry);
+ } else {
+ index = drive_get_index(IF_PFLASH, 0, fl_idx);
+ if (index != -1) {
+ /* Load firmware from flash. */
+ bios_size = 0x400000;
+ fl_sectors = bios_size >> 16;
+#ifdef DEBUG_BOARD_INIT
+ printf("Register parallel flash %d size " TARGET_FMT_lx " at "
+ "offset %08lx addr %08llx '%s' %x\n",
+ fl_idx, bios_size, bios_offset, 0x1e000000LL,
+ bdrv_get_device_name(drives_table[index].bdrv), fl_sectors);
+#endif
+ pflash_cfi01_register(0x1e000000LL, bios_offset,
+ drives_table[index].bdrv, 65536, fl_sectors,
+ 4, 0x0000, 0x0000, 0x0000, 0x0000);
+ fl_idx++;
+ } else {
+ /* Load a BIOS image. */
+ if (bios_name == NULL)
+ bios_name = BIOS_FILENAME;
+ snprintf(buf, sizeof(buf), "%s/%s", bios_dir, bios_name);
+ bios_size = load_image(buf, phys_ram_base + bios_offset);
+ if ((bios_size < 0 || bios_size > BIOS_SIZE) && !kernel_filename) {
+ fprintf(stderr,
+ "qemu: Could not load MIPS bios '%s', and no -kernel argument was specified\n",
+ buf);
+ exit(1);
+ }
}
/* In little endian mode the 32bit words in the bios are swapped,
a neat trick which allows bi-endian firmware. */
@@ -829,26 +862,14 @@
{
uint32_t *addr;
for (addr = (uint32_t *)(phys_ram_base + bios_offset);
- addr < (uint32_t *)(phys_ram_base + bios_offset + ret);
- addr++) {
+ addr < (uint32_t *)(phys_ram_base + bios_offset + bios_size);
+ addr++) {
*addr = bswap32(*addr);
}
}
#endif
}
- /* If a kernel image has been specified, write a small bootloader
- to the flash location. */
- if (kernel_filename) {
- loaderparams.ram_size = ram_size;
- loaderparams.kernel_filename = kernel_filename;
- loaderparams.kernel_cmdline = kernel_cmdline;
- loaderparams.initrd_filename = initrd_filename;
- kernel_entry = load_kernel(env);
- env->CP0_Status &= ~((1 << CP0St_BEV) | (1 << CP0St_ERL));
- write_bootloader(env, bios_offset, kernel_entry);
- }
-
/* Board ID = 0x420 (Malta Board with CoreLV)
XXX: theoretically 0x1e000010 should map to flash and 0x1fc00010 should
map to the board ID. */
Modified: trunk/src/host/qemu-neo1973/hw/pcnet.c
===================================================================
--- trunk/src/host/qemu-neo1973/hw/pcnet.c 2008-01-06 01:02:26 UTC (rev 3777)
+++ trunk/src/host/qemu-neo1973/hw/pcnet.c 2008-01-07 07:17:44 UTC (rev 3778)
@@ -2043,15 +2043,15 @@
}
static CPUReadMemoryFunc *lance_mem_read[3] = {
+ NULL,
lance_mem_readw,
- lance_mem_readw,
- lance_mem_readw,
+ NULL,
};
static CPUWriteMemoryFunc *lance_mem_write[3] = {
+ NULL,
lance_mem_writew,
- lance_mem_writew,
- lance_mem_writew,
+ NULL,
};
void lance_init(NICInfo *nd, target_phys_addr_t leaddr, void *dma_opaque,
Modified: trunk/src/host/qemu-neo1973/hw/pflash_cfi01.c
===================================================================
--- trunk/src/host/qemu-neo1973/hw/pflash_cfi01.c 2008-01-06 01:02:26 UTC (rev 3777)
+++ trunk/src/host/qemu-neo1973/hw/pflash_cfi01.c 2008-01-07 07:17:44 UTC (rev 3778)
@@ -111,8 +111,8 @@
else if (pfl->width == 4)
boff = boff >> 2;
- DPRINTF("%s: reading offset %08x under cmd %02x\n",
- __func__, boff, pfl->cmd);
+ DPRINTF("%s: reading offset " TARGET_FMT_lx " under cmd %02x\n",
+ __func__, boff, pfl->cmd);
switch (pfl->cmd) {
case 0x00:
@@ -121,7 +121,8 @@
switch (width) {
case 1:
ret = p[offset];
- DPRINTF("%s: data offset %08x %02x\n", __func__, offset, ret);
+ DPRINTF("%s: data offset " TARGET_FMT_lx " %02x\n",
+ __func__, offset, ret);
break;
case 2:
#if defined(TARGET_WORDS_BIGENDIAN)
@@ -131,7 +132,8 @@
ret = p[offset];
ret |= p[offset + 1] << 8;
#endif
- DPRINTF("%s: data offset %08x %04x\n", __func__, offset, ret);
+ DPRINTF("%s: data offset " TARGET_FMT_lx " %04x\n",
+ __func__, offset, ret);
break;
case 4:
#if defined(TARGET_WORDS_BIGENDIAN)
@@ -146,7 +148,8 @@
ret |= p[offset + 2] << 16;
ret |= p[offset + 3] << 24;
#endif
- DPRINTF("%s: data offset %08x %08x\n", __func__, offset, ret);
+ DPRINTF("%s: data offset " TARGET_FMT_lx " %08x\n",
+ __func__, offset, ret);
break;
default:
DPRINTF("BUG in %s\n", __func__);
@@ -208,8 +211,8 @@
else
offset -= pfl->base;
- DPRINTF("%s: offset %08x %08x %d wcycle 0x%x\n",
- __func__, offset, value, width, pfl->wcycle);
+ DPRINTF("%s: offset " TARGET_FMT_lx " %08x %d wcycle 0x%x\n",
+ __func__, offset, value, width, pfl->wcycle);
/* Set the device in I/O access mode */
cpu_register_physical_memory(pfl->base, pfl->total_len, pfl->fl_mem);
@@ -230,8 +233,9 @@
p = pfl->storage;
offset &= ~(pfl->sector_len - 1);
- DPRINTF("%s: block erase at 0x%x bytes 0x%x\n", __func__,
- offset, pfl->sector_len);
+ DPRINTF("%s: block erase at " TARGET_FMT_lx " bytes "
+ TARGET_FMT_lx "\n",
+ __func__, offset, pfl->sector_len);
memset(p + offset, 0xff, pfl->sector_len);
pflash_update(pfl, offset, pfl->sector_len);
@@ -278,7 +282,7 @@
break;
case 0xe8:
- DPRINTF("%s: block write of 0x%x bytes\n", __func__, cmd);
+ DPRINTF("%s: block write of %x bytes\n", __func__, cmd);
pfl->counter = cmd;
pfl->wcycle++;
break;
@@ -311,8 +315,9 @@
switch (pfl->cmd) {
case 0xe8: /* Block write */
p = pfl->storage;
- DPRINTF("%s: block write offset 0x%x value 0x%x counter 0x%x\n",
- __func__, offset, value, pfl->counter);
+ DPRINTF("%s: block write offset " TARGET_FMT_lx
+ " value %x counter " TARGET_FMT_lx "\n",
+ __func__, offset, value, pfl->counter);
switch (width) {
case 1:
p[offset] = value;
@@ -382,8 +387,8 @@
error_flash:
printf("%s: Unimplemented flash cmd sequence "
- "(offset 0x%x, wcycle 0x%x cmd 0x%x value 0x%x\n",
- __func__, offset, pfl->wcycle, pfl->cmd, value);
+ "(offset " TARGET_FMT_lx ", wcycle 0x%x cmd 0x%x value 0x%x\n",
+ __func__, offset, pfl->wcycle, pfl->cmd, value);
reset_flash:
cpu_register_physical_memory(pfl->base, pfl->total_len,
@@ -484,7 +489,7 @@
}
pflash_t *pflash_cfi01_register(target_phys_addr_t base, ram_addr_t off,
- BlockDriverState *bs, target_ulong sector_len,
+ BlockDriverState *bs, uint32_t sector_len,
int nb_blocs, int width,
uint16_t id0, uint16_t id1,
uint16_t id2, uint16_t id3)
@@ -495,9 +500,11 @@
total_len = sector_len * nb_blocs;
/* XXX: to be fixed */
+#if 0
if (total_len != (8 * 1024 * 1024) && total_len != (16 * 1024 * 1024) &&
total_len != (32 * 1024 * 1024) && total_len != (64 * 1024 * 1024))
return NULL;
+#endif
pfl = qemu_mallocz(sizeof(pflash_t));
Added: trunk/src/host/qemu-neo1973/hw/sbi.c
===================================================================
--- trunk/src/host/qemu-neo1973/hw/sbi.c 2008-01-06 01:02:26 UTC (rev 3777)
+++ trunk/src/host/qemu-neo1973/hw/sbi.c 2008-01-07 07:17:44 UTC (rev 3778)
@@ -0,0 +1,167 @@
+/*
+ * QEMU Sparc SBI interrupt controller emulation
+ *
+ * Based on slavio_intctl, copyright (c) 2003-2005 Fabrice Bellard
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+#include "hw.h"
+#include "sun4m.h"
+#include "console.h"
+
+//#define DEBUG_IRQ
+
+#ifdef DEBUG_IRQ
+#define DPRINTF(fmt, args...) \
+do { printf("IRQ: " fmt , ##args); } while (0)
+#else
+#define DPRINTF(fmt, args...)
+#endif
+
+#define MAX_CPUS 16
+
+#define SBI_NREGS 16
+
+typedef struct SBIState {
+ uint32_t regs[SBI_NREGS];
+ uint32_t intreg_pending[MAX_CPUS];
+ qemu_irq *cpu_irqs[MAX_CPUS];
+ uint32_t pil_out[MAX_CPUS];
+} SBIState;
+
+#define SBI_SIZE (SBI_NREGS * 4)
+#define SBI_MASK (SBI_SIZE - 1)
+
+static void sbi_check_interrupts(void *opaque)
+{
+}
+
+static void sbi_set_irq(void *opaque, int irq, int level)
+{
+}
+
+static void sbi_set_timer_irq_cpu(void *opaque, int cpu, int level)
+{
+}
+
+static uint32_t sbi_mem_readl(void *opaque, target_phys_addr_t addr)
+{
+ SBIState *s = opaque;
+ uint32_t saddr, ret;
+
+ saddr = (addr & SBI_MASK) >> 2;
+ switch (saddr) {
+ default:
+ ret = s->regs[saddr];
+ break;
+ }
+ DPRINTF("read system reg 0x" TARGET_FMT_plx " = %x\n", addr, ret);
+
+ return ret;
+}
+
+static void sbi_mem_writel(void *opaque, target_phys_addr_t addr, uint32_t val)
+{
+ SBIState *s = opaque;
+ uint32_t saddr;
+
+ saddr = (addr & SBI_MASK) >> 2;
+ DPRINTF("write system reg 0x" TARGET_FMT_plx " = %x\n", addr, val);
+ switch (saddr) {
+ default:
+ s->regs[saddr] = val;
+ break;
+ }
+}
+
+static CPUReadMemoryFunc *sbi_mem_read[3] = {
+ NULL,
+ NULL,
+ sbi_mem_readl,
+};
+
+static CPUWriteMemoryFunc *sbi_mem_write[3] = {
+ NULL,
+ NULL,
+ sbi_mem_writel,
+};
+
+static void sbi_save(QEMUFile *f, void *opaque)
+{
+ SBIState *s = opaque;
+ unsigned int i;
+
+ for (i = 0; i < MAX_CPUS; i++) {
+ qemu_put_be32s(f, &s->intreg_pending[i]);
+ }
+}
+
+static int sbi_load(QEMUFile *f, void *opaque, int version_id)
+{
+ SBIState *s = opaque;
+ unsigned int i;
+
+ if (version_id != 1)
+ return -EINVAL;
+
+ for (i = 0; i < MAX_CPUS; i++) {
+ qemu_get_be32s(f, &s->intreg_pending[i]);
+ }
+ sbi_check_interrupts(s);
+
+ return 0;
+}
+
+static void sbi_reset(void *opaque)
+{
+ SBIState *s = opaque;
+ unsigned int i;
+
+ for (i = 0; i < MAX_CPUS; i++) {
+ s->intreg_pending[i] = 0;
+ }
+ sbi_check_interrupts(s);
+}
+
+void *sbi_init(target_phys_addr_t addr, qemu_irq **irq, qemu_irq **cpu_irq,
+ qemu_irq **parent_irq)
+{
+ unsigned int i;
+ int sbi_io_memory;
+ SBIState *s;
+
+ s = qemu_mallocz(sizeof(SBIState));
+ if (!s)
+ return NULL;
+
+ for (i = 0; i < MAX_CPUS; i++) {
+ s->cpu_irqs[i] = parent_irq[i];
+ }
+
+ sbi_io_memory = cpu_register_io_memory(0, sbi_mem_read, sbi_mem_write, s);
+ cpu_register_physical_memory(addr, SBI_SIZE, sbi_io_memory);
+
+ register_savevm("sbi", addr, 1, sbi_save, sbi_load, s);
+ qemu_register_reset(sbi_reset, s);
+ *irq = qemu_allocate_irqs(sbi_set_irq, s, 32);
+ *cpu_irq = qemu_allocate_irqs(sbi_set_timer_irq_cpu, s, MAX_CPUS);
+ sbi_reset(s);
+
+ return s;
+}
Modified: trunk/src/host/qemu-neo1973/hw/slavio_intctl.c
===================================================================
--- trunk/src/host/qemu-neo1973/hw/slavio_intctl.c 2008-01-06 01:02:26 UTC (rev 3777)
+++ trunk/src/host/qemu-neo1973/hw/slavio_intctl.c 2008-01-07 07:17:44 UTC (rev 3778)
@@ -59,7 +59,7 @@
#endif
qemu_irq *cpu_irqs[MAX_CPUS];
const uint32_t *intbit_to_level;
- uint32_t cputimer_bit;
+ uint32_t cputimer_lbit, cputimer_mbit;
uint32_t pil_out[MAX_CPUS];
} SLAVIO_INTCTLState;
@@ -68,9 +68,10 @@
#define INTCTLM_MAXADDR 0x13
#define INTCTLM_SIZE (INTCTLM_MAXADDR + 1)
#define INTCTLM_MASK 0x1f
-#define MASTER_IRQ_MASK ~0x4fb2007f
+#define MASTER_IRQ_MASK ~0x0fa2007f
#define MASTER_DISABLE 0x80000000
-#define CPU_IRQ_MASK 0xfffe0000
+#define CPU_SOFTIRQ_MASK 0xfffe0000
+#define CPU_HARDIRQ_MASK 0x0000fffe
#define CPU_IRQ_INT15_IN 0x0004000
#define CPU_IRQ_INT15_MASK 0x80000000
@@ -111,13 +112,13 @@
case 1: // clear pending softints
if (val & CPU_IRQ_INT15_IN)
val |= CPU_IRQ_INT15_MASK;
- val &= CPU_IRQ_MASK;
+ val &= CPU_SOFTIRQ_MASK;
s->intreg_pending[cpu] &= ~val;
slavio_check_interrupts(s);
DPRINTF("Cleared cpu %d irq mask %x, curmask %x\n", cpu, val, s->intreg_pending[cpu]);
break;
case 2: // set softint
- val &= CPU_IRQ_MASK;
+ val &= CPU_SOFTIRQ_MASK;
s->intreg_pending[cpu] |= val;
slavio_check_interrupts(s);
DPRINTF("Set cpu %d irq mask %x, curmask %x\n", cpu, val, s->intreg_pending[cpu]);
@@ -128,15 +129,15 @@
}
static CPUReadMemoryFunc *slavio_intctl_mem_read[3] = {
+ NULL,
+ NULL,
slavio_intctl_mem_readl,
- slavio_intctl_mem_readl,
- slavio_intctl_mem_readl,
};
static CPUWriteMemoryFunc *slavio_intctl_mem_write[3] = {
+ NULL,
+ NULL,
slavio_intctl_mem_writel,
- slavio_intctl_mem_writel,
- slavio_intctl_mem_writel,
};
// master system interrupt controller
@@ -145,13 +146,13 @@
SLAVIO_INTCTLState *s = opaque;
uint32_t saddr, ret;
- saddr = (addr & INTCTLM_MAXADDR) >> 2;
+ saddr = (addr & INTCTLM_MASK) >> 2;
switch (saddr) {
case 0:
ret = s->intregm_pending & ~MASTER_DISABLE;
break;
case 1:
- ret = s->intregm_disabled;
+ ret = s->intregm_disabled & MASTER_IRQ_MASK;
break;
case 4:
ret = s->target_cpu;
@@ -199,15 +200,15 @@
}
static CPUReadMemoryFunc *slavio_intctlm_mem_read[3] = {
+ NULL,
+ NULL,
slavio_intctlm_mem_readl,
- slavio_intctlm_mem_readl,
- slavio_intctlm_mem_readl,
};
static CPUWriteMemoryFunc *slavio_intctlm_mem_write[3] = {
+ NULL,
+ NULL,
slavio_intctlm_mem_writel,
- slavio_intctlm_mem_writel,
- slavio_intctlm_mem_writel,
};
void slavio_pic_info(void *opaque)
@@ -257,7 +258,7 @@
pil_pending |= 1 << s->intbit_to_level[j];
}
}
- pil_pending |= (s->intreg_pending[i] & CPU_IRQ_MASK) >> 16;
+ pil_pending |= (s->intreg_pending[i] & CPU_SOFTIRQ_MASK) >> 16;
for (j = 0; j < MAX_PILS; j++) {
if (pil_pending & (1 << j)) {
@@ -305,10 +306,13 @@
DPRINTF("Set cpu %d local timer level %d\n", cpu, level);
- if (level)
- s->intreg_pending[cpu] |= s->cputimer_bit;
- else
- s->intreg_pending[cpu] &= ~s->cputimer_bit;
+ if (level) {
+ s->intregm_pending |= s->cputimer_mbit;
+ s->intreg_pending[cpu] |= s->cputimer_lbit;
+ } else {
+ s->intregm_pending &= ~s->cputimer_mbit;
+ s->intreg_pending[cpu] &= ~s->cputimer_lbit;
+ }
slavio_check_interrupts(s);
}
@@ -386,7 +390,8 @@
*irq = qemu_allocate_irqs(slavio_set_irq, s, 32);
*cpu_irq = qemu_allocate_irqs(slavio_set_timer_irq_cpu, s, MAX_CPUS);
- s->cputimer_bit = 1 << s->intbit_to_level[cputimer];
+ s->cputimer_mbit = 1 << cputimer;
+ s->cputimer_lbit = 1 << intbit_to_level[cputimer];
slavio_intctl_reset(s);
return s;
}
Modified: trunk/src/host/qemu-neo1973/hw/slavio_misc.c
===================================================================
--- trunk/src/host/qemu-neo1973/hw/slavio_misc.c 2008-01-06 01:02:26 UTC (rev 3777)
+++ trunk/src/host/qemu-neo1973/hw/slavio_misc.c 2008-01-07 07:17:44 UTC (rev 3778)
@@ -191,14 +191,14 @@
static CPUReadMemoryFunc *slavio_misc_mem_read[3] = {
slavio_misc_mem_readb,
- slavio_misc_mem_readb,
- slavio_misc_mem_readb,
+ NULL,
+ NULL,
};
static CPUWriteMemoryFunc *slavio_misc_mem_write[3] = {
slavio_misc_mem_writeb,
- slavio_misc_mem_writeb,
- slavio_misc_mem_writeb,
+ NULL,
+ NULL,
};
static uint32_t slavio_sysctrl_mem_readl(void *opaque, target_phys_addr_t addr)
@@ -241,18 +241,18 @@
}
static CPUReadMemoryFunc *slavio_sysctrl_mem_read[3] = {
+ NULL,
+ NULL,
slavio_sysctrl_mem_readl,
- slavio_sysctrl_mem_readl,
- slavio_sysctrl_mem_readl,
};
static CPUWriteMemoryFunc *slavio_sysctrl_mem_write[3] = {
+ NULL,
+ NULL,
slavio_sysctrl_mem_writel,
- slavio_sysctrl_mem_writel,
- slavio_sysctrl_mem_writel,
};
-static uint32_t slavio_led_mem_reads(void *opaque, target_phys_addr_t addr)
+static uint32_t slavio_led_mem_readw(void *opaque, target_phys_addr_t addr)
{
MiscState *s = opaque;
uint32_t ret = 0, saddr;
@@ -270,7 +270,7 @@
return ret;
}
-static void slavio_led_mem_writes(void *opaque, target_phys_addr_t addr,
+static void slavio_led_mem_writew(void *opaque, target_phys_addr_t addr,
uint32_t val)
{
MiscState *s = opaque;
@@ -289,15 +289,15 @@
}
static CPUReadMemoryFunc *slavio_led_mem_read[3] = {
- slavio_led_mem_reads,
- slavio_led_mem_reads,
- slavio_led_mem_reads,
+ NULL,
+ slavio_led_mem_readw,
+ NULL,
};
static CPUWriteMemoryFunc *slavio_led_mem_write[3] = {
- slavio_led_mem_writes,
- slavio_led_mem_writes,
- slavio_led_mem_writes,
+ NULL,
+ slavio_led_mem_writew,
+ NULL,
};
static void slavio_misc_save(QEMUFile *f, void *opaque)
Modified: trunk/src/host/qemu-neo1973/hw/slavio_serial.c
===================================================================
--- trunk/src/host/qemu-neo1973/hw/slavio_serial.c 2008-01-06 01:02:26 UTC (rev 3777)
+++ trunk/src/host/qemu-neo1973/hw/slavio_serial.c 2008-01-07 07:17:44 UTC (rev 3778)
@@ -305,7 +305,7 @@
STATUS_CTS | STATUS_TXUNDRN;
else
s->rregs[R_STATUS] = STATUS_TXEMPTY | STATUS_TXUNDRN;
- s->rregs[R_SPEC] = SPEC_BITS8;
+ s->rregs[R_SPEC] = SPEC_BITS8 | SPEC_ALLSENT;
s->rx = s->tx = 0;
s->rxint = s->txint = 0;
@@ -641,14 +641,14 @@
static CPUReadMemoryFunc *slavio_serial_mem_read[3] = {
slavio_serial_mem_readb,
- slavio_serial_mem_readb,
- slavio_serial_mem_readb,
+ NULL,
+ NULL,
};
static CPUWriteMemoryFunc *slavio_serial_mem_write[3] = {
slavio_serial_mem_writeb,
- slavio_serial_mem_writeb,
- slavio_serial_mem_writeb,
+ NULL,
+ NULL,
};
static void slavio_serial_save_chn(QEMUFile *f, ChannelState *s)
Modified: trunk/src/host/qemu-neo1973/hw/slavio_timer.c
===================================================================
--- trunk/src/host/qemu-neo1973/hw/slavio_timer.c 2008-01-06 01:02:26 UTC (rev 3777)
+++ trunk/src/host/qemu-neo1973/hw/slavio_timer.c 2008-01-07 07:17:44 UTC (rev 3778)
@@ -104,7 +104,11 @@
else
limit = s->limit;
- count = limit - PERIODS_TO_LIMIT(ptimer_get_count(s->timer));
+ if (s->timer)
+ count = limit - PERIODS_TO_LIMIT(ptimer_get_count(s->timer));
+ else
+ count = 0;
+
DPRINTF("get_out: limit %" PRIx64 " count %x%08x\n", s->limit,
s->counthigh, s->count);
s->count = count & TIMER_COUNT_MASK32;
@@ -190,15 +194,18 @@
qemu_irq_lower(s->irq);
s->limit = TIMER_MAX_COUNT64;
DPRINTF("processor %d user timer reset\n", s->slave_index);
- ptimer_set_limit(s->timer, LIMIT_TO_PERIODS(s->limit), 1);
+ if (s->timer)
+ ptimer_set_limit(s->timer, LIMIT_TO_PERIODS(s->limit), 1);
} else {
// set limit, reset counter
qemu_irq_lower(s->irq);
s->limit = val & TIMER_MAX_COUNT32;
- if (s->limit == 0) /* free-run */
- ptimer_set_limit(s->timer, LIMIT_TO_PERIODS(TIMER_MAX_COUNT32), 1);
- else
- ptimer_set_limit(s->timer, LIMIT_TO_PERIODS(s->limit), 1);
+ if (s->timer) {
+ if (s->limit == 0) /* free-run */
+ ptimer_set_limit(s->timer, LIMIT_TO_PERIODS(TIMER_MAX_COUNT32), 1);
+ else
+ ptimer_set_limit(s->timer, LIMIT_TO_PERIODS(s->limit), 1);
+ }
}
break;
case TIMER_COUNTER:
@@ -207,28 +214,33 @@
qemu_irq_lower(s->irq);
s->limit = TIMER_MAX_COUNT64;
DPRINTF("processor %d user timer reset\n", s->slave_index);
- ptimer_set_limit(s->timer, LIMIT_TO_PERIODS(s->limit), 1);
+ if (s->timer)
+ ptimer_set_limit(s->timer, LIMIT_TO_PERIODS(s->limit), 1);
} else
DPRINTF("not user timer\n");
break;
case TIMER_COUNTER_NORST:
// set limit without resetting counter
s->limit = val & TIMER_MAX_COUNT32;
- if (s->limit == 0) /* free-run */
- ptimer_set_limit(s->timer, LIMIT_TO_PERIODS(TIMER_MAX_COUNT32), 0);
- else
- ptimer_set_limit(s->timer, LIMIT_TO_PERIODS(s->limit), 0);
+ if (s->timer) {
+ if (s->limit == 0) /* free-run */
+ ptimer_set_limit(s->timer, LIMIT_TO_PERIODS(TIMER_MAX_COUNT32), 0);
+ else
+ ptimer_set_limit(s->timer, LIMIT_TO_PERIODS(s->limit), 0);
+ }
break;
case TIMER_STATUS:
if (slavio_timer_is_user(s)) {
// start/stop user counter
if ((val & 1) && !s->running) {
DPRINTF("processor %d user timer started\n", s->slave_index);
- ptimer_run(s->timer, 0);
+ if (s->timer)
+ ptimer_run(s->timer, 0);
s->running = 1;
} else if (!(val & 1) && s->running) {
DPRINTF("processor %d user timer stopped\n", s->slave_index);
- ptimer_stop(s->timer);
+ if (s->timer)
+ ptimer_stop(s->timer);
s->running = 0;
}
}
@@ -241,6 +253,8 @@
if (val & (1 << i)) {
qemu_irq_lower(s->slave[i]->irq);
s->slave[i]->limit = -1ULL;
+ } else {
+ ptimer_stop(s->slave[i]->timer);
}
if ((val & (1 << i)) != (s->slave_mode & (1 << i))) {
ptimer_stop(s->slave[i]->timer);
@@ -262,15 +276,15 @@
}
static CPUReadMemoryFunc *slavio_timer_mem_read[3] = {
+ NULL,
+ NULL,
slavio_timer_mem_readl,
- slavio_timer_mem_readl,
- slavio_timer_mem_readl,
};
static CPUWriteMemoryFunc *slavio_timer_mem_write[3] = {
+ NULL,
+ NULL,
slavio_timer_mem_writel,
- slavio_timer_mem_writel,
- slavio_timer_mem_writel,
};
static void slavio_timer_save(QEMUFile *f, void *opaque)
@@ -280,29 +294,26 @@
qemu_put_be64s(f, &s->limit);
qemu_put_be32s(f, &s->count);
qemu_put_be32s(f, &s->counthigh);
- qemu_put_be32(f, 0); // Was irq
qemu_put_be32s(f, &s->reached);
qemu_put_be32s(f, &s->running);
- qemu_put_be32s(f, 0); // Was mode
- qemu_put_ptimer(f, s->timer);
+ if (s->timer)
+ qemu_put_ptimer(f, s->timer);
}
static int slavio_timer_load(QEMUFile *f, void *opaque, int version_id)
{
SLAVIO_TIMERState *s = opaque;
- uint32_t tmp;
- if (version_id != 2)
+ if (version_id != 3)
return -EINVAL;
qemu_get_be64s(f, &s->limit);
qemu_get_be32s(f, &s->count);
qemu_get_be32s(f, &s->counthigh);
- qemu_get_be32s(f, &tmp); // Was irq
qemu_get_be32s(f, &s->reached);
qemu_get_be32s(f, &s->running);
- qemu_get_be32s(f, &tmp); // Was mode
- qemu_get_ptimer(f, s->timer);
+ if (s->timer)
+ qemu_get_ptimer(f, s->timer);
return 0;
}
@@ -315,8 +326,10 @@
s->count = 0;
s->reached = 0;
s->slave_mode = 0;
- ptimer_set_limit(s->timer, LIMIT_TO_PERIODS(TIMER_MAX_COUNT32), 1);
- ptimer_run(s->timer, 0);
+ if (!s->master || s->slave_index < s->master->num_slaves) {
+ ptimer_set_limit(s->timer, LIMIT_TO_PERIODS(TIMER_MAX_COUNT32), 1);
+ ptimer_run(s->timer, 0);
+ }
s->running = 1;
qemu_irq_lower(s->irq);
}
@@ -336,9 +349,11 @@
s->irq = irq;
s->master = master;
s->slave_index = slave_index;
- bh = qemu_bh_new(slavio_timer_irq, s);
- s->timer = ptimer_init(bh);
- ptimer_set_period(s->timer, TIMER_PERIOD);
+ if (!master || slave_index < master->num_slaves) {
+ bh = qemu_bh_new(slavio_timer_irq, s);
+ s->timer = ptimer_init(bh);
+ ptimer_set_period(s->timer, TIMER_PERIOD);
+ }
slavio_timer_io_memory = cpu_register_io_memory(0, slavio_timer_mem_read,
slavio_timer_mem_write, s);
@@ -348,7 +363,7 @@
else
cpu_register_physical_memory(addr, SYS_TIMER_SIZE,
slavio_timer_io_memory);
- register_savevm("slavio_timer", addr, 2, slavio_timer_save,
+ register_savevm("slavio_timer", addr, 3, slavio_timer_save,
slavio_timer_load, s);
qemu_register_reset(slavio_timer_reset, s);
slavio_timer_reset(s);
Modified: trunk/src/host/qemu-neo1973/hw/sparc32_dma.c
===================================================================
--- trunk/src/host/qemu-neo1973/hw/sparc32_dma.c 2008-01-06 01:02:26 UTC (rev 3777)
+++ trunk/src/host/qemu-neo1973/hw/sparc32_dma.c 2008-01-07 07:17:44 UTC (rev 3778)
@@ -198,15 +198,15 @@
}
static CPUReadMemoryFunc *dma_mem_read[3] = {
+ NULL,
+ NULL,
dma_mem_readl,
- dma_mem_readl,
- dma_mem_readl,
};
static CPUWriteMemoryFunc *dma_mem_write[3] = {
+ NULL,
+ NULL,
dma_mem_writel,
- dma_mem_writel,
- dma_mem_writel,
};
static void dma_reset(void *opaque)
Added: trunk/src/host/qemu-neo1973/hw/sun4c_intctl.c
===================================================================
--- trunk/src/host/qemu-neo1973/hw/sun4c_intctl.c 2008-01-06 01:02:26 UTC (rev 3777)
+++ trunk/src/host/qemu-neo1973/hw/sun4c_intctl.c 2008-01-07 07:17:44 UTC (rev 3778)
@@ -0,0 +1,223 @@
+/*
+ * QEMU Sparc Sun4c interrupt controller emulation
+ *
+ * Based on slavio_intctl, copyright (c) 2003-2005 Fabrice Bellard
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+#include "hw.h"
+#include "sun4m.h"
+#include "console.h"
+//#define DEBUG_IRQ_COUNT
+//#define DEBUG_IRQ
+
+#ifdef DEBUG_IRQ
+#define DPRINTF(fmt, args...) \
+do { printf("IRQ: " fmt , ##args); } while (0)
+#else
+#define DPRINTF(fmt, args...)
+#endif
+
+/*
+ * Registers of interrupt controller in sun4c.
+ *
+ */
+
+#define MAX_PILS 16
+
+typedef struct Sun4c_INTCTLState {
+#ifdef DEBUG_IRQ_COUNT
+ uint64_t irq_count;
+#endif
+ qemu_irq *cpu_irqs;
+ const uint32_t *intbit_to_level;
+ uint32_t pil_out;
+ uint8_t reg;
+ uint8_t pending;
+} Sun4c_INTCTLState;
+
+#define INTCTL_MAXADDR 0
+#define INTCTL_SIZE (INTCTL_MAXADDR + 1)
+
+static void sun4c_check_interrupts(void *opaque);
+
+static uint32_t sun4c_intctl_mem_readb(void *opaque, target_phys_addr_t addr)
+{
+ Sun4c_INTCTLState *s = opaque;
+ uint32_t ret;
+
+ ret = s->reg;
+ DPRINTF("read reg 0x" TARGET_FMT_plx " = %x\n", addr, ret);
+
+ return ret;
+}
+
+static void sun4c_intctl_mem_writeb(void *opaque, target_phys_addr_t addr, uint32_t val)
+{
+ Sun4c_INTCTLState *s = opaque;
+
+ DPRINTF("write reg 0x" TARGET_FMT_plx " = %x\n", addr, val);
+ val &= 0xbf;
+ s->reg = val;
+ sun4c_check_interrupts(s);
+}
+
+static CPUReadMemoryFunc *sun4c_intctl_mem_read[3] = {
+ sun4c_intctl_mem_readb,
+ NULL,
+ NULL,
+};
+
+static CPUWriteMemoryFunc *sun4c_intctl_mem_write[3] = {
+ sun4c_intctl_mem_writeb,
+ NULL,
+ NULL,
+};
+
+void sun4c_pic_info(void *opaque)
+{
+ Sun4c_INTCTLState *s = opaque;
+
+ term_printf("master: pending 0x%2.2x, enabled 0x%2.2x\n", s->pending, s->reg);
+}
+
+void sun4c_irq_info(void *opaque)
+{
+#ifndef DEBUG_IRQ_COUNT
+ term_printf("irq statistic code not compiled.\n");
+#else
+ Sun4c_INTCTLState *s = opaque;
+ int64_t count;
+
+ term_printf("IRQ statistics:\n");
+ count = s->irq_count[i];
+ if (count > 0)
+ term_printf("%2d: %" PRId64 "\n", i, count);
+#endif
+}
+
+static const uint32_t intbit_to_level[] = { 0, 1, 4, 6, 8, 10, 0, 14, };
+
+static void sun4c_check_interrupts(void *opaque)
+{
+ Sun4c_INTCTLState *s = opaque;
+ uint32_t pil_pending;
+ unsigned int i;
+
+ DPRINTF("pending %x disabled %x\n", pending, s->intregm_disabled);
+ pil_pending = 0;
+ if (s->pending && !(s->reg & 0x80000000)) {
+ for (i = 0; i < 8; i++) {
+ if (s->pending & (1 << i))
+ pil_pending |= 1 << intbit_to_level[i];
+ }
+ }
+
+ for (i = 0; i < MAX_PILS; i++) {
+ if (pil_pending & (1 << i)) {
+ if (!(s->pil_out & (1 << i)))
+ qemu_irq_raise(s->cpu_irqs[i]);
+ } else {
+ if (s->pil_out & (1 << i))
+ qemu_irq_lower(s->cpu_irqs[i]);
+ }
+ }
+ s->pil_out = pil_pending;
+}
+
+/*
+ * "irq" here is the bit number in the system interrupt register
+ */
+static void sun4c_set_irq(void *opaque, int irq, int level)
+{
+ Sun4c_INTCTLState *s = opaque;
+ uint32_t mask = 1 << irq;
+ uint32_t pil = intbit_to_level[irq];
+
+ DPRINTF("Set irq %d -> pil %d level %d\n", irq, pil,
+ level);
+ if (pil > 0) {
+ if (level) {
+#ifdef DEBUG_IRQ_COUNT
+ s->irq_count[pil]++;
+#endif
+ s->pending |= mask;
+ } else {
+ s->pending &= ~mask;
+ }
+ sun4c_check_interrupts(s);
+ }
+}
+
+static void sun4c_intctl_save(QEMUFile *f, void *opaque)
+{
+ Sun4c_INTCTLState *s = opaque;
+
+ qemu_put_8s(f, &s->reg);
+ qemu_put_8s(f, &s->pending);
+}
+
+static int sun4c_intctl_load(QEMUFile *f, void *opaque, int version_id)
+{
+ Sun4c_INTCTLState *s = opaque;
+
+ if (version_id != 1)
+ return -EINVAL;
+
+ qemu_get_8s(f, &s->reg);
+ qemu_get_8s(f, &s->pending);
+ sun4c_check_interrupts(s);
+
+ return 0;
+}
+
+static void sun4c_intctl_reset(void *opaque)
+{
+ Sun4c_INTCTLState *s = opaque;
+
+ s->reg = 1;
+ s->pending = 0;
+ sun4c_check_interrupts(s);
+}
+
+void *sun4c_intctl_init(target_phys_addr_t addr, qemu_irq **irq,
+ qemu_irq *parent_irq)
+{
+ int sun4c_intctl_io_memory;
+ Sun4c_INTCTLState *s;
+
+ s = qemu_mallocz(sizeof(Sun4c_INTCTLState));
+ if (!s)
+ return NULL;
+
+ sun4c_intctl_io_memory = cpu_register_io_memory(0, sun4c_intctl_mem_read,
+ sun4c_intctl_mem_write, s);
+ cpu_register_physical_memory(addr, INTCTL_SIZE, sun4c_intctl_io_memory);
+ s->cpu_irqs = parent_irq;
+
+ register_savevm("sun4c_intctl", addr, 1, sun4c_intctl_save,
+ sun4c_intctl_load, s);
+
+ qemu_register_reset(sun4c_intctl_reset, s);
+ *irq = qemu_allocate_irqs(sun4c_set_irq, s, 8);
+
+ sun4c_intctl_reset(s);
+ return s;
+}
+
Modified: trunk/src/host/qemu-neo1973/hw/sun4m.c
===================================================================
--- trunk/src/host/qemu-neo1973/hw/sun4m.c 2008-01-06 01:02:26 UTC (rev 3777)
+++ trunk/src/host/qemu-neo1973/hw/sun4m.c 2008-01-07 07:17:44 UTC (rev 3778)
@@ -1,5 +1,5 @@
/*
- * QEMU Sun4m System Emulator
+ * QEMU Sun4m & Sun4d & Sun4c System Emulator
*
* Copyright (c) 2003-2005 Fabrice Bellard
*
@@ -46,6 +46,18 @@
* SPARCstation 20/xx, SPARCserver 20
* SPARCstation 4
*
+ * Sun4d architecture was used in the following machines:
+ *
+ * SPARCcenter 2000
+ * SPARCserver 1000
+ *
+ * Sun4c architecture was used in the following machines:
+ * SPARCstation 1/1+, SPARCserver 1/1+
+ * SPARCstation SLC
+ * SPARCstation IPC
+ * SPARCstation ELC
+ * SPARCstation IPX
+ *
* See for example: http://www.sunhelp.org/faq/sunref1.html
*/
@@ -70,13 +82,14 @@
target_phys_addr_t iommu_base, slavio_base;
target_phys_addr_t intctl_base, counter_base, nvram_base, ms_kb_base;
target_phys_addr_t serial_base, fd_base;
- target_phys_addr_t dma_base, esp_base, le_base;
+ target_phys_addr_t idreg_base, dma_base, esp_base, le_base;
target_phys_addr_t tcx_base, cs_base, power_base;
target_phys_addr_t ecc_base;
uint32_t ecc_version;
+ target_phys_addr_t sun4c_intctl_base, sun4c_counter_base;
long vram_size, nvram_size;
- // IRQ numbers are not PIL ones, but master interrupt controller register
- // bit numbers
+ // IRQ numbers are not PIL ones, but master interrupt controller
+ // register bit numbers
int intctl_g_intr, esp_irq, le_irq, clock_irq, clock1_irq;
int ser_irq, ms_kb_irq, fd_irq, me_irq, cs_irq;
int machine_id; // For NVRAM
@@ -86,6 +99,26 @@
const char * const default_cpu_model;
};
+#define MAX_IOUNITS 5
+
+struct sun4d_hwdef {
+ target_phys_addr_t iounit_bases[MAX_IOUNITS], slavio_base;
+ target_phys_addr_t counter_base, nvram_base, ms_kb_base;
+ target_phys_addr_t serial_base;
+ target_phys_addr_t espdma_base, esp_base;
+ target_phys_addr_t ledma_base, le_base;
+ target_phys_addr_t tcx_base;
+ target_phys_addr_t sbi_base;
+ unsigned long vram_size, nvram_size;
+ // IRQ numbers are not PIL ones, but SBI register bit numbers
+ int esp_irq, le_irq, clock_irq, clock1_irq;
+ int ser_irq, ms_kb_irq, me_irq;
+ int machine_id; // For NVRAM
+ uint32_t iounit_version;
+ uint64_t max_mem;
+ const char * const default_cpu_model;
+};
+
/* TSC handling */
uint64_t cpu_get_tsc()
@@ -122,7 +155,7 @@
const char *boot_devices, uint32_t RAM_size,
uint32_t kernel_size,
int width, int height, int depth,
- int machine_id)
+ int machine_id, const char *arch)
{
unsigned int i;
uint32_t start, end;
@@ -140,7 +173,7 @@
header->nvram_size = cpu_to_be16(0x2000);
header->nvram_arch_ptr = cpu_to_be16(sizeof(ohwcfg_v3_t));
header->nvram_arch_size = cpu_to_be16(sizeof(struct sparc_arch_cfg));
- strcpy(header->arch, "sun4m");
+ strcpy(header->arch, arch);
header->nb_cpus = smp_cpus & 0xff;
header->RAM0_base = 0;
header->RAM0_size = cpu_to_be64((uint64_t)RAM_size);
@@ -203,12 +236,14 @@
void pic_info()
{
- slavio_pic_info(slavio_intctl);
+ if (slavio_intctl)
+ slavio_pic_info(slavio_intctl);
}
void irq_info()
{
- slavio_irq_info(slavio_intctl);
+ if (slavio_intctl)
+ slavio_irq_info(slavio_intctl);
}
void cpu_check_irqs(CPUState *env)
@@ -350,7 +385,7 @@
for(i = 0; i < smp_cpus; i++) {
env = cpu_init(cpu_model);
if (!env) {
- fprintf(stderr, "Unable to find Sparc CPU definition\n");
+ fprintf(stderr, "qemu: Unable to find Sparc CPU definition\n");
exit(1);
}
cpu_sparc_set_id(env, i);
@@ -397,9 +432,9 @@
buf);
exit(1);
}
+ prom_offset += (ret + TARGET_PAGE_SIZE - 1) & TARGET_PAGE_MASK;
/* set up devices */
- iommu = iommu_init(hwdef->iommu_base, hwdef->iommu_version);
slavio_intctl = slavio_intctl_init(hwdef->intctl_base,
hwdef->intctl_base + 0x10000ULL,
&hwdef->intbit_to_level[0],
@@ -407,6 +442,16 @@
cpu_irqs,
hwdef->clock_irq);
+ if (hwdef->idreg_base != (target_phys_addr_t)-1) {
+ stl_raw(phys_ram_base + prom_offset, 0xfe810103);
+
+ cpu_register_physical_memory(hwdef->idreg_base, sizeof(uint32_t),
+ prom_offset | IO_MEM_ROM);
+ }
+
+ iommu = iommu_init(hwdef->iommu_base, hwdef->iommu_version,
+ slavio_irq[hwdef->me_irq]);
+
espdma = sparc32_dma_init(hwdef->dma_base, slavio_irq[hwdef->esp_irq],
iommu, &espdma_irq, &esp_reset);
@@ -480,12 +525,150 @@
nvram_init(nvram, (uint8_t *)&nd_table[0].macaddr, kernel_cmdline,
boot_device, RAM_size, kernel_size, graphic_width,
- graphic_height, graphic_depth, hwdef->machine_id);
+ graphic_height, graphic_depth, hwdef->machine_id, "Sun4m");
if (hwdef->ecc_base != (target_phys_addr_t)-1)
ecc_init(hwdef->ecc_base, hwdef->ecc_version);
}
+static void sun4c_hw_init(const struct hwdef *hwdef, int RAM_size,
+ const char *boot_device,
+ DisplayState *ds, const char *kernel_filename,
+ const char *kernel_cmdline,
+ const char *initrd_filename, const char *cpu_model)
+{
+ CPUState *env;
+ unsigned int i;
+ void *iommu, *espdma, *ledma, *main_esp, *nvram;
+ qemu_irq *cpu_irqs, *slavio_irq, *espdma_irq, *ledma_irq;
+ qemu_irq *esp_reset, *le_reset;
+ unsigned long prom_offset, kernel_size;
+ int ret;
+ char buf[1024];
+ BlockDriverState *fd[MAX_FD];
+ int index;
+
+ /* init CPU */
+ if (!cpu_model)
+ cpu_model = hwdef->default_cpu_model;
+
+ env = cpu_init(cpu_model);
+ if (!env) {
+ fprintf(stderr, "qemu: Unable to find Sparc CPU definition\n");
+ exit(1);
+ }
+
+ cpu_sparc_set_id(env, 0);
+
+ qemu_register_reset(main_cpu_reset, env);
+ register_savevm("cpu", 0, 3, cpu_save, cpu_load, env);
+ cpu_irqs = qemu_allocate_irqs(cpu_set_irq, env, MAX_PILS);
+ env->prom_addr = hwdef->slavio_base;
+
+ /* allocate RAM */
+ if ((uint64_t)RAM_size > hwdef->max_mem) {
+ fprintf(stderr, "qemu: Too much memory for this machine: %d, maximum %d\n",
+ (unsigned int)RAM_size / (1024 * 1024),
+ (unsigned int)hwdef->max_mem / (1024 * 1024));
+ exit(1);
+ }
+ cpu_register_physical_memory(0, RAM_size, 0);
+
+ /* load boot prom */
+ prom_offset = RAM_size + hwdef->vram_size;
+ cpu_register_physical_memory(hwdef->slavio_base,
+ (PROM_SIZE_MAX + TARGET_PAGE_SIZE - 1) &
+ TARGET_PAGE_MASK,
+ prom_offset | IO_MEM_ROM);
+
+ if (bios_name == NULL)
+ bios_name = PROM_FILENAME;
+ snprintf(buf, sizeof(buf), "%s/%s", bios_dir, bios_name);
+ ret = load_elf(buf, hwdef->slavio_base - PROM_VADDR, NULL, NULL, NULL);
+ if (ret < 0 || ret > PROM_SIZE_MAX)
+ ret = load_image(buf, phys_ram_base + prom_offset);
+ if (ret < 0 || ret > PROM_SIZE_MAX) {
+ fprintf(stderr, "qemu: could not load prom '%s'\n",
+ buf);
+ exit(1);
+ }
+ prom_offset += (ret + TARGET_PAGE_SIZE - 1) & TARGET_PAGE_MASK;
+
+ /* set up devices */
+ slavio_intctl = sun4c_intctl_init(hwdef->sun4c_intctl_base,
+ &slavio_irq, cpu_irqs);
+
+ iommu = iommu_init(hwdef->iommu_base, hwdef->iommu_version,
+ slavio_irq[hwdef->me_irq]);
+
+ espdma = sparc32_dma_init(hwdef->dma_base, slavio_irq[hwdef->esp_irq],
+ iommu, &espdma_irq, &esp_reset);
+
+ ledma = sparc32_dma_init(hwdef->dma_base + 16ULL,
+ slavio_irq[hwdef->le_irq], iommu, &ledma_irq,
+ &le_reset);
+
+ if (graphic_depth != 8 && graphic_depth != 24) {
+ fprintf(stderr, "qemu: Unsupported depth: %d\n", graphic_depth);
+ exit (1);
+ }
+ tcx_init(ds, hwdef->tcx_base, phys_ram_base + RAM_size, RAM_size,
+ hwdef->vram_size, graphic_width, graphic_height, graphic_depth);
+
+ if (nd_table[0].model == NULL
+ || strcmp(nd_table[0].model, "lance") == 0) {
+ lance_init(&nd_table[0], hwdef->le_base, ledma, *ledma_irq, le_reset);
+ } else if (strcmp(nd_table[0].model, "?") == 0) {
+ fprintf(stderr, "qemu: Supported NICs: lance\n");
+ exit (1);
+ } else {
+ fprintf(stderr, "qemu: Unsupported NIC: %s\n", nd_table[0].model);
+ exit (1);
+ }
+
+ nvram = m48t59_init(slavio_irq[0], hwdef->nvram_base, 0,
+ hwdef->nvram_size, 2);
+
+ slavio_serial_ms_kbd_init(hwdef->ms_kb_base, slavio_irq[hwdef->ms_kb_irq],
+ nographic);
+ // Slavio TTYA (base+4, Linux ttyS0) is the first Qemu serial device
+ // Slavio TTYB (base+0, Linux ttyS1) is the second Qemu serial device
+ slavio_serial_init(hwdef->serial_base, slavio_irq[hwdef->ser_irq],
+ serial_hds[1], serial_hds[0]);
+
+ if (hwdef->fd_base != (target_phys_addr_t)-1) {
+ /* there is zero or one floppy drive */
+ fd[1] = fd[0] = NULL;
+ index = drive_get_index(IF_FLOPPY, 0, 0);
+ if (index != -1)
+ fd[0] = drives_table[index].bdrv;
+
+ sun4m_fdctrl_init(slavio_irq[hwdef->fd_irq], hwdef->fd_base, fd);
+ }
+
+ if (drive_get_max_bus(IF_SCSI) > 0) {
+ fprintf(stderr, "qemu: too many SCSI bus\n");
+ exit(1);
+ }
+
+ main_esp = esp_init(hwdef->esp_base, espdma, *espdma_irq,
+ esp_reset);
+
+ for (i = 0; i < ESP_MAX_DEVS; i++) {
+ index = drive_get_index(IF_SCSI, 0, i);
+ if (index == -1)
+ continue;
+ esp_scsi_attach(main_esp, drives_table[index].bdrv, i);
+ }
+
+ kernel_size = sun4m_load_kernel(kernel_filename, kernel_cmdline,
+ initrd_filename);
+
+ nvram_init(nvram, (uint8_t *)&nd_table[0].macaddr, kernel_cmdline,
+ boot_device, RAM_size, kernel_size, graphic_width,
+ graphic_height, graphic_depth, hwdef->machine_id, "Sun4c");
+}
+
static const struct hwdef hwdefs[] = {
/* SS-5 */
{
@@ -499,11 +682,14 @@
.fd_base = 0x71400000,
.counter_base = 0x71d00000,
.intctl_base = 0x71e00000,
+ .idreg_base = 0x78000000,
.dma_base = 0x78400000,
.esp_base = 0x78800000,
.le_base = 0x78c00000,
.power_base = 0x7a000000,
.ecc_base = -1,
+ .sun4c_intctl_base = -1,
+ .sun4c_counter_base = -1,
.vram_size = 0x00100000,
.nvram_size = 0x2000,
.esp_irq = 18,
@@ -516,7 +702,7 @@
.me_irq = 30,
.cs_irq = 5,
.machine_id = 0x80,
- .iommu_version = 0x04000000,
+ .iommu_version = 0x05000000,
.intbit_to_level = {
2, 3, 5, 7, 9, 11, 0, 14, 3, 5, 7, 9, 11, 13, 12, 12,
6, 0, 4, 10, 8, 0, 11, 0, 0, 0, 0, 0, 15, 0, 15, 0,
@@ -536,12 +722,15 @@
.fd_base = 0xff1700000ULL,
.counter_base = 0xff1300000ULL,
.intctl_base = 0xff1400000ULL,
+ .idreg_base = 0xef0000000ULL,
.dma_base = 0xef0400000ULL,
.esp_base = 0xef0800000ULL,
.le_base = 0xef0c00000ULL,
.power_base = 0xefa000000ULL,
.ecc_base = 0xf00000000ULL,
.ecc_version = 0x10000000, // version 0, implementation 1
+ .sun4c_intctl_base = -1,
+ .sun4c_counter_base = -1,
.vram_size = 0x00100000,
.nvram_size = 0x2000,
.esp_irq = 18,
@@ -574,12 +763,15 @@
.fd_base = -1,
.counter_base = 0xff1300000ULL,
.intctl_base = 0xff1400000ULL,
+ .idreg_base = -1,
.dma_base = 0xef0081000ULL,
.esp_base = 0xef0080000ULL,
.le_base = 0xef0060000ULL,
.power_base = 0xefa000000ULL,
.ecc_base = 0xf00000000ULL,
.ecc_version = 0x00000000, // version 0, implementation 0
+ .sun4c_intctl_base = -1,
+ .sun4c_counter_base = -1,
.vram_size = 0x00100000,
.nvram_size = 0x2000,
.esp_irq = 18,
@@ -612,12 +804,15 @@
.fd_base = 0xff1700000ULL,
.counter_base = 0xff1300000ULL,
.intctl_base = 0xff1400000ULL,
+ .idreg_base = 0xef0000000ULL,
.dma_base = 0xef0400000ULL,
.esp_base = 0xef0800000ULL,
.le_base = 0xef0c00000ULL,
.power_base = 0xefa000000ULL,
.ecc_base = 0xf00000000ULL,
.ecc_version = 0x20000000, // version 0, implementation 2
+ .sun4c_intctl_base = -1,
+ .sun4c_counter_base = -1,
.vram_size = 0x00100000,
.nvram_size = 0x2000,
.esp_irq = 18,
@@ -638,6 +833,39 @@
.max_mem = 0xffffffff, // XXX actually first 62GB ok
.default_cpu_model = "TI SuperSparc II",
},
+ /* SS-2 */
+ {
+ .iommu_base = 0xf8000000,
+ .tcx_base = 0xfe000000,
+ .cs_base = -1,
+ .slavio_base = 0xf6000000,
+ .ms_kb_base = 0xf0000000,
+ .serial_base = 0xf1000000,
+ .nvram_base = 0xf2000000,
+ .fd_base = 0xf7200000,
+ .counter_base = -1,
+ .intctl_base = -1,
+ .dma_base = 0xf8400000,
+ .esp_base = 0xf8800000,
+ .le_base = 0xf8c00000,
+ .power_base = -1,
+ .sun4c_intctl_base = 0xf5000000,
+ .sun4c_counter_base = 0xf3000000,
+ .vram_size = 0x00100000,
+ .nvram_size = 0x800,
+ .esp_irq = 2,
+ .le_irq = 3,
+ .clock_irq = 5,
+ .clock1_irq = 7,
+ .ms_kb_irq = 1,
+ .ser_irq = 1,
+ .fd_irq = 1,
+ .me_irq = 1,
+ .cs_irq = -1,
+ .machine_id = 0x55,
+ .max_mem = 0x10000000,
+ .default_cpu_model = "Cypress CY7C601",
+ },
};
/* SPARCstation 5 hardware initialisation */
@@ -680,6 +908,16 @@
kernel_cmdline, initrd_filename, cpu_model);
}
+/* SPARCstation 2 hardware initialisation */
+static void ss2_init(int RAM_size, int vga_ram_size,
+ const char *boot_device, DisplayState *ds,
+ const char *kernel_filename, const char *kernel_cmdline,
+ const char *initrd_filename, const char *cpu_model)
+{
+ sun4c_hw_init(&hwdefs[4], RAM_size, boot_device, ds, kernel_filename,
+ kernel_cmdline, initrd_filename, cpu_model);
+}
+
QEMUMachine ss5_machine = {
"SS-5",
"Sun4m platform, SPARCstation 5",
@@ -704,3 +942,249 @@
ss20_init,
};
+QEMUMachine ss2_machine = {
+ "SS-2",
+ "Sun4c platform, SPARCstation 2",
+ ss2_init,
+};
+
+static const struct sun4d_hwdef sun4d_hwdefs[] = {
+ /* SS-1000 */
+ {
+ .iounit_bases = {
+ 0xfe0200000ULL,
+ 0xfe1200000ULL,
+ 0xfe2200000ULL,
+ 0xfe3200000ULL,
+ -1,
+ },
+ .tcx_base = 0x820000000ULL,
+ .slavio_base = 0xf00000000ULL,
+ .ms_kb_base = 0xf00240000ULL,
+ .serial_base = 0xf00200000ULL,
+ .nvram_base = 0xf00280000ULL,
+ .counter_base = 0xf00300000ULL,
+ .espdma_base = 0x800081000ULL,
+ .esp_base = 0x800080000ULL,
+ .ledma_base = 0x800040000ULL,
+ .le_base = 0x800060000ULL,
+ .sbi_base = 0xf02800000ULL,
+ .vram_size = 0x00100000,
+ .nvram_size = 0x2000,
+ .esp_irq = 3,
+ .le_irq = 4,
+ .clock_irq = 14,
+ .clock1_irq = 10,
+ .ms_kb_irq = 12,
+ .ser_irq = 12,
+ .machine_id = 0x80,
+ .iounit_version = 0x03000000,
+ .max_mem = 0xffffffff, // XXX actually first 62GB ok
+ .default_cpu_model = "TI SuperSparc II",
+ },
+ /* SS-2000 */
+ {
+ .iounit_bases = {
+ 0xfe0200000ULL,
+ 0xfe1200000ULL,
+ 0xfe2200000ULL,
+ 0xfe3200000ULL,
+ 0xfe4200000ULL,
+ },
+ .tcx_base = 0x820000000ULL,
+ .slavio_base = 0xf00000000ULL,
+ .ms_kb_base = 0xf00240000ULL,
+ .serial_base = 0xf00200000ULL,
+ .nvram_base = 0xf00280000ULL,
+ .counter_base = 0xf00300000ULL,
+ .espdma_base = 0x800081000ULL,
+ .esp_base = 0x800080000ULL,
+ .ledma_base = 0x800040000ULL,
+ .le_base = 0x800060000ULL,
+ .sbi_base = 0xf02800000ULL,
+ .vram_size = 0x00100000,
+ .nvram_size = 0x2000,
+ .esp_irq = 3,
+ .le_irq = 4,
+ .clock_irq = 14,
+ .clock1_irq = 10,
+ .ms_kb_irq = 12,
+ .ser_irq = 12,
+ .machine_id = 0x80,
+ .iounit_version = 0x03000000,
+ .max_mem = 0xffffffff, // XXX actually first 62GB ok
+ .default_cpu_model = "TI SuperSparc II",
+ },
+};
+
+static void sun4d_hw_init(const struct sun4d_hwdef *hwdef, int RAM_size,
+ const char *boot_device,
+ DisplayState *ds, const char *kernel_filename,
+ const char *kernel_cmdline,
+ const char *initrd_filename, const char *cpu_model)
+{
+ CPUState *env, *envs[MAX_CPUS];
+ unsigned int i;
+ void *iounits[MAX_IOUNITS], *espdma, *ledma, *main_esp, *nvram, *sbi;
+ qemu_irq *cpu_irqs[MAX_CPUS], *sbi_irq, *sbi_cpu_irq,
+ *espdma_irq, *ledma_irq;
+ qemu_irq *esp_reset, *le_reset;
+ unsigned long prom_offset, kernel_size;
+ int ret;
+ char buf[1024];
+ int index;
+
+ /* init CPUs */
+ if (!cpu_model)
+ cpu_model = hwdef->default_cpu_model;
+
+ for (i = 0; i < smp_cpus; i++) {
+ env = cpu_init(cpu_model);
+ if (!env) {
+ fprintf(stderr, "qemu: Unable to find Sparc CPU definition\n");
+ exit(1);
+ }
+ cpu_sparc_set_id(env, i);
+ envs[i] = env;
+ if (i == 0) {
+ qemu_register_reset(main_cpu_reset, env);
+ } else {
+ qemu_register_reset(secondary_cpu_reset, env);
+ env->halted = 1;
+ }
+ register_savevm("cpu", i, 3, cpu_save, cpu_load, env);
+ cpu_irqs[i] = qemu_allocate_irqs(cpu_set_irq, envs[i], MAX_PILS);
+ env->prom_addr = hwdef->slavio_base;
+ }
+
+ for (i = smp_cpus; i < MAX_CPUS; i++)
+ cpu_irqs[i] = qemu_allocate_irqs(dummy_cpu_set_irq, NULL, MAX_PILS);
+
+ /* allocate RAM */
+ if ((uint64_t)RAM_size > hwdef->max_mem) {
+ fprintf(stderr, "qemu: Too much memory for this machine: %d, maximum %d\n",
+ (unsigned int)RAM_size / (1024 * 1024),
+ (unsigned int)(hwdef->max_mem / (1024 * 1024)));
+ exit(1);
+ }
+ cpu_register_physical_memory(0, RAM_size, 0);
+
+ /* load boot prom */
+ prom_offset = RAM_size + hwdef->vram_size;
+ cpu_register_physical_memory(hwdef->slavio_base,
+ (PROM_SIZE_MAX + TARGET_PAGE_SIZE - 1) &
+ TARGET_PAGE_MASK,
+ prom_offset | IO_MEM_ROM);
+
+ if (bios_name == NULL)
+ bios_name = PROM_FILENAME;
+ snprintf(buf, sizeof(buf), "%s/%s", bios_dir, bios_name);
+ ret = load_elf(buf, hwdef->slavio_base - PROM_VADDR, NULL, NULL, NULL);
+ if (ret < 0 || ret > PROM_SIZE_MAX)
+ ret = load_image(buf, phys_ram_base + prom_offset);
+ if (ret < 0 || ret > PROM_SIZE_MAX) {
+ fprintf(stderr, "qemu: could not load prom '%s'\n",
+ buf);
+ exit(1);
+ }
+
+ /* set up devices */
+ sbi = sbi_init(hwdef->sbi_base, &sbi_irq, &sbi_cpu_irq, cpu_irqs);
+
+ for (i = 0; i < MAX_IOUNITS; i++)
+ if (hwdef->iounit_bases[i] != (target_phys_addr_t)-1)
+ iounits[i] = iommu_init(hwdef->iounit_bases[i],
+ hwdef->iounit_version,
+ sbi_irq[hwdef->me_irq]);
+
+ espdma = sparc32_dma_init(hwdef->espdma_base, sbi_irq[hwdef->esp_irq],
+ iounits[0], &espdma_irq, &esp_reset);
+
+ ledma = sparc32_dma_init(hwdef->ledma_base, sbi_irq[hwdef->le_irq],
+ iounits[0], &ledma_irq, &le_reset);
+
+ if (graphic_depth != 8 && graphic_depth != 24) {
+ fprintf(stderr, "qemu: Unsupported depth: %d\n", graphic_depth);
+ exit (1);
+ }
+ tcx_init(ds, hwdef->tcx_base, phys_ram_base + RAM_size, RAM_size,
+ hwdef->vram_size, graphic_width, graphic_height, graphic_depth);
+
+ if (nd_table[0].model == NULL
+ || strcmp(nd_table[0].model, "lance") == 0) {
+ lance_init(&nd_table[0], hwdef->le_base, ledma, *ledma_irq, le_reset);
+ } else if (strcmp(nd_table[0].model, "?") == 0) {
+ fprintf(stderr, "qemu: Supported NICs: lance\n");
+ exit (1);
+ } else {
+ fprintf(stderr, "qemu: Unsupported NIC: %s\n", nd_table[0].model);
+ exit (1);
+ }
+
+ nvram = m48t59_init(sbi_irq[0], hwdef->nvram_base, 0,
+ hwdef->nvram_size, 8);
+
+ slavio_timer_init_all(hwdef->counter_base, sbi_irq[hwdef->clock1_irq],
+ sbi_cpu_irq, smp_cpus);
+
+ slavio_serial_ms_kbd_init(hwdef->ms_kb_base, sbi_irq[hwdef->ms_kb_irq],
+ nographic);
+ // Slavio TTYA (base+4, Linux ttyS0) is the first Qemu serial device
+ // Slavio TTYB (base+0, Linux ttyS1) is the second Qemu serial device
+ slavio_serial_init(hwdef->serial_base, sbi_irq[hwdef->ser_irq],
+ serial_hds[1], serial_hds[0]);
+
+ if (drive_get_max_bus(IF_SCSI) > 0) {
+ fprintf(stderr, "qemu: too many SCSI bus\n");
+ exit(1);
+ }
+
+ main_esp = esp_init(hwdef->esp_base, espdma, *espdma_irq,
+ esp_reset);
+
+ for (i = 0; i < ESP_MAX_DEVS; i++) {
+ index = drive_get_index(IF_SCSI, 0, i);
+ if (index == -1)
+ continue;
+ esp_scsi_attach(main_esp, drives_table[index].bdrv, i);
+ }
+
+ kernel_size = sun4m_load_kernel(kernel_filename, kernel_cmdline,
+ initrd_filename);
+
+ nvram_init(nvram, (uint8_t *)&nd_table[0].macaddr, kernel_cmdline,
+ boot_device, RAM_size, kernel_size, graphic_width,
+ graphic_height, graphic_depth, hwdef->machine_id, "Sun4d");
+}
+
+/* SPARCserver 1000 hardware initialisation */
+static void ss1000_init(int RAM_size, int vga_ram_size,
+ const char *boot_device, DisplayState *ds,
+ const char *kernel_filename, const char *kernel_cmdline,
+ const char *initrd_filename, const char *cpu_model)
+{
+ sun4d_hw_init(&sun4d_hwdefs[0], RAM_size, boot_device, ds, kernel_filename,
+ kernel_cmdline, initrd_filename, cpu_model);
+}
+
+/* SPARCcenter 2000 hardware initialisation */
+static void ss2000_init(int RAM_size, int vga_ram_size,
+ const char *boot_device, DisplayState *ds,
+ const char *kernel_filename, const char *kernel_cmdline,
+ const char *initrd_filename, const char *cpu_model)
+{
+ sun4d_hw_init(&sun4d_hwdefs[1], RAM_size, boot_device, ds, kernel_filename,
+ kernel_cmdline, initrd_filename, cpu_model);
+}
+
+QEMUMachine ss1000_machine = {
+ "SS-1000",
+ "Sun4d platform, SPARCserver 1000",
+ ss1000_init,
+};
+
+QEMUMachine ss2000_machine = {
+ "SS-2000",
+ "Sun4d platform, SPARCcenter 2000",
+ ss2000_init,
+};
Modified: trunk/src/host/qemu-neo1973/hw/sun4m.h
===================================================================
--- trunk/src/host/qemu-neo1973/hw/sun4m.h 2008-01-06 01:02:26 UTC (rev 3777)
+++ trunk/src/host/qemu-neo1973/hw/sun4m.h 2008-01-07 07:17:44 UTC (rev 3778)
@@ -4,7 +4,7 @@
/* Devices used by sparc32 system. */
/* iommu.c */
-void *iommu_init(target_phys_addr_t addr, uint32_t version);
+void *iommu_init(target_phys_addr_t addr, uint32_t version, qemu_irq irq);
void sparc_iommu_memory_rw(void *opaque, target_phys_addr_t addr,
uint8_t *buf, int len, int is_write);
static inline void sparc_iommu_memory_read(void *opaque,
@@ -34,6 +34,14 @@
void slavio_pic_info(void *opaque);
void slavio_irq_info(void *opaque);
+/* sbi.c */
+void *sbi_init(target_phys_addr_t addr, qemu_irq **irq, qemu_irq **cpu_irq,
+ qemu_irq **parent_irq);
+
+/* sun4c_intctl.c */
+void *sun4c_intctl_init(target_phys_addr_t addr, qemu_irq **irq,
+ qemu_irq *parent_irq);
+
/* slavio_timer.c */
void slavio_timer_init_all(target_phys_addr_t base, qemu_irq master_irq,
qemu_irq *cpu_irqs, unsigned int num_cpus);
Modified: trunk/src/host/qemu-neo1973/hw/tcx.c
===================================================================
--- trunk/src/host/qemu-neo1973/hw/tcx.c 2008-01-06 01:02:26 UTC (rev 3777)
+++ trunk/src/host/qemu-neo1973/hw/tcx.c 2008-01-07 07:17:44 UTC (rev 3778)
@@ -457,15 +457,15 @@
}
static CPUReadMemoryFunc *tcx_dac_read[3] = {
+ NULL,
+ NULL,
tcx_dac_readl,
- tcx_dac_readl,
- tcx_dac_readl,
};
static CPUWriteMemoryFunc *tcx_dac_write[3] = {
+ NULL,
+ NULL,
tcx_dac_writel,
- tcx_dac_writel,
- tcx_dac_writel,
};
static uint32_t tcx_dummy_readl(void *opaque, target_phys_addr_t addr)
@@ -479,15 +479,15 @@
}
static CPUReadMemoryFunc *tcx_dummy_read[3] = {
+ NULL,
+ NULL,
tcx_dummy_readl,
- tcx_dummy_readl,
- tcx_dummy_readl,
};
static CPUWriteMemoryFunc *tcx_dummy_write[3] = {
+ NULL,
+ NULL,
tcx_dummy_writel,
- tcx_dummy_writel,
- tcx_dummy_writel,
};
void tcx_init(DisplayState *ds, target_phys_addr_t addr, uint8_t *vram_base,
Modified: trunk/src/host/qemu-neo1973/linux-user/main.c
===================================================================
--- trunk/src/host/qemu-neo1973/linux-user/main.c 2008-01-06 01:02:26 UTC (rev 3777)
+++ trunk/src/host/qemu-neo1973/linux-user/main.c 2008-01-07 07:17:44 UTC (rev 3778)
@@ -1,7 +1,7 @@
/*
* qemu user main
*
- * Copyright (c) 2003 Fabrice Bellard
+ * Copyright (c) 2003-2008 Fabrice Bellard
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -1892,10 +1892,11 @@
void usage(void)
{
- printf("qemu-" TARGET_ARCH " version " QEMU_VERSION ", Copyright (c) 2003-2007 Fabrice Bellard\n"
- "usage: qemu-" TARGET_ARCH " [-h] [-g] [-d opts] [-L path] [-s size] [-cpu model] program [arguments...]\n"
+ printf("qemu-" TARGET_ARCH " version " QEMU_VERSION ", Copyright (c) 2003-2008 Fabrice Bellard\n"
+ "usage: qemu-" TARGET_ARCH " [options] program [arguments...]\n"
"Linux CPU emulator (compiled for %s emulation)\n"
"\n"
+ "Standard options:\n"
"-h print this help\n"
"-g port wait gdb connection to port\n"
"-L path set the elf interpreter prefix (default=%s)\n"
@@ -1903,12 +1904,12 @@
"-cpu model select CPU (-cpu ? for list)\n"
"-drop-ld-preload drop LD_PRELOAD for target process\n"
"\n"
- "debug options:\n"
+ "Debug options:\n"
"-d options activate log (logfile=%s)\n"
"-p pagesize set the host page size to 'pagesize'\n"
"-strace log system calls\n"
"\n"
- "environment variables:\n"
+ "Environment variables:\n"
"QEMU_STRACE Print system calls and arguments similar to the\n"
" 'strace' program. Enable by setting to any value.\n"
,
Modified: trunk/src/host/qemu-neo1973/pc-bios/README
===================================================================
--- trunk/src/host/qemu-neo1973/pc-bios/README 2008-01-06 01:02:26 UTC (rev 3777)
+++ trunk/src/host/qemu-neo1973/pc-bios/README 2008-01-07 07:17:44 UTC (rev 3778)
@@ -14,8 +14,8 @@
- OpenBIOS (http://www.openbios.org/) is a free (GPL v2) portable
firmware implementation. The goal is to implement a 100% IEEE
1275-1994 (referred to as Open Firmware) compliant firmware.
- The included Sparc32 and Sparc64 images are built from SVN
- revision 181.
+ The included Sparc32 image is built from SVN revision 183
+ and Sparc64 from SVN revision 181.
- The PXE roms come from Rom-o-Matic etherboot 5.4.2.
pcnet32:pcnet32 -- [0x1022,0x2000]
Modified: trunk/src/host/qemu-neo1973/pc-bios/openbios-sparc32
===================================================================
(Binary files differ)
Modified: trunk/src/host/qemu-neo1973/qemu-doc.texi
===================================================================
--- trunk/src/host/qemu-neo1973/qemu-doc.texi 2008-01-06 01:02:26 UTC (rev 3777)
+++ trunk/src/host/qemu-neo1973/qemu-doc.texi 2008-01-07 07:17:44 UTC (rev 3778)
@@ -74,7 +74,7 @@
@item PREP (PowerPC processor)
@item G3 BW PowerMac (PowerPC processor)
@item Mac99 PowerMac (PowerPC processor, in progress)
- at item Sun4m (32-bit Sparc processor)
+ at item Sun4m/Sun4c/Sun4d (32-bit Sparc processor)
@item Sun4u (64-bit Sparc processor, in progress)
@item Malta board (32-bit and 64-bit MIPS processors)
@item ARM Integrator/CP (ARM)
@@ -2026,15 +2026,17 @@
@section Sparc32 System emulator
Use the executable @file{qemu-system-sparc} to simulate a SPARCstation
-5, SPARCstation 10, or SPARCserver 600MP (sun4m architecture). The
-emulation is somewhat complete. SMP up to 16 CPUs is supported, but
-Linux limits the number of usable CPUs to 4.
+5, SPARCstation 10, SPARCstation 20, SPARCserver 600MP (sun4m
+architecture), SPARCstation 2 (sun4c architecture), SPARCserver 1000,
+or SPARCcenter 2000 (sun4d architecture). The emulation is somewhat
+complete. SMP up to 16 CPUs is supported, but Linux limits the number
+of usable CPUs to 4.
-QEMU emulates the following sun4m peripherals:
+QEMU emulates the following sun4m/sun4d peripherals:
@itemize @minus
@item
-IOMMU
+IOMMU or IO-UNITs
@item
TCX Frame buffer
@item
@@ -2054,7 +2056,7 @@
The number of peripherals is fixed in the architecture. Maximum
memory size depends on the machine type, for SS-5 it is 256MB and for
-SS-10 and SS-600MP 2047MB.
+others 2047MB.
Since version 0.8.2, QEMU uses OpenBIOS
@url{http://www.openbios.org/}. OpenBIOS is a free (GPL v2) portable
@@ -2085,7 +2087,7 @@
-prom-env 'boot-device=sd(0,2,0):d' -prom-env 'boot-args=linux single'
@end example
- at item -M [SS-5|SS-10|SS-600MP]
+ at item -M [SS-5|SS-10|SS-20|SS-600MP|SS-2|SS-1000|SS-2000]
Set the emulated machine type. Default is SS-5.
Modified: trunk/src/host/qemu-neo1973/qemu-img.c
===================================================================
--- trunk/src/host/qemu-neo1973/qemu-img.c 2008-01-06 01:02:26 UTC (rev 3777)
+++ trunk/src/host/qemu-neo1973/qemu-img.c 2008-01-07 07:17:44 UTC (rev 3778)
@@ -1,7 +1,7 @@
/*
* QEMU disk image utility
*
- * Copyright (c) 2003-2007 Fabrice Bellard
+ * Copyright (c) 2003-2008 Fabrice Bellard
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
@@ -83,7 +83,7 @@
static void help(void)
{
- printf("qemu-img version " QEMU_VERSION ", Copyright (c) 2004-2007 Fabrice Bellard\n"
+ printf("qemu-img version " QEMU_VERSION ", Copyright (c) 2004-2008 Fabrice Bellard\n"
"usage: qemu-img command [command options]\n"
"QEMU disk image utility\n"
"\n"
Modified: trunk/src/host/qemu-neo1973/target-mips/cpu.h
===================================================================
--- trunk/src/host/qemu-neo1973/target-mips/cpu.h 2008-01-06 01:02:26 UTC (rev 3777)
+++ trunk/src/host/qemu-neo1973/target-mips/cpu.h 2008-01-07 07:17:44 UTC (rev 3778)
@@ -162,6 +162,8 @@
uint32_t SEGBITS;
target_ulong SEGMask;
+ uint32_t PABITS;
+ target_ulong PAMask;
int32_t CP0_Index;
/* CP0_MVP* are per MVP registers. */
@@ -415,7 +417,7 @@
int user_mode_only; /* user mode only simulation */
uint32_t hflags; /* CPU State */
/* TMASK defines different execution modes */
-#define MIPS_HFLAG_TMASK 0x00FF
+#define MIPS_HFLAG_TMASK 0x01FF
#define MIPS_HFLAG_MODE 0x0007 /* execution modes */
/* The KSU flags must be the lowest bits in hflags. The flag order
must be the same as defined for CP0 Status. This allows to use
@@ -429,16 +431,20 @@
#define MIPS_HFLAG_CP0 0x0010 /* CP0 enabled */
#define MIPS_HFLAG_FPU 0x0020 /* FPU enabled */
#define MIPS_HFLAG_F64 0x0040 /* 64-bit FPU enabled */
-#define MIPS_HFLAG_RE 0x0080 /* Reversed endianness */
+ /* True if the MIPS IV COP1X instructions can be used. This also
+ controls the non-COP1X instructions RECIP.S, RECIP.D, RSQRT.S
+ and RSQRT.D. */
+#define MIPS_HFLAG_COP1X 0x0080 /* COP1X instructions enabled */
+#define MIPS_HFLAG_RE 0x0100 /* Reversed endianness */
/* If translation is interrupted between the branch instruction and
* the delay slot, record what type of branch it is so that we can
* resume translation properly. It might be possible to reduce
* this from three bits to two. */
-#define MIPS_HFLAG_BMASK 0x0700
-#define MIPS_HFLAG_B 0x0100 /* Unconditional branch */
-#define MIPS_HFLAG_BC 0x0200 /* Conditional branch */
-#define MIPS_HFLAG_BL 0x0300 /* Likely branch */
-#define MIPS_HFLAG_BR 0x0400 /* branch to register (can't link TB) */
+#define MIPS_HFLAG_BMASK 0x0e00
+#define MIPS_HFLAG_B 0x0200 /* Unconditional branch */
+#define MIPS_HFLAG_BC 0x0400 /* Conditional branch */
+#define MIPS_HFLAG_BL 0x0600 /* Likely branch */
+#define MIPS_HFLAG_BR 0x0800 /* branch to register (can't link TB) */
target_ulong btarget; /* Jump / branch target */
int bcond; /* Branch condition (if needed) */
@@ -521,40 +527,37 @@
EXCP_SRESET,
EXCP_DSS,
EXCP_DINT,
+ EXCP_DDBL,
+ EXCP_DDBS,
EXCP_NMI,
EXCP_MCHECK,
- EXCP_EXT_INTERRUPT,
+ EXCP_EXT_INTERRUPT, /* 8 */
EXCP_DFWATCH,
- EXCP_DIB, /* 8 */
+ EXCP_DIB,
EXCP_IWATCH,
EXCP_AdEL,
EXCP_AdES,
EXCP_TLBF,
EXCP_IBE,
- EXCP_DBp,
+ EXCP_DBp, /* 16 */
EXCP_SYSCALL,
- EXCP_BREAK, /* 16 */
+ EXCP_BREAK,
EXCP_CpU,
EXCP_RI,
EXCP_OVERFLOW,
EXCP_TRAP,
EXCP_FPE,
- EXCP_DDBS,
- EXCP_DWATCH,
- EXCP_LAE, /* 24 */
- EXCP_SAE,
+ EXCP_DWATCH, /* 24 */
EXCP_LTLBL,
EXCP_TLBL,
EXCP_TLBS,
EXCP_DBE,
- EXCP_DDBL,
EXCP_THREAD,
- EXCP_MTCP0 = 0x104, /* mtmsr instruction: */
- /* may change privilege level */
- EXCP_BRANCH = 0x108, /* branch instruction */
- EXCP_ERET = 0x10C, /* return from interrupt */
- EXCP_SYSCALL_USER = 0x110, /* System call in user mode only */
- EXCP_FLUSH = 0x109,
+ EXCP_MDMX,
+ EXCP_C2E,
+ EXCP_CACHE, /* 32 */
+
+ EXCP_LAST = EXCP_CACHE,
};
int cpu_mips_exec(CPUMIPSState *s);
Modified: trunk/src/host/qemu-neo1973/target-mips/exec.h
===================================================================
--- trunk/src/host/qemu-neo1973/target-mips/exec.h 2008-01-06 01:02:26 UTC (rev 3777)
+++ trunk/src/host/qemu-neo1973/target-mips/exec.h 2008-01-07 07:17:44 UTC (rev 3778)
@@ -79,6 +79,20 @@
void do_maddu (void);
void do_msub (void);
void do_msubu (void);
+void do_muls (void);
+void do_mulsu (void);
+void do_macc (void);
+void do_macchi (void);
+void do_maccu (void);
+void do_macchiu (void);
+void do_msac (void);
+void do_msachi (void);
+void do_msacu (void);
+void do_msachiu (void);
+void do_mulhi (void);
+void do_mulhiu (void);
+void do_mulshi (void);
+void do_mulshiu (void);
#endif
#if defined(TARGET_MIPS64)
void do_ddiv (void);
@@ -223,8 +237,8 @@
static always_inline void compute_hflags(CPUState *env)
{
- env->hflags &= ~(MIPS_HFLAG_64 | MIPS_HFLAG_CP0 | MIPS_HFLAG_F64 |
- MIPS_HFLAG_FPU | MIPS_HFLAG_KSU);
+ env->hflags &= ~(MIPS_HFLAG_COP1X | MIPS_HFLAG_64 | MIPS_HFLAG_CP0 |
+ MIPS_HFLAG_F64 | MIPS_HFLAG_FPU | MIPS_HFLAG_KSU);
if (!(env->CP0_Status & (1 << CP0St_EXL)) &&
!(env->CP0_Status & (1 << CP0St_ERL)) &&
!(env->hflags & MIPS_HFLAG_DM)) {
@@ -243,6 +257,20 @@
env->hflags |= MIPS_HFLAG_FPU;
if (env->CP0_Status & (1 << CP0St_FR))
env->hflags |= MIPS_HFLAG_F64;
+ if (env->insn_flags & ISA_MIPS32R2) {
+ if (env->fpu->fcr0 & FCR0_F64)
+ env->hflags |= MIPS_HFLAG_COP1X;
+ } else if (env->insn_flags & ISA_MIPS32) {
+ if (env->hflags & MIPS_HFLAG_64)
+ env->hflags |= MIPS_HFLAG_COP1X;
+ } else if (env->insn_flags & ISA_MIPS4) {
+ /* All supported MIPS IV CPUs use the XX (CU3) to enable
+ and disable the MIPS IV extensions to the MIPS III ISA.
+ Some other MIPS IV CPUs ignore the bit, so the check here
+ would be too restrictive for them. */
+ if (env->CP0_Status & (1 << CP0St_CU3))
+ env->hflags |= MIPS_HFLAG_COP1X;
+ }
}
#endif /* !defined(__QEMU_MIPS_EXEC_H__) */
Modified: trunk/src/host/qemu-neo1973/target-mips/helper.c
===================================================================
--- trunk/src/host/qemu-neo1973/target-mips/helper.c 2008-01-06 01:02:26 UTC (rev 3777)
+++ trunk/src/host/qemu-neo1973/target-mips/helper.c 2008-01-07 07:17:44 UTC (rev 3778)
@@ -148,10 +148,9 @@
}
} else if (address < 0xC000000000000000ULL) {
/* xkphys */
- /* XXX: Assumes PABITS = 36 (correct for MIPS64R1) */
if (kernel_mode && KX &&
- (address & 0x07FFFFFFFFFFFFFFULL) <= 0x0000000FFFFFFFFFULL) {
- *physical = address & 0x0000000FFFFFFFFFULL;
+ (address & 0x07FFFFFFFFFFFFFFULL) <= env->PAMask) {
+ *physical = address & env->PAMask;
*prot = PAGE_READ | PAGE_WRITE;
} else {
ret = TLBRET_BADADDR;
@@ -319,20 +318,59 @@
return ret;
}
-#if defined(CONFIG_USER_ONLY)
+#if !defined(CONFIG_USER_ONLY)
+static const char * const excp_names[EXCP_LAST + 1] = {
+ [EXCP_RESET] = "reset",
+ [EXCP_SRESET] = "soft reset",
+ [EXCP_DSS] = "debug single step",
+ [EXCP_DINT] = "debug interrupt",
+ [EXCP_NMI] = "non-maskable interrupt",
+ [EXCP_MCHECK] = "machine check",
+ [EXCP_EXT_INTERRUPT] = "interrupt",
+ [EXCP_DFWATCH] = "deferred watchpoint",
+ [EXCP_DIB] = "debug instruction breakpoint",
+ [EXCP_IWATCH] = "instruction fetch watchpoint",
+ [EXCP_AdEL] = "address error load",
+ [EXCP_AdES] = "address error store",
+ [EXCP_TLBF] = "TLB refill",
+ [EXCP_IBE] = "instruction bus error",
+ [EXCP_DBp] = "debug breakpoint",
+ [EXCP_SYSCALL] = "syscall",
+ [EXCP_BREAK] = "break",
+ [EXCP_CpU] = "coprocessor unusable",
+ [EXCP_RI] = "reserved instruction",
+ [EXCP_OVERFLOW] = "arithmetic overflow",
+ [EXCP_TRAP] = "trap",
+ [EXCP_FPE] = "floating point",
+ [EXCP_DDBS] = "debug data break store",
+ [EXCP_DWATCH] = "data watchpoint",
+ [EXCP_LTLBL] = "TLB modify",
+ [EXCP_TLBL] = "TLB load",
+ [EXCP_TLBS] = "TLB store",
+ [EXCP_DBE] = "data bus error",
+ [EXCP_DDBL] = "debug data break load",
+ [EXCP_THREAD] = "thread",
+ [EXCP_MDMX] = "MDMX",
+ [EXCP_C2E] = "precise coprocessor 2",
+ [EXCP_CACHE] = "cache error",
+};
+#endif
+
void do_interrupt (CPUState *env)
{
- env->exception_index = EXCP_NONE;
-}
-#else
-void do_interrupt (CPUState *env)
-{
+#if !defined(CONFIG_USER_ONLY)
target_ulong offset;
int cause = -1;
+ const char *name;
if (logfile && env->exception_index != EXCP_EXT_INTERRUPT) {
- fprintf(logfile, "%s enter: PC " TARGET_FMT_lx " EPC " TARGET_FMT_lx " cause %d excp %d\n",
- __func__, env->PC[env->current_tc], env->CP0_EPC, cause, env->exception_index);
+ if (env->exception_index < 0 || env->exception_index > EXCP_LAST)
+ name = "unknown";
+ else
+ name = excp_names[env->exception_index];
+
+ fprintf(logfile, "%s enter: PC " TARGET_FMT_lx " EPC " TARGET_FMT_lx " %s exception\n",
+ __func__, env->PC[env->current_tc], env->CP0_EPC, name);
}
if (env->exception_index == EXCP_EXT_INTERRUPT &&
(env->hflags & MIPS_HFLAG_DM))
@@ -404,24 +442,14 @@
env->CP0_Cause &= ~(1 << CP0Ca_BD);
env->PC[env->current_tc] = (int32_t)0xBFC00000;
break;
- case EXCP_MCHECK:
- cause = 24;
- goto set_EPC;
case EXCP_EXT_INTERRUPT:
cause = 0;
if (env->CP0_Cause & (1 << CP0Ca_IV))
offset = 0x200;
goto set_EPC;
- case EXCP_DWATCH:
- cause = 23;
- /* XXX: TODO: manage defered watch exceptions */
+ case EXCP_LTLBL:
+ cause = 1;
goto set_EPC;
- case EXCP_AdEL:
- cause = 4;
- goto set_EPC;
- case EXCP_AdES:
- cause = 5;
- goto set_EPC;
case EXCP_TLBL:
cause = 2;
if (env->error_code == 1 && !(env->CP0_Status & (1 << CP0St_EXL))) {
@@ -438,6 +466,28 @@
offset = 0x000;
}
goto set_EPC;
+ case EXCP_TLBS:
+ cause = 3;
+ if (env->error_code == 1 && !(env->CP0_Status & (1 << CP0St_EXL))) {
+#if defined(TARGET_MIPS64)
+ int R = env->CP0_BadVAddr >> 62;
+ int UX = (env->CP0_Status & (1 << CP0St_UX)) != 0;
+ int SX = (env->CP0_Status & (1 << CP0St_SX)) != 0;
+ int KX = (env->CP0_Status & (1 << CP0St_KX)) != 0;
+
+ if ((R == 0 && UX) || (R == 1 && SX) || (R == 3 && KX))
+ offset = 0x080;
+ else
+#endif
+ offset = 0x000;
+ }
+ goto set_EPC;
+ case EXCP_AdEL:
+ cause = 4;
+ goto set_EPC;
+ case EXCP_AdES:
+ cause = 5;
+ goto set_EPC;
case EXCP_IBE:
cause = 6;
goto set_EPC;
@@ -467,27 +517,29 @@
case EXCP_FPE:
cause = 15;
goto set_EPC;
- case EXCP_LTLBL:
- cause = 1;
+ case EXCP_C2E:
+ cause = 18;
goto set_EPC;
- case EXCP_TLBS:
- cause = 3;
- if (env->error_code == 1 && !(env->CP0_Status & (1 << CP0St_EXL))) {
-#if defined(TARGET_MIPS64)
- int R = env->CP0_BadVAddr >> 62;
- int UX = (env->CP0_Status & (1 << CP0St_UX)) != 0;
- int SX = (env->CP0_Status & (1 << CP0St_SX)) != 0;
- int KX = (env->CP0_Status & (1 << CP0St_KX)) != 0;
-
- if ((R == 0 && UX) || (R == 1 && SX) || (R == 3 && KX))
- offset = 0x080;
- else
-#endif
- offset = 0x000;
- }
+ case EXCP_MDMX:
+ cause = 22;
goto set_EPC;
+ case EXCP_DWATCH:
+ cause = 23;
+ /* XXX: TODO: manage defered watch exceptions */
+ goto set_EPC;
+ case EXCP_MCHECK:
+ cause = 24;
+ goto set_EPC;
case EXCP_THREAD:
cause = 25;
+ goto set_EPC;
+ case EXCP_CACHE:
+ cause = 30;
+ if (env->CP0_Status & (1 << CP0St_BEV)) {
+ offset = 0x100;
+ } else {
+ offset = 0x20000100;
+ }
set_EPC:
if (!(env->CP0_Status & (1 << CP0St_EXL))) {
if (env->hflags & MIPS_HFLAG_BMASK) {
@@ -521,15 +573,15 @@
exit(1);
}
if (logfile && env->exception_index != EXCP_EXT_INTERRUPT) {
- fprintf(logfile, "%s: PC " TARGET_FMT_lx " EPC " TARGET_FMT_lx " cause %d excp %d\n"
+ fprintf(logfile, "%s: PC " TARGET_FMT_lx " EPC " TARGET_FMT_lx " cause %d\n"
" S %08x C %08x A " TARGET_FMT_lx " D " TARGET_FMT_lx "\n",
- __func__, env->PC[env->current_tc], env->CP0_EPC, cause, env->exception_index,
+ __func__, env->PC[env->current_tc], env->CP0_EPC, cause,
env->CP0_Status, env->CP0_Cause, env->CP0_BadVAddr,
env->CP0_DEPC);
}
+#endif /* !defined(CONFIG_USER_ONLY) */
env->exception_index = EXCP_NONE;
}
-#endif /* !defined(CONFIG_USER_ONLY) */
void r4k_invalidate_tlb (CPUState *env, int idx, int use_extra)
{
Modified: trunk/src/host/qemu-neo1973/target-mips/mips-defs.h
===================================================================
--- trunk/src/host/qemu-neo1973/target-mips/mips-defs.h 2008-01-06 01:02:26 UTC (rev 3777)
+++ trunk/src/host/qemu-neo1973/target-mips/mips-defs.h 2008-01-07 07:17:44 UTC (rev 3778)
@@ -4,7 +4,7 @@
/* If we want to use host float regs... */
//#define USE_HOST_FLOAT_REGS
-/* real pages are variable size... */
+/* Real pages are variable size... */
#define TARGET_PAGE_BITS 12
#define MIPS_TLB_MAX 128
@@ -29,7 +29,7 @@
#define ISA_MIPS64 0x00000080
#define ISA_MIPS64R2 0x00000100
-/* MIPS ASE */
+/* MIPS ASEs. */
#define ASE_MIPS16 0x00001000
#define ASE_MIPS3D 0x00002000
#define ASE_MDMX 0x00004000
@@ -38,19 +38,23 @@
#define ASE_MT 0x00020000
#define ASE_SMARTMIPS 0x00040000
-/* Chip specific instructions. */
-/* Currently void */
+/* Chip specific instructions. */
+#define INSN_VR54XX 0x80000000
-/* MIPS CPU defines. */
+/* MIPS CPU defines. */
#define CPU_MIPS1 (ISA_MIPS1)
#define CPU_MIPS2 (CPU_MIPS1 | ISA_MIPS2)
#define CPU_MIPS3 (CPU_MIPS2 | ISA_MIPS3)
#define CPU_MIPS4 (CPU_MIPS3 | ISA_MIPS4)
+#define CPU_VR54XX (CPU_MIPS4 | INSN_VR54XX)
+
#define CPU_MIPS5 (CPU_MIPS4 | ISA_MIPS5)
+/* MIPS Technologies "Release 1" */
#define CPU_MIPS32 (CPU_MIPS2 | ISA_MIPS32)
#define CPU_MIPS64 (CPU_MIPS5 | CPU_MIPS32 | ISA_MIPS64)
+/* MIPS Technologies "Release 2" */
#define CPU_MIPS32R2 (CPU_MIPS32 | ISA_MIPS32R2)
#define CPU_MIPS64R2 (CPU_MIPS64 | CPU_MIPS32R2 | ISA_MIPS64R2)
Modified: trunk/src/host/qemu-neo1973/target-mips/op.c
===================================================================
--- trunk/src/host/qemu-neo1973/target-mips/op.c 2008-01-06 01:02:26 UTC (rev 3777)
+++ trunk/src/host/qemu-neo1973/target-mips/op.c 2008-01-07 07:17:44 UTC (rev 3778)
@@ -781,6 +781,90 @@
FORCE_RET();
}
+/* Multiplication variants of the vr54xx. */
+void op_muls (void)
+{
+ CALL_FROM_TB0(do_muls);
+ FORCE_RET();
+}
+
+void op_mulsu (void)
+{
+ CALL_FROM_TB0(do_mulsu);
+ FORCE_RET();
+}
+
+void op_macc (void)
+{
+ CALL_FROM_TB0(do_macc);
+ FORCE_RET();
+}
+
+void op_macchi (void)
+{
+ CALL_FROM_TB0(do_macchi);
+ FORCE_RET();
+}
+
+void op_maccu (void)
+{
+ CALL_FROM_TB0(do_maccu);
+ FORCE_RET();
+}
+void op_macchiu (void)
+{
+ CALL_FROM_TB0(do_macchiu);
+ FORCE_RET();
+}
+
+void op_msac (void)
+{
+ CALL_FROM_TB0(do_msac);
+ FORCE_RET();
+}
+
+void op_msachi (void)
+{
+ CALL_FROM_TB0(do_msachi);
+ FORCE_RET();
+}
+
+void op_msacu (void)
+{
+ CALL_FROM_TB0(do_msacu);
+ FORCE_RET();
+}
+
+void op_msachiu (void)
+{
+ CALL_FROM_TB0(do_msachiu);
+ FORCE_RET();
+}
+
+void op_mulhi (void)
+{
+ CALL_FROM_TB0(do_mulhi);
+ FORCE_RET();
+}
+
+void op_mulhiu (void)
+{
+ CALL_FROM_TB0(do_mulhiu);
+ FORCE_RET();
+}
+
+void op_mulshi (void)
+{
+ CALL_FROM_TB0(do_mulshi);
+ FORCE_RET();
+}
+
+void op_mulshiu (void)
+{
+ CALL_FROM_TB0(do_mulshiu);
+ FORCE_RET();
+}
+
#else /* TARGET_LONG_BITS > HOST_LONG_BITS */
static always_inline uint64_t get_HILO (void)
@@ -795,6 +879,18 @@
env->HI[0][env->current_tc] = (int32_t)(HILO >> 32);
}
+static always_inline void set_HIT0_LO (uint64_t HILO)
+{
+ env->LO[0][env->current_tc] = (int32_t)(HILO & 0xFFFFFFFF);
+ T0 = env->HI[0][env->current_tc] = (int32_t)(HILO >> 32);
+}
+
+static always_inline void set_HI_LOT0 (uint64_t HILO)
+{
+ T0 = env->LO[0][env->current_tc] = (int32_t)(HILO & 0xFFFFFFFF);
+ env->HI[0][env->current_tc] = (int32_t)(HILO >> 32);
+}
+
void op_mult (void)
{
set_HILO((int64_t)(int32_t)T0 * (int64_t)(int32_t)T1);
@@ -842,6 +938,92 @@
set_HILO(get_HILO() - tmp);
FORCE_RET();
}
+
+/* Multiplication variants of the vr54xx. */
+void op_muls (void)
+{
+ set_HI_LOT0(0 - ((int64_t)(int32_t)T0 * (int64_t)(int32_t)T1));
+ FORCE_RET();
+}
+
+void op_mulsu (void)
+{
+ set_HI_LOT0(0 - ((uint64_t)(uint32_t)T0 * (uint64_t)(uint32_t)T1));
+ FORCE_RET();
+}
+
+void op_macc (void)
+{
+ set_HI_LOT0(get_HILO() + ((int64_t)(int32_t)T0 * (int64_t)(int32_t)T1));
+ FORCE_RET();
+}
+
+void op_macchi (void)
+{
+ set_HIT0_LO(get_HILO() + ((int64_t)(int32_t)T0 * (int64_t)(int32_t)T1));
+ FORCE_RET();
+}
+
+void op_maccu (void)
+{
+ set_HI_LOT0(get_HILO() + ((uint64_t)(uint32_t)T0 * (uint64_t)(uint32_t)T1));
+ FORCE_RET();
+}
+
+void op_macchiu (void)
+{
+ set_HIT0_LO(get_HILO() + ((uint64_t)(uint32_t)T0 * (uint64_t)(uint32_t)T1));
+ FORCE_RET();
+}
+
+void op_msac (void)
+{
+ set_HI_LOT0(get_HILO() - ((int64_t)(int32_t)T0 * (int64_t)(int32_t)T1));
+ FORCE_RET();
+}
+
+void op_msachi (void)
+{
+ set_HIT0_LO(get_HILO() - ((int64_t)(int32_t)T0 * (int64_t)(int32_t)T1));
+ FORCE_RET();
+}
+
+void op_msacu (void)
+{
+ set_HI_LOT0(get_HILO() - ((uint64_t)(uint32_t)T0 * (uint64_t)(uint32_t)T1));
+ FORCE_RET();
+}
+
+void op_msachiu (void)
+{
+ set_HIT0_LO(get_HILO() - ((uint64_t)(uint32_t)T0 * (uint64_t)(uint32_t)T1));
+ FORCE_RET();
+}
+
+void op_mulhi (void)
+{
+ set_HIT0_LO((int64_t)(int32_t)T0 * (int64_t)(int32_t)T1);
+ FORCE_RET();
+}
+
+void op_mulhiu (void)
+{
+ set_HIT0_LO((uint64_t)(uint32_t)T0 * (uint64_t)(uint32_t)T1);
+ FORCE_RET();
+}
+
+void op_mulshi (void)
+{
+ set_HIT0_LO(0 - ((int64_t)(int32_t)T0 * (int64_t)(int32_t)T1));
+ FORCE_RET();
+}
+
+void op_mulshiu (void)
+{
+ set_HIT0_LO(0 - ((uint64_t)(uint32_t)T0 * (uint64_t)(uint32_t)T1));
+ FORCE_RET();
+}
+
#endif /* TARGET_LONG_BITS > HOST_LONG_BITS */
#if defined(TARGET_MIPS64)
@@ -1563,7 +1745,7 @@
void op_mtc0_entrylo0 (void)
{
- /* Large physaddr not implemented */
+ /* Large physaddr (PABITS) not implemented */
/* 1k pages not implemented */
env->CP0_EntryLo0 = T0 & 0x3FFFFFFF;
FORCE_RET();
@@ -1700,7 +1882,7 @@
void op_mtc0_entrylo1 (void)
{
- /* Large physaddr not implemented */
+ /* Large physaddr (PABITS) not implemented */
/* 1k pages not implemented */
env->CP0_EntryLo1 = T0 & 0x3FFFFFFF;
FORCE_RET();
@@ -1722,7 +1904,7 @@
void op_mtc0_pagegrain (void)
{
/* SmartMIPS not implemented */
- /* Large physaddr not implemented */
+ /* Large physaddr (PABITS) not implemented */
/* 1k pages not implemented */
env->CP0_PageGrain = 0;
FORCE_RET();
Modified: trunk/src/host/qemu-neo1973/target-mips/op_helper.c
===================================================================
--- trunk/src/host/qemu-neo1973/target-mips/op_helper.c 2008-01-06 01:02:26 UTC (rev 3777)
+++ trunk/src/host/qemu-neo1973/target-mips/op_helper.c 2008-01-07 07:17:44 UTC (rev 3778)
@@ -172,6 +172,18 @@
env->HI[0][env->current_tc] = (int32_t)(HILO >> 32);
}
+static always_inline void set_HIT0_LO (uint64_t HILO)
+{
+ env->LO[0][env->current_tc] = (int32_t)(HILO & 0xFFFFFFFF);
+ T0 = env->HI[0][env->current_tc] = (int32_t)(HILO >> 32);
+}
+
+static always_inline void set_HI_LOT0 (uint64_t HILO)
+{
+ T0 = env->LO[0][env->current_tc] = (int32_t)(HILO & 0xFFFFFFFF);
+ env->HI[0][env->current_tc] = (int32_t)(HILO >> 32);
+}
+
void do_mult (void)
{
set_HILO((int64_t)(int32_t)T0 * (int64_t)(int32_t)T1);
@@ -213,8 +225,79 @@
tmp = ((uint64_t)(uint32_t)T0 * (uint64_t)(uint32_t)T1);
set_HILO(get_HILO() - tmp);
}
-#endif
+/* Multiplication variants of the vr54xx. */
+void do_muls (void)
+{
+ set_HI_LOT0(0 - ((int64_t)(int32_t)T0 * (int64_t)(int32_t)T1));
+}
+
+void do_mulsu (void)
+{
+ set_HI_LOT0(0 - ((uint64_t)(uint32_t)T0 * (uint64_t)(uint32_t)T1));
+}
+
+void do_macc (void)
+{
+ set_HI_LOT0(((int64_t)get_HILO()) + ((int64_t)(int32_t)T0 * (int64_t)(int32_t)T1));
+}
+
+void do_macchi (void)
+{
+ set_HIT0_LO(((int64_t)get_HILO()) + ((int64_t)(int32_t)T0 * (int64_t)(int32_t)T1));
+}
+
+void do_maccu (void)
+{
+ set_HI_LOT0(((uint64_t)get_HILO()) + ((uint64_t)(uint32_t)T0 * (uint64_t)(uint32_t)T1));
+}
+
+void do_macchiu (void)
+{
+ set_HIT0_LO(((uint64_t)get_HILO()) + ((uint64_t)(uint32_t)T0 * (uint64_t)(uint32_t)T1));
+}
+
+void do_msac (void)
+{
+ set_HI_LOT0(((int64_t)get_HILO()) - ((int64_t)(int32_t)T0 * (int64_t)(int32_t)T1));
+}
+
+void do_msachi (void)
+{
+ set_HIT0_LO(((int64_t)get_HILO()) - ((int64_t)(int32_t)T0 * (int64_t)(int32_t)T1));
+}
+
+void do_msacu (void)
+{
+ set_HI_LOT0(((uint64_t)get_HILO()) - ((uint64_t)(uint32_t)T0 * (uint64_t)(uint32_t)T1));
+}
+
+void do_msachiu (void)
+{
+ set_HIT0_LO(((uint64_t)get_HILO()) - ((uint64_t)(uint32_t)T0 * (uint64_t)(uint32_t)T1));
+}
+
+void do_mulhi (void)
+{
+ set_HIT0_LO((int64_t)(int32_t)T0 * (int64_t)(int32_t)T1);
+}
+
+void do_mulhiu (void)
+{
+ set_HIT0_LO((uint64_t)(uint32_t)T0 * (uint64_t)(uint32_t)T1);
+}
+
+void do_mulshi (void)
+{
+ set_HIT0_LO(0 - ((int64_t)(int32_t)T0 * (int64_t)(int32_t)T1));
+}
+
+void do_mulshiu (void)
+{
+ set_HIT0_LO(0 - ((uint64_t)(uint32_t)T0 * (uint64_t)(uint32_t)T1));
+}
+#endif /* TARGET_LONG_BITS > HOST_LONG_BITS */
+
#if HOST_LONG_BITS < 64
void do_div (void)
{
@@ -230,9 +313,16 @@
void do_ddiv (void)
{
if (T1 != 0) {
- lldiv_t res = lldiv((int64_t)T0, (int64_t)T1);
- env->LO[0][env->current_tc] = res.quot;
- env->HI[0][env->current_tc] = res.rem;
+ int64_t arg0 = (int64_t)T0;
+ int64_t arg1 = (int64_t)T1;
+ if (arg0 == ((int64_t)-1 << 63) && arg1 == (int64_t)-1) {
+ env->LO[0][env->current_tc] = arg0;
+ env->HI[0][env->current_tc] = 0;
+ } else {
+ lldiv_t res = lldiv(arg0, arg1);
+ env->LO[0][env->current_tc] = res.quot;
+ env->HI[0][env->current_tc] = res.rem;
+ }
}
}
Modified: trunk/src/host/qemu-neo1973/target-mips/translate.c
===================================================================
--- trunk/src/host/qemu-neo1973/target-mips/translate.c 2008-01-06 01:02:26 UTC (rev 3777)
+++ trunk/src/host/qemu-neo1973/target-mips/translate.c 2008-01-07 07:17:44 UTC (rev 3778)
@@ -214,6 +214,26 @@
OPC_SPECIAL3D_RESERVED = 0x3D | OPC_SPECIAL,
};
+/* Multiplication variants of the vr54xx. */
+#define MASK_MUL_VR54XX(op) MASK_SPECIAL(op) | (op & (0x1F << 6))
+
+enum {
+ OPC_VR54XX_MULS = (0x03 << 6) | OPC_MULT,
+ OPC_VR54XX_MULSU = (0x03 << 6) | OPC_MULTU,
+ OPC_VR54XX_MACC = (0x05 << 6) | OPC_MULT,
+ OPC_VR54XX_MACCU = (0x05 << 6) | OPC_MULTU,
+ OPC_VR54XX_MSAC = (0x07 << 6) | OPC_MULT,
+ OPC_VR54XX_MSACU = (0x07 << 6) | OPC_MULTU,
+ OPC_VR54XX_MULHI = (0x09 << 6) | OPC_MULT,
+ OPC_VR54XX_MULHIU = (0x09 << 6) | OPC_MULTU,
+ OPC_VR54XX_MULSHI = (0x0B << 6) | OPC_MULT,
+ OPC_VR54XX_MULSHIU = (0x0B << 6) | OPC_MULTU,
+ OPC_VR54XX_MACCHI = (0x0D << 6) | OPC_MULT,
+ OPC_VR54XX_MACCHIU = (0x0D << 6) | OPC_MULTU,
+ OPC_VR54XX_MSACHI = (0x0F << 6) | OPC_MULT,
+ OPC_VR54XX_MSACHIU = (0x0F << 6) | OPC_MULTU,
+};
+
/* REGIMM (rt field) opcodes */
#define MASK_REGIMM(op) MASK_OP_MAJOR(op) | (op & (0x1F << 16))
@@ -774,9 +794,22 @@
generate_exception_err(ctx, EXCP_CpU, 1);
}
+/* Verify that the processor is running with COP1X instructions enabled.
+ This is associated with the nabla symbol in the MIPS32 and MIPS64
+ opcode tables. */
+
+static always_inline void check_cop1x(DisasContext *ctx)
+{
+ if (unlikely(!(ctx->hflags & MIPS_HFLAG_COP1X)))
+ generate_exception(ctx, EXCP_RI);
+}
+
+/* Verify that the processor is running with 64-bit floating-point
+ operations enabled. */
+
static always_inline void check_cp1_64bitmode(DisasContext *ctx)
{
- if (unlikely(!(ctx->hflags & MIPS_HFLAG_F64)))
+ if (unlikely(~ctx->hflags & (MIPS_HFLAG_F64 | MIPS_HFLAG_COP1X)))
generate_exception(ctx, EXCP_RI);
}
@@ -1530,6 +1563,80 @@
MIPS_DEBUG("%s %s %s", opn, regnames[rs], regnames[rt]);
}
+static void gen_mul_vr54xx (DisasContext *ctx, uint32_t opc,
+ int rd, int rs, int rt)
+{
+ const char *opn = "mul vr54xx";
+
+ GEN_LOAD_REG_T0(rs);
+ GEN_LOAD_REG_T1(rt);
+
+ switch (opc) {
+ case OPC_VR54XX_MULS:
+ gen_op_muls();
+ opn = "muls";
+ break;
+ case OPC_VR54XX_MULSU:
+ gen_op_mulsu();
+ opn = "mulsu";
+ break;
+ case OPC_VR54XX_MACC:
+ gen_op_macc();
+ opn = "macc";
+ break;
+ case OPC_VR54XX_MACCU:
+ gen_op_maccu();
+ opn = "maccu";
+ break;
+ case OPC_VR54XX_MSAC:
+ gen_op_msac();
+ opn = "msac";
+ break;
+ case OPC_VR54XX_MSACU:
+ gen_op_msacu();
+ opn = "msacu";
+ break;
+ case OPC_VR54XX_MULHI:
+ gen_op_mulhi();
+ opn = "mulhi";
+ break;
+ case OPC_VR54XX_MULHIU:
+ gen_op_mulhiu();
+ opn = "mulhiu";
+ break;
+ case OPC_VR54XX_MULSHI:
+ gen_op_mulshi();
+ opn = "mulshi";
+ break;
+ case OPC_VR54XX_MULSHIU:
+ gen_op_mulshiu();
+ opn = "mulshiu";
+ break;
+ case OPC_VR54XX_MACCHI:
+ gen_op_macchi();
+ opn = "macchi";
+ break;
+ case OPC_VR54XX_MACCHIU:
+ gen_op_macchiu();
+ opn = "macchiu";
+ break;
+ case OPC_VR54XX_MSACHI:
+ gen_op_msachi();
+ opn = "msachi";
+ break;
+ case OPC_VR54XX_MSACHIU:
+ gen_op_msachiu();
+ opn = "msachiu";
+ break;
+ default:
+ MIPS_INVAL("mul vr54xx");
+ generate_exception(ctx, EXCP_RI);
+ return;
+ }
+ GEN_STORE_T0_REG(rd);
+ MIPS_DEBUG("%s %s, %s, %s", opn, regnames[rd], regnames[rs], regnames[rt]);
+}
+
static void gen_cl (DisasContext *ctx, uint32_t opc,
int rd, int rs)
{
@@ -5084,12 +5191,14 @@
opn = "movn.s";
break;
case FOP(21, 16):
+ check_cop1x(ctx);
GEN_LOAD_FREG_FTN(WT0, fs);
gen_op_float_recip_s();
GEN_STORE_FTN_FREG(fd, WT2);
opn = "recip.s";
break;
case FOP(22, 16):
+ check_cop1x(ctx);
GEN_LOAD_FREG_FTN(WT0, fs);
gen_op_float_rsqrt_s();
GEN_STORE_FTN_FREG(fd, WT2);
@@ -5172,7 +5281,7 @@
GEN_LOAD_FREG_FTN(WT0, fs);
GEN_LOAD_FREG_FTN(WT1, ft);
if (ctx->opcode & (1 << 6)) {
- check_cp1_64bitmode(ctx);
+ check_cop1x(ctx);
gen_cmpabs_s(func-48, cc);
opn = condnames_abs[func-48];
} else {
@@ -5325,14 +5434,14 @@
opn = "movn.d";
break;
case FOP(21, 17):
- check_cp1_registers(ctx, fs | fd);
+ check_cp1_64bitmode(ctx);
GEN_LOAD_FREG_FTN(DT0, fs);
gen_op_float_recip_d();
GEN_STORE_FTN_FREG(fd, DT2);
opn = "recip.d";
break;
case FOP(22, 17):
- check_cp1_registers(ctx, fs | fd);
+ check_cp1_64bitmode(ctx);
GEN_LOAD_FREG_FTN(DT0, fs);
gen_op_float_rsqrt_d();
GEN_STORE_FTN_FREG(fd, DT2);
@@ -5387,7 +5496,8 @@
GEN_LOAD_FREG_FTN(DT0, fs);
GEN_LOAD_FREG_FTN(DT1, ft);
if (ctx->opcode & (1 << 6)) {
- check_cp1_64bitmode(ctx);
+ check_cop1x(ctx);
+ check_cp1_registers(ctx, fs | ft);
gen_cmpabs_d(func-48, cc);
opn = condnames_abs[func-48];
} else {
@@ -5720,8 +5830,6 @@
const char *opn = "extended float load/store";
int store = 0;
- /* All of those work only on 64bit FPUs. */
- check_cp1_64bitmode(ctx);
if (base == 0) {
if (index == 0)
gen_op_reset_T0();
@@ -5738,33 +5846,41 @@
memory access. */
switch (opc) {
case OPC_LWXC1:
+ check_cop1x(ctx);
op_ldst(lwc1);
GEN_STORE_FTN_FREG(fd, WT0);
opn = "lwxc1";
break;
case OPC_LDXC1:
+ check_cop1x(ctx);
+ check_cp1_registers(ctx, fd);
op_ldst(ldc1);
GEN_STORE_FTN_FREG(fd, DT0);
opn = "ldxc1";
break;
case OPC_LUXC1:
+ check_cp1_64bitmode(ctx);
op_ldst(luxc1);
GEN_STORE_FTN_FREG(fd, DT0);
opn = "luxc1";
break;
case OPC_SWXC1:
+ check_cop1x(ctx);
GEN_LOAD_FREG_FTN(WT0, fs);
op_ldst(swc1);
opn = "swxc1";
store = 1;
break;
case OPC_SDXC1:
+ check_cop1x(ctx);
+ check_cp1_registers(ctx, fs);
GEN_LOAD_FREG_FTN(DT0, fs);
op_ldst(sdc1);
opn = "sdxc1";
store = 1;
break;
case OPC_SUXC1:
+ check_cp1_64bitmode(ctx);
GEN_LOAD_FREG_FTN(DT0, fs);
op_ldst(suxc1);
opn = "suxc1";
@@ -5784,10 +5900,9 @@
{
const char *opn = "flt3_arith";
- /* All of those work only on 64bit FPUs. */
- check_cp1_64bitmode(ctx);
switch (opc) {
case OPC_ALNV_PS:
+ check_cp1_64bitmode(ctx);
GEN_LOAD_REG_T0(fr);
GEN_LOAD_FREG_FTN(DT0, fs);
GEN_LOAD_FREG_FTN(DT1, ft);
@@ -5796,6 +5911,7 @@
opn = "alnv.ps";
break;
case OPC_MADD_S:
+ check_cop1x(ctx);
GEN_LOAD_FREG_FTN(WT0, fs);
GEN_LOAD_FREG_FTN(WT1, ft);
GEN_LOAD_FREG_FTN(WT2, fr);
@@ -5804,6 +5920,8 @@
opn = "madd.s";
break;
case OPC_MADD_D:
+ check_cop1x(ctx);
+ check_cp1_registers(ctx, fd | fs | ft | fr);
GEN_LOAD_FREG_FTN(DT0, fs);
GEN_LOAD_FREG_FTN(DT1, ft);
GEN_LOAD_FREG_FTN(DT2, fr);
@@ -5812,6 +5930,7 @@
opn = "madd.d";
break;
case OPC_MADD_PS:
+ check_cp1_64bitmode(ctx);
GEN_LOAD_FREG_FTN(WT0, fs);
GEN_LOAD_FREG_FTN(WTH0, fs);
GEN_LOAD_FREG_FTN(WT1, ft);
@@ -5824,6 +5943,7 @@
opn = "madd.ps";
break;
case OPC_MSUB_S:
+ check_cop1x(ctx);
GEN_LOAD_FREG_FTN(WT0, fs);
GEN_LOAD_FREG_FTN(WT1, ft);
GEN_LOAD_FREG_FTN(WT2, fr);
@@ -5832,6 +5952,8 @@
opn = "msub.s";
break;
case OPC_MSUB_D:
+ check_cop1x(ctx);
+ check_cp1_registers(ctx, fd | fs | ft | fr);
GEN_LOAD_FREG_FTN(DT0, fs);
GEN_LOAD_FREG_FTN(DT1, ft);
GEN_LOAD_FREG_FTN(DT2, fr);
@@ -5840,6 +5962,7 @@
opn = "msub.d";
break;
case OPC_MSUB_PS:
+ check_cp1_64bitmode(ctx);
GEN_LOAD_FREG_FTN(WT0, fs);
GEN_LOAD_FREG_FTN(WTH0, fs);
GEN_LOAD_FREG_FTN(WT1, ft);
@@ -5852,6 +5975,7 @@
opn = "msub.ps";
break;
case OPC_NMADD_S:
+ check_cop1x(ctx);
GEN_LOAD_FREG_FTN(WT0, fs);
GEN_LOAD_FREG_FTN(WT1, ft);
GEN_LOAD_FREG_FTN(WT2, fr);
@@ -5860,6 +5984,8 @@
opn = "nmadd.s";
break;
case OPC_NMADD_D:
+ check_cop1x(ctx);
+ check_cp1_registers(ctx, fd | fs | ft | fr);
GEN_LOAD_FREG_FTN(DT0, fs);
GEN_LOAD_FREG_FTN(DT1, ft);
GEN_LOAD_FREG_FTN(DT2, fr);
@@ -5868,6 +5994,7 @@
opn = "nmadd.d";
break;
case OPC_NMADD_PS:
+ check_cp1_64bitmode(ctx);
GEN_LOAD_FREG_FTN(WT0, fs);
GEN_LOAD_FREG_FTN(WTH0, fs);
GEN_LOAD_FREG_FTN(WT1, ft);
@@ -5880,6 +6007,7 @@
opn = "nmadd.ps";
break;
case OPC_NMSUB_S:
+ check_cop1x(ctx);
GEN_LOAD_FREG_FTN(WT0, fs);
GEN_LOAD_FREG_FTN(WT1, ft);
GEN_LOAD_FREG_FTN(WT2, fr);
@@ -5888,6 +6016,8 @@
opn = "nmsub.s";
break;
case OPC_NMSUB_D:
+ check_cop1x(ctx);
+ check_cp1_registers(ctx, fd | fs | ft | fr);
GEN_LOAD_FREG_FTN(DT0, fs);
GEN_LOAD_FREG_FTN(DT1, ft);
GEN_LOAD_FREG_FTN(DT2, fr);
@@ -5896,6 +6026,7 @@
opn = "nmsub.d";
break;
case OPC_NMSUB_PS:
+ check_cp1_64bitmode(ctx);
GEN_LOAD_FREG_FTN(WT0, fs);
GEN_LOAD_FREG_FTN(WTH0, fs);
GEN_LOAD_FREG_FTN(WT1, ft);
@@ -5973,7 +6104,12 @@
gen_arith(env, ctx, op1, rd, rs, rt);
break;
case OPC_MULT ... OPC_DIVU:
- gen_muldiv(ctx, op1, rs, rt);
+ if (sa) {
+ check_insn(env, ctx, INSN_VR54XX);
+ op1 = MASK_MUL_VR54XX(ctx->opcode);
+ gen_mul_vr54xx(ctx, op1, rd, rs, rt);
+ } else
+ gen_muldiv(ctx, op1, rs, rt);
break;
case OPC_JR ... OPC_JALR:
gen_compute_branch(ctx, op1, rs, rd, sa);
@@ -6366,6 +6502,7 @@
#endif
case OPC_BC1ANY2:
case OPC_BC1ANY4:
+ check_cop1x(ctx);
check_insn(env, ctx, ASE_MIPS3D);
/* fall through */
case OPC_BC1:
Modified: trunk/src/host/qemu-neo1973/target-mips/translate_init.c
===================================================================
--- trunk/src/host/qemu-neo1973/target-mips/translate_init.c 2008-01-06 01:02:26 UTC (rev 3777)
+++ trunk/src/host/qemu-neo1973/target-mips/translate_init.c 2008-01-07 07:17:44 UTC (rev 3778)
@@ -21,12 +21,9 @@
/* CPU / CPU family specific config register values. */
-/* Have config1, is MIPS32R1, uses TLB, no virtual icache,
- uncached coherency */
+/* Have config1, uncached coherency */
#define MIPS_CONFIG0 \
- ((1 << CP0C0_M) | (0x0 << CP0C0_K23) | (0x0 << CP0C0_KU) | \
- (0x0 << CP0C0_AT) | (0x0 << CP0C0_AR) | (0x1 << CP0C0_MT) | \
- (0x2 << CP0C0_K0))
+ ((1 << CP0C0_M) | (0x2 << CP0C0_K0))
/* Have config2, no coprocessor2 attached, no MDMX support attached,
no performance counters, watch registers present,
@@ -41,7 +38,7 @@
#define MIPS_CONFIG2 \
((1 << CP0C2_M))
-/* No config4, no DSP ASE, no large physaddr,
+/* No config4, no DSP ASE, no large physaddr (PABITS),
no external interrupt controller, no vectored interupts,
no 1kb pages, no SmartMIPS ASE, no trace logic */
#define MIPS_CONFIG3 \
@@ -53,6 +50,18 @@
Define a major version 1, minor version 0. */
#define MIPS_FCR0 ((0 << FCR0_S) | (0x1 << FCR0_PRID) | (0x10 << FCR0_REV))
+/* MMU types, the first four entries have the same layout as the
+ CP0C0_MT field. */
+enum mips_mmu_types {
+ MMU_TYPE_NONE,
+ MMU_TYPE_R4000,
+ MMU_TYPE_RESERVED,
+ MMU_TYPE_FMT,
+ MMU_TYPE_R3000,
+ MMU_TYPE_R6000,
+ MMU_TYPE_R8000
+};
+
struct mips_def_t {
const unsigned char *name;
int32_t CP0_PRid;
@@ -69,6 +78,7 @@
int32_t CP0_SRSCtl;
int32_t CP1_fcr0;
int32_t SEGBITS;
+ int32_t PABITS;
int32_t CP0_SRSConf0_rw_bitmask;
int32_t CP0_SRSConf0;
int32_t CP0_SRSConf1_rw_bitmask;
@@ -80,6 +90,7 @@
int32_t CP0_SRSConf4_rw_bitmask;
int32_t CP0_SRSConf4;
int insn_flags;
+ enum mips_mmu_types mmu_type;
};
/*****************************************************************************/
@@ -89,7 +100,7 @@
{
.name = "4Kc",
.CP0_PRid = 0x00018000,
- .CP0_Config0 = MIPS_CONFIG0,
+ .CP0_Config0 = MIPS_CONFIG0 | (MMU_TYPE_R4000 << CP0C0_MT),
.CP0_Config1 = MIPS_CONFIG1 | (15 << CP0C1_MMU) |
(0 << CP0C1_IS) | (3 << CP0C1_IL) | (1 << CP0C1_IA) |
(0 << CP0C1_DS) | (3 << CP0C1_DL) | (1 << CP0C1_DA),
@@ -98,15 +109,17 @@
.SYNCI_Step = 32,
.CCRes = 2,
.CP0_Status_rw_bitmask = 0x1278FF17,
+ .SEGBITS = 32,
+ .PABITS = 32,
.insn_flags = CPU_MIPS32 | ASE_MIPS16,
+ .mmu_type = MMU_TYPE_R4000,
},
{
.name = "4Km",
.CP0_PRid = 0x00018300,
/* Config1 implemented, fixed mapping MMU,
no virtual icache, uncached coherency. */
- .CP0_Config0 = (1 << CP0C0_M) |
- (0x3 << CP0C0_MT) | (0x2 << CP0C0_K0),
+ .CP0_Config0 = MIPS_CONFIG0 | (MMU_TYPE_FMT << CP0C0_MT),
.CP0_Config1 = MIPS_CONFIG1 |
(0 << CP0C1_IS) | (3 << CP0C1_IL) | (1 << CP0C1_IA) |
(0 << CP0C1_DS) | (3 << CP0C1_DL) | (1 << CP0C1_DA),
@@ -115,12 +128,15 @@
.SYNCI_Step = 32,
.CCRes = 2,
.CP0_Status_rw_bitmask = 0x1258FF17,
+ .SEGBITS = 32,
+ .PABITS = 32,
.insn_flags = CPU_MIPS32 | ASE_MIPS16,
+ .mmu_type = MMU_TYPE_FMT,
},
{
.name = "4KEcR1",
.CP0_PRid = 0x00018400,
- .CP0_Config0 = MIPS_CONFIG0,
+ .CP0_Config0 = MIPS_CONFIG0 | (MMU_TYPE_R4000 << CP0C0_MT),
.CP0_Config1 = MIPS_CONFIG1 | (15 << CP0C1_MMU) |
(0 << CP0C1_IS) | (3 << CP0C1_IL) | (1 << CP0C1_IA) |
(0 << CP0C1_DS) | (3 << CP0C1_DL) | (1 << CP0C1_DA),
@@ -129,15 +145,15 @@
.SYNCI_Step = 32,
.CCRes = 2,
.CP0_Status_rw_bitmask = 0x1278FF17,
+ .SEGBITS = 32,
+ .PABITS = 32,
.insn_flags = CPU_MIPS32 | ASE_MIPS16,
+ .mmu_type = MMU_TYPE_R4000,
},
{
.name = "4KEmR1",
.CP0_PRid = 0x00018500,
- /* Config1 implemented, fixed mapping MMU,
- no virtual icache, uncached coherency. */
- .CP0_Config0 = (1 << CP0C0_M) |
- (0x3 << CP0C0_MT) | (0x2 << CP0C0_K0),
+ .CP0_Config0 = MIPS_CONFIG0 | (MMU_TYPE_FMT << CP0C0_MT),
.CP0_Config1 = MIPS_CONFIG1 |
(0 << CP0C1_IS) | (3 << CP0C1_IL) | (1 << CP0C1_IA) |
(0 << CP0C1_DS) | (3 << CP0C1_DL) | (1 << CP0C1_DA),
@@ -146,12 +162,16 @@
.SYNCI_Step = 32,
.CCRes = 2,
.CP0_Status_rw_bitmask = 0x1258FF17,
+ .SEGBITS = 32,
+ .PABITS = 32,
.insn_flags = CPU_MIPS32 | ASE_MIPS16,
+ .mmu_type = MMU_TYPE_FMT,
},
{
.name = "4KEc",
.CP0_PRid = 0x00019000,
- .CP0_Config0 = MIPS_CONFIG0 | (0x1 << CP0C0_AR),
+ .CP0_Config0 = MIPS_CONFIG0 | (0x1 << CP0C0_AR) |
+ (MMU_TYPE_R4000 << CP0C0_MT),
.CP0_Config1 = MIPS_CONFIG1 | (15 << CP0C1_MMU) |
(0 << CP0C1_IS) | (3 << CP0C1_IL) | (1 << CP0C1_IA) |
(0 << CP0C1_DS) | (3 << CP0C1_DL) | (1 << CP0C1_DA),
@@ -160,15 +180,16 @@
.SYNCI_Step = 32,
.CCRes = 2,
.CP0_Status_rw_bitmask = 0x1278FF17,
+ .SEGBITS = 32,
+ .PABITS = 32,
.insn_flags = CPU_MIPS32R2 | ASE_MIPS16,
+ .mmu_type = MMU_TYPE_R4000,
},
{
.name = "4KEm",
.CP0_PRid = 0x00019100,
- /* Config1 implemented, MIPS32R2, fixed mapping MMU,
- no virtual icache, uncached coherency. */
- .CP0_Config0 = (1 << CP0C0_M) | (0x1 << CP0C0_AR) |
- (0x3 << CP0C0_MT) | (0x2 << CP0C0_K0),
+ .CP0_Config0 = MIPS_CONFIG0 | (0x1 << CP0C0_AR) |
+ (MMU_TYPE_FMT << CP0C0_MT),
.CP0_Config1 = MIPS_CONFIG1 |
(0 << CP0C1_IS) | (3 << CP0C1_IL) | (1 << CP0C1_IA) |
(0 << CP0C1_DS) | (3 << CP0C1_DL) | (1 << CP0C1_DA),
@@ -177,12 +198,16 @@
.SYNCI_Step = 32,
.CCRes = 2,
.CP0_Status_rw_bitmask = 0x1258FF17,
+ .SEGBITS = 32,
+ .PABITS = 32,
.insn_flags = CPU_MIPS32R2 | ASE_MIPS16,
+ .mmu_type = MMU_TYPE_FMT,
},
{
.name = "24Kc",
.CP0_PRid = 0x00019300,
- .CP0_Config0 = MIPS_CONFIG0 | (0x1 << CP0C0_AR),
+ .CP0_Config0 = MIPS_CONFIG0 | (0x1 << CP0C0_AR) |
+ (MMU_TYPE_R4000 << CP0C0_MT),
.CP0_Config1 = MIPS_CONFIG1 | (15 << CP0C1_MMU) |
(0 << CP0C1_IS) | (3 << CP0C1_IL) | (1 << CP0C1_IA) |
(0 << CP0C1_DS) | (3 << CP0C1_DL) | (1 << CP0C1_DA),
@@ -192,12 +217,16 @@
.CCRes = 2,
/* No DSP implemented. */
.CP0_Status_rw_bitmask = 0x1278FF1F,
+ .SEGBITS = 32,
+ .PABITS = 32,
.insn_flags = CPU_MIPS32R2 | ASE_MIPS16,
+ .mmu_type = MMU_TYPE_R4000,
},
{
.name = "24Kf",
.CP0_PRid = 0x00019300,
- .CP0_Config0 = MIPS_CONFIG0 | (0x1 << CP0C0_AR),
+ .CP0_Config0 = MIPS_CONFIG0 | (0x1 << CP0C0_AR) |
+ (MMU_TYPE_R4000 << CP0C0_MT),
.CP0_Config1 = MIPS_CONFIG1 | (1 << CP0C1_FP) | (15 << CP0C1_MMU) |
(0 << CP0C1_IS) | (3 << CP0C1_IL) | (1 << CP0C1_IA) |
(0 << CP0C1_DS) | (3 << CP0C1_DL) | (1 << CP0C1_DA),
@@ -209,12 +238,16 @@
.CP0_Status_rw_bitmask = 0x3678FF1F,
.CP1_fcr0 = (1 << FCR0_F64) | (1 << FCR0_L) | (1 << FCR0_W) |
(1 << FCR0_D) | (1 << FCR0_S) | (0x93 << FCR0_PRID),
+ .SEGBITS = 32,
+ .PABITS = 32,
.insn_flags = CPU_MIPS32R2 | ASE_MIPS16,
+ .mmu_type = MMU_TYPE_R4000,
},
{
.name = "34Kf",
.CP0_PRid = 0x00019500,
- .CP0_Config0 = MIPS_CONFIG0 | (0x1 << CP0C0_AR),
+ .CP0_Config0 = MIPS_CONFIG0 | (0x1 << CP0C0_AR) |
+ (MMU_TYPE_R4000 << CP0C0_MT),
.CP0_Config1 = MIPS_CONFIG1 | (1 << CP0C1_FP) | (15 << CP0C1_MMU) |
(0 << CP0C1_IS) | (3 << CP0C1_IL) | (1 << CP0C1_IA) |
(0 << CP0C1_DS) | (3 << CP0C1_DL) | (1 << CP0C1_DA),
@@ -249,30 +282,50 @@
.CP0_SRSConf4_rw_bitmask = 0x3fffffff,
.CP0_SRSConf4 = (0x3fe << CP0SRSC4_SRS15) |
(0x3fe << CP0SRSC4_SRS14) | (0x3fe << CP0SRSC4_SRS13),
+ .SEGBITS = 32,
+ .PABITS = 32,
.insn_flags = CPU_MIPS32R2 | ASE_MIPS16 | ASE_DSP | ASE_MT,
+ .mmu_type = MMU_TYPE_R4000,
},
#if defined(TARGET_MIPS64)
{
.name = "R4000",
.CP0_PRid = 0x00000400,
- .CP0_Config0 = MIPS_CONFIG0 | (0x2 << CP0C0_AT),
- .CP0_Config1 = MIPS_CONFIG1 | (1 << CP0C1_FP) | (47 << CP0C1_MMU) |
- (0 << CP0C1_IS) | (3 << CP0C1_IL) | (1 << CP0C1_IA) |
- (0 << CP0C1_DS) | (3 << CP0C1_DL) | (1 << CP0C1_DA),
- .CP0_Config2 = MIPS_CONFIG2,
- .CP0_Config3 = MIPS_CONFIG3,
+ /* No L2 cache, icache size 8k, dcache size 8k, uncached coherency. */
+ .CP0_Config0 = (1 << 17) | (0x1 << 9) | (0x1 << 6) | (0x2 << CP0C0_K0),
+ /* Note: Config1 is only used internally, the R4000 has only Config0. */
+ .CP0_Config1 = (1 << CP0C1_FP) | (47 << CP0C1_MMU),
.SYNCI_Step = 16,
.CCRes = 2,
.CP0_Status_rw_bitmask = 0x3678FFFF,
- /* The R4000 has a full 64bit FPU doesn't use the fcr0 bits. */
+ /* The R4000 has a full 64bit FPU but doesn't use the fcr0 bits. */
.CP1_fcr0 = (0x5 << FCR0_PRID) | (0x0 << FCR0_REV),
.SEGBITS = 40,
+ .PABITS = 36,
.insn_flags = CPU_MIPS3,
+ .mmu_type = MMU_TYPE_R4000,
},
{
+ .name = "VR5432",
+ .CP0_PRid = 0x00005400,
+ /* No L2 cache, icache size 8k, dcache size 8k, uncached coherency. */
+ .CP0_Config0 = (1 << 17) | (0x1 << 9) | (0x1 << 6) | (0x2 << CP0C0_K0),
+ .CP0_Config1 = (1 << CP0C1_FP) | (47 << CP0C1_MMU),
+ .SYNCI_Step = 16,
+ .CCRes = 2,
+ .CP0_Status_rw_bitmask = 0x3678FFFF,
+ /* The VR5432 has a full 64bit FPU but doesn't use the fcr0 bits. */
+ .CP1_fcr0 = (0x54 << FCR0_PRID) | (0x0 << FCR0_REV),
+ .SEGBITS = 40,
+ .PABITS = 32,
+ .insn_flags = CPU_VR54XX,
+ .mmu_type = MMU_TYPE_R4000,
+ },
+ {
.name = "5Kc",
.CP0_PRid = 0x00018100,
- .CP0_Config0 = MIPS_CONFIG0 | (0x2 << CP0C0_AT),
+ .CP0_Config0 = MIPS_CONFIG0 | (0x2 << CP0C0_AT) |
+ (MMU_TYPE_R4000 << CP0C0_MT),
.CP0_Config1 = MIPS_CONFIG1 | (31 << CP0C1_MMU) |
(1 << CP0C1_IS) | (4 << CP0C1_IL) | (1 << CP0C1_IA) |
(1 << CP0C1_DS) | (4 << CP0C1_DL) | (1 << CP0C1_DA) |
@@ -283,12 +336,15 @@
.CCRes = 2,
.CP0_Status_rw_bitmask = 0x32F8FFFF,
.SEGBITS = 42,
+ .PABITS = 36,
.insn_flags = CPU_MIPS64,
+ .mmu_type = MMU_TYPE_R4000,
},
{
.name = "5Kf",
.CP0_PRid = 0x00018100,
- .CP0_Config0 = MIPS_CONFIG0 | (0x2 << CP0C0_AT),
+ .CP0_Config0 = MIPS_CONFIG0 | (0x2 << CP0C0_AT) |
+ (MMU_TYPE_R4000 << CP0C0_MT),
.CP0_Config1 = MIPS_CONFIG1 | (1 << CP0C1_FP) | (31 << CP0C1_MMU) |
(1 << CP0C1_IS) | (4 << CP0C1_IL) | (1 << CP0C1_IA) |
(1 << CP0C1_DS) | (4 << CP0C1_DL) | (1 << CP0C1_DA) |
@@ -302,14 +358,17 @@
.CP1_fcr0 = (1 << FCR0_D) | (1 << FCR0_S) |
(0x81 << FCR0_PRID) | (0x0 << FCR0_REV),
.SEGBITS = 42,
+ .PABITS = 36,
.insn_flags = CPU_MIPS64,
+ .mmu_type = MMU_TYPE_R4000,
},
{
.name = "20Kc",
/* We emulate a later version of the 20Kc, earlier ones had a broken
WAIT instruction. */
.CP0_PRid = 0x000182a0,
- .CP0_Config0 = MIPS_CONFIG0 | (0x2 << CP0C0_AT) | (1 << CP0C0_VI),
+ .CP0_Config0 = MIPS_CONFIG0 | (0x2 << CP0C0_AT) |
+ (MMU_TYPE_R4000 << CP0C0_MT) | (1 << CP0C0_VI),
.CP0_Config1 = MIPS_CONFIG1 | (1 << CP0C1_FP) | (47 << CP0C1_MMU) |
(2 << CP0C1_IS) | (4 << CP0C1_IL) | (3 << CP0C1_IA) |
(2 << CP0C1_DS) | (4 << CP0C1_DL) | (3 << CP0C1_DA) |
@@ -324,28 +383,36 @@
(1 << FCR0_D) | (1 << FCR0_S) |
(0x82 << FCR0_PRID) | (0x0 << FCR0_REV),
.SEGBITS = 40,
+ .PABITS = 36,
.insn_flags = CPU_MIPS64 | ASE_MIPS3D,
+ .mmu_type = MMU_TYPE_R4000,
},
{
/* A generic CPU providing MIPS64 Release 2 features.
FIXME: Eventually this should be replaced by a real CPU model. */
.name = "MIPS64R2-generic",
.CP0_PRid = 0x00010000,
- .CP0_Config0 = MIPS_CONFIG0 | (0x2 << CP0C0_AT) | (0x1 << CP0C0_AR),
+ .CP0_Config0 = MIPS_CONFIG0 | (0x1 << CP0C0_AR) | (0x2 << CP0C0_AT) |
+ (MMU_TYPE_R4000 << CP0C0_MT),
.CP0_Config1 = MIPS_CONFIG1 | (1 << CP0C1_FP) | (63 << CP0C1_MMU) |
(2 << CP0C1_IS) | (4 << CP0C1_IL) | (3 << CP0C1_IA) |
(2 << CP0C1_DS) | (4 << CP0C1_DL) | (3 << CP0C1_DA) |
(1 << CP0C1_PC) | (1 << CP0C1_WR) | (1 << CP0C1_EP),
.CP0_Config2 = MIPS_CONFIG2,
- .CP0_Config3 = MIPS_CONFIG3,
+ .CP0_Config3 = MIPS_CONFIG3 | (1 << CP0C3_LPA),
.SYNCI_Step = 32,
.CCRes = 2,
.CP0_Status_rw_bitmask = 0x36FBFFFF,
- .CP1_fcr0 = (1 << FCR0_3D) | (1 << FCR0_PS) | (1 << FCR0_L) |
- (1 << FCR0_W) | (1 << FCR0_D) | (1 << FCR0_S) |
- (0x00 << FCR0_PRID) | (0x0 << FCR0_REV),
- .SEGBITS = 40,
+ .CP1_fcr0 = (1 << FCR0_F64) | (1 << FCR0_3D) | (1 << FCR0_PS) |
+ (1 << FCR0_L) | (1 << FCR0_W) | (1 << FCR0_D) |
+ (1 << FCR0_S) | (0x00 << FCR0_PRID) | (0x0 << FCR0_REV),
+ .SEGBITS = 42,
+ /* The architectural limit is 59, but we have hardcoded 36 bit
+ in some places...
+ .PABITS = 59, */ /* the architectural limit */
+ .PABITS = 36,
.insn_flags = CPU_MIPS64R2 | ASE_MIPS3D,
+ .mmu_type = MMU_TYPE_R4000,
},
#endif
};
@@ -399,20 +466,19 @@
{
env->tlb = qemu_mallocz(sizeof(CPUMIPSTLBContext));
- /* There are more full-featured MMU variants in older MIPS CPUs,
- R3000, R6000 and R8000 come to mind. If we ever support them,
- this check will need to look up a different place than those
- newfangled config registers. */
- switch ((env->CP0_Config0 >> CP0C0_MT) & 3) {
- case 0:
+ switch (def->mmu_type) {
+ case MMU_TYPE_NONE:
no_mmu_init(env, def);
break;
- case 1:
+ case MMU_TYPE_R4000:
r4k_mmu_init(env, def);
break;
- case 3:
+ case MMU_TYPE_FMT:
fixed_mmu_init(env, def);
break;
+ case MMU_TYPE_R3000:
+ case MMU_TYPE_R6000:
+ case MMU_TYPE_R8000:
default:
cpu_abort(env, "MMU type not supported\n");
}
@@ -477,17 +543,16 @@
env->CP0_Status_rw_bitmask = def->CP0_Status_rw_bitmask;
env->CP0_TCStatus_rw_bitmask = def->CP0_TCStatus_rw_bitmask;
env->CP0_SRSCtl = def->CP0_SRSCtl;
+ env->SEGBITS = def->SEGBITS;
+ env->SEGMask = (target_ulong)((1ULL << def->SEGBITS) - 1);
#if defined(TARGET_MIPS64)
- if (def->insn_flags & ISA_MIPS3)
- {
+ if (def->insn_flags & ISA_MIPS3) {
env->hflags |= MIPS_HFLAG_64;
- env->SEGBITS = def->SEGBITS;
- env->SEGMask = (3ULL << 62) | ((1ULL << def->SEGBITS) - 1);
- } else {
- env->SEGBITS = 32;
- env->SEGMask = 0xFFFFFFFF;
+ env->SEGMask |= 3ULL << 62;
}
#endif
+ env->PABITS = def->PABITS;
+ env->PAMask = (target_ulong)((1ULL << def->PABITS) - 1);
env->CP0_SRSConf0_rw_bitmask = def->CP0_SRSConf0_rw_bitmask;
env->CP0_SRSConf0 = def->CP0_SRSConf0;
env->CP0_SRSConf1_rw_bitmask = def->CP0_SRSConf1_rw_bitmask;
Modified: trunk/src/host/qemu-neo1973/target-sparc/helper.c
===================================================================
--- trunk/src/host/qemu-neo1973/target-sparc/helper.c 2008-01-06 01:02:26 UTC (rev 3777)
+++ trunk/src/host/qemu-neo1973/target-sparc/helper.c 2008-01-07 07:17:44 UTC (rev 3778)
@@ -129,7 +129,7 @@
/* SPARC reference MMU table walk: Context table->L1->L2->PTE */
/* Context base + context number */
- pde_ptr = (env->mmuregs[1] << 4) + (env->mmuregs[2] << 2);
+ pde_ptr = ((env->mmuregs[1] & ~63)<< 4) + (env->mmuregs[2] << 2);
pde = ldl_phys(pde_ptr);
/* Ctx pde */
Modified: trunk/src/host/qemu-neo1973/target-sparc/op_helper.c
===================================================================
--- trunk/src/host/qemu-neo1973/target-sparc/op_helper.c 2008-01-06 01:02:26 UTC (rev 3777)
+++ trunk/src/host/qemu-neo1973/target-sparc/op_helper.c 2008-01-07 07:17:44 UTC (rev 3778)
@@ -6,6 +6,7 @@
//#define DEBUG_MXCC
//#define DEBUG_UNALIGNED
//#define DEBUG_UNASSIGNED
+//#define DEBUG_ASI
#ifdef DEBUG_MMU
#define DPRINTF_MMU(fmt, args...) \
@@ -21,6 +22,13 @@
#define DPRINTF_MXCC(fmt, args...)
#endif
+#ifdef DEBUG_ASI
+#define DPRINTF_ASI(fmt, args...) \
+do { printf("ASI: " fmt , ##args); } while (0)
+#else
+#define DPRINTF_ASI(fmt, args...)
+#endif
+
void raise_exception(int tt)
{
env->exception_index = tt;
@@ -229,11 +237,34 @@
}
#endif
+#ifdef DEBUG_ASI
+static void dump_asi(const char * txt, uint32_t addr, int asi, int size,
+ uint32_t r1, uint32_t r2)
+{
+ switch (size)
+ {
+ case 1:
+ DPRINTF_ASI("%s %08x asi 0x%02x = %02x\n", txt, addr, asi, r1 & 0xff);
+ break;
+ case 2:
+ DPRINTF_ASI("%s %08x asi 0x%02x = %04x\n", txt, addr, asi, r1 & 0xffff);
+ break;
+ case 4:
+ DPRINTF_ASI("%s %08x asi 0x%02x = %08x\n", txt, addr, asi, r1);
+ break;
+ case 8:
+ DPRINTF_ASI("%s %08x asi 0x%02x = %016llx\n", txt, addr, asi,
+ r2 | ((uint64_t)r1 << 32));
+ break;
+ }
+}
+#endif
+
void helper_ld_asi(int asi, int size, int sign)
{
uint32_t ret = 0;
uint64_t tmp;
-#ifdef DEBUG_MXCC
+#if defined(DEBUG_MXCC) || defined(DEBUG_ASI)
uint32_t last_T0 = T0;
#endif
@@ -306,6 +337,10 @@
DPRINTF_MMU("mmu_read: reg[%d] = 0x%08x\n", reg, ret);
}
break;
+ case 5: // Turbosparc ITLB Diagnostic
+ case 6: // Turbosparc DTLB Diagnostic
+ case 7: // Turbosparc IOTLB Diagnostic
+ break;
case 9: /* Supervisor code access */
switch(size) {
case 1:
@@ -387,8 +422,7 @@
break;
}
break;
- case 0x2e: /* MMU passthrough, 0xexxxxxxxx */
- case 0x2f: /* MMU passthrough, 0xfxxxxxxxx */
+ case 0x21 ... 0x2f: /* MMU passthrough, 0x100000000 to 0xfffffffff */
switch(size) {
case 1:
ret = ldub_phys((target_phys_addr_t)T0
@@ -411,12 +445,15 @@
break;
}
break;
+ case 0x30: // Turbosparc secondary cache diagnostic
+ case 0x31: // Turbosparc RAM snoop
+ case 0x32: // Turbosparc page table descriptor diagnostic
case 0x39: /* data cache diagnostic register */
ret = 0;
break;
- case 0x21 ... 0x2d: /* MMU passthrough, unassigned */
+ case 8: /* User code access, XXX */
default:
- do_unassigned_access(T0, 0, 0, 1);
+ do_unassigned_access(T0, 0, 0, asi);
ret = 0;
break;
}
@@ -435,6 +472,9 @@
}
else
T1 = ret;
+#ifdef DEBUG_ASI
+ dump_asi("read ", last_T0, asi, size, T1, T0);
+#endif
}
void helper_st_asi(int asi, int size)
@@ -542,8 +582,8 @@
#ifdef DEBUG_MMU
dump_mmu(env);
#endif
- return;
}
+ break;
case 4: /* write MMU regs */
{
int reg = (T0 >> 8) & 0x1f;
@@ -587,8 +627,12 @@
#ifdef DEBUG_MMU
dump_mmu(env);
#endif
- return;
}
+ break;
+ case 5: // Turbosparc ITLB Diagnostic
+ case 6: // Turbosparc DTLB Diagnostic
+ case 7: // Turbosparc IOTLB Diagnostic
+ break;
case 0xa: /* User data access */
switch(size) {
case 1:
@@ -646,7 +690,7 @@
stl_kernel(dst, temp);
}
}
- return;
+ break;
case 0x1f: /* Block fill, stda access */
{
// value (T1, T2)
@@ -661,7 +705,7 @@
for (i = 0; i < 32; i += 8, dst += 8)
stq_kernel(dst, val);
}
- return;
+ break;
case 0x20: /* MMU passthrough */
{
switch(size) {
@@ -680,9 +724,8 @@
break;
}
}
- return;
- case 0x2e: /* MMU passthrough, 0xexxxxxxxx */
- case 0x2f: /* MMU passthrough, 0xfxxxxxxxx */
+ break;
+ case 0x21 ... 0x2f: /* MMU passthrough, 0x100000000 to 0xfffffffff */
{
switch(size) {
case 1:
@@ -705,21 +748,25 @@
break;
}
}
- return;
- case 0x30: /* store buffer tags */
- case 0x31: /* store buffer data or Ross RT620 I-cache flush */
- case 0x32: /* store buffer control */
+ break;
+ case 0x30: // store buffer tags or Turbosparc secondary cache diagnostic
+ case 0x31: // store buffer data, Ross RT620 I-cache flush or
+ // Turbosparc snoop RAM
+ case 0x32: // store buffer control or Turbosparc page table descriptor diagnostic
case 0x36: /* I-cache flash clear */
case 0x37: /* D-cache flash clear */
case 0x38: /* breakpoint diagnostics */
case 0x4c: /* breakpoint action */
break;
+ case 8: /* User code access, XXX */
case 9: /* Supervisor code access, XXX */
- case 0x21 ... 0x2d: /* MMU passthrough, unassigned */
default:
- do_unassigned_access(T0, 1, 0, 1);
- return;
+ do_unassigned_access(T0, 1, 0, asi);
+ break;
}
+#ifdef DEBUG_ASI
+ dump_asi("write", T0, asi, size, T1, T2);
+#endif
}
#endif /* CONFIG_USER_ONLY */
@@ -1646,13 +1693,66 @@
}
#ifdef TARGET_SPARC64
+#ifdef DEBUG_PCALL
+static const char * const excp_names[0x50] = {
+ [TT_TFAULT] = "Instruction Access Fault",
+ [TT_TMISS] = "Instruction Access MMU Miss",
+ [TT_CODE_ACCESS] = "Instruction Access Error",
+ [TT_ILL_INSN] = "Illegal Instruction",
+ [TT_PRIV_INSN] = "Privileged Instruction",
+ [TT_NFPU_INSN] = "FPU Disabled",
+ [TT_FP_EXCP] = "FPU Exception",
+ [TT_TOVF] = "Tag Overflow",
+ [TT_CLRWIN] = "Clean Windows",
+ [TT_DIV_ZERO] = "Division By Zero",
+ [TT_DFAULT] = "Data Access Fault",
+ [TT_DMISS] = "Data Access MMU Miss",
+ [TT_DATA_ACCESS] = "Data Access Error",
+ [TT_DPROT] = "Data Protection Error",
+ [TT_UNALIGNED] = "Unaligned Memory Access",
+ [TT_PRIV_ACT] = "Privileged Action",
+ [TT_EXTINT | 0x1] = "External Interrupt 1",
+ [TT_EXTINT | 0x2] = "External Interrupt 2",
+ [TT_EXTINT | 0x3] = "External Interrupt 3",
+ [TT_EXTINT | 0x4] = "External Interrupt 4",
+ [TT_EXTINT | 0x5] = "External Interrupt 5",
+ [TT_EXTINT | 0x6] = "External Interrupt 6",
+ [TT_EXTINT | 0x7] = "External Interrupt 7",
+ [TT_EXTINT | 0x8] = "External Interrupt 8",
+ [TT_EXTINT | 0x9] = "External Interrupt 9",
+ [TT_EXTINT | 0xa] = "External Interrupt 10",
+ [TT_EXTINT | 0xb] = "External Interrupt 11",
+ [TT_EXTINT | 0xc] = "External Interrupt 12",
+ [TT_EXTINT | 0xd] = "External Interrupt 13",
+ [TT_EXTINT | 0xe] = "External Interrupt 14",
+ [TT_EXTINT | 0xf] = "External Interrupt 15",
+};
+#endif
+
void do_interrupt(int intno)
{
#ifdef DEBUG_PCALL
if (loglevel & CPU_LOG_INT) {
static int count;
- fprintf(logfile, "%6d: v=%04x pc=%016" PRIx64 " npc=%016" PRIx64 " SP=%016" PRIx64 "\n",
- count, intno,
+ const char *name;
+
+ if (intno < 0 || intno >= 0x180 || (intno > 0x4f && intno < 0x80))
+ name = "Unknown";
+ else if (intno >= 0x100)
+ name = "Trap Instruction";
+ else if (intno >= 0xc0)
+ name = "Window Fill";
+ else if (intno >= 0x80)
+ name = "Window Spill";
+ else {
+ name = excp_names[intno];
+ if (!name)
+ name = "Unknown";
+ }
+
+ fprintf(logfile, "%6d: %s (v=%04x) pc=%016" PRIx64 " npc=%016" PRIx64
+ " SP=%016" PRIx64 "\n",
+ count, name, intno,
env->pc,
env->npc, env->regwptr[6]);
cpu_dump_state(env, logfile, fprintf, 0);
@@ -1705,6 +1805,41 @@
env->exception_index = 0;
}
#else
+#ifdef DEBUG_PCALL
+static const char * const excp_names[0x80] = {
+ [TT_TFAULT] = "Instruction Access Fault",
+ [TT_ILL_INSN] = "Illegal Instruction",
+ [TT_PRIV_INSN] = "Privileged Instruction",
+ [TT_NFPU_INSN] = "FPU Disabled",
+ [TT_WIN_OVF] = "Window Overflow",
+ [TT_WIN_UNF] = "Window Underflow",
+ [TT_UNALIGNED] = "Unaligned Memory Access",
+ [TT_FP_EXCP] = "FPU Exception",
+ [TT_DFAULT] = "Data Access Fault",
+ [TT_TOVF] = "Tag Overflow",
+ [TT_EXTINT | 0x1] = "External Interrupt 1",
+ [TT_EXTINT | 0x2] = "External Interrupt 2",
+ [TT_EXTINT | 0x3] = "External Interrupt 3",
+ [TT_EXTINT | 0x4] = "External Interrupt 4",
+ [TT_EXTINT | 0x5] = "External Interrupt 5",
+ [TT_EXTINT | 0x6] = "External Interrupt 6",
+ [TT_EXTINT | 0x7] = "External Interrupt 7",
+ [TT_EXTINT | 0x8] = "External Interrupt 8",
+ [TT_EXTINT | 0x9] = "External Interrupt 9",
+ [TT_EXTINT | 0xa] = "External Interrupt 10",
+ [TT_EXTINT | 0xb] = "External Interrupt 11",
+ [TT_EXTINT | 0xc] = "External Interrupt 12",
+ [TT_EXTINT | 0xd] = "External Interrupt 13",
+ [TT_EXTINT | 0xe] = "External Interrupt 14",
+ [TT_EXTINT | 0xf] = "External Interrupt 15",
+ [TT_TOVF] = "Tag Overflow",
+ [TT_CODE_ACCESS] = "Instruction Access Error",
+ [TT_DATA_ACCESS] = "Data Access Error",
+ [TT_DIV_ZERO] = "Division By Zero",
+ [TT_NCP_INSN] = "Coprocessor Disabled",
+};
+#endif
+
void do_interrupt(int intno)
{
int cwp;
@@ -1712,8 +1847,20 @@
#ifdef DEBUG_PCALL
if (loglevel & CPU_LOG_INT) {
static int count;
- fprintf(logfile, "%6d: v=%02x pc=%08x npc=%08x SP=%08x\n",
- count, intno,
+ const char *name;
+
+ if (intno < 0 || intno >= 0x100)
+ name = "Unknown";
+ else if (intno >= 0x80)
+ name = "Trap Instruction";
+ else {
+ name = excp_names[intno];
+ if (!name)
+ name = "Unknown";
+ }
+
+ fprintf(logfile, "%6d: %s (v=%02x) pc=%08x npc=%08x SP=%08x\n",
+ count, name, intno,
env->pc,
env->npc, env->regwptr[6]);
cpu_dump_state(env, logfile, fprintf, 0);
@@ -1832,6 +1979,17 @@
generated code */
saved_env = env;
env = cpu_single_env;
+#ifdef DEBUG_UNASSIGNED
+ if (is_asi)
+ printf("Unassigned mem %s access to " TARGET_FMT_plx " asi 0x%02x from "
+ TARGET_FMT_lx "\n",
+ is_exec ? "exec" : is_write ? "write" : "read", addr, is_asi,
+ env->pc);
+ else
+ printf("Unassigned mem %s access to " TARGET_FMT_plx " from "
+ TARGET_FMT_lx "\n",
+ is_exec ? "exec" : is_write ? "write" : "read", addr, env->pc);
+#endif
if (env->mmuregs[3]) /* Fault status register */
env->mmuregs[3] = 1; /* overflow (not read before another fault) */
if (is_asi)
@@ -1845,10 +2003,6 @@
env->mmuregs[3] |= (5 << 2) | 2;
env->mmuregs[4] = addr; /* Fault address register */
if ((env->mmuregs[0] & MMU_E) && !(env->mmuregs[0] & MMU_NF)) {
-#ifdef DEBUG_UNASSIGNED
- printf("Unassigned mem access to " TARGET_FMT_plx " from " TARGET_FMT_lx
- "\n", addr, env->pc);
-#endif
if (is_exec)
raise_exception(TT_CODE_ACCESS);
else
Modified: trunk/src/host/qemu-neo1973/vl.c
===================================================================
--- trunk/src/host/qemu-neo1973/vl.c 2008-01-06 01:02:26 UTC (rev 3777)
+++ trunk/src/host/qemu-neo1973/vl.c 2008-01-07 07:17:44 UTC (rev 3778)
@@ -1,7 +1,7 @@
/*
* QEMU System Emulator
*
- * Copyright (c) 2003-2007 Fabrice Bellard
+ * Copyright (c) 2003-2008 Fabrice Bellard
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
@@ -828,7 +828,7 @@
};
#define ALARM_FLAG_DYNTICKS 0x1
-#define ALARM_FLAG_MODIFIED 0x2
+#define ALARM_FLAG_EXPIRED 0x2
static inline int alarm_has_dynticks(struct qemu_alarm_timer *t)
{
@@ -840,11 +840,6 @@
if (!alarm_has_dynticks(t))
return;
- if (!(t->flags & ALARM_FLAG_MODIFIED))
- return;
-
- t->flags &= ~(ALARM_FLAG_MODIFIED);
-
t->rearm(t);
}
@@ -1018,8 +1013,6 @@
{
QEMUTimer **pt, *t;
- alarm_timer->flags |= ALARM_FLAG_MODIFIED;
-
/* NOTE: this code must be signal safe because
qemu_timer_expired() can be called from a signal. */
pt = &active_timers[ts->clock->type];
@@ -1058,6 +1051,11 @@
ts->expire_time = expire_time;
ts->next = *pt;
*pt = ts;
+
+ /* Rearm if necessary */
+ if ((alarm_timer->flags & ALARM_FLAG_EXPIRED) == 0 &&
+ pt == &active_timers[ts->clock->type])
+ qemu_rearm_alarm_timer(alarm_timer);
}
#ifdef TIMER_DEBUG
@@ -1218,12 +1216,13 @@
#endif
CPUState *env = next_cpu;
+ alarm_timer->flags |= ALARM_FLAG_EXPIRED;
+
/* FIXME Ugly hack only to make usb-gadgetfs work */
if (!alarm_has_dynticks(alarm_timer) && !cpu_single_env)
return;
if (env) {
- alarm_timer->flags |= ALARM_FLAG_MODIFIED;
/* stop the currently executing cpu because a timer occured */
cpu_interrupt(env, CPU_INTERRUPT_EXIT);
#ifdef USE_KQEMU
@@ -1408,7 +1407,7 @@
if (!active_timers[QEMU_TIMER_REALTIME] &&
!active_timers[QEMU_TIMER_VIRTUAL])
- return;
+ return;
nearest_delta_us = qemu_next_deadline();
@@ -1535,7 +1534,7 @@
if (!active_timers[QEMU_TIMER_REALTIME] &&
!active_timers[QEMU_TIMER_VIRTUAL])
- return;
+ return;
nearest_delta_us = qemu_next_deadline();
nearest_delta_us /= 1000;
@@ -7651,7 +7650,10 @@
qemu_run_timers(&active_timers[QEMU_TIMER_REALTIME],
qemu_get_clock(rt_clock));
- qemu_rearm_alarm_timer(alarm_timer);
+ if (alarm_timer->flags & ALARM_FLAG_EXPIRED) {
+ alarm_timer->flags &= ~(ALARM_FLAG_EXPIRED);
+ qemu_rearm_alarm_timer(alarm_timer);
+ }
/* Check bottom-halves last in case any of the earlier events triggered
them. */
@@ -7741,7 +7743,7 @@
static void help(int exitcode)
{
- printf("QEMU PC emulator version " QEMU_VERSION ", Copyright (c) 2003-2007 Fabrice Bellard\n"
+ printf("QEMU PC emulator version " QEMU_VERSION ", Copyright (c) 2003-2008 Fabrice Bellard\n"
"usage: %s [options] [disk_image]\n"
"\n"
"'disk_image' is a raw hard image image for IDE hard disk 0\n"
@@ -8150,6 +8152,9 @@
qemu_register_machine(&ss10_machine);
qemu_register_machine(&ss600mp_machine);
qemu_register_machine(&ss20_machine);
+ qemu_register_machine(&ss2_machine);
+ qemu_register_machine(&ss1000_machine);
+ qemu_register_machine(&ss2000_machine);
#endif
#elif defined(TARGET_ARM)
qemu_register_machine(&integratorcp_machine);
More information about the commitlog
mailing list