diff options
author | Avi Kivity <avi@redhat.com> | 2008-12-15 18:14:37 +0200 |
---|---|---|
committer | Avi Kivity <avi@redhat.com> | 2008-12-15 18:17:52 +0200 |
commit | 7b91a3ffdeea0121a36f3551d9b6b64bf3b05202 (patch) | |
tree | 0b8eb511dfbdb3c046081ba53fe645a243f491a7 | |
parent | 5b18e1d97013c34e3142a2487206a53eaa60cb8c (diff) | |
parent | b34913267a02bde6607a707c32738baac5875355 (diff) |
Merge branch 'qemu-cvs'
Conflicts:
qemu/Makefile
qemu/Makefile.target
qemu/block-raw-posix.c
qemu/configure
qemu/cutils.c
qemu/dyngen.c
qemu/hw/cirrus_vga.c
qemu/hw/e1000.c
qemu/hw/pci.c
qemu/hw/vga.c
qemu/osdep.c
qemu/pc-bios/Makefile
qemu/qemu-common.h
qemu/target-ppc/helper.c
Signed-off-by: Avi Kivity <avi@redhat.com>
215 files changed, 4103 insertions, 6546 deletions
@@ -142,7 +142,6 @@ fi #configure qemu (cd qemu; ./configure --target-list=$target_exec \ --disable-kqemu \ - --disable-gcc-check \ --extra-cflags="-I $PWD/../libkvm $qemu_cflags" \ --extra-ldflags="-L $PWD/../libkvm $qemu_ldflags" \ --kerneldir="$libkvm_kerneldir" \ diff --git a/qemu/.gitignore b/qemu/.gitignore index e70ebab4..0f4af35a 100644 --- a/qemu/.gitignore +++ b/qemu/.gitignore @@ -1,10 +1,9 @@ config-host.* -dyngen -dyngen.dSYM i386 *-softmmu *-darwin-user *-linux-user +*-bsd-user qemu-doc.html qemu-tech.html qemu-doc.info @@ -16,6 +15,7 @@ qemu-img.pod qemu-img qemu-nbd qemu-nbd.8 +qemu-nbd.pod .gdbinit *.a *.aux @@ -30,4 +30,5 @@ qemu-nbd.8 *.tp *.vr *.d - +.pc +patches diff --git a/qemu/LICENSE b/qemu/LICENSE index 2fa7ddae..cbd92c03 100644 --- a/qemu/LICENSE +++ b/qemu/LICENSE @@ -15,4 +15,4 @@ device emulation sources are released under the BSD license. 4) QEMU is a trademark of Fabrice Bellard. -Fabrice Bellard.
\ No newline at end of file +Fabrice Bellard. diff --git a/qemu/Makefile b/qemu/Makefile index 59b4cf9f..b2ca0396 100644 --- a/qemu/Makefile +++ b/qemu/Makefile @@ -36,7 +36,7 @@ all: $(TOOLS) $(DOCS) recurse-all SUBDIR_RULES=$(patsubst %,subdir-%, $(TARGET_DIRS)) -subdir-%: dyngen$(EXESUF) +subdir-%: $(MAKE) -C $(subst subdir-,,$@) all $(filter %-softmmu,$(SUBDIR_RULES)): libqemu_common.a @@ -56,6 +56,9 @@ BLOCK_OBJS+=nbd.o block.o aio.o ifdef CONFIG_WIN32 BLOCK_OBJS += block-raw-win32.o else +ifdef CONFIG_AIO +BLOCK_OBJS += posix-aio-compat.o +endif BLOCK_OBJS += block-raw-posix.o endif @@ -82,8 +85,8 @@ OBJS+=usb.o usb-hub.o usb-$(HOST_USB).o usb-hid.o usb-msd.o usb-wacom.o OBJS+=usb-serial.o usb-net.o OBJS+=sd.o ssi-sd.o OBJS+=bt.o bt-host.o bt-vhci.o bt-l2cap.o bt-sdp.o bt-hci.o bt-hid.o usb-bt.o -OBJS+=buffered_file.o migration.o migration-tcp.o qemu-sockets.o -OBJS+=qemu-char.o aio.o net-checksum.o savevm.o +OBJS+=buffered_file.o migration.o migration-tcp.o net.o qemu-sockets.o +OBJS+=qemu-char.o aio.o net-checksum.o savevm.o cache-utils.o ifdef CONFIG_BRLAPI OBJS+= baum.o @@ -182,7 +185,7 @@ libqemu_common.a: $(OBJS) ####################################################################### # USER_OBJS is code used by qemu userspace emulation -USER_OBJS=cutils.o +USER_OBJS=cutils.o cache-utils.o libqemu_user.a: $(USER_OBJS) rm -f $@ @@ -199,15 +202,10 @@ qemu-img$(EXESUF): qemu-img.o qemu-tool.o osdep.o $(BLOCK_OBJS) qemu-nbd$(EXESUF): qemu-nbd.o qemu-tool.o osdep.o $(BLOCK_OBJS) $(CC) $(LDFLAGS) -o $@ $^ -lz $(LIBS) -# dyngen host tool -dyngen$(EXESUF): dyngen.c - $(HOST_CC) $(CFLAGS) $(CPPFLAGS) -o $@ $^ - clean: # avoid old build problems by removing potentially incorrect old files rm -f config.mak config.h op-i386.h opc-i386.h gen-op-i386.h op-arm.h opc-arm.h gen-op-arm.h - rm -f *.o *.d *.a $(TOOLS) dyngen$(EXESUF) TAGS cscope.* *.pod *~ */*~ - rm -rf dyngen.dSYM + rm -f *.o *.d *.a $(TOOLS) TAGS cscope.* *.pod *~ */*~ rm -f slirp/*.o slirp/*.d audio/*.o audio/*.d $(MAKE) -C tests clean for d in $(TARGET_DIRS); do \ diff --git a/qemu/Makefile.target b/qemu/Makefile.target index d6a6479f..315c3c9f 100644 --- a/qemu/Makefile.target +++ b/qemu/Makefile.target @@ -34,7 +34,6 @@ VPATH=$(SRC_PATH):$(TARGET_PATH):$(SRC_PATH)/hw CPPFLAGS=-I. -I.. -I$(TARGET_PATH) -I$(SRC_PATH) -MMD -MT $@ -MP -DNEED_CPU_H #CFLAGS+=-Werror LIBS= -DYNGEN=../dyngen$(EXESUF) # user emulator name ifndef TARGET_ARCH2 TARGET_ARCH2=$(TARGET_ARCH) @@ -81,7 +80,7 @@ PROGS=$(QEMU_PROG) # We require -O2 to avoid the stack setup prologue in EXIT_TB OP_CFLAGS := -O2 -g -fno-strict-aliasing -OP_CFLAGS += -Wall -Wundef -Wendif-labels -Wwrite-strings +OP_CFLAGS += -Wall -Wundef -Wendif-labels -Wwrite-strings -Wmissing-prototypes -Wstrict-prototypes -Wredundant-decls # cc-option # Usage: OP_CFLAGS+=$(call cc-option, -falign-functions=0, -malign-functions=0) @@ -104,12 +103,6 @@ HELPER_CFLAGS= ifeq ($(ARCH),i386) HELPER_CFLAGS+=-fomit-frame-pointer OP_CFLAGS+=-mpreferred-stack-boundary=2 -fomit-frame-pointer -# op.c and helper.c need this on 32-bit x86 system to avoid -# a compiler spill error. This can probably go away -# once the SSE ops have been converted to TCG -ifeq ($(HAVE_GT_GCC_3_3), true) -I386_CFLAGS=-march=i586 -mtune=i686 -endif endif ifeq ($(ARCH),ppc) @@ -203,14 +196,8 @@ ifeq ($(NO_CPU_EMULATION), 1) LIBOBJS+=fake-exec.o else LIBOBJS+= translate-all.o translate.o -endif -ifdef CONFIG_DYNGEN_OP -exec.o: dyngen-opc.h -LIBOBJS+=op.o -endif # TCG code generator -ifneq ($(TARGET_ARCH), ia64) -LIBOBJS+= tcg/tcg.o tcg/tcg-dyngen.o tcg/tcg-runtime.o +LIBOBJS+= tcg/tcg.o tcg/tcg-runtime.o CPPFLAGS+=-I$(SRC_PATH)/tcg -I$(SRC_PATH)/tcg/$(ARCH) endif ifeq ($(ARCH),sparc64) @@ -226,6 +213,7 @@ else LIBOBJS+=fpu/softfloat-native.o endif CPPFLAGS+=-I$(SRC_PATH)/fpu +LIBOBJS+= op_helper.o helper.o ifeq ($(TARGET_ARCH), i386) LIBOBJS+=helper.o @@ -320,35 +308,15 @@ endif # libqemu -ifdef CONFIG_DYNGEN_OP -OPC_H = gen-op.h dyngen-opc.h op.h -endif - libqemu.a: $(LIBOBJS) rm -f $@ $(AR) rcs $@ $(LIBOBJS) -translate.o: translate.c cpu.h $(OPC_H) - -translate-all.o: translate-all.c cpu.h $(OPC_H) +translate.o: translate.c cpu.h -tcg/tcg.o: cpu.h $(OPC_H) +translate-all.o: translate-all.c cpu.h -tcg/tcg-dyngen.o: $(OPC_H) - -tcg/tcg-runtime.o: $(OPC_H) - -op.h: op.o $(DYNGEN) - $(DYNGEN) -o $@ $< - -dyngen-opc.h: op.o $(DYNGEN) - $(DYNGEN) -c -o $@ $< - -gen-op.h: op.o $(DYNGEN) - $(DYNGEN) -g -o $@ $< - -op.o: op.c - $(CC) $(OP_CFLAGS) $(CPPFLAGS) $(I386_CFLAGS) -c -o $@ $< +tcg/tcg.o: cpu.h machine.o: machine.c $(CC) $(OP_CFLAGS) $(CPPFLAGS) $(CFLAGS) -c -o $@ $< @@ -358,7 +326,7 @@ machine.o: machine.c op_helper.o: op_helper.c $(CC) $(HELPER_CFLAGS) $(CPPFLAGS) $(CFLAGS) $(I386_CFLAGS) -c -o $@ $< -cpu-exec.o: cpu-exec.c $(OPC_H) +cpu-exec.o: cpu-exec.c $(CC) $(HELPER_CFLAGS) $(CPPFLAGS) $(CFLAGS) -c -o $@ $< qemu-kvm-helper.o: qemu-kvm-helper.c @@ -645,13 +613,15 @@ ifndef CONFIG_USER_ONLY OBJS=vl.o osdep.o monitor.o pci.o loader.o isa_mmio.o machine.o OBJS+=fw_cfg.o -OBJS+=net.o ifdef CONFIG_KVM OBJS+=kvm.o kvm-all.o endif ifdef CONFIG_WIN32 OBJS+=block-raw-win32.o else +ifdef CONFIG_AIO +OBJS+=posix-aio-compat.o +endif OBJS+=block-raw-posix.o endif @@ -685,7 +655,7 @@ SOUND_HW += ac97.o endif ifdef CONFIG_ADLIB SOUND_HW += fmopl.o adlib.o -fmopl.o: CFLAGS := ${CFLAGS} -DBUILD_Y8950=0 +adlib.o fmopl.o: CFLAGS := ${CFLAGS} -DBUILD_Y8950=0 endif ifdef CONFIG_GUS SOUND_HW += gus.o gusemu_hal.o gusemu_mixer.o @@ -828,7 +798,7 @@ OBJS+= pflash_cfi01.o gumstix.o OBJS+= zaurus.o ide.o serial.o nand.o ecc.o spitz.o tosa.o tc6393xb.o OBJS+= omap1.o omap_lcdc.o omap_dma.o omap_clk.o omap_mmc.o omap_i2c.o OBJS+= omap2.o omap_dss.o soc_dma.o -OBJS+= palm.o tsc210x.o +OBJS+= omap_sx1.o palm.o tsc210x.o OBJS+= nseries.o blizzard.o onenand.o vga.o cbus.o tusb6010.o usb-musb.o OBJS+= tsc2005.o bt-hci-csr.o OBJS+= mst_fpga.o mainstone.o @@ -837,7 +807,8 @@ CPPFLAGS += -DHAS_AUDIO endif ifeq ($(TARGET_BASE_ARCH), sh4) OBJS+= shix.o r2d.o sh7750.o sh7750_regnames.o tc58128.o -OBJS+= sh_timer.o ptimer.o sh_serial.o sh_intc.o sm501.o serial.o +OBJS+= sh_timer.o ptimer.o sh_serial.o sh_intc.o sh_pci.o sm501.o serial.o +OBJS+= ide.o endif ifeq ($(TARGET_BASE_ARCH), m68k) OBJS+= an5206.o mcf5206.o ptimer.o mcf_uart.o mcf_intc.o mcf5208.o mcf_fec.o @@ -913,7 +884,7 @@ endif $(CC) $(CPPFLAGS) -c -o $@ $< clean: - rm -f *.o *.a *~ $(PROGS) gen-op.h dyngen-opc.h op.h nwfpe/*.o fpu/*.o + rm -f *.o *.a *~ $(PROGS) nwfpe/*.o fpu/*.o rm -f *.d */*.d tcg/*.o install: all diff --git a/qemu/README b/qemu/README index 1a39500b..dfd56f24 100644 --- a/qemu/README +++ b/qemu/README @@ -1,3 +1,3 @@ Read the documentation in qemu-doc.html. -Fabrice Bellard.
\ No newline at end of file +Fabrice Bellard. diff --git a/qemu/a.out.h b/qemu/a.out.h index 2d35ebfd..dfc104e6 100644 --- a/qemu/a.out.h +++ b/qemu/a.out.h @@ -428,4 +428,3 @@ typedef struct #endif #endif /* _A_OUT_H_ */ - diff --git a/qemu/block-cloop.c b/qemu/block-cloop.c index 43d38012..ad0e65d9 100644 --- a/qemu/block-cloop.c +++ b/qemu/block-cloop.c @@ -165,5 +165,3 @@ BlockDriver bdrv_cloop = { NULL, cloop_close, }; - - diff --git a/qemu/block-dmg.c b/qemu/block-dmg.c index 8c9d0da2..4320c5dc 100644 --- a/qemu/block-dmg.c +++ b/qemu/block-dmg.c @@ -294,4 +294,3 @@ BlockDriver bdrv_dmg = { NULL, dmg_close, }; - diff --git a/qemu/block-raw-posix.c b/qemu/block-raw-posix.c index 5e3e0bfb..820de243 100644 --- a/qemu/block-raw-posix.c +++ b/qemu/block-raw-posix.c @@ -28,7 +28,7 @@ #include "compatfd.h" #include <assert.h> #ifdef CONFIG_AIO -#include <aio.h> +#include "posix-aio-compat.h" #endif #ifdef CONFIG_COCOA @@ -94,16 +94,10 @@ reopen it to see if the disk has been changed */ #define FD_OPEN_TIMEOUT 1000 -/* posix-aio doesn't allow multiple outstanding requests to a single file - * descriptor. we implement a pool of dup()'d file descriptors to work - * around this */ -#define RAW_FD_POOL_SIZE 64 - typedef struct BDRVRawState { int fd; int type; unsigned int lseek_err_cnt; - int fd_pool[RAW_FD_POOL_SIZE]; #if defined(__linux__) /* linux floppy specific */ int fd_open_flags; @@ -123,7 +117,6 @@ static int raw_open(BlockDriverState *bs, const char *filename, int flags) { BDRVRawState *s = bs->opaque; int fd, open_flags, ret; - int i; posix_aio_init(); @@ -156,8 +149,6 @@ static int raw_open(BlockDriverState *bs, const char *filename, int flags) return ret; } s->fd = fd; - for (i = 0; i < RAW_FD_POOL_SIZE; i++) - s->fd_pool[i] = -1; s->aligned_buf = NULL; if ((flags & BDRV_O_NOCACHE)) { s->aligned_buf = qemu_memalign(512, ALIGNED_BUFFER_SIZE); @@ -447,8 +438,7 @@ static int raw_pwrite(BlockDriverState *bs, int64_t offset, typedef struct RawAIOCB { BlockDriverAIOCB common; - int fd; - struct aiocb aiocb; + struct qemu_paiocb aiocb; struct RawAIOCB *next; int ret; } RawAIOCB; @@ -459,38 +449,6 @@ typedef struct PosixAioState RawAIOCB *first_aio; } PosixAioState; -static int raw_fd_pool_get(BDRVRawState *s) -{ - int i; - - for (i = 0; i < RAW_FD_POOL_SIZE; i++) { - /* already in use */ - if (s->fd_pool[i] != -1) - continue; - - /* try to dup file descriptor */ - s->fd_pool[i] = dup(s->fd); - if (s->fd_pool[i] != -1) - return s->fd_pool[i]; - } - - /* we couldn't dup the file descriptor so just use the main one */ - return s->fd; -} - -static void raw_fd_pool_put(RawAIOCB *acb) -{ - BDRVRawState *s = acb->common.bs->opaque; - int i; - - for (i = 0; i < RAW_FD_POOL_SIZE; i++) { - if (s->fd_pool[i] == acb->fd) { - close(s->fd_pool[i]); - s->fd_pool[i] = -1; - } - } -} - static void posix_aio_read(void *opaque) { PosixAioState *s = opaque; @@ -527,16 +485,15 @@ static void posix_aio_read(void *opaque) acb = *pacb; if (!acb) goto the_end; - ret = aio_error(&acb->aiocb); + ret = qemu_paio_error(&acb->aiocb); if (ret == ECANCELED) { /* remove the request */ *pacb = acb->next; - raw_fd_pool_put(acb); qemu_aio_release(acb); } else if (ret != EINPROGRESS) { /* end of aio */ if (ret == 0) { - ret = aio_return(&acb->aiocb); + ret = qemu_paio_return(&acb->aiocb); if (ret == acb->aiocb.aio_nbytes) ret = 0; else @@ -548,7 +505,6 @@ static void posix_aio_read(void *opaque) *pacb = acb->next; /* call the callback */ acb->common.cb(acb->common.opaque, ret); - raw_fd_pool_put(acb); qemu_aio_release(acb); break; } else { @@ -571,6 +527,8 @@ static int posix_aio_init(void) { sigset_t mask; PosixAioState *s; + int fds[2]; + struct qemu_paioinit ai; if (posix_aio_state) return 0; @@ -595,24 +553,11 @@ static int posix_aio_init(void) qemu_aio_set_fd_handler(s->fd, posix_aio_read, NULL, posix_aio_flush, s); -#if defined(__linux__) - { - struct aioinit ai; + memset(&ai, 0, sizeof(ai)); + ai.aio_threads = 64; + ai.aio_num = 64; + qemu_paio_init(&ai); - memset(&ai, 0, sizeof(ai)); -#if defined(__GLIBC_PREREQ) && __GLIBC_PREREQ(2, 4) - ai.aio_threads = 64; - ai.aio_num = 64; -#else - /* XXX: aio thread exit seems to hang on RedHat 9 and this init - seems to fix the problem. */ - ai.aio_threads = 1; - ai.aio_num = 1; - ai.aio_idle_time = 365 * 100000; -#endif - aio_init(&ai); - } -#endif posix_aio_state = s; return 0; @@ -631,8 +576,7 @@ static RawAIOCB *raw_aio_setup(BlockDriverState *bs, acb = qemu_aio_get(bs, cb, opaque); if (!acb) return NULL; - acb->fd = raw_fd_pool_get(s); - acb->aiocb.aio_fildes = acb->fd; + acb->aiocb.aio_fildes = s->fd; acb->aiocb.aio_sigevent.sigev_signo = SIGUSR2; acb->aiocb.aio_sigevent.sigev_notify = SIGEV_SIGNAL; acb->aiocb.aio_buf = buf; @@ -677,7 +621,7 @@ static BlockDriverAIOCB *raw_aio_read(BlockDriverState *bs, acb = raw_aio_setup(bs, sector_num, buf, nb_sectors, cb, opaque); if (!acb) return NULL; - if (aio_read(&acb->aiocb) < 0) { + if (qemu_paio_read(&acb->aiocb) < 0) { qemu_aio_release(acb); return NULL; } @@ -708,7 +652,7 @@ static BlockDriverAIOCB *raw_aio_write(BlockDriverState *bs, acb = raw_aio_setup(bs, sector_num, (uint8_t*)buf, nb_sectors, cb, opaque); if (!acb) return NULL; - if (aio_write(&acb->aiocb) < 0) { + if (qemu_paio_write(&acb->aiocb) < 0) { qemu_aio_release(acb); return NULL; } @@ -721,11 +665,11 @@ static void raw_aio_cancel(BlockDriverAIOCB *blockacb) RawAIOCB *acb = (RawAIOCB *)blockacb; RawAIOCB **pacb; - ret = aio_cancel(acb->aiocb.aio_fildes, &acb->aiocb); - if (ret == AIO_NOTCANCELED) { + ret = qemu_paio_cancel(acb->aiocb.aio_fildes, &acb->aiocb); + if (ret == QEMU_PAIO_NOTCANCELED) { /* fail safe: if the aio could not be canceled, we wait for it */ - while (aio_error(&acb->aiocb) == EINPROGRESS); + while (qemu_paio_error(&acb->aiocb) == EINPROGRESS); } /* remove the callback from the queue */ @@ -735,14 +679,12 @@ static void raw_aio_cancel(BlockDriverAIOCB *blockacb) break; } else if (*pacb == acb) { *pacb = acb->next; - raw_fd_pool_put(acb); qemu_aio_release(acb); break; } pacb = &acb->next; } } - #else /* CONFIG_AIO */ static int posix_aio_init(void) { @@ -750,17 +692,6 @@ static int posix_aio_init(void) } #endif /* CONFIG_AIO */ -static void raw_close_fd_pool(BDRVRawState *s) -{ - int i; - - for (i = 0; i < RAW_FD_POOL_SIZE; i++) { - if (s->fd_pool[i] != -1) { - close(s->fd_pool[i]); - s->fd_pool[i] = -1; - } - } -} static void raw_close(BlockDriverState *bs) { @@ -771,7 +702,6 @@ static void raw_close(BlockDriverState *bs) if (s->aligned_buf != NULL) qemu_free(s->aligned_buf); } - raw_close_fd_pool(s); } static int raw_truncate(BlockDriverState *bs, int64_t offset) @@ -892,6 +822,7 @@ BlockDriver bdrv_raw = { .bdrv_aio_cancel = raw_aio_cancel, .aiocb_size = sizeof(RawAIOCB), #endif + .bdrv_pread = raw_pread, .bdrv_pwrite = raw_pwrite, .bdrv_truncate = raw_truncate, @@ -962,7 +893,7 @@ kern_return_t GetBSDPath( io_iterator_t mediaIterator, char *bsdPath, CFIndex ma static int hdev_open(BlockDriverState *bs, const char *filename, int flags) { BDRVRawState *s = bs->opaque; - int fd, open_flags, ret, i; + int fd, open_flags, ret; posix_aio_init(); @@ -1029,8 +960,6 @@ static int hdev_open(BlockDriverState *bs, const char *filename, int flags) return ret; } s->fd = fd; - for (i = 0; i < RAW_FD_POOL_SIZE; i++) - s->fd_pool[i] = -1; #if defined(__linux__) /* close fd so that we can reopen it as needed */ if (s->type == FTYPE_FD) { @@ -1058,7 +987,6 @@ static int fd_open(BlockDriverState *bs) (qemu_get_clock(rt_clock) - s->fd_open_time) >= FD_OPEN_TIMEOUT) { close(s->fd); s->fd = -1; - raw_close_fd_pool(s); #ifdef DEBUG_FLOPPY printf("Floppy closed\n"); #endif @@ -1159,7 +1087,6 @@ static int raw_eject(BlockDriverState *bs, int eject_flag) if (s->fd >= 0) { close(s->fd); s->fd = -1; - raw_close_fd_pool(s); } fd = open(bs->filename, s->fd_open_flags | O_NONBLOCK); if (fd >= 0) { @@ -1249,6 +1176,7 @@ BlockDriver bdrv_host_device = { .bdrv_aio_cancel = raw_aio_cancel, .aiocb_size = sizeof(RawAIOCB), #endif + .bdrv_pread = raw_pread, .bdrv_pwrite = raw_pwrite, .bdrv_getlength = raw_getlength, diff --git a/qemu/block-vvfat.c b/qemu/block-vvfat.c index b8fa7298..1ac4472a 100644 --- a/qemu/block-vvfat.c +++ b/qemu/block-vvfat.c @@ -1249,7 +1249,7 @@ static void print_direntry(const direntry_t* direntry) unsigned char* c=(unsigned char*)direntry; int i; for(i=1;i<11 && c[i] && c[i]!=0xff;i+=2) -#define ADD_CHAR(c) {buffer[j] = (c); if (buffer[j] < ' ') buffer[j] = '°'; j++;} +#define ADD_CHAR(c) {buffer[j] = (c); if (buffer[j] < ' ') buffer[j] = 0xb0; j++;} ADD_CHAR(c[i]); for(i=14;i<26 && c[i] && c[i]!=0xff;i+=2) ADD_CHAR(c[i]); @@ -2848,4 +2848,3 @@ static void checkpoint(void) { print_direntry(NULL); } #endif - diff --git a/qemu/bsd-user/qemu-types.h b/qemu/bsd-user/qemu-types.h new file mode 100644 index 00000000..1adda9fb --- /dev/null +++ b/qemu/bsd-user/qemu-types.h @@ -0,0 +1,24 @@ +#ifndef QEMU_TYPES_H +#define QEMU_TYPES_H +#include "cpu.h" + +#ifdef TARGET_ABI32 +typedef uint32_t abi_ulong; +typedef int32_t abi_long; +#define TARGET_ABI_FMT_lx "%08x" +#define TARGET_ABI_FMT_ld "%d" +#define TARGET_ABI_FMT_lu "%u" +#define TARGET_ABI_BITS 32 +#else +typedef target_ulong abi_ulong; +typedef target_long abi_long; +#define TARGET_ABI_FMT_lx TARGET_FMT_lx +#define TARGET_ABI_FMT_ld TARGET_FMT_ld +#define TARGET_ABI_FMT_lu TARGET_FMT_lu +#define TARGET_ABI_BITS TARGET_LONG_BITS +/* for consistency, define ABI32 too */ +#if TARGET_ABI_BITS == 32 +#define TARGET_ABI32 1 +#endif +#endif +#endif diff --git a/qemu/bsd-user/qemu.h b/qemu/bsd-user/qemu.h index 0a55ac38..3ea0044f 100644 --- a/qemu/bsd-user/qemu.h +++ b/qemu/bsd-user/qemu.h @@ -11,25 +11,7 @@ #include <stdlib.h> #endif /* DEBUG_REMAP */ -#ifdef TARGET_ABI32 -typedef uint32_t abi_ulong; -typedef int32_t abi_long; -#define TARGET_ABI_FMT_lx "%08x" -#define TARGET_ABI_FMT_ld "%d" -#define TARGET_ABI_FMT_lu "%u" -#define TARGET_ABI_BITS 32 -#else -typedef target_ulong abi_ulong; -typedef target_long abi_long; -#define TARGET_ABI_FMT_lx TARGET_FMT_lx -#define TARGET_ABI_FMT_ld TARGET_FMT_ld -#define TARGET_ABI_FMT_lu TARGET_FMT_lu -#define TARGET_ABI_BITS TARGET_LONG_BITS -/* for consistency, define ABI32 too */ -#if TARGET_ABI_BITS == 32 -#define TARGET_ABI32 1 -#endif -#endif +#include "qemu-types.h" enum BSDType { target_freebsd, diff --git a/qemu/buffered_file.c b/qemu/buffered_file.c index 1d72b463..be5baea6 100644 --- a/qemu/buffered_file.c +++ b/qemu/buffered_file.c @@ -247,4 +247,3 @@ QEMUFile *qemu_fopen_ops_buffered(void *opaque, return s->file; } - diff --git a/qemu/cache-utils.c b/qemu/cache-utils.c new file mode 100644 index 00000000..7c98144a --- /dev/null +++ b/qemu/cache-utils.c @@ -0,0 +1,71 @@ +#include "cache-utils.h" + +#ifdef __powerpc__ +struct qemu_cache_conf qemu_cache_conf = { + .dcache_bsize = 16, + .icache_bsize = 16 +}; + +#if defined _AIX +#include <sys/systemcfg.h> + +static void ppc_init_cacheline_sizes(void) +{ + qemu_cache_conf.icache_bsize = _system_configuration.icache_line; + qemu_cache_conf.dcache_bsize = _system_configuration.dcache_line; +} + +#elif defined __linux__ + +#define QEMU_AT_NULL 0 +#define QEMU_AT_DCACHEBSIZE 19 +#define QEMU_AT_ICACHEBSIZE 20 + +static void ppc_init_cacheline_sizes(char **envp) +{ + unsigned long *auxv; + + while (*envp++); + + for (auxv = (unsigned long *) envp; *auxv != QEMU_AT_NULL; auxv += 2) { + switch (*auxv) { + case QEMU_AT_DCACHEBSIZE: qemu_cache_conf.dcache_bsize = auxv[1]; break; + case QEMU_AT_ICACHEBSIZE: qemu_cache_conf.icache_bsize = auxv[1]; break; + default: break; + } + } +} + +#elif defined __APPLE__ +#include <sys/types.h> +#include <sys/sysctl.h> + +static void ppc_init_cacheline_sizes(void) +{ + size_t len; + unsigned cacheline; + int name[2] = { CTL_HW, HW_CACHELINE }; + + if (sysctl(name, 2, &cacheline, &len, NULL, 0)) { + perror("sysctl CTL_HW HW_CACHELINE failed"); + } else { + qemu_cache_conf.dcache_bsize = cacheline; + qemu_cache_conf.icache_bsize = cacheline; + } +} +#endif + +#ifdef __linux__ +void qemu_cache_utils_init(char **envp) +{ + ppc_init_cacheline_sizes(envp); +} +#else +void qemu_cache_utils_init(char **envp) +{ + (void) envp; + ppc_init_cacheline_sizes(); +} +#endif + +#endif /* __powerpc__ */ diff --git a/qemu/cache-utils.h b/qemu/cache-utils.h new file mode 100644 index 00000000..0598b96e --- /dev/null +++ b/qemu/cache-utils.h @@ -0,0 +1,41 @@ +#ifndef QEMU_CACHE_UTILS_H +#define QEMU_CACHE_UTILS_H + +#ifdef __powerpc__ +struct qemu_cache_conf { + unsigned long dcache_bsize; + unsigned long icache_bsize; +}; + +extern struct qemu_cache_conf qemu_cache_conf; + +extern void qemu_cache_utils_init(char **envp); + +/* mildly adjusted code from tcg-dyngen.c */ +static inline void flush_icache_range(unsigned long start, unsigned long stop) +{ + unsigned long p, start1, stop1; + unsigned long dsize = qemu_cache_conf.dcache_bsize; + unsigned long isize = qemu_cache_conf.icache_bsize; + + start1 = start & ~(dsize - 1); + stop1 = (stop + dsize - 1) & ~(dsize - 1); + for (p = start1; p < stop1; p += dsize) { + asm volatile ("dcbst 0,%0" : : "r"(p) : "memory"); + } + asm volatile ("sync" : : : "memory"); + + start &= start & ~(isize - 1); + stop1 = (stop + isize - 1) & ~(isize - 1); + for (p = start1; p < stop1; p += isize) { + asm volatile ("icbi 0,%0" : : "r"(p) : "memory"); + } + asm volatile ("sync" : : : "memory"); + asm volatile ("isync" : : : "memory"); +} + +#else +#define qemu_cache_utils_init(envp) do { (void) (envp); } while (0) +#endif + +#endif /* QEMU_CACHE_UTILS_H */ diff --git a/qemu/check_ops.sh b/qemu/check_ops.sh deleted file mode 100755 index 1c9cf87e..00000000 --- a/qemu/check_ops.sh +++ /dev/null @@ -1,50 +0,0 @@ -#! /bin/sh -# Script to check for duplicate function prologues in op.o -# Typically this indicates missing FORCE_RET(); -# This script does not detect other errors that may be present. - -# Usage: check_ops.sh [-m machine] [op.o] -# machine and op.o are guessed if not specified. - -if [ "x$1" = "x-m" ]; then - machine=$2 - shift 2 -else - machine=`uname -m` -fi -if [ -z "$1" ]; then - for f in `find . -name op.o`; do - /bin/sh "$0" -m $machine $f - done - exit 0 -fi - -case $machine in - i?86) - ret='\tret' - ;; - x86_64) - ret='\tretq' - ;; - arm) - ret='\tldm.*pc' - ;; - ppc* | powerpc*) - ret='\tblr' - ;; - mips*) - ret='\tjr.*ra' - ;; - s390*) - ret='\tbr.*' - ;; - *) - echo "Unknown machine `uname -m`" - ;; -esac -echo $1 -# op_exit_tb causes false positives on some hosts. -${CROSS}objdump -dr $1 | \ - sed -e '/>:$\|'"$ret"'/!d' -e 's/.*<\(.*\)>:/~\1:/' -e 's/.*'"$ret"'.*/!/' | \ - sed -e ':1;N;s/\n//;t1' | sed -e 's/~/\n/g' | grep -v '^op_exit_tb' | \ - grep '^op_.*!!' diff --git a/qemu/configure b/qemu/configure index 1f8b9b4c..5f5264fd 100755 --- a/qemu/configure +++ b/qemu/configure @@ -26,8 +26,6 @@ interp_prefix="/usr/gnemul/qemu-%M" static="no" cross_prefix="" cc="gcc" -gcc3_search="yes" -gcc3_list="gcc-3.4.6 gcc-3.4 gcc34 gcc-3.3.6 gcc-3.3 gcc33 gcc-3.2 gcc32" audio_drv_list="" audio_card_list="" host_cc="gcc" @@ -106,7 +104,6 @@ kqemu="no" profiler="no" cocoa="no" check_gfx="yes" -check_gcc="yes" softmmu="yes" linux_user="no" darwin_user="no" @@ -158,7 +155,6 @@ FreeBSD) bsd="yes" audio_drv_list="oss" audio_possible_drivers="oss sdl esd pa" -aio_lib="-lpthread" if [ "$cpu" = "i386" -o "$cpu" = "x86_64" ] ; then kqemu="yes" kvm="yes" @@ -169,7 +165,6 @@ bsd="yes" audio_drv_list="oss" audio_possible_drivers="oss sdl esd" oss_lib="-lossaudio" -aio_lib="-lrt -lpthread" ;; OpenBSD) bsd="yes" @@ -177,7 +172,6 @@ openbsd="yes" audio_drv_list="oss" audio_possible_drivers="oss sdl esd" oss_lib="-lossaudio" -aio_lib="-lpthread" ;; Darwin) bsd="yes" @@ -188,7 +182,6 @@ audio_drv_list="coreaudio" audio_possible_drivers="coreaudio sdl fmod" OS_CFLAGS="-mdynamic-no-pic" OS_LDFLAGS="-framework CoreFoundation -framework IOKit" -aio_lib="-lpthread" ;; SunOS) solaris="yes" @@ -290,7 +283,6 @@ for opt do --cross-prefix=*) cross_prefix="$optarg" ;; --cc=*) cc="$optarg" - gcc3_search="no" ;; --host-cc=*) host_cc="$optarg" ;; @@ -349,8 +341,6 @@ for opt do ;; --disable-gfx-check) check_gfx="no" ;; - --disable-gcc-check) check_gcc="no" - ;; --disable-system) softmmu="no" ;; --enable-system) softmmu="yes" @@ -408,7 +398,7 @@ done # default flags for all hosts CFLAGS="$CFLAGS -O2 -g -fno-strict-aliasing" -CFLAGS="$CFLAGS -Wall -Wundef -Wendif-labels -Wwrite-strings" +CFLAGS="$CFLAGS -Wall -Wundef -Wendif-labels -Wwrite-strings -Wmissing-prototypes -Wstrict-prototypes -Wredundant-decls" LDFLAGS="$LDFLAGS -g" if test "$werror" = "yes" ; then CFLAGS="$CFLAGS -Werror" @@ -528,7 +518,7 @@ cat > $TMPC <<EOF int main(void) {} EOF -if $cc $ARCH_CFLAGS -c -o $TMPO $TMPC 2> /dev/null ; then +if $cc $ARCH_CFLAGS -c -o $TMPO $TMPC > /dev/null 2> /dev/null ; then : C compiler works ok else echo "ERROR: \"$cc\" either does not exist or does not work" @@ -544,7 +534,7 @@ cat > $TMPC <<EOF int main(void) {} EOF -if $cc $ARCH_CFLAGS -c -o $TMPO $TMPC 2> /dev/null ; then +if $cc $ARCH_CFLAGS -c -o $TMPO $TMPC > /dev/null 2> /dev/null ; then mingw32="yes" fi @@ -556,49 +546,6 @@ if test "$mingw32" = "yes" ; then bsd_user="no" fi -if [ "$darwin" = "yes" -o "$mingw32" = "yes" ] ; then - AIOLIBS= -elif [ "$bsd" = "yes" ]; then - AIOLIBS="$aio_lib" -else - # Some Linux architectures (e.g. s390) don't imply -lpthread automatically. - AIOLIBS="-lrt -lpthread" -fi - -# Check for gcc4, error if pre-gcc4 -if test "$check_gcc" = "yes" ; then - cat > $TMPC <<EOF -#if __GNUC__ < 4 -#error gcc3 -#endif -int main(){return 0;} -EOF - if "$cc" $ARCH_CFLAGS -o $TMPE $TMPC 2> /dev/null ; then - echo "WARNING: \"$cc\" looks like gcc 4.x" - found_compat_cc="no" - if test "$gcc3_search" = "yes" ; then - echo "Looking for gcc 3.x" - for compat_cc in $gcc3_list ; do - if "$cross_prefix$compat_cc" --version 2> /dev/null | fgrep '(GCC) 3.' > /dev/null 2>&1 ; then - echo "Found \"$compat_cc\"" - cc="$cross_prefix$compat_cc" - found_compat_cc="yes" - break - fi - done - if test "$found_compat_cc" = "no" ; then - echo "gcc 3.x not found!" - fi - fi - if test "$found_compat_cc" = "no" ; then - echo "QEMU is known to have problems when compiled with gcc 4.x" - echo "It is recommended that you use gcc 3.x to build QEMU" - echo "To use this compiler anyway, configure with --disable-gcc-check" - exit 1; - fi - fi -fi - if test ! -x "$(which cgcc 2>/dev/null)"; then sparse="no" fi @@ -607,19 +554,6 @@ fi # Solaris specific configure tool chain decisions # if test "$solaris" = "yes" ; then - # - # gcc for solaris 10/fcs in /usr/sfw/bin doesn't compile qemu correctly - # override the check with --disable-gcc-check - # - if test "$solarisrev" -eq 10 -a "$check_gcc" = "yes" ; then - solgcc=`which $cc` - if test "$solgcc" = "/usr/sfw/bin/gcc" ; then - echo "Solaris 10/FCS gcc in /usr/sfw/bin will not compiled qemu correctly." - echo "please get gcc-3.4.3 or later, from www.blastwave.org using pkg-get -i gcc3" - echo "or get the latest patch from SunSolve for gcc" - exit 1 - fi - fi solinst=`which $install 2> /dev/null | /usr/bin/grep -v "no $install in"` if test -z "$solinst" ; then echo "Solaris install program not found. Use --install=/usr/ucb/install or" @@ -717,7 +651,7 @@ int main(int argc, char ** argv){ } EOF -if $cc $ARCH_CFLAGS -o $TMPE $TMPC 2> /dev/null ; then +if $cc $ARCH_CFLAGS -o $TMPE $TMPC > /dev/null 2> /dev/null ; then $TMPE && bigendian="yes" else echo big/little test failed @@ -777,7 +711,7 @@ void foo() } EOF -if $cc $ARCH_CFLAGS -c -o $TMPO $TMPC 2> /dev/null ; then +if $cc $ARCH_CFLAGS -c -o $TMPO $TMPC > /dev/null 2> /dev/null ; then : else nptl="no" @@ -822,7 +756,7 @@ cat > $TMPC << EOF #include <zlib.h> int main(void) { zlibVersion(); return 0; } EOF -if $cc $ARCH_CFLAGS -o $TMPE ${OS_CFLAGS} $TMPC -lz 2> /dev/null ; then +if $cc $ARCH_CFLAGS -o $TMPE ${OS_CFLAGS} $TMPC -lz > /dev/null 2> /dev/null ; then : else echo @@ -847,7 +781,7 @@ cat > $TMPC << EOF #undef main /* We don't want SDL to override our main() */ int main( void ) { return SDL_Init (SDL_INIT_VIDEO); } EOF - if $cc $ARCH_CFLAGS -o $TMPE ${OS_CFLAGS} `$sdl_config --cflags 2> /dev/null` $TMPC `$sdl_config --libs 2> /dev/null` 2> $TMPSDLLOG ; then + if $cc $ARCH_CFLAGS -o $TMPE ${OS_CFLAGS} `$sdl_config --cflags 2> /dev/null` $TMPC `$sdl_config --libs 2> /dev/null` > $TMPSDLLOG 2>&1 ; then _sdlversion=`$sdl_config --version | sed 's/[^0-9]//g'` if test "$_sdlversion" -lt 121 ; then sdl_too_old=yes @@ -866,7 +800,7 @@ EOF sdl_static_libs="$sdl_static_libs `aalib-config --static-libs`" fi - if $cc -o $TMPE ${OS_CFLAGS} `$sdl_config --cflags 2> /dev/null` $TMPC $sdl_static_libs 2> /dev/null; then + if $cc -o $TMPE ${OS_CFLAGS} `$sdl_config --cflags 2> /dev/null` $TMPC $sdl_static_libs > /dev/null 2> /dev/null; then sdl_static=yes fi fi # static link @@ -889,7 +823,7 @@ EOF vnc_tls_cflags=`pkg-config --cflags gnutls 2> /dev/null` vnc_tls_libs=`pkg-config --libs gnutls 2> /dev/null` if $cc $ARCH_CFLAGS -o $TMPE ${OS_CFLAGS} $vnc_tls_cflags $TMPC \ - $vnc_tls_libs 2> /dev/null ; then + $vnc_tls_libs > /dev/null 2> /dev/null ; then : else vnc_tls="no" @@ -908,7 +842,7 @@ int main(void) return 0; } EOF - if $cc $ARCH_CFLAGS -o $TMPE $TMPC -lvdeplug 2> /dev/null ; then + if $cc $ARCH_CFLAGS -o $TMPE $TMPC -lvdeplug > /dev/null 2> /dev/null ; then : else vde="no" @@ -929,7 +863,7 @@ audio_drv_probe() #include <$hdr> int main(void) { $exp } EOF - if $cc $ARCH_CFLAGS $cfl -o $TMPE $TMPC $lib 2> /dev/null ; then + if $cc $ARCH_CFLAGS $cfl -o $TMPE $TMPC $lib > /dev/null 2> /dev/null ; then : else echo @@ -993,7 +927,7 @@ cat > $TMPC << EOF #include <brlapi.h> int main( void ) { return brlapi__openConnection (NULL, NULL, NULL); } EOF - if $cc ${ARCH_CFLAGS} -o $TMPE ${OS_CFLAGS} $TMPC -lbrlapi 2> /dev/null ; then + if $cc ${ARCH_CFLAGS} -o $TMPE ${OS_CFLAGS} $TMPC -lbrlapi > /dev/null 2> /dev/null ; then brlapi=yes fi # brlapi compile test fi # -z $brlapi @@ -1007,7 +941,7 @@ if test "$curses" = "yes" ; then #include <curses.h> int main(void) { return curses_version(); } EOF - if $cc $ARCH_CFLAGS -o $TMPE $TMPC -lcurses 2> /dev/null ; then + if $cc $ARCH_CFLAGS -o $TMPE $TMPC -lcurses > /dev/null 2> /dev/null ; then curses=yes fi fi # test "$curses" @@ -1025,7 +959,7 @@ EOF bluez_cflags=`pkg-config --cflags bluez` bluez_libs=`pkg-config --libs bluez` if $cc $ARCH_CFLAGS -o $TMPE ${OS_CFLAGS} $bluez_cflags $TMPC \ - $bluez_libs 2> /dev/null ; then + $bluez_libs > /dev/null 2> /dev/null ; then : else bluez="no" @@ -1041,7 +975,8 @@ if test "$kvm" = "yes" ; then KVM_API_VERSION < 12 || \ KVM_API_VERSION > 12 || \ !defined(KVM_CAP_USER_MEMORY) || \ - !defined(KVM_CAP_SET_TSS_ADDR) + !defined(KVM_CAP_SET_TSS_ADDR) || \ + !defined(KVM_CAP_DESTROY_MEMORY_REGION_WORKS) #error Invalid KVM version #endif int main(void) { return 0; } @@ -1052,7 +987,7 @@ EOF kvm_cflags="" fi if $cc $ARCH_CFLAGS -o $TMPE ${OS_CFLAGS} $kvm_cflags $TMPC \ - 2>/dev/null ; then + > /dev/null 2>/dev/null ; then : else kvm="no" @@ -1061,14 +996,17 @@ fi ########################################## # AIO probe +AIOLIBS="" + if test "$aio" = "yes" ; then aio=no cat > $TMPC << EOF -#include <aio.h> -int main(void) { return aio_write(NULL); } +#include <pthread.h> +int main(void) { pthread_mutex_t lock; return 0; } EOF if $cc $ARCH_CFLAGS -o $TMPE $AIOLIBS $TMPC 2> /dev/null ; then aio=yes + AIOLIBS="-lpthread" fi fi @@ -1079,7 +1017,7 @@ cat > $TMPC <<EOF int main(void) { struct iovec iov; return 0; } EOF iovec=no -if $cc $ARCH_CFLAGS -o $TMPE $TMPC 2> /dev/null ; then +if $cc $ARCH_CFLAGS -o $TMPE $TMPC > /dev/null 2> /dev/null ; then iovec=yes fi @@ -1116,6 +1054,26 @@ if [ -x "`which texi2html 2>/dev/null`" ] && \ build_docs="yes" fi +########################################## +# Do we need librt +cat > $TMPC <<EOF +#include <signal.h> +#include <time.h> +int main(void) { clockid_t id; return clock_gettime(id, NULL); } +EOF + +rt=no +if $cc $ARCH_CFLAGS -o $TMPE $TMPC > /dev/null 2> /dev/null ; then + : +elif $cc $ARCH_CFLAGS -o $TMPE $TMPC -lrt > /dev/null 2> /dev/null ; then + rt=yes +fi + +if test "$rt" = "yes" ; then + # Hack, we should have a general purpose LIBS for this sort of thing + AIOLIBS="$AIOLIBS -lrt" +fi + if test "$mingw32" = "yes" ; then if test -z "$prefix" ; then prefix="c:\\\\Program Files\\\\Qemu" @@ -1234,7 +1192,9 @@ config_h="config-host.h" test -f $config_h && mv $config_h ${config_h}~ echo "# Automatically generated by configure - do not modify" > $config_mak -echo "# Configured with: $0 $@" >> $config_mak +echo -n "# Configured with:" >> $config_mak +printf " '%s'" "$0" "$@" >> $config_mak +echo >> $config_mak echo "/* Automatically generated by configure - do not modify */" > $config_h echo "prefix=$prefix" >> $config_mak @@ -1349,7 +1309,7 @@ else #include <byteswap.h> int main(void) { return bswap_32(0); } EOF - if $cc $ARCH_CFLAGS -o $TMPE $TMPC 2> /dev/null ; then + if $cc $ARCH_CFLAGS -o $TMPE $TMPC >/dev/null 2> /dev/null ; then echo "#define HAVE_BYTESWAP_H 1" >> $config_h fi cat > $TMPC << EOF @@ -1358,7 +1318,7 @@ EOF #include <machine/bswap.h> int main(void) { return bswap32(0); } EOF - if $cc $ARCH_CFLAGS -o $TMPE $TMPC 2> /dev/null ; then + if $cc $ARCH_CFLAGS -o $TMPE $TMPC >/dev/null 2> /dev/null ; then echo "#define HAVE_MACHINE_BSWAP_H 1" >> $config_h fi fi @@ -1685,13 +1645,6 @@ case "$target_cpu" in echo "KVM_CFLAGS=$kvm_cflags" >> $config_mak echo "#define CONFIG_KVM 1" >> $config_h fi - gcc3minver=`$cc --version 2> /dev/null| fgrep "(GCC) 3." | awk '{ print $3 }' | cut -f2 -d.` - if test -n "$gcc3minver" && test $gcc3minver -gt 3 - then - echo "HAVE_GT_GCC_3_3=true" >> $config_mak - else - echo "HAVE_GT_GCC_3_3=false" >> $config_mak - fi configure_kvm ;; x86_64) @@ -1764,19 +1717,15 @@ case "$target_cpu" in ;; ppc) echo "TARGET_ARCH=ppc" >> $config_mak - echo "CONFIG_DYNGEN_OP=yes" >> $config_mak echo "#define TARGET_ARCH \"ppc\"" >> $config_h echo "#define TARGET_PPC 1" >> $config_h - echo "#define CONFIG_DYNGEN_OP 1" >> $config_h ;; ppcemb) echo "TARGET_ARCH=ppcemb" >> $config_mak echo "TARGET_ABI_DIR=ppc" >> $config_mak - echo "CONFIG_DYNGEN_OP=yes" >> $config_mak echo "#define TARGET_ARCH \"ppcemb\"" >> $config_h echo "#define TARGET_PPC 1" >> $config_h echo "#define TARGET_PPCEMB 1" >> $config_h - echo "#define CONFIG_DYNGEN_OP 1" >> $config_h if test "$device_tree_support" = "yes" ; then echo "#define CONFIG_LIBFDT 1" >> $config_h echo "CONFIG_LIBFDT=1" >> $config_mak @@ -1786,22 +1735,18 @@ case "$target_cpu" in ppc64) echo "TARGET_ARCH=ppc64" >> $config_mak echo "TARGET_ABI_DIR=ppc" >> $config_mak - echo "CONFIG_DYNGEN_OP=yes" >> $config_mak echo "#define TARGET_ARCH \"ppc64\"" >> $config_h echo "#define TARGET_PPC 1" >> $config_h echo "#define TARGET_PPC64 1" >> $config_h - echo "#define CONFIG_DYNGEN_OP 1" >> $config_h ;; ppc64abi32) echo "TARGET_ARCH=ppc64" >> $config_mak echo "TARGET_ABI_DIR=ppc" >> $config_mak echo "TARGET_ARCH2=ppc64abi32" >> $config_mak - echo "CONFIG_DYNGEN_OP=yes" >> $config_mak echo "#define TARGET_ARCH \"ppc64\"" >> $config_h echo "#define TARGET_PPC 1" >> $config_h echo "#define TARGET_PPC64 1" >> $config_h echo "#define TARGET_ABI32 1" >> $config_h - echo "#define CONFIG_DYNGEN_OP 1" >> $config_h ;; sh4|sh4eb) echo "TARGET_ARCH=sh4" >> $config_mak @@ -1873,6 +1818,8 @@ if test "$target_cpu" = "arm" \ -o "$target_cpu" = "mipsn32el" \ -o "$target_cpu" = "mips64" \ -o "$target_cpu" = "mips64el" \ + -o "$target_cpu" = "ppc" \ + -o "$target_cpu" = "ppc64" \ -o "$target_cpu" = "sparc" \ -o "$target_cpu" = "sparc64" \ -o "$target_cpu" = "sparc32plus"; then diff --git a/qemu/cpu-all.h b/qemu/cpu-all.h index b7928c58..c512f988 100644 --- a/qemu/cpu-all.h +++ b/qemu/cpu-all.h @@ -206,12 +206,12 @@ typedef union { * user : user mode access using soft MMU * kernel : kernel mode access using soft MMU */ -static inline int ldub_p(void *ptr) +static inline int ldub_p(const void *ptr) { return *(uint8_t *)ptr; } -static inline int ldsb_p(void *ptr) +static inline int ldsb_p(const void *ptr) { return *(int8_t *)ptr; } @@ -227,45 +227,45 @@ static inline void stb_p(void *ptr, int v) #if defined(WORDS_BIGENDIAN) || defined(WORDS_ALIGNED) /* conservative code for little endian unaligned accesses */ -static inline int lduw_le_p(void *ptr) +static inline int lduw_le_p(const void *ptr) { #ifdef __powerpc__ int val; __asm__ __volatile__ ("lhbrx %0,0,%1" : "=r" (val) : "r" (ptr)); return val; #else - uint8_t *p = ptr; + const uint8_t *p = ptr; return p[0] | (p[1] << 8); #endif } -static inline int ldsw_le_p(void *ptr) +static inline int ldsw_le_p(const void *ptr) { #ifdef __powerpc__ int val; __asm__ __volatile__ ("lhbrx %0,0,%1" : "=r" (val) : "r" (ptr)); return (int16_t)val; #else - uint8_t *p = ptr; + const uint8_t *p = ptr; return (int16_t)(p[0] | (p[1] << 8)); #endif } -static inline int ldl_le_p(void *ptr) +static inline int ldl_le_p(const void *ptr) { #ifdef __powerpc__ int val; __asm__ __volatile__ ("lwbrx %0,0,%1" : "=r" (val) : "r" (ptr)); return val; #else - uint8_t *p = ptr; + const uint8_t *p = ptr; return p[0] | (p[1] << 8) | (p[2] << 16) | (p[3] << 24); #endif } -static inline uint64_t ldq_le_p(void *ptr) +static inline uint64_t ldq_le_p(const void *ptr) { - uint8_t *p = ptr; + const uint8_t *p = ptr; uint32_t v1, v2; v1 = ldl_le_p(p); v2 = ldl_le_p(p + 4); @@ -305,7 +305,7 @@ static inline void stq_le_p(void *ptr, uint64_t v) /* float access */ -static inline float32 ldfl_le_p(void *ptr) +static inline float32 ldfl_le_p(const void *ptr) { union { float32 f; @@ -325,7 +325,7 @@ static inline void stfl_le_p(void *ptr, float32 v) stl_le_p(ptr, u.i); } -static inline float64 ldfq_le_p(void *ptr) +static inline float64 ldfq_le_p(const void *ptr) { CPU_DoubleU u; u.l.lower = ldl_le_p(ptr); @@ -343,22 +343,22 @@ static inline void stfq_le_p(void *ptr, float64 v) #else -static inline int lduw_le_p(void *ptr) +static inline int lduw_le_p(const void *ptr) { return *(uint16_t *)ptr; } -static inline int ldsw_le_p(void *ptr) +static inline int ldsw_le_p(const void *ptr) { return *(int16_t *)ptr; } -static inline int ldl_le_p(void *ptr) +static inline int ldl_le_p(const void *ptr) { return *(uint32_t *)ptr; } -static inline uint64_t ldq_le_p(void *ptr) +static inline uint64_t ldq_le_p(const void *ptr) { return *(uint64_t *)ptr; } @@ -380,12 +380,12 @@ static inline void stq_le_p(void *ptr, uint64_t v) /* float access */ -static inline float32 ldfl_le_p(void *ptr) +static inline float32 ldfl_le_p(const void *ptr) { return *(float32 *)ptr; } -static inline float64 ldfq_le_p(void *ptr) +static inline float64 ldfq_le_p(const void *ptr) { return *(float64 *)ptr; } @@ -403,7 +403,7 @@ static inline void stfq_le_p(void *ptr, float64 v) #if !defined(WORDS_BIGENDIAN) || defined(WORDS_ALIGNED) -static inline int lduw_be_p(void *ptr) +static inline int lduw_be_p(const void *ptr) { #if defined(__i386__) int val; @@ -413,12 +413,12 @@ static inline int lduw_be_p(void *ptr) : "m" (*(uint16_t *)ptr)); return val; #else - uint8_t *b = (uint8_t *) ptr; + const uint8_t *b = ptr; return ((b[0] << 8) | b[1]); #endif } -static inline int ldsw_be_p(void *ptr) +static inline int ldsw_be_p(const void *ptr) { #if defined(__i386__) int val; @@ -428,12 +428,12 @@ static inline int ldsw_be_p(void *ptr) : "m" (*(uint16_t *)ptr)); return (int16_t)val; #else - uint8_t *b = (uint8_t *) ptr; + const uint8_t *b = ptr; return (int16_t)((b[0] << 8) | b[1]); #endif } -static inline int ldl_be_p(void *ptr) +static inline int ldl_be_p(const void *ptr) { #if defined(__i386__) || defined(__x86_64__) int val; @@ -443,12 +443,12 @@ static inline int ldl_be_p(void *ptr) : "m" (*(uint32_t *)ptr)); return val; #else - uint8_t *b = (uint8_t *) ptr; + const uint8_t *b = ptr; return (b[0] << 24) | (b[1] << 16) | (b[2] << 8) | b[3]; #endif } -static inline uint64_t ldq_be_p(void *ptr) +static inline uint64_t ldq_be_p(const void *ptr) { uint32_t a,b; a = ldl_be_p(ptr); @@ -494,7 +494,7 @@ static inline void stq_be_p(void *ptr, uint64_t v) /* float access */ -static inline float32 ldfl_be_p(void *ptr) +static inline float32 ldfl_be_p(const void *ptr) { union { float32 f; @@ -514,7 +514,7 @@ static inline void stfl_be_p(void *ptr, float32 v) stl_be_p(ptr, u.i); } -static inline float64 ldfq_be_p(void *ptr) +static inline float64 ldfq_be_p(const void *ptr) { CPU_DoubleU u; u.l.upper = ldl_be_p(ptr); @@ -532,22 +532,22 @@ static inline void stfq_be_p(void *ptr, float64 v) #else -static inline int lduw_be_p(void *ptr) +static inline int lduw_be_p(const void *ptr) { return *(uint16_t *)ptr; } -static inline int ldsw_be_p(void *ptr) +static inline int ldsw_be_p(const void *ptr) { return *(int16_t *)ptr; } -static inline int ldl_be_p(void *ptr) +static inline int ldl_be_p(const void *ptr) { return *(uint32_t *)ptr; } -static inline uint64_t ldq_be_p(void *ptr) +static inline uint64_t ldq_be_p(const void *ptr) { return *(uint64_t *)ptr; } @@ -569,12 +569,12 @@ static inline void stq_be_p(void *ptr, uint64_t v) /* float access */ -static inline float32 ldfl_be_p(void *ptr) +static inline float32 ldfl_be_p(const void *ptr) { return *(float32 *)ptr; } -static inline float64 ldfq_be_p(void *ptr) +static inline float64 ldfq_be_p(const void *ptr) { return *(float64 *)ptr; } @@ -621,6 +621,9 @@ static inline void stfq_be_p(void *ptr, float64 v) /* MMU memory access macros */ #if defined(CONFIG_USER_ONLY) +#include <assert.h> +#include "qemu-types.h" + /* On some host systems the guest address space is reserved on the host. * This allows the guest address space to be offset to a convenient location. */ @@ -629,7 +632,16 @@ static inline void stfq_be_p(void *ptr, float64 v) /* All direct uses of g2h and h2g need to go away for usermode softmmu. */ #define g2h(x) ((void *)((unsigned long)(x) + GUEST_BASE)) -#define h2g(x) ((target_ulong)((unsigned long)(x) - GUEST_BASE)) +#define h2g(x) ({ \ + unsigned long __ret = (unsigned long)(x) - GUEST_BASE; \ + /* Check if given address fits target address space */ \ + assert(__ret == (abi_ulong)__ret); \ + (abi_ulong)__ret; \ +}) +#define h2g_valid(x) ({ \ + unsigned long __guest = (unsigned long)(x) - GUEST_BASE; \ + (__guest == (abi_ulong)__guest); \ +}) #define saddr(x) g2h(x) #define laddr(x) g2h(x) @@ -963,6 +975,15 @@ void cpu_physical_sync_dirty_bitmap(target_phys_addr_t start_addr, target_phys_a void dump_exec_info(FILE *f, int (*cpu_fprintf)(FILE *f, const char *fmt, ...)); +/* Coalesced MMIO regions are areas where write operations can be reordered. + * This usually implies that write operations are side-effect free. This allows + * batching which can make a major impact on performance when using + * virtualization. + */ +void qemu_register_coalesced_mmio(target_phys_addr_t addr, ram_addr_t size); + +void qemu_unregister_coalesced_mmio(target_phys_addr_t addr, ram_addr_t size); + /*******************************************/ /* host CPU ticks (if available) */ diff --git a/qemu/cpu-exec.c b/qemu/cpu-exec.c index e3e22af5..66f173fb 100644 --- a/qemu/cpu-exec.c +++ b/qemu/cpu-exec.c @@ -414,11 +414,11 @@ int cpu_exec(CPUState *env1) int intno; /* FIXME: this should respect TPR */ svm_check_intercept(SVM_EXIT_VINTR); - env->interrupt_request &= ~CPU_INTERRUPT_VIRQ; 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, 0, 1); + env->interrupt_request &= ~CPU_INTERRUPT_VIRQ; next_tb = 0; #endif } @@ -932,7 +932,7 @@ static inline int handle_cpu_signal(unsigned long pc, unsigned long address, /* we restore the process signal mask as the sigreturn should do it (XXX: use sigsetjmp) */ sigprocmask(SIG_SETMASK, old_set, NULL); - raise_exception_err(env, env->exception_index, env->error_code); + cpu_loop_exit(); } else { /* activate soft MMU for this block */ cpu_resume_from_signal(env, puc); diff --git a/qemu/cutils.c b/qemu/cutils.c index f6413146..280d0b16 100644 --- a/qemu/cutils.c +++ b/qemu/cutils.c @@ -136,7 +136,7 @@ char *urldecode(const char *ptr) return ret; } -int fls(int i) +int qemu_fls(int i) { return 32 - clz32(i); } diff --git a/qemu/darwin-user/ioctls_types.h b/qemu/darwin-user/ioctls_types.h index 63e65f03..014561a4 100644 --- a/qemu/darwin-user/ioctls_types.h +++ b/qemu/darwin-user/ioctls_types.h @@ -1 +1 @@ -STRUCT(termios, TYPE_INT, TYPE_INT, TYPE_INT, TYPE_INT, MK_ARRAY(TYPE_CHAR, 20), TYPE_INT, TYPE_INT)
\ No newline at end of file +STRUCT(termios, TYPE_INT, TYPE_INT, TYPE_INT, TYPE_INT, MK_ARRAY(TYPE_CHAR, 20), TYPE_INT, TYPE_INT) diff --git a/qemu/darwin-user/mmap.c b/qemu/darwin-user/mmap.c index b4055abe..bb7d7e69 100644 --- a/qemu/darwin-user/mmap.c +++ b/qemu/darwin-user/mmap.c @@ -408,4 +408,3 @@ int target_msync(unsigned long start, unsigned long len, int flags) start &= qemu_host_page_mask; return msync((void *)start, end - start, flags); } - diff --git a/qemu/darwin-user/signal.c b/qemu/darwin-user/signal.c index aeb8a622..f412b36f 100644 --- a/qemu/darwin-user/signal.c +++ b/qemu/darwin-user/signal.c @@ -455,5 +455,3 @@ handle_signal: if (q != &k->info) free_sigqueue(q); } - - diff --git a/qemu/def-helper.h b/qemu/def-helper.h index 98a5f680..d57ea4d5 100644 --- a/qemu/def-helper.h +++ b/qemu/def-helper.h @@ -218,4 +218,3 @@ DEF_HELPER_FLAGS_0(name, flags, ret) #undef GEN_HELPER #endif - diff --git a/qemu/dyngen-exec.h b/qemu/dyngen-exec.h index 9260b6f4..cc2502e6 100644 --- a/qemu/dyngen-exec.h +++ b/qemu/dyngen-exec.h @@ -198,13 +198,6 @@ extern int printf(const char *, ...); #error unsupported CPU #endif -/* force GCC to generate only one epilog at the end of the function */ -#define FORCE_RET() __asm__ __volatile__("" : : : "memory"); - -#ifndef OPPROTO -#define OPPROTO -#endif - #define xglue(x, y) x ## y #define glue(x, y) xglue(x, y) #define stringify(s) tostring(s) @@ -217,79 +210,6 @@ extern int printf(const char *, ...); #define __hidden #endif -#if defined(__alpha__) -/* Suggested by Richard Henderson. This will result in code like - ldah $0,__op_param1($29) !gprelhigh - lda $0,__op_param1($0) !gprellow - We can then conveniently change $29 to $31 and adapt the offsets to - emit the appropriate constant. */ -extern int __op_param1 __hidden; -extern int __op_param2 __hidden; -extern int __op_param3 __hidden; -#define PARAM1 ({ int _r; asm("" : "=r"(_r) : "0" (&__op_param1)); _r; }) -#define PARAM2 ({ int _r; asm("" : "=r"(_r) : "0" (&__op_param2)); _r; }) -#define PARAM3 ({ int _r; asm("" : "=r"(_r) : "0" (&__op_param3)); _r; }) -#elif defined(__s390__) -extern int __op_param1 __hidden; -extern int __op_param2 __hidden; -extern int __op_param3 __hidden; -#define PARAM1 ({ int _r; asm("bras %0,8; .long " ASM_NAME(__op_param1) "; l %0,0(%0)" : "=r"(_r) : ); _r; }) -#define PARAM2 ({ int _r; asm("bras %0,8; .long " ASM_NAME(__op_param2) "; l %0,0(%0)" : "=r"(_r) : ); _r; }) -#define PARAM3 ({ int _r; asm("bras %0,8; .long " ASM_NAME(__op_param3) "; l %0,0(%0)" : "=r"(_r) : ); _r; }) -#else -#if defined(__APPLE__) -static int __op_param1, __op_param2, __op_param3; -#else -extern int __op_param1, __op_param2, __op_param3; -#endif -#define PARAM1 ((long)(&__op_param1)) -#define PARAM2 ((long)(&__op_param2)) -#define PARAM3 ((long)(&__op_param3)) -#endif /* !defined(__alpha__) */ - -extern int __op_jmp0, __op_jmp1, __op_jmp2, __op_jmp3; - -#if defined(_WIN32) || defined(__APPLE__) -#define ASM_NAME(x) "_" #x -#else -#define ASM_NAME(x) #x -#endif - -#if defined(__i386__) -#define EXIT_TB() asm volatile ("ret") -#define GOTO_LABEL_PARAM(n) asm volatile ("jmp " ASM_NAME(__op_gen_label) #n) -#elif defined(__x86_64__) -#define EXIT_TB() asm volatile ("ret") -#define GOTO_LABEL_PARAM(n) asm volatile ("jmp " ASM_NAME(__op_gen_label) #n) -#elif defined(__powerpc__) -#define EXIT_TB() asm volatile ("blr") -#define GOTO_LABEL_PARAM(n) asm volatile ("b " ASM_NAME(__op_gen_label) #n) -#elif defined(__s390__) -#define EXIT_TB() asm volatile ("br %r14") -#define GOTO_LABEL_PARAM(n) asm volatile ("larl %r7,12; l %r7,0(%r7); br %r7; .long " ASM_NAME(__op_gen_label) #n) -#elif defined(__alpha__) -#define EXIT_TB() asm volatile ("ret") -#elif defined(__ia64__) -#define EXIT_TB() asm volatile ("br.ret.sptk.many b0;;") -#define GOTO_LABEL_PARAM(n) asm volatile ("br.sptk.many " \ - ASM_NAME(__op_gen_label) #n) -#elif defined(__sparc__) -#define EXIT_TB() asm volatile ("jmpl %i0 + 8, %g0; nop") -#define GOTO_LABEL_PARAM(n) asm volatile ("ba " ASM_NAME(__op_gen_label) #n ";nop") -#elif defined(__arm__) -#define EXIT_TB() asm volatile ("b exec_loop") -#define GOTO_LABEL_PARAM(n) asm volatile ("b " ASM_NAME(__op_gen_label) #n) -#elif defined(__mc68000) -#define EXIT_TB() asm volatile ("rts") -#elif defined(__mips__) -#define EXIT_TB() asm volatile ("jr $ra") -#define GOTO_LABEL_PARAM(n) asm volatile (".set noat; la $1, " ASM_NAME(__op_gen_label) #n "; jr $1; .set at") -#elif defined(__hppa__) -#define GOTO_LABEL_PARAM(n) asm volatile ("b,n " ASM_NAME(__op_gen_label) #n) -#else -#error unsupported CPU -#endif - /* The return address may point to the start of the next instruction. Subtracting one gets us the call instruction itself. */ #if defined(__s390__) diff --git a/qemu/dyngen.c b/qemu/dyngen.c deleted file mode 100644 index 2c7e9b5d..00000000 --- a/qemu/dyngen.c +++ /dev/null @@ -1,2793 +0,0 @@ -/* - * Generic Dynamic compiler generator - * - * Copyright (c) 2003 Fabrice Bellard - * - * The COFF object format support was extracted from Kazu's QEMU port - * to Win32. - * - * Mach-O Support by Matt Reda and Pierre d'Herbemont - * - * 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., 675 Mass Ave, Cambridge, MA 02139, USA. - */ -#include <stdlib.h> -#include <stdio.h> -#include <string.h> -#include <stdarg.h> -#include <inttypes.h> -#include <unistd.h> -#include <fcntl.h> - -#include "config-host.h" - -/* NOTE: we test CONFIG_WIN32 instead of _WIN32 to enabled cross - compilation */ -#if defined(CONFIG_WIN32) -#define CONFIG_FORMAT_COFF -#elif defined(CONFIG_DARWIN) -#define CONFIG_FORMAT_MACH -#else -#define CONFIG_FORMAT_ELF -#endif - -#ifdef CONFIG_FORMAT_ELF - -/* elf format definitions. We use these macros to test the CPU to - allow cross compilation (this tool must be ran on the build - platform) */ -#if defined(HOST_I386) - -#define ELF_CLASS ELFCLASS32 -#define ELF_ARCH EM_386 -#define elf_check_arch(x) ( ((x) == EM_386) || ((x) == EM_486) ) -#undef ELF_USES_RELOCA - -#elif defined(HOST_X86_64) - -#define ELF_CLASS ELFCLASS64 -#define ELF_ARCH EM_X86_64 -#define elf_check_arch(x) ((x) == EM_X86_64) -#define ELF_USES_RELOCA - -#elif defined(HOST_PPC) - -#define ELF_CLASS ELFCLASS32 -#define ELF_ARCH EM_PPC -#define elf_check_arch(x) ((x) == EM_PPC) -#define ELF_USES_RELOCA - -#elif defined(HOST_PPC64) - -#define ELF_CLASS ELFCLASS64 -#define ELF_ARCH EM_PPC64 -#define elf_check_arch(x) ((x) == EM_PPC64) -#define ELF_USES_RELOCA - -#elif defined(HOST_S390) - -#define ELF_CLASS ELFCLASS32 -#define ELF_ARCH EM_S390 -#define elf_check_arch(x) ((x) == EM_S390) -#define ELF_USES_RELOCA - -#elif defined(HOST_ALPHA) - -#define ELF_CLASS ELFCLASS64 -#define ELF_ARCH EM_ALPHA -#define elf_check_arch(x) ((x) == EM_ALPHA) -#define ELF_USES_RELOCA - -#elif defined(HOST_IA64) - -#define ELF_CLASS ELFCLASS64 -#define ELF_ARCH EM_IA_64 -#define elf_check_arch(x) ((x) == EM_IA_64) -#define ELF_USES_RELOCA - -#elif defined(HOST_SPARC) - -#define ELF_CLASS ELFCLASS32 -#define ELF_ARCH EM_SPARC -#define elf_check_arch(x) ((x) == EM_SPARC || (x) == EM_SPARC32PLUS) -#define ELF_USES_RELOCA - -#elif defined(HOST_SPARC64) - -#define ELF_CLASS ELFCLASS64 -#define ELF_ARCH EM_SPARCV9 -#define elf_check_arch(x) ((x) == EM_SPARCV9) -#define ELF_USES_RELOCA - -#elif defined(HOST_ARM) - -#define ELF_CLASS ELFCLASS32 -#define ELF_ARCH EM_ARM -#define elf_check_arch(x) ((x) == EM_ARM) -#define ELF_USES_RELOC - -#elif defined(HOST_M68K) - -#define ELF_CLASS ELFCLASS32 -#define ELF_ARCH EM_68K -#define elf_check_arch(x) ((x) == EM_68K) -#define ELF_USES_RELOCA - -#elif defined(HOST_HPPA) - -#define ELF_CLASS ELFCLASS32 -#define ELF_ARCH EM_PARISC -#define elf_check_arch(x) ((x) == EM_PARISC) -#define ELF_USES_RELOCA - -#elif defined(HOST_MIPS) - -#define ELF_CLASS ELFCLASS32 -#define ELF_ARCH EM_MIPS -#define elf_check_arch(x) ((x) == EM_MIPS) -#define ELF_USES_RELOC - -#elif defined(HOST_MIPS64) - -/* Assume n32 ABI here, which is ELF32. */ -#define ELF_CLASS ELFCLASS32 -#define ELF_ARCH EM_MIPS -#define elf_check_arch(x) ((x) == EM_MIPS) -#define ELF_USES_RELOCA - -#else -#error unsupported CPU - please update the code -#endif - -#include "elf.h" - -#if ELF_CLASS == ELFCLASS32 -typedef int32_t host_long; -typedef uint32_t host_ulong; -#define swabls(x) swab32s(x) -#define swablss(x) swab32ss(x) -#else -typedef int64_t host_long; -typedef uint64_t host_ulong; -#define swabls(x) swab64s(x) -#define swablss(x) swab64ss(x) -#endif - -#ifdef ELF_USES_RELOCA -#define SHT_RELOC SHT_RELA -#else -#define SHT_RELOC SHT_REL -#endif - -#define EXE_RELOC ELF_RELOC -#define EXE_SYM ElfW(Sym) - -#endif /* CONFIG_FORMAT_ELF */ - -#ifdef CONFIG_FORMAT_COFF - -typedef int32_t host_long; -typedef uint32_t host_ulong; - -#include "a.out.h" - -#define FILENAMELEN 256 - -typedef struct coff_sym { - struct external_syment *st_syment; - char st_name[FILENAMELEN]; - uint32_t st_value; - int st_size; - uint8_t st_type; - uint8_t st_shndx; -} coff_Sym; - -typedef struct coff_rel { - struct external_reloc *r_reloc; - int r_offset; - uint8_t r_type; -} coff_Rel; - -#define EXE_RELOC struct coff_rel -#define EXE_SYM struct coff_sym - -#endif /* CONFIG_FORMAT_COFF */ - -#ifdef CONFIG_FORMAT_MACH - -#include <mach-o/loader.h> -#include <mach-o/nlist.h> -#include <mach-o/reloc.h> -#include <mach-o/ppc/reloc.h> - -# define check_mach_header(x) (x.magic == MH_MAGIC) -typedef int32_t host_long; -typedef uint32_t host_ulong; - -struct nlist_extended -{ - union { - char *n_name; - long n_strx; - } n_un; - unsigned char n_type; - unsigned char n_sect; - short st_desc; - unsigned long st_value; - unsigned long st_size; -}; - -#define EXE_RELOC struct relocation_info -#define EXE_SYM struct nlist_extended - -#endif /* CONFIG_FORMAT_MACH */ - -#include "bswap.h" - -enum { - OUT_GEN_OP, - OUT_CODE, - OUT_INDEX_OP, -}; - -/* all dynamically generated functions begin with this code */ -#define OP_PREFIX "op_" - -int do_swap; - -static void __attribute__((noreturn)) __attribute__((format (printf, 1, 2))) error(const char *fmt, ...) -{ - va_list ap; - va_start(ap, fmt); - fprintf(stderr, "dyngen: "); - vfprintf(stderr, fmt, ap); - fprintf(stderr, "\n"); - va_end(ap); - exit(1); -} - -static void *load_data(int fd, long offset, unsigned int size) -{ - char *data; - - data = malloc(size); - if (!data) - return NULL; - lseek(fd, offset, SEEK_SET); - if (read(fd, data, size) != size) { - free(data); - return NULL; - } - return data; -} - -static int strstart(const char *str, const char *val, const char **ptr) -{ - const char *p, *q; - p = str; - q = val; - while (*q != '\0') { - if (*p != *q) - return 0; - p++; - q++; - } - if (ptr) - *ptr = p; - return 1; -} - -static void pstrcpy(char *buf, int buf_size, const char *str) -{ - int c; - char *q = buf; - - if (buf_size <= 0) - return; - - for(;;) { - c = *str++; - if (c == 0 || q >= buf + buf_size - 1) - break; - *q++ = c; - } - *q = '\0'; -} - -static void swab16s(uint16_t *p) -{ - *p = bswap16(*p); -} - -static void swab32s(uint32_t *p) -{ - *p = bswap32(*p); -} - -static void swab32ss(int32_t *p) -{ - *p = bswap32(*p); -} - -static void swab64s(uint64_t *p) -{ - *p = bswap64(*p); -} - -static void swab64ss(int64_t *p) -{ - *p = bswap64(*p); -} - -static uint16_t get16(uint16_t *p) -{ - uint16_t val; - val = *p; - if (do_swap) - val = bswap16(val); - return val; -} - -static uint32_t get32(uint32_t *p) -{ - uint32_t val; - val = *p; - if (do_swap) - val = bswap32(val); - return val; -} - -static void put16(uint16_t *p, uint16_t val) -{ - if (do_swap) - val = bswap16(val); - *p = val; -} - -static void put32(uint32_t *p, uint32_t val) -{ - if (do_swap) - val = bswap32(val); - *p = val; -} - -/* executable information */ -EXE_SYM *symtab; -int nb_syms; -int text_shndx; -uint8_t *text; -EXE_RELOC *relocs; -int nb_relocs; - -#ifdef CONFIG_FORMAT_ELF - -/* ELF file info */ -struct elf_shdr *shdr; -uint8_t **sdata; -struct elfhdr ehdr; -char *strtab; - -static int elf_must_swap(struct elfhdr *h) -{ - union { - uint32_t i; - uint8_t b[4]; - } swaptest; - - swaptest.i = 1; - return (h->e_ident[EI_DATA] == ELFDATA2MSB) != - (swaptest.b[0] == 0); -} - -static void elf_swap_ehdr(struct elfhdr *h) -{ - swab16s(&h->e_type); /* Object file type */ - swab16s(&h-> e_machine); /* Architecture */ - swab32s(&h-> e_version); /* Object file version */ - swabls(&h-> e_entry); /* Entry point virtual address */ - swabls(&h-> e_phoff); /* Program header table file offset */ - swabls(&h-> e_shoff); /* Section header table file offset */ - swab32s(&h-> e_flags); /* Processor-specific flags */ - swab16s(&h-> e_ehsize); /* ELF header size in bytes */ - swab16s(&h-> e_phentsize); /* Program header table entry size */ - swab16s(&h-> e_phnum); /* Program header table entry count */ - swab16s(&h-> e_shentsize); /* Section header table entry size */ - swab16s(&h-> e_shnum); /* Section header table entry count */ - swab16s(&h-> e_shstrndx); /* Section header string table index */ -} - -static void elf_swap_shdr(struct elf_shdr *h) -{ - swab32s(&h-> sh_name); /* Section name (string tbl index) */ - swab32s(&h-> sh_type); /* Section type */ - swabls(&h-> sh_flags); /* Section flags */ - swabls(&h-> sh_addr); /* Section virtual addr at execution */ - swabls(&h-> sh_offset); /* Section file offset */ - swabls(&h-> sh_size); /* Section size in bytes */ - swab32s(&h-> sh_link); /* Link to another section */ - swab32s(&h-> sh_info); /* Additional section information */ - swabls(&h-> sh_addralign); /* Section alignment */ - swabls(&h-> sh_entsize); /* Entry size if section holds table */ -} - -static void elf_swap_phdr(struct elf_phdr *h) -{ - swab32s(&h->p_type); /* Segment type */ - swabls(&h->p_offset); /* Segment file offset */ - swabls(&h->p_vaddr); /* Segment virtual address */ - swabls(&h->p_paddr); /* Segment physical address */ - swabls(&h->p_filesz); /* Segment size in file */ - swabls(&h->p_memsz); /* Segment size in memory */ - swab32s(&h->p_flags); /* Segment flags */ - swabls(&h->p_align); /* Segment alignment */ -} - -static void elf_swap_rel(ELF_RELOC *rel) -{ - swabls(&rel->r_offset); - swabls(&rel->r_info); -#ifdef ELF_USES_RELOCA - swablss(&rel->r_addend); -#endif -} - -static struct elf_shdr *find_elf_section(struct elf_shdr *shdr, int shnum, - const char *shstr, const char *name) -{ - int i; - const char *shname; - struct elf_shdr *sec; - - for(i = 0; i < shnum; i++) { - sec = &shdr[i]; - if (!sec->sh_name) - continue; - shname = shstr + sec->sh_name; - if (!strcmp(shname, name)) - return sec; - } - return NULL; -} - -static int find_reloc(int sh_index) -{ - struct elf_shdr *sec; - int i; - - for(i = 0; i < ehdr.e_shnum; i++) { - sec = &shdr[i]; - if (sec->sh_type == SHT_RELOC && sec->sh_info == sh_index) - return i; - } - return 0; -} - -static host_ulong get_rel_offset(EXE_RELOC *rel) -{ - return rel->r_offset; -} - -static char *get_rel_sym_name(EXE_RELOC *rel) -{ - return strtab + symtab[ELFW(R_SYM)(rel->r_info)].st_name; -} - -static char *get_sym_name(EXE_SYM *sym) -{ - return strtab + sym->st_name; -} - -/* load an elf object file */ -static int load_object(const char *filename) -{ - int fd; - struct elf_shdr *sec, *symtab_sec, *strtab_sec, *text_sec; - int i, j; - ElfW(Sym) *sym; - char *shstr; - ELF_RELOC *rel; - - fd = open(filename, O_RDONLY); - if (fd < 0) - error("can't open file '%s'", filename); - - /* Read ELF header. */ - if (read(fd, &ehdr, sizeof (ehdr)) != sizeof (ehdr)) - error("unable to read file header"); - - /* Check ELF identification. */ - if (ehdr.e_ident[EI_MAG0] != ELFMAG0 - || ehdr.e_ident[EI_MAG1] != ELFMAG1 - || ehdr.e_ident[EI_MAG2] != ELFMAG2 - || ehdr.e_ident[EI_MAG3] != ELFMAG3 - || ehdr.e_ident[EI_VERSION] != EV_CURRENT) { - error("bad ELF header"); - } - - do_swap = elf_must_swap(&ehdr); - if (do_swap) - elf_swap_ehdr(&ehdr); - if (ehdr.e_ident[EI_CLASS] != ELF_CLASS) - error("Unsupported ELF class"); - if (ehdr.e_type != ET_REL) - error("ELF object file expected"); - if (ehdr.e_version != EV_CURRENT) - error("Invalid ELF version"); - if (!elf_check_arch(ehdr.e_machine)) - error("Unsupported CPU (e_machine=%d)", ehdr.e_machine); - - /* read section headers */ - shdr = load_data(fd, ehdr.e_shoff, ehdr.e_shnum * sizeof(struct elf_shdr)); - if (do_swap) { - for(i = 0; i < ehdr.e_shnum; i++) { - elf_swap_shdr(&shdr[i]); - } - } - - /* read all section data */ - sdata = malloc(sizeof(void *) * ehdr.e_shnum); - memset(sdata, 0, sizeof(void *) * ehdr.e_shnum); - - for(i = 0;i < ehdr.e_shnum; i++) { - sec = &shdr[i]; - if (sec->sh_type != SHT_NOBITS) - sdata[i] = load_data(fd, sec->sh_offset, sec->sh_size); - } - - sec = &shdr[ehdr.e_shstrndx]; - shstr = (char *)sdata[ehdr.e_shstrndx]; - - /* swap relocations */ - for(i = 0; i < ehdr.e_shnum; i++) { - sec = &shdr[i]; - if (sec->sh_type == SHT_RELOC) { - nb_relocs = sec->sh_size / sec->sh_entsize; - if (do_swap) { - for(j = 0, rel = (ELF_RELOC *)sdata[i]; j < nb_relocs; j++, rel++) - elf_swap_rel(rel); - } - } - } - /* text section */ - - text_sec = find_elf_section(shdr, ehdr.e_shnum, shstr, ".text"); - if (!text_sec) - error("could not find .text section"); - text_shndx = text_sec - shdr; - text = sdata[text_shndx]; - - /* find text relocations, if any */ - relocs = NULL; - nb_relocs = 0; - i = find_reloc(text_shndx); - if (i != 0) { - relocs = (ELF_RELOC *)sdata[i]; - nb_relocs = shdr[i].sh_size / shdr[i].sh_entsize; - } - - symtab_sec = find_elf_section(shdr, ehdr.e_shnum, shstr, ".symtab"); - if (!symtab_sec) - error("could not find .symtab section"); - strtab_sec = &shdr[symtab_sec->sh_link]; - - symtab = (ElfW(Sym) *)sdata[symtab_sec - shdr]; - strtab = (char *)sdata[symtab_sec->sh_link]; - - nb_syms = symtab_sec->sh_size / sizeof(ElfW(Sym)); - if (do_swap) { - for(i = 0, sym = symtab; i < nb_syms; i++, sym++) { - swab32s(&sym->st_name); - swabls(&sym->st_value); - swabls(&sym->st_size); - swab16s(&sym->st_shndx); - } - } - close(fd); - return 0; -} - -#endif /* CONFIG_FORMAT_ELF */ - -#ifdef CONFIG_FORMAT_COFF - -/* COFF file info */ -struct external_scnhdr *shdr; -uint8_t **sdata; -struct external_filehdr fhdr; -struct external_syment *coff_symtab; -char *strtab; -int coff_text_shndx, coff_data_shndx; - -int data_shndx; - -#define STRTAB_SIZE 4 - -#define DIR32 0x06 -#define DISP32 0x14 - -#define T_FUNCTION 0x20 -#define C_EXTERNAL 2 - -void sym_ent_name(struct external_syment *ext_sym, EXE_SYM *sym) -{ - char *q; - int c, i, len; - - if (ext_sym->e.e.e_zeroes != 0) { - q = sym->st_name; - for(i = 0; i < 8; i++) { - c = ext_sym->e.e_name[i]; - if (c == '\0') - break; - *q++ = c; - } - *q = '\0'; - } else { - pstrcpy(sym->st_name, sizeof(sym->st_name), strtab + ext_sym->e.e.e_offset); - } - - /* now convert the name to a C name (suppress the leading '_') */ - if (sym->st_name[0] == '_') { - len = strlen(sym->st_name); - memmove(sym->st_name, sym->st_name + 1, len - 1); - sym->st_name[len - 1] = '\0'; - } -} - -char *name_for_dotdata(struct coff_rel *rel) -{ - int i; - struct coff_sym *sym; - uint32_t text_data; - - text_data = *(uint32_t *)(text + rel->r_offset); - - for (i = 0, sym = symtab; i < nb_syms; i++, sym++) { - if (sym->st_syment->e_scnum == data_shndx && - text_data >= sym->st_value && - text_data < sym->st_value + sym->st_size) { - - return sym->st_name; - - } - } - return NULL; -} - -static char *get_sym_name(EXE_SYM *sym) -{ - return sym->st_name; -} - -static char *get_rel_sym_name(EXE_RELOC *rel) -{ - char *name; - name = get_sym_name(symtab + *(uint32_t *)(rel->r_reloc->r_symndx)); - if (!strcmp(name, ".data")) - name = name_for_dotdata(rel); - if (name[0] == '.') - return NULL; - return name; -} - -static host_ulong get_rel_offset(EXE_RELOC *rel) -{ - return rel->r_offset; -} - -struct external_scnhdr *find_coff_section(struct external_scnhdr *shdr, int shnum, const char *name) -{ - int i; - const char *shname; - struct external_scnhdr *sec; - - for(i = 0; i < shnum; i++) { - sec = &shdr[i]; - if (!sec->s_name) - continue; - shname = sec->s_name; - if (!strcmp(shname, name)) - return sec; - } - return NULL; -} - -/* load a coff object file */ -int load_object(const char *filename) -{ - int fd; - struct external_scnhdr *sec, *text_sec, *data_sec; - int i; - struct external_syment *ext_sym; - struct external_reloc *coff_relocs; - struct external_reloc *ext_rel; - uint32_t *n_strtab; - EXE_SYM *sym; - EXE_RELOC *rel; - const char *p; - int aux_size, j; - - fd = open(filename, O_RDONLY -#ifdef _WIN32 - | O_BINARY -#endif - ); - if (fd < 0) - error("can't open file '%s'", filename); - - /* Read COFF header. */ - if (read(fd, &fhdr, sizeof (fhdr)) != sizeof (fhdr)) - error("unable to read file header"); - - /* Check COFF identification. */ - if (fhdr.f_magic != I386MAGIC) { - error("bad COFF header"); - } - do_swap = 0; - - /* read section headers */ - shdr = load_data(fd, sizeof(struct external_filehdr) + fhdr.f_opthdr, fhdr.f_nscns * sizeof(struct external_scnhdr)); - - /* read all section data */ - sdata = malloc(sizeof(void *) * fhdr.f_nscns); - memset(sdata, 0, sizeof(void *) * fhdr.f_nscns); - - for(i = 0;i < fhdr.f_nscns; i++) { - sec = &shdr[i]; - if (!strstart(sec->s_name, ".bss", &p)) - sdata[i] = load_data(fd, sec->s_scnptr, sec->s_size); - } - - - /* text section */ - text_sec = find_coff_section(shdr, fhdr.f_nscns, ".text"); - if (!text_sec) - error("could not find .text section"); - coff_text_shndx = text_sec - shdr; - text = sdata[coff_text_shndx]; - - /* data section */ - data_sec = find_coff_section(shdr, fhdr.f_nscns, ".data"); - if (!data_sec) - error("could not find .data section"); - coff_data_shndx = data_sec - shdr; - - coff_symtab = load_data(fd, fhdr.f_symptr, fhdr.f_nsyms*SYMESZ); - for (i = 0, ext_sym = coff_symtab; i < nb_syms; i++, ext_sym++) { - for(i=0;i<8;i++) - printf(" %02x", ((uint8_t *)ext_sym->e.e_name)[i]); - printf("\n"); - } - - - n_strtab = load_data(fd, (fhdr.f_symptr + fhdr.f_nsyms*SYMESZ), STRTAB_SIZE); - strtab = load_data(fd, (fhdr.f_symptr + fhdr.f_nsyms*SYMESZ), *n_strtab); - - nb_syms = fhdr.f_nsyms; - - for (i = 0, ext_sym = coff_symtab; i < nb_syms; i++, ext_sym++) { - if (strstart(ext_sym->e.e_name, ".text", NULL)) - text_shndx = ext_sym->e_scnum; - if (strstart(ext_sym->e.e_name, ".data", NULL)) - data_shndx = ext_sym->e_scnum; - } - - /* set coff symbol */ - symtab = malloc(sizeof(struct coff_sym) * nb_syms); - - for (i = 0, ext_sym = coff_symtab, sym = symtab; i < nb_syms; i++, ext_sym++, sym++) { - memset(sym, 0, sizeof(*sym)); - sym->st_syment = ext_sym; - sym_ent_name(ext_sym, sym); - sym->st_value = ext_sym->e_value; - - aux_size = *(int8_t *)ext_sym->e_numaux; - if (ext_sym->e_scnum == text_shndx && ext_sym->e_type == T_FUNCTION) { - for (j = aux_size + 1; j < nb_syms - i; j++) { - if ((ext_sym + j)->e_scnum == text_shndx && - (ext_sym + j)->e_type == T_FUNCTION ){ - sym->st_size = (ext_sym + j)->e_value - ext_sym->e_value; - break; - } else if (j == nb_syms - i - 1) { - sec = &shdr[coff_text_shndx]; - sym->st_size = sec->s_size - ext_sym->e_value; - break; - } - } - } else if (ext_sym->e_scnum == data_shndx && *(uint8_t *)ext_sym->e_sclass == C_EXTERNAL) { - for (j = aux_size + 1; j < nb_syms - i; j++) { - if ((ext_sym + j)->e_scnum == data_shndx) { - sym->st_size = (ext_sym + j)->e_value - ext_sym->e_value; - break; - } else if (j == nb_syms - i - 1) { - sec = &shdr[coff_data_shndx]; - sym->st_size = sec->s_size - ext_sym->e_value; - break; - } - } - } else { - sym->st_size = 0; - } - - sym->st_type = ext_sym->e_type; - sym->st_shndx = ext_sym->e_scnum; - } - - - /* find text relocations, if any */ - sec = &shdr[coff_text_shndx]; - coff_relocs = load_data(fd, sec->s_relptr, sec->s_nreloc*RELSZ); - nb_relocs = sec->s_nreloc; - - /* set coff relocation */ - relocs = malloc(sizeof(struct coff_rel) * nb_relocs); - for (i = 0, ext_rel = coff_relocs, rel = relocs; i < nb_relocs; - i++, ext_rel++, rel++) { - memset(rel, 0, sizeof(*rel)); - rel->r_reloc = ext_rel; - rel->r_offset = *(uint32_t *)ext_rel->r_vaddr; - rel->r_type = *(uint16_t *)ext_rel->r_type; - } - return 0; -} - -#endif /* CONFIG_FORMAT_COFF */ - -#ifdef CONFIG_FORMAT_MACH - -/* File Header */ -struct mach_header mach_hdr; - -/* commands */ -struct segment_command *segment = 0; -struct dysymtab_command *dysymtabcmd = 0; -struct symtab_command *symtabcmd = 0; - -/* section */ -struct section *section_hdr; -struct section *text_sec_hdr; -uint8_t **sdata; - -/* relocs */ -struct relocation_info *relocs; - -/* symbols */ -EXE_SYM *symtab; -struct nlist *symtab_std; -char *strtab; - -/* indirect symbols */ -uint32_t *tocdylib; - -/* Utility functions */ - -static inline char *find_str_by_index(int index) -{ - return strtab+index; -} - -/* Used by dyngen common code */ -static char *get_sym_name(EXE_SYM *sym) -{ - char *name = find_str_by_index(sym->n_un.n_strx); - - if ( sym->n_type & N_STAB ) /* Debug symbols are ignored */ - return "debug"; - - if(!name) - return name; - if(name[0]=='_') - return name + 1; - else - return name; -} - -/* find a section index given its segname, sectname */ -static int find_mach_sec_index(struct section *section_hdr, int shnum, const char *segname, - const char *sectname) -{ - int i; - struct section *sec = section_hdr; - - for(i = 0; i < shnum; i++, sec++) { - if (!sec->segname || !sec->sectname) - continue; - if (!strcmp(sec->sectname, sectname) && !strcmp(sec->segname, segname)) - return i; - } - return -1; -} - -/* find a section header given its segname, sectname */ -struct section *find_mach_sec_hdr(struct section *section_hdr, int shnum, const char *segname, - const char *sectname) -{ - int index = find_mach_sec_index(section_hdr, shnum, segname, sectname); - if(index == -1) - return NULL; - return section_hdr+index; -} - - -static inline void fetch_next_pair_value(struct relocation_info * rel, unsigned int *value) -{ - struct scattered_relocation_info * scarel; - - if(R_SCATTERED & rel->r_address) { - scarel = (struct scattered_relocation_info*)rel; - if(scarel->r_type != PPC_RELOC_PAIR) - error("fetch_next_pair_value: looking for a pair which was not found (1)"); - *value = scarel->r_value; - } else { - if(rel->r_type != PPC_RELOC_PAIR) - error("fetch_next_pair_value: looking for a pair which was not found (2)"); - *value = rel->r_address; - } -} - -/* find a sym name given its value, in a section number */ -static const char * find_sym_with_value_and_sec_number( int value, int sectnum, int * offset ) -{ - int i, ret = -1; - - for( i = 0 ; i < nb_syms; i++ ) - { - if( !(symtab[i].n_type & N_STAB) && (symtab[i].n_type & N_SECT) && - (symtab[i].n_sect == sectnum) && (symtab[i].st_value <= value) ) - { - if( (ret<0) || (symtab[i].st_value >= symtab[ret].st_value) ) - ret = i; - } - } - if( ret < 0 ) { - *offset = 0; - return 0; - } else { - *offset = value - symtab[ret].st_value; - return get_sym_name(&symtab[ret]); - } -} - -/* - * Find symbol name given a (virtual) address, and a section which is of type - * S_NON_LAZY_SYMBOL_POINTERS or S_LAZY_SYMBOL_POINTERS or S_SYMBOL_STUBS - */ -static const char * find_reloc_name_in_sec_ptr(int address, struct section * sec_hdr) -{ - unsigned int tocindex, symindex, size; - const char *name = 0; - - /* Sanity check */ - if(!( address >= sec_hdr->addr && address < (sec_hdr->addr + sec_hdr->size) ) ) - return (char*)0; - - if( sec_hdr->flags & S_SYMBOL_STUBS ){ - size = sec_hdr->reserved2; - if(size == 0) - error("size = 0"); - - } - else if( sec_hdr->flags & S_LAZY_SYMBOL_POINTERS || - sec_hdr->flags & S_NON_LAZY_SYMBOL_POINTERS) - size = sizeof(unsigned long); - else - return 0; - - /* Compute our index in toc */ - tocindex = (address - sec_hdr->addr)/size; - symindex = tocdylib[sec_hdr->reserved1 + tocindex]; - - name = get_sym_name(&symtab[symindex]); - - return name; -} - -static const char * find_reloc_name_given_its_address(int address) -{ - unsigned int i; - for(i = 0; i < segment->nsects ; i++) - { - const char * name = find_reloc_name_in_sec_ptr(address, §ion_hdr[i]); - if((long)name != -1) - return name; - } - return 0; -} - -static const char * get_reloc_name(EXE_RELOC * rel, int * sslide) -{ - char * name = 0; - struct scattered_relocation_info * sca_rel = (struct scattered_relocation_info*)rel; - int sectnum = rel->r_symbolnum; - int sectoffset; - int other_half=0; - - /* init the slide value */ - *sslide = 0; - - if(R_SCATTERED & rel->r_address) - return (char *)find_reloc_name_given_its_address(sca_rel->r_value); - - if(rel->r_extern) - { - /* ignore debug sym */ - if ( symtab[rel->r_symbolnum].n_type & N_STAB ) - return 0; - return get_sym_name(&symtab[rel->r_symbolnum]); - } - - /* Intruction contains an offset to the symbols pointed to, in the rel->r_symbolnum section */ - sectoffset = *(uint32_t *)(text + rel->r_address) & 0xffff; - - if(sectnum==0xffffff) - return 0; - - /* Sanity Check */ - if(sectnum > segment->nsects) - error("sectnum > segment->nsects"); - - switch(rel->r_type) - { - case PPC_RELOC_LO16: fetch_next_pair_value(rel+1, &other_half); sectoffset |= (other_half << 16); - break; - case PPC_RELOC_HI16: fetch_next_pair_value(rel+1, &other_half); sectoffset = (sectoffset << 16) | (uint16_t)(other_half & 0xffff); - break; - case PPC_RELOC_HA16: fetch_next_pair_value(rel+1, &other_half); sectoffset = (sectoffset << 16) + (int16_t)(other_half & 0xffff); - break; - case PPC_RELOC_BR24: - sectoffset = ( *(uint32_t *)(text + rel->r_address) & 0x03fffffc ); - if (sectoffset & 0x02000000) sectoffset |= 0xfc000000; - break; - default: - error("switch(rel->type) not found"); - } - - if(rel->r_pcrel) - sectoffset += rel->r_address; - - if (rel->r_type == PPC_RELOC_BR24) - name = (char *)find_reloc_name_in_sec_ptr((int)sectoffset, §ion_hdr[sectnum-1]); - - /* search it in the full symbol list, if not found */ - if(!name) - name = (char *)find_sym_with_value_and_sec_number(sectoffset, sectnum, sslide); - - return name; -} - -/* Used by dyngen common code */ -static const char * get_rel_sym_name(EXE_RELOC * rel) -{ - int sslide; - return get_reloc_name( rel, &sslide); -} - -/* Used by dyngen common code */ -static host_ulong get_rel_offset(EXE_RELOC *rel) -{ - struct scattered_relocation_info * sca_rel = (struct scattered_relocation_info*)rel; - if(R_SCATTERED & rel->r_address) - return sca_rel->r_address; - else - return rel->r_address; -} - -/* load a mach-o object file */ -int load_object(const char *filename) -{ - int fd; - unsigned int offset_to_segment = 0; - unsigned int offset_to_dysymtab = 0; - unsigned int offset_to_symtab = 0; - struct load_command lc; - unsigned int i, j; - EXE_SYM *sym; - struct nlist *syment; - - fd = open(filename, O_RDONLY); - if (fd < 0) - error("can't open file '%s'", filename); - - /* Read Mach header. */ - if (read(fd, &mach_hdr, sizeof (mach_hdr)) != sizeof (mach_hdr)) - error("unable to read file header"); - - /* Check Mach identification. */ - if (!check_mach_header(mach_hdr)) { - error("bad Mach header"); - } - - if (mach_hdr.cputype != CPU_TYPE_POWERPC) - error("Unsupported CPU"); - - if (mach_hdr.filetype != MH_OBJECT) - error("Unsupported Mach Object"); - - /* read segment headers */ - for(i=0, j=sizeof(mach_hdr); i<mach_hdr.ncmds ; i++) - { - if(read(fd, &lc, sizeof(struct load_command)) != sizeof(struct load_command)) - error("unable to read load_command"); - if(lc.cmd == LC_SEGMENT) - { - offset_to_segment = j; - lseek(fd, offset_to_segment, SEEK_SET); - segment = malloc(sizeof(struct segment_command)); - if(read(fd, segment, sizeof(struct segment_command)) != sizeof(struct segment_command)) - error("unable to read LC_SEGMENT"); - } - if(lc.cmd == LC_DYSYMTAB) - { - offset_to_dysymtab = j; - lseek(fd, offset_to_dysymtab, SEEK_SET); - dysymtabcmd = malloc(sizeof(struct dysymtab_command)); - if(read(fd, dysymtabcmd, sizeof(struct dysymtab_command)) != sizeof(struct dysymtab_command)) - error("unable to read LC_DYSYMTAB"); - } - if(lc.cmd == LC_SYMTAB) - { - offset_to_symtab = j; - lseek(fd, offset_to_symtab, SEEK_SET); - symtabcmd = malloc(sizeof(struct symtab_command)); - if(read(fd, symtabcmd, sizeof(struct symtab_command)) != sizeof(struct symtab_command)) - error("unable to read LC_SYMTAB"); - } - j+=lc.cmdsize; - - lseek(fd, j, SEEK_SET); - } - - if(!segment) - error("unable to find LC_SEGMENT"); - - /* read section headers */ - section_hdr = load_data(fd, offset_to_segment + sizeof(struct segment_command), segment->nsects * sizeof(struct section)); - - /* read all section data */ - sdata = (uint8_t **)malloc(sizeof(void *) * segment->nsects); - memset(sdata, 0, sizeof(void *) * segment->nsects); - - /* Load the data in section data */ - for(i = 0; i < segment->nsects; i++) { - sdata[i] = load_data(fd, section_hdr[i].offset, section_hdr[i].size); - } - - /* text section */ - text_sec_hdr = find_mach_sec_hdr(section_hdr, segment->nsects, SEG_TEXT, SECT_TEXT); - i = find_mach_sec_index(section_hdr, segment->nsects, SEG_TEXT, SECT_TEXT); - if (i == -1 || !text_sec_hdr) - error("could not find __TEXT,__text section"); - text = sdata[i]; - - /* Make sure dysym was loaded */ - if(!(int)dysymtabcmd) - error("could not find __DYSYMTAB segment"); - - /* read the table of content of the indirect sym */ - tocdylib = load_data( fd, dysymtabcmd->indirectsymoff, dysymtabcmd->nindirectsyms * sizeof(uint32_t) ); - - /* Make sure symtab was loaded */ - if(!(int)symtabcmd) - error("could not find __SYMTAB segment"); - nb_syms = symtabcmd->nsyms; - - symtab_std = load_data(fd, symtabcmd->symoff, symtabcmd->nsyms * sizeof(struct nlist)); - strtab = load_data(fd, symtabcmd->stroff, symtabcmd->strsize); - - symtab = malloc(sizeof(EXE_SYM) * nb_syms); - - /* Now transform the symtab, to an extended version, with the sym size, and the C name */ - for(i = 0, sym = symtab, syment = symtab_std; i < nb_syms; i++, sym++, syment++) { - struct nlist *sym_follow, *sym_next = 0; - unsigned int j; - memset(sym, 0, sizeof(*sym)); - - if ( syment->n_type & N_STAB ) /* Debug symbols are skipped */ - continue; - - memcpy(sym, syment, sizeof(*syment)); - - /* Find the following symbol in order to get the current symbol size */ - for(j = 0, sym_follow = symtab_std; j < nb_syms; j++, sym_follow++) { - if ( sym_follow->n_sect != 1 || sym_follow->n_type & N_STAB || !(sym_follow->n_value > sym->st_value)) - continue; - if(!sym_next) { - sym_next = sym_follow; - continue; - } - if(!(sym_next->n_value > sym_follow->n_value)) - continue; - sym_next = sym_follow; - } - if(sym_next) - sym->st_size = sym_next->n_value - sym->st_value; - else - sym->st_size = text_sec_hdr->size - sym->st_value; - } - - /* Find Reloc */ - relocs = load_data(fd, text_sec_hdr->reloff, text_sec_hdr->nreloc * sizeof(struct relocation_info)); - nb_relocs = text_sec_hdr->nreloc; - - close(fd); - return 0; -} - -#endif /* CONFIG_FORMAT_MACH */ - -/* return true if the expression is a label reference */ -static int get_reloc_expr(char *name, int name_size, const char *sym_name) -{ - const char *p; - - if (strstart(sym_name, "__op_param", &p)) { - snprintf(name, name_size, "param%s", p); - } else if (strstart(sym_name, "__op_gen_label", &p)) { - snprintf(name, name_size, "param%s", p); - return 1; - } else { -#if defined(HOST_SPARC) || defined(HOST_HPPA) - if (sym_name[0] == '.') - snprintf(name, name_size, - "(long)(&__dot_%s)", - sym_name + 1); - else -#endif - snprintf(name, name_size, "(long)(&%s)", sym_name); - } - return 0; -} - -#ifdef HOST_IA64 - -#define PLT_ENTRY_SIZE 16 /* 1 bundle containing "brl" */ - -struct plt_entry { - struct plt_entry *next; - const char *name; - unsigned long addend; -} *plt_list; - -static int -get_plt_index (const char *name, unsigned long addend) -{ - struct plt_entry *plt, *prev= NULL; - int index = 0; - - /* see if we already have an entry for this target: */ - for (plt = plt_list; plt; ++index, prev = plt, plt = plt->next) - if (strcmp(plt->name, name) == 0 && plt->addend == addend) - return index; - - /* nope; create a new PLT entry: */ - - plt = malloc(sizeof(*plt)); - if (!plt) { - perror("malloc"); - exit(1); - } - memset(plt, 0, sizeof(*plt)); - plt->name = strdup(name); - plt->addend = addend; - - /* append to plt-list: */ - if (prev) - prev->next = plt; - else - plt_list = plt; - return index; -} - -#endif - -#define MAX_ARGS 3 - -/* generate op code */ -static void gen_code(const char *name, host_ulong offset, host_ulong size, - FILE *outfile, int gen_switch) -{ - int copy_size = 0; - uint8_t *p_start, *p_end; - host_ulong start_offset; - int nb_args, i, n; - uint8_t args_present[MAX_ARGS]; - const char *sym_name, *p; - EXE_RELOC *rel; - - /* Compute exact size excluding prologue and epilogue instructions. - * Increment start_offset to skip epilogue instructions, then compute - * copy_size the indicate the size of the remaining instructions (in - * bytes). - */ - p_start = text + offset; - p_end = p_start + size; - start_offset = offset; -#if defined(HOST_I386) || defined(HOST_X86_64) -#ifdef CONFIG_FORMAT_COFF - { - uint8_t *p; - p = p_end - 1; - if (p == p_start) - error("empty code for %s", name); - while (*p != 0xc3) { - p--; - if (p <= p_start) - error("ret or jmp expected at the end of %s", name); - } - copy_size = p - p_start; - } -#else - { - int len; - len = p_end - p_start; - if (len == 0) - error("empty code for %s", name); - if (p_end[-1] == 0xc3) { - len--; - } else { - error("ret or jmp expected at the end of %s", name); - } - copy_size = len; - } -#endif -#elif defined(HOST_PPC) - { - uint8_t *p; - p = (void *)(p_end - 4); - if (p == p_start) - error("empty code for %s", name); - if (get32((uint32_t *)p) != 0x4e800020) - error("blr expected at the end of %s", name); - copy_size = p - p_start; - } -#elif defined(HOST_S390) - { - uint8_t *p; - p = (void *)(p_end - 2); - if (p == p_start) - error("empty code for %s", name); - if ((get16((uint16_t *)p) & 0xfff0) != 0x07f0) - error("br expected at the end of %s", name); - copy_size = p - p_start; - } -#elif defined(HOST_ALPHA) - { - uint8_t *p; - p = p_end - 4; -#if 0 - /* XXX: check why it occurs */ - if (p == p_start) - error("empty code for %s", name); -#endif - if (get32((uint32_t *)p) != 0x6bfa8001) - error("ret expected at the end of %s", name); - copy_size = p - p_start; - } -#elif defined(HOST_IA64) - { - uint8_t *p; - p = (void *)(p_end - 4); - if (p == p_start) - error("empty code for %s", name); - /* br.ret.sptk.many b0;; */ - /* 08 00 84 00 */ - if (get32((uint32_t *)p) != 0x00840008) - error("br.ret.sptk.many b0;; expected at the end of %s", name); - copy_size = p_end - p_start; - } -#elif defined(HOST_SPARC) - { -#define INSN_SAVE 0x9de3a000 -#define INSN_RET 0x81c7e008 -#define INSN_RETL 0x81c3e008 -#define INSN_RESTORE 0x81e80000 -#define INSN_RETURN 0x81cfe008 -#define INSN_NOP 0x01000000 -#define INSN_ADD_SP 0x9c03a000 // add %sp, nn, %sp -#define INSN_SUB_SP 0x9c23a000 // sub %sp, nn, %sp - - uint32_t start_insn, end_insn1, end_insn2; - uint8_t *p; - p = (void *)(p_end - 8); - if (p <= p_start) - error("empty code for %s", name); - start_insn = get32((uint32_t *)(p_start + 0x0)); - end_insn1 = get32((uint32_t *)(p + 0x0)); - end_insn2 = get32((uint32_t *)(p + 0x4)); - if (((start_insn & ~0x1fff) == INSN_SAVE) || - (start_insn & ~0x1fff) == INSN_ADD_SP) { - p_start += 0x4; - start_offset += 0x4; - if (end_insn1 == INSN_RET && end_insn2 == INSN_RESTORE) - /* SPARC v7: ret; restore; */ ; - else if (end_insn1 == INSN_RETURN && end_insn2 == INSN_NOP) - /* SPARC v9: return; nop; */ ; - else if (end_insn1 == INSN_RETL && (end_insn2 & ~0x1fff) == INSN_SUB_SP) - /* SPARC v7: retl; sub %sp, nn, %sp; */ ; - else - - error("ret; restore; not found at end of %s", name); - } else if (end_insn1 == INSN_RETL && end_insn2 == INSN_NOP) { - ; - } else { - error("No save at the beginning of %s", name); - } -#if 0 - /* Skip a preceeding nop, if present. */ - if (p > p_start) { - skip_insn = get32((uint32_t *)(p - 0x4)); - if (skip_insn == INSN_NOP) - p -= 4; - } -#endif - copy_size = p - p_start; - } -#elif defined(HOST_SPARC64) - { -#define INSN_SAVE 0x9de3a000 -#define INSN_RET 0x81c7e008 -#define INSN_RETL 0x81c3e008 -#define INSN_RESTORE 0x81e80000 -#define INSN_RETURN 0x81cfe008 -#define INSN_NOP 0x01000000 -#define INSN_ADD_SP 0x9c03a000 // add %sp, nn, %sp -#define INSN_SUB_SP 0x9c23a000 // sub %sp, nn, %sp - - uint32_t start_insn, end_insn1, end_insn2, skip_insn; - uint8_t *p; - p = (void *)(p_end - 8); -#if 0 - /* XXX: check why it occurs */ - if (p <= p_start) - error("empty code for %s", name); -#endif - start_insn = get32((uint32_t *)(p_start + 0x0)); - end_insn1 = get32((uint32_t *)(p + 0x0)); - end_insn2 = get32((uint32_t *)(p + 0x4)); - if (((start_insn & ~0x1fff) == INSN_SAVE) || - (start_insn & ~0x1fff) == INSN_ADD_SP) { - p_start += 0x4; - start_offset += 0x4; - if (end_insn1 == INSN_RET && end_insn2 == INSN_RESTORE) - /* SPARC v7: ret; restore; */ ; - else if (end_insn1 == INSN_RETURN && end_insn2 == INSN_NOP) - /* SPARC v9: return; nop; */ ; - else if (end_insn1 == INSN_RETL && (end_insn2 & ~0x1fff) == INSN_SUB_SP) - /* SPARC v7: retl; sub %sp, nn, %sp; */ ; - else - - error("ret; restore; not found at end of %s", name); - } else if (end_insn1 == INSN_RETL && end_insn2 == INSN_NOP) { - ; - } else { - error("No save at the beginning of %s", name); - } - -#if 0 - /* Skip a preceeding nop, if present. */ - if (p > p_start) { - skip_insn = get32((uint32_t *)(p - 0x4)); - if (skip_insn == 0x01000000) - p -= 4; - } -#endif - - copy_size = p - p_start; - } -#elif defined(HOST_M68K) - { - uint8_t *p; - p = (void *)(p_end - 2); - if (p == p_start) - error("empty code for %s", name); - // remove NOP's, probably added for alignment - while ((get16((uint16_t *)p) == 0x4e71) && - (p>p_start)) - p -= 2; - if (get16((uint16_t *)p) != 0x4e75) - error("rts expected at the end of %s", name); - copy_size = p - p_start; - } -#elif defined(HOST_HPPA) - { - uint8_t *p; - p = p_start; - while (p < p_end) { - uint32_t insn = get32((uint32_t *)p); - if (insn == 0x6bc23fd9 || /* stw rp,-14(sp) */ - insn == 0x08030241 || /* copy r3,r1 */ - insn == 0x081e0243 || /* copy sp,r3 */ - (insn & 0xffffc000) == 0x37de0000 || /* ldo x(sp),sp */ - (insn & 0xffffc000) == 0x6fc10000) /* stwm r1,x(sp) */ - p += 4; - else - break; - } - start_offset += p - p_start; - p_start = p; - p = p_end - 4; - - while (p > p_start) { - uint32_t insn = get32((uint32_t *)p); - if ((insn & 0xffffc000) == 0x347e0000 || /* ldo x(r3),sp */ - (insn & 0xffe0c000) == 0x4fc00000 || /* ldwm x(sp),rx */ - (insn & 0xffffc000) == 0x37de0000 || /* ldo x(sp),sp */ - insn == 0x48623fd9 || /* ldw -14(r3),rp */ - insn == 0xe840c000 || /* bv r0(rp) */ - insn == 0xe840c002) /* bv,n r0(rp) */ - p -= 4; - else - break; - } - p += 4; - if (p <= p_start) - error("empty code for %s", name); - - copy_size = p - p_start; - } -#elif defined(HOST_MIPS) || defined(HOST_MIPS64) - { -#define INSN_RETURN 0x03e00008 -#define INSN_NOP 0x00000000 - - uint8_t *p = p_end; - - if (p < (p_start + 0x8)) { - error("empty code for %s", name); - } else { - uint32_t end_insn1, end_insn2; - - p -= 0x8; - end_insn1 = get32((uint32_t *)(p + 0x0)); - end_insn2 = get32((uint32_t *)(p + 0x4)); - if (end_insn1 != INSN_RETURN && end_insn2 != INSN_NOP) - error("jr ra not found at end of %s", name); - } - copy_size = p - p_start; - } -#elif defined(HOST_ARM) - error("dyngen targets not supported on ARM"); -#elif defined(HOST_PPC64) - error("dyngen targets not supported on PPC64"); -#else -#error unsupported CPU -#endif - - /* compute the number of arguments by looking at the relocations */ - for(i = 0;i < MAX_ARGS; i++) - args_present[i] = 0; - - for(i = 0, rel = relocs;i < nb_relocs; i++, rel++) { - host_ulong offset = get_rel_offset(rel); - if (offset >= start_offset && - offset < start_offset + (p_end - p_start)) { - sym_name = get_rel_sym_name(rel); - if(!sym_name) - continue; - if (strstart(sym_name, "__op_param", &p) || - strstart(sym_name, "__op_gen_label", &p)) { - n = strtoul(p, NULL, 10); - if (n > MAX_ARGS) - error("too many arguments in %s", name); - args_present[n - 1] = 1; - } - } - } - - nb_args = 0; - while (nb_args < MAX_ARGS && args_present[nb_args]) - nb_args++; - for(i = nb_args; i < MAX_ARGS; i++) { - if (args_present[i]) - error("inconsistent argument numbering in %s", name); - } - - if (gen_switch == 2) { - -#if defined(HOST_HPPA) - int op_size = copy_size; - int has_stubs = 0; - char relname[256]; - int type, is_label; - - for (i = 0, rel = relocs; i < nb_relocs; i++, rel++) { - if (rel->r_offset >= start_offset && - rel->r_offset < start_offset + copy_size) { - sym_name = get_rel_sym_name(rel); - sym_name = strtab + symtab[ELF32_R_SYM(rel->r_info)].st_name; - is_label = get_reloc_expr(relname, sizeof(relname), sym_name); - type = ELF32_R_TYPE(rel->r_info); - - if (!is_label && type == R_PARISC_PCREL17F) { - has_stubs = 1; - op_size += 8; /* ldil and be,n instructions */ - } - } - } - - if (has_stubs) - op_size += 4; /* b,l,n instruction, to skip past the stubs */ - - fprintf(outfile, "DEF(%s, %d, %d)\n", name + 3, nb_args, op_size); -#else - fprintf(outfile, "DEF(%s, %d, %d)\n", name + 3, nb_args, copy_size); -#endif - - } else if (gen_switch == 1) { - - /* output C code */ - fprintf(outfile, "case INDEX_%s: {\n", name); - if (nb_args > 0) { - fprintf(outfile, " long "); - for(i = 0; i < nb_args; i++) { - if (i != 0) - fprintf(outfile, ", "); - fprintf(outfile, "param%d", i + 1); - } - fprintf(outfile, ";\n"); - } -#if defined(HOST_IA64) - fprintf(outfile, " extern char %s;\n", name); -#else - fprintf(outfile, " extern void %s();\n", name); -#endif - - for(i = 0, rel = relocs;i < nb_relocs; i++, rel++) { - host_ulong offset = get_rel_offset(rel); - if (offset >= start_offset && - offset < start_offset + (p_end - p_start)) { - sym_name = get_rel_sym_name(rel); - if(!sym_name) - continue; - if (*sym_name && - !strstart(sym_name, "__op_param", NULL) && - !strstart(sym_name, "__op_jmp", NULL) && - !strstart(sym_name, "__op_gen_label", NULL)) { -#if defined(HOST_SPARC) || defined(HOST_HPPA) - if (sym_name[0] == '.') { - fprintf(outfile, - "extern char __dot_%s __asm__(\"%s\");\n", - sym_name+1, sym_name); - continue; - } -#endif -#if defined(__APPLE__) - /* Set __attribute((unused)) on darwin because we - want to avoid warning when we don't use the symbol. */ - fprintf(outfile, " extern char %s __attribute__((unused));\n", sym_name); -#elif defined(HOST_IA64) - if (ELF64_R_TYPE(rel->r_info) != R_IA64_PCREL21B) - /* - * PCREL21 br.call targets generally - * are out of range and need to go - * through an "import stub". - */ - fprintf(outfile, " extern char %s;\n", - sym_name); -#else - fprintf(outfile, "extern char %s;\n", sym_name); -#endif - } - } - } - -#ifdef __hppa__ - fprintf(outfile, " memcpy(gen_code_ptr, (void *)((char *)__canonicalize_funcptr_for_compare(%s)+%d), %d);\n", - name, (int)(start_offset - offset), copy_size); -#else - fprintf(outfile, " memcpy(gen_code_ptr, (void *)((char *)&%s+%d), %d);\n", - name, (int)(start_offset - offset), copy_size); -#endif - - /* emit code offset information */ - { - EXE_SYM *sym; - const char *sym_name, *p; - host_ulong val; - int n; - - for(i = 0, sym = symtab; i < nb_syms; i++, sym++) { - sym_name = get_sym_name(sym); - if (strstart(sym_name, "__op_label", &p)) { - uint8_t *ptr; - unsigned long offset; - - /* test if the variable refers to a label inside - the code we are generating */ -#ifdef CONFIG_FORMAT_COFF - if (sym->st_shndx == text_shndx) { - ptr = sdata[coff_text_shndx]; - } else if (sym->st_shndx == data_shndx) { - ptr = sdata[coff_data_shndx]; - } else { - ptr = NULL; - } -#elif defined(CONFIG_FORMAT_MACH) - if(!sym->n_sect) - continue; - ptr = sdata[sym->n_sect-1]; -#else - ptr = sdata[sym->st_shndx]; -#endif - if (!ptr) - error("__op_labelN in invalid section"); - offset = sym->st_value; -#ifdef CONFIG_FORMAT_MACH - offset -= section_hdr[sym->n_sect-1].addr; -#endif - val = *(host_ulong *)(ptr + offset); -#ifdef ELF_USES_RELOCA - { - int reloc_shndx, nb_relocs1, j; - - /* try to find a matching relocation */ - reloc_shndx = find_reloc(sym->st_shndx); - if (reloc_shndx) { - nb_relocs1 = shdr[reloc_shndx].sh_size / - shdr[reloc_shndx].sh_entsize; - rel = (ELF_RELOC *)sdata[reloc_shndx]; - for(j = 0; j < nb_relocs1; j++) { - if (rel->r_offset == offset) { - val = rel->r_addend; - break; - } - rel++; - } - } - } -#endif - if (val >= start_offset && val <= start_offset + copy_size) { - n = strtol(p, NULL, 10); - fprintf(outfile, " label_offsets[%d] = %ld + (gen_code_ptr - gen_code_buf);\n", n, (long)(val - start_offset)); - } - } - } - } - - /* load parameters in variables */ - for(i = 0; i < nb_args; i++) { - fprintf(outfile, " param%d = *opparam_ptr++;\n", i + 1); - } - - /* patch relocations */ -#if defined(HOST_I386) - { - char relname[256]; - int type, is_label; - int addend; - int reloc_offset; - for(i = 0, rel = relocs;i < nb_relocs; i++, rel++) { - if (rel->r_offset >= start_offset && - rel->r_offset < start_offset + copy_size) { - sym_name = get_rel_sym_name(rel); - if (!sym_name) - continue; - reloc_offset = rel->r_offset - start_offset; - if (strstart(sym_name, "__op_jmp", &p)) { - int n; - n = strtol(p, NULL, 10); - /* __op_jmp relocations are done at - runtime to do translated block - chaining: the offset of the instruction - needs to be stored */ - fprintf(outfile, " jmp_offsets[%d] = %d + (gen_code_ptr - gen_code_buf);\n", - n, reloc_offset); - continue; - } - - is_label = get_reloc_expr(relname, sizeof(relname), sym_name); - addend = get32((uint32_t *)(text + rel->r_offset)); -#ifdef CONFIG_FORMAT_ELF - type = ELF32_R_TYPE(rel->r_info); - if (is_label) { - switch(type) { - case R_386_32: - case R_386_PC32: - fprintf(outfile, " tcg_out_reloc(s, gen_code_ptr + %d, %d, %s, %d);\n", - reloc_offset, type, relname, addend); - break; - default: - error("unsupported i386 relocation (%d)", type); - } - } else { - switch(type) { - case R_386_32: - fprintf(outfile, " *(uint32_t *)(gen_code_ptr + %d) = %s + %d;\n", - reloc_offset, relname, addend); - break; - case R_386_PC32: - fprintf(outfile, " *(uint32_t *)(gen_code_ptr + %d) = %s - (long)(gen_code_ptr + %d) + %d;\n", - reloc_offset, relname, reloc_offset, addend); - break; - default: - error("unsupported i386 relocation (%d)", type); - } - } -#elif defined(CONFIG_FORMAT_COFF) - { - char *temp_name; - int j; - EXE_SYM *sym; - temp_name = get_sym_name(symtab + *(uint32_t *)(rel->r_reloc->r_symndx)); - if (!strcmp(temp_name, ".data")) { - for (j = 0, sym = symtab; j < nb_syms; j++, sym++) { - if (strstart(sym->st_name, sym_name, NULL)) { - addend -= sym->st_value; - } - } - } - } - type = rel->r_type; - if (is_label) { -/* TCG uses elf relocation constants */ -#define R_386_32 1 -#define R_386_PC32 2 - switch(type) { - case DIR32: - type = R_386_32; - goto do_reloc; - case DISP32: - type = R_386_PC32; - addend -= 4; - do_reloc: - fprintf(outfile, " tcg_out_reloc(s, gen_code_ptr + %d, %d, %s, %d);\n", - reloc_offset, type, relname, addend); - break; - default: - error("unsupported i386 relocation (%d)", type); - } - } else { - switch(type) { - case DIR32: - fprintf(outfile, " *(uint32_t *)(gen_code_ptr + %d) = %s + %d;\n", - reloc_offset, relname, addend); - break; - case DISP32: - fprintf(outfile, " *(uint32_t *)(gen_code_ptr + %d) = %s - (long)(gen_code_ptr + %d) + %d -4;\n", - reloc_offset, relname, reloc_offset, addend); - break; - default: - error("unsupported i386 relocation (%d)", type); - } - } -#else -#error unsupport object format -#endif - } - } - } -#elif defined(HOST_X86_64) - { - char relname[256]; - int type, is_label; - int addend; - int reloc_offset; - for(i = 0, rel = relocs;i < nb_relocs; i++, rel++) { - if (rel->r_offset >= start_offset && - rel->r_offset < start_offset + copy_size) { - sym_name = strtab + symtab[ELFW(R_SYM)(rel->r_info)].st_name; - is_label = get_reloc_expr(relname, sizeof(relname), sym_name); - type = ELF32_R_TYPE(rel->r_info); - addend = rel->r_addend; - reloc_offset = rel->r_offset - start_offset; - if (is_label) { - switch(type) { - case R_X86_64_32: - case R_X86_64_32S: - case R_X86_64_PC32: - fprintf(outfile, " tcg_out_reloc(s, gen_code_ptr + %d, %d, %s, %d);\n", - reloc_offset, type, relname, addend); - break; - default: - error("unsupported X86_64 relocation (%d)", type); - } - } else { - switch(type) { - case R_X86_64_32: - fprintf(outfile, " *(uint32_t *)(gen_code_ptr + %d) = (uint32_t)%s + %d;\n", - reloc_offset, relname, addend); - break; - case R_X86_64_32S: - fprintf(outfile, " *(uint32_t *)(gen_code_ptr + %d) = (int32_t)%s + %d;\n", - reloc_offset, relname, addend); - break; - case R_X86_64_PC32: - fprintf(outfile, " *(uint32_t *)(gen_code_ptr + %d) = %s - (long)(gen_code_ptr + %d) + %d;\n", - reloc_offset, relname, reloc_offset, addend); - break; - default: - error("unsupported X86_64 relocation (%d)", type); - } - } - } - } - } -#elif defined(HOST_PPC) - { -#ifdef CONFIG_FORMAT_ELF - char relname[256]; - int type; - int addend; - int is_label; - int reloc_offset; - for(i = 0, rel = relocs;i < nb_relocs; i++, rel++) { - if (rel->r_offset >= start_offset && - rel->r_offset < start_offset + copy_size) { - sym_name = strtab + symtab[ELFW(R_SYM)(rel->r_info)].st_name; - reloc_offset = rel->r_offset - start_offset; - if (strstart(sym_name, "__op_jmp", &p)) { - int n; - n = strtol(p, NULL, 10); - /* __op_jmp relocations are done at - runtime to do translated block - chaining: the offset of the instruction - needs to be stored */ - fprintf(outfile, " jmp_offsets[%d] = %d + (gen_code_ptr - gen_code_buf);\n", - n, reloc_offset); - continue; - } - - get_reloc_expr(relname, sizeof(relname), sym_name); - type = ELF32_R_TYPE(rel->r_info); - is_label = get_reloc_expr(relname, sizeof(relname), sym_name); - addend = rel->r_addend; - if (is_label) { - switch (type) { - case R_PPC_REL24: - fprintf (outfile, " tcg_out_reloc(s, gen_code_ptr + %d, %d, %s, %d);\n", - reloc_offset, type, relname, addend); - break; - default: - error ("unsupported ppc relocation (%d)", type); - } - } - else { - switch(type) { - case R_PPC_ADDR32: - fprintf(outfile, " *(uint32_t *)(gen_code_ptr + %d) = %s + %d;\n", - reloc_offset, relname, addend); - break; - case R_PPC_ADDR16_LO: - fprintf(outfile, " *(uint16_t *)(gen_code_ptr + %d) = (%s + %d);\n", - reloc_offset, relname, addend); - break; - case R_PPC_ADDR16_HI: - fprintf(outfile, " *(uint16_t *)(gen_code_ptr + %d) = (%s + %d) >> 16;\n", - reloc_offset, relname, addend); - break; - case R_PPC_ADDR16_HA: - fprintf(outfile, " *(uint16_t *)(gen_code_ptr + %d) = (%s + %d + 0x8000) >> 16;\n", - reloc_offset, relname, addend); - break; - case R_PPC_REL24: - /* warning: must be at 32 MB distancy */ - fprintf(outfile, "{\n" - " long disp = (%s - (long)(gen_code_ptr + %d) + %d);\n" - " if ((disp << 6) >> 6 != disp) {;\n" - " fprintf(stderr, \"Branch target is too far away\\n\");" - " abort();\n" - " }\n" - "}\n", - relname, reloc_offset, addend); - fprintf(outfile, " *(uint32_t *)(gen_code_ptr + %d) = (*(uint32_t *)(gen_code_ptr + %d) & ~0x03fffffc) | ((%s - (long)(gen_code_ptr + %d) + %d) & 0x03fffffc);\n", - reloc_offset, reloc_offset, relname, reloc_offset, addend); - break; - default: - error("unsupported powerpc relocation (%d)", type); - } - } - } - } -#elif defined(CONFIG_FORMAT_MACH) - struct scattered_relocation_info *scarel; - struct relocation_info * rel; - char final_sym_name[256]; - const char *sym_name; - const char *p; - int slide, sslide; - int i; - - for(i = 0, rel = relocs; i < nb_relocs; i++, rel++) { - unsigned int offset, length, value = 0; - unsigned int type, pcrel, isym = 0; - unsigned int usesym = 0; - - if(R_SCATTERED & rel->r_address) { - scarel = (struct scattered_relocation_info*)rel; - offset = (unsigned int)scarel->r_address; - length = scarel->r_length; - pcrel = scarel->r_pcrel; - type = scarel->r_type; - value = scarel->r_value; - } else { - value = isym = rel->r_symbolnum; - usesym = (rel->r_extern); - offset = rel->r_address; - length = rel->r_length; - pcrel = rel->r_pcrel; - type = rel->r_type; - } - - slide = offset - start_offset; - - if (!(offset >= start_offset && offset < start_offset + size)) - continue; /* not in our range */ - - sym_name = get_reloc_name(rel, &sslide); - - if(usesym && symtab[isym].n_type & N_STAB) - continue; /* don't handle STAB (debug sym) */ - - if (sym_name && strstart(sym_name, "__op_jmp", &p)) { - int n; - n = strtol(p, NULL, 10); - fprintf(outfile, " jmp_offsets[%d] = %d + (gen_code_ptr - gen_code_buf);\n", - n, slide); - continue; /* Nothing more to do */ - } - - if(!sym_name) { - fprintf(outfile, "/* #warning relocation not handled in %s (value 0x%x, %s, offset 0x%x, length 0x%x, %s, type 0x%x) */\n", - name, value, usesym ? "use sym" : "don't use sym", offset, length, pcrel ? "pcrel":"", type); - continue; /* dunno how to handle without final_sym_name */ - } - - get_reloc_expr(final_sym_name, sizeof(final_sym_name), - sym_name); - switch(type) { - case PPC_RELOC_BR24: - if (!strstart(sym_name,"__op_gen_label",&p)) { - fprintf(outfile, "{\n"); - fprintf(outfile, " uint32_t imm = *(uint32_t *)(gen_code_ptr + %d) & 0x3fffffc;\n", slide); - fprintf(outfile, " *(uint32_t *)(gen_code_ptr + %d) = (*(uint32_t *)(gen_code_ptr + %d) & ~0x03fffffc) | ((imm + ((long)%s - (long)gen_code_ptr) + %d) & 0x03fffffc);\n", - slide, slide, name, sslide); - fprintf(outfile, "}\n"); - } else { - fprintf(outfile, " *(uint32_t *)(gen_code_ptr + %d) = (*(uint32_t *)(gen_code_ptr + %d) & ~0x03fffffc) | (((long)%s - (long)gen_code_ptr - %d) & 0x03fffffc);\n", - slide, slide, final_sym_name, slide); - } - break; - case PPC_RELOC_HI16: - fprintf(outfile, " *(uint16_t *)(gen_code_ptr + %d + 2) = (%s + %d) >> 16;\n", - slide, final_sym_name, sslide); - break; - case PPC_RELOC_LO16: - fprintf(outfile, " *(uint16_t *)(gen_code_ptr + %d + 2) = (%s + %d);\n", - slide, final_sym_name, sslide); - break; - case PPC_RELOC_HA16: - fprintf(outfile, " *(uint16_t *)(gen_code_ptr + %d + 2) = (%s + %d + 0x8000) >> 16;\n", - slide, final_sym_name, sslide); - break; - default: - error("unsupported powerpc relocation (%d)", type); - } - } -#else -#error unsupport object format -#endif - } -#elif defined(HOST_S390) - { - char relname[256]; - int type; - int addend; - int reloc_offset; - for(i = 0, rel = relocs;i < nb_relocs; i++, rel++) { - if (rel->r_offset >= start_offset && - rel->r_offset < start_offset + copy_size) { - sym_name = strtab + symtab[ELFW(R_SYM)(rel->r_info)].st_name; - get_reloc_expr(relname, sizeof(relname), sym_name); - type = ELF32_R_TYPE(rel->r_info); - addend = rel->r_addend; - reloc_offset = rel->r_offset - start_offset; - switch(type) { - case R_390_32: - fprintf(outfile, " *(uint32_t *)(gen_code_ptr + %d) = %s + %d;\n", - reloc_offset, relname, addend); - break; - case R_390_16: - fprintf(outfile, " *(uint16_t *)(gen_code_ptr + %d) = %s + %d;\n", - reloc_offset, relname, addend); - break; - case R_390_8: - fprintf(outfile, " *(uint8_t *)(gen_code_ptr + %d) = %s + %d;\n", - reloc_offset, relname, addend); - break; - case R_390_PC32DBL: - if (ELF32_ST_TYPE(symtab[ELFW(R_SYM)(rel->r_info)].st_info) == STT_SECTION) { - fprintf(outfile, - " *(uint32_t *)(gen_code_ptr + %d) += " - "((long)&%s - (long)gen_code_ptr) >> 1;\n", - reloc_offset, name); - } - else - fprintf(outfile, - " *(uint32_t *)(gen_code_ptr + %d) = " - "(%s + %d - ((uint32_t)gen_code_ptr + %d)) >> 1;\n", - reloc_offset, relname, addend, reloc_offset); - break; - default: - error("unsupported s390 relocation (%d)", type); - } - } - } - } -#elif defined(HOST_ALPHA) - { - for (i = 0, rel = relocs; i < nb_relocs; i++, rel++) { - if (rel->r_offset >= start_offset && rel->r_offset < start_offset + copy_size) { - int type; - long reloc_offset; - - type = ELF64_R_TYPE(rel->r_info); - sym_name = strtab + symtab[ELF64_R_SYM(rel->r_info)].st_name; - reloc_offset = rel->r_offset - start_offset; - switch (type) { - case R_ALPHA_GPDISP: - /* The gp is just 32 bit, and never changes, so it's easiest to emit it - as an immediate instead of constructing it from the pv or ra. */ - fprintf(outfile, " immediate_ldah(gen_code_ptr + %ld, gp);\n", - reloc_offset); - fprintf(outfile, " immediate_lda(gen_code_ptr + %ld, gp);\n", - reloc_offset + (int)rel->r_addend); - break; - case R_ALPHA_LITUSE: - /* jsr to literal hint. Could be used to optimize to bsr. Ignore for - now, since some called functions (libc) need pv to be set up. */ - break; - case R_ALPHA_HINT: - /* Branch target prediction hint. Ignore for now. Should be already - correct for in-function jumps. */ - break; - case R_ALPHA_LITERAL: - /* Load a literal from the GOT relative to the gp. Since there's only a - single gp, nothing is to be done. */ - break; - case R_ALPHA_GPRELHIGH: - /* Handle fake relocations against __op_param symbol. Need to emit the - high part of the immediate value instead. Other symbols need no - special treatment. */ - if (strstart(sym_name, "__op_param", &p)) - fprintf(outfile, " immediate_ldah(gen_code_ptr + %ld, param%s);\n", - reloc_offset, p); - break; - case R_ALPHA_GPRELLOW: - if (strstart(sym_name, "__op_param", &p)) - fprintf(outfile, " immediate_lda(gen_code_ptr + %ld, param%s);\n", - reloc_offset, p); - break; - case R_ALPHA_BRSGP: - /* PC-relative jump. Tweak offset to skip the two instructions that try to - set up the gp from the pv. */ - fprintf(outfile, " fix_bsr(gen_code_ptr + %ld, (uint8_t *) &%s - (gen_code_ptr + %ld + 4) + 8);\n", - reloc_offset, sym_name, reloc_offset); - break; - default: - error("unsupported Alpha relocation (%d)", type); - } - } - } - } -#elif defined(HOST_IA64) - { - unsigned long sym_idx; - long code_offset; - char relname[256]; - int type; - long addend; - - for(i = 0, rel = relocs;i < nb_relocs; i++, rel++) { - sym_idx = ELF64_R_SYM(rel->r_info); - if (rel->r_offset < start_offset - || rel->r_offset >= start_offset + copy_size) - continue; - sym_name = (strtab + symtab[sym_idx].st_name); - code_offset = rel->r_offset - start_offset; - if (strstart(sym_name, "__op_jmp", &p)) { - int n; - n = strtol(p, NULL, 10); - /* __op_jmp relocations are done at - runtime to do translated block - chaining: the offset of the instruction - needs to be stored */ - fprintf(outfile, " jmp_offsets[%d] =" - "%ld + (gen_code_ptr - gen_code_buf);\n", - n, code_offset); - continue; - } - get_reloc_expr(relname, sizeof(relname), sym_name); - type = ELF64_R_TYPE(rel->r_info); - addend = rel->r_addend; - switch(type) { - case R_IA64_IMM64: - fprintf(outfile, - " ia64_imm64(gen_code_ptr + %ld, " - "%s + %ld);\n", - code_offset, relname, addend); - break; - case R_IA64_LTOFF22X: - case R_IA64_LTOFF22: - fprintf(outfile, " IA64_LTOFF(gen_code_ptr + %ld," - " %s + %ld, %d);\n", - code_offset, relname, addend, - (type == R_IA64_LTOFF22X)); - break; - case R_IA64_LDXMOV: - fprintf(outfile, - " ia64_ldxmov(gen_code_ptr + %ld," - " %s + %ld);\n", code_offset, relname, addend); - break; - - case R_IA64_PCREL21B: - if (strstart(sym_name, "__op_gen_label", NULL)) { - fprintf(outfile, - " ia64_imm21b(gen_code_ptr + %ld," - " (long) (%s + %ld -\n\t\t" - "((long) gen_code_ptr + %ld)) >> 4);\n", - code_offset, relname, addend, - code_offset & ~0xfUL); - } else { - fprintf(outfile, - " IA64_PLT(gen_code_ptr + %ld, " - "%d);\t/* %s + %ld */\n", - code_offset, - get_plt_index(sym_name, addend), - sym_name, addend); - } - break; - default: - error("unsupported ia64 relocation (0x%x)", - type); - } - } - fprintf(outfile, " ia64_nop_b(gen_code_ptr + %d);\n", - copy_size - 16 + 2); - } -#elif defined(HOST_SPARC) - { - char relname[256]; - int type; - int addend; - int reloc_offset; - for(i = 0, rel = relocs;i < nb_relocs; i++, rel++) { - if (rel->r_offset >= start_offset && - rel->r_offset < start_offset + copy_size) { - sym_name = strtab + symtab[ELF32_R_SYM(rel->r_info)].st_name; - get_reloc_expr(relname, sizeof(relname), sym_name); - type = ELF32_R_TYPE(rel->r_info); - addend = rel->r_addend; - reloc_offset = rel->r_offset - start_offset; - switch(type) { - case R_SPARC_32: - fprintf(outfile, " *(uint32_t *)(gen_code_ptr + %d) = %s + %d;\n", - reloc_offset, relname, addend); - break; - case R_SPARC_HI22: - fprintf(outfile, - " *(uint32_t *)(gen_code_ptr + %d) = " - "((*(uint32_t *)(gen_code_ptr + %d)) " - " & ~0x3fffff) " - " | (((%s + %d) >> 10) & 0x3fffff);\n", - reloc_offset, reloc_offset, relname, addend); - break; - case R_SPARC_LO10: - fprintf(outfile, - " *(uint32_t *)(gen_code_ptr + %d) = " - "((*(uint32_t *)(gen_code_ptr + %d)) " - " & ~0x3ff) " - " | ((%s + %d) & 0x3ff);\n", - reloc_offset, reloc_offset, relname, addend); - break; - case R_SPARC_WDISP30: - fprintf(outfile, - " *(uint32_t *)(gen_code_ptr + %d) = " - "((*(uint32_t *)(gen_code_ptr + %d)) " - " & ~0x3fffffff) " - " | ((((%s + %d) - (long)(gen_code_ptr + %d))>>2) " - " & 0x3fffffff);\n", - reloc_offset, reloc_offset, relname, addend, - reloc_offset); - break; - case R_SPARC_WDISP22: - fprintf(outfile, - " *(uint32_t *)(gen_code_ptr + %d) = " - "((*(uint32_t *)(gen_code_ptr + %d)) " - " & ~0x3fffff) " - " | ((((%s + %d) - (long)(gen_code_ptr + %d))>>2) " - " & 0x3fffff);\n", - rel->r_offset - start_offset, - rel->r_offset - start_offset, - relname, addend, - rel->r_offset - start_offset); - break; - default: - error("unsupported sparc relocation (%d)", type); - } - } - } - } -#elif defined(HOST_SPARC64) - { - char relname[256]; - int type; - int addend; - int reloc_offset; - for(i = 0, rel = relocs;i < nb_relocs; i++, rel++) { - if (rel->r_offset >= start_offset && - rel->r_offset < start_offset + copy_size) { - sym_name = strtab + symtab[ELF64_R_SYM(rel->r_info)].st_name; - get_reloc_expr(relname, sizeof(relname), sym_name); - type = ELF32_R_TYPE(rel->r_info); - addend = rel->r_addend; - reloc_offset = rel->r_offset - start_offset; - switch(type) { - case R_SPARC_32: - fprintf(outfile, " *(uint32_t *)(gen_code_ptr + %d) = %s + %d;\n", - reloc_offset, relname, addend); - break; - case R_SPARC_HI22: - fprintf(outfile, - " *(uint32_t *)(gen_code_ptr + %d) = " - "((*(uint32_t *)(gen_code_ptr + %d)) " - " & ~0x3fffff) " - " | (((%s + %d) >> 10) & 0x3fffff);\n", - reloc_offset, reloc_offset, relname, addend); - break; - case R_SPARC_LO10: - fprintf(outfile, - " *(uint32_t *)(gen_code_ptr + %d) = " - "((*(uint32_t *)(gen_code_ptr + %d)) " - " & ~0x3ff) " - " | ((%s + %d) & 0x3ff);\n", - reloc_offset, reloc_offset, relname, addend); - break; - case R_SPARC_OLO10: - addend += ELF64_R_TYPE_DATA (rel->r_info); - fprintf(outfile, - " *(uint32_t *)(gen_code_ptr + %d) = " - "((*(uint32_t *)(gen_code_ptr + %d)) " - " & ~0x3ff) " - " | ((%s + %d) & 0x3ff);\n", - reloc_offset, reloc_offset, relname, addend); - break; - case R_SPARC_WDISP30: - fprintf(outfile, - " *(uint32_t *)(gen_code_ptr + %d) = " - "((*(uint32_t *)(gen_code_ptr + %d)) " - " & ~0x3fffffff) " - " | ((((%s + %d) - (long)(gen_code_ptr + %d))>>2) " - " & 0x3fffffff);\n", - reloc_offset, reloc_offset, relname, addend, - reloc_offset); - break; - case R_SPARC_WDISP22: - fprintf(outfile, - " *(uint32_t *)(gen_code_ptr + %d) = " - "((*(uint32_t *)(gen_code_ptr + %d)) " - " & ~0x3fffff) " - " | ((((%s + %d) - (long)(gen_code_ptr + %d))>>2) " - " & 0x3fffff);\n", - reloc_offset, reloc_offset, relname, addend, - reloc_offset); - break; - case R_SPARC_HH22: - fprintf(outfile, - " *(uint32_t *)(gen_code_ptr + %d) = " - "((*(uint32_t *)(gen_code_ptr + %d)) " - " & ~0x00000000) " - " | (((%s + %d) >> 42) & 0x00000000);\n", - reloc_offset, reloc_offset, relname, addend); - break; - - case R_SPARC_LM22: - fprintf(outfile, - " *(uint32_t *)(gen_code_ptr + %d) = " - "((*(uint32_t *)(gen_code_ptr + %d)) " - " & ~0x00000000) " - " | (((%s + %d) >> 10) & 0x00000000);\n", - reloc_offset, reloc_offset, relname, addend); - break; - - case R_SPARC_HM10: - fprintf(outfile, - " *(uint32_t *)(gen_code_ptr + %d) = " - "((*(uint32_t *)(gen_code_ptr + %d)) " - " & ~0x00000000) " - " | ((((%s + %d) >> 32 & 0x3ff)) & 0x00000000);\n", - reloc_offset, reloc_offset, relname, addend); - break; - - default: - error("unsupported sparc64 relocation (%d) for symbol %s", type, relname); - } - } - } - } -#elif defined(HOST_M68K) - { - char relname[256]; - int type; - int addend; - int reloc_offset; - Elf32_Sym *sym; - for(i = 0, rel = relocs;i < nb_relocs; i++, rel++) { - if (rel->r_offset >= start_offset && - rel->r_offset < start_offset + copy_size) { - sym = &(symtab[ELFW(R_SYM)(rel->r_info)]); - sym_name = strtab + symtab[ELFW(R_SYM)(rel->r_info)].st_name; - get_reloc_expr(relname, sizeof(relname), sym_name); - type = ELF32_R_TYPE(rel->r_info); - addend = get32((uint32_t *)(text + rel->r_offset)) + rel->r_addend; - reloc_offset = rel->r_offset - start_offset; - switch(type) { - case R_68K_32: - fprintf(outfile, " /* R_68K_32 RELOC, offset %x */\n", rel->r_offset) ; - fprintf(outfile, " *(uint32_t *)(gen_code_ptr + %d) = %s + %#x;\n", - reloc_offset, relname, addend ); - break; - case R_68K_PC32: - fprintf(outfile, " /* R_68K_PC32 RELOC, offset %x */\n", rel->r_offset); - fprintf(outfile, " *(uint32_t *)(gen_code_ptr + %d) = %s - (long)(gen_code_ptr + %#x) + %#x;\n", - reloc_offset, relname, reloc_offset, /*sym->st_value+*/ addend); - break; - default: - error("unsupported m68k relocation (%d)", type); - } - } - } - } -#elif defined(HOST_HPPA) - { - char relname[256]; - int type, is_label; - int addend; - int reloc_offset; - for (i = 0, rel = relocs; i < nb_relocs; i++, rel++) { - if (rel->r_offset >= start_offset && - rel->r_offset < start_offset + copy_size) { - sym_name = get_rel_sym_name(rel); - sym_name = strtab + symtab[ELF32_R_SYM(rel->r_info)].st_name; - is_label = get_reloc_expr(relname, sizeof(relname), sym_name); - type = ELF32_R_TYPE(rel->r_info); - addend = rel->r_addend; - reloc_offset = rel->r_offset - start_offset; - - if (is_label) { - switch (type) { - case R_PARISC_PCREL17F: - fprintf(outfile, -" tcg_out_reloc(s, gen_code_ptr + %d, %d, %s, %d);\n", - reloc_offset, type, relname, addend); - break; - default: - error("unsupported hppa label relocation (%d)", type); - } - } else { - switch (type) { - case R_PARISC_DIR21L: - fprintf(outfile, -" hppa_patch21l((uint32_t *)(gen_code_ptr + %d), %s, %d);\n", - reloc_offset, relname, addend); - break; - case R_PARISC_DIR14R: - fprintf(outfile, -" hppa_patch14r((uint32_t *)(gen_code_ptr + %d), %s, %d);\n", - reloc_offset, relname, addend); - break; - case R_PARISC_PCREL17F: - if (strstart(sym_name, "__op_gen_label", NULL)) { - fprintf(outfile, -" hppa_patch17f((uint32_t *)(gen_code_ptr + %d), %s, %d);\n", - reloc_offset, relname, addend); - } else { - fprintf(outfile, -" HPPA_RECORD_BRANCH(hppa_stubs, (uint32_t *)(gen_code_ptr + %d), %s);\n", - reloc_offset, relname); - } - break; - case R_PARISC_DPREL21L: - if (strstart(sym_name, "__op_param", &p)) - fprintf(outfile, -" hppa_load_imm21l((uint32_t *)(gen_code_ptr + %d), param%s, %d);\n", - reloc_offset, p, addend); - else - fprintf(outfile, -" hppa_patch21l_dprel((uint32_t *)(gen_code_ptr + %d), %s, %d);\n", - reloc_offset, relname, addend); - break; - case R_PARISC_DPREL14R: - if (strstart(sym_name, "__op_param", &p)) - fprintf(outfile, -" hppa_load_imm14r((uint32_t *)(gen_code_ptr + %d), param%s, %d);\n", - reloc_offset, p, addend); - else - fprintf(outfile, -" hppa_patch14r_dprel((uint32_t *)(gen_code_ptr + %d), %s, %d);\n", - reloc_offset, relname, addend); - break; - default: - error("unsupported hppa relocation (%d)", type); - } - } - } - } - } -#elif defined(HOST_MIPS) || defined(HOST_MIPS64) - { - for (i = 0, rel = relocs; i < nb_relocs; i++, rel++) { - if (rel->r_offset >= start_offset && rel->r_offset < start_offset + copy_size) { - char relname[256]; - int type; - int addend; - int reloc_offset; - - sym_name = strtab + symtab[ELF32_R_SYM(rel->r_info)].st_name; - /* the compiler leave some unnecessary references to the code */ - if (sym_name[0] == '\0') - continue; - get_reloc_expr(relname, sizeof(relname), sym_name); - type = ELF32_R_TYPE(rel->r_info); - addend = get32((uint32_t *)(text + rel->r_offset)); - reloc_offset = rel->r_offset - start_offset; - switch (type) { - case R_MIPS_26: - fprintf(outfile, " /* R_MIPS_26 RELOC, offset 0x%x, name %s */\n", - rel->r_offset, sym_name); - fprintf(outfile, - " *(uint32_t *)(gen_code_ptr + 0x%x) = " - "(0x%x & ~0x3fffff) " - "| ((0x%x + ((%s - (*(uint32_t *)(gen_code_ptr + 0x%x))) >> 2)) " - " & 0x3fffff);\n", - reloc_offset, addend, addend, relname, reloc_offset); - break; - case R_MIPS_HI16: - fprintf(outfile, " /* R_MIPS_HI16 RELOC, offset 0x%x, name %s */\n", - rel->r_offset, sym_name); - fprintf(outfile, - " *(uint32_t *)(gen_code_ptr + 0x%x) = " - "((*(uint32_t *)(gen_code_ptr + 0x%x)) " - " & ~0xffff) " - " | (((%s - 0x8000) >> 16) & 0xffff);\n", - reloc_offset, reloc_offset, relname); - break; - case R_MIPS_LO16: - fprintf(outfile, " /* R_MIPS_LO16 RELOC, offset 0x%x, name %s */\n", - rel->r_offset, sym_name); - fprintf(outfile, - " *(uint32_t *)(gen_code_ptr + 0x%x) = " - "((*(uint32_t *)(gen_code_ptr + 0x%x)) " - " & ~0xffff) " - " | (%s & 0xffff);\n", - reloc_offset, reloc_offset, relname); - break; - case R_MIPS_PC16: - fprintf(outfile, " /* R_MIPS_PC16 RELOC, offset 0x%x, name %s */\n", - rel->r_offset, sym_name); - fprintf(outfile, - " *(uint32_t *)(gen_code_ptr + 0x%x) = " - "(0x%x & ~0xffff) " - "| ((0x%x + ((%s - (*(uint32_t *)(gen_code_ptr + 0x%x))) >> 2)) " - " & 0xffff);\n", - reloc_offset, addend, addend, relname, reloc_offset); - break; - case R_MIPS_GOT16: - case R_MIPS_CALL16: - fprintf(outfile, " /* R_MIPS_GOT16 RELOC, offset 0x%x, name %s */\n", - rel->r_offset, sym_name); - fprintf(outfile, - " *(uint32_t *)(gen_code_ptr + 0x%x) = " - "((*(uint32_t *)(gen_code_ptr + 0x%x)) " - " & ~0xffff) " - " | (((%s - 0x8000) >> 16) & 0xffff);\n", - reloc_offset, reloc_offset, relname); - break; - default: - error("unsupported MIPS relocation (%d)", type); - } - } - } - } -#elif defined(HOST_ARM) - error("dyngen targets not supported on ARM"); -#elif defined(HOST_PPC64) - error("dyngen targets not supported on PPC64"); -#else -#error unsupported CPU -#endif - fprintf(outfile, " gen_code_ptr += %d;\n", copy_size); - fprintf(outfile, "}\n"); - fprintf(outfile, "break;\n\n"); - } else { - fprintf(outfile, "static inline void gen_%s(", name); - if (nb_args == 0) { - fprintf(outfile, "void"); - } else { - for(i = 0; i < nb_args; i++) { - if (i != 0) - fprintf(outfile, ", "); - fprintf(outfile, "long param%d", i + 1); - } - } - fprintf(outfile, ")\n"); - fprintf(outfile, "{\n"); - for(i = 0; i < nb_args; i++) { - fprintf(outfile, " *gen_opparam_ptr++ = param%d;\n", i + 1); - } - fprintf(outfile, " *gen_opc_ptr++ = INDEX_%s;\n", name); - fprintf(outfile, "}\n\n"); - } -} - -static int gen_file(FILE *outfile, int out_type) -{ - int i; - EXE_SYM *sym; - - if (out_type == OUT_INDEX_OP) { - for(i = 0, sym = symtab; i < nb_syms; i++, sym++) { - const char *name; - name = get_sym_name(sym); - if (strstart(name, OP_PREFIX, NULL)) { - gen_code(name, sym->st_value, sym->st_size, outfile, 2); - } - } - } else if (out_type == OUT_GEN_OP) { - /* generate gen_xxx functions */ - for(i = 0, sym = symtab; i < nb_syms; i++, sym++) { - const char *name; - name = get_sym_name(sym); - if (strstart(name, OP_PREFIX, NULL)) { -#if defined(CONFIG_FORMAT_ELF) || defined(CONFIG_FORMAT_COFF) - if (sym->st_shndx != text_shndx) - error("invalid section for opcode (0x%x)", sym->st_shndx); -#endif - gen_code(name, sym->st_value, sym->st_size, outfile, 0); - } - } - - } else { - /* generate big code generation switch */ - -#ifdef HOST_ARM - error("dyngen targets not supported on ARM"); -#endif -#ifdef HOST_IA64 - { - long addend, not_first = 0; - unsigned long sym_idx; - int index, max_index; - const char *sym_name; - EXE_RELOC *rel; - - max_index = -1; - for (i = 0, rel = relocs;i < nb_relocs; i++, rel++) { - sym_idx = ELF64_R_SYM(rel->r_info); - sym_name = (strtab + symtab[sym_idx].st_name); - if (strstart(sym_name, "__op_gen_label", NULL)) - continue; - if (ELF64_R_TYPE(rel->r_info) != R_IA64_PCREL21B) - continue; - - addend = rel->r_addend; - index = get_plt_index(sym_name, addend); - if (index <= max_index) - continue; - max_index = index; - fprintf(outfile, " extern void %s(void);\n", sym_name); - } - - fprintf(outfile, - " struct ia64_fixup *plt_fixes = NULL, " - "*ltoff_fixes = NULL;\n" - " static long plt_target[] = {\n\t"); - - max_index = -1; - for (i = 0, rel = relocs;i < nb_relocs; i++, rel++) { - sym_idx = ELF64_R_SYM(rel->r_info); - sym_name = (strtab + symtab[sym_idx].st_name); - if (strstart(sym_name, "__op_gen_label", NULL)) - continue; - if (ELF64_R_TYPE(rel->r_info) != R_IA64_PCREL21B) - continue; - - addend = rel->r_addend; - index = get_plt_index(sym_name, addend); - if (index <= max_index) - continue; - max_index = index; - - if (not_first) - fprintf(outfile, ",\n\t"); - not_first = 1; - if (addend) - fprintf(outfile, "(long) &%s + %ld", sym_name, addend); - else - fprintf(outfile, "(long) &%s", sym_name); - } - fprintf(outfile, "\n };\n" - " unsigned int plt_offset[%u] = { 0 };\n", max_index + 1); - } -#endif - - for(i = 0, sym = symtab; i < nb_syms; i++, sym++) { - const char *name; - name = get_sym_name(sym); - if (strstart(name, OP_PREFIX, NULL)) { -#if 0 - printf("%4d: %s pos=0x%08x len=%d\n", - i, name, sym->st_value, sym->st_size); -#endif -#if defined(CONFIG_FORMAT_ELF) || defined(CONFIG_FORMAT_COFF) - if (sym->st_shndx != text_shndx) - error("invalid section for opcode (0x%x)", sym->st_shndx); -#endif - gen_code(name, sym->st_value, sym->st_size, outfile, 1); - } - } - } - - return 0; -} - -static void usage(void) -{ - printf("dyngen (c) 2003 Fabrice Bellard\n" - "usage: dyngen [-o outfile] [-c] objfile\n" - "Generate a dynamic code generator from an object file\n" - "-c output enum of operations\n" - "-g output gen_op_xx() functions\n" - ); - exit(1); -} - -int main(int argc, char **argv) -{ - int c, out_type; - const char *filename, *outfilename; - FILE *outfile; - - outfilename = "out.c"; - out_type = OUT_CODE; - for(;;) { - c = getopt(argc, argv, "ho:cg"); - if (c == -1) - break; - switch(c) { - case 'h': - usage(); - break; - case 'o': - outfilename = optarg; - break; - case 'c': - out_type = OUT_INDEX_OP; - break; - case 'g': - out_type = OUT_GEN_OP; - break; - } - } - if (optind >= argc) - usage(); - filename = argv[optind]; - outfile = fopen(outfilename, "w"); - if (!outfile) - error("could not open '%s'", outfilename); - - load_object(filename); - gen_file(outfile, out_type); - fclose(outfile); - return 0; -} diff --git a/qemu/exec-all.h b/qemu/exec-all.h index 7f963b05..fd96adf0 100644 --- a/qemu/exec-all.h +++ b/qemu/exec-all.h @@ -267,20 +267,6 @@ static inline void tb_add_jump(TranslationBlock *tb, int n, TranslationBlock *tb_find_pc(unsigned long pc_ptr); -#if defined(_WIN32) -#define ASM_DATA_SECTION ".section \".data\"\n" -#define ASM_PREVIOUS_SECTION ".section .text\n" -#elif defined(__APPLE__) -#define ASM_DATA_SECTION ".data\n" -#define ASM_PREVIOUS_SECTION ".text\n" -#else -#define ASM_DATA_SECTION ".section \".data\"\n" -#define ASM_PREVIOUS_SECTION ".previous\n" -#endif - -#define ASM_OP_LABEL_NAME(n, opname) \ - ASM_NAME(__op_label) #n "." ASM_NAME(opname) - extern CPUWriteMemoryFunc *io_mem_write[IO_MEM_NB_ENTRIES][4]; extern CPUReadMemoryFunc *io_mem_read[IO_MEM_NB_ENTRIES][4]; extern void *io_mem_opaque[IO_MEM_NB_ENTRIES]; diff --git a/qemu/exec.c b/qemu/exec.c index 36ff1f0a..109cc1fd 100644 --- a/qemu/exec.c +++ b/qemu/exec.c @@ -313,14 +313,13 @@ static inline PageDesc *page_find_alloc(target_ulong index) if (!p) { /* allocate if not found */ #if defined(CONFIG_USER_ONLY) - unsigned long addr; size_t len = sizeof(PageDesc) * L2_SIZE; /* Don't use qemu_malloc because it may recurse. */ p = mmap(0, len, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANONYMOUS, -1, 0); *lp = p; - addr = h2g(p); - if (addr == (target_ulong)addr) { + if (h2g_valid(p)) { + unsigned long addr = h2g(p); page_set_flags(addr & TARGET_PAGE_MASK, TARGET_PAGE_ALIGN(addr + len), PAGE_RESERVED); @@ -2375,6 +2374,18 @@ ram_addr_t cpu_get_physical_page_desc(target_phys_addr_t addr) return p->phys_offset; } +void qemu_register_coalesced_mmio(target_phys_addr_t addr, ram_addr_t size) +{ + if (kvm_enabled()) + kvm_coalesce_mmio_region(addr, size); +} + +void qemu_unregister_coalesced_mmio(target_phys_addr_t addr, ram_addr_t size) +{ + if (kvm_enabled()) + kvm_uncoalesce_mmio_region(addr, size); +} + /* XXX: better than nothing */ ram_addr_t qemu_ram_alloc(ram_addr_t size) { diff --git a/qemu/fpu/softfloat-macros.h b/qemu/fpu/softfloat-macros.h index 2c8f18b1..0502fb89 100644 --- a/qemu/fpu/softfloat-macros.h +++ b/qemu/fpu/softfloat-macros.h @@ -717,4 +717,3 @@ INLINE flag ne128( bits64 a0, bits64 a1, bits64 b0, bits64 b1 ) return ( a0 != b0 ) || ( a1 != b1 ); } - diff --git a/qemu/fpu/softfloat-native.c b/qemu/fpu/softfloat-native.c index e58551f3..cd88113f 100644 --- a/qemu/fpu/softfloat-native.c +++ b/qemu/fpu/softfloat-native.c @@ -220,25 +220,25 @@ float32 float32_sqrt( float32 a STATUS_PARAM) int float32_compare( float32 a, float32 b STATUS_PARAM ) { if (a < b) { - return -1; + return float_relation_less; } else if (a == b) { - return 0; + return float_relation_equal; } else if (a > b) { - return 1; + return float_relation_greater; } else { - return 2; + return float_relation_unordered; } } int float32_compare_quiet( float32 a, float32 b STATUS_PARAM ) { if (isless(a, b)) { - return -1; + return float_relation_less; } else if (a == b) { - return 0; + return float_relation_equal; } else if (isgreater(a, b)) { - return 1; + return float_relation_greater; } else { - return 2; + return float_relation_unordered; } } int float32_is_signaling_nan( float32 a1) @@ -250,6 +250,15 @@ int float32_is_signaling_nan( float32 a1) return ( ( ( a>>22 ) & 0x1FF ) == 0x1FE ) && ( a & 0x003FFFFF ); } +int float32_is_nan( float32 a1 ) +{ + float32u u; + uint64_t a; + u.f = a1; + a = u.i; + return ( 0xFF800000 < ( a<<1 ) ); +} + /*---------------------------------------------------------------------------- | Software IEC/IEEE double-precision conversion routines. *----------------------------------------------------------------------------*/ @@ -382,25 +391,25 @@ float64 float64_sqrt( float64 a STATUS_PARAM) int float64_compare( float64 a, float64 b STATUS_PARAM ) { if (a < b) { - return -1; + return float_relation_less; } else if (a == b) { - return 0; + return float_relation_equal; } else if (a > b) { - return 1; + return float_relation_greater; } else { - return 2; + return float_relation_unordered; } } int float64_compare_quiet( float64 a, float64 b STATUS_PARAM ) { if (isless(a, b)) { - return -1; + return float_relation_less; } else if (a == b) { - return 0; + return float_relation_equal; } else if (isgreater(a, b)) { - return 1; + return float_relation_greater; } else { - return 2; + return float_relation_unordered; } } int float64_is_signaling_nan( float64 a1) @@ -474,25 +483,25 @@ floatx80 floatx80_sqrt( floatx80 a STATUS_PARAM) int floatx80_compare( floatx80 a, floatx80 b STATUS_PARAM ) { if (a < b) { - return -1; + return float_relation_less; } else if (a == b) { - return 0; + return float_relation_equal; } else if (a > b) { - return 1; + return float_relation_greater; } else { - return 2; + return float_relation_unordered; } } int floatx80_compare_quiet( floatx80 a, floatx80 b STATUS_PARAM ) { if (isless(a, b)) { - return -1; + return float_relation_less; } else if (a == b) { - return 0; + return float_relation_equal; } else if (isgreater(a, b)) { - return 1; + return float_relation_greater; } else { - return 2; + return float_relation_unordered; } } int floatx80_is_signaling_nan( floatx80 a1) diff --git a/qemu/fpu/softfloat-native.h b/qemu/fpu/softfloat-native.h index b51c0825..817a2a81 100644 --- a/qemu/fpu/softfloat-native.h +++ b/qemu/fpu/softfloat-native.h @@ -246,6 +246,7 @@ INLINE int float32_unordered( float32 a, float32 b STATUS_PARAM) int float32_compare( float32, float32 STATUS_PARAM ); int float32_compare_quiet( float32, float32 STATUS_PARAM ); int float32_is_signaling_nan( float32 ); +int float32_is_nan( float32 ); INLINE float32 float32_abs(float32 a) { diff --git a/qemu/gdbstub.c b/qemu/gdbstub.c index b02571a9..f8dfa3d1 100644 --- a/qemu/gdbstub.c +++ b/qemu/gdbstub.c @@ -991,6 +991,56 @@ static int cpu_gdb_write_register(CPUState *env, uint8_t *mem_buf, int n) return 4; } +#elif defined (TARGET_ALPHA) + +#define NUM_CORE_REGS 65 + +static int cpu_gdb_read_register(CPUState *env, uint8_t *mem_buf, int n) +{ + if (n < 31) { + GET_REGL(env->ir[n]); + } + else if (n == 31) { + GET_REGL(0); + } + else if (n<63) { + uint64_t val; + + val=*((uint64_t *)&env->fir[n-32]); + GET_REGL(val); + } + else if (n==63) { + GET_REGL(env->fpcr); + } + else if (n==64) { + GET_REGL(env->pc); + } + else { + GET_REGL(0); + } + + return 0; +} + +static int cpu_gdb_write_register(CPUState *env, uint8_t *mem_buf, int n) +{ + target_ulong tmp; + tmp = ldtul_p(mem_buf); + + if (n < 31) { + env->ir[n] = tmp; + } + + if (n > 31 && n < 63) { + env->fir[n - 32] = ldfl_p(mem_buf); + } + + if (n == 64 ) { + env->pc=tmp; + } + + return 8; +} #else #define NUM_CORE_REGS 0 @@ -1031,7 +1081,7 @@ static int memtox(char *buf, const char *mem, int len) return p - buf; } -const char *get_feature_xml(const char *p, const char **newp) +static const char *get_feature_xml(const char *p, const char **newp) { extern const char *const xml_builtin[][2]; size_t len; @@ -1280,6 +1330,8 @@ static int gdb_handle_packet(GDBState *s, const char *line_buf) s->c_cpu->active_tc.PC = addr; #elif defined (TARGET_CRIS) s->c_cpu->pc = addr; +#elif defined (TARGET_ALPHA) + s->c_cpu->pc = addr; #endif } gdb_continue(s); @@ -1318,6 +1370,8 @@ static int gdb_handle_packet(GDBState *s, const char *line_buf) s->c_cpu->active_tc.PC = addr; #elif defined (TARGET_CRIS) s->c_cpu->pc = addr; +#elif defined (TARGET_ALPHA) + s->c_cpu->pc = addr; #endif } cpu_single_step(s->c_cpu, sstep_flags); @@ -1609,8 +1663,6 @@ static int gdb_handle_packet(GDBState *s, const char *line_buf) return RS_IDLE; } -extern void tb_flush(CPUState *env); - void gdb_set_stop_cpu(CPUState *env) { gdbserver_state->c_cpu = env; diff --git a/qemu/gen-icount.h b/qemu/gen-icount.h index d53159c0..d4524d66 100644 --- a/qemu/gen-icount.h +++ b/qemu/gen-icount.h @@ -53,4 +53,3 @@ static inline void gen_io_end(void) tcg_gen_st_i32(tmp, cpu_env, offsetof(CPUState, can_do_io)); tcg_temp_free_i32(tmp); } - diff --git a/qemu/hostregs_helper.h b/qemu/hostregs_helper.h index 4fdf8ad9..67e45e74 100644 --- a/qemu/hostregs_helper.h +++ b/qemu/hostregs_helper.h @@ -18,9 +18,9 @@ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ -/* The GCC global register vairable extension is used to reserve some - host registers for use by dyngen. However only the core parts of the - translation engine are compiled with these settings. We must manually +/* The GCC global register variable extension is used to reserve some + host registers for use by generated code. However only the core parts of + the translation engine are compiled with these settings. We must manually save/restore these registers when called from regular code. It is not sufficient to save/restore T0 et. al. as these may be declared with a datatype smaller than the actual register. */ diff --git a/qemu/hw/apb_pci.c b/qemu/hw/apb_pci.c index b56bb073..d8478885 100644 --- a/qemu/hw/apb_pci.c +++ b/qemu/hw/apb_pci.c @@ -261,5 +261,3 @@ PCIBus *pci_apb_init(target_phys_addr_t special_base, "Advanced PCI Bus secondary bridge 2"); return secondary; } - - diff --git a/qemu/hw/arm-misc.h b/qemu/hw/arm-misc.h index a1472542..a6991975 100644 --- a/qemu/hw/arm-misc.h +++ b/qemu/hw/arm-misc.h @@ -44,4 +44,3 @@ qemu_irq *armv7m_nvic_init(CPUState *env); void stellaris_enet_init(NICInfo *nd, uint32_t base, qemu_irq irq); #endif /* !ARM_MISC_H */ - diff --git a/qemu/hw/arm_sysctl.c b/qemu/hw/arm_sysctl.c index ab22e840..ca668ca6 100644 --- a/qemu/hw/arm_sysctl.c +++ b/qemu/hw/arm_sysctl.c @@ -205,4 +205,3 @@ void arm_sysctl_init(uint32_t base, uint32_t sys_id) cpu_register_physical_memory(base, 0x00001000, iomemtype); /* ??? Save/restore. */ } - diff --git a/qemu/hw/arm_timer.c b/qemu/hw/arm_timer.c index 3ffe9965..c93f333d 100644 --- a/qemu/hw/arm_timer.c +++ b/qemu/hw/arm_timer.c @@ -340,4 +340,3 @@ void icp_pit_init(uint32_t base, qemu_irq *pic, int irq) /* This device has no state to save/restore. The component timers will save themselves. */ } - diff --git a/qemu/hw/armv7m.c b/qemu/hw/armv7m.c index 096193d8..71bbd957 100644 --- a/qemu/hw/armv7m.c +++ b/qemu/hw/armv7m.c @@ -207,4 +207,3 @@ qemu_irq *armv7m_init(int flash_size, int sram_size, return pic; } - diff --git a/qemu/hw/baum.c b/qemu/hw/baum.c index f47456a8..925ad2ad 100644 --- a/qemu/hw/baum.c +++ b/qemu/hw/baum.c @@ -25,6 +25,7 @@ #include "qemu-char.h" #include "qemu-timer.h" #include "usb.h" +#include "baum.h" #include <assert.h> #include <brlapi.h> #include <brlapi_constants.h> diff --git a/qemu/hw/boards.h b/qemu/hw/boards.h index c4181016..d2b26c69 100644 --- a/qemu/hw/boards.h +++ b/qemu/hw/boards.h @@ -89,6 +89,10 @@ extern QEMUMachine spitzpda_machine; extern QEMUMachine borzoipda_machine; extern QEMUMachine terrierpda_machine; +/* omap_sx1.c */ +extern QEMUMachine sx1_machine_v1; +extern QEMUMachine sx1_machine_v2; + /* palm.c */ extern QEMUMachine palmte_machine; diff --git a/qemu/hw/cdrom.c b/qemu/hw/cdrom.c index 2aa4d3b2..87427a5a 100644 --- a/qemu/hw/cdrom.c +++ b/qemu/hw/cdrom.c @@ -153,5 +153,3 @@ int cdrom_read_toc_raw(int nb_sectors, uint8_t *buf, int msf, int session_num) cpu_to_be16wu((uint16_t *)buf, len - 2); return len; } - - diff --git a/qemu/hw/cirrus_vga.c b/qemu/hw/cirrus_vga.c index ff2b59c1..8d578906 100644 --- a/qemu/hw/cirrus_vga.c +++ b/qemu/hw/cirrus_vga.c @@ -3235,8 +3235,7 @@ static void cirrus_init_common(CirrusVGAState * s, int device_id, int is_pci) cirrus_vga_mem_write, s); cpu_register_physical_memory(isa_mem_base + 0x000a0000, 0x20000, s->vga_io_memory); - if (kvm_enabled()) - qemu_kvm_register_coalesced_mmio(isa_mem_base + 0x000a0000, 0x20000); + qemu_register_coalesced_mmio(isa_mem_base + 0x000a0000, 0x20000); s->sr[0x06] = 0x0f; if (device_id == CIRRUS_ID_CLGD5446) { diff --git a/qemu/hw/e1000.c b/qemu/hw/e1000.c index ba8f54d8..aed3f9a8 100644 --- a/qemu/hw/e1000.c +++ b/qemu/hw/e1000.c @@ -1002,22 +1002,22 @@ e1000_mmio_map(PCIDevice *pci_dev, int region_num, uint32_t addr, uint32_t size, int type) { E1000State *d = (E1000State *)pci_dev; + int i; + const uint32_t excluded_regs[] = { + E1000_MDIC, E1000_ICR, E1000_ICS, E1000_IMS, + E1000_IMC, E1000_TCTL, E1000_TDT, PNPMMIO_SIZE + }; + DBGOUT(MMIO, "e1000_mmio_map addr=0x%08x 0x%08x\n", addr, size); cpu_register_physical_memory(addr, PNPMMIO_SIZE, d->mmio_index); + qemu_register_coalesced_mmio(addr, excluded_regs[0]); - if (kvm_enabled()) { - int i; - uint32_t excluded_regs[] = { - E1000_MDIC, E1000_ICR, E1000_ICS, E1000_IMS, - E1000_IMC, E1000_TCTL, E1000_TDT, PNPMMIO_SIZE - }; - qemu_kvm_register_coalesced_mmio(addr, excluded_regs[0]); - for (i = 0; excluded_regs[i] != PNPMMIO_SIZE; i++) - qemu_kvm_register_coalesced_mmio(addr + excluded_regs[i] + 4, - excluded_regs[i + 1] - excluded_regs[i] - 4); - } + for (i = 0; excluded_regs[i] != PNPMMIO_SIZE; i++) + qemu_register_coalesced_mmio(addr + excluded_regs[i] + 4, + excluded_regs[i + 1] - + excluded_regs[i] - 4); } static int diff --git a/qemu/hw/fw_cfg.c b/qemu/hw/fw_cfg.c index 4e686702..4333ed9f 100644 --- a/qemu/hw/fw_cfg.c +++ b/qemu/hw/fw_cfg.c @@ -240,10 +240,12 @@ int fw_cfg_add_callback(void *opaque, uint16_t key, FWCfgCallback callback, FWCfgState *s = opaque; int arch = !!(key & FW_CFG_ARCH_LOCAL); + if (!(key & FW_CFG_WRITE_CHANNEL)) + return 0; + key &= FW_CFG_ENTRY_MASK; - if (key >= FW_CFG_MAX_ENTRY || !(key & FW_CFG_WRITE_CHANNEL) - || len > 65535) + if (key >= FW_CFG_MAX_ENTRY || len > 65535) return 0; s->entries[arch][key].data = data; diff --git a/qemu/hw/g364fb.c b/qemu/hw/g364fb.c index 64c29889..5360bce6 100644 --- a/qemu/hw/g364fb.c +++ b/qemu/hw/g364fb.c @@ -20,6 +20,7 @@ */ #include "hw.h" +#include "mips.h" #include "console.h" #include "pixel_ops.h" diff --git a/qemu/hw/grackle_pci.c b/qemu/hw/grackle_pci.c index 91d42610..c6aee948 100644 --- a/qemu/hw/grackle_pci.c +++ b/qemu/hw/grackle_pci.c @@ -146,4 +146,3 @@ PCIBus *pci_grackle_init(uint32_t base, qemu_irq *pic) #endif return s->bus; } - diff --git a/qemu/hw/gus.c b/qemu/hw/gus.c index fb129cd4..860a47c3 100644 --- a/qemu/hw/gus.c +++ b/qemu/hw/gus.c @@ -42,9 +42,9 @@ #endif #define IO_READ_PROTO(name) \ - uint32_t name (void *opaque, uint32_t nport) + static uint32_t name (void *opaque, uint32_t nport) #define IO_WRITE_PROTO(name) \ - void name (void *opaque, uint32_t nport, uint32_t val) + static void name (void *opaque, uint32_t nport, uint32_t val) static struct { int port; @@ -195,7 +195,7 @@ void GUS_dmarequest (GUSEmuState *der) DMA_hold_DREQ (der->gusdma); } -int GUS_read_DMA (void *opaque, int nchan, int dma_pos, int dma_len) +static int GUS_read_DMA (void *opaque, int nchan, int dma_pos, int dma_len) { GUSState *s = opaque; char tmpbuf[4096]; diff --git a/qemu/hw/ide.c b/qemu/hw/ide.c index 315576bb..7a7dedcb 100644 --- a/qemu/hw/ide.c +++ b/qemu/hw/ide.c @@ -32,6 +32,7 @@ #include "qemu-timer.h" #include "sysemu.h" #include "ppc_mac.h" +#include "sh.h" /* debug IDE devices */ //#define DEBUG_IDE @@ -2324,6 +2325,13 @@ static void ide_ioport_write(void *opaque, uint32_t addr, uint32_t val) s->status = READY_STAT; ide_set_irq(s); break; + case WIN_SEEK: + if(s->is_cdrom) + goto abort_cmd; + /* XXX: Check that seek is within bounds */ + s->status = READY_STAT | SEEK_STAT; + ide_set_irq(s); + break; /* ATAPI commands */ case WIN_PIDENTIFY: if (s->is_cdrom) { @@ -3420,6 +3428,98 @@ int pmac_ide_init (BlockDriverState **hd_table, qemu_irq irq) } /***********************************************************/ +/* MMIO based ide port + * This emulates IDE device connected directly to the CPU bus without + * dedicated ide controller, which is often seen on embedded boards. + */ + +typedef struct { + void *dev; + int shift; +} MMIOState; + +static uint32_t mmio_ide_read (void *opaque, target_phys_addr_t addr) +{ + MMIOState *s = (MMIOState*)opaque; + IDEState *ide = (IDEState*)s->dev; + addr >>= s->shift; + if (addr & 7) + return ide_ioport_read(ide, addr); + else + return ide_data_readw(ide, 0); +} + +static void mmio_ide_write (void *opaque, target_phys_addr_t addr, + uint32_t val) +{ + MMIOState *s = (MMIOState*)opaque; + IDEState *ide = (IDEState*)s->dev; + addr >>= s->shift; + if (addr & 7) + ide_ioport_write(ide, addr, val); + else + ide_data_writew(ide, 0, val); +} + +static CPUReadMemoryFunc *mmio_ide_reads[] = { + mmio_ide_read, + mmio_ide_read, + mmio_ide_read, +}; + +static CPUWriteMemoryFunc *mmio_ide_writes[] = { + mmio_ide_write, + mmio_ide_write, + mmio_ide_write, +}; + +static uint32_t mmio_ide_status_read (void *opaque, target_phys_addr_t addr) +{ + MMIOState *s= (MMIOState*)opaque; + IDEState *ide = (IDEState*)s->dev; + return ide_status_read(ide, 0); +} + +static void mmio_ide_cmd_write (void *opaque, target_phys_addr_t addr, + uint32_t val) +{ + MMIOState *s = (MMIOState*)opaque; + IDEState *ide = (IDEState*)s->dev; + ide_cmd_write(ide, 0, val); +} + +static CPUReadMemoryFunc *mmio_ide_status[] = { + mmio_ide_status_read, + mmio_ide_status_read, + mmio_ide_status_read, +}; + +static CPUWriteMemoryFunc *mmio_ide_cmd[] = { + mmio_ide_cmd_write, + mmio_ide_cmd_write, + mmio_ide_cmd_write, +}; + +void mmio_ide_init (target_phys_addr_t membase, target_phys_addr_t membase2, + qemu_irq irq, int shift, + BlockDriverState *hd0, BlockDriverState *hd1) +{ + MMIOState *s = qemu_mallocz(sizeof(MMIOState)); + IDEState *ide = qemu_mallocz(sizeof(IDEState) * 2); + int mem1, mem2; + + ide_init2(ide, hd0, hd1, irq); + + s->dev = ide; + s->shift = shift; + + mem1 = cpu_register_io_memory(0, mmio_ide_reads, mmio_ide_writes, s); + mem2 = cpu_register_io_memory(0, mmio_ide_status, mmio_ide_cmd, s); + cpu_register_physical_memory(membase, 16 << shift, mem1); + cpu_register_physical_memory(membase2, 2 << shift, mem2); +} + +/***********************************************************/ /* CF-ATA Microdrive */ #define METADATA_SIZE 0x20 diff --git a/qemu/hw/lsi53c895a.c b/qemu/hw/lsi53c895a.c index cfd520fd..c65ff904 100644 --- a/qemu/hw/lsi53c895a.c +++ b/qemu/hw/lsi53c895a.c @@ -252,7 +252,7 @@ typedef struct { uint32_t sfs; uint32_t drs; uint32_t sbms; - uint32_t dmbs; + uint32_t dbms; uint32_t dnad64; uint32_t pmjad1; uint32_t pmjad2; @@ -321,7 +321,7 @@ static void lsi_soft_reset(LSIState *s) s->sfs = 0; s->drs = 0; s->sbms = 0; - s->dmbs = 0; + s->dbms = 0; s->dnad64 = 0; s->pmjad1 = 0; s->pmjad2 = 0; @@ -339,6 +339,20 @@ static int lsi_dma_40bit(LSIState *s) return 0; } +static int lsi_dma_ti64bit(LSIState *s) +{ + if ((s->ccntl1 & LSI_CCNTL1_EN64TIBMV) == LSI_CCNTL1_EN64TIBMV) + return 1; + return 0; +} + +static int lsi_dma_64bit(LSIState *s) +{ + if ((s->ccntl1 & LSI_CCNTL1_EN64DBMV) == LSI_CCNTL1_EN64DBMV) + return 1; + return 0; +} + static uint8_t lsi_reg_readb(LSIState *s, int offset); static void lsi_reg_writeb(LSIState *s, int offset, uint8_t val); static void lsi_execute_script(LSIState *s); @@ -478,8 +492,11 @@ static void lsi_do_dma(LSIState *s, int out) count = s->current_dma_len; addr = s->dnad; - if (lsi_dma_40bit(s)) + /* both 40 and Table Indirect 64-bit DMAs store upper bits in dnad64 */ + if (lsi_dma_40bit(s) || lsi_dma_ti64bit(s)) addr |= ((uint64_t)s->dnad64 << 32); + else if (s->dbms) + addr |= ((uint64_t)s->dbms << 32); else if (s->sbms) addr |= ((uint64_t)s->sbms << 32); @@ -889,6 +906,8 @@ again: } s->dbc = insn & 0xffffff; s->rbc = s->dbc; + /* ??? Set ESA. */ + s->ia = s->dsp - 8; if (insn & (1 << 29)) { /* Indirect addressing. */ addr = read_dword(s, addr); @@ -896,6 +915,8 @@ again: uint32_t buf[2]; int32_t offset; /* Table indirect addressing. */ + + /* 32-bit Table indirect */ offset = sxt24(addr); cpu_physical_memory_read(s->dsa + offset, (uint8_t *)buf, 8); /* byte count is stored in bits 0:23 only */ @@ -907,6 +928,44 @@ again: * table, bits [31:24] */ if (lsi_dma_40bit(s)) addr_high = cpu_to_le32(buf[0]) >> 24; + else if (lsi_dma_ti64bit(s)) { + int selector = (cpu_to_le32(buf[0]) >> 24) & 0x1f; + switch (selector) { + case 0 ... 0x0f: + /* offset index into scratch registers since + * TI64 mode can use registers C to R */ + addr_high = s->scratch[2 + selector]; + break; + case 0x10: + addr_high = s->mmrs; + break; + case 0x11: + addr_high = s->mmws; + break; + case 0x12: + addr_high = s->sfs; + break; + case 0x13: + addr_high = s->drs; + break; + case 0x14: + addr_high = s->sbms; + break; + case 0x15: + addr_high = s->dbms; + break; + default: + BADF("Illegal selector specified (0x%x > 0x15)" + " for 64-bit DMA block move", selector); + break; + } + } + } else if (lsi_dma_64bit(s)) { + /* fetch a 3rd dword if 64-bit direct move is enabled and + only if we're not doing table indirect or indirect addressing */ + s->dbms = read_dword(s, s->dsp); + s->dsp += 4; + s->ia = s->dsp - 12; } if ((s->sstat1 & PHASE_MASK) != ((insn >> 24) & 7)) { DPRINTF("Wrong phase got %d expected %d\n", @@ -916,8 +975,6 @@ again: } s->dnad = addr; s->dnad64 = addr_high; - /* ??? Set ESA. */ - s->ia = s->dsp - 8; switch (s->sstat1 & 0x7) { case PHASE_DO: s->waiting = 2; @@ -1402,7 +1459,7 @@ static uint8_t lsi_reg_readb(LSIState *s, int offset) CASE_GET_REG32(sfs, 0xa8) CASE_GET_REG32(drs, 0xac) CASE_GET_REG32(sbms, 0xb0) - CASE_GET_REG32(dmbs, 0xb4) + CASE_GET_REG32(dbms, 0xb4) CASE_GET_REG32(dnad64, 0xb8) CASE_GET_REG32(pmjad1, 0xc0) CASE_GET_REG32(pmjad2, 0xc4) @@ -1619,7 +1676,7 @@ static void lsi_reg_writeb(LSIState *s, int offset, uint8_t val) CASE_SET_REG32(sfs, 0xa8) CASE_SET_REG32(drs, 0xac) CASE_SET_REG32(sbms, 0xb0) - CASE_SET_REG32(dmbs, 0xb4) + CASE_SET_REG32(dbms, 0xb4) CASE_SET_REG32(dnad64, 0xb8) CASE_SET_REG32(pmjad1, 0xc0) CASE_SET_REG32(pmjad2, 0xc4) @@ -1963,4 +2020,3 @@ void *lsi_scsi_init(PCIBus *bus, int devfn) return s; } - diff --git a/qemu/hw/mac_dbdma.c b/qemu/hw/mac_dbdma.c index 74003e60..401384c4 100644 --- a/qemu/hw/mac_dbdma.c +++ b/qemu/hw/mac_dbdma.c @@ -76,4 +76,3 @@ void dbdma_init (int *dbdma_mem_index) { *dbdma_mem_index = cpu_register_io_memory(0, dbdma_read, dbdma_write, NULL); } - diff --git a/qemu/hw/mcf5206.c b/qemu/hw/mcf5206.c index 449ca12f..ee41a611 100644 --- a/qemu/hw/mcf5206.c +++ b/qemu/hw/mcf5206.c @@ -540,4 +540,3 @@ qemu_irq *mcf5206_init(uint32_t base, CPUState *env) m5206_mbar_reset(s); return pic; } - diff --git a/qemu/hw/mips_jazz.c b/qemu/hw/mips_jazz.c index b332a459..0dcc332c 100644 --- a/qemu/hw/mips_jazz.c +++ b/qemu/hw/mips_jazz.c @@ -102,12 +102,12 @@ static void audio_init(qemu_irq *pic) } #endif -void espdma_memory_read(void *opaque, uint8_t *buf, int len) +static void espdma_memory_read(void *opaque, uint8_t *buf, int len) { printf("espdma_memory_read(buf %p, len %d) not implemented\n", buf, len); } -void espdma_memory_write(void *opaque, uint8_t *buf, int len) +static void espdma_memory_write(void *opaque, uint8_t *buf, int len) { printf("espdma_memory_write(buf %p, len %d) not implemented\n", buf, len); } @@ -229,7 +229,7 @@ void mips_jazz_init (ram_addr_t ram_size, int vga_ram_size, cpu_register_physical_memory(0x80004000, 0x00001000, s_rtc); /* Keyboard (i8042) */ - i8042_mm_init(rc4030[6], rc4030[7], 0x80005000, 0); + i8042_mm_init(rc4030[6], rc4030[7], 0x80005000, 0x1000, 0x1); /* Serial ports */ if (serial_hds[0]) diff --git a/qemu/hw/omap1.c b/qemu/hw/omap1.c index 9aa28cab..89b62787 100644 --- a/qemu/hw/omap1.c +++ b/qemu/hw/omap1.c @@ -1966,6 +1966,7 @@ struct omap_uart_s { uint8_t cfps; uint8_t mdr[2]; uint8_t scr; + uint8_t clksel; }; void omap_uart_reset(struct omap_uart_s *s) @@ -1974,6 +1975,7 @@ void omap_uart_reset(struct omap_uart_s *s) s->syscontrol = 0; s->wkup = 0x3f; s->cfps = 0x69; + s->clksel = 0; } struct omap_uart_s *omap_uart_init(target_phys_addr_t base, @@ -2006,17 +2008,19 @@ static uint32_t omap_uart_read(void *opaque, target_phys_addr_t addr) return s->scr; case 0x44: /* SSR */ return 0x0; - case 0x48: /* EBLR */ + case 0x48: /* EBLR (OMAP2) */ return s->eblr; + case 0x4C: /* OSC_12M_SEL (OMAP1) */ + return s->clksel; case 0x50: /* MVR */ return 0x30; - case 0x54: /* SYSC */ + case 0x54: /* SYSC (OMAP2) */ return s->syscontrol; - case 0x58: /* SYSS */ + case 0x58: /* SYSS (OMAP2) */ return 1; - case 0x5c: /* WER */ + case 0x5c: /* WER (OMAP2) */ return s->wkup; - case 0x60: /* CFPS */ + case 0x60: /* CFPS (OMAP2) */ return s->cfps; } @@ -2040,23 +2044,26 @@ static void omap_uart_write(void *opaque, target_phys_addr_t addr, case 0x40: /* SCR */ s->scr = value & 0xff; break; - case 0x48: /* EBLR */ + case 0x48: /* EBLR (OMAP2) */ s->eblr = value & 0xff; break; + case 0x4C: /* OSC_12M_SEL (OMAP1) */ + s->clksel = value & 1; + break; case 0x44: /* SSR */ case 0x50: /* MVR */ - case 0x58: /* SYSS */ + case 0x58: /* SYSS (OMAP2) */ OMAP_RO_REG(addr); break; - case 0x54: /* SYSC */ + case 0x54: /* SYSC (OMAP2) */ s->syscontrol = value & 0x1d; if (value & 2) omap_uart_reset(s); break; - case 0x5c: /* WER */ + case 0x5c: /* WER (OMAP2) */ s->wkup = value & 0x7f; break; - case 0x60: /* CFPS */ + case 0x60: /* CFPS (OMAP2) */ s->cfps = value & 0xff; break; default: @@ -4726,7 +4733,7 @@ struct omap_mpu_state_s *omap310_mpu_init(unsigned long sdram_size, omap_findclk(s, "uart2_ck"), s->drq[OMAP_DMA_UART2_TX], s->drq[OMAP_DMA_UART2_RX], serial_hds[0] ? serial_hds[1] : 0); - s->uart[2] = omap_uart_init(0xe1019800, s->irq[0][OMAP_INT_UART3], + s->uart[2] = omap_uart_init(0xfffb9800, s->irq[0][OMAP_INT_UART3], omap_findclk(s, "uart3_ck"), omap_findclk(s, "uart3_ck"), s->drq[OMAP_DMA_UART3_TX], s->drq[OMAP_DMA_UART3_RX], diff --git a/qemu/hw/omap_sx1.c b/qemu/hw/omap_sx1.c new file mode 100644 index 00000000..df2b52ea --- /dev/null +++ b/qemu/hw/omap_sx1.c @@ -0,0 +1,238 @@ +/* omap_sx1.c Support for the Siemens SX1 smartphone emulation. + * + * Copyright (C) 2008 + * Jean-Christophe PLAGNIOL-VILLARD <plagnioj@jcrosoft.com> + * Copyright (C) 2007 Vladimir Ananiev <vovan888@gmail.com> + * + * based on PalmOne's (TM) PDAs support (palm.c) + */ + +/* + * PalmOne's (TM) PDAs. + * + * Copyright (C) 2006-2007 Andrzej Zaborowski <balrog@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 "hw.h" +#include "sysemu.h" +#include "console.h" +#include "omap.h" +#include "boards.h" +#include "arm-misc.h" +#include "flash.h" + +/*****************************************************************************/ +/* Siemens SX1 Cellphone V1 */ +/* - ARM OMAP310 processor + * - SRAM 192 kB + * - SDRAM 32 MB at 0x10000000 + * - Boot flash 16 MB at 0x00000000 + * - Application flash 8 MB at 0x04000000 + * - 3 serial ports + * - 1 SecureDigital + * - 1 LCD display + * - 1 RTC + */ + +/*****************************************************************************/ +/* Siemens SX1 Cellphone V2 */ +/* - ARM OMAP310 processor + * - SRAM 192 kB + * - SDRAM 32 MB at 0x10000000 + * - Boot flash 32 MB at 0x00000000 + * - 3 serial ports + * - 1 SecureDigital + * - 1 LCD display + * - 1 RTC + */ + +static uint32_t static_readb(void *opaque, target_phys_addr_t offset) +{ + uint32_t *val = (uint32_t *) opaque; + + return *val >> ((offset & 3) << 3); +} + +static uint32_t static_readh(void *opaque, target_phys_addr_t offset) +{ + uint32_t *val = (uint32_t *) opaque; + + return *val >> ((offset & 1) << 3); +} + +static uint32_t static_readw(void *opaque, target_phys_addr_t offset) +{ + uint32_t *val = (uint32_t *) opaque; + + return *val >> ((offset & 0) << 3); +} + +static void static_write(void *opaque, target_phys_addr_t offset, + uint32_t value) +{ +#ifdef SPY + printf("%s: value %08lx written at " PA_FMT "\n", + __FUNCTION__, value, offset); +#endif +} + +static CPUReadMemoryFunc *static_readfn[] = { + static_readb, + static_readh, + static_readw, +}; + +static CPUWriteMemoryFunc *static_writefn[] = { + static_write, + static_write, + static_write, +}; + +#define sdram_size 0x02000000 +#define sector_size (128 * 1024) +#define flash0_size (16 * 1024 * 1024) +#define flash1_size ( 8 * 1024 * 1024) +#define flash2_size (32 * 1024 * 1024) +#define total_ram_v1 (sdram_size + flash0_size + flash1_size + OMAP15XX_SRAM_SIZE) +#define total_ram_v2 (sdram_size + flash2_size + OMAP15XX_SRAM_SIZE) + +static struct arm_boot_info sx1_binfo = { + .loader_start = OMAP_EMIFF_BASE, + .ram_size = sdram_size, + .board_id = 0x265, +}; + +static void sx1_init(ram_addr_t ram_size, int vga_ram_size, + const char *boot_device, DisplayState *ds, + const char *kernel_filename, const char *kernel_cmdline, + const char *initrd_filename, const char *cpu_model, + const int version) +{ + struct omap_mpu_state_s *cpu; + int io; + static uint32_t cs0val = 0x00213090; + static uint32_t cs1val = 0x00215070; + static uint32_t cs2val = 0x00001139; + static uint32_t cs3val = 0x00001139; + ram_addr_t phys_flash; + int index; + int fl_idx; + uint32_t flash_size = flash0_size; + + if (version == 2) { + flash_size = flash2_size; + } + + cpu = omap310_mpu_init(sx1_binfo.ram_size, ds, cpu_model); + + /* External Flash (EMIFS) */ + cpu_register_physical_memory(OMAP_CS0_BASE, flash_size, + (phys_flash = qemu_ram_alloc(flash_size)) | IO_MEM_ROM); + + io = cpu_register_io_memory(0, static_readfn, static_writefn, &cs0val); + cpu_register_physical_memory(OMAP_CS0_BASE + flash_size, + OMAP_CS0_SIZE - flash_size, io); + io = cpu_register_io_memory(0, static_readfn, static_writefn, &cs2val); + cpu_register_physical_memory(OMAP_CS2_BASE, OMAP_CS2_SIZE, io); + io = cpu_register_io_memory(0, static_readfn, static_writefn, &cs3val); + cpu_register_physical_memory(OMAP_CS3_BASE, OMAP_CS3_SIZE, io); + + fl_idx = 0; + + if ((index = drive_get_index(IF_PFLASH, 0, fl_idx)) > -1) { + if (!pflash_cfi01_register(OMAP_CS0_BASE, qemu_ram_alloc(flash_size), + drives_table[index].bdrv, sector_size, flash_size / sector_size, + 4, 0, 0, 0, 0)) { + fprintf(stderr, "qemu: Error registering flash memory %d.\n", + fl_idx); + } + fl_idx++; + } + + if ((version == 1) && + (index = drive_get_index(IF_PFLASH, 0, fl_idx)) > -1) { + cpu_register_physical_memory(OMAP_CS1_BASE, flash1_size, + (phys_flash = qemu_ram_alloc(flash1_size)) | + IO_MEM_ROM); + io = cpu_register_io_memory(0, static_readfn, static_writefn, &cs1val); + cpu_register_physical_memory(OMAP_CS1_BASE + flash1_size, + OMAP_CS1_SIZE - flash1_size, io); + + if (!pflash_cfi01_register(OMAP_CS1_BASE, qemu_ram_alloc(flash1_size), + drives_table[index].bdrv, sector_size, flash1_size / sector_size, + 4, 0, 0, 0, 0)) { + fprintf(stderr, "qemu: Error registering flash memory %d.\n", + fl_idx); + } + fl_idx++; + } else { + io = cpu_register_io_memory(0, static_readfn, static_writefn, &cs1val); + cpu_register_physical_memory(OMAP_CS1_BASE, OMAP_CS1_SIZE, io); + } + + if (!kernel_filename && !fl_idx) { + fprintf(stderr, "Kernel or Flash image must be specified\n"); + exit(1); + } + + /* Load the kernel. */ + if (kernel_filename) { + /* Start at bootloader. */ + cpu->env->regs[15] = sx1_binfo.loader_start; + + sx1_binfo.kernel_filename = kernel_filename; + sx1_binfo.kernel_cmdline = kernel_cmdline; + sx1_binfo.initrd_filename = initrd_filename; + arm_load_kernel(cpu->env, &sx1_binfo); + } else { + cpu->env->regs[15] = 0x00000000; + } + + dpy_resize(ds, 640, 480); +} + +static void sx1_init_v1(ram_addr_t ram_size, int vga_ram_size, + const char *boot_device, DisplayState *ds, + const char *kernel_filename, const char *kernel_cmdline, + const char *initrd_filename, const char *cpu_model) +{ + sx1_init(ram_size, vga_ram_size, boot_device, ds, kernel_filename, + kernel_cmdline, initrd_filename, cpu_model, 1); +} + +static void sx1_init_v2(ram_addr_t ram_size, int vga_ram_size, + const char *boot_device, DisplayState *ds, + const char *kernel_filename, const char *kernel_cmdline, + const char *initrd_filename, const char *cpu_model) +{ + sx1_init(ram_size, vga_ram_size, boot_device, ds, kernel_filename, + kernel_cmdline, initrd_filename, cpu_model, 2); +} + +QEMUMachine sx1_machine_v2 = { + .name = "sx1", + .desc = "Siemens SX1 (OMAP310) V2", + .init = sx1_init_v2, + .ram_require = total_ram_v2 | RAMSIZE_FIXED, +}; + +QEMUMachine sx1_machine_v1 = { + .name = "sx1-v1", + .desc = "Siemens SX1 (OMAP310) V1", + .init = sx1_init_v1, + .ram_require = total_ram_v1 | RAMSIZE_FIXED, +}; diff --git a/qemu/hw/parallel.c b/qemu/hw/parallel.c index 025067af..c734bdb3 100644 --- a/qemu/hw/parallel.c +++ b/qemu/hw/parallel.c @@ -418,8 +418,10 @@ static uint32_t parallel_ioport_ecp_read(void *opaque, uint32_t addr) return ret; } -static void parallel_reset(ParallelState *s, qemu_irq irq, CharDriverState *chr) +static void parallel_reset(void *opaque) { + ParallelState *s = opaque; + s->datar = ~0; s->dataw = ~0; s->status = PARA_STS_BUSY; @@ -430,9 +432,7 @@ static void parallel_reset(ParallelState *s, qemu_irq irq, CharDriverState *chr) s->control = PARA_CTR_SELECT; s->control |= PARA_CTR_INIT; s->control |= 0xc0; - s->irq = irq; s->irq_pending = 0; - s->chr = chr; s->hw_driver = 0; s->epp_timeout = 0; s->last_read_offset = ~0U; @@ -447,7 +447,10 @@ ParallelState *parallel_init(int base, qemu_irq irq, CharDriverState *chr) s = qemu_mallocz(sizeof(ParallelState)); if (!s) return NULL; - parallel_reset(s, irq, chr); + s->irq = irq; + s->chr = chr; + parallel_reset(s); + qemu_register_reset(parallel_reset, s); if (qemu_chr_ioctl(chr, CHR_IOCTL_PP_READ_STATUS, &dummy) == 0) { s->hw_driver = 1; @@ -538,8 +541,11 @@ ParallelState *parallel_mm_init(target_phys_addr_t base, int it_shift, qemu_irq s = qemu_mallocz(sizeof(ParallelState)); if (!s) return NULL; - parallel_reset(s, irq, chr); + s->irq = irq; + s->chr = chr; s->it_shift = it_shift; + parallel_reset(s); + qemu_register_reset(parallel_reset, s); io_sw = cpu_register_io_memory(0, parallel_mm_read_sw, parallel_mm_write_sw, s); cpu_register_physical_memory(base, 8 << it_shift, io_sw); diff --git a/qemu/hw/pc.c b/qemu/hw/pc.c index 3cf5a730..2924b2a9 100644 --- a/qemu/hw/pc.c +++ b/qemu/hw/pc.c @@ -1164,8 +1164,7 @@ static void pc_init1(ram_addr_t ram_size, int vga_ram_size, int unit_id = 0; while ((index = drive_get_index(IF_VIRTIO, 0, unit_id)) != -1) { - virtio_blk_init(pci_bus, 0x1AF4, 0x1001, - drives_table[index].bdrv); + virtio_blk_init(pci_bus, drives_table[index].bdrv); unit_id++; } } diff --git a/qemu/hw/pc.h b/qemu/hw/pc.h index 8cfa1ca9..4df4a0e6 100644 --- a/qemu/hw/pc.h +++ b/qemu/hw/pc.h @@ -75,7 +75,8 @@ void *vmmouse_init(void *m); void i8042_init(qemu_irq kbd_irq, qemu_irq mouse_irq, uint32_t io_base); void i8042_mm_init(qemu_irq kbd_irq, qemu_irq mouse_irq, - target_phys_addr_t base, int it_shift); + target_phys_addr_t base, ram_addr_t size, + target_phys_addr_t mask); /* mc146818rtc.c */ diff --git a/qemu/hw/pci.c b/qemu/hw/pci.c index c93758d7..01b39fa4 100644 --- a/qemu/hw/pci.c +++ b/qemu/hw/pci.c @@ -54,6 +54,8 @@ static void pci_set_irq(void *opaque, int irq_num, int level); void assigned_dev_update_irq(PCIDevice *d); target_phys_addr_t pci_mem_base; +static uint16_t pci_default_sub_vendor_id = PCI_SUBVENDOR_ID_REDHAT_QUMRANET; +static uint16_t pci_default_sub_device_id = PCI_SUBDEVICE_ID_QEMU; static int pci_irq_index; static PCIBus *first_bus; @@ -149,6 +151,16 @@ int pci_device_load(PCIDevice *s, QEMUFile *f) return 0; } +static int pci_set_default_subsystem_id(PCIDevice *pci_dev) +{ + uint16_t *id; + + id = (void*)(&pci_dev->config[PCI_SUBVENDOR_ID]); + id[0] = cpu_to_le16(pci_default_sub_vendor_id); + id[1] = cpu_to_le16(pci_default_sub_device_id); + return 0; +} + /* -1 for devfn means auto assign */ PCIDevice *pci_register_device(PCIBus *bus, const char *name, int instance_size, int devfn, @@ -175,6 +187,7 @@ PCIDevice *pci_register_device(PCIBus *bus, const char *name, pci_dev->devfn = devfn; pstrcpy(pci_dev->name, sizeof(pci_dev->name), name); memset(pci_dev->irq_state, 0, sizeof(pci_dev->irq_state)); + pci_set_default_subsystem_id(pci_dev); if (!config_read) config_read = pci_default_read_config; @@ -326,9 +339,7 @@ static void pci_update_mappings(PCIDevice *d) cpu_register_physical_memory(pci_to_cpu_addr(r->addr), r->size, IO_MEM_UNASSIGNED); - if (kvm_enabled()) - qemu_kvm_unregister_coalesced_mmio(r->addr, - r->size); + qemu_unregister_coalesced_mmio(r->addr, r->size); } } r->addr = new_addr; diff --git a/qemu/hw/pci.h b/qemu/hw/pci.h index e11fbbf4..f6f417ec 100644 --- a/qemu/hw/pci.h +++ b/qemu/hw/pci.h @@ -11,6 +11,15 @@ /* PCI bus */ extern target_phys_addr_t pci_mem_base; +/* see pci-ids.txt */ +#define PCI_VENDOR_ID_REDHAT_QUMRANET 0x1af4 +#define PCI_SUBVENDOR_ID_REDHAT_QUMRANET 0x1af4 +#define PCI_SUBDEVICE_ID_QEMU 0x1100 + +#define PCI_DEVICE_ID_VIRTIO_NET 0x1000 +#define PCI_DEVICE_ID_VIRTIO_BLOCK 0x1001 +#define PCI_DEVICE_ID_VIRTIO_BALLOON 0x1002 + typedef void PCIConfigWriteFunc(PCIDevice *pci_dev, uint32_t address, uint32_t data, int len); typedef uint32_t PCIConfigReadFunc(PCIDevice *pci_dev, @@ -40,7 +49,10 @@ typedef struct PCIIORegion { #define PCI_COMMAND 0x04 /* 16 bits */ #define PCI_COMMAND_IO 0x1 /* Enable response in I/O space */ #define PCI_COMMAND_MEMORY 0x2 /* Enable response in Memory space */ +#define PCI_REVISION 0x08 #define PCI_CLASS_DEVICE 0x0a /* Device class */ +#define PCI_SUBVENDOR_ID 0x2c /* 16 bits */ +#define PCI_SUBDEVICE_ID 0x2e /* 16 bits */ #define PCI_INTERRUPT_LINE 0x3c /* 8 bits */ #define PCI_INTERRUPT_PIN 0x3d /* 8 bits */ #define PCI_MIN_GNT 0x3e /* 8 bits */ @@ -149,4 +161,8 @@ PCIBus *pci_prep_init(qemu_irq *pic); PCIBus *pci_apb_init(target_phys_addr_t special_base, target_phys_addr_t mem_base, qemu_irq *pic); +/* sh_pci.c */ +PCIBus *sh_pci_register_bus(pci_set_irq_fn set_irq, pci_map_irq_fn map_irq, + qemu_irq *pic, int devfn_min, int nirq); + #endif diff --git a/qemu/hw/pci_host.h b/qemu/hw/pci_host.h index 49a0c59d..e2e428a2 100644 --- a/qemu/hw/pci_host.h +++ b/qemu/hw/pci_host.h @@ -90,4 +90,3 @@ static uint32_t pci_host_data_readl(void* opaque, pci_addr_t addr) #endif return val; } - diff --git a/qemu/hw/pckbd.c b/qemu/hw/pckbd.c index cceea4a5..3a004f7a 100644 --- a/qemu/hw/pckbd.c +++ b/qemu/hw/pckbd.c @@ -125,7 +125,7 @@ typedef struct KBDState { qemu_irq irq_kbd; qemu_irq irq_mouse; - int it_shift; + target_phys_addr_t mask; } KBDState; static KBDState kbd_state; @@ -391,28 +391,20 @@ static uint32_t kbd_mm_readb (void *opaque, target_phys_addr_t addr) { KBDState *s = opaque; - switch (addr >> s->it_shift) { - case 0: - return kbd_read_data(s, 0) & 0xff; - case 1: + if (addr & s->mask) return kbd_read_status(s, 0) & 0xff; - default: - return 0xff; - } + else + return kbd_read_data(s, 0) & 0xff; } static void kbd_mm_writeb (void *opaque, target_phys_addr_t addr, uint32_t value) { KBDState *s = opaque; - switch (addr >> s->it_shift) { - case 0: - kbd_write_data(s, 0, value & 0xff); - break; - case 1: + if (addr & s->mask) kbd_write_command(s, 0, value & 0xff); - break; - } + else + kbd_write_data(s, 0, value & 0xff); } static CPUReadMemoryFunc *kbd_mm_read[] = { @@ -428,19 +420,20 @@ static CPUWriteMemoryFunc *kbd_mm_write[] = { }; void i8042_mm_init(qemu_irq kbd_irq, qemu_irq mouse_irq, - target_phys_addr_t base, int it_shift) + target_phys_addr_t base, ram_addr_t size, + target_phys_addr_t mask) { KBDState *s = &kbd_state; int s_io_memory; s->irq_kbd = kbd_irq; s->irq_mouse = mouse_irq; - s->it_shift = it_shift; + s->mask = mask; kbd_reset(s); register_savevm("pckbd", 0, 3, kbd_save, kbd_load, s); s_io_memory = cpu_register_io_memory(0, kbd_mm_read, kbd_mm_write, s); - cpu_register_physical_memory(base, 2 << it_shift, s_io_memory); + cpu_register_physical_memory(base, size, s_io_memory); s->kbd = ps2_kbd_init(kbd_update_kbd_irq, s); s->mouse = ps2_mouse_init(kbd_update_aux_irq, s); diff --git a/qemu/hw/pcmcia.h b/qemu/hw/pcmcia.h index bfa23bab..8f8366c8 100644 --- a/qemu/hw/pcmcia.h +++ b/qemu/hw/pcmcia.h @@ -47,4 +47,3 @@ struct pcmcia_card_s { /* dscm1xxxx.c */ struct pcmcia_card_s *dscm1xxxx_init(BlockDriverState *bdrv); - diff --git a/qemu/hw/pflash_cfi01.c b/qemu/hw/pflash_cfi01.c index 6113fa64..6f97e9d8 100644 --- a/qemu/hw/pflash_cfi01.c +++ b/qemu/hw/pflash_cfi01.c @@ -194,6 +194,47 @@ static void pflash_update(pflash_t *pfl, int offset, } } +static void inline pflash_data_write(pflash_t *pfl, target_ulong offset, + uint32_t value, int width) +{ + uint8_t *p = pfl->storage; + + DPRINTF("%s: block write offset " TARGET_FMT_lx + " value %x counter " TARGET_FMT_lx "\n", + __func__, offset, value, pfl->counter); + switch (width) { + case 1: + p[offset] = value; + pflash_update(pfl, offset, 1); + break; + case 2: +#if defined(TARGET_WORDS_BIGENDIAN) + p[offset] = value >> 8; + p[offset + 1] = value; +#else + p[offset] = value; + p[offset + 1] = value >> 8; +#endif + pflash_update(pfl, offset, 2); + break; + case 4: +#if defined(TARGET_WORDS_BIGENDIAN) + p[offset] = value >> 24; + p[offset + 1] = value >> 16; + p[offset + 2] = value >> 8; + p[offset + 3] = value; +#else + p[offset] = value; + p[offset + 1] = value >> 8; + p[offset + 2] = value >> 16; + p[offset + 3] = value >> 24; +#endif + pflash_update(pfl, offset, 4); + break; + } + +} + static void pflash_write (pflash_t *pfl, target_ulong offset, uint32_t value, int width) { @@ -221,6 +262,10 @@ static void pflash_write (pflash_t *pfl, target_ulong offset, uint32_t value, switch (cmd) { case 0x00: /* ??? */ goto reset_flash; + case 0x10: /* Single Byte Program */ + case 0x40: /* Single Byte Program */ + DPRINTF(stderr, "%s: Single Byte Program\n", __func__); + break; case 0x20: /* Block erase */ p = pfl->storage; offset &= ~(pfl->sector_len - 1); @@ -262,6 +307,13 @@ static void pflash_write (pflash_t *pfl, target_ulong offset, uint32_t value, return; case 1: switch (pfl->cmd) { + case 0x10: /* Single Byte Program */ + case 0x40: /* Single Byte Program */ + DPRINTF("%s: Single Byte Program\n", __func__); + pflash_data_write(pfl, offset, value, width); + pfl->status |= 0x80; /* Ready! */ + pfl->wcycle = 0; + break; case 0x20: /* Block erase */ case 0x28: if (cmd == 0xd0) { /* confirm */ @@ -306,40 +358,7 @@ static void pflash_write (pflash_t *pfl, target_ulong offset, uint32_t value, case 2: switch (pfl->cmd) { case 0xe8: /* Block write */ - p = pfl->storage; - DPRINTF("%s: block write offset " TARGET_FMT_lx - " value %x counter " TARGET_FMT_lx "\n", - __func__, offset, value, pfl->counter); - switch (width) { - case 1: - p[offset] = value; - pflash_update(pfl, offset, 1); - break; - case 2: -#if defined(TARGET_WORDS_BIGENDIAN) - p[offset] = value >> 8; - p[offset + 1] = value; -#else - p[offset] = value; - p[offset + 1] = value >> 8; -#endif - pflash_update(pfl, offset, 2); - break; - case 4: -#if defined(TARGET_WORDS_BIGENDIAN) - p[offset] = value >> 24; - p[offset + 1] = value >> 16; - p[offset + 2] = value >> 8; - p[offset + 3] = value; -#else - p[offset] = value; - p[offset + 1] = value >> 8; - p[offset + 2] = value >> 16; - p[offset + 3] = value >> 24; -#endif - pflash_update(pfl, offset, 4); - break; - } + pflash_data_write(pfl, offset, value, width); pfl->status |= 0x80; diff --git a/qemu/hw/pl011.c b/qemu/hw/pl011.c index dd6994c4..468d48a9 100644 --- a/qemu/hw/pl011.c +++ b/qemu/hw/pl011.c @@ -309,4 +309,3 @@ void pl011_init(uint32_t base, qemu_irq irq, } register_savevm("pl011_uart", -1, 1, pl011_save, pl011_load, s); } - diff --git a/qemu/hw/pl022.c b/qemu/hw/pl022.c index ee166ffc..90f4f0f1 100644 --- a/qemu/hw/pl022.c +++ b/qemu/hw/pl022.c @@ -306,5 +306,3 @@ void pl022_init(uint32_t base, qemu_irq irq, int (*xfer_cb)(void *, int), pl022_reset(s); register_savevm("pl022_ssp", -1, 1, pl022_save, pl022_load, s); } - - diff --git a/qemu/hw/pl050.c b/qemu/hw/pl050.c index e74a6dcd..0ab60bf8 100644 --- a/qemu/hw/pl050.c +++ b/qemu/hw/pl050.c @@ -139,4 +139,3 @@ void pl050_init(uint32_t base, qemu_irq irq, int is_mouse) s->dev = ps2_kbd_init(pl050_update, s); /* ??? Save/restore. */ } - diff --git a/qemu/hw/pl061.c b/qemu/hw/pl061.c index a4d59c79..fab99d4a 100644 --- a/qemu/hw/pl061.c +++ b/qemu/hw/pl061.c @@ -311,4 +311,3 @@ qemu_irq *pl061_init(uint32_t base, qemu_irq irq, qemu_irq **out) register_savevm("pl061_gpio", -1, 1, pl061_save, pl061_load, s); return qemu_allocate_irqs(pl061_set_irq, s, 8); } - diff --git a/qemu/hw/pl080.c b/qemu/hw/pl080.c index 1be30354..e4d7e170 100644 --- a/qemu/hw/pl080.c +++ b/qemu/hw/pl080.c @@ -336,4 +336,3 @@ void *pl080_init(uint32_t base, qemu_irq irq, int nchannels) /* ??? Save/restore. */ return s; } - diff --git a/qemu/hw/ppc405_boards.c b/qemu/hw/ppc405_boards.c index 4144daee..1d8b6aba 100644 --- a/qemu/hw/ppc405_boards.c +++ b/qemu/hw/ppc405_boards.c @@ -129,9 +129,9 @@ static uint32_t ref405ep_fpga_readl (void *opaque, target_phys_addr_t addr) static void ref405ep_fpga_writel (void *opaque, target_phys_addr_t addr, uint32_t value) { - ref405ep_fpga_writel(opaque, addr, (value >> 24) & 0xFF); - ref405ep_fpga_writel(opaque, addr + 1, (value >> 16) & 0xFF); - ref405ep_fpga_writel(opaque, addr + 2, (value >> 8) & 0xFF); + ref405ep_fpga_writeb(opaque, addr, (value >> 24) & 0xFF); + ref405ep_fpga_writeb(opaque, addr + 1, (value >> 16) & 0xFF); + ref405ep_fpga_writeb(opaque, addr + 2, (value >> 8) & 0xFF); ref405ep_fpga_writeb(opaque, addr + 3, value & 0xFF); } diff --git a/qemu/hw/ppc4xx_pci.c b/qemu/hw/ppc4xx_pci.c index bfd2f3e9..b21c2fef 100644 --- a/qemu/hw/ppc4xx_pci.c +++ b/qemu/hw/ppc4xx_pci.c @@ -21,6 +21,8 @@ * 4xx SoCs, such as the 440EP. */ #include "hw.h" +#include "ppc.h" +#include "ppc4xx.h" typedef target_phys_addr_t pci_addr_t; #include "pci.h" diff --git a/qemu/hw/prep_pci.c b/qemu/hw/prep_pci.c index 815db530..dd53f871 100644 --- a/qemu/hw/prep_pci.c +++ b/qemu/hw/prep_pci.c @@ -169,4 +169,3 @@ PCIBus *pci_prep_init(qemu_irq *pic) return s->bus; } - diff --git a/qemu/hw/ps2.h b/qemu/hw/ps2.h index f2c091ed..32a4231e 100644 --- a/qemu/hw/ps2.h +++ b/qemu/hw/ps2.h @@ -7,4 +7,3 @@ uint32_t ps2_read_data(void *); void ps2_queue(void *, int b); void ps2_keyboard_set_translation(void *opaque, int mode); void ps2_mouse_fake_event(void *opaque); - diff --git a/qemu/hw/ptimer.c b/qemu/hw/ptimer.c index b772ca29..9d386272 100644 --- a/qemu/hw/ptimer.c +++ b/qemu/hw/ptimer.c @@ -192,4 +192,3 @@ ptimer_state *ptimer_init(QEMUBH *bh) s->timer = qemu_new_timer(vm_clock, ptimer_tick, s); return s; } - diff --git a/qemu/hw/pxa2xx.c b/qemu/hw/pxa2xx.c index 660ff4a1..b780bad8 100644 --- a/qemu/hw/pxa2xx.c +++ b/qemu/hw/pxa2xx.c @@ -1487,7 +1487,7 @@ struct pxa2xx_i2c_s *pxa2xx_i2c_init(target_phys_addr_t base, s->slave.recv = pxa2xx_i2c_rx; s->slave.send = pxa2xx_i2c_tx; s->bus = i2c_init_bus(); - s->offset = base & region_size; + s->offset = base - (base & (~region_size) & TARGET_PAGE_MASK); iomemtype = cpu_register_io_memory(0, pxa2xx_i2c_readfn, pxa2xx_i2c_writefn, s); diff --git a/qemu/hw/pxa2xx_lcd.c b/qemu/hw/pxa2xx_lcd.c index c36ff364..ffe7a56a 100644 --- a/qemu/hw/pxa2xx_lcd.c +++ b/qemu/hw/pxa2xx_lcd.c @@ -696,7 +696,7 @@ static void pxa2xx_lcdc_dma0_redraw_horiz(struct pxa2xx_lcdc_s *s, addr = (ram_addr_t) (fb - phys_ram_base); start = addr + s->yres * src_width; end = addr; - dirty[0] = dirty[1] = cpu_physical_memory_get_dirty(start, VGA_DIRTY_FLAG); + dirty[0] = dirty[1] = cpu_physical_memory_get_dirty(addr, VGA_DIRTY_FLAG); for (y = 0; y < s->yres; y ++) { new_addr = addr + src_width; for (x = addr + TARGET_PAGE_SIZE; x < new_addr; @@ -752,11 +752,11 @@ static void pxa2xx_lcdc_dma0_redraw_vert(struct pxa2xx_lcdc_s *s, addr = (ram_addr_t) (fb - phys_ram_base); start = addr + s->yres * src_width; end = addr; + x = addr + TARGET_PAGE_SIZE; dirty[0] = dirty[1] = cpu_physical_memory_get_dirty(start, VGA_DIRTY_FLAG); for (y = 0; y < s->yres; y ++) { new_addr = addr + src_width; - for (x = addr + TARGET_PAGE_SIZE; x < new_addr; - x += TARGET_PAGE_SIZE) { + for (; x < new_addr; x += TARGET_PAGE_SIZE) { dirty[1] = cpu_physical_memory_get_dirty(x, VGA_DIRTY_FLAG); dirty[0] |= dirty[1]; } diff --git a/qemu/hw/r2d.c b/qemu/hw/r2d.c index 5f9f5697..5d5eb1e4 100644 --- a/qemu/hw/r2d.c +++ b/qemu/hw/r2d.c @@ -28,18 +28,23 @@ #include "devices.h" #include "sysemu.h" #include "boards.h" +#include "pci.h" +#include "net.h" +#include "sh7750_regs.h" #define SDRAM_BASE 0x0c000000 /* Physical location of SDRAM: Area 3 */ #define SDRAM_SIZE 0x04000000 #define SM501_VRAM_SIZE 0x800000 +#define PA_IRLMSK 0x00 #define PA_POWOFF 0x30 #define PA_VERREG 0x32 #define PA_OUTPORT 0x36 typedef struct { uint16_t bcr; + uint16_t irlmsk; uint16_t irlmon; uint16_t cfctl; uint16_t cfpow; @@ -60,13 +65,60 @@ typedef struct { uint16_t inport; uint16_t outport; uint16_t bverreg; + +/* output pin */ + qemu_irq irl; } r2d_fpga_t; +enum r2d_fpga_irq { + PCI_INTD, CF_IDE, CF_CD, PCI_INTC, SM501, KEY, RTC_A, RTC_T, + SDCARD, PCI_INTA, PCI_INTB, EXT, TP, + NR_IRQS +}; + +static const struct { short irl; uint16_t msk; } irqtab[NR_IRQS] = { + [CF_IDE] = { 1, 1<<9 }, + [CF_CD] = { 2, 1<<8 }, + [PCI_INTA] = { 9, 1<<14 }, + [PCI_INTB] = { 10, 1<<13 }, + [PCI_INTC] = { 3, 1<<12 }, + [PCI_INTD] = { 0, 1<<11 }, + [SM501] = { 4, 1<<10 }, + [KEY] = { 5, 1<<6 }, + [RTC_A] = { 6, 1<<5 }, + [RTC_T] = { 7, 1<<4 }, + [SDCARD] = { 8, 1<<7 }, + [EXT] = { 11, 1<<0 }, + [TP] = { 12, 1<<15 }, +}; + +static void update_irl(r2d_fpga_t *fpga) +{ + int i, irl = 15; + for (i = 0; i < NR_IRQS; i++) + if (fpga->irlmon & fpga->irlmsk & irqtab[i].msk) + if (irqtab[i].irl < irl) + irl = irqtab[i].irl; + qemu_set_irq(fpga->irl, irl ^ 15); +} + +static void r2d_fpga_irq_set(void *opaque, int n, int level) +{ + r2d_fpga_t *fpga = opaque; + if (level) + fpga->irlmon |= irqtab[n].msk; + else + fpga->irlmon &= ~irqtab[n].msk; + update_irl(fpga); +} + static uint32_t r2d_fpga_read(void *opaque, target_phys_addr_t addr) { r2d_fpga_t *s = opaque; switch (addr) { + case PA_IRLMSK: + return s->irlmsk; case PA_OUTPORT: return s->outport; case PA_POWOFF: @@ -84,6 +136,10 @@ r2d_fpga_write(void *opaque, target_phys_addr_t addr, uint32_t value) r2d_fpga_t *s = opaque; switch (addr) { + case PA_IRLMSK: + s->irlmsk = value; + update_irl(s); + break; case PA_OUTPORT: s->outport = value; break; @@ -108,18 +164,32 @@ static CPUWriteMemoryFunc *r2d_fpga_writefn[] = { NULL, }; -static void r2d_fpga_init(target_phys_addr_t base) +static qemu_irq *r2d_fpga_init(target_phys_addr_t base, qemu_irq irl) { int iomemtype; r2d_fpga_t *s; s = qemu_mallocz(sizeof(r2d_fpga_t)); if (!s) - return; + return NULL; + + s->irl = irl; iomemtype = cpu_register_io_memory(0, r2d_fpga_readfn, r2d_fpga_writefn, s); cpu_register_physical_memory(base, 0x40, iomemtype); + return qemu_allocate_irqs(r2d_fpga_irq_set, s, NR_IRQS); +} + +static void r2d_pci_set_irq(qemu_irq *p, int n, int l) +{ + qemu_set_irq(p[n], l); +} + +static int r2d_pci_map_irq(PCIDevice *d, int irq_num) +{ + const int intx[] = { PCI_INTA, PCI_INTB, PCI_INTC, PCI_INTD }; + return intx[d->devfn >> 3]; } static void r2d_init(ram_addr_t ram_size, int vga_ram_size, @@ -130,6 +200,9 @@ static void r2d_init(ram_addr_t ram_size, int vga_ram_size, CPUState *env; struct SH7750State *s; ram_addr_t sdram_addr, sm501_vga_ram_addr; + qemu_irq *irq; + PCIBus *pci; + int i; if (!cpu_model) cpu_model = "SH7751R"; @@ -144,14 +217,31 @@ static void r2d_init(ram_addr_t ram_size, int vga_ram_size, sdram_addr = qemu_ram_alloc(SDRAM_SIZE); cpu_register_physical_memory(SDRAM_BASE, SDRAM_SIZE, sdram_addr); /* Register peripherals */ - r2d_fpga_init(0x04000000); s = sh7750_init(env); + irq = r2d_fpga_init(0x04000000, sh7750_irl(s)); + pci = sh_pci_register_bus(r2d_pci_set_irq, r2d_pci_map_irq, irq, 0, 4); + sm501_vga_ram_addr = qemu_ram_alloc(SM501_VRAM_SIZE); sm501_init(ds, 0x10000000, sm501_vga_ram_addr, SM501_VRAM_SIZE, serial_hds[2]); + + /* onboard CF (True IDE mode, Master only). */ + mmio_ide_init(0x14001000, 0x1400080c, irq[CF_IDE], 1, + drives_table[drive_get_index(IF_IDE, 0, 0)].bdrv, NULL); + + /* NIC: rtl8139 on-board, and 2 slots. */ + pci_rtl8139_init(pci, &nd_table[0], 2 << 3); + for (i = 1; i < nb_nics; i++) + pci_nic_init(pci, &nd_table[i], -1); + /* Todo: register on board registers */ { int kernel_size; + /* initialization which should be done by firmware */ + uint32_t bcr1 = 1 << 3; /* cs3 SDRAM */ + uint16_t bcr2 = 3 << (3 * 2); /* cs3 32-bit */ + cpu_physical_memory_write(SH7750_BCR1_A7, (uint8_t *)&bcr1, 4); + cpu_physical_memory_write(SH7750_BCR2_A7, (uint8_t *)&bcr2, 2); kernel_size = load_image(kernel_filename, phys_ram_base); diff --git a/qemu/hw/rc4030.c b/qemu/hw/rc4030.c index 0384cf27..54f9adfa 100644 --- a/qemu/hw/rc4030.c +++ b/qemu/hw/rc4030.c @@ -23,6 +23,7 @@ */ #include "hw.h" +#include "mips.h" #include "qemu-timer.h" //#define DEBUG_RC4030 diff --git a/qemu/hw/rtl8139.c b/qemu/hw/rtl8139.c index cff4f10c..ed80fdea 100644 --- a/qemu/hw/rtl8139.c +++ b/qemu/hw/rtl8139.c @@ -3467,4 +3467,3 @@ PCIDevice *pci_rtl8139_init(PCIBus *bus, NICInfo *nd, int devfn) #endif /* RTL8139_ONBOARD_TIMER */ return (PCIDevice *)d; } - diff --git a/qemu/hw/sh.h b/qemu/hw/sh.h index 15c58cb9..5e3c22bb 100644 --- a/qemu/hw/sh.h +++ b/qemu/hw/sh.h @@ -4,6 +4,9 @@ #include "sh_intc.h" +#define A7ADDR(x) ((x) & 0x1fffffff) +#define P4ADDR(x) ((x) | 0xe0000000) + /* sh7750.c */ struct SH7750State; @@ -42,7 +45,14 @@ void sh_serial_init (target_phys_addr_t base, int feat, qemu_irq tei_source, qemu_irq bri_source); +/* sh7750.c */ +qemu_irq sh7750_irl(struct SH7750State *s); + /* tc58128.c */ int tc58128_init(struct SH7750State *s, const char *zone1, const char *zone2); +/* ide.c */ +void mmio_ide_init(target_phys_addr_t membase, target_phys_addr_t membase2, + qemu_irq irq, int shift, + BlockDriverState *hd0, BlockDriverState *hd1); #endif diff --git a/qemu/hw/sh7750.c b/qemu/hw/sh7750.c index 1d180102..4d1a8065 100644 --- a/qemu/hw/sh7750.c +++ b/qemu/hw/sh7750.c @@ -41,6 +41,8 @@ typedef struct SH7750State { /* Peripheral frequency in Hz */ uint32_t periph_freq; /* SDRAM controller */ + uint32_t bcr1; + uint32_t bcr2; uint16_t rfcr; /* IO ports */ uint16_t gpioic; @@ -58,7 +60,6 @@ typedef struct SH7750State { uint16_t periph_portdirb; /* Direction seen from the peripherals */ sh7750_io_device *devices[NB_DEVICES]; /* External peripherals */ - uint16_t icr; /* Cache */ uint32_t ccr; @@ -208,6 +209,8 @@ static uint32_t sh7750_mem_readw(void *opaque, target_phys_addr_t addr) SH7750State *s = opaque; switch (addr) { + case SH7750_BCR2_A7: + return s->bcr2; case SH7750_FRQCR_A7: return 0; case SH7750_RFCR_A7: @@ -218,8 +221,6 @@ static uint32_t sh7750_mem_readw(void *opaque, target_phys_addr_t addr) 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); @@ -231,6 +232,15 @@ static uint32_t sh7750_mem_readl(void *opaque, target_phys_addr_t addr) SH7750State *s = opaque; switch (addr) { + case SH7750_BCR1_A7: + return s->bcr1; + case SH7750_BCR4_A7: + case SH7750_WCR1_A7: + case SH7750_WCR2_A7: + case SH7750_WCR3_A7: + case SH7750_MCR_A7: + ignore_access("long read", addr); + return 0; case SH7750_MMUCR_A7: return s->cpu->mmucr; case SH7750_PTEH_A7: @@ -285,6 +295,8 @@ static void sh7750_mem_writew(void *opaque, target_phys_addr_t addr, switch (addr) { /* SDRAM controller */ case SH7750_BCR2_A7: + s->bcr2 = mem_value; + return; case SH7750_BCR3_A7: case SH7750_RTCOR_A7: case SH7750_RTCNT_A7: @@ -313,9 +325,6 @@ static void sh7750_mem_writew(void *opaque, target_phys_addr_t addr, assert(0); } return; - case 0x1fd00000: - s->icr = mem_value; - return; default: error_access("word write", addr); assert(0); @@ -331,6 +340,8 @@ static void sh7750_mem_writel(void *opaque, target_phys_addr_t addr, switch (addr) { /* SDRAM controller */ case SH7750_BCR1_A7: + s->bcr1 = mem_value; + return; case SH7750_BCR4_A7: case SH7750_WCR1_A7: case SH7750_WCR2_A7: @@ -412,7 +423,9 @@ enum { UNUSED = 0, /* interrupt sources */ - IRL0, IRL1, IRL2, IRL3, /* only IRLM mode supported */ + IRL_0, IRL_1, IRL_2, IRL_3, IRL_4, IRL_5, IRL_6, IRL_7, + IRL_8, IRL_9, IRL_A, IRL_B, IRL_C, IRL_D, IRL_E, + IRL0, IRL1, IRL2, IRL3, HUDI, GPIOI, DMAC_DMTE0, DMAC_DMTE1, DMAC_DMTE2, DMAC_DMTE3, DMAC_DMTE4, DMAC_DMTE5, DMAC_DMTE6, DMAC_DMTE7, @@ -428,6 +441,8 @@ enum { /* interrupt groups */ DMAC, PCIC1, TMU2, RTC, SCI1, SCIF, REF, + /* irl bundle */ + IRL, NR_SOURCES, }; @@ -529,6 +544,29 @@ static struct intc_group groups_pci[] = { PCIC1_PCIDMA0, PCIC1_PCIDMA1, PCIC1_PCIDMA2, PCIC1_PCIDMA3), }; +static struct intc_vect vectors_irl[] = { + INTC_VECT(IRL_0, 0x200), + INTC_VECT(IRL_1, 0x220), + INTC_VECT(IRL_2, 0x240), + INTC_VECT(IRL_3, 0x260), + INTC_VECT(IRL_4, 0x280), + INTC_VECT(IRL_5, 0x2a0), + INTC_VECT(IRL_6, 0x2c0), + INTC_VECT(IRL_7, 0x2e0), + INTC_VECT(IRL_8, 0x300), + INTC_VECT(IRL_9, 0x320), + INTC_VECT(IRL_A, 0x340), + INTC_VECT(IRL_B, 0x360), + INTC_VECT(IRL_C, 0x380), + INTC_VECT(IRL_D, 0x3a0), + INTC_VECT(IRL_E, 0x3c0), +}; + +static struct intc_group groups_irl[] = { + INTC_GROUP(IRL, IRL_0, IRL_1, IRL_2, IRL_3, IRL_4, IRL_5, IRL_6, + IRL_7, IRL_8, IRL_9, IRL_A, IRL_B, IRL_C, IRL_D, IRL_E), +}; + /********************************************************************** Memory mapped cache and TLB **********************************************************************/ @@ -643,8 +681,18 @@ SH7750State *sh7750_init(CPUSH4State * cpu) sh7750_io_memory = cpu_register_io_memory(0, sh7750_mem_read, sh7750_mem_write, s); - cpu_register_physical_memory_offset(0x1c000000, 0x04000000, - sh7750_io_memory, 0x1c000000); + cpu_register_physical_memory_offset(0x1f000000, 0x1000, + sh7750_io_memory, 0x1f000000); + cpu_register_physical_memory_offset(0xff000000, 0x1000, + sh7750_io_memory, 0x1f000000); + cpu_register_physical_memory_offset(0x1f800000, 0x1000, + sh7750_io_memory, 0x1f800000); + cpu_register_physical_memory_offset(0xff800000, 0x1000, + sh7750_io_memory, 0x1f800000); + cpu_register_physical_memory_offset(0x1fc00000, 0x1000, + sh7750_io_memory, 0x1fc00000); + cpu_register_physical_memory_offset(0xffc00000, 0x1000, + sh7750_io_memory, 0x1fc00000); sh7750_mm_cache_and_tlb = cpu_register_io_memory(0, sh7750_mmct_read, @@ -718,5 +766,15 @@ SH7750State *sh7750_init(CPUSH4State * cpu) NULL, 0); } + sh_intc_register_sources(&s->intc, + _INTC_ARRAY(vectors_irl), + _INTC_ARRAY(groups_irl)); return s; } + +qemu_irq sh7750_irl(SH7750State *s) +{ + sh_intc_toggle_source(sh_intc_source(&s->intc, IRL), 1, 0); /* enable */ + return qemu_allocate_irqs(sh_intc_set_irl, sh_intc_source(&s->intc, IRL), + 1)[0]; +} diff --git a/qemu/hw/sh_intc.c b/qemu/hw/sh_intc.c index 99db51c6..136e7dd2 100644 --- a/qemu/hw/sh_intc.c +++ b/qemu/hw/sh_intc.c @@ -73,7 +73,7 @@ void sh_intc_toggle_source(struct intc_source *source, } } -void sh_intc_set_irq (void *opaque, int n, int level) +static void sh_intc_set_irq (void *opaque, int n, int level) { struct intc_desc *desc = opaque; struct intc_source *source = &(desc->sources[n]); @@ -307,9 +307,12 @@ struct intc_source *sh_intc_source(struct intc_desc *desc, intc_enum id) static void sh_intc_register(struct intc_desc *desc, unsigned long address) { - if (address) - cpu_register_physical_memory_offset(INTC_A7(address), 4, + if (address) { + cpu_register_physical_memory_offset(P4ADDR(address), 4, desc->iomemtype, INTC_A7(address)); + cpu_register_physical_memory_offset(A7ADDR(address), 4, + desc->iomemtype, INTC_A7(address)); + } } static void sh_intc_register_source(struct intc_desc *desc, @@ -465,3 +468,18 @@ int sh_intc_init(struct intc_desc *desc, return 0; } + +/* Assert level <n> IRL interrupt. + 0:deassert. 1:lowest priority,... 15:highest priority. */ +void sh_intc_set_irl(void *opaque, int n, int level) +{ + struct intc_source *s = opaque; + int i, irl = level ^ 15; + for (i = 0; (s = sh_intc_source(s->parent, s->next_enum_id)); i++) { + if (i == irl) + sh_intc_toggle_source(s, s->enable_count?0:1, s->asserted?0:1); + else + if (s->asserted) + sh_intc_toggle_source(s, 0, -1); + } +} diff --git a/qemu/hw/sh_intc.h b/qemu/hw/sh_intc.h index 4362dcf1..4e36f007 100644 --- a/qemu/hw/sh_intc.h +++ b/qemu/hw/sh_intc.h @@ -75,4 +75,6 @@ int sh_intc_init(struct intc_desc *desc, struct intc_prio_reg *prio_regs, int nr_prio_regs); +void sh_intc_set_irl(void *opaque, int n, int level); + #endif /* __SH_INTC_H__ */ diff --git a/qemu/hw/sh_pci.c b/qemu/hw/sh_pci.c new file mode 100644 index 00000000..5524c598 --- /dev/null +++ b/qemu/hw/sh_pci.c @@ -0,0 +1,204 @@ +/* + * SuperH on-chip PCIC emulation. + * + * Copyright (c) 2008 Takashi YOSHII + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ +#include "hw.h" +#include "sh.h" +#include "pci.h" +#include "bswap.h" + +typedef struct { + PCIBus *bus; + PCIDevice *dev; + uint32_t regbase; + uint32_t iopbase; + uint32_t membase; + uint32_t par; + uint32_t mbr; + uint32_t iobr; +} SHPCIC; + +static void sh_pci_reg_write (void *p, target_phys_addr_t addr, uint32_t val) +{ + SHPCIC *pcic = p; + switch(addr) { + case 0 ... 0xfc: + cpu_to_le32w((uint32_t*)(pcic->dev->config + addr), val); + break; + case 0x1c0: + pcic->par = val; + break; + case 0x1c4: + pcic->mbr = val; + break; + case 0x1c8: + pcic->iobr = val; + break; + case 0x220: + pci_data_write(pcic->bus, pcic->par, val, 4); + break; + } +} + +static uint32_t sh_pci_reg_read (void *p, target_phys_addr_t addr) +{ + SHPCIC *pcic = p; + switch(addr) { + case 0 ... 0xfc: + return le32_to_cpup((uint32_t*)(pcic->dev->config + addr)); + case 0x1c0: + return pcic->par; + case 0x220: + return pci_data_read(pcic->bus, pcic->par, 4); + } + return 0; +} + +static void sh_pci_data_write (SHPCIC *pcic, target_phys_addr_t addr, + uint32_t val, int size) +{ + pci_data_write(pcic->bus, addr + pcic->mbr, val, size); +} + +static uint32_t sh_pci_mem_read (SHPCIC *pcic, target_phys_addr_t addr, + int size) +{ + return pci_data_read(pcic->bus, addr + pcic->mbr, size); +} + +static void sh_pci_writeb (void *p, target_phys_addr_t addr, uint32_t val) +{ + sh_pci_data_write(p, addr, val, 1); +} + +static void sh_pci_writew (void *p, target_phys_addr_t addr, uint32_t val) +{ + sh_pci_data_write(p, addr, val, 2); +} + +static void sh_pci_writel (void *p, target_phys_addr_t addr, uint32_t val) +{ + sh_pci_data_write(p, addr, val, 4); +} + +static uint32_t sh_pci_readb (void *p, target_phys_addr_t addr) +{ + return sh_pci_mem_read(p, addr, 1); +} + +static uint32_t sh_pci_readw (void *p, target_phys_addr_t addr) +{ + return sh_pci_mem_read(p, addr, 2); +} + +static uint32_t sh_pci_readl (void *p, target_phys_addr_t addr) +{ + return sh_pci_mem_read(p, addr, 4); +} + +static int sh_pci_addr2port(SHPCIC *pcic, target_phys_addr_t addr) +{ + return addr + pcic->iobr; +} + +static void sh_pci_outb (void *p, target_phys_addr_t addr, uint32_t val) +{ + cpu_outb(NULL, sh_pci_addr2port(p, addr), val); +} + +static void sh_pci_outw (void *p, target_phys_addr_t addr, uint32_t val) +{ + cpu_outw(NULL, sh_pci_addr2port(p, addr), val); +} + +static void sh_pci_outl (void *p, target_phys_addr_t addr, uint32_t val) +{ + cpu_outl(NULL, sh_pci_addr2port(p, addr), val); +} + +static uint32_t sh_pci_inb (void *p, target_phys_addr_t addr) +{ + return cpu_inb(NULL, sh_pci_addr2port(p, addr)); +} + +static uint32_t sh_pci_inw (void *p, target_phys_addr_t addr) +{ + return cpu_inw(NULL, sh_pci_addr2port(p, addr)); +} + +static uint32_t sh_pci_inl (void *p, target_phys_addr_t addr) +{ + return cpu_inl(NULL, sh_pci_addr2port(p, addr)); +} + +typedef struct { + CPUReadMemoryFunc *r[3]; + CPUWriteMemoryFunc *w[3]; +} MemOp; + +static MemOp sh_pci_reg = { + { NULL, NULL, sh_pci_reg_read }, + { NULL, NULL, sh_pci_reg_write }, +}; + +static MemOp sh_pci_mem = { + { sh_pci_readb, sh_pci_readw, sh_pci_readl }, + { sh_pci_writeb, sh_pci_writew, sh_pci_writel }, +}; + +static MemOp sh_pci_iop = { + { sh_pci_inb, sh_pci_inw, sh_pci_inl }, + { sh_pci_outb, sh_pci_outw, sh_pci_outl }, +}; + +PCIBus *sh_pci_register_bus(pci_set_irq_fn set_irq, pci_map_irq_fn map_irq, + qemu_irq *pic, int devfn_min, int nirq) +{ + SHPCIC *p; + int mem, reg, iop; + + p = qemu_mallocz(sizeof(SHPCIC)); + p->bus = pci_register_bus(set_irq, map_irq, pic, devfn_min, nirq); + + p->dev = pci_register_device(p->bus, "SH PCIC", sizeof(PCIDevice), + -1, NULL, NULL); + p->regbase = 0x1e200000; + p->iopbase = 0x1e240000; + p->membase = 0xfd000000; + reg = cpu_register_io_memory(0, sh_pci_reg.r, sh_pci_reg.w, p); + mem = cpu_register_io_memory(0, sh_pci_mem.r, sh_pci_mem.w, p); + iop = cpu_register_io_memory(0, sh_pci_iop.r, sh_pci_iop.w, p); + cpu_register_physical_memory(p->regbase, 0x224, reg); + cpu_register_physical_memory(p->iopbase, 0x40000, iop); + cpu_register_physical_memory(p->membase, 0x1000000, mem); + + p->dev->config[0x00] = 0x54; // HITACHI + p->dev->config[0x01] = 0x10; // + p->dev->config[0x02] = 0x0e; // SH7751R + p->dev->config[0x03] = 0x35; // + p->dev->config[0x04] = 0x80; + p->dev->config[0x05] = 0x00; + p->dev->config[0x06] = 0x90; + p->dev->config[0x07] = 0x02; + + return p->bus; +} diff --git a/qemu/hw/sh_serial.c b/qemu/hw/sh_serial.c index 8397739d..da1a2ca7 100644 --- a/qemu/hw/sh_serial.c +++ b/qemu/hw/sh_serial.c @@ -167,19 +167,19 @@ static void sh_serial_ioport_write(void *opaque, uint32_t offs, uint32_t val) } } else { -#if 0 switch(offs) { +#if 0 case 0x0c: ret = s->dr; break; case 0x10: ret = 0; break; +#endif case 0x1c: - ret = s->sptr; - break; + s->sptr = val & 0x8f; + return; } -#endif } fprintf(stderr, "sh_serial: unsupported write to 0x%02x\n", offs); @@ -259,8 +259,8 @@ static uint32_t sh_serial_ioport_read(void *opaque, uint32_t offs) } } else { -#if 0 switch(offs) { +#if 0 case 0x0c: ret = s->dr; break; @@ -270,11 +270,11 @@ static uint32_t sh_serial_ioport_read(void *opaque, uint32_t offs) case 0x14: ret = s->rx_fifo[0]; break; +#endif case 0x1c: ret = s->sptr; break; } -#endif } #ifdef DEBUG_SERIAL printf("sh_serial: read offs=0x%02x val=0x%x\n", @@ -399,7 +399,8 @@ void sh_serial_init (target_phys_addr_t base, int feat, s_io_memory = cpu_register_io_memory(0, sh_serial_readfn, sh_serial_writefn, s); - cpu_register_physical_memory(base, 0x28, s_io_memory); + cpu_register_physical_memory(P4ADDR(base), 0x28, s_io_memory); + cpu_register_physical_memory(A7ADDR(base), 0x28, s_io_memory); s->chr = chr; diff --git a/qemu/hw/sh_timer.c b/qemu/hw/sh_timer.c index 4557a835..c5c45f50 100644 --- a/qemu/hw/sh_timer.c +++ b/qemu/hw/sh_timer.c @@ -320,6 +320,7 @@ void tmu012_init(target_phys_addr_t base, int feat, uint32_t freq, ch2_irq0); /* ch2_irq1 not supported */ iomemtype = cpu_register_io_memory(0, tmu012_readfn, tmu012_writefn, s); - cpu_register_physical_memory(base, 0x00001000, iomemtype); + cpu_register_physical_memory(P4ADDR(base), 0x00001000, iomemtype); + cpu_register_physical_memory(A7ADDR(base), 0x00001000, iomemtype); /* ??? Save/restore. */ } diff --git a/qemu/hw/slavio_intctl.c b/qemu/hw/slavio_intctl.c index 4e08c6a0..0729c2ab 100644 --- a/qemu/hw/slavio_intctl.c +++ b/qemu/hw/slavio_intctl.c @@ -421,4 +421,3 @@ void *slavio_intctl_init(target_phys_addr_t addr, target_phys_addr_t addrg, slavio_intctl_reset(s); return s; } - diff --git a/qemu/hw/sm501.c b/qemu/hw/sm501.c index de610752..54d176b8 100644 --- a/qemu/hw/sm501.c +++ b/qemu/hw/sm501.c @@ -27,6 +27,7 @@ #include "hw.h" #include "pc.h" #include "console.h" +#include "devices.h" /* * Status: 2008/11/02 @@ -638,6 +639,32 @@ static CPUWriteMemoryFunc *sm501_system_config_writefn[] = { &sm501_system_config_write, }; +static uint32_t sm501_palette_read(void *opaque, target_phys_addr_t addr) +{ + SM501State * s = (SM501State *)opaque; + SM501_DPRINTF("sm501 palette read addr=%x\n", (int)addr); + + /* TODO : consider BYTE/WORD access */ + /* TODO : consider endian */ + + assert(0 <= addr && addr < 0x400 * 3); + return *(uint32_t*)&s->dc_palette[addr]; +} + +static void sm501_palette_write(void *opaque, + target_phys_addr_t addr, uint32_t value) +{ + SM501State * s = (SM501State *)opaque; + SM501_DPRINTF("sm501 palette write addr=%x, val=%x\n", + (int)addr, value); + + /* TODO : consider BYTE/WORD access */ + /* TODO : consider endian */ + + assert(0 <= addr && addr < 0x400 * 3); + *(uint32_t*)&s->dc_palette[addr] = value; +} + static uint32_t sm501_disp_ctrl_read(void *opaque, target_phys_addr_t addr) { SM501State * s = (SM501State *)opaque; @@ -719,6 +746,10 @@ static uint32_t sm501_disp_ctrl_read(void *opaque, target_phys_addr_t addr) ret = s->dc_crt_hwc_addr; break; + case SM501_DC_PANEL_PALETTE ... SM501_DC_PANEL_PALETTE + 0x400*3 - 4: + ret = sm501_palette_read(opaque, addr - SM501_DC_PANEL_PALETTE); + break; + default: printf("sm501 disp ctrl : not implemented register read." " addr=%x\n", (int)addr); @@ -823,6 +854,10 @@ static void sm501_disp_ctrl_write(void *opaque, s->dc_crt_hwc_addr = value & 0x0000FFFF; break; + case SM501_DC_PANEL_PALETTE ... SM501_DC_PANEL_PALETTE + 0x400*3 - 4: + sm501_palette_write(opaque, addr - SM501_DC_PANEL_PALETTE, value); + break; + default: printf("sm501 disp ctrl : not implemented register write." " addr=%x, val=%x\n", (int)addr, value); @@ -842,45 +877,6 @@ static CPUWriteMemoryFunc *sm501_disp_ctrl_writefn[] = { &sm501_disp_ctrl_write, }; -static uint32_t sm501_palette_read(void *opaque, target_phys_addr_t addr) -{ - SM501State * s = (SM501State *)opaque; - SM501_DPRINTF("sm501 palette read addr=%x\n", (int)addr); - - /* TODO : consider BYTE/WORD access */ - /* TODO : consider endian */ - - assert(0 <= addr && addr < 0x400 * 3); - return *(uint32_t*)&s->dc_palette[addr]; -} - -static void sm501_palette_write(void *opaque, - target_phys_addr_t addr, uint32_t value) -{ - SM501State * s = (SM501State *)opaque; - SM501_DPRINTF("sm501 palette write addr=%x, val=%x\n", - (int)addr, value); - - /* TODO : consider BYTE/WORD access */ - /* TODO : consider endian */ - - assert(0 <= addr && addr < 0x400 * 3); - *(uint32_t*)&s->dc_palette[addr] = value; -} - -static CPUReadMemoryFunc *sm501_palette_readfn[] = { - &sm501_palette_read, - &sm501_palette_read, - &sm501_palette_read, -}; - -static CPUWriteMemoryFunc *sm501_palette_writefn[] = { - &sm501_palette_write, - &sm501_palette_write, - &sm501_palette_write, -}; - - /* draw line functions for all console modes */ #include "pixel_ops.h" @@ -1070,7 +1066,6 @@ void sm501_init(DisplayState *ds, uint32_t base, unsigned long local_mem_base, SM501State * s; int sm501_system_config_index; int sm501_disp_ctrl_index; - int sm501_palette_index; /* allocate management data region */ s = (SM501State *)qemu_mallocz(sizeof(SM501State)); @@ -1098,13 +1093,7 @@ void sm501_init(DisplayState *ds, uint32_t base, unsigned long local_mem_base, sm501_disp_ctrl_index = cpu_register_io_memory(0, sm501_disp_ctrl_readfn, sm501_disp_ctrl_writefn, s); cpu_register_physical_memory(base + MMIO_BASE_OFFSET + SM501_DC, - 0x400, sm501_disp_ctrl_index); - - sm501_palette_index = cpu_register_io_memory(0, sm501_palette_readfn, - sm501_palette_writefn, s); - cpu_register_physical_memory(base + MMIO_BASE_OFFSET - + SM501_DC + SM501_DC_PANEL_PALETTE, - 0x400 * 3, sm501_palette_index); + 0x1000, sm501_disp_ctrl_index); /* bridge to serial emulation module */ if (chr) diff --git a/qemu/hw/sm501_template.h b/qemu/hw/sm501_template.h index c96ac253..1679df7b 100644 --- a/qemu/hw/sm501_template.h +++ b/qemu/hw/sm501_template.h @@ -101,4 +101,3 @@ static void glue(draw_line32_, PIXEL_NAME)( #undef PIXEL_TYPE #undef PIXEL_NAME #undef BGR_FORMAT - diff --git a/qemu/hw/smbus.h b/qemu/hw/smbus.h index b6b06624..640377b0 100644 --- a/qemu/hw/smbus.h +++ b/qemu/hw/smbus.h @@ -67,4 +67,3 @@ void smbus_write_block(i2c_bus *bus, int addr, uint8_t command, uint8_t *data, /* smbus_eeprom.c */ void smbus_eeprom_device_init(i2c_bus *bus, uint8_t addr, uint8_t *buf); - diff --git a/qemu/hw/spitz.c b/qemu/hw/spitz.c index e551fa68..85b48297 100644 --- a/qemu/hw/spitz.c +++ b/qemu/hw/spitz.c @@ -699,7 +699,7 @@ static void spitz_ssp_attach(struct pxa2xx_state_s *cpu) /* CF Microdrive */ -static void spitz_microdrive_attach(struct pxa2xx_state_s *cpu) +static void spitz_microdrive_attach(struct pxa2xx_state_s *cpu, int slot) { struct pcmcia_card_s *md; int index; @@ -711,7 +711,7 @@ static void spitz_microdrive_attach(struct pxa2xx_state_s *cpu) bs = drives_table[index].bdrv; if (bdrv_is_inserted(bs) && !bdrv_is_removable(bs)) { md = dscm1xxxx_init(bs); - pxa2xx_pcmcia_attach(cpu->pcmcia[1], md); + pxa2xx_pcmcia_attach(cpu->pcmcia[slot], md); } } @@ -952,10 +952,10 @@ static void spitz_common_init(ram_addr_t ram_size, int vga_ram_size, if (model == terrier) /* A 6.0 GB microdrive is permanently sitting in CF slot 1. */ - spitz_microdrive_attach(cpu); + spitz_microdrive_attach(cpu, 1); else if (model != akita) - /* A 4.0 GB microdrive is permanently sitting in CF slot 1. */ - spitz_microdrive_attach(cpu); + /* A 4.0 GB microdrive is permanently sitting in CF slot 0. */ + spitz_microdrive_attach(cpu, 0); /* Setup initial (reset) machine state */ cpu->env->regs[15] = spitz_binfo.loader_start; diff --git a/qemu/hw/ssi-sd.c b/qemu/hw/ssi-sd.c index 1c57f1f2..ffb9c4cd 100644 --- a/qemu/hw/ssi-sd.c +++ b/qemu/hw/ssi-sd.c @@ -237,4 +237,3 @@ void *ssi_sd_init(BlockDriverState *bs) register_savevm("ssi_sd", -1, 1, ssi_sd_save, ssi_sd_load, s); return s; } - diff --git a/qemu/hw/stellaris_input.c b/qemu/hw/stellaris_input.c index aef4ce0c..33395a42 100644 --- a/qemu/hw/stellaris_input.c +++ b/qemu/hw/stellaris_input.c @@ -89,5 +89,3 @@ void stellaris_gamepad_init(int n, qemu_irq *irq, const int *keycode) register_savevm("stellaris_gamepad", -1, 1, stellaris_gamepad_save, stellaris_gamepad_load, s); } - - diff --git a/qemu/hw/sun4c_intctl.c b/qemu/hw/sun4c_intctl.c index c8c40c9f..dd427776 100644 --- a/qemu/hw/sun4c_intctl.c +++ b/qemu/hw/sun4c_intctl.c @@ -221,4 +221,3 @@ void *sun4c_intctl_init(target_phys_addr_t addr, qemu_irq **irq, sun4c_intctl_reset(s); return s; } - diff --git a/qemu/hw/sun4m.c b/qemu/hw/sun4m.c index 2035b6c9..4028ff29 100644 --- a/qemu/hw/sun4m.c +++ b/qemu/hw/sun4m.c @@ -1646,4 +1646,3 @@ QEMUMachine ss2_machine = { .nodisk_ok = 1, .use_scsi = 1, }; - diff --git a/qemu/hw/tc6393xb_template.h b/qemu/hw/tc6393xb_template.h index 587382ee..c0c4cde1 100644 --- a/qemu/hw/tc6393xb_template.h +++ b/qemu/hw/tc6393xb_template.h @@ -69,4 +69,3 @@ static void glue(tc6393xb_draw_graphic, BITS)(struct tc6393xb_s *s) #undef BITS #undef SET_PIXEL - diff --git a/qemu/hw/unin_pci.c b/qemu/hw/unin_pci.c index 60fdea89..a835e172 100644 --- a/qemu/hw/unin_pci.c +++ b/qemu/hw/unin_pci.c @@ -268,4 +268,3 @@ PCIBus *pci_pmac_init(qemu_irq *pic) #endif return s->bus; } - diff --git a/qemu/hw/versatile_pci.c b/qemu/hw/versatile_pci.c index 67cee88e..1f4c1f30 100644 --- a/qemu/hw/versatile_pci.c +++ b/qemu/hw/versatile_pci.c @@ -141,4 +141,3 @@ PCIBus *pci_vpb_init(qemu_irq *pic, int irq, int realview) return s; } - diff --git a/qemu/hw/vga.c b/qemu/hw/vga.c index 9c9cf148..f1e50006 100644 --- a/qemu/hw/vga.c +++ b/qemu/hw/vga.c @@ -2417,8 +2417,7 @@ void vga_init(VGAState *s) vga_io_memory = cpu_register_io_memory(0, vga_mem_read, vga_mem_write, s); cpu_register_physical_memory(isa_mem_base + 0x000a0000, 0x20000, vga_io_memory); - if (kvm_enabled()) - qemu_kvm_register_coalesced_mmio(isa_mem_base + 0x000a0000, 0x20000); + qemu_register_coalesced_mmio(isa_mem_base + 0x000a0000, 0x20000); } /* Memory mapped interface */ @@ -2493,8 +2492,7 @@ static void vga_mm_init(VGAState *s, target_phys_addr_t vram_base, cpu_register_physical_memory(ctrl_base, 0x100000, s_ioport_ctrl); s->bank_offset = 0; cpu_register_physical_memory(vram_base + 0x000a0000, 0x20000, vga_io_memory); - if (kvm_enabled()) - qemu_kvm_register_coalesced_mmio(vram_base + 0x000a0000, 0x20000); + qemu_register_coalesced_mmio(vram_base + 0x000a0000, 0x20000); } int isa_vga_init(DisplayState *ds, uint8_t *vga_ram_base, diff --git a/qemu/hw/virtio-balloon.c b/qemu/hw/virtio-balloon.c index 9393db19..24d387f3 100644 --- a/qemu/hw/virtio-balloon.c +++ b/qemu/hw/virtio-balloon.c @@ -173,7 +173,8 @@ void *virtio_balloon_init(PCIBus *bus) VirtIOBalloon *s; s = (VirtIOBalloon *)virtio_init_pci(bus, "virtio-balloon", - 6900, 0x1002, + PCI_VENDOR_ID_REDHAT_QUMRANET, + PCI_DEVICE_ID_VIRTIO_BALLOON, 0, VIRTIO_ID_BALLOON, 0x05, 0x00, 0x00, 8, sizeof(VirtIOBalloon)); diff --git a/qemu/hw/virtio-blk.c b/qemu/hw/virtio-blk.c index bd965f92..bcc58548 100644 --- a/qemu/hw/virtio-blk.c +++ b/qemu/hw/virtio-blk.c @@ -218,14 +218,15 @@ static int virtio_blk_load(QEMUFile *f, void *opaque, int version_id) return 0; } -void *virtio_blk_init(PCIBus *bus, uint16_t vendor, uint16_t device, - BlockDriverState *bs) +void *virtio_blk_init(PCIBus *bus, BlockDriverState *bs) { VirtIOBlock *s; int cylinders, heads, secs; static int virtio_blk_id; - s = (VirtIOBlock *)virtio_init_pci(bus, "virtio-blk", vendor, device, + s = (VirtIOBlock *)virtio_init_pci(bus, "virtio-blk", + PCI_VENDOR_ID_REDHAT_QUMRANET, + PCI_DEVICE_ID_VIRTIO_BLOCK, 0, VIRTIO_ID_BLOCK, 0x01, 0x80, 0x00, sizeof(struct virtio_blk_config), sizeof(VirtIOBlock)); diff --git a/qemu/hw/virtio-blk.h b/qemu/hw/virtio-blk.h index c6661c0a..8c91e1ec 100644 --- a/qemu/hw/virtio-blk.h +++ b/qemu/hw/virtio-blk.h @@ -70,7 +70,6 @@ struct virtio_blk_inhdr unsigned char status; }; -void *virtio_blk_init(PCIBus *bus, uint16_t vendor, uint16_t device, - BlockDriverState *bs); +void *virtio_blk_init(PCIBus *bus, BlockDriverState *bs); #endif diff --git a/qemu/hw/virtio.c b/qemu/hw/virtio.c index 1d06fcc9..35f46696 100644 --- a/qemu/hw/virtio.c +++ b/qemu/hw/virtio.c @@ -485,7 +485,7 @@ static void virtio_update_irq(VirtIODevice *vdev) qemu_set_irq(vdev->pci_dev.irq[0], vdev->isr & 1); } -void virtio_reset(void *opaque) +static void virtio_reset(void *opaque) { VirtIODevice *vdev = opaque; int i; @@ -858,7 +858,7 @@ VirtIODevice *virtio_init_pci(PCIBus *bus, const char *name, size = 20 + config_size; if (size & (size-1)) - size = 1 << fls(size); + size = 1 << qemu_fls(size); pci_register_io_region(pci_dev, 0, size, PCI_ADDRESS_SPACE_IO, virtio_map); diff --git a/qemu/hw/vmmouse.c b/qemu/hw/vmmouse.c index 0a93b15e..52493936 100644 --- a/qemu/hw/vmmouse.c +++ b/qemu/hw/vmmouse.c @@ -288,4 +288,3 @@ void *vmmouse_init(void *m) return s; } - diff --git a/qemu/keymaps/et b/qemu/keymaps/et index 3252e31c..85541a37 100644 --- a/qemu/keymaps/et +++ b/qemu/keymaps/et @@ -83,4 +83,3 @@ period 0x34 colon 0x34 shift minus 0x35 underscore 0x35 shift - diff --git a/qemu/keymaps/fo b/qemu/keymaps/fo index 83add423..c00d9d4d 100644 --- a/qemu/keymaps/fo +++ b/qemu/keymaps/fo @@ -74,4 +74,3 @@ period 0x34 colon 0x34 shift minus 0x35 underscore 0x35 shift - diff --git a/qemu/keymaps/is b/qemu/keymaps/is index d512cf66..21dc1fd3 100644 --- a/qemu/keymaps/is +++ b/qemu/keymaps/is @@ -137,4 +137,3 @@ thorn 0x35 THORN 0x35 shift dead_belowdot 0x35 altgr dead_abovedot 0x35 shift altgr - diff --git a/qemu/keymaps/nl b/qemu/keymaps/nl index 4f0fe3df..b4892f93 100644 --- a/qemu/keymaps/nl +++ b/qemu/keymaps/nl @@ -57,4 +57,3 @@ equal 0x35 shift bracketright 0x56 bracketleft 0x56 shift brokenbar 0x56 altgr - diff --git a/qemu/keymaps/sv b/qemu/keymaps/sv index 9905a48d..5d9080ef 100644 --- a/qemu/keymaps/sv +++ b/qemu/keymaps/sv @@ -79,4 +79,3 @@ period 0x34 colon 0x34 shift minus 0x35 underscore 0x35 shift - diff --git a/qemu/kvm-all.c b/qemu/kvm-all.c index 69ca46b1..dad80df5 100644 --- a/qemu/kvm-all.c +++ b/qemu/kvm-all.c @@ -24,6 +24,9 @@ #include "sysemu.h" #include "kvm.h" +/* KVM uses PAGE_SIZE in it's definition of COALESCED_MMIO_MAX */ +#define PAGE_SIZE TARGET_PAGE_SIZE + //#define DEBUG_KVM #ifdef DEBUG_KVM @@ -52,6 +55,7 @@ struct KVMState KVMSlot slots[32]; int fd; int vmfd; + int coalesced_mmio; }; static KVMState *kvm_state; @@ -228,6 +232,44 @@ out: qemu_free(d.dirty_bitmap); } +int kvm_coalesce_mmio_region(target_phys_addr_t start, ram_addr_t size) +{ + int ret = -ENOSYS; +#ifdef KVM_CAP_COALESCED_MMIO + KVMState *s = kvm_state; + + if (s->coalesced_mmio) { + struct kvm_coalesced_mmio_zone zone; + + zone.addr = start; + zone.size = size; + + ret = kvm_vm_ioctl(s, KVM_REGISTER_COALESCED_MMIO, &zone); + } +#endif + + return ret; +} + +int kvm_uncoalesce_mmio_region(target_phys_addr_t start, ram_addr_t size) +{ + int ret = -ENOSYS; +#ifdef KVM_CAP_COALESCED_MMIO + KVMState *s = kvm_state; + + if (s->coalesced_mmio) { + struct kvm_coalesced_mmio_zone zone; + + zone.addr = start; + zone.size = size; + + ret = kvm_vm_ioctl(s, KVM_UNREGISTER_COALESCED_MMIO, &zone); + } +#endif + + return ret; +} + int kvm_init(int smp_cpus) { KVMState *s; @@ -283,6 +325,28 @@ int kvm_init(int smp_cpus) goto err; } + /* There was a nasty bug in < kvm-80 that prevents memory slots from being + * destroyed properly. Since we rely on this capability, refuse to work + * with any kernel without this capability. */ + ret = kvm_ioctl(s, KVM_CHECK_EXTENSION, + KVM_CAP_DESTROY_MEMORY_REGION_WORKS); + if (ret <= 0) { + if (ret == 0) + ret = -EINVAL; + + fprintf(stderr, + "KVM kernel module broken (DESTROY_MEMORY_REGION)\n" + "Please upgrade to at least kvm-81.\n"); + goto err; + } + + s->coalesced_mmio = 0; +#ifdef KVM_CAP_COALESCED_MMIO + ret = kvm_ioctl(s, KVM_CHECK_EXTENSION, KVM_CAP_COALESCED_MMIO); + if (ret > 0) + s->coalesced_mmio = ret; +#endif + ret = kvm_arch_init(s, smp_cpus); if (ret < 0) goto err; @@ -342,6 +406,27 @@ static int kvm_handle_io(CPUState *env, uint16_t port, void *data, return 1; } +static void kvm_run_coalesced_mmio(CPUState *env, struct kvm_run *run) +{ +#ifdef KVM_CAP_COALESCED_MMIO + KVMState *s = kvm_state; + if (s->coalesced_mmio) { + struct kvm_coalesced_mmio_ring *ring; + + ring = (void *)run + (s->coalesced_mmio * TARGET_PAGE_SIZE); + while (ring->first != ring->last) { + struct kvm_coalesced_mmio *ent; + + ent = &ring->coalesced_mmio[ring->first]; + + cpu_physical_memory_write(ent->phys_addr, ent->data, ent->len); + /* FIXME smp_wmb() */ + ring->first = (ring->first + 1) % KVM_COALESCED_MMIO_MAX; + } + } +#endif +} + int kvm_cpu_exec(CPUState *env) { struct kvm_run *run = env->kvm_run; @@ -372,6 +457,8 @@ int kvm_cpu_exec(CPUState *env) abort(); } + kvm_run_coalesced_mmio(env, run); + ret = 0; /* exit loop */ switch (run->exit_reason) { case KVM_EXIT_IO: @@ -47,6 +47,9 @@ int kvm_log_stop(target_phys_addr_t phys_addr, target_phys_addr_t len); int kvm_has_sync_mmu(void); +int kvm_coalesce_mmio_region(target_phys_addr_t start, ram_addr_t size); +int kvm_uncoalesce_mmio_region(target_phys_addr_t start, ram_addr_t size); + /* internal API */ struct KVMState; diff --git a/qemu/linux-user/alpha/termbits.h b/qemu/linux-user/alpha/termbits.h index 68587115..6406b6a7 100644 --- a/qemu/linux-user/alpha/termbits.h +++ b/qemu/linux-user/alpha/termbits.h @@ -262,4 +262,3 @@ struct target_termios { #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 */ - diff --git a/qemu/linux-user/arm/nwfpe/fpa11.c b/qemu/linux-user/arm/nwfpe/fpa11.c index beed9687..eb006f0d 100644 --- a/qemu/linux-user/arm/nwfpe/fpa11.c +++ b/qemu/linux-user/arm/nwfpe/fpa11.c @@ -241,4 +241,3 @@ unsigned int EmulateAll1(unsigned int opcode) } } #endif - diff --git a/qemu/linux-user/arm/termbits.h b/qemu/linux-user/arm/termbits.h index f018c075..7772df17 100644 --- a/qemu/linux-user/arm/termbits.h +++ b/qemu/linux-user/arm/termbits.h @@ -214,4 +214,3 @@ struct target_termios { #define TARGET_TIOCPKT_DOSTOP 32 #define TARGET_TIOCSER_TEMT 0x01 /* Transmitter physically empty */ - diff --git a/qemu/linux-user/cris/syscall.h b/qemu/linux-user/cris/syscall.h index 8fa7474f..24f92ba4 100644 --- a/qemu/linux-user/cris/syscall.h +++ b/qemu/linux-user/cris/syscall.h @@ -34,4 +34,3 @@ struct target_pt_regs { unsigned long exs; unsigned long eda; }; - diff --git a/qemu/linux-user/cris/termbits.h b/qemu/linux-user/cris/termbits.h index adff8024..fc82ca08 100644 --- a/qemu/linux-user/cris/termbits.h +++ b/qemu/linux-user/cris/termbits.h @@ -211,4 +211,3 @@ struct target_termios { #define TARGET_TIOCPKT_DOSTOP 32 #define TARGET_TIOCSER_TEMT 0x01 /* Transmitter physically empty */ - diff --git a/qemu/linux-user/errno_defs.h b/qemu/linux-user/errno_defs.h index 209c1870..8a1cf76c 100644 --- a/qemu/linux-user/errno_defs.h +++ b/qemu/linux-user/errno_defs.h @@ -139,4 +139,3 @@ /* for robust mutexes */ #define TARGET_EOWNERDEAD 130 /* Owner died */ #define TARGET_ENOTRECOVERABLE 131 /* State not recoverable */ - diff --git a/qemu/linux-user/i386/termbits.h b/qemu/linux-user/i386/termbits.h index 4acd2bda..e051a3af 100644 --- a/qemu/linux-user/i386/termbits.h +++ b/qemu/linux-user/i386/termbits.h @@ -224,4 +224,3 @@ struct target_termios { #define TARGET_TIOCPKT_DOSTOP 32 #define TARGET_TIOCSER_TEMT 0x01 /* Transmitter physically empty */ - diff --git a/qemu/linux-user/m68k/termbits.h b/qemu/linux-user/m68k/termbits.h index 1bce39d8..f7982fb6 100644 --- a/qemu/linux-user/m68k/termbits.h +++ b/qemu/linux-user/m68k/termbits.h @@ -225,4 +225,3 @@ struct target_termios { #define TARGET_TIOCPKT_DOSTOP 32 #define TARGET_TIOCSER_TEMT 0x01 /* Transmitter physically empty */ - diff --git a/qemu/linux-user/main.c b/qemu/linux-user/main.c index a1182164..3d2d4e5d 100644 --- a/qemu/linux-user/main.c +++ b/qemu/linux-user/main.c @@ -27,6 +27,7 @@ #include "qemu.h" #include "qemu-common.h" +#include "cache-utils.h" /* For tb_lock */ #include "exec-all.h" @@ -2215,7 +2216,7 @@ void init_task_state(TaskState *ts) ts->sigqueue_table[i].next = NULL; } -int main(int argc, char **argv) +int main(int argc, char **argv, char **envp) { const char *filename; const char *cpu_model; @@ -2232,6 +2233,8 @@ int main(int argc, char **argv) if (argc <= 1) usage(); + qemu_cache_utils_init(envp); + /* init debug */ cpu_set_log_filename(DEBUG_LOGFILE); diff --git a/qemu/linux-user/mmap.c b/qemu/linux-user/mmap.c index d5f22b82..00a941e3 100644 --- a/qemu/linux-user/mmap.c +++ b/qemu/linux-user/mmap.c @@ -382,6 +382,16 @@ abi_long target_mmap(abi_ulong start, abi_ulong len, int prot, end = start + len; real_end = HOST_PAGE_ALIGN(end); + /* + * Test if requested memory area fits target address space + * It can fail only on 64-bit host with 32-bit target. + * On any other target/host host mmap() handles this error correctly. + */ + if ((unsigned long)start + len - 1 > (abi_ulong) -1) { + errno = EINVAL; + goto fail; + } + for(addr = real_start; addr < real_end; addr += TARGET_PAGE_SIZE) { flg = page_get_flags(addr); if (flg & PAGE_RESERVED) { @@ -527,19 +537,44 @@ int target_munmap(abi_ulong start, abi_ulong len) return ret; } -/* XXX: currently, we only handle MAP_ANONYMOUS and not MAP_FIXED - blocks which have been allocated starting on a host page */ 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; + void *host_addr; mmap_lock(); - /* XXX: use 5 args syscall */ - host_addr = (long)mremap(g2h(old_addr), old_size, new_size, flags); - if (host_addr == -1) { + +#if defined(MREMAP_FIXED) + if (flags & MREMAP_FIXED) + host_addr = mremap(g2h(old_addr), old_size, new_size, + flags, new_addr); + else if (flags & MREMAP_MAYMOVE) { + abi_ulong mmap_start; + + mmap_start = mmap_find_vma(0, new_size); + + if (mmap_start == -1) { + errno = ENOMEM; + host_addr = MAP_FAILED; + } else + host_addr = mremap(g2h(old_addr), old_size, new_size, + flags | MREMAP_FIXED, g2h(mmap_start)); + } else +#endif + { + host_addr = mremap(g2h(old_addr), old_size, new_size, flags); + /* Check if address fits target address space */ + if ((unsigned long)host_addr + new_size > (abi_ulong)-1) { + /* Revert mremap() changes */ + host_addr = mremap(g2h(old_addr), new_size, old_size, flags); + errno = ENOMEM; + host_addr = MAP_FAILED; + } + } + + if (host_addr == MAP_FAILED) { new_addr = -1; } else { new_addr = h2g(host_addr); diff --git a/qemu/linux-user/ppc/termbits.h b/qemu/linux-user/ppc/termbits.h index 002de956..73e71517 100644 --- a/qemu/linux-user/ppc/termbits.h +++ b/qemu/linux-user/ppc/termbits.h @@ -234,4 +234,3 @@ struct target_termios { #define TARGET_TIOCMIWAIT 0x545C /* wait for a change on serial input line(s) */ #define TARGET_TIOCGICOUNT 0x545D /* read serial port inline interrupt counts */ - diff --git a/qemu/linux-user/qemu-types.h b/qemu/linux-user/qemu-types.h new file mode 100644 index 00000000..1adda9fb --- /dev/null +++ b/qemu/linux-user/qemu-types.h @@ -0,0 +1,24 @@ +#ifndef QEMU_TYPES_H +#define QEMU_TYPES_H +#include "cpu.h" + +#ifdef TARGET_ABI32 +typedef uint32_t abi_ulong; +typedef int32_t abi_long; +#define TARGET_ABI_FMT_lx "%08x" +#define TARGET_ABI_FMT_ld "%d" +#define TARGET_ABI_FMT_lu "%u" +#define TARGET_ABI_BITS 32 +#else +typedef target_ulong abi_ulong; +typedef target_long abi_long; +#define TARGET_ABI_FMT_lx TARGET_FMT_lx +#define TARGET_ABI_FMT_ld TARGET_FMT_ld +#define TARGET_ABI_FMT_lu TARGET_FMT_lu +#define TARGET_ABI_BITS TARGET_LONG_BITS +/* for consistency, define ABI32 too */ +#if TARGET_ABI_BITS == 32 +#define TARGET_ABI32 1 +#endif +#endif +#endif diff --git a/qemu/linux-user/qemu.h b/qemu/linux-user/qemu.h index a2abe517..9fddd051 100644 --- a/qemu/linux-user/qemu.h +++ b/qemu/linux-user/qemu.h @@ -11,25 +11,7 @@ #include <stdlib.h> #endif /* DEBUG_REMAP */ -#ifdef TARGET_ABI32 -typedef uint32_t abi_ulong; -typedef int32_t abi_long; -#define TARGET_ABI_FMT_lx "%08x" -#define TARGET_ABI_FMT_ld "%d" -#define TARGET_ABI_FMT_lu "%u" -#define TARGET_ABI_BITS 32 -#else -typedef target_ulong abi_ulong; -typedef target_long abi_long; -#define TARGET_ABI_FMT_lx TARGET_FMT_lx -#define TARGET_ABI_FMT_ld TARGET_FMT_ld -#define TARGET_ABI_FMT_lu TARGET_FMT_lu -#define TARGET_ABI_BITS TARGET_LONG_BITS -/* for consistency, define ABI32 too */ -#if TARGET_ABI_BITS == 32 -#define TARGET_ABI32 1 -#endif -#endif +#include "qemu-types.h" #include "thunk.h" #include "syscall_defs.h" diff --git a/qemu/linux-user/sparc/termbits.h b/qemu/linux-user/sparc/termbits.h index ed9ab245..691600d2 100644 --- a/qemu/linux-user/sparc/termbits.h +++ b/qemu/linux-user/sparc/termbits.h @@ -277,4 +277,3 @@ struct target_termios { #define TARGET_TIOCSERSETMULTI 0x545B /* Set multiport config */ #define TARGET_TIOCMIWAIT 0x545C /* Wait input */ #define TARGET_TIOCGICOUNT 0x545D /* Read serial port inline interrupt counts */ - diff --git a/qemu/linux-user/sparc64/termbits.h b/qemu/linux-user/sparc64/termbits.h index ed9ab245..691600d2 100644 --- a/qemu/linux-user/sparc64/termbits.h +++ b/qemu/linux-user/sparc64/termbits.h @@ -277,4 +277,3 @@ struct target_termios { #define TARGET_TIOCSERSETMULTI 0x545B /* Set multiport config */ #define TARGET_TIOCMIWAIT 0x545C /* Wait input */ #define TARGET_TIOCGICOUNT 0x545D /* Read serial port inline interrupt counts */ - diff --git a/qemu/linux-user/strace.c b/qemu/linux-user/strace.c index fca2f391..116726c5 100644 --- a/qemu/linux-user/strace.c +++ b/qemu/linux-user/strace.c @@ -314,4 +314,3 @@ print_syscall_ret(int num, abi_long ret) break; } } - diff --git a/qemu/linux-user/syscall.c b/qemu/linux-user/syscall.c index 40659178..73427abb 100644 --- a/qemu/linux-user/syscall.c +++ b/qemu/linux-user/syscall.c @@ -1614,12 +1614,14 @@ static abi_long do_socketcall(int num, abi_ulong vptr) } #endif +#ifdef TARGET_NR_ipc #define N_SHM_REGIONS 32 static struct shm_region { abi_ulong start; abi_ulong size; } shm_regions[N_SHM_REGIONS]; +#endif struct target_ipc_perm { diff --git a/qemu/linux-user/vm86.c b/qemu/linux-user/vm86.c index d87174b5..c9330389 100644 --- a/qemu/linux-user/vm86.c +++ b/qemu/linux-user/vm86.c @@ -485,4 +485,3 @@ int do_vm86(CPUX86State *env, long subfunction, abi_ulong vm86_addr) out: return ret; } - diff --git a/qemu/migration.h b/qemu/migration.h index 953ec704..d9771adb 100644 --- a/qemu/migration.h +++ b/qemu/migration.h @@ -95,4 +95,3 @@ static inline FdMigrationState *migrate_to_fms(MigrationState *mig_state) } #endif - diff --git a/qemu/monitor.c b/qemu/monitor.c index 3948aae3..0fa8547c 100644 --- a/qemu/monitor.c +++ b/qemu/monitor.c @@ -453,13 +453,16 @@ static void do_change_block(const char *device, const char *filename, const char qemu_key_check(bs, filename); } -static void do_change_vnc(const char *target) +static void do_change_vnc(const char *target, const char *arg) { if (strcmp(target, "passwd") == 0 || strcmp(target, "password") == 0) { char password[9]; - monitor_readline("Password: ", 1, password, sizeof(password)-1); - password[sizeof(password)-1] = '\0'; + if (arg) { + strncpy(password, arg, sizeof(password)); + password[sizeof(password) - 1] = '\0'; + } else + monitor_readline("Password: ", 1, password, sizeof(password)); if (vnc_display_password(NULL, password) < 0) term_printf("could not set VNC server password\n"); } else { @@ -468,12 +471,12 @@ static void do_change_vnc(const char *target) } } -static void do_change(const char *device, const char *target, const char *fmt) +static void do_change(const char *device, const char *target, const char *arg) { if (strcmp(device, "vnc") == 0) { - do_change_vnc(target); + do_change_vnc(target, arg); } else { - do_change_block(device, target, fmt); + do_change_block(device, target, arg); } } @@ -120,7 +120,7 @@ #define memalign(align, size) malloc(size) #endif -#include "qemu-kvm.h" +// FIXME: #include "qemu-kvm.h" #define DEFAULT_NETWORK_SCRIPT "/etc/qemu-ifup" #define DEFAULT_NETWORK_DOWN_SCRIPT "/etc/qemu-ifdown" @@ -286,8 +286,8 @@ int parse_host_port(struct sockaddr_in *saddr, const char *str) return 0; } -#ifndef _WIN32 -int parse_unix_path(struct sockaddr_un *uaddr, const char *str) +#if !defined(_WIN32) && 0 +static int parse_unix_path(struct sockaddr_un *uaddr, const char *str) { const char *p; int len; @@ -776,9 +776,9 @@ static void tap_send(void *opaque) sbuf.buf = s->buf; s->size = getmsg(s->fd, NULL, &sbuf, &f) >=0 ? sbuf.len : -1; #else - kvm_sleep_begin(); + // FIXME: kvm_sleep_begin(); s->size = read(s->fd, s->buf, sizeof(s->buf)); - kvm_sleep_end(); + // FIXME: kvm_sleep_end(); #endif if (s->size == -1 && errno == EINTR) diff --git a/qemu/osdep.c b/qemu/osdep.c index dc8c9d46..6e751c52 100644 --- a/qemu/osdep.c +++ b/qemu/osdep.c @@ -200,15 +200,11 @@ void *qemu_vmalloc(size_t size) if (kqemu_allowed) return kqemu_vmalloc(size); #endif -#ifdef _BSD - return valloc(size); -#else #ifndef __ia64__ return qemu_memalign(getpagesize(), size); #else return qemu_memalign(65536, size); #endif -#endif } void qemu_vfree(void *ptr) diff --git a/qemu/pc-bios/Makefile b/qemu/pc-bios/Makefile index 2d270f7f..61179034 100644 --- a/qemu/pc-bios/Makefile +++ b/qemu/pc-bios/Makefile @@ -17,4 +17,3 @@ all: $(TARGETS) clean: rm -f $(TARGETS) *.o *~ *.dtb - diff --git a/qemu/posix-aio-compat.c b/qemu/posix-aio-compat.c new file mode 100644 index 00000000..92ec2345 --- /dev/null +++ b/qemu/posix-aio-compat.c @@ -0,0 +1,201 @@ +/* + * QEMU posix-aio emulation + * + * Copyright IBM, Corp. 2008 + * + * Authors: + * Anthony Liguori <aliguori@us.ibm.com> + * + * This work is licensed under the terms of the GNU GPL, version 2. See + * the COPYING file in the top-level directory. + * + */ + +#include <pthread.h> +#include <unistd.h> +#include <errno.h> +#include <sys/time.h> +#include "osdep.h" + +#include "posix-aio-compat.h" + +static pthread_mutex_t lock = PTHREAD_MUTEX_INITIALIZER; +static pthread_cond_t cond = PTHREAD_COND_INITIALIZER; +static pthread_t thread_id; +static int max_threads = 64; +static int cur_threads = 0; +static int idle_threads = 0; +static TAILQ_HEAD(, qemu_paiocb) request_list; + +static void *aio_thread(void *unused) +{ + sigset_t set; + + /* block all signals */ + sigfillset(&set); + sigprocmask(SIG_BLOCK, &set, NULL); + + while (1) { + struct qemu_paiocb *aiocb; + size_t offset; + int ret = 0; + + pthread_mutex_lock(&lock); + + while (TAILQ_EMPTY(&request_list) && + !(ret == ETIMEDOUT)) { + struct timespec ts = { 0 }; + qemu_timeval tv; + + qemu_gettimeofday(&tv); + ts.tv_sec = tv.tv_sec + 10; + ret = pthread_cond_timedwait(&cond, &lock, &ts); + } + + if (ret == ETIMEDOUT) + break; + + aiocb = TAILQ_FIRST(&request_list); + TAILQ_REMOVE(&request_list, aiocb, node); + + offset = 0; + aiocb->active = 1; + + idle_threads--; + pthread_mutex_unlock(&lock); + + while (offset < aiocb->aio_nbytes) { + ssize_t len; + + if (aiocb->is_write) + len = pwrite(aiocb->aio_fildes, + (const char *)aiocb->aio_buf + offset, + aiocb->aio_nbytes - offset, + aiocb->aio_offset + offset); + else + len = pread(aiocb->aio_fildes, + (char *)aiocb->aio_buf + offset, + aiocb->aio_nbytes - offset, + aiocb->aio_offset + offset); + + if (len == -1 && errno == EINTR) + continue; + else if (len == -1) { + pthread_mutex_lock(&lock); + aiocb->ret = -errno; + pthread_mutex_unlock(&lock); + break; + } else if (len == 0) + break; + + offset += len; + + pthread_mutex_lock(&lock); + aiocb->ret = offset; + pthread_mutex_unlock(&lock); + } + + pthread_mutex_lock(&lock); + idle_threads++; + pthread_mutex_unlock(&lock); + + sigqueue(getpid(), + aiocb->aio_sigevent.sigev_signo, + aiocb->aio_sigevent.sigev_value); + } + + idle_threads--; + cur_threads--; + pthread_mutex_unlock(&lock); + + return NULL; +} + +static int spawn_thread(void) +{ + pthread_attr_t attr; + int ret; + + cur_threads++; + idle_threads++; + + pthread_attr_init(&attr); + pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED); + ret = pthread_create(&thread_id, &attr, aio_thread, NULL); + pthread_attr_destroy(&attr); + + return ret; +} + +int qemu_paio_init(struct qemu_paioinit *aioinit) +{ + TAILQ_INIT(&request_list); + + return 0; +} + +static int qemu_paio_submit(struct qemu_paiocb *aiocb, int is_write) +{ + aiocb->is_write = is_write; + aiocb->ret = -EINPROGRESS; + aiocb->active = 0; + pthread_mutex_lock(&lock); + if (idle_threads == 0 && cur_threads < max_threads) + spawn_thread(); + TAILQ_INSERT_TAIL(&request_list, aiocb, node); + pthread_mutex_unlock(&lock); + pthread_cond_broadcast(&cond); + + return 0; +} + +int qemu_paio_read(struct qemu_paiocb *aiocb) +{ + return qemu_paio_submit(aiocb, 0); +} + +int qemu_paio_write(struct qemu_paiocb *aiocb) +{ + return qemu_paio_submit(aiocb, 1); +} + +ssize_t qemu_paio_return(struct qemu_paiocb *aiocb) +{ + ssize_t ret; + + pthread_mutex_lock(&lock); + ret = aiocb->ret; + pthread_mutex_unlock(&lock); + + return ret; +} + +int qemu_paio_error(struct qemu_paiocb *aiocb) +{ + ssize_t ret = qemu_paio_return(aiocb); + + if (ret < 0) + ret = -ret; + else + ret = 0; + + return ret; +} + +int qemu_paio_cancel(int fd, struct qemu_paiocb *aiocb) +{ + int ret; + + pthread_mutex_lock(&lock); + if (!aiocb->active) { + TAILQ_REMOVE(&request_list, aiocb, node); + aiocb->ret = -ECANCELED; + ret = QEMU_PAIO_CANCELED; + } else if (aiocb->ret == -EINPROGRESS) + ret = QEMU_PAIO_NOTCANCELED; + else + ret = QEMU_PAIO_ALLDONE; + pthread_mutex_unlock(&lock); + + return ret; +} diff --git a/qemu/posix-aio-compat.h b/qemu/posix-aio-compat.h new file mode 100644 index 00000000..5dddd711 --- /dev/null +++ b/qemu/posix-aio-compat.h @@ -0,0 +1,56 @@ +/* + * QEMU posix-aio emulation + * + * Copyright IBM, Corp. 2008 + * + * Authors: + * Anthony Liguori <aliguori@us.ibm.com> + * + * This work is licensed under the terms of the GNU GPL, version 2. See + * the COPYING file in the top-level directory. + * + */ + +#ifndef QEMU_POSIX_AIO_COMPAT_H +#define QEMU_POSIX_AIO_COMPAT_H + +#include <sys/types.h> +#include <unistd.h> +#include <signal.h> + +#include "sys-queue.h" + +#define QEMU_PAIO_CANCELED 0x01 +#define QEMU_PAIO_NOTCANCELED 0x02 +#define QEMU_PAIO_ALLDONE 0x03 + +struct qemu_paiocb +{ + int aio_fildes; + void *aio_buf; + size_t aio_nbytes; + struct sigevent aio_sigevent; + off_t aio_offset; + + /* private */ + TAILQ_ENTRY(qemu_paiocb) node; + int is_write; + ssize_t ret; + int active; +}; + +struct qemu_paioinit +{ + unsigned int aio_threads; + unsigned int aio_num; + unsigned int aio_idle_time; +}; + +int qemu_paio_init(struct qemu_paioinit *aioinit); +int qemu_paio_read(struct qemu_paiocb *aiocb); +int qemu_paio_write(struct qemu_paiocb *aiocb); +int qemu_paio_error(struct qemu_paiocb *aiocb); +ssize_t qemu_paio_return(struct qemu_paiocb *aiocb); +int qemu_paio_cancel(int fd, struct qemu_paiocb *aiocb); + +#endif diff --git a/qemu/qemu-common.h b/qemu/qemu-common.h index cc40273d..5f75b2e7 100644 --- a/qemu/qemu-common.h +++ b/qemu/qemu-common.h @@ -104,9 +104,9 @@ char *pstrcat(char *buf, int buf_size, const char *s); int strstart(const char *str, const char *val, const char **ptr); int stristart(const char *str, const char *val, const char **ptr); time_t mktimegm(struct tm *tm); +int qemu_fls(int i); int hex2bin(char ch); char *urldecode(const char *ptr); -int fls(int i); #define qemu_isalnum(c) isalnum((unsigned char)(c)) #define qemu_isalpha(c) isalpha((unsigned char)(c)) diff --git a/qemu/qemu-doc.texi b/qemu/qemu-doc.texi index 6cf35be3..e004a261 100644 --- a/qemu/qemu-doc.texi +++ b/qemu/qemu-doc.texi @@ -81,7 +81,7 @@ For system emulation, the following hardware targets are supported: @item ARM Integrator/CP (ARM) @item ARM Versatile baseboard (ARM) @item ARM RealView Emulation baseboard (ARM) -@item Spitz, Akita, Borzoi and Terrier PDAs (PXA270 processor) +@item Spitz, Akita, Borzoi, Terrier and Tosa PDAs (PXA270 processor) @item Luminary Micro LM3S811EVB (ARM Cortex-M3) @item Luminary Micro LM3S6965EVB (ARM Cortex-M3) @item Freescale MCF5208EVB (ColdFire V2). @@ -89,6 +89,8 @@ For system emulation, the following hardware targets are supported: @item Palm Tungsten|E PDA (OMAP310 processor) @item N800 and N810 tablets (OMAP2420 processor) @item MusicPal (MV88W8618 ARM processor) +@item Gumstix "Connex" and "Verdex" motherboards (PXA255/270). +@item Siemens SX1 smartphone (OMAP310 processor) @end itemize For user emulation, x86, PowerPC, ARM, 32-bit MIPS, Sparc32/64 and ColdFire(m68k) CPUs are supported. @@ -1249,11 +1251,11 @@ and @var{options} are described at @ref{sec_invocation}. eg (qemu) change vnc localhost:1 @end example -@item change vnc password +@item change vnc password [@var{password}] -Change the password associated with the VNC server. The monitor will prompt for -the new password to be entered. VNC passwords are only significant upto 8 letters. -eg. +Change the password associated with the VNC server. If the new password is not +supplied, the monitor will prompt for it to be entered. VNC passwords are only +significant up to 8 letters. eg @example (qemu) change vnc password @@ -2806,6 +2808,28 @@ MV88W8618 audio controller, WM8750 CODEC and mixer 2 buttons, 2 navigation wheels with button function @end itemize +The Siemens SX1 models v1 and v2 (default) basic emulation. +The emulaton includes the following elements: + +@itemize @minus +@item +Texas Instruments OMAP310 System-on-chip (ARM 925T core) +@item +ROM and RAM memories (ROM firmware image can be loaded with -pflash) +V1 +1 Flash of 16MB and 1 Flash of 8MB +V2 +1 Flash of 32MB +@item +On-chip LCD controller +@item +On-chip Real Time Clock +@item +Secure Digital card connected to OMAP MMC/SD host +@item +Three on-chip UARTs +@end itemize + A Linux 2.6 test image is available on the QEMU web site. More information is available in the QEMU mailing-list archive. diff --git a/qemu/qemu-kvm.c b/qemu/qemu-kvm.c index c5a58807..e1088be6 100644 --- a/qemu/qemu-kvm.c +++ b/qemu/qemu-kvm.c @@ -1136,6 +1136,16 @@ int qemu_kvm_unregister_coalesced_mmio(target_phys_addr_t addr, return kvm_unregister_coalesced_mmio(kvm_context, addr, size); } +int kvm_coalesce_mmio_region(target_phys_addr_t start, ram_addr_t size) +{ + return kvm_register_coalesced_mmio(kvm_context, start, size); +} + +int kvm_uncoalesce_mmio_region(target_phys_addr_t start, ram_addr_t size) +{ + return kvm_unregister_coalesced_mmio(kvm_context, start, size); +} + #ifdef USE_KVM_DEVICE_ASSIGNMENT void kvm_add_ioperm_data(struct ioperm_data *data) { diff --git a/qemu/qemu-kvm.h b/qemu/qemu-kvm.h index 90fadcd2..745eed81 100644 --- a/qemu/qemu-kvm.h +++ b/qemu/qemu-kvm.h @@ -90,6 +90,9 @@ int qemu_kvm_unregister_coalesced_mmio(target_phys_addr_t addr, void qemu_kvm_system_reset_request(void); +int kvm_coalesce_mmio_region(target_phys_addr_t start, ram_addr_t size); +int kvm_uncoalesce_mmio_region(target_phys_addr_t start, ram_addr_t size); + #ifdef USE_KVM_DEVICE_ASSIGNMENT void kvm_ioperm(CPUState *env, void *data); void kvm_arch_do_ioperm(void *_data); diff --git a/qemu/readline.c b/qemu/readline.c index e1e963a2..7bf9a5e1 100644 --- a/qemu/readline.c +++ b/qemu/readline.c @@ -484,5 +484,3 @@ const char *readline_get_history(unsigned int index) return NULL; return term_history[index]; } - - diff --git a/qemu/s390-dis.c b/qemu/s390-dis.c index a447a197..fa247921 100644 --- a/qemu/s390-dis.c +++ b/qemu/s390-dis.c @@ -1708,4 +1708,3 @@ const struct s390_opcode s390_opcodes[] = const int s390_num_opcodes = sizeof (s390_opcodes) / sizeof (s390_opcodes[0]); - diff --git a/qemu/s390.ld b/qemu/s390.ld index 7f14ea91..ccae2e71 100644 --- a/qemu/s390.ld +++ b/qemu/s390.ld @@ -201,4 +201,3 @@ SECTIONS .debug_typenames 0 : { *(.debug_typenames) } .debug_varnames 0 : { *(.debug_varnames) } } - diff --git a/qemu/savevm.c b/qemu/savevm.c index d4017fa1..1b3ba894 100644 --- a/qemu/savevm.c +++ b/qemu/savevm.c @@ -1021,6 +1021,7 @@ void do_savevm(const char *name) BlockDriverInfo bdi1, *bdi = &bdi1; QEMUFile *f; int saved_vm_running; + uint32_t vm_state_size; #ifdef _WIN32 struct _timeb tb; #else @@ -1080,7 +1081,7 @@ void do_savevm(const char *name) goto the_end; } ret = qemu_savevm_state(f); - sn->vm_state_size = qemu_ftell(f); + vm_state_size = qemu_ftell(f); qemu_fclose(f); if (ret < 0) { term_printf("Error %d while writing VM\n", ret); @@ -1099,6 +1100,8 @@ void do_savevm(const char *name) bdrv_get_device_name(bs1)); } } + /* Write VM state size only to the image that contains the state */ + sn->vm_state_size = (bs == bs1 ? vm_state_size : 0); ret = bdrv_snapshot_create(bs1, sn); if (ret < 0) { term_printf("Error while creating snapshot on '%s'\n", @@ -1116,6 +1119,7 @@ void do_loadvm(const char *name) { BlockDriverState *bs, *bs1; BlockDriverInfo bdi1, *bdi = &bdi1; + QEMUSnapshotInfo sn; QEMUFile *f; int i, ret; int saved_vm_running; @@ -1166,6 +1170,11 @@ void do_loadvm(const char *name) return; } + /* Don't even try to load empty VM states */ + ret = bdrv_snapshot_find(bs, &sn, name); + if ((ret >= 0) && (sn.vm_state_size == 0)) + goto the_end; + /* restore the VM state */ f = qemu_fopen_bdrv(bs, bdi->vm_state_offset, 0); if (!f) { diff --git a/qemu/slirp/debug.h b/qemu/slirp/debug.h index 8a523b2e..c43eff73 100644 --- a/qemu/slirp/debug.h +++ b/qemu/slirp/debug.h @@ -37,4 +37,3 @@ extern int slirp_debug; #endif void debug_init _P((char *, int)); - diff --git a/qemu/slirp/mbuf.c b/qemu/slirp/mbuf.c index 1f3985a7..655de418 100644 --- a/qemu/slirp/mbuf.c +++ b/qemu/slirp/mbuf.c @@ -234,4 +234,3 @@ dtom(dat) return (struct mbuf *)0; } - diff --git a/qemu/slirp/sbuf.c b/qemu/slirp/sbuf.c index 02c5fce0..b0e08384 100644 --- a/qemu/slirp/sbuf.c +++ b/qemu/slirp/sbuf.c @@ -198,4 +198,3 @@ sbcopy(sb, off, len, to) memcpy(to+off,sb->sb_data,len); } } - diff --git a/qemu/slirp/slirp.c b/qemu/slirp/slirp.c index de4b4806..17b40e24 100644 --- a/qemu/slirp/slirp.c +++ b/qemu/slirp/slirp.c @@ -654,6 +654,9 @@ void slirp_input(const uint8_t *pkt, int pkt_len) if (!m) return; /* Note: we add to align the IP header */ + if (M_FREEROOM(m) < pkt_len + 2) { + m_inc(m, pkt_len + 2); + } m->m_len = pkt_len + 2; memcpy(m->m_data + 2, pkt, pkt_len); diff --git a/qemu/slirp/socket.c b/qemu/slirp/socket.c index 75f98fd4..00694e2c 100644 --- a/qemu/slirp/socket.c +++ b/qemu/slirp/socket.c @@ -723,4 +723,3 @@ sofwdrain(so) else sofcantsendmore(so); } - diff --git a/qemu/sys-queue.h b/qemu/sys-queue.h index ad5c8fb5..cb6a4c89 100644 --- a/qemu/sys-queue.h +++ b/qemu/sys-queue.h @@ -1,343 +1,343 @@ -/* $NetBSD: queue.h,v 1.45.14.1 2007/07/18 20:13:24 liamjfoy Exp $ */
-
-/*
- * Qemu version: Copy from netbsd, removed debug code, removed some of
- * the implementations. Left in lists, tail queues and circular queues.
- */
-
-/*
- * Copyright (c) 1991, 1993
- * The Regents of the University of California. All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- * 3. Neither the name of the University nor the names of its contributors
- * may be used to endorse or promote products derived from this software
- * without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
- * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
- * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
- * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
- * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- *
- * @(#)queue.h 8.5 (Berkeley) 8/20/94
- */
-
-#ifndef _SYS_QUEUE_H_
-#define _SYS_QUEUE_H_
-
-/*
- * This file defines three types of data structures:
- * lists, tail queues, and circular queues.
- *
- * A list is headed by a single forward pointer (or an array of forward
- * pointers for a hash table header). The elements are doubly linked
- * so that an arbitrary element can be removed without a need to
- * traverse the list. New elements can be added to the list before
- * or after an existing element or at the head of the list. A list
- * may only be traversed in the forward direction.
- *
- * A tail queue is headed by a pair of pointers, one to the head of the
- * list and the other to the tail of the list. The elements are doubly
- * linked so that an arbitrary element can be removed without a need to
- * traverse the list. New elements can be added to the list before or
- * after an existing element, at the head of the list, or at the end of
- * the list. A tail queue may be traversed in either direction.
- *
- * A circle queue is headed by a pair of pointers, one to the head of the
- * list and the other to the tail of the list. The elements are doubly
- * linked so that an arbitrary element can be removed without a need to
- * traverse the list. New elements can be added to the list before or after
- * an existing element, at the head of the list, or at the end of the list.
- * A circle queue may be traversed in either direction, but has a more
- * complex end of list detection.
- *
- * For details on the use of these macros, see the queue(3) manual page.
- */
-
-/*
- * List definitions.
- */
-#define LIST_HEAD(name, type) \
-struct name { \
- struct type *lh_first; /* first element */ \
-}
-
-#define LIST_HEAD_INITIALIZER(head) \
- { NULL }
-
-#define LIST_ENTRY(type) \
-struct { \
- struct type *le_next; /* next element */ \
- struct type **le_prev; /* address of previous next element */ \
-}
-
-/*
- * List functions.
- */
-#define LIST_INIT(head) do { \
- (head)->lh_first = NULL; \
-} while (/*CONSTCOND*/0)
-
-#define LIST_INSERT_AFTER(listelm, elm, field) do { \
- if (((elm)->field.le_next = (listelm)->field.le_next) != NULL) \
- (listelm)->field.le_next->field.le_prev = \
- &(elm)->field.le_next; \
- (listelm)->field.le_next = (elm); \
- (elm)->field.le_prev = &(listelm)->field.le_next; \
-} while (/*CONSTCOND*/0)
-
-#define LIST_INSERT_BEFORE(listelm, elm, field) do { \
- (elm)->field.le_prev = (listelm)->field.le_prev; \
- (elm)->field.le_next = (listelm); \
- *(listelm)->field.le_prev = (elm); \
- (listelm)->field.le_prev = &(elm)->field.le_next; \
-} while (/*CONSTCOND*/0)
-
-#define LIST_INSERT_HEAD(head, elm, field) do { \
- if (((elm)->field.le_next = (head)->lh_first) != NULL) \
- (head)->lh_first->field.le_prev = &(elm)->field.le_next;\
- (head)->lh_first = (elm); \
- (elm)->field.le_prev = &(head)->lh_first; \
-} while (/*CONSTCOND*/0)
-
-#define LIST_REMOVE(elm, field) do { \
- if ((elm)->field.le_next != NULL) \
- (elm)->field.le_next->field.le_prev = \
- (elm)->field.le_prev; \
- *(elm)->field.le_prev = (elm)->field.le_next; \
-} while (/*CONSTCOND*/0)
-
-#define LIST_FOREACH(var, head, field) \
- for ((var) = ((head)->lh_first); \
- (var); \
- (var) = ((var)->field.le_next))
-
-/*
- * List access methods.
- */
-#define LIST_EMPTY(head) ((head)->lh_first == NULL)
-#define LIST_FIRST(head) ((head)->lh_first)
-#define LIST_NEXT(elm, field) ((elm)->field.le_next)
-
-
-/*
- * Tail queue definitions.
- */
-#define _TAILQ_HEAD(name, type, qual) \
-struct name { \
- qual type *tqh_first; /* first element */ \
- qual type *qual *tqh_last; /* addr of last next element */ \
-}
-#define TAILQ_HEAD(name, type) _TAILQ_HEAD(name, struct type,)
-
-#define TAILQ_HEAD_INITIALIZER(head) \
- { NULL, &(head).tqh_first }
-
-#define _TAILQ_ENTRY(type, qual) \
-struct { \
- qual type *tqe_next; /* next element */ \
- qual type *qual *tqe_prev; /* address of previous next element */\
-}
-#define TAILQ_ENTRY(type) _TAILQ_ENTRY(struct type,)
-
-/*
- * Tail queue functions.
- */
-#define TAILQ_INIT(head) do { \
- (head)->tqh_first = NULL; \
- (head)->tqh_last = &(head)->tqh_first; \
-} while (/*CONSTCOND*/0)
-
-#define TAILQ_INSERT_HEAD(head, elm, field) do { \
- if (((elm)->field.tqe_next = (head)->tqh_first) != NULL) \
- (head)->tqh_first->field.tqe_prev = \
- &(elm)->field.tqe_next; \
- else \
- (head)->tqh_last = &(elm)->field.tqe_next; \
- (head)->tqh_first = (elm); \
- (elm)->field.tqe_prev = &(head)->tqh_first; \
-} while (/*CONSTCOND*/0)
-
-#define TAILQ_INSERT_TAIL(head, elm, field) do { \
- (elm)->field.tqe_next = NULL; \
- (elm)->field.tqe_prev = (head)->tqh_last; \
- *(head)->tqh_last = (elm); \
- (head)->tqh_last = &(elm)->field.tqe_next; \
-} while (/*CONSTCOND*/0)
-
-#define TAILQ_INSERT_AFTER(head, listelm, elm, field) do { \
- if (((elm)->field.tqe_next = (listelm)->field.tqe_next) != NULL)\
- (elm)->field.tqe_next->field.tqe_prev = \
- &(elm)->field.tqe_next; \
- else \
- (head)->tqh_last = &(elm)->field.tqe_next; \
- (listelm)->field.tqe_next = (elm); \
- (elm)->field.tqe_prev = &(listelm)->field.tqe_next; \
-} while (/*CONSTCOND*/0)
-
-#define TAILQ_INSERT_BEFORE(listelm, elm, field) do { \
- (elm)->field.tqe_prev = (listelm)->field.tqe_prev; \
- (elm)->field.tqe_next = (listelm); \
- *(listelm)->field.tqe_prev = (elm); \
- (listelm)->field.tqe_prev = &(elm)->field.tqe_next; \
-} while (/*CONSTCOND*/0)
-
-#define TAILQ_REMOVE(head, elm, field) do { \
- if (((elm)->field.tqe_next) != NULL) \
- (elm)->field.tqe_next->field.tqe_prev = \
- (elm)->field.tqe_prev; \
- else \
- (head)->tqh_last = (elm)->field.tqe_prev; \
- *(elm)->field.tqe_prev = (elm)->field.tqe_next; \
-} while (/*CONSTCOND*/0)
-
-#define TAILQ_FOREACH(var, head, field) \
- for ((var) = ((head)->tqh_first); \
- (var); \
- (var) = ((var)->field.tqe_next))
-
-#define TAILQ_FOREACH_SAFE(var, head, field, next_var) \
- for ((var) = ((head)->tqh_first); \
- (var) && ((next_var) = ((var)->field.tqe_next), 1); \
- (var) = (next_var))
-
-#define TAILQ_FOREACH_REVERSE(var, head, headname, field) \
- for ((var) = (*(((struct headname *)((head)->tqh_last))->tqh_last)); \
- (var); \
- (var) = (*(((struct headname *)((var)->field.tqe_prev))->tqh_last)))
-
-/*
- * Tail queue access methods.
- */
-#define TAILQ_EMPTY(head) ((head)->tqh_first == NULL)
-#define TAILQ_FIRST(head) ((head)->tqh_first)
-#define TAILQ_NEXT(elm, field) ((elm)->field.tqe_next)
-
-#define TAILQ_LAST(head, headname) \
- (*(((struct headname *)((head)->tqh_last))->tqh_last))
-#define TAILQ_PREV(elm, headname, field) \
- (*(((struct headname *)((elm)->field.tqe_prev))->tqh_last))
-
-
-/*
- * Circular queue definitions.
- */
-#define CIRCLEQ_HEAD(name, type) \
-struct name { \
- struct type *cqh_first; /* first element */ \
- struct type *cqh_last; /* last element */ \
-}
-
-#define CIRCLEQ_HEAD_INITIALIZER(head) \
- { (void *)&head, (void *)&head }
-
-#define CIRCLEQ_ENTRY(type) \
-struct { \
- struct type *cqe_next; /* next element */ \
- struct type *cqe_prev; /* previous element */ \
-}
-
-/*
- * Circular queue functions.
- */
-#define CIRCLEQ_INIT(head) do { \
- (head)->cqh_first = (void *)(head); \
- (head)->cqh_last = (void *)(head); \
-} while (/*CONSTCOND*/0)
-
-#define CIRCLEQ_INSERT_AFTER(head, listelm, elm, field) do { \
- (elm)->field.cqe_next = (listelm)->field.cqe_next; \
- (elm)->field.cqe_prev = (listelm); \
- if ((listelm)->field.cqe_next == (void *)(head)) \
- (head)->cqh_last = (elm); \
- else \
- (listelm)->field.cqe_next->field.cqe_prev = (elm); \
- (listelm)->field.cqe_next = (elm); \
-} while (/*CONSTCOND*/0)
-
-#define CIRCLEQ_INSERT_BEFORE(head, listelm, elm, field) do { \
- (elm)->field.cqe_next = (listelm); \
- (elm)->field.cqe_prev = (listelm)->field.cqe_prev; \
- if ((listelm)->field.cqe_prev == (void *)(head)) \
- (head)->cqh_first = (elm); \
- else \
- (listelm)->field.cqe_prev->field.cqe_next = (elm); \
- (listelm)->field.cqe_prev = (elm); \
-} while (/*CONSTCOND*/0)
-
-#define CIRCLEQ_INSERT_HEAD(head, elm, field) do { \
- (elm)->field.cqe_next = (head)->cqh_first; \
- (elm)->field.cqe_prev = (void *)(head); \
- if ((head)->cqh_last == (void *)(head)) \
- (head)->cqh_last = (elm); \
- else \
- (head)->cqh_first->field.cqe_prev = (elm); \
- (head)->cqh_first = (elm); \
-} while (/*CONSTCOND*/0)
-
-#define CIRCLEQ_INSERT_TAIL(head, elm, field) do { \
- (elm)->field.cqe_next = (void *)(head); \
- (elm)->field.cqe_prev = (head)->cqh_last; \
- if ((head)->cqh_first == (void *)(head)) \
- (head)->cqh_first = (elm); \
- else \
- (head)->cqh_last->field.cqe_next = (elm); \
- (head)->cqh_last = (elm); \
-} while (/*CONSTCOND*/0)
-
-#define CIRCLEQ_REMOVE(head, elm, field) do { \
- if ((elm)->field.cqe_next == (void *)(head)) \
- (head)->cqh_last = (elm)->field.cqe_prev; \
- else \
- (elm)->field.cqe_next->field.cqe_prev = \
- (elm)->field.cqe_prev; \
- if ((elm)->field.cqe_prev == (void *)(head)) \
- (head)->cqh_first = (elm)->field.cqe_next; \
- else \
- (elm)->field.cqe_prev->field.cqe_next = \
- (elm)->field.cqe_next; \
-} while (/*CONSTCOND*/0)
-
-#define CIRCLEQ_FOREACH(var, head, field) \
- for ((var) = ((head)->cqh_first); \
- (var) != (const void *)(head); \
- (var) = ((var)->field.cqe_next))
-
-#define CIRCLEQ_FOREACH_REVERSE(var, head, field) \
- for ((var) = ((head)->cqh_last); \
- (var) != (const void *)(head); \
- (var) = ((var)->field.cqe_prev))
-
-/*
- * Circular queue access methods.
- */
-#define CIRCLEQ_EMPTY(head) ((head)->cqh_first == (void *)(head))
-#define CIRCLEQ_FIRST(head) ((head)->cqh_first)
-#define CIRCLEQ_LAST(head) ((head)->cqh_last)
-#define CIRCLEQ_NEXT(elm, field) ((elm)->field.cqe_next)
-#define CIRCLEQ_PREV(elm, field) ((elm)->field.cqe_prev)
-
-#define CIRCLEQ_LOOP_NEXT(head, elm, field) \
- (((elm)->field.cqe_next == (void *)(head)) \
- ? ((head)->cqh_first) \
- : (elm->field.cqe_next))
-#define CIRCLEQ_LOOP_PREV(head, elm, field) \
- (((elm)->field.cqe_prev == (void *)(head)) \
- ? ((head)->cqh_last) \
- : (elm->field.cqe_prev))
-
-#endif /* !_SYS_QUEUE_H_ */
+/* $NetBSD: queue.h,v 1.45.14.1 2007/07/18 20:13:24 liamjfoy Exp $ */ + +/* + * Qemu version: Copy from netbsd, removed debug code, removed some of + * the implementations. Left in lists, tail queues and circular queues. + */ + +/* + * Copyright (c) 1991, 1993 + * The Regents of the University of California. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * @(#)queue.h 8.5 (Berkeley) 8/20/94 + */ + +#ifndef _SYS_QUEUE_H_ +#define _SYS_QUEUE_H_ + +/* + * This file defines three types of data structures: + * lists, tail queues, and circular queues. + * + * A list is headed by a single forward pointer (or an array of forward + * pointers for a hash table header). The elements are doubly linked + * so that an arbitrary element can be removed without a need to + * traverse the list. New elements can be added to the list before + * or after an existing element or at the head of the list. A list + * may only be traversed in the forward direction. + * + * A tail queue is headed by a pair of pointers, one to the head of the + * list and the other to the tail of the list. The elements are doubly + * linked so that an arbitrary element can be removed without a need to + * traverse the list. New elements can be added to the list before or + * after an existing element, at the head of the list, or at the end of + * the list. A tail queue may be traversed in either direction. + * + * A circle queue is headed by a pair of pointers, one to the head of the + * list and the other to the tail of the list. The elements are doubly + * linked so that an arbitrary element can be removed without a need to + * traverse the list. New elements can be added to the list before or after + * an existing element, at the head of the list, or at the end of the list. + * A circle queue may be traversed in either direction, but has a more + * complex end of list detection. + * + * For details on the use of these macros, see the queue(3) manual page. + */ + +/* + * List definitions. + */ +#define LIST_HEAD(name, type) \ +struct name { \ + struct type *lh_first; /* first element */ \ +} + +#define LIST_HEAD_INITIALIZER(head) \ + { NULL } + +#define LIST_ENTRY(type) \ +struct { \ + struct type *le_next; /* next element */ \ + struct type **le_prev; /* address of previous next element */ \ +} + +/* + * List functions. + */ +#define LIST_INIT(head) do { \ + (head)->lh_first = NULL; \ +} while (/*CONSTCOND*/0) + +#define LIST_INSERT_AFTER(listelm, elm, field) do { \ + if (((elm)->field.le_next = (listelm)->field.le_next) != NULL) \ + (listelm)->field.le_next->field.le_prev = \ + &(elm)->field.le_next; \ + (listelm)->field.le_next = (elm); \ + (elm)->field.le_prev = &(listelm)->field.le_next; \ +} while (/*CONSTCOND*/0) + +#define LIST_INSERT_BEFORE(listelm, elm, field) do { \ + (elm)->field.le_prev = (listelm)->field.le_prev; \ + (elm)->field.le_next = (listelm); \ + *(listelm)->field.le_prev = (elm); \ + (listelm)->field.le_prev = &(elm)->field.le_next; \ +} while (/*CONSTCOND*/0) + +#define LIST_INSERT_HEAD(head, elm, field) do { \ + if (((elm)->field.le_next = (head)->lh_first) != NULL) \ + (head)->lh_first->field.le_prev = &(elm)->field.le_next;\ + (head)->lh_first = (elm); \ + (elm)->field.le_prev = &(head)->lh_first; \ +} while (/*CONSTCOND*/0) + +#define LIST_REMOVE(elm, field) do { \ + if ((elm)->field.le_next != NULL) \ + (elm)->field.le_next->field.le_prev = \ + (elm)->field.le_prev; \ + *(elm)->field.le_prev = (elm)->field.le_next; \ +} while (/*CONSTCOND*/0) + +#define LIST_FOREACH(var, head, field) \ + for ((var) = ((head)->lh_first); \ + (var); \ + (var) = ((var)->field.le_next)) + +/* + * List access methods. + */ +#define LIST_EMPTY(head) ((head)->lh_first == NULL) +#define LIST_FIRST(head) ((head)->lh_first) +#define LIST_NEXT(elm, field) ((elm)->field.le_next) + + +/* + * Tail queue definitions. + */ +#define _TAILQ_HEAD(name, type, qual) \ +struct name { \ + qual type *tqh_first; /* first element */ \ + qual type *qual *tqh_last; /* addr of last next element */ \ +} +#define TAILQ_HEAD(name, type) _TAILQ_HEAD(name, struct type,) + +#define TAILQ_HEAD_INITIALIZER(head) \ + { NULL, &(head).tqh_first } + +#define _TAILQ_ENTRY(type, qual) \ +struct { \ + qual type *tqe_next; /* next element */ \ + qual type *qual *tqe_prev; /* address of previous next element */\ +} +#define TAILQ_ENTRY(type) _TAILQ_ENTRY(struct type,) + +/* + * Tail queue functions. + */ +#define TAILQ_INIT(head) do { \ + (head)->tqh_first = NULL; \ + (head)->tqh_last = &(head)->tqh_first; \ +} while (/*CONSTCOND*/0) + +#define TAILQ_INSERT_HEAD(head, elm, field) do { \ + if (((elm)->field.tqe_next = (head)->tqh_first) != NULL) \ + (head)->tqh_first->field.tqe_prev = \ + &(elm)->field.tqe_next; \ + else \ + (head)->tqh_last = &(elm)->field.tqe_next; \ + (head)->tqh_first = (elm); \ + (elm)->field.tqe_prev = &(head)->tqh_first; \ +} while (/*CONSTCOND*/0) + +#define TAILQ_INSERT_TAIL(head, elm, field) do { \ + (elm)->field.tqe_next = NULL; \ + (elm)->field.tqe_prev = (head)->tqh_last; \ + *(head)->tqh_last = (elm); \ + (head)->tqh_last = &(elm)->field.tqe_next; \ +} while (/*CONSTCOND*/0) + +#define TAILQ_INSERT_AFTER(head, listelm, elm, field) do { \ + if (((elm)->field.tqe_next = (listelm)->field.tqe_next) != NULL)\ + (elm)->field.tqe_next->field.tqe_prev = \ + &(elm)->field.tqe_next; \ + else \ + (head)->tqh_last = &(elm)->field.tqe_next; \ + (listelm)->field.tqe_next = (elm); \ + (elm)->field.tqe_prev = &(listelm)->field.tqe_next; \ +} while (/*CONSTCOND*/0) + +#define TAILQ_INSERT_BEFORE(listelm, elm, field) do { \ + (elm)->field.tqe_prev = (listelm)->field.tqe_prev; \ + (elm)->field.tqe_next = (listelm); \ + *(listelm)->field.tqe_prev = (elm); \ + (listelm)->field.tqe_prev = &(elm)->field.tqe_next; \ +} while (/*CONSTCOND*/0) + +#define TAILQ_REMOVE(head, elm, field) do { \ + if (((elm)->field.tqe_next) != NULL) \ + (elm)->field.tqe_next->field.tqe_prev = \ + (elm)->field.tqe_prev; \ + else \ + (head)->tqh_last = (elm)->field.tqe_prev; \ + *(elm)->field.tqe_prev = (elm)->field.tqe_next; \ +} while (/*CONSTCOND*/0) + +#define TAILQ_FOREACH(var, head, field) \ + for ((var) = ((head)->tqh_first); \ + (var); \ + (var) = ((var)->field.tqe_next)) + +#define TAILQ_FOREACH_SAFE(var, head, field, next_var) \ + for ((var) = ((head)->tqh_first); \ + (var) && ((next_var) = ((var)->field.tqe_next), 1); \ + (var) = (next_var)) + +#define TAILQ_FOREACH_REVERSE(var, head, headname, field) \ + for ((var) = (*(((struct headname *)((head)->tqh_last))->tqh_last)); \ + (var); \ + (var) = (*(((struct headname *)((var)->field.tqe_prev))->tqh_last))) + +/* + * Tail queue access methods. + */ +#define TAILQ_EMPTY(head) ((head)->tqh_first == NULL) +#define TAILQ_FIRST(head) ((head)->tqh_first) +#define TAILQ_NEXT(elm, field) ((elm)->field.tqe_next) + +#define TAILQ_LAST(head, headname) \ + (*(((struct headname *)((head)->tqh_last))->tqh_last)) +#define TAILQ_PREV(elm, headname, field) \ + (*(((struct headname *)((elm)->field.tqe_prev))->tqh_last)) + + +/* + * Circular queue definitions. + */ +#define CIRCLEQ_HEAD(name, type) \ +struct name { \ + struct type *cqh_first; /* first element */ \ + struct type *cqh_last; /* last element */ \ +} + +#define CIRCLEQ_HEAD_INITIALIZER(head) \ + { (void *)&head, (void *)&head } + +#define CIRCLEQ_ENTRY(type) \ +struct { \ + struct type *cqe_next; /* next element */ \ + struct type *cqe_prev; /* previous element */ \ +} + +/* + * Circular queue functions. + */ +#define CIRCLEQ_INIT(head) do { \ + (head)->cqh_first = (void *)(head); \ + (head)->cqh_last = (void *)(head); \ +} while (/*CONSTCOND*/0) + +#define CIRCLEQ_INSERT_AFTER(head, listelm, elm, field) do { \ + (elm)->field.cqe_next = (listelm)->field.cqe_next; \ + (elm)->field.cqe_prev = (listelm); \ + if ((listelm)->field.cqe_next == (void *)(head)) \ + (head)->cqh_last = (elm); \ + else \ + (listelm)->field.cqe_next->field.cqe_prev = (elm); \ + (listelm)->field.cqe_next = (elm); \ +} while (/*CONSTCOND*/0) + +#define CIRCLEQ_INSERT_BEFORE(head, listelm, elm, field) do { \ + (elm)->field.cqe_next = (listelm); \ + (elm)->field.cqe_prev = (listelm)->field.cqe_prev; \ + if ((listelm)->field.cqe_prev == (void *)(head)) \ + (head)->cqh_first = (elm); \ + else \ + (listelm)->field.cqe_prev->field.cqe_next = (elm); \ + (listelm)->field.cqe_prev = (elm); \ +} while (/*CONSTCOND*/0) + +#define CIRCLEQ_INSERT_HEAD(head, elm, field) do { \ + (elm)->field.cqe_next = (head)->cqh_first; \ + (elm)->field.cqe_prev = (void *)(head); \ + if ((head)->cqh_last == (void *)(head)) \ + (head)->cqh_last = (elm); \ + else \ + (head)->cqh_first->field.cqe_prev = (elm); \ + (head)->cqh_first = (elm); \ +} while (/*CONSTCOND*/0) + +#define CIRCLEQ_INSERT_TAIL(head, elm, field) do { \ + (elm)->field.cqe_next = (void *)(head); \ + (elm)->field.cqe_prev = (head)->cqh_last; \ + if ((head)->cqh_first == (void *)(head)) \ + (head)->cqh_first = (elm); \ + else \ + (head)->cqh_last->field.cqe_next = (elm); \ + (head)->cqh_last = (elm); \ +} while (/*CONSTCOND*/0) + +#define CIRCLEQ_REMOVE(head, elm, field) do { \ + if ((elm)->field.cqe_next == (void *)(head)) \ + (head)->cqh_last = (elm)->field.cqe_prev; \ + else \ + (elm)->field.cqe_next->field.cqe_prev = \ + (elm)->field.cqe_prev; \ + if ((elm)->field.cqe_prev == (void *)(head)) \ + (head)->cqh_first = (elm)->field.cqe_next; \ + else \ + (elm)->field.cqe_prev->field.cqe_next = \ + (elm)->field.cqe_next; \ +} while (/*CONSTCOND*/0) + +#define CIRCLEQ_FOREACH(var, head, field) \ + for ((var) = ((head)->cqh_first); \ + (var) != (const void *)(head); \ + (var) = ((var)->field.cqe_next)) + +#define CIRCLEQ_FOREACH_REVERSE(var, head, field) \ + for ((var) = ((head)->cqh_last); \ + (var) != (const void *)(head); \ + (var) = ((var)->field.cqe_prev)) + +/* + * Circular queue access methods. + */ +#define CIRCLEQ_EMPTY(head) ((head)->cqh_first == (void *)(head)) +#define CIRCLEQ_FIRST(head) ((head)->cqh_first) +#define CIRCLEQ_LAST(head) ((head)->cqh_last) +#define CIRCLEQ_NEXT(elm, field) ((elm)->field.cqe_next) +#define CIRCLEQ_PREV(elm, field) ((elm)->field.cqe_prev) + +#define CIRCLEQ_LOOP_NEXT(head, elm, field) \ + (((elm)->field.cqe_next == (void *)(head)) \ + ? ((head)->cqh_first) \ + : (elm->field.cqe_next)) +#define CIRCLEQ_LOOP_PREV(head, elm, field) \ + (((elm)->field.cqe_prev == (void *)(head)) \ + ? ((head)->cqh_last) \ + : (elm->field.cqe_prev)) + +#endif /* !_SYS_QUEUE_H_ */ diff --git a/qemu/target-alpha/cpu.h b/qemu/target-alpha/cpu.h index 65be4fb5..710a6021 100644 --- a/qemu/target-alpha/cpu.h +++ b/qemu/target-alpha/cpu.h @@ -407,6 +407,10 @@ int cpu_alpha_exec(CPUAlphaState *s); is returned if the signal was handled by the virtual CPU. */ int cpu_alpha_signal_handler(int host_signum, void *pinfo, void *puc); +int cpu_alpha_handle_mmu_fault (CPUState *env, uint64_t address, int rw, + int mmu_idx, int is_softmmu); +void do_interrupt (CPUState *env); + int cpu_alpha_mfpr (CPUState *env, int iprn, uint64_t *valp); int cpu_alpha_mtpr (CPUState *env, int iprn, uint64_t val, uint64_t *oldvalp); void pal_init (CPUState *env); diff --git a/qemu/target-alpha/exec.h b/qemu/target-alpha/exec.h index 99b31312..bf0c80e2 100644 --- a/qemu/target-alpha/exec.h +++ b/qemu/target-alpha/exec.h @@ -48,11 +48,6 @@ static always_inline void regs_to_env(void) { } -int cpu_alpha_handle_mmu_fault (CPUState *env, uint64_t address, int rw, - int mmu_idx, int is_softmmu); - -void do_interrupt (CPUState *env); - static always_inline int cpu_halted(CPUState *env) { if (!env->halted) return 0; diff --git a/qemu/target-alpha/helper.c b/qemu/target-alpha/helper.c index cc94807e..5a8955d0 100644 --- a/qemu/target-alpha/helper.c +++ b/qemu/target-alpha/helper.c @@ -436,4 +436,3 @@ void cpu_dump_state (CPUState *env, FILE *f, } cpu_fprintf(f, "\nlock " TARGET_FMT_lx "\n", env->lock); } - diff --git a/qemu/target-alpha/translate.c b/qemu/target-alpha/translate.c index 7a0e54fe..7e8e6442 100644 --- a/qemu/target-alpha/translate.c +++ b/qemu/target-alpha/translate.c @@ -2407,10 +2407,15 @@ static always_inline void gen_intermediate_code_internal (CPUState *env, * generation */ if (((ctx.pc & (TARGET_PAGE_SIZE - 1)) == 0) || - (env->singlestep_enabled) || num_insns >= max_insns) { break; } + + if (env->singlestep_enabled) { + gen_excp(&ctx, EXCP_DEBUG, 0); + break; + } + #if defined (DO_SINGLE_STEP) break; #endif diff --git a/qemu/target-arm/machine.c b/qemu/target-arm/machine.c index 42ff5844..323bace3 100644 --- a/qemu/target-arm/machine.c +++ b/qemu/target-arm/machine.c @@ -11,6 +11,8 @@ void register_machines(void) qemu_register_machine(&spitzpda_machine); qemu_register_machine(&borzoipda_machine); qemu_register_machine(&terrierpda_machine); + qemu_register_machine(&sx1_machine_v1); + qemu_register_machine(&sx1_machine_v2); qemu_register_machine(&palmte_machine); qemu_register_machine(&n800_machine); qemu_register_machine(&n810_machine); @@ -211,5 +213,3 @@ int cpu_load(QEMUFile *f, void *opaque, int version_id) return 0; } - - diff --git a/qemu/target-arm/op_helper.c b/qemu/target-arm/op_helper.c index 84a3d157..04828d02 100644 --- a/qemu/target-arm/op_helper.c +++ b/qemu/target-arm/op_helper.c @@ -509,7 +509,6 @@ void HELPER(neon_trn_u8)(void) rm = ((T1 & 0xff00ff00) >> 8) | (T0 & 0xff00ff00); T0 = rd; T1 = rm; - FORCE_RET(); } void HELPER(neon_trn_u16)(void) @@ -520,7 +519,6 @@ void HELPER(neon_trn_u16)(void) rm = (T1 >> 16) | (T0 & 0xffff0000); T0 = rd; T1 = rm; - FORCE_RET(); } /* Worker routines for zip and unzip. */ @@ -534,7 +532,6 @@ void HELPER(neon_unzip_u8)(void) | ((T1 << 8) & 0xff0000) | (T1 & 0xff000000); T0 = rd; T1 = rm; - FORCE_RET(); } void HELPER(neon_zip_u8)(void) @@ -547,7 +544,6 @@ void HELPER(neon_zip_u8)(void) | ((T0 >> 8) & 0xff0000) | (T1 & 0xff000000); T0 = rd; T1 = rm; - FORCE_RET(); } void HELPER(neon_zip_u16)(void) @@ -557,5 +553,4 @@ void HELPER(neon_zip_u16)(void) tmp = (T0 & 0xffff) | (T1 << 16); T1 = (T1 & 0xffff0000) | (T0 >> 16); T0 = tmp; - FORCE_RET(); } diff --git a/qemu/target-arm/translate.c b/qemu/target-arm/translate.c index f984de7c..0650bc3a 100644 --- a/qemu/target-arm/translate.c +++ b/qemu/target-arm/translate.c @@ -57,7 +57,6 @@ typedef struct DisasContext { struct TranslationBlock *tb; int singlestep_enabled; int thumb; - int is_mem; #if !defined(CONFIG_USER_ONLY) int user; #endif @@ -195,7 +194,6 @@ static void store_reg(DisasContext *s, int reg, TCGv var) /* Basic operations. */ #define gen_op_movl_T0_T1() tcg_gen_mov_i32(cpu_T[0], cpu_T[1]) -#define gen_op_movl_T1_T0() tcg_gen_mov_i32(cpu_T[1], cpu_T[0]) #define gen_op_movl_T0_im(im) tcg_gen_movi_i32(cpu_T[0], im) #define gen_op_movl_T1_im(im) tcg_gen_movi_i32(cpu_T[1], im) @@ -219,11 +217,8 @@ static void store_reg(DisasContext *s, int reg, TCGv var) #define gen_op_logic_T0_cc() gen_logic_CC(cpu_T[0]); #define gen_op_logic_T1_cc() gen_logic_CC(cpu_T[1]); -#define gen_op_shll_T0_im(im) tcg_gen_shli_i32(cpu_T[0], cpu_T[0], im) #define gen_op_shll_T1_im(im) tcg_gen_shli_i32(cpu_T[1], cpu_T[1], im) #define gen_op_shrl_T1_im(im) tcg_gen_shri_i32(cpu_T[1], cpu_T[1], im) -#define gen_op_sarl_T1_im(im) tcg_gen_sari_i32(cpu_T[1], cpu_T[1], im) -#define gen_op_rorl_T1_im(im) tcg_gen_rori_i32(cpu_T[1], cpu_T[1], im) /* Value extensions. */ #define gen_uxtb(var) tcg_gen_ext8u_i32(var, var) @@ -382,7 +377,6 @@ static void gen_imull(TCGv a, TCGv b) tcg_gen_shri_i64(tmp1, tmp1, 32); tcg_gen_trunc_i64_i32(b, tmp1); } -#define gen_op_imull_T0_T1() gen_imull(cpu_T[0], cpu_T[1]) /* Swap low and high halfwords. */ static void gen_swap_half(TCGv var) @@ -421,7 +415,7 @@ static void gen_set_CF_bit31(TCGv var) { TCGv tmp = new_tmp(); tcg_gen_shri_i32(tmp, var, 31); - gen_set_CF(var); + gen_set_CF(tmp); dead_tmp(tmp); } @@ -496,7 +490,7 @@ static void shifter_out_im(TCGv var, int shift) tcg_gen_andi_i32(tmp, var, 1); } else { tcg_gen_shri_i32(tmp, var, shift); - if (shift != 31); + if (shift != 31) tcg_gen_andi_i32(tmp, tmp, 1); } gen_set_CF(tmp); @@ -817,17 +811,6 @@ static inline void gen_bx_T0(DisasContext *s) gen_bx(s, tmp); } -#if defined(CONFIG_USER_ONLY) -#define gen_ldst(name, s) gen_op_##name##_raw() -#else -#define gen_ldst(name, s) do { \ - s->is_mem = 1; \ - if (IS_USER(s)) \ - gen_op_##name##_user(); \ - else \ - gen_op_##name##_kernel(); \ - } while (0) -#endif static inline TCGv gen_ld8s(TCGv addr, int index) { TCGv tmp = new_tmp(); @@ -995,15 +978,6 @@ static inline void gen_vfp_##name(int dp) \ gen_helper_vfp_##name##s(cpu_F0s, cpu_F0s, cpu_F1s, cpu_env); \ } -#define VFP_OP1(name) \ -static inline void gen_vfp_##name(int dp, int arg) \ -{ \ - if (dp) \ - gen_op_vfp_##name##d(arg); \ - else \ - gen_op_vfp_##name##s(arg); \ -} - VFP_OP2(add) VFP_OP2(sub) VFP_OP2(mul) @@ -4644,6 +4618,7 @@ static int disas_neon_data_insn(CPUState * env, DisasContext *s, uint32_t insn) imm = (uint32_t)shift; tmp2 = tcg_const_i32(imm); TCGV_UNUSED_I64(tmp64); + break; case 3: tmp64 = tcg_const_i64(shift); TCGV_UNUSED(tmp2); @@ -6532,8 +6507,8 @@ static void disas_arm_insn(CPUState * env, DisasContext *s) tcg_gen_shri_i64(tmp64, tmp64, 32); tmp = new_tmp(); tcg_gen_trunc_i64_i32(tmp, tmp64); - if (rn != 15) { - tmp2 = load_reg(s, rn); + if (rd != 15) { + tmp2 = load_reg(s, rd); if (insn & (1 << 6)) { tcg_gen_sub_i32(tmp, tmp, tmp2); } else { @@ -6541,7 +6516,7 @@ static void disas_arm_insn(CPUState * env, DisasContext *s) } dead_tmp(tmp2); } - store_reg(s, rd, tmp); + store_reg(s, rn, tmp); } else { if (insn & (1 << 5)) gen_swap_half(tmp2); @@ -6581,12 +6556,12 @@ static void disas_arm_insn(CPUState * env, DisasContext *s) tmp2 = load_reg(s, rs); gen_helper_usad8(tmp, tmp, tmp2); dead_tmp(tmp2); - if (rn != 15) { - tmp2 = load_reg(s, rn); + if (rd != 15) { + tmp2 = load_reg(s, rd); tcg_gen_add_i32(tmp, tmp, tmp2); dead_tmp(tmp2); } - store_reg(s, rd, tmp); + store_reg(s, rn, tmp); break; case 0x20: case 0x24: case 0x28: case 0x2c: /* Bitfield insert/clear. */ @@ -6609,6 +6584,7 @@ static void disas_arm_insn(CPUState * env, DisasContext *s) break; case 0x12: case 0x16: case 0x1a: case 0x1e: /* sbfx */ case 0x32: case 0x36: case 0x3a: case 0x3e: /* ubfx */ + ARCH(6T2); tmp = load_reg(s, rm); shift = (insn >> 7) & 0x1f; i = ((insn >> 16) & 0x1f) + 1; @@ -6649,7 +6625,6 @@ static void disas_arm_insn(CPUState * env, DisasContext *s) gen_add_data_offset(s, insn, tmp2); if (insn & (1 << 20)) { /* load */ - s->is_mem = 1; if (insn & (1 << 22)) { tmp = gen_ld8u(tmp2, i); } else { @@ -8625,7 +8600,6 @@ static inline void gen_intermediate_code_internal(CPUState *env, dc->thumb = env->thumb; dc->condexec_mask = (env->condexec_bits & 0xf) << 1; dc->condexec_cond = env->condexec_bits >> 4; - dc->is_mem = 0; #if !defined(CONFIG_USER_ONLY) if (IS_M(env)) { dc->user = ((env->v7m.exception == 0) && (env->v7m.control & 1)); @@ -8729,7 +8703,7 @@ static inline void gen_intermediate_code_internal(CPUState *env, gen_set_label(dc->condlabel); dc->condjmp = 0; } - /* Translation stops when a conditional branch is enoutered. + /* Translation stops when a conditional branch is encountered. * Otherwise the subsequent code could get translated several times. * Also stop translation when a page boundary is reached. This * ensures prefetch aborts occur at the right place. */ diff --git a/qemu/target-cris/exec.h b/qemu/target-cris/exec.h index ec7346ac..e82c04a7 100644 --- a/qemu/target-cris/exec.h +++ b/qemu/target-cris/exec.h @@ -25,8 +25,6 @@ register struct CPUCRISState *env asm(AREG0); #include "cpu.h" #include "exec-all.h" -#define RETURN() __asm__ __volatile__("" : : : "memory"); - static inline void env_to_regs(void) { } diff --git a/qemu/target-cris/op_helper.c b/qemu/target-cris/op_helper.c index 49bcebc4..a681f84f 100644 --- a/qemu/target-cris/op_helper.c +++ b/qemu/target-cris/op_helper.c @@ -189,7 +189,6 @@ void helper_movl_reg_sreg (uint32_t reg, uint32_t sreg) } #endif env->regs[reg] = env->sregs[srs][sreg]; - RETURN(); } static void cris_ccs_rshift(CPUState *env) diff --git a/qemu/target-i386/cpu.h b/qemu/target-i386/cpu.h index 86480386..0f518f87 100644 --- a/qemu/target-i386/cpu.h +++ b/qemu/target-i386/cpu.h @@ -721,10 +721,12 @@ static inline void cpu_x86_set_cpl(CPUX86State *s, int cpl) #endif } +/* op_helper.c */ /* used for debug or cpu save/restore */ void cpu_get_fp80(uint64_t *pmant, uint16_t *pexp, CPU86_LDouble f); CPU86_LDouble cpu_set_fp80(uint64_t mant, uint16_t upper); +/* cpu-exec.c */ /* the following helpers are only usable in user mode simulation as they can trigger unexpected exceptions */ void cpu_x86_load_seg(CPUX86State *s, int seg_reg, int selector); @@ -736,24 +738,51 @@ void cpu_x86_frstor(CPUX86State *s, target_ulong ptr, int data32); is returned if the signal was handled by the virtual CPU. */ int cpu_x86_signal_handler(int host_signum, void *pinfo, void *puc); + +/* helper.c */ +int cpu_x86_handle_mmu_fault(CPUX86State *env, target_ulong addr, + int is_write, int mmu_idx, int is_softmmu); void cpu_x86_set_a20(CPUX86State *env, int a20_state); +void cpu_x86_cpuid(CPUX86State *env, uint32_t index, + uint32_t *eax, uint32_t *ebx, + uint32_t *ecx, uint32_t *edx); -uint64_t cpu_get_tsc(CPUX86State *env); +static inline int hw_breakpoint_enabled(unsigned long dr7, int index) +{ + return (dr7 >> (index * 2)) & 3; +} +static inline int hw_breakpoint_type(unsigned long dr7, int index) +{ + return (dr7 >> (DR7_TYPE_SHIFT + (index * 2))) & 3; +} + +static inline int hw_breakpoint_len(unsigned long dr7, int index) +{ + int len = ((dr7 >> (DR7_LEN_SHIFT + (index * 2))) & 3); + return (len == 2) ? 8 : len + 1; +} + +void hw_breakpoint_insert(CPUX86State *env, int index); +void hw_breakpoint_remove(CPUX86State *env, int index); +int check_hw_breakpoints(CPUX86State *env, int force_dr6_update); + +/* will be suppressed */ +void cpu_x86_update_cr0(CPUX86State *env, uint32_t new_cr0); +void cpu_x86_update_cr3(CPUX86State *env, target_ulong new_cr3); +void cpu_x86_update_cr4(CPUX86State *env, uint32_t new_cr4); + +/* hw/apic.c */ void cpu_set_apic_base(CPUX86State *env, uint64_t val); uint64_t cpu_get_apic_base(CPUX86State *env); void cpu_set_apic_tpr(CPUX86State *env, uint8_t val); #ifndef NO_CPU_IO_DEFS uint8_t cpu_get_apic_tpr(CPUX86State *env); #endif -void cpu_smm_update(CPUX86State *env); -/* will be suppressed */ -void cpu_x86_update_cr0(CPUX86State *env, uint32_t new_cr0); - -void cpu_x86_cpuid(CPUX86State *env, uint32_t index, - uint32_t *eax, uint32_t *ebx, - uint32_t *ecx, uint32_t *edx); +/* hw/pc.c */ +void cpu_smm_update(CPUX86State *env); +uint64_t cpu_get_tsc(CPUX86State *env); /* used to debug */ #define X86_DUMP_FPU 0x0001 /* dump FPU state too */ @@ -788,6 +817,7 @@ static inline int cpu_mmu_index (CPUState *env) return (env->hflags & HF_CPL_MASK) == 3 ? 1 : 0; } +/* translate.c */ void optimize_flags_init(void); typedef struct CCTable { @@ -804,26 +834,6 @@ static inline void cpu_clone_regs(CPUState *env, target_ulong newsp) } #endif -static inline int hw_breakpoint_enabled(unsigned long dr7, int index) -{ - return (dr7 >> (index * 2)) & 3; -} - -static inline int hw_breakpoint_type(unsigned long dr7, int index) -{ - return (dr7 >> (DR7_TYPE_SHIFT + (index * 2))) & 3; -} - -static inline int hw_breakpoint_len(unsigned long dr7, int index) -{ - int len = ((dr7 >> (DR7_LEN_SHIFT + (index * 2))) & 3); - return (len == 2) ? 8 : len + 1; -} - -void hw_breakpoint_insert(CPUState *env, int index); -void hw_breakpoint_remove(CPUState *env, int index); -int check_hw_breakpoints(CPUState *env, int force_dr6_update); - #include "cpu-all.h" #include "exec-all.h" diff --git a/qemu/target-i386/exec.h b/qemu/target-i386/exec.h index 36631665..4d97a1bc 100644 --- a/qemu/target-i386/exec.h +++ b/qemu/target-i386/exec.h @@ -57,18 +57,11 @@ register struct CPUX86State *env asm(AREG0); #include "cpu.h" #include "exec-all.h" -void cpu_x86_update_cr3(CPUX86State *env, target_ulong new_cr3); -void cpu_x86_update_cr4(CPUX86State *env, uint32_t new_cr4); -int cpu_x86_handle_mmu_fault(CPUX86State *env, target_ulong addr, - int is_write, int mmu_idx, int is_softmmu); -void __hidden cpu_lock(void); -void __hidden cpu_unlock(void); +/* op_helper.c */ void do_interrupt(int intno, int is_int, int error_code, target_ulong next_eip, int is_hw); void do_interrupt_user(int intno, int is_int, int error_code, target_ulong next_eip); -void raise_interrupt(int intno, int is_int, int error_code, - int next_eip_addend); void raise_exception_err(int exception_index, int error_code); void raise_exception(int exception_index); void do_smm_enter(void); @@ -274,16 +267,6 @@ static inline void helper_fstt(CPU86_LDouble f, target_ulong ptr) #define FPUC_EM 0x3f -extern const CPU86_LDouble f15rk[7]; - -void fpu_raise_exception(void); -void restore_native_fp_state(CPUState *env); -void save_native_fp_state(CPUState *env); - -extern const uint8_t parity_table[256]; -extern const uint8_t rclw_table[32]; -extern const uint8_t rclb_table[32]; - static inline uint32_t compute_eflags(void) { return env->eflags | helper_cc_compute_all(CC_OP) | (DF & DF_MASK); diff --git a/qemu/target-i386/helper.c b/qemu/target-i386/helper.c index f67d9556..c8293261 100644 --- a/qemu/target-i386/helper.c +++ b/qemu/target-i386/helper.c @@ -27,10 +27,8 @@ #include "cpu.h" #include "exec-all.h" -#include "svm.h" #include "qemu-common.h" #include "kvm.h" -#include "helper.h" #include "qemu-kvm.h" @@ -856,12 +854,6 @@ void cpu_x86_update_cr4(CPUX86State *env, uint32_t new_cr4) env->cr[4] = new_cr4; } -/* XXX: also flush 4MB pages */ -void cpu_x86_flush_tlb(CPUX86State *env, target_ulong addr) -{ - tlb_flush_page(env, addr); -} - #if defined(CONFIG_USER_ONLY) int cpu_x86_handle_mmu_fault(CPUX86State *env, target_ulong addr, diff --git a/qemu/target-i386/kvm.c b/qemu/target-i386/kvm.c index 3f60654e..2412ae43 100644 --- a/qemu/target-i386/kvm.c +++ b/qemu/target-i386/kvm.c @@ -39,7 +39,7 @@ int kvm_arch_init_vcpu(CPUState *env) struct kvm_cpuid cpuid; struct kvm_cpuid_entry entries[100]; } __attribute__((packed)) cpuid_data; - int limit, i, cpuid_i; + uint32_t limit, i, cpuid_i; uint32_t eax, ebx, ecx, edx; cpuid_i = 0; @@ -90,16 +90,17 @@ static int kvm_has_msr_star(CPUState *env) /* Obtain MSR list from KVM. These are the MSRs that we must * save/restore */ + msr_list.nmsrs = 0; ret = kvm_ioctl(env->kvm_state, KVM_GET_MSR_INDEX_LIST, &msr_list); if (ret < 0) return 0; - msr_list.nmsrs = 0; kvm_msr_list = qemu_mallocz(sizeof(msr_list) + msr_list.nmsrs * sizeof(msr_list.indices[0])); if (kvm_msr_list == NULL) return 0; + kvm_msr_list->nmsrs = msr_list.nmsrs; ret = kvm_ioctl(env->kvm_state, KVM_GET_MSR_INDEX_LIST, kvm_msr_list); if (ret >= 0) { int i; diff --git a/qemu/target-i386/op_helper.c b/qemu/target-i386/op_helper.c index 6dc0802f..52fee3d4 100644 --- a/qemu/target-i386/op_helper.c +++ b/qemu/target-i386/op_helper.c @@ -19,6 +19,7 @@ */ #define CPU_NO_GLOBAL_REGS #include "exec.h" +#include "exec-all.h" #include "host-utils.h" //#define DEBUG_PCALL @@ -32,7 +33,7 @@ do {\ } while (0) #endif -const uint8_t parity_table[256] = { +static const uint8_t parity_table[256] = { CC_P, 0, 0, CC_P, 0, CC_P, CC_P, 0, 0, CC_P, CC_P, 0, CC_P, 0, 0, CC_P, 0, CC_P, CC_P, 0, CC_P, 0, 0, CC_P, @@ -68,7 +69,7 @@ const uint8_t parity_table[256] = { }; /* modulo 17 table */ -const uint8_t rclw_table[32] = { +static const uint8_t rclw_table[32] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9,10,11,12,13,14,15, 16, 0, 1, 2, 3, 4, 5, 6, @@ -76,14 +77,14 @@ const uint8_t rclw_table[32] = { }; /* modulo 9 table */ -const uint8_t rclb_table[32] = { +static const uint8_t rclb_table[32] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 0, 1, 2, 3, 4, 5, 6, 7, 8, 0, 1, 2, 3, 4, 5, 6, 7, 8, 0, 1, 2, 3, 4, }; -const CPU86_LDouble f15rk[7] = +static const CPU86_LDouble f15rk[7] = { 0.00000000000000000000L, 1.00000000000000000000L, @@ -995,6 +996,7 @@ static void do_interrupt64(int intno, int is_int, int error_code, } #endif +#ifdef TARGET_X86_64 #if defined(CONFIG_USER_ONLY) void helper_syscall(int next_eip_addend) { @@ -1011,7 +1013,6 @@ void helper_syscall(int next_eip_addend) raise_exception_err(EXCP06_ILLOP, 0); } selector = (env->star >> 32) & 0xffff; -#ifdef TARGET_X86_64 if (env->hflags & HF_LMA_MASK) { int code64; @@ -1037,9 +1038,7 @@ void helper_syscall(int next_eip_addend) env->eip = env->lstar; else env->eip = env->cstar; - } else -#endif - { + } else { ECX = (uint32_t)(env->eip + next_eip_addend); cpu_x86_set_cpl(env, 0); @@ -1058,7 +1057,9 @@ void helper_syscall(int next_eip_addend) } } #endif +#endif +#ifdef TARGET_X86_64 void helper_sysret(int dflag) { int cpl, selector; @@ -1071,7 +1072,6 @@ void helper_sysret(int dflag) raise_exception_err(EXCP0D_GPF, 0); } selector = (env->star >> 48) & 0xffff; -#ifdef TARGET_X86_64 if (env->hflags & HF_LMA_MASK) { if (dflag == 2) { cpu_x86_load_seg_cache(env, R_CS, (selector + 16) | 3, @@ -1097,9 +1097,7 @@ void helper_sysret(int dflag) load_eflags((uint32_t)(env->regs[11]), TF_MASK | AC_MASK | ID_MASK | IF_MASK | IOPL_MASK | VM_MASK | RF_MASK | NT_MASK); cpu_x86_set_cpl(env, 3); - } else -#endif - { + } else { cpu_x86_load_seg_cache(env, R_CS, selector | 3, 0, 0xffffffff, DESC_G_MASK | DESC_B_MASK | DESC_P_MASK | @@ -1123,6 +1121,7 @@ void helper_sysret(int dflag) } #endif } +#endif /* real mode interrupt */ static void do_interrupt_real(int intno, int is_int, int error_code, @@ -1285,8 +1284,8 @@ static int check_exception(int intno, int *error_code) * EIP value AFTER the interrupt instruction. It is only relevant if * is_int is TRUE. */ -void raise_interrupt(int intno, int is_int, int error_code, - int next_eip_addend) +static void raise_interrupt(int intno, int is_int, int error_code, + int next_eip_addend) { if (!is_int) { helper_svm_check_intercept_param(SVM_EXIT_EXCP_BASE + intno, error_code); @@ -1304,7 +1303,7 @@ void raise_interrupt(int intno, int is_int, int error_code, /* shortcuts to generate exceptions */ -void (raise_exception_err)(int exception_index, int error_code) +void raise_exception_err(int exception_index, int error_code) { raise_interrupt(exception_index, 0, error_code, 0); } @@ -1745,7 +1744,6 @@ void helper_aaa(void) } EAX = (EAX & ~0xffff) | al | (ah << 8); CC_SRC = eflags; - FORCE_RET(); } void helper_aas(void) @@ -1770,7 +1768,6 @@ void helper_aas(void) } EAX = (EAX & ~0xffff) | al | (ah << 8); CC_SRC = eflags; - FORCE_RET(); } void helper_daa(void) @@ -1798,7 +1795,6 @@ void helper_daa(void) eflags |= parity_table[al]; /* pf */ eflags |= (al & 0x80); /* sf */ CC_SRC = eflags; - FORCE_RET(); } void helper_das(void) @@ -1829,7 +1825,6 @@ void helper_das(void) eflags |= parity_table[al]; /* pf */ eflags |= (al & 0x80); /* sf */ CC_SRC = eflags; - FORCE_RET(); } void helper_into(int next_eip_addend) @@ -3323,7 +3318,7 @@ static inline CPU86_LDouble helper_fdiv(CPU86_LDouble a, CPU86_LDouble b) return a / b; } -void fpu_raise_exception(void) +static void fpu_raise_exception(void) { if (env->cr[0] & CR0_NE_MASK) { raise_exception(EXCP10_COPR); @@ -3553,7 +3548,6 @@ void helper_fcom_ST0_FT0(void) ret = floatx_compare(ST0, FT0, &env->fp_status); env->fpus = (env->fpus & ~0x4500) | fcom_ccval[ret + 1]; - FORCE_RET(); } void helper_fucom_ST0_FT0(void) @@ -3562,7 +3556,6 @@ void helper_fucom_ST0_FT0(void) ret = floatx_compare_quiet(ST0, FT0, &env->fp_status); env->fpus = (env->fpus & ~0x4500) | fcom_ccval[ret+ 1]; - FORCE_RET(); } static const int fcomi_ccval[4] = {CC_C, CC_Z, 0, CC_Z | CC_P | CC_C}; @@ -3576,7 +3569,6 @@ void helper_fcomi_ST0_FT0(void) eflags = helper_cc_compute_all(CC_OP); eflags = (eflags & ~(CC_Z | CC_P | CC_C)) | fcomi_ccval[ret + 1]; CC_SRC = eflags; - FORCE_RET(); } void helper_fucomi_ST0_FT0(void) @@ -3588,7 +3580,6 @@ void helper_fucomi_ST0_FT0(void) eflags = helper_cc_compute_all(CC_OP); eflags = (eflags & ~(CC_Z | CC_P | CC_C)) | fcomi_ccval[ret + 1]; CC_SRC = eflags; - FORCE_RET(); } void helper_fadd_ST0_FT0(void) @@ -3773,7 +3764,6 @@ void helper_fwait(void) { if (env->fpus & FPUS_SE) fpu_raise_exception(); - FORCE_RET(); } void helper_fninit(void) @@ -4629,7 +4619,6 @@ void helper_boundw(target_ulong a0, int v) if (v < low || v > high) { raise_exception(EXCP05_BOUND); } - FORCE_RET(); } void helper_boundl(target_ulong a0, int v) @@ -4640,7 +4629,6 @@ void helper_boundl(target_ulong a0, int v) if (v < low || v > high) { raise_exception(EXCP05_BOUND); } - FORCE_RET(); } static float approx_rsqrt(float a) @@ -4671,6 +4659,7 @@ static float approx_rcp(float a) #endif +#if !defined(CONFIG_USER_ONLY) /* try to fill the TLB and return an exception if error. If retaddr is NULL, it means that the function was called in C code (i.e. not from generated code or from helper.c) */ @@ -4703,7 +4692,7 @@ void tlb_fill(target_ulong addr, int is_write, int mmu_idx, void *retaddr) } env = saved_env; } - +#endif /* Secure Virtual Machine helpers */ diff --git a/qemu/target-i386/ops_sse.h b/qemu/target-i386/ops_sse.h index 720d97c4..03623058 100644 --- a/qemu/target-i386/ops_sse.h +++ b/qemu/target-i386/ops_sse.h @@ -58,7 +58,6 @@ void glue(helper_psrlw, SUFFIX)(Reg *d, Reg *s) d->W(7) >>= shift; #endif } - FORCE_RET(); } void glue(helper_psraw, SUFFIX)(Reg *d, Reg *s) @@ -104,7 +103,6 @@ void glue(helper_psllw, SUFFIX)(Reg *d, Reg *s) d->W(7) <<= shift; #endif } - FORCE_RET(); } void glue(helper_psrld, SUFFIX)(Reg *d, Reg *s) @@ -125,7 +123,6 @@ void glue(helper_psrld, SUFFIX)(Reg *d, Reg *s) d->L(3) >>= shift; #endif } - FORCE_RET(); } void glue(helper_psrad, SUFFIX)(Reg *d, Reg *s) @@ -163,7 +160,6 @@ void glue(helper_pslld, SUFFIX)(Reg *d, Reg *s) d->L(3) <<= shift; #endif } - FORCE_RET(); } void glue(helper_psrlq, SUFFIX)(Reg *d, Reg *s) @@ -182,7 +178,6 @@ void glue(helper_psrlq, SUFFIX)(Reg *d, Reg *s) d->Q(1) >>= shift; #endif } - FORCE_RET(); } void glue(helper_psllq, SUFFIX)(Reg *d, Reg *s) @@ -201,7 +196,6 @@ void glue(helper_psllq, SUFFIX)(Reg *d, Reg *s) d->Q(1) <<= shift; #endif } - FORCE_RET(); } #if SHIFT == 1 @@ -216,7 +210,6 @@ void glue(helper_psrldq, SUFFIX)(Reg *d, Reg *s) d->B(i) = d->B(i + shift); for(i = 16 - shift; i < 16; i++) d->B(i) = 0; - FORCE_RET(); } void glue(helper_pslldq, SUFFIX)(Reg *d, Reg *s) @@ -230,7 +223,6 @@ void glue(helper_pslldq, SUFFIX)(Reg *d, Reg *s) d->B(i) = d->B(i - shift); for(i = 0; i < shift; i++) d->B(i) = 0; - FORCE_RET(); } #endif @@ -432,7 +424,6 @@ void glue(helper_pmaddwd, SUFFIX) (Reg *d, Reg *s) d->L(i) = (int16_t)s->W(2*i) * (int16_t)d->W(2*i) + (int16_t)s->W(2*i+1) * (int16_t)d->W(2*i+1); } - FORCE_RET(); } #if SHIFT == 0 @@ -479,7 +470,6 @@ void glue(helper_maskmov, SUFFIX) (Reg *d, Reg *s, target_ulong a0) if (s->B(i) & 0x80) stb(a0 + i, d->B(i)); } - FORCE_RET(); } void glue(helper_movl_mm_T0, SUFFIX) (Reg *d, uint32_t val) @@ -917,7 +907,6 @@ void helper_ucomiss(Reg *d, Reg *s) s1 = s->XMM_S(0); ret = float32_compare_quiet(s0, s1, &env->sse_status); CC_SRC = comis_eflags[ret + 1]; - FORCE_RET(); } void helper_comiss(Reg *d, Reg *s) @@ -929,7 +918,6 @@ void helper_comiss(Reg *d, Reg *s) s1 = s->XMM_S(0); ret = float32_compare(s0, s1, &env->sse_status); CC_SRC = comis_eflags[ret + 1]; - FORCE_RET(); } void helper_ucomisd(Reg *d, Reg *s) @@ -941,7 +929,6 @@ void helper_ucomisd(Reg *d, Reg *s) d1 = s->XMM_D(0); ret = float64_compare_quiet(d0, d1, &env->sse_status); CC_SRC = comis_eflags[ret + 1]; - FORCE_RET(); } void helper_comisd(Reg *d, Reg *s) @@ -953,7 +940,6 @@ void helper_comisd(Reg *d, Reg *s) d1 = s->XMM_D(0); ret = float64_compare(d0, d1, &env->sse_status); CC_SRC = comis_eflags[ret + 1]; - FORCE_RET(); } uint32_t helper_movmskps(Reg *s) diff --git a/qemu/target-i386/translate.c b/qemu/target-i386/translate.c index 612811b0..3c71c957 100644 --- a/qemu/target-i386/translate.c +++ b/qemu/target-i386/translate.c @@ -6165,6 +6165,8 @@ static target_ulong disas_insn(DisasContext *s, target_ulong pc_start) tval += s->pc - s->cs_base; if (s->dflag == 0) tval &= 0xffff; + else if(!CODE64(s)) + tval &= 0xffffffff; gen_jmp(s, tval); break; case 0xea: /* ljmp im */ @@ -6564,6 +6566,7 @@ static target_ulong disas_insn(DisasContext *s, target_ulong pc_start) gen_jmp_im(pc_start - s->cs_base); gen_helper_into(tcg_const_i32(s->pc - pc_start)); break; +#ifdef WANT_ICEBP case 0xf1: /* icebp (undocumented, exits to external debugger) */ gen_svm_check_intercept(s, pc_start, SVM_EXIT_ICEBP); #if 1 @@ -6574,6 +6577,7 @@ static target_ulong disas_insn(DisasContext *s, target_ulong pc_start) cpu_set_log(CPU_LOG_INT | CPU_LOG_TB_IN_ASM); #endif break; +#endif case 0xfa: /* cli */ if (!s->vm86) { if (s->cpl <= s->iopl) { @@ -7074,7 +7078,11 @@ static target_ulong disas_insn(DisasContext *s, target_ulong pc_start) break; case 4: /* smsw */ gen_svm_check_intercept(s, pc_start, SVM_EXIT_READ_CR0); +#if defined TARGET_X86_64 && defined WORDS_BIGENDIAN + tcg_gen_ld32u_tl(cpu_T[0], cpu_env, offsetof(CPUX86State,cr[0]) + 4); +#else tcg_gen_ld32u_tl(cpu_T[0], cpu_env, offsetof(CPUX86State,cr[0])); +#endif gen_ldst_modrm(s, modrm, OT_WORD, OR_TMP0, 1); break; case 6: /* lmsw */ diff --git a/qemu/target-m68k/m68k-qreg.h b/qemu/target-m68k/m68k-qreg.h index 34bcb02e..c224d5ec 100644 --- a/qemu/target-m68k/m68k-qreg.h +++ b/qemu/target-m68k/m68k-qreg.h @@ -9,4 +9,3 @@ enum { #undef DEFR #undef DEFF64 }; - diff --git a/qemu/target-m68k/op_helper.c b/qemu/target-m68k/op_helper.c index aa36a335..c198e855 100644 --- a/qemu/target-m68k/op_helper.c +++ b/qemu/target-m68k/op_helper.c @@ -224,4 +224,3 @@ void HELPER(divs)(CPUState *env, uint32_t word) env->div2 = rem; env->cc_dest = flags; } - diff --git a/qemu/target-mips/machine.c b/qemu/target-mips/machine.c index f73b9e2f..15ce73cd 100644 --- a/qemu/target-mips/machine.c +++ b/qemu/target-mips/machine.c @@ -18,5 +18,3 @@ int cpu_load(QEMUFile *f, void *opaque, int version_id) { return 0; } - - diff --git a/qemu/target-mips/op_helper.c b/qemu/target-mips/op_helper.c index 390de7bb..27f58c2b 100644 --- a/qemu/target-mips/op_helper.c +++ b/qemu/target-mips/op_helper.c @@ -1701,7 +1701,7 @@ target_ulong do_ei (void) return t0; } -void debug_pre_eret (void) +static void debug_pre_eret (void) { fprintf(logfile, "ERET: PC " TARGET_FMT_lx " EPC " TARGET_FMT_lx, env->active_tc.PC, env->CP0_EPC); @@ -1712,7 +1712,7 @@ void debug_pre_eret (void) fputs("\n", logfile); } -void debug_post_eret (void) +static void debug_post_eret (void) { fprintf(logfile, " => PC " TARGET_FMT_lx " EPC " TARGET_FMT_lx, env->active_tc.PC, env->CP0_EPC); @@ -2776,7 +2776,7 @@ void do_cmpabs_d_ ## op (uint64_t fdt0, uint64_t fdt1, int cc) \ CLEAR_FP_COND(cc, env->active_fpu); \ } -int float64_is_unordered(int sig, float64 a, float64 b STATUS_PARAM) +static int float64_is_unordered(int sig, float64 a, float64 b STATUS_PARAM) { if (float64_is_signaling_nan(a) || float64_is_signaling_nan(b) || @@ -2834,7 +2834,7 @@ void do_cmpabs_s_ ## op (uint32_t fst0, uint32_t fst1, int cc) \ CLEAR_FP_COND(cc, env->active_fpu); \ } -flag float32_is_unordered(int sig, float32 a, float32 b STATUS_PARAM) +static flag float32_is_unordered(int sig, float32 a, float32 b STATUS_PARAM) { if (float32_is_signaling_nan(a) || float32_is_signaling_nan(b) || diff --git a/qemu/target-ppc/cpu.h b/qemu/target-ppc/cpu.h index 15ec6abe..2c565e65 100644 --- a/qemu/target-ppc/cpu.h +++ b/qemu/target-ppc/cpu.h @@ -296,13 +296,13 @@ typedef union ppc_tlb_t ppc_tlb_t; /* SPR access micro-ops generations callbacks */ struct ppc_spr_t { - void (*uea_read)(void *opaque, int spr_num); - void (*uea_write)(void *opaque, int spr_num); + void (*uea_read)(void *opaque, int gpr_num, int spr_num); + void (*uea_write)(void *opaque, int spr_num, int gpr_num); #if !defined(CONFIG_USER_ONLY) - void (*oea_read)(void *opaque, int spr_num); - void (*oea_write)(void *opaque, int spr_num); - void (*hea_read)(void *opaque, int spr_num); - void (*hea_write)(void *opaque, int spr_num); + void (*oea_read)(void *opaque, int gpr_num, int spr_num); + void (*oea_write)(void *opaque, int spr_num, int gpr_num); + void (*hea_read)(void *opaque, int gpr_num, int spr_num); + void (*hea_write)(void *opaque, int spr_num, int gpr_num); #endif const char *name; }; @@ -312,6 +312,9 @@ union ppc_avr_t { uint8_t u8[16]; uint16_t u16[8]; uint32_t u32[4]; + int8_t s8[16]; + int16_t s16[8]; + int32_t s32[4]; uint64_t u64[2]; }; @@ -530,10 +533,6 @@ struct CPUPPCState { /* First are the most commonly used resources * during translated code execution */ -#if TARGET_LONG_BITS > HOST_LONG_BITS - target_ulong t0; -#endif - /* general purpose registers */ target_ulong gpr[32]; #if !defined(TARGET_PPC64) @@ -683,35 +682,31 @@ void cpu_ppc_close (CPUPPCState *s); is returned if the signal was handled by the virtual CPU. */ int cpu_ppc_signal_handler (int host_signum, void *pinfo, void *puc); - +int cpu_ppc_handle_mmu_fault (CPUPPCState *env, target_ulong address, int rw, + int mmu_idx, int is_softmmu); +int get_physical_address (CPUPPCState *env, mmu_ctx_t *ctx, target_ulong vaddr, + int rw, int access_type); void do_interrupt (CPUPPCState *env); void ppc_hw_interrupt (CPUPPCState *env); -void dump_stack (CPUPPCState *env); +void cpu_dump_rfi (target_ulong RA, target_ulong msr); #if !defined(CONFIG_USER_ONLY) -target_ulong do_load_ibatu (CPUPPCState *env, int nr); -target_ulong do_load_ibatl (CPUPPCState *env, int nr); -void do_store_ibatu (CPUPPCState *env, int nr, target_ulong value); -void do_store_ibatl (CPUPPCState *env, int nr, target_ulong value); -target_ulong do_load_dbatu (CPUPPCState *env, int nr); -target_ulong do_load_dbatl (CPUPPCState *env, int nr); -void do_store_dbatu (CPUPPCState *env, int nr, target_ulong value); -void do_store_dbatl (CPUPPCState *env, int nr, target_ulong value); -void do_store_ibatu_601 (CPUPPCState *env, int nr, target_ulong value); -void do_store_ibatl_601 (CPUPPCState *env, int nr, target_ulong value); -target_ulong do_load_sdr1 (CPUPPCState *env); -void do_store_sdr1 (CPUPPCState *env, target_ulong value); +void ppc6xx_tlb_store (CPUPPCState *env, target_ulong EPN, int way, int is_code, + target_ulong pte0, target_ulong pte1); +void ppc_store_ibatu (CPUPPCState *env, int nr, target_ulong value); +void ppc_store_ibatl (CPUPPCState *env, int nr, target_ulong value); +void ppc_store_dbatu (CPUPPCState *env, int nr, target_ulong value); +void ppc_store_dbatl (CPUPPCState *env, int nr, target_ulong value); +void ppc_store_ibatu_601 (CPUPPCState *env, int nr, target_ulong value); +void ppc_store_ibatl_601 (CPUPPCState *env, int nr, target_ulong value); +void ppc_store_sdr1 (CPUPPCState *env, target_ulong value); #if defined(TARGET_PPC64) -target_ulong ppc_load_asr (CPUPPCState *env); void ppc_store_asr (CPUPPCState *env, target_ulong value); target_ulong ppc_load_slb (CPUPPCState *env, int slb_nr); void ppc_store_slb (CPUPPCState *env, int slb_nr, target_ulong rs); #endif /* defined(TARGET_PPC64) */ -#if 0 // Unused -target_ulong do_load_sr (CPUPPCState *env, int srnum); -#endif -void do_store_sr (CPUPPCState *env, int srnum, target_ulong value); +void ppc_store_sr (CPUPPCState *env, int srnum, target_ulong value); #endif /* !defined(CONFIG_USER_ONLY) */ void ppc_store_msr (CPUPPCState *env, target_ulong value); diff --git a/qemu/target-ppc/exec.h b/qemu/target-ppc/exec.h index cc7c924a..e9c7e65f 100644 --- a/qemu/target-ppc/exec.h +++ b/qemu/target-ppc/exec.h @@ -32,34 +32,12 @@ #define USE_PRECISE_EMULATION 0 register struct CPUPPCState *env asm(AREG0); -#if TARGET_LONG_BITS > HOST_LONG_BITS -/* no registers can be used */ -#define T0 (env->t0) #define TDX "%016" PRIx64 -#else -register target_ulong T0 asm(AREG1); -#define TDX "%016lx" -#endif - -#if defined (DEBUG_OP) -# define RETURN() __asm__ __volatile__("nop" : : : "memory"); -#else -# define RETURN() __asm__ __volatile__("" : : : "memory"); -#endif #if !defined(CONFIG_USER_ONLY) #include "softmmu_exec.h" #endif /* !defined(CONFIG_USER_ONLY) */ -void raise_exception_err (CPUState *env, int exception, int error_code); -void raise_exception (CPUState *env, int exception); - -int get_physical_address (CPUState *env, mmu_ctx_t *ctx, target_ulong vaddr, - int rw, int access_type); - -void ppc6xx_tlb_store (CPUState *env, target_ulong EPN, int way, int is_code, - target_ulong pte0, target_ulong pte1); - static always_inline void env_to_regs (void) { } @@ -68,9 +46,6 @@ static always_inline void regs_to_env (void) { } -int cpu_ppc_handle_mmu_fault (CPUState *env, target_ulong address, int rw, - int mmu_idx, int is_softmmu); - static always_inline int cpu_halted (CPUState *env) { if (!env->halted) diff --git a/qemu/target-ppc/helper.c b/qemu/target-ppc/helper.c index 47fa3f99..7a08f4ba 100644 --- a/qemu/target-ppc/helper.c +++ b/qemu/target-ppc/helper.c @@ -29,7 +29,6 @@ #include "exec-all.h" #include "helper_regs.h" #include "qemu-common.h" -#include "helper.h" #include "qemu-kvm.h" //#define DEBUG_MMU @@ -41,24 +40,6 @@ //#define FLUSH_ALL_TLBS /*****************************************************************************/ -/* Exceptions processing */ - -void raise_exception_err (CPUState *env, int exception, int error_code) -{ -#if 0 - printf("Raise exception %3x code : %d\n", exception, error_code); -#endif - env->exception_index = exception; - env->error_code = error_code; - cpu_loop_exit(); -} - -void raise_exception (CPUState *env, int exception) -{ - helper_raise_exception_err(exception, 0); -} - -/*****************************************************************************/ /* PowerPC MMU emulation */ #if defined(CONFIG_USER_ONLY) @@ -1225,7 +1206,7 @@ static always_inline void ppc4xx_tlb_invalidate_virt (CPUState *env, #endif } -int mmu40x_get_physical_address (CPUState *env, mmu_ctx_t *ctx, +static int mmu40x_get_physical_address (CPUState *env, mmu_ctx_t *ctx, target_ulong address, int rw, int access_type) { ppcemb_tlb_t *tlb; @@ -1307,9 +1288,9 @@ void store_40x_sler (CPUPPCState *env, uint32_t val) env->spr[SPR_405_SLER] = val; } -int mmubooke_get_physical_address (CPUState *env, mmu_ctx_t *ctx, - target_ulong address, int rw, - int access_type) +static int mmubooke_get_physical_address (CPUState *env, mmu_ctx_t *ctx, + target_ulong address, int rw, + int access_type) { ppcemb_tlb_t *tlb; target_phys_addr_t raddr; @@ -1511,10 +1492,7 @@ int cpu_ppc_handle_mmu_fault (CPUState *env, target_ulong address, int rw, access_type = ACCESS_CODE; } else { /* data access */ - /* XXX: put correct access by using cpu_restore_state() - correctly */ - access_type = ACCESS_INT; - // access_type = env->access_type; + access_type = env->access_type; } ret = get_physical_address(env, &ctx, address, rw, access_type); if (ret == 0) { @@ -1801,17 +1779,7 @@ static always_inline void dump_store_bat (CPUPPCState *env, char ID, #endif } -target_ulong do_load_ibatu (CPUPPCState *env, int nr) -{ - return env->IBAT[0][nr]; -} - -target_ulong do_load_ibatl (CPUPPCState *env, int nr) -{ - return env->IBAT[1][nr]; -} - -void do_store_ibatu (CPUPPCState *env, int nr, target_ulong value) +void ppc_store_ibatu (CPUPPCState *env, int nr, target_ulong value) { target_ulong mask; @@ -1837,23 +1805,13 @@ void do_store_ibatu (CPUPPCState *env, int nr, target_ulong value) } } -void do_store_ibatl (CPUPPCState *env, int nr, target_ulong value) +void ppc_store_ibatl (CPUPPCState *env, int nr, target_ulong value) { dump_store_bat(env, 'I', 1, nr, value); env->IBAT[1][nr] = value; } -target_ulong do_load_dbatu (CPUPPCState *env, int nr) -{ - return env->DBAT[0][nr]; -} - -target_ulong do_load_dbatl (CPUPPCState *env, int nr) -{ - return env->DBAT[1][nr]; -} - -void do_store_dbatu (CPUPPCState *env, int nr, target_ulong value) +void ppc_store_dbatu (CPUPPCState *env, int nr, target_ulong value) { target_ulong mask; @@ -1879,13 +1837,13 @@ void do_store_dbatu (CPUPPCState *env, int nr, target_ulong value) } } -void do_store_dbatl (CPUPPCState *env, int nr, target_ulong value) +void ppc_store_dbatl (CPUPPCState *env, int nr, target_ulong value) { dump_store_bat(env, 'D', 1, nr, value); env->DBAT[1][nr] = value; } -void do_store_ibatu_601 (CPUPPCState *env, int nr, target_ulong value) +void ppc_store_ibatu_601 (CPUPPCState *env, int nr, target_ulong value) { target_ulong mask; int do_inval; @@ -1922,7 +1880,7 @@ void do_store_ibatu_601 (CPUPPCState *env, int nr, target_ulong value) } } -void do_store_ibatl_601 (CPUPPCState *env, int nr, target_ulong value) +void ppc_store_ibatl_601 (CPUPPCState *env, int nr, target_ulong value) { target_ulong mask; int do_inval; @@ -2076,11 +2034,6 @@ void ppc_tlb_invalidate_one (CPUPPCState *env, target_ulong addr) /*****************************************************************************/ /* Special registers manipulation */ #if defined(TARGET_PPC64) -target_ulong ppc_load_asr (CPUPPCState *env) -{ - return env->asr; -} - void ppc_store_asr (CPUPPCState *env, target_ulong value) { if (env->asr != value) { @@ -2090,12 +2043,7 @@ void ppc_store_asr (CPUPPCState *env, target_ulong value) } #endif -target_ulong do_load_sdr1 (CPUPPCState *env) -{ - return env->sdr1; -} - -void do_store_sdr1 (CPUPPCState *env, target_ulong value) +void ppc_store_sdr1 (CPUPPCState *env, target_ulong value) { #if defined (DEBUG_MMU) if (loglevel != 0) { @@ -2111,7 +2059,7 @@ void do_store_sdr1 (CPUPPCState *env, target_ulong value) } } -void do_store_sr (CPUPPCState *env, int srnum, target_ulong value) +void ppc_store_sr (CPUPPCState *env, int srnum, target_ulong value) { #if defined (DEBUG_MMU) if (loglevel != 0) { @@ -2937,13 +2885,15 @@ void cpu_ppc_reset (void *opaque) #endif #if defined(CONFIG_USER_ONLY) msr |= (target_ulong)1 << MSR_FP; /* Allow floating point usage */ + msr |= (target_ulong)1 << MSR_VR; /* Allow altivec usage */ + msr |= (target_ulong)1 << MSR_SPE; /* Allow SPE usage */ msr |= (target_ulong)1 << MSR_PR; + env->msr = msr & env->msr_mask; #else env->nip = env->hreset_vector | env->excp_prefix; if (env->mmu_model != POWERPC_MMU_REAL) ppc_tlb_invalidate_all(env); #endif - env->msr = msr; hreg_compute_hflags(env); env->reserve = (target_ulong)-1ULL; /* Be sure no exception or interrupt is pending */ diff --git a/qemu/target-ppc/helper.h b/qemu/target-ppc/helper.h index 5b260785..6b5728c5 100644 --- a/qemu/target-ppc/helper.h +++ b/qemu/target-ppc/helper.h @@ -1,7 +1,7 @@ #include "def-helper.h" DEF_HELPER_2(raise_exception_err, void, i32, i32) -DEF_HELPER_0(raise_debug, void) +DEF_HELPER_1(raise_exception, void, i32) DEF_HELPER_3(tw, void, tl, tl, i32) #if defined(TARGET_PPC64) DEF_HELPER_3(td, void, tl, tl, i32) @@ -58,12 +58,13 @@ DEF_HELPER_0(reset_fpstatus, void) #endif DEF_HELPER_2(compute_fprf, i32, i64, i32) DEF_HELPER_2(store_fpscr, void, i64, i32) +DEF_HELPER_1(fpscr_clrbit, void, i32) DEF_HELPER_1(fpscr_setbit, void, i32) DEF_HELPER_1(float64_to_float32, i32, i64) DEF_HELPER_1(float32_to_float64, i64, i32) -DEF_HELPER_2(fcmpo, i32, i64, i64) -DEF_HELPER_2(fcmpu, i32, i64, i64) +DEF_HELPER_3(fcmpo, void, i64, i64, i32) +DEF_HELPER_3(fcmpu, void, i64, i64, i32) DEF_HELPER_1(fctiw, i64, i64) DEF_HELPER_1(fctiwz, i64, i64) @@ -184,7 +185,7 @@ DEF_HELPER_0(slbia, void) DEF_HELPER_1(slbie, void, tl) #endif DEF_HELPER_1(load_sr, tl, tl); -DEF_HELPER_2(store_sr, void, tl, tl); +DEF_HELPER_2(store_sr, void, tl, tl) DEF_HELPER_1(602_mfrom, tl, tl) #endif @@ -200,6 +201,43 @@ DEF_HELPER_2(divs, tl, tl, tl) DEF_HELPER_2(divso, tl, tl, tl) DEF_HELPER_1(load_dcr, tl, tl); -DEF_HELPER_2(store_dcr, void, tl, tl); +DEF_HELPER_2(store_dcr, void, tl, tl) + +DEF_HELPER_1(load_dump_spr, void, i32) +DEF_HELPER_1(store_dump_spr, void, i32) +DEF_HELPER_0(load_tbl, tl) +DEF_HELPER_0(load_tbu, tl) +DEF_HELPER_0(load_atbl, tl) +DEF_HELPER_0(load_atbu, tl) +DEF_HELPER_0(load_601_rtcl, tl) +DEF_HELPER_0(load_601_rtcu, tl) +#if !defined(CONFIG_USER_ONLY) +#if defined(TARGET_PPC64) +DEF_HELPER_1(store_asr, void, tl) +#endif +DEF_HELPER_1(store_sdr1, void, tl) +DEF_HELPER_1(store_tbl, void, tl) +DEF_HELPER_1(store_tbu, void, tl) +DEF_HELPER_1(store_atbl, void, tl) +DEF_HELPER_1(store_atbu, void, tl) +DEF_HELPER_1(store_601_rtcl, void, tl) +DEF_HELPER_1(store_601_rtcu, void, tl) +DEF_HELPER_0(load_decr, tl) +DEF_HELPER_1(store_decr, void, tl) +DEF_HELPER_1(store_hid0_601, void, tl) +DEF_HELPER_2(store_403_pbr, void, i32, tl) +DEF_HELPER_0(load_40x_pit, tl) +DEF_HELPER_1(store_40x_pit, void, tl) +DEF_HELPER_1(store_40x_dbcr0, void, tl) +DEF_HELPER_1(store_40x_sler, void, tl) +DEF_HELPER_1(store_booke_tcr, void, tl) +DEF_HELPER_1(store_booke_tsr, void, tl) +DEF_HELPER_2(store_ibatl, void, i32, tl) +DEF_HELPER_2(store_ibatu, void, i32, tl) +DEF_HELPER_2(store_dbatl, void, i32, tl) +DEF_HELPER_2(store_dbatu, void, i32, tl) +DEF_HELPER_2(store_601_batl, void, i32, tl) +DEF_HELPER_2(store_601_batu, void, i32, tl) +#endif #include "def-helper.h" diff --git a/qemu/target-ppc/op.c b/qemu/target-ppc/op.c deleted file mode 100644 index 868db837..00000000 --- a/qemu/target-ppc/op.c +++ /dev/null @@ -1,320 +0,0 @@ -/* - * PowerPC emulation micro-operations for qemu. - * - * Copyright (c) 2003-2007 Jocelyn Mayer - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -//#define DEBUG_OP - -#include "config.h" -#include "exec.h" -#include "host-utils.h" -#include "helper_regs.h" -#include "op_helper.h" - -#if !defined(CONFIG_USER_ONLY) -void OPPROTO op_load_sdr1 (void) -{ - T0 = env->sdr1; - RETURN(); -} - -void OPPROTO op_store_sdr1 (void) -{ - do_store_sdr1(env, T0); - RETURN(); -} - -#if defined (TARGET_PPC64) -void OPPROTO op_load_asr (void) -{ - T0 = env->asr; - RETURN(); -} - -void OPPROTO op_store_asr (void) -{ - ppc_store_asr(env, T0); - RETURN(); -} -#endif -#endif - -/* SPR */ -void OPPROTO op_load_spr (void) -{ - T0 = env->spr[PARAM1]; - RETURN(); -} - -void OPPROTO op_store_spr (void) -{ - env->spr[PARAM1] = T0; - RETURN(); -} - -void OPPROTO op_load_dump_spr (void) -{ - T0 = ppc_load_dump_spr(PARAM1); - RETURN(); -} - -void OPPROTO op_store_dump_spr (void) -{ - ppc_store_dump_spr(PARAM1, T0); - RETURN(); -} - -void OPPROTO op_mask_spr (void) -{ - env->spr[PARAM1] &= ~T0; - RETURN(); -} - -void OPPROTO op_load_tbl (void) -{ - T0 = cpu_ppc_load_tbl(env); - RETURN(); -} - -void OPPROTO op_load_tbu (void) -{ - T0 = cpu_ppc_load_tbu(env); - RETURN(); -} - -void OPPROTO op_load_atbl (void) -{ - T0 = cpu_ppc_load_atbl(env); - RETURN(); -} - -void OPPROTO op_load_atbu (void) -{ - T0 = cpu_ppc_load_atbu(env); - RETURN(); -} - -#if !defined(CONFIG_USER_ONLY) -void OPPROTO op_store_tbl (void) -{ - cpu_ppc_store_tbl(env, T0); - RETURN(); -} - -void OPPROTO op_store_tbu (void) -{ - cpu_ppc_store_tbu(env, T0); - RETURN(); -} - -void OPPROTO op_store_atbl (void) -{ - cpu_ppc_store_atbl(env, T0); - RETURN(); -} - -void OPPROTO op_store_atbu (void) -{ - cpu_ppc_store_atbu(env, T0); - RETURN(); -} - -void OPPROTO op_load_decr (void) -{ - T0 = cpu_ppc_load_decr(env); - RETURN(); -} - -void OPPROTO op_store_decr (void) -{ - cpu_ppc_store_decr(env, T0); - RETURN(); -} - -void OPPROTO op_load_ibat (void) -{ - T0 = env->IBAT[PARAM1][PARAM2]; - RETURN(); -} - -void OPPROTO op_store_ibatu (void) -{ - do_store_ibatu(env, PARAM1, T0); - RETURN(); -} - -void OPPROTO op_store_ibatl (void) -{ -#if 1 - env->IBAT[1][PARAM1] = T0; -#else - do_store_ibatl(env, PARAM1, T0); -#endif - RETURN(); -} - -void OPPROTO op_load_dbat (void) -{ - T0 = env->DBAT[PARAM1][PARAM2]; - RETURN(); -} - -void OPPROTO op_store_dbatu (void) -{ - do_store_dbatu(env, PARAM1, T0); - RETURN(); -} - -void OPPROTO op_store_dbatl (void) -{ -#if 1 - env->DBAT[1][PARAM1] = T0; -#else - do_store_dbatl(env, PARAM1, T0); -#endif - RETURN(); -} -#endif /* !defined(CONFIG_USER_ONLY) */ - -/* Return from interrupt */ -#if !defined(CONFIG_USER_ONLY) -/* Exception vectors */ -void OPPROTO op_store_excp_prefix (void) -{ - T0 &= env->ivpr_mask; - env->excp_prefix = T0; - RETURN(); -} - -void OPPROTO op_store_excp_vector (void) -{ - T0 &= env->ivor_mask; - env->excp_vectors[PARAM1] = T0; - RETURN(); -} -#endif - -/* 601 specific */ -void OPPROTO op_load_601_rtcl (void) -{ - T0 = cpu_ppc601_load_rtcl(env); - RETURN(); -} - -void OPPROTO op_load_601_rtcu (void) -{ - T0 = cpu_ppc601_load_rtcu(env); - RETURN(); -} - -#if !defined(CONFIG_USER_ONLY) -void OPPROTO op_store_601_rtcl (void) -{ - cpu_ppc601_store_rtcl(env, T0); - RETURN(); -} - -void OPPROTO op_store_601_rtcu (void) -{ - cpu_ppc601_store_rtcu(env, T0); - RETURN(); -} - -void OPPROTO op_store_hid0_601 (void) -{ - do_store_hid0_601(); - RETURN(); -} - -void OPPROTO op_load_601_bat (void) -{ - T0 = env->IBAT[PARAM1][PARAM2]; - RETURN(); -} - -void OPPROTO op_store_601_batl (void) -{ - do_store_ibatl_601(env, PARAM1, T0); - RETURN(); -} - -void OPPROTO op_store_601_batu (void) -{ - do_store_ibatu_601(env, PARAM1, T0); - RETURN(); -} -#endif /* !defined(CONFIG_USER_ONLY) */ - -/* SPR micro-ops */ -/* 440 specific */ -#if !defined(CONFIG_USER_ONLY) -void OPPROTO op_store_pir (void) -{ - env->spr[SPR_PIR] = T0 & 0x0000000FUL; - RETURN(); -} - -void OPPROTO op_load_403_pb (void) -{ - do_load_403_pb(PARAM1); - RETURN(); -} - -void OPPROTO op_store_403_pb (void) -{ - do_store_403_pb(PARAM1); - RETURN(); -} - -void OPPROTO op_load_40x_pit (void) -{ - T0 = load_40x_pit(env); - RETURN(); -} - -void OPPROTO op_store_40x_pit (void) -{ - store_40x_pit(env, T0); - RETURN(); -} - -void OPPROTO op_store_40x_dbcr0 (void) -{ - store_40x_dbcr0(env, T0); - RETURN(); -} - -void OPPROTO op_store_40x_sler (void) -{ - store_40x_sler(env, T0); - RETURN(); -} - -void OPPROTO op_store_booke_tcr (void) -{ - store_booke_tcr(env, T0); - RETURN(); -} - -void OPPROTO op_store_booke_tsr (void) -{ - store_booke_tsr(env, T0); - RETURN(); -} -#endif /* !defined(CONFIG_USER_ONLY) */ - diff --git a/qemu/target-ppc/op_helper.c b/qemu/target-ppc/op_helper.c index a4dc41d0..7cd589a1 100644 --- a/qemu/target-ppc/op_helper.c +++ b/qemu/target-ppc/op_helper.c @@ -22,7 +22,6 @@ #include "helper.h" #include "helper_regs.h" -#include "op_helper.h" //#define DEBUG_OP //#define DEBUG_EXCEPTIONS @@ -33,12 +32,17 @@ void helper_raise_exception_err (uint32_t exception, uint32_t error_code) { - raise_exception_err(env, exception, error_code); +#if 0 + printf("Raise exception %3x code : %d\n", exception, error_code); +#endif + env->exception_index = exception; + env->error_code = error_code; + cpu_loop_exit(); } -void helper_raise_debug (void) +void helper_raise_exception (uint32_t exception) { - raise_exception(env, EXCP_DEBUG); + helper_raise_exception_err(exception, 0); } /*****************************************************************************/ @@ -65,77 +69,244 @@ void helper_store_cr (target_ulong val, uint32_t mask) } } -#if defined(TARGET_PPC64) -void do_store_pri (int prio) +/*****************************************************************************/ +/* SPR accesses */ +void helper_load_dump_spr (uint32_t sprn) { - env->spr[SPR_PPR] &= ~0x001C000000000000ULL; - env->spr[SPR_PPR] |= ((uint64_t)prio & 0x7) << 50; + if (loglevel != 0) { + fprintf(logfile, "Read SPR %d %03x => " ADDRX "\n", + sprn, sprn, env->spr[sprn]); + } } -#endif -target_ulong ppc_load_dump_spr (int sprn) +void helper_store_dump_spr (uint32_t sprn) { if (loglevel != 0) { - fprintf(logfile, "Read SPR %d %03x => " ADDRX "\n", + fprintf(logfile, "Write SPR %d %03x <= " ADDRX "\n", sprn, sprn, env->spr[sprn]); } +} - return env->spr[sprn]; +target_ulong helper_load_tbl (void) +{ + return cpu_ppc_load_tbl(env); } -void ppc_store_dump_spr (int sprn, target_ulong val) +target_ulong helper_load_tbu (void) { - if (loglevel != 0) { - fprintf(logfile, "Write SPR %d %03x => " ADDRX " <= " ADDRX "\n", - sprn, sprn, env->spr[sprn], val); + return cpu_ppc_load_tbu(env); +} + +target_ulong helper_load_atbl (void) +{ + return cpu_ppc_load_atbl(env); +} + +target_ulong helper_load_atbu (void) +{ + return cpu_ppc_load_atbu(env); +} + +target_ulong helper_load_601_rtcl (void) +{ + return cpu_ppc601_load_rtcl(env); +} + +target_ulong helper_load_601_rtcu (void) +{ + return cpu_ppc601_load_rtcu(env); +} + +#if !defined(CONFIG_USER_ONLY) +#if defined (TARGET_PPC64) +void helper_store_asr (target_ulong val) +{ + ppc_store_asr(env, val); +} +#endif + +void helper_store_sdr1 (target_ulong val) +{ + ppc_store_sdr1(env, val); +} + +void helper_store_tbl (target_ulong val) +{ + cpu_ppc_store_tbl(env, val); +} + +void helper_store_tbu (target_ulong val) +{ + cpu_ppc_store_tbu(env, val); +} + +void helper_store_atbl (target_ulong val) +{ + cpu_ppc_store_atbl(env, val); +} + +void helper_store_atbu (target_ulong val) +{ + cpu_ppc_store_atbu(env, val); +} + +void helper_store_601_rtcl (target_ulong val) +{ + cpu_ppc601_store_rtcl(env, val); +} + +void helper_store_601_rtcu (target_ulong val) +{ + cpu_ppc601_store_rtcu(env, val); +} + +target_ulong helper_load_decr (void) +{ + return cpu_ppc_load_decr(env); +} + +void helper_store_decr (target_ulong val) +{ + cpu_ppc_store_decr(env, val); +} + +void helper_store_hid0_601 (target_ulong val) +{ + target_ulong hid0; + + hid0 = env->spr[SPR_HID0]; + if ((val ^ hid0) & 0x00000008) { + /* Change current endianness */ + env->hflags &= ~(1 << MSR_LE); + env->hflags_nmsr &= ~(1 << MSR_LE); + env->hflags_nmsr |= (1 << MSR_LE) & (((val >> 3) & 1) << MSR_LE); + env->hflags |= env->hflags_nmsr; + if (loglevel != 0) { + fprintf(logfile, "%s: set endianness to %c => " ADDRX "\n", + __func__, val & 0x8 ? 'l' : 'b', env->hflags); + } } - env->spr[sprn] = val; + env->spr[SPR_HID0] = (uint32_t)val; +} + +void helper_store_403_pbr (uint32_t num, target_ulong value) +{ + if (likely(env->pb[num] != value)) { + env->pb[num] = value; + /* Should be optimized */ + tlb_flush(env, 1); + } +} + +target_ulong helper_load_40x_pit (void) +{ + return load_40x_pit(env); +} + +void helper_store_40x_pit (target_ulong val) +{ + store_40x_pit(env, val); +} + +void helper_store_40x_dbcr0 (target_ulong val) +{ + store_40x_dbcr0(env, val); +} + +void helper_store_40x_sler (target_ulong val) +{ + store_40x_sler(env, val); +} + +void helper_store_booke_tcr (target_ulong val) +{ + store_booke_tcr(env, val); +} + +void helper_store_booke_tsr (target_ulong val) +{ + store_booke_tsr(env, val); +} + +void helper_store_ibatu (uint32_t nr, target_ulong val) +{ + ppc_store_ibatu(env, nr, val); +} + +void helper_store_ibatl (uint32_t nr, target_ulong val) +{ + ppc_store_ibatl(env, nr, val); +} + +void helper_store_dbatu (uint32_t nr, target_ulong val) +{ + ppc_store_dbatu(env, nr, val); +} + +void helper_store_dbatl (uint32_t nr, target_ulong val) +{ + ppc_store_dbatl(env, nr, val); } +void helper_store_601_batl (uint32_t nr, target_ulong val) +{ + ppc_store_ibatl_601(env, nr, val); +} + +void helper_store_601_batu (uint32_t nr, target_ulong val) +{ + ppc_store_ibatu_601(env, nr, val); +} +#endif + /*****************************************************************************/ /* Memory load and stores */ -static always_inline target_ulong get_addr(target_ulong addr) +static always_inline target_ulong addr_add(target_ulong addr, target_long arg) { #if defined(TARGET_PPC64) - if (msr_sf) - return addr; + if (!msr_sf) + return (uint32_t)(addr + arg); else #endif - return (uint32_t)addr; + return addr + arg; } void helper_lmw (target_ulong addr, uint32_t reg) { - for (; reg < 32; reg++, addr += 4) { + for (; reg < 32; reg++) { if (msr_le) - env->gpr[reg] = bswap32(ldl(get_addr(addr))); + env->gpr[reg] = bswap32(ldl(addr)); else - env->gpr[reg] = ldl(get_addr(addr)); + env->gpr[reg] = ldl(addr); + addr = addr_add(addr, 4); } } void helper_stmw (target_ulong addr, uint32_t reg) { - for (; reg < 32; reg++, addr += 4) { + for (; reg < 32; reg++) { if (msr_le) - stl(get_addr(addr), bswap32((uint32_t)env->gpr[reg])); + stl(addr, bswap32((uint32_t)env->gpr[reg])); else - stl(get_addr(addr), (uint32_t)env->gpr[reg]); + stl(addr, (uint32_t)env->gpr[reg]); + addr = addr_add(addr, 4); } } void helper_lsw(target_ulong addr, uint32_t nb, uint32_t reg) { int sh; - for (; nb > 3; nb -= 4, addr += 4) { - env->gpr[reg] = ldl(get_addr(addr)); + for (; nb > 3; nb -= 4) { + env->gpr[reg] = ldl(addr); reg = (reg + 1) % 32; + addr = addr_add(addr, 4); } if (unlikely(nb > 0)) { env->gpr[reg] = 0; - for (sh = 24; nb > 0; nb--, addr++, sh -= 8) { - env->gpr[reg] |= ldub(get_addr(addr)) << sh; + for (sh = 24; nb > 0; nb--, sh -= 8) { + env->gpr[reg] |= ldub(addr) << sh; + addr = addr_add(addr, 1); } } } @@ -149,9 +320,9 @@ void helper_lswx(target_ulong addr, uint32_t reg, uint32_t ra, uint32_t rb) if (likely(xer_bc != 0)) { if (unlikely((ra != 0 && reg < ra && (reg + xer_bc) > ra) || (reg < rb && (reg + xer_bc) > rb))) { - raise_exception_err(env, POWERPC_EXCP_PROGRAM, - POWERPC_EXCP_INVAL | - POWERPC_EXCP_INVAL_LSWX); + helper_raise_exception_err(POWERPC_EXCP_PROGRAM, + POWERPC_EXCP_INVAL | + POWERPC_EXCP_INVAL_LSWX); } else { helper_lsw(addr, xer_bc, reg); } @@ -161,25 +332,26 @@ void helper_lswx(target_ulong addr, uint32_t reg, uint32_t ra, uint32_t rb) void helper_stsw(target_ulong addr, uint32_t nb, uint32_t reg) { int sh; - for (; nb > 3; nb -= 4, addr += 4) { - stl(get_addr(addr), env->gpr[reg]); + for (; nb > 3; nb -= 4) { + stl(addr, env->gpr[reg]); reg = (reg + 1) % 32; + addr = addr_add(addr, 4); } if (unlikely(nb > 0)) { - for (sh = 24; nb > 0; nb--, addr++, sh -= 8) - stb(get_addr(addr), (env->gpr[reg] >> sh) & 0xFF); + for (sh = 24; nb > 0; nb--, sh -= 8) + stb(addr, (env->gpr[reg] >> sh) & 0xFF); + addr = addr_add(addr, 1); } } static void do_dcbz(target_ulong addr, int dcache_line_size) { - target_long mask = get_addr(~(dcache_line_size - 1)); + addr &= ~(dcache_line_size - 1); int i; - addr &= mask; for (i = 0 ; i < dcache_line_size ; i += 4) { stl(addr + i , 0); } - if ((env->reserve & mask) == addr) + if (env->reserve == addr) env->reserve = (target_ulong)-1ULL; } @@ -200,7 +372,7 @@ void helper_icbi(target_ulong addr) { uint32_t tmp; - addr = get_addr(addr & ~(env->dcache_line_size - 1)); + addr &= ~(env->dcache_line_size - 1); /* Invalidate one cache line : * PowerPC specification says this is to be treated like a load * (not a fetch) by the MMU. To be sure it will be so, @@ -216,7 +388,8 @@ target_ulong helper_lscbx (target_ulong addr, uint32_t reg, uint32_t ra, uint32_ int i, c, d; d = 24; for (i = 0; i < xer_bc; i++) { - c = ldub((uint32_t)addr++); + c = ldub(addr); + addr = addr_add(addr, 1); /* ra (if not 0) and rb are never modified */ if (likely(reg != rb && (ra == 0 || reg != ra))) { env->gpr[reg] = (env->gpr[reg] & ~(0xFF << d)) | (c << d); @@ -570,7 +743,7 @@ static always_inline uint64_t fload_invalid_op_excp (int op) /* Update the floating-point enabled exception summary */ env->fpscr |= 1 << FPSCR_FEX; if (msr_fe0 != 0 || msr_fe1 != 0) - raise_exception_err(env, POWERPC_EXCP_PROGRAM, POWERPC_EXCP_FP | op); + helper_raise_exception_err(POWERPC_EXCP_PROGRAM, POWERPC_EXCP_FP | op); } return ret; } @@ -585,8 +758,8 @@ static always_inline uint64_t float_zero_divide_excp (uint64_t arg1, uint64_t ar /* Update the floating-point enabled exception summary */ env->fpscr |= 1 << FPSCR_FEX; if (msr_fe0 != 0 || msr_fe1 != 0) { - raise_exception_err(env, POWERPC_EXCP_PROGRAM, - POWERPC_EXCP_FP | POWERPC_EXCP_FP_ZX); + helper_raise_exception_err(POWERPC_EXCP_PROGRAM, + POWERPC_EXCP_FP | POWERPC_EXCP_FP_ZX); } } else { /* Set the result to infinity */ @@ -670,6 +843,24 @@ static always_inline void fpscr_set_rounding_mode (void) set_float_rounding_mode(rnd_type, &env->fp_status); } +void helper_fpscr_clrbit (uint32_t bit) +{ + int prev; + + prev = (env->fpscr >> bit) & 1; + env->fpscr &= ~(1 << bit); + if (prev == 1) { + switch (bit) { + case FPSCR_RN1: + case FPSCR_RN: + fpscr_set_rounding_mode(); + break; + default: + break; + } + } +} + void helper_fpscr_setbit (uint32_t bit) { int prev; @@ -795,9 +986,9 @@ void helper_store_fpscr (uint64_t arg, uint32_t mask) prev = env->fpscr; new = (uint32_t)arg; - new &= ~0x90000000; - new |= prev & 0x90000000; - for (i = 0; i < 7; i++) { + new &= ~0x60000000; + new |= prev & 0x60000000; + for (i = 0; i < 8; i++) { if (mask & (1 << i)) { env->fpscr &= ~(0xF << (4 * i)); env->fpscr |= new & (0xF << (4 * i)); @@ -826,29 +1017,31 @@ void helper_float_check_status (void) (env->error_code & POWERPC_EXCP_FP)) { /* Differred floating-point exception after target FPR update */ if (msr_fe0 != 0 || msr_fe1 != 0) - raise_exception_err(env, env->exception_index, env->error_code); - } else if (env->fp_status.float_exception_flags & float_flag_overflow) { - float_overflow_excp(); - } else if (env->fp_status.float_exception_flags & float_flag_underflow) { - float_underflow_excp(); - } else if (env->fp_status.float_exception_flags & float_flag_inexact) { - float_inexact_excp(); + helper_raise_exception_err(env->exception_index, env->error_code); + } else { + int status = get_float_exception_flags(&env->fp_status); + if (status & float_flag_overflow) { + float_overflow_excp(); + } else if (status & float_flag_underflow) { + float_underflow_excp(); + } else if (status & float_flag_inexact) { + float_inexact_excp(); + } } #else if (env->exception_index == POWERPC_EXCP_PROGRAM && (env->error_code & POWERPC_EXCP_FP)) { /* Differred floating-point exception after target FPR update */ if (msr_fe0 != 0 || msr_fe1 != 0) - raise_exception_err(env, env->exception_index, env->error_code); + helper_raise_exception_err(env->exception_index, env->error_code); } - RETURN(); #endif } #ifdef CONFIG_SOFTFLOAT void helper_reset_fpstatus (void) { - env->fp_status.float_exception_flags = 0; + set_float_exception_flags(0, &env->fp_status); } #endif @@ -869,7 +1062,7 @@ uint64_t helper_fadd (uint64_t arg1, uint64_t arg2) farg1.d = float64_add(farg1.d, farg2.d, &env->fp_status); } else { /* Magnitude subtraction of infinities */ - farg1.ll == fload_invalid_op_excp(POWERPC_EXCP_FP_VXISI); + farg1.ll = fload_invalid_op_excp(POWERPC_EXCP_FP_VXISI); } #else farg1.d = float64_add(farg1.d, farg2.d, &env->fp_status); @@ -923,7 +1116,6 @@ uint64_t helper_fmul (uint64_t arg1, uint64_t arg2) } else { farg1.d = float64_mul(farg1.d, farg2.d, &env->fp_status); } -} #else farg1.d = float64_mul(farg1.d, farg2.d, &env->fp_status); #endif @@ -948,7 +1140,7 @@ uint64_t helper_fdiv (uint64_t arg1, uint64_t arg2) } else if (unlikely(iszero(farg2.d))) { if (iszero(farg1.d)) { /* Division of zero by zero */ - farg1.ll fload_invalid_op_excp(POWERPC_EXCP_FP_VXZDZ); + farg1.ll = fload_invalid_op_excp(POWERPC_EXCP_FP_VXZDZ); } else { /* Division by zero */ farg1.ll = float_zero_divide_excp(farg1.d, farg2.d); @@ -1236,7 +1428,7 @@ uint64_t helper_fnmadd (uint64_t arg1, uint64_t arg2, uint64_t arg3) farg1.d = float64_mul(farg1.d, farg2.d, &env->fp_status); farg1.d = float64_add(farg1.d, farg3.d, &env->fp_status); #endif - if (likely(!isnan(farg1.d))) + if (likely(!float64_is_nan(farg1.d))) farg1.d = float64_chs(farg1.d); } return farg1.ll; @@ -1276,7 +1468,7 @@ uint64_t helper_fnmsub (uint64_t arg1, uint64_t arg2, uint64_t arg3) farg1.d = float64_mul(farg1.d, farg2.d, &env->fp_status); farg1.d = float64_sub(farg1.d, farg3.d, &env->fp_status); #endif - if (likely(!isnan(farg1.d))) + if (likely(!float64_is_nan(farg1.d))) farg1.d = float64_chs(farg1.d); } return farg1.ll; @@ -1286,6 +1478,7 @@ uint64_t helper_fnmsub (uint64_t arg1, uint64_t arg2, uint64_t arg3) uint64_t helper_frsp (uint64_t arg) { CPU_DoubleU farg; + float32 f32; farg.ll = arg; #if USE_PRECISE_EMULATION @@ -1293,10 +1486,12 @@ uint64_t helper_frsp (uint64_t arg) /* sNaN square root */ farg.ll = fload_invalid_op_excp(POWERPC_EXCP_FP_VXSNAN); } else { - fard.d = float64_to_float32(farg.d, &env->fp_status); + f32 = float64_to_float32(farg.d, &env->fp_status); + farg.d = float32_to_float64(f32, &env->fp_status); } #else - farg.d = float64_to_float32(farg.d, &env->fp_status); + f32 = float64_to_float32(farg.d, &env->fp_status); + farg.d = float32_to_float64(f32, &env->fp_status); #endif return farg.ll; } @@ -1338,7 +1533,7 @@ uint64_t helper_fre (uint64_t arg) farg.ll = 0xFFF0000000000000ULL; } else if (farg.ll == 0x0000000000000000ULL) { farg.ll = 0x7FF0000000000000ULL; - } else if (isnan(farg.d)) { + } else if (float64_is_nan(farg.d)) { farg.ll = 0x7FF8000000000000ULL; } else if (fpisneg(farg.d)) { farg.ll = 0x8000000000000000ULL; @@ -1373,7 +1568,7 @@ uint64_t helper_fres (uint64_t arg) farg.ll = 0xFFF0000000000000ULL; } else if (farg.ll == 0x0000000000000000ULL) { farg.ll = 0x7FF0000000000000ULL; - } else if (isnan(farg.d)) { + } else if (float64_is_nan(farg.d)) { farg.ll = 0x7FF8000000000000ULL; } else if (fpisneg(farg.d)) { farg.ll = 0x8000000000000000ULL; @@ -1404,7 +1599,7 @@ uint64_t helper_frsqrte (uint64_t arg) farg.ll = 0xFFF0000000000000ULL; } else if (farg.ll == 0x0000000000000000ULL) { farg.ll = 0x7FF0000000000000ULL; - } else if (isnan(farg.d)) { + } else if (float64_is_nan(farg.d)) { farg.ll |= 0x000FFFFFFFFFFFFFULL; } else if (fpisneg(farg.d)) { farg.ll = 0x7FF8000000000000ULL; @@ -1418,44 +1613,46 @@ uint64_t helper_frsqrte (uint64_t arg) /* fsel - fsel. */ uint64_t helper_fsel (uint64_t arg1, uint64_t arg2, uint64_t arg3) { - CPU_DoubleU farg1, farg2, farg3; + CPU_DoubleU farg1; farg1.ll = arg1; - farg2.ll = arg2; - farg3.ll = arg3; if (!fpisneg(farg1.d) || iszero(farg1.d)) - return farg2.ll; + return arg2; else - return farg2.ll; + return arg3; } -uint32_t helper_fcmpu (uint64_t arg1, uint64_t arg2) +void helper_fcmpu (uint64_t arg1, uint64_t arg2, uint32_t crfD) { CPU_DoubleU farg1, farg2; uint32_t ret = 0; farg1.ll = arg1; farg2.ll = arg2; - if (unlikely(float64_is_signaling_nan(farg1.d) || - float64_is_signaling_nan(farg2.d))) { - /* sNaN comparison */ - fload_invalid_op_excp(POWERPC_EXCP_FP_VXSNAN); + if (unlikely(float64_is_nan(farg1.d) || + float64_is_nan(farg2.d))) { + ret = 0x01UL; + } else if (float64_lt(farg1.d, farg2.d, &env->fp_status)) { + ret = 0x08UL; + } else if (!float64_le(farg1.d, farg2.d, &env->fp_status)) { + ret = 0x04UL; } else { - if (float64_lt(farg1.d, farg2.d, &env->fp_status)) { - ret = 0x08UL; - } else if (!float64_le(farg1.d, farg2.d, &env->fp_status)) { - ret = 0x04UL; - } else { - ret = 0x02UL; - } + ret = 0x02UL; } + env->fpscr &= ~(0x0F << FPSCR_FPRF); env->fpscr |= ret << FPSCR_FPRF; - return ret; + env->crf[crfD] = ret; + if (unlikely(ret == 0x01UL + && (float64_is_signaling_nan(farg1.d) || + float64_is_signaling_nan(farg2.d)))) { + /* sNaN comparison */ + fload_invalid_op_excp(POWERPC_EXCP_FP_VXSNAN); + } } -uint32_t helper_fcmpo (uint64_t arg1, uint64_t arg2) +void helper_fcmpo (uint64_t arg1, uint64_t arg2, uint32_t crfD) { CPU_DoubleU farg1, farg2; uint32_t ret = 0; @@ -1464,6 +1661,19 @@ uint32_t helper_fcmpo (uint64_t arg1, uint64_t arg2) if (unlikely(float64_is_nan(farg1.d) || float64_is_nan(farg2.d))) { + ret = 0x01UL; + } else if (float64_lt(farg1.d, farg2.d, &env->fp_status)) { + ret = 0x08UL; + } else if (!float64_le(farg1.d, farg2.d, &env->fp_status)) { + ret = 0x04UL; + } else { + ret = 0x02UL; + } + + env->fpscr &= ~(0x0F << FPSCR_FPRF); + env->fpscr |= ret << FPSCR_FPRF; + env->crf[crfD] = ret; + if (unlikely (ret == 0x01UL)) { if (float64_is_signaling_nan(farg1.d) || float64_is_signaling_nan(farg2.d)) { /* sNaN comparison */ @@ -1473,18 +1683,7 @@ uint32_t helper_fcmpo (uint64_t arg1, uint64_t arg2) /* qNaN comparison */ fload_invalid_op_excp(POWERPC_EXCP_FP_VXVC); } - } else { - if (float64_lt(farg1.d, farg2.d, &env->fp_status)) { - ret = 0x08UL; - } else if (!float64_le(farg1.d, farg2.d, &env->fp_status)) { - ret = 0x04UL; - } else { - ret = 0x02UL; - } } - env->fpscr &= ~(0x0F << FPSCR_FPRF); - env->fpscr |= ret << FPSCR_FPRF; - return ret; } #if !defined (CONFIG_USER_ONLY) @@ -1493,12 +1692,10 @@ void helper_store_msr (target_ulong val) val = hreg_store_msr(env, val, 0); if (val != 0) { env->interrupt_request |= CPU_INTERRUPT_EXITTB; - raise_exception(env, val); + helper_raise_exception(val); } } -void cpu_dump_rfi (target_ulong RA, target_ulong msr); - static always_inline void do_rfi (target_ulong nip, target_ulong msr, target_ulong msrm, int keep_msrh) { @@ -1556,7 +1753,7 @@ void helper_tw (target_ulong arg1, target_ulong arg2, uint32_t flags) ((int32_t)arg1 == (int32_t)arg2 && (flags & 0x04)) || ((uint32_t)arg1 < (uint32_t)arg2 && (flags & 0x02)) || ((uint32_t)arg1 > (uint32_t)arg2 && (flags & 0x01))))) { - raise_exception_err(env, POWERPC_EXCP_PROGRAM, POWERPC_EXCP_TRAP); + helper_raise_exception_err(POWERPC_EXCP_PROGRAM, POWERPC_EXCP_TRAP); } } @@ -1568,24 +1765,12 @@ void helper_td (target_ulong arg1, target_ulong arg2, uint32_t flags) ((int64_t)arg1 == (int64_t)arg2 && (flags & 0x04)) || ((uint64_t)arg1 < (uint64_t)arg2 && (flags & 0x02)) || ((uint64_t)arg1 > (uint64_t)arg2 && (flags & 0x01))))) - raise_exception_err(env, POWERPC_EXCP_PROGRAM, POWERPC_EXCP_TRAP); + helper_raise_exception_err(POWERPC_EXCP_PROGRAM, POWERPC_EXCP_TRAP); } #endif /*****************************************************************************/ /* PowerPC 601 specific instructions (POWER bridge) */ -void do_POWER_abso (void) -{ - if ((int32_t)T0 == INT32_MIN) { - T0 = INT32_MAX; - env->xer |= (1 << XER_OV) | (1 << XER_SO); - } else if ((int32_t)T0 < 0) { - T0 = -T0; - env->xer &= ~(1 << XER_OV); - } else { - env->xer &= ~(1 << XER_OV); - } -} target_ulong helper_clcs (uint32_t arg) { @@ -1699,58 +1884,27 @@ void helper_rfsvc (void) { do_rfi(env->lr, env->ctr, 0x0000FFFF, 0); } - -void do_store_hid0_601 (void) -{ - uint32_t hid0; - - hid0 = env->spr[SPR_HID0]; - if ((T0 ^ hid0) & 0x00000008) { - /* Change current endianness */ - env->hflags &= ~(1 << MSR_LE); - env->hflags_nmsr &= ~(1 << MSR_LE); - env->hflags_nmsr |= (1 << MSR_LE) & (((T0 >> 3) & 1) << MSR_LE); - env->hflags |= env->hflags_nmsr; - if (loglevel != 0) { - fprintf(logfile, "%s: set endianness to %c => " ADDRX "\n", - __func__, T0 & 0x8 ? 'l' : 'b', env->hflags); - } - } - env->spr[SPR_HID0] = T0; -} #endif /*****************************************************************************/ /* 602 specific instructions */ /* mfrom is the most crazy instruction ever seen, imho ! */ /* Real implementation uses a ROM table. Do the same */ -#define USE_MFROM_ROM_TABLE +/* Extremly decomposed: + * -arg / 256 + * return 256 * log10(10 + 1.0) + 0.5 + */ +#if !defined (CONFIG_USER_ONLY) target_ulong helper_602_mfrom (target_ulong arg) { if (likely(arg < 602)) { -#if defined(USE_MFROM_ROM_TABLE) #include "mfrom_table.c" - return mfrom_ROM_table[T0]; -#else - double d; - /* Extremly decomposed: - * -arg / 256 - * return 256 * log10(10 + 1.0) + 0.5 - */ - d = arg; - d = float64_div(d, 256, &env->fp_status); - d = float64_chs(d); - d = exp10(d); // XXX: use float emulation function - d = float64_add(d, 1.0, &env->fp_status); - d = log10(d); // XXX: use float emulation function - d = float64_mul(d, 256, &env->fp_status); - d = float64_add(d, 0.5, &env->fp_status); - return float64_round_to_int(d, &env->fp_status); -#endif + return mfrom_ROM_table[arg]; } else { return 0; } } +#endif /*****************************************************************************/ /* Embedded PowerPC specific helpers */ @@ -1764,14 +1918,14 @@ target_ulong helper_load_dcr (target_ulong dcrn) if (loglevel != 0) { fprintf(logfile, "No DCR environment\n"); } - raise_exception_err(env, POWERPC_EXCP_PROGRAM, - POWERPC_EXCP_INVAL | POWERPC_EXCP_INVAL_INVAL); + helper_raise_exception_err(POWERPC_EXCP_PROGRAM, + POWERPC_EXCP_INVAL | POWERPC_EXCP_INVAL_INVAL); } else if (unlikely(ppc_dcr_read(env->dcr_env, dcrn, &val) != 0)) { if (loglevel != 0) { - fprintf(logfile, "DCR read error %d %03x\n", (int)T0, (int)T0); + fprintf(logfile, "DCR read error %d %03x\n", (int)dcrn, (int)dcrn); } - raise_exception_err(env, POWERPC_EXCP_PROGRAM, - POWERPC_EXCP_INVAL | POWERPC_EXCP_PRIV_REG); + helper_raise_exception_err(POWERPC_EXCP_PROGRAM, + POWERPC_EXCP_INVAL | POWERPC_EXCP_PRIV_REG); } return val; } @@ -1782,14 +1936,14 @@ void helper_store_dcr (target_ulong dcrn, target_ulong val) if (loglevel != 0) { fprintf(logfile, "No DCR environment\n"); } - raise_exception_err(env, POWERPC_EXCP_PROGRAM, - POWERPC_EXCP_INVAL | POWERPC_EXCP_INVAL_INVAL); + helper_raise_exception_err(POWERPC_EXCP_PROGRAM, + POWERPC_EXCP_INVAL | POWERPC_EXCP_INVAL_INVAL); } else if (unlikely(ppc_dcr_write(env->dcr_env, dcrn, val) != 0)) { if (loglevel != 0) { - fprintf(logfile, "DCR write error %d %03x\n", (int)T0, (int)T0); + fprintf(logfile, "DCR write error %d %03x\n", (int)dcrn, (int)dcrn); } - raise_exception_err(env, POWERPC_EXCP_PROGRAM, - POWERPC_EXCP_INVAL | POWERPC_EXCP_PRIV_REG); + helper_raise_exception_err(POWERPC_EXCP_PROGRAM, + POWERPC_EXCP_INVAL | POWERPC_EXCP_PRIV_REG); } } @@ -1817,20 +1971,6 @@ void helper_rfmci (void) do_rfi(env->spr[SPR_BOOKE_MCSRR0], SPR_BOOKE_MCSRR1, ~((target_ulong)0x3FFF0000), 0); } - -void do_load_403_pb (int num) -{ - T0 = env->pb[num]; -} - -void do_store_403_pb (int num) -{ - if (likely(env->pb[num] != T0)) { - env->pb[num] = T0; - /* Should be optimized */ - tlb_flush(env, 1); - } -} #endif /* 440 specific */ @@ -1938,7 +2078,7 @@ static always_inline int32_t efsctsi (uint32_t val) u.l = val; /* NaN are not treated the same way IEEE 754 does */ - if (unlikely(isnan(u.f))) + if (unlikely(float32_is_nan(u.f))) return 0; return float32_to_int32(u.f, &env->spe_status); @@ -1950,7 +2090,7 @@ static always_inline uint32_t efsctui (uint32_t val) u.l = val; /* NaN are not treated the same way IEEE 754 does */ - if (unlikely(isnan(u.f))) + if (unlikely(float32_is_nan(u.f))) return 0; return float32_to_uint32(u.f, &env->spe_status); @@ -1962,7 +2102,7 @@ static always_inline uint32_t efsctsiz (uint32_t val) u.l = val; /* NaN are not treated the same way IEEE 754 does */ - if (unlikely(isnan(u.f))) + if (unlikely(float32_is_nan(u.f))) return 0; return float32_to_int32_round_to_zero(u.f, &env->spe_status); @@ -1974,7 +2114,7 @@ static always_inline uint32_t efsctuiz (uint32_t val) u.l = val; /* NaN are not treated the same way IEEE 754 does */ - if (unlikely(isnan(u.f))) + if (unlikely(float32_is_nan(u.f))) return 0; return float32_to_uint32_round_to_zero(u.f, &env->spe_status); @@ -2011,7 +2151,7 @@ static always_inline uint32_t efsctsf (uint32_t val) u.l = val; /* NaN are not treated the same way IEEE 754 does */ - if (unlikely(isnan(u.f))) + if (unlikely(float32_is_nan(u.f))) return 0; tmp = uint64_to_float32(1ULL << 32, &env->spe_status); u.f = float32_mul(u.f, tmp, &env->spe_status); @@ -2026,7 +2166,7 @@ static always_inline uint32_t efsctuf (uint32_t val) u.l = val; /* NaN are not treated the same way IEEE 754 does */ - if (unlikely(isnan(u.f))) + if (unlikely(float32_is_nan(u.f))) return 0; tmp = uint64_to_float32(1ULL << 32, &env->spe_status); u.f = float32_mul(u.f, tmp, &env->spe_status); @@ -2280,7 +2420,7 @@ uint32_t helper_efdctsi (uint64_t val) u.ll = val; /* NaN are not treated the same way IEEE 754 does */ - if (unlikely(isnan(u.d))) + if (unlikely(float64_is_nan(u.d))) return 0; return float64_to_int32(u.d, &env->spe_status); @@ -2292,7 +2432,7 @@ uint32_t helper_efdctui (uint64_t val) u.ll = val; /* NaN are not treated the same way IEEE 754 does */ - if (unlikely(isnan(u.d))) + if (unlikely(float64_is_nan(u.d))) return 0; return float64_to_uint32(u.d, &env->spe_status); @@ -2304,7 +2444,7 @@ uint32_t helper_efdctsiz (uint64_t val) u.ll = val; /* NaN are not treated the same way IEEE 754 does */ - if (unlikely(isnan(u.d))) + if (unlikely(float64_is_nan(u.d))) return 0; return float64_to_int32_round_to_zero(u.d, &env->spe_status); @@ -2316,7 +2456,7 @@ uint64_t helper_efdctsidz (uint64_t val) u.ll = val; /* NaN are not treated the same way IEEE 754 does */ - if (unlikely(isnan(u.d))) + if (unlikely(float64_is_nan(u.d))) return 0; return float64_to_int64_round_to_zero(u.d, &env->spe_status); @@ -2328,7 +2468,7 @@ uint32_t helper_efdctuiz (uint64_t val) u.ll = val; /* NaN are not treated the same way IEEE 754 does */ - if (unlikely(isnan(u.d))) + if (unlikely(float64_is_nan(u.d))) return 0; return float64_to_uint32_round_to_zero(u.d, &env->spe_status); @@ -2340,7 +2480,7 @@ uint64_t helper_efdctuidz (uint64_t val) u.ll = val; /* NaN are not treated the same way IEEE 754 does */ - if (unlikely(isnan(u.d))) + if (unlikely(float64_is_nan(u.d))) return 0; return float64_to_uint64_round_to_zero(u.d, &env->spe_status); @@ -2377,7 +2517,7 @@ uint32_t helper_efdctsf (uint64_t val) u.ll = val; /* NaN are not treated the same way IEEE 754 does */ - if (unlikely(isnan(u.d))) + if (unlikely(float64_is_nan(u.d))) return 0; tmp = uint64_to_float64(1ULL << 32, &env->spe_status); u.d = float64_mul(u.d, tmp, &env->spe_status); @@ -2392,7 +2532,7 @@ uint32_t helper_efdctuf (uint64_t val) u.ll = val; /* NaN are not treated the same way IEEE 754 does */ - if (unlikely(isnan(u.d))) + if (unlikely(float64_is_nan(u.d))) return 0; tmp = uint64_to_float64(1ULL << 32, &env->spe_status); u.d = float64_mul(u.d, tmp, &env->spe_status); @@ -2547,7 +2687,7 @@ void tlb_fill (target_ulong addr, int is_write, int mmu_idx, void *retaddr) cpu_restore_state(tb, env, pc, NULL); } } - raise_exception_err(env, env->exception_index, env->error_code); + helper_raise_exception_err(env->exception_index, env->error_code); } env = saved_env; } @@ -2560,7 +2700,7 @@ target_ulong helper_load_sr (target_ulong sr_num) void helper_store_sr (target_ulong sr_num, target_ulong val) { - do_store_sr(env, sr_num, val); + ppc_store_sr(env, sr_num, val); } /* SLB management */ @@ -2616,9 +2756,9 @@ static void do_6xx_tlb (target_ulong new_EPN, int is_code) way = (env->spr[SPR_SRR1] >> 17) & 1; #if defined (DEBUG_SOFTWARE_TLB) if (loglevel != 0) { - fprintf(logfile, "%s: EPN " TDX " " ADDRX " PTE0 " ADDRX + fprintf(logfile, "%s: EPN " ADDRX " " ADDRX " PTE0 " ADDRX " PTE1 " ADDRX " way %d\n", - __func__, T0, EPN, CMP, RPN, way); + __func__, new_EPN, EPN, CMP, RPN, way); } #endif /* Store this TLB */ @@ -2648,9 +2788,9 @@ static void do_74xx_tlb (target_ulong new_EPN, int is_code) way = env->spr[SPR_TLBMISS] & 0x3; #if defined (DEBUG_SOFTWARE_TLB) if (loglevel != 0) { - fprintf(logfile, "%s: EPN " TDX " " ADDRX " PTE0 " ADDRX + fprintf(logfile, "%s: EPN " ADDRX " " ADDRX " PTE0 " ADDRX " PTE1 " ADDRX " way %d\n", - __func__, T0, EPN, CMP, RPN, way); + __func__, new_EPN, EPN, CMP, RPN, way); } #endif /* Store this TLB */ @@ -2778,7 +2918,7 @@ void helper_4xx_tlbwe_hi (target_ulong entry, target_ulong val) #if defined (DEBUG_SOFTWARE_TLB) if (loglevel != 0) { - fprintf(logfile, "%s entry " TDX " val " TDX "\n", __func__, entry, val); + fprintf(logfile, "%s entry %d val " ADDRX "\n", __func__, (int)entry, val); } #endif entry &= 0x3F; @@ -2820,7 +2960,7 @@ void helper_4xx_tlbwe_hi (target_ulong entry, target_ulong val) if (loglevel != 0) { fprintf(logfile, "%s: set up TLB %d RPN " PADDRX " EPN " ADDRX " size " ADDRX " prot %c%c%c%c PID %d\n", __func__, - (int)T0, tlb->RPN, tlb->EPN, tlb->size, + (int)entry, tlb->RPN, tlb->EPN, tlb->size, tlb->prot & PAGE_READ ? 'r' : '-', tlb->prot & PAGE_WRITE ? 'w' : '-', tlb->prot & PAGE_EXEC ? 'x' : '-', @@ -2833,7 +2973,7 @@ void helper_4xx_tlbwe_hi (target_ulong entry, target_ulong val) #if defined (DEBUG_SOFTWARE_TLB) if (loglevel != 0) { fprintf(logfile, "%s: invalidate TLB %d start " ADDRX - " end " ADDRX "\n", __func__, (int)T0, tlb->EPN, end); + " end " ADDRX "\n", __func__, (int)entry, tlb->EPN, end); } #endif for (page = tlb->EPN; page < end; page += TARGET_PAGE_SIZE) @@ -2847,7 +2987,7 @@ void helper_4xx_tlbwe_lo (target_ulong entry, target_ulong val) #if defined (DEBUG_SOFTWARE_TLB) if (loglevel != 0) { - fprintf(logfile, "%s entry " TDX " val " TDX "\n", __func__, entry, val); + fprintf(logfile, "%s entry %i val " ADDRX "\n", __func__, (int)entry, val); } #endif entry &= 0x3F; @@ -2885,8 +3025,8 @@ void helper_440_tlbwe (uint32_t word, target_ulong entry, target_ulong value) #if defined (DEBUG_SOFTWARE_TLB) if (loglevel != 0) { - fprintf(logfile, "%s word %d entry " TDX " value " TDX "\n", - __func__, word, entry, value); + fprintf(logfile, "%s word %d entry %d value " ADDRX "\n", + __func__, word, (int)entry, value); } #endif do_flush_tlbs = 0; diff --git a/qemu/target-ppc/op_helper.h b/qemu/target-ppc/op_helper.h deleted file mode 100644 index 0fc379a8..00000000 --- a/qemu/target-ppc/op_helper.h +++ /dev/null @@ -1,38 +0,0 @@ -/* - * PowerPC emulation helpers header for qemu. - * - * Copyright (c) 2003-2007 Jocelyn Mayer - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -/* Registers load and stores */ -#if defined(TARGET_PPC64) -void do_store_pri (int prio); -#endif -target_ulong ppc_load_dump_spr (int sprn); -void ppc_store_dump_spr (int sprn, target_ulong val); - -/* Misc */ -/* POWER / PowerPC 601 specific helpers */ -#if !defined(CONFIG_USER_ONLY) -void do_store_hid0_601 (void); -#endif - -/* PowerPC 403 specific helpers */ -#if !defined(CONFIG_USER_ONLY) -void do_load_403_pb (int num); -void do_store_403_pb (int num); -#endif diff --git a/qemu/target-ppc/translate.c b/qemu/target-ppc/translate.c index b34de137..4c4f9efd 100644 --- a/qemu/target-ppc/translate.c +++ b/qemu/target-ppc/translate.c @@ -41,7 +41,6 @@ //#define DO_SINGLE_STEP //#define PPC_DEBUG_DISAS //#define DO_PPC_STATISTICS -//#define OPTIMIZE_FPRF_UPDATE /*****************************************************************************/ /* Code translation helpers */ @@ -71,9 +70,6 @@ static TCGv cpu_reserve; static TCGv_i32 cpu_fpscr; static TCGv_i32 cpu_access_type; -/* dyngen register indexes */ -static TCGv cpu_T[1]; - #include "gen-icount.h" void ppc_translate_init(void) @@ -86,11 +82,6 @@ void ppc_translate_init(void) return; cpu_env = tcg_global_reg_new_ptr(TCG_AREG0, "env"); -#if TARGET_LONG_BITS > HOST_LONG_BITS - cpu_T[0] = tcg_global_mem_new(TCG_AREG0, offsetof(CPUState, t0), "T0"); -#else - cpu_T[0] = tcg_global_reg_new(TCG_AREG1, "T0"); -#endif p = cpu_reg_names; @@ -170,11 +161,6 @@ void ppc_translate_init(void) done_init = 1; } -#if defined(OPTIMIZE_FPRF_UPDATE) -static uint16_t *gen_fprf_buf[OPC_BUF_SIZE]; -static uint16_t **gen_fprf_ptr; -#endif - /* internal defines */ typedef struct DisasContext { struct TranslationBlock *tb; @@ -183,10 +169,9 @@ typedef struct DisasContext { uint32_t exception; /* Routine used to access memory */ int mem_idx; + int access_type; /* Translation flags */ -#if !defined(CONFIG_USER_ONLY) - int supervisor; -#endif + int le_mode; #if defined(TARGET_PPC64) int sf_mode; #endif @@ -215,7 +200,7 @@ struct opc_handler_t { static always_inline void gen_reset_fpstatus (void) { #ifdef CONFIG_SOFTFLOAT - gen_op_reset_fpstatus(); + gen_helper_reset_fpstatus(); #endif } @@ -225,9 +210,6 @@ static always_inline void gen_compute_fprf (TCGv_i64 arg, int set_fprf, int set_ if (set_fprf != 0) { /* This case might be optimized later */ -#if defined(OPTIMIZE_FPRF_UPDATE) - *gen_fprf_ptr++ = gen_opc_ptr; -#endif tcg_gen_movi_i32(t0, 1); gen_helper_compute_fprf(t0, arg, t0); if (unlikely(set_rc)) { @@ -239,27 +221,17 @@ static always_inline void gen_compute_fprf (TCGv_i64 arg, int set_fprf, int set_ tcg_gen_movi_i32(t0, 0); gen_helper_compute_fprf(t0, arg, t0); tcg_gen_mov_i32(cpu_crf[1], t0); - if (set_fprf) - gen_helper_float_check_status(); } tcg_temp_free_i32(t0); } -static always_inline void gen_optimize_fprf (void) -{ -#if defined(OPTIMIZE_FPRF_UPDATE) - uint16_t **ptr; - - for (ptr = gen_fprf_buf; ptr != (gen_fprf_ptr - 1); ptr++) - *ptr = INDEX_op_nop1; - gen_fprf_ptr = gen_fprf_buf; -#endif -} - -static always_inline void gen_set_access_type(int access_type) +static always_inline void gen_set_access_type (DisasContext *ctx, int access_type) { - tcg_gen_movi_i32(cpu_access_type, access_type); + if (ctx->access_type != access_type) { + tcg_gen_movi_i32(cpu_access_type, access_type); + ctx->access_type = access_type; + } } static always_inline void gen_update_nip (DisasContext *ctx, target_ulong nip) @@ -272,49 +244,55 @@ static always_inline void gen_update_nip (DisasContext *ctx, target_ulong nip) tcg_gen_movi_tl(cpu_nip, (uint32_t)nip); } -#define GEN_EXCP(ctx, excp, error) \ -do { \ - TCGv_i32 t0 = tcg_const_i32(excp); \ - TCGv_i32 t1 = tcg_const_i32(error); \ - if ((ctx)->exception == POWERPC_EXCP_NONE) { \ - gen_update_nip(ctx, (ctx)->nip); \ - } \ - gen_helper_raise_exception_err(t0, t1); \ - tcg_temp_free_i32(t0); \ - tcg_temp_free_i32(t1); \ - ctx->exception = (excp); \ -} while (0) - -#define GEN_EXCP_INVAL(ctx) \ -GEN_EXCP((ctx), POWERPC_EXCP_PROGRAM, \ - POWERPC_EXCP_INVAL | POWERPC_EXCP_INVAL_INVAL) - -#define GEN_EXCP_PRIVOPC(ctx) \ -GEN_EXCP((ctx), POWERPC_EXCP_PROGRAM, \ - POWERPC_EXCP_INVAL | POWERPC_EXCP_PRIV_OPC) - -#define GEN_EXCP_PRIVREG(ctx) \ -GEN_EXCP((ctx), POWERPC_EXCP_PROGRAM, \ - POWERPC_EXCP_INVAL | POWERPC_EXCP_PRIV_REG) +static always_inline void gen_exception_err (DisasContext *ctx, uint32_t excp, uint32_t error) +{ + TCGv_i32 t0, t1; + if (ctx->exception == POWERPC_EXCP_NONE) { + gen_update_nip(ctx, ctx->nip); + } + t0 = tcg_const_i32(excp); + t1 = tcg_const_i32(error); + gen_helper_raise_exception_err(t0, t1); + tcg_temp_free_i32(t0); + tcg_temp_free_i32(t1); + ctx->exception = (excp); +} -#define GEN_EXCP_NO_FP(ctx) \ -GEN_EXCP(ctx, POWERPC_EXCP_FPU, 0) +static always_inline void gen_exception (DisasContext *ctx, uint32_t excp) +{ + TCGv_i32 t0; + if (ctx->exception == POWERPC_EXCP_NONE) { + gen_update_nip(ctx, ctx->nip); + } + t0 = tcg_const_i32(excp); + gen_helper_raise_exception(t0); + tcg_temp_free_i32(t0); + ctx->exception = (excp); +} -#define GEN_EXCP_NO_AP(ctx) \ -GEN_EXCP(ctx, POWERPC_EXCP_APU, 0) +static always_inline void gen_debug_exception (DisasContext *ctx) +{ + TCGv_i32 t0; + gen_update_nip(ctx, ctx->nip); + t0 = tcg_const_i32(EXCP_DEBUG); + gen_helper_raise_exception(t0); + tcg_temp_free_i32(t0); +} -#define GEN_EXCP_NO_VR(ctx) \ -GEN_EXCP(ctx, POWERPC_EXCP_VPU, 0) +static always_inline void gen_inval_exception (DisasContext *ctx, uint32_t error) +{ + gen_exception_err(ctx, POWERPC_EXCP_PROGRAM, POWERPC_EXCP_INVAL | error); +} /* Stop translation */ -static always_inline void GEN_STOP (DisasContext *ctx) +static always_inline void gen_stop_exception (DisasContext *ctx) { gen_update_nip(ctx, ctx->nip); ctx->exception = POWERPC_EXCP_STOP; } /* No need to update nip here, as execution flow will change */ -static always_inline void GEN_SYNC (DisasContext *ctx) +static always_inline void gen_sync_exception (DisasContext *ctx) { ctx->exception = POWERPC_EXCP_SYNC; } @@ -697,7 +675,7 @@ GEN_OPCODE_MARK(start); /* Invalid instruction */ GEN_HANDLER(invalid, 0x00, 0x00, 0x00, 0xFFFFFFFF, PPC_NONE) { - GEN_EXCP_INVAL(ctx); + gen_inval_exception(ctx, POWERPC_EXCP_INVAL_INVAL); } static opc_handler_t invalid_handler = { @@ -1523,25 +1501,25 @@ GEN_HANDLER(or, 0x1F, 0x1C, 0x0D, 0x00000000, PPC_INTEGER) break; #if !defined(CONFIG_USER_ONLY) case 31: - if (ctx->supervisor > 0) { + if (ctx->mem_idx > 0) { /* Set process priority to very low */ prio = 1; } break; case 5: - if (ctx->supervisor > 0) { + if (ctx->mem_idx > 0) { /* Set process priority to medium-hight */ prio = 5; } break; case 3: - if (ctx->supervisor > 0) { + if (ctx->mem_idx > 0) { /* Set process priority to high */ prio = 6; } break; case 7: - if (ctx->supervisor > 1) { + if (ctx->mem_idx > 1) { /* Set process priority to very high */ prio = 7; } @@ -2091,7 +2069,7 @@ GEN_HANDLER(srd, 0x1F, 0x1B, 0x10, 0x00000000, PPC_64B) GEN_HANDLER(f##name, op1, op2, 0xFF, 0x00000000, type) \ { \ if (unlikely(!ctx->fpu_enabled)) { \ - GEN_EXCP_NO_FP(ctx); \ + gen_exception(ctx, POWERPC_EXCP_FPU); \ return; \ } \ gen_reset_fpstatus(); \ @@ -2112,7 +2090,7 @@ _GEN_FLOAT_ACB(name##s, name, 0x3B, op2, 1, set_fprf, type); GEN_HANDLER(f##name, op1, op2, 0xFF, inval, type) \ { \ if (unlikely(!ctx->fpu_enabled)) { \ - GEN_EXCP_NO_FP(ctx); \ + gen_exception(ctx, POWERPC_EXCP_FPU); \ return; \ } \ gen_reset_fpstatus(); \ @@ -2132,7 +2110,7 @@ _GEN_FLOAT_AB(name##s, name, 0x3B, op2, inval, 1, set_fprf, type); GEN_HANDLER(f##name, op1, op2, 0xFF, inval, type) \ { \ if (unlikely(!ctx->fpu_enabled)) { \ - GEN_EXCP_NO_FP(ctx); \ + gen_exception(ctx, POWERPC_EXCP_FPU); \ return; \ } \ gen_reset_fpstatus(); \ @@ -2152,7 +2130,7 @@ _GEN_FLOAT_AC(name##s, name, 0x3B, op2, inval, 1, set_fprf, type); GEN_HANDLER(f##name, 0x3F, op2, op3, 0x001F0000, type) \ { \ if (unlikely(!ctx->fpu_enabled)) { \ - GEN_EXCP_NO_FP(ctx); \ + gen_exception(ctx, POWERPC_EXCP_FPU); \ return; \ } \ gen_reset_fpstatus(); \ @@ -2165,7 +2143,7 @@ GEN_HANDLER(f##name, 0x3F, op2, op3, 0x001F0000, type) \ GEN_HANDLER(f##name, op1, op2, 0xFF, 0x001F07C0, type) \ { \ if (unlikely(!ctx->fpu_enabled)) { \ - GEN_EXCP_NO_FP(ctx); \ + gen_exception(ctx, POWERPC_EXCP_FPU); \ return; \ } \ gen_reset_fpstatus(); \ @@ -2194,7 +2172,7 @@ GEN_FLOAT_BS(rsqrte, 0x3F, 0x1A, 1, PPC_FLOAT_FRSQRTE); GEN_HANDLER(frsqrtes, 0x3B, 0x1A, 0xFF, 0x001F07C0, PPC_FLOAT_FRSQRTES) { if (unlikely(!ctx->fpu_enabled)) { - GEN_EXCP_NO_FP(ctx); + gen_exception(ctx, POWERPC_EXCP_FPU); return; } gen_reset_fpstatus(); @@ -2212,7 +2190,7 @@ GEN_FLOAT_AB(sub, 0x14, 0x000007C0, 1, PPC_FLOAT); GEN_HANDLER(fsqrt, 0x3F, 0x16, 0xFF, 0x001F07C0, PPC_FLOAT_FSQRT) { if (unlikely(!ctx->fpu_enabled)) { - GEN_EXCP_NO_FP(ctx); + gen_exception(ctx, POWERPC_EXCP_FPU); return; } gen_reset_fpstatus(); @@ -2223,7 +2201,7 @@ GEN_HANDLER(fsqrt, 0x3F, 0x16, 0xFF, 0x001F07C0, PPC_FLOAT_FSQRT) GEN_HANDLER(fsqrts, 0x3B, 0x16, 0xFF, 0x001F07C0, PPC_FLOAT_FSQRT) { if (unlikely(!ctx->fpu_enabled)) { - GEN_EXCP_NO_FP(ctx); + gen_exception(ctx, POWERPC_EXCP_FPU); return; } gen_reset_fpstatus(); @@ -2271,26 +2249,30 @@ GEN_FLOAT_B(rim, 0x08, 0x0F, 1, PPC_FLOAT_EXT); /* fcmpo */ GEN_HANDLER(fcmpo, 0x3F, 0x00, 0x01, 0x00600001, PPC_FLOAT) { + TCGv crf; if (unlikely(!ctx->fpu_enabled)) { - GEN_EXCP_NO_FP(ctx); + gen_exception(ctx, POWERPC_EXCP_FPU); return; } gen_reset_fpstatus(); - gen_helper_fcmpo(cpu_crf[crfD(ctx->opcode)], - cpu_fpr[rA(ctx->opcode)], cpu_fpr[rB(ctx->opcode)]); + crf = tcg_const_i32(crfD(ctx->opcode)); + gen_helper_fcmpo(cpu_fpr[rA(ctx->opcode)], cpu_fpr[rB(ctx->opcode)], crf); + tcg_temp_free(crf); gen_helper_float_check_status(); } /* fcmpu */ GEN_HANDLER(fcmpu, 0x3F, 0x00, 0x00, 0x00600001, PPC_FLOAT) { + TCGv crf; if (unlikely(!ctx->fpu_enabled)) { - GEN_EXCP_NO_FP(ctx); + gen_exception(ctx, POWERPC_EXCP_FPU); return; } gen_reset_fpstatus(); - gen_helper_fcmpu(cpu_crf[crfD(ctx->opcode)], - cpu_fpr[rA(ctx->opcode)], cpu_fpr[rB(ctx->opcode)]); + crf = tcg_const_i32(crfD(ctx->opcode)); + gen_helper_fcmpu(cpu_fpr[rA(ctx->opcode)], cpu_fpr[rB(ctx->opcode)], crf); + tcg_temp_free(crf); gen_helper_float_check_status(); } @@ -2304,7 +2286,7 @@ GEN_FLOAT_B(abs, 0x08, 0x08, 0, PPC_FLOAT); GEN_HANDLER(fmr, 0x3F, 0x08, 0x02, 0x001F0000, PPC_FLOAT) { if (unlikely(!ctx->fpu_enabled)) { - GEN_EXCP_NO_FP(ctx); + gen_exception(ctx, POWERPC_EXCP_FPU); return; } tcg_gen_mov_i64(cpu_fpr[rD(ctx->opcode)], cpu_fpr[rB(ctx->opcode)]); @@ -2325,10 +2307,9 @@ GEN_HANDLER(mcrfs, 0x3F, 0x00, 0x02, 0x0063F801, PPC_FLOAT) int bfa; if (unlikely(!ctx->fpu_enabled)) { - GEN_EXCP_NO_FP(ctx); + gen_exception(ctx, POWERPC_EXCP_FPU); return; } - gen_optimize_fprf(); bfa = 4 * (7 - crfS(ctx->opcode)); tcg_gen_shri_i32(cpu_crf[crfD(ctx->opcode)], cpu_fpscr, bfa); tcg_gen_andi_i32(cpu_crf[crfD(ctx->opcode)], cpu_crf[crfD(ctx->opcode)], 0xf); @@ -2339,10 +2320,9 @@ GEN_HANDLER(mcrfs, 0x3F, 0x00, 0x02, 0x0063F801, PPC_FLOAT) GEN_HANDLER(mffs, 0x3F, 0x07, 0x12, 0x001FF800, PPC_FLOAT) { if (unlikely(!ctx->fpu_enabled)) { - GEN_EXCP_NO_FP(ctx); + gen_exception(ctx, POWERPC_EXCP_FPU); return; } - gen_optimize_fprf(); gen_reset_fpstatus(); tcg_gen_extu_i32_i64(cpu_fpr[rD(ctx->opcode)], cpu_fpscr); gen_compute_fprf(cpu_fpr[rD(ctx->opcode)], 0, Rc(ctx->opcode) != 0); @@ -2354,14 +2334,16 @@ GEN_HANDLER(mtfsb0, 0x3F, 0x06, 0x02, 0x001FF800, PPC_FLOAT) uint8_t crb; if (unlikely(!ctx->fpu_enabled)) { - GEN_EXCP_NO_FP(ctx); + gen_exception(ctx, POWERPC_EXCP_FPU); return; } - crb = 32 - (crbD(ctx->opcode) >> 2); - gen_optimize_fprf(); + crb = 31 - crbD(ctx->opcode); gen_reset_fpstatus(); - if (likely(crb != 30 && crb != 29)) - tcg_gen_andi_i32(cpu_fpscr, cpu_fpscr, ~(1 << crb)); + if (likely(crb != FPSCR_FEX && crb != FPSCR_VX)) { + TCGv_i32 t0 = tcg_const_i32(crb); + gen_helper_fpscr_clrbit(t0); + tcg_temp_free_i32(t0); + } if (unlikely(Rc(ctx->opcode) != 0)) { tcg_gen_shri_i32(cpu_crf[1], cpu_fpscr, FPSCR_OX); } @@ -2373,11 +2355,10 @@ GEN_HANDLER(mtfsb1, 0x3F, 0x06, 0x01, 0x001FF800, PPC_FLOAT) uint8_t crb; if (unlikely(!ctx->fpu_enabled)) { - GEN_EXCP_NO_FP(ctx); + gen_exception(ctx, POWERPC_EXCP_FPU); return; } - crb = 32 - (crbD(ctx->opcode) >> 2); - gen_optimize_fprf(); + crb = 31 - crbD(ctx->opcode); gen_reset_fpstatus(); /* XXX: we pretend we can only do IEEE floating-point computations */ if (likely(crb != FPSCR_FEX && crb != FPSCR_VX && crb != FPSCR_NI)) { @@ -2398,10 +2379,9 @@ GEN_HANDLER(mtfsf, 0x3F, 0x07, 0x16, 0x02010000, PPC_FLOAT) TCGv_i32 t0; if (unlikely(!ctx->fpu_enabled)) { - GEN_EXCP_NO_FP(ctx); + gen_exception(ctx, POWERPC_EXCP_FPU); return; } - gen_optimize_fprf(); gen_reset_fpstatus(); t0 = tcg_const_i32(FM(ctx->opcode)); gen_helper_store_fpscr(cpu_fpr[rB(ctx->opcode)], t0); @@ -2421,12 +2401,11 @@ GEN_HANDLER(mtfsfi, 0x3F, 0x06, 0x04, 0x006f0800, PPC_FLOAT) TCGv_i32 t1; if (unlikely(!ctx->fpu_enabled)) { - GEN_EXCP_NO_FP(ctx); + gen_exception(ctx, POWERPC_EXCP_FPU); return; } bf = crbD(ctx->opcode) >> 2; sh = 7 - bf; - gen_optimize_fprf(); gen_reset_fpstatus(); t0 = tcg_const_i64(FPIMM(ctx->opcode) << (4 * sh)); t1 = tcg_const_i32(1 << sh); @@ -2442,37 +2421,76 @@ GEN_HANDLER(mtfsfi, 0x3F, 0x06, 0x04, 0x006f0800, PPC_FLOAT) /*** Addressing modes ***/ /* Register indirect with immediate index : EA = (rA|0) + SIMM */ -static always_inline void gen_addr_imm_index (TCGv EA, - DisasContext *ctx, - target_long maskl) +static always_inline void gen_addr_imm_index (DisasContext *ctx, TCGv EA, target_long maskl) { target_long simm = SIMM(ctx->opcode); simm &= ~maskl; - if (rA(ctx->opcode) == 0) + if (rA(ctx->opcode) == 0) { +#if defined(TARGET_PPC64) + if (!ctx->sf_mode) { + tcg_gen_movi_tl(EA, (uint32_t)simm); + } else +#endif tcg_gen_movi_tl(EA, simm); - else if (likely(simm != 0)) + } else if (likely(simm != 0)) { tcg_gen_addi_tl(EA, cpu_gpr[rA(ctx->opcode)], simm); - else +#if defined(TARGET_PPC64) + if (!ctx->sf_mode) { + tcg_gen_ext32u_tl(EA, EA); + } +#endif + } else { +#if defined(TARGET_PPC64) + if (!ctx->sf_mode) { + tcg_gen_ext32u_tl(EA, cpu_gpr[rA(ctx->opcode)]); + } else +#endif tcg_gen_mov_tl(EA, cpu_gpr[rA(ctx->opcode)]); + } } -static always_inline void gen_addr_reg_index (TCGv EA, - DisasContext *ctx) +static always_inline void gen_addr_reg_index (DisasContext *ctx, TCGv EA) { - if (rA(ctx->opcode) == 0) + if (rA(ctx->opcode) == 0) { +#if defined(TARGET_PPC64) + if (!ctx->sf_mode) { + tcg_gen_ext32u_tl(EA, cpu_gpr[rB(ctx->opcode)]); + } else +#endif tcg_gen_mov_tl(EA, cpu_gpr[rB(ctx->opcode)]); - else + } else { tcg_gen_add_tl(EA, cpu_gpr[rA(ctx->opcode)], cpu_gpr[rB(ctx->opcode)]); +#if defined(TARGET_PPC64) + if (!ctx->sf_mode) { + tcg_gen_ext32u_tl(EA, EA); + } +#endif + } } -static always_inline void gen_addr_register (TCGv EA, - DisasContext *ctx) +static always_inline void gen_addr_register (DisasContext *ctx, TCGv EA) { - if (rA(ctx->opcode) == 0) + if (rA(ctx->opcode) == 0) { tcg_gen_movi_tl(EA, 0); - else - tcg_gen_mov_tl(EA, cpu_gpr[rA(ctx->opcode)]); + } else { +#if defined(TARGET_PPC64) + if (!ctx->sf_mode) { + tcg_gen_ext32u_tl(EA, cpu_gpr[rA(ctx->opcode)]); + } else +#endif + tcg_gen_mov_tl(EA, cpu_gpr[rA(ctx->opcode)]); + } +} + +static always_inline void gen_addr_add (DisasContext *ctx, TCGv ret, TCGv arg1, target_long val) +{ + tcg_gen_addi_tl(ret, arg1, val); +#if defined(TARGET_PPC64) + if (!ctx->sf_mode) { + tcg_gen_ext32u_tl(ret, ret); + } +#endif } static always_inline void gen_check_align (DisasContext *ctx, TCGv EA, int mask) @@ -2494,288 +2512,170 @@ static always_inline void gen_check_align (DisasContext *ctx, TCGv EA, int mask) } /*** Integer load ***/ +static always_inline void gen_qemu_ld8u(DisasContext *ctx, TCGv arg1, TCGv arg2) +{ + tcg_gen_qemu_ld8u(arg1, arg2, ctx->mem_idx); +} + +static always_inline void gen_qemu_ld8s(DisasContext *ctx, TCGv arg1, TCGv arg2) +{ + tcg_gen_qemu_ld8s(arg1, arg2, ctx->mem_idx); +} + +static always_inline void gen_qemu_ld16u(DisasContext *ctx, TCGv arg1, TCGv arg2) +{ + tcg_gen_qemu_ld16u(arg1, arg2, ctx->mem_idx); + if (unlikely(ctx->le_mode)) { #if defined(TARGET_PPC64) -#define GEN_QEMU_LD_PPC64(width) \ -static always_inline void gen_qemu_ld##width##_ppc64(TCGv t0, TCGv t1, int flags)\ -{ \ - if (likely(flags & 2)) \ - tcg_gen_qemu_ld##width(t0, t1, flags >> 2); \ - else { \ - TCGv addr = tcg_temp_new(); \ - tcg_gen_ext32u_tl(addr, t1); \ - tcg_gen_qemu_ld##width(t0, addr, flags >> 2); \ - tcg_temp_free(addr); \ - } \ -} -GEN_QEMU_LD_PPC64(8u) -GEN_QEMU_LD_PPC64(8s) -GEN_QEMU_LD_PPC64(16u) -GEN_QEMU_LD_PPC64(16s) -GEN_QEMU_LD_PPC64(32u) -GEN_QEMU_LD_PPC64(32s) -GEN_QEMU_LD_PPC64(64) - -#define GEN_QEMU_ST_PPC64(width) \ -static always_inline void gen_qemu_st##width##_ppc64(TCGv t0, TCGv t1, int flags)\ -{ \ - if (likely(flags & 2)) \ - tcg_gen_qemu_st##width(t0, t1, flags >> 2); \ - else { \ - TCGv addr = tcg_temp_new(); \ - tcg_gen_ext32u_tl(addr, t1); \ - tcg_gen_qemu_st##width(t0, addr, flags >> 2); \ - tcg_temp_free(addr); \ - } \ -} -GEN_QEMU_ST_PPC64(8) -GEN_QEMU_ST_PPC64(16) -GEN_QEMU_ST_PPC64(32) -GEN_QEMU_ST_PPC64(64) - -static always_inline void gen_qemu_ld8u(TCGv arg0, TCGv arg1, int flags) -{ - gen_qemu_ld8u_ppc64(arg0, arg1, flags); -} - -static always_inline void gen_qemu_ld8s(TCGv arg0, TCGv arg1, int flags) -{ - gen_qemu_ld8s_ppc64(arg0, arg1, flags); -} - -static always_inline void gen_qemu_ld16u(TCGv arg0, TCGv arg1, int flags) -{ - if (unlikely(flags & 1)) { - TCGv_i32 t0; - gen_qemu_ld16u_ppc64(arg0, arg1, flags); - t0 = tcg_temp_new_i32(); - tcg_gen_trunc_tl_i32(t0, arg0); + TCGv_i32 t0 = tcg_temp_new_i32(); + tcg_gen_trunc_tl_i32(t0, arg1); tcg_gen_bswap16_i32(t0, t0); - tcg_gen_extu_i32_tl(arg0, t0); + tcg_gen_extu_i32_tl(arg1, t0); tcg_temp_free_i32(t0); - } else - gen_qemu_ld16u_ppc64(arg0, arg1, flags); +#else + tcg_gen_bswap16_i32(arg1, arg1); +#endif + } } -static always_inline void gen_qemu_ld16s(TCGv arg0, TCGv arg1, int flags) +static always_inline void gen_qemu_ld16s(DisasContext *ctx, TCGv arg1, TCGv arg2) { - if (unlikely(flags & 1)) { + if (unlikely(ctx->le_mode)) { +#if defined(TARGET_PPC64) TCGv_i32 t0; - gen_qemu_ld16u_ppc64(arg0, arg1, flags); + tcg_gen_qemu_ld16u(arg1, arg2, ctx->mem_idx); t0 = tcg_temp_new_i32(); - tcg_gen_trunc_tl_i32(t0, arg0); + tcg_gen_trunc_tl_i32(t0, arg1); tcg_gen_bswap16_i32(t0, t0); - tcg_gen_extu_i32_tl(arg0, t0); - tcg_gen_ext16s_tl(arg0, arg0); + tcg_gen_extu_i32_tl(arg1, t0); + tcg_gen_ext16s_tl(arg1, arg1); tcg_temp_free_i32(t0); - } else - gen_qemu_ld16s_ppc64(arg0, arg1, flags); +#else + tcg_gen_qemu_ld16u(arg1, arg2, ctx->mem_idx); + tcg_gen_bswap16_i32(arg1, arg1); + tcg_gen_ext16s_i32(arg1, arg1); +#endif + } else { + tcg_gen_qemu_ld16s(arg1, arg2, ctx->mem_idx); + } } -static always_inline void gen_qemu_ld32u(TCGv arg0, TCGv arg1, int flags) +static always_inline void gen_qemu_ld32u(DisasContext *ctx, TCGv arg1, TCGv arg2) { - if (unlikely(flags & 1)) { - TCGv_i32 t0; - gen_qemu_ld32u_ppc64(arg0, arg1, flags); - t0 = tcg_temp_new_i32(); - tcg_gen_trunc_tl_i32(t0, arg0); + tcg_gen_qemu_ld32u(arg1, arg2, ctx->mem_idx); + if (unlikely(ctx->le_mode)) { +#if defined(TARGET_PPC64) + TCGv_i32 t0 = tcg_temp_new_i32(); + tcg_gen_trunc_tl_i32(t0, arg1); tcg_gen_bswap_i32(t0, t0); - tcg_gen_extu_i32_tl(arg0, t0); + tcg_gen_extu_i32_tl(arg1, t0); tcg_temp_free_i32(t0); - } else - gen_qemu_ld32u_ppc64(arg0, arg1, flags); +#else + tcg_gen_bswap_i32(arg1, arg1); +#endif + } } -static always_inline void gen_qemu_ld32s(TCGv arg0, TCGv arg1, int flags) +#if defined(TARGET_PPC64) +static always_inline void gen_qemu_ld32s(DisasContext *ctx, TCGv arg1, TCGv arg2) { - if (unlikely(flags & 1)) { + if (unlikely(ctx->mem_idx)) { TCGv_i32 t0; - gen_qemu_ld32u_ppc64(arg0, arg1, flags); + tcg_gen_qemu_ld32u(arg1, arg2, ctx->mem_idx); t0 = tcg_temp_new_i32(); - tcg_gen_trunc_tl_i32(t0, arg0); + tcg_gen_trunc_tl_i32(t0, arg1); tcg_gen_bswap_i32(t0, t0); - tcg_gen_ext_i32_tl(arg0, t0); + tcg_gen_ext_i32_tl(arg1, t0); tcg_temp_free_i32(t0); } else - gen_qemu_ld32s_ppc64(arg0, arg1, flags); + tcg_gen_qemu_ld32s(arg1, arg2, ctx->mem_idx); } +#endif -static always_inline void gen_qemu_ld64(TCGv arg0, TCGv arg1, int flags) +static always_inline void gen_qemu_ld64(DisasContext *ctx, TCGv_i64 arg1, TCGv arg2) { - gen_qemu_ld64_ppc64(arg0, arg1, flags); - if (unlikely(flags & 1)) - tcg_gen_bswap_i64(arg0, arg0); + tcg_gen_qemu_ld64(arg1, arg2, ctx->mem_idx); + if (unlikely(ctx->le_mode)) { + tcg_gen_bswap_i64(arg1, arg1); + } } -static always_inline void gen_qemu_st8(TCGv arg0, TCGv arg1, int flags) +static always_inline void gen_qemu_st8(DisasContext *ctx, TCGv arg1, TCGv arg2) { - gen_qemu_st8_ppc64(arg0, arg1, flags); + tcg_gen_qemu_st8(arg1, arg2, ctx->mem_idx); } -static always_inline void gen_qemu_st16(TCGv arg0, TCGv arg1, int flags) +static always_inline void gen_qemu_st16(DisasContext *ctx, TCGv arg1, TCGv arg2) { - if (unlikely(flags & 1)) { + if (unlikely(ctx->le_mode)) { +#if defined(TARGET_PPC64) TCGv_i32 t0; - TCGv_i64 t1; + TCGv t1; t0 = tcg_temp_new_i32(); - tcg_gen_trunc_tl_i32(t0, arg0); + tcg_gen_trunc_tl_i32(t0, arg1); tcg_gen_ext16u_i32(t0, t0); tcg_gen_bswap16_i32(t0, t0); - t1 = tcg_temp_new_i64(); + t1 = tcg_temp_new(); tcg_gen_extu_i32_tl(t1, t0); tcg_temp_free_i32(t0); - gen_qemu_st16_ppc64(t1, arg1, flags); - tcg_temp_free_i64(t1); - } else - gen_qemu_st16_ppc64(arg0, arg1, flags); + tcg_gen_qemu_st16(t1, arg2, ctx->mem_idx); + tcg_temp_free(t1); +#else + TCGv t0 = tcg_temp_new(); + tcg_gen_ext16u_tl(t0, arg1); + tcg_gen_bswap16_i32(t0, t0); + tcg_gen_qemu_st16(t0, arg2, ctx->mem_idx); + tcg_temp_free(t0); +#endif + } else { + tcg_gen_qemu_st16(arg1, arg2, ctx->mem_idx); + } } -static always_inline void gen_qemu_st32(TCGv arg0, TCGv arg1, int flags) +static always_inline void gen_qemu_st32(DisasContext *ctx, TCGv arg1, TCGv arg2) { - if (unlikely(flags & 1)) { + if (unlikely(ctx->le_mode)) { +#if defined(TARGET_PPC64) TCGv_i32 t0; - TCGv_i64 t1; + TCGv t1; t0 = tcg_temp_new_i32(); - tcg_gen_trunc_tl_i32(t0, arg0); + tcg_gen_trunc_tl_i32(t0, arg1); tcg_gen_bswap_i32(t0, t0); - t1 = tcg_temp_new_i64(); + t1 = tcg_temp_new(); tcg_gen_extu_i32_tl(t1, t0); tcg_temp_free_i32(t0); - gen_qemu_st32_ppc64(t1, arg1, flags); - tcg_temp_free_i64(t1); - } else - gen_qemu_st32_ppc64(arg0, arg1, flags); + tcg_gen_qemu_st32(t1, arg2, ctx->mem_idx); + tcg_temp_free(t1); +#else + TCGv t0 = tcg_temp_new_i32(); + tcg_gen_bswap_i32(t0, arg1); + tcg_gen_qemu_st32(t0, arg2, ctx->mem_idx); + tcg_temp_free(t0); +#endif + } else { + tcg_gen_qemu_st32(arg1, arg2, ctx->mem_idx); + } } -static always_inline void gen_qemu_st64(TCGv arg0, TCGv arg1, int flags) +static always_inline void gen_qemu_st64(DisasContext *ctx, TCGv_i64 arg1, TCGv arg2) { - if (unlikely(flags & 1)) { + if (unlikely(ctx->le_mode)) { TCGv_i64 t0 = tcg_temp_new_i64(); - tcg_gen_bswap_i64(t0, arg0); - gen_qemu_st64_ppc64(t0, arg1, flags); + tcg_gen_bswap_i64(t0, arg1); + tcg_gen_qemu_st64(t0, arg2, ctx->mem_idx); tcg_temp_free_i64(t0); } else - gen_qemu_st64_ppc64(arg0, arg1, flags); -} - - -#else /* defined(TARGET_PPC64) */ -#define GEN_QEMU_LD_PPC32(width) \ -static always_inline void gen_qemu_ld##width##_ppc32(TCGv arg0, TCGv arg1, int flags) \ -{ \ - tcg_gen_qemu_ld##width(arg0, arg1, flags >> 1); \ -} -GEN_QEMU_LD_PPC32(8u) -GEN_QEMU_LD_PPC32(8s) -GEN_QEMU_LD_PPC32(16u) -GEN_QEMU_LD_PPC32(16s) -GEN_QEMU_LD_PPC32(32u) -GEN_QEMU_LD_PPC32(32s) -static always_inline void gen_qemu_ld64_ppc32(TCGv_i64 arg0, TCGv arg1, int flags) -{ - tcg_gen_qemu_ld64(arg0, arg1, flags >> 1); -} - -#define GEN_QEMU_ST_PPC32(width) \ -static always_inline void gen_qemu_st##width##_ppc32(TCGv arg0, TCGv arg1, int flags) \ -{ \ - tcg_gen_qemu_st##width(arg0, arg1, flags >> 1); \ -} -GEN_QEMU_ST_PPC32(8) -GEN_QEMU_ST_PPC32(16) -GEN_QEMU_ST_PPC32(32) -static always_inline void gen_qemu_st64_ppc32(TCGv_i64 arg0, TCGv arg1, int flags) -{ - tcg_gen_qemu_st64(arg0, arg1, flags >> 1); -} - -static always_inline void gen_qemu_ld8u(TCGv arg0, TCGv arg1, int flags) -{ - gen_qemu_ld8u_ppc32(arg0, arg1, flags >> 1); -} - -static always_inline void gen_qemu_ld8s(TCGv arg0, TCGv arg1, int flags) -{ - gen_qemu_ld8s_ppc32(arg0, arg1, flags >> 1); -} - -static always_inline void gen_qemu_ld16u(TCGv arg0, TCGv arg1, int flags) -{ - gen_qemu_ld16u_ppc32(arg0, arg1, flags >> 1); - if (unlikely(flags & 1)) - tcg_gen_bswap16_i32(arg0, arg0); -} - -static always_inline void gen_qemu_ld16s(TCGv arg0, TCGv arg1, int flags) -{ - if (unlikely(flags & 1)) { - gen_qemu_ld16u_ppc32(arg0, arg1, flags); - tcg_gen_bswap16_i32(arg0, arg0); - tcg_gen_ext16s_i32(arg0, arg0); - } else - gen_qemu_ld16s_ppc32(arg0, arg1, flags); -} - -static always_inline void gen_qemu_ld32u(TCGv arg0, TCGv arg1, int flags) -{ - gen_qemu_ld32u_ppc32(arg0, arg1, flags); - if (unlikely(flags & 1)) - tcg_gen_bswap_i32(arg0, arg0); -} - -static always_inline void gen_qemu_ld64(TCGv_i64 arg0, TCGv arg1, int flags) -{ - gen_qemu_ld64_ppc32(arg0, arg1, flags); - if (unlikely(flags & 1)) - tcg_gen_bswap_i64(arg0, arg0); -} - -static always_inline void gen_qemu_st8(TCGv arg0, TCGv arg1, int flags) -{ - gen_qemu_st8_ppc32(arg0, arg1, flags); -} - -static always_inline void gen_qemu_st16(TCGv arg0, TCGv arg1, int flags) -{ - if (unlikely(flags & 1)) { - TCGv_i32 temp = tcg_temp_new_i32(); - tcg_gen_ext16u_i32(temp, arg0); - tcg_gen_bswap16_i32(temp, temp); - gen_qemu_st16_ppc32(temp, arg1, flags); - tcg_temp_free_i32(temp); - } else - gen_qemu_st16_ppc32(arg0, arg1, flags); -} - -static always_inline void gen_qemu_st32(TCGv arg0, TCGv arg1, int flags) -{ - if (unlikely(flags & 1)) { - TCGv_i32 temp = tcg_temp_new_i32(); - tcg_gen_bswap_i32(temp, arg0); - gen_qemu_st32_ppc32(temp, arg1, flags); - tcg_temp_free_i32(temp); - } else - gen_qemu_st32_ppc32(arg0, arg1, flags); -} - -static always_inline void gen_qemu_st64(TCGv_i64 arg0, TCGv arg1, int flags) -{ - if (unlikely(flags & 1)) { - TCGv_i64 temp = tcg_temp_new_i64(); - tcg_gen_bswap_i64(temp, arg0); - gen_qemu_st64_ppc32(temp, arg1, flags); - tcg_temp_free_i64(temp); - } else - gen_qemu_st64_ppc32(arg0, arg1, flags); + tcg_gen_qemu_st64(arg1, arg2, ctx->mem_idx); } -#endif #define GEN_LD(name, ldop, opc, type) \ GEN_HANDLER(name, opc, 0xFF, 0xFF, 0x00000000, type) \ { \ - TCGv EA = tcg_temp_new(); \ - gen_set_access_type(ACCESS_INT); \ - gen_addr_imm_index(EA, ctx, 0); \ - gen_qemu_##ldop(cpu_gpr[rD(ctx->opcode)], EA, ctx->mem_idx); \ + TCGv EA; \ + gen_set_access_type(ctx, ACCESS_INT); \ + EA = tcg_temp_new(); \ + gen_addr_imm_index(ctx, EA, 0); \ + gen_qemu_##ldop(ctx, cpu_gpr[rD(ctx->opcode)], EA); \ tcg_temp_free(EA); \ } @@ -2785,16 +2685,16 @@ GEN_HANDLER(name##u, opc, 0xFF, 0xFF, 0x00000000, type) \ TCGv EA; \ if (unlikely(rA(ctx->opcode) == 0 || \ rA(ctx->opcode) == rD(ctx->opcode))) { \ - GEN_EXCP_INVAL(ctx); \ + gen_inval_exception(ctx, POWERPC_EXCP_INVAL_INVAL); \ return; \ } \ + gen_set_access_type(ctx, ACCESS_INT); \ EA = tcg_temp_new(); \ - gen_set_access_type(ACCESS_INT); \ if (type == PPC_64B) \ - gen_addr_imm_index(EA, ctx, 0x03); \ + gen_addr_imm_index(ctx, EA, 0x03); \ else \ - gen_addr_imm_index(EA, ctx, 0); \ - gen_qemu_##ldop(cpu_gpr[rD(ctx->opcode)], EA, ctx->mem_idx); \ + gen_addr_imm_index(ctx, EA, 0); \ + gen_qemu_##ldop(ctx, cpu_gpr[rD(ctx->opcode)], EA); \ tcg_gen_mov_tl(cpu_gpr[rA(ctx->opcode)], EA); \ tcg_temp_free(EA); \ } @@ -2805,13 +2705,13 @@ GEN_HANDLER(name##ux, 0x1F, opc2, opc3, 0x00000001, type) \ TCGv EA; \ if (unlikely(rA(ctx->opcode) == 0 || \ rA(ctx->opcode) == rD(ctx->opcode))) { \ - GEN_EXCP_INVAL(ctx); \ + gen_inval_exception(ctx, POWERPC_EXCP_INVAL_INVAL); \ return; \ } \ + gen_set_access_type(ctx, ACCESS_INT); \ EA = tcg_temp_new(); \ - gen_set_access_type(ACCESS_INT); \ - gen_addr_reg_index(EA, ctx); \ - gen_qemu_##ldop(cpu_gpr[rD(ctx->opcode)], EA, ctx->mem_idx); \ + gen_addr_reg_index(ctx, EA); \ + gen_qemu_##ldop(ctx, cpu_gpr[rD(ctx->opcode)], EA); \ tcg_gen_mov_tl(cpu_gpr[rA(ctx->opcode)], EA); \ tcg_temp_free(EA); \ } @@ -2819,10 +2719,11 @@ GEN_HANDLER(name##ux, 0x1F, opc2, opc3, 0x00000001, type) \ #define GEN_LDX(name, ldop, opc2, opc3, type) \ GEN_HANDLER(name##x, 0x1F, opc2, opc3, 0x00000001, type) \ { \ - TCGv EA = tcg_temp_new(); \ - gen_set_access_type(ACCESS_INT); \ - gen_addr_reg_index(EA, ctx); \ - gen_qemu_##ldop(cpu_gpr[rD(ctx->opcode)], EA, ctx->mem_idx); \ + TCGv EA; \ + gen_set_access_type(ctx, ACCESS_INT); \ + EA = tcg_temp_new(); \ + gen_addr_reg_index(ctx, EA); \ + gen_qemu_##ldop(ctx, cpu_gpr[rD(ctx->opcode)], EA); \ tcg_temp_free(EA); \ } @@ -2855,19 +2756,19 @@ GEN_HANDLER(ld, 0x3A, 0xFF, 0xFF, 0x00000000, PPC_64B) if (Rc(ctx->opcode)) { if (unlikely(rA(ctx->opcode) == 0 || rA(ctx->opcode) == rD(ctx->opcode))) { - GEN_EXCP_INVAL(ctx); + gen_inval_exception(ctx, POWERPC_EXCP_INVAL_INVAL); return; } } + gen_set_access_type(ctx, ACCESS_INT); EA = tcg_temp_new(); - gen_set_access_type(ACCESS_INT); - gen_addr_imm_index(EA, ctx, 0x03); + gen_addr_imm_index(ctx, EA, 0x03); if (ctx->opcode & 0x02) { /* lwa (lwau is undefined) */ - gen_qemu_ld32s(cpu_gpr[rD(ctx->opcode)], EA, ctx->mem_idx); + gen_qemu_ld32s(ctx, cpu_gpr[rD(ctx->opcode)], EA); } else { /* ld - ldu */ - gen_qemu_ld64(cpu_gpr[rD(ctx->opcode)], EA, ctx->mem_idx); + gen_qemu_ld64(ctx, cpu_gpr[rD(ctx->opcode)], EA); } if (Rc(ctx->opcode)) tcg_gen_mov_tl(cpu_gpr[rA(ctx->opcode)], EA); @@ -2877,33 +2778,33 @@ GEN_HANDLER(ld, 0x3A, 0xFF, 0xFF, 0x00000000, PPC_64B) GEN_HANDLER(lq, 0x38, 0xFF, 0xFF, 0x00000000, PPC_64BX) { #if defined(CONFIG_USER_ONLY) - GEN_EXCP_PRIVOPC(ctx); + gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC); #else int ra, rd; TCGv EA; /* Restore CPU state */ - if (unlikely(ctx->supervisor == 0)) { - GEN_EXCP_PRIVOPC(ctx); + if (unlikely(ctx->mem_idx == 0)) { + gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC); return; } ra = rA(ctx->opcode); rd = rD(ctx->opcode); if (unlikely((rd & 1) || rd == ra)) { - GEN_EXCP_INVAL(ctx); + gen_inval_exception(ctx, POWERPC_EXCP_INVAL_INVAL); return; } - if (unlikely(ctx->mem_idx & 1)) { + if (unlikely(ctx->le_mode)) { /* Little-endian mode is not handled */ - GEN_EXCP(ctx, POWERPC_EXCP_ALIGN, POWERPC_EXCP_ALIGN_LE); + gen_exception_err(ctx, POWERPC_EXCP_ALIGN, POWERPC_EXCP_ALIGN_LE); return; } + gen_set_access_type(ctx, ACCESS_INT); EA = tcg_temp_new(); - gen_set_access_type(ACCESS_INT); - gen_addr_imm_index(EA, ctx, 0x0F); - gen_qemu_ld64(cpu_gpr[rd], EA, ctx->mem_idx); - tcg_gen_addi_tl(EA, EA, 8); - gen_qemu_ld64(cpu_gpr[rd+1], EA, ctx->mem_idx); + gen_addr_imm_index(ctx, EA, 0x0F); + gen_qemu_ld64(ctx, cpu_gpr[rd], EA); + gen_addr_add(ctx, EA, EA, 8); + gen_qemu_ld64(ctx, cpu_gpr[rd+1], EA); tcg_temp_free(EA); #endif } @@ -2913,10 +2814,11 @@ GEN_HANDLER(lq, 0x38, 0xFF, 0xFF, 0x00000000, PPC_64BX) #define GEN_ST(name, stop, opc, type) \ GEN_HANDLER(name, opc, 0xFF, 0xFF, 0x00000000, type) \ { \ - TCGv EA = tcg_temp_new(); \ - gen_set_access_type(ACCESS_INT); \ - gen_addr_imm_index(EA, ctx, 0); \ - gen_qemu_##stop(cpu_gpr[rS(ctx->opcode)], EA, ctx->mem_idx); \ + TCGv EA; \ + gen_set_access_type(ctx, ACCESS_INT); \ + EA = tcg_temp_new(); \ + gen_addr_imm_index(ctx, EA, 0); \ + gen_qemu_##stop(ctx, cpu_gpr[rS(ctx->opcode)], EA); \ tcg_temp_free(EA); \ } @@ -2925,16 +2827,16 @@ GEN_HANDLER(stop##u, opc, 0xFF, 0xFF, 0x00000000, type) \ { \ TCGv EA; \ if (unlikely(rA(ctx->opcode) == 0)) { \ - GEN_EXCP_INVAL(ctx); \ + gen_inval_exception(ctx, POWERPC_EXCP_INVAL_INVAL); \ return; \ } \ + gen_set_access_type(ctx, ACCESS_INT); \ EA = tcg_temp_new(); \ - gen_set_access_type(ACCESS_INT); \ if (type == PPC_64B) \ - gen_addr_imm_index(EA, ctx, 0x03); \ + gen_addr_imm_index(ctx, EA, 0x03); \ else \ - gen_addr_imm_index(EA, ctx, 0); \ - gen_qemu_##stop(cpu_gpr[rS(ctx->opcode)], EA, ctx->mem_idx); \ + gen_addr_imm_index(ctx, EA, 0); \ + gen_qemu_##stop(ctx, cpu_gpr[rS(ctx->opcode)], EA); \ tcg_gen_mov_tl(cpu_gpr[rA(ctx->opcode)], EA); \ tcg_temp_free(EA); \ } @@ -2944,13 +2846,13 @@ GEN_HANDLER(name##ux, 0x1F, opc2, opc3, 0x00000001, type) \ { \ TCGv EA; \ if (unlikely(rA(ctx->opcode) == 0)) { \ - GEN_EXCP_INVAL(ctx); \ + gen_inval_exception(ctx, POWERPC_EXCP_INVAL_INVAL); \ return; \ } \ + gen_set_access_type(ctx, ACCESS_INT); \ EA = tcg_temp_new(); \ - gen_set_access_type(ACCESS_INT); \ - gen_addr_reg_index(EA, ctx); \ - gen_qemu_##stop(cpu_gpr[rS(ctx->opcode)], EA, ctx->mem_idx); \ + gen_addr_reg_index(ctx, EA); \ + gen_qemu_##stop(ctx, cpu_gpr[rS(ctx->opcode)], EA); \ tcg_gen_mov_tl(cpu_gpr[rA(ctx->opcode)], EA); \ tcg_temp_free(EA); \ } @@ -2958,10 +2860,11 @@ GEN_HANDLER(name##ux, 0x1F, opc2, opc3, 0x00000001, type) \ #define GEN_STX(name, stop, opc2, opc3, type) \ GEN_HANDLER(name##x, 0x1F, opc2, opc3, 0x00000001, type) \ { \ - TCGv EA = tcg_temp_new(); \ - gen_set_access_type(ACCESS_INT); \ - gen_addr_reg_index(EA, ctx); \ - gen_qemu_##stop(cpu_gpr[rS(ctx->opcode)], EA, ctx->mem_idx); \ + TCGv EA; \ + gen_set_access_type(ctx, ACCESS_INT); \ + EA = tcg_temp_new(); \ + gen_addr_reg_index(ctx, EA); \ + gen_qemu_##stop(ctx, cpu_gpr[rS(ctx->opcode)], EA); \ tcg_temp_free(EA); \ } @@ -2988,42 +2891,42 @@ GEN_HANDLER(std, 0x3E, 0xFF, 0xFF, 0x00000000, PPC_64B) rs = rS(ctx->opcode); if ((ctx->opcode & 0x3) == 0x2) { #if defined(CONFIG_USER_ONLY) - GEN_EXCP_PRIVOPC(ctx); + gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC); #else /* stq */ - if (unlikely(ctx->supervisor == 0)) { - GEN_EXCP_PRIVOPC(ctx); + if (unlikely(ctx->mem_idx == 0)) { + gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC); return; } if (unlikely(rs & 1)) { - GEN_EXCP_INVAL(ctx); + gen_inval_exception(ctx, POWERPC_EXCP_INVAL_INVAL); return; } - if (unlikely(ctx->mem_idx & 1)) { + if (unlikely(ctx->le_mode)) { /* Little-endian mode is not handled */ - GEN_EXCP(ctx, POWERPC_EXCP_ALIGN, POWERPC_EXCP_ALIGN_LE); + gen_exception_err(ctx, POWERPC_EXCP_ALIGN, POWERPC_EXCP_ALIGN_LE); return; } + gen_set_access_type(ctx, ACCESS_INT); EA = tcg_temp_new(); - gen_set_access_type(ACCESS_INT); - gen_addr_imm_index(EA, ctx, 0x03); - gen_qemu_st64(cpu_gpr[rs], EA, ctx->mem_idx); - tcg_gen_addi_tl(EA, EA, 8); - gen_qemu_st64(cpu_gpr[rs+1], EA, ctx->mem_idx); + gen_addr_imm_index(ctx, EA, 0x03); + gen_qemu_st64(ctx, cpu_gpr[rs], EA); + gen_addr_add(ctx, EA, EA, 8); + gen_qemu_st64(ctx, cpu_gpr[rs+1], EA); tcg_temp_free(EA); #endif } else { /* std / stdu */ if (Rc(ctx->opcode)) { if (unlikely(rA(ctx->opcode) == 0)) { - GEN_EXCP_INVAL(ctx); + gen_inval_exception(ctx, POWERPC_EXCP_INVAL_INVAL); return; } } + gen_set_access_type(ctx, ACCESS_INT); EA = tcg_temp_new(); - gen_set_access_type(ACCESS_INT); - gen_addr_imm_index(EA, ctx, 0x03); - gen_qemu_st64(cpu_gpr[rs], EA, ctx->mem_idx); + gen_addr_imm_index(ctx, EA, 0x03); + gen_qemu_st64(ctx, cpu_gpr[rs], EA); if (Rc(ctx->opcode)) tcg_gen_mov_tl(cpu_gpr[rA(ctx->opcode)], EA); tcg_temp_free(EA); @@ -3032,55 +2935,94 @@ GEN_HANDLER(std, 0x3E, 0xFF, 0xFF, 0x00000000, PPC_64B) #endif /*** Integer load and store with byte reverse ***/ /* lhbrx */ -void always_inline gen_qemu_ld16ur(TCGv t0, TCGv t1, int flags) +static void always_inline gen_qemu_ld16ur(DisasContext *ctx, TCGv arg1, TCGv arg2) { - TCGv_i32 temp = tcg_temp_new_i32(); - gen_qemu_ld16u(t0, t1, flags); - tcg_gen_trunc_tl_i32(temp, t0); - tcg_gen_bswap16_i32(temp, temp); - tcg_gen_extu_i32_tl(t0, temp); - tcg_temp_free_i32(temp); + tcg_gen_qemu_ld16u(arg1, arg2, ctx->mem_idx); + if (likely(!ctx->le_mode)) { +#if defined(TARGET_PPC64) + TCGv_i32 t0 = tcg_temp_new_i32(); + tcg_gen_trunc_tl_i32(t0, arg1); + tcg_gen_bswap16_i32(t0, t0); + tcg_gen_extu_i32_tl(arg1, t0); + tcg_temp_free_i32(t0); +#else + tcg_gen_bswap16_i32(arg1, arg1); +#endif + } } GEN_LDX(lhbr, ld16ur, 0x16, 0x18, PPC_INTEGER); /* lwbrx */ -void always_inline gen_qemu_ld32ur(TCGv t0, TCGv t1, int flags) +static void always_inline gen_qemu_ld32ur(DisasContext *ctx, TCGv arg1, TCGv arg2) { - TCGv_i32 temp = tcg_temp_new_i32(); - gen_qemu_ld32u(t0, t1, flags); - tcg_gen_trunc_tl_i32(temp, t0); - tcg_gen_bswap_i32(temp, temp); - tcg_gen_extu_i32_tl(t0, temp); - tcg_temp_free_i32(temp); + tcg_gen_qemu_ld32u(arg1, arg2, ctx->mem_idx); + if (likely(!ctx->le_mode)) { +#if defined(TARGET_PPC64) + TCGv_i32 t0 = tcg_temp_new_i32(); + tcg_gen_trunc_tl_i32(t0, arg1); + tcg_gen_bswap_i32(t0, t0); + tcg_gen_extu_i32_tl(arg1, t0); + tcg_temp_free_i32(t0); +#else + tcg_gen_bswap_i32(arg1, arg1); +#endif + } } GEN_LDX(lwbr, ld32ur, 0x16, 0x10, PPC_INTEGER); /* sthbrx */ -void always_inline gen_qemu_st16r(TCGv t0, TCGv t1, int flags) +static void always_inline gen_qemu_st16r(DisasContext *ctx, TCGv arg1, TCGv arg2) { - TCGv_i32 temp = tcg_temp_new_i32(); - TCGv t2 = tcg_temp_new(); - tcg_gen_trunc_tl_i32(temp, t0); - tcg_gen_ext16u_i32(temp, temp); - tcg_gen_bswap16_i32(temp, temp); - tcg_gen_extu_i32_tl(t2, temp); - tcg_temp_free_i32(temp); - gen_qemu_st16(t2, t1, flags); - tcg_temp_free(t2); + if (likely(!ctx->le_mode)) { +#if defined(TARGET_PPC64) + TCGv_i32 t0; + TCGv t1; + t0 = tcg_temp_new_i32(); + tcg_gen_trunc_tl_i32(t0, arg1); + tcg_gen_ext16u_i32(t0, t0); + tcg_gen_bswap16_i32(t0, t0); + t1 = tcg_temp_new(); + tcg_gen_extu_i32_tl(t1, t0); + tcg_temp_free_i32(t0); + tcg_gen_qemu_st16(t1, arg2, ctx->mem_idx); + tcg_temp_free(t1); +#else + TCGv t0 = tcg_temp_new(); + tcg_gen_ext16u_tl(t0, arg1); + tcg_gen_bswap16_i32(t0, t0); + tcg_gen_qemu_st16(t0, arg2, ctx->mem_idx); + tcg_temp_free(t0); +#endif + } else { + tcg_gen_qemu_st16(arg1, arg2, ctx->mem_idx); + } } GEN_STX(sthbr, st16r, 0x16, 0x1C, PPC_INTEGER); /* stwbrx */ -void always_inline gen_qemu_st32r(TCGv t0, TCGv t1, int flags) +static void always_inline gen_qemu_st32r(DisasContext *ctx, TCGv arg1, TCGv arg2) { - TCGv_i32 temp = tcg_temp_new_i32(); - TCGv t2 = tcg_temp_new(); - tcg_gen_trunc_tl_i32(temp, t0); - tcg_gen_bswap_i32(temp, temp); - tcg_gen_extu_i32_tl(t2, temp); - tcg_temp_free_i32(temp); - gen_qemu_st32(t2, t1, flags); - tcg_temp_free(t2); + if (likely(!ctx->le_mode)) { +#if defined(TARGET_PPC64) + TCGv_i32 t0; + TCGv t1; + t0 = tcg_temp_new_i32(); + tcg_gen_trunc_tl_i32(t0, arg1); + tcg_gen_bswap_i32(t0, t0); + t1 = tcg_temp_new(); + tcg_gen_extu_i32_tl(t1, t0); + tcg_temp_free_i32(t0); + tcg_gen_qemu_st32(t1, arg2, ctx->mem_idx); + tcg_temp_free(t1); +#else + TCGv t0 = tcg_temp_new_i32(); + tcg_gen_bswap_i32(t0, arg1); + tcg_gen_qemu_st32(t0, arg2, ctx->mem_idx); + tcg_temp_free(t0); +#endif + } else { + tcg_gen_qemu_st32(arg1, arg2, ctx->mem_idx); + } } GEN_STX(stwbr, st32r, 0x16, 0x14, PPC_INTEGER); @@ -3088,11 +3030,14 @@ GEN_STX(stwbr, st32r, 0x16, 0x14, PPC_INTEGER); /* lmw */ GEN_HANDLER(lmw, 0x2E, 0xFF, 0xFF, 0x00000000, PPC_INTEGER) { - TCGv t0 = tcg_temp_new(); - TCGv_i32 t1 = tcg_const_i32(rD(ctx->opcode)); + TCGv t0; + TCGv_i32 t1; + gen_set_access_type(ctx, ACCESS_INT); /* NIP cannot be restored if the memory exception comes from an helper */ gen_update_nip(ctx, ctx->nip - 4); - gen_addr_imm_index(t0, ctx, 0); + t0 = tcg_temp_new(); + t1 = tcg_const_i32(rD(ctx->opcode)); + gen_addr_imm_index(ctx, t0, 0); gen_helper_lmw(t0, t1); tcg_temp_free(t0); tcg_temp_free_i32(t1); @@ -3101,11 +3046,14 @@ GEN_HANDLER(lmw, 0x2E, 0xFF, 0xFF, 0x00000000, PPC_INTEGER) /* stmw */ GEN_HANDLER(stmw, 0x2F, 0xFF, 0xFF, 0x00000000, PPC_INTEGER) { - TCGv t0 = tcg_temp_new(); - TCGv_i32 t1 = tcg_const_i32(rS(ctx->opcode)); + TCGv t0; + TCGv_i32 t1; + gen_set_access_type(ctx, ACCESS_INT); /* NIP cannot be restored if the memory exception comes from an helper */ gen_update_nip(ctx, ctx->nip - 4); - gen_addr_imm_index(t0, ctx, 0); + t0 = tcg_temp_new(); + t1 = tcg_const_i32(rS(ctx->opcode)); + gen_addr_imm_index(ctx, t0, 0); gen_helper_stmw(t0, t1); tcg_temp_free(t0); tcg_temp_free_i32(t1); @@ -3133,14 +3081,14 @@ GEN_HANDLER(lswi, 0x1F, 0x15, 0x12, 0x00000001, PPC_STRING) if (unlikely(((start + nr) > 32 && start <= ra && (start + nr - 32) > ra) || ((start + nr) <= 32 && start <= ra && (start + nr) > ra))) { - GEN_EXCP(ctx, POWERPC_EXCP_PROGRAM, - POWERPC_EXCP_INVAL | POWERPC_EXCP_INVAL_LSWX); + gen_inval_exception(ctx, POWERPC_EXCP_INVAL_LSWX); return; } + gen_set_access_type(ctx, ACCESS_INT); /* NIP cannot be restored if the memory exception comes from an helper */ gen_update_nip(ctx, ctx->nip - 4); t0 = tcg_temp_new(); - gen_addr_register(t0, ctx); + gen_addr_register(ctx, t0); t1 = tcg_const_i32(nb); t2 = tcg_const_i32(start); gen_helper_lsw(t0, t1, t2); @@ -3152,13 +3100,16 @@ GEN_HANDLER(lswi, 0x1F, 0x15, 0x12, 0x00000001, PPC_STRING) /* lswx */ GEN_HANDLER(lswx, 0x1F, 0x15, 0x10, 0x00000001, PPC_STRING) { - TCGv t0 = tcg_temp_new(); - TCGv_i32 t1 = tcg_const_i32(rD(ctx->opcode)); - TCGv_i32 t2 = tcg_const_i32(rA(ctx->opcode)); - TCGv_i32 t3 = tcg_const_i32(rB(ctx->opcode)); + TCGv t0; + TCGv_i32 t1, t2, t3; + gen_set_access_type(ctx, ACCESS_INT); /* NIP cannot be restored if the memory exception comes from an helper */ gen_update_nip(ctx, ctx->nip - 4); - gen_addr_reg_index(t0, ctx); + t0 = tcg_temp_new(); + gen_addr_reg_index(ctx, t0); + t1 = tcg_const_i32(rD(ctx->opcode)); + t2 = tcg_const_i32(rA(ctx->opcode)); + t3 = tcg_const_i32(rB(ctx->opcode)); gen_helper_lswx(t0, t1, t2, t3); tcg_temp_free(t0); tcg_temp_free_i32(t1); @@ -3169,16 +3120,18 @@ GEN_HANDLER(lswx, 0x1F, 0x15, 0x10, 0x00000001, PPC_STRING) /* stswi */ GEN_HANDLER(stswi, 0x1F, 0x15, 0x16, 0x00000001, PPC_STRING) { + TCGv t0; + TCGv_i32 t1, t2; int nb = NB(ctx->opcode); - TCGv t0 = tcg_temp_new(); - TCGv_i32 t1; - TCGv_i32 t2 = tcg_const_i32(rS(ctx->opcode)); + gen_set_access_type(ctx, ACCESS_INT); /* NIP cannot be restored if the memory exception comes from an helper */ gen_update_nip(ctx, ctx->nip - 4); - gen_addr_register(t0, ctx); + t0 = tcg_temp_new(); + gen_addr_register(ctx, t0); if (nb == 0) nb = 32; t1 = tcg_const_i32(nb); + t2 = tcg_const_i32(rS(ctx->opcode)); gen_helper_stsw(t0, t1, t2); tcg_temp_free(t0); tcg_temp_free_i32(t1); @@ -3188,14 +3141,17 @@ GEN_HANDLER(stswi, 0x1F, 0x15, 0x16, 0x00000001, PPC_STRING) /* stswx */ GEN_HANDLER(stswx, 0x1F, 0x15, 0x14, 0x00000001, PPC_STRING) { - TCGv t0 = tcg_temp_new(); - TCGv_i32 t1 = tcg_temp_new_i32(); - TCGv_i32 t2 = tcg_const_i32(rS(ctx->opcode)); + TCGv t0; + TCGv_i32 t1, t2; + gen_set_access_type(ctx, ACCESS_INT); /* NIP cannot be restored if the memory exception comes from an helper */ gen_update_nip(ctx, ctx->nip - 4); - gen_addr_reg_index(t0, ctx); + t0 = tcg_temp_new(); + gen_addr_reg_index(ctx, t0); + t1 = tcg_temp_new_i32(); tcg_gen_trunc_tl_i32(t1, cpu_xer); tcg_gen_andi_i32(t1, t1, 0x7F); + t2 = tcg_const_i32(rS(ctx->opcode)); gen_helper_stsw(t0, t1, t2); tcg_temp_free(t0); tcg_temp_free_i32(t1); @@ -3211,21 +3167,18 @@ GEN_HANDLER(eieio, 0x1F, 0x16, 0x1A, 0x03FFF801, PPC_MEM_EIEIO) /* isync */ GEN_HANDLER(isync, 0x13, 0x16, 0x04, 0x03FFF801, PPC_MEM) { - GEN_STOP(ctx); + gen_stop_exception(ctx); } /* lwarx */ GEN_HANDLER(lwarx, 0x1F, 0x14, 0x00, 0x00000001, PPC_RES) { - TCGv t0 = tcg_temp_local_new(); - gen_set_access_type(ACCESS_RES); - gen_addr_reg_index(t0, ctx); + TCGv t0; + gen_set_access_type(ctx, ACCESS_RES); + t0 = tcg_temp_local_new(); + gen_addr_reg_index(ctx, t0); gen_check_align(ctx, t0, 0x03); -#if defined(TARGET_PPC64) - if (!ctx->sf_mode) - tcg_gen_ext32u_tl(t0, t0); -#endif - gen_qemu_ld32u(cpu_gpr[rD(ctx->opcode)], t0, ctx->mem_idx); + gen_qemu_ld32u(ctx, cpu_gpr[rD(ctx->opcode)], t0); tcg_gen_mov_tl(cpu_reserve, t0); tcg_temp_free(t0); } @@ -3233,21 +3186,19 @@ GEN_HANDLER(lwarx, 0x1F, 0x14, 0x00, 0x00000001, PPC_RES) /* stwcx. */ GEN_HANDLER2(stwcx_, "stwcx.", 0x1F, 0x16, 0x04, 0x00000000, PPC_RES) { - int l1 = gen_new_label(); - TCGv t0 = tcg_temp_local_new(); - gen_set_access_type(ACCESS_RES); - gen_addr_reg_index(t0, ctx); + int l1; + TCGv t0; + gen_set_access_type(ctx, ACCESS_RES); + t0 = tcg_temp_local_new(); + gen_addr_reg_index(ctx, t0); gen_check_align(ctx, t0, 0x03); -#if defined(TARGET_PPC64) - if (!ctx->sf_mode) - tcg_gen_ext32u_tl(t0, t0); -#endif tcg_gen_trunc_tl_i32(cpu_crf[0], cpu_xer); tcg_gen_shri_i32(cpu_crf[0], cpu_crf[0], XER_SO); tcg_gen_andi_i32(cpu_crf[0], cpu_crf[0], 1); + l1 = gen_new_label(); tcg_gen_brcond_tl(TCG_COND_NE, t0, cpu_reserve, l1); tcg_gen_ori_i32(cpu_crf[0], cpu_crf[0], 1 << CRF_EQ); - gen_qemu_st32(cpu_gpr[rS(ctx->opcode)], t0, ctx->mem_idx); + gen_qemu_st32(ctx, cpu_gpr[rS(ctx->opcode)], t0); gen_set_label(l1); tcg_gen_movi_tl(cpu_reserve, -1); tcg_temp_free(t0); @@ -3257,13 +3208,12 @@ GEN_HANDLER2(stwcx_, "stwcx.", 0x1F, 0x16, 0x04, 0x00000000, PPC_RES) /* ldarx */ GEN_HANDLER(ldarx, 0x1F, 0x14, 0x02, 0x00000001, PPC_64B) { - TCGv t0 = tcg_temp_local_new(); - gen_set_access_type(ACCESS_RES); - gen_addr_reg_index(t0, ctx); + TCGv t0; + gen_set_access_type(ctx, ACCESS_RES); + t0 = tcg_temp_local_new(); + gen_addr_reg_index(ctx, t0); gen_check_align(ctx, t0, 0x07); - if (!ctx->sf_mode) - tcg_gen_ext32u_tl(t0, t0); - gen_qemu_ld64(cpu_gpr[rD(ctx->opcode)], t0, ctx->mem_idx); + gen_qemu_ld64(ctx, cpu_gpr[rD(ctx->opcode)], t0); tcg_gen_mov_tl(cpu_reserve, t0); tcg_temp_free(t0); } @@ -3271,19 +3221,19 @@ GEN_HANDLER(ldarx, 0x1F, 0x14, 0x02, 0x00000001, PPC_64B) /* stdcx. */ GEN_HANDLER2(stdcx_, "stdcx.", 0x1F, 0x16, 0x06, 0x00000000, PPC_64B) { - int l1 = gen_new_label(); - TCGv t0 = tcg_temp_local_new(); - gen_set_access_type(ACCESS_RES); - gen_addr_reg_index(t0, ctx); + int l1; + TCGv t0; + gen_set_access_type(ctx, ACCESS_RES); + t0 = tcg_temp_local_new(); + gen_addr_reg_index(ctx, t0); gen_check_align(ctx, t0, 0x07); - if (!ctx->sf_mode) - tcg_gen_ext32u_tl(t0, t0); tcg_gen_trunc_tl_i32(cpu_crf[0], cpu_xer); tcg_gen_shri_i32(cpu_crf[0], cpu_crf[0], XER_SO); tcg_gen_andi_i32(cpu_crf[0], cpu_crf[0], 1); + l1 = gen_new_label(); tcg_gen_brcond_tl(TCG_COND_NE, t0, cpu_reserve, l1); tcg_gen_ori_i32(cpu_crf[0], cpu_crf[0], 1 << CRF_EQ); - gen_qemu_st64(cpu_gpr[rS(ctx->opcode)], t0, ctx->mem_idx); + gen_qemu_st64(ctx, cpu_gpr[rS(ctx->opcode)], t0); gen_set_label(l1); tcg_gen_movi_tl(cpu_reserve, -1); tcg_temp_free(t0); @@ -3302,7 +3252,7 @@ GEN_HANDLER(wait, 0x1F, 0x1E, 0x01, 0x03FFF801, PPC_WAIT) tcg_gen_st_i32(t0, cpu_env, offsetof(CPUState, halted)); tcg_temp_free_i32(t0); /* Stop translation, as the CPU is supposed to sleep from now */ - GEN_EXCP(ctx, EXCP_HLT, 1); + gen_exception_err(ctx, EXCP_HLT, 1); } /*** Floating-point load ***/ @@ -3311,13 +3261,13 @@ GEN_HANDLER(name, opc, 0xFF, 0xFF, 0x00000000, type) \ { \ TCGv EA; \ if (unlikely(!ctx->fpu_enabled)) { \ - GEN_EXCP_NO_FP(ctx); \ + gen_exception(ctx, POWERPC_EXCP_FPU); \ return; \ } \ - gen_set_access_type(ACCESS_FLOAT); \ + gen_set_access_type(ctx, ACCESS_FLOAT); \ EA = tcg_temp_new(); \ - gen_addr_imm_index(EA, ctx, 0); \ - gen_qemu_##ldop(cpu_fpr[rD(ctx->opcode)], EA, ctx->mem_idx); \ + gen_addr_imm_index(ctx, EA, 0); \ + gen_qemu_##ldop(ctx, cpu_fpr[rD(ctx->opcode)], EA); \ tcg_temp_free(EA); \ } @@ -3326,17 +3276,17 @@ GEN_HANDLER(name##u, opc, 0xFF, 0xFF, 0x00000000, type) \ { \ TCGv EA; \ if (unlikely(!ctx->fpu_enabled)) { \ - GEN_EXCP_NO_FP(ctx); \ + gen_exception(ctx, POWERPC_EXCP_FPU); \ return; \ } \ if (unlikely(rA(ctx->opcode) == 0)) { \ - GEN_EXCP_INVAL(ctx); \ + gen_inval_exception(ctx, POWERPC_EXCP_INVAL_INVAL); \ return; \ } \ - gen_set_access_type(ACCESS_FLOAT); \ + gen_set_access_type(ctx, ACCESS_FLOAT); \ EA = tcg_temp_new(); \ - gen_addr_imm_index(EA, ctx, 0); \ - gen_qemu_##ldop(cpu_fpr[rD(ctx->opcode)], EA, ctx->mem_idx); \ + gen_addr_imm_index(ctx, EA, 0); \ + gen_qemu_##ldop(ctx, cpu_fpr[rD(ctx->opcode)], EA); \ tcg_gen_mov_tl(cpu_gpr[rA(ctx->opcode)], EA); \ tcg_temp_free(EA); \ } @@ -3346,17 +3296,17 @@ GEN_HANDLER(name##ux, 0x1F, 0x17, opc, 0x00000001, type) \ { \ TCGv EA; \ if (unlikely(!ctx->fpu_enabled)) { \ - GEN_EXCP_NO_FP(ctx); \ + gen_exception(ctx, POWERPC_EXCP_FPU); \ return; \ } \ if (unlikely(rA(ctx->opcode) == 0)) { \ - GEN_EXCP_INVAL(ctx); \ + gen_inval_exception(ctx, POWERPC_EXCP_INVAL_INVAL); \ return; \ } \ - gen_set_access_type(ACCESS_FLOAT); \ + gen_set_access_type(ctx, ACCESS_FLOAT); \ EA = tcg_temp_new(); \ - gen_addr_reg_index(EA, ctx); \ - gen_qemu_##ldop(cpu_fpr[rD(ctx->opcode)], EA, ctx->mem_idx); \ + gen_addr_reg_index(ctx, EA); \ + gen_qemu_##ldop(ctx, cpu_fpr[rD(ctx->opcode)], EA); \ tcg_gen_mov_tl(cpu_gpr[rA(ctx->opcode)], EA); \ tcg_temp_free(EA); \ } @@ -3366,13 +3316,13 @@ GEN_HANDLER(name##x, 0x1F, opc2, opc3, 0x00000001, type) \ { \ TCGv EA; \ if (unlikely(!ctx->fpu_enabled)) { \ - GEN_EXCP_NO_FP(ctx); \ + gen_exception(ctx, POWERPC_EXCP_FPU); \ return; \ } \ - gen_set_access_type(ACCESS_FLOAT); \ + gen_set_access_type(ctx, ACCESS_FLOAT); \ EA = tcg_temp_new(); \ - gen_addr_reg_index(EA, ctx); \ - gen_qemu_##ldop(cpu_fpr[rD(ctx->opcode)], EA, ctx->mem_idx); \ + gen_addr_reg_index(ctx, EA); \ + gen_qemu_##ldop(ctx, cpu_fpr[rD(ctx->opcode)], EA); \ tcg_temp_free(EA); \ } @@ -3382,11 +3332,11 @@ GEN_LDUF(name, ldop, op | 0x21, type); \ GEN_LDUXF(name, ldop, op | 0x01, type); \ GEN_LDXF(name, ldop, 0x17, op | 0x00, type) -static always_inline void gen_qemu_ld32fs(TCGv_i64 arg1, TCGv arg2, int flags) +static always_inline void gen_qemu_ld32fs(DisasContext *ctx, TCGv_i64 arg1, TCGv arg2) { TCGv t0 = tcg_temp_new(); TCGv_i32 t1 = tcg_temp_new_i32(); - gen_qemu_ld32u(t0, arg2, flags); + gen_qemu_ld32u(ctx, t0, arg2); tcg_gen_trunc_tl_i32(t1, t0); tcg_temp_free(t0); gen_helper_float32_to_float64(arg1, t1); @@ -3404,13 +3354,13 @@ GEN_HANDLER(name, opc, 0xFF, 0xFF, 0x00000000, type) \ { \ TCGv EA; \ if (unlikely(!ctx->fpu_enabled)) { \ - GEN_EXCP_NO_FP(ctx); \ + gen_exception(ctx, POWERPC_EXCP_FPU); \ return; \ } \ - gen_set_access_type(ACCESS_FLOAT); \ + gen_set_access_type(ctx, ACCESS_FLOAT); \ EA = tcg_temp_new(); \ - gen_addr_imm_index(EA, ctx, 0); \ - gen_qemu_##stop(cpu_fpr[rS(ctx->opcode)], EA, ctx->mem_idx); \ + gen_addr_imm_index(ctx, EA, 0); \ + gen_qemu_##stop(ctx, cpu_fpr[rS(ctx->opcode)], EA); \ tcg_temp_free(EA); \ } @@ -3419,17 +3369,17 @@ GEN_HANDLER(name##u, opc, 0xFF, 0xFF, 0x00000000, type) \ { \ TCGv EA; \ if (unlikely(!ctx->fpu_enabled)) { \ - GEN_EXCP_NO_FP(ctx); \ + gen_exception(ctx, POWERPC_EXCP_FPU); \ return; \ } \ if (unlikely(rA(ctx->opcode) == 0)) { \ - GEN_EXCP_INVAL(ctx); \ + gen_inval_exception(ctx, POWERPC_EXCP_INVAL_INVAL); \ return; \ } \ - gen_set_access_type(ACCESS_FLOAT); \ + gen_set_access_type(ctx, ACCESS_FLOAT); \ EA = tcg_temp_new(); \ - gen_addr_imm_index(EA, ctx, 0); \ - gen_qemu_##stop(cpu_fpr[rS(ctx->opcode)], EA, ctx->mem_idx); \ + gen_addr_imm_index(ctx, EA, 0); \ + gen_qemu_##stop(ctx, cpu_fpr[rS(ctx->opcode)], EA); \ tcg_gen_mov_tl(cpu_gpr[rA(ctx->opcode)], EA); \ tcg_temp_free(EA); \ } @@ -3439,17 +3389,17 @@ GEN_HANDLER(name##ux, 0x1F, 0x17, opc, 0x00000001, type) \ { \ TCGv EA; \ if (unlikely(!ctx->fpu_enabled)) { \ - GEN_EXCP_NO_FP(ctx); \ + gen_exception(ctx, POWERPC_EXCP_FPU); \ return; \ } \ if (unlikely(rA(ctx->opcode) == 0)) { \ - GEN_EXCP_INVAL(ctx); \ + gen_inval_exception(ctx, POWERPC_EXCP_INVAL_INVAL); \ return; \ } \ - gen_set_access_type(ACCESS_FLOAT); \ + gen_set_access_type(ctx, ACCESS_FLOAT); \ EA = tcg_temp_new(); \ - gen_addr_reg_index(EA, ctx); \ - gen_qemu_##stop(cpu_fpr[rS(ctx->opcode)], EA, ctx->mem_idx); \ + gen_addr_reg_index(ctx, EA); \ + gen_qemu_##stop(ctx, cpu_fpr[rS(ctx->opcode)], EA); \ tcg_gen_mov_tl(cpu_gpr[rA(ctx->opcode)], EA); \ tcg_temp_free(EA); \ } @@ -3459,13 +3409,13 @@ GEN_HANDLER(name##x, 0x1F, opc2, opc3, 0x00000001, type) \ { \ TCGv EA; \ if (unlikely(!ctx->fpu_enabled)) { \ - GEN_EXCP_NO_FP(ctx); \ + gen_exception(ctx, POWERPC_EXCP_FPU); \ return; \ } \ - gen_set_access_type(ACCESS_FLOAT); \ + gen_set_access_type(ctx, ACCESS_FLOAT); \ EA = tcg_temp_new(); \ - gen_addr_reg_index(EA, ctx); \ - gen_qemu_##stop(cpu_fpr[rS(ctx->opcode)], EA, ctx->mem_idx); \ + gen_addr_reg_index(ctx, EA); \ + gen_qemu_##stop(ctx, cpu_fpr[rS(ctx->opcode)], EA); \ tcg_temp_free(EA); \ } @@ -3475,14 +3425,14 @@ GEN_STUF(name, stop, op | 0x21, type); \ GEN_STUXF(name, stop, op | 0x01, type); \ GEN_STXF(name, stop, 0x17, op | 0x00, type) -static always_inline void gen_qemu_st32fs(TCGv_i64 arg1, TCGv arg2, int flags) +static always_inline void gen_qemu_st32fs(DisasContext *ctx, TCGv_i64 arg1, TCGv arg2) { TCGv_i32 t0 = tcg_temp_new_i32(); TCGv t1 = tcg_temp_new(); gen_helper_float64_to_float32(t0, arg1); tcg_gen_extu_i32_tl(t1, t0); tcg_temp_free_i32(t0); - gen_qemu_st32(t1, arg2, flags); + gen_qemu_st32(ctx, t1, arg2); tcg_temp_free(t1); } @@ -3492,11 +3442,11 @@ GEN_STFS(stfd, st64, 0x16, PPC_FLOAT); GEN_STFS(stfs, st32fs, 0x14, PPC_FLOAT); /* Optional: */ -static always_inline void gen_qemu_st32fiw(TCGv_i64 arg1, TCGv arg2, int flags) +static always_inline void gen_qemu_st32fiw(DisasContext *ctx, TCGv_i64 arg1, TCGv arg2) { TCGv t0 = tcg_temp_new(); tcg_gen_trunc_i64_tl(t0, arg1), - gen_qemu_st32(t0, arg2, flags); + gen_qemu_st32(ctx, t0, arg2); tcg_temp_free(t0); } /* stfiwx */ @@ -3525,12 +3475,11 @@ static always_inline void gen_goto_tb (DisasContext *ctx, int n, ctx->exception == POWERPC_EXCP_BRANCH) { target_ulong tmp = ctx->nip; ctx->nip = dest; - GEN_EXCP(ctx, POWERPC_EXCP_TRACE, 0); + gen_exception(ctx, POWERPC_EXCP_TRACE); ctx->nip = tmp; } if (ctx->singlestep_enabled & GDBSTUB_SINGLE_STEP) { - gen_update_nip(ctx, dest); - gen_helper_raise_debug(); + gen_debug_exception(ctx); } } tcg_gen_exit_tb(0); @@ -3594,7 +3543,7 @@ static always_inline void gen_bcond (DisasContext *ctx, int type) /* Decrement and test CTR */ TCGv temp = tcg_temp_new(); if (unlikely(type == BCOND_CTR)) { - GEN_EXCP_INVAL(ctx); + gen_inval_exception(ctx, POWERPC_EXCP_INVAL_INVAL); return; } tcg_gen_subi_tl(cpu_ctr, cpu_ctr, 1); @@ -3724,19 +3673,19 @@ GEN_HANDLER(mcrf, 0x13, 0x00, 0xFF, 0x00000001, PPC_INTEGER) } /*** System linkage ***/ -/* rfi (supervisor only) */ +/* rfi (mem_idx only) */ GEN_HANDLER(rfi, 0x13, 0x12, 0x01, 0x03FF8001, PPC_FLOW) { #if defined(CONFIG_USER_ONLY) - GEN_EXCP_PRIVOPC(ctx); + gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC); #else /* Restore CPU state */ - if (unlikely(!ctx->supervisor)) { - GEN_EXCP_PRIVOPC(ctx); + if (unlikely(!ctx->mem_idx)) { + gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC); return; } gen_helper_rfi(); - GEN_SYNC(ctx); + gen_sync_exception(ctx); #endif } @@ -3744,30 +3693,30 @@ GEN_HANDLER(rfi, 0x13, 0x12, 0x01, 0x03FF8001, PPC_FLOW) GEN_HANDLER(rfid, 0x13, 0x12, 0x00, 0x03FF8001, PPC_64B) { #if defined(CONFIG_USER_ONLY) - GEN_EXCP_PRIVOPC(ctx); + gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC); #else /* Restore CPU state */ - if (unlikely(!ctx->supervisor)) { - GEN_EXCP_PRIVOPC(ctx); + if (unlikely(!ctx->mem_idx)) { + gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC); return; } gen_helper_rfid(); - GEN_SYNC(ctx); + gen_sync_exception(ctx); #endif } GEN_HANDLER(hrfid, 0x13, 0x12, 0x08, 0x03FF8001, PPC_64H) { #if defined(CONFIG_USER_ONLY) - GEN_EXCP_PRIVOPC(ctx); + gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC); #else /* Restore CPU state */ - if (unlikely(ctx->supervisor <= 1)) { - GEN_EXCP_PRIVOPC(ctx); + if (unlikely(ctx->mem_idx <= 1)) { + gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC); return; } gen_helper_hrfid(); - GEN_SYNC(ctx); + gen_sync_exception(ctx); #endif } #endif @@ -3783,7 +3732,7 @@ GEN_HANDLER(sc, 0x11, 0xFF, 0xFF, 0x03FFF01D, PPC_FLOW) uint32_t lev; lev = (ctx->opcode >> 5) & 0x7F; - GEN_EXCP(ctx, POWERPC_SYSCALL, lev); + gen_exception_err(ctx, POWERPC_SYSCALL, lev); } /*** Trap ***/ @@ -3862,10 +3811,10 @@ GEN_HANDLER(mfcr, 0x1F, 0x13, 0x00, 0x00000801, PPC_MISC) GEN_HANDLER(mfmsr, 0x1F, 0x13, 0x02, 0x001FF801, PPC_MISC) { #if defined(CONFIG_USER_ONLY) - GEN_EXCP_PRIVREG(ctx); + gen_inval_exception(ctx, POWERPC_EXCP_PRIV_REG); #else - if (unlikely(!ctx->supervisor)) { - GEN_EXCP_PRIVREG(ctx); + if (unlikely(!ctx->mem_idx)) { + gen_inval_exception(ctx, POWERPC_EXCP_PRIV_REG); return; } tcg_gen_mov_tl(cpu_gpr[rD(ctx->opcode)], cpu_msr); @@ -3886,21 +3835,20 @@ static void spr_noaccess (void *opaque, int sprn) /* mfspr */ static always_inline void gen_op_mfspr (DisasContext *ctx) { - void (*read_cb)(void *opaque, int sprn); + void (*read_cb)(void *opaque, int gprn, int sprn); uint32_t sprn = SPR(ctx->opcode); #if !defined(CONFIG_USER_ONLY) - if (ctx->supervisor == 2) + if (ctx->mem_idx == 2) read_cb = ctx->spr_cb[sprn].hea_read; - else if (ctx->supervisor) + else if (ctx->mem_idx) read_cb = ctx->spr_cb[sprn].oea_read; else #endif read_cb = ctx->spr_cb[sprn].uea_read; if (likely(read_cb != NULL)) { if (likely(read_cb != SPR_NOACCESS)) { - (*read_cb)(ctx, sprn); - tcg_gen_mov_tl(cpu_gpr[rD(ctx->opcode)], cpu_T[0]); + (*read_cb)(ctx, rD(ctx->opcode), sprn); } else { /* Privilege exception */ /* This is a hack to avoid warnings when running Linux: @@ -3915,7 +3863,7 @@ static always_inline void gen_op_mfspr (DisasContext *ctx) printf("Trying to read privileged spr %d %03x at " ADDRX "\n", sprn, sprn, ctx->nip); } - GEN_EXCP_PRIVREG(ctx); + gen_inval_exception(ctx, POWERPC_EXCP_PRIV_REG); } } else { /* Not defined */ @@ -3925,8 +3873,7 @@ static always_inline void gen_op_mfspr (DisasContext *ctx) } printf("Trying to read invalid spr %d %03x at " ADDRX "\n", sprn, sprn, ctx->nip); - GEN_EXCP(ctx, POWERPC_EXCP_PROGRAM, - POWERPC_EXCP_INVAL | POWERPC_EXCP_INVAL_SPR); + gen_inval_exception(ctx, POWERPC_EXCP_INVAL_SPR); } } @@ -3966,13 +3913,12 @@ GEN_HANDLER(mtcrf, 0x1F, 0x10, 0x04, 0x00000801, PPC_MISC) GEN_HANDLER(mtmsrd, 0x1F, 0x12, 0x05, 0x001EF801, PPC_64B) { #if defined(CONFIG_USER_ONLY) - GEN_EXCP_PRIVREG(ctx); + gen_inval_exception(ctx, POWERPC_EXCP_PRIV_REG); #else - if (unlikely(!ctx->supervisor)) { - GEN_EXCP_PRIVREG(ctx); + if (unlikely(!ctx->mem_idx)) { + gen_inval_exception(ctx, POWERPC_EXCP_PRIV_REG); return; } - tcg_gen_mov_tl(cpu_T[0], cpu_gpr[rS(ctx->opcode)]); if (ctx->opcode & 0x00010000) { /* Special form that does not need any synchronisation */ TCGv t0 = tcg_temp_new(); @@ -3989,7 +3935,7 @@ GEN_HANDLER(mtmsrd, 0x1F, 0x12, 0x05, 0x001EF801, PPC_64B) gen_helper_store_msr(cpu_gpr[rS(ctx->opcode)]); /* Must stop the translation as machine state (may have) changed */ /* Note that mtmsr is not always defined as context-synchronizing */ - ctx->exception = POWERPC_EXCP_STOP; + gen_stop_exception(ctx); } #endif } @@ -3998,13 +3944,12 @@ GEN_HANDLER(mtmsrd, 0x1F, 0x12, 0x05, 0x001EF801, PPC_64B) GEN_HANDLER(mtmsr, 0x1F, 0x12, 0x04, 0x001FF801, PPC_MISC) { #if defined(CONFIG_USER_ONLY) - GEN_EXCP_PRIVREG(ctx); + gen_inval_exception(ctx, POWERPC_EXCP_PRIV_REG); #else - if (unlikely(!ctx->supervisor)) { - GEN_EXCP_PRIVREG(ctx); + if (unlikely(!ctx->mem_idx)) { + gen_inval_exception(ctx, POWERPC_EXCP_PRIV_REG); return; } - tcg_gen_mov_tl(cpu_T[0], cpu_gpr[rS(ctx->opcode)]); if (ctx->opcode & 0x00010000) { /* Special form that does not need any synchronisation */ TCGv t0 = tcg_temp_new(); @@ -4033,7 +3978,7 @@ GEN_HANDLER(mtmsr, 0x1F, 0x12, 0x04, 0x001FF801, PPC_MISC) gen_helper_store_msr(cpu_gpr[rS(ctx->opcode)]); /* Must stop the translation as machine state (may have) changed */ /* Note that mtmsr is not always defined as context-synchronizing */ - ctx->exception = POWERPC_EXCP_STOP; + gen_stop_exception(ctx); } #endif } @@ -4041,21 +3986,20 @@ GEN_HANDLER(mtmsr, 0x1F, 0x12, 0x04, 0x001FF801, PPC_MISC) /* mtspr */ GEN_HANDLER(mtspr, 0x1F, 0x13, 0x0E, 0x00000001, PPC_MISC) { - void (*write_cb)(void *opaque, int sprn); + void (*write_cb)(void *opaque, int sprn, int gprn); uint32_t sprn = SPR(ctx->opcode); #if !defined(CONFIG_USER_ONLY) - if (ctx->supervisor == 2) + if (ctx->mem_idx == 2) write_cb = ctx->spr_cb[sprn].hea_write; - else if (ctx->supervisor) + else if (ctx->mem_idx) write_cb = ctx->spr_cb[sprn].oea_write; else #endif write_cb = ctx->spr_cb[sprn].uea_write; if (likely(write_cb != NULL)) { if (likely(write_cb != SPR_NOACCESS)) { - tcg_gen_mov_tl(cpu_T[0], cpu_gpr[rS(ctx->opcode)]); - (*write_cb)(ctx, sprn); + (*write_cb)(ctx, sprn, rS(ctx->opcode)); } else { /* Privilege exception */ if (loglevel != 0) { @@ -4064,7 +4008,7 @@ GEN_HANDLER(mtspr, 0x1F, 0x13, 0x0E, 0x00000001, PPC_MISC) } printf("Trying to write privileged spr %d %03x at " ADDRX "\n", sprn, sprn, ctx->nip); - GEN_EXCP_PRIVREG(ctx); + gen_inval_exception(ctx, POWERPC_EXCP_PRIV_REG); } } else { /* Not defined */ @@ -4074,8 +4018,7 @@ GEN_HANDLER(mtspr, 0x1F, 0x13, 0x0E, 0x00000001, PPC_MISC) } printf("Trying to write invalid spr %d %03x at " ADDRX "\n", sprn, sprn, ctx->nip); - GEN_EXCP(ctx, POWERPC_EXCP_PROGRAM, - POWERPC_EXCP_INVAL | POWERPC_EXCP_INVAL_SPR); + gen_inval_exception(ctx, POWERPC_EXCP_INVAL_SPR); } } @@ -4084,10 +4027,11 @@ GEN_HANDLER(mtspr, 0x1F, 0x13, 0x0E, 0x00000001, PPC_MISC) GEN_HANDLER(dcbf, 0x1F, 0x16, 0x02, 0x03C00001, PPC_CACHE) { /* XXX: specification says this is treated as a load by the MMU */ - TCGv t0 = tcg_temp_new(); - gen_set_access_type(ACCESS_CACHE); - gen_addr_reg_index(t0, ctx); - gen_qemu_ld8u(t0, t0, ctx->mem_idx); + TCGv t0; + gen_set_access_type(ctx, ACCESS_CACHE); + t0 = tcg_temp_new(); + gen_addr_reg_index(ctx, t0); + gen_qemu_ld8u(ctx, t0, t0); tcg_temp_free(t0); } @@ -4095,20 +4039,20 @@ GEN_HANDLER(dcbf, 0x1F, 0x16, 0x02, 0x03C00001, PPC_CACHE) GEN_HANDLER(dcbi, 0x1F, 0x16, 0x0E, 0x03E00001, PPC_CACHE) { #if defined(CONFIG_USER_ONLY) - GEN_EXCP_PRIVOPC(ctx); + gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC); #else TCGv EA, val; - if (unlikely(!ctx->supervisor)) { - GEN_EXCP_PRIVOPC(ctx); + if (unlikely(!ctx->mem_idx)) { + gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC); return; } EA = tcg_temp_new(); - gen_set_access_type(ACCESS_CACHE); - gen_addr_reg_index(EA, ctx); + gen_set_access_type(ctx, ACCESS_CACHE); + gen_addr_reg_index(ctx, EA); val = tcg_temp_new(); /* XXX: specification says this should be treated as a store by the MMU */ - gen_qemu_ld8u(val, EA, ctx->mem_idx); - gen_qemu_st8(val, EA, ctx->mem_idx); + gen_qemu_ld8u(ctx, val, EA); + gen_qemu_st8(ctx, val, EA); tcg_temp_free(val); tcg_temp_free(EA); #endif @@ -4118,10 +4062,11 @@ GEN_HANDLER(dcbi, 0x1F, 0x16, 0x0E, 0x03E00001, PPC_CACHE) GEN_HANDLER(dcbst, 0x1F, 0x16, 0x01, 0x03E00001, PPC_CACHE) { /* XXX: specification say this is treated as a load by the MMU */ - TCGv t0 = tcg_temp_new(); - gen_set_access_type(ACCESS_CACHE); - gen_addr_reg_index(t0, ctx); - gen_qemu_ld8u(t0, t0, ctx->mem_idx); + TCGv t0; + gen_set_access_type(ctx, ACCESS_CACHE); + t0 = tcg_temp_new(); + gen_addr_reg_index(ctx, t0); + gen_qemu_ld8u(ctx, t0, t0); tcg_temp_free(t0); } @@ -4146,20 +4091,24 @@ GEN_HANDLER(dcbtst, 0x1F, 0x16, 0x07, 0x02000001, PPC_CACHE) /* dcbz */ GEN_HANDLER(dcbz, 0x1F, 0x16, 0x1F, 0x03E00001, PPC_CACHE_DCBZ) { - TCGv t0 = tcg_temp_new(); - gen_addr_reg_index(t0, ctx); + TCGv t0; + gen_set_access_type(ctx, ACCESS_CACHE); /* NIP cannot be restored if the memory exception comes from an helper */ gen_update_nip(ctx, ctx->nip - 4); + t0 = tcg_temp_new(); + gen_addr_reg_index(ctx, t0); gen_helper_dcbz(t0); tcg_temp_free(t0); } GEN_HANDLER2(dcbz_970, "dcbz", 0x1F, 0x16, 0x1F, 0x03C00001, PPC_CACHE_DCBZT) { - TCGv t0 = tcg_temp_new(); - gen_addr_reg_index(t0, ctx); + TCGv t0; + gen_set_access_type(ctx, ACCESS_CACHE); /* NIP cannot be restored if the memory exception comes from an helper */ gen_update_nip(ctx, ctx->nip - 4); + t0 = tcg_temp_new(); + gen_addr_reg_index(ctx, t0); if (ctx->opcode & 0x00200000) gen_helper_dcbz(t0); else @@ -4170,10 +4119,12 @@ GEN_HANDLER2(dcbz_970, "dcbz", 0x1F, 0x16, 0x1F, 0x03C00001, PPC_CACHE_DCBZT) /* icbi */ GEN_HANDLER(icbi, 0x1F, 0x16, 0x1E, 0x03E00001, PPC_CACHE_ICBI) { - TCGv t0 = tcg_temp_new(); + TCGv t0; + gen_set_access_type(ctx, ACCESS_CACHE); /* NIP cannot be restored if the memory exception comes from an helper */ gen_update_nip(ctx, ctx->nip - 4); - gen_addr_reg_index(t0, ctx); + t0 = tcg_temp_new(); + gen_addr_reg_index(ctx, t0); gen_helper_icbi(t0); tcg_temp_free(t0); } @@ -4194,11 +4145,11 @@ GEN_HANDLER(dcba, 0x1F, 0x16, 0x17, 0x03E00001, PPC_CACHE_DCBA) GEN_HANDLER(mfsr, 0x1F, 0x13, 0x12, 0x0010F801, PPC_SEGMENT) { #if defined(CONFIG_USER_ONLY) - GEN_EXCP_PRIVREG(ctx); + gen_inval_exception(ctx, POWERPC_EXCP_PRIV_REG); #else TCGv t0; - if (unlikely(!ctx->supervisor)) { - GEN_EXCP_PRIVREG(ctx); + if (unlikely(!ctx->mem_idx)) { + gen_inval_exception(ctx, POWERPC_EXCP_PRIV_REG); return; } t0 = tcg_const_tl(SR(ctx->opcode)); @@ -4211,11 +4162,11 @@ GEN_HANDLER(mfsr, 0x1F, 0x13, 0x12, 0x0010F801, PPC_SEGMENT) GEN_HANDLER(mfsrin, 0x1F, 0x13, 0x14, 0x001F0001, PPC_SEGMENT) { #if defined(CONFIG_USER_ONLY) - GEN_EXCP_PRIVREG(ctx); + gen_inval_exception(ctx, POWERPC_EXCP_PRIV_REG); #else TCGv t0; - if (unlikely(!ctx->supervisor)) { - GEN_EXCP_PRIVREG(ctx); + if (unlikely(!ctx->mem_idx)) { + gen_inval_exception(ctx, POWERPC_EXCP_PRIV_REG); return; } t0 = tcg_temp_new(); @@ -4230,11 +4181,11 @@ GEN_HANDLER(mfsrin, 0x1F, 0x13, 0x14, 0x001F0001, PPC_SEGMENT) GEN_HANDLER(mtsr, 0x1F, 0x12, 0x06, 0x0010F801, PPC_SEGMENT) { #if defined(CONFIG_USER_ONLY) - GEN_EXCP_PRIVREG(ctx); + gen_inval_exception(ctx, POWERPC_EXCP_PRIV_REG); #else TCGv t0; - if (unlikely(!ctx->supervisor)) { - GEN_EXCP_PRIVREG(ctx); + if (unlikely(!ctx->mem_idx)) { + gen_inval_exception(ctx, POWERPC_EXCP_PRIV_REG); return; } t0 = tcg_const_tl(SR(ctx->opcode)); @@ -4247,11 +4198,11 @@ GEN_HANDLER(mtsr, 0x1F, 0x12, 0x06, 0x0010F801, PPC_SEGMENT) GEN_HANDLER(mtsrin, 0x1F, 0x12, 0x07, 0x001F0001, PPC_SEGMENT) { #if defined(CONFIG_USER_ONLY) - GEN_EXCP_PRIVREG(ctx); + gen_inval_exception(ctx, POWERPC_EXCP_PRIV_REG); #else TCGv t0; - if (unlikely(!ctx->supervisor)) { - GEN_EXCP_PRIVREG(ctx); + if (unlikely(!ctx->mem_idx)) { + gen_inval_exception(ctx, POWERPC_EXCP_PRIV_REG); return; } t0 = tcg_temp_new(); @@ -4268,11 +4219,11 @@ GEN_HANDLER(mtsrin, 0x1F, 0x12, 0x07, 0x001F0001, PPC_SEGMENT) GEN_HANDLER2(mfsr_64b, "mfsr", 0x1F, 0x13, 0x12, 0x0010F801, PPC_SEGMENT_64B) { #if defined(CONFIG_USER_ONLY) - GEN_EXCP_PRIVREG(ctx); + gen_inval_exception(ctx, POWERPC_EXCP_PRIV_REG); #else TCGv t0; - if (unlikely(!ctx->supervisor)) { - GEN_EXCP_PRIVREG(ctx); + if (unlikely(!ctx->mem_idx)) { + gen_inval_exception(ctx, POWERPC_EXCP_PRIV_REG); return; } t0 = tcg_const_tl(SR(ctx->opcode)); @@ -4286,11 +4237,11 @@ GEN_HANDLER2(mfsrin_64b, "mfsrin", 0x1F, 0x13, 0x14, 0x001F0001, PPC_SEGMENT_64B) { #if defined(CONFIG_USER_ONLY) - GEN_EXCP_PRIVREG(ctx); + gen_inval_exception(ctx, POWERPC_EXCP_PRIV_REG); #else TCGv t0; - if (unlikely(!ctx->supervisor)) { - GEN_EXCP_PRIVREG(ctx); + if (unlikely(!ctx->mem_idx)) { + gen_inval_exception(ctx, POWERPC_EXCP_PRIV_REG); return; } t0 = tcg_temp_new(); @@ -4305,11 +4256,11 @@ GEN_HANDLER2(mfsrin_64b, "mfsrin", 0x1F, 0x13, 0x14, 0x001F0001, GEN_HANDLER2(mtsr_64b, "mtsr", 0x1F, 0x12, 0x06, 0x0010F801, PPC_SEGMENT_64B) { #if defined(CONFIG_USER_ONLY) - GEN_EXCP_PRIVREG(ctx); + gen_inval_exception(ctx, POWERPC_EXCP_PRIV_REG); #else TCGv t0; - if (unlikely(!ctx->supervisor)) { - GEN_EXCP_PRIVREG(ctx); + if (unlikely(!ctx->mem_idx)) { + gen_inval_exception(ctx, POWERPC_EXCP_PRIV_REG); return; } t0 = tcg_const_tl(SR(ctx->opcode)); @@ -4323,11 +4274,11 @@ GEN_HANDLER2(mtsrin_64b, "mtsrin", 0x1F, 0x12, 0x07, 0x001F0001, PPC_SEGMENT_64B) { #if defined(CONFIG_USER_ONLY) - GEN_EXCP_PRIVREG(ctx); + gen_inval_exception(ctx, POWERPC_EXCP_PRIV_REG); #else TCGv t0; - if (unlikely(!ctx->supervisor)) { - GEN_EXCP_PRIVREG(ctx); + if (unlikely(!ctx->mem_idx)) { + gen_inval_exception(ctx, POWERPC_EXCP_PRIV_REG); return; } t0 = tcg_temp_new(); @@ -4340,15 +4291,15 @@ GEN_HANDLER2(mtsrin_64b, "mtsrin", 0x1F, 0x12, 0x07, 0x001F0001, #endif /* defined(TARGET_PPC64) */ /*** Lookaside buffer management ***/ -/* Optional & supervisor only: */ +/* Optional & mem_idx only: */ /* tlbia */ GEN_HANDLER(tlbia, 0x1F, 0x12, 0x0B, 0x03FFFC01, PPC_MEM_TLBIA) { #if defined(CONFIG_USER_ONLY) - GEN_EXCP_PRIVOPC(ctx); + gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC); #else - if (unlikely(!ctx->supervisor)) { - GEN_EXCP_PRIVOPC(ctx); + if (unlikely(!ctx->mem_idx)) { + gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC); return; } gen_helper_tlbia(); @@ -4359,10 +4310,10 @@ GEN_HANDLER(tlbia, 0x1F, 0x12, 0x0B, 0x03FFFC01, PPC_MEM_TLBIA) GEN_HANDLER(tlbie, 0x1F, 0x12, 0x09, 0x03FF0001, PPC_MEM_TLBIE) { #if defined(CONFIG_USER_ONLY) - GEN_EXCP_PRIVOPC(ctx); + gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC); #else - if (unlikely(!ctx->supervisor)) { - GEN_EXCP_PRIVOPC(ctx); + if (unlikely(!ctx->mem_idx)) { + gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC); return; } #if defined(TARGET_PPC64) @@ -4381,16 +4332,16 @@ GEN_HANDLER(tlbie, 0x1F, 0x12, 0x09, 0x03FF0001, PPC_MEM_TLBIE) GEN_HANDLER(tlbsync, 0x1F, 0x16, 0x11, 0x03FFF801, PPC_MEM_TLBSYNC) { #if defined(CONFIG_USER_ONLY) - GEN_EXCP_PRIVOPC(ctx); + gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC); #else - if (unlikely(!ctx->supervisor)) { - GEN_EXCP_PRIVOPC(ctx); + if (unlikely(!ctx->mem_idx)) { + gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC); return; } /* This has no effect: it should ensure that all previous * tlbie have completed */ - GEN_STOP(ctx); + gen_stop_exception(ctx); #endif } @@ -4399,10 +4350,10 @@ GEN_HANDLER(tlbsync, 0x1F, 0x16, 0x11, 0x03FFF801, PPC_MEM_TLBSYNC) GEN_HANDLER(slbia, 0x1F, 0x12, 0x0F, 0x03FFFC01, PPC_SLBI) { #if defined(CONFIG_USER_ONLY) - GEN_EXCP_PRIVOPC(ctx); + gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC); #else - if (unlikely(!ctx->supervisor)) { - GEN_EXCP_PRIVOPC(ctx); + if (unlikely(!ctx->mem_idx)) { + gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC); return; } gen_helper_slbia(); @@ -4413,10 +4364,10 @@ GEN_HANDLER(slbia, 0x1F, 0x12, 0x0F, 0x03FFFC01, PPC_SLBI) GEN_HANDLER(slbie, 0x1F, 0x12, 0x0D, 0x03FF0001, PPC_SLBI) { #if defined(CONFIG_USER_ONLY) - GEN_EXCP_PRIVOPC(ctx); + gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC); #else - if (unlikely(!ctx->supervisor)) { - GEN_EXCP_PRIVOPC(ctx); + if (unlikely(!ctx->mem_idx)) { + gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC); return; } gen_helper_slbie(cpu_gpr[rB(ctx->opcode)]); @@ -4429,24 +4380,26 @@ GEN_HANDLER(slbie, 0x1F, 0x12, 0x0D, 0x03FF0001, PPC_SLBI) /* eciwx */ GEN_HANDLER(eciwx, 0x1F, 0x16, 0x0D, 0x00000001, PPC_EXTERN) { + TCGv t0; /* Should check EAR[E] ! */ - TCGv t0 = tcg_temp_new(); - gen_set_access_type(ACCESS_RES); - gen_addr_reg_index(t0, ctx); + gen_set_access_type(ctx, ACCESS_EXT); + t0 = tcg_temp_new(); + gen_addr_reg_index(ctx, t0); gen_check_align(ctx, t0, 0x03); - gen_qemu_ld32u(cpu_gpr[rD(ctx->opcode)], t0, ctx->mem_idx); + gen_qemu_ld32u(ctx, cpu_gpr[rD(ctx->opcode)], t0); tcg_temp_free(t0); } /* ecowx */ GEN_HANDLER(ecowx, 0x1F, 0x16, 0x09, 0x00000001, PPC_EXTERN) { + TCGv t0; /* Should check EAR[E] ! */ - TCGv t0 = tcg_temp_new(); - gen_set_access_type(ACCESS_RES); - gen_addr_reg_index(t0, ctx); + gen_set_access_type(ctx, ACCESS_EXT); + t0 = tcg_temp_new(); + gen_addr_reg_index(ctx, t0); gen_check_align(ctx, t0, 0x03); - gen_qemu_st32(cpu_gpr[rD(ctx->opcode)], t0, ctx->mem_idx); + gen_qemu_st32(ctx, cpu_gpr[rD(ctx->opcode)], t0); tcg_temp_free(t0); } @@ -4597,7 +4550,7 @@ GEN_HANDLER(lscbx, 0x1F, 0x15, 0x08, 0x00000000, PPC_POWER_BR) TCGv_i32 t2 = tcg_const_i32(rA(ctx->opcode)); TCGv_i32 t3 = tcg_const_i32(rB(ctx->opcode)); - gen_addr_reg_index(t0, ctx); + gen_addr_reg_index(ctx, t0); /* NIP cannot be restored if the memory exception comes from an helper */ gen_update_nip(ctx, ctx->nip - 4); gen_helper_lscbx(t0, t0, t1, t2, t3); @@ -5095,24 +5048,24 @@ GEN_HANDLER(srq, 0x1F, 0x18, 0x14, 0x00000000, PPC_POWER_BR) GEN_HANDLER(dsa, 0x1F, 0x14, 0x13, 0x03FFF801, PPC_602_SPEC) { /* XXX: TODO */ - GEN_EXCP_INVAL(ctx); + gen_inval_exception(ctx, POWERPC_EXCP_INVAL_INVAL); } /* esa */ GEN_HANDLER(esa, 0x1F, 0x14, 0x12, 0x03FFF801, PPC_602_SPEC) { /* XXX: TODO */ - GEN_EXCP_INVAL(ctx); + gen_inval_exception(ctx, POWERPC_EXCP_INVAL_INVAL); } /* mfrom */ GEN_HANDLER(mfrom, 0x1F, 0x09, 0x08, 0x03E0F801, PPC_602_SPEC) { #if defined(CONFIG_USER_ONLY) - GEN_EXCP_PRIVOPC(ctx); + gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC); #else - if (unlikely(!ctx->supervisor)) { - GEN_EXCP_PRIVOPC(ctx); + if (unlikely(!ctx->mem_idx)) { + gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC); return; } gen_helper_602_mfrom(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rA(ctx->opcode)]); @@ -5124,10 +5077,10 @@ GEN_HANDLER(mfrom, 0x1F, 0x09, 0x08, 0x03E0F801, PPC_602_SPEC) GEN_HANDLER2(tlbld_6xx, "tlbld", 0x1F, 0x12, 0x1E, 0x03FF0001, PPC_6xx_TLB) { #if defined(CONFIG_USER_ONLY) - GEN_EXCP_PRIVOPC(ctx); + gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC); #else - if (unlikely(!ctx->supervisor)) { - GEN_EXCP_PRIVOPC(ctx); + if (unlikely(!ctx->mem_idx)) { + gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC); return; } gen_helper_6xx_tlbd(cpu_gpr[rB(ctx->opcode)]); @@ -5138,10 +5091,10 @@ GEN_HANDLER2(tlbld_6xx, "tlbld", 0x1F, 0x12, 0x1E, 0x03FF0001, PPC_6xx_TLB) GEN_HANDLER2(tlbli_6xx, "tlbli", 0x1F, 0x12, 0x1F, 0x03FF0001, PPC_6xx_TLB) { #if defined(CONFIG_USER_ONLY) - GEN_EXCP_PRIVOPC(ctx); + gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC); #else - if (unlikely(!ctx->supervisor)) { - GEN_EXCP_PRIVOPC(ctx); + if (unlikely(!ctx->mem_idx)) { + gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC); return; } gen_helper_6xx_tlbi(cpu_gpr[rB(ctx->opcode)]); @@ -5153,10 +5106,10 @@ GEN_HANDLER2(tlbli_6xx, "tlbli", 0x1F, 0x12, 0x1F, 0x03FF0001, PPC_6xx_TLB) GEN_HANDLER2(tlbld_74xx, "tlbld", 0x1F, 0x12, 0x1E, 0x03FF0001, PPC_74xx_TLB) { #if defined(CONFIG_USER_ONLY) - GEN_EXCP_PRIVOPC(ctx); + gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC); #else - if (unlikely(!ctx->supervisor)) { - GEN_EXCP_PRIVOPC(ctx); + if (unlikely(!ctx->mem_idx)) { + gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC); return; } gen_helper_74xx_tlbd(cpu_gpr[rB(ctx->opcode)]); @@ -5167,10 +5120,10 @@ GEN_HANDLER2(tlbld_74xx, "tlbld", 0x1F, 0x12, 0x1E, 0x03FF0001, PPC_74xx_TLB) GEN_HANDLER2(tlbli_74xx, "tlbli", 0x1F, 0x12, 0x1F, 0x03FF0001, PPC_74xx_TLB) { #if defined(CONFIG_USER_ONLY) - GEN_EXCP_PRIVOPC(ctx); + gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC); #else - if (unlikely(!ctx->supervisor)) { - GEN_EXCP_PRIVOPC(ctx); + if (unlikely(!ctx->mem_idx)) { + gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC); return; } gen_helper_74xx_tlbi(cpu_gpr[rB(ctx->opcode)]); @@ -5189,10 +5142,10 @@ GEN_HANDLER(cli, 0x1F, 0x16, 0x0F, 0x03E00000, PPC_POWER) { /* Cache line invalidate: privileged and treated as no-op */ #if defined(CONFIG_USER_ONLY) - GEN_EXCP_PRIVOPC(ctx); + gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC); #else - if (unlikely(!ctx->supervisor)) { - GEN_EXCP_PRIVOPC(ctx); + if (unlikely(!ctx->mem_idx)) { + gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC); return; } #endif @@ -5207,17 +5160,17 @@ GEN_HANDLER(dclst, 0x1F, 0x16, 0x13, 0x03E00000, PPC_POWER) GEN_HANDLER(mfsri, 0x1F, 0x13, 0x13, 0x00000001, PPC_POWER) { #if defined(CONFIG_USER_ONLY) - GEN_EXCP_PRIVOPC(ctx); + gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC); #else int ra = rA(ctx->opcode); int rd = rD(ctx->opcode); TCGv t0; - if (unlikely(!ctx->supervisor)) { - GEN_EXCP_PRIVOPC(ctx); + if (unlikely(!ctx->mem_idx)) { + gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC); return; } t0 = tcg_temp_new(); - gen_addr_reg_index(t0, ctx); + gen_addr_reg_index(ctx, t0); tcg_gen_shri_tl(t0, t0, 28); tcg_gen_andi_tl(t0, t0, 0xF); gen_helper_load_sr(cpu_gpr[rd], t0); @@ -5230,15 +5183,15 @@ GEN_HANDLER(mfsri, 0x1F, 0x13, 0x13, 0x00000001, PPC_POWER) GEN_HANDLER(rac, 0x1F, 0x12, 0x19, 0x00000001, PPC_POWER) { #if defined(CONFIG_USER_ONLY) - GEN_EXCP_PRIVOPC(ctx); + gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC); #else TCGv t0; - if (unlikely(!ctx->supervisor)) { - GEN_EXCP_PRIVOPC(ctx); + if (unlikely(!ctx->mem_idx)) { + gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC); return; } t0 = tcg_temp_new(); - gen_addr_reg_index(t0, ctx); + gen_addr_reg_index(ctx, t0); gen_helper_rac(cpu_gpr[rD(ctx->opcode)], t0); tcg_temp_free(t0); #endif @@ -5247,14 +5200,14 @@ GEN_HANDLER(rac, 0x1F, 0x12, 0x19, 0x00000001, PPC_POWER) GEN_HANDLER(rfsvc, 0x13, 0x12, 0x02, 0x03FFF0001, PPC_POWER) { #if defined(CONFIG_USER_ONLY) - GEN_EXCP_PRIVOPC(ctx); + gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC); #else - if (unlikely(!ctx->supervisor)) { - GEN_EXCP_PRIVOPC(ctx); + if (unlikely(!ctx->mem_idx)) { + gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC); return; } gen_helper_rfsvc(); - GEN_SYNC(ctx); + gen_sync_exception(ctx); #endif } @@ -5267,11 +5220,13 @@ GEN_HANDLER(rfsvc, 0x13, 0x12, 0x02, 0x03FFF0001, PPC_POWER) GEN_HANDLER(lfq, 0x38, 0xFF, 0xFF, 0x00000003, PPC_POWER2) { int rd = rD(ctx->opcode); - TCGv t0 = tcg_temp_new(); - gen_addr_imm_index(t0, ctx, 0); - gen_qemu_ld64(cpu_fpr[rd], t0, ctx->mem_idx); - tcg_gen_addi_tl(t0, t0, 8); - gen_qemu_ld64(cpu_fpr[(rd + 1) % 32], t0, ctx->mem_idx); + TCGv t0; + gen_set_access_type(ctx, ACCESS_FLOAT); + t0 = tcg_temp_new(); + gen_addr_imm_index(ctx, t0, 0); + gen_qemu_ld64(ctx, cpu_fpr[rd], t0); + gen_addr_add(ctx, t0, t0, 8); + gen_qemu_ld64(ctx, cpu_fpr[(rd + 1) % 32], t0); tcg_temp_free(t0); } @@ -5280,12 +5235,14 @@ GEN_HANDLER(lfqu, 0x39, 0xFF, 0xFF, 0x00000003, PPC_POWER2) { int ra = rA(ctx->opcode); int rd = rD(ctx->opcode); - TCGv t0 = tcg_temp_new(); - TCGv t1 = tcg_temp_new(); - gen_addr_imm_index(t0, ctx, 0); - gen_qemu_ld64(cpu_fpr[rd], t0, ctx->mem_idx); - tcg_gen_addi_tl(t1, t0, 8); - gen_qemu_ld64(cpu_fpr[(rd + 1) % 32], t1, ctx->mem_idx); + TCGv t0, t1; + gen_set_access_type(ctx, ACCESS_FLOAT); + t0 = tcg_temp_new(); + t1 = tcg_temp_new(); + gen_addr_imm_index(ctx, t0, 0); + gen_qemu_ld64(ctx, cpu_fpr[rd], t0); + gen_addr_add(ctx, t1, t0, 8); + gen_qemu_ld64(ctx, cpu_fpr[(rd + 1) % 32], t1); if (ra != 0) tcg_gen_mov_tl(cpu_gpr[ra], t0); tcg_temp_free(t0); @@ -5297,27 +5254,31 @@ GEN_HANDLER(lfqux, 0x1F, 0x17, 0x19, 0x00000001, PPC_POWER2) { int ra = rA(ctx->opcode); int rd = rD(ctx->opcode); - TCGv t0 = tcg_temp_new(); - TCGv t1 = tcg_temp_new(); - gen_addr_reg_index(t0, ctx); - gen_qemu_ld64(cpu_fpr[rd], t0, ctx->mem_idx); - tcg_gen_addi_tl(t1, t0, 8); - gen_qemu_ld64(cpu_fpr[(rd + 1) % 32], t1, ctx->mem_idx); + gen_set_access_type(ctx, ACCESS_FLOAT); + TCGv t0, t1; + t0 = tcg_temp_new(); + gen_addr_reg_index(ctx, t0); + gen_qemu_ld64(ctx, cpu_fpr[rd], t0); + t1 = tcg_temp_new(); + gen_addr_add(ctx, t1, t0, 8); + gen_qemu_ld64(ctx, cpu_fpr[(rd + 1) % 32], t1); + tcg_temp_free(t1); if (ra != 0) tcg_gen_mov_tl(cpu_gpr[ra], t0); tcg_temp_free(t0); - tcg_temp_free(t1); } /* lfqx */ GEN_HANDLER(lfqx, 0x1F, 0x17, 0x18, 0x00000001, PPC_POWER2) { int rd = rD(ctx->opcode); - TCGv t0 = tcg_temp_new(); - gen_addr_reg_index(t0, ctx); - gen_qemu_ld64(cpu_fpr[rd], t0, ctx->mem_idx); - tcg_gen_addi_tl(t0, t0, 8); - gen_qemu_ld64(cpu_fpr[(rd + 1) % 32], t0, ctx->mem_idx); + TCGv t0; + gen_set_access_type(ctx, ACCESS_FLOAT); + t0 = tcg_temp_new(); + gen_addr_reg_index(ctx, t0); + gen_qemu_ld64(ctx, cpu_fpr[rd], t0); + gen_addr_add(ctx, t0, t0, 8); + gen_qemu_ld64(ctx, cpu_fpr[(rd + 1) % 32], t0); tcg_temp_free(t0); } @@ -5325,11 +5286,13 @@ GEN_HANDLER(lfqx, 0x1F, 0x17, 0x18, 0x00000001, PPC_POWER2) GEN_HANDLER(stfq, 0x3C, 0xFF, 0xFF, 0x00000003, PPC_POWER2) { int rd = rD(ctx->opcode); - TCGv t0 = tcg_temp_new(); - gen_addr_imm_index(t0, ctx, 0); - gen_qemu_st64(cpu_fpr[rd], t0, ctx->mem_idx); - tcg_gen_addi_tl(t0, t0, 8); - gen_qemu_st64(cpu_fpr[(rd + 1) % 32], t0, ctx->mem_idx); + TCGv t0; + gen_set_access_type(ctx, ACCESS_FLOAT); + t0 = tcg_temp_new(); + gen_addr_imm_index(ctx, t0, 0); + gen_qemu_st64(ctx, cpu_fpr[rd], t0); + gen_addr_add(ctx, t0, t0, 8); + gen_qemu_st64(ctx, cpu_fpr[(rd + 1) % 32], t0); tcg_temp_free(t0); } @@ -5338,16 +5301,18 @@ GEN_HANDLER(stfqu, 0x3D, 0xFF, 0xFF, 0x00000003, PPC_POWER2) { int ra = rA(ctx->opcode); int rd = rD(ctx->opcode); - TCGv t0 = tcg_temp_new(); - TCGv t1 = tcg_temp_new(); - gen_addr_imm_index(t0, ctx, 0); - gen_qemu_st64(cpu_fpr[rd], t0, ctx->mem_idx); - tcg_gen_addi_tl(t1, t0, 8); - gen_qemu_st64(cpu_fpr[(rd + 1) % 32], t1, ctx->mem_idx); + TCGv t0, t1; + gen_set_access_type(ctx, ACCESS_FLOAT); + t0 = tcg_temp_new(); + gen_addr_imm_index(ctx, t0, 0); + gen_qemu_st64(ctx, cpu_fpr[rd], t0); + t1 = tcg_temp_new(); + gen_addr_add(ctx, t1, t0, 8); + gen_qemu_st64(ctx, cpu_fpr[(rd + 1) % 32], t1); + tcg_temp_free(t1); if (ra != 0) tcg_gen_mov_tl(cpu_gpr[ra], t0); tcg_temp_free(t0); - tcg_temp_free(t1); } /* stfqux */ @@ -5355,27 +5320,31 @@ GEN_HANDLER(stfqux, 0x1F, 0x17, 0x1D, 0x00000001, PPC_POWER2) { int ra = rA(ctx->opcode); int rd = rD(ctx->opcode); - TCGv t0 = tcg_temp_new(); - TCGv t1 = tcg_temp_new(); - gen_addr_reg_index(t0, ctx); - gen_qemu_st64(cpu_fpr[rd], t0, ctx->mem_idx); - tcg_gen_addi_tl(t1, t0, 8); - gen_qemu_st64(cpu_fpr[(rd + 1) % 32], t1, ctx->mem_idx); + TCGv t0, t1; + gen_set_access_type(ctx, ACCESS_FLOAT); + t0 = tcg_temp_new(); + gen_addr_reg_index(ctx, t0); + gen_qemu_st64(ctx, cpu_fpr[rd], t0); + t1 = tcg_temp_new(); + gen_addr_add(ctx, t1, t0, 8); + gen_qemu_st64(ctx, cpu_fpr[(rd + 1) % 32], t1); + tcg_temp_free(t1); if (ra != 0) tcg_gen_mov_tl(cpu_gpr[ra], t0); tcg_temp_free(t0); - tcg_temp_free(t1); } /* stfqx */ GEN_HANDLER(stfqx, 0x1F, 0x17, 0x1C, 0x00000001, PPC_POWER2) { int rd = rD(ctx->opcode); - TCGv t0 = tcg_temp_new(); - gen_addr_reg_index(t0, ctx); - gen_qemu_st64(cpu_fpr[rd], t0, ctx->mem_idx); - tcg_gen_addi_tl(t0, t0, 8); - gen_qemu_st64(cpu_fpr[(rd + 1) % 32], t0, ctx->mem_idx); + TCGv t0; + gen_set_access_type(ctx, ACCESS_FLOAT); + t0 = tcg_temp_new(); + gen_addr_reg_index(ctx, t0); + gen_qemu_st64(ctx, cpu_fpr[rd], t0); + gen_addr_add(ctx, t0, t0, 8); + gen_qemu_st64(ctx, cpu_fpr[(rd + 1) % 32], t0); tcg_temp_free(t0); } @@ -5384,25 +5353,22 @@ GEN_HANDLER(stfqx, 0x1F, 0x17, 0x1C, 0x00000001, PPC_POWER2) GEN_HANDLER(mfapidi, 0x1F, 0x13, 0x08, 0x0000F801, PPC_MFAPIDI) { /* XXX: TODO */ - GEN_EXCP_INVAL(ctx); + gen_inval_exception(ctx, POWERPC_EXCP_INVAL_INVAL); } /* XXX: not implemented on 440 ? */ GEN_HANDLER(tlbiva, 0x1F, 0x12, 0x18, 0x03FFF801, PPC_TLBIVA) { #if defined(CONFIG_USER_ONLY) - GEN_EXCP_PRIVOPC(ctx); + gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC); #else TCGv t0; - if (unlikely(!ctx->supervisor)) { - GEN_EXCP_PRIVOPC(ctx); + if (unlikely(!ctx->mem_idx)) { + gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC); return; } - gen_addr_reg_index(t0, ctx); -#if defined(TARGET_PPC64) - if (!ctx->sf_mode) - tcg_gen_ext32u_tl(t0, t0); -#endif + t0 = tcg_temp_new(); + gen_addr_reg_index(ctx, t0); gen_helper_tlbie(cpu_gpr[rB(ctx->opcode)]); tcg_temp_free(t0); #endif @@ -5627,11 +5593,11 @@ GEN_MAC_HANDLER(mullhwu, 0x08, 0x0C); GEN_HANDLER(mfdcr, 0x1F, 0x03, 0x0A, 0x00000001, PPC_DCR) { #if defined(CONFIG_USER_ONLY) - GEN_EXCP_PRIVREG(ctx); + gen_inval_exception(ctx, POWERPC_EXCP_PRIV_REG); #else TCGv dcrn; - if (unlikely(!ctx->supervisor)) { - GEN_EXCP_PRIVREG(ctx); + if (unlikely(!ctx->mem_idx)) { + gen_inval_exception(ctx, POWERPC_EXCP_PRIV_REG); return; } /* NIP cannot be restored if the memory exception comes from an helper */ @@ -5646,11 +5612,11 @@ GEN_HANDLER(mfdcr, 0x1F, 0x03, 0x0A, 0x00000001, PPC_DCR) GEN_HANDLER(mtdcr, 0x1F, 0x03, 0x0E, 0x00000001, PPC_DCR) { #if defined(CONFIG_USER_ONLY) - GEN_EXCP_PRIVREG(ctx); + gen_inval_exception(ctx, POWERPC_EXCP_PRIV_REG); #else TCGv dcrn; - if (unlikely(!ctx->supervisor)) { - GEN_EXCP_PRIVREG(ctx); + if (unlikely(!ctx->mem_idx)) { + gen_inval_exception(ctx, POWERPC_EXCP_PRIV_REG); return; } /* NIP cannot be restored if the memory exception comes from an helper */ @@ -5666,10 +5632,10 @@ GEN_HANDLER(mtdcr, 0x1F, 0x03, 0x0E, 0x00000001, PPC_DCR) GEN_HANDLER(mfdcrx, 0x1F, 0x03, 0x08, 0x00000000, PPC_DCRX) { #if defined(CONFIG_USER_ONLY) - GEN_EXCP_PRIVREG(ctx); + gen_inval_exception(ctx, POWERPC_EXCP_PRIV_REG); #else - if (unlikely(!ctx->supervisor)) { - GEN_EXCP_PRIVREG(ctx); + if (unlikely(!ctx->mem_idx)) { + gen_inval_exception(ctx, POWERPC_EXCP_PRIV_REG); return; } /* NIP cannot be restored if the memory exception comes from an helper */ @@ -5684,10 +5650,10 @@ GEN_HANDLER(mfdcrx, 0x1F, 0x03, 0x08, 0x00000000, PPC_DCRX) GEN_HANDLER(mtdcrx, 0x1F, 0x03, 0x0C, 0x00000000, PPC_DCRX) { #if defined(CONFIG_USER_ONLY) - GEN_EXCP_PRIVREG(ctx); + gen_inval_exception(ctx, POWERPC_EXCP_PRIV_REG); #else - if (unlikely(!ctx->supervisor)) { - GEN_EXCP_PRIVREG(ctx); + if (unlikely(!ctx->mem_idx)) { + gen_inval_exception(ctx, POWERPC_EXCP_PRIV_REG); return; } /* NIP cannot be restored if the memory exception comes from an helper */ @@ -5719,10 +5685,10 @@ GEN_HANDLER(mtdcrux, 0x1F, 0x03, 0x0D, 0x00000000, PPC_DCRUX) GEN_HANDLER(dccci, 0x1F, 0x06, 0x0E, 0x03E00001, PPC_4xx_COMMON) { #if defined(CONFIG_USER_ONLY) - GEN_EXCP_PRIVOPC(ctx); + gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC); #else - if (unlikely(!ctx->supervisor)) { - GEN_EXCP_PRIVOPC(ctx); + if (unlikely(!ctx->mem_idx)) { + gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC); return; } /* interpreted as no-op */ @@ -5733,18 +5699,18 @@ GEN_HANDLER(dccci, 0x1F, 0x06, 0x0E, 0x03E00001, PPC_4xx_COMMON) GEN_HANDLER(dcread, 0x1F, 0x06, 0x0F, 0x00000001, PPC_4xx_COMMON) { #if defined(CONFIG_USER_ONLY) - GEN_EXCP_PRIVOPC(ctx); + gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC); #else TCGv EA, val; - if (unlikely(!ctx->supervisor)) { - GEN_EXCP_PRIVOPC(ctx); + if (unlikely(!ctx->mem_idx)) { + gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC); return; } + gen_set_access_type(ctx, ACCESS_CACHE); EA = tcg_temp_new(); - gen_set_access_type(ACCESS_CACHE); - gen_addr_reg_index(EA, ctx); + gen_addr_reg_index(ctx, EA); val = tcg_temp_new(); - gen_qemu_ld32u(val, EA, ctx->mem_idx); + gen_qemu_ld32u(ctx, val, EA); tcg_temp_free(val); tcg_gen_mov_tl(cpu_gpr[rD(ctx->opcode)], EA); tcg_temp_free(EA); @@ -5764,10 +5730,10 @@ GEN_HANDLER2(icbt_40x, "icbt", 0x1F, 0x06, 0x08, 0x03E00001, PPC_40x_ICBT) GEN_HANDLER(iccci, 0x1F, 0x06, 0x1E, 0x00000001, PPC_4xx_COMMON) { #if defined(CONFIG_USER_ONLY) - GEN_EXCP_PRIVOPC(ctx); + gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC); #else - if (unlikely(!ctx->supervisor)) { - GEN_EXCP_PRIVOPC(ctx); + if (unlikely(!ctx->mem_idx)) { + gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC); return; } /* interpreted as no-op */ @@ -5778,44 +5744,44 @@ GEN_HANDLER(iccci, 0x1F, 0x06, 0x1E, 0x00000001, PPC_4xx_COMMON) GEN_HANDLER(icread, 0x1F, 0x06, 0x1F, 0x03E00001, PPC_4xx_COMMON) { #if defined(CONFIG_USER_ONLY) - GEN_EXCP_PRIVOPC(ctx); + gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC); #else - if (unlikely(!ctx->supervisor)) { - GEN_EXCP_PRIVOPC(ctx); + if (unlikely(!ctx->mem_idx)) { + gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC); return; } /* interpreted as no-op */ #endif } -/* rfci (supervisor only) */ +/* rfci (mem_idx only) */ GEN_HANDLER2(rfci_40x, "rfci", 0x13, 0x13, 0x01, 0x03FF8001, PPC_40x_EXCP) { #if defined(CONFIG_USER_ONLY) - GEN_EXCP_PRIVOPC(ctx); + gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC); #else - if (unlikely(!ctx->supervisor)) { - GEN_EXCP_PRIVOPC(ctx); + if (unlikely(!ctx->mem_idx)) { + gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC); return; } /* Restore CPU state */ gen_helper_40x_rfci(); - GEN_SYNC(ctx); + gen_sync_exception(ctx); #endif } GEN_HANDLER(rfci, 0x13, 0x13, 0x01, 0x03FF8001, PPC_BOOKE) { #if defined(CONFIG_USER_ONLY) - GEN_EXCP_PRIVOPC(ctx); + gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC); #else - if (unlikely(!ctx->supervisor)) { - GEN_EXCP_PRIVOPC(ctx); + if (unlikely(!ctx->mem_idx)) { + gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC); return; } /* Restore CPU state */ gen_helper_rfci(); - GEN_SYNC(ctx); + gen_sync_exception(ctx); #endif } @@ -5824,15 +5790,15 @@ GEN_HANDLER(rfci, 0x13, 0x13, 0x01, 0x03FF8001, PPC_BOOKE) GEN_HANDLER(rfdi, 0x13, 0x07, 0x01, 0x03FF8001, PPC_RFDI) { #if defined(CONFIG_USER_ONLY) - GEN_EXCP_PRIVOPC(ctx); + gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC); #else - if (unlikely(!ctx->supervisor)) { - GEN_EXCP_PRIVOPC(ctx); + if (unlikely(!ctx->mem_idx)) { + gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC); return; } /* Restore CPU state */ gen_helper_rfdi(); - GEN_SYNC(ctx); + gen_sync_exception(ctx); #endif } @@ -5840,15 +5806,15 @@ GEN_HANDLER(rfdi, 0x13, 0x07, 0x01, 0x03FF8001, PPC_RFDI) GEN_HANDLER(rfmci, 0x13, 0x06, 0x01, 0x03FF8001, PPC_RFMCI) { #if defined(CONFIG_USER_ONLY) - GEN_EXCP_PRIVOPC(ctx); + gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC); #else - if (unlikely(!ctx->supervisor)) { - GEN_EXCP_PRIVOPC(ctx); + if (unlikely(!ctx->mem_idx)) { + gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC); return; } /* Restore CPU state */ gen_helper_rfmci(); - GEN_SYNC(ctx); + gen_sync_exception(ctx); #endif } @@ -5857,10 +5823,10 @@ GEN_HANDLER(rfmci, 0x13, 0x06, 0x01, 0x03FF8001, PPC_RFMCI) GEN_HANDLER2(tlbre_40x, "tlbre", 0x1F, 0x12, 0x1D, 0x00000001, PPC_40x_TLB) { #if defined(CONFIG_USER_ONLY) - GEN_EXCP_PRIVOPC(ctx); + gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC); #else - if (unlikely(!ctx->supervisor)) { - GEN_EXCP_PRIVOPC(ctx); + if (unlikely(!ctx->mem_idx)) { + gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC); return; } switch (rB(ctx->opcode)) { @@ -5871,7 +5837,7 @@ GEN_HANDLER2(tlbre_40x, "tlbre", 0x1F, 0x12, 0x1D, 0x00000001, PPC_40x_TLB) gen_helper_4xx_tlbre_lo(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rA(ctx->opcode)]); break; default: - GEN_EXCP_INVAL(ctx); + gen_inval_exception(ctx, POWERPC_EXCP_INVAL_INVAL); break; } #endif @@ -5881,15 +5847,15 @@ GEN_HANDLER2(tlbre_40x, "tlbre", 0x1F, 0x12, 0x1D, 0x00000001, PPC_40x_TLB) GEN_HANDLER2(tlbsx_40x, "tlbsx", 0x1F, 0x12, 0x1C, 0x00000000, PPC_40x_TLB) { #if defined(CONFIG_USER_ONLY) - GEN_EXCP_PRIVOPC(ctx); + gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC); #else TCGv t0; - if (unlikely(!ctx->supervisor)) { - GEN_EXCP_PRIVOPC(ctx); + if (unlikely(!ctx->mem_idx)) { + gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC); return; } t0 = tcg_temp_new(); - gen_addr_reg_index(t0, ctx); + gen_addr_reg_index(ctx, t0); gen_helper_4xx_tlbsx(cpu_gpr[rD(ctx->opcode)], t0); tcg_temp_free(t0); if (Rc(ctx->opcode)) { @@ -5908,10 +5874,10 @@ GEN_HANDLER2(tlbsx_40x, "tlbsx", 0x1F, 0x12, 0x1C, 0x00000000, PPC_40x_TLB) GEN_HANDLER2(tlbwe_40x, "tlbwe", 0x1F, 0x12, 0x1E, 0x00000001, PPC_40x_TLB) { #if defined(CONFIG_USER_ONLY) - GEN_EXCP_PRIVOPC(ctx); + gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC); #else - if (unlikely(!ctx->supervisor)) { - GEN_EXCP_PRIVOPC(ctx); + if (unlikely(!ctx->mem_idx)) { + gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC); return; } switch (rB(ctx->opcode)) { @@ -5922,7 +5888,7 @@ GEN_HANDLER2(tlbwe_40x, "tlbwe", 0x1F, 0x12, 0x1E, 0x00000001, PPC_40x_TLB) gen_helper_4xx_tlbwe_lo(cpu_gpr[rA(ctx->opcode)], cpu_gpr[rS(ctx->opcode)]); break; default: - GEN_EXCP_INVAL(ctx); + gen_inval_exception(ctx, POWERPC_EXCP_INVAL_INVAL); break; } #endif @@ -5933,10 +5899,10 @@ GEN_HANDLER2(tlbwe_40x, "tlbwe", 0x1F, 0x12, 0x1E, 0x00000001, PPC_40x_TLB) GEN_HANDLER2(tlbre_440, "tlbre", 0x1F, 0x12, 0x1D, 0x00000001, PPC_BOOKE) { #if defined(CONFIG_USER_ONLY) - GEN_EXCP_PRIVOPC(ctx); + gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC); #else - if (unlikely(!ctx->supervisor)) { - GEN_EXCP_PRIVOPC(ctx); + if (unlikely(!ctx->mem_idx)) { + gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC); return; } switch (rB(ctx->opcode)) { @@ -5950,7 +5916,7 @@ GEN_HANDLER2(tlbre_440, "tlbre", 0x1F, 0x12, 0x1D, 0x00000001, PPC_BOOKE) } break; default: - GEN_EXCP_INVAL(ctx); + gen_inval_exception(ctx, POWERPC_EXCP_INVAL_INVAL); break; } #endif @@ -5960,15 +5926,15 @@ GEN_HANDLER2(tlbre_440, "tlbre", 0x1F, 0x12, 0x1D, 0x00000001, PPC_BOOKE) GEN_HANDLER2(tlbsx_440, "tlbsx", 0x1F, 0x12, 0x1C, 0x00000000, PPC_BOOKE) { #if defined(CONFIG_USER_ONLY) - GEN_EXCP_PRIVOPC(ctx); + gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC); #else TCGv t0; - if (unlikely(!ctx->supervisor)) { - GEN_EXCP_PRIVOPC(ctx); + if (unlikely(!ctx->mem_idx)) { + gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC); return; } t0 = tcg_temp_new(); - gen_addr_reg_index(t0, ctx); + gen_addr_reg_index(ctx, t0); gen_helper_440_tlbsx(cpu_gpr[rD(ctx->opcode)], t0); tcg_temp_free(t0); if (Rc(ctx->opcode)) { @@ -5987,10 +5953,10 @@ GEN_HANDLER2(tlbsx_440, "tlbsx", 0x1F, 0x12, 0x1C, 0x00000000, PPC_BOOKE) GEN_HANDLER2(tlbwe_440, "tlbwe", 0x1F, 0x12, 0x1E, 0x00000001, PPC_BOOKE) { #if defined(CONFIG_USER_ONLY) - GEN_EXCP_PRIVOPC(ctx); + gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC); #else - if (unlikely(!ctx->supervisor)) { - GEN_EXCP_PRIVOPC(ctx); + if (unlikely(!ctx->mem_idx)) { + gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC); return; } switch (rB(ctx->opcode)) { @@ -6004,7 +5970,7 @@ GEN_HANDLER2(tlbwe_440, "tlbwe", 0x1F, 0x12, 0x1E, 0x00000001, PPC_BOOKE) } break; default: - GEN_EXCP_INVAL(ctx); + gen_inval_exception(ctx, POWERPC_EXCP_INVAL_INVAL); break; } #endif @@ -6014,11 +5980,11 @@ GEN_HANDLER2(tlbwe_440, "tlbwe", 0x1F, 0x12, 0x1E, 0x00000001, PPC_BOOKE) GEN_HANDLER(wrtee, 0x1F, 0x03, 0x04, 0x000FFC01, PPC_WRTEE) { #if defined(CONFIG_USER_ONLY) - GEN_EXCP_PRIVOPC(ctx); + gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC); #else TCGv t0; - if (unlikely(!ctx->supervisor)) { - GEN_EXCP_PRIVOPC(ctx); + if (unlikely(!ctx->mem_idx)) { + gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC); return; } t0 = tcg_temp_new(); @@ -6029,7 +5995,7 @@ GEN_HANDLER(wrtee, 0x1F, 0x03, 0x04, 0x000FFC01, PPC_WRTEE) /* Stop translation to have a chance to raise an exception * if we just set msr_ee to 1 */ - GEN_STOP(ctx); + gen_stop_exception(ctx); #endif } @@ -6037,16 +6003,16 @@ GEN_HANDLER(wrtee, 0x1F, 0x03, 0x04, 0x000FFC01, PPC_WRTEE) GEN_HANDLER(wrteei, 0x1F, 0x03, 0x05, 0x000EFC01, PPC_WRTEE) { #if defined(CONFIG_USER_ONLY) - GEN_EXCP_PRIVOPC(ctx); + gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC); #else - if (unlikely(!ctx->supervisor)) { - GEN_EXCP_PRIVOPC(ctx); + if (unlikely(!ctx->mem_idx)) { + gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC); return; } if (ctx->opcode & 0x00010000) { tcg_gen_ori_tl(cpu_msr, cpu_msr, (1 << MSR_EE)); /* Stop translation to have a chance to raise an exception */ - GEN_STOP(ctx); + gen_stop_exception(ctx); } else { tcg_gen_andi_tl(cpu_msr, cpu_msr, (1 << MSR_EE)); } @@ -6064,7 +6030,7 @@ GEN_HANDLER(dlmzb, 0x1F, 0x0E, 0x02, 0x00000000, PPC_440_SPEC) } /* mbar replaces eieio on 440 */ -GEN_HANDLER(mbar, 0x1F, 0x16, 0x13, 0x001FF801, PPC_BOOKE) +GEN_HANDLER(mbar, 0x1F, 0x16, 0x1a, 0x001FF801, PPC_BOOKE) { /* interpreted as no-op */ } @@ -6092,20 +6058,21 @@ GEN_HANDLER(name, 0x1F, opc2, opc3, 0x00000001, PPC_ALTIVEC) \ { \ TCGv EA; \ if (unlikely(!ctx->altivec_enabled)) { \ - GEN_EXCP_NO_VR(ctx); \ + gen_exception(ctx, POWERPC_EXCP_VPU); \ return; \ } \ + gen_set_access_type(ctx, ACCESS_INT); \ EA = tcg_temp_new(); \ - gen_addr_reg_index(EA, ctx); \ + gen_addr_reg_index(ctx, EA); \ tcg_gen_andi_tl(EA, EA, ~0xf); \ - if (ctx->mem_idx & 1) { \ - gen_qemu_ld64(cpu_avrl[rD(ctx->opcode)], EA, ctx->mem_idx); \ + if (ctx->le_mode) { \ + gen_qemu_ld64(ctx, cpu_avrl[rD(ctx->opcode)], EA); \ tcg_gen_addi_tl(EA, EA, 8); \ - gen_qemu_ld64(cpu_avrh[rD(ctx->opcode)], EA, ctx->mem_idx); \ + gen_qemu_ld64(ctx, cpu_avrh[rD(ctx->opcode)], EA); \ } else { \ - gen_qemu_ld64(cpu_avrh[rD(ctx->opcode)], EA, ctx->mem_idx); \ + gen_qemu_ld64(ctx, cpu_avrh[rD(ctx->opcode)], EA); \ tcg_gen_addi_tl(EA, EA, 8); \ - gen_qemu_ld64(cpu_avrl[rD(ctx->opcode)], EA, ctx->mem_idx); \ + gen_qemu_ld64(ctx, cpu_avrl[rD(ctx->opcode)], EA); \ } \ tcg_temp_free(EA); \ } @@ -6115,20 +6082,21 @@ GEN_HANDLER(st##name, 0x1F, opc2, opc3, 0x00000001, PPC_ALTIVEC) \ { \ TCGv EA; \ if (unlikely(!ctx->altivec_enabled)) { \ - GEN_EXCP_NO_VR(ctx); \ + gen_exception(ctx, POWERPC_EXCP_VPU); \ return; \ } \ + gen_set_access_type(ctx, ACCESS_INT); \ EA = tcg_temp_new(); \ - gen_addr_reg_index(EA, ctx); \ + gen_addr_reg_index(ctx, EA); \ tcg_gen_andi_tl(EA, EA, ~0xf); \ - if (ctx->mem_idx & 1) { \ - gen_qemu_st64(cpu_avrl[rD(ctx->opcode)], EA, ctx->mem_idx); \ + if (ctx->le_mode) { \ + gen_qemu_st64(ctx, cpu_avrl[rD(ctx->opcode)], EA); \ tcg_gen_addi_tl(EA, EA, 8); \ - gen_qemu_st64(cpu_avrh[rD(ctx->opcode)], EA, ctx->mem_idx); \ + gen_qemu_st64(ctx, cpu_avrh[rD(ctx->opcode)], EA); \ } else { \ - gen_qemu_st64(cpu_avrh[rD(ctx->opcode)], EA, ctx->mem_idx); \ + gen_qemu_st64(ctx, cpu_avrh[rD(ctx->opcode)], EA); \ tcg_gen_addi_tl(EA, EA, 8); \ - gen_qemu_st64(cpu_avrl[rD(ctx->opcode)], EA, ctx->mem_idx); \ + gen_qemu_st64(ctx, cpu_avrl[rD(ctx->opcode)], EA); \ } \ tcg_temp_free(EA); \ } @@ -6176,7 +6144,7 @@ GEN_HANDLER(name0##_##name1, 0x04, opc2, opc3, inval, type) \ /* Handler for undefined SPE opcodes */ static always_inline void gen_speundef (DisasContext *ctx) { - GEN_EXCP_INVAL(ctx); + gen_inval_exception(ctx, POWERPC_EXCP_INVAL_INVAL); } /* SPE logic */ @@ -6185,7 +6153,7 @@ static always_inline void gen_speundef (DisasContext *ctx) static always_inline void gen_##name (DisasContext *ctx) \ { \ if (unlikely(!ctx->spe_enabled)) { \ - GEN_EXCP_NO_AP(ctx); \ + gen_exception(ctx, POWERPC_EXCP_APU); \ return; \ } \ tcg_op(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rA(ctx->opcode)], \ @@ -6196,7 +6164,7 @@ static always_inline void gen_##name (DisasContext *ctx) \ static always_inline void gen_##name (DisasContext *ctx) \ { \ if (unlikely(!ctx->spe_enabled)) { \ - GEN_EXCP_NO_AP(ctx); \ + gen_exception(ctx, POWERPC_EXCP_APU); \ return; \ } \ tcg_op(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rA(ctx->opcode)], \ @@ -6221,7 +6189,7 @@ GEN_SPEOP_LOGIC2(evnand, tcg_gen_nand_tl); static always_inline void gen_##name (DisasContext *ctx) \ { \ if (unlikely(!ctx->spe_enabled)) { \ - GEN_EXCP_NO_AP(ctx); \ + gen_exception(ctx, POWERPC_EXCP_APU); \ return; \ } \ TCGv_i32 t0 = tcg_temp_local_new_i32(); \ @@ -6242,7 +6210,7 @@ static always_inline void gen_##name (DisasContext *ctx) \ static always_inline void gen_##name (DisasContext *ctx) \ { \ if (unlikely(!ctx->spe_enabled)) { \ - GEN_EXCP_NO_AP(ctx); \ + gen_exception(ctx, POWERPC_EXCP_APU); \ return; \ } \ tcg_opi(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rA(ctx->opcode)], \ @@ -6262,7 +6230,7 @@ GEN_SPEOP_TCG_LOGIC_IMM2(evrlwi, tcg_gen_rotli_i32); static always_inline void gen_##name (DisasContext *ctx) \ { \ if (unlikely(!ctx->spe_enabled)) { \ - GEN_EXCP_NO_AP(ctx); \ + gen_exception(ctx, POWERPC_EXCP_APU); \ return; \ } \ TCGv_i32 t0 = tcg_temp_local_new_i32(); \ @@ -6283,7 +6251,7 @@ static always_inline void gen_##name (DisasContext *ctx) \ static always_inline void gen_##name (DisasContext *ctx) \ { \ if (unlikely(!ctx->spe_enabled)) { \ - GEN_EXCP_NO_AP(ctx); \ + gen_exception(ctx, POWERPC_EXCP_APU); \ return; \ } \ tcg_op(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rA(ctx->opcode)]); \ @@ -6321,7 +6289,7 @@ GEN_SPEOP_ARITH1(evcntlzw, gen_helper_cntlzw32); static always_inline void gen_##name (DisasContext *ctx) \ { \ if (unlikely(!ctx->spe_enabled)) { \ - GEN_EXCP_NO_AP(ctx); \ + gen_exception(ctx, POWERPC_EXCP_APU); \ return; \ } \ TCGv_i32 t0 = tcg_temp_local_new_i32(); \ @@ -6347,7 +6315,7 @@ static always_inline void gen_##name (DisasContext *ctx) \ static always_inline void gen_##name (DisasContext *ctx) \ { \ if (unlikely(!ctx->spe_enabled)) { \ - GEN_EXCP_NO_AP(ctx); \ + gen_exception(ctx, POWERPC_EXCP_APU); \ return; \ } \ tcg_op(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rA(ctx->opcode)], \ @@ -6425,7 +6393,7 @@ GEN_SPEOP_ARITH2(evrlw, gen_op_evrlw); static always_inline void gen_evmergehi (DisasContext *ctx) { if (unlikely(!ctx->spe_enabled)) { - GEN_EXCP_NO_AP(ctx); + gen_exception(ctx, POWERPC_EXCP_APU); return; } #if defined(TARGET_PPC64) @@ -6454,7 +6422,7 @@ GEN_SPEOP_ARITH2(evsubfw, gen_op_evsubf); static always_inline void gen_##name (DisasContext *ctx) \ { \ if (unlikely(!ctx->spe_enabled)) { \ - GEN_EXCP_NO_AP(ctx); \ + gen_exception(ctx, POWERPC_EXCP_APU); \ return; \ } \ TCGv_i32 t0 = tcg_temp_local_new_i32(); \ @@ -6464,7 +6432,7 @@ static always_inline void gen_##name (DisasContext *ctx) \ tcg_op(t0, t0, rA(ctx->opcode)); \ tcg_gen_shri_i64(t2, cpu_gpr[rB(ctx->opcode)], 32); \ tcg_gen_trunc_i64_i32(t1, t2); \ - tcg_temp_free_i64(t2); \ + tcg_temp_free_i64(t2); \ tcg_op(t1, t1, rA(ctx->opcode)); \ tcg_gen_concat_i32_i64(cpu_gpr[rD(ctx->opcode)], t0, t1); \ tcg_temp_free_i32(t0); \ @@ -6475,7 +6443,7 @@ static always_inline void gen_##name (DisasContext *ctx) \ static always_inline void gen_##name (DisasContext *ctx) \ { \ if (unlikely(!ctx->spe_enabled)) { \ - GEN_EXCP_NO_AP(ctx); \ + gen_exception(ctx, POWERPC_EXCP_APU); \ return; \ } \ tcg_op(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rB(ctx->opcode)], \ @@ -6493,7 +6461,7 @@ GEN_SPEOP_ARITH_IMM2(evsubifw, tcg_gen_subi_i32); static always_inline void gen_##name (DisasContext *ctx) \ { \ if (unlikely(!ctx->spe_enabled)) { \ - GEN_EXCP_NO_AP(ctx); \ + gen_exception(ctx, POWERPC_EXCP_APU); \ return; \ } \ int l1 = gen_new_label(); \ @@ -6533,7 +6501,7 @@ static always_inline void gen_##name (DisasContext *ctx) \ static always_inline void gen_##name (DisasContext *ctx) \ { \ if (unlikely(!ctx->spe_enabled)) { \ - GEN_EXCP_NO_AP(ctx); \ + gen_exception(ctx, POWERPC_EXCP_APU); \ return; \ } \ int l1 = gen_new_label(); \ @@ -6576,7 +6544,7 @@ static always_inline void gen_brinc (DisasContext *ctx) static always_inline void gen_evmergelo (DisasContext *ctx) { if (unlikely(!ctx->spe_enabled)) { - GEN_EXCP_NO_AP(ctx); + gen_exception(ctx, POWERPC_EXCP_APU); return; } #if defined(TARGET_PPC64) @@ -6595,7 +6563,7 @@ static always_inline void gen_evmergelo (DisasContext *ctx) static always_inline void gen_evmergehilo (DisasContext *ctx) { if (unlikely(!ctx->spe_enabled)) { - GEN_EXCP_NO_AP(ctx); + gen_exception(ctx, POWERPC_EXCP_APU); return; } #if defined(TARGET_PPC64) @@ -6614,7 +6582,7 @@ static always_inline void gen_evmergehilo (DisasContext *ctx) static always_inline void gen_evmergelohi (DisasContext *ctx) { if (unlikely(!ctx->spe_enabled)) { - GEN_EXCP_NO_AP(ctx); + gen_exception(ctx, POWERPC_EXCP_APU); return; } #if defined(TARGET_PPC64) @@ -6745,23 +6713,29 @@ GEN_SPE(evcmpltu, evcmplts, 0x19, 0x08, 0x00600000, PPC_SPE); //// GEN_SPE(evcmpeq, speundef, 0x1A, 0x08, 0x00600000, PPC_SPE); //// /* SPE load and stores */ -static always_inline void gen_addr_spe_imm_index (TCGv EA, DisasContext *ctx, int sh) +static always_inline void gen_addr_spe_imm_index (DisasContext *ctx, TCGv EA, int sh) { target_ulong uimm = rB(ctx->opcode); - if (rA(ctx->opcode) == 0) + if (rA(ctx->opcode) == 0) { tcg_gen_movi_tl(EA, uimm << sh); - else + } else { tcg_gen_addi_tl(EA, cpu_gpr[rA(ctx->opcode)], uimm << sh); +#if defined(TARGET_PPC64) + if (!ctx->sf_mode) { + tcg_gen_ext32u_tl(EA, EA); + } +#endif + } } static always_inline void gen_op_evldd(DisasContext *ctx, TCGv addr) { #if defined(TARGET_PPC64) - gen_qemu_ld64(cpu_gpr[rD(ctx->opcode)], addr, ctx->mem_idx); + gen_qemu_ld64(ctx, cpu_gpr[rD(ctx->opcode)], addr); #else TCGv_i64 t0 = tcg_temp_new_i64(); - gen_qemu_ld64(t0, addr, ctx->mem_idx); + gen_qemu_ld64(ctx, t0, addr); tcg_gen_trunc_i64_i32(cpu_gpr[rD(ctx->opcode)], t0); tcg_gen_shri_i64(t0, t0, 32); tcg_gen_trunc_i64_i32(cpu_gprh[rD(ctx->opcode)], t0); @@ -6773,16 +6747,16 @@ static always_inline void gen_op_evldw(DisasContext *ctx, TCGv addr) { #if defined(TARGET_PPC64) TCGv t0 = tcg_temp_new(); - gen_qemu_ld32u(t0, addr, ctx->mem_idx); + gen_qemu_ld32u(ctx, t0, addr); tcg_gen_shli_tl(cpu_gpr[rD(ctx->opcode)], t0, 32); - tcg_gen_addi_tl(addr, addr, 4); - gen_qemu_ld32u(t0, addr, ctx->mem_idx); + gen_addr_add(ctx, addr, addr, 4); + gen_qemu_ld32u(ctx, t0, addr); tcg_gen_or_tl(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rD(ctx->opcode)], t0); tcg_temp_free(t0); #else - gen_qemu_ld32u(cpu_gprh[rD(ctx->opcode)], addr, ctx->mem_idx); - tcg_gen_addi_tl(addr, addr, 4); - gen_qemu_ld32u(cpu_gpr[rD(ctx->opcode)], addr, ctx->mem_idx); + gen_qemu_ld32u(ctx, cpu_gprh[rD(ctx->opcode)], addr); + gen_addr_add(ctx, addr, addr, 4); + gen_qemu_ld32u(ctx, cpu_gpr[rD(ctx->opcode)], addr); #endif } @@ -6790,30 +6764,30 @@ static always_inline void gen_op_evldh(DisasContext *ctx, TCGv addr) { TCGv t0 = tcg_temp_new(); #if defined(TARGET_PPC64) - gen_qemu_ld16u(t0, addr, ctx->mem_idx); + gen_qemu_ld16u(ctx, t0, addr); tcg_gen_shli_tl(cpu_gpr[rD(ctx->opcode)], t0, 48); - tcg_gen_addi_tl(addr, addr, 2); - gen_qemu_ld16u(t0, addr, ctx->mem_idx); + gen_addr_add(ctx, addr, addr, 2); + gen_qemu_ld16u(ctx, t0, addr); tcg_gen_shli_tl(t0, t0, 32); tcg_gen_or_tl(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rD(ctx->opcode)], t0); - tcg_gen_addi_tl(addr, addr, 2); - gen_qemu_ld16u(t0, addr, ctx->mem_idx); + gen_addr_add(ctx, addr, addr, 2); + gen_qemu_ld16u(ctx, t0, addr); tcg_gen_shli_tl(t0, t0, 16); tcg_gen_or_tl(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rD(ctx->opcode)], t0); - tcg_gen_addi_tl(addr, addr, 2); - gen_qemu_ld16u(t0, addr, ctx->mem_idx); + gen_addr_add(ctx, addr, addr, 2); + gen_qemu_ld16u(ctx, t0, addr); tcg_gen_or_tl(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rD(ctx->opcode)], t0); #else - gen_qemu_ld16u(t0, addr, ctx->mem_idx); + gen_qemu_ld16u(ctx, t0, addr); tcg_gen_shli_tl(cpu_gprh[rD(ctx->opcode)], t0, 16); - tcg_gen_addi_tl(addr, addr, 2); - gen_qemu_ld16u(t0, addr, ctx->mem_idx); + gen_addr_add(ctx, addr, addr, 2); + gen_qemu_ld16u(ctx, t0, addr); tcg_gen_or_tl(cpu_gprh[rD(ctx->opcode)], cpu_gprh[rD(ctx->opcode)], t0); - tcg_gen_addi_tl(addr, addr, 2); - gen_qemu_ld16u(t0, addr, ctx->mem_idx); + gen_addr_add(ctx, addr, addr, 2); + gen_qemu_ld16u(ctx, t0, addr); tcg_gen_shli_tl(cpu_gprh[rD(ctx->opcode)], t0, 16); - tcg_gen_addi_tl(addr, addr, 2); - gen_qemu_ld16u(t0, addr, ctx->mem_idx); + gen_addr_add(ctx, addr, addr, 2); + gen_qemu_ld16u(ctx, t0, addr); tcg_gen_or_tl(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rD(ctx->opcode)], t0); #endif tcg_temp_free(t0); @@ -6822,7 +6796,7 @@ static always_inline void gen_op_evldh(DisasContext *ctx, TCGv addr) static always_inline void gen_op_evlhhesplat(DisasContext *ctx, TCGv addr) { TCGv t0 = tcg_temp_new(); - gen_qemu_ld16u(t0, addr, ctx->mem_idx); + gen_qemu_ld16u(ctx, t0, addr); #if defined(TARGET_PPC64) tcg_gen_shli_tl(cpu_gpr[rD(ctx->opcode)], t0, 48); tcg_gen_shli_tl(t0, t0, 16); @@ -6838,7 +6812,7 @@ static always_inline void gen_op_evlhhesplat(DisasContext *ctx, TCGv addr) static always_inline void gen_op_evlhhousplat(DisasContext *ctx, TCGv addr) { TCGv t0 = tcg_temp_new(); - gen_qemu_ld16u(t0, addr, ctx->mem_idx); + gen_qemu_ld16u(ctx, t0, addr); #if defined(TARGET_PPC64) tcg_gen_shli_tl(cpu_gpr[rD(ctx->opcode)], t0, 32); tcg_gen_or_tl(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rD(ctx->opcode)], t0); @@ -6852,7 +6826,7 @@ static always_inline void gen_op_evlhhousplat(DisasContext *ctx, TCGv addr) static always_inline void gen_op_evlhhossplat(DisasContext *ctx, TCGv addr) { TCGv t0 = tcg_temp_new(); - gen_qemu_ld16s(t0, addr, ctx->mem_idx); + gen_qemu_ld16s(ctx, t0, addr); #if defined(TARGET_PPC64) tcg_gen_shli_tl(cpu_gpr[rD(ctx->opcode)], t0, 32); tcg_gen_ext32u_tl(t0, t0); @@ -6868,16 +6842,17 @@ static always_inline void gen_op_evlwhe(DisasContext *ctx, TCGv addr) { TCGv t0 = tcg_temp_new(); #if defined(TARGET_PPC64) - gen_qemu_ld16u(t0, addr, ctx->mem_idx); + gen_qemu_ld16u(ctx, t0, addr); tcg_gen_shli_tl(cpu_gpr[rD(ctx->opcode)], t0, 48); - gen_qemu_ld16u(t0, addr, ctx->mem_idx); + gen_addr_add(ctx, addr, addr, 2); + gen_qemu_ld16u(ctx, t0, addr); tcg_gen_shli_tl(t0, t0, 16); tcg_gen_or_tl(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rD(ctx->opcode)], t0); #else - gen_qemu_ld16u(t0, addr, ctx->mem_idx); + gen_qemu_ld16u(ctx, t0, addr); tcg_gen_shli_tl(cpu_gprh[rD(ctx->opcode)], t0, 16); - tcg_gen_addi_tl(addr, addr, 2); - gen_qemu_ld16u(t0, addr, ctx->mem_idx); + gen_addr_add(ctx, addr, addr, 2); + gen_qemu_ld16u(ctx, t0, addr); tcg_gen_shli_tl(cpu_gpr[rD(ctx->opcode)], t0, 16); #endif tcg_temp_free(t0); @@ -6887,16 +6862,16 @@ static always_inline void gen_op_evlwhou(DisasContext *ctx, TCGv addr) { #if defined(TARGET_PPC64) TCGv t0 = tcg_temp_new(); - gen_qemu_ld16u(cpu_gpr[rD(ctx->opcode)], addr, ctx->mem_idx); - tcg_gen_addi_tl(addr, addr, 2); - gen_qemu_ld16u(t0, addr, ctx->mem_idx); + gen_qemu_ld16u(ctx, cpu_gpr[rD(ctx->opcode)], addr); + gen_addr_add(ctx, addr, addr, 2); + gen_qemu_ld16u(ctx, t0, addr); tcg_gen_shli_tl(t0, t0, 32); tcg_gen_or_tl(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rD(ctx->opcode)], t0); tcg_temp_free(t0); #else - gen_qemu_ld16u(cpu_gprh[rD(ctx->opcode)], addr, ctx->mem_idx); - tcg_gen_addi_tl(addr, addr, 2); - gen_qemu_ld16u(cpu_gpr[rD(ctx->opcode)], addr, ctx->mem_idx); + gen_qemu_ld16u(ctx, cpu_gprh[rD(ctx->opcode)], addr); + gen_addr_add(ctx, addr, addr, 2); + gen_qemu_ld16u(ctx, cpu_gpr[rD(ctx->opcode)], addr); #endif } @@ -6904,24 +6879,24 @@ static always_inline void gen_op_evlwhos(DisasContext *ctx, TCGv addr) { #if defined(TARGET_PPC64) TCGv t0 = tcg_temp_new(); - gen_qemu_ld16s(t0, addr, ctx->mem_idx); + gen_qemu_ld16s(ctx, t0, addr); tcg_gen_ext32u_tl(cpu_gpr[rD(ctx->opcode)], t0); - tcg_gen_addi_tl(addr, addr, 2); - gen_qemu_ld16s(t0, addr, ctx->mem_idx); + gen_addr_add(ctx, addr, addr, 2); + gen_qemu_ld16s(ctx, t0, addr); tcg_gen_shli_tl(t0, t0, 32); tcg_gen_or_tl(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rD(ctx->opcode)], t0); tcg_temp_free(t0); #else - gen_qemu_ld16s(cpu_gprh[rD(ctx->opcode)], addr, ctx->mem_idx); - tcg_gen_addi_tl(addr, addr, 2); - gen_qemu_ld16s(cpu_gpr[rD(ctx->opcode)], addr, ctx->mem_idx); + gen_qemu_ld16s(ctx, cpu_gprh[rD(ctx->opcode)], addr); + gen_addr_add(ctx, addr, addr, 2); + gen_qemu_ld16s(ctx, cpu_gpr[rD(ctx->opcode)], addr); #endif } static always_inline void gen_op_evlwwsplat(DisasContext *ctx, TCGv addr) { TCGv t0 = tcg_temp_new(); - gen_qemu_ld32u(t0, addr, ctx->mem_idx); + gen_qemu_ld32u(ctx, t0, addr); #if defined(TARGET_PPC64) tcg_gen_shli_tl(cpu_gpr[rD(ctx->opcode)], t0, 32); tcg_gen_or_tl(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rD(ctx->opcode)], t0); @@ -6936,21 +6911,21 @@ static always_inline void gen_op_evlwhsplat(DisasContext *ctx, TCGv addr) { TCGv t0 = tcg_temp_new(); #if defined(TARGET_PPC64) - gen_qemu_ld16u(t0, addr, ctx->mem_idx); + gen_qemu_ld16u(ctx, t0, addr); tcg_gen_shli_tl(cpu_gpr[rD(ctx->opcode)], t0, 48); tcg_gen_shli_tl(t0, t0, 32); tcg_gen_or_tl(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rD(ctx->opcode)], t0); - tcg_gen_addi_tl(addr, addr, 2); - gen_qemu_ld16u(t0, addr, ctx->mem_idx); + gen_addr_add(ctx, addr, addr, 2); + gen_qemu_ld16u(ctx, t0, addr); tcg_gen_or_tl(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rD(ctx->opcode)], t0); tcg_gen_shli_tl(t0, t0, 16); tcg_gen_or_tl(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rD(ctx->opcode)], t0); #else - gen_qemu_ld16u(t0, addr, ctx->mem_idx); + gen_qemu_ld16u(ctx, t0, addr); tcg_gen_shli_tl(cpu_gprh[rD(ctx->opcode)], t0, 16); tcg_gen_or_tl(cpu_gprh[rD(ctx->opcode)], cpu_gprh[rD(ctx->opcode)], t0); - tcg_gen_addi_tl(addr, addr, 2); - gen_qemu_ld16u(t0, addr, ctx->mem_idx); + gen_addr_add(ctx, addr, addr, 2); + gen_qemu_ld16u(ctx, t0, addr); tcg_gen_shli_tl(cpu_gpr[rD(ctx->opcode)], t0, 16); tcg_gen_or_tl(cpu_gpr[rD(ctx->opcode)], cpu_gprh[rD(ctx->opcode)], t0); #endif @@ -6960,11 +6935,11 @@ static always_inline void gen_op_evlwhsplat(DisasContext *ctx, TCGv addr) static always_inline void gen_op_evstdd(DisasContext *ctx, TCGv addr) { #if defined(TARGET_PPC64) - gen_qemu_st64(cpu_gpr[rS(ctx->opcode)], addr, ctx->mem_idx); + gen_qemu_st64(ctx, cpu_gpr[rS(ctx->opcode)], addr); #else TCGv_i64 t0 = tcg_temp_new_i64(); tcg_gen_concat_i32_i64(t0, cpu_gpr[rS(ctx->opcode)], cpu_gprh[rS(ctx->opcode)]); - gen_qemu_st64(t0, addr, ctx->mem_idx); + gen_qemu_st64(ctx, t0, addr); tcg_temp_free_i64(t0); #endif } @@ -6974,13 +6949,13 @@ static always_inline void gen_op_evstdw(DisasContext *ctx, TCGv addr) #if defined(TARGET_PPC64) TCGv t0 = tcg_temp_new(); tcg_gen_shri_tl(t0, cpu_gpr[rS(ctx->opcode)], 32); - gen_qemu_st32(t0, addr, ctx->mem_idx); + gen_qemu_st32(ctx, t0, addr); tcg_temp_free(t0); #else - gen_qemu_st32(cpu_gprh[rS(ctx->opcode)], addr, ctx->mem_idx); + gen_qemu_st32(ctx, cpu_gprh[rS(ctx->opcode)], addr); #endif - tcg_gen_addi_tl(addr, addr, 4); - gen_qemu_st32(cpu_gpr[rS(ctx->opcode)], addr, ctx->mem_idx); + gen_addr_add(ctx, addr, addr, 4); + gen_qemu_st32(ctx, cpu_gpr[rS(ctx->opcode)], addr); } static always_inline void gen_op_evstdh(DisasContext *ctx, TCGv addr) @@ -6991,20 +6966,20 @@ static always_inline void gen_op_evstdh(DisasContext *ctx, TCGv addr) #else tcg_gen_shri_tl(t0, cpu_gprh[rS(ctx->opcode)], 16); #endif - gen_qemu_st16(t0, addr, ctx->mem_idx); - tcg_gen_addi_tl(addr, addr, 2); + gen_qemu_st16(ctx, t0, addr); + gen_addr_add(ctx, addr, addr, 2); #if defined(TARGET_PPC64) tcg_gen_shri_tl(t0, cpu_gpr[rS(ctx->opcode)], 32); - gen_qemu_st16(t0, addr, ctx->mem_idx); + gen_qemu_st16(ctx, t0, addr); #else - gen_qemu_st16(cpu_gprh[rS(ctx->opcode)], addr, ctx->mem_idx); + gen_qemu_st16(ctx, cpu_gprh[rS(ctx->opcode)], addr); #endif - tcg_gen_addi_tl(addr, addr, 2); + gen_addr_add(ctx, addr, addr, 2); tcg_gen_shri_tl(t0, cpu_gpr[rS(ctx->opcode)], 16); - gen_qemu_st16(t0, addr, ctx->mem_idx); + gen_qemu_st16(ctx, t0, addr); tcg_temp_free(t0); - tcg_gen_addi_tl(addr, addr, 2); - gen_qemu_st16(cpu_gpr[rS(ctx->opcode)], addr, ctx->mem_idx); + gen_addr_add(ctx, addr, addr, 2); + gen_qemu_st16(ctx, cpu_gpr[rS(ctx->opcode)], addr); } static always_inline void gen_op_evstwhe(DisasContext *ctx, TCGv addr) @@ -7015,10 +6990,10 @@ static always_inline void gen_op_evstwhe(DisasContext *ctx, TCGv addr) #else tcg_gen_shri_tl(t0, cpu_gprh[rS(ctx->opcode)], 16); #endif - gen_qemu_st16(t0, addr, ctx->mem_idx); - tcg_gen_addi_tl(addr, addr, 2); + gen_qemu_st16(ctx, t0, addr); + gen_addr_add(ctx, addr, addr, 2); tcg_gen_shri_tl(t0, cpu_gpr[rS(ctx->opcode)], 16); - gen_qemu_st16(t0, addr, ctx->mem_idx); + gen_qemu_st16(ctx, t0, addr); tcg_temp_free(t0); } @@ -7027,13 +7002,13 @@ static always_inline void gen_op_evstwho(DisasContext *ctx, TCGv addr) #if defined(TARGET_PPC64) TCGv t0 = tcg_temp_new(); tcg_gen_shri_tl(t0, cpu_gpr[rS(ctx->opcode)], 32); - gen_qemu_st16(t0, addr, ctx->mem_idx); + gen_qemu_st16(ctx, t0, addr); tcg_temp_free(t0); #else - gen_qemu_st16(cpu_gprh[rS(ctx->opcode)], addr, ctx->mem_idx); + gen_qemu_st16(ctx, cpu_gprh[rS(ctx->opcode)], addr); #endif - tcg_gen_addi_tl(addr, addr, 2); - gen_qemu_st16(cpu_gpr[rS(ctx->opcode)], addr, ctx->mem_idx); + gen_addr_add(ctx, addr, addr, 2); + gen_qemu_st16(ctx, cpu_gpr[rS(ctx->opcode)], addr); } static always_inline void gen_op_evstwwe(DisasContext *ctx, TCGv addr) @@ -7041,31 +7016,32 @@ static always_inline void gen_op_evstwwe(DisasContext *ctx, TCGv addr) #if defined(TARGET_PPC64) TCGv t0 = tcg_temp_new(); tcg_gen_shri_tl(t0, cpu_gpr[rS(ctx->opcode)], 32); - gen_qemu_st32(t0, addr, ctx->mem_idx); + gen_qemu_st32(ctx, t0, addr); tcg_temp_free(t0); #else - gen_qemu_st32(cpu_gprh[rS(ctx->opcode)], addr, ctx->mem_idx); + gen_qemu_st32(ctx, cpu_gprh[rS(ctx->opcode)], addr); #endif } static always_inline void gen_op_evstwwo(DisasContext *ctx, TCGv addr) { - gen_qemu_st32(cpu_gpr[rS(ctx->opcode)], addr, ctx->mem_idx); + gen_qemu_st32(ctx, cpu_gpr[rS(ctx->opcode)], addr); } #define GEN_SPEOP_LDST(name, opc2, sh) \ -GEN_HANDLER(gen_##name, 0x04, opc2, 0x0C, 0x00000000, PPC_SPE) \ +GEN_HANDLER(name, 0x04, opc2, 0x0C, 0x00000000, PPC_SPE) \ { \ TCGv t0; \ if (unlikely(!ctx->spe_enabled)) { \ - GEN_EXCP_NO_AP(ctx); \ + gen_exception(ctx, POWERPC_EXCP_APU); \ return; \ } \ + gen_set_access_type(ctx, ACCESS_INT); \ t0 = tcg_temp_new(); \ if (Rc(ctx->opcode)) { \ - gen_addr_spe_imm_index(t0, ctx, sh); \ + gen_addr_spe_imm_index(ctx, t0, sh); \ } else { \ - gen_addr_reg_index(t0, ctx); \ + gen_addr_reg_index(ctx, t0); \ } \ gen_op_##name(ctx, t0); \ tcg_temp_free(t0); \ @@ -7219,7 +7195,7 @@ static always_inline void gen_##name (DisasContext *ctx) \ TCGv_i32 t0, t1; \ TCGv_i64 t2; \ if (unlikely(!ctx->spe_enabled)) { \ - GEN_EXCP_NO_AP(ctx); \ + gen_exception(ctx, POWERPC_EXCP_APU); \ return; \ } \ t0 = tcg_temp_new_i32(); \ @@ -7240,7 +7216,7 @@ static always_inline void gen_##name (DisasContext *ctx) \ static always_inline void gen_##name (DisasContext *ctx) \ { \ if (unlikely(!ctx->spe_enabled)) { \ - GEN_EXCP_NO_AP(ctx); \ + gen_exception(ctx, POWERPC_EXCP_APU); \ return; \ } \ gen_helper_##name(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rA(ctx->opcode)], \ @@ -7251,7 +7227,7 @@ static always_inline void gen_##name (DisasContext *ctx) \ { \ TCGv_i32 t0, t1; \ if (unlikely(!ctx->spe_enabled)) { \ - GEN_EXCP_NO_AP(ctx); \ + gen_exception(ctx, POWERPC_EXCP_APU); \ return; \ } \ t0 = tcg_temp_new_i32(); \ @@ -7266,7 +7242,7 @@ static always_inline void gen_##name (DisasContext *ctx) \ static always_inline void gen_##name (DisasContext *ctx) \ { \ if (unlikely(!ctx->spe_enabled)) { \ - GEN_EXCP_NO_AP(ctx); \ + gen_exception(ctx, POWERPC_EXCP_APU); \ return; \ } \ gen_helper_##name(cpu_crf[crfD(ctx->opcode)], \ @@ -7307,7 +7283,7 @@ static always_inline void gen_##name (DisasContext *ctx) \ static always_inline void gen_##name (DisasContext *ctx) \ { \ if (unlikely(!ctx->spe_enabled)) { \ - GEN_EXCP_NO_AP(ctx); \ + gen_exception(ctx, POWERPC_EXCP_APU); \ return; \ } \ gen_helper_##name(cpu_gpr[rD(ctx->opcode)], \ @@ -7318,7 +7294,7 @@ static always_inline void gen_##name (DisasContext *ctx) \ { \ TCGv_i64 t0, t1; \ if (unlikely(!ctx->spe_enabled)) { \ - GEN_EXCP_NO_AP(ctx); \ + gen_exception(ctx, POWERPC_EXCP_APU); \ return; \ } \ t0 = tcg_temp_new_i64(); \ @@ -7334,7 +7310,7 @@ static always_inline void gen_##name (DisasContext *ctx) \ static always_inline void gen_##name (DisasContext *ctx) \ { \ if (unlikely(!ctx->spe_enabled)) { \ - GEN_EXCP_NO_AP(ctx); \ + gen_exception(ctx, POWERPC_EXCP_APU); \ return; \ } \ gen_helper_##name(cpu_crf[crfD(ctx->opcode)], \ @@ -7345,7 +7321,7 @@ static always_inline void gen_##name (DisasContext *ctx) \ { \ TCGv_i64 t0, t1; \ if (unlikely(!ctx->spe_enabled)) { \ - GEN_EXCP_NO_AP(ctx); \ + gen_exception(ctx, POWERPC_EXCP_APU); \ return; \ } \ t0 = tcg_temp_new_i64(); \ @@ -7367,7 +7343,7 @@ GEN_SPEFPUOP_ARITH2_64_64(evfsdiv); static always_inline void gen_evfsabs (DisasContext *ctx) { if (unlikely(!ctx->spe_enabled)) { - GEN_EXCP_NO_AP(ctx); + gen_exception(ctx, POWERPC_EXCP_APU); return; } #if defined(TARGET_PPC64) @@ -7380,7 +7356,7 @@ static always_inline void gen_evfsabs (DisasContext *ctx) static always_inline void gen_evfsnabs (DisasContext *ctx) { if (unlikely(!ctx->spe_enabled)) { - GEN_EXCP_NO_AP(ctx); + gen_exception(ctx, POWERPC_EXCP_APU); return; } #if defined(TARGET_PPC64) @@ -7393,7 +7369,7 @@ static always_inline void gen_evfsnabs (DisasContext *ctx) static always_inline void gen_evfsneg (DisasContext *ctx) { if (unlikely(!ctx->spe_enabled)) { - GEN_EXCP_NO_AP(ctx); + gen_exception(ctx, POWERPC_EXCP_APU); return; } #if defined(TARGET_PPC64) @@ -7449,7 +7425,7 @@ GEN_SPEFPUOP_ARITH2_32_32(efsdiv); static always_inline void gen_efsabs (DisasContext *ctx) { if (unlikely(!ctx->spe_enabled)) { - GEN_EXCP_NO_AP(ctx); + gen_exception(ctx, POWERPC_EXCP_APU); return; } tcg_gen_andi_tl(cpu_gpr[rA(ctx->opcode)], cpu_gpr[rA(ctx->opcode)], (target_long)~0x80000000LL); @@ -7457,7 +7433,7 @@ static always_inline void gen_efsabs (DisasContext *ctx) static always_inline void gen_efsnabs (DisasContext *ctx) { if (unlikely(!ctx->spe_enabled)) { - GEN_EXCP_NO_AP(ctx); + gen_exception(ctx, POWERPC_EXCP_APU); return; } tcg_gen_ori_tl(cpu_gpr[rA(ctx->opcode)], cpu_gpr[rA(ctx->opcode)], 0x80000000); @@ -7465,7 +7441,7 @@ static always_inline void gen_efsnabs (DisasContext *ctx) static always_inline void gen_efsneg (DisasContext *ctx) { if (unlikely(!ctx->spe_enabled)) { - GEN_EXCP_NO_AP(ctx); + gen_exception(ctx, POWERPC_EXCP_APU); return; } tcg_gen_xori_tl(cpu_gpr[rA(ctx->opcode)], cpu_gpr[rA(ctx->opcode)], 0x80000000); @@ -7517,7 +7493,7 @@ GEN_SPEFPUOP_ARITH2_64_64(efddiv); static always_inline void gen_efdabs (DisasContext *ctx) { if (unlikely(!ctx->spe_enabled)) { - GEN_EXCP_NO_AP(ctx); + gen_exception(ctx, POWERPC_EXCP_APU); return; } #if defined(TARGET_PPC64) @@ -7529,7 +7505,7 @@ static always_inline void gen_efdabs (DisasContext *ctx) static always_inline void gen_efdnabs (DisasContext *ctx) { if (unlikely(!ctx->spe_enabled)) { - GEN_EXCP_NO_AP(ctx); + gen_exception(ctx, POWERPC_EXCP_APU); return; } #if defined(TARGET_PPC64) @@ -7541,7 +7517,7 @@ static always_inline void gen_efdnabs (DisasContext *ctx) static always_inline void gen_efdneg (DisasContext *ctx) { if (unlikely(!ctx->spe_enabled)) { - GEN_EXCP_NO_AP(ctx); + gen_exception(ctx, POWERPC_EXCP_APU); return; } #if defined(TARGET_PPC64) @@ -7656,6 +7632,7 @@ void cpu_dump_state (CPUState *env, FILE *f, if ((i & (RFPL - 1)) == (RFPL - 1)) cpu_fprintf(f, "\n"); } + cpu_fprintf(f, "FPSCR %08x\n", env->fpscr); #if !defined(CONFIG_USER_ONLY) cpu_fprintf(f, "SRR0 " ADDRX " SRR1 " ADDRX " SDR1 " ADDRX "\n", env->spr[SPR_SRR0], env->spr[SPR_SRR1], env->sdr1); @@ -7721,7 +7698,6 @@ static always_inline void gen_intermediate_code_internal (CPUState *env, opc_handler_t **table, *handler; target_ulong pc_start; uint16_t *gen_opc_end; - int supervisor, little_endian; CPUBreakpoint *bp; int j, lj = -1; int num_insns; @@ -7729,23 +7705,15 @@ static always_inline void gen_intermediate_code_internal (CPUState *env, pc_start = tb->pc; gen_opc_end = gen_opc_buf + OPC_MAX_SIZE; -#if defined(OPTIMIZE_FPRF_UPDATE) - gen_fprf_ptr = gen_fprf_buf; -#endif ctx.nip = pc_start; ctx.tb = tb; ctx.exception = POWERPC_EXCP_NONE; ctx.spr_cb = env->spr_cb; - supervisor = env->mmu_idx; -#if !defined(CONFIG_USER_ONLY) - ctx.supervisor = supervisor; -#endif - little_endian = env->hflags & (1 << MSR_LE) ? 1 : 0; + ctx.mem_idx = env->mmu_idx; + ctx.access_type = -1; + ctx.le_mode = env->hflags & (1 << MSR_LE) ? 1 : 0; #if defined(TARGET_PPC64) ctx.sf_mode = msr_sf; - ctx.mem_idx = (supervisor << 2) | (msr_sf << 1) | little_endian; -#else - ctx.mem_idx = (supervisor << 1) | little_endian; #endif ctx.fpu_enabled = msr_fp; if ((env->flags & POWERPC_FLAG_SPE) && msr_spe) @@ -7779,8 +7747,7 @@ static always_inline void gen_intermediate_code_internal (CPUState *env, if (unlikely(!TAILQ_EMPTY(&env->breakpoints))) { TAILQ_FOREACH(bp, &env->breakpoints, entry) { if (bp->pc == ctx.nip) { - gen_update_nip(&ctx, ctx.nip); - gen_helper_raise_debug(); + gen_debug_exception(ctxp); break; } } @@ -7800,12 +7767,12 @@ static always_inline void gen_intermediate_code_internal (CPUState *env, if (loglevel & CPU_LOG_TB_IN_ASM) { fprintf(logfile, "----------------\n"); fprintf(logfile, "nip=" ADDRX " super=%d ir=%d\n", - ctx.nip, supervisor, (int)msr_ir); + ctx.nip, ctx.mem_idx, (int)msr_ir); } #endif if (num_insns + 1 == max_insns && (tb->cflags & CF_LAST_IO)) gen_io_start(); - if (unlikely(little_endian)) { + if (unlikely(ctx.le_mode)) { ctx.opcode = bswap32(ldl_code(ctx.nip)); } else { ctx.opcode = ldl_code(ctx.nip); @@ -7857,7 +7824,7 @@ static always_inline void gen_intermediate_code_internal (CPUState *env, opc2(ctx.opcode), opc3(ctx.opcode), ctx.opcode, ctx.nip - 4); } - GEN_EXCP_INVAL(ctxp); + gen_inval_exception(ctxp, POWERPC_EXCP_INVAL_INVAL); break; } } @@ -7871,7 +7838,7 @@ static always_inline void gen_intermediate_code_internal (CPUState *env, ctx.exception != POWERPC_SYSCALL && ctx.exception != POWERPC_EXCP_TRAP && ctx.exception != POWERPC_EXCP_BRANCH)) { - GEN_EXCP(ctxp, POWERPC_EXCP_TRACE, 0); + gen_exception(ctxp, POWERPC_EXCP_TRACE); } else if (unlikely(((ctx.nip & (TARGET_PAGE_SIZE - 1)) == 0) || (env->singlestep_enabled) || num_insns >= max_insns)) { @@ -7890,8 +7857,7 @@ static always_inline void gen_intermediate_code_internal (CPUState *env, gen_goto_tb(&ctx, 0, ctx.nip); } else if (ctx.exception != POWERPC_EXCP_BRANCH) { if (unlikely(env->singlestep_enabled)) { - gen_update_nip(&ctx, ctx.nip); - gen_helper_raise_debug(); + gen_debug_exception(ctxp); } /* Generate the return instruction */ tcg_gen_exit_tb(0); @@ -7915,7 +7881,7 @@ static always_inline void gen_intermediate_code_internal (CPUState *env, if (loglevel & CPU_LOG_TB_IN_ASM) { int flags; flags = env->bfd_mach; - flags |= little_endian << 16; + flags |= ctx.le_mode << 16; fprintf(logfile, "IN: %s\n", lookup_symbol(pc_start)); target_disas(logfile, pc_start, ctx.nip - pc_start, flags); fprintf(logfile, "\n"); diff --git a/qemu/target-ppc/translate_init.c b/qemu/target-ppc/translate_init.c index 4208f3de..0ce81ed7 100644 --- a/qemu/target-ppc/translate_init.c +++ b/qemu/target-ppc/translate_init.c @@ -66,67 +66,76 @@ PPC_IRQ_INIT_FN(970); /* Generic callbacks: * do nothing but store/retrieve spr value */ -#ifdef PPC_DUMP_SPR_ACCESSES -static void spr_read_generic (void *opaque, int sprn) -{ - gen_op_load_dump_spr(sprn); -} - -static void spr_write_generic (void *opaque, int sprn) +static void spr_read_generic (void *opaque, int gprn, int sprn) { - gen_op_store_dump_spr(sprn); -} -#else -static void spr_read_generic (void *opaque, int sprn) -{ - gen_op_load_spr(sprn); + gen_load_spr(cpu_gpr[gprn], sprn); +#ifdef PPC_DUMP_SPR_ACCESSES + { + TCGv t0 = tcg_const_i32(sprn); + gen_helper_load_dump_spr(t0); + tcg_temp_free_i32(t0); + } +#endif } -static void spr_write_generic (void *opaque, int sprn) +static void spr_write_generic (void *opaque, int sprn, int gprn) { - gen_op_store_spr(sprn); -} + gen_store_spr(sprn, cpu_gpr[gprn]); +#ifdef PPC_DUMP_SPR_ACCESSES + { + TCGv t0 = tcg_const_i32(sprn); + gen_helper_store_dump_spr(t0); + tcg_temp_free_i32(t0); + } #endif +} #if !defined(CONFIG_USER_ONLY) -static void spr_write_clear (void *opaque, int sprn) +static void spr_write_clear (void *opaque, int sprn, int gprn) { - gen_op_mask_spr(sprn); + TCGv t0 = tcg_temp_new(); + TCGv t1 = tcg_temp_new(); + gen_load_spr(t0, sprn); + tcg_gen_neg_tl(t1, cpu_gpr[gprn]); + tcg_gen_and_tl(t0, t0, t1); + gen_store_spr(sprn, t0); + tcg_temp_free(t0); + tcg_temp_free(t1); } #endif /* SPR common to all PowerPC */ /* XER */ -static void spr_read_xer (void *opaque, int sprn) +static void spr_read_xer (void *opaque, int gprn, int sprn) { - tcg_gen_mov_tl(cpu_T[0], cpu_xer); + tcg_gen_mov_tl(cpu_gpr[gprn], cpu_xer); } -static void spr_write_xer (void *opaque, int sprn) +static void spr_write_xer (void *opaque, int sprn, int gprn) { - tcg_gen_mov_tl(cpu_xer, cpu_T[0]); + tcg_gen_mov_tl(cpu_xer, cpu_gpr[gprn]); } /* LR */ -static void spr_read_lr (void *opaque, int sprn) +static void spr_read_lr (void *opaque, int gprn, int sprn) { - tcg_gen_mov_tl(cpu_T[0], cpu_lr); + tcg_gen_mov_tl(cpu_gpr[gprn], cpu_lr); } -static void spr_write_lr (void *opaque, int sprn) +static void spr_write_lr (void *opaque, int sprn, int gprn) { - tcg_gen_mov_tl(cpu_lr, cpu_T[0]); + tcg_gen_mov_tl(cpu_lr, cpu_gpr[gprn]); } /* CTR */ -static void spr_read_ctr (void *opaque, int sprn) +static void spr_read_ctr (void *opaque, int gprn, int sprn) { - tcg_gen_mov_tl(cpu_T[0], cpu_ctr); + tcg_gen_mov_tl(cpu_gpr[gprn], cpu_ctr); } -static void spr_write_ctr (void *opaque, int sprn) +static void spr_write_ctr (void *opaque, int sprn, int gprn) { - tcg_gen_mov_tl(cpu_ctr, cpu_T[0]); + tcg_gen_mov_tl(cpu_ctr, cpu_gpr[gprn]); } /* User read access to SPR */ @@ -135,293 +144,329 @@ static void spr_write_ctr (void *opaque, int sprn) /* UPMCx */ /* USIA */ /* UDECR */ -static void spr_read_ureg (void *opaque, int sprn) +static void spr_read_ureg (void *opaque, int gprn, int sprn) { - gen_op_load_spr(sprn + 0x10); + gen_load_spr(cpu_gpr[gprn], sprn + 0x10); } /* SPR common to all non-embedded PowerPC */ /* DECR */ #if !defined(CONFIG_USER_ONLY) -static void spr_read_decr (void *opaque, int sprn) +static void spr_read_decr (void *opaque, int gprn, int sprn) { - gen_op_load_decr(); + gen_helper_load_decr(cpu_gpr[gprn]); } -static void spr_write_decr (void *opaque, int sprn) +static void spr_write_decr (void *opaque, int sprn, int gprn) { - gen_op_store_decr(); + gen_helper_store_decr(cpu_gpr[gprn]); } #endif /* SPR common to all non-embedded PowerPC, except 601 */ /* Time base */ -static void spr_read_tbl (void *opaque, int sprn) +static void spr_read_tbl (void *opaque, int gprn, int sprn) { - gen_op_load_tbl(); + gen_helper_load_tbl(cpu_gpr[gprn]); } -static void spr_read_tbu (void *opaque, int sprn) +static void spr_read_tbu (void *opaque, int gprn, int sprn) { - gen_op_load_tbu(); + gen_helper_load_tbu(cpu_gpr[gprn]); } __attribute__ (( unused )) -static void spr_read_atbl (void *opaque, int sprn) +static void spr_read_atbl (void *opaque, int gprn, int sprn) { - gen_op_load_atbl(); + gen_helper_load_atbl(cpu_gpr[gprn]); } __attribute__ (( unused )) -static void spr_read_atbu (void *opaque, int sprn) +static void spr_read_atbu (void *opaque, int gprn, int sprn) { - gen_op_load_atbu(); + gen_helper_load_atbu(cpu_gpr[gprn]); } #if !defined(CONFIG_USER_ONLY) -static void spr_write_tbl (void *opaque, int sprn) +static void spr_write_tbl (void *opaque, int sprn, int gprn) { - gen_op_store_tbl(); + gen_helper_store_tbl(cpu_gpr[gprn]); } -static void spr_write_tbu (void *opaque, int sprn) +static void spr_write_tbu (void *opaque, int sprn, int gprn) { - gen_op_store_tbu(); + gen_helper_store_tbu(cpu_gpr[gprn]); } __attribute__ (( unused )) -static void spr_write_atbl (void *opaque, int sprn) +static void spr_write_atbl (void *opaque, int sprn, int gprn) { - gen_op_store_atbl(); + gen_helper_store_atbl(cpu_gpr[gprn]); } __attribute__ (( unused )) -static void spr_write_atbu (void *opaque, int sprn) +static void spr_write_atbu (void *opaque, int sprn, int gprn) { - gen_op_store_atbu(); + gen_helper_store_atbu(cpu_gpr[gprn]); } #endif #if !defined(CONFIG_USER_ONLY) /* IBAT0U...IBAT0U */ /* IBAT0L...IBAT7L */ -static void spr_read_ibat (void *opaque, int sprn) +static void spr_read_ibat (void *opaque, int gprn, int sprn) { - gen_op_load_ibat(sprn & 1, (sprn - SPR_IBAT0U) / 2); + tcg_gen_ld_tl(cpu_gpr[gprn], cpu_env, offsetof(CPUState, IBAT[sprn & 1][(sprn - SPR_IBAT0U) / 2])); } -static void spr_read_ibat_h (void *opaque, int sprn) +static void spr_read_ibat_h (void *opaque, int gprn, int sprn) { - gen_op_load_ibat(sprn & 1, (sprn - SPR_IBAT4U) / 2); + tcg_gen_ld_tl(cpu_gpr[gprn], cpu_env, offsetof(CPUState, IBAT[sprn & 1][(sprn - SPR_IBAT4U) / 2])); } -static void spr_write_ibatu (void *opaque, int sprn) +static void spr_write_ibatu (void *opaque, int sprn, int gprn) { - gen_op_store_ibatu((sprn - SPR_IBAT0U) / 2); + TCGv_i32 t0 = tcg_const_i32((sprn - SPR_IBAT0U) / 2); + gen_helper_store_ibatu(t0, cpu_gpr[gprn]); + tcg_temp_free_i32(t0); } -static void spr_write_ibatu_h (void *opaque, int sprn) +static void spr_write_ibatu_h (void *opaque, int sprn, int gprn) { - gen_op_store_ibatu((sprn - SPR_IBAT4U) / 2); + TCGv_i32 t0 = tcg_const_i32((sprn - SPR_IBAT4U) / 2); + gen_helper_store_ibatu(t0, cpu_gpr[gprn]); + tcg_temp_free_i32(t0); } -static void spr_write_ibatl (void *opaque, int sprn) +static void spr_write_ibatl (void *opaque, int sprn, int gprn) { - gen_op_store_ibatl((sprn - SPR_IBAT0L) / 2); + TCGv_i32 t0 = tcg_const_i32((sprn - SPR_IBAT0L) / 2); + gen_helper_store_ibatl(t0, cpu_gpr[gprn]); + tcg_temp_free_i32(t0); } -static void spr_write_ibatl_h (void *opaque, int sprn) +static void spr_write_ibatl_h (void *opaque, int sprn, int gprn) { - gen_op_store_ibatl((sprn - SPR_IBAT4L) / 2); + TCGv_i32 t0 = tcg_const_i32((sprn - SPR_IBAT4L) / 2); + gen_helper_store_ibatl(t0, cpu_gpr[gprn]); + tcg_temp_free_i32(t0); } /* DBAT0U...DBAT7U */ /* DBAT0L...DBAT7L */ -static void spr_read_dbat (void *opaque, int sprn) +static void spr_read_dbat (void *opaque, int gprn, int sprn) { - gen_op_load_dbat(sprn & 1, (sprn - SPR_DBAT0U) / 2); + tcg_gen_ld_tl(cpu_gpr[gprn], cpu_env, offsetof(CPUState, DBAT[sprn & 1][(sprn - SPR_DBAT0U) / 2])); } -static void spr_read_dbat_h (void *opaque, int sprn) +static void spr_read_dbat_h (void *opaque, int gprn, int sprn) { - gen_op_load_dbat(sprn & 1, ((sprn - SPR_DBAT4U) / 2) + 4); + tcg_gen_ld_tl(cpu_gpr[gprn], cpu_env, offsetof(CPUState, DBAT[sprn & 1][((sprn - SPR_DBAT4U) / 2) + 4])); } -static void spr_write_dbatu (void *opaque, int sprn) +static void spr_write_dbatu (void *opaque, int sprn, int gprn) { - gen_op_store_dbatu((sprn - SPR_DBAT0U) / 2); + TCGv_i32 t0 = tcg_const_i32((sprn - SPR_DBAT0U) / 2); + gen_helper_store_dbatu(t0, cpu_gpr[gprn]); + tcg_temp_free_i32(t0); } -static void spr_write_dbatu_h (void *opaque, int sprn) +static void spr_write_dbatu_h (void *opaque, int sprn, int gprn) { - gen_op_store_dbatu(((sprn - SPR_DBAT4U) / 2) + 4); + TCGv_i32 t0 = tcg_const_i32(((sprn - SPR_DBAT4U) / 2) + 4); + gen_helper_store_dbatu(t0, cpu_gpr[gprn]); + tcg_temp_free_i32(t0); } -static void spr_write_dbatl (void *opaque, int sprn) +static void spr_write_dbatl (void *opaque, int sprn, int gprn) { - gen_op_store_dbatl((sprn - SPR_DBAT0L) / 2); + TCGv_i32 t0 = tcg_const_i32((sprn - SPR_DBAT0L) / 2); + gen_helper_store_dbatl(t0, cpu_gpr[gprn]); + tcg_temp_free_i32(t0); } -static void spr_write_dbatl_h (void *opaque, int sprn) +static void spr_write_dbatl_h (void *opaque, int sprn, int gprn) { - gen_op_store_dbatl(((sprn - SPR_DBAT4L) / 2) + 4); + TCGv_i32 t0 = tcg_const_i32(((sprn - SPR_DBAT4L) / 2) + 4); + gen_helper_store_dbatl(t0, cpu_gpr[gprn]); + tcg_temp_free_i32(t0); } /* SDR1 */ -static void spr_read_sdr1 (void *opaque, int sprn) +static void spr_read_sdr1 (void *opaque, int gprn, int sprn) { - gen_op_load_sdr1(); + tcg_gen_ld_tl(cpu_gpr[gprn], cpu_env, offsetof(CPUState, sdr1)); } -static void spr_write_sdr1 (void *opaque, int sprn) +static void spr_write_sdr1 (void *opaque, int sprn, int gprn) { - gen_op_store_sdr1(); + gen_helper_store_sdr1(cpu_gpr[gprn]); } /* 64 bits PowerPC specific SPRs */ /* ASR */ #if defined(TARGET_PPC64) -static void spr_read_asr (void *opaque, int sprn) +static void spr_read_asr (void *opaque, int gprn, int sprn) { - gen_op_load_asr(); + tcg_gen_ld_tl(cpu_gpr[gprn], cpu_env, offsetof(CPUState, asr)); } -static void spr_write_asr (void *opaque, int sprn) +static void spr_write_asr (void *opaque, int sprn, int gprn) { - gen_op_store_asr(); + gen_helper_store_asr(cpu_gpr[gprn]); } #endif #endif /* PowerPC 601 specific registers */ /* RTC */ -static void spr_read_601_rtcl (void *opaque, int sprn) +static void spr_read_601_rtcl (void *opaque, int gprn, int sprn) { - gen_op_load_601_rtcl(); + gen_helper_load_601_rtcl(cpu_gpr[gprn]); } -static void spr_read_601_rtcu (void *opaque, int sprn) +static void spr_read_601_rtcu (void *opaque, int gprn, int sprn) { - gen_op_load_601_rtcu(); + gen_helper_load_601_rtcu(cpu_gpr[gprn]); } #if !defined(CONFIG_USER_ONLY) -static void spr_write_601_rtcu (void *opaque, int sprn) +static void spr_write_601_rtcu (void *opaque, int sprn, int gprn) { - gen_op_store_601_rtcu(); + gen_helper_store_601_rtcu(cpu_gpr[gprn]); } -static void spr_write_601_rtcl (void *opaque, int sprn) +static void spr_write_601_rtcl (void *opaque, int sprn, int gprn) { - gen_op_store_601_rtcl(); + gen_helper_store_601_rtcl(cpu_gpr[gprn]); } -static void spr_write_hid0_601 (void *opaque, int sprn) +static void spr_write_hid0_601 (void *opaque, int sprn, int gprn) { DisasContext *ctx = opaque; - gen_op_store_hid0_601(); + gen_helper_store_hid0_601(cpu_gpr[gprn]); /* Must stop the translation as endianness may have changed */ - GEN_STOP(ctx); + gen_stop_exception(ctx); } #endif /* Unified bats */ #if !defined(CONFIG_USER_ONLY) -static void spr_read_601_ubat (void *opaque, int sprn) +static void spr_read_601_ubat (void *opaque, int gprn, int sprn) { - gen_op_load_601_bat(sprn & 1, (sprn - SPR_IBAT0U) / 2); + tcg_gen_ld_tl(cpu_gpr[gprn], cpu_env, offsetof(CPUState, IBAT[sprn & 1][(sprn - SPR_IBAT0U) / 2])); } -static void spr_write_601_ubatu (void *opaque, int sprn) +static void spr_write_601_ubatu (void *opaque, int sprn, int gprn) { - gen_op_store_601_batu((sprn - SPR_IBAT0U) / 2); + TCGv_i32 t0 = tcg_const_i32((sprn - SPR_IBAT0U) / 2); + gen_helper_store_601_batl(t0, cpu_gpr[gprn]); + tcg_temp_free_i32(t0); } -static void spr_write_601_ubatl (void *opaque, int sprn) +static void spr_write_601_ubatl (void *opaque, int sprn, int gprn) { - gen_op_store_601_batl((sprn - SPR_IBAT0L) / 2); + TCGv_i32 t0 = tcg_const_i32((sprn - SPR_IBAT0U) / 2); + gen_helper_store_601_batu(t0, cpu_gpr[gprn]); + tcg_temp_free_i32(t0); } #endif /* PowerPC 40x specific registers */ #if !defined(CONFIG_USER_ONLY) -static void spr_read_40x_pit (void *opaque, int sprn) +static void spr_read_40x_pit (void *opaque, int gprn, int sprn) { - gen_op_load_40x_pit(); + gen_helper_load_40x_pit(cpu_gpr[gprn]); } -static void spr_write_40x_pit (void *opaque, int sprn) +static void spr_write_40x_pit (void *opaque, int sprn, int gprn) { - gen_op_store_40x_pit(); + gen_helper_store_40x_pit(cpu_gpr[gprn]); } -static void spr_write_40x_dbcr0 (void *opaque, int sprn) +static void spr_write_40x_dbcr0 (void *opaque, int sprn, int gprn) { DisasContext *ctx = opaque; - gen_op_store_40x_dbcr0(); + gen_helper_store_40x_dbcr0(cpu_gpr[gprn]); /* We must stop translation as we may have rebooted */ - GEN_STOP(ctx); + gen_stop_exception(ctx); } -static void spr_write_40x_sler (void *opaque, int sprn) +static void spr_write_40x_sler (void *opaque, int sprn, int gprn) { - gen_op_store_40x_sler(); + gen_helper_store_40x_sler(cpu_gpr[gprn]); } -static void spr_write_booke_tcr (void *opaque, int sprn) +static void spr_write_booke_tcr (void *opaque, int sprn, int gprn) { - gen_op_store_booke_tcr(); + gen_helper_store_booke_tcr(cpu_gpr[gprn]); } -static void spr_write_booke_tsr (void *opaque, int sprn) +static void spr_write_booke_tsr (void *opaque, int sprn, int gprn) { - gen_op_store_booke_tsr(); + gen_helper_store_booke_tsr(cpu_gpr[gprn]); } #endif /* PowerPC 403 specific registers */ /* PBL1 / PBU1 / PBL2 / PBU2 */ #if !defined(CONFIG_USER_ONLY) -static void spr_read_403_pbr (void *opaque, int sprn) +static void spr_read_403_pbr (void *opaque, int gprn, int sprn) { - gen_op_load_403_pb(sprn - SPR_403_PBL1); + tcg_gen_ld_tl(cpu_gpr[gprn], cpu_env, offsetof(CPUState, pb[sprn - SPR_403_PBL1])); } -static void spr_write_403_pbr (void *opaque, int sprn) +static void spr_write_403_pbr (void *opaque, int sprn, int gprn) { - gen_op_store_403_pb(sprn - SPR_403_PBL1); + TCGv_i32 t0 = tcg_const_i32(sprn - SPR_403_PBL1); + gen_helper_store_403_pbr(t0, cpu_gpr[gprn]); + tcg_temp_free_i32(t0); } -static void spr_write_pir (void *opaque, int sprn) +static void spr_write_pir (void *opaque, int sprn, int gprn) { - gen_op_store_pir(); + TCGv t0 = tcg_temp_new(); + tcg_gen_andi_tl(t0, cpu_gpr[gprn], 0xF); + gen_store_spr(SPR_PIR, t0); + tcg_temp_free(t0); } #endif #if !defined(CONFIG_USER_ONLY) /* Callback used to write the exception vector base */ -static void spr_write_excp_prefix (void *opaque, int sprn) +static void spr_write_excp_prefix (void *opaque, int sprn, int gprn) { - gen_op_store_excp_prefix(); - gen_op_store_spr(sprn); + TCGv t0 = tcg_temp_new(); + tcg_gen_ld_tl(t0, cpu_env, offsetof(CPUState, ivpr_mask)); + tcg_gen_and_tl(t0, t0, cpu_gpr[gprn]); + tcg_gen_st_tl(t0, cpu_env, offsetof(CPUState, excp_prefix)); + gen_store_spr(sprn, t0); } -static void spr_write_excp_vector (void *opaque, int sprn) +static void spr_write_excp_vector (void *opaque, int sprn, int gprn) { DisasContext *ctx = opaque; if (sprn >= SPR_BOOKE_IVOR0 && sprn <= SPR_BOOKE_IVOR15) { - gen_op_store_excp_vector(sprn - SPR_BOOKE_IVOR0); - gen_op_store_spr(sprn); + TCGv t0 = tcg_temp_new(); + tcg_gen_ld_tl(t0, cpu_env, offsetof(CPUState, ivor_mask)); + tcg_gen_and_tl(t0, t0, cpu_gpr[gprn]); + tcg_gen_st_tl(t0, cpu_env, offsetof(CPUState, excp_vectors[sprn - SPR_BOOKE_IVOR0])); + gen_store_spr(sprn, t0); + tcg_temp_free(t0); } else if (sprn >= SPR_BOOKE_IVOR32 && sprn <= SPR_BOOKE_IVOR37) { - gen_op_store_excp_vector(sprn - SPR_BOOKE_IVOR32 + 32); - gen_op_store_spr(sprn); + TCGv t0 = tcg_temp_new(); + tcg_gen_ld_tl(t0, cpu_env, offsetof(CPUState, ivor_mask)); + tcg_gen_and_tl(t0, t0, cpu_gpr[gprn]); + tcg_gen_st_tl(t0, cpu_env, offsetof(CPUState, excp_vectors[sprn - SPR_BOOKE_IVOR32 + 32])); + gen_store_spr(sprn, t0); + tcg_temp_free(t0); } else { printf("Trying to write an unknown exception vector %d %03x\n", sprn, sprn); - GEN_EXCP_PRIVREG(ctx); + gen_inval_exception(ctx, POWERPC_EXCP_PRIV_REG); } } #endif @@ -434,16 +479,16 @@ do { \ } while (0) static inline void _spr_register (CPUPPCState *env, int num, const char *name, - void (*uea_read)(void *opaque, int sprn), - void (*uea_write)(void *opaque, int sprn), + void (*uea_read)(void *opaque, int gprn, int sprn), + void (*uea_write)(void *opaque, int sprn, int gprn), target_ulong initial_value) #else static inline void spr_register (CPUPPCState *env, int num, const char *name, - void (*uea_read)(void *opaque, int sprn), - void (*uea_write)(void *opaque, int sprn), - void (*oea_read)(void *opaque, int sprn), - void (*oea_write)(void *opaque, int sprn), + void (*uea_read)(void *opaque, int gprn, int sprn), + void (*uea_write)(void *opaque, int sprn, int gprn), + void (*oea_read)(void *opaque, int gprn, int sprn), + void (*oea_write)(void *opaque, int sprn, int gprn), target_ulong initial_value) #endif { diff --git a/qemu/target-sh4/cpu.h b/qemu/target-sh4/cpu.h index 23ecded5..226417f3 100644 --- a/qemu/target-sh4/cpu.h +++ b/qemu/target-sh4/cpu.h @@ -33,6 +33,7 @@ #define SH_CPU_SH7750R (1 << 2) #define SH_CPU_SH7751 (1 << 3) #define SH_CPU_SH7751R (1 << 4) +#define SH_CPU_SH7785 (1 << 5) #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) @@ -48,6 +49,10 @@ #define SR_FD (1 << 15) #define SR_M (1 << 9) #define SR_Q (1 << 8) +#define SR_I3 (1 << 7) +#define SR_I2 (1 << 6) +#define SR_I1 (1 << 5) +#define SR_I0 (1 << 4) #define SR_S (1 << 1) #define SR_T (1 << 0) @@ -88,6 +93,10 @@ typedef struct tlb_t { #define NB_MMU_MODES 2 +enum sh_features { + SH_FEATURE_SH4A = 1, +}; + typedef struct CPUSH4State { int id; /* CPU model */ @@ -112,6 +121,9 @@ typedef struct CPUSH4State { /* float point status register */ float_status fp_status; + /* The features that we should emulate. See sh_features above. */ + uint32_t features; + /* Those belong to the specific unit (SH7750) but are handled here */ uint32_t mmucr; /* MMU control register */ uint32_t pteh; /* page table entry high register */ @@ -137,6 +149,10 @@ CPUSH4State *cpu_sh4_init(const char *cpu_model); int cpu_sh4_exec(CPUSH4State * s); int cpu_sh4_signal_handler(int host_signum, void *pinfo, void *puc); +int cpu_sh4_handle_mmu_fault(CPUSH4State * env, target_ulong address, int rw, + int mmu_idx, int is_softmmu); +void do_interrupt(CPUSH4State * env); + void sh4_cpu_list(FILE *f, int (*cpu_fprintf)(FILE *f, const char *fmt, ...)); void cpu_sh4_write_mmaped_utlb_addr(CPUSH4State *s, target_phys_addr_t addr, uint32_t mem_value); @@ -279,7 +295,8 @@ static inline void cpu_get_tb_cpu_state(CPUState *env, target_ulong *pc, *flags = (env->flags & (DELAY_SLOT | DELAY_SLOT_CONDITIONAL | DELAY_SLOT_TRUE | DELAY_SLOT_CLEARME)) /* Bits 0- 3 */ | (env->fpscr & (FPSCR_FR | FPSCR_SZ | FPSCR_PR)) /* Bits 19-21 */ - | (env->sr & (SR_MD | SR_RB)); /* Bits 29-30 */ + | (env->sr & (SR_MD | SR_RB)) /* Bits 29-30 */ + | (env->sr & SR_FD); /* Bit 15 */ } #endif /* _CPU_SH4_H */ diff --git a/qemu/target-sh4/exec.h b/qemu/target-sh4/exec.h index 61226108..70297841 100644 --- a/qemu/target-sh4/exec.h +++ b/qemu/target-sh4/exec.h @@ -43,8 +43,6 @@ static inline int cpu_halted(CPUState *env) { #include "softmmu_exec.h" #endif -#define RETURN() __asm__ __volatile__("") - static inline void regs_to_env(void) { /* XXXXX */ @@ -55,14 +53,10 @@ static inline void env_to_regs(void) /* XXXXX */ } -int cpu_sh4_handle_mmu_fault(CPUState * env, target_ulong address, int rw, - int mmu_idx, int is_softmmu); void cpu_load_tlb(CPUState * env); int find_itlb_entry(CPUState * env, target_ulong address, int use_asid, int update); int find_utlb_entry(CPUState * env, target_ulong address, int use_asid); -void do_interrupt(CPUState * env); - #endif /* _EXEC_SH4_H */ diff --git a/qemu/target-sh4/helper.c b/qemu/target-sh4/helper.c index c536015c..882bc9c5 100644 --- a/qemu/target-sh4/helper.c +++ b/qemu/target-sh4/helper.c @@ -255,7 +255,7 @@ static int find_tlb_entry(CPUState * env, target_ulong address, for (i = 0; i < nbtlb; i++) { if (!entries[i].v) continue; /* Invalid entry */ - if (use_asid && entries[i].asid != asid) + if (!entries[i].sh && use_asid && entries[i].asid != asid) continue; /* Bad ASID */ #if 0 switch (entries[i].sz) { @@ -439,16 +439,7 @@ int get_physical_address(CPUState * env, target_ulong * physical, if (address >= 0x80000000 && address < 0xc0000000) { /* Mask upper 3 bits for P1 and P2 areas */ *physical = address & 0x1fffffff; - } else if (address >= 0xfc000000) { - /* - * Mask upper 3 bits for control registers in P4 area, - * to unify access to control registers via P0-P3 area. - * The addresses for cache store queue, TLB address array - * are not masked. - */ - *physical = address & 0x1fffffff; } else { - /* access to cache store queue, or TLB address array. */ *physical = address; } *prot = PAGE_READ | PAGE_WRITE; @@ -547,9 +538,6 @@ void cpu_load_tlb(CPUState * env) } } - /* per utlb access cannot implemented. */ - increment_urc(env); - /* Take values into cpu status from registers. */ entry->asid = (uint8_t)cpu_pteh_asid(env->pteh); entry->vpn = cpu_pteh_vpn(env->pteh); @@ -590,6 +578,7 @@ void cpu_sh4_write_mmaped_utlb_addr(CPUSH4State *s, target_phys_addr_t addr, uint8_t d = (uint8_t)((mem_value & 0x00000200) >> 9); uint8_t v = (uint8_t)((mem_value & 0x00000100) >> 8); uint8_t asid = (uint8_t)(mem_value & 0x000000ff); + int use_asid = (s->mmucr & MMUCR_SV) == 0 || (s->sr & SR_MD) == 0; if (associate) { int i; @@ -602,7 +591,8 @@ void cpu_sh4_write_mmaped_utlb_addr(CPUSH4State *s, target_phys_addr_t addr, if (!entry->v) continue; - if (entry->vpn == vpn && entry->asid == asid) { + if (entry->vpn == vpn + && (!use_asid || entry->asid == asid || entry->sh)) { if (utlb_match_entry) { /* Multiple TLB Exception */ s->exception_index = 0x140; @@ -621,7 +611,8 @@ void cpu_sh4_write_mmaped_utlb_addr(CPUSH4State *s, target_phys_addr_t addr, /* search ITLB */ for (i = 0; i < ITLB_SIZE; i++) { tlb_t * entry = &s->itlb[i]; - if (entry->vpn == vpn && entry->asid == asid) { + if (entry->vpn == vpn + && (!use_asid || entry->asid == asid || entry->sh)) { if (entry->v && !v) needs_tlb_flush = 1; if (utlb_match_entry) diff --git a/qemu/target-sh4/helper.h b/qemu/target-sh4/helper.h index e8fd050e..631e7e19 100644 --- a/qemu/target-sh4/helper.h +++ b/qemu/target-sh4/helper.h @@ -3,6 +3,8 @@ DEF_HELPER_0(ldtlb, void) DEF_HELPER_0(raise_illegal_instruction, void) DEF_HELPER_0(raise_slot_illegal_instruction, void) +DEF_HELPER_0(raise_fpu_disable, void) +DEF_HELPER_0(raise_slot_fpu_disable, void) DEF_HELPER_0(debug, void) DEF_HELPER_1(sleep, void, i32) DEF_HELPER_1(trapa, void, i32) diff --git a/qemu/target-sh4/op_helper.c b/qemu/target-sh4/op_helper.c index f3e73004..63522194 100644 --- a/qemu/target-sh4/op_helper.c +++ b/qemu/target-sh4/op_helper.c @@ -89,6 +89,18 @@ void helper_raise_slot_illegal_instruction(void) cpu_loop_exit(); } +void helper_raise_fpu_disable(void) +{ + env->exception_index = 0x800; + cpu_loop_exit(); +} + +void helper_raise_slot_fpu_disable(void) +{ + env->exception_index = 0x820; + cpu_loop_exit(); +} + void helper_debug(void) { env->exception_index = EXCP_DEBUG; diff --git a/qemu/target-sh4/translate.c b/qemu/target-sh4/translate.c index 505b1969..2d3981c2 100644 --- a/qemu/target-sh4/translate.c +++ b/qemu/target-sh4/translate.c @@ -49,6 +49,7 @@ typedef struct DisasContext { int memidx; uint32_t delayed_pc; int singlestep_enabled; + uint32_t features; } DisasContext; #if defined(CONFIG_USER_ONLY) @@ -71,7 +72,7 @@ static TCGv_ptr cpu_env; static TCGv cpu_gregs[24]; static TCGv cpu_pc, cpu_sr, cpu_ssr, cpu_spc, cpu_gbr; static TCGv cpu_vbr, cpu_sgr, cpu_dbr, cpu_mach, cpu_macl; -static TCGv cpu_pr, cpu_fpscr, cpu_fpul, cpu_flags; +static TCGv cpu_pr, cpu_fpscr, cpu_fpul; static TCGv cpu_fregs[32]; /* internal register indexes */ @@ -181,12 +182,12 @@ void cpu_dump_state(CPUState * env, FILE * f, } } -void cpu_sh4_reset(CPUSH4State * env) +static void cpu_sh4_reset(CPUSH4State * env) { #if defined(CONFIG_USER_ONLY) - env->sr = SR_FD; /* FD - kernel does lazy fpu context switch */ + env->sr = 0; #else - env->sr = 0x700000F0; /* MD, RB, BL, I3-I0 */ + env->sr = SR_MD | SR_RB | SR_BL | SR_I3 | SR_I2 | SR_I1 | SR_I0; #endif env->vbr = 0; env->pc = 0xA0000000; @@ -206,6 +207,7 @@ typedef struct { uint32_t pvr; uint32_t prr; uint32_t cvr; + uint32_t features; } sh4_def_t; static sh4_def_t sh4_defs[] = { @@ -221,7 +223,14 @@ static sh4_def_t sh4_defs[] = { .pvr = 0x04050005, .prr = 0x00000113, .cvr = 0x00110000, /* Neutered caches, should be 0x20480000 */ - }, + }, { + .name = "SH7785", + .id = SH_CPU_SH7785, + .pvr = 0x10300700, + .prr = 0x00000200, + .cvr = 0x71440211, + .features = SH_FEATURE_SH4A, + }, }; static const sh4_def_t *cpu_sh4_find_by_name(const char *name) @@ -265,6 +274,7 @@ CPUSH4State *cpu_sh4_init(const char *cpu_model) env = qemu_mallocz(sizeof(CPUSH4State)); if (!env) return NULL; + env->features = def->features; cpu_exec_init(env); sh4_translate_init(); env->cpu_model_str = cpu_model; @@ -447,22 +457,41 @@ static inline void gen_store_fpr64 (TCGv_i64 t, int reg) #define DREG(x) FREG(x) /* Assumes lsb of (x) is always 0 */ #define CHECK_NOT_DELAY_SLOT \ - if (ctx->flags & (DELAY_SLOT | DELAY_SLOT_CONDITIONAL)) \ - {gen_helper_raise_slot_illegal_instruction(); ctx->bstate = BS_EXCP; \ - return;} + if (ctx->flags & (DELAY_SLOT | DELAY_SLOT_CONDITIONAL)) \ + { \ + tcg_gen_movi_i32(cpu_pc, ctx->pc-2); \ + gen_helper_raise_slot_illegal_instruction(); \ + ctx->bstate = BS_EXCP; \ + return; \ + } #define CHECK_PRIVILEGED \ if (IS_USER(ctx)) { \ + tcg_gen_movi_i32(cpu_pc, ctx->pc); \ gen_helper_raise_illegal_instruction(); \ ctx->bstate = BS_EXCP; \ return; \ } +#define CHECK_FPU_ENABLED \ + if (ctx->flags & SR_FD) { \ + if (ctx->flags & (DELAY_SLOT | DELAY_SLOT_CONDITIONAL)) { \ + tcg_gen_movi_i32(cpu_pc, ctx->pc-2); \ + gen_helper_raise_slot_fpu_disable(); \ + } else { \ + tcg_gen_movi_i32(cpu_pc, ctx->pc); \ + gen_helper_raise_fpu_disable(); \ + } \ + ctx->bstate = BS_EXCP; \ + return; \ + } + static void _decode_opc(DisasContext * ctx) { #if 0 fprintf(stderr, "Translating opcode 0x%04x\n", ctx->opcode); #endif + switch (ctx->opcode) { case 0x0019: /* div0u */ tcg_gen_andi_i32(cpu_sr, cpu_sr, ~(SR_M | SR_Q | SR_T)); @@ -980,6 +1009,7 @@ static void _decode_opc(DisasContext * ctx) tcg_gen_xor_i32(REG(B11_8), REG(B11_8), REG(B7_4)); return; case 0xf00c: /* fmov {F,D,X}Rm,{F,D,X}Rn - FPSCR: Nothing */ + CHECK_FPU_ENABLED if (ctx->fpscr & FPSCR_SZ) { TCGv_i64 fp = tcg_temp_new_i64(); gen_load_fpr64(fp, XREG(B7_4)); @@ -990,6 +1020,7 @@ static void _decode_opc(DisasContext * ctx) } return; case 0xf00a: /* fmov {F,D,X}Rm,@Rn - FPSCR: Nothing */ + CHECK_FPU_ENABLED if (ctx->fpscr & FPSCR_SZ) { TCGv addr_hi = tcg_temp_new(); int fr = XREG(B7_4); @@ -1002,6 +1033,7 @@ static void _decode_opc(DisasContext * ctx) } return; case 0xf008: /* fmov @Rm,{F,D,X}Rn - FPSCR: Nothing */ + CHECK_FPU_ENABLED if (ctx->fpscr & FPSCR_SZ) { TCGv addr_hi = tcg_temp_new(); int fr = XREG(B11_8); @@ -1014,6 +1046,7 @@ static void _decode_opc(DisasContext * ctx) } return; case 0xf009: /* fmov @Rm+,{F,D,X}Rn - FPSCR: Nothing */ + CHECK_FPU_ENABLED if (ctx->fpscr & FPSCR_SZ) { TCGv addr_hi = tcg_temp_new(); int fr = XREG(B11_8); @@ -1028,6 +1061,7 @@ static void _decode_opc(DisasContext * ctx) } return; case 0xf00b: /* fmov {F,D,X}Rm,@-Rn - FPSCR: Nothing */ + CHECK_FPU_ENABLED if (ctx->fpscr & FPSCR_SZ) { TCGv addr = tcg_temp_new_i32(); int fr = XREG(B7_4); @@ -1047,6 +1081,7 @@ static void _decode_opc(DisasContext * ctx) } return; case 0xf006: /* fmov @(R0,Rm),{F,D,X}Rm - FPSCR: Nothing */ + CHECK_FPU_ENABLED { TCGv addr = tcg_temp_new_i32(); tcg_gen_add_i32(addr, REG(B7_4), REG(0)); @@ -1062,6 +1097,7 @@ static void _decode_opc(DisasContext * ctx) } return; case 0xf007: /* fmov {F,D,X}Rn,@(R0,Rn) - FPSCR: Nothing */ + CHECK_FPU_ENABLED { TCGv addr = tcg_temp_new(); tcg_gen_add_i32(addr, REG(B11_8), REG(0)); @@ -1083,6 +1119,7 @@ static void _decode_opc(DisasContext * ctx) case 0xf004: /* fcmp/eq Rm,Rn - FPSCR: R[PR,Enable.V]/W[Cause,Flag] */ case 0xf005: /* fcmp/gt Rm,Rn - FPSCR: R[PR,Enable.V]/W[Cause,Flag] */ { + CHECK_FPU_ENABLED if (ctx->fpscr & FPSCR_PR) { TCGv_i64 fp0, fp1; @@ -1454,12 +1491,14 @@ static void _decode_opc(DisasContext * ctx) LDST(mach, 0x400a, 0x4006, 0x000a, 0x4002, {}) LDST(macl, 0x401a, 0x4016, 0x001a, 0x4012, {}) LDST(pr, 0x402a, 0x4026, 0x002a, 0x4022, {}) - LDST(fpul, 0x405a, 0x4056, 0x005a, 0x4052, {}) + LDST(fpul, 0x405a, 0x4056, 0x005a, 0x4052, {CHECK_FPU_ENABLED}) case 0x406a: /* lds Rm,FPSCR */ + CHECK_FPU_ENABLED gen_helper_ld_fpscr(REG(B11_8)); ctx->bstate = BS_STOP; return; case 0x4066: /* lds.l @Rm+,FPSCR */ + CHECK_FPU_ENABLED { TCGv addr = tcg_temp_new(); tcg_gen_qemu_ld32s(addr, REG(B11_8), ctx->memidx); @@ -1470,9 +1509,11 @@ static void _decode_opc(DisasContext * ctx) } return; case 0x006a: /* sts FPSCR,Rn */ + CHECK_FPU_ENABLED tcg_gen_andi_i32(REG(B11_8), cpu_fpscr, 0x003fffff); return; case 0x4062: /* sts FPSCR,@-Rn */ + CHECK_FPU_ENABLED { TCGv addr, val; val = tcg_temp_new(); @@ -1525,6 +1566,21 @@ static void _decode_opc(DisasContext * ctx) return; case 0x0083: /* pref @Rn */ return; + case 0x00d3: /* prefi @Rn */ + if (ctx->features & SH_FEATURE_SH4A) + return; + else + break; + case 0x00e3: /* icbi @Rn */ + if (ctx->features & SH_FEATURE_SH4A) + return; + else + break; + case 0x00ab: /* synco */ + if (ctx->features & SH_FEATURE_SH4A) + return; + else + break; case 0x4024: /* rotcl Rn */ { TCGv tmp = tcg_temp_new(); @@ -1601,16 +1657,15 @@ static void _decode_opc(DisasContext * ctx) } return; case 0xf00d: /* fsts FPUL,FRn - FPSCR: Nothing */ - { - tcg_gen_mov_i32(cpu_fregs[FREG(B11_8)], cpu_fpul); - } + CHECK_FPU_ENABLED + tcg_gen_mov_i32(cpu_fregs[FREG(B11_8)], cpu_fpul); return; case 0xf01d: /* flds FRm,FPUL - FPSCR: Nothing */ - { - tcg_gen_mov_i32(cpu_fpul, cpu_fregs[FREG(B11_8)]); - } + CHECK_FPU_ENABLED + tcg_gen_mov_i32(cpu_fpul, cpu_fregs[FREG(B11_8)]); return; case 0xf02d: /* float FPUL,FRn/DRn - FPSCR: R[PR,Enable.I]/W[Cause,Flag] */ + CHECK_FPU_ENABLED if (ctx->fpscr & FPSCR_PR) { TCGv_i64 fp; if (ctx->opcode & 0x0100) @@ -1625,6 +1680,7 @@ static void _decode_opc(DisasContext * ctx) } return; case 0xf03d: /* ftrc FRm/DRm,FPUL - FPSCR: R[PR,Enable.V]/W[Cause,Flag] */ + CHECK_FPU_ENABLED if (ctx->fpscr & FPSCR_PR) { TCGv_i64 fp; if (ctx->opcode & 0x0100) @@ -1639,11 +1695,13 @@ static void _decode_opc(DisasContext * ctx) } return; case 0xf04d: /* fneg FRn/DRn - FPSCR: Nothing */ + CHECK_FPU_ENABLED { gen_helper_fneg_T(cpu_fregs[FREG(B11_8)], cpu_fregs[FREG(B11_8)]); } return; case 0xf05d: /* fabs FRn/DRn */ + CHECK_FPU_ENABLED if (ctx->fpscr & FPSCR_PR) { if (ctx->opcode & 0x0100) break; /* illegal instruction */ @@ -1657,6 +1715,7 @@ static void _decode_opc(DisasContext * ctx) } return; case 0xf06d: /* fsqrt FRn */ + CHECK_FPU_ENABLED if (ctx->fpscr & FPSCR_PR) { if (ctx->opcode & 0x0100) break; /* illegal instruction */ @@ -1670,18 +1729,22 @@ static void _decode_opc(DisasContext * ctx) } return; case 0xf07d: /* fsrra FRn */ + CHECK_FPU_ENABLED break; case 0xf08d: /* fldi0 FRn - FPSCR: R[PR] */ + CHECK_FPU_ENABLED if (!(ctx->fpscr & FPSCR_PR)) { tcg_gen_movi_i32(cpu_fregs[FREG(B11_8)], 0); } return; case 0xf09d: /* fldi1 FRn - FPSCR: R[PR] */ + CHECK_FPU_ENABLED if (!(ctx->fpscr & FPSCR_PR)) { tcg_gen_movi_i32(cpu_fregs[FREG(B11_8)], 0x3f800000); } return; case 0xf0ad: /* fcnvsd FPUL,DRn */ + CHECK_FPU_ENABLED { TCGv_i64 fp = tcg_temp_new_i64(); gen_helper_fcnvsd_FT_DT(fp, cpu_fpul); @@ -1690,6 +1753,7 @@ static void _decode_opc(DisasContext * ctx) } return; case 0xf0bd: /* fcnvds DRn,FPUL */ + CHECK_FPU_ENABLED { TCGv_i64 fp = tcg_temp_new_i64(); gen_load_fpr64(fp, DREG(B11_8)); @@ -1698,9 +1762,11 @@ static void _decode_opc(DisasContext * ctx) } return; } - +#if 0 fprintf(stderr, "unknown instruction 0x%04x at pc 0x%08x\n", ctx->opcode, ctx->pc); + fflush(stderr); +#endif gen_helper_raise_illegal_instruction(); ctx->bstate = BS_EXCP; } @@ -1760,6 +1826,7 @@ gen_intermediate_code_internal(CPUState * env, TranslationBlock * tb, ctx.delayed_pc = -1; /* use delayed pc from env pointer */ ctx.tb = tb; ctx.singlestep_enabled = env->singlestep_enabled; + ctx.features = env->features; #ifdef DEBUG_DISAS if (loglevel & CPU_LOG_TB_CPU) { diff --git a/qemu/target-sparc/TODO b/qemu/target-sparc/TODO index 62b0f47d..c87459f5 100644 --- a/qemu/target-sparc/TODO +++ b/qemu/target-sparc/TODO @@ -86,4 +86,3 @@ Sun4u: Sun4v: - A lot of unimplemented features - A lot of real machine types - diff --git a/qemu/target-sparc/machine.c b/qemu/target-sparc/machine.c index 417523f8..e845fac3 100644 --- a/qemu/target-sparc/machine.c +++ b/qemu/target-sparc/machine.c @@ -220,5 +220,3 @@ int cpu_load(QEMUFile *f, void *opaque, int version_id) tlb_flush(env, 1); return 0; } - - diff --git a/qemu/target-sparc/op_helper.c b/qemu/target-sparc/op_helper.c index d3c50299..15f259da 100644 --- a/qemu/target-sparc/op_helper.c +++ b/qemu/target-sparc/op_helper.c @@ -49,7 +49,7 @@ static inline void address_mask(CPUState *env1, target_ulong *addr) #endif } -void raise_exception(int tt) +static void raise_exception(int tt) { env->exception_index = tt; cpu_loop_exit(); diff --git a/qemu/tcg/README b/qemu/tcg/README index bdb44dfd..fcdb6014 100644 --- a/qemu/tcg/README +++ b/qemu/tcg/README @@ -60,9 +60,8 @@ add_i32 t0, t1, t2 (t0 <- t1 + t2) - Basic blocks end after branches (e.g. brcond_i32 instruction), goto_tb and exit_tb instructions. -- Basic blocks end before legacy dyngen operations. -- Basic blocks start after the end of a previous basic block, at a - set_label instruction or after a legacy dyngen operation. +- Basic blocks start after the end of a previous basic block, or at a + set_label instruction. After the end of a basic block, the content of temporaries is destroyed, but local temporaries and globals are preserved. @@ -423,18 +422,7 @@ register. target, functions must be able to return 2 values in registers for 64 bit return type. -5) Migration from dyngen to TCG - -TCG is backward compatible with QEMU "dyngen" operations. It means -that TCG instructions can be freely mixed with dyngen operations. It -is expected that QEMU targets will be progressively fully converted to -TCG. Once a target is fully converted to TCG, it will be possible -to apply more optimizations because more registers will be free for -the generated code. - -The exception model is the same as the dyngen one. - -6) Recommended coding rules for best performance +5) Recommended coding rules for best performance - Use globals to represent the parts of the QEMU CPU state which are often modified, e.g. the integer registers and the condition @@ -442,8 +430,7 @@ The exception model is the same as the dyngen one. - Avoid globals stored in fixed registers. They must be used only to store the pointer to the CPU state and possibly to store a pointer - to a register window. The other uses are to ensure backward - compatibility with dyngen during the porting a new target to TCG. + to a register window. - Use temporaries. Use local temporaries only when really needed, e.g. when you need to use a value after a jump. Local temporaries diff --git a/qemu/tcg/arm/tcg-target.c b/qemu/tcg/arm/tcg-target.c index c4cae8a3..8e99dd09 100644 --- a/qemu/tcg/arm/tcg-target.c +++ b/qemu/tcg/arm/tcg-target.c @@ -858,10 +858,10 @@ static inline void tcg_out_qemu_ld(TCGContext *s, int cond, else data_reg2 = 0; /* surpress warning */ addr_reg = *args++; -#if TARGET_LONG_BITS == 64 - addr_reg2 = *args++; -#endif #ifdef CONFIG_SOFTMMU +# if TARGET_LONG_BITS == 64 + addr_reg2 = *args++; +# endif mem_index = *args; s_bits = opc & 3; @@ -1036,10 +1036,10 @@ static inline void tcg_out_qemu_st(TCGContext *s, int cond, else data_reg2 = 0; /* surpress warning */ addr_reg = *args++; -#if TARGET_LONG_BITS == 64 - addr_reg2 = *args++; -#endif #ifdef CONFIG_SOFTMMU +# if TARGET_LONG_BITS == 64 + addr_reg2 = *args++; +# endif mem_index = *args; s_bits = opc & 3; diff --git a/qemu/tcg/i386/tcg-target.c b/qemu/tcg/i386/tcg-target.c index fa0a2ca9..fc9c8a18 100644 --- a/qemu/tcg/i386/tcg-target.c +++ b/qemu/tcg/i386/tcg-target.c @@ -285,7 +285,7 @@ static inline void tgen_arithi(TCGContext *s, int c, int r0, int32_t val) } } -void tcg_out_addi(TCGContext *s, int reg, tcg_target_long val) +static void tcg_out_addi(TCGContext *s, int reg, tcg_target_long val) { if (val != 0) tgen_arithi(s, ARITH_ADD, reg, val); @@ -525,7 +525,13 @@ static void tcg_out_qemu_ld(TCGContext *s, const TCGArg *args, tcg_out_modrm(s, 0xbf | P_EXT, data_reg, TCG_REG_EAX); break; case 0: + /* movzbl */ + tcg_out_modrm(s, 0xb6 | P_EXT, data_reg, TCG_REG_EAX); + break; case 1: + /* movzwl */ + tcg_out_modrm(s, 0xb7 | P_EXT, data_reg, TCG_REG_EAX); + break; case 2: default: tcg_out_mov(s, data_reg, TCG_REG_EAX); diff --git a/qemu/tcg/ppc/tcg-target.h b/qemu/tcg/ppc/tcg-target.h index 1bc1dc38..551df9ec 100644 --- a/qemu/tcg/ppc/tcg-target.h +++ b/qemu/tcg/ppc/tcg-target.h @@ -86,24 +86,3 @@ enum { #define TCG_AREG1 TCG_REG_R24 #define TCG_AREG2 TCG_REG_R25 #define TCG_AREG3 TCG_REG_R26 - -/* taken directly from tcg-dyngen.c */ -#define MIN_CACHE_LINE_SIZE 8 /* conservative value */ - -static inline void flush_icache_range(unsigned long start, unsigned long stop) -{ - unsigned long p; - - start &= ~(MIN_CACHE_LINE_SIZE - 1); - stop = (stop + MIN_CACHE_LINE_SIZE - 1) & ~(MIN_CACHE_LINE_SIZE - 1); - - for (p = start; p < stop; p += MIN_CACHE_LINE_SIZE) { - asm volatile ("dcbst 0,%0" : : "r"(p) : "memory"); - } - asm volatile ("sync" : : : "memory"); - for (p = start; p < stop; p += MIN_CACHE_LINE_SIZE) { - asm volatile ("icbi 0,%0" : : "r"(p) : "memory"); - } - asm volatile ("sync" : : : "memory"); - asm volatile ("isync" : : : "memory"); -} diff --git a/qemu/tcg/ppc64/tcg-target.h b/qemu/tcg/ppc64/tcg-target.h index 2174db23..eaade01b 100644 --- a/qemu/tcg/ppc64/tcg-target.h +++ b/qemu/tcg/ppc64/tcg-target.h @@ -82,24 +82,3 @@ enum { #define TCG_AREG1 TCG_REG_R24 #define TCG_AREG2 TCG_REG_R25 #define TCG_AREG3 TCG_REG_R26 - -/* taken directly from tcg-dyngen.c */ -#define MIN_CACHE_LINE_SIZE 8 /* conservative value */ - -static inline void flush_icache_range(unsigned long start, unsigned long stop) -{ - unsigned long p; - - start &= ~(MIN_CACHE_LINE_SIZE - 1); - stop = (stop + MIN_CACHE_LINE_SIZE - 1) & ~(MIN_CACHE_LINE_SIZE - 1); - - for (p = start; p < stop; p += MIN_CACHE_LINE_SIZE) { - asm volatile ("dcbst 0,%0" : : "r"(p) : "memory"); - } - asm volatile ("sync" : : : "memory"); - for (p = start; p < stop; p += MIN_CACHE_LINE_SIZE) { - asm volatile ("icbi 0,%0" : : "r"(p) : "memory"); - } - asm volatile ("sync" : : : "memory"); - asm volatile ("isync" : : : "memory"); -} diff --git a/qemu/tcg/tcg-dyngen.c b/qemu/tcg/tcg-dyngen.c deleted file mode 100644 index b4ceb5e5..00000000 --- a/qemu/tcg/tcg-dyngen.c +++ /dev/null @@ -1,431 +0,0 @@ -/* - * Tiny Code Generator for QEMU - * - * Copyright (c) 2008 Fabrice Bellard - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * 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 <assert.h> -#include <stdarg.h> -#include <stdlib.h> -#include <stdio.h> -#include <string.h> -#include <inttypes.h> - -#include "config.h" -#include "osdep.h" - -#include "tcg.h" - -int __op_param1, __op_param2, __op_param3; -#if defined(__sparc__) || defined(__arm__) - void __op_gen_label1(){} - void __op_gen_label2(){} - void __op_gen_label3(){} -#else - int __op_gen_label1, __op_gen_label2, __op_gen_label3; -#endif -int __op_jmp0, __op_jmp1, __op_jmp2, __op_jmp3; - -#if 0 -#if defined(__s390__) -static inline void flush_icache_range(unsigned long start, unsigned long stop) -{ -} -#elif defined(__ia64__) -static inline void flush_icache_range(unsigned long start, unsigned long stop) -{ - while (start < stop) { - asm volatile ("fc %0" :: "r"(start)); - start += 32; - } - asm volatile (";;sync.i;;srlz.i;;"); -} -#elif defined(__powerpc__) - -#define MIN_CACHE_LINE_SIZE 8 /* conservative value */ - -static inline void flush_icache_range(unsigned long start, unsigned long stop) -{ - unsigned long p; - - start &= ~(MIN_CACHE_LINE_SIZE - 1); - stop = (stop + MIN_CACHE_LINE_SIZE - 1) & ~(MIN_CACHE_LINE_SIZE - 1); - - for (p = start; p < stop; p += MIN_CACHE_LINE_SIZE) { - asm volatile ("dcbst 0,%0" : : "r"(p) : "memory"); - } - asm volatile ("sync" : : : "memory"); - for (p = start; p < stop; p += MIN_CACHE_LINE_SIZE) { - asm volatile ("icbi 0,%0" : : "r"(p) : "memory"); - } - asm volatile ("sync" : : : "memory"); - asm volatile ("isync" : : : "memory"); -} -#elif defined(__alpha__) -static inline void flush_icache_range(unsigned long start, unsigned long stop) -{ - asm ("imb"); -} -#elif defined(__sparc__) -static inline void flush_icache_range(unsigned long start, unsigned long stop) -{ - unsigned long p; - - p = start & ~(8UL - 1UL); - stop = (stop + (8UL - 1UL)) & ~(8UL - 1UL); - - for (; p < stop; p += 8) - __asm__ __volatile__("flush\t%0" : : "r" (p)); -} -#elif defined(__arm__) -static inline void flush_icache_range(unsigned long start, unsigned long stop) -{ - register unsigned long _beg __asm ("a1") = start; - register unsigned long _end __asm ("a2") = stop; - register unsigned long _flg __asm ("a3") = 0; - __asm __volatile__ ("swi 0x9f0002" : : "r" (_beg), "r" (_end), "r" (_flg)); -} -#elif defined(__mc68000) - -# include <asm/cachectl.h> -static inline void flush_icache_range(unsigned long start, unsigned long stop) -{ - cacheflush(start,FLUSH_SCOPE_LINE,FLUSH_CACHE_BOTH,stop-start+16); -} -#elif defined(__mips__) - -#include <sys/cachectl.h> -static inline void flush_icache_range(unsigned long start, unsigned long stop) -{ - _flush_cache ((void *)start, stop - start, BCACHE); -} -#else -#error unsupported CPU -#endif - -#ifdef __alpha__ - -register int gp asm("$29"); - -static inline void immediate_ldah(void *p, int val) { - uint32_t *dest = p; - long high = ((val >> 16) + ((val >> 15) & 1)) & 0xffff; - - *dest &= ~0xffff; - *dest |= high; - *dest |= 31 << 16; -} -static inline void immediate_lda(void *dest, int val) { - *(uint16_t *) dest = val; -} -void fix_bsr(void *p, int offset) { - uint32_t *dest = p; - *dest &= ~((1 << 21) - 1); - *dest |= (offset >> 2) & ((1 << 21) - 1); -} - -#endif /* __alpha__ */ - -#ifdef __ia64 - -/* Patch instruction with "val" where "mask" has 1 bits. */ -static inline void ia64_patch (uint64_t insn_addr, uint64_t mask, uint64_t val) -{ - uint64_t m0, m1, v0, v1, b0, b1, *b = (uint64_t *) (insn_addr & -16); -# define insn_mask ((1UL << 41) - 1) - unsigned long shift; - - b0 = b[0]; b1 = b[1]; - shift = 5 + 41 * (insn_addr % 16); /* 5 template, 3 x 41-bit insns */ - if (shift >= 64) { - m1 = mask << (shift - 64); - v1 = val << (shift - 64); - } else { - m0 = mask << shift; m1 = mask >> (64 - shift); - v0 = val << shift; v1 = val >> (64 - shift); - b[0] = (b0 & ~m0) | (v0 & m0); - } - b[1] = (b1 & ~m1) | (v1 & m1); -} - -static inline void ia64_patch_imm60 (uint64_t insn_addr, uint64_t val) -{ - ia64_patch(insn_addr, - 0x011ffffe000UL, - ( ((val & 0x0800000000000000UL) >> 23) /* bit 59 -> 36 */ - | ((val & 0x00000000000fffffUL) << 13) /* bit 0 -> 13 */)); - ia64_patch(insn_addr - 1, 0x1fffffffffcUL, val >> 18); -} - -static inline void ia64_imm64 (void *insn, uint64_t val) -{ - /* Ignore the slot number of the relocation; GCC and Intel - toolchains differed for some time on whether IMM64 relocs are - against slot 1 (Intel) or slot 2 (GCC). */ - uint64_t insn_addr = (uint64_t) insn & ~3UL; - - ia64_patch(insn_addr + 2, - 0x01fffefe000UL, - ( ((val & 0x8000000000000000UL) >> 27) /* bit 63 -> 36 */ - | ((val & 0x0000000000200000UL) << 0) /* bit 21 -> 21 */ - | ((val & 0x00000000001f0000UL) << 6) /* bit 16 -> 22 */ - | ((val & 0x000000000000ff80UL) << 20) /* bit 7 -> 27 */ - | ((val & 0x000000000000007fUL) << 13) /* bit 0 -> 13 */) - ); - ia64_patch(insn_addr + 1, 0x1ffffffffffUL, val >> 22); -} - -static inline void ia64_imm60b (void *insn, uint64_t val) -{ - /* Ignore the slot number of the relocation; GCC and Intel - toolchains differed for some time on whether IMM64 relocs are - against slot 1 (Intel) or slot 2 (GCC). */ - uint64_t insn_addr = (uint64_t) insn & ~3UL; - - if (val + ((uint64_t) 1 << 59) >= (1UL << 60)) - fprintf(stderr, "%s: value %ld out of IMM60 range\n", - __FUNCTION__, (int64_t) val); - ia64_patch_imm60(insn_addr + 2, val); -} - -static inline void ia64_imm22 (void *insn, uint64_t val) -{ - if (val + (1 << 21) >= (1 << 22)) - fprintf(stderr, "%s: value %li out of IMM22 range\n", - __FUNCTION__, (int64_t)val); - ia64_patch((uint64_t) insn, 0x01fffcfe000UL, - ( ((val & 0x200000UL) << 15) /* bit 21 -> 36 */ - | ((val & 0x1f0000UL) << 6) /* bit 16 -> 22 */ - | ((val & 0x00ff80UL) << 20) /* bit 7 -> 27 */ - | ((val & 0x00007fUL) << 13) /* bit 0 -> 13 */)); -} - -/* Like ia64_imm22(), but also clear bits 20-21. For addl, this has - the effect of turning "addl rX=imm22,rY" into "addl - rX=imm22,r0". */ -static inline void ia64_imm22_r0 (void *insn, uint64_t val) -{ - if (val + (1 << 21) >= (1 << 22)) - fprintf(stderr, "%s: value %li out of IMM22 range\n", - __FUNCTION__, (int64_t)val); - ia64_patch((uint64_t) insn, 0x01fffcfe000UL | (0x3UL << 20), - ( ((val & 0x200000UL) << 15) /* bit 21 -> 36 */ - | ((val & 0x1f0000UL) << 6) /* bit 16 -> 22 */ - | ((val & 0x00ff80UL) << 20) /* bit 7 -> 27 */ - | ((val & 0x00007fUL) << 13) /* bit 0 -> 13 */)); -} - -static inline void ia64_imm21b (void *insn, uint64_t val) -{ - if (val + (1 << 20) >= (1 << 21)) - fprintf(stderr, "%s: value %li out of IMM21b range\n", - __FUNCTION__, (int64_t)val); - ia64_patch((uint64_t) insn, 0x11ffffe000UL, - ( ((val & 0x100000UL) << 16) /* bit 20 -> 36 */ - | ((val & 0x0fffffUL) << 13) /* bit 0 -> 13 */)); -} - -static inline void ia64_nop_b (void *insn) -{ - ia64_patch((uint64_t) insn, (1UL << 41) - 1, 2UL << 37); -} - -static inline void ia64_ldxmov(void *insn, uint64_t val) -{ - if (val + (1 << 21) < (1 << 22)) - ia64_patch((uint64_t) insn, 0x1fff80fe000UL, 8UL << 37); -} - -static inline int ia64_patch_ltoff(void *insn, uint64_t val, - int relaxable) -{ - if (relaxable && (val + (1 << 21) < (1 << 22))) { - ia64_imm22_r0(insn, val); - return 0; - } - return 1; -} - -struct ia64_fixup { - struct ia64_fixup *next; - void *addr; /* address that needs to be patched */ - long value; -}; - -#define IA64_PLT(insn, plt_index) \ -do { \ - struct ia64_fixup *fixup = alloca(sizeof(*fixup)); \ - fixup->next = plt_fixes; \ - plt_fixes = fixup; \ - fixup->addr = (insn); \ - fixup->value = (plt_index); \ - plt_offset[(plt_index)] = 1; \ -} while (0) - -#define IA64_LTOFF(insn, val, relaxable) \ -do { \ - if (ia64_patch_ltoff(insn, val, relaxable)) { \ - struct ia64_fixup *fixup = alloca(sizeof(*fixup)); \ - fixup->next = ltoff_fixes; \ - ltoff_fixes = fixup; \ - fixup->addr = (insn); \ - fixup->value = (val); \ - } \ -} while (0) - -static inline void ia64_apply_fixes (uint8_t **gen_code_pp, - struct ia64_fixup *ltoff_fixes, - uint64_t gp, - struct ia64_fixup *plt_fixes, - int num_plts, - unsigned long *plt_target, - unsigned int *plt_offset) -{ - static const uint8_t plt_bundle[] = { - 0x04, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, /* nop 0; movl r1=GP */ - 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x60, - - 0x05, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, /* nop 0; brl IP */ - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc0 - }; - uint8_t *gen_code_ptr = *gen_code_pp, *plt_start, *got_start; - uint64_t *vp; - struct ia64_fixup *fixup; - unsigned int offset = 0; - struct fdesc { - long ip; - long gp; - } *fdesc; - int i; - - if (plt_fixes) { - plt_start = gen_code_ptr; - - for (i = 0; i < num_plts; ++i) { - if (plt_offset[i]) { - plt_offset[i] = offset; - offset += sizeof(plt_bundle); - - fdesc = (struct fdesc *) plt_target[i]; - memcpy(gen_code_ptr, plt_bundle, sizeof(plt_bundle)); - ia64_imm64 (gen_code_ptr + 0x02, fdesc->gp); - ia64_imm60b(gen_code_ptr + 0x12, - (fdesc->ip - (long) (gen_code_ptr + 0x10)) >> 4); - gen_code_ptr += sizeof(plt_bundle); - } - } - - for (fixup = plt_fixes; fixup; fixup = fixup->next) - ia64_imm21b(fixup->addr, - ((long) plt_start + plt_offset[fixup->value] - - ((long) fixup->addr & ~0xf)) >> 4); - } - - got_start = gen_code_ptr; - - /* First, create the GOT: */ - for (fixup = ltoff_fixes; fixup; fixup = fixup->next) { - /* first check if we already have this value in the GOT: */ - for (vp = (uint64_t *) got_start; vp < (uint64_t *) gen_code_ptr; ++vp) - if (*vp == fixup->value) - break; - if (vp == (uint64_t *) gen_code_ptr) { - /* Nope, we need to put the value in the GOT: */ - *vp = fixup->value; - gen_code_ptr += 8; - } - ia64_imm22(fixup->addr, (long) vp - gp); - } - /* Keep code ptr aligned. */ - if ((long) gen_code_ptr & 15) - gen_code_ptr += 8; - *gen_code_pp = gen_code_ptr; -} -#endif -#endif - -#ifdef CONFIG_DYNGEN_OP - -#if defined __hppa__ -struct hppa_branch_stub { - uint32_t *location; - long target; - struct hppa_branch_stub *next; -}; - -#define HPPA_RECORD_BRANCH(LIST, LOC, TARGET) \ -do { \ - struct hppa_branch_stub *stub = alloca(sizeof(struct hppa_branch_stub)); \ - stub->location = LOC; \ - stub->target = TARGET; \ - stub->next = LIST; \ - LIST = stub; \ -} while (0) - -static inline void hppa_process_stubs(struct hppa_branch_stub *stub, - uint8_t **gen_code_pp) -{ - uint32_t *s = (uint32_t *)*gen_code_pp; - uint32_t *p = s + 1; - - if (!stub) return; - - for (; stub != NULL; stub = stub->next) { - unsigned long l = (unsigned long)p; - /* stub: - * ldil L'target, %r1 - * be,n R'target(%sr4,%r1) - */ - *p++ = 0x20200000 | reassemble_21(lrsel(stub->target, 0)); - *p++ = 0xe0202002 | (reassemble_17(rrsel(stub->target, 0) >> 2)); - hppa_patch17f(stub->location, l, 0); - } - /* b,l,n stub,%r0 */ - *s = 0xe8000002 | reassemble_17((p - s) - 2); - *gen_code_pp = (uint8_t *)p; -} -#endif /* __hppa__ */ - -const TCGArg *dyngen_op(TCGContext *s, int opc, const TCGArg *opparam_ptr) -{ - uint8_t *gen_code_ptr; - -#ifdef __hppa__ - struct hppa_branch_stub *hppa_stubs = NULL; -#endif - - gen_code_ptr = s->code_ptr; - switch(opc) { - -/* op.h is dynamically generated by dyngen.c from op.c */ -#include "op.h" - - default: - tcg_abort(); - } - -#ifdef __hppa__ - hppa_process_stubs(hppa_stubs, &gen_code_ptr); -#endif - - s->code_ptr = gen_code_ptr; - return opparam_ptr; -} -#endif diff --git a/qemu/tcg/tcg-op.h b/qemu/tcg/tcg-op.h index dc404464..5432ac1f 100644 --- a/qemu/tcg/tcg-op.h +++ b/qemu/tcg/tcg-op.h @@ -23,11 +23,6 @@ */ #include "tcg.h" -#ifdef CONFIG_DYNGEN_OP -/* legacy dyngen operations */ -#include "gen-op.h" -#endif - int gen_new_label(void); static inline void tcg_gen_op1_i32(int opc, TCGv_i32 arg1) @@ -132,7 +127,7 @@ static inline void tcg_gen_ldst_op_i64(int opc, TCGv_i64 val, TCGv_ptr base, TCGArg offset) { *gen_opc_ptr++ = opc; - *gen_opparam_ptr++ = GET_TCGV_I32(val); + *gen_opparam_ptr++ = GET_TCGV_I64(val); *gen_opparam_ptr++ = GET_TCGV_PTR(base); *gen_opparam_ptr++ = offset; } @@ -166,7 +161,7 @@ static inline void tcg_gen_op4_i32(int opc, TCGv_i32 arg1, TCGv_i32 arg2, } static inline void tcg_gen_op4_i64(int opc, TCGv_i64 arg1, TCGv_i64 arg2, - TCGv_i64 arg3, TCGv_i32 arg4) + TCGv_i64 arg3, TCGv_i64 arg4) { *gen_opc_ptr++ = opc; *gen_opparam_ptr++ = GET_TCGV_I64(arg1); @@ -2059,4 +2054,3 @@ static inline void tcg_gen_qemu_st64(TCGv_i64 arg, TCGv addr, int mem_index) #define tcg_gen_addi_ptr tcg_gen_addi_i64 #define tcg_gen_ext_i32_ptr tcg_gen_ext_i32_i64 #endif /* TCG_TARGET_REG_BITS != 32 */ - diff --git a/qemu/tcg/tcg-opc.h b/qemu/tcg/tcg-opc.h index 31ae5505..17c4bfba 100644 --- a/qemu/tcg/tcg-opc.h +++ b/qemu/tcg/tcg-opc.h @@ -21,10 +21,6 @@ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ -#ifdef CONFIG_DYNGEN_OP -#include "dyngen-opc.h" -#endif - #ifndef DEF2 #define DEF2(name, oargs, iargs, cargs, flags) DEF(name, oargs + iargs + cargs, 0) #endif diff --git a/qemu/tcg/tcg-runtime.c b/qemu/tcg/tcg-runtime.c index 575da430..1d77c37e 100644 --- a/qemu/tcg/tcg-runtime.c +++ b/qemu/tcg/tcg-runtime.c @@ -29,6 +29,7 @@ #include "config.h" #include "osdep.h" +#include "cpu.h" // For TARGET_LONG_BITS #include "tcg.h" int64_t tcg_helper_shl_i64(int64_t arg1, int64_t arg2) @@ -65,4 +66,3 @@ uint64_t tcg_helper_remu_i64(uint64_t arg1, uint64_t arg2) { return arg1 % arg2; } - diff --git a/qemu/tcg/tcg.c b/qemu/tcg/tcg.c index 78e7f932..35ca05a4 100644 --- a/qemu/tcg/tcg.c +++ b/qemu/tcg/tcg.c @@ -43,6 +43,7 @@ #include "config.h" #include "qemu-common.h" +#include "cache-utils.h" /* Note: the long term plan is to reduce the dependancies on the QEMU CPU definitions. Currently they are used for qemu_ld/st @@ -747,7 +748,7 @@ char *tcg_get_arg_str_i32(TCGContext *s, char *buf, int buf_size, TCGv_i32 arg) char *tcg_get_arg_str_i64(TCGContext *s, char *buf, int buf_size, TCGv_i64 arg) { - return tcg_get_arg_str_idx(s, buf, buf_size, GET_TCGV_I32(arg)); + return tcg_get_arg_str_idx(s, buf, buf_size, GET_TCGV_I64(arg)); } static int helper_cmp(const void *p1, const void *p2) @@ -885,7 +886,7 @@ void tcg_dump_ops(TCGContext *s, FILE *outfile) val = args[1]; th = tcg_find_helper(s, val); if (th) { - fprintf(outfile, th->name); + fprintf(outfile, "%s", th->name); } else { if (c == INDEX_op_movi_i32) fprintf(outfile, "0x%x", (uint32_t)val); @@ -1198,57 +1199,50 @@ static void tcg_liveness_analysis(TCGContext *s) break; /* XXX: optimize by hardcoding common cases (e.g. triadic ops) */ default: - if (op > INDEX_op_end) { - args -= def->nb_args; - nb_iargs = def->nb_iargs; - nb_oargs = def->nb_oargs; + args -= def->nb_args; + nb_iargs = def->nb_iargs; + nb_oargs = def->nb_oargs; - /* Test if the operation can be removed because all - its outputs are dead. We assume that nb_oargs == 0 - implies side effects */ - if (!(def->flags & TCG_OPF_SIDE_EFFECTS) && nb_oargs != 0) { - for(i = 0; i < nb_oargs; i++) { - arg = args[i]; - if (!dead_temps[arg]) - goto do_not_remove; - } - tcg_set_nop(s, gen_opc_buf + op_index, args, def->nb_args); + /* Test if the operation can be removed because all + its outputs are dead. We assume that nb_oargs == 0 + implies side effects */ + if (!(def->flags & TCG_OPF_SIDE_EFFECTS) && nb_oargs != 0) { + for(i = 0; i < nb_oargs; i++) { + arg = args[i]; + if (!dead_temps[arg]) + goto do_not_remove; + } + tcg_set_nop(s, gen_opc_buf + op_index, args, def->nb_args); #ifdef CONFIG_PROFILER - s->del_op_count++; + s->del_op_count++; #endif - } else { - do_not_remove: + } else { + do_not_remove: - /* output args are dead */ - for(i = 0; i < nb_oargs; i++) { - arg = args[i]; - dead_temps[arg] = 1; - } - - /* if end of basic block, update */ - if (def->flags & TCG_OPF_BB_END) { - tcg_la_bb_end(s, dead_temps); - } else if (def->flags & TCG_OPF_CALL_CLOBBER) { - /* globals are live */ - memset(dead_temps, 0, s->nb_globals); - } - - /* input args are live */ - dead_iargs = 0; - for(i = 0; i < nb_iargs; i++) { - arg = args[i + nb_oargs]; - if (dead_temps[arg]) { - dead_iargs |= (1 << i); - } - dead_temps[arg] = 0; + /* output args are dead */ + for(i = 0; i < nb_oargs; i++) { + arg = args[i]; + dead_temps[arg] = 1; + } + + /* if end of basic block, update */ + if (def->flags & TCG_OPF_BB_END) { + tcg_la_bb_end(s, dead_temps); + } else if (def->flags & TCG_OPF_CALL_CLOBBER) { + /* globals are live */ + memset(dead_temps, 0, s->nb_globals); + } + + /* input args are live */ + dead_iargs = 0; + for(i = 0; i < nb_iargs; i++) { + arg = args[i + nb_oargs]; + if (dead_temps[arg]) { + dead_iargs |= (1 << i); } - s->op_dead_iargs[op_index] = dead_iargs; + dead_temps[arg] = 0; } - } else { - /* legacy dyngen operations */ - args -= def->nb_args; - /* mark end of basic block */ - tcg_la_bb_end(s, dead_temps); + s->op_dead_iargs[op_index] = dead_iargs; } break; } @@ -1897,20 +1891,15 @@ static int tcg_reg_alloc_call(TCGContext *s, const TCGOpDef *def, #ifdef CONFIG_PROFILER -static int64_t dyngen_table_op_count[NB_OPS]; +static int64_t tcg_table_op_count[NB_OPS]; void dump_op_count(void) { int i; FILE *f; - f = fopen("/tmp/op1.log", "w"); - for(i = 0; i < INDEX_op_end; i++) { - fprintf(f, "%s %" PRId64 "\n", tcg_op_defs[i].name, dyngen_table_op_count[i]); - } - fclose(f); - f = fopen("/tmp/op2.log", "w"); + f = fopen("/tmp/op.log", "w"); for(i = INDEX_op_end; i < NB_OPS; i++) { - fprintf(f, "%s %" PRId64 "\n", tcg_op_defs[i].name, dyngen_table_op_count[i]); + fprintf(f, "%s %" PRId64 "\n", tcg_op_defs[i].name, tcg_table_op_count[i]); } fclose(f); } @@ -1960,7 +1949,7 @@ static inline int tcg_gen_code_common(TCGContext *s, uint8_t *gen_code_buf, for(;;) { opc = gen_opc_buf[op_index]; #ifdef CONFIG_PROFILER - dyngen_table_op_count[opc]++; + tcg_table_op_count[opc]++; #endif def = &tcg_op_defs[opc]; #if 0 @@ -2015,22 +2004,6 @@ static inline int tcg_gen_code_common(TCGContext *s, uint8_t *gen_code_buf, goto next; case INDEX_op_end: goto the_end; - -#ifdef CONFIG_DYNGEN_OP - case 0 ... INDEX_op_end - 1: - /* legacy dyngen ops */ -#ifdef CONFIG_PROFILER - s->old_op_count++; -#endif - tcg_reg_alloc_bb_end(s, s->reserved_regs); - if (search_pc >= 0) { - s->code_ptr += def->copy_size; - args += def->nb_args; - } else { - args = dyngen_op(s, opc, args); - } - goto next; -#endif default: /* Note: in order to speed up the code, it would be much faster to have specialized register allocator functions for @@ -2053,7 +2026,7 @@ static inline int tcg_gen_code_common(TCGContext *s, uint8_t *gen_code_buf, return -1; } -int dyngen_code(TCGContext *s, uint8_t *gen_code_buf) +int tcg_gen_code(TCGContext *s, uint8_t *gen_code_buf) { #ifdef CONFIG_PROFILER { @@ -2081,7 +2054,7 @@ int dyngen_code(TCGContext *s, uint8_t *gen_code_buf) offset bytes from the start of the TB. The contents of gen_code_buf must not be changed, though writing the same values is ok. Return -1 if not found. */ -int dyngen_code_search_pc(TCGContext *s, uint8_t *gen_code_buf, long offset) +int tcg_gen_code_search_pc(TCGContext *s, uint8_t *gen_code_buf, long offset) { return tcg_gen_code_common(s, gen_code_buf, offset); } diff --git a/qemu/tcg/tcg.h b/qemu/tcg/tcg.h index 0581020c..08c7bccf 100644 --- a/qemu/tcg/tcg.h +++ b/qemu/tcg/tcg.h @@ -126,20 +126,20 @@ typedef tcg_target_ulong TCGArg; typedef struct { - int n; + int i32; } TCGv_i32; typedef struct { - int n; + int i64; } TCGv_i64; #define MAKE_TCGV_I32(i) __extension__ \ ({ TCGv_i32 make_tcgv_tmp = {i}; make_tcgv_tmp;}) #define MAKE_TCGV_I64(i) __extension__ \ ({ TCGv_i64 make_tcgv_tmp = {i}; make_tcgv_tmp;}) -#define GET_TCGV_I32(t) ((t).n) -#define GET_TCGV_I64(t) ((t).n) +#define GET_TCGV_I32(t) ((t).i32) +#define GET_TCGV_I64(t) ((t).i64) #if TCG_TARGET_REG_BITS == 32 #define TCGV_LOW(t) MAKE_TCGV_I32(GET_TCGV_I64(t)) #define TCGV_HIGH(t) MAKE_TCGV_I32(GET_TCGV_I64(t) + 1) @@ -314,8 +314,8 @@ static inline void *tcg_malloc(int size) void tcg_context_init(TCGContext *s); void tcg_func_start(TCGContext *s); -int dyngen_code(TCGContext *s, uint8_t *gen_code_buf); -int dyngen_code_search_pc(TCGContext *s, uint8_t *gen_code_buf, long offset); +int tcg_gen_code(TCGContext *s, uint8_t *gen_code_buf); +int tcg_gen_code_search_pc(TCGContext *s, uint8_t *gen_code_buf, long offset); void tcg_set_frame(TCGContext *s, int reg, tcg_target_long start, tcg_target_long size); @@ -449,8 +449,6 @@ void tcg_out_reloc(TCGContext *s, uint8_t *code_ptr, int type, const TCGArg *tcg_gen_code_op(TCGContext *s, int opc, const TCGArg *args1, unsigned int dead_iargs); -const TCGArg *dyngen_op(TCGContext *s, int opc, const TCGArg *opparam_ptr); - /* tcg-runtime.c */ int64_t tcg_helper_shl_i64(int64_t arg1, int64_t arg2); int64_t tcg_helper_shr_i64(int64_t arg1, int64_t arg2); diff --git a/qemu/tcg/x86_64/tcg-target.c b/qemu/tcg/x86_64/tcg-target.c index 551ca78b..ce58fa17 100644 --- a/qemu/tcg/x86_64/tcg-target.c +++ b/qemu/tcg/x86_64/tcg-target.c @@ -575,7 +575,13 @@ static void tcg_out_qemu_ld(TCGContext *s, const TCGArg *args, tcg_out_modrm(s, 0x63 | P_REXW, data_reg, TCG_REG_RAX); break; case 0: + /* movzbq */ + tcg_out_modrm(s, 0xb6 | P_EXT | P_REXW, data_reg, TCG_REG_RAX); + break; case 1: + /* movzwq */ + tcg_out_modrm(s, 0xb7 | P_EXT | P_REXW, data_reg, TCG_REG_RAX); + break; case 2: default: /* movl */ diff --git a/qemu/tests/cris/.gdbinit b/qemu/tests/cris/.gdbinit index 579eac94..5e8c1d32 100644 --- a/qemu/tests/cris/.gdbinit +++ b/qemu/tests/cris/.gdbinit @@ -9,4 +9,3 @@ display /x $r2 display /x $r3 display /x $r4 display /t $ccs - diff --git a/qemu/tests/cris/README b/qemu/tests/cris/README index 93c955cb..2e65a76f 100644 --- a/qemu/tests/cris/README +++ b/qemu/tests/cris/README @@ -1,2 +1 @@ Test-suite for the cris port. Heavily based on the test-suite for the CRIS port of sim by Hans-Peter Nilsson. - diff --git a/qemu/tests/cris/check_cmp-2.s b/qemu/tests/cris/check_cmp-2.s index c5c3f5ce..414d3705 100644 --- a/qemu/tests/cris/check_cmp-2.s +++ b/qemu/tests/cris/check_cmp-2.s @@ -12,4 +12,4 @@ fail 1: pass - quit
\ No newline at end of file + quit diff --git a/qemu/tests/cris/check_movemr.s b/qemu/tests/cris/check_movemr.s index 776da768..88489dee 100644 --- a/qemu/tests/cris/check_movemr.s +++ b/qemu/tests/cris/check_movemr.s @@ -76,4 +76,3 @@ mem3: checkr3 6712 quit - diff --git a/qemu/tests/cris/check_movemrv32.s b/qemu/tests/cris/check_movemrv32.s index dc340afa..53950abd 100644 --- a/qemu/tests/cris/check_movemrv32.s +++ b/qemu/tests/cris/check_movemrv32.s @@ -94,4 +94,3 @@ y: checkr3 d quit - diff --git a/qemu/tests/cris/check_mover.s b/qemu/tests/cris/check_mover.s index c93106f1..b4db595d 100644 --- a/qemu/tests/cris/check_mover.s +++ b/qemu/tests/cris/check_mover.s @@ -26,4 +26,3 @@ checkr3 ffffff00 quit - diff --git a/qemu/tests/cris/check_stat3.c b/qemu/tests/cris/check_stat3.c index a248ec08..3b5b217a 100644 --- a/qemu/tests/cris/check_stat3.c +++ b/qemu/tests/cris/check_stat3.c @@ -23,4 +23,3 @@ int main (int argc, char *argv[]) printf ("pass\n"); exit (0); } - diff --git a/qemu/tests/cris/check_stat4.c b/qemu/tests/cris/check_stat4.c index d10655d4..e1955cab 100644 --- a/qemu/tests/cris/check_stat4.c +++ b/qemu/tests/cris/check_stat4.c @@ -25,4 +25,3 @@ int main (int argc, char *argv[]) printf ("pass\n"); exit (0); } - diff --git a/qemu/tests/sha1.c b/qemu/tests/sha1.c index 31b00192..2557344d 100644 --- a/qemu/tests/sha1.c +++ b/qemu/tests/sha1.c @@ -238,5 +238,3 @@ main(int argc, char **argv) printf("\n"); return 0; } - - diff --git a/qemu/tests/test-i386-shift.h b/qemu/tests/test-i386-shift.h index 2bd6a4ad..3d8f84bf 100644 --- a/qemu/tests/test-i386-shift.h +++ b/qemu/tests/test-i386-shift.h @@ -183,4 +183,3 @@ void *glue(_test_, OP) __init_call = glue(test_, OP); #undef OP_SHIFTD #undef OP_NOBYTE #undef EXECSHIFT - diff --git a/qemu/tests/test_path.c b/qemu/tests/test_path.c index 7d6e8317..def7441c 100644 --- a/qemu/tests/test_path.c +++ b/qemu/tests/test_path.c @@ -149,4 +149,3 @@ int main(int argc, char *argv[]) } return 0; } - diff --git a/qemu/translate-all.c b/qemu/translate-all.c index 1c27fd32..75ef7f33 100644 --- a/qemu/translate-all.c +++ b/qemu/translate-all.c @@ -118,7 +118,7 @@ int cpu_gen_code(CPUState *env, TranslationBlock *tb, int *gen_code_size_ptr) s->interm_time += profile_getclock() - ti; s->code_time -= profile_getclock(); #endif - gen_code_size = dyngen_code(s, gen_code_buf); + gen_code_size = tcg_gen_code(s, gen_code_buf); *gen_code_size_ptr = gen_code_size; #ifdef CONFIG_PROFILER s->code_time += profile_getclock(); @@ -177,7 +177,7 @@ int cpu_restore_state(TranslationBlock *tb, s->tb_jmp_offset = NULL; s->tb_next = tb->tb_next; #endif - j = dyngen_code_search_pc(s, (uint8_t *)tc_ptr, searched_pc - tc_ptr); + j = tcg_gen_code_search_pc(s, (uint8_t *)tc_ptr, searched_pc - tc_ptr); if (j < 0) return -1; /* now find start of instruction before */ @@ -36,6 +36,7 @@ #include "gdbstub.h" #include "qemu-timer.h" #include "qemu-char.h" +#include "cache-utils.h" #include "block.h" #include "audio/audio.h" #include "hw/device-assignment.h" @@ -3628,7 +3629,7 @@ static int qemu_select(int max_fd, fd_set *rfds, fd_set *wfds, fd_set *xfds, } #ifdef _WIN32 -void host_main_loop_wait(int *timeout) +static void host_main_loop_wait(int *timeout) { int ret, ret2, i; PollingEntry *pe; @@ -3672,7 +3673,7 @@ void host_main_loop_wait(int *timeout) *timeout = 0; } #else -void host_main_loop_wait(int *timeout) +static void host_main_loop_wait(int *timeout) { } #endif @@ -4716,7 +4717,7 @@ static void termsig_setup(void) #endif -int main(int argc, char **argv) +int main(int argc, char **argv, char **envp) { #ifdef CONFIG_GDBSTUB int use_gdbstub; @@ -4754,6 +4755,8 @@ int main(int argc, char **argv) int autostart; const char *incoming = NULL; + qemu_cache_utils_init(envp); + LIST_INIT (&vm_change_state_head); #ifndef _WIN32 { @@ -183,7 +183,7 @@ static VncState *vnc_state; /* needed for info vnc */ void do_info_vnc(void) { - if (vnc_state == NULL) + if (vnc_state == NULL || vnc_state->display == NULL) term_printf("VNC server disabled\n"); else { term_printf("VNC server active on: "); |