r3303 - in trunk/src/host/qemu-neo1973: . darwin-user hw linux-user linux-user/alpha linux-user/arm linux-user/cris linux-user/i386 linux-user/m68k linux-user/mips linux-user/ppc linux-user/sh4 linux-user/sparc linux-user/sparc64 linux-user/x86_64 pc-bios slirp target-alpha target-arm target-cris target-i386 target-m68k target-mips target-ppc target-sh4 target-sparc tests
andrew at sita.openmoko.org
andrew at sita.openmoko.org
Mon Oct 29 22:16:21 CET 2007
Author: andrew
Date: 2007-10-29 22:14:04 +0100 (Mon, 29 Oct 2007)
New Revision: 3303
Added:
trunk/src/host/qemu-neo1973/cris-dis.c
trunk/src/host/qemu-neo1973/host-utils.h
trunk/src/host/qemu-neo1973/hw/ecc.c
trunk/src/host/qemu-neo1973/hw/etraxfs.c
trunk/src/host/qemu-neo1973/hw/etraxfs_ser.c
trunk/src/host/qemu-neo1973/hw/etraxfs_timer.c
trunk/src/host/qemu-neo1973/hw/mac_dbdma.c
trunk/src/host/qemu-neo1973/hw/mac_nvram.c
trunk/src/host/qemu-neo1973/hw/macio.c
trunk/src/host/qemu-neo1973/hw/mips_mipssim.c
trunk/src/host/qemu-neo1973/hw/mipsnet.c
trunk/src/host/qemu-neo1973/hw/ppc4xx.h
trunk/src/host/qemu-neo1973/hw/ppc4xx_devs.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/r2d.c
trunk/src/host/qemu-neo1973/hw/sh_intc.c
trunk/src/host/qemu-neo1973/hw/sh_intc.h
trunk/src/host/qemu-neo1973/hw/sh_serial.c
trunk/src/host/qemu-neo1973/hw/sh_timer.c
trunk/src/host/qemu-neo1973/hw/tsc210x.c
trunk/src/host/qemu-neo1973/linux-user/alpha/target_signal.h
trunk/src/host/qemu-neo1973/linux-user/arm/target_signal.h
trunk/src/host/qemu-neo1973/linux-user/cris/
trunk/src/host/qemu-neo1973/linux-user/cris/syscall.h
trunk/src/host/qemu-neo1973/linux-user/cris/syscall_nr.h
trunk/src/host/qemu-neo1973/linux-user/cris/target_signal.h
trunk/src/host/qemu-neo1973/linux-user/cris/termbits.h
trunk/src/host/qemu-neo1973/linux-user/elfload32.c
trunk/src/host/qemu-neo1973/linux-user/i386/target_signal.h
trunk/src/host/qemu-neo1973/linux-user/m68k/target_signal.h
trunk/src/host/qemu-neo1973/linux-user/mips/target_signal.h
trunk/src/host/qemu-neo1973/linux-user/ppc/target_signal.h
trunk/src/host/qemu-neo1973/linux-user/sh4/target_signal.h
trunk/src/host/qemu-neo1973/linux-user/sparc/target_signal.h
trunk/src/host/qemu-neo1973/linux-user/sparc64/target_signal.h
trunk/src/host/qemu-neo1973/linux-user/x86_64/target_signal.h
trunk/src/host/qemu-neo1973/target-alpha/STATUS
trunk/src/host/qemu-neo1973/target-cris/
trunk/src/host/qemu-neo1973/target-cris/cpu.h
trunk/src/host/qemu-neo1973/target-cris/crisv32-decode.h
trunk/src/host/qemu-neo1973/target-cris/exec.h
trunk/src/host/qemu-neo1973/target-cris/helper.c
trunk/src/host/qemu-neo1973/target-cris/mmu.c
trunk/src/host/qemu-neo1973/target-cris/mmu.h
trunk/src/host/qemu-neo1973/target-cris/op.c
trunk/src/host/qemu-neo1973/target-cris/op_helper.c
trunk/src/host/qemu-neo1973/target-cris/op_mem.c
trunk/src/host/qemu-neo1973/target-cris/op_template.h
trunk/src/host/qemu-neo1973/target-cris/opcode-cris.h
trunk/src/host/qemu-neo1973/target-cris/translate.c
trunk/src/host/qemu-neo1973/target-i386/svm.h
trunk/src/host/qemu-neo1973/target-ppc/helper_regs.h
Removed:
trunk/src/host/qemu-neo1973/ecc.h
trunk/src/host/qemu-neo1973/linux-user/ppc64/
trunk/src/host/qemu-neo1973/target-mips/op_helper_mem.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/block-raw.c
trunk/src/host/qemu-neo1973/block-vmdk.c
trunk/src/host/qemu-neo1973/block-vvfat.c
trunk/src/host/qemu-neo1973/configure
trunk/src/host/qemu-neo1973/cpu-all.h
trunk/src/host/qemu-neo1973/cpu-defs.h
trunk/src/host/qemu-neo1973/cpu-exec.c
trunk/src/host/qemu-neo1973/darwin-user/main.c
trunk/src/host/qemu-neo1973/dis-asm.h
trunk/src/host/qemu-neo1973/disas.c
trunk/src/host/qemu-neo1973/elf.h
trunk/src/host/qemu-neo1973/elf_ops.h
trunk/src/host/qemu-neo1973/exec-all.h
trunk/src/host/qemu-neo1973/exec.c
trunk/src/host/qemu-neo1973/gdbstub.c
trunk/src/host/qemu-neo1973/host-utils.c
trunk/src/host/qemu-neo1973/hw/acpi.c
trunk/src/host/qemu-neo1973/hw/alpha_palcode.c
trunk/src/host/qemu-neo1973/hw/apb_pci.c
trunk/src/host/qemu-neo1973/hw/apic.c
trunk/src/host/qemu-neo1973/hw/cs4231.c
trunk/src/host/qemu-neo1973/hw/cuda.c
trunk/src/host/qemu-neo1973/hw/esp.c
trunk/src/host/qemu-neo1973/hw/grackle_pci.c
trunk/src/host/qemu-neo1973/hw/gt64xxx.c
trunk/src/host/qemu-neo1973/hw/heathrow_pic.c
trunk/src/host/qemu-neo1973/hw/i8259.c
trunk/src/host/qemu-neo1973/hw/iommu.c
trunk/src/host/qemu-neo1973/hw/irq.c
trunk/src/host/qemu-neo1973/hw/irq.h
trunk/src/host/qemu-neo1973/hw/m48t59.c
trunk/src/host/qemu-neo1973/hw/m48t59.h
trunk/src/host/qemu-neo1973/hw/mips_malta.c
trunk/src/host/qemu-neo1973/hw/mips_pica61.c
trunk/src/host/qemu-neo1973/hw/mips_r4k.c
trunk/src/host/qemu-neo1973/hw/mips_timer.c
trunk/src/host/qemu-neo1973/hw/omap.c
trunk/src/host/qemu-neo1973/hw/omap.h
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/pckbd.c
trunk/src/host/qemu-neo1973/hw/piix_pci.c
trunk/src/host/qemu-neo1973/hw/pl110.c
trunk/src/host/qemu-neo1973/hw/pl110_template.h
trunk/src/host/qemu-neo1973/hw/ppc.c
trunk/src/host/qemu-neo1973/hw/ppc405.h
trunk/src/host/qemu-neo1973/hw/ppc405_boards.c
trunk/src/host/qemu-neo1973/hw/ppc405_uc.c
trunk/src/host/qemu-neo1973/hw/ppc_chrp.c
trunk/src/host/qemu-neo1973/hw/ppc_prep.c
trunk/src/host/qemu-neo1973/hw/prep_pci.c
trunk/src/host/qemu-neo1973/hw/pxa.h
trunk/src/host/qemu-neo1973/hw/pxa2xx_gpio.c
trunk/src/host/qemu-neo1973/hw/sh7750.c
trunk/src/host/qemu-neo1973/hw/sh7750_regnames.c
trunk/src/host/qemu-neo1973/hw/sh7750_regs.h
trunk/src/host/qemu-neo1973/hw/shix.c
trunk/src/host/qemu-neo1973/hw/slavio_intctl.c
trunk/src/host/qemu-neo1973/hw/slavio_misc.c
trunk/src/host/qemu-neo1973/hw/slavio_serial.c
trunk/src/host/qemu-neo1973/hw/slavio_timer.c
trunk/src/host/qemu-neo1973/hw/spitz.c
trunk/src/host/qemu-neo1973/hw/sun4m.c
trunk/src/host/qemu-neo1973/hw/sun4u.c
trunk/src/host/qemu-neo1973/hw/tcx.c
trunk/src/host/qemu-neo1973/hw/usb-uhci.c
trunk/src/host/qemu-neo1973/hw/vmport.c
trunk/src/host/qemu-neo1973/linux-user/alpha/syscall.h
trunk/src/host/qemu-neo1973/linux-user/alpha/syscall_nr.h
trunk/src/host/qemu-neo1973/linux-user/arm/syscall.h
trunk/src/host/qemu-neo1973/linux-user/arm/syscall_nr.h
trunk/src/host/qemu-neo1973/linux-user/arm/termbits.h
trunk/src/host/qemu-neo1973/linux-user/elfload.c
trunk/src/host/qemu-neo1973/linux-user/flat.h
trunk/src/host/qemu-neo1973/linux-user/flatload.c
trunk/src/host/qemu-neo1973/linux-user/i386/syscall.h
trunk/src/host/qemu-neo1973/linux-user/i386/syscall_nr.h
trunk/src/host/qemu-neo1973/linux-user/i386/termbits.h
trunk/src/host/qemu-neo1973/linux-user/linuxload.c
trunk/src/host/qemu-neo1973/linux-user/m68k/syscall.h
trunk/src/host/qemu-neo1973/linux-user/m68k/syscall_nr.h
trunk/src/host/qemu-neo1973/linux-user/m68k/termbits.h
trunk/src/host/qemu-neo1973/linux-user/main.c
trunk/src/host/qemu-neo1973/linux-user/mips/syscall.h
trunk/src/host/qemu-neo1973/linux-user/mips/syscall_nr.h
trunk/src/host/qemu-neo1973/linux-user/mips/termbits.h
trunk/src/host/qemu-neo1973/linux-user/mmap.c
trunk/src/host/qemu-neo1973/linux-user/ppc/syscall.h
trunk/src/host/qemu-neo1973/linux-user/ppc/syscall_nr.h
trunk/src/host/qemu-neo1973/linux-user/ppc/termbits.h
trunk/src/host/qemu-neo1973/linux-user/qemu.h
trunk/src/host/qemu-neo1973/linux-user/sh4/syscall_nr.h
trunk/src/host/qemu-neo1973/linux-user/signal.c
trunk/src/host/qemu-neo1973/linux-user/sparc/syscall.h
trunk/src/host/qemu-neo1973/linux-user/sparc/syscall_nr.h
trunk/src/host/qemu-neo1973/linux-user/sparc/termbits.h
trunk/src/host/qemu-neo1973/linux-user/sparc64/syscall.h
trunk/src/host/qemu-neo1973/linux-user/sparc64/syscall_nr.h
trunk/src/host/qemu-neo1973/linux-user/sparc64/termbits.h
trunk/src/host/qemu-neo1973/linux-user/syscall.c
trunk/src/host/qemu-neo1973/linux-user/syscall_defs.h
trunk/src/host/qemu-neo1973/linux-user/vm86.c
trunk/src/host/qemu-neo1973/linux-user/x86_64/syscall.h
trunk/src/host/qemu-neo1973/linux-user/x86_64/syscall_nr.h
trunk/src/host/qemu-neo1973/loader.c
trunk/src/host/qemu-neo1973/monitor.c
trunk/src/host/qemu-neo1973/pc-bios/README
trunk/src/host/qemu-neo1973/pc-bios/openbios-sparc32
trunk/src/host/qemu-neo1973/pc-bios/ppc_rom.bin
trunk/src/host/qemu-neo1973/qemu-binfmt-conf.sh
trunk/src/host/qemu-neo1973/qemu-doc.texi
trunk/src/host/qemu-neo1973/qemu-img.c
trunk/src/host/qemu-neo1973/qemu-tech.texi
trunk/src/host/qemu-neo1973/readline.c
trunk/src/host/qemu-neo1973/slirp/bootp.c
trunk/src/host/qemu-neo1973/slirp/debug.c
trunk/src/host/qemu-neo1973/slirp/debug.h
trunk/src/host/qemu-neo1973/slirp/icmp_var.h
trunk/src/host/qemu-neo1973/slirp/if.c
trunk/src/host/qemu-neo1973/slirp/if.h
trunk/src/host/qemu-neo1973/slirp/ip.h
trunk/src/host/qemu-neo1973/slirp/ip_icmp.c
trunk/src/host/qemu-neo1973/slirp/ip_input.c
trunk/src/host/qemu-neo1973/slirp/ip_output.c
trunk/src/host/qemu-neo1973/slirp/libslirp.h
trunk/src/host/qemu-neo1973/slirp/main.h
trunk/src/host/qemu-neo1973/slirp/mbuf.c
trunk/src/host/qemu-neo1973/slirp/mbuf.h
trunk/src/host/qemu-neo1973/slirp/misc.c
trunk/src/host/qemu-neo1973/slirp/misc.h
trunk/src/host/qemu-neo1973/slirp/sbuf.c
trunk/src/host/qemu-neo1973/slirp/sbuf.h
trunk/src/host/qemu-neo1973/slirp/slirp.c
trunk/src/host/qemu-neo1973/slirp/slirp.h
trunk/src/host/qemu-neo1973/slirp/socket.c
trunk/src/host/qemu-neo1973/slirp/socket.h
trunk/src/host/qemu-neo1973/slirp/tcp.h
trunk/src/host/qemu-neo1973/slirp/tcp_input.c
trunk/src/host/qemu-neo1973/slirp/tcp_output.c
trunk/src/host/qemu-neo1973/slirp/tcp_subr.c
trunk/src/host/qemu-neo1973/slirp/tcp_timer.c
trunk/src/host/qemu-neo1973/slirp/tcp_timer.h
trunk/src/host/qemu-neo1973/slirp/tcp_var.h
trunk/src/host/qemu-neo1973/slirp/tftp.c
trunk/src/host/qemu-neo1973/slirp/udp.c
trunk/src/host/qemu-neo1973/slirp/udp.h
trunk/src/host/qemu-neo1973/softmmu_exec.h
trunk/src/host/qemu-neo1973/softmmu_header.h
trunk/src/host/qemu-neo1973/softmmu_template.h
trunk/src/host/qemu-neo1973/sparc-dis.c
trunk/src/host/qemu-neo1973/sparc.ld
trunk/src/host/qemu-neo1973/sparc64.ld
trunk/src/host/qemu-neo1973/target-alpha/cpu.h
trunk/src/host/qemu-neo1973/target-alpha/exec.h
trunk/src/host/qemu-neo1973/target-alpha/helper.c
trunk/src/host/qemu-neo1973/target-alpha/op.c
trunk/src/host/qemu-neo1973/target-alpha/op_helper.c
trunk/src/host/qemu-neo1973/target-alpha/op_helper.h
trunk/src/host/qemu-neo1973/target-alpha/op_mem.h
trunk/src/host/qemu-neo1973/target-alpha/translate.c
trunk/src/host/qemu-neo1973/target-arm/cpu.h
trunk/src/host/qemu-neo1973/target-arm/exec.h
trunk/src/host/qemu-neo1973/target-arm/helper.c
trunk/src/host/qemu-neo1973/target-arm/op_helper.c
trunk/src/host/qemu-neo1973/target-i386/cpu.h
trunk/src/host/qemu-neo1973/target-i386/exec.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/op.c
trunk/src/host/qemu-neo1973/target-i386/translate.c
trunk/src/host/qemu-neo1973/target-m68k/cpu.h
trunk/src/host/qemu-neo1973/target-m68k/exec.h
trunk/src/host/qemu-neo1973/target-m68k/helper.c
trunk/src/host/qemu-neo1973/target-m68k/op_helper.c
trunk/src/host/qemu-neo1973/target-mips/TODO
trunk/src/host/qemu-neo1973/target-mips/cpu.h
trunk/src/host/qemu-neo1973/target-mips/exec.h
trunk/src/host/qemu-neo1973/target-mips/helper.c
trunk/src/host/qemu-neo1973/target-mips/mips-defs.h
trunk/src/host/qemu-neo1973/target-mips/op.c
trunk/src/host/qemu-neo1973/target-mips/op_helper.c
trunk/src/host/qemu-neo1973/target-mips/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/STATUS
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/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/op_helper_mem.h
trunk/src/host/qemu-neo1973/target-ppc/op_mem.h
trunk/src/host/qemu-neo1973/target-ppc/op_template.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-sh4/cpu.h
trunk/src/host/qemu-neo1973/target-sh4/exec.h
trunk/src/host/qemu-neo1973/target-sh4/helper.c
trunk/src/host/qemu-neo1973/target-sh4/op_helper.c
trunk/src/host/qemu-neo1973/target-sh4/translate.c
trunk/src/host/qemu-neo1973/target-sparc/cpu.h
trunk/src/host/qemu-neo1973/target-sparc/exec.h
trunk/src/host/qemu-neo1973/target-sparc/helper.c
trunk/src/host/qemu-neo1973/target-sparc/op.c
trunk/src/host/qemu-neo1973/target-sparc/op_helper.c
trunk/src/host/qemu-neo1973/target-sparc/op_mem.h
trunk/src/host/qemu-neo1973/target-sparc/translate.c
trunk/src/host/qemu-neo1973/tests/Makefile
trunk/src/host/qemu-neo1973/thunk.c
trunk/src/host/qemu-neo1973/thunk.h
trunk/src/host/qemu-neo1973/usb-linux.c
trunk/src/host/qemu-neo1973/vl.c
trunk/src/host/qemu-neo1973/vl.h
trunk/src/host/qemu-neo1973/vnc.c
Log:
Pull changes from cvs.savannah.nongnu.org.
Modified: trunk/src/host/qemu-neo1973/Changelog
===================================================================
--- trunk/src/host/qemu-neo1973/Changelog 2007-10-29 20:40:05 UTC (rev 3302)
+++ trunk/src/host/qemu-neo1973/Changelog 2007-10-29 21:14:04 UTC (rev 3303)
@@ -3,7 +3,7 @@
- Monitor multiplexing to several I/O channels (Jason Wessel)
- ds1225y nvram support (Herve Poussineau)
- CPU model selection support (J. Mayer, Paul Brook, Herve Poussineau)
- - Several Sparc fixes (Aurelien Jarno, Blue Swirl)
+ - Several Sparc fixes (Aurelien Jarno, Blue Swirl, Robert Reif)
- MIPS 64-bit FPU support (Thiemo Seufer)
- Xscale PDA emulation (Andrzei Zaborowski)
- ColdFire system emulation (Paul Brook)
@@ -11,6 +11,9 @@
- MIPS64 support (Aurelien Jarno, Thiemo Seufer)
- Preliminary Alpha guest support (J. Mayer)
- Read-only support for Parallels disk images (Alex Beregszaszi)
+ - SVM (x86 virtualization) support (Alexander Graf)
+ - CRIS emulation (Edgar E. Iglesias)
+ - SPARC32PLUS execution support (Blue Swirl)
version 0.9.0:
Modified: trunk/src/host/qemu-neo1973/Makefile
===================================================================
--- trunk/src/host/qemu-neo1973/Makefile 2007-10-29 20:40:05 UTC (rev 3302)
+++ trunk/src/host/qemu-neo1973/Makefile 2007-10-29 21:14:04 UTC (rev 3303)
@@ -13,7 +13,6 @@
CPPFLAGS += -I. -D_GNU_SOURCE -D_FILE_OFFSET_BITS=64 -D_LARGEFILE_SOURCE
LIBS=
-TOOLS=qemu-img$(EXESUF) raw2flash$(EXESUF) flash2raw$(EXESUF)
ifdef CONFIG_STATIC
BASE_LDFLAGS += -static
endif
@@ -80,7 +79,9 @@
install: all $(if $(BUILD_DOCS),install-doc)
mkdir -p "$(DESTDIR)$(bindir)"
+ifneq ($(TOOLS),)
$(INSTALL) -m 755 -s $(TOOLS) "$(DESTDIR)$(bindir)"
+endif
mkdir -p "$(DESTDIR)$(datadir)"
for x in bios.bin vgabios.bin vgabios-cirrus.bin ppc_rom.bin \
video.x openbios-sparc32 pxe-ne2k_pci.bin \
@@ -150,7 +151,7 @@
# generate a binary distribution
tarbin:
- ( cd / ; tar zcvf ~/qemu-$(VERSION)-i386.tar.gz \
+ ( cd / ; tar zcvf ~/qemu-$(VERSION)-$(ARCH).tar.gz \
$(bindir)/qemu \
$(bindir)/qemu-system-ppc \
$(bindir)/qemu-system-ppc64 \
@@ -162,6 +163,8 @@
$(bindir)/qemu-system-mips64 \
$(bindir)/qemu-system-mips64el \
$(bindir)/qemu-system-arm \
+ $(bindir)/qemu-system-m68k \
+ $(bindir)/qemu-system-sh4 \
$(bindir)/qemu-i386 \
$(bindir)/qemu-arm \
$(bindir)/qemu-armeb \
@@ -170,7 +173,13 @@
$(bindir)/qemu-ppc64 \
$(bindir)/qemu-mips \
$(bindir)/qemu-mipsel \
+ $(bindir)/qemu-mipsn32 \
+ $(bindir)/qemu-mipsn32el \
+ $(bindir)/qemu-mips64 \
+ $(bindir)/qemu-mips64el \
$(bindir)/qemu-alpha \
+ $(bindir)/qemu-m68k \
+ $(bindir)/qemu-sh4 \
$(bindir)/qemu-img \
$(datadir)/bios.bin \
$(datadir)/vgabios.bin \
Modified: trunk/src/host/qemu-neo1973/Makefile.target
===================================================================
--- trunk/src/host/qemu-neo1973/Makefile.target 2007-10-29 20:40:05 UTC (rev 3302)
+++ trunk/src/host/qemu-neo1973/Makefile.target 2007-10-29 21:14:04 UTC (rev 3303)
@@ -4,12 +4,18 @@
ifeq ($(TARGET_ARCH), x86_64)
TARGET_BASE_ARCH:=i386
endif
+ifeq ($(TARGET_ARCH), mipsn32)
+TARGET_BASE_ARCH:=mips
+endif
ifeq ($(TARGET_ARCH), mips64)
TARGET_BASE_ARCH:=mips
endif
ifeq ($(TARGET_ARCH), ppc64)
TARGET_BASE_ARCH:=ppc
endif
+ifeq ($(TARGET_ARCH), ppc64h)
+TARGET_BASE_ARCH:=ppc
+endif
ifeq ($(TARGET_ARCH), ppcemb)
TARGET_BASE_ARCH:=ppc
endif
@@ -18,15 +24,18 @@
endif
TARGET_PATH=$(SRC_PATH)/target-$(TARGET_BASE_ARCH)
VPATH=$(SRC_PATH):$(TARGET_PATH):$(SRC_PATH)/hw:$(SRC_PATH)/audio
-CPPFLAGS=-I. -I.. -I$(TARGET_PATH) -I$(SRC_PATH)
+CPPFLAGS=-I. -I.. -I$(TARGET_PATH) -I$(SRC_PATH) -MMD -MP
ifdef CONFIG_DARWIN_USER
VPATH+=:$(SRC_PATH)/darwin-user
CPPFLAGS+=-I$(SRC_PATH)/darwin-user -I$(SRC_PATH)/darwin-user/$(TARGET_ARCH)
endif
ifdef CONFIG_LINUX_USER
VPATH+=:$(SRC_PATH)/linux-user
-CPPFLAGS+=-I$(SRC_PATH)/linux-user -I$(SRC_PATH)/linux-user/$(TARGET_ARCH)
+ifndef TARGET_ABI_DIR
+ TARGET_ABI_DIR=$(TARGET_ARCH)
endif
+CPPFLAGS+=-I$(SRC_PATH)/linux-user -I$(SRC_PATH)/linux-user/$(TARGET_ABI_DIR)
+endif
BASE_CFLAGS=
BASE_LDFLAGS=
#CFLAGS+=-Werror
@@ -50,11 +59,21 @@
TARGET_ARCH2=mipsel
endif
endif
+ifeq ($(TARGET_ARCH),mipsn32)
+ ifneq ($(TARGET_WORDS_BIGENDIAN),yes)
+ TARGET_ARCH2=mipsn32el
+ endif
+endif
ifeq ($(TARGET_ARCH),mips64)
ifneq ($(TARGET_WORDS_BIGENDIAN),yes)
TARGET_ARCH2=mips64el
endif
endif
+ifeq ($(TARGET_ARCH),sparc64)
+ ifeq ($(TARGET_ABI_DIR),sparc)
+ TARGET_ARCH2=sparc32plus
+ endif
+endif
QEMU_USER=qemu-$(TARGET_ARCH2)
# system emulator name
ifdef CONFIG_SOFTMMU
@@ -246,6 +265,10 @@
ifdef TARGET_HAS_BFLT
OBJS+= flatload.o
endif
+ifdef TARGET_HAS_ELFLOAD32
+OBJS+= elfload32.o
+elfload32.o: elfload.c
+endif
ifeq ($(TARGET_ARCH), i386)
OBJS+= vm86.o
@@ -269,7 +292,7 @@
# cpu emulator library
LIBOBJS=exec.o kqemu.o translate-op.o translate-all.o cpu-exec.o\
- translate.o op.o
+ translate.o op.o host-utils.o
ifdef CONFIG_SOFTFLOAT
LIBOBJS+=fpu/softfloat.o
else
@@ -316,6 +339,15 @@
LIBOBJS+= op_helper.o helper.o alpha_palcode.o
endif
+ifeq ($(TARGET_BASE_ARCH), cris)
+LIBOBJS+= op_helper.o helper.o
+LIBOBJS+= cris-dis.o
+
+ifndef CONFIG_USER_ONLY
+LIBOBJS+= mmu.o
+endif
+endif
+
# NOTE: the disassembler code is only needed for debugging
LIBOBJS+=disas.o
ifeq ($(findstring i386, $(TARGET_ARCH) $(ARCH)),i386)
@@ -369,7 +401,6 @@
# 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+=host-utils.o
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
@@ -446,20 +477,36 @@
CPPFLAGS += -DHAS_AUDIO -DHAS_AUDIO_CHOICE
endif
ifeq ($(TARGET_BASE_ARCH), ppc)
-VL_OBJS+= ppc.o ide.o pckbd.o ps2.o vga.o $(SOUND_HW) dma.o $(AUDIODRV)
-VL_OBJS+= mc146818rtc.o serial.o i8259.o i8254.o fdc.o m48t59.o pflash_cfi02.o
-VL_OBJS+= ppc_prep.o ppc_chrp.o cuda.o adb.o openpic.o heathrow_pic.o
-VL_OBJS+= grackle_pci.o prep_pci.o unin_pci.o ppc405_uc.o ppc405_boards.o
CPPFLAGS += -DHAS_AUDIO -DHAS_AUDIO_CHOICE
+# shared objects
+VL_OBJS+= ppc.o ide.o vga.o $(SOUND_HW) dma.o openpic.o $(AUDIODRV)
+# 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
+# Mac shared devices
+VL_OBJS+= macio.o cuda.o adb.o mac_nvram.o mac_dbdma.o
+# OldWorld PowerMac
+VL_OBJS+= heathrow_pic.o grackle_pci.o ppc_oldworld.o
+# NewWorld PowerMac
+VL_OBJS+= unin_pci.o ppc_chrp.o
+# PowerPC 4xx boards
+VL_OBJS+= pflash_cfi02.o ppc4xx_devs.o ppc405_uc.o ppc405_boards.o
endif
ifeq ($(TARGET_BASE_ARCH), mips)
-VL_OBJS+= mips_r4k.o mips_malta.o mips_pica61.o
+VL_OBJS+= mips_r4k.o mips_malta.o mips_pica61.o mips_mipssim.o
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+= mipsnet.o
CPPFLAGS += -DHAS_AUDIO
endif
+ifeq ($(TARGET_BASE_ARCH), cris)
+VL_OBJS+= etraxfs.o
+VL_OBJS+= ptimer.o
+VL_OBJS+= etraxfs_timer.o
+VL_OBJS+= etraxfs_ser.o
+endif
ifeq ($(TARGET_BASE_ARCH), sparc)
ifeq ($(TARGET_ARCH), sparc64)
VL_OBJS+= sun4u.o ide.o pckbd.o ps2.o vga.o apb_pci.o
@@ -479,15 +526,17 @@
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 $(AUDIODRV) wm8750.o wm8753.o
+VL_OBJS+= spitz.o ads7846.o ide.o serial.o nand.o ecc.o
+VL_OBJS+= $(AUDIODRV) 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
VL_OBJS+= $(GSM_OBJS) modem.o
-VL_OBJS+= omap.o omap_lcdc.o omap1_clk.o omap_mmc.o palm.o
+VL_OBJS+= omap.o omap_lcdc.o omap1_clk.o omap_mmc.o palm.o tsc210x.o
CPPFLAGS+= -DHAS_AUDIO $(GSM_CPPFLAGS)
endif
ifeq ($(TARGET_BASE_ARCH), sh4)
-VL_OBJS+= shix.o sh7750.o sh7750_regnames.o tc58128.o
+VL_OBJS+= shix.o r2d.o sh7750.o sh7750_regnames.o tc58128.o
+VL_OBJS+= sh_timer.o ptimer.o sh_serial.o sh_intc.o
endif
ifeq ($(TARGET_BASE_ARCH), m68k)
VL_OBJS+= an5206.o mcf5206.o ptimer.o mcf_uart.o mcf_intc.o mcf5208.o mcf_fec.o
@@ -615,58 +664,6 @@
signal.o: signal.c
$(CC) $(HELPER_CFLAGS) $(CPPFLAGS) $(BASE_CFLAGS) -c -o $@ $<
-vga.o: pixel_ops.h
-
-tcx.o: pixel_ops.h
-
-ifeq ($(TARGET_BASE_ARCH), i386)
-op.o: op.c opreg_template.h ops_template.h ops_template_mem.h ops_mem.h ops_sse.h
-endif
-
-ifeq ($(TARGET_ARCH), arm)
-op.o: op.c op_template.h
-pl110.o: pl110_template.h
-endif
-
-ifeq ($(TARGET_BASE_ARCH), sparc)
-helper.o: cpu.h exec-all.h
-op.o: op.c op_template.h op_mem.h fop_template.h fbranch_template.h exec.h cpu.h
-op_helper.o: exec.h softmmu_template.h cpu.h
-translate.o: cpu.h exec-all.h disas.h
-endif
-
-ifeq ($(TARGET_BASE_ARCH), ppc)
-op.o: op.c op_template.h op_mem.h
-op_helper.o: op_helper_mem.h
-translate.o: translate.c translate_init.c
-endif
-
-ifeq ($(TARGET_BASE_ARCH), mips)
-helper.o: cpu.h exec-all.h
-op.o: op_template.c fop_template.c op_mem.c exec.h cpu.h
-op_helper.o: op_helper_mem.c exec.h softmmu_template.h cpu.h
-translate.o: translate_init.c exec-all.h disas.h
-endif
-
-loader.o: loader.c elf_ops.h
-
-ifeq ($(TARGET_ARCH), sh4)
-op.o: op.c op_mem.c cpu.h
-op_helper.o: op_helper.c exec.h cpu.h
-helper.o: helper.c exec.h cpu.h
-sh7750.o: sh7750.c sh7750_regs.h sh7750_regnames.h cpu.h
-shix.o: shix.c sh7750_regs.h sh7750_regnames.h
-sh7750_regnames.o: sh7750_regnames.c sh7750_regnames.h sh7750_regs.h
-tc58128.o: tc58128.c
-endif
-
-ifeq ($(TARGET_BASE_ARCH), alpha)
-op.o: op.c op_template.h op_mem.h
-op_helper.o: op_helper_mem.h
-endif
-
-$(OBJS) $(LIBOBJS) $(VL_OBJS): config.h ../config-host.h
-
%.o: %.c
$(CC) $(CFLAGS) $(CPPFLAGS) $(BASE_CFLAGS) -c -o $@ $<
@@ -674,7 +671,8 @@
$(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 slirp/*.o fpu/*.o
+ rm -f *.d */*.d
install: all
ifneq ($(PROGS),)
@@ -690,3 +688,6 @@
fmodaudio.o alsaaudio.o mixeng.o sb16.o es1370.o gus.o adlib.o: \
CFLAGS := $(CFLAGS) -Wall -Werror -W -Wsign-compare
endif
+
+# Include automatically generated dependency files
+-include $(wildcard *.d */*.d)
Modified: trunk/src/host/qemu-neo1973/block-raw.c
===================================================================
--- trunk/src/host/qemu-neo1973/block-raw.c 2007-10-29 20:40:05 UTC (rev 3302)
+++ trunk/src/host/qemu-neo1973/block-raw.c 2007-10-29 21:14:04 UTC (rev 3303)
@@ -151,7 +151,8 @@
if (lseek(s->fd, offset, SEEK_SET) == (off_t)-1) {
++(s->lseek_err_cnt);
if(s->lseek_err_cnt <= 10) {
- DEBUG_BLOCK_PRINT("raw_pread(%d:%s, %lld, %p, %d) [%lld] lseek failed : %d = %s\n",
+ DEBUG_BLOCK_PRINT("raw_pread(%d:%s, %" PRId64 ", %p, %d) [%" PRId64
+ "] lseek failed : %d = %s\n",
s->fd, bs->filename, offset, buf, count,
bs->total_sectors, errno, strerror(errno));
}
@@ -163,7 +164,8 @@
if (ret == count)
goto label__raw_read__success;
- DEBUG_BLOCK_PRINT("raw_pread(%d:%s, %lld, %p, %d) [%lld] read failed %d : %d = %s\n",
+ DEBUG_BLOCK_PRINT("raw_pread(%d:%s, %" PRId64 ", %p, %d) [%" PRId64
+ "] read failed %d : %d = %s\n",
s->fd, bs->filename, offset, buf, count,
bs->total_sectors, ret, errno, strerror(errno));
@@ -178,7 +180,8 @@
if (ret == count)
goto label__raw_read__success;
- DEBUG_BLOCK_PRINT("raw_pread(%d:%s, %lld, %p, %d) [%lld] retry read failed %d : %d = %s\n",
+ DEBUG_BLOCK_PRINT("raw_pread(%d:%s, %" PRId64 ", %p, %d) [%" PRId64
+ "] retry read failed %d : %d = %s\n",
s->fd, bs->filename, offset, buf, count,
bs->total_sectors, ret, errno, strerror(errno));
}
@@ -201,7 +204,8 @@
if (lseek(s->fd, offset, SEEK_SET) == (off_t)-1) {
++(s->lseek_err_cnt);
if(s->lseek_err_cnt) {
- DEBUG_BLOCK_PRINT("raw_pwrite(%d:%s, %lld, %p, %d) [%lld] lseek failed : %d = %s\n",
+ DEBUG_BLOCK_PRINT("raw_pwrite(%d:%s, %" PRId64 ", %p, %d) [%"
+ PRId64 "] lseek failed : %d = %s\n",
s->fd, bs->filename, offset, buf, count,
bs->total_sectors, errno, strerror(errno));
}
@@ -213,7 +217,8 @@
if (ret == count)
goto label__raw_write__success;
- DEBUG_BLOCK_PRINT("raw_pwrite(%d:%s, %lld, %p, %d) [%lld] write failed %d : %d = %s\n",
+ DEBUG_BLOCK_PRINT("raw_pwrite(%d:%s, %" PRId64 ", %p, %d) [%" PRId64
+ "] write failed %d : %d = %s\n",
s->fd, bs->filename, offset, buf, count,
bs->total_sectors, ret, errno, strerror(errno));
@@ -1169,7 +1174,7 @@
BDRVRawState *s = bs->opaque;
LARGE_INTEGER l;
ULARGE_INTEGER available, total, total_free;
- DISK_GEOMETRY dg;
+ DISK_GEOMETRY_EX dg;
DWORD count;
BOOL status;
@@ -1185,11 +1190,10 @@
l.QuadPart = total.QuadPart;
break;
case FTYPE_HARDDISK:
- status = DeviceIoControl(s->hfile, IOCTL_DISK_GET_DRIVE_GEOMETRY,
+ status = DeviceIoControl(s->hfile, IOCTL_DISK_GET_DRIVE_GEOMETRY_EX,
NULL, 0, &dg, sizeof(dg), &count, NULL);
- if (status != FALSE) {
- l.QuadPart = dg.Cylinders.QuadPart * dg.TracksPerCylinder
- * dg.SectorsPerTrack * dg.BytesPerSector;
+ if (status != 0) {
+ l = dg.DiskSize;
}
break;
default:
Modified: trunk/src/host/qemu-neo1973/block-vmdk.c
===================================================================
--- trunk/src/host/qemu-neo1973/block-vmdk.c 2007-10-29 20:40:05 UTC (rev 3302)
+++ trunk/src/host/qemu-neo1973/block-vmdk.c 2007-10-29 21:14:04 UTC (rev 3303)
@@ -659,7 +659,8 @@
if (sector_num > bs->total_sectors) {
fprintf(stderr,
- "(VMDK) Wrong offset: sector_num=0x%llx total_sectors=0x%llx\n",
+ "(VMDK) Wrong offset: sector_num=0x%" PRIx64
+ " total_sectors=0x%" PRIx64 "\n",
sector_num, bs->total_sectors);
return -1;
}
Modified: trunk/src/host/qemu-neo1973/block-vvfat.c
===================================================================
--- trunk/src/host/qemu-neo1973/block-vvfat.c 2007-10-29 20:40:05 UTC (rev 3302)
+++ trunk/src/host/qemu-neo1973/block-vvfat.c 2007-10-29 21:14:04 UTC (rev 3303)
@@ -242,21 +242,25 @@
uint8_t magic[2];
} __attribute__((packed)) bootsector_t;
+typedef struct {
+ uint8_t head;
+ uint8_t sector;
+ uint8_t cylinder;
+} mbr_chs_t;
+
typedef struct partition_t {
uint8_t attributes; /* 0x80 = bootable */
- uint8_t start_head;
- uint8_t start_sector;
- uint8_t start_cylinder;
- uint8_t fs_type; /* 0x1 = FAT12, 0x6 = FAT16, 0xb = FAT32 */
- uint8_t end_head;
- uint8_t end_sector;
- uint8_t end_cylinder;
+ mbr_chs_t start_CHS;
+ uint8_t fs_type; /* 0x1 = FAT12, 0x6 = FAT16, 0xe = FAT16_LBA, 0xb = FAT32, 0xc = FAT32_LBA */
+ mbr_chs_t end_CHS;
uint32_t start_sector_long;
- uint32_t end_sector_long;
+ uint32_t length_sector_long;
} __attribute__((packed)) partition_t;
typedef struct mbr_t {
- uint8_t ignored[0x1be];
+ uint8_t ignored[0x1b8];
+ uint32_t nt_id;
+ uint8_t ignored2[2];
partition_t partition[4];
uint8_t magic[2];
} __attribute__((packed)) mbr_t;
@@ -350,26 +354,57 @@
int downcase_short_names;
} BDRVVVFATState;
+/* take the sector position spos and convert it to Cylinder/Head/Sector position
+ * if the position is outside the specified geometry, fill maximum value for CHS
+ * and return 1 to signal overflow.
+ */
+static int sector2CHS(BlockDriverState* bs, mbr_chs_t * chs, int spos){
+ int head,sector;
+ sector = spos % (bs->secs); spos/= bs->secs;
+ head = spos % (bs->heads); spos/= bs->heads;
+ if(spos >= bs->cyls){
+ /* Overflow,
+ it happens if 32bit sector positions are used, while CHS is only 24bit.
+ Windows/Dos is said to take 1023/255/63 as nonrepresentable CHS */
+ chs->head = 0xFF;
+ chs->sector = 0xFF;
+ chs->cylinder = 0xFF;
+ return 1;
+ }
+ chs->head = (uint8_t)head;
+ chs->sector = (uint8_t)( (sector+1) | ((spos>>8)<<6) );
+ chs->cylinder = (uint8_t)spos;
+ return 0;
+}
static void init_mbr(BDRVVVFATState* s)
{
/* TODO: if the files mbr.img and bootsect.img exist, use them */
mbr_t* real_mbr=(mbr_t*)s->first_sectors;
partition_t* partition=&(real_mbr->partition[0]);
+ int lba;
memset(s->first_sectors,0,512);
+ /* Win NT Disk Signature */
+ real_mbr->nt_id= cpu_to_le32(0xbe1afdfa);
+
partition->attributes=0x80; /* bootable */
- partition->start_head=1;
- partition->start_sector=1;
- partition->start_cylinder=0;
+
+ /* LBA is used when partition is outside the CHS geometry */
+ lba = sector2CHS(s->bs, &partition->start_CHS, s->first_sectors_number-1);
+ lba|= sector2CHS(s->bs, &partition->end_CHS, s->sector_count);
+
+ /*LBA partitions are identified only by start/length_sector_long not by CHS*/
+ partition->start_sector_long =cpu_to_le32(s->first_sectors_number-1);
+ partition->length_sector_long=cpu_to_le32(s->sector_count - s->first_sectors_number+1);
+
/* FAT12/FAT16/FAT32 */
- partition->fs_type=(s->fat_type==12?0x1:s->fat_type==16?0x6:0xb);
- partition->end_head=s->bs->heads-1;
- partition->end_sector=0xff; /* end sector & upper 2 bits of cylinder */;
- partition->end_cylinder=0xff; /* lower 8 bits of end cylinder */;
- partition->start_sector_long=cpu_to_le32(s->bs->secs);
- partition->end_sector_long=cpu_to_le32(s->sector_count);
+ /* DOS uses different types when partition is LBA,
+ probably to prevent older versions from using CHS on them */
+ partition->fs_type= s->fat_type==12 ? 0x1:
+ s->fat_type==16 ? (lba?0xe:0x06):
+ /*fat_tyoe==32*/ (lba?0xc:0x0b);
real_mbr->magic[0]=0x55; real_mbr->magic[1]=0xaa;
}
@@ -973,10 +1008,9 @@
s->fat_type=16;
/* LATER TODO: if FAT32, adjust */
- s->sector_count=0xec04f;
s->sectors_per_cluster=0x10;
- /* LATER TODO: this could be wrong for FAT32 */
- bs->cyls=1023; bs->heads=15; bs->secs=63;
+ /* 504MB disk*/
+ bs->cyls=1024; bs->heads=16; bs->secs=63;
s->current_cluster=0xffffffff;
@@ -991,12 +1025,6 @@
if (!strstart(dirname, "fat:", NULL))
return -1;
- if (strstr(dirname, ":rw:")) {
- if (enable_write_target(s))
- return -1;
- bs->read_only = 0;
- }
-
if (strstr(dirname, ":floppy:")) {
floppy = 1;
s->fat_type = 12;
@@ -1005,6 +1033,8 @@
bs->cyls = 80; bs->heads = 2; bs->secs = 36;
}
+ s->sector_count=bs->cyls*bs->heads*bs->secs;
+
if (strstr(dirname, ":32:")) {
fprintf(stderr, "Big fat greek warning: FAT32 has not been tested. You are welcome to do so!\n");
s->fat_type = 32;
@@ -1015,6 +1045,12 @@
s->sector_count=2880;
}
+ if (strstr(dirname, ":rw:")) {
+ if (enable_write_target(s))
+ return -1;
+ bs->read_only = 0;
+ }
+
i = strrchr(dirname, ':') - dirname;
assert(i >= 3);
if (dirname[i-2] == ':' && isalpha(dirname[i-1]))
@@ -1024,11 +1060,12 @@
dirname += i+1;
bs->total_sectors=bs->cyls*bs->heads*bs->secs;
- if (s->sector_count > bs->total_sectors)
- s->sector_count = bs->total_sectors;
+
if(init_directories(s, dirname))
return -1;
+ s->sector_count = s->faked_sectors + s->sectors_per_cluster*s->cluster_count;
+
if(s->first_sectors_number==0x40)
init_mbr(s);
Modified: trunk/src/host/qemu-neo1973/configure
===================================================================
--- trunk/src/host/qemu-neo1973/configure 2007-10-29 20:40:05 UTC (rev 3302)
+++ trunk/src/host/qemu-neo1973/configure 2007-10-29 21:14:04 UTC (rev 3303)
@@ -53,6 +53,9 @@
mips64)
cpu="mips64"
;;
+ cris)
+ cpu="cris"
+ ;;
s390*)
cpu="s390"
;;
@@ -501,11 +504,11 @@
if test -z "$target_list" ; then
# these targets are portable
if [ "$softmmu" = "yes" ] ; then
- target_list="i386-softmmu ppc-softmmu sparc-softmmu x86_64-softmmu mips-softmmu mipsel-softmmu mips64-softmmu mips64el-softmmu arm-softmmu ppc64-softmmu ppcemb-softmmu m68k-softmmu"
+ target_list="i386-softmmu sparc-softmmu x86_64-softmmu mips-softmmu mipsel-softmmu mips64-softmmu mips64el-softmmu arm-softmmu ppc-softmmu ppcemb-softmmu ppc64-softmmu m68k-softmmu sh4-softmmu cris-softmmu"
fi
# the following are Linux specific
if [ "$linux_user" = "yes" ] ; then
- target_list="i386-linux-user arm-linux-user armeb-linux-user sparc-linux-user ppc-linux-user mips-linux-user mipsel-linux-user m68k-linux-user alpha-linux-user $target_list"
+ target_list="i386-linux-user arm-linux-user armeb-linux-user sparc-linux-user sparc64-linux-user sparc32plus-linux-user mips-linux-user mipsel-linux-user m68k-linux-user alpha-linux-user sh4-linux-user ppc-linux-user ppcemb-linux-user ppc64-linux-user ppc64abi32-linux-user x86_64-linux-user cris-linux-user $target_list"
fi
# the following are Darwin specific
if [ "$darwin_user" = "yes" ] ; then
@@ -826,6 +829,9 @@
elif test "$cpu" = "mips64" ; then
echo "ARCH=mips64" >> $config_mak
echo "#define HOST_MIPS64 1" >> $config_h
+elif test "$cpu" = "cris" ; then
+ echo "ARCH=cris" >> $config_mak
+ echo "#define HOST_CRIS 1" >> $config_h
elif test "$cpu" = "s390" ; then
echo "ARCH=s390" >> $config_mak
echo "#define HOST_S390 1" >> $config_h
@@ -967,6 +973,12 @@
echo "#define INTERNAL_MODEM \"gnokiigsm\"" >> $config_h
fi
+if test `expr "$target_list" : ".*softmmu.*"` != 0 ; then
+ tools="raw2flash\$(EXESUF) flash2raw\$(EXESUF) $tools"
+ tools="qemu-img\$(EXESUF) $tools"
+fi
+echo "TOOLS=$tools" >> $config_mak
+
test -f ${config_h}~ && cmp -s $config_h ${config_h}~ && mv ${config_h}~ $config_h
for target in $target_list; do
@@ -978,10 +990,14 @@
[ "$target_cpu" = "armeb" ] && target_bigendian=yes
[ "$target_cpu" = "sparc" ] && target_bigendian=yes
[ "$target_cpu" = "sparc64" ] && target_bigendian=yes
+[ "$target_cpu" = "sparc32plus" ] && target_bigendian=yes
[ "$target_cpu" = "ppc" ] && target_bigendian=yes
+[ "$target_cpu" = "ppcemb" ] && target_bigendian=yes
[ "$target_cpu" = "ppc64" ] && target_bigendian=yes
-[ "$target_cpu" = "ppcemb" ] && target_bigendian=yes
+[ "$target_cpu" = "ppc64abi32" ] && target_bigendian=yes
+[ "$target_cpu" = "ppc64h" ] && target_bigendian=yes
[ "$target_cpu" = "mips" ] && target_bigendian=yes
+[ "$target_cpu" = "mipsn32" ] && target_bigendian=yes
[ "$target_cpu" = "mips64" ] && target_bigendian=yes
[ "$target_cpu" = "sh4eb" ] && target_bigendian=yes
[ "$target_cpu" = "m68k" ] && target_bigendian=yes
@@ -1046,6 +1062,7 @@
echo "#include \"../config-host.h\"" >> $config_h
bflt="no"
+elfload32="no"
interp_prefix1=`echo "$interp_prefix" | sed "s/%M/$target_cpu/g"`
echo "#define CONFIG_QEMU_PREFIX \"$interp_prefix1\"" >> $config_h
@@ -1070,20 +1087,44 @@
echo "#define TARGET_ARCH \"sparc64\"" >> $config_h
echo "#define TARGET_SPARC 1" >> $config_h
echo "#define TARGET_SPARC64 1" >> $config_h
+ elfload32="yes"
+elif test "$target_cpu" = "sparc32plus" ; then
+ echo "TARGET_ARCH=sparc64" >> $config_mak
+ echo "TARGET_ABI_DIR=sparc" >> $config_mak
+ echo "#define TARGET_ARCH \"sparc64\"" >> $config_h
+ echo "#define TARGET_SPARC 1" >> $config_h
+ echo "#define TARGET_SPARC64 1" >> $config_h
+ echo "#define TARGET_ABI32 1" >> $config_h
elif test "$target_cpu" = "ppc" ; then
echo "TARGET_ARCH=ppc" >> $config_mak
echo "#define TARGET_ARCH \"ppc\"" >> $config_h
echo "#define TARGET_PPC 1" >> $config_h
+elif test "$target_cpu" = "ppcemb" ; then
+ echo "TARGET_ARCH=ppcemb" >> $config_mak
+ echo "TARGET_ABI_DIR=ppc" >> $config_mak
+ echo "#define TARGET_ARCH \"ppcemb\"" >> $config_h
+ echo "#define TARGET_PPC 1" >> $config_h
+ echo "#define TARGET_PPCEMB 1" >> $config_h
elif test "$target_cpu" = "ppc64" ; then
echo "TARGET_ARCH=ppc64" >> $config_mak
echo "#define TARGET_ARCH \"ppc64\"" >> $config_h
+ echo "TARGET_ABI_DIR=ppc" >> $config_mak
echo "#define TARGET_PPC 1" >> $config_h
echo "#define TARGET_PPC64 1" >> $config_h
-elif test "$target_cpu" = "ppcemb" ; then
- echo "TARGET_ARCH=ppcemb" >> $config_mak
- echo "#define TARGET_ARCH \"ppcemb\"" >> $config_h
+elif test "$target_cpu" = "ppc64abi32" ; then
+ echo "TARGET_ARCH=ppc64" >> $config_mak
+ echo "#define TARGET_ARCH \"ppc64\"" >> $config_h
+ echo "TARGET_ABI_DIR=ppc" >> $config_mak
echo "#define TARGET_PPC 1" >> $config_h
- echo "#define TARGET_PPCEMB 1" >> $config_h
+ echo "#define TARGET_PPC64 1" >> $config_h
+ echo "#define TARGET_ABI32 1" >> $config_h
+elif test "$target_cpu" = "ppc64h" ; then
+ echo "TARGET_ARCH=ppc64h" >> $config_mak
+ echo "#define TARGET_ARCH \"ppc64h\"" >> $config_h
+ echo "TARGET_ABI_DIR=ppc" >> $config_mak
+ echo "#define TARGET_PPC 1" >> $config_h
+ echo "#define TARGET_PPC64 1" >> $config_h
+ echo "#define TARGET_PPC64H 1" >> $config_h
elif test "$target_cpu" = "x86_64" ; then
echo "TARGET_ARCH=x86_64" >> $config_mak
echo "#define TARGET_ARCH \"x86_64\"" >> $config_h
@@ -1096,13 +1137,20 @@
echo "TARGET_ARCH=mips" >> $config_mak
echo "#define TARGET_ARCH \"mips\"" >> $config_h
echo "#define TARGET_MIPS 1" >> $config_h
- echo "CONFIG_SOFTFLOAT=yes" >> $config_mak
- echo "#define CONFIG_SOFTFLOAT 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
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
+elif test "$target_cpu" = "cris" ; then
+ echo "TARGET_ARCH=cris" >> $config_mak
+ echo "#define TARGET_ARCH \"cris\"" >> $config_h
+ echo "#define TARGET_CRIS 1" >> $config_h
echo "CONFIG_SOFTFLOAT=yes" >> $config_mak
echo "#define CONFIG_SOFTFLOAT 1" >> $config_h
elif test "$target_cpu" = "sh4" -o "$target_cpu" = "sh4eb" ; then
@@ -1144,7 +1192,7 @@
echo "#define CONFIG_DARWIN_USER 1" >> $config_h
fi
-if test "$target_cpu" = "arm" -o "$target_cpu" = "armeb" -o "$target_cpu" = "sparc" -o "$target_cpu" = "sparc64" -o "$target_cpu" = "m68k"; then
+if test "$target_cpu" = "arm" -o "$target_cpu" = "armeb" -o "$target_cpu" = "sparc" -o "$target_cpu" = "sparc64" -o "$target_cpu" = "sparc32plus" -o "$target_cpu" = "m68k" -o "$target_cpu" = "mips" -o "$target_cpu" = "mipsel" -o "$target_cpu" = "mipsn32" -o "$target_cpu" = "mipsn32el" -o "$target_cpu" = "mips64" -o "$target_cpu" = "mips64el"; then
echo "CONFIG_SOFTFLOAT=yes" >> $config_mak
echo "#define CONFIG_SOFTFLOAT 1" >> $config_h
fi
@@ -1152,6 +1200,11 @@
echo "TARGET_HAS_BFLT=yes" >> $config_mak
echo "#define TARGET_HAS_BFLT 1" >> $config_h
fi
+# 32 bit ELF loader in addition to native 64 bit loader?
+if test "$target_user_only" = "yes" -a "$elfload32" = "yes"; then
+ 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
@@ -1187,8 +1240,9 @@
# build tree in object directory if source path is different from current one
if test "$source_path_used" = "yes" ; then
- DIRS="tests"
+ DIRS="tests tests/cris"
FILES="Makefile tests/Makefile"
+ FILES="$FILES tests/cris/Makefile tests/cris/.gdbinit"
for dir in $DIRS ; do
mkdir -p $dir
done
Modified: trunk/src/host/qemu-neo1973/cpu-all.h
===================================================================
--- trunk/src/host/qemu-neo1973/cpu-all.h 2007-10-29 20:40:05 UTC (rev 3302)
+++ trunk/src/host/qemu-neo1973/cpu-all.h 2007-10-29 21:14:04 UTC (rev 3303)
@@ -716,6 +716,7 @@
#define CPU_INTERRUPT_HALT 0x20 /* CPU halt wanted */
#define CPU_INTERRUPT_SMI 0x40 /* (x86 only) SMI interrupt pending */
#define CPU_INTERRUPT_DEBUG 0x80 /* Debug event occured. */
+#define CPU_INTERRUPT_VIRQ 0x100 /* virtual interrupt pending. */
void cpu_interrupt(CPUState *s, int mask);
void cpu_reset_interrupt(CPUState *env, int mask);
Modified: trunk/src/host/qemu-neo1973/cpu-defs.h
===================================================================
--- trunk/src/host/qemu-neo1973/cpu-defs.h 2007-10-29 20:40:05 UTC (rev 3302)
+++ trunk/src/host/qemu-neo1973/cpu-defs.h 2007-10-29 21:14:04 UTC (rev 3303)
@@ -112,15 +112,6 @@
target_phys_addr_t addend;
} CPUTLBEntry;
-/* Alpha has 4 different running levels */
-#if defined(TARGET_ALPHA)
-#define NB_MMU_MODES 4
-#elif defined(TARGET_PPC64H) /* PowerPC 64 with hypervisor mode support */
-#define NB_MMU_MODES 3
-#else
-#define NB_MMU_MODES 2
-#endif
-
#define CPU_COMMON \
struct TranslationBlock *current_tb; /* currently executing TB */ \
/* soft mmu support */ \
@@ -131,7 +122,7 @@
written */ \
target_ulong mem_write_vaddr; /* target virtual addr at which the \
memory was written */ \
- /* 0 = kernel, 1 = user */ \
+ /* The meaning of the MMU modes is defined in the target code. */ \
CPUTLBEntry tlb_table[NB_MMU_MODES][CPU_TLB_SIZE]; \
struct TranslationBlock *tb_jmp_cache[TB_JMP_CACHE_SIZE]; \
\
Modified: trunk/src/host/qemu-neo1973/cpu-exec.c
===================================================================
--- trunk/src/host/qemu-neo1973/cpu-exec.c 2007-10-29 20:40:05 UTC (rev 3302)
+++ trunk/src/host/qemu-neo1973/cpu-exec.c 2007-10-29 21:14:04 UTC (rev 3303)
@@ -77,7 +77,7 @@
static TranslationBlock *tb_find_slow(target_ulong pc,
target_ulong cs_base,
- unsigned int flags)
+ uint64_t flags)
{
TranslationBlock *tb, **ptb1;
int code_gen_size;
@@ -155,7 +155,7 @@
{
TranslationBlock *tb;
target_ulong cs_base, pc;
- unsigned int flags;
+ uint64_t flags;
/* we record a subset of the CPU state. It will
always be the same before a given translated block
@@ -163,6 +163,7 @@
#if defined(TARGET_I386)
flags = env->hflags;
flags |= (env->eflags & (IOPL_MASK | TF_MASK | VM_MASK));
+ flags |= env->intercept;
cs_base = env->segs[R_CS].base;
pc = cs_base + env->eip;
#elif defined(TARGET_ARM)
@@ -180,8 +181,9 @@
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 enabled . MMU no-fault . Supervisor
- flags = (env->psref << 3) | ((env->mmuregs[0] & (MMU_E | MMU_NF)) << 1)
+ // 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;
#endif
cs_base = env->npc;
@@ -208,6 +210,10 @@
flags = env->ps;
cs_base = 0;
pc = env->pc;
+#elif defined(TARGET_CRIS)
+ flags = 0;
+ cs_base = 0;
+ pc = env->pc;
#else
#error unsupported CPU
#endif
@@ -282,6 +288,7 @@
#elif defined(TARGET_PPC)
#elif defined(TARGET_MIPS)
#elif defined(TARGET_SH4)
+#elif defined(TARGET_CRIS)
/* XXXXX */
#else
#error unsupported target CPU
@@ -333,6 +340,8 @@
do_interrupt(env);
#elif defined(TARGET_ALPHA)
do_interrupt(env);
+#elif defined(TARGET_CRIS)
+ do_interrupt(env);
#elif defined(TARGET_M68K)
do_interrupt(0);
#endif
@@ -372,14 +381,18 @@
tmp_T0 = T0;
#endif
interrupt_request = env->interrupt_request;
- if (__builtin_expect(interrupt_request, 0)) {
+ if (__builtin_expect(interrupt_request, 0)
+#if defined(TARGET_I386)
+ && env->hflags & HF_GIF_MASK
+#endif
+ ) {
if (interrupt_request & CPU_INTERRUPT_DEBUG) {
env->interrupt_request &= ~CPU_INTERRUPT_DEBUG;
env->exception_index = EXCP_DEBUG;
cpu_loop_exit();
}
#if defined(TARGET_ARM) || defined(TARGET_SPARC) || defined(TARGET_MIPS) || \
- defined(TARGET_PPC) || defined(TARGET_ALPHA)
+ defined(TARGET_PPC) || defined(TARGET_ALPHA) || defined(TARGET_CRIS)
if (interrupt_request & CPU_INTERRUPT_HALT) {
env->interrupt_request &= ~CPU_INTERRUPT_HALT;
env->halted = 1;
@@ -390,6 +403,7 @@
#if defined(TARGET_I386)
if ((interrupt_request & CPU_INTERRUPT_SMI) &&
!(env->hflags & HF_SMM_MASK)) {
+ svm_check_intercept(SVM_EXIT_SMI);
env->interrupt_request &= ~CPU_INTERRUPT_SMI;
do_smm_enter();
#if defined(__sparc__) && !defined(HOST_SOLARIS)
@@ -398,10 +412,11 @@
T0 = 0;
#endif
} else if ((interrupt_request & CPU_INTERRUPT_HARD) &&
- (env->eflags & IF_MASK) &&
+ (env->eflags & IF_MASK || env->hflags & HF_HIF_MASK) &&
!(env->hflags & HF_INHIBIT_IRQ_MASK)) {
int intno;
- env->interrupt_request &= ~CPU_INTERRUPT_HARD;
+ svm_check_intercept(SVM_EXIT_INTR);
+ env->interrupt_request &= ~(CPU_INTERRUPT_HARD | CPU_INTERRUPT_VIRQ);
intno = cpu_get_pic_interrupt(env);
if (loglevel & CPU_LOG_TB_IN_ASM) {
fprintf(logfile, "Servicing hardware INT=0x%02x\n", intno);
@@ -414,6 +429,25 @@
#else
T0 = 0;
#endif
+#if !defined(CONFIG_USER_ONLY)
+ } else if ((interrupt_request & CPU_INTERRUPT_VIRQ) &&
+ (env->eflags & IF_MASK) && !(env->hflags & HF_INHIBIT_IRQ_MASK)) {
+ int intno;
+ /* FIXME: this should respect TPR */
+ env->interrupt_request &= ~CPU_INTERRUPT_VIRQ;
+ svm_check_intercept(SVM_EXIT_VINTR);
+ intno = ldl_phys(env->vm_vmcb + offsetof(struct vmcb, control.int_vector));
+ if (loglevel & CPU_LOG_TB_IN_ASM)
+ fprintf(logfile, "Servicing virtual hardware INT=0x%02x\n", intno);
+ do_interrupt(intno, 0, 0, -1, 1);
+ stl_phys(env->vm_vmcb + offsetof(struct vmcb, control.int_ctl),
+ ldl_phys(env->vm_vmcb + offsetof(struct vmcb, control.int_ctl)) & ~V_IRQ_MASK);
+#if defined(__sparc__) && !defined(HOST_SOLARIS)
+ tmp_T0 = 0;
+#else
+ T0 = 0;
+#endif
+#endif
}
#elif defined(TARGET_PPC)
#if 0
@@ -490,6 +524,11 @@
if (interrupt_request & CPU_INTERRUPT_HARD) {
do_interrupt(env);
}
+#elif defined(TARGET_CRIS)
+ if (interrupt_request & CPU_INTERRUPT_HARD) {
+ do_interrupt(env);
+ env->interrupt_request &= ~CPU_INTERRUPT_HARD;
+ }
#elif defined(TARGET_M68K)
if (interrupt_request & CPU_INTERRUPT_HARD
&& ((env->sr & SR_I) >> SR_I_SHIFT)
@@ -549,6 +588,8 @@
cpu_dump_state(env, logfile, fprintf, 0);
#elif defined(TARGET_ALPHA)
cpu_dump_state(env, logfile, fprintf, 0);
+#elif defined(TARGET_CRIS)
+ cpu_dump_state(env, logfile, fprintf, 0);
#else
#error unsupported target CPU
#endif
@@ -742,6 +783,7 @@
#elif defined(TARGET_MIPS)
#elif defined(TARGET_SH4)
#elif defined(TARGET_ALPHA)
+#elif defined(TARGET_CRIS)
/* XXXXX */
#else
#error unsupported target CPU
@@ -842,8 +884,7 @@
}
/* see if it is an MMU fault */
- ret = cpu_x86_handle_mmu_fault(env, address, is_write,
- ((env->hflags & HF_CPL_MASK) == 3), 0);
+ ret = cpu_x86_handle_mmu_fault(env, address, is_write, MMU_USER_IDX, 0);
if (ret < 0)
return 0; /* not an MMU fault */
if (ret == 0)
@@ -892,7 +933,7 @@
return 1;
}
/* see if it is an MMU fault */
- ret = cpu_arm_handle_mmu_fault(env, address, is_write, 1, 0);
+ ret = cpu_arm_handle_mmu_fault(env, address, is_write, MMU_USER_IDX, 0);
if (ret < 0)
return 0; /* not an MMU fault */
if (ret == 0)
@@ -928,7 +969,7 @@
return 1;
}
/* see if it is an MMU fault */
- ret = cpu_sparc_handle_mmu_fault(env, address, is_write, 1, 0);
+ ret = cpu_sparc_handle_mmu_fault(env, address, is_write, MMU_USER_IDX, 0);
if (ret < 0)
return 0; /* not an MMU fault */
if (ret == 0)
@@ -965,7 +1006,7 @@
}
/* see if it is an MMU fault */
- ret = cpu_ppc_handle_mmu_fault(env, address, is_write, msr_pr, 0);
+ ret = cpu_ppc_handle_mmu_fault(env, address, is_write, MMU_USER_IDX, 0);
if (ret < 0)
return 0; /* not an MMU fault */
if (ret == 0)
@@ -1014,7 +1055,7 @@
return 1;
}
/* see if it is an MMU fault */
- ret = cpu_m68k_handle_mmu_fault(env, address, is_write, 1, 0);
+ ret = cpu_m68k_handle_mmu_fault(env, address, is_write, MMU_USER_IDX, 0);
if (ret < 0)
return 0; /* not an MMU fault */
if (ret == 0)
@@ -1054,7 +1095,7 @@
}
/* see if it is an MMU fault */
- ret = cpu_mips_handle_mmu_fault(env, address, is_write, 1, 0);
+ ret = cpu_mips_handle_mmu_fault(env, address, is_write, MMU_USER_IDX, 0);
if (ret < 0)
return 0; /* not an MMU fault */
if (ret == 0)
@@ -1104,7 +1145,7 @@
}
/* see if it is an MMU fault */
- ret = cpu_sh4_handle_mmu_fault(env, address, is_write, 1, 0);
+ ret = cpu_sh4_handle_mmu_fault(env, address, is_write, MMU_USER_IDX, 0);
if (ret < 0)
return 0; /* not an MMU fault */
if (ret == 0)
@@ -1149,7 +1190,7 @@
}
/* see if it is an MMU fault */
- ret = cpu_alpha_handle_mmu_fault(env, address, is_write, 1, 0);
+ ret = cpu_alpha_handle_mmu_fault(env, address, is_write, MMU_USER_IDX, 0);
if (ret < 0)
return 0; /* not an MMU fault */
if (ret == 0)
@@ -1173,6 +1214,51 @@
/* never comes here */
return 1;
}
+#elif defined (TARGET_CRIS)
+static inline int handle_cpu_signal(unsigned long pc, unsigned long address,
+ int is_write, sigset_t *old_set,
+ void *puc)
+{
+ TranslationBlock *tb;
+ int ret;
+
+ if (cpu_single_env)
+ env = cpu_single_env; /* XXX: find a correct solution for multithread */
+#if defined(DEBUG_SIGNAL)
+ printf("qemu: SIGSEGV pc=0x%08lx address=%08lx w=%d oldset=0x%08lx\n",
+ pc, address, is_write, *(unsigned long *)old_set);
+#endif
+ /* XXX: locking issue */
+ if (is_write && page_unprotect(h2g(address), pc, puc)) {
+ return 1;
+ }
+
+ /* see if it is an MMU fault */
+ ret = cpu_cris_handle_mmu_fault(env, address, is_write, MMU_USER_IDX, 0);
+ if (ret < 0)
+ return 0; /* not an MMU fault */
+ if (ret == 0)
+ return 1; /* the MMU fault was handled without causing real CPU fault */
+
+ /* 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, puc);
+ }
+#if 0
+ printf("PF exception: NIP=0x%08x error=0x%x %p\n",
+ env->nip, env->error_code, tb);
+#endif
+ /* we restore the process signal mask as the sigreturn should
+ do it (XXX: use sigsetjmp) */
+ sigprocmask(SIG_SETMASK, old_set, NULL);
+ cpu_loop_exit();
+ /* never comes here */
+ return 1;
+}
+
#else
#error unsupported target CPU
#endif
Added: trunk/src/host/qemu-neo1973/cris-dis.c
===================================================================
--- trunk/src/host/qemu-neo1973/cris-dis.c 2007-10-29 20:40:05 UTC (rev 3302)
+++ trunk/src/host/qemu-neo1973/cris-dis.c 2007-10-29 21:14:04 UTC (rev 3303)
@@ -0,0 +1,2907 @@
+/* Disassembler code for CRIS.
+ Copyright 2000, 2001, 2002, 2004, 2005, 2006 Free Software Foundation, Inc.
+ Contributed by Axis Communications AB, Lund, Sweden.
+ Written by Hans-Peter Nilsson.
+
+ This file is part of the GNU binutils and GDB, the GNU debugger.
+
+ This program is free software; you can redistribute it and/or modify it
+ under the terms of the GNU General Public License as published by the
+ Free Software Foundation; either version 2, or (at your option) any later
+ version.
+
+ This program 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 General Public License for
+ more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston,
+ MA 02110-1301, USA. */
+
+#include "dis-asm.h"
+//#include "sysdep.h"
+#include "target-cris/opcode-cris.h"
+//#include "libiberty.h"
+
+
+#define FALSE 0
+#define TRUE 1
+#define CONST_STRNEQ(STR1,STR2) (strncmp ((STR1), (STR2), sizeof (STR2) - 1) == 0)
+
+/* cris-opc.c -- Table of opcodes for the CRIS processor.
+ Copyright 2000, 2001, 2004 Free Software Foundation, Inc.
+ Contributed by Axis Communications AB, Lund, Sweden.
+ Originally written for GAS 1.38.1 by Mikael Asker.
+ Reorganized by Hans-Peter Nilsson.
+
+This file is part of GAS, GDB and the GNU binutils.
+
+GAS, GDB, and GNU binutils is free software; you can redistribute it
+and/or modify it under the terms of the GNU General Public License as
+published by the Free Software Foundation; either version 2, or (at your
+option) any later version.
+
+GAS, GDB, and GNU binutils are distributed in the hope that they will be
+useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA 02110-1301, USA. */
+
+#ifndef NULL
+#define NULL (0)
+#endif
+
+/* This table isn't used for CRISv32 and the size of immediate operands. */
+const struct cris_spec_reg
+cris_spec_regs[] =
+{
+ {"bz", 0, 1, cris_ver_v32p, NULL},
+ {"p0", 0, 1, 0, NULL},
+ {"vr", 1, 1, 0, NULL},
+ {"p1", 1, 1, 0, NULL},
+ {"pid", 2, 1, cris_ver_v32p, NULL},
+ {"p2", 2, 1, cris_ver_v32p, NULL},
+ {"p2", 2, 1, cris_ver_warning, NULL},
+ {"srs", 3, 1, cris_ver_v32p, NULL},
+ {"p3", 3, 1, cris_ver_v32p, NULL},
+ {"p3", 3, 1, cris_ver_warning, NULL},
+ {"wz", 4, 2, cris_ver_v32p, NULL},
+ {"p4", 4, 2, 0, NULL},
+ {"ccr", 5, 2, cris_ver_v0_10, NULL},
+ {"exs", 5, 4, cris_ver_v32p, NULL},
+ {"p5", 5, 2, cris_ver_v0_10, NULL},
+ {"p5", 5, 4, cris_ver_v32p, NULL},
+ {"dcr0",6, 2, cris_ver_v0_3, NULL},
+ {"eda", 6, 4, cris_ver_v32p, NULL},
+ {"p6", 6, 2, cris_ver_v0_3, NULL},
+ {"p6", 6, 4, cris_ver_v32p, NULL},
+ {"dcr1/mof", 7, 4, cris_ver_v10p,
+ "Register `dcr1/mof' with ambiguous size specified. Guessing 4 bytes"},
+ {"dcr1/mof", 7, 2, cris_ver_v0_3,
+ "Register `dcr1/mof' with ambiguous size specified. Guessing 2 bytes"},
+ {"mof", 7, 4, cris_ver_v10p, NULL},
+ {"dcr1",7, 2, cris_ver_v0_3, NULL},
+ {"p7", 7, 4, cris_ver_v10p, NULL},
+ {"p7", 7, 2, cris_ver_v0_3, NULL},
+ {"dz", 8, 4, cris_ver_v32p, NULL},
+ {"p8", 8, 4, 0, NULL},
+ {"ibr", 9, 4, cris_ver_v0_10, NULL},
+ {"ebp", 9, 4, cris_ver_v32p, NULL},
+ {"p9", 9, 4, 0, NULL},
+ {"irp", 10, 4, cris_ver_v0_10, NULL},
+ {"erp", 10, 4, cris_ver_v32p, NULL},
+ {"p10", 10, 4, 0, NULL},
+ {"srp", 11, 4, 0, NULL},
+ {"p11", 11, 4, 0, NULL},
+ /* For disassembly use only. Accept at assembly with a warning. */
+ {"bar/dtp0", 12, 4, cris_ver_warning,
+ "Ambiguous register `bar/dtp0' specified"},
+ {"nrp", 12, 4, cris_ver_v32p, NULL},
+ {"bar", 12, 4, cris_ver_v8_10, NULL},
+ {"dtp0",12, 4, cris_ver_v0_3, NULL},
+ {"p12", 12, 4, 0, NULL},
+ /* For disassembly use only. Accept at assembly with a warning. */
+ {"dccr/dtp1",13, 4, cris_ver_warning,
+ "Ambiguous register `dccr/dtp1' specified"},
+ {"ccs", 13, 4, cris_ver_v32p, NULL},
+ {"dccr",13, 4, cris_ver_v8_10, NULL},
+ {"dtp1",13, 4, cris_ver_v0_3, NULL},
+ {"p13", 13, 4, 0, NULL},
+ {"brp", 14, 4, cris_ver_v3_10, NULL},
+ {"usp", 14, 4, cris_ver_v32p, NULL},
+ {"p14", 14, 4, cris_ver_v3p, NULL},
+ {"usp", 15, 4, cris_ver_v10, NULL},
+ {"spc", 15, 4, cris_ver_v32p, NULL},
+ {"p15", 15, 4, cris_ver_v10p, NULL},
+ {NULL, 0, 0, cris_ver_version_all, NULL}
+};
+
+/* Add version specifiers to this table when necessary.
+ The (now) regular coding of register names suggests a simpler
+ implementation. */
+const struct cris_support_reg cris_support_regs[] =
+{
+ {"s0", 0},
+ {"s1", 1},
+ {"s2", 2},
+ {"s3", 3},
+ {"s4", 4},
+ {"s5", 5},
+ {"s6", 6},
+ {"s7", 7},
+ {"s8", 8},
+ {"s9", 9},
+ {"s10", 10},
+ {"s11", 11},
+ {"s12", 12},
+ {"s13", 13},
+ {"s14", 14},
+ {"s15", 15},
+ {NULL, 0}
+};
+
+/* All CRIS opcodes are 16 bits.
+
+ - The match component is a mask saying which bits must match a
+ particular opcode in order for an instruction to be an instance
+ of that opcode.
+
+ - The args component is a string containing characters symbolically
+ matching the operands of an instruction. Used for both assembly
+ and disassembly.
+
+ Operand-matching characters:
+ [ ] , space
+ Verbatim.
+ A The string "ACR" (case-insensitive).
+ B Not really an operand. It causes a "BDAP -size,SP" prefix to be
+ output for the PUSH alias-instructions and recognizes a push-
+ prefix at disassembly. This letter isn't recognized for v32.
+ Must be followed by a R or P letter.
+ ! Non-match pattern, will not match if there's a prefix insn.
+ b Non-matching operand, used for branches with 16-bit
+ displacement. Only recognized by the disassembler.
+ c 5-bit unsigned immediate in bits <4:0>.
+ C 4-bit unsigned immediate in bits <3:0>.
+ d At assembly, optionally (as in put other cases before this one)
+ ".d" or ".D" at the start of the operands, followed by one space
+ character. At disassembly, nothing.
+ D General register in bits <15:12> and <3:0>.
+ f List of flags in bits <15:12> and <3:0>.
+ i 6-bit signed immediate in bits <5:0>.
+ I 6-bit unsigned immediate in bits <5:0>.
+ M Size modifier (B, W or D) for CLEAR instructions.
+ m Size modifier (B, W or D) in bits <5:4>
+ N A 32-bit dword, like in the difference between s and y.
+ This has no effect on bits in the opcode. Can also be expressed
+ as "[pc+]" in input.
+ n As N, but PC-relative (to the start of the instruction).
+ o [-128..127] word offset in bits <7:1> and <0>. Used by 8-bit
+ branch instructions.
+ O [-128..127] offset in bits <7:0>. Also matches a comma and a
+ general register after the expression, in bits <15:12>. Used
+ only for the BDAP prefix insn (in v32 the ADDOQ insn; same opcode).
+ P Special register in bits <15:12>.
+ p Indicates that the insn is a prefix insn. Must be first
+ character.
+ Q As O, but don't relax; force an 8-bit offset.
+ R General register in bits <15:12>.
+ r General register in bits <3:0>.
+ S Source operand in bit <10> and a prefix; a 3-operand prefix
+ without side-effect.
+ s Source operand in bits <10> and <3:0>, optionally with a
+ side-effect prefix, except [pc] (the name, not R15 as in ACR)
+ isn't allowed for v32 and higher.
+ T Support register in bits <15:12>.
+ u 4-bit (PC-relative) unsigned immediate word offset in bits <3:0>.
+ U Relaxes to either u or n, instruction is assumed LAPCQ or LAPC.
+ Not recognized at disassembly.
+ x Register-dot-modifier, for example "r5.w" in bits <15:12> and <5:4>.
+ y Like 's' but do not allow an integer at assembly.
+ Y The difference s-y; only an integer is allowed.
+ z Size modifier (B or W) in bit <4>. */
+
+
+/* Please note the order of the opcodes in this table is significant.
+ The assembler requires that all instances of the same mnemonic must
+ be consecutive. If they aren't, the assembler might not recognize
+ them, or may indicate an internal error.
+
+ The disassembler should not normally care about the order of the
+ opcodes, but will prefer an earlier alternative if the "match-score"
+ (see cris-dis.c) is computed as equal.
+
+ It should not be significant for proper execution that this table is
+ in alphabetical order, but please follow that convention for an easy
+ overview. */
+
+const struct cris_opcode
+cris_opcodes[] =
+{
+ {"abs", 0x06B0, 0x0940, "r,R", 0, SIZE_NONE, 0,
+ cris_abs_op},
+
+ {"add", 0x0600, 0x09c0, "m r,R", 0, SIZE_NONE, 0,
+ cris_reg_mode_add_sub_cmp_and_or_move_op},
+
+ {"add", 0x0A00, 0x01c0, "m s,R", 0, SIZE_FIELD, 0,
+ cris_none_reg_mode_add_sub_cmp_and_or_move_op},
+
+ {"add", 0x0A00, 0x01c0, "m S,D", 0, SIZE_NONE,
+ cris_ver_v0_10,
+ cris_none_reg_mode_add_sub_cmp_and_or_move_op},
+
+ {"add", 0x0a00, 0x05c0, "m S,R,r", 0, SIZE_NONE,
+ cris_ver_v0_10,
+ cris_three_operand_add_sub_cmp_and_or_op},
+
+ {"add", 0x0A00, 0x01c0, "m s,R", 0, SIZE_FIELD,
+ cris_ver_v32p,
+ cris_none_reg_mode_add_sub_cmp_and_or_move_op},
+
+ {"addc", 0x0570, 0x0A80, "r,R", 0, SIZE_FIX_32,
+ cris_ver_v32p,
+ cris_not_implemented_op},
+
+ {"addc", 0x09A0, 0x0250, "s,R", 0, SIZE_FIX_32,
+ cris_ver_v32p,
+ cris_not_implemented_op},
+
+ {"addi", 0x0540, 0x0A80, "x,r,A", 0, SIZE_NONE,
+ cris_ver_v32p,
+ cris_addi_op},
+
+ {"addi", 0x0500, 0x0Ac0, "x,r", 0, SIZE_NONE, 0,
+ cris_addi_op},
+
+ /* This collates after "addo", but we want to disassemble as "addoq",
+ not "addo". */
+ {"addoq", 0x0100, 0x0E00, "Q,A", 0, SIZE_NONE,
+ cris_ver_v32p,
+ cris_not_implemented_op},
+
+ {"addo", 0x0940, 0x0280, "m s,R,A", 0, SIZE_FIELD_SIGNED,
+ cris_ver_v32p,
+ cris_not_implemented_op},
+
+ /* This must be located after the insn above, lest we misinterpret
+ "addo.b -1,r0,acr" as "addo .b-1,r0,acr". FIXME: Sounds like a
+ parser bug. */
+ {"addo", 0x0100, 0x0E00, "O,A", 0, SIZE_NONE,
+ cris_ver_v32p,
+ cris_not_implemented_op},
+
+ {"addq", 0x0200, 0x0Dc0, "I,R", 0, SIZE_NONE, 0,
+ cris_quick_mode_add_sub_op},
+
+ {"adds", 0x0420, 0x0Bc0, "z r,R", 0, SIZE_NONE, 0,
+ cris_reg_mode_add_sub_cmp_and_or_move_op},
+
+ /* FIXME: SIZE_FIELD_SIGNED and all necessary changes. */
+ {"adds", 0x0820, 0x03c0, "z s,R", 0, SIZE_FIELD, 0,
+ cris_none_reg_mode_add_sub_cmp_and_or_move_op},
+
+ {"adds", 0x0820, 0x03c0, "z S,D", 0, SIZE_NONE,
+ cris_ver_v0_10,
+ cris_none_reg_mode_add_sub_cmp_and_or_move_op},
+
+ {"adds", 0x0820, 0x07c0, "z S,R,r", 0, SIZE_NONE,
+ cris_ver_v0_10,
+ cris_three_operand_add_sub_cmp_and_or_op},
+
+ {"addu", 0x0400, 0x0be0, "z r,R", 0, SIZE_NONE, 0,
+ cris_reg_mode_add_sub_cmp_and_or_move_op},
+
+ /* FIXME: SIZE_FIELD_UNSIGNED and all necessary changes. */
+ {"addu", 0x0800, 0x03e0, "z s,R", 0, SIZE_FIELD, 0,
+ cris_none_reg_mode_add_sub_cmp_and_or_move_op},
+
+ {"addu", 0x0800, 0x03e0, "z S,D", 0, SIZE_NONE,
+ cris_ver_v0_10,
+ cris_none_reg_mode_add_sub_cmp_and_or_move_op},
+
+ {"addu", 0x0800, 0x07e0, "z S,R,r", 0, SIZE_NONE,
+ cris_ver_v0_10,
+ cris_three_operand_add_sub_cmp_and_or_op},
+
+ {"and", 0x0700, 0x08C0, "m r,R", 0, SIZE_NONE, 0,
+ cris_reg_mode_add_sub_cmp_and_or_move_op},
+
+ {"and", 0x0B00, 0x00C0, "m s,R", 0, SIZE_FIELD, 0,
+ cris_none_reg_mode_add_sub_cmp_and_or_move_op},
+
+ {"and", 0x0B00, 0x00C0, "m S,D", 0, SIZE_NONE,
+ cris_ver_v0_10,
+ cris_none_reg_mode_add_sub_cmp_and_or_move_op},
+
+ {"and", 0x0B00, 0x04C0, "m S,R,r", 0, SIZE_NONE,
+ cris_ver_v0_10,
+ cris_three_operand_add_sub_cmp_and_or_op},
+
+ {"andq", 0x0300, 0x0CC0, "i,R", 0, SIZE_NONE, 0,
+ cris_quick_mode_and_cmp_move_or_op},
+
+ {"asr", 0x0780, 0x0840, "m r,R", 0, SIZE_NONE, 0,
+ cris_asr_op},
+
+ {"asrq", 0x03a0, 0x0c40, "c,R", 0, SIZE_NONE, 0,
+ cris_asrq_op},
+
+ {"ax", 0x15B0, 0xEA4F, "", 0, SIZE_NONE, 0,
+ cris_ax_ei_setf_op},
+
+ /* FIXME: Should use branch #defines. */
+ {"b", 0x0dff, 0x0200, "b", 1, SIZE_NONE, 0,
+ cris_sixteen_bit_offset_branch_op},
+
+ {"ba",
+ BA_QUICK_OPCODE,
+ 0x0F00+(0xF-CC_A)*0x1000, "o", 1, SIZE_NONE, 0,
+ cris_eight_bit_offset_branch_op},
+
+ /* Needs to come after the usual "ba o", which might be relaxed to
+ this one. */
+ {"ba", BA_DWORD_OPCODE,
+ 0xffff & (~BA_DWORD_OPCODE), "n", 0, SIZE_FIX_32,
+ cris_ver_v32p,
+ cris_none_reg_mode_jump_op},
+
+ {"bas", 0x0EBF, 0x0140, "n,P", 0, SIZE_FIX_32,
+ cris_ver_v32p,
+ cris_none_reg_mode_jump_op},
+
+ {"basc", 0x0EFF, 0x0100, "n,P", 0, SIZE_FIX_32,
+ cris_ver_v32p,
+ cris_none_reg_mode_jump_op},
+
+ {"bcc",
+ BRANCH_QUICK_OPCODE+CC_CC*0x1000,
+ 0x0f00+(0xF-CC_CC)*0x1000, "o", 1, SIZE_NONE, 0,
+ cris_eight_bit_offset_branch_op},
+
+ {"bcs",
+ BRANCH_QUICK_OPCODE+CC_CS*0x1000,
+ 0x0f00+(0xF-CC_CS)*0x1000, "o", 1, SIZE_NONE, 0,
+ cris_eight_bit_offset_branch_op},
+
+ {"bdap",
+ BDAP_INDIR_OPCODE, BDAP_INDIR_Z_BITS, "pm s,R", 0, SIZE_FIELD_SIGNED,
+ cris_ver_v0_10,
+ cris_bdap_prefix},
+
+ {"bdap",
+ BDAP_QUICK_OPCODE, BDAP_QUICK_Z_BITS, "pO", 0, SIZE_NONE,
+ cris_ver_v0_10,
+ cris_quick_mode_bdap_prefix},
+
+ {"beq",
+ BRANCH_QUICK_OPCODE+CC_EQ*0x1000,
+ 0x0f00+(0xF-CC_EQ)*0x1000, "o", 1, SIZE_NONE, 0,
+ cris_eight_bit_offset_branch_op},
+
+ /* This is deliberately put before "bext" to trump it, even though not
+ in alphabetical order, since we don't do excluding version checks
+ for v0..v10. */
+ {"bwf",
+ BRANCH_QUICK_OPCODE+CC_EXT*0x1000,
+ 0x0f00+(0xF-CC_EXT)*0x1000, "o", 1, SIZE_NONE,
+ cris_ver_v10,
+ cris_eight_bit_offset_branch_op},
+
+ {"bext",
+ BRANCH_QUICK_OPCODE+CC_EXT*0x1000,
+ 0x0f00+(0xF-CC_EXT)*0x1000, "o", 1, SIZE_NONE,
+ cris_ver_v0_3,
+ cris_eight_bit_offset_branch_op},
+
+ {"bge",
+ BRANCH_QUICK_OPCODE+CC_GE*0x1000,
+ 0x0f00+(0xF-CC_GE)*0x1000, "o", 1, SIZE_NONE, 0,
+ cris_eight_bit_offset_branch_op},
+
+ {"bgt",
+ BRANCH_QUICK_OPCODE+CC_GT*0x1000,
+ 0x0f00+(0xF-CC_GT)*0x1000, "o", 1, SIZE_NONE, 0,
+ cris_eight_bit_offset_branch_op},
+
+ {"bhi",
+ BRANCH_QUICK_OPCODE+CC_HI*0x1000,
+ 0x0f00+(0xF-CC_HI)*0x1000, "o", 1, SIZE_NONE, 0,
+ cris_eight_bit_offset_branch_op},
+
+ {"bhs",
+ BRANCH_QUICK_OPCODE+CC_HS*0x1000,
+ 0x0f00+(0xF-CC_HS)*0x1000, "o", 1, SIZE_NONE, 0,
+ cris_eight_bit_offset_branch_op},
+
+ {"biap", BIAP_OPCODE, BIAP_Z_BITS, "pm r,R", 0, SIZE_NONE,
+ cris_ver_v0_10,
+ cris_biap_prefix},
+
+ {"ble",
+ BRANCH_QUICK_OPCODE+CC_LE*0x1000,
+ 0x0f00+(0xF-CC_LE)*0x1000, "o", 1, SIZE_NONE, 0,
+ cris_eight_bit_offset_branch_op},
+
+ {"blo",
+ BRANCH_QUICK_OPCODE+CC_LO*0x1000,
+ 0x0f00+(0xF-CC_LO)*0x1000, "o", 1, SIZE_NONE, 0,
+ cris_eight_bit_offset_branch_op},
+
+ {"bls",
+ BRANCH_QUICK_OPCODE+CC_LS*0x1000,
+ 0x0f00+(0xF-CC_LS)*0x1000, "o", 1, SIZE_NONE, 0,
+ cris_eight_bit_offset_branch_op},
+
+ {"blt",
+ BRANCH_QUICK_OPCODE+CC_LT*0x1000,
+ 0x0f00+(0xF-CC_LT)*0x1000, "o", 1, SIZE_NONE, 0,
+ cris_eight_bit_offset_branch_op},
+
+ {"bmi",
+ BRANCH_QUICK_OPCODE+CC_MI*0x1000,
+ 0x0f00+(0xF-CC_MI)*0x1000, "o", 1, SIZE_NONE, 0,
+ cris_eight_bit_offset_branch_op},
+
+ {"bmod", 0x0ab0, 0x0140, "s,R", 0, SIZE_FIX_32,
+ cris_ver_sim_v0_10,
+ cris_not_implemented_op},
+
+ {"bmod", 0x0ab0, 0x0140, "S,D", 0, SIZE_NONE,
+ cris_ver_sim_v0_10,
+ cris_not_implemented_op},
+
+ {"bmod", 0x0ab0, 0x0540, "S,R,r", 0, SIZE_NONE,
+ cris_ver_sim_v0_10,
+ cris_not_implemented_op},
+
+ {"bne",
+ BRANCH_QUICK_OPCODE+CC_NE*0x1000,
+ 0x0f00+(0xF-CC_NE)*0x1000, "o", 1, SIZE_NONE, 0,
+ cris_eight_bit_offset_branch_op},
+
+ {"bound", 0x05c0, 0x0A00, "m r,R", 0, SIZE_NONE, 0,
+ cris_two_operand_bound_op},
+ /* FIXME: SIZE_FIELD_UNSIGNED and all necessary changes. */
+ {"bound", 0x09c0, 0x0200, "m s,R", 0, SIZE_FIELD,
+ cris_ver_v0_10,
+ cris_two_operand_bound_op},
+ /* FIXME: SIZE_FIELD_UNSIGNED and all necessary changes. */
+ {"bound", 0x0dcf, 0x0200, "m Y,R", 0, SIZE_FIELD, 0,
+ cris_two_operand_bound_op},
+ {"bound", 0x09c0, 0x0200, "m S,D", 0, SIZE_NONE,
+ cris_ver_v0_10,
+ cris_two_operand_bound_op},
+ {"bound", 0x09c0, 0x0600, "m S,R,r", 0, SIZE_NONE,
+ cris_ver_v0_10,
+ cris_three_operand_bound_op},
+
+ {"bpl",
+ BRANCH_QUICK_OPCODE+CC_PL*0x1000,
+ 0x0f00+(0xF-CC_PL)*0x1000, "o", 1, SIZE_NONE, 0,
+ cris_eight_bit_offset_branch_op},
+
+ {"break", 0xe930, 0x16c0, "C", 0, SIZE_NONE,
+ cris_ver_v3p,
+ cris_break_op},
+
+ {"bsb",
+ BRANCH_QUICK_OPCODE+CC_EXT*0x1000,
+ 0x0f00+(0xF-CC_EXT)*0x1000, "o", 1, SIZE_NONE,
+ cris_ver_v32p,
+ cris_eight_bit_offset_branch_op},
+
+ {"bsr", 0xBEBF, 0x4140, "n", 0, SIZE_FIX_32,
+ cris_ver_v32p,
+ cris_none_reg_mode_jump_op},
+
+ {"bsrc", 0xBEFF, 0x4100, "n", 0, SIZE_FIX_32,
+ cris_ver_v32p,
+ cris_none_reg_mode_jump_op},
+
+ {"bstore", 0x0af0, 0x0100, "s,R", 0, SIZE_FIX_32,
+ cris_ver_warning,
+ cris_not_implemented_op},
+
+ {"bstore", 0x0af0, 0x0100, "S,D", 0, SIZE_NONE,
+ cris_ver_warning,
+ cris_not_implemented_op},
+
+ {"bstore", 0x0af0, 0x0500, "S,R,r", 0, SIZE_NONE,
+ cris_ver_warning,
+ cris_not_implemented_op},
+
+ {"btst", 0x04F0, 0x0B00, "r,R", 0, SIZE_NONE, 0,
+ cris_btst_nop_op},
+ {"btstq", 0x0380, 0x0C60, "c,R", 0, SIZE_NONE, 0,
+ cris_btst_nop_op},
+
+ {"bvc",
+ BRANCH_QUICK_OPCODE+CC_VC*0x1000,
+ 0x0f00+(0xF-CC_VC)*0x1000, "o", 1, SIZE_NONE, 0,
+ cris_eight_bit_offset_branch_op},
+
+ {"bvs",
+ BRANCH_QUICK_OPCODE+CC_VS*0x1000,
+ 0x0f00+(0xF-CC_VS)*0x1000, "o", 1, SIZE_NONE, 0,
+ cris_eight_bit_offset_branch_op},
+
+ {"clear", 0x0670, 0x3980, "M r", 0, SIZE_NONE, 0,
+ cris_reg_mode_clear_op},
+
+ {"clear", 0x0A70, 0x3180, "M y", 0, SIZE_NONE, 0,
+ cris_none_reg_mode_clear_test_op},
+
+ {"clear", 0x0A70, 0x3180, "M S", 0, SIZE_NONE,
+ cris_ver_v0_10,
+ cris_none_reg_mode_clear_test_op},
+
+ {"clearf", 0x05F0, 0x0A00, "f", 0, SIZE_NONE, 0,
+ cris_clearf_di_op},
+
+ {"cmp", 0x06C0, 0x0900, "m r,R", 0, SIZE_NONE, 0,
+ cris_reg_mode_add_sub_cmp_and_or_move_op},
+
+ {"cmp", 0x0Ac0, 0x0100, "m s,R", 0, SIZE_FIELD, 0,
+ cris_none_reg_mode_add_sub_cmp_and_or_move_op},
+
+ {"cmp", 0x0Ac0, 0x0100, "m S,D", 0, SIZE_NONE,
+ cris_ver_v0_10,
+ cris_none_reg_mode_add_sub_cmp_and_or_move_op},
+
+ {"cmpq", 0x02C0, 0x0D00, "i,R", 0, SIZE_NONE, 0,
+ cris_quick_mode_and_cmp_move_or_op},
+
+ /* FIXME: SIZE_FIELD_SIGNED and all necessary changes. */
+ {"cmps", 0x08e0, 0x0300, "z s,R", 0, SIZE_FIELD, 0,
+ cris_none_reg_mode_add_sub_cmp_and_or_move_op},
+
+ {"cmps", 0x08e0, 0x0300, "z S,D", 0, SIZE_NONE,
+ cris_ver_v0_10,
+ cris_none_reg_mode_add_sub_cmp_and_or_move_op},
+
+ /* FIXME: SIZE_FIELD_UNSIGNED and all necessary changes. */
+ {"cmpu", 0x08c0, 0x0320, "z s,R" , 0, SIZE_FIELD, 0,
+ cris_none_reg_mode_add_sub_cmp_and_or_move_op},
+
+ {"cmpu", 0x08c0, 0x0320, "z S,D", 0, SIZE_NONE,
+ cris_ver_v0_10,
+ cris_none_reg_mode_add_sub_cmp_and_or_move_op},
+
+ {"di", 0x25F0, 0xDA0F, "", 0, SIZE_NONE, 0,
+ cris_clearf_di_op},
+
+ {"dip", DIP_OPCODE, DIP_Z_BITS, "ps", 0, SIZE_FIX_32,
+ cris_ver_v0_10,
+ cris_dip_prefix},
+
+ {"div", 0x0980, 0x0640, "m R,r", 0, SIZE_FIELD, 0,
+ cris_not_implemented_op},
+
+ {"dstep", 0x06f0, 0x0900, "r,R", 0, SIZE_NONE, 0,
+ cris_dstep_logshift_mstep_neg_not_op},
+
+ {"ei", 0x25B0, 0xDA4F, "", 0, SIZE_NONE, 0,
+ cris_ax_ei_setf_op},
+
+ {"fidxd", 0x0ab0, 0xf540, "[r]", 0, SIZE_NONE,
+ cris_ver_v32p,
+ cris_not_implemented_op},
+
+ {"fidxi", 0x0d30, 0xF2C0, "[r]", 0, SIZE_NONE,
+ cris_ver_v32p,
+ cris_not_implemented_op},
+
+ {"ftagd", 0x1AB0, 0xE540, "[r]", 0, SIZE_NONE,
+ cris_ver_v32p,
+ cris_not_implemented_op},
+
+ {"ftagi", 0x1D30, 0xE2C0, "[r]", 0, SIZE_NONE,
+ cris_ver_v32p,
+ cris_not_implemented_op},
+
+ {"halt", 0xF930, 0x06CF, "", 0, SIZE_NONE,
+ cris_ver_v32p,
+ cris_not_implemented_op},
+
+ {"jas", 0x09B0, 0x0640, "r,P", 0, SIZE_NONE,
+ cris_ver_v32p,
+ cris_reg_mode_jump_op},
+
+ {"jas", 0x0DBF, 0x0240, "N,P", 0, SIZE_FIX_32,
+ cris_ver_v32p,
+ cris_reg_mode_jump_op},
+
+ {"jasc", 0x0B30, 0x04C0, "r,P", 0, SIZE_NONE,
+ cris_ver_v32p,
+ cris_reg_mode_jump_op},
+
+ {"jasc", 0x0F3F, 0x00C0, "N,P", 0, SIZE_FIX_32,
+ cris_ver_v32p,
+ cris_reg_mode_jump_op},
+
+ {"jbrc", 0x69b0, 0x9640, "r", 0, SIZE_NONE,
+ cris_ver_v8_10,
+ cris_reg_mode_jump_op},
+
+ {"jbrc", 0x6930, 0x92c0, "s", 0, SIZE_FIX_32,
+ cris_ver_v8_10,
+ cris_none_reg_mode_jump_op},
+
+ {"jbrc", 0x6930, 0x92c0, "S", 0, SIZE_NONE,
+ cris_ver_v8_10,
+ cris_none_reg_mode_jump_op},
+
+ {"jir", 0xA9b0, 0x5640, "r", 0, SIZE_NONE,
+ cris_ver_v8_10,
+ cris_reg_mode_jump_op},
+
+ {"jir", 0xA930, 0x52c0, "s", 0, SIZE_FIX_32,
+ cris_ver_v8_10,
+ cris_none_reg_mode_jump_op},
+
+ {"jir", 0xA930, 0x52c0, "S", 0, SIZE_NONE,
+ cris_ver_v8_10,
+ cris_none_reg_mode_jump_op},
+
+ {"jirc", 0x29b0, 0xd640, "r", 0, SIZE_NONE,
+ cris_ver_v8_10,
+ cris_reg_mode_jump_op},
+
+ {"jirc", 0x2930, 0xd2c0, "s", 0, SIZE_FIX_32,
+ cris_ver_v8_10,
+ cris_none_reg_mode_jump_op},
+
+ {"jirc", 0x2930, 0xd2c0, "S", 0, SIZE_NONE,
+ cris_ver_v8_10,
+ cris_none_reg_mode_jump_op},
+
+ {"jsr", 0xB9b0, 0x4640, "r", 0, SIZE_NONE, 0,
+ cris_reg_mode_jump_op},
+
+ {"jsr", 0xB930, 0x42c0, "s", 0, SIZE_FIX_32,
+ cris_ver_v0_10,
+ cris_none_reg_mode_jump_op},
+
+ {"jsr", 0xBDBF, 0x4240, "N", 0, SIZE_FIX_32,
+ cris_ver_v32p,
+ cris_none_reg_mode_jump_op},
+
+ {"jsr", 0xB930, 0x42c0, "S", 0, SIZE_NONE,
+ cris_ver_v0_10,
+ cris_none_reg_mode_jump_op},
+
+ {"jsrc", 0x39b0, 0xc640, "r", 0, SIZE_NONE,
+ cris_ver_v8_10,
+ cris_reg_mode_jump_op},
+
+ {"jsrc", 0x3930, 0xc2c0, "s", 0, SIZE_FIX_32,
+ cris_ver_v8_10,
+ cris_none_reg_mode_jump_op},
+
+ {"jsrc", 0x3930, 0xc2c0, "S", 0, SIZE_NONE,
+ cris_ver_v8_10,
+ cris_none_reg_mode_jump_op},
+
+ {"jsrc", 0xBB30, 0x44C0, "r", 0, SIZE_NONE,
+ cris_ver_v32p,
+ cris_reg_mode_jump_op},
+
+ {"jsrc", 0xBF3F, 0x40C0, "N", 0, SIZE_FIX_32,
+ cris_ver_v32p,
+ cris_reg_mode_jump_op},
+
+ {"jump", 0x09b0, 0xF640, "r", 0, SIZE_NONE, 0,
+ cris_reg_mode_jump_op},
+
+ {"jump",
+ JUMP_INDIR_OPCODE, JUMP_INDIR_Z_BITS, "s", 0, SIZE_FIX_32,
+ cris_ver_v0_10,
+ cris_none_reg_mode_jump_op},
+
+ {"jump",
+ JUMP_INDIR_OPCODE, JUMP_INDIR_Z_BITS, "S", 0, SIZE_NONE,
+ cris_ver_v0_10,
+ cris_none_reg_mode_jump_op},
+
+ {"jump", 0x09F0, 0x060F, "P", 0, SIZE_NONE,
+ cris_ver_v32p,
+ cris_none_reg_mode_jump_op},
+
+ {"jump",
+ JUMP_PC_INCR_OPCODE_V32,
+ (0xffff & ~JUMP_PC_INCR_OPCODE_V32), "N", 0, SIZE_FIX_32,
+ cris_ver_v32p,
+ cris_none_reg_mode_jump_op},
+
+ {"jmpu", 0x8930, 0x72c0, "s", 0, SIZE_FIX_32,
+ cris_ver_v10,
+ cris_none_reg_mode_jump_op},
+
+ {"jmpu", 0x8930, 0x72c0, "S", 0, SIZE_NONE,
+ cris_ver_v10,
+ cris_none_reg_mode_jump_op},
+
+ {"lapc", 0x0970, 0x0680, "U,R", 0, SIZE_NONE,
+ cris_ver_v32p,
+ cris_not_implemented_op},
+
+ {"lapc", 0x0D7F, 0x0280, "dn,R", 0, SIZE_FIX_32,
+ cris_ver_v32p,
+ cris_not_implemented_op},
+
+ {"lapcq", 0x0970, 0x0680, "u,R", 0, SIZE_NONE,
+ cris_ver_v32p,
+ cris_addi_op},
+
+ {"lsl", 0x04C0, 0x0B00, "m r,R", 0, SIZE_NONE, 0,
+ cris_dstep_logshift_mstep_neg_not_op},
+
+ {"lslq", 0x03c0, 0x0C20, "c,R", 0, SIZE_NONE, 0,
+ cris_dstep_logshift_mstep_neg_not_op},
+
+ {"lsr", 0x07C0, 0x0800, "m r,R", 0, SIZE_NONE, 0,
+ cris_dstep_logshift_mstep_neg_not_op},
+
+ {"lsrq", 0x03e0, 0x0C00, "c,R", 0, SIZE_NONE, 0,
+ cris_dstep_logshift_mstep_neg_not_op},
+
+ {"lz", 0x0730, 0x08C0, "r,R", 0, SIZE_NONE,
+ cris_ver_v3p,
+ cris_not_implemented_op},
+
+ {"mcp", 0x07f0, 0x0800, "P,r", 0, SIZE_NONE,
+ cris_ver_v32p,
+ cris_not_implemented_op},
+
+ {"move", 0x0640, 0x0980, "m r,R", 0, SIZE_NONE, 0,
+ cris_reg_mode_add_sub_cmp_and_or_move_op},
+
+ {"move", 0x0A40, 0x0180, "m s,R", 0, SIZE_FIELD, 0,
+ cris_none_reg_mode_add_sub_cmp_and_or_move_op},
+
+ {"move", 0x0A40, 0x0180, "m S,D", 0, SIZE_NONE,
+ cris_ver_v0_10,
+ cris_none_reg_mode_add_sub_cmp_and_or_move_op},
+
+ {"move", 0x0630, 0x09c0, "r,P", 0, SIZE_NONE, 0,
+ cris_move_to_preg_op},
+
+ {"move", 0x0670, 0x0980, "P,r", 0, SIZE_NONE, 0,
+ cris_reg_mode_move_from_preg_op},
+
+ {"move", 0x0BC0, 0x0000, "m R,y", 0, SIZE_FIELD, 0,
+ cris_none_reg_mode_add_sub_cmp_and_or_move_op},
+
+ {"move", 0x0BC0, 0x0000, "m D,S", 0, SIZE_NONE,
+ cris_ver_v0_10,
+ cris_none_reg_mode_add_sub_cmp_and_or_move_op},
+
+ {"move",
+ MOVE_M_TO_PREG_OPCODE, MOVE_M_TO_PREG_ZBITS,
+ "s,P", 0, SIZE_SPEC_REG, 0,
+ cris_move_to_preg_op},
+
+ {"move", 0x0A30, 0x01c0, "S,P", 0, SIZE_NONE,
+ cris_ver_v0_10,
+ cris_move_to_preg_op},
+
+ {"move", 0x0A70, 0x0180, "P,y", 0, SIZE_SPEC_REG, 0,
+ cris_none_reg_mode_move_from_preg_op},
+
+ {"move", 0x0A70, 0x0180, "P,S", 0, SIZE_NONE,
+ cris_ver_v0_10,
+ cris_none_reg_mode_move_from_preg_op},
+
+ {"move", 0x0B70, 0x0480, "r,T", 0, SIZE_NONE,
+ cris_ver_v32p,
+ cris_not_implemented_op},
+
+ {"move", 0x0F70, 0x0080, "T,r", 0, SIZE_NONE,
+ cris_ver_v32p,
+ cris_not_implemented_op},
+
+ {"movem", 0x0BF0, 0x0000, "R,y", 0, SIZE_FIX_32, 0,
+ cris_move_reg_to_mem_movem_op},
+
+ {"movem", 0x0BF0, 0x0000, "D,S", 0, SIZE_NONE,
+ cris_ver_v0_10,
+ cris_move_reg_to_mem_movem_op},
+
+ {"movem", 0x0BB0, 0x0040, "s,R", 0, SIZE_FIX_32, 0,
+ cris_move_mem_to_reg_movem_op},
+
+ {"movem", 0x0BB0, 0x0040, "S,D", 0, SIZE_NONE,
+ cris_ver_v0_10,
+ cris_move_mem_to_reg_movem_op},
+
+ {"moveq", 0x0240, 0x0D80, "i,R", 0, SIZE_NONE, 0,
+ cris_quick_mode_and_cmp_move_or_op},
+
+ {"movs", 0x0460, 0x0B80, "z r,R", 0, SIZE_NONE, 0,
+ cris_reg_mode_add_sub_cmp_and_or_move_op},
+
+ /* FIXME: SIZE_FIELD_SIGNED and all necessary changes. */
+ {"movs", 0x0860, 0x0380, "z s,R", 0, SIZE_FIELD, 0,
+ cris_none_reg_mode_add_sub_cmp_and_or_move_op},
+
+ {"movs", 0x0860, 0x0380, "z S,D", 0, SIZE_NONE,
+ cris_ver_v0_10,
+ cris_none_reg_mode_add_sub_cmp_and_or_move_op},
+
+ {"movu", 0x0440, 0x0Ba0, "z r,R", 0, SIZE_NONE, 0,
+ cris_reg_mode_add_sub_cmp_and_or_move_op},
+
+ /* FIXME: SIZE_FIELD_UNSIGNED and all necessary changes. */
+ {"movu", 0x0840, 0x03a0, "z s,R", 0, SIZE_FIELD, 0,
+ cris_none_reg_mode_add_sub_cmp_and_or_move_op},
+
+ {"movu", 0x0840, 0x03a0, "z S,D", 0, SIZE_NONE,
+ cris_ver_v0_10,
+ cris_none_reg_mode_add_sub_cmp_and_or_move_op},
+
+ {"mstep", 0x07f0, 0x0800, "r,R", 0, SIZE_NONE,
+ cris_ver_v0_10,
+ cris_dstep_logshift_mstep_neg_not_op},
+
+ {"muls", 0x0d00, 0x02c0, "m r,R", 0, SIZE_NONE,
+ cris_ver_v10p,
+ cris_muls_op},
+
+ {"mulu", 0x0900, 0x06c0, "m r,R", 0, SIZE_NONE,
+ cris_ver_v10p,
+ cris_mulu_op},
+
+ {"neg", 0x0580, 0x0A40, "m r,R", 0, SIZE_NONE, 0,
+ cris_dstep_logshift_mstep_neg_not_op},
+
+ {"nop", NOP_OPCODE, NOP_Z_BITS, "", 0, SIZE_NONE,
+ cris_ver_v0_10,
+ cris_btst_nop_op},
+
+ {"nop", NOP_OPCODE_V32, NOP_Z_BITS_V32, "", 0, SIZE_NONE,
+ cris_ver_v32p,
+ cris_btst_nop_op},
+
+ {"not", 0x8770, 0x7880, "r", 0, SIZE_NONE, 0,
+ cris_dstep_logshift_mstep_neg_not_op},
+
+ {"or", 0x0740, 0x0880, "m r,R", 0, SIZE_NONE, 0,
+ cris_reg_mode_add_sub_cmp_and_or_move_op},
+
+ {"or", 0x0B40, 0x0080, "m s,R", 0, SIZE_FIELD, 0,
+ cris_none_reg_mode_add_sub_cmp_and_or_move_op},
+
+ {"or", 0x0B40, 0x0080, "m S,D", 0, SIZE_NONE,
+ cris_ver_v0_10,
+ cris_none_reg_mode_add_sub_cmp_and_or_move_op},
+
+ {"or", 0x0B40, 0x0480, "m S,R,r", 0, SIZE_NONE,
+ cris_ver_v0_10,
+ cris_three_operand_add_sub_cmp_and_or_op},
+
+ {"orq", 0x0340, 0x0C80, "i,R", 0, SIZE_NONE, 0,
+ cris_quick_mode_and_cmp_move_or_op},
+
+ {"pop", 0x0E6E, 0x0191, "!R", 0, SIZE_NONE,
+ cris_ver_v0_10,
+ cris_none_reg_mode_add_sub_cmp_and_or_move_op},
+
+ {"pop", 0x0e3e, 0x01c1, "!P", 0, SIZE_NONE,
+ cris_ver_v0_10,
+ cris_none_reg_mode_move_from_preg_op},
+
+ {"push", 0x0FEE, 0x0011, "BR", 0, SIZE_NONE,
+ cris_ver_v0_10,
+ cris_none_reg_mode_add_sub_cmp_and_or_move_op},
+
+ {"push", 0x0E7E, 0x0181, "BP", 0, SIZE_NONE,
+ cris_ver_v0_10,
+ cris_move_to_preg_op},
+
+ {"rbf", 0x3b30, 0xc0c0, "y", 0, SIZE_NONE,
+ cris_ver_v10,
+ cris_not_implemented_op},
+
+ {"rbf", 0x3b30, 0xc0c0, "S", 0, SIZE_NONE,
+ cris_ver_v10,
+ cris_not_implemented_op},
+
+ {"rfe", 0x2930, 0xD6CF, "", 0, SIZE_NONE,
+ cris_ver_v32p,
+ cris_not_implemented_op},
+
+ {"rfg", 0x4930, 0xB6CF, "", 0, SIZE_NONE,
+ cris_ver_v32p,
+ cris_not_implemented_op},
+
+ {"rfn", 0x5930, 0xA6CF, "", 0, SIZE_NONE,
+ cris_ver_v32p,
+ cris_not_implemented_op},
+
+ {"ret", 0xB67F, 0x4980, "", 1, SIZE_NONE,
+ cris_ver_v0_10,
+ cris_reg_mode_move_from_preg_op},
+
+ {"ret", 0xB9F0, 0x460F, "", 1, SIZE_NONE,
+ cris_ver_v32p,
+ cris_reg_mode_move_from_preg_op},
+
+ {"retb", 0xe67f, 0x1980, "", 1, SIZE_NONE,
+ cris_ver_v0_10,
+ cris_reg_mode_move_from_preg_op},
+
+ {"rete", 0xA9F0, 0x560F, "", 1, SIZE_NONE,
+ cris_ver_v32p,
+ cris_reg_mode_move_from_preg_op},
+
+ {"reti", 0xA67F, 0x5980, "", 1, SIZE_NONE,
+ cris_ver_v0_10,
+ cris_reg_mode_move_from_preg_op},
+
+ {"retn", 0xC9F0, 0x360F, "", 1, SIZE_NONE,
+ cris_ver_v32p,
+ cris_reg_mode_move_from_preg_op},
+
+ {"sbfs", 0x3b70, 0xc080, "y", 0, SIZE_NONE,
+ cris_ver_v10,
+ cris_not_implemented_op},
+
+ {"sbfs", 0x3b70, 0xc080, "S", 0, SIZE_NONE,
+ cris_ver_v10,
+ cris_not_implemented_op},
+
+ {"sa",
+ 0x0530+CC_A*0x1000,
+ 0x0AC0+(0xf-CC_A)*0x1000, "r", 0, SIZE_NONE, 0,
+ cris_scc_op},
+
+ {"ssb",
+ 0x0530+CC_EXT*0x1000,
+ 0x0AC0+(0xf-CC_EXT)*0x1000, "r", 0, SIZE_NONE,
+ cris_ver_v32p,
+ cris_scc_op},
+
+ {"scc",
+ 0x0530+CC_CC*0x1000,
+ 0x0AC0+(0xf-CC_CC)*0x1000, "r", 0, SIZE_NONE, 0,
+ cris_scc_op},
+
+ {"scs",
+ 0x0530+CC_CS*0x1000,
+ 0x0AC0+(0xf-CC_CS)*0x1000, "r", 0, SIZE_NONE, 0,
+ cris_scc_op},
+
+ {"seq",
+ 0x0530+CC_EQ*0x1000,
+ 0x0AC0+(0xf-CC_EQ)*0x1000, "r", 0, SIZE_NONE, 0,
+ cris_scc_op},
+
+ {"setf", 0x05b0, 0x0A40, "f", 0, SIZE_NONE, 0,
+ cris_ax_ei_setf_op},
+
+ {"sfe", 0x3930, 0xC6CF, "", 0, SIZE_NONE,
+ cris_ver_v32p,
+ cris_not_implemented_op},
+
+ /* Need to have "swf" in front of "sext" so it is the one displayed in
+ disassembly. */
+ {"swf",
+ 0x0530+CC_EXT*0x1000,
+ 0x0AC0+(0xf-CC_EXT)*0x1000, "r", 0, SIZE_NONE,
+ cris_ver_v10,
+ cris_scc_op},
+
+ {"sext",
+ 0x0530+CC_EXT*0x1000,
+ 0x0AC0+(0xf-CC_EXT)*0x1000, "r", 0, SIZE_NONE,
+ cris_ver_v0_3,
+ cris_scc_op},
+
+ {"sge",
+ 0x0530+CC_GE*0x1000,
+ 0x0AC0+(0xf-CC_GE)*0x1000, "r", 0, SIZE_NONE, 0,
+ cris_scc_op},
+
+ {"sgt",
+ 0x0530+CC_GT*0x1000,
+ 0x0AC0+(0xf-CC_GT)*0x1000, "r", 0, SIZE_NONE, 0,
+ cris_scc_op},
+
+ {"shi",
+ 0x0530+CC_HI*0x1000,
+ 0x0AC0+(0xf-CC_HI)*0x1000, "r", 0, SIZE_NONE, 0,
+ cris_scc_op},
+
+ {"shs",
+ 0x0530+CC_HS*0x1000,
+ 0x0AC0+(0xf-CC_HS)*0x1000, "r", 0, SIZE_NONE, 0,
+ cris_scc_op},
+
+ {"sle",
+ 0x0530+CC_LE*0x1000,
+ 0x0AC0+(0xf-CC_LE)*0x1000, "r", 0, SIZE_NONE, 0,
+ cris_scc_op},
+
+ {"slo",
+ 0x0530+CC_LO*0x1000,
+ 0x0AC0+(0xf-CC_LO)*0x1000, "r", 0, SIZE_NONE, 0,
+ cris_scc_op},
+
+ {"sls",
+ 0x0530+CC_LS*0x1000,
+ 0x0AC0+(0xf-CC_LS)*0x1000, "r", 0, SIZE_NONE, 0,
+ cris_scc_op},
+
+ {"slt",
+ 0x0530+CC_LT*0x1000,
+ 0x0AC0+(0xf-CC_LT)*0x1000, "r", 0, SIZE_NONE, 0,
+ cris_scc_op},
+
+ {"smi",
+ 0x0530+CC_MI*0x1000,
+ 0x0AC0+(0xf-CC_MI)*0x1000, "r", 0, SIZE_NONE, 0,
+ cris_scc_op},
+
+ {"sne",
+ 0x0530+CC_NE*0x1000,
+ 0x0AC0+(0xf-CC_NE)*0x1000, "r", 0, SIZE_NONE, 0,
+ cris_scc_op},
+
+ {"spl",
+ 0x0530+CC_PL*0x1000,
+ 0x0AC0+(0xf-CC_PL)*0x1000, "r", 0, SIZE_NONE, 0,
+ cris_scc_op},
+
+ {"sub", 0x0680, 0x0940, "m r,R", 0, SIZE_NONE, 0,
+ cris_reg_mode_add_sub_cmp_and_or_move_op},
+
+ {"sub", 0x0a80, 0x0140, "m s,R", 0, SIZE_FIELD, 0,
+ cris_none_reg_mode_add_sub_cmp_and_or_move_op},
+
+ {"sub", 0x0a80, 0x0140, "m S,D", 0, SIZE_NONE,
+ cris_ver_v0_10,
+ cris_none_reg_mode_add_sub_cmp_and_or_move_op},
+
+ {"sub", 0x0a80, 0x0540, "m S,R,r", 0, SIZE_NONE,
+ cris_ver_v0_10,
+ cris_three_operand_add_sub_cmp_and_or_op},
+
+ {"subq", 0x0280, 0x0d40, "I,R", 0, SIZE_NONE, 0,
+ cris_quick_mode_add_sub_op},
+
+ {"subs", 0x04a0, 0x0b40, "z r,R", 0, SIZE_NONE, 0,
+ cris_reg_mode_add_sub_cmp_and_or_move_op},
+
+ /* FIXME: SIZE_FIELD_SIGNED and all necessary changes. */
+ {"subs", 0x08a0, 0x0340, "z s,R", 0, SIZE_FIELD, 0,
+ cris_none_reg_mode_add_sub_cmp_and_or_move_op},
+
+ {"subs", 0x08a0, 0x0340, "z S,D", 0, SIZE_NONE,
+ cris_ver_v0_10,
+ cris_none_reg_mode_add_sub_cmp_and_or_move_op},
+
+ {"subs", 0x08a0, 0x0740, "z S,R,r", 0, SIZE_NONE,
+ cris_ver_v0_10,
+ cris_three_operand_add_sub_cmp_and_or_op},
+
+ {"subu", 0x0480, 0x0b60, "z r,R", 0, SIZE_NONE, 0,
+ cris_reg_mode_add_sub_cmp_and_or_move_op},
+
+ /* FIXME: SIZE_FIELD_UNSIGNED and all necessary changes. */
+ {"subu", 0x0880, 0x0360, "z s,R", 0, SIZE_FIELD, 0,
+ cris_none_reg_mode_add_sub_cmp_and_or_move_op},
+
+ {"subu", 0x0880, 0x0360, "z S,D", 0, SIZE_NONE,
+ cris_ver_v0_10,
+ cris_none_reg_mode_add_sub_cmp_and_or_move_op},
+
+ {"subu", 0x0880, 0x0760, "z S,R,r", 0, SIZE_NONE,
+ cris_ver_v0_10,
+ cris_three_operand_add_sub_cmp_and_or_op},
+
+ {"svc",
+ 0x0530+CC_VC*0x1000,
+ 0x0AC0+(0xf-CC_VC)*0x1000, "r", 0, SIZE_NONE, 0,
+ cris_scc_op},
+
+ {"svs",
+ 0x0530+CC_VS*0x1000,
+ 0x0AC0+(0xf-CC_VS)*0x1000, "r", 0, SIZE_NONE, 0,
+ cris_scc_op},
+
+ /* The insn "swapn" is the same as "not" and will be disassembled as
+ such, but the swap* family of mnmonics are generally v8-and-higher
+ only, so count it in. */
+ {"swapn", 0x8770, 0x7880, "r", 0, SIZE_NONE,
+ cris_ver_v8p,
+ cris_not_implemented_op},
+
+ {"swapw", 0x4770, 0xb880, "r", 0, SIZE_NONE,
+ cris_ver_v8p,
+ cris_not_implemented_op},
+
+ {"swapnw", 0xc770, 0x3880, "r", 0, SIZE_NONE,
+ cris_ver_v8p,
+ cris_not_implemented_op},
+
+ {"swapb", 0x2770, 0xd880, "r", 0, SIZE_NONE,
+ cris_ver_v8p,
+ cris_not_implemented_op},
+
+ {"swapnb", 0xA770, 0x5880, "r", 0, SIZE_NONE,
+ cris_ver_v8p,
+ cris_not_implemented_op},
+
+ {"swapwb", 0x6770, 0x9880, "r", 0, SIZE_NONE,
+ cris_ver_v8p,
+ cris_not_implemented_op},
+
+ {"swapnwb", 0xE770, 0x1880, "r", 0, SIZE_NONE,
+ cris_ver_v8p,
+ cris_not_implemented_op},
+
+ {"swapr", 0x1770, 0xe880, "r", 0, SIZE_NONE,
+ cris_ver_v8p,
+ cris_not_implemented_op},
+
+ {"swapnr", 0x9770, 0x6880, "r", 0, SIZE_NONE,
+ cris_ver_v8p,
+ cris_not_implemented_op},
+
+ {"swapwr", 0x5770, 0xa880, "r", 0, SIZE_NONE,
+ cris_ver_v8p,
+ cris_not_implemented_op},
+
+ {"swapnwr", 0xd770, 0x2880, "r", 0, SIZE_NONE,
+ cris_ver_v8p,
+ cris_not_implemented_op},
+
+ {"swapbr", 0x3770, 0xc880, "r", 0, SIZE_NONE,
+ cris_ver_v8p,
+ cris_not_implemented_op},
+
+ {"swapnbr", 0xb770, 0x4880, "r", 0, SIZE_NONE,
+ cris_ver_v8p,
+ cris_not_implemented_op},
+
+ {"swapwbr", 0x7770, 0x8880, "r", 0, SIZE_NONE,
+ cris_ver_v8p,
+ cris_not_implemented_op},
+
+ {"swapnwbr", 0xf770, 0x0880, "r", 0, SIZE_NONE,
+ cris_ver_v8p,
+ cris_not_implemented_op},
+
+ {"test", 0x0640, 0x0980, "m D", 0, SIZE_NONE,
+ cris_ver_v0_10,
+ cris_reg_mode_test_op},
+
+ {"test", 0x0b80, 0xf040, "m y", 0, SIZE_FIELD, 0,
+ cris_none_reg_mode_clear_test_op},
+
+ {"test", 0x0b80, 0xf040, "m S", 0, SIZE_NONE,
+ cris_ver_v0_10,
+ cris_none_reg_mode_clear_test_op},
+
+ {"xor", 0x07B0, 0x0840, "r,R", 0, SIZE_NONE, 0,
+ cris_xor_op},
+
+ {NULL, 0, 0, NULL, 0, 0, 0, cris_not_implemented_op}
+};
+
+/* Condition-names, indexed by the CC_* numbers as found in cris.h. */
+const char * const
+cris_cc_strings[] =
+{
+ "hs",
+ "lo",
+ "ne",
+ "eq",
+ "vc",
+ "vs",
+ "pl",
+ "mi",
+ "ls",
+ "hi",
+ "ge",
+ "lt",
+ "gt",
+ "le",
+ "a",
+ /* This is a placeholder. In v0, this would be "ext". In v32, this
+ is "sb". See cris_conds15. */
+ "wf"
+};
+
+/* Different names and semantics for condition 1111 (0xf). */
+const struct cris_cond15 cris_cond15s[] =
+{
+ /* FIXME: In what version did condition "ext" disappear? */
+ {"ext", cris_ver_v0_3},
+ {"wf", cris_ver_v10},
+ {"sb", cris_ver_v32p},
+ {NULL, 0}
+};
+
+
+/*
+ * Local variables:
+ * eval: (c-set-style "gnu")
+ * indent-tabs-mode: t
+ * End:
+ */
+
+
+/* No instruction will be disassembled longer than this. In theory, and
+ in silicon, address prefixes can be cascaded. In practice, cascading
+ is not used by GCC, and not supported by the assembler. */
+#ifndef MAX_BYTES_PER_CRIS_INSN
+#define MAX_BYTES_PER_CRIS_INSN 8
+#endif
+
+/* Whether or not to decode prefixes, folding it into the following
+ instruction. FIXME: Make this optional later. */
+#ifndef PARSE_PREFIX
+#define PARSE_PREFIX 1
+#endif
+
+/* Sometimes we prefix all registers with this character. */
+#define REGISTER_PREFIX_CHAR '$'
+
+/* Whether or not to trace the following sequence:
+ sub* X,r%d
+ bound* Y,r%d
+ adds.w [pc+r%d.w],pc
+
+ This is the assembly form of a switch-statement in C.
+ The "sub is optional. If there is none, then X will be zero.
+ X is the value of the first case,
+ Y is the number of cases (including default).
+
+ This results in case offsets printed on the form:
+ case N: -> case_address
+ where N is an estimation on the corresponding 'case' operand in C,
+ and case_address is where execution of that case continues after the
+ sequence presented above.
+
+ The old style of output was to print the offsets as instructions,
+ which made it hard to follow "case"-constructs in the disassembly,
+ and caused a lot of annoying warnings about undefined instructions.
+
+ FIXME: Make this optional later. */
+#ifndef TRACE_CASE
+#define TRACE_CASE (disdata->trace_case)
+#endif
+
+enum cris_disass_family
+ { cris_dis_v0_v10, cris_dis_common_v10_v32, cris_dis_v32 };
+
+/* Stored in the disasm_info->private_data member. */
+struct cris_disasm_data
+{
+ /* Whether to print something less confusing if we find something
+ matching a switch-construct. */
+ bfd_boolean trace_case;
+
+ /* Whether this code is flagged as crisv32. FIXME: Should be an enum
+ that includes "compatible". */
+ enum cris_disass_family distype;
+};
+
+/* Value of first element in switch. */
+static long case_offset = 0;
+
+/* How many more case-offsets to print. */
+static long case_offset_counter = 0;
+
+/* Number of case offsets. */
+static long no_of_case_offsets = 0;
+
+/* Candidate for next case_offset. */
+static long last_immediate = 0;
+
+static int cris_constraint
+ (const char *, unsigned, unsigned, struct cris_disasm_data *);
+
+/* Parse disassembler options and store state in info. FIXME: For the
+ time being, we abuse static variables. */
+
+static bfd_boolean
+cris_parse_disassembler_options (disassemble_info *info,
+ enum cris_disass_family distype)
+{
+ struct cris_disasm_data *disdata;
+
+ info->private_data = calloc (1, sizeof (struct cris_disasm_data));
+ disdata = (struct cris_disasm_data *) info->private_data;
+ if (disdata == NULL)
+ return FALSE;
+
+ /* Default true. */
+ disdata->trace_case
+ = (info->disassembler_options == NULL
+ || (strcmp (info->disassembler_options, "nocase") != 0));
+
+ disdata->distype = distype;
+ return TRUE;
+}
+
+static const struct cris_spec_reg *
+spec_reg_info (unsigned int sreg, enum cris_disass_family distype)
+{
+ int i;
+
+ for (i = 0; cris_spec_regs[i].name != NULL; i++)
+ {
+ if (cris_spec_regs[i].number == sreg)
+ {
+ if (distype == cris_dis_v32)
+ switch (cris_spec_regs[i].applicable_version)
+ {
+ case cris_ver_warning:
+ case cris_ver_version_all:
+ case cris_ver_v3p:
+ case cris_ver_v8p:
+ case cris_ver_v10p:
+ case cris_ver_v32p:
+ /* No ambiguous sizes or register names with CRISv32. */
+ if (cris_spec_regs[i].warning == NULL)
+ return &cris_spec_regs[i];
+ default:
+ ;
+ }
+ else if (cris_spec_regs[i].applicable_version != cris_ver_v32p)
+ return &cris_spec_regs[i];
+ }
+ }
+
+ return NULL;
+}
+
+/* Return the number of bits in the argument. */
+
+static int
+number_of_bits (unsigned int val)
+{
+ int bits;
+
+ for (bits = 0; val != 0; val &= val - 1)
+ bits++;
+
+ return bits;
+}
+
+/* Get an entry in the opcode-table. */
+
+static const struct cris_opcode *
+get_opcode_entry (unsigned int insn,
+ unsigned int prefix_insn,
+ struct cris_disasm_data *disdata)
+{
+ /* For non-prefixed insns, we keep a table of pointers, indexed by the
+ insn code. Each entry is initialized when found to be NULL. */
+ static const struct cris_opcode **opc_table = NULL;
+
+ const struct cris_opcode *max_matchedp = NULL;
+ const struct cris_opcode **prefix_opc_table = NULL;
+
+ /* We hold a table for each prefix that need to be handled differently. */
+ static const struct cris_opcode **dip_prefixes = NULL;
+ static const struct cris_opcode **bdapq_m1_prefixes = NULL;
+ static const struct cris_opcode **bdapq_m2_prefixes = NULL;
+ static const struct cris_opcode **bdapq_m4_prefixes = NULL;
+ static const struct cris_opcode **rest_prefixes = NULL;
+
+ /* Allocate and clear the opcode-table. */
+ if (opc_table == NULL)
+ {
+ opc_table = malloc (65536 * sizeof (opc_table[0]));
+ if (opc_table == NULL)
+ return NULL;
+
+ memset (opc_table, 0, 65536 * sizeof (const struct cris_opcode *));
+
+ dip_prefixes
+ = malloc (65536 * sizeof (const struct cris_opcode **));
+ if (dip_prefixes == NULL)
+ return NULL;
+
+ memset (dip_prefixes, 0, 65536 * sizeof (dip_prefixes[0]));
+
+ bdapq_m1_prefixes
+ = malloc (65536 * sizeof (const struct cris_opcode **));
+ if (bdapq_m1_prefixes == NULL)
+ return NULL;
+
+ memset (bdapq_m1_prefixes, 0, 65536 * sizeof (bdapq_m1_prefixes[0]));
+
+ bdapq_m2_prefixes
+ = malloc (65536 * sizeof (const struct cris_opcode **));
+ if (bdapq_m2_prefixes == NULL)
+ return NULL;
+
+ memset (bdapq_m2_prefixes, 0, 65536 * sizeof (bdapq_m2_prefixes[0]));
+
+ bdapq_m4_prefixes
+ = malloc (65536 * sizeof (const struct cris_opcode **));
+ if (bdapq_m4_prefixes == NULL)
+ return NULL;
+
+ memset (bdapq_m4_prefixes, 0, 65536 * sizeof (bdapq_m4_prefixes[0]));
+
+ rest_prefixes
+ = malloc (65536 * sizeof (const struct cris_opcode **));
+ if (rest_prefixes == NULL)
+ return NULL;
+
+ memset (rest_prefixes, 0, 65536 * sizeof (rest_prefixes[0]));
+ }
+
+ /* Get the right table if this is a prefix.
+ This code is connected to cris_constraints in that it knows what
+ prefixes play a role in recognition of patterns; the necessary
+ state is reflected by which table is used. If constraints
+ involving match or non-match of prefix insns are changed, then this
+ probably needs changing too. */
+ if (prefix_insn != NO_CRIS_PREFIX)
+ {
+ const struct cris_opcode *popcodep
+ = (opc_table[prefix_insn] != NULL
+ ? opc_table[prefix_insn]
+ : get_opcode_entry (prefix_insn, NO_CRIS_PREFIX, disdata));
+
+ if (popcodep == NULL)
+ return NULL;
+
+ if (popcodep->match == BDAP_QUICK_OPCODE)
+ {
+ /* Since some offsets are recognized with "push" macros, we
+ have to have different tables for them. */
+ int offset = (prefix_insn & 255);
+
+ if (offset > 127)
+ offset -= 256;
+
+ switch (offset)
+ {
+ case -4:
+ prefix_opc_table = bdapq_m4_prefixes;
+ break;
+
+ case -2:
+ prefix_opc_table = bdapq_m2_prefixes;
+ break;
+
+ case -1:
+ prefix_opc_table = bdapq_m1_prefixes;
+ break;
+
+ default:
+ prefix_opc_table = rest_prefixes;
+ break;
+ }
+ }
+ else if (popcodep->match == DIP_OPCODE)
+ /* We don't allow postincrement when the prefix is DIP, so use a
+ different table for DIP. */
+ prefix_opc_table = dip_prefixes;
+ else
+ prefix_opc_table = rest_prefixes;
+ }
+
+ if (prefix_insn != NO_CRIS_PREFIX
+ && prefix_opc_table[insn] != NULL)
+ max_matchedp = prefix_opc_table[insn];
+ else if (prefix_insn == NO_CRIS_PREFIX && opc_table[insn] != NULL)
+ max_matchedp = opc_table[insn];
+ else
+ {
+ const struct cris_opcode *opcodep;
+ int max_level_of_match = -1;
+
+ for (opcodep = cris_opcodes;
+ opcodep->name != NULL;
+ opcodep++)
+ {
+ int level_of_match;
+
+ if (disdata->distype == cris_dis_v32)
+ {
+ switch (opcodep->applicable_version)
+ {
+ case cris_ver_version_all:
+ break;
+
+ case cris_ver_v0_3:
+ case cris_ver_v0_10:
+ case cris_ver_v3_10:
+ case cris_ver_sim_v0_10:
+ case cris_ver_v8_10:
+ case cris_ver_v10:
+ case cris_ver_warning:
+ continue;
+
+ case cris_ver_v3p:
+ case cris_ver_v8p:
+ case cris_ver_v10p:
+ case cris_ver_v32p:
+ break;
+
+ case cris_ver_v8:
+ abort ();
+ default:
+ abort ();
+ }
+ }
+ else
+ {
+ switch (opcodep->applicable_version)
+ {
+ case cris_ver_version_all:
+ case cris_ver_v0_3:
+ case cris_ver_v3p:
+ case cris_ver_v0_10:
+ case cris_ver_v8p:
+ case cris_ver_v8_10:
+ case cris_ver_v10:
+ case cris_ver_sim_v0_10:
+ case cris_ver_v10p:
+ case cris_ver_warning:
+ break;
+
+ case cris_ver_v32p:
+ continue;
+
+ case cris_ver_v8:
+ abort ();
+ default:
+ abort ();
+ }
+ }
+
+ /* We give a double lead for bits matching the template in
+ cris_opcodes. Not even, because then "move p8,r10" would
+ be given 2 bits lead over "clear.d r10". When there's a
+ tie, the first entry in the table wins. This is
+ deliberate, to avoid a more complicated recognition
+ formula. */
+ if ((opcodep->match & insn) == opcodep->match
+ && (opcodep->lose & insn) == 0
+ && ((level_of_match
+ = cris_constraint (opcodep->args,
+ insn,
+ prefix_insn,
+ disdata))
+ >= 0)
+ && ((level_of_match
+ += 2 * number_of_bits (opcodep->match
+ | opcodep->lose))
+ > max_level_of_match))
+ {
+ max_matchedp = opcodep;
+ max_level_of_match = level_of_match;
+
+ /* If there was a full match, never mind looking
+ further. */
+ if (level_of_match >= 2 * 16)
+ break;
+ }
+ }
+ /* Fill in the new entry.
+
+ If there are changes to the opcode-table involving prefixes, and
+ disassembly then does not work correctly, try removing the
+ else-clause below that fills in the prefix-table. If that
+ helps, you need to change the prefix_opc_table setting above, or
+ something related. */
+ if (prefix_insn == NO_CRIS_PREFIX)
+ opc_table[insn] = max_matchedp;
+ else
+ prefix_opc_table[insn] = max_matchedp;
+ }
+
+ return max_matchedp;
+}
+
+/* Return -1 if the constraints of a bitwise-matched instruction say
+ that there is no match. Otherwise return a nonnegative number
+ indicating the confidence in the match (higher is better). */
+
+static int
+cris_constraint (const char *cs,
+ unsigned int insn,
+ unsigned int prefix_insn,
+ struct cris_disasm_data *disdata)
+{
+ int retval = 0;
+ int tmp;
+ int prefix_ok = 0;
+ const char *s;
+
+ for (s = cs; *s; s++)
+ switch (*s)
+ {
+ case '!':
+ /* Do not recognize "pop" if there's a prefix and then only for
+ v0..v10. */
+ if (prefix_insn != NO_CRIS_PREFIX
+ || disdata->distype != cris_dis_v0_v10)
+ return -1;
+ break;
+
+ case 'U':
+ /* Not recognized at disassembly. */
+ return -1;
+
+ case 'M':
+ /* Size modifier for "clear", i.e. special register 0, 4 or 8.
+ Check that it is one of them. Only special register 12 could
+ be mismatched, but checking for matches is more logical than
+ checking for mismatches when there are only a few cases. */
+ tmp = ((insn >> 12) & 0xf);
+ if (tmp != 0 && tmp != 4 && tmp != 8)
+ return -1;
+ break;
+
+ case 'm':
+ if ((insn & 0x30) == 0x30)
+ return -1;
+ break;
+
+ case 'S':
+ /* A prefix operand without side-effect. */
+ if (prefix_insn != NO_CRIS_PREFIX && (insn & 0x400) == 0)
+ {
+ prefix_ok = 1;
+ break;
+ }
+ else
+ return -1;
+
+ case 's':
+ case 'y':
+ case 'Y':
+ /* If this is a prefixed insn with postincrement (side-effect),
+ the prefix must not be DIP. */
+ if (prefix_insn != NO_CRIS_PREFIX)
+ {
+ if (insn & 0x400)
+ {
+ const struct cris_opcode *prefix_opcodep
+ = get_opcode_entry (prefix_insn, NO_CRIS_PREFIX, disdata);
+
+ if (prefix_opcodep->match == DIP_OPCODE)
+ return -1;
+ }
+
+ prefix_ok = 1;
+ }
+ break;
+
+ case 'B':
+ /* If we don't fall through, then the prefix is ok. */
+ prefix_ok = 1;
+
+ /* A "push" prefix. Check for valid "push" size.
+ In case of special register, it may be != 4. */
+ if (prefix_insn != NO_CRIS_PREFIX)
+ {
+ /* Match the prefix insn to BDAPQ. */
+ const struct cris_opcode *prefix_opcodep
+ = get_opcode_entry (prefix_insn, NO_CRIS_PREFIX, disdata);
+
+ if (prefix_opcodep->match == BDAP_QUICK_OPCODE)
+ {
+ int pushsize = (prefix_insn & 255);
+
+ if (pushsize > 127)
+ pushsize -= 256;
+
+ if (s[1] == 'P')
+ {
+ unsigned int spec_reg = (insn >> 12) & 15;
+ const struct cris_spec_reg *sregp
+ = spec_reg_info (spec_reg, disdata->distype);
+
+ /* For a special-register, the "prefix size" must
+ match the size of the register. */
+ if (sregp && sregp->reg_size == (unsigned int) -pushsize)
+ break;
+ }
+ else if (s[1] == 'R')
+ {
+ if ((insn & 0x30) == 0x20 && pushsize == -4)
+ break;
+ }
+ /* FIXME: Should abort here; next constraint letter
+ *must* be 'P' or 'R'. */
+ }
+ }
+ return -1;
+
+ case 'D':
+ retval = (((insn >> 12) & 15) == (insn & 15));
+ if (!retval)
+ return -1;
+ else
+ retval += 4;
+ break;
+
+ case 'P':
+ {
+ const struct cris_spec_reg *sregp
+ = spec_reg_info ((insn >> 12) & 15, disdata->distype);
+
+ /* Since we match four bits, we will give a value of 4-1 = 3
+ in a match. If there is a corresponding exact match of a
+ special register in another pattern, it will get a value of
+ 4, which will be higher. This should be correct in that an
+ exact pattern would match better than a general pattern.
+
+ Note that there is a reason for not returning zero; the
+ pattern for "clear" is partly matched in the bit-pattern
+ (the two lower bits must be zero), while the bit-pattern
+ for a move from a special register is matched in the
+ register constraint. */
+
+ if (sregp != NULL)
+ {
+ retval += 3;
+ break;
+ }
+ else
+ return -1;
+ }
+ }
+
+ if (prefix_insn != NO_CRIS_PREFIX && ! prefix_ok)
+ return -1;
+
+ return retval;
+}
+
+/* Format number as hex with a leading "0x" into outbuffer. */
+
+static char *
+format_hex (unsigned long number,
+ char *outbuffer,
+ struct cris_disasm_data *disdata)
+{
+ /* Truncate negative numbers on >32-bit hosts. */
+ number &= 0xffffffff;
+
+ sprintf (outbuffer, "0x%lx", number);
+
+ /* Save this value for the "case" support. */
+ if (TRACE_CASE)
+ last_immediate = number;
+
+ return outbuffer + strlen (outbuffer);
+}
+
+/* Format number as decimal into outbuffer. Parameter signedp says
+ whether the number should be formatted as signed (!= 0) or
+ unsigned (== 0). */
+
+static char *
+format_dec (long number, char *outbuffer, int signedp)
+{
+ last_immediate = number;
+ sprintf (outbuffer, signedp ? "%ld" : "%lu", number);
+
+ return outbuffer + strlen (outbuffer);
+}
+
+/* Format the name of the general register regno into outbuffer. */
+
+static char *
+format_reg (struct cris_disasm_data *disdata,
+ int regno,
+ char *outbuffer_start,
+ bfd_boolean with_reg_prefix)
+{
+ char *outbuffer = outbuffer_start;
+
+ if (with_reg_prefix)
+ *outbuffer++ = REGISTER_PREFIX_CHAR;
+
+ switch (regno)
+ {
+ case 15:
+ /* For v32, there is no context in which we output PC. */
+ if (disdata->distype == cris_dis_v32)
+ strcpy (outbuffer, "acr");
+ else
+ strcpy (outbuffer, "pc");
+ break;
+
+ case 14:
+ strcpy (outbuffer, "sp");
+ break;
+
+ default:
+ sprintf (outbuffer, "r%d", regno);
+ break;
+ }
+
+ return outbuffer_start + strlen (outbuffer_start);
+}
+
+/* Format the name of a support register into outbuffer. */
+
+static char *
+format_sup_reg (unsigned int regno,
+ char *outbuffer_start,
+ bfd_boolean with_reg_prefix)
+{
+ char *outbuffer = outbuffer_start;
+ int i;
+
+ if (with_reg_prefix)
+ *outbuffer++ = REGISTER_PREFIX_CHAR;
+
+ for (i = 0; cris_support_regs[i].name != NULL; i++)
+ if (cris_support_regs[i].number == regno)
+ {
+ sprintf (outbuffer, "%s", cris_support_regs[i].name);
+ return outbuffer_start + strlen (outbuffer_start);
+ }
+
+ /* There's supposed to be register names covering all numbers, though
+ some may be generic names. */
+ sprintf (outbuffer, "format_sup_reg-BUG");
+ return outbuffer_start + strlen (outbuffer_start);
+}
+
+/* Return the length of an instruction. */
+
+static unsigned
+bytes_to_skip (unsigned int insn,
+ const struct cris_opcode *matchedp,
+ enum cris_disass_family distype,
+ const struct cris_opcode *prefix_matchedp)
+{
+ /* Each insn is a word plus "immediate" operands. */
+ unsigned to_skip = 2;
+ const char *template = matchedp->args;
+ const char *s;
+
+ for (s = template; *s; s++)
+ if ((*s == 's' || *s == 'N' || *s == 'Y')
+ && (insn & 0x400) && (insn & 15) == 15
+ && prefix_matchedp == NULL)
+ {
+ /* Immediate via [pc+], so we have to check the size of the
+ operand. */
+ int mode_size = 1 << ((insn >> 4) & (*template == 'z' ? 1 : 3));
+
+ if (matchedp->imm_oprnd_size == SIZE_FIX_32)
+ to_skip += 4;
+ else if (matchedp->imm_oprnd_size == SIZE_SPEC_REG)
+ {
+ const struct cris_spec_reg *sregp
+ = spec_reg_info ((insn >> 12) & 15, distype);
+
+ /* FIXME: Improve error handling; should have been caught
+ earlier. */
+ if (sregp == NULL)
+ return 2;
+
+ /* PC is incremented by two, not one, for a byte. Except on
+ CRISv32, where constants are always DWORD-size for
+ special registers. */
+ to_skip +=
+ distype == cris_dis_v32 ? 4 : (sregp->reg_size + 1) & ~1;
+ }
+ else
+ to_skip += (mode_size + 1) & ~1;
+ }
+ else if (*s == 'n')
+ to_skip += 4;
+ else if (*s == 'b')
+ to_skip += 2;
+
+ return to_skip;
+}
+
+/* Print condition code flags. */
+
+static char *
+print_flags (struct cris_disasm_data *disdata, unsigned int insn, char *cp)
+{
+ /* Use the v8 (Etrax 100) flag definitions for disassembly.
+ The differences with v0 (Etrax 1..4) vs. Svinto are:
+ v0 'd' <=> v8 'm'
+ v0 'e' <=> v8 'b'.
+ FIXME: Emit v0..v3 flag names somehow. */
+ static const char v8_fnames[] = "cvznxibm";
+ static const char v32_fnames[] = "cvznxiup";
+ const char *fnames
+ = disdata->distype == cris_dis_v32 ? v32_fnames : v8_fnames;
+
+ unsigned char flagbits = (((insn >> 8) & 0xf0) | (insn & 15));
+ int i;
+
+ for (i = 0; i < 8; i++)
+ if (flagbits & (1 << i))
+ *cp++ = fnames[i];
+
+ return cp;
+}
+
+/* Print out an insn with its operands, and update the info->insn_type
+ fields. The prefix_opcodep and the rest hold a prefix insn that is
+ supposed to be output as an address mode. */
+
+static void
+print_with_operands (const struct cris_opcode *opcodep,
+ unsigned int insn,
+ unsigned char *buffer,
+ bfd_vma addr,
+ disassemble_info *info,
+ /* If a prefix insn was before this insn (and is supposed
+ to be output as an address), here is a description of
+ it. */
+ const struct cris_opcode *prefix_opcodep,
+ unsigned int prefix_insn,
+ unsigned char *prefix_buffer,
+ bfd_boolean with_reg_prefix)
+{
+ /* Get a buffer of somewhat reasonable size where we store
+ intermediate parts of the insn. */
+ char temp[sizeof (".d [$r13=$r12-2147483648],$r10") * 2];
+ char *tp = temp;
+ static const char mode_char[] = "bwd?";
+ const char *s;
+ const char *cs;
+ struct cris_disasm_data *disdata
+ = (struct cris_disasm_data *) info->private_data;
+
+ /* Print out the name first thing we do. */
+ (*info->fprintf_func) (info->stream, "%s", opcodep->name);
+
+ cs = opcodep->args;
+ s = cs;
+
+ /* Ignore any prefix indicator. */
+ if (*s == 'p')
+ s++;
+
+ if (*s == 'm' || *s == 'M' || *s == 'z')
+ {
+ *tp++ = '.';
+
+ /* Get the size-letter. */
+ *tp++ = *s == 'M'
+ ? (insn & 0x8000 ? 'd'
+ : insn & 0x4000 ? 'w' : 'b')
+ : mode_char[(insn >> 4) & (*s == 'z' ? 1 : 3)];
+
+ /* Ignore the size and the space character that follows. */
+ s += 2;
+ }
+
+ /* Add a space if this isn't a long-branch, because for those will add
+ the condition part of the name later. */
+ if (opcodep->match != (BRANCH_PC_LOW + BRANCH_INCR_HIGH * 256))
+ *tp++ = ' ';
+
+ /* Fill in the insn-type if deducible from the name (and there's no
+ better way). */
+ if (opcodep->name[0] == 'j')
+ {
+ if (CONST_STRNEQ (opcodep->name, "jsr"))
+ /* It's "jsr" or "jsrc". */
+ info->insn_type = dis_jsr;
+ else
+ /* Any other jump-type insn is considered a branch. */
+ info->insn_type = dis_branch;
+ }
+
+ /* We might know some more fields right now. */
+ info->branch_delay_insns = opcodep->delayed;
+
+ /* Handle operands. */
+ for (; *s; s++)
+ {
+ switch (*s)
+ {
+ case 'T':
+ tp = format_sup_reg ((insn >> 12) & 15, tp, with_reg_prefix);
+ break;
+
+ case 'A':
+ if (with_reg_prefix)
+ *tp++ = REGISTER_PREFIX_CHAR;
+ *tp++ = 'a';
+ *tp++ = 'c';
+ *tp++ = 'r';
+ break;
+
+ case '[':
+ case ']':
+ case ',':
+ *tp++ = *s;
+ break;
+
+ case '!':
+ /* Ignore at this point; used at earlier stages to avoid
+ recognition if there's a prefix at something that in other
+ ways looks like a "pop". */
+ break;
+
+ case 'd':
+ /* Ignore. This is an optional ".d " on the large one of
+ relaxable insns. */
+ break;
+
+ case 'B':
+ /* This was the prefix that made this a "push". We've already
+ handled it by recognizing it, so signal that the prefix is
+ handled by setting it to NULL. */
+ prefix_opcodep = NULL;
+ break;
+
+ case 'D':
+ case 'r':
+ tp = format_reg (disdata, insn & 15, tp, with_reg_prefix);
+ break;
+
+ case 'R':
+ tp = format_reg (disdata, (insn >> 12) & 15, tp, with_reg_prefix);
+ break;
+
+ case 'n':
+ {
+ /* Like N but pc-relative to the start of the insn. */
+ unsigned long number
+ = (buffer[2] + buffer[3] * 256 + buffer[4] * 65536
+ + buffer[5] * 0x1000000 + addr);
+
+ /* Finish off and output previous formatted bytes. */
+ *tp = 0;
+ if (temp[0])
+ (*info->fprintf_func) (info->stream, "%s", temp);
+ tp = temp;
+
+ (*info->print_address_func) ((bfd_vma) number, info);
+ }
+ break;
+
+ case 'u':
+ {
+ /* Like n but the offset is bits <3:0> in the instruction. */
+ unsigned long number = (buffer[0] & 0xf) * 2 + addr;
+
+ /* Finish off and output previous formatted bytes. */
+ *tp = 0;
+ if (temp[0])
+ (*info->fprintf_func) (info->stream, "%s", temp);
+ tp = temp;
+
+ (*info->print_address_func) ((bfd_vma) number, info);
+ }
+ break;
+
+ case 'N':
+ case 'y':
+ case 'Y':
+ case 'S':
+ case 's':
+ /* Any "normal" memory operand. */
+ if ((insn & 0x400) && (insn & 15) == 15 && prefix_opcodep == NULL)
+ {
+ /* We're looking at [pc+], i.e. we need to output an immediate
+ number, where the size can depend on different things. */
+ long number;
+ int signedp
+ = ((*cs == 'z' && (insn & 0x20))
+ || opcodep->match == BDAP_QUICK_OPCODE);
+ int nbytes;
+
+ if (opcodep->imm_oprnd_size == SIZE_FIX_32)
+ nbytes = 4;
+ else if (opcodep->imm_oprnd_size == SIZE_SPEC_REG)
+ {
+ const struct cris_spec_reg *sregp
+ = spec_reg_info ((insn >> 12) & 15, disdata->distype);
+
+ /* A NULL return should have been as a non-match earlier,
+ so catch it as an internal error in the error-case
+ below. */
+ if (sregp == NULL)
+ /* Whatever non-valid size. */
+ nbytes = 42;
+ else
+ /* PC is always incremented by a multiple of two.
+ For CRISv32, immediates are always 4 bytes for
+ special registers. */
+ nbytes = disdata->distype == cris_dis_v32
+ ? 4 : (sregp->reg_size + 1) & ~1;
+ }
+ else
+ {
+ int mode_size = 1 << ((insn >> 4) & (*cs == 'z' ? 1 : 3));
+
+ if (mode_size == 1)
+ nbytes = 2;
+ else
+ nbytes = mode_size;
+ }
+
+ switch (nbytes)
+ {
+ case 1:
+ number = buffer[2];
+ if (signedp && number > 127)
+ number -= 256;
+ break;
+
+ case 2:
+ number = buffer[2] + buffer[3] * 256;
+ if (signedp && number > 32767)
+ number -= 65536;
+ break;
+
+ case 4:
+ number
+ = buffer[2] + buffer[3] * 256 + buffer[4] * 65536
+ + buffer[5] * 0x1000000;
+ break;
+
+ default:
+ strcpy (tp, "bug");
+ tp += 3;
+ number = 42;
+ }
+
+ if ((*cs == 'z' && (insn & 0x20))
+ || (opcodep->match == BDAP_QUICK_OPCODE
+ && (nbytes <= 2 || buffer[1 + nbytes] == 0)))
+ tp = format_dec (number, tp, signedp);
+ else
+ {
+ unsigned int highbyte = (number >> 24) & 0xff;
+
+ /* Either output this as an address or as a number. If it's
+ a dword with the same high-byte as the address of the
+ insn, assume it's an address, and also if it's a non-zero
+ non-0xff high-byte. If this is a jsr or a jump, then
+ it's definitely an address. */
+ if (nbytes == 4
+ && (highbyte == ((addr >> 24) & 0xff)
+ || (highbyte != 0 && highbyte != 0xff)
+ || info->insn_type == dis_branch
+ || info->insn_type == dis_jsr))
+ {
+ /* Finish off and output previous formatted bytes. */
+ *tp = 0;
+ tp = temp;
+ if (temp[0])
+ (*info->fprintf_func) (info->stream, "%s", temp);
+
+ (*info->print_address_func) ((bfd_vma) number, info);
+
+ info->target = number;
+ }
+ else
+ tp = format_hex (number, tp, disdata);
+ }
+ }
+ else
+ {
+ /* Not an immediate number. Then this is a (possibly
+ prefixed) memory operand. */
+ if (info->insn_type != dis_nonbranch)
+ {
+ int mode_size
+ = 1 << ((insn >> 4)
+ & (opcodep->args[0] == 'z' ? 1 : 3));
+ int size;
+ info->insn_type = dis_dref;
+ info->flags |= CRIS_DIS_FLAG_MEMREF;
+
+ if (opcodep->imm_oprnd_size == SIZE_FIX_32)
+ size = 4;
+ else if (opcodep->imm_oprnd_size == SIZE_SPEC_REG)
+ {
+ const struct cris_spec_reg *sregp
+ = spec_reg_info ((insn >> 12) & 15, disdata->distype);
+
+ /* FIXME: Improve error handling; should have been caught
+ earlier. */
+ if (sregp == NULL)
+ size = 4;
+ else
+ size = sregp->reg_size;
+ }
+ else
+ size = mode_size;
+
+ info->data_size = size;
+ }
+
+ *tp++ = '[';
+
+ if (prefix_opcodep
+ /* We don't match dip with a postincremented field
+ as a side-effect address mode. */
+ && ((insn & 0x400) == 0
+ || prefix_opcodep->match != DIP_OPCODE))
+ {
+ if (insn & 0x400)
+ {
+ tp = format_reg (disdata, insn & 15, tp, with_reg_prefix);
+ *tp++ = '=';
+ }
+
+
+ /* We mainly ignore the prefix format string when the
+ address-mode syntax is output. */
+ switch (prefix_opcodep->match)
+ {
+ case DIP_OPCODE:
+ /* It's [r], [r+] or [pc+]. */
+ if ((prefix_insn & 0x400) && (prefix_insn & 15) == 15)
+ {
+ /* It's [pc+]. This cannot possibly be anything
+ but an address. */
+ unsigned long number
+ = prefix_buffer[2] + prefix_buffer[3] * 256
+ + prefix_buffer[4] * 65536
+ + prefix_buffer[5] * 0x1000000;
+
+ info->target = (bfd_vma) number;
+
+ /* Finish off and output previous formatted
+ data. */
+ *tp = 0;
+ tp = temp;
+ if (temp[0])
+ (*info->fprintf_func) (info->stream, "%s", temp);
+
+ (*info->print_address_func) ((bfd_vma) number, info);
+ }
+ else
+ {
+ /* For a memref in an address, we use target2.
+ In this case, target is zero. */
+ info->flags
+ |= (CRIS_DIS_FLAG_MEM_TARGET2_IS_REG
+ | CRIS_DIS_FLAG_MEM_TARGET2_MEM);
+
+ info->target2 = prefix_insn & 15;
+
+ *tp++ = '[';
+ tp = format_reg (disdata, prefix_insn & 15, tp,
+ with_reg_prefix);
+ if (prefix_insn & 0x400)
+ *tp++ = '+';
+ *tp++ = ']';
+ }
+ break;
+
+ case BDAP_QUICK_OPCODE:
+ {
+ int number;
+
+ number = prefix_buffer[0];
+ if (number > 127)
+ number -= 256;
+
+ /* Output "reg+num" or, if num < 0, "reg-num". */
+ tp = format_reg (disdata, (prefix_insn >> 12) & 15, tp,
+ with_reg_prefix);
+ if (number >= 0)
+ *tp++ = '+';
+ tp = format_dec (number, tp, 1);
+
+ info->flags |= CRIS_DIS_FLAG_MEM_TARGET_IS_REG;
+ info->target = (prefix_insn >> 12) & 15;
+ info->target2 = (bfd_vma) number;
+ break;
+ }
+
+ case BIAP_OPCODE:
+ /* Output "r+R.m". */
+ tp = format_reg (disdata, prefix_insn & 15, tp,
+ with_reg_prefix);
+ *tp++ = '+';
+ tp = format_reg (disdata, (prefix_insn >> 12) & 15, tp,
+ with_reg_prefix);
+ *tp++ = '.';
+ *tp++ = mode_char[(prefix_insn >> 4) & 3];
+
+ info->flags
+ |= (CRIS_DIS_FLAG_MEM_TARGET2_IS_REG
+ | CRIS_DIS_FLAG_MEM_TARGET_IS_REG
+
+ | ((prefix_insn & 0x8000)
+ ? CRIS_DIS_FLAG_MEM_TARGET2_MULT4
+ : ((prefix_insn & 0x8000)
+ ? CRIS_DIS_FLAG_MEM_TARGET2_MULT2 : 0)));
+
+ /* Is it the casejump? It's a "adds.w [pc+r%d.w],pc". */
+ if (insn == 0xf83f && (prefix_insn & ~0xf000) == 0x55f)
+ /* Then start interpreting data as offsets. */
+ case_offset_counter = no_of_case_offsets;
+ break;
+
+ case BDAP_INDIR_OPCODE:
+ /* Output "r+s.m", or, if "s" is [pc+], "r+s" or
+ "r-s". */
+ tp = format_reg (disdata, (prefix_insn >> 12) & 15, tp,
+ with_reg_prefix);
+
+ if ((prefix_insn & 0x400) && (prefix_insn & 15) == 15)
+ {
+ long number;
+ unsigned int nbytes;
+
+ /* It's a value. Get its size. */
+ int mode_size = 1 << ((prefix_insn >> 4) & 3);
+
+ if (mode_size == 1)
+ nbytes = 2;
+ else
+ nbytes = mode_size;
+
+ switch (nbytes)
+ {
+ case 1:
+ number = prefix_buffer[2];
+ if (number > 127)
+ number -= 256;
+ break;
+
+ case 2:
+ number = prefix_buffer[2] + prefix_buffer[3] * 256;
+ if (number > 32767)
+ number -= 65536;
+ break;
+
+ case 4:
+ number
+ = prefix_buffer[2] + prefix_buffer[3] * 256
+ + prefix_buffer[4] * 65536
+ + prefix_buffer[5] * 0x1000000;
+ break;
+
+ default:
+ strcpy (tp, "bug");
+ tp += 3;
+ number = 42;
+ }
+
+ info->flags |= CRIS_DIS_FLAG_MEM_TARGET_IS_REG;
+ info->target2 = (bfd_vma) number;
+
+ /* If the size is dword, then assume it's an
+ address. */
+ if (nbytes == 4)
+ {
+ /* Finish off and output previous formatted
+ bytes. */
+ *tp++ = '+';
+ *tp = 0;
+ tp = temp;
+ (*info->fprintf_func) (info->stream, "%s", temp);
+
+ (*info->print_address_func) ((bfd_vma) number, info);
+ }
+ else
+ {
+ if (number >= 0)
+ *tp++ = '+';
+ tp = format_dec (number, tp, 1);
+ }
+ }
+ else
+ {
+ /* Output "r+[R].m" or "r+[R+].m". */
+ *tp++ = '+';
+ *tp++ = '[';
+ tp = format_reg (disdata, prefix_insn & 15, tp,
+ with_reg_prefix);
+ if (prefix_insn & 0x400)
+ *tp++ = '+';
+ *tp++ = ']';
+ *tp++ = '.';
+ *tp++ = mode_char[(prefix_insn >> 4) & 3];
+
+ info->flags
+ |= (CRIS_DIS_FLAG_MEM_TARGET2_IS_REG
+ | CRIS_DIS_FLAG_MEM_TARGET2_MEM
+ | CRIS_DIS_FLAG_MEM_TARGET_IS_REG
+
+ | (((prefix_insn >> 4) == 2)
+ ? 0
+ : (((prefix_insn >> 4) & 3) == 1
+ ? CRIS_DIS_FLAG_MEM_TARGET2_MEM_WORD
+ : CRIS_DIS_FLAG_MEM_TARGET2_MEM_BYTE)));
+ }
+ break;
+
+ default:
+ (*info->fprintf_func) (info->stream, "?prefix-bug");
+ }
+
+ /* To mark that the prefix is used, reset it. */
+ prefix_opcodep = NULL;
+ }
+ else
+ {
+ tp = format_reg (disdata, insn & 15, tp, with_reg_prefix);
+
+ info->flags |= CRIS_DIS_FLAG_MEM_TARGET_IS_REG;
+ info->target = insn & 15;
+
+ if (insn & 0x400)
+ *tp++ = '+';
+ }
+ *tp++ = ']';
+ }
+ break;
+
+ case 'x':
+ tp = format_reg (disdata, (insn >> 12) & 15, tp, with_reg_prefix);
+ *tp++ = '.';
+ *tp++ = mode_char[(insn >> 4) & 3];
+ break;
+
+ case 'I':
+ tp = format_dec (insn & 63, tp, 0);
+ break;
+
+ case 'b':
+ {
+ int where = buffer[2] + buffer[3] * 256;
+
+ if (where > 32767)
+ where -= 65536;
+
+ where += addr + ((disdata->distype == cris_dis_v32) ? 0 : 4);
+
+ if (insn == BA_PC_INCR_OPCODE)
+ info->insn_type = dis_branch;
+ else
+ info->insn_type = dis_condbranch;
+
+ info->target = (bfd_vma) where;
+
+ *tp = 0;
+ tp = temp;
+ (*info->fprintf_func) (info->stream, "%s%s ",
+ temp, cris_cc_strings[insn >> 12]);
+
+ (*info->print_address_func) ((bfd_vma) where, info);
+ }
+ break;
+
+ case 'c':
+ tp = format_dec (insn & 31, tp, 0);
+ break;
+
+ case 'C':
+ tp = format_dec (insn & 15, tp, 0);
+ break;
+
+ case 'o':
+ {
+ long offset = insn & 0xfe;
+ bfd_vma target;
+
+ if (insn & 1)
+ offset |= ~0xff;
+
+ if (opcodep->match == BA_QUICK_OPCODE)
+ info->insn_type = dis_branch;
+ else
+ info->insn_type = dis_condbranch;
+
+ target = addr + ((disdata->distype == cris_dis_v32) ? 0 : 2) + offset;
+ info->target = target;
+ *tp = 0;
+ tp = temp;
+ (*info->fprintf_func) (info->stream, "%s", temp);
+ (*info->print_address_func) (target, info);
+ }
+ break;
+
+ case 'Q':
+ case 'O':
+ {
+ long number = buffer[0];
+
+ if (number > 127)
+ number = number - 256;
+
+ tp = format_dec (number, tp, 1);
+ *tp++ = ',';
+ tp = format_reg (disdata, (insn >> 12) & 15, tp, with_reg_prefix);
+ }
+ break;
+
+ case 'f':
+ tp = print_flags (disdata, insn, tp);
+ break;
+
+ case 'i':
+ tp = format_dec ((insn & 32) ? (insn & 31) | ~31L : insn & 31, tp, 1);
+ break;
+
+ case 'P':
+ {
+ const struct cris_spec_reg *sregp
+ = spec_reg_info ((insn >> 12) & 15, disdata->distype);
+
+ if (sregp->name == NULL)
+ /* Should have been caught as a non-match eariler. */
+ *tp++ = '?';
+ else
+ {
+ if (with_reg_prefix)
+ *tp++ = REGISTER_PREFIX_CHAR;
+ strcpy (tp, sregp->name);
+ tp += strlen (tp);
+ }
+ }
+ break;
+
+ default:
+ strcpy (tp, "???");
+ tp += 3;
+ }
+ }
+
+ *tp = 0;
+
+ if (prefix_opcodep)
+ (*info->fprintf_func) (info->stream, " (OOPS unused prefix \"%s: %s\")",
+ prefix_opcodep->name, prefix_opcodep->args);
+
+ (*info->fprintf_func) (info->stream, "%s", temp);
+
+ /* Get info for matching case-tables, if we don't have any active.
+ We assume that the last constant seen is used; either in the insn
+ itself or in a "move.d const,rN, sub.d rN,rM"-like sequence. */
+ if (TRACE_CASE && case_offset_counter == 0)
+ {
+ if (CONST_STRNEQ (opcodep->name, "sub"))
+ case_offset = last_immediate;
+
+ /* It could also be an "add", if there are negative case-values. */
+ else if (CONST_STRNEQ (opcodep->name, "add"))
+ /* The first case is the negated operand to the add. */
+ case_offset = -last_immediate;
+
+ /* A bound insn will tell us the number of cases. */
+ else if (CONST_STRNEQ (opcodep->name, "bound"))
+ no_of_case_offsets = last_immediate + 1;
+
+ /* A jump or jsr or branch breaks the chain of insns for a
+ case-table, so assume default first-case again. */
+ else if (info->insn_type == dis_jsr
+ || info->insn_type == dis_branch
+ || info->insn_type == dis_condbranch)
+ case_offset = 0;
+ }
+}
+
+
+/* Print the CRIS instruction at address memaddr on stream. Returns
+ length of the instruction, in bytes. Prefix register names with `$' if
+ WITH_REG_PREFIX. */
+
+static int
+print_insn_cris_generic (bfd_vma memaddr,
+ disassemble_info *info,
+ bfd_boolean with_reg_prefix)
+{
+ int nbytes;
+ unsigned int insn;
+ const struct cris_opcode *matchedp;
+ int advance = 0;
+ struct cris_disasm_data *disdata
+ = (struct cris_disasm_data *) info->private_data;
+
+ /* No instruction will be disassembled as longer than this number of
+ bytes; stacked prefixes will not be expanded. */
+ unsigned char buffer[MAX_BYTES_PER_CRIS_INSN];
+ unsigned char *bufp;
+ int status = 0;
+ bfd_vma addr;
+
+ /* There will be an "out of range" error after the last instruction.
+ Reading pairs of bytes in decreasing number, we hope that we will get
+ at least the amount that we will consume.
+
+ If we can't get any data, or we do not get enough data, we print
+ the error message. */
+
+ for (nbytes = MAX_BYTES_PER_CRIS_INSN; nbytes > 0; nbytes -= 2)
+ {
+ status = (*info->read_memory_func) (memaddr, buffer, nbytes, info);
+ if (status == 0)
+ break;
+ }
+
+ /* If we did not get all we asked for, then clear the rest.
+ Hopefully this makes a reproducible result in case of errors. */
+ if (nbytes != MAX_BYTES_PER_CRIS_INSN)
+ memset (buffer + nbytes, 0, MAX_BYTES_PER_CRIS_INSN - nbytes);
+
+ addr = memaddr;
+ bufp = buffer;
+
+ /* Set some defaults for the insn info. */
+ info->insn_info_valid = 1;
+ info->branch_delay_insns = 0;
+ info->data_size = 0;
+ info->insn_type = dis_nonbranch;
+ info->flags = 0;
+ info->target = 0;
+ info->target2 = 0;
+
+ /* If we got any data, disassemble it. */
+ if (nbytes != 0)
+ {
+ matchedp = NULL;
+
+ insn = bufp[0] + bufp[1] * 256;
+
+ /* If we're in a case-table, don't disassemble the offsets. */
+ if (TRACE_CASE && case_offset_counter != 0)
+ {
+ info->insn_type = dis_noninsn;
+ advance += 2;
+
+ /* If to print data as offsets, then shortcut here. */
+ (*info->fprintf_func) (info->stream, "case %ld%s: -> ",
+ case_offset + no_of_case_offsets
+ - case_offset_counter,
+ case_offset_counter == 1 ? "/default" :
+ "");
+
+ (*info->print_address_func) ((bfd_vma)
+ ((short) (insn)
+ + (long) (addr
+ - (no_of_case_offsets
+ - case_offset_counter)
+ * 2)), info);
+ case_offset_counter--;
+
+ /* The default case start (without a "sub" or "add") must be
+ zero. */
+ if (case_offset_counter == 0)
+ case_offset = 0;
+ }
+ else if (insn == 0)
+ {
+ /* We're often called to disassemble zeroes. While this is a
+ valid "bcc .+2" insn, it is also useless enough and enough
+ of a nuiscance that we will just output "bcc .+2" for it
+ and signal it as a noninsn. */
+ (*info->fprintf_func) (info->stream,
+ disdata->distype == cris_dis_v32
+ ? "bcc ." : "bcc .+2");
+ info->insn_type = dis_noninsn;
+ advance += 2;
+ }
+ else
+ {
+ const struct cris_opcode *prefix_opcodep = NULL;
+ unsigned char *prefix_buffer = bufp;
+ unsigned int prefix_insn = insn;
+ int prefix_size = 0;
+
+ matchedp = get_opcode_entry (insn, NO_CRIS_PREFIX, disdata);
+
+ /* Check if we're supposed to write out prefixes as address
+ modes and if this was a prefix. */
+ if (matchedp != NULL && PARSE_PREFIX && matchedp->args[0] == 'p')
+ {
+ /* If it's a prefix, put it into the prefix vars and get the
+ main insn. */
+ prefix_size = bytes_to_skip (prefix_insn, matchedp,
+ disdata->distype, NULL);
+ prefix_opcodep = matchedp;
+
+ insn = bufp[prefix_size] + bufp[prefix_size + 1] * 256;
+ matchedp = get_opcode_entry (insn, prefix_insn, disdata);
+
+ if (matchedp != NULL)
+ {
+ addr += prefix_size;
+ bufp += prefix_size;
+ advance += prefix_size;
+ }
+ else
+ {
+ /* The "main" insn wasn't valid, at least not when
+ prefixed. Put back things enough to output the
+ prefix insn only, as a normal insn. */
+ matchedp = prefix_opcodep;
+ insn = prefix_insn;
+ prefix_opcodep = NULL;
+ }
+ }
+
+ if (matchedp == NULL)
+ {
+ (*info->fprintf_func) (info->stream, "??0x%x", insn);
+ advance += 2;
+
+ info->insn_type = dis_noninsn;
+ }
+ else
+ {
+ advance
+ += bytes_to_skip (insn, matchedp, disdata->distype,
+ prefix_opcodep);
+
+ /* The info_type and assorted fields will be set according
+ to the operands. */
+ print_with_operands (matchedp, insn, bufp, addr, info,
+ prefix_opcodep, prefix_insn,
+ prefix_buffer, with_reg_prefix);
+ }
+ }
+ }
+ else
+ info->insn_type = dis_noninsn;
+
+ /* If we read less than MAX_BYTES_PER_CRIS_INSN, i.e. we got an error
+ status when reading that much, and the insn decoding indicated a
+ length exceeding what we read, there is an error. */
+ if (status != 0 && (nbytes == 0 || advance > nbytes))
+ {
+ (*info->memory_error_func) (status, memaddr, info);
+ return -1;
+ }
+
+ /* Max supported insn size with one folded prefix insn. */
+ info->bytes_per_line = MAX_BYTES_PER_CRIS_INSN;
+
+ /* I would like to set this to a fixed value larger than the actual
+ number of bytes to print in order to avoid spaces between bytes,
+ but objdump.c (2.9.1) does not like that, so we print 16-bit
+ chunks, which is the next choice. */
+ info->bytes_per_chunk = 2;
+
+ /* Printing bytes in order of increasing addresses makes sense,
+ especially on a little-endian target.
+ This is completely the opposite of what you think; setting this to
+ BFD_ENDIAN_LITTLE will print bytes in order N..0 rather than the 0..N
+ we want. */
+ info->display_endian = BFD_ENDIAN_BIG;
+
+ return advance;
+}
+
+/* Disassemble, prefixing register names with `$'. CRIS v0..v10. */
+#if 0
+static int
+print_insn_cris_with_register_prefix (bfd_vma vma,
+ disassemble_info *info)
+{
+ if (info->private_data == NULL
+ && !cris_parse_disassembler_options (info, cris_dis_v0_v10))
+ return -1;
+ return print_insn_cris_generic (vma, info, TRUE);
+}
+#endif
+/* Disassemble, prefixing register names with `$'. CRIS v32. */
+
+static int
+print_insn_crisv32_with_register_prefix (bfd_vma vma,
+ disassemble_info *info)
+{
+ if (info->private_data == NULL
+ && !cris_parse_disassembler_options (info, cris_dis_v32))
+ return -1;
+ return print_insn_cris_generic (vma, info, TRUE);
+}
+
+#if 0
+/* Disassemble, prefixing register names with `$'.
+ Common v10 and v32 subset. */
+
+static int
+print_insn_crisv10_v32_with_register_prefix (bfd_vma vma,
+ disassemble_info *info)
+{
+ if (info->private_data == NULL
+ && !cris_parse_disassembler_options (info, cris_dis_common_v10_v32))
+ return -1;
+ return print_insn_cris_generic (vma, info, TRUE);
+}
+
+/* Disassemble, no prefixes on register names. CRIS v0..v10. */
+
+static int
+print_insn_cris_without_register_prefix (bfd_vma vma,
+ disassemble_info *info)
+{
+ if (info->private_data == NULL
+ && !cris_parse_disassembler_options (info, cris_dis_v0_v10))
+ return -1;
+ return print_insn_cris_generic (vma, info, FALSE);
+}
+
+/* Disassemble, no prefixes on register names. CRIS v32. */
+
+static int
+print_insn_crisv32_without_register_prefix (bfd_vma vma,
+ disassemble_info *info)
+{
+ if (info->private_data == NULL
+ && !cris_parse_disassembler_options (info, cris_dis_v32))
+ return -1;
+ return print_insn_cris_generic (vma, info, FALSE);
+}
+
+/* Disassemble, no prefixes on register names.
+ Common v10 and v32 subset. */
+
+static int
+print_insn_crisv10_v32_without_register_prefix (bfd_vma vma,
+ disassemble_info *info)
+{
+ if (info->private_data == NULL
+ && !cris_parse_disassembler_options (info, cris_dis_common_v10_v32))
+ return -1;
+ return print_insn_cris_generic (vma, info, FALSE);
+}
+#endif
+
+int
+print_insn_crisv32 (bfd_vma vma,
+ disassemble_info *info)
+{
+ return print_insn_crisv32_with_register_prefix(vma, info);
+}
+
+/* Return a disassembler-function that prints registers with a `$' prefix,
+ or one that prints registers without a prefix.
+ FIXME: We should improve the solution to avoid the multitude of
+ functions seen above. */
+#if 0
+disassembler_ftype
+cris_get_disassembler (bfd *abfd)
+{
+ /* If there's no bfd in sight, we return what is valid as input in all
+ contexts if fed back to the assembler: disassembly *with* register
+ prefix. Unfortunately this will be totally wrong for v32. */
+ if (abfd == NULL)
+ return print_insn_cris_with_register_prefix;
+
+ if (bfd_get_symbol_leading_char (abfd) == 0)
+ {
+ if (bfd_get_mach (abfd) == bfd_mach_cris_v32)
+ return print_insn_crisv32_with_register_prefix;
+ if (bfd_get_mach (abfd) == bfd_mach_cris_v10_v32)
+ return print_insn_crisv10_v32_with_register_prefix;
+
+ /* We default to v10. This may be specifically specified in the
+ bfd mach, but is also the default setting. */
+ return print_insn_cris_with_register_prefix;
+ }
+
+ if (bfd_get_mach (abfd) == bfd_mach_cris_v32)
+ return print_insn_crisv32_without_register_prefix;
+ if (bfd_get_mach (abfd) == bfd_mach_cris_v10_v32)
+ return print_insn_crisv10_v32_without_register_prefix;
+ return print_insn_cris_without_register_prefix;
+}
+#endif
+/* Local variables:
+ eval: (c-set-style "gnu")
+ indent-tabs-mode: t
+ End: */
Modified: trunk/src/host/qemu-neo1973/darwin-user/main.c
===================================================================
--- trunk/src/host/qemu-neo1973/darwin-user/main.c 2007-10-29 20:40:05 UTC (rev 3302)
+++ trunk/src/host/qemu-neo1973/darwin-user/main.c 2007-10-29 21:14:04 UTC (rev 3303)
@@ -124,47 +124,47 @@
return cpu_ppc_get_tb(env) >> 32;
}
-static void cpu_ppc_store_tb (CPUState *env, uint64_t value)
+uint32_t cpu_ppc_load_atbl (CPUState *env)
{
- /* TO FIX */
+ return cpu_ppc_get_tb(env) & 0xFFFFFFFF;
}
-void cpu_ppc_store_tbu (CPUState *env, uint32_t value)
+uint32_t cpu_ppc_load_atbu (CPUState *env)
{
- cpu_ppc_store_tb(env, ((uint64_t)value << 32) | cpu_ppc_load_tbl(env));
+ return cpu_ppc_get_tb(env) >> 32;
}
-void cpu_ppc_store_tbl (CPUState *env, uint32_t value)
+uint32_t cpu_ppc601_load_rtcu (CPUState *env)
{
- cpu_ppc_store_tb(env, ((uint64_t)cpu_ppc_load_tbl(env) << 32) | value);
+ cpu_ppc_load_tbu(env);
}
-uint32_t cpu_ppc_load_decr (CPUState *env)
+uint32_t cpu_ppc601_load_rtcl (CPUState *env)
{
- /* TO FIX */
- return -1;
+ return cpu_ppc_load_tbl(env) & 0x3FFFFF80;
}
-void cpu_ppc_store_decr (CPUState *env, uint32_t value)
+/* XXX: to be fixed */
+int ppc_dcr_read (ppc_dcr_t *dcr_env, int dcrn, target_ulong *valp)
{
- /* TO FIX */
+ return -1;
}
-void cpu_ppc601_store_rtcu (CPUState *env, uint32_t value)
+int ppc_dcr_write (ppc_dcr_t *dcr_env, int dcrn, target_ulong val)
{
- cpu_ppc_store_tbu( env, value );
+ return -1;
}
-uint32_t cpu_ppc601_load_rtcu (CPUState *env)
-{
- cpu_ppc_load_tbu(env);
-}
+#define EXCP_DUMP(env, fmt, args...) \
+do { \
+ fprintf(stderr, fmt , ##args); \
+ cpu_dump_state(env, stderr, fprintf, 0); \
+ if (loglevel != 0) { \
+ fprintf(logfile, fmt , ##args); \
+ cpu_dump_state(env, logfile, fprintf, 0); \
+ } \
+} while (0)
-uint32_t cpu_ppc601_load_rtcl (CPUState *env)
-{
- return cpu_ppc_load_tbl(env) & 0x3FFFFF80;
-}
-
void cpu_loop(CPUPPCState *env)
{
int trapnr;
@@ -173,271 +173,363 @@
for(;;) {
trapnr = cpu_ppc_exec(env);
- if (trapnr != EXCP_SYSCALL_USER && trapnr != EXCP_BRANCH &&
- trapnr != EXCP_TRACE) {
- if (loglevel > 0) {
- cpu_dump_state(env, logfile, fprintf, 0);
- }
- }
switch(trapnr) {
- case EXCP_NONE:
+ case POWERPC_EXCP_NONE:
+ /* Just go on */
break;
- case EXCP_SYSCALL_USER:
- /* system call */
- if(((int)env->gpr[0]) <= SYS_MAXSYSCALL && ((int)env->gpr[0])>0)
- ret = do_unix_syscall(env, env->gpr[0]/*, env->gpr[3], env->gpr[4],
- env->gpr[5], env->gpr[6], env->gpr[7],
- env->gpr[8], env->gpr[9], env->gpr[10]*/);
- else if(((int)env->gpr[0])<0)
- ret = do_mach_syscall(env, env->gpr[0], env->gpr[3], env->gpr[4],
- env->gpr[5], env->gpr[6], env->gpr[7],
- env->gpr[8], env->gpr[9], env->gpr[10]);
- else
- ret = do_thread_syscall(env, env->gpr[0], env->gpr[3], env->gpr[4],
- env->gpr[5], env->gpr[6], env->gpr[7],
- env->gpr[8], env->gpr[9], env->gpr[10]);
-
- /* Unix syscall error signaling */
- if(((int)env->gpr[0]) <= SYS_MAXSYSCALL && ((int)env->gpr[0])>0)
- {
- if( (int)ret < 0 )
- env->nip += 0;
- else
- env->nip += 4;
- }
-
- /* Return value */
- env->gpr[3] = ret;
+ case POWERPC_EXCP_CRITICAL: /* Critical input */
+ cpu_abort(env, "Critical interrupt while in user mode. "
+ "Aborting\n");
break;
- case EXCP_RESET:
- /* Should not happen ! */
- fprintf(stderr, "RESET asked... Stop emulation\n");
- if (loglevel)
- fprintf(logfile, "RESET asked... Stop emulation\n");
- abort();
- case EXCP_MACHINE_CHECK:
- fprintf(stderr, "Machine check exeption... Stop emulation\n");
- if (loglevel)
- fprintf(logfile, "RESET asked... Stop emulation\n");
- info.si_signo = SIGBUS;
- info.si_errno = 0;
- info.si_code = BUS_OBJERR;
- info.si_addr = (void*)(env->nip - 4);
- queue_signal(info.si_signo, &info);
- case EXCP_DSI:
+ case POWERPC_EXCP_MCHECK: /* Machine check exception */
+ cpu_abort(env, "Machine check exception while in user mode. "
+ "Aborting\n");
+ break;
+ case POWERPC_EXCP_DSI: /* Data storage exception */
#ifndef DAR
/* To deal with multiple qemu header version as host for the darwin-user code */
# define DAR SPR_DAR
#endif
- fprintf(stderr, "Invalid data memory access: 0x%08x\n", env->spr[DAR]);
- if (loglevel) {
- fprintf(logfile, "Invalid data memory access: 0x%08x\n",
- env->spr[DAR]);
- }
+ EXCP_DUMP(env, "Invalid data memory access: 0x" ADDRX "\n",
+ env->spr[SPR_DAR]);
/* Handle this via the gdb */
gdb_handlesig (env, SIGSEGV);
info.si_addr = (void*)env->nip;
queue_signal(info.si_signo, &info);
break;
- case EXCP_ISI:
- fprintf(stderr, "Invalid instruction fetch\n");
- if (loglevel)
- fprintf(logfile, "Invalid instruction fetch\n");
+ case POWERPC_EXCP_ISI: /* Instruction storage exception */
+ EXCP_DUMP(env, "Invalid instruction fetch: 0x\n" ADDRX "\n",
+ env->spr[SPR_DAR]);
/* Handle this via the gdb */
gdb_handlesig (env, SIGSEGV);
info.si_addr = (void*)(env->nip - 4);
queue_signal(info.si_signo, &info);
break;
- case EXCP_EXTERNAL:
- /* Should not happen ! */
- fprintf(stderr, "External interruption... Stop emulation\n");
- if (loglevel)
- fprintf(logfile, "External interruption... Stop emulation\n");
- abort();
- case EXCP_ALIGN:
- fprintf(stderr, "Invalid unaligned memory access\n");
- if (loglevel)
- fprintf(logfile, "Invalid unaligned memory access\n");
- info.si_signo = SIGBUS;
+ case POWERPC_EXCP_EXTERNAL: /* External input */
+ cpu_abort(env, "External interrupt while in user mode. "
+ "Aborting\n");
+ break;
+ case POWERPC_EXCP_ALIGN: /* Alignment exception */
+ EXCP_DUMP(env, "Unaligned memory access\n");
info.si_errno = 0;
info.si_code = BUS_ADRALN;
info.si_addr = (void*)(env->nip - 4);
queue_signal(info.si_signo, &info);
break;
- case EXCP_PROGRAM:
+ case POWERPC_EXCP_PROGRAM: /* Program exception */
+ /* XXX: check this */
switch (env->error_code & ~0xF) {
- case EXCP_FP:
- fprintf(stderr, "Program exception\n");
- if (loglevel)
- fprintf(logfile, "Program exception\n");
- /* Set FX */
- env->fpscr[7] |= 0x8;
- /* Finally, update FEX */
- if ((((env->fpscr[7] & 0x3) << 3) | (env->fpscr[6] >> 1)) &
- ((env->fpscr[1] << 1) | (env->fpscr[0] >> 3)))
- env->fpscr[7] |= 0x4;
- info.si_signo = SIGFPE;
- info.si_errno = 0;
- switch (env->error_code & 0xF) {
- case EXCP_FP_OX:
- info.si_code = FPE_FLTOVF;
- break;
- case EXCP_FP_UX:
- info.si_code = FPE_FLTUND;
- break;
- case EXCP_FP_ZX:
- case EXCP_FP_VXZDZ:
- info.si_code = FPE_FLTDIV;
- break;
- case EXCP_FP_XX:
- info.si_code = FPE_FLTRES;
- break;
- case EXCP_FP_VXSOFT:
- info.si_code = FPE_FLTINV;
- break;
- case EXCP_FP_VXNAN:
- case EXCP_FP_VXISI:
- case EXCP_FP_VXIDI:
- case EXCP_FP_VXIMZ:
- case EXCP_FP_VXVC:
- case EXCP_FP_VXSQRT:
- case EXCP_FP_VXCVI:
- info.si_code = FPE_FLTSUB;
- break;
- default:
- fprintf(stderr, "Unknown floating point exception "
- "(%02x)\n", env->error_code);
- if (loglevel) {
- fprintf(logfile, "Unknown floating point exception "
- "(%02x)\n", env->error_code & 0xF);
- }
- }
- break;
- case EXCP_INVAL:
- fprintf(stderr, "Invalid instruction\n");
- if (loglevel)
- fprintf(logfile, "Invalid instruction\n");
- info.si_signo = SIGILL;
- info.si_errno = 0;
- switch (env->error_code & 0xF) {
- case EXCP_INVAL_INVAL:
- info.si_code = ILL_ILLOPC;
- break;
- case EXCP_INVAL_LSWX:
- info.si_code = ILL_ILLOPN;
- break;
- case EXCP_INVAL_SPR:
- info.si_code = ILL_PRVREG;
- break;
- case EXCP_INVAL_FP:
- info.si_code = ILL_COPROC;
- break;
- default:
- fprintf(stderr, "Unknown invalid operation (%02x)\n",
- env->error_code & 0xF);
- if (loglevel) {
- fprintf(logfile, "Unknown invalid operation (%02x)\n",
- env->error_code & 0xF);
- }
- info.si_code = ILL_ILLADR;
- break;
- }
- /* Handle this via the gdb */
- gdb_handlesig (env, SIGSEGV);
+ case POWERPC_EXCP_FP:
+ EXCP_DUMP(env, "Floating point program exception\n");
+ /* Set FX */
+ info.si_signo = SIGFPE;
+ info.si_errno = 0;
+ switch (env->error_code & 0xF) {
+ case POWERPC_EXCP_FP_OX:
+ info.si_code = FPE_FLTOVF;
break;
- case EXCP_PRIV:
- fprintf(stderr, "Privilege violation\n");
- if (loglevel)
- fprintf(logfile, "Privilege violation\n");
- info.si_signo = SIGILL;
- info.si_errno = 0;
- switch (env->error_code & 0xF) {
- case EXCP_PRIV_OPC:
- info.si_code = ILL_PRVOPC;
- break;
- case EXCP_PRIV_REG:
- info.si_code = ILL_PRVREG;
- break;
- default:
- fprintf(stderr, "Unknown privilege violation (%02x)\n",
- env->error_code & 0xF);
- info.si_code = ILL_PRVOPC;
- break;
- }
- break;
- case EXCP_TRAP:
- fprintf(stderr, "Tried to call a TRAP\n");
- if (loglevel)
- fprintf(logfile, "Tried to call a TRAP\n");
- abort();
+ case POWERPC_EXCP_FP_UX:
+ info.si_code = FPE_FLTUND;
+ break;
+ case POWERPC_EXCP_FP_ZX:
+ case POWERPC_EXCP_FP_VXZDZ:
+ info.si_code = FPE_FLTDIV;
+ break;
+ case POWERPC_EXCP_FP_XX:
+ info.si_code = FPE_FLTRES;
+ break;
+ case POWERPC_EXCP_FP_VXSOFT:
+ info.si_code = FPE_FLTINV;
+ break;
+ case POWERPC_EXCP_FP_VXSNAN:
+ case POWERPC_EXCP_FP_VXISI:
+ case POWERPC_EXCP_FP_VXIDI:
+ case POWERPC_EXCP_FP_VXIMZ:
+ case POWERPC_EXCP_FP_VXVC:
+ case POWERPC_EXCP_FP_VXSQRT:
+ case POWERPC_EXCP_FP_VXCVI:
+ info.si_code = FPE_FLTSUB;
+ break;
default:
- /* Should not happen ! */
- fprintf(stderr, "Unknown program exception (%02x)\n",
- env->error_code);
- if (loglevel) {
- fprintf(logfile, "Unknwon program exception (%02x)\n",
- env->error_code);
- }
- abort();
+ EXCP_DUMP(env, "Unknown floating point exception (%02x)\n",
+ env->error_code);
+ break;
+ }
+ break;
+ case POWERPC_EXCP_INVAL:
+ EXCP_DUMP(env, "Invalid instruction\n");
+ info.si_signo = SIGILL;
+ info.si_errno = 0;
+ switch (env->error_code & 0xF) {
+ case POWERPC_EXCP_INVAL_INVAL:
+ info.si_code = ILL_ILLOPC;
+ break;
+ case POWERPC_EXCP_INVAL_LSWX:
+ info.si_code = ILL_ILLOPN;
+ break;
+ case POWERPC_EXCP_INVAL_SPR:
+ info.si_code = ILL_PRVREG;
+ break;
+ case POWERPC_EXCP_INVAL_FP:
+ info.si_code = ILL_COPROC;
+ break;
+ default:
+ EXCP_DUMP(env, "Unknown invalid operation (%02x)\n",
+ env->error_code & 0xF);
+ info.si_code = ILL_ILLADR;
+ break;
+ }
+ /* Handle this via the gdb */
+ gdb_handlesig (env, SIGSEGV);
+ break;
+ case POWERPC_EXCP_PRIV:
+ EXCP_DUMP(env, "Privilege violation\n");
+ info.si_signo = SIGILL;
+ info.si_errno = 0;
+ switch (env->error_code & 0xF) {
+ case POWERPC_EXCP_PRIV_OPC:
+ info.si_code = ILL_PRVOPC;
+ break;
+ case POWERPC_EXCP_PRIV_REG:
+ info.si_code = ILL_PRVREG;
+ break;
+ default:
+ EXCP_DUMP(env, "Unknown privilege violation (%02x)\n",
+ env->error_code & 0xF);
+ info.si_code = ILL_PRVOPC;
+ break;
+ }
+ break;
+ case POWERPC_EXCP_TRAP:
+ cpu_abort(env, "Tried to call a TRAP\n");
+ break;
+ default:
+ /* Should not happen ! */
+ cpu_abort(env, "Unknown program exception (%02x)\n",
+ env->error_code);
+ break;
}
info.si_addr = (void*)(env->nip - 4);
queue_signal(info.si_signo, &info);
break;
- case EXCP_NO_FP:
- fprintf(stderr, "No floating point allowed\n");
- if (loglevel)
- fprintf(logfile, "No floating point allowed\n");
- info.si_signo = SIGILL;
+ case POWERPC_EXCP_FPU: /* Floating-point unavailable exception */
+ EXCP_DUMP(env, "No floating point allowed\n");
+ info.si_signo = SIGILL;
info.si_errno = 0;
info.si_code = ILL_COPROC;
info.si_addr = (void*)(env->nip - 4);
queue_signal(info.si_signo, &info);
break;
- case EXCP_DECR:
- /* Should not happen ! */
- fprintf(stderr, "Decrementer exception\n");
- if (loglevel)
- fprintf(logfile, "Decrementer exception\n");
- abort();
- case EXCP_TRACE:
- /* Pass to gdb: we use this to trace execution */
+ case POWERPC_EXCP_SYSCALL: /* System call exception */
+ cpu_abort(env, "Syscall exception while in user mode. "
+ "Aborting\n");
+ break;
+ case POWERPC_EXCP_APU: /* Auxiliary processor unavailable */
+ EXCP_DUMP(env, "No APU instruction allowed\n");
+ info.si_signo = SIGILL;
+ info.si_errno = 0;
+ info.si_code = ILL_COPROC;
+ info.si_addr = (void*)(env->nip - 4);
+ queue_signal(info.si_signo, &info);
+ break;
+ case POWERPC_EXCP_DECR: /* Decrementer exception */
+ cpu_abort(env, "Decrementer interrupt while in user mode. "
+ "Aborting\n");
+ break;
+ case POWERPC_EXCP_FIT: /* Fixed-interval timer interrupt */
+ cpu_abort(env, "Fix interval timer interrupt while in user mode. "
+ "Aborting\n");
+ break;
+ case POWERPC_EXCP_WDT: /* Watchdog timer interrupt */
+ cpu_abort(env, "Watchdog timer interrupt while in user mode. "
+ "Aborting\n");
+ break;
+ case POWERPC_EXCP_DTLB: /* Data TLB error */
+ cpu_abort(env, "Data TLB exception while in user mode. "
+ "Aborting\n");
+ break;
+ case POWERPC_EXCP_ITLB: /* Instruction TLB error */
+ cpu_abort(env, "Instruction TLB exception while in user mode. "
+ "Aborting\n");
+ break;
+ case POWERPC_EXCP_DEBUG: /* Debug interrupt */
gdb_handlesig (env, SIGTRAP);
break;
- case EXCP_FP_ASSIST:
- /* Should not happen ! */
- fprintf(stderr, "Floating point assist exception\n");
- if (loglevel)
- fprintf(logfile, "Floating point assist exception\n");
- abort();
- case EXCP_MTMSR:
- /* We reloaded the msr, just go on */
- if (msr_pr == 0) {
- fprintf(stderr, "Tried to go into supervisor mode !\n");
- if (loglevel)
- fprintf(logfile, "Tried to go into supervisor mode !\n");
- abort();
+#if defined(TARGET_PPCEMB)
+ case POWERPC_EXCP_SPEU: /* SPE/embedded floating-point unavail. */
+ EXCP_DUMP(env, "No SPE/floating-point instruction allowed\n");
+ info.si_signo = SIGILL;
+ info.si_errno = 0;
+ info.si_code = ILL_COPROC;
+ info.si_addr = (void*)(env->nip - 4);
+ queue_signal(info.si_signo, &info);
+ break;
+ case POWERPC_EXCP_EFPDI: /* Embedded floating-point data IRQ */
+ cpu_abort(env, "Embedded floating-point data IRQ not handled\n");
+ break;
+ case POWERPC_EXCP_EFPRI: /* Embedded floating-point round IRQ */
+ cpu_abort(env, "Embedded floating-point round IRQ not handled\n");
+ break;
+ case POWERPC_EXCP_EPERFM: /* Embedded performance monitor IRQ */
+ cpu_abort(env, "Performance monitor exception not handled\n");
+ break;
+ case POWERPC_EXCP_DOORI: /* Embedded doorbell interrupt */
+ cpu_abort(env, "Doorbell interrupt while in user mode. "
+ "Aborting\n");
+ break;
+ case POWERPC_EXCP_DOORCI: /* Embedded doorbell critical interrupt */
+ cpu_abort(env, "Doorbell critical interrupt while in user mode. "
+ "Aborting\n");
+ break;
+#endif /* defined(TARGET_PPCEMB) */
+ case POWERPC_EXCP_RESET: /* System reset exception */
+ cpu_abort(env, "Reset interrupt while in user mode. "
+ "Aborting\n");
+ break;
+#if defined(TARGET_PPC64) /* PowerPC 64 */
+ case POWERPC_EXCP_DSEG: /* Data segment exception */
+ cpu_abort(env, "Data segment exception while in user mode. "
+ "Aborting\n");
+ break;
+ case POWERPC_EXCP_ISEG: /* Instruction segment exception */
+ cpu_abort(env, "Instruction segment exception "
+ "while in user mode. Aborting\n");
+ break;
+#endif /* defined(TARGET_PPC64) */
+#if defined(TARGET_PPC64H) /* PowerPC 64 with hypervisor mode support */
+ case POWERPC_EXCP_HDECR: /* Hypervisor decrementer exception */
+ cpu_abort(env, "Hypervisor decrementer interrupt "
+ "while in user mode. Aborting\n");
+ break;
+#endif /* defined(TARGET_PPC64H) */
+ case POWERPC_EXCP_TRACE: /* Trace exception */
+ /* Nothing to do:
+ * we use this exception to emulate step-by-step execution mode.
+ */
+ break;
+#if defined(TARGET_PPC64H) /* PowerPC 64 with hypervisor mode support */
+ case POWERPC_EXCP_HDSI: /* Hypervisor data storage exception */
+ cpu_abort(env, "Hypervisor data storage exception "
+ "while in user mode. Aborting\n");
+ break;
+ case POWERPC_EXCP_HISI: /* Hypervisor instruction storage excp */
+ cpu_abort(env, "Hypervisor instruction storage exception "
+ "while in user mode. Aborting\n");
+ break;
+ case POWERPC_EXCP_HDSEG: /* Hypervisor data segment exception */
+ cpu_abort(env, "Hypervisor data segment exception "
+ "while in user mode. Aborting\n");
+ break;
+ case POWERPC_EXCP_HISEG: /* Hypervisor instruction segment excp */
+ cpu_abort(env, "Hypervisor instruction segment exception "
+ "while in user mode. Aborting\n");
+ break;
+#endif /* defined(TARGET_PPC64H) */
+ case POWERPC_EXCP_VPU: /* Vector unavailable exception */
+ EXCP_DUMP(env, "No Altivec instructions allowed\n");
+ info.si_signo = SIGILL;
+ info.si_errno = 0;
+ info.si_code = ILL_COPROC;
+ info.si_addr = (void*)(env->nip - 4);
+ queue_signal(info.si_signo, &info);
+ break;
+ case POWERPC_EXCP_PIT: /* Programmable interval timer IRQ */
+ cpu_abort(env, "Programable interval timer interrupt "
+ "while in user mode. Aborting\n");
+ break;
+ case POWERPC_EXCP_IO: /* IO error exception */
+ cpu_abort(env, "IO error exception while in user mode. "
+ "Aborting\n");
+ break;
+ case POWERPC_EXCP_RUNM: /* Run mode exception */
+ cpu_abort(env, "Run mode exception while in user mode. "
+ "Aborting\n");
+ break;
+ case POWERPC_EXCP_EMUL: /* Emulation trap exception */
+ cpu_abort(env, "Emulation trap exception not handled\n");
+ break;
+ case POWERPC_EXCP_IFTLB: /* Instruction fetch TLB error */
+ cpu_abort(env, "Instruction fetch TLB exception "
+ "while in user-mode. Aborting");
+ break;
+ case POWERPC_EXCP_DLTLB: /* Data load TLB miss */
+ cpu_abort(env, "Data load TLB exception while in user-mode. "
+ "Aborting");
+ break;
+ case POWERPC_EXCP_DSTLB: /* Data store TLB miss */
+ cpu_abort(env, "Data store TLB exception while in user-mode. "
+ "Aborting");
+ break;
+ case POWERPC_EXCP_FPA: /* Floating-point assist exception */
+ cpu_abort(env, "Floating-point assist exception not handled\n");
+ break;
+ case POWERPC_EXCP_IABR: /* Instruction address breakpoint */
+ cpu_abort(env, "Instruction address breakpoint exception "
+ "not handled\n");
+ break;
+ case POWERPC_EXCP_SMI: /* System management interrupt */
+ cpu_abort(env, "System management interrupt while in user mode. "
+ "Aborting\n");
+ break;
+ case POWERPC_EXCP_THERM: /* Thermal interrupt */
+ cpu_abort(env, "Thermal interrupt interrupt while in user mode. "
+ "Aborting\n");
+ break;
+ case POWERPC_EXCP_PERFM: /* Embedded performance monitor IRQ */
+ cpu_abort(env, "Performance monitor exception not handled\n");
+ break;
+ case POWERPC_EXCP_VPUA: /* Vector assist exception */
+ cpu_abort(env, "Vector assist exception not handled\n");
+ break;
+ case POWERPC_EXCP_SOFTP: /* Soft patch exception */
+ cpu_abort(env, "Soft patch exception not handled\n");
+ break;
+ case POWERPC_EXCP_MAINT: /* Maintenance exception */
+ cpu_abort(env, "Maintenance exception while in user mode. "
+ "Aborting\n");
+ break;
+ case POWERPC_EXCP_STOP: /* stop translation */
+ /* We did invalidate the instruction cache. Go on */
+ break;
+ case POWERPC_EXCP_BRANCH: /* branch instruction: */
+ /* We just stopped because of a branch. Go on */
+ break;
+ case POWERPC_EXCP_SYSCALL_USER:
+ /* system call in user-mode emulation */
+ /* system call */
+ if(((int)env->gpr[0]) <= SYS_MAXSYSCALL && ((int)env->gpr[0])>0)
+ ret = do_unix_syscall(env, env->gpr[0]/*, env->gpr[3], env->gpr[4],
+ env->gpr[5], env->gpr[6], env->gpr[7],
+ env->gpr[8], env->gpr[9], env->gpr[10]*/);
+ else if(((int)env->gpr[0])<0)
+ ret = do_mach_syscall(env, env->gpr[0], env->gpr[3], env->gpr[4],
+ env->gpr[5], env->gpr[6], env->gpr[7],
+ env->gpr[8], env->gpr[9], env->gpr[10]);
+ else
+ ret = do_thread_syscall(env, env->gpr[0], env->gpr[3], env->gpr[4],
+ env->gpr[5], env->gpr[6], env->gpr[7],
+ env->gpr[8], env->gpr[9], env->gpr[10]);
+
+ /* Unix syscall error signaling */
+ if(((int)env->gpr[0]) <= SYS_MAXSYSCALL && ((int)env->gpr[0])>0)
+ {
+ if( (int)ret < 0 )
+ env->nip += 0;
+ else
+ env->nip += 4;
}
+
+ /* Return value */
+ env->gpr[3] = ret;
break;
- case EXCP_BRANCH:
- /* We stopped because of a jump... */
- break;
case EXCP_INTERRUPT:
- /* Don't know why this should ever happen... */
- fprintf(stderr, "EXCP_INTERRUPT\n");
+ /* just indicate that signals should be handled asap */
break;
- case EXCP_DEBUG:
- gdb_handlesig (env, SIGTRAP);
+ default:
+ cpu_abort(env, "Unknown exception 0x%d. Aborting\n", trapnr);
break;
- default:
- fprintf(stderr, "qemu: unhandled CPU exception 0x%x - aborting\n",
- trapnr);
- if (loglevel) {
- fprintf(logfile, "qemu: unhandled CPU exception 0x%02x - "
- "0x%02x - aborting\n", trapnr, env->error_code);
- }
- abort();
}
process_pending_signals(env);
}
Modified: trunk/src/host/qemu-neo1973/dis-asm.h
===================================================================
--- trunk/src/host/qemu-neo1973/dis-asm.h 2007-10-29 20:40:05 UTC (rev 3302)
+++ trunk/src/host/qemu-neo1973/dis-asm.h 2007-10-29 21:14:04 UTC (rev 3303)
@@ -200,6 +200,10 @@
#define bfd_mach_m32r 0 /* backwards compatibility */
bfd_arch_mn10200, /* Matsushita MN10200 */
bfd_arch_mn10300, /* Matsushita MN10300 */
+ bfd_arch_cris, /* Axis CRIS */
+#define bfd_mach_cris_v0_v10 255
+#define bfd_mach_cris_v32 32
+#define bfd_mach_cris_v10_v32 1032
bfd_arch_last
};
#define bfd_mach_s390_31 31
@@ -382,6 +386,7 @@
extern int print_insn_ppc PARAMS ((bfd_vma, disassemble_info*));
extern int print_insn_alpha PARAMS ((bfd_vma, disassemble_info*));
extern int print_insn_s390 PARAMS ((bfd_vma, disassemble_info*));
+extern int print_insn_crisv32 PARAMS ((bfd_vma, disassemble_info*));
#if 0
/* Fetch the disassembler for a given BFD, if that support is available. */
Modified: trunk/src/host/qemu-neo1973/disas.c
===================================================================
--- trunk/src/host/qemu-neo1973/disas.c 2007-10-29 20:40:05 UTC (rev 3302)
+++ trunk/src/host/qemu-neo1973/disas.c 2007-10-29 21:14:04 UTC (rev 3303)
@@ -178,13 +178,18 @@
disasm_info.mach = bfd_mach_sparc_v9b;
#endif
#elif defined(TARGET_PPC)
- if (flags)
+ if (flags >> 16)
disasm_info.endian = BFD_ENDIAN_LITTLE;
+ if (flags & 0xFFFF) {
+ /* If we have a precise definitions of the instructions set, use it */
+ disasm_info.mach = flags & 0xFFFF;
+ } else {
#ifdef TARGET_PPC64
- disasm_info.mach = bfd_mach_ppc64;
+ disasm_info.mach = bfd_mach_ppc64;
#else
- disasm_info.mach = bfd_mach_ppc;
+ disasm_info.mach = bfd_mach_ppc;
#endif
+ }
print_insn = print_insn_ppc;
#elif defined(TARGET_M68K)
print_insn = print_insn_m68k;
@@ -200,6 +205,9 @@
#elif defined(TARGET_ALPHA)
disasm_info.mach = bfd_mach_alpha;
print_insn = print_insn_alpha;
+#elif defined(TARGET_CRIS)
+ disasm_info.mach = bfd_mach_cris_v32;
+ print_insn = print_insn_crisv32;
#else
fprintf(out, "0x" TARGET_FMT_lx
": Asm output not supported on this arch\n", code);
Deleted: trunk/src/host/qemu-neo1973/ecc.h
===================================================================
--- trunk/src/host/qemu-neo1973/ecc.h 2007-10-29 20:40:05 UTC (rev 3302)
+++ trunk/src/host/qemu-neo1973/ecc.h 2007-10-29 21:14:04 UTC (rev 3303)
@@ -1,94 +0,0 @@
-/*
- * Calculate Error-correcting Codes. Used by NAND Flash controllers
- * (not by NAND chips).
- *
- * Copyright (c) 2006 Openedhand Ltd.
- * Written by Andrzej Zaborowski <balrog at zabor.org>
- *
- * This code is licensed under the GNU GPL v2.
- */
-
-struct ecc_state_s {
- uint8_t cp; /* Column parity */
- uint16_t lp[2]; /* Line parity */
- uint16_t count;
-};
-
-/*
- * Pre-calculated 256-way 1 byte column parity. Table borrowed from Linux.
- */
-static const uint8_t nand_ecc_precalc_table[] = {
- 0x00, 0x55, 0x56, 0x03, 0x59, 0x0c, 0x0f, 0x5a,
- 0x5a, 0x0f, 0x0c, 0x59, 0x03, 0x56, 0x55, 0x00,
- 0x65, 0x30, 0x33, 0x66, 0x3c, 0x69, 0x6a, 0x3f,
- 0x3f, 0x6a, 0x69, 0x3c, 0x66, 0x33, 0x30, 0x65,
- 0x66, 0x33, 0x30, 0x65, 0x3f, 0x6a, 0x69, 0x3c,
- 0x3c, 0x69, 0x6a, 0x3f, 0x65, 0x30, 0x33, 0x66,
- 0x03, 0x56, 0x55, 0x00, 0x5a, 0x0f, 0x0c, 0x59,
- 0x59, 0x0c, 0x0f, 0x5a, 0x00, 0x55, 0x56, 0x03,
- 0x69, 0x3c, 0x3f, 0x6a, 0x30, 0x65, 0x66, 0x33,
- 0x33, 0x66, 0x65, 0x30, 0x6a, 0x3f, 0x3c, 0x69,
- 0x0c, 0x59, 0x5a, 0x0f, 0x55, 0x00, 0x03, 0x56,
- 0x56, 0x03, 0x00, 0x55, 0x0f, 0x5a, 0x59, 0x0c,
- 0x0f, 0x5a, 0x59, 0x0c, 0x56, 0x03, 0x00, 0x55,
- 0x55, 0x00, 0x03, 0x56, 0x0c, 0x59, 0x5a, 0x0f,
- 0x6a, 0x3f, 0x3c, 0x69, 0x33, 0x66, 0x65, 0x30,
- 0x30, 0x65, 0x66, 0x33, 0x69, 0x3c, 0x3f, 0x6a,
- 0x6a, 0x3f, 0x3c, 0x69, 0x33, 0x66, 0x65, 0x30,
- 0x30, 0x65, 0x66, 0x33, 0x69, 0x3c, 0x3f, 0x6a,
- 0x0f, 0x5a, 0x59, 0x0c, 0x56, 0x03, 0x00, 0x55,
- 0x55, 0x00, 0x03, 0x56, 0x0c, 0x59, 0x5a, 0x0f,
- 0x0c, 0x59, 0x5a, 0x0f, 0x55, 0x00, 0x03, 0x56,
- 0x56, 0x03, 0x00, 0x55, 0x0f, 0x5a, 0x59, 0x0c,
- 0x69, 0x3c, 0x3f, 0x6a, 0x30, 0x65, 0x66, 0x33,
- 0x33, 0x66, 0x65, 0x30, 0x6a, 0x3f, 0x3c, 0x69,
- 0x03, 0x56, 0x55, 0x00, 0x5a, 0x0f, 0x0c, 0x59,
- 0x59, 0x0c, 0x0f, 0x5a, 0x00, 0x55, 0x56, 0x03,
- 0x66, 0x33, 0x30, 0x65, 0x3f, 0x6a, 0x69, 0x3c,
- 0x3c, 0x69, 0x6a, 0x3f, 0x65, 0x30, 0x33, 0x66,
- 0x65, 0x30, 0x33, 0x66, 0x3c, 0x69, 0x6a, 0x3f,
- 0x3f, 0x6a, 0x69, 0x3c, 0x66, 0x33, 0x30, 0x65,
- 0x00, 0x55, 0x56, 0x03, 0x59, 0x0c, 0x0f, 0x5a,
- 0x5a, 0x0f, 0x0c, 0x59, 0x03, 0x56, 0x55, 0x00,
-};
-
-/* Update ECC parity count. */
-static inline uint8_t ecc_digest(struct ecc_state_s *s, uint8_t sample)
-{
- uint8_t idx = nand_ecc_precalc_table[sample];
-
- s->cp ^= idx & 0x3f;
- if (idx & 0x40) {
- s->lp[0] ^= ~s->count;
- s->lp[1] ^= s->count;
- }
- s->count ++;
-
- return sample;
-}
-
-/* Reinitialise the counters. */
-static inline void ecc_reset(struct ecc_state_s *s)
-{
- s->lp[0] = 0x0000;
- s->lp[1] = 0x0000;
- s->cp = 0x00;
- s->count = 0;
-}
-
-/* Save/restore */
-static inline void ecc_put(QEMUFile *f, struct ecc_state_s *s)
-{
- qemu_put_8s(f, &s->cp);
- qemu_put_be16s(f, &s->lp[0]);
- qemu_put_be16s(f, &s->lp[1]);
- qemu_put_be16s(f, &s->count);
-}
-
-static inline void ecc_get(QEMUFile *f, struct ecc_state_s *s)
-{
- qemu_get_8s(f, &s->cp);
- qemu_get_be16s(f, &s->lp[0]);
- qemu_get_be16s(f, &s->lp[1]);
- qemu_get_be16s(f, &s->count);
-}
Modified: trunk/src/host/qemu-neo1973/elf.h
===================================================================
--- trunk/src/host/qemu-neo1973/elf.h 2007-10-29 20:40:05 UTC (rev 3302)
+++ trunk/src/host/qemu-neo1973/elf.h 2007-10-29 21:14:04 UTC (rev 3303)
@@ -1130,6 +1130,7 @@
#define elf_note elf32_note
#define elf_shdr elf32_shdr
#define elf_sym elf32_sym
+#define elf_addr_t Elf32_Off
#ifdef ELF_USES_RELOCA
# define ELF_RELOC Elf32_Rela
@@ -1144,6 +1145,7 @@
#define elf_note elf64_note
#define elf_shdr elf64_shdr
#define elf_sym elf64_sym
+#define elf_addr_t Elf64_Off
#ifdef ELF_USES_RELOCA
# define ELF_RELOC Elf64_Rela
Modified: trunk/src/host/qemu-neo1973/elf_ops.h
===================================================================
--- trunk/src/host/qemu-neo1973/elf_ops.h 2007-10-29 20:40:05 UTC (rev 3302)
+++ trunk/src/host/qemu-neo1973/elf_ops.h 2007-10-29 21:14:04 UTC (rev 3303)
@@ -145,8 +145,8 @@
struct elfhdr ehdr;
struct elf_phdr *phdr = NULL, *ph;
int size, i, total_size;
- elf_word low = 0, high = 0;
- elf_word mem_size, addr;
+ elf_word mem_size;
+ uint64_t addr, low = 0, high = 0;
uint8_t *data = NULL;
if (read(fd, &ehdr, sizeof(ehdr)) != sizeof(ehdr))
@@ -159,7 +159,7 @@
goto fail;
if (pentry)
- *pentry = (uint64_t)ehdr.e_entry;
+ *pentry = (uint64_t)(elf_sword)ehdr.e_entry;
glue(load_symbols, SZ)(&ehdr, fd, must_swab);
@@ -206,9 +206,9 @@
}
qemu_free(phdr);
if (lowaddr)
- *lowaddr = (uint64_t)low;
+ *lowaddr = (uint64_t)(elf_sword)low;
if (highaddr)
- *highaddr = (uint64_t)high;
+ *highaddr = (uint64_t)(elf_sword)high;
return total_size;
fail:
qemu_free(data);
Modified: trunk/src/host/qemu-neo1973/exec-all.h
===================================================================
--- trunk/src/host/qemu-neo1973/exec-all.h 2007-10-29 20:40:05 UTC (rev 3302)
+++ trunk/src/host/qemu-neo1973/exec-all.h 2007-10-29 21:14:04 UTC (rev 3303)
@@ -37,6 +37,14 @@
#define unlikely(x) __builtin_expect(!!(x), 0)
#endif
+#ifndef always_inline
+#if (__GNUC__ < 3) || defined(__APPLE__)
+#define always_inline inline
+#else
+#define always_inline __attribute__ (( always_inline )) inline
+#endif
+#endif
+
#ifdef __i386__
#define REGPARM(n) __attribute((regparm(n)))
#else
@@ -109,14 +117,14 @@
void tlb_flush(CPUState *env, int flush_global);
int tlb_set_page_exec(CPUState *env, target_ulong vaddr,
target_phys_addr_t paddr, int prot,
- int is_user, int is_softmmu);
+ int mmu_idx, int is_softmmu);
static inline int tlb_set_page(CPUState *env, target_ulong vaddr,
target_phys_addr_t paddr, int prot,
- int is_user, int is_softmmu)
+ int mmu_idx, int is_softmmu)
{
if (prot & PAGE_READ)
prot |= PAGE_EXEC;
- return tlb_set_page_exec(env, vaddr, paddr, prot, is_user, is_softmmu);
+ return tlb_set_page_exec(env, vaddr, paddr, prot, mmu_idx, is_softmmu);
}
#define CODE_GEN_MAX_SIZE 65536
@@ -171,7 +179,7 @@
typedef struct TranslationBlock {
target_ulong pc; /* simulated PC corresponding to this block (EIP + CS base) */
target_ulong cs_base; /* CS base for this block */
- unsigned int flags; /* flags defining in which context the code was generated */
+ uint64_t flags; /* flags defining in which context the code was generated */
uint16_t size; /* size of target code for this block (1 <=
size <= TARGET_PAGE_SIZE) */
uint16_t cflags; /* compile flags */
@@ -554,10 +562,10 @@
#if !defined(CONFIG_USER_ONLY)
-void tlb_fill(target_ulong addr, int is_write, int is_user,
+void tlb_fill(target_ulong addr, int is_write, int mmu_idx,
void *retaddr);
-#define ACCESS_TYPE 3
+#define ACCESS_TYPE (NB_MMU_MODES + 1)
#define MEMSUFFIX _code
#define env cpu_single_env
@@ -590,41 +598,23 @@
is the offset relative to phys_ram_base */
static inline target_ulong get_phys_addr_code(CPUState *env, target_ulong addr)
{
- int is_user, index, pd;
+ int mmu_idx, index, pd;
index = (addr >> TARGET_PAGE_BITS) & (CPU_TLB_SIZE - 1);
-#if defined(TARGET_I386)
- is_user = ((env->hflags & HF_CPL_MASK) == 3);
-#elif defined (TARGET_PPC)
- is_user = msr_pr;
-#elif defined (TARGET_MIPS)
- is_user = ((env->hflags & MIPS_HFLAG_MODE) == MIPS_HFLAG_UM);
-#elif defined (TARGET_SPARC)
- is_user = (env->psrs == 0);
-#elif defined (TARGET_ARM)
- is_user = ((env->uncached_cpsr & CPSR_M) == ARM_CPU_MODE_USR);
-#elif defined (TARGET_SH4)
- is_user = ((env->sr & SR_MD) == 0);
-#elif defined (TARGET_ALPHA)
- is_user = ((env->ps >> 3) & 3);
-#elif defined (TARGET_M68K)
- is_user = ((env->sr & SR_S) == 0);
-#else
-#error unimplemented CPU
-#endif
- if (__builtin_expect(env->tlb_table[is_user][index].addr_code !=
+ mmu_idx = cpu_mmu_index(env);
+ if (__builtin_expect(env->tlb_table[mmu_idx][index].addr_code !=
(addr & TARGET_PAGE_MASK), 0)) {
ldub_code(addr);
}
- pd = env->tlb_table[is_user][index].addr_code & ~TARGET_PAGE_MASK;
+ pd = env->tlb_table[mmu_idx][index].addr_code & ~TARGET_PAGE_MASK;
if (pd > IO_MEM_ROM && !(pd & IO_MEM_ROMD)) {
-#ifdef TARGET_SPARC
+#if defined(TARGET_SPARC) || defined(TARGET_MIPS)
do_unassigned_access(addr, 0, 1, 0);
#else
cpu_abort(env, "Trying to execute code outside RAM or ROM at 0x" TARGET_FMT_lx "\n", addr);
#endif
}
- return addr + env->tlb_table[is_user][index].addend - (unsigned long)phys_ram_base;
+ return addr + env->tlb_table[mmu_idx][index].addend - (unsigned long)phys_ram_base;
}
#endif
Modified: trunk/src/host/qemu-neo1973/exec.c
===================================================================
--- trunk/src/host/qemu-neo1973/exec.c 2007-10-29 20:40:05 UTC (rev 3302)
+++ trunk/src/host/qemu-neo1973/exec.c 2007-10-29 21:14:04 UTC (rev 3303)
@@ -1292,15 +1292,28 @@
vfprintf(stderr, fmt, ap);
fprintf(stderr, "\n");
#ifdef TARGET_I386
+ if(env->intercept & INTERCEPT_SVM_MASK) {
+ /* most probably the virtual machine should not
+ be shut down but rather caught by the VMM */
+ vmexit(SVM_EXIT_SHUTDOWN, 0);
+ }
cpu_dump_state(env, stderr, fprintf, X86_DUMP_FPU | X86_DUMP_CCOP);
#else
cpu_dump_state(env, stderr, fprintf, 0);
#endif
- va_end(ap);
if (logfile) {
+ fprintf(logfile, "qemu: fatal: ");
+ vfprintf(logfile, fmt, ap);
+ fprintf(logfile, "\n");
+#ifdef TARGET_I386
+ cpu_dump_state(env, logfile, fprintf, X86_DUMP_FPU | X86_DUMP_CCOP);
+#else
+ cpu_dump_state(env, logfile, fprintf, 0);
+#endif
fflush(logfile);
fclose(logfile);
}
+ va_end(ap);
abort();
}
@@ -1595,7 +1608,7 @@
conflicting with the host address space). */
int tlb_set_page_exec(CPUState *env, target_ulong vaddr,
target_phys_addr_t paddr, int prot,
- int is_user, int is_softmmu)
+ int mmu_idx, int is_softmmu)
{
PhysPageDesc *p;
unsigned long pd;
@@ -1613,8 +1626,8 @@
pd = p->phys_offset;
}
#if defined(DEBUG_TLB)
- printf("tlb_set_page: vaddr=" TARGET_FMT_lx " paddr=0x%08x prot=%x u=%d smmu=%d pd=0x%08lx\n",
- vaddr, (int)paddr, prot, is_user, is_softmmu, pd);
+ printf("tlb_set_page: vaddr=" TARGET_FMT_lx " paddr=0x%08x prot=%x idx=%d smmu=%d pd=0x%08lx\n",
+ vaddr, (int)paddr, prot, mmu_idx, is_softmmu, pd);
#endif
ret = 0;
@@ -1651,7 +1664,7 @@
index = (vaddr >> TARGET_PAGE_BITS) & (CPU_TLB_SIZE - 1);
addend -= vaddr;
- te = &env->tlb_table[is_user][index];
+ te = &env->tlb_table[mmu_idx][index];
te->addend = addend;
if (prot & PAGE_READ) {
te->addr_read = address;
@@ -1777,7 +1790,7 @@
int tlb_set_page_exec(CPUState *env, target_ulong vaddr,
target_phys_addr_t paddr, int prot,
- int is_user, int is_softmmu)
+ int mmu_idx, int is_softmmu)
{
return 0;
}
@@ -2053,6 +2066,8 @@
#endif
#ifdef TARGET_SPARC
do_unassigned_access(addr, 0, 0, 0);
+#elif TARGET_CRIS
+ do_unassigned_access(addr, 0, 0, 0);
#endif
return 0;
}
@@ -2064,6 +2079,8 @@
#endif
#ifdef TARGET_SPARC
do_unassigned_access(addr, 1, 0, 0);
+#elif TARGET_CRIS
+ do_unassigned_access(addr, 1, 0, 0);
#endif
}
Modified: trunk/src/host/qemu-neo1973/gdbstub.c
===================================================================
--- trunk/src/host/qemu-neo1973/gdbstub.c 2007-10-29 20:40:05 UTC (rev 3302)
+++ trunk/src/host/qemu-neo1973/gdbstub.c 2007-10-29 21:14:04 UTC (rev 3303)
@@ -300,7 +300,7 @@
}
/* nip, msr, ccr, lnk, ctr, xer, mq */
registers[96] = tswapl(env->nip);
- registers[97] = tswapl(do_load_msr(env));
+ registers[97] = tswapl(env->msr);
tmp = 0;
for (i = 0; i < 8; i++)
tmp |= env->crf[i] << (32 - ((i + 1) * 4));
@@ -329,7 +329,7 @@
}
/* nip, msr, ccr, lnk, ctr, xer, mq */
env->nip = tswapl(registers[96]);
- do_store_msr(env, tswapl(registers[97]));
+ ppc_store_msr(env, tswapl(registers[97]));
registers[98] = tswapl(registers[98]);
for (i = 0; i < 8; i++)
env->crf[i] = (registers[98] >> (32 - ((i + 1) * 4))) & 0xF;
@@ -563,7 +563,7 @@
ptr += sizeof(target_ulong);
}
- *(target_ulong *)ptr = tswapl(env->CP0_Status);
+ *(target_ulong *)ptr = (int32_t)tswap32(env->CP0_Status);
ptr += sizeof(target_ulong);
*(target_ulong *)ptr = tswapl(env->LO[0][env->current_tc]);
@@ -575,7 +575,7 @@
*(target_ulong *)ptr = tswapl(env->CP0_BadVAddr);
ptr += sizeof(target_ulong);
- *(target_ulong *)ptr = tswapl(env->CP0_Cause);
+ *(target_ulong *)ptr = (int32_t)tswap32(env->CP0_Cause);
ptr += sizeof(target_ulong);
*(target_ulong *)ptr = tswapl(env->PC[env->current_tc]);
@@ -585,20 +585,35 @@
{
for (i = 0; i < 32; i++)
{
- *(target_ulong *)ptr = tswapl(env->fpu->fpr[i].fs[FP_ENDIAN_IDX]);
+ if (env->CP0_Status & (1 << CP0St_FR))
+ *(target_ulong *)ptr = tswapl(env->fpu->fpr[i].d);
+ else
+ *(target_ulong *)ptr = tswap32(env->fpu->fpr[i].w[FP_ENDIAN_IDX]);
ptr += sizeof(target_ulong);
}
- *(target_ulong *)ptr = tswapl(env->fpu->fcr31);
+ *(target_ulong *)ptr = (int32_t)tswap32(env->fpu->fcr31);
ptr += sizeof(target_ulong);
- *(target_ulong *)ptr = tswapl(env->fpu->fcr0);
+ *(target_ulong *)ptr = (int32_t)tswap32(env->fpu->fcr0);
ptr += sizeof(target_ulong);
}
- /* 32 FP registers, fsr, fir, fp. Not yet implemented. */
- /* what's 'fp' mean here? */
+ /* "fp", pseudo frame pointer. Not yet implemented in gdb. */
+ *(target_ulong *)ptr = 0;
+ ptr += sizeof(target_ulong);
+ /* Registers for embedded use, we just pad them. */
+ for (i = 0; i < 16; i++)
+ {
+ *(target_ulong *)ptr = 0;
+ ptr += sizeof(target_ulong);
+ }
+
+ /* Processor ID. */
+ *(target_ulong *)ptr = (int32_t)tswap32(env->CP0_PRid);
+ ptr += sizeof(target_ulong);
+
return ptr - mem_buf;
}
@@ -647,15 +662,17 @@
{
for (i = 0; i < 32; i++)
{
- env->fpu->fpr[i].fs[FP_ENDIAN_IDX] = tswapl(*(target_ulong *)ptr);
+ if (env->CP0_Status & (1 << CP0St_FR))
+ env->fpu->fpr[i].d = tswapl(*(target_ulong *)ptr);
+ else
+ env->fpu->fpr[i].w[FP_ENDIAN_IDX] = tswapl(*(target_ulong *)ptr);
ptr += sizeof(target_ulong);
}
- env->fpu->fcr31 = tswapl(*(target_ulong *)ptr) & 0x0183FFFF;
+ env->fpu->fcr31 = tswapl(*(target_ulong *)ptr) & 0xFF83FFFF;
ptr += sizeof(target_ulong);
- env->fpu->fcr0 = tswapl(*(target_ulong *)ptr);
- ptr += sizeof(target_ulong);
+ /* The remaining registers are assumed to be read-only. */
/* set rounding mode */
RESTORE_ROUNDING_MODE;
@@ -728,6 +745,66 @@
for (i = 0; i < 8; i++) LOAD(env->gregs[i]);
for (i = 0; i < 8; i++) LOAD(env->gregs[i + 16]);
}
+#elif defined (TARGET_CRIS)
+
+static int cris_save_32 (unsigned char *d, uint32_t value)
+{
+ *d++ = (value);
+ *d++ = (value >>= 8);
+ *d++ = (value >>= 8);
+ *d++ = (value >>= 8);
+ return 4;
+}
+static int cris_save_16 (unsigned char *d, uint32_t value)
+{
+ *d++ = (value);
+ *d++ = (value >>= 8);
+ return 2;
+}
+static int cris_save_8 (unsigned char *d, uint32_t value)
+{
+ *d++ = (value);
+ return 1;
+}
+
+/* FIXME: this will bug on archs not supporting unaligned word accesses. */
+static int cpu_gdb_read_registers(CPUState *env, uint8_t *mem_buf)
+{
+ uint8_t *ptr = mem_buf;
+ uint8_t srs;
+ int i;
+
+ for (i = 0; i < 16; i++)
+ ptr += cris_save_32 (ptr, env->regs[i]);
+
+ srs = env->pregs[SR_SRS];
+
+ ptr += cris_save_8 (ptr, env->pregs[0]);
+ ptr += cris_save_8 (ptr, env->pregs[1]);
+ ptr += cris_save_32 (ptr, env->pregs[2]);
+ ptr += cris_save_8 (ptr, srs);
+ ptr += cris_save_16 (ptr, env->pregs[4]);
+
+ for (i = 5; i < 16; i++)
+ ptr += cris_save_32 (ptr, env->pregs[i]);
+
+ ptr += cris_save_32 (ptr, env->pc);
+
+ for (i = 0; i < 16; i++)
+ ptr += cris_save_32 (ptr, env->sregs[srs][i]);
+
+ return ((uint8_t *)ptr - mem_buf);
+}
+
+static void cpu_gdb_write_registers(CPUState *env, uint8_t *mem_buf, int size)
+{
+ uint32_t *ptr = (uint32_t *)mem_buf;
+ int i;
+
+#define LOAD(x) (x)=*ptr++;
+ for (i = 0; i < 16; i++) LOAD(env->regs[i]);
+ LOAD (env->pc);
+}
#else
static int cpu_gdb_read_registers(CPUState *env, uint8_t *mem_buf)
{
@@ -745,7 +822,7 @@
const char *p;
int ch, reg_size, type;
char buf[4096];
- uint8_t mem_buf[2000];
+ uint8_t mem_buf[4096];
uint32_t *registers;
target_ulong addr, len;
@@ -776,6 +853,8 @@
env->pc = addr;
#elif defined (TARGET_MIPS)
env->PC[env->current_tc] = addr;
+#elif defined (TARGET_CRIS)
+ env->pc = addr;
#endif
}
#ifdef CONFIG_USER_ONLY
@@ -800,6 +879,8 @@
env->pc = addr;
#elif defined (TARGET_MIPS)
env->PC[env->current_tc] = addr;
+#elif defined (TARGET_CRIS)
+ env->pc = addr;
#endif
}
cpu_single_step(env, 1);
Modified: trunk/src/host/qemu-neo1973/host-utils.c
===================================================================
--- trunk/src/host/qemu-neo1973/host-utils.c 2007-10-29 20:40:05 UTC (rev 3302)
+++ trunk/src/host/qemu-neo1973/host-utils.c 2007-10-29 21:14:04 UTC (rev 3303)
@@ -1,6 +1,7 @@
/*
* Utility compute operations used by translated code.
*
+ * Copyright (c) 2003 Fabrice Bellard
* Copyright (c) 2007 Aurelien Jarno
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
@@ -24,52 +25,90 @@
#include "vl.h"
-/* Signed 64x64 -> 128 multiplication */
+//#define DEBUG_MULDIV
-void muls64(int64_t *phigh, int64_t *plow, int64_t a, int64_t b)
+/* Long integer helpers */
+static void add128 (uint64_t *plow, uint64_t *phigh, uint64_t a, uint64_t b)
{
-#if defined(__x86_64__)
- __asm__ ("imul %0\n\t"
- : "=d" (*phigh), "=a" (*plow)
- : "a" (a), "0" (b)
- );
-#else
- int64_t ph;
- uint64_t pm1, pm2, pl;
+ *plow += a;
+ /* carry test */
+ if (*plow < a)
+ (*phigh)++;
+ *phigh += b;
+}
- pl = (uint64_t)((uint32_t)a) * (uint64_t)((uint32_t)b);
- pm1 = (a >> 32) * (uint32_t)b;
- pm2 = (uint32_t)a * (b >> 32);
- ph = (a >> 32) * (b >> 32);
+static void neg128 (uint64_t *plow, uint64_t *phigh)
+{
+ *plow = ~*plow;
+ *phigh = ~*phigh;
+ add128(plow, phigh, 1, 0);
+}
- ph += (int64_t)pm1 >> 32;
- pm1 = (uint64_t)((uint32_t)pm1) + pm2 + (pl >> 32);
+static void mul64 (uint64_t *plow, uint64_t *phigh, uint64_t a, uint64_t b)
+{
+ uint32_t a0, a1, b0, b1;
+ uint64_t v;
- *phigh = ph + ((int64_t)pm1 >> 32);
- *plow = (pm1 << 32) + (uint32_t)pl;
-#endif
+ a0 = a;
+ a1 = a >> 32;
+
+ b0 = b;
+ b1 = b >> 32;
+
+ v = (uint64_t)a0 * (uint64_t)b0;
+ *plow = v;
+ *phigh = 0;
+
+ v = (uint64_t)a0 * (uint64_t)b1;
+ add128(plow, phigh, v << 32, v >> 32);
+
+ v = (uint64_t)a1 * (uint64_t)b0;
+ add128(plow, phigh, v << 32, v >> 32);
+
+ v = (uint64_t)a1 * (uint64_t)b1;
+ *phigh += v;
}
+
/* Unsigned 64x64 -> 128 multiplication */
-void mulu64(uint64_t *phigh, uint64_t *plow, uint64_t a, uint64_t b)
+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)
- );
+ : "a" (a), "0" (b));
#else
- uint64_t ph, pm1, pm2, pl;
+ mul64(plow, phigh, a, b);
+#endif
+#if defined(DEBUG_MULDIV)
+ printf("mulu64: 0x%016llx * 0x%016llx = 0x%016llx%016llx\n",
+ a, b, *phigh, *plow);
+#endif
+}
- pl = (uint64_t)((uint32_t)a) * (uint64_t)((uint32_t)b);
- pm1 = (a >> 32) * (uint32_t)b;
- pm2 = (uint32_t)a * (b >> 32);
- ph = (a >> 32) * (b >> 32);
+/* 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;
- ph += pm1 >> 32;
- pm1 = (uint64_t)((uint32_t)pm1) + pm2 + (pl >> 32);
-
- *phigh = ph + (pm1 >> 32);
- *plow = (pm1 << 32) + (uint32_t)pl;
+ sa = (a < 0);
+ if (sa)
+ a = -a;
+ sb = (b < 0);
+ if (sb)
+ b = -b;
+ mul64(plow, phigh, a, b);
+ 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
}
Added: trunk/src/host/qemu-neo1973/host-utils.h
===================================================================
--- trunk/src/host/qemu-neo1973/host-utils.h 2007-10-29 20:40:05 UTC (rev 3302)
+++ trunk/src/host/qemu-neo1973/host-utils.h 2007-10-29 21:14:04 UTC (rev 3303)
@@ -0,0 +1,201 @@
+/*
+ * Utility compute operations used by translated code.
+ *
+ * Copyright (c) 2007 Thiemo Seufer
+ * Copyright (c) 2007 Jocelyn Mayer
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+
+/* 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. */
+
+/* Binary search for leading zeros. */
+
+static always_inline int clz32(uint32_t val)
+{
+ int cnt = 0;
+
+ if (!(val & 0xFFFF0000U)) {
+ cnt += 16;
+ val <<= 16;
+ }
+ if (!(val & 0xFF000000U)) {
+ cnt += 8;
+ val <<= 8;
+ }
+ if (!(val & 0xF0000000U)) {
+ cnt += 4;
+ val <<= 4;
+ }
+ if (!(val & 0xC0000000U)) {
+ cnt += 2;
+ val <<= 2;
+ }
+ if (!(val & 0x80000000U)) {
+ cnt++;
+ val <<= 1;
+ }
+ if (!(val & 0x80000000U)) {
+ cnt++;
+ }
+ return cnt;
+}
+
+static always_inline int clo32(uint32_t val)
+{
+ return clz32(~val);
+}
+
+static always_inline int clz64(uint64_t val)
+{
+ int cnt = 0;
+
+ if (!(val & 0xFFFFFFFF00000000ULL)) {
+ cnt += 32;
+ 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;
+}
+
+static always_inline int clo64(uint64_t val)
+{
+ return clz64(~val);
+}
+
+static always_inline int ctz32 (uint32_t val)
+{
+ int cnt;
+
+ cnt = 0;
+ if (!(val & 0x0000FFFFUL)) {
+ cnt += 16;
+ val >>= 16;
+ }
+ if (!(val & 0x000000FFUL)) {
+ cnt += 8;
+ val >>= 8;
+ }
+ if (!(val & 0x0000000FUL)) {
+ cnt += 4;
+ val >>= 4;
+ }
+ if (!(val & 0x00000003UL)) {
+ cnt += 2;
+ val >>= 2;
+ }
+ if (!(val & 0x00000001UL)) {
+ cnt++;
+ val >>= 1;
+ }
+ if (!(val & 0x00000001UL)) {
+ cnt++;
+ }
+
+ return cnt;
+ }
+
+static always_inline int cto32 (uint32_t val)
+ {
+ return ctz32(~val);
+}
+
+static always_inline int ctz64 (uint64_t val)
+{
+ int cnt;
+
+ cnt = 0;
+ if (!((uint32_t)val)) {
+ cnt += 32;
+ val >>= 32;
+ }
+
+ return cnt + ctz32(val);
+}
+
+static always_inline int cto64 (uint64_t val)
+{
+ return ctz64(~val);
+}
+
+static always_inline int ctpop8 (uint8_t val)
+{
+ val = (val & 0x55) + ((val >> 1) & 0x55);
+ val = (val & 0x33) + ((val >> 2) & 0x33);
+ val = (val & 0x0f) + ((val >> 4) & 0x0f);
+
+ return val;
+}
+
+static always_inline int ctpop16 (uint16_t val)
+{
+ val = (val & 0x5555) + ((val >> 1) & 0x5555);
+ val = (val & 0x3333) + ((val >> 2) & 0x3333);
+ val = (val & 0x0f0f) + ((val >> 4) & 0x0f0f);
+ val = (val & 0x00ff) + ((val >> 8) & 0x00ff);
+
+ return val;
+}
+
+static always_inline int ctpop32 (uint32_t val)
+{
+ val = (val & 0x55555555) + ((val >> 1) & 0x55555555);
+ val = (val & 0x33333333) + ((val >> 2) & 0x33333333);
+ val = (val & 0x0f0f0f0f) + ((val >> 4) & 0x0f0f0f0f);
+ val = (val & 0x00ff00ff) + ((val >> 8) & 0x00ff00ff);
+ val = (val & 0x0000ffff) + ((val >> 16) & 0x0000ffff);
+
+ return val;
+}
+
+static always_inline int ctpop64 (uint64_t val)
+{
+ val = (val & 0x5555555555555555ULL) + ((val >> 1) & 0x5555555555555555ULL);
+ val = (val & 0x3333333333333333ULL) + ((val >> 2) & 0x3333333333333333ULL);
+ val = (val & 0x0f0f0f0f0f0f0f0fULL) + ((val >> 4) & 0x0f0f0f0f0f0f0f0fULL);
+ val = (val & 0x00ff00ff00ff00ffULL) + ((val >> 8) & 0x00ff00ff00ff00ffULL);
+ val = (val & 0x0000ffff0000ffffULL) + ((val >> 16) & 0x0000ffff0000ffffULL);
+ val = (val & 0x00000000ffffffffULL) + ((val >> 32) & 0x00000000ffffffffULL);
+
+ return val;
+ }
Modified: trunk/src/host/qemu-neo1973/hw/acpi.c
===================================================================
--- trunk/src/host/qemu-neo1973/hw/acpi.c 2007-10-29 20:40:05 UTC (rev 3302)
+++ trunk/src/host/qemu-neo1973/hw/acpi.c 2007-10-29 21:14:04 UTC (rev 3303)
@@ -400,7 +400,7 @@
if (s->dev.config[0x80] & 1) {
pm_io_base = le32_to_cpu(*(uint32_t *)(s->dev.config + 0x40));
- pm_io_base &= 0xfffe;
+ pm_io_base &= 0xffc0;
/* XXX: need to improve memory and ioport allocation */
#if defined(DEBUG)
@@ -474,6 +474,8 @@
pci_conf[0x01] = 0x80;
pci_conf[0x02] = 0x13;
pci_conf[0x03] = 0x71;
+ pci_conf[0x06] = 0x80;
+ pci_conf[0x07] = 0x02;
pci_conf[0x08] = 0x00; // revision number
pci_conf[0x09] = 0x00;
pci_conf[0x0a] = 0x80; // other bridge device
Modified: trunk/src/host/qemu-neo1973/hw/alpha_palcode.c
===================================================================
--- trunk/src/host/qemu-neo1973/hw/alpha_palcode.c 2007-10-29 20:40:05 UTC (rev 3302)
+++ trunk/src/host/qemu-neo1973/hw/alpha_palcode.c 2007-10-29 21:14:04 UTC (rev 3303)
@@ -811,12 +811,14 @@
static int get_pte (uint64_t *pfnp, int *zbitsp, int *protp,
uint64_t ptebase, int page_bits, uint64_t level,
- int is_user, int rw)
+ int mmu_idx, int rw)
{
uint64_t pteaddr, pte, pfn;
uint8_t gh;
- int ure, uwe, kre, kwe, foE, foR, foW, v, ret, ar;
+ int ure, uwe, kre, kwe, foE, foR, foW, v, ret, ar, is_user;
+ /* XXX: TOFIX */
+ is_user = mmu_idx == MMU_USER_IDX;
pteaddr = (ptebase << page_bits) + (8 * level);
pte = ldq_raw(pteaddr);
/* Decode all interresting PTE fields */
@@ -871,7 +873,7 @@
static int paddr_from_pte (uint64_t *paddr, int *zbitsp, int *prot,
uint64_t ptebase, int page_bits,
- uint64_t vaddr, int is_user, int rw)
+ uint64_t vaddr, int mmu_idx, int rw)
{
uint64_t pfn, page_mask, lvl_mask, level1, level2, level3;
int lvl_bits, ret;
@@ -909,7 +911,7 @@
break;
}
/* Level 3 PTE */
- ret = get_pte(&pfn, zbitsp, prot, pfn, page_bits, level3, is_user, rw);
+ ret = get_pte(&pfn, zbitsp, prot, pfn, page_bits, level3, mmu_idx, rw);
if (ret & 0x1) {
/* Translation not valid */
ret = 1;
@@ -943,7 +945,7 @@
static int virtual_to_physical (CPUState *env, uint64_t *physp,
int *zbitsp, int *protp,
- uint64_t virtual, int is_user, int rw)
+ uint64_t virtual, int mmu_idx, int rw)
{
uint64_t sva, ptebase;
int seg, page_bits, ret;
@@ -961,16 +963,16 @@
case 0:
/* seg1: 3 levels of PTE */
ret = paddr_from_pte(physp, zbitsp, protp, ptebase, page_bits,
- virtual, is_user, rw);
+ virtual, mmu_idx, rw);
break;
case 1:
/* seg1: 2 levels of PTE */
ret = paddr_from_pte(physp, zbitsp, protp, ptebase, page_bits,
- virtual, is_user, rw);
+ virtual, mmu_idx, rw);
break;
case 2:
/* kernel segment */
- if (is_user) {
+ if (mmu_idx != 0) {
ret = 2;
} else {
*physp = virtual;
@@ -979,7 +981,7 @@
case 3:
/* seg1: TB mapped */
ret = paddr_from_pte(physp, zbitsp, protp, ptebase, page_bits,
- virtual, is_user, rw);
+ virtual, mmu_idx, rw);
break;
default:
ret = 1;
@@ -991,7 +993,7 @@
/* XXX: code provision */
int cpu_ppc_handle_mmu_fault (CPUState *env, uint32_t address, int rw,
- int is_user, int is_softmmu)
+ int mmu_idx, int is_softmmu)
{
uint64_t physical, page_size, end;
int prot, zbits, ret;
@@ -1000,7 +1002,7 @@
ret = 2;
} else {
ret = virtual_to_physical(env, &physical, &zbits, &prot,
- address, is_user, rw);
+ address, mmu_idx, rw);
}
switch (ret) {
case 0:
@@ -1009,7 +1011,7 @@
address &= ~(page_size - 1);
for (end = physical + page_size; physical < end; physical += 0x1000) {
ret = tlb_set_page(env, address, physical, prot,
- is_user, is_softmmu);
+ mmu_idx, is_softmmu);
address += 0x1000;
}
break;
Modified: trunk/src/host/qemu-neo1973/hw/apb_pci.c
===================================================================
--- trunk/src/host/qemu-neo1973/hw/apb_pci.c 2007-10-29 20:40:05 UTC (rev 3302)
+++ trunk/src/host/qemu-neo1973/hw/apb_pci.c 2007-10-29 21:14:04 UTC (rev 3303)
@@ -70,7 +70,7 @@
};
static void apb_config_writel (void *opaque, target_phys_addr_t addr,
- uint32_t val)
+ uint32_t val)
{
//PCIBus *s = opaque;
@@ -80,14 +80,14 @@
case 0x18: // AFAR
case 0x20: // Diagnostic
case 0x28: // Target address space
- // XXX
+ // XXX
default:
- break;
+ break;
}
}
static uint32_t apb_config_readl (void *opaque,
- target_phys_addr_t addr)
+ target_phys_addr_t addr)
{
//PCIBus *s = opaque;
uint32_t val;
@@ -98,10 +98,10 @@
case 0x18: // AFAR
case 0x20: // Diagnostic
case 0x28: // Target address space
- // XXX
+ // XXX
default:
- val = 0;
- break;
+ val = 0;
+ break;
}
return val;
}
@@ -222,7 +222,7 @@
pci_mem_config = cpu_register_io_memory(0, pci_apb_config_read,
pci_apb_config_write, s);
apb_config = cpu_register_io_memory(0, apb_config_read,
- apb_config_write, s);
+ apb_config_write, s);
pci_mem_data = cpu_register_io_memory(0, pci_apb_read,
pci_apb_write, s);
pci_ioport = cpu_register_io_memory(0, pci_apb_ioread,
Modified: trunk/src/host/qemu-neo1973/hw/apic.c
===================================================================
--- trunk/src/host/qemu-neo1973/hw/apic.c 2007-10-29 20:40:05 UTC (rev 3302)
+++ trunk/src/host/qemu-neo1973/hw/apic.c 2007-10-29 21:14:04 UTC (rev 3303)
@@ -484,6 +484,25 @@
return intno;
}
+int apic_accept_pic_intr(CPUState *env)
+{
+ APICState *s = env->apic_state;
+ uint32_t lvt0;
+
+ if (!s)
+ return -1;
+
+ lvt0 = s->lvt[APIC_LVT_LINT0];
+
+ if (s->id == 0 &&
+ ((s->apicbase & MSR_IA32_APICBASE_ENABLE) == 0 ||
+ ((lvt0 & APIC_LVT_MASKED) == 0 &&
+ ((lvt0 >> 8) & 0x7) == APIC_DM_EXTINT)))
+ return 1;
+
+ return 0;
+}
+
static uint32_t apic_get_current_count(APICState *s)
{
int64_t d;
@@ -790,6 +809,13 @@
{
APICState *s = opaque;
apic_init_ipi(s);
+
+ /*
+ * LINT0 delivery mode is set to ExtInt at initialization time
+ * typically by BIOS, so PIC interrupt can be delivered to the
+ * processor when local APIC is enabled.
+ */
+ s->lvt[APIC_LVT_LINT0] = 0x700;
}
static CPUReadMemoryFunc *apic_mem_read[3] = {
@@ -821,6 +847,13 @@
s->apicbase = 0xfee00000 |
(s->id ? 0 : MSR_IA32_APICBASE_BSP) | MSR_IA32_APICBASE_ENABLE;
+ /*
+ * LINT0 delivery mode is set to ExtInt at initialization time
+ * typically by BIOS, so PIC interrupt can be delivered to the
+ * processor when local APIC is enabled.
+ */
+ s->lvt[APIC_LVT_LINT0] = 0x700;
+
/* XXX: mapping more APICs at the same memory location */
if (apic_io_memory == 0) {
/* NOTE: the APIC is directly connected to the CPU - it is not
Modified: trunk/src/host/qemu-neo1973/hw/cs4231.c
===================================================================
--- trunk/src/host/qemu-neo1973/hw/cs4231.c 2007-10-29 20:40:05 UTC (rev 3302)
+++ trunk/src/host/qemu-neo1973/hw/cs4231.c 2007-10-29 21:14:04 UTC (rev 3303)
@@ -79,11 +79,11 @@
break;
}
DPRINTF("read dreg[%d]: 0x%8.8x\n", CS_RAP(s), ret);
- break;
+ break;
default:
ret = s->regs[saddr];
DPRINTF("read reg[%d]: 0x%8.8x\n", saddr, ret);
- break;
+ break;
}
return ret;
}
@@ -122,7 +122,7 @@
break;
default:
s->regs[saddr] = val;
- break;
+ break;
}
}
Modified: trunk/src/host/qemu-neo1973/hw/cuda.c
===================================================================
--- trunk/src/host/qemu-neo1973/hw/cuda.c 2007-10-29 20:40:05 UTC (rev 3302)
+++ trunk/src/host/qemu-neo1973/hw/cuda.c 2007-10-29 21:14:04 UTC (rev 3303)
@@ -1,7 +1,8 @@
/*
- * QEMU CUDA support
+ * QEMU PowerMac CUDA device support
*
- * Copyright (c) 2004 Fabrice Bellard
+ * Copyright (c) 2004-2007 Fabrice Bellard
+ * Copyright (c) 2007 Jocelyn Mayer
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
@@ -22,6 +23,7 @@
* THE SOFTWARE.
*/
#include "vl.h"
+#include "ppc_mac.h"
/* XXX: implement all timer modes */
@@ -634,10 +636,9 @@
&cuda_readl,
};
-int cuda_init(qemu_irq irq)
+void cuda_init (int *cuda_mem_index, qemu_irq irq)
{
CUDAState *s = &cuda_state;
- int cuda_mem_index;
s->irq = irq;
@@ -653,6 +654,5 @@
set_counter(s, &s->timers[1], 0xffff);
s->adb_poll_timer = qemu_new_timer(vm_clock, cuda_adb_poll, s);
- cuda_mem_index = cpu_register_io_memory(0, cuda_read, cuda_write, s);
- return cuda_mem_index;
+ *cuda_mem_index = cpu_register_io_memory(0, cuda_read, cuda_write, s);
}
Added: trunk/src/host/qemu-neo1973/hw/ecc.c
===================================================================
--- trunk/src/host/qemu-neo1973/hw/ecc.c 2007-10-29 20:40:05 UTC (rev 3302)
+++ trunk/src/host/qemu-neo1973/hw/ecc.c 2007-10-29 21:14:04 UTC (rev 3303)
@@ -0,0 +1,90 @@
+/*
+ * Calculate Error-correcting Codes. Used by NAND Flash controllers
+ * (not by NAND chips).
+ *
+ * Copyright (c) 2006 Openedhand Ltd.
+ * Written by Andrzej Zaborowski <balrog at zabor.org>
+ *
+ * This code is licensed under the GNU GPL v2.
+ */
+
+#include "vl.h"
+
+/*
+ * Pre-calculated 256-way 1 byte column parity. Table borrowed from Linux.
+ */
+static const uint8_t nand_ecc_precalc_table[] = {
+ 0x00, 0x55, 0x56, 0x03, 0x59, 0x0c, 0x0f, 0x5a,
+ 0x5a, 0x0f, 0x0c, 0x59, 0x03, 0x56, 0x55, 0x00,
+ 0x65, 0x30, 0x33, 0x66, 0x3c, 0x69, 0x6a, 0x3f,
+ 0x3f, 0x6a, 0x69, 0x3c, 0x66, 0x33, 0x30, 0x65,
+ 0x66, 0x33, 0x30, 0x65, 0x3f, 0x6a, 0x69, 0x3c,
+ 0x3c, 0x69, 0x6a, 0x3f, 0x65, 0x30, 0x33, 0x66,
+ 0x03, 0x56, 0x55, 0x00, 0x5a, 0x0f, 0x0c, 0x59,
+ 0x59, 0x0c, 0x0f, 0x5a, 0x00, 0x55, 0x56, 0x03,
+ 0x69, 0x3c, 0x3f, 0x6a, 0x30, 0x65, 0x66, 0x33,
+ 0x33, 0x66, 0x65, 0x30, 0x6a, 0x3f, 0x3c, 0x69,
+ 0x0c, 0x59, 0x5a, 0x0f, 0x55, 0x00, 0x03, 0x56,
+ 0x56, 0x03, 0x00, 0x55, 0x0f, 0x5a, 0x59, 0x0c,
+ 0x0f, 0x5a, 0x59, 0x0c, 0x56, 0x03, 0x00, 0x55,
+ 0x55, 0x00, 0x03, 0x56, 0x0c, 0x59, 0x5a, 0x0f,
+ 0x6a, 0x3f, 0x3c, 0x69, 0x33, 0x66, 0x65, 0x30,
+ 0x30, 0x65, 0x66, 0x33, 0x69, 0x3c, 0x3f, 0x6a,
+ 0x6a, 0x3f, 0x3c, 0x69, 0x33, 0x66, 0x65, 0x30,
+ 0x30, 0x65, 0x66, 0x33, 0x69, 0x3c, 0x3f, 0x6a,
+ 0x0f, 0x5a, 0x59, 0x0c, 0x56, 0x03, 0x00, 0x55,
+ 0x55, 0x00, 0x03, 0x56, 0x0c, 0x59, 0x5a, 0x0f,
+ 0x0c, 0x59, 0x5a, 0x0f, 0x55, 0x00, 0x03, 0x56,
+ 0x56, 0x03, 0x00, 0x55, 0x0f, 0x5a, 0x59, 0x0c,
+ 0x69, 0x3c, 0x3f, 0x6a, 0x30, 0x65, 0x66, 0x33,
+ 0x33, 0x66, 0x65, 0x30, 0x6a, 0x3f, 0x3c, 0x69,
+ 0x03, 0x56, 0x55, 0x00, 0x5a, 0x0f, 0x0c, 0x59,
+ 0x59, 0x0c, 0x0f, 0x5a, 0x00, 0x55, 0x56, 0x03,
+ 0x66, 0x33, 0x30, 0x65, 0x3f, 0x6a, 0x69, 0x3c,
+ 0x3c, 0x69, 0x6a, 0x3f, 0x65, 0x30, 0x33, 0x66,
+ 0x65, 0x30, 0x33, 0x66, 0x3c, 0x69, 0x6a, 0x3f,
+ 0x3f, 0x6a, 0x69, 0x3c, 0x66, 0x33, 0x30, 0x65,
+ 0x00, 0x55, 0x56, 0x03, 0x59, 0x0c, 0x0f, 0x5a,
+ 0x5a, 0x0f, 0x0c, 0x59, 0x03, 0x56, 0x55, 0x00,
+};
+
+/* Update ECC parity count. */
+uint8_t ecc_digest(struct ecc_state_s *s, uint8_t sample)
+{
+ uint8_t idx = nand_ecc_precalc_table[sample];
+
+ s->cp ^= idx & 0x3f;
+ if (idx & 0x40) {
+ s->lp[0] ^= ~s->count;
+ s->lp[1] ^= s->count;
+ }
+ s->count ++;
+
+ return sample;
+}
+
+/* Reinitialise the counters. */
+void ecc_reset(struct ecc_state_s *s)
+{
+ s->lp[0] = 0x0000;
+ s->lp[1] = 0x0000;
+ s->cp = 0x00;
+ s->count = 0;
+}
+
+/* Save/restore */
+void ecc_put(QEMUFile *f, struct ecc_state_s *s)
+{
+ qemu_put_8s(f, &s->cp);
+ qemu_put_be16s(f, &s->lp[0]);
+ qemu_put_be16s(f, &s->lp[1]);
+ qemu_put_be16s(f, &s->count);
+}
+
+void ecc_get(QEMUFile *f, struct ecc_state_s *s)
+{
+ qemu_get_8s(f, &s->cp);
+ qemu_get_be16s(f, &s->lp[0]);
+ qemu_get_be16s(f, &s->lp[1]);
+ qemu_get_be16s(f, &s->count);
+}
Modified: trunk/src/host/qemu-neo1973/hw/esp.c
===================================================================
--- trunk/src/host/qemu-neo1973/hw/esp.c 2007-10-29 20:40:05 UTC (rev 3302)
+++ trunk/src/host/qemu-neo1973/hw/esp.c 2007-10-29 21:14:04 UTC (rev 3303)
@@ -107,9 +107,9 @@
if (s->dma) {
espdma_memory_read(s->dma_opaque, buf, dmalen);
} else {
- buf[0] = 0;
- memcpy(&buf[1], s->ti_buf, dmalen);
- dmalen++;
+ buf[0] = 0;
+ memcpy(&buf[1], s->ti_buf, dmalen);
+ dmalen++;
}
s->ti_size = 0;
@@ -124,11 +124,11 @@
if (target >= MAX_DISKS || !s->scsi_dev[target]) {
// No such drive
- s->rregs[4] = STAT_IN;
- s->rregs[5] = INTR_DC;
- s->rregs[6] = SEQ_0;
- qemu_irq_raise(s->irq);
- return 0;
+ s->rregs[4] = STAT_IN;
+ s->rregs[5] = INTR_DC;
+ s->rregs[6] = SEQ_0;
+ qemu_irq_raise(s->irq);
+ return 0;
}
s->current_dev = s->scsi_dev[target];
return dmalen;
@@ -190,14 +190,14 @@
s->ti_buf[1] = 0;
if (s->dma) {
espdma_memory_write(s->dma_opaque, s->ti_buf, 2);
- s->rregs[4] = STAT_IN | STAT_TC | STAT_ST;
- s->rregs[5] = INTR_BS | INTR_FC;
- s->rregs[6] = SEQ_CD;
+ s->rregs[4] = STAT_IN | STAT_TC | STAT_ST;
+ s->rregs[5] = INTR_BS | INTR_FC;
+ s->rregs[6] = SEQ_CD;
} else {
- s->ti_size = 2;
- s->ti_rptr = 0;
- s->ti_wptr = 0;
- s->rregs[7] = 2;
+ s->ti_size = 2;
+ s->ti_rptr = 0;
+ s->ti_wptr = 0;
+ s->rregs[7] = 2;
}
qemu_irq_raise(s->irq);
}
@@ -359,9 +359,9 @@
DPRINTF("read reg[%d]: 0x%2.2x\n", saddr, s->rregs[saddr]);
switch (saddr) {
case 2:
- // FIFO
- if (s->ti_size > 0) {
- s->ti_size--;
+ // FIFO
+ if (s->ti_size > 0) {
+ s->ti_size--;
if ((s->rregs[4] & 6) == 0) {
/* Data in/out. */
fprintf(stderr, "esp: PIO data read not implemented\n");
@@ -370,20 +370,20 @@
s->rregs[2] = s->ti_buf[s->ti_rptr++];
}
qemu_irq_raise(s->irq);
- }
- if (s->ti_size == 0) {
+ }
+ if (s->ti_size == 0) {
s->ti_rptr = 0;
s->ti_wptr = 0;
}
- break;
+ break;
case 5:
// interrupt
// Clear interrupt/error status bits
s->rregs[4] &= ~(STAT_IN | STAT_GE | STAT_PE);
- qemu_irq_lower(s->irq);
+ qemu_irq_lower(s->irq);
break;
default:
- break;
+ break;
}
return s->rregs[saddr];
}
@@ -401,7 +401,7 @@
s->rregs[4] &= ~STAT_TC;
break;
case 2:
- // FIFO
+ // FIFO
if (s->do_cmd) {
s->cmdbuf[s->cmdlen++] = val & 0xff;
} else if ((s->rregs[4] & 6) == 0) {
@@ -413,73 +413,73 @@
s->ti_size++;
s->ti_buf[s->ti_wptr++] = val & 0xff;
}
- break;
+ break;
case 3:
s->rregs[saddr] = val;
- // Command
- if (val & 0x80) {
- s->dma = 1;
+ // Command
+ if (val & 0x80) {
+ s->dma = 1;
/* Reload DMA counter. */
s->rregs[0] = s->wregs[0];
s->rregs[1] = s->wregs[1];
- } else {
- s->dma = 0;
- }
- switch(val & 0x7f) {
- case 0:
- DPRINTF("NOP (%2.2x)\n", val);
- break;
- case 1:
- DPRINTF("Flush FIFO (%2.2x)\n", val);
+ } else {
+ s->dma = 0;
+ }
+ switch(val & 0x7f) {
+ case 0:
+ DPRINTF("NOP (%2.2x)\n", val);
+ break;
+ case 1:
+ DPRINTF("Flush FIFO (%2.2x)\n", val);
//s->ti_size = 0;
- s->rregs[5] = INTR_FC;
- s->rregs[6] = 0;
- break;
- case 2:
- DPRINTF("Chip reset (%2.2x)\n", val);
- esp_reset(s);
- break;
- case 3:
- DPRINTF("Bus reset (%2.2x)\n", val);
- s->rregs[5] = INTR_RST;
+ s->rregs[5] = INTR_FC;
+ s->rregs[6] = 0;
+ break;
+ case 2:
+ DPRINTF("Chip reset (%2.2x)\n", val);
+ esp_reset(s);
+ break;
+ case 3:
+ DPRINTF("Bus reset (%2.2x)\n", val);
+ s->rregs[5] = INTR_RST;
if (!(s->wregs[8] & 0x40)) {
qemu_irq_raise(s->irq);
}
- break;
- case 0x10:
- handle_ti(s);
- break;
- case 0x11:
- DPRINTF("Initiator Command Complete Sequence (%2.2x)\n", val);
- write_response(s);
- break;
- case 0x12:
- DPRINTF("Message Accepted (%2.2x)\n", val);
- write_response(s);
- s->rregs[5] = INTR_DC;
- s->rregs[6] = 0;
- break;
- case 0x1a:
- DPRINTF("Set ATN (%2.2x)\n", val);
- break;
- case 0x42:
- DPRINTF("Set ATN (%2.2x)\n", val);
- handle_satn(s);
- break;
- case 0x43:
- DPRINTF("Set ATN & stop (%2.2x)\n", val);
- handle_satn_stop(s);
- break;
+ break;
+ case 0x10:
+ handle_ti(s);
+ break;
+ case 0x11:
+ DPRINTF("Initiator Command Complete Sequence (%2.2x)\n", val);
+ write_response(s);
+ break;
+ case 0x12:
+ DPRINTF("Message Accepted (%2.2x)\n", val);
+ write_response(s);
+ s->rregs[5] = INTR_DC;
+ s->rregs[6] = 0;
+ break;
+ case 0x1a:
+ DPRINTF("Set ATN (%2.2x)\n", val);
+ break;
+ case 0x42:
+ DPRINTF("Set ATN (%2.2x)\n", val);
+ handle_satn(s);
+ break;
+ case 0x43:
+ DPRINTF("Set ATN & stop (%2.2x)\n", val);
+ handle_satn_stop(s);
+ break;
case 0x44:
DPRINTF("Enable selection (%2.2x)\n", val);
break;
- default:
- DPRINTF("Unhandled ESP command (%2.2x)\n", val);
- break;
- }
- break;
+ default:
+ DPRINTF("Unhandled ESP command (%2.2x)\n", val);
+ break;
+ }
+ break;
case 4 ... 7:
- break;
+ break;
case 8:
s->rregs[saddr] = val;
break;
@@ -492,7 +492,7 @@
s->rregs[saddr] = val;
break;
default:
- break;
+ break;
}
s->wregs[saddr] = val;
}
Added: trunk/src/host/qemu-neo1973/hw/etraxfs.c
===================================================================
--- trunk/src/host/qemu-neo1973/hw/etraxfs.c 2007-10-29 20:40:05 UTC (rev 3302)
+++ trunk/src/host/qemu-neo1973/hw/etraxfs.c 2007-10-29 21:14:04 UTC (rev 3303)
@@ -0,0 +1,178 @@
+/*
+ * QEMU ETRAX System Emulator
+ *
+ * Copyright (c) 2007 Edgar E. Iglesias, Axis Communications AB.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+#include <time.h>
+#include <sys/time.h>
+#include "vl.h"
+
+extern FILE *logfile;
+
+static void main_cpu_reset(void *opaque)
+{
+ CPUState *env = opaque;
+ cpu_reset(env);
+}
+
+static uint32_t fs_mmio_readb (void *opaque, target_phys_addr_t addr)
+{
+ CPUState *env = opaque;
+ uint32_t r = 0;
+ printf ("%s %x pc=%x\n", __func__, addr, env->pc);
+ return r;
+}
+static uint32_t fs_mmio_readw (void *opaque, target_phys_addr_t addr)
+{
+ CPUState *env = opaque;
+ uint32_t r = 0;
+ printf ("%s %x pc=%x\n", __func__, addr, env->pc);
+ return r;
+}
+
+static uint32_t fs_mmio_readl (void *opaque, target_phys_addr_t addr)
+{
+ CPUState *env = opaque;
+ uint32_t r = 0;
+ printf ("%s %x p=%x\n", __func__, addr, env->pc);
+ return r;
+}
+
+static void
+fs_mmio_writeb (void *opaque, target_phys_addr_t addr, uint32_t value)
+{
+ CPUState *env = opaque;
+ printf ("%s %x %x pc=%x\n", __func__, addr, value, env->pc);
+}
+static void
+fs_mmio_writew (void *opaque, target_phys_addr_t addr, uint32_t value)
+{
+ CPUState *env = opaque;
+ printf ("%s %x %x pc=%x\n", __func__, addr, value, env->pc);
+}
+static void
+fs_mmio_writel (void *opaque, target_phys_addr_t addr, uint32_t value)
+{
+ CPUState *env = opaque;
+ printf ("%s %x %x pc=%x\n", __func__, addr, value, env->pc);
+}
+
+static CPUReadMemoryFunc *fs_mmio_read[] = {
+ &fs_mmio_readb,
+ &fs_mmio_readw,
+ &fs_mmio_readl,
+};
+
+static CPUWriteMemoryFunc *fs_mmio_write[] = {
+ &fs_mmio_writeb,
+ &fs_mmio_writew,
+ &fs_mmio_writel,
+};
+
+
+/* Init functions for different blocks. */
+extern void etraxfs_timer_init(CPUState *env, qemu_irq *irqs);
+extern void etraxfs_ser_init(CPUState *env, qemu_irq *irqs);
+
+void etrax_ack_irq(CPUState *env, uint32_t mask)
+{
+ env->pending_interrupts &= ~mask;
+}
+
+static void dummy_cpu_set_irq(void *opaque, int irq, int level)
+{
+ CPUState *env = opaque;
+
+ /* Hmm, should this really be done here? */
+ env->pending_interrupts |= 1 << irq;
+ cpu_interrupt(env, CPU_INTERRUPT_HARD);
+}
+
+static
+void bareetraxfs_init (int ram_size, int vga_ram_size, int boot_device,
+ DisplayState *ds, const char **fd_filename, int snapshot,
+ const char *kernel_filename, const char *kernel_cmdline,
+ const char *initrd_filename, const char *cpu_model)
+{
+ CPUState *env;
+ qemu_irq *irqs;
+ int kernel_size;
+ int internal_regs;
+
+ /* init CPUs */
+ if (cpu_model == NULL) {
+ cpu_model = "crisv32";
+ }
+ env = cpu_init();
+/* register_savevm("cpu", 0, 3, cpu_save, cpu_load, env); */
+ qemu_register_reset(main_cpu_reset, env);
+ irqs = qemu_allocate_irqs(dummy_cpu_set_irq, env, 32);
+
+ internal_regs = cpu_register_io_memory(0,
+ fs_mmio_read, fs_mmio_write, env);
+ /* 0xb0050000 is the last reg. */
+ cpu_register_physical_memory (0xac000000, 0x4010000, internal_regs);
+ /* allocate RAM */
+ cpu_register_physical_memory(0x40000000, ram_size, IO_MEM_RAM);
+
+ etraxfs_timer_init(env, irqs);
+ etraxfs_ser_init(env, irqs);
+
+ kernel_size = load_image(kernel_filename, phys_ram_base + 0x4000);
+ /* magic for boot. */
+ env->regs[8] = 0x56902387;
+ env->regs[9] = 0x40004000 + kernel_size;
+ env->pc = 0x40004000;
+
+ {
+ unsigned char *ptr = phys_ram_base + 0x4000;
+ int i;
+ for (i = 0; i < 8; i++)
+ {
+ printf ("%2.2x ", ptr[i]);
+ }
+ printf("\n");
+ }
+
+ printf ("pc =%x\n", env->pc);
+ printf ("ram size =%d\n", ram_size);
+ printf ("kernel name =%s\n", kernel_filename);
+ printf ("kernel size =%d\n", kernel_size);
+ printf ("cpu haltd =%d\n", env->halted);
+}
+
+void DMA_run(void)
+{
+}
+
+void pic_info()
+{
+}
+
+void irq_info()
+{
+}
+
+QEMUMachine bareetraxfs_machine = {
+ "bareetraxfs",
+ "Bare ETRAX FS board",
+ bareetraxfs_init,
+};
Added: trunk/src/host/qemu-neo1973/hw/etraxfs_ser.c
===================================================================
--- trunk/src/host/qemu-neo1973/hw/etraxfs_ser.c 2007-10-29 20:40:05 UTC (rev 3302)
+++ trunk/src/host/qemu-neo1973/hw/etraxfs_ser.c 2007-10-29 21:14:04 UTC (rev 3303)
@@ -0,0 +1,122 @@
+/*
+ * QEMU ETRAX System Emulator
+ *
+ * Copyright (c) 2007 Edgar E. Iglesias, Axis Communications AB.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+
+#include <stdio.h>
+#include <ctype.h>
+#include "vl.h"
+
+#define RW_TR_DMA_EN 0xb0026004
+#define RW_DOUT 0xb002601c
+#define RW_STAT_DIN 0xb0026020
+#define R_STAT_DIN 0xb0026024
+
+static uint32_t ser_readb (void *opaque, target_phys_addr_t addr)
+{
+ CPUState *env = opaque;
+ uint32_t r = 0;
+ printf ("%s %x pc=%x\n", __func__, addr, env->pc);
+ return r;
+}
+static uint32_t ser_readw (void *opaque, target_phys_addr_t addr)
+{
+ CPUState *env = opaque;
+ uint32_t r = 0;
+ printf ("%s %x pc=%x\n", __func__, addr, env->pc);
+ return r;
+}
+
+static uint32_t ser_readl (void *opaque, target_phys_addr_t addr)
+{
+ CPUState *env = opaque;
+ uint32_t r = 0;
+
+ switch (addr)
+ {
+ case RW_TR_DMA_EN:
+ break;
+ case R_STAT_DIN:
+ r |= 1 << 24; /* set tr_rdy. */
+ r |= 1 << 22; /* set tr_idle. */
+ break;
+
+ default:
+ printf ("%s %x p=%x\n", __func__, addr, env->pc);
+ break;
+ }
+ return r;
+}
+
+static void
+ser_writeb (void *opaque, target_phys_addr_t addr, uint32_t value)
+{
+ CPUState *env = opaque;
+ printf ("%s %x %x pc=%x\n", __func__, addr, value, env->pc);
+}
+static void
+ser_writew (void *opaque, target_phys_addr_t addr, uint32_t value)
+{
+ CPUState *env = opaque;
+ printf ("%s %x %x pc=%x\n", __func__, addr, value, env->pc);
+}
+static void
+ser_writel (void *opaque, target_phys_addr_t addr, uint32_t value)
+{
+ CPUState *env = opaque;
+
+ switch (addr)
+ {
+ case RW_TR_DMA_EN:
+ break;
+ case RW_DOUT:
+ if (isprint(value) || isspace(value))
+ putchar(value);
+ else
+ putchar('.');
+ break;
+ default:
+ printf ("%s %x %x pc=%x\n",
+ __func__, addr, value, env->pc);
+ break;
+ }
+}
+
+static CPUReadMemoryFunc *ser_read[] = {
+ &ser_readb,
+ &ser_readw,
+ &ser_readl,
+};
+
+static CPUWriteMemoryFunc *ser_write[] = {
+ &ser_writeb,
+ &ser_writew,
+ &ser_writel,
+};
+
+void etraxfs_ser_init(CPUState *env, qemu_irq *irqs)
+{
+ int ser_regs;
+
+ ser_regs = cpu_register_io_memory(0, ser_read, ser_write, env);
+ cpu_register_physical_memory (0xb0026000, 0x3c, ser_regs);
+}
Added: trunk/src/host/qemu-neo1973/hw/etraxfs_timer.c
===================================================================
--- trunk/src/host/qemu-neo1973/hw/etraxfs_timer.c 2007-10-29 20:40:05 UTC (rev 3302)
+++ trunk/src/host/qemu-neo1973/hw/etraxfs_timer.c 2007-10-29 21:14:04 UTC (rev 3303)
@@ -0,0 +1,268 @@
+/*
+ * QEMU ETRAX System Emulator
+ *
+ * Copyright (c) 2007 Edgar E. Iglesias, Axis Communications AB.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+#include <stdio.h>
+#include <sys/time.h>
+#include "vl.h"
+
+void etrax_ack_irq(CPUState *env, uint32_t mask);
+
+#define R_TIME 0xb001e038
+#define RW_TMR0_DIV 0xb001e000
+#define R_TMR0_DATA 0xb001e004
+#define RW_TMR0_CTRL 0xb001e008
+#define RW_TMR1_DIV 0xb001e010
+#define R_TMR1_DATA 0xb001e014
+#define RW_TMR1_CTRL 0xb001e018
+
+#define RW_INTR_MASK 0xb001e048
+#define RW_ACK_INTR 0xb001e04c
+#define R_INTR 0xb001e050
+#define R_MASKED_INTR 0xb001e054
+
+
+uint32_t rw_intr_mask;
+uint32_t rw_ack_intr;
+uint32_t r_intr;
+
+struct fs_timer_t {
+ QEMUBH *bh;
+ unsigned int limit;
+ int scale;
+ ptimer_state *ptimer;
+ CPUState *env;
+ qemu_irq *irq;
+ uint32_t mask;
+};
+
+static struct fs_timer_t timer0;
+
+/* diff two timevals. Return a single int in us. */
+int diff_timeval_us(struct timeval *a, struct timeval *b)
+{
+ int diff;
+
+ /* assume these values are signed. */
+ diff = (a->tv_sec - b->tv_sec) * 1000 * 1000;
+ diff += (a->tv_usec - b->tv_usec);
+ return diff;
+}
+
+static uint32_t timer_readb (void *opaque, target_phys_addr_t addr)
+{
+ CPUState *env = opaque;
+ uint32_t r = 0;
+ printf ("%s %x pc=%x\n", __func__, addr, env->pc);
+ return r;
+}
+static uint32_t timer_readw (void *opaque, target_phys_addr_t addr)
+{
+ CPUState *env = opaque;
+ uint32_t r = 0;
+ printf ("%s %x pc=%x\n", __func__, addr, env->pc);
+ return r;
+}
+
+static uint32_t timer_readl (void *opaque, target_phys_addr_t addr)
+{
+ CPUState *env = opaque;
+ uint32_t r = 0;
+
+ switch (addr) {
+ case R_TMR0_DATA:
+ break;
+ case R_TMR1_DATA:
+ printf ("R_TMR1_DATA\n");
+ break;
+ case R_TIME:
+ {
+ static struct timeval last;
+ struct timeval now;
+ gettimeofday(&now, NULL);
+ if (!(last.tv_sec == 0 && last.tv_usec == 0)) {
+ r = diff_timeval_us(&now, &last);
+ r *= 1000; /* convert to ns. */
+ r++; /* make sure we increase for each call. */
+ }
+ last = now;
+ break;
+ }
+
+ case RW_INTR_MASK:
+ r = rw_intr_mask;
+ break;
+ case R_MASKED_INTR:
+ r = r_intr & rw_intr_mask;
+ break;
+ default:
+ printf ("%s %x p=%x\n", __func__, addr, env->pc);
+ break;
+ }
+ return r;
+}
+
+static void
+timer_writeb (void *opaque, target_phys_addr_t addr, uint32_t value)
+{
+ CPUState *env = opaque;
+ printf ("%s %x %x pc=%x\n", __func__, addr, value, env->pc);
+}
+static void
+timer_writew (void *opaque, target_phys_addr_t addr, uint32_t value)
+{
+ CPUState *env = opaque;
+ printf ("%s %x %x pc=%x\n", __func__, addr, value, env->pc);
+}
+
+static void write_ctrl(struct fs_timer_t *t, uint32_t v)
+{
+ int op;
+ int freq;
+ int freq_hz;
+
+ op = v & 3;
+ freq = v >> 2;
+ freq_hz = 32000000;
+
+ switch (freq)
+ {
+ case 0:
+ case 1:
+ printf ("extern or disabled timer clock?\n");
+ break;
+ case 4: freq_hz = 29493000; break;
+ case 5: freq_hz = 32000000; break;
+ case 6: freq_hz = 32768000; break;
+ case 7: freq_hz = 100000000; break;
+ default:
+ abort();
+ break;
+ }
+
+ printf ("freq_hz=%d limit=%d\n", freq_hz, t->limit);
+ t->scale = 0;
+ if (t->limit > 2048)
+ {
+ t->scale = 2048;
+ ptimer_set_period(timer0.ptimer, freq_hz / t->scale);
+ }
+
+ printf ("op=%d\n", op);
+ switch (op)
+ {
+ case 0:
+ printf ("limit=%d %d\n", t->limit, t->limit/t->scale);
+ ptimer_set_limit(t->ptimer, t->limit / t->scale, 1);
+ break;
+ case 1:
+ ptimer_stop(t->ptimer);
+ break;
+ case 2:
+ ptimer_run(t->ptimer, 0);
+ break;
+ default:
+ abort();
+ break;
+ }
+}
+
+static void timer_ack_irq(void)
+{
+ if (!(r_intr & timer0.mask & rw_intr_mask)) {
+ qemu_irq_lower(timer0.irq[0]);
+ etrax_ack_irq(timer0.env, 1 << 0x1b);
+ }
+}
+
+static void
+timer_writel (void *opaque, target_phys_addr_t addr, uint32_t value)
+{
+ CPUState *env = opaque;
+ printf ("%s %x %x pc=%x\n",
+ __func__, addr, value, env->pc);
+ switch (addr)
+ {
+ case RW_TMR0_DIV:
+ printf ("RW_TMR0_DIV=%x\n", value);
+ timer0.limit = value;
+ break;
+ case RW_TMR0_CTRL:
+ printf ("RW_TMR0_CTRL=%x\n", value);
+ write_ctrl(&timer0, value);
+ break;
+ case RW_TMR1_DIV:
+ printf ("RW_TMR1_DIV=%x\n", value);
+ break;
+ case RW_TMR1_CTRL:
+ printf ("RW_TMR1_CTRL=%x\n", value);
+ break;
+ case RW_INTR_MASK:
+ printf ("RW_INTR_MASK=%x\n", value);
+ rw_intr_mask = value;
+ break;
+ case RW_ACK_INTR:
+ r_intr &= ~value;
+ timer_ack_irq();
+ break;
+ default:
+ printf ("%s %x %x pc=%x\n",
+ __func__, addr, value, env->pc);
+ break;
+ }
+}
+
+static CPUReadMemoryFunc *timer_read[] = {
+ &timer_readb,
+ &timer_readw,
+ &timer_readl,
+};
+
+static CPUWriteMemoryFunc *timer_write[] = {
+ &timer_writeb,
+ &timer_writew,
+ &timer_writel,
+};
+
+static void timer_irq(void *opaque)
+{
+ struct fs_timer_t *t = opaque;
+
+ r_intr |= t->mask;
+ if (t->mask & rw_intr_mask) {
+ qemu_irq_raise(t->irq[0]);
+ }
+}
+
+void etraxfs_timer_init(CPUState *env, qemu_irq *irqs)
+{
+ int timer_regs;
+
+ timer0.bh = qemu_bh_new(timer_irq, &timer0);
+ timer0.ptimer = ptimer_init(timer0.bh);
+ timer0.irq = irqs + 0x1b;
+ timer0.mask = 1;
+ timer0.env = env;
+
+ timer_regs = cpu_register_io_memory(0, timer_read, timer_write, env);
+ cpu_register_physical_memory (0xb001e000, 0x5c, timer_regs);
+}
Modified: trunk/src/host/qemu-neo1973/hw/grackle_pci.c
===================================================================
--- trunk/src/host/qemu-neo1973/hw/grackle_pci.c 2007-10-29 20:40:05 UTC (rev 3302)
+++ trunk/src/host/qemu-neo1973/hw/grackle_pci.c 2007-10-29 21:14:04 UTC (rev 3303)
@@ -1,7 +1,8 @@
/*
- * QEMU Grackle (heathrow PPC) PCI host
+ * QEMU Grackle PCI host (heathrow OldWorld PowerMac)
*
- * Copyright (c) 2006 Fabrice Bellard
+ * Copyright (c) 2006-2007 Fabrice Bellard
+ * Copyright (c) 2007 Jocelyn Mayer
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
@@ -23,6 +24,7 @@
*/
#include "vl.h"
+#include "ppc_mac.h"
typedef target_phys_addr_t pci_addr_t;
#include "pci_host.h"
@@ -82,7 +84,7 @@
static void pci_grackle_set_irq(qemu_irq *pic, int irq_num, int level)
{
- qemu_set_irq(pic[irq_num + 8], level);
+ qemu_set_irq(pic[irq_num + 0x15], level);
}
PCIBus *pci_grackle_init(uint32_t base, qemu_irq *pic)
@@ -93,7 +95,7 @@
s = qemu_mallocz(sizeof(GrackleState));
s->bus = pci_register_bus(pci_grackle_set_irq, pci_grackle_map_irq,
- pic, 0, 0);
+ pic, 0, 4);
pci_mem_config = cpu_register_io_memory(0, pci_grackle_config_read,
pci_grackle_config_write, s);
Modified: trunk/src/host/qemu-neo1973/hw/gt64xxx.c
===================================================================
--- trunk/src/host/qemu-neo1973/hw/gt64xxx.c 2007-10-29 20:40:05 UTC (rev 3302)
+++ trunk/src/host/qemu-neo1973/hw/gt64xxx.c 2007-10-29 21:14:04 UTC (rev 3303)
@@ -306,9 +306,8 @@
GT64120State *s = opaque;
uint32_t saddr;
-#ifdef TARGET_WORDS_BIGENDIAN
- val = bswap32(val);
-#endif
+ if (!(s->regs[GT_PCI0_CMD] & 1))
+ val = bswap32(val);
saddr = (addr & 0xfff) >> 2;
switch (saddr) {
@@ -528,8 +527,7 @@
s->pci->config_reg = val & 0x80fffffc;
break;
case GT_PCI0_CFGDATA:
- if (s->pci->config_reg & (1u << 31))
- pci_host_data_writel(s->pci, 0, val);
+ pci_host_data_writel(s->pci, 0, val);
break;
/* Interrupts */
@@ -585,9 +583,7 @@
uint32_t val;
uint32_t saddr;
- val = 0;
saddr = (addr & 0xfff) >> 2;
-
switch (saddr) {
/* CPU Configuration */
@@ -768,10 +764,7 @@
val = s->pci->config_reg;
break;
case GT_PCI0_CFGDATA:
- if (!(s->pci->config_reg & (1u << 31)))
- val = 0xffffffff;
- else
- val = pci_host_data_readl(s->pci, 0);
+ val = pci_host_data_readl(s->pci, 0);
break;
case GT_PCI0_CMD:
@@ -844,9 +837,9 @@
break;
}
-#ifdef TARGET_WORDS_BIGENDIAN
- val = bswap32(val);
-#endif
+ if (!(s->regs[GT_PCI0_CMD] & 1))
+ val = bswap32(val);
+
return val;
}
@@ -1083,19 +1076,12 @@
static uint32_t gt64120_read_config(PCIDevice *d, uint32_t address, int len)
{
- uint32_t val = pci_default_read_config(d, address, len);
-#ifdef TARGET_WORDS_BIGENDIAN
- val = bswap32(val);
-#endif
- return val;
+ return pci_default_read_config(d, address, len);
}
static void gt64120_write_config(PCIDevice *d, uint32_t address, uint32_t val,
int len)
{
-#ifdef TARGET_WORDS_BIGENDIAN
- val = bswap32(val);
-#endif
pci_default_write_config(d, address, val, len);
}
Modified: trunk/src/host/qemu-neo1973/hw/heathrow_pic.c
===================================================================
--- trunk/src/host/qemu-neo1973/hw/heathrow_pic.c 2007-10-29 20:40:05 UTC (rev 3302)
+++ trunk/src/host/qemu-neo1973/hw/heathrow_pic.c 2007-10-29 21:14:04 UTC (rev 3303)
@@ -1,7 +1,8 @@
/*
- * Heathrow PIC support (standard PowerMac PIC)
+ * Heathrow PIC support (OldWorld PowerMac)
*
- * Copyright (c) 2005 Fabrice Bellard
+ * Copyright (c) 2005-2007 Fabrice Bellard
+ * Copyright (c) 2007 Jocelyn Mayer
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
@@ -22,6 +23,7 @@
* THE SOFTWARE.
*/
#include "vl.h"
+#include "ppc_mac.h"
//#define DEBUG
@@ -34,6 +36,7 @@
typedef struct HeathrowPICS {
HeathrowPIC pics[2];
+ qemu_irq *irqs;
} HeathrowPICS;
static inline int check_irq(HeathrowPIC *pic)
@@ -45,9 +48,9 @@
static void heathrow_pic_update(HeathrowPICS *s)
{
if (check_irq(&s->pics[0]) || check_irq(&s->pics[1])) {
- cpu_interrupt(first_cpu, CPU_INTERRUPT_HARD);
+ qemu_irq_raise(s->irqs[0]);
} else {
- cpu_reset_interrupt(first_cpu, CPU_INTERRUPT_HARD);
+ qemu_irq_lower(s->irqs[0]);
}
}
@@ -57,12 +60,13 @@
HeathrowPIC *pic;
unsigned int n;
+#ifdef TARGET_WORDS_BIGENDIAN
value = bswap32(value);
+#endif
+ n = ((addr & 0xfff) - 0x10) >> 4;
#ifdef DEBUG
- printf("pic_writel: %08x: %08x\n",
- addr, value);
+ printf("pic_writel: " PADDRX " %u: %08x\n", addr, n, value);
#endif
- n = ((addr & 0xfff) - 0x10) >> 4;
if (n >= 2)
return;
pic = &s->pics[n];
@@ -110,10 +114,11 @@
}
}
#ifdef DEBUG
- printf("pic_readl: %08x: %08x\n",
- addr, value);
+ printf("pic_readl: " PADDRX " %u: %08x\n", addr, n, value);
#endif
+#ifdef TARGET_WORDS_BIGENDIAN
value = bswap32(value);
+#endif
return value;
}
@@ -156,13 +161,17 @@
heathrow_pic_update(s);
}
-qemu_irq *heathrow_pic_init(int *pmem_index)
+qemu_irq *heathrow_pic_init(int *pmem_index,
+ int nb_cpus, qemu_irq **irqs)
{
HeathrowPICS *s;
s = qemu_mallocz(sizeof(HeathrowPICS));
s->pics[0].level_triggered = 0;
s->pics[1].level_triggered = 0x1ff00000;
+ /* only 1 CPU */
+ s->irqs = irqs[0];
*pmem_index = cpu_register_io_memory(0, pic_read, pic_write, s);
+
return qemu_allocate_irqs(heathrow_pic_set_irq, s, 64);
}
Modified: trunk/src/host/qemu-neo1973/hw/i8259.c
===================================================================
--- trunk/src/host/qemu-neo1973/hw/i8259.c 2007-10-29 20:40:05 UTC (rev 3302)
+++ trunk/src/host/qemu-neo1973/hw/i8259.c 2007-10-29 21:14:04 UTC (rev 3303)
@@ -164,7 +164,7 @@
}
/* all targets should do this rather than acking the IRQ in the cpu */
-#if defined(TARGET_MIPS)
+#if defined(TARGET_MIPS) || defined(TARGET_PPC)
else {
qemu_irq_lower(s->parent_irq);
}
Modified: trunk/src/host/qemu-neo1973/hw/iommu.c
===================================================================
--- trunk/src/host/qemu-neo1973/hw/iommu.c 2007-10-29 20:40:05 UTC (rev 3302)
+++ trunk/src/host/qemu-neo1973/hw/iommu.c 2007-10-29 21:14:04 UTC (rev 3303)
@@ -81,7 +81,7 @@
#define IOMMU_SBCFG_BA16 0x00000004 /* Slave supports 16 byte bursts */
#define IOMMU_SBCFG_BA8 0x00000002 /* Slave supports 8 byte bursts */
#define IOMMU_SBCFG_BYPASS 0x00000001 /* Bypass IOMMU, treat all addresses
- produced by this device as pure
+ produced by this device as pure
physical. */
#define IOMMU_SBCFG_MASK 0x00010003
@@ -98,7 +98,7 @@
#define PAGE_SHIFT 12
#define PAGE_SIZE (1 << PAGE_SHIFT)
-#define PAGE_MASK (PAGE_SIZE - 1)
+#define PAGE_MASK (PAGE_SIZE - 1)
typedef struct IOMMUState {
target_phys_addr_t addr;
@@ -114,9 +114,9 @@
saddr = (addr - s->addr) >> 2;
switch (saddr) {
default:
- DPRINTF("read reg[%d] = %x\n", (int)saddr, s->regs[saddr]);
- return s->regs[saddr];
- break;
+ DPRINTF("read reg[%d] = %x\n", (int)saddr, s->regs[saddr]);
+ return s->regs[saddr];
+ break;
}
return 0;
}
@@ -130,61 +130,61 @@
DPRINTF("write reg[%d] = %x\n", (int)saddr, val);
switch (saddr) {
case IOMMU_CTRL:
- switch (val & IOMMU_CTRL_RNGE) {
- case IOMMU_RNGE_16MB:
- s->iostart = 0xffffffffff000000ULL;
- break;
- case IOMMU_RNGE_32MB:
- s->iostart = 0xfffffffffe000000ULL;
- break;
- case IOMMU_RNGE_64MB:
- s->iostart = 0xfffffffffc000000ULL;
- break;
- case IOMMU_RNGE_128MB:
- s->iostart = 0xfffffffff8000000ULL;
- break;
- case IOMMU_RNGE_256MB:
- s->iostart = 0xfffffffff0000000ULL;
- break;
- case IOMMU_RNGE_512MB:
- s->iostart = 0xffffffffe0000000ULL;
- break;
- case IOMMU_RNGE_1GB:
- s->iostart = 0xffffffffc0000000ULL;
- break;
- default:
- case IOMMU_RNGE_2GB:
- s->iostart = 0xffffffff80000000ULL;
- break;
- }
- DPRINTF("iostart = " TARGET_FMT_plx "\n", s->iostart);
- s->regs[saddr] = ((val & IOMMU_CTRL_MASK) | IOMMU_VERSION);
- break;
+ switch (val & IOMMU_CTRL_RNGE) {
+ case IOMMU_RNGE_16MB:
+ s->iostart = 0xffffffffff000000ULL;
+ break;
+ case IOMMU_RNGE_32MB:
+ s->iostart = 0xfffffffffe000000ULL;
+ break;
+ case IOMMU_RNGE_64MB:
+ s->iostart = 0xfffffffffc000000ULL;
+ break;
+ case IOMMU_RNGE_128MB:
+ s->iostart = 0xfffffffff8000000ULL;
+ break;
+ case IOMMU_RNGE_256MB:
+ s->iostart = 0xfffffffff0000000ULL;
+ break;
+ case IOMMU_RNGE_512MB:
+ s->iostart = 0xffffffffe0000000ULL;
+ break;
+ case IOMMU_RNGE_1GB:
+ s->iostart = 0xffffffffc0000000ULL;
+ break;
+ default:
+ case IOMMU_RNGE_2GB:
+ s->iostart = 0xffffffff80000000ULL;
+ break;
+ }
+ DPRINTF("iostart = " TARGET_FMT_plx "\n", s->iostart);
+ s->regs[saddr] = ((val & IOMMU_CTRL_MASK) | IOMMU_VERSION);
+ break;
case IOMMU_BASE:
- s->regs[saddr] = val & IOMMU_BASE_MASK;
- break;
+ s->regs[saddr] = val & IOMMU_BASE_MASK;
+ break;
case IOMMU_TLBFLUSH:
- DPRINTF("tlb flush %x\n", val);
- s->regs[saddr] = val & IOMMU_TLBFLUSH_MASK;
- break;
+ DPRINTF("tlb flush %x\n", val);
+ s->regs[saddr] = val & IOMMU_TLBFLUSH_MASK;
+ break;
case IOMMU_PGFLUSH:
- DPRINTF("page flush %x\n", val);
- s->regs[saddr] = val & IOMMU_PGFLUSH_MASK;
- break;
+ DPRINTF("page flush %x\n", val);
+ s->regs[saddr] = val & IOMMU_PGFLUSH_MASK;
+ break;
case IOMMU_SBCFG0:
case IOMMU_SBCFG1:
case IOMMU_SBCFG2:
case IOMMU_SBCFG3:
- s->regs[saddr] = val & IOMMU_SBCFG_MASK;
- break;
+ s->regs[saddr] = val & IOMMU_SBCFG_MASK;
+ break;
case IOMMU_ARBEN:
// XXX implement SBus probing: fault when reading unmapped
// addresses, fault cause and address stored to MMU/IOMMU
- s->regs[saddr] = (val & IOMMU_ARBEN_MASK) | IOMMU_MID;
- break;
+ s->regs[saddr] = (val & IOMMU_ARBEN_MASK) | IOMMU_MID;
+ break;
default:
- s->regs[saddr] = val;
- break;
+ s->regs[saddr] = val;
+ break;
}
}
@@ -202,7 +202,8 @@
static uint32_t iommu_page_get_flags(IOMMUState *s, target_phys_addr_t addr)
{
- uint32_t iopte, ret;
+ uint32_t ret;
+ target_phys_addr_t iopte;
#ifdef DEBUG_IOMMU
target_phys_addr_t pa = addr;
#endif
@@ -210,9 +211,10 @@
iopte = s->regs[IOMMU_BASE] << 4;
addr &= ~s->iostart;
iopte += (addr >> (PAGE_SHIFT - 2)) & ~3;
- ret = ldl_phys(iopte);
- DPRINTF("get flags addr " TARGET_FMT_plx " => pte %x, *ptes = %x\n", pa,
- iopte, ret);
+ cpu_physical_memory_read(iopte, (uint8_t *)&ret, 4);
+ tswap32s(&ret);
+ DPRINTF("get flags addr " TARGET_FMT_plx " => pte " TARGET_FMT_plx
+ ", *pte = %x\n", pa, iopte, ret);
return ret;
}
@@ -281,7 +283,7 @@
int i;
for (i = 0; i < IOMMU_NREGS; i++)
- qemu_put_be32s(f, &s->regs[i]);
+ qemu_put_be32s(f, &s->regs[i]);
qemu_put_be64s(f, &s->iostart);
}
Modified: trunk/src/host/qemu-neo1973/hw/irq.c
===================================================================
--- trunk/src/host/qemu-neo1973/hw/irq.c 2007-10-29 20:40:05 UTC (rev 3302)
+++ trunk/src/host/qemu-neo1973/hw/irq.c 2007-10-29 21:14:04 UTC (rev 3303)
@@ -55,3 +55,14 @@
return s;
}
+static void qemu_notirq(void *opaque, int line, int level)
+{
+ struct IRQState *irq = opaque;
+
+ irq->handler(irq->opaque, irq->n, !level);
+}
+
+qemu_irq qemu_irq_invert(qemu_irq irq)
+{
+ return qemu_allocate_irqs(qemu_notirq, irq, 1)[0];
+}
Modified: trunk/src/host/qemu-neo1973/hw/irq.h
===================================================================
--- trunk/src/host/qemu-neo1973/hw/irq.h 2007-10-29 20:40:05 UTC (rev 3302)
+++ trunk/src/host/qemu-neo1973/hw/irq.h 2007-10-29 21:14:04 UTC (rev 3303)
@@ -19,3 +19,5 @@
/* Returns an array of N IRQs. */
qemu_irq *qemu_allocate_irqs(qemu_irq_handler handler, void *opaque, int n);
+/* Returns a new IRQ with opposite polarity. */
+qemu_irq qemu_irq_invert(qemu_irq irq);
Modified: trunk/src/host/qemu-neo1973/hw/m48t59.c
===================================================================
--- trunk/src/host/qemu-neo1973/hw/m48t59.c 2007-10-29 20:40:05 UTC (rev 3302)
+++ trunk/src/host/qemu-neo1973/hw/m48t59.c 2007-10-29 21:14:04 UTC (rev 3303)
@@ -161,10 +161,9 @@
NVRAM->alarm = mktime(tm);
if (NVRAM->alrm_timer != NULL) {
qemu_del_timer(NVRAM->alrm_timer);
- NVRAM->alrm_timer = NULL;
+ if (NVRAM->alarm - time(NULL) > 0)
+ qemu_mod_timer(NVRAM->alrm_timer, NVRAM->alarm * 1000);
}
- if (NVRAM->alarm - time(NULL) > 0)
- qemu_mod_timer(NVRAM->alrm_timer, NVRAM->alarm * 1000);
}
/* Watchdog management */
@@ -188,21 +187,21 @@
{
uint64_t interval; /* in 1/16 seconds */
+ NVRAM->buffer[0x1FF0] &= ~0x80;
if (NVRAM->wd_timer != NULL) {
qemu_del_timer(NVRAM->wd_timer);
- NVRAM->wd_timer = NULL;
+ if (value != 0) {
+ interval = (1 << (2 * (value & 0x03))) * ((value >> 2) & 0x1F);
+ qemu_mod_timer(NVRAM->wd_timer, ((uint64_t)time(NULL) * 1000) +
+ ((interval * 1000) >> 4));
+ }
}
- NVRAM->buffer[0x1FF0] &= ~0x80;
- if (value != 0) {
- interval = (1 << (2 * (value & 0x03))) * ((value >> 2) & 0x1F);
- qemu_mod_timer(NVRAM->wd_timer, ((uint64_t)time(NULL) * 1000) +
- ((interval * 1000) >> 4));
- }
}
/* Direct access to NVRAM */
-void m48t59_write (m48t59_t *NVRAM, uint32_t addr, uint32_t val)
+void m48t59_write (void *opaque, uint32_t addr, uint32_t val)
{
+ m48t59_t *NVRAM = opaque;
struct tm tm;
int tmp;
@@ -359,8 +358,9 @@
}
}
-uint32_t m48t59_read (m48t59_t *NVRAM, uint32_t addr)
+uint32_t m48t59_read (void *opaque, uint32_t addr)
{
+ m48t59_t *NVRAM = opaque;
struct tm tm;
uint32_t retval = 0xFF;
@@ -453,13 +453,17 @@
return retval;
}
-void m48t59_set_addr (m48t59_t *NVRAM, uint32_t addr)
+void m48t59_set_addr (void *opaque, uint32_t addr)
{
+ m48t59_t *NVRAM = opaque;
+
NVRAM->addr = addr;
}
-void m48t59_toggle_lock (m48t59_t *NVRAM, int lock)
+void m48t59_toggle_lock (void *opaque, int lock)
{
+ m48t59_t *NVRAM = opaque;
+
NVRAM->lock ^= 1 << lock;
}
Modified: trunk/src/host/qemu-neo1973/hw/m48t59.h
===================================================================
--- trunk/src/host/qemu-neo1973/hw/m48t59.h 2007-10-29 20:40:05 UTC (rev 3302)
+++ trunk/src/host/qemu-neo1973/hw/m48t59.h 2007-10-29 21:14:04 UTC (rev 3303)
@@ -3,9 +3,9 @@
typedef struct m48t59_t m48t59_t;
-void m48t59_write (m48t59_t *NVRAM, uint32_t addr, uint32_t val);
-uint32_t m48t59_read (m48t59_t *NVRAM, uint32_t addr);
-void m48t59_toggle_lock (m48t59_t *NVRAM, int lock);
+void m48t59_write (void *private, uint32_t addr, uint32_t val);
+uint32_t m48t59_read (void *private, uint32_t addr);
+void m48t59_toggle_lock (void *private, int lock);
m48t59_t *m48t59_init (qemu_irq IRQ, target_phys_addr_t mem_base,
uint32_t io_base, uint16_t size,
int type);
Added: trunk/src/host/qemu-neo1973/hw/mac_dbdma.c
===================================================================
--- trunk/src/host/qemu-neo1973/hw/mac_dbdma.c 2007-10-29 20:40:05 UTC (rev 3302)
+++ trunk/src/host/qemu-neo1973/hw/mac_dbdma.c 2007-10-29 21:14:04 UTC (rev 3303)
@@ -0,0 +1,79 @@
+/*
+ * PowerMac descriptor-based DMA emulation
+ *
+ * Copyright (c) 2005-2007 Fabrice Bellard
+ * Copyright (c) 2007 Jocelyn Mayer
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+#include "vl.h"
+#include "ppc_mac.h"
+
+/* DBDMA: currently no op - should suffice right now */
+
+static void dbdma_writeb (void *opaque,
+ target_phys_addr_t addr, uint32_t value)
+{
+ printf("%s: 0x" PADDRX " <= 0x%08x\n", __func__, addr, value);
+}
+
+static void dbdma_writew (void *opaque,
+ target_phys_addr_t addr, uint32_t value)
+{
+}
+
+static void dbdma_writel (void *opaque,
+ target_phys_addr_t addr, uint32_t value)
+{
+}
+
+static uint32_t dbdma_readb (void *opaque, target_phys_addr_t addr)
+{
+ printf("%s: 0x" PADDRX " => 0x00000000\n", __func__, addr);
+
+ return 0;
+}
+
+static uint32_t dbdma_readw (void *opaque, target_phys_addr_t addr)
+{
+ return 0;
+}
+
+static uint32_t dbdma_readl (void *opaque, target_phys_addr_t addr)
+{
+ return 0;
+}
+
+static CPUWriteMemoryFunc *dbdma_write[] = {
+ &dbdma_writeb,
+ &dbdma_writew,
+ &dbdma_writel,
+};
+
+static CPUReadMemoryFunc *dbdma_read[] = {
+ &dbdma_readb,
+ &dbdma_readw,
+ &dbdma_readl,
+};
+
+void dbdma_init (int *dbdma_mem_index)
+{
+ *dbdma_mem_index = cpu_register_io_memory(0, dbdma_read, dbdma_write, NULL);
+}
+
Added: trunk/src/host/qemu-neo1973/hw/mac_nvram.c
===================================================================
--- trunk/src/host/qemu-neo1973/hw/mac_nvram.c 2007-10-29 20:40:05 UTC (rev 3302)
+++ trunk/src/host/qemu-neo1973/hw/mac_nvram.c 2007-10-29 21:14:04 UTC (rev 3303)
@@ -0,0 +1,123 @@
+/*
+ * PowerMac NVRAM emulation
+ *
+ * Copyright (c) 2005-2007 Fabrice Bellard
+ * Copyright (c) 2007 Jocelyn Mayer
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+#include "vl.h"
+#include "ppc_mac.h"
+
+struct MacIONVRAMState {
+ uint8_t data[0x2000];
+};
+
+/* Direct access to NVRAM */
+uint32_t macio_nvram_read (void *opaque, uint32_t addr)
+{
+ MacIONVRAMState *s = opaque;
+ uint32_t ret;
+
+ // printf("%s: %p addr %04x\n", __func__, s, addr);
+ if (addr < 0x2000)
+ ret = s->data[addr];
+ else
+ ret = -1;
+
+ return ret;
+}
+
+void macio_nvram_write (void *opaque, uint32_t addr, uint32_t val)
+{
+ MacIONVRAMState *s = opaque;
+
+ // printf("%s: %p addr %04x val %02x\n", __func__, s, addr, val);
+ if (addr < 0x2000)
+ s->data[addr] = val;
+}
+
+/* macio style NVRAM device */
+static void macio_nvram_writeb (void *opaque,
+ target_phys_addr_t addr, uint32_t value)
+{
+ MacIONVRAMState *s = opaque;
+ addr = (addr >> 4) & 0x1fff;
+ s->data[addr] = value;
+ // printf("macio_nvram_writeb %04x = %02x\n", addr, value);
+}
+
+static uint32_t macio_nvram_readb (void *opaque, target_phys_addr_t addr)
+{
+ MacIONVRAMState *s = opaque;
+ uint32_t value;
+
+ addr = (addr >> 4) & 0x1fff;
+ value = s->data[addr];
+ // printf("macio_nvram_readb %04x = %02x\n", addr, value);
+
+ return value;
+}
+
+static CPUWriteMemoryFunc *nvram_write[] = {
+ &macio_nvram_writeb,
+ &macio_nvram_writeb,
+ &macio_nvram_writeb,
+};
+
+static CPUReadMemoryFunc *nvram_read[] = {
+ &macio_nvram_readb,
+ &macio_nvram_readb,
+ &macio_nvram_readb,
+};
+
+MacIONVRAMState *macio_nvram_init (int *mem_index)
+{
+ MacIONVRAMState *s;
+ s = qemu_mallocz(sizeof(MacIONVRAMState));
+ if (!s)
+ return NULL;
+ *mem_index = cpu_register_io_memory(0, nvram_read, nvram_write, s);
+
+ return s;
+}
+
+static uint8_t nvram_chksum (const uint8_t *buf, int n)
+{
+ int sum, i;
+ sum = 0;
+ for(i = 0; i < n; i++)
+ sum += buf[i];
+ return (sum & 0xff) + (sum >> 8);
+}
+
+/* set a free Mac OS NVRAM partition */
+void pmac_format_nvram_partition (MacIONVRAMState *nvr, int len)
+{
+ uint8_t *buf;
+ char partition_name[12] = "wwwwwwwwwwww";
+
+ buf = nvr->data;
+ buf[0] = 0x7f; /* free partition magic */
+ buf[1] = 0; /* checksum */
+ buf[2] = len >> 8;
+ buf[3] = len;
+ memcpy(buf + 4, partition_name, 12);
+ buf[1] = nvram_chksum(buf, 16);
+}
Added: trunk/src/host/qemu-neo1973/hw/macio.c
===================================================================
--- trunk/src/host/qemu-neo1973/hw/macio.c 2007-10-29 20:40:05 UTC (rev 3302)
+++ trunk/src/host/qemu-neo1973/hw/macio.c 2007-10-29 21:14:04 UTC (rev 3303)
@@ -0,0 +1,116 @@
+/*
+ * PowerMac MacIO device emulation
+ *
+ * Copyright (c) 2005-2007 Fabrice Bellard
+ * Copyright (c) 2007 Jocelyn Mayer
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+#include "vl.h"
+#include "ppc_mac.h"
+
+typedef struct macio_state_t macio_state_t;
+struct macio_state_t {
+ int is_oldworld;
+ int pic_mem_index;
+ int dbdma_mem_index;
+ int cuda_mem_index;
+ int nvram_mem_index;
+ int nb_ide;
+ int ide_mem_index[4];
+};
+
+static void macio_map (PCIDevice *pci_dev, int region_num,
+ uint32_t addr, uint32_t size, int type)
+{
+ macio_state_t *macio_state;
+ int i;
+
+ macio_state = (macio_state_t *)(pci_dev + 1);
+ if (macio_state->pic_mem_index >= 0) {
+ if (macio_state->is_oldworld) {
+ /* Heathrow PIC */
+ cpu_register_physical_memory(addr + 0x00000, 0x1000,
+ macio_state->pic_mem_index);
+ } else {
+ /* OpenPIC */
+ cpu_register_physical_memory(addr + 0x40000, 0x40000,
+ macio_state->pic_mem_index);
+ }
+ }
+ if (macio_state->dbdma_mem_index >= 0) {
+ cpu_register_physical_memory(addr + 0x08000, 0x1000,
+ macio_state->dbdma_mem_index);
+ }
+ if (macio_state->cuda_mem_index >= 0) {
+ cpu_register_physical_memory(addr + 0x16000, 0x2000,
+ macio_state->cuda_mem_index);
+ }
+ for (i = 0; i < macio_state->nb_ide; i++) {
+ if (macio_state->ide_mem_index[i] >= 0) {
+ cpu_register_physical_memory(addr + 0x1f000 + (i * 0x1000), 0x1000,
+ 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);
+ }
+}
+
+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 nb_ide, int *ide_mem_index)
+{
+ PCIDevice *d;
+ macio_state_t *macio_state;
+ int i;
+
+ d = pci_register_device(bus, "macio",
+ sizeof(PCIDevice) + sizeof(macio_state_t),
+ -1, NULL, NULL);
+ macio_state = (macio_state_t *)(d + 1);
+ macio_state->is_oldworld = is_oldworld;
+ 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;
+ if (nb_ide > 4)
+ nb_ide = 4;
+ macio_state->nb_ide = nb_ide;
+ for (i = 0; i < nb_ide; i++)
+ macio_state->ide_mem_index[i] = ide_mem_index[i];
+ for (; i < 4; i++)
+ macio_state->ide_mem_index[i] = -1;
+ /* Note: this code is strongly inspirated from the corresponding code
+ in PearPC */
+ d->config[0x00] = 0x6b; // vendor_id
+ d->config[0x01] = 0x10;
+ d->config[0x02] = device_id;
+ d->config[0x03] = device_id >> 8;
+
+ d->config[0x0a] = 0x00; // class_sub = pci2pci
+ d->config[0x0b] = 0xff; // class_base = bridge
+ d->config[0x0e] = 0x00; // header_type
+
+ d->config[0x3d] = 0x01; // interrupt on pin 1
+
+ pci_register_io_region(d, 0, 0x80000,
+ PCI_ADDRESS_SPACE_MEM, macio_map);
+}
Modified: trunk/src/host/qemu-neo1973/hw/mips_malta.c
===================================================================
--- trunk/src/host/qemu-neo1973/hw/mips_malta.c 2007-10-29 20:40:05 UTC (rev 3302)
+++ trunk/src/host/qemu-neo1973/hw/mips_malta.c 2007-10-29 21:14:04 UTC (rev 3303)
@@ -791,7 +791,9 @@
/* Load a BIOS image unless a kernel image has been specified. */
if (!kernel_filename) {
- snprintf(buf, sizeof(buf), "%s/%s", bios_dir, BIOS_FILENAME);
+ if (bios_name == NULL)
+ bios_name = BIOS_FILENAME;
+ snprintf(buf, sizeof(buf), "%s/%s", bios_dir, bios_name);
ret = load_image(buf, phys_ram_base + bios_offset);
if (ret < 0 || ret > BIOS_SIZE) {
fprintf(stderr,
Added: trunk/src/host/qemu-neo1973/hw/mips_mipssim.c
===================================================================
--- trunk/src/host/qemu-neo1973/hw/mips_mipssim.c 2007-10-29 20:40:05 UTC (rev 3302)
+++ trunk/src/host/qemu-neo1973/hw/mips_mipssim.c 2007-10-29 21:14:04 UTC (rev 3303)
@@ -0,0 +1,166 @@
+/*
+ * QEMU/mipssim emulation
+ *
+ * Emulates a very simple machine model similiar to the one use by the
+ * proprietary MIPS emulator.
+ */
+#include "vl.h"
+
+#ifdef TARGET_WORDS_BIGENDIAN
+#define BIOS_FILENAME "mips_bios.bin"
+#else
+#define BIOS_FILENAME "mipsel_bios.bin"
+#endif
+
+#ifdef TARGET_MIPS64
+#define PHYS_TO_VIRT(x) ((x) | ~0x7fffffffULL)
+#else
+#define PHYS_TO_VIRT(x) ((x) | ~0x7fffffffU)
+#endif
+
+#define VIRT_TO_PHYS_ADDEND (-((int64_t)(int32_t)0x80000000))
+
+static void load_kernel (CPUState *env)
+{
+ int64_t entry, kernel_low, kernel_high;
+ long kernel_size;
+ long initrd_size;
+ ram_addr_t initrd_offset;
+
+ kernel_size = load_elf(env->kernel_filename, VIRT_TO_PHYS_ADDEND,
+ &entry, &kernel_low, &kernel_high);
+ if (kernel_size >= 0) {
+ if ((entry & ~0x7fffffffULL) == 0x80000000)
+ entry = (int32_t)entry;
+ env->PC[env->current_tc] = entry;
+ } else {
+ fprintf(stderr, "qemu: could not load kernel '%s'\n",
+ env->kernel_filename);
+ exit(1);
+ }
+
+ /* load initrd */
+ initrd_size = 0;
+ initrd_offset = 0;
+ if (env->initrd_filename) {
+ initrd_size = get_image_size (env->initrd_filename);
+ if (initrd_size > 0) {
+ initrd_offset = (kernel_high + ~TARGET_PAGE_MASK) & TARGET_PAGE_MASK;
+ if (initrd_offset + initrd_size > env->ram_size) {
+ fprintf(stderr,
+ "qemu: memory too small for initial ram disk '%s'\n",
+ env->initrd_filename);
+ exit(1);
+ }
+ initrd_size = load_image(env->initrd_filename,
+ phys_ram_base + initrd_offset);
+ }
+ if (initrd_size == (target_ulong) -1) {
+ fprintf(stderr, "qemu: could not load initial ram disk '%s'\n",
+ env->initrd_filename);
+ exit(1);
+ }
+ }
+}
+
+static void main_cpu_reset(void *opaque)
+{
+ CPUState *env = opaque;
+ cpu_reset(env);
+ cpu_mips_register(env, NULL);
+
+ if (env->kernel_filename)
+ load_kernel (env);
+}
+
+static void
+mips_mipssim_init (int ram_size, int vga_ram_size, int boot_device,
+ DisplayState *ds, const char **fd_filename, int snapshot,
+ const char *kernel_filename, const char *kernel_cmdline,
+ const char *initrd_filename, const char *cpu_model)
+{
+ char buf[1024];
+ unsigned long bios_offset;
+ CPUState *env;
+ int bios_size;
+ mips_def_t *def;
+
+ /* Init CPUs. */
+ if (cpu_model == NULL) {
+#ifdef TARGET_MIPS64
+ cpu_model = "5Kf";
+#else
+ cpu_model = "24Kf";
+#endif
+ }
+ if (mips_find_by_name(cpu_model, &def) != 0)
+ def = NULL;
+ env = cpu_init();
+ cpu_mips_register(env, def);
+ register_savevm("cpu", 0, 3, cpu_save, cpu_load, env);
+ qemu_register_reset(main_cpu_reset, env);
+
+ /* Allocate RAM. */
+ cpu_register_physical_memory(0, ram_size, IO_MEM_RAM);
+
+ /* Load a BIOS / boot exception handler image. */
+ bios_offset = ram_size + vga_ram_size;
+ if (bios_name == NULL)
+ bios_name = BIOS_FILENAME;
+ snprintf(buf, sizeof(buf), "%s/%s", bios_dir, bios_name);
+ bios_size = load_image(buf, phys_ram_base + bios_offset);
+ if ((bios_size < 0 || bios_size > BIOS_SIZE) && !kernel_filename) {
+ /* Bail out if we have neither a kernel image nor boot vector code. */
+ fprintf(stderr,
+ "qemu: Could not load MIPS bios '%s', and no -kernel argument was specified\n",
+ buf);
+ exit(1);
+ } else {
+ /* Map the BIOS / boot exception handler. */
+ cpu_register_physical_memory(0x1fc00000LL,
+ bios_size, bios_offset | IO_MEM_ROM);
+ /* We have a boot vector start address. */
+ env->PC[env->current_tc] = (target_long)(int32_t)0xbfc00000;
+ }
+
+ if (kernel_filename) {
+ env->ram_size = ram_size;
+ env->kernel_filename = kernel_filename;
+ env->kernel_cmdline = kernel_cmdline;
+ env->initrd_filename = initrd_filename;
+ load_kernel(env);
+ }
+
+ /* Init CPU internal devices. */
+ cpu_mips_irq_init_cpu(env);
+ cpu_mips_clock_init(env);
+ cpu_mips_irqctrl_init();
+
+ /* Register 64 KB of ISA IO space at 0x1fd00000. */
+ isa_mmio_init(0x1fd00000, 0x00010000);
+
+ /* A single 16450 sits at offset 0x3f8. It is attached to
+ MIPS CPU INT2, which is interrupt 4. */
+ if (serial_hds[0])
+ serial_init(0x3f8, env->irq[4], serial_hds[0]);
+
+ if (nd_table[0].vlan) {
+ if (nd_table[0].model == NULL
+ || strcmp(nd_table[0].model, "mipsnet") == 0) {
+ /* MIPSnet uses the MIPS CPU INT0, which is interrupt 2. */
+ mipsnet_init(0x4200, env->irq[2], &nd_table[0]);
+ } else if (strcmp(nd_table[0].model, "?") == 0) {
+ fprintf(stderr, "qemu: Supported NICs: mipsnet\n");
+ exit (1);
+ } else {
+ fprintf(stderr, "qemu: Unsupported NIC: %s\n", nd_table[0].model);
+ exit (1);
+ }
+ }
+}
+
+QEMUMachine mips_mipssim_machine = {
+ "mipssim",
+ "MIPS MIPSsim platform",
+ mips_mipssim_init,
+};
Modified: trunk/src/host/qemu-neo1973/hw/mips_pica61.c
===================================================================
--- trunk/src/host/qemu-neo1973/hw/mips_pica61.c 2007-10-29 20:40:05 UTC (rev 3302)
+++ trunk/src/host/qemu-neo1973/hw/mips_pica61.c 2007-10-29 21:14:04 UTC (rev 3303)
@@ -94,7 +94,9 @@
/* load a BIOS image */
bios_offset = ram_size + vga_ram_size;
- snprintf(buf, sizeof(buf), "%s/%s", bios_dir, BIOS_FILENAME);
+ if (bios_name == NULL)
+ bios_name = BIOS_FILENAME;
+ snprintf(buf, sizeof(buf), "%s/%s", bios_dir, bios_name);
bios_size = load_image(buf, phys_ram_base + bios_offset);
if ((bios_size <= 0) || (bios_size > BIOS_SIZE)) {
/* fatal */
Modified: trunk/src/host/qemu-neo1973/hw/mips_r4k.c
===================================================================
--- trunk/src/host/qemu-neo1973/hw/mips_r4k.c 2007-10-29 20:40:05 UTC (rev 3302)
+++ trunk/src/host/qemu-neo1973/hw/mips_r4k.c 2007-10-29 21:14:04 UTC (rev 3303)
@@ -64,9 +64,10 @@
static int mips_qemu_iomemtype = 0;
-void load_kernel (CPUState *env, int ram_size, const char *kernel_filename,
- const char *kernel_cmdline,
- const char *initrd_filename)
+static void load_kernel (CPUState *env, int ram_size,
+ const char *kernel_filename,
+ const char *kernel_cmdline,
+ const char *initrd_filename)
{
int64_t entry, kernel_low, kernel_high;
long kernel_size, initrd_size;
@@ -179,7 +180,9 @@
preloaded we also initialize the hardware, since the BIOS wasn't
run. */
bios_offset = ram_size + vga_ram_size;
- snprintf(buf, sizeof(buf), "%s/%s", bios_dir, BIOS_FILENAME);
+ if (bios_name == NULL)
+ bios_name = BIOS_FILENAME;
+ snprintf(buf, sizeof(buf), "%s/%s", bios_dir, bios_name);
bios_size = load_image(buf, phys_ram_base + bios_offset);
if ((bios_size > 0) && (bios_size <= BIOS_SIZE)) {
cpu_register_physical_memory(0x1fc00000,
Modified: trunk/src/host/qemu-neo1973/hw/mips_timer.c
===================================================================
--- trunk/src/host/qemu-neo1973/hw/mips_timer.c 2007-10-29 20:40:05 UTC (rev 3302)
+++ trunk/src/host/qemu-neo1973/hw/mips_timer.c 2007-10-29 21:14:04 UTC (rev 3303)
@@ -17,9 +17,12 @@
/* MIPS R4K timer */
uint32_t cpu_mips_get_count (CPUState *env)
{
- return env->CP0_Count +
- (uint32_t)muldiv64(qemu_get_clock(vm_clock),
- 100 * 1000 * 1000, ticks_per_sec);
+ if (env->CP0_Cause & (1 << CP0Ca_DC))
+ return env->CP0_Count;
+ else
+ return env->CP0_Count +
+ (uint32_t)muldiv64(qemu_get_clock(vm_clock),
+ 100 * 1000 * 1000, ticks_per_sec);
}
void cpu_mips_store_count (CPUState *env, uint32_t count)
@@ -63,9 +66,21 @@
cpu_mips_update_count(env, cpu_mips_get_count(env));
if ((env->CP0_Config0 & (0x7 << CP0C0_AR)) == (1 << CP0C0_AR))
env->CP0_Cause &= ~(1 << CP0Ca_TI);
- qemu_irq_lower(env->irq[7]);
+ qemu_irq_lower(env->irq[(env->CP0_IntCtl >> CP0IntCtl_IPTI) & 0x7]);
}
+void cpu_mips_start_count(CPUState *env)
+{
+ cpu_mips_store_count(env, env->CP0_Count);
+}
+
+void cpu_mips_stop_count(CPUState *env)
+{
+ /* Store the current value */
+ env->CP0_Count += (uint32_t)muldiv64(qemu_get_clock(vm_clock),
+ 100 * 1000 * 1000, ticks_per_sec);
+}
+
static void mips_timer_cb (void *opaque)
{
CPUState *env;
@@ -76,10 +91,14 @@
fprintf(logfile, "%s\n", __func__);
}
#endif
+
+ if (env->CP0_Cause & (1 << CP0Ca_DC))
+ return;
+
cpu_mips_update_count(env, cpu_mips_get_count(env));
if ((env->CP0_Config0 & (0x7 << CP0C0_AR)) == (1 << CP0C0_AR))
env->CP0_Cause |= 1 << CP0Ca_TI;
- qemu_irq_raise(env->irq[7]);
+ qemu_irq_raise(env->irq[(env->CP0_IntCtl >> CP0IntCtl_IPTI) & 0x7]);
}
void cpu_mips_clock_init (CPUState *env)
Added: trunk/src/host/qemu-neo1973/hw/mipsnet.c
===================================================================
--- trunk/src/host/qemu-neo1973/hw/mipsnet.c 2007-10-29 20:40:05 UTC (rev 3302)
+++ trunk/src/host/qemu-neo1973/hw/mipsnet.c 2007-10-29 21:14:04 UTC (rev 3303)
@@ -0,0 +1,269 @@
+#include "vl.h"
+
+//#define DEBUG_MIPSNET_SEND
+//#define DEBUG_MIPSNET_RECEIVE
+//#define DEBUG_MIPSNET_DATA
+//#define DEBUG_MIPSNET_IRQ
+
+/* MIPSnet register offsets */
+
+#define MIPSNET_DEV_ID 0x00
+# define MIPSNET_DEV_ID_STRING "MIPSNET0"
+#define MIPSNET_BUSY 0x08
+#define MIPSNET_RX_DATA_COUNT 0x0c
+#define MIPSNET_TX_DATA_COUNT 0x10
+#define MIPSNET_INT_CTL 0x14
+# define MIPSNET_INTCTL_TXDONE 0x00000001
+# define MIPSNET_INTCTL_RXDONE 0x00000002
+# define MIPSNET_INTCTL_TESTBIT 0x80000000
+#define MIPSNET_INTERRUPT_INFO 0x18
+#define MIPSNET_RX_DATA_BUFFER 0x1c
+#define MIPSNET_TX_DATA_BUFFER 0x20
+
+#define MAX_ETH_FRAME_SIZE 1514
+
+typedef struct MIPSnetState {
+ uint32_t busy;
+ uint32_t rx_count;
+ uint32_t rx_read;
+ uint32_t tx_count;
+ uint32_t tx_written;
+ uint32_t intctl;
+ uint8_t rx_buffer[MAX_ETH_FRAME_SIZE];
+ uint8_t tx_buffer[MAX_ETH_FRAME_SIZE];
+ qemu_irq irq;
+ VLANClientState *vc;
+ NICInfo *nd;
+} MIPSnetState;
+
+static void mipsnet_reset(MIPSnetState *s)
+{
+ s->busy = 1;
+ s->rx_count = 0;
+ s->rx_read = 0;
+ s->tx_count = 0;
+ s->tx_written = 0;
+ s->intctl = 0;
+ memset(s->rx_buffer, 0, MAX_ETH_FRAME_SIZE);
+ memset(s->tx_buffer, 0, MAX_ETH_FRAME_SIZE);
+}
+
+static void mipsnet_update_irq(MIPSnetState *s)
+{
+ int isr = !!s->intctl;
+#ifdef DEBUG_MIPSNET_IRQ
+ printf("mipsnet: Set IRQ to %d (%02x)\n", isr, s->intctl);
+#endif
+ qemu_set_irq(s->irq, isr);
+}
+
+static int mipsnet_buffer_full(MIPSnetState *s)
+{
+ if (s->rx_count >= MAX_ETH_FRAME_SIZE)
+ return 1;
+ return 0;
+}
+
+static int mipsnet_can_receive(void *opaque)
+{
+ MIPSnetState *s = opaque;
+
+ if (s->busy)
+ return 0;
+ return !mipsnet_buffer_full(s);
+}
+
+static void mipsnet_receive(void *opaque, const uint8_t *buf, int size)
+{
+ MIPSnetState *s = opaque;
+
+#ifdef DEBUG_MIPSNET_RECEIVE
+ printf("mipsnet: receiving len=%d\n", size);
+#endif
+ if (!mipsnet_can_receive(opaque))
+ return;
+
+ s->busy = 1;
+
+ /* Just accept everything. */
+
+ /* Write packet data. */
+ memcpy(s->rx_buffer, buf, size);
+
+ s->rx_count = size;
+ s->rx_read = 0;
+
+ /* Now we can signal we have received something. */
+ s->intctl |= MIPSNET_INTCTL_RXDONE;
+ mipsnet_update_irq(s);
+}
+
+static uint32_t mipsnet_ioport_read(void *opaque, uint32_t addr)
+{
+ MIPSnetState *s = opaque;
+ int ret = 0;
+ const char *devid = MIPSNET_DEV_ID_STRING;
+
+ addr &= 0x3f;
+ switch (addr) {
+ case MIPSNET_DEV_ID:
+ ret = *((uint32_t *)&devid);
+ break;
+ case MIPSNET_DEV_ID + 4:
+ ret = *((uint32_t *)(&devid + 4));
+ break;
+ case MIPSNET_BUSY:
+ ret = s->busy;
+ break;
+ case MIPSNET_RX_DATA_COUNT:
+ ret = s->rx_count;
+ break;
+ case MIPSNET_TX_DATA_COUNT:
+ ret = s->tx_count;
+ break;
+ case MIPSNET_INT_CTL:
+ ret = s->intctl;
+ s->intctl &= ~MIPSNET_INTCTL_TESTBIT;
+ break;
+ case MIPSNET_INTERRUPT_INFO:
+ /* XXX: This seems to be a per-VPE interrupt number. */
+ ret = 0;
+ break;
+ case MIPSNET_RX_DATA_BUFFER:
+ if (s->rx_count) {
+ s->rx_count--;
+ ret = s->rx_buffer[s->rx_read++];
+ }
+ break;
+ /* Reads as zero. */
+ case MIPSNET_TX_DATA_BUFFER:
+ default:
+ break;
+ }
+#ifdef DEBUG_MIPSNET_DATA
+ printf("mipsnet: read addr=0x%02x val=0x%02x\n", addr, ret);
+#endif
+ return ret;
+}
+
+static void mipsnet_ioport_write(void *opaque, uint32_t addr, uint32_t val)
+{
+ MIPSnetState *s = opaque;
+
+ addr &= 0x3f;
+#ifdef DEBUG_MIPSNET_DATA
+ printf("mipsnet: write addr=0x%02x val=0x%02x\n", addr, val);
+#endif
+ switch (addr) {
+ case MIPSNET_TX_DATA_COUNT:
+ s->tx_count = (val <= MAX_ETH_FRAME_SIZE) ? val : 0;
+ s->tx_written = 0;
+ break;
+ case MIPSNET_INT_CTL:
+ if (val & MIPSNET_INTCTL_TXDONE) {
+ s->intctl &= ~MIPSNET_INTCTL_TXDONE;
+ } else if (val & MIPSNET_INTCTL_RXDONE) {
+ s->intctl &= ~MIPSNET_INTCTL_RXDONE;
+ } else if (val & MIPSNET_INTCTL_TESTBIT) {
+ mipsnet_reset(s);
+ s->intctl |= MIPSNET_INTCTL_TESTBIT;
+ } else if (!val) {
+ /* ACK testbit interrupt, flag was cleared on read. */
+ }
+ s->busy = !!s->intctl;
+ mipsnet_update_irq(s);
+ break;
+ case MIPSNET_TX_DATA_BUFFER:
+ s->tx_buffer[s->tx_written++] = val;
+ if (s->tx_written == s->tx_count) {
+ /* Send buffer. */
+#ifdef DEBUG_MIPSNET_SEND
+ printf("mipsnet: sending len=%d\n", s->tx_count);
+#endif
+ qemu_send_packet(s->vc, s->tx_buffer, s->tx_count);
+ s->tx_count = s->tx_written = 0;
+ s->intctl |= MIPSNET_INTCTL_TXDONE;
+ s->busy = 1;
+ mipsnet_update_irq(s);
+ }
+ break;
+ /* Read-only registers */
+ case MIPSNET_DEV_ID:
+ case MIPSNET_BUSY:
+ case MIPSNET_RX_DATA_COUNT:
+ case MIPSNET_INTERRUPT_INFO:
+ case MIPSNET_RX_DATA_BUFFER:
+ default:
+ break;
+ }
+}
+
+static void mipsnet_save(QEMUFile *f, void *opaque)
+{
+ MIPSnetState *s = opaque;
+
+ qemu_put_be32s(f, &s->busy);
+ qemu_put_be32s(f, &s->rx_count);
+ qemu_put_be32s(f, &s->rx_read);
+ qemu_put_be32s(f, &s->tx_count);
+ qemu_put_be32s(f, &s->tx_written);
+ qemu_put_be32s(f, &s->intctl);
+ qemu_put_buffer(f, s->rx_buffer, MAX_ETH_FRAME_SIZE);
+ qemu_put_buffer(f, s->tx_buffer, MAX_ETH_FRAME_SIZE);
+}
+
+static int mipsnet_load(QEMUFile *f, void *opaque, int version_id)
+{
+ MIPSnetState *s = opaque;
+
+ if (version_id > 0)
+ return -EINVAL;
+
+ qemu_get_be32s(f, &s->busy);
+ qemu_get_be32s(f, &s->rx_count);
+ qemu_get_be32s(f, &s->rx_read);
+ qemu_get_be32s(f, &s->tx_count);
+ qemu_get_be32s(f, &s->tx_written);
+ qemu_get_be32s(f, &s->intctl);
+ qemu_get_buffer(f, s->rx_buffer, MAX_ETH_FRAME_SIZE);
+ qemu_get_buffer(f, s->tx_buffer, MAX_ETH_FRAME_SIZE);
+
+ return 0;
+}
+
+void mipsnet_init (int base, qemu_irq irq, NICInfo *nd)
+{
+ MIPSnetState *s;
+
+ s = qemu_mallocz(sizeof(MIPSnetState));
+ if (!s)
+ return;
+
+ register_ioport_write(base, 36, 1, mipsnet_ioport_write, s);
+ register_ioport_read(base, 36, 1, mipsnet_ioport_read, s);
+ register_ioport_write(base, 36, 2, mipsnet_ioport_write, s);
+ register_ioport_read(base, 36, 2, mipsnet_ioport_read, s);
+ register_ioport_write(base, 36, 4, mipsnet_ioport_write, s);
+ register_ioport_read(base, 36, 4, mipsnet_ioport_read, s);
+
+ s->irq = irq;
+ s->nd = nd;
+ if (nd && nd->vlan) {
+ s->vc = qemu_new_vlan_client(nd->vlan, mipsnet_receive,
+ mipsnet_can_receive, s);
+ } else {
+ s->vc = NULL;
+ }
+
+ snprintf(s->vc->info_str, sizeof(s->vc->info_str),
+ "mipsnet macaddr=%02x:%02x:%02x:%02x:%02x:%02x",
+ s->nd->macaddr[0],
+ s->nd->macaddr[1],
+ s->nd->macaddr[2],
+ s->nd->macaddr[3],
+ s->nd->macaddr[4],
+ s->nd->macaddr[5]);
+
+ mipsnet_reset(s);
+ register_savevm("mipsnet", 0, 0, mipsnet_save, mipsnet_load, s);
+}
Modified: trunk/src/host/qemu-neo1973/hw/omap.c
===================================================================
--- trunk/src/host/qemu-neo1973/hw/omap.c 2007-10-29 20:40:05 UTC (rev 3302)
+++ trunk/src/host/qemu-neo1973/hw/omap.c 2007-10-29 21:14:04 UTC (rev 3303)
@@ -2787,6 +2787,626 @@
cpu_register_physical_memory(s->clkm.dsp_base, 0x1000, iomemtype[1]);
}
+/* MPU I/O */
+struct omap_mpuio_s {
+ target_phys_addr_t base;
+ qemu_irq irq;
+ qemu_irq kbd_irq;
+ qemu_irq *in;
+ qemu_irq handler[16];
+ qemu_irq wakeup;
+
+ uint16_t inputs;
+ uint16_t outputs;
+ uint16_t dir;
+ uint16_t edge;
+ uint16_t mask;
+ uint16_t ints;
+
+ uint16_t debounce;
+ uint16_t latch;
+ uint8_t event;
+
+ uint8_t buttons[5];
+ uint8_t row_latch;
+ uint8_t cols;
+ int kbd_mask;
+ int clk;
+};
+
+static void omap_mpuio_set(void *opaque, int line, int level)
+{
+ struct omap_mpuio_s *s = (struct omap_mpuio_s *) opaque;
+ uint16_t prev = s->inputs;
+
+ if (level)
+ s->inputs |= 1 << line;
+ else
+ s->inputs &= ~(1 << line);
+
+ if (((1 << line) & s->dir & ~s->mask) && s->clk) {
+ if ((s->edge & s->inputs & ~prev) | (~s->edge & ~s->inputs & prev)) {
+ s->ints |= 1 << line;
+ qemu_irq_raise(s->irq);
+ /* TODO: wakeup */
+ }
+ if ((s->event & (1 << 0)) && /* SET_GPIO_EVENT_MODE */
+ (s->event >> 1) == line) /* PIN_SELECT */
+ s->latch = s->inputs;
+ }
+}
+
+static void omap_mpuio_kbd_update(struct omap_mpuio_s *s)
+{
+ int i;
+ uint8_t *row, rows = 0, cols = ~s->cols;
+
+ for (row = s->buttons + 4, i = 1 << 4; i; row --, i >>= 1)
+ if (*row & cols)
+ rows |= i;
+
+ qemu_set_irq(s->kbd_irq, rows && ~s->kbd_mask && s->clk);
+ s->row_latch = rows ^ 0x1f;
+}
+
+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;
+ uint16_t ret;
+
+ switch (offset) {
+ case 0x00: /* INPUT_LATCH */
+ return s->inputs;
+
+ case 0x04: /* OUTPUT_REG */
+ return s->outputs;
+
+ case 0x08: /* IO_CNTL */
+ return s->dir;
+
+ case 0x10: /* KBR_LATCH */
+ return s->row_latch;
+
+ case 0x14: /* KBC_REG */
+ return s->cols;
+
+ case 0x18: /* GPIO_EVENT_MODE_REG */
+ return s->event;
+
+ case 0x1c: /* GPIO_INT_EDGE_REG */
+ return s->edge;
+
+ case 0x20: /* KBD_INT */
+ return (s->row_latch != 0x1f) && !s->kbd_mask;
+
+ case 0x24: /* GPIO_INT */
+ ret = s->ints;
+ s->ints &= s->mask;
+ if (ret)
+ qemu_irq_lower(s->irq);
+ return ret;
+
+ case 0x28: /* KBD_MASKIT */
+ return s->kbd_mask;
+
+ case 0x2c: /* GPIO_MASKIT */
+ return s->mask;
+
+ case 0x30: /* GPIO_DEBOUNCING_REG */
+ return s->debounce;
+
+ case 0x34: /* GPIO_LATCH_REG */
+ return s->latch;
+ }
+
+ OMAP_BAD_REG(addr);
+ return 0;
+}
+
+static void omap_mpuio_write(void *opaque, target_phys_addr_t addr,
+ uint32_t value)
+{
+ struct omap_mpuio_s *s = (struct omap_mpuio_s *) opaque;
+ int offset = addr - s->base;
+ uint16_t diff;
+ int ln;
+
+ switch (offset) {
+ case 0x04: /* OUTPUT_REG */
+ diff = s->outputs ^ (value & ~s->dir);
+ s->outputs = value;
+ value &= ~s->dir;
+ while ((ln = ffs(diff))) {
+ ln --;
+ if (s->handler[ln])
+ qemu_set_irq(s->handler[ln], (value >> ln) & 1);
+ diff &= ~(1 << ln);
+ }
+ break;
+
+ case 0x08: /* IO_CNTL */
+ diff = s->outputs & (s->dir ^ value);
+ s->dir = value;
+
+ value = s->outputs & ~s->dir;
+ while ((ln = ffs(diff))) {
+ ln --;
+ if (s->handler[ln])
+ qemu_set_irq(s->handler[ln], (value >> ln) & 1);
+ diff &= ~(1 << ln);
+ }
+ break;
+
+ case 0x14: /* KBC_REG */
+ s->cols = value;
+ omap_mpuio_kbd_update(s);
+ break;
+
+ case 0x18: /* GPIO_EVENT_MODE_REG */
+ s->event = value & 0x1f;
+ break;
+
+ case 0x1c: /* GPIO_INT_EDGE_REG */
+ s->edge = value;
+ break;
+
+ case 0x28: /* KBD_MASKIT */
+ s->kbd_mask = value & 1;
+ omap_mpuio_kbd_update(s);
+ break;
+
+ case 0x2c: /* GPIO_MASKIT */
+ s->mask = value;
+ break;
+
+ case 0x30: /* GPIO_DEBOUNCING_REG */
+ s->debounce = value & 0x1ff;
+ break;
+
+ case 0x00: /* INPUT_LATCH */
+ case 0x10: /* KBR_LATCH */
+ case 0x20: /* KBD_INT */
+ case 0x24: /* GPIO_INT */
+ case 0x34: /* GPIO_LATCH_REG */
+ OMAP_RO_REG(addr);
+ return;
+
+ default:
+ OMAP_BAD_REG(addr);
+ return;
+ }
+}
+
+static CPUReadMemoryFunc *omap_mpuio_readfn[] = {
+ omap_badwidth_read16,
+ omap_mpuio_read,
+ omap_badwidth_read16,
+};
+
+static CPUWriteMemoryFunc *omap_mpuio_writefn[] = {
+ omap_badwidth_write16,
+ omap_mpuio_write,
+ omap_badwidth_write16,
+};
+
+void omap_mpuio_reset(struct omap_mpuio_s *s)
+{
+ s->inputs = 0;
+ s->outputs = 0;
+ s->dir = ~0;
+ s->event = 0;
+ s->edge = 0;
+ s->kbd_mask = 0;
+ s->mask = 0;
+ s->debounce = 0;
+ s->latch = 0;
+ s->ints = 0;
+ s->row_latch = 0x1f;
+ s->clk = 1;
+}
+
+static void omap_mpuio_onoff(void *opaque, int line, int on)
+{
+ struct omap_mpuio_s *s = (struct omap_mpuio_s *) opaque;
+
+ s->clk = on;
+ if (on)
+ omap_mpuio_kbd_update(s);
+}
+
+struct omap_mpuio_s *omap_mpuio_init(target_phys_addr_t base,
+ qemu_irq kbd_int, qemu_irq gpio_int, qemu_irq wakeup,
+ omap_clk clk)
+{
+ int iomemtype;
+ struct omap_mpuio_s *s = (struct omap_mpuio_s *)
+ qemu_mallocz(sizeof(struct omap_mpuio_s));
+
+ s->base = base;
+ s->irq = gpio_int;
+ s->kbd_irq = kbd_int;
+ s->wakeup = wakeup;
+ s->in = qemu_allocate_irqs(omap_mpuio_set, s, 16);
+ omap_mpuio_reset(s);
+
+ iomemtype = cpu_register_io_memory(0, omap_mpuio_readfn,
+ omap_mpuio_writefn, s);
+ cpu_register_physical_memory(s->base, 0x800, iomemtype);
+
+ omap_clk_adduser(clk, qemu_allocate_irqs(omap_mpuio_onoff, s, 1)[0]);
+
+ return s;
+}
+
+qemu_irq *omap_mpuio_in_get(struct omap_mpuio_s *s)
+{
+ return s->in;
+}
+
+void omap_mpuio_out_set(struct omap_mpuio_s *s, int line, qemu_irq handler)
+{
+ if (line >= 16 || line < 0)
+ cpu_abort(cpu_single_env, "%s: No GPIO line %i\n", __FUNCTION__, line);
+ s->handler[line] = handler;
+}
+
+void omap_mpuio_key(struct omap_mpuio_s *s, int row, int col, int down)
+{
+ if (row >= 5 || row < 0)
+ cpu_abort(cpu_single_env, "%s: No key %i-%i\n",
+ __FUNCTION__, col, row);
+
+ if (down)
+ s->buttons[row] |= 1 << col;
+ else
+ s->buttons[row] &= ~(1 << col);
+
+ omap_mpuio_kbd_update(s);
+}
+
+/* General-Purpose I/O */
+struct omap_gpio_s {
+ target_phys_addr_t base;
+ qemu_irq irq;
+ qemu_irq *in;
+ qemu_irq handler[16];
+
+ uint16_t inputs;
+ uint16_t outputs;
+ uint16_t dir;
+ uint16_t edge;
+ uint16_t mask;
+ uint16_t ints;
+};
+
+static void omap_gpio_set(void *opaque, int line, int level)
+{
+ struct omap_gpio_s *s = (struct omap_gpio_s *) opaque;
+ uint16_t prev = s->inputs;
+
+ if (level)
+ s->inputs |= 1 << line;
+ else
+ s->inputs &= ~(1 << line);
+
+ if (((s->edge & s->inputs & ~prev) | (~s->edge & ~s->inputs & prev)) &
+ (1 << line) & s->dir & ~s->mask) {
+ s->ints |= 1 << line;
+ qemu_irq_raise(s->irq);
+ }
+}
+
+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;
+
+ switch (offset) {
+ case 0x00: /* DATA_INPUT */
+ return s->inputs;
+
+ case 0x04: /* DATA_OUTPUT */
+ return s->outputs;
+
+ case 0x08: /* DIRECTION_CONTROL */
+ return s->dir;
+
+ case 0x0c: /* INTERRUPT_CONTROL */
+ return s->edge;
+
+ case 0x10: /* INTERRUPT_MASK */
+ return s->mask;
+
+ case 0x14: /* INTERRUPT_STATUS */
+ return s->ints;
+ }
+
+ OMAP_BAD_REG(addr);
+ return 0;
+}
+
+static void omap_gpio_write(void *opaque, target_phys_addr_t addr,
+ uint32_t value)
+{
+ struct omap_gpio_s *s = (struct omap_gpio_s *) opaque;
+ int offset = addr - s->base;
+ uint16_t diff;
+ int ln;
+
+ switch (offset) {
+ case 0x00: /* DATA_INPUT */
+ OMAP_RO_REG(addr);
+ return;
+
+ case 0x04: /* DATA_OUTPUT */
+ diff = s->outputs ^ (value & ~s->dir);
+ s->outputs = value;
+ value &= ~s->dir;
+ while ((ln = ffs(diff))) {
+ ln --;
+ if (s->handler[ln])
+ qemu_set_irq(s->handler[ln], (value >> ln) & 1);
+ diff &= ~(1 << ln);
+ }
+ break;
+
+ case 0x08: /* DIRECTION_CONTROL */
+ diff = s->outputs & (s->dir ^ value);
+ s->dir = value;
+
+ value = s->outputs & ~s->dir;
+ while ((ln = ffs(diff))) {
+ ln --;
+ if (s->handler[ln])
+ qemu_set_irq(s->handler[ln], (value >> ln) & 1);
+ diff &= ~(1 << ln);
+ }
+ break;
+
+ case 0x0c: /* INTERRUPT_CONTROL */
+ s->edge = value;
+ break;
+
+ case 0x10: /* INTERRUPT_MASK */
+ s->mask = value;
+ break;
+
+ case 0x14: /* INTERRUPT_STATUS */
+ s->ints &= ~value;
+ if (!s->ints)
+ qemu_irq_lower(s->irq);
+ break;
+
+ default:
+ OMAP_BAD_REG(addr);
+ return;
+ }
+}
+
+/* *Some* sources say the memory region is 32-bit. */
+static CPUReadMemoryFunc *omap_gpio_readfn[] = {
+ omap_badwidth_read16,
+ omap_gpio_read,
+ omap_badwidth_read16,
+};
+
+static CPUWriteMemoryFunc *omap_gpio_writefn[] = {
+ omap_badwidth_write16,
+ omap_gpio_write,
+ omap_badwidth_write16,
+};
+
+void omap_gpio_reset(struct omap_gpio_s *s)
+{
+ s->inputs = 0;
+ s->outputs = ~0;
+ s->dir = ~0;
+ s->edge = ~0;
+ s->mask = ~0;
+ s->ints = 0;
+}
+
+struct omap_gpio_s *omap_gpio_init(target_phys_addr_t base,
+ qemu_irq irq, omap_clk clk)
+{
+ int iomemtype;
+ struct omap_gpio_s *s = (struct omap_gpio_s *)
+ qemu_mallocz(sizeof(struct omap_gpio_s));
+
+ s->base = base;
+ s->irq = irq;
+ s->in = qemu_allocate_irqs(omap_gpio_set, s, 16);
+ omap_gpio_reset(s);
+
+ iomemtype = cpu_register_io_memory(0, omap_gpio_readfn,
+ omap_gpio_writefn, s);
+ cpu_register_physical_memory(s->base, 0x1000, iomemtype);
+
+ return s;
+}
+
+qemu_irq *omap_gpio_in_get(struct omap_gpio_s *s)
+{
+ return s->in;
+}
+
+void omap_gpio_out_set(struct omap_gpio_s *s, int line, qemu_irq handler)
+{
+ if (line >= 16 || line < 0)
+ cpu_abort(cpu_single_env, "%s: No GPIO line %i\n", __FUNCTION__, line);
+ s->handler[line] = handler;
+}
+
+/* MicroWire Interface */
+struct omap_uwire_s {
+ target_phys_addr_t base;
+ qemu_irq txirq;
+ qemu_irq rxirq;
+ qemu_irq txdrq;
+
+ uint16_t txbuf;
+ uint16_t rxbuf;
+ uint16_t control;
+ uint16_t setup[5];
+
+ struct uwire_slave_s *chip[4];
+};
+
+static void omap_uwire_transfer_start(struct omap_uwire_s *s)
+{
+ int chipselect = (s->control >> 10) & 3; /* INDEX */
+ struct uwire_slave_s *slave = s->chip[chipselect];
+
+ if ((s->control >> 5) & 0x1f) { /* NB_BITS_WR */
+ if (s->control & (1 << 12)) /* CS_CMD */
+ if (slave && slave->send)
+ slave->send(slave->opaque,
+ s->txbuf >> (16 - ((s->control >> 5) & 0x1f)));
+ s->control &= ~(1 << 14); /* CSRB */
+ /* TODO: depending on s->setup[4] bits [1:0] assert an IRQ or
+ * a DRQ. When is the level IRQ supposed to be reset? */
+ }
+
+ if ((s->control >> 0) & 0x1f) { /* NB_BITS_RD */
+ if (s->control & (1 << 12)) /* CS_CMD */
+ if (slave && slave->receive)
+ s->rxbuf = slave->receive(slave->opaque);
+ s->control |= 1 << 15; /* RDRB */
+ /* TODO: depending on s->setup[4] bits [1:0] assert an IRQ or
+ * a DRQ. When is the level IRQ supposed to be reset? */
+ }
+}
+
+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;
+
+ switch (offset) {
+ case 0x00: /* RDR */
+ s->control &= ~(1 << 15); /* RDRB */
+ return s->rxbuf;
+
+ case 0x04: /* CSR */
+ return s->control;
+
+ case 0x08: /* SR1 */
+ return s->setup[0];
+ case 0x0c: /* SR2 */
+ return s->setup[1];
+ case 0x10: /* SR3 */
+ return s->setup[2];
+ case 0x14: /* SR4 */
+ return s->setup[3];
+ case 0x18: /* SR5 */
+ return s->setup[4];
+ }
+
+ OMAP_BAD_REG(addr);
+ return 0;
+}
+
+static void omap_uwire_write(void *opaque, target_phys_addr_t addr,
+ uint32_t value)
+{
+ struct omap_uwire_s *s = (struct omap_uwire_s *) opaque;
+ int offset = addr - s->base;
+
+ 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 */
+ omap_uwire_transfer_start(s);
+ break;
+
+ case 0x04: /* CSR */
+ s->control = value & 0x1fff;
+ if (value & (1 << 13)) /* START */
+ omap_uwire_transfer_start(s);
+ break;
+
+ case 0x08: /* SR1 */
+ s->setup[0] = value & 0x003f;
+ break;
+
+ case 0x0c: /* SR2 */
+ s->setup[1] = value & 0x0fc0;
+ break;
+
+ case 0x10: /* SR3 */
+ s->setup[2] = value & 0x0003;
+ break;
+
+ case 0x14: /* SR4 */
+ s->setup[3] = value & 0x0001;
+ break;
+
+ case 0x18: /* SR5 */
+ s->setup[4] = value & 0x000f;
+ break;
+
+ default:
+ OMAP_BAD_REG(addr);
+ return;
+ }
+}
+
+static CPUReadMemoryFunc *omap_uwire_readfn[] = {
+ omap_badwidth_read16,
+ omap_uwire_read,
+ omap_badwidth_read16,
+};
+
+static CPUWriteMemoryFunc *omap_uwire_writefn[] = {
+ omap_badwidth_write16,
+ omap_uwire_write,
+ omap_badwidth_write16,
+};
+
+void omap_uwire_reset(struct omap_uwire_s *s)
+{
+ s->control= 0;
+ s->setup[0] = 0;
+ s->setup[1] = 0;
+ s->setup[2] = 0;
+ s->setup[3] = 0;
+ s->setup[4] = 0;
+}
+
+struct omap_uwire_s *omap_uwire_init(target_phys_addr_t base,
+ qemu_irq *irq, qemu_irq dma, omap_clk clk)
+{
+ int iomemtype;
+ struct omap_uwire_s *s = (struct omap_uwire_s *)
+ qemu_mallocz(sizeof(struct omap_uwire_s));
+
+ s->base = base;
+ s->txirq = irq[0];
+ s->rxirq = irq[1];
+ s->txdrq = dma;
+ omap_uwire_reset(s);
+
+ iomemtype = cpu_register_io_memory(0, omap_uwire_readfn,
+ omap_uwire_writefn, s);
+ cpu_register_physical_memory(s->base, 0x800, iomemtype);
+
+ return s;
+}
+
+void omap_uwire_attach(struct omap_uwire_s *s,
+ struct uwire_slave_s *slave, int chipselect)
+{
+ if (chipselect < 0 || chipselect > 3)
+ cpu_abort(cpu_single_env, "%s: Bad chipselect %i\n", __FUNCTION__,
+ chipselect);
+
+ s->chip[chipselect] = slave;
+}
+
/* General chip reset */
static void omap_mpu_reset(void *opaque)
{
@@ -2810,10 +3430,13 @@
omap_dpll_reset(&mpu->dpll[0]);
omap_dpll_reset(&mpu->dpll[1]);
omap_dpll_reset(&mpu->dpll[2]);
- omap_uart_reset(mpu->uart1);
- omap_uart_reset(mpu->uart2);
- omap_uart_reset(mpu->uart3);
+ omap_uart_reset(mpu->uart[0]);
+ omap_uart_reset(mpu->uart[1]);
+ omap_uart_reset(mpu->uart[2]);
omap_mmc_reset(mpu->mmc);
+ omap_mpuio_reset(mpu->mpuio);
+ omap_gpio_reset(mpu->gpio);
+ omap_uwire_reset(mpu->microwire);
cpu_reset(mpu->env);
}
@@ -2821,7 +3444,8 @@
{
struct omap_mpu_state_s *mpu = (struct omap_mpu_state_s *) opaque;
- cpu_interrupt(mpu->env, CPU_INTERRUPT_EXITTB);
+ if (mpu->env->halted)
+ cpu_interrupt(mpu->env, CPU_INTERRUPT_EXITTB);
}
struct omap_mpu_state_s *omap310_mpu_init(unsigned long sdram_size,
@@ -2839,6 +3463,8 @@
cpu_arm_set_model(s->env, core ?: "ti925t");
+ s->wakeup = qemu_allocate_irqs(omap_mpu_wakeup, s, 1)[0];
+
/* Clocks */
omap_clk_init(s);
@@ -2905,13 +3531,13 @@
omap_tcmi_init(0xfffecc00, s);
- s->uart1 = omap_uart_init(0xfffb0000, s->irq[1][OMAP_INT_UART1],
+ s->uart[0] = omap_uart_init(0xfffb0000, s->irq[1][OMAP_INT_UART1],
omap_findclk(s, "uart1_ck"),
serial_hds[0]);
- s->uart2 = omap_uart_init(0xfffb0800, s->irq[1][OMAP_INT_UART2],
+ s->uart[1] = omap_uart_init(0xfffb0800, s->irq[1][OMAP_INT_UART2],
omap_findclk(s, "uart2_ck"),
serial_hds[0] ? serial_hds[1] : 0);
- s->uart3 = omap_uart_init(0xe1019800, s->irq[0][OMAP_INT_UART3],
+ s->uart[2] = omap_uart_init(0xe1019800, s->irq[0][OMAP_INT_UART3],
omap_findclk(s, "uart3_ck"),
serial_hds[0] && serial_hds[1] ? serial_hds[2] : 0);
@@ -2922,8 +3548,17 @@
s->mmc = omap_mmc_init(0xfffb7800, s->irq[1][OMAP_INT_OQN],
&s->drq[OMAP_DMA_MMC_TX], omap_findclk(s, "mmc_ck"));
+ s->mpuio = omap_mpuio_init(0xfffb5000,
+ s->irq[1][OMAP_INT_KEYBOARD], s->irq[1][OMAP_INT_MPUIO],
+ 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"));
+
+ s->microwire = omap_uwire_init(0xfffb3000, &s->irq[1][OMAP_INT_uWireTX],
+ s->drq[OMAP_DMA_UWIRE_TX], omap_findclk(s, "mpuper_ck"));
+
qemu_register_reset(omap_mpu_reset, s);
- s->wakeup = qemu_allocate_irqs(omap_mpu_wakeup, s, 1)[0];
return s;
}
Modified: trunk/src/host/qemu-neo1973/hw/omap.h
===================================================================
--- trunk/src/host/qemu-neo1973/hw/omap.h 2007-10-29 20:40:05 UTC (rev 3302)
+++ trunk/src/host/qemu-neo1973/hw/omap.h 2007-10-29 21:14:04 UTC (rev 3303)
@@ -450,6 +450,31 @@
struct omap_uart_s *omap_uart_init(target_phys_addr_t base,
qemu_irq irq, omap_clk clk, CharDriverState *chr);
+struct omap_mpuio_s;
+struct omap_mpuio_s *omap_mpuio_init(target_phys_addr_t base,
+ qemu_irq kbd_int, qemu_irq gpio_int, qemu_irq wakeup,
+ omap_clk clk);
+qemu_irq *omap_mpuio_in_get(struct omap_mpuio_s *s);
+void omap_mpuio_out_set(struct omap_mpuio_s *s, int line, qemu_irq handler);
+void omap_mpuio_key(struct omap_mpuio_s *s, int row, int col, int down);
+
+struct omap_gpio_s;
+struct omap_gpio_s *omap_gpio_init(target_phys_addr_t base,
+ qemu_irq irq, omap_clk clk);
+qemu_irq *omap_gpio_in_get(struct omap_gpio_s *s);
+void omap_gpio_out_set(struct omap_gpio_s *s, int line, qemu_irq handler);
+
+struct uwire_slave_s {
+ uint16_t (*receive)(void *opaque);
+ void (*send)(void *opaque, uint16_t data);
+ void *opaque;
+};
+struct omap_uwire_s;
+struct omap_uwire_s *omap_uwire_init(target_phys_addr_t base,
+ qemu_irq *irq, qemu_irq dma, omap_clk clk);
+void omap_uwire_attach(struct omap_uwire_s *s,
+ struct uwire_slave_s *slave, int chipselect);
+
/* omap_lcdc.c */
struct omap_lcd_panel_s;
void omap_lcdc_reset(struct omap_lcd_panel_s *s);
@@ -462,6 +487,7 @@
struct omap_mmc_s *omap_mmc_init(target_phys_addr_t base,
qemu_irq irq, qemu_irq dma[], omap_clk clk);
void omap_mmc_reset(struct omap_mmc_s *s);
+void omap_mmc_handlers(struct omap_mmc_s *s, qemu_irq ro, qemu_irq cover);
# define cpu_is_omap310(cpu) (cpu->mpu_model == omap310)
# define cpu_is_omap1510(cpu) (cpu->mpu_model == omap1510)
@@ -495,16 +521,19 @@
unsigned long sram_size;
/* MPUI-TIPB peripherals */
- struct omap_uart_s *uart3;
+ struct omap_uart_s *uart[3];
+ struct omap_gpio_s *gpio;
+
/* MPU public TIPB peripherals */
struct omap_32khz_timer_s *os_timer;
- struct omap_uart_s *uart1;
- struct omap_uart_s *uart2;
-
struct omap_mmc_s *mmc;
+ struct omap_mpuio_s *mpuio;
+
+ struct omap_uwire_s *microwire;
+
/* MPU private TIPB peripherals */
struct omap_intr_handler_s *ih[2];
Modified: trunk/src/host/qemu-neo1973/hw/omap_mmc.c
===================================================================
--- trunk/src/host/qemu-neo1973/hw/omap_mmc.c 2007-10-29 20:40:05 UTC (rev 3302)
+++ trunk/src/host/qemu-neo1973/hw/omap_mmc.c 2007-10-29 21:14:04 UTC (rev 3303)
@@ -25,6 +25,7 @@
target_phys_addr_t base;
qemu_irq irq;
qemu_irq *dma;
+ qemu_irq handler[2];
omap_clk clk;
SDState *card;
uint16_t last_cmd;
@@ -506,6 +507,22 @@
host->transfer = 0;
}
+static void omap_mmc_ro_cb(void *opaque, int level)
+{
+ struct omap_mmc_s *s = (struct omap_mmc_s *) opaque;
+
+ if (s->handler[0])
+ qemu_set_irq(s->handler[0], level);
+}
+
+static void omap_mmc_cover_cb(void *opaque, int level)
+{
+ struct omap_mmc_s *s = (struct omap_mmc_s *) opaque;
+
+ if (s->handler[1])
+ qemu_set_irq(s->handler[1], level);
+}
+
struct omap_mmc_s *omap_mmc_init(target_phys_addr_t base,
qemu_irq irq, qemu_irq dma[], omap_clk clk)
{
@@ -525,7 +542,13 @@
/* Instantiate the storage */
s->card = sd_init(sd_bdrv);
+ sd_set_cb(s->card, s, omap_mmc_ro_cb, omap_mmc_cover_cb);
+
return s;
}
-/* TODO: insertion and read-only handlers */
+void omap_mmc_handlers(struct omap_mmc_s *s, qemu_irq ro, qemu_irq cover)
+{
+ s->handler[0] = ro;
+ s->handler[1] = cover;
+}
Modified: trunk/src/host/qemu-neo1973/hw/palm.c
===================================================================
--- trunk/src/host/qemu-neo1973/hw/palm.c 2007-10-29 20:40:05 UTC (rev 3302)
+++ trunk/src/host/qemu-neo1973/hw/palm.c 2007-10-29 21:14:04 UTC (rev 3303)
@@ -37,7 +37,8 @@
}
static void static_write(void *opaque, target_phys_addr_t offset,
- uint32_t value) {
+ uint32_t value)
+{
#ifdef SPY
printf("%s: value %08lx written at " PA_FMT "\n",
__FUNCTION__, value, offset);
@@ -57,10 +58,63 @@
};
/* Palm Tunsgten|E support */
+
+/* Shared GPIOs */
+#define PALMTE_USBDETECT_GPIO 0
+#define PALMTE_USB_OR_DC_GPIO 1
+#define PALMTE_TSC_GPIO 4
+#define PALMTE_PINTDAV_GPIO 6
+#define PALMTE_MMC_WP_GPIO 8
+#define PALMTE_MMC_POWER_GPIO 9
+#define PALMTE_HDQ_GPIO 11
+#define PALMTE_HEADPHONES_GPIO 14
+#define PALMTE_SPEAKER_GPIO 15
+/* MPU private GPIOs */
+#define PALMTE_DC_GPIO 2
+#define PALMTE_MMC_SWITCH_GPIO 4
+#define PALMTE_MMC1_GPIO 6
+#define PALMTE_MMC2_GPIO 7
+#define PALMTE_MMC3_GPIO 11
+
static void palmte_microwire_setup(struct omap_mpu_state_s *cpu)
{
+ qemu_irq p_int = omap_gpio_in_get(cpu->gpio)[PALMTE_PINTDAV_GPIO];
+
+ omap_uwire_attach(
+ cpu->microwire,
+ tsc2102_init(qemu_irq_invert(p_int)),
+ 0);
}
+static struct {
+ int row;
+ int column;
+} palmte_keymap[0x80] = {
+ [0 ... 0x7f] = { -1, -1 },
+ [0x3b] = { 0, 0 }, /* F1 -> Calendar */
+ [0x3c] = { 1, 0 }, /* F2 -> Contacts */
+ [0x3d] = { 2, 0 }, /* F3 -> Tasks List */
+ [0x3e] = { 3, 0 }, /* F4 -> Note Pad */
+ [0x01] = { 4, 0 }, /* Esc -> Power */
+ [0x4b] = { 0, 1 }, /* Left */
+ [0x50] = { 1, 1 }, /* Down */
+ [0x48] = { 2, 1 }, /* Up */
+ [0x4d] = { 3, 1 }, /* Right */
+ [0x4c] = { 4, 1 }, /* Centre */
+ [0x39] = { 4, 1 }, /* Spc -> Centre */
+};
+
+static void palmte_button_event(void *opaque, int keycode)
+{
+ struct omap_mpu_state_s *cpu = (struct omap_mpu_state_s *) opaque;
+
+ if (palmte_keymap[keycode & 0x7f].row != -1)
+ omap_mpuio_key(cpu->mpuio,
+ palmte_keymap[keycode & 0x7f].row,
+ palmte_keymap[keycode & 0x7f].column,
+ !(keycode & 0x80));
+}
+
static void palmte_init(int ram_size, int vga_ram_size, int boot_device,
DisplayState *ds, const char **fd_filename, int snapshot,
const char *kernel_filename, const char *kernel_cmdline,
@@ -101,6 +155,13 @@
palmte_microwire_setup(cpu);
+ 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]));
+
/* Setup initial (reset) machine state */
if (nb_option_roms) {
rom_size = get_image_size(option_rom[0]);
Modified: trunk/src/host/qemu-neo1973/hw/pc.c
===================================================================
--- trunk/src/host/qemu-neo1973/hw/pc.c 2007-10-29 20:40:05 UTC (rev 3302)
+++ trunk/src/host/qemu-neo1973/hw/pc.c 2007-10-29 21:14:04 UTC (rev 3303)
@@ -93,6 +93,9 @@
return intno;
}
/* read the irq from the PIC */
+ if (!apic_accept_pic_intr(env))
+ return -1;
+
intno = pic_read_irq(isa_pic);
return intno;
}
@@ -100,10 +103,8 @@
static void pic_irq_request(void *opaque, int irq, int level)
{
CPUState *env = opaque;
- if (level)
+ if (level && apic_accept_pic_intr(env))
cpu_interrupt(env, CPU_INTERRUPT_HARD);
- else
- cpu_reset_interrupt(env, CPU_INTERRUPT_HARD);
}
/* PC cmos mappings */
@@ -706,7 +707,9 @@
vga_ram_addr = qemu_ram_alloc(vga_ram_size);
/* BIOS load */
- snprintf(buf, sizeof(buf), "%s/%s", bios_dir, BIOS_FILENAME);
+ if (bios_name == NULL)
+ bios_name = BIOS_FILENAME;
+ snprintf(buf, sizeof(buf), "%s/%s", bios_dir, bios_name);
bios_size = get_image_size(buf);
if (bios_size <= 0 ||
(bios_size % 65536) != 0) {
Modified: trunk/src/host/qemu-neo1973/hw/pckbd.c
===================================================================
--- trunk/src/host/qemu-neo1973/hw/pckbd.c 2007-10-29 20:40:05 UTC (rev 3302)
+++ trunk/src/host/qemu-neo1973/hw/pckbd.c 2007-10-29 21:14:04 UTC (rev 3303)
@@ -207,7 +207,7 @@
#endif
switch(val) {
case KBD_CCMD_READ_MODE:
- kbd_queue(s, s->mode, 0);
+ kbd_queue(s, s->mode, 1);
break;
case KBD_CCMD_WRITE_MODE:
case KBD_CCMD_WRITE_OBUF:
Modified: trunk/src/host/qemu-neo1973/hw/piix_pci.c
===================================================================
--- trunk/src/host/qemu-neo1973/hw/piix_pci.c 2007-10-29 20:40:05 UTC (rev 3302)
+++ trunk/src/host/qemu-neo1973/hw/piix_pci.c 2007-10-29 21:14:04 UTC (rev 3303)
@@ -208,6 +208,7 @@
{
int i, pic_irq, pic_level;
+ piix3_dev->config[0x60 + irq_num] &= ~0x80; // enable bit
pci_irq_levels[irq_num] = level;
/* now we change the pic irq level according to the piix irq mappings */
Modified: trunk/src/host/qemu-neo1973/hw/pl110.c
===================================================================
--- trunk/src/host/qemu-neo1973/hw/pl110.c 2007-10-29 20:40:05 UTC (rev 3302)
+++ trunk/src/host/qemu-neo1973/hw/pl110.c 2007-10-29 21:14:04 UTC (rev 3303)
@@ -10,6 +10,7 @@
#include "vl.h"
#define PL110_CR_EN 0x001
+#define PL110_CR_BGR 0x100
#define PL110_CR_BEBO 0x200
#define PL110_CR_BEPO 0x400
#define PL110_CR_PWR 0x800
@@ -114,6 +115,7 @@
int first, last = 0;
int dirty, new_dirty;
int i;
+ int bpp_offset;
if (!pl110_enabled(s))
return;
@@ -145,12 +147,17 @@
fprintf(stderr, "pl110: Bad color depth\n");
exit(1);
}
+ if (s->cr & PL110_CR_BGR)
+ bpp_offset = 0;
+ else
+ bpp_offset = 18;
+
if (s->cr & PL110_CR_BEBO)
- fn = fntable[s->bpp + 6];
+ fn = fntable[s->bpp + 6 + bpp_offset];
else if (s->cr & PL110_CR_BEPO)
- fn = fntable[s->bpp + 12];
+ fn = fntable[s->bpp + 12 + bpp_offset];
else
- fn = fntable[s->bpp];
+ fn = fntable[s->bpp + bpp_offset];
src_width = s->cols;
switch (s->bpp) {
Modified: trunk/src/host/qemu-neo1973/hw/pl110_template.h
===================================================================
--- trunk/src/host/qemu-neo1973/hw/pl110_template.h 2007-10-29 20:40:05 UTC (rev 3302)
+++ trunk/src/host/qemu-neo1973/hw/pl110_template.h 2007-10-29 21:14:04 UTC (rev 3303)
@@ -24,35 +24,68 @@
#error unknown bit depth
#endif
+#undef RGB
+#define BORDER bgr
#define ORDER 0
#include "pl110_template.h"
#define ORDER 1
#include "pl110_template.h"
#define ORDER 2
#include "pl110_template.h"
+#undef BORDER
+#define RGB
+#define BORDER rgb
+#define ORDER 0
+#include "pl110_template.h"
+#define ORDER 1
+#include "pl110_template.h"
+#define ORDER 2
+#include "pl110_template.h"
+#undef BORDER
-static drawfn glue(pl110_draw_fn_,BITS)[18] =
+static drawfn glue(pl110_draw_fn_,BITS)[36] =
{
- glue(pl110_draw_line1_lblp,BITS),
- glue(pl110_draw_line2_lblp,BITS),
- glue(pl110_draw_line4_lblp,BITS),
- glue(pl110_draw_line8_lblp,BITS),
- glue(pl110_draw_line16_lblp,BITS),
- glue(pl110_draw_line32_lblp,BITS),
+ glue(pl110_draw_line1_lblp_bgr,BITS),
+ glue(pl110_draw_line2_lblp_bgr,BITS),
+ glue(pl110_draw_line4_lblp_bgr,BITS),
+ glue(pl110_draw_line8_lblp_bgr,BITS),
+ glue(pl110_draw_line16_lblp_bgr,BITS),
+ glue(pl110_draw_line32_lblp_bgr,BITS),
- glue(pl110_draw_line1_bbbp,BITS),
- glue(pl110_draw_line2_bbbp,BITS),
- glue(pl110_draw_line4_bbbp,BITS),
- glue(pl110_draw_line8_bbbp,BITS),
- glue(pl110_draw_line16_bbbp,BITS),
- glue(pl110_draw_line32_bbbp,BITS),
+ glue(pl110_draw_line1_bbbp_bgr,BITS),
+ glue(pl110_draw_line2_bbbp_bgr,BITS),
+ glue(pl110_draw_line4_bbbp_bgr,BITS),
+ glue(pl110_draw_line8_bbbp_bgr,BITS),
+ glue(pl110_draw_line16_bbbp_bgr,BITS),
+ glue(pl110_draw_line32_bbbp_bgr,BITS),
- glue(pl110_draw_line1_lbbp,BITS),
- glue(pl110_draw_line2_lbbp,BITS),
- glue(pl110_draw_line4_lbbp,BITS),
- glue(pl110_draw_line8_lbbp,BITS),
- glue(pl110_draw_line16_lbbp,BITS),
- glue(pl110_draw_line32_lbbp,BITS)
+ glue(pl110_draw_line1_lbbp_bgr,BITS),
+ glue(pl110_draw_line2_lbbp_bgr,BITS),
+ glue(pl110_draw_line4_lbbp_bgr,BITS),
+ glue(pl110_draw_line8_lbbp_bgr,BITS),
+ glue(pl110_draw_line16_lbbp_bgr,BITS),
+ glue(pl110_draw_line32_lbbp_bgr,BITS),
+
+ glue(pl110_draw_line1_lblp_rgb,BITS),
+ glue(pl110_draw_line2_lblp_rgb,BITS),
+ glue(pl110_draw_line4_lblp_rgb,BITS),
+ glue(pl110_draw_line8_lblp_rgb,BITS),
+ glue(pl110_draw_line16_lblp_rgb,BITS),
+ glue(pl110_draw_line32_lblp_rgb,BITS),
+
+ glue(pl110_draw_line1_bbbp_rgb,BITS),
+ glue(pl110_draw_line2_bbbp_rgb,BITS),
+ glue(pl110_draw_line4_bbbp_rgb,BITS),
+ glue(pl110_draw_line8_bbbp_rgb,BITS),
+ glue(pl110_draw_line16_bbbp_rgb,BITS),
+ glue(pl110_draw_line32_bbbp_rgb,BITS),
+
+ glue(pl110_draw_line1_lbbp_rgb,BITS),
+ glue(pl110_draw_line2_lbbp_rgb,BITS),
+ glue(pl110_draw_line4_lbbp_rgb,BITS),
+ glue(pl110_draw_line8_lbbp_rgb,BITS),
+ glue(pl110_draw_line16_lbbp_rgb,BITS),
+ glue(pl110_draw_line32_lbbp_rgb,BITS),
};
#undef BITS
@@ -61,18 +94,18 @@
#else
#if ORDER == 0
-#define NAME glue(lblp, BITS)
+#define NAME glue(glue(lblp_, BORDER), BITS)
#ifdef WORDS_BIGENDIAN
#define SWAP_WORDS 1
#endif
#elif ORDER == 1
-#define NAME glue(bbbp, BITS)
+#define NAME glue(glue(bbbp_, BORDER), BITS)
#ifndef WORDS_BIGENDIAN
#define SWAP_WORDS 1
#endif
#else
#define SWAP_PIXELS 1
-#define NAME glue(lbbp, BITS)
+#define NAME glue(glue(lbbp_, BORDER), BITS)
#ifdef WORDS_BIGENDIAN
#define SWAP_WORDS 1
#endif
@@ -195,29 +228,38 @@
#ifdef SWAP_WORDS
data = bswap32(data);
#endif
+#ifdef RGB
+#define LSB r
+#define MSB b
+#else
+#define LSB b
+#define MSB r
+#endif
#if 0
- r = data & 0x1f;
+ LSB = data & 0x1f;
data >>= 5;
g = data & 0x3f;
data >>= 6;
- b = data & 0x1f;
+ MSB = data & 0x1f;
data >>= 5;
#else
- r = (data & 0x1f) << 3;
+ LSB = (data & 0x1f) << 3;
data >>= 5;
g = (data & 0x3f) << 2;
data >>= 6;
- b = (data & 0x1f) << 3;
+ MSB = (data & 0x1f) << 3;
data >>= 5;
#endif
COPY_PIXEL(d, glue(rgb_to_pixel,BITS)(r, g, b));
- r = (data & 0x1f) << 3;
+ LSB = (data & 0x1f) << 3;
data >>= 5;
g = (data & 0x3f) << 2;
data >>= 6;
- b = (data & 0x1f) << 3;
+ MSB = (data & 0x1f) << 3;
data >>= 5;
COPY_PIXEL(d, glue(rgb_to_pixel,BITS)(r, g, b));
+#undef MSB
+#undef LSB
width -= 2;
src += 4;
}
@@ -229,16 +271,25 @@
unsigned int r, g, b;
while (width > 0) {
data = *(uint32_t *)src;
+#ifdef RGB
+#define LSB r
+#define MSB b
+#else
+#define LSB b
+#define MSB r
+#endif
#ifdef SWAP_WORDS
- r = data & 0xff;
+ LSB = data & 0xff;
g = (data >> 8) & 0xff;
- b = (data >> 16) & 0xff;
+ MSB = (data >> 16) & 0xff;
#else
- r = (data >> 24) & 0xff;
+ LSB = (data >> 24) & 0xff;
g = (data >> 16) & 0xff;
- b = (data >> 8) & 0xff;
+ MSB = (data >> 8) & 0xff;
#endif
COPY_PIXEL(d, glue(rgb_to_pixel,BITS)(r, g, b));
+#undef MSB
+#undef LSB
width--;
src += 4;
}
Modified: trunk/src/host/qemu-neo1973/hw/ppc.c
===================================================================
--- trunk/src/host/qemu-neo1973/hw/ppc.c 2007-10-29 20:40:05 UTC (rev 3302)
+++ trunk/src/host/qemu-neo1973/hw/ppc.c 2007-10-29 21:14:04 UTC (rev 3303)
@@ -22,7 +22,6 @@
* THE SOFTWARE.
*/
#include "vl.h"
-#include "m48t59.h"
//#define PPC_DEBUG_IRQ
//#define PPC_DEBUG_TB
@@ -30,7 +29,10 @@
extern FILE *logfile;
extern int loglevel;
-void ppc_set_irq (CPUState *env, int n_IRQ, int level)
+static void cpu_ppc_tb_stop (CPUState *env);
+static void cpu_ppc_tb_start (CPUState *env);
+
+static void ppc_set_irq (CPUState *env, int n_IRQ, int level)
{
if (level) {
env->pending_interrupts |= 1 << n_IRQ;
@@ -65,6 +67,19 @@
/* Don't generate spurious events */
if ((cur_level == 1 && level == 0) || (cur_level == 0 && level != 0)) {
switch (pin) {
+ case PPC6xx_INPUT_TBEN:
+ /* Level sensitive - active high */
+#if defined(PPC_DEBUG_IRQ)
+ if (loglevel & CPU_LOG_INT) {
+ fprintf(logfile, "%s: %s the time base\n",
+ __func__, level ? "start" : "stop");
+ }
+#endif
+ if (level) {
+ cpu_ppc_tb_start(env);
+ } else {
+ cpu_ppc_tb_stop(env);
+ }
case PPC6xx_INPUT_INT:
/* Level sensitive - active high */
#if defined(PPC_DEBUG_IRQ)
@@ -103,6 +118,7 @@
case PPC6xx_INPUT_CKSTP_IN:
/* Level sensitive - active low */
/* XXX: TODO: relay the signal to CKSTP_OUT pin */
+ /* XXX: Note that the only way to restart the CPU is to reset it */
if (level) {
#if defined(PPC_DEBUG_IRQ)
if (loglevel & CPU_LOG_INT) {
@@ -110,25 +126,22 @@
}
#endif
env->halted = 1;
- } else {
-#if defined(PPC_DEBUG_IRQ)
- if (loglevel & CPU_LOG_INT) {
- fprintf(logfile, "%s: restart the CPU\n", __func__);
- }
-#endif
- env->halted = 0;
}
break;
case PPC6xx_INPUT_HRESET:
/* Level sensitive - active low */
if (level) {
-#if 0 // XXX: TOFIX
#if defined(PPC_DEBUG_IRQ)
if (loglevel & CPU_LOG_INT) {
fprintf(logfile, "%s: reset the CPU\n", __func__);
}
#endif
- cpu_reset(env);
+ env->interrupt_request |= CPU_INTERRUPT_EXITTB;
+ /* XXX: TOFIX */
+#if 0
+ cpu_ppc_reset(env);
+#else
+ qemu_system_reset_request();
#endif
}
break;
@@ -162,6 +175,7 @@
env->irq_inputs = (void **)qemu_allocate_irqs(&ppc6xx_set_irq, env, 6);
}
+#if defined(TARGET_PPC64)
/* PowerPC 970 internal IRQ controller */
static void ppc970_set_irq (void *opaque, int pin, int level)
{
@@ -283,9 +297,10 @@
{
env->irq_inputs = (void **)qemu_allocate_irqs(&ppc970_set_irq, env, 7);
}
+#endif /* defined(TARGET_PPC64) */
-/* PowerPC 405 internal IRQ controller */
-static void ppc405_set_irq (void *opaque, int pin, int level)
+/* PowerPC 40x internal IRQ controller */
+static void ppc40x_set_irq (void *opaque, int pin, int level)
{
CPUState *env = opaque;
int cur_level;
@@ -300,7 +315,7 @@
/* Don't generate spurious events */
if ((cur_level == 1 && level == 0) || (cur_level == 0 && level != 0)) {
switch (pin) {
- case PPC405_INPUT_RESET_SYS:
+ case PPC40x_INPUT_RESET_SYS:
if (level) {
#if defined(PPC_DEBUG_IRQ)
if (loglevel & CPU_LOG_INT) {
@@ -311,7 +326,7 @@
ppc40x_system_reset(env);
}
break;
- case PPC405_INPUT_RESET_CHIP:
+ case PPC40x_INPUT_RESET_CHIP:
if (level) {
#if defined(PPC_DEBUG_IRQ)
if (loglevel & CPU_LOG_INT) {
@@ -321,8 +336,7 @@
ppc40x_chip_reset(env);
}
break;
- /* No break here */
- case PPC405_INPUT_RESET_CORE:
+ case PPC40x_INPUT_RESET_CORE:
/* XXX: TODO: update DBSR[MRR] */
if (level) {
#if defined(PPC_DEBUG_IRQ)
@@ -333,7 +347,7 @@
ppc40x_core_reset(env);
}
break;
- case PPC405_INPUT_CINT:
+ case PPC40x_INPUT_CINT:
/* Level sensitive - active high */
#if defined(PPC_DEBUG_IRQ)
if (loglevel & CPU_LOG_INT) {
@@ -341,10 +355,9 @@
__func__, level);
}
#endif
- /* XXX: TOFIX */
- ppc_set_irq(env, PPC_INTERRUPT_RESET, level);
+ ppc_set_irq(env, PPC_INTERRUPT_CEXT, level);
break;
- case PPC405_INPUT_INT:
+ case PPC40x_INPUT_INT:
/* Level sensitive - active high */
#if defined(PPC_DEBUG_IRQ)
if (loglevel & CPU_LOG_INT) {
@@ -354,7 +367,7 @@
#endif
ppc_set_irq(env, PPC_INTERRUPT_EXT, level);
break;
- case PPC405_INPUT_HALT:
+ case PPC40x_INPUT_HALT:
/* Level sensitive - active low */
if (level) {
#if defined(PPC_DEBUG_IRQ)
@@ -372,15 +385,15 @@
env->halted = 0;
}
break;
- case PPC405_INPUT_DEBUG:
+ case PPC40x_INPUT_DEBUG:
/* Level sensitive - active high */
#if defined(PPC_DEBUG_IRQ)
if (loglevel & CPU_LOG_INT) {
- fprintf(logfile, "%s: set the external IRQ state to %d\n",
+ fprintf(logfile, "%s: set the debug pin state to %d\n",
__func__, level);
}
#endif
- ppc_set_irq(env, EXCP_40x_DEBUG, level);
+ ppc_set_irq(env, PPC_INTERRUPT_DEBUG, level);
break;
default:
/* Unknown pin - do nothing */
@@ -398,28 +411,38 @@
}
}
-void ppc405_irq_init (CPUState *env)
+void ppc40x_irq_init (CPUState *env)
{
- env->irq_inputs = (void **)qemu_allocate_irqs(&ppc405_set_irq, env, 7);
+ env->irq_inputs = (void **)qemu_allocate_irqs(&ppc40x_set_irq,
+ env, PPC40x_INPUT_NB);
}
/*****************************************************************************/
/* PowerPC time base and decrementer emulation */
struct ppc_tb_t {
/* Time base management */
- int64_t tb_offset; /* Compensation */
- uint32_t tb_freq; /* TB frequency */
+ int64_t tb_offset; /* Compensation */
+ int64_t atb_offset; /* Compensation */
+ uint32_t tb_freq; /* TB frequency */
/* Decrementer management */
- uint64_t decr_next; /* Tick for next decr interrupt */
+ uint64_t decr_next; /* Tick for next decr interrupt */
+ uint32_t decr_freq; /* decrementer frequency */
struct QEMUTimer *decr_timer;
+#if defined(TARGET_PPC64H)
+ /* Hypervisor decrementer management */
+ uint64_t hdecr_next; /* Tick for next hdecr interrupt */
+ struct QEMUTimer *hdecr_timer;
+ uint64_t purr_load;
+ uint64_t purr_start;
+#endif
void *opaque;
};
-static inline uint64_t cpu_ppc_get_tb (ppc_tb_t *tb_env)
+static always_inline uint64_t cpu_ppc_get_tb (ppc_tb_t *tb_env, uint64_t vmclk,
+ int64_t tb_offset)
{
/* TB time in tb periods */
- return muldiv64(qemu_get_clock(vm_clock) + tb_env->tb_offset,
- tb_env->tb_freq, ticks_per_sec);
+ return muldiv64(vmclk, tb_env->tb_freq, ticks_per_sec) + tb_offset;
}
uint32_t cpu_ppc_load_tbl (CPUState *env)
@@ -427,31 +450,22 @@
ppc_tb_t *tb_env = env->tb_env;
uint64_t tb;
- tb = cpu_ppc_get_tb(tb_env);
-#ifdef PPC_DEBUG_TB
- {
- static int last_time;
- int now;
- now = time(NULL);
- if (last_time != now) {
- last_time = now;
- if (loglevel != 0) {
- fprintf(logfile, "%s: tb=0x%016lx %d %08lx\n",
- __func__, tb, now, tb_env->tb_offset);
- }
- }
+ tb = cpu_ppc_get_tb(tb_env, qemu_get_clock(vm_clock), tb_env->tb_offset);
+#if defined(PPC_DEBUG_TB)
+ if (loglevel != 0) {
+ fprintf(logfile, "%s: tb=0x%016lx\n", __func__, tb);
}
#endif
return tb & 0xFFFFFFFF;
}
-uint32_t cpu_ppc_load_tbu (CPUState *env)
+static always_inline uint32_t _cpu_ppc_load_tbu (CPUState *env)
{
ppc_tb_t *tb_env = env->tb_env;
uint64_t tb;
- tb = cpu_ppc_get_tb(tb_env);
+ tb = cpu_ppc_get_tb(tb_env, qemu_get_clock(vm_clock), tb_env->tb_offset);
#if defined(PPC_DEBUG_TB)
if (loglevel != 0) {
fprintf(logfile, "%s: tb=0x%016lx\n", __func__, tb);
@@ -461,45 +475,158 @@
return tb >> 32;
}
-static void cpu_ppc_store_tb (ppc_tb_t *tb_env, uint64_t value)
+uint32_t cpu_ppc_load_tbu (CPUState *env)
{
- tb_env->tb_offset = muldiv64(value, ticks_per_sec, tb_env->tb_freq)
- - qemu_get_clock(vm_clock);
+ return _cpu_ppc_load_tbu(env);
+}
+
+static always_inline void cpu_ppc_store_tb (ppc_tb_t *tb_env, uint64_t vmclk,
+ int64_t *tb_offsetp,
+ uint64_t value)
+{
+ *tb_offsetp = value - muldiv64(vmclk, tb_env->tb_freq, ticks_per_sec);
#ifdef PPC_DEBUG_TB
if (loglevel != 0) {
fprintf(logfile, "%s: tb=0x%016lx offset=%08lx\n", __func__, value,
- tb_env->tb_offset);
+ *tb_offsetp);
}
#endif
}
+void cpu_ppc_store_tbl (CPUState *env, uint32_t value)
+{
+ ppc_tb_t *tb_env = env->tb_env;
+ uint64_t tb;
+
+ tb = cpu_ppc_get_tb(tb_env, qemu_get_clock(vm_clock), tb_env->tb_offset);
+ tb &= 0xFFFFFFFF00000000ULL;
+ cpu_ppc_store_tb(tb_env, qemu_get_clock(vm_clock),
+ &tb_env->tb_offset, tb | (uint64_t)value);
+}
+
+static always_inline void _cpu_ppc_store_tbu (CPUState *env, uint32_t value)
+{
+ ppc_tb_t *tb_env = env->tb_env;
+ uint64_t tb;
+
+ tb = cpu_ppc_get_tb(tb_env, qemu_get_clock(vm_clock), tb_env->tb_offset);
+ tb &= 0x00000000FFFFFFFFULL;
+ cpu_ppc_store_tb(tb_env, qemu_get_clock(vm_clock),
+ &tb_env->tb_offset, ((uint64_t)value << 32) | tb);
+}
+
void cpu_ppc_store_tbu (CPUState *env, uint32_t value)
{
+ _cpu_ppc_store_tbu(env, value);
+}
+
+uint32_t cpu_ppc_load_atbl (CPUState *env)
+{
ppc_tb_t *tb_env = env->tb_env;
+ uint64_t tb;
- cpu_ppc_store_tb(tb_env,
- ((uint64_t)value << 32) | cpu_ppc_load_tbl(env));
+ tb = cpu_ppc_get_tb(tb_env, qemu_get_clock(vm_clock), tb_env->atb_offset);
+#if defined(PPC_DEBUG_TB)
+ if (loglevel != 0) {
+ fprintf(logfile, "%s: tb=0x%016lx\n", __func__, tb);
+ }
+#endif
+
+ return tb & 0xFFFFFFFF;
}
-void cpu_ppc_store_tbl (CPUState *env, uint32_t value)
+uint32_t cpu_ppc_load_atbu (CPUState *env)
{
ppc_tb_t *tb_env = env->tb_env;
+ uint64_t tb;
- cpu_ppc_store_tb(tb_env,
- ((uint64_t)cpu_ppc_load_tbu(env) << 32) | value);
+ tb = cpu_ppc_get_tb(tb_env, qemu_get_clock(vm_clock), tb_env->atb_offset);
+#if defined(PPC_DEBUG_TB)
+ if (loglevel != 0) {
+ fprintf(logfile, "%s: tb=0x%016lx\n", __func__, tb);
+ }
+#endif
+
+ return tb >> 32;
}
-uint32_t cpu_ppc_load_decr (CPUState *env)
+void cpu_ppc_store_atbl (CPUState *env, uint32_t value)
{
ppc_tb_t *tb_env = env->tb_env;
+ uint64_t tb;
+
+ tb = cpu_ppc_get_tb(tb_env, qemu_get_clock(vm_clock), tb_env->atb_offset);
+ tb &= 0xFFFFFFFF00000000ULL;
+ cpu_ppc_store_tb(tb_env, qemu_get_clock(vm_clock),
+ &tb_env->atb_offset, tb | (uint64_t)value);
+}
+
+void cpu_ppc_store_atbu (CPUState *env, uint32_t value)
+{
+ ppc_tb_t *tb_env = env->tb_env;
+ uint64_t tb;
+
+ tb = cpu_ppc_get_tb(tb_env, qemu_get_clock(vm_clock), tb_env->atb_offset);
+ tb &= 0x00000000FFFFFFFFULL;
+ cpu_ppc_store_tb(tb_env, qemu_get_clock(vm_clock),
+ &tb_env->atb_offset, ((uint64_t)value << 32) | tb);
+}
+
+static void cpu_ppc_tb_stop (CPUState *env)
+{
+ ppc_tb_t *tb_env = env->tb_env;
+ uint64_t tb, atb, vmclk;
+
+ /* If the time base is already frozen, do nothing */
+ if (tb_env->tb_freq != 0) {
+ vmclk = qemu_get_clock(vm_clock);
+ /* Get the time base */
+ tb = cpu_ppc_get_tb(tb_env, vmclk, tb_env->tb_offset);
+ /* Get the alternate time base */
+ atb = cpu_ppc_get_tb(tb_env, vmclk, tb_env->atb_offset);
+ /* Store the time base value (ie compute the current offset) */
+ cpu_ppc_store_tb(tb_env, vmclk, &tb_env->tb_offset, tb);
+ /* Store the alternate time base value (compute the current offset) */
+ cpu_ppc_store_tb(tb_env, vmclk, &tb_env->atb_offset, atb);
+ /* Set the time base frequency to zero */
+ tb_env->tb_freq = 0;
+ /* Now, the time bases are frozen to tb_offset / atb_offset value */
+ }
+}
+
+static void cpu_ppc_tb_start (CPUState *env)
+{
+ ppc_tb_t *tb_env = env->tb_env;
+ uint64_t tb, atb, vmclk;
+
+ /* If the time base is not frozen, do nothing */
+ if (tb_env->tb_freq == 0) {
+ vmclk = qemu_get_clock(vm_clock);
+ /* Get the time base from tb_offset */
+ tb = tb_env->tb_offset;
+ /* Get the alternate time base from atb_offset */
+ atb = tb_env->atb_offset;
+ /* Restore the tb frequency from the decrementer frequency */
+ tb_env->tb_freq = tb_env->decr_freq;
+ /* Store the time base value */
+ cpu_ppc_store_tb(tb_env, vmclk, &tb_env->tb_offset, tb);
+ /* Store the alternate time base value */
+ cpu_ppc_store_tb(tb_env, vmclk, &tb_env->atb_offset, atb);
+ }
+}
+
+static always_inline uint32_t _cpu_ppc_load_decr (CPUState *env,
+ uint64_t *next)
+{
+ ppc_tb_t *tb_env = env->tb_env;
uint32_t decr;
int64_t diff;
diff = tb_env->decr_next - qemu_get_clock(vm_clock);
if (diff >= 0)
- decr = muldiv64(diff, tb_env->tb_freq, ticks_per_sec);
+ decr = muldiv64(diff, tb_env->decr_freq, ticks_per_sec);
else
- decr = -muldiv64(-diff, tb_env->tb_freq, ticks_per_sec);
+ decr = -muldiv64(-diff, tb_env->decr_freq, ticks_per_sec);
#if defined(PPC_DEBUG_TB)
if (loglevel != 0) {
fprintf(logfile, "%s: 0x%08x\n", __func__, decr);
@@ -509,10 +636,36 @@
return decr;
}
+uint32_t cpu_ppc_load_decr (CPUState *env)
+{
+ ppc_tb_t *tb_env = env->tb_env;
+
+ return _cpu_ppc_load_decr(env, &tb_env->decr_next);
+}
+
+#if defined(TARGET_PPC64H)
+uint32_t cpu_ppc_load_hdecr (CPUState *env)
+{
+ ppc_tb_t *tb_env = env->tb_env;
+
+ return _cpu_ppc_load_decr(env, &tb_env->hdecr_next);
+}
+
+uint64_t cpu_ppc_load_purr (CPUState *env)
+{
+ ppc_tb_t *tb_env = env->tb_env;
+ uint64_t diff;
+
+ diff = qemu_get_clock(vm_clock) - tb_env->purr_start;
+
+ return tb_env->purr_load + muldiv64(diff, tb_env->tb_freq, ticks_per_sec);
+}
+#endif /* defined(TARGET_PPC64H) */
+
/* When decrementer expires,
* all we need to do is generate or queue a CPU exception
*/
-static inline void cpu_ppc_decr_excp (CPUState *env)
+static always_inline void cpu_ppc_decr_excp (CPUState *env)
{
/* Raise it */
#ifdef PPC_DEBUG_TB
@@ -523,9 +676,23 @@
ppc_set_irq(env, PPC_INTERRUPT_DECR, 1);
}
-static void _cpu_ppc_store_decr (CPUState *env, uint32_t decr,
- uint32_t value, int is_excp)
+static always_inline void cpu_ppc_hdecr_excp (CPUState *env)
{
+ /* Raise it */
+#ifdef PPC_DEBUG_TB
+ if (loglevel != 0) {
+ fprintf(logfile, "raise decrementer exception\n");
+ }
+#endif
+ ppc_set_irq(env, PPC_INTERRUPT_HDECR, 1);
+}
+
+static void __cpu_ppc_store_decr (CPUState *env, uint64_t *nextp,
+ struct QEMUTimer *timer,
+ void (*raise_excp)(CPUState *),
+ uint32_t decr, uint32_t value,
+ int is_excp)
+{
ppc_tb_t *tb_env = env->tb_env;
uint64_t now, next;
@@ -535,21 +702,30 @@
}
#endif
now = qemu_get_clock(vm_clock);
- next = now + muldiv64(value, ticks_per_sec, tb_env->tb_freq);
+ next = now + muldiv64(value, ticks_per_sec, tb_env->decr_freq);
if (is_excp)
- next += tb_env->decr_next - now;
+ next += *nextp - now;
if (next == now)
next++;
- tb_env->decr_next = next;
+ *nextp = next;
/* Adjust timer */
- qemu_mod_timer(tb_env->decr_timer, next);
+ qemu_mod_timer(timer, next);
/* If we set a negative value and the decrementer was positive,
* raise an exception.
*/
if ((value & 0x80000000) && !(decr & 0x80000000))
- cpu_ppc_decr_excp(env);
+ (*raise_excp)(env);
}
+static always_inline void _cpu_ppc_store_decr (CPUState *env, uint32_t decr,
+ uint32_t value, int is_excp)
+{
+ ppc_tb_t *tb_env = env->tb_env;
+
+ __cpu_ppc_store_decr(env, &tb_env->decr_next, tb_env->decr_timer,
+ &cpu_ppc_decr_excp, decr, value, is_excp);
+}
+
void cpu_ppc_store_decr (CPUState *env, uint32_t value)
{
_cpu_ppc_store_decr(env, cpu_ppc_load_decr(env), value, 0);
@@ -560,17 +736,51 @@
_cpu_ppc_store_decr(opaque, 0x00000000, 0xFFFFFFFF, 1);
}
+#if defined(TARGET_PPC64H)
+static always_inline void _cpu_ppc_store_hdecr (CPUState *env, uint32_t hdecr,
+ uint32_t value, int is_excp)
+{
+ ppc_tb_t *tb_env = env->tb_env;
+
+ __cpu_ppc_store_decr(env, &tb_env->hdecr_next, tb_env->hdecr_timer,
+ &cpu_ppc_hdecr_excp, hdecr, value, is_excp);
+}
+
+void cpu_ppc_store_hdecr (CPUState *env, uint32_t value)
+{
+ _cpu_ppc_store_hdecr(env, cpu_ppc_load_hdecr(env), value, 0);
+}
+
+static void cpu_ppc_hdecr_cb (void *opaque)
+{
+ _cpu_ppc_store_hdecr(opaque, 0x00000000, 0xFFFFFFFF, 1);
+}
+
+void cpu_ppc_store_purr (CPUState *env, uint64_t value)
+{
+ ppc_tb_t *tb_env = env->tb_env;
+
+ tb_env->purr_load = value;
+ tb_env->purr_start = qemu_get_clock(vm_clock);
+}
+#endif /* defined(TARGET_PPC64H) */
+
static void cpu_ppc_set_tb_clk (void *opaque, uint32_t freq)
{
CPUState *env = opaque;
ppc_tb_t *tb_env = env->tb_env;
tb_env->tb_freq = freq;
+ tb_env->decr_freq = freq;
/* There is a bug in Linux 2.4 kernels:
* if a decrementer exception is pending when it enables msr_ee at startup,
* it's not ready to handle it...
*/
_cpu_ppc_store_decr(env, 0xFFFFFFFF, 0xFFFFFFFF, 0);
+#if defined(TARGET_PPC64H)
+ _cpu_ppc_store_hdecr(env, 0xFFFFFFFF, 0xFFFFFFFF, 0);
+ cpu_ppc_store_purr(env, 0x0000000000000000ULL);
+#endif /* defined(TARGET_PPC64H) */
}
/* Set up (once) timebase frequency (in Hz) */
@@ -584,6 +794,9 @@
env->tb_env = tb_env;
/* Create new timer */
tb_env->decr_timer = qemu_new_timer(vm_clock, &cpu_ppc_decr_cb, env);
+#if defined(TARGET_PPC64H)
+ tb_env->hdecr_timer = qemu_new_timer(vm_clock, &cpu_ppc_hdecr_cb, env);
+#endif /* defined(TARGET_PPC64H) */
cpu_ppc_set_tb_clk(env, freq);
return &cpu_ppc_set_tb_clk;
@@ -596,10 +809,14 @@
}
void cpu_ppc601_store_rtcu (CPUState *env, uint32_t value)
-__attribute__ (( alias ("cpu_ppc_store_tbu") ));
+{
+ _cpu_ppc_store_tbu(env, value);
+}
uint32_t cpu_ppc601_load_rtcu (CPUState *env)
-__attribute__ (( alias ("cpu_ppc_load_tbu") ));
+{
+ return _cpu_ppc_load_tbu(env);
+}
void cpu_ppc601_store_rtcl (CPUState *env, uint32_t value)
{
@@ -695,7 +912,7 @@
#endif
now = qemu_get_clock(vm_clock);
next = now + muldiv64(ppcemb_timer->pit_reload,
- ticks_per_sec, tb_env->tb_freq);
+ ticks_per_sec, tb_env->decr_freq);
if (is_excp)
next += tb_env->decr_next - now;
if (next == now)
@@ -759,7 +976,7 @@
/* Cannot occur, but makes gcc happy */
return;
}
- next = now + muldiv64(next, ticks_per_sec, tb_env->tb_freq);
+ next = now + muldiv64(next, ticks_per_sec, tb_env->decr_freq);
if (next == now)
next++;
#ifdef PPC_DEBUG_TB
@@ -861,6 +1078,7 @@
}
#endif
tb_env->tb_freq = freq;
+ tb_env->decr_freq = freq;
/* XXX: we should also update all timers */
}
@@ -876,6 +1094,7 @@
env->tb_env = tb_env;
ppcemb_timer = qemu_mallocz(sizeof(ppcemb_timer_t));
tb_env->tb_freq = freq;
+ tb_env->decr_freq = freq;
tb_env->opaque = ppcemb_timer;
#ifdef PPC_DEBUG_TB
if (loglevel != 0) {
@@ -904,6 +1123,9 @@
void *opaque;
};
+/* XXX: on 460, DCR addresses are 32 bits wide,
+ * using DCRIPR to get the 22 upper bits of the DCR address
+ */
#define DCRN_NB 1024
struct ppc_dcr_t {
ppc_dcrn_t dcrn[DCRN_NB];
@@ -989,7 +1211,6 @@
return 0;
}
-
#if 0
/*****************************************************************************/
/* Handle system reset (for now, just stop emulation) */
@@ -1022,63 +1243,75 @@
/*****************************************************************************/
/* NVRAM helpers */
-void NVRAM_set_byte (m48t59_t *nvram, uint32_t addr, uint8_t value)
+static inline uint32_t nvram_read (nvram_t *nvram, uint32_t addr)
{
- m48t59_write(nvram, addr, value);
+ return (*nvram->read_fn)(nvram->opaque, addr);;
}
-uint8_t NVRAM_get_byte (m48t59_t *nvram, uint32_t addr)
+static inline void nvram_write (nvram_t *nvram, uint32_t addr, uint32_t val)
{
- return m48t59_read(nvram, addr);
+ (*nvram->write_fn)(nvram->opaque, addr, val);
}
-void NVRAM_set_word (m48t59_t *nvram, uint32_t addr, uint16_t value)
+void NVRAM_set_byte (nvram_t *nvram, uint32_t addr, uint8_t value)
{
- m48t59_write(nvram, addr, value >> 8);
- m48t59_write(nvram, addr + 1, value & 0xFF);
+ nvram_write(nvram, addr, value);
}
-uint16_t NVRAM_get_word (m48t59_t *nvram, uint32_t addr)
+uint8_t NVRAM_get_byte (nvram_t *nvram, uint32_t addr)
{
+ return nvram_read(nvram, addr);
+}
+
+void NVRAM_set_word (nvram_t *nvram, uint32_t addr, uint16_t value)
+{
+ nvram_write(nvram, addr, value >> 8);
+ nvram_write(nvram, addr + 1, value & 0xFF);
+}
+
+uint16_t NVRAM_get_word (nvram_t *nvram, uint32_t addr)
+{
uint16_t tmp;
- tmp = m48t59_read(nvram, addr) << 8;
- tmp |= m48t59_read(nvram, addr + 1);
+ tmp = nvram_read(nvram, addr) << 8;
+ tmp |= nvram_read(nvram, addr + 1);
+
return tmp;
}
-void NVRAM_set_lword (m48t59_t *nvram, uint32_t addr, uint32_t value)
+void NVRAM_set_lword (nvram_t *nvram, uint32_t addr, uint32_t value)
{
- m48t59_write(nvram, addr, value >> 24);
- m48t59_write(nvram, addr + 1, (value >> 16) & 0xFF);
- m48t59_write(nvram, addr + 2, (value >> 8) & 0xFF);
- m48t59_write(nvram, addr + 3, value & 0xFF);
+ nvram_write(nvram, addr, value >> 24);
+ nvram_write(nvram, addr + 1, (value >> 16) & 0xFF);
+ nvram_write(nvram, addr + 2, (value >> 8) & 0xFF);
+ nvram_write(nvram, addr + 3, value & 0xFF);
}
-uint32_t NVRAM_get_lword (m48t59_t *nvram, uint32_t addr)
+uint32_t NVRAM_get_lword (nvram_t *nvram, uint32_t addr)
{
uint32_t tmp;
- tmp = m48t59_read(nvram, addr) << 24;
- tmp |= m48t59_read(nvram, addr + 1) << 16;
- tmp |= m48t59_read(nvram, addr + 2) << 8;
- tmp |= m48t59_read(nvram, addr + 3);
+ tmp = nvram_read(nvram, addr) << 24;
+ tmp |= nvram_read(nvram, addr + 1) << 16;
+ tmp |= nvram_read(nvram, addr + 2) << 8;
+ tmp |= nvram_read(nvram, addr + 3);
return tmp;
}
-void NVRAM_set_string (m48t59_t *nvram, uint32_t addr,
+void NVRAM_set_string (nvram_t *nvram, uint32_t addr,
const unsigned char *str, uint32_t max)
{
int i;
for (i = 0; i < max && str[i] != '\0'; i++) {
- m48t59_write(nvram, addr + i, str[i]);
+ nvram_write(nvram, addr + i, str[i]);
}
- m48t59_write(nvram, addr + max - 1, '\0');
+ nvram_write(nvram, addr + i, str[i]);
+ nvram_write(nvram, addr + max - 1, '\0');
}
-int NVRAM_get_string (m48t59_t *nvram, uint8_t *dst, uint16_t addr, int max)
+int NVRAM_get_string (nvram_t *nvram, uint8_t *dst, uint16_t addr, int max)
{
int i;
@@ -1107,7 +1340,7 @@
return tmp;
}
-uint16_t NVRAM_compute_crc (m48t59_t *nvram, uint32_t start, uint32_t count)
+uint16_t NVRAM_compute_crc (nvram_t *nvram, uint32_t start, uint32_t count)
{
uint32_t i;
uint16_t crc = 0xFFFF;
@@ -1127,7 +1360,7 @@
#define CMDLINE_ADDR 0x017ff000
-int PPC_NVRAM_set_params (m48t59_t *nvram, uint16_t NVRAM_size,
+int PPC_NVRAM_set_params (nvram_t *nvram, uint16_t NVRAM_size,
const unsigned char *arch,
uint32_t RAM_size, int boot_device,
uint32_t kernel_image, uint32_t kernel_size,
@@ -1164,7 +1397,7 @@
NVRAM_set_word(nvram, 0x56, height);
NVRAM_set_word(nvram, 0x58, depth);
crc = NVRAM_compute_crc(nvram, 0x00, 0xF8);
- NVRAM_set_word(nvram, 0xFC, crc);
+ NVRAM_set_word(nvram, 0xFC, crc);
return 0;
}
Modified: trunk/src/host/qemu-neo1973/hw/ppc405.h
===================================================================
--- trunk/src/host/qemu-neo1973/hw/ppc405.h 2007-10-29 20:40:05 UTC (rev 3302)
+++ trunk/src/host/qemu-neo1973/hw/ppc405.h 2007-10-29 21:14:04 UTC (rev 3303)
@@ -25,6 +25,8 @@
#if !defined(PPC_405_H)
#define PPC_405_H
+#include "ppc4xx.h"
+
/* Bootinfo as set-up by u-boot */
typedef struct ppc4xx_bd_info_t ppc4xx_bd_info_t;
struct ppc4xx_bd_info_t {
@@ -54,18 +56,9 @@
};
/* PowerPC 405 core */
-CPUState *ppc405_init (const unsigned char *cpu_model,
- clk_setup_t *cpu_clk, clk_setup_t *tb_clk,
- uint32_t sysclk);
-ram_addr_t ppc405_set_bootinfo (CPUState *env, ppc4xx_bd_info_t *bd);
+ram_addr_t ppc405_set_bootinfo (CPUState *env, ppc4xx_bd_info_t *bd,
+ uint32_t flags);
-/* */
-typedef struct ppc4xx_mmio_t ppc4xx_mmio_t;
-int ppc4xx_mmio_register (CPUState *env, ppc4xx_mmio_t *mmio,
- target_phys_addr_t offset, uint32_t len,
- CPUReadMemoryFunc **mem_read,
- CPUWriteMemoryFunc **mem_write, void *opaque);
-ppc4xx_mmio_t *ppc4xx_mmio_init (CPUState *env, target_phys_addr_t base);
/* PowerPC 4xx peripheral local bus arbitrer */
void ppc4xx_plb_init (CPUState *env);
/* PLB to OPB bridge */
@@ -73,14 +66,6 @@
/* OPB arbitrer */
void ppc4xx_opba_init (CPUState *env, ppc4xx_mmio_t *mmio,
target_phys_addr_t offset);
-/* PowerPC 4xx universal interrupt controller */
-enum {
- PPCUIC_OUTPUT_INT = 0,
- PPCUIC_OUTPUT_CINT = 1,
- PPCUIC_OUTPUT_NB,
-};
-qemu_irq *ppcuic_init (CPUState *env, qemu_irq *irqs,
- uint32_t dcr_base, int has_ssr, int has_vr);
/* SDRAM controller */
void ppc405_sdram_init (CPUState *env, qemu_irq irq, int nbanks,
target_phys_addr_t *ram_bases,
Modified: trunk/src/host/qemu-neo1973/hw/ppc405_boards.c
===================================================================
--- trunk/src/host/qemu-neo1973/hw/ppc405_boards.c 2007-10-29 20:40:05 UTC (rev 3302)
+++ trunk/src/host/qemu-neo1973/hw/ppc405_boards.c 2007-10-29 21:14:04 UTC (rev 3303)
@@ -226,8 +226,8 @@
fl_idx, bios_size, bios_offset, -bios_size,
bdrv_get_device_name(pflash_table[fl_idx]), fl_sectors);
#endif
- pflash_register(-(bios_size), bios_offset, pflash_table[fl_idx],
- 65536, fl_sectors, 2,
+ pflash_register((uint32_t)(-bios_size), bios_offset,
+ pflash_table[fl_idx], 65536, fl_sectors, 2,
0x0001, 0x22DA, 0x0000, 0x0000);
fl_idx++;
} else
@@ -236,7 +236,9 @@
#ifdef DEBUG_BOARD_INIT
printf("Load BIOS from file\n");
#endif
- snprintf(buf, sizeof(buf), "%s/%s", bios_dir, BIOS_FILENAME);
+ if (bios_name == NULL)
+ bios_name = BIOS_FILENAME;
+ snprintf(buf, sizeof(buf), "%s/%s", bios_dir, bios_name);
bios_size = load_image(buf, phys_ram_base + bios_offset);
if (bios_size < 0 || bios_size > BIOS_SIZE) {
fprintf(stderr, "qemu: could not load PowerPC bios '%s'\n", buf);
@@ -266,7 +268,7 @@
memset(&bd, 0, sizeof(bd));
bd.bi_memstart = 0x00000000;
bd.bi_memsize = ram_size;
- bd.bi_flashstart = -(bios_size);
+ bd.bi_flashstart = -bios_size;
bd.bi_flashsize = -bios_size;
bd.bi_flashoffset = 0;
bd.bi_sramstart = 0xFFF00000;
@@ -288,7 +290,7 @@
bd.bi_plb_busfreq = 33333333;
bd.bi_pci_busfreq = 33333333;
bd.bi_opbfreq = 33333333;
- bdloc = ppc405_set_bootinfo(env, &bd);
+ bdloc = ppc405_set_bootinfo(env, &bd, 0x00000001);
env->gpr[3] = bdloc;
kernel_base = KERNEL_LOAD_ADDR;
/* now we can load the kernel */
@@ -539,8 +541,8 @@
fl_idx, bios_size, bios_offset, -bios_size,
bdrv_get_device_name(pflash_table[fl_idx]), fl_sectors);
#endif
- pflash_register(-(bios_size), bios_offset, pflash_table[fl_idx],
- 65536, fl_sectors, 4,
+ pflash_register((uint32_t)(-bios_size), bios_offset,
+ pflash_table[fl_idx], 65536, fl_sectors, 4,
0x0001, 0x22DA, 0x0000, 0x0000);
fl_idx++;
} else
@@ -549,7 +551,9 @@
#ifdef DEBUG_BOARD_INIT
printf("Load BIOS from file\n");
#endif
- snprintf(buf, sizeof(buf), "%s/%s", bios_dir, BIOS_FILENAME);
+ if (bios_name == NULL)
+ bios_name = BIOS_FILENAME;
+ snprintf(buf, sizeof(buf), "%s/%s", bios_dir, bios_name);
bios_size = load_image(buf, phys_ram_base + bios_offset);
if (bios_size < 0 || bios_size > BIOS_SIZE) {
fprintf(stderr, "qemu: could not load PowerPC bios '%s'\n", buf);
Modified: trunk/src/host/qemu-neo1973/hw/ppc405_uc.c
===================================================================
--- trunk/src/host/qemu-neo1973/hw/ppc405_uc.c 2007-10-29 20:40:05 UTC (rev 3302)
+++ trunk/src/host/qemu-neo1973/hw/ppc405_uc.c 2007-10-29 21:14:04 UTC (rev 3303)
@@ -27,7 +27,6 @@
extern int loglevel;
extern FILE *logfile;
-//#define DEBUG_MMIO
#define DEBUG_OPBA
#define DEBUG_SDRAM
#define DEBUG_GPIO
@@ -36,41 +35,12 @@
//#define DEBUG_I2C
#define DEBUG_GPT
#define DEBUG_MAL
-#define DEBUG_UIC
#define DEBUG_CLOCKS
//#define DEBUG_UNASSIGNED
-/*****************************************************************************/
-/* Generic PowerPC 405 processor instanciation */
-CPUState *ppc405_init (const unsigned char *cpu_model,
- clk_setup_t *cpu_clk, clk_setup_t *tb_clk,
- uint32_t sysclk)
+ram_addr_t ppc405_set_bootinfo (CPUState *env, ppc4xx_bd_info_t *bd,
+ uint32_t flags)
{
- CPUState *env;
- ppc_def_t *def;
-
- /* init CPUs */
- env = cpu_init();
- qemu_register_reset(&cpu_ppc_reset, env);
- register_savevm("cpu", 0, 3, cpu_save, cpu_load, env);
- ppc_find_by_name(cpu_model, &def);
- if (def == NULL) {
- cpu_abort(env, "Unable to find PowerPC %s CPU definition\n",
- cpu_model);
- }
- cpu_ppc_register(env, def);
- cpu_clk->cb = NULL; /* We don't care about CPU clock frequency changes */
- cpu_clk->opaque = env;
- /* Set time-base frequency to sysclk */
- tb_clk->cb = ppc_emb_timers_init(env, sysclk);
- tb_clk->opaque = env;
- ppc_dcr_init(env, NULL, NULL);
-
- return env;
-}
-
-ram_addr_t ppc405_set_bootinfo (CPUState *env, ppc4xx_bd_info_t *bd)
-{
ram_addr_t bdloc;
int i, n;
@@ -103,7 +73,7 @@
for (i = 0; i < 6; i++)
stb_raw(phys_ram_base + bdloc + 0x64 + i, bd->bi_pci_enetaddr[i]);
n = 0x6A;
- if (env->spr[SPR_PVR] == CPU_PPC_405EP) {
+ if (flags & 0x00000001) {
for (i = 0; i < 6; i++)
stb_raw(phys_ram_base + bdloc + n++, bd->bi_pci_enetaddr2[i]);
}
@@ -121,203 +91,6 @@
/* Shared peripherals */
/*****************************************************************************/
-/* Fake device used to map multiple devices in a single memory page */
-#define MMIO_AREA_BITS 8
-#define MMIO_AREA_LEN (1 << MMIO_AREA_BITS)
-#define MMIO_AREA_NB (1 << (TARGET_PAGE_BITS - MMIO_AREA_BITS))
-#define MMIO_IDX(addr) (((addr) >> MMIO_AREA_BITS) & (MMIO_AREA_NB - 1))
-struct ppc4xx_mmio_t {
- target_phys_addr_t base;
- CPUReadMemoryFunc **mem_read[MMIO_AREA_NB];
- CPUWriteMemoryFunc **mem_write[MMIO_AREA_NB];
- void *opaque[MMIO_AREA_NB];
-};
-
-static uint32_t unassigned_mmio_readb (void *opaque, target_phys_addr_t addr)
-{
-#ifdef DEBUG_UNASSIGNED
- ppc4xx_mmio_t *mmio;
-
- mmio = opaque;
- printf("Unassigned mmio read 0x" PADDRX " base " PADDRX "\n",
- addr, mmio->base);
-#endif
-
- return 0;
-}
-
-static void unassigned_mmio_writeb (void *opaque,
- target_phys_addr_t addr, uint32_t val)
-{
-#ifdef DEBUG_UNASSIGNED
- ppc4xx_mmio_t *mmio;
-
- mmio = opaque;
- printf("Unassigned mmio write 0x" PADDRX " = 0x%x base " PADDRX "\n",
- addr, val, mmio->base);
-#endif
-}
-
-static CPUReadMemoryFunc *unassigned_mmio_read[3] = {
- unassigned_mmio_readb,
- unassigned_mmio_readb,
- unassigned_mmio_readb,
-};
-
-static CPUWriteMemoryFunc *unassigned_mmio_write[3] = {
- unassigned_mmio_writeb,
- unassigned_mmio_writeb,
- unassigned_mmio_writeb,
-};
-
-static uint32_t mmio_readlen (ppc4xx_mmio_t *mmio,
- target_phys_addr_t addr, int len)
-{
- CPUReadMemoryFunc **mem_read;
- uint32_t ret;
- int idx;
-
- idx = MMIO_IDX(addr - mmio->base);
-#if defined(DEBUG_MMIO)
- printf("%s: mmio %p len %d addr " PADDRX " idx %d\n", __func__,
- mmio, len, addr, idx);
-#endif
- mem_read = mmio->mem_read[idx];
- ret = (*mem_read[len])(mmio->opaque[idx], addr - mmio->base);
-
- return ret;
-}
-
-static void mmio_writelen (ppc4xx_mmio_t *mmio,
- target_phys_addr_t addr, uint32_t value, int len)
-{
- CPUWriteMemoryFunc **mem_write;
- int idx;
-
- idx = MMIO_IDX(addr - mmio->base);
-#if defined(DEBUG_MMIO)
- printf("%s: mmio %p len %d addr " PADDRX " idx %d value %08x\n", __func__,
- mmio, len, addr, idx, value);
-#endif
- mem_write = mmio->mem_write[idx];
- (*mem_write[len])(mmio->opaque[idx], addr - mmio->base, value);
-}
-
-static uint32_t mmio_readb (void *opaque, target_phys_addr_t addr)
-{
-#if defined(DEBUG_MMIO)
- printf("%s: addr " PADDRX "\n", __func__, addr);
-#endif
-
- return mmio_readlen(opaque, addr, 0);
-}
-
-static void mmio_writeb (void *opaque,
- target_phys_addr_t addr, uint32_t value)
-{
-#if defined(DEBUG_MMIO)
- printf("%s: addr " PADDRX " val %08x\n", __func__, addr, value);
-#endif
- mmio_writelen(opaque, addr, value, 0);
-}
-
-static uint32_t mmio_readw (void *opaque, target_phys_addr_t addr)
-{
-#if defined(DEBUG_MMIO)
- printf("%s: addr " PADDRX "\n", __func__, addr);
-#endif
-
- return mmio_readlen(opaque, addr, 1);
-}
-
-static void mmio_writew (void *opaque,
- target_phys_addr_t addr, uint32_t value)
-{
-#if defined(DEBUG_MMIO)
- printf("%s: addr " PADDRX " val %08x\n", __func__, addr, value);
-#endif
- mmio_writelen(opaque, addr, value, 1);
-}
-
-static uint32_t mmio_readl (void *opaque, target_phys_addr_t addr)
-{
-#if defined(DEBUG_MMIO)
- printf("%s: addr " PADDRX "\n", __func__, addr);
-#endif
-
- return mmio_readlen(opaque, addr, 2);
-}
-
-static void mmio_writel (void *opaque,
- target_phys_addr_t addr, uint32_t value)
-{
-#if defined(DEBUG_MMIO)
- printf("%s: addr " PADDRX " val %08x\n", __func__, addr, value);
-#endif
- mmio_writelen(opaque, addr, value, 2);
-}
-
-static CPUReadMemoryFunc *mmio_read[] = {
- &mmio_readb,
- &mmio_readw,
- &mmio_readl,
-};
-
-static CPUWriteMemoryFunc *mmio_write[] = {
- &mmio_writeb,
- &mmio_writew,
- &mmio_writel,
-};
-
-int ppc4xx_mmio_register (CPUState *env, ppc4xx_mmio_t *mmio,
- target_phys_addr_t offset, uint32_t len,
- CPUReadMemoryFunc **mem_read,
- CPUWriteMemoryFunc **mem_write, void *opaque)
-{
- uint32_t end;
- int idx, eidx;
-
- if ((offset + len) > TARGET_PAGE_SIZE)
- return -1;
- idx = MMIO_IDX(offset);
- end = offset + len - 1;
- eidx = MMIO_IDX(end);
-#if defined(DEBUG_MMIO)
- printf("%s: offset %08x len %08x %08x %d %d\n", __func__, offset, len,
- end, idx, eidx);
-#endif
- for (; idx <= eidx; idx++) {
- mmio->mem_read[idx] = mem_read;
- mmio->mem_write[idx] = mem_write;
- mmio->opaque[idx] = opaque;
- }
-
- return 0;
-}
-
-ppc4xx_mmio_t *ppc4xx_mmio_init (CPUState *env, target_phys_addr_t base)
-{
- ppc4xx_mmio_t *mmio;
- int mmio_memory;
-
- mmio = qemu_mallocz(sizeof(ppc4xx_mmio_t));
- if (mmio != NULL) {
- mmio->base = base;
- mmio_memory = cpu_register_io_memory(0, mmio_read, mmio_write, mmio);
-#if defined(DEBUG_MMIO)
- printf("%s: %p base %08x len %08x %d\n", __func__,
- mmio, base, TARGET_PAGE_SIZE, mmio_memory);
-#endif
- cpu_register_physical_memory(base, TARGET_PAGE_SIZE, mmio_memory);
- ppc4xx_mmio_register(env, mmio, 0, TARGET_PAGE_SIZE,
- unassigned_mmio_read, unassigned_mmio_write,
- mmio);
- }
-
- return mmio;
-}
-
-/*****************************************************************************/
/* Peripheral local bus arbitrer */
enum {
PLB0_BESR = 0x084,
@@ -622,281 +395,6 @@
}
/*****************************************************************************/
-/* "Universal" Interrupt controller */
-enum {
- DCR_UICSR = 0x000,
- DCR_UICSRS = 0x001,
- DCR_UICER = 0x002,
- DCR_UICCR = 0x003,
- DCR_UICPR = 0x004,
- DCR_UICTR = 0x005,
- DCR_UICMSR = 0x006,
- DCR_UICVR = 0x007,
- DCR_UICVCR = 0x008,
- DCR_UICMAX = 0x009,
-};
-
-#define UIC_MAX_IRQ 32
-typedef struct ppcuic_t ppcuic_t;
-struct ppcuic_t {
- uint32_t dcr_base;
- int use_vectors;
- uint32_t uicsr; /* Status register */
- uint32_t uicer; /* Enable register */
- uint32_t uiccr; /* Critical register */
- uint32_t uicpr; /* Polarity register */
- uint32_t uictr; /* Triggering register */
- uint32_t uicvcr; /* Vector configuration register */
- uint32_t uicvr;
- qemu_irq *irqs;
-};
-
-static void ppcuic_trigger_irq (ppcuic_t *uic)
-{
- uint32_t ir, cr;
- int start, end, inc, i;
-
- /* Trigger interrupt if any is pending */
- ir = uic->uicsr & uic->uicer & (~uic->uiccr);
- cr = uic->uicsr & uic->uicer & uic->uiccr;
-#ifdef DEBUG_UIC
- if (loglevel & CPU_LOG_INT) {
- fprintf(logfile, "%s: uicsr %08x uicer %08x uiccr %08x\n"
- " %08x ir %08x cr %08x\n", __func__,
- uic->uicsr, uic->uicer, uic->uiccr,
- uic->uicsr & uic->uicer, ir, cr);
- }
-#endif
- if (ir != 0x0000000) {
-#ifdef DEBUG_UIC
- if (loglevel & CPU_LOG_INT) {
- fprintf(logfile, "Raise UIC interrupt\n");
- }
-#endif
- qemu_irq_raise(uic->irqs[PPCUIC_OUTPUT_INT]);
- } else {
-#ifdef DEBUG_UIC
- if (loglevel & CPU_LOG_INT) {
- fprintf(logfile, "Lower UIC interrupt\n");
- }
-#endif
- qemu_irq_lower(uic->irqs[PPCUIC_OUTPUT_INT]);
- }
- /* Trigger critical interrupt if any is pending and update vector */
- if (cr != 0x0000000) {
- qemu_irq_raise(uic->irqs[PPCUIC_OUTPUT_CINT]);
- if (uic->use_vectors) {
- /* Compute critical IRQ vector */
- if (uic->uicvcr & 1) {
- start = 31;
- end = 0;
- inc = -1;
- } else {
- start = 0;
- end = 31;
- inc = 1;
- }
- uic->uicvr = uic->uicvcr & 0xFFFFFFFC;
- for (i = start; i <= end; i += inc) {
- if (cr & (1 << i)) {
- uic->uicvr += (i - start) * 512 * inc;
- break;
- }
- }
- }
-#ifdef DEBUG_UIC
- if (loglevel & CPU_LOG_INT) {
- fprintf(logfile, "Raise UIC critical interrupt - vector %08x\n",
- uic->uicvr);
- }
-#endif
- } else {
-#ifdef DEBUG_UIC
- if (loglevel & CPU_LOG_INT) {
- fprintf(logfile, "Lower UIC critical interrupt\n");
- }
-#endif
- qemu_irq_lower(uic->irqs[PPCUIC_OUTPUT_CINT]);
- uic->uicvr = 0x00000000;
- }
-}
-
-static void ppcuic_set_irq (void *opaque, int irq_num, int level)
-{
- ppcuic_t *uic;
- uint32_t mask, sr;
-
- uic = opaque;
- mask = 1 << irq_num;
-#ifdef DEBUG_UIC
- if (loglevel & CPU_LOG_INT) {
- fprintf(logfile, "%s: irq %d level %d uicsr %08x mask %08x => %08x "
- "%08x\n", __func__, irq_num, level,
- uic->uicsr, mask, uic->uicsr & mask, level << irq_num);
- }
-#endif
- if (irq_num < 0 || irq_num > 31)
- return;
- sr = uic->uicsr;
- if (!(uic->uicpr & mask)) {
- /* Negatively asserted IRQ */
- level = level == 0 ? 1 : 0;
- }
- /* Update status register */
- if (uic->uictr & mask) {
- /* Edge sensitive interrupt */
- if (level == 1)
- uic->uicsr |= mask;
- } else {
- /* Level sensitive interrupt */
- if (level == 1)
- uic->uicsr |= mask;
- else
- uic->uicsr &= ~mask;
- }
-#ifdef DEBUG_UIC
- if (loglevel & CPU_LOG_INT) {
- fprintf(logfile, "%s: irq %d level %d sr %08x => %08x\n", __func__,
- irq_num, level, uic->uicsr, sr);
- }
-#endif
- if (sr != uic->uicsr)
- ppcuic_trigger_irq(uic);
-}
-
-static target_ulong dcr_read_uic (void *opaque, int dcrn)
-{
- ppcuic_t *uic;
- target_ulong ret;
-
- uic = opaque;
- dcrn -= uic->dcr_base;
- switch (dcrn) {
- case DCR_UICSR:
- case DCR_UICSRS:
- ret = uic->uicsr;
- break;
- case DCR_UICER:
- ret = uic->uicer;
- break;
- case DCR_UICCR:
- ret = uic->uiccr;
- break;
- case DCR_UICPR:
- ret = uic->uicpr;
- break;
- case DCR_UICTR:
- ret = uic->uictr;
- break;
- case DCR_UICMSR:
- ret = uic->uicsr & uic->uicer;
- break;
- case DCR_UICVR:
- if (!uic->use_vectors)
- goto no_read;
- ret = uic->uicvr;
- break;
- case DCR_UICVCR:
- if (!uic->use_vectors)
- goto no_read;
- ret = uic->uicvcr;
- break;
- default:
- no_read:
- ret = 0x00000000;
- break;
- }
-
- return ret;
-}
-
-static void dcr_write_uic (void *opaque, int dcrn, target_ulong val)
-{
- ppcuic_t *uic;
-
- uic = opaque;
- dcrn -= uic->dcr_base;
-#ifdef DEBUG_UIC
- if (loglevel & CPU_LOG_INT) {
- fprintf(logfile, "%s: dcr %d val " ADDRX "\n", __func__, dcrn, val);
- }
-#endif
- switch (dcrn) {
- case DCR_UICSR:
- uic->uicsr &= ~val;
- ppcuic_trigger_irq(uic);
- break;
- case DCR_UICSRS:
- uic->uicsr |= val;
- ppcuic_trigger_irq(uic);
- break;
- case DCR_UICER:
- uic->uicer = val;
- ppcuic_trigger_irq(uic);
- break;
- case DCR_UICCR:
- uic->uiccr = val;
- ppcuic_trigger_irq(uic);
- break;
- case DCR_UICPR:
- uic->uicpr = val;
- ppcuic_trigger_irq(uic);
- break;
- case DCR_UICTR:
- uic->uictr = val;
- ppcuic_trigger_irq(uic);
- break;
- case DCR_UICMSR:
- break;
- case DCR_UICVR:
- break;
- case DCR_UICVCR:
- uic->uicvcr = val & 0xFFFFFFFD;
- ppcuic_trigger_irq(uic);
- break;
- }
-}
-
-static void ppcuic_reset (void *opaque)
-{
- ppcuic_t *uic;
-
- uic = opaque;
- uic->uiccr = 0x00000000;
- uic->uicer = 0x00000000;
- uic->uicpr = 0x00000000;
- uic->uicsr = 0x00000000;
- uic->uictr = 0x00000000;
- if (uic->use_vectors) {
- uic->uicvcr = 0x00000000;
- uic->uicvr = 0x0000000;
- }
-}
-
-qemu_irq *ppcuic_init (CPUState *env, qemu_irq *irqs,
- uint32_t dcr_base, int has_ssr, int has_vr)
-{
- ppcuic_t *uic;
- int i;
-
- uic = qemu_mallocz(sizeof(ppcuic_t));
- if (uic != NULL) {
- uic->dcr_base = dcr_base;
- uic->irqs = irqs;
- if (has_vr)
- uic->use_vectors = 1;
- for (i = 0; i < DCR_UICMAX; i++) {
- ppc_dcr_register(env, dcr_base + i, uic,
- &dcr_read_uic, &dcr_write_uic);
- }
- qemu_register_reset(ppcuic_reset, uic);
- ppcuic_reset(uic);
- }
-
- return qemu_allocate_irqs(&ppcuic_set_irq, uic, UIC_MAX_IRQ);
-}
-
-/*****************************************************************************/
/* Code decompression controller */
/* XXX: TODO */
@@ -965,7 +463,7 @@
return bcr;
}
-static inline target_phys_addr_t sdram_base (uint32_t bcr)
+static always_inline target_phys_addr_t sdram_base (uint32_t bcr)
{
return bcr & 0xFF800000;
}
@@ -2691,12 +2189,17 @@
target_ulong dbsr;
printf("Reset PowerPC core\n");
+ env->interrupt_request |= CPU_INTERRUPT_EXITTB;
+ /* XXX: TOFIX */
+#if 0
cpu_ppc_reset(env);
+#else
+ qemu_system_reset_request();
+#endif
dbsr = env->spr[SPR_40x_DBSR];
dbsr &= ~0x00000300;
dbsr |= 0x00000100;
env->spr[SPR_40x_DBSR] = dbsr;
- cpu_loop_exit();
}
void ppc40x_chip_reset (CPUState *env)
@@ -2704,13 +2207,18 @@
target_ulong dbsr;
printf("Reset PowerPC chip\n");
+ env->interrupt_request |= CPU_INTERRUPT_EXITTB;
+ /* XXX: TOFIX */
+#if 0
cpu_ppc_reset(env);
+#else
+ qemu_system_reset_request();
+#endif
/* XXX: TODO reset all internal peripherals */
dbsr = env->spr[SPR_40x_DBSR];
dbsr &= ~0x00000300;
dbsr |= 0x00000200;
env->spr[SPR_40x_DBSR] = dbsr;
- cpu_loop_exit();
}
void ppc40x_system_reset (CPUState *env)
@@ -3037,7 +2545,7 @@
int i;
memset(clk_setup, 0, sizeof(clk_setup));
- env = ppc405_init("405cr", &clk_setup[PPC405CR_CPU_CLK],
+ env = ppc4xx_init("405cr", &clk_setup[PPC405CR_CPU_CLK],
&clk_setup[PPC405CR_TMR_CLK], sysclk);
/* Memory mapped devices registers */
mmio = ppc4xx_mmio_init(env, 0xEF600000);
@@ -3050,9 +2558,9 @@
/* Universal interrupt controller */
irqs = qemu_mallocz(sizeof(qemu_irq) * PPCUIC_OUTPUT_NB);
irqs[PPCUIC_OUTPUT_INT] =
- ((qemu_irq *)env->irq_inputs)[PPC405_INPUT_INT];
+ ((qemu_irq *)env->irq_inputs)[PPC40x_INPUT_INT];
irqs[PPCUIC_OUTPUT_CINT] =
- ((qemu_irq *)env->irq_inputs)[PPC405_INPUT_CINT];
+ ((qemu_irq *)env->irq_inputs)[PPC40x_INPUT_CINT];
pic = ppcuic_init(env, irqs, 0x0C0, 0, 1);
*picp = pic;
/* SDRAM controller */
@@ -3387,7 +2895,7 @@
memset(clk_setup, 0, sizeof(clk_setup));
/* init CPUs */
- env = ppc405_init("405ep", &clk_setup[PPC405EP_CPU_CLK],
+ env = ppc4xx_init("405ep", &clk_setup[PPC405EP_CPU_CLK],
&tlb_clk_setup, sysclk);
clk_setup[PPC405EP_CPU_CLK].cb = tlb_clk_setup.cb;
clk_setup[PPC405EP_CPU_CLK].opaque = tlb_clk_setup.opaque;
@@ -3403,9 +2911,9 @@
/* Universal interrupt controller */
irqs = qemu_mallocz(sizeof(qemu_irq) * PPCUIC_OUTPUT_NB);
irqs[PPCUIC_OUTPUT_INT] =
- ((qemu_irq *)env->irq_inputs)[PPC405_INPUT_INT];
+ ((qemu_irq *)env->irq_inputs)[PPC40x_INPUT_INT];
irqs[PPCUIC_OUTPUT_CINT] =
- ((qemu_irq *)env->irq_inputs)[PPC405_INPUT_CINT];
+ ((qemu_irq *)env->irq_inputs)[PPC40x_INPUT_CINT];
pic = ppcuic_init(env, irqs, 0x0C0, 0, 1);
*picp = pic;
/* SDRAM controller */
Added: trunk/src/host/qemu-neo1973/hw/ppc4xx.h
===================================================================
--- trunk/src/host/qemu-neo1973/hw/ppc4xx.h 2007-10-29 20:40:05 UTC (rev 3302)
+++ trunk/src/host/qemu-neo1973/hw/ppc4xx.h 2007-10-29 21:14:04 UTC (rev 3303)
@@ -0,0 +1,49 @@
+/*
+ * QEMU PowerPC 4xx emulation shared definitions
+ *
+ * Copyright (c) 2007 Jocelyn Mayer
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+
+#if !defined(PPC_4XX_H)
+#define PPC_4XX_H
+
+/* PowerPC 4xx core initialization */
+CPUState *ppc4xx_init (const unsigned char *cpu_model,
+ clk_setup_t *cpu_clk, clk_setup_t *tb_clk,
+ uint32_t sysclk);
+
+typedef struct ppc4xx_mmio_t ppc4xx_mmio_t;
+int ppc4xx_mmio_register (CPUState *env, ppc4xx_mmio_t *mmio,
+ target_phys_addr_t offset, uint32_t len,
+ CPUReadMemoryFunc **mem_read,
+ CPUWriteMemoryFunc **mem_write, void *opaque);
+ppc4xx_mmio_t *ppc4xx_mmio_init (CPUState *env, target_phys_addr_t base);
+
+/* PowerPC 4xx universal interrupt controller */
+enum {
+ PPCUIC_OUTPUT_INT = 0,
+ PPCUIC_OUTPUT_CINT = 1,
+ PPCUIC_OUTPUT_NB,
+};
+qemu_irq *ppcuic_init (CPUState *env, qemu_irq *irqs,
+ uint32_t dcr_base, int has_ssr, int has_vr);
+
+#endif /* !defined(PPC_4XX_H) */
Added: trunk/src/host/qemu-neo1973/hw/ppc4xx_devs.c
===================================================================
--- trunk/src/host/qemu-neo1973/hw/ppc4xx_devs.c 2007-10-29 20:40:05 UTC (rev 3302)
+++ trunk/src/host/qemu-neo1973/hw/ppc4xx_devs.c 2007-10-29 21:14:04 UTC (rev 3303)
@@ -0,0 +1,534 @@
+/*
+ * QEMU PowerPC 4xx embedded processors shared devices emulation
+ *
+ * Copyright (c) 2007 Jocelyn Mayer
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+#include "vl.h"
+#include "ppc4xx.h"
+
+extern int loglevel;
+extern FILE *logfile;
+
+//#define DEBUG_MMIO
+#define DEBUG_UIC
+
+/*****************************************************************************/
+/* Generic PowerPC 4xx processor instanciation */
+CPUState *ppc4xx_init (const unsigned char *cpu_model,
+ clk_setup_t *cpu_clk, clk_setup_t *tb_clk,
+ uint32_t sysclk)
+{
+ CPUState *env;
+ ppc_def_t *def;
+
+ /* init CPUs */
+ env = cpu_init();
+ ppc_find_by_name(cpu_model, &def);
+ if (def == NULL) {
+ cpu_abort(env, "Unable to find PowerPC %s CPU definition\n",
+ cpu_model);
+ }
+ cpu_ppc_register(env, def);
+ cpu_ppc_reset(env);
+ cpu_clk->cb = NULL; /* We don't care about CPU clock frequency changes */
+ cpu_clk->opaque = env;
+ /* Set time-base frequency to sysclk */
+ tb_clk->cb = ppc_emb_timers_init(env, sysclk);
+ tb_clk->opaque = env;
+ ppc_dcr_init(env, NULL, NULL);
+ /* Register qemu callbacks */
+ qemu_register_reset(&cpu_ppc_reset, env);
+ register_savevm("cpu", 0, 3, cpu_save, cpu_load, env);
+
+ return env;
+}
+
+/*****************************************************************************/
+/* Fake device used to map multiple devices in a single memory page */
+#define MMIO_AREA_BITS 8
+#define MMIO_AREA_LEN (1 << MMIO_AREA_BITS)
+#define MMIO_AREA_NB (1 << (TARGET_PAGE_BITS - MMIO_AREA_BITS))
+#define MMIO_IDX(addr) (((addr) >> MMIO_AREA_BITS) & (MMIO_AREA_NB - 1))
+struct ppc4xx_mmio_t {
+ target_phys_addr_t base;
+ CPUReadMemoryFunc **mem_read[MMIO_AREA_NB];
+ CPUWriteMemoryFunc **mem_write[MMIO_AREA_NB];
+ void *opaque[MMIO_AREA_NB];
+};
+
+static uint32_t unassigned_mmio_readb (void *opaque, target_phys_addr_t addr)
+{
+#ifdef DEBUG_UNASSIGNED
+ ppc4xx_mmio_t *mmio;
+
+ mmio = opaque;
+ printf("Unassigned mmio read 0x" PADDRX " base " PADDRX "\n",
+ addr, mmio->base);
+#endif
+
+ return 0;
+}
+
+static void unassigned_mmio_writeb (void *opaque,
+ target_phys_addr_t addr, uint32_t val)
+{
+#ifdef DEBUG_UNASSIGNED
+ ppc4xx_mmio_t *mmio;
+
+ mmio = opaque;
+ printf("Unassigned mmio write 0x" PADDRX " = 0x%x base " PADDRX "\n",
+ addr, val, mmio->base);
+#endif
+}
+
+static CPUReadMemoryFunc *unassigned_mmio_read[3] = {
+ unassigned_mmio_readb,
+ unassigned_mmio_readb,
+ unassigned_mmio_readb,
+};
+
+static CPUWriteMemoryFunc *unassigned_mmio_write[3] = {
+ unassigned_mmio_writeb,
+ unassigned_mmio_writeb,
+ unassigned_mmio_writeb,
+};
+
+static uint32_t mmio_readlen (ppc4xx_mmio_t *mmio,
+ target_phys_addr_t addr, int len)
+{
+ CPUReadMemoryFunc **mem_read;
+ uint32_t ret;
+ int idx;
+
+ idx = MMIO_IDX(addr - mmio->base);
+#if defined(DEBUG_MMIO)
+ printf("%s: mmio %p len %d addr " PADDRX " idx %d\n", __func__,
+ mmio, len, addr, idx);
+#endif
+ mem_read = mmio->mem_read[idx];
+ ret = (*mem_read[len])(mmio->opaque[idx], addr - mmio->base);
+
+ return ret;
+}
+
+static void mmio_writelen (ppc4xx_mmio_t *mmio,
+ target_phys_addr_t addr, uint32_t value, int len)
+{
+ CPUWriteMemoryFunc **mem_write;
+ int idx;
+
+ idx = MMIO_IDX(addr - mmio->base);
+#if defined(DEBUG_MMIO)
+ printf("%s: mmio %p len %d addr " PADDRX " idx %d value %08x\n", __func__,
+ mmio, len, addr, idx, value);
+#endif
+ mem_write = mmio->mem_write[idx];
+ (*mem_write[len])(mmio->opaque[idx], addr - mmio->base, value);
+}
+
+static uint32_t mmio_readb (void *opaque, target_phys_addr_t addr)
+{
+#if defined(DEBUG_MMIO)
+ printf("%s: addr " PADDRX "\n", __func__, addr);
+#endif
+
+ return mmio_readlen(opaque, addr, 0);
+}
+
+static void mmio_writeb (void *opaque,
+ target_phys_addr_t addr, uint32_t value)
+{
+#if defined(DEBUG_MMIO)
+ printf("%s: addr " PADDRX " val %08x\n", __func__, addr, value);
+#endif
+ mmio_writelen(opaque, addr, value, 0);
+}
+
+static uint32_t mmio_readw (void *opaque, target_phys_addr_t addr)
+{
+#if defined(DEBUG_MMIO)
+ printf("%s: addr " PADDRX "\n", __func__, addr);
+#endif
+
+ return mmio_readlen(opaque, addr, 1);
+}
+
+static void mmio_writew (void *opaque,
+ target_phys_addr_t addr, uint32_t value)
+{
+#if defined(DEBUG_MMIO)
+ printf("%s: addr " PADDRX " val %08x\n", __func__, addr, value);
+#endif
+ mmio_writelen(opaque, addr, value, 1);
+}
+
+static uint32_t mmio_readl (void *opaque, target_phys_addr_t addr)
+{
+#if defined(DEBUG_MMIO)
+ printf("%s: addr " PADDRX "\n", __func__, addr);
+#endif
+
+ return mmio_readlen(opaque, addr, 2);
+}
+
+static void mmio_writel (void *opaque,
+ target_phys_addr_t addr, uint32_t value)
+{
+#if defined(DEBUG_MMIO)
+ printf("%s: addr " PADDRX " val %08x\n", __func__, addr, value);
+#endif
+ mmio_writelen(opaque, addr, value, 2);
+}
+
+static CPUReadMemoryFunc *mmio_read[] = {
+ &mmio_readb,
+ &mmio_readw,
+ &mmio_readl,
+};
+
+static CPUWriteMemoryFunc *mmio_write[] = {
+ &mmio_writeb,
+ &mmio_writew,
+ &mmio_writel,
+};
+
+int ppc4xx_mmio_register (CPUState *env, ppc4xx_mmio_t *mmio,
+ target_phys_addr_t offset, uint32_t len,
+ CPUReadMemoryFunc **mem_read,
+ CPUWriteMemoryFunc **mem_write, void *opaque)
+{
+ uint32_t end;
+ int idx, eidx;
+
+ if ((offset + len) > TARGET_PAGE_SIZE)
+ return -1;
+ idx = MMIO_IDX(offset);
+ end = offset + len - 1;
+ eidx = MMIO_IDX(end);
+#if defined(DEBUG_MMIO)
+ printf("%s: offset %08x len %08x %08x %d %d\n", __func__, offset, len,
+ end, idx, eidx);
+#endif
+ for (; idx <= eidx; idx++) {
+ mmio->mem_read[idx] = mem_read;
+ mmio->mem_write[idx] = mem_write;
+ mmio->opaque[idx] = opaque;
+ }
+
+ return 0;
+}
+
+ppc4xx_mmio_t *ppc4xx_mmio_init (CPUState *env, target_phys_addr_t base)
+{
+ ppc4xx_mmio_t *mmio;
+ int mmio_memory;
+
+ mmio = qemu_mallocz(sizeof(ppc4xx_mmio_t));
+ if (mmio != NULL) {
+ mmio->base = base;
+ mmio_memory = cpu_register_io_memory(0, mmio_read, mmio_write, mmio);
+#if defined(DEBUG_MMIO)
+ printf("%s: %p base %08x len %08x %d\n", __func__,
+ mmio, base, TARGET_PAGE_SIZE, mmio_memory);
+#endif
+ cpu_register_physical_memory(base, TARGET_PAGE_SIZE, mmio_memory);
+ ppc4xx_mmio_register(env, mmio, 0, TARGET_PAGE_SIZE,
+ unassigned_mmio_read, unassigned_mmio_write,
+ mmio);
+ }
+
+ return mmio;
+}
+
+/*****************************************************************************/
+/* "Universal" Interrupt controller */
+enum {
+ DCR_UICSR = 0x000,
+ DCR_UICSRS = 0x001,
+ DCR_UICER = 0x002,
+ DCR_UICCR = 0x003,
+ DCR_UICPR = 0x004,
+ DCR_UICTR = 0x005,
+ DCR_UICMSR = 0x006,
+ DCR_UICVR = 0x007,
+ DCR_UICVCR = 0x008,
+ DCR_UICMAX = 0x009,
+};
+
+#define UIC_MAX_IRQ 32
+typedef struct ppcuic_t ppcuic_t;
+struct ppcuic_t {
+ uint32_t dcr_base;
+ int use_vectors;
+ uint32_t uicsr; /* Status register */
+ uint32_t uicer; /* Enable register */
+ uint32_t uiccr; /* Critical register */
+ uint32_t uicpr; /* Polarity register */
+ uint32_t uictr; /* Triggering register */
+ uint32_t uicvcr; /* Vector configuration register */
+ uint32_t uicvr;
+ qemu_irq *irqs;
+};
+
+static void ppcuic_trigger_irq (ppcuic_t *uic)
+{
+ uint32_t ir, cr;
+ int start, end, inc, i;
+
+ /* Trigger interrupt if any is pending */
+ ir = uic->uicsr & uic->uicer & (~uic->uiccr);
+ cr = uic->uicsr & uic->uicer & uic->uiccr;
+#ifdef DEBUG_UIC
+ if (loglevel & CPU_LOG_INT) {
+ fprintf(logfile, "%s: uicsr %08x uicer %08x uiccr %08x\n"
+ " %08x ir %08x cr %08x\n", __func__,
+ uic->uicsr, uic->uicer, uic->uiccr,
+ uic->uicsr & uic->uicer, ir, cr);
+ }
+#endif
+ if (ir != 0x0000000) {
+#ifdef DEBUG_UIC
+ if (loglevel & CPU_LOG_INT) {
+ fprintf(logfile, "Raise UIC interrupt\n");
+ }
+#endif
+ qemu_irq_raise(uic->irqs[PPCUIC_OUTPUT_INT]);
+ } else {
+#ifdef DEBUG_UIC
+ if (loglevel & CPU_LOG_INT) {
+ fprintf(logfile, "Lower UIC interrupt\n");
+ }
+#endif
+ qemu_irq_lower(uic->irqs[PPCUIC_OUTPUT_INT]);
+ }
+ /* Trigger critical interrupt if any is pending and update vector */
+ if (cr != 0x0000000) {
+ qemu_irq_raise(uic->irqs[PPCUIC_OUTPUT_CINT]);
+ if (uic->use_vectors) {
+ /* Compute critical IRQ vector */
+ if (uic->uicvcr & 1) {
+ start = 31;
+ end = 0;
+ inc = -1;
+ } else {
+ start = 0;
+ end = 31;
+ inc = 1;
+ }
+ uic->uicvr = uic->uicvcr & 0xFFFFFFFC;
+ for (i = start; i <= end; i += inc) {
+ if (cr & (1 << i)) {
+ uic->uicvr += (i - start) * 512 * inc;
+ break;
+ }
+ }
+ }
+#ifdef DEBUG_UIC
+ if (loglevel & CPU_LOG_INT) {
+ fprintf(logfile, "Raise UIC critical interrupt - vector %08x\n",
+ uic->uicvr);
+ }
+#endif
+ } else {
+#ifdef DEBUG_UIC
+ if (loglevel & CPU_LOG_INT) {
+ fprintf(logfile, "Lower UIC critical interrupt\n");
+ }
+#endif
+ qemu_irq_lower(uic->irqs[PPCUIC_OUTPUT_CINT]);
+ uic->uicvr = 0x00000000;
+ }
+}
+
+static void ppcuic_set_irq (void *opaque, int irq_num, int level)
+{
+ ppcuic_t *uic;
+ uint32_t mask, sr;
+
+ uic = opaque;
+ mask = 1 << irq_num;
+#ifdef DEBUG_UIC
+ if (loglevel & CPU_LOG_INT) {
+ fprintf(logfile, "%s: irq %d level %d uicsr %08x mask %08x => %08x "
+ "%08x\n", __func__, irq_num, level,
+ uic->uicsr, mask, uic->uicsr & mask, level << irq_num);
+ }
+#endif
+ if (irq_num < 0 || irq_num > 31)
+ return;
+ sr = uic->uicsr;
+ if (!(uic->uicpr & mask)) {
+ /* Negatively asserted IRQ */
+ level = level == 0 ? 1 : 0;
+ }
+ /* Update status register */
+ if (uic->uictr & mask) {
+ /* Edge sensitive interrupt */
+ if (level == 1)
+ uic->uicsr |= mask;
+ } else {
+ /* Level sensitive interrupt */
+ if (level == 1)
+ uic->uicsr |= mask;
+ else
+ uic->uicsr &= ~mask;
+ }
+#ifdef DEBUG_UIC
+ if (loglevel & CPU_LOG_INT) {
+ fprintf(logfile, "%s: irq %d level %d sr %08x => %08x\n", __func__,
+ irq_num, level, uic->uicsr, sr);
+ }
+#endif
+ if (sr != uic->uicsr)
+ ppcuic_trigger_irq(uic);
+}
+
+static target_ulong dcr_read_uic (void *opaque, int dcrn)
+{
+ ppcuic_t *uic;
+ target_ulong ret;
+
+ uic = opaque;
+ dcrn -= uic->dcr_base;
+ switch (dcrn) {
+ case DCR_UICSR:
+ case DCR_UICSRS:
+ ret = uic->uicsr;
+ break;
+ case DCR_UICER:
+ ret = uic->uicer;
+ break;
+ case DCR_UICCR:
+ ret = uic->uiccr;
+ break;
+ case DCR_UICPR:
+ ret = uic->uicpr;
+ break;
+ case DCR_UICTR:
+ ret = uic->uictr;
+ break;
+ case DCR_UICMSR:
+ ret = uic->uicsr & uic->uicer;
+ break;
+ case DCR_UICVR:
+ if (!uic->use_vectors)
+ goto no_read;
+ ret = uic->uicvr;
+ break;
+ case DCR_UICVCR:
+ if (!uic->use_vectors)
+ goto no_read;
+ ret = uic->uicvcr;
+ break;
+ default:
+ no_read:
+ ret = 0x00000000;
+ break;
+ }
+
+ return ret;
+}
+
+static void dcr_write_uic (void *opaque, int dcrn, target_ulong val)
+{
+ ppcuic_t *uic;
+
+ uic = opaque;
+ dcrn -= uic->dcr_base;
+#ifdef DEBUG_UIC
+ if (loglevel & CPU_LOG_INT) {
+ fprintf(logfile, "%s: dcr %d val " ADDRX "\n", __func__, dcrn, val);
+ }
+#endif
+ switch (dcrn) {
+ case DCR_UICSR:
+ uic->uicsr &= ~val;
+ ppcuic_trigger_irq(uic);
+ break;
+ case DCR_UICSRS:
+ uic->uicsr |= val;
+ ppcuic_trigger_irq(uic);
+ break;
+ case DCR_UICER:
+ uic->uicer = val;
+ ppcuic_trigger_irq(uic);
+ break;
+ case DCR_UICCR:
+ uic->uiccr = val;
+ ppcuic_trigger_irq(uic);
+ break;
+ case DCR_UICPR:
+ uic->uicpr = val;
+ ppcuic_trigger_irq(uic);
+ break;
+ case DCR_UICTR:
+ uic->uictr = val;
+ ppcuic_trigger_irq(uic);
+ break;
+ case DCR_UICMSR:
+ break;
+ case DCR_UICVR:
+ break;
+ case DCR_UICVCR:
+ uic->uicvcr = val & 0xFFFFFFFD;
+ ppcuic_trigger_irq(uic);
+ break;
+ }
+}
+
+static void ppcuic_reset (void *opaque)
+{
+ ppcuic_t *uic;
+
+ uic = opaque;
+ uic->uiccr = 0x00000000;
+ uic->uicer = 0x00000000;
+ uic->uicpr = 0x00000000;
+ uic->uicsr = 0x00000000;
+ uic->uictr = 0x00000000;
+ if (uic->use_vectors) {
+ uic->uicvcr = 0x00000000;
+ uic->uicvr = 0x0000000;
+ }
+}
+
+qemu_irq *ppcuic_init (CPUState *env, qemu_irq *irqs,
+ uint32_t dcr_base, int has_ssr, int has_vr)
+{
+ ppcuic_t *uic;
+ int i;
+
+ uic = qemu_mallocz(sizeof(ppcuic_t));
+ if (uic != NULL) {
+ uic->dcr_base = dcr_base;
+ uic->irqs = irqs;
+ if (has_vr)
+ uic->use_vectors = 1;
+ for (i = 0; i < DCR_UICMAX; i++) {
+ ppc_dcr_register(env, dcr_base + i, uic,
+ &dcr_read_uic, &dcr_write_uic);
+ }
+ qemu_register_reset(ppcuic_reset, uic);
+ ppcuic_reset(uic);
+ }
+
+ return qemu_allocate_irqs(&ppcuic_set_irq, uic, UIC_MAX_IRQ);
+}
Modified: trunk/src/host/qemu-neo1973/hw/ppc_chrp.c
===================================================================
--- trunk/src/host/qemu-neo1973/hw/ppc_chrp.c 2007-10-29 20:40:05 UTC (rev 3302)
+++ trunk/src/host/qemu-neo1973/hw/ppc_chrp.c 2007-10-29 21:14:04 UTC (rev 3303)
@@ -1,7 +1,8 @@
/*
- * QEMU PPC CHRP/PMAC hardware System Emulator
+ * QEMU PowerPC CHRP (currently NewWorld PowerMac) hardware System Emulator
*
* Copyright (c) 2004-2007 Fabrice Bellard
+ * Copyright (c) 2007 Jocelyn Mayer
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
@@ -22,172 +23,8 @@
* THE SOFTWARE.
*/
#include "vl.h"
+#include "ppc_mac.h"
-/* SMP is not enabled, for now */
-#define MAX_CPUS 1
-
-#define BIOS_FILENAME "ppc_rom.bin"
-#define VGABIOS_FILENAME "video.x"
-#define NVRAM_SIZE 0x2000
-
-#define KERNEL_LOAD_ADDR 0x01000000
-#define INITRD_LOAD_ADDR 0x01800000
-
-/* MacIO devices (mapped inside the MacIO address space): CUDA, DBDMA,
- NVRAM */
-
-static int dbdma_mem_index;
-static int cuda_mem_index;
-static int ide0_mem_index = -1;
-static int ide1_mem_index = -1;
-static int openpic_mem_index = -1;
-static int heathrow_pic_mem_index = -1;
-static int macio_nvram_mem_index = -1;
-
-/* DBDMA: currently no op - should suffice right now */
-
-static void dbdma_writeb (void *opaque,
- target_phys_addr_t addr, uint32_t value)
-{
- printf("%s: 0x" PADDRX " <= 0x%08x\n", __func__, addr, value);
-}
-
-static void dbdma_writew (void *opaque,
- target_phys_addr_t addr, uint32_t value)
-{
-}
-
-static void dbdma_writel (void *opaque,
- target_phys_addr_t addr, uint32_t value)
-{
-}
-
-static uint32_t dbdma_readb (void *opaque, target_phys_addr_t addr)
-{
- printf("%s: 0x" PADDRX " => 0x00000000\n", __func__, addr);
-
- return 0;
-}
-
-static uint32_t dbdma_readw (void *opaque, target_phys_addr_t addr)
-{
- return 0;
-}
-
-static uint32_t dbdma_readl (void *opaque, target_phys_addr_t addr)
-{
- return 0;
-}
-
-static CPUWriteMemoryFunc *dbdma_write[] = {
- &dbdma_writeb,
- &dbdma_writew,
- &dbdma_writel,
-};
-
-static CPUReadMemoryFunc *dbdma_read[] = {
- &dbdma_readb,
- &dbdma_readw,
- &dbdma_readl,
-};
-
-/* macio style NVRAM device */
-typedef struct MacIONVRAMState {
- uint8_t data[0x2000];
-} MacIONVRAMState;
-
-static void macio_nvram_writeb (void *opaque,
- target_phys_addr_t addr, uint32_t value)
-{
- MacIONVRAMState *s = opaque;
- addr = (addr >> 4) & 0x1fff;
- s->data[addr] = value;
- // printf("macio_nvram_writeb %04x = %02x\n", addr, value);
-}
-
-static uint32_t macio_nvram_readb (void *opaque, target_phys_addr_t addr)
-{
- MacIONVRAMState *s = opaque;
- uint32_t value;
-
- addr = (addr >> 4) & 0x1fff;
- value = s->data[addr];
- // printf("macio_nvram_readb %04x = %02x\n", addr, value);
-
- return value;
-}
-
-static CPUWriteMemoryFunc *macio_nvram_write[] = {
- &macio_nvram_writeb,
- &macio_nvram_writeb,
- &macio_nvram_writeb,
-};
-
-static CPUReadMemoryFunc *macio_nvram_read[] = {
- &macio_nvram_readb,
- &macio_nvram_readb,
- &macio_nvram_readb,
-};
-
-static MacIONVRAMState *macio_nvram_init (void)
-{
- MacIONVRAMState *s;
- s = qemu_mallocz(sizeof(MacIONVRAMState));
- if (!s)
- return NULL;
- macio_nvram_mem_index = cpu_register_io_memory(0, macio_nvram_read,
- macio_nvram_write, s);
-
- return s;
-}
-
-static void macio_map (PCIDevice *pci_dev, int region_num,
- uint32_t addr, uint32_t size, int type)
-{
- if (heathrow_pic_mem_index >= 0) {
- cpu_register_physical_memory(addr + 0x00000, 0x1000,
- heathrow_pic_mem_index);
- }
- cpu_register_physical_memory(addr + 0x08000, 0x1000, dbdma_mem_index);
- cpu_register_physical_memory(addr + 0x16000, 0x2000, cuda_mem_index);
- if (ide0_mem_index >= 0)
- cpu_register_physical_memory(addr + 0x1f000, 0x1000, ide0_mem_index);
- if (ide1_mem_index >= 0)
- cpu_register_physical_memory(addr + 0x20000, 0x1000, ide1_mem_index);
- if (openpic_mem_index >= 0) {
- cpu_register_physical_memory(addr + 0x40000, 0x40000,
- openpic_mem_index);
- }
- if (macio_nvram_mem_index >= 0)
- cpu_register_physical_memory(addr + 0x60000, 0x20000,
- macio_nvram_mem_index);
-}
-
-static void macio_init (PCIBus *bus, int device_id)
-{
- PCIDevice *d;
-
- d = pci_register_device(bus, "macio", sizeof(PCIDevice),
- -1, NULL, NULL);
- /* Note: this code is strongly inspirated from the corresponding code
- in PearPC */
- d->config[0x00] = 0x6b; // vendor_id
- d->config[0x01] = 0x10;
- d->config[0x02] = device_id;
- d->config[0x03] = device_id >> 8;
-
- d->config[0x0a] = 0x00; // class_sub = pci2pci
- d->config[0x0b] = 0xff; // class_base = bridge
- d->config[0x0e] = 0x00; // header_type
-
- d->config[0x3d] = 0x01; // interrupt on pin 1
-
- dbdma_mem_index = cpu_register_io_memory(0, dbdma_read, dbdma_write, NULL);
-
- pci_register_io_region(d, 0, 0x80000,
- PCI_ADDRESS_SPACE_MEM, macio_map);
-}
-
/* UniN device */
static void unin_writel (void *opaque, target_phys_addr_t addr, uint32_t value)
{
@@ -210,159 +47,83 @@
&unin_readl,
};
-/* temporary frame buffer OSI calls for the video.x driver. The right
- solution is to modify the driver to use VGA PCI I/Os */
-/* XXX: to be removed. This is no way related to emulation */
-static int vga_osi_call (CPUState *env)
+/* PowerPC Mac99 hardware initialisation */
+static void ppc_core99_init (int ram_size, int vga_ram_size, int boot_device,
+ DisplayState *ds, const char **fd_filename,
+ int snapshot,
+ const char *kernel_filename,
+ const char *kernel_cmdline,
+ const char *initrd_filename,
+ const char *cpu_model)
{
- static int vga_vbl_enabled;
- int linesize;
-
- // printf("osi_call R5=%d\n", env->gpr[5]);
-
- /* same handler as PearPC, coming from the original MOL video
- driver. */
- switch(env->gpr[5]) {
- case 4:
- break;
- case 28: /* set_vmode */
- if (env->gpr[6] != 1 || env->gpr[7] != 0)
- env->gpr[3] = 1;
- else
- env->gpr[3] = 0;
- break;
- case 29: /* get_vmode_info */
- if (env->gpr[6] != 0) {
- if (env->gpr[6] != 1 || env->gpr[7] != 0) {
- env->gpr[3] = 1;
- break;
- }
- }
- env->gpr[3] = 0;
- env->gpr[4] = (1 << 16) | 1; /* num_vmodes, cur_vmode */
- env->gpr[5] = (1 << 16) | 0; /* num_depths, cur_depth_mode */
- env->gpr[6] = (graphic_width << 16) | graphic_height; /* w, h */
- env->gpr[7] = 85 << 16; /* refresh rate */
- env->gpr[8] = (graphic_depth + 7) & ~7; /* depth (round to byte) */
- linesize = ((graphic_depth + 7) >> 3) * graphic_width;
- linesize = (linesize + 3) & ~3;
- env->gpr[9] = (linesize << 16) | 0; /* row_bytes, offset */
- break;
- case 31: /* set_video power */
- env->gpr[3] = 0;
- break;
- case 39: /* video_ctrl */
- if (env->gpr[6] == 0 || env->gpr[6] == 1)
- vga_vbl_enabled = env->gpr[6];
- env->gpr[3] = 0;
- break;
- case 47:
- break;
- case 59: /* set_color */
- /* R6 = index, R7 = RGB */
- env->gpr[3] = 0;
- break;
- case 64: /* get color */
- /* R6 = index */
- env->gpr[3] = 0;
- break;
- case 116: /* set hwcursor */
- /* R6 = x, R7 = y, R8 = visible, R9 = data */
- break;
- default:
- fprintf(stderr, "unsupported OSI call R5=" REGX "\n", env->gpr[5]);
- break;
- }
-
- return 1; /* osi_call handled */
-}
-
-static uint8_t nvram_chksum (const uint8_t *buf, int n)
-{
- int sum, i;
- sum = 0;
- for(i = 0; i < n; i++)
- sum += buf[i];
- return (sum & 0xff) + (sum >> 8);
-}
-
-/* set a free Mac OS NVRAM partition */
-void pmac_format_nvram_partition (uint8_t *buf, int len)
-{
- char partition_name[12] = "wwwwwwwwwwww";
-
- buf[0] = 0x7f; /* free partition magic */
- buf[1] = 0; /* checksum */
- buf[2] = len >> 8;
- buf[3] = len;
- memcpy(buf + 4, partition_name, 12);
- buf[1] = nvram_chksum(buf, 16);
-}
-
-/* PowerPC CHRP hardware initialisation */
-static void ppc_chrp_init (int ram_size, int vga_ram_size, int boot_device,
- DisplayState *ds, const char **fd_filename,
- int snapshot,
- const char *kernel_filename,
- const char *kernel_cmdline,
- const char *initrd_filename,
- const char *cpu_model,
- int is_heathrow)
-{
CPUState *env, *envs[MAX_CPUS];
char buf[1024];
qemu_irq *pic, **openpic_irqs;
- m48t59_t *nvram;
int unin_memory;
int linux_boot, i;
unsigned long bios_offset, vga_bios_offset;
uint32_t kernel_base, kernel_size, initrd_base, initrd_size;
ppc_def_t *def;
PCIBus *pci_bus;
- const char *arch_name;
+ nvram_t nvram;
+#if 0
+ MacIONVRAMState *nvr;
+ int nvram_mem_index;
+#endif
+ m48t59_t *m48t59;
int vga_bios_size, bios_size;
qemu_irq *dummy_irq;
+ int pic_mem_index, dbdma_mem_index, cuda_mem_index;
+ int ide_mem_index[2];
linux_boot = (kernel_filename != NULL);
/* init CPUs */
env = cpu_init();
- qemu_register_reset(&cpu_ppc_reset, env);
- register_savevm("cpu", 0, 3, cpu_save, cpu_load, env);
-
- /* Default CPU is a generic 74x/75x */
if (cpu_model == NULL)
- cpu_model = "750";
- /* XXX: CPU model (or PVR) should be provided on command line */
- // ppc_find_by_name("750gx", &def); // Linux boot OK
- // ppc_find_by_name("750fx", &def); // Linux boot OK
- /* Linux does not boot on 750cxe (and probably other 750cx based)
- * because it assumes it has 8 IBAT & DBAT pairs as it only have 4.
- */
+ cpu_model = "default";
ppc_find_by_name(cpu_model, &def);
if (def == NULL) {
cpu_abort(env, "Unable to find PowerPC CPU definition\n");
}
for (i = 0; i < smp_cpus; i++) {
cpu_ppc_register(env, def);
+ cpu_ppc_reset(env);
/* Set time-base frequency to 100 Mhz */
cpu_ppc_tb_init(env, 100UL * 1000UL * 1000UL);
+#if 0
env->osi_call = vga_osi_call;
+#endif
+ qemu_register_reset(&cpu_ppc_reset, env);
+ register_savevm("cpu", 0, 3, cpu_save, cpu_load, env);
envs[i] = env;
}
+ if (env->nip < 0xFFF80000) {
+ /* Special test for PowerPC 601:
+ * the boot vector is at 0xFFF00100, then we need a 1MB BIOS.
+ * But the NVRAM is located at 0xFFF04000...
+ */
+ cpu_abort(env, "Mac99 hardware can not handle 1 MB BIOS\n");
+ }
/* allocate RAM */
cpu_register_physical_memory(0, ram_size, IO_MEM_RAM);
/* allocate and load BIOS */
bios_offset = ram_size + vga_ram_size;
- snprintf(buf, sizeof(buf), "%s/%s", bios_dir, BIOS_FILENAME);
+ if (bios_name == NULL)
+ bios_name = BIOS_FILENAME;
+ snprintf(buf, sizeof(buf), "%s/%s", bios_dir, bios_name);
bios_size = load_image(buf, phys_ram_base + bios_offset);
if (bios_size < 0 || bios_size > BIOS_SIZE) {
cpu_abort(env, "qemu: could not load PowerPC bios '%s'\n", buf);
exit(1);
}
bios_size = (bios_size + 0xfff) & ~0xfff;
+ if (bios_size > 0x00080000) {
+ /* As the NVRAM is located at 0xFFF04000, we cannot use 1 MB BIOSes */
+ cpu_abort(env, "Mac99 hardware can not handle 1 MB BIOS\n");
+ }
cpu_register_physical_memory((uint32_t)(-bios_size),
bios_size, bios_offset | IO_MEM_ROM);
@@ -418,150 +179,113 @@
initrd_size = 0;
}
- if (is_heathrow) {
- isa_mem_base = 0x80000000;
+ isa_mem_base = 0x80000000;
- /* Register 2 MB of ISA IO space */
- isa_mmio_init(0xfe000000, 0x00200000);
+ /* Register 8 MB of ISA IO space */
+ isa_mmio_init(0xf2000000, 0x00800000);
- /* init basic PC hardware */
- if (PPC_INPUT(env) != PPC_FLAGS_INPUT_6xx) {
- cpu_abort(env, "Only 6xx bus is supported on heathrow machine\n");
+ /* UniN init */
+ unin_memory = cpu_register_io_memory(0, unin_read, unin_write, NULL);
+ cpu_register_physical_memory(0xf8000000, 0x00001000, unin_memory);
+
+ openpic_irqs = qemu_mallocz(smp_cpus * sizeof(qemu_irq *));
+ openpic_irqs[0] =
+ qemu_mallocz(smp_cpus * sizeof(qemu_irq) * OPENPIC_OUTPUT_NB);
+ for (i = 0; i < smp_cpus; i++) {
+ /* Mac99 IRQ connection between OpenPIC outputs pins
+ * and PowerPC input pins
+ */
+ switch (PPC_INPUT(env)) {
+ case PPC_FLAGS_INPUT_6xx:
+ openpic_irqs[i] = openpic_irqs[0] + (i * OPENPIC_OUTPUT_NB);
+ openpic_irqs[i][OPENPIC_OUTPUT_INT] =
+ ((qemu_irq *)env->irq_inputs)[PPC6xx_INPUT_INT];
+ openpic_irqs[i][OPENPIC_OUTPUT_CINT] =
+ ((qemu_irq *)env->irq_inputs)[PPC6xx_INPUT_INT];
+ openpic_irqs[i][OPENPIC_OUTPUT_MCK] =
+ ((qemu_irq *)env->irq_inputs)[PPC6xx_INPUT_MCP];
+ /* Not connected ? */
+ openpic_irqs[i][OPENPIC_OUTPUT_DEBUG] = NULL;
+ /* Check this */
+ openpic_irqs[i][OPENPIC_OUTPUT_RESET] =
+ ((qemu_irq *)env->irq_inputs)[PPC6xx_INPUT_HRESET];
+ break;
+#if defined(TARGET_PPC64)
+ case PPC_FLAGS_INPUT_970:
+ openpic_irqs[i] = openpic_irqs[0] + (i * OPENPIC_OUTPUT_NB);
+ openpic_irqs[i][OPENPIC_OUTPUT_INT] =
+ ((qemu_irq *)env->irq_inputs)[PPC970_INPUT_INT];
+ openpic_irqs[i][OPENPIC_OUTPUT_CINT] =
+ ((qemu_irq *)env->irq_inputs)[PPC970_INPUT_INT];
+ openpic_irqs[i][OPENPIC_OUTPUT_MCK] =
+ ((qemu_irq *)env->irq_inputs)[PPC970_INPUT_MCP];
+ /* Not connected ? */
+ openpic_irqs[i][OPENPIC_OUTPUT_DEBUG] = NULL;
+ /* Check this */
+ openpic_irqs[i][OPENPIC_OUTPUT_RESET] =
+ ((qemu_irq *)env->irq_inputs)[PPC970_INPUT_HRESET];
+ break;
+#endif /* defined(TARGET_PPC64) */
+ default:
+ cpu_abort(env, "Bus model not supported on mac99 machine\n");
exit(1);
}
- pic = heathrow_pic_init(&heathrow_pic_mem_index);
- pci_bus = pci_grackle_init(0xfec00000, pic);
- pci_vga_init(pci_bus, ds, phys_ram_base + ram_size,
- ram_size, vga_ram_size,
- vga_bios_offset, vga_bios_size);
+ }
+ pic = openpic_init(NULL, &pic_mem_index, smp_cpus, openpic_irqs, NULL);
+ pci_bus = pci_pmac_init(pic);
+ /* init basic PC hardware */
+ pci_vga_init(pci_bus, ds, phys_ram_base + ram_size,
+ ram_size, vga_ram_size,
+ vga_bios_offset, vga_bios_size);
+
+ /* XXX: suppress that */
+ dummy_irq = i8259_init(NULL);
- /* XXX: suppress that */
- dummy_irq = i8259_init(NULL);
-
- /* XXX: use Mac Serial port */
- serial_init(0x3f8, dummy_irq[4], serial_hds[0]);
-
- for(i = 0; i < nb_nics; i++) {
- if (!nd_table[i].model)
- nd_table[i].model = "ne2k_pci";
- pci_nic_init(pci_bus, &nd_table[i], -1);
- }
-
- pci_cmd646_ide_init(pci_bus, &bs_table[0], 0);
-
- /* cuda also initialize ADB */
- cuda_mem_index = cuda_init(pic[0x12]);
-
- adb_kbd_init(&adb_bus);
- adb_mouse_init(&adb_bus);
-
- {
- MacIONVRAMState *nvr;
- nvr = macio_nvram_init();
- pmac_format_nvram_partition(nvr->data, 0x2000);
- }
-
- macio_init(pci_bus, 0x0017);
-
- nvram = m48t59_init(dummy_irq[8], 0xFFF04000, 0x0074, NVRAM_SIZE, 59);
-
- arch_name = "HEATHROW";
- } else {
- isa_mem_base = 0x80000000;
-
- /* Register 8 MB of ISA IO space */
- isa_mmio_init(0xf2000000, 0x00800000);
-
- /* UniN init */
- unin_memory = cpu_register_io_memory(0, unin_read, unin_write, NULL);
- cpu_register_physical_memory(0xf8000000, 0x00001000, unin_memory);
-
- openpic_irqs = qemu_mallocz(smp_cpus * sizeof(qemu_irq *));
- openpic_irqs[0] =
- qemu_mallocz(smp_cpus * sizeof(qemu_irq) * OPENPIC_OUTPUT_NB);
- for (i = 0; i < smp_cpus; i++) {
- /* Mac99 IRQ connection between OpenPIC outputs pins
- * and PowerPC input pins
- */
- switch (PPC_INPUT(env)) {
- case PPC_FLAGS_INPUT_6xx:
- openpic_irqs[i] = openpic_irqs[0] + (i * OPENPIC_OUTPUT_NB);
- openpic_irqs[i][OPENPIC_OUTPUT_INT] =
- ((qemu_irq *)env->irq_inputs)[PPC6xx_INPUT_INT];
- openpic_irqs[i][OPENPIC_OUTPUT_CINT] =
- ((qemu_irq *)env->irq_inputs)[PPC6xx_INPUT_INT];
- openpic_irqs[i][OPENPIC_OUTPUT_MCK] =
- ((qemu_irq *)env->irq_inputs)[PPC6xx_INPUT_MCP];
- /* Not connected ? */
- openpic_irqs[i][OPENPIC_OUTPUT_DEBUG] = NULL;
- /* Check this */
- openpic_irqs[i][OPENPIC_OUTPUT_RESET] =
- ((qemu_irq *)env->irq_inputs)[PPC6xx_INPUT_HRESET];
- break;
- case PPC_FLAGS_INPUT_970:
- openpic_irqs[i] = openpic_irqs[0] + (i * OPENPIC_OUTPUT_NB);
- openpic_irqs[i][OPENPIC_OUTPUT_INT] =
- ((qemu_irq *)env->irq_inputs)[PPC970_INPUT_INT];
- openpic_irqs[i][OPENPIC_OUTPUT_CINT] =
- ((qemu_irq *)env->irq_inputs)[PPC970_INPUT_INT];
- openpic_irqs[i][OPENPIC_OUTPUT_MCK] =
- ((qemu_irq *)env->irq_inputs)[PPC970_INPUT_MCP];
- /* Not connected ? */
- openpic_irqs[i][OPENPIC_OUTPUT_DEBUG] = NULL;
- /* Check this */
- openpic_irqs[i][OPENPIC_OUTPUT_RESET] =
- ((qemu_irq *)env->irq_inputs)[PPC970_INPUT_HRESET];
- break;
- default:
- cpu_abort(env, "Bus model not supported on mac99 machine\n");
- exit(1);
- }
- }
- pic = openpic_init(NULL, &openpic_mem_index, smp_cpus,
- openpic_irqs, NULL);
- pci_bus = pci_pmac_init(pic);
- /* init basic PC hardware */
- pci_vga_init(pci_bus, ds, phys_ram_base + ram_size,
- ram_size, vga_ram_size,
- vga_bios_offset, vga_bios_size);
-
- /* XXX: suppress that */
- dummy_irq = i8259_init(NULL);
-
- /* XXX: use Mac Serial port */
- serial_init(0x3f8, dummy_irq[4], serial_hds[0]);
- for(i = 0; i < nb_nics; i++) {
- if (!nd_table[i].model)
- nd_table[i].model = "ne2k_pci";
- pci_nic_init(pci_bus, &nd_table[i], -1);
- }
+ /* XXX: use Mac Serial port */
+ serial_init(0x3f8, dummy_irq[4], serial_hds[0]);
+ for(i = 0; i < nb_nics; i++) {
+ if (!nd_table[i].model)
+ nd_table[i].model = "ne2k_pci";
+ pci_nic_init(pci_bus, &nd_table[i], -1);
+ }
#if 1
- ide0_mem_index = pmac_ide_init(&bs_table[0], pic[0x13]);
- ide1_mem_index = pmac_ide_init(&bs_table[2], pic[0x14]);
+ ide_mem_index[0] = pmac_ide_init(&bs_table[0], pic[0x13]);
+ ide_mem_index[1] = pmac_ide_init(&bs_table[2], pic[0x14]);
#else
- pci_cmd646_ide_init(pci_bus, &bs_table[0], 0);
+ pci_cmd646_ide_init(pci_bus, &bs_table[0], 0);
#endif
- /* cuda also initialize ADB */
- cuda_mem_index = cuda_init(pic[0x19]);
+ /* cuda also initialize ADB */
+ cuda_init(&cuda_mem_index, pic[0x19]);
+
+ adb_kbd_init(&adb_bus);
+ adb_mouse_init(&adb_bus);
- adb_kbd_init(&adb_bus);
- adb_mouse_init(&adb_bus);
+ dbdma_init(&dbdma_mem_index);
- macio_init(pci_bus, 0x0022);
+ macio_init(pci_bus, 0x0022, 0, pic_mem_index, dbdma_mem_index,
+ cuda_mem_index, -1, 2, ide_mem_index);
- nvram = m48t59_init(dummy_irq[8], 0xFFF04000, 0x0074, NVRAM_SIZE, 59);
-
- arch_name = "MAC99";
- }
-
if (usb_enabled) {
usb_ohci_init_pci(pci_bus, 3, -1);
}
if (graphic_depth != 15 && graphic_depth != 32 && graphic_depth != 8)
graphic_depth = 15;
-
- PPC_NVRAM_set_params(nvram, NVRAM_SIZE, arch_name, ram_size, boot_device,
+#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);
+ pmac_format_nvram_partition(nvr, 0x2000);
+ cpu_register_physical_memory(0xFFF04000, 0x20000, nvram_mem_index);
+ nvram.opaque = nvr;
+ nvram.read_fn = &macio_nvram_read;
+ nvram.write_fn = &macio_nvram_write;
+#else
+ m48t59 = m48t59_init(dummy_irq[8], 0xFFF04000, 0x0074, NVRAM_SIZE, 59);
+ nvram.opaque = m48t59;
+ nvram.read_fn = &m48t59_read;
+ nvram.write_fn = &m48t59_write;
+#endif
+ PPC_NVRAM_set_params(&nvram, NVRAM_SIZE, "MAC99", ram_size, boot_device,
kernel_base, kernel_size,
kernel_cmdline,
initrd_base, initrd_size,
@@ -572,44 +296,10 @@
/* Special port to get debug messages from Open-Firmware */
register_ioport_write(0x0F00, 4, 1, &PPC_debug_write, NULL);
-}
+ }
-static void ppc_core99_init (int ram_size, int vga_ram_size, int boot_device,
- DisplayState *ds, const char **fd_filename,
- int snapshot,
- const char *kernel_filename,
- const char *kernel_cmdline,
- const char *initrd_filename,
- const char *cpu_model)
-{
- ppc_chrp_init(ram_size, vga_ram_size, boot_device,
- ds, fd_filename, snapshot,
- kernel_filename, kernel_cmdline,
- initrd_filename, cpu_model, 0);
-}
-
-static void ppc_heathrow_init (int ram_size, int vga_ram_size, int boot_device,
- DisplayState *ds, const char **fd_filename,
- int snapshot,
- const char *kernel_filename,
- const char *kernel_cmdline,
- const char *initrd_filename,
- const char *cpu_model)
-{
- ppc_chrp_init(ram_size, vga_ram_size, boot_device,
- ds, fd_filename, snapshot,
- kernel_filename, kernel_cmdline,
- initrd_filename, cpu_model, 1);
-}
-
QEMUMachine core99_machine = {
"mac99",
"Mac99 based PowerMAC",
ppc_core99_init,
};
-
-QEMUMachine heathrow_machine = {
- "g3bw",
- "Heathrow based PowerMAC",
- ppc_heathrow_init,
-};
Added: trunk/src/host/qemu-neo1973/hw/ppc_mac.h
===================================================================
--- trunk/src/host/qemu-neo1973/hw/ppc_mac.h 2007-10-29 20:40:05 UTC (rev 3302)
+++ trunk/src/host/qemu-neo1973/hw/ppc_mac.h 2007-10-29 21:14:04 UTC (rev 3303)
@@ -0,0 +1,70 @@
+/*
+ * QEMU PowerMac emulation shared definitions and prototypes
+ *
+ * Copyright (c) 2004-2007 Fabrice Bellard
+ * Copyright (c) 2007 Jocelyn Mayer
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+#if !defined(__PPC_MAC_H__)
+#define __PPC_MAC_H__
+
+/* SMP is not enabled, for now */
+#define MAX_CPUS 1
+
+#define BIOS_FILENAME "ppc_rom.bin"
+#define VGABIOS_FILENAME "video.x"
+#define NVRAM_SIZE 0x2000
+
+#define KERNEL_LOAD_ADDR 0x01000000
+#define INITRD_LOAD_ADDR 0x01800000
+
+/* DBDMA */
+void dbdma_init (int *dbdma_mem_index);
+
+/* Cuda */
+void cuda_init (int *cuda_mem_index, qemu_irq irq);
+
+/* 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 nb_ide, int *ide_mem_index);
+
+/* NewWorld PowerMac IDE */
+int pmac_ide_init (BlockDriverState **hd_table, qemu_irq irq);
+
+/* Heathrow PIC */
+qemu_irq *heathrow_pic_init(int *pmem_index,
+ int nb_cpus, qemu_irq **irqs);
+
+/* Grackle PCI */
+PCIBus *pci_grackle_init(uint32_t base, qemu_irq *pic);
+
+/* UniNorth PCI */
+PCIBus *pci_pmac_init(qemu_irq *pic);
+
+/* Mac NVRAM */
+typedef struct MacIONVRAMState MacIONVRAMState;
+
+MacIONVRAMState *macio_nvram_init (int *mem_index);
+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);
+
+#endif /* !defined(__PPC_MAC_H__) */
Added: trunk/src/host/qemu-neo1973/hw/ppc_oldworld.c
===================================================================
--- trunk/src/host/qemu-neo1973/hw/ppc_oldworld.c 2007-10-29 20:40:05 UTC (rev 3302)
+++ trunk/src/host/qemu-neo1973/hw/ppc_oldworld.c 2007-10-29 21:14:04 UTC (rev 3303)
@@ -0,0 +1,309 @@
+/*
+ * QEMU OldWorld PowerMac (currently ~G3 B&W) hardware System Emulator
+ *
+ * Copyright (c) 2004-2007 Fabrice Bellard
+ * Copyright (c) 2007 Jocelyn Mayer
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+#include "vl.h"
+#include "ppc_mac.h"
+
+/* temporary frame buffer OSI calls for the video.x driver. The right
+ solution is to modify the driver to use VGA PCI I/Os */
+/* XXX: to be removed. This is no way related to emulation */
+static int vga_osi_call (CPUState *env)
+{
+ static int vga_vbl_enabled;
+ int linesize;
+
+ // printf("osi_call R5=%d\n", env->gpr[5]);
+
+ /* same handler as PearPC, coming from the original MOL video
+ driver. */
+ switch(env->gpr[5]) {
+ case 4:
+ break;
+ case 28: /* set_vmode */
+ if (env->gpr[6] != 1 || env->gpr[7] != 0)
+ env->gpr[3] = 1;
+ else
+ env->gpr[3] = 0;
+ break;
+ case 29: /* get_vmode_info */
+ if (env->gpr[6] != 0) {
+ if (env->gpr[6] != 1 || env->gpr[7] != 0) {
+ env->gpr[3] = 1;
+ break;
+ }
+ }
+ env->gpr[3] = 0;
+ env->gpr[4] = (1 << 16) | 1; /* num_vmodes, cur_vmode */
+ env->gpr[5] = (1 << 16) | 0; /* num_depths, cur_depth_mode */
+ env->gpr[6] = (graphic_width << 16) | graphic_height; /* w, h */
+ env->gpr[7] = 85 << 16; /* refresh rate */
+ env->gpr[8] = (graphic_depth + 7) & ~7; /* depth (round to byte) */
+ linesize = ((graphic_depth + 7) >> 3) * graphic_width;
+ linesize = (linesize + 3) & ~3;
+ env->gpr[9] = (linesize << 16) | 0; /* row_bytes, offset */
+ break;
+ case 31: /* set_video power */
+ env->gpr[3] = 0;
+ break;
+ case 39: /* video_ctrl */
+ if (env->gpr[6] == 0 || env->gpr[6] == 1)
+ vga_vbl_enabled = env->gpr[6];
+ env->gpr[3] = 0;
+ break;
+ case 47:
+ break;
+ case 59: /* set_color */
+ /* R6 = index, R7 = RGB */
+ env->gpr[3] = 0;
+ break;
+ case 64: /* get color */
+ /* R6 = index */
+ env->gpr[3] = 0;
+ break;
+ case 116: /* set hwcursor */
+ /* R6 = x, R7 = y, R8 = visible, R9 = data */
+ break;
+ default:
+ fprintf(stderr, "unsupported OSI call R5=" REGX "\n", env->gpr[5]);
+ break;
+ }
+
+ return 1; /* osi_call handled */
+}
+
+static void ppc_heathrow_init (int ram_size, int vga_ram_size, int boot_device,
+ DisplayState *ds, const char **fd_filename,
+ int snapshot,
+ const char *kernel_filename,
+ const char *kernel_cmdline,
+ const char *initrd_filename,
+ const char *cpu_model)
+{
+ CPUState *env, *envs[MAX_CPUS];
+ char buf[1024];
+ qemu_irq *pic, **heathrow_irqs;
+ nvram_t nvram;
+ m48t59_t *m48t59;
+ int linux_boot, i;
+ unsigned long bios_offset, vga_bios_offset;
+ uint32_t kernel_base, kernel_size, initrd_base, initrd_size;
+ ppc_def_t *def;
+ PCIBus *pci_bus;
+ MacIONVRAMState *nvr;
+ int vga_bios_size, bios_size;
+ qemu_irq *dummy_irq;
+ int pic_mem_index, nvram_mem_index, dbdma_mem_index, cuda_mem_index;
+
+ linux_boot = (kernel_filename != NULL);
+
+ /* init CPUs */
+ env = cpu_init();
+ if (cpu_model == NULL)
+ cpu_model = "default";
+ ppc_find_by_name(cpu_model, &def);
+ if (def == NULL) {
+ cpu_abort(env, "Unable to find PowerPC CPU definition\n");
+ }
+ for (i = 0; i < smp_cpus; i++) {
+ cpu_ppc_register(env, def);
+ cpu_ppc_reset(env);
+ /* Set time-base frequency to 100 Mhz */
+ cpu_ppc_tb_init(env, 100UL * 1000UL * 1000UL);
+ env->osi_call = vga_osi_call;
+ qemu_register_reset(&cpu_ppc_reset, env);
+ register_savevm("cpu", 0, 3, cpu_save, cpu_load, env);
+ envs[i] = env;
+ }
+ if (env->nip < 0xFFF80000) {
+ /* Special test for PowerPC 601:
+ * the boot vector is at 0xFFF00100, then we need a 1MB BIOS.
+ * But the NVRAM is located at 0xFFF04000...
+ */
+ cpu_abort(env, "G3BW Mac hardware can not handle 1 MB BIOS\n");
+ }
+
+ /* allocate RAM */
+ cpu_register_physical_memory(0, ram_size, IO_MEM_RAM);
+
+ /* allocate and load BIOS */
+ bios_offset = ram_size + vga_ram_size;
+ if (bios_name == NULL)
+ bios_name = BIOS_FILENAME;
+ snprintf(buf, sizeof(buf), "%s/%s", bios_dir, bios_name);
+ bios_size = load_image(buf, phys_ram_base + bios_offset);
+ if (bios_size < 0 || bios_size > BIOS_SIZE) {
+ cpu_abort(env, "qemu: could not load PowerPC bios '%s'\n", buf);
+ exit(1);
+ }
+ bios_size = (bios_size + 0xfff) & ~0xfff;
+ if (bios_size > 0x00080000) {
+ /* As the NVRAM is located at 0xFFF04000, we cannot use 1 MB BIOSes */
+ cpu_abort(env, "G3BW Mac hardware can not handle 1 MB BIOS\n");
+ }
+ cpu_register_physical_memory((uint32_t)(-bios_size),
+ bios_size, bios_offset | IO_MEM_ROM);
+
+ /* allocate and load VGA BIOS */
+ vga_bios_offset = bios_offset + bios_size;
+ snprintf(buf, sizeof(buf), "%s/%s", bios_dir, VGABIOS_FILENAME);
+ vga_bios_size = load_image(buf, phys_ram_base + vga_bios_offset + 8);
+ if (vga_bios_size < 0) {
+ /* if no bios is present, we can still work */
+ fprintf(stderr, "qemu: warning: could not load VGA bios '%s'\n", buf);
+ vga_bios_size = 0;
+ } else {
+ /* set a specific header (XXX: find real Apple format for NDRV
+ drivers) */
+ phys_ram_base[vga_bios_offset] = 'N';
+ phys_ram_base[vga_bios_offset + 1] = 'D';
+ phys_ram_base[vga_bios_offset + 2] = 'R';
+ phys_ram_base[vga_bios_offset + 3] = 'V';
+ cpu_to_be32w((uint32_t *)(phys_ram_base + vga_bios_offset + 4),
+ vga_bios_size);
+ vga_bios_size += 8;
+ }
+ vga_bios_size = (vga_bios_size + 0xfff) & ~0xfff;
+
+ if (linux_boot) {
+ kernel_base = KERNEL_LOAD_ADDR;
+ /* now we can load the kernel */
+ kernel_size = load_image(kernel_filename, phys_ram_base + kernel_base);
+ if (kernel_size < 0) {
+ cpu_abort(env, "qemu: could not load kernel '%s'\n",
+ kernel_filename);
+ exit(1);
+ }
+ /* load initrd */
+ if (initrd_filename) {
+ initrd_base = INITRD_LOAD_ADDR;
+ initrd_size = load_image(initrd_filename,
+ phys_ram_base + initrd_base);
+ if (initrd_size < 0) {
+ cpu_abort(env, "qemu: could not load initial ram disk '%s'\n",
+ initrd_filename);
+ exit(1);
+ }
+ } else {
+ initrd_base = 0;
+ initrd_size = 0;
+ }
+ boot_device = 'm';
+ } else {
+ kernel_base = 0;
+ kernel_size = 0;
+ initrd_base = 0;
+ initrd_size = 0;
+ }
+
+ isa_mem_base = 0x80000000;
+
+ /* Register 2 MB of ISA IO space */
+ isa_mmio_init(0xfe000000, 0x00200000);
+
+ /* XXX: we register only 1 output pin for heathrow PIC */
+ heathrow_irqs = qemu_mallocz(smp_cpus * sizeof(qemu_irq *));
+ heathrow_irqs[0] =
+ qemu_mallocz(smp_cpus * sizeof(qemu_irq) * 1);
+ /* Connect the heathrow PIC outputs to the 6xx bus */
+ for (i = 0; i < smp_cpus; i++) {
+ switch (PPC_INPUT(env)) {
+ case PPC_FLAGS_INPUT_6xx:
+ heathrow_irqs[i] = heathrow_irqs[0] + (i * 1);
+ heathrow_irqs[i][0] =
+ ((qemu_irq *)env->irq_inputs)[PPC6xx_INPUT_INT];
+ break;
+ default:
+ cpu_abort(env, "Bus model not supported on OldWorld Mac machine\n");
+ exit(1);
+ }
+ }
+
+ /* init basic PC hardware */
+ if (PPC_INPUT(env) != PPC_FLAGS_INPUT_6xx) {
+ cpu_abort(env, "Only 6xx bus is supported on heathrow machine\n");
+ exit(1);
+ }
+ pic = heathrow_pic_init(&pic_mem_index, 1, heathrow_irqs);
+ pci_bus = pci_grackle_init(0xfec00000, pic);
+ pci_vga_init(pci_bus, ds, phys_ram_base + ram_size,
+ ram_size, vga_ram_size,
+ vga_bios_offset, vga_bios_size);
+
+ /* XXX: suppress that */
+ dummy_irq = i8259_init(NULL);
+
+ /* XXX: use Mac Serial port */
+ serial_init(0x3f8, dummy_irq[4], serial_hds[0]);
+
+ for(i = 0; i < nb_nics; i++) {
+ if (!nd_table[i].model)
+ nd_table[i].model = "ne2k_pci";
+ pci_nic_init(pci_bus, &nd_table[i], -1);
+ }
+
+ pci_cmd646_ide_init(pci_bus, &bs_table[0], 0);
+
+ /* cuda also initialize ADB */
+ cuda_init(&cuda_mem_index, pic[0x12]);
+
+ adb_kbd_init(&adb_bus);
+ adb_mouse_init(&adb_bus);
+
+ nvr = macio_nvram_init(&nvram_mem_index);
+ 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);
+
+ if (usb_enabled) {
+ usb_ohci_init_pci(pci_bus, 3, -1);
+ }
+
+ if (graphic_depth != 15 && graphic_depth != 32 && graphic_depth != 8)
+ graphic_depth = 15;
+
+ m48t59 = m48t59_init(dummy_irq[8], 0xFFF04000, 0x0074, NVRAM_SIZE, 59);
+ nvram.opaque = m48t59;
+ nvram.read_fn = &m48t59_read;
+ nvram.write_fn = &m48t59_write;
+ PPC_NVRAM_set_params(&nvram, NVRAM_SIZE, "HEATHROW", ram_size, boot_device,
+ kernel_base, kernel_size,
+ kernel_cmdline,
+ initrd_base, initrd_size,
+ /* XXX: need an option to load a NVRAM image */
+ 0,
+ graphic_width, graphic_height, graphic_depth);
+ /* No PCI init: the BIOS will do it */
+
+ /* Special port to get debug messages from Open-Firmware */
+ register_ioport_write(0x0F00, 4, 1, &PPC_debug_write, NULL);
+}
+
+QEMUMachine heathrow_machine = {
+ "g3bw",
+ "Heathrow based PowerMAC",
+ ppc_heathrow_init,
+};
Modified: trunk/src/host/qemu-neo1973/hw/ppc_prep.c
===================================================================
--- trunk/src/host/qemu-neo1973/hw/ppc_prep.c 2007-10-29 20:40:05 UTC (rev 3302)
+++ trunk/src/host/qemu-neo1973/hw/ppc_prep.c 2007-10-29 21:14:04 UTC (rev 3303)
@@ -26,6 +26,9 @@
//#define HARD_DEBUG_PPC_IO
//#define DEBUG_PPC_IO
+/* SMP is not enabled, for now */
+#define MAX_CPUS 1
+
#define BIOS_FILENAME "ppc_rom.bin"
#define KERNEL_LOAD_ADDR 0x01000000
#define INITRD_LOAD_ADDR 0x01800000
@@ -104,7 +107,7 @@
// printf("%s: 0x%08x => 0x%08x\n", __func__, addr, value);
}
-static inline uint32_t _PPC_intack_read (target_phys_addr_t addr)
+static always_inline uint32_t _PPC_intack_read (target_phys_addr_t addr)
{
uint32_t retval = 0;
@@ -249,6 +252,7 @@
/* Fake super-io ports for PREP platform (Intel 82378ZB) */
typedef struct sysctrl_t {
+ qemu_irq reset_irq;
m48t59_t *nvram;
uint8_t state;
uint8_t syscontrol;
@@ -290,7 +294,9 @@
/* Special port 92 */
/* Check soft reset asked */
if (val & 0x01) {
- // cpu_interrupt(first_cpu, PPC_INTERRUPT_RESET);
+ qemu_irq_raise(sysctrl->reset_irq);
+ } else {
+ qemu_irq_lower(sysctrl->reset_irq);
}
/* Check LE mode */
if (val & 0x02) {
@@ -409,8 +415,9 @@
return retval;
}
-static inline target_phys_addr_t prep_IO_address (sysctrl_t *sysctrl,
- target_phys_addr_t addr)
+static always_inline target_phys_addr_t prep_IO_address (sysctrl_t *sysctrl,
+ target_phys_addr_t
+ addr)
{
if (sysctrl->contiguous_map == 0) {
/* 64 KB contiguous space for IOs */
@@ -521,9 +528,10 @@
const char *initrd_filename,
const char *cpu_model)
{
- CPUState *env;
+ CPUState *env, *envs[MAX_CPUS];
char buf[1024];
- m48t59_t *nvram;
+ nvram_t nvram;
+ m48t59_t *m48t59;
int PPC_io_memory;
int linux_boot, i, nb_nics1, bios_size;
unsigned long bios_offset;
@@ -539,33 +547,39 @@
linux_boot = (kernel_filename != NULL);
/* init CPUs */
-
env = cpu_init();
- qemu_register_reset(&cpu_ppc_reset, env);
- register_savevm("cpu", 0, 3, cpu_save, cpu_load, env);
-
- /* Default CPU is a 604 */
if (cpu_model == NULL)
- cpu_model = "604";
+ cpu_model = "default";
ppc_find_by_name(cpu_model, &def);
if (def == NULL) {
cpu_abort(env, "Unable to find PowerPC CPU definition\n");
}
- cpu_ppc_register(env, def);
- /* Set time-base frequency to 100 Mhz */
- cpu_ppc_tb_init(env, 100UL * 1000UL * 1000UL);
+ for (i = 0; i < smp_cpus; i++) {
+ cpu_ppc_register(env, def);
+ cpu_ppc_reset(env);
+ /* Set time-base frequency to 100 Mhz */
+ cpu_ppc_tb_init(env, 100UL * 1000UL * 1000UL);
+ qemu_register_reset(&cpu_ppc_reset, env);
+ register_savevm("cpu", 0, 3, cpu_save, cpu_load, env);
+ envs[i] = env;
+ }
/* allocate RAM */
cpu_register_physical_memory(0, ram_size, IO_MEM_RAM);
/* allocate and load BIOS */
bios_offset = ram_size + vga_ram_size;
- snprintf(buf, sizeof(buf), "%s/%s", bios_dir, BIOS_FILENAME);
+ if (bios_name == NULL)
+ bios_name = BIOS_FILENAME;
+ snprintf(buf, sizeof(buf), "%s/%s", bios_dir, bios_name);
bios_size = load_image(buf, phys_ram_base + bios_offset);
if (bios_size < 0 || bios_size > BIOS_SIZE) {
cpu_abort(env, "qemu: could not load PPC PREP bios '%s'\n", buf);
exit(1);
}
+ if (env->nip < 0xFFF80000 && bios_size < 0x00100000) {
+ cpu_abort(env, "PowerPC 601 / 620 / 970 need a 1MB BIOS\n");
+ }
bios_size = (bios_size + 0xfff) & ~0xfff;
cpu_register_physical_memory((uint32_t)(-bios_size),
bios_size, bios_offset | IO_MEM_ROM);
@@ -626,16 +640,11 @@
if (nb_nics1 > NE2000_NB_MAX)
nb_nics1 = NE2000_NB_MAX;
for(i = 0; i < nb_nics1; i++) {
- if (nd_table[0].model == NULL
- || strcmp(nd_table[0].model, "ne2k_isa") == 0) {
+ if (nd_table[i].model == NULL
+ || strcmp(nd_table[i].model, "ne2k_isa") == 0) {
isa_ne2000_init(ne2000_io[i], i8259[ne2000_irq[i]], &nd_table[i]);
- } else if (strcmp(nd_table[0].model, "?") == 0) {
- fprintf(stderr, "qemu: Supported NICs: ne2k_isa\n");
- exit (1);
} else {
- /* Why ? */
- cpu_abort(env, "qemu: Unsupported NIC: %s\n", nd_table[0].model);
- exit (1);
+ pci_nic_init(pci_bus, &nd_table[i], -1);
}
}
@@ -654,6 +663,7 @@
register_ioport_read(0x61, 1, 1, speaker_ioport_read, NULL);
register_ioport_write(0x61, 1, 1, speaker_ioport_write, NULL);
/* Register fake IO ports for PREP */
+ sysctrl->reset_irq = first_cpu->irq_inputs[PPC6xx_INPUT_HRESET];
register_ioport_read(0x398, 2, 1, &PREP_io_read, sysctrl);
register_ioport_write(0x398, 2, 1, &PREP_io_write, sysctrl);
/* System control ports */
@@ -676,13 +686,16 @@
usb_ohci_init_pci(pci_bus, 3, -1);
}
- nvram = m48t59_init(i8259[8], 0, 0x0074, NVRAM_SIZE, 59);
- if (nvram == NULL)
+ m48t59 = m48t59_init(i8259[8], 0, 0x0074, NVRAM_SIZE, 59);
+ if (m48t59 == NULL)
return;
- sysctrl->nvram = nvram;
+ sysctrl->nvram = m48t59;
/* Initialise NVRAM */
- PPC_NVRAM_set_params(nvram, NVRAM_SIZE, "PREP", ram_size, boot_device,
+ nvram.opaque = m48t59;
+ nvram.read_fn = &m48t59_read;
+ nvram.write_fn = &m48t59_write;
+ PPC_NVRAM_set_params(&nvram, NVRAM_SIZE, "PREP", ram_size, boot_device,
kernel_base, kernel_size,
kernel_cmdline,
initrd_base, initrd_size,
Modified: trunk/src/host/qemu-neo1973/hw/prep_pci.c
===================================================================
--- trunk/src/host/qemu-neo1973/hw/prep_pci.c 2007-10-29 20:40:05 UTC (rev 3302)
+++ trunk/src/host/qemu-neo1973/hw/prep_pci.c 2007-10-29 21:14:04 UTC (rev 3303)
@@ -117,7 +117,6 @@
&PPC_PCIIO_readl,
};
-/* Don't know if this matches real hardware, but it agrees with OHW. */
static int prep_map_irq(PCIDevice *pci_dev, int irq_num)
{
return (irq_num + (pci_dev->devfn >> 3)) & 1;
@@ -125,7 +124,7 @@
static void prep_set_irq(qemu_irq *pic, int irq_num, int level)
{
- qemu_set_irq(pic[irq_num ? 11 : 9], level);
+ qemu_set_irq(pic[(irq_num & 1) ? 11 : 9] , level);
}
PCIBus *pci_prep_init(qemu_irq *pic)
@@ -135,7 +134,7 @@
int PPC_io_memory;
s = qemu_mallocz(sizeof(PREPPCIState));
- s->bus = pci_register_bus(prep_set_irq, prep_map_irq, pic, 0, 2);
+ s->bus = pci_register_bus(prep_set_irq, prep_map_irq, pic, 0, 4);
register_ioport_write(0xcf8, 4, 4, pci_prep_addr_writel, s);
register_ioport_read(0xcf8, 4, 4, pci_prep_addr_readl, s);
Modified: trunk/src/host/qemu-neo1973/hw/pxa.h
===================================================================
--- trunk/src/host/qemu-neo1973/hw/pxa.h 2007-10-29 20:40:05 UTC (rev 3302)
+++ trunk/src/host/qemu-neo1973/hw/pxa.h 2007-10-29 21:14:04 UTC (rev 3303)
@@ -4,7 +4,7 @@
* Copyright (c) 2006 Openedhand Ltd.
* Written by Andrzej Zaborowski <balrog at zabor.org>
*
- * This code is licenced under the GPL.
+ * This code is licenced under the GNU GPL v2.
*/
#ifndef PXA_H
# define PXA_H "pxa.h"
Modified: trunk/src/host/qemu-neo1973/hw/pxa2xx_gpio.c
===================================================================
--- trunk/src/host/qemu-neo1973/hw/pxa2xx_gpio.c 2007-10-29 20:40:05 UTC (rev 3302)
+++ trunk/src/host/qemu-neo1973/hw/pxa2xx_gpio.c 2007-10-29 21:14:04 UTC (rev 3303)
@@ -24,6 +24,7 @@
uint32_t rising[PXA2XX_GPIO_BANKS];
uint32_t falling[PXA2XX_GPIO_BANKS];
uint32_t status[PXA2XX_GPIO_BANKS];
+ uint32_t gpsr[PXA2XX_GPIO_BANKS];
uint32_t gafr[PXA2XX_GPIO_BANKS * 2];
uint32_t prev_level[PXA2XX_GPIO_BANKS];
@@ -152,6 +153,11 @@
case GPDR: /* GPIO Pin-Direction registers */
return s->dir[bank];
+ case GPSR: /* GPIO Pin-Output Set registers */
+ printf("%s: Read from a write-only register " REG_FMT "\n",
+ __FUNCTION__, offset);
+ return s->gpsr[bank]; /* Return last written value. */
+
case GRER: /* GPIO Rising-Edge Detect Enable registers */
return s->rising[bank];
@@ -201,6 +207,7 @@
case GPSR: /* GPIO Pin-Output Set registers */
s->olevel[bank] |= value;
pxa2xx_gpio_handler_update(s);
+ s->gpsr[bank] = value;
break;
case GPCR: /* GPIO Pin-Output Clear registers */
Added: trunk/src/host/qemu-neo1973/hw/r2d.c
===================================================================
--- trunk/src/host/qemu-neo1973/hw/r2d.c 2007-10-29 20:40:05 UTC (rev 3302)
+++ trunk/src/host/qemu-neo1973/hw/r2d.c 2007-10-29 21:14:04 UTC (rev 3303)
@@ -0,0 +1,63 @@
+/*
+ * Renesas SH7751R R2D-PLUS emulation
+ *
+ * Copyright (c) 2007 Magnus Damm
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+
+#include "vl.h"
+
+#define SDRAM_BASE 0x0c000000 /* Physical location of SDRAM: Area 3 */
+#define SDRAM_SIZE 0x04000000
+
+void r2d_init(int ram_size, int vga_ram_size, int boot_device,
+ DisplayState * ds, const char **fd_filename, int snapshot,
+ const char *kernel_filename, const char *kernel_cmdline,
+ const char *initrd_filename, const char *cpu_model)
+{
+ CPUState *env;
+ struct SH7750State *s;
+
+ env = cpu_init();
+
+ /* Allocate memory space */
+ cpu_register_physical_memory(SDRAM_BASE, SDRAM_SIZE, 0);
+ /* Register peripherals */
+ s = sh7750_init(env);
+ /* Todo: register on board registers */
+ {
+ int kernel_size;
+
+ kernel_size = load_image(kernel_filename, phys_ram_base);
+
+ if (kernel_size < 0) {
+ fprintf(stderr, "qemu: could not load kernel '%s'\n", kernel_filename);
+ exit(1);
+ }
+
+ env->pc = SDRAM_BASE | 0xa0000000; /* Start from P2 area */
+ }
+}
+
+QEMUMachine r2d_machine = {
+ "r2d",
+ "r2d-plus board",
+ r2d_init
+};
Modified: trunk/src/host/qemu-neo1973/hw/sh7750.c
===================================================================
--- trunk/src/host/qemu-neo1973/hw/sh7750.c 2007-10-29 20:40:05 UTC (rev 3302)
+++ trunk/src/host/qemu-neo1973/hw/sh7750.c 2007-10-29 21:14:04 UTC (rev 3303)
@@ -1,6 +1,7 @@
/*
* SH7750 device
*
+ * Copyright (c) 2007 Magnus Damm
* Copyright (c) 2005 Samuel Tardieu
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
@@ -26,14 +27,8 @@
#include "vl.h"
#include "sh7750_regs.h"
#include "sh7750_regnames.h"
+#include "sh_intc.h"
-typedef struct {
- uint8_t data[16];
- uint8_t length; /* Number of characters in the FIFO */
- uint8_t write_idx; /* Index of first character to write */
- uint8_t read_idx; /* Index of first character to read */
-} fifo;
-
#define NB_DEVICES 4
typedef struct SH7750State {
@@ -43,34 +38,6 @@
uint32_t periph_freq;
/* SDRAM controller */
uint16_t rfcr;
- /* First serial port */
- CharDriverState *serial1;
- uint8_t scscr1;
- uint8_t scsmr1;
- uint8_t scbrr1;
- uint8_t scssr1;
- uint8_t scssr1_read;
- uint8_t sctsr1;
- uint8_t sctsr1_loaded;
- uint8_t sctdr1;
- uint8_t scrdr1;
- /* Second serial port */
- CharDriverState *serial2;
- uint16_t sclsr2;
- uint16_t scscr2;
- uint16_t scfcr2;
- uint16_t scfsr2;
- uint16_t scsmr2;
- uint8_t scbrr2;
- fifo serial2_receive_fifo;
- fifo serial2_transmit_fifo;
- /* Timers */
- uint8_t tstr;
- /* Timer 0 */
- QEMUTimer *timer0;
- uint16_t tcr0;
- uint32_t tcor0;
- uint32_t tcnt0;
/* IO ports */
uint16_t gpioic;
uint32_t pctra;
@@ -86,345 +53,16 @@
uint16_t periph_pdtrb; /* Imposed by the peripherals */
uint16_t periph_portdirb; /* Direction seen from the peripherals */
sh7750_io_device *devices[NB_DEVICES]; /* External peripherals */
+
+ uint16_t icr;
/* Cache */
uint32_t ccr;
+
+ struct intc_desc intc;
} SH7750State;
-/**********************************************************************
- Timers
-**********************************************************************/
-/* XXXXX At this time, timer0 works in underflow only mode, that is
- the value of tcnt0 is read at alarm computation time and cannot
- be read back by the guest OS */
-
-static void start_timer0(SH7750State * s)
-{
- uint64_t now, next, prescaler;
-
- if ((s->tcr0 & 6) == 6) {
- fprintf(stderr, "rtc clock for timer 0 not supported\n");
- assert(0);
- }
-
- if ((s->tcr0 & 7) == 5) {
- fprintf(stderr, "timer 0 configuration not supported\n");
- assert(0);
- }
-
- if ((s->tcr0 & 4) == 4)
- prescaler = 1024;
- else
- prescaler = 4 << (s->tcr0 & 3);
-
- now = qemu_get_clock(vm_clock);
- /* XXXXX */
- next =
- now + muldiv64(prescaler * s->tcnt0, ticks_per_sec,
- s->periph_freq);
- if (next == now)
- next = now + 1;
- fprintf(stderr, "now=%016" PRIx64 ", next=%016" PRIx64 "\n", now, next);
- fprintf(stderr, "timer will underflow in %f seconds\n",
- (float) (next - now) / (float) ticks_per_sec);
-
- qemu_mod_timer(s->timer0, next);
-}
-
-static void timer_start_changed(SH7750State * s)
-{
- if (s->tstr & SH7750_TSTR_STR0) {
- start_timer0(s);
- } else {
- fprintf(stderr, "timer 0 is stopped\n");
- qemu_del_timer(s->timer0);
- }
-}
-
-static void timer0_cb(void *opaque)
-{
- SH7750State *s = opaque;
-
- s->tcnt0 = (uint32_t) 0; /* XXXXX */
- if (--s->tcnt0 == (uint32_t) - 1) {
- fprintf(stderr, "timer 0 underflow\n");
- s->tcnt0 = s->tcor0;
- s->tcr0 |= SH7750_TCR_UNF;
- if (s->tcr0 & SH7750_TCR_UNIE) {
- fprintf(stderr,
- "interrupt generation for timer 0 not supported\n");
- assert(0);
- }
- }
- start_timer0(s);
-}
-
-static void init_timers(SH7750State * s)
-{
- s->tcor0 = 0xffffffff;
- s->tcnt0 = 0xffffffff;
- s->timer0 = qemu_new_timer(vm_clock, &timer0_cb, s);
-}
-
/**********************************************************************
- First serial port
-**********************************************************************/
-
-static int serial1_can_receive(void *opaque)
-{
- SH7750State *s = opaque;
-
- return s->scscr1 & SH7750_SCSCR_RE;
-}
-
-static void serial1_receive_char(SH7750State * s, uint8_t c)
-{
- if (s->scssr1 & SH7750_SCSSR1_RDRF) {
- s->scssr1 |= SH7750_SCSSR1_ORER;
- return;
- }
-
- s->scrdr1 = c;
- s->scssr1 |= SH7750_SCSSR1_RDRF;
-}
-
-static void serial1_receive(void *opaque, const uint8_t * buf, int size)
-{
- SH7750State *s = opaque;
- int i;
-
- for (i = 0; i < size; i++) {
- serial1_receive_char(s, buf[i]);
- }
-}
-
-static void serial1_event(void *opaque, int event)
-{
- assert(0);
-}
-
-static void serial1_maybe_send(SH7750State * s)
-{
- uint8_t c;
-
- if (s->scssr1 & SH7750_SCSSR1_TDRE)
- return;
- c = s->sctdr1;
- s->scssr1 |= SH7750_SCSSR1_TDRE | SH7750_SCSSR1_TEND;
- if (s->scscr1 & SH7750_SCSCR_TIE) {
- fprintf(stderr, "interrupts for serial port 1 not implemented\n");
- assert(0);
- }
- /* XXXXX Check for errors in write */
- qemu_chr_write(s->serial1, &c, 1);
-}
-
-static void serial1_change_scssr1(SH7750State * s, uint8_t mem_value)
-{
- uint8_t new_flags;
-
- /* If transmit disable, TDRE and TEND stays up */
- if ((s->scscr1 & SH7750_SCSCR_TE) == 0) {
- mem_value |= SH7750_SCSSR1_TDRE | SH7750_SCSSR1_TEND;
- }
-
- /* Only clear bits which have been read before and do not set any bit
- in the flags */
- new_flags = s->scssr1 & ~s->scssr1_read; /* Preserve unread flags */
- new_flags &= mem_value | ~s->scssr1_read; /* Clear read flags */
-
- s->scssr1 = (new_flags & 0xf8) | (mem_value & 1);
- s->scssr1_read &= mem_value;
-
- /* If TDRE has been cleared, TEND will also be cleared */
- if ((s->scssr1 & SH7750_SCSSR1_TDRE) == 0) {
- s->scssr1 &= ~SH7750_SCSSR1_TEND;
- }
-
- /* Check for transmission to start */
- serial1_maybe_send(s);
-}
-
-static void serial1_update_parameters(SH7750State * s)
-{
- QEMUSerialSetParams ssp;
-
- if (s->scsmr1 & SH7750_SCSMR_CHR_7)
- ssp.data_bits = 7;
- else
- ssp.data_bits = 8;
- if (s->scsmr1 & SH7750_SCSMR_PE) {
- if (s->scsmr1 & SH7750_SCSMR_PM_ODD)
- ssp.parity = 'O';
- else
- ssp.parity = 'E';
- } else
- ssp.parity = 'N';
- if (s->scsmr1 & SH7750_SCSMR_STOP_2)
- ssp.stop_bits = 2;
- else
- ssp.stop_bits = 1;
- fprintf(stderr, "SCSMR1=%04x SCBRR1=%02x\n", s->scsmr1, s->scbrr1);
- ssp.speed = s->periph_freq /
- (32 * s->scbrr1 * (1 << (2 * (s->scsmr1 & 3)))) - 1;
- fprintf(stderr, "data bits=%d, stop bits=%d, parity=%c, speed=%d\n",
- ssp.data_bits, ssp.stop_bits, ssp.parity, ssp.speed);
- qemu_chr_ioctl(s->serial1, CHR_IOCTL_SERIAL_SET_PARAMS, &ssp);
-}
-
-static void scscr1_changed(SH7750State * s)
-{
- if (s->scscr1 & (SH7750_SCSCR_TE | SH7750_SCSCR_RE)) {
- if (!s->serial1) {
- fprintf(stderr, "serial port 1 not bound to anything\n");
- assert(0);
- }
- serial1_update_parameters(s);
- }
- if ((s->scscr1 & SH7750_SCSCR_RE) == 0) {
- s->scssr1 |= SH7750_SCSSR1_TDRE;
- }
-}
-
-static void init_serial1(SH7750State * s, int serial_nb)
-{
- CharDriverState *chr;
-
- s->scssr1 = 0x84;
- chr = serial_hds[serial_nb];
- if (!chr) {
- fprintf(stderr,
- "no serial port associated to SH7750 first serial port\n");
- return;
- }
-
- s->serial1 = chr;
- qemu_chr_add_handlers(chr, serial1_can_receive,
- serial1_receive, serial1_event, s);
-}
-
-/**********************************************************************
- Second serial port
-**********************************************************************/
-
-static int serial2_can_receive(void *opaque)
-{
- SH7750State *s = opaque;
- static uint8_t max_fifo_size[] = { 15, 1, 4, 6, 8, 10, 12, 14 };
-
- return s->serial2_receive_fifo.length <
- max_fifo_size[(s->scfcr2 >> 9) & 7];
-}
-
-static void serial2_adjust_receive_flags(SH7750State * s)
-{
- static uint8_t max_fifo_size[] = { 1, 4, 8, 14 };
-
- /* XXXXX Add interrupt generation */
- if (s->serial2_receive_fifo.length >=
- max_fifo_size[(s->scfcr2 >> 7) & 3]) {
- s->scfsr2 |= SH7750_SCFSR2_RDF;
- s->scfsr2 &= ~SH7750_SCFSR2_DR;
- } else {
- s->scfsr2 &= ~SH7750_SCFSR2_RDF;
- if (s->serial2_receive_fifo.length > 0)
- s->scfsr2 |= SH7750_SCFSR2_DR;
- else
- s->scfsr2 &= ~SH7750_SCFSR2_DR;
- }
-}
-
-static void serial2_append_char(SH7750State * s, uint8_t c)
-{
- if (s->serial2_receive_fifo.length == 16) {
- /* Overflow */
- s->sclsr2 |= SH7750_SCLSR2_ORER;
- return;
- }
-
- s->serial2_receive_fifo.data[s->serial2_receive_fifo.write_idx++] = c;
- s->serial2_receive_fifo.length++;
- serial2_adjust_receive_flags(s);
-}
-
-static void serial2_receive(void *opaque, const uint8_t * buf, int size)
-{
- SH7750State *s = opaque;
- int i;
-
- for (i = 0; i < size; i++)
- serial2_append_char(s, buf[i]);
-}
-
-static void serial2_event(void *opaque, int event)
-{
- /* XXXXX */
- assert(0);
-}
-
-static void serial2_update_parameters(SH7750State * s)
-{
- QEMUSerialSetParams ssp;
-
- if (s->scsmr2 & SH7750_SCSMR_CHR_7)
- ssp.data_bits = 7;
- else
- ssp.data_bits = 8;
- if (s->scsmr2 & SH7750_SCSMR_PE) {
- if (s->scsmr2 & SH7750_SCSMR_PM_ODD)
- ssp.parity = 'O';
- else
- ssp.parity = 'E';
- } else
- ssp.parity = 'N';
- if (s->scsmr2 & SH7750_SCSMR_STOP_2)
- ssp.stop_bits = 2;
- else
- ssp.stop_bits = 1;
- fprintf(stderr, "SCSMR2=%04x SCBRR2=%02x\n", s->scsmr2, s->scbrr2);
- ssp.speed = s->periph_freq /
- (32 * s->scbrr2 * (1 << (2 * (s->scsmr2 & 3)))) - 1;
- fprintf(stderr, "data bits=%d, stop bits=%d, parity=%c, speed=%d\n",
- ssp.data_bits, ssp.stop_bits, ssp.parity, ssp.speed);
- qemu_chr_ioctl(s->serial2, CHR_IOCTL_SERIAL_SET_PARAMS, &ssp);
-}
-
-static void scscr2_changed(SH7750State * s)
-{
- if (s->scscr2 & (SH7750_SCSCR_TE | SH7750_SCSCR_RE)) {
- if (!s->serial2) {
- fprintf(stderr, "serial port 2 not bound to anything\n");
- assert(0);
- }
- serial2_update_parameters(s);
- }
-}
-
-static void init_serial2(SH7750State * s, int serial_nb)
-{
- CharDriverState *chr;
-
- s->scfsr2 = 0x0060;
-
- chr = serial_hds[serial_nb];
- if (!chr) {
- fprintf(stderr,
- "no serial port associated to SH7750 second serial port\n");
- return;
- }
-
- s->serial2 = chr;
- qemu_chr_add_handlers(chr, serial2_can_receive,
- serial2_receive, serial1_event, s);
-}
-
-static void init_serial_ports(SH7750State * s)
-{
- init_serial1(s, 0);
- init_serial2(s, 1);
-}
-
-/**********************************************************************
I/O ports
**********************************************************************/
@@ -554,17 +192,7 @@
static uint32_t sh7750_mem_readb(void *opaque, target_phys_addr_t addr)
{
- SH7750State *s = opaque;
- uint8_t r;
-
switch (addr) {
- case SH7750_SCSSR1_A7:
- r = s->scssr1;
- s->scssr1_read |= r;
- return s->scssr1;
- case SH7750_SCRDR1_A7:
- s->scssr1 &= ~SH7750_SCSSR1_RDRF;
- return s->scrdr1;
default:
error_access("byte read", addr);
assert(0);
@@ -574,26 +202,20 @@
static uint32_t sh7750_mem_readw(void *opaque, target_phys_addr_t addr)
{
SH7750State *s = opaque;
- uint16_t r;
switch (addr) {
+ case SH7750_FRQCR_A7:
+ return 0;
case SH7750_RFCR_A7:
fprintf(stderr,
"Read access to refresh count register, incrementing\n");
return s->rfcr++;
- case SH7750_TCR0_A7:
- return s->tcr0;
- case SH7750_SCLSR2_A7:
- /* Read and clear overflow bit */
- r = s->sclsr2;
- s->sclsr2 = 0;
- return r;
- case SH7750_SCSFR2_A7:
- return s->scfsr2;
case SH7750_PDTRA_A7:
return porta_lines(s);
case SH7750_PDTRB_A7:
return portb_lines(s);
+ case 0x1fd00000:
+ return s->icr;
default:
error_access("word read", addr);
assert(0);
@@ -638,38 +260,12 @@
static void sh7750_mem_writeb(void *opaque, target_phys_addr_t addr,
uint32_t mem_value)
{
- SH7750State *s = opaque;
-
switch (addr) {
/* PRECHARGE ? XXXXX */
case SH7750_PRECHARGE0_A7:
case SH7750_PRECHARGE1_A7:
ignore_access("byte write", addr);
return;
- case SH7750_SCBRR2_A7:
- s->scbrr2 = mem_value;
- return;
- case SH7750_TSTR_A7:
- s->tstr = mem_value;
- timer_start_changed(s);
- return;
- case SH7750_SCSCR1_A7:
- s->scscr1 = mem_value;
- scscr1_changed(s);
- return;
- case SH7750_SCSMR1_A7:
- s->scsmr1 = mem_value;
- return;
- case SH7750_SCBRR1_A7:
- s->scbrr1 = mem_value;
- return;
- case SH7750_SCTDR1_A7:
- s->scssr1 &= ~SH7750_SCSSR1_TEND;
- s->sctdr1 = mem_value;
- return;
- case SH7750_SCSSR1_A7:
- serial1_change_scssr1(s, mem_value);
- return;
default:
error_access("byte write", addr);
assert(0);
@@ -684,8 +280,6 @@
switch (addr) {
/* SDRAM controller */
- case SH7750_SCBRR1_A7:
- case SH7750_SCBRR2_A7:
case SH7750_BCR2_A7:
case SH7750_BCR3_A7:
case SH7750_RTCOR_A7:
@@ -708,22 +302,6 @@
fprintf(stderr, "Write access to refresh count register\n");
s->rfcr = mem_value;
return;
- case SH7750_SCLSR2_A7:
- s->sclsr2 = mem_value;
- return;
- case SH7750_SCSCR2_A7:
- s->scscr2 = mem_value;
- scscr2_changed(s);
- return;
- case SH7750_SCFCR2_A7:
- s->scfcr2 = mem_value;
- return;
- case SH7750_SCSMR2_A7:
- s->scsmr2 = mem_value;
- return;
- case SH7750_TCR0_A7:
- s->tcr0 = mem_value;
- return;
case SH7750_GPIOIC_A7:
s->gpioic = mem_value;
if (mem_value != 0) {
@@ -731,6 +309,9 @@
assert(0);
}
return;
+ case 0x1fd00000:
+ s->icr = mem_value;
+ return;
default:
error_access("word write", addr);
assert(0);
@@ -768,9 +349,6 @@
s->portpullupb = portpullup(mem_value);
portb_changed(s, temp);
return;
- case SH7750_TCNT0_A7:
- s->tcnt0 = mem_value & 0xf;
- return;
case SH7750_MMUCR_A7:
s->cpu->mmucr = mem_value;
return;
@@ -816,10 +394,144 @@
sh7750_mem_writel
};
+/* sh775x interrupt controller tables for sh_intc.c
+ * stolen from linux/arch/sh/kernel/cpu/sh4/setup-sh7750.c
+ */
+
+enum {
+ UNUSED = 0,
+
+ /* interrupt sources */
+ IRL0, IRL1, IRL2, IRL3, /* only IRLM mode supported */
+ HUDI, GPIOI,
+ DMAC_DMTE0, DMAC_DMTE1, DMAC_DMTE2, DMAC_DMTE3,
+ DMAC_DMTE4, DMAC_DMTE5, DMAC_DMTE6, DMAC_DMTE7,
+ DMAC_DMAE,
+ PCIC0_PCISERR, PCIC1_PCIERR, PCIC1_PCIPWDWN, PCIC1_PCIPWON,
+ PCIC1_PCIDMA0, PCIC1_PCIDMA1, PCIC1_PCIDMA2, PCIC1_PCIDMA3,
+ TMU3, TMU4, TMU0, TMU1, TMU2_TUNI, TMU2_TICPI,
+ RTC_ATI, RTC_PRI, RTC_CUI,
+ SCI1_ERI, SCI1_RXI, SCI1_TXI, SCI1_TEI,
+ SCIF_ERI, SCIF_RXI, SCIF_BRI, SCIF_TXI,
+ WDT,
+ REF_RCMI, REF_ROVI,
+
+ /* interrupt groups */
+ DMAC, PCIC1, TMU2, RTC, SCI1, SCIF, REF,
+
+ NR_SOURCES,
+};
+
+static struct intc_vect vectors[] = {
+ INTC_VECT(HUDI, 0x600), INTC_VECT(GPIOI, 0x620),
+ INTC_VECT(TMU0, 0x400), INTC_VECT(TMU1, 0x420),
+ INTC_VECT(TMU2_TUNI, 0x440), INTC_VECT(TMU2_TICPI, 0x460),
+ INTC_VECT(RTC_ATI, 0x480), INTC_VECT(RTC_PRI, 0x4a0),
+ INTC_VECT(RTC_CUI, 0x4c0),
+ INTC_VECT(SCI1_ERI, 0x4e0), INTC_VECT(SCI1_RXI, 0x500),
+ INTC_VECT(SCI1_TXI, 0x520), INTC_VECT(SCI1_TEI, 0x540),
+ INTC_VECT(SCIF_ERI, 0x700), INTC_VECT(SCIF_RXI, 0x720),
+ INTC_VECT(SCIF_BRI, 0x740), INTC_VECT(SCIF_TXI, 0x760),
+ INTC_VECT(WDT, 0x560),
+ INTC_VECT(REF_RCMI, 0x580), INTC_VECT(REF_ROVI, 0x5a0),
+};
+
+static struct intc_group groups[] = {
+ INTC_GROUP(TMU2, TMU2_TUNI, TMU2_TICPI),
+ INTC_GROUP(RTC, RTC_ATI, RTC_PRI, RTC_CUI),
+ INTC_GROUP(SCI1, SCI1_ERI, SCI1_RXI, SCI1_TXI, SCI1_TEI),
+ INTC_GROUP(SCIF, SCIF_ERI, SCIF_RXI, SCIF_BRI, SCIF_TXI),
+ INTC_GROUP(REF, REF_RCMI, REF_ROVI),
+};
+
+static struct intc_prio_reg prio_registers[] = {
+ { 0xffd00004, 0, 16, 4, /* IPRA */ { TMU0, TMU1, TMU2, RTC } },
+ { 0xffd00008, 0, 16, 4, /* IPRB */ { WDT, REF, SCI1, 0 } },
+ { 0xffd0000c, 0, 16, 4, /* IPRC */ { GPIOI, DMAC, SCIF, HUDI } },
+ { 0xffd00010, 0, 16, 4, /* IPRD */ { IRL0, IRL1, IRL2, IRL3 } },
+ { 0xfe080000, 0, 32, 4, /* INTPRI00 */ { 0, 0, 0, 0,
+ TMU4, TMU3,
+ PCIC1, PCIC0_PCISERR } },
+};
+
+/* SH7750, SH7750S, SH7751 and SH7091 all have 4-channel DMA controllers */
+
+static struct intc_vect vectors_dma4[] = {
+ INTC_VECT(DMAC_DMTE0, 0x640), INTC_VECT(DMAC_DMTE1, 0x660),
+ INTC_VECT(DMAC_DMTE2, 0x680), INTC_VECT(DMAC_DMTE3, 0x6a0),
+ INTC_VECT(DMAC_DMAE, 0x6c0),
+};
+
+static struct intc_group groups_dma4[] = {
+ INTC_GROUP(DMAC, DMAC_DMTE0, DMAC_DMTE1, DMAC_DMTE2,
+ DMAC_DMTE3, DMAC_DMAE),
+};
+
+/* SH7750R and SH7751R both have 8-channel DMA controllers */
+
+static struct intc_vect vectors_dma8[] = {
+ INTC_VECT(DMAC_DMTE0, 0x640), INTC_VECT(DMAC_DMTE1, 0x660),
+ INTC_VECT(DMAC_DMTE2, 0x680), INTC_VECT(DMAC_DMTE3, 0x6a0),
+ INTC_VECT(DMAC_DMTE4, 0x780), INTC_VECT(DMAC_DMTE5, 0x7a0),
+ INTC_VECT(DMAC_DMTE6, 0x7c0), INTC_VECT(DMAC_DMTE7, 0x7e0),
+ INTC_VECT(DMAC_DMAE, 0x6c0),
+};
+
+static struct intc_group groups_dma8[] = {
+ INTC_GROUP(DMAC, DMAC_DMTE0, DMAC_DMTE1, DMAC_DMTE2,
+ DMAC_DMTE3, DMAC_DMTE4, DMAC_DMTE5,
+ DMAC_DMTE6, DMAC_DMTE7, DMAC_DMAE),
+};
+
+/* SH7750R, SH7751 and SH7751R all have two extra timer channels */
+
+static struct intc_vect vectors_tmu34[] = {
+ INTC_VECT(TMU3, 0xb00), INTC_VECT(TMU4, 0xb80),
+};
+
+static struct intc_mask_reg mask_registers[] = {
+ { 0xfe080040, 0xfe080060, 32, /* INTMSK00 / INTMSKCLR00 */
+ { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, TMU4, TMU3,
+ PCIC1_PCIERR, PCIC1_PCIPWDWN, PCIC1_PCIPWON,
+ PCIC1_PCIDMA0, PCIC1_PCIDMA1, PCIC1_PCIDMA2,
+ PCIC1_PCIDMA3, PCIC0_PCISERR } },
+};
+
+/* SH7750S, SH7750R, SH7751 and SH7751R all have IRLM priority registers */
+
+static struct intc_vect vectors_irlm[] = {
+ INTC_VECT(IRL0, 0x240), INTC_VECT(IRL1, 0x2a0),
+ INTC_VECT(IRL2, 0x300), INTC_VECT(IRL3, 0x360),
+};
+
+/* SH7751 and SH7751R both have PCI */
+
+static struct intc_vect vectors_pci[] = {
+ INTC_VECT(PCIC0_PCISERR, 0xa00), INTC_VECT(PCIC1_PCIERR, 0xae0),
+ INTC_VECT(PCIC1_PCIPWDWN, 0xac0), INTC_VECT(PCIC1_PCIPWON, 0xaa0),
+ INTC_VECT(PCIC1_PCIDMA0, 0xa80), INTC_VECT(PCIC1_PCIDMA1, 0xa60),
+ INTC_VECT(PCIC1_PCIDMA2, 0xa40), INTC_VECT(PCIC1_PCIDMA3, 0xa20),
+};
+
+static struct intc_group groups_pci[] = {
+ INTC_GROUP(PCIC1, PCIC1_PCIERR, PCIC1_PCIPWDWN, PCIC1_PCIPWON,
+ PCIC1_PCIDMA0, PCIC1_PCIDMA1, PCIC1_PCIDMA2, PCIC1_PCIDMA3),
+};
+
+#define SH_CPU_SH7750 (1 << 0)
+#define SH_CPU_SH7750S (1 << 1)
+#define SH_CPU_SH7750R (1 << 2)
+#define SH_CPU_SH7751 (1 << 3)
+#define SH_CPU_SH7751R (1 << 4)
+#define SH_CPU_SH7750_ALL (SH_CPU_SH7750 | SH_CPU_SH7750S | SH_CPU_SH7750R)
+#define SH_CPU_SH7751_ALL (SH_CPU_SH7751 | SH_CPU_SH7751R)
+
SH7750State *sh7750_init(CPUSH4State * cpu)
{
SH7750State *s;
int sh7750_io_memory;
+ int cpu_model = SH_CPU_SH7751R; /* for now */
s = qemu_mallocz(sizeof(SH7750State));
s->cpu = cpu;
@@ -828,7 +540,54 @@
sh7750_mem_read,
sh7750_mem_write, s);
cpu_register_physical_memory(0x1c000000, 0x04000000, sh7750_io_memory);
- init_timers(s);
- init_serial_ports(s);
+
+ sh_intc_init(&s->intc, NR_SOURCES,
+ _INTC_ARRAY(mask_registers),
+ _INTC_ARRAY(prio_registers));
+
+ sh_intc_register_sources(&s->intc,
+ _INTC_ARRAY(vectors),
+ _INTC_ARRAY(groups));
+
+ sh_serial_init(0x1fe00000, 0, s->periph_freq, serial_hds[0]);
+ sh_serial_init(0x1fe80000, SH_SERIAL_FEAT_SCIF,
+ s->periph_freq, serial_hds[1]);
+
+ tmu012_init(0x1fd80000,
+ TMU012_FEAT_TOCR | TMU012_FEAT_3CHAN | TMU012_FEAT_EXTCLK,
+ s->periph_freq);
+
+
+ if (cpu_model & (SH_CPU_SH7750 | SH_CPU_SH7750S | SH_CPU_SH7751)) {
+ sh_intc_register_sources(&s->intc,
+ _INTC_ARRAY(vectors_dma4),
+ _INTC_ARRAY(groups_dma4));
+ }
+
+ if (cpu_model & (SH_CPU_SH7750R | SH_CPU_SH7751R)) {
+ sh_intc_register_sources(&s->intc,
+ _INTC_ARRAY(vectors_dma8),
+ _INTC_ARRAY(groups_dma8));
+ }
+
+ if (cpu_model & (SH_CPU_SH7750R | SH_CPU_SH7751 | SH_CPU_SH7751R)) {
+ sh_intc_register_sources(&s->intc,
+ _INTC_ARRAY(vectors_tmu34),
+ _INTC_ARRAY(NULL));
+ tmu012_init(0x1e100000, 0, s->periph_freq);
+ }
+
+ if (cpu_model & (SH_CPU_SH7751_ALL)) {
+ sh_intc_register_sources(&s->intc,
+ _INTC_ARRAY(vectors_pci),
+ _INTC_ARRAY(groups_pci));
+ }
+
+ if (cpu_model & (SH_CPU_SH7750S | SH_CPU_SH7750R | SH_CPU_SH7751_ALL)) {
+ sh_intc_register_sources(&s->intc,
+ _INTC_ARRAY(vectors_irlm),
+ _INTC_ARRAY(NULL));
+ }
+
return s;
}
Modified: trunk/src/host/qemu-neo1973/hw/sh7750_regnames.c
===================================================================
--- trunk/src/host/qemu-neo1973/hw/sh7750_regnames.c 2007-10-29 20:40:05 UTC (rev 3302)
+++ trunk/src/host/qemu-neo1973/hw/sh7750_regnames.c 2007-10-29 21:14:04 UTC (rev 3303)
@@ -42,18 +42,6 @@
REGNAME(SH7750_RMONAR_A7)
REGNAME(SH7750_RCR1_A7)
REGNAME(SH7750_RCR2_A7)
- REGNAME(SH7750_TOCR_A7)
- REGNAME(SH7750_TSTR_A7)
- REGNAME(SH7750_TCOR0_A7)
- REGNAME(SH7750_TCOR1_A7)
- REGNAME(SH7750_TCOR2_A7)
- REGNAME(SH7750_TCNT0_A7)
- REGNAME(SH7750_TCNT1_A7)
- REGNAME(SH7750_TCNT2_A7)
- REGNAME(SH7750_TCR0_A7)
- REGNAME(SH7750_TCR1_A7)
- REGNAME(SH7750_TCR2_A7)
- REGNAME(SH7750_TCPR2_A7)
REGNAME(SH7750_BCR1_A7)
REGNAME(SH7750_BCR2_A7)
REGNAME(SH7750_WCR1_A7)
@@ -82,33 +70,12 @@
REGNAME(SH7750_CHCR2_A7)
REGNAME(SH7750_CHCR3_A7)
REGNAME(SH7750_DMAOR_A7)
- REGNAME(SH7750_SCRDR1_A7)
- REGNAME(SH7750_SCRDR2_A7)
- REGNAME(SH7750_SCTDR1_A7)
- REGNAME(SH7750_SCTDR2_A7)
- REGNAME(SH7750_SCSMR1_A7)
- REGNAME(SH7750_SCSMR2_A7)
- REGNAME(SH7750_SCSCR1_A7)
- REGNAME(SH7750_SCSCR2_A7)
- REGNAME(SH7750_SCSSR1_A7)
- REGNAME(SH7750_SCSFR2_A7)
- REGNAME(SH7750_SCSPTR1_A7)
- REGNAME(SH7750_SCSPTR2_A7)
- REGNAME(SH7750_SCBRR1_A7)
- REGNAME(SH7750_SCBRR2_A7)
- REGNAME(SH7750_SCFCR2_A7)
- REGNAME(SH7750_SCFDR2_A7)
- REGNAME(SH7750_SCLSR2_A7)
- REGNAME(SH7750_SCSCMR1_A7)
REGNAME(SH7750_PCTRA_A7)
REGNAME(SH7750_PDTRA_A7)
REGNAME(SH7750_PCTRB_A7)
REGNAME(SH7750_PDTRB_A7)
REGNAME(SH7750_GPIOIC_A7)
REGNAME(SH7750_ICR_A7)
- REGNAME(SH7750_IPRA_A7)
- REGNAME(SH7750_IPRB_A7)
- REGNAME(SH7750_IPRC_A7)
REGNAME(SH7750_BCR3_A7)
REGNAME(SH7750_BCR4_A7)
REGNAME(SH7750_PRECHARGE0_A7)
Modified: trunk/src/host/qemu-neo1973/hw/sh7750_regs.h
===================================================================
--- trunk/src/host/qemu-neo1973/hw/sh7750_regs.h 2007-10-29 20:40:05 UTC (rev 3302)
+++ trunk/src/host/qemu-neo1973/hw/sh7750_regs.h 2007-10-29 21:14:04 UTC (rev 3303)
@@ -524,95 +524,7 @@
year counters are stopped
1 - sec, min, hr, day-of-week, month,
year counters operate normally */
-
-
/*
- * Timer Unit (TMU)
- */
-/* Timer Output Control Register (byte) - TOCR */
-#define SH7750_TOCR_REGOFS 0xD80000 /* offset */
-#define SH7750_TOCR SH7750_P4_REG32(SH7750_TOCR_REGOFS)
-#define SH7750_TOCR_A7 SH7750_A7_REG32(SH7750_TOCR_REGOFS)
-#define SH7750_TOCR_TCOE 0x01 /* Timer Clock Pin Control:
- 0 - TCLK is used as external clock
- input or input capture control
- 1 - TCLK is used as on-chip RTC
- output clock pin */
-
-/* Timer Start Register (byte) - TSTR */
-#define SH7750_TSTR_REGOFS 0xD80004 /* offset */
-#define SH7750_TSTR SH7750_P4_REG32(SH7750_TSTR_REGOFS)
-#define SH7750_TSTR_A7 SH7750_A7_REG32(SH7750_TSTR_REGOFS)
-#define SH7750_TSTR_STR2 0x04 /* TCNT2 performs count operations */
-#define SH7750_TSTR_STR1 0x02 /* TCNT1 performs count operations */
-#define SH7750_TSTR_STR0 0x01 /* TCNT0 performs count operations */
-#define SH7750_TSTR_STR(n) (1 << (n))
-
-/* Timer Constant Register - TCOR0, TCOR1, TCOR2 */
-#define SH7750_TCOR_REGOFS(n) (0xD80008 + ((n)*12)) /* offset */
-#define SH7750_TCOR(n) SH7750_P4_REG32(SH7750_TCOR_REGOFS(n))
-#define SH7750_TCOR_A7(n) SH7750_A7_REG32(SH7750_TCOR_REGOFS(n))
-#define SH7750_TCOR0 SH7750_TCOR(0)
-#define SH7750_TCOR1 SH7750_TCOR(1)
-#define SH7750_TCOR2 SH7750_TCOR(2)
-#define SH7750_TCOR0_A7 SH7750_TCOR_A7(0)
-#define SH7750_TCOR1_A7 SH7750_TCOR_A7(1)
-#define SH7750_TCOR2_A7 SH7750_TCOR_A7(2)
-
-/* Timer Counter Register - TCNT0, TCNT1, TCNT2 */
-#define SH7750_TCNT_REGOFS(n) (0xD8000C + ((n)*12)) /* offset */
-#define SH7750_TCNT(n) SH7750_P4_REG32(SH7750_TCNT_REGOFS(n))
-#define SH7750_TCNT_A7(n) SH7750_A7_REG32(SH7750_TCNT_REGOFS(n))
-#define SH7750_TCNT0 SH7750_TCNT(0)
-#define SH7750_TCNT1 SH7750_TCNT(1)
-#define SH7750_TCNT2 SH7750_TCNT(2)
-#define SH7750_TCNT0_A7 SH7750_TCNT_A7(0)
-#define SH7750_TCNT1_A7 SH7750_TCNT_A7(1)
-#define SH7750_TCNT2_A7 SH7750_TCNT_A7(2)
-
-/* Timer Control Register (half) - TCR0, TCR1, TCR2 */
-#define SH7750_TCR_REGOFS(n) (0xD80010 + ((n)*12)) /* offset */
-#define SH7750_TCR(n) SH7750_P4_REG32(SH7750_TCR_REGOFS(n))
-#define SH7750_TCR_A7(n) SH7750_A7_REG32(SH7750_TCR_REGOFS(n))
-#define SH7750_TCR0 SH7750_TCR(0)
-#define SH7750_TCR1 SH7750_TCR(1)
-#define SH7750_TCR2 SH7750_TCR(2)
-#define SH7750_TCR0_A7 SH7750_TCR_A7(0)
-#define SH7750_TCR1_A7 SH7750_TCR_A7(1)
-#define SH7750_TCR2_A7 SH7750_TCR_A7(2)
-
-#define SH7750_TCR2_ICPF 0x200 /* Input Capture Interrupt Flag
- (1 - input capture has occured) */
-#define SH7750_TCR_UNF 0x100 /* Underflow flag */
-#define SH7750_TCR2_ICPE 0x0C0 /* Input Capture Control: */
-#define SH7750_TCR2_ICPE_DIS 0x000 /* Input Capture function is not used */
-#define SH7750_TCR2_ICPE_NOINT 0x080 /* Input Capture function is used, but
- input capture interrupt is not
- enabled */
-#define SH7750_TCR2_ICPE_INT 0x0C0 /* Input Capture function is used,
- input capture interrupt enabled */
-#define SH7750_TCR_UNIE 0x020 /* Underflow Interrupt Control
- (1 - underflow interrupt enabled) */
-#define SH7750_TCR_CKEG 0x018 /* Clock Edge selection: */
-#define SH7750_TCR_CKEG_RAISE 0x000 /* Count/capture on rising edge */
-#define SH7750_TCR_CKEG_FALL 0x008 /* Count/capture on falling edge */
-#define SH7750_TCR_CKEG_BOTH 0x018 /* Count/capture on both rising and
- falling edges */
-#define SH7750_TCR_TPSC 0x007 /* Timer prescaler */
-#define SH7750_TCR_TPSC_DIV4 0x000 /* Counts on peripheral clock/4 */
-#define SH7750_TCR_TPSC_DIV16 0x001 /* Counts on peripheral clock/16 */
-#define SH7750_TCR_TPSC_DIV64 0x002 /* Counts on peripheral clock/64 */
-#define SH7750_TCR_TPSC_DIV256 0x003 /* Counts on peripheral clock/256 */
-#define SH7750_TCR_TPSC_DIV1024 0x004 /* Counts on peripheral clock/1024 */
-#define SH7750_TCR_TPSC_RTC 0x006 /* Counts on on-chip RTC output clk */
-#define SH7750_TCR_TPSC_EXT 0x007 /* Counts on external clock */
-
-/* Input Capture Register (read-only) - TCPR2 */
-#define SH7750_TCPR2_REGOFS 0xD8002C /* offset */
-#define SH7750_TCPR2 SH7750_P4_REG32(SH7750_TCPR2_REGOFS)
-#define SH7750_TCPR2_A7 SH7750_A7_REG32(SH7750_TCPR2_REGOFS)
-
-/*
* Bus State Controller - BSC
*/
/* Bus Control Register 1 - BCR1 */
@@ -1257,231 +1169,6 @@
#define SH7750_DMAOR_DME 0x00000001 /* DMAC Master Enable */
/*
- * Serial Communication Interface - SCI
- * Serial Communication Interface with FIFO - SCIF
- */
-/* SCI Receive Data Register (byte, read-only) - SCRDR1, SCFRDR2 */
-#define SH7750_SCRDR_REGOFS(n) ((n) == 1 ? 0xE00014 : 0xE80014) /* offset */
-#define SH7750_SCRDR(n) SH7750_P4_REG32(SH7750_SCRDR_REGOFS(n))
-#define SH7750_SCRDR1 SH7750_SCRDR(1)
-#define SH7750_SCRDR2 SH7750_SCRDR(2)
-#define SH7750_SCRDR_A7(n) SH7750_A7_REG32(SH7750_SCRDR_REGOFS(n))
-#define SH7750_SCRDR1_A7 SH7750_SCRDR_A7(1)
-#define SH7750_SCRDR2_A7 SH7750_SCRDR_A7(2)
-
-/* SCI Transmit Data Register (byte) - SCTDR1, SCFTDR2 */
-#define SH7750_SCTDR_REGOFS(n) ((n) == 1 ? 0xE0000C : 0xE8000C) /* offset */
-#define SH7750_SCTDR(n) SH7750_P4_REG32(SH7750_SCTDR_REGOFS(n))
-#define SH7750_SCTDR1 SH7750_SCTDR(1)
-#define SH7750_SCTDR2 SH7750_SCTDR(2)
-#define SH7750_SCTDR_A7(n) SH7750_A7_REG32(SH7750_SCTDR_REGOFS(n))
-#define SH7750_SCTDR1_A7 SH7750_SCTDR_A7(1)
-#define SH7750_SCTDR2_A7 SH7750_SCTDR_A7(2)
-
-/* SCI Serial Mode Register - SCSMR1(byte), SCSMR2(half) */
-#define SH7750_SCSMR_REGOFS(n) ((n) == 1 ? 0xE00000 : 0xE80000) /* offset */
-#define SH7750_SCSMR(n) SH7750_P4_REG32(SH7750_SCSMR_REGOFS(n))
-#define SH7750_SCSMR1 SH7750_SCSMR(1)
-#define SH7750_SCSMR2 SH7750_SCSMR(2)
-#define SH7750_SCSMR_A7(n) SH7750_A7_REG32(SH7750_SCSMR_REGOFS(n))
-#define SH7750_SCSMR1_A7 SH7750_SCSMR_A7(1)
-#define SH7750_SCSMR2_A7 SH7750_SCSMR_A7(2)
-
-#define SH7750_SCSMR1_CA 0x80 /* Communication Mode (C/A\): */
-#define SH7750_SCSMR1_CA_ASYNC 0x00 /* Asynchronous Mode */
-#define SH7750_SCSMR1_CA_SYNC 0x80 /* Synchronous Mode */
-#define SH7750_SCSMR_CHR 0x40 /* Character Length: */
-#define SH7750_SCSMR_CHR_8 0x00 /* 8-bit data */
-#define SH7750_SCSMR_CHR_7 0x40 /* 7-bit data */
-#define SH7750_SCSMR_PE 0x20 /* Parity Enable */
-#define SH7750_SCSMR_PM 0x10 /* Parity Mode: */
-#define SH7750_SCSMR_PM_EVEN 0x00 /* Even Parity */
-#define SH7750_SCSMR_PM_ODD 0x10 /* Odd Parity */
-#define SH7750_SCSMR_STOP 0x08 /* Stop Bit Length: */
-#define SH7750_SCSMR_STOP_1 0x00 /* 1 stop bit */
-#define SH7750_SCSMR_STOP_2 0x08 /* 2 stop bit */
-#define SH7750_SCSMR1_MP 0x04 /* Multiprocessor Mode */
-#define SH7750_SCSMR_CKS 0x03 /* Clock Select */
-#define SH7750_SCSMR_CKS_S 0
-#define SH7750_SCSMR_CKS_DIV1 0x00 /* Periph clock */
-#define SH7750_SCSMR_CKS_DIV4 0x01 /* Periph clock / 4 */
-#define SH7750_SCSMR_CKS_DIV16 0x02 /* Periph clock / 16 */
-#define SH7750_SCSMR_CKS_DIV64 0x03 /* Periph clock / 64 */
-
-/* SCI Serial Control Register - SCSCR1(byte), SCSCR2(half) */
-#define SH7750_SCSCR_REGOFS(n) ((n) == 1 ? 0xE00008 : 0xE80008) /* offset */
-#define SH7750_SCSCR(n) SH7750_P4_REG32(SH7750_SCSCR_REGOFS(n))
-#define SH7750_SCSCR1 SH7750_SCSCR(1)
-#define SH7750_SCSCR2 SH7750_SCSCR(2)
-#define SH7750_SCSCR_A7(n) SH7750_A7_REG32(SH7750_SCSCR_REGOFS(n))
-#define SH7750_SCSCR1_A7 SH7750_SCSCR_A7(1)
-#define SH7750_SCSCR2_A7 SH7750_SCSCR_A7(2)
-
-#define SH7750_SCSCR_TIE 0x80 /* Transmit Interrupt Enable */
-#define SH7750_SCSCR_RIE 0x40 /* Receive Interrupt Enable */
-#define SH7750_SCSCR_TE 0x20 /* Transmit Enable */
-#define SH7750_SCSCR_RE 0x10 /* Receive Enable */
-#define SH7750_SCSCR1_MPIE 0x08 /* Multiprocessor Interrupt Enable */
-#define SH7750_SCSCR2_REIE 0x08 /* Receive Error Interrupt Enable */
-#define SH7750_SCSCR1_TEIE 0x04 /* Transmit End Interrupt Enable */
-#define SH7750_SCSCR1_CKE 0x03 /* Clock Enable: */
-#define SH7750_SCSCR_CKE_INTCLK 0x00 /* Use Internal Clock */
-#define SH7750_SCSCR_CKE_EXTCLK 0x02 /* Use External Clock from SCK */
-#define SH7750_SCSCR1_CKE_ASYNC_SCK_CLKOUT 0x01 /* Use SCK as a clock output
- in asynchronous mode */
-
-/* SCI Serial Status Register - SCSSR1(byte), SCSFR2(half) */
-#define SH7750_SCSSR_REGOFS(n) ((n) == 1 ? 0xE00010 : 0xE80010) /* offset */
-#define SH7750_SCSSR(n) SH7750_P4_REG32(SH7750_SCSSR_REGOFS(n))
-#define SH7750_SCSSR1 SH7750_SCSSR(1)
-#define SH7750_SCSFR2 SH7750_SCSSR(2)
-#define SH7750_SCSSR_A7(n) SH7750_A7_REG32(SH7750_SCSSR_REGOFS(n))
-#define SH7750_SCSSR1_A7 SH7750_SCSSR_A7(1)
-#define SH7750_SCSFR2_A7 SH7750_SCSSR_A7(2)
-
-#define SH7750_SCSSR1_TDRE 0x80 /* Transmit Data Register Empty */
-#define SH7750_SCSSR1_RDRF 0x40 /* Receive Data Register Full */
-#define SH7750_SCSSR1_ORER 0x20 /* Overrun Error */
-#define SH7750_SCSSR1_FER 0x10 /* Framing Error */
-#define SH7750_SCSSR1_PER 0x08 /* Parity Error */
-#define SH7750_SCSSR1_TEND 0x04 /* Transmit End */
-#define SH7750_SCSSR1_MPB 0x02 /* Multiprocessor Bit */
-#define SH7750_SCSSR1_MPBT 0x01 /* Multiprocessor Bit Transfer */
-
-#define SH7750_SCFSR2_PERN 0xF000 /* Number of Parity Errors */
-#define SH7750_SCFSR2_PERN_S 12
-#define SH7750_SCFSR2_FERN 0x0F00 /* Number of Framing Errors */
-#define SH7750_SCFSR2_FERN_S 8
-#define SH7750_SCFSR2_ER 0x0080 /* Receive Error */
-#define SH7750_SCFSR2_TEND 0x0040 /* Transmit End */
-#define SH7750_SCFSR2_TDFE 0x0020 /* Transmit FIFO Data Empty */
-#define SH7750_SCFSR2_BRK 0x0010 /* Break Detect */
-#define SH7750_SCFSR2_FER 0x0008 /* Framing Error */
-#define SH7750_SCFSR2_PER 0x0004 /* Parity Error */
-#define SH7750_SCFSR2_RDF 0x0002 /* Receive FIFO Data Full */
-#define SH7750_SCFSR2_DR 0x0001 /* Receive Data Ready */
-
-/* SCI Serial Port Register - SCSPTR1(byte) */
-#define SH7750_SCSPTR1_REGOFS 0xE0001C /* offset */
-#define SH7750_SCSPTR1 SH7750_P4_REG32(SH7750_SCSPTR1_REGOFS)
-#define SH7750_SCSPTR1_A7 SH7750_A7_REG32(SH7750_SCSPTR1_REGOFS)
-
-#define SH7750_SCSPTR1_EIO 0x80 /* Error Interrupt Only */
-#define SH7750_SCSPTR1_SPB1IO 0x08 /* 1: Output SPB1DT bit to SCK pin */
-#define SH7750_SCSPTR1_SPB1DT 0x04 /* Serial Port Clock Port Data */
-#define SH7750_SCSPTR1_SPB0IO 0x02 /* 1: Output SPB0DT bit to TxD pin */
-#define SH7750_SCSPTR1_SPB0DT 0x01 /* Serial Port Break Data */
-
-/* SCIF Serial Port Register - SCSPTR2(half) */
-#define SH7750_SCSPTR2_REGOFS 0xE80020 /* offset */
-#define SH7750_SCSPTR2 SH7750_P4_REG32(SH7750_SCSPTR2_REGOFS)
-#define SH7750_SCSPTR2_A7 SH7750_A7_REG32(SH7750_SCSPTR2_REGOFS)
-
-#define SH7750_SCSPTR2_RTSIO 0x80 /* 1: Output RTSDT bit to RTS2\ pin */
-#define SH7750_SCSPTR2_RTSDT 0x40 /* RTS Port Data */
-#define SH7750_SCSPTR2_CTSIO 0x20 /* 1: Output CTSDT bit to CTS2\ pin */
-#define SH7750_SCSPTR2_CTSDT 0x10 /* CTS Port Data */
-#define SH7750_SCSPTR2_SPB2IO 0x02 /* 1: Output SPBDT bit to TxD2 pin */
-#define SH7750_SCSPTR2_SPB2DT 0x01 /* Serial Port Break Data */
-
-/* SCI Bit Rate Register - SCBRR1(byte), SCBRR2(byte) */
-#define SH7750_SCBRR_REGOFS(n) ((n) == 1 ? 0xE00004 : 0xE80004) /* offset */
-#define SH7750_SCBRR(n) SH7750_P4_REG32(SH7750_SCBRR_REGOFS(n))
-#define SH7750_SCBRR1 SH7750_SCBRR_P4(1)
-#define SH7750_SCBRR2 SH7750_SCBRR_P4(2)
-#define SH7750_SCBRR_A7(n) SH7750_A7_REG32(SH7750_SCBRR_REGOFS(n))
-#define SH7750_SCBRR1_A7 SH7750_SCBRR_A7(1)
-#define SH7750_SCBRR2_A7 SH7750_SCBRR_A7(2)
-
-/* SCIF FIFO Control Register - SCFCR2(half) */
-#define SH7750_SCFCR2_REGOFS 0xE80018 /* offset */
-#define SH7750_SCFCR2 SH7750_P4_REG32(SH7750_SCFCR2_REGOFS)
-#define SH7750_SCFCR2_A7 SH7750_A7_REG32(SH7750_SCFCR2_REGOFS)
-
-#define SH7750_SCFCR2_RSTRG 0x700 /* RTS2\ Output Active Trigger; RTS2\
- signal goes to high level when the
- number of received data stored in
- FIFO exceeds the trigger number */
-#define SH7750_SCFCR2_RSTRG_15 0x000 /* 15 bytes */
-#define SH7750_SCFCR2_RSTRG_1 0x000 /* 1 byte */
-#define SH7750_SCFCR2_RSTRG_4 0x000 /* 4 bytes */
-#define SH7750_SCFCR2_RSTRG_6 0x000 /* 6 bytes */
-#define SH7750_SCFCR2_RSTRG_8 0x000 /* 8 bytes */
-#define SH7750_SCFCR2_RSTRG_10 0x000 /* 10 bytes */
-#define SH7750_SCFCR2_RSTRG_14 0x000 /* 14 bytes */
-
-#define SH7750_SCFCR2_RTRG 0x0C0 /* Receive FIFO Data Number Trigger,
- Receive Data Full (RDF) Flag sets
- when number of receive data bytes is
- equal or greater than the trigger
- number */
-#define SH7750_SCFCR2_RTRG_1 0x000 /* 1 byte */
-#define SH7750_SCFCR2_RTRG_4 0x040 /* 4 bytes */
-#define SH7750_SCFCR2_RTRG_8 0x080 /* 8 bytes */
-#define SH7750_SCFCR2_RTRG_14 0x0C0 /* 14 bytes */
-
-#define SH7750_SCFCR2_TTRG 0x030 /* Transmit FIFO Data Number Trigger,
- Transmit FIFO Data Register Empty (TDFE)
- flag sets when the number of remaining
- transmit data bytes is equal or less
- than the trigger number */
-#define SH7750_SCFCR2_TTRG_8 0x000 /* 8 bytes */
-#define SH7750_SCFCR2_TTRG_4 0x010 /* 4 bytes */
-#define SH7750_SCFCR2_TTRG_2 0x020 /* 2 bytes */
-#define SH7750_SCFCR2_TTRG_1 0x030 /* 1 byte */
-
-#define SH7750_SCFCR2_MCE 0x008 /* Modem Control Enable */
-#define SH7750_SCFCR2_TFRST 0x004 /* Transmit FIFO Data Register Reset,
- invalidates the transmit data in the
- transmit FIFO */
-#define SH7750_SCFCR2_RFRST 0x002 /* Receive FIFO Data Register Reset,
- invalidates the receive data in the
- receive FIFO data register and resets
- it to the empty state */
-#define SH7750_SCFCR2_LOOP 0x001 /* Loopback Test */
-
-/* SCIF FIFO Data Count Register - SCFDR2(half, read-only) */
-#define SH7750_SCFDR2_REGOFS 0xE8001C /* offset */
-#define SH7750_SCFDR2 SH7750_P4_REG32(SH7750_SCFDR2_REGOFS)
-#define SH7750_SCFDR2_A7 SH7750_A7_REG32(SH7750_SCFDR2_REGOFS)
-
-#define SH7750_SCFDR2_T 0x1F00 /* Number of untransmitted data bytes
- in transmit FIFO */
-#define SH7750_SCFDR2_T_S 8
-#define SH7750_SCFDR2_R 0x001F /* Number of received data bytes in
- receive FIFO */
-#define SH7750_SCFDR2_R_S 0
-
-/* SCIF Line Status Register - SCLSR2(half, read-only) */
-#define SH7750_SCLSR2_REGOFS 0xE80024 /* offset */
-#define SH7750_SCLSR2 SH7750_P4_REG32(SH7750_SCLSR2_REGOFS)
-#define SH7750_SCLSR2_A7 SH7750_A7_REG32(SH7750_SCLSR2_REGOFS)
-
-#define SH7750_SCLSR2_ORER 0x0001 /* Overrun Error */
-
-/*
- * SCI-based Smart Card Interface
- */
-/* Smart Card Mode Register - SCSCMR1(byte) */
-#define SH7750_SCSCMR1_REGOFS 0xE00018 /* offset */
-#define SH7750_SCSCMR1 SH7750_P4_REG32(SH7750_SCSCMR1_REGOFS)
-#define SH7750_SCSCMR1_A7 SH7750_A7_REG32(SH7750_SCSCMR1_REGOFS)
-
-#define SH7750_SCSCMR1_SDIR 0x08 /* Smart Card Data Transfer Direction: */
-#define SH7750_SCSCMR1_SDIR_LSBF 0x00 /* LSB-first */
-#define SH7750_SCSCMR1_SDIR_MSBF 0x08 /* MSB-first */
-
-#define SH7750_SCSCMR1_SINV 0x04 /* Smart Card Data Inversion */
-#define SH7750_SCSCMR1_SMIF 0x01 /* Smart Card Interface Mode Select */
-
-/* Smart-card specific bits in other registers */
-/* SCSMR1: */
-#define SH7750_SCSMR1_GSM 0x80 /* GSM mode select */
-
-/* SCSSR1: */
-#define SH7750_SCSSR1_ERS 0x10 /* Error Signal Status */
-
-/*
* I/O Ports
*/
/* Port Control Register A - PCTRA */
@@ -1554,48 +1241,6 @@
#define SH7750_ICR_IRLM_RAW 0x0080 /* IRL\ pins used as a four independent
interrupt requests */
-/* Interrupt Priority Register A - IPRA (half) */
-#define SH7750_IPRA_REGOFS 0xD00004 /* offset */
-#define SH7750_IPRA SH7750_P4_REG32(SH7750_IPRA_REGOFS)
-#define SH7750_IPRA_A7 SH7750_A7_REG32(SH7750_IPRA_REGOFS)
-
-#define SH7750_IPRA_TMU0 0xF000 /* TMU0 interrupt priority */
-#define SH7750_IPRA_TMU0_S 12
-#define SH7750_IPRA_TMU1 0x0F00 /* TMU1 interrupt priority */
-#define SH7750_IPRA_TMU1_S 8
-#define SH7750_IPRA_TMU2 0x00F0 /* TMU2 interrupt priority */
-#define SH7750_IPRA_TMU2_S 4
-#define SH7750_IPRA_RTC 0x000F /* RTC interrupt priority */
-#define SH7750_IPRA_RTC_S 0
-
-/* Interrupt Priority Register B - IPRB (half) */
-#define SH7750_IPRB_REGOFS 0xD00008 /* offset */
-#define SH7750_IPRB SH7750_P4_REG32(SH7750_IPRB_REGOFS)
-#define SH7750_IPRB_A7 SH7750_A7_REG32(SH7750_IPRB_REGOFS)
-
-#define SH7750_IPRB_WDT 0xF000 /* WDT interrupt priority */
-#define SH7750_IPRB_WDT_S 12
-#define SH7750_IPRB_REF 0x0F00 /* Memory Refresh unit interrupt
- priority */
-#define SH7750_IPRB_REF_S 8
-#define SH7750_IPRB_SCI1 0x00F0 /* SCI1 interrupt priority */
-#define SH7750_IPRB_SCI1_S 4
-
-/* Interrupt Priority Register ó - IPRó (half) */
-#define SH7750_IPRC_REGOFS 0xD00004 /* offset */
-#define SH7750_IPRC SH7750_P4_REG32(SH7750_IPRC_REGOFS)
-#define SH7750_IPRC_A7 SH7750_A7_REG32(SH7750_IPRC_REGOFS)
-
-#define SH7750_IPRC_GPIO 0xF000 /* GPIO interrupt priority */
-#define SH7750_IPRC_GPIO_S 12
-#define SH7750_IPRC_DMAC 0x0F00 /* DMAC interrupt priority */
-#define SH7750_IPRC_DMAC_S 8
-#define SH7750_IPRC_SCIF 0x00F0 /* SCIF interrupt priority */
-#define SH7750_IPRC_SCIF_S 4
-#define SH7750_IPRC_HUDI 0x000F /* H-UDI interrupt priority */
-#define SH7750_IPRC_HUDI_S 0
-
-
/*
* User Break Controller registers
*/
Added: trunk/src/host/qemu-neo1973/hw/sh_intc.c
===================================================================
--- trunk/src/host/qemu-neo1973/hw/sh_intc.c 2007-10-29 20:40:05 UTC (rev 3302)
+++ trunk/src/host/qemu-neo1973/hw/sh_intc.c 2007-10-29 21:14:04 UTC (rev 3303)
@@ -0,0 +1,383 @@
+/*
+ * SuperH interrupt controller module
+ *
+ * Copyright (c) 2007 Magnus Damm
+ * Based on sh_timer.c and arm_timer.c by Paul Brook
+ * Copyright (c) 2005-2006 CodeSourcery.
+ *
+ * This code is licenced under the GPL.
+ */
+
+#include <assert.h>
+#include "sh_intc.h"
+#include "vl.h"
+
+//#define DEBUG_INTC
+
+#define INTC_A7(x) ((x) & 0x1fffffff)
+#define INTC_ARRAY(x) (sizeof(x) / sizeof(x[0]))
+
+#define INTC_MODE_NONE 0
+#define INTC_MODE_DUAL_SET 1
+#define INTC_MODE_DUAL_CLR 2
+#define INTC_MODE_ENABLE_REG 3
+#define INTC_MODE_MASK_REG 4
+#define INTC_MODE_IS_PRIO 8
+
+static unsigned int sh_intc_mode(unsigned long address,
+ unsigned long set_reg, unsigned long clr_reg)
+{
+ if ((address != INTC_A7(set_reg)) &&
+ (address != INTC_A7(clr_reg)))
+ return INTC_MODE_NONE;
+
+ if (set_reg && clr_reg) {
+ if (address == INTC_A7(set_reg))
+ return INTC_MODE_DUAL_SET;
+ else
+ return INTC_MODE_DUAL_CLR;
+ }
+
+ if (set_reg)
+ return INTC_MODE_ENABLE_REG;
+ else
+ return INTC_MODE_MASK_REG;
+}
+
+static void sh_intc_locate(struct intc_desc *desc,
+ unsigned long address,
+ unsigned long **datap,
+ intc_enum **enums,
+ unsigned int *first,
+ unsigned int *width,
+ unsigned int *modep)
+{
+ unsigned int i, mode;
+
+ /* this is slow but works for now */
+
+ if (desc->mask_regs) {
+ for (i = 0; i < desc->nr_mask_regs; i++) {
+ struct intc_mask_reg *mr = desc->mask_regs + i;
+
+ mode = sh_intc_mode(address, mr->set_reg, mr->clr_reg);
+ if (mode == INTC_MODE_NONE)
+ continue;
+
+ *modep = mode;
+ *datap = &mr->value;
+ *enums = mr->enum_ids;
+ *first = mr->reg_width - 1;
+ *width = 1;
+ return;
+ }
+ }
+
+ if (desc->prio_regs) {
+ for (i = 0; i < desc->nr_prio_regs; i++) {
+ struct intc_prio_reg *pr = desc->prio_regs + i;
+
+ mode = sh_intc_mode(address, pr->set_reg, pr->clr_reg);
+ if (mode == INTC_MODE_NONE)
+ continue;
+
+ *modep = mode | INTC_MODE_IS_PRIO;
+ *datap = &pr->value;
+ *enums = pr->enum_ids;
+ *first = (pr->reg_width / pr->field_width) - 1;
+ *width = pr->field_width;
+ return;
+ }
+ }
+
+ assert(0);
+}
+
+static void sh_intc_toggle(struct intc_desc *desc, intc_enum id,
+ int enable, int is_group)
+{
+ struct intc_source *source = desc->sources + id;
+ int old = source->enable_count;
+
+ if (!id)
+ return;
+
+ if (!source->next_enum_id && (!source->enable_max || !source->vect)) {
+#ifdef DEBUG_INTC
+ printf("sh_intc: reserved interrupt source %d modified\n", id);
+#endif
+ return;
+ }
+
+ if (source->vect) {
+ if (enable)
+ source->enable_count++;
+ else
+ source->enable_count--;
+
+ if (source->enable_count == source->enable_max) {
+#ifdef DEBUG_INTC
+ printf("sh_intc: enabling interrupt source %d -> 0x%04x\n",
+ id, source->vect);
+#endif
+ }
+
+ if (old == source->enable_max) {
+#ifdef DEBUG_INTC
+ printf("sh_intc: disabling interrupt source %d -> 0x%04x\n",
+ id, source->vect);
+#endif
+ }
+ }
+#ifdef DEBUG_INTC
+ else {
+ printf("setting interrupt group %d to %d\n", id, !!enable);
+ }
+#endif
+
+ if ((is_group || !source->vect) && source->next_enum_id) {
+ sh_intc_toggle(desc, source->next_enum_id, enable, 1);
+ }
+
+#ifdef DEBUG_INTC
+ if (!source->vect) {
+ printf("setting interrupt group %d to %d - done\n", id, !!enable);
+ }
+#endif
+}
+
+static uint32_t sh_intc_read(void *opaque, target_phys_addr_t offset)
+{
+ struct intc_desc *desc = opaque;
+ intc_enum *enum_ids = NULL;
+ unsigned int first = 0;
+ unsigned int width = 0;
+ unsigned int mode = 0;
+ unsigned long *valuep;
+
+#ifdef DEBUG_INTC
+ printf("sh_intc_read 0x%lx\n", (unsigned long) offset);
+#endif
+
+ sh_intc_locate(desc, (unsigned long)offset, &valuep,
+ &enum_ids, &first, &width, &mode);
+ return *valuep;
+}
+
+static void sh_intc_write(void *opaque, target_phys_addr_t offset,
+ uint32_t value)
+{
+ struct intc_desc *desc = opaque;
+ intc_enum *enum_ids = NULL;
+ unsigned int first = 0;
+ unsigned int width = 0;
+ unsigned int mode = 0;
+ unsigned int k;
+ unsigned long *valuep;
+ unsigned long mask;
+
+#ifdef DEBUG_INTC
+ printf("sh_intc_write 0x%lx 0x%08x\n", (unsigned long) offset, value);
+#endif
+
+ sh_intc_locate(desc, (unsigned long)offset, &valuep,
+ &enum_ids, &first, &width, &mode);
+
+ switch (mode) {
+ case INTC_MODE_ENABLE_REG | INTC_MODE_IS_PRIO: break;
+ case INTC_MODE_DUAL_SET: value |= *valuep; break;
+ case INTC_MODE_DUAL_CLR: value = *valuep & ~value; break;
+ default: assert(0);
+ }
+
+ for (k = 0; k <= first; k++) {
+ mask = ((1 << width) - 1) << ((first - k) * width);
+
+ if ((*valuep & mask) == (value & mask))
+ continue;
+#if 0
+ printf("k = %d, first = %d, enum = %d, mask = 0x%08x\n",
+ k, first, enum_ids[k], (unsigned int)mask);
+#endif
+ sh_intc_toggle(desc, enum_ids[k], value & mask, 0);
+ }
+
+ *valuep = value;
+
+#ifdef DEBUG_INTC
+ printf("sh_intc_write 0x%lx -> 0x%08x\n", (unsigned long) offset, value);
+#endif
+}
+
+static CPUReadMemoryFunc *sh_intc_readfn[] = {
+ sh_intc_read,
+ sh_intc_read,
+ sh_intc_read
+};
+
+static CPUWriteMemoryFunc *sh_intc_writefn[] = {
+ sh_intc_write,
+ sh_intc_write,
+ sh_intc_write
+};
+
+struct intc_source *sh_intc_source(struct intc_desc *desc, intc_enum id)
+{
+ if (id)
+ return desc->sources + id;
+
+ return NULL;
+}
+
+static void sh_intc_register(struct intc_desc *desc,
+ unsigned long address)
+{
+ if (address)
+ cpu_register_physical_memory(INTC_A7(address), 4, desc->iomemtype);
+}
+
+static void sh_intc_register_source(struct intc_desc *desc,
+ intc_enum source,
+ struct intc_group *groups,
+ int nr_groups)
+{
+ unsigned int i, k;
+ struct intc_source *s;
+
+ if (desc->mask_regs) {
+ for (i = 0; i < desc->nr_mask_regs; i++) {
+ struct intc_mask_reg *mr = desc->mask_regs + i;
+
+ for (k = 0; k < INTC_ARRAY(mr->enum_ids); k++) {
+ if (mr->enum_ids[k] != source)
+ continue;
+
+ s = sh_intc_source(desc, mr->enum_ids[k]);
+ if (s)
+ s->enable_max++;
+ }
+ }
+ }
+
+ if (desc->prio_regs) {
+ for (i = 0; i < desc->nr_prio_regs; i++) {
+ struct intc_prio_reg *pr = desc->prio_regs + i;
+
+ for (k = 0; k < INTC_ARRAY(pr->enum_ids); k++) {
+ if (pr->enum_ids[k] != source)
+ continue;
+
+ s = sh_intc_source(desc, pr->enum_ids[k]);
+ if (s)
+ s->enable_max++;
+ }
+ }
+ }
+
+ if (groups) {
+ for (i = 0; i < nr_groups; i++) {
+ struct intc_group *gr = groups + i;
+
+ for (k = 0; k < INTC_ARRAY(gr->enum_ids); k++) {
+ if (gr->enum_ids[k] != source)
+ continue;
+
+ s = sh_intc_source(desc, gr->enum_ids[k]);
+ if (s)
+ s->enable_max++;
+ }
+ }
+ }
+
+}
+
+void sh_intc_register_sources(struct intc_desc *desc,
+ struct intc_vect *vectors,
+ int nr_vectors,
+ struct intc_group *groups,
+ int nr_groups)
+{
+ unsigned int i, k;
+ struct intc_source *s;
+
+ for (i = 0; i < nr_vectors; i++) {
+ struct intc_vect *vect = vectors + i;
+
+ sh_intc_register_source(desc, vect->enum_id, groups, nr_groups);
+ s = sh_intc_source(desc, vect->enum_id);
+ if (s)
+ s->vect = vect->vect;
+
+#ifdef DEBUG_INTC
+ printf("sh_intc: registered source %d -> 0x%04x (%d/%d)\n",
+ vect->enum_id, s->vect, s->enable_count, s->enable_max);
+#endif
+ }
+
+ if (groups) {
+ for (i = 0; i < nr_groups; i++) {
+ struct intc_group *gr = groups + i;
+
+ s = sh_intc_source(desc, gr->enum_id);
+ s->next_enum_id = gr->enum_ids[0];
+
+ for (k = 1; k < INTC_ARRAY(gr->enum_ids); k++) {
+ if (!gr->enum_ids[k])
+ continue;
+
+ s = sh_intc_source(desc, gr->enum_ids[k - 1]);
+ s->next_enum_id = gr->enum_ids[k];
+ }
+
+#ifdef DEBUG_INTC
+ printf("sh_intc: registered group %d (%d/%d)\n",
+ gr->enum_id, s->enable_count, s->enable_max);
+#endif
+ }
+ }
+}
+
+int sh_intc_init(struct intc_desc *desc,
+ int nr_sources,
+ struct intc_mask_reg *mask_regs,
+ int nr_mask_regs,
+ struct intc_prio_reg *prio_regs,
+ int nr_prio_regs)
+{
+ unsigned int i;
+
+ desc->nr_sources = nr_sources;
+ desc->mask_regs = mask_regs;
+ desc->nr_mask_regs = nr_mask_regs;
+ desc->prio_regs = prio_regs;
+ desc->nr_prio_regs = nr_prio_regs;
+
+ i = sizeof(struct intc_source) * nr_sources;
+ desc->sources = malloc(i);
+ if (!desc->sources)
+ return -1;
+
+ memset(desc->sources, 0, i);
+
+ desc->iomemtype = cpu_register_io_memory(0, sh_intc_readfn,
+ sh_intc_writefn, desc);
+ if (desc->mask_regs) {
+ for (i = 0; i < desc->nr_mask_regs; i++) {
+ struct intc_mask_reg *mr = desc->mask_regs + i;
+
+ sh_intc_register(desc, mr->set_reg);
+ sh_intc_register(desc, mr->clr_reg);
+ }
+ }
+
+ if (desc->prio_regs) {
+ for (i = 0; i < desc->nr_prio_regs; i++) {
+ struct intc_prio_reg *pr = desc->prio_regs + i;
+
+ sh_intc_register(desc, pr->set_reg);
+ sh_intc_register(desc, pr->clr_reg);
+ }
+ }
+
+ return 0;
+}
Added: trunk/src/host/qemu-neo1973/hw/sh_intc.h
===================================================================
--- trunk/src/host/qemu-neo1973/hw/sh_intc.h 2007-10-29 20:40:05 UTC (rev 3302)
+++ trunk/src/host/qemu-neo1973/hw/sh_intc.h 2007-10-29 21:14:04 UTC (rev 3303)
@@ -0,0 +1,69 @@
+#ifndef __SH_INTC_H__
+#define __SH_INTC_H__
+
+typedef unsigned char intc_enum;
+
+struct intc_vect {
+ intc_enum enum_id;
+ unsigned short vect;
+};
+
+#define INTC_VECT(enum_id, vect) { enum_id, vect }
+
+struct intc_group {
+ intc_enum enum_id;
+ intc_enum enum_ids[32];
+};
+
+#define INTC_GROUP(enum_id, ids...) { enum_id, { ids } }
+
+struct intc_mask_reg {
+ unsigned long set_reg, clr_reg, reg_width;
+ intc_enum enum_ids[32];
+ unsigned long value;
+};
+
+struct intc_prio_reg {
+ unsigned long set_reg, clr_reg, reg_width, field_width;
+ intc_enum enum_ids[16];
+ unsigned long value;
+};
+
+#define _INTC_ARRAY(a) a, sizeof(a)/sizeof(*a)
+
+struct intc_source {
+ unsigned short vect;
+ intc_enum next_enum_id;
+
+ int asserted;
+ int enable_count;
+ int enable_max;
+};
+
+struct intc_desc {
+ struct intc_source *sources;
+ int nr_sources;
+ struct intc_mask_reg *mask_regs;
+ int nr_mask_regs;
+ struct intc_prio_reg *prio_regs;
+ int nr_prio_regs;
+
+ int iomemtype;
+};
+
+struct intc_source *sh_intc_source(struct intc_desc *desc, intc_enum id);
+
+void sh_intc_register_sources(struct intc_desc *desc,
+ struct intc_vect *vectors,
+ int nr_vectors,
+ struct intc_group *groups,
+ int nr_groups);
+
+int sh_intc_init(struct intc_desc *desc,
+ int nr_sources,
+ struct intc_mask_reg *mask_regs,
+ int nr_mask_regs,
+ struct intc_prio_reg *prio_regs,
+ int nr_prio_regs);
+
+#endif /* __SH_INTC_H__ */
Added: trunk/src/host/qemu-neo1973/hw/sh_serial.c
===================================================================
--- trunk/src/host/qemu-neo1973/hw/sh_serial.c 2007-10-29 20:40:05 UTC (rev 3302)
+++ trunk/src/host/qemu-neo1973/hw/sh_serial.c 2007-10-29 21:14:04 UTC (rev 3303)
@@ -0,0 +1,315 @@
+/*
+ * QEMU SCI/SCIF serial port emulation
+ *
+ * Copyright (c) 2007 Magnus Damm
+ *
+ * Based on serial.c - QEMU 16450 UART emulation
+ * Copyright (c) 2003-2004 Fabrice Bellard
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+#include "vl.h"
+#include <assert.h>
+
+//#define DEBUG_SERIAL
+
+#define SH_SERIAL_FLAG_TEND (1 << 0)
+#define SH_SERIAL_FLAG_TDE (1 << 1)
+#define SH_SERIAL_FLAG_RDF (1 << 2)
+#define SH_SERIAL_FLAG_BRK (1 << 3)
+#define SH_SERIAL_FLAG_DR (1 << 4)
+
+typedef struct {
+ uint8_t smr;
+ uint8_t brr;
+ uint8_t scr;
+ uint8_t dr; /* ftdr / tdr */
+ uint8_t sr; /* fsr / ssr */
+ uint16_t fcr;
+ uint8_t sptr;
+
+ uint8_t rx_fifo[16]; /* frdr / rdr */
+ uint8_t rx_cnt;
+
+ target_phys_addr_t base;
+ int freq;
+ int feat;
+ int flags;
+
+ CharDriverState *chr;
+} sh_serial_state;
+
+static void sh_serial_ioport_write(void *opaque, uint32_t offs, uint32_t val)
+{
+ sh_serial_state *s = opaque;
+ unsigned char ch;
+
+#ifdef DEBUG_SERIAL
+ printf("sh_serial: write base=0x%08lx offs=0x%02x val=0x%02x\n",
+ (unsigned long) s->base, offs, val);
+#endif
+ switch(offs) {
+ case 0x00: /* SMR */
+ s->smr = val & ((s->feat & SH_SERIAL_FEAT_SCIF) ? 0x7b : 0xff);
+ return;
+ case 0x04: /* BRR */
+ s->brr = val;
+ return;
+ case 0x08: /* SCR */
+ s->scr = val & ((s->feat & SH_SERIAL_FEAT_SCIF) ? 0xfb : 0xff);
+ if (!(val & (1 << 5)))
+ s->flags |= SH_SERIAL_FLAG_TEND;
+ return;
+ case 0x0c: /* FTDR / TDR */
+ if (s->chr) {
+ ch = val;
+ qemu_chr_write(s->chr, &ch, 1);
+ }
+ s->dr = val;
+ s->flags &= ~SH_SERIAL_FLAG_TDE;
+ return;
+#if 0
+ case 0x14: /* FRDR / RDR */
+ ret = 0;
+ break;
+#endif
+ }
+ if (s->feat & SH_SERIAL_FEAT_SCIF) {
+ switch(offs) {
+ case 0x10: /* FSR */
+ if (!(val & (1 << 6)))
+ s->flags &= ~SH_SERIAL_FLAG_TEND;
+ if (!(val & (1 << 5)))
+ s->flags &= ~SH_SERIAL_FLAG_TDE;
+ if (!(val & (1 << 4)))
+ s->flags &= ~SH_SERIAL_FLAG_BRK;
+ if (!(val & (1 << 1)))
+ s->flags &= ~SH_SERIAL_FLAG_RDF;
+ if (!(val & (1 << 0)))
+ s->flags &= ~SH_SERIAL_FLAG_DR;
+ return;
+ case 0x18: /* FCR */
+ s->fcr = val;
+ return;
+ case 0x20: /* SPTR */
+ s->sptr = val;
+ return;
+ case 0x24: /* LSR */
+ return;
+ }
+ }
+ else {
+#if 0
+ switch(offs) {
+ case 0x0c:
+ ret = s->dr;
+ break;
+ case 0x10:
+ ret = 0;
+ break;
+ case 0x1c:
+ ret = s->sptr;
+ break;
+ }
+#endif
+ }
+
+ fprintf(stderr, "sh_serial: unsupported write to 0x%02x\n", offs);
+ assert(0);
+}
+
+static uint32_t sh_serial_ioport_read(void *opaque, uint32_t offs)
+{
+ sh_serial_state *s = opaque;
+ uint32_t ret = ~0;
+
+#if 0
+ switch(offs) {
+ case 0x00:
+ ret = s->smr;
+ break;
+ case 0x04:
+ ret = s->brr;
+ break;
+ case 0x08:
+ ret = s->scr;
+ break;
+ case 0x14:
+ ret = 0;
+ break;
+ }
+#endif
+ if (s->feat & SH_SERIAL_FEAT_SCIF) {
+ switch(offs) {
+ case 0x10: /* FSR */
+ ret = 0;
+ if (s->flags & SH_SERIAL_FLAG_TEND)
+ ret |= (1 << 6);
+ if (s->flags & SH_SERIAL_FLAG_TDE)
+ ret |= (1 << 5);
+ if (s->flags & SH_SERIAL_FLAG_BRK)
+ ret |= (1 << 4);
+ if (s->flags & SH_SERIAL_FLAG_RDF)
+ ret |= (1 << 1);
+ if (s->flags & SH_SERIAL_FLAG_DR)
+ ret |= (1 << 0);
+
+ if (s->scr & (1 << 5))
+ s->flags |= SH_SERIAL_FLAG_TDE | SH_SERIAL_FLAG_TEND;
+
+ break;
+#if 0
+ case 0x18:
+ ret = s->fcr;
+ break;
+#endif
+ case 0x1c:
+ ret = s->rx_cnt;
+ break;
+ case 0x20:
+ ret = s->sptr;
+ break;
+ case 0x24:
+ ret = 0;
+ break;
+ }
+ }
+ else {
+#if 0
+ switch(offs) {
+ case 0x0c:
+ ret = s->dr;
+ break;
+ case 0x10:
+ ret = 0;
+ break;
+ case 0x1c:
+ ret = s->sptr;
+ break;
+ }
+#endif
+ }
+#ifdef DEBUG_SERIAL
+ printf("sh_serial: read base=0x%08lx offs=0x%02x val=0x%x\n",
+ (unsigned long) s->base, offs, ret);
+#endif
+
+ if (ret & ~((1 << 16) - 1)) {
+ fprintf(stderr, "sh_serial: unsupported read from 0x%02x\n", offs);
+ assert(0);
+ }
+
+ return ret;
+}
+
+static int sh_serial_can_receive(sh_serial_state *s)
+{
+ return 0;
+}
+
+static void sh_serial_receive_byte(sh_serial_state *s, int ch)
+{
+}
+
+static void sh_serial_receive_break(sh_serial_state *s)
+{
+}
+
+static int sh_serial_can_receive1(void *opaque)
+{
+ sh_serial_state *s = opaque;
+ return sh_serial_can_receive(s);
+}
+
+static void sh_serial_receive1(void *opaque, const uint8_t *buf, int size)
+{
+ sh_serial_state *s = opaque;
+ sh_serial_receive_byte(s, buf[0]);
+}
+
+static void sh_serial_event(void *opaque, int event)
+{
+ sh_serial_state *s = opaque;
+ if (event == CHR_EVENT_BREAK)
+ sh_serial_receive_break(s);
+}
+
+uint32_t sh_serial_read (void *opaque, target_phys_addr_t addr)
+{
+ sh_serial_state *s = opaque;
+ return sh_serial_ioport_read(s, addr - s->base);
+}
+
+void sh_serial_write (void *opaque,
+ target_phys_addr_t addr, uint32_t value)
+{
+ sh_serial_state *s = opaque;
+ sh_serial_ioport_write(s, addr - s->base, value);
+}
+
+static CPUReadMemoryFunc *sh_serial_readfn[] = {
+ &sh_serial_read,
+ &sh_serial_read,
+ &sh_serial_read,
+};
+
+static CPUWriteMemoryFunc *sh_serial_writefn[] = {
+ &sh_serial_write,
+ &sh_serial_write,
+ &sh_serial_write,
+};
+
+void sh_serial_init (target_phys_addr_t base, int feat,
+ uint32_t freq, CharDriverState *chr)
+{
+ sh_serial_state *s;
+ int s_io_memory;
+
+ s = qemu_mallocz(sizeof(sh_serial_state));
+ if (!s)
+ return;
+
+ s->base = base;
+ s->feat = feat;
+ s->flags = SH_SERIAL_FLAG_TEND | SH_SERIAL_FLAG_TDE;
+
+ s->smr = 0;
+ s->brr = 0xff;
+ s->scr = 0;
+ s->sptr = 0;
+
+ if (feat & SH_SERIAL_FEAT_SCIF) {
+ s->fcr = 0;
+ }
+ else {
+ s->dr = 0xff;
+ }
+
+ s->rx_cnt = 0;
+
+ s_io_memory = cpu_register_io_memory(0, sh_serial_readfn,
+ sh_serial_writefn, s);
+ cpu_register_physical_memory(base, 0x28, s_io_memory);
+
+ s->chr = chr;
+
+ if (chr)
+ qemu_chr_add_handlers(chr, sh_serial_can_receive1, sh_serial_receive1,
+ sh_serial_event, s);
+}
Added: trunk/src/host/qemu-neo1973/hw/sh_timer.c
===================================================================
--- trunk/src/host/qemu-neo1973/hw/sh_timer.c 2007-10-29 20:40:05 UTC (rev 3302)
+++ trunk/src/host/qemu-neo1973/hw/sh_timer.c 2007-10-29 21:14:04 UTC (rev 3303)
@@ -0,0 +1,323 @@
+/*
+ * SuperH Timer modules.
+ *
+ * Copyright (c) 2007 Magnus Damm
+ * Based on arm_timer.c by Paul Brook
+ * Copyright (c) 2005-2006 CodeSourcery.
+ *
+ * This code is licenced under the GPL.
+ */
+
+#include "vl.h"
+
+//#define DEBUG_TIMER
+
+#define TIMER_TCR_TPSC (7 << 0)
+#define TIMER_TCR_CKEG (3 << 3)
+#define TIMER_TCR_UNIE (1 << 5)
+#define TIMER_TCR_ICPE (3 << 6)
+#define TIMER_TCR_UNF (1 << 8)
+#define TIMER_TCR_ICPF (1 << 9)
+#define TIMER_TCR_RESERVED (0x3f << 10)
+
+#define TIMER_FEAT_CAPT (1 << 0)
+#define TIMER_FEAT_EXTCLK (1 << 1)
+
+typedef struct {
+ ptimer_state *timer;
+ uint32_t tcnt;
+ uint32_t tcor;
+ uint32_t tcr;
+ uint32_t tcpr;
+ int freq;
+ int int_level;
+ int feat;
+ int enabled;
+ qemu_irq irq;
+} sh_timer_state;
+
+/* Check all active timers, and schedule the next timer interrupt. */
+
+static void sh_timer_update(sh_timer_state *s)
+{
+#if 0 /* not yet */
+ /* Update interrupts. */
+ if (s->int_level && (s->tcr & TIMER_TCR_UNIE)) {
+ qemu_irq_raise(s->irq);
+ } else {
+ qemu_irq_lower(s->irq);
+ }
+#endif
+}
+
+uint32_t sh_timer_read(void *opaque, target_phys_addr_t offset)
+{
+ sh_timer_state *s = (sh_timer_state *)opaque;
+
+ switch (offset >> 2) {
+ case 0:
+ return s->tcor;
+ case 1:
+ return ptimer_get_count(s->timer);
+ case 2:
+ return s->tcr | (s->int_level ? TIMER_TCR_UNF : 0);
+ case 3:
+ if (s->feat & TIMER_FEAT_CAPT)
+ return s->tcpr;
+ default:
+ cpu_abort (cpu_single_env, "sh_timer_read: Bad offset %x\n",
+ (int)offset);
+ return 0;
+ }
+}
+
+static void sh_timer_write(void *opaque, target_phys_addr_t offset,
+ uint32_t value)
+{
+ sh_timer_state *s = (sh_timer_state *)opaque;
+ int freq;
+
+ switch (offset >> 2) {
+ case 0:
+ s->tcor = value;
+ ptimer_set_limit(s->timer, s->tcor, 0);
+ break;
+ case 1:
+ s->tcnt = value;
+ ptimer_set_count(s->timer, s->tcnt);
+ break;
+ case 2:
+ if (s->enabled) {
+ /* Pause the timer if it is running. This may cause some
+ inaccuracy dure to rounding, but avoids a whole lot of other
+ messyness. */
+ ptimer_stop(s->timer);
+ }
+ freq = s->freq;
+ /* ??? Need to recalculate expiry time after changing divisor. */
+ switch (value & TIMER_TCR_TPSC) {
+ case 0: freq >>= 2; break;
+ case 1: freq >>= 4; break;
+ case 2: freq >>= 6; break;
+ case 3: freq >>= 8; break;
+ case 4: freq >>= 10; break;
+ case 6:
+ case 7: if (s->feat & TIMER_FEAT_EXTCLK) break;
+ default: cpu_abort (cpu_single_env,
+ "sh_timer_write: Reserved TPSC value\n"); break;
+ }
+ switch ((value & TIMER_TCR_CKEG) >> 3) {
+ case 0: break;
+ case 1:
+ case 2:
+ case 3: if (s->feat & TIMER_FEAT_EXTCLK) break;
+ default: cpu_abort (cpu_single_env,
+ "sh_timer_write: Reserved CKEG value\n"); break;
+ }
+ switch ((value & TIMER_TCR_ICPE) >> 6) {
+ case 0: break;
+ case 2:
+ case 3: if (s->feat & TIMER_FEAT_CAPT) break;
+ default: cpu_abort (cpu_single_env,
+ "sh_timer_write: Reserved ICPE value\n"); break;
+ }
+ if ((value & TIMER_TCR_UNF) == 0)
+ s->int_level = 0;
+
+ value &= ~TIMER_TCR_UNF;
+
+ if ((value & TIMER_TCR_ICPF) && (!(s->feat & TIMER_FEAT_CAPT)))
+ cpu_abort (cpu_single_env,
+ "sh_timer_write: Reserved ICPF value\n");
+
+ value &= ~TIMER_TCR_ICPF; /* capture not supported */
+
+ if (value & TIMER_TCR_RESERVED)
+ cpu_abort (cpu_single_env,
+ "sh_timer_write: Reserved TCR bits set\n");
+ s->tcr = value;
+ ptimer_set_limit(s->timer, s->tcor, 0);
+ ptimer_set_freq(s->timer, freq);
+ if (s->enabled) {
+ /* Restart the timer if still enabled. */
+ ptimer_run(s->timer, 0);
+ }
+ break;
+ case 3:
+ if (s->feat & TIMER_FEAT_CAPT) {
+ s->tcpr = value;
+ break;
+ }
+ default:
+ cpu_abort (cpu_single_env, "sh_timer_write: Bad offset %x\n",
+ (int)offset);
+ }
+ sh_timer_update(s);
+}
+
+static void sh_timer_start_stop(void *opaque, int enable)
+{
+ sh_timer_state *s = (sh_timer_state *)opaque;
+
+#ifdef DEBUG_TIMER
+ printf("sh_timer_start_stop %d (%d)\n", enable, s->enabled);
+#endif
+
+ if (s->enabled && !enable) {
+ ptimer_stop(s->timer);
+ }
+ if (!s->enabled && enable) {
+ ptimer_run(s->timer, 0);
+ }
+ s->enabled = !!enable;
+
+#ifdef DEBUG_TIMER
+ printf("sh_timer_start_stop done %d\n", s->enabled);
+#endif
+}
+
+static void sh_timer_tick(void *opaque)
+{
+ sh_timer_state *s = (sh_timer_state *)opaque;
+ s->int_level = s->enabled;
+ sh_timer_update(s);
+}
+
+static void *sh_timer_init(uint32_t freq, int feat)
+{
+ sh_timer_state *s;
+ QEMUBH *bh;
+
+ s = (sh_timer_state *)qemu_mallocz(sizeof(sh_timer_state));
+ s->freq = freq;
+ s->feat = feat;
+ s->tcor = 0xffffffff;
+ s->tcnt = 0xffffffff;
+ s->tcpr = 0xdeadbeef;
+ s->tcor = 0;
+ s->enabled = 0;
+
+ bh = qemu_bh_new(sh_timer_tick, s);
+ s->timer = ptimer_init(bh);
+ /* ??? Save/restore. */
+ return s;
+}
+
+typedef struct {
+ void *timer[3];
+ int level[3];
+ uint32_t tocr;
+ uint32_t tstr;
+ target_phys_addr_t base;
+ int feat;
+} tmu012_state;
+
+static uint32_t tmu012_read(void *opaque, target_phys_addr_t offset)
+{
+ tmu012_state *s = (tmu012_state *)opaque;
+
+#ifdef DEBUG_TIMER
+ printf("tmu012_read 0x%lx\n", (unsigned long) offset);
+#endif
+ offset -= s->base;
+
+ if (offset >= 0x20) {
+ if (!(s->feat & TMU012_FEAT_3CHAN))
+ cpu_abort (cpu_single_env, "tmu012_write: Bad channel offset %x\n",
+ (int)offset);
+ return sh_timer_read(s->timer[2], offset - 0x20);
+ }
+
+ if (offset >= 0x14)
+ return sh_timer_read(s->timer[1], offset - 0x14);
+
+ if (offset >= 0x08)
+ return sh_timer_read(s->timer[0], offset - 0x08);
+
+ if (offset == 4)
+ return s->tstr;
+
+ if ((s->feat & TMU012_FEAT_TOCR) && offset == 0)
+ return s->tocr;
+
+ cpu_abort (cpu_single_env, "tmu012_write: Bad offset %x\n",
+ (int)offset);
+ return 0;
+}
+
+static void tmu012_write(void *opaque, target_phys_addr_t offset,
+ uint32_t value)
+{
+ tmu012_state *s = (tmu012_state *)opaque;
+
+#ifdef DEBUG_TIMER
+ printf("tmu012_write 0x%lx 0x%08x\n", (unsigned long) offset, value);
+#endif
+ offset -= s->base;
+
+ if (offset >= 0x20) {
+ if (!(s->feat & TMU012_FEAT_3CHAN))
+ cpu_abort (cpu_single_env, "tmu012_write: Bad channel offset %x\n",
+ (int)offset);
+ sh_timer_write(s->timer[2], offset - 0x20, value);
+ return;
+ }
+
+ if (offset >= 0x14) {
+ sh_timer_write(s->timer[1], offset - 0x14, value);
+ return;
+ }
+
+ if (offset >= 0x08) {
+ sh_timer_write(s->timer[0], offset - 0x08, value);
+ return;
+ }
+
+ if (offset == 4) {
+ sh_timer_start_stop(s->timer[0], value & (1 << 0));
+ sh_timer_start_stop(s->timer[1], value & (1 << 1));
+ if (s->feat & TMU012_FEAT_3CHAN)
+ sh_timer_start_stop(s->timer[2], value & (1 << 2));
+ else
+ if (value & (1 << 2))
+ cpu_abort (cpu_single_env, "tmu012_write: Bad channel\n");
+
+ s->tstr = value;
+ return;
+ }
+
+ if ((s->feat & TMU012_FEAT_TOCR) && offset == 0) {
+ s->tocr = value & (1 << 0);
+ }
+}
+
+static CPUReadMemoryFunc *tmu012_readfn[] = {
+ tmu012_read,
+ tmu012_read,
+ tmu012_read
+};
+
+static CPUWriteMemoryFunc *tmu012_writefn[] = {
+ tmu012_write,
+ tmu012_write,
+ tmu012_write
+};
+
+void tmu012_init(uint32_t base, int feat, uint32_t freq)
+{
+ int iomemtype;
+ tmu012_state *s;
+ int timer_feat = (feat & TMU012_FEAT_EXTCLK) ? TIMER_FEAT_EXTCLK : 0;
+
+ s = (tmu012_state *)qemu_mallocz(sizeof(tmu012_state));
+ s->base = base;
+ s->feat = feat;
+ s->timer[0] = sh_timer_init(freq, timer_feat);
+ s->timer[1] = sh_timer_init(freq, timer_feat);
+ if (feat & TMU012_FEAT_3CHAN)
+ s->timer[2] = sh_timer_init(freq, timer_feat | TIMER_FEAT_CAPT);
+ iomemtype = cpu_register_io_memory(0, tmu012_readfn,
+ tmu012_writefn, s);
+ cpu_register_physical_memory(base, 0x00001000, iomemtype);
+ /* ??? Save/restore. */
+}
Modified: trunk/src/host/qemu-neo1973/hw/shix.c
===================================================================
--- trunk/src/host/qemu-neo1973/hw/shix.c 2007-10-29 20:40:05 UTC (rev 3302)
+++ trunk/src/host/qemu-neo1973/hw/shix.c 2007-10-29 21:14:04 UTC (rev 3303)
@@ -83,12 +83,14 @@
cpu_register_physical_memory(0x0c000000, 0x01000000, 0x01004000);
/* Load BIOS in 0 (and access it through P2, 0xA0000000) */
- printf("%s: load BIOS '%s'\n", __func__, BIOS_FILENAME);
- ret = load_image(BIOS_FILENAME, phys_ram_base);
+ if (bios_name == NULL)
+ bios_name = BIOS_FILENAME;
+ printf("%s: load BIOS '%s'\n", __func__, bios_name);
+ ret = load_image(bios_name, phys_ram_base);
if (ret < 0) { /* Check bios size */
fprintf(stderr, "ret=%d\n", ret);
fprintf(stderr, "qemu: could not load SHIX bios '%s'\n",
- BIOS_FILENAME);
+ bios_name);
exit(1);
}
Modified: trunk/src/host/qemu-neo1973/hw/slavio_intctl.c
===================================================================
--- trunk/src/host/qemu-neo1973/hw/slavio_intctl.c 2007-10-29 20:40:05 UTC (rev 3302)
+++ trunk/src/host/qemu-neo1973/hw/slavio_intctl.c 2007-10-29 21:14:04 UTC (rev 3303)
@@ -100,21 +100,21 @@
DPRINTF("write cpu %d reg 0x" TARGET_FMT_plx " = %x\n", cpu, addr, val);
switch (saddr) {
case 1: // clear pending softints
- if (val & 0x4000)
- val |= 80000000;
- val &= 0xfffe0000;
- s->intreg_pending[cpu] &= ~val;
+ if (val & 0x4000)
+ val |= 80000000;
+ val &= 0xfffe0000;
+ s->intreg_pending[cpu] &= ~val;
slavio_check_interrupts(s);
- DPRINTF("Cleared cpu %d irq mask %x, curmask %x\n", cpu, val, s->intreg_pending[cpu]);
- break;
+ DPRINTF("Cleared cpu %d irq mask %x, curmask %x\n", cpu, val, s->intreg_pending[cpu]);
+ break;
case 2: // set softint
- val &= 0xfffe0000;
- s->intreg_pending[cpu] |= val;
+ val &= 0xfffe0000;
+ s->intreg_pending[cpu] |= val;
slavio_check_interrupts(s);
- DPRINTF("Set cpu %d irq mask %x, curmask %x\n", cpu, val, s->intreg_pending[cpu]);
- break;
+ DPRINTF("Set cpu %d irq mask %x, curmask %x\n", cpu, val, s->intreg_pending[cpu]);
+ break;
default:
- break;
+ break;
}
}
@@ -165,27 +165,27 @@
DPRINTF("write system reg 0x" TARGET_FMT_plx " = %x\n", addr, val);
switch (saddr) {
case 2: // clear (enable)
- // Force clear unused bits
- val &= ~0x4fb2007f;
- s->intregm_disabled &= ~val;
- DPRINTF("Enabled master irq mask %x, curmask %x\n", val, s->intregm_disabled);
- slavio_check_interrupts(s);
- break;
+ // Force clear unused bits
+ val &= ~0x4fb2007f;
+ s->intregm_disabled &= ~val;
+ DPRINTF("Enabled master irq mask %x, curmask %x\n", val, s->intregm_disabled);
+ slavio_check_interrupts(s);
+ break;
case 3: // set (disable, clear pending)
- // Force clear unused bits
- val &= ~0x4fb2007f;
- s->intregm_disabled |= val;
- s->intregm_pending &= ~val;
+ // Force clear unused bits
+ val &= ~0x4fb2007f;
+ s->intregm_disabled |= val;
+ s->intregm_pending &= ~val;
slavio_check_interrupts(s);
- DPRINTF("Disabled master irq mask %x, curmask %x\n", val, s->intregm_disabled);
- break;
+ DPRINTF("Disabled master irq mask %x, curmask %x\n", val, s->intregm_disabled);
+ break;
case 4:
- s->target_cpu = val & (MAX_CPUS - 1);
+ s->target_cpu = val & (MAX_CPUS - 1);
slavio_check_interrupts(s);
- DPRINTF("Set master irq cpu %d\n", s->target_cpu);
- break;
+ DPRINTF("Set master irq cpu %d\n", s->target_cpu);
+ break;
default:
- break;
+ break;
}
}
@@ -207,7 +207,7 @@
int i;
for (i = 0; i < MAX_CPUS; i++) {
- term_printf("per-cpu %d: pending 0x%08x\n", i, s->intreg_pending[i]);
+ term_printf("per-cpu %d: pending 0x%08x\n", i, s->intreg_pending[i]);
}
term_printf("master: pending 0x%08x, disabled 0x%08x\n", s->intregm_pending, s->intregm_disabled);
}
@@ -310,7 +310,7 @@
int i;
for (i = 0; i < MAX_CPUS; i++) {
- qemu_put_be32s(f, &s->intreg_pending[i]);
+ qemu_put_be32s(f, &s->intreg_pending[i]);
}
qemu_put_be32s(f, &s->intregm_pending);
qemu_put_be32s(f, &s->intregm_disabled);
@@ -326,7 +326,7 @@
return -EINVAL;
for (i = 0; i < MAX_CPUS; i++) {
- qemu_get_be32s(f, &s->intreg_pending[i]);
+ qemu_get_be32s(f, &s->intreg_pending[i]);
}
qemu_get_be32s(f, &s->intregm_pending);
qemu_get_be32s(f, &s->intregm_disabled);
@@ -341,7 +341,7 @@
int i;
for (i = 0; i < MAX_CPUS; i++) {
- s->intreg_pending[i] = 0;
+ s->intreg_pending[i] = 0;
}
s->intregm_disabled = ~0xffb2007f;
s->intregm_pending = 0;
@@ -363,8 +363,8 @@
s->intbit_to_level = intbit_to_level;
for (i = 0; i < MAX_CPUS; i++) {
- slavio_intctl_io_memory = cpu_register_io_memory(0, slavio_intctl_mem_read, slavio_intctl_mem_write, s);
- cpu_register_physical_memory(addr + i * TARGET_PAGE_SIZE, INTCTL_SIZE,
+ slavio_intctl_io_memory = cpu_register_io_memory(0, slavio_intctl_mem_read, slavio_intctl_mem_write, s);
+ cpu_register_physical_memory(addr + i * TARGET_PAGE_SIZE, INTCTL_SIZE,
slavio_intctl_io_memory);
s->cpu_irqs[i] = parent_irq[i];
}
Modified: trunk/src/host/qemu-neo1973/hw/slavio_misc.c
===================================================================
--- trunk/src/host/qemu-neo1973/hw/slavio_misc.c 2007-10-29 20:40:05 UTC (rev 3302)
+++ trunk/src/host/qemu-neo1973/hw/slavio_misc.c 2007-10-29 21:14:04 UTC (rev 3303)
@@ -76,9 +76,9 @@
MISC_DPRINTF("Power fail: %d, config: %d\n", power_failing, s->config);
if (power_failing && (s->config & 0x8)) {
- s->aux2 |= 0x4;
+ s->aux2 |= 0x4;
} else {
- s->aux2 &= ~0x4;
+ s->aux2 &= ~0x4;
}
slavio_misc_update_irq(s);
}
@@ -89,44 +89,44 @@
switch (addr & 0xfff0000) {
case 0x1800000:
- MISC_DPRINTF("Write config %2.2x\n", val & 0xff);
- s->config = val & 0xff;
- slavio_misc_update_irq(s);
- break;
+ MISC_DPRINTF("Write config %2.2x\n", val & 0xff);
+ s->config = val & 0xff;
+ slavio_misc_update_irq(s);
+ break;
case 0x1900000:
- MISC_DPRINTF("Write aux1 %2.2x\n", val & 0xff);
- s->aux1 = val & 0xff;
- break;
+ MISC_DPRINTF("Write aux1 %2.2x\n", val & 0xff);
+ s->aux1 = val & 0xff;
+ break;
case 0x1910000:
- val &= 0x3;
- MISC_DPRINTF("Write aux2 %2.2x\n", val);
- val |= s->aux2 & 0x4;
- if (val & 0x2) // Clear Power Fail int
- val &= 0x1;
- s->aux2 = val;
- if (val & 1)
- qemu_system_shutdown_request();
- slavio_misc_update_irq(s);
- break;
+ val &= 0x3;
+ MISC_DPRINTF("Write aux2 %2.2x\n", val);
+ val |= s->aux2 & 0x4;
+ if (val & 0x2) // Clear Power Fail int
+ val &= 0x1;
+ s->aux2 = val;
+ if (val & 1)
+ qemu_system_shutdown_request();
+ slavio_misc_update_irq(s);
+ break;
case 0x1a00000:
- MISC_DPRINTF("Write diag %2.2x\n", val & 0xff);
- s->diag = val & 0xff;
- break;
+ MISC_DPRINTF("Write diag %2.2x\n", val & 0xff);
+ s->diag = val & 0xff;
+ break;
case 0x1b00000:
- MISC_DPRINTF("Write modem control %2.2x\n", val & 0xff);
- s->mctrl = val & 0xff;
- break;
+ 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;
+ 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);
+ MISC_DPRINTF("Write power management %2.2x\n", val & 0xff);
cpu_interrupt(cpu_single_env, CPU_INTERRUPT_HALT);
- break;
+ break;
}
}
@@ -137,32 +137,32 @@
switch (addr & 0xfff0000) {
case 0x1800000:
- ret = s->config;
- MISC_DPRINTF("Read config %2.2x\n", ret);
- break;
+ ret = s->config;
+ MISC_DPRINTF("Read config %2.2x\n", ret);
+ break;
case 0x1900000:
- ret = s->aux1;
- MISC_DPRINTF("Read aux1 %2.2x\n", ret);
- break;
+ ret = s->aux1;
+ MISC_DPRINTF("Read aux1 %2.2x\n", ret);
+ break;
case 0x1910000:
- ret = s->aux2;
- MISC_DPRINTF("Read aux2 %2.2x\n", ret);
- break;
+ ret = s->aux2;
+ MISC_DPRINTF("Read aux2 %2.2x\n", ret);
+ break;
case 0x1a00000:
- ret = s->diag;
- MISC_DPRINTF("Read diag %2.2x\n", ret);
- break;
+ ret = s->diag;
+ MISC_DPRINTF("Read diag %2.2x\n", ret);
+ break;
case 0x1b00000:
- ret = s->mctrl;
- MISC_DPRINTF("Read modem control %2.2x\n", ret);
- break;
+ 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;
+ 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;
+ MISC_DPRINTF("Read power management %2.2x\n", ret);
+ break;
}
return ret;
}
Modified: trunk/src/host/qemu-neo1973/hw/slavio_serial.c
===================================================================
--- trunk/src/host/qemu-neo1973/hw/slavio_serial.c 2007-10-29 20:40:05 UTC (rev 3302)
+++ trunk/src/host/qemu-neo1973/hw/slavio_serial.c 2007-10-29 21:14:04 UTC (rev 3303)
@@ -95,6 +95,7 @@
uint8_t rx, tx, wregs[16], rregs[16];
SERIOQueue queue;
CharDriverState *chr;
+ int e0_mode, led_mode, caps_lock_mode, num_lock_mode;
} ChannelState;
struct SerialState {
@@ -138,7 +139,7 @@
int val;
if (q->count == 0) {
- return 0;
+ return 0;
} else {
val = q->data[q->rptr];
if (++q->rptr == SERIO_QUEUE_SIZE)
@@ -147,17 +148,17 @@
}
SER_DPRINTF("channel %c get 0x%02x\n", CHN_C(s), val);
if (q->count > 0)
- serial_receive_byte(s, 0);
+ serial_receive_byte(s, 0);
return val;
}
static int slavio_serial_update_irq_chn(ChannelState *s)
{
if ((s->wregs[1] & 1) && // interrupts enabled
- (((s->wregs[1] & 2) && s->txint == 1) || // tx ints enabled, pending
- ((((s->wregs[1] & 0x18) == 8) || ((s->wregs[1] & 0x18) == 0x10)) &&
- s->rxint == 1) || // rx ints enabled, pending
- ((s->wregs[15] & 0x80) && (s->rregs[0] & 0x80)))) { // break int e&p
+ (((s->wregs[1] & 2) && s->txint == 1) || // tx ints enabled, pending
+ ((((s->wregs[1] & 0x18) == 8) || ((s->wregs[1] & 0x18) == 0x10)) &&
+ s->rxint == 1) || // rx ints enabled, pending
+ ((s->wregs[15] & 0x80) && (s->rregs[0] & 0x80)))) { // break int e&p
return 1;
}
return 0;
@@ -180,8 +181,8 @@
s->reg = 0;
for (i = 0; i < SERIAL_SIZE; i++) {
- s->rregs[i] = 0;
- s->wregs[i] = 0;
+ s->rregs[i] = 0;
+ s->wregs[i] = 0;
}
s->wregs[4] = 4;
s->wregs[9] = 0xc0;
@@ -194,6 +195,7 @@
s->rx = s->tx = 0;
s->rxint = s->txint = 0;
s->rxint_under_svc = s->txint_under_svc = 0;
+ s->e0_mode = s->led_mode = s->caps_lock_mode = s->num_lock_mode = 0;
clear_queue(s);
}
@@ -365,82 +367,82 @@
s = &serial->chn[channel];
switch (saddr) {
case 0:
- SER_DPRINTF("Write channel %c, reg[%d] = %2.2x\n", CHN_C(s), s->reg, val & 0xff);
- newreg = 0;
- switch (s->reg) {
- case 0:
- newreg = val & 7;
- val &= 0x38;
- switch (val) {
- case 8:
- newreg |= 0x8;
- break;
- case 0x28:
+ SER_DPRINTF("Write channel %c, reg[%d] = %2.2x\n", CHN_C(s), s->reg, val & 0xff);
+ newreg = 0;
+ switch (s->reg) {
+ case 0:
+ newreg = val & 7;
+ val &= 0x38;
+ switch (val) {
+ case 8:
+ newreg |= 0x8;
+ break;
+ case 0x28:
clr_txint(s);
- break;
- case 0x38:
+ break;
+ case 0x38:
if (s->rxint_under_svc)
clr_rxint(s);
else if (s->txint_under_svc)
clr_txint(s);
- break;
- default:
- break;
- }
- break;
+ break;
+ default:
+ break;
+ }
+ break;
case 1 ... 3:
case 6 ... 8:
case 10 ... 11:
case 14 ... 15:
- s->wregs[s->reg] = val;
- break;
+ s->wregs[s->reg] = val;
+ break;
case 4:
case 5:
case 12:
case 13:
- s->wregs[s->reg] = val;
+ s->wregs[s->reg] = val;
slavio_serial_update_parameters(s);
- break;
- case 9:
- switch (val & 0xc0) {
- case 0:
- default:
- break;
- case 0x40:
- slavio_serial_reset_chn(&serial->chn[1]);
- return;
- case 0x80:
- slavio_serial_reset_chn(&serial->chn[0]);
- return;
- case 0xc0:
- slavio_serial_reset(serial);
- return;
- }
- break;
- default:
- break;
- }
- if (s->reg == 0)
- s->reg = newreg;
- else
- s->reg = 0;
- break;
+ break;
+ case 9:
+ switch (val & 0xc0) {
+ case 0:
+ default:
+ break;
+ case 0x40:
+ slavio_serial_reset_chn(&serial->chn[1]);
+ return;
+ case 0x80:
+ slavio_serial_reset_chn(&serial->chn[0]);
+ return;
+ case 0xc0:
+ slavio_serial_reset(serial);
+ return;
+ }
+ break;
+ default:
+ break;
+ }
+ if (s->reg == 0)
+ s->reg = newreg;
+ else
+ s->reg = 0;
+ break;
case 1:
- SER_DPRINTF("Write channel %c, ch %d\n", CHN_C(s), val);
+ SER_DPRINTF("Write channel %c, ch %d\n", CHN_C(s), val);
s->tx = val;
- if (s->wregs[5] & 8) { // tx enabled
- if (s->chr)
- qemu_chr_write(s->chr, &s->tx, 1);
- else if (s->type == kbd) {
- handle_kbd_command(s, val);
- }
- }
+ if (s->wregs[5] & 8) { // tx enabled
+ if (s->chr)
+ qemu_chr_write(s->chr, &s->tx, 1);
+ else if (s->type == kbd) {
+ handle_kbd_command(s, val);
+ }
+ }
s->rregs[0] |= 4; // Tx buffer empty
s->rregs[1] |= 1; // All sent
set_txint(s);
- break;
+ break;
default:
- break;
+ break;
}
}
@@ -457,21 +459,21 @@
s = &serial->chn[channel];
switch (saddr) {
case 0:
- SER_DPRINTF("Read channel %c, reg[%d] = %2.2x\n", CHN_C(s), s->reg, s->rregs[s->reg]);
- ret = s->rregs[s->reg];
- s->reg = 0;
- return ret;
+ SER_DPRINTF("Read channel %c, reg[%d] = %2.2x\n", CHN_C(s), s->reg, s->rregs[s->reg]);
+ ret = s->rregs[s->reg];
+ s->reg = 0;
+ return ret;
case 1:
- s->rregs[0] &= ~1;
+ s->rregs[0] &= ~1;
clr_rxint(s);
- if (s->type == kbd || s->type == mouse)
- ret = get_queue(s);
- else
- ret = s->rx;
- SER_DPRINTF("Read channel %c, ch %d\n", CHN_C(s), ret);
- return ret;
+ if (s->type == kbd || s->type == mouse)
+ ret = get_queue(s);
+ else
+ ret = s->rx;
+ SER_DPRINTF("Read channel %c, ch %d\n", CHN_C(s), ret);
+ return ret;
default:
- break;
+ break;
}
return 0;
}
@@ -482,10 +484,10 @@
int ret;
if (((s->wregs[3] & 1) == 0) // Rx not enabled
- || ((s->rregs[0] & 1) == 1)) // char already available
- ret = 0;
+ || ((s->rregs[0] & 1) == 1)) // char already available
+ ret = 0;
else
- ret = 1;
+ ret = 1;
//SER_DPRINTF("channel %c can receive %d\n", CHN_C(s), ret);
return ret;
}
@@ -582,7 +584,7 @@
ret = slavio_serial_load_chn(f, &s->chn[0], version_id);
if (ret != 0)
- return ret;
+ return ret;
ret = slavio_serial_load_chn(f, &s->chn[1], version_id);
return ret;
@@ -605,13 +607,13 @@
s->chn[1].chr = chr2;
for (i = 0; i < 2; i++) {
- s->chn[i].irq = irq;
- s->chn[i].chn = 1 - i;
- s->chn[i].type = ser;
- if (s->chn[i].chr) {
- qemu_chr_add_handlers(s->chn[i].chr, serial_can_receive,
+ s->chn[i].irq = irq;
+ s->chn[i].chn = 1 - i;
+ s->chn[i].type = ser;
+ if (s->chn[i].chr) {
+ qemu_chr_add_handlers(s->chn[i].chr, serial_can_receive,
serial_receive1, serial_event, &s->chn[i]);
- }
+ }
}
s->chn[0].otherchn = &s->chn[1];
s->chn[1].otherchn = &s->chn[0];
@@ -632,33 +634,85 @@
0, 45, 2, 4, 48, 0, 0, 21, 0, 0, 0, 0, 0, 120, 122, 67,
};
+static const uint8_t e0_keycodes[128] = {
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 90, 76, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 109, 0, 0, 13, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 68, 69, 70, 0, 91, 0, 93, 0, 112,
+ 113, 114, 94, 50, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+};
+
static void sunkbd_event(void *opaque, int ch)
{
ChannelState *s = opaque;
int release = ch & 0x80;
- ch = keycodes[ch & 0x7f];
- KBD_DPRINTF("Keycode %d (%s)\n", ch, release? "release" : "press");
+ KBD_DPRINTF("Untranslated keycode %2.2x (%s)\n", ch, release? "release" : "press");
+ switch (ch) {
+ case 58: // Caps lock press
+ s->caps_lock_mode ^= 1;
+ if (s->caps_lock_mode == 2)
+ return; // Drop second press
+ break;
+ case 69: // Num lock press
+ s->num_lock_mode ^= 1;
+ if (s->num_lock_mode == 2)
+ return; // Drop second press
+ break;
+ case 186: // Caps lock release
+ s->caps_lock_mode ^= 2;
+ if (s->caps_lock_mode == 3)
+ return; // Drop first release
+ break;
+ case 197: // Num lock release
+ s->num_lock_mode ^= 2;
+ if (s->num_lock_mode == 3)
+ return; // Drop first release
+ break;
+ case 0xe0:
+ s->e0_mode = 1;
+ return;
+ default:
+ break;
+ }
+ if (s->e0_mode) {
+ s->e0_mode = 0;
+ ch = e0_keycodes[ch & 0x7f];
+ } else {
+ ch = keycodes[ch & 0x7f];
+ }
+ KBD_DPRINTF("Translated keycode %2.2x\n", ch);
put_queue(s, ch | release);
}
static void handle_kbd_command(ChannelState *s, int val)
{
KBD_DPRINTF("Command %d\n", val);
+ if (s->led_mode) { // Ignore led byte
+ s->led_mode = 0;
+ return;
+ }
switch (val) {
case 1: // Reset, return type code
clear_queue(s);
- put_queue(s, 0xff);
- put_queue(s, 4); // Type 4
- break;
+ put_queue(s, 0xff);
+ put_queue(s, 4); // Type 4
+ put_queue(s, 0x7f);
+ break;
+ case 0xe: // Set leds
+ s->led_mode = 1;
+ break;
case 7: // Query layout
case 0xf:
clear_queue(s);
- put_queue(s, 0xfe);
- put_queue(s, 19); // XXX, layout?
- break;
+ put_queue(s, 0xfe);
+ put_queue(s, 0); // XXX, layout?
+ break;
default:
- break;
+ break;
}
}
@@ -714,9 +768,9 @@
if (!s)
return;
for (i = 0; i < 2; i++) {
- s->chn[i].irq = irq;
- s->chn[i].chn = 1 - i;
- s->chn[i].chr = NULL;
+ s->chn[i].irq = irq;
+ s->chn[i].chn = 1 - i;
+ s->chn[i].chr = NULL;
}
s->chn[0].otherchn = &s->chn[1];
s->chn[1].otherchn = &s->chn[0];
Modified: trunk/src/host/qemu-neo1973/hw/slavio_timer.c
===================================================================
--- trunk/src/host/qemu-neo1973/hw/slavio_timer.c 2007-10-29 20:40:05 UTC (rev 3302)
+++ trunk/src/host/qemu-neo1973/hw/slavio_timer.c 2007-10-29 21:14:04 UTC (rev 3303)
@@ -47,18 +47,31 @@
*
*/
+#define MAX_CPUS 16
+
typedef struct SLAVIO_TIMERState {
qemu_irq irq;
ptimer_state *timer;
uint32_t count, counthigh, reached;
uint64_t limit;
- int stopped;
- int mode; // 0 = processor, 1 = user, 2 = system
+ // processor only
+ int running;
+ struct SLAVIO_TIMERState *master;
+ int slave_index;
+ // system only
+ struct SLAVIO_TIMERState *slave[MAX_CPUS];
+ uint32_t slave_mode;
} SLAVIO_TIMERState;
#define TIMER_MAXADDR 0x1f
-#define TIMER_SIZE (TIMER_MAXADDR + 1)
+#define SYS_TIMER_SIZE 0x14
+#define CPU_TIMER_SIZE 0x10
+static int slavio_timer_is_user(SLAVIO_TIMERState *s)
+{
+ return s->master && (s->master->slave_mode & (1 << s->slave_index));
+}
+
// Update count, set irq, update expire_time
// Convert from ptimer countdown units
static void slavio_timer_get_out(SLAVIO_TIMERState *s)
@@ -79,9 +92,10 @@
slavio_timer_get_out(s);
DPRINTF("callback: count %x%08x\n", s->counthigh, s->count);
- s->reached = 0x80000000;
- if (s->mode != 1)
- qemu_irq_raise(s->irq);
+ if (!slavio_timer_is_user(s)) {
+ s->reached = 0x80000000;
+ qemu_irq_raise(s->irq);
+ }
}
static uint32_t slavio_timer_mem_readl(void *opaque, target_phys_addr_t addr)
@@ -92,37 +106,41 @@
saddr = (addr & TIMER_MAXADDR) >> 2;
switch (saddr) {
case 0:
- // read limit (system counter mode) or read most signifying
- // part of counter (user mode)
- if (s->mode != 1) {
- // clear irq
+ // read limit (system counter mode) or read most signifying
+ // part of counter (user mode)
+ if (slavio_timer_is_user(s)) {
+ // read user timer MSW
+ slavio_timer_get_out(s);
+ ret = s->counthigh;
+ } else {
+ // read limit
+ // clear irq
qemu_irq_lower(s->irq);
- s->reached = 0;
+ s->reached = 0;
ret = s->limit & 0x7fffffff;
- }
- else {
- slavio_timer_get_out(s);
- ret = s->counthigh & 0x7fffffff;
- }
+ }
break;
case 1:
- // read counter and reached bit (system mode) or read lsbits
- // of counter (user mode)
- slavio_timer_get_out(s);
- if (s->mode != 1)
- ret = (s->count & 0x7fffffff) | s->reached;
- else
- ret = s->count;
+ // read counter and reached bit (system mode) or read lsbits
+ // of counter (user mode)
+ slavio_timer_get_out(s);
+ if (slavio_timer_is_user(s)) // read user timer LSW
+ ret = s->count & 0xffffffe00;
+ else // read limit
+ ret = (s->count & 0x7ffffe00) | s->reached;
break;
case 3:
- // read start/stop status
- ret = s->stopped;
+ // only available in processor counter/timer
+ // read start/stop status
+ ret = s->running;
break;
case 4:
- // read user/system mode
- ret = s->mode & 1;
+ // only available in system counter
+ // read user/system mode
+ ret = s->slave_mode;
break;
default:
+ DPRINTF("invalid read address " TARGET_FMT_plx "\n", addr);
ret = 0;
break;
}
@@ -141,42 +159,75 @@
saddr = (addr & TIMER_MAXADDR) >> 2;
switch (saddr) {
case 0:
- // set limit, reset counter
- reload = 1;
- qemu_irq_lower(s->irq);
- // fall through
+ if (slavio_timer_is_user(s)) {
+ // set user counter MSW, reset counter
+ qemu_irq_lower(s->irq);
+ s->limit = 0x7ffffffffffffe00ULL;
+ DPRINTF("processor %d user timer reset\n", s->slave_index);
+ ptimer_set_limit(s->timer, s->limit >> 9, 1);
+ } else {
+ // set limit, reset counter
+ qemu_irq_lower(s->irq);
+ s->limit = val & 0x7ffffe00ULL;
+ if (!s->limit)
+ s->limit = 0x7ffffe00ULL;
+ ptimer_set_limit(s->timer, s->limit >> 9, 1);
+ }
+ break;
+ case 1:
+ if (slavio_timer_is_user(s)) {
+ // set user counter LSW, reset counter
+ qemu_irq_lower(s->irq);
+ s->limit = 0x7ffffffffffffe00ULL;
+ DPRINTF("processor %d user timer reset\n", s->slave_index);
+ ptimer_set_limit(s->timer, s->limit >> 9, 1);
+ } else
+ DPRINTF("not user timer\n");
+ break;
case 2:
- // set limit without resetting counter
+ // set limit without resetting counter
s->limit = val & 0x7ffffe00ULL;
if (!s->limit)
s->limit = 0x7ffffe00ULL;
ptimer_set_limit(s->timer, s->limit >> 9, reload);
- break;
+ break;
case 3:
- // start/stop user counter
- if (s->mode == 1) {
- if (val & 1) {
+ if (slavio_timer_is_user(s)) {
+ // start/stop user counter
+ if ((val & 1) && !s->running) {
+ DPRINTF("processor %d user timer started\n", s->slave_index);
+ ptimer_run(s->timer, 0);
+ s->running = 1;
+ } else if (!(val & 1) && s->running) {
+ DPRINTF("processor %d user timer stopped\n", s->slave_index);
ptimer_stop(s->timer);
- s->stopped = 1;
- }
- else {
- ptimer_run(s->timer, 0);
- s->stopped = 0;
- }
- }
- break;
+ s->running = 0;
+ }
+ }
+ break;
case 4:
- // bit 0: user (1) or system (0) counter mode
- if (s->mode == 0 || s->mode == 1)
- s->mode = val & 1;
- if (s->mode == 1) {
- qemu_irq_lower(s->irq);
- s->limit = -1ULL;
- }
- ptimer_set_limit(s->timer, s->limit >> 9, 1);
- break;
+ if (s->master == NULL) {
+ unsigned int i;
+
+ for (i = 0; i < MAX_CPUS; i++) {
+ if (val & (1 << i)) {
+ qemu_irq_lower(s->slave[i]->irq);
+ s->slave[i]->limit = -1ULL;
+ }
+ if ((val & (1 << i)) != (s->slave_mode & (1 << i))) {
+ ptimer_stop(s->slave[i]->timer);
+ ptimer_set_limit(s->slave[i]->timer, s->slave[i]->limit >> 9, 1);
+ DPRINTF("processor %d timer changed\n", s->slave[i]->slave_index);
+ ptimer_run(s->slave[i]->timer, 0);
+ }
+ }
+ s->slave_mode = val & ((1 << MAX_CPUS) - 1);
+ } else
+ DPRINTF("not system timer\n");
+ break;
default:
- break;
+ DPRINTF("invalid write address " TARGET_FMT_plx "\n", addr);
+ break;
}
}
@@ -201,8 +252,8 @@
qemu_put_be32s(f, &s->counthigh);
qemu_put_be32(f, 0); // Was irq
qemu_put_be32s(f, &s->reached);
- qemu_put_be32s(f, &s->stopped);
- qemu_put_be32s(f, &s->mode);
+ qemu_put_be32s(f, &s->running);
+ qemu_put_be32s(f, 0); // Was mode
qemu_put_ptimer(f, s->timer);
}
@@ -219,8 +270,8 @@
qemu_get_be32s(f, &s->counthigh);
qemu_get_be32s(f, &tmp); // Was irq
qemu_get_be32s(f, &s->reached);
- qemu_get_be32s(f, &s->stopped);
- qemu_get_be32s(f, &s->mode);
+ qemu_get_be32s(f, &s->running);
+ qemu_get_be32s(f, &tmp); // Was mode
qemu_get_ptimer(f, s->timer);
return 0;
@@ -230,17 +281,22 @@
{
SLAVIO_TIMERState *s = opaque;
- s->limit = 0x7ffffe00ULL;
+ if (slavio_timer_is_user(s))
+ s->limit = 0x7ffffffffffffe00ULL;
+ else
+ s->limit = 0x7ffffe00ULL;
s->count = 0;
s->reached = 0;
- s->mode &= 2;
ptimer_set_limit(s->timer, s->limit >> 9, 1);
ptimer_run(s->timer, 0);
- s->stopped = 1;
+ s->running = 1;
qemu_irq_lower(s->irq);
}
-void slavio_timer_init(target_phys_addr_t addr, qemu_irq irq, int mode)
+static SLAVIO_TIMERState *slavio_timer_init(target_phys_addr_t addr,
+ qemu_irq irq,
+ SLAVIO_TIMERState *master,
+ int slave_index)
{
int slavio_timer_io_memory;
SLAVIO_TIMERState *s;
@@ -248,17 +304,38 @@
s = qemu_mallocz(sizeof(SLAVIO_TIMERState));
if (!s)
- return;
+ return s;
s->irq = irq;
- s->mode = mode;
+ s->master = master;
+ s->slave_index = slave_index;
bh = qemu_bh_new(slavio_timer_irq, s);
s->timer = ptimer_init(bh);
ptimer_set_period(s->timer, 500ULL);
slavio_timer_io_memory = cpu_register_io_memory(0, slavio_timer_mem_read,
- slavio_timer_mem_write, s);
- cpu_register_physical_memory(addr, TIMER_SIZE, slavio_timer_io_memory);
+ slavio_timer_mem_write, s);
+ if (master)
+ cpu_register_physical_memory(addr, CPU_TIMER_SIZE, slavio_timer_io_memory);
+ else
+ cpu_register_physical_memory(addr, SYS_TIMER_SIZE, slavio_timer_io_memory);
register_savevm("slavio_timer", addr, 2, slavio_timer_save, slavio_timer_load, s);
qemu_register_reset(slavio_timer_reset, s);
slavio_timer_reset(s);
+
+ return s;
}
+
+void slavio_timer_init_all(target_phys_addr_t base, qemu_irq master_irq,
+ qemu_irq *cpu_irqs)
+{
+ SLAVIO_TIMERState *master;
+ unsigned int i;
+
+ master = slavio_timer_init(base + 0x10000ULL, master_irq, NULL, 0);
+
+ for (i = 0; i < MAX_CPUS; i++) {
+ master->slave[i] = slavio_timer_init(base + (target_phys_addr_t)
+ (i * TARGET_PAGE_SIZE),
+ cpu_irqs[i], master, i);
+ }
+}
Modified: trunk/src/host/qemu-neo1973/hw/spitz.c
===================================================================
--- trunk/src/host/qemu-neo1973/hw/spitz.c 2007-10-29 20:40:05 UTC (rev 3302)
+++ trunk/src/host/qemu-neo1973/hw/spitz.c 2007-10-29 21:14:04 UTC (rev 3303)
@@ -194,8 +194,8 @@
{ 0x0f, 0x10, 0x12, 0x14, 0x22, 0x16, 0x24, 0x25, -1 , -1 , -1 },
{ 0x3c, 0x11, 0x1f, 0x21, 0x2f, 0x23, 0x32, 0x26, -1 , 0x36, -1 },
{ 0x3b, 0x1e, 0x20, 0x2e, 0x30, 0x31, 0x34, -1 , 0x1c, 0x2a, -1 },
- { 0x44, 0x2c, 0x2d, 0x0c, 0x39, 0x33, -1 , 0x48, -1 , -1 , 0x3d },
- { 0x37, 0x38, -1 , 0x45, 0x57, 0x58, 0x4b, 0x50, 0x4d, -1 , -1 },
+ { 0x44, 0x2c, 0x2d, 0x0c, 0x39, 0x33, -1 , 0x48, -1 , -1 , 0x38 },
+ { 0x37, 0x3d, -1 , 0x45, 0x57, 0x58, 0x4b, 0x50, 0x4d, -1 , -1 },
{ 0x52, 0x43, 0x01, 0x47, 0x49, -1 , -1 , -1 , -1 , -1 , -1 },
};
@@ -415,13 +415,17 @@
s->pre_map[0x0d | SHIFT ] = 0x13 | FN; /* plus */
s->pre_map[0x1a ] = 0x14 | FN; /* bracketleft */
s->pre_map[0x1b ] = 0x15 | FN; /* bracketright */
+ s->pre_map[0x1a | SHIFT ] = 0x16 | FN; /* braceleft */
+ s->pre_map[0x1b | SHIFT ] = 0x17 | FN; /* braceright */
s->pre_map[0x27 ] = 0x22 | FN; /* semicolon */
s->pre_map[0x27 | SHIFT ] = 0x23 | FN; /* colon */
s->pre_map[0x09 | SHIFT ] = 0x24 | FN; /* asterisk */
s->pre_map[0x2b ] = 0x25 | FN; /* backslash */
s->pre_map[0x2b | SHIFT ] = 0x26 | FN; /* bar */
s->pre_map[0x0c | SHIFT ] = 0x30 | FN; /* underscore */
+ s->pre_map[0x33 | SHIFT ] = 0x33 | FN; /* less */
s->pre_map[0x35 ] = 0x33 | SHIFT; /* slash */
+ s->pre_map[0x34 | SHIFT ] = 0x34 | FN; /* greater */
s->pre_map[0x35 | SHIFT ] = 0x34 | SHIFT; /* question */
s->pre_map[0x49 ] = 0x48 | FN; /* Page_Up */
s->pre_map[0x51 ] = 0x50 | FN; /* Page_Down */
Modified: trunk/src/host/qemu-neo1973/hw/sun4m.c
===================================================================
--- trunk/src/host/qemu-neo1973/hw/sun4m.c 2007-10-29 20:40:05 UTC (rev 3302)
+++ trunk/src/host/qemu-neo1973/hw/sun4m.c 2007-10-29 21:14:04 UTC (rev 3303)
@@ -49,9 +49,10 @@
#define KERNEL_LOAD_ADDR 0x00004000
#define CMDLINE_ADDR 0x007ff000
#define INITRD_LOAD_ADDR 0x00800000
-#define PROM_SIZE_MAX (256 * 1024)
-#define PROM_ADDR 0xffd00000
-#define PROM_FILENAME "openbios-sparc32"
+#define PROM_SIZE_MAX (512 * 1024)
+#define PROM_PADDR 0xff0000000ULL
+#define PROM_VADDR 0xffd00000
+#define PROM_FILENAME "openbios-sparc32"
#define MAX_CPUS 16
#define MAX_PILS 16
@@ -157,9 +158,9 @@
extern int nographic;
static void nvram_init(m48t59_t *nvram, uint8_t *macaddr, const char *cmdline,
- int boot_device, uint32_t RAM_size,
- uint32_t kernel_size,
- int width, int height, int depth,
+ int boot_device, uint32_t RAM_size,
+ uint32_t kernel_size,
+ int width, int height, int depth,
int machine_id)
{
unsigned char tmp = 0;
@@ -178,8 +179,8 @@
nvram_set_lword(nvram, 0x38, KERNEL_LOAD_ADDR);
nvram_set_lword(nvram, 0x3C, kernel_size);
if (cmdline) {
- strcpy(phys_ram_base + CMDLINE_ADDR, cmdline);
- nvram_set_lword(nvram, 0x40, CMDLINE_ADDR);
+ strcpy(phys_ram_base + CMDLINE_ADDR, cmdline);
+ nvram_set_lword(nvram, 0x40, CMDLINE_ADDR);
nvram_set_lword(nvram, 0x44, strlen(cmdline));
}
// initrd_image, initrd_size passed differently
@@ -326,7 +327,7 @@
for(i = 0; i < smp_cpus; i++) {
env = cpu_init();
- cpu_sparc_register(env, def);
+ cpu_sparc_register(env, def, i);
envs[i] = env;
if (i == 0) {
qemu_register_reset(main_cpu_reset, env);
@@ -379,13 +380,10 @@
nvram = m48t59_init(slavio_irq[0], hwdef->nvram_base, 0,
hwdef->nvram_size, 8);
- for (i = 0; i < MAX_CPUS; i++) {
- slavio_timer_init(hwdef->counter_base +
- (target_phys_addr_t)(i * TARGET_PAGE_SIZE),
- slavio_cpu_irq[i], 0);
- }
- slavio_timer_init(hwdef->counter_base + 0x10000ULL,
- slavio_irq[hwdef->clock1_irq], 2);
+
+ slavio_timer_init_all(hwdef->counter_base, slavio_irq[hwdef->clock1_irq],
+ slavio_cpu_irq);
+
slavio_serial_ms_kbd_init(hwdef->ms_kb_base, slavio_irq[hwdef->ms_kb_irq]);
// Slavio TTYA (base+4, Linux ttyS0) is the first Qemu serial device
// Slavio TTYB (base+0, Linux ttyS1) is the second Qemu serial device
@@ -425,29 +423,34 @@
linux_boot = (kernel_filename != NULL);
prom_offset = RAM_size + vram_size;
- cpu_register_physical_memory(PROM_ADDR,
+ cpu_register_physical_memory(PROM_PADDR,
(PROM_SIZE_MAX + TARGET_PAGE_SIZE - 1) & TARGET_PAGE_MASK,
prom_offset | IO_MEM_ROM);
- snprintf(buf, sizeof(buf), "%s/%s", bios_dir, PROM_FILENAME);
- ret = load_elf(buf, 0, NULL, NULL, NULL);
- if (ret < 0) {
- fprintf(stderr, "qemu: could not load prom '%s'\n",
- buf);
- exit(1);
+ if (bios_name == NULL)
+ bios_name = PROM_FILENAME;
+ snprintf(buf, sizeof(buf), "%s/%s", bios_dir, bios_name);
+ ret = load_elf(buf, PROM_PADDR - PROM_VADDR, NULL, NULL, NULL);
+ if (ret < 0 || ret > PROM_SIZE_MAX)
+ ret = load_image(buf, phys_ram_base + prom_offset);
+ if (ret < 0 || ret > PROM_SIZE_MAX) {
+ fprintf(stderr, "qemu: could not load prom '%s'\n",
+ buf);
+ exit(1);
}
kernel_size = 0;
if (linux_boot) {
- kernel_size = load_elf(kernel_filename, -0xf0000000, NULL, NULL, NULL);
+ kernel_size = load_elf(kernel_filename, -0xf0000000ULL, NULL, NULL,
+ NULL);
if (kernel_size < 0)
- kernel_size = load_aout(kernel_filename, phys_ram_base + KERNEL_LOAD_ADDR);
- if (kernel_size < 0)
- kernel_size = load_image(kernel_filename, phys_ram_base + KERNEL_LOAD_ADDR);
+ kernel_size = load_aout(kernel_filename, phys_ram_base + KERNEL_LOAD_ADDR);
+ if (kernel_size < 0)
+ kernel_size = load_image(kernel_filename, phys_ram_base + KERNEL_LOAD_ADDR);
if (kernel_size < 0) {
fprintf(stderr, "qemu: could not load kernel '%s'\n",
kernel_filename);
- exit(1);
+ exit(1);
}
/* load initrd */
@@ -461,14 +464,14 @@
}
}
if (initrd_size > 0) {
- for (i = 0; i < 64 * TARGET_PAGE_SIZE; i += TARGET_PAGE_SIZE) {
- if (ldl_raw(phys_ram_base + KERNEL_LOAD_ADDR + i)
- == 0x48647253) { // HdrS
- stl_raw(phys_ram_base + KERNEL_LOAD_ADDR + i + 16, INITRD_LOAD_ADDR);
- stl_raw(phys_ram_base + KERNEL_LOAD_ADDR + i + 20, initrd_size);
- break;
- }
- }
+ for (i = 0; i < 64 * TARGET_PAGE_SIZE; i += TARGET_PAGE_SIZE) {
+ if (ldl_raw(phys_ram_base + KERNEL_LOAD_ADDR + i)
+ == 0x48647253) { // HdrS
+ stl_raw(phys_ram_base + KERNEL_LOAD_ADDR + i + 16, INITRD_LOAD_ADDR);
+ stl_raw(phys_ram_base + KERNEL_LOAD_ADDR + i + 20, initrd_size);
+ break;
+ }
+ }
}
}
nvram_init(nvram, (uint8_t *)&nd_table[0].macaddr, kernel_cmdline,
@@ -506,8 +509,8 @@
.cs_irq = 5,
.machine_id = 0x80,
.intbit_to_level = {
- 2, 3, 5, 7, 9, 11, 0, 14, 3, 5, 7, 9, 11, 13, 12, 12,
- 6, 0, 4, 10, 8, 0, 11, 0, 0, 0, 0, 0, 15, 0, 15, 0,
+ 2, 3, 5, 7, 9, 11, 0, 14, 3, 5, 7, 9, 11, 13, 12, 12,
+ 6, 0, 4, 10, 8, 0, 11, 0, 0, 0, 0, 0, 15, 0, 15, 0,
},
},
/* SS-10 */
@@ -539,8 +542,8 @@
.cs_irq = -1,
.machine_id = 0x72,
.intbit_to_level = {
- 2, 3, 5, 7, 9, 11, 0, 14, 3, 5, 7, 9, 11, 13, 12, 12,
- 6, 0, 4, 10, 8, 0, 11, 0, 0, 0, 0, 0, 15, 0, 15, 0,
+ 2, 3, 5, 7, 9, 11, 0, 14, 3, 5, 7, 9, 11, 13, 12, 12,
+ 6, 0, 4, 10, 8, 0, 11, 0, 0, 0, 0, 0, 15, 0, 15, 0,
},
},
};
@@ -588,7 +591,7 @@
cpu_model = "TI SuperSparc II";
sun4m_common_init(RAM_size, boot_device, ds, kernel_filename,
kernel_cmdline, initrd_filename, cpu_model,
- 1, PROM_ADDR); // XXX prom overlap, actually first 4GB ok
+ 1, 0xffffffff); // XXX actually first 62GB ok
}
QEMUMachine ss5_machine = {
Modified: trunk/src/host/qemu-neo1973/hw/sun4u.c
===================================================================
--- trunk/src/host/qemu-neo1973/hw/sun4u.c 2007-10-29 20:40:05 UTC (rev 3302)
+++ trunk/src/host/qemu-neo1973/hw/sun4u.c 2007-10-29 21:14:04 UTC (rev 3303)
@@ -28,12 +28,12 @@
#define CMDLINE_ADDR 0x003ff000
#define INITRD_LOAD_ADDR 0x00300000
#define PROM_SIZE_MAX (512 * 1024)
-#define PROM_ADDR 0x1fff0000000ULL
-#define PROM_VADDR 0x000ffd00000ULL
+#define PROM_ADDR 0x1fff0000000ULL
+#define PROM_VADDR 0x000ffd00000ULL
#define APB_SPECIAL_BASE 0x1fe00000000ULL
-#define APB_MEM_BASE 0x1ff00000000ULL
-#define VGA_BASE (APB_MEM_BASE + 0x400000ULL)
-#define PROM_FILENAME "openbios-sparc64"
+#define APB_MEM_BASE 0x1ff00000000ULL
+#define VGA_BASE (APB_MEM_BASE + 0x400000ULL)
+#define PROM_FILENAME "openbios-sparc64"
#define NVRAM_SIZE 0x2000
/* TSC handling */
@@ -162,10 +162,10 @@
odd = count & 1;
count &= ~1;
for (i = 0; i != count; i++) {
- crc = NVRAM_crc_update(crc, NVRAM_get_word(nvram, start + i));
+ crc = NVRAM_crc_update(crc, NVRAM_get_word(nvram, start + i));
}
if (odd) {
- crc = NVRAM_crc_update(crc, NVRAM_get_byte(nvram, start + i) << 8);
+ crc = NVRAM_crc_update(crc, NVRAM_get_byte(nvram, start + i) << 8);
}
return crc;
@@ -358,7 +358,7 @@
exit(1);
}
env = cpu_init();
- cpu_sparc_register(env, def);
+ cpu_sparc_register(env, def, 0);
bh = qemu_bh_new(tick_irq, env);
env->tick = ptimer_init(bh);
ptimer_set_period(env->tick, 1ULL);
@@ -382,12 +382,14 @@
(PROM_SIZE_MAX + TARGET_PAGE_SIZE) & TARGET_PAGE_MASK,
prom_offset | IO_MEM_ROM);
- snprintf(buf, sizeof(buf), "%s/%s", bios_dir, PROM_FILENAME);
+ if (bios_name == NULL)
+ bios_name = PROM_FILENAME;
+ snprintf(buf, sizeof(buf), "%s/%s", bios_dir, bios_name);
ret = load_elf(buf, PROM_ADDR - PROM_VADDR, NULL, NULL, NULL);
if (ret < 0) {
- fprintf(stderr, "qemu: could not load prom '%s'\n",
- buf);
- exit(1);
+ fprintf(stderr, "qemu: could not load prom '%s'\n",
+ buf);
+ exit(1);
}
kernel_size = 0;
@@ -396,13 +398,13 @@
/* XXX: put correct offset */
kernel_size = load_elf(kernel_filename, 0, NULL, NULL, NULL);
if (kernel_size < 0)
- kernel_size = load_aout(kernel_filename, phys_ram_base + KERNEL_LOAD_ADDR);
- if (kernel_size < 0)
- kernel_size = load_image(kernel_filename, phys_ram_base + KERNEL_LOAD_ADDR);
+ kernel_size = load_aout(kernel_filename, phys_ram_base + KERNEL_LOAD_ADDR);
+ if (kernel_size < 0)
+ kernel_size = load_image(kernel_filename, phys_ram_base + KERNEL_LOAD_ADDR);
if (kernel_size < 0) {
fprintf(stderr, "qemu: could not load kernel '%s'\n",
kernel_filename);
- exit(1);
+ exit(1);
}
/* load initrd */
@@ -415,14 +417,14 @@
}
}
if (initrd_size > 0) {
- for (i = 0; i < 64 * TARGET_PAGE_SIZE; i += TARGET_PAGE_SIZE) {
- if (ldl_raw(phys_ram_base + KERNEL_LOAD_ADDR + i)
- == 0x48647253) { // HdrS
- stl_raw(phys_ram_base + KERNEL_LOAD_ADDR + i + 16, INITRD_LOAD_ADDR);
- stl_raw(phys_ram_base + KERNEL_LOAD_ADDR + i + 20, initrd_size);
- break;
- }
- }
+ for (i = 0; i < 64 * TARGET_PAGE_SIZE; i += TARGET_PAGE_SIZE) {
+ if (ldl_raw(phys_ram_base + KERNEL_LOAD_ADDR + i)
+ == 0x48647253) { // HdrS
+ stl_raw(phys_ram_base + KERNEL_LOAD_ADDR + i + 16, INITRD_LOAD_ADDR);
+ stl_raw(phys_ram_base + KERNEL_LOAD_ADDR + i + 20, initrd_size);
+ break;
+ }
+ }
}
}
pci_bus = pci_apb_init(APB_SPECIAL_BASE, APB_MEM_BASE, NULL);
@@ -444,7 +446,7 @@
for(i = 0; i < nb_nics; i++) {
if (!nd_table[i].model)
nd_table[i].model = "ne2k_pci";
- pci_nic_init(pci_bus, &nd_table[i], -1);
+ pci_nic_init(pci_bus, &nd_table[i], -1);
}
irq = qemu_allocate_irqs(dummy_cpu_set_irq, NULL, 32);
Modified: trunk/src/host/qemu-neo1973/hw/tcx.c
===================================================================
--- trunk/src/host/qemu-neo1973/hw/tcx.c 2007-10-29 20:40:05 UTC (rev 3302)
+++ trunk/src/host/qemu-neo1973/hw/tcx.c 2007-10-29 21:14:04 UTC (rev 3303)
@@ -84,39 +84,39 @@
}
static void tcx_draw_line32(TCXState *s1, uint8_t *d,
- const uint8_t *s, int width)
+ const uint8_t *s, int width)
{
int x;
uint8_t val;
uint32_t *p = (uint32_t *)d;
for(x = 0; x < width; x++) {
- val = *s++;
+ val = *s++;
*p++ = s1->palette[val];
}
}
static void tcx_draw_line16(TCXState *s1, uint8_t *d,
- const uint8_t *s, int width)
+ const uint8_t *s, int width)
{
int x;
uint8_t val;
uint16_t *p = (uint16_t *)d;
for(x = 0; x < width; x++) {
- val = *s++;
+ val = *s++;
*p++ = s1->palette[val];
}
}
static void tcx_draw_line8(TCXState *s1, uint8_t *d,
- const uint8_t *s, int width)
+ const uint8_t *s, int width)
{
int x;
uint8_t val;
for(x = 0; x < width; x++) {
- val = *s++;
+ val = *s++;
*d++ = s1->palette[val];
}
}
@@ -183,7 +183,7 @@
void (*f)(TCXState *s1, uint8_t *dst, const uint8_t *src, int width);
if (ts->ds->depth == 0)
- return;
+ return;
page = ts->vram_offset;
y_start = -1;
page_min = 0xffffffff;
@@ -195,55 +195,55 @@
switch (ts->ds->depth) {
case 32:
- f = tcx_draw_line32;
- break;
+ f = tcx_draw_line32;
+ break;
case 15:
case 16:
- f = tcx_draw_line16;
- break;
+ f = tcx_draw_line16;
+ break;
default:
case 8:
- f = tcx_draw_line8;
- break;
+ f = tcx_draw_line8;
+ break;
case 0:
- return;
+ return;
}
for(y = 0; y < ts->height; y += 4, page += TARGET_PAGE_SIZE) {
- if (cpu_physical_memory_get_dirty(page, VGA_DIRTY_FLAG)) {
- if (y_start < 0)
+ if (cpu_physical_memory_get_dirty(page, VGA_DIRTY_FLAG)) {
+ if (y_start < 0)
y_start = y;
if (page < page_min)
page_min = page;
if (page > page_max)
page_max = page;
- f(ts, d, s, ts->width);
- d += dd;
- s += ds;
- f(ts, d, s, ts->width);
- d += dd;
- s += ds;
- f(ts, d, s, ts->width);
- d += dd;
- s += ds;
- f(ts, d, s, ts->width);
- d += dd;
- s += ds;
- } else {
+ f(ts, d, s, ts->width);
+ d += dd;
+ s += ds;
+ f(ts, d, s, ts->width);
+ d += dd;
+ s += ds;
+ f(ts, d, s, ts->width);
+ d += dd;
+ s += ds;
+ f(ts, d, s, ts->width);
+ d += dd;
+ s += ds;
+ } else {
if (y_start >= 0) {
/* flush to display */
dpy_update(ts->ds, 0, y_start,
ts->width, y - y_start);
y_start = -1;
}
- d += dd * 4;
- s += ds * 4;
- }
+ d += dd * 4;
+ s += ds * 4;
+ }
}
if (y_start >= 0) {
- /* flush to display */
- dpy_update(ts->ds, 0, y_start,
- ts->width, y - y_start);
+ /* flush to display */
+ dpy_update(ts->ds, 0, y_start,
+ ts->width, y - y_start);
}
/* reset modified pages */
if (page_min <= page_max) {
@@ -334,7 +334,7 @@
int i;
for (i = 0; i < MAXX*MAXY; i += TARGET_PAGE_SIZE) {
- cpu_physical_memory_set_dirty(s->vram_offset + i);
+ cpu_physical_memory_set_dirty(s->vram_offset + i);
}
}
@@ -424,32 +424,32 @@
saddr = (addr & (TCX_DAC_NREGS - 1)) >> 2;
switch (saddr) {
case 0:
- s->dac_index = val >> 24;
- s->dac_state = 0;
- break;
+ s->dac_index = val >> 24;
+ s->dac_state = 0;
+ break;
case 1:
- switch (s->dac_state) {
- case 0:
- s->r[s->dac_index] = val >> 24;
+ switch (s->dac_state) {
+ case 0:
+ s->r[s->dac_index] = val >> 24;
update_palette_entries(s, s->dac_index, s->dac_index + 1);
- s->dac_state++;
- break;
- case 1:
- s->g[s->dac_index] = val >> 24;
+ s->dac_state++;
+ break;
+ case 1:
+ s->g[s->dac_index] = val >> 24;
update_palette_entries(s, s->dac_index, s->dac_index + 1);
- s->dac_state++;
- break;
- case 2:
- s->b[s->dac_index] = val >> 24;
+ s->dac_state++;
+ break;
+ case 2:
+ s->b[s->dac_index] = val >> 24;
update_palette_entries(s, s->dac_index, s->dac_index + 1);
s->dac_index = (s->dac_index + 1) & 255; // Index autoincrement
- default:
- s->dac_state = 0;
- break;
- }
- break;
+ default:
+ s->dac_state = 0;
+ break;
+ }
+ break;
default:
- break;
+ break;
}
return;
}
Added: trunk/src/host/qemu-neo1973/hw/tsc210x.c
===================================================================
--- trunk/src/host/qemu-neo1973/hw/tsc210x.c 2007-10-29 20:40:05 UTC (rev 3302)
+++ trunk/src/host/qemu-neo1973/hw/tsc210x.c 2007-10-29 21:14:04 UTC (rev 3303)
@@ -0,0 +1,848 @@
+/*
+ * TI TSC2102 (touchscreen/sensors/audio controller) controller.
+ *
+ * Copyright (c) 2006 Andrzej Zaborowski <balrog at zabor.org>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * This program 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ */
+
+#include "vl.h"
+
+#define TSC_DATA_REGISTERS_PAGE 0x0
+#define TSC_CONTROL_REGISTERS_PAGE 0x1
+#define TSC_AUDIO_REGISTERS_PAGE 0x2
+
+#define TSC_VERBOSE
+
+#define TSC_CUT_RESOLUTION(value, p) ((value) >> (16 - resolution[p]))
+
+struct tsc210x_state_s {
+ qemu_irq pint;
+ QEMUTimer *timer;
+ struct uwire_slave_s chip;
+
+ int x, y;
+ int pressure;
+
+ int state, page, offset, irq;
+ uint16_t command, dav;
+
+ int busy;
+ int enabled;
+ int host_mode;
+ int function;
+ int nextfunction;
+ int precision;
+ int nextprecision;
+ int filter;
+ int pin_func;
+ int ref;
+ int timing;
+ int noise;
+
+ uint16_t audio_ctrl1;
+ uint16_t audio_ctrl2;
+ uint16_t audio_ctrl3;
+ uint16_t pll[2];
+ uint16_t volume;
+ int64_t volume_change;
+ int softstep;
+ uint16_t dac_power;
+ int64_t powerdown;
+ uint16_t filter_data[0x14];
+};
+
+static const int resolution[4] = { 12, 8, 10, 12 };
+
+#define TSC_MODE_NO_SCAN 0x0
+#define TSC_MODE_XY_SCAN 0x1
+#define TSC_MODE_XYZ_SCAN 0x2
+#define TSC_MODE_X 0x3
+#define TSC_MODE_Y 0x4
+#define TSC_MODE_Z 0x5
+#define TSC_MODE_BAT1 0x6
+#define TSC_MODE_BAT2 0x7
+#define TSC_MODE_AUX 0x8
+#define TSC_MODE_AUX_SCAN 0x9
+#define TSC_MODE_TEMP1 0xa
+#define TSC_MODE_PORT_SCAN 0xb
+#define TSC_MODE_TEMP2 0xc
+#define TSC_MODE_XX_DRV 0xd
+#define TSC_MODE_YY_DRV 0xe
+#define TSC_MODE_YX_DRV 0xf
+
+static const uint16_t mode_regs[16] = {
+ 0x0000, /* No scan */
+ 0x0600, /* X, Y scan */
+ 0x0780, /* X, Y, Z scan */
+ 0x0400, /* X */
+ 0x0200, /* Y */
+ 0x0180, /* Z */
+ 0x0040, /* BAT1 */
+ 0x0030, /* BAT2 */
+ 0x0010, /* AUX */
+ 0x0010, /* AUX scan */
+ 0x0004, /* TEMP1 */
+ 0x0070, /* Port scan */
+ 0x0002, /* TEMP2 */
+ 0x0000, /* X+, X- drivers */
+ 0x0000, /* Y+, Y- drivers */
+ 0x0000, /* Y+, X- drivers */
+};
+
+/*
+ * Convert screen coordinates to arbitrary values that the
+ * touchscreen in my Palm Tungsten E device returns.
+ * This shouldn't really matter (because the guest system
+ * should calibrate the touchscreen anyway), but let's
+ * imitate some real hardware.
+ */
+#define X_TRANSFORM(value) \
+ ((3850 - ((int) (value) * (3850 - 250) / 32768)) << 4)
+#define Y_TRANSFORM(value) \
+ ((150 + ((int) (value) * (3037 - 150) / 32768)) << 4)
+#define Z1_TRANSFORM(s) \
+ ((400 - (s)->x + ((s)->pressure << 9)) << 4)
+#define Z2_TRANSFORM(s) \
+ ((4000 + (s)->y - ((s)->pressure << 10)) << 4)
+#define BAT1_VAL 0x8660
+#define BAT2_VAL 0x0000
+#define AUX1_VAL 0x35c0
+#define AUX2_VAL 0xffff
+#define TEMP1_VAL 0x8c70
+#define TEMP2_VAL 0xa5b0
+
+#define TSC_POWEROFF_DELAY 50
+#define TSC_SOFTSTEP_DELAY 50
+
+static void tsc210x_reset(struct tsc210x_state_s *s)
+{
+ s->state = 0;
+ s->pin_func = 2;
+ s->enabled = 0;
+ s->busy = 0;
+ s->nextfunction = 0;
+ s->ref = 0;
+ s->timing = 0;
+ s->irq = 0;
+ s->dav = 0;
+
+ s->audio_ctrl1 = 0x0000;
+ s->audio_ctrl2 = 0x4410;
+ s->audio_ctrl3 = 0x0000;
+ s->pll[0] = 0x1004;
+ s->pll[1] = 0x0000;
+ s->volume = 0xffff;
+ s->dac_power = 0x8540;
+ s->softstep = 1;
+ s->volume_change = 0;
+ s->powerdown = 0;
+ s->filter_data[0x00] = 0x6be3;
+ s->filter_data[0x01] = 0x9666;
+ s->filter_data[0x02] = 0x675d;
+ s->filter_data[0x03] = 0x6be3;
+ s->filter_data[0x04] = 0x9666;
+ s->filter_data[0x05] = 0x675d;
+ s->filter_data[0x06] = 0x7d83;
+ s->filter_data[0x07] = 0x84ee;
+ s->filter_data[0x08] = 0x7d83;
+ s->filter_data[0x09] = 0x84ee;
+ s->filter_data[0x0a] = 0x6be3;
+ s->filter_data[0x0b] = 0x9666;
+ s->filter_data[0x0c] = 0x675d;
+ s->filter_data[0x0d] = 0x6be3;
+ s->filter_data[0x0e] = 0x9666;
+ s->filter_data[0x0f] = 0x675d;
+ s->filter_data[0x10] = 0x7d83;
+ s->filter_data[0x11] = 0x84ee;
+ s->filter_data[0x12] = 0x7d83;
+ s->filter_data[0x13] = 0x84ee;
+
+ qemu_set_irq(s->pint, s->irq);
+}
+
+static uint16_t tsc2102_data_register_read(struct tsc210x_state_s *s, int reg)
+{
+ switch (reg) {
+ case 0x00: /* X */
+ s->dav &= 0xfbff;
+ return TSC_CUT_RESOLUTION(X_TRANSFORM(s->x), s->precision) +
+ (s->noise & 3);
+
+ case 0x01: /* Y */
+ s->noise ++;
+ s->dav &= 0xfdff;
+ return TSC_CUT_RESOLUTION(Y_TRANSFORM(s->y), s->precision) ^
+ (s->noise & 3);
+
+ case 0x02: /* Z1 */
+ s->dav &= 0xfeff;
+ return TSC_CUT_RESOLUTION(Z1_TRANSFORM(s), s->precision) -
+ (s->noise & 3);
+
+ case 0x03: /* Z2 */
+ s->dav &= 0xff7f;
+ return TSC_CUT_RESOLUTION(Z2_TRANSFORM(s), s->precision) |
+ (s->noise & 3);
+
+ case 0x04: /* KPData */
+ return 0xffff;
+
+ case 0x05: /* BAT1 */
+ s->dav &= 0xffbf;
+ return TSC_CUT_RESOLUTION(BAT1_VAL, s->precision);
+
+ case 0x06: /* BAT2 */
+ s->dav &= 0xffdf;
+ return TSC_CUT_RESOLUTION(BAT2_VAL, s->precision);
+
+ case 0x07: /* AUX1 */
+ s->dav &= 0xffef;
+ return TSC_CUT_RESOLUTION(AUX1_VAL, s->precision);
+
+ case 0x08: /* AUX2 */
+ s->dav &= 0xfff7;
+ return 0xffff;
+
+ case 0x09: /* TEMP1 */
+ s->dav &= 0xfffb;
+ return TSC_CUT_RESOLUTION(TEMP1_VAL, s->precision);
+
+ case 0x0a: /* TEMP2 */
+ s->dav &= 0xfffd;
+ return TSC_CUT_RESOLUTION(TEMP2_VAL, s->precision);
+
+ case 0x0b: /* DAC */
+ s->dav &= 0xfffe;
+ return 0xffff;
+
+ default:
+#ifdef TSC_VERBOSE
+ fprintf(stderr, "tsc2102_data_register_read: "
+ "no such register: 0x%02x\n", reg);
+#endif
+ return 0xffff;
+ }
+}
+
+static uint16_t tsc2102_control_register_read(
+ struct tsc210x_state_s *s, int reg)
+{
+ switch (reg) {
+ case 0x00: /* TSC ADC */
+ return (s->pressure << 15) | ((!s->busy) << 14) |
+ (s->nextfunction << 10) | (s->nextprecision << 8) | s->filter;
+
+ case 0x01: /* Status */
+ return (s->pin_func << 14) | ((!s->enabled) << 13) |
+ (s->host_mode << 12) | ((!!s->dav) << 11) | s->dav;
+
+ case 0x03: /* Reference */
+ return s->ref;
+
+ case 0x04: /* Reset */
+ return 0xffff;
+
+ case 0x05: /* Configuration */
+ return s->timing;
+
+ default:
+#ifdef TSC_VERBOSE
+ fprintf(stderr, "tsc2102_control_register_read: "
+ "no such register: 0x%02x\n", reg);
+#endif
+ return 0xffff;
+ }
+}
+
+static uint16_t tsc2102_audio_register_read(struct tsc210x_state_s *s, int reg)
+{
+ int l_ch, r_ch;
+ uint16_t val;
+
+ switch (reg) {
+ case 0x00: /* Audio Control 1 */
+ return s->audio_ctrl1;
+
+ case 0x01:
+ return 0xff00;
+
+ case 0x02: /* DAC Volume Control */
+ return s->volume;
+
+ case 0x03:
+ return 0x8b00;
+
+ case 0x04: /* Audio Control 2 */
+ l_ch = 1;
+ r_ch = 1;
+ if (s->softstep && !(s->dac_power & (1 << 10))) {
+ l_ch = (qemu_get_clock(vm_clock) >
+ s->volume_change + TSC_SOFTSTEP_DELAY);
+ r_ch = (qemu_get_clock(vm_clock) >
+ s->volume_change + TSC_SOFTSTEP_DELAY);
+ }
+
+ return s->audio_ctrl2 | (l_ch << 3) | (r_ch << 2);
+
+ case 0x05: /* Stereo DAC Power Control */
+ return 0x2aa0 | s->dac_power |
+ (((s->dac_power & (1 << 10)) &&
+ (qemu_get_clock(vm_clock) >
+ s->powerdown + TSC_POWEROFF_DELAY)) << 6);
+
+ case 0x06: /* Audio Control 3 */
+ val = s->audio_ctrl3 | 0x0001;
+ s->audio_ctrl3 &= 0xff3f;
+ return val;
+
+ case 0x07: /* LCH_BASS_BOOST_N0 */
+ case 0x08: /* LCH_BASS_BOOST_N1 */
+ case 0x09: /* LCH_BASS_BOOST_N2 */
+ case 0x0a: /* LCH_BASS_BOOST_N3 */
+ case 0x0b: /* LCH_BASS_BOOST_N4 */
+ case 0x0c: /* LCH_BASS_BOOST_N5 */
+ case 0x0d: /* LCH_BASS_BOOST_D1 */
+ case 0x0e: /* LCH_BASS_BOOST_D2 */
+ case 0x0f: /* LCH_BASS_BOOST_D4 */
+ case 0x10: /* LCH_BASS_BOOST_D5 */
+ case 0x11: /* RCH_BASS_BOOST_N0 */
+ case 0x12: /* RCH_BASS_BOOST_N1 */
+ case 0x13: /* RCH_BASS_BOOST_N2 */
+ case 0x14: /* RCH_BASS_BOOST_N3 */
+ case 0x15: /* RCH_BASS_BOOST_N4 */
+ case 0x16: /* RCH_BASS_BOOST_N5 */
+ case 0x17: /* RCH_BASS_BOOST_D1 */
+ case 0x18: /* RCH_BASS_BOOST_D2 */
+ case 0x19: /* RCH_BASS_BOOST_D4 */
+ case 0x1a: /* RCH_BASS_BOOST_D5 */
+ return s->filter_data[reg - 0x07];
+
+ case 0x1b: /* PLL Programmability 1 */
+ return s->pll[0];
+
+ case 0x1c: /* PLL Programmability 2 */
+ return s->pll[1];
+
+ case 0x1d: /* Audio Control 4 */
+ return (!s->softstep) << 14;
+
+ default:
+#ifdef TSC_VERBOSE
+ fprintf(stderr, "tsc2102_audio_register_read: "
+ "no such register: 0x%02x\n", reg);
+#endif
+ return 0xffff;
+ }
+}
+
+static void tsc2102_data_register_write(
+ struct tsc210x_state_s *s, int reg, uint16_t value)
+{
+ switch (reg) {
+ case 0x00: /* X */
+ case 0x01: /* Y */
+ case 0x02: /* Z1 */
+ case 0x03: /* Z2 */
+ case 0x05: /* BAT1 */
+ case 0x06: /* BAT2 */
+ case 0x07: /* AUX1 */
+ case 0x08: /* AUX2 */
+ case 0x09: /* TEMP1 */
+ case 0x0a: /* TEMP2 */
+ return;
+
+ default:
+#ifdef TSC_VERBOSE
+ fprintf(stderr, "tsc2102_data_register_write: "
+ "no such register: 0x%02x\n", reg);
+#endif
+ }
+}
+
+static void tsc2102_control_register_write(
+ struct tsc210x_state_s *s, int reg, uint16_t value)
+{
+ switch (reg) {
+ case 0x00: /* TSC ADC */
+ s->host_mode = value >> 15;
+ s->enabled = !(value & 0x4000);
+ if (s->busy && !s->enabled)
+ qemu_del_timer(s->timer);
+ s->busy &= s->enabled;
+ s->nextfunction = (value >> 10) & 0xf;
+ s->nextprecision = (value >> 8) & 3;
+ s->filter = value & 0xff;
+ return;
+
+ case 0x01: /* Status */
+ s->pin_func = value >> 14;
+ return;
+
+ case 0x03: /* Reference */
+ s->ref = value & 0x1f;
+ return;
+
+ case 0x04: /* Reset */
+ if (value == 0xbb00) {
+ if (s->busy)
+ qemu_del_timer(s->timer);
+ tsc210x_reset(s);
+#ifdef TSC_VERBOSE
+ } else {
+ fprintf(stderr, "tsc2102_control_register_write: "
+ "wrong value written into RESET\n");
+#endif
+ }
+ return;
+
+ case 0x05: /* Configuration */
+ s->timing = value & 0x3f;
+#ifdef TSC_VERBOSE
+ if (value & ~0x3f)
+ fprintf(stderr, "tsc2102_control_register_write: "
+ "wrong value written into CONFIG\n");
+#endif
+ return;
+
+ default:
+#ifdef TSC_VERBOSE
+ fprintf(stderr, "tsc2102_control_register_write: "
+ "no such register: 0x%02x\n", reg);
+#endif
+ }
+}
+
+static void tsc2102_audio_register_write(
+ struct tsc210x_state_s *s, int reg, uint16_t value)
+{
+ switch (reg) {
+ case 0x00: /* Audio Control 1 */
+ s->audio_ctrl1 = value & 0x0f3f;
+#ifdef TSC_VERBOSE
+ if ((value & ~0x0f3f) || ((value & 7) != ((value >> 3) & 7)))
+ fprintf(stderr, "tsc2102_audio_register_write: "
+ "wrong value written into Audio 1\n");
+#endif
+ return;
+
+ case 0x01:
+#ifdef TSC_VERBOSE
+ if (value != 0xff00)
+ fprintf(stderr, "tsc2102_audio_register_write: "
+ "wrong value written into reg 0x01\n");
+#endif
+ return;
+
+ case 0x02: /* DAC Volume Control */
+ s->volume = value;
+ s->volume_change = qemu_get_clock(vm_clock);
+ return;
+
+ case 0x03:
+#ifdef TSC_VERBOSE
+ if (value != 0x8b00)
+ fprintf(stderr, "tsc2102_audio_register_write: "
+ "wrong value written into reg 0x03\n");
+#endif
+ return;
+
+ case 0x04: /* Audio Control 2 */
+ s->audio_ctrl2 = value & 0xf7f2;
+#ifdef TSC_VERBOSE
+ if (value & ~0xf7fd)
+ fprintf(stderr, "tsc2102_audio_register_write: "
+ "wrong value written into Audio 2\n");
+#endif
+ return;
+
+ case 0x05: /* Stereo DAC Power Control */
+ if ((value & ~s->dac_power) & (1 << 10))
+ s->powerdown = qemu_get_clock(vm_clock);
+
+ s->dac_power = value & 0x9543;
+#ifdef TSC_VERBOSE
+ if ((value & ~0x9543) != 0x2aa0)
+ fprintf(stderr, "tsc2102_audio_register_write: "
+ "wrong value written into Power\n");
+#endif
+ return;
+
+ case 0x06: /* Audio Control 3 */
+ s->audio_ctrl3 &= 0x00c0;
+ s->audio_ctrl3 |= value & 0xf800;
+#ifdef TSC_VERBOSE
+ if (value & ~0xf8c7)
+ fprintf(stderr, "tsc2102_audio_register_write: "
+ "wrong value written into Audio 3\n");
+#endif
+ return;
+
+ case 0x07: /* LCH_BASS_BOOST_N0 */
+ case 0x08: /* LCH_BASS_BOOST_N1 */
+ case 0x09: /* LCH_BASS_BOOST_N2 */
+ case 0x0a: /* LCH_BASS_BOOST_N3 */
+ case 0x0b: /* LCH_BASS_BOOST_N4 */
+ case 0x0c: /* LCH_BASS_BOOST_N5 */
+ case 0x0d: /* LCH_BASS_BOOST_D1 */
+ case 0x0e: /* LCH_BASS_BOOST_D2 */
+ case 0x0f: /* LCH_BASS_BOOST_D4 */
+ case 0x10: /* LCH_BASS_BOOST_D5 */
+ case 0x11: /* RCH_BASS_BOOST_N0 */
+ case 0x12: /* RCH_BASS_BOOST_N1 */
+ case 0x13: /* RCH_BASS_BOOST_N2 */
+ case 0x14: /* RCH_BASS_BOOST_N3 */
+ case 0x15: /* RCH_BASS_BOOST_N4 */
+ case 0x16: /* RCH_BASS_BOOST_N5 */
+ case 0x17: /* RCH_BASS_BOOST_D1 */
+ case 0x18: /* RCH_BASS_BOOST_D2 */
+ case 0x19: /* RCH_BASS_BOOST_D4 */
+ case 0x1a: /* RCH_BASS_BOOST_D5 */
+ s->filter_data[reg - 0x07] = value;
+ return;
+
+ case 0x1b: /* PLL Programmability 1 */
+ s->pll[0] = value & 0xfffc;
+#ifdef TSC_VERBOSE
+ if (value & ~0xfffc)
+ fprintf(stderr, "tsc2102_audio_register_write: "
+ "wrong value written into PLL 1\n");
+#endif
+ return;
+
+ case 0x1c: /* PLL Programmability 2 */
+ s->pll[1] = value & 0xfffc;
+#ifdef TSC_VERBOSE
+ if (value & ~0xfffc)
+ fprintf(stderr, "tsc2102_audio_register_write: "
+ "wrong value written into PLL 2\n");
+#endif
+ return;
+
+ case 0x1d: /* Audio Control 4 */
+ s->softstep = !(value & 0x4000);
+#ifdef TSC_VERBOSE
+ if (value & ~0x4000)
+ fprintf(stderr, "tsc2102_audio_register_write: "
+ "wrong value written into Audio 4\n");
+#endif
+ return;
+
+ default:
+#ifdef TSC_VERBOSE
+ fprintf(stderr, "tsc2102_audio_register_write: "
+ "no such register: 0x%02x\n", reg);
+#endif
+ }
+}
+
+/* This handles most of the chip logic. */
+static void tsc210x_pin_update(struct tsc210x_state_s *s)
+{
+ int64_t expires;
+ int pin_state;
+
+ switch (s->pin_func) {
+ case 0:
+ pin_state = s->pressure;
+ break;
+ case 1:
+ pin_state = !!s->dav;
+ break;
+ case 2:
+ default:
+ pin_state = s->pressure && !s->dav;
+ }
+
+ if (!s->enabled)
+ pin_state = 0;
+
+ if (pin_state != s->irq) {
+ s->irq = pin_state;
+ qemu_set_irq(s->pint, s->irq);
+ }
+
+ switch (s->nextfunction) {
+ case TSC_MODE_XY_SCAN:
+ case TSC_MODE_XYZ_SCAN:
+ if (!s->pressure)
+ return;
+ break;
+
+ case TSC_MODE_X:
+ case TSC_MODE_Y:
+ case TSC_MODE_Z:
+ if (!s->pressure)
+ return;
+ /* Fall through */
+ case TSC_MODE_BAT1:
+ case TSC_MODE_BAT2:
+ case TSC_MODE_AUX:
+ case TSC_MODE_TEMP1:
+ case TSC_MODE_TEMP2:
+ if (s->dav)
+ s->enabled = 0;
+ break;
+
+ case TSC_MODE_AUX_SCAN:
+ case TSC_MODE_PORT_SCAN:
+ break;
+
+ case TSC_MODE_NO_SCAN:
+ case TSC_MODE_XX_DRV:
+ case TSC_MODE_YY_DRV:
+ case TSC_MODE_YX_DRV:
+ default:
+ return;
+ }
+
+ if (!s->enabled || s->busy)
+ return;
+
+ s->busy = 1;
+ s->precision = s->nextprecision;
+ s->function = s->nextfunction;
+ expires = qemu_get_clock(vm_clock) + (ticks_per_sec >> 10);
+ qemu_mod_timer(s->timer, expires);
+}
+
+static uint16_t tsc210x_read(struct tsc210x_state_s *s)
+{
+ uint16_t ret = 0x0000;
+
+ if (!s->command)
+ fprintf(stderr, "tsc210x_read: SPI underrun!\n");
+
+ switch (s->page) {
+ case TSC_DATA_REGISTERS_PAGE:
+ ret = tsc2102_data_register_read(s, s->offset);
+ break;
+ case TSC_CONTROL_REGISTERS_PAGE:
+ ret = tsc2102_control_register_read(s, s->offset);
+ break;
+ case TSC_AUDIO_REGISTERS_PAGE:
+ ret = tsc2102_audio_register_read(s, s->offset);
+ break;
+ default:
+ cpu_abort(cpu_single_env, "tsc210x_read: wrong memory page\n");
+ }
+
+ tsc210x_pin_update(s);
+
+ /* Allow sequential reads. */
+ s->offset ++;
+ s->state = 0;
+ return ret;
+}
+
+static void tsc210x_write(struct tsc210x_state_s *s, uint16_t value)
+{
+ /*
+ * This is a two-state state machine for reading
+ * command and data every second time.
+ */
+ if (!s->state) {
+ s->command = value >> 15;
+ s->page = (value >> 11) & 0x0f;
+ s->offset = (value >> 5) & 0x3f;
+ s->state = 1;
+ } else {
+ if (s->command)
+ fprintf(stderr, "tsc210x_write: SPI overrun!\n");
+ else
+ switch (s->page) {
+ case TSC_DATA_REGISTERS_PAGE:
+ tsc2102_data_register_write(s, s->offset, value);
+ break;
+ case TSC_CONTROL_REGISTERS_PAGE:
+ tsc2102_control_register_write(s, s->offset, value);
+ break;
+ case TSC_AUDIO_REGISTERS_PAGE:
+ tsc2102_audio_register_write(s, s->offset, value);
+ break;
+ default:
+ cpu_abort(cpu_single_env,
+ "tsc210x_write: wrong memory page\n");
+ }
+
+ tsc210x_pin_update(s);
+ s->state = 0;
+ }
+}
+
+static void tsc210x_timer_tick(void *opaque)
+{
+ struct tsc210x_state_s *s = opaque;
+
+ /* Timer ticked -- a set of conversions has been finished. */
+
+ if (!s->busy)
+ return;
+
+ s->busy = 0;
+ s->dav |= mode_regs[s->function];
+ tsc210x_pin_update(s);
+}
+
+static void tsc210x_touchscreen_event(void *opaque,
+ int x, int y, int z, int buttons_state)
+{
+ struct tsc210x_state_s *s = opaque;
+ int p = s->pressure;
+
+ if (buttons_state) {
+ s->x = x;
+ s->y = y;
+ }
+ s->pressure = !!buttons_state;
+
+ /*
+ * Note: We would get better responsiveness in the guest by
+ * signaling TS events immediately, but for now we simulate
+ * the first conversion delay for sake of correctness.
+ */
+ if (p != s->pressure)
+ tsc210x_pin_update(s);
+}
+
+static void tsc210x_save(QEMUFile *f, void *opaque)
+{
+ struct tsc210x_state_s *s = (struct tsc210x_state_s *) opaque;
+ int64_t now = qemu_get_clock(vm_clock);
+ int i;
+
+ qemu_put_be16(f, s->x);
+ qemu_put_be16(f, s->y);
+ qemu_put_byte(f, s->pressure);
+
+ qemu_put_byte(f, s->state);
+ qemu_put_byte(f, s->page);
+ qemu_put_byte(f, s->offset);
+ qemu_put_byte(f, s->command);
+
+ qemu_put_byte(f, s->irq);
+ qemu_put_be16s(f, &s->dav);
+
+ qemu_put_timer(f, s->timer);
+ qemu_put_byte(f, s->enabled);
+ qemu_put_byte(f, s->host_mode);
+ qemu_put_byte(f, s->function);
+ qemu_put_byte(f, s->nextfunction);
+ qemu_put_byte(f, s->precision);
+ qemu_put_byte(f, s->nextprecision);
+ qemu_put_byte(f, s->filter);
+ qemu_put_byte(f, s->pin_func);
+ qemu_put_byte(f, s->ref);
+ qemu_put_byte(f, s->timing);
+ qemu_put_be32(f, s->noise);
+
+ qemu_put_be16s(f, &s->audio_ctrl1);
+ qemu_put_be16s(f, &s->audio_ctrl2);
+ qemu_put_be16s(f, &s->audio_ctrl3);
+ qemu_put_be16s(f, &s->pll[0]);
+ qemu_put_be16s(f, &s->pll[1]);
+ qemu_put_be16s(f, &s->volume);
+ qemu_put_be64(f, (uint64_t) (s->volume_change - now));
+ qemu_put_be64(f, (uint64_t) (s->powerdown - now));
+ qemu_put_byte(f, s->softstep);
+ qemu_put_be16s(f, &s->dac_power);
+
+ for (i = 0; i < 0x14; i ++)
+ qemu_put_be16s(f, &s->filter_data[i]);
+}
+
+static int tsc210x_load(QEMUFile *f, void *opaque, int version_id)
+{
+ struct tsc210x_state_s *s = (struct tsc210x_state_s *) opaque;
+ int64_t now = qemu_get_clock(vm_clock);
+ int i;
+
+ s->x = qemu_get_be16(f);
+ s->y = qemu_get_be16(f);
+ s->pressure = qemu_get_byte(f);
+
+ s->state = qemu_get_byte(f);
+ s->page = qemu_get_byte(f);
+ s->offset = qemu_get_byte(f);
+ s->command = qemu_get_byte(f);
+
+ s->irq = qemu_get_byte(f);
+ qemu_get_be16s(f, &s->dav);
+
+ qemu_get_timer(f, s->timer);
+ s->enabled = qemu_get_byte(f);
+ s->host_mode = qemu_get_byte(f);
+ s->function = qemu_get_byte(f);
+ s->nextfunction = qemu_get_byte(f);
+ s->precision = qemu_get_byte(f);
+ s->nextprecision = qemu_get_byte(f);
+ s->filter = qemu_get_byte(f);
+ s->pin_func = qemu_get_byte(f);
+ s->ref = qemu_get_byte(f);
+ s->timing = qemu_get_byte(f);
+ s->noise = qemu_get_be32(f);
+
+ qemu_get_be16s(f, &s->audio_ctrl1);
+ qemu_get_be16s(f, &s->audio_ctrl2);
+ qemu_get_be16s(f, &s->audio_ctrl3);
+ qemu_get_be16s(f, &s->pll[0]);
+ qemu_get_be16s(f, &s->pll[1]);
+ qemu_get_be16s(f, &s->volume);
+ s->volume_change = (int64_t) qemu_get_be64(f) + now;
+ s->powerdown = (int64_t) qemu_get_be64(f) + now;
+ s->softstep = qemu_get_byte(f);
+ qemu_get_be16s(f, &s->dac_power);
+
+ for (i = 0; i < 0x14; i ++)
+ qemu_get_be16s(f, &s->filter_data[i]);
+
+ s->busy = qemu_timer_pending(s->timer);
+ qemu_set_irq(s->pint, s->irq);
+
+ return 0;
+}
+
+static int tsc2102_iid = 0;
+
+struct uwire_slave_s *tsc2102_init(qemu_irq pint)
+{
+ struct tsc210x_state_s *s;
+
+ s = (struct tsc210x_state_s *)
+ qemu_mallocz(sizeof(struct tsc210x_state_s));
+ memset(s, 0, sizeof(struct tsc210x_state_s));
+ s->x = 160;
+ s->y = 160;
+ s->pressure = 0;
+ s->precision = s->nextprecision = 0;
+ s->timer = qemu_new_timer(vm_clock, tsc210x_timer_tick, s);
+ s->pint = pint;
+
+ s->chip.opaque = s;
+ s->chip.send = (void *) tsc210x_write;
+ s->chip.receive = (void *) tsc210x_read;
+
+ tsc210x_reset(s);
+
+ qemu_add_mouse_event_handler(tsc210x_touchscreen_event, s, 1,
+ "QEMU TSC2102-driven Touchscreen");
+
+ qemu_register_reset((void *) tsc210x_reset, s);
+ register_savevm("tsc2102", tsc2102_iid ++, 0,
+ tsc210x_save, tsc210x_load, s);
+
+ return &s->chip;
+}
Modified: trunk/src/host/qemu-neo1973/hw/usb-uhci.c
===================================================================
--- trunk/src/host/qemu-neo1973/hw/usb-uhci.c 2007-10-29 20:40:05 UTC (rev 3302)
+++ trunk/src/host/qemu-neo1973/hw/usb-uhci.c 2007-10-29 21:14:04 UTC (rev 3303)
@@ -25,6 +25,7 @@
//#define DEBUG
//#define DEBUG_PACKET
+//#define DEBUG_ISOCH
#define UHCI_CMD_FGR (1 << 4)
#define UHCI_CMD_EGSM (1 << 3)
@@ -88,6 +89,7 @@
other queues will not be processed until the next frame. The solution
is to allow multiple pending requests. */
uint32_t async_qh;
+ uint32_t async_frame_addr;
USBPacket usb_packet;
uint8_t usb_buf[2048];
} UHCIState;
@@ -146,6 +148,58 @@
}
}
+static void uhci_save(QEMUFile *f, void *opaque)
+{
+ UHCIState *s = opaque;
+ uint8_t num_ports = NB_PORTS;
+ int i;
+
+ pci_device_save(&s->dev, f);
+
+ qemu_put_8s(f, &num_ports);
+ for (i = 0; i < num_ports; ++i)
+ qemu_put_be16s(f, &s->ports[i].ctrl);
+ qemu_put_be16s(f, &s->cmd);
+ qemu_put_be16s(f, &s->status);
+ qemu_put_be16s(f, &s->intr);
+ qemu_put_be16s(f, &s->frnum);
+ qemu_put_be32s(f, &s->fl_base_addr);
+ qemu_put_8s(f, &s->sof_timing);
+ qemu_put_8s(f, &s->status2);
+ qemu_put_timer(f, s->frame_timer);
+}
+
+static int uhci_load(QEMUFile *f, void *opaque, int version_id)
+{
+ UHCIState *s = opaque;
+ uint8_t num_ports;
+ int i, ret;
+
+ if (version_id > 1)
+ return -EINVAL;
+
+ ret = pci_device_load(&s->dev, f);
+ if (ret < 0)
+ return ret;
+
+ qemu_get_8s(f, &num_ports);
+ if (num_ports != NB_PORTS)
+ return -EINVAL;
+
+ for (i = 0; i < num_ports; ++i)
+ qemu_get_be16s(f, &s->ports[i].ctrl);
+ qemu_get_be16s(f, &s->cmd);
+ qemu_get_be16s(f, &s->status);
+ qemu_get_be16s(f, &s->intr);
+ qemu_get_be16s(f, &s->frnum);
+ qemu_get_be32s(f, &s->fl_base_addr);
+ qemu_get_8s(f, &s->sof_timing);
+ qemu_get_8s(f, &s->status2);
+ qemu_get_timer(f, s->frame_timer);
+
+ return 0;
+}
+
static void uhci_ioport_writeb(void *opaque, uint32_t addr, uint32_t val)
{
UHCIState *s = opaque;
@@ -449,10 +503,11 @@
0 if TD successful
1 if TD unsuccessful or inactive
*/
-static int uhci_handle_td(UHCIState *s, UHCI_TD *td, int *int_mask)
+static int uhci_handle_td(UHCIState *s, UHCI_TD *td, int *int_mask,
+ int completion)
{
uint8_t pid;
- int len, max_len, err, ret;
+ int len = 0, max_len, err, ret = 0;
/* ??? This is wrong for async completion. */
if (td->ctrl & TD_CTRL_IOC) {
@@ -465,7 +520,8 @@
/* TD is active */
max_len = ((td->token >> 21) + 1) & 0x7ff;
pid = td->token & 0xff;
- if (s->async_qh) {
+
+ if (completion && (s->async_qh || s->async_frame_addr)) {
ret = s->usb_packet.len;
if (ret >= 0) {
len = ret;
@@ -481,7 +537,8 @@
len = 0;
}
s->async_qh = 0;
- } else {
+ s->async_frame_addr = 0;
+ } else if (!completion) {
s->usb_packet.pid = pid;
s->usb_packet.devaddr = (td->token >> 8) & 0x7f;
s->usb_packet.devep = (td->token >> 15) & 0xf;
@@ -519,6 +576,7 @@
return -1;
}
}
+
if (ret == USB_RET_ASYNC) {
return 2;
}
@@ -584,8 +642,42 @@
uint32_t link;
uint32_t old_td_ctrl;
uint32_t val;
+ uint32_t frame_addr;
int ret;
+ /* Handle async isochronous packet completion */
+ frame_addr = s->async_frame_addr;
+ if (frame_addr) {
+ cpu_physical_memory_read(frame_addr, (uint8_t *)&link, 4);
+ le32_to_cpus(&link);
+
+ cpu_physical_memory_read(link & ~0xf, (uint8_t *)&td, sizeof(td));
+ le32_to_cpus(&td.link);
+ le32_to_cpus(&td.ctrl);
+ le32_to_cpus(&td.token);
+ le32_to_cpus(&td.buffer);
+ old_td_ctrl = td.ctrl;
+ ret = uhci_handle_td(s, &td, &s->pending_int_mask, 1);
+
+ /* update the status bits of the TD */
+ if (old_td_ctrl != td.ctrl) {
+ val = cpu_to_le32(td.ctrl);
+ cpu_physical_memory_write((link & ~0xf) + 4,
+ (const uint8_t *)&val,
+ sizeof(val));
+ }
+ if (ret == 2) {
+ s->async_frame_addr = frame_addr;
+ } else if (ret == 0) {
+ /* update qh element link */
+ val = cpu_to_le32(td.link);
+ cpu_physical_memory_write(frame_addr,
+ (const uint8_t *)&val,
+ sizeof(val));
+ }
+ return;
+ }
+
link = s->async_qh;
if (!link) {
/* This should never happen. It means a TD somehow got removed
@@ -604,7 +696,8 @@
le32_to_cpus(&td.token);
le32_to_cpus(&td.buffer);
old_td_ctrl = td.ctrl;
- ret = uhci_handle_td(s, &td, &s->pending_int_mask);
+ ret = uhci_handle_td(s, &td, &s->pending_int_mask, 1);
+
/* update the status bits of the TD */
if (old_td_ctrl != td.ctrl) {
val = cpu_to_le32(td.ctrl);
@@ -697,7 +790,8 @@
le32_to_cpus(&td.token);
le32_to_cpus(&td.buffer);
old_td_ctrl = td.ctrl;
- ret = uhci_handle_td(s, &td, &int_mask);
+ ret = uhci_handle_td(s, &td, &int_mask, 0);
+
/* update the status bits of the TD */
if (old_td_ctrl != td.ctrl) {
val = cpu_to_le32(td.ctrl);
@@ -731,28 +825,24 @@
le32_to_cpus(&td.ctrl);
le32_to_cpus(&td.token);
le32_to_cpus(&td.buffer);
- /* Ignore isochonous transfers while there is an async packet
- pending. This is wrong, but we don't implement isochronous
- transfers anyway. */
- if (s->async_qh == 0) {
- old_td_ctrl = td.ctrl;
- ret = uhci_handle_td(s, &td, &int_mask);
- /* update the status bits of the TD */
- if (old_td_ctrl != td.ctrl) {
- val = cpu_to_le32(td.ctrl);
- cpu_physical_memory_write((link & ~0xf) + 4,
- (const uint8_t *)&val,
- sizeof(val));
- }
- if (ret < 0)
- break; /* interrupted frame */
- if (ret == 2) {
- /* We can't handle async isochronous transfers.
- Cancel The packet. */
- fprintf(stderr, "usb-uhci: Unimplemented async packet\n");
- usb_cancel_packet(&s->usb_packet);
- }
+
+ /* Handle isochonous transfer. */
+ /* FIXME: might be more than one isoc in frame */
+ old_td_ctrl = td.ctrl;
+ ret = uhci_handle_td(s, &td, &int_mask, 0);
+
+ /* update the status bits of the TD */
+ if (old_td_ctrl != td.ctrl) {
+ val = cpu_to_le32(td.ctrl);
+ cpu_physical_memory_write((link & ~0xf) + 4,
+ (const uint8_t *)&val,
+ sizeof(val));
}
+ if (ret < 0)
+ break; /* interrupted frame */
+ if (ret == 2) {
+ s->async_frame_addr = frame_addr;
+ }
link = td.link;
}
}
@@ -767,6 +857,7 @@
usb_cancel_packet(&s->usb_packet);
s->async_qh = 0;
}
+
/* prepare the timer for the next frame */
expire_time = qemu_get_clock(vm_clock) +
(ticks_per_sec / FRAME_TIMER_FREQ);
@@ -855,4 +946,3 @@
pci_register_io_region(&s->dev, 4, 0x20,
PCI_ADDRESS_SPACE_IO, uhci_map);
}
-
Modified: trunk/src/host/qemu-neo1973/hw/vmport.c
===================================================================
--- trunk/src/host/qemu-neo1973/hw/vmport.c 2007-10-29 20:40:05 UTC (rev 3302)
+++ trunk/src/host/qemu-neo1973/hw/vmport.c 2007-10-29 21:14:04 UTC (rev 3303)
@@ -52,7 +52,7 @@
{
VMPortState *s = opaque;
unsigned char command;
- target_ulong eax;
+ uint32_t eax;
eax = s->env->regs[R_EAX];
if (eax != VMPORT_MAGIC)
Modified: trunk/src/host/qemu-neo1973/linux-user/alpha/syscall.h
===================================================================
--- trunk/src/host/qemu-neo1973/linux-user/alpha/syscall.h 2007-10-29 20:40:05 UTC (rev 3302)
+++ trunk/src/host/qemu-neo1973/linux-user/alpha/syscall.h 2007-10-29 21:14:04 UTC (rev 3303)
@@ -2,40 +2,40 @@
#define __USER_DS (1)
struct target_pt_regs {
- target_ulong r0;
- target_ulong r1;
- target_ulong r2;
- target_ulong r3;
- target_ulong r4;
- target_ulong r5;
- target_ulong r6;
- target_ulong r7;
- target_ulong r8;
- target_ulong r19;
- target_ulong r20;
- target_ulong r21;
- target_ulong r22;
- target_ulong r23;
- target_ulong r24;
- target_ulong r25;
- target_ulong r26;
- target_ulong r27;
- target_ulong r28;
- target_ulong hae;
+ abi_ulong r0;
+ abi_ulong r1;
+ abi_ulong r2;
+ abi_ulong r3;
+ abi_ulong r4;
+ abi_ulong r5;
+ abi_ulong r6;
+ abi_ulong r7;
+ abi_ulong r8;
+ abi_ulong r19;
+ abi_ulong r20;
+ abi_ulong r21;
+ abi_ulong r22;
+ abi_ulong r23;
+ abi_ulong r24;
+ abi_ulong r25;
+ abi_ulong r26;
+ abi_ulong r27;
+ abi_ulong r28;
+ abi_ulong hae;
/* JRP - These are the values provided to a0-a2 by PALcode */
- target_ulong trap_a0;
- target_ulong trap_a1;
- target_ulong trap_a2;
+ abi_ulong trap_a0;
+ abi_ulong trap_a1;
+ abi_ulong trap_a2;
/* These are saved by PAL-code: */
- target_ulong ps;
- target_ulong pc;
- target_ulong gp;
- target_ulong r16;
- target_ulong r17;
- target_ulong r18;
+ abi_ulong ps;
+ abi_ulong pc;
+ abi_ulong gp;
+ abi_ulong r16;
+ abi_ulong r17;
+ abi_ulong r18;
/* Those is needed by qemu to temporary store the user stack pointer */
- target_ulong usp;
- target_ulong unique;
+ abi_ulong usp;
+ abi_ulong unique;
};
#define UNAME_MACHINE "alpha"
Modified: trunk/src/host/qemu-neo1973/linux-user/alpha/syscall_nr.h
===================================================================
--- trunk/src/host/qemu-neo1973/linux-user/alpha/syscall_nr.h 2007-10-29 20:40:05 UTC (rev 3302)
+++ trunk/src/host/qemu-neo1973/linux-user/alpha/syscall_nr.h 2007-10-29 21:14:04 UTC (rev 3303)
@@ -379,3 +379,35 @@
#define TARGET_NR_inotify_init 444
#define TARGET_NR_inotify_add_watch 445
#define TARGET_NR_inotify_rm_watch 446
+#define TARGET_NR_fdatasync 447
+#define TARGET_NR_kexec_load 448
+#define TARGET_NR_migrate_pages 449
+#define TARGET_NR_openat 450
+#define TARGET_NR_mkdirat 451
+#define TARGET_NR_mknodat 452
+#define TARGET_NR_fchownat 453
+#define TARGET_NR_futimesat 454
+#define TARGET_NR_fstatat64 455
+#define TARGET_NR_unlinkat 456
+#define TARGET_NR_renameat 457
+#define TARGET_NR_linkat 458
+#define TARGET_NR_symlinkat 459
+#define TARGET_NR_readlinkat 460
+#define TARGET_NR_fchmodat 461
+#define TARGET_NR_faccessat 462
+#define TARGET_NR_pselect6 463
+#define TARGET_NR_ppoll 464
+#define TARGET_NR_unshare 465
+#define TARGET_NR_set_robust_list 466
+#define TARGET_NR_get_robust_list 467
+#define TARGET_NR_splice 468
+#define TARGET_NR_sync_file_range 469
+#define TARGET_NR_tee 470
+#define TARGET_NR_vmsplice 471
+#define TARGET_NR_move_pages 472
+#define TARGET_NR_getcpu 473
+#define TARGET_NR_epoll_pwait 474
+#define TARGET_NR_utimensat 475
+#define TARGET_NR_signalfd 476
+#define TARGET_NR_timerfd 477
+#define TARGET_NR_eventfd 478
Added: trunk/src/host/qemu-neo1973/linux-user/alpha/target_signal.h
===================================================================
--- trunk/src/host/qemu-neo1973/linux-user/alpha/target_signal.h 2007-10-29 20:40:05 UTC (rev 3302)
+++ trunk/src/host/qemu-neo1973/linux-user/alpha/target_signal.h 2007-10-29 21:14:04 UTC (rev 3303)
@@ -0,0 +1,29 @@
+#ifndef TARGET_SIGNAL_H
+#define TARGET_SIGNAL_H
+
+#include "cpu.h"
+
+/* this struct defines a stack used during syscall handling */
+
+typedef struct target_sigaltstack {
+ abi_ulong ss_sp;
+ abi_long ss_flags;
+ abi_ulong ss_size;
+} target_stack_t;
+
+
+/*
+ * sigaltstack controls
+ */
+#define TARGET_SS_ONSTACK 1
+#define TARGET_SS_DISABLE 2
+
+#define TARGET_MINSIGSTKSZ 4096
+#define TARGET_SIGSTKSZ 16384
+
+static inline abi_ulong get_sp_from_cpustate(CPUAlphaState *state)
+{
+ return state->ir[IR_SP];
+}
+
+#endif /* TARGET_SIGNAL_H */
Modified: trunk/src/host/qemu-neo1973/linux-user/arm/syscall.h
===================================================================
--- trunk/src/host/qemu-neo1973/linux-user/arm/syscall.h 2007-10-29 20:40:05 UTC (rev 3302)
+++ trunk/src/host/qemu-neo1973/linux-user/arm/syscall.h 2007-10-29 21:14:04 UTC (rev 3303)
@@ -3,7 +3,7 @@
stack during a system call. */
struct target_pt_regs {
- target_long uregs[18];
+ abi_long uregs[18];
};
#define ARM_cpsr uregs[16]
Modified: trunk/src/host/qemu-neo1973/linux-user/arm/syscall_nr.h
===================================================================
--- trunk/src/host/qemu-neo1973/linux-user/arm/syscall_nr.h 2007-10-29 20:40:05 UTC (rev 3302)
+++ trunk/src/host/qemu-neo1973/linux-user/arm/syscall_nr.h 2007-10-29 21:14:04 UTC (rev 3303)
@@ -325,3 +325,34 @@
#define TARGET_NR_mbind 319
#define TARGET_NR_get_mempolicy 320
#define TARGET_NR_set_mempolicy 321
+#define TARGET_NR_openat (322)
+#define TARGET_NR_mkdirat (323)
+#define TARGET_NR_mknodat (324)
+#define TARGET_NR_fchownat (325)
+#define TARGET_NR_futimesat (326)
+#define TARGET_NR_fstatat64 (327)
+#define TARGET_NR_unlinkat (328)
+#define TARGET_NR_renameat (329)
+#define TARGET_NR_linkat (330)
+#define TARGET_NR_symlinkat (331)
+#define TARGET_NR_readlinkat (332)
+#define TARGET_NR_fchmodat (333)
+#define TARGET_NR_faccessat (334)
+ /* 335 for pselect6 */
+ /* 336 for ppoll */
+#define TARGET_NR_unshare (337)
+#define TARGET_NR_set_robust_list (338)
+#define TARGET_NR_get_robust_list (339)
+#define TARGET_NR_splice (340)
+#define TARGET_NR_arm_sync_file_range (341)
+#define TARGET_NR_sync_file_range2 TARGET_NR_arm_sync_file_range
+#define TARGET_NR_tee (342)
+#define TARGET_NR_vmsplice (343)
+#define TARGET_NR_move_pages (344)
+#define TARGET_NR_getcpu (345)
+ /* 346 for epoll_pwait */
+#define TARGET_NR_kexec_load (347)
+#define TARGET_NR_utimensat (348)
+#define TARGET_NR_signalfd (349)
+#define TARGET_NR_timerfd (350)
+#define TARGET_NR_eventfd (351)
Added: trunk/src/host/qemu-neo1973/linux-user/arm/target_signal.h
===================================================================
--- trunk/src/host/qemu-neo1973/linux-user/arm/target_signal.h 2007-10-29 20:40:05 UTC (rev 3302)
+++ trunk/src/host/qemu-neo1973/linux-user/arm/target_signal.h 2007-10-29 21:14:04 UTC (rev 3303)
@@ -0,0 +1,29 @@
+#ifndef TARGET_SIGNAL_H
+#define TARGET_SIGNAL_H
+
+#include "cpu.h"
+
+/* this struct defines a stack used during syscall handling */
+
+typedef struct target_sigaltstack {
+ abi_ulong ss_sp;
+ abi_long ss_flags;
+ abi_ulong ss_size;
+} target_stack_t;
+
+
+/*
+ * sigaltstack controls
+ */
+#define TARGET_SS_ONSTACK 1
+#define TARGET_SS_DISABLE 2
+
+#define TARGET_MINSIGSTKSZ 2048
+#define TARGET_SIGSTKSZ 8192
+
+static inline abi_ulong get_sp_from_cpustate(CPUARMState *state)
+{
+ return state->regs[13];
+}
+
+#endif /* TARGET_SIGNAL_H */
Modified: trunk/src/host/qemu-neo1973/linux-user/arm/termbits.h
===================================================================
--- trunk/src/host/qemu-neo1973/linux-user/arm/termbits.h 2007-10-29 20:40:05 UTC (rev 3302)
+++ trunk/src/host/qemu-neo1973/linux-user/arm/termbits.h 2007-10-29 21:14:04 UTC (rev 3303)
@@ -27,6 +27,7 @@
#define TARGET_IXANY 0004000
#define TARGET_IXOFF 0010000
#define TARGET_IMAXBEL 0020000
+#define TARGET_IUTF8 0040000
/* c_oflag bits */
#define TARGET_OPOST 0000001
@@ -98,7 +99,8 @@
#define TARGET_B230400 0010003
#define TARGET_B460800 0010004
#define TARGET_CIBAUD 002003600000 /* input baud rate (not used) */
-#define TARGET_CRTSCTS 020000000000 /* flow control */
+#define TARGET_CMSPAR 010000000000 /* mark or space (stick) parity */
+#define TARGET_CRTSCTS 020000000000 /* flow control */
/* c_lflag bits */
#define TARGET_ISIG 0000001
Added: trunk/src/host/qemu-neo1973/linux-user/cris/syscall.h
===================================================================
--- trunk/src/host/qemu-neo1973/linux-user/cris/syscall.h 2007-10-29 20:40:05 UTC (rev 3302)
+++ trunk/src/host/qemu-neo1973/linux-user/cris/syscall.h 2007-10-29 21:14:04 UTC (rev 3303)
@@ -0,0 +1,37 @@
+
+#define UNAME_MACHINE "cris"
+
+/* pt_regs not only specifices the format in the user-struct during
+ * ptrace but is also the frame format used in the kernel prologue/epilogues
+ * themselves
+ */
+
+struct target_pt_regs {
+ unsigned long orig_r10;
+ /* pushed by movem r13, [sp] in SAVE_ALL. */
+ unsigned long r0;
+ unsigned long r1;
+ unsigned long r2;
+ unsigned long r3;
+ unsigned long r4;
+ unsigned long r5;
+ unsigned long r6;
+ unsigned long r7;
+ unsigned long r8;
+ unsigned long r9;
+ unsigned long r10;
+ unsigned long r11;
+ unsigned long r12;
+ unsigned long r13;
+ unsigned long acr;
+ unsigned long srs;
+ unsigned long mof;
+ unsigned long spc;
+ unsigned long ccs;
+ unsigned long srp;
+ unsigned long erp; /* This is actually the debugged process' PC */
+ /* For debugging purposes; saved only when needed. */
+ unsigned long exs;
+ unsigned long eda;
+};
+
Added: trunk/src/host/qemu-neo1973/linux-user/cris/syscall_nr.h
===================================================================
--- trunk/src/host/qemu-neo1973/linux-user/cris/syscall_nr.h 2007-10-29 20:40:05 UTC (rev 3302)
+++ trunk/src/host/qemu-neo1973/linux-user/cris/syscall_nr.h 2007-10-29 21:14:04 UTC (rev 3303)
@@ -0,0 +1,291 @@
+/*
+ * This file contains the system call numbers, and stub macros for libc.
+ */
+
+#define TARGET_NR_restart_syscall 0
+#define TARGET_NR_exit 1
+#define TARGET_NR_fork 2
+#define TARGET_NR_read 3
+#define TARGET_NR_write 4
+#define TARGET_NR_open 5
+#define TARGET_NR_close 6
+#define TARGET_NR_waitpid 7
+#define TARGET_NR_creat 8
+#define TARGET_NR_link 9
+#define TARGET_NR_unlink 10
+#define TARGET_NR_execve 11
+#define TARGET_NR_chdir 12
+#define TARGET_NR_time 13
+#define TARGET_NR_mknod 14
+#define TARGET_NR_chmod 15
+#define TARGET_NR_lchown 16
+#define TARGET_NR_break 17
+#define TARGET_NR_oldstat 18
+#define TARGET_NR_lseek 19
+#define TARGET_NR_getpid 20
+#define TARGET_NR_mount 21
+#define TARGET_NR_umount 22
+#define TARGET_NR_setuid 23
+#define TARGET_NR_getuid 24
+#define TARGET_NR_stime 25
+#define TARGET_NR_ptrace 26
+#define TARGET_NR_alarm 27
+#define TARGET_NR_oldfstat 28
+#define TARGET_NR_pause 29
+#define TARGET_NR_utime 30
+#define TARGET_NR_stty 31
+#define TARGET_NR_gtty 32
+#define TARGET_NR_access 33
+#define TARGET_NR_nice 34
+#define TARGET_NR_ftime 35
+#define TARGET_NR_sync 36
+#define TARGET_NR_kill 37
+#define TARGET_NR_rename 38
+#define TARGET_NR_mkdir 39
+#define TARGET_NR_rmdir 40
+#define TARGET_NR_dup 41
+#define TARGET_NR_pipe 42
+#define TARGET_NR_times 43
+#define TARGET_NR_prof 44
+#define TARGET_NR_brk 45
+#define TARGET_NR_setgid 46
+#define TARGET_NR_getgid 47
+#define TARGET_NR_signal 48
+#define TARGET_NR_geteuid 49
+#define TARGET_NR_getegid 50
+#define TARGET_NR_acct 51
+#define TARGET_NR_umount2 52
+#define TARGET_NR_lock 53
+#define TARGET_NR_ioctl 54
+#define TARGET_NR_fcntl 55
+#define TARGET_NR_mpx 56
+#define TARGET_NR_setpgid 57
+#define TARGET_NR_ulimit 58
+#define TARGET_NR_oldolduname 59
+#define TARGET_NR_umask 60
+#define TARGET_NR_chroot 61
+#define TARGET_NR_ustat 62
+#define TARGET_NR_dup2 63
+#define TARGET_NR_getppid 64
+#define TARGET_NR_getpgrp 65
+#define TARGET_NR_setsid 66
+#define TARGET_NR_sigaction 67
+#define TARGET_NR_sgetmask 68
+#define TARGET_NR_ssetmask 69
+#define TARGET_NR_setreuid 70
+#define TARGET_NR_setregid 71
+#define TARGET_NR_sigsuspend 72
+#define TARGET_NR_sigpending 73
+#define TARGET_NR_sethostname 74
+#define TARGET_NR_setrlimit 75
+#define TARGET_NR_getrlimit 76
+#define TARGET_NR_getrusage 77
+#define TARGET_NR_gettimeofday 78
+#define TARGET_NR_settimeofday 79
+#define TARGET_NR_getgroups 80
+#define TARGET_NR_setgroups 81
+#define TARGET_NR_select 82
+#define TARGET_NR_symlink 83
+#define TARGET_NR_oldlstat 84
+#define TARGET_NR_readlink 85
+#define TARGET_NR_uselib 86
+#define TARGET_NR_swapon 87
+#define TARGET_NR_reboot 88
+#define TARGET_NR_readdir 89
+#define TARGET_NR_mmap 90
+#define TARGET_NR_munmap 91
+#define TARGET_NR_truncate 92
+#define TARGET_NR_ftruncate 93
+#define TARGET_NR_fchmod 94
+#define TARGET_NR_fchown 95
+#define TARGET_NR_getpriority 96
+#define TARGET_NR_setpriority 97
+#define TARGET_NR_profil 98
+#define TARGET_NR_statfs 99
+#define TARGET_NR_fstatfs 100
+#define TARGET_NR_ioperm 101
+#define TARGET_NR_socketcall 102
+#define TARGET_NR_syslog 103
+#define TARGET_NR_setitimer 104
+#define TARGET_NR_getitimer 105
+#define TARGET_NR_stat 106
+#define TARGET_NR_lstat 107
+#define TARGET_NR_fstat 108
+#define TARGET_NR_olduname 109
+#define TARGET_NR_iopl 110
+#define TARGET_NR_vhangup 111
+#define TARGET_NR_idle 112
+#define TARGET_NR_vm86 113
+#define TARGET_NR_wait4 114
+#define TARGET_NR_swapoff 115
+#define TARGET_NR_sysinfo 116
+#define TARGET_NR_ipc 117
+#define TARGET_NR_fsync 118
+#define TARGET_NR_sigreturn 119
+#define TARGET_NR_clone 120
+#define TARGET_NR_setdomainname 121
+#define TARGET_NR_uname 122
+#define TARGET_NR_modify_ldt 123
+#define TARGET_NR_adjtimex 124
+#define TARGET_NR_mprotect 125
+#define TARGET_NR_sigprocmask 126
+#define TARGET_NR_create_module 127
+#define TARGET_NR_init_module 128
+#define TARGET_NR_delete_module 129
+#define TARGET_NR_get_kernel_syms 130
+#define TARGET_NR_quotactl 131
+#define TARGET_NR_getpgid 132
+#define TARGET_NR_fchdir 133
+#define TARGET_NR_bdflush 134
+#define TARGET_NR_sysfs 135
+#define TARGET_NR_personality 136
+#define TARGET_NR_afs_syscall 137 /* Syscall for Andrew File System */
+#define TARGET_NR_setfsuid 138
+#define TARGET_NR_setfsgid 139
+#define TARGET_NR__llseek 140
+#define TARGET_NR_getdents 141
+#define TARGET_NR__newselect 142
+#define TARGET_NR_flock 143
+#define TARGET_NR_msync 144
+#define TARGET_NR_readv 145
+#define TARGET_NR_writev 146
+#define TARGET_NR_getsid 147
+#define TARGET_NR_fdatasync 148
+#define TARGET_NR__sysctl 149
+#define TARGET_NR_mlock 150
+#define TARGET_NR_munlock 151
+#define TARGET_NR_mlockall 152
+#define TARGET_NR_munlockall 153
+#define TARGET_NR_sched_setparam 154
+#define TARGET_NR_sched_getparam 155
+#define TARGET_NR_sched_setscheduler 156
+#define TARGET_NR_sched_getscheduler 157
+#define TARGET_NR_sched_yield 158
+#define TARGET_NR_sched_get_priority_max 159
+#define TARGET_NR_sched_get_priority_min 160
+#define TARGET_NR_sched_rr_get_interval 161
+#define TARGET_NR_nanosleep 162
+#define TARGET_NR_mremap 163
+#define TARGET_NR_setresuid 164
+#define TARGET_NR_getresuid 165
+
+#define TARGET_NR_query_module 167
+#define TARGET_NR_poll 168
+#define TARGET_NR_nfsservctl 169
+#define TARGET_NR_setresgid 170
+#define TARGET_NR_getresgid 171
+#define TARGET_NR_prctl 172
+#define TARGET_NR_rt_sigreturn 173
+#define TARGET_NR_rt_sigaction 174
+#define TARGET_NR_rt_sigprocmask 175
+#define TARGET_NR_rt_sigpending 176
+#define TARGET_NR_rt_sigtimedwait 177
+#define TARGET_NR_rt_sigqueueinfo 178
+#define TARGET_NR_rt_sigsuspend 179
+#define TARGET_NR_pread64 180
+#define TARGET_NR_pwrite64 181
+#define TARGET_NR_chown 182
+#define TARGET_NR_getcwd 183
+#define TARGET_NR_capget 184
+#define TARGET_NR_capset 185
+#define TARGET_NR_sigaltstack 186
+#define TARGET_NR_sendfile 187
+#define TARGET_NR_getpmsg 188 /* some people actually want streams */
+#define TARGET_NR_putpmsg 189 /* some people actually want streams */
+#define TARGET_NR_vfork 190
+#define TARGET_NR_ugetrlimit 191 /* SuS compliant getrlimit */
+#define TARGET_NR_mmap2 192
+#define TARGET_NR_truncate64 193
+#define TARGET_NR_ftruncate64 194
+#define TARGET_NR_stat64 195
+#define TARGET_NR_lstat64 196
+#define TARGET_NR_fstat64 197
+#define TARGET_NR_lchown32 198
+#define TARGET_NR_getuid32 199
+#define TARGET_NR_getgid32 200
+#define TARGET_NR_geteuid32 201
+#define TARGET_NR_getegid32 202
+#define TARGET_NR_setreuid32 203
+#define TARGET_NR_setregid32 204
+#define TARGET_NR_getgroups32 205
+#define TARGET_NR_setgroups32 206
+#define TARGET_NR_fchown32 207
+#define TARGET_NR_setresuid32 208
+#define TARGET_NR_getresuid32 209
+#define TARGET_NR_setresgid32 210
+#define TARGET_NR_getresgid32 211
+#define TARGET_NR_chown32 212
+#define TARGET_NR_setuid32 213
+#define TARGET_NR_setgid32 214
+#define TARGET_NR_setfsuid32 215
+#define TARGET_NR_setfsgid32 216
+#define TARGET_NR_pivot_root 217
+#define TARGET_NR_mincore 218
+#define TARGET_NR_madvise 219
+#define TARGET_NR_getdents64 220
+#define TARGET_NR_fcntl64 221
+/* 223 is unused */
+#define TARGET_NR_gettid 224
+#define TARGET_NR_readahead 225
+#define TARGET_NR_setxattr 226
+#define TARGET_NR_lsetxattr 227
+#define TARGET_NR_fsetxattr 228
+#define TARGET_NR_getxattr 229
+#define TARGET_NR_lgetxattr 230
+#define TARGET_NR_fgetxattr 231
+#define TARGET_NR_listxattr 232
+#define TARGET_NR_llistxattr 233
+#define TARGET_NR_flistxattr 234
+#define TARGET_NR_removexattr 235
+#define TARGET_NR_lremovexattr 236
+#define TARGET_NR_fremovexattr 237
+#define TARGET_NR_tkill 238
+#define TARGET_NR_sendfile64 239
+#define TARGET_NR_futex 240
+#define TARGET_NR_sched_setaffinity 241
+#define TARGET_NR_sched_getaffinity 242
+#define TARGET_NR_set_thread_area 243
+#define TARGET_NR_get_thread_area 244
+#define TARGET_NR_io_setup 245
+#define TARGET_NR_io_destroy 246
+#define TARGET_NR_io_getevents 247
+#define TARGET_NR_io_submit 248
+#define TARGET_NR_io_cancel 249
+#define TARGET_NR_fadvise64 250
+#define TARGET_NR_exit_group 252
+#define TARGET_NR_lookup_dcookie 253
+#define TARGET_NR_epoll_create 254
+#define TARGET_NR_epoll_ctl 255
+#define TARGET_NR_epoll_wait 256
+#define TARGET_NR_remap_file_pages 257
+#define TARGET_NR_set_tid_address 258
+#define TARGET_NR_timer_create 259
+#define TARGET_NR_timer_settime (TARGET_NR_timer_create+1)
+#define TARGET_NR_timer_gettime (TARGET_NR_timer_create+2)
+#define TARGET_NR_timer_getoverrun (TARGET_NR_timer_create+3)
+#define TARGET_NR_timer_delete (TARGET_NR_timer_create+4)
+#define TARGET_NR_clock_settime (TARGET_NR_timer_create+5)
+#define TARGET_NR_clock_gettime (TARGET_NR_timer_create+6)
+#define TARGET_NR_clock_getres (TARGET_NR_timer_create+7)
+#define TARGET_NR_clock_nanosleep (TARGET_NR_timer_create+8)
+#define TARGET_NR_statfs64 268
+#define TARGET_NR_fstatfs64 269
+#define TARGET_NR_tgkill 270
+#define TARGET_NR_utimes 271
+#define TARGET_NR_fadvise64_64 272
+#define TARGET_NR_vserver 273
+#define TARGET_NR_mbind 274
+#define TARGET_NR_get_mempolicy 275
+#define TARGET_NR_set_mempolicy 276
+#define TARGET_NR_mq_open 277
+#define TARGET_NR_mq_unlink (TARGET_NR_mq_open+1)
+#define TARGET_NR_mq_timedsend (TARGET_NR_mq_open+2)
+#define TARGET_NR_mq_timedreceive (TARGET_NR_mq_open+3)
+#define TARGET_NR_mq_notify (TARGET_NR_mq_open+4)
+#define TARGET_NR_mq_getsetattr (TARGET_NR_mq_open+5)
+#define TARGET_NR_kexec_load 283
+#define TARGET_NR_waitid 284
+/* #define TARGET_NR_sys_setaltroot 285 */
+#define TARGET_NR_add_key 286
+#define TARGET_NR_request_key 287
+#define TARGET_NR_keyctl 288
Added: trunk/src/host/qemu-neo1973/linux-user/cris/target_signal.h
===================================================================
--- trunk/src/host/qemu-neo1973/linux-user/cris/target_signal.h 2007-10-29 20:40:05 UTC (rev 3302)
+++ trunk/src/host/qemu-neo1973/linux-user/cris/target_signal.h 2007-10-29 21:14:04 UTC (rev 3303)
@@ -0,0 +1,29 @@
+#ifndef TARGET_SIGNAL_H
+#define TARGET_SIGNAL_H
+
+#include "cpu.h"
+
+/* this struct defines a stack used during syscall handling */
+
+typedef struct target_sigaltstack {
+ abi_ulong ss_sp;
+ abi_ulong ss_size;
+ abi_long ss_flags;
+} target_stack_t;
+
+
+/*
+ * sigaltstack controls
+ */
+#define TARGET_SS_ONSTACK 1
+#define TARGET_SS_DISABLE 2
+
+#define TARGET_MINSIGSTKSZ 2048
+#define TARGET_SIGSTKSZ 8192
+
+static inline abi_ulong get_sp_from_cpustate(CPUCRISState *state)
+{
+ return state->regs[14];
+}
+
+#endif /* TARGET_SIGNAL_H */
Added: trunk/src/host/qemu-neo1973/linux-user/cris/termbits.h
===================================================================
--- trunk/src/host/qemu-neo1973/linux-user/cris/termbits.h 2007-10-29 20:40:05 UTC (rev 3302)
+++ trunk/src/host/qemu-neo1973/linux-user/cris/termbits.h 2007-10-29 21:14:04 UTC (rev 3303)
@@ -0,0 +1,214 @@
+/* from asm/termbits.h */
+
+#define TARGET_NCCS 19
+
+struct target_termios {
+ unsigned int c_iflag; /* input mode flags */
+ unsigned int c_oflag; /* output mode flags */
+ unsigned int c_cflag; /* control mode flags */
+ unsigned int c_lflag; /* local mode flags */
+ unsigned char c_line; /* line discipline */
+ unsigned char c_cc[TARGET_NCCS]; /* control characters */
+};
+
+/* c_iflag bits */
+#define TARGET_IGNBRK 0000001
+#define TARGET_BRKINT 0000002
+#define TARGET_IGNPAR 0000004
+#define TARGET_PARMRK 0000010
+#define TARGET_INPCK 0000020
+#define TARGET_ISTRIP 0000040
+#define TARGET_INLCR 0000100
+#define TARGET_IGNCR 0000200
+#define TARGET_ICRNL 0000400
+#define TARGET_IUCLC 0001000
+#define TARGET_IXON 0002000
+#define TARGET_IXANY 0004000
+#define TARGET_IXOFF 0010000
+#define TARGET_IMAXBEL 0020000
+
+/* c_oflag bits */
+#define TARGET_OPOST 0000001
+#define TARGET_OLCUC 0000002
+#define TARGET_ONLCR 0000004
+#define TARGET_OCRNL 0000010
+#define TARGET_ONOCR 0000020
+#define TARGET_ONLRET 0000040
+#define TARGET_OFILL 0000100
+#define TARGET_OFDEL 0000200
+#define TARGET_NLDLY 0000400
+#define TARGET_NL0 0000000
+#define TARGET_NL1 0000400
+#define TARGET_CRDLY 0003000
+#define TARGET_CR0 0000000
+#define TARGET_CR1 0001000
+#define TARGET_CR2 0002000
+#define TARGET_CR3 0003000
+#define TARGET_TABDLY 0014000
+#define TARGET_TAB0 0000000
+#define TARGET_TAB1 0004000
+#define TARGET_TAB2 0010000
+#define TARGET_TAB3 0014000
+#define TARGET_XTABS 0014000
+#define TARGET_BSDLY 0020000
+#define TARGET_BS0 0000000
+#define TARGET_BS1 0020000
+#define TARGET_VTDLY 0040000
+#define TARGET_VT0 0000000
+#define TARGET_VT1 0040000
+#define TARGET_FFDLY 0100000
+#define TARGET_FF0 0000000
+#define TARGET_FF1 0100000
+
+/* c_cflag bit meaning */
+#define TARGET_CBAUD 0010017
+#define TARGET_B0 0000000 /* hang up */
+#define TARGET_B50 0000001
+#define TARGET_B75 0000002
+#define TARGET_B110 0000003
+#define TARGET_B134 0000004
+#define TARGET_B150 0000005
+#define TARGET_B200 0000006
+#define TARGET_B300 0000007
+#define TARGET_B600 0000010
+#define TARGET_B1200 0000011
+#define TARGET_B1800 0000012
+#define TARGET_B2400 0000013
+#define TARGET_B4800 0000014
+#define TARGET_B9600 0000015
+#define TARGET_B19200 0000016
+#define TARGET_B38400 0000017
+#define TARGET_EXTA B19200
+#define TARGET_EXTB B38400
+#define TARGET_CSIZE 0000060
+#define TARGET_CS5 0000000
+#define TARGET_CS6 0000020
+#define TARGET_CS7 0000040
+#define TARGET_CS8 0000060
+#define TARGET_CSTOPB 0000100
+#define TARGET_CREAD 0000200
+#define TARGET_PARENB 0000400
+#define TARGET_PARODD 0001000
+#define TARGET_HUPCL 0002000
+#define TARGET_CLOCAL 0004000
+#define TARGET_CBAUDEX 0010000
+#define TARGET_B57600 0010001
+#define TARGET_B115200 0010002
+#define TARGET_B230400 0010003
+#define TARGET_B460800 0010004
+#define TARGET_CIBAUD 002003600000 /* input baud rate (not used) */
+#define TARGET_CRTSCTS 020000000000 /* flow control */
+
+/* c_lflag bits */
+#define TARGET_ISIG 0000001
+#define TARGET_ICANON 0000002
+#define TARGET_XCASE 0000004
+#define TARGET_ECHO 0000010
+#define TARGET_ECHOE 0000020
+#define TARGET_ECHOK 0000040
+#define TARGET_ECHONL 0000100
+#define TARGET_NOFLSH 0000200
+#define TARGET_TOSTOP 0000400
+#define TARGET_ECHOCTL 0001000
+#define TARGET_ECHOPRT 0002000
+#define TARGET_ECHOKE 0004000
+#define TARGET_FLUSHO 0010000
+#define TARGET_PENDIN 0040000
+#define TARGET_IEXTEN 0100000
+
+/* c_cc character offsets */
+#define TARGET_VINTR 0
+#define TARGET_VQUIT 1
+#define TARGET_VERASE 2
+#define TARGET_VKILL 3
+#define TARGET_VEOF 4
+#define TARGET_VTIME 5
+#define TARGET_VMIN 6
+#define TARGET_VSWTC 7
+#define TARGET_VSTART 8
+#define TARGET_VSTOP 9
+#define TARGET_VSUSP 10
+#define TARGET_VEOL 11
+#define TARGET_VREPRINT 12
+#define TARGET_VDISCARD 13
+#define TARGET_VWERASE 14
+#define TARGET_VLNEXT 15
+#define TARGET_VEOL2 16
+
+/* ioctls */
+
+#define TARGET_TCGETS 0x5401
+#define TARGET_TCSETS 0x5402
+#define TARGET_TCSETSW 0x5403
+#define TARGET_TCSETSF 0x5404
+#define TARGET_TCGETA 0x5405
+#define TARGET_TCSETA 0x5406
+#define TARGET_TCSETAW 0x5407
+#define TARGET_TCSETAF 0x5408
+#define TARGET_TCSBRK 0x5409
+#define TARGET_TCXONC 0x540A
+#define TARGET_TCFLSH 0x540B
+
+#define TARGET_TIOCEXCL 0x540C
+#define TARGET_TIOCNXCL 0x540D
+#define TARGET_TIOCSCTTY 0x540E
+#define TARGET_TIOCGPGRP 0x540F
+#define TARGET_TIOCSPGRP 0x5410
+#define TARGET_TIOCOUTQ 0x5411
+#define TARGET_TIOCSTI 0x5412
+#define TARGET_TIOCGWINSZ 0x5413
+#define TARGET_TIOCSWINSZ 0x5414
+#define TARGET_TIOCMGET 0x5415
+#define TARGET_TIOCMBIS 0x5416
+#define TARGET_TIOCMBIC 0x5417
+#define TARGET_TIOCMSET 0x5418
+#define TARGET_TIOCGSOFTCAR 0x5419
+#define TARGET_TIOCSSOFTCAR 0x541A
+#define TARGET_FIONREAD 0x541B
+#define TARGET_TIOCINQ TARGET_FIONREAD
+#define TARGET_TIOCLINUX 0x541C
+#define TARGET_TIOCCONS 0x541D
+#define TARGET_TIOCGSERIAL 0x541E
+#define TARGET_TIOCSSERIAL 0x541F
+#define TARGET_TIOCPKT 0x5420
+#define TARGET_FIONBIO 0x5421
+#define TARGET_TIOCNOTTY 0x5422
+#define TARGET_TIOCSETD 0x5423
+#define TARGET_TIOCGETD 0x5424
+#define TARGET_TCSBRKP 0x5425 /* Needed for POSIX tcsendbreak() */
+#define TARGET_TIOCTTYGSTRUCT 0x5426 /* For debugging only */
+#define TARGET_TIOCSBRK 0x5427 /* BSD compatibility */
+#define TARGET_TIOCCBRK 0x5428 /* BSD compatibility */
+#define TARGET_TIOCGSID 0x5429 /* Return the session ID of FD */
+#define TARGET_TIOCGPTN TARGET_IOR('T',0x30, unsigned int) /* Get Pty Number (of pty-mux device) */
+#define TARGET_TIOCSPTLCK TARGET_IOW('T',0x31, int) /* Lock/unlock Pty */
+
+#define TARGET_FIONCLEX 0x5450 /* these numbers need to be adjusted. */
+#define TARGET_FIOCLEX 0x5451
+#define TARGET_FIOASYNC 0x5452
+#define TARGET_TIOCSERCONFIG 0x5453
+#define TARGET_TIOCSERGWILD 0x5454
+#define TARGET_TIOCSERSWILD 0x5455
+#define TARGET_TIOCGLCKTRMIOS 0x5456
+#define TARGET_TIOCSLCKTRMIOS 0x5457
+#define TARGET_TIOCSERGSTRUCT 0x5458 /* For debugging only */
+#define TARGET_TIOCSERGETLSR 0x5459 /* Get line status register */
+#define TARGET_TIOCSERGETMULTI 0x545A /* Get multiport config */
+#define TARGET_TIOCSERSETMULTI 0x545B /* Set multiport config */
+
+#define TARGET_TIOCMIWAIT 0x545C /* wait for a change on serial input line(s) */
+#define TARGET_TIOCGICOUNT 0x545D /* read serial port inline interrupt counts */
+#define TARGET_TIOCGHAYESESP 0x545E /* Get Hayes ESP configuration */
+#define TARGET_TIOCSHAYESESP 0x545F /* Set Hayes ESP configuration */
+
+/* Used for packet mode */
+#define TARGET_TIOCPKT_DATA 0
+#define TARGET_TIOCPKT_FLUSHREAD 1
+#define TARGET_TIOCPKT_FLUSHWRITE 2
+#define TARGET_TIOCPKT_STOP 4
+#define TARGET_TIOCPKT_START 8
+#define TARGET_TIOCPKT_NOSTOP 16
+#define TARGET_TIOCPKT_DOSTOP 32
+
+#define TARGET_TIOCSER_TEMT 0x01 /* Transmitter physically empty */
+
Modified: trunk/src/host/qemu-neo1973/linux-user/elfload.c
===================================================================
--- trunk/src/host/qemu-neo1973/linux-user/elfload.c 2007-10-29 20:40:05 UTC (rev 3302)
+++ trunk/src/host/qemu-neo1973/linux-user/elfload.c 2007-10-29 21:14:04 UTC (rev 3303)
@@ -12,6 +12,66 @@
#include "qemu.h"
#include "disas.h"
+/* from personality.h */
+
+/*
+ * Flags for bug emulation.
+ *
+ * These occupy the top three bytes.
+ */
+enum {
+ ADDR_NO_RANDOMIZE = 0x0040000, /* disable randomization of VA space */
+ FDPIC_FUNCPTRS = 0x0080000, /* userspace function ptrs point to descriptors
+ * (signal handling)
+ */
+ MMAP_PAGE_ZERO = 0x0100000,
+ ADDR_COMPAT_LAYOUT = 0x0200000,
+ READ_IMPLIES_EXEC = 0x0400000,
+ ADDR_LIMIT_32BIT = 0x0800000,
+ SHORT_INODE = 0x1000000,
+ WHOLE_SECONDS = 0x2000000,
+ STICKY_TIMEOUTS = 0x4000000,
+ ADDR_LIMIT_3GB = 0x8000000,
+};
+
+/*
+ * Personality types.
+ *
+ * These go in the low byte. Avoid using the top bit, it will
+ * conflict with error returns.
+ */
+enum {
+ PER_LINUX = 0x0000,
+ PER_LINUX_32BIT = 0x0000 | ADDR_LIMIT_32BIT,
+ PER_LINUX_FDPIC = 0x0000 | FDPIC_FUNCPTRS,
+ PER_SVR4 = 0x0001 | STICKY_TIMEOUTS | MMAP_PAGE_ZERO,
+ PER_SVR3 = 0x0002 | STICKY_TIMEOUTS | SHORT_INODE,
+ PER_SCOSVR3 = 0x0003 | STICKY_TIMEOUTS |
+ WHOLE_SECONDS | SHORT_INODE,
+ PER_OSR5 = 0x0003 | STICKY_TIMEOUTS | WHOLE_SECONDS,
+ PER_WYSEV386 = 0x0004 | STICKY_TIMEOUTS | SHORT_INODE,
+ PER_ISCR4 = 0x0005 | STICKY_TIMEOUTS,
+ PER_BSD = 0x0006,
+ PER_SUNOS = 0x0006 | STICKY_TIMEOUTS,
+ PER_XENIX = 0x0007 | STICKY_TIMEOUTS | SHORT_INODE,
+ PER_LINUX32 = 0x0008,
+ PER_LINUX32_3GB = 0x0008 | ADDR_LIMIT_3GB,
+ PER_IRIX32 = 0x0009 | STICKY_TIMEOUTS,/* IRIX5 32-bit */
+ PER_IRIXN32 = 0x000a | STICKY_TIMEOUTS,/* IRIX6 new 32-bit */
+ PER_IRIX64 = 0x000b | STICKY_TIMEOUTS,/* IRIX6 64-bit */
+ PER_RISCOS = 0x000c,
+ PER_SOLARIS = 0x000d | STICKY_TIMEOUTS,
+ PER_UW7 = 0x000e | STICKY_TIMEOUTS | MMAP_PAGE_ZERO,
+ PER_OSF4 = 0x000f, /* OSF/1 v4 */
+ PER_HPUX = 0x0010,
+ PER_MASK = 0x00ff,
+};
+
+/*
+ * Return the base personality without flags.
+ */
+#define personality(pers) (pers & PER_MASK)
+
/* this flag is uneffective under linux too, should be deleted */
#ifndef MAP_DENYWRITE
#define MAP_DENYWRITE 0
@@ -112,7 +172,7 @@
static inline void init_thread(struct target_pt_regs *regs, struct image_info *infop)
{
- target_long stack = infop->start_stack;
+ abi_long stack = infop->start_stack;
memset(regs, 0, sizeof(*regs));
regs->ARM_cpsr = 0x10;
if (infop->entry & 1)
@@ -124,6 +184,7 @@
/* XXX: it seems that r0 is zeroed after ! */
regs->ARM_r0 = 0;
/* For uClinux PIC binaries. */
+ /* XXX: Linux does this only on ARM with no MMU (do we care ?) */
regs->ARM_r10 = infop->start_data;
}
@@ -153,7 +214,11 @@
#define ELF_START_MMAP 0x80000000
-#define elf_check_arch(x) ( (x) == EM_SPARCV9 )
+#ifndef TARGET_ABI32
+#define elf_check_arch(x) ( (x) == EM_SPARCV9 || (x) == EM_SPARC32PLUS )
+#else
+#define elf_check_arch(x) ( (x) == EM_SPARC32PLUS || (x) == EM_SPARC )
+#endif
#define ELF_CLASS ELFCLASS64
#define ELF_DATA ELFDATA2MSB
@@ -163,11 +228,20 @@
static inline void init_thread(struct target_pt_regs *regs, struct image_info *infop)
{
+#ifndef TARGET_ABI32
regs->tstate = 0;
+#endif
regs->pc = infop->entry;
regs->npc = regs->pc + 4;
regs->y = 0;
- regs->u_regs[14] = infop->start_stack - 16 * 8 - STACK_BIAS;
+#ifdef TARGET_ABI32
+ regs->u_regs[14] = infop->start_stack - 16 * 4;
+#else
+ if (personality(infop->personality) == PER_LINUX32)
+ regs->u_regs[14] = infop->start_stack - 16 * 4;
+ else
+ regs->u_regs[14] = infop->start_stack - 16 * 8 - STACK_BIAS;
+#endif
}
#else
@@ -195,7 +269,7 @@
#define ELF_START_MMAP 0x80000000
-#ifdef TARGET_PPC64
+#if defined(TARGET_PPC64) && !defined(TARGET_ABI32)
#define elf_check_arch(x) ( (x) == EM_PPC64 )
@@ -249,15 +323,14 @@
static inline void init_thread(struct target_pt_regs *_regs, struct image_info *infop)
{
- target_ulong pos = infop->start_stack;
- target_ulong tmp;
-#ifdef TARGET_PPC64
- target_ulong entry, toc;
+ abi_ulong pos = infop->start_stack;
+ abi_ulong tmp;
+#if defined(TARGET_PPC64) && !defined(TARGET_ABI32)
+ abi_ulong entry, toc;
#endif
- _regs->msr = 1 << MSR_PR; /* Set user mode */
_regs->gpr[1] = infop->start_stack;
-#ifdef TARGET_PPC64
+#if defined(TARGET_PPC64) && !defined(TARGET_ABI32)
entry = ldq_raw(infop->entry) + infop->load_addr;
toc = ldq_raw(infop->entry + 8) + infop->load_addr;
_regs->gpr[2] = toc;
@@ -269,9 +342,9 @@
* execution of PPC BSD programs.
*/
_regs->gpr[3] = tgetl(pos);
- pos += sizeof(target_ulong);
+ pos += sizeof(abi_ulong);
_regs->gpr[4] = pos;
- for (tmp = 1; tmp != 0; pos += sizeof(target_ulong))
+ for (tmp = 1; tmp != 0; pos += sizeof(abi_ulong))
tmp = ldl(pos);
_regs->gpr[5] = pos;
}
@@ -301,7 +374,7 @@
static inline void init_thread(struct target_pt_regs *regs, struct image_info *infop)
{
- regs->cp0_status = CP0St_UM;
+ regs->cp0_status = 2 << CP0St_KSU;
regs->cp0_epc = infop->entry;
regs->regs[29] = infop->start_stack;
}
@@ -333,6 +406,26 @@
#endif
+#ifdef TARGET_CRIS
+
+#define ELF_START_MMAP 0x80000000
+
+#define elf_check_arch(x) ( (x) == EM_CRIS )
+
+#define ELF_CLASS ELFCLASS32
+#define ELF_DATA ELFDATA2LSB
+#define ELF_ARCH EM_CRIS
+
+static inline void init_thread(struct target_pt_regs *regs, struct image_info *infop)
+{
+ regs->erp = infop->entry;
+}
+
+#define USE_ELF_CORE_DUMP
+#define ELF_EXEC_PAGESIZE 8192
+
+#endif
+
#ifdef TARGET_M68K
#define ELF_START_MMAP 0x80000000
@@ -391,6 +484,13 @@
#define ELF_HWCAP 0
#endif
+#ifdef TARGET_ABI32
+#undef ELF_CLASS
+#define ELF_CLASS ELFCLASS32
+#undef bswaptls
+#define bswaptls(ptr) bswap32s(ptr)
+#endif
+
#include "elf.h"
struct exec
@@ -418,25 +518,6 @@
/* max code+data+bss+brk space allocated to ET_DYN executables */
#define ET_DYN_MAP_SIZE (128 * 1024 * 1024)
-/* from personality.h */
-
-/* Flags for bug emulation. These occupy the top three bytes. */
-#define STICKY_TIMEOUTS 0x4000000
-#define WHOLE_SECONDS 0x2000000
-
-/* Personality types. These go in the low byte. Avoid using the top bit,
- * it will conflict with error returns.
- */
-#define PER_MASK (0x00ff)
-#define PER_LINUX (0x0000)
-#define PER_SVR4 (0x0001 | STICKY_TIMEOUTS)
-#define PER_SVR3 (0x0002 | STICKY_TIMEOUTS)
-#define PER_SCOSVR3 (0x0003 | STICKY_TIMEOUTS | WHOLE_SECONDS)
-#define PER_WYSEV386 (0x0004 | STICKY_TIMEOUTS)
-#define PER_ISCR4 (0x0005 | STICKY_TIMEOUTS)
-#define PER_BSD (0x0006)
-#define PER_XENIX (0x0007 | STICKY_TIMEOUTS)
-
/* Necessary parameters */
#define TARGET_ELF_EXEC_PAGESIZE TARGET_PAGE_SIZE
#define TARGET_ELF_PAGESTART(_v) ((_v) & ~(unsigned long)(TARGET_ELF_EXEC_PAGESIZE-1))
@@ -516,8 +597,8 @@
* to be put directly into the top of new user memory.
*
*/
-static unsigned long copy_elf_strings(int argc,char ** argv, void **page,
- unsigned long p)
+static abi_ulong copy_elf_strings(int argc,char ** argv, void **page,
+ abi_ulong p)
{
char *tmp, *tmp1, *pag = NULL;
int len, offset = 0;
@@ -544,6 +625,7 @@
pag = (char *)page[p/TARGET_PAGE_SIZE];
if (!pag) {
pag = (char *)malloc(TARGET_PAGE_SIZE);
+ memset(pag, 0, TARGET_PAGE_SIZE);
page[p/TARGET_PAGE_SIZE] = pag;
if (!pag)
return 0;
@@ -565,10 +647,10 @@
return p;
}
-unsigned long setup_arg_pages(target_ulong p, struct linux_binprm * bprm,
- struct image_info * info)
+static abi_ulong setup_arg_pages(abi_ulong p, struct linux_binprm *bprm,
+ struct image_info *info)
{
- target_ulong stack_base, size, error;
+ abi_ulong stack_base, size, error;
int i;
/* Create enough stack to hold everything. If we don't use
@@ -604,7 +686,7 @@
return p;
}
-static void set_brk(unsigned long start, unsigned long end)
+static void set_brk(abi_ulong start, abi_ulong end)
{
/* page-align the start and end addresses... */
start = HOST_PAGE_ALIGN(start);
@@ -623,9 +705,9 @@
/* We need to explicitly zero any fractional pages after the data
section (i.e. bss). This would contain the junk from the file that
should not be in memory. */
-static void padzero(unsigned long elf_bss, unsigned long last_bss)
+static void padzero(abi_ulong elf_bss, abi_ulong last_bss)
{
- unsigned long nbyte;
+ abi_ulong nbyte;
if (elf_bss >= last_bss)
return;
@@ -636,12 +718,12 @@
patch target_mmap(), but it is more complicated as the file
size must be known */
if (qemu_real_host_page_size < qemu_host_page_size) {
- unsigned long end_addr, end_addr1;
+ abi_ulong end_addr, end_addr1;
end_addr1 = (elf_bss + qemu_real_host_page_size - 1) &
~(qemu_real_host_page_size - 1);
end_addr = HOST_PAGE_ALIGN(elf_bss);
if (end_addr1 < end_addr) {
- mmap((void *)end_addr1, end_addr - end_addr1,
+ mmap((void *)g2h(end_addr1), end_addr - end_addr1,
PROT_READ|PROT_WRITE|PROT_EXEC,
MAP_FIXED|MAP_PRIVATE|MAP_ANONYMOUS, -1, 0);
}
@@ -658,18 +740,18 @@
}
-static unsigned long create_elf_tables(target_ulong p, int argc, int envc,
- struct elfhdr * exec,
- unsigned long load_addr,
- unsigned long load_bias,
- unsigned long interp_load_addr, int ibcs,
- struct image_info *info)
+static abi_ulong create_elf_tables(abi_ulong p, int argc, int envc,
+ struct elfhdr * exec,
+ abi_ulong load_addr,
+ abi_ulong load_bias,
+ abi_ulong interp_load_addr, int ibcs,
+ struct image_info *info)
{
- target_ulong sp;
+ abi_ulong sp;
int size;
- target_ulong u_platform;
+ abi_ulong u_platform;
const char *k_platform;
- const int n = sizeof(target_ulong);
+ const int n = sizeof(elf_addr_t);
sp = p;
u_platform = 0;
@@ -683,7 +765,7 @@
/*
* Force 16 byte _final_ alignment here for generality.
*/
- sp = sp &~ (target_ulong)15;
+ sp = sp &~ (abi_ulong)15;
size = (DLINFO_ITEMS + 1) * 2;
if (k_platform)
size += 2;
@@ -696,25 +778,35 @@
if (size & 15)
sp -= 16 - (size & 15);
+ /* This is correct because Linux defines
+ * elf_addr_t as Elf32_Off / Elf64_Off
+ */
+#if ELF_CLASS == ELFCLASS32
#define NEW_AUX_ENT(id, val) do { \
- sp -= n; tputl(sp, val); \
- sp -= n; tputl(sp, id); \
+ sp -= n; tput32(sp, val); \
+ sp -= n; tput32(sp, id); \
} while(0)
+#else
+#define NEW_AUX_ENT(id, val) do { \
+ sp -= n; tput64(sp, val); \
+ sp -= n; tput64(sp, id); \
+ } while(0)
+#endif
NEW_AUX_ENT (AT_NULL, 0);
/* There must be exactly DLINFO_ITEMS entries here. */
- NEW_AUX_ENT(AT_PHDR, (target_ulong)(load_addr + exec->e_phoff));
- NEW_AUX_ENT(AT_PHENT, (target_ulong)(sizeof (struct elf_phdr)));
- NEW_AUX_ENT(AT_PHNUM, (target_ulong)(exec->e_phnum));
- NEW_AUX_ENT(AT_PAGESZ, (target_ulong)(TARGET_PAGE_SIZE));
- NEW_AUX_ENT(AT_BASE, (target_ulong)(interp_load_addr));
- NEW_AUX_ENT(AT_FLAGS, (target_ulong)0);
+ NEW_AUX_ENT(AT_PHDR, (abi_ulong)(load_addr + exec->e_phoff));
+ NEW_AUX_ENT(AT_PHENT, (abi_ulong)(sizeof (struct elf_phdr)));
+ NEW_AUX_ENT(AT_PHNUM, (abi_ulong)(exec->e_phnum));
+ NEW_AUX_ENT(AT_PAGESZ, (abi_ulong)(TARGET_PAGE_SIZE));
+ NEW_AUX_ENT(AT_BASE, (abi_ulong)(interp_load_addr));
+ NEW_AUX_ENT(AT_FLAGS, (abi_ulong)0);
NEW_AUX_ENT(AT_ENTRY, load_bias + exec->e_entry);
- NEW_AUX_ENT(AT_UID, (target_ulong) getuid());
- NEW_AUX_ENT(AT_EUID, (target_ulong) geteuid());
- NEW_AUX_ENT(AT_GID, (target_ulong) getgid());
- NEW_AUX_ENT(AT_EGID, (target_ulong) getegid());
- NEW_AUX_ENT(AT_HWCAP, (target_ulong) ELF_HWCAP);
+ NEW_AUX_ENT(AT_UID, (abi_ulong) getuid());
+ NEW_AUX_ENT(AT_EUID, (abi_ulong) geteuid());
+ NEW_AUX_ENT(AT_GID, (abi_ulong) getgid());
+ NEW_AUX_ENT(AT_EGID, (abi_ulong) getegid());
+ NEW_AUX_ENT(AT_HWCAP, (abi_ulong) ELF_HWCAP);
if (k_platform)
NEW_AUX_ENT(AT_PLATFORM, u_platform);
#ifdef ARCH_DLINFO
@@ -731,17 +823,17 @@
}
-static unsigned long load_elf_interp(struct elfhdr * interp_elf_ex,
- int interpreter_fd,
- unsigned long *interp_load_addr)
+static abi_ulong load_elf_interp(struct elfhdr * interp_elf_ex,
+ int interpreter_fd,
+ abi_ulong *interp_load_addr)
{
struct elf_phdr *elf_phdata = NULL;
struct elf_phdr *eppnt;
- unsigned long load_addr = 0;
+ abi_ulong load_addr = 0;
int load_addr_set = 0;
int retval;
- unsigned long last_bss, elf_bss;
- unsigned long error;
+ abi_ulong last_bss, elf_bss;
+ abi_ulong error;
int i;
elf_bss = 0;
@@ -755,20 +847,20 @@
if ((interp_elf_ex->e_type != ET_EXEC &&
interp_elf_ex->e_type != ET_DYN) ||
!elf_check_arch(interp_elf_ex->e_machine)) {
- return ~0UL;
+ return ~((abi_ulong)0UL);
}
/* Now read in all of the header information */
if (sizeof(struct elf_phdr) * interp_elf_ex->e_phnum > TARGET_PAGE_SIZE)
- return ~0UL;
+ return ~(abi_ulong)0UL;
elf_phdata = (struct elf_phdr *)
malloc(sizeof(struct elf_phdr) * interp_elf_ex->e_phnum);
if (!elf_phdata)
- return ~0UL;
+ return ~((abi_ulong)0UL);
/*
* If the size of this structure has changed, then punt, since
@@ -776,7 +868,7 @@
*/
if (interp_elf_ex->e_phentsize != sizeof(struct elf_phdr)) {
free(elf_phdata);
- return ~0UL;
+ return ~((abi_ulong)0UL);
}
retval = lseek(interpreter_fd, interp_elf_ex->e_phoff, SEEK_SET);
@@ -817,8 +909,8 @@
if (eppnt->p_type == PT_LOAD) {
int elf_type = MAP_PRIVATE | MAP_DENYWRITE;
int elf_prot = 0;
- unsigned long vaddr = 0;
- unsigned long k;
+ abi_ulong vaddr = 0;
+ abi_ulong k;
if (eppnt->p_flags & PF_R) elf_prot = PROT_READ;
if (eppnt->p_flags & PF_W) elf_prot |= PROT_WRITE;
@@ -838,7 +930,7 @@
/* Real error */
close(interpreter_fd);
free(elf_phdata);
- return ~0UL;
+ return ~((abi_ulong)0UL);
}
if (!load_addr_set && interp_elf_ex->e_type == ET_DYN) {
@@ -883,7 +975,7 @@
free(elf_phdata);
*interp_load_addr = load_addr;
- return ((unsigned long) interp_elf_ex->e_entry) + load_addr;
+ return ((abi_ulong) interp_elf_ex->e_entry) + load_addr;
}
/* Best attempt to load symbols from this ELF object. */
@@ -971,22 +1063,22 @@
struct elfhdr interp_elf_ex;
struct exec interp_ex;
int interpreter_fd = -1; /* avoid warning */
- unsigned long load_addr, load_bias;
+ abi_ulong load_addr, load_bias;
int load_addr_set = 0;
unsigned int interpreter_type = INTERPRETER_NONE;
unsigned char ibcs2_interpreter;
int i;
- unsigned long mapped_addr;
+ abi_ulong mapped_addr;
struct elf_phdr * elf_ppnt;
struct elf_phdr *elf_phdata;
- unsigned long elf_bss, k, elf_brk;
+ abi_ulong elf_bss, k, elf_brk;
int retval;
char * elf_interpreter;
- unsigned long elf_entry, interp_load_addr = 0;
+ abi_ulong elf_entry, interp_load_addr = 0;
int status;
- unsigned long start_code, end_code, end_data;
- unsigned long reloc_func_desc = 0;
- unsigned long elf_stack;
+ abi_ulong start_code, end_code, start_data, end_data;
+ abi_ulong reloc_func_desc = 0;
+ abi_ulong elf_stack;
char passed_fileno[6];
ibcs2_interpreter = 0;
@@ -1042,10 +1134,11 @@
elf_brk = 0;
- elf_stack = ~0UL;
+ elf_stack = ~((abi_ulong)0UL);
elf_interpreter = NULL;
- start_code = ~0UL;
+ start_code = ~((abi_ulong)0UL);
end_code = 0;
+ start_data = 0;
end_data = 0;
for(i=0;i < elf_ex.e_phnum; i++) {
@@ -1179,9 +1272,9 @@
/* OK, This is the point of no return */
info->end_data = 0;
info->end_code = 0;
- info->start_mmap = (unsigned long)ELF_START_MMAP;
+ info->start_mmap = (abi_ulong)ELF_START_MMAP;
info->mmap = 0;
- elf_entry = (unsigned long) elf_ex.e_entry;
+ elf_entry = (abi_ulong) elf_ex.e_entry;
/* Do this so that we can load the interpreter, if need be. We will
change some of these later */
@@ -1198,7 +1291,7 @@
for(i = 0, elf_ppnt = elf_phdata; i < elf_ex.e_phnum; i++, elf_ppnt++) {
int elf_prot = 0;
int elf_flags = 0;
- unsigned long error;
+ abi_ulong error;
if (elf_ppnt->p_type != PT_LOAD)
continue;
@@ -1256,6 +1349,8 @@
k = elf_ppnt->p_vaddr;
if (k < start_code)
start_code = k;
+ if (start_data < k)
+ start_data = k;
k = elf_ppnt->p_vaddr + elf_ppnt->p_filesz;
if (k > elf_bss)
elf_bss = k;
@@ -1272,7 +1367,7 @@
elf_brk += load_bias;
start_code += load_bias;
end_code += load_bias;
- // start_data += load_bias;
+ start_data += load_bias;
end_data += load_bias;
if (elf_interpreter) {
@@ -1288,7 +1383,7 @@
close(interpreter_fd);
free(elf_interpreter);
- if (elf_entry == ~0UL) {
+ if (elf_entry == ~((abi_ulong)0UL)) {
printf("Unable to load interpreter\n");
free(elf_phdata);
exit(-1);
@@ -1315,10 +1410,11 @@
interp_load_addr,
(interpreter_type == INTERPRETER_AOUT ? 0 : 1),
info);
+ info->load_addr = reloc_func_desc;
info->start_brk = info->brk = elf_brk;
info->end_code = end_code;
info->start_code = start_code;
- info->start_data = end_code;
+ info->start_data = start_data;
info->end_data = end_data;
info->start_stack = bprm->p;
Added: trunk/src/host/qemu-neo1973/linux-user/elfload32.c
===================================================================
--- trunk/src/host/qemu-neo1973/linux-user/elfload32.c 2007-10-29 20:40:05 UTC (rev 3302)
+++ trunk/src/host/qemu-neo1973/linux-user/elfload32.c 2007-10-29 21:14:04 UTC (rev 3303)
@@ -0,0 +1,30 @@
+#define TARGET_ABI32
+#define load_elf_binary load_elf_binary32
+#define do_init_thread do_init_thread32
+
+#include "elfload.c"
+
+#undef load_elf_binary
+#undef do_init_thread
+
+int load_elf_binary(struct linux_binprm *bprm, struct target_pt_regs *regs,
+ struct image_info *info);
+
+int load_elf_binary_multi(struct linux_binprm *bprm,
+ struct target_pt_regs *regs,
+ struct image_info *info)
+{
+ struct elfhdr *elf_ex;
+ int retval;
+
+ elf_ex = (struct elfhdr *) bprm->buf; /* exec-header */
+ if (elf_ex->e_ident[EI_CLASS] == ELFCLASS64) {
+ retval = load_elf_binary(bprm, regs, info);
+ } else {
+ retval = load_elf_binary32(bprm, regs, info);
+ if (personality(info->personality) == PER_LINUX)
+ info->personality = PER_LINUX32;
+ }
+
+ return retval;
+}
Property changes on: trunk/src/host/qemu-neo1973/linux-user/elfload32.c
___________________________________________________________________
Name: svn:executable
+ *
Modified: trunk/src/host/qemu-neo1973/linux-user/flat.h
===================================================================
--- trunk/src/host/qemu-neo1973/linux-user/flat.h 2007-10-29 20:40:05 UTC (rev 3302)
+++ trunk/src/host/qemu-neo1973/linux-user/flat.h 2007-10-29 21:14:04 UTC (rev 3303)
@@ -22,25 +22,25 @@
struct flat_hdr {
char magic[4];
- target_ulong rev; /* version (as above) */
- target_ulong entry; /* Offset of first executable instruction
- with text segment from beginning of file */
- target_ulong data_start; /* Offset of data segment from beginning of
- file */
- target_ulong data_end; /* Offset of end of data segment
- from beginning of file */
- target_ulong bss_end; /* Offset of end of bss segment from beginning
- of file */
+ abi_ulong rev; /* version (as above) */
+ abi_ulong entry; /* Offset of first executable instruction
+ with text segment from beginning of file */
+ abi_ulong data_start; /* Offset of data segment from beginning of
+ file */
+ abi_ulong data_end; /* Offset of end of data segment
+ from beginning of file */
+ abi_ulong bss_end; /* Offset of end of bss segment from beginning
+ of file */
/* (It is assumed that data_end through bss_end forms the bss segment.) */
- target_ulong stack_size; /* Size of stack, in bytes */
- target_ulong reloc_start; /* Offset of relocation records from
- beginning of file */
- target_ulong reloc_count; /* Number of relocation records */
- target_ulong flags;
- target_ulong build_date; /* When the program/library was built */
- target_ulong filler[5]; /* Reservered, set to zero */
+ abi_ulong stack_size; /* Size of stack, in bytes */
+ abi_ulong reloc_start; /* Offset of relocation records from
+ beginning of file */
+ abi_ulong reloc_count; /* Number of relocation records */
+ abi_ulong flags;
+ abi_ulong build_date; /* When the program/library was built */
+ abi_ulong filler[5]; /* Reservered, set to zero */
};
#define FLAT_FLAG_RAM 0x0001 /* load program entirely into RAM */
Modified: trunk/src/host/qemu-neo1973/linux-user/flatload.c
===================================================================
--- trunk/src/host/qemu-neo1973/linux-user/flatload.c 2007-10-29 20:40:05 UTC (rev 3302)
+++ trunk/src/host/qemu-neo1973/linux-user/flatload.c 2007-10-29 21:14:04 UTC (rev 3303)
@@ -63,13 +63,13 @@
#define UNLOADED_LIB 0x7ff000ff /* Placeholder for unused library */
struct lib_info {
- target_ulong start_code; /* Start of text segment */
- target_ulong start_data; /* Start of data segment */
- target_ulong end_data; /* Start of bss section */
- target_ulong start_brk; /* End of data segment */
- target_ulong text_len; /* Length of text segment */
- target_ulong entry; /* Start address for this module */
- target_ulong build_date; /* When this one was compiled */
+ abi_ulong start_code; /* Start of text segment */
+ abi_ulong start_data; /* Start of data segment */
+ abi_ulong end_data; /* Start of bss section */
+ abi_ulong start_brk; /* End of data segment */
+ abi_ulong text_len; /* Length of text segment */
+ abi_ulong entry; /* Start address for this module */
+ abi_ulong build_date; /* When this one was compiled */
short loaded; /* Has this library been loaded? */
};
@@ -89,7 +89,7 @@
*/
/* Push a block of strings onto the guest stack. */
-static target_ulong copy_strings(target_ulong p, int n, char **s)
+static abi_ulong copy_strings(abi_ulong p, int n, char **s)
{
int len;
@@ -102,8 +102,8 @@
return p;
}
-int target_pread(int fd, target_ulong ptr, target_ulong len,
- target_ulong offset)
+int target_pread(int fd, abi_ulong ptr, abi_ulong len,
+ abi_ulong offset)
{
void *buf;
int ret;
@@ -262,15 +262,15 @@
/****************************************************************************/
-static target_ulong
-calc_reloc(target_ulong r, struct lib_info *p, int curid, int internalp)
+static abi_ulong
+calc_reloc(abi_ulong r, struct lib_info *p, int curid, int internalp)
{
- target_ulong addr;
+ abi_ulong addr;
int id;
- target_ulong start_brk;
- target_ulong start_data;
- target_ulong text_len;
- target_ulong start_code;
+ abi_ulong start_brk;
+ abi_ulong start_data;
+ abi_ulong text_len;
+ abi_ulong start_code;
#ifdef CONFIG_BINFMT_SHARED_FLAT
#error needs checking
@@ -381,19 +381,19 @@
/****************************************************************************/
static int load_flat_file(struct linux_binprm * bprm,
- struct lib_info *libinfo, int id, target_ulong *extra_stack)
+ struct lib_info *libinfo, int id, abi_ulong *extra_stack)
{
struct flat_hdr * hdr;
- target_ulong textpos = 0, datapos = 0, result;
- target_ulong realdatastart = 0;
- target_ulong text_len, data_len, bss_len, stack_len, flags;
- target_ulong memp = 0; /* for finding the brk area */
- target_ulong extra;
- target_ulong reloc = 0, rp;
+ abi_ulong textpos = 0, datapos = 0, result;
+ abi_ulong realdatastart = 0;
+ abi_ulong text_len, data_len, bss_len, stack_len, flags;
+ abi_ulong memp = 0; /* for finding the brk area */
+ abi_ulong extra;
+ abi_ulong reloc = 0, rp;
int i, rev, relocs = 0;
- target_ulong fpos;
- target_ulong start_code, end_code;
- target_ulong indx_len;
+ abi_ulong fpos;
+ abi_ulong start_code, end_code;
+ abi_ulong indx_len;
hdr = ((struct flat_hdr *) bprm->buf); /* exec-header */
@@ -440,14 +440,14 @@
/*
* calculate the extra space we need to map in
*/
- extra = relocs * sizeof(target_ulong);
+ extra = relocs * sizeof(abi_ulong);
if (extra < bss_len + stack_len)
extra = bss_len + stack_len;
/* Add space for library base pointers. Make sure this does not
misalign the doesn't misalign the data segment. */
- indx_len = MAX_SHARED_LIBS * sizeof(target_ulong);
- indx_len = (indx_len + 15) & ~(target_ulong)15;
+ indx_len = MAX_SHARED_LIBS * sizeof(abi_ulong);
+ indx_len = (indx_len + 15) & ~(abi_ulong)15;
/*
* there are a couple of cases here, the separate code/data
@@ -485,12 +485,12 @@
#ifdef CONFIG_BINFMT_ZFLAT
if (flags & FLAT_FLAG_GZDATA) {
result = decompress_exec(bprm, fpos, (char *) datapos,
- data_len + (relocs * sizeof(target_ulong)))
+ data_len + (relocs * sizeof(abi_ulong)))
} else
#endif
{
result = target_pread(bprm->fd, datapos,
- data_len + (relocs * sizeof(target_ulong)),
+ data_len + (relocs * sizeof(abi_ulong)),
fpos);
}
if (result < 0) {
@@ -544,7 +544,7 @@
text_len, 0);
if (result >= 0) {
result = target_pread(bprm->fd, datapos,
- data_len + (relocs * sizeof(target_ulong)),
+ data_len + (relocs * sizeof(abi_ulong)),
ntohl(hdr->data_start));
}
}
@@ -597,7 +597,7 @@
if (flags & FLAT_FLAG_GOTPIC) {
rp = datapos;
while (1) {
- target_ulong addr;
+ abi_ulong addr;
addr = tgetl(rp);
if (addr == -1)
break;
@@ -607,7 +607,7 @@
return -ENOEXEC;
tputl(rp, addr);
}
- rp += sizeof(target_ulong);
+ rp += sizeof(abi_ulong);
}
}
@@ -624,12 +624,12 @@
*/
if (rev > OLD_FLAT_VERSION) {
for (i = 0; i < relocs; i++) {
- target_ulong addr, relval;
+ abi_ulong addr, relval;
/* Get the address of the pointer to be
relocated (of course, the address has to be
relocated first). */
- relval = tgetl(reloc + i * sizeof (target_ulong));
+ relval = tgetl(reloc + i * sizeof (abi_ulong));
addr = flat_get_relocate_addr(relval);
rp = calc_reloc(addr, libinfo, id, 1);
if (rp == RELOC_FAILED)
@@ -657,8 +657,8 @@
}
} else {
for (i = 0; i < relocs; i++) {
- target_ulong relval;
- relval = tgetl(reloc + i * sizeof (target_ulong));
+ abi_ulong relval;
+ relval = tgetl(reloc + i * sizeof (abi_ulong));
old_reloc(&libinfo[0], relval);
}
}
@@ -712,10 +712,10 @@
struct image_info * info)
{
struct lib_info libinfo[MAX_SHARED_LIBS];
- target_ulong p = bprm->p;
- target_ulong stack_len;
- target_ulong start_addr;
- target_ulong sp;
+ abi_ulong p = bprm->p;
+ abi_ulong stack_len;
+ abi_ulong start_addr;
+ abi_ulong sp;
int res;
int i, j;
@@ -740,7 +740,7 @@
/* Update data segment pointers for all libraries */
for (i=0; i<MAX_SHARED_LIBS; i++) {
if (libinfo[i].loaded) {
- target_ulong p;
+ abi_ulong p;
p = libinfo[i].start_data;
for (j=0; j<MAX_SHARED_LIBS; j++) {
p -= 4;
@@ -758,12 +758,12 @@
p = copy_strings(p, bprm->envc, bprm->envp);
p = copy_strings(p, bprm->argc, bprm->argv);
/* Align stack. */
- sp = p & ~(target_ulong)(sizeof(target_ulong) - 1);
+ sp = p & ~(abi_ulong)(sizeof(abi_ulong) - 1);
/* Enforce final stack alignment of 16 bytes. This is sufficient
for all current targets, and excess alignment is harmless. */
stack_len = bprm->envc + bprm->argc + 2;
stack_len += 3; /* argc, arvg, argp */
- stack_len *= sizeof(target_ulong);
+ stack_len *= sizeof(abi_ulong);
if ((sp + stack_len) & 15)
sp -= 16 - ((sp + stack_len) & 15);
sp = loader_build_argptr(bprm->envc, bprm->argc, sp, p, 1);
Modified: trunk/src/host/qemu-neo1973/linux-user/i386/syscall.h
===================================================================
--- trunk/src/host/qemu-neo1973/linux-user/i386/syscall.h 2007-10-29 20:40:05 UTC (rev 3302)
+++ trunk/src/host/qemu-neo1973/linux-user/i386/syscall.h 2007-10-29 21:14:04 UTC (rev 3303)
@@ -31,7 +31,7 @@
struct target_modify_ldt_ldt_s {
unsigned int entry_number;
- target_ulong base_addr;
+ abi_ulong base_addr;
unsigned int limit;
unsigned int flags;
};
@@ -79,22 +79,22 @@
/*
* normal regs, with special meaning for the segment descriptors..
*/
- target_long ebx;
- target_long ecx;
- target_long edx;
- target_long esi;
- target_long edi;
- target_long ebp;
- target_long eax;
- target_long __null_ds;
- target_long __null_es;
- target_long __null_fs;
- target_long __null_gs;
- target_long orig_eax;
- target_long eip;
+ abi_long ebx;
+ abi_long ecx;
+ abi_long edx;
+ abi_long esi;
+ abi_long edi;
+ abi_long ebp;
+ abi_long eax;
+ abi_long __null_ds;
+ abi_long __null_es;
+ abi_long __null_fs;
+ abi_long __null_gs;
+ abi_long orig_eax;
+ abi_long eip;
unsigned short cs, __csh;
- target_long eflags;
- target_long esp;
+ abi_long eflags;
+ abi_long esp;
unsigned short ss, __ssh;
/*
* these are specific to v86 mode:
@@ -106,14 +106,14 @@
};
struct target_revectored_struct {
- target_ulong __map[8]; /* 256 bits */
+ abi_ulong __map[8]; /* 256 bits */
};
struct target_vm86_struct {
struct target_vm86_regs regs;
- target_ulong flags;
- target_ulong screen_bitmap;
- target_ulong cpu_type;
+ abi_ulong flags;
+ abi_ulong screen_bitmap;
+ abi_ulong cpu_type;
struct target_revectored_struct int_revectored;
struct target_revectored_struct int21_revectored;
};
@@ -124,7 +124,7 @@
#define TARGET_VM86_SCREEN_BITMAP 0x0001
struct target_vm86plus_info_struct {
- target_ulong flags;
+ abi_ulong flags;
#define TARGET_force_return_for_pic (1 << 0)
#define TARGET_vm86dbg_active (1 << 1) /* for debugger */
#define TARGET_vm86dbg_TFpendig (1 << 2) /* for debugger */
@@ -134,9 +134,9 @@
struct target_vm86plus_struct {
struct target_vm86_regs regs;
- target_ulong flags;
- target_ulong screen_bitmap;
- target_ulong cpu_type;
+ abi_ulong flags;
+ abi_ulong screen_bitmap;
+ abi_ulong cpu_type;
struct target_revectored_struct int_revectored;
struct target_revectored_struct int21_revectored;
struct target_vm86plus_info_struct vm86plus;
Modified: trunk/src/host/qemu-neo1973/linux-user/i386/syscall_nr.h
===================================================================
--- trunk/src/host/qemu-neo1973/linux-user/i386/syscall_nr.h 2007-10-29 20:40:05 UTC (rev 3302)
+++ trunk/src/host/qemu-neo1973/linux-user/i386/syscall_nr.h 2007-10-29 21:14:04 UTC (rev 3303)
@@ -253,7 +253,7 @@
#define TARGET_NR_io_submit 248
#define TARGET_NR_io_cancel 249
#define TARGET_NR_fadvise64 250
-
+/* 251 is available for reuse (was briefly sys_set_zone_reclaim) */
#define TARGET_NR_exit_group 252
#define TARGET_NR_lookup_dcookie 253
#define TARGET_NR_epoll_create 254
@@ -270,8 +270,60 @@
#define TARGET_NR_clock_gettime (TARGET_NR_timer_create+6)
#define TARGET_NR_clock_getres (TARGET_NR_timer_create+7)
#define TARGET_NR_clock_nanosleep (TARGET_NR_timer_create+8)
-
+#define TARGET_NR_statfs64 268
+#define TARGET_NR_fstatfs64 269
#define TARGET_NR_tgkill 270
#define TARGET_NR_utimes 271
-
+#define TARGET_NR_fadvise64_64 272
+#define TARGET_NR_vserver 273
+#define TARGET_NR_mbind 274
+#define TARGET_NR_get_mempolicy 275
+#define TARGET_NR_set_mempolicy 276
+#define TARGET_NR_mq_open 277
+#define TARGET_NR_mq_unlink (TARGET_NR_mq_open+1)
+#define TARGET_NR_mq_timedsend (TARGET_NR_mq_open+2)
+#define TARGET_NR_mq_timedreceive (TARGET_NR_mq_open+3)
+#define TARGET_NR_mq_notify (TARGET_NR_mq_open+4)
+#define TARGET_NR_mq_getsetattr (TARGET_NR_mq_open+5)
+#define TARGET_NR_kexec_load 283
+#define TARGET_NR_waitid 284
+/* #define TARGET_NR_sys_setaltroot 285 */
+#define TARGET_NR_add_key 286
+#define TARGET_NR_request_key 287
+#define TARGET_NR_keyctl 288
+#define TARGET_NR_ioprio_set 289
+#define TARGET_NR_ioprio_get 290
+#define TARGET_NR_inotify_init 291
+#define TARGET_NR_inotify_add_watch 292
+#define TARGET_NR_inotify_rm_watch 293
+#define TARGET_NR_migrate_pages 294
+#define TARGET_NR_openat 295
+#define TARGET_NR_mkdirat 296
+#define TARGET_NR_mknodat 297
+#define TARGET_NR_fchownat 298
+#define TARGET_NR_futimesat 299
+#define TARGET_NR_fstatat64 300
+#define TARGET_NR_unlinkat 301
+#define TARGET_NR_renameat 302
+#define TARGET_NR_linkat 303
+#define TARGET_NR_symlinkat 304
+#define TARGET_NR_readlinkat 305
+#define TARGET_NR_fchmodat 306
+#define TARGET_NR_faccessat 307
+#define TARGET_NR_pselect6 308
+#define TARGET_NR_ppoll 309
+#define TARGET_NR_unshare 310
#define TARGET_NR_set_robust_list 311
+#define TARGET_NR_get_robust_list 312
+#define TARGET_NR_splice 313
+#define TARGET_NR_sync_file_range 314
+#define TARGET_NR_tee 315
+#define TARGET_NR_vmsplice 316
+#define TARGET_NR_move_pages 317
+#define TARGET_NR_getcpu 318
+#define TARGET_NR_epoll_pwait 319
+#define TARGET_NR_utimensat 320
+#define TARGET_NR_signalfd 321
+#define TARGET_NR_timerfd 322
+#define TARGET_NR_eventfd 323
+#define TARGET_NR_fallocate 324
Added: trunk/src/host/qemu-neo1973/linux-user/i386/target_signal.h
===================================================================
--- trunk/src/host/qemu-neo1973/linux-user/i386/target_signal.h 2007-10-29 20:40:05 UTC (rev 3302)
+++ trunk/src/host/qemu-neo1973/linux-user/i386/target_signal.h 2007-10-29 21:14:04 UTC (rev 3303)
@@ -0,0 +1,29 @@
+#ifndef TARGET_SIGNAL_H
+#define TARGET_SIGNAL_H
+
+#include "cpu.h"
+
+/* this struct defines a stack used during syscall handling */
+
+typedef struct target_sigaltstack {
+ abi_ulong ss_sp;
+ abi_long ss_flags;
+ abi_ulong ss_size;
+} target_stack_t;
+
+
+/*
+ * sigaltstack controls
+ */
+#define TARGET_SS_ONSTACK 1
+#define TARGET_SS_DISABLE 2
+
+#define TARGET_MINSIGSTKSZ 2048
+#define TARGET_SIGSTKSZ 8192
+
+static inline abi_ulong get_sp_from_cpustate(CPUX86State *state)
+{
+ return state->regs[R_ESP];
+}
+
+#endif /* TARGET_SIGNAL_H */
Modified: trunk/src/host/qemu-neo1973/linux-user/i386/termbits.h
===================================================================
--- trunk/src/host/qemu-neo1973/linux-user/i386/termbits.h 2007-10-29 20:40:05 UTC (rev 3302)
+++ trunk/src/host/qemu-neo1973/linux-user/i386/termbits.h 2007-10-29 21:14:04 UTC (rev 3303)
@@ -26,6 +26,7 @@
#define TARGET_IXANY 0004000
#define TARGET_IXOFF 0010000
#define TARGET_IMAXBEL 0020000
+#define TARGET_IUTF8 0040000
/* c_oflag bits */
#define TARGET_OPOST 0000001
@@ -96,8 +97,20 @@
#define TARGET_B115200 0010002
#define TARGET_B230400 0010003
#define TARGET_B460800 0010004
+#define TARGET_B500000 0010005
+#define TARGET_B576000 0010006
+#define TARGET_B921600 0010007
+#define TARGET_B1000000 0010010
+#define TARGET_B1152000 0010011
+#define TARGET_B1500000 0010012
+#define TARGET_B2000000 0010013
+#define TARGET_B2500000 0010014
+#define TARGET_B3000000 0010015
+#define TARGET_B3500000 0010016
+#define TARGET_B4000000 0010017
#define TARGET_CIBAUD 002003600000 /* input baud rate (not used) */
-#define TARGET_CRTSCTS 020000000000 /* flow control */
+#define TARGET_CMSPAR 010000000000 /* mark or space (stick) parity */
+#define TARGET_CRTSCTS 020000000000 /* flow control */
/* c_lflag bits */
#define TARGET_ISIG 0000001
Modified: trunk/src/host/qemu-neo1973/linux-user/linuxload.c
===================================================================
--- trunk/src/host/qemu-neo1973/linux-user/linuxload.c 2007-10-29 20:40:05 UTC (rev 3302)
+++ trunk/src/host/qemu-neo1973/linux-user/linuxload.c 2007-10-29 21:14:04 UTC (rev 3303)
@@ -13,7 +13,7 @@
#define NGROUPS 32
/* ??? This should really be somewhere else. */
-void memcpy_to_target(target_ulong dest, const void *src,
+void memcpy_to_target(abi_ulong dest, const void *src,
unsigned long len)
{
void *host_ptr;
@@ -109,12 +109,12 @@
}
/* Construct the envp and argv tables on the target stack. */
-target_ulong loader_build_argptr(int envc, int argc, target_ulong sp,
- target_ulong stringp, int push_ptr)
+abi_ulong loader_build_argptr(int envc, int argc, abi_ulong sp,
+ abi_ulong stringp, int push_ptr)
{
- int n = sizeof(target_ulong);
- target_ulong envp;
- target_ulong argv;
+ int n = sizeof(abi_ulong);
+ abi_ulong envp;
+ abi_ulong argv;
sp -= (envc + 1) * n;
envp = sp;
@@ -169,7 +169,11 @@
&& bprm.buf[1] == 'E'
&& bprm.buf[2] == 'L'
&& bprm.buf[3] == 'F') {
+#ifndef TARGET_HAS_ELFLOAD32
retval = load_elf_binary(&bprm,regs,infop);
+#else
+ retval = load_elf_binary_multi(&bprm, regs, infop);
+#endif
#if defined(TARGET_HAS_BFLT)
} else if (bprm.buf[0] == 'b'
&& bprm.buf[1] == 'F'
Modified: trunk/src/host/qemu-neo1973/linux-user/m68k/syscall.h
===================================================================
--- trunk/src/host/qemu-neo1973/linux-user/m68k/syscall.h 2007-10-29 20:40:05 UTC (rev 3302)
+++ trunk/src/host/qemu-neo1973/linux-user/m68k/syscall.h 2007-10-29 21:14:04 UTC (rev 3303)
@@ -3,14 +3,14 @@
stack during a system call. */
struct target_pt_regs {
- target_long d1, d2, d3, d4, d5, d6, d7;
- target_long a0, a1, a2, a3, a4, a5, a6;
- target_ulong d0;
- target_ulong usp;
- target_ulong orig_d0;
+ abi_long d1, d2, d3, d4, d5, d6, d7;
+ abi_long a0, a1, a2, a3, a4, a5, a6;
+ abi_ulong d0;
+ abi_ulong usp;
+ abi_ulong orig_d0;
int16_t stkadj;
uint16_t sr;
- target_ulong pc;
+ abi_ulong pc;
uint16_t fntvex;
uint16_t __fill;
};
Modified: trunk/src/host/qemu-neo1973/linux-user/m68k/syscall_nr.h
===================================================================
--- trunk/src/host/qemu-neo1973/linux-user/m68k/syscall_nr.h 2007-10-29 20:40:05 UTC (rev 3302)
+++ trunk/src/host/qemu-neo1973/linux-user/m68k/syscall_nr.h 2007-10-29 21:14:04 UTC (rev 3303)
@@ -281,3 +281,42 @@
#define TARGET_NR_add_key 279
#define TARGET_NR_request_key 280
#define TARGET_NR_keyctl 281
+#define TARGET_NR_ioprio_set 282
+#define TARGET_NR_ioprio_get 283
+#define TARGET_NR_inotify_init 284
+#define TARGET_NR_inotify_add_watch 285
+#define TARGET_NR_inotify_rm_watch 286
+#define TARGET_NR_migrate_pages 287
+#define TARGET_NR_openat 288
+#define TARGET_NR_mkdirat 289
+#define TARGET_NR_mknodat 290
+#define TARGET_NR_fchownat 291
+#define TARGET_NR_futimesat 292
+#define TARGET_NR_fstatat64 293
+#define TARGET_NR_unlinkat 294
+#define TARGET_NR_renameat 295
+#define TARGET_NR_linkat 296
+#define TARGET_NR_symlinkat 297
+#define TARGET_NR_readlinkat 298
+#define TARGET_NR_fchmodat 299
+#define TARGET_NR_faccessat 300
+#define TARGET_NR_pselect6 301
+#define TARGET_NR_ppoll 302
+#define TARGET_NR_unshare 303
+#define TARGET_NR_set_robust_list 304
+#define TARGET_NR_get_robust_list 305
+#define TARGET_NR_splice 306
+#define TARGET_NR_sync_file_range 307
+#define TARGET_NR_tee 308
+#define TARGET_NR_vmsplice 309
+#define TARGET_NR_move_pages 310
+#define TARGET_NR_sched_setaffinity 311
+#define TARGET_NR_sched_getaffinity 312
+#define TARGET_NR_kexec_load 313
+#define TARGET_NR_getcpu 314
+#define TARGET_NR_epoll_pwait 315
+#define TARGET_NR_utimensat 316
+#define TARGET_NR_signalfd 317
+#define TARGET_NR_timerfd 318
+#define TARGET_NR_eventfd 319
+#define TARGET_NR_fallocate 320
Added: trunk/src/host/qemu-neo1973/linux-user/m68k/target_signal.h
===================================================================
--- trunk/src/host/qemu-neo1973/linux-user/m68k/target_signal.h 2007-10-29 20:40:05 UTC (rev 3302)
+++ trunk/src/host/qemu-neo1973/linux-user/m68k/target_signal.h 2007-10-29 21:14:04 UTC (rev 3303)
@@ -0,0 +1,24 @@
+#ifndef TARGET_SIGNAL_H
+#define TARGET_SIGNAL_H
+
+#include "cpu.h"
+
+/* this struct defines a stack used during syscall handling */
+
+typedef struct target_sigaltstack {
+ abi_ulong ss_sp;
+ abi_long ss_flags;
+ abi_ulong ss_size;
+} target_stack_t;
+
+
+/*
+ * sigaltstack controls
+ */
+#define TARGET_SS_ONSTACK 1
+#define TARGET_SS_DISABLE 2
+
+#define TARGET_MINSIGSTKSZ 2048
+#define TARGET_SIGSTKSZ 8192
+
+#endif /* TARGET_SIGNAL_H */
Modified: trunk/src/host/qemu-neo1973/linux-user/m68k/termbits.h
===================================================================
--- trunk/src/host/qemu-neo1973/linux-user/m68k/termbits.h 2007-10-29 20:40:05 UTC (rev 3302)
+++ trunk/src/host/qemu-neo1973/linux-user/m68k/termbits.h 2007-10-29 21:14:04 UTC (rev 3303)
@@ -27,6 +27,7 @@
#define TARGET_IXANY 0004000
#define TARGET_IXOFF 0010000
#define TARGET_IMAXBEL 0020000
+#define TARGET_IUTF8 0040000
/* c_oflag bits */
#define TARGET_OPOST 0000001
@@ -97,8 +98,20 @@
#define TARGET_B115200 0010002
#define TARGET_B230400 0010003
#define TARGET_B460800 0010004
+#define TARGET_B500000 0010005
+#define TARGET_B576000 0010006
+#define TARGET_B921600 0010007
+#define TARGET_B1000000 0010010
+#define TARGET_B1152000 0010011
+#define TARGET_B1500000 0010012
+#define TARGET_B2000000 0010013
+#define TARGET_B2500000 0010014
+#define TARGET_B3000000 0010015
+#define TARGET_B3500000 0010016
+#define TARGET_B4000000 0010017
#define TARGET_CIBAUD 002003600000 /* input baud rate (not used) */
-#define TARGET_CRTSCTS 020000000000 /* flow control */
+#define TARGET_CMSPAR 010000000000 /* mark or space (stick) parity */
+#define TARGET_CRTSCTS 020000000000 /* flow control */
/* c_lflag bits */
#define TARGET_ISIG 0000001
Modified: trunk/src/host/qemu-neo1973/linux-user/main.c
===================================================================
--- trunk/src/host/qemu-neo1973/linux-user/main.c 2007-10-29 20:40:05 UTC (rev 3302)
+++ trunk/src/host/qemu-neo1973/linux-user/main.c 2007-10-29 21:14:04 UTC (rev 3303)
@@ -168,7 +168,7 @@
void cpu_loop(CPUX86State *env)
{
int trapnr;
- target_ulong pc;
+ abi_ulong pc;
target_siginfo_t info;
for(;;) {
@@ -305,11 +305,11 @@
#ifdef TARGET_ARM
/* XXX: find a better solution */
-extern void tb_invalidate_page_range(target_ulong start, target_ulong end);
+extern void tb_invalidate_page_range(abi_ulong start, abi_ulong end);
-static void arm_cache_flush(target_ulong start, target_ulong last)
+static void arm_cache_flush(abi_ulong start, abi_ulong last)
{
- target_ulong addr, last1;
+ abi_ulong addr, last1;
if (last < start)
return;
@@ -474,7 +474,7 @@
static inline void save_window_offset(CPUSPARCState *env, int cwp1)
{
unsigned int i;
- target_ulong sp_ptr;
+ abi_ulong sp_ptr;
sp_ptr = env->regbase[get_reg_index(env, cwp1, 6)];
#if defined(DEBUG_WIN)
@@ -483,7 +483,7 @@
#endif
for(i = 0; i < 16; i++) {
tputl(sp_ptr, env->regbase[get_reg_index(env, cwp1, 8 + i)]);
- sp_ptr += sizeof(target_ulong);
+ sp_ptr += sizeof(abi_ulong);
}
}
@@ -505,7 +505,7 @@
static void restore_window(CPUSPARCState *env)
{
unsigned int new_wim, i, cwp1;
- target_ulong sp_ptr;
+ abi_ulong sp_ptr;
new_wim = ((env->wim << 1) | (env->wim >> (NWINDOWS - 1))) &
((1LL << NWINDOWS) - 1);
@@ -519,7 +519,7 @@
#endif
for(i = 0; i < 16; i++) {
env->regbase[get_reg_index(env, cwp1, 8 + i)] = tgetl(sp_ptr);
- sp_ptr += sizeof(target_ulong);
+ sp_ptr += sizeof(abi_ulong);
}
env->wim = new_wim;
#ifdef TARGET_SPARC64
@@ -564,6 +564,7 @@
case 0x88:
case 0x90:
#else
+ case 0x110:
case 0x16d:
#endif
ret = do_syscall (env, env->gregs[1],
@@ -571,14 +572,14 @@
env->regwptr[2], env->regwptr[3],
env->regwptr[4], env->regwptr[5]);
if ((unsigned int)ret >= (unsigned int)(-515)) {
-#ifdef TARGET_SPARC64
+#if defined(TARGET_SPARC64) && !defined(TARGET_ABI32)
env->xcc |= PSR_CARRY;
#else
env->psr |= PSR_CARRY;
#endif
ret = -ret;
} else {
-#ifdef TARGET_SPARC64
+#if defined(TARGET_SPARC64) && !defined(TARGET_ABI32)
env->xcc &= ~PSR_CARRY;
#else
env->psr &= ~PSR_CARRY;
@@ -590,6 +591,9 @@
env->npc = env->npc + 4;
break;
case 0x83: /* flush windows */
+#ifdef TARGET_ABI32
+ case 0x103:
+#endif
flush_windows(env);
/* next instruction */
env->pc = env->npc;
@@ -634,6 +638,14 @@
queue_signal(info.si_signo, &info);
}
break;
+ case 0x16e:
+ flush_windows(env);
+ sparc64_get_context(env);
+ break;
+ case 0x16f:
+ flush_windows(env);
+ sparc64_set_context(env);
+ break;
#endif
case EXCP_INTERRUPT:
/* just indicate that signals should be handled asap */
@@ -664,7 +676,6 @@
#endif
#ifdef TARGET_PPC
-
static inline uint64_t cpu_ppc_get_tb (CPUState *env)
{
/* TO FIX */
@@ -681,37 +692,45 @@
return cpu_ppc_get_tb(env) >> 32;
}
-static void cpu_ppc_store_tb (CPUState *env, uint64_t value)
+uint32_t cpu_ppc_load_atbl (CPUState *env)
{
- /* TO FIX */
+ return cpu_ppc_get_tb(env) & 0xFFFFFFFF;
}
-void cpu_ppc_store_tbu (CPUState *env, uint32_t value)
+uint32_t cpu_ppc_load_atbu (CPUState *env)
{
- cpu_ppc_store_tb(env, ((uint64_t)value << 32) | cpu_ppc_load_tbl(env));
+ return cpu_ppc_get_tb(env) >> 32;
}
-void cpu_ppc_store_tbl (CPUState *env, uint32_t value)
-{
- cpu_ppc_store_tb(env, ((uint64_t)cpu_ppc_load_tbl(env) << 32) | value);
-}
-
-void cpu_ppc601_store_rtcu (CPUState *env, uint32_t value)
-__attribute__ (( alias ("cpu_ppc_store_tbu") ));
-
uint32_t cpu_ppc601_load_rtcu (CPUState *env)
__attribute__ (( alias ("cpu_ppc_load_tbu") ));
-void cpu_ppc601_store_rtcl (CPUState *env, uint32_t value)
+uint32_t cpu_ppc601_load_rtcl (CPUState *env)
{
- cpu_ppc_store_tbl(env, value & 0x3FFFFF80);
+ return cpu_ppc_load_tbl(env) & 0x3FFFFF80;
}
-uint32_t cpu_ppc601_load_rtcl (CPUState *env)
+/* XXX: to be fixed */
+int ppc_dcr_read (ppc_dcr_t *dcr_env, int dcrn, target_ulong *valp)
{
- return cpu_ppc_load_tbl(env) & 0x3FFFFF80;
+ return -1;
}
+int ppc_dcr_write (ppc_dcr_t *dcr_env, int dcrn, target_ulong val)
+{
+ return -1;
+}
+
+#define EXCP_DUMP(env, fmt, args...) \
+do { \
+ fprintf(stderr, fmt , ##args); \
+ cpu_dump_state(env, stderr, fprintf, 0); \
+ if (loglevel != 0) { \
+ fprintf(logfile, fmt , ##args); \
+ cpu_dump_state(env, logfile, fprintf, 0); \
+ } \
+} while (0)
+
void cpu_loop(CPUPPCState *env)
{
target_siginfo_t info;
@@ -720,60 +739,22 @@
for(;;) {
trapnr = cpu_ppc_exec(env);
- if (trapnr != EXCP_SYSCALL_USER && trapnr != EXCP_BRANCH &&
- trapnr != EXCP_TRACE) {
- if (loglevel > 0) {
- cpu_dump_state(env, logfile, fprintf, 0);
- }
- }
switch(trapnr) {
- case EXCP_NONE:
+ case POWERPC_EXCP_NONE:
+ /* Just go on */
break;
- case EXCP_SYSCALL_USER:
- /* system call */
- /* WARNING:
- * PPC ABI uses overflow flag in cr0 to signal an error
- * in syscalls.
- */
-#if 0
- printf("syscall %d 0x%08x 0x%08x 0x%08x 0x%08x\n", env->gpr[0],
- env->gpr[3], env->gpr[4], env->gpr[5], env->gpr[6]);
-#endif
- env->crf[0] &= ~0x1;
- ret = do_syscall(env, env->gpr[0], env->gpr[3], env->gpr[4],
- env->gpr[5], env->gpr[6], env->gpr[7],
- env->gpr[8]);
- if (ret > (uint32_t)(-515)) {
- env->crf[0] |= 0x1;
- ret = -ret;
- }
- env->gpr[3] = ret;
-#if 0
- printf("syscall returned 0x%08x (%d)\n", ret, ret);
-#endif
+ case POWERPC_EXCP_CRITICAL: /* Critical input */
+ cpu_abort(env, "Critical interrupt while in user mode. "
+ "Aborting\n");
break;
- case EXCP_RESET:
- /* Should not happen ! */
- fprintf(stderr, "RESET asked... Stop emulation\n");
- if (loglevel)
- fprintf(logfile, "RESET asked... Stop emulation\n");
- abort();
- case EXCP_MACHINE_CHECK:
- fprintf(stderr, "Machine check exeption... Stop emulation\n");
- if (loglevel)
- fprintf(logfile, "RESET asked... Stop emulation\n");
- info.si_signo = TARGET_SIGBUS;
- info.si_errno = 0;
- info.si_code = TARGET_BUS_OBJERR;
- info._sifields._sigfault._addr = env->nip - 4;
- queue_signal(info.si_signo, &info);
- case EXCP_DSI:
- fprintf(stderr, "Invalid data memory access: 0x" ADDRX "\n",
- env->spr[SPR_DAR]);
- if (loglevel) {
- fprintf(logfile, "Invalid data memory access: 0x" ADDRX "\n",
- env->spr[SPR_DAR]);
- }
+ case POWERPC_EXCP_MCHECK: /* Machine check exception */
+ cpu_abort(env, "Machine check exception while in user mode. "
+ "Aborting\n");
+ break;
+ case POWERPC_EXCP_DSI: /* Data storage exception */
+ EXCP_DUMP(env, "Invalid data memory access: 0x" ADDRX "\n",
+ env->spr[SPR_DAR]);
+ /* XXX: check this. Seems bugged */
switch (env->error_code & 0xFF000000) {
case 0x40000000:
info.si_signo = TARGET_SIGSEGV;
@@ -792,12 +773,8 @@
break;
default:
/* Let's send a regular segfault... */
- fprintf(stderr, "Invalid segfault errno (%02x)\n",
- env->error_code);
- if (loglevel) {
- fprintf(logfile, "Invalid segfault errno (%02x)\n",
- env->error_code);
- }
+ EXCP_DUMP(env, "Invalid segfault errno (%02x)\n",
+ env->error_code);
info.si_signo = TARGET_SIGSEGV;
info.si_errno = 0;
info.si_code = TARGET_SEGV_MAPERR;
@@ -806,10 +783,10 @@
info._sifields._sigfault._addr = env->nip;
queue_signal(info.si_signo, &info);
break;
- case EXCP_ISI:
- fprintf(stderr, "Invalid instruction fetch\n");
- if (loglevel)
- fprintf(logfile, "Invalid instruction fetch\n");
+ case POWERPC_EXCP_ISI: /* Instruction storage exception */
+ EXCP_DUMP(env, "Invalid instruction fetch: 0x\n" ADDRX "\n",
+ env->spr[SPR_DAR]);
+ /* XXX: check this */
switch (env->error_code & 0xFF000000) {
case 0x40000000:
info.si_signo = TARGET_SIGSEGV;
@@ -824,12 +801,8 @@
break;
default:
/* Let's send a regular segfault... */
- fprintf(stderr, "Invalid segfault errno (%02x)\n",
- env->error_code);
- if (loglevel) {
- fprintf(logfile, "Invalid segfault errno (%02x)\n",
- env->error_code);
- }
+ EXCP_DUMP(env, "Invalid segfault errno (%02x)\n",
+ env->error_code);
info.si_signo = TARGET_SIGSEGV;
info.si_errno = 0;
info.si_code = TARGET_SEGV_MAPERR;
@@ -838,186 +811,159 @@
info._sifields._sigfault._addr = env->nip - 4;
queue_signal(info.si_signo, &info);
break;
- case EXCP_EXTERNAL:
- /* Should not happen ! */
- fprintf(stderr, "External interruption... Stop emulation\n");
- if (loglevel)
- fprintf(logfile, "External interruption... Stop emulation\n");
- abort();
- case EXCP_ALIGN:
- fprintf(stderr, "Invalid unaligned memory access\n");
- if (loglevel)
- fprintf(logfile, "Invalid unaligned memory access\n");
+ case POWERPC_EXCP_EXTERNAL: /* External input */
+ cpu_abort(env, "External interrupt while in user mode. "
+ "Aborting\n");
+ break;
+ case POWERPC_EXCP_ALIGN: /* Alignment exception */
+ EXCP_DUMP(env, "Unaligned memory access\n");
+ /* XXX: check this */
info.si_signo = TARGET_SIGBUS;
info.si_errno = 0;
info.si_code = TARGET_BUS_ADRALN;
info._sifields._sigfault._addr = env->nip - 4;
queue_signal(info.si_signo, &info);
break;
- case EXCP_PROGRAM:
+ case POWERPC_EXCP_PROGRAM: /* Program exception */
+ /* XXX: check this */
switch (env->error_code & ~0xF) {
- case EXCP_FP:
- fprintf(stderr, "Program exception\n");
- if (loglevel)
- fprintf(logfile, "Program exception\n");
- /* Set FX */
- env->fpscr[7] |= 0x8;
- /* Finally, update FEX */
- if ((((env->fpscr[7] & 0x3) << 3) | (env->fpscr[6] >> 1)) &
- ((env->fpscr[1] << 1) | (env->fpscr[0] >> 3)))
- env->fpscr[7] |= 0x4;
+ case POWERPC_EXCP_FP:
+ EXCP_DUMP(env, "Floating point program exception\n");
info.si_signo = TARGET_SIGFPE;
info.si_errno = 0;
switch (env->error_code & 0xF) {
- case EXCP_FP_OX:
+ case POWERPC_EXCP_FP_OX:
info.si_code = TARGET_FPE_FLTOVF;
break;
- case EXCP_FP_UX:
+ case POWERPC_EXCP_FP_UX:
info.si_code = TARGET_FPE_FLTUND;
break;
- case EXCP_FP_ZX:
- case EXCP_FP_VXZDZ:
+ case POWERPC_EXCP_FP_ZX:
+ case POWERPC_EXCP_FP_VXZDZ:
info.si_code = TARGET_FPE_FLTDIV;
break;
- case EXCP_FP_XX:
+ case POWERPC_EXCP_FP_XX:
info.si_code = TARGET_FPE_FLTRES;
break;
- case EXCP_FP_VXSOFT:
+ case POWERPC_EXCP_FP_VXSOFT:
info.si_code = TARGET_FPE_FLTINV;
break;
- case EXCP_FP_VXNAN:
- case EXCP_FP_VXISI:
- case EXCP_FP_VXIDI:
- case EXCP_FP_VXIMZ:
- case EXCP_FP_VXVC:
- case EXCP_FP_VXSQRT:
- case EXCP_FP_VXCVI:
+ case POWERPC_EXCP_FP_VXSNAN:
+ case POWERPC_EXCP_FP_VXISI:
+ case POWERPC_EXCP_FP_VXIDI:
+ case POWERPC_EXCP_FP_VXIMZ:
+ case POWERPC_EXCP_FP_VXVC:
+ case POWERPC_EXCP_FP_VXSQRT:
+ case POWERPC_EXCP_FP_VXCVI:
info.si_code = TARGET_FPE_FLTSUB;
break;
default:
- fprintf(stderr, "Unknown floating point exception "
- "(%02x)\n", env->error_code);
- if (loglevel) {
- fprintf(logfile, "Unknown floating point exception "
- "(%02x)\n", env->error_code & 0xF);
- }
+ EXCP_DUMP(env, "Unknown floating point exception (%02x)\n",
+ env->error_code);
+ break;
}
- break;
- case EXCP_INVAL:
- fprintf(stderr, "Invalid instruction\n");
- if (loglevel)
- fprintf(logfile, "Invalid instruction\n");
+ break;
+ case POWERPC_EXCP_INVAL:
+ EXCP_DUMP(env, "Invalid instruction\n");
info.si_signo = TARGET_SIGILL;
info.si_errno = 0;
switch (env->error_code & 0xF) {
- case EXCP_INVAL_INVAL:
+ case POWERPC_EXCP_INVAL_INVAL:
info.si_code = TARGET_ILL_ILLOPC;
break;
- case EXCP_INVAL_LSWX:
- info.si_code = TARGET_ILL_ILLOPN;
+ case POWERPC_EXCP_INVAL_LSWX:
+ info.si_code = TARGET_ILL_ILLOPN;
break;
- case EXCP_INVAL_SPR:
+ case POWERPC_EXCP_INVAL_SPR:
info.si_code = TARGET_ILL_PRVREG;
break;
- case EXCP_INVAL_FP:
+ case POWERPC_EXCP_INVAL_FP:
info.si_code = TARGET_ILL_COPROC;
break;
default:
- fprintf(stderr, "Unknown invalid operation (%02x)\n",
- env->error_code & 0xF);
- if (loglevel) {
- fprintf(logfile, "Unknown invalid operation (%02x)\n",
- env->error_code & 0xF);
- }
+ EXCP_DUMP(env, "Unknown invalid operation (%02x)\n",
+ env->error_code & 0xF);
info.si_code = TARGET_ILL_ILLADR;
break;
}
break;
- case EXCP_PRIV:
- fprintf(stderr, "Privilege violation\n");
- if (loglevel)
- fprintf(logfile, "Privilege violation\n");
+ case POWERPC_EXCP_PRIV:
+ EXCP_DUMP(env, "Privilege violation\n");
info.si_signo = TARGET_SIGILL;
info.si_errno = 0;
switch (env->error_code & 0xF) {
- case EXCP_PRIV_OPC:
+ case POWERPC_EXCP_PRIV_OPC:
info.si_code = TARGET_ILL_PRVOPC;
break;
- case EXCP_PRIV_REG:
+ case POWERPC_EXCP_PRIV_REG:
info.si_code = TARGET_ILL_PRVREG;
- break;
+ break;
default:
- fprintf(stderr, "Unknown privilege violation (%02x)\n",
- env->error_code & 0xF);
+ EXCP_DUMP(env, "Unknown privilege violation (%02x)\n",
+ env->error_code & 0xF);
info.si_code = TARGET_ILL_PRVOPC;
break;
}
break;
- case EXCP_TRAP:
- fprintf(stderr, "Tried to call a TRAP\n");
- if (loglevel)
- fprintf(logfile, "Tried to call a TRAP\n");
- abort();
+ case POWERPC_EXCP_TRAP:
+ cpu_abort(env, "Tried to call a TRAP\n");
+ break;
default:
/* Should not happen ! */
- fprintf(stderr, "Unknown program exception (%02x)\n",
- env->error_code);
- if (loglevel) {
- fprintf(logfile, "Unknwon program exception (%02x)\n",
- env->error_code);
- }
- abort();
+ cpu_abort(env, "Unknown program exception (%02x)\n",
+ env->error_code);
+ break;
}
info._sifields._sigfault._addr = env->nip - 4;
queue_signal(info.si_signo, &info);
break;
- case EXCP_NO_FP:
- fprintf(stderr, "No floating point allowed\n");
- if (loglevel)
- fprintf(logfile, "No floating point allowed\n");
+ case POWERPC_EXCP_FPU: /* Floating-point unavailable exception */
+ EXCP_DUMP(env, "No floating point allowed\n");
info.si_signo = TARGET_SIGILL;
info.si_errno = 0;
info.si_code = TARGET_ILL_COPROC;
info._sifields._sigfault._addr = env->nip - 4;
queue_signal(info.si_signo, &info);
break;
- case EXCP_DECR:
- /* Should not happen ! */
- fprintf(stderr, "Decrementer exception\n");
- if (loglevel)
- fprintf(logfile, "Decrementer exception\n");
- abort();
- case EXCP_TRACE:
- /* Do nothing: we use this to trace execution */
+ case POWERPC_EXCP_SYSCALL: /* System call exception */
+ cpu_abort(env, "Syscall exception while in user mode. "
+ "Aborting\n");
break;
- case EXCP_FP_ASSIST:
- /* Should not happen ! */
- fprintf(stderr, "Floating point assist exception\n");
- if (loglevel)
- fprintf(logfile, "Floating point assist exception\n");
- abort();
- case EXCP_MTMSR:
- /* We reloaded the msr, just go on */
- if (msr_pr == 0) {
- fprintf(stderr, "Tried to go into supervisor mode !\n");
- if (loglevel)
- fprintf(logfile, "Tried to go into supervisor mode !\n");
- abort();
- }
+ case POWERPC_EXCP_APU: /* Auxiliary processor unavailable */
+ EXCP_DUMP(env, "No APU instruction allowed\n");
+ info.si_signo = TARGET_SIGILL;
+ info.si_errno = 0;
+ info.si_code = TARGET_ILL_COPROC;
+ info._sifields._sigfault._addr = env->nip - 4;
+ queue_signal(info.si_signo, &info);
break;
- case EXCP_BRANCH:
- /* We stopped because of a jump... */
+ case POWERPC_EXCP_DECR: /* Decrementer exception */
+ cpu_abort(env, "Decrementer interrupt while in user mode. "
+ "Aborting\n");
break;
- case EXCP_INTERRUPT:
- /* Don't know why this should ever happen... */
+ case POWERPC_EXCP_FIT: /* Fixed-interval timer interrupt */
+ cpu_abort(env, "Fix interval timer interrupt while in user mode. "
+ "Aborting\n");
break;
- case EXCP_DEBUG:
+ case POWERPC_EXCP_WDT: /* Watchdog timer interrupt */
+ cpu_abort(env, "Watchdog timer interrupt while in user mode. "
+ "Aborting\n");
+ break;
+ case POWERPC_EXCP_DTLB: /* Data TLB error */
+ cpu_abort(env, "Data TLB exception while in user mode. "
+ "Aborting\n");
+ break;
+ case POWERPC_EXCP_ITLB: /* Instruction TLB error */
+ cpu_abort(env, "Instruction TLB exception while in user mode. "
+ "Aborting\n");
+ break;
+ case POWERPC_EXCP_DEBUG: /* Debug interrupt */
+ /* XXX: check this */
{
int sig;
- sig = gdb_handlesig (env, TARGET_SIGTRAP);
- if (sig)
- {
+ sig = gdb_handlesig(env, TARGET_SIGTRAP);
+ if (sig) {
info.si_signo = sig;
info.si_errno = 0;
info.si_code = TARGET_TRAP_BRKPT;
@@ -1025,14 +971,176 @@
}
}
break;
+#if defined(TARGET_PPCEMB)
+ case POWERPC_EXCP_SPEU: /* SPE/embedded floating-point unavail. */
+ EXCP_DUMP(env, "No SPE/floating-point instruction allowed\n");
+ info.si_signo = TARGET_SIGILL;
+ info.si_errno = 0;
+ info.si_code = TARGET_ILL_COPROC;
+ info._sifields._sigfault._addr = env->nip - 4;
+ queue_signal(info.si_signo, &info);
+ break;
+ case POWERPC_EXCP_EFPDI: /* Embedded floating-point data IRQ */
+ cpu_abort(env, "Embedded floating-point data IRQ not handled\n");
+ break;
+ case POWERPC_EXCP_EFPRI: /* Embedded floating-point round IRQ */
+ cpu_abort(env, "Embedded floating-point round IRQ not handled\n");
+ break;
+ case POWERPC_EXCP_EPERFM: /* Embedded performance monitor IRQ */
+ cpu_abort(env, "Performance monitor exception not handled\n");
+ break;
+ case POWERPC_EXCP_DOORI: /* Embedded doorbell interrupt */
+ cpu_abort(env, "Doorbell interrupt while in user mode. "
+ "Aborting\n");
+ break;
+ case POWERPC_EXCP_DOORCI: /* Embedded doorbell critical interrupt */
+ cpu_abort(env, "Doorbell critical interrupt while in user mode. "
+ "Aborting\n");
+ break;
+ case POWERPC_EXCP_RESET: /* System reset exception */
+ cpu_abort(env, "Reset interrupt while in user mode. "
+ "Aborting\n");
+ break;
+#endif /* defined(TARGET_PPCEMB) */
+#if defined(TARGET_PPC64) && !defined(TARGET_ABI32) /* PowerPC 64 */
+ case POWERPC_EXCP_DSEG: /* Data segment exception */
+ cpu_abort(env, "Data segment exception while in user mode. "
+ "Aborting\n");
+ break;
+ case POWERPC_EXCP_ISEG: /* Instruction segment exception */
+ cpu_abort(env, "Instruction segment exception "
+ "while in user mode. Aborting\n");
+ break;
+#endif /* defined(TARGET_PPC64) && !defined(TARGET_ABI32) */
+#if defined(TARGET_PPC64H) && !defined(TARGET_ABI32)
+ /* PowerPC 64 with hypervisor mode support */
+ case POWERPC_EXCP_HDECR: /* Hypervisor decrementer exception */
+ cpu_abort(env, "Hypervisor decrementer interrupt "
+ "while in user mode. Aborting\n");
+ break;
+#endif /* defined(TARGET_PPC64H) && !defined(TARGET_ABI32) */
+ case POWERPC_EXCP_TRACE: /* Trace exception */
+ /* Nothing to do:
+ * we use this exception to emulate step-by-step execution mode.
+ */
+ break;
+#if defined(TARGET_PPC64H) && !defined(TARGET_ABI32)
+ /* PowerPC 64 with hypervisor mode support */
+ case POWERPC_EXCP_HDSI: /* Hypervisor data storage exception */
+ cpu_abort(env, "Hypervisor data storage exception "
+ "while in user mode. Aborting\n");
+ break;
+ case POWERPC_EXCP_HISI: /* Hypervisor instruction storage excp */
+ cpu_abort(env, "Hypervisor instruction storage exception "
+ "while in user mode. Aborting\n");
+ break;
+ case POWERPC_EXCP_HDSEG: /* Hypervisor data segment exception */
+ cpu_abort(env, "Hypervisor data segment exception "
+ "while in user mode. Aborting\n");
+ break;
+ case POWERPC_EXCP_HISEG: /* Hypervisor instruction segment excp */
+ cpu_abort(env, "Hypervisor instruction segment exception "
+ "while in user mode. Aborting\n");
+ break;
+#endif /* defined(TARGET_PPC64H) && !defined(TARGET_ABI32) */
+ case POWERPC_EXCP_VPU: /* Vector unavailable exception */
+ EXCP_DUMP(env, "No Altivec instructions allowed\n");
+ info.si_signo = TARGET_SIGILL;
+ info.si_errno = 0;
+ info.si_code = TARGET_ILL_COPROC;
+ info._sifields._sigfault._addr = env->nip - 4;
+ queue_signal(info.si_signo, &info);
+ break;
+ case POWERPC_EXCP_PIT: /* Programmable interval timer IRQ */
+ cpu_abort(env, "Programable interval timer interrupt "
+ "while in user mode. Aborting\n");
+ break;
+ case POWERPC_EXCP_IO: /* IO error exception */
+ cpu_abort(env, "IO error exception while in user mode. "
+ "Aborting\n");
+ break;
+ case POWERPC_EXCP_RUNM: /* Run mode exception */
+ cpu_abort(env, "Run mode exception while in user mode. "
+ "Aborting\n");
+ break;
+ case POWERPC_EXCP_EMUL: /* Emulation trap exception */
+ cpu_abort(env, "Emulation trap exception not handled\n");
+ break;
+ case POWERPC_EXCP_IFTLB: /* Instruction fetch TLB error */
+ cpu_abort(env, "Instruction fetch TLB exception "
+ "while in user-mode. Aborting");
+ break;
+ case POWERPC_EXCP_DLTLB: /* Data load TLB miss */
+ cpu_abort(env, "Data load TLB exception while in user-mode. "
+ "Aborting");
+ break;
+ case POWERPC_EXCP_DSTLB: /* Data store TLB miss */
+ cpu_abort(env, "Data store TLB exception while in user-mode. "
+ "Aborting");
+ break;
+ case POWERPC_EXCP_FPA: /* Floating-point assist exception */
+ cpu_abort(env, "Floating-point assist exception not handled\n");
+ break;
+ case POWERPC_EXCP_IABR: /* Instruction address breakpoint */
+ cpu_abort(env, "Instruction address breakpoint exception "
+ "not handled\n");
+ break;
+ case POWERPC_EXCP_SMI: /* System management interrupt */
+ cpu_abort(env, "System management interrupt while in user mode. "
+ "Aborting\n");
+ break;
+ case POWERPC_EXCP_THERM: /* Thermal interrupt */
+ cpu_abort(env, "Thermal interrupt interrupt while in user mode. "
+ "Aborting\n");
+ break;
+ case POWERPC_EXCP_PERFM: /* Embedded performance monitor IRQ */
+ cpu_abort(env, "Performance monitor exception not handled\n");
+ break;
+ case POWERPC_EXCP_VPUA: /* Vector assist exception */
+ cpu_abort(env, "Vector assist exception not handled\n");
+ break;
+ case POWERPC_EXCP_SOFTP: /* Soft patch exception */
+ cpu_abort(env, "Soft patch exception not handled\n");
+ break;
+ case POWERPC_EXCP_MAINT: /* Maintenance exception */
+ cpu_abort(env, "Maintenance exception while in user mode. "
+ "Aborting\n");
+ break;
+ case POWERPC_EXCP_STOP: /* stop translation */
+ /* We did invalidate the instruction cache. Go on */
+ break;
+ case POWERPC_EXCP_BRANCH: /* branch instruction: */
+ /* We just stopped because of a branch. Go on */
+ break;
+ case POWERPC_EXCP_SYSCALL_USER:
+ /* system call in user-mode emulation */
+ /* WARNING:
+ * PPC ABI uses overflow flag in cr0 to signal an error
+ * in syscalls.
+ */
+#if 0
+ printf("syscall %d 0x%08x 0x%08x 0x%08x 0x%08x\n", env->gpr[0],
+ env->gpr[3], env->gpr[4], env->gpr[5], env->gpr[6]);
+#endif
+ env->crf[0] &= ~0x1;
+ ret = do_syscall(env, env->gpr[0], env->gpr[3], env->gpr[4],
+ env->gpr[5], env->gpr[6], env->gpr[7],
+ env->gpr[8]);
+ if (ret > (uint32_t)(-515)) {
+ env->crf[0] |= 0x1;
+ ret = -ret;
+ }
+ env->gpr[3] = ret;
+#if 0
+ printf("syscall returned 0x%08x (%d)\n", ret, ret);
+#endif
+ break;
+ case EXCP_INTERRUPT:
+ /* just indicate that signals should be handled asap */
+ break;
default:
- fprintf(stderr, "qemu: unhandled CPU exception 0x%x - aborting\n",
- trapnr);
- if (loglevel) {
- fprintf(logfile, "qemu: unhandled CPU exception 0x%02x - "
- "0x%02x - aborting\n", trapnr, env->error_code);
- }
- abort();
+ cpu_abort(env, "Unknown exception 0x%d. Aborting\n", trapnr);
+ break;
}
process_pending_signals(env);
}
@@ -1380,8 +1488,8 @@
ret = -ENOSYS;
} else {
int nb_args;
- target_ulong sp_reg;
- target_ulong arg5 = 0, arg6 = 0, arg7 = 0, arg8 = 0;
+ abi_ulong sp_reg;
+ abi_ulong arg5 = 0, arg6 = 0, arg7 = 0, arg8 = 0;
nb_args = mips_syscall_args[syscall_num];
sp_reg = env->gpr[29][env->current_tc];
@@ -1493,6 +1601,61 @@
}
#endif
+#ifdef TARGET_CRIS
+void cpu_loop (CPUState *env)
+{
+ int trapnr, ret;
+ target_siginfo_t info;
+
+ while (1) {
+ trapnr = cpu_cris_exec (env);
+ switch (trapnr) {
+ case 0xaa:
+ {
+ info.si_signo = SIGSEGV;
+ info.si_errno = 0;
+ /* XXX: check env->error_code */
+ info.si_code = TARGET_SEGV_MAPERR;
+ info._sifields._sigfault._addr = env->debug1;
+ queue_signal(info.si_signo, &info);
+ }
+ break;
+ case EXCP_BREAK:
+ ret = do_syscall(env,
+ env->regs[9],
+ env->regs[10],
+ env->regs[11],
+ env->regs[12],
+ env->regs[13],
+ env->pregs[7],
+ env->pregs[11]);
+ env->regs[10] = ret;
+ env->pc += 2;
+ break;
+ case EXCP_DEBUG:
+ {
+ int sig;
+
+ sig = gdb_handlesig (env, TARGET_SIGTRAP);
+ if (sig)
+ {
+ info.si_signo = sig;
+ info.si_errno = 0;
+ info.si_code = TARGET_TRAP_BRKPT;
+ queue_signal(info.si_signo, &info);
+ }
+ }
+ break;
+ default:
+ printf ("Unhandled trap: 0x%x\n", trapnr);
+ cpu_dump_state(env, stderr, fprintf, 0);
+ exit (1);
+ }
+ process_pending_signals (env);
+ }
+}
+#endif
+
#ifdef TARGET_M68K
void cpu_loop(CPUM68KState *env)
@@ -1781,14 +1944,9 @@
} else if (!strcmp(r, "cpu")) {
cpu_model = argv[optind++];
if (strcmp(cpu_model, "?") == 0) {
-#if defined(TARGET_PPC)
- ppc_cpu_list(stdout, &fprintf);
-#elif defined(TARGET_ARM)
- arm_cpu_list();
-#elif defined(TARGET_MIPS)
- mips_cpu_list(stdout, &fprintf);
-#elif defined(TARGET_SPARC)
- sparc_cpu_list(stdout, &fprintf);
+/* XXX: implement xxx_cpu_list for targets that still miss it */
+#if defined(cpu_list)
+ cpu_list(stdout, &fprintf);
#endif
_exit(1);
}
@@ -1850,14 +2008,17 @@
if (loglevel) {
page_dump(logfile);
- fprintf(logfile, "start_brk 0x%08lx\n" , info->start_brk);
- fprintf(logfile, "end_code 0x%08lx\n" , info->end_code);
- fprintf(logfile, "start_code 0x%08lx\n" , info->start_code);
- fprintf(logfile, "start_data 0x%08lx\n" , info->start_data);
- fprintf(logfile, "end_data 0x%08lx\n" , info->end_data);
- fprintf(logfile, "start_stack 0x%08lx\n" , info->start_stack);
- fprintf(logfile, "brk 0x%08lx\n" , info->brk);
- fprintf(logfile, "entry 0x%08lx\n" , info->entry);
+ fprintf(logfile, "start_brk 0x" TARGET_FMT_lx "\n", info->start_brk);
+ fprintf(logfile, "end_code 0x" TARGET_FMT_lx "\n", info->end_code);
+ fprintf(logfile, "start_code 0x" TARGET_FMT_lx "\n",
+ info->start_code);
+ fprintf(logfile, "start_data 0x" TARGET_FMT_lx "\n",
+ info->start_data);
+ fprintf(logfile, "end_data 0x" TARGET_FMT_lx "\n", info->end_data);
+ fprintf(logfile, "start_stack 0x" TARGET_FMT_lx "\n",
+ info->start_stack);
+ fprintf(logfile, "brk 0x" TARGET_FMT_lx "\n", info->brk);
+ fprintf(logfile, "entry 0x" TARGET_FMT_lx "\n", info->entry);
}
target_set_brk(info->brk);
@@ -1977,7 +2138,7 @@
fprintf(stderr, "Unable to find Sparc CPU definition\n");
exit(1);
}
- cpu_sparc_register(env, def);
+ cpu_sparc_register(env, def, 0);
env->pc = regs->pc;
env->npc = regs->npc;
env->y = regs->y;
@@ -2000,14 +2161,14 @@
"Unable to find PowerPC CPU definition\n");
}
cpu_ppc_register(env, def);
-
- for (i = 0; i < 32; i++) {
- if (i != 12 && i != 6 && i != 13)
- env->msr[i] = (regs->msr >> i) & 1;
- }
+ cpu_ppc_reset(env);
#if defined(TARGET_PPC64)
- msr_sf = 1;
+#if defined(TARGET_ABI32)
+ env->msr &= ~((target_ulong)1 << MSR_SF);
+#else
+ env->msr |= (target_ulong)1 << MSR_SF;
#endif
+#endif
env->nip = regs->nip;
for(i = 0; i < 32; i++) {
env->gpr[i] = regs->gpr[i];
@@ -2048,7 +2209,11 @@
/* Choose and initialise CPU */
if (cpu_model == NULL)
+#if defined(TARGET_MIPSN32) || defined(TARGET_MIPS64)
+ cpu_model = "20Kc";
+#else
cpu_model = "24Kf";
+#endif
mips_find_by_name(cpu_model, &def);
if (def == NULL)
cpu_abort(env, "Unable to find MIPS CPU definition\n");
@@ -2073,13 +2238,33 @@
int i;
for(i = 0; i < 28; i++) {
- env->ir[i] = ((target_ulong *)regs)[i];
+ env->ir[i] = ((abi_ulong *)regs)[i];
}
env->ipr[IPR_USP] = regs->usp;
env->ir[30] = regs->usp;
env->pc = regs->pc;
env->unique = regs->unique;
}
+#elif defined(TARGET_CRIS)
+ {
+ env->regs[0] = regs->r0;
+ env->regs[1] = regs->r1;
+ env->regs[2] = regs->r2;
+ env->regs[3] = regs->r3;
+ env->regs[4] = regs->r4;
+ env->regs[5] = regs->r5;
+ env->regs[6] = regs->r6;
+ env->regs[7] = regs->r7;
+ env->regs[8] = regs->r8;
+ env->regs[9] = regs->r9;
+ env->regs[10] = regs->r10;
+ env->regs[11] = regs->r11;
+ env->regs[12] = regs->r12;
+ env->regs[13] = regs->r13;
+ env->regs[14] = info->start_stack;
+ env->regs[15] = regs->acr;
+ env->pc = regs->erp;
+ }
#else
#error unsupported target CPU
#endif
Modified: trunk/src/host/qemu-neo1973/linux-user/mips/syscall.h
===================================================================
--- trunk/src/host/qemu-neo1973/linux-user/mips/syscall.h 2007-10-29 20:40:05 UTC (rev 3302)
+++ trunk/src/host/qemu-neo1973/linux-user/mips/syscall.h 2007-10-29 21:14:04 UTC (rev 3303)
@@ -3,21 +3,19 @@
stack during a system call. */
struct target_pt_regs {
-#if 1
/* Pad bytes for argument save space on the stack. */
- target_ulong pad0[6];
-#endif
+ abi_ulong pad0[6];
/* Saved main processor registers. */
- target_ulong regs[32];
+ abi_ulong regs[32];
/* Saved special registers. */
- target_ulong cp0_status;
- target_ulong lo;
- target_ulong hi;
- target_ulong cp0_badvaddr;
- target_ulong cp0_cause;
- target_ulong cp0_epc;
+ abi_ulong cp0_status;
+ abi_ulong lo;
+ abi_ulong hi;
+ abi_ulong cp0_badvaddr;
+ abi_ulong cp0_cause;
+ abi_ulong cp0_epc;
};
/* Target errno definitions taken from asm-mips/errno.h */
Modified: trunk/src/host/qemu-neo1973/linux-user/mips/syscall_nr.h
===================================================================
--- trunk/src/host/qemu-neo1973/linux-user/mips/syscall_nr.h 2007-10-29 20:40:05 UTC (rev 3302)
+++ trunk/src/host/qemu-neo1973/linux-user/mips/syscall_nr.h 2007-10-29 21:14:04 UTC (rev 3303)
@@ -318,3 +318,8 @@
#define TARGET_NR_epoll_pwait (TARGET_NR_Linux + 313)
#define TARGET_NR_ioprio_set (TARGET_NR_Linux + 314)
#define TARGET_NR_ioprio_get (TARGET_NR_Linux + 315)
+#define TARGET_NR_utimensat (TARGET_NR_Linux + 316)
+#define TARGET_NR_signalfd (TARGET_NR_Linux + 317)
+#define TARGET_NR_timerfd (TARGET_NR_Linux + 318)
+#define TARGET_NR_eventfd (TARGET_NR_Linux + 319)
+#define TARGET_NR_fallocate (TARGET_NR_Linux + 320)
Added: trunk/src/host/qemu-neo1973/linux-user/mips/target_signal.h
===================================================================
--- trunk/src/host/qemu-neo1973/linux-user/mips/target_signal.h 2007-10-29 20:40:05 UTC (rev 3302)
+++ trunk/src/host/qemu-neo1973/linux-user/mips/target_signal.h 2007-10-29 21:14:04 UTC (rev 3303)
@@ -0,0 +1,29 @@
+#ifndef TARGET_SIGNAL_H
+#define TARGET_SIGNAL_H
+
+#include "cpu.h"
+
+/* this struct defines a stack used during syscall handling */
+
+typedef struct target_sigaltstack {
+ abi_long ss_sp;
+ abi_ulong ss_size;
+ abi_long ss_flags;
+} target_stack_t;
+
+
+/*
+ * sigaltstack controls
+ */
+#define TARGET_SS_ONSTACK 1
+#define TARGET_SS_DISABLE 2
+
+#define TARGET_MINSIGSTKSZ 2048
+#define TARGET_SIGSTKSZ 8192
+
+static inline abi_ulong get_sp_from_cpustate(CPUMIPSState *state)
+{
+ return state->gpr[29][state->current_tc];
+}
+
+#endif /* TARGET_SIGNAL_H */
Modified: trunk/src/host/qemu-neo1973/linux-user/mips/termbits.h
===================================================================
--- trunk/src/host/qemu-neo1973/linux-user/mips/termbits.h 2007-10-29 20:40:05 UTC (rev 3302)
+++ trunk/src/host/qemu-neo1973/linux-user/mips/termbits.h 2007-10-29 21:14:04 UTC (rev 3303)
@@ -26,6 +26,7 @@
#define TARGET_IXANY 0004000
#define TARGET_IXOFF 0010000
#define TARGET_IMAXBEL 0020000
+#define TARGET_IUTF8 0040000
/* c_oflag bits */
#define TARGET_OPOST 0000001
@@ -92,12 +93,25 @@
#define TARGET_HUPCL 0002000
#define TARGET_CLOCAL 0004000
#define TARGET_CBAUDEX 0010000
-#define TARGET_B57600 0010001
-#define TARGET_B115200 0010002
-#define TARGET_B230400 0010003
-#define TARGET_B460800 0010004
+#define TARGET_BOTHER 0010000
+#define TARGET_B57600 0010001
+#define TARGET_B115200 0010002
+#define TARGET_B230400 0010003
+#define TARGET_B460800 0010004
+#define TARGET_B500000 0010005
+#define TARGET_B576000 0010006
+#define TARGET_B921600 0010007
+#define TARGET_B1000000 0010010
+#define TARGET_B1152000 0010011
+#define TARGET_B1500000 0010012
+#define TARGET_B2000000 0010013
+#define TARGET_B2500000 0010014
+#define TARGET_B3000000 0010015
+#define TARGET_B3500000 0010016
+#define TARGET_B4000000 0010017
#define TARGET_CIBAUD 002003600000 /* input baud rate (not used) */
-#define TARGET_CRTSCTS 020000000000 /* flow control */
+#define TARGET_CMSPAR 010000000000 /* mark or space (stick) parity */
+#define TARGET_CRTSCTS 020000000000 /* flow control */
/* c_lflag bits */
#define TARGET_ISIG 0000001
@@ -108,32 +122,34 @@
#define TARGET_ECHOK 0000040
#define TARGET_ECHONL 0000100
#define TARGET_NOFLSH 0000200
-#define TARGET_TOSTOP 0000400
+#define TARGET_IEXTEN 0000400
#define TARGET_ECHOCTL 0001000
#define TARGET_ECHOPRT 0002000
#define TARGET_ECHOKE 0004000
#define TARGET_FLUSHO 0010000
#define TARGET_PENDIN 0040000
-#define TARGET_IEXTEN 0100000
+#define TARGET_TOSTOP 0100000
+#define TARGET_ITOSTOP TARGET_TOSTOP
/* c_cc character offsets */
#define TARGET_VINTR 0
#define TARGET_VQUIT 1
#define TARGET_VERASE 2
#define TARGET_VKILL 3
-#define TARGET_VEOF 4
+#define TARGET_VMIN 4
#define TARGET_VTIME 5
-#define TARGET_VMIN 6
+#define TARGET_VEOL2 6
#define TARGET_VSWTC 7
#define TARGET_VSTART 8
#define TARGET_VSTOP 9
#define TARGET_VSUSP 10
-#define TARGET_VEOL 11
+/* VDSUSP not supported */
#define TARGET_VREPRINT 12
#define TARGET_VDISCARD 13
#define TARGET_VWERASE 14
#define TARGET_VLNEXT 15
-#define TARGET_VEOL2 16
+#define TARGET_VEOF 16
+#define TARGET_VEOL 17
/* ioctls */
@@ -154,7 +170,7 @@
#define TARGET_TIOCEXCL 0x740d /* set exclusive use of tty */
#define TARGET_TIOCNXCL 0x740e /* reset exclusive use of tty */
#define TARGET_TIOCOUTQ 0x7472 /* output queue size */
-#define TARGET_TIOCSTI 0x5472 /* simulate terminal input */
+#define TARGET_TIOCSTI 0x5472 /* simulate terminal input */
#define TARGET_TIOCMGET 0x741d /* get all modem bits */
#define TARGET_TIOCMBIS 0x741b /* bis modem bits */
#define TARGET_TIOCMBIC 0x741c /* bic modem bits */
Modified: trunk/src/host/qemu-neo1973/linux-user/mmap.c
===================================================================
--- trunk/src/host/qemu-neo1973/linux-user/mmap.c 2007-10-29 20:40:05 UTC (rev 3302)
+++ trunk/src/host/qemu-neo1973/linux-user/mmap.c 2007-10-29 21:14:04 UTC (rev 3303)
@@ -30,13 +30,14 @@
//#define DEBUG_MMAP
/* NOTE: all the constants are the HOST ones, but addresses are target. */
-int target_mprotect(target_ulong start, target_ulong len, int prot)
+int target_mprotect(abi_ulong start, abi_ulong len, int prot)
{
- target_ulong end, host_start, host_end, addr;
+ abi_ulong end, host_start, host_end, addr;
int prot1, ret;
#ifdef DEBUG_MMAP
- printf("mprotect: start=0x%lx len=0x%lx prot=%c%c%c\n", start, len,
+ printf("mprotect: start=0x" TARGET_FMT_lx
+ "len=0x" TARGET_FMT_lx " prot=%c%c%c\n", start, len,
prot & PROT_READ ? 'r' : '-',
prot & PROT_WRITE ? 'w' : '-',
prot & PROT_EXEC ? 'x' : '-');
@@ -95,11 +96,11 @@
}
/* map an incomplete host page */
-static int mmap_frag(target_ulong real_start,
- target_ulong start, target_ulong end,
- int prot, int flags, int fd, target_ulong offset)
+static int mmap_frag(abi_ulong real_start,
+ abi_ulong start, abi_ulong end,
+ int prot, int flags, int fd, abi_ulong offset)
{
- target_ulong real_end, ret, addr;
+ abi_ulong real_end, ret, addr;
void *host_start;
int prot1, prot_new;
@@ -151,22 +152,23 @@
}
/* NOTE: all the constants are the HOST ones */
-long target_mmap(target_ulong start, target_ulong len, int prot,
- int flags, int fd, target_ulong offset)
+abi_long target_mmap(abi_ulong start, abi_ulong len, int prot,
+ int flags, int fd, abi_ulong offset)
{
- target_ulong ret, end, real_start, real_end, retaddr, host_offset, host_len;
- long host_start;
+ abi_ulong ret, end, real_start, real_end, retaddr, host_offset, host_len;
+ unsigned long host_start;
#if defined(__alpha__) || defined(__sparc__) || defined(__x86_64__) || \
defined(__ia64) || defined(__mips__)
- static target_ulong last_start = 0x40000000;
+ static abi_ulong last_start = 0x40000000;
#elif defined(__CYGWIN__)
/* Cygwin doesn't have a whole lot of address space. */
- static target_ulong last_start = 0x18000000;
+ static abi_ulong last_start = 0x18000000;
#endif
#ifdef DEBUG_MMAP
{
- printf("mmap: start=0x%lx len=0x%lx prot=%c%c%c flags=",
+ printf("mmap: start=0x" TARGET_FMT_lx
+ " len=0x" TARGET_FMT_lx " prot=%c%c%c flags=",
start, len,
prot & PROT_READ ? 'r' : '-',
prot & PROT_WRITE ? 'w' : '-',
@@ -186,7 +188,7 @@
printf("[MAP_TYPE=0x%x] ", flags & MAP_TYPE);
break;
}
- printf("fd=%d offset=%lx\n", fd, offset);
+ printf("fd=%d offset=" TARGET_FMT_lx "\n", fd, offset);
}
#endif
@@ -209,34 +211,59 @@
last_start += HOST_PAGE_ALIGN(len);
}
#endif
- if (0 && qemu_host_page_size != qemu_real_host_page_size) {
- /* NOTE: this code is only for debugging with '-p' option */
- /* ??? Can also occur when TARGET_PAGE_SIZE > host page size. */
- /* reserve a memory area */
- /* ??? This needs fixing for remapping. */
-abort();
- host_len = HOST_PAGE_ALIGN(len) + qemu_host_page_size - TARGET_PAGE_SIZE;
- real_start = (long)mmap(g2h(real_start), host_len, PROT_NONE,
- MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
- if (real_start == -1)
- return real_start;
- real_end = real_start + host_len;
- start = HOST_PAGE_ALIGN(real_start);
- end = start + HOST_PAGE_ALIGN(len);
- if (start > real_start)
- munmap((void *)real_start, start - real_start);
- if (end < real_end)
- munmap((void *)end, real_end - end);
- /* use it as a fixed mapping */
- flags |= MAP_FIXED;
+ host_offset = offset & qemu_host_page_mask;
+ host_len = len + offset - host_offset;
+
+ if (qemu_host_page_size > qemu_real_host_page_size) {
+ /*
+ * The guest expects to see mmapped areas aligned to it's pagesize.
+ * If the host's real page size is smaller than the guest's, we need
+ * to fixup the maps. It is done by allocating a larger area,
+ * displacing the map (if needed) and finally chopping off the spare
+ * room at the edges.
+ */
+
+ /*
+ * We assume qemu_host_page_size is always the same as
+ * TARGET_PAGE_SIZE, see exec.c. qemu_real_host_page_size is the
+ * hosts real page size.
+ */
+ abi_ulong host_end;
+ unsigned long host_aligned_start;
+
+ 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)
+ return -1;
+
+ host_end = host_start + host_len;
+
+ /* Find start and end, aligned to the targets pagesize with-in the
+ large mmaped area. */
+ host_aligned_start = TARGET_PAGE_ALIGN(host_start);
+ if (!(flags & MAP_ANONYMOUS))
+ host_aligned_start += offset - host_offset;
+
+ start = h2g(host_aligned_start);
+ end = start + TARGET_PAGE_ALIGN(len);
+
+ /* Chop off the leftovers, if any. */
+ if (host_aligned_start > host_start)
+ munmap((void *)host_start, host_aligned_start - host_start);
+ if (end < host_end)
+ munmap((void *)g2h(end), host_end - end);
+
+ goto the_end1;
} else {
/* if not fixed, no need to do anything */
- host_offset = offset & qemu_host_page_mask;
- host_len = len + offset - host_offset;
host_start = (long)mmap(real_start ? g2h(real_start) : NULL,
host_len, prot, flags, fd, host_offset);
if (host_start == -1)
- return host_start;
+ return -1;
/* update start so that it points to the file position at 'offset' */
if (!(flags & MAP_ANONYMOUS))
host_start += offset - host_offset;
@@ -267,7 +294,7 @@
MAP_FIXED | MAP_PRIVATE | MAP_ANONYMOUS,
-1, 0);
if (retaddr == -1)
- return retaddr;
+ return -1;
pread(fd, g2h(start), len, offset);
if (!(prot & PROT_WRITE)) {
ret = target_mprotect(start, len, prot);
@@ -300,7 +327,7 @@
prot, flags, fd,
offset + real_end - qemu_host_page_size - start);
if (ret == -1)
- return ret;
+ return -1;
real_end -= qemu_host_page_size;
}
@@ -314,22 +341,22 @@
ret = (long)mmap(g2h(real_start), real_end - real_start,
prot, flags, fd, offset1);
if (ret == -1)
- return ret;
+ return -1;
}
the_end1:
page_set_flags(start, start + len, prot | PAGE_VALID);
the_end:
#ifdef DEBUG_MMAP
- printf("ret=0x%lx\n", (long)start);
+ printf("ret=0x%llx\n", start);
page_dump(stdout);
printf("\n");
#endif
return start;
}
-int target_munmap(target_ulong start, target_ulong len)
+int target_munmap(abi_ulong start, abi_ulong len)
{
- target_ulong end, real_start, real_end, addr;
+ abi_ulong end, real_start, real_end, addr;
int prot, ret;
#ifdef DEBUG_MMAP
@@ -370,7 +397,7 @@
/* unmap what we can */
if (real_start < real_end) {
- ret = munmap((void *)real_start, real_end - real_start);
+ ret = munmap(g2h(real_start), real_end - real_start);
if (ret != 0)
return ret;
}
@@ -381,26 +408,27 @@
/* XXX: currently, we only handle MAP_ANONYMOUS and not MAP_FIXED
blocks which have been allocated starting on a host page */
-long target_mremap(target_ulong old_addr, target_ulong old_size,
- target_ulong new_size, unsigned long flags,
- target_ulong new_addr)
+abi_long target_mremap(abi_ulong old_addr, abi_ulong old_size,
+ abi_ulong new_size, unsigned long flags,
+ abi_ulong new_addr)
{
int prot;
+ unsigned long host_addr;
/* XXX: use 5 args syscall */
- new_addr = (long)mremap(g2h(old_addr), old_size, new_size, flags);
- if (new_addr == -1)
- return new_addr;
- new_addr = h2g(new_addr);
+ host_addr = (long)mremap(g2h(old_addr), old_size, new_size, flags);
+ if (host_addr == -1)
+ return -1;
+ new_addr = h2g(host_addr);
prot = page_get_flags(old_addr);
page_set_flags(old_addr, old_addr + old_size, 0);
page_set_flags(new_addr, new_addr + new_size, prot | PAGE_VALID);
return new_addr;
}
-int target_msync(target_ulong start, target_ulong len, int flags)
+int target_msync(abi_ulong start, abi_ulong len, int flags)
{
- target_ulong end;
+ abi_ulong end;
if (start & ~TARGET_PAGE_MASK)
return -EINVAL;
Modified: trunk/src/host/qemu-neo1973/linux-user/ppc/syscall.h
===================================================================
--- trunk/src/host/qemu-neo1973/linux-user/ppc/syscall.h 2007-10-29 20:40:05 UTC (rev 3302)
+++ trunk/src/host/qemu-neo1973/linux-user/ppc/syscall.h 2007-10-29 21:14:04 UTC (rev 3303)
@@ -44,11 +44,15 @@
/* ioctls */
struct target_revectored_struct {
- target_ulong __map[8]; /* 256 bits */
+ abi_ulong __map[8]; /* 256 bits */
};
/*
* flags masks
*/
+#if defined(TARGET_PPC64) && !defined(TARGET_ABI32)
+#define UNAME_MACHINE "ppc64"
+#else
#define UNAME_MACHINE "ppc"
+#endif
Modified: trunk/src/host/qemu-neo1973/linux-user/ppc/syscall_nr.h
===================================================================
--- trunk/src/host/qemu-neo1973/linux-user/ppc/syscall_nr.h 2007-10-29 20:40:05 UTC (rev 3302)
+++ trunk/src/host/qemu-neo1973/linux-user/ppc/syscall_nr.h 2007-10-29 21:14:04 UTC (rev 3303)
@@ -193,19 +193,23 @@
#define TARGET_NR_vfork 189
#define TARGET_NR_ugetrlimit 190 /* SuS compliant getrlimit */
#define TARGET_NR_readahead 191
+#if !defined(TARGET_PPC64) || defined(TARGET_ABI32)
#define TARGET_NR_mmap2 192
#define TARGET_NR_truncate64 193
#define TARGET_NR_ftruncate64 194
#define TARGET_NR_stat64 195
#define TARGET_NR_lstat64 196
#define TARGET_NR_fstat64 197
+#endif
#define TARGET_NR_pciconfig_read 198
#define TARGET_NR_pciconfig_write 199
#define TARGET_NR_pciconfig_iobase 200
#define TARGET_NR_multiplexer 201
#define TARGET_NR_getdents64 202
#define TARGET_NR_pivot_root 203
+#if !defined(TARGET_PPC64) || defined(TARGET_ABI32)
#define TARGET_NR_fcntl64 204
+#endif
#define TARGET_NR_madvise 205
#define TARGET_NR_mincore 206
#define TARGET_NR_gettid 207
@@ -227,7 +231,9 @@
#define TARGET_NR_sched_getaffinity 223
/* 224 currently unused */
#define TARGET_NR_tuxcall 225
+#if !defined(TARGET_PPC64) || defined(TARGET_ABI32)
#define TARGET_NR_sendfile64 226
+#endif
#define TARGET_NR_io_setup 227
#define TARGET_NR_io_destroy 228
#define TARGET_NR_io_getevents 229
@@ -255,4 +261,65 @@
#define TARGET_NR_utimes 251
#define TARGET_NR_statfs64 252
#define TARGET_NR_fstatfs64 253
+#if !defined(TARGET_PPC64) || defined(TARGET_ABI32)
#define TARGET_NR_fadvise64_64 254
+#endif
+#define TARGET_NR_rtas 255
+#define TARGET_NR_sys_debug_setcontext 256
+/* Number 257 is reserved for vserver */
+#define TARGET_NR_migrate_pages 258
+#define TARGET_NR_mbind 259
+#define TARGET_NR_get_mempolicy 260
+#define TARGET_NR_set_mempolicy 261
+#define TARGET_NR_mq_open 262
+#define TARGET_NR_mq_unlink 263
+#define TARGET_NR_mq_timedsend 264
+#define TARGET_NR_mq_timedreceive 265
+#define TARGET_NR_mq_notify 266
+#define TARGET_NR_mq_getsetattr 267
+#define TARGET_NR_kexec_load 268
+#define TARGET_NR_add_key 269
+#define TARGET_NR_request_key 270
+#define TARGET_NR_keyctl 271
+#define TARGET_NR_waitid 272
+#define TARGET_NR_ioprio_set 273
+#define TARGET_NR_ioprio_get 274
+#define TARGET_NR_inotify_init 275
+#define TARGET_NR_inotify_add_watch 276
+#define TARGET_NR_inotify_rm_watch 277
+#define TARGET_NR_spu_run 278
+#define TARGET_NR_spu_create 279
+#define TARGET_NR_pselect6 280
+#define TARGET_NR_ppoll 281
+#define TARGET_NR_unshare 282
+#define TARGET_NR_splice 283
+#define TARGET_NR_tee 284
+#define TARGET_NR_vmsplice 285
+#define TARGET_NR_openat 286
+#define TARGET_NR_mkdirat 287
+#define TARGET_NR_mknodat 288
+#define TARGET_NR_fchownat 289
+#define TARGET_NR_futimesat 290
+#if defined(TARGET_PPC64) && !defined(TARGET_ABI32)
+#define TARGET_NR_newfstatat 291
+#else
+#define TARGET_NR_fstatat64 291
+#endif
+#define TARGET_NR_unlinkat 292
+#define TARGET_NR_renameat 293
+#define TARGET_NR_linkat 294
+#define TARGET_NR_symlinkat 295
+#define TARGET_NR_readlinkat 296
+#define TARGET_NR_fchmodat 297
+#define TARGET_NR_faccessat 298
+#define TARGET_NR_get_robust_list 299
+#define TARGET_NR_set_robust_list 300
+#define TARGET_NR_move_pages 301
+#define TARGET_NR_getcpu 302
+#define TARGET_NR_epoll_pwait 303
+#define TARGET_NR_utimensat 304
+#define TARGET_NR_signalfd 305
+#define TARGET_NR_timerfd 306
+#define TARGET_NR_eventfd 307
+#define TARGET_NR_sync_file_range2 308
+#define TARGET_NR_fallocate 309
Added: trunk/src/host/qemu-neo1973/linux-user/ppc/target_signal.h
===================================================================
--- trunk/src/host/qemu-neo1973/linux-user/ppc/target_signal.h 2007-10-29 20:40:05 UTC (rev 3302)
+++ trunk/src/host/qemu-neo1973/linux-user/ppc/target_signal.h 2007-10-29 21:14:04 UTC (rev 3303)
@@ -0,0 +1,29 @@
+#ifndef TARGET_SIGNAL_H
+#define TARGET_SIGNAL_H
+
+#include "cpu.h"
+
+/* this struct defines a stack used during syscall handling */
+
+typedef struct target_sigaltstack {
+ abi_ulong ss_sp;
+ abi_long ss_flags;
+ abi_ulong ss_size;
+} target_stack_t;
+
+
+/*
+ * sigaltstack controls
+ */
+#define TARGET_SS_ONSTACK 1
+#define TARGET_SS_DISABLE 2
+
+#define TARGET_MINSIGSTKSZ 2048
+#define TARGET_SIGSTKSZ 8192
+
+static inline abi_ulong get_sp_from_cpustate(CPUPPCState *state)
+{
+ return state->gpr[1];
+}
+
+#endif /* TARGET_SIGNAL_H */
Modified: trunk/src/host/qemu-neo1973/linux-user/ppc/termbits.h
===================================================================
--- trunk/src/host/qemu-neo1973/linux-user/ppc/termbits.h 2007-10-29 20:40:05 UTC (rev 3302)
+++ trunk/src/host/qemu-neo1973/linux-user/ppc/termbits.h 2007-10-29 21:14:04 UTC (rev 3303)
@@ -47,6 +47,7 @@
#define TARGET_IXANY 0004000
#define TARGET_IUCLC 0010000
#define TARGET_IMAXBEL 0020000
+#define TARGET_IUTF8 0040000
/* c_oflag bits */
#define TARGET_OPOST 0000001
@@ -69,6 +70,7 @@
#define TARGET_TAB1 00002000
#define TARGET_TAB2 00004000
#define TARGET_TAB3 00006000
+#define TARGET_XTABS 00006000 /* required by POSIX to == TAB3 */
#define TARGET_CRDLY 00030000
#define TARGET_CR0 00000000
#define TARGET_CR1 00010000
@@ -83,7 +85,6 @@
#define TARGET_VTDLY 00200000
#define TARGET_VT0 00000000
#define TARGET_VT1 00200000
-#define TARGET_XTABS 01000000 /* Hmm.. Linux/i386 considers this part of TABDLY.. */
/* c_cflag bit meaning */
#define TARGET_CBAUD 0000377
@@ -135,7 +136,8 @@
#define TARGET_HUPCL 00040000
#define TARGET_CLOCAL 00100000
-#define TARGET_CRTSCTS 020000000000 /* flow control */
+#define TARGET_CMSPAR 010000000000 /* mark or space (stick) parity */
+#define TARGET_CRTSCTS 020000000000 /* flow control */
/* c_lflag bits */
#define TARGET_ISIG 0x00000080
Modified: trunk/src/host/qemu-neo1973/linux-user/qemu.h
===================================================================
--- trunk/src/host/qemu-neo1973/linux-user/qemu.h 2007-10-29 20:40:05 UTC (rev 3302)
+++ trunk/src/host/qemu-neo1973/linux-user/qemu.h 2007-10-29 21:14:04 UTC (rev 3303)
@@ -1,14 +1,25 @@
#ifndef QEMU_H
#define QEMU_H
-#include "thunk.h"
-
#include <signal.h>
#include <string.h>
-#include "syscall_defs.h"
#include "cpu.h"
+
+#ifdef TARGET_ABI32
+typedef uint32_t abi_ulong;
+typedef int32_t abi_long;
+#define TARGET_ABI_BITS 32
+#else
+typedef target_ulong abi_ulong;
+typedef target_long abi_long;
+#define TARGET_ABI_BITS TARGET_LONG_BITS
+#endif
+
+#include "thunk.h"
+#include "syscall_defs.h"
#include "syscall.h"
+#include "target_signal.h"
#include "gdbstub.h"
/* This struct is used to hold certain information about the image.
@@ -16,19 +27,20 @@
* task_struct fields in the kernel
*/
struct image_info {
- unsigned long start_code;
- unsigned long end_code;
- unsigned long start_data;
- unsigned long end_data;
- unsigned long start_brk;
- unsigned long brk;
- unsigned long start_mmap;
- unsigned long mmap;
- unsigned long rss;
- unsigned long start_stack;
- unsigned long entry;
- target_ulong code_offset;
- target_ulong data_offset;
+ abi_ulong load_addr;
+ abi_ulong start_code;
+ abi_ulong end_code;
+ abi_ulong start_data;
+ abi_ulong end_data;
+ abi_ulong start_brk;
+ abi_ulong brk;
+ abi_ulong start_mmap;
+ abi_ulong mmap;
+ abi_ulong rss;
+ abi_ulong start_stack;
+ abi_ulong entry;
+ abi_ulong code_offset;
+ abi_ulong data_offset;
char **host_argv;
int personality;
};
@@ -65,7 +77,7 @@
int swi_errno;
#endif
#if defined(TARGET_I386) && !defined(TARGET_X86_64)
- target_ulong target_v86;
+ abi_ulong target_v86;
struct vm86_saved_state vm86_saved_regs;
struct target_vm86plus_struct vm86plus;
uint32_t v86flags;
@@ -103,7 +115,7 @@
struct linux_binprm {
char buf[128];
void *page[MAX_ARG_PAGES];
- unsigned long p;
+ abi_ulong p;
int fd;
int e_uid, e_gid;
int argc, envc;
@@ -113,8 +125,8 @@
};
void do_init_thread(struct target_pt_regs *regs, struct image_info *infop);
-target_ulong loader_build_argptr(int envc, int argc, target_ulong sp,
- target_ulong stringp, int push_ptr);
+abi_ulong loader_build_argptr(int envc, int argc, abi_ulong sp,
+ abi_ulong stringp, int push_ptr);
int loader_exec(const char * filename, char ** argv, char ** envp,
struct target_pt_regs * regs, struct image_info *infop);
@@ -122,14 +134,20 @@
struct image_info * info);
int load_flt_binary(struct linux_binprm * bprm, struct target_pt_regs * regs,
struct image_info * info);
+#ifdef TARGET_HAS_ELFLOAD32
+int load_elf_binary_multi(struct linux_binprm *bprm,
+ struct target_pt_regs *regs,
+ struct image_info *info);
+#endif
-void memcpy_to_target(target_ulong dest, const void *src,
+void memcpy_to_target(abi_ulong dest, const void *src,
unsigned long len);
-void target_set_brk(target_ulong new_brk);
-long do_brk(target_ulong new_brk);
+void target_set_brk(abi_ulong new_brk);
+abi_long do_brk(abi_ulong new_brk);
void syscall_init(void);
-long do_syscall(void *cpu_env, int num, long arg1, long arg2, long arg3,
- long arg4, long arg5, long arg6);
+abi_long do_syscall(void *cpu_env, int num, abi_long arg1,
+ abi_long arg2, abi_long arg3, abi_long arg4,
+ abi_long arg5, abi_long arg6);
void gemu_log(const char *fmt, ...) __attribute__((format(printf,1,2)));
extern CPUState *global_env;
void cpu_loop(CPUState *env);
@@ -147,24 +165,30 @@
void target_to_host_siginfo(siginfo_t *info, const target_siginfo_t *tinfo);
long do_sigreturn(CPUState *env);
long do_rt_sigreturn(CPUState *env);
+int do_sigaltstack(const struct target_sigaltstack *uss,
+ struct target_sigaltstack *uoss,
+ abi_ulong sp);
#ifdef TARGET_I386
/* vm86.c */
void save_v86_state(CPUX86State *env);
void handle_vm86_trap(CPUX86State *env, int trapno);
void handle_vm86_fault(CPUX86State *env);
-int do_vm86(CPUX86State *env, long subfunction, target_ulong v86_addr);
+int do_vm86(CPUX86State *env, long subfunction, abi_ulong v86_addr);
+#elif defined(TARGET_SPARC64)
+void sparc64_set_context(CPUSPARCState *env);
+void sparc64_get_context(CPUSPARCState *env);
#endif
/* mmap.c */
-int target_mprotect(target_ulong start, target_ulong len, int prot);
-long target_mmap(target_ulong start, target_ulong len, int prot,
- int flags, int fd, target_ulong offset);
-int target_munmap(target_ulong start, target_ulong len);
-long target_mremap(target_ulong old_addr, target_ulong old_size,
- target_ulong new_size, unsigned long flags,
- target_ulong new_addr);
-int target_msync(target_ulong start, target_ulong len, int flags);
+int target_mprotect(abi_ulong start, abi_ulong len, int prot);
+abi_long target_mmap(abi_ulong start, abi_ulong len, int prot,
+ int flags, int fd, abi_ulong offset);
+int target_munmap(abi_ulong start, abi_ulong len);
+abi_long target_mremap(abi_ulong old_addr, abi_ulong old_size,
+ abi_ulong new_size, unsigned long flags,
+ abi_ulong new_addr);
+int target_msync(abi_ulong start, abi_ulong len, int flags);
/* user access */
@@ -246,7 +270,7 @@
/* Lock an area of guest memory into the host. If copy is true then the
host area will have the same contents as the guest. */
-static inline void *lock_user(target_ulong guest_addr, long len, int copy)
+static inline void *lock_user(abi_ulong guest_addr, long len, int copy)
{
#ifdef DEBUG_REMAP
void *addr;
@@ -263,8 +287,8 @@
/* Unlock an area of guest memory. The first LEN bytes must be flushed back
to guest memory. */
-static inline void unlock_user(void *host_addr, target_ulong guest_addr,
- long len)
+static inline void unlock_user(void *host_addr, abi_ulong guest_addr,
+ long len)
{
#ifdef DEBUG_REMAP
if (host_addr == g2h(guest_addr))
@@ -276,13 +300,13 @@
}
/* Return the length of a string in target memory. */
-static inline int target_strlen(target_ulong ptr)
+static inline int target_strlen(abi_ulong ptr)
{
return strlen(g2h(ptr));
}
/* Like lock_user but for null terminated strings. */
-static inline void *lock_user_string(target_ulong guest_addr)
+static inline void *lock_user_string(abi_ulong guest_addr)
{
long len;
len = target_strlen(guest_addr) + 1;
@@ -303,7 +327,7 @@
#define tput32(addr, val) stl(addr, val)
#define tget64(addr) ldq(addr)
#define tput64(addr, val) stq(addr, val)
-#if TARGET_LONG_BITS == 64
+#if TARGET_ABI_BITS == 64
#define tgetl(addr) ldq(addr)
#define tputl(addr, val) stq(addr, val)
#else
Modified: trunk/src/host/qemu-neo1973/linux-user/sh4/syscall_nr.h
===================================================================
--- trunk/src/host/qemu-neo1973/linux-user/sh4/syscall_nr.h 2007-10-29 20:40:05 UTC (rev 3302)
+++ trunk/src/host/qemu-neo1973/linux-user/sh4/syscall_nr.h 2007-10-29 21:14:04 UTC (rev 3303)
@@ -226,6 +226,7 @@
#define TARGET_NR_fcntl64 221
/* 223 is unused */
#define TARGET_NR_gettid 224
+#define TARGET_NR_readahead 225
#define TARGET_NR_setxattr 226
#define TARGET_NR_lsetxattr 227
#define TARGET_NR_fsetxattr 228
@@ -288,5 +289,40 @@
#define TARGET_NR_add_key 285
#define TARGET_NR_request_key 286
#define TARGET_NR_keyctl 287
-
-#define TARGET_NR_readahead 225 /* XXXXX */
+#define TARGET_NR_ioprio_set 288
+#define TARGET_NR_ioprio_get 289
+#define TARGET_NR_inotify_init 290
+#define TARGET_NR_inotify_add_watch 291
+#define TARGET_NR_inotify_rm_watch 292
+/* 293 is unused */
+#define TARGET_NR_migrate_pages 294
+#define TARGET_NR_openat 295
+#define TARGET_NR_mkdirat 296
+#define TARGET_NR_mknodat 297
+#define TARGET_NR_fchownat 298
+#define TARGET_NR_futimesat 299
+#define TARGET_NR_fstatat64 300
+#define TARGET_NR_unlinkat 301
+#define TARGET_NR_renameat 302
+#define TARGET_NR_linkat 303
+#define TARGET_NR_symlinkat 304
+#define TARGET_NR_readlinkat 305
+#define TARGET_NR_fchmodat 306
+#define TARGET_NR_faccessat 307
+#define TARGET_NR_pselect6 308
+#define TARGET_NR_ppoll 309
+#define TARGET_NR_unshare 310
+#define TARGET_NR_set_robust_list 311
+#define TARGET_NR_get_robust_list 312
+#define TARGET_NR_splice 313
+#define TARGET_NR_sync_file_range 314
+#define TARGET_NR_tee 315
+#define TARGET_NR_vmsplice 316
+#define TARGET_NR_move_pages 317
+#define TARGET_NR_getcpu 318
+#define TARGET_NR_epoll_pwait 319
+#define TARGET_NR_utimensat 320
+#define TARGET_NR_signalfd 321
+#define TARGET_NR_timerfd 322
+#define TARGET_NR_eventfd 323
+#define TARGET_NR_fallocate 324
Added: trunk/src/host/qemu-neo1973/linux-user/sh4/target_signal.h
===================================================================
--- trunk/src/host/qemu-neo1973/linux-user/sh4/target_signal.h 2007-10-29 20:40:05 UTC (rev 3302)
+++ trunk/src/host/qemu-neo1973/linux-user/sh4/target_signal.h 2007-10-29 21:14:04 UTC (rev 3303)
@@ -0,0 +1,24 @@
+#ifndef TARGET_SIGNAL_H
+#define TARGET_SIGNAL_H
+
+#include "cpu.h"
+
+/* this struct defines a stack used during syscall handling */
+
+typedef struct target_sigaltstack {
+ abi_ulong ss_sp;
+ abi_long ss_flags;
+ abi_ulong ss_size;
+} target_stack_t;
+
+
+/*
+ * sigaltstack controls
+ */
+#define TARGET_SS_ONSTACK 1
+#define TARGET_SS_DISABLE 2
+
+#define TARGET_MINSIGSTKSZ 2048
+#define TARGET_SIGSTKSZ 8192
+
+#endif /* TARGET_SIGNAL_H */
Modified: trunk/src/host/qemu-neo1973/linux-user/signal.c
===================================================================
--- trunk/src/host/qemu-neo1973/linux-user/signal.c 2007-10-29 20:40:05 UTC (rev 3302)
+++ trunk/src/host/qemu-neo1973/linux-user/signal.c 2007-10-29 21:14:04 UTC (rev 3303)
@@ -27,6 +27,7 @@
#include <sys/ucontext.h>
#include "qemu.h"
+#include "target_signal.h"
//#define DEBUG_SIGNAL
@@ -45,6 +46,12 @@
first signal, we put it here */
};
+struct target_sigaltstack target_sigaltstack_used = {
+ .ss_sp = 0,
+ .ss_size = 0,
+ .ss_flags = TARGET_SS_DISABLE,
+};
+
static struct emulated_sigaction sigact_table[TARGET_NSIG];
static struct sigqueue sigqueue_table[MAX_SIGQUEUE_SIZE]; /* siginfo queue */
static struct sigqueue *first_free; /* first free siginfo queue entry */
@@ -92,6 +99,18 @@
};
static uint8_t target_to_host_signal_table[65];
+static inline int on_sig_stack(unsigned long sp)
+{
+ return (sp - target_sigaltstack_used.ss_sp
+ < target_sigaltstack_used.ss_size);
+}
+
+static inline int sas_ss_flags(unsigned long sp)
+{
+ return (target_sigaltstack_used.ss_size == 0 ? SS_DISABLE
+ : on_sig_stack(sp) ? SS_ONSTACK : 0);
+}
+
static inline int host_to_target_signal(int sig)
{
return host_to_target_signal_table[sig];
@@ -115,12 +134,12 @@
if (sigmask & (1 << i))
target_sigmask |= 1 << (host_to_target_signal(i + 1) - 1);
}
-#if TARGET_LONG_BITS == 32 && HOST_LONG_BITS == 32
+#if TARGET_ABI_BITS == 32 && HOST_LONG_BITS == 32
d->sig[0] = target_sigmask;
for(i = 1;i < TARGET_NSIG_WORDS; i++) {
d->sig[i] = ((unsigned long *)s)[i];
}
-#elif TARGET_LONG_BITS == 32 && HOST_LONG_BITS == 64 && TARGET_NSIG_WORDS == 2
+#elif TARGET_ABI_BITS == 32 && HOST_LONG_BITS == 64 && TARGET_NSIG_WORDS == 2
d->sig[0] = target_sigmask;
d->sig[1] = sigmask >> 32;
#else
@@ -142,7 +161,7 @@
{
int i;
unsigned long sigmask;
- target_ulong target_sigmask;
+ abi_ulong target_sigmask;
target_sigmask = s->sig[0];
sigmask = 0;
@@ -150,16 +169,16 @@
if (target_sigmask & (1 << i))
sigmask |= 1 << (target_to_host_signal(i + 1) - 1);
}
-#if TARGET_LONG_BITS == 32 && HOST_LONG_BITS == 32
+#if TARGET_ABI_BITS == 32 && HOST_LONG_BITS == 32
((unsigned long *)d)[0] = sigmask;
for(i = 1;i < TARGET_NSIG_WORDS; i++) {
((unsigned long *)d)[i] = s->sig[i];
}
-#elif TARGET_LONG_BITS == 32 && HOST_LONG_BITS == 64 && TARGET_NSIG_WORDS == 2
+#elif TARGET_ABI_BITS == 32 && HOST_LONG_BITS == 64 && TARGET_NSIG_WORDS == 2
((unsigned long *)d)[0] = sigmask | ((unsigned long)(s->sig[1]) << 32);
#else
#warning target_to_host_sigset
-#endif /* TARGET_LONG_BITS */
+#endif /* TARGET_ABI_BITS */
}
void target_to_host_sigset(sigset_t *d, const target_sigset_t *s)
@@ -172,7 +191,7 @@
target_to_host_sigset_internal(d, &s1);
}
-void host_to_target_old_sigset(target_ulong *old_sigset,
+void host_to_target_old_sigset(abi_ulong *old_sigset,
const sigset_t *sigset)
{
target_sigset_t d;
@@ -181,7 +200,7 @@
}
void target_to_host_old_sigset(sigset_t *sigset,
- const target_ulong *old_sigset)
+ const abi_ulong *old_sigset)
{
target_sigset_t d;
int i;
@@ -214,7 +233,7 @@
tinfo->_sifields._rt._uid = info->si_uid;
/* XXX: potential problem if 64 bit */
tinfo->_sifields._rt._sigval.sival_ptr =
- (target_ulong)info->si_value.sival_ptr;
+ (abi_ulong)info->si_value.sival_ptr;
}
}
@@ -336,7 +355,7 @@
{
struct emulated_sigaction *k;
struct sigqueue *q, **pq;
- target_ulong handler;
+ abi_ulong handler;
#if defined(DEBUG_SIGNAL)
fprintf(stderr, "queue_signal: sig=%d\n",
@@ -419,12 +438,76 @@
}
}
+/* do_sigaltstack() returns target values and errnos. */
+int do_sigaltstack(const struct target_sigaltstack *uss,
+ struct target_sigaltstack *uoss,
+ abi_ulong sp)
+{
+ int ret;
+ struct target_sigaltstack oss;
+
+ /* XXX: test errors */
+ if(uoss)
+ {
+ __put_user(target_sigaltstack_used.ss_sp, &oss.ss_sp);
+ __put_user(target_sigaltstack_used.ss_size, &oss.ss_size);
+ __put_user(sas_ss_flags(sp), &oss.ss_flags);
+ }
+
+ if(uss)
+ {
+ struct target_sigaltstack ss;
+
+ ret = -TARGET_EFAULT;
+ if (!access_ok(VERIFY_READ, uss, sizeof(*uss))
+ || __get_user(ss.ss_sp, &uss->ss_sp)
+ || __get_user(ss.ss_size, &uss->ss_size)
+ || __get_user(ss.ss_flags, &uss->ss_flags))
+ goto out;
+
+ ret = -TARGET_EPERM;
+ if (on_sig_stack(sp))
+ goto out;
+
+ ret = -TARGET_EINVAL;
+ if (ss.ss_flags != TARGET_SS_DISABLE
+ && ss.ss_flags != TARGET_SS_ONSTACK
+ && ss.ss_flags != 0)
+ goto out;
+
+ if (ss.ss_flags == TARGET_SS_DISABLE) {
+ ss.ss_size = 0;
+ ss.ss_sp = 0;
+ } else {
+ ret = -TARGET_ENOMEM;
+ if (ss.ss_size < MINSIGSTKSZ)
+ goto out;
+ }
+
+ target_sigaltstack_used.ss_sp = ss.ss_sp;
+ target_sigaltstack_used.ss_size = ss.ss_size;
+ }
+
+ if (uoss) {
+ ret = -TARGET_EFAULT;
+ if (!access_ok(VERIFY_WRITE, uoss, sizeof(oss)))
+ goto out;
+ memcpy(uoss, &oss, sizeof(oss));
+ }
+
+ ret = 0;
+out:
+ return ret;
+}
+
+/* do_sigaction() return host values and errnos */
int do_sigaction(int sig, const struct target_sigaction *act,
struct target_sigaction *oact)
{
struct emulated_sigaction *k;
struct sigaction act1;
int host_sig;
+ int ret = 0;
if (sig < 1 || sig > TARGET_NSIG || sig == SIGKILL || sig == SIGSTOP)
return -EINVAL;
@@ -466,10 +549,10 @@
} else {
act1.sa_sigaction = host_signal_handler;
}
- sigaction(host_sig, &act1, NULL);
+ ret = sigaction(host_sig, &act1, NULL);
}
}
- return 0;
+ return ret;
}
#ifndef offsetof
@@ -499,29 +582,29 @@
};
struct target_xmmreg {
- target_ulong element[4];
+ abi_ulong element[4];
};
struct target_fpstate {
/* Regular FPU environment */
- target_ulong cw;
- target_ulong sw;
- target_ulong tag;
- target_ulong ipoff;
- target_ulong cssel;
- target_ulong dataoff;
- target_ulong datasel;
+ abi_ulong cw;
+ abi_ulong sw;
+ abi_ulong tag;
+ abi_ulong ipoff;
+ abi_ulong cssel;
+ abi_ulong dataoff;
+ abi_ulong datasel;
struct target_fpreg _st[8];
uint16_t status;
uint16_t magic; /* 0xffff = regular FPU data only */
/* FXSR FPU environment */
- target_ulong _fxsr_env[6]; /* FXSR FPU env is ignored */
- target_ulong mxcsr;
- target_ulong reserved;
+ abi_ulong _fxsr_env[6]; /* FXSR FPU env is ignored */
+ abi_ulong mxcsr;
+ abi_ulong reserved;
struct target_fpxreg _fxsr_st[8]; /* FXSR FPU reg data is ignored */
struct target_xmmreg _xmm[8];
- target_ulong padding[56];
+ abi_ulong padding[56];
};
#define X86_FXSR_MAGIC 0x0000
@@ -531,35 +614,29 @@
uint16_t fs, __fsh;
uint16_t es, __esh;
uint16_t ds, __dsh;
- target_ulong edi;
- target_ulong esi;
- target_ulong ebp;
- target_ulong esp;
- target_ulong ebx;
- target_ulong edx;
- target_ulong ecx;
- target_ulong eax;
- target_ulong trapno;
- target_ulong err;
- target_ulong eip;
+ abi_ulong edi;
+ abi_ulong esi;
+ abi_ulong ebp;
+ abi_ulong esp;
+ abi_ulong ebx;
+ abi_ulong edx;
+ abi_ulong ecx;
+ abi_ulong eax;
+ abi_ulong trapno;
+ abi_ulong err;
+ abi_ulong eip;
uint16_t cs, __csh;
- target_ulong eflags;
- target_ulong esp_at_signal;
+ abi_ulong eflags;
+ abi_ulong esp_at_signal;
uint16_t ss, __ssh;
- target_ulong fpstate; /* pointer */
- target_ulong oldmask;
- target_ulong cr2;
+ abi_ulong fpstate; /* pointer */
+ abi_ulong oldmask;
+ abi_ulong cr2;
};
-typedef struct target_sigaltstack {
- target_ulong ss_sp;
- int ss_flags;
- target_ulong ss_size;
-} target_stack_t;
-
struct target_ucontext {
- target_ulong tuc_flags;
- target_ulong tuc_link;
+ abi_ulong tuc_flags;
+ abi_ulong tuc_link;
target_stack_t tuc_stack;
struct target_sigcontext tuc_mcontext;
target_sigset_t tuc_sigmask; /* mask last for extensibility */
@@ -567,20 +644,20 @@
struct sigframe
{
- target_ulong pretcode;
+ abi_ulong pretcode;
int sig;
struct target_sigcontext sc;
struct target_fpstate fpstate;
- target_ulong extramask[TARGET_NSIG_WORDS-1];
+ abi_ulong extramask[TARGET_NSIG_WORDS-1];
char retcode[8];
};
struct rt_sigframe
{
- target_ulong pretcode;
+ abi_ulong pretcode;
int sig;
- target_ulong pinfo;
- target_ulong puc;
+ abi_ulong pinfo;
+ abi_ulong puc;
struct target_siginfo info;
struct target_ucontext uc;
struct target_fpstate fpstate;
@@ -640,16 +717,14 @@
/* Default to using normal stack */
esp = env->regs[R_ESP];
-#if 0
/* This is the X/Open sanctioned signal stack switching. */
- if (ka->sa.sa_flags & SA_ONSTACK) {
- if (sas_ss_flags(esp) == 0)
- esp = current->sas_ss_sp + current->sas_ss_size;
- }
+ if (ka->sa.sa_flags & TARGET_SA_ONSTACK) {
+ if (sas_ss_flags(esp) == 0)
+ esp = target_sigaltstack_used.ss_sp + target_sigaltstack_used.ss_size;
+ }
/* This is the legacy signal stack switching. */
else
-#endif
if ((env->segs[R_SS].selector & 0xffff) != __USER_DS &&
!(ka->sa.sa_flags & TARGET_SA_RESTORER) &&
ka->sa.sa_restorer) {
@@ -741,8 +816,8 @@
? current->exec_domain->signal_invmap[sig]
: */sig),
&frame->sig);
- err |= __put_user((target_ulong)&frame->info, &frame->pinfo);
- err |= __put_user((target_ulong)&frame->uc, &frame->puc);
+ err |= __put_user((abi_ulong)&frame->info, &frame->pinfo);
+ err |= __put_user((abi_ulong)&frame->uc, &frame->puc);
err |= copy_siginfo_to_user(&frame->info, info);
if (err)
goto give_sigsegv;
@@ -750,11 +825,11 @@
/* Create the ucontext. */
err |= __put_user(0, &frame->uc.tuc_flags);
err |= __put_user(0, &frame->uc.tuc_link);
- err |= __put_user(/*current->sas_ss_sp*/ 0,
+ err |= __put_user(target_sigaltstack_used.ss_sp,
&frame->uc.tuc_stack.ss_sp);
- err |= __put_user(/* sas_ss_flags(regs->esp) */ 0,
+ err |= __put_user(sas_ss_flags(get_sp_from_cpustate(env)),
&frame->uc.tuc_stack.ss_flags);
- err |= __put_user(/* current->sas_ss_size */ 0,
+ err |= __put_user(target_sigaltstack_used.ss_size,
&frame->uc.tuc_stack.ss_size);
err |= setup_sigcontext(&frame->uc.tuc_mcontext, &frame->fpstate,
env, set->sig[0]);
@@ -880,7 +955,6 @@
{
struct rt_sigframe *frame = (struct rt_sigframe *)g2h(env->regs[R_ESP] - 4);
sigset_t set;
- // stack_t st;
int eax;
#if 0
@@ -893,13 +967,9 @@
if (restore_sigcontext(env, &frame->uc.tuc_mcontext, &eax))
goto badframe;
-#if 0
- if (__copy_from_user(&st, &frame->uc.tuc_stack, sizeof(st)))
+ if (do_sigaltstack(&frame->uc.tuc_stack, NULL, get_sp_from_cpustate(env)) == -EFAULT)
goto badframe;
- /* It is more difficult to avoid calling this function than to
- call it and ignore errors. */
- do_sigaltstack(&st, NULL, regs->esp);
-#endif
+
return eax;
badframe:
@@ -910,38 +980,32 @@
#elif defined(TARGET_ARM)
struct target_sigcontext {
- target_ulong trap_no;
- target_ulong error_code;
- target_ulong oldmask;
- target_ulong arm_r0;
- target_ulong arm_r1;
- target_ulong arm_r2;
- target_ulong arm_r3;
- target_ulong arm_r4;
- target_ulong arm_r5;
- target_ulong arm_r6;
- target_ulong arm_r7;
- target_ulong arm_r8;
- target_ulong arm_r9;
- target_ulong arm_r10;
- target_ulong arm_fp;
- target_ulong arm_ip;
- target_ulong arm_sp;
- target_ulong arm_lr;
- target_ulong arm_pc;
- target_ulong arm_cpsr;
- target_ulong fault_address;
+ abi_ulong trap_no;
+ abi_ulong error_code;
+ abi_ulong oldmask;
+ abi_ulong arm_r0;
+ abi_ulong arm_r1;
+ abi_ulong arm_r2;
+ abi_ulong arm_r3;
+ abi_ulong arm_r4;
+ abi_ulong arm_r5;
+ abi_ulong arm_r6;
+ abi_ulong arm_r7;
+ abi_ulong arm_r8;
+ abi_ulong arm_r9;
+ abi_ulong arm_r10;
+ abi_ulong arm_fp;
+ abi_ulong arm_ip;
+ abi_ulong arm_sp;
+ abi_ulong arm_lr;
+ abi_ulong arm_pc;
+ abi_ulong arm_cpsr;
+ abi_ulong fault_address;
};
-typedef struct target_sigaltstack {
- target_ulong ss_sp;
- int ss_flags;
- target_ulong ss_size;
-} target_stack_t;
-
struct target_ucontext {
- target_ulong tuc_flags;
- target_ulong tuc_link;
+ abi_ulong tuc_flags;
+ abi_ulong tuc_link;
target_stack_t tuc_stack;
struct target_sigcontext tuc_mcontext;
target_sigset_t tuc_sigmask; /* mask last for extensibility */
@@ -950,8 +1014,8 @@
struct sigframe
{
struct target_sigcontext sc;
- target_ulong extramask[TARGET_NSIG_WORDS-1];
- target_ulong retcode;
+ abi_ulong extramask[TARGET_NSIG_WORDS-1];
+ abi_ulong retcode;
};
struct rt_sigframe
@@ -960,7 +1024,7 @@
void *puc;
struct target_siginfo info;
struct target_ucontext uc;
- target_ulong retcode;
+ abi_ulong retcode;
};
#define TARGET_CONFIG_CPU_32 1
@@ -978,7 +1042,7 @@
#define SWI_THUMB_SIGRETURN (0xdf00 << 16 | 0x2700 | (TARGET_NR_sigreturn))
#define SWI_THUMB_RT_SIGRETURN (0xdf00 << 16 | 0x2700 | (TARGET_NR_rt_sigreturn))
-static const target_ulong retcodes[4] = {
+static const abi_ulong retcodes[4] = {
SWI_SYS_SIGRETURN, SWI_THUMB_SIGRETURN,
SWI_SYS_RT_SIGRETURN, SWI_THUMB_RT_SIGRETURN
};
@@ -1031,13 +1095,11 @@
{
unsigned long sp = regs->regs[13];
-#if 0
/*
* This is the X/Open sanctioned signal stack switching.
*/
- if ((ka->sa.sa_flags & SA_ONSTACK) && !sas_ss_flags(sp))
- sp = current->sas_ss_sp + current->sas_ss_size;
-#endif
+ if ((ka->sa.sa_flags & TARGET_SA_ONSTACK) && !sas_ss_flags(sp))
+ sp = target_sigaltstack_used.ss_sp + target_sigaltstack_used.ss_size;
/*
* ATPCS B01 mandates 8-byte alignment
*/
@@ -1046,14 +1108,14 @@
static int
setup_return(CPUState *env, struct emulated_sigaction *ka,
- target_ulong *rc, void *frame, int usig)
+ abi_ulong *rc, void *frame, int usig)
{
- target_ulong handler = (target_ulong)ka->sa._sa_handler;
- target_ulong retcode;
+ abi_ulong handler = (abi_ulong)ka->sa._sa_handler;
+ abi_ulong retcode;
int thumb = 0;
#if defined(TARGET_CONFIG_CPU_32)
#if 0
- target_ulong cpsr = env->cpsr;
+ abi_ulong cpsr = env->cpsr;
/*
* Maybe we need to deliver a 32-bit signal to a 26-bit task.
@@ -1074,12 +1136,12 @@
else
cpsr &= ~T_BIT;
}
-#endif
-#endif
+#endif /* CONFIG_ARM_THUMB */
+#endif /* 0 */
#endif /* TARGET_CONFIG_CPU_32 */
if (ka->sa.sa_flags & TARGET_SA_RESTORER) {
- retcode = (target_ulong)ka->sa.sa_restorer;
+ retcode = (abi_ulong)ka->sa.sa_restorer;
} else {
unsigned int idx = thumb;
@@ -1089,10 +1151,10 @@
if (__put_user(retcodes[idx], rc))
return 1;
#if 0
- flush_icache_range((target_ulong)rc,
- (target_ulong)(rc + 1));
+ flush_icache_range((abi_ulong)rc,
+ (abi_ulong)(rc + 1));
#endif
- retcode = ((target_ulong)rc) + thumb;
+ retcode = ((abi_ulong)rc) + thumb;
}
env->regs[0] = usig;
@@ -1132,18 +1194,28 @@
target_sigset_t *set, CPUState *env)
{
struct rt_sigframe *frame = get_sigframe(ka, env, sizeof(*frame));
+ struct target_sigaltstack stack;
int i, err = 0;
if (!access_ok(VERIFY_WRITE, frame, sizeof (*frame)))
return /* 1 */;
- __put_user_error(&frame->info, (target_ulong *)&frame->pinfo, err);
- __put_user_error(&frame->uc, (target_ulong *)&frame->puc, err);
+ __put_user_error(&frame->info, (abi_ulong *)&frame->pinfo, err);
+ __put_user_error(&frame->uc, (abi_ulong *)&frame->puc, err);
err |= copy_siginfo_to_user(&frame->info, info);
/* Clear all the bits of the ucontext we don't use. */
memset(&frame->uc, 0, offsetof(struct target_ucontext, tuc_mcontext));
+ memset(&stack, 0, sizeof(stack));
+ __put_user(target_sigaltstack_used.ss_sp, &stack.ss_sp);
+ __put_user(target_sigaltstack_used.ss_size, &stack.ss_size);
+ __put_user(sas_ss_flags(get_sp_from_cpustate(env)), &stack.ss_flags);
+ if (!access_ok(VERIFY_WRITE, &frame->uc.tuc_stack, sizeof(stack)))
+ err = 1;
+ else
+ memcpy(&frame->uc.tuc_stack, &stack, sizeof(stack));
+
err |= setup_sigcontext(&frame->uc.tuc_mcontext, /*&frame->fpstate,*/
env, set->sig[0]);
for(i = 0; i < TARGET_NSIG_WORDS; i++) {
@@ -1160,8 +1232,8 @@
* arguments for the signal handler.
* -- Peter Maydell <pmaydell at chiark.greenend.org.uk> 2000-12-06
*/
- env->regs[1] = (target_ulong)frame->pinfo;
- env->regs[2] = (target_ulong)frame->puc;
+ env->regs[1] = (abi_ulong)frame->pinfo;
+ env->regs[2] = (abi_ulong)frame->puc;
}
// return err;
@@ -1270,6 +1342,9 @@
if (restore_sigcontext(env, &frame->uc.tuc_mcontext))
goto badframe;
+ if (do_sigaltstack(&frame->uc.tuc_stack, NULL, get_sp_from_cpustate(env)) == -EFAULT)
+ goto badframe;
+
#if 0
/* Send SIGTRAP if we're single-stepping */
if (ptrace_cancel_bpt(current))
@@ -1288,48 +1363,48 @@
/* This is what SunOS does, so shall I. */
struct target_sigcontext {
- target_ulong sigc_onstack; /* state to restore */
+ abi_ulong sigc_onstack; /* state to restore */
- target_ulong sigc_mask; /* sigmask to restore */
- target_ulong sigc_sp; /* stack pointer */
- target_ulong sigc_pc; /* program counter */
- target_ulong sigc_npc; /* next program counter */
- target_ulong sigc_psr; /* for condition codes etc */
- target_ulong sigc_g1; /* User uses these two registers */
- target_ulong sigc_o0; /* within the trampoline code. */
+ abi_ulong sigc_mask; /* sigmask to restore */
+ abi_ulong sigc_sp; /* stack pointer */
+ abi_ulong sigc_pc; /* program counter */
+ abi_ulong sigc_npc; /* next program counter */
+ abi_ulong sigc_psr; /* for condition codes etc */
+ abi_ulong sigc_g1; /* User uses these two registers */
+ abi_ulong sigc_o0; /* within the trampoline code. */
/* Now comes information regarding the users window set
* at the time of the signal.
*/
- target_ulong sigc_oswins; /* outstanding windows */
+ abi_ulong sigc_oswins; /* outstanding windows */
/* stack ptrs for each regwin buf */
char *sigc_spbuf[__SUNOS_MAXWIN];
/* Windows to restore after signal */
struct {
- target_ulong locals[8];
- target_ulong ins[8];
+ abi_ulong locals[8];
+ abi_ulong ins[8];
} sigc_wbuf[__SUNOS_MAXWIN];
};
/* A Sparc stack frame */
struct sparc_stackf {
- target_ulong locals[8];
- target_ulong ins[6];
+ abi_ulong locals[8];
+ abi_ulong ins[6];
struct sparc_stackf *fp;
- target_ulong callers_pc;
+ abi_ulong callers_pc;
char *structptr;
- target_ulong xargs[6];
- target_ulong xxargs[1];
+ abi_ulong xargs[6];
+ abi_ulong xxargs[1];
};
typedef struct {
struct {
- target_ulong psr;
- target_ulong pc;
- target_ulong npc;
- target_ulong y;
- target_ulong u_regs[16]; /* globals and ins */
+ abi_ulong psr;
+ abi_ulong pc;
+ abi_ulong npc;
+ abi_ulong y;
+ abi_ulong u_regs[16]; /* globals and ins */
} si_regs;
int si_mask;
} __siginfo_t;
@@ -1349,15 +1424,15 @@
struct sparc_stackf ss;
__siginfo_t info;
qemu_siginfo_fpu_t *fpu_save;
- target_ulong insns[2] __attribute__ ((aligned (8)));
- target_ulong extramask[TARGET_NSIG_WORDS - 1];
- target_ulong extra_size; /* Should be 0 */
+ abi_ulong insns[2] __attribute__ ((aligned (8)));
+ abi_ulong extramask[TARGET_NSIG_WORDS - 1];
+ abi_ulong extra_size; /* Should be 0 */
qemu_siginfo_fpu_t fpu_state;
};
struct target_rt_signal_frame {
struct sparc_stackf ss;
siginfo_t info;
- target_ulong regs[20];
+ abi_ulong regs[20];
sigset_t mask;
qemu_siginfo_fpu_t *fpu_save;
unsigned int insns[2];
@@ -1371,6 +1446,9 @@
#define UREG_I0 0
#define UREG_I1 1
#define UREG_I2 2
+#define UREG_I3 3
+#define UREG_I4 4
+#define UREG_I5 5
#define UREG_I6 6
#define UREG_I7 7
#define UREG_L0 8
@@ -1382,19 +1460,18 @@
unsigned long sp;
sp = env->regwptr[UREG_FP];
-#if 0
/* This is the X/Open sanctioned signal stack switching. */
- if (sa->sa_flags & TARGET_SA_ONSTACK) {
- if (!on_sig_stack(sp) && !((current->sas_ss_sp + current->sas_ss_size) & 7))
- sp = current->sas_ss_sp + current->sas_ss_size;
+ if (sa->sa.sa_flags & TARGET_SA_ONSTACK) {
+ if (!on_sig_stack(sp)
+ && !((target_sigaltstack_used.ss_sp + target_sigaltstack_used.ss_size) & 7))
+ sp = target_sigaltstack_used.ss_sp + target_sigaltstack_used.ss_size;
}
-#endif
return g2h(sp - framesize);
}
static int
-setup___siginfo(__siginfo_t *si, CPUState *env, target_ulong mask)
+setup___siginfo(__siginfo_t *si, CPUState *env, abi_ulong mask)
{
int err = 0, i;
@@ -1560,7 +1637,7 @@
uint32_t up_psr, pc, npc;
target_sigset_t set;
sigset_t host_set;
- target_ulong fpu_save;
+ abi_ulong fpu_save;
int err, i;
sf = (struct target_signal_frame *)g2h(env->regwptr[UREG_FP]);
@@ -1602,7 +1679,7 @@
err |= __get_user(env->regwptr[i + UREG_I0], &sf->info.si_regs.u_regs[i+8]);
}
- err |= __get_user(fpu_save, (target_ulong *)&sf->fpu_save);
+ err |= __get_user(fpu_save, (abi_ulong *)&sf->fpu_save);
//if (fpu_save)
// err |= restore_fpu_state(env, fpu_save);
@@ -1633,6 +1710,297 @@
return -ENOSYS;
}
+#ifdef TARGET_SPARC64
+#define MC_TSTATE 0
+#define MC_PC 1
+#define MC_NPC 2
+#define MC_Y 3
+#define MC_G1 4
+#define MC_G2 5
+#define MC_G3 6
+#define MC_G4 7
+#define MC_G5 8
+#define MC_G6 9
+#define MC_G7 10
+#define MC_O0 11
+#define MC_O1 12
+#define MC_O2 13
+#define MC_O3 14
+#define MC_O4 15
+#define MC_O5 16
+#define MC_O6 17
+#define MC_O7 18
+#define MC_NGREG 19
+
+typedef abi_ulong target_mc_greg_t;
+typedef target_mc_greg_t target_mc_gregset_t[MC_NGREG];
+
+struct target_mc_fq {
+ abi_ulong *mcfq_addr;
+ uint32_t mcfq_insn;
+};
+
+struct target_mc_fpu {
+ union {
+ uint32_t sregs[32];
+ uint64_t dregs[32];
+ //uint128_t qregs[16];
+ } mcfpu_fregs;
+ abi_ulong mcfpu_fsr;
+ abi_ulong mcfpu_fprs;
+ abi_ulong mcfpu_gsr;
+ struct target_mc_fq *mcfpu_fq;
+ unsigned char mcfpu_qcnt;
+ unsigned char mcfpu_qentsz;
+ unsigned char mcfpu_enab;
+};
+typedef struct target_mc_fpu target_mc_fpu_t;
+
+typedef struct {
+ target_mc_gregset_t mc_gregs;
+ target_mc_greg_t mc_fp;
+ target_mc_greg_t mc_i7;
+ target_mc_fpu_t mc_fpregs;
+} target_mcontext_t;
+
+struct target_ucontext {
+ struct target_ucontext *uc_link;
+ abi_ulong uc_flags;
+ target_sigset_t uc_sigmask;
+ target_mcontext_t uc_mcontext;
+};
+
+/* A V9 register window */
+struct target_reg_window {
+ abi_ulong locals[8];
+ abi_ulong ins[8];
+};
+
+#define TARGET_STACK_BIAS 2047
+
+/* {set, get}context() needed for 64-bit SparcLinux userland. */
+void sparc64_set_context(CPUSPARCState *env)
+{
+ struct target_ucontext *ucp = (struct target_ucontext *)
+ env->regwptr[UREG_I0];
+ target_mc_gregset_t *grp;
+ abi_ulong pc, npc, tstate;
+ abi_ulong fp, i7;
+ unsigned char fenab;
+ int err;
+ unsigned int i;
+ abi_ulong *src, *dst;
+
+ grp = &ucp->uc_mcontext.mc_gregs;
+ err = get_user(pc, &((*grp)[MC_PC]));
+ err |= get_user(npc, &((*grp)[MC_NPC]));
+ if (err || ((pc | npc) & 3))
+ goto do_sigsegv;
+ if (env->regwptr[UREG_I1]) {
+ target_sigset_t target_set;
+ sigset_t set;
+
+ if (TARGET_NSIG_WORDS == 1) {
+ if (get_user(target_set.sig[0], &ucp->uc_sigmask.sig[0]))
+ goto do_sigsegv;
+ } else {
+ src = &ucp->uc_sigmask;
+ dst = &target_set;
+ for (i = 0; i < sizeof(target_sigset_t) / sizeof(abi_ulong);
+ i++, dst++, src++)
+ err |= get_user(dst, src);
+ if (err)
+ goto do_sigsegv;
+ }
+ target_to_host_sigset_internal(&set, &target_set);
+ sigprocmask(SIG_SETMASK, &set, NULL);
+ }
+ env->pc = pc;
+ env->npc = npc;
+ err |= get_user(env->y, &((*grp)[MC_Y]));
+ err |= get_user(tstate, &((*grp)[MC_TSTATE]));
+ env->asi = (tstate >> 24) & 0xff;
+ PUT_CCR(env, tstate >> 32);
+ PUT_CWP64(env, tstate & 0x1f);
+ err |= get_user(env->gregs[1], (&(*grp)[MC_G1]));
+ err |= get_user(env->gregs[2], (&(*grp)[MC_G2]));
+ err |= get_user(env->gregs[3], (&(*grp)[MC_G3]));
+ err |= get_user(env->gregs[4], (&(*grp)[MC_G4]));
+ err |= get_user(env->gregs[5], (&(*grp)[MC_G5]));
+ err |= get_user(env->gregs[6], (&(*grp)[MC_G6]));
+ err |= get_user(env->gregs[7], (&(*grp)[MC_G7]));
+ err |= get_user(env->regwptr[UREG_I0], (&(*grp)[MC_O0]));
+ err |= get_user(env->regwptr[UREG_I1], (&(*grp)[MC_O1]));
+ err |= get_user(env->regwptr[UREG_I2], (&(*grp)[MC_O2]));
+ err |= get_user(env->regwptr[UREG_I3], (&(*grp)[MC_O3]));
+ err |= get_user(env->regwptr[UREG_I4], (&(*grp)[MC_O4]));
+ err |= get_user(env->regwptr[UREG_I5], (&(*grp)[MC_O5]));
+ err |= get_user(env->regwptr[UREG_I6], (&(*grp)[MC_O6]));
+ err |= get_user(env->regwptr[UREG_I7], (&(*grp)[MC_O7]));
+
+ err |= get_user(fp, &(ucp->uc_mcontext.mc_fp));
+ err |= get_user(i7, &(ucp->uc_mcontext.mc_i7));
+ err |= put_user(fp,
+ (&(((struct target_reg_window *)(TARGET_STACK_BIAS+env->regwptr[UREG_I6]))->ins[6])));
+ err |= put_user(i7,
+ (&(((struct target_reg_window *)(TARGET_STACK_BIAS+env->regwptr[UREG_I6]))->ins[7])));
+
+ err |= get_user(fenab, &(ucp->uc_mcontext.mc_fpregs.mcfpu_enab));
+ err |= get_user(env->fprs, &(ucp->uc_mcontext.mc_fpregs.mcfpu_fprs));
+ src = &(ucp->uc_mcontext.mc_fpregs.mcfpu_fregs);
+ dst = &env->fpr;
+ for (i = 0; i < 64; i++, dst++, src++)
+ err |= get_user(dst, src);
+ err |= get_user(env->fsr,
+ &(ucp->uc_mcontext.mc_fpregs.mcfpu_fsr));
+ err |= get_user(env->gsr,
+ &(ucp->uc_mcontext.mc_fpregs.mcfpu_gsr));
+ if (err)
+ goto do_sigsegv;
+
+ return;
+ do_sigsegv:
+ force_sig(SIGSEGV);
+}
+
+void sparc64_get_context(CPUSPARCState *env)
+{
+ struct target_ucontext *ucp = (struct target_ucontext *)
+ env->regwptr[UREG_I0];
+ target_mc_gregset_t *grp;
+ target_mcontext_t *mcp;
+ abi_ulong fp, i7;
+ int err;
+ unsigned int i;
+ abi_ulong *src, *dst;
+ target_sigset_t target_set;
+ sigset_t set;
+
+ mcp = &ucp->uc_mcontext;
+ grp = &mcp->mc_gregs;
+
+ /* Skip over the trap instruction, first. */
+ env->pc = env->npc;
+ env->npc += 4;
+
+ err = 0;
+
+ sigprocmask(0, NULL, &set);
+ host_to_target_sigset_internal(&target_set, &set);
+ if (TARGET_NSIG_WORDS == 1)
+ err |= put_user(target_set.sig[0],
+ (abi_ulong *)&ucp->uc_sigmask);
+ else {
+ src = &target_set;
+ dst = &ucp->uc_sigmask;
+ for (i = 0; i < sizeof(target_sigset_t) / sizeof(abi_ulong);
+ i++, dst++, src++)
+ err |= put_user(src, dst);
+ if (err)
+ goto do_sigsegv;
+ }
+
+ err |= put_user(env->tstate, &((*grp)[MC_TSTATE]));
+ err |= put_user(env->pc, &((*grp)[MC_PC]));
+ err |= put_user(env->npc, &((*grp)[MC_NPC]));
+ err |= put_user(env->y, &((*grp)[MC_Y]));
+ err |= put_user(env->gregs[1], &((*grp)[MC_G1]));
+ err |= put_user(env->gregs[2], &((*grp)[MC_G2]));
+ err |= put_user(env->gregs[3], &((*grp)[MC_G3]));
+ err |= put_user(env->gregs[4], &((*grp)[MC_G4]));
+ err |= put_user(env->gregs[5], &((*grp)[MC_G5]));
+ err |= put_user(env->gregs[6], &((*grp)[MC_G6]));
+ err |= put_user(env->gregs[7], &((*grp)[MC_G7]));
+ err |= put_user(env->regwptr[UREG_I0], &((*grp)[MC_O0]));
+ err |= put_user(env->regwptr[UREG_I1], &((*grp)[MC_O1]));
+ err |= put_user(env->regwptr[UREG_I2], &((*grp)[MC_O2]));
+ err |= put_user(env->regwptr[UREG_I3], &((*grp)[MC_O3]));
+ err |= put_user(env->regwptr[UREG_I4], &((*grp)[MC_O4]));
+ err |= put_user(env->regwptr[UREG_I5], &((*grp)[MC_O5]));
+ err |= put_user(env->regwptr[UREG_I6], &((*grp)[MC_O6]));
+ err |= put_user(env->regwptr[UREG_I7], &((*grp)[MC_O7]));
+
+ err |= get_user(fp,
+ (&(((struct target_reg_window *)(TARGET_STACK_BIAS+env->regwptr[UREG_I6]))->ins[6])));
+ err |= get_user(i7,
+ (&(((struct target_reg_window *)(TARGET_STACK_BIAS+env->regwptr[UREG_I6]))->ins[7])));
+ err |= put_user(fp, &(mcp->mc_fp));
+ err |= put_user(i7, &(mcp->mc_i7));
+
+ src = &env->fpr;
+ dst = &(ucp->uc_mcontext.mc_fpregs.mcfpu_fregs);
+ for (i = 0; i < 64; i++, dst++, src++)
+ err |= put_user(src, dst);
+ err |= put_user(env->fsr, &(mcp->mc_fpregs.mcfpu_fsr));
+ err |= put_user(env->gsr, &(mcp->mc_fpregs.mcfpu_gsr));
+ err |= put_user(env->fprs, &(mcp->mc_fpregs.mcfpu_fprs));
+
+ if (err)
+ goto do_sigsegv;
+
+ return;
+ do_sigsegv:
+ force_sig(SIGSEGV);
+}
+#endif
+#elif defined(TARGET_MIPS64)
+
+# warning signal handling not implemented
+
+static void setup_frame(int sig, struct emulated_sigaction *ka,
+ target_sigset_t *set, CPUState *env)
+{
+ fprintf(stderr, "setup_frame: not implemented\n");
+}
+
+static void setup_rt_frame(int sig, struct emulated_sigaction *ka,
+ target_siginfo_t *info,
+ target_sigset_t *set, CPUState *env)
+{
+ fprintf(stderr, "setup_rt_frame: not implemented\n");
+}
+
+long do_sigreturn(CPUState *env)
+{
+ fprintf(stderr, "do_sigreturn: not implemented\n");
+ return -ENOSYS;
+}
+
+long do_rt_sigreturn(CPUState *env)
+{
+ fprintf(stderr, "do_rt_sigreturn: not implemented\n");
+ return -ENOSYS;
+}
+
+#elif defined(TARGET_MIPSN32)
+
+# warning signal handling not implemented
+
+static void setup_frame(int sig, struct emulated_sigaction *ka,
+ target_sigset_t *set, CPUState *env)
+{
+ fprintf(stderr, "setup_frame: not implemented\n");
+}
+
+static void setup_rt_frame(int sig, struct emulated_sigaction *ka,
+ target_siginfo_t *info,
+ target_sigset_t *set, CPUState *env)
+{
+ fprintf(stderr, "setup_rt_frame: not implemented\n");
+}
+
+long do_sigreturn(CPUState *env)
+{
+ fprintf(stderr, "do_sigreturn: not implemented\n");
+ return -ENOSYS;
+}
+
+long do_rt_sigreturn(CPUState *env)
+{
+ fprintf(stderr, "do_rt_sigreturn: not implemented\n");
+ return -ENOSYS;
+}
+
#elif defined(TARGET_MIPS)
struct target_sigcontext {
@@ -1842,11 +2210,10 @@
*/
sp -= 32;
-#if 0
/* This is the X/Open sanctioned signal stack switching. */
- if ((ka->sa.sa_flags & SA_ONSTACK) && (sas_ss_flags (sp) == 0))
- sp = current->sas_ss_sp + current->sas_ss_size;
-#endif
+ if ((ka->sa.sa_flags & TARGET_SA_ONSTACK) && (sas_ss_flags (sp) == 0)) {
+ sp = target_sigaltstack_used.ss_sp + target_sigaltstack_used.ss_size;
+ }
return g2h((sp - frame_size) & ~7);
}
@@ -1990,7 +2357,7 @@
void process_pending_signals(void *cpu_env)
{
int sig;
- target_ulong handler;
+ abi_ulong handler;
sigset_t set, old_set;
target_sigset_t target_old_set;
struct emulated_sigaction *k;
Modified: trunk/src/host/qemu-neo1973/linux-user/sparc/syscall.h
===================================================================
--- trunk/src/host/qemu-neo1973/linux-user/sparc/syscall.h 2007-10-29 20:40:05 UTC (rev 3302)
+++ trunk/src/host/qemu-neo1973/linux-user/sparc/syscall.h 2007-10-29 21:14:04 UTC (rev 3303)
@@ -1,9 +1,9 @@
struct target_pt_regs {
- target_ulong psr;
- target_ulong pc;
- target_ulong npc;
- target_ulong y;
- target_ulong u_regs[16];
+ abi_ulong psr;
+ abi_ulong pc;
+ abi_ulong npc;
+ abi_ulong y;
+ abi_ulong u_regs[16];
};
#define UNAME_MACHINE "sun4"
Modified: trunk/src/host/qemu-neo1973/linux-user/sparc/syscall_nr.h
===================================================================
--- trunk/src/host/qemu-neo1973/linux-user/sparc/syscall_nr.h 2007-10-29 20:40:05 UTC (rev 3302)
+++ trunk/src/host/qemu-neo1973/linux-user/sparc/syscall_nr.h 2007-10-29 21:14:04 UTC (rev 3303)
@@ -217,4 +217,62 @@
#define TARGET_NR_fdatasync 253
#define TARGET_NR_nfsservctl 254
#define TARGET_NR_aplib 255
-#define TARGET_NR__exit TARGET_NR_exit
+#define TARGET_NR_clock_settime 256
+#define TARGET_NR_clock_gettime 257
+#define TARGET_NR_clock_getres 258
+#define TARGET_NR_clock_nanosleep 259
+#define TARGET_NR_sched_getaffinity 260
+#define TARGET_NR_sched_setaffinity 261
+#define TARGET_NR_timer_settime 262
+#define TARGET_NR_timer_gettime 263
+#define TARGET_NR_timer_getoverrun 264
+#define TARGET_NR_timer_delete 265
+#define TARGET_NR_timer_create 266
+/* #define TARGET_NR_vserver 267 Reserved for VSERVER */
+#define TARGET_NR_io_setup 268
+#define TARGET_NR_io_destroy 269
+#define TARGET_NR_io_submit 270
+#define TARGET_NR_io_cancel 271
+#define TARGET_NR_io_getevents 272
+#define TARGET_NR_mq_open 273
+#define TARGET_NR_mq_unlink 274
+#define TARGET_NR_mq_timedsend 275
+#define TARGET_NR_mq_timedreceive 276
+#define TARGET_NR_mq_notify 277
+#define TARGET_NR_mq_getsetattr 278
+#define TARGET_NR_waitid 279
+#define TARGET_NR_tee 280
+#define TARGET_NR_add_key 281
+#define TARGET_NR_request_key 282
+#define TARGET_NR_keyctl 283
+#define TARGET_NR_openat 284
+#define TARGET_NR_mkdirat 285
+#define TARGET_NR_mknodat 286
+#define TARGET_NR_fchownat 287
+#define TARGET_NR_futimesat 288
+#define TARGET_NR_fstatat64 289
+#define TARGET_NR_unlinkat 290
+#define TARGET_NR_renameat 291
+#define TARGET_NR_linkat 292
+#define TARGET_NR_symlinkat 293
+#define TARGET_NR_readlinkat 294
+#define TARGET_NR_fchmodat 295
+#define TARGET_NR_faccessat 296
+#define TARGET_NR_pselect6 297
+#define TARGET_NR_ppoll 298
+#define TARGET_NR_unshare 299
+#define TARGET_NR_set_robust_list 300
+#define TARGET_NR_get_robust_list 301
+#define TARGET_NR_migrate_pages 302
+#define TARGET_NR_mbind 303
+#define TARGET_NR_get_mempolicy 304
+#define TARGET_NR_set_mempolicy 305
+#define TARGET_NR_kexec_load 306
+#define TARGET_NR_move_pages 307
+#define TARGET_NR_getcpu 308
+#define TARGET_NR_epoll_pwait 309
+#define TARGET_NR_utimensat 310
+#define TARGET_NR_signalfd 311
+#define TARGET_NR_timerfd 312
+#define TARGET_NR_eventfd 313
+#define TARGET_NR_fallocate 314
Added: trunk/src/host/qemu-neo1973/linux-user/sparc/target_signal.h
===================================================================
--- trunk/src/host/qemu-neo1973/linux-user/sparc/target_signal.h 2007-10-29 20:40:05 UTC (rev 3302)
+++ trunk/src/host/qemu-neo1973/linux-user/sparc/target_signal.h 2007-10-29 21:14:04 UTC (rev 3303)
@@ -0,0 +1,36 @@
+#ifndef TARGET_SIGNAL_H
+#define TARGET_SIGNAL_H
+
+#include "cpu.h"
+
+/* this struct defines a stack used during syscall handling */
+
+typedef struct target_sigaltstack {
+ abi_ulong ss_sp;
+ abi_long ss_flags;
+ abi_ulong ss_size;
+} target_stack_t;
+
+
+/*
+ * sigaltstack controls
+ */
+#define TARGET_SS_ONSTACK 1
+#define TARGET_SS_DISABLE 2
+
+#define TARGET_MINSIGSTKSZ 4096
+#define TARGET_SIGSTKSZ 16384
+
+#ifndef UREG_I6
+#define UREG_I6 6
+#endif
+#ifndef UREG_FP
+#define UREG_FP UREG_I6
+#endif
+
+static inline abi_ulong get_sp_from_cpustate(CPUSPARCState *state)
+{
+ return state->regwptr[UREG_FP];
+}
+
+#endif /* TARGET_SIGNAL_H */
Modified: trunk/src/host/qemu-neo1973/linux-user/sparc/termbits.h
===================================================================
--- trunk/src/host/qemu-neo1973/linux-user/sparc/termbits.h 2007-10-29 20:40:05 UTC (rev 3302)
+++ trunk/src/host/qemu-neo1973/linux-user/sparc/termbits.h 2007-10-29 21:14:04 UTC (rev 3303)
@@ -51,6 +51,7 @@
#define TARGET_IXANY 0x00000800
#define TARGET_IXOFF 0x00001000
#define TARGET_IMAXBEL 0x00002000
+#define TARGET_IUTF8 0x00004000
/* c_oflag bits */
#define TARGET_OPOST 0x00000001
Modified: trunk/src/host/qemu-neo1973/linux-user/sparc64/syscall.h
===================================================================
--- trunk/src/host/qemu-neo1973/linux-user/sparc64/syscall.h 2007-10-29 20:40:05 UTC (rev 3302)
+++ trunk/src/host/qemu-neo1973/linux-user/sparc64/syscall.h 2007-10-29 21:14:04 UTC (rev 3303)
@@ -1,10 +1,10 @@
struct target_pt_regs {
- target_ulong u_regs[16];
- target_ulong tstate;
- target_ulong pc;
- target_ulong npc;
- target_ulong y;
- target_ulong fprs;
+ abi_ulong u_regs[16];
+ abi_ulong tstate;
+ abi_ulong pc;
+ abi_ulong npc;
+ abi_ulong y;
+ abi_ulong fprs;
};
#define UNAME_MACHINE "sun4u"
Modified: trunk/src/host/qemu-neo1973/linux-user/sparc64/syscall_nr.h
===================================================================
--- trunk/src/host/qemu-neo1973/linux-user/sparc64/syscall_nr.h 2007-10-29 20:40:05 UTC (rev 3302)
+++ trunk/src/host/qemu-neo1973/linux-user/sparc64/syscall_nr.h 2007-10-29 21:14:04 UTC (rev 3303)
@@ -29,11 +29,11 @@
#define TARGET_NR_sigaltstack 28 /* Common */
#define TARGET_NR_pause 29 /* Is sigblock(0)->sigpause() in SunOS */
#define TARGET_NR_utime 30 /* Implemented via utimes() under SunOS */
-/* #define TARGET_NR_lchown32 31 Linux sparc32 specific */
-/* #define TARGET_NR_fchown32 32 Linux sparc32 specific */
+#define TARGET_NR_lchown32 31 /* Linux sparc32 specific */
+#define TARGET_NR_fchown32 32 /* Linux sparc32 specific */
#define TARGET_NR_access 33 /* Common */
#define TARGET_NR_nice 34 /* Implemented via get/setpriority() in SunOS */
-/* #define TARGET_NR_chown32 35 Linux sparc32 specific */
+#define TARGET_NR_chown32 35 /* Linux sparc32 specific */
#define TARGET_NR_sync 36 /* Common */
#define TARGET_NR_kill 37 /* Common */
#define TARGET_NR_stat 38 /* Common */
@@ -42,7 +42,7 @@
#define TARGET_NR_dup 41 /* Common */
#define TARGET_NR_pipe 42 /* Common */
#define TARGET_NR_times 43 /* Implemented via getrusage() in SunOS */
-/* #define TARGET_NR_getuid32 44 Linux sparc32 specific */
+#define TARGET_NR_getuid32 44 /* Linux sparc32 specific */
#define TARGET_NR_umount2 45 /* Linux Specific */
#define TARGET_NR_setgid 46 /* Implemented via setregid() in SunOS */
#define TARGET_NR_getgid 47 /* Common */
@@ -51,48 +51,48 @@
#define TARGET_NR_getegid 50 /* SunOS calls getgid() */
#define TARGET_NR_acct 51 /* Common */
#define TARGET_NR_memory_ordering 52 /* Linux Specific */
-/* #define TARGET_NR_getgid32 53 Linux sparc32 specific */
+#define TARGET_NR_getgid32 53 /* Linux sparc32 specific */
#define TARGET_NR_ioctl 54 /* Common */
#define TARGET_NR_reboot 55 /* Common */
-/* #define TARGET_NR_mmap2 56 Linux sparc32 Specific */
+#define TARGET_NR_mmap2 56 /* Linux sparc32 Specific */
#define TARGET_NR_symlink 57 /* Common */
#define TARGET_NR_readlink 58 /* Common */
#define TARGET_NR_execve 59 /* Common */
#define TARGET_NR_umask 60 /* Common */
#define TARGET_NR_chroot 61 /* Common */
#define TARGET_NR_fstat 62 /* Common */
-/* #define TARGET_NR_fstat64 63 Linux sparc32 Specific */
+#define TARGET_NR_fstat64 63 /* Linux sparc32 Specific */
#define TARGET_NR_getpagesize 64 /* Common */
#define TARGET_NR_msync 65 /* Common in newer 1.3.x revs... */
#define TARGET_NR_vfork 66 /* Common */
#define TARGET_NR_pread64 67 /* Linux Specific */
#define TARGET_NR_pwrite64 68 /* Linux Specific */
-/* #define TARGET_NR_geteuid32 69 Linux sparc32, sbrk under SunOS */
-/* #define TARGET_NR_getegid32 70 Linux sparc32, sstk under SunOS */
+#define TARGET_NR_geteuid32 69 /* Linux sparc32, sbrk under SunOS */
+#define TARGET_NR_getegid32 70 /* Linux sparc32, sstk under SunOS */
#define TARGET_NR_mmap 71 /* Common */
-/* #define TARGET_NR_setreuid32 72 Linux sparc32, vadvise under SunOS */
+#define TARGET_NR_setreuid32 72 /* Linux sparc32, vadvise under SunOS */
#define TARGET_NR_munmap 73 /* Common */
#define TARGET_NR_mprotect 74 /* Common */
#define TARGET_NR_madvise 75 /* Common */
#define TARGET_NR_vhangup 76 /* Common */
-/* #define TARGET_NR_truncate64 77 Linux sparc32 Specific */
+#define TARGET_NR_truncate64 77 /* Linux sparc32 Specific */
#define TARGET_NR_mincore 78 /* Common */
#define TARGET_NR_getgroups 79 /* Common */
#define TARGET_NR_setgroups 80 /* Common */
#define TARGET_NR_getpgrp 81 /* Common */
-/* #define TARGET_NR_setgroups32 82 Linux sparc32, setpgrp under SunOS */
+#define TARGET_NR_setgroups32 82 /* Linux sparc32, setpgrp under SunOS */
#define TARGET_NR_setitimer 83 /* Common */
-/* #define TARGET_NR_ftruncate64 84 Linux sparc32 Specific */
+#define TARGET_NR_ftruncate64 84 /* Linux sparc32 Specific */
#define TARGET_NR_swapon 85 /* Common */
#define TARGET_NR_getitimer 86 /* Common */
-/* #define TARGET_NR_setuid32 87 Linux sparc32, gethostname under SunOS */
+#define TARGET_NR_setuid32 87 /* Linux sparc32, gethostname under SunOS */
#define TARGET_NR_sethostname 88 /* Common */
-/* #define TARGET_NR_setgid32 89 Linux sparc32, getdtablesize under SunOS */
+#define TARGET_NR_setgid32 89 /* Linux sparc32, getdtablesize under SunOS */
#define TARGET_NR_dup2 90 /* Common */
-/* #define TARGET_NR_setfsuid32 91 Linux sparc32, getdopt under SunOS */
+#define TARGET_NR_setfsuid32 91 /* Linux sparc32, getdopt under SunOS */
#define TARGET_NR_fcntl 92 /* Common */
#define TARGET_NR_select 93 /* Common */
-/* #define TARGET_NR_setfsgid32 94 Linux sparc32, setdopt under SunOS */
+#define TARGET_NR_setfsgid32 94 /* Linux sparc32, setdopt under SunOS */
#define TARGET_NR_fsync 95 /* Common */
#define TARGET_NR_setpriority 96 /* Common */
#define TARGET_NR_socket 97 /* Common */
@@ -110,10 +110,10 @@
#define TARGET_NR_getresuid 109 /* Linux Specific, sigblock under SunOS */
#define TARGET_NR_setresgid 110 /* Linux Specific, sigsetmask under SunOS */
#define TARGET_NR_getresgid 111 /* Linux Specific, sigpause under SunOS */
-/* #define TARGET_NR_setregid32 75 Linux sparc32, sigstack under SunOS */
+/* #define TARGET_NR_setregid32 75 Linux sparc32, sigstack under SunOS */
#define TARGET_NR_recvmsg 113 /* Common */
#define TARGET_NR_sendmsg 114 /* Common */
-/* #define TARGET_NR_getgroups32 115 Linux sparc32, vtrace under SunOS */
+#define TARGET_NR_getgroups32 115 /* Linux sparc32, vtrace under SunOS */
#define TARGET_NR_gettimeofday 116 /* Common */
#define TARGET_NR_getrusage 117 /* Common */
#define TARGET_NR_getsockopt 118 /* Common */
@@ -130,14 +130,14 @@
#define TARGET_NR_truncate 129 /* Common */
#define TARGET_NR_ftruncate 130 /* Common */
#define TARGET_NR_flock 131 /* Common */
-/* #define TARGET_NR_lstat64 132 Linux sparc32 Specific */
+#define TARGET_NR_lstat64 132 /* Linux sparc32 Specific */
#define TARGET_NR_sendto 133 /* Common */
#define TARGET_NR_shutdown 134 /* Common */
#define TARGET_NR_socketpair 135 /* Common */
#define TARGET_NR_mkdir 136 /* Common */
#define TARGET_NR_rmdir 137 /* Common */
#define TARGET_NR_utimes 138 /* SunOS Specific */
-/* #define TARGET_NR_stat64 139 Linux sparc32 Specific */
+#define TARGET_NR_stat64 139 /* Linux sparc32 Specific */
#define TARGET_NR_sendfile64 140 /* adjtime under SunOS */
#define TARGET_NR_getpeername 141 /* Common */
#define TARGET_NR_futex 142 /* gethostid under SunOS */
@@ -153,7 +153,7 @@
/* #define TARGET_NR_putmsg 152 SunOS Specific */
#define TARGET_NR_poll 153 /* Common */
#define TARGET_NR_getdents64 154 /* Linux specific */
-/* #define TARGET_NR_fcntl64 155 Linux sparc32 Specific */
+#define TARGET_NR_fcntl64 155 /* Linux sparc32 Specific */
/* #define TARGET_NR_getdirentries 156 SunOS Specific */
#define TARGET_NR_statfs 157 /* Common */
#define TARGET_NR_fstatfs 158 /* Common */
@@ -229,9 +229,7 @@
#define TARGET_NR_setfsuid 228 /* Linux Specific */
#define TARGET_NR_setfsgid 229 /* Linux Specific */
#define TARGET_NR__newselect 230 /* Linux Specific */
-#ifdef __KERNEL__
-#define TARGET_NR_time 231 /* Linux sparc32 */
-#endif
+#define TARGET_NR_time 231 /* Linux sparc32 */
/* #define TARGET_NR_oldstat 232 Linux Specific */
#define TARGET_NR_stime 233 /* Linux Specific */
#define TARGET_NR_statfs64 234 /* Linux Specific */
@@ -284,3 +282,34 @@
#define TARGET_NR_add_key 281
#define TARGET_NR_request_key 282
#define TARGET_NR_keyctl 283
+#define TARGET_NR_openat 284
+#define TARGET_NR_mkdirat 285
+#define TARGET_NR_mknodat 286
+#define TARGET_NR_fchownat 287
+#define TARGET_NR_futimesat 288
+#define TARGET_NR_fstatat64 289
+#define TARGET_NR_unlinkat 290
+#define TARGET_NR_renameat 291
+#define TARGET_NR_linkat 292
+#define TARGET_NR_symlinkat 293
+#define TARGET_NR_readlinkat 294
+#define TARGET_NR_fchmodat 295
+#define TARGET_NR_faccessat 296
+#define TARGET_NR_pselect6 297
+#define TARGET_NR_ppoll 298
+#define TARGET_NR_unshare 299
+#define TARGET_NR_set_robust_list 300
+#define TARGET_NR_get_robust_list 301
+#define TARGET_NR_migrate_pages 302
+#define TARGET_NR_mbind 303
+#define TARGET_NR_get_mempolicy 304
+#define TARGET_NR_set_mempolicy 305
+#define TARGET_NR_kexec_load 306
+#define TARGET_NR_move_pages 307
+#define TARGET_NR_getcpu 308
+#define TARGET_NR_epoll_pwait 309
+#define TARGET_NR_utimensat 310
+#define TARGET_NR_signalfd 311
+#define TARGET_NR_timerfd 312
+#define TARGET_NR_eventfd 313
+#define TARGET_NR_fallocate 314
Added: trunk/src/host/qemu-neo1973/linux-user/sparc64/target_signal.h
===================================================================
--- trunk/src/host/qemu-neo1973/linux-user/sparc64/target_signal.h 2007-10-29 20:40:05 UTC (rev 3302)
+++ trunk/src/host/qemu-neo1973/linux-user/sparc64/target_signal.h 2007-10-29 21:14:04 UTC (rev 3303)
@@ -0,0 +1,36 @@
+#ifndef TARGET_SIGNAL_H
+#define TARGET_SIGNAL_H
+
+#include "cpu.h"
+
+/* this struct defines a stack used during syscall handling */
+
+typedef struct target_sigaltstack {
+ abi_ulong ss_sp;
+ abi_long ss_flags;
+ abi_ulong ss_size;
+} target_stack_t;
+
+
+/*
+ * sigaltstack controls
+ */
+#define TARGET_SS_ONSTACK 1
+#define TARGET_SS_DISABLE 2
+
+#define TARGET_MINSIGSTKSZ 4096
+#define TARGET_SIGSTKSZ 16384
+
+#ifndef UREG_I6
+#define UREG_I6 6
+#endif
+#ifndef UREG_FP
+#define UREG_FP UREG_I6
+#endif
+
+static inline abi_ulong get_sp_from_cpustate(CPUSPARCState *state)
+{
+ return state->regwptr[UREG_FP];
+}
+
+#endif /* TARGET_SIGNAL_H */
Modified: trunk/src/host/qemu-neo1973/linux-user/sparc64/termbits.h
===================================================================
--- trunk/src/host/qemu-neo1973/linux-user/sparc64/termbits.h 2007-10-29 20:40:05 UTC (rev 3302)
+++ trunk/src/host/qemu-neo1973/linux-user/sparc64/termbits.h 2007-10-29 21:14:04 UTC (rev 3303)
@@ -51,6 +51,7 @@
#define TARGET_IXANY 0x00000800
#define TARGET_IXOFF 0x00001000
#define TARGET_IMAXBEL 0x00002000
+#define TARGET_IUTF8 0x00004000
/* c_oflag bits */
#define TARGET_OPOST 0x00000001
Modified: trunk/src/host/qemu-neo1973/linux-user/syscall.c
===================================================================
--- trunk/src/host/qemu-neo1973/linux-user/syscall.c 2007-10-29 20:40:05 UTC (rev 3302)
+++ trunk/src/host/qemu-neo1973/linux-user/syscall.c 2007-10-29 21:14:04 UTC (rev 3303)
@@ -74,7 +74,7 @@
//#define DEBUG
#if defined(TARGET_I386) || defined(TARGET_ARM) || defined(TARGET_SPARC) \
- || defined(TARGET_M68K) || defined(TARGET_SH4)
+ || defined(TARGET_M68K) || defined(TARGET_SH4) || defined(TARGET_CRIS)
/* 16 bit uid wrappers emulation */
#define USE_UID16
#endif
@@ -139,13 +139,26 @@
#define __NR_sys_uname __NR_uname
+#define __NR_sys_faccessat __NR_faccessat
+#define __NR_sys_fchmodat __NR_fchmodat
+#define __NR_sys_fchownat __NR_fchownat
#define __NR_sys_getcwd1 __NR_getcwd
#define __NR_sys_getdents __NR_getdents
#define __NR_sys_getdents64 __NR_getdents64
+#define __NR_sys_getpriority __NR_getpriority
+#define __NR_sys_linkat __NR_linkat
+#define __NR_sys_mkdirat __NR_mkdirat
+#define __NR_sys_mknodat __NR_mknodat
+#define __NR_sys_openat __NR_openat
+#define __NR_sys_readlinkat __NR_readlinkat
+#define __NR_sys_renameat __NR_renameat
#define __NR_sys_rt_sigqueueinfo __NR_rt_sigqueueinfo
+#define __NR_sys_symlinkat __NR_symlinkat
#define __NR_sys_syslog __NR_syslog
#define __NR_sys_tgkill __NR_tgkill
#define __NR_sys_tkill __NR_tkill
+#define __NR_sys_unlinkat __NR_unlinkat
+#define __NR_sys_utimensat __NR_utimensat
#if defined(__alpha__) || defined (__ia64__) || defined(__x86_64__)
#define __NR__llseek __NR_lseek
@@ -154,19 +167,59 @@
#ifdef __NR_gettid
_syscall0(int, gettid)
#else
+/* This is a replacement for the host gettid() and must return a host
+ errno. */
static int gettid(void) {
return -ENOSYS;
}
#endif
_syscall1(int,sys_uname,struct new_utsname *,buf)
+#if defined(TARGET_NR_faccessat) && defined(__NR_faccessat)
+_syscall4(int,sys_faccessat,int,dirfd,const char *,pathname,int,mode,int,flags)
+#endif
+#if defined(TARGET_NR_fchmodat) && defined(__NR_fchmodat)
+_syscall4(int,sys_fchmodat,int,dirfd,const char *,pathname,
+ mode_t,mode,int,flags)
+#endif
+#if defined(TARGET_NR_fchownat) && defined(__NR_fchownat)
+_syscall5(int,sys_fchownat,int,dirfd,const char *,pathname,
+ uid_t,owner,gid_t,group,int,flags)
+#endif
_syscall2(int,sys_getcwd1,char *,buf,size_t,size)
_syscall3(int, sys_getdents, uint, fd, struct dirent *, dirp, uint, count);
#if defined(TARGET_NR_getdents64) && defined(__NR_getdents64)
_syscall3(int, sys_getdents64, uint, fd, struct dirent64 *, dirp, uint, count);
#endif
+_syscall2(int, sys_getpriority, int, which, int, who);
_syscall5(int, _llseek, uint, fd, ulong, hi, ulong, lo,
loff_t *, res, uint, wh);
+#if defined(TARGET_NR_linkat) && defined(__NR_linkat)
+_syscall5(int,sys_linkat,int,olddirfd,const char *,oldpath,
+ int,newdirfd,const char *,newpath,int,flags)
+#endif
+#if defined(TARGET_NR_mkdirat) && defined(__NR_mkdirat)
+_syscall3(int,sys_mkdirat,int,dirfd,const char *,pathname,mode_t,mode)
+#endif
+#if defined(TARGET_NR_mknodat) && defined(__NR_mknodat)
+_syscall4(int,sys_mknodat,int,dirfd,const char *,pathname,
+ mode_t,mode,dev_t,dev)
+#endif
+#if defined(TARGET_NR_openat) && defined(__NR_openat)
+_syscall4(int,sys_openat,int,dirfd,const char *,pathname,int,flags,mode_t,mode)
+#endif
+#if defined(TARGET_NR_readlinkat) && defined(__NR_readlinkat)
+_syscall4(int,sys_readlinkat,int,dirfd,const char *,pathname,
+ char *,buf,size_t,bufsize)
+#endif
+#if defined(TARGET_NR_renameat) && defined(__NR_renameat)
+_syscall4(int,sys_renameat,int,olddirfd,const char *,oldpath,
+ int,newdirfd,const char *,newpath)
+#endif
_syscall3(int,sys_rt_sigqueueinfo,int,pid,int,sig,siginfo_t *,uinfo)
+#if defined(TARGET_NR_symlinkat) && defined(__NR_symlinkat)
+_syscall3(int,sys_symlinkat,const char *,oldpath,
+ int,newdirfd,const char *,newpath)
+#endif
_syscall3(int,sys_syslog,int,type,char*,bufp,int,len)
#if defined(TARGET_NR_tgkill) && defined(__NR_tgkill)
_syscall3(int,sys_tgkill,int,tgid,int,pid,int,sig)
@@ -180,6 +233,13 @@
#if defined(TARGET_NR_set_tid_address) && defined(__NR_set_tid_address)
_syscall1(int,set_tid_address,int *,tidptr)
#endif
+#if defined(TARGET_NR_unlinkat) && defined(__NR_unlinkat)
+_syscall3(int,sys_unlinkat,int,dirfd,const char *,pathname,int,flags)
+#endif
+#if defined(TARGET_NR_utimensat) && defined(__NR_utimensat)
+_syscall4(int,sys_utimensat,int,dirfd,const char *,pathname,
+ const struct timespec *,tsp,int,flags)
+#endif
extern int personality(int);
extern int flock(int, int);
@@ -310,7 +370,7 @@
return err;
}
-static inline long get_errno(long ret)
+static inline abi_long get_errno(abi_long ret)
{
if (ret == -1)
return -host_to_target_errno(errno);
@@ -318,29 +378,30 @@
return ret;
}
-static inline int is_error(long ret)
+static inline int is_error(abi_long ret)
{
- return (unsigned long)ret >= (unsigned long)(-4096);
+ return (abi_ulong)ret >= (abi_ulong)(-4096);
}
-static target_ulong target_brk;
-static target_ulong target_original_brk;
+static abi_ulong target_brk;
+static abi_ulong target_original_brk;
-void target_set_brk(target_ulong new_brk)
+void target_set_brk(abi_ulong new_brk)
{
target_original_brk = target_brk = HOST_PAGE_ALIGN(new_brk);
}
-long do_brk(target_ulong new_brk)
+/* do_brk() must return target values and target errnos. */
+abi_long do_brk(abi_ulong new_brk)
{
- target_ulong brk_page;
- long mapped_addr;
+ abi_ulong brk_page;
+ abi_long mapped_addr;
int new_alloc_size;
if (!new_brk)
return target_brk;
if (new_brk < target_original_brk)
- return -ENOMEM;
+ return -TARGET_ENOMEM;
brk_page = HOST_PAGE_ALIGN(target_brk);
@@ -364,7 +425,7 @@
}
static inline fd_set *target_to_host_fds(fd_set *fds,
- target_long *target_fds, int n)
+ abi_long *target_fds, int n)
{
#if !defined(BSWAP_NEEDED) && !defined(WORDS_BIGENDIAN)
return (fd_set *)target_fds;
@@ -373,8 +434,8 @@
if (target_fds) {
FD_ZERO(fds);
for(i = 0;i < n; i++) {
- b = (tswapl(target_fds[i / TARGET_LONG_BITS]) >>
- (i & (TARGET_LONG_BITS - 1))) & 1;
+ b = (tswapl(target_fds[i / TARGET_ABI_BITS]) >>
+ (i & (TARGET_ABI_BITS - 1))) & 1;
if (b)
FD_SET(i, fds);
}
@@ -385,21 +446,21 @@
#endif
}
-static inline void host_to_target_fds(target_long *target_fds,
+static inline void host_to_target_fds(abi_long *target_fds,
fd_set *fds, int n)
{
#if !defined(BSWAP_NEEDED) && !defined(WORDS_BIGENDIAN)
/* nothing to do */
#else
int i, nw, j, k;
- target_long v;
+ abi_long v;
if (target_fds) {
- nw = (n + TARGET_LONG_BITS - 1) / TARGET_LONG_BITS;
+ nw = (n + TARGET_ABI_BITS - 1) / TARGET_ABI_BITS;
k = 0;
for(i = 0;i < nw; i++) {
v = 0;
- for(j = 0; j < TARGET_LONG_BITS; j++) {
+ for(j = 0; j < TARGET_ABI_BITS; j++) {
v |= ((FD_ISSET(k, fds) != 0) << j);
k++;
}
@@ -415,7 +476,7 @@
#define HOST_HZ 100
#endif
-static inline long host_to_target_clock_t(long ticks)
+static inline abi_long host_to_target_clock_t(long ticks)
{
#if HOST_HZ == TARGET_HZ
return ticks;
@@ -424,7 +485,7 @@
#endif
}
-static inline void host_to_target_rusage(target_ulong target_addr,
+static inline void host_to_target_rusage(abi_ulong target_addr,
const struct rusage *rusage)
{
struct target_rusage *target_rusage;
@@ -452,7 +513,7 @@
}
static inline void target_to_host_timeval(struct timeval *tv,
- target_ulong target_addr)
+ abi_ulong target_addr)
{
struct target_timeval *target_tv;
@@ -462,7 +523,7 @@
unlock_user_struct(target_tv, target_addr, 0);
}
-static inline void host_to_target_timeval(target_ulong target_addr,
+static inline void host_to_target_timeval(abi_ulong target_addr,
const struct timeval *tv)
{
struct target_timeval *target_tv;
@@ -474,33 +535,34 @@
}
-static long do_select(long n,
- target_ulong rfd_p, target_ulong wfd_p,
- target_ulong efd_p, target_ulong target_tv)
+/* do_select() must return target values and target errnos. */
+static abi_long do_select(int n,
+ abi_ulong rfd_p, abi_ulong wfd_p,
+ abi_ulong efd_p, abi_ulong target_tv)
{
fd_set rfds, wfds, efds;
fd_set *rfds_ptr, *wfds_ptr, *efds_ptr;
- target_long *target_rfds, *target_wfds, *target_efds;
+ abi_long *target_rfds, *target_wfds, *target_efds;
struct timeval tv, *tv_ptr;
- long ret;
+ abi_long ret;
int ok;
if (rfd_p) {
- target_rfds = lock_user(rfd_p, sizeof(target_long) * n, 1);
+ target_rfds = lock_user(rfd_p, sizeof(abi_long) * n, 1);
rfds_ptr = target_to_host_fds(&rfds, target_rfds, n);
} else {
target_rfds = NULL;
rfds_ptr = NULL;
}
if (wfd_p) {
- target_wfds = lock_user(wfd_p, sizeof(target_long) * n, 1);
+ target_wfds = lock_user(wfd_p, sizeof(abi_long) * n, 1);
wfds_ptr = target_to_host_fds(&wfds, target_wfds, n);
} else {
target_wfds = NULL;
wfds_ptr = NULL;
}
if (efd_p) {
- target_efds = lock_user(efd_p, sizeof(target_long) * n, 1);
+ target_efds = lock_user(efd_p, sizeof(abi_long) * n, 1);
efds_ptr = target_to_host_fds(&efds, target_efds, n);
} else {
target_efds = NULL;
@@ -526,17 +588,17 @@
}
}
if (target_rfds)
- unlock_user(target_rfds, rfd_p, ok ? sizeof(target_long) * n : 0);
+ unlock_user(target_rfds, rfd_p, ok ? sizeof(abi_long) * n : 0);
if (target_wfds)
- unlock_user(target_wfds, wfd_p, ok ? sizeof(target_long) * n : 0);
+ unlock_user(target_wfds, wfd_p, ok ? sizeof(abi_long) * n : 0);
if (target_efds)
- unlock_user(target_efds, efd_p, ok ? sizeof(target_long) * n : 0);
+ unlock_user(target_efds, efd_p, ok ? sizeof(abi_long) * n : 0);
return ret;
}
static inline void target_to_host_sockaddr(struct sockaddr *addr,
- target_ulong target_addr,
+ abi_ulong target_addr,
socklen_t len)
{
struct target_sockaddr *target_saddr;
@@ -547,7 +609,7 @@
unlock_user(target_saddr, target_addr, 0);
}
-static inline void host_to_target_sockaddr(target_ulong target_addr,
+static inline void host_to_target_sockaddr(abi_ulong target_addr,
struct sockaddr *addr,
socklen_t len)
{
@@ -648,16 +710,18 @@
msgh->msg_controllen = tswapl(space);
}
-static long do_setsockopt(int sockfd, int level, int optname,
- target_ulong optval, socklen_t optlen)
+/* do_setsockopt() Must return target values and target errnos. */
+static abi_long do_setsockopt(int sockfd, int level, int optname,
+ abi_ulong optval, socklen_t optlen)
{
- int val, ret;
+ abi_long ret;
+ int val;
switch(level) {
case SOL_TCP:
/* TCP options all take an 'int' value. */
if (optlen < sizeof(uint32_t))
- return -EINVAL;
+ return -TARGET_EINVAL;
val = tget32(optval);
ret = get_errno(setsockopt(sockfd, level, optname, &val, sizeof(val)));
@@ -755,7 +819,7 @@
goto unimplemented;
}
if (optlen < sizeof(uint32_t))
- return -EINVAL;
+ return -TARGET_EINVAL;
val = tget32(optval);
ret = get_errno(setsockopt(sockfd, SOL_SOCKET, optname, &val, sizeof(val)));
@@ -763,15 +827,17 @@
default:
unimplemented:
gemu_log("Unsupported setsockopt level=%d optname=%d \n", level, optname);
- ret = -ENOSYS;
+ ret = -TARGET_ENOSYS;
}
return ret;
}
-static long do_getsockopt(int sockfd, int level, int optname,
- target_ulong optval, target_ulong optlen)
+/* do_getsockopt() Must return target values and target errnos. */
+static abi_long do_getsockopt(int sockfd, int level, int optname,
+ abi_ulong optval, abi_ulong optlen)
{
- int len, lv, val, ret;
+ abi_long ret;
+ int len, lv, val;
switch(level) {
case TARGET_SOL_SOCKET:
@@ -793,7 +859,7 @@
int_case:
len = tget32(optlen);
if (len < 0)
- return -EINVAL;
+ return -TARGET_EINVAL;
lv = sizeof(int);
ret = get_errno(getsockopt(sockfd, level, optname, &val, &lv));
if (ret < 0)
@@ -826,7 +892,7 @@
case IP_MULTICAST_LOOP:
len = tget32(optlen);
if (len < 0)
- return -EINVAL;
+ return -TARGET_EINVAL;
lv = sizeof(int);
ret = get_errno(getsockopt(sockfd, level, optname, &val, &lv));
if (ret < 0)
@@ -850,17 +916,17 @@
unimplemented:
gemu_log("getsockopt level=%d optname=%d not yet supported\n",
level, optname);
- ret = -ENOSYS;
+ ret = -TARGET_ENOSYS;
break;
}
return ret;
}
-static void lock_iovec(struct iovec *vec, target_ulong target_addr,
+static void lock_iovec(struct iovec *vec, abi_ulong target_addr,
int count, int copy)
{
struct target_iovec *target_vec;
- target_ulong base;
+ abi_ulong base;
int i;
target_vec = lock_user(target_addr, count * sizeof(struct target_iovec), 1);
@@ -872,11 +938,11 @@
unlock_user (target_vec, target_addr, 0);
}
-static void unlock_iovec(struct iovec *vec, target_ulong target_addr,
+static void unlock_iovec(struct iovec *vec, abi_ulong target_addr,
int count, int copy)
{
struct target_iovec *target_vec;
- target_ulong base;
+ abi_ulong base;
int i;
target_vec = lock_user(target_addr, count * sizeof(struct target_iovec), 1);
@@ -887,7 +953,8 @@
unlock_user (target_vec, target_addr, 0);
}
-static long do_socket(int domain, int type, int protocol)
+/* do_socket() Must return target values and target errnos. */
+static abi_long do_socket(int domain, int type, int protocol)
{
#if defined(TARGET_MIPS)
switch(type) {
@@ -914,8 +981,9 @@
return get_errno(socket(domain, type, protocol));
}
-static long do_bind(int sockfd, target_ulong target_addr,
- socklen_t addrlen)
+/* do_bind() Must return target values and target errnos. */
+static abi_long do_bind(int sockfd, abi_ulong target_addr,
+ socklen_t addrlen)
{
void *addr = alloca(addrlen);
@@ -923,8 +991,9 @@
return get_errno(bind(sockfd, addr, addrlen));
}
-static long do_connect(int sockfd, target_ulong target_addr,
- socklen_t addrlen)
+/* do_connect() Must return target values and target errnos. */
+static abi_long do_connect(int sockfd, abi_ulong target_addr,
+ socklen_t addrlen)
{
void *addr = alloca(addrlen);
@@ -932,15 +1001,16 @@
return get_errno(connect(sockfd, addr, addrlen));
}
-static long do_sendrecvmsg(int fd, target_ulong target_msg,
- int flags, int send)
+/* do_sendrecvmsg() Must return target values and target errnos. */
+static abi_long do_sendrecvmsg(int fd, abi_ulong target_msg,
+ int flags, int send)
{
- long ret;
+ abi_long ret;
struct target_msghdr *msgp;
struct msghdr msg;
int count;
struct iovec *vec;
- target_ulong target_vec;
+ abi_ulong target_vec;
lock_user_struct(msgp, target_msg, 1);
if (msgp->msg_name) {
@@ -975,12 +1045,13 @@
return ret;
}
-static long do_accept(int fd, target_ulong target_addr,
- target_ulong target_addrlen)
+/* do_accept() Must return target values and target errnos. */
+static abi_long do_accept(int fd, abi_ulong target_addr,
+ abi_ulong target_addrlen)
{
socklen_t addrlen = tget32(target_addrlen);
void *addr = alloca(addrlen);
- long ret;
+ abi_long ret;
ret = get_errno(accept(fd, addr, &addrlen));
if (!is_error(ret)) {
@@ -990,12 +1061,13 @@
return ret;
}
-static long do_getpeername(int fd, target_ulong target_addr,
- target_ulong target_addrlen)
+/* do_getpeername() Must return target values and target errnos. */
+static abi_long do_getpeername(int fd, abi_ulong target_addr,
+ abi_ulong target_addrlen)
{
socklen_t addrlen = tget32(target_addrlen);
void *addr = alloca(addrlen);
- long ret;
+ abi_long ret;
ret = get_errno(getpeername(fd, addr, &addrlen));
if (!is_error(ret)) {
@@ -1005,12 +1077,13 @@
return ret;
}
-static long do_getsockname(int fd, target_ulong target_addr,
- target_ulong target_addrlen)
+/* do_getsockname() Must return target values and target errnos. */
+static abi_long do_getsockname(int fd, abi_ulong target_addr,
+ abi_ulong target_addrlen)
{
socklen_t addrlen = tget32(target_addrlen);
void *addr = alloca(addrlen);
- long ret;
+ abi_long ret;
ret = get_errno(getsockname(fd, addr, &addrlen));
if (!is_error(ret)) {
@@ -1020,11 +1093,12 @@
return ret;
}
-static long do_socketpair(int domain, int type, int protocol,
- target_ulong target_tab)
+/* do_socketpair() Must return target values and target errnos. */
+static abi_long do_socketpair(int domain, int type, int protocol,
+ abi_ulong target_tab)
{
int tab[2];
- long ret;
+ abi_long ret;
ret = get_errno(socketpair(domain, type, protocol, tab));
if (!is_error(ret)) {
@@ -1034,12 +1108,13 @@
return ret;
}
-static long do_sendto(int fd, target_ulong msg, size_t len, int flags,
- target_ulong target_addr, socklen_t addrlen)
+/* do_sendto() Must return target values and target errnos. */
+static abi_long do_sendto(int fd, abi_ulong msg, size_t len, int flags,
+ abi_ulong target_addr, socklen_t addrlen)
{
void *addr;
void *host_msg;
- long ret;
+ abi_long ret;
host_msg = lock_user(msg, len, 1);
if (target_addr) {
@@ -1053,13 +1128,15 @@
return ret;
}
-static long do_recvfrom(int fd, target_ulong msg, size_t len, int flags,
- target_ulong target_addr, target_ulong target_addrlen)
+/* do_recvfrom() Must return target values and target errnos. */
+static abi_long do_recvfrom(int fd, abi_ulong msg, size_t len, int flags,
+ abi_ulong target_addr,
+ abi_ulong target_addrlen)
{
socklen_t addrlen;
void *addr;
void *host_msg;
- long ret;
+ abi_long ret;
host_msg = lock_user(msg, len, 0);
if (target_addr) {
@@ -1082,10 +1159,12 @@
return ret;
}
-static long do_socketcall(int num, target_ulong vptr)
+#ifdef TARGET_NR_socketcall
+/* do_socketcall() Must return target values and target errnos. */
+static abi_long do_socketcall(int num, abi_ulong vptr)
{
- long ret;
- const int n = sizeof(target_ulong);
+ abi_long ret;
+ const int n = sizeof(abi_ulong);
switch(num) {
case SOCKOP_socket:
@@ -1099,7 +1178,7 @@
case SOCKOP_bind:
{
int sockfd = tgetl(vptr);
- target_ulong target_addr = tgetl(vptr + n);
+ abi_ulong target_addr = tgetl(vptr + n);
socklen_t addrlen = tgetl(vptr + 2 * n);
ret = do_bind(sockfd, target_addr, addrlen);
}
@@ -1107,7 +1186,7 @@
case SOCKOP_connect:
{
int sockfd = tgetl(vptr);
- target_ulong target_addr = tgetl(vptr + n);
+ abi_ulong target_addr = tgetl(vptr + n);
socklen_t addrlen = tgetl(vptr + 2 * n);
ret = do_connect(sockfd, target_addr, addrlen);
}
@@ -1122,24 +1201,24 @@
case SOCKOP_accept:
{
int sockfd = tgetl(vptr);
- target_ulong target_addr = tgetl(vptr + n);
- target_ulong target_addrlen = tgetl(vptr + 2 * n);
+ abi_ulong target_addr = tgetl(vptr + n);
+ abi_ulong target_addrlen = tgetl(vptr + 2 * n);
ret = do_accept(sockfd, target_addr, target_addrlen);
}
break;
case SOCKOP_getsockname:
{
int sockfd = tgetl(vptr);
- target_ulong target_addr = tgetl(vptr + n);
- target_ulong target_addrlen = tgetl(vptr + 2 * n);
+ abi_ulong target_addr = tgetl(vptr + n);
+ abi_ulong target_addrlen = tgetl(vptr + 2 * n);
ret = do_getsockname(sockfd, target_addr, target_addrlen);
}
break;
case SOCKOP_getpeername:
{
int sockfd = tgetl(vptr);
- target_ulong target_addr = tgetl(vptr + n);
- target_ulong target_addrlen = tgetl(vptr + 2 * n);
+ abi_ulong target_addr = tgetl(vptr + n);
+ abi_ulong target_addrlen = tgetl(vptr + 2 * n);
ret = do_getpeername(sockfd, target_addr, target_addrlen);
}
break;
@@ -1148,14 +1227,14 @@
int domain = tgetl(vptr);
int type = tgetl(vptr + n);
int protocol = tgetl(vptr + 2 * n);
- target_ulong tab = tgetl(vptr + 3 * n);
+ abi_ulong tab = tgetl(vptr + 3 * n);
ret = do_socketpair(domain, type, protocol, tab);
}
break;
case SOCKOP_send:
{
int sockfd = tgetl(vptr);
- target_ulong msg = tgetl(vptr + n);
+ abi_ulong msg = tgetl(vptr + n);
size_t len = tgetl(vptr + 2 * n);
int flags = tgetl(vptr + 3 * n);
ret = do_sendto(sockfd, msg, len, flags, 0, 0);
@@ -1164,7 +1243,7 @@
case SOCKOP_recv:
{
int sockfd = tgetl(vptr);
- target_ulong msg = tgetl(vptr + n);
+ abi_ulong msg = tgetl(vptr + n);
size_t len = tgetl(vptr + 2 * n);
int flags = tgetl(vptr + 3 * n);
ret = do_recvfrom(sockfd, msg, len, flags, 0, 0);
@@ -1173,10 +1252,10 @@
case SOCKOP_sendto:
{
int sockfd = tgetl(vptr);
- target_ulong msg = tgetl(vptr + n);
+ abi_ulong msg = tgetl(vptr + n);
size_t len = tgetl(vptr + 2 * n);
int flags = tgetl(vptr + 3 * n);
- target_ulong addr = tgetl(vptr + 4 * n);
+ abi_ulong addr = tgetl(vptr + 4 * n);
socklen_t addrlen = tgetl(vptr + 5 * n);
ret = do_sendto(sockfd, msg, len, flags, addr, addrlen);
}
@@ -1184,11 +1263,11 @@
case SOCKOP_recvfrom:
{
int sockfd = tgetl(vptr);
- target_ulong msg = tgetl(vptr + n);
+ abi_ulong msg = tgetl(vptr + n);
size_t len = tgetl(vptr + 2 * n);
int flags = tgetl(vptr + 3 * n);
- target_ulong addr = tgetl(vptr + 4 * n);
- target_ulong addrlen = tgetl(vptr + 5 * n);
+ abi_ulong addr = tgetl(vptr + 4 * n);
+ abi_ulong addrlen = tgetl(vptr + 5 * n);
ret = do_recvfrom(sockfd, msg, len, flags, addr, addrlen);
}
break;
@@ -1204,7 +1283,7 @@
case SOCKOP_recvmsg:
{
int fd;
- target_ulong target_msg;
+ abi_ulong target_msg;
int flags;
fd = tgetl(vptr);
@@ -1220,7 +1299,7 @@
int sockfd = tgetl(vptr);
int level = tgetl(vptr + n);
int optname = tgetl(vptr + 2 * n);
- target_ulong optval = tgetl(vptr + 3 * n);
+ abi_ulong optval = tgetl(vptr + 3 * n);
socklen_t optlen = tgetl(vptr + 4 * n);
ret = do_setsockopt(sockfd, level, optname, optval, optlen);
@@ -1231,20 +1310,22 @@
int sockfd = tgetl(vptr);
int level = tgetl(vptr + n);
int optname = tgetl(vptr + 2 * n);
- target_ulong optval = tgetl(vptr + 3 * n);
- target_ulong poptlen = tgetl(vptr + 4 * n);
+ abi_ulong optval = tgetl(vptr + 3 * n);
+ abi_ulong poptlen = tgetl(vptr + 4 * n);
ret = do_getsockopt(sockfd, level, optname, optval, poptlen);
}
break;
default:
gemu_log("Unsupported socketcall: %d\n", num);
- ret = -ENOSYS;
+ ret = -TARGET_ENOSYS;
break;
}
return ret;
}
+#endif
+#ifdef TARGET_NR_ipc
#define N_SHM_REGIONS 32
static struct shm_region {
@@ -1254,33 +1335,33 @@
struct target_ipc_perm
{
- target_long __key;
- target_ulong uid;
- target_ulong gid;
- target_ulong cuid;
- target_ulong cgid;
+ abi_long __key;
+ abi_ulong uid;
+ abi_ulong gid;
+ abi_ulong cuid;
+ abi_ulong cgid;
unsigned short int mode;
unsigned short int __pad1;
unsigned short int __seq;
unsigned short int __pad2;
- target_ulong __unused1;
- target_ulong __unused2;
+ abi_ulong __unused1;
+ abi_ulong __unused2;
};
struct target_semid_ds
{
struct target_ipc_perm sem_perm;
- target_ulong sem_otime;
- target_ulong __unused1;
- target_ulong sem_ctime;
- target_ulong __unused2;
- target_ulong sem_nsems;
- target_ulong __unused3;
- target_ulong __unused4;
+ abi_ulong sem_otime;
+ abi_ulong __unused1;
+ abi_ulong sem_ctime;
+ abi_ulong __unused2;
+ abi_ulong sem_nsems;
+ abi_ulong __unused3;
+ abi_ulong __unused4;
};
static inline void target_to_host_ipc_perm(struct ipc_perm *host_ip,
- target_ulong target_addr)
+ abi_ulong target_addr)
{
struct target_ipc_perm *target_ip;
struct target_semid_ds *target_sd;
@@ -1296,7 +1377,7 @@
unlock_user_struct(target_sd, target_addr, 0);
}
-static inline void host_to_target_ipc_perm(target_ulong target_addr,
+static inline void host_to_target_ipc_perm(abi_ulong target_addr,
struct ipc_perm *host_ip)
{
struct target_ipc_perm *target_ip;
@@ -1314,7 +1395,7 @@
}
static inline void target_to_host_semid_ds(struct semid_ds *host_sd,
- target_ulong target_addr)
+ abi_ulong target_addr)
{
struct target_semid_ds *target_sd;
@@ -1326,7 +1407,7 @@
unlock_user_struct(target_sd, target_addr, 0);
}
-static inline void host_to_target_semid_ds(target_ulong target_addr,
+static inline void host_to_target_semid_ds(abi_ulong target_addr,
struct semid_ds *host_sd)
{
struct target_semid_ds *target_sd;
@@ -1347,13 +1428,13 @@
union target_semun {
int val;
- target_long buf;
+ abi_long buf;
unsigned short int *array;
};
-static inline void target_to_host_semun(unsigned long cmd,
+static inline void target_to_host_semun(int cmd,
union semun *host_su,
- target_ulong target_addr,
+ abi_ulong target_addr,
struct semid_ds *ds)
{
union target_semun *target_su;
@@ -1383,8 +1464,8 @@
}
}
-static inline void host_to_target_semun(unsigned long cmd,
- target_ulong target_addr,
+static inline void host_to_target_semun(int cmd,
+ abi_ulong target_addr,
union semun *host_su,
struct semid_ds *ds)
{
@@ -1414,12 +1495,13 @@
}
}
-static inline long do_semctl(long first, long second, long third, long ptr)
+static inline abi_long do_semctl(int first, int second, int third,
+ abi_long ptr)
{
union semun arg;
struct semid_ds dsarg;
int cmd = third&0xff;
- long ret = 0;
+ abi_long ret = 0;
switch( cmd ) {
case GETVAL:
@@ -1462,23 +1544,23 @@
struct target_msqid_ds
{
struct target_ipc_perm msg_perm;
- target_ulong msg_stime;
- target_ulong __unused1;
- target_ulong msg_rtime;
- target_ulong __unused2;
- target_ulong msg_ctime;
- target_ulong __unused3;
- target_ulong __msg_cbytes;
- target_ulong msg_qnum;
- target_ulong msg_qbytes;
- target_ulong msg_lspid;
- target_ulong msg_lrpid;
- target_ulong __unused4;
- target_ulong __unused5;
+ abi_ulong msg_stime;
+ abi_ulong __unused1;
+ abi_ulong msg_rtime;
+ abi_ulong __unused2;
+ abi_ulong msg_ctime;
+ abi_ulong __unused3;
+ abi_ulong __msg_cbytes;
+ abi_ulong msg_qnum;
+ abi_ulong msg_qbytes;
+ abi_ulong msg_lspid;
+ abi_ulong msg_lrpid;
+ abi_ulong __unused4;
+ abi_ulong __unused5;
};
static inline void target_to_host_msqid_ds(struct msqid_ds *host_md,
- target_ulong target_addr)
+ abi_ulong target_addr)
{
struct target_msqid_ds *target_md;
@@ -1495,7 +1577,7 @@
unlock_user_struct(target_md, target_addr, 0);
}
-static inline void host_to_target_msqid_ds(target_ulong target_addr,
+static inline void host_to_target_msqid_ds(abi_ulong target_addr,
struct msqid_ds *host_md)
{
struct target_msqid_ds *target_md;
@@ -1513,11 +1595,11 @@
unlock_user_struct(target_md, target_addr, 1);
}
-static inline long do_msgctl(long first, long second, long ptr)
+static inline abi_long do_msgctl(int first, int second, abi_long ptr)
{
struct msqid_ds dsarg;
int cmd = second&0xff;
- long ret = 0;
+ abi_long ret = 0;
switch( cmd ) {
case IPC_STAT:
case IPC_SET:
@@ -1531,15 +1613,16 @@
}
struct target_msgbuf {
- target_ulong mtype;
+ abi_ulong mtype;
char mtext[1];
};
-static inline long do_msgsnd(long msqid, long msgp, long msgsz, long msgflg)
+static inline abi_long do_msgsnd(int msqid, abi_long msgp,
+ unsigned int msgsz, int msgflg)
{
struct target_msgbuf *target_mb;
struct msgbuf *host_mb;
- long ret = 0;
+ abi_long ret = 0;
lock_user_struct(target_mb,msgp,0);
host_mb = malloc(msgsz+sizeof(long));
@@ -1552,11 +1635,13 @@
return ret;
}
-static inline long do_msgrcv(long msqid, long msgp, long msgsz, long msgtype, long msgflg)
+static inline abi_long do_msgrcv(int msqid, abi_long msgp,
+ unsigned int msgsz, int msgtype,
+ int msgflg)
{
struct target_msgbuf *target_mb;
struct msgbuf *host_mb;
- long ret = 0;
+ abi_long ret = 0;
lock_user_struct(target_mb, msgp, 0);
host_mb = malloc(msgsz+sizeof(long));
@@ -1571,11 +1656,13 @@
}
/* ??? This only works with linear mappings. */
-static long do_ipc(long call, long first, long second, long third,
- long ptr, long fifth)
+/* do_ipc() must return target values and target errnos. */
+static abi_long do_ipc(unsigned int call, int first,
+ int second, int third,
+ abi_long ptr, abi_long fifth)
{
int version;
- long ret = 0;
+ abi_long ret = 0;
unsigned long raddr;
struct shmid_ds shm_info;
int i;
@@ -1597,8 +1684,8 @@
break;
case IPCOP_semtimedop:
- gemu_log("Unsupported ipc call: %ld (version %d)\n", call, version);
- ret = -ENOSYS;
+ gemu_log("Unsupported ipc call: %d (version %d)\n", call, version);
+ ret = -TARGET_ENOSYS;
break;
case IPCOP_msgget:
@@ -1653,8 +1740,8 @@
break;
}
}
- if (put_user(raddr, (uint32_t *)third))
- return -EFAULT;
+ if (put_user(raddr, (abi_ulong *)third))
+ return -TARGET_EFAULT;
ret = 0;
break;
case IPCOP_shmdt:
@@ -1687,12 +1774,13 @@
break;
default:
unimplemented:
- gemu_log("Unsupported ipc call: %ld (version %d)\n", call, version);
- ret = -ENOSYS;
+ gemu_log("Unsupported ipc call: %d (version %d)\n", call, version);
+ ret = -TARGET_ENOSYS;
break;
}
return ret;
}
+#endif
/* kernel structure types definitions */
#define IFNAMSIZ 16
@@ -1733,11 +1821,12 @@
};
/* ??? Implement proper locking for ioctls. */
-static long do_ioctl(long fd, long cmd, long arg)
+/* do_ioctl() Must return target values and target errnos. */
+static abi_long do_ioctl(int fd, abi_long cmd, abi_long arg)
{
const IOCTLEntry *ie;
const argtype *arg_type;
- long ret;
+ abi_long ret;
uint8_t buf_temp[MAX_STRUCT_SIZE];
int target_size;
void *argptr;
@@ -1745,8 +1834,8 @@
ie = ioctl_entries;
for(;;) {
if (ie->target_cmd == 0) {
- gemu_log("Unsupported ioctl: cmd=0x%04lx\n", cmd);
- return -ENOSYS;
+ gemu_log("Unsupported ioctl: cmd=0x%04lx\n", (long)cmd);
+ return -TARGET_ENOSYS;
}
if (ie->target_cmd == cmd)
break;
@@ -1754,7 +1843,7 @@
}
arg_type = ie->arg_type;
#if defined(DEBUG)
- gemu_log("ioctl: cmd=0x%04lx (%s)\n", cmd, ie->name);
+ gemu_log("ioctl: cmd=0x%04lx (%s)\n", (long)cmd, ie->name);
#endif
switch(arg_type[0]) {
case TYPE_NULL:
@@ -1799,8 +1888,9 @@
}
break;
default:
- gemu_log("Unsupported ioctl type: cmd=0x%04lx type=%d\n", cmd, arg_type[0]);
- ret = -ENOSYS;
+ gemu_log("Unsupported ioctl type: cmd=0x%04lx type=%d\n",
+ (long)cmd, arg_type[0]);
+ ret = -TARGET_ENOSYS;
break;
}
return ret;
@@ -2017,7 +2107,7 @@
/* NOTE: there is really one LDT for all the threads */
uint8_t *ldt_table;
-static int read_ldt(target_ulong ptr, unsigned long bytecount)
+static int read_ldt(abi_ulong ptr, unsigned long bytecount)
{
int size;
void *p;
@@ -2035,8 +2125,9 @@
}
/* XXX: add locking support */
+/* write_ldt() returns host errnos */
static int write_ldt(CPUX86State *env,
- target_ulong ptr, unsigned long bytecount, int oldmode)
+ abi_ulong ptr, unsigned long bytecount, int oldmode)
{
struct target_modify_ldt_ldt_s ldt_info;
struct target_modify_ldt_ldt_s *target_ldt_info;
@@ -2117,7 +2208,9 @@
}
/* specific and weird i386 syscalls */
-int do_modify_ldt(CPUX86State *env, int func, target_ulong ptr, unsigned long bytecount)
+/* do_modify_ldt() returns host errnos (it is inconsistent with the
+ other do_*() functions which return target errnos). */
+int do_modify_ldt(CPUX86State *env, int func, abi_ulong ptr, unsigned long bytecount)
{
int ret = -ENOSYS;
@@ -2149,7 +2242,9 @@
return 0;
}
-int do_fork(CPUState *env, unsigned int flags, unsigned long newsp)
+/* do_fork() Must return host values and target errnos (unlike most
+ do_*() functions). */
+int do_fork(CPUState *env, unsigned int flags, abi_ulong newsp)
{
int ret;
TaskState *ts;
@@ -2217,6 +2312,10 @@
for (i = 7; i < 30; i++)
new_env->ir[i] = 0;
}
+#elif defined(TARGET_CRIS)
+ if (!newsp)
+ newsp = env->regs[14];
+ new_env->regs[14] = newsp;
#else
#error unsupported target CPU
#endif
@@ -2235,13 +2334,13 @@
return ret;
}
-static long do_fcntl(int fd, int cmd, target_ulong arg)
+static abi_long do_fcntl(int fd, int cmd, abi_ulong arg)
{
struct flock fl;
struct target_flock *target_fl;
struct flock64 fl64;
struct target_flock64 *target_fl64;
- long ret;
+ abi_long ret;
switch(cmd) {
case TARGET_F_GETLK:
@@ -2400,6 +2499,7 @@
}
}
+#if TARGET_ABI_BITS == 32
static inline uint64_t target_offset64(uint32_t word0, uint32_t word1)
{
#ifdef TARGET_WORDS_BIG_ENDIAN
@@ -2408,10 +2508,18 @@
return ((uint64_t)word1 << 32) | word0;
#endif
}
+#else /* TARGET_ABI_BITS == 32 */
+static inline uint64_t target_offset64(uint64_t word0, uint64_t word1)
+{
+ return word0;
+}
+#endif /* TARGET_ABI_BITS != 32 */
#ifdef TARGET_NR_truncate64
-static inline long target_truncate64(void *cpu_env, const char *arg1,
- long arg2, long arg3, long arg4)
+static inline abi_long target_truncate64(void *cpu_env, const char *arg1,
+ abi_long arg2,
+ abi_long arg3,
+ abi_long arg4)
{
#ifdef TARGET_ARM
if (((CPUARMState *)cpu_env)->eabi)
@@ -2425,8 +2533,10 @@
#endif
#ifdef TARGET_NR_ftruncate64
-static inline long target_ftruncate64(void *cpu_env, long arg1, long arg2,
- long arg3, long arg4)
+static inline abi_long target_ftruncate64(void *cpu_env, abi_long arg1,
+ abi_long arg2,
+ abi_long arg3,
+ abi_long arg4)
{
#ifdef TARGET_ARM
if (((CPUARMState *)cpu_env)->eabi)
@@ -2440,7 +2550,7 @@
#endif
static inline void target_to_host_timespec(struct timespec *host_ts,
- target_ulong target_addr)
+ abi_ulong target_addr)
{
struct target_timespec *target_ts;
@@ -2450,7 +2560,7 @@
unlock_user_struct(target_ts, target_addr, 0);
}
-static inline void host_to_target_timespec(target_ulong target_addr,
+static inline void host_to_target_timespec(abi_ulong target_addr,
struct timespec *host_ts)
{
struct target_timespec *target_ts;
@@ -2461,10 +2571,14 @@
unlock_user_struct(target_ts, target_addr, 1);
}
-long do_syscall(void *cpu_env, int num, long arg1, long arg2, long arg3,
- long arg4, long arg5, long arg6)
+/* do_syscall() should always have a single exit point at the end so
+ that actions, such as logging of syscall results, can be performed.
+ All errnos that do_syscall() returns must be -TARGET_<errcode>. */
+abi_long do_syscall(void *cpu_env, int num, abi_long arg1,
+ abi_long arg2, abi_long arg3, abi_long arg4,
+ abi_long arg5, abi_long arg6)
{
- long ret;
+ abi_long ret;
struct stat st;
struct statfs stfs;
void *p;
@@ -2500,6 +2614,25 @@
arg3));
unlock_user(p, arg1, 0);
break;
+#if defined(TARGET_NR_openat) && defined(__NR_openat)
+ case TARGET_NR_openat:
+ if (!arg2) {
+ ret = -TARGET_EFAULT;
+ goto fail;
+ }
+ p = lock_user_string(arg2);
+ if (!access_ok(VERIFY_READ, p, 1))
+ /* Don't "goto fail" so that cleanup can happen. */
+ ret = -TARGET_EFAULT;
+ else
+ ret = get_errno(sys_openat(arg1,
+ path(p),
+ target_to_host_bitmask(arg3, fcntl_flags_tbl),
+ arg4));
+ if (p)
+ unlock_user(p, arg2, 0);
+ break;
+#endif
case TARGET_NR_close:
ret = get_errno(close(arg1));
break;
@@ -2536,19 +2669,58 @@
unlock_user(p, arg1, 0);
}
break;
+#if defined(TARGET_NR_linkat) && defined(__NR_linkat)
+ case TARGET_NR_linkat:
+ if (!arg2 || !arg4) {
+ ret = -TARGET_EFAULT;
+ goto fail;
+ }
+ {
+ void * p2 = NULL;
+ p = lock_user_string(arg2);
+ p2 = lock_user_string(arg4);
+ if (!access_ok(VERIFY_READ, p, 1)
+ || !access_ok(VERIFY_READ, p2, 1))
+ /* Don't "goto fail" so that cleanup can happen. */
+ ret = -TARGET_EFAULT;
+ else
+ ret = get_errno(sys_linkat(arg1, p, arg3, p2, arg5));
+ if (p2)
+ unlock_user(p, arg2, 0);
+ if (p)
+ unlock_user(p2, arg4, 0);
+ }
+ break;
+#endif
case TARGET_NR_unlink:
p = lock_user_string(arg1);
ret = get_errno(unlink(p));
unlock_user(p, arg1, 0);
break;
+#if defined(TARGET_NR_unlinkat) && defined(__NR_unlinkat)
+ case TARGET_NR_unlinkat:
+ if (!arg2) {
+ ret = -TARGET_EFAULT;
+ goto fail;
+ }
+ p = lock_user_string(arg2);
+ if (!access_ok(VERIFY_READ, p, 1))
+ /* Don't "goto fail" so that cleanup can happen. */
+ ret = -TARGET_EFAULT;
+ else
+ ret = get_errno(sys_unlinkat(arg1, p, arg3));
+ if (p)
+ unlock_user(p, arg2, 0);
+ break;
+#endif
case TARGET_NR_execve:
{
char **argp, **envp;
int argc, envc;
- target_ulong gp;
- target_ulong guest_argp;
- target_ulong guest_envp;
- target_ulong addr;
+ abi_ulong gp;
+ abi_ulong guest_argp;
+ abi_ulong guest_envp;
+ abi_ulong addr;
char **q;
argc = 0;
@@ -2564,7 +2736,7 @@
envp = alloca((envc + 1) * sizeof(void *));
for (gp = guest_argp, q = argp; ;
- gp += sizeof(target_ulong), q++) {
+ gp += sizeof(abi_ulong), q++) {
addr = tgetl(gp);
if (!addr)
break;
@@ -2573,7 +2745,7 @@
*q = NULL;
for (gp = guest_envp, q = envp; ;
- gp += sizeof(target_ulong), q++) {
+ gp += sizeof(abi_ulong), q++) {
addr = tgetl(gp);
if (!addr)
break;
@@ -2586,12 +2758,12 @@
unlock_user(p, arg1, 0);
for (gp = guest_argp, q = argp; *q;
- gp += sizeof(target_ulong), q++) {
+ gp += sizeof(abi_ulong), q++) {
addr = tgetl(gp);
unlock_user(*q, addr, 0);
}
for (gp = guest_envp, q = envp; *q;
- gp += sizeof(target_ulong), q++) {
+ gp += sizeof(abi_ulong), q++) {
addr = tgetl(gp);
unlock_user(*q, addr, 0);
}
@@ -2617,6 +2789,22 @@
ret = get_errno(mknod(p, arg2, arg3));
unlock_user(p, arg1, 0);
break;
+#if defined(TARGET_NR_mknodat) && defined(__NR_mknodat)
+ case TARGET_NR_mknodat:
+ if (!arg2) {
+ ret = -TARGET_EFAULT;
+ goto fail;
+ }
+ p = lock_user_string(arg2);
+ if (!access_ok(VERIFY_READ, p, 1))
+ /* Don't "goto fail" so that cleanup can happen. */
+ ret = -TARGET_EFAULT;
+ else
+ ret = get_errno(sys_mknodat(arg1, p, arg3, arg4));
+ if (p)
+ unlock_user(p, arg2, 0);
+ break;
+#endif
case TARGET_NR_chmod:
p = lock_user_string(arg1);
ret = get_errno(chmod(p, arg2));
@@ -2734,6 +2922,22 @@
ret = get_errno(access(p, arg2));
unlock_user(p, arg1, 0);
break;
+#if defined(TARGET_NR_faccessat) && defined(__NR_faccessat)
+ case TARGET_NR_faccessat:
+ if (!arg2) {
+ ret = -TARGET_EFAULT;
+ goto fail;
+ }
+ p = lock_user_string(arg2);
+ if (!access_ok(VERIFY_READ, p, 1))
+ /* Don't "goto fail" so that cleanup can happen. */
+ ret = -TARGET_EFAULT;
+ else
+ ret = get_errno(sys_faccessat(arg1, p, arg3, arg4));
+ if (p)
+ unlock_user(p, arg2, 0);
+ break;
+#endif
#ifdef TARGET_NR_nice /* not on alpha */
case TARGET_NR_nice:
ret = get_errno(nice(arg1));
@@ -2760,11 +2964,50 @@
unlock_user(p, arg1, 0);
}
break;
+#if defined(TARGET_NR_renameat) && defined(__NR_renameat)
+ case TARGET_NR_renameat:
+ if (!arg2 || !arg4) {
+ ret = -TARGET_EFAULT;
+ goto fail;
+ }
+ {
+ void *p2 = NULL;
+ p = lock_user_string(arg2);
+ p2 = lock_user_string(arg4);
+ if (!access_ok(VERIFY_READ, p, 1)
+ || !access_ok(VERIFY_READ, p2, 1))
+ /* Don't "goto fail" so that cleanup can happen. */
+ ret = -TARGET_EFAULT;
+ else
+ ret = get_errno(sys_renameat(arg1, p, arg3, p2));
+ if (p2)
+ unlock_user(p2, arg4, 0);
+ if (p)
+ unlock_user(p, arg2, 0);
+ }
+ break;
+#endif
case TARGET_NR_mkdir:
p = lock_user_string(arg1);
ret = get_errno(mkdir(p, arg2));
unlock_user(p, arg1, 0);
break;
+#if defined(TARGET_NR_mkdirat) && defined(__NR_mkdirat)
+ case TARGET_NR_mkdirat:
+ if (!arg2) {
+ ret = -TARGET_EFAULT;
+ goto fail;
+ }
+ p = lock_user_string(arg2);
+ if (!access_ok(VERIFY_READ, p, 1))
+ /* Don't "goto fail" so that cleanup can happen. */
+ ret = -TARGET_EFAULT;
+ else
+ ret = get_errno(sys_mkdirat(arg1, p, arg3));
+ if (p)
+ unlock_user(p, arg2, 0);
+ break;
+#endif
case TARGET_NR_rmdir:
p = lock_user_string(arg1);
ret = get_errno(rmdir(p));
@@ -2954,7 +3197,7 @@
case TARGET_NR_sgetmask:
{
sigset_t cur_set;
- target_ulong target_set;
+ abi_ulong target_set;
sigprocmask(0, NULL, &cur_set);
host_to_target_old_sigset(&target_set, &cur_set);
ret = target_set;
@@ -2965,7 +3208,7 @@
case TARGET_NR_ssetmask:
{
sigset_t set, oset, cur_set;
- target_ulong target_set = arg1;
+ abi_ulong target_set = arg1;
sigprocmask(0, NULL, &cur_set);
target_to_host_old_sigset(&set, &target_set);
sigorset(&set, &set, &cur_set);
@@ -2993,7 +3236,7 @@
how = SIG_SETMASK;
break;
default:
- ret = -EINVAL;
+ ret = -TARGET_EINVAL;
goto fail;
}
p = lock_user(arg2, sizeof(target_sigset_t), 1);
@@ -3030,7 +3273,7 @@
how = SIG_SETMASK;
break;
default:
- ret = -EINVAL;
+ ret = -TARGET_EINVAL;
goto fail;
}
p = lock_user(arg2, sizeof(target_sigset_t), 1);
@@ -3198,7 +3441,7 @@
case TARGET_NR_select:
{
struct target_sel_arg_struct *sel;
- target_ulong inp, outp, exp, tvp;
+ abi_ulong inp, outp, exp, tvp;
long nsel;
lock_user_struct(sel, arg1, 1);
@@ -3222,6 +3465,29 @@
unlock_user(p, arg1, 0);
}
break;
+#if defined(TARGET_NR_symlinkat) && defined(__NR_symlinkat)
+ case TARGET_NR_symlinkat:
+ if (!arg1 || !arg3) {
+ ret = -TARGET_EFAULT;
+ goto fail;
+ }
+ {
+ void *p2 = NULL;
+ p = lock_user_string(arg1);
+ p2 = lock_user_string(arg3);
+ if (!access_ok(VERIFY_READ, p, 1)
+ || !access_ok(VERIFY_READ, p2, 1))
+ /* Don't "goto fail" so that cleanup can happen. */
+ ret = -TARGET_EFAULT;
+ else
+ ret = get_errno(sys_symlinkat(p, arg2, p2));
+ if (p2)
+ unlock_user(p2, arg3, 0);
+ if (p)
+ unlock_user(p, arg1, 0);
+ }
+ break;
+#endif
#ifdef TARGET_NR_oldlstat
case TARGET_NR_oldlstat:
goto unimplemented;
@@ -3236,6 +3502,29 @@
unlock_user(p, arg1, 0);
}
break;
+#if defined(TARGET_NR_readlinkat) && defined(__NR_readlinkat)
+ case TARGET_NR_readlinkat:
+ if (!arg2 || !arg3) {
+ ret = -TARGET_EFAULT;
+ goto fail;
+ }
+ {
+ void *p2 = NULL;
+ p = lock_user_string(arg2);
+ p2 = lock_user(arg3, arg4, 0);
+ if (!access_ok(VERIFY_READ, p, 1)
+ || !access_ok(VERIFY_READ, p2, 1))
+ /* Don't "goto fail" so that cleanup can happen. */
+ ret = -TARGET_EFAULT;
+ else
+ ret = get_errno(sys_readlinkat(arg1, path(p), p2, arg4));
+ if (p2)
+ unlock_user(p2, arg3, ret);
+ if (p)
+ unlock_user(p, arg2, 0);
+ }
+ break;
+#endif
#ifdef TARGET_NR_uselib
case TARGET_NR_uselib:
goto unimplemented;
@@ -3255,11 +3544,11 @@
#endif
#ifdef TARGET_NR_mmap
case TARGET_NR_mmap:
-#if defined(TARGET_I386) || defined(TARGET_ARM) || defined(TARGET_M68K)
+#if defined(TARGET_I386) || defined(TARGET_ARM) || defined(TARGET_M68K) || defined(TARGET_CRIS)
{
- target_ulong *v;
- target_ulong v1, v2, v3, v4, v5, v6;
- v = lock_user(arg1, 6 * sizeof(target_ulong), 1);
+ abi_ulong *v;
+ abi_ulong v1, v2, v3, v4, v5, v6;
+ v = lock_user(arg1, 6 * sizeof(abi_ulong), 1);
v1 = tswapl(v[0]);
v2 = tswapl(v[1]);
v3 = tswapl(v[2]);
@@ -3340,8 +3629,27 @@
case TARGET_NR_fchmod:
ret = get_errno(fchmod(arg1, arg2));
break;
+#if defined(TARGET_NR_fchmodat) && defined(__NR_fchmodat)
+ case TARGET_NR_fchmodat:
+ if (!arg2) {
+ ret = -TARGET_EFAULT;
+ goto fail;
+ }
+ p = lock_user_string(arg2);
+ if (!access_ok(VERIFY_READ, p, 1))
+ /* Don't "goto fail" so that cleanup can happen. */
+ ret = -TARGET_EFAULT;
+ else
+ ret = get_errno(sys_fchmodat(arg1, p, arg3, arg4));
+ if (p)
+ unlock_user(p, arg2, 0);
+ break;
+#endif
case TARGET_NR_getpriority:
- ret = get_errno(getpriority(arg1, arg2));
+ /* libc does special remapping of the return value of
+ * sys_getpriority() so it's just easiest to call
+ * sys_getpriority() directly rather than through libc. */
+ ret = sys_getpriority(arg1, arg2);
break;
case TARGET_NR_setpriority:
ret = get_errno(setpriority(arg1, arg2, arg3));
@@ -3558,7 +3866,7 @@
struct target_stat *target_st;
lock_user_struct(target_st, arg2, 0);
-#if defined(TARGET_MIPS) || defined(TARGET_SPARC64)
+#if defined(TARGET_MIPS) || (defined(TARGET_SPARC64) && !defined(TARGET_ABI32))
target_st->st_dev = tswap32(st.st_dev);
#else
target_st->st_dev = tswap16(st.st_dev);
@@ -3568,7 +3876,7 @@
target_st->st_mode = tswapl(st.st_mode); /* XXX: check this */
target_st->st_uid = tswap32(st.st_uid);
target_st->st_gid = tswap32(st.st_gid);
-#elif defined(TARGET_SPARC64)
+#elif defined(TARGET_SPARC64) && !defined(TARGET_ABI32)
target_st->st_mode = tswap32(st.st_mode);
target_st->st_uid = tswap32(st.st_uid);
target_st->st_gid = tswap32(st.st_gid);
@@ -3581,7 +3889,7 @@
/* If this is the same on PPC, then just merge w/ the above ifdef */
target_st->st_nlink = tswapl(st.st_nlink);
target_st->st_rdev = tswapl(st.st_rdev);
-#elif defined(TARGET_SPARC64)
+#elif defined(TARGET_SPARC64) && !defined(TARGET_ABI32)
target_st->st_nlink = tswap32(st.st_nlink);
target_st->st_rdev = tswap32(st.st_rdev);
#else
@@ -3621,9 +3929,9 @@
case TARGET_NR_wait4:
{
int status;
- target_long status_ptr = arg2;
+ abi_long status_ptr = arg2;
struct rusage rusage, *rusage_ptr;
- target_ulong target_rusage = arg4;
+ abi_ulong target_rusage = arg4;
if (target_rusage)
rusage_ptr = &rusage;
else
@@ -3774,18 +4082,20 @@
break;
#endif
case TARGET_NR_getdents:
-#if TARGET_LONG_SIZE != 4
+#if TARGET_ABI_BITS != 32
goto unimplemented;
#warning not supported
-#elif TARGET_LONG_SIZE == 4 && HOST_LONG_SIZE == 8
+#elif TARGET_ABI_BITS == 32 && HOST_LONG_BITS == 64
{
struct target_dirent *target_dirp;
struct dirent *dirp;
- long count = arg3;
+ abi_long count = arg3;
dirp = malloc(count);
- if (!dirp)
- return -ENOMEM;
+ if (!dirp) {
+ ret = -TARGET_EFAULT;
+ goto fail;
+ }
ret = get_errno(sys_getdents(arg1, dirp, count));
if (!is_error(ret)) {
@@ -3801,11 +4111,11 @@
tde = target_dirp;
while (len > 0) {
reclen = de->d_reclen;
- treclen = reclen - (2 * (sizeof(long) - sizeof(target_long)));
+ treclen = reclen - (2 * (sizeof(long) - sizeof(abi_long)));
tde->d_reclen = tswap16(treclen);
tde->d_ino = tswapl(de->d_ino);
tde->d_off = tswapl(de->d_off);
- tnamelen = treclen - (2 * sizeof(target_long) + 2);
+ tnamelen = treclen - (2 * sizeof(abi_long) + 2);
if (tnamelen > 256)
tnamelen = 256;
/* XXX: may not be correct */
@@ -3823,7 +4133,7 @@
#else
{
struct dirent *dirp;
- long count = arg3;
+ abi_long count = arg3;
dirp = lock_user(arg2, count, 0);
ret = get_errno(sys_getdents(arg1, dirp, count));
@@ -3851,7 +4161,7 @@
case TARGET_NR_getdents64:
{
struct dirent64 *dirp;
- long count = arg3;
+ abi_long count = arg3;
dirp = lock_user(arg2, count, 0);
ret = get_errno(sys_getdents64(arg1, dirp, count));
if (!is_error(ret)) {
@@ -3942,9 +4252,10 @@
break;
#endif
case TARGET_NR__sysctl:
- /* We don't implement this, but ENODIR is always a safe
+ /* We don't implement this, but ENOTDIR is always a safe
return value. */
- return -ENOTDIR;
+ ret = -TARGET_ENOTDIR;
+ break;
case TARGET_NR_sched_setparam:
{
struct sched_param *target_schp;
@@ -4056,7 +4367,15 @@
case TARGET_NR_capset:
goto unimplemented;
case TARGET_NR_sigaltstack:
+#if defined(TARGET_I386) || defined(TARGET_ARM) || defined(TARGET_MIPS) || \
+ defined(TARGET_SPARC) || defined(TARGET_PPC) || defined(TARGET_ALPHA)
+ ret = do_sigaltstack((struct target_sigaltstack *)arg1,
+ (struct target_sigaltstack *)arg2,
+ get_sp_from_cpustate((CPUState *)cpu_env));
+ break;
+#else
goto unimplemented;
+#endif
case TARGET_NR_sendfile:
goto unimplemented;
#ifdef TARGET_NR_getpmsg
@@ -4232,6 +4551,22 @@
case TARGET_NR_fchown:
ret = get_errno(fchown(arg1, low2highuid(arg2), low2highgid(arg3)));
break;
+#if defined(TARGET_NR_fchownat) && defined(__NR_fchownat)
+ case TARGET_NR_fchownat:
+ if (!arg2) {
+ ret = -TARGET_EFAULT;
+ goto fail;
+ }
+ p = lock_user_string(arg2);
+ if (!access_ok(VERIFY_READ, p, 1))
+ /* Don't "goto fail" so that cleanup can happen. */
+ ret = -TARGET_EFAULT;
+ else
+ ret = get_errno(sys_fchownat(arg1, p, low2highuid(arg3), low2highgid(arg4), arg5));
+ if (p)
+ unlock_user(p, arg2, 0);
+ break;
+#endif
#ifdef TARGET_NR_setresuid
case TARGET_NR_setresuid:
ret = get_errno(setresuid(low2highuid(arg1),
@@ -4448,7 +4783,7 @@
ret = get_errno(0);
break;
#endif
-#if TARGET_LONG_BITS == 32
+#if TARGET_ABI_BITS == 32
case TARGET_NR_fcntl64:
{
int cmd;
@@ -4653,13 +4988,35 @@
goto unimplemented_nowarn;
#endif
+#if defined(TARGET_NR_utimensat) && defined(__NR_utimensat)
+ case TARGET_NR_utimensat:
+ {
+ struct timespec ts[2];
+ target_to_host_timespec(ts, arg3);
+ target_to_host_timespec(ts+1, arg3+sizeof(struct target_timespec));
+ if (!arg2)
+ ret = get_errno(sys_utimensat(arg1, NULL, ts, arg4));
+ else {
+ p = lock_user_string(arg2);
+ if (!access_ok(VERIFY_READ, p, 1))
+ /* Don't "goto fail" so that cleanup can happen. */
+ ret = -TARGET_EFAULT;
+ else
+ ret = get_errno(sys_utimensat(arg1, path(p), ts, arg4));
+ if (p)
+ unlock_user(p, arg2, 0);
+ }
+ }
+ break;
+#endif
+
default:
unimplemented:
gemu_log("qemu: Unsupported syscall: %d\n", num);
#if defined(TARGET_NR_setxattr) || defined(TARGET_NR_get_thread_area) || defined(TARGET_NR_getdomainname) || defined(TARGET_NR_set_robust_list)
unimplemented_nowarn:
#endif
- ret = -ENOSYS;
+ ret = -TARGET_ENOSYS;
break;
}
fail:
@@ -4668,4 +5025,3 @@
#endif
return ret;
}
-
Modified: trunk/src/host/qemu-neo1973/linux-user/syscall_defs.h
===================================================================
--- trunk/src/host/qemu-neo1973/linux-user/syscall_defs.h 2007-10-29 20:40:05 UTC (rev 3302)
+++ trunk/src/host/qemu-neo1973/linux-user/syscall_defs.h 2007-10-29 21:14:04 UTC (rev 3303)
@@ -49,7 +49,7 @@
#define TARGET_IOC_TYPEBITS 8
#if defined(TARGET_I386) || defined(TARGET_ARM) || defined(TARGET_SH4) \
- || defined(TARGET_M68K) || defined(TARGET_ALPHA)
+ || defined(TARGET_M68K) || defined(TARGET_ALPHA) || defined(TARGET_CRIS)
#define TARGET_IOC_SIZEBITS 14
#define TARGET_IOC_DIRBITS 2
@@ -105,13 +105,13 @@
};
struct target_timeval {
- target_long tv_sec;
- target_long tv_usec;
+ abi_long tv_sec;
+ abi_long tv_usec;
};
struct target_timespec {
- target_long tv_sec;
- target_long tv_nsec;
+ abi_long tv_sec;
+ abi_long tv_nsec;
};
struct target_itimerval {
@@ -119,7 +119,7 @@
struct target_timeval it_value;
};
-typedef target_long target_clock_t;
+typedef abi_long target_clock_t;
#define TARGET_HZ 100
@@ -131,33 +131,33 @@
};
struct target_utimbuf {
- target_long actime;
- target_long modtime;
+ abi_long actime;
+ abi_long modtime;
};
struct target_sel_arg_struct {
- target_long n;
- target_long inp, outp, exp;
- target_long tvp;
+ abi_long n;
+ abi_long inp, outp, exp;
+ abi_long tvp;
};
struct target_iovec {
- target_long iov_base; /* Starting address */
- target_long iov_len; /* Number of bytes */
+ abi_long iov_base; /* Starting address */
+ abi_long iov_len; /* Number of bytes */
};
struct target_msghdr {
- target_long msg_name; /* Socket name */
- int msg_namelen; /* Length of name */
- target_long msg_iov; /* Data blocks */
- target_long msg_iovlen; /* Number of blocks */
- target_long msg_control; /* Per protocol magic (eg BSD file descriptor passing) */
- target_long msg_controllen; /* Length of cmsg list */
+ abi_long msg_name; /* Socket name */
+ int msg_namelen; /* Length of name */
+ abi_long msg_iov; /* Data blocks */
+ abi_long msg_iovlen; /* Number of blocks */
+ abi_long msg_control; /* Per protocol magic (eg BSD file descriptor passing) */
+ abi_long msg_controllen; /* Length of cmsg list */
unsigned int msg_flags;
};
struct target_cmsghdr {
- target_long cmsg_len;
+ abi_long cmsg_len;
int cmsg_level;
int cmsg_type;
};
@@ -167,8 +167,8 @@
#define TARGET_CMSG_FIRSTHDR(mhdr) \
((size_t) tswapl((mhdr)->msg_controllen) >= sizeof (struct target_cmsghdr) \
? (struct target_cmsghdr *) tswapl((mhdr)->msg_control) : (struct target_cmsghdr *) NULL)
-#define TARGET_CMSG_ALIGN(len) (((len) + sizeof (target_long) - 1) \
- & (size_t) ~(sizeof (target_long) - 1))
+#define TARGET_CMSG_ALIGN(len) (((len) + sizeof (abi_long) - 1) \
+ & (size_t) ~(sizeof (abi_long) - 1))
#define TARGET_CMSG_SPACE(len) (TARGET_CMSG_ALIGN (len) \
+ TARGET_CMSG_ALIGN (sizeof (struct target_cmsghdr)))
#define TARGET_CMSG_LEN(len) (TARGET_CMSG_ALIGN (sizeof (struct target_cmsghdr)) + (len))
@@ -191,20 +191,20 @@
struct target_rusage {
struct target_timeval ru_utime; /* user time used */
struct target_timeval ru_stime; /* system time used */
- target_long ru_maxrss; /* maximum resident set size */
- target_long ru_ixrss; /* integral shared memory size */
- target_long ru_idrss; /* integral unshared data size */
- target_long ru_isrss; /* integral unshared stack size */
- target_long ru_minflt; /* page reclaims */
- target_long ru_majflt; /* page faults */
- target_long ru_nswap; /* swaps */
- target_long ru_inblock; /* block input operations */
- target_long ru_oublock; /* block output operations */
- target_long ru_msgsnd; /* messages sent */
- target_long ru_msgrcv; /* messages received */
- target_long ru_nsignals; /* signals received */
- target_long ru_nvcsw; /* voluntary context switches */
- target_long ru_nivcsw; /* involuntary " */
+ abi_long ru_maxrss; /* maximum resident set size */
+ abi_long ru_ixrss; /* integral shared memory size */
+ abi_long ru_idrss; /* integral unshared data size */
+ abi_long ru_isrss; /* integral unshared stack size */
+ abi_long ru_minflt; /* page reclaims */
+ abi_long ru_majflt; /* page faults */
+ abi_long ru_nswap; /* swaps */
+ abi_long ru_inblock; /* block input operations */
+ abi_long ru_oublock; /* block output operations */
+ abi_long ru_msgsnd; /* messages sent */
+ abi_long ru_msgrcv; /* messages received */
+ abi_long ru_nsignals; /* signals received */
+ abi_long ru_nvcsw; /* voluntary context switches */
+ abi_long ru_nivcsw; /* involuntary " */
};
typedef struct {
@@ -225,8 +225,8 @@
};
struct target_dirent {
- target_long d_ino;
- target_long d_off;
+ abi_long d_ino;
+ abi_long d_off;
unsigned short d_reclen;
char d_name[256]; /* We must not include limits.h! */
};
@@ -241,20 +241,20 @@
/* mostly generic signal stuff */
-#define TARGET_SIG_DFL ((target_long)0) /* default signal handling */
-#define TARGET_SIG_IGN ((target_long)1) /* ignore signal */
-#define TARGET_SIG_ERR ((target_long)-1) /* error return from signal */
+#define TARGET_SIG_DFL ((abi_long)0) /* default signal handling */
+#define TARGET_SIG_IGN ((abi_long)1) /* ignore signal */
+#define TARGET_SIG_ERR ((abi_long)-1) /* error return from signal */
#ifdef TARGET_MIPS
#define TARGET_NSIG 128
#else
#define TARGET_NSIG 64
#endif
-#define TARGET_NSIG_BPW TARGET_LONG_BITS
+#define TARGET_NSIG_BPW TARGET_ABI_BITS
#define TARGET_NSIG_WORDS (TARGET_NSIG / TARGET_NSIG_BPW)
typedef struct {
- target_ulong sig[TARGET_NSIG_WORDS];
+ abi_ulong sig[TARGET_NSIG_WORDS];
} target_sigset_t;
#ifdef BSWAP_NEEDED
@@ -271,7 +271,7 @@
}
#endif
-static inline void target_siginitset(target_sigset_t *d, target_ulong set)
+static inline void target_siginitset(target_sigset_t *d, abi_ulong set)
{
int i;
d->sig[0] = set;
@@ -281,15 +281,15 @@
void host_to_target_sigset(target_sigset_t *d, const sigset_t *s);
void target_to_host_sigset(sigset_t *d, const target_sigset_t *s);
-void host_to_target_old_sigset(target_ulong *old_sigset,
+void host_to_target_old_sigset(abi_ulong *old_sigset,
const sigset_t *sigset);
void target_to_host_old_sigset(sigset_t *sigset,
- const target_ulong *old_sigset);
+ const abi_ulong *old_sigset);
struct target_sigaction;
int do_sigaction(int sig, const struct target_sigaction *act,
struct target_sigaction *oact);
-#if defined(TARGET_I386) || defined(TARGET_ARM) || defined(TARGET_SPARC) || defined(TARGET_PPC) || defined(TARGET_MIPS) || defined (TARGET_SH4) || defined(TARGET_M68K) || defined(TARGET_ALPHA)
+#if defined(TARGET_I386) || defined(TARGET_ARM) || defined(TARGET_SPARC) || defined(TARGET_PPC) || defined(TARGET_MIPS) || defined (TARGET_SH4) || defined(TARGET_M68K) || defined(TARGET_ALPHA) || defined(TARGET_CRIS)
#if defined(TARGET_SPARC)
#define TARGET_SA_NOCLDSTOP 8u
@@ -307,7 +307,9 @@
#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 */
+#endif
#else
#define TARGET_SA_NOCLDSTOP 0x00000001
#define TARGET_SA_NOCLDWAIT 0x00000002 /* not supported yet */
@@ -447,40 +449,44 @@
#if defined(TARGET_MIPS)
struct target_sigaction {
- target_ulong sa_flags;
- target_ulong _sa_handler;
+ uint32_t sa_flags;
+#if defined(TARGET_MIPSN32)
+ uint32_t _sa_handler;
+#else
+ abi_ulong _sa_handler;
+#endif
target_sigset_t sa_mask;
};
#else
struct target_old_sigaction {
- target_ulong _sa_handler;
- target_ulong sa_mask;
- target_ulong sa_flags;
- target_ulong sa_restorer;
+ abi_ulong _sa_handler;
+ abi_ulong sa_mask;
+ abi_ulong sa_flags;
+ abi_ulong sa_restorer;
};
struct target_sigaction {
- target_ulong _sa_handler;
- target_ulong sa_flags;
- target_ulong sa_restorer;
+ abi_ulong _sa_handler;
+ abi_ulong sa_flags;
+ abi_ulong sa_restorer;
target_sigset_t sa_mask;
};
#endif
typedef union target_sigval {
int sival_int;
- target_ulong sival_ptr;
+ abi_ulong sival_ptr;
} target_sigval_t;
#if 0
#if defined (TARGET_SPARC)
typedef struct {
struct {
- target_ulong psr;
- target_ulong pc;
- target_ulong npc;
- target_ulong y;
- target_ulong u_regs[16]; /* globals and ins */
+ abi_ulong psr;
+ abi_ulong pc;
+ abi_ulong npc;
+ abi_ulong y;
+ abi_ulong u_regs[16]; /* globals and ins */
} si_regs;
int si_mask;
} __siginfo_t;
@@ -538,7 +544,7 @@
/* SIGILL, SIGFPE, SIGSEGV, SIGBUS */
struct {
- target_ulong _addr; /* faulting insn/memory ref. */
+ abi_ulong _addr; /* faulting insn/memory ref. */
} _sigfault;
/* SIGPOLL */
@@ -608,8 +614,8 @@
#endif /* defined(TARGET_I386) || defined(TARGET_ARM) */
struct target_rlimit {
- target_ulong rlim_cur;
- target_ulong rlim_max;
+ abi_ulong rlim_cur;
+ abi_ulong rlim_max;
};
struct target_pollfd {
@@ -860,6 +866,8 @@
#define TARGET_MAP_EXECUTABLE 0x4000 /* mark it as an executable */
#define TARGET_MAP_LOCKED 0x8000 /* pages are locked */
#define TARGET_MAP_NORESERVE 0x0400 /* don't check for reservations */
+#define TARGET_MAP_POPULATE 0x10000 /* populate (prefault) pagetables */
+#define TARGET_MAP_NONBLOCK 0x20000 /* do not block on IO */
#else
#define TARGET_MAP_ANONYMOUS 0x20 /* don't use a file */
#define TARGET_MAP_GROWSDOWN 0x0100 /* stack-like segment */
@@ -872,30 +880,32 @@
#define TARGET_MAP_LOCKED 0x2000 /* pages are locked */
#define TARGET_MAP_NORESERVE 0x4000 /* don't check for reservations */
#endif
+#define TARGET_MAP_POPULATE 0x8000 /* populate (prefault) pagetables */
+#define TARGET_MAP_NONBLOCK 0x10000 /* do not block on IO */
#endif
-#if defined(TARGET_I386) || defined(TARGET_ARM)
+#if defined(TARGET_I386) || defined(TARGET_ARM) || defined(TARGET_CRIS)
struct target_stat {
unsigned short st_dev;
unsigned short __pad1;
- target_ulong st_ino;
+ abi_ulong st_ino;
unsigned short st_mode;
unsigned short st_nlink;
unsigned short st_uid;
unsigned short st_gid;
unsigned short st_rdev;
unsigned short __pad2;
- target_ulong st_size;
- target_ulong st_blksize;
- target_ulong st_blocks;
- target_ulong target_st_atime;
- target_ulong __unused1;
- target_ulong target_st_mtime;
- target_ulong __unused2;
- target_ulong target_st_ctime;
- target_ulong __unused3;
- target_ulong __unused4;
- target_ulong __unused5;
+ abi_ulong st_size;
+ abi_ulong st_blksize;
+ abi_ulong st_blocks;
+ abi_ulong target_st_atime;
+ abi_ulong __unused1;
+ abi_ulong target_st_mtime;
+ abi_ulong __unused2;
+ abi_ulong target_st_ctime;
+ abi_ulong __unused3;
+ abi_ulong __unused4;
+ abi_ulong __unused5;
};
/* This matches struct stat64 in glibc2.1, hence the absolutely
@@ -906,31 +916,31 @@
unsigned char __pad0[10];
#define TARGET_STAT64_HAS_BROKEN_ST_INO 1
- target_ulong __st_ino;
+ abi_ulong __st_ino;
unsigned int st_mode;
unsigned int st_nlink;
- target_ulong st_uid;
- target_ulong st_gid;
+ abi_ulong st_uid;
+ abi_ulong st_gid;
unsigned short st_rdev;
unsigned char __pad3[10];
long long st_size;
- target_ulong st_blksize;
+ abi_ulong st_blksize;
- target_ulong st_blocks; /* Number 512-byte blocks allocated. */
- target_ulong __pad4; /* future possible st_blocks high bits */
+ abi_ulong st_blocks; /* Number 512-byte blocks allocated. */
+ abi_ulong __pad4; /* future possible st_blocks high bits */
- target_ulong target_st_atime;
- target_ulong __pad5;
+ abi_ulong target_st_atime;
+ abi_ulong __pad5;
- target_ulong target_st_mtime;
- target_ulong __pad6;
+ abi_ulong target_st_mtime;
+ abi_ulong __pad6;
- target_ulong target_st_ctime;
- target_ulong __pad7; /* will be high 32 bits of ctime someday */
+ abi_ulong target_st_ctime;
+ abi_ulong __pad7; /* will be high 32 bits of ctime someday */
unsigned long long st_ino;
} __attribute__((packed));
@@ -939,50 +949,50 @@
struct target_eabi_stat64 {
unsigned long long st_dev;
unsigned int __pad1;
- target_ulong __st_ino;
+ abi_ulong __st_ino;
unsigned int st_mode;
unsigned int st_nlink;
- target_ulong st_uid;
- target_ulong st_gid;
+ abi_ulong st_uid;
+ abi_ulong st_gid;
unsigned long long st_rdev;
unsigned int __pad2[2];
long long st_size;
- target_ulong st_blksize;
+ abi_ulong st_blksize;
unsigned int __pad3;
unsigned long long st_blocks;
- target_ulong target_st_atime;
- target_ulong target_st_atime_nsec;
+ abi_ulong target_st_atime;
+ abi_ulong target_st_atime_nsec;
- target_ulong target_st_mtime;
- target_ulong target_st_mtime_nsec;
+ abi_ulong target_st_mtime;
+ abi_ulong target_st_mtime_nsec;
- target_ulong target_st_ctime;
- target_ulong target_st_ctime_nsec;
+ abi_ulong target_st_ctime;
+ abi_ulong target_st_ctime_nsec;
unsigned long long st_ino;
} __attribute__ ((packed));
#endif
-#elif defined(TARGET_SPARC64)
+#elif defined(TARGET_SPARC64) && !defined(TARGET_ABI32)
struct target_stat {
unsigned int st_dev;
- target_ulong st_ino;
+ abi_ulong st_ino;
unsigned int st_mode;
unsigned int st_nlink;
unsigned int st_uid;
unsigned int st_gid;
unsigned int st_rdev;
- target_long st_size;
- target_long target_st_atime;
- target_long target_st_mtime;
- target_long target_st_ctime;
- target_long st_blksize;
- target_long st_blocks;
- target_ulong __unused4[2];
+ abi_long st_size;
+ abi_long target_st_atime;
+ abi_long target_st_mtime;
+ abi_long target_st_ctime;
+ abi_long st_blksize;
+ abi_long st_blocks;
+ abi_ulong __unused4[2];
};
struct target_stat64 {
@@ -1006,38 +1016,38 @@
unsigned char __pad4[4];
unsigned int st_blocks;
- target_ulong target_st_atime;
- target_ulong __unused1;
+ abi_ulong target_st_atime;
+ abi_ulong __unused1;
- target_ulong target_st_mtime;
- target_ulong __unused2;
+ abi_ulong target_st_mtime;
+ abi_ulong __unused2;
- target_ulong target_st_ctime;
- target_ulong __unused3;
+ abi_ulong target_st_ctime;
+ abi_ulong __unused3;
- target_ulong __unused4[3];
+ abi_ulong __unused4[3];
};
#elif defined(TARGET_SPARC)
struct target_stat {
unsigned short st_dev;
- target_ulong st_ino;
+ abi_ulong st_ino;
unsigned short st_mode;
short st_nlink;
unsigned short st_uid;
unsigned short st_gid;
unsigned short st_rdev;
- target_long st_size;
- target_long target_st_atime;
- target_ulong __unused1;
- target_long target_st_mtime;
- target_ulong __unused2;
- target_long target_st_ctime;
- target_ulong __unused3;
- target_long st_blksize;
- target_long st_blocks;
- target_ulong __unused4[2];
+ abi_long st_size;
+ abi_long target_st_atime;
+ abi_ulong __unused1;
+ abi_long target_st_mtime;
+ abi_ulong __unused2;
+ abi_long target_st_ctime;
+ abi_ulong __unused3;
+ abi_long st_blksize;
+ abi_long st_blocks;
+ abi_ulong __unused4[2];
};
struct target_stat64 {
@@ -1080,23 +1090,23 @@
struct target_stat {
unsigned short st_dev;
- target_ulong st_ino;
+ abi_ulong st_ino;
unsigned int st_mode;
unsigned short st_nlink;
unsigned int st_uid;
unsigned int st_gid;
unsigned short st_rdev;
- target_ulong st_size;
- target_ulong st_blksize;
- target_ulong st_blocks;
- target_ulong target_st_atime;
- target_ulong __unused1;
- target_ulong target_st_mtime;
- target_ulong __unused2;
- target_ulong target_st_ctime;
- target_ulong __unused3;
- target_ulong __unused4;
- target_ulong __unused5;
+ abi_ulong st_size;
+ abi_ulong st_blksize;
+ abi_ulong st_blocks;
+ abi_ulong target_st_atime;
+ abi_ulong __unused1;
+ abi_ulong target_st_mtime;
+ abi_ulong __unused2;
+ abi_ulong target_st_ctime;
+ abi_ulong __unused3;
+ abi_ulong __unused4;
+ abi_ulong __unused5;
};
struct target_stat64 {
@@ -1109,17 +1119,17 @@
unsigned long long st_rdev;
long long pad0;
long long st_size;
- target_ulong st_blksize;
- target_ulong pad1;
+ abi_ulong st_blksize;
+ abi_ulong pad1;
long long st_blocks; /* Number 512-byte blocks allocated. */
- target_ulong target_st_atime;
- target_ulong target_st_atime_nsec;
- target_ulong target_st_mtime;
- target_ulong target_st_mtime_nsec;
- target_ulong target_st_ctime;
- target_ulong target_st_ctime_nsec;
- target_ulong __unused4;
- target_ulong __unused5;
+ abi_ulong target_st_atime;
+ abi_ulong target_st_atime_nsec;
+ abi_ulong target_st_mtime;
+ abi_ulong target_st_mtime_nsec;
+ abi_ulong target_st_ctime;
+ abi_ulong target_st_ctime_nsec;
+ abi_ulong __unused4;
+ abi_ulong __unused5;
};
#elif defined(TARGET_M68K)
@@ -1127,24 +1137,24 @@
struct target_stat {
unsigned short st_dev;
unsigned short __pad1;
- target_ulong st_ino;
+ abi_ulong st_ino;
unsigned short st_mode;
unsigned short st_nlink;
unsigned short st_uid;
unsigned short st_gid;
unsigned short st_rdev;
unsigned short __pad2;
- target_ulong st_size;
- target_ulong st_blksize;
- target_ulong st_blocks;
- target_ulong target_st_atime;
- target_ulong __unused1;
- target_ulong target_st_mtime;
- target_ulong __unused2;
- target_ulong target_st_ctime;
- target_ulong __unused3;
- target_ulong __unused4;
- target_ulong __unused5;
+ abi_ulong st_size;
+ abi_ulong st_blksize;
+ abi_ulong st_blocks;
+ abi_ulong target_st_atime;
+ abi_ulong __unused1;
+ abi_ulong target_st_mtime;
+ abi_ulong __unused2;
+ abi_ulong target_st_ctime;
+ abi_ulong __unused3;
+ abi_ulong __unused4;
+ abi_ulong __unused5;
};
/* This matches struct stat64 in glibc2.1, hence the absolutely
@@ -1155,62 +1165,172 @@
unsigned char __pad1[2];
#define TARGET_STAT64_HAS_BROKEN_ST_INO 1
- target_ulong __st_ino;
+ abi_ulong __st_ino;
unsigned int st_mode;
unsigned int st_nlink;
- target_ulong st_uid;
- target_ulong st_gid;
+ abi_ulong st_uid;
+ abi_ulong st_gid;
unsigned long long st_rdev;
unsigned char __pad3[2];
long long st_size;
- target_ulong st_blksize;
+ abi_ulong st_blksize;
- target_ulong __pad4; /* future possible st_blocks high bits */
- target_ulong st_blocks; /* Number 512-byte blocks allocated. */
+ abi_ulong __pad4; /* future possible st_blocks high bits */
+ abi_ulong st_blocks; /* Number 512-byte blocks allocated. */
- target_ulong target_st_atime;
- target_ulong target_st_atime_nsec;
+ abi_ulong target_st_atime;
+ abi_ulong target_st_atime_nsec;
- target_ulong target_st_mtime;
- target_ulong target_st_mtime_nsec;
+ abi_ulong target_st_mtime;
+ abi_ulong target_st_mtime_nsec;
- target_ulong target_st_ctime;
- target_ulong target_st_ctime_nsec;
+ abi_ulong target_st_ctime;
+ abi_ulong target_st_ctime_nsec;
unsigned long long st_ino;
} __attribute__((packed));
+#elif defined(TARGET_MIPS64)
+
+/* The memory layout is the same as of struct stat64 of the 32-bit kernel. */
+struct target_stat {
+ unsigned int st_dev;
+ unsigned int st_pad0[3]; /* Reserved for st_dev expansion */
+
+ abi_ulong st_ino;
+
+ unsigned int st_mode;
+ unsigned int st_nlink;
+
+ int st_uid;
+ int st_gid;
+
+ unsigned int st_rdev;
+ unsigned int st_pad1[3]; /* Reserved for st_rdev expansion */
+
+ abi_ulong st_size;
+
+ /*
+ * Actually this should be timestruc_t st_atime, st_mtime and st_ctime
+ * but we don't have it under Linux.
+ */
+ unsigned int target_st_atime;
+ unsigned int target_st_atime_nsec;
+
+ unsigned int target_st_mtime;
+ unsigned int target_st_mtime_nsec;
+
+ unsigned int target_st_ctime;
+ unsigned int target_st_ctime_nsec;
+
+ unsigned int st_blksize;
+ unsigned int st_pad2;
+
+ abi_ulong st_blocks;
+};
+
+#elif defined(TARGET_MIPSN32)
+
+struct target_stat {
+ unsigned st_dev;
+ int st_pad1[3]; /* Reserved for network id */
+ unsigned int st_ino;
+ unsigned int st_mode;
+ unsigned int st_nlink;
+ int st_uid;
+ int st_gid;
+ unsigned st_rdev;
+ unsigned int st_pad2[2];
+ unsigned int st_size;
+ unsigned int st_pad3;
+ /*
+ * Actually this should be timestruc_t st_atime, st_mtime and st_ctime
+ * but we don't have it under Linux.
+ */
+ unsigned int target_st_atime;
+ unsigned int target_st_atime_nsec;
+ unsigned int target_st_mtime;
+ unsigned int target_st_mtime_nsec;
+ unsigned int target_st_ctime;
+ unsigned int target_st_ctime_nsec;
+ unsigned int st_blksize;
+ unsigned int st_blocks;
+ unsigned int st_pad4[14];
+};
+
+/*
+ * This matches struct stat64 in glibc2.1, hence the absolutely insane
+ * amounts of padding around dev_t's. The memory layout is the same as of
+ * struct stat of the 64-bit kernel.
+ */
+
+struct target_stat64 {
+ unsigned int st_dev;
+ unsigned int st_pad0[3]; /* Reserved for st_dev expansion */
+
+ target_ulong st_ino;
+
+ unsigned int st_mode;
+ unsigned int st_nlink;
+
+ int st_uid;
+ int st_gid;
+
+ unsigned int st_rdev;
+ unsigned int st_pad1[3]; /* Reserved for st_rdev expansion */
+
+ int st_size;
+
+ /*
+ * Actually this should be timestruc_t st_atime, st_mtime and st_ctime
+ * but we don't have it under Linux.
+ */
+ int target_st_atime;
+ unsigned int target_st_atime_nsec; /* Reserved for st_atime expansion */
+
+ int target_st_mtime;
+ unsigned int target_st_mtime_nsec; /* Reserved for st_mtime expansion */
+
+ int target_st_ctime;
+ unsigned int target_st_ctime_nsec; /* Reserved for st_ctime expansion */
+
+ unsigned int st_blksize;
+ unsigned int st_pad2;
+
+ int st_blocks;
+};
+
#elif defined(TARGET_MIPS)
struct target_stat {
unsigned st_dev;
- target_long st_pad1[3]; /* Reserved for network id */
- target_ulong st_ino;
+ abi_long st_pad1[3]; /* Reserved for network id */
+ abi_ulong st_ino;
unsigned int st_mode;
unsigned int st_nlink;
int st_uid;
int st_gid;
unsigned st_rdev;
- target_long st_pad2[2];
- target_long st_size;
- target_long st_pad3;
+ abi_long st_pad2[2];
+ abi_long st_size;
+ abi_long st_pad3;
/*
* Actually this should be timestruc_t st_atime, st_mtime and st_ctime
* but we don't have it under Linux.
*/
- target_long target_st_atime;
- target_long target_st_atime_nsec;
- target_long target_st_mtime;
- target_long target_st_mtime_nsec;
- target_long target_st_ctime;
- target_long target_st_ctime_nsec;
- target_long st_blksize;
- target_long st_blocks;
- target_long st_pad4[14];
+ abi_long target_st_atime;
+ abi_long target_st_atime_nsec;
+ abi_long target_st_mtime;
+ abi_long target_st_mtime_nsec;
+ abi_long target_st_ctime;
+ abi_long target_st_ctime_nsec;
+ abi_long st_blksize;
+ abi_long st_blocks;
+ abi_long st_pad4[14];
};
/*
@@ -1220,8 +1340,8 @@
*/
struct target_stat64 {
- target_ulong st_dev;
- target_ulong st_pad0[3]; /* Reserved for st_dev expansion */
+ abi_ulong st_dev;
+ abi_ulong st_pad0[3]; /* Reserved for st_dev expansion */
uint64_t st_ino;
@@ -1231,8 +1351,8 @@
int st_uid;
int st_gid;
- target_ulong st_rdev;
- target_ulong st_pad1[3]; /* Reserved for st_rdev expansion */
+ abi_ulong st_rdev;
+ abi_ulong st_pad1[3]; /* Reserved for st_rdev expansion */
int64_t st_size;
@@ -1240,17 +1360,17 @@
* Actually this should be timestruc_t st_atime, st_mtime and st_ctime
* but we don't have it under Linux.
*/
- target_long target_st_atime;
- target_ulong target_st_atime_nsec; /* Reserved for st_atime expansion */
+ abi_long target_st_atime;
+ abi_ulong target_st_atime_nsec; /* Reserved for st_atime expansion */
- target_long target_st_mtime;
- target_ulong target_st_mtime_nsec; /* Reserved for st_mtime expansion */
+ abi_long target_st_mtime;
+ abi_ulong target_st_mtime_nsec; /* Reserved for st_mtime expansion */
- target_long target_st_ctime;
- target_ulong target_st_ctime_nsec; /* Reserved for st_ctime expansion */
+ abi_long target_st_ctime;
+ abi_ulong target_st_ctime_nsec; /* Reserved for st_ctime expansion */
- target_ulong st_blksize;
- target_ulong st_pad2;
+ abi_ulong st_blksize;
+ abi_ulong st_pad2;
int64_t st_blocks;
};
@@ -1265,10 +1385,10 @@
unsigned int st_uid;
unsigned int st_gid;
unsigned int st_rdev;
- target_long st_size;
- target_ulong target_st_atime;
- target_ulong target_st_mtime;
- target_ulong target_st_ctime;
+ abi_long st_size;
+ abi_ulong target_st_atime;
+ abi_ulong target_st_mtime;
+ abi_ulong target_st_ctime;
unsigned int st_blksize;
unsigned int st_blocks;
unsigned int st_flags;
@@ -1276,11 +1396,11 @@
};
struct target_stat64 {
- target_ulong st_dev;
- target_ulong st_ino;
- target_ulong st_rdev;
- target_long st_size;
- target_ulong st_blocks;
+ abi_ulong st_dev;
+ abi_ulong st_ino;
+ abi_ulong st_rdev;
+ abi_long st_size;
+ abi_ulong st_blocks;
unsigned int st_mode;
unsigned int st_uid;
@@ -1289,36 +1409,36 @@
unsigned int st_nlink;
unsigned int __pad0;
- target_ulong target_st_atime;
- target_ulong target_st_atime_nsec;
- target_ulong target_st_mtime;
- target_ulong target_st_mtime_nsec;
- target_ulong target_st_ctime;
- target_ulong target_st_ctime_nsec;
- target_long __unused[3];
+ abi_ulong target_st_atime;
+ abi_ulong target_st_atime_nsec;
+ abi_ulong target_st_mtime;
+ abi_ulong target_st_mtime_nsec;
+ abi_ulong target_st_ctime;
+ abi_ulong target_st_ctime_nsec;
+ abi_long __unused[3];
};
#elif defined(TARGET_SH4)
struct target_stat {
- target_ulong st_dev;
- target_ulong st_ino;
+ abi_ulong st_dev;
+ abi_ulong st_ino;
unsigned short st_mode;
unsigned short st_nlink;
unsigned short st_uid;
unsigned short st_gid;
- target_ulong st_rdev;
- target_ulong st_size;
- target_ulong st_blksize;
- target_ulong st_blocks;
- target_ulong target_st_atime;
- target_ulong target_st_atime_nsec;
- target_ulong target_st_mtime;
- target_ulong target_st_mtime_nsec;
- target_ulong target_st_ctime;
- target_ulong target_st_ctime_nsec;
- target_ulong __unused4;
- target_ulong __unused5;
+ abi_ulong st_rdev;
+ abi_ulong st_size;
+ abi_ulong st_blksize;
+ abi_ulong st_blocks;
+ abi_ulong target_st_atime;
+ abi_ulong target_st_atime_nsec;
+ abi_ulong target_st_mtime;
+ abi_ulong target_st_mtime_nsec;
+ abi_ulong target_st_ctime;
+ abi_ulong target_st_ctime_nsec;
+ abi_ulong __unused4;
+ abi_ulong __unused5;
};
/* This matches struct stat64 in glibc2.1, hence the absolutely
@@ -1329,30 +1449,30 @@
unsigned char __pad0[4];
#define TARGET_STAT64_HAS_BROKEN_ST_INO 1
- target_ulong __st_ino;
+ abi_ulong __st_ino;
unsigned int st_mode;
unsigned int st_nlink;
- target_ulong st_uid;
- target_ulong st_gid;
+ abi_ulong st_uid;
+ abi_ulong st_gid;
unsigned long long st_rdev;
unsigned char __pad3[4];
long long st_size;
- target_ulong st_blksize;
+ abi_ulong st_blksize;
unsigned long long st_blocks; /* Number 512-byte blocks allocated. */
- target_ulong target_st_atime;
- target_ulong target_st_atime_nsec;
+ abi_ulong target_st_atime;
+ abi_ulong target_st_atime_nsec;
- target_ulong target_st_mtime;
- target_ulong target_st_mtime_nsec;
+ abi_ulong target_st_mtime;
+ abi_ulong target_st_mtime_nsec;
- target_ulong target_st_ctime;
- target_ulong target_st_ctime_nsec;
+ abi_ulong target_st_ctime;
+ abi_ulong target_st_ctime_nsec;
unsigned long long st_ino;
};
@@ -1366,22 +1486,40 @@
} target_fsid_t;
#ifdef TARGET_MIPS
+#ifdef TARGET_MIPSN32
struct target_statfs {
- target_long f_type;
- target_long f_bsize;
- target_long f_frsize; /* Fragment size - unsupported */
- target_long f_blocks;
- target_long f_bfree;
- target_long f_files;
- target_long f_ffree;
- target_long f_bavail;
+ int32_t f_type;
+ int32_t f_bsize;
+ int32_t f_frsize; /* Fragment size - unsupported */
+ int32_t f_blocks;
+ int32_t f_bfree;
+ int32_t f_files;
+ int32_t f_ffree;
+ int32_t f_bavail;
/* Linux specials */
target_fsid_t f_fsid;
- target_long f_namelen;
- target_long f_spare[6];
+ int32_t f_namelen;
+ int32_t f_spare[6];
};
+#else
+struct target_statfs {
+ abi_long f_type;
+ abi_long f_bsize;
+ abi_long f_frsize; /* Fragment size - unsupported */
+ abi_long f_blocks;
+ abi_long f_bfree;
+ abi_long f_files;
+ abi_long f_ffree;
+ abi_long f_bavail;
+ /* Linux specials */
+ target_fsid_t f_fsid;
+ abi_long f_namelen;
+ abi_long f_spare[6];
+};
+#endif
+
struct target_statfs64 {
uint32_t f_type;
uint32_t f_bsize;
@@ -1550,8 +1688,8 @@
struct target_flock {
short l_type;
short l_whence;
- target_ulong l_start;
- target_ulong l_len;
+ abi_ulong l_start;
+ abi_ulong l_len;
int l_pid;
};
@@ -1718,20 +1856,20 @@
#define TARGET_VFAT_IOCTL_READDIR_SHORT TARGET_IORU('r', 2)
struct target_sysinfo {
- target_long uptime; /* Seconds since boot */
- target_ulong loads[3]; /* 1, 5, and 15 minute load averages */
- target_ulong totalram; /* Total usable main memory size */
- target_ulong freeram; /* Available memory size */
- target_ulong sharedram; /* Amount of shared memory */
- target_ulong bufferram; /* Memory used by buffers */
- target_ulong totalswap; /* Total swap space size */
- target_ulong freeswap; /* swap space still available */
+ abi_long uptime; /* Seconds since boot */
+ abi_ulong loads[3]; /* 1, 5, and 15 minute load averages */
+ abi_ulong totalram; /* Total usable main memory size */
+ abi_ulong freeram; /* Available memory size */
+ abi_ulong sharedram; /* Amount of shared memory */
+ abi_ulong bufferram; /* Memory used by buffers */
+ abi_ulong totalswap; /* Total swap space size */
+ abi_ulong freeswap; /* swap space still available */
unsigned short procs; /* Number of current processes */
unsigned short pad; /* explicit padding for m68k */
- target_ulong totalhigh; /* Total high memory size */
- target_ulong freehigh; /* Available high memory size */
+ abi_ulong totalhigh; /* Total high memory size */
+ abi_ulong freehigh; /* Available high memory size */
unsigned int mem_unit; /* Memory unit size in bytes */
- char _f[20-2*sizeof(target_long)-sizeof(int)]; /* Padding: libc5 uses this.. */
+ char _f[20-2*sizeof(abi_long)-sizeof(int)]; /* Padding: libc5 uses this.. */
};
#include "socket.h"
Modified: trunk/src/host/qemu-neo1973/linux-user/vm86.c
===================================================================
--- trunk/src/host/qemu-neo1973/linux-user/vm86.c 2007-10-29 20:40:05 UTC (rev 3302)
+++ trunk/src/host/qemu-neo1973/linux-user/vm86.c 2007-10-29 21:14:04 UTC (rev 3303)
@@ -381,7 +381,7 @@
}
}
-int do_vm86(CPUX86State *env, long subfunction, target_ulong vm86_addr)
+int do_vm86(CPUX86State *env, long subfunction, abi_ulong vm86_addr)
{
TaskState *ts = env->opaque;
struct target_vm86plus_struct * target_v86;
Modified: trunk/src/host/qemu-neo1973/linux-user/x86_64/syscall.h
===================================================================
--- trunk/src/host/qemu-neo1973/linux-user/x86_64/syscall.h 2007-10-29 20:40:05 UTC (rev 3302)
+++ trunk/src/host/qemu-neo1973/linux-user/x86_64/syscall.h 2007-10-29 21:14:04 UTC (rev 3303)
@@ -2,30 +2,30 @@
#define __USER_DS (0x2B)
struct target_pt_regs {
- target_ulong r15;
- target_ulong r14;
- target_ulong r13;
- target_ulong r12;
- target_ulong rbp;
- target_ulong rbx;
+ abi_ulong r15;
+ abi_ulong r14;
+ abi_ulong r13;
+ abi_ulong r12;
+ abi_ulong rbp;
+ abi_ulong rbx;
/* arguments: non interrupts/non tracing syscalls only save upto here*/
- target_ulong r11;
- target_ulong r10;
- target_ulong r9;
- target_ulong r8;
- target_ulong rax;
- target_ulong rcx;
- target_ulong rdx;
- target_ulong rsi;
- target_ulong rdi;
- target_ulong orig_rax;
+ abi_ulong r11;
+ abi_ulong r10;
+ abi_ulong r9;
+ abi_ulong r8;
+ abi_ulong rax;
+ abi_ulong rcx;
+ abi_ulong rdx;
+ abi_ulong rsi;
+ abi_ulong rdi;
+ abi_ulong orig_rax;
/* end of arguments */
/* cpu exception frame or undefined */
- target_ulong rip;
- target_ulong cs;
- target_ulong eflags;
- target_ulong rsp;
- target_ulong ss;
+ abi_ulong rip;
+ abi_ulong cs;
+ abi_ulong eflags;
+ abi_ulong rsp;
+ abi_ulong ss;
/* top of stack page */
};
@@ -41,7 +41,7 @@
#if 0 // Redefine this
struct target_modify_ldt_ldt_s {
unsigned int entry_number;
- target_ulong base_addr;
+ abi_ulong base_addr;
unsigned int limit;
unsigned int seg_32bit:1;
unsigned int contents:2;
@@ -54,7 +54,7 @@
#else
struct target_modify_ldt_ldt_s {
unsigned int entry_number;
- target_ulong base_addr;
+ abi_ulong base_addr;
unsigned int limit;
unsigned int flags;
};
@@ -71,8 +71,8 @@
unsigned short __pad1;
unsigned short seq;
unsigned short __pad2;
- target_ulong __unused1;
- target_ulong __unused2;
+ abi_ulong __unused1;
+ abi_ulong __unused2;
};
struct target_msqid64_ds {
@@ -80,13 +80,13 @@
unsigned int msg_stime; /* last msgsnd time */
unsigned int msg_rtime; /* last msgrcv time */
unsigned int msg_ctime; /* last change time */
- target_ulong msg_cbytes; /* current number of bytes on queue */
- target_ulong msg_qnum; /* number of messages in queue */
- target_ulong msg_qbytes; /* max number of bytes on queue */
+ abi_ulong msg_cbytes; /* current number of bytes on queue */
+ abi_ulong msg_qnum; /* number of messages in queue */
+ abi_ulong msg_qbytes; /* max number of bytes on queue */
unsigned int msg_lspid; /* pid of last msgsnd */
unsigned int msg_lrpid; /* last receive pid */
- target_ulong __unused4;
- target_ulong __unused5;
+ abi_ulong __unused4;
+ abi_ulong __unused5;
};
#define UNAME_MACHINE "x86_64"
Modified: trunk/src/host/qemu-neo1973/linux-user/x86_64/syscall_nr.h
===================================================================
--- trunk/src/host/qemu-neo1973/linux-user/x86_64/syscall_nr.h 2007-10-29 20:40:05 UTC (rev 3302)
+++ trunk/src/host/qemu-neo1973/linux-user/x86_64/syscall_nr.h 2007-10-29 21:14:04 UTC (rev 3303)
@@ -278,3 +278,9 @@
#define TARGET_NR_sync_file_range 277
#define TARGET_NR_vmsplice 278
#define TARGET_NR_move_pages 279
+#define TARGET_NR_utimensat 280
+#define TARGET_NR_epoll_pwait 281
+#define TARGET_NR_signalfd 282
+#define TARGET_NR_timerfd 283
+#define TARGET_NR_eventfd 284
+#define TARGET_NR_fallocate 285
Added: trunk/src/host/qemu-neo1973/linux-user/x86_64/target_signal.h
===================================================================
--- trunk/src/host/qemu-neo1973/linux-user/x86_64/target_signal.h 2007-10-29 20:40:05 UTC (rev 3302)
+++ trunk/src/host/qemu-neo1973/linux-user/x86_64/target_signal.h 2007-10-29 21:14:04 UTC (rev 3303)
@@ -0,0 +1,29 @@
+#ifndef TARGET_SIGNAL_H
+#define TARGET_SIGNAL_H
+
+#include "cpu.h"
+
+/* this struct defines a stack used during syscall handling */
+
+typedef struct target_sigaltstack {
+ abi_ulong ss_sp;
+ abi_long ss_flags;
+ abi_ulong ss_size;
+} target_stack_t;
+
+
+/*
+ * sigaltstack controls
+ */
+#define TARGET_SS_ONSTACK 1
+#define TARGET_SS_DISABLE 2
+
+#define TARGET_MINSIGSTKSZ 2048
+#define TARGET_SIGSTKSZ 8192
+
+static inline abi_ulong get_sp_from_cpustate(CPUX86State *state)
+{
+ return state->regs[R_ESP];
+}
+
+#endif /* TARGET_SIGNAL_H */
Modified: trunk/src/host/qemu-neo1973/loader.c
===================================================================
--- trunk/src/host/qemu-neo1973/loader.c 2007-10-29 20:40:05 UTC (rev 3302)
+++ trunk/src/host/qemu-neo1973/loader.c 2007-10-29 21:14:04 UTC (rev 3303)
@@ -173,6 +173,7 @@
#define SZ 32
#define elf_word uint32_t
+#define elf_sword int32_t
#define bswapSZs bswap32s
#include "elf_ops.h"
@@ -182,6 +183,7 @@
#undef elf_sym
#undef elf_note
#undef elf_word
+#undef elf_sword
#undef bswapSZs
#undef SZ
#define elfhdr elf64_hdr
@@ -190,6 +192,7 @@
#define elf_shdr elf64_shdr
#define elf_sym elf64_sym
#define elf_word uint64_t
+#define elf_sword int64_t
#define bswapSZs bswap64s
#define SZ 64
#include "elf_ops.h"
Modified: trunk/src/host/qemu-neo1973/monitor.c
===================================================================
--- trunk/src/host/qemu-neo1973/monitor.c 2007-10-29 20:40:05 UTC (rev 3302)
+++ trunk/src/host/qemu-neo1973/monitor.c 2007-10-29 21:14:04 UTC (rev 3303)
@@ -509,7 +509,7 @@
}
static void memory_dump(int count, int format, int wsize,
- target_ulong addr, int is_physical)
+ target_phys_addr_t addr, int is_physical)
{
CPUState *env;
int nb_per_line, l, line_size, i, max_digits, len;
@@ -572,7 +572,10 @@
}
while (len > 0) {
- term_printf(TARGET_FMT_lx ":", addr);
+ if (is_physical)
+ term_printf(TARGET_FMT_plx ":", addr);
+ else
+ term_printf(TARGET_FMT_lx ":", (target_ulong)addr);
l = len;
if (l > line_size)
l = line_size;
@@ -640,18 +643,24 @@
memory_dump(count, format, size, addr, 0);
}
+#if TARGET_PHYS_ADDR_BITS > 32
+#define GET_TPHYSADDR(h, l) (((uint64_t)(h) << 32) | (l))
+#else
+#define GET_TPHYSADDR(h, l) (l)
+#endif
+
static void do_physical_memory_dump(int count, int format, int size,
uint32_t addrh, uint32_t addrl)
{
- target_long addr = GET_TLONG(addrh, addrl);
+ target_phys_addr_t addr = GET_TPHYSADDR(addrh, addrl);
memory_dump(count, format, size, addr, 1);
}
static void do_print(int count, int format, int size, unsigned int valh, unsigned int vall)
{
- target_long val = GET_TLONG(valh, vall);
-#if TARGET_LONG_BITS == 32
+ target_phys_addr_t val = GET_TPHYSADDR(valh, vall);
+#if TARGET_PHYS_ADDR_BITS == 32
switch(format) {
case 'o':
term_printf("%#o", val);
@@ -1386,6 +1395,10 @@
{ "cpustats", "", do_info_cpu_stats,
"", "show CPU statistics", },
#endif
+#if defined(CONFIG_SLIRP)
+ { "slirp", "", do_info_slirp,
+ "", "show SLIRP statistics", },
+#endif
{ NULL, NULL, },
};
@@ -1442,7 +1455,7 @@
CPUState *env = mon_get_cpu();
if (!env)
return 0;
- return do_load_msr(env);
+ return env->msr;
}
static target_long monitor_get_xer (struct MonitorDef *md, int val)
@@ -1788,11 +1801,11 @@
}
}
-static target_long expr_sum(void);
+static int64_t expr_sum(void);
-static target_long expr_unary(void)
+static int64_t expr_unary(void)
{
- target_long n;
+ int64_t n;
char *p;
int ret;
@@ -1830,6 +1843,7 @@
case '$':
{
char buf[128], *q;
+ target_long reg;
pch++;
q = buf;
@@ -1844,11 +1858,12 @@
while (isspace(*pch))
pch++;
*q = 0;
- ret = get_monitor_def(&n, buf);
+ ret = get_monitor_def(®, buf);
if (ret == -1)
expr_error("unknown register");
else if (ret == -2)
expr_error("no cpu defined");
+ n = reg;
}
break;
case '\0':
@@ -1856,7 +1871,7 @@
n = 0;
break;
default:
-#if TARGET_LONG_BITS == 64
+#if TARGET_PHYS_ADDR_BITS > 32
n = strtoull(pch, &p, 0);
#else
n = strtoul(pch, &p, 0);
@@ -1873,9 +1888,9 @@
}
-static target_long expr_prod(void)
+static int64_t expr_prod(void)
{
- target_long val, val2;
+ int64_t val, val2;
int op;
val = expr_unary();
@@ -1904,9 +1919,9 @@
return val;
}
-static target_long expr_logic(void)
+static int64_t expr_logic(void)
{
- target_long val, val2;
+ int64_t val, val2;
int op;
val = expr_prod();
@@ -1932,9 +1947,9 @@
return val;
}
-static target_long expr_sum(void)
+static int64_t expr_sum(void)
{
- target_long val, val2;
+ int64_t val, val2;
int op;
val = expr_logic();
@@ -1952,7 +1967,7 @@
return val;
}
-static int get_expr(target_long *pval, const char **pp)
+static int get_expr(int64_t *pval, const char **pp)
{
pch = *pp;
if (setjmp(expr_env)) {
@@ -2215,7 +2230,8 @@
case 'i':
case 'l':
{
- target_long val;
+ int64_t val;
+
while (isspace(*p))
p++;
if (*typestr == '?' || *typestr == '.') {
@@ -2255,7 +2271,7 @@
} else {
if ((nb_args + 1) >= MAX_ARGS)
goto error_args;
-#if TARGET_LONG_BITS == 64
+#if TARGET_PHYS_ADDR_BITS > 32
args[nb_args++] = (void *)(long)((val >> 32) & 0xffffffff);
#else
args[nb_args++] = (void *)0;
Modified: trunk/src/host/qemu-neo1973/pc-bios/README
===================================================================
--- trunk/src/host/qemu-neo1973/pc-bios/README 2007-10-29 20:40:05 UTC (rev 3302)
+++ trunk/src/host/qemu-neo1973/pc-bios/README 2007-10-29 21:14:04 UTC (rev 3303)
@@ -14,7 +14,8 @@
- OpenBIOS (http://www.openbios.org/) is a free (GPL v2) portable
firmware implementation. The goal is to implement a 100% IEEE
1275-1994 (referred to as Open Firmware) compliant firmware.
- The included Sparc32 and Sparc64 images are built from SVN revision 169.
+ The included Sparc32 image is built from SVN revision 171 and
+ Sparc64 image from revision 169.
- The PXE roms come from Rom-o-Matic etherboot 5.4.2.
pcnet32:pcnet32 -- [0x1022,0x2000]
Modified: trunk/src/host/qemu-neo1973/pc-bios/openbios-sparc32
===================================================================
(Binary files differ)
Modified: trunk/src/host/qemu-neo1973/pc-bios/ppc_rom.bin
===================================================================
(Binary files differ)
Modified: trunk/src/host/qemu-neo1973/qemu-binfmt-conf.sh
===================================================================
--- trunk/src/host/qemu-neo1973/qemu-binfmt-conf.sh 2007-10-29 20:40:05 UTC (rev 3302)
+++ trunk/src/host/qemu-neo1973/qemu-binfmt-conf.sh 2007-10-29 21:14:04 UTC (rev 3303)
@@ -46,10 +46,14 @@
fi
if [ $cpu != "m68k" ] ; then
echo 'Please check cpu value and header information for m68k!'
- echo ':m68k:M::\x7fELF\x01\x02\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x04\x00\x08:\xff\xff\xff\xff\xff\xff\xff\x00\xff\xff\xff\xff\xff\xff\xff\xff\xff\xfe\xff\xff:/usr/local/bin/qemu-m68k:' > /proc/sys/fs/binfmt_misc/register
+ echo ':m68k:M::\x7fELF\x01\x02\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x02\x00\x04:\xff\xff\xff\xff\xff\xff\xff\x00\xff\xff\xff\xff\xff\xff\xff\xff\xff\xfe\xff\xff:/usr/local/bin/qemu-m68k:' > /proc/sys/fs/binfmt_misc/register
fi
if [ $cpu != "mips" ] ; then
# FIXME: We could use the other endianness on a MIPS host.
echo ':mips:M::\x7fELF\x01\x02\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x02\x00\x08:\xff\xff\xff\xff\xff\xff\xff\x00\xff\xff\xff\xff\xff\xff\xff\xff\xff\xfe\xff\xff:/usr/local/bin/qemu-mips:' > /proc/sys/fs/binfmt_misc/register
echo ':mipsel:M::\x7fELF\x01\x01\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x02\x00\x08\x00:\xff\xff\xff\xff\xff\xff\xff\x00\xff\xff\xff\xff\xff\xff\xff\xff\xfe\xff\xff\xff:/usr/local/bin/qemu-mipsel:' > /proc/sys/fs/binfmt_misc/register
+ echo ':mipsn32:M::\x7fELF\x01\x02\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x02\x00\x08:\xff\xff\xff\xff\xff\xff\xff\x00\xff\xff\xff\xff\xff\xff\xff\xff\xff\xfe\xff\xff:/usr/local/bin/qemu-mipsn32:' > /proc/sys/fs/binfmt_misc/register
+ echo ':mipsn32el:M::\x7fELF\x01\x01\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x02\x00\x08\x00:\xff\xff\xff\xff\xff\xff\xff\x00\xff\xff\xff\xff\xff\xff\xff\xff\xfe\xff\xff\xff:/usr/local/bin/qemu-mipsn32el:' > /proc/sys/fs/binfmt_misc/register
+ echo ':mips64:M::\x7fELF\x02\x02\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x02\x00\x08:\xff\xff\xff\xff\xff\xff\xff\x00\xff\xff\xff\xff\xff\xff\xff\xff\xff\xfe\xff\xff:/usr/local/bin/qemu-mips64:' > /proc/sys/fs/binfmt_misc/register
+ echo ':mips64el:M::\x7fELF\x02\x01\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x02\x00\x08\x00:\xff\xff\xff\xff\xff\xff\xff\x00\xff\xff\xff\xff\xff\xff\xff\xff\xfe\xff\xff\xff:/usr/local/bin/qemu-mips64el:' > /proc/sys/fs/binfmt_misc/register
fi
Modified: trunk/src/host/qemu-neo1973/qemu-doc.texi
===================================================================
--- trunk/src/host/qemu-neo1973/qemu-doc.texi 2007-10-29 20:40:05 UTC (rev 3302)
+++ trunk/src/host/qemu-neo1973/qemu-doc.texi 2007-10-29 21:14:04 UTC (rev 3303)
@@ -242,7 +242,8 @@
@item -smp n
Simulate an SMP system with @var{n} CPUs. On the PC target, up to 255
-CPUs are supported.
+CPUs are supported. On Sparc32 target, Linux limits the number of usable CPUs
+to 4.
@item -audio-help
@@ -1942,6 +1943,8 @@
Use the executable @file{qemu-system-sparc} to simulate a SparcStation 5
or SparcStation 10 (sun4m architecture). The emulation is somewhat complete.
+SMP up to 16 CPUs is supported, but Linux limits the number of usable CPUs
+to 4.
QEMU emulates the following sun4m peripherals:
@@ -1965,7 +1968,8 @@
CS4231 sound device (only on SS-5, not working yet)
@end itemize
-The number of peripherals is fixed in the architecture.
+The number of peripherals is fixed in the architecture. Maximum memory size
+depends on the machine type, for SS-5 it is 256MB and for SS-10 2047MB.
Since version 0.8.2, QEMU uses OpenBIOS
@url{http://www.openbios.org/}. OpenBIOS is a free (GPL v2) portable
@@ -2036,6 +2040,8 @@
The MIPS Malta prototype board "malta"
@item
An ACER Pica "pica61"
+ at item
+MIPS emulator pseudo board "mipssim"
@end itemize
The generic emulation is supported by Debian 'Etch' and is able to
@@ -2044,7 +2050,7 @@
@itemize @minus
@item
-MIPS 24Kf CPU
+A range of MIPS CPUs, default is the 24Kf
@item
PC style serial port
@item
@@ -2083,6 +2089,19 @@
IDE controller
@end itemize
+The mipssim pseudo board emulation provides an environment similiar
+to what the proprietary MIPS emulator uses for running Linux.
+It supports:
+
+ at itemize @minus
+ at item
+A range of MIPS CPUs, default is the 24Kf
+ at item
+PC style serial port
+ at item
+MIPSnet network emulation
+ at end itemize
+
@node ARM System emulator
@section ARM System emulator
@@ -2367,6 +2386,12 @@
The binary format is detected automatically.
+ at command{qemu-sparc32plus} can execute Sparc32 and SPARC32PLUS binaries
+(Sparc64 CPU, 32 bit ABI).
+
+ at command{qemu-sparc64} can execute some Sparc64 (Sparc64 CPU, 64 bit ABI) and
+SPARC32PLUS binaries (Sparc64 CPU, 32 bit ABI).
+
@node Mac OS X/Darwin User space emulator
@section Mac OS X/Darwin User space emulator
Modified: trunk/src/host/qemu-neo1973/qemu-img.c
===================================================================
--- trunk/src/host/qemu-neo1973/qemu-img.c 2007-10-29 20:40:05 UTC (rev 3302)
+++ trunk/src/host/qemu-neo1973/qemu-img.c 2007-10-29 21:14:04 UTC (rev 3303)
@@ -269,9 +269,9 @@
case 'e':
flags |= BLOCK_FLAG_ENCRYPT;
break;
- case '6':
+ case '6':
flags |= BLOCK_FLAG_COMPAT6;
- break;
+ break;
}
}
if (optind >= argc)
@@ -471,7 +471,7 @@
error("Compression not supported for this file format");
if (flags & BLOCK_FLAG_ENCRYPT && drv != &bdrv_qcow && drv != &bdrv_qcow2)
error("Encryption not supported for this file format");
- if (flags & BLOCK_FLAG_COMPRESS && drv != &bdrv_vmdk)
+ if (flags & BLOCK_FLAG_COMPAT6 && drv != &bdrv_vmdk)
error("Alternative compatibility level not supported for this file format");
if (flags & BLOCK_FLAG_ENCRYPT && flags & BLOCK_FLAG_COMPRESS)
error("Compression and encryption not supported at the same time");
Modified: trunk/src/host/qemu-neo1973/qemu-tech.texi
===================================================================
--- trunk/src/host/qemu-neo1973/qemu-tech.texi 2007-10-29 20:40:05 UTC (rev 3302)
+++ trunk/src/host/qemu-neo1973/qemu-tech.texi 2007-10-29 21:14:04 UTC (rev 3303)
@@ -199,9 +199,10 @@
@item Full SPARC V8 emulation, including privileged
instructions, FPU and MMU. SPARC V9 emulation includes most privileged
-instructions, FPU and I/D MMU, but misses most VIS instructions.
+and VIS instructions, FPU and I/D MMU. Alignment is fully enforced.
- at item Can run most 32-bit SPARC Linux binaries and some handcrafted 64-bit SPARC Linux binaries.
+ at item Can run most 32-bit SPARC Linux binaries, SPARC32PLUS Linux binaries and
+some 64-bit SPARC Linux binaries.
@end itemize
@@ -212,11 +213,8 @@
@item IPC syscalls are missing.
@item 128-bit floating point operations are not supported, though none of the
-real CPUs implement them either. FCMPE[SD] are not correctly
-implemented. Floating point exception support is untested.
+real CPUs implement them either. Floating point exception support is untested.
- at item Alignment is not enforced at all.
-
@item Atomic instructions are not correctly implemented.
@item Sparc64 emulators are not usable for anything yet.
Modified: trunk/src/host/qemu-neo1973/readline.c
===================================================================
--- trunk/src/host/qemu-neo1973/readline.c 2007-10-29 20:40:05 UTC (rev 3302)
+++ trunk/src/host/qemu-neo1973/readline.c 2007-10-29 21:14:04 UTC (rev 3303)
@@ -301,7 +301,7 @@
static void term_completion(void)
{
- int len, i, j, max_width, nb_cols;
+ int len, i, j, max_width, nb_cols, max_prefix;
char *cmdline;
nb_completions = 0;
@@ -328,11 +328,26 @@
} else {
term_printf("\n");
max_width = 0;
+ max_prefix = 0;
for(i = 0; i < nb_completions; i++) {
len = strlen(completions[i]);
+ if (i==0) {
+ max_prefix = len;
+ } else {
+ if (len < max_prefix)
+ max_prefix = len;
+ for(j=0; j<max_prefix; j++) {
+ if (completions[i][j] != completions[0][j])
+ max_prefix = j;
+ }
+ }
if (len > max_width)
max_width = len;
}
+ if (max_prefix > 0)
+ for(i = completion_index; i < max_prefix; i++) {
+ term_insert_char(completions[0][i]);
+ }
max_width += 2;
if (max_width < 10)
max_width = 10;
Modified: trunk/src/host/qemu-neo1973/slirp/bootp.c
===================================================================
--- trunk/src/host/qemu-neo1973/slirp/bootp.c 2007-10-29 20:40:05 UTC (rev 3302)
+++ trunk/src/host/qemu-neo1973/slirp/bootp.c 2007-10-29 21:14:04 UTC (rev 3303)
@@ -149,7 +149,7 @@
if ((m = m_get()) == NULL)
return;
- m->m_data += if_maxlinkhdr;
+ m->m_data += IF_MAXLINKHDR;
rbp = (struct bootp_t *)m->m_data;
m->m_data += sizeof(struct udpiphdr);
memset(rbp, 0, sizeof(struct bootp_t));
Modified: trunk/src/host/qemu-neo1973/slirp/debug.c
===================================================================
--- trunk/src/host/qemu-neo1973/slirp/debug.c 2007-10-29 20:40:05 UTC (rev 3302)
+++ trunk/src/host/qemu-neo1973/slirp/debug.c 2007-10-29 21:14:04 UTC (rev 3303)
@@ -20,6 +20,7 @@
/* Carry over one item from main.c so that the tty's restored.
* Only done when the tty being used is /dev/tty --RedWolf */
+#ifndef CONFIG_QEMU
extern struct termios slirp_tty_settings;
extern int slirp_tty_restore;
@@ -70,7 +71,9 @@
}
}
#endif
+#endif
+#ifdef LOG_ENABLED
#if 0
/*
* Statistic routines
@@ -80,7 +83,7 @@
* the link as well.
*/
-void
+static void
ttystats(ttyp)
struct ttys *ttyp;
{
@@ -89,9 +92,9 @@
lprint(" \r\n");
- if (if_comp & IF_COMPRESS)
+ if (IF_COMP & IF_COMPRESS)
strcpy(buff, "on");
- else if (if_comp & IF_NOCOMPRESS)
+ else if (IF_COMP & IF_NOCOMPRESS)
strcpy(buff, "off");
else
strcpy(buff, "off (for now)");
@@ -119,8 +122,8 @@
lprint(" %6d bad input packets\r\n", is->in_mbad);
}
-void
-allttystats()
+static void
+allttystats(void)
{
struct ttys *ttyp;
@@ -129,8 +132,8 @@
}
#endif
-void
-ipstats()
+static void
+ipstats(void)
{
lprint(" \r\n");
@@ -153,9 +156,9 @@
lprint(" %6d total packets delivered\r\n", ipstat.ips_delivered);
}
-#if 0
-void
-vjstats()
+#ifndef CONFIG_QEMU
+static void
+vjstats(void)
{
lprint(" \r\n");
@@ -172,8 +175,8 @@
}
#endif
-void
-tcpstats()
+static void
+tcpstats(void)
{
lprint(" \r\n");
@@ -240,8 +243,8 @@
}
-void
-udpstats()
+static void
+udpstats(void)
{
lprint(" \r\n");
@@ -254,8 +257,8 @@
lprint(" %6d datagrams sent\r\n", udpstat.udps_opackets);
}
-void
-icmpstats()
+static void
+icmpstats(void)
{
lprint(" \r\n");
lprint("ICMP stats:\r\n");
@@ -267,8 +270,8 @@
lprint(" %6d ICMP packets sent in reply\r\n", icmpstat.icps_reflect);
}
-void
-mbufstats()
+static void
+mbufstats(void)
{
struct mbuf *m;
int i;
@@ -291,8 +294,8 @@
lprint(" %6d mbufs queued as packets\r\n\r\n", if_queued);
}
-void
-sockstats()
+static void
+sockstats(void)
{
char buff[256];
int n;
@@ -331,8 +334,9 @@
so->so_rcv.sb_cc, so->so_snd.sb_cc);
}
}
+#endif
-#if 0
+#ifndef CONFIG_QEMU
void
slirp_exit(exit_status)
int exit_status;
@@ -374,3 +378,18 @@
exit(exit_status);
}
#endif
+
+void
+slirp_stats(void)
+{
+#ifdef LOG_ENABLED
+ ipstats();
+ tcpstats();
+ udpstats();
+ icmpstats();
+ mbufstats();
+ sockstats();
+#else
+ lprint("SLIRP statistics code not compiled.\n");
+#endif
+}
Modified: trunk/src/host/qemu-neo1973/slirp/debug.h
===================================================================
--- trunk/src/host/qemu-neo1973/slirp/debug.h 2007-10-29 20:40:05 UTC (rev 3302)
+++ trunk/src/host/qemu-neo1973/slirp/debug.h 2007-10-29 21:14:04 UTC (rev 3303)
@@ -37,14 +37,4 @@
#endif
void debug_init _P((char *, int));
-//void ttystats _P((struct ttys *));
-void allttystats _P((void));
-void ipstats _P((void));
-void vjstats _P((void));
-void tcpstats _P((void));
-void udpstats _P((void));
-void icmpstats _P((void));
-void mbufstats _P((void));
-void sockstats _P((void));
-void slirp_exit _P((int));
Modified: trunk/src/host/qemu-neo1973/slirp/icmp_var.h
===================================================================
--- trunk/src/host/qemu-neo1973/slirp/icmp_var.h 2007-10-29 20:40:05 UTC (rev 3302)
+++ trunk/src/host/qemu-neo1973/slirp/icmp_var.h 2007-10-29 21:14:04 UTC (rev 3303)
@@ -64,6 +64,8 @@
{ "stats", CTLTYPE_STRUCT }, \
}
+#ifdef LOG_ENABLED
extern struct icmpstat icmpstat;
+#endif
#endif
Modified: trunk/src/host/qemu-neo1973/slirp/if.c
===================================================================
--- trunk/src/host/qemu-neo1973/slirp/if.c 2007-10-29 20:40:05 UTC (rev 3302)
+++ trunk/src/host/qemu-neo1973/slirp/if.c 2007-10-29 21:14:04 UTC (rev 3303)
@@ -7,12 +7,7 @@
#include <slirp.h>
-int if_mtu, if_mru;
-int if_comp;
-int if_maxlinkhdr;
int if_queued = 0; /* Number of packets queued so far */
-int if_thresh = 10; /* Number of packets queued before we start sending
- * (to prevent allocing too many mbufs) */
struct mbuf if_fastq; /* fast queue (for interactive data) */
struct mbuf if_batchq; /* queue for non-interactive data */
@@ -41,23 +36,6 @@
void
if_init()
{
-#if 0
- /*
- * Set if_maxlinkhdr to 48 because it's 40 bytes for TCP/IP,
- * and 8 bytes for PPP, but need to have it on an 8byte boundary
- */
-#ifdef USE_PPP
- if_maxlinkhdr = 48;
-#else
- if_maxlinkhdr = 40;
-#endif
-#else
- /* 2 for alignment, 14 for ethernet, 40 for TCP/IP */
- if_maxlinkhdr = 2 + 14 + 40;
-#endif
- if_mtu = 1500;
- if_mru = 1500;
- if_comp = IF_AUTOCOMP;
if_fastq.ifq_next = if_fastq.ifq_prev = &if_fastq;
if_batchq.ifq_next = if_batchq.ifq_prev = &if_batchq;
// sl_compress_init(&comp_s);
Modified: trunk/src/host/qemu-neo1973/slirp/if.h
===================================================================
--- trunk/src/host/qemu-neo1973/slirp/if.h 2007-10-29 20:40:05 UTC (rev 3302)
+++ trunk/src/host/qemu-neo1973/slirp/if.h 2007-10-29 21:14:04 UTC (rev 3303)
@@ -13,15 +13,26 @@
#define IF_AUTOCOMP 0x04 /* Autodetect (default) */
#define IF_NOCIDCOMP 0x08 /* CID compression */
-/* Needed for FreeBSD */
-#undef if_mtu
-extern int if_mtu;
-extern int if_mru; /* MTU and MRU */
-extern int if_comp; /* Flags for compression */
-extern int if_maxlinkhdr;
+#define IF_MTU 1500
+#define IF_MRU 1500
+#define IF_COMP IF_AUTOCOMP /* Flags for compression */
+
+#if 0
+/*
+ * Set if_maxlinkhdr to 48 because it's 40 bytes for TCP/IP,
+ * and 8 bytes for PPP, but need to have it on an 8byte boundary
+ */
+#ifdef USE_PPP
+#define IF_MAXLINKHDR 48
+#else
+#define IF_MAXLINKHDR 40
+#endif
+#else
+ /* 2 for alignment, 14 for ethernet, 40 for TCP/IP */
+#define IF_MAXLINKHDR (2 + 14 + 40)
+#endif
+
extern int if_queued; /* Number of packets queued so far */
-extern int if_thresh; /* Number of packets queued before we start sending
- * (to prevent allocing too many mbufs) */
extern struct mbuf if_fastq; /* fast queue (for interactive data) */
extern struct mbuf if_batchq; /* queue for non-interactive data */
@@ -29,6 +40,7 @@
#define ifs_init(ifm) ((ifm)->ifs_next = (ifm)->ifs_prev = (ifm))
+#ifdef LOG_ENABLED
/* Interface statistics */
struct slirp_ifstats {
u_int out_pkts; /* Output packets */
@@ -46,5 +58,6 @@
u_int in_mbad; /* Bad incoming packets */
};
+#endif
#endif
Modified: trunk/src/host/qemu-neo1973/slirp/ip.h
===================================================================
--- trunk/src/host/qemu-neo1973/slirp/ip.h 2007-10-29 20:40:05 UTC (rev 3302)
+++ trunk/src/host/qemu-neo1973/slirp/ip.h 2007-10-29 21:14:04 UTC (rev 3303)
@@ -272,6 +272,7 @@
int8_t ipopt_list[MAX_IPOPTLEN]; /* options proper */
};
+#ifdef LOG_ENABLED
/*
* Structure attached to inpcb.ip_moptions and
* passed to ip_output when IP multicast options are in use.
@@ -306,8 +307,9 @@
};
extern struct ipstat ipstat;
+#endif
+
extern struct ipq ipq; /* ip reass. queue */
extern u_int16_t ip_id; /* ip packet ctr, for ids */
-extern int ip_defttl; /* default IP ttl */
#endif
Modified: trunk/src/host/qemu-neo1973/slirp/ip_icmp.c
===================================================================
--- trunk/src/host/qemu-neo1973/slirp/ip_icmp.c 2007-10-29 20:40:05 UTC (rev 3302)
+++ trunk/src/host/qemu-neo1973/slirp/ip_icmp.c 2007-10-29 21:14:04 UTC (rev 3303)
@@ -37,14 +37,16 @@
#include "slirp.h"
#include "ip_icmp.h"
+#ifdef LOG_ENABLED
struct icmpstat icmpstat;
+#endif
/* The message sent when emulating PING */
-/* Be nice and tell them it's just a psuedo-ping packet */
-char icmp_ping_msg[] = "This is a psuedo-PING packet used by Slirp to emulate ICMP ECHO-REQUEST packets.\n";
+/* Be nice and tell them it's just a pseudo-ping packet */
+const char icmp_ping_msg[] = "This is a pseudo-PING packet used by Slirp to emulate ICMP ECHO-REQUEST packets.\n";
/* list of actions for icmp_error() on RX of an icmp message */
-static int icmp_flush[19] = {
+static const int icmp_flush[19] = {
/* ECHO REPLY (0) */ 0,
1,
1,
@@ -83,14 +85,14 @@
DEBUG_ARG("m = %lx", (long )m);
DEBUG_ARG("m_len = %d", m->m_len);
- icmpstat.icps_received++;
+ STAT(icmpstat.icps_received++);
/*
* Locate icmp structure in mbuf, and check
* that its not corrupted and of at least minimum length.
*/
if (icmplen < ICMP_MINLEN) { /* min 8 bytes payload */
- icmpstat.icps_tooshort++;
+ STAT(icmpstat.icps_tooshort++);
freeit:
m_freem(m);
goto end_error;
@@ -100,7 +102,7 @@
m->m_data += hlen;
icp = mtod(m, struct icmp *);
if (cksum(m, icmplen)) {
- icmpstat.icps_checksum++;
+ STAT(icmpstat.icps_checksum++);
goto freeit;
}
m->m_len += hlen;
@@ -170,12 +172,12 @@
case ICMP_TSTAMP:
case ICMP_MASKREQ:
case ICMP_REDIRECT:
- icmpstat.icps_notsupp++;
+ STAT(icmpstat.icps_notsupp++);
m_freem(m);
break;
default:
- icmpstat.icps_badtype++;
+ STAT(icmpstat.icps_badtype++);
m_freem(m);
} /* swith */
@@ -314,7 +316,7 @@
(void ) ip_output((struct socket *)NULL, m);
- icmpstat.icps_reflect++;
+ STAT(icmpstat.icps_reflect++);
end_error:
return;
@@ -371,5 +373,5 @@
(void ) ip_output((struct socket *)NULL, m);
- icmpstat.icps_reflect++;
+ STAT(icmpstat.icps_reflect++);
}
Modified: trunk/src/host/qemu-neo1973/slirp/ip_input.c
===================================================================
--- trunk/src/host/qemu-neo1973/slirp/ip_input.c 2007-10-29 20:40:05 UTC (rev 3302)
+++ trunk/src/host/qemu-neo1973/slirp/ip_input.c 2007-10-29 21:14:04 UTC (rev 3303)
@@ -45,10 +45,19 @@
#include <slirp.h>
#include "ip_icmp.h"
-int ip_defttl;
+#ifdef LOG_ENABLED
struct ipstat ipstat;
+#endif
+
struct ipq ipq;
+static struct ip *ip_reass(register struct ipasfrag *ip,
+ register struct ipq *fp);
+static void ip_freef(struct ipq *fp);
+static void ip_enq(register struct ipasfrag *p,
+ register struct ipasfrag *prev);
+static void ip_deq(register struct ipasfrag *p);
+
/*
* IP initialization: fill in IP protocol switch table.
* All protocols not implemented in kernel go to raw IP protocol handler.
@@ -60,7 +69,6 @@
ip_id = tt.tv_sec & 0xffff;
udp_init();
tcp_init();
- ip_defttl = IPDEFTTL;
}
/*
@@ -78,23 +86,23 @@
DEBUG_ARG("m = %lx", (long)m);
DEBUG_ARG("m_len = %d", m->m_len);
- ipstat.ips_total++;
+ STAT(ipstat.ips_total++);
if (m->m_len < sizeof (struct ip)) {
- ipstat.ips_toosmall++;
+ STAT(ipstat.ips_toosmall++);
return;
}
ip = mtod(m, struct ip *);
if (ip->ip_v != IPVERSION) {
- ipstat.ips_badvers++;
+ STAT(ipstat.ips_badvers++);
goto bad;
}
hlen = ip->ip_hl << 2;
if (hlen<sizeof(struct ip ) || hlen>m->m_len) {/* min header length */
- ipstat.ips_badhlen++; /* or packet too short */
+ STAT(ipstat.ips_badhlen++); /* or packet too short */
goto bad;
}
@@ -103,7 +111,7 @@
* if (ip->ip_sum) {
*/
if(cksum(m,hlen)) {
- ipstat.ips_badsum++;
+ STAT(ipstat.ips_badsum++);
goto bad;
}
@@ -112,7 +120,7 @@
*/
NTOHS(ip->ip_len);
if (ip->ip_len < hlen) {
- ipstat.ips_badlen++;
+ STAT(ipstat.ips_badlen++);
goto bad;
}
NTOHS(ip->ip_id);
@@ -125,7 +133,7 @@
* Drop packet if shorter than we expect.
*/
if (m->m_len < ip->ip_len) {
- ipstat.ips_tooshort++;
+ STAT(ipstat.ips_tooshort++);
goto bad;
}
/* Should drop packet if mbuf too long? hmmm... */
@@ -192,11 +200,11 @@
* attempt reassembly; if it succeeds, proceed.
*/
if (((struct ipasfrag *)ip)->ipf_mff & 1 || ip->ip_off) {
- ipstat.ips_fragments++;
+ STAT(ipstat.ips_fragments++);
ip = ip_reass((struct ipasfrag *)ip, fp);
if (ip == 0)
return;
- ipstat.ips_reassembled++;
+ STAT(ipstat.ips_reassembled++);
m = dtom(ip);
} else
if (fp)
@@ -208,7 +216,7 @@
/*
* Switch out to protocol's input routine.
*/
- ipstat.ips_delivered++;
+ STAT(ipstat.ips_delivered++);
switch (ip->ip_p) {
case IPPROTO_TCP:
tcp_input(m, hlen, (struct socket *)NULL);
@@ -220,7 +228,7 @@
icmp_input(m, hlen);
break;
default:
- ipstat.ips_noproto++;
+ STAT(ipstat.ips_noproto++);
m_free(m);
}
return;
@@ -235,10 +243,8 @@
* reassembly of this datagram already exists, then it
* is given as fp; otherwise have to make a chain.
*/
-struct ip *
-ip_reass(ip, fp)
- register struct ipasfrag *ip;
- register struct ipq *fp;
+static struct ip *
+ip_reass(register struct ipasfrag *ip, register struct ipq *fp)
{
register struct mbuf *m = dtom(ip);
register struct ipasfrag *q;
@@ -385,7 +391,7 @@
return ((struct ip *)ip);
dropfrag:
- ipstat.ips_fragdropped++;
+ STAT(ipstat.ips_fragdropped++);
m_freem(m);
return (0);
}
@@ -394,9 +400,8 @@
* Free a fragment reassembly header and all
* associated datagrams.
*/
-void
-ip_freef(fp)
- struct ipq *fp;
+static void
+ip_freef(struct ipq *fp)
{
register struct ipasfrag *q, *p;
@@ -414,9 +419,8 @@
* Put an ip fragment on a reassembly chain.
* Like insque, but pointers in middle of structure.
*/
-void
-ip_enq(p, prev)
- register struct ipasfrag *p, *prev;
+static void
+ip_enq(register struct ipasfrag *p, register struct ipasfrag *prev)
{
DEBUG_CALL("ip_enq");
DEBUG_ARG("prev = %lx", (long)prev);
@@ -429,9 +433,8 @@
/*
* To ip_enq as remque is to insque.
*/
-void
-ip_deq(p)
- register struct ipasfrag *p;
+static void
+ip_deq(register struct ipasfrag *p)
{
((struct ipasfrag *)(p->ipf_prev))->ipf_next = p->ipf_next;
((struct ipasfrag *)(p->ipf_next))->ipf_prev = p->ipf_prev;
@@ -457,7 +460,7 @@
--fp->ipq_ttl;
fp = (struct ipq *) fp->next;
if (((struct ipq *)(fp->prev))->ipq_ttl == 0) {
- ipstat.ips_fragtimeout++;
+ STAT(ipstat.ips_fragtimeout++);
ip_freef((struct ipq *) fp->prev);
}
}
@@ -664,7 +667,7 @@
/* Not yet */
icmp_error(m, type, code, 0, 0);
- ipstat.ips_badoptions++;
+ STAT(ipstat.ips_badoptions++);
return (1);
}
Modified: trunk/src/host/qemu-neo1973/slirp/ip_output.c
===================================================================
--- trunk/src/host/qemu-neo1973/slirp/ip_output.c 2007-10-29 20:40:05 UTC (rev 3302)
+++ trunk/src/host/qemu-neo1973/slirp/ip_output.c 2007-10-29 21:14:04 UTC (rev 3303)
@@ -46,6 +46,10 @@
u_int16_t ip_id;
+/* Number of packets queued before we start sending
+ * (to prevent allocing too many mbufs) */
+#define IF_THRESH 10
+
/*
* IP output. The packet in mbuf chain m contains a skeletal IP
* header (with len, off, ttl, proto, tos, src, dst).
@@ -80,14 +84,14 @@
ip->ip_off &= IP_DF;
ip->ip_id = htons(ip_id++);
ip->ip_hl = hlen >> 2;
- ipstat.ips_localout++;
+ STAT(ipstat.ips_localout++);
/*
* Verify that we have any chance at all of being able to queue
* the packet or packet fragments
*/
/* XXX Hmmm... */
-/* if (if_queued > if_thresh && towrite <= 0) {
+/* if (if_queued > IF_THRESH && towrite <= 0) {
* error = ENOBUFS;
* goto bad;
* }
@@ -96,7 +100,7 @@
/*
* If small enough for interface, can just send directly.
*/
- if ((u_int16_t)ip->ip_len <= if_mtu) {
+ if ((u_int16_t)ip->ip_len <= IF_MTU) {
ip->ip_len = htons((u_int16_t)ip->ip_len);
ip->ip_off = htons((u_int16_t)ip->ip_off);
ip->ip_sum = 0;
@@ -112,11 +116,11 @@
*/
if (ip->ip_off & IP_DF) {
error = -1;
- ipstat.ips_cantfrag++;
+ STAT(ipstat.ips_cantfrag++);
goto bad;
}
- len = (if_mtu - hlen) &~ 7; /* ip databytes per packet */
+ len = (IF_MTU - hlen) &~ 7; /* ip databytes per packet */
if (len < 8) {
error = -1;
goto bad;
@@ -137,10 +141,10 @@
m = m_get();
if (m == 0) {
error = -1;
- ipstat.ips_odropped++;
+ STAT(ipstat.ips_odropped++);
goto sendorfree;
}
- m->m_data += if_maxlinkhdr;
+ m->m_data += IF_MAXLINKHDR;
mhip = mtod(m, struct ip *);
*mhip = *ip;
@@ -170,7 +174,7 @@
mhip->ip_sum = cksum(m, mhlen);
*mnext = m;
mnext = &m->m_nextpkt;
- ipstat.ips_ofragments++;
+ STAT(ipstat.ips_ofragments++);
}
/*
* Update first fragment by trimming what's been copied out
@@ -193,7 +197,7 @@
}
if (error == 0)
- ipstat.ips_fragmented++;
+ STAT(ipstat.ips_fragmented++);
}
done:
Modified: trunk/src/host/qemu-neo1973/slirp/libslirp.h
===================================================================
--- trunk/src/host/qemu-neo1973/slirp/libslirp.h 2007-10-29 20:40:05 UTC (rev 3302)
+++ trunk/src/host/qemu-neo1973/slirp/libslirp.h 2007-10-29 21:14:04 UTC (rev 3303)
@@ -26,6 +26,8 @@
extern const char *tftp_prefix;
extern char slirp_hostname[33];
+void slirp_stats(void);
+
#ifdef __cplusplus
}
#endif
Modified: trunk/src/host/qemu-neo1973/slirp/main.h
===================================================================
--- trunk/src/host/qemu-neo1973/slirp/main.h 2007-10-29 20:40:05 UTC (rev 3302)
+++ trunk/src/host/qemu-neo1973/slirp/main.h 2007-10-29 21:14:04 UTC (rev 3303)
@@ -42,7 +42,6 @@
extern char *socket_path;
extern int towrite_max;
extern int ppp_exit;
-extern int so_options;
extern int tcp_keepintvl;
extern uint8_t client_ethaddr[6];
Modified: trunk/src/host/qemu-neo1973/slirp/mbuf.c
===================================================================
--- trunk/src/host/qemu-neo1973/slirp/mbuf.c 2007-10-29 20:40:05 UTC (rev 3302)
+++ trunk/src/host/qemu-neo1973/slirp/mbuf.c 2007-10-29 21:14:04 UTC (rev 3303)
@@ -21,29 +21,22 @@
char *mclrefcnt;
int mbuf_alloced = 0;
struct mbuf m_freelist, m_usedlist;
-int mbuf_thresh = 30;
+#define MBUF_THRESH 30
int mbuf_max = 0;
-int msize;
+/*
+ * Find a nice value for msize
+ * XXX if_maxlinkhdr already in mtu
+ */
+#define MSIZE (IF_MTU + IF_MAXLINKHDR + sizeof(struct m_hdr ) + 6)
+
void
m_init()
{
m_freelist.m_next = m_freelist.m_prev = &m_freelist;
m_usedlist.m_next = m_usedlist.m_prev = &m_usedlist;
- msize_init();
}
-void
-msize_init()
-{
- /*
- * Find a nice value for msize
- * XXX if_maxlinkhdr already in mtu
- */
- msize = (if_mtu>if_mru?if_mtu:if_mru) +
- if_maxlinkhdr + sizeof(struct m_hdr ) + 6;
-}
-
/*
* Get an mbuf from the free list, if there are none
* malloc one
@@ -61,10 +54,10 @@
DEBUG_CALL("m_get");
if (m_freelist.m_next == &m_freelist) {
- m = (struct mbuf *)malloc(msize);
+ m = (struct mbuf *)malloc(MSIZE);
if (m == NULL) goto end_error;
mbuf_alloced++;
- if (mbuf_alloced > mbuf_thresh)
+ if (mbuf_alloced > MBUF_THRESH)
flags = M_DOFREE;
if (mbuf_alloced > mbuf_max)
mbuf_max = mbuf_alloced;
@@ -78,7 +71,7 @@
m->m_flags = (flags | M_USEDLIST);
/* Initialise it */
- m->m_size = msize - sizeof(struct m_hdr);
+ m->m_size = MSIZE - sizeof(struct m_hdr);
m->m_data = m->m_dat;
m->m_len = 0;
m->m_nextpkt = 0;
Modified: trunk/src/host/qemu-neo1973/slirp/mbuf.h
===================================================================
--- trunk/src/host/qemu-neo1973/slirp/mbuf.h 2007-10-29 20:40:05 UTC (rev 3302)
+++ trunk/src/host/qemu-neo1973/slirp/mbuf.h 2007-10-29 21:14:04 UTC (rev 3303)
@@ -135,7 +135,6 @@
extern int mbuf_max;
void m_init _P((void));
-void msize_init _P((void));
struct mbuf * m_get _P((void));
void m_free _P((struct mbuf *));
void m_cat _P((register struct mbuf *, register struct mbuf *));
Modified: trunk/src/host/qemu-neo1973/slirp/misc.c
===================================================================
--- trunk/src/host/qemu-neo1973/slirp/misc.c 2007-10-29 20:40:05 UTC (rev 3302)
+++ trunk/src/host/qemu-neo1973/slirp/misc.c 2007-10-29 21:14:04 UTC (rev 3303)
@@ -8,8 +8,7 @@
#define WANT_SYS_IOCTL_H
#include <slirp.h>
-u_int curtime, time_fasttimo, last_slowtimo, detach_time;
-u_int detach_wait = 600000; /* 10 minutes */
+u_int curtime, time_fasttimo, last_slowtimo;
#if 0
int x_port = -1;
@@ -214,10 +213,7 @@
#ifdef _WIN32
int
-fork_exec(so, ex, do_pty)
- struct socket *so;
- char *ex;
- int do_pty;
+fork_exec(struct socket *so, const char *ex, int do_pty)
{
/* not implemented */
return 0;
@@ -225,6 +221,7 @@
#else
+#ifndef CONFIG_QEMU
int
slirp_openpty(amaster, aslave)
int *amaster, *aslave;
@@ -289,6 +286,7 @@
return (-1);
#endif
}
+#endif
/*
* XXX This is ugly
@@ -302,23 +300,20 @@
* do_ptr = 2 Fork/exec using pty
*/
int
-fork_exec(so, ex, do_pty)
- struct socket *so;
- char *ex;
- int do_pty;
+fork_exec(struct socket *so, const char *ex, int do_pty)
{
int s;
struct sockaddr_in addr;
int addrlen = sizeof(addr);
int opt;
- int master;
+ int master = -1;
char *argv[256];
#if 0
char buff[256];
#endif
/* don't want to clobber the original */
char *bptr;
- char *curarg;
+ const char *curarg;
int c, i, ret;
DEBUG_CALL("fork_exec");
@@ -327,10 +322,12 @@
DEBUG_ARG("do_pty = %lx", (long)do_pty);
if (do_pty == 2) {
+#if 0
if (slirp_openpty(&master, &s) == -1) {
lprint("Error: openpty failed: %s\n", strerror(errno));
return 0;
}
+#endif
} else {
addr.sin_family = AF_INET;
addr.sin_port = 0;
@@ -390,7 +387,7 @@
dup2(s, 0);
dup2(s, 1);
dup2(s, 2);
- for (s = 3; s <= 255; s++)
+ for (s = getdtablesize() - 1; s >= 3; s--)
close(s);
i = 0;
@@ -603,6 +600,16 @@
}
#endif
+#ifdef CONFIG_QEMU
+void lprint(const char *format, ...)
+{
+ va_list args;
+
+ va_start(args, format);
+ term_vprintf(format, args);
+ va_end(args);
+}
+#else
int (*lprint_print) _P((void *, const char *, va_list));
char *lprint_ptr, *lprint_ptr2, **lprint_arg;
@@ -754,6 +761,7 @@
lprint("Adding emulation for %s to port %d/%d\r\n", buff1, emup->lport, emup->fport);
}
+#endif
#ifdef BAD_SPRINTF
Modified: trunk/src/host/qemu-neo1973/slirp/misc.h
===================================================================
--- trunk/src/host/qemu-neo1973/slirp/misc.h 2007-10-29 20:40:05 UTC (rev 3302)
+++ trunk/src/host/qemu-neo1973/slirp/misc.h 2007-10-29 21:14:04 UTC (rev 3303)
@@ -12,12 +12,12 @@
int ex_pty; /* Do we want a pty? */
int ex_addr; /* The last byte of the address */
int ex_fport; /* Port to telnet to */
- char *ex_exec; /* Command line of what to exec */
+ const char *ex_exec; /* Command line of what to exec */
struct ex_list *ex_next;
};
extern struct ex_list *exec_list;
-extern u_int curtime, time_fasttimo, last_slowtimo, detach_time, detach_wait;
+extern u_int curtime, time_fasttimo, last_slowtimo;
extern int (*lprint_print) _P((void *, const char *, va_list));
extern char *lprint_ptr, *lprint_ptr2, **lprint_arg;
@@ -74,7 +74,7 @@
inline void slirp_remque _P((void *));
int add_exec _P((struct ex_list **, int, char *, int, int));
int slirp_openpty _P((int *, int *));
-int fork_exec _P((struct socket *, char *, int));
+int fork_exec(struct socket *so, const char *ex, int do_pty);
void snooze_hup _P((int));
void snooze _P((void));
void relay _P((int));
Modified: trunk/src/host/qemu-neo1973/slirp/sbuf.c
===================================================================
--- trunk/src/host/qemu-neo1973/slirp/sbuf.c 2007-10-29 20:40:05 UTC (rev 3302)
+++ trunk/src/host/qemu-neo1973/slirp/sbuf.c 2007-10-29 21:14:04 UTC (rev 3303)
@@ -7,6 +7,8 @@
#include <slirp.h>
+static void sbappendsb(struct sbuf *sb, struct mbuf *m);
+
/* Done as a macro in socket.h */
/* int
* sbspace(struct sockbuff *sb)
@@ -133,10 +135,8 @@
* Copy the data from m into sb
* The caller is responsible to make sure there's enough room
*/
-void
-sbappendsb(sb, m)
- struct sbuf *sb;
- struct mbuf *m;
+static void
+sbappendsb(struct sbuf *sb, struct mbuf *m)
{
int len, n, nn;
Modified: trunk/src/host/qemu-neo1973/slirp/sbuf.h
===================================================================
--- trunk/src/host/qemu-neo1973/slirp/sbuf.h 2007-10-29 20:40:05 UTC (rev 3302)
+++ trunk/src/host/qemu-neo1973/slirp/sbuf.h 2007-10-29 21:14:04 UTC (rev 3303)
@@ -25,7 +25,6 @@
void sbdrop _P((struct sbuf *, int));
void sbreserve _P((struct sbuf *, int));
void sbappend _P((struct socket *, struct mbuf *));
-void sbappendsb _P((struct sbuf *, struct mbuf *));
void sbcopy _P((struct sbuf *, int, int, char *));
#endif
Modified: trunk/src/host/qemu-neo1973/slirp/slirp.c
===================================================================
--- trunk/src/host/qemu-neo1973/slirp/slirp.c 2007-10-29 20:40:05 UTC (rev 3302)
+++ trunk/src/host/qemu-neo1973/slirp/slirp.c 2007-10-29 21:14:04 UTC (rev 3303)
@@ -12,7 +12,7 @@
/* virtual address alias for host */
struct in_addr alias_addr;
-const uint8_t special_ethaddr[6] = {
+static const uint8_t special_ethaddr[6] = {
0x52, 0x54, 0x00, 0x12, 0x35, 0x00
};
@@ -93,7 +93,9 @@
if (!f)
return -1;
+#ifdef DEBUG
lprint("IP address of your DNS(s): ");
+#endif
while (fgets(buff, 512, f) != NULL) {
if (sscanf(buff, "nameserver%*[ \t]%256s", buff2) == 1) {
if (!inet_aton(buff2, &tmp_addr))
@@ -103,13 +105,20 @@
/* If it's the first one, set it to dns_addr */
if (!found)
*pdns_addr = tmp_addr;
+#ifdef DEBUG
else
lprint(", ");
+#endif
if (++found > 3) {
+#ifdef DEBUG
lprint("(more)");
+#endif
break;
- } else
+ }
+#ifdef DEBUG
+ else
lprint("%s", inet_ntoa(tmp_addr));
+#endif
}
}
fclose(f);
@@ -121,7 +130,7 @@
#endif
#ifdef _WIN32
-void slirp_cleanup(void)
+static void slirp_cleanup(void)
{
WSACleanup();
}
Modified: trunk/src/host/qemu-neo1973/slirp/slirp.h
===================================================================
--- trunk/src/host/qemu-neo1973/slirp/slirp.h 2007-10-29 20:40:05 UTC (rev 3302)
+++ trunk/src/host/qemu-neo1973/slirp/slirp.h 2007-10-29 21:14:04 UTC (rev 3303)
@@ -3,8 +3,17 @@
#define CONFIG_QEMU
-#define DEBUG 1
+//#define DEBUG 1
+// Uncomment the following line to enable SLIRP statistics printing in Qemu
+//#define LOG_ENABLED
+
+#ifdef LOG_ENABLED
+#define STAT(expr) expr
+#else
+#define STAT(expr) do { } while(0)
+#endif
+
#ifndef CONFIG_QEMU
#include "version.h"
#endif
@@ -255,8 +264,6 @@
void lprint _P((const char *, ...));
-extern int do_echo;
-
#if SIZEOF_CHAR_P == 4
# define insque_32 insque
# define remque_32 remque
@@ -271,6 +278,9 @@
#define DEFAULT_BAUD 115200
+#define SO_OPTIONS DO_KEEPALIVE
+#define TCP_MAXIDLE (TCPTV_KEEPCNT * TCPTV_KEEPINTVL)
+
/* cksum.c */
int cksum(struct mbuf *m, int len);
@@ -281,10 +291,6 @@
/* ip_input.c */
void ip_init _P((void));
void ip_input _P((struct mbuf *));
-struct ip * ip_reass _P((register struct ipasfrag *, register struct ipq *));
-void ip_freef _P((struct ipq *));
-void ip_enq _P((register struct ipasfrag *, register struct ipasfrag *));
-void ip_deq _P((register struct ipasfrag *));
void ip_slowtimo _P((void));
void ip_stripoptions _P((register struct mbuf *, struct mbuf *));
@@ -292,10 +298,7 @@
int ip_output _P((struct socket *, struct mbuf *));
/* tcp_input.c */
-int tcp_reass _P((register struct tcpcb *, register struct tcpiphdr *, struct mbuf *));
void tcp_input _P((register struct mbuf *, int, struct socket *));
-void tcp_dooptions _P((struct tcpcb *, u_char *, int, struct tcpiphdr *));
-void tcp_xmit_timer _P((register struct tcpcb *, int));
int tcp_mss _P((register struct tcpcb *, u_int));
/* tcp_output.c */
@@ -308,7 +311,6 @@
void tcp_respond _P((struct tcpcb *, register struct tcpiphdr *, register struct mbuf *, tcp_seq, tcp_seq, int));
struct tcpcb * tcp_newtcpcb _P((struct socket *));
struct tcpcb * tcp_close _P((register struct tcpcb *));
-void tcp_drain _P((void));
void tcp_sockclosed _P((struct tcpcb *));
int tcp_fconnect _P((struct socket *));
void tcp_connect _P((struct socket *));
Modified: trunk/src/host/qemu-neo1973/slirp/socket.c
===================================================================
--- trunk/src/host/qemu-neo1973/slirp/socket.c 2007-10-29 20:40:05 UTC (rev 3302)
+++ trunk/src/host/qemu-neo1973/slirp/socket.c 2007-10-29 21:14:04 UTC (rev 3303)
@@ -13,13 +13,17 @@
#include <sys/filio.h>
#endif
-void
+static void sofcantrcvmore(struct socket *so);
+static void sofcantsendmore(struct socket *so);
+
+#if 0
+static void
so_init()
{
/* Nothing yet */
}
+#endif
-
struct socket *
solookup(head, laddr, lport, faddr, fport)
struct socket *head;
@@ -421,7 +425,7 @@
int len, n;
if (!(m = m_get())) return;
- m->m_data += if_maxlinkhdr;
+ m->m_data += IF_MAXLINKHDR;
/*
* XXX Shouldn't FIONREAD packets destined for port 53,
@@ -604,12 +608,13 @@
return so;
}
+#if 0
/*
* Data is available in so_rcv
* Just write() the data to the socket
* XXX not yet...
*/
-void
+static void
sorwakeup(so)
struct socket *so;
{
@@ -622,12 +627,13 @@
* We have room for a read() if we want to
* For now, don't read, it'll be done in the main loop
*/
-void
+static void
sowwakeup(so)
struct socket *so;
{
/* Nothing, yet */
}
+#endif
/*
* Various session state calls
@@ -652,9 +658,8 @@
so->so_state |= SS_ISFCONNECTED; /* Clobber other states */
}
-void
-sofcantrcvmore(so)
- struct socket *so;
+static void
+sofcantrcvmore(struct socket *so)
{
if ((so->so_state & SS_NOFDREF) == 0) {
shutdown(so->s,0);
@@ -669,9 +674,8 @@
so->so_state |= SS_FCANTRCVMORE;
}
-void
-sofcantsendmore(so)
- struct socket *so;
+static void
+sofcantsendmore(struct socket *so)
{
if ((so->so_state & SS_NOFDREF) == 0) {
shutdown(so->s,1); /* send FIN to fhost */
Modified: trunk/src/host/qemu-neo1973/slirp/socket.h
===================================================================
--- trunk/src/host/qemu-neo1973/slirp/socket.h 2007-10-29 20:40:05 UTC (rev 3302)
+++ trunk/src/host/qemu-neo1973/slirp/socket.h 2007-10-29 21:14:04 UTC (rev 3303)
@@ -81,7 +81,6 @@
};
#endif
-void so_init _P((void));
struct socket * solookup _P((struct socket *, struct in_addr, u_int, struct in_addr, u_int));
struct socket * socreate _P((void));
void sofree _P((struct socket *));
@@ -92,12 +91,8 @@
void sorecvfrom _P((struct socket *));
int sosendto _P((struct socket *, struct mbuf *));
struct socket * solisten _P((u_int, u_int32_t, u_int, int));
-void sorwakeup _P((struct socket *));
-void sowwakeup _P((struct socket *));
void soisfconnecting _P((register struct socket *));
void soisfconnected _P((register struct socket *));
-void sofcantrcvmore _P((struct socket *));
-void sofcantsendmore _P((struct socket *));
void soisfdisconnected _P((struct socket *));
void sofwdrain _P((struct socket *));
Modified: trunk/src/host/qemu-neo1973/slirp/tcp.h
===================================================================
--- trunk/src/host/qemu-neo1973/slirp/tcp.h 2007-10-29 20:40:05 UTC (rev 3302)
+++ trunk/src/host/qemu-neo1973/slirp/tcp.h 2007-10-29 21:14:04 UTC (rev 3303)
@@ -42,8 +42,6 @@
#define PR_SLOWHZ 2 /* 2 slow timeouts per second (approx) */
#define PR_FASTHZ 5 /* 5 fast timeouts per second (not important) */
-extern int tcp_rcvspace;
-extern int tcp_sndspace;
extern struct socket *tcp_last_so;
#define TCP_SNDSPACE 8192
@@ -172,6 +170,6 @@
extern tcp_seq tcp_iss; /* tcp initial send seq # */
-extern char *tcpstates[];
+extern const char * const tcpstates[];
#endif
Modified: trunk/src/host/qemu-neo1973/slirp/tcp_input.c
===================================================================
--- trunk/src/host/qemu-neo1973/slirp/tcp_input.c 2007-10-29 20:40:05 UTC (rev 3302)
+++ trunk/src/host/qemu-neo1973/slirp/tcp_input.c 2007-10-29 21:14:04 UTC (rev 3303)
@@ -47,7 +47,7 @@
struct socket tcb;
-int tcprexmtthresh = 3;
+#define TCPREXMTTHRESH 3
struct socket *tcp_last_so = &tcb;
tcp_seq tcp_iss; /* tcp initial send seq # */
@@ -79,8 +79,8 @@
tp->t_flags |= TF_DELACK; \
(tp)->rcv_nxt += (ti)->ti_len; \
flags = (ti)->ti_flags & TH_FIN; \
- tcpstat.tcps_rcvpack++;\
- tcpstat.tcps_rcvbyte += (ti)->ti_len;\
+ STAT(tcpstat.tcps_rcvpack++); \
+ STAT(tcpstat.tcps_rcvbyte += (ti)->ti_len); \
if (so->so_emu) { \
if (tcp_emu((so),(m))) sbappend((so), (m)); \
} else \
@@ -99,8 +99,8 @@
tp->t_flags |= TF_DELACK; \
(tp)->rcv_nxt += (ti)->ti_len; \
flags = (ti)->ti_flags & TH_FIN; \
- tcpstat.tcps_rcvpack++;\
- tcpstat.tcps_rcvbyte += (ti)->ti_len;\
+ STAT(tcpstat.tcps_rcvpack++); \
+ STAT(tcpstat.tcps_rcvbyte += (ti)->ti_len); \
if (so->so_emu) { \
if (tcp_emu((so),(m))) sbappend(so, (m)); \
} else \
@@ -112,12 +112,13 @@
} \
}
#endif
+static void tcp_dooptions(struct tcpcb *tp, u_char *cp, int cnt,
+ struct tcpiphdr *ti);
+static void tcp_xmit_timer(register struct tcpcb *tp, int rtt);
-int
-tcp_reass(tp, ti, m)
- register struct tcpcb *tp;
- register struct tcpiphdr *ti;
- struct mbuf *m;
+static int
+tcp_reass(register struct tcpcb *tp, register struct tcpiphdr *ti,
+ struct mbuf *m)
{
register struct tcpiphdr *q;
struct socket *so = tp->t_socket;
@@ -150,8 +151,8 @@
i = q->ti_seq + q->ti_len - ti->ti_seq;
if (i > 0) {
if (i >= ti->ti_len) {
- tcpstat.tcps_rcvduppack++;
- tcpstat.tcps_rcvdupbyte += ti->ti_len;
+ STAT(tcpstat.tcps_rcvduppack++);
+ STAT(tcpstat.tcps_rcvdupbyte += ti->ti_len);
m_freem(m);
/*
* Try to present any queued data
@@ -167,8 +168,8 @@
}
q = (struct tcpiphdr *)(q->ti_next);
}
- tcpstat.tcps_rcvoopack++;
- tcpstat.tcps_rcvoobyte += ti->ti_len;
+ STAT(tcpstat.tcps_rcvoopack++);
+ STAT(tcpstat.tcps_rcvoobyte += ti->ti_len);
REASS_MBUF(ti) = (mbufp_32) m; /* XXX */
/*
@@ -275,7 +276,7 @@
}
- tcpstat.tcps_rcvtotal++;
+ STAT(tcpstat.tcps_rcvtotal++);
/*
* Get IP and TCP header together in first mbuf.
* Note: IP leaves IP header in first mbuf.
@@ -308,7 +309,7 @@
* ti->ti_sum = cksum(m, len);
* if (ti->ti_sum) { */
if(cksum(m, len)) {
- tcpstat.tcps_rcvbadsum++;
+ STAT(tcpstat.tcps_rcvbadsum++);
goto drop;
}
@@ -318,7 +319,7 @@
*/
off = ti->ti_off << 2;
if (off < sizeof (struct tcphdr) || off > tlen) {
- tcpstat.tcps_rcvbadoff++;
+ STAT(tcpstat.tcps_rcvbadoff++);
goto drop;
}
tlen -= off;
@@ -375,7 +376,7 @@
ti->ti_dst, ti->ti_dport);
if (so)
tcp_last_so = so;
- ++tcpstat.tcps_socachemiss;
+ STAT(tcpstat.tcps_socachemiss++);
}
/*
@@ -402,8 +403,8 @@
goto dropwithreset;
}
- sbreserve(&so->so_snd, tcp_sndspace);
- sbreserve(&so->so_rcv, tcp_rcvspace);
+ sbreserve(&so->so_snd, TCP_SNDSPACE);
+ sbreserve(&so->so_rcv, TCP_RCVSPACE);
/* tcp_last_so = so; */ /* XXX ? */
/* tp = sototcpcb(so); */
@@ -448,10 +449,10 @@
* Reset idle time and keep-alive timer.
*/
tp->t_idle = 0;
- if (so_options)
- tp->t_timer[TCPT_KEEP] = tcp_keepintvl;
+ if (SO_OPTIONS)
+ tp->t_timer[TCPT_KEEP] = TCPTV_KEEPINTVL;
else
- tp->t_timer[TCPT_KEEP] = tcp_keepidle;
+ tp->t_timer[TCPT_KEEP] = TCPTV_KEEP_IDLE;
/*
* Process options if not in LISTEN state,
@@ -503,7 +504,7 @@
/*
* this is a pure ack for outstanding data.
*/
- ++tcpstat.tcps_predack;
+ STAT(tcpstat.tcps_predack++);
/* if (ts_present)
* tcp_xmit_timer(tp, tcp_now-ts_ecr+1);
* else
@@ -511,8 +512,8 @@
SEQ_GT(ti->ti_ack, tp->t_rtseq))
tcp_xmit_timer(tp, tp->t_rtt);
acked = ti->ti_ack - tp->snd_una;
- tcpstat.tcps_rcvackpack++;
- tcpstat.tcps_rcvackbyte += acked;
+ STAT(tcpstat.tcps_rcvackpack++);
+ STAT(tcpstat.tcps_rcvackbyte += acked);
sbdrop(&so->so_snd, acked);
tp->snd_una = ti->ti_ack;
m_freem(m);
@@ -556,10 +557,10 @@
* with nothing on the reassembly queue and
* we have enough buffer space to take it.
*/
- ++tcpstat.tcps_preddat;
+ STAT(tcpstat.tcps_preddat++);
tp->rcv_nxt += ti->ti_len;
- tcpstat.tcps_rcvpack++;
- tcpstat.tcps_rcvbyte += ti->ti_len;
+ STAT(tcpstat.tcps_rcvpack++);
+ STAT(tcpstat.tcps_rcvbyte += ti->ti_len);
/*
* Add data to socket buffer.
*/
@@ -726,7 +727,7 @@
tp->t_flags |= TF_ACKNOW;
tp->t_state = TCPS_SYN_RECEIVED;
tp->t_timer[TCPT_KEEP] = TCPTV_KEEP_INIT;
- tcpstat.tcps_accepts++;
+ STAT(tcpstat.tcps_accepts++);
goto trimthenstep6;
} /* case TCPS_LISTEN */
@@ -767,7 +768,7 @@
tcp_rcvseqinit(tp);
tp->t_flags |= TF_ACKNOW;
if (tiflags & TH_ACK && SEQ_GT(tp->snd_una, tp->iss)) {
- tcpstat.tcps_connects++;
+ STAT(tcpstat.tcps_connects++);
soisfconnected(so);
tp->t_state = TCPS_ESTABLISHED;
@@ -801,8 +802,8 @@
m_adj(m, -todrop);
ti->ti_len = tp->rcv_wnd;
tiflags &= ~TH_FIN;
- tcpstat.tcps_rcvpackafterwin++;
- tcpstat.tcps_rcvbyteafterwin += todrop;
+ STAT(tcpstat.tcps_rcvpackafterwin++);
+ STAT(tcpstat.tcps_rcvbyteafterwin += todrop);
}
tp->snd_wl1 = ti->ti_seq - 1;
tp->rcv_up = ti->ti_seq;
@@ -873,11 +874,11 @@
*/
tp->t_flags |= TF_ACKNOW;
todrop = ti->ti_len;
- tcpstat.tcps_rcvduppack++;
- tcpstat.tcps_rcvdupbyte += todrop;
+ STAT(tcpstat.tcps_rcvduppack++);
+ STAT(tcpstat.tcps_rcvdupbyte += todrop);
} else {
- tcpstat.tcps_rcvpartduppack++;
- tcpstat.tcps_rcvpartdupbyte += todrop;
+ STAT(tcpstat.tcps_rcvpartduppack++);
+ STAT(tcpstat.tcps_rcvpartdupbyte += todrop);
}
m_adj(m, todrop);
ti->ti_seq += todrop;
@@ -896,7 +897,7 @@
if ((so->so_state & SS_NOFDREF) &&
tp->t_state > TCPS_CLOSE_WAIT && ti->ti_len) {
tp = tcp_close(tp);
- tcpstat.tcps_rcvafterclose++;
+ STAT(tcpstat.tcps_rcvafterclose++);
goto dropwithreset;
}
@@ -906,9 +907,9 @@
*/
todrop = (ti->ti_seq+ti->ti_len) - (tp->rcv_nxt+tp->rcv_wnd);
if (todrop > 0) {
- tcpstat.tcps_rcvpackafterwin++;
+ STAT(tcpstat.tcps_rcvpackafterwin++);
if (todrop >= ti->ti_len) {
- tcpstat.tcps_rcvbyteafterwin += ti->ti_len;
+ STAT(tcpstat.tcps_rcvbyteafterwin += ti->ti_len);
/*
* If a new connection request is received
* while in TIME_WAIT, drop the old connection
@@ -931,11 +932,11 @@
*/
if (tp->rcv_wnd == 0 && ti->ti_seq == tp->rcv_nxt) {
tp->t_flags |= TF_ACKNOW;
- tcpstat.tcps_rcvwinprobe++;
+ STAT(tcpstat.tcps_rcvwinprobe++);
} else
goto dropafterack;
} else
- tcpstat.tcps_rcvbyteafterwin += todrop;
+ STAT(tcpstat.tcps_rcvbyteafterwin += todrop);
m_adj(m, -todrop);
ti->ti_len -= todrop;
tiflags &= ~(TH_PUSH|TH_FIN);
@@ -976,7 +977,7 @@
/* so->so_error = ECONNRESET; */
close:
tp->t_state = TCPS_CLOSED;
- tcpstat.tcps_drops++;
+ STAT(tcpstat.tcps_drops++);
tp = tcp_close(tp);
goto drop;
@@ -1015,7 +1016,7 @@
if (SEQ_GT(tp->snd_una, ti->ti_ack) ||
SEQ_GT(ti->ti_ack, tp->snd_max))
goto dropwithreset;
- tcpstat.tcps_connects++;
+ STAT(tcpstat.tcps_connects++);
tp->t_state = TCPS_ESTABLISHED;
/*
* The sent SYN is ack'ed with our sequence number +1
@@ -1072,7 +1073,7 @@
if (SEQ_LEQ(ti->ti_ack, tp->snd_una)) {
if (ti->ti_len == 0 && tiwin == tp->snd_wnd) {
- tcpstat.tcps_rcvdupack++;
+ STAT(tcpstat.tcps_rcvdupack++);
DEBUG_MISC((dfd," dup ack m = %lx so = %lx \n",
(long )m, (long )so));
/*
@@ -1102,7 +1103,7 @@
if (tp->t_timer[TCPT_REXMT] == 0 ||
ti->ti_ack != tp->snd_una)
tp->t_dupacks = 0;
- else if (++tp->t_dupacks == tcprexmtthresh) {
+ else if (++tp->t_dupacks == TCPREXMTTHRESH) {
tcp_seq onxt = tp->snd_nxt;
u_int win =
min(tp->snd_wnd, tp->snd_cwnd) / 2 /
@@ -1121,7 +1122,7 @@
if (SEQ_GT(onxt, tp->snd_nxt))
tp->snd_nxt = onxt;
goto drop;
- } else if (tp->t_dupacks > tcprexmtthresh) {
+ } else if (tp->t_dupacks > TCPREXMTTHRESH) {
tp->snd_cwnd += tp->t_maxseg;
(void) tcp_output(tp);
goto drop;
@@ -1135,17 +1136,17 @@
* If the congestion window was inflated to account
* for the other side's cached packets, retract it.
*/
- if (tp->t_dupacks > tcprexmtthresh &&
+ if (tp->t_dupacks > TCPREXMTTHRESH &&
tp->snd_cwnd > tp->snd_ssthresh)
tp->snd_cwnd = tp->snd_ssthresh;
tp->t_dupacks = 0;
if (SEQ_GT(ti->ti_ack, tp->snd_max)) {
- tcpstat.tcps_rcvacktoomuch++;
+ STAT(tcpstat.tcps_rcvacktoomuch++);
goto dropafterack;
}
acked = ti->ti_ack - tp->snd_una;
- tcpstat.tcps_rcvackpack++;
- tcpstat.tcps_rcvackbyte += acked;
+ STAT(tcpstat.tcps_rcvackpack++);
+ STAT(tcpstat.tcps_rcvackbyte += acked);
/*
* If we have a timestamp reply, update smoothed
@@ -1227,7 +1228,7 @@
*/
if (so->so_state & SS_FCANTRCVMORE) {
soisfdisconnected(so);
- tp->t_timer[TCPT_2MSL] = tcp_maxidle;
+ tp->t_timer[TCPT_2MSL] = TCP_MAXIDLE;
}
tp->t_state = TCPS_FIN_WAIT_2;
}
@@ -1284,7 +1285,7 @@
/* keep track of pure window updates */
if (ti->ti_len == 0 &&
tp->snd_wl2 == ti->ti_ack && tiwin > tp->snd_wnd)
- tcpstat.tcps_rcvwinupd++;
+ STAT(tcpstat.tcps_rcvwinupd++);
tp->snd_wnd = tiwin;
tp->snd_wl1 = ti->ti_seq;
tp->snd_wl2 = ti->ti_ack;
@@ -1490,12 +1491,8 @@
/* int *ts_present;
* u_int32_t *ts_val, *ts_ecr;
*/
-void
-tcp_dooptions(tp, cp, cnt, ti)
- struct tcpcb *tp;
- u_char *cp;
- int cnt;
- struct tcpiphdr *ti;
+static void
+tcp_dooptions(struct tcpcb *tp, u_char *cp, int cnt, struct tcpiphdr *ti)
{
u_int16_t mss;
int opt, optlen;
@@ -1605,10 +1602,8 @@
* and update averages and current timeout.
*/
-void
-tcp_xmit_timer(tp, rtt)
- register struct tcpcb *tp;
- int rtt;
+static void
+tcp_xmit_timer(register struct tcpcb *tp, int rtt)
{
register short delta;
@@ -1616,7 +1611,7 @@
DEBUG_ARG("tp = %lx", (long)tp);
DEBUG_ARG("rtt = %d", rtt);
- tcpstat.tcps_rttupdated++;
+ STAT(tcpstat.tcps_rttupdated++);
if (tp->t_srtt != 0) {
/*
* srtt is stored as fixed point with 3 bits after the
@@ -1707,7 +1702,7 @@
DEBUG_ARG("tp = %lx", (long)tp);
DEBUG_ARG("offer = %d", offer);
- mss = min(if_mtu, if_mru) - sizeof(struct tcpiphdr);
+ mss = min(IF_MTU, IF_MRU) - sizeof(struct tcpiphdr);
if (offer)
mss = min(mss, offer);
mss = max(mss, 32);
@@ -1716,8 +1711,12 @@
tp->snd_cwnd = mss;
- sbreserve(&so->so_snd, tcp_sndspace+((tcp_sndspace%mss)?(mss-(tcp_sndspace%mss)):0));
- sbreserve(&so->so_rcv, tcp_rcvspace+((tcp_rcvspace%mss)?(mss-(tcp_rcvspace%mss)):0));
+ sbreserve(&so->so_snd, TCP_SNDSPACE + ((TCP_SNDSPACE % mss) ?
+ (mss - (TCP_SNDSPACE % mss)) :
+ 0));
+ sbreserve(&so->so_rcv, TCP_RCVSPACE + ((TCP_RCVSPACE % mss) ?
+ (mss - (TCP_RCVSPACE % mss)) :
+ 0));
DEBUG_MISC((dfd, " returning mss = %d\n", mss));
Modified: trunk/src/host/qemu-neo1973/slirp/tcp_output.c
===================================================================
--- trunk/src/host/qemu-neo1973/slirp/tcp_output.c 2007-10-29 20:40:05 UTC (rev 3302)
+++ trunk/src/host/qemu-neo1973/slirp/tcp_output.c 2007-10-29 21:14:04 UTC (rev 3303)
@@ -48,14 +48,14 @@
* Since this is only used in "stats socket", we give meaning
* names instead of the REAL names
*/
-char *tcpstates[] = {
+const char * const tcpstates[] = {
/* "CLOSED", "LISTEN", "SYN_SENT", "SYN_RCVD", */
"REDIRECT", "LISTEN", "SYN_SENT", "SYN_RCVD",
"ESTABLISHED", "CLOSE_WAIT", "FIN_WAIT_1", "CLOSING",
"LAST_ACK", "FIN_WAIT_2", "TIME_WAIT",
};
-u_char tcp_outflags[TCP_NSTATES] = {
+static const u_char tcp_outflags[TCP_NSTATES] = {
TH_RST|TH_ACK, 0, TH_SYN, TH_SYN|TH_ACK,
TH_ACK, TH_ACK, TH_FIN|TH_ACK, TH_FIN|TH_ACK,
TH_FIN|TH_ACK, TH_ACK, TH_ACK,
@@ -263,7 +263,7 @@
/*
* No reason to send a segment, just return.
*/
- tcpstat.tcps_didnuttin++;
+ STAT(tcpstat.tcps_didnuttin++);
return (0);
@@ -339,13 +339,13 @@
*/
if (len) {
if (tp->t_force && len == 1)
- tcpstat.tcps_sndprobe++;
+ STAT(tcpstat.tcps_sndprobe++);
else if (SEQ_LT(tp->snd_nxt, tp->snd_max)) {
- tcpstat.tcps_sndrexmitpack++;
- tcpstat.tcps_sndrexmitbyte += len;
+ STAT(tcpstat.tcps_sndrexmitpack++);
+ STAT(tcpstat.tcps_sndrexmitbyte += len);
} else {
- tcpstat.tcps_sndpack++;
- tcpstat.tcps_sndbyte += len;
+ STAT(tcpstat.tcps_sndpack++);
+ STAT(tcpstat.tcps_sndbyte += len);
}
m = m_get();
@@ -354,7 +354,7 @@
error = 1;
goto out;
}
- m->m_data += if_maxlinkhdr;
+ m->m_data += IF_MAXLINKHDR;
m->m_len = hdrlen;
/*
@@ -382,13 +382,13 @@
flags |= TH_PUSH;
} else {
if (tp->t_flags & TF_ACKNOW)
- tcpstat.tcps_sndacks++;
+ STAT(tcpstat.tcps_sndacks++);
else if (flags & (TH_SYN|TH_FIN|TH_RST))
- tcpstat.tcps_sndctrl++;
+ STAT(tcpstat.tcps_sndctrl++);
else if (SEQ_GT(tp->snd_up, tp->snd_una))
- tcpstat.tcps_sndurg++;
+ STAT(tcpstat.tcps_sndurg++);
else
- tcpstat.tcps_sndwinup++;
+ STAT(tcpstat.tcps_sndwinup++);
m = m_get();
if (m == NULL) {
@@ -396,7 +396,7 @@
error = 1;
goto out;
}
- m->m_data += if_maxlinkhdr;
+ m->m_data += IF_MAXLINKHDR;
m->m_len = hdrlen;
}
@@ -500,7 +500,7 @@
if (tp->t_rtt == 0) {
tp->t_rtt = 1;
tp->t_rtseq = startseq;
- tcpstat.tcps_segstimed++;
+ STAT(tcpstat.tcps_segstimed++);
}
}
@@ -536,7 +536,7 @@
((struct ip *)ti)->ip_len = m->m_len;
- ((struct ip *)ti)->ip_ttl = ip_defttl;
+ ((struct ip *)ti)->ip_ttl = IPDEFTTL;
((struct ip *)ti)->ip_tos = so->so_iptos;
/* #if BSD >= 43 */
@@ -567,7 +567,7 @@
*/
return (error);
}
- tcpstat.tcps_sndtotal++;
+ STAT(tcpstat.tcps_sndtotal++);
/*
* Data sent (as far as we can tell).
Modified: trunk/src/host/qemu-neo1973/slirp/tcp_subr.c
===================================================================
--- trunk/src/host/qemu-neo1973/slirp/tcp_subr.c 2007-10-29 20:40:05 UTC (rev 3302)
+++ trunk/src/host/qemu-neo1973/slirp/tcp_subr.c 2007-10-29 21:14:04 UTC (rev 3303)
@@ -46,11 +46,8 @@
#include <slirp.h>
/* patchable/settable parameters for tcp */
-int tcp_mssdflt = TCP_MSS;
-int tcp_rttdflt = TCPTV_SRTTDFLT / PR_SLOWHZ;
-int tcp_do_rfc1323 = 0; /* Don't do rfc1323 performance enhancements */
-int tcp_rcvspace; /* You may want to change this */
-int tcp_sndspace; /* Keep small if you have an error prone link */
+/* Don't do rfc1323 performance enhancements */
+#define TCP_DO_RFC1323 0
/*
* Tcp initialization
@@ -60,14 +57,6 @@
{
tcp_iss = 1; /* wrong */
tcb.so_next = tcb.so_prev = &tcb;
-
- /* tcp_rcvspace = our Window we advertise to the remote */
- tcp_rcvspace = TCP_RCVSPACE;
- tcp_sndspace = TCP_SNDSPACE;
-
- /* Make sure tcp_sndspace is at least 2*MSS */
- if (tcp_sndspace < 2*(min(if_mtu, if_mru) - sizeof(struct tcpiphdr)))
- tcp_sndspace = 2*(min(if_mtu, if_mru) - sizeof(struct tcpiphdr));
}
/*
@@ -145,7 +134,7 @@
#else
tlen = 0;
#endif
- m->m_data += if_maxlinkhdr;
+ m->m_data += IF_MAXLINKHDR;
*mtod(m, struct tcpiphdr *) = *ti;
ti = mtod(m, struct tcpiphdr *);
flags = TH_ACK;
@@ -186,7 +175,7 @@
if(flags & TH_RST)
((struct ip *)ti)->ip_ttl = MAXTTL;
else
- ((struct ip *)ti)->ip_ttl = ip_defttl;
+ ((struct ip *)ti)->ip_ttl = IPDEFTTL;
(void) ip_output((struct socket *)0, m);
}
@@ -208,9 +197,9 @@
memset((char *) tp, 0, sizeof(struct tcpcb));
tp->seg_next = tp->seg_prev = (tcpiphdrp_32)tp;
- tp->t_maxseg = tcp_mssdflt;
+ tp->t_maxseg = TCP_MSS;
- tp->t_flags = tcp_do_rfc1323 ? (TF_REQ_SCALE|TF_REQ_TSTMP) : 0;
+ tp->t_flags = TCP_DO_RFC1323 ? (TF_REQ_SCALE|TF_REQ_TSTMP) : 0;
tp->t_socket = so;
/*
@@ -219,7 +208,7 @@
* reasonable initial retransmit time.
*/
tp->t_srtt = TCPTV_SRTTBASE;
- tp->t_rttvar = tcp_rttdflt * PR_SLOWHZ << 2;
+ tp->t_rttvar = TCPTV_SRTTDFLT << 2;
tp->t_rttmin = TCPTV_MIN;
TCPT_RANGESET(tp->t_rxtcur,
@@ -255,9 +244,9 @@
if (TCPS_HAVERCVDSYN(tp->t_state)) {
tp->t_state = TCPS_CLOSED;
(void) tcp_output(tp);
- tcpstat.tcps_drops++;
+ STAT(tcpstat.tcps_drops++);
} else
- tcpstat.tcps_conndrops++;
+ STAT(tcpstat.tcps_conndrops++);
/* if (errno == ETIMEDOUT && tp->t_softerror)
* errno = tp->t_softerror;
*/
@@ -305,10 +294,11 @@
sbfree(&so->so_rcv);
sbfree(&so->so_snd);
sofree(so);
- tcpstat.tcps_closed++;
+ STAT(tcpstat.tcps_closed++);
return ((struct tcpcb *)0);
}
+#ifdef notdef
void
tcp_drain()
{
@@ -319,9 +309,6 @@
* When a source quench is received, close congestion window
* to one segment. We will gradually open it again as we proceed.
*/
-
-#ifdef notdef
-
void
tcp_quench(i, errno)
@@ -528,7 +515,7 @@
*/
/* soisconnecting(so); */ /* NOFDREF used instead */
- tcpstat.tcps_connattempt++;
+ STAT(tcpstat.tcps_connattempt++);
tp->t_state = TCPS_SYN_SENT;
tp->t_timer[TCPT_KEEP] = TCPTV_KEEP_INIT;
@@ -556,7 +543,7 @@
/*
* Set the socket's type of service field
*/
-struct tos_t tcptos[] = {
+static const struct tos_t tcptos[] = {
{0, 20, IPTOS_THROUGHPUT, 0}, /* ftp data */
{21, 21, IPTOS_LOWDELAY, EMU_FTP}, /* ftp control */
{0, 23, IPTOS_LOWDELAY, 0}, /* telnet */
@@ -572,7 +559,7 @@
{0, 0, 0, 0}
};
-struct emu_t *tcpemu = 0;
+static struct emu_t *tcpemu = 0;
/*
* Return TOS according to the above table
@@ -605,7 +592,9 @@
return 0;
}
+#if 0
int do_echo = -1;
+#endif
/*
* Emulate programs that try and connect to us
@@ -665,7 +654,7 @@
so_rcv->sb_rptr += m->m_len;
m->m_data[m->m_len] = 0; /* NULL terminate */
if (strchr(m->m_data, '\r') || strchr(m->m_data, '\n')) {
- if (sscanf(so_rcv->sb_data, "%d%*[ ,]%d", &n1, &n2) == 2) {
+ if (sscanf(so_rcv->sb_data, "%u%*[ ,]%u", &n1, &n2) == 2) {
HTONS(n1);
HTONS(n2);
/* n2 is the one on our host */
@@ -857,7 +846,7 @@
/*soisfconnecting(ns);*/
- tcpstat.tcps_connattempt++;
+ STAT(tcpstat.tcps_connattempt++);
tp->t_state = TCPS_SYN_SENT;
tp->t_timer[TCPT_KEEP] = TCPTV_KEEP_INIT;
@@ -991,7 +980,7 @@
/*
* Need to emulate the PORT command
*/
- x = sscanf(bptr, "ORT %d,%d,%d,%d,%d,%d\r\n%256[^\177]",
+ x = sscanf(bptr, "ORT %u,%u,%u,%u,%u,%u\r\n%256[^\177]",
&n1, &n2, &n3, &n4, &n5, &n6, buff);
if (x < 6)
return 1;
@@ -1022,7 +1011,7 @@
/*
* Need to emulate the PASV response
*/
- x = sscanf(bptr, "27 Entering Passive Mode (%d,%d,%d,%d,%d,%d)\r\n%256[^\177]",
+ x = sscanf(bptr, "27 Entering Passive Mode (%u,%u,%u,%u,%u,%u)\r\n%256[^\177]",
&n1, &n2, &n3, &n4, &n5, &n6, buff);
if (x < 6)
return 1;
Modified: trunk/src/host/qemu-neo1973/slirp/tcp_timer.c
===================================================================
--- trunk/src/host/qemu-neo1973/slirp/tcp_timer.c 2007-10-29 20:40:05 UTC (rev 3302)
+++ trunk/src/host/qemu-neo1973/slirp/tcp_timer.c 2007-10-29 21:14:04 UTC (rev 3303)
@@ -36,14 +36,14 @@
#include <slirp.h>
-int tcp_keepidle = TCPTV_KEEP_IDLE;
-int tcp_keepintvl = TCPTV_KEEPINTVL;
-int tcp_maxidle;
-int so_options = DO_KEEPALIVE;
-
+#ifdef LOG_ENABLED
struct tcpstat tcpstat; /* tcp statistics */
+#endif
+
u_int32_t tcp_now; /* for RFC 1323 timestamps */
+static struct tcpcb *tcp_timers(register struct tcpcb *tp, int timer);
+
/*
* Fast timeout routine for processing delayed acks
*/
@@ -62,7 +62,7 @@
(tp->t_flags & TF_DELACK)) {
tp->t_flags &= ~TF_DELACK;
tp->t_flags |= TF_ACKNOW;
- tcpstat.tcps_delack++;
+ STAT(tcpstat.tcps_delack++);
(void) tcp_output(tp);
}
}
@@ -81,7 +81,6 @@
DEBUG_CALL("tcp_slowtimo");
- tcp_maxidle = TCPTV_KEEPCNT * tcp_keepintvl;
/*
* Search through tcb's and update active timers.
*/
@@ -127,16 +126,14 @@
tp->t_timer[i] = 0;
}
-int tcp_backoff[TCP_MAXRXTSHIFT + 1] =
+const int tcp_backoff[TCP_MAXRXTSHIFT + 1] =
{ 1, 2, 4, 8, 16, 32, 64, 64, 64, 64, 64, 64, 64 };
/*
* TCP timer processing.
*/
-struct tcpcb *
-tcp_timers(tp, timer)
- register struct tcpcb *tp;
- int timer;
+static struct tcpcb *
+tcp_timers(register struct tcpcb *tp, int timer)
{
register int rexmt;
@@ -152,8 +149,8 @@
*/
case TCPT_2MSL:
if (tp->t_state != TCPS_TIME_WAIT &&
- tp->t_idle <= tcp_maxidle)
- tp->t_timer[TCPT_2MSL] = tcp_keepintvl;
+ tp->t_idle <= TCP_MAXIDLE)
+ tp->t_timer[TCPT_2MSL] = TCPTV_KEEPINTVL;
else
tp = tcp_close(tp);
break;
@@ -192,7 +189,7 @@
* We tried our best, now the connection must die!
*/
tp->t_rxtshift = TCP_MAXRXTSHIFT;
- tcpstat.tcps_timeoutdrop++;
+ STAT(tcpstat.tcps_timeoutdrop++);
tp = tcp_drop(tp, tp->t_softerror);
/* tp->t_softerror : ETIMEDOUT); */ /* XXX */
return (tp); /* XXX */
@@ -204,7 +201,7 @@
*/
tp->t_rxtshift = 6;
}
- tcpstat.tcps_rexmttimeo++;
+ STAT(tcpstat.tcps_rexmttimeo++);
rexmt = TCP_REXMTVAL(tp) * tcp_backoff[tp->t_rxtshift];
TCPT_RANGESET(tp->t_rxtcur, rexmt,
(short)tp->t_rttmin, TCPTV_REXMTMAX); /* XXX */
@@ -267,7 +264,7 @@
* Force a byte to be output, if possible.
*/
case TCPT_PERSIST:
- tcpstat.tcps_persisttimeo++;
+ STAT(tcpstat.tcps_persisttimeo++);
tcp_setpersist(tp);
tp->t_force = 1;
(void) tcp_output(tp);
@@ -279,13 +276,13 @@
* or drop connection if idle for too long.
*/
case TCPT_KEEP:
- tcpstat.tcps_keeptimeo++;
+ STAT(tcpstat.tcps_keeptimeo++);
if (tp->t_state < TCPS_ESTABLISHED)
goto dropit;
/* if (tp->t_socket->so_options & SO_KEEPALIVE && */
- if ((so_options) && tp->t_state <= TCPS_CLOSE_WAIT) {
- if (tp->t_idle >= tcp_keepidle + tcp_maxidle)
+ if ((SO_OPTIONS) && tp->t_state <= TCPS_CLOSE_WAIT) {
+ if (tp->t_idle >= TCPTV_KEEP_IDLE + TCP_MAXIDLE)
goto dropit;
/*
* Send a packet designed to force a response
@@ -299,7 +296,7 @@
* by the protocol spec, this requires the
* correspondent TCP to respond.
*/
- tcpstat.tcps_keepprobe++;
+ STAT(tcpstat.tcps_keepprobe++);
#ifdef TCP_COMPAT_42
/*
* The keepalive packet must have nonzero length
@@ -311,13 +308,13 @@
tcp_respond(tp, &tp->t_template, (struct mbuf *)NULL,
tp->rcv_nxt, tp->snd_una - 1, 0);
#endif
- tp->t_timer[TCPT_KEEP] = tcp_keepintvl;
+ tp->t_timer[TCPT_KEEP] = TCPTV_KEEPINTVL;
} else
- tp->t_timer[TCPT_KEEP] = tcp_keepidle;
+ tp->t_timer[TCPT_KEEP] = TCPTV_KEEP_IDLE;
break;
dropit:
- tcpstat.tcps_keepdrops++;
+ STAT(tcpstat.tcps_keepdrops++);
tp = tcp_drop(tp, 0); /* ETIMEDOUT); */
break;
}
Modified: trunk/src/host/qemu-neo1973/slirp/tcp_timer.h
===================================================================
--- trunk/src/host/qemu-neo1973/slirp/tcp_timer.h 2007-10-29 20:40:05 UTC (rev 3302)
+++ trunk/src/host/qemu-neo1973/slirp/tcp_timer.h 2007-10-29 21:14:04 UTC (rev 3303)
@@ -126,17 +126,12 @@
(tv) = (tvmax); \
}
-extern int tcp_keepidle; /* time before keepalive probes begin */
-extern int tcp_keepintvl; /* time between keepalive probes */
-extern int tcp_maxidle; /* time to drop after starting probes */
-extern int tcp_ttl; /* time to live for TCP segs */
-extern int tcp_backoff[];
+extern const int tcp_backoff[];
struct tcpcb;
void tcp_fasttimo _P((void));
void tcp_slowtimo _P((void));
void tcp_canceltimers _P((struct tcpcb *));
-struct tcpcb * tcp_timers _P((register struct tcpcb *, int));
#endif
Modified: trunk/src/host/qemu-neo1973/slirp/tcp_var.h
===================================================================
--- trunk/src/host/qemu-neo1973/slirp/tcp_var.h 2007-10-29 20:40:05 UTC (rev 3302)
+++ trunk/src/host/qemu-neo1973/slirp/tcp_var.h 2007-10-29 21:14:04 UTC (rev 3303)
@@ -185,6 +185,7 @@
#endif
#define REASS_MBUF(ti) (*(mbufp_32 *)&((ti)->ti_t))
+#ifdef LOG_ENABLED
/*
* TCP statistics.
* Many of these should be kept per connection,
@@ -247,6 +248,8 @@
};
extern struct tcpstat tcpstat; /* tcp statistics */
+#endif
+
extern u_int32_t tcp_now; /* for RFC 1323 timestamps */
#endif
Modified: trunk/src/host/qemu-neo1973/slirp/tftp.c
===================================================================
--- trunk/src/host/qemu-neo1973/slirp/tftp.c 2007-10-29 20:40:05 UTC (rev 3302)
+++ trunk/src/host/qemu-neo1973/slirp/tftp.c 2007-10-29 21:14:04 UTC (rev 3303)
@@ -34,7 +34,7 @@
int timestamp;
};
-struct tftp_session tftp_sessions[TFTP_SESSIONS_MAX];
+static struct tftp_session tftp_sessions[TFTP_SESSIONS_MAX];
const char *tftp_prefix;
@@ -143,7 +143,7 @@
memset(m->m_data, 0, m->m_size);
- m->m_data += if_maxlinkhdr;
+ m->m_data += IF_MAXLINKHDR;
tp = (void *)m->m_data;
m->m_data += sizeof(struct udpiphdr);
@@ -183,7 +183,7 @@
memset(m->m_data, 0, m->m_size);
- m->m_data += if_maxlinkhdr;
+ m->m_data += IF_MAXLINKHDR;
tp = (void *)m->m_data;
m->m_data += sizeof(struct udpiphdr);
@@ -230,7 +230,7 @@
memset(m->m_data, 0, m->m_size);
- m->m_data += if_maxlinkhdr;
+ m->m_data += IF_MAXLINKHDR;
tp = (void *)m->m_data;
m->m_data += sizeof(struct udpiphdr);
Modified: trunk/src/host/qemu-neo1973/slirp/udp.c
===================================================================
--- trunk/src/host/qemu-neo1973/slirp/udp.c 2007-10-29 20:40:05 UTC (rev 3302)
+++ trunk/src/host/qemu-neo1973/slirp/udp.c 2007-10-29 21:14:04 UTC (rev 3303)
@@ -45,18 +45,23 @@
#include <slirp.h>
#include "ip_icmp.h"
+#ifdef LOG_ENABLED
struct udpstat udpstat;
+#endif
struct socket udb;
+static u_int8_t udp_tos(struct socket *so);
+static void udp_emu(struct socket *so, struct mbuf *m);
+
/*
* UDP protocol implementation.
* Per RFC 768, August, 1980.
*/
#ifndef COMPAT_42
-int udpcksum = 1;
+#define UDPCKSUM 1
#else
-int udpcksum = 0; /* XXX */
+#define UDPCKSUM 0 /* XXX */
#endif
struct socket *udp_last_so = &udb;
@@ -86,7 +91,7 @@
DEBUG_ARG("m = %lx", (long)m);
DEBUG_ARG("iphlen = %d", iphlen);
- udpstat.udps_ipackets++;
+ STAT(udpstat.udps_ipackets++);
/*
* Strip IP options, if any; should skip this,
@@ -113,7 +118,7 @@
if (ip->ip_len != len) {
if (len > ip->ip_len) {
- udpstat.udps_badlen++;
+ STAT(udpstat.udps_badlen++);
goto bad;
}
m_adj(m, len - ip->ip_len);
@@ -130,7 +135,7 @@
/*
* Checksum extended UDP header and data.
*/
- if (udpcksum && uh->uh_sum) {
+ if (UDPCKSUM && uh->uh_sum) {
((struct ipovly *)ip)->ih_next = 0;
((struct ipovly *)ip)->ih_prev = 0;
((struct ipovly *)ip)->ih_x1 = 0;
@@ -140,7 +145,7 @@
* if (uh->uh_sum) {
*/
if(cksum(m, len + sizeof(struct ip))) {
- udpstat.udps_badsum++;
+ STAT(udpstat.udps_badsum++);
goto bad;
}
}
@@ -181,7 +186,7 @@
if (tmp == &udb) {
so = NULL;
} else {
- udpstat.udpps_pcbcachemiss++;
+ STAT(udpstat.udpps_pcbcachemiss++);
udp_last_so = so;
}
}
@@ -290,16 +295,16 @@
* Stuff checksum and output datagram.
*/
ui->ui_sum = 0;
- if (udpcksum) {
+ if (UDPCKSUM) {
if ((ui->ui_sum = cksum(m, /* sizeof (struct udpiphdr) + */ m->m_len)) == 0)
ui->ui_sum = 0xffff;
}
((struct ip *)ui)->ip_len = m->m_len;
- ((struct ip *)ui)->ip_ttl = ip_defttl;
+ ((struct ip *)ui)->ip_ttl = IPDEFTTL;
((struct ip *)ui)->ip_tos = iptos;
- udpstat.udps_opackets++;
+ STAT(udpstat.udps_opackets++);
error = ip_output(so, m);
@@ -367,7 +372,7 @@
sofree(so);
}
-struct tos_t udptos[] = {
+static const struct tos_t udptos[] = {
{0, 53, IPTOS_LOWDELAY, 0}, /* DNS */
{517, 517, IPTOS_LOWDELAY, EMU_TALK}, /* talk */
{518, 518, IPTOS_LOWDELAY, EMU_NTALK}, /* ntalk */
@@ -375,9 +380,8 @@
{0, 0, 0, 0}
};
-u_int8_t
-udp_tos(so)
- struct socket *so;
+static u_int8_t
+udp_tos(struct socket *so)
{
int i = 0;
@@ -400,10 +404,8 @@
/*
* Here, talk/ytalk/ntalk requests must be emulated
*/
-void
-udp_emu(so, m)
- struct socket *so;
- struct mbuf *m;
+static void
+udp_emu(struct socket *so, struct mbuf *m)
{
struct sockaddr_in addr;
int addrlen = sizeof(addr);
Modified: trunk/src/host/qemu-neo1973/slirp/udp.h
===================================================================
--- trunk/src/host/qemu-neo1973/slirp/udp.h 2007-10-29 20:40:05 UTC (rev 3302)
+++ trunk/src/host/qemu-neo1973/slirp/udp.h 2007-10-29 21:14:04 UTC (rev 3303)
@@ -72,6 +72,7 @@
#define ui_ulen ui_u.uh_ulen
#define ui_sum ui_u.uh_sum
+#ifdef LOG_ENABLED
struct udpstat {
/* input statistics: */
u_long udps_ipackets; /* total input packets */
@@ -85,6 +86,7 @@
/* output statistics: */
u_long udps_opackets; /* total output packets */
};
+#endif
/*
* Names for UDP sysctl objects
@@ -92,7 +94,10 @@
#define UDPCTL_CHECKSUM 1 /* checksum UDP packets */
#define UDPCTL_MAXID 2
+#ifdef LOG_ENABLED
extern struct udpstat udpstat;
+#endif
+
extern struct socket udb;
struct mbuf;
@@ -101,8 +106,6 @@
int udp_output _P((struct socket *, struct mbuf *, struct sockaddr_in *));
int udp_attach _P((struct socket *));
void udp_detach _P((struct socket *));
-u_int8_t udp_tos _P((struct socket *));
-void udp_emu _P((struct socket *, struct mbuf *));
struct socket * udp_listen _P((u_int, u_int32_t, u_int, int));
int udp_output2(struct socket *so, struct mbuf *m,
struct sockaddr_in *saddr, struct sockaddr_in *daddr,
Modified: trunk/src/host/qemu-neo1973/softmmu_exec.h
===================================================================
--- trunk/src/host/qemu-neo1973/softmmu_exec.h 2007-10-29 20:40:05 UTC (rev 3302)
+++ trunk/src/host/qemu-neo1973/softmmu_exec.h 2007-10-29 21:14:04 UTC (rev 3303)
@@ -1,10 +1,16 @@
/* Common softmmu definitions and inline routines. */
-#define ldul_user ldl_user
-#define ldul_kernel ldl_kernel
+/* XXX: find something cleaner.
+ * Furthermore, this is false for 64 bits targets
+ */
+#define ldul_user ldl_user
+#define ldul_kernel ldl_kernel
+#define ldul_hypv ldl_hypv
+#define ldul_executive ldl_executive
+#define ldul_supervisor ldl_supervisor
#define ACCESS_TYPE 0
-#define MEMSUFFIX _kernel
+#define MEMSUFFIX MMU_MODE0_SUFFIX
#define DATA_SIZE 1
#include "softmmu_header.h"
@@ -20,7 +26,7 @@
#undef MEMSUFFIX
#define ACCESS_TYPE 1
-#define MEMSUFFIX _user
+#define MEMSUFFIX MMU_MODE1_SUFFIX
#define DATA_SIZE 1
#include "softmmu_header.h"
@@ -35,8 +41,50 @@
#undef ACCESS_TYPE
#undef MEMSUFFIX
+#if (NB_MMU_MODES >= 3)
+
+#define ACCESS_TYPE 2
+#define MEMSUFFIX MMU_MODE2_SUFFIX
+#define DATA_SIZE 1
+#include "softmmu_header.h"
+
+#define DATA_SIZE 2
+#include "softmmu_header.h"
+
+#define DATA_SIZE 4
+#include "softmmu_header.h"
+
+#define DATA_SIZE 8
+#include "softmmu_header.h"
+#undef ACCESS_TYPE
+#undef MEMSUFFIX
+
+#if (NB_MMU_MODES >= 4)
+
+#define ACCESS_TYPE 3
+#define MEMSUFFIX MMU_MODE3_SUFFIX
+#define DATA_SIZE 1
+#include "softmmu_header.h"
+
+#define DATA_SIZE 2
+#include "softmmu_header.h"
+
+#define DATA_SIZE 4
+#include "softmmu_header.h"
+
+#define DATA_SIZE 8
+#include "softmmu_header.h"
+#undef ACCESS_TYPE
+#undef MEMSUFFIX
+
+#if (NB_MMU_MODES > 4)
+#error "NB_MMU_MODES > 4 is not supported for now"
+#endif /* (NB_MMU_MODES > 4) */
+#endif /* (NB_MMU_MODES == 4) */
+#endif /* (NB_MMU_MODES >= 3) */
+
/* these access are slower, they must be as rare as possible */
-#define ACCESS_TYPE 2
+#define ACCESS_TYPE (NB_MMU_MODES)
#define MEMSUFFIX _data
#define DATA_SIZE 1
#include "softmmu_header.h"
Modified: trunk/src/host/qemu-neo1973/softmmu_header.h
===================================================================
--- trunk/src/host/qemu-neo1973/softmmu_header.h 2007-10-29 20:40:05 UTC (rev 3302)
+++ trunk/src/host/qemu-neo1973/softmmu_header.h 2007-10-29 21:14:04 UTC (rev 3303)
@@ -39,60 +39,19 @@
#error unsupported data size
#endif
-#if ACCESS_TYPE == 0
+#if ACCESS_TYPE < (NB_MMU_MODES)
-#define CPU_MEM_INDEX 0
+#define CPU_MMU_INDEX ACCESS_TYPE
#define MMUSUFFIX _mmu
-#elif ACCESS_TYPE == 1
+#elif ACCESS_TYPE == (NB_MMU_MODES)
-#define CPU_MEM_INDEX 1
+#define CPU_MMU_INDEX (cpu_mmu_index(env))
#define MMUSUFFIX _mmu
-#elif ACCESS_TYPE == 2
+#elif ACCESS_TYPE == (NB_MMU_MODES + 1)
-#ifdef TARGET_I386
-#define CPU_MEM_INDEX ((env->hflags & HF_CPL_MASK) == 3)
-#elif defined (TARGET_PPC)
-#define CPU_MEM_INDEX (msr_pr)
-#elif defined (TARGET_MIPS)
-#define CPU_MEM_INDEX ((env->hflags & MIPS_HFLAG_MODE) == MIPS_HFLAG_UM)
-#elif defined (TARGET_SPARC)
-#define CPU_MEM_INDEX ((env->psrs) == 0)
-#elif defined (TARGET_ARM)
-#define CPU_MEM_INDEX ((env->uncached_cpsr & CPSR_M) == ARM_CPU_MODE_USR)
-#elif defined (TARGET_SH4)
-#define CPU_MEM_INDEX ((env->sr & SR_MD) == 0)
-#elif defined (TARGET_ALPHA)
-#define CPU_MEM_INDEX ((env->ps >> 3) & 3)
-#elif defined (TARGET_M68K)
-#define CPU_MEM_INDEX ((env->sr & SR_S) == 0)
-#else
-#error unsupported CPU
-#endif
-#define MMUSUFFIX _mmu
-
-#elif ACCESS_TYPE == 3
-
-#ifdef TARGET_I386
-#define CPU_MEM_INDEX ((env->hflags & HF_CPL_MASK) == 3)
-#elif defined (TARGET_PPC)
-#define CPU_MEM_INDEX (msr_pr)
-#elif defined (TARGET_MIPS)
-#define CPU_MEM_INDEX ((env->hflags & MIPS_HFLAG_MODE) == MIPS_HFLAG_UM)
-#elif defined (TARGET_SPARC)
-#define CPU_MEM_INDEX ((env->psrs) == 0)
-#elif defined (TARGET_ARM)
-#define CPU_MEM_INDEX ((env->uncached_cpsr & CPSR_M) == ARM_CPU_MODE_USR)
-#elif defined (TARGET_SH4)
-#define CPU_MEM_INDEX ((env->sr & SR_MD) == 0)
-#elif defined (TARGET_ALPHA)
-#define CPU_MEM_INDEX ((env->ps >> 3) & 3)
-#elif defined (TARGET_M68K)
-#define CPU_MEM_INDEX ((env->sr & SR_S) == 0)
-#else
-#error unsupported CPU
-#endif
+#define CPU_MMU_INDEX (cpu_mmu_index(env))
#define MMUSUFFIX _cmmu
#else
@@ -105,18 +64,18 @@
#define RES_TYPE int
#endif
-#if ACCESS_TYPE == 3
+#if ACCESS_TYPE == (NB_MMU_MODES + 1)
#define ADDR_READ addr_code
#else
#define ADDR_READ addr_read
#endif
DATA_TYPE REGPARM(1) glue(glue(__ld, SUFFIX), MMUSUFFIX)(target_ulong addr,
- int is_user);
-void REGPARM(2) glue(glue(__st, SUFFIX), MMUSUFFIX)(target_ulong addr, DATA_TYPE v, int is_user);
+ int mmu_idx);
+void REGPARM(2) glue(glue(__st, SUFFIX), MMUSUFFIX)(target_ulong addr, DATA_TYPE v, int mmu_idx);
#if (DATA_SIZE <= 4) && (TARGET_LONG_BITS == 32) && defined(__i386__) && \
- (ACCESS_TYPE <= 1) && defined(ASM_SOFTMMU)
+ (ACCESS_TYPE < NB_MMU_MODES) && defined(ASM_SOFTMMU)
#define CPU_TLB_ENTRY_BITS 4
@@ -155,8 +114,8 @@
"i" ((CPU_TLB_SIZE - 1) << CPU_TLB_ENTRY_BITS),
"i" (TARGET_PAGE_BITS - CPU_TLB_ENTRY_BITS),
"i" (TARGET_PAGE_MASK | (DATA_SIZE - 1)),
- "m" (*(uint32_t *)offsetof(CPUState, tlb_table[CPU_MEM_INDEX][0].addr_read)),
- "i" (CPU_MEM_INDEX),
+ "m" (*(uint32_t *)offsetof(CPUState, tlb_table[CPU_MMU_INDEX][0].addr_read)),
+ "i" (CPU_MMU_INDEX),
"m" (*(uint8_t *)&glue(glue(__ld, SUFFIX), MMUSUFFIX))
: "%eax", "%ecx", "%edx", "memory", "cc");
return res;
@@ -202,8 +161,8 @@
"i" ((CPU_TLB_SIZE - 1) << CPU_TLB_ENTRY_BITS),
"i" (TARGET_PAGE_BITS - CPU_TLB_ENTRY_BITS),
"i" (TARGET_PAGE_MASK | (DATA_SIZE - 1)),
- "m" (*(uint32_t *)offsetof(CPUState, tlb_table[CPU_MEM_INDEX][0].addr_read)),
- "i" (CPU_MEM_INDEX),
+ "m" (*(uint32_t *)offsetof(CPUState, tlb_table[CPU_MMU_INDEX][0].addr_read)),
+ "i" (CPU_MMU_INDEX),
"m" (*(uint8_t *)&glue(glue(__ld, SUFFIX), MMUSUFFIX))
: "%eax", "%ecx", "%edx", "memory", "cc");
return res;
@@ -254,8 +213,8 @@
"i" ((CPU_TLB_SIZE - 1) << CPU_TLB_ENTRY_BITS),
"i" (TARGET_PAGE_BITS - CPU_TLB_ENTRY_BITS),
"i" (TARGET_PAGE_MASK | (DATA_SIZE - 1)),
- "m" (*(uint32_t *)offsetof(CPUState, tlb_table[CPU_MEM_INDEX][0].addr_write)),
- "i" (CPU_MEM_INDEX),
+ "m" (*(uint32_t *)offsetof(CPUState, tlb_table[CPU_MMU_INDEX][0].addr_write)),
+ "i" (CPU_MMU_INDEX),
"m" (*(uint8_t *)&glue(glue(__st, SUFFIX), MMUSUFFIX))
: "%eax", "%ecx", "%edx", "memory", "cc");
}
@@ -270,16 +229,16 @@
RES_TYPE res;
target_ulong addr;
unsigned long physaddr;
- int is_user;
+ int mmu_idx;
addr = ptr;
index = (addr >> TARGET_PAGE_BITS) & (CPU_TLB_SIZE - 1);
- is_user = CPU_MEM_INDEX;
- if (__builtin_expect(env->tlb_table[is_user][index].ADDR_READ !=
+ mmu_idx = CPU_MMU_INDEX;
+ if (__builtin_expect(env->tlb_table[mmu_idx][index].ADDR_READ !=
(addr & (TARGET_PAGE_MASK | (DATA_SIZE - 1))), 0)) {
- res = glue(glue(__ld, SUFFIX), MMUSUFFIX)(addr, is_user);
+ res = glue(glue(__ld, SUFFIX), MMUSUFFIX)(addr, mmu_idx);
} else {
- physaddr = addr + env->tlb_table[is_user][index].addend;
+ physaddr = addr + env->tlb_table[mmu_idx][index].addend;
res = glue(glue(ld, USUFFIX), _raw)((uint8_t *)physaddr);
}
return res;
@@ -291,23 +250,23 @@
int res, index;
target_ulong addr;
unsigned long physaddr;
- int is_user;
+ int mmu_idx;
addr = ptr;
index = (addr >> TARGET_PAGE_BITS) & (CPU_TLB_SIZE - 1);
- is_user = CPU_MEM_INDEX;
- if (__builtin_expect(env->tlb_table[is_user][index].ADDR_READ !=
+ mmu_idx = CPU_MMU_INDEX;
+ if (__builtin_expect(env->tlb_table[mmu_idx][index].ADDR_READ !=
(addr & (TARGET_PAGE_MASK | (DATA_SIZE - 1))), 0)) {
- res = (DATA_STYPE)glue(glue(__ld, SUFFIX), MMUSUFFIX)(addr, is_user);
+ res = (DATA_STYPE)glue(glue(__ld, SUFFIX), MMUSUFFIX)(addr, mmu_idx);
} else {
- physaddr = addr + env->tlb_table[is_user][index].addend;
+ physaddr = addr + env->tlb_table[mmu_idx][index].addend;
res = glue(glue(lds, SUFFIX), _raw)((uint8_t *)physaddr);
}
return res;
}
#endif
-#if ACCESS_TYPE != 3
+#if ACCESS_TYPE != (NB_MMU_MODES + 1)
/* generic store macro */
@@ -316,25 +275,25 @@
int index;
target_ulong addr;
unsigned long physaddr;
- int is_user;
+ int mmu_idx;
addr = ptr;
index = (addr >> TARGET_PAGE_BITS) & (CPU_TLB_SIZE - 1);
- is_user = CPU_MEM_INDEX;
- if (__builtin_expect(env->tlb_table[is_user][index].addr_write !=
+ mmu_idx = CPU_MMU_INDEX;
+ if (__builtin_expect(env->tlb_table[mmu_idx][index].addr_write !=
(addr & (TARGET_PAGE_MASK | (DATA_SIZE - 1))), 0)) {
- glue(glue(__st, SUFFIX), MMUSUFFIX)(addr, v, is_user);
+ glue(glue(__st, SUFFIX), MMUSUFFIX)(addr, v, mmu_idx);
} else {
- physaddr = addr + env->tlb_table[is_user][index].addend;
+ physaddr = addr + env->tlb_table[mmu_idx][index].addend;
glue(glue(st, SUFFIX), _raw)((uint8_t *)physaddr, v);
}
}
-#endif /* ACCESS_TYPE != 3 */
+#endif /* ACCESS_TYPE != (NB_MMU_MODES + 1) */
#endif /* !asm */
-#if ACCESS_TYPE != 3
+#if ACCESS_TYPE != (NB_MMU_MODES + 1)
#if DATA_SIZE == 8
static inline float64 glue(ldfq, MEMSUFFIX)(target_ulong ptr)
@@ -380,7 +339,7 @@
}
#endif /* DATA_SIZE == 4 */
-#endif /* ACCESS_TYPE != 3 */
+#endif /* ACCESS_TYPE != (NB_MMU_MODES + 1) */
#undef RES_TYPE
#undef DATA_TYPE
@@ -388,6 +347,6 @@
#undef SUFFIX
#undef USUFFIX
#undef DATA_SIZE
-#undef CPU_MEM_INDEX
+#undef CPU_MMU_INDEX
#undef MMUSUFFIX
#undef ADDR_READ
Modified: trunk/src/host/qemu-neo1973/softmmu_template.h
===================================================================
--- trunk/src/host/qemu-neo1973/softmmu_template.h 2007-10-29 20:40:05 UTC (rev 3302)
+++ trunk/src/host/qemu-neo1973/softmmu_template.h 2007-10-29 21:14:04 UTC (rev 3303)
@@ -48,7 +48,7 @@
#endif
static DATA_TYPE glue(glue(slow_ld, SUFFIX), MMUSUFFIX)(target_ulong addr,
- int is_user,
+ int mmu_idx,
void *retaddr);
static inline DATA_TYPE glue(io_read, SUFFIX)(target_phys_addr_t physaddr,
target_ulong tlb_addr)
@@ -76,7 +76,7 @@
/* handle all cases except unaligned access which span two pages */
DATA_TYPE REGPARM(1) glue(glue(__ld, SUFFIX), MMUSUFFIX)(target_ulong addr,
- int is_user)
+ int mmu_idx)
{
DATA_TYPE res;
int index;
@@ -88,9 +88,9 @@
/* XXX: could done more in memory macro in a non portable way */
index = (addr >> TARGET_PAGE_BITS) & (CPU_TLB_SIZE - 1);
redo:
- tlb_addr = env->tlb_table[is_user][index].ADDR_READ;
+ tlb_addr = env->tlb_table[mmu_idx][index].ADDR_READ;
if ((addr & TARGET_PAGE_MASK) == (tlb_addr & (TARGET_PAGE_MASK | TLB_INVALID_MASK))) {
- physaddr = addr + env->tlb_table[is_user][index].addend;
+ physaddr = addr + env->tlb_table[mmu_idx][index].addend;
if (tlb_addr & ~TARGET_PAGE_MASK) {
/* IO access */
if ((addr & (DATA_SIZE - 1)) != 0)
@@ -101,16 +101,16 @@
do_unaligned_access:
retaddr = GETPC();
#ifdef ALIGNED_ONLY
- do_unaligned_access(addr, READ_ACCESS_TYPE, is_user, retaddr);
+ do_unaligned_access(addr, READ_ACCESS_TYPE, mmu_idx, retaddr);
#endif
res = glue(glue(slow_ld, SUFFIX), MMUSUFFIX)(addr,
- is_user, retaddr);
+ mmu_idx, retaddr);
} else {
/* unaligned/aligned access in the same page */
#ifdef ALIGNED_ONLY
if ((addr & (DATA_SIZE - 1)) != 0) {
retaddr = GETPC();
- do_unaligned_access(addr, READ_ACCESS_TYPE, is_user, retaddr);
+ do_unaligned_access(addr, READ_ACCESS_TYPE, mmu_idx, retaddr);
}
#endif
res = glue(glue(ld, USUFFIX), _raw)((uint8_t *)(long)physaddr);
@@ -120,9 +120,9 @@
retaddr = GETPC();
#ifdef ALIGNED_ONLY
if ((addr & (DATA_SIZE - 1)) != 0)
- do_unaligned_access(addr, READ_ACCESS_TYPE, is_user, retaddr);
+ do_unaligned_access(addr, READ_ACCESS_TYPE, mmu_idx, retaddr);
#endif
- tlb_fill(addr, READ_ACCESS_TYPE, is_user, retaddr);
+ tlb_fill(addr, READ_ACCESS_TYPE, mmu_idx, retaddr);
goto redo;
}
return res;
@@ -130,7 +130,7 @@
/* handle all unaligned cases */
static DATA_TYPE glue(glue(slow_ld, SUFFIX), MMUSUFFIX)(target_ulong addr,
- int is_user,
+ int mmu_idx,
void *retaddr)
{
DATA_TYPE res, res1, res2;
@@ -140,9 +140,9 @@
index = (addr >> TARGET_PAGE_BITS) & (CPU_TLB_SIZE - 1);
redo:
- tlb_addr = env->tlb_table[is_user][index].ADDR_READ;
+ tlb_addr = env->tlb_table[mmu_idx][index].ADDR_READ;
if ((addr & TARGET_PAGE_MASK) == (tlb_addr & (TARGET_PAGE_MASK | TLB_INVALID_MASK))) {
- physaddr = addr + env->tlb_table[is_user][index].addend;
+ physaddr = addr + env->tlb_table[mmu_idx][index].addend;
if (tlb_addr & ~TARGET_PAGE_MASK) {
/* IO access */
if ((addr & (DATA_SIZE - 1)) != 0)
@@ -154,9 +154,9 @@
addr1 = addr & ~(DATA_SIZE - 1);
addr2 = addr1 + DATA_SIZE;
res1 = glue(glue(slow_ld, SUFFIX), MMUSUFFIX)(addr1,
- is_user, retaddr);
+ mmu_idx, retaddr);
res2 = glue(glue(slow_ld, SUFFIX), MMUSUFFIX)(addr2,
- is_user, retaddr);
+ mmu_idx, retaddr);
shift = (addr & (DATA_SIZE - 1)) * 8;
#ifdef TARGET_WORDS_BIGENDIAN
res = (res1 << shift) | (res2 >> ((DATA_SIZE * 8) - shift));
@@ -170,7 +170,7 @@
}
} else {
/* the page is not in the TLB : fill it */
- tlb_fill(addr, READ_ACCESS_TYPE, is_user, retaddr);
+ tlb_fill(addr, READ_ACCESS_TYPE, mmu_idx, retaddr);
goto redo;
}
return res;
@@ -180,7 +180,7 @@
static void glue(glue(slow_st, SUFFIX), MMUSUFFIX)(target_ulong addr,
DATA_TYPE val,
- int is_user,
+ int mmu_idx,
void *retaddr);
static inline void glue(io_write, SUFFIX)(target_phys_addr_t physaddr,
@@ -211,7 +211,7 @@
void REGPARM(2) glue(glue(__st, SUFFIX), MMUSUFFIX)(target_ulong addr,
DATA_TYPE val,
- int is_user)
+ int mmu_idx)
{
target_phys_addr_t physaddr;
target_ulong tlb_addr;
@@ -220,9 +220,9 @@
index = (addr >> TARGET_PAGE_BITS) & (CPU_TLB_SIZE - 1);
redo:
- tlb_addr = env->tlb_table[is_user][index].addr_write;
+ tlb_addr = env->tlb_table[mmu_idx][index].addr_write;
if ((addr & TARGET_PAGE_MASK) == (tlb_addr & (TARGET_PAGE_MASK | TLB_INVALID_MASK))) {
- physaddr = addr + env->tlb_table[is_user][index].addend;
+ physaddr = addr + env->tlb_table[mmu_idx][index].addend;
if (tlb_addr & ~TARGET_PAGE_MASK) {
/* IO access */
if ((addr & (DATA_SIZE - 1)) != 0)
@@ -233,16 +233,16 @@
do_unaligned_access:
retaddr = GETPC();
#ifdef ALIGNED_ONLY
- do_unaligned_access(addr, 1, is_user, retaddr);
+ do_unaligned_access(addr, 1, mmu_idx, retaddr);
#endif
glue(glue(slow_st, SUFFIX), MMUSUFFIX)(addr, val,
- is_user, retaddr);
+ mmu_idx, retaddr);
} else {
/* aligned/unaligned access in the same page */
#ifdef ALIGNED_ONLY
if ((addr & (DATA_SIZE - 1)) != 0) {
retaddr = GETPC();
- do_unaligned_access(addr, 1, is_user, retaddr);
+ do_unaligned_access(addr, 1, mmu_idx, retaddr);
}
#endif
glue(glue(st, SUFFIX), _raw)((uint8_t *)(long)physaddr, val);
@@ -252,9 +252,9 @@
retaddr = GETPC();
#ifdef ALIGNED_ONLY
if ((addr & (DATA_SIZE - 1)) != 0)
- do_unaligned_access(addr, 1, is_user, retaddr);
+ do_unaligned_access(addr, 1, mmu_idx, retaddr);
#endif
- tlb_fill(addr, 1, is_user, retaddr);
+ tlb_fill(addr, 1, mmu_idx, retaddr);
goto redo;
}
}
@@ -262,7 +262,7 @@
/* handles all unaligned cases */
static void glue(glue(slow_st, SUFFIX), MMUSUFFIX)(target_ulong addr,
DATA_TYPE val,
- int is_user,
+ int mmu_idx,
void *retaddr)
{
target_phys_addr_t physaddr;
@@ -271,9 +271,9 @@
index = (addr >> TARGET_PAGE_BITS) & (CPU_TLB_SIZE - 1);
redo:
- tlb_addr = env->tlb_table[is_user][index].addr_write;
+ tlb_addr = env->tlb_table[mmu_idx][index].addr_write;
if ((addr & TARGET_PAGE_MASK) == (tlb_addr & (TARGET_PAGE_MASK | TLB_INVALID_MASK))) {
- physaddr = addr + env->tlb_table[is_user][index].addend;
+ physaddr = addr + env->tlb_table[mmu_idx][index].addend;
if (tlb_addr & ~TARGET_PAGE_MASK) {
/* IO access */
if ((addr & (DATA_SIZE - 1)) != 0)
@@ -285,10 +285,10 @@
for(i = 0;i < DATA_SIZE; i++) {
#ifdef TARGET_WORDS_BIGENDIAN
glue(slow_stb, MMUSUFFIX)(addr + i, val >> (((DATA_SIZE - 1) * 8) - (i * 8)),
- is_user, retaddr);
+ mmu_idx, retaddr);
#else
glue(slow_stb, MMUSUFFIX)(addr + i, val >> (i * 8),
- is_user, retaddr);
+ mmu_idx, retaddr);
#endif
}
} else {
@@ -297,7 +297,7 @@
}
} else {
/* the page is not in the TLB : fill it */
- tlb_fill(addr, 1, is_user, retaddr);
+ tlb_fill(addr, 1, mmu_idx, retaddr);
goto redo;
}
}
Modified: trunk/src/host/qemu-neo1973/sparc-dis.c
===================================================================
--- trunk/src/host/qemu-neo1973/sparc-dis.c 2007-10-29 20:40:05 UTC (rev 3302)
+++ trunk/src/host/qemu-neo1973/sparc-dis.c 2007-10-29 21:14:04 UTC (rev 3303)
@@ -88,21 +88,21 @@
struct sparc_opcode {
const char *name;
- unsigned long match; /* Bits that must be set. */
- unsigned long lose; /* Bits that must not be set. */
+ unsigned long match; /* Bits that must be set. */
+ unsigned long lose; /* Bits that must not be set. */
const char *args;
/* This was called "delayed" in versions before the flags. */
char flags;
- short architecture; /* Bitmask of sparc_opcode_arch_val's. */
+ short architecture; /* Bitmask of sparc_opcode_arch_val's. */
};
-#define F_DELAYED 1 /* Delayed branch */
-#define F_ALIAS 2 /* Alias for a "real" instruction */
-#define F_UNBR 4 /* Unconditional branch */
-#define F_CONDBR 8 /* Conditional branch */
-#define F_JSR 16 /* Subroutine call */
-#define F_FLOAT 32 /* Floating point instruction (not a branch) */
-#define F_FBR 64 /* Floating point branch */
+#define F_DELAYED 1 /* Delayed branch */
+#define F_ALIAS 2 /* Alias for a "real" instruction */
+#define F_UNBR 4 /* Unconditional branch */
+#define F_CONDBR 8 /* Conditional branch */
+#define F_JSR 16 /* Subroutine call */
+#define F_FLOAT 32 /* Floating point instruction (not a branch) */
+#define F_FBR 64 /* Floating point branch */
/* FIXME: Add F_ANACHRONISTIC flag for v9. */
/*
@@ -117,104 +117,104 @@
instruction.
Kinds of operands:
- # Number used by optimizer. It is ignored.
- 1 rs1 register.
- 2 rs2 register.
- d rd register.
- e frs1 floating point register.
- v frs1 floating point register (double/even).
- V frs1 floating point register (quad/multiple of 4).
- f frs2 floating point register.
- B frs2 floating point register (double/even).
- R frs2 floating point register (quad/multiple of 4).
- g frsd floating point register.
- H frsd floating point register (double/even).
- J frsd floating point register (quad/multiple of 4).
- b crs1 coprocessor register
- c crs2 coprocessor register
- D crsd coprocessor register
- m alternate space register (asr) in rd
- M alternate space register (asr) in rs1
- h 22 high bits.
- X 5 bit unsigned immediate
- Y 6 bit unsigned immediate
- 3 SIAM mode (3 bits). (v9b)
- K MEMBAR mask (7 bits). (v9)
- j 10 bit Immediate. (v9)
- I 11 bit Immediate. (v9)
- i 13 bit Immediate.
- n 22 bit immediate.
- k 2+14 bit PC relative immediate. (v9)
- G 19 bit PC relative immediate. (v9)
- l 22 bit PC relative immediate.
- L 30 bit PC relative immediate.
- a Annul. The annul bit is set.
- A Alternate address space. Stored as 8 bits.
- C Coprocessor state register.
- F floating point state register.
- p Processor state register.
- N Branch predict clear ",pn" (v9)
- T Branch predict set ",pt" (v9)
- z %icc. (v9)
- Z %xcc. (v9)
- q Floating point queue.
- r Single register that is both rs1 and rd.
- O Single register that is both rs2 and rd.
- Q Coprocessor queue.
- S Special case.
- t Trap base register.
- w Window invalid mask register.
- y Y register.
- u sparclet coprocessor registers in rd position
- U sparclet coprocessor registers in rs1 position
- E %ccr. (v9)
- s %fprs. (v9)
- P %pc. (v9)
- W %tick. (v9)
- o %asi. (v9)
- 6 %fcc0. (v9)
- 7 %fcc1. (v9)
- 8 %fcc2. (v9)
- 9 %fcc3. (v9)
- ! Privileged Register in rd (v9)
- ? Privileged Register in rs1 (v9)
- * Prefetch function constant. (v9)
- x OPF field (v9 impdep).
- 0 32/64 bit immediate for set or setx (v9) insns
- _ Ancillary state register in rd (v9a)
- / Ancillary state register in rs1 (v9a)
+ # Number used by optimizer. It is ignored.
+ 1 rs1 register.
+ 2 rs2 register.
+ d rd register.
+ e frs1 floating point register.
+ v frs1 floating point register (double/even).
+ V frs1 floating point register (quad/multiple of 4).
+ f frs2 floating point register.
+ B frs2 floating point register (double/even).
+ R frs2 floating point register (quad/multiple of 4).
+ g frsd floating point register.
+ H frsd floating point register (double/even).
+ J frsd floating point register (quad/multiple of 4).
+ b crs1 coprocessor register
+ c crs2 coprocessor register
+ D crsd coprocessor register
+ m alternate space register (asr) in rd
+ M alternate space register (asr) in rs1
+ h 22 high bits.
+ X 5 bit unsigned immediate
+ Y 6 bit unsigned immediate
+ 3 SIAM mode (3 bits). (v9b)
+ K MEMBAR mask (7 bits). (v9)
+ j 10 bit Immediate. (v9)
+ I 11 bit Immediate. (v9)
+ i 13 bit Immediate.
+ n 22 bit immediate.
+ k 2+14 bit PC relative immediate. (v9)
+ G 19 bit PC relative immediate. (v9)
+ l 22 bit PC relative immediate.
+ L 30 bit PC relative immediate.
+ a Annul. The annul bit is set.
+ A Alternate address space. Stored as 8 bits.
+ C Coprocessor state register.
+ F floating point state register.
+ p Processor state register.
+ N Branch predict clear ",pn" (v9)
+ T Branch predict set ",pt" (v9)
+ z %icc. (v9)
+ Z %xcc. (v9)
+ q Floating point queue.
+ r Single register that is both rs1 and rd.
+ O Single register that is both rs2 and rd.
+ Q Coprocessor queue.
+ S Special case.
+ t Trap base register.
+ w Window invalid mask register.
+ y Y register.
+ u sparclet coprocessor registers in rd position
+ U sparclet coprocessor registers in rs1 position
+ E %ccr. (v9)
+ s %fprs. (v9)
+ P %pc. (v9)
+ W %tick. (v9)
+ o %asi. (v9)
+ 6 %fcc0. (v9)
+ 7 %fcc1. (v9)
+ 8 %fcc2. (v9)
+ 9 %fcc3. (v9)
+ ! Privileged Register in rd (v9)
+ ? Privileged Register in rs1 (v9)
+ * Prefetch function constant. (v9)
+ x OPF field (v9 impdep).
+ 0 32/64 bit immediate for set or setx (v9) insns
+ _ Ancillary state register in rd (v9a)
+ / Ancillary state register in rs1 (v9a)
The following chars are unused: (note: ,[] are used as punctuation)
[45]
*/
-#define OP2(x) (((x)&0x7) << 22) /* op2 field of format2 insns */
-#define OP3(x) (((x)&0x3f) << 19) /* op3 field of format3 insns */
-#define OP(x) ((unsigned)((x)&0x3) << 30) /* op field of all insns */
-#define OPF(x) (((x)&0x1ff) << 5) /* opf field of float insns */
-#define OPF_LOW5(x) OPF((x)&0x1f) /* v9 */
-#define F3F(x, y, z) (OP(x) | OP3(y) | OPF(z)) /* format3 float insns */
-#define F3I(x) (((x)&0x1) << 13) /* immediate field of format 3 insns */
-#define F2(x, y) (OP(x) | OP2(y)) /* format 2 insns */
-#define F3(x, y, z) (OP(x) | OP3(y) | F3I(z)) /* format3 insns */
-#define F1(x) (OP(x))
-#define DISP30(x) ((x)&0x3fffffff)
-#define ASI(x) (((x)&0xff) << 5) /* asi field of format3 insns */
-#define RS2(x) ((x)&0x1f) /* rs2 field */
-#define SIMM13(x) ((x)&0x1fff) /* simm13 field */
-#define RD(x) (((x)&0x1f) << 25) /* destination register field */
-#define RS1(x) (((x)&0x1f) << 14) /* rs1 field */
-#define ASI_RS2(x) (SIMM13(x))
-#define MEMBAR(x) ((x)&0x7f)
-#define SLCPOP(x) (((x)&0x7f) << 6) /* sparclet cpop */
+#define OP2(x) (((x)&0x7) << 22) /* op2 field of format2 insns */
+#define OP3(x) (((x)&0x3f) << 19) /* op3 field of format3 insns */
+#define OP(x) ((unsigned)((x)&0x3) << 30) /* op field of all insns */
+#define OPF(x) (((x)&0x1ff) << 5) /* opf field of float insns */
+#define OPF_LOW5(x) OPF((x)&0x1f) /* v9 */
+#define F3F(x, y, z) (OP(x) | OP3(y) | OPF(z)) /* format3 float insns */
+#define F3I(x) (((x)&0x1) << 13) /* immediate field of format 3 insns */
+#define F2(x, y) (OP(x) | OP2(y)) /* format 2 insns */
+#define F3(x, y, z) (OP(x) | OP3(y) | F3I(z)) /* format3 insns */
+#define F1(x) (OP(x))
+#define DISP30(x) ((x)&0x3fffffff)
+#define ASI(x) (((x)&0xff) << 5) /* asi field of format3 insns */
+#define RS2(x) ((x)&0x1f) /* rs2 field */
+#define SIMM13(x) ((x)&0x1fff) /* simm13 field */
+#define RD(x) (((x)&0x1f) << 25) /* destination register field */
+#define RS1(x) (((x)&0x1f) << 14) /* rs1 field */
+#define ASI_RS2(x) (SIMM13(x))
+#define MEMBAR(x) ((x)&0x7f)
+#define SLCPOP(x) (((x)&0x7f) << 6) /* sparclet cpop */
-#define ANNUL (1<<29)
-#define BPRED (1<<19) /* v9 */
-#define IMMED F3I(1)
-#define RD_G0 RD(~0)
-#define RS1_G0 RS1(~0)
-#define RS2_G0 RS2(~0)
+#define ANNUL (1<<29)
+#define BPRED (1<<19) /* v9 */
+#define IMMED F3I(1)
+#define RD_G0 RD(~0)
+#define RS1_G0 RS1(~0)
+#define RS2_G0 RS2(~0)
extern const struct sparc_opcode sparc_opcodes[];
extern const int sparc_num_opcodes;
@@ -229,43 +229,43 @@
extern const char *sparc_decode_sparclet_cpreg PARAMS ((int));
/* Some defines to make life easy. */
-#define MASK_V6 SPARC_OPCODE_ARCH_MASK (SPARC_OPCODE_ARCH_V6)
-#define MASK_V7 SPARC_OPCODE_ARCH_MASK (SPARC_OPCODE_ARCH_V7)
-#define MASK_V8 SPARC_OPCODE_ARCH_MASK (SPARC_OPCODE_ARCH_V8)
-#define MASK_SPARCLET SPARC_OPCODE_ARCH_MASK (SPARC_OPCODE_ARCH_SPARCLET)
-#define MASK_SPARCLITE SPARC_OPCODE_ARCH_MASK (SPARC_OPCODE_ARCH_SPARCLITE)
-#define MASK_V9 SPARC_OPCODE_ARCH_MASK (SPARC_OPCODE_ARCH_V9)
-#define MASK_V9A SPARC_OPCODE_ARCH_MASK (SPARC_OPCODE_ARCH_V9A)
-#define MASK_V9B SPARC_OPCODE_ARCH_MASK (SPARC_OPCODE_ARCH_V9B)
+#define MASK_V6 SPARC_OPCODE_ARCH_MASK (SPARC_OPCODE_ARCH_V6)
+#define MASK_V7 SPARC_OPCODE_ARCH_MASK (SPARC_OPCODE_ARCH_V7)
+#define MASK_V8 SPARC_OPCODE_ARCH_MASK (SPARC_OPCODE_ARCH_V8)
+#define MASK_SPARCLET SPARC_OPCODE_ARCH_MASK (SPARC_OPCODE_ARCH_SPARCLET)
+#define MASK_SPARCLITE SPARC_OPCODE_ARCH_MASK (SPARC_OPCODE_ARCH_SPARCLITE)
+#define MASK_V9 SPARC_OPCODE_ARCH_MASK (SPARC_OPCODE_ARCH_V9)
+#define MASK_V9A SPARC_OPCODE_ARCH_MASK (SPARC_OPCODE_ARCH_V9A)
+#define MASK_V9B SPARC_OPCODE_ARCH_MASK (SPARC_OPCODE_ARCH_V9B)
/* Bit masks of architectures supporting the insn. */
-#define v6 (MASK_V6 | MASK_V7 | MASK_V8 | MASK_SPARCLET \
- | MASK_SPARCLITE | MASK_V9 | MASK_V9A | MASK_V9B)
+#define v6 (MASK_V6 | MASK_V7 | MASK_V8 | MASK_SPARCLET \
+ | MASK_SPARCLITE | MASK_V9 | MASK_V9A | MASK_V9B)
/* v6 insns not supported on the sparclet */
-#define v6notlet (MASK_V6 | MASK_V7 | MASK_V8 \
- | MASK_SPARCLITE | MASK_V9 | MASK_V9A | MASK_V9B)
-#define v7 (MASK_V7 | MASK_V8 | MASK_SPARCLET \
- | MASK_SPARCLITE | MASK_V9 | MASK_V9A | MASK_V9B)
+#define v6notlet (MASK_V6 | MASK_V7 | MASK_V8 \
+ | MASK_SPARCLITE | MASK_V9 | MASK_V9A | MASK_V9B)
+#define v7 (MASK_V7 | MASK_V8 | MASK_SPARCLET \
+ | MASK_SPARCLITE | MASK_V9 | MASK_V9A | MASK_V9B)
/* Although not all insns are implemented in hardware, sparclite is defined
to be a superset of v8. Unimplemented insns trap and are then theoretically
implemented in software.
It's not clear that the same is true for sparclet, although the docs
suggest it is. Rather than complicating things, the sparclet assembler
recognizes all v8 insns. */
-#define v8 (MASK_V8 | MASK_SPARCLET | MASK_SPARCLITE \
- | MASK_V9 | MASK_V9A | MASK_V9B)
-#define sparclet (MASK_SPARCLET)
-#define sparclite (MASK_SPARCLITE)
-#define v9 (MASK_V9 | MASK_V9A | MASK_V9B)
-#define v9a (MASK_V9A | MASK_V9B)
-#define v9b (MASK_V9B)
+#define v8 (MASK_V8 | MASK_SPARCLET | MASK_SPARCLITE \
+ | MASK_V9 | MASK_V9A | MASK_V9B)
+#define sparclet (MASK_SPARCLET)
+#define sparclite (MASK_SPARCLITE)
+#define v9 (MASK_V9 | MASK_V9A | MASK_V9B)
+#define v9a (MASK_V9A | MASK_V9B)
+#define v9b (MASK_V9B)
/* v6 insns not supported by v9 */
-#define v6notv9 (MASK_V6 | MASK_V7 | MASK_V8 \
- | MASK_SPARCLET | MASK_SPARCLITE)
+#define v6notv9 (MASK_V6 | MASK_V7 | MASK_V8 \
+ | MASK_SPARCLET | MASK_SPARCLITE)
/* v9a instructions which would appear to be aliases to v9's impdep's
otherwise */
-#define v9notv9a (MASK_V9)
+#define v9notv9a (MASK_V9)
/* Table of opcode architectures.
The order is defined in opcode/sparc.h. */
@@ -296,959 +296,959 @@
for (p = &sparc_opcode_archs[0]; p->name; ++p)
{
if (strcmp (name, p->name) == 0)
- return (enum sparc_opcode_arch_val) (p - &sparc_opcode_archs[0]);
+ return (enum sparc_opcode_arch_val) (p - &sparc_opcode_archs[0]);
}
return SPARC_OPCODE_ARCH_BAD;
}
/* Branch condition field. */
-#define COND(x) (((x)&0xf)<<25)
+#define COND(x) (((x)&0xf)<<25)
/* v9: Move (MOVcc and FMOVcc) condition field. */
-#define MCOND(x,i_or_f) ((((i_or_f)&1)<<18)|(((x)>>11)&(0xf<<14))) /* v9 */
+#define MCOND(x,i_or_f) ((((i_or_f)&1)<<18)|(((x)>>11)&(0xf<<14))) /* v9 */
/* v9: Move register (MOVRcc and FMOVRcc) condition field. */
-#define RCOND(x) (((x)&0x7)<<10) /* v9 */
+#define RCOND(x) (((x)&0x7)<<10) /* v9 */
-#define CONDA (COND(0x8))
-#define CONDCC (COND(0xd))
-#define CONDCS (COND(0x5))
-#define CONDE (COND(0x1))
-#define CONDG (COND(0xa))
-#define CONDGE (COND(0xb))
-#define CONDGU (COND(0xc))
-#define CONDL (COND(0x3))
-#define CONDLE (COND(0x2))
-#define CONDLEU (COND(0x4))
-#define CONDN (COND(0x0))
-#define CONDNE (COND(0x9))
-#define CONDNEG (COND(0x6))
-#define CONDPOS (COND(0xe))
-#define CONDVC (COND(0xf))
-#define CONDVS (COND(0x7))
+#define CONDA (COND(0x8))
+#define CONDCC (COND(0xd))
+#define CONDCS (COND(0x5))
+#define CONDE (COND(0x1))
+#define CONDG (COND(0xa))
+#define CONDGE (COND(0xb))
+#define CONDGU (COND(0xc))
+#define CONDL (COND(0x3))
+#define CONDLE (COND(0x2))
+#define CONDLEU (COND(0x4))
+#define CONDN (COND(0x0))
+#define CONDNE (COND(0x9))
+#define CONDNEG (COND(0x6))
+#define CONDPOS (COND(0xe))
+#define CONDVC (COND(0xf))
+#define CONDVS (COND(0x7))
-#define CONDNZ CONDNE
-#define CONDZ CONDE
-#define CONDGEU CONDCC
-#define CONDLU CONDCS
+#define CONDNZ CONDNE
+#define CONDZ CONDE
+#define CONDGEU CONDCC
+#define CONDLU CONDCS
-#define FCONDA (COND(0x8))
-#define FCONDE (COND(0x9))
-#define FCONDG (COND(0x6))
-#define FCONDGE (COND(0xb))
-#define FCONDL (COND(0x4))
-#define FCONDLE (COND(0xd))
-#define FCONDLG (COND(0x2))
-#define FCONDN (COND(0x0))
-#define FCONDNE (COND(0x1))
-#define FCONDO (COND(0xf))
-#define FCONDU (COND(0x7))
-#define FCONDUE (COND(0xa))
-#define FCONDUG (COND(0x5))
-#define FCONDUGE (COND(0xc))
-#define FCONDUL (COND(0x3))
-#define FCONDULE (COND(0xe))
+#define FCONDA (COND(0x8))
+#define FCONDE (COND(0x9))
+#define FCONDG (COND(0x6))
+#define FCONDGE (COND(0xb))
+#define FCONDL (COND(0x4))
+#define FCONDLE (COND(0xd))
+#define FCONDLG (COND(0x2))
+#define FCONDN (COND(0x0))
+#define FCONDNE (COND(0x1))
+#define FCONDO (COND(0xf))
+#define FCONDU (COND(0x7))
+#define FCONDUE (COND(0xa))
+#define FCONDUG (COND(0x5))
+#define FCONDUGE (COND(0xc))
+#define FCONDUL (COND(0x3))
+#define FCONDULE (COND(0xe))
-#define FCONDNZ FCONDNE
-#define FCONDZ FCONDE
+#define FCONDNZ FCONDNE
+#define FCONDZ FCONDE
-#define ICC (0) /* v9 */
+#define ICC (0) /* v9 */
#define XCC (1<<12) /* v9 */
-#define FCC(x) (((x)&0x3)<<11) /* v9 */
-#define FBFCC(x) (((x)&0x3)<<20) /* v9 */
+#define FCC(x) (((x)&0x3)<<11) /* v9 */
+#define FBFCC(x) (((x)&0x3)<<20) /* v9 */
/* The order of the opcodes in the table is significant:
- * The assembler requires that all instances of the same mnemonic must
- be consecutive. If they aren't, the assembler will bomb at runtime.
+ * The assembler requires that all instances of the same mnemonic must
+ be consecutive. If they aren't, the assembler will bomb at runtime.
- * The disassembler should not care about the order of the opcodes.
+ * The disassembler should not care about the order of the opcodes.
*/
/* Entries for commutative arithmetic operations. */
/* ??? More entries can make use of this. */
#define COMMUTEOP(opcode, op3, arch_mask) \
-{ opcode, F3(2, op3, 0), F3(~2, ~op3, ~0)|ASI(~0), "1,2,d", 0, arch_mask }, \
-{ opcode, F3(2, op3, 1), F3(~2, ~op3, ~1), "1,i,d", 0, arch_mask }, \
-{ opcode, F3(2, op3, 1), F3(~2, ~op3, ~1), "i,1,d", 0, arch_mask }
+{ opcode, F3(2, op3, 0), F3(~2, ~op3, ~0)|ASI(~0), "1,2,d", 0, arch_mask }, \
+{ opcode, F3(2, op3, 1), F3(~2, ~op3, ~1), "1,i,d", 0, arch_mask }, \
+{ opcode, F3(2, op3, 1), F3(~2, ~op3, ~1), "i,1,d", 0, arch_mask }
const struct sparc_opcode sparc_opcodes[] = {
-{ "ld", F3(3, 0x00, 0), F3(~3, ~0x00, ~0), "[1+2],d", 0, v6 },
-{ "ld", F3(3, 0x00, 0), F3(~3, ~0x00, ~0)|RS2_G0, "[1],d", 0, v6 }, /* ld [rs1+%g0],d */
-{ "ld", F3(3, 0x00, 1), F3(~3, ~0x00, ~1), "[1+i],d", 0, v6 },
-{ "ld", F3(3, 0x00, 1), F3(~3, ~0x00, ~1), "[i+1],d", 0, v6 },
-{ "ld", F3(3, 0x00, 1), F3(~3, ~0x00, ~1)|RS1_G0, "[i],d", 0, v6 },
-{ "ld", F3(3, 0x00, 1), F3(~3, ~0x00, ~1)|SIMM13(~0), "[1],d", 0, v6 }, /* ld [rs1+0],d */
-{ "ld", F3(3, 0x20, 0), F3(~3, ~0x20, ~0), "[1+2],g", 0, v6 },
-{ "ld", F3(3, 0x20, 0), F3(~3, ~0x20, ~0)|RS2_G0, "[1],g", 0, v6 }, /* ld [rs1+%g0],d */
-{ "ld", F3(3, 0x20, 1), F3(~3, ~0x20, ~1), "[1+i],g", 0, v6 },
-{ "ld", F3(3, 0x20, 1), F3(~3, ~0x20, ~1), "[i+1],g", 0, v6 },
-{ "ld", F3(3, 0x20, 1), F3(~3, ~0x20, ~1)|RS1_G0, "[i],g", 0, v6 },
-{ "ld", F3(3, 0x20, 1), F3(~3, ~0x20, ~1)|SIMM13(~0), "[1],g", 0, v6 }, /* ld [rs1+0],d */
+{ "ld", F3(3, 0x00, 0), F3(~3, ~0x00, ~0), "[1+2],d", 0, v6 },
+{ "ld", F3(3, 0x00, 0), F3(~3, ~0x00, ~0)|RS2_G0, "[1],d", 0, v6 }, /* ld [rs1+%g0],d */
+{ "ld", F3(3, 0x00, 1), F3(~3, ~0x00, ~1), "[1+i],d", 0, v6 },
+{ "ld", F3(3, 0x00, 1), F3(~3, ~0x00, ~1), "[i+1],d", 0, v6 },
+{ "ld", F3(3, 0x00, 1), F3(~3, ~0x00, ~1)|RS1_G0, "[i],d", 0, v6 },
+{ "ld", F3(3, 0x00, 1), F3(~3, ~0x00, ~1)|SIMM13(~0), "[1],d", 0, v6 }, /* ld [rs1+0],d */
+{ "ld", F3(3, 0x20, 0), F3(~3, ~0x20, ~0), "[1+2],g", 0, v6 },
+{ "ld", F3(3, 0x20, 0), F3(~3, ~0x20, ~0)|RS2_G0, "[1],g", 0, v6 }, /* ld [rs1+%g0],d */
+{ "ld", F3(3, 0x20, 1), F3(~3, ~0x20, ~1), "[1+i],g", 0, v6 },
+{ "ld", F3(3, 0x20, 1), F3(~3, ~0x20, ~1), "[i+1],g", 0, v6 },
+{ "ld", F3(3, 0x20, 1), F3(~3, ~0x20, ~1)|RS1_G0, "[i],g", 0, v6 },
+{ "ld", F3(3, 0x20, 1), F3(~3, ~0x20, ~1)|SIMM13(~0), "[1],g", 0, v6 }, /* ld [rs1+0],d */
-{ "ld", F3(3, 0x21, 0), F3(~3, ~0x21, ~0)|RD(~0), "[1+2],F", 0, v6 },
-{ "ld", F3(3, 0x21, 0), F3(~3, ~0x21, ~0)|RS2_G0|RD(~0),"[1],F", 0, v6 }, /* ld [rs1+%g0],d */
-{ "ld", F3(3, 0x21, 1), F3(~3, ~0x21, ~1)|RD(~0), "[1+i],F", 0, v6 },
-{ "ld", F3(3, 0x21, 1), F3(~3, ~0x21, ~1)|RD(~0), "[i+1],F", 0, v6 },
-{ "ld", F3(3, 0x21, 1), F3(~3, ~0x21, ~1)|RS1_G0|RD(~0),"[i],F", 0, v6 },
-{ "ld", F3(3, 0x21, 1), F3(~3, ~0x21, ~1)|SIMM13(~0)|RD(~0),"[1],F", 0, v6 }, /* ld [rs1+0],d */
+{ "ld", F3(3, 0x21, 0), F3(~3, ~0x21, ~0)|RD(~0), "[1+2],F", 0, v6 },
+{ "ld", F3(3, 0x21, 0), F3(~3, ~0x21, ~0)|RS2_G0|RD(~0),"[1],F", 0, v6 }, /* ld [rs1+%g0],d */
+{ "ld", F3(3, 0x21, 1), F3(~3, ~0x21, ~1)|RD(~0), "[1+i],F", 0, v6 },
+{ "ld", F3(3, 0x21, 1), F3(~3, ~0x21, ~1)|RD(~0), "[i+1],F", 0, v6 },
+{ "ld", F3(3, 0x21, 1), F3(~3, ~0x21, ~1)|RS1_G0|RD(~0),"[i],F", 0, v6 },
+{ "ld", F3(3, 0x21, 1), F3(~3, ~0x21, ~1)|SIMM13(~0)|RD(~0),"[1],F", 0, v6 }, /* ld [rs1+0],d */
-{ "ld", F3(3, 0x30, 0), F3(~3, ~0x30, ~0), "[1+2],D", 0, v6notv9 },
-{ "ld", F3(3, 0x30, 0), F3(~3, ~0x30, ~0)|RS2_G0, "[1],D", 0, v6notv9 }, /* ld [rs1+%g0],d */
-{ "ld", F3(3, 0x30, 1), F3(~3, ~0x30, ~1), "[1+i],D", 0, v6notv9 },
-{ "ld", F3(3, 0x30, 1), F3(~3, ~0x30, ~1), "[i+1],D", 0, v6notv9 },
-{ "ld", F3(3, 0x30, 1), F3(~3, ~0x30, ~1)|RS1_G0, "[i],D", 0, v6notv9 },
-{ "ld", F3(3, 0x30, 1), F3(~3, ~0x30, ~1)|SIMM13(~0), "[1],D", 0, v6notv9 }, /* ld [rs1+0],d */
-{ "ld", F3(3, 0x31, 0), F3(~3, ~0x31, ~0), "[1+2],C", 0, v6notv9 },
-{ "ld", F3(3, 0x31, 0), F3(~3, ~0x31, ~0)|RS2_G0, "[1],C", 0, v6notv9 }, /* ld [rs1+%g0],d */
-{ "ld", F3(3, 0x31, 1), F3(~3, ~0x31, ~1), "[1+i],C", 0, v6notv9 },
-{ "ld", F3(3, 0x31, 1), F3(~3, ~0x31, ~1), "[i+1],C", 0, v6notv9 },
-{ "ld", F3(3, 0x31, 1), F3(~3, ~0x31, ~1)|RS1_G0, "[i],C", 0, v6notv9 },
-{ "ld", F3(3, 0x31, 1), F3(~3, ~0x31, ~1)|SIMM13(~0), "[1],C", 0, v6notv9 }, /* ld [rs1+0],d */
+{ "ld", F3(3, 0x30, 0), F3(~3, ~0x30, ~0), "[1+2],D", 0, v6notv9 },
+{ "ld", F3(3, 0x30, 0), F3(~3, ~0x30, ~0)|RS2_G0, "[1],D", 0, v6notv9 }, /* ld [rs1+%g0],d */
+{ "ld", F3(3, 0x30, 1), F3(~3, ~0x30, ~1), "[1+i],D", 0, v6notv9 },
+{ "ld", F3(3, 0x30, 1), F3(~3, ~0x30, ~1), "[i+1],D", 0, v6notv9 },
+{ "ld", F3(3, 0x30, 1), F3(~3, ~0x30, ~1)|RS1_G0, "[i],D", 0, v6notv9 },
+{ "ld", F3(3, 0x30, 1), F3(~3, ~0x30, ~1)|SIMM13(~0), "[1],D", 0, v6notv9 }, /* ld [rs1+0],d */
+{ "ld", F3(3, 0x31, 0), F3(~3, ~0x31, ~0), "[1+2],C", 0, v6notv9 },
+{ "ld", F3(3, 0x31, 0), F3(~3, ~0x31, ~0)|RS2_G0, "[1],C", 0, v6notv9 }, /* ld [rs1+%g0],d */
+{ "ld", F3(3, 0x31, 1), F3(~3, ~0x31, ~1), "[1+i],C", 0, v6notv9 },
+{ "ld", F3(3, 0x31, 1), F3(~3, ~0x31, ~1), "[i+1],C", 0, v6notv9 },
+{ "ld", F3(3, 0x31, 1), F3(~3, ~0x31, ~1)|RS1_G0, "[i],C", 0, v6notv9 },
+{ "ld", F3(3, 0x31, 1), F3(~3, ~0x31, ~1)|SIMM13(~0), "[1],C", 0, v6notv9 }, /* ld [rs1+0],d */
/* The v9 LDUW is the same as the old 'ld' opcode, it is not the same as the
'ld' pseudo-op in v9. */
-{ "lduw", F3(3, 0x00, 0), F3(~3, ~0x00, ~0), "[1+2],d", F_ALIAS, v9 },
-{ "lduw", F3(3, 0x00, 0), F3(~3, ~0x00, ~0)|RS2_G0, "[1],d", F_ALIAS, v9 }, /* ld [rs1+%g0],d */
-{ "lduw", F3(3, 0x00, 1), F3(~3, ~0x00, ~1), "[1+i],d", F_ALIAS, v9 },
-{ "lduw", F3(3, 0x00, 1), F3(~3, ~0x00, ~1), "[i+1],d", F_ALIAS, v9 },
-{ "lduw", F3(3, 0x00, 1), F3(~3, ~0x00, ~1)|RS1_G0, "[i],d", F_ALIAS, v9 },
-{ "lduw", F3(3, 0x00, 1), F3(~3, ~0x00, ~1)|SIMM13(~0), "[1],d", F_ALIAS, v9 }, /* ld [rs1+0],d */
+{ "lduw", F3(3, 0x00, 0), F3(~3, ~0x00, ~0), "[1+2],d", F_ALIAS, v9 },
+{ "lduw", F3(3, 0x00, 0), F3(~3, ~0x00, ~0)|RS2_G0, "[1],d", F_ALIAS, v9 }, /* ld [rs1+%g0],d */
+{ "lduw", F3(3, 0x00, 1), F3(~3, ~0x00, ~1), "[1+i],d", F_ALIAS, v9 },
+{ "lduw", F3(3, 0x00, 1), F3(~3, ~0x00, ~1), "[i+1],d", F_ALIAS, v9 },
+{ "lduw", F3(3, 0x00, 1), F3(~3, ~0x00, ~1)|RS1_G0, "[i],d", F_ALIAS, v9 },
+{ "lduw", F3(3, 0x00, 1), F3(~3, ~0x00, ~1)|SIMM13(~0), "[1],d", F_ALIAS, v9 }, /* ld [rs1+0],d */
-{ "ldd", F3(3, 0x03, 0), F3(~3, ~0x03, ~0)|ASI(~0), "[1+2],d", 0, v6 },
-{ "ldd", F3(3, 0x03, 0), F3(~3, ~0x03, ~0)|ASI_RS2(~0), "[1],d", 0, v6 }, /* ldd [rs1+%g0],d */
-{ "ldd", F3(3, 0x03, 1), F3(~3, ~0x03, ~1), "[1+i],d", 0, v6 },
-{ "ldd", F3(3, 0x03, 1), F3(~3, ~0x03, ~1), "[i+1],d", 0, v6 },
-{ "ldd", F3(3, 0x03, 1), F3(~3, ~0x03, ~1)|RS1_G0, "[i],d", 0, v6 },
-{ "ldd", F3(3, 0x03, 1), F3(~3, ~0x03, ~1)|SIMM13(~0), "[1],d", 0, v6 }, /* ldd [rs1+0],d */
-{ "ldd", F3(3, 0x23, 0), F3(~3, ~0x23, ~0)|ASI(~0), "[1+2],H", 0, v6 },
-{ "