r3387 - in trunk/src/host/qemu-neo1973: . audio darwin-user hw linux-user slirp target-alpha target-i386 target-mips target-ppc target-sparc tests
andrew at sita.openmoko.org
andrew at sita.openmoko.org
Fri Nov 9 18:12:53 CET 2007
Author: andrew
Date: 2007-11-09 18:12:19 +0100 (Fri, 09 Nov 2007)
New Revision: 3387
Added:
trunk/src/host/qemu-neo1973/audio/.cvsignore
trunk/src/host/qemu-neo1973/slirp/.cvsignore
Removed:
trunk/src/host/qemu-neo1973/target-i386/translate-copy.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/audio/audio.h
trunk/src/host/qemu-neo1973/configure
trunk/src/host/qemu-neo1973/cpu-all.h
trunk/src/host/qemu-neo1973/cpu-exec.c
trunk/src/host/qemu-neo1973/darwin-user/main.c
trunk/src/host/qemu-neo1973/darwin-user/signal.c
trunk/src/host/qemu-neo1973/dyngen.c
trunk/src/host/qemu-neo1973/exec-all.h
trunk/src/host/qemu-neo1973/exec.c
trunk/src/host/qemu-neo1973/host-utils.c
trunk/src/host/qemu-neo1973/host-utils.h
trunk/src/host/qemu-neo1973/hw/fdc.c
trunk/src/host/qemu-neo1973/hw/grackle_pci.c
trunk/src/host/qemu-neo1973/hw/i2c.c
trunk/src/host/qemu-neo1973/hw/ide.c
trunk/src/host/qemu-neo1973/hw/mac_nvram.c
trunk/src/host/qemu-neo1973/hw/macio.c
trunk/src/host/qemu-neo1973/hw/mc146818rtc.c
trunk/src/host/qemu-neo1973/hw/omap.c
trunk/src/host/qemu-neo1973/hw/omap.h
trunk/src/host/qemu-neo1973/hw/omap1_clk.c
trunk/src/host/qemu-neo1973/hw/omap_mmc.c
trunk/src/host/qemu-neo1973/hw/palm.c
trunk/src/host/qemu-neo1973/hw/pc.c
trunk/src/host/qemu-neo1973/hw/ppc_chrp.c
trunk/src/host/qemu-neo1973/hw/ppc_mac.h
trunk/src/host/qemu-neo1973/hw/ppc_oldworld.c
trunk/src/host/qemu-neo1973/hw/slavio_misc.c
trunk/src/host/qemu-neo1973/hw/sun4m.c
trunk/src/host/qemu-neo1973/hw/tsc210x.c
trunk/src/host/qemu-neo1973/linux-user/main.c
trunk/src/host/qemu-neo1973/linux-user/mmap.c
trunk/src/host/qemu-neo1973/linux-user/qemu.h
trunk/src/host/qemu-neo1973/linux-user/signal.c
trunk/src/host/qemu-neo1973/linux-user/strace.c
trunk/src/host/qemu-neo1973/linux-user/syscall_defs.h
trunk/src/host/qemu-neo1973/qemu-doc.texi
trunk/src/host/qemu-neo1973/slirp/misc.h
trunk/src/host/qemu-neo1973/slirp/slirp.h
trunk/src/host/qemu-neo1973/slirp/tcp_subr.c
trunk/src/host/qemu-neo1973/target-alpha/op.c
trunk/src/host/qemu-neo1973/target-i386/cpu.h
trunk/src/host/qemu-neo1973/target-i386/helper.c
trunk/src/host/qemu-neo1973/target-i386/helper2.c
trunk/src/host/qemu-neo1973/target-i386/translate.c
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/op_mem.c
trunk/src/host/qemu-neo1973/target-mips/op_template.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-ppc/cpu.h
trunk/src/host/qemu-neo1973/target-ppc/exec.h
trunk/src/host/qemu-neo1973/target-ppc/helper.c
trunk/src/host/qemu-neo1973/target-ppc/helper_regs.h
trunk/src/host/qemu-neo1973/target-ppc/op.c
trunk/src/host/qemu-neo1973/target-ppc/op_helper.c
trunk/src/host/qemu-neo1973/target-ppc/op_helper.h
trunk/src/host/qemu-neo1973/target-ppc/translate.c
trunk/src/host/qemu-neo1973/target-ppc/translate_init.c
trunk/src/host/qemu-neo1973/target-sparc/cpu.h
trunk/src/host/qemu-neo1973/target-sparc/helper.c
trunk/src/host/qemu-neo1973/target-sparc/op_helper.c
trunk/src/host/qemu-neo1973/target-sparc/translate.c
trunk/src/host/qemu-neo1973/tests/qruncom.c
trunk/src/host/qemu-neo1973/translate-all.c
trunk/src/host/qemu-neo1973/vl.c
trunk/src/host/qemu-neo1973/vl.h
Log:
Sync with cvs.savannah.nongnu.org:/sources/qemu.
Modified: trunk/src/host/qemu-neo1973/Changelog
===================================================================
--- trunk/src/host/qemu-neo1973/Changelog 2007-11-09 16:32:22 UTC (rev 3386)
+++ trunk/src/host/qemu-neo1973/Changelog 2007-11-09 17:12:19 UTC (rev 3387)
@@ -5,7 +5,7 @@
- CPU model selection support (J. Mayer, Paul Brook, Herve Poussineau)
- Several Sparc fixes (Aurelien Jarno, Blue Swirl, Robert Reif)
- MIPS 64-bit FPU support (Thiemo Seufer)
- - Xscale PDA emulation (Andrzei Zaborowski)
+ - Xscale PDA emulation (Andrzej Zaborowski)
- ColdFire system emulation (Paul Brook)
- Improved SH4 support (Magnus Damm)
- MIPS64 support (Aurelien Jarno, Thiemo Seufer)
@@ -16,6 +16,7 @@
- SPARC32PLUS execution support (Blue Swirl)
- MIPS mipssim pequdo machine (Thiemo Seufer)
- Strace for Linux userland emulation (Stuart Anderson, Thayne Harbaugh)
+ - OMAP310 MPU emulation plus Palm T|E machine (Andrzej Zaborowski)
version 0.9.0:
Modified: trunk/src/host/qemu-neo1973/Makefile
===================================================================
--- trunk/src/host/qemu-neo1973/Makefile 2007-11-09 16:32:22 UTC (rev 3386)
+++ trunk/src/host/qemu-neo1973/Makefile 2007-11-09 17:12:19 UTC (rev 3387)
@@ -11,7 +11,9 @@
BASE_CFLAGS += $(OS_CFLAGS) $(ARCH_CFLAGS)
BASE_LDFLAGS += $(OS_LDFLAGS) $(ARCH_LDFLAGS)
-CPPFLAGS += -I. -D_GNU_SOURCE -D_FILE_OFFSET_BITS=64 -D_LARGEFILE_SOURCE
+CPPFLAGS += -I. -I$(SRC_PATH) -MMD -MP
+CPPFLAGS += -D_GNU_SOURCE -D_FILE_OFFSET_BITS=64 -D_LARGEFILE_SOURCE
+CPPFLAGS += -DQEMU_TOOL
LIBS=
ifdef CONFIG_STATIC
BASE_LDFLAGS += -static
@@ -25,23 +27,99 @@
LIBS+=$(AIOLIBS)
-all: $(TOOLS) $(DOCS) recurse-all $(MODEM)
+all: libqemu_common.a $(TOOLS) $(DOCS) recurse-all $(MODEM)
subdir-%: dyngen$(EXESUF)
$(MAKE) -C $(subst subdir-,,$@) all
recurse-all: $(patsubst %,subdir-%, $(TARGET_DIRS))
-qemu-img$(EXESUF): qemu-img.c cutils.c block.c block-raw.c block-cow.c block-qcow.c aes.c block-vmdk.c block-cloop.c block-dmg.c block-bochs.c block-vpc.c block-vvfat.c block-qcow2.c block-parallels.c
- $(CC) -DQEMU_TOOL $(CFLAGS) $(CPPFLAGS) $(BASE_CFLAGS) $(LDFLAGS) $(BASE_LDFLAGS) -o $@ $^ -lz $(LIBS)
+######################################################################
+# libqemu_common.a: target indepedent part of system emulation. The
+# long term path is to suppress *all* target specific code in case of
+# system emulation, i.e. a single QEMU executable should support all
+# CPUs and machines.
+OBJS+=cutils.o readline.o console.o
+#OBJS+=block.o block-raw.o
+OBJS+=block-cow.o block-qcow.o aes.o block-vmdk.o block-cloop.o block-dmg.o block-bochs.o block-vpc.o block-vvfat.o block-qcow2.o block-parallels.o
+
+ifdef CONFIG_WIN32
+OBJS+=tap-win32.o
+endif
+
+AUDIO_OBJS = audio.o noaudio.o wavaudio.o mixeng.o
+ifdef CONFIG_SDL
+AUDIO_OBJS += sdlaudio.o
+endif
+ifdef CONFIG_OSS
+AUDIO_OBJS += ossaudio.o
+endif
+ifdef CONFIG_COREAUDIO
+AUDIO_OBJS += coreaudio.o
+endif
+ifdef CONFIG_ALSA
+AUDIO_OBJS += alsaaudio.o
+endif
+ifdef CONFIG_DSOUND
+AUDIO_OBJS += dsoundaudio.o
+endif
+ifdef CONFIG_FMOD
+AUDIO_OBJS += fmodaudio.o
+audio/audio.o audio/fmodaudio.o: CPPFLAGS := -I$(CONFIG_FMOD_INC) $(CPPFLAGS)
+endif
+AUDIO_OBJS+= wavcapture.o
+OBJS+=$(addprefix audio/, $(AUDIO_OBJS))
+
+ifdef CONFIG_SDL
+OBJS+=sdl.o x_keymap.o
+endif
+OBJS+=vnc.o d3des.o
+
+ifdef CONFIG_COCOA
+OBJS+=cocoa.o
+endif
+
+ifdef CONFIG_SLIRP
+CPPFLAGS+=-I$(SRC_PATH)/slirp
+SLIRP_OBJS=cksum.o if.o ip_icmp.o ip_input.o ip_output.o \
+slirp.o mbuf.o misc.o sbuf.o socket.o tcp_input.o tcp_output.o \
+tcp_subr.o tcp_timer.o udp.o bootp.o debug.o tftp.o
+OBJS+=$(addprefix slirp/, $(SLIRP_OBJS))
+endif
+
+cocoa.o: cocoa.m
+ $(CC) $(CFLAGS) $(CPPFLAGS) $(BASE_CFLAGS) -c -o $@ $<
+
+sdl.o: sdl.c keymaps.c sdl_keysym.h
+ $(CC) $(CFLAGS) $(CPPFLAGS) $(SDL_CFLAGS) $(BASE_CFLAGS) -c -o $@ $<
+
+vnc.o: vnc.c keymaps.c sdl_keysym.h vnchextile.h d3des.c d3des.h
+ $(CC) $(CFLAGS) $(CPPFLAGS) $(BASE_CFLAGS) -c -o $@ $<
+
+audio/sdlaudio.o: audio/sdlaudio.c
+ $(CC) $(CFLAGS) $(CPPFLAGS) $(SDL_CFLAGS) $(BASE_CFLAGS) -c -o $@ $<
+
+libqemu_common.a: $(OBJS)
+ rm -f $@
+ $(AR) rcs $@ $(OBJS)
+
+######################################################################
+
+qemu-img$(EXESUF): qemu-img.o block.o block-raw.o libqemu_common.a
+ $(CC) $(LDFLAGS) $(BASE_LDFLAGS) -o $@ $^ -lz $(LIBS)
+
+%.o: %.c
+ $(CC) $(CFLAGS) $(CPPFLAGS) $(BASE_CFLAGS) -c -o $@ $<
+
+# dyngen host tool
+dyngen$(EXESUF): dyngen.c
+ $(HOST_CC) $(CFLAGS) $(CPPFLAGS) $(BASE_CFLAGS) -o $@ $^
+
phonesim: phonesim/phonesim
phonesim/phonesim:
$(MAKE) -C phonesim
-dyngen$(EXESUF): dyngen.c
- $(HOST_CC) $(CFLAGS) $(CPPFLAGS) $(BASE_CFLAGS) -o $@ $^
-
raw2flash$(EXESUF) flash2raw$(EXESUF): raw2flash.c
$(CC) -D$@ $(CFLAGS) $(LDFLAGS) $(DEFINES) -o $@ $^
for m in $(MODELS); do \
@@ -52,7 +130,8 @@
clean:
# avoid old build problems by removing potentially incorrect old files
rm -f config.mak config.h op-i386.h opc-i386.h gen-op-i386.h op-arm.h opc-arm.h gen-op-arm.h
- rm -f *.o *.a $(TOOLS) dyngen$(EXESUF) TAGS cscope.* *.pod *~ */*~
+ rm -f *.o *.d *.a $(TOOLS) dyngen$(EXESUF) TAGS cscope.* *.pod *~ */*~
+ rm -f slirp/*.o slirp/*.d audio/*.o audio/*.d
$(MAKE) -C tests clean
for d in $(TARGET_DIRS); do \
$(MAKE) -C $$d $@ || exit 1 ; \
@@ -197,3 +276,6 @@
ifneq ($(wildcard .depend),)
include .depend
endif
+
+# Include automatically generated dependency files
+-include $(wildcard *.d audio/*.d slirp/*.d)
Modified: trunk/src/host/qemu-neo1973/Makefile.target
===================================================================
--- trunk/src/host/qemu-neo1973/Makefile.target 2007-11-09 16:32:22 UTC (rev 3386)
+++ trunk/src/host/qemu-neo1973/Makefile.target 2007-11-09 17:12:19 UTC (rev 3387)
@@ -23,7 +23,7 @@
TARGET_BASE_ARCH:=sparc
endif
TARGET_PATH=$(SRC_PATH)/target-$(TARGET_BASE_ARCH)
-VPATH=$(SRC_PATH):$(TARGET_PATH):$(SRC_PATH)/hw:$(SRC_PATH)/audio
+VPATH=$(SRC_PATH):$(TARGET_PATH):$(SRC_PATH)/hw
CPPFLAGS=-I. -I.. -I$(TARGET_PATH) -I$(SRC_PATH) -MMD -MP
ifdef CONFIG_DARWIN_USER
VPATH+=:$(SRC_PATH)/darwin-user
@@ -302,10 +302,7 @@
ifeq ($(TARGET_ARCH), i386)
LIBOBJS+=helper.o helper2.o
-ifeq ($(ARCH), i386)
-LIBOBJS+=translate-copy.o
endif
-endif
ifeq ($(TARGET_ARCH), x86_64)
LIBOBJS+=helper.o helper2.o
@@ -399,43 +396,25 @@
endif
# must use static linking to avoid leaving stuff in virtual address space
-VL_OBJS=vl.o osdep.o readline.o monitor.o pci.o console.o loader.o isa_mmio.o
-VL_OBJS+=cutils.o
+VL_OBJS=vl.o osdep.o monitor.o pci.o loader.o isa_mmio.o
+# XXX: suppress QEMU_TOOL tests
VL_OBJS+=block.o block-raw.o
-VL_OBJS+=block-cow.o block-qcow.o aes.o block-vmdk.o block-cloop.o block-dmg.o block-bochs.o block-vpc.o block-vvfat.o block-qcow2.o block-parallels.o
VL_OBJS+=irq.o
-ifdef CONFIG_WIN32
-VL_OBJS+=tap-win32.o
-endif
-SOUND_HW = sb16.o es1370.o
-AUDIODRV = audio.o noaudio.o wavaudio.o mixeng.o
-ifdef CONFIG_SDL
-AUDIODRV += sdlaudio.o
-endif
-ifdef CONFIG_OSS
-AUDIODRV += ossaudio.o
-endif
-ifdef CONFIG_COREAUDIO
-AUDIODRV += coreaudio.o
-endif
ifdef CONFIG_ALSA
-AUDIODRV += alsaaudio.o
LIBS += -lasound
endif
ifdef CONFIG_DSOUND
-AUDIODRV += dsoundaudio.o
LIBS += -lole32 -ldxguid
endif
ifdef CONFIG_FMOD
-AUDIODRV += fmodaudio.o
-audio.o fmodaudio.o: CPPFLAGS := -I$(CONFIG_FMOD_INC) $(CPPFLAGS)
LIBS += $(CONFIG_FMOD_LIB)
endif
+
+SOUND_HW = sb16.o es1370.o
ifdef CONFIG_ADLIB
SOUND_HW += fmopl.o adlib.o
endif
-AUDIODRV+= wavcapture.o
ifdef CONFIG_VNC_TLS
CPPFLAGS += $(CONFIG_VNC_TLS_CFLAGS)
@@ -470,7 +449,7 @@
ifeq ($(TARGET_BASE_ARCH), i386)
# Hardware support
-VL_OBJS+= ide.o pckbd.o ps2.o vga.o $(SOUND_HW) dma.o $(AUDIODRV)
+VL_OBJS+= ide.o pckbd.o ps2.o vga.o $(SOUND_HW) dma.o
VL_OBJS+= fdc.o mc146818rtc.o serial.o i8259.o i8254.o pcspk.o pc.o
VL_OBJS+= cirrus_vga.o apic.o parallel.o acpi.o piix_pci.o
VL_OBJS+= usb-uhci.o smbus_eeprom.o vmmouse.o vmport.o vmware_vga.o
@@ -479,7 +458,7 @@
ifeq ($(TARGET_BASE_ARCH), ppc)
CPPFLAGS += -DHAS_AUDIO -DHAS_AUDIO_CHOICE
# shared objects
-VL_OBJS+= ppc.o ide.o vga.o $(SOUND_HW) dma.o openpic.o $(AUDIODRV)
+VL_OBJS+= ppc.o ide.o vga.o $(SOUND_HW) dma.o openpic.o
# PREP target
VL_OBJS+= pckbd.o ps2.o serial.o i8259.o i8254.o fdc.o m48t59.o mc146818rtc.o
VL_OBJS+= prep_pci.o ppc_prep.o
@@ -497,7 +476,7 @@
VL_OBJS+= mips_timer.o mips_int.o dma.o vga.o serial.o i8254.o i8259.o
VL_OBJS+= jazz_led.o
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 smbus_eeprom.o parallel.o mixeng.o cirrus_vga.o $(SOUND_HW) $(AUDIODRV)
+VL_OBJS+= piix_pci.o smbus_eeprom.o parallel.o cirrus_vga.o $(SOUND_HW)
VL_OBJS+= mipsnet.o
CPPFLAGS += -DHAS_AUDIO
endif
@@ -526,12 +505,12 @@
VL_OBJS+= arm-semi.o
VL_OBJS+= pxa2xx.o pxa2xx_pic.o pxa2xx_gpio.o pxa2xx_timer.o pxa2xx_dma.o
VL_OBJS+= pxa2xx_lcd.o pxa2xx_mmci.o pxa2xx_pcmcia.o max111x.o max7310.o
-VL_OBJS+= spitz.o ads7846.o ide.o serial.o nand.o ecc.o
-VL_OBJS+= $(AUDIODRV) wm8750.o wm8753.o
+VL_OBJS+= spitz.o ads7846.o ide.o serial.o nand.o ecc.o wm8750.o wm8753.o
VL_OBJS+= s3c2410.o s3c24xx_gpio.o s3c24xx_lcd.o s3c24xx_mmci.o s3c24xx_rtc.o
VL_OBJS+= s3c24xx_udc.o neo1973.o pcf5060x.o jbt6k74.o gps.o
VL_OBJS+= $(GSM_OBJS) modem.o
-VL_OBJS+= omap.o omap_lcdc.o omap1_clk.o omap_mmc.o palm.o tsc210x.o
+VL_OBJS+= omap.o omap_lcdc.o omap1_clk.o omap_mmc.o omap_i2c.o
+VL_OBJS+= palm.o tsc210x.o
CPPFLAGS+= -DHAS_AUDIO $(GSM_CPPFLAGS)
endif
ifeq ($(TARGET_BASE_ARCH), sh4)
@@ -545,12 +524,7 @@
ifdef CONFIG_GDBSTUB
VL_OBJS+=gdbstub.o
endif
-ifdef CONFIG_SDL
-VL_OBJS+=sdl.o x_keymap.o
-endif
-VL_OBJS+=vnc.o d3des.o
ifdef CONFIG_COCOA
-VL_OBJS+=cocoa.o
COCOA_LIBS=-F/System/Library/Frameworks -framework Cocoa -framework IOKit
ifdef CONFIG_COREAUDIO
COCOA_LIBS+=-framework CoreAudio
@@ -558,10 +532,6 @@
endif
ifdef CONFIG_SLIRP
CPPFLAGS+=-I$(SRC_PATH)/slirp
-SLIRP_OBJS=cksum.o if.o ip_icmp.o ip_input.o ip_output.o \
-slirp.o mbuf.o misc.o sbuf.o socket.o tcp_input.o tcp_output.o \
-tcp_subr.o tcp_timer.o udp.o bootp.o debug.o tftp.o
-VL_OBJS+=$(addprefix slirp/, $(SLIRP_OBJS))
endif
VL_LDFLAGS=$(VL_OS_LDFLAGS)
@@ -600,21 +570,9 @@
SDL_LIBS := $(filter-out -mwindows, $(SDL_LIBS)) -mconsole
endif
-$(QEMU_SYSTEM): $(VL_OBJS) libqemu.a
+$(QEMU_SYSTEM): $(VL_OBJS) ../libqemu_common.a libqemu.a
$(CC) $(VL_LDFLAGS) $(LDFLAGS) -o $@ $^ $(LIBS) $(SDL_LIBS) $(COCOA_LIBS) $(VL_LIBS)
-cocoa.o: cocoa.m
- $(CC) $(CFLAGS) $(CPPFLAGS) $(BASE_CFLAGS) -c -o $@ $<
-
-sdl.o: sdl.c keymaps.c sdl_keysym.h
- $(CC) $(CFLAGS) $(CPPFLAGS) $(SDL_CFLAGS) $(BASE_CFLAGS) -c -o $@ $<
-
-vnc.o: vnc.c keymaps.c sdl_keysym.h vnchextile.h d3des.c d3des.h
- $(CC) $(CFLAGS) $(CPPFLAGS) $(BASE_CFLAGS) -c -o $@ $<
-
-sdlaudio.o: sdlaudio.c
- $(CC) $(CFLAGS) $(CPPFLAGS) $(SDL_CFLAGS) $(BASE_CFLAGS) -c -o $@ $<
-
depend: $(SRCS)
$(CC) -MM $(CFLAGS) $(CPPFLAGS) $(BASE_CFLAGS) $^ 1>.depend
@@ -671,7 +629,7 @@
$(CC) $(CPPFLAGS) -c -o $@ $<
clean:
- rm -f *.o *.a *~ $(PROGS) gen-op.h opc.h op.h nwfpe/*.o slirp/*.o fpu/*.o
+ rm -f *.o *.a *~ $(PROGS) gen-op.h opc.h op.h nwfpe/*.o fpu/*.o
rm -f *.d */*.d
install: all
Added: trunk/src/host/qemu-neo1973/audio/.cvsignore
===================================================================
--- trunk/src/host/qemu-neo1973/audio/.cvsignore 2007-11-09 16:32:22 UTC (rev 3386)
+++ trunk/src/host/qemu-neo1973/audio/.cvsignore 2007-11-09 17:12:19 UTC (rev 3387)
@@ -0,0 +1 @@
+*.d
Modified: trunk/src/host/qemu-neo1973/audio/audio.h
===================================================================
--- trunk/src/host/qemu-neo1973/audio/audio.h 2007-11-09 16:32:22 UTC (rev 3386)
+++ trunk/src/host/qemu-neo1973/audio/audio.h 2007-11-09 17:12:19 UTC (rev 3387)
@@ -24,7 +24,7 @@
#ifndef QEMU_AUDIO_H
#define QEMU_AUDIO_H
-#include "config.h"
+#include "config-host.h"
#include "sys-queue.h"
typedef void (*audio_callback_fn_t) (void *opaque, int avail);
Modified: trunk/src/host/qemu-neo1973/configure
===================================================================
--- trunk/src/host/qemu-neo1973/configure 2007-11-09 16:32:22 UTC (rev 3386)
+++ trunk/src/host/qemu-neo1973/configure 2007-11-09 17:12:19 UTC (rev 3387)
@@ -316,7 +316,8 @@
if [ "$bsd" = "yes" -o "$darwin" = "yes" -o "$mingw32" = "yes" ] ; then
AIOLIBS=
else
- AIOLIBS="-lrt"
+ # Some Linux architectures (e.g. s390) don't imply -lpthread automatically.
+ AIOLIBS="-lrt -lpthread"
fi
# default flags for all hosts
@@ -951,6 +952,29 @@
if [ "$build_docs" = "yes" ] ; then
echo "BUILD_DOCS=yes" >> $config_mak
fi
+if test "$static" = "yes"; then
+ sdl1=$sdl_static
+else
+ sdl1=$sdl
+fi
+if test "$sdl1" = "yes" ; then
+ echo "#define CONFIG_SDL 1" >> $config_h
+ echo "CONFIG_SDL=yes" >> $config_mak
+ if test "$target_softmmu" = "no" -o "$static" = "yes"; then
+ echo "SDL_LIBS=$sdl_static_libs" >> $config_mak
+ else
+ echo "SDL_LIBS=`$sdl_config --libs`" >> $config_mak
+ fi
+ if [ "${aa}" = "yes" ] ; then
+ echo "SDL_CFLAGS=`$sdl_config --cflags` `aalib-config --cflags`" >> $config_mak
+ else
+ echo "SDL_CFLAGS=`$sdl_config --cflags`" >> $config_mak
+ fi
+fi
+if test "$cocoa" = "yes" ; then
+ echo "#define CONFIG_COCOA 1" >> $config_h
+ echo "CONFIG_COCOA=yes" >> $config_mak
+fi
# XXX: suppress that
if [ "$bsd" = "yes" ] ; then
@@ -1041,9 +1065,6 @@
if test "$target" = "arm-linux-user" -o "$target" = "armeb-linux-user" ; then
mkdir -p $target_dir/nwfpe
fi
-if test "$target_user_only" = "no" ; then
- mkdir -p $target_dir/slirp
-fi
if test "$target" = "arm-softmmu" ; then
mkdir -p $target_dir/gnokiigsm
fi
@@ -1138,16 +1159,18 @@
echo "TARGET_ARCH=mips" >> $config_mak
echo "#define TARGET_ARCH \"mips\"" >> $config_h
echo "#define TARGET_MIPS 1" >> $config_h
+ echo "#define TARGET_ABI_MIPSO32 1" >> $config_h
elif test "$target_cpu" = "mipsn32" -o "$target_cpu" = "mipsn32el" ; then
echo "TARGET_ARCH=mipsn32" >> $config_mak
echo "#define TARGET_ARCH \"mipsn32\"" >> $config_h
echo "#define TARGET_MIPS 1" >> $config_h
- echo "#define TARGET_MIPSN32 1" >> $config_h
+ echo "#define TARGET_ABI_MIPSN32 1" >> $config_h
elif test "$target_cpu" = "mips64" -o "$target_cpu" = "mips64el" ; then
echo "TARGET_ARCH=mips64" >> $config_mak
echo "#define TARGET_ARCH \"mips64\"" >> $config_h
echo "#define TARGET_MIPS 1" >> $config_h
echo "#define TARGET_MIPS64 1" >> $config_h
+ echo "#define TARGET_ABI_MIPSN64 1" >> $config_h
elif test "$target_cpu" = "cris" ; then
echo "TARGET_ARCH=cris" >> $config_mak
echo "#define TARGET_ARCH \"cris\"" >> $config_h
@@ -1206,42 +1229,14 @@
echo "TARGET_HAS_ELFLOAD32=yes" >> $config_mak
echo "#define TARGET_HAS_ELFLOAD32 1" >> $config_h
fi
-# sdl defines
-if test "$target_user_only" = "no"; then
- if test "$target_softmmu" = "no" -o "$static" = "yes"; then
- sdl1=$sdl_static
- else
- sdl1=$sdl
- fi
- if test "$sdl1" = "yes" ; then
- echo "#define CONFIG_SDL 1" >> $config_h
- echo "CONFIG_SDL=yes" >> $config_mak
- if test "$target_softmmu" = "no" -o "$static" = "yes"; then
- echo "SDL_LIBS=$sdl_static_libs" >> $config_mak
- else
- echo "SDL_LIBS=`$sdl_config --libs`" >> $config_mak
- fi
- if [ "${aa}" = "yes" ] ; then
- echo "SDL_CFLAGS=`$sdl_config --cflags` `aalib-config --cflags`" >> $config_mak
- else
- echo "SDL_CFLAGS=`$sdl_config --cflags`" >> $config_mak
- fi
- fi
-fi
-
-if test "$cocoa" = "yes" ; then
- echo "#define CONFIG_COCOA 1" >> $config_h
- echo "CONFIG_COCOA=yes" >> $config_mak
-fi
-
test -f ${config_h}~ && cmp -s $config_h ${config_h}~ && mv ${config_h}~ $config_h
done # for target in $targets
# build tree in object directory if source path is different from current one
if test "$source_path_used" = "yes" ; then
- DIRS="tests tests/cris"
+ DIRS="tests tests/cris slirp audio"
FILES="Makefile tests/Makefile"
FILES="$FILES tests/cris/Makefile tests/cris/.gdbinit"
for dir in $DIRS ; do
Modified: trunk/src/host/qemu-neo1973/cpu-all.h
===================================================================
--- trunk/src/host/qemu-neo1973/cpu-all.h 2007-11-09 16:32:22 UTC (rev 3386)
+++ trunk/src/host/qemu-neo1973/cpu-all.h 2007-11-09 17:12:19 UTC (rev 3387)
@@ -691,6 +691,7 @@
int page_get_flags(target_ulong address);
void page_set_flags(target_ulong start, target_ulong end, int flags);
void page_unprotect_range(target_ulong data, target_ulong data_size);
+int page_check_range(target_ulong start, target_ulong len, int flags);
CPUState *cpu_copy(CPUState *env);
Modified: trunk/src/host/qemu-neo1973/cpu-exec.c
===================================================================
--- trunk/src/host/qemu-neo1973/cpu-exec.c 2007-11-09 16:32:22 UTC (rev 3386)
+++ trunk/src/host/qemu-neo1973/cpu-exec.c 2007-11-09 17:12:19 UTC (rev 3387)
@@ -181,10 +181,8 @@
flags = (((env->pstate & PS_PEF) >> 1) | ((env->fprs & FPRS_FEF) << 2))
| (env->pstate & PS_PRIV) | ((env->lsu & (DMMU_E | IMMU_E)) >> 2);
#else
- // FPU enable . MMU Boot . MMU enabled . MMU no-fault . Supervisor
- flags = (env->psref << 4) | (((env->mmuregs[0] & MMU_BM) >> 14) << 3)
- | ((env->mmuregs[0] & (MMU_E | MMU_NF)) << 1)
- | env->psrs;
+ // FPU enable . Supervisor
+ flags = (env->psref << 4) | env->psrs;
#endif
cs_base = env->npc;
pc = env->pc;
@@ -614,19 +612,9 @@
#if USE_KQEMU
(env->kqemu_enabled != 2) &&
#endif
- tb->page_addr[1] == -1
-#if defined(TARGET_I386) && defined(USE_CODE_COPY)
- && (tb->cflags & CF_CODE_COPY) ==
- (((TranslationBlock *)(T0 & ~3))->cflags & CF_CODE_COPY)
-#endif
- ) {
+ tb->page_addr[1] == -1) {
spin_lock(&tb_lock);
tb_add_jump((TranslationBlock *)(long)(T0 & ~3), T0 & 3, tb);
-#if defined(USE_CODE_COPY)
- /* propagates the FP use info */
- ((TranslationBlock *)(T0 & ~3))->cflags |=
- (tb->cflags & CF_FP_USED);
-#endif
spin_unlock(&tb_lock);
}
}
@@ -650,80 +638,6 @@
: /* no outputs */
: "r" (gen_func)
: "r1", "r2", "r3", "r8", "r9", "r10", "r12", "r14");
-#elif defined(TARGET_I386) && defined(USE_CODE_COPY)
-{
- if (!(tb->cflags & CF_CODE_COPY)) {
- if ((tb->cflags & CF_FP_USED) && env->native_fp_regs) {
- save_native_fp_state(env);
- }
- gen_func();
- } else {
- if ((tb->cflags & CF_FP_USED) && !env->native_fp_regs) {
- restore_native_fp_state(env);
- }
- /* we work with native eflags */
- CC_SRC = cc_table[CC_OP].compute_all();
- CC_OP = CC_OP_EFLAGS;
- asm(".globl exec_loop\n"
- "\n"
- "debug1:\n"
- " pushl %%ebp\n"
- " fs movl %10, %9\n"
- " fs movl %11, %%eax\n"
- " andl $0x400, %%eax\n"
- " fs orl %8, %%eax\n"
- " pushl %%eax\n"
- " popf\n"
- " fs movl %%esp, %12\n"
- " fs movl %0, %%eax\n"
- " fs movl %1, %%ecx\n"
- " fs movl %2, %%edx\n"
- " fs movl %3, %%ebx\n"
- " fs movl %4, %%esp\n"
- " fs movl %5, %%ebp\n"
- " fs movl %6, %%esi\n"
- " fs movl %7, %%edi\n"
- " fs jmp *%9\n"
- "exec_loop:\n"
- " fs movl %%esp, %4\n"
- " fs movl %12, %%esp\n"
- " fs movl %%eax, %0\n"
- " fs movl %%ecx, %1\n"
- " fs movl %%edx, %2\n"
- " fs movl %%ebx, %3\n"
- " fs movl %%ebp, %5\n"
- " fs movl %%esi, %6\n"
- " fs movl %%edi, %7\n"
- " pushf\n"
- " popl %%eax\n"
- " movl %%eax, %%ecx\n"
- " andl $0x400, %%ecx\n"
- " shrl $9, %%ecx\n"
- " andl $0x8d5, %%eax\n"
- " fs movl %%eax, %8\n"
- " movl $1, %%eax\n"
- " subl %%ecx, %%eax\n"
- " fs movl %%eax, %11\n"
- " fs movl %9, %%ebx\n" /* get T0 value */
- " popl %%ebp\n"
- :
- : "m" (*(uint8_t *)offsetof(CPUState, regs[0])),
- "m" (*(uint8_t *)offsetof(CPUState, regs[1])),
- "m" (*(uint8_t *)offsetof(CPUState, regs[2])),
- "m" (*(uint8_t *)offsetof(CPUState, regs[3])),
- "m" (*(uint8_t *)offsetof(CPUState, regs[4])),
- "m" (*(uint8_t *)offsetof(CPUState, regs[5])),
- "m" (*(uint8_t *)offsetof(CPUState, regs[6])),
- "m" (*(uint8_t *)offsetof(CPUState, regs[7])),
- "m" (*(uint8_t *)offsetof(CPUState, cc_src)),
- "m" (*(uint8_t *)offsetof(CPUState, tmp0)),
- "a" (gen_func),
- "m" (*(uint8_t *)offsetof(CPUState, df)),
- "m" (*(uint8_t *)offsetof(CPUState, saved_esp))
- : "%ecx", "%edx"
- );
- }
-}
#elif defined(__ia64)
struct fptr {
void *ip;
@@ -761,11 +675,6 @@
#if defined(TARGET_I386)
-#if defined(USE_CODE_COPY)
- if (env->native_fp_regs) {
- save_native_fp_state(env);
- }
-#endif
/* restore flags in standard format */
env->eflags = env->eflags | cc_table[CC_OP].compute_all() | (DF & DF_MASK);
#elif defined(TARGET_ARM)
@@ -1277,26 +1186,6 @@
# define ERROR_sig(context) ((context)->uc_mcontext.gregs[REG_ERR])
#endif
-#if defined(USE_CODE_COPY)
-static void cpu_send_trap(unsigned long pc, int trap,
- struct ucontext *uc)
-{
- TranslationBlock *tb;
-
- if (cpu_single_env)
- env = cpu_single_env; /* XXX: find a correct solution for multithread */
- /* now we have a real cpu fault */
- tb = tb_find_pc(pc);
- if (tb) {
- /* the PC is inside the translated code. It means that we have
- a virtual CPU fault */
- cpu_restore_state(tb, env, pc, uc);
- }
- sigprocmask(SIG_SETMASK, &uc->uc_sigmask, NULL);
- raise_exception_err(trap, env->error_code);
-}
-#endif
-
int cpu_signal_handler(int host_signum, void *pinfo,
void *puc)
{
@@ -1313,17 +1202,10 @@
#endif
pc = EIP_sig(uc);
trapno = TRAP_sig(uc);
-#if defined(TARGET_I386) && defined(USE_CODE_COPY)
- if (trapno == 0x00 || trapno == 0x05) {
- /* send division by zero or bound exception */
- cpu_send_trap(pc, trapno, uc);
- return 1;
- } else
-#endif
- return handle_cpu_signal(pc, (unsigned long)info->si_addr,
- trapno == 0xe ?
- (ERROR_sig(uc) >> 1) & 1 : 0,
- &uc->uc_sigmask, puc);
+ return handle_cpu_signal(pc, (unsigned long)info->si_addr,
+ trapno == 0xe ?
+ (ERROR_sig(uc) >> 1) & 1 : 0,
+ &uc->uc_sigmask, puc);
}
#elif defined(__x86_64__)
Modified: trunk/src/host/qemu-neo1973/darwin-user/main.c
===================================================================
--- trunk/src/host/qemu-neo1973/darwin-user/main.c 2007-11-09 16:32:22 UTC (rev 3386)
+++ trunk/src/host/qemu-neo1973/darwin-user/main.c 2007-11-09 17:12:19 UTC (rev 3387)
@@ -757,9 +757,6 @@
"-s size set the stack size in bytes (default=%ld)\n"
"\n"
"debug options:\n"
-#ifdef USE_CODE_COPY
- "-no-code-copy disable code copy acceleration\n"
-#endif
"-d options activate log (logfile='%s')\n"
"-g wait for gdb on port 1234\n"
"-p pagesize set the host page size to 'pagesize'\n",
@@ -845,11 +842,6 @@
if (!strcmp(r, "g")) {
use_gdbstub = 1;
} else
-#ifdef USE_CODE_COPY
- if (!strcmp(r, "no-code-copy")) {
- code_copy_enabled = 0;
- } else
-#endif
{
usage();
}
Modified: trunk/src/host/qemu-neo1973/darwin-user/signal.c
===================================================================
--- trunk/src/host/qemu-neo1973/darwin-user/signal.c 2007-11-09 16:32:22 UTC (rev 3386)
+++ trunk/src/host/qemu-neo1973/darwin-user/signal.c 2007-11-09 17:12:19 UTC (rev 3387)
@@ -198,11 +198,7 @@
/* the CPU emulator uses some host signals to detect exceptions,
we we forward to it some signals */
- if (host_signum == SIGSEGV || host_signum == SIGBUS
-#if defined(TARGET_I386) && defined(USE_CODE_COPY)
- || host_signum == SIGFPE
-#endif
- ) {
+ if (host_signum == SIGSEGV || host_signum == SIGBUS) {
if (cpu_signal_handler(host_signum, (void*)info, puc))
return;
}
Modified: trunk/src/host/qemu-neo1973/dyngen.c
===================================================================
--- trunk/src/host/qemu-neo1973/dyngen.c 2007-11-09 16:32:22 UTC (rev 3386)
+++ trunk/src/host/qemu-neo1973/dyngen.c 2007-11-09 17:12:19 UTC (rev 3387)
@@ -701,6 +701,8 @@
uint32_t *n_strtab;
EXE_SYM *sym;
EXE_RELOC *rel;
+ const char *p;
+ int aux_size, j;
fd = open(filename, O_RDONLY
#ifdef _WIN32
@@ -727,7 +729,6 @@
sdata = malloc(sizeof(void *) * fhdr.f_nscns);
memset(sdata, 0, sizeof(void *) * fhdr.f_nscns);
- const char *p;
for(i = 0;i < fhdr.f_nscns; i++) {
sec = &shdr[i];
if (!strstart(sec->s_name, ".bss", &p))
@@ -771,7 +772,6 @@
/* set coff symbol */
symtab = malloc(sizeof(struct coff_sym) * nb_syms);
- int aux_size, j;
for (i = 0, ext_sym = coff_symtab, sym = symtab; i < nb_syms; i++, ext_sym++, sym++) {
memset(sym, 0, sizeof(*sym));
sym->st_syment = ext_sym;
Modified: trunk/src/host/qemu-neo1973/exec-all.h
===================================================================
--- trunk/src/host/qemu-neo1973/exec-all.h 2007-11-09 16:32:22 UTC (rev 3386)
+++ trunk/src/host/qemu-neo1973/exec-all.h 2007-11-09 17:12:19 UTC (rev 3387)
@@ -91,9 +91,6 @@
extern FILE *logfile;
extern int loglevel;
-void muls64(int64_t *phigh, int64_t *plow, int64_t a, int64_t b);
-void mulu64(uint64_t *phigh, uint64_t *plow, uint64_t a, uint64_t b);
-
int gen_intermediate_code(CPUState *env, struct TranslationBlock *tb);
int gen_intermediate_code_pc(CPUState *env, struct TranslationBlock *tb);
void dump_ops(const uint16_t *opc_buf, const uint32_t *opparam_buf);
Modified: trunk/src/host/qemu-neo1973/exec.c
===================================================================
--- trunk/src/host/qemu-neo1973/exec.c 2007-11-09 16:32:22 UTC (rev 3386)
+++ trunk/src/host/qemu-neo1973/exec.c 2007-11-09 17:12:19 UTC (rev 3387)
@@ -339,10 +339,10 @@
{
CPUState *env;
#if defined(DEBUG_FLUSH)
- printf("qemu: flush code_size=%d nb_tbs=%d avg_tb_size=%d\n",
- code_gen_ptr - code_gen_buffer,
- nb_tbs,
- nb_tbs > 0 ? (code_gen_ptr - code_gen_buffer) / nb_tbs : 0);
+ printf("qemu: flush code_size=%ld nb_tbs=%d avg_tb_size=%ld\n",
+ (unsigned long)(code_gen_ptr - code_gen_buffer),
+ nb_tbs, nb_tbs > 0 ?
+ ((unsigned long)(code_gen_ptr - code_gen_buffer)) / nb_tbs : 0);
#endif
nb_tbs = 0;
@@ -889,7 +889,7 @@
mprotect(g2h(page_addr), qemu_host_page_size,
(prot & PAGE_BITS) & ~PAGE_WRITE);
#ifdef DEBUG_TB_INVALIDATE
- printf("protecting code page: 0x%08lx\n",
+ printf("protecting code page: 0x" TARGET_FMT_lx "\n",
page_addr);
#endif
}
@@ -944,11 +944,6 @@
tb->jmp_first = (TranslationBlock *)((long)tb | 2);
tb->jmp_next[0] = NULL;
tb->jmp_next[1] = NULL;
-#ifdef USE_CODE_COPY
- tb->cflags &= ~CF_FP_USED;
- if (tb->cflags & CF_TB_FP_USED)
- tb->cflags |= CF_FP_USED;
-#endif
/* init original jump addresses */
if (tb->tb_next_offset[0] != 0xffff)
@@ -1875,6 +1870,33 @@
spin_unlock(&tb_lock);
}
+int page_check_range(target_ulong start, target_ulong len, int flags)
+{
+ PageDesc *p;
+ target_ulong end;
+ target_ulong addr;
+
+ end = TARGET_PAGE_ALIGN(start+len); /* must do before we loose bits in the next step */
+ start = start & TARGET_PAGE_MASK;
+
+ if( end < start )
+ /* we've wrapped around */
+ return -1;
+ for(addr = start; addr < end; addr += TARGET_PAGE_SIZE) {
+ p = page_find(addr >> TARGET_PAGE_BITS);
+ if( !p )
+ return -1;
+ if( !(p->flags & PAGE_VALID) )
+ return -1;
+
+ if (!(p->flags & PAGE_READ) && (flags & PAGE_READ) )
+ return -1;
+ if (!(p->flags & PAGE_WRITE) && (flags & PAGE_WRITE) )
+ return -1;
+ }
+ return 0;
+}
+
/* called from signal handler: invalidate the code and unprotect the
page. Return TRUE if the fault was succesfully handled. */
int page_unprotect(target_ulong address, unsigned long pc, void *puc)
@@ -2062,7 +2084,7 @@
static uint32_t unassigned_mem_readb(void *opaque, target_phys_addr_t addr)
{
#ifdef DEBUG_UNASSIGNED
- printf("Unassigned mem read " TARGET_FMT_lx "\n", addr);
+ printf("Unassigned mem read " TARGET_FMT_plx "\n", addr);
#endif
#ifdef TARGET_SPARC
do_unassigned_access(addr, 0, 0, 0);
@@ -2075,7 +2097,7 @@
static void unassigned_mem_writeb(void *opaque, target_phys_addr_t addr, uint32_t val)
{
#ifdef DEBUG_UNASSIGNED
- printf("Unassigned mem write " TARGET_FMT_lx " = 0x%x\n", addr, val);
+ printf("Unassigned mem write " TARGET_FMT_plx " = 0x%x\n", addr, val);
#endif
#ifdef TARGET_SPARC
do_unassigned_access(addr, 1, 0, 0);
Modified: trunk/src/host/qemu-neo1973/host-utils.c
===================================================================
--- trunk/src/host/qemu-neo1973/host-utils.c 2007-11-09 16:32:22 UTC (rev 3386)
+++ trunk/src/host/qemu-neo1973/host-utils.c 2007-11-09 17:12:19 UTC (rev 3387)
@@ -23,11 +23,13 @@
* THE SOFTWARE.
*/
-#include "vl.h"
+#include "exec.h"
+#include "host-utils.h"
//#define DEBUG_MULDIV
/* Long integer helpers */
+#if !defined(__x86_64__)
static void add128 (uint64_t *plow, uint64_t *phigh, uint64_t a, uint64_t b)
{
*plow += a;
@@ -69,17 +71,10 @@
*phigh += v;
}
-
/* Unsigned 64x64 -> 128 multiplication */
void mulu64 (uint64_t *plow, uint64_t *phigh, uint64_t a, uint64_t b)
{
-#if defined(__x86_64__)
- __asm__ ("mul %0\n\t"
- : "=d" (*phigh), "=a" (*plow)
- : "a" (a), "0" (b));
-#else
mul64(plow, phigh, a, b);
-#endif
#if defined(DEBUG_MULDIV)
printf("mulu64: 0x%016llx * 0x%016llx = 0x%016llx%016llx\n",
a, b, *phigh, *plow);
@@ -89,11 +84,6 @@
/* Signed 64x64 -> 128 multiplication */
void muls64 (uint64_t *plow, uint64_t *phigh, int64_t a, int64_t b)
{
-#if defined(__x86_64__)
- __asm__ ("imul %0\n\t"
- : "=d" (*phigh), "=a" (*plow)
- : "a" (a), "0" (b));
-#else
int sa, sb;
sa = (a < 0);
@@ -106,9 +96,9 @@
if (sa ^ sb) {
neg128(plow, phigh);
}
-#endif
#if defined(DEBUG_MULDIV)
printf("muls64: 0x%016llx * 0x%016llx = 0x%016llx%016llx\n",
a, b, *phigh, *plow);
#endif
}
+#endif /* !defined(__x86_64__) */
Modified: trunk/src/host/qemu-neo1973/host-utils.h
===================================================================
--- trunk/src/host/qemu-neo1973/host-utils.h 2007-11-09 16:32:22 UTC (rev 3386)
+++ trunk/src/host/qemu-neo1973/host-utils.h 2007-11-09 17:12:19 UTC (rev 3387)
@@ -23,6 +23,28 @@
* THE SOFTWARE.
*/
+#if defined(__x86_64__)
+#define __HAVE_FAST_MULU64__
+static always_inline void mulu64 (uint64_t *plow, uint64_t *phigh,
+ uint64_t a, uint64_t b)
+{
+ __asm__ ("mul %0\n\t"
+ : "=d" (*phigh), "=a" (*plow)
+ : "a" (a), "0" (b));
+}
+#define __HAVE_FAST_MULS64__
+static always_inline void muls64 (uint64_t *plow, uint64_t *phigh,
+ int64_t a, int64_t b)
+{
+ __asm__ ("imul %0\n\t"
+ : "=d" (*phigh), "=a" (*plow)
+ : "a" (a), "0" (b));
+}
+#else
+void muls64(uint64_t *phigh, uint64_t *plow, int64_t a, int64_t b);
+void mulu64(uint64_t *phigh, uint64_t *plow, uint64_t a, uint64_t b);
+#endif
+
/* Note that some of those functions may end up calling libgcc functions,
depending on the host machine. It is up to the target emulation to
cope with that. */
@@ -68,34 +90,13 @@
{
int cnt = 0;
- if (!(val & 0xFFFFFFFF00000000ULL)) {
+ if (!(val >> 32)) {
cnt += 32;
- val <<= 32;
+ } else {
+ val >>= 32;
}
- if (!(val & 0xFFFF000000000000ULL)) {
- cnt += 16;
- val <<= 16;
- }
- if (!(val & 0xFF00000000000000ULL)) {
- cnt += 8;
- val <<= 8;
- }
- if (!(val & 0xF000000000000000ULL)) {
- cnt += 4;
- val <<= 4;
- }
- if (!(val & 0xC000000000000000ULL)) {
- cnt += 2;
- val <<= 2;
- }
- if (!(val & 0x8000000000000000ULL)) {
- cnt++;
- val <<= 1;
- }
- if (!(val & 0x8000000000000000ULL)) {
- cnt++;
- }
- return cnt;
+
+ return cnt + clz32(val);
}
static always_inline int clo64(uint64_t val)
Modified: trunk/src/host/qemu-neo1973/hw/fdc.c
===================================================================
--- trunk/src/host/qemu-neo1973/hw/fdc.c 2007-11-09 16:32:22 UTC (rev 3386)
+++ trunk/src/host/qemu-neo1973/hw/fdc.c 2007-11-09 17:12:19 UTC (rev 3387)
@@ -106,7 +106,7 @@
}
static int _fd_sector (uint8_t head, uint8_t track,
- uint8_t sect, uint8_t last_sect)
+ uint8_t sect, uint8_t last_sect)
{
return (((track * 2) + head) * last_sect) + sect - 1;
}
@@ -124,7 +124,7 @@
int ret;
if (track > drv->max_track ||
- (head != 0 && (drv->flags & FDISK_DBL_SIDES) == 0)) {
+ (head != 0 && (drv->flags & FDISK_DBL_SIDES) == 0)) {
FLOPPY_DPRINTF("try to read %d %02x %02x (max=%d %d %02x %02x)\n",
head, track, sect, 1,
(drv->flags & FDISK_DBL_SIDES) == 0 ? 0 : 1,
@@ -149,8 +149,8 @@
}
#endif
drv->head = head;
- if (drv->track != track)
- ret = 1;
+ if (drv->track != track)
+ ret = 1;
drv->track = track;
drv->sect = sect;
}
@@ -179,7 +179,7 @@
const unsigned char *str;
} fd_format_t;
-static fd_format_t fd_formats[] = {
+static const fd_format_t fd_formats[] = {
/* First entry is default format */
/* 1.44 MB 3"1/2 floppy disks */
{ FDRIVE_DRV_144, FDRIVE_DISK_144, 18, 80, 1, "1.44 MB 3\"1/2", },
@@ -229,65 +229,65 @@
/* Revalidate a disk drive after a disk change */
static void fd_revalidate (fdrive_t *drv)
{
- fd_format_t *parse;
+ const fd_format_t *parse;
int64_t nb_sectors, size;
int i, first_match, match;
int nb_heads, max_track, last_sect, ro;
FLOPPY_DPRINTF("revalidate\n");
if (drv->bs != NULL && bdrv_is_inserted(drv->bs)) {
- ro = bdrv_is_read_only(drv->bs);
- bdrv_get_geometry_hint(drv->bs, &nb_heads, &max_track, &last_sect);
- if (nb_heads != 0 && max_track != 0 && last_sect != 0) {
- FLOPPY_DPRINTF("User defined disk (%d %d %d)",
+ ro = bdrv_is_read_only(drv->bs);
+ bdrv_get_geometry_hint(drv->bs, &nb_heads, &max_track, &last_sect);
+ if (nb_heads != 0 && max_track != 0 && last_sect != 0) {
+ FLOPPY_DPRINTF("User defined disk (%d %d %d)",
nb_heads - 1, max_track, last_sect);
- } else {
- bdrv_get_geometry(drv->bs, &nb_sectors);
- match = -1;
- first_match = -1;
- for (i = 0;; i++) {
- parse = &fd_formats[i];
- if (parse->drive == FDRIVE_DRV_NONE)
- break;
- if (drv->drive == parse->drive ||
- drv->drive == FDRIVE_DRV_NONE) {
- size = (parse->max_head + 1) * parse->max_track *
- parse->last_sect;
- if (nb_sectors == size) {
- match = i;
- break;
- }
- if (first_match == -1)
- first_match = i;
- }
- }
- if (match == -1) {
- if (first_match == -1)
- match = 1;
- else
- match = first_match;
- parse = &fd_formats[match];
- }
- nb_heads = parse->max_head + 1;
- max_track = parse->max_track;
- last_sect = parse->last_sect;
- drv->drive = parse->drive;
- FLOPPY_DPRINTF("%s floppy disk (%d h %d t %d s) %s\n", parse->str,
+ } else {
+ bdrv_get_geometry(drv->bs, &nb_sectors);
+ match = -1;
+ first_match = -1;
+ for (i = 0;; i++) {
+ parse = &fd_formats[i];
+ if (parse->drive == FDRIVE_DRV_NONE)
+ break;
+ if (drv->drive == parse->drive ||
+ drv->drive == FDRIVE_DRV_NONE) {
+ size = (parse->max_head + 1) * parse->max_track *
+ parse->last_sect;
+ if (nb_sectors == size) {
+ match = i;
+ break;
+ }
+ if (first_match == -1)
+ first_match = i;
+ }
+ }
+ if (match == -1) {
+ if (first_match == -1)
+ match = 1;
+ else
+ match = first_match;
+ parse = &fd_formats[match];
+ }
+ nb_heads = parse->max_head + 1;
+ max_track = parse->max_track;
+ last_sect = parse->last_sect;
+ drv->drive = parse->drive;
+ FLOPPY_DPRINTF("%s floppy disk (%d h %d t %d s) %s\n", parse->str,
nb_heads, max_track, last_sect, ro ? "ro" : "rw");
- }
- if (nb_heads == 1) {
- drv->flags &= ~FDISK_DBL_SIDES;
- } else {
- drv->flags |= FDISK_DBL_SIDES;
- }
- drv->max_track = max_track;
- drv->last_sect = last_sect;
- drv->ro = ro;
+ }
+ if (nb_heads == 1) {
+ drv->flags &= ~FDISK_DBL_SIDES;
+ } else {
+ drv->flags |= FDISK_DBL_SIDES;
+ }
+ drv->max_track = max_track;
+ drv->last_sect = last_sect;
+ drv->ro = ro;
} else {
- FLOPPY_DPRINTF("No disk in drive\n");
+ FLOPPY_DPRINTF("No disk in drive\n");
drv->last_sect = 0;
- drv->max_track = 0;
- drv->flags &= ~FDISK_DBL_SIDES;
+ drv->max_track = 0;
+ drv->flags &= ~FDISK_DBL_SIDES;
}
}
@@ -395,6 +395,8 @@
uint8_t lock;
/* Power down config (also with status regB access mode */
uint8_t pwrd;
+ /* Sun4m quirks? */
+ int sun4m;
/* Floppy drives */
fdrive_t drives[2];
};
@@ -405,33 +407,35 @@
uint32_t retval;
switch (reg & 0x07) {
-#ifdef TARGET_SPARC
case 0x00:
- // Identify to Linux as S82078B
- retval = fdctrl_read_statusB(fdctrl);
- break;
-#endif
+ if (fdctrl->sun4m) {
+ // Identify to Linux as S82078B
+ retval = fdctrl_read_statusB(fdctrl);
+ } else {
+ retval = (uint32_t)(-1);
+ }
+ break;
case 0x01:
- retval = fdctrl_read_statusB(fdctrl);
- break;
+ retval = fdctrl_read_statusB(fdctrl);
+ break;
case 0x02:
- retval = fdctrl_read_dor(fdctrl);
- break;
+ retval = fdctrl_read_dor(fdctrl);
+ break;
case 0x03:
retval = fdctrl_read_tape(fdctrl);
- break;
+ break;
case 0x04:
retval = fdctrl_read_main_status(fdctrl);
- break;
+ break;
case 0x05:
retval = fdctrl_read_data(fdctrl);
- break;
+ break;
case 0x07:
retval = fdctrl_read_dir(fdctrl);
- break;
+ break;
default:
- retval = (uint32_t)(-1);
- break;
+ retval = (uint32_t)(-1);
+ break;
}
FLOPPY_DPRINTF("read reg%d: 0x%02x\n", reg & 7, retval);
@@ -446,19 +450,19 @@
switch (reg & 0x07) {
case 0x02:
- fdctrl_write_dor(fdctrl, value);
- break;
+ fdctrl_write_dor(fdctrl, value);
+ break;
case 0x03:
fdctrl_write_tape(fdctrl, value);
- break;
+ break;
case 0x04:
fdctrl_write_rate(fdctrl, value);
- break;
+ break;
case 0x05:
fdctrl_write_data(fdctrl, value);
- break;
+ break;
default:
- break;
+ break;
}
}
@@ -598,6 +602,7 @@
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);
@@ -610,7 +615,8 @@
fdctrl_reset(fdctrl, 0);
fdctrl->state = FD_CTRL_ACTIVE;
if (mem_mapped) {
- io_mem = cpu_register_io_memory(0, fdctrl_mem_read, fdctrl_mem_write, fdctrl);
+ io_mem = cpu_register_io_memory(0, fdctrl_mem_read, fdctrl_mem_write,
+ fdctrl);
cpu_register_physical_memory(io_base, 0x08, io_mem);
} else {
register_ioport_read((uint32_t)io_base + 0x01, 5, 1, &fdctrl_read,
@@ -631,6 +637,17 @@
return fdctrl;
}
+fdctrl_t *sun4m_fdctrl_init (qemu_irq irq, target_phys_addr_t io_base,
+ BlockDriverState **fds)
+{
+ fdctrl_t *fdctrl;
+
+ fdctrl = fdctrl_init(irq, 0, 1, io_base, fds);
+ fdctrl->sun4m = 1;
+
+ return fdctrl;
+}
+
/* XXX: may change if moved to bdrv */
int fdctrl_get_drive_type(fdctrl_t *fdctrl, int drive_num)
{
@@ -647,14 +664,12 @@
static void fdctrl_raise_irq (fdctrl_t *fdctrl, uint8_t status)
{
-#ifdef TARGET_SPARC
// Sparc mutation
- if (!fdctrl->dma_en) {
- fdctrl->state &= ~FD_CTRL_BUSY;
- fdctrl->int_status = status;
- return;
+ if (fdctrl->sun4m && !fdctrl->dma_en) {
+ fdctrl->state &= ~FD_CTRL_BUSY;
+ fdctrl->int_status = status;
+ return;
}
-#endif
if (~(fdctrl->state & FD_CTRL_INTR)) {
qemu_set_irq(fdctrl->irq, 1);
fdctrl->state |= FD_CTRL_INTR;
@@ -713,9 +728,9 @@
/* Drive motors state indicators */
if (drv0(fdctrl)->drflags & FDRIVE_MOTOR_ON)
- retval |= 1 << 5;
+ retval |= 1 << 5;
if (drv1(fdctrl)->drflags & FDRIVE_MOTOR_ON)
- retval |= 1 << 4;
+ retval |= 1 << 4;
/* DMA enable */
retval |= fdctrl->dma_en << 3;
/* Reset indicator */
@@ -822,9 +837,9 @@
{
/* Reset mode */
if (fdctrl->state & FD_CTRL_RESET) {
- FLOPPY_DPRINTF("Floppy controller in RESET state !\n");
- return;
- }
+ FLOPPY_DPRINTF("Floppy controller in RESET state !\n");
+ return;
+ }
FLOPPY_DPRINTF("select rate register set to 0x%02x\n", value);
/* Reset: autoclear */
if (value & 0x80) {
@@ -842,6 +857,7 @@
static int fdctrl_media_changed(fdrive_t *drv)
{
int ret;
+
if (!drv->bs)
return 0;
ret = bdrv_media_changed(drv->bs);
@@ -857,7 +873,7 @@
uint32_t retval = 0;
if (fdctrl_media_changed(drv0(fdctrl)) ||
- fdctrl_media_changed(drv1(fdctrl)))
+ fdctrl_media_changed(drv1(fdctrl)))
retval |= 0x80;
if (retval != 0)
FLOPPY_DPRINTF("Floppy digital input register: 0x%02x\n", retval);
@@ -904,7 +920,7 @@
/* Callback for transfer end (stop or abort) */
static void fdctrl_stop_transfer (fdctrl_t *fdctrl, uint8_t status0,
- uint8_t status1, uint8_t status2)
+ uint8_t status1, uint8_t status2)
{
fdrive_t *cur_drv;
@@ -986,12 +1002,12 @@
if (fdctrl->fifo[5] == 00) {
fdctrl->data_len = fdctrl->fifo[8];
} else {
- int tmp;
+ int tmp;
fdctrl->data_len = 128 << (fdctrl->fifo[5] > 7 ? 7 : fdctrl->fifo[5]);
tmp = (cur_drv->last_sect - ks + 1);
if (fdctrl->fifo[0] & 0x80)
tmp += cur_drv->last_sect;
- fdctrl->data_len *= tmp;
+ fdctrl->data_len *= tmp;
}
fdctrl->eot = fdctrl->fifo[6];
if (fdctrl->dma_en) {
@@ -1000,9 +1016,9 @@
dma_mode = DMA_get_channel_mode(fdctrl->dma_chann);
dma_mode = (dma_mode >> 2) & 3;
FLOPPY_DPRINTF("dma_mode=%d direction=%d (%d - %d)\n",
- dma_mode, direction,
+ dma_mode, direction,
(128 << fdctrl->fifo[5]) *
- (cur_drv->last_sect - ks + 1), fdctrl->data_len);
+ (cur_drv->last_sect - ks + 1), fdctrl->data_len);
if (((direction == FD_DIR_SCANE || direction == FD_DIR_SCANL ||
direction == FD_DIR_SCANH) && dma_mode == 0) ||
(direction == FD_DIR_WRITE && dma_mode == 2) ||
@@ -1016,7 +1032,7 @@
DMA_schedule(fdctrl->dma_chann);
return;
} else {
- FLOPPY_ERROR("dma_mode=%d direction=%d\n", dma_mode, direction);
+ FLOPPY_ERROR("dma_mode=%d direction=%d\n", dma_mode, direction);
}
}
FLOPPY_DPRINTF("start non-DMA transfer\n");
@@ -1056,11 +1072,11 @@
if (dma_len > fdctrl->data_len)
dma_len = fdctrl->data_len;
if (cur_drv->bs == NULL) {
- if (fdctrl->data_dir == FD_DIR_WRITE)
- fdctrl_stop_transfer(fdctrl, 0x60, 0x00, 0x00);
- else
- fdctrl_stop_transfer(fdctrl, 0x40, 0x00, 0x00);
- len = 0;
+ if (fdctrl->data_dir == FD_DIR_WRITE)
+ fdctrl_stop_transfer(fdctrl, 0x60, 0x00, 0x00);
+ else
+ fdctrl_stop_transfer(fdctrl, 0x40, 0x00, 0x00);
+ len = 0;
goto transfer_error;
}
rel_pos = fdctrl->data_pos % FD_SECTOR_LEN;
@@ -1074,45 +1090,39 @@
cur_drv->track, cur_drv->sect, fd_sector(cur_drv),
fd_sector(cur_drv) * 512);
if (fdctrl->data_dir != FD_DIR_WRITE ||
- len < FD_SECTOR_LEN || rel_pos != 0) {
+ len < FD_SECTOR_LEN || rel_pos != 0) {
/* READ & SCAN commands and realign to a sector for WRITE */
if (bdrv_read(cur_drv->bs, fd_sector(cur_drv),
- fdctrl->fifo, 1) < 0) {
+ fdctrl->fifo, 1) < 0) {
FLOPPY_DPRINTF("Floppy: error getting sector %d\n",
fd_sector(cur_drv));
/* Sure, image size is too small... */
memset(fdctrl->fifo, 0, FD_SECTOR_LEN);
}
}
- switch (fdctrl->data_dir) {
- case FD_DIR_READ:
- /* READ commands */
+ switch (fdctrl->data_dir) {
+ case FD_DIR_READ:
+ /* READ commands */
DMA_write_memory (nchan, fdctrl->fifo + rel_pos,
fdctrl->data_pos, len);
-/* cpu_physical_memory_write(addr + fdctrl->data_pos, */
-/* fdctrl->fifo + rel_pos, len); */
- break;
- case FD_DIR_WRITE:
+ break;
+ case FD_DIR_WRITE:
/* WRITE commands */
DMA_read_memory (nchan, fdctrl->fifo + rel_pos,
fdctrl->data_pos, len);
-/* cpu_physical_memory_read(addr + fdctrl->data_pos, */
-/* fdctrl->fifo + rel_pos, len); */
if (bdrv_write(cur_drv->bs, fd_sector(cur_drv),
- fdctrl->fifo, 1) < 0) {
+ fdctrl->fifo, 1) < 0) {
FLOPPY_ERROR("writting sector %d\n", fd_sector(cur_drv));
fdctrl_stop_transfer(fdctrl, 0x60, 0x00, 0x00);
goto transfer_error;
}
- break;
- default:
- /* SCAN commands */
+ break;
+ default:
+ /* SCAN commands */
{
- uint8_t tmpbuf[FD_SECTOR_LEN];
+ uint8_t tmpbuf[FD_SECTOR_LEN];
int ret;
DMA_read_memory (nchan, tmpbuf, fdctrl->data_pos, len);
-/* cpu_physical_memory_read(addr + fdctrl->data_pos, */
-/* tmpbuf, len); */
ret = memcmp(tmpbuf, fdctrl->fifo + rel_pos, len);
if (ret == 0) {
status2 = 0x08;
@@ -1124,47 +1134,47 @@
goto end_transfer;
}
}
- break;
+ break;
}
- fdctrl->data_pos += len;
- rel_pos = fdctrl->data_pos % FD_SECTOR_LEN;
+ fdctrl->data_pos += len;
+ rel_pos = fdctrl->data_pos % FD_SECTOR_LEN;
if (rel_pos == 0) {
/* Seek to next sector */
- FLOPPY_DPRINTF("seek to next sector (%d %02x %02x => %d) (%d)\n",
- cur_drv->head, cur_drv->track, cur_drv->sect,
- fd_sector(cur_drv),
- fdctrl->data_pos - len);
+ FLOPPY_DPRINTF("seek to next sector (%d %02x %02x => %d) (%d)\n",
+ cur_drv->head, cur_drv->track, cur_drv->sect,
+ fd_sector(cur_drv),
+ fdctrl->data_pos - len);
/* XXX: cur_drv->sect >= cur_drv->last_sect should be an
error in fact */
if (cur_drv->sect >= cur_drv->last_sect ||
cur_drv->sect == fdctrl->eot) {
- cur_drv->sect = 1;
- if (FD_MULTI_TRACK(fdctrl->data_state)) {
- if (cur_drv->head == 0 &&
- (cur_drv->flags & FDISK_DBL_SIDES) != 0) {
+ cur_drv->sect = 1;
+ if (FD_MULTI_TRACK(fdctrl->data_state)) {
+ if (cur_drv->head == 0 &&
+ (cur_drv->flags & FDISK_DBL_SIDES) != 0) {
cur_drv->head = 1;
} else {
cur_drv->head = 0;
- cur_drv->track++;
- if ((cur_drv->flags & FDISK_DBL_SIDES) == 0)
- break;
+ cur_drv->track++;
+ if ((cur_drv->flags & FDISK_DBL_SIDES) == 0)
+ break;
}
} else {
cur_drv->track++;
break;
}
- FLOPPY_DPRINTF("seek to next track (%d %02x %02x => %d)\n",
- cur_drv->head, cur_drv->track,
- cur_drv->sect, fd_sector(cur_drv));
+ FLOPPY_DPRINTF("seek to next track (%d %02x %02x => %d)\n",
+ cur_drv->head, cur_drv->track,
+ cur_drv->sect, fd_sector(cur_drv));
} else {
cur_drv->sect++;
}
}
}
-end_transfer:
+ end_transfer:
len = fdctrl->data_pos - start_pos;
FLOPPY_DPRINTF("end transfer %d %d %d\n",
- fdctrl->data_pos, len, fdctrl->data_len);
+ fdctrl->data_pos, len, fdctrl->data_len);
if (fdctrl->data_dir == FD_DIR_SCANE ||
fdctrl->data_dir == FD_DIR_SCANL ||
fdctrl->data_dir == FD_DIR_SCANH)
@@ -1174,7 +1184,7 @@
fdctrl->data_len -= len;
// if (fdctrl->data_len == 0)
fdctrl_stop_transfer(fdctrl, status0, status1, status2);
-transfer_error:
+ transfer_error:
return len;
}
@@ -1199,8 +1209,7 @@
len = fdctrl->data_len - fdctrl->data_pos;
if (len > FD_SECTOR_LEN)
len = FD_SECTOR_LEN;
- bdrv_read(cur_drv->bs, fd_sector(cur_drv),
- fdctrl->fifo, len);
+ bdrv_read(cur_drv->bs, fd_sector(cur_drv), fdctrl->fifo, 1);
}
}
retval = fdctrl->fifo[pos];
@@ -1271,18 +1280,18 @@
FLOPPY_ERROR("formatting sector %d\n", fd_sector(cur_drv));
fdctrl_stop_transfer(fdctrl, 0x60, 0x00, 0x00);
} else {
- if (cur_drv->sect == cur_drv->last_sect) {
- fdctrl->data_state &= ~FD_STATE_FORMAT;
- /* Last sector done */
- if (FD_DID_SEEK(fdctrl->data_state))
- fdctrl_stop_transfer(fdctrl, 0x20, 0x00, 0x00);
- else
- fdctrl_stop_transfer(fdctrl, 0x00, 0x00, 0x00);
- } else {
- /* More to do */
- fdctrl->data_pos = 0;
- fdctrl->data_len = 4;
- }
+ if (cur_drv->sect == cur_drv->last_sect) {
+ fdctrl->data_state &= ~FD_STATE_FORMAT;
+ /* Last sector done */
+ if (FD_DID_SEEK(fdctrl->data_state))
+ fdctrl_stop_transfer(fdctrl, 0x20, 0x00, 0x00);
+ else
+ fdctrl_stop_transfer(fdctrl, 0x00, 0x00, 0x00);
+ } else {
+ /* More to do */
+ fdctrl->data_pos = 0;
+ fdctrl->data_len = 4;
+ }
}
}
@@ -1307,8 +1316,7 @@
fdctrl->fifo[fdctrl->data_pos++] = value;
if (fdctrl->data_pos % FD_SECTOR_LEN == (FD_SECTOR_LEN - 1) ||
fdctrl->data_pos == fdctrl->data_len) {
- bdrv_write(cur_drv->bs, fd_sector(cur_drv),
- fdctrl->fifo, FD_SECTOR_LEN);
+ bdrv_write(cur_drv->bs, fd_sector(cur_drv), fdctrl->fifo, 1);
}
/* Switch from transfer mode to status mode
* then from status mode to command mode
@@ -1411,8 +1419,8 @@
#endif
fdctrl->fifo[1] = cur_drv->track;
fdctrl_set_fifo(fdctrl, 2, 0);
- fdctrl_reset_irq(fdctrl);
- fdctrl->int_status = 0xC0;
+ fdctrl_reset_irq(fdctrl);
+ fdctrl->int_status = 0xC0;
return;
case 0x0E:
/* DUMPREG */
@@ -1427,7 +1435,7 @@
fdctrl->fifo[5] = (fdctrl->timer1 << 1) | fdctrl->dma_en;
fdctrl->fifo[6] = cur_drv->last_sect;
fdctrl->fifo[7] = (fdctrl->lock << 7) |
- (cur_drv->perpendicular << 2);
+ (cur_drv->perpendicular << 2);
fdctrl->fifo[8] = fdctrl->config;
fdctrl->fifo[9] = fdctrl->precomp_trk;
fdctrl_set_fifo(fdctrl, 10, 0);
@@ -1495,7 +1503,7 @@
fdctrl->fifo[7] = fdctrl->timer1;
fdctrl->fifo[8] = cur_drv->last_sect;
fdctrl->fifo[9] = (fdctrl->lock << 7) |
- (cur_drv->perpendicular << 2);
+ (cur_drv->perpendicular << 2);
fdctrl->fifo[10] = fdctrl->config;
fdctrl->fifo[11] = fdctrl->precomp_trk;
fdctrl->fifo[12] = fdctrl->pwrd;
@@ -1572,25 +1580,25 @@
return;
}
}
-enqueue:
+ enqueue:
FLOPPY_DPRINTF("%s: %02x\n", __func__, value);
fdctrl->fifo[fdctrl->data_pos] = value;
if (++fdctrl->data_pos == fdctrl->data_len) {
/* We now have all parameters
* and will be able to treat the command
*/
- if (fdctrl->data_state & FD_STATE_FORMAT) {
- fdctrl_format_sector(fdctrl);
- return;
- }
+ if (fdctrl->data_state & FD_STATE_FORMAT) {
+ fdctrl_format_sector(fdctrl);
+ return;
+ }
switch (fdctrl->fifo[0] & 0x1F) {
case 0x06:
- {
- /* READ variants */
- FLOPPY_DPRINTF("treat READ command\n");
- fdctrl_start_transfer(fdctrl, FD_DIR_READ);
- return;
- }
+ {
+ /* READ variants */
+ FLOPPY_DPRINTF("treat READ command\n");
+ fdctrl_start_transfer(fdctrl, FD_DIR_READ);
+ return;
+ }
case 0x0C:
/* READ_DELETED variants */
// FLOPPY_DPRINTF("treat READ_DELETED command\n");
@@ -1645,7 +1653,7 @@
FLOPPY_DPRINTF("treat SPECIFY command\n");
fdctrl->timer0 = (fdctrl->fifo[1] >> 4) & 0xF;
fdctrl->timer1 = fdctrl->fifo[2] >> 1;
- fdctrl->dma_en = 1 - (fdctrl->fifo[2] & 1) ;
+ fdctrl->dma_en = 1 - (fdctrl->fifo[2] & 1) ;
/* No result back */
fdctrl_reset_fifo(fdctrl);
break;
@@ -1653,7 +1661,7 @@
/* SENSE_DRIVE_STATUS */
FLOPPY_DPRINTF("treat SENSE_DRIVE_STATUS command\n");
fdctrl->cur_drv = fdctrl->fifo[1] & 1;
- cur_drv = get_cur_drv(fdctrl);
+ cur_drv = get_cur_drv(fdctrl);
cur_drv->head = (fdctrl->fifo[1] >> 2) & 1;
/* 1 Byte status back */
fdctrl->fifo[0] = (cur_drv->ro << 6) |
@@ -1667,23 +1675,23 @@
/* RECALIBRATE */
FLOPPY_DPRINTF("treat RECALIBRATE command\n");
fdctrl->cur_drv = fdctrl->fifo[1] & 1;
- cur_drv = get_cur_drv(fdctrl);
+ cur_drv = get_cur_drv(fdctrl);
fd_recalibrate(cur_drv);
- fdctrl_reset_fifo(fdctrl);
+ fdctrl_reset_fifo(fdctrl);
/* Raise Interrupt */
- fdctrl_raise_irq(fdctrl, 0x20);
+ fdctrl_raise_irq(fdctrl, 0x20);
break;
case 0x0F:
/* SEEK */
FLOPPY_DPRINTF("treat SEEK command\n");
fdctrl->cur_drv = fdctrl->fifo[1] & 1;
- cur_drv = get_cur_drv(fdctrl);
- fd_start(cur_drv);
+ cur_drv = get_cur_drv(fdctrl);
+ fd_start(cur_drv);
if (fdctrl->fifo[2] <= cur_drv->track)
cur_drv->dir = 1;
else
cur_drv->dir = 0;
- fdctrl_reset_fifo(fdctrl);
+ fdctrl_reset_fifo(fdctrl);
if (fdctrl->fifo[2] > cur_drv->max_track) {
fdctrl_raise_irq(fdctrl, 0x60);
} else {
@@ -1728,7 +1736,7 @@
fdctrl_start_transfer(fdctrl, FD_DIR_READ);
break;
case 0x4A:
- /* READ_ID */
+ /* READ_ID */
FLOPPY_DPRINTF("treat READ_ID command\n");
/* XXX: should set main status register to busy */
cur_drv->head = (fdctrl->fifo[1] >> 2) & 1;
@@ -1754,30 +1762,30 @@
break;
case 0x4D:
/* FORMAT_TRACK */
- FLOPPY_DPRINTF("treat FORMAT_TRACK command\n");
- fdctrl->cur_drv = fdctrl->fifo[1] & 1;
- cur_drv = get_cur_drv(fdctrl);
- fdctrl->data_state |= FD_STATE_FORMAT;
- if (fdctrl->fifo[0] & 0x80)
- fdctrl->data_state |= FD_STATE_MULTI;
- else
- fdctrl->data_state &= ~FD_STATE_MULTI;
- fdctrl->data_state &= ~FD_STATE_SEEK;
- cur_drv->bps =
- fdctrl->fifo[2] > 7 ? 16384 : 128 << fdctrl->fifo[2];
+ FLOPPY_DPRINTF("treat FORMAT_TRACK command\n");
+ fdctrl->cur_drv = fdctrl->fifo[1] & 1;
+ cur_drv = get_cur_drv(fdctrl);
+ fdctrl->data_state |= FD_STATE_FORMAT;
+ if (fdctrl->fifo[0] & 0x80)
+ fdctrl->data_state |= FD_STATE_MULTI;
+ else
+ fdctrl->data_state &= ~FD_STATE_MULTI;
+ fdctrl->data_state &= ~FD_STATE_SEEK;
+ cur_drv->bps =
+ fdctrl->fifo[2] > 7 ? 16384 : 128 << fdctrl->fifo[2];
#if 0
- cur_drv->last_sect =
- cur_drv->flags & FDISK_DBL_SIDES ? fdctrl->fifo[3] :
- fdctrl->fifo[3] / 2;
+ cur_drv->last_sect =
+ cur_drv->flags & FDISK_DBL_SIDES ? fdctrl->fifo[3] :
+ fdctrl->fifo[3] / 2;
#else
- cur_drv->last_sect = fdctrl->fifo[3];
+ cur_drv->last_sect = fdctrl->fifo[3];
#endif
- /* TODO: implement format using DMA expected by the Bochs BIOS
- * and Linux fdformat (read 3 bytes per sector via DMA and fill
- * the sector with the specified fill byte
- */
- fdctrl->data_state &= ~FD_STATE_FORMAT;
- fdctrl_stop_transfer(fdctrl, 0x00, 0x00, 0x00);
+ /* TODO: implement format using DMA expected by the Bochs BIOS
+ * and Linux fdformat (read 3 bytes per sector via DMA and fill
+ * the sector with the specified fill byte
+ */
+ fdctrl->data_state &= ~FD_STATE_FORMAT;
+ fdctrl_stop_transfer(fdctrl, 0x00, 0x00, 0x00);
break;
case 0x8E:
/* DRIVE_SPECIFICATION_COMMAND */
@@ -1803,16 +1811,16 @@
/* RELATIVE_SEEK_OUT */
FLOPPY_DPRINTF("treat RELATIVE_SEEK_OUT command\n");
fdctrl->cur_drv = fdctrl->fifo[1] & 1;
- cur_drv = get_cur_drv(fdctrl);
- fd_start(cur_drv);
- cur_drv->dir = 0;
+ cur_drv = get_cur_drv(fdctrl);
+ fd_start(cur_drv);
+ cur_drv->dir = 0;
if (fdctrl->fifo[2] + cur_drv->track >= cur_drv->max_track) {
- cur_drv->track = cur_drv->max_track - 1;
+ cur_drv->track = cur_drv->max_track - 1;
} else {
cur_drv->track += fdctrl->fifo[2];
}
- fdctrl_reset_fifo(fdctrl);
- fdctrl_raise_irq(fdctrl, 0x20);
+ fdctrl_reset_fifo(fdctrl);
+ fdctrl_raise_irq(fdctrl, 0x20);
break;
case 0xCD:
/* FORMAT_AND_WRITE */
@@ -1821,20 +1829,20 @@
fdctrl_unimplemented(fdctrl);
break;
case 0xCF:
- /* RELATIVE_SEEK_IN */
+ /* RELATIVE_SEEK_IN */
FLOPPY_DPRINTF("treat RELATIVE_SEEK_IN command\n");
fdctrl->cur_drv = fdctrl->fifo[1] & 1;
- cur_drv = get_cur_drv(fdctrl);
- fd_start(cur_drv);
- cur_drv->dir = 1;
+ cur_drv = get_cur_drv(fdctrl);
+ fd_start(cur_drv);
+ cur_drv->dir = 1;
if (fdctrl->fifo[2] > cur_drv->track) {
- cur_drv->track = 0;
+ cur_drv->track = 0;
} else {
cur_drv->track -= fdctrl->fifo[2];
}
- fdctrl_reset_fifo(fdctrl);
- /* Raise Interrupt */
- fdctrl_raise_irq(fdctrl, 0x20);
+ fdctrl_reset_fifo(fdctrl);
+ /* Raise Interrupt */
+ fdctrl_raise_irq(fdctrl, 0x20);
break;
}
}
@@ -1844,6 +1852,7 @@
{
fdctrl_t *fdctrl = opaque;
fdrive_t *cur_drv = get_cur_drv(fdctrl);
+
/* Pretend we are spinning.
* This is needed for Coherent, which uses READ ID to check for
* sector interleaving.
Modified: trunk/src/host/qemu-neo1973/hw/grackle_pci.c
===================================================================
--- trunk/src/host/qemu-neo1973/hw/grackle_pci.c 2007-11-09 16:32:22 UTC (rev 3386)
+++ trunk/src/host/qemu-neo1973/hw/grackle_pci.c 2007-11-09 17:12:19 UTC (rev 3387)
@@ -115,22 +115,6 @@
d->config[0x0b] = 0x06; // class_base = PCI_bridge
d->config[0x0e] = 0x00; // header_type
- d->config[0x18] = 0x00; // primary_bus
- d->config[0x19] = 0x01; // secondary_bus
- d->config[0x1a] = 0x00; // subordinate_bus
- d->config[0x1c] = 0x00;
- d->config[0x1d] = 0x00;
-
- d->config[0x20] = 0x00; // memory_base
- d->config[0x21] = 0x00;
- d->config[0x22] = 0x01; // memory_limit
- d->config[0x23] = 0x00;
-
- d->config[0x24] = 0x00; // prefetchable_memory_base
- d->config[0x25] = 0x00;
- d->config[0x26] = 0x00; // prefetchable_memory_limit
- d->config[0x27] = 0x00;
-
#if 0
/* PCI2PCI bridge same values as PearPC - check this */
d->config[0x00] = 0x11; // vendor_id
Modified: trunk/src/host/qemu-neo1973/hw/i2c.c
===================================================================
--- trunk/src/host/qemu-neo1973/hw/i2c.c 2007-11-09 16:32:22 UTC (rev 3386)
+++ trunk/src/host/qemu-neo1973/hw/i2c.c 2007-11-09 17:12:19 UTC (rev 3387)
@@ -51,8 +51,7 @@
return bus->current_dev != NULL;
}
-/* Returns nonzero if the bus is already busy, or is the address is not
- valid. */
+/* Returns non-zero if the address is not valid. */
/* TODO: Make this handle multiple masters. */
int i2c_start_transfer(i2c_bus *bus, int address, int recv)
{
Modified: trunk/src/host/qemu-neo1973/hw/ide.c
===================================================================
--- trunk/src/host/qemu-neo1973/hw/ide.c 2007-11-09 16:32:22 UTC (rev 3386)
+++ trunk/src/host/qemu-neo1973/hw/ide.c 2007-11-09 17:12:19 UTC (rev 3387)
@@ -358,7 +358,7 @@
uint8_t *data_ptr;
uint8_t *data_end;
uint8_t io_buffer[MAX_MULT_SECTORS*512 + 4];
- QEMUTimer *sector_write_timer; /* only used for win2k instal hack */
+ QEMUTimer *sector_write_timer; /* only used for win2k install hack */
uint32_t irq_count; /* counts IRQs when using win2k install hack */
/* CF-ATA extended error */
uint8_t ext_error;
@@ -865,45 +865,11 @@
ide_set_irq(s);
}
-static void ide_sector_write_aio_cb(void *opaque, int ret)
-{
- BMDMAState *bm = opaque;
- IDEState *s = bm->ide_if;
-
-#ifdef TARGET_I386
- if (win2k_install_hack && ((++s->irq_count % 16) == 0)) {
- /* It seems there is a bug in the Windows 2000 installer HDD
- IDE driver which fills the disk with empty logs when the
- IDE write IRQ comes too early. This hack tries to correct
- that at the expense of slower write performances. Use this
- option _only_ to install Windows 2000. You must disable it
- for normal use. */
- qemu_mod_timer(s->sector_write_timer,
- qemu_get_clock(vm_clock) + (ticks_per_sec / 1000));
- } else
-#endif
- {
- ide_set_irq(s);
- }
- bm->aiocb = NULL;
-}
-
static void ide_sector_write(IDEState *s)
{
- BMDMAState *bm;
int64_t sector_num;
- int n, n1;
+ int ret, n, n1;
- s->io_buffer_index = 0;
- s->io_buffer_size = 0;
- bm = s->bmdma;
- if(bm == NULL) {
- bm = qemu_mallocz(sizeof(BMDMAState));
- s->bmdma = bm;
- }
- bm->ide_if = s;
- bm->dma_cb = ide_sector_write_aio_cb;
-
s->status = READY_STAT | SEEK_STAT;
sector_num = ide_get_sector(s);
#if defined(DEBUG_IDE)
@@ -912,6 +878,7 @@
n = s->nsector;
if (n > s->req_nb_sectors)
n = s->req_nb_sectors;
+ ret = bdrv_write(s->bs, sector_num, s->io_buffer, n);
s->nsector -= n;
if (s->nsector == 0) {
/* no more sectors to write */
@@ -924,8 +891,21 @@
}
ide_set_sector(s, sector_num + n);
- bm->aiocb = bdrv_aio_write(s->bs, sector_num, s->io_buffer, n,
- ide_sector_write_aio_cb, bm);
+#ifdef TARGET_I386
+ if (win2k_install_hack && ((++s->irq_count % 16) == 0)) {
+ /* It seems there is a bug in the Windows 2000 installer HDD
+ IDE driver which fills the disk with empty logs when the
+ IDE write IRQ comes too early. This hack tries to correct
+ that at the expense of slower write performances. Use this
+ option _only_ to install Windows 2000. You must disable it
+ for normal use. */
+ qemu_mod_timer(s->sector_write_timer,
+ qemu_get_clock(vm_clock) + (ticks_per_sec / 1000));
+ } else
+#endif
+ {
+ ide_set_irq(s);
+ }
}
/* XXX: handle errors */
Modified: trunk/src/host/qemu-neo1973/hw/mac_nvram.c
===================================================================
--- trunk/src/host/qemu-neo1973/hw/mac_nvram.c 2007-11-09 16:32:22 UTC (rev 3386)
+++ trunk/src/host/qemu-neo1973/hw/mac_nvram.c 2007-11-09 17:12:19 UTC (rev 3387)
@@ -26,6 +26,9 @@
#include "ppc_mac.h"
struct MacIONVRAMState {
+ target_phys_addr_t mem_base;
+ target_phys_addr_t size;
+ int mem_index;
uint8_t data[0x2000];
};
@@ -58,6 +61,8 @@
target_phys_addr_t addr, uint32_t value)
{
MacIONVRAMState *s = opaque;
+
+ addr -= s->mem_base;
addr = (addr >> 4) & 0x1fff;
s->data[addr] = value;
// printf("macio_nvram_writeb %04x = %02x\n", addr, value);
@@ -68,6 +73,7 @@
MacIONVRAMState *s = opaque;
uint32_t value;
+ addr -= s->mem_base;
addr = (addr >> 4) & 0x1fff;
value = s->data[addr];
// printf("macio_nvram_readb %04x = %02x\n", addr, value);
@@ -87,17 +93,29 @@
&macio_nvram_readb,
};
-MacIONVRAMState *macio_nvram_init (int *mem_index)
+MacIONVRAMState *macio_nvram_init (int *mem_index, target_phys_addr_t size)
{
MacIONVRAMState *s;
+
s = qemu_mallocz(sizeof(MacIONVRAMState));
if (!s)
return NULL;
- *mem_index = cpu_register_io_memory(0, nvram_read, nvram_write, s);
+ s->size = size;
+ s->mem_index = cpu_register_io_memory(0, nvram_read, nvram_write, s);
+ *mem_index = s->mem_index;
return s;
}
+void macio_nvram_map (void *opaque, target_phys_addr_t mem_base)
+{
+ MacIONVRAMState *s;
+
+ s = opaque;
+ s->mem_base = mem_base;
+ cpu_register_physical_memory(mem_base, s->size, s->mem_index);
+}
+
static uint8_t nvram_chksum (const uint8_t *buf, int n)
{
int sum, i;
Modified: trunk/src/host/qemu-neo1973/hw/macio.c
===================================================================
--- trunk/src/host/qemu-neo1973/hw/macio.c 2007-11-09 16:32:22 UTC (rev 3386)
+++ trunk/src/host/qemu-neo1973/hw/macio.c 2007-11-09 17:12:19 UTC (rev 3387)
@@ -31,7 +31,7 @@
int pic_mem_index;
int dbdma_mem_index;
int cuda_mem_index;
- int nvram_mem_index;
+ void *nvram;
int nb_ide;
int ide_mem_index[4];
};
@@ -68,14 +68,12 @@
macio_state->ide_mem_index[i]);
}
}
- if (macio_state->nvram_mem_index >= 0) {
- cpu_register_physical_memory(addr + 0x60000, 0x20000,
- macio_state->nvram_mem_index);
- }
+ if (macio_state->nvram != NULL)
+ macio_nvram_map(macio_state->nvram, addr + 0x60000);
}
void macio_init (PCIBus *bus, int device_id, int is_oldworld, int pic_mem_index,
- int dbdma_mem_index, int cuda_mem_index, int nvram_mem_index,
+ int dbdma_mem_index, int cuda_mem_index, void *nvram,
int nb_ide, int *ide_mem_index)
{
PCIDevice *d;
@@ -90,7 +88,7 @@
macio_state->pic_mem_index = pic_mem_index;
macio_state->dbdma_mem_index = dbdma_mem_index;
macio_state->cuda_mem_index = cuda_mem_index;
- macio_state->nvram_mem_index = nvram_mem_index;
+ macio_state->nvram = nvram;
if (nb_ide > 4)
nb_ide = 4;
macio_state->nb_ide = nb_ide;
Modified: trunk/src/host/qemu-neo1973/hw/mc146818rtc.c
===================================================================
--- trunk/src/host/qemu-neo1973/hw/mc146818rtc.c 2007-11-09 16:32:22 UTC (rev 3386)
+++ trunk/src/host/qemu-neo1973/hw/mc146818rtc.c 2007-11-09 17:12:19 UTC (rev 3387)
@@ -393,11 +393,16 @@
int val;
/* set the CMOS date */
- time(&ti);
- if (rtc_utc)
+ if (rtc_start_date == -1) {
+ time(&ti);
+ if (rtc_utc)
+ tm = gmtime(&ti);
+ else
+ tm = localtime(&ti);
+ } else {
+ ti = rtc_start_date;
tm = gmtime(&ti);
- else
- tm = localtime(&ti);
+ }
rtc_set_date(s, tm);
val = to_bcd(s, (tm->tm_year / 100) + 19);
Modified: trunk/src/host/qemu-neo1973/hw/omap.c
===================================================================
--- trunk/src/host/qemu-neo1973/hw/omap.c 2007-11-09 16:32:22 UTC (rev 3386)
+++ trunk/src/host/qemu-neo1973/hw/omap.c 2007-11-09 17:12:19 UTC (rev 3387)
@@ -22,28 +22,56 @@
#include "arm_pic.h"
/* Should signal the TCMI */
+uint32_t omap_badwidth_read8(void *opaque, target_phys_addr_t addr)
+{
+ uint8_t ret;
+
+ OMAP_8B_REG(addr);
+ cpu_physical_memory_read(addr, (void *) &ret, 1);
+ return ret;
+}
+
+void omap_badwidth_write8(void *opaque, target_phys_addr_t addr,
+ uint32_t value)
+{
+ uint8_t val8 = value;
+
+ OMAP_8B_REG(addr);
+ cpu_physical_memory_write(addr, (void *) &val8, 1);
+}
+
uint32_t omap_badwidth_read16(void *opaque, target_phys_addr_t addr)
{
+ uint16_t ret;
+
OMAP_16B_REG(addr);
- return 0;
+ cpu_physical_memory_read(addr, (void *) &ret, 2);
+ return ret;
}
void omap_badwidth_write16(void *opaque, target_phys_addr_t addr,
uint32_t value)
{
+ uint16_t val16 = value;
+
OMAP_16B_REG(addr);
+ cpu_physical_memory_write(addr, (void *) &val16, 2);
}
uint32_t omap_badwidth_read32(void *opaque, target_phys_addr_t addr)
{
+ uint32_t ret;
+
OMAP_32B_REG(addr);
- return 0;
+ cpu_physical_memory_read(addr, (void *) &ret, 4);
+ return ret;
}
void omap_badwidth_write32(void *opaque, target_phys_addr_t addr,
uint32_t value)
{
OMAP_32B_REG(addr);
+ cpu_physical_memory_write(addr, (void *) &value, 4);
}
/* Interrupt Handlers */
@@ -226,7 +254,7 @@
switch (offset) {
case 0x00: /* ITR */
- s->irqs &= value;
+ s->irqs &= value | 1;
omap_inth_sir_update(s);
omap_inth_update(s);
return;
@@ -772,7 +800,7 @@
case 0x0a: /* SYS_DMA_CSSA_U_CH0 */
s->ch[ch].addr[0] &= 0x0000ffff;
- s->ch[ch].addr[0] |= value << 16;
+ s->ch[ch].addr[0] |= (uint32_t) value << 16;
break;
case 0x0c: /* SYS_DMA_CDSA_L_CH0 */
@@ -782,7 +810,7 @@
case 0x0e: /* SYS_DMA_CDSA_U_CH0 */
s->ch[ch].addr[1] &= 0x0000ffff;
- s->ch[ch].addr[1] |= value << 16;
+ s->ch[ch].addr[1] |= (uint32_t) value << 16;
break;
case 0x10: /* SYS_DMA_CEN_CH0 */
@@ -964,7 +992,7 @@
struct omap_dma_s *s = (struct omap_dma_s *) opaque;
if (on) {
- s->delay = ticks_per_sec >> 5;
+ s->delay = ticks_per_sec >> 7;
if (s->run_count)
qemu_mod_timer(s->tm, qemu_get_clock(vm_clock) + s->delay);
} else {
@@ -1018,37 +1046,37 @@
}
/* DMA ports */
-int omap_validate_emiff_addr(struct omap_mpu_state_s *s,
+static int omap_validate_emiff_addr(struct omap_mpu_state_s *s,
target_phys_addr_t addr)
{
return addr >= OMAP_EMIFF_BASE && addr < OMAP_EMIFF_BASE + s->sdram_size;
}
-int omap_validate_emifs_addr(struct omap_mpu_state_s *s,
+static int omap_validate_emifs_addr(struct omap_mpu_state_s *s,
target_phys_addr_t addr)
{
return addr >= OMAP_EMIFS_BASE && addr < OMAP_EMIFF_BASE;
}
-int omap_validate_imif_addr(struct omap_mpu_state_s *s,
+static int omap_validate_imif_addr(struct omap_mpu_state_s *s,
target_phys_addr_t addr)
{
return addr >= OMAP_IMIF_BASE && addr < OMAP_IMIF_BASE + s->sram_size;
}
-int omap_validate_tipb_addr(struct omap_mpu_state_s *s,
+static int omap_validate_tipb_addr(struct omap_mpu_state_s *s,
target_phys_addr_t addr)
{
return addr >= 0xfffb0000 && addr < 0xffff0000;
}
-int omap_validate_local_addr(struct omap_mpu_state_s *s,
+static int omap_validate_local_addr(struct omap_mpu_state_s *s,
target_phys_addr_t addr)
{
return addr >= OMAP_LOCALBUS_BASE && addr < OMAP_LOCALBUS_BASE + 0x1000000;
}
-int omap_validate_tipb_mpui_addr(struct omap_mpu_state_s *s,
+static int omap_validate_tipb_mpui_addr(struct omap_mpu_state_s *s,
target_phys_addr_t addr)
{
return addr >= 0xe1010000 && addr < 0xe1020004;
@@ -1095,9 +1123,23 @@
if (timer->enable && timer->st && timer->rate) {
timer->val = timer->reset_val; /* Should skip this on clk enable */
- expires = timer->time + muldiv64(timer->val << (timer->ptv + 1),
+ expires = muldiv64(timer->val << (timer->ptv + 1),
ticks_per_sec, timer->rate);
- qemu_mod_timer(timer->timer, expires);
+
+ /* If timer expiry would be sooner than in about 1 ms and
+ * auto-reload isn't set, then fire immediately. This is a hack
+ * to make systems like PalmOS run in acceptable time. PalmOS
+ * sets the interval to a very low value and polls the status bit
+ * in a busy loop when it wants to sleep just a couple of CPU
+ * ticks. */
+ if (expires > (ticks_per_sec >> 10) || timer->ar)
+ qemu_mod_timer(timer->timer, timer->time + expires);
+ else {
+ timer->val = 0;
+ timer->st = 0;
+ if (timer->it_ena)
+ qemu_irq_raise(timer->irq);
+ }
} else
qemu_del_timer(timer->timer);
}
@@ -1283,8 +1325,10 @@
s->mode |= (value >> 15) & 1;
if (s->last_wr == 0xf5) {
if ((value & 0xff) == 0xa0) {
- s->mode = 0;
- omap_clk_put(s->timer.clk);
+ if (s->mode) {
+ s->mode = 0;
+ omap_clk_put(s->timer.clk);
+ }
} else {
/* XXX: on T|E hardware somehow this has no effect,
* on Zire 71 it works as specified. */
@@ -1359,7 +1403,7 @@
static uint32_t omap_os_timer_read(void *opaque, target_phys_addr_t addr)
{
struct omap_32khz_timer_s *s = (struct omap_32khz_timer_s *) opaque;
- int offset = addr - s->timer.base;
+ int offset = addr & OMAP_MPUI_REG_MASK;
switch (offset) {
case 0x00: /* TVR */
@@ -1382,7 +1426,7 @@
uint32_t value)
{
struct omap_32khz_timer_s *s = (struct omap_32khz_timer_s *) opaque;
- int offset = addr - s->timer.base;
+ int offset = addr & OMAP_MPUI_REG_MASK;
switch (offset) {
case 0x00: /* TVR */
@@ -2175,23 +2219,23 @@
uint32_t ret;
switch (offset) {
- case 0xfffecc00: /* IMIF_PRIO */
- case 0xfffecc04: /* EMIFS_PRIO */
- case 0xfffecc08: /* EMIFF_PRIO */
- case 0xfffecc0c: /* EMIFS_CONFIG */
- case 0xfffecc10: /* EMIFS_CS0_CONFIG */
- case 0xfffecc14: /* EMIFS_CS1_CONFIG */
- case 0xfffecc18: /* EMIFS_CS2_CONFIG */
- case 0xfffecc1c: /* EMIFS_CS3_CONFIG */
- case 0xfffecc24: /* EMIFF_MRS */
- case 0xfffecc28: /* TIMEOUT1 */
- case 0xfffecc2c: /* TIMEOUT2 */
- case 0xfffecc30: /* TIMEOUT3 */
- case 0xfffecc3c: /* EMIFF_SDRAM_CONFIG_2 */
- case 0xfffecc40: /* EMIFS_CFG_DYN_WAIT */
+ case 0x00: /* IMIF_PRIO */
+ case 0x04: /* EMIFS_PRIO */
+ case 0x08: /* EMIFF_PRIO */
+ case 0x0c: /* EMIFS_CONFIG */
+ case 0x10: /* EMIFS_CS0_CONFIG */
+ case 0x14: /* EMIFS_CS1_CONFIG */
+ case 0x18: /* EMIFS_CS2_CONFIG */
+ case 0x1c: /* EMIFS_CS3_CONFIG */
+ case 0x24: /* EMIFF_MRS */
+ case 0x28: /* TIMEOUT1 */
+ case 0x2c: /* TIMEOUT2 */
+ case 0x30: /* TIMEOUT3 */
+ case 0x3c: /* EMIFF_SDRAM_CONFIG_2 */
+ case 0x40: /* EMIFS_CFG_DYN_WAIT */
return s->tcmi_regs[offset >> 2];
- case 0xfffecc20: /* EMIFF_SDRAM_CONFIG */
+ case 0x20: /* EMIFF_SDRAM_CONFIG */
ret = s->tcmi_regs[offset >> 2];
s->tcmi_regs[offset >> 2] &= ~1; /* XXX: Clear SLRF on SDRAM access */
/* XXX: We can try using the VGA_DIRTY flag for this */
@@ -2209,23 +2253,23 @@
int offset = addr - s->tcmi_base;
switch (offset) {
- case 0xfffecc00: /* IMIF_PRIO */
- case 0xfffecc04: /* EMIFS_PRIO */
- case 0xfffecc08: /* EMIFF_PRIO */
- case 0xfffecc10: /* EMIFS_CS0_CONFIG */
- case 0xfffecc14: /* EMIFS_CS1_CONFIG */
- case 0xfffecc18: /* EMIFS_CS2_CONFIG */
- case 0xfffecc1c: /* EMIFS_CS3_CONFIG */
- case 0xfffecc20: /* EMIFF_SDRAM_CONFIG */
- case 0xfffecc24: /* EMIFF_MRS */
- case 0xfffecc28: /* TIMEOUT1 */
- case 0xfffecc2c: /* TIMEOUT2 */
- case 0xfffecc30: /* TIMEOUT3 */
- case 0xfffecc3c: /* EMIFF_SDRAM_CONFIG_2 */
- case 0xfffecc40: /* EMIFS_CFG_DYN_WAIT */
+ case 0x00: /* IMIF_PRIO */
+ case 0x04: /* EMIFS_PRIO */
+ case 0x08: /* EMIFF_PRIO */
+ case 0x10: /* EMIFS_CS0_CONFIG */
+ case 0x14: /* EMIFS_CS1_CONFIG */
+ case 0x18: /* EMIFS_CS2_CONFIG */
+ case 0x1c: /* EMIFS_CS3_CONFIG */
+ case 0x20: /* EMIFF_SDRAM_CONFIG */
+ case 0x24: /* EMIFF_MRS */
+ case 0x28: /* TIMEOUT1 */
+ case 0x2c: /* TIMEOUT2 */
+ case 0x30: /* TIMEOUT3 */
+ case 0x3c: /* EMIFF_SDRAM_CONFIG_2 */
+ case 0x40: /* EMIFS_CFG_DYN_WAIT */
s->tcmi_regs[offset >> 2] = value;
break;
- case 0xfffecc0c: /* EMIFS_CONFIG */
+ case 0x0c: /* EMIFS_CONFIG */
s->tcmi_regs[offset >> 2] = (value & 0xf) | (1 << 4);
break;
@@ -2399,7 +2443,7 @@
return s->clkm.arm_rstct2;
case 0x18: /* ARM_SYSST */
- return (s->clkm.clocking_scheme < 11) | s->clkm.cold_start;
+ return (s->clkm.clocking_scheme << 11) | s->clkm.cold_start;
case 0x1c: /* ARM_CKOUT1 */
return s->clkm.arm_ckout1;
@@ -2678,7 +2722,7 @@
return s->clkm.dsp_rstct2;
case 0x18: /* DSP_SYSST */
- return (s->clkm.clocking_scheme < 11) | s->clkm.cold_start |
+ return (s->clkm.clocking_scheme << 11) | s->clkm.cold_start |
(s->env->halted << 6); /* Quite useless... */
}
@@ -2754,9 +2798,9 @@
s->clkm.clocking_scheme = 0;
omap_clkm_ckctl_update(s, ~0, 0x3000);
s->clkm.arm_ckctl = 0x3000;
- omap_clkm_idlect1_update(s, s->clkm.arm_idlect1 & 0x0400, 0x0400);
+ omap_clkm_idlect1_update(s, s->clkm.arm_idlect1 ^ 0x0400, 0x0400);
s->clkm.arm_idlect1 = 0x0400;
- omap_clkm_idlect2_update(s, s->clkm.arm_idlect2 & 0x0100, 0x0100);
+ omap_clkm_idlect2_update(s, s->clkm.arm_idlect2 ^ 0x0100, 0x0100);
s->clkm.arm_idlect2 = 0x0100;
s->clkm.arm_ewupct = 0x003f;
s->clkm.arm_rstct1 = 0x0000;
@@ -2780,8 +2824,11 @@
s->clkm.mpu_base = mpu_base;
s->clkm.dsp_base = dsp_base;
+ s->clkm.arm_idlect1 = 0x03ff;
+ s->clkm.arm_idlect2 = 0x0100;
+ s->clkm.dsp_idlect1 = 0x0002;
+ omap_clkm_reset(s);
s->clkm.cold_start = 0x3a;
- omap_clkm_reset(s);
cpu_register_physical_memory(s->clkm.mpu_base, 0x100, iomemtype[0]);
cpu_register_physical_memory(s->clkm.dsp_base, 0x1000, iomemtype[1]);
@@ -2852,7 +2899,7 @@
static uint32_t omap_mpuio_read(void *opaque, target_phys_addr_t addr)
{
struct omap_mpuio_s *s = (struct omap_mpuio_s *) opaque;
- int offset = addr - s->base;
+ int offset = addr & OMAP_MPUI_REG_MASK;
uint16_t ret;
switch (offset) {
@@ -2908,15 +2955,14 @@
uint32_t value)
{
struct omap_mpuio_s *s = (struct omap_mpuio_s *) opaque;
- int offset = addr - s->base;
+ int offset = addr & OMAP_MPUI_REG_MASK;
uint16_t diff;
int ln;
switch (offset) {
case 0x04: /* OUTPUT_REG */
- diff = s->outputs ^ (value & ~s->dir);
+ diff = (s->outputs ^ value) & ~s->dir;
s->outputs = value;
- value &= ~s->dir;
while ((ln = ffs(diff))) {
ln --;
if (s->handler[ln])
@@ -3078,6 +3124,7 @@
uint16_t edge;
uint16_t mask;
uint16_t ints;
+ uint16_t pins;
};
static void omap_gpio_set(void *opaque, int line, int level)
@@ -3100,11 +3147,11 @@
static uint32_t omap_gpio_read(void *opaque, target_phys_addr_t addr)
{
struct omap_gpio_s *s = (struct omap_gpio_s *) opaque;
- int offset = addr - s->base;
+ int offset = addr & OMAP_MPUI_REG_MASK;
switch (offset) {
case 0x00: /* DATA_INPUT */
- return s->inputs;
+ return s->inputs & s->pins;
case 0x04: /* DATA_OUTPUT */
return s->outputs;
@@ -3120,6 +3167,10 @@
case 0x14: /* INTERRUPT_STATUS */
return s->ints;
+
+ case 0x18: /* PIN_CONTROL (not in OMAP310) */
+ OMAP_BAD_REG(addr);
+ return s->pins;
}
OMAP_BAD_REG(addr);
@@ -3130,7 +3181,7 @@
uint32_t value)
{
struct omap_gpio_s *s = (struct omap_gpio_s *) opaque;
- int offset = addr - s->base;
+ int offset = addr & OMAP_MPUI_REG_MASK;
uint16_t diff;
int ln;
@@ -3140,9 +3191,8 @@
return;
case 0x04: /* DATA_OUTPUT */
- diff = s->outputs ^ (value & ~s->dir);
+ diff = (s->outputs ^ value) & ~s->dir;
s->outputs = value;
- value &= ~s->dir;
while ((ln = ffs(diff))) {
ln --;
if (s->handler[ln])
@@ -3178,6 +3228,11 @@
qemu_irq_lower(s->irq);
break;
+ case 0x18: /* PIN_CONTROL (not in OMAP310 TRM) */
+ OMAP_BAD_REG(addr);
+ s->pins = value;
+ break;
+
default:
OMAP_BAD_REG(addr);
return;
@@ -3205,6 +3260,7 @@
s->edge = ~0;
s->mask = ~0;
s->ints = 0;
+ s->pins = ~0;
}
struct omap_gpio_s *omap_gpio_init(target_phys_addr_t base,
@@ -3281,7 +3337,7 @@
static uint32_t omap_uwire_read(void *opaque, target_phys_addr_t addr)
{
struct omap_uwire_s *s = (struct omap_uwire_s *) opaque;
- int offset = addr - s->base;
+ int offset = addr & OMAP_MPUI_REG_MASK;
switch (offset) {
case 0x00: /* RDR */
@@ -3311,16 +3367,17 @@
uint32_t value)
{
struct omap_uwire_s *s = (struct omap_uwire_s *) opaque;
- int offset = addr - s->base;
+ int offset = addr & OMAP_MPUI_REG_MASK;
switch (offset) {
case 0x00: /* TDR */
s->txbuf = value; /* TD */
- s->control |= 1 << 14; /* CSRB */
if ((s->setup[4] & (1 << 2)) && /* AUTO_TX_EN */
((s->setup[4] & (1 << 3)) || /* CS_TOGGLE_TX_EN */
- (s->control & (1 << 12)))) /* CS_CMD */
+ (s->control & (1 << 12)))) { /* CS_CMD */
+ s->control |= 1 << 14; /* CSRB */
omap_uwire_transfer_start(s);
+ }
break;
case 0x04: /* CSR */
@@ -3369,7 +3426,7 @@
void omap_uwire_reset(struct omap_uwire_s *s)
{
- s->control= 0;
+ s->control = 0;
s->setup[0] = 0;
s->setup[1] = 0;
s->setup[2] = 0;
@@ -3407,6 +3464,1067 @@
s->chip[chipselect] = slave;
}
+/* Pseudonoise Pulse-Width Light Modulator */
+void omap_pwl_update(struct omap_mpu_state_s *s)
+{
+ int output = (s->pwl.clk && s->pwl.enable) ? s->pwl.level : 0;
+
+ if (output != s->pwl.output) {
+ s->pwl.output = output;
+ printf("%s: Backlight now at %i/256\n", __FUNCTION__, output);
+ }
+}
+
+static uint32_t omap_pwl_read(void *opaque, target_phys_addr_t addr)
+{
+ struct omap_mpu_state_s *s = (struct omap_mpu_state_s *) opaque;
+ int offset = addr & OMAP_MPUI_REG_MASK;
+
+ switch (offset) {
+ case 0x00: /* PWL_LEVEL */
+ return s->pwl.level;
+ case 0x04: /* PWL_CTRL */
+ return s->pwl.enable;
+ }
+ OMAP_BAD_REG(addr);
+ return 0;
+}
+
+static void omap_pwl_write(void *opaque, target_phys_addr_t addr,
+ uint32_t value)
+{
+ struct omap_mpu_state_s *s = (struct omap_mpu_state_s *) opaque;
+ int offset = addr & OMAP_MPUI_REG_MASK;
+
+ switch (offset) {
+ case 0x00: /* PWL_LEVEL */
+ s->pwl.level = value;
+ omap_pwl_update(s);
+ break;
+ case 0x04: /* PWL_CTRL */
+ s->pwl.enable = value & 1;
+ omap_pwl_update(s);
+ break;
+ default:
+ OMAP_BAD_REG(addr);
+ return;
+ }
+}
+
+static CPUReadMemoryFunc *omap_pwl_readfn[] = {
+ omap_pwl_read,
+ omap_badwidth_read8,
+ omap_badwidth_read8,
+};
+
+static CPUWriteMemoryFunc *omap_pwl_writefn[] = {
+ omap_pwl_write,
+ omap_badwidth_write8,
+ omap_badwidth_write8,
+};
+
+void omap_pwl_reset(struct omap_mpu_state_s *s)
+{
+ s->pwl.output = 0;
+ s->pwl.level = 0;
+ s->pwl.enable = 0;
+ s->pwl.clk = 1;
+ omap_pwl_update(s);
+}
+
+static void omap_pwl_clk_update(void *opaque, int line, int on)
+{
+ struct omap_mpu_state_s *s = (struct omap_mpu_state_s *) opaque;
+
+ s->pwl.clk = on;
+ omap_pwl_update(s);
+}
+
+static void omap_pwl_init(target_phys_addr_t base, struct omap_mpu_state_s *s,
+ omap_clk clk)
+{
+ int iomemtype;
+
+ omap_pwl_reset(s);
+
+ iomemtype = cpu_register_io_memory(0, omap_pwl_readfn,
+ omap_pwl_writefn, s);
+ cpu_register_physical_memory(base, 0x800, iomemtype);
+
+ omap_clk_adduser(clk, qemu_allocate_irqs(omap_pwl_clk_update, s, 1)[0]);
+}
+
+/* Pulse-Width Tone module */
+static uint32_t omap_pwt_read(void *opaque, target_phys_addr_t addr)
+{
+ struct omap_mpu_state_s *s = (struct omap_mpu_state_s *) opaque;
+ int offset = addr & OMAP_MPUI_REG_MASK;
+
+ switch (offset) {
+ case 0x00: /* FRC */
+ return s->pwt.frc;
+ case 0x04: /* VCR */
+ return s->pwt.vrc;
+ case 0x08: /* GCR */
+ return s->pwt.gcr;
+ }
+ OMAP_BAD_REG(addr);
+ return 0;
+}
+
+static void omap_pwt_write(void *opaque, target_phys_addr_t addr,
+ uint32_t value)
+{
+ struct omap_mpu_state_s *s = (struct omap_mpu_state_s *) opaque;
+ int offset = addr & OMAP_MPUI_REG_MASK;
+
+ switch (offset) {
+ case 0x00: /* FRC */
+ s->pwt.frc = value & 0x3f;
+ break;
+ case 0x04: /* VRC */
+ if ((value ^ s->pwt.vrc) & 1) {
+ if (value & 1)
+ printf("%s: %iHz buzz on\n", __FUNCTION__, (int)
+ /* 1.5 MHz from a 12-MHz or 13-MHz PWT_CLK */
+ ((omap_clk_getrate(s->pwt.clk) >> 3) /
+ /* Pre-multiplexer divider */
+ ((s->pwt.gcr & 2) ? 1 : 154) /
+ /* Octave multiplexer */
+ (2 << (value & 3)) *
+ /* 101/107 divider */
+ ((value & (1 << 2)) ? 101 : 107) *
+ /* 49/55 divider */
+ ((value & (1 << 3)) ? 49 : 55) *
+ /* 50/63 divider */
+ ((value & (1 << 4)) ? 50 : 63) *
+ /* 80/127 divider */
+ ((value & (1 << 5)) ? 80 : 127) /
+ (107 * 55 * 63 * 127)));
+ else
+ printf("%s: silence!\n", __FUNCTION__);
+ }
+ s->pwt.vrc = value & 0x7f;
+ break;
+ case 0x08: /* GCR */
+ s->pwt.gcr = value & 3;
+ break;
+ default:
+ OMAP_BAD_REG(addr);
+ return;
+ }
+}
+
+static CPUReadMemoryFunc *omap_pwt_readfn[] = {
+ omap_pwt_read,
+ omap_badwidth_read8,
+ omap_badwidth_read8,
+};
+
+static CPUWriteMemoryFunc *omap_pwt_writefn[] = {
+ omap_pwt_write,
+ omap_badwidth_write8,
+ omap_badwidth_write8,
+};
+
+void omap_pwt_reset(struct omap_mpu_state_s *s)
+{
+ s->pwt.frc = 0;
+ s->pwt.vrc = 0;
+ s->pwt.gcr = 0;
+}
+
+static void omap_pwt_init(target_phys_addr_t base, struct omap_mpu_state_s *s,
+ omap_clk clk)
+{
+ int iomemtype;
+
+ s->pwt.clk = clk;
+ omap_pwt_reset(s);
+
+ iomemtype = cpu_register_io_memory(0, omap_pwt_readfn,
+ omap_pwt_writefn, s);
+ cpu_register_physical_memory(base, 0x800, iomemtype);
+}
+
+/* Real-time Clock module */
+struct omap_rtc_s {
+ target_phys_addr_t base;
+ qemu_irq irq;
+ qemu_irq alarm;
+ QEMUTimer *clk;
+
+ uint8_t interrupts;
+ uint8_t status;
+ int16_t comp_reg;
+ int running;
+ int pm_am;
+ int auto_comp;
+ int round;
+ struct tm *(*convert)(const time_t *timep, struct tm *result);
+ struct tm alarm_tm;
+ time_t alarm_ti;
+
+ struct tm current_tm;
+ time_t ti;
+ uint64_t tick;
+};
+
+static void omap_rtc_interrupts_update(struct omap_rtc_s *s)
+{
+ qemu_set_irq(s->alarm, (s->status >> 6) & 1);
+}
+
+static void omap_rtc_alarm_update(struct omap_rtc_s *s)
+{
+ s->alarm_ti = mktime(&s->alarm_tm);
+ if (s->alarm_ti == -1)
+ printf("%s: conversion failed\n", __FUNCTION__);
+}
+
+static inline uint8_t omap_rtc_bcd(int num)
+{
+ return ((num / 10) << 4) | (num % 10);
+}
+
+static inline int omap_rtc_bin(uint8_t num)
+{
+ return (num & 15) + 10 * (num >> 4);
+}
+
+static uint32_t omap_rtc_read(void *opaque, target_phys_addr_t addr)
+{
+ struct omap_rtc_s *s = (struct omap_rtc_s *) opaque;
+ int offset = addr & OMAP_MPUI_REG_MASK;
+ uint8_t i;
+
+ switch (offset) {
+ case 0x00: /* SECONDS_REG */
+ return omap_rtc_bcd(s->current_tm.tm_sec);
+
+ case 0x04: /* MINUTES_REG */
+ return omap_rtc_bcd(s->current_tm.tm_min);
+
+ case 0x08: /* HOURS_REG */
+ if (s->pm_am)
+ return ((s->current_tm.tm_hour > 11) << 7) |
+ omap_rtc_bcd(((s->current_tm.tm_hour - 1) % 12) + 1);
+ else
+ return omap_rtc_bcd(s->current_tm.tm_hour);
+
+ case 0x0c: /* DAYS_REG */
+ return omap_rtc_bcd(s->current_tm.tm_mday);
+
+ case 0x10: /* MONTHS_REG */
+ return omap_rtc_bcd(s->current_tm.tm_mon + 1);
+
+ case 0x14: /* YEARS_REG */
+ return omap_rtc_bcd(s->current_tm.tm_year % 100);
+
+ case 0x18: /* WEEK_REG */
+ return s->current_tm.tm_wday;
+
+ case 0x20: /* ALARM_SECONDS_REG */
+ return omap_rtc_bcd(s->alarm_tm.tm_sec);
+
+ case 0x24: /* ALARM_MINUTES_REG */
+ return omap_rtc_bcd(s->alarm_tm.tm_min);
+
+ case 0x28: /* ALARM_HOURS_REG */
+ if (s->pm_am)
+ return ((s->alarm_tm.tm_hour > 11) << 7) |
+ omap_rtc_bcd(((s->alarm_tm.tm_hour - 1) % 12) + 1);
+ else
+ return omap_rtc_bcd(s->alarm_tm.tm_hour);
+
+ case 0x2c: /* ALARM_DAYS_REG */
+ return omap_rtc_bcd(s->alarm_tm.tm_mday);
+
+ case 0x30: /* ALARM_MONTHS_REG */
+ return omap_rtc_bcd(s->alarm_tm.tm_mon + 1);
+
+ case 0x34: /* ALARM_YEARS_REG */
+ return omap_rtc_bcd(s->alarm_tm.tm_year % 100);
+
+ case 0x40: /* RTC_CTRL_REG */
+ return (s->pm_am << 3) | (s->auto_comp << 2) |
+ (s->round << 1) | s->running;
+
+ case 0x44: /* RTC_STATUS_REG */
+ i = s->status;
+ s->status &= ~0x3d;
+ return i;
+
+ case 0x48: /* RTC_INTERRUPTS_REG */
+ return s->interrupts;
+
+ case 0x4c: /* RTC_COMP_LSB_REG */
+ return ((uint16_t) s->comp_reg) & 0xff;
+
+ case 0x50: /* RTC_COMP_MSB_REG */
+ return ((uint16_t) s->comp_reg) >> 8;
+ }
+
+ OMAP_BAD_REG(addr);
+ return 0;
+}
+
+static void omap_rtc_write(void *opaque, target_phys_addr_t addr,
+ uint32_t value)
+{
+ struct omap_rtc_s *s = (struct omap_rtc_s *) opaque;
+ int offset = addr & OMAP_MPUI_REG_MASK;
+ struct tm new_tm;
+ time_t ti[2];
+
+ switch (offset) {
+ case 0x00: /* SECONDS_REG */
+#if ALMDEBUG
+ printf("RTC SEC_REG <-- %02x\n", value);
+#endif
+ s->ti -= s->current_tm.tm_sec;
+ s->ti += omap_rtc_bin(value);
+ return;
+
+ case 0x04: /* MINUTES_REG */
+#if ALMDEBUG
+ printf("RTC MIN_REG <-- %02x\n", value);
+#endif
+ s->ti -= s->current_tm.tm_min * 60;
+ s->ti += omap_rtc_bin(value) * 60;
+ return;
+
+ case 0x08: /* HOURS_REG */
+#if ALMDEBUG
+ printf("RTC HRS_REG <-- %02x\n", value);
+#endif
+ s->ti -= s->current_tm.tm_hour * 3600;
+ if (s->pm_am) {
+ s->ti += (omap_rtc_bin(value & 0x3f) & 12) * 3600;
+ s->ti += ((value >> 7) & 1) * 43200;
+ } else
+ s->ti += omap_rtc_bin(value & 0x3f) * 3600;
+ return;
+
+ case 0x0c: /* DAYS_REG */
+#if ALMDEBUG
+ printf("RTC DAY_REG <-- %02x\n", value);
+#endif
+ s->ti -= s->current_tm.tm_mday * 86400;
+ s->ti += omap_rtc_bin(value) * 86400;
+ return;
+
+ case 0x10: /* MONTHS_REG */
+#if ALMDEBUG
+ printf("RTC MTH_REG <-- %02x\n", value);
+#endif
+ memcpy(&new_tm, &s->current_tm, sizeof(new_tm));
+ new_tm.tm_mon = omap_rtc_bin(value);
+ ti[0] = mktime(&s->current_tm);
+ ti[1] = mktime(&new_tm);
+
+ if (ti[0] != -1 && ti[1] != -1) {
+ s->ti -= ti[0];
+ s->ti += ti[1];
+ } else {
+ /* A less accurate version */
+ s->ti -= s->current_tm.tm_mon * 2592000;
+ s->ti += omap_rtc_bin(value) * 2592000;
+ }
+ return;
+
+ case 0x14: /* YEARS_REG */
+#if ALMDEBUG
+ printf("RTC YRS_REG <-- %02x\n", value);
+#endif
+ memcpy(&new_tm, &s->current_tm, sizeof(new_tm));
+ new_tm.tm_year += omap_rtc_bin(value) - (new_tm.tm_year % 100);
+ ti[0] = mktime(&s->current_tm);
+ ti[1] = mktime(&new_tm);
+
+ if (ti[0] != -1 && ti[1] != -1) {
+ s->ti -= ti[0];
+ s->ti += ti[1];
+ } else {
+ /* A less accurate version */
+ s->ti -= (s->current_tm.tm_year % 100) * 31536000;
+ s->ti += omap_rtc_bin(value) * 31536000;
+ }
+ return;
+
+ case 0x18: /* WEEK_REG */
+ return; /* Ignored */
+
+ case 0x20: /* ALARM_SECONDS_REG */
+#if ALMDEBUG
+ printf("ALM SEC_REG <-- %02x\n", value);
+#endif
+ s->alarm_tm.tm_sec = omap_rtc_bin(value);
+ omap_rtc_alarm_update(s);
+ return;
+
+ case 0x24: /* ALARM_MINUTES_REG */
+#if ALMDEBUG
+ printf("ALM MIN_REG <-- %02x\n", value);
+#endif
+ s->alarm_tm.tm_min = omap_rtc_bin(value);
+ omap_rtc_alarm_update(s);
+ return;
+
+ case 0x28: /* ALARM_HOURS_REG */
+#if ALMDEBUG
+ printf("ALM HRS_REG <-- %02x\n", value);
+#endif
+ if (s->pm_am)
+ s->alarm_tm.tm_hour =
+ ((omap_rtc_bin(value & 0x3f)) % 12) +
+ ((value >> 7) & 1) * 12;
+ else
+ s->alarm_tm.tm_hour = omap_rtc_bin(value);
+ omap_rtc_alarm_update(s);
+ return;
+
+ case 0x2c: /* ALARM_DAYS_REG */
+#if ALMDEBUG
+ printf("ALM DAY_REG <-- %02x\n", value);
+#endif
+ s->alarm_tm.tm_mday = omap_rtc_bin(value);
+ omap_rtc_alarm_update(s);
+ return;
+
+ case 0x30: /* ALARM_MONTHS_REG */
+#if ALMDEBUG
+ printf("ALM MON_REG <-- %02x\n", value);
+#endif
+ s->alarm_tm.tm_mon = omap_rtc_bin(value);
+ omap_rtc_alarm_update(s);
+ return;
+
+ case 0x34: /* ALARM_YEARS_REG */
+#if ALMDEBUG
+ printf("ALM YRS_REG <-- %02x\n", value);
+#endif
+ s->alarm_tm.tm_year = omap_rtc_bin(value);
+ omap_rtc_alarm_update(s);
+ return;
+
+ case 0x40: /* RTC_CTRL_REG */
+#if ALMDEBUG
+ printf("RTC CONTROL <-- %02x\n", value);
+#endif
+ s->pm_am = (value >> 3) & 1;
+ s->auto_comp = (value >> 2) & 1;
+ s->round = (value >> 1) & 1;
+ s->running = value & 1;
+ s->status &= 0xfd;
+ s->status |= s->running << 1;
+ return;
+
+ case 0x44: /* RTC_STATUS_REG */
+#if ALMDEBUG
+ printf("RTC STATUSL <-- %02x\n", value);
+#endif
+ s->status &= ~((value & 0xc0) ^ 0x80);
+ omap_rtc_interrupts_update(s);
+ return;
+
+ case 0x48: /* RTC_INTERRUPTS_REG */
+#if ALMDEBUG
+ printf("RTC INTRS <-- %02x\n", value);
+#endif
+ s->interrupts = value;
+ return;
+
+ case 0x4c: /* RTC_COMP_LSB_REG */
+#if ALMDEBUG
+ printf("RTC COMPLSB <-- %02x\n", value);
+#endif
+ s->comp_reg &= 0xff00;
+ s->comp_reg |= 0x00ff & value;
+ return;
+
+ case 0x50: /* RTC_COMP_MSB_REG */
+#if ALMDEBUG
+ printf("RTC COMPMSB <-- %02x\n", value);
+#endif
+ s->comp_reg &= 0x00ff;
+ s->comp_reg |= 0xff00 & (value << 8);
+ return;
+
+ default:
+ OMAP_BAD_REG(addr);
+ return;
+ }
+}
+
+static CPUReadMemoryFunc *omap_rtc_readfn[] = {
+ omap_rtc_read,
+ omap_badwidth_read8,
+ omap_badwidth_read8,
+};
+
+static CPUWriteMemoryFunc *omap_rtc_writefn[] = {
+ omap_rtc_write,
+ omap_badwidth_write8,
+ omap_badwidth_write8,
+};
+
+static void omap_rtc_tick(void *opaque)
+{
+ struct omap_rtc_s *s = opaque;
+
+ if (s->round) {
+ /* Round to nearest full minute. */
+ if (s->current_tm.tm_sec < 30)
+ s->ti -= s->current_tm.tm_sec;
+ else
+ s->ti += 60 - s->current_tm.tm_sec;
+
+ s->round = 0;
+ }
+
+ localtime_r(&s->ti, &s->current_tm);
+
+ if ((s->interrupts & 0x08) && s->ti == s->alarm_ti) {
+ s->status |= 0x40;
+ omap_rtc_interrupts_update(s);
+ }
+
+ if (s->interrupts & 0x04)
+ switch (s->interrupts & 3) {
+ case 0:
+ s->status |= 0x04;
+ qemu_irq_raise(s->irq);
+ break;
+ case 1:
+ if (s->current_tm.tm_sec)
+ break;
+ s->status |= 0x08;
+ qemu_irq_raise(s->irq);
+ break;
+ case 2:
+ if (s->current_tm.tm_sec || s->current_tm.tm_min)
+ break;
+ s->status |= 0x10;
+ qemu_irq_raise(s->irq);
+ break;
+ case 3:
+ if (s->current_tm.tm_sec ||
+ s->current_tm.tm_min || s->current_tm.tm_hour)
+ break;
+ s->status |= 0x20;
+ qemu_irq_raise(s->irq);
+ break;
+ }
+
+ /* Move on */
+ if (s->running)
+ s->ti ++;
+ s->tick += 1000;
+
+ /*
+ * Every full hour add a rough approximation of the compensation
+ * register to the 32kHz Timer (which drives the RTC) value.
+ */
+ if (s->auto_comp && !s->current_tm.tm_sec && !s->current_tm.tm_min)
+ s->tick += s->comp_reg * 1000 / 32768;
+
+ qemu_mod_timer(s->clk, s->tick);
+}
+
+void omap_rtc_reset(struct omap_rtc_s *s)
+{
+ s->interrupts = 0;
+ s->comp_reg = 0;
+ s->running = 0;
+ s->pm_am = 0;
+ s->auto_comp = 0;
+ s->round = 0;
+ s->tick = qemu_get_clock(rt_clock);
+ memset(&s->alarm_tm, 0, sizeof(s->alarm_tm));
+ s->alarm_tm.tm_mday = 0x01;
+ s->status = 1 << 7;
+ time(&s->ti);
+ s->ti = mktime(s->convert(&s->ti, &s->current_tm));
+
+ omap_rtc_alarm_update(s);
+ omap_rtc_tick(s);
+}
+
+struct omap_rtc_s *omap_rtc_init(target_phys_addr_t base,
+ qemu_irq *irq, omap_clk clk)
+{
+ int iomemtype;
+ struct omap_rtc_s *s = (struct omap_rtc_s *)
+ qemu_mallocz(sizeof(struct omap_rtc_s));
+
+ s->base = base;
+ s->irq = irq[0];
+ s->alarm = irq[1];
+ s->clk = qemu_new_timer(rt_clock, omap_rtc_tick, s);
+ s->convert = rtc_utc ? gmtime_r : localtime_r;
+
+ omap_rtc_reset(s);
+
+ iomemtype = cpu_register_io_memory(0, omap_rtc_readfn,
+ omap_rtc_writefn, s);
+ cpu_register_physical_memory(s->base, 0x800, iomemtype);
+
+ return s;
+}
+
+/* Multi-channel Buffered Serial Port interfaces */
+struct omap_mcbsp_s {
+ target_phys_addr_t base;
+ qemu_irq txirq;
+ qemu_irq rxirq;
+ qemu_irq txdrq;
+ qemu_irq rxdrq;
+
+ uint16_t spcr[2];
+ uint16_t rcr[2];
+ uint16_t xcr[2];
+ uint16_t srgr[2];
+ uint16_t mcr[2];
+ uint16_t pcr;
+ uint16_t rcer[8];
+ uint16_t xcer[8];
+ int tx_rate;
+ int rx_rate;
+ int tx_req;
+
+ struct i2s_codec_s *codec;
+};
+
+static void omap_mcbsp_intr_update(struct omap_mcbsp_s *s)
+{
+ int irq;
+
+ switch ((s->spcr[0] >> 4) & 3) { /* RINTM */
+ case 0:
+ irq = (s->spcr[0] >> 1) & 1; /* RRDY */
+ break;
+ case 3:
+ irq = (s->spcr[0] >> 3) & 1; /* RSYNCERR */
+ break;
+ default:
+ irq = 0;
+ break;
+ }
+
+ qemu_set_irq(s->rxirq, irq);
+
+ switch ((s->spcr[1] >> 4) & 3) { /* XINTM */
+ case 0:
+ irq = (s->spcr[1] >> 1) & 1; /* XRDY */
+ break;
+ case 3:
+ irq = (s->spcr[1] >> 3) & 1; /* XSYNCERR */
+ break;
+ default:
+ irq = 0;
+ break;
+ }
+
+ qemu_set_irq(s->txirq, irq);
+}
+
+static void omap_mcbsp_req_update(struct omap_mcbsp_s *s)
+{
+ int prev = s->tx_req;
+
+ s->tx_req = (s->tx_rate ||
+ (s->spcr[0] & (1 << 12))) && /* CLKSTP */
+ (s->spcr[1] & (1 << 6)) && /* GRST */
+ (s->spcr[1] & (1 << 0)); /* XRST */
+
+ if (!s->tx_req && prev) {
+ s->spcr[1] &= ~(1 << 1); /* XRDY */
+ qemu_irq_lower(s->txdrq);
+ omap_mcbsp_intr_update(s);
+
+ if (s->codec)
+ s->codec->tx_swallow(s->codec->opaque);
+ } else if (s->codec && s->tx_req && !prev) {
+ s->spcr[1] |= 1 << 1; /* XRDY */
+ qemu_irq_raise(s->txdrq);
+ omap_mcbsp_intr_update(s);
+ }
+}
+
+static void omap_mcbsp_rate_update(struct omap_mcbsp_s *s)
+{
+ int rx_clk = 0, tx_clk = 0;
+ int cpu_rate = 1500000; /* XXX */
+ if (!s->codec)
+ return;
+
+ if (s->spcr[1] & (1 << 6)) { /* GRST */
+ if (s->spcr[0] & (1 << 0)) /* RRST */
+ if ((s->srgr[1] & (1 << 13)) && /* CLKSM */
+ (s->pcr & (1 << 8))) /* CLKRM */
+ if (~s->pcr & (1 << 7)) /* SCLKME */
+ rx_clk = cpu_rate /
+ ((s->srgr[0] & 0xff) + 1); /* CLKGDV */
+ if (s->spcr[1] & (1 << 0)) /* XRST */
+ if ((s->srgr[1] & (1 << 13)) && /* CLKSM */
+ (s->pcr & (1 << 9))) /* CLKXM */
+ if (~s->pcr & (1 << 7)) /* SCLKME */
+ tx_clk = cpu_rate /
+ ((s->srgr[0] & 0xff) + 1); /* CLKGDV */
+ }
+
+ s->codec->set_rate(s->codec->opaque, rx_clk, tx_clk);
+}
+
+static void omap_mcbsp_rx_start(struct omap_mcbsp_s *s)
+{
+ if (!(s->spcr[0] & 1)) { /* RRST */
+ if (s->codec)
+ s->codec->in.len = 0;
+ return;
+ }
+
+ if ((s->spcr[0] >> 1) & 1) /* RRDY */
+ s->spcr[0] |= 1 << 2; /* RFULL */
+ s->spcr[0] |= 1 << 1; /* RRDY */
+ qemu_irq_raise(s->rxdrq);
+ omap_mcbsp_intr_update(s);
+}
+
+static void omap_mcbsp_rx_stop(struct omap_mcbsp_s *s)
+{
+ s->spcr[0] &= ~(1 << 1); /* RRDY */
+ qemu_irq_lower(s->rxdrq);
+ omap_mcbsp_intr_update(s);
+}
+
+static void omap_mcbsp_tx_start(struct omap_mcbsp_s *s)
+{
+ if (s->tx_rate)
+ return;
+ s->tx_rate = 1;
+ omap_mcbsp_req_update(s);
+}
+
+static void omap_mcbsp_tx_stop(struct omap_mcbsp_s *s)
+{
+ s->tx_rate = 0;
+ omap_mcbsp_req_update(s);
+}
+
+static uint32_t omap_mcbsp_read(void *opaque, target_phys_addr_t addr)
+{
+ struct omap_mcbsp_s *s = (struct omap_mcbsp_s *) opaque;
+ int offset = addr & OMAP_MPUI_REG_MASK;
+ uint16_t ret;
+
+ switch (offset) {
+ case 0x00: /* DRR2 */
+ if (((s->rcr[0] >> 5) & 7) < 3) /* RWDLEN1 */
+ return 0x0000;
+ /* Fall through. */
+ case 0x02: /* DRR1 */
+ if (!s->codec)
+ return 0x0000;
+ if (s->codec->in.len < 2) {
+ printf("%s: Rx FIFO underrun\n", __FUNCTION__);
+ omap_mcbsp_rx_stop(s);
+ } else {
+ s->codec->in.len -= 2;
+ ret = s->codec->in.fifo[s->codec->in.start ++] << 8;
+ ret |= s->codec->in.fifo[s->codec->in.start ++];
+ if (!s->codec->in.len)
+ omap_mcbsp_rx_stop(s);
+ return ret;
+ }
+ return 0x0000;
+
+ case 0x04: /* DXR2 */
+ case 0x06: /* DXR1 */
+ return 0x0000;
+
+ case 0x08: /* SPCR2 */
+ return s->spcr[1];
+ case 0x0a: /* SPCR1 */
+ return s->spcr[0];
+ case 0x0c: /* RCR2 */
+ return s->rcr[1];
+ case 0x0e: /* RCR1 */
+ return s->rcr[0];
+ case 0x10: /* XCR2 */
+ return s->xcr[1];
+ case 0x12: /* XCR1 */
+ return s->xcr[0];
+ case 0x14: /* SRGR2 */
+ return s->srgr[1];
+ case 0x16: /* SRGR1 */
+ return s->srgr[0];
+ case 0x18: /* MCR2 */
+ return s->mcr[1];
+ case 0x1a: /* MCR1 */
+ return s->mcr[0];
+ case 0x1c: /* RCERA */
+ return s->rcer[0];
+ case 0x1e: /* RCERB */
+ return s->rcer[1];
+ case 0x20: /* XCERA */
+ return s->xcer[0];
+ case 0x22: /* XCERB */
+ return s->xcer[1];
+ case 0x24: /* PCR0 */
+ return s->pcr;
+ case 0x26: /* RCERC */
+ return s->rcer[2];
+ case 0x28: /* RCERD */
+ return s->rcer[3];
+ case 0x2a: /* XCERC */
+ return s->xcer[2];
+ case 0x2c: /* XCERD */
+ return s->xcer[3];
+ case 0x2e: /* RCERE */
+ return s->rcer[4];
+ case 0x30: /* RCERF */
+ return s->rcer[5];
+ case 0x32: /* XCERE */
+ return s->xcer[4];
+ case 0x34: /* XCERF */
+ return s->xcer[5];
+ case 0x36: /* RCERG */
+ return s->rcer[6];
+ case 0x38: /* RCERH */
+ return s->rcer[7];
+ case 0x3a: /* XCERG */
+ return s->xcer[6];
+ case 0x3c: /* XCERH */
+ return s->xcer[7];
+ }
+
+ OMAP_BAD_REG(addr);
+ return 0;
+}
+
+static void omap_mcbsp_write(void *opaque, target_phys_addr_t addr,
+ uint32_t value)
+{
+ struct omap_mcbsp_s *s = (struct omap_mcbsp_s *) opaque;
+ int offset = addr & OMAP_MPUI_REG_MASK;
+
+ switch (offset) {
+ case 0x00: /* DRR2 */
+ case 0x02: /* DRR1 */
+ OMAP_RO_REG(addr);
+ return;
+
+ case 0x04: /* DXR2 */
+ if (((s->xcr[0] >> 5) & 7) < 3) /* XWDLEN1 */
+ return;
+ /* Fall through. */
+ case 0x06: /* DXR1 */
+ if (!s->codec)
+ return;
+ if (s->tx_req) {
+ if (s->codec->out.len > s->codec->out.size - 2) {
+ printf("%s: Tx FIFO overrun\n", __FUNCTION__);
+ omap_mcbsp_tx_stop(s);
+ } else {
+ s->codec->out.fifo[s->codec->out.len ++] = (value >> 8) & 0xff;
+ s->codec->out.fifo[s->codec->out.len ++] = (value >> 0) & 0xff;
+ if (s->codec->out.len >= s->codec->out.size)
+ omap_mcbsp_tx_stop(s);
+ }
+ } else
+ printf("%s: Tx FIFO overrun\n", __FUNCTION__);
+ return;
+
+ case 0x08: /* SPCR2 */
+ s->spcr[1] &= 0x0002;
+ s->spcr[1] |= 0x03f9 & value;
+ s->spcr[1] |= 0x0004 & (value << 2); /* XEMPTY := XRST */
+ if (~value & 1) { /* XRST */
+ s->spcr[1] &= ~6;
+ qemu_irq_lower(s->rxdrq);
+ if (s->codec)
+ s->codec->out.len = 0;
+ }
+ if (s->codec)
+ omap_mcbsp_rate_update(s);
+ omap_mcbsp_req_update(s);
+ return;
+ case 0x0a: /* SPCR1 */
+ s->spcr[0] &= 0x0006;
+ s->spcr[0] |= 0xf8f9 & value;
+ if (value & (1 << 15)) /* DLB */
+ printf("%s: Digital Loopback mode enable attempt\n", __FUNCTION__);
+ if (~value & 1) { /* RRST */
+ s->spcr[0] &= ~6;
+ qemu_irq_lower(s->txdrq);
+ if (s->codec)
+ s->codec->in.len = 0;
+ }
+ if (s->codec)
+ omap_mcbsp_rate_update(s);
+ omap_mcbsp_req_update(s);
+ return;
+
+ case 0x0c: /* RCR2 */
+ s->rcr[1] = value & 0xffff;
+ return;
+ case 0x0e: /* RCR1 */
+ s->rcr[0] = value & 0x7fe0;
+ return;
+ case 0x10: /* XCR2 */
+ s->xcr[1] = value & 0xffff;
+ return;
+ case 0x12: /* XCR1 */
+ s->xcr[0] = value & 0x7fe0;
+ return;
+ case 0x14: /* SRGR2 */
+ s->srgr[1] = value & 0xffff;
+ omap_mcbsp_rate_update(s);
+ return;
+ case 0x16: /* SRGR1 */
+ s->srgr[0] = value & 0xffff;
+ omap_mcbsp_rate_update(s);
+ return;
+ case 0x18: /* MCR2 */
+ s->mcr[1] = value & 0x03e3;
+ if (value & 3) /* XMCM */
+ printf("%s: Tx channel selection mode enable attempt\n",
+ __FUNCTION__);
+ return;
+ case 0x1a: /* MCR1 */
+ s->mcr[0] = value & 0x03e1;
+ if (value & 1) /* RMCM */
+ printf("%s: Rx channel selection mode enable attempt\n",
+ __FUNCTION__);
+ return;
+ case 0x1c: /* RCERA */
+ s->rcer[0] = value & 0xffff;
+ return;
+ case 0x1e: /* RCERB */
+ s->rcer[1] = value & 0xffff;
+ return;
+ case 0x20: /* XCERA */
+ s->xcer[0] = value & 0xffff;
+ return;
+ case 0x22: /* XCERB */
+ s->xcer[1] = value & 0xffff;
+ return;
+ case 0x24: /* PCR0 */
+ s->pcr = value & 0x7faf;
+ return;
+ case 0x26: /* RCERC */
+ s->rcer[2] = value & 0xffff;
+ return;
+ case 0x28: /* RCERD */
+ s->rcer[3] = value & 0xffff;
+ return;
+ case 0x2a: /* XCERC */
+ s->xcer[2] = value & 0xffff;
+ return;
+ case 0x2c: /* XCERD */
+ s->xcer[3] = value & 0xffff;
+ return;
+ case 0x2e: /* RCERE */
+ s->rcer[4] = value & 0xffff;
+ return;
+ case 0x30: /* RCERF */
+ s->rcer[5] = value & 0xffff;
+ return;
+ case 0x32: /* XCERE */
+ s->xcer[4] = value & 0xffff;
+ return;
+ case 0x34: /* XCERF */
+ s->xcer[5] = value & 0xffff;
+ return;
+ case 0x36: /* RCERG */
+ s->rcer[6] = value & 0xffff;
+ return;
+ case 0x38: /* RCERH */
+ s->rcer[7] = value & 0xffff;
+ return;
+ case 0x3a: /* XCERG */
+ s->xcer[6] = value & 0xffff;
+ return;
+ case 0x3c: /* XCERH */
+ s->xcer[7] = value & 0xffff;
+ return;
+ }
+
+ OMAP_BAD_REG(addr);
+}
+
+static CPUReadMemoryFunc *omap_mcbsp_readfn[] = {
+ omap_badwidth_read16,
+ omap_mcbsp_read,
+ omap_badwidth_read16,
+};
+
+static CPUWriteMemoryFunc *omap_mcbsp_writefn[] = {
+ omap_badwidth_write16,
+ omap_mcbsp_write,
+ omap_badwidth_write16,
+};
+
+static void omap_mcbsp_reset(struct omap_mcbsp_s *s)
+{
+ memset(&s->spcr, 0, sizeof(s->spcr));
+ memset(&s->rcr, 0, sizeof(s->rcr));
+ memset(&s->xcr, 0, sizeof(s->xcr));
+ s->srgr[0] = 0x0001;
+ s->srgr[1] = 0x2000;
+ memset(&s->mcr, 0, sizeof(s->mcr));
+ memset(&s->pcr, 0, sizeof(s->pcr));
+ memset(&s->rcer, 0, sizeof(s->rcer));
+ memset(&s->xcer, 0, sizeof(s->xcer));
+ s->tx_req = 0;
+ s->tx_rate = 0;
+ s->rx_rate = 0;
+}
+
+struct omap_mcbsp_s *omap_mcbsp_init(target_phys_addr_t base,
+ qemu_irq *irq, qemu_irq *dma, omap_clk clk)
+{
+ int iomemtype;
+ struct omap_mcbsp_s *s = (struct omap_mcbsp_s *)
+ qemu_mallocz(sizeof(struct omap_mcbsp_s));
+
+ s->base = base;
+ s->txirq = irq[0];
+ s->rxirq = irq[1];
+ s->txdrq = dma[0];
+ s->rxdrq = dma[1];
+ omap_mcbsp_reset(s);
+
+ iomemtype = cpu_register_io_memory(0, omap_mcbsp_readfn,
+ omap_mcbsp_writefn, s);
+ cpu_register_physical_memory(s->base, 0x800, iomemtype);
+
+ return s;
+}
+
+void omap_mcbsp_i2s_swallow(void *opaque, int line, int level)
+{
+ struct omap_mcbsp_s *s = (struct omap_mcbsp_s *) opaque;
+
+ omap_mcbsp_rx_start(s);
+}
+
+void omap_mcbsp_i2s_start(void *opaque, int line, int level)
+{
+ struct omap_mcbsp_s *s = (struct omap_mcbsp_s *) opaque;
+
+ omap_mcbsp_tx_start(s);
+}
+
+void omap_mcbsp_i2s_attach(struct omap_mcbsp_s *s, struct i2s_codec_s *slave)
+{
+ s->codec = slave;
+ slave->rx_swallow = qemu_allocate_irqs(omap_mcbsp_i2s_swallow, s, 1)[0];
+ slave->tx_start = qemu_allocate_irqs(omap_mcbsp_i2s_start, s, 1)[0];
+}
+
/* General chip reset */
static void omap_mpu_reset(void *opaque)
{
@@ -3437,9 +4555,57 @@
omap_mpuio_reset(mpu->mpuio);
omap_gpio_reset(mpu->gpio);
omap_uwire_reset(mpu->microwire);
+ omap_pwl_reset(mpu);
+ omap_pwt_reset(mpu);
+ omap_i2c_reset(mpu->i2c);
+ omap_rtc_reset(mpu->rtc);
+ omap_mcbsp_reset(mpu->mcbsp1);
+ omap_mcbsp_reset(mpu->mcbsp2);
+ omap_mcbsp_reset(mpu->mcbsp3);
cpu_reset(mpu->env);
}
+static const struct omap_map_s {
+ target_phys_addr_t phys_dsp;
+ target_phys_addr_t phys_mpu;
+ uint32_t size;
+ const char *name;
+} omap15xx_dsp_mm[] = {
+ /* Strobe 0 */
+ { 0xe1010000, 0xfffb0000, 0x800, "UART1 BT" }, /* CS0 */
+ { 0xe1010800, 0xfffb0800, 0x800, "UART2 COM" }, /* CS1 */
+ { 0xe1011800, 0xfffb1800, 0x800, "McBSP1 audio" }, /* CS3 */
+ { 0xe1012000, 0xfffb2000, 0x800, "MCSI2 communication" }, /* CS4 */
+ { 0xe1012800, 0xfffb2800, 0x800, "MCSI1 BT u-Law" }, /* CS5 */
+ { 0xe1013000, 0xfffb3000, 0x800, "uWire" }, /* CS6 */
+ { 0xe1013800, 0xfffb3800, 0x800, "I^2C" }, /* CS7 */
+ { 0xe1014000, 0xfffb4000, 0x800, "USB W2FC" }, /* CS8 */
+ { 0xe1014800, 0xfffb4800, 0x800, "RTC" }, /* CS9 */
+ { 0xe1015000, 0xfffb5000, 0x800, "MPUIO" }, /* CS10 */
+ { 0xe1015800, 0xfffb5800, 0x800, "PWL" }, /* CS11 */
+ { 0xe1016000, 0xfffb6000, 0x800, "PWT" }, /* CS12 */
+ { 0xe1017000, 0xfffb7000, 0x800, "McBSP3" }, /* CS14 */
+ { 0xe1017800, 0xfffb7800, 0x800, "MMC" }, /* CS15 */
+ { 0xe1019000, 0xfffb9000, 0x800, "32-kHz timer" }, /* CS18 */
+ { 0xe1019800, 0xfffb9800, 0x800, "UART3" }, /* CS19 */
+ { 0xe101c800, 0xfffbc800, 0x800, "TIPB switches" }, /* CS25 */
+ /* Strobe 1 */
+ { 0xe101e000, 0xfffce000, 0x800, "GPIOs" }, /* CS28 */
+
+ { 0 }
+};
+
+static void omap_setup_dsp_mapping(const struct omap_map_s *map)
+{
+ int io;
+
+ for (; map->phys_dsp; map ++) {
+ io = cpu_get_physical_page_desc(map->phys_mpu);
+
+ cpu_register_physical_memory(map->phys_dsp, map->size, io);
+ }
+}
+
static void omap_mpu_wakeup(void *opaque, int irq, int req)
{
struct omap_mpu_state_s *mpu = (struct omap_mpu_state_s *) opaque;
@@ -3553,11 +4719,46 @@
s->wakeup, omap_findclk(s, "clk32-kHz"));
s->gpio = omap_gpio_init(0xfffce000, s->irq[0][OMAP_INT_GPIO_BANK1],
- omap_findclk(s, "mpuper_ck"));
+ omap_findclk(s, "arm_gpio_ck"));
s->microwire = omap_uwire_init(0xfffb3000, &s->irq[1][OMAP_INT_uWireTX],
s->drq[OMAP_DMA_UWIRE_TX], omap_findclk(s, "mpuper_ck"));
+ omap_pwl_init(0xfffb5800, s, omap_findclk(s, "armxor_ck"));
+ omap_pwt_init(0xfffb6000, s, omap_findclk(s, "armxor_ck"));
+
+ s->i2c = omap_i2c_init(0xfffb3800, s->irq[1][OMAP_INT_I2C],
+ &s->drq[OMAP_DMA_I2C_RX], omap_findclk(s, "mpuper_ck"));
+
+ s->rtc = omap_rtc_init(0xfffb4800, &s->irq[1][OMAP_INT_RTC_TIMER],
+ omap_findclk(s, "clk32-kHz"));
+
+ s->mcbsp1 = omap_mcbsp_init(0xfffb1800, &s->irq[1][OMAP_INT_McBSP1TX],
+ &s->drq[OMAP_DMA_MCBSP1_TX], omap_findclk(s, "dspxor_ck"));
+ s->mcbsp2 = omap_mcbsp_init(0xfffb1000, &s->irq[0][OMAP_INT_310_McBSP2_TX],
+ &s->drq[OMAP_DMA_MCBSP2_TX], omap_findclk(s, "mpuper_ck"));
+ s->mcbsp3 = omap_mcbsp_init(0xfffb7000, &s->irq[1][OMAP_INT_McBSP3TX],
+ &s->drq[OMAP_DMA_MCBSP3_TX], omap_findclk(s, "dspxor_ck"));
+
+ /* Register mappings not currenlty implemented:
+ * MCSI2 Comm fffb2000 - fffb27ff (not mapped on OMAP310)
+ * MCSI1 Bluetooth fffb2800 - fffb2fff (not mapped on OMAP310)
+ * USB W2FC fffb4000 - fffb47ff
+ * Camera Interface fffb6800 - fffb6fff
+ * USB Host fffba000 - fffba7ff
+ * FAC fffba800 - fffbafff
+ * HDQ/1-Wire fffbc000 - fffbc7ff
+ * TIPB switches fffbc800 - fffbcfff
+ * LED1 fffbd000 - fffbd7ff
+ * LED2 fffbd800 - fffbdfff
+ * Mailbox fffcf000 - fffcf7ff
+ * Local bus IF fffec100 - fffec1ff
+ * Local bus MMU fffec200 - fffec2ff
+ * DSP MMU fffed200 - fffed2ff
+ */
+
+ omap_setup_dsp_mapping(omap15xx_dsp_mm);
+
qemu_register_reset(omap_mpu_reset, s);
return s;
Modified: trunk/src/host/qemu-neo1973/hw/omap.h
===================================================================
--- trunk/src/host/qemu-neo1973/hw/omap.h 2007-11-09 16:32:22 UTC (rev 3386)
+++ trunk/src/host/qemu-neo1973/hw/omap.h 2007-11-09 17:12:19 UTC (rev 3387)
@@ -475,6 +475,34 @@
void omap_uwire_attach(struct omap_uwire_s *s,
struct uwire_slave_s *slave, int chipselect);
+struct omap_rtc_s;
+struct omap_rtc_s *omap_rtc_init(target_phys_addr_t base,
+ qemu_irq *irq, omap_clk clk);
+
+struct i2s_codec_s {
+ void *opaque;
+
+ /* The CPU can call this if it is generating the clock signal on the
+ * i2s port. The CODEC can ignore it if it is set up as a clock
+ * master and generates its own clock. */
+ void (*set_rate)(void *opaque, int in, int out);
+
+ void (*tx_swallow)(void *opaque);
+ qemu_irq rx_swallow;
+ qemu_irq tx_start;
+
+ struct i2s_fifo_s {
+ uint8_t *fifo;
+ int len;
+ int start;
+ int size;
+ } in, out;
+};
+struct omap_mcbsp_s;
+struct omap_mcbsp_s *omap_mcbsp_init(target_phys_addr_t base,
+ qemu_irq *irq, qemu_irq *dma, omap_clk clk);
+void omap_mcbsp_i2s_attach(struct omap_mcbsp_s *s, struct i2s_codec_s *slave);
+
/* omap_lcdc.c */
struct omap_lcd_panel_s;
void omap_lcdc_reset(struct omap_lcd_panel_s *s);
@@ -489,6 +517,13 @@
void omap_mmc_reset(struct omap_mmc_s *s);
void omap_mmc_handlers(struct omap_mmc_s *s, qemu_irq ro, qemu_irq cover);
+/* omap_i2c.c */
+struct omap_i2c_s;
+struct omap_i2c_s *omap_i2c_init(target_phys_addr_t base,
+ qemu_irq irq, qemu_irq *dma, omap_clk clk);
+void omap_i2c_reset(struct omap_i2c_s *s);
+i2c_bus *omap_i2c_bus(struct omap_i2c_s *s);
+
# define cpu_is_omap310(cpu) (cpu->mpu_model == omap310)
# define cpu_is_omap1510(cpu) (cpu->mpu_model == omap1510)
# define cpu_is_omap15xx(cpu) \
@@ -525,6 +560,9 @@
struct omap_gpio_s *gpio;
+ struct omap_mcbsp_s *mcbsp1;
+ struct omap_mcbsp_s *mcbsp3;
+
/* MPU public TIPB peripherals */
struct omap_32khz_timer_s *os_timer;
@@ -534,6 +572,26 @@
struct omap_uwire_s *microwire;
+ struct {
+ uint8_t output;
+ uint8_t level;
+ uint8_t enable;
+ int clk;
+ } pwl;
+
+ struct {
+ uint8_t frc;
+ uint8_t vrc;
+ uint8_t gcr;
+ omap_clk clk;
+ } pwt;
+
+ struct omap_i2c_s *i2c;
+
+ struct omap_rtc_s *rtc;
+
+ struct omap_mcbsp_s *mcbsp2;
+
/* MPU private TIPB peripherals */
struct omap_intr_handler_s *ih[2];
@@ -615,11 +673,119 @@
# define OMAP_RO_REG(paddr) \
printf("%s: Read-only register " OMAP_FMT_plx "\n", \
__FUNCTION__, paddr)
-# define OMAP_16B_REG(paddr) \
+
+# define TCMI_VERBOSE 1
+//# define MEM_VERBOSE 1
+
+# ifdef TCMI_VERBOSE
+# define OMAP_8B_REG(paddr) \
+ printf("%s: 8-bit register " OMAP_FMT_plx "\n", \
+ __FUNCTION__, paddr)
+# define OMAP_16B_REG(paddr) \
printf("%s: 16-bit register " OMAP_FMT_plx "\n", \
__FUNCTION__, paddr)
-# define OMAP_32B_REG(paddr) \
+# define OMAP_32B_REG(paddr) \
printf("%s: 32-bit register " OMAP_FMT_plx "\n", \
__FUNCTION__, paddr)
+# else
+# define OMAP_8B_REG(paddr)
+# define OMAP_16B_REG(paddr)
+# define OMAP_32B_REG(paddr)
+# endif
+# define OMAP_MPUI_REG_MASK 0x000007ff
+
+# ifdef MEM_VERBOSE
+struct io_fn {
+ CPUReadMemoryFunc **mem_read;
+ CPUWriteMemoryFunc **mem_write;
+ void *opaque;
+ int in;
+};
+
+static uint32_t io_readb(void *opaque, target_phys_addr_t addr)
+{
+ struct io_fn *s = opaque;
+ uint32_t ret;
+
+ s->in ++;
+ ret = s->mem_read[0](s->opaque, addr);
+ s->in --;
+ if (!s->in)
+ fprintf(stderr, "%08x ---> %02x\n", (uint32_t) addr, ret);
+ return ret;
+}
+static uint32_t io_readh(void *opaque, target_phys_addr_t addr)
+{
+ struct io_fn *s = opaque;
+ uint32_t ret;
+
+ s->in ++;
+ ret = s->mem_read[1](s->opaque, addr);
+ s->in --;
+ if (!s->in)
+ fprintf(stderr, "%08x ---> %04x\n", (uint32_t) addr, ret);
+ return ret;
+}
+static uint32_t io_readw(void *opaque, target_phys_addr_t addr)
+{
+ struct io_fn *s = opaque;
+ uint32_t ret;
+
+ s->in ++;
+ ret = s->mem_read[2](s->opaque, addr);
+ s->in --;
+ if (!s->in)
+ fprintf(stderr, "%08x ---> %08x\n", (uint32_t) addr, ret);
+ return ret;
+}
+static void io_writeb(void *opaque, target_phys_addr_t addr, uint32_t value)
+{
+ struct io_fn *s = opaque;
+
+ if (!s->in)
+ fprintf(stderr, "%08x <--- %02x\n", (uint32_t) addr, value);
+ s->in ++;
+ s->mem_write[0](s->opaque, addr, value);
+ s->in --;
+}
+static void io_writeh(void *opaque, target_phys_addr_t addr, uint32_t value)
+{
+ struct io_fn *s = opaque;
+
+ if (!s->in)
+ fprintf(stderr, "%08x <--- %04x\n", (uint32_t) addr, value);
+ s->in ++;
+ s->mem_write[1](s->opaque, addr, value);
+ s->in --;
+}
+static void io_writew(void *opaque, target_phys_addr_t addr, uint32_t value)
+{
+ struct io_fn *s = opaque;
+
+ if (!s->in)
+ fprintf(stderr, "%08x <--- %08x\n", (uint32_t) addr, value);
+ s->in ++;
+ s->mem_write[2](s->opaque, addr, value);
+ s->in --;
+}
+
+static CPUReadMemoryFunc *io_readfn[] = { io_readb, io_readh, io_readw, };
+static CPUWriteMemoryFunc *io_writefn[] = { io_writeb, io_writeh, io_writew, };
+
+inline static int debug_register_io_memory(int io_index,
+ CPUReadMemoryFunc **mem_read, CPUWriteMemoryFunc **mem_write,
+ void *opaque)
+{
+ struct io_fn *s = qemu_malloc(sizeof(struct io_fn));
+
+ s->mem_read = mem_read;
+ s->mem_write = mem_write;
+ s->opaque = opaque;
+ s->in = 0;
+ return cpu_register_io_memory(io_index, io_readfn, io_writefn, s);
+}
+# define cpu_register_io_memory debug_register_io_memory
+# endif
+
#endif /* hw_omap_h */
Modified: trunk/src/host/qemu-neo1973/hw/omap1_clk.c
===================================================================
--- trunk/src/host/qemu-neo1973/hw/omap1_clk.c 2007-11-09 16:32:22 UTC (rev 3386)
+++ trunk/src/host/qemu-neo1973/hw/omap1_clk.c 2007-11-09 17:12:19 UTC (rev 3387)
@@ -307,6 +307,12 @@
.flags = CLOCK_IN_OMAP1510 | CLOCK_IN_OMAP310,
};
+static struct clk hsab_ck = {
+ .name = "hsab_ck",
+ .parent = &tc_ck,
+ .flags = CLOCK_IN_OMAP1510 | CLOCK_IN_OMAP310,
+};
+
static struct clk rhea1_ck = {
.name = "rhea1_ck",
.parent = &tc_ck,
@@ -359,7 +365,7 @@
static struct clk uart3_1510 = {
.name = "uart3_ck",
/* Direct from ULPD, no real parent */
- .parent = &armper_ck,/* either armper_ck or dpll4 */
+ .parent = &armper_ck, /* either armper_ck or dpll4 */
.rate = 12000000,
.flags = CLOCK_IN_OMAP1510 | CLOCK_IN_OMAP310 | ALWAYS_ENABLED,
};
@@ -395,11 +401,12 @@
.flags = CLOCK_IN_OMAP16XX,
};
-static struct clk usb_dc_ck = {
- .name = "usb_dc_ck",
- /* Direct from ULPD, no parent */
+static struct clk usb_w2fc_mclk = {
+ .name = "usb_w2fc_mclk",
+ .alias = "usb_w2fc_ck",
+ .parent = &ck_48m,
.rate = 48000000,
- .flags = CLOCK_IN_OMAP16XX,
+ .flags = CLOCK_IN_OMAP310 | CLOCK_IN_OMAP1510 | CLOCK_IN_OMAP16XX,
};
static struct clk mclk_1510 = {
@@ -539,6 +546,7 @@
&api_ck,
&lb_ck,
&lbfree_ck,
+ &hsab_ck,
&rhea1_ck,
&rhea2_ck,
&lcd_ck_16xx,
@@ -551,7 +559,6 @@
&uart3_16xx,
&usb_clk0,
&usb_hhc_ck1510, &usb_hhc_ck16xx,
- &usb_dc_ck,
&mclk_1510, &mclk_16xx, &mclk_310,
&bclk_1510, &bclk_16xx, &bclk_310,
&mmc1_ck,
@@ -560,6 +567,7 @@
&cam_exclk,
&cam_lclk,
&clk32k,
+ &usb_w2fc_mclk,
/* Virtual clocks */
&i2c_fck,
&i2c_ick,
@@ -742,4 +750,8 @@
j->multiplier = j->multiplier ?: 1;
j ++;
}
+ for (j = mpu->clks; count --; j ++) {
+ omap_clk_update(j);
+ omap_clk_rate_update(j);
+ }
}
Modified: trunk/src/host/qemu-neo1973/hw/omap_mmc.c
===================================================================
--- trunk/src/host/qemu-neo1973/hw/omap_mmc.c 2007-11-09 16:32:22 UTC (rev 3386)
+++ trunk/src/host/qemu-neo1973/hw/omap_mmc.c 2007-11-09 17:12:19 UTC (rev 3387)
@@ -269,7 +269,7 @@
{
uint16_t i;
struct omap_mmc_s *s = (struct omap_mmc_s *) opaque;
- offset -= s->base;
+ offset &= OMAP_MPUI_REG_MASK;
switch (offset) {
case 0x00: /* MMC_CMD */
@@ -351,7 +351,7 @@
{
int i;
struct omap_mmc_s *s = (struct omap_mmc_s *) opaque;
- offset -= s->base;
+ offset &= OMAP_MPUI_REG_MASK;
switch (offset) {
case 0x00: /* MMC_CMD */
Modified: trunk/src/host/qemu-neo1973/hw/palm.c
===================================================================
--- trunk/src/host/qemu-neo1973/hw/palm.c 2007-11-09 16:32:22 UTC (rev 3386)
+++ trunk/src/host/qemu-neo1973/hw/palm.c 2007-11-09 17:12:19 UTC (rev 3387)
@@ -78,12 +78,18 @@
static void palmte_microwire_setup(struct omap_mpu_state_s *cpu)
{
- qemu_irq p_int = omap_gpio_in_get(cpu->gpio)[PALMTE_PINTDAV_GPIO];
+ struct uwire_slave_s *tsc;
+ AudioState *audio = 0;
- omap_uwire_attach(
- cpu->microwire,
- tsc2102_init(qemu_irq_invert(p_int)),
- 0);
+#ifdef HAS_AUDIO
+ audio = AUD_init();
+#endif
+
+ tsc = tsc2102_init(omap_gpio_in_get(cpu->gpio)[PALMTE_PINTDAV_GPIO],
+ audio);
+
+ omap_uwire_attach(cpu->microwire, tsc, 0);
+ omap_mcbsp_i2s_attach(cpu->mcbsp1, tsc210x_codec(tsc));
}
static struct {
@@ -115,6 +121,62 @@
!(keycode & 0x80));
}
+static void palmte_onoff_gpios(void *opaque, int line, int level)
+{
+ switch (line) {
+ case 0:
+ printf("%s: current to MMC/SD card %sabled.\n",
+ __FUNCTION__, level ? "dis" : "en");
+ break;
+ case 1:
+ printf("%s: internal speaker amplifier %s.\n",
+ __FUNCTION__, level ? "down" : "on");
+ break;
+
+ /* These LCD & Audio output signals have not been identified yet. */
+ case 2:
+ case 3:
+ case 4:
+ printf("%s: LCD GPIO%i %s.\n",
+ __FUNCTION__, line - 1, level ? "high" : "low");
+ break;
+ case 5:
+ case 6:
+ printf("%s: Audio GPIO%i %s.\n",
+ __FUNCTION__, line - 4, level ? "high" : "low");
+ break;
+ }
+}
+
+static void palmte_gpio_setup(struct omap_mpu_state_s *cpu)
+{
+ qemu_irq *misc_gpio;
+
+ omap_mmc_handlers(cpu->mmc,
+ omap_gpio_in_get(cpu->gpio)[PALMTE_MMC_WP_GPIO],
+ qemu_irq_invert(omap_mpuio_in_get(cpu->mpuio)
+ [PALMTE_MMC_SWITCH_GPIO]));
+
+ misc_gpio = qemu_allocate_irqs(palmte_onoff_gpios, cpu, 7);
+ omap_gpio_out_set(cpu->gpio, PALMTE_MMC_POWER_GPIO, misc_gpio[0]);
+ omap_gpio_out_set(cpu->gpio, PALMTE_SPEAKER_GPIO, misc_gpio[1]);
+ omap_gpio_out_set(cpu->gpio, 11, misc_gpio[2]);
+ omap_gpio_out_set(cpu->gpio, 12, misc_gpio[3]);
+ omap_gpio_out_set(cpu->gpio, 13, misc_gpio[4]);
+ omap_mpuio_out_set(cpu->mpuio, 1, misc_gpio[5]);
+ omap_mpuio_out_set(cpu->mpuio, 3, misc_gpio[6]);
+
+ /* Reset some inputs to initial state. */
+ qemu_irq_lower(omap_gpio_in_get(cpu->gpio)[PALMTE_USBDETECT_GPIO]);
+ qemu_irq_lower(omap_gpio_in_get(cpu->gpio)[PALMTE_USB_OR_DC_GPIO]);
+ qemu_irq_lower(omap_gpio_in_get(cpu->gpio)[4]);
+ qemu_irq_lower(omap_gpio_in_get(cpu->gpio)[PALMTE_HEADPHONES_GPIO]);
+ qemu_irq_lower(omap_mpuio_in_get(cpu->mpuio)[PALMTE_DC_GPIO]);
+ qemu_irq_raise(omap_mpuio_in_get(cpu->mpuio)[6]);
+ qemu_irq_raise(omap_mpuio_in_get(cpu->mpuio)[7]);
+ qemu_irq_raise(omap_mpuio_in_get(cpu->mpuio)[11]);
+}
+
static void palmte_init(int ram_size, int vga_ram_size,
const char *boot_device, DisplayState *ds,
const char **fd_filename, int snapshot,
@@ -158,10 +220,7 @@
qemu_add_kbd_event_handler(palmte_button_event, cpu);
- omap_mmc_handlers(cpu->mmc,
- omap_gpio_in_get(cpu->gpio)[PALMTE_MMC_WP_GPIO],
- qemu_irq_invert(omap_mpuio_in_get(cpu->mpuio)
- [PALMTE_MMC_SWITCH_GPIO]));
+ palmte_gpio_setup(cpu);
/* Setup initial (reset) machine state */
if (nb_option_roms) {
Modified: trunk/src/host/qemu-neo1973/hw/pc.c
===================================================================
--- trunk/src/host/qemu-neo1973/hw/pc.c 2007-11-09 16:32:22 UTC (rev 3386)
+++ trunk/src/host/qemu-neo1973/hw/pc.c 2007-11-09 17:12:19 UTC (rev 3387)
@@ -482,7 +482,9 @@
}
/* kernel protocol version */
+#if 0
fprintf(stderr, "header magic: %#x\n", ldl_p(header+0x202));
+#endif
if (ldl_p(header+0x202) == 0x53726448)
protocol = lduw_p(header+0x206);
else
@@ -505,6 +507,7 @@
prot_addr = phys_ram_base + 0x100000;
}
+#if 0
fprintf(stderr,
"qemu: real_addr = %#zx\n"
"qemu: cmdline_addr = %#zx\n"
@@ -512,6 +515,7 @@
real_addr-phys_ram_base,
cmdline_addr-phys_ram_base,
prot_addr-phys_ram_base);
+#endif
/* highest address for loading the initrd */
if (protocol >= 0x203)
@@ -672,7 +676,7 @@
DisplayState *ds, const char **fd_filename, int snapshot,
const char *kernel_filename, const char *kernel_cmdline,
const char *initrd_filename,
- int pci_enabled)
+ int pci_enabled, const char *cpu_model)
{
char buf[1024];
int ret, linux_boot, i;
@@ -688,6 +692,18 @@
linux_boot = (kernel_filename != NULL);
/* init CPUs */
+ if (cpu_model == NULL) {
+#ifdef TARGET_X86_64
+ cpu_model = "qemu64";
+#else
+ cpu_model = "qemu32";
+#endif
+ }
+
+ if (x86_find_cpu_by_name(cpu_model)) {
+ fprintf(stderr, "Unable to find x86 CPU definition\n");
+ exit(1);
+ }
for(i = 0; i < smp_cpus; i++) {
env = cpu_init();
if (i != 0)
@@ -956,7 +972,7 @@
pc_init1(ram_size, vga_ram_size, boot_device,
ds, fd_filename, snapshot,
kernel_filename, kernel_cmdline,
- initrd_filename, 1);
+ initrd_filename, 1, cpu_model);
}
static void pc_init_isa(int ram_size, int vga_ram_size, const char *boot_device,
@@ -970,7 +986,7 @@
pc_init1(ram_size, vga_ram_size, boot_device,
ds, fd_filename, snapshot,
kernel_filename, kernel_cmdline,
- initrd_filename, 0);
+ initrd_filename, 0, cpu_model);
}
QEMUMachine pc_machine = {
Modified: trunk/src/host/qemu-neo1973/hw/ppc_chrp.c
===================================================================
--- trunk/src/host/qemu-neo1973/hw/ppc_chrp.c 2007-11-09 16:32:22 UTC (rev 3386)
+++ trunk/src/host/qemu-neo1973/hw/ppc_chrp.c 2007-11-09 17:12:19 UTC (rev 3387)
@@ -264,7 +264,7 @@
dbdma_init(&dbdma_mem_index);
macio_init(pci_bus, 0x0022, 0, pic_mem_index, dbdma_mem_index,
- cuda_mem_index, -1, 2, ide_mem_index);
+ cuda_mem_index, NULL, 2, ide_mem_index);
if (usb_enabled) {
usb_ohci_init_pci(pci_bus, 3, -1);
@@ -274,9 +274,9 @@
graphic_depth = 15;
#if 0 /* XXX: this is ugly but needed for now, or OHW won't boot */
/* The NewWorld NVRAM is not located in the MacIO device */
- nvr = macio_nvram_init(&nvram_mem_index);
+ nvr = macio_nvram_init(&nvram_mem_index, 0x2000);
pmac_format_nvram_partition(nvr, 0x2000);
- cpu_register_physical_memory(0xFFF04000, 0x20000, nvram_mem_index);
+ macio_nvram_map(nvr, 0xFFF04000);
nvram.opaque = nvr;
nvram.read_fn = &macio_nvram_read;
nvram.write_fn = &macio_nvram_write;
Modified: trunk/src/host/qemu-neo1973/hw/ppc_mac.h
===================================================================
--- trunk/src/host/qemu-neo1973/hw/ppc_mac.h 2007-11-09 16:32:22 UTC (rev 3386)
+++ trunk/src/host/qemu-neo1973/hw/ppc_mac.h 2007-11-09 17:12:19 UTC (rev 3387)
@@ -43,7 +43,7 @@
/* MacIO */
void macio_init (PCIBus *bus, int device_id, int is_oldworld, int pic_mem_index,
- int dbdma_mem_index, int cuda_mem_index, int nvram_mem_index,
+ int dbdma_mem_index, int cuda_mem_index, void *nvram,
int nb_ide, int *ide_mem_index);
/* NewWorld PowerMac IDE */
@@ -62,7 +62,8 @@
/* Mac NVRAM */
typedef struct MacIONVRAMState MacIONVRAMState;
-MacIONVRAMState *macio_nvram_init (int *mem_index);
+MacIONVRAMState *macio_nvram_init (int *mem_index, target_phys_addr_t size);
+void macio_nvram_map (void *opaque, target_phys_addr_t mem_base);
void pmac_format_nvram_partition (MacIONVRAMState *nvr, int len);
uint32_t macio_nvram_read (void *opaque, uint32_t addr);
void macio_nvram_write (void *opaque, uint32_t addr, uint32_t val);
Modified: trunk/src/host/qemu-neo1973/hw/ppc_oldworld.c
===================================================================
--- trunk/src/host/qemu-neo1973/hw/ppc_oldworld.c 2007-11-09 16:32:22 UTC (rev 3386)
+++ trunk/src/host/qemu-neo1973/hw/ppc_oldworld.c 2007-11-09 17:12:19 UTC (rev 3387)
@@ -271,13 +271,13 @@
adb_kbd_init(&adb_bus);
adb_mouse_init(&adb_bus);
- nvr = macio_nvram_init(&nvram_mem_index);
+ nvr = macio_nvram_init(&nvram_mem_index, 0x2000);
pmac_format_nvram_partition(nvr, 0x2000);
dbdma_init(&dbdma_mem_index);
macio_init(pci_bus, 0x0017, 1, pic_mem_index, dbdma_mem_index,
- cuda_mem_index, nvram_mem_index, 0, NULL);
+ cuda_mem_index, nvr, 0, NULL);
if (usb_enabled) {
usb_ohci_init_pci(pci_bus, 3, -1);
Modified: trunk/src/host/qemu-neo1973/hw/slavio_misc.c
===================================================================
--- trunk/src/host/qemu-neo1973/hw/slavio_misc.c 2007-11-09 16:32:22 UTC (rev 3386)
+++ trunk/src/host/qemu-neo1973/hw/slavio_misc.c 2007-11-09 17:12:19 UTC (rev 3387)
@@ -44,10 +44,13 @@
qemu_irq irq;
uint8_t config;
uint8_t aux1, aux2;
- uint8_t diag, mctrl, sysctrl;
+ uint8_t diag, mctrl;
+ uint32_t sysctrl;
} MiscState;
#define MISC_SIZE 1
+#define SYSCTRL_MAXADDR 3
+#define SYSCTRL_SIZE (SYSCTRL_MAXADDR + 1)
static void slavio_misc_update_irq(void *opaque)
{
@@ -83,7 +86,8 @@
slavio_misc_update_irq(s);
}
-static void slavio_misc_mem_writeb(void *opaque, target_phys_addr_t addr, uint32_t val)
+static void slavio_misc_mem_writeb(void *opaque, target_phys_addr_t addr,
+ uint32_t val)
{
MiscState *s = opaque;
@@ -116,13 +120,6 @@
MISC_DPRINTF("Write modem control %2.2x\n", val & 0xff);
s->mctrl = val & 0xff;
break;
- case 0x1f00000:
- MISC_DPRINTF("Write system control %2.2x\n", val & 0xff);
- if (val & 1) {
- s->sysctrl = 0x2;
- qemu_system_reset_request();
- }
- break;
case 0xa000000:
MISC_DPRINTF("Write power management %2.2x\n", val & 0xff);
cpu_interrupt(cpu_single_env, CPU_INTERRUPT_HALT);
@@ -156,10 +153,6 @@
ret = s->mctrl;
MISC_DPRINTF("Read modem control %2.2x\n", ret);
break;
- case 0x1f00000:
- MISC_DPRINTF("Read system control %2.2x\n", ret);
- ret = s->sysctrl;
- break;
case 0xa000000:
MISC_DPRINTF("Read power management %2.2x\n", ret);
break;
@@ -179,10 +172,62 @@
slavio_misc_mem_writeb,
};
+static uint32_t slavio_sysctrl_mem_readl(void *opaque, target_phys_addr_t addr)
+{
+ MiscState *s = opaque;
+ uint32_t ret = 0, saddr;
+
+ saddr = addr & SYSCTRL_MAXADDR;
+ switch (saddr) {
+ case 0:
+ ret = s->sysctrl;
+ break;
+ default:
+ break;
+ }
+ MISC_DPRINTF("Read system control reg 0x" TARGET_FMT_plx " = %x\n", addr,
+ ret);
+ return ret;
+}
+
+static void slavio_sysctrl_mem_writel(void *opaque, target_phys_addr_t addr,
+ uint32_t val)
+{
+ MiscState *s = opaque;
+ uint32_t saddr;
+
+ saddr = addr & SYSCTRL_MAXADDR;
+ MISC_DPRINTF("Write system control reg 0x" TARGET_FMT_plx " = %x\n", addr,
+ val);
+ switch (saddr) {
+ case 0:
+ if (val & 1) {
+ s->sysctrl = 0x2;
+ qemu_system_reset_request();
+ }
+ break;
+ default:
+ break;
+ }
+}
+
+static CPUReadMemoryFunc *slavio_sysctrl_mem_read[3] = {
+ slavio_sysctrl_mem_readl,
+ slavio_sysctrl_mem_readl,
+ slavio_sysctrl_mem_readl,
+};
+
+static CPUWriteMemoryFunc *slavio_sysctrl_mem_write[3] = {
+ slavio_sysctrl_mem_writel,
+ slavio_sysctrl_mem_writel,
+ slavio_sysctrl_mem_writel,
+};
+
static void slavio_misc_save(QEMUFile *f, void *opaque)
{
MiscState *s = opaque;
int tmp;
+ uint8_t tmp8;
tmp = 0;
qemu_put_be32s(f, &tmp); /* ignored, was IRQ. */
@@ -191,13 +236,15 @@
qemu_put_8s(f, &s->aux2);
qemu_put_8s(f, &s->diag);
qemu_put_8s(f, &s->mctrl);
- qemu_put_8s(f, &s->sysctrl);
+ tmp8 = s->sysctrl & 0xff;
+ qemu_put_8s(f, &tmp8);
}
static int slavio_misc_load(QEMUFile *f, void *opaque, int version_id)
{
MiscState *s = opaque;
int tmp;
+ uint8_t tmp8;
if (version_id != 1)
return -EINVAL;
@@ -208,7 +255,8 @@
qemu_get_8s(f, &s->aux2);
qemu_get_8s(f, &s->diag);
qemu_get_8s(f, &s->mctrl);
- qemu_get_8s(f, &s->sysctrl);
+ qemu_get_8s(f, &tmp8);
+ s->sysctrl = (uint32_t)tmp8;
return 0;
}
@@ -222,7 +270,9 @@
if (!s)
return NULL;
- slavio_misc_io_memory = cpu_register_io_memory(0, slavio_misc_mem_read, slavio_misc_mem_write, s);
+ /* 8 bit registers */
+ slavio_misc_io_memory = cpu_register_io_memory(0, slavio_misc_mem_read,
+ slavio_misc_mem_write, s);
// Slavio control
cpu_register_physical_memory(base + 0x1800000, MISC_SIZE,
slavio_misc_io_memory);
@@ -238,15 +288,21 @@
// Modem control
cpu_register_physical_memory(base + 0x1b00000, MISC_SIZE,
slavio_misc_io_memory);
- // System control
- cpu_register_physical_memory(base + 0x1f00000, MISC_SIZE,
- slavio_misc_io_memory);
// Power management
cpu_register_physical_memory(power_base, MISC_SIZE, slavio_misc_io_memory);
+ /* 32 bit registers */
+ slavio_misc_io_memory = cpu_register_io_memory(0, slavio_sysctrl_mem_read,
+ slavio_sysctrl_mem_write,
+ s);
+ // System control
+ cpu_register_physical_memory(base + 0x1f00000, SYSCTRL_SIZE,
+ slavio_misc_io_memory);
+
s->irq = irq;
- register_savevm("slavio_misc", base, 1, slavio_misc_save, slavio_misc_load, s);
+ register_savevm("slavio_misc", base, 1, slavio_misc_save, slavio_misc_load,
+ s);
qemu_register_reset(slavio_misc_reset, s);
slavio_misc_reset(s);
return s;
Modified: trunk/src/host/qemu-neo1973/hw/sun4m.c
===================================================================
--- trunk/src/host/qemu-neo1973/hw/sun4m.c 2007-11-09 16:32:22 UTC (rev 3386)
+++ trunk/src/host/qemu-neo1973/hw/sun4m.c 2007-11-09 17:12:19 UTC (rev 3387)
@@ -389,8 +389,9 @@
// 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]);
- fdctrl_init(slavio_irq[hwdef->fd_irq], 0, 1, hwdef->fd_base, fd_table);
+ sun4m_fdctrl_init(slavio_irq[hwdef->fd_irq], hwdef->fd_base, fd_table);
+
main_esp = esp_init(bs_table, hwdef->esp_base, espdma, *espdma_irq,
esp_reset);
Modified: trunk/src/host/qemu-neo1973/hw/tsc210x.c
===================================================================
--- trunk/src/host/qemu-neo1973/hw/tsc210x.c 2007-11-09 16:32:22 UTC (rev 3386)
+++ trunk/src/host/qemu-neo1973/hw/tsc210x.c 2007-11-09 17:12:19 UTC (rev 3387)
@@ -1,5 +1,5 @@
/*
- * TI TSC2102 (touchscreen/sensors/audio controller) controller.
+ * TI TSC2102 (touchscreen/sensors/audio controller) emulator.
*
* Copyright (c) 2006 Andrzej Zaborowski <balrog at zabor.org>
*
@@ -32,7 +32,11 @@
struct tsc210x_state_s {
qemu_irq pint;
QEMUTimer *timer;
+ QEMUSoundCard card;
struct uwire_slave_s chip;
+ struct i2s_codec_s codec;
+ uint8_t in_fifo[16384];
+ uint8_t out_fifo[16384];
int x, y;
int pressure;
@@ -63,6 +67,13 @@
uint16_t dac_power;
int64_t powerdown;
uint16_t filter_data[0x14];
+
+ const char *name;
+ SWVoiceIn *adc_voice[1];
+ SWVoiceOut *dac_voice[1];
+ int i2s_rx_rate;
+ int i2s_tx_rate;
+ AudioState *audio;
};
static const int resolution[4] = { 12, 8, 10, 12 };
@@ -171,9 +182,144 @@
s->filter_data[0x12] = 0x7d83;
s->filter_data[0x13] = 0x84ee;
- qemu_set_irq(s->pint, s->irq);
+ s->i2s_tx_rate = 0;
+ s->i2s_rx_rate = 0;
+
+ qemu_set_irq(s->pint, !s->irq);
}
+struct tsc210x_rate_info_s {
+ int rate;
+ int dsor;
+ int fsref;
+};
+
+/* { rate, dsor, fsref } */
+static const struct tsc210x_rate_info_s tsc2101_rates[] = {
+ /* Fsref / 6.0 */
+ { 7350, 7, 1 },
+ { 8000, 7, 0 },
+ /* Fsref / 5.5 */
+ { 8018, 6, 1 },
+ { 8727, 6, 0 },
+ /* Fsref / 5.0 */
+ { 8820, 5, 1 },
+ { 9600, 5, 0 },
+ /* Fsref / 4.0 */
+ { 11025, 4, 1 },
+ { 12000, 4, 0 },
+ /* Fsref / 3.0 */
+ { 14700, 3, 1 },
+ { 16000, 3, 0 },
+ /* Fsref / 2.0 */
+ { 22050, 2, 1 },
+ { 24000, 2, 0 },
+ /* Fsref / 1.5 */
+ { 29400, 1, 1 },
+ { 32000, 1, 0 },
+ /* Fsref */
+ { 44100, 0, 1 },
+ { 48000, 0, 0 },
+
+ { 0, 0, 0 },
+};
+
+/* { rate, dsor, fsref } */
+static const struct tsc210x_rate_info_s tsc2102_rates[] = {
+ /* Fsref / 6.0 */
+ { 7350, 63, 1 },
+ { 8000, 63, 0 },
+ /* Fsref / 6.0 */
+ { 7350, 54, 1 },
+ { 8000, 54, 0 },
+ /* Fsref / 5.0 */
+ { 8820, 45, 1 },
+ { 9600, 45, 0 },
+ /* Fsref / 4.0 */
+ { 11025, 36, 1 },
+ { 12000, 36, 0 },
+ /* Fsref / 3.0 */
+ { 14700, 27, 1 },
+ { 16000, 27, 0 },
+ /* Fsref / 2.0 */
+ { 22050, 18, 1 },
+ { 24000, 18, 0 },
+ /* Fsref / 1.5 */
+ { 29400, 9, 1 },
+ { 32000, 9, 0 },
+ /* Fsref */
+ { 44100, 0, 1 },
+ { 48000, 0, 0 },
+
+ { 0, 0, 0 },
+};
+
+static inline void tsc210x_out_flush(struct tsc210x_state_s *s, int len)
+{
+ uint8_t *data = s->codec.out.fifo + s->codec.out.start;
+ uint8_t *end = data + len;
+
+ while (data < end)
+ data += AUD_write(s->dac_voice[0], data, end - data) ?: (end - data);
+
+ s->codec.out.len -= len;
+ if (s->codec.out.len)
+ memmove(s->codec.out.fifo, end, s->codec.out.len);
+ s->codec.out.start = 0;
+}
+
+static void tsc210x_audio_out_cb(struct tsc210x_state_s *s, int free_b)
+{
+ if (s->codec.out.len >= free_b) {
+ tsc210x_out_flush(s, free_b);
+ return;
+ }
+
+ s->codec.out.size = MIN(free_b, 16384);
+ qemu_irq_raise(s->codec.tx_start);
+}
+
+static void tsc2102_audio_set_format(struct tsc210x_state_s *s)
+{
+ int enable;
+ const struct tsc210x_rate_info_s *rate;
+ audsettings_t fmt;
+
+ if (s->dac_voice[0]) {
+ tsc210x_out_flush(s, s->codec.out.len);
+ s->codec.out.size = 0;
+ AUD_set_active_out(s->dac_voice[0], 0);
+ AUD_close_out(&s->card, s->dac_voice[0]);
+ s->dac_voice[0] = 0;
+ }
+
+ enable =
+ (~s->dac_power & (1 << 15)) && /* PWDNC */
+ (~s->dac_power & (1 << 10)); /* DAPWDN */
+ if (!enable)
+ return;
+
+ for (rate = tsc2102_rates; rate->rate; rate ++)
+ if (rate->dsor == (s->audio_ctrl1 & 0x3f) && /* DACFS */
+ rate->fsref == ((s->audio_ctrl3 >> 13) & 1))/* REFFS */
+ break;
+ if (!rate->rate) {
+ printf("%s: unknown sampling rate configured\n", __FUNCTION__);
+ return;
+ }
+
+ /* Force our own sampling rate even in slave DAC mode */
+ fmt.endianness = 0;
+ fmt.nchannels = 2;
+ fmt.freq = rate->rate;
+ fmt.fmt = AUD_FMT_S16;
+
+ s->dac_voice[0] = AUD_open_out(&s->card, s->dac_voice[0],
+ "tsc2102.sink", s, (void *) tsc210x_audio_out_cb, &fmt);
+ if (s->dac_voice[0])
+ AUD_set_active_out(s->dac_voice[0], 1);
+}
+
static uint16_t tsc2102_data_register_read(struct tsc210x_state_s *s, int reg)
{
switch (reg) {
@@ -437,6 +583,8 @@
fprintf(stderr, "tsc2102_audio_register_write: "
"wrong value written into Audio 1\n");
#endif
+ if (s->audio)
+ tsc2102_audio_set_format(s);
return;
case 0x01:
@@ -479,6 +627,8 @@
fprintf(stderr, "tsc2102_audio_register_write: "
"wrong value written into Power\n");
#endif
+ if (s->audio)
+ tsc2102_audio_set_format(s);
return;
case 0x06: /* Audio Control 3 */
@@ -489,6 +639,8 @@
fprintf(stderr, "tsc2102_audio_register_write: "
"wrong value written into Audio 3\n");
#endif
+ if (s->audio)
+ tsc2102_audio_set_format(s);
return;
case 0x07: /* LCH_BASS_BOOST_N0 */
@@ -572,7 +724,7 @@
if (pin_state != s->irq) {
s->irq = pin_state;
- qemu_set_irq(s->pint, s->irq);
+ qemu_set_irq(s->pint, !s->irq);
}
switch (s->nextfunction) {
@@ -718,6 +870,20 @@
tsc210x_pin_update(s);
}
+static void tsc210x_i2s_swallow(struct tsc210x_state_s *s)
+{
+ if (s->dac_voice[0])
+ tsc210x_out_flush(s, s->codec.out.len);
+ else
+ s->codec.out.len = 0;
+}
+
+static void tsc210x_i2s_set_rate(struct tsc210x_state_s *s, int in, int out)
+{
+ s->i2s_tx_rate = out;
+ s->i2s_rx_rate = in;
+}
+
static void tsc210x_save(QEMUFile *f, void *opaque)
{
struct tsc210x_state_s *s = (struct tsc210x_state_s *) opaque;
@@ -810,14 +976,14 @@
qemu_get_be16s(f, &s->filter_data[i]);
s->busy = qemu_timer_pending(s->timer);
- qemu_set_irq(s->pint, s->irq);
+ qemu_set_irq(s->pint, !s->irq);
return 0;
}
static int tsc2102_iid = 0;
-struct uwire_slave_s *tsc2102_init(qemu_irq pint)
+struct uwire_slave_s *tsc2102_init(qemu_irq pint, AudioState *audio)
{
struct tsc210x_state_s *s;
@@ -830,19 +996,37 @@
s->precision = s->nextprecision = 0;
s->timer = qemu_new_timer(vm_clock, tsc210x_timer_tick, s);
s->pint = pint;
+ s->name = "tsc2102";
+ s->audio = audio;
s->chip.opaque = s;
s->chip.send = (void *) tsc210x_write;
s->chip.receive = (void *) tsc210x_read;
+ s->codec.opaque = s;
+ s->codec.tx_swallow = (void *) tsc210x_i2s_swallow;
+ s->codec.set_rate = (void *) tsc210x_i2s_set_rate;
+ s->codec.in.fifo = s->in_fifo;
+ s->codec.out.fifo = s->out_fifo;
+
tsc210x_reset(s);
qemu_add_mouse_event_handler(tsc210x_touchscreen_event, s, 1,
"QEMU TSC2102-driven Touchscreen");
+ if (s->audio)
+ AUD_register_card(s->audio, s->name, &s->card);
+
qemu_register_reset((void *) tsc210x_reset, s);
- register_savevm("tsc2102", tsc2102_iid ++, 0,
+ register_savevm(s->name, tsc2102_iid ++, 0,
tsc210x_save, tsc210x_load, s);
return &s->chip;
}
+
+struct i2s_codec_s *tsc210x_codec(struct uwire_slave_s *chip)
+{
+ struct tsc210x_state_s *s = (struct tsc210x_state_s *) chip->opaque;
+
+ return &s->codec;
+}
Modified: trunk/src/host/qemu-neo1973/linux-user/main.c
===================================================================
--- trunk/src/host/qemu-neo1973/linux-user/main.c 2007-11-09 16:32:22 UTC (rev 3386)
+++ trunk/src/host/qemu-neo1973/linux-user/main.c 2007-11-09 17:12:19 UTC (rev 3387)
@@ -28,11 +28,6 @@
#define DEBUG_LOGFILE "/tmp/qemu.log"
-#ifdef __APPLE__
-#include <crt_externs.h>
-# define environ (*_NSGetEnviron())
-#endif
-
static const char *interp_prefix = CONFIG_QEMU_PREFIX;
const char *qemu_uname_release = CONFIG_UNAME_RELEASE;
@@ -45,12 +40,20 @@
/* for recent libc, we add these dummy symbols which are not declared
when generating a linked object (bug in ld ?) */
#if (__GLIBC__ > 2 || (__GLIBC__ == 2 && __GLIBC_MINOR__ >= 3)) && !defined(CONFIG_STATIC)
-long __preinit_array_start[0];
-long __preinit_array_end[0];
-long __init_array_start[0];
-long __init_array_end[0];
-long __fini_array_start[0];
-long __fini_array_end[0];
+asm(".globl __preinit_array_start\n"
+ ".globl __preinit_array_end\n"
+ ".globl __init_array_start\n"
+ ".globl __init_array_end\n"
+ ".globl __fini_array_start\n"
+ ".globl __fini_array_end\n"
+ ".section \".rodata\"\n"
+ "__preinit_array_start:\n"
+ "__preinit_array_end:\n"
+ "__init_array_start:\n"
+ "__init_array_end:\n"
+ "__fini_array_start:\n"
+ "__fini_array_end:\n"
+ ".long 0\n");
#endif
/* XXX: on x86 MAP_GROWSDOWN only works if ESP <= address + 32, so
@@ -785,7 +788,7 @@
break;
case POWERPC_EXCP_ISI: /* Instruction storage exception */
EXCP_DUMP(env, "Invalid instruction fetch: 0x\n" ADDRX "\n",
- env->spr[SPR_DAR]);
+ env->spr[SPR_SRR0]);
/* XXX: check this */
switch (env->error_code & 0xFF000000) {
case 0x40000000:
@@ -1852,9 +1855,6 @@
"-drop-ld-preload drop LD_PRELOAD for target process\n"
"\n"
"debug options:\n"
-#ifdef USE_CODE_COPY
- "-no-code-copy disable code copy acceleration\n"
-#endif
"-d options activate log (logfile=%s)\n"
"-p pagesize set the host page size to 'pagesize'\n",
TARGET_ARCH,
@@ -1953,11 +1953,6 @@
} else if (!strcmp(r, "drop-ld-preload")) {
drop_ld_preload = 1;
} else
-#ifdef USE_CODE_COPY
- if (!strcmp(r, "no-code-copy")) {
- code_copy_enabled = 0;
- } else
-#endif
{
usage();
}
@@ -1975,6 +1970,23 @@
/* Scan interp_prefix dir for replacement files. */
init_paths(interp_prefix);
+#if defined(TARGET_I386)
+ /* must be done before cpu_init() for x86 XXX: suppress this hack
+ by adding a new parameter to cpu_init and by suppressing
+ cpu_xxx_register() */
+ if (cpu_model == NULL) {
+#ifdef TARGET_X86_64
+ cpu_model = "qemu64";
+#else
+ cpu_model = "qemu32";
+#endif
+ }
+ if (x86_find_cpu_by_name(cpu_model)) {
+ fprintf(stderr, "Unable to find x86 CPU definition\n");
+ exit(1);
+ }
+#endif
+
/* NOTE: we need to init the CPU at this stage to get
qemu_host_page_size */
env = cpu_init();
@@ -2213,7 +2225,7 @@
/* Choose and initialise CPU */
if (cpu_model == NULL)
-#if defined(TARGET_MIPSN32) || defined(TARGET_MIPS64)
+#if defined(TARGET_ABI_MIPSN32) || defined(TARGET_ABI_MIPSN64)
cpu_model = "20Kc";
#else
cpu_model = "24Kf";
Modified: trunk/src/host/qemu-neo1973/linux-user/mmap.c
===================================================================
--- trunk/src/host/qemu-neo1973/linux-user/mmap.c 2007-11-09 16:32:22 UTC (rev 3386)
+++ trunk/src/host/qemu-neo1973/linux-user/mmap.c 2007-11-09 17:12:19 UTC (rev 3387)
@@ -37,7 +37,7 @@
#ifdef DEBUG_MMAP
printf("mprotect: start=0x" TARGET_FMT_lx
- "len=0x" TARGET_FMT_lx " prot=%c%c%c\n", start, len,
+ "len=0x" TARGET_FMT_lx " prot=%c%c%c\n", start, len,
prot & PROT_READ ? 'r' : '-',
prot & PROT_WRITE ? 'w' : '-',
prot & PROT_EXEC ? 'x' : '-');
@@ -100,7 +100,7 @@
abi_ulong start, abi_ulong end,
int prot, int flags, int fd, abi_ulong offset)
{
- abi_ulong real_end, ret, addr;
+ abi_ulong real_end, addr;
void *host_start;
int prot1, prot_new;
@@ -116,10 +116,10 @@
if (prot1 == 0) {
/* no page was there, so we allocate one */
- ret = (long)mmap(host_start, qemu_host_page_size, prot,
- flags | MAP_ANONYMOUS, -1, 0);
- if (ret == -1)
- return ret;
+ void *p = mmap(host_start, qemu_host_page_size, prot,
+ flags | MAP_ANONYMOUS, -1, 0);
+ if (p == MAP_FAILED)
+ return -1;
prot1 = prot;
}
prot1 &= PAGE_BITS;
@@ -168,7 +168,7 @@
#ifdef DEBUG_MMAP
{
printf("mmap: start=0x" TARGET_FMT_lx
- " len=0x" TARGET_FMT_lx " prot=%c%c%c flags=",
+ " len=0x" TARGET_FMT_lx " prot=%c%c%c flags=",
start, len,
prot & PROT_READ ? 'r' : '-',
prot & PROT_WRITE ? 'w' : '-',
@@ -230,16 +230,16 @@
*/
abi_ulong host_end;
unsigned long host_aligned_start;
+ void *p;
host_len = HOST_PAGE_ALIGN(host_len + qemu_host_page_size
- qemu_real_host_page_size);
- host_start = (unsigned long) mmap(real_start ?
- g2h(real_start) : NULL,
- host_len, prot, flags,
- fd, host_offset);
- if (host_start == -1)
+ p = mmap(real_start ? g2h(real_start) : NULL,
+ host_len, prot, flags, fd, host_offset);
+ if (p == MAP_FAILED)
return -1;
+ host_start = (unsigned long)p;
host_end = host_start + host_len;
/* Find start and end, aligned to the targets pagesize with-in the
@@ -260,11 +260,12 @@
goto the_end1;
} else {
/* if not fixed, no need to do anything */
- host_start = (long)mmap(real_start ? g2h(real_start) : NULL,
+ void *p = mmap(real_start ? g2h(real_start) : NULL,
host_len, prot, flags, fd, host_offset);
- if (host_start == -1)
+ if (p == MAP_FAILED)
return -1;
/* update start so that it points to the file position at 'offset' */
+ host_start = (unsigned long)p;
if (!(flags & MAP_ANONYMOUS))
host_start += offset - host_offset;
start = h2g(host_start);
@@ -333,14 +334,15 @@
/* map the middle (easier) */
if (real_start < real_end) {
+ void *p;
unsigned long offset1;
- if (flags & MAP_ANONYMOUS)
- offset1 = 0;
- else
- offset1 = offset + real_start - start;
- ret = (long)mmap(g2h(real_start), real_end - real_start,
- prot, flags, fd, offset1);
- if (ret == -1)
+ if (flags & MAP_ANONYMOUS)
+ offset1 = 0;
+ else
+ offset1 = offset + real_start - start;
+ p = mmap(g2h(real_start), real_end - real_start,
+ prot, flags, fd, offset1);
+ if (p == MAP_FAILED)
return -1;
}
the_end1:
Modified: trunk/src/host/qemu-neo1973/linux-user/qemu.h
===================================================================
--- trunk/src/host/qemu-neo1973/linux-user/qemu.h 2007-11-09 16:32:22 UTC (rev 3386)
+++ trunk/src/host/qemu-neo1973/linux-user/qemu.h 2007-11-09 17:12:19 UTC (rev 3387)
@@ -9,10 +9,16 @@
#ifdef TARGET_ABI32
typedef uint32_t abi_ulong;
typedef int32_t abi_long;
+#define TARGET_ABI_FMT_lx "%08x"
+#define TARGET_ABI_FMT_ld "%d"
+#define TARGET_ABI_FMT_lu "%u"
#define TARGET_ABI_BITS 32
#else
typedef target_ulong abi_ulong;
typedef target_long abi_long;
+#define TARGET_ABI_FMT_lx TARGET_FMT_lx
+#define TARGET_ABI_FMT_ld TARGET_FMT_ld
+#define TARGET_ABI_FMT_lu TARGET_FMT_lu
#define TARGET_ABI_BITS TARGET_LONG_BITS
#endif
@@ -203,24 +209,25 @@
#define VERIFY_READ 0
#define VERIFY_WRITE 1
-#define access_ok(type,addr,size) (1)
+#define access_ok(type,addr,size) \
+ (page_check_range((target_ulong)addr,size,(type==VERIFY_READ)?PAGE_READ:PAGE_WRITE)==0)
-/* NOTE get_user and put_user use host addresses. */
-#define __put_user(x,ptr)\
+/* NOTE __get_user and __put_user use host pointers and don't check access. */
+#define __put_user(x, hptr)\
({\
- int size = sizeof(*ptr);\
+ int size = sizeof(*hptr);\
switch(size) {\
case 1:\
- *(uint8_t *)(ptr) = (typeof(*ptr))(x);\
+ *(uint8_t *)(hptr) = (typeof(*hptr))(x);\
break;\
case 2:\
- *(uint16_t *)(ptr) = tswap16((typeof(*ptr))(x));\
+ *(uint16_t *)(hptr) = tswap16((typeof(*hptr))(x));\
break;\
case 4:\
- *(uint32_t *)(ptr) = tswap32((typeof(*ptr))(x));\
+ *(uint32_t *)(hptr) = tswap32((typeof(*hptr))(x));\
break;\
case 8:\
- *(uint64_t *)(ptr) = tswap64((typeof(*ptr))(x));\
+ *(uint64_t *)(hptr) = tswap64((typeof(*hptr))(x));\
break;\
default:\
abort();\
@@ -228,21 +235,21 @@
0;\
})
-#define __get_user(x, ptr) \
+#define __get_user(x, hptr) \
({\
- int size = sizeof(*ptr);\
+ int size = sizeof(*hptr);\
switch(size) {\
case 1:\
- x = (typeof(*ptr))*(uint8_t *)(ptr);\
+ x = (typeof(*hptr))*(uint8_t *)(hptr);\
break;\
case 2:\
- x = (typeof(*ptr))tswap16(*(uint16_t *)(ptr));\
+ x = (typeof(*hptr))tswap16(*(uint16_t *)(hptr));\
break;\
case 4:\
- x = (typeof(*ptr))tswap32(*(uint32_t *)(ptr));\
+ x = (typeof(*hptr))tswap32(*(uint32_t *)(hptr));\
break;\
case 8:\
- x = (typeof(*ptr))tswap64(*(uint64_t *)(ptr));\
+ x = (typeof(*hptr))tswap64(*(uint64_t *)(hptr));\
break;\
default:\
abort();\
Modified: trunk/src/host/qemu-neo1973/linux-user/signal.c
===================================================================
--- trunk/src/host/qemu-neo1973/linux-user/signal.c 2007-11-09 16:32:22 UTC (rev 3386)
+++ trunk/src/host/qemu-neo1973/linux-user/signal.c 2007-11-09 17:12:19 UTC (rev 3387)
@@ -415,11 +415,7 @@
/* the CPU emulator uses some host signals to detect exceptions,
we we forward to it some signals */
- if (host_signum == SIGSEGV || host_signum == SIGBUS
-#if defined(TARGET_I386) && defined(USE_CODE_COPY)
- || host_signum == SIGFPE
-#endif
- ) {
+ if (host_signum == SIGSEGV || host_signum == SIGBUS) {
if (cpu_signal_handler(host_signum, info, puc))
return;
}
@@ -1943,7 +1939,7 @@
force_sig(SIGSEGV);
}
#endif
-#elif defined(TARGET_MIPS64)
+#elif defined(TARGET_ABI_MIPSN64)
# warning signal handling not implemented
@@ -1972,7 +1968,7 @@
return -ENOSYS;
}
-#elif defined(TARGET_MIPSN32)
+#elif defined(TARGET_ABI_MIPSN32)
# warning signal handling not implemented
@@ -2001,7 +1997,7 @@
return -ENOSYS;
}
-#elif defined(TARGET_MIPS)
+#elif defined(TARGET_ABI_MIPSO32)
struct target_sigcontext {
uint32_t sc_regmask; /* Unused */
Modified: trunk/src/host/qemu-neo1973/linux-user/strace.c
===================================================================
--- trunk/src/host/qemu-neo1973/linux-user/strace.c 2007-11-09 16:32:22 UTC (rev 3386)
+++ trunk/src/host/qemu-neo1973/linux-user/strace.c 2007-11-09 17:12:19 UTC (rev 3387)
@@ -106,7 +106,8 @@
return;
tv = lock_user(tv_addr, sizeof(*tv), 1);
- gemu_log("{%d,%d}", tv->tv_sec, tv->tv_usec);
+ gemu_log("{" TARGET_ABI_FMT_ld "," TARGET_ABI_FMT_ld "}",
+ tv->tv_sec, tv->tv_usec);
unlock_user(tv, tv_addr, 0);
} else
gemu_log("NULL");
@@ -220,12 +221,15 @@
}
}
+#if 0 /* currently unused */
static void
print_syscall_ret_raw(struct syscallname *name, target_long ret)
{
gemu_log(" = " TARGET_FMT_lx "\n", ret);
}
+#endif
+#ifdef TARGET_NR__newselect
static void
print_syscall_ret_newselect(struct syscallname *name, target_long ret)
{
@@ -239,6 +243,7 @@
print_timeval(newselect_arg5);
gemu_log(")\n");
}
+#endif
/*
* An array of all of the syscalls we know about
Modified: trunk/src/host/qemu-neo1973/linux-user/syscall_defs.h
===================================================================
--- trunk/src/host/qemu-neo1973/linux-user/syscall_defs.h 2007-11-09 16:32:22 UTC (rev 3386)
+++ trunk/src/host/qemu-neo1973/linux-user/syscall_defs.h 2007-11-09 17:12:19 UTC (rev 3387)
@@ -307,8 +307,8 @@
#define TARGET_SA_NODEFER 0x40000000
#define TARGET_SA_RESTART 0x10000000
#define TARGET_SA_RESETHAND 0x80000000
-#if !defined(TARGET_MIPSN32) && !defined(TARGET_MIPS64)
-#define TARGET_SA_RESTORER 0x04000000 /* Only for o32 */
+#if !defined(TARGET_ABI_MIPSN32) && !defined(TARGET_ABI_MIPSN64)
+#define TARGET_SA_RESTORER 0x04000000 /* Only for O32 */
#endif
#else
#define TARGET_SA_NOCLDSTOP 0x00000001
@@ -450,7 +450,7 @@
struct target_sigaction {
uint32_t sa_flags;
-#if defined(TARGET_MIPSN32)
+#if defined(TARGET_ABI_MIPSN32)
uint32_t _sa_handler;
#else
abi_ulong _sa_handler;
@@ -1194,7 +1194,7 @@
unsigned long long st_ino;
} __attribute__((packed));
-#elif defined(TARGET_MIPS64)
+#elif defined(TARGET_ABI_MIPSN64)
/* The memory layout is the same as of struct stat64 of the 32-bit kernel. */
struct target_stat {
@@ -1233,7 +1233,7 @@
abi_ulong st_blocks;
};
-#elif defined(TARGET_MIPSN32)
+#elif defined(TARGET_ABI_MIPSN32)
struct target_stat {
unsigned st_dev;
@@ -1304,7 +1304,7 @@
int st_blocks;
};
-#elif defined(TARGET_MIPS)
+#elif defined(TARGET_ABI_MIPSO32)
struct target_stat {
unsigned st_dev;
@@ -1486,7 +1486,7 @@
} target_fsid_t;
#ifdef TARGET_MIPS
-#ifdef TARGET_MIPSN32
+#ifdef TARGET_ABI_MIPSN32
struct target_statfs {
int32_t f_type;
int32_t f_bsize;
Modified: trunk/src/host/qemu-neo1973/qemu-doc.texi
===================================================================
--- trunk/src/host/qemu-neo1973/qemu-doc.texi 2007-11-09 16:32:22 UTC (rev 3386)
+++ trunk/src/host/qemu-neo1973/qemu-doc.texi 2007-11-09 17:12:19 UTC (rev 3387)
@@ -83,6 +83,7 @@
@item Spitz, Akita, Borzoi and Terrier PDAs (PXA270 processor)
@item Freescale MCF5208EVB (ColdFire V2).
@item Arnewsh MCF5206 evaluation board (ColdFire V2).
+ at item Palm Tungsten|E PDA (OMAP310 processor)
@end itemize
For user emulation, x86, PowerPC, ARM, MIPS, Sparc32/64 and ColdFire(m68k) CPUs are supported.
@@ -267,6 +268,11 @@
time). This option is needed to have correct date in MS-DOS or
Windows.
+ at item -startdate date
+Set the initial date of the real time clock. Valid format for
+ at var{date} are: @code{now} or @code{2006-06-17T16:01:21} or
+ at code{2006-06-17}. The default value is @code{now}.
+
@item -pidfile file
Store the QEMU process PID in @var{file}. It is useful if you launch QEMU
from a script.
@@ -2208,6 +2214,29 @@
WM8750 audio CODEC on I at math{^2}C and I at math{^2}S busses
@end itemize
+The Palm Tungsten|E PDA (codename "Cheetah") emulation includes the
+following elements:
+
+ at itemize @minus
+ at item
+Texas Instruments OMAP310 System-on-chip (ARM 925T core)
+ at item
+ROM and RAM memories (ROM firmware image can be loaded with -option-rom)
+ at item
+On-chip LCD controller
+ at item
+On-chip Real Time Clock
+ at item
+TI TSC2102i touchscreen controller / analog-digital converter / Audio
+CODEC, connected through MicroWire and I at math{^2}S busses
+ at item
+GPIO-connected matrix keypad
+ at item
+Secure Digital card connected to OMAP MMC/SD host
+ at item
+Three on-chip UARTs
+ at end itemize
+
A Linux 2.6 test image is available on the QEMU web site. More
information is available in the QEMU mailing-list archive.
Added: trunk/src/host/qemu-neo1973/slirp/.cvsignore
===================================================================
--- trunk/src/host/qemu-neo1973/slirp/.cvsignore 2007-11-09 16:32:22 UTC (rev 3386)
+++ trunk/src/host/qemu-neo1973/slirp/.cvsignore 2007-11-09 17:12:19 UTC (rev 3387)
@@ -0,0 +1 @@
+*.d
Modified: trunk/src/host/qemu-neo1973/slirp/misc.h
===================================================================
--- trunk/src/host/qemu-neo1973/slirp/misc.h 2007-11-09 16:32:22 UTC (rev 3386)
+++ trunk/src/host/qemu-neo1973/slirp/misc.h 2007-11-09 17:12:19 UTC (rev 3387)
@@ -63,7 +63,9 @@
struct emu_t *next;
};
+#ifndef CONFIG_QEMU
extern struct emu_t *tcpemu;
+#endif
extern int x_port, x_server, x_display;
Modified: trunk/src/host/qemu-neo1973/slirp/slirp.h
===================================================================
--- trunk/src/host/qemu-neo1973/slirp/slirp.h 2007-11-09 16:32:22 UTC (rev 3386)
+++ trunk/src/host/qemu-neo1973/slirp/slirp.h 2007-11-09 17:12:19 UTC (rev 3387)
@@ -17,7 +17,7 @@
#ifndef CONFIG_QEMU
#include "version.h"
#endif
-#include "config.h"
+#include "config-host.h"
#include "slirp_config.h"
#ifdef _WIN32
Modified: trunk/src/host/qemu-neo1973/slirp/tcp_subr.c
===================================================================
--- trunk/src/host/qemu-neo1973/slirp/tcp_subr.c 2007-11-09 16:32:22 UTC (rev 3386)
+++ trunk/src/host/qemu-neo1973/slirp/tcp_subr.c 2007-11-09 17:12:19 UTC (rev 3387)
@@ -559,7 +559,10 @@
{0, 0, 0, 0}
};
-static struct emu_t *tcpemu = 0;
+#ifdef CONFIG_QEMU
+static
+#endif
+struct emu_t *tcpemu = 0;
/*
* Return TOS according to the above table
Modified: trunk/src/host/qemu-neo1973/target-alpha/op.c
===================================================================
--- trunk/src/host/qemu-neo1973/target-alpha/op.c 2007-11-09 16:32:22 UTC (rev 3386)
+++ trunk/src/host/qemu-neo1973/target-alpha/op.c 2007-11-09 17:12:19 UTC (rev 3387)
@@ -22,6 +22,7 @@
#include "config.h"
#include "exec.h"
+#include "host-utils.h"
#include "op_helper.h"
Modified: trunk/src/host/qemu-neo1973/target-i386/cpu.h
===================================================================
--- trunk/src/host/qemu-neo1973/target-i386/cpu.h 2007-11-09 16:32:22 UTC (rev 3386)
+++ trunk/src/host/qemu-neo1973/target-i386/cpu.h 2007-11-09 17:12:19 UTC (rev 3387)
@@ -46,10 +46,6 @@
#include "softfloat.h"
-#if defined(__i386__) && !defined(CONFIG_SOFTMMU) && !defined(__APPLE__)
-#define USE_CODE_COPY
-#endif
-
#define R_EAX 0
#define R_ECX 1
#define R_EDX 2
@@ -274,23 +270,56 @@
#define CPUID_CMOV (1 << 15)
#define CPUID_PAT (1 << 16)
#define CPUID_PSE36 (1 << 17)
+#define CPUID_PN (1 << 18)
#define CPUID_CLFLUSH (1 << 19)
-/* ... */
+#define CPUID_DTS (1 << 21)
+#define CPUID_ACPI (1 << 22)
#define CPUID_MMX (1 << 23)
#define CPUID_FXSR (1 << 24)
#define CPUID_SSE (1 << 25)
#define CPUID_SSE2 (1 << 26)
+#define CPUID_SS (1 << 27)
+#define CPUID_HT (1 << 28)
+#define CPUID_TM (1 << 29)
+#define CPUID_IA64 (1 << 30)
+#define CPUID_PBE (1 << 31)
#define CPUID_EXT_SSE3 (1 << 0)
#define CPUID_EXT_MONITOR (1 << 3)
+#define CPUID_EXT_DSCPL (1 << 4)
+#define CPUID_EXT_VMX (1 << 5)
+#define CPUID_EXT_SMX (1 << 6)
+#define CPUID_EXT_EST (1 << 7)
+#define CPUID_EXT_TM2 (1 << 8)
+#define CPUID_EXT_SSSE3 (1 << 9)
+#define CPUID_EXT_CID (1 << 10)
#define CPUID_EXT_CX16 (1 << 13)
+#define CPUID_EXT_XTPR (1 << 14)
+#define CPUID_EXT_DCA (1 << 17)
+#define CPUID_EXT_POPCNT (1 << 22)
#define CPUID_EXT2_SYSCALL (1 << 11)
+#define CPUID_EXT2_MP (1 << 19)
#define CPUID_EXT2_NX (1 << 20)
+#define CPUID_EXT2_MMXEXT (1 << 22)
#define CPUID_EXT2_FFXSR (1 << 25)
+#define CPUID_EXT2_PDPE1GB (1 << 26)
+#define CPUID_EXT2_RDTSCP (1 << 27)
#define CPUID_EXT2_LM (1 << 29)
+#define CPUID_EXT2_3DNOWEXT (1 << 30)
+#define CPUID_EXT2_3DNOW (1 << 31)
+#define CPUID_EXT3_LAHF_LM (1 << 0)
+#define CPUID_EXT3_CMP_LEG (1 << 1)
#define CPUID_EXT3_SVM (1 << 2)
+#define CPUID_EXT3_EXTAPIC (1 << 3)
+#define CPUID_EXT3_CR8LEG (1 << 4)
+#define CPUID_EXT3_ABM (1 << 5)
+#define CPUID_EXT3_SSE4A (1 << 6)
+#define CPUID_EXT3_MISALIGNSSE (1 << 7)
+#define CPUID_EXT3_3DNOWPREFETCH (1 << 8)
+#define CPUID_EXT3_OSVW (1 << 9)
+#define CPUID_EXT3_IBS (1 << 10)
#define EXCP00_DIVZ 0
#define EXCP01_SSTP 1
@@ -519,13 +548,6 @@
uint64_t pat;
- /* temporary data for USE_CODE_COPY mode */
-#ifdef USE_CODE_COPY
- uint32_t tmp0;
- uint32_t saved_esp;
- int native_fp_regs; /* if true, the FPU state is in the native CPU regs */
-#endif
-
/* exception/interrupt handling */
jmp_buf jmp_env;
int exception_index;
@@ -566,6 +588,9 @@
CPUX86State *cpu_x86_init(void);
int cpu_x86_exec(CPUX86State *s);
void cpu_x86_close(CPUX86State *s);
+int x86_find_cpu_by_name (const unsigned char *name);
+void x86_cpu_list (FILE *f, int (*cpu_fprintf)(FILE *f, const char *fmt,
+ ...));
int cpu_get_pic_interrupt(CPUX86State *s);
/* MSDOS compatibility mode FPU exception support */
void cpu_set_ferr(CPUX86State *s);
@@ -689,6 +714,7 @@
#define cpu_exec cpu_x86_exec
#define cpu_gen_code cpu_x86_gen_code
#define cpu_signal_handler cpu_x86_signal_handler
+#define cpu_list x86_cpu_list
/* MMU modes definitions */
#define MMU_MODE0_SUFFIX _kernel
Modified: trunk/src/host/qemu-neo1973/target-i386/helper.c
===================================================================
--- trunk/src/host/qemu-neo1973/target-i386/helper.c 2007-11-09 16:32:22 UTC (rev 3386)
+++ trunk/src/host/qemu-neo1973/target-i386/helper.c 2007-11-09 17:12:19 UTC (rev 3387)
@@ -18,6 +18,7 @@
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#include "exec.h"
+#include "host-utils.h"
//#define DEBUG_PCALL
Modified: trunk/src/host/qemu-neo1973/target-i386/helper2.c
===================================================================
--- trunk/src/host/qemu-neo1973/target-i386/helper2.c 2007-11-09 16:32:22 UTC (rev 3386)
+++ trunk/src/host/qemu-neo1973/target-i386/helper2.c 2007-11-09 17:12:19 UTC (rev 3387)
@@ -31,21 +31,67 @@
//#define DEBUG_MMU
-#ifdef USE_CODE_COPY
-#include <asm/ldt.h>
-#include <linux/unistd.h>
-#include <linux/version.h>
+static struct x86_def_t *x86_cpu_def;
+typedef struct x86_def_t x86_def_t;
+static int cpu_x86_register (CPUX86State *env, const x86_def_t *def);
-int modify_ldt(int func, void *ptr, unsigned long bytecount)
+static void add_flagname_to_bitmaps(char *flagname, uint32_t *features,
+ uint32_t *ext_features,
+ uint32_t *ext2_features,
+ uint32_t *ext3_features)
{
- return syscall(__NR_modify_ldt, func, ptr, bytecount);
+ int i;
+ /* feature flags taken from "Intel Processor Identification and the CPUID
+ * Instruction" and AMD's "CPUID Specification". In cases of disagreement
+ * about feature names, the Linux name is used. */
+ const char *feature_name[] = {
+ "fpu", "vme", "de", "pse", "tsc", "msr", "pae", "mce",
+ "cx8", "apic", NULL, "sep", "mtrr", "pge", "mca", "cmov",
+ "pat", "pse36", "pn" /* Intel psn */, "clflush" /* Intel clfsh */, NULL, "ds" /* Intel dts */, "acpi", "mmx",
+ "fxsr", "sse", "sse2", "ss", "ht" /* Intel htt */, "tm", "ia64", "pbe",
+ };
+ const char *ext_feature_name[] = {
+ "pni" /* Intel,AMD sse3 */, NULL, NULL, "monitor", "ds_cpl", "vmx", NULL /* Linux smx */, "est",
+ "tm2", "ssse3", "cid", NULL, NULL, "cx16", "xtpr", NULL,
+ NULL, NULL, "dca", NULL, NULL, NULL, NULL, "popcnt",
+ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
+ };
+ const char *ext2_feature_name[] = {
+ "fpu", "vme", "de", "pse", "tsc", "msr", "pae", "mce",
+ "cx8" /* AMD CMPXCHG8B */, "apic", NULL, "syscall", "mttr", "pge", "mca", "cmov",
+ "pat", "pse36", NULL, NULL /* Linux mp */, "nx" /* Intel xd */, NULL, "mmxext", "mmx",
+ "fxsr", "fxsr_opt" /* AMD ffxsr */, "pdpe1gb" /* AMD Page1GB */, "rdtscp", NULL, "lm" /* Intel 64 */, "3dnowext", "3dnow",
+ };
+ const char *ext3_feature_name[] = {
+ "lahf_lm" /* AMD LahfSahf */, "cmp_legacy", "svm", "extapic" /* AMD ExtApicSpace */, "cr8legacy" /* AMD AltMovCr8 */, "abm", "sse4a", "misalignsse",
+ "3dnowprefetch", "osvw", NULL /* Linux ibs */, NULL, "skinit", "wdt", NULL, NULL,
+ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
+ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
+ };
+
+ for ( i = 0 ; i < 32 ; i++ )
+ if (feature_name[i] && !strcmp (flagname, feature_name[i])) {
+ *features |= 1 << i;
+ return;
+ }
+ for ( i = 0 ; i < 32 ; i++ )
+ if (ext_feature_name[i] && !strcmp (flagname, ext_feature_name[i])) {
+ *ext_features |= 1 << i;
+ return;
+ }
+ for ( i = 0 ; i < 32 ; i++ )
+ if (ext2_feature_name[i] && !strcmp (flagname, ext2_feature_name[i])) {
+ *ext2_features |= 1 << i;
+ return;
+ }
+ for ( i = 0 ; i < 32 ; i++ )
+ if (ext3_features[i] && !strcmp (flagname, ext3_feature_name[i])) {
+ *ext3_features |= 1 << i;
+ return;
+ }
+ fprintf(stderr, "CPU feature %s not found\n", flagname);
}
-#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 5, 66)
-#define modify_ldt_ldt_s user_desc
-#endif
-#endif /* USE_CODE_COPY */
-
CPUX86State *cpu_x86_init(void)
{
CPUX86State *env;
@@ -61,90 +107,219 @@
inited = 1;
optimize_flags_init();
}
-#ifdef USE_CODE_COPY
- /* testing code for code copy case */
+ cpu_x86_register(env, x86_cpu_def);
+ cpu_reset(env);
+#ifdef USE_KQEMU
+ kqemu_init(env);
+#endif
+ return env;
+}
+
+struct x86_def_t {
+ const char *name;
+ uint32_t vendor1, vendor2, vendor3;
+ int family;
+ int model;
+ int stepping;
+ uint32_t features, ext_features, ext2_features, ext3_features;
+ uint32_t xlevel;
+};
+
+#define PPRO_FEATURES (CPUID_FP87 | CPUID_DE | CPUID_PSE | CPUID_TSC | \
+ CPUID_MSR | CPUID_MCE | CPUID_CX8 | CPUID_PGE | CPUID_CMOV | \
+ CPUID_PAT | CPUID_FXSR | CPUID_MMX | CPUID_SSE | CPUID_SSE2 | \
+ CPUID_PAE | CPUID_SEP | CPUID_APIC)
+static x86_def_t x86_defs[] = {
+#ifdef TARGET_X86_64
{
- struct modify_ldt_ldt_s ldt;
+ .name = "qemu64",
+ .vendor1 = 0x68747541, /* "Auth" */
+ .vendor2 = 0x69746e65, /* "enti" */
+ .vendor3 = 0x444d4163, /* "cAMD" */
+ .family = 6,
+ .model = 2,
+ .stepping = 3,
+ .features = PPRO_FEATURES |
+ /* these features are needed for Win64 and aren't fully implemented */
+ CPUID_MTRR | CPUID_CLFLUSH | CPUID_MCA |
+ /* this feature is needed for Solaris and isn't fully implemented */
+ CPUID_PSE36,
+ .ext_features = CPUID_EXT_SSE3,
+ .ext2_features = (PPRO_FEATURES & 0x0183F3FF) |
+ CPUID_EXT2_LM | CPUID_EXT2_SYSCALL | CPUID_EXT2_NX,
+ .ext3_features = CPUID_EXT3_SVM,
+ .xlevel = 0x80000008,
+ },
+#endif
+ {
+ .name = "qemu32",
+ .family = 6,
+ .model = 3,
+ .stepping = 3,
+ .features = PPRO_FEATURES,
+ .ext_features = CPUID_EXT_SSE3,
+ .xlevel = 0,
+ },
+ {
+ .name = "486",
+ .family = 4,
+ .model = 0,
+ .stepping = 0,
+ .features = 0x0000000B,
+ .xlevel = 0,
+ },
+ {
+ .name = "pentium",
+ .family = 5,
+ .model = 4,
+ .stepping = 3,
+ .features = 0x008001BF,
+ .xlevel = 0,
+ },
+ {
+ .name = "pentium2",
+ .family = 6,
+ .model = 5,
+ .stepping = 2,
+ .features = 0x0183F9FF,
+ .xlevel = 0,
+ },
+ {
+ .name = "pentium3",
+ .family = 6,
+ .model = 7,
+ .stepping = 3,
+ .features = 0x0383F9FF,
+ .xlevel = 0,
+ },
+};
- ldt.entry_number = 1;
- ldt.base_addr = (unsigned long)env;
- ldt.limit = (sizeof(CPUState) + 0xfff) >> 12;
- ldt.seg_32bit = 1;
- ldt.contents = MODIFY_LDT_CONTENTS_DATA;
- ldt.read_exec_only = 0;
- ldt.limit_in_pages = 1;
- ldt.seg_not_present = 0;
- ldt.useable = 1;
- modify_ldt(1, &ldt, sizeof(ldt)); /* write ldt entry */
+int x86_find_cpu_by_name(const unsigned char *cpu_model)
+{
+ int ret;
+ unsigned int i;
- asm volatile ("movl %0, %%fs" : : "r" ((1 << 3) | 7));
+ char *s = strdup(cpu_model);
+ char *featurestr, *name = strtok(s, ",");
+ uint32_t plus_features = 0, plus_ext_features = 0, plus_ext2_features = 0, plus_ext3_features = 0;
+ uint32_t minus_features = 0, minus_ext_features = 0, minus_ext2_features = 0, minus_ext3_features = 0;
+ int family = -1, model = -1, stepping = -1;
+
+ ret = -1;
+ x86_cpu_def = NULL;
+ for (i = 0; i < sizeof(x86_defs) / sizeof(x86_def_t); i++) {
+ if (strcmp(name, x86_defs[i].name) == 0) {
+ x86_cpu_def = &x86_defs[i];
+ ret = 0;
+ break;
+ }
}
-#endif
- {
- int family, model, stepping;
-#ifdef TARGET_X86_64
- env->cpuid_vendor1 = 0x68747541; /* "Auth" */
- env->cpuid_vendor2 = 0x69746e65; /* "enti" */
- env->cpuid_vendor3 = 0x444d4163; /* "cAMD" */
- family = 6;
- model = 2;
- stepping = 3;
-#else
+ if (!x86_cpu_def)
+ goto error;
+
+ featurestr = strtok(NULL, ",");
+
+ while (featurestr) {
+ char *val;
+ if (featurestr[0] == '+') {
+ add_flagname_to_bitmaps(featurestr + 1, &plus_features, &plus_ext_features, &plus_ext2_features, &plus_ext3_features);
+ } else if (featurestr[0] == '-') {
+ add_flagname_to_bitmaps(featurestr + 1, &minus_features, &minus_ext_features, &minus_ext2_features, &minus_ext3_features);
+ } else if ((val = strchr(featurestr, '='))) {
+ *val = 0; val++;
+ if (!strcmp(featurestr, "family")) {
+ char *err;
+ family = strtol(val, &err, 10);
+ if (!*val || *err || family < 0) {
+ fprintf(stderr, "bad numerical value %s\n", val);
+ x86_cpu_def = 0;
+ goto error;
+ }
+ x86_cpu_def->family = family;
+ } else if (!strcmp(featurestr, "model")) {
+ char *err;
+ model = strtol(val, &err, 10);
+ if (!*val || *err || model < 0 || model > 0xf) {
+ fprintf(stderr, "bad numerical value %s\n", val);
+ x86_cpu_def = 0;
+ goto error;
+ }
+ x86_cpu_def->model = model;
+ } else if (!strcmp(featurestr, "stepping")) {
+ char *err;
+ stepping = strtol(val, &err, 10);
+ if (!*val || *err || stepping < 0 || stepping > 0xf) {
+ fprintf(stderr, "bad numerical value %s\n", val);
+ x86_cpu_def = 0;
+ goto error;
+ }
+ x86_cpu_def->stepping = stepping;
+ } else {
+ fprintf(stderr, "unregnized feature %s\n", featurestr);
+ x86_cpu_def = 0;
+ goto error;
+ }
+ } else {
+ fprintf(stderr, "feature string `%s' not in format (+feature|-feature|feature=xyz)\n", featurestr);
+ x86_cpu_def = 0;
+ goto error;
+ }
+ featurestr = strtok(NULL, ",");
+ }
+ x86_cpu_def->features |= plus_features;
+ x86_cpu_def->ext_features |= plus_ext_features;
+ x86_cpu_def->ext2_features |= plus_ext2_features;
+ x86_cpu_def->ext3_features |= plus_ext3_features;
+ x86_cpu_def->features &= ~minus_features;
+ x86_cpu_def->ext_features &= ~minus_ext_features;
+ x86_cpu_def->ext2_features &= ~minus_ext2_features;
+ x86_cpu_def->ext3_features &= ~minus_ext3_features;
+
+error:
+ free(s);
+ return ret;
+}
+
+void x86_cpu_list (FILE *f, int (*cpu_fprintf)(FILE *f, const char *fmt, ...))
+{
+ unsigned int i;
+
+ for (i = 0; i < sizeof(x86_defs) / sizeof(x86_def_t); i++)
+ (*cpu_fprintf)(f, "x86 %16s\n", x86_defs[i].name);
+}
+
+int cpu_x86_register (CPUX86State *env, const x86_def_t *def)
+{
+ if (def->vendor1) {
+ env->cpuid_vendor1 = def->vendor1;
+ env->cpuid_vendor2 = def->vendor2;
+ env->cpuid_vendor3 = def->vendor3;
+ } else {
env->cpuid_vendor1 = 0x756e6547; /* "Genu" */
env->cpuid_vendor2 = 0x49656e69; /* "ineI" */
env->cpuid_vendor3 = 0x6c65746e; /* "ntel" */
-#if 0
- /* pentium 75-200 */
- family = 5;
- model = 2;
- stepping = 11;
-#else
- /* pentium pro */
- family = 6;
- model = 3;
- stepping = 3;
-#endif
-#endif
- env->cpuid_level = 2;
- env->cpuid_version = (family << 8) | (model << 4) | stepping;
- env->cpuid_features = (CPUID_FP87 | CPUID_DE | CPUID_PSE |
- CPUID_TSC | CPUID_MSR | CPUID_MCE |
- CPUID_CX8 | CPUID_PGE | CPUID_CMOV |
- CPUID_PAT);
- env->pat = 0x0007040600070406ULL;
- env->cpuid_ext3_features = CPUID_EXT3_SVM;
- env->cpuid_ext_features = CPUID_EXT_SSE3;
- env->cpuid_features |= CPUID_FXSR | CPUID_MMX | CPUID_SSE | CPUID_SSE2 | CPUID_PAE | CPUID_SEP;
- env->cpuid_features |= CPUID_APIC;
- env->cpuid_xlevel = 0x8000000e;
- {
- const char *model_id = "QEMU Virtual CPU version " QEMU_VERSION;
- int c, len, i;
- len = strlen(model_id);
- for(i = 0; i < 48; i++) {
- if (i >= len)
- c = '\0';
- else
- c = model_id[i];
- env->cpuid_model[i >> 2] |= c << (8 * (i & 3));
- }
+ }
+ env->cpuid_level = 2;
+ env->cpuid_version = (def->family << 8) | (def->model << 4) | def->stepping;
+ env->cpuid_features = def->features;
+ env->pat = 0x0007040600070406ULL;
+ env->cpuid_ext_features = def->ext_features;
+ env->cpuid_ext2_features = def->ext2_features;
+ env->cpuid_xlevel = def->xlevel;
+ env->cpuid_ext3_features = def->ext3_features;
+ {
+ const char *model_id = "QEMU Virtual CPU version " QEMU_VERSION;
+ int c, len, i;
+ len = strlen(model_id);
+ for(i = 0; i < 48; i++) {
+ if (i >= len)
+ c = '\0';
+ else
+ c = model_id[i];
+ env->cpuid_model[i >> 2] |= c << (8 * (i & 3));
}
-#ifdef TARGET_X86_64
- /* currently not enabled for std i386 because not fully tested */
- env->cpuid_ext2_features = (env->cpuid_features & 0x0183F3FF);
- env->cpuid_ext2_features |= CPUID_EXT2_LM | CPUID_EXT2_SYSCALL | CPUID_EXT2_NX;
-
- /* these features are needed for Win64 and aren't fully implemented */
- env->cpuid_features |= CPUID_MTRR | CPUID_CLFLUSH | CPUID_MCA;
- /* this feature is needed for Solaris and isn't fully implemented */
- env->cpuid_features |= CPUID_PSE36;
-#endif
}
- cpu_reset(env);
-#ifdef USE_KQEMU
- kqemu_init(env);
-#endif
- return env;
+ return 0;
}
/* NOTE: must be called outside the CPU execute loop */
@@ -184,7 +359,7 @@
cpu_x86_load_seg_cache(env, R_GS, 0, 0, 0xffff, 0);
env->eip = 0xfff0;
- env->regs[R_EDX] = 0x600; /* indicate P6 processor */
+ env->regs[R_EDX] = env->cpuid_version;
env->eflags = 0x2;
@@ -976,73 +1151,3 @@
return paddr;
}
#endif /* !CONFIG_USER_ONLY */
-
-#if defined(USE_CODE_COPY)
-struct fpstate {
- uint16_t fpuc;
- uint16_t dummy1;
- uint16_t fpus;
- uint16_t dummy2;
- uint16_t fptag;
- uint16_t dummy3;
-
- uint32_t fpip;
- uint32_t fpcs;
- uint32_t fpoo;
- uint32_t fpos;
- uint8_t fpregs1[8 * 10];
-};
-
-void restore_native_fp_state(CPUState *env)
-{
- int fptag, i, j;
- struct fpstate fp1, *fp = &fp1;
-
- fp->fpuc = env->fpuc;
- fp->fpus = (env->fpus & ~0x3800) | (env->fpstt & 0x7) << 11;
- fptag = 0;
- for (i=7; i>=0; i--) {
- fptag <<= 2;
- if (env->fptags[i]) {
- fptag |= 3;
- } else {
- /* the FPU automatically computes it */
- }
- }
- fp->fptag = fptag;
- j = env->fpstt;
- for(i = 0;i < 8; i++) {
- memcpy(&fp->fpregs1[i * 10], &env->fpregs[j].d, 10);
- j = (j + 1) & 7;
- }
- asm volatile ("frstor %0" : "=m" (*fp));
- env->native_fp_regs = 1;
-}
-
-void save_native_fp_state(CPUState *env)
-{
- int fptag, i, j;
- uint16_t fpuc;
- struct fpstate fp1, *fp = &fp1;
-
- asm volatile ("fsave %0" : : "m" (*fp));
- env->fpuc = fp->fpuc;
- env->fpstt = (fp->fpus >> 11) & 7;
- env->fpus = fp->fpus & ~0x3800;
- fptag = fp->fptag;
- for(i = 0;i < 8; i++) {
- env->fptags[i] = ((fptag & 3) == 3);
- fptag >>= 2;
- }
- j = env->fpstt;
- for(i = 0;i < 8; i++) {
- memcpy(&env->fpregs[j].d, &fp->fpregs1[i * 10], 10);
- j = (j + 1) & 7;
- }
- /* we must restore the default rounding state */
- /* XXX: we do not restore the exception state */
- fpuc = 0x037f | (env->fpuc & (3 << 10));
- asm volatile("fldcw %0" : : "m" (fpuc));
- env->native_fp_regs = 0;
-}
-#endif
Deleted: trunk/src/host/qemu-neo1973/target-i386/translate-copy.c
===================================================================
--- trunk/src/host/qemu-neo1973/target-i386/translate-copy.c 2007-11-09 16:32:22 UTC (rev 3386)
+++ trunk/src/host/qemu-neo1973/target-i386/translate-copy.c 2007-11-09 17:12:19 UTC (rev 3387)
@@ -1,1323 +0,0 @@
-/*
- * i386 on i386 translation
- *
- * Copyright (c) 2003 Fabrice Bellard
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- */
-#include "config.h"
-
-#include <stdarg.h>
-#include <stdlib.h>
-#include <stdio.h>
-#include <string.h>
-#include <inttypes.h>
-#include <assert.h>
-
-#include "cpu.h"
-#include "exec-all.h"
-#include "disas.h"
-
-#ifdef USE_CODE_COPY
-
-#include <signal.h>
-#include <sys/mman.h>
-#include <sys/ucontext.h>
-
-extern char exec_loop;
-
-/* operand size */
-enum {
- OT_BYTE = 0,
- OT_WORD,
- OT_LONG,
- OT_QUAD,
-};
-
-#define PREFIX_REPZ 0x01
-#define PREFIX_REPNZ 0x02
-#define PREFIX_LOCK 0x04
-#define PREFIX_DATA 0x08
-#define PREFIX_ADR 0x10
-
-typedef struct DisasContext {
- /* current insn context */
- int override; /* -1 if no override */
- int prefix;
- int aflag, dflag;
- target_ulong pc; /* pc = eip + cs_base */
- int is_jmp; /* 1 = means jump (stop translation), 2 means CPU
- static state change (stop translation) */
- /* code output */
- uint8_t *gen_code_ptr;
- uint8_t *gen_code_start;
-
- /* current block context */
- target_ulong cs_base; /* base of CS segment */
- int pe; /* protected mode */
- int code32; /* 32 bit code segment */
- int f_st; /* currently unused */
- int vm86; /* vm86 mode */
- int cpl;
- int iopl;
- int flags;
- struct TranslationBlock *tb;
-} DisasContext;
-
-#define CPU_FIELD_OFFSET(field) offsetof(CPUState, field)
-
-#define CPU_SEG 0x64 /* fs override */
-
-static inline void gb(DisasContext *s, uint32_t val)
-{
- *s->gen_code_ptr++ = val;
-}
-
-static inline void gw(DisasContext *s, uint32_t val)
-{
- *s->gen_code_ptr++ = val;
- *s->gen_code_ptr++ = val >> 8;
-}
-
-static inline void gl(DisasContext *s, uint32_t val)
-{
- *s->gen_code_ptr++ = val;
- *s->gen_code_ptr++ = val >> 8;
- *s->gen_code_ptr++ = val >> 16;
- *s->gen_code_ptr++ = val >> 24;
-}
-
-static inline void gjmp(DisasContext *s, long val)
-{
- gb(s, 0xe9); /* jmp */
- gl(s, val - (long)(s->gen_code_ptr + 4));
-}
-
-static inline void gen_movl_addr_im(DisasContext *s,
- uint32_t addr, uint32_t val)
-{
- gb(s, CPU_SEG); /* seg movl im, addr */
- gb(s, 0xc7);
- gb(s, 0x05);
- gl(s, addr);
- gl(s, val);
-}
-
-static inline void gen_movw_addr_im(DisasContext *s,
- uint32_t addr, uint32_t val)
-{
- gb(s, CPU_SEG); /* seg movl im, addr */
- gb(s, 0x66);
- gb(s, 0xc7);
- gb(s, 0x05);
- gl(s, addr);
- gw(s, val);
-}
-
-
-static void gen_jmp(DisasContext *s, uint32_t target_eip)
-{
- TranslationBlock *tb = s->tb;
-
- gb(s, 0xe9); /* jmp */
- tb->tb_jmp_offset[0] = s->gen_code_ptr - s->gen_code_start;
- gl(s, 0);
-
- tb->tb_next_offset[0] = s->gen_code_ptr - s->gen_code_start;
- gen_movl_addr_im(s, CPU_FIELD_OFFSET(eip), target_eip);
- gen_movl_addr_im(s, CPU_FIELD_OFFSET(tmp0), (uint32_t)tb);
- gjmp(s, (long)&exec_loop);
-
- s->is_jmp = 1;
-}
-
-static void gen_jcc(DisasContext *s, int op,
- uint32_t target_eip, uint32_t next_eip)
-{
- TranslationBlock *tb = s->tb;
-
- gb(s, 0x0f); /* jcc */
- gb(s, 0x80 + op);
- tb->tb_jmp_offset[0] = s->gen_code_ptr - s->gen_code_start;
- gl(s, 0);
- gb(s, 0xe9); /* jmp */
- tb->tb_jmp_offset[1] = s->gen_code_ptr - s->gen_code_start;
- gl(s, 0);
-
- tb->tb_next_offset[0] = s->gen_code_ptr - s->gen_code_start;
- gen_movl_addr_im(s, CPU_FIELD_OFFSET(eip), target_eip);
- gen_movl_addr_im(s, CPU_FIELD_OFFSET(tmp0), (uint32_t)tb);
- gjmp(s, (long)&exec_loop);
-
- tb->tb_next_offset[1] = s->gen_code_ptr - s->gen_code_start;
- gen_movl_addr_im(s, CPU_FIELD_OFFSET(eip), next_eip);
- gen_movl_addr_im(s, CPU_FIELD_OFFSET(tmp0), (uint32_t)tb | 1);
- gjmp(s, (long)&exec_loop);
-
- s->is_jmp = 1;
-}
-
-static void gen_eob(DisasContext *s)
-{
- gen_movl_addr_im(s, CPU_FIELD_OFFSET(tmp0), 0);
- gjmp(s, (long)&exec_loop);
-
- s->is_jmp = 1;
-}
-
-static inline void gen_lea_modrm(DisasContext *s, int modrm)
-{
- int havesib;
- int base, disp;
- int index;
- int scale;
- int mod, rm, code;
-
- mod = (modrm >> 6) & 3;
- rm = modrm & 7;
-
- if (s->aflag) {
-
- havesib = 0;
- base = rm;
- index = 0;
- scale = 0;
-
- if (base == 4) {
- havesib = 1;
- code = ldub_code(s->pc++);
- scale = (code >> 6) & 3;
- index = (code >> 3) & 7;
- base = code & 7;
- }
-
- switch (mod) {
- case 0:
- if (base == 5) {
- base = -1;
- disp = ldl_code(s->pc);
- s->pc += 4;
- } else {
- disp = 0;
- }
- break;
- case 1:
- disp = (int8_t)ldub_code(s->pc++);
- break;
- default:
- case 2:
- disp = ldl_code(s->pc);
- s->pc += 4;
- break;
- }
-
- } else {
- switch (mod) {
- case 0:
- if (rm == 6) {
- disp = lduw_code(s->pc);
- s->pc += 2;
- } else {
- disp = 0;
- }
- break;
- case 1:
- disp = (int8_t)ldub_code(s->pc++);
- break;
- default:
- case 2:
- disp = lduw_code(s->pc);
- s->pc += 2;
- break;
- }
- }
-}
-
-static inline void parse_modrm(DisasContext *s, int modrm)
-{
- if ((modrm & 0xc0) != 0xc0)
- gen_lea_modrm(s, modrm);
-}
-
-static inline uint32_t insn_get(DisasContext *s, int ot)
-{
- uint32_t ret;
-
- switch(ot) {
- case OT_BYTE:
- ret = ldub_code(s->pc);
- s->pc++;
- break;
- case OT_WORD:
- ret = lduw_code(s->pc);
- s->pc += 2;
- break;
- default:
- case OT_LONG:
- ret = ldl_code(s->pc);
- s->pc += 4;
- break;
- }
- return ret;
-}
-
-/* convert one instruction. s->is_jmp is set if the translation must
- be stopped. */
-static int disas_insn(DisasContext *s)
-{
- target_ulong pc_start, pc_tmp, pc_start_insn;
- int b, prefixes, aflag, dflag, next_eip, val;
- int ot;
- int modrm, mod, op, rm;
-
- pc_start = s->pc;
- prefixes = 0;
- aflag = s->code32;
- dflag = s->code32;
- s->override = -1;
- next_byte:
- b = ldub_code(s->pc);
- s->pc++;
- /* check prefixes */
- switch (b) {
- case 0xf3:
- prefixes |= PREFIX_REPZ;
- goto next_byte;
- case 0xf2:
- prefixes |= PREFIX_REPNZ;
- goto next_byte;
- case 0xf0:
- prefixes |= PREFIX_LOCK;
- goto next_byte;
- case 0x2e:
- s->override = R_CS;
- goto next_byte;
- case 0x36:
- s->override = R_SS;
- goto next_byte;
- case 0x3e:
- s->override = R_DS;
- goto next_byte;
- case 0x26:
- s->override = R_ES;
- goto next_byte;
- case 0x64:
- s->override = R_FS;
- goto next_byte;
- case 0x65:
- s->override = R_GS;
- goto next_byte;
- case 0x66:
- prefixes |= PREFIX_DATA;
- goto next_byte;
- case 0x67:
- prefixes |= PREFIX_ADR;
- goto next_byte;
- }
-
- if (prefixes & PREFIX_DATA)
- dflag ^= 1;
- if (prefixes & PREFIX_ADR)
- aflag ^= 1;
-
- s->prefix = prefixes;
- s->aflag = aflag;
- s->dflag = dflag;
-
- /* lock generation */
- if (prefixes & PREFIX_LOCK)
- goto unsupported_op;
- if (s->override == R_FS || s->override == R_GS || s->override == R_CS)
- goto unsupported_op;
-
- pc_start_insn = s->pc - 1;
- /* now check op code */
- reswitch:
- switch(b) {
- case 0x0f:
- /**************************/
- /* extended op code */
- b = ldub_code(s->pc++) | 0x100;
- goto reswitch;
-
- /**************************/
- /* arith & logic */
- case 0x00 ... 0x05:
- case 0x08 ... 0x0d:
- case 0x10 ... 0x15:
- case 0x18 ... 0x1d:
- case 0x20 ... 0x25:
- case 0x28 ... 0x2d:
- case 0x30 ... 0x35:
- case 0x38 ... 0x3d:
- {
- int f;
- f = (b >> 1) & 3;
-
- if ((b & 1) == 0)
- ot = OT_BYTE;
- else
- ot = dflag ? OT_LONG : OT_WORD;
-
- switch(f) {
- case 0: /* OP Ev, Gv */
- modrm = ldub_code(s->pc++);
- parse_modrm(s, modrm);
- break;
- case 1: /* OP Gv, Ev */
- modrm = ldub_code(s->pc++);
- parse_modrm(s, modrm);
- break;
- case 2: /* OP A, Iv */
- insn_get(s, ot);
- break;
- }
- }
- break;
-
- case 0x80: /* GRP1 */
- case 0x81:
- case 0x82:
- case 0x83:
- {
- if ((b & 1) == 0)
- ot = OT_BYTE;
- else
- ot = dflag ? OT_LONG : OT_WORD;
-
- modrm = ldub_code(s->pc++);
- parse_modrm(s, modrm);
-
- switch(b) {
- default:
- case 0x80:
- case 0x81:
- case 0x82:
- insn_get(s, ot);
- break;
- case 0x83:
- insn_get(s, OT_BYTE);
- break;
- }
- }
- break;
-
- /**************************/
- /* inc, dec, and other misc arith */
- case 0x40 ... 0x47: /* inc Gv */
- break;
- case 0x48 ... 0x4f: /* dec Gv */
- break;
- case 0xf6: /* GRP3 */
- case 0xf7:
- if ((b & 1) == 0)
- ot = OT_BYTE;
- else
- ot = dflag ? OT_LONG : OT_WORD;
-
- modrm = ldub_code(s->pc++);
- op = (modrm >> 3) & 7;
- parse_modrm(s, modrm);
-
- switch(op) {
- case 0: /* test */
- insn_get(s, ot);
- break;
- case 2: /* not */
- break;
- case 3: /* neg */
- break;
- case 4: /* mul */
- break;
- case 5: /* imul */
- break;
- case 6: /* div */
- break;
- case 7: /* idiv */
- break;
- default:
- goto illegal_op;
- }
- break;
-
- case 0xfe: /* GRP4 */
- case 0xff: /* GRP5 */
- if ((b & 1) == 0)
- ot = OT_BYTE;
- else
- ot = dflag ? OT_LONG : OT_WORD;
-
- modrm = ldub_code(s->pc++);
- mod = (modrm >> 6) & 3;
- op = (modrm >> 3) & 7;
- if (op >= 2 && b == 0xfe) {
- goto illegal_op;
- }
- pc_tmp = s->pc;
- parse_modrm(s, modrm);
-
- switch(op) {
- case 0: /* inc Ev */
- break;
- case 1: /* dec Ev */
- break;
- case 2: /* call Ev */
- /* XXX: optimize and handle MEM exceptions specifically
- fs movl %eax, regs[0]
- movl Ev, %eax
- pushl next_eip
- fs movl %eax, eip
- */
- goto unsupported_op;
- case 3: /* lcall Ev */
- goto unsupported_op;
- case 4: /* jmp Ev */
- /* XXX: optimize and handle MEM exceptions specifically
- fs movl %eax, regs[0]
- movl Ev, %eax
- fs movl %eax, eip
- */
- goto unsupported_op;
- case 5: /* ljmp Ev */
- goto unsupported_op;
- case 6: /* push Ev */
- break;
- default:
- goto illegal_op;
- }
- break;
- case 0xa8: /* test eAX, Iv */
- case 0xa9:
- if ((b & 1) == 0)
- ot = OT_BYTE;
- else
- ot = dflag ? OT_LONG : OT_WORD;
- insn_get(s, ot);
- break;
-
- case 0x98: /* CWDE/CBW */
- break;
- case 0x99: /* CDQ/CWD */
- break;
- case 0x1af: /* imul Gv, Ev */
- case 0x69: /* imul Gv, Ev, I */
- case 0x6b:
- ot = dflag ? OT_LONG : OT_WORD;
- modrm = ldub_code(s->pc++);
- parse_modrm(s, modrm);
- if (b == 0x69) {
- insn_get(s, ot);
- } else if (b == 0x6b) {
- insn_get(s, OT_BYTE);
- } else {
- }
- break;
-
- case 0x84: /* test Ev, Gv */
- case 0x85:
-
- case 0x1c0:
- case 0x1c1: /* xadd Ev, Gv */
-
- case 0x1b0:
- case 0x1b1: /* cmpxchg Ev, Gv */
-
- case 0x8f: /* pop Ev */
-
- case 0x88:
- case 0x89: /* mov Gv, Ev */
-
- case 0x8a:
- case 0x8b: /* mov Ev, Gv */
-
- case 0x1b6: /* movzbS Gv, Eb */
- case 0x1b7: /* movzwS Gv, Eb */
- case 0x1be: /* movsbS Gv, Eb */
- case 0x1bf: /* movswS Gv, Eb */
-
- case 0x86:
- case 0x87: /* xchg Ev, Gv */
-
- case 0xd0:
- case 0xd1: /* shift Ev,1 */
-
- case 0xd2:
- case 0xd3: /* shift Ev,cl */
-
- case 0x1a5: /* shld cl */
- case 0x1ad: /* shrd cl */
-
- case 0x190 ... 0x19f: /* setcc Gv */
-
- /* XXX: emulate cmov if not available ? */
- case 0x140 ... 0x14f: /* cmov Gv, Ev */
-
- case 0x1a3: /* bt Gv, Ev */
- case 0x1ab: /* bts */
- case 0x1b3: /* btr */
- case 0x1bb: /* btc */
-
- case 0x1bc: /* bsf */
- case 0x1bd: /* bsr */
-
- modrm = ldub_code(s->pc++);
- parse_modrm(s, modrm);
- break;
-
- case 0x1c7: /* cmpxchg8b */
- modrm = ldub_code(s->pc++);
- mod = (modrm >> 6) & 3;
- if (mod == 3)
- goto illegal_op;
- parse_modrm(s, modrm);
- break;
-
- /**************************/
- /* push/pop */
- case 0x50 ... 0x57: /* push */
- case 0x58 ... 0x5f: /* pop */
- case 0x60: /* pusha */
- case 0x61: /* popa */
- break;
-
- case 0x68: /* push Iv */
- case 0x6a:
- ot = dflag ? OT_LONG : OT_WORD;
- if (b == 0x68)
- insn_get(s, ot);
- else
- insn_get(s, OT_BYTE);
- break;
- case 0xc8: /* enter */
- lduw_code(s->pc);
- s->pc += 2;
- ldub_code(s->pc++);
- break;
- case 0xc9: /* leave */
- break;
-
- case 0x06: /* push es */
- case 0x0e: /* push cs */
- case 0x16: /* push ss */
- case 0x1e: /* push ds */
- /* XXX: optimize:
- push segs[n].selector
- */
- goto unsupported_op;
- case 0x1a0: /* push fs */
- case 0x1a8: /* push gs */
- goto unsupported_op;
- case 0x07: /* pop es */
- case 0x17: /* pop ss */
- case 0x1f: /* pop ds */
- goto unsupported_op;
- case 0x1a1: /* pop fs */
- case 0x1a9: /* pop gs */
- goto unsupported_op;
- case 0x8e: /* mov seg, Gv */
- /* XXX: optimize:
- fs movl r, regs[]
- movl segs[].selector, r
- mov r, Gv
- fs movl regs[], r
- */
- goto unsupported_op;
- case 0x8c: /* mov Gv, seg */
- goto unsupported_op;
- case 0xc4: /* les Gv */
- op = R_ES;
- goto do_lxx;
- case 0xc5: /* lds Gv */
- op = R_DS;
- goto do_lxx;
- case 0x1b2: /* lss Gv */
- op = R_SS;
- goto do_lxx;
- case 0x1b4: /* lfs Gv */
- op = R_FS;
- goto do_lxx;
- case 0x1b5: /* lgs Gv */
- op = R_GS;
- do_lxx:
- goto unsupported_op;
- /************************/
- /* floats */
- case 0xd8 ... 0xdf:
-#if 1
- /* currently not stable enough */
- goto unsupported_op;
-#else
- if (s->flags & (HF_EM_MASK | HF_TS_MASK))
- goto unsupported_op;
-#endif
-#if 0
- /* for testing FPU context switch */
- {
- static int count;
- count = (count + 1) % 3;
- if (count != 0)
- goto unsupported_op;
- }
-#endif
- modrm = ldub_code(s->pc++);
- mod = (modrm >> 6) & 3;
- rm = modrm & 7;
- op = ((b & 7) << 3) | ((modrm >> 3) & 7);
- if (mod != 3) {
- /* memory op */
- parse_modrm(s, modrm);
- switch(op) {
- case 0x00 ... 0x07: /* fxxxs */
- case 0x10 ... 0x17: /* fixxxl */
- case 0x20 ... 0x27: /* fxxxl */
- case 0x30 ... 0x37: /* fixxx */
- break;
- case 0x08: /* flds */
- case 0x0a: /* fsts */
- case 0x0b: /* fstps */
- case 0x18: /* fildl */
- case 0x1a: /* fistl */
- case 0x1b: /* fistpl */
- case 0x28: /* fldl */
- case 0x2a: /* fstl */
- case 0x2b: /* fstpl */
- case 0x38: /* filds */
- case 0x3a: /* fists */
- case 0x3b: /* fistps */
- case 0x0c: /* fldenv mem */
- case 0x0d: /* fldcw mem */
- case 0x0e: /* fnstenv mem */
- case 0x0f: /* fnstcw mem */
- case 0x1d: /* fldt mem */
- case 0x1f: /* fstpt mem */
- case 0x2c: /* frstor mem */
- case 0x2e: /* fnsave mem */
- case 0x2f: /* fnstsw mem */
- case 0x3c: /* fbld */
- case 0x3e: /* fbstp */
- case 0x3d: /* fildll */
- case 0x3f: /* fistpll */
- break;
- default:
- goto illegal_op;
- }
- } else {
- /* register float ops */
- switch(op) {
- case 0x08: /* fld sti */
- case 0x09: /* fxchg sti */
- break;
- case 0x0a: /* grp d9/2 */
- switch(rm) {
- case 0: /* fnop */
- break;
- default:
- goto illegal_op;
- }
- break;
- case 0x0c: /* grp d9/4 */
- switch(rm) {
- case 0: /* fchs */
- case 1: /* fabs */
- case 4: /* ftst */
- case 5: /* fxam */
- break;
- default:
- goto illegal_op;
- }
- break;
- case 0x0d: /* grp d9/5 */
- switch(rm) {
- case 0:
- case 1:
- case 2:
- case 3:
- case 4:
- case 5:
- case 6:
- break;
- default:
- goto illegal_op;
- }
- break;
- case 0x0e: /* grp d9/6 */
- break;
- case 0x0f: /* grp d9/7 */
- break;
- case 0x00: case 0x01: case 0x04 ... 0x07: /* fxxx st, sti */
- case 0x20: case 0x21: case 0x24 ... 0x27: /* fxxx sti, st */
- case 0x30: case 0x31: case 0x34 ... 0x37: /* fxxxp sti, st */
- break;
- case 0x02: /* fcom */
- break;
- case 0x03: /* fcomp */
- break;
- case 0x15: /* da/5 */
- switch(rm) {
- case 1: /* fucompp */
- break;
- default:
- goto illegal_op;
- }
- break;
- case 0x1c:
- switch(rm) {
- case 0: /* feni (287 only, just do nop here) */
- case 1: /* fdisi (287 only, just do nop here) */
- goto unsupported_op;
- case 2: /* fclex */
- case 3: /* fninit */
- case 4: /* fsetpm (287 only, just do nop here) */
- break;
- default:
- goto illegal_op;
- }
- break;
- case 0x1d: /* fucomi */
- break;
- case 0x1e: /* fcomi */
- break;
- case 0x28: /* ffree sti */
- break;
- case 0x2a: /* fst sti */
- break;
- case 0x2b: /* fstp sti */
- break;
- case 0x2c: /* fucom st(i) */
- break;
- case 0x2d: /* fucomp st(i) */
- break;
- case 0x33: /* de/3 */
- switch(rm) {
- case 1: /* fcompp */
- break;
- default:
- goto illegal_op;
- }
- break;
- case 0x3c: /* df/4 */
- switch(rm) {
- case 0:
- break;
- default:
- goto illegal_op;
- }
- break;
- case 0x3d: /* fucomip */
- break;
- case 0x3e: /* fcomip */
- break;
- case 0x10 ... 0x13: /* fcmovxx */
- case 0x18 ... 0x1b:
- break;
- default:
- goto illegal_op;
- }
- }
- s->tb->cflags |= CF_TB_FP_USED;
- break;
-
- /**************************/
- /* mov */
- case 0xc6:
- case 0xc7: /* mov Ev, Iv */
- if ((b & 1) == 0)
- ot = OT_BYTE;
- else
- ot = dflag ? OT_LONG : OT_WORD;
- modrm = ldub_code(s->pc++);
- parse_modrm(s, modrm);
- insn_get(s, ot);
- break;
-
- case 0x8d: /* lea */
- ot = dflag ? OT_LONG : OT_WORD;
- modrm = ldub_code(s->pc++);
- mod = (modrm >> 6) & 3;
- if (mod == 3)
- goto illegal_op;
- parse_modrm(s, modrm);
- break;
-
- case 0xa0: /* mov EAX, Ov */
- case 0xa1:
- case 0xa2: /* mov Ov, EAX */
- case 0xa3:
- if ((b & 1) == 0)
- ot = OT_BYTE;
- else
- ot = dflag ? OT_LONG : OT_WORD;
- if (s->aflag)
- insn_get(s, OT_LONG);
- else
- insn_get(s, OT_WORD);
- break;
- case 0xd7: /* xlat */
- break;
- case 0xb0 ... 0xb7: /* mov R, Ib */
- insn_get(s, OT_BYTE);
- break;
- case 0xb8 ... 0xbf: /* mov R, Iv */
- ot = dflag ? OT_LONG : OT_WORD;
- insn_get(s, ot);
- break;
-
- case 0x91 ... 0x97: /* xchg R, EAX */
- break;
-
- /************************/
- /* shifts */
- case 0xc0:
- case 0xc1: /* shift Ev,imm */
-
- case 0x1a4: /* shld imm */
- case 0x1ac: /* shrd imm */
- modrm = ldub_code(s->pc++);
- parse_modrm(s, modrm);
- ldub_code(s->pc++);
- break;
-
- /************************/
- /* string ops */
-
- case 0xa4: /* movsS */
- case 0xa5:
- break;
-
- case 0xaa: /* stosS */
- case 0xab:
- break;
-
- case 0xac: /* lodsS */
- case 0xad:
- break;
-
- case 0xae: /* scasS */
- case 0xaf:
- break;
-
- case 0xa6: /* cmpsS */
- case 0xa7:
- break;
-
- case 0x6c: /* insS */
- case 0x6d:
- goto unsupported_op;
-
- case 0x6e: /* outsS */
- case 0x6f:
- goto unsupported_op;
-
- /************************/
- /* port I/O */
- case 0xe4:
- case 0xe5:
- goto unsupported_op;
-
- case 0xe6:
- case 0xe7:
- goto unsupported_op;
-
- case 0xec:
- case 0xed:
- goto unsupported_op;
-
- case 0xee:
- case 0xef:
- goto unsupported_op;
-
- /************************/
- /* control */
-#if 0
- case 0xc2: /* ret im */
- val = ldsw_code(s->pc);
- s->pc += 2;
- gen_pop_T0(s);
- gen_stack_update(s, val + (2 << s->dflag));
- if (s->dflag == 0)
- gen_op_andl_T0_ffff();
- gen_op_jmp_T0();
- gen_eob(s);
- break;
-#endif
-
- case 0xc3: /* ret */
- gb(s, CPU_SEG);
- if (!s->dflag)
- gb(s, 0x66); /* d16 */
- gb(s, 0x8f); /* pop addr */
- gb(s, 0x05);
- gl(s, CPU_FIELD_OFFSET(eip));
- if (!s->dflag) {
- /* reset high bits of EIP */
- gen_movw_addr_im(s, CPU_FIELD_OFFSET(eip) + 2, 0);
- }
- gen_eob(s);
- goto no_copy;
- case 0xca: /* lret im */
- case 0xcb: /* lret */
- case 0xcf: /* iret */
- case 0x9a: /* lcall im */
- case 0xea: /* ljmp im */
- goto unsupported_op;
-
- case 0xe8: /* call im */
- ot = dflag ? OT_LONG : OT_WORD;
- val = insn_get(s, ot);
- next_eip = s->pc - s->cs_base;
- val += next_eip;
- if (s->dflag) {
- gb(s, 0x68); /* pushl imm */
- gl(s, next_eip);
- } else {
- gb(s, 0x66); /* pushw imm */
- gb(s, 0x68);
- gw(s, next_eip);
- val &= 0xffff;
- }
- gen_jmp(s, val);
- goto no_copy;
- case 0xe9: /* jmp */
- ot = dflag ? OT_LONG : OT_WORD;
- val = insn_get(s, ot);
- val += s->pc - s->cs_base;
- if (s->dflag == 0)
- val = val & 0xffff;
- gen_jmp(s, val);
- goto no_copy;
- case 0xeb: /* jmp Jb */
- val = (int8_t)insn_get(s, OT_BYTE);
- val += s->pc - s->cs_base;
- if (s->dflag == 0)
- val = val & 0xffff;
- gen_jmp(s, val);
- goto no_copy;
- case 0x70 ... 0x7f: /* jcc Jb */
- val = (int8_t)insn_get(s, OT_BYTE);
- goto do_jcc;
- case 0x180 ... 0x18f: /* jcc Jv */
- if (dflag) {
- val = insn_get(s, OT_LONG);
- } else {
- val = (int16_t)insn_get(s, OT_WORD);
- }
- do_jcc:
- next_eip = s->pc - s->cs_base;
- val += next_eip;
- if (s->dflag == 0)
- val &= 0xffff;
- gen_jcc(s, b & 0xf, val, next_eip);
- goto no_copy;
-
- /************************/
- /* flags */
- case 0x9c: /* pushf */
- /* XXX: put specific code ? */
- goto unsupported_op;
- case 0x9d: /* popf */
- goto unsupported_op;
-
- case 0x9e: /* sahf */
- case 0x9f: /* lahf */
- case 0xf5: /* cmc */
- case 0xf8: /* clc */
- case 0xf9: /* stc */
- case 0xfc: /* cld */
- case 0xfd: /* std */
- break;
-
- /************************/
- /* bit operations */
- case 0x1ba: /* bt/bts/btr/btc Gv, im */
- ot = dflag ? OT_LONG : OT_WORD;
- modrm = ldub_code(s->pc++);
- op = (modrm >> 3) & 7;
- parse_modrm(s, modrm);
- /* load shift */
- ldub_code(s->pc++);
- if (op < 4)
- goto illegal_op;
- break;
- /************************/
- /* bcd */
- case 0x27: /* daa */
- break;
- case 0x2f: /* das */
- break;
- case 0x37: /* aaa */
- break;
- case 0x3f: /* aas */
- break;
- case 0xd4: /* aam */
- ldub_code(s->pc++);
- break;
- case 0xd5: /* aad */
- ldub_code(s->pc++);
- break;
- /************************/
- /* misc */
- case 0x90: /* nop */
- break;
- case 0x9b: /* fwait */
- if ((s->flags & (HF_MP_MASK | HF_TS_MASK)) ==
- (HF_MP_MASK | HF_TS_MASK)) {
- goto unsupported_op;
- }
- break;
- case 0xcc: /* int3 */
- goto unsupported_op;
- case 0xcd: /* int N */
- goto unsupported_op;
- case 0xce: /* into */
- goto unsupported_op;
- case 0xf1: /* icebp (undocumented, exits to external debugger) */
- goto unsupported_op;
- case 0xfa: /* cli */
- goto unsupported_op;
- case 0xfb: /* sti */
- goto unsupported_op;
- case 0x62: /* bound */
- modrm = ldub_code(s->pc++);
- mod = (modrm >> 6) & 3;
- if (mod == 3)
- goto illegal_op;
- parse_modrm(s, modrm);
- break;
- case 0x1c8 ... 0x1cf: /* bswap reg */
- break;
- case 0xd6: /* salc */
- break;
- case 0xe0: /* loopnz */
- case 0xe1: /* loopz */
- case 0xe2: /* loop */
- case 0xe3: /* jecxz */
- goto unsupported_op;
-
- case 0x130: /* wrmsr */
- case 0x132: /* rdmsr */
- goto unsupported_op;
- case 0x131: /* rdtsc */
- goto unsupported_op;
- case 0x1a2: /* cpuid */
- goto unsupported_op;
- case 0xf4: /* hlt */
- goto unsupported_op;
- case 0x100:
- goto unsupported_op;
- case 0x101:
- goto unsupported_op;
- case 0x108: /* invd */
- case 0x109: /* wbinvd */
- goto unsupported_op;
- case 0x63: /* arpl */
- goto unsupported_op;
- case 0x102: /* lar */
- case 0x103: /* lsl */
- goto unsupported_op;
- case 0x118:
- goto unsupported_op;
- case 0x120: /* mov reg, crN */
- case 0x122: /* mov crN, reg */
- goto unsupported_op;
- case 0x121: /* mov reg, drN */
- case 0x123: /* mov drN, reg */
- goto unsupported_op;
- case 0x106: /* clts */
- goto unsupported_op;
- default:
- goto illegal_op;
- }
-
- /* just copy the code */
-
- /* no override yet */
- if (!s->dflag)
- gb(s, 0x66);
- if (!s->aflag)
- gb(s, 0x67);
- if (prefixes & PREFIX_REPZ)
- gb(s, 0xf3);
- else if (prefixes & PREFIX_REPNZ)
- gb(s, 0xf2);
- {
- int len, i;
- len = s->pc - pc_start_insn;
- for(i = 0; i < len; i++) {
- *s->gen_code_ptr++ = ldub_code(pc_start_insn + i);
- }
- }
- no_copy:
- return 0;
- illegal_op:
- unsupported_op:
- /* fall back to slower code gen necessary */
- s->pc = pc_start;
- return -1;
-}
-
-#define GEN_CODE_MAX_SIZE 8192
-#define GEN_CODE_MAX_INSN_SIZE 512
-
-static inline int gen_intermediate_code_internal(CPUState *env,
- TranslationBlock *tb,
- uint8_t *gen_code_ptr,
- int *gen_code_size_ptr,
- int search_pc,
- uint8_t *tc_ptr)
-{
- DisasContext dc1, *dc = &dc1;
- target_ulong pc_insn, pc_start, cs_base;
- uint8_t *gen_code_end;
- int flags, ret;
-
- if (env->nb_breakpoints > 0 ||
- env->singlestep_enabled)
- return -1;
- flags = tb->flags;
- if (flags & (HF_TF_MASK | HF_ADDSEG_MASK |
- HF_SOFTMMU_MASK | HF_INHIBIT_IRQ_MASK))
- return -1;
- if (!(flags & HF_SS32_MASK))
- return -1;
- if (tb->cflags & CF_SINGLE_INSN)
- return -1;
- gen_code_end = gen_code_ptr +
- GEN_CODE_MAX_SIZE - GEN_CODE_MAX_INSN_SIZE;
- dc->gen_code_ptr = gen_code_ptr;
- dc->gen_code_start = gen_code_ptr;
-
- /* generate intermediate code */
- pc_start = tb->pc;
- cs_base = tb->cs_base;
- dc->pc = pc_start;
- dc->cs_base = cs_base;
- dc->pe = (flags >> HF_PE_SHIFT) & 1;
- dc->code32 = (flags >> HF_CS32_SHIFT) & 1;
- dc->f_st = 0;
- dc->vm86 = (flags >> VM_SHIFT) & 1;
- dc->cpl = (flags >> HF_CPL_SHIFT) & 3;
- dc->iopl = (flags >> IOPL_SHIFT) & 3;
- dc->tb = tb;
- dc->flags = flags;
-
- dc->is_jmp = 0;
-
- for(;;) {
- pc_insn = dc->pc;
- ret = disas_insn(dc);
- if (ret < 0) {
- /* unsupported insn */
- if (dc->pc == pc_start) {
- /* if first instruction, signal that no copying was done */
- return -1;
- } else {
- gen_jmp(dc, dc->pc - dc->cs_base);
- dc->is_jmp = 1;
- }
- }
- if (search_pc) {
- /* search pc mode */
- if (tc_ptr < dc->gen_code_ptr) {
- env->eip = pc_insn - cs_base;
- return 0;
- }
- }
- /* stop translation if indicated */
- if (dc->is_jmp)
- break;
- /* if too long translation, stop generation */
- if (dc->gen_code_ptr >= gen_code_end ||
- (dc->pc - pc_start) >= (TARGET_PAGE_SIZE - 32)) {
- gen_jmp(dc, dc->pc - dc->cs_base);
- break;
- }
- }
-
-#ifdef DEBUG_DISAS
- if (loglevel & CPU_LOG_TB_IN_ASM) {
- fprintf(logfile, "----------------\n");
- fprintf(logfile, "IN: COPY: %s fpu=%d\n",
- lookup_symbol(pc_start),
- tb->cflags & CF_TB_FP_USED ? 1 : 0);
- target_disas(logfile, pc_start, dc->pc - pc_start, !dc->code32);
- fprintf(logfile, "\n");
- }
-#endif
-
- if (!search_pc) {
- *gen_code_size_ptr = dc->gen_code_ptr - dc->gen_code_start;
- tb->size = dc->pc - pc_start;
- tb->cflags |= CF_CODE_COPY;
- return 0;
- } else {
- return -1;
- }
-}
-
-/* generate code by just copying data. Return -1 if cannot generate
- any code. Return 0 if code was generated */
-int cpu_gen_code_copy(CPUState *env, TranslationBlock *tb,
- int max_code_size, int *gen_code_size_ptr)
-{
- /* generate machine code */
- tb->tb_next_offset[0] = 0xffff;
- tb->tb_next_offset[1] = 0xffff;
-#ifdef USE_DIRECT_JUMP
- /* the following two entries are optional (only used for string ops) */
- tb->tb_jmp_offset[2] = 0xffff;
- tb->tb_jmp_offset[3] = 0xffff;
-#endif
- return gen_intermediate_code_internal(env, tb,
- tb->tc_ptr, gen_code_size_ptr,
- 0, NULL);
-}
-
-static uint8_t dummy_gen_code_buf[GEN_CODE_MAX_SIZE];
-
-int cpu_restore_state_copy(TranslationBlock *tb,
- CPUState *env, unsigned long searched_pc,
- void *puc)
-{
- struct ucontext *uc = puc;
- int ret, eflags;
-
- /* find opc index corresponding to search_pc */
- if (searched_pc < (unsigned long)tb->tc_ptr)
- return -1;
- searched_pc = searched_pc - (long)tb->tc_ptr + (long)dummy_gen_code_buf;
- ret = gen_intermediate_code_internal(env, tb,
- dummy_gen_code_buf, NULL,
- 1, (uint8_t *)searched_pc);
- if (ret < 0)
- return ret;
- /* restore all the CPU state from the CPU context from the
- signal. The FPU context stays in the host CPU. */
-
- env->regs[R_EAX] = uc->uc_mcontext.gregs[REG_EAX];
- env->regs[R_ECX] = uc->uc_mcontext.gregs[REG_ECX];
- env->regs[R_EDX] = uc->uc_mcontext.gregs[REG_EDX];
- env->regs[R_EBX] = uc->uc_mcontext.gregs[REG_EBX];
- env->regs[R_ESP] = uc->uc_mcontext.gregs[REG_ESP];
- env->regs[R_EBP] = uc->uc_mcontext.gregs[REG_EBP];
- env->regs[R_ESI] = uc->uc_mcontext.gregs[REG_ESI];
- env->regs[R_EDI] = uc->uc_mcontext.gregs[REG_EDI];
- eflags = uc->uc_mcontext.gregs[REG_EFL];
- env->df = 1 - (2 * ((eflags >> 10) & 1));
- env->cc_src = eflags & (CC_O | CC_S | CC_Z | CC_A | CC_P | CC_C);
- env->cc_op = CC_OP_EFLAGS;
- return 0;
-}
-
-#endif /* USE_CODE_COPY */
Modified: trunk/src/host/qemu-neo1973/target-i386/translate.c
===================================================================
--- trunk/src/host/qemu-neo1973/target-i386/translate.c 2007-11-09 16:32:22 UTC (rev 3386)
+++ trunk/src/host/qemu-neo1973/target-i386/translate.c 2007-11-09 17:12:19 UTC (rev 3387)
@@ -4888,9 +4888,6 @@
goto illegal_op;
}
}
-#ifdef USE_CODE_COPY
- s->tb->cflags |= CF_TB_FP_USED;
-#endif
break;
/************************/
/* string ops */
Modified: trunk/src/host/qemu-neo1973/target-mips/exec.h
===================================================================
--- trunk/src/host/qemu-neo1973/target-mips/exec.h 2007-11-09 16:32:22 UTC (rev 3386)
+++ trunk/src/host/qemu-neo1973/target-mips/exec.h 2007-11-09 17:12:19 UTC (rev 3387)
@@ -56,7 +56,7 @@
#include "softmmu_exec.h"
#endif /* !defined(CONFIG_USER_ONLY) */
-#if defined(TARGET_MIPSN32) || defined(TARGET_MIPS64)
+#if defined(TARGET_MIPS64)
#if TARGET_LONG_BITS > HOST_LONG_BITS
void do_dsll (void);
void do_dsll32 (void);
@@ -86,7 +86,7 @@
void do_msub (void);
void do_msubu (void);
#endif
-#if defined(TARGET_MIPSN32) || defined(TARGET_MIPS64)
+#if defined(TARGET_MIPS64)
void do_ddiv (void);
#if TARGET_LONG_BITS > HOST_LONG_BITS
void do_ddivu (void);
@@ -236,7 +236,7 @@
!(env->hflags & MIPS_HFLAG_DM)) {
env->hflags |= (env->CP0_Status >> CP0St_KSU) & MIPS_HFLAG_KSU;
}
-#if defined(TARGET_MIPSN32) || defined(TARGET_MIPS64)
+#if defined(TARGET_MIPS64)
if (((env->hflags & MIPS_HFLAG_KSU) != MIPS_HFLAG_UM) ||
(env->CP0_Status & (1 << CP0St_PX)) ||
(env->CP0_Status & (1 << CP0St_UX)))
Modified: trunk/src/host/qemu-neo1973/target-mips/helper.c
===================================================================
--- trunk/src/host/qemu-neo1973/target-mips/helper.c 2007-11-09 16:32:22 UTC (rev 3386)
+++ trunk/src/host/qemu-neo1973/target-mips/helper.c 2007-11-09 17:12:19 UTC (rev 3387)
@@ -76,7 +76,7 @@
target_ulong mask = tlb->PageMask | ~(TARGET_PAGE_MASK << 1);
target_ulong tag = address & ~mask;
target_ulong VPN = tlb->VPN & ~mask;
-#if defined(TARGET_MIPSN32) || defined(TARGET_MIPS64)
+#if defined(TARGET_MIPS64)
tag &= env->SEGMask;
#endif
@@ -108,7 +108,7 @@
int user_mode = (env->hflags & MIPS_HFLAG_MODE) == MIPS_HFLAG_UM;
int supervisor_mode = (env->hflags & MIPS_HFLAG_MODE) == MIPS_HFLAG_SM;
int kernel_mode = !user_mode && !supervisor_mode;
-#if defined(TARGET_MIPSN32) || defined(TARGET_MIPS64)
+#if defined(TARGET_MIPS64)
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;
@@ -130,7 +130,7 @@
} else {
ret = env->tlb->map_address(env, physical, prot, address, rw, access_type);
}
-#if defined(TARGET_MIPSN32) || defined(TARGET_MIPS64)
+#if defined(TARGET_MIPS64)
} else if (address < 0x4000000000000000ULL) {
/* xuseg */
if (UX && address < (0x3FFFFFFFFFFFFFFFULL & env->SEGMask)) {
@@ -305,7 +305,7 @@
((address >> 9) & 0x007ffff0);
env->CP0_EntryHi =
(env->CP0_EntryHi & 0xFF) | (address & (TARGET_PAGE_MASK << 1));
-#if defined(TARGET_MIPSN32) || defined(TARGET_MIPS64)
+#if defined(TARGET_MIPS64)
env->CP0_EntryHi &= env->SEGMask;
env->CP0_XContext = (env->CP0_XContext & ((~0ULL) << (env->SEGBITS - 7))) |
((address & 0xC00000000000ULL) >> (env->SEGBITS - 9)) |
@@ -425,7 +425,7 @@
case EXCP_TLBL:
cause = 2;
if (env->error_code == 1 && !(env->CP0_Status & (1 << CP0St_EXL))) {
-#if defined(TARGET_MIPSN32) || defined(TARGET_MIPS64)
+#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;
@@ -473,7 +473,7 @@
case EXCP_TLBS:
cause = 3;
if (env->error_code == 1 && !(env->CP0_Status & (1 << CP0St_EXL))) {
-#if defined(TARGET_MIPSN32) || defined(TARGET_MIPS64)
+#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;
@@ -559,7 +559,7 @@
mask = tlb->PageMask | ~(TARGET_PAGE_MASK << 1);
if (tlb->V0) {
addr = tlb->VPN & ~mask;
-#if defined(TARGET_MIPSN32) || defined(TARGET_MIPS64)
+#if defined(TARGET_MIPS64)
if (addr >= (0xFFFFFFFF80000000ULL & env->SEGMask)) {
addr |= 0x3FFFFF0000000000ULL;
}
@@ -572,7 +572,7 @@
}
if (tlb->V1) {
addr = (tlb->VPN & ~mask) | ((mask >> 1) + 1);
-#if defined(TARGET_MIPSN32) || defined(TARGET_MIPS64)
+#if defined(TARGET_MIPS64)
if (addr >= (0xFFFFFFFF80000000ULL & env->SEGMask)) {
addr |= 0x3FFFFF0000000000ULL;
}
Modified: trunk/src/host/qemu-neo1973/target-mips/mips-defs.h
===================================================================
--- trunk/src/host/qemu-neo1973/target-mips/mips-defs.h 2007-11-09 16:32:22 UTC (rev 3386)
+++ trunk/src/host/qemu-neo1973/target-mips/mips-defs.h 2007-11-09 17:12:19 UTC (rev 3387)
@@ -8,7 +8,7 @@
#define TARGET_PAGE_BITS 12
#define MIPS_TLB_MAX 128
-#if defined(TARGET_MIPSN32) || defined(TARGET_MIPS64)
+#if defined(TARGET_MIPS64)
#define TARGET_LONG_BITS 64
#else
#define TARGET_LONG_BITS 32
Modified: trunk/src/host/qemu-neo1973/target-mips/op.c
===================================================================
--- trunk/src/host/qemu-neo1973/target-mips/op.c 2007-11-09 16:32:22 UTC (rev 3386)
+++ trunk/src/host/qemu-neo1973/target-mips/op.c 2007-11-09 17:12:19 UTC (rev 3387)
@@ -301,7 +301,7 @@
/* For compatibility with 32-bit code, data reference in user mode
with Status_UX = 0 should be casted to 32-bit and sign extended.
See the MIPS64 PRA manual, section 4.10. */
-#if defined(TARGET_MIPSN32) || defined(TARGET_MIPS64)
+#if defined(TARGET_MIPS64)
if (((env->hflags & MIPS_HFLAG_KSU) == MIPS_HFLAG_UM) &&
!(env->CP0_Status & (1 << CP0St_UX)))
T0 = (int64_t)(int32_t)(T0 + T1);
@@ -384,7 +384,7 @@
RETURN();
}
-#if defined(TARGET_MIPSN32) || defined(TARGET_MIPS64)
+#if defined(TARGET_MIPS64)
/* Arithmetic */
void op_dadd (void)
{
@@ -453,7 +453,7 @@
RETURN();
}
#endif
-#endif /* TARGET_MIPSN32 || TARGET_MIPS64 */
+#endif /* TARGET_MIPS64 */
/* Logical */
void op_and (void)
@@ -552,7 +552,7 @@
RETURN();
}
-#if defined(TARGET_MIPSN32) || defined(TARGET_MIPS64)
+#if defined(TARGET_MIPS64)
#if TARGET_LONG_BITS > HOST_LONG_BITS
/* Those might call libgcc functions. */
@@ -743,7 +743,7 @@
RETURN();
}
#endif /* TARGET_LONG_BITS > HOST_LONG_BITS */
-#endif /* TARGET_MIPSN32 || TARGET_MIPS64 */
+#endif /* TARGET_MIPS64 */
/* 64 bits arithmetic */
#if TARGET_LONG_BITS > HOST_LONG_BITS
@@ -846,7 +846,7 @@
}
#endif /* TARGET_LONG_BITS > HOST_LONG_BITS */
-#if defined(TARGET_MIPSN32) || defined(TARGET_MIPS64)
+#if defined(TARGET_MIPS64)
void op_dmult (void)
{
CALL_FROM_TB4(muls64, &(env->LO[0][env->current_tc]), &(env->HI[0][env->current_tc]), T0, T1);
@@ -950,7 +950,7 @@
RETURN();
}
-#if defined(TARGET_MIPSN32) || defined(TARGET_MIPS64)
+#if defined(TARGET_MIPS64)
void op_save_btarget64 (void)
{
env->btarget = ((uint64_t)PARAM1 << 32) | (uint32_t)PARAM2;
@@ -1784,7 +1784,7 @@
/* 1k pages not implemented */
val = T0 & ((TARGET_PAGE_MASK << 1) | 0xFF);
-#if defined(TARGET_MIPSN32) || defined(TARGET_MIPS64)
+#if defined(TARGET_MIPS64)
val &= env->SEGMask;
#endif
old = env->CP0_EntryHi;
@@ -2011,7 +2011,7 @@
RETURN();
}
-#if defined(TARGET_MIPSN32) || defined(TARGET_MIPS64)
+#if defined(TARGET_MIPS64)
void op_dmfc0_yqmask (void)
{
T0 = env->CP0_YQMask;
@@ -2125,7 +2125,7 @@
T0 = env->CP0_ErrorEPC;
RETURN();
}
-#endif /* TARGET_MIPSN32 || TARGET_MIPS64 */
+#endif /* TARGET_MIPS64 */
/* MIPS MT functions */
void op_mftgpr(void)
@@ -3039,7 +3039,7 @@
RETURN();
}
-#if defined(TARGET_MIPSN32) || defined(TARGET_MIPS64)
+#if defined(TARGET_MIPS64)
void op_save_pc64 (void)
{
env->PC[env->current_tc] = ((uint64_t)PARAM1 << 32) | (uint32_t)PARAM2;
@@ -3111,7 +3111,7 @@
RETURN();
}
-#if defined(TARGET_MIPSN32) || defined(TARGET_MIPS64)
+#if defined(TARGET_MIPS64)
void op_dext(void)
{
unsigned int pos = PARAM1;
Modified: trunk/src/host/qemu-neo1973/target-mips/op_helper.c
===================================================================
--- trunk/src/host/qemu-neo1973/target-mips/op_helper.c 2007-11-09 16:32:22 UTC (rev 3386)
+++ trunk/src/host/qemu-neo1973/target-mips/op_helper.c 2007-11-09 17:12:19 UTC (rev 3387)
@@ -68,7 +68,7 @@
do_raise_exception_direct_err (exception, 0);
}
-#if defined(TARGET_MIPSN32) || defined(TARGET_MIPS64)
+#if defined(TARGET_MIPS64)
#if TARGET_LONG_BITS > HOST_LONG_BITS
/* Those might call libgcc functions. */
void do_dsll (void)
@@ -159,7 +159,7 @@
}
#endif /* TARGET_LONG_BITS > HOST_LONG_BITS */
-#endif /* TARGET_MIPSN32 || TARGET_MIPS64 */
+#endif /* TARGET_MIPS64 */
/* 64 bits arithmetic for 32 bits hosts */
#if TARGET_LONG_BITS > HOST_LONG_BITS
@@ -228,7 +228,7 @@
}
#endif
-#if defined(TARGET_MIPSN32) || defined(TARGET_MIPS64)
+#if defined(TARGET_MIPS64)
void do_ddiv (void)
{
if (T1 != 0) {
@@ -247,7 +247,7 @@
}
}
#endif
-#endif /* TARGET_MIPSN32 || TARGET_MIPS64 */
+#endif /* TARGET_MIPS64 */
#if defined(CONFIG_USER_ONLY)
void do_mfc0_random (void)
@@ -392,7 +392,7 @@
/* XXX: detect conflicting TLBs and raise a MCHECK exception when needed */
tlb = &env->tlb->mmu.r4k.tlb[idx];
tlb->VPN = env->CP0_EntryHi & (TARGET_PAGE_MASK << 1);
-#if defined(TARGET_MIPSN32) || defined(TARGET_MIPS64)
+#if defined(TARGET_MIPS64)
tlb->VPN &= env->SEGMask;
#endif
tlb->ASID = env->CP0_EntryHi & 0xFF;
Modified: trunk/src/host/qemu-neo1973/target-mips/op_mem.c
===================================================================
--- trunk/src/host/qemu-neo1973/target-mips/op_mem.c 2007-11-09 16:32:22 UTC (rev 3386)
+++ trunk/src/host/qemu-neo1973/target-mips/op_mem.c 2007-11-09 17:12:19 UTC (rev 3387)
@@ -190,7 +190,7 @@
RETURN();
}
-#if defined(TARGET_MIPSN32) || defined(TARGET_MIPS64)
+#if defined(TARGET_MIPS64)
void glue(op_ld, MEMSUFFIX) (void)
{
T0 = glue(ldq, MEMSUFFIX)(T0);
@@ -381,7 +381,7 @@
}
RETURN();
}
-#endif /* TARGET_MIPSN32 || TARGET_MIPS64 */
+#endif /* TARGET_MIPS64 */
void glue(op_lwc1, MEMSUFFIX) (void)
{
Modified: trunk/src/host/qemu-neo1973/target-mips/op_template.c
===================================================================
--- trunk/src/host/qemu-neo1973/target-mips/op_template.c 2007-11-09 16:32:22 UTC (rev 3386)
+++ trunk/src/host/qemu-neo1973/target-mips/op_template.c 2007-11-09 17:12:19 UTC (rev 3387)
@@ -82,7 +82,7 @@
#undef SET_RESET
-#if defined(TARGET_MIPSN32) || defined(TARGET_MIPS64)
+#if defined(TARGET_MIPS64)
#define SET64(treg, tregname) \
void glue(op_set64, tregname)(void) \
{ \
Modified: trunk/src/host/qemu-neo1973/target-mips/translate.c
===================================================================
--- trunk/src/host/qemu-neo1973/target-mips/translate.c 2007-11-09 16:32:22 UTC (rev 3386)
+++ trunk/src/host/qemu-neo1973/target-mips/translate.c 2007-11-09 17:12:19 UTC (rev 3387)
@@ -590,7 +590,7 @@
} \
} while (0)
-#if defined(TARGET_MIPSN32) || defined(TARGET_MIPS64)
+#if defined(TARGET_MIPS64)
#define GEN_LOAD_IMM_TN(Tn, Imm) \
do { \
if (Imm == 0) { \
@@ -638,7 +638,7 @@
static always_inline void gen_save_pc(target_ulong pc)
{
-#if defined(TARGET_MIPSN32) || defined(TARGET_MIPS64)
+#if defined(TARGET_MIPS64)
if (pc == (int32_t)pc) {
gen_op_save_pc(pc);
} else {
@@ -651,7 +651,7 @@
static always_inline void gen_save_btarget(target_ulong btarget)
{
-#if defined(TARGET_MIPSN32) || defined(TARGET_MIPS64)
+#if defined(TARGET_MIPS64)
if (btarget == (int32_t)btarget) {
gen_op_save_btarget(btarget);
} else {
@@ -802,7 +802,7 @@
}
#endif
-#if defined(TARGET_MIPSN32) || defined(TARGET_MIPS64)
+#if defined(TARGET_MIPS64)
OP_LD_TABLE(d);
OP_LD_TABLE(dl);
OP_LD_TABLE(dr);
@@ -852,7 +852,7 @@
/* Don't do NOP if destination is zero: we must perform the actual
memory access. */
switch (opc) {
-#if defined(TARGET_MIPSN32) || defined(TARGET_MIPS64)
+#if defined(TARGET_MIPS64)
case OPC_LWU:
op_ldst(lwu);
GEN_STORE_TN_REG(rt, T0);
@@ -1048,7 +1048,7 @@
switch (opc) {
case OPC_ADDI:
case OPC_ADDIU:
-#if defined(TARGET_MIPSN32) || defined(TARGET_MIPS64)
+#if defined(TARGET_MIPS64)
case OPC_DADDI:
case OPC_DADDIU:
#endif
@@ -1068,7 +1068,7 @@
case OPC_SLL:
case OPC_SRA:
case OPC_SRL:
-#if defined(TARGET_MIPSN32) || defined(TARGET_MIPS64)
+#if defined(TARGET_MIPS64)
case OPC_DSLL:
case OPC_DSRA:
case OPC_DSRL:
@@ -1091,7 +1091,7 @@
gen_op_add();
opn = "addiu";
break;
-#if defined(TARGET_MIPSN32) || defined(TARGET_MIPS64)
+#if defined(TARGET_MIPS64)
case OPC_DADDI:
save_cpu_state(ctx, 1);
gen_op_daddo();
@@ -1155,7 +1155,7 @@
break;
}
break;
-#if defined(TARGET_MIPSN32) || defined(TARGET_MIPS64)
+#if defined(TARGET_MIPS64)
case OPC_DSLL:
gen_op_dsll();
opn = "dsll";
@@ -1260,7 +1260,7 @@
gen_op_sub();
opn = "subu";
break;
-#if defined(TARGET_MIPSN32) || defined(TARGET_MIPS64)
+#if defined(TARGET_MIPS64)
case OPC_DADD:
save_cpu_state(ctx, 1);
gen_op_daddo();
@@ -1346,7 +1346,7 @@
break;
}
break;
-#if defined(TARGET_MIPSN32) || defined(TARGET_MIPS64)
+#if defined(TARGET_MIPS64)
case OPC_DSLLV:
gen_op_dsllv();
opn = "dsllv";
@@ -1451,7 +1451,7 @@
gen_op_multu();
opn = "multu";
break;
-#if defined(TARGET_MIPSN32) || defined(TARGET_MIPS64)
+#if defined(TARGET_MIPS64)
case OPC_DDIV:
gen_op_ddiv();
opn = "ddiv";
@@ -1512,7 +1512,7 @@
gen_op_clz();
opn = "clz";
break;
-#if defined(TARGET_MIPSN32) || defined(TARGET_MIPS64)
+#if defined(TARGET_MIPS64)
case OPC_DCLO:
gen_op_dclo();
opn = "dclo";
@@ -2319,7 +2319,7 @@
case 20:
switch (sel) {
case 0:
-#if defined(TARGET_MIPSN32) || defined(TARGET_MIPS64)
+#if defined(TARGET_MIPS64)
check_insn(env, ctx, ISA_MIPS3);
gen_op_mfc0_xcontext();
rn = "XContext";
@@ -2523,7 +2523,7 @@
case 0:
switch (sel) {
case 0:
- gen_op_mtc0_index();
+ gen_op_mtc0_index();
rn = "Index";
break;
case 1:
@@ -2901,7 +2901,7 @@
case 20:
switch (sel) {
case 0:
-#if defined(TARGET_MIPSN32) || defined(TARGET_MIPS64)
+#if defined(TARGET_MIPS64)
check_insn(env, ctx, ISA_MIPS3);
gen_op_mtc0_xcontext();
rn = "XContext";
@@ -3111,7 +3111,7 @@
generate_exception(ctx, EXCP_RI);
}
-#if defined(TARGET_MIPSN32) || defined(TARGET_MIPS64)
+#if defined(TARGET_MIPS64)
static void gen_dmfc0 (CPUState *env, DisasContext *ctx, int reg, int sel)
{
const char *rn = "invalid";
@@ -4254,7 +4254,7 @@
#endif
generate_exception(ctx, EXCP_RI);
}
-#endif /* TARGET_MIPSN32 || TARGET_MIPS64 */
+#endif /* TARGET_MIPS64 */
static void gen_mftr(CPUState *env, DisasContext *ctx, int rt,
int u, int sel, int h)
@@ -4604,7 +4604,7 @@
gen_mtc0(env, ctx, rd, ctx->opcode & 0x7);
opn = "mtc0";
break;
-#if defined(TARGET_MIPSN32) || defined(TARGET_MIPS64)
+#if defined(TARGET_MIPS64)
case OPC_DMFC0:
check_insn(env, ctx, ISA_MIPS3);
if (rt == 0) {
@@ -5877,7 +5877,7 @@
/* MIPS16 extension to MIPS32 */
/* SmartMIPS extension to MIPS32 */
-#if defined(TARGET_MIPSN32) || defined(TARGET_MIPS64)
+#if defined(TARGET_MIPS64)
/* MDMX extension to MIPS64 */
@@ -5987,7 +5987,7 @@
}
break;
-#if defined(TARGET_MIPSN32) || defined(TARGET_MIPS64)
+#if defined(TARGET_MIPS64)
/* MIPS64 specific opcodes */
case OPC_DSLL:
case OPC_DSRL ... OPC_DSRA:
@@ -6043,7 +6043,7 @@
}
/* Treat as NOP. */
break;
-#if defined(TARGET_MIPSN32) || defined(TARGET_MIPS64)
+#if defined(TARGET_MIPS64)
case OPC_DCLZ ... OPC_DCLO:
check_insn(env, ctx, ISA_MIPS64);
check_mips_64(ctx);
@@ -6130,7 +6130,7 @@
gen_op_yield();
GEN_STORE_TN_REG(rd, T0);
break;
-#if defined(TARGET_MIPSN32) || defined(TARGET_MIPS64)
+#if defined(TARGET_MIPS64)
case OPC_DEXTM ... OPC_DEXT:
case OPC_DINSM ... OPC_DINS:
check_insn(env, ctx, ISA_MIPS64R2);
@@ -6192,7 +6192,7 @@
case OPC_MTC0:
case OPC_MFTR:
case OPC_MTTR:
-#if defined(TARGET_MIPSN32) || defined(TARGET_MIPS64)
+#if defined(TARGET_MIPS64)
case OPC_DMFC0:
case OPC_DMTC0:
#endif
@@ -6313,7 +6313,7 @@
case OPC_CTC1:
gen_cp1(ctx, op1, rt, rd);
break;
-#if defined(TARGET_MIPSN32) || defined(TARGET_MIPS64)
+#if defined(TARGET_MIPS64)
case OPC_DMFC1:
case OPC_DMTC1:
check_insn(env, ctx, ISA_MIPS3);
@@ -6398,7 +6398,7 @@
}
break;
-#if defined(TARGET_MIPSN32) || defined(TARGET_MIPS64)
+#if defined(TARGET_MIPS64)
/* MIPS64 opcodes */
case OPC_LWU:
case OPC_LDL ... OPC_LDR:
@@ -6665,7 +6665,7 @@
}
}
-#if (defined(TARGET_MIPSN32) || defined(TARGET_MIPS64)) && defined(MIPS_DEBUG_SIGN_EXTENSIONS)
+#if defined(TARGET_MIPS64) && defined(MIPS_DEBUG_SIGN_EXTENSIONS)
/* Debug help: The architecture requires 32bit code to maintain proper
sign-extened values on 64bit machines. */
@@ -6720,7 +6720,7 @@
env->CP0_Config0, env->CP0_Config1, env->CP0_LLAddr);
if (env->hflags & MIPS_HFLAG_FPU)
fpu_dump_state(env, f, cpu_fprintf, flags);
-#if (defined(TARGET_MIPSN32) || defined(TARGET_MIPS64)) && defined(MIPS_DEBUG_SIGN_EXTENSIONS)
+#if defined(TARGET_MIPS64) && defined(MIPS_DEBUG_SIGN_EXTENSIONS)
cpu_mips_check_sign_extensions(env, f, cpu_fprintf, flags);
#endif
}
Modified: trunk/src/host/qemu-neo1973/target-mips/translate_init.c
===================================================================
--- trunk/src/host/qemu-neo1973/target-mips/translate_init.c 2007-11-09 16:32:22 UTC (rev 3386)
+++ trunk/src/host/qemu-neo1973/target-mips/translate_init.c 2007-11-09 17:12:19 UTC (rev 3387)
@@ -201,7 +201,7 @@
(0x3fe << CP0SRSC4_SRS14) | (0x3fe << CP0SRSC4_SRS13),
.insn_flags = CPU_MIPS32R2 | ASE_MIPS16 | ASE_DSP | ASE_MT,
},
-#if defined(TARGET_MIPSN32) || defined(TARGET_MIPS64)
+#if defined(TARGET_MIPS64)
{
.name = "R4000",
.CP0_PRid = 0x00000400,
@@ -437,7 +437,7 @@
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;
-#if defined(TARGET_MIPSN32) || defined(TARGET_MIPS64)
+#if defined(TARGET_MIPS64)
if (def->insn_flags & ISA_MIPS3)
{
env->hflags |= MIPS_HFLAG_64;
Modified: trunk/src/host/qemu-neo1973/target-ppc/cpu.h
===================================================================
--- trunk/src/host/qemu-neo1973/target-ppc/cpu.h 2007-11-09 16:32:22 UTC (rev 3386)
+++ trunk/src/host/qemu-neo1973/target-ppc/cpu.h 2007-11-09 17:12:19 UTC (rev 3387)
@@ -102,6 +102,8 @@
POWERPC_MMU_BOOKE,
/* BookE FSL MMU model */
POWERPC_MMU_BOOKE_FSL,
+ /* PowerPC 601 MMU model (specific BATs format) */
+ POWERPC_MMU_601,
#if defined(TARGET_PPC64)
/* 64 bits PowerPC MMU */
POWERPC_MMU_64B,
@@ -649,7 +651,8 @@
/* Those resources are used only in Qemu core */
jmp_buf jmp_env;
int user_mode_only; /* user mode only simulation */
- target_ulong hflags; /* hflags is a MSR & HFLAGS_MASK */
+ target_ulong hflags; /* hflags is a MSR & HFLAGS_MASK */
+ target_ulong hflags_nmsr; /* specific hflags, not comming from MSR */
int mmu_idx; /* precomputed MMU index to speed up mem accesses */
/* Power management */
@@ -696,6 +699,8 @@
target_ulong do_load_dbatl (CPUPPCState *env, int nr);
void do_store_dbatu (CPUPPCState *env, int nr, target_ulong value);
void do_store_dbatl (CPUPPCState *env, int nr, target_ulong value);
+void do_store_ibatu_601 (CPUPPCState *env, int nr, target_ulong value);
+void do_store_ibatl_601 (CPUPPCState *env, int nr, target_ulong value);
target_ulong do_load_sdr1 (CPUPPCState *env);
void do_store_sdr1 (CPUPPCState *env, target_ulong value);
#if defined(TARGET_PPC64)
Modified: trunk/src/host/qemu-neo1973/target-ppc/exec.h
===================================================================
--- trunk/src/host/qemu-neo1973/target-ppc/exec.h 2007-11-09 16:32:22 UTC (rev 3386)
+++ trunk/src/host/qemu-neo1973/target-ppc/exec.h 2007-11-09 17:12:19 UTC (rev 3387)
@@ -98,7 +98,7 @@
void do_raise_exception (uint32_t exception);
int get_physical_address (CPUState *env, mmu_ctx_t *ctx, target_ulong vaddr,
- int rw, int access_type, int check_BATs);
+ int rw, int access_type);
void ppc6xx_tlb_store (CPUState *env, target_ulong EPN, int way, int is_code,
target_ulong pte0, target_ulong pte1);
Modified: trunk/src/host/qemu-neo1973/target-ppc/helper.c
===================================================================
--- trunk/src/host/qemu-neo1973/target-ppc/helper.c 2007-11-09 16:32:22 UTC (rev 3386)
+++ trunk/src/host/qemu-neo1973/target-ppc/helper.c 2007-11-09 17:12:19 UTC (rev 3387)
@@ -448,12 +448,67 @@
}
/* Perform BAT hit & translation */
+static always_inline void bat_size_prot (CPUState *env, target_ulong *blp,
+ int *validp, int *protp,
+ target_ulong *BATu, target_ulong *BATl)
+{
+ target_ulong bl;
+ int pp, valid, prot;
+
+ bl = (*BATu & 0x00001FFC) << 15;
+ valid = 0;
+ prot = 0;
+ if (((msr_pr == 0) && (*BATu & 0x00000002)) ||
+ ((msr_pr != 0) && (*BATu & 0x00000001))) {
+ valid = 1;
+ pp = *BATl & 0x00000003;
+ if (pp != 0) {
+ prot = PAGE_READ | PAGE_EXEC;
+ if (pp == 0x2)
+ prot |= PAGE_WRITE;
+ }
+ }
+ *blp = bl;
+ *validp = valid;
+ *protp = prot;
+}
+
+static always_inline void bat_601_size_prot (CPUState *env,target_ulong *blp,
+ int *validp, int *protp,
+ target_ulong *BATu,
+ target_ulong *BATl)
+{
+ target_ulong bl;
+ int key, pp, valid, prot;
+
+ bl = (*BATl & 0x0000003F) << 17;
+#if defined (DEBUG_BATS)
+ if (loglevel != 0) {
+ fprintf(logfile, "b %02x ==> bl %08x msk %08x\n",
+ *BATl & 0x0000003F, bl, ~bl);
+ }
+#endif
+ prot = 0;
+ valid = (*BATl >> 6) & 1;
+ if (valid) {
+ pp = *BATu & 0x00000003;
+ if (msr_pr == 0)
+ key = (*BATu >> 3) & 1;
+ else
+ key = (*BATu >> 2) & 1;
+ prot = pp_check(key, pp, 0);
+ }
+ *blp = bl;
+ *validp = valid;
+ *protp = prot;
+}
+
static always_inline int get_bat (CPUState *env, mmu_ctx_t *ctx,
target_ulong virtual, int rw, int type)
{
target_ulong *BATlt, *BATut, *BATu, *BATl;
target_ulong base, BEPIl, BEPIu, bl;
- int i, pp, pr;
+ int i, valid, prot;
int ret = -1;
#if defined (DEBUG_BATS)
@@ -462,7 +517,6 @@
type == ACCESS_CODE ? 'I' : 'D', virtual);
}
#endif
- pr = msr_pr;
switch (type) {
case ACCESS_CODE:
BATlt = env->IBAT[1];
@@ -480,12 +534,16 @@
}
#endif
base = virtual & 0xFFFC0000;
- for (i = 0; i < 4; i++) {
+ for (i = 0; i < env->nb_BATs; i++) {
BATu = &BATut[i];
BATl = &BATlt[i];
BEPIu = *BATu & 0xF0000000;
BEPIl = *BATu & 0x0FFE0000;
- bl = (*BATu & 0x00001FFC) << 15;
+ if (unlikely(env->mmu_model == POWERPC_MMU_601)) {
+ bat_601_size_prot(env, &bl, &valid, &prot, BATu, BATl);
+ } else {
+ bat_size_prot(env, &bl, &valid, &prot, BATu, BATl);
+ }
#if defined (DEBUG_BATS)
if (loglevel != 0) {
fprintf(logfile, "%s: %cBAT%d v 0x" ADDRX " BATu 0x" ADDRX
@@ -497,20 +555,13 @@
if ((virtual & 0xF0000000) == BEPIu &&
((virtual & 0x0FFE0000) & ~bl) == BEPIl) {
/* BAT matches */
- if (((pr == 0) && (*BATu & 0x00000002)) ||
- ((pr != 0) && (*BATu & 0x00000001))) {
+ if (valid != 0) {
/* Get physical address */
ctx->raddr = (*BATl & 0xF0000000) |
((virtual & 0x0FFE0000 & bl) | (*BATl & 0x0FFE0000)) |
(virtual & 0x0001F000);
/* Compute access rights */
- pp = *BATl & 0x00000003;
- ctx->prot = 0;
- if (pp != 0) {
- ctx->prot = PAGE_READ | PAGE_EXEC;
- if (pp == 0x2)
- ctx->prot |= PAGE_WRITE;
- }
+ ctx->prot = prot;
ret = check_prot(ctx->prot, rw, type);
#if defined (DEBUG_BATS)
if (ret == 0 && loglevel != 0) {
@@ -1302,6 +1353,7 @@
ret = 0;
switch (env->mmu_model) {
case POWERPC_MMU_32B:
+ case POWERPC_MMU_601:
case POWERPC_MMU_SOFT_6xx:
case POWERPC_MMU_SOFT_74xx:
case POWERPC_MMU_SOFT_4xx:
@@ -1353,7 +1405,7 @@
}
int get_physical_address (CPUState *env, mmu_ctx_t *ctx, target_ulong eaddr,
- int rw, int access_type, int check_BATs)
+ int rw, int access_type)
{
int ret;
@@ -1370,15 +1422,15 @@
ret = -1;
switch (env->mmu_model) {
case POWERPC_MMU_32B:
+ case POWERPC_MMU_601:
case POWERPC_MMU_SOFT_6xx:
case POWERPC_MMU_SOFT_74xx:
- /* Try to find a BAT */
- if (check_BATs)
- ret = get_bat(env, ctx, eaddr, rw, access_type);
- /* No break here */
#if defined(TARGET_PPC64)
case POWERPC_MMU_64B:
#endif
+ /* Try to find a BAT */
+ if (env->nb_BATs != 0)
+ ret = get_bat(env, ctx, eaddr, rw, access_type);
if (ret < 0) {
/* We didn't match any BAT entry or don't have BATs */
ret = get_segment(env, ctx, eaddr, rw, access_type);
@@ -1419,7 +1471,7 @@
{
mmu_ctx_t ctx;
- if (unlikely(get_physical_address(env, &ctx, addr, 0, ACCESS_INT, 1) != 0))
+ if (unlikely(get_physical_address(env, &ctx, addr, 0, ACCESS_INT) != 0))
return -1;
return ctx.raddr & TARGET_PAGE_MASK;
@@ -1444,7 +1496,7 @@
access_type = ACCESS_INT;
// access_type = env->access_type;
}
- ret = get_physical_address(env, &ctx, address, rw, access_type, 1);
+ ret = get_physical_address(env, &ctx, address, rw, access_type);
if (ret == 0) {
ret = tlb_set_page_exec(env, address & TARGET_PAGE_MASK,
ctx.raddr & TARGET_PAGE_MASK, ctx.prot,
@@ -1476,6 +1528,7 @@
env->spr[SPR_40x_ESR] = 0x00000000;
break;
case POWERPC_MMU_32B:
+ case POWERPC_MMU_601:
#if defined(TARGET_PPC64)
case POWERPC_MMU_64B:
#endif
@@ -1567,6 +1620,7 @@
env->spr[SPR_40x_ESR] = 0x00000000;
break;
case POWERPC_MMU_32B:
+ case POWERPC_MMU_601:
#if defined(TARGET_PPC64)
case POWERPC_MMU_64B:
#endif
@@ -1784,6 +1838,76 @@
env->DBAT[1][nr] = value;
}
+void do_store_ibatu_601 (CPUPPCState *env, int nr, target_ulong value)
+{
+ target_ulong mask;
+ int do_inval;
+
+ dump_store_bat(env, 'I', 0, nr, value);
+ if (env->IBAT[0][nr] != value) {
+ do_inval = 0;
+ mask = (env->IBAT[1][nr] << 17) & 0x0FFE0000UL;
+ if (env->IBAT[1][nr] & 0x40) {
+ /* Invalidate BAT only if it is valid */
+#if !defined(FLUSH_ALL_TLBS)
+ do_invalidate_BAT(env, env->IBAT[0][nr], mask);
+#else
+ do_inval = 1;
+#endif
+ }
+ /* When storing valid upper BAT, mask BEPI and BRPN
+ * and invalidate all TLBs covered by this BAT
+ */
+ env->IBAT[0][nr] = (value & 0x00001FFFUL) |
+ (value & ~0x0001FFFFUL & ~mask);
+ env->DBAT[0][nr] = env->IBAT[0][nr];
+ if (env->IBAT[1][nr] & 0x40) {
+#if !defined(FLUSH_ALL_TLBS)
+ do_invalidate_BAT(env, env->IBAT[0][nr], mask);
+#else
+ do_inval = 1;
+#endif
+ }
+#if defined(FLUSH_ALL_TLBS)
+ if (do_inval)
+ tlb_flush(env, 1);
+#endif
+ }
+}
+
+void do_store_ibatl_601 (CPUPPCState *env, int nr, target_ulong value)
+{
+ target_ulong mask;
+ int do_inval;
+
+ dump_store_bat(env, 'I', 1, nr, value);
+ if (env->IBAT[1][nr] != value) {
+ do_inval = 0;
+ if (env->IBAT[1][nr] & 0x40) {
+#if !defined(FLUSH_ALL_TLBS)
+ mask = (env->IBAT[1][nr] << 17) & 0x0FFE0000UL;
+ do_invalidate_BAT(env, env->IBAT[0][nr], mask);
+#else
+ do_inval = 1;
+#endif
+ }
+ if (value & 0x40) {
+#if !defined(FLUSH_ALL_TLBS)
+ mask = (value << 17) & 0x0FFE0000UL;
+ do_invalidate_BAT(env, env->IBAT[0][nr], mask);
+#else
+ do_inval = 1;
+#endif
+ }
+ env->IBAT[1][nr] = value;
+ env->DBAT[1][nr] = value;
+#if defined(FLUSH_ALL_TLBS)
+ if (do_inval)
+ tlb_flush(env, 1);
+#endif
+ }
+}
+
/*****************************************************************************/
/* TLB management */
void ppc_tlb_invalidate_all (CPUPPCState *env)
@@ -1809,6 +1933,7 @@
cpu_abort(env, "MMU model not implemented\n");
break;
case POWERPC_MMU_32B:
+ case POWERPC_MMU_601:
#if defined(TARGET_PPC64)
case POWERPC_MMU_64B:
#endif /* defined(TARGET_PPC64) */
@@ -1848,6 +1973,7 @@
cpu_abort(env, "MMU model not implemented\n");
break;
case POWERPC_MMU_32B:
+ case POWERPC_MMU_601:
/* tlbie invalidate TLBs for all segments */
addr &= ~((target_ulong)-1 << 28);
/* XXX: this case should be optimized,
@@ -2146,10 +2272,9 @@
new_msr |= (target_ulong)1 << MSR_HV;
#endif
msr |= 0x00100000;
- if (msr_fe0 != msr_fe1) {
- msr |= 0x00010000;
- goto store_current;
- }
+ if (msr_fe0 == msr_fe1)
+ goto store_next;
+ msr |= 0x00010000;
break;
case POWERPC_EXCP_INVAL:
#if defined (DEBUG_EXCEPTIONS)
@@ -2187,7 +2312,7 @@
env->error_code);
break;
}
- goto store_next;
+ goto store_current;
case POWERPC_EXCP_FPU: /* Floating-point unavailable exception */
new_msr &= ~((target_ulong)1 << MSR_RI);
#if defined(TARGET_PPC64H)
@@ -2631,6 +2756,7 @@
* any special case that could occur. Just store MSR and update hflags
*/
env->msr = new_msr;
+ env->hflags_nmsr = 0x00000000;
hreg_compute_hflags(env);
env->nip = vector;
/* Reset exception state */
Modified: trunk/src/host/qemu-neo1973/target-ppc/helper_regs.h
===================================================================
--- trunk/src/host/qemu-neo1973/target-ppc/helper_regs.h 2007-11-09 16:32:22 UTC (rev 3386)
+++ trunk/src/host/qemu-neo1973/target-ppc/helper_regs.h 2007-11-09 17:12:19 UTC (rev 3387)
@@ -58,6 +58,17 @@
env->tgpr[3] = tmp;
}
+static always_inline void hreg_compute_mem_idx (CPUPPCState *env)
+{
+#if defined (TARGET_PPC64H)
+ /* Precompute MMU index */
+ if (msr_pr == 0 && msr_hv != 0)
+ env->mmu_idx = 2;
+ else
+#endif
+ env->mmu_idx = 1 - msr_pr;
+}
+
static always_inline void hreg_compute_hflags (CPUPPCState *env)
{
target_ulong hflags_mask;
@@ -70,14 +81,12 @@
hflags_mask |= (1ULL << MSR_CM) | (1ULL << MSR_SF);
#if defined (TARGET_PPC64H)
hflags_mask |= 1ULL << MSR_HV;
- /* Precompute MMU index */
- if (msr_pr == 0 && msr_hv != 0)
- env->mmu_idx = 2;
- else
#endif
#endif
- env->mmu_idx = 1 - msr_pr;
+ hreg_compute_mem_idx(env);
env->hflags = env->msr & hflags_mask;
+ /* Merge with hflags coming from other registers */
+ env->hflags |= env->hflags_nmsr;
}
static always_inline int hreg_store_msr (CPUPPCState *env, target_ulong value)
Modified: trunk/src/host/qemu-neo1973/target-ppc/op.c
===================================================================
--- trunk/src/host/qemu-neo1973/target-ppc/op.c 2007-11-09 16:32:22 UTC (rev 3386)
+++ trunk/src/host/qemu-neo1973/target-ppc/op.c 2007-11-09 17:12:19 UTC (rev 3387)
@@ -2190,30 +2190,27 @@
RETURN();
}
+void OPPROTO op_store_hid0_601 (void)
+{
+ do_store_hid0_601();
+ RETURN();
+}
+
void OPPROTO op_load_601_bat (void)
{
T0 = env->IBAT[PARAM1][PARAM2];
RETURN();
}
-#endif /* !defined(CONFIG_USER_ONLY) */
-/* 601 unified BATs store.
- * To avoid using specific MMU code for 601, we store BATs in
- * IBAT and DBAT simultaneously, then emulate unified BATs.
- */
-#if !defined(CONFIG_USER_ONLY)
void OPPROTO op_store_601_batl (void)
{
- int nr = PARAM1;
-
- env->IBAT[1][nr] = T0;
- env->DBAT[1][nr] = T0;
+ do_store_ibatl_601(env, PARAM1, T0);
RETURN();
}
void OPPROTO op_store_601_batu (void)
{
- do_store_601_batu(PARAM1);
+ do_store_ibatu_601(env, PARAM1, T0);
RETURN();
}
#endif /* !defined(CONFIG_USER_ONLY) */
Modified: trunk/src/host/qemu-neo1973/target-ppc/op_helper.c
===================================================================
--- trunk/src/host/qemu-neo1973/target-ppc/op_helper.c 2007-11-09 16:32:22 UTC (rev 3386)
+++ trunk/src/host/qemu-neo1973/target-ppc/op_helper.c 2007-11-09 17:12:19 UTC (rev 3387)
@@ -1682,15 +1682,18 @@
#if !defined (CONFIG_USER_ONLY)
void do_POWER_rac (void)
{
-#if 0
mmu_ctx_t ctx;
+ int nb_BATs;
/* We don't have to generate many instances of this instruction,
* as rac is supervisor only.
*/
- if (get_physical_address(env, &ctx, T0, 0, ACCESS_INT, 1) == 0)
+ /* XXX: FIX THIS: Pretend we have no BAT */
+ nb_BATs = env->nb_BATs;
+ env->nb_BATs = 0;
+ if (get_physical_address(env, &ctx, T0, 0, ACCESS_INT) == 0)
T0 = ctx.raddr;
-#endif
+ env->nb_BATs = nb_BATs;
}
void do_POWER_rfsvc (void)
@@ -1698,12 +1701,23 @@
__do_rfi(env->lr, env->ctr, 0x0000FFFF, 0);
}
-/* PowerPC 601 BAT management helper */
-void do_store_601_batu (int nr)
+void do_store_hid0_601 (void)
{
- do_store_ibatu(env, nr, (uint32_t)T0);
- env->DBAT[0][nr] = env->IBAT[0][nr];
- env->DBAT[1][nr] = env->IBAT[1][nr];
+ uint32_t hid0;
+
+ hid0 = env->spr[SPR_HID0];
+ if ((T0 ^ hid0) & 0x00000008) {
+ /* Change current endianness */
+ env->hflags &= ~(1 << MSR_LE);
+ env->hflags_nmsr &= ~(1 << MSR_LE);
+ env->hflags_nmsr |= (1 << MSR_LE) & (((T0 >> 3) & 1) << MSR_LE);
+ env->hflags |= env->hflags_nmsr;
+ if (loglevel != 0) {
+ fprintf(logfile, "%s: set endianness to %c => " ADDRX "\n",
+ __func__, T0 & 0x8 ? 'l' : 'b', env->hflags);
+ }
+ }
+ env->spr[SPR_HID0] = T0;
}
#endif
Modified: trunk/src/host/qemu-neo1973/target-ppc/op_helper.h
===================================================================
--- trunk/src/host/qemu-neo1973/target-ppc/op_helper.h 2007-11-09 16:32:22 UTC (rev 3386)
+++ trunk/src/host/qemu-neo1973/target-ppc/op_helper.h 2007-11-09 17:12:19 UTC (rev 3387)
@@ -155,7 +155,6 @@
#endif
/* POWER / PowerPC 601 specific helpers */
-void do_store_601_batu (int nr);
void do_POWER_abso (void);
void do_POWER_clcs (void);
void do_POWER_div (void);
@@ -168,6 +167,7 @@
#if !defined(CONFIG_USER_ONLY)
void do_POWER_rac (void);
void do_POWER_rfsvc (void);
+void do_store_hid0_601 (void);
#endif
/* PowerPC 602 specific helper */
Modified: trunk/src/host/qemu-neo1973/target-ppc/translate.c
===================================================================
--- trunk/src/host/qemu-neo1973/target-ppc/translate.c 2007-11-09 16:32:22 UTC (rev 3386)
+++ trunk/src/host/qemu-neo1973/target-ppc/translate.c 2007-11-09 17:12:19 UTC (rev 3387)
@@ -3550,20 +3550,28 @@
gen_op_store_T0_gpr(rD(ctx->opcode));
} else {
/* Privilege exception */
- if (loglevel != 0) {
- fprintf(logfile, "Trying to read privileged spr %d %03x\n",
- sprn, sprn);
+ /* This is a hack to avoid warnings when running Linux:
+ * this OS breaks the PowerPC virtualisation model,
+ * allowing userland application to read the PVR
+ */
+ if (sprn != SPR_PVR) {
+ if (loglevel != 0) {
+ fprintf(logfile, "Trying to read privileged spr %d %03x at"
+ ADDRX "\n", sprn, sprn, ctx->nip);
+ }
+ printf("Trying to read privileged spr %d %03x at " ADDRX "\n",
+ sprn, sprn, ctx->nip);
}
- printf("Trying to read privileged spr %d %03x\n", sprn, sprn);
GEN_EXCP_PRIVREG(ctx);
}
} else {
/* Not defined */
if (loglevel != 0) {
- fprintf(logfile, "Trying to read invalid spr %d %03x\n",
- sprn, sprn);
+ fprintf(logfile, "Trying to read invalid spr %d %03x at "
+ ADDRX "\n", sprn, sprn, ctx->nip);
}
- printf("Trying to read invalid spr %d %03x\n", sprn, sprn);
+ printf("Trying to read invalid spr %d %03x at " ADDRX "\n",
+ sprn, sprn, ctx->nip);
GEN_EXCP(ctx, POWERPC_EXCP_PROGRAM,
POWERPC_EXCP_INVAL | POWERPC_EXCP_INVAL_SPR);
}
@@ -3683,19 +3691,21 @@
} else {
/* Privilege exception */
if (loglevel != 0) {
- fprintf(logfile, "Trying to write privileged spr %d %03x\n",
- sprn, sprn);
+ fprintf(logfile, "Trying to write privileged spr %d %03x at "
+ ADDRX "\n", sprn, sprn, ctx->nip);
}
- printf("Trying to write privileged spr %d %03x\n", sprn, sprn);
+ printf("Trying to write privileged spr %d %03x at " ADDRX "\n",
+ sprn, sprn, ctx->nip);
GEN_EXCP_PRIVREG(ctx);
}
} else {
/* Not defined */
if (loglevel != 0) {
- fprintf(logfile, "Trying to write invalid spr %d %03x\n",
- sprn, sprn);
+ fprintf(logfile, "Trying to write invalid spr %d %03x at "
+ ADDRX "\n", sprn, sprn, ctx->nip);
}
- printf("Trying to write invalid spr %d %03x\n", sprn, sprn);
+ printf("Trying to write invalid spr %d %03x at " ADDRX "\n",
+ sprn, sprn, ctx->nip);
GEN_EXCP(ctx, POWERPC_EXCP_PROGRAM,
POWERPC_EXCP_INVAL | POWERPC_EXCP_INVAL_SPR);
}
@@ -6679,24 +6689,23 @@
int i;
- cpu_fprintf(f, "NIP " ADDRX " LR " ADDRX " CTR " ADDRX " idx %d\n",
- env->nip, env->lr, env->ctr, env->mmu_idx);
- cpu_fprintf(f, "MSR " REGX FILL " XER %08x "
+ cpu_fprintf(f, "NIP " ADDRX " LR " ADDRX " CTR " ADDRX " XER %08x\n",
+ env->nip, env->lr, env->ctr, hreg_load_xer(env));
+ cpu_fprintf(f, "MSR " REGX FILL " HID0 " REGX FILL " HF " REGX FILL
+ " idx %d\n",
+ env->msr, env->hflags, env->spr[SPR_HID0], env->mmu_idx);
#if !defined(NO_TIMER_DUMP)
- "TB %08x %08x "
+ cpu_fprintf(f, "TB %08x %08x "
#if !defined(CONFIG_USER_ONLY)
"DECR %08x"
#endif
-#endif
"\n",
- env->msr, hreg_load_xer(env)
-#if !defined(NO_TIMER_DUMP)
- , cpu_ppc_load_tbu(env), cpu_ppc_load_tbl(env)
+ cpu_ppc_load_tbu(env), cpu_ppc_load_tbl(env)
#if !defined(CONFIG_USER_ONLY)
, cpu_ppc_load_decr(env)
#endif
+ );
#endif
- );
for (i = 0; i < 32; i++) {
if ((i & (RGPL - 1)) == 0)
cpu_fprintf(f, "GPR%02d", i);
@@ -6727,8 +6736,7 @@
cpu_fprintf(f, "\n");
}
#if !defined(CONFIG_USER_ONLY)
- cpu_fprintf(f, "SRR0 " REGX " SRR1 " REGX " " FILL FILL FILL
- "SDR1 " REGX "\n",
+ cpu_fprintf(f, "SRR0 " REGX " SRR1 " REGX " SDR1 " REGX "\n",
env->spr[SPR_SRR0], env->spr[SPR_SRR1], env->sdr1);
#endif
@@ -6793,7 +6801,7 @@
opc_handler_t **table, *handler;
target_ulong pc_start;
uint16_t *gen_opc_end;
- int supervisor;
+ int supervisor, little_endian;
int single_step, branch_step;
int j, lj = -1;
@@ -6813,11 +6821,12 @@
#if !defined(CONFIG_USER_ONLY)
ctx.supervisor = supervisor;
#endif
+ little_endian = env->hflags & (1 << MSR_LE) ? 1 : 0;
#if defined(TARGET_PPC64)
ctx.sf_mode = msr_sf;
- ctx.mem_idx = (supervisor << 2) | (msr_sf << 1) | msr_le;
+ ctx.mem_idx = (supervisor << 2) | (msr_sf << 1) | little_endian;
#else
- ctx.mem_idx = (supervisor << 1) | msr_le;
+ ctx.mem_idx = (supervisor << 1) | little_endian;
#endif
ctx.dcache_line_size = env->dcache_line_size;
ctx.fpu_enabled = msr_fp;
@@ -6872,18 +6881,16 @@
ctx.nip, supervisor, (int)msr_ir);
}
#endif
- ctx.opcode = ldl_code(ctx.nip);
- if (msr_le) {
- ctx.opcode = ((ctx.opcode & 0xFF000000) >> 24) |
- ((ctx.opcode & 0x00FF0000) >> 8) |
- ((ctx.opcode & 0x0000FF00) << 8) |
- ((ctx.opcode & 0x000000FF) << 24);
+ if (unlikely(little_endian)) {
+ ctx.opcode = bswap32(ldl_code(ctx.nip));
+ } else {
+ ctx.opcode = ldl_code(ctx.nip);
}
#if defined PPC_DEBUG_DISAS
if (loglevel & CPU_LOG_TB_IN_ASM) {
fprintf(logfile, "translate opcode %08x (%02x %02x %02x) (%s)\n",
ctx.opcode, opc1(ctx.opcode), opc2(ctx.opcode),
- opc3(ctx.opcode), msr_le ? "little" : "big");
+ opc3(ctx.opcode), little_endian ? "little" : "big");
}
#endif
ctx.nip += 4;
@@ -6978,7 +6985,7 @@
if (loglevel & CPU_LOG_TB_IN_ASM) {
int flags;
flags = env->bfd_mach;
- flags |= msr_le << 16;
+ flags |= little_endian << 16;
fprintf(logfile, "IN: %s\n", lookup_symbol(pc_start));
target_disas(logfile, pc_start, ctx.nip - pc_start, flags);
fprintf(logfile, "\n");
Modified: trunk/src/host/qemu-neo1973/target-ppc/translate_init.c
===================================================================
--- trunk/src/host/qemu-neo1973/target-ppc/translate_init.c 2007-11-09 16:32:22 UTC (rev 3386)
+++ trunk/src/host/qemu-neo1973/target-ppc/translate_init.c 2007-11-09 17:12:19 UTC (rev 3387)
@@ -241,7 +241,7 @@
static void spr_read_dbat_h (void *opaque, int sprn)
{
- gen_op_load_dbat(sprn & 1, (sprn - SPR_DBAT4U) / 2);
+ gen_op_load_dbat(sprn & 1, ((sprn - SPR_DBAT4U) / 2) + 4);
}
static void spr_write_dbatu (void *opaque, int sprn)
@@ -251,7 +251,7 @@
static void spr_write_dbatu_h (void *opaque, int sprn)
{
- gen_op_store_dbatu((sprn - SPR_DBAT4U) / 2);
+ gen_op_store_dbatu(((sprn - SPR_DBAT4U) / 2) + 4);
}
static void spr_write_dbatl (void *opaque, int sprn)
@@ -261,7 +261,7 @@
static void spr_write_dbatl_h (void *opaque, int sprn)
{
- gen_op_store_dbatl((sprn - SPR_DBAT4L) / 2);
+ gen_op_store_dbatl(((sprn - SPR_DBAT4L) / 2) + 4);
}
/* SDR1 */
@@ -314,6 +314,15 @@
{
gen_op_store_601_rtcl();
}
+
+static void spr_write_hid0_601 (void *opaque, int sprn)
+{
+ DisasContext *ctx = opaque;
+
+ gen_op_store_hid0_601();
+ /* Must stop the translation as endianness may have changed */
+ GEN_STOP(ctx);
+}
#endif
/* Unified bats */
@@ -2246,9 +2255,9 @@
env->excp_vectors[POWERPC_EXCP_FIT] = 0x00001010;
env->excp_vectors[POWERPC_EXCP_WDT] = 0x00001020;
env->excp_vectors[POWERPC_EXCP_DEBUG] = 0x00002000;
- env->excp_prefix = 0x00000000;
- env->ivor_mask = 0x0000FFF0;
- env->ivpr_mask = 0xFFFF0000;
+ env->excp_prefix = 0x00000000UL;
+ env->ivor_mask = 0x0000FFF0UL;
+ env->ivpr_mask = 0xFFFF0000UL;
/* Hardware reset vector */
env->hreset_vector = 0xFFFFFFFCUL;
#endif
@@ -2271,9 +2280,9 @@
env->excp_vectors[POWERPC_EXCP_DTLB] = 0x00001100;
env->excp_vectors[POWERPC_EXCP_ITLB] = 0x00001200;
env->excp_vectors[POWERPC_EXCP_DEBUG] = 0x00002000;
- env->excp_prefix = 0x00000000;
- env->ivor_mask = 0x0000FFF0;
- env->ivpr_mask = 0xFFFF0000;
+ env->excp_prefix = 0x00000000UL;
+ env->ivor_mask = 0x0000FFF0UL;
+ env->ivpr_mask = 0xFFFF0000UL;
/* Hardware reset vector */
env->hreset_vector = 0xFFFFFFFCUL;
#endif
@@ -2298,9 +2307,9 @@
env->excp_vectors[POWERPC_EXCP_DTLB] = 0x00000000;
env->excp_vectors[POWERPC_EXCP_ITLB] = 0x00000000;
env->excp_vectors[POWERPC_EXCP_DEBUG] = 0x00000000;
- env->excp_prefix = 0x00000000;
- env->ivor_mask = 0x0000FFE0;
- env->ivpr_mask = 0xFFFF0000;
+ env->excp_prefix = 0x00000000UL;
+ env->ivor_mask = 0x0000FFE0UL;
+ env->ivpr_mask = 0xFFFF0000UL;
/* Hardware reset vector */
env->hreset_vector = 0xFFFFFFFCUL;
#endif
@@ -2321,7 +2330,7 @@
env->excp_vectors[POWERPC_EXCP_IO] = 0x00000A00;
env->excp_vectors[POWERPC_EXCP_SYSCALL] = 0x00000C00;
env->excp_vectors[POWERPC_EXCP_RUNM] = 0x00002000;
- env->excp_prefix = 0xFFF00000;
+ env->excp_prefix = 0xFFF00000UL;
/* Hardware reset vector */
env->hreset_vector = 0x00000100UL;
#endif
@@ -2349,7 +2358,7 @@
env->excp_vectors[POWERPC_EXCP_SMI] = 0x00001400;
env->excp_vectors[POWERPC_EXCP_WDT] = 0x00001500;
env->excp_vectors[POWERPC_EXCP_EMUL] = 0x00001600;
- env->excp_prefix = 0xFFF00000;
+ env->excp_prefix = 0xFFF00000UL;
/* Hardware reset vector */
env->hreset_vector = 0xFFFFFFFCUL;
#endif
@@ -2374,6 +2383,7 @@
env->excp_vectors[POWERPC_EXCP_DSTLB] = 0x00001200;
env->excp_vectors[POWERPC_EXCP_IABR] = 0x00001300;
env->excp_vectors[POWERPC_EXCP_SMI] = 0x00001400;
+ env->excp_prefix = 0x00000000UL;
/* Hardware reset vector */
env->hreset_vector = 0xFFFFFFFCUL;
#endif
@@ -2399,6 +2409,7 @@
env->excp_vectors[POWERPC_EXCP_DSTLB] = 0x00001200;
env->excp_vectors[POWERPC_EXCP_IABR] = 0x00001300;
env->excp_vectors[POWERPC_EXCP_SMI] = 0x00001400;
+ env->excp_prefix = 0x00000000UL;
/* Hardware reset vector */
env->hreset_vector = 0xFFFFFFFCUL;
#endif
@@ -2421,6 +2432,7 @@
env->excp_vectors[POWERPC_EXCP_PERFM] = 0x00000F00;
env->excp_vectors[POWERPC_EXCP_IABR] = 0x00001300;
env->excp_vectors[POWERPC_EXCP_SMI] = 0x00001400;
+ env->excp_prefix = 0x00000000UL;
/* Hardware reset vector */
env->hreset_vector = 0xFFFFFFFCUL;
#endif
@@ -2433,7 +2445,9 @@
env->excp_vectors[POWERPC_EXCP_RESET] = 0x00000100;
env->excp_vectors[POWERPC_EXCP_MCHECK] = 0x00000200;
env->excp_vectors[POWERPC_EXCP_DSI] = 0x00000300;
+ env->excp_vectors[POWERPC_EXCP_DSEG] = 0x00000380;
env->excp_vectors[POWERPC_EXCP_ISI] = 0x00000400;
+ env->excp_vectors[POWERPC_EXCP_ISEG] = 0x00000480;
env->excp_vectors[POWERPC_EXCP_EXTERNAL] = 0x00000500;
env->excp_vectors[POWERPC_EXCP_ALIGN] = 0x00000600;
env->excp_vectors[POWERPC_EXCP_PROGRAM] = 0x00000700;
@@ -2445,8 +2459,9 @@
env->excp_vectors[POWERPC_EXCP_PERFM] = 0x00000F00;
env->excp_vectors[POWERPC_EXCP_IABR] = 0x00001300;
env->excp_vectors[POWERPC_EXCP_SMI] = 0x00001400;
+ env->excp_prefix = 0xFFF00000UL;
/* Hardware reset vector */
- env->hreset_vector = 0x0000000000000100ULL; /* ? */
+ env->hreset_vector = 0x0000000000000100ULL;
#endif
}
#endif /* defined(TARGET_PPC64) */
@@ -2468,6 +2483,7 @@
env->excp_vectors[POWERPC_EXCP_PERFM] = 0x00000F00;
env->excp_vectors[POWERPC_EXCP_IABR] = 0x00001300;
env->excp_vectors[POWERPC_EXCP_THERM] = 0x00001700;
+ env->excp_prefix = 0x00000000UL;
/* Hardware reset vector */
env->hreset_vector = 0xFFFFFFFCUL;
#endif
@@ -2491,6 +2507,7 @@
env->excp_vectors[POWERPC_EXCP_IABR] = 0x00001300;
env->excp_vectors[POWERPC_EXCP_SMI] = 0x00001400;
env->excp_vectors[POWERPC_EXCP_THERM] = 0x00001700;
+ env->excp_prefix = 0x00000000UL;
/* Hardware reset vector */
env->hreset_vector = 0xFFFFFFFCUL;
#endif
@@ -2517,6 +2534,7 @@
env->excp_vectors[POWERPC_EXCP_PERFM] = 0x00000F00;
env->excp_vectors[POWERPC_EXCP_IABR] = 0x00001300;
env->excp_vectors[POWERPC_EXCP_SMI] = 0x00001400;
+ env->excp_prefix = 0x00000000UL;
/* Hardware reset vector */
env->hreset_vector = 0xFFFFFFFCUL;
#endif
@@ -2542,6 +2560,7 @@
env->excp_vectors[POWERPC_EXCP_SMI] = 0x00001400;
env->excp_vectors[POWERPC_EXCP_VPUA] = 0x00001600;
env->excp_vectors[POWERPC_EXCP_THERM] = 0x00001700;
+ env->excp_prefix = 0x00000000UL;
/* Hardware reset vector */
env->hreset_vector = 0xFFFFFFFCUL;
#endif
@@ -2569,6 +2588,7 @@
env->excp_vectors[POWERPC_EXCP_IABR] = 0x00001300;
env->excp_vectors[POWERPC_EXCP_SMI] = 0x00001400;
env->excp_vectors[POWERPC_EXCP_VPUA] = 0x00001600;
+ env->excp_prefix = 0x00000000UL;
/* Hardware reset vector */
env->hreset_vector = 0xFFFFFFFCUL;
#endif
@@ -2600,6 +2620,7 @@
env->excp_vectors[POWERPC_EXCP_MAINT] = 0x00001600;
env->excp_vectors[POWERPC_EXCP_VPUA] = 0x00001700;
env->excp_vectors[POWERPC_EXCP_THERM] = 0x00001800;
+ env->excp_prefix = 0x00000000FFF00000ULL;
/* Hardware reset vector */
env->hreset_vector = 0x0000000000000100ULL;
#endif
@@ -3232,7 +3253,7 @@
#define POWERPC_INSNS_601 (POWERPC_INSNS_6xx | PPC_CACHE_DCBZ | \
PPC_SEGMENT | PPC_EXTERN | PPC_POWER_BR)
#define POWERPC_MSRM_601 (0x000000000000FD70ULL)
-#define POWERPC_MMU_601 (POWERPC_MMU_32B)
+//#define POWERPC_MMU_601 (POWERPC_MMU_601)
//#define POWERPC_EXCP_601 (POWERPC_EXCP_601)
#define POWERPC_INPUT_601 (PPC_FLAGS_INPUT_6xx)
#define POWERPC_BFDM_601 (bfd_mach_ppc_601)
@@ -3247,8 +3268,8 @@
/* XXX : not implemented */
spr_register(env, SPR_HID0, "HID0",
SPR_NOACCESS, SPR_NOACCESS,
- &spr_read_generic, &spr_write_generic,
- 0x00000000);
+ &spr_read_generic, &spr_write_hid0_601,
+ 0x80010080);
/* XXX : not implemented */
spr_register(env, SPR_HID1, "HID1",
SPR_NOACCESS, SPR_NOACCESS,
@@ -3278,7 +3299,8 @@
init_excp_601(env);
env->dcache_line_size = 64;
env->icache_line_size = 64;
- /* XXX: TODO: allocate internal IRQ controller */
+ /* Allocate hardware IRQ controller */
+ ppc6xx_irq_init(env);
}
/* PowerPC 602 */
@@ -4183,9 +4205,6 @@
&spr_read_generic, &spr_write_generic,
0xFFF00000); /* XXX: This is a hack */
#if !defined(CONFIG_USER_ONLY)
- env->excp_prefix = 0xFFF00000;
-#endif
-#if !defined(CONFIG_USER_ONLY)
env->slb_nr = 32;
#endif
init_excp_970(env);
@@ -4260,9 +4279,6 @@
&spr_read_generic, &spr_write_generic,
0xFFF00000); /* XXX: This is a hack */
#if !defined(CONFIG_USER_ONLY)
- env->excp_prefix = 0xFFF00000;
-#endif
-#if !defined(CONFIG_USER_ONLY)
env->slb_nr = 32;
#endif
init_excp_970(env);
@@ -4337,9 +4353,6 @@
&spr_read_generic, &spr_write_generic,
0xFFF00000); /* XXX: This is a hack */
#if !defined(CONFIG_USER_ONLY)
- env->excp_prefix = 0xFFF00000;
-#endif
-#if !defined(CONFIG_USER_ONLY)
env->slb_nr = 32;
#endif
init_excp_970(env);
@@ -4414,9 +4427,6 @@
&spr_read_generic, &spr_write_generic,
0xFFF00000); /* XXX: This is a hack */
#if !defined(CONFIG_USER_ONLY)
- env->excp_prefix = 0xFFF00000;
-#endif
-#if !defined(CONFIG_USER_ONLY)
env->slb_nr = 32;
#endif
init_excp_970(env);
@@ -4432,7 +4442,7 @@
#define POWERPC_MSRM_620 (0x800000000005FF73ULL)
#define POWERPC_MMU_620 (POWERPC_MMU_64B)
#define POWERPC_EXCP_620 (POWERPC_EXCP_970)
-#define POWERPC_INPUT_620 (PPC_FLAGS_INPUT_970)
+#define POWERPC_INPUT_620 (PPC_FLAGS_INPUT_6xx)
#define POWERPC_BFDM_620 (bfd_mach_ppc64)
#define POWERPC_FLAG_620 (POWERPC_FLAG_SE | POWERPC_FLAG_BE)
#define check_pow_620 check_pow_nocheck /* Check this */
@@ -4456,7 +4466,8 @@
init_excp_620(env);
env->dcache_line_size = 64;
env->icache_line_size = 64;
- /* XXX: TODO: initialize internal interrupt controller */
+ /* Allocate hardware IRQ controller */
+ ppc6xx_irq_init(env);
}
#endif /* defined (TARGET_PPC64) */
@@ -5771,10 +5782,8 @@
POWERPC_DEF("7457v1.2", CPU_POWERPC_74x7_v12, 0xFFFFFFFF, 7455),
/* 64 bits PowerPC */
#if defined (TARGET_PPC64)
-#if defined (TODO)
/* PowerPC 620 */
POWERPC_DEF("620", CPU_POWERPC_620, 0xFFFFFFFF, 620),
-#endif
#if defined (TODO)
/* PowerPC 630 (POWER3) */
POWERPC_DEF("630", CPU_POWERPC_630, 0xFFFFFFFF, 630),
Modified: trunk/src/host/qemu-neo1973/target-sparc/cpu.h
===================================================================
--- trunk/src/host/qemu-neo1973/target-sparc/cpu.h 2007-11-09 16:32:22 UTC (rev 3386)
+++ trunk/src/host/qemu-neo1973/target-sparc/cpu.h 2007-11-09 17:12:19 UTC (rev 3387)
@@ -147,7 +147,6 @@
/* MMU */
#define MMU_E (1<<0)
#define MMU_NF (1<<1)
-#define MMU_BM (1<<14)
#define PTE_ENTRYTYPE_MASK 3
#define PTE_ACCESS_MASK 0x1c
@@ -200,6 +199,7 @@
int interrupt_index;
int interrupt_request;
int halted;
+ uint32_t mmu_bm;
/* NOTE: we allow 8 more registers to handle wrapping */
target_ulong regbase[NWINDOWS * 16 + 8];
Modified: trunk/src/host/qemu-neo1973/target-sparc/helper.c
===================================================================
--- trunk/src/host/qemu-neo1973/target-sparc/helper.c 2007-11-09 16:32:22 UTC (rev 3386)
+++ trunk/src/host/qemu-neo1973/target-sparc/helper.c 2007-11-09 17:12:19 UTC (rev 3387)
@@ -114,7 +114,7 @@
if ((env->mmuregs[0] & MMU_E) == 0) { /* MMU disabled */
// Boot mode: instruction fetches are taken from PROM
- if (rw == 2 && (env->mmuregs[0] & MMU_BM)) {
+ if (rw == 2 && (env->mmuregs[0] & env->mmu_bm)) {
*physical = 0xff0000000ULL | (address & 0x3ffffULL);
*prot = PAGE_READ | PAGE_EXEC;
return 0;
Modified: trunk/src/host/qemu-neo1973/target-sparc/op_helper.c
===================================================================
--- trunk/src/host/qemu-neo1973/target-sparc/op_helper.c 2007-11-09 16:32:22 UTC (rev 3386)
+++ trunk/src/host/qemu-neo1973/target-sparc/op_helper.c 2007-11-09 17:12:19 UTC (rev 3387)
@@ -493,8 +493,8 @@
oldreg = env->mmuregs[reg];
switch(reg) {
case 0:
- env->mmuregs[reg] &= ~(MMU_E | MMU_NF | MMU_BM);
- env->mmuregs[reg] |= T1 & (MMU_E | MMU_NF | MMU_BM);
+ env->mmuregs[reg] &= ~(MMU_E | MMU_NF | env->mmu_bm);
+ env->mmuregs[reg] |= T1 & (MMU_E | MMU_NF | env->mmu_bm);
// Mappings generated during no-fault mode or MMU
// disabled mode are invalid in normal mode
if (oldreg != env->mmuregs[reg])
Modified: trunk/src/host/qemu-neo1973/target-sparc/translate.c
===================================================================
--- trunk/src/host/qemu-neo1973/target-sparc/translate.c 2007-11-09 16:32:22 UTC (rev 3386)
+++ trunk/src/host/qemu-neo1973/target-sparc/translate.c 2007-11-09 17:12:19 UTC (rev 3387)
@@ -59,6 +59,7 @@
target_ulong iu_version;
uint32_t fpu_version;
uint32_t mmu_version;
+ uint32_t mmu_bm;
};
static uint16_t *gen_opc_ptr;
@@ -3482,7 +3483,7 @@
#else
env->pc = 0;
env->mmuregs[0] &= ~(MMU_E | MMU_NF);
- env->mmuregs[0] |= MMU_BM;
+ env->mmuregs[0] |= env->mmu_bm;
#endif
env->npc = env->pc + 4;
#endif
@@ -3496,7 +3497,6 @@
if (!env)
return NULL;
cpu_exec_init(env);
- cpu_reset(env);
return (env);
}
@@ -3515,30 +3515,35 @@
.iu_version = 0x04 << 24, /* Impl 0, ver 4 */
.fpu_version = 4 << 17, /* FPU version 4 (Meiko) */
.mmu_version = 0x04 << 24, /* Impl 0, ver 4 */
+ .mmu_bm = 0x00004000,
},
{
.name = "Fujitsu MB86907",
.iu_version = 0x05 << 24, /* Impl 0, ver 5 */
.fpu_version = 4 << 17, /* FPU version 4 (Meiko) */
.mmu_version = 0x05 << 24, /* Impl 0, ver 5 */
+ .mmu_bm = 0x00004000,
},
{
.name = "TI MicroSparc I",
.iu_version = 0x41000000,
.fpu_version = 4 << 17,
.mmu_version = 0x41000000,
+ .mmu_bm = 0x00004000,
},
{
.name = "TI SuperSparc II",
.iu_version = 0x40000000,
.fpu_version = 0 << 17,
.mmu_version = 0x04000000,
+ .mmu_bm = 0x00002000,
},
{
.name = "Ross RT620",
.iu_version = 0x1e000000,
.fpu_version = 1 << 17,
.mmu_version = 0x17000000,
+ .mmu_bm = 0x00004000,
},
#endif
};
@@ -3579,9 +3584,11 @@
env->version = def->iu_version;
env->fsr = def->fpu_version;
#if !defined(TARGET_SPARC64)
+ env->mmu_bm = def->mmu_bm;
env->mmuregs[0] |= def->mmu_version;
env->mxccregs[7] = ((cpu + 8) & 0xf) << 24;
#endif
+ cpu_reset(env);
return 0;
}
Modified: trunk/src/host/qemu-neo1973/tests/qruncom.c
===================================================================
--- trunk/src/host/qemu-neo1973/tests/qruncom.c 2007-11-09 16:32:22 UTC (rev 3386)
+++ trunk/src/host/qemu-neo1973/tests/qruncom.c 2007-11-09 17:12:19 UTC (rev 3387)
@@ -193,9 +193,6 @@
act.sa_sigaction = host_segv_handler;
sigaction(SIGSEGV, &act, NULL);
sigaction(SIGBUS, &act, NULL);
-#if defined (TARGET_I386) && defined(USE_CODE_COPY)
- sigaction(SIGFPE, &act, NULL);
-#endif
}
// cpu_set_log(CPU_LOG_TB_IN_ASM | CPU_LOG_TB_OUT_ASM | CPU_LOG_EXEC);
Modified: trunk/src/host/qemu-neo1973/translate-all.c
===================================================================
--- trunk/src/host/qemu-neo1973/translate-all.c 2007-11-09 16:32:22 UTC (rev 3386)
+++ trunk/src/host/qemu-neo1973/translate-all.c 2007-11-09 17:12:19 UTC (rev 3387)
@@ -144,35 +144,27 @@
uint8_t *gen_code_buf;
int gen_code_size;
-#ifdef USE_CODE_COPY
- if (code_copy_enabled &&
- cpu_gen_code_copy(env, tb, max_code_size, &gen_code_size) == 0) {
- /* nothing more to do */
- } else
-#endif
- {
- if (gen_intermediate_code(env, tb) < 0)
- return -1;
-
- /* generate machine code */
- tb->tb_next_offset[0] = 0xffff;
- tb->tb_next_offset[1] = 0xffff;
- gen_code_buf = tb->tc_ptr;
+ if (gen_intermediate_code(env, tb) < 0)
+ return -1;
+
+ /* generate machine code */
+ tb->tb_next_offset[0] = 0xffff;
+ tb->tb_next_offset[1] = 0xffff;
+ gen_code_buf = tb->tc_ptr;
#ifdef USE_DIRECT_JUMP
- /* the following two entries are optional (only used for string ops) */
- tb->tb_jmp_offset[2] = 0xffff;
- tb->tb_jmp_offset[3] = 0xffff;
+ /* the following two entries are optional (only used for string ops) */
+ tb->tb_jmp_offset[2] = 0xffff;
+ tb->tb_jmp_offset[3] = 0xffff;
#endif
- dyngen_labels(gen_labels, nb_gen_labels, gen_code_buf, gen_opc_buf);
-
- gen_code_size = dyngen_code(gen_code_buf, tb->tb_next_offset,
+ dyngen_labels(gen_labels, nb_gen_labels, gen_code_buf, gen_opc_buf);
+
+ gen_code_size = dyngen_code(gen_code_buf, tb->tb_next_offset,
#ifdef USE_DIRECT_JUMP
- tb->tb_jmp_offset,
+ tb->tb_jmp_offset,
#else
- NULL,
+ NULL,
#endif
- gen_opc_buf, gen_opparam_buf, gen_labels);
- }
+ gen_opc_buf, gen_opparam_buf, gen_labels);
*gen_code_size_ptr = gen_code_size;
#ifdef DEBUG_DISAS
if (loglevel & CPU_LOG_TB_OUT_ASM) {
@@ -195,11 +187,6 @@
unsigned long tc_ptr;
uint16_t *opc_ptr;
-#ifdef USE_CODE_COPY
- if (tb->cflags & CF_CODE_COPY) {
- return cpu_restore_state_copy(tb, env, searched_pc, puc);
- }
-#endif
if (gen_intermediate_code_pc(env, tb) < 0)
return -1;
Modified: trunk/src/host/qemu-neo1973/vl.c
===================================================================
--- trunk/src/host/qemu-neo1973/vl.c 2007-11-09 16:32:22 UTC (rev 3386)
+++ trunk/src/host/qemu-neo1973/vl.c 2007-11-09 17:12:19 UTC (rev 3387)
@@ -174,6 +174,7 @@
NICInfo nd_table[MAX_NICS];
int vm_running;
int rtc_utc = 1;
+int rtc_start_date = -1; /* -1 means now */
int cirrus_vga_enabled = 1;
int vmsvga_enabled = 0;
#ifdef TARGET_SPARC
@@ -1223,9 +1224,6 @@
/* timer signal */
sigfillset(&act.sa_mask);
act.sa_flags = 0;
-#if defined (TARGET_I386) && defined(USE_CODE_COPY)
- act.sa_flags |= SA_ONSTACK;
-#endif
act.sa_handler = host_alarm_handler;
sigaction(SIGIO, &act, NULL);
@@ -1323,9 +1321,6 @@
sigfillset(&act.sa_mask);
act.sa_flags = 0;
-#if defined(TARGET_I386) && defined(USE_CODE_COPY)
- act.sa_flags |= SA_ONSTACK;
-#endif
act.sa_handler = host_alarm_handler;
sigaction(SIGALRM, &act, NULL);
@@ -1400,9 +1395,6 @@
/* timer signal */
sigfillset(&act.sa_mask);
act.sa_flags = 0;
-#if defined(TARGET_I386) && defined(USE_CODE_COPY)
- act.sa_flags |= SA_ONSTACK;
-#endif
act.sa_handler = host_alarm_handler;
sigaction(SIGALRM, &act, NULL);
@@ -7310,9 +7302,6 @@
"-kernel-kqemu enable KQEMU full virtualization (default is user mode only)\n"
"-no-kqemu disable KQEMU kernel module usage\n"
#endif
-#ifdef USE_CODE_COPY
- "-no-code-copy disable code copy acceleration\n"
-#endif
#ifdef TARGET_I386
"-std-vga simulate a standard VGA card with VESA Bochs Extensions\n"
" (default is CL-GD5446 PCI VGA)\n"
@@ -7431,6 +7420,7 @@
QEMU_OPTION_prom_env,
QEMU_OPTION_old_param,
QEMU_OPTION_clock,
+ QEMU_OPTION_startdate,
};
typedef struct QEMUOption {
@@ -7538,18 +7528,10 @@
{ "old-param", 0, QEMU_OPTION_old_param },
#endif
{ "clock", HAS_ARG, QEMU_OPTION_clock },
+ { "startdate", HAS_ARG, QEMU_OPTION_startdate },
{ NULL },
};
-#if defined (TARGET_I386) && defined(USE_CODE_COPY)
-
-/* this stack is only used during signal handling */
-#define SIGNAL_STACK_SIZE 32768
-
-static uint8_t *signal_stack;
-
-#endif
-
/* password input */
int qemu_key_check(BlockDriverState *bs, const char *name)
@@ -8343,6 +8325,42 @@
case QEMU_OPTION_clock:
configure_alarms(optarg);
break;
+ case QEMU_OPTION_startdate:
+ {
+ struct tm tm;
+ if (!strcmp(optarg, "now")) {
+ rtc_start_date = -1;
+ } else {
+ if (sscanf(optarg, "%d-%d-%dT%d:%d:%d",
+ &tm.tm_year,
+ &tm.tm_mon,
+ &tm.tm_mday,
+ &tm.tm_hour,
+ &tm.tm_min,
+ &tm.tm_sec) == 6) {
+ /* OK */
+ } else if (sscanf(optarg, "%d-%d-%d",
+ &tm.tm_year,
+ &tm.tm_mon,
+ &tm.tm_mday) == 3) {
+ tm.tm_hour = 0;
+ tm.tm_min = 0;
+ tm.tm_sec = 0;
+ } else {
+ goto date_fail;
+ }
+ tm.tm_year -= 1900;
+ tm.tm_mon--;
+ rtc_start_date = timegm(&tm);
+ if (rtc_start_date == -1) {
+ date_fail:
+ fprintf(stderr, "Invalid date format. Valid format are:\n"
+ "'now' or '2006-06-17T16:01:21' or '2006-06-17'\n");
+ exit(1);
+ }
+ }
+ }
+ break;
}
}
}
Modified: trunk/src/host/qemu-neo1973/vl.h
===================================================================
--- trunk/src/host/qemu-neo1973/vl.h 2007-11-09 16:32:22 UTC (rev 3386)
+++ trunk/src/host/qemu-neo1973/vl.h 2007-11-09 17:12:19 UTC (rev 3387)
@@ -72,8 +72,8 @@
#ifdef QEMU_TOOL
-/* we use QEMU_TOOL in the command line tools which do not depend on
- the target CPU type */
+/* we use QEMU_TOOL on code which does not depend on the target CPU
+ type */
#include "config-host.h"
#include <setjmp.h>
#include "osdep.h"
@@ -81,7 +81,6 @@
#else
-#include "audio/audio.h"
#include "cpu.h"
#endif /* !defined(QEMU_TOOL) */
@@ -117,6 +116,8 @@
#endif
#endif
+#include "audio/audio.h"
+
/* cutils.c */
void pstrcpy(char *buf, int buf_size, const char *str);
char *pstrcat(char *buf, int buf_size, const char *s);
@@ -166,6 +167,7 @@
extern int ram_size;
extern int bios_size;
extern int rtc_utc;
+extern int rtc_start_date;
extern int cirrus_vga_enabled;
extern int vmsvga_enabled;
extern int graphic_width;
@@ -361,6 +363,38 @@
typedef struct DisplayState DisplayState;
typedef struct TextConsole TextConsole;
+struct DisplayState {
+ uint8_t *data;
+ int linesize;
+ int depth;
+ int bgr; /* BGR color order instead of RGB. Only valid for depth == 32 */
+ int width;
+ int height;
+ void *opaque;
+ struct QEMUTimer *gui_timer;
+
+ void (*dpy_update)(struct DisplayState *s, int x, int y, int w, int h);
+ void (*dpy_resize)(struct DisplayState *s, int w, int h);
+ void (*dpy_refresh)(struct DisplayState *s);
+ void (*dpy_copy)(struct DisplayState *s, int src_x, int src_y,
+ int dst_x, int dst_y, int w, int h);
+ void (*dpy_fill)(struct DisplayState *s, int x, int y,
+ int w, int h, uint32_t c);
+ void (*mouse_set)(int x, int y, int on);
+ void (*cursor_define)(int width, int height, int bpp, int hot_x, int hot_y,
+ uint8_t *image, uint8_t *mask);
+};
+
+static inline void dpy_update(DisplayState *s, int x, int y, int w, int h)
+{
+ s->dpy_update(s, x, y, w, h);
+}
+
+static inline void dpy_resize(DisplayState *s, int w, int h)
+{
+ s->dpy_resize(s, w, h);
+}
+
typedef void (*vga_hw_update_ptr)(void *);
typedef void (*vga_hw_invalidate_ptr)(void *);
typedef void (*vga_hw_screen_dump_ptr)(void *, const char *);
@@ -730,6 +764,33 @@
const char *base_path,
const char *filename);
+
+/* monitor.c */
+void monitor_init(CharDriverState *hd, int show_banner);
+void term_puts(const char *str);
+void term_vprintf(const char *fmt, va_list ap);
+void term_printf(const char *fmt, ...) __attribute__ ((__format__ (__printf__, 1, 2)));
+void term_print_filename(const char *filename);
+void term_flush(void);
+void term_print_help(void);
+void monitor_readline(const char *prompt, int is_password,
+ char *buf, int buf_size);
+
+/* readline.c */
+typedef void ReadLineFunc(void *opaque, const char *str);
+
+extern int completion_index;
+void add_completion(const char *str);
+void readline_handle_byte(int ch);
+void readline_find_completion(const char *cmdline);
+const char *readline_get_history(unsigned int index);
+void readline_start(const char *prompt, int is_password,
+ ReadLineFunc *readline_func, void *opaque);
+void readline_history_save(void);
+void readline_history_restore(void);
+
+void kqemu_record_dump(void);
+
#ifndef QEMU_TOOL
typedef void QEMUMachineInitFunc(int ram_size, int vga_ram_size,
@@ -917,38 +978,6 @@
#define VGA_RAM_SIZE (9 * 1024 * 1024)
#endif
-struct DisplayState {
- uint8_t *data;
- int linesize;
- int depth;
- int bgr; /* BGR color order instead of RGB. Only valid for depth == 32 */
- int width;
- int height;
- void *opaque;
- QEMUTimer *gui_timer;
-
- void (*dpy_update)(struct DisplayState *s, int x, int y, int w, int h);
- void (*dpy_resize)(struct DisplayState *s, int w, int h);
- void (*dpy_refresh)(struct DisplayState *s);
- void (*dpy_copy)(struct DisplayState *s, int src_x, int src_y,
- int dst_x, int dst_y, int w, int h);
- void (*dpy_fill)(struct DisplayState *s, int x, int y,
- int w, int h, uint32_t c);
- void (*mouse_set)(int x, int y, int on);
- void (*cursor_define)(int width, int height, int bpp, int hot_x, int hot_y,
- uint8_t *image, uint8_t *mask);
-};
-
-static inline void dpy_update(DisplayState *s, int x, int y, int w, int h)
-{
- s->dpy_update(s, x, y, w, h);
-}
-
-static inline void dpy_resize(DisplayState *s, int w, int h)
-{
- s->dpy_resize(s, w, h);
-}
-
int isa_vga_init(DisplayState *ds, uint8_t *vga_ram_base,
unsigned long vga_ram_offset, int vga_ram_size);
int pci_vga_init(PCIBus *bus, DisplayState *ds, uint8_t *vga_ram_base,
@@ -1043,6 +1072,8 @@
fdctrl_t *fdctrl_init (qemu_irq irq, int dma_chann, int mem_mapped,
target_phys_addr_t io_base,
BlockDriverState **fds);
+fdctrl_t *sun4m_fdctrl_init (qemu_irq irq, target_phys_addr_t io_base,
+ BlockDriverState **fds);
int fdctrl_get_drive_type(fdctrl_t *fdctrl, int drive_num);
/* eepro100.c */
@@ -1691,12 +1722,14 @@
void qemu_get_ptimer(QEMUFile *f, ptimer_state *s);
#include "hw/pxa.h"
+
#include "hw/s3c.h"
#include "hw/omap.h"
/* tsc210x.c */
-struct uwire_slave_s *tsc2102_init(qemu_irq pint);
+struct uwire_slave_s *tsc2102_init(qemu_irq pint, AudioState *audio);
+struct i2s_codec_s *tsc210x_codec(struct uwire_slave_s *chip);
/* mcf_uart.c */
uint32_t mcf_uart_read(void *opaque, target_phys_addr_t addr);
@@ -1723,31 +1756,4 @@
#include "gdbstub.h"
#endif /* defined(QEMU_TOOL) */
-
-/* monitor.c */
-void monitor_init(CharDriverState *hd, int show_banner);
-void term_puts(const char *str);
-void term_vprintf(const char *fmt, va_list ap);
-void term_printf(const char *fmt, ...) __attribute__ ((__format__ (__printf__, 1, 2)));
-void term_print_filename(const char *filename);
-void term_flush(void);
-void term_print_help(void);
-void monitor_readline(const char *prompt, int is_password,
- char *buf, int buf_size);
-
-/* readline.c */
-typedef void ReadLineFunc(void *opaque, const char *str);
-
-extern int completion_index;
-void add_completion(const char *str);
-void readline_handle_byte(int ch);
-void readline_find_completion(const char *cmdline);
-const char *readline_get_history(unsigned int index);
-void readline_start(const char *prompt, int is_password,
- ReadLineFunc *readline_func, void *opaque);
-void readline_history_save(void);
-void readline_history_restore(void);
-
-void kqemu_record_dump(void);
-
#endif /* VL_H */
More information about the commitlog
mailing list