aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMarcelo Tosatti <mtosatti@redhat.com>2012-10-11 05:25:37 -0300
committerMarcelo Tosatti <mtosatti@redhat.com>2012-10-11 05:25:37 -0300
commit8e65440d5f64435c003d32088757f702b86af9b4 (patch)
tree93a31afc3151c19e4906aed6748e842d8431fb02
parenta60ffef7db55339b471ebf85105eb549c9959149 (diff)
parentb4ae3cfa57b8c1bdbbd7b7d420971e9171203ade (diff)
Merge commit 'b4ae3cfa57b8c1bdbbd7b7d420971e9171203ade' into upstream-merge
* commit 'b4ae3cfa57b8c1bdbbd7b7d420971e9171203ade': (114 commits) ssi: Add slave autoconnect helper MAINTAINERS: Added maintainerships for SSI xilinx_zynq: Added SPI controllers + flashes xilinx_spips: Xilinx Zynq SPI cntrlr device model petalogix-ml605: added SPI controller with n25q128 xilinx_spi: Initial impl. of Xilinx SPI controller m25p80: Initial implementation of SPI flash device hw: Added generic FIFO API. stellaris: Removed SSI mux qdev: allow multiple qdev_init_gpio_in() calls ssi: Added create_slave_no_init() ssi: Implemented CS behaviour ssi: Support for multiple attached devices qemu-barrier: Fix compilation on i386 hosts target-sparc: Optimize conditionals using SUBCC target-sparc: Fall through from not-taken trap target-sparc: Cleanup "global" temporary allocation target-sparc: Use movcond for FMOV*R target-sparc: Use movcond in mulscc target-sparc: Move taddcctv and tsubcctv out of line ... Signed-off-by: Marcelo Tosatti <mtosatti@redhat.com>
-rw-r--r--MAINTAINERS58
-rw-r--r--block/qed-table.c1
-rw-r--r--blockdev.c1
-rw-r--r--cpu-all.h3
-rw-r--r--cpu-exec.c2
-rw-r--r--cpus.c8
-rw-r--r--default-configs/arm-softmmu.mak1
-rw-r--r--default-configs/microblaze-softmmu.mak2
-rw-r--r--default-configs/microblazeel-softmmu.mak2
-rw-r--r--device_tree.c15
-rw-r--r--device_tree.h2
-rw-r--r--exec.c12
-rw-r--r--hw/9pfs/virtio-9p.c5
-rw-r--r--hw/Makefile.objs2
-rw-r--r--hw/ads7846.c7
-rw-r--r--hw/alpha_dp264.c2
-rw-r--r--hw/alpha_pci.c24
-rw-r--r--hw/alpha_sys.h2
-rw-r--r--hw/arm/Makefile.objs1
-rw-r--r--hw/blizzard.c2
-rw-r--r--hw/bt-hci.c1
-rw-r--r--hw/cirrus_vga.c6
-rw-r--r--hw/device-hotplug.c1
-rw-r--r--hw/exynos4210_combiner.c4
-rw-r--r--hw/exynos4210_gic.c4
-rw-r--r--hw/exynos4210_mct.c2
-rw-r--r--hw/fdc.c2
-rw-r--r--hw/fifo.c78
-rw-r--r--hw/fifo.h99
-rw-r--r--hw/framebuffer.c1
-rw-r--r--hw/ide/macio.c1
-rw-r--r--hw/irq.c27
-rw-r--r--hw/irq.h11
-rw-r--r--hw/isa-bus.c20
-rw-r--r--hw/isa.h2
-rw-r--r--hw/ivshmem.c4
-rw-r--r--hw/leon3.c2
-rw-r--r--hw/m25p80.c598
-rw-r--r--hw/max111x.c7
-rw-r--r--hw/megasas.c1
-rw-r--r--hw/microblaze/Makefile.objs1
-rw-r--r--hw/mips_fulong2e.c2
-rw-r--r--hw/mips_malta.c10
-rw-r--r--hw/msix.c1
-rw-r--r--hw/pc.c35
-rw-r--r--hw/pc.h13
-rw-r--r--hw/pci.c18
-rw-r--r--hw/pci.h3
-rw-r--r--hw/petalogix_ml605_mmu.c27
-rw-r--r--hw/pflash_cfi01.c1
-rw-r--r--hw/pflash_cfi02.c1
-rw-r--r--hw/ppc/e500.c24
-rw-r--r--hw/ppc405_uc.c16
-rw-r--r--hw/ppc_newworld.c1
-rw-r--r--hw/ppc_oldworld.c1
-rw-r--r--hw/ppc_prep.c1
-rw-r--r--hw/pxa2xx_keypad.c1
-rw-r--r--hw/qdev.c12
-rw-r--r--hw/qdev.h1
-rw-r--r--hw/sb16.c1
-rw-r--r--hw/scsi-disk.c2
-rw-r--r--hw/spapr.c336
-rw-r--r--hw/spapr.h14
-rw-r--r--hw/spapr_hcall.c49
-rw-r--r--hw/spapr_iommu.c24
-rw-r--r--hw/spapr_pci.c12
-rw-r--r--hw/spapr_rtas.c5
-rw-r--r--hw/spapr_vio.c37
-rw-r--r--hw/spapr_vio.h2
-rw-r--r--hw/spitz.c8
-rw-r--r--hw/ssd0323.c7
-rw-r--r--hw/ssi-sd.c7
-rw-r--r--hw/ssi.c109
-rw-r--r--hw/ssi.h42
-rw-r--r--hw/stellaris.c93
-rw-r--r--hw/sun4u.c1
-rw-r--r--hw/tcx.c1
-rw-r--r--hw/usb/dev-uas.c2
-rw-r--r--hw/usb/hcd-ohci.c2
-rw-r--r--hw/usb/hcd-xhci.c1
-rw-r--r--hw/versatilepb.c3
-rw-r--r--hw/vga-pci.c10
-rw-r--r--hw/vga-pci.h12
-rw-r--r--hw/vmware_vga.c1
-rw-r--r--hw/vmware_vga.h15
-rw-r--r--hw/xen_domainbuild.c1
-rw-r--r--hw/xics.c114
-rw-r--r--hw/xics.h8
-rw-r--r--hw/xilinx_spi.c385
-rw-r--r--hw/xilinx_spips.c354
-rw-r--r--hw/xilinx_zynq.c34
-rw-r--r--hw/z2.c7
-rw-r--r--libcacard/vcard.c1
-rw-r--r--libcacard/vcard_emul_nss.c3
-rw-r--r--libcacard/vreader.c1
-rw-r--r--linux-user/signal.c2
-rw-r--r--monitor.c8
-rw-r--r--os-posix.c1
-rw-r--r--qemu-barrier.h2
-rw-r--r--qemu-common.h10
-rw-r--r--qemu-sockets.c3
-rw-r--r--qga/commands-posix.c2
-rw-r--r--qga/commands-win32.c2
-rw-r--r--savevm.c1
-rw-r--r--slirp/ip_icmp.h4
-rw-r--r--slirp/ip_input.c1
-rw-r--r--slirp/tcp_input.c2
-rw-r--r--slirp/udp.c1
-rw-r--r--sysemu.h3
-rw-r--r--target-arm/cpu.h2
-rw-r--r--target-arm/helper.h24
-rw-r--r--target-arm/op_helper.c44
-rw-r--r--target-arm/translate.c302
-rw-r--r--target-i386/cpu.c2
-rw-r--r--target-i386/cpu.h4
-rw-r--r--target-i386/helper.c4
-rw-r--r--target-i386/seg_helper.c4
-rw-r--r--target-i386/smm_helper.c4
-rw-r--r--target-ppc/cpu.h1
-rw-r--r--target-ppc/int_helper.c127
-rw-r--r--target-ppc/kvm.c139
-rw-r--r--target-ppc/kvm_ppc.h19
-rw-r--r--target-ppc/machine.c4
-rw-r--r--target-ppc/translate_init.c8
-rw-r--r--target-sparc/cpu.c7
-rw-r--r--target-sparc/cpu.h1
-rw-r--r--target-sparc/helper.c86
-rw-r--r--target-sparc/helper.h6
-rw-r--r--target-sparc/int32_helper.c7
-rw-r--r--target-sparc/int64_helper.c8
-rw-r--r--target-sparc/ldst_helper.c4
-rw-r--r--target-sparc/translate.c1133
-rw-r--r--target-unicore32/translate.c2
-rw-r--r--target-xtensa/translate.c22
-rw-r--r--tcg/README7
-rw-r--r--tcg/arm/tcg-target.c24
-rw-r--r--tcg/hppa/tcg-target.c25
-rw-r--r--tcg/i386/tcg-target.c11
-rw-r--r--tcg/ia64/tcg-target.c4
-rw-r--r--tcg/mips/tcg-target.c5
-rw-r--r--tcg/optimize.c6
-rw-r--r--tcg/ppc/tcg-target.c12
-rw-r--r--tcg/ppc64/tcg-target.c12
-rw-r--r--tcg/s390/tcg-target.c12
-rw-r--r--tcg/sparc/tcg-target.c4
-rw-r--r--tcg/tcg-op.h82
-rw-r--r--tcg/tcg-opc.h1
-rw-r--r--tcg/tcg.c3
-rw-r--r--tcg/tcg.h60
-rw-r--r--tcg/tci/tcg-target.c4
-rw-r--r--tci.c1
-rw-r--r--ui/vnc-auth-sasl.c1
-rw-r--r--ui/vnc-tls.c2
-rw-r--r--vl.c28
-rw-r--r--xen-all.c1
155 files changed, 3442 insertions, 1765 deletions
diff --git a/MAINTAINERS b/MAINTAINERS
index 29aac4fce..f1f925007 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -268,6 +268,7 @@ S: Maintained
F: hw/xilinx_zynq.c
F: hw/zynq_slcr.c
F: hw/cadence_*
+F: hw/xilinx_spips.c
CRIS Machines
-------------
@@ -349,9 +350,31 @@ PowerPC Machines
405
M: Alexander Graf <agraf@suse.de>
L: qemu-ppc@nongnu.org
-S: Maintained
+S: Odd Fixes
F: hw/ppc405_boards.c
+Bamboo
+M: Alexander Graf <agraf@suse.de>
+L: qemu-ppc@nongnu.org
+S: Odd Fixes
+F: hw/ppc440_bamboo.c
+
+e500
+M: Alexander Graf <agraf@suse.de>
+M: Scott Wood <scottwood@freescale.com>
+L: qemu-ppc@nongnu.org
+S: Supported
+F: hw/ppc/e500.[hc]
+F: hw/ppc/e500plat.c
+
+mpc8544ds
+M: Alexander Graf <agraf@suse.de>
+M: Scott Wood <scottwood@freescale.com>
+L: qemu-ppc@nongnu.org
+S: Supported
+F: hw/ppc/mpc8544ds.c
+F: hw/mpc8544_guts.c
+
New World
M: Alexander Graf <agraf@suse.de>
L: qemu-ppc@nongnu.org
@@ -374,6 +397,19 @@ S: Odd Fixes
F: hw/ppc_prep.c
F: hw/prep_pci.[hc]
+sPAPR
+M: David Gibson <david@gibson.dropbear.id.au>
+M: Alexander Graf <agraf@suse.de>
+L: qemu-ppc@nongnu.org
+S: Supported
+F: hw/spapr*
+
+virtex_ml507
+M: Edgar E. Iglesias <edgar.iglesias@gmail.com>
+L: qemu-ppc@nongnu.org
+S: Odd Fixes
+F: hw/virtex_ml507.c
+
SH4 Machines
------------
R2D
@@ -457,6 +493,19 @@ S: Supported
F: hw/pci*
F: hw/piix*
+ppc4xx
+M: Alexander Graf <agraf@suse.de>
+L: qemu-ppc@nongnu.org
+S: Odd Fixes
+F: hw/ppc4xx*.[hc]
+
+ppce500
+M: Alexander Graf <agraf@suse.de>
+M: Scott Wood <scottwood@freescale.com>
+L: qemu-ppc@nongnu.org
+S: Supported
+F: hw/ppce500_*
+
SCSI
M: Paolo Bonzini <pbonzini@redhat.com>
S: Supported
@@ -469,6 +518,12 @@ M: Paul Brook <paul@codesourcery.com>
S: Odd Fixes
F: hw/lsi53c895a.c
+SSI
+M: Peter Crosthwaite <peter.crosthwaite@petalogix.com>
+S: Maintained
+F: hw/ssi.*
+F: hw/m25p80.c
+
USB
M: Gerd Hoffmann <kraxel@redhat.com>
S: Maintained
@@ -517,6 +572,7 @@ F: hw/xilinx_intc.c
F: hw/xilinx_ethlite.c
F: hw/xilinx_timer.c
F: hw/xilinx.h
+F: hw/xilinx_spi.c
Subsystems
----------
diff --git a/block/qed-table.c b/block/qed-table.c
index ce07b0554..de845ec3d 100644
--- a/block/qed-table.c
+++ b/block/qed-table.c
@@ -103,7 +103,6 @@ static void qed_write_table_cb(void *opaque, int ret)
out:
qemu_vfree(write_table_cb->table);
gencb_complete(&write_table_cb->gencb, ret);
- return;
}
/**
diff --git a/blockdev.c b/blockdev.c
index 1db9efecf..636fc5632 100644
--- a/blockdev.c
+++ b/blockdev.c
@@ -836,7 +836,6 @@ exit:
QSIMPLEQ_FOREACH_SAFE(states, &snap_bdrv_states, entry, next) {
g_free(states);
}
- return;
}
diff --git a/cpu-all.h b/cpu-all.h
index 74d3681c2..2b9968267 100644
--- a/cpu-all.h
+++ b/cpu-all.h
@@ -356,6 +356,9 @@ CPUArchState *cpu_copy(CPUArchState *env);
CPUArchState *qemu_get_cpu(int cpu);
#define CPU_DUMP_CODE 0x00010000
+#define CPU_DUMP_FPU 0x00020000 /* dump FPU register state, not just integer */
+/* dump info about TCG QEMU's condition code optimization state */
+#define CPU_DUMP_CCOP 0x00040000
void cpu_dump_state(CPUArchState *env, FILE *f, fprintf_function cpu_fprintf,
int flags);
diff --git a/cpu-exec.c b/cpu-exec.c
index 134b3c4fc..252da8688 100644
--- a/cpu-exec.c
+++ b/cpu-exec.c
@@ -552,7 +552,7 @@ int cpu_exec(CPUArchState *env)
#if defined(TARGET_I386)
env->eflags = env->eflags | cpu_cc_compute_all(env, CC_OP)
| (DF & DF_MASK);
- log_cpu_state(env, X86_DUMP_CCOP);
+ log_cpu_state(env, CPU_DUMP_CCOP);
env->eflags &= ~(DF_MASK | CC_O | CC_S | CC_Z | CC_A | CC_P | CC_C);
#elif defined(TARGET_M68K)
cpu_m68k_flush_flags(env, env->cc_op);
diff --git a/cpus.c b/cpus.c
index 4b726ef4e..750a76fbc 100644
--- a/cpus.c
+++ b/cpus.c
@@ -395,11 +395,7 @@ void hw_error(const char *fmt, ...)
fprintf(stderr, "\n");
for(env = first_cpu; env != NULL; env = env->next_cpu) {
fprintf(stderr, "CPU #%d:\n", env->cpu_index);
-#ifdef TARGET_I386
- cpu_dump_state(env, stderr, fprintf, X86_DUMP_FPU);
-#else
- cpu_dump_state(env, stderr, fprintf, 0);
-#endif
+ cpu_dump_state(env, stderr, fprintf, CPU_DUMP_FPU);
}
va_end(ap);
abort();
@@ -613,7 +609,7 @@ static void qemu_tcg_init_cpu_signals(void)
}
#endif /* _WIN32 */
-QemuMutex qemu_global_mutex;
+static QemuMutex qemu_global_mutex;
static QemuCond qemu_io_proceeded_cond;
static bool iothread_requesting_mutex;
diff --git a/default-configs/arm-softmmu.mak b/default-configs/arm-softmmu.mak
index f335a725f..2f1a5c994 100644
--- a/default-configs/arm-softmmu.mak
+++ b/default-configs/arm-softmmu.mak
@@ -22,6 +22,7 @@ CONFIG_ADS7846=y
CONFIG_MAX111X=y
CONFIG_SSI=y
CONFIG_SSI_SD=y
+CONFIG_SSI_M25P80=y
CONFIG_LAN9118=y
CONFIG_SMC91C111=y
CONFIG_DS1338=y
diff --git a/default-configs/microblaze-softmmu.mak b/default-configs/microblaze-softmmu.mak
index 64c9485de..2f442e5ae 100644
--- a/default-configs/microblaze-softmmu.mak
+++ b/default-configs/microblaze-softmmu.mak
@@ -5,3 +5,5 @@ CONFIG_PFLASH_CFI01=y
CONFIG_SERIAL=y
CONFIG_XILINX=y
CONFIG_XILINX_AXI=y
+CONFIG_SSI=y
+CONFIG_SSI_M25P80=y
diff --git a/default-configs/microblazeel-softmmu.mak b/default-configs/microblazeel-softmmu.mak
index a9622760c..af9a3cde0 100644
--- a/default-configs/microblazeel-softmmu.mak
+++ b/default-configs/microblazeel-softmmu.mak
@@ -5,3 +5,5 @@ CONFIG_PFLASH_CFI01=y
CONFIG_SERIAL=y
CONFIG_XILINX=y
CONFIG_XILINX_AXI=y
+CONFIG_SSI=y
+CONFIG_SSI_M25P80=y
diff --git a/device_tree.c b/device_tree.c
index d7a9b6bb8..a9236133c 100644
--- a/device_tree.c
+++ b/device_tree.c
@@ -304,3 +304,18 @@ int qemu_devtree_add_subnode(void *fdt, const char *name)
g_free(dupname);
return retval;
}
+
+void qemu_devtree_dumpdtb(void *fdt, int size)
+{
+ QemuOpts *machine_opts;
+
+ machine_opts = qemu_opts_find(qemu_find_opts("machine"), 0);
+ if (machine_opts) {
+ const char *dumpdtb = qemu_opt_get(machine_opts, "dumpdtb");
+ if (dumpdtb) {
+ /* Dump the dtb to a file and quit */
+ exit(g_file_set_contents(dumpdtb, fdt, size, NULL) ? 0 : 1);
+ }
+ }
+
+}
diff --git a/device_tree.h b/device_tree.h
index f7a3e6cfc..f0b3f35e0 100644
--- a/device_tree.h
+++ b/device_tree.h
@@ -49,4 +49,6 @@ int qemu_devtree_add_subnode(void *fdt, const char *name);
sizeof(qdt_tmp)); \
} while (0)
+void qemu_devtree_dumpdtb(void *fdt, int size);
+
#endif /* __DEVICE_TREE_H__ */
diff --git a/exec.c b/exec.c
index 1114a0932..7899042ce 100644
--- a/exec.c
+++ b/exec.c
@@ -1742,20 +1742,12 @@ void cpu_abort(CPUArchState *env, const char *fmt, ...)
fprintf(stderr, "qemu: fatal: ");
vfprintf(stderr, fmt, ap);
fprintf(stderr, "\n");
-#ifdef TARGET_I386
- cpu_dump_state(env, stderr, fprintf, X86_DUMP_FPU | X86_DUMP_CCOP);
-#else
- cpu_dump_state(env, stderr, fprintf, 0);
-#endif
+ cpu_dump_state(env, stderr, fprintf, CPU_DUMP_FPU | CPU_DUMP_CCOP);
if (qemu_log_enabled()) {
qemu_log("qemu: fatal: ");
qemu_log_vprintf(fmt, ap2);
qemu_log("\n");
-#ifdef TARGET_I386
- log_cpu_state(env, X86_DUMP_FPU | X86_DUMP_CCOP);
-#else
- log_cpu_state(env, 0);
-#endif
+ log_cpu_state(env, CPU_DUMP_FPU | CPU_DUMP_CCOP);
qemu_log_flush();
qemu_log_close();
}
diff --git a/hw/9pfs/virtio-9p.c b/hw/9pfs/virtio-9p.c
index 4b5254011..8b9cdc96e 100644
--- a/hw/9pfs/virtio-9p.c
+++ b/hw/9pfs/virtio-9p.c
@@ -505,7 +505,6 @@ static void virtfs_reset(V9fsPDU *pdu)
error_report("9pfs:%s: One or more uncluncked fids "
"found during reset", __func__);
}
- return;
}
#define P9_QID_TYPE_DIR 0x80
@@ -934,7 +933,6 @@ static void v9fs_version(void *opaque)
out:
complete_pdu(s, pdu, offset);
v9fs_string_free(&version);
- return;
}
static void v9fs_attach(void *opaque)
@@ -1314,7 +1312,6 @@ out_nofid:
g_free(wnames);
g_free(qids);
}
- return;
}
static int32_t get_iounit(V9fsPDU *pdu, V9fsPath *path)
@@ -2257,7 +2254,6 @@ static void v9fs_flush(void *opaque)
free_pdu(pdu->s, cancel_pdu);
}
complete_pdu(s, pdu, 7);
- return;
}
static void v9fs_link(void *opaque)
@@ -2763,7 +2759,6 @@ out:
put_fid(pdu, fidp);
out_nofid:
complete_pdu(s, pdu, retval);
- return;
}
static void v9fs_mknod(void *opaque)
diff --git a/hw/Makefile.objs b/hw/Makefile.objs
index 24392f568..66ff86897 100644
--- a/hw/Makefile.objs
+++ b/hw/Makefile.objs
@@ -36,6 +36,7 @@ common-obj-$(CONFIG_APPLESMC) += applesmc.o
common-obj-$(CONFIG_SMARTCARD) += ccid-card-passthru.o
common-obj-$(CONFIG_SMARTCARD_NSS) += ccid-card-emulated.o
common-obj-$(CONFIG_I8259) += i8259_common.o i8259.o
+common-obj-y += fifo.o
# PPC devices
common-obj-$(CONFIG_PREP_PCI) += prep_pci.o
@@ -174,6 +175,7 @@ common-obj-y += scsi-disk.o cdrom.o hd-geometry.o block-common.o
common-obj-y += scsi-generic.o scsi-bus.o
common-obj-y += hid.o
common-obj-$(CONFIG_SSI) += ssi.o
+common-obj-$(CONFIG_SSI_M25P80) += m25p80.o
common-obj-$(CONFIG_SSI_SD) += ssi-sd.o
common-obj-$(CONFIG_SD) += sd.o
common-obj-y += bt.o bt-l2cap.o bt-sdp.o bt-hci.o bt-hid.o
diff --git a/hw/ads7846.c b/hw/ads7846.c
index 41c7f101c..2ea9e55bb 100644
--- a/hw/ads7846.c
+++ b/hw/ads7846.c
@@ -119,11 +119,12 @@ static int ads7856_post_load(void *opaque, int version_id)
static const VMStateDescription vmstate_ads7846 = {
.name = "ads7846",
- .version_id = 0,
- .minimum_version_id = 0,
- .minimum_version_id_old = 0,
+ .version_id = 1,
+ .minimum_version_id = 1,
+ .minimum_version_id_old = 1,
.post_load = ads7856_post_load,
.fields = (VMStateField[]) {
+ VMSTATE_SSI_SLAVE(ssidev, ADS7846State),
VMSTATE_INT32_ARRAY(input, ADS7846State, 8),
VMSTATE_INT32(noise, ADS7846State),
VMSTATE_INT32(cycle, ADS7846State),
diff --git a/hw/alpha_dp264.c b/hw/alpha_dp264.c
index 9eb939f38..5ea04c75a 100644
--- a/hw/alpha_dp264.c
+++ b/hw/alpha_dp264.c
@@ -77,7 +77,7 @@ static void clipper_init(ram_addr_t ram_size,
isa_create_simple(isa_bus, "i8042");
/* VGA setup. Don't bother loading the bios. */
- alpha_pci_vga_setup(pci_bus);
+ pci_vga_init(pci_bus);
/* Serial code setup. */
for (i = 0; i < MAX_SERIAL_PORTS; ++i) {
diff --git a/hw/alpha_pci.c b/hw/alpha_pci.c
index ea546f83f..8079a46ae 100644
--- a/hw/alpha_pci.c
+++ b/hw/alpha_pci.c
@@ -10,8 +10,6 @@
#include "alpha_sys.h"
#include "qemu-log.h"
#include "sysemu.h"
-#include "vmware_vga.h"
-#include "vga-pci.h"
/* PCI IO reads/writes, to byte-word addressable memory. */
@@ -109,25 +107,3 @@ const MemoryRegionOps alpha_pci_iack_ops = {
.max_access_size = 4,
},
};
-
-void alpha_pci_vga_setup(PCIBus *pci_bus)
-{
- switch (vga_interface_type) {
-#ifdef CONFIG_SPICE
- case VGA_QXL:
- pci_create_simple(pci_bus, -1, "qxl-vga");
- return;
-#endif
- case VGA_CIRRUS:
- pci_cirrus_vga_init(pci_bus);
- return;
- case VGA_VMWARE:
- pci_vmsvga_init(pci_bus);
- return;
- }
- /* If VGA is enabled at all, and one of the above didn't work, then
- fallback to Standard VGA. */
- if (vga_interface_type != VGA_NONE) {
- pci_vga_init(pci_bus);
- }
-}
diff --git a/hw/alpha_sys.h b/hw/alpha_sys.h
index de40f8b61..7604d09c8 100644
--- a/hw/alpha_sys.h
+++ b/hw/alpha_sys.h
@@ -19,6 +19,4 @@ extern const MemoryRegionOps alpha_pci_bw_io_ops;
extern const MemoryRegionOps alpha_pci_conf1_ops;
extern const MemoryRegionOps alpha_pci_iack_ops;
-void alpha_pci_vga_setup(PCIBus *pci_bus);
-
#endif
diff --git a/hw/arm/Makefile.objs b/hw/arm/Makefile.objs
index 2b39fb3c8..6d049e7de 100644
--- a/hw/arm/Makefile.objs
+++ b/hw/arm/Makefile.objs
@@ -1,6 +1,7 @@
obj-y = integratorcp.o versatilepb.o arm_pic.o
obj-y += arm_boot.o
obj-y += xilinx_zynq.o zynq_slcr.o
+obj-y += xilinx_spips.o
obj-y += arm_gic.o arm_gic_common.o
obj-y += realview_gic.o realview.o arm_sysctl.o arm11mpcore.o a9mpcore.o
obj-y += exynos4210_gic.o exynos4210_combiner.o exynos4210.o
diff --git a/hw/blizzard.c b/hw/blizzard.c
index d1c9d8151..06e19b364 100644
--- a/hw/blizzard.c
+++ b/hw/blizzard.c
@@ -878,8 +878,6 @@ void s1d13745_write_block(void *opaque, int dc,
len -= 2;
buf += 2;
}
-
- return;
}
static void blizzard_update_display(void *opaque)
diff --git a/hw/bt-hci.c b/hw/bt-hci.c
index 47f9a4e49..e54cfd781 100644
--- a/hw/bt-hci.c
+++ b/hw/bt-hci.c
@@ -786,7 +786,6 @@ static void bt_hci_lmp_connection_request(struct bt_link_s *link)
memcpy(&params.dev_class, &link->host->class, sizeof(params.dev_class));
params.link_type = ACL_LINK;
bt_hci_event(hci, EVT_CONN_REQUEST, &params, EVT_CONN_REQUEST_SIZE);
- return;
}
static void bt_hci_conn_accept_timeout(void *opaque)
diff --git a/hw/cirrus_vga.c b/hw/cirrus_vga.c
index 4284c1e2a..df059307b 100644
--- a/hw/cirrus_vga.c
+++ b/hw/cirrus_vga.c
@@ -28,7 +28,6 @@
*/
#include "hw.h"
#include "pci.h"
-#include "vga-pci.h"
#include "console.h"
#include "vga_int.h"
#include "loader.h"
@@ -2970,11 +2969,6 @@ static int pci_cirrus_vga_initfn(PCIDevice *dev)
return 0;
}
-DeviceState *pci_cirrus_vga_init(PCIBus *bus)
-{
- return &pci_create_simple(bus, -1, "cirrus-vga")->qdev;
-}
-
static void cirrus_vga_class_init(ObjectClass *klass, void *data)
{
DeviceClass *dc = DEVICE_CLASS(klass);
diff --git a/hw/device-hotplug.c b/hw/device-hotplug.c
index 2bdc615b4..eec0fe314 100644
--- a/hw/device-hotplug.c
+++ b/hw/device-hotplug.c
@@ -89,5 +89,4 @@ err:
if (dinfo) {
drive_put_ref(dinfo);
}
- return;
}
diff --git a/hw/exynos4210_combiner.c b/hw/exynos4210_combiner.c
index 80af22cc3..60b33c788 100644
--- a/hw/exynos4210_combiner.c
+++ b/hw/exynos4210_combiner.c
@@ -347,8 +347,6 @@ static void exynos4210_combiner_write(void *opaque, target_phys_addr_t offset,
TARGET_FMT_plx "\n", offset);
break;
}
-
- return;
}
/* Get combiner group and bit from irq number */
@@ -380,8 +378,6 @@ static void exynos4210_combiner_handler(void *opaque, int irq, int level)
}
exynos4210_combiner_update(s, group_n);
-
- return;
}
static void exynos4210_combiner_reset(DeviceState *d)
diff --git a/hw/exynos4210_gic.c b/hw/exynos4210_gic.c
index 7d03dd9ae..4fea09873 100644
--- a/hw/exynos4210_gic.c
+++ b/hw/exynos4210_gic.c
@@ -193,8 +193,6 @@ static void exynos4210_irq_handler(void *opaque, int irq, int level)
/* Bypass */
qemu_set_irq(s->board_irqs[irq], level);
-
- return;
}
/*
@@ -410,8 +408,6 @@ static void exynos4210_irq_gate_handler(void *opaque, int irq, int level)
}
qemu_irq_lower(s->out);
-
- return;
}
static void exynos4210_irq_gate_reset(DeviceState *d)
diff --git a/hw/exynos4210_mct.c b/hw/exynos4210_mct.c
index 7a22b1f90..6f94ce230 100644
--- a/hw/exynos4210_mct.c
+++ b/hw/exynos4210_mct.c
@@ -574,8 +574,6 @@ static void exynos4210_gfrc_event(void *opaque)
exynos4210_gfrc_set_count(&s->g_timer, distance);
exynos4210_gfrc_start(&s->g_timer);
-
- return;
}
/*
diff --git a/hw/fdc.c b/hw/fdc.c
index 43b0f2050..25a49e350 100644
--- a/hw/fdc.c
+++ b/hw/fdc.c
@@ -1286,8 +1286,6 @@ static void fdctrl_start_transfer(FDCtrl *fdctrl, int direction)
fdctrl->msr |= FD_MSR_DIO;
/* IO based transfer: calculate len */
fdctrl_raise_irq(fdctrl, FD_SR0_SEEK);
-
- return;
}
/* Prepare a transfer of deleted data */
diff --git a/hw/fifo.c b/hw/fifo.c
new file mode 100644
index 000000000..68a955a77
--- /dev/null
+++ b/hw/fifo.c
@@ -0,0 +1,78 @@
+/*
+ * Generic FIFO component, implemented as a circular buffer.
+ *
+ * Copyright (c) 2012 Peter A. G. Crosthwaite
+ *
+ * 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.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include "fifo.h"
+
+void fifo8_create(Fifo8 *fifo, uint32_t capacity)
+{
+ fifo->data = g_new(uint8_t, capacity);
+ fifo->capacity = capacity;
+ fifo->head = 0;
+ fifo->num = 0;
+}
+
+void fifo8_destroy(Fifo8 *fifo)
+{
+ g_free(fifo->data);
+}
+
+void fifo8_push(Fifo8 *fifo, uint8_t data)
+{
+ if (fifo->num == fifo->capacity) {
+ abort();
+ }
+ fifo->data[(fifo->head + fifo->num) % fifo->capacity] = data;
+ fifo->num++;
+}
+
+uint8_t fifo8_pop(Fifo8 *fifo)
+{
+ uint8_t ret;
+
+ if (fifo->num == 0) {
+ abort();
+ }
+ ret = fifo->data[fifo->head++];
+ fifo->head %= fifo->capacity;
+ fifo->num--;
+ return ret;
+}
+
+void fifo8_reset(Fifo8 *fifo)
+{
+ fifo->num = 0;
+}
+
+bool fifo8_is_empty(Fifo8 *fifo)
+{
+ return (fifo->num == 0);
+}
+
+bool fifo8_is_full(Fifo8 *fifo)
+{
+ return (fifo->num == fifo->capacity);
+}
+
+const VMStateDescription vmstate_fifo8 = {
+ .name = "Fifo8",
+ .version_id = 1,
+ .minimum_version_id = 1,
+ .minimum_version_id_old = 1,
+ .fields = (VMStateField[]) {
+ VMSTATE_VBUFFER_UINT32(data, Fifo8, 1, NULL, 0, capacity),
+ VMSTATE_UINT32(head, Fifo8),
+ VMSTATE_UINT32(num, Fifo8),
+ VMSTATE_END_OF_LIST()
+ }
+};
diff --git a/hw/fifo.h b/hw/fifo.h
new file mode 100644
index 000000000..f23890abf
--- /dev/null
+++ b/hw/fifo.h
@@ -0,0 +1,99 @@
+#ifndef FIFO_H
+#define FIFO_H
+
+#include "hw.h"
+
+typedef struct {
+ /* All fields are private */
+ uint8_t *data;
+ uint32_t capacity;
+ uint32_t head;
+ uint32_t num;
+} Fifo8;
+
+/**
+ * fifo8_create:
+ * @fifo: struct Fifo8 to initialise with new FIFO
+ * @capacity: capacity of the newly created FIFO
+ *
+ * Create a FIFO of the specified size. Clients should call fifo8_destroy()
+ * when finished using the fifo. The FIFO is initially empty.
+ */
+
+void fifo8_create(Fifo8 *fifo, uint32_t capacity);
+
+/**
+ * fifo8_destroy:
+ * @fifo: FIFO to cleanup
+ *
+ * Cleanup a FIFO created with fifo8_create(). Frees memory created for FIFO
+ *storage. The FIFO is no longer usable after this has been called.
+ */
+
+void fifo8_destroy(Fifo8 *fifo);
+
+/**
+ * fifo8_push:
+ * @fifo: FIFO to push to
+ * @data: data byte to push
+ *
+ * Push a data byte to the FIFO. Behaviour is undefined if the FIFO is full.
+ * Clients are responsible for checking for fullness using fifo8_is_full().
+ */
+
+void fifo8_push(Fifo8 *fifo, uint8_t data);
+
+/**
+ * fifo8_pop:
+ * @fifo: fifo to pop from
+ *
+ * Pop a data byte from the FIFO. Behaviour is undefined if the FIFO is empty.
+ * Clients are responsible for checking for emptyness using fifo8_is_empty().
+ *
+ * Returns: The popped data byte.
+ */
+
+uint8_t fifo8_pop(Fifo8 *fifo);
+
+/**
+ * fifo8_reset:
+ * @fifo: FIFO to reset
+ *
+ * Reset a FIFO. All data is discarded and the FIFO is emptied.
+ */
+
+void fifo8_reset(Fifo8 *fifo);
+
+/**
+ * fifo8_is_empty:
+ * @fifo: FIFO to check
+ *
+ * Check if a FIFO is empty.
+ *
+ * Returns: True if the fifo is empty, false otherwise.
+ */
+
+bool fifo8_is_empty(Fifo8 *fifo);
+
+/**
+ * fifo8_is_full:
+ * @fifo: FIFO to check
+ *
+ * Check if a FIFO is full.
+ *
+ * Returns: True if the fifo is full, false otherwise.
+ */
+
+bool fifo8_is_full(Fifo8 *fifo);
+
+extern const VMStateDescription vmstate_fifo8;
+
+#define VMSTATE_FIFO8(_field, _state) { \
+ .name = (stringify(_field)), \
+ .size = sizeof(Fifo8), \
+ .vmsd = &vmstate_fifo8, \
+ .flags = VMS_STRUCT, \
+ .offset = vmstate_offset_value(_state, _field, Fifo8), \
+}
+
+#endif /* FIFO_H */
diff --git a/hw/framebuffer.c b/hw/framebuffer.c
index 85a00a579..27fa6f51f 100644
--- a/hw/framebuffer.c
+++ b/hw/framebuffer.c
@@ -107,5 +107,4 @@ void framebuffer_update_display(
DIRTY_MEMORY_VGA);
*first_row = first;
*last_row = last;
- return;
}
diff --git a/hw/ide/macio.c b/hw/ide/macio.c
index 848cb3142..f22872514 100644
--- a/hw/ide/macio.c
+++ b/hw/ide/macio.c
@@ -89,7 +89,6 @@ static void pmac_ide_atapi_transfer_cb(void *opaque, int ret)
done:
bdrv_acct_done(s->bs, &s->acct);
io->dma_end(opaque);
- return;
}
static void pmac_ide_transfer_cb(void *opaque, int ret)
diff --git a/hw/irq.c b/hw/irq.c
index d413a0b23..f4e2a7804 100644
--- a/hw/irq.c
+++ b/hw/irq.c
@@ -38,24 +38,37 @@ void qemu_set_irq(qemu_irq irq, int level)
irq->handler(irq->opaque, irq->n, level);
}
-qemu_irq *qemu_allocate_irqs(qemu_irq_handler handler, void *opaque, int n)
+qemu_irq *qemu_extend_irqs(qemu_irq *old, int n_old, qemu_irq_handler handler,
+ void *opaque, int n)
{
qemu_irq *s;
struct IRQState *p;
int i;
- s = (qemu_irq *)g_malloc0(sizeof(qemu_irq) * n);
- p = (struct IRQState *)g_malloc0(sizeof(struct IRQState) * n);
- for (i = 0; i < n; i++) {
- p->handler = handler;
- p->opaque = opaque;
- p->n = i;
+ if (!old) {
+ n_old = 0;
+ }
+ s = old ? g_renew(qemu_irq, old, n + n_old) : g_new(qemu_irq, n);
+ p = old ? g_renew(struct IRQState, s[0], n + n_old) :
+ g_new(struct IRQState, n);
+ for (i = 0; i < n + n_old; i++) {
+ if (i >= n_old) {
+ p->handler = handler;
+ p->opaque = opaque;
+ p->n = i;
+ }
s[i] = p;
p++;
}
return s;
}
+qemu_irq *qemu_allocate_irqs(qemu_irq_handler handler, void *opaque, int n)
+{
+ return qemu_extend_irqs(NULL, 0, handler, opaque, n);
+}
+
+
void qemu_free_irqs(qemu_irq *s)
{
g_free(s[0]);
diff --git a/hw/irq.h b/hw/irq.h
index 56c55f0c4..e640c105e 100644
--- a/hw/irq.h
+++ b/hw/irq.h
@@ -23,8 +23,17 @@ static inline void qemu_irq_pulse(qemu_irq irq)
qemu_set_irq(irq, 0);
}
-/* Returns an array of N IRQs. */
+/* Returns an array of N IRQs. Each IRQ is assigned the argument handler and
+ * opaque data.
+ */
qemu_irq *qemu_allocate_irqs(qemu_irq_handler handler, void *opaque, int n);
+
+/* Extends an Array of IRQs. Old IRQs have their handlers and opaque data
+ * preserved. New IRQs are assigned the argument handler and opaque data.
+ */
+qemu_irq *qemu_extend_irqs(qemu_irq *old, int n_old, qemu_irq_handler handler,
+ void *opaque, int n);
+
void qemu_free_irqs(qemu_irq *s);
/* Returns a new IRQ with opposite polarity. */
diff --git a/hw/isa-bus.c b/hw/isa-bus.c
index 47c93d37b..214f19457 100644
--- a/hw/isa-bus.c
+++ b/hw/isa-bus.c
@@ -19,6 +19,7 @@
#include "hw.h"
#include "monitor.h"
#include "sysbus.h"
+#include "sysemu.h"
#include "isa.h"
#include "exec-memory.h"
@@ -166,6 +167,25 @@ ISADevice *isa_create_simple(ISABus *bus, const char *name)
return dev;
}
+ISADevice *isa_vga_init(ISABus *bus)
+{
+ switch (vga_interface_type) {
+ case VGA_CIRRUS:
+ return isa_create_simple(bus, "isa-cirrus-vga");
+ case VGA_QXL:
+ fprintf(stderr, "%s: qxl: no PCI bus\n", __func__);
+ return NULL;
+ case VGA_STD:
+ return isa_create_simple(bus, "isa-vga");
+ case VGA_VMWARE:
+ fprintf(stderr, "%s: vmware_vga: no PCI bus\n", __func__);
+ return NULL;
+ case VGA_NONE:
+ default:
+ return NULL;
+ }
+}
+
static void isabus_dev_print(Monitor *mon, DeviceState *dev, int indent)
{
ISADevice *d = ISA_DEVICE(dev);
diff --git a/hw/isa.h b/hw/isa.h
index dc970527a..8fb498aa8 100644
--- a/hw/isa.h
+++ b/hw/isa.h
@@ -47,6 +47,8 @@ ISADevice *isa_create(ISABus *bus, const char *name);
ISADevice *isa_try_create(ISABus *bus, const char *name);
ISADevice *isa_create_simple(ISABus *bus, const char *name);
+ISADevice *isa_vga_init(ISABus *bus);
+
/**
* isa_register_ioport: Install an I/O port region on the ISA bus.
*
diff --git a/hw/ivshmem.c b/hw/ivshmem.c
index 59f1aa426..5c4ccb85f 100644
--- a/hw/ivshmem.c
+++ b/hw/ivshmem.c
@@ -149,7 +149,6 @@ static void ivshmem_IntrStatus_write(IVShmemState *s, uint32_t val)
s->intrstatus = val;
ivshmem_update_irq(s, val);
- return;
}
static uint32_t ivshmem_IntrStatus_read(IVShmemState *s)
@@ -510,8 +509,6 @@ static void ivshmem_read(void *opaque, const uint8_t * buf, int flags)
if (ivshmem_has_feature(s, IVSHMEM_IOEVENTFD)) {
ivshmem_add_eventfd(s, incoming_posn, guest_max_eventfd);
}
-
- return;
}
/* Select the MSI-X vectors used by device.
@@ -536,7 +533,6 @@ static void ivshmem_reset(DeviceState *d)
s->intrstatus = 0;
ivshmem_use_msix(s);
- return;
}
static uint64_t ivshmem_get_size(IVShmemState * s) {
diff --git a/hw/leon3.c b/hw/leon3.c
index 878d3aa55..7a9729dc2 100644
--- a/hw/leon3.c
+++ b/hw/leon3.c
@@ -210,7 +210,7 @@ static void leon3_generic_hw_init(ram_addr_t ram_size,
}
}
-QEMUMachine leon3_generic_machine = {
+static QEMUMachine leon3_generic_machine = {
.name = "leon3_generic",
.desc = "Leon-3 generic",
.init = leon3_generic_hw_init,
diff --git a/hw/m25p80.c b/hw/m25p80.c
new file mode 100644
index 000000000..9a56de802
--- /dev/null
+++ b/hw/m25p80.c
@@ -0,0 +1,598 @@
+/*
+ * ST M25P80 emulator. Emulate all SPI flash devices based on the m25p80 command
+ * set. Known devices table current as of Jun/2012 and taken from linux.
+ * See drivers/mtd/devices/m25p80.c.
+ *
+ * Copyright (C) 2011 Edgar E. Iglesias <edgar.iglesias@gmail.com>
+ * Copyright (C) 2012 Peter A. G. Crosthwaite <peter.crosthwaite@petalogix.com>
+ * Copyright (C) 2012 PetaLogix
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 or
+ * (at your option) a later version of the License.
+ *
+ * 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, see <http://www.gnu.org/licenses/>.
+ */
+
+#include "hw.h"
+#include "blockdev.h"
+#include "ssi.h"
+#include "devices.h"
+
+#ifdef M25P80_ERR_DEBUG
+#define DB_PRINT(...) do { \
+ fprintf(stderr, ": %s: ", __func__); \
+ fprintf(stderr, ## __VA_ARGS__); \
+ } while (0);
+#else
+ #define DB_PRINT(...)
+#endif
+
+/* Fields for FlashPartInfo->flags */
+
+/* erase capabilities */
+#define ER_4K 1
+#define ER_32K 2
+/* set to allow the page program command to write 0s back to 1. Useful for
+ * modelling EEPROM with SPI flash command set
+ */
+#define WR_1 0x100
+
+typedef struct FlashPartInfo {
+ const char *part_name;
+ /* jedec code. (jedec >> 16) & 0xff is the 1st byte, >> 8 the 2nd etc */
+ uint32_t jedec;
+ /* extended jedec code */
+ uint16_t ext_jedec;
+ /* there is confusion between manufacturers as to what a sector is. In this
+ * device model, a "sector" is the size that is erased by the ERASE_SECTOR
+ * command (opcode 0xd8).
+ */
+ uint32_t sector_size;
+ uint32_t n_sectors;
+ uint32_t page_size;
+ uint8_t flags;
+} FlashPartInfo;
+
+/* adapted from linux */
+
+#define INFO(_part_name, _jedec, _ext_jedec, _sector_size, _n_sectors, _flags)\
+ .part_name = (_part_name),\
+ .jedec = (_jedec),\
+ .ext_jedec = (_ext_jedec),\
+ .sector_size = (_sector_size),\
+ .n_sectors = (_n_sectors),\
+ .page_size = 256,\
+ .flags = (_flags),\
+
+static const FlashPartInfo known_devices[] = {
+ /* Atmel -- some are (confusingly) marketed as "DataFlash" */
+ { INFO("at25fs010", 0x1f6601, 0, 32 << 10, 4, ER_4K) },
+ { INFO("at25fs040", 0x1f6604, 0, 64 << 10, 8, ER_4K) },
+
+ { INFO("at25df041a", 0x1f4401, 0, 64 << 10, 8, ER_4K) },
+ { INFO("at25df321a", 0x1f4701, 0, 64 << 10, 64, ER_4K) },
+ { INFO("at25df641", 0x1f4800, 0, 64 << 10, 128, ER_4K) },
+
+ { INFO("at26f004", 0x1f0400, 0, 64 << 10, 8, ER_4K) },
+ { INFO("at26df081a", 0x1f4501, 0, 64 << 10, 16, ER_4K) },
+ { INFO("at26df161a", 0x1f4601, 0, 64 << 10, 32, ER_4K) },
+ { INFO("at26df321", 0x1f4700, 0, 64 << 10, 64, ER_4K) },
+
+ /* EON -- en25xxx */
+ { INFO("en25f32", 0x1c3116, 0, 64 << 10, 64, ER_4K) },
+ { INFO("en25p32", 0x1c2016, 0, 64 << 10, 64, 0) },
+ { INFO("en25q32b", 0x1c3016, 0, 64 << 10, 64, 0) },
+ { INFO("en25p64", 0x1c2017, 0, 64 << 10, 128, 0) },
+
+ /* Intel/Numonyx -- xxxs33b */
+ { INFO("160s33b", 0x898911, 0, 64 << 10, 32, 0) },
+ { INFO("320s33b", 0x898912, 0, 64 << 10, 64, 0) },
+ { INFO("640s33b", 0x898913, 0, 64 << 10, 128, 0) },
+
+ /* Macronix */
+ { INFO("mx25l4005a", 0xc22013, 0, 64 << 10, 8, ER_4K) },
+ { INFO("mx25l8005", 0xc22014, 0, 64 << 10, 16, 0) },
+ { INFO("mx25l1606e", 0xc22015, 0, 64 << 10, 32, ER_4K) },
+ { INFO("mx25l3205d", 0xc22016, 0, 64 << 10, 64, 0) },
+ { INFO("mx25l6405d", 0xc22017, 0, 64 << 10, 128, 0) },
+ { INFO("mx25l12805d", 0xc22018, 0, 64 << 10, 256, 0) },
+ { INFO("mx25l12855e", 0xc22618, 0, 64 << 10, 256, 0) },
+ { INFO("mx25l25635e", 0xc22019, 0, 64 << 10, 512, 0) },
+ { INFO("mx25l25655e", 0xc22619, 0, 64 << 10, 512, 0) },
+
+ /* Spansion -- single (large) sector size only, at least
+ * for the chips listed here (without boot sectors).
+ */
+ { INFO("s25sl004a", 0x010212, 0, 64 << 10, 8, 0) },
+ { INFO("s25sl008a", 0x010213, 0, 64 << 10, 16, 0) },
+ { INFO("s25sl016a", 0x010214, 0, 64 << 10, 32, 0) },
+ { INFO("s25sl032a", 0x010215, 0, 64 << 10, 64, 0) },
+ { INFO("s25sl032p", 0x010215, 0x4d00, 64 << 10, 64, ER_4K) },
+ { INFO("s25sl064a", 0x010216, 0, 64 << 10, 128, 0) },
+ { INFO("s25fl256s0", 0x010219, 0x4d00, 256 << 10, 128, 0) },
+ { INFO("s25fl256s1", 0x010219, 0x4d01, 64 << 10, 512, 0) },
+ { INFO("s25fl512s", 0x010220, 0x4d00, 256 << 10, 256, 0) },
+ { INFO("s70fl01gs", 0x010221, 0x4d00, 256 << 10, 256, 0) },
+ { INFO("s25sl12800", 0x012018, 0x0300, 256 << 10, 64, 0) },
+ { INFO("s25sl12801", 0x012018, 0x0301, 64 << 10, 256, 0) },
+ { INFO("s25fl129p0", 0x012018, 0x4d00, 256 << 10, 64, 0) },
+ { INFO("s25fl129p1", 0x012018, 0x4d01, 64 << 10, 256, 0) },
+ { INFO("s25fl016k", 0xef4015, 0, 64 << 10, 32, ER_4K | ER_32K) },
+ { INFO("s25fl064k", 0xef4017, 0, 64 << 10, 128, ER_4K | ER_32K) },
+
+ /* SST -- large erase sizes are "overlays", "sectors" are 4<< 10 */
+ { INFO("sst25vf040b", 0xbf258d, 0, 64 << 10, 8, ER_4K) },
+ { INFO("sst25vf080b", 0xbf258e, 0, 64 << 10, 16, ER_4K) },
+ { INFO("sst25vf016b", 0xbf2541, 0, 64 << 10, 32, ER_4K) },
+ { INFO("sst25vf032b", 0xbf254a, 0, 64 << 10, 64, ER_4K) },
+ { INFO("sst25wf512", 0xbf2501, 0, 64 << 10, 1, ER_4K) },
+ { INFO("sst25wf010", 0xbf2502, 0, 64 << 10, 2, ER_4K) },
+ { INFO("sst25wf020", 0xbf2503, 0, 64 << 10, 4, ER_4K) },
+ { INFO("sst25wf040", 0xbf2504, 0, 64 << 10, 8, ER_4K) },
+
+ /* ST Microelectronics -- newer production may have feature updates */
+ { INFO("m25p05", 0x202010, 0, 32 << 10, 2, 0) },
+ { INFO("m25p10", 0x202011, 0, 32 << 10, 4, 0) },
+ { INFO("m25p20", 0x202012, 0, 64 << 10, 4, 0) },
+ { INFO("m25p40", 0x202013, 0, 64 << 10, 8, 0) },
+ { INFO("m25p80", 0x202014, 0, 64 << 10, 16, 0) },
+ { INFO("m25p16", 0x202015, 0, 64 << 10, 32, 0) },
+ { INFO("m25p32", 0x202016, 0, 64 << 10, 64, 0) },
+ { INFO("m25p64", 0x202017, 0, 64 << 10, 128, 0) },
+ { INFO("m25p128", 0x202018, 0, 256 << 10, 64, 0) },
+
+ { INFO("m45pe10", 0x204011, 0, 64 << 10, 2, 0) },
+ { INFO("m45pe80", 0x204014, 0, 64 << 10, 16, 0) },
+ { INFO("m45pe16", 0x204015, 0, 64 << 10, 32, 0) },
+
+ { INFO("m25pe80", 0x208014, 0, 64 << 10, 16, 0) },
+ { INFO("m25pe16", 0x208015, 0, 64 << 10, 32, ER_4K) },
+
+ { INFO("m25px32", 0x207116, 0, 64 << 10, 64, ER_4K) },
+ { INFO("m25px32-s0", 0x207316, 0, 64 << 10, 64, ER_4K) },
+ { INFO("m25px32-s1", 0x206316, 0, 64 << 10, 64, ER_4K) },
+ { INFO("m25px64", 0x207117, 0, 64 << 10, 128, 0) },
+
+ /* Winbond -- w25x "blocks" are 64k, "sectors" are 4KiB */
+ { INFO("w25x10", 0xef3011, 0, 64 << 10, 2, ER_4K) },
+ { INFO("w25x20", 0xef3012, 0, 64 << 10, 4, ER_4K) },
+ { INFO("w25x40", 0xef3013, 0, 64 << 10, 8, ER_4K) },
+ { INFO("w25x80", 0xef3014, 0, 64 << 10, 16, ER_4K) },
+ { INFO("w25x16", 0xef3015, 0, 64 << 10, 32, ER_4K) },
+ { INFO("w25x32", 0xef3016, 0, 64 << 10, 64, ER_4K) },
+ { INFO("w25q32", 0xef4016, 0, 64 << 10, 64, ER_4K) },
+ { INFO("w25x64", 0xef3017, 0, 64 << 10, 128, ER_4K) },
+ { INFO("w25q64", 0xef4017, 0, 64 << 10, 128, ER_4K) },
+
+ /* Numonyx -- n25q128 */
+ { INFO("n25q128", 0x20ba18, 0, 64 << 10, 256, 0) },
+
+ { },
+};
+
+typedef enum {
+ NOP = 0,
+ PP = 0x2,
+ READ = 0x3,
+ WRDI = 0x4,
+ RDSR = 0x5,
+ WREN = 0x6,
+ FAST_READ = 0xb,
+ ERASE_4K = 0x20,
+ ERASE_32K = 0x52,
+ ERASE_SECTOR = 0xd8,
+ JEDEC_READ = 0x9f,
+ BULK_ERASE = 0xc7,
+} FlashCMD;
+
+typedef enum {
+ STATE_IDLE,
+ STATE_PAGE_PROGRAM,
+ STATE_READ,
+ STATE_COLLECTING_DATA,
+ STATE_READING_DATA,
+} CMDState;
+
+typedef struct Flash {
+ SSISlave ssidev;
+ uint32_t r;
+
+ BlockDriverState *bdrv;
+
+ uint8_t *storage;
+ uint32_t size;
+ int page_size;
+
+ uint8_t state;
+ uint8_t data[16];
+ uint32_t len;
+ uint32_t pos;
+ uint8_t needed_bytes;
+ uint8_t cmd_in_progress;
+ uint64_t cur_addr;
+ bool write_enable;
+
+ int64_t dirty_page;
+
+ char *part_name;
+ const FlashPartInfo *pi;
+
+} Flash;
+
+static void bdrv_sync_complete(void *opaque, int ret)
+{
+ /* do nothing. Masters do not directly interact with the backing store,
+ * only the working copy so no mutexing required.
+ */
+}
+
+static void flash_sync_page(Flash *s, int page)
+{
+ if (s->bdrv) {
+ int bdrv_sector, nb_sectors;
+ QEMUIOVector iov;
+
+ bdrv_sector = (page * s->pi->page_size) / BDRV_SECTOR_SIZE;
+ nb_sectors = DIV_ROUND_UP(s->pi->page_size, BDRV_SECTOR_SIZE);
+ qemu_iovec_init(&iov, 1);
+ qemu_iovec_add(&iov, s->storage + bdrv_sector * BDRV_SECTOR_SIZE,
+ nb_sectors * BDRV_SECTOR_SIZE);
+ bdrv_aio_writev(s->bdrv, bdrv_sector, &iov, nb_sectors,
+ bdrv_sync_complete, NULL);
+ }
+}
+
+static inline void flash_sync_area(Flash *s, int64_t off, int64_t len)
+{
+ int64_t start, end, nb_sectors;
+ QEMUIOVector iov;
+
+ if (!s->bdrv) {
+ return;
+ }
+
+ assert(!(len % BDRV_SECTOR_SIZE));
+ start = off / BDRV_SECTOR_SIZE;
+ end = (off + len) / BDRV_SECTOR_SIZE;
+ nb_sectors = end - start;
+ qemu_iovec_init(&iov, 1);
+ qemu_iovec_add(&iov, s->storage + (start * BDRV_SECTOR_SIZE),
+ nb_sectors * BDRV_SECTOR_SIZE);
+ bdrv_aio_writev(s->bdrv, start, &iov, nb_sectors, bdrv_sync_complete, NULL);
+}
+
+static void flash_erase(Flash *s, int offset, FlashCMD cmd)
+{
+ uint32_t len;
+ uint8_t capa_to_assert = 0;
+
+ switch (cmd) {
+ case ERASE_4K:
+ len = 4 << 10;
+ capa_to_assert = ER_4K;
+ break;
+ case ERASE_32K:
+ len = 32 << 10;
+ capa_to_assert = ER_32K;
+ break;
+ case ERASE_SECTOR:
+ len = s->pi->sector_size;
+ break;
+ case BULK_ERASE:
+ len = s->size;
+ break;
+ default:
+ abort();
+ }
+
+ DB_PRINT("offset = %#x, len = %d\n", offset, len);
+ if ((s->pi->flags & capa_to_assert) != capa_to_assert) {
+ hw_error("m25p80: %dk erase size not supported by device\n", len);
+ }
+
+ if (!s->write_enable) {
+ DB_PRINT("erase with write protect!\n");
+ return;
+ }
+ memset(s->storage + offset, 0xff, len);
+ flash_sync_area(s, offset, len);
+}
+
+static inline void flash_sync_dirty(Flash *s, int64_t newpage)
+{
+ if (s->dirty_page >= 0 && s->dirty_page != newpage) {
+ flash_sync_page(s, s->dirty_page);
+ s->dirty_page = newpage;
+ }
+}
+
+static inline
+void flash_write8(Flash *s, uint64_t addr, uint8_t data)
+{
+ int64_t page = addr / s->pi->page_size;
+ uint8_t prev = s->storage[s->cur_addr];
+
+ if (!s->write_enable) {
+ DB_PRINT("write with write protect!\n");
+ }
+
+ if ((prev ^ data) & data) {
+ DB_PRINT("programming zero to one! addr=%lx %x -> %x\n",
+ addr, prev, data);
+ }
+
+ if (s->pi->flags & WR_1) {
+ s->storage[s->cur_addr] = data;
+ } else {
+ s->storage[s->cur_addr] &= data;
+ }
+
+ flash_sync_dirty(s, page);
+ s->dirty_page = page;
+}
+
+static void complete_collecting_data(Flash *s)
+{
+ s->cur_addr = s->data[0] << 16;
+ s->cur_addr |= s->data[1] << 8;
+ s->cur_addr |= s->data[2];
+
+ switch (s->cmd_in_progress) {
+ case PP:
+ s->state = STATE_PAGE_PROGRAM;
+ break;
+ case READ:
+ case FAST_READ:
+ s->state = STATE_READ;
+ break;
+ case ERASE_4K:
+ case ERASE_32K:
+ case ERASE_SECTOR:
+ flash_erase(s, s->cur_addr, s->cmd_in_progress);
+ break;
+ default:
+ break;
+ }
+}
+
+static void decode_new_cmd(Flash *s, uint32_t value)
+{
+ s->cmd_in_progress = value;
+ DB_PRINT("decoded new command:%x\n", value);
+
+ switch (value) {
+
+ case ERASE_4K:
+ case ERASE_32K:
+ case ERASE_SECTOR:
+ case READ:
+ case PP:
+ s->needed_bytes = 3;
+ s->pos = 0;
+ s->len = 0;
+ s->state = STATE_COLLECTING_DATA;
+ break;
+
+ case FAST_READ:
+ s->needed_bytes = 4;
+ s->pos = 0;
+ s->len = 0;
+ s->state = STATE_COLLECTING_DATA;
+ break;
+
+ case WRDI:
+ s->write_enable = false;
+ break;
+ case WREN:
+ s->write_enable = true;
+ break;
+
+ case RDSR:
+ s->data[0] = (!!s->write_enable) << 1;
+ s->pos = 0;
+ s->len = 1;
+ s->state = STATE_READING_DATA;
+ break;
+
+ case JEDEC_READ:
+ DB_PRINT("populated jedec code\n");
+ s->data[0] = (s->pi->jedec >> 16) & 0xff;
+ s->data[1] = (s->pi->jedec >> 8) & 0xff;
+ s->data[2] = s->pi->jedec & 0xff;
+ if (s->pi->ext_jedec) {
+ s->data[3] = (s->pi->ext_jedec >> 8) & 0xff;
+ s->data[4] = s->pi->ext_jedec & 0xff;
+ s->len = 5;
+ } else {
+ s->len = 3;
+ }
+ s->pos = 0;
+ s->state = STATE_READING_DATA;
+ break;
+
+ case BULK_ERASE:
+ if (s->write_enable) {
+ DB_PRINT("chip erase\n");
+ flash_erase(s, 0, BULK_ERASE);
+ } else {
+ DB_PRINT("chip erase with write protect!\n");
+ }
+ break;
+ case NOP:
+ break;
+ default:
+ DB_PRINT("Unknown cmd %x\n", value);
+ break;
+ }
+}
+
+static int m25p80_cs(SSISlave *ss, bool select)
+{
+ Flash *s = FROM_SSI_SLAVE(Flash, ss);
+
+ if (select) {
+ s->len = 0;
+ s->pos = 0;
+ s->state = STATE_IDLE;
+ flash_sync_dirty(s, -1);
+ }
+
+ DB_PRINT("%sselect\n", select ? "de" : "");
+
+ return 0;
+}
+
+static uint32_t m25p80_transfer8(SSISlave *ss, uint32_t tx)
+{
+ Flash *s = FROM_SSI_SLAVE(Flash, ss);
+ uint32_t r = 0;
+
+ switch (s->state) {
+
+ case STATE_PAGE_PROGRAM:
+ DB_PRINT("page program cur_addr=%lx data=%x\n", s->cur_addr,
+ (uint8_t)tx);
+ flash_write8(s, s->cur_addr, (uint8_t)tx);
+ s->cur_addr++;
+ break;
+
+ case STATE_READ:
+ r = s->storage[s->cur_addr];
+ DB_PRINT("READ 0x%lx=%x\n", s->cur_addr, r);
+ s->cur_addr = (s->cur_addr + 1) % s->size;
+ break;
+
+ case STATE_COLLECTING_DATA:
+ s->data[s->len] = (uint8_t)tx;
+ s->len++;
+
+ if (s->len == s->needed_bytes) {
+ complete_collecting_data(s);
+ }
+ break;
+
+ case STATE_READING_DATA:
+ r = s->data[s->pos];
+ s->pos++;
+ if (s->pos == s->len) {
+ s->pos = 0;
+ s->state = STATE_IDLE;
+ }
+ break;
+
+ default:
+ case STATE_IDLE:
+ decode_new_cmd(s, (uint8_t)tx);
+ break;
+ }
+
+ return r;
+}
+
+static int m25p80_init(SSISlave *ss)
+{
+ DriveInfo *dinfo;
+ Flash *s = FROM_SSI_SLAVE(Flash, ss);
+ const FlashPartInfo *i;
+
+ if (!s->part_name) { /* default to actual m25p80 if no partname given */
+ s->part_name = (char *)"m25p80";
+ }
+
+ i = known_devices;
+ for (i = known_devices;; i++) {
+ assert(i);
+ if (!i->part_name) {
+ fprintf(stderr, "Unknown SPI flash part: \"%s\"\n", s->part_name);
+ return 1;
+ } else if (!strcmp(i->part_name, s->part_name)) {
+ s->pi = i;
+ break;
+ }
+ }
+
+ s->size = s->pi->sector_size * s->pi->n_sectors;
+ s->dirty_page = -1;
+ s->storage = qemu_blockalign(s->bdrv, s->size);
+
+ dinfo = drive_get_next(IF_MTD);
+
+ if (dinfo && dinfo->bdrv) {
+ DB_PRINT("Binding to IF_MTD drive\n");
+ s->bdrv = dinfo->bdrv;
+ /* FIXME: Move to late init */
+ if (bdrv_read(s->bdrv, 0, s->storage, DIV_ROUND_UP(s->size,
+ BDRV_SECTOR_SIZE))) {
+ fprintf(stderr, "Failed to initialize SPI flash!\n");
+ return 1;
+ }
+ } else {
+ memset(s->storage, 0xFF, s->size);
+ }
+
+ return 0;
+}
+
+static void m25p80_pre_save(void *opaque)
+{
+ flash_sync_dirty((Flash *)opaque, -1);
+}
+
+static const VMStateDescription vmstate_m25p80 = {
+ .name = "xilinx_spi",
+ .version_id = 1,
+ .minimum_version_id = 1,
+ .minimum_version_id_old = 1,
+ .pre_save = m25p80_pre_save,
+ .fields = (VMStateField[]) {
+ VMSTATE_UINT8(state, Flash),
+ VMSTATE_UINT8_ARRAY(data, Flash, 16),
+ VMSTATE_UINT32(len, Flash),
+ VMSTATE_UINT32(pos, Flash),
+ VMSTATE_UINT8(needed_bytes, Flash),
+ VMSTATE_UINT8(cmd_in_progress, Flash),
+ VMSTATE_UINT64(cur_addr, Flash),
+ VMSTATE_BOOL(write_enable, Flash),
+ VMSTATE_END_OF_LIST()
+ }
+};
+
+static Property m25p80_properties[] = {
+ DEFINE_PROP_STRING("partname", Flash, part_name),
+ DEFINE_PROP_END_OF_LIST(),
+};
+
+static void m25p80_class_init(ObjectClass *klass, void *data)
+{
+ DeviceClass *dc = DEVICE_CLASS(klass);
+ SSISlaveClass *k = SSI_SLAVE_CLASS(klass);
+
+ k->init = m25p80_init;
+ k->transfer = m25p80_transfer8;
+ k->set_cs = m25p80_cs;
+ k->cs_polarity = SSI_CS_LOW;
+ dc->props = m25p80_properties;
+ dc->vmsd = &vmstate_m25p80;
+}
+
+static const TypeInfo m25p80_info = {
+ .name = "m25p80",
+ .parent = TYPE_SSI_SLAVE,
+ .instance_size = sizeof(Flash),
+ .class_init = m25p80_class_init,
+};
+
+static void m25p80_register_types(void)
+{
+ type_register_static(&m25p80_info);
+}
+
+type_init(m25p80_register_types)
diff --git a/hw/max111x.c b/hw/max111x.c
index 706d89f4f..67640f109 100644
--- a/hw/max111x.c
+++ b/hw/max111x.c
@@ -99,10 +99,11 @@ static uint32_t max111x_transfer(SSISlave *dev, uint32_t value)
static const VMStateDescription vmstate_max111x = {
.name = "max111x",
- .version_id = 0,
- .minimum_version_id = 0,
- .minimum_version_id_old = 0,
+ .version_id = 1,
+ .minimum_version_id = 1,
+ .minimum_version_id_old = 1,
.fields = (VMStateField[]) {
+ VMSTATE_SSI_SLAVE(ssidev, MAX111xState),
VMSTATE_UINT8(tb1, MAX111xState),
VMSTATE_UINT8(rb2, MAX111xState),
VMSTATE_UINT8(rb3, MAX111xState),
diff --git a/hw/megasas.c b/hw/megasas.c
index c728aea69..0e57740fd 100644
--- a/hw/megasas.c
+++ b/hw/megasas.c
@@ -652,7 +652,6 @@ static void megasas_finish_dcmd(MegasasCmd *cmd, uint32_t iov_size)
}
}
cmd->iov_size = 0;
- return;
}
static int megasas_ctrl_get_info(MegasasState *s, MegasasCmd *cmd)
diff --git a/hw/microblaze/Makefile.objs b/hw/microblaze/Makefile.objs
index 274d2c543..3028e651c 100644
--- a/hw/microblaze/Makefile.objs
+++ b/hw/microblaze/Makefile.objs
@@ -1,6 +1,7 @@
obj-y = petalogix_s3adsp1800_mmu.o
obj-y += petalogix_ml605_mmu.o
obj-y += microblaze_boot.o
+obj-y += xilinx_spi.o
obj-y += microblaze_pic_cpu.o
obj-y += xilinx_ethlite.o
diff --git a/hw/mips_fulong2e.c b/hw/mips_fulong2e.c
index 38e4b8615..d4a8672f2 100644
--- a/hw/mips_fulong2e.c
+++ b/hw/mips_fulong2e.c
@@ -392,7 +392,7 @@ static void mips_fulong2e_init(ram_addr_t ram_size, const char *boot_device,
network_init();
}
-QEMUMachine mips_fulong2e_machine = {
+static QEMUMachine mips_fulong2e_machine = {
.name = "fulong2e",
.desc = "Fulong 2e mini pc",
.init = mips_fulong2e_init,
diff --git a/hw/mips_malta.c b/hw/mips_malta.c
index ad23f26e5..632b466e3 100644
--- a/hw/mips_malta.c
+++ b/hw/mips_malta.c
@@ -33,7 +33,6 @@
#include "mips.h"
#include "mips_cpudevs.h"
#include "pci.h"
-#include "vmware_vga.h"
#include "qemu-char.h"
#include "sysemu.h"
#include "arch_init.h"
@@ -48,7 +47,6 @@
#include "blockdev.h"
#include "exec-memory.h"
#include "sysbus.h" /* SysBusDevice */
-#include "vga-pci.h"
//#define DEBUG_BOARD_INIT
@@ -987,13 +985,7 @@ void mips_malta_init (ram_addr_t ram_size,
network_init();
/* Optional PCI video card */
- if (cirrus_vga_enabled) {
- pci_cirrus_vga_init(pci_bus);
- } else if (vmsvga_enabled) {
- pci_vmsvga_init(pci_bus);
- } else if (std_vga_enabled) {
- pci_vga_init(pci_bus);
- }
+ pci_vga_init(pci_bus);
}
static int mips_malta_sysbus_device_init(SysBusDevice *sysbusdev)
diff --git a/hw/msix.c b/hw/msix.c
index d81209413..b623cb597 100644
--- a/hw/msix.c
+++ b/hw/msix.c
@@ -366,7 +366,6 @@ void msix_uninit(PCIDevice *dev, MemoryRegion *table_bar, MemoryRegion *pba_bar)
g_free(dev->msix_entry_used);
dev->msix_entry_used = NULL;
dev->cap_present &= ~QEMU_PCI_CAP_MSIX;
- return;
}
void msix_uninit_exclusive_bar(PCIDevice *dev)
diff --git a/hw/pc.c b/hw/pc.c
index 52bc4618b..0e417c9cb 100644
--- a/hw/pc.c
+++ b/hw/pc.c
@@ -27,7 +27,6 @@
#include "fdc.h"
#include "ide.h"
#include "pci.h"
-#include "vmware_vga.h"
#include "monitor.h"
#include "fw_cfg.h"
#include "hpet_emul.h"
@@ -51,7 +50,6 @@
#include "exec-memory.h"
#include "arch_init.h"
#include "bitmap.h"
-#include "vga-pci.h"
/* debug PC/ISA interrupts */
//#define DEBUG_IRQ
@@ -992,34 +990,13 @@ DeviceState *pc_vga_init(ISABus *isa_bus, PCIBus *pci_bus)
{
DeviceState *dev = NULL;
- if (cirrus_vga_enabled) {
- if (pci_bus) {
- dev = pci_cirrus_vga_init(pci_bus);
- } else {
- dev = &isa_create_simple(isa_bus, "isa-cirrus-vga")->qdev;
- }
- } else if (vmsvga_enabled) {
- if (pci_bus) {
- dev = pci_vmsvga_init(pci_bus);
- } else {
- fprintf(stderr, "%s: vmware_vga: no PCI bus\n", __FUNCTION__);
- }
-#ifdef CONFIG_SPICE
- } else if (qxl_enabled) {
- if (pci_bus) {
- dev = &pci_create_simple(pci_bus, -1, "qxl-vga")->qdev;
- } else {
- fprintf(stderr, "%s: qxl: no PCI bus\n", __FUNCTION__);
- }
-#endif
- } else if (std_vga_enabled) {
- if (pci_bus) {
- dev = pci_vga_init(pci_bus);
- } else {
- dev = isa_vga_init(isa_bus);
- }
+ if (pci_bus) {
+ PCIDevice *pcidev = pci_vga_init(pci_bus);
+ dev = pcidev ? &pcidev->qdev : NULL;
+ } else if (isa_bus) {
+ ISADevice *isadev = isa_vga_init(isa_bus);
+ dev = isadev ? &isadev->qdev : NULL;
}
-
return dev;
}
diff --git a/hw/pc.h b/hw/pc.h
index e4db0715b..9923d9602 100644
--- a/hw/pc.h
+++ b/hw/pc.h
@@ -176,19 +176,6 @@ enum vga_retrace_method {
extern enum vga_retrace_method vga_retrace_method;
-static inline DeviceState *isa_vga_init(ISABus *bus)
-{
- ISADevice *dev;
-
- dev = isa_try_create(bus, "isa-vga");
- if (!dev) {
- fprintf(stderr, "Warning: isa-vga not available\n");
- return NULL;
- }
- qdev_init_nofail(&dev->qdev);
- return &dev->qdev;
-}
-
int isa_vga_mm_init(target_phys_addr_t vram_base,
target_phys_addr_t ctrl_base, int it_shift,
MemoryRegion *address_space);
diff --git a/hw/pci.c b/hw/pci.c
index de4b4485e..2ca6ff6fe 100644
--- a/hw/pci.c
+++ b/hw/pci.c
@@ -1474,6 +1474,24 @@ PCIDevice *pci_nic_init_nofail(NICInfo *nd, const char *default_model,
return res;
}
+PCIDevice *pci_vga_init(PCIBus *bus)
+{
+ switch (vga_interface_type) {
+ case VGA_CIRRUS:
+ return pci_create_simple(bus, -1, "cirrus-vga");
+ case VGA_QXL:
+ return pci_create_simple(bus, -1, "qxl-vga");
+ case VGA_STD:
+ return pci_create_simple(bus, -1, "VGA");
+ case VGA_VMWARE:
+ return pci_create_simple(bus, -1, "vmware-svga");
+ case VGA_NONE:
+ default: /* Other non-PCI types. Checking for unsupported types is already
+ done in vl.c. */
+ return NULL;
+ }
+}
+
/* Whether a given bus number is in range of the secondary
* bus of the given bridge device. */
static bool pci_secondary_bus_in_range(PCIDevice *dev, int bus_num)
diff --git a/hw/pci.h b/hw/pci.h
index 4b6ab3d19..d50d26c8a 100644
--- a/hw/pci.h
+++ b/hw/pci.h
@@ -334,6 +334,9 @@ PCIDevice *pci_nic_init(NICInfo *nd, const char *default_model,
const char *default_devaddr);
PCIDevice *pci_nic_init_nofail(NICInfo *nd, const char *default_model,
const char *default_devaddr);
+
+PCIDevice *pci_vga_init(PCIBus *bus);
+
int pci_bus_num(PCIBus *s);
void pci_for_each_device(PCIBus *bus, int bus_num,
void (*fn)(PCIBus *bus, PCIDevice *d, void *opaque),
diff --git a/hw/petalogix_ml605_mmu.c b/hw/petalogix_ml605_mmu.c
index dced648f4..b9bfbed4c 100644
--- a/hw/petalogix_ml605_mmu.c
+++ b/hw/petalogix_ml605_mmu.c
@@ -36,6 +36,7 @@
#include "blockdev.h"
#include "pc.h"
#include "exec-memory.h"
+#include "ssi.h"
#include "microblaze_boot.h"
#include "microblaze_pic_cpu.h"
@@ -47,6 +48,8 @@
#define BINARY_DEVICE_TREE_FILE "petalogix-ml605.dtb"
+#define NUM_SPI_FLASHES 4
+
#define MEMORY_BASEADDR 0x50000000
#define FLASH_BASEADDR 0x86000000
#define INTC_BASEADDR 0x81800000
@@ -79,6 +82,7 @@ petalogix_ml605_init(ram_addr_t ram_size,
MemoryRegion *address_space_mem = get_system_memory();
DeviceState *dev, *dma, *eth0;
MicroBlazeCPU *cpu;
+ SysBusDevice *busdev;
CPUMBState *env;
DriveInfo *dinfo;
int i;
@@ -139,6 +143,29 @@ petalogix_ml605_init(ram_addr_t ram_size,
xilinx_axiethernetdma_init(dma, STREAM_SLAVE(eth0),
0x84600000, irq[1], irq[0], 100 * 1000000);
+ {
+ SSIBus *spi;
+
+ dev = qdev_create(NULL, "xlnx.xps-spi");
+ qdev_prop_set_uint8(dev, "num-ss-bits", NUM_SPI_FLASHES);
+ qdev_init_nofail(dev);
+ busdev = sysbus_from_qdev(dev);
+ sysbus_mmio_map(busdev, 0, 0x40a00000);
+ sysbus_connect_irq(busdev, 0, irq[4]);
+
+ spi = (SSIBus *)qdev_get_child_bus(dev, "spi");
+
+ for (i = 0; i < NUM_SPI_FLASHES; i++) {
+ qemu_irq cs_line;
+
+ dev = ssi_create_slave_no_init(spi, "m25p80");
+ qdev_prop_set_string(dev, "partname", "n25q128");
+ qdev_init_nofail(dev);
+ cs_line = qdev_get_gpio_in(dev, 0);
+ sysbus_connect_irq(busdev, i+1, cs_line);
+ }
+ }
+
microblaze_load_kernel(cpu, ddr_base, ram_size, BINARY_DEVICE_TREE_FILE,
machine_cpu_reset);
diff --git a/hw/pflash_cfi01.c b/hw/pflash_cfi01.c
index 855890d1f..3b437da9c 100644
--- a/hw/pflash_cfi01.c
+++ b/hw/pflash_cfi01.c
@@ -442,7 +442,6 @@ static void pflash_write(pflash_t *pfl, target_phys_addr_t offset,
pfl->bypass = 0;
pfl->wcycle = 0;
pfl->cmd = 0;
- return;
}
diff --git a/hw/pflash_cfi02.c b/hw/pflash_cfi02.c
index 8cb154958..39337ec30 100644
--- a/hw/pflash_cfi02.c
+++ b/hw/pflash_cfi02.c
@@ -474,7 +474,6 @@ static void pflash_write (pflash_t *pfl, target_phys_addr_t offset,
do_bypass:
pfl->wcycle = 2;
pfl->cmd = 0;
- return;
}
diff --git a/hw/ppc/e500.c b/hw/ppc/e500.c
index 6f0de6d95..d23f9b2f6 100644
--- a/hw/ppc/e500.c
+++ b/hw/ppc/e500.c
@@ -36,7 +36,7 @@
#define BINARY_DEVICE_TREE_FILE "mpc8544ds.dtb"
#define UIMAGE_LOAD_BASE 0
-#define DTC_LOAD_PAD 0x500000
+#define DTC_LOAD_PAD 0x1800000
#define DTC_PAD_MASK 0xFFFFF
#define INITRD_LOAD_PAD 0x2000000
#define INITRD_PAD_MASK 0xFFFFFF
@@ -139,12 +139,10 @@ static int ppce500_load_device_tree(CPUPPCState *env,
0x0, 0x10000,
};
QemuOpts *machine_opts;
- const char *dumpdtb = NULL;
const char *dtb_file = NULL;
machine_opts = qemu_opts_find(qemu_find_opts("machine"), 0);
if (machine_opts) {
- dumpdtb = qemu_opt_get(machine_opts, "dumpdtb");
dtb_file = qemu_opt_get(machine_opts, "dtb");
toplevel_compat = qemu_opt_get(machine_opts, "dt_compatible");
}
@@ -334,18 +332,7 @@ static int ppce500_load_device_tree(CPUPPCState *env,
}
done:
- if (dumpdtb) {
- /* Dump the dtb to a file and quit */
- FILE *f = fopen(dumpdtb, "wb");
- size_t len;
- len = fwrite(fdt, fdt_size, 1, f);
- fclose(f);
- if (len != fdt_size) {
- exit(1);
- }
- exit(0);
- }
-
+ qemu_devtree_dumpdtb(fdt, fdt_size);
ret = rom_add_blob_fixed(BINARY_DEVICE_TREE_FILE, fdt, fdt_size, addr);
if (ret < 0) {
goto out;
@@ -375,6 +362,10 @@ static void mmubooke_create_initial_mapping(CPUPPCState *env)
the device tree top */
dt_end = bi->dt_base + bi->dt_size;
ps = booke206_page_size_to_tlb(dt_end) + 1;
+ if (ps & 1) {
+ /* e500v2 can only do even TLB size bits */
+ ps++;
+ }
size = (ps << MAS1_TSIZE_SHIFT);
tlb->mas1 = MAS1_VALID | size;
tlb->mas2 = 0;
@@ -553,7 +544,8 @@ void ppce500_init(PPCE500Params *params)
/* Load initrd. */
if (params->initrd_filename) {
- initrd_base = (kernel_size + INITRD_LOAD_PAD) & ~INITRD_PAD_MASK;
+ initrd_base = (loadaddr + kernel_size + INITRD_LOAD_PAD) &
+ ~INITRD_PAD_MASK;
initrd_size = load_image_targphys(params->initrd_filename, initrd_base,
ram_size - initrd_base);
diff --git a/hw/ppc405_uc.c b/hw/ppc405_uc.c
index 89e5013b5..b52ab2f17 100644
--- a/hw/ppc405_uc.c
+++ b/hw/ppc405_uc.c
@@ -191,7 +191,8 @@ enum {
typedef struct ppc4xx_pob_t ppc4xx_pob_t;
struct ppc4xx_pob_t {
uint32_t bear;
- uint32_t besr[2];
+ uint32_t besr0;
+ uint32_t besr1;
};
static uint32_t dcr_read_pob (void *opaque, int dcrn)
@@ -205,8 +206,10 @@ static uint32_t dcr_read_pob (void *opaque, int dcrn)
ret = pob->bear;
break;
case POB0_BESR0:
+ ret = pob->besr0;
+ break;
case POB0_BESR1:
- ret = pob->besr[dcrn - POB0_BESR0];
+ ret = pob->besr1;
break;
default:
/* Avoid gcc warning */
@@ -227,9 +230,12 @@ static void dcr_write_pob (void *opaque, int dcrn, uint32_t val)
/* Read only */
break;
case POB0_BESR0:
+ /* Write-clear */
+ pob->besr0 &= ~val;
+ break;
case POB0_BESR1:
/* Write-clear */
- pob->besr[dcrn - POB0_BESR0] &= ~val;
+ pob->besr1 &= ~val;
break;
}
}
@@ -241,8 +247,8 @@ static void ppc4xx_pob_reset (void *opaque)
pob = opaque;
/* No error */
pob->bear = 0x00000000;
- pob->besr[0] = 0x0000000;
- pob->besr[1] = 0x0000000;
+ pob->besr0 = 0x0000000;
+ pob->besr1 = 0x0000000;
}
static void ppc4xx_pob_init(CPUPPCState *env)
diff --git a/hw/ppc_newworld.c b/hw/ppc_newworld.c
index e95cfe831..b8d3c9c98 100644
--- a/hw/ppc_newworld.c
+++ b/hw/ppc_newworld.c
@@ -67,7 +67,6 @@
#include "hw/usb.h"
#include "blockdev.h"
#include "exec-memory.h"
-#include "vga-pci.h"
#define MAX_IDE_BUS 2
#define CFG_ADDR 0xf0000510
diff --git a/hw/ppc_oldworld.c b/hw/ppc_oldworld.c
index 1dcd8a6c3..2c4a47813 100644
--- a/hw/ppc_oldworld.c
+++ b/hw/ppc_oldworld.c
@@ -43,7 +43,6 @@
#include "kvm_ppc.h"
#include "blockdev.h"
#include "exec-memory.h"
-#include "vga-pci.h"
#define MAX_IDE_BUS 2
#define CFG_ADDR 0xf0000510
diff --git a/hw/ppc_prep.c b/hw/ppc_prep.c
index 592b7b255..15444303e 100644
--- a/hw/ppc_prep.c
+++ b/hw/ppc_prep.c
@@ -39,7 +39,6 @@
#include "blockdev.h"
#include "arch_init.h"
#include "exec-memory.h"
-#include "vga-pci.h"
//#define HARD_DEBUG_PPC_IO
//#define DEBUG_PPC_IO
diff --git a/hw/pxa2xx_keypad.c b/hw/pxa2xx_keypad.c
index 59db02584..1a997c9c8 100644
--- a/hw/pxa2xx_keypad.c
+++ b/hw/pxa2xx_keypad.c
@@ -172,7 +172,6 @@ static void pxa27x_keyboard_event (PXA2xxKeyPadState *kp, int keycode)
kp->kpc |= KPC_MI;
qemu_irq_raise(kp->irq);
}
- return;
}
static uint64_t pxa2xx_keypad_read(void *opaque, target_phys_addr_t offset,
diff --git a/hw/qdev.c b/hw/qdev.c
index 3b5ce3312..9b9aba376 100644
--- a/hw/qdev.c
+++ b/hw/qdev.c
@@ -34,7 +34,6 @@ int qdev_hotplug = 0;
static bool qdev_hot_added = false;
static bool qdev_hot_removed = false;
-/* Register a new device type. */
const VMStateDescription *qdev_get_vmsd(DeviceState *dev)
{
DeviceClass *dc = DEVICE_GET_CLASS(dev);
@@ -52,11 +51,6 @@ const char *qdev_fw_name(DeviceState *dev)
return object_get_typename(OBJECT(dev));
}
-bool qdev_exists(const char *name)
-{
- return !!object_class_by_name(name);
-}
-
static void qdev_property_add_legacy(DeviceState *dev, Property *prop,
Error **errp);
@@ -291,9 +285,9 @@ BusState *qdev_get_parent_bus(DeviceState *dev)
void qdev_init_gpio_in(DeviceState *dev, qemu_irq_handler handler, int n)
{
- assert(dev->num_gpio_in == 0);
- dev->num_gpio_in = n;
- dev->gpio_in = qemu_allocate_irqs(handler, dev, n);
+ dev->gpio_in = qemu_extend_irqs(dev->gpio_in, dev->num_gpio_in, handler,
+ dev, n);
+ dev->num_gpio_in += n;
}
void qdev_init_gpio_out(DeviceState *dev, qemu_irq *pins, int n)
diff --git a/hw/qdev.h b/hw/qdev.h
index d69919441..c6ac63620 100644
--- a/hw/qdev.h
+++ b/hw/qdev.h
@@ -153,7 +153,6 @@ typedef struct GlobalProperty {
DeviceState *qdev_create(BusState *bus, const char *name);
DeviceState *qdev_try_create(BusState *bus, const char *name);
-bool qdev_exists(const char *name);
int qdev_device_help(QemuOpts *opts);
DeviceState *qdev_device_add(QemuOpts *opts);
int qdev_init(DeviceState *dev) QEMU_WARN_UNUSED_RESULT;
diff --git a/hw/sb16.c b/hw/sb16.c
index c81455d7f..523ab0d5f 100644
--- a/hw/sb16.c
+++ b/hw/sb16.c
@@ -822,7 +822,6 @@ static void complete (SB16State *s)
ldebug ("\n");
s->cmd = -1;
- return;
}
static void legacy_reset (SB16State *s)
diff --git a/hw/scsi-disk.c b/hw/scsi-disk.c
index 99bb02ebf..1b0afa635 100644
--- a/hw/scsi-disk.c
+++ b/hw/scsi-disk.c
@@ -1437,7 +1437,6 @@ invalid_param_len:
invalid_field:
scsi_check_condition(r, SENSE_CODE(INVALID_FIELD));
- return;
}
static inline bool check_lba_range(SCSIDiskState *s,
@@ -1535,7 +1534,6 @@ static void scsi_disk_emulate_unmap(SCSIDiskReq *r, uint8_t *inbuf)
invalid_param_len:
scsi_check_condition(r, SENSE_CODE(INVALID_PARAM_LEN));
- return;
}
static void scsi_disk_emulate_write_data(SCSIRequest *req)
diff --git a/hw/spapr.c b/hw/spapr.c
index c34b767c6..09b8e9922 100644
--- a/hw/spapr.c
+++ b/hw/spapr.c
@@ -46,7 +46,6 @@
#include "kvm.h"
#include "kvm_ppc.h"
#include "pci.h"
-#include "vga-pci.h"
#include "exec-memory.h"
#include "hw/usb.h"
@@ -85,9 +84,11 @@
#define PHANDLE_XICP 0x00001111
+#define HTAB_SIZE(spapr) (1ULL << ((spapr)->htab_shift))
+
sPAPREnvironment *spapr;
-int spapr_allocate_irq(int hint, enum xics_irq_type type)
+int spapr_allocate_irq(int hint, bool lsi)
{
int irq;
@@ -103,13 +104,13 @@ int spapr_allocate_irq(int hint, enum xics_irq_type type)
return 0;
}
- xics_set_irq_type(spapr->icp, irq, type);
+ xics_set_irq_type(spapr->icp, irq, lsi);
return irq;
}
/* Allocate block of consequtive IRQs, returns a number of the first */
-int spapr_allocate_irq_block(int num, enum xics_irq_type type)
+int spapr_allocate_irq_block(int num, bool lsi)
{
int first = -1;
int i;
@@ -117,7 +118,7 @@ int spapr_allocate_irq_block(int num, enum xics_irq_type type)
for (i = 0; i < num; ++i) {
int irq;
- irq = spapr_allocate_irq(0, type);
+ irq = spapr_allocate_irq(0, lsi);
if (!irq) {
return -1;
}
@@ -134,12 +135,13 @@ int spapr_allocate_irq_block(int num, enum xics_irq_type type)
return first;
}
-static int spapr_set_associativity(void *fdt, sPAPREnvironment *spapr)
+static int spapr_fixup_cpu_dt(void *fdt, sPAPREnvironment *spapr)
{
int ret = 0, offset;
CPUPPCState *env;
char cpu_model[32];
int smt = kvmppc_smt_threads();
+ uint32_t pft_size_prop[] = {0, cpu_to_be32(spapr->htab_shift)};
assert(spapr->cpu_model);
@@ -163,8 +165,16 @@ static int spapr_set_associativity(void *fdt, sPAPREnvironment *spapr)
return offset;
}
- ret = fdt_setprop(fdt, offset, "ibm,associativity", associativity,
- sizeof(associativity));
+ if (nb_numa_nodes > 1) {
+ ret = fdt_setprop(fdt, offset, "ibm,associativity", associativity,
+ sizeof(associativity));
+ if (ret < 0) {
+ return ret;
+ }
+ }
+
+ ret = fdt_setprop(fdt, offset, "ibm,pft-size",
+ pft_size_prop, sizeof(pft_size_prop));
if (ret < 0) {
return ret;
}
@@ -206,45 +216,36 @@ static size_t create_page_sizes_prop(CPUPPCState *env, uint32_t *prop,
return (p - prop) * sizeof(uint32_t);
}
+#define _FDT(exp) \
+ do { \
+ int ret = (exp); \
+ if (ret < 0) { \
+ fprintf(stderr, "qemu: error creating device tree: %s: %s\n", \
+ #exp, fdt_strerror(ret)); \
+ exit(1); \
+ } \
+ } while (0)
+
+
static void *spapr_create_fdt_skel(const char *cpu_model,
- target_phys_addr_t rma_size,
target_phys_addr_t initrd_base,
target_phys_addr_t initrd_size,
target_phys_addr_t kernel_size,
const char *boot_device,
- const char *kernel_cmdline,
- long hash_shift)
+ const char *kernel_cmdline)
{
void *fdt;
CPUPPCState *env;
- uint64_t mem_reg_property[2];
uint32_t start_prop = cpu_to_be32(initrd_base);
uint32_t end_prop = cpu_to_be32(initrd_base + initrd_size);
- uint32_t pft_size_prop[] = {0, cpu_to_be32(hash_shift)};
char hypertas_prop[] = "hcall-pft\0hcall-term\0hcall-dabr\0hcall-interrupt"
"\0hcall-tce\0hcall-vio\0hcall-splpar\0hcall-bulk";
char qemu_hypertas_prop[] = "hcall-memop1";
+ uint32_t refpoints[] = {cpu_to_be32(0x4), cpu_to_be32(0x4)};
uint32_t interrupt_server_ranges_prop[] = {0, cpu_to_be32(smp_cpus)};
- int i;
char *modelname;
- int smt = kvmppc_smt_threads();
+ int i, smt = kvmppc_smt_threads();
unsigned char vec5[] = {0x0, 0x0, 0x0, 0x0, 0x0, 0x80};
- uint32_t refpoints[] = {cpu_to_be32(0x4), cpu_to_be32(0x4)};
- uint32_t associativity[] = {cpu_to_be32(0x4), cpu_to_be32(0x0),
- cpu_to_be32(0x0), cpu_to_be32(0x0),
- cpu_to_be32(0x0)};
- char mem_name[32];
- target_phys_addr_t node0_size, mem_start;
-
-#define _FDT(exp) \
- do { \
- int ret = (exp); \
- if (ret < 0) { \
- fprintf(stderr, "qemu: error creating device tree: %s: %s\n", \
- #exp, fdt_strerror(ret)); \
- exit(1); \
- } \
- } while (0)
fdt = g_malloc0(FDT_MAX_SIZE);
_FDT((fdt_create(fdt, FDT_MAX_SIZE)));
@@ -289,55 +290,6 @@ static void *spapr_create_fdt_skel(const char *cpu_model,
_FDT((fdt_end_node(fdt)));
- /* memory node(s) */
- node0_size = (nb_numa_nodes > 1) ? node_mem[0] : ram_size;
- if (rma_size > node0_size) {
- rma_size = node0_size;
- }
-
- /* RMA */
- mem_reg_property[0] = 0;
- mem_reg_property[1] = cpu_to_be64(rma_size);
- _FDT((fdt_begin_node(fdt, "memory@0")));
- _FDT((fdt_property_string(fdt, "device_type", "memory")));
- _FDT((fdt_property(fdt, "reg", mem_reg_property,
- sizeof(mem_reg_property))));
- _FDT((fdt_property(fdt, "ibm,associativity", associativity,
- sizeof(associativity))));
- _FDT((fdt_end_node(fdt)));
-
- /* RAM: Node 0 */
- if (node0_size > rma_size) {
- mem_reg_property[0] = cpu_to_be64(rma_size);
- mem_reg_property[1] = cpu_to_be64(node0_size - rma_size);
-
- sprintf(mem_name, "memory@" TARGET_FMT_lx, rma_size);
- _FDT((fdt_begin_node(fdt, mem_name)));
- _FDT((fdt_property_string(fdt, "device_type", "memory")));
- _FDT((fdt_property(fdt, "reg", mem_reg_property,
- sizeof(mem_reg_property))));
- _FDT((fdt_property(fdt, "ibm,associativity", associativity,
- sizeof(associativity))));
- _FDT((fdt_end_node(fdt)));
- }
-
- /* RAM: Node 1 and beyond */
- mem_start = node0_size;
- for (i = 1; i < nb_numa_nodes; i++) {
- mem_reg_property[0] = cpu_to_be64(mem_start);
- mem_reg_property[1] = cpu_to_be64(node_mem[i]);
- associativity[3] = associativity[4] = cpu_to_be32(i);
- sprintf(mem_name, "memory@" TARGET_FMT_lx, mem_start);
- _FDT((fdt_begin_node(fdt, mem_name)));
- _FDT((fdt_property_string(fdt, "device_type", "memory")));
- _FDT((fdt_property(fdt, "reg", mem_reg_property,
- sizeof(mem_reg_property))));
- _FDT((fdt_property(fdt, "ibm,associativity", associativity,
- sizeof(associativity))));
- _FDT((fdt_end_node(fdt)));
- mem_start += node_mem[i];
- }
-
/* cpus */
_FDT((fdt_begin_node(fdt, "cpus")));
@@ -389,8 +341,6 @@ static void *spapr_create_fdt_skel(const char *cpu_model,
_FDT((fdt_property_cell(fdt, "timebase-frequency", tbfreq)));
_FDT((fdt_property_cell(fdt, "clock-frequency", cpufreq)));
_FDT((fdt_property_cell(fdt, "ibm,slb-size", env->slb_nr)));
- _FDT((fdt_property(fdt, "ibm,pft-size",
- pft_size_prop, sizeof(pft_size_prop))));
_FDT((fdt_property_string(fdt, "status", "okay")));
_FDT((fdt_property(fdt, "64-bit", NULL, 0)));
@@ -489,6 +439,68 @@ static void *spapr_create_fdt_skel(const char *cpu_model,
return fdt;
}
+static int spapr_populate_memory(sPAPREnvironment *spapr, void *fdt)
+{
+ uint32_t associativity[] = {cpu_to_be32(0x4), cpu_to_be32(0x0),
+ cpu_to_be32(0x0), cpu_to_be32(0x0),
+ cpu_to_be32(0x0)};
+ char mem_name[32];
+ target_phys_addr_t node0_size, mem_start;
+ uint64_t mem_reg_property[2];
+ int i, off;
+
+ /* memory node(s) */
+ node0_size = (nb_numa_nodes > 1) ? node_mem[0] : ram_size;
+ if (spapr->rma_size > node0_size) {
+ spapr->rma_size = node0_size;
+ }
+
+ /* RMA */
+ mem_reg_property[0] = 0;
+ mem_reg_property[1] = cpu_to_be64(spapr->rma_size);
+ off = fdt_add_subnode(fdt, 0, "memory@0");
+ _FDT(off);
+ _FDT((fdt_setprop_string(fdt, off, "device_type", "memory")));
+ _FDT((fdt_setprop(fdt, off, "reg", mem_reg_property,
+ sizeof(mem_reg_property))));
+ _FDT((fdt_setprop(fdt, off, "ibm,associativity", associativity,
+ sizeof(associativity))));
+
+ /* RAM: Node 0 */
+ if (node0_size > spapr->rma_size) {
+ mem_reg_property[0] = cpu_to_be64(spapr->rma_size);
+ mem_reg_property[1] = cpu_to_be64(node0_size - spapr->rma_size);
+
+ sprintf(mem_name, "memory@" TARGET_FMT_lx, spapr->rma_size);
+ off = fdt_add_subnode(fdt, 0, mem_name);
+ _FDT(off);
+ _FDT((fdt_setprop_string(fdt, off, "device_type", "memory")));
+ _FDT((fdt_setprop(fdt, off, "reg", mem_reg_property,
+ sizeof(mem_reg_property))));
+ _FDT((fdt_setprop(fdt, off, "ibm,associativity", associativity,
+ sizeof(associativity))));
+ }
+
+ /* RAM: Node 1 and beyond */
+ mem_start = node0_size;
+ for (i = 1; i < nb_numa_nodes; i++) {
+ mem_reg_property[0] = cpu_to_be64(mem_start);
+ mem_reg_property[1] = cpu_to_be64(node_mem[i]);
+ associativity[3] = associativity[4] = cpu_to_be32(i);
+ sprintf(mem_name, "memory@" TARGET_FMT_lx, mem_start);
+ off = fdt_add_subnode(fdt, 0, mem_name);
+ _FDT(off);
+ _FDT((fdt_setprop_string(fdt, off, "device_type", "memory")));
+ _FDT((fdt_setprop(fdt, off, "reg", mem_reg_property,
+ sizeof(mem_reg_property))));
+ _FDT((fdt_setprop(fdt, off, "ibm,associativity", associativity,
+ sizeof(associativity))));
+ mem_start += node_mem[i];
+ }
+
+ return 0;
+}
+
static void spapr_finalize_fdt(sPAPREnvironment *spapr,
target_phys_addr_t fdt_addr,
target_phys_addr_t rtas_addr,
@@ -503,6 +515,12 @@ static void spapr_finalize_fdt(sPAPREnvironment *spapr,
/* open out the base tree into a temp buffer for the final tweaks */
_FDT((fdt_open_into(spapr->fdt_skel, fdt, FDT_MAX_SIZE)));
+ ret = spapr_populate_memory(spapr, fdt);
+ if (ret < 0) {
+ fprintf(stderr, "couldn't setup memory nodes in fdt\n");
+ exit(1);
+ }
+
ret = spapr_populate_vdevice(spapr->vio_bus, fdt);
if (ret < 0) {
fprintf(stderr, "couldn't setup vio devices in fdt\n");
@@ -525,11 +543,9 @@ static void spapr_finalize_fdt(sPAPREnvironment *spapr,
}
/* Advertise NUMA via ibm,associativity */
- if (nb_numa_nodes > 1) {
- ret = spapr_set_associativity(fdt, spapr);
- if (ret < 0) {
- fprintf(stderr, "Couldn't set up NUMA device tree properties\n");
- }
+ ret = spapr_fixup_cpu_dt(fdt, spapr);
+ if (ret < 0) {
+ fprintf(stderr, "Couldn't finalize CPU device tree properties\n");
}
if (!spapr->has_graphics) {
@@ -556,15 +572,49 @@ static uint64_t translate_kernel_address(void *opaque, uint64_t addr)
static void emulate_spapr_hypercall(CPUPPCState *env)
{
- env->gpr[3] = spapr_hypercall(env, env->gpr[3], &env->gpr[4]);
+ if (msr_pr) {
+ hcall_dprintf("Hypercall made with MSR[PR]=1\n");
+ env->gpr[3] = H_PRIVILEGE;
+ } else {
+ env->gpr[3] = spapr_hypercall(env, env->gpr[3], &env->gpr[4]);
+ }
}
-static void spapr_reset(void *opaque)
+static void spapr_reset_htab(sPAPREnvironment *spapr)
{
- sPAPREnvironment *spapr = (sPAPREnvironment *)opaque;
+ long shift;
+
+ /* allocate hash page table. For now we always make this 16mb,
+ * later we should probably make it scale to the size of guest
+ * RAM */
+
+ shift = kvmppc_reset_htab(spapr->htab_shift);
- /* flush out the hash table */
- memset(spapr->htab, 0, spapr->htab_size);
+ if (shift > 0) {
+ /* Kernel handles htab, we don't need to allocate one */
+ spapr->htab_shift = shift;
+ } else {
+ if (!spapr->htab) {
+ /* Allocate an htab if we don't yet have one */
+ spapr->htab = qemu_memalign(HTAB_SIZE(spapr), HTAB_SIZE(spapr));
+ }
+
+ /* And clear it */
+ memset(spapr->htab, 0, HTAB_SIZE(spapr));
+ }
+
+ /* Update the RMA size if necessary */
+ if (spapr->vrma_adjust) {
+ spapr->rma_size = kvmppc_rma_size(ram_size, spapr->htab_shift);
+ }
+}
+
+static void ppc_spapr_reset(void)
+{
+ /* Reset the hash table & recalc the RMA */
+ spapr_reset_htab(spapr);
+
+ qemu_devices_reset();
/* Load the fdt */
spapr_finalize_fdt(spapr, spapr->fdt_addr, spapr->rtas_addr,
@@ -581,19 +631,31 @@ static void spapr_reset(void *opaque)
static void spapr_cpu_reset(void *opaque)
{
PowerPCCPU *cpu = opaque;
+ CPUPPCState *env = &cpu->env;
cpu_reset(CPU(cpu));
+
+ /* All CPUs start halted. CPU0 is unhalted from the machine level
+ * reset code and the rest are explicitly started up by the guest
+ * using an RTAS call */
+ env->halted = 1;
+
+ env->spr[SPR_HIOR] = 0;
+
+ env->external_htab = spapr->htab;
+ env->htab_base = -1;
+ env->htab_mask = HTAB_SIZE(spapr) - 1;
+ env->spr[SPR_SDR1] = (unsigned long)spapr->htab |
+ (spapr->htab_shift - 18);
}
/* Returns whether we want to use VGA or not */
static int spapr_vga_init(PCIBus *pci_bus)
{
switch (vga_interface_type) {
- case VGA_STD:
- pci_vga_init(pci_bus);
- return 1;
case VGA_NONE:
- return 0;
+ case VGA_STD:
+ return pci_vga_init(pci_bus) != NULL;
default:
fprintf(stderr, "This vga model is not supported,"
"currently it only supports -vga std\n");
@@ -616,11 +678,10 @@ static void ppc_spapr_init(ram_addr_t ram_size,
int i;
MemoryRegion *sysmem = get_system_memory();
MemoryRegion *ram = g_new(MemoryRegion, 1);
- target_phys_addr_t rma_alloc_size, rma_size;
+ target_phys_addr_t rma_alloc_size;
uint32_t initrd_base = 0;
long kernel_size = 0, initrd_size = 0;
long load_limit, rtas_limit, fw_size;
- long pteg_shift = 17;
char *filename;
msi_supported = true;
@@ -637,20 +698,46 @@ static void ppc_spapr_init(ram_addr_t ram_size,
hw_error("qemu: Unable to create RMA\n");
exit(1);
}
+
if (rma_alloc_size && (rma_alloc_size < ram_size)) {
- rma_size = rma_alloc_size;
+ spapr->rma_size = rma_alloc_size;
} else {
- rma_size = ram_size;
+ spapr->rma_size = ram_size;
+
+ /* With KVM, we don't actually know whether KVM supports an
+ * unbounded RMA (PR KVM) or is limited by the hash table size
+ * (HV KVM using VRMA), so we always assume the latter
+ *
+ * In that case, we also limit the initial allocations for RTAS
+ * etc... to 256M since we have no way to know what the VRMA size
+ * is going to be as it depends on the size of the hash table
+ * isn't determined yet.
+ */
+ if (kvm_enabled()) {
+ spapr->vrma_adjust = 1;
+ spapr->rma_size = MIN(spapr->rma_size, 0x10000000);
+ }
}
/* We place the device tree and RTAS just below either the top of the RMA,
* or just below 2GB, whichever is lowere, so that it can be
* processed with 32-bit real mode code if necessary */
- rtas_limit = MIN(rma_size, 0x80000000);
+ rtas_limit = MIN(spapr->rma_size, 0x80000000);
spapr->rtas_addr = rtas_limit - RTAS_MAX_SIZE;
spapr->fdt_addr = spapr->rtas_addr - FDT_MAX_SIZE;
load_limit = spapr->fdt_addr - FW_OVERHEAD;
+ /* We aim for a hash table of size 1/128 the size of RAM. The
+ * normal rule of thumb is 1/64 the size of RAM, but that's much
+ * more than needed for the Linux guests we support. */
+ spapr->htab_shift = 18; /* Minimum architected size */
+ while (spapr->htab_shift <= 46) {
+ if ((1ULL << (spapr->htab_shift + 7)) >= ram_size) {
+ break;
+ }
+ spapr->htab_shift++;
+ }
+
/* init CPUs */
if (cpu_model == NULL) {
cpu_model = kvm_enabled() ? "host" : "POWER7";
@@ -665,11 +752,16 @@ static void ppc_spapr_init(ram_addr_t ram_size,
/* Set time-base frequency to 512 MHz */
cpu_ppc_tb_init(env, TIMEBASE_FREQ);
- qemu_register_reset(spapr_cpu_reset, cpu);
- env->hreset_vector = 0x60;
+ /* PAPR always has exception vectors in RAM not ROM */
env->hreset_excp_prefix = 0;
- env->gpr[3] = env->cpu_index;
+
+ /* Tell KVM that we're in PAPR mode */
+ if (kvm_enabled()) {
+ kvmppc_set_papr(env);
+ }
+
+ qemu_register_reset(spapr_cpu_reset, cpu);
}
/* allocate RAM */
@@ -683,27 +775,6 @@ static void ppc_spapr_init(ram_addr_t ram_size,
memory_region_add_subregion(sysmem, nonrma_base, ram);
}
- /* allocate hash page table. For now we always make this 16mb,
- * later we should probably make it scale to the size of guest
- * RAM */
- spapr->htab_size = 1ULL << (pteg_shift + 7);
- spapr->htab = qemu_memalign(spapr->htab_size, spapr->htab_size);
-
- for (env = first_cpu; env != NULL; env = env->next_cpu) {
- env->external_htab = spapr->htab;
- env->htab_base = -1;
- env->htab_mask = spapr->htab_size - 1;
-
- /* Tell KVM that we're in PAPR mode */
- env->spr[SPR_SDR1] = (unsigned long)spapr->htab |
- ((pteg_shift + 7) - 18);
- env->spr[SPR_HIOR] = 0;
-
- if (kvm_enabled()) {
- kvmppc_set_papr(env);
- }
- }
-
filename = qemu_find_file(QEMU_FILE_TYPE_BIOS, "spapr-rtas.bin");
spapr->rtas_size = load_image_targphys(filename, spapr->rtas_addr,
rtas_limit - spapr->rtas_addr);
@@ -776,7 +847,7 @@ static void ppc_spapr_init(ram_addr_t ram_size,
}
}
- if (rma_size < (MIN_RMA_SLOF << 20)) {
+ if (spapr->rma_size < (MIN_RMA_SLOF << 20)) {
fprintf(stderr, "qemu: pSeries SLOF firmware requires >= "
"%ldM guest RMA (Real Mode Area memory)\n", MIN_RMA_SLOF);
exit(1);
@@ -827,26 +898,19 @@ static void ppc_spapr_init(ram_addr_t ram_size,
spapr->entry_point = 0x100;
- /* SLOF will startup the secondary CPUs using RTAS */
- for (env = first_cpu; env != NULL; env = env->next_cpu) {
- env->halted = 1;
- }
-
/* Prepare the device tree */
- spapr->fdt_skel = spapr_create_fdt_skel(cpu_model, rma_size,
+ spapr->fdt_skel = spapr_create_fdt_skel(cpu_model,
initrd_base, initrd_size,
kernel_size,
- boot_device, kernel_cmdline,
- pteg_shift + 7);
+ boot_device, kernel_cmdline);
assert(spapr->fdt_skel != NULL);
-
- qemu_register_reset(spapr_reset, spapr);
}
static QEMUMachine spapr_machine = {
.name = "pseries",
.desc = "pSeries Logical Partition (PAPR compliant)",
.init = ppc_spapr_init,
+ .reset = ppc_spapr_reset,
.max_cpus = MAX_CPUS,
.no_parallel = 1,
.use_scsi = 1,
diff --git a/hw/spapr.h b/hw/spapr.h
index ac34a171e..e984e3fc3 100644
--- a/hw/spapr.h
+++ b/hw/spapr.h
@@ -15,7 +15,9 @@ typedef struct sPAPREnvironment {
target_phys_addr_t ram_limit;
void *htab;
- long htab_size;
+ long htab_shift;
+ target_phys_addr_t rma_size;
+ int vrma_adjust;
target_phys_addr_t fdt_addr, rtas_addr;
long rtas_size;
void *fdt_skel;
@@ -289,17 +291,17 @@ void spapr_register_hypercall(target_ulong opcode, spapr_hcall_fn fn);
target_ulong spapr_hypercall(CPUPPCState *env, target_ulong opcode,
target_ulong *args);
-int spapr_allocate_irq(int hint, enum xics_irq_type type);
-int spapr_allocate_irq_block(int num, enum xics_irq_type type);
+int spapr_allocate_irq(int hint, bool lsi);
+int spapr_allocate_irq_block(int num, bool lsi);
static inline int spapr_allocate_msi(int hint)
{
- return spapr_allocate_irq(hint, XICS_MSI);
+ return spapr_allocate_irq(hint, false);
}
static inline int spapr_allocate_lsi(int hint)
{
- return spapr_allocate_irq(hint, XICS_LSI);
+ return spapr_allocate_irq(hint, true);
}
static inline uint32_t rtas_ld(target_ulong phys, int n)
@@ -336,6 +338,8 @@ typedef struct sPAPRTCE {
void spapr_iommu_init(void);
DMAContext *spapr_tce_new_dma_context(uint32_t liobn, size_t window_size);
void spapr_tce_free(DMAContext *dma);
+void spapr_tce_reset(DMAContext *dma);
+void spapr_tce_set_bypass(DMAContext *dma, bool bypass);
int spapr_dma_dt(void *fdt, int node_off, const char *propname,
uint32_t liobn, uint64_t window, uint32_t size);
int spapr_tcet_dma_dt(void *fdt, int node_off, const char *propname,
diff --git a/hw/spapr_hcall.c b/hw/spapr_hcall.c
index abd847f96..194d9c24b 100644
--- a/hw/spapr_hcall.c
+++ b/hw/spapr_hcall.c
@@ -39,22 +39,6 @@
#define HPTE_V_1TB_SEG 0x4000000000000000ULL
#define HPTE_V_VRMA_MASK 0x4001ffffff000000ULL
-#define HPTE_V_HVLOCK 0x40ULL
-
-static inline int lock_hpte(void *hpte, target_ulong bits)
-{
- uint64_t pteh;
-
- pteh = ldq_p(hpte);
-
- /* We're protected by qemu's global lock here */
- if (pteh & bits) {
- return 0;
- }
- stq_p(hpte, pteh | HPTE_V_HVLOCK);
- return 1;
-}
-
static target_ulong compute_tlbie_rb(target_ulong v, target_ulong r,
target_ulong pte_index)
{
@@ -151,8 +135,7 @@ static target_ulong h_enter(CPUPPCState *env, sPAPREnvironment *spapr,
if (i == 8) {
return H_PTEG_FULL;
}
- if (((ldq_p(hpte) & HPTE_V_VALID) == 0) &&
- lock_hpte(hpte, HPTE_V_HVLOCK | HPTE_V_VALID)) {
+ if ((ldq_p(hpte) & HPTE_V_VALID) == 0) {
break;
}
hpte += HASH_PTE_SIZE_64;
@@ -160,7 +143,7 @@ static target_ulong h_enter(CPUPPCState *env, sPAPREnvironment *spapr,
} else {
i = 0;
hpte = env->external_htab + (pte_index * HASH_PTE_SIZE_64);
- if (!lock_hpte(hpte, HPTE_V_HVLOCK | HPTE_V_VALID)) {
+ if (ldq_p(hpte) & HPTE_V_VALID) {
return H_PTEG_FULL;
}
}
@@ -168,7 +151,6 @@ static target_ulong h_enter(CPUPPCState *env, sPAPREnvironment *spapr,
/* eieio(); FIXME: need some sort of barrier for smp? */
stq_p(hpte, pteh);
- assert(!(ldq_p(hpte) & HPTE_V_HVLOCK));
args[0] = pte_index + i;
return H_SUCCESS;
}
@@ -193,11 +175,6 @@ static target_ulong remove_hpte(CPUPPCState *env, target_ulong ptex,
}
hpte = env->external_htab + (ptex * HASH_PTE_SIZE_64);
- while (!lock_hpte(hpte, HPTE_V_HVLOCK)) {
- /* We have no real concurrency in qemu soft-emulation, so we
- * will never actually have a contested lock */
- assert(0);
- }
v = ldq_p(hpte);
r = ldq_p(hpte + (HASH_PTE_SIZE_64/2));
@@ -205,16 +182,13 @@ static target_ulong remove_hpte(CPUPPCState *env, target_ulong ptex,
if ((v & HPTE_V_VALID) == 0 ||
((flags & H_AVPN) && (v & ~0x7fULL) != avpn) ||
((flags & H_ANDCOND) && (v & avpn) != 0)) {
- stq_p(hpte, v & ~HPTE_V_HVLOCK);
- assert(!(ldq_p(hpte) & HPTE_V_HVLOCK));
return REMOVE_NOT_FOUND;
}
- *vp = v & ~HPTE_V_HVLOCK;
+ *vp = v;
*rp = r;
stq_p(hpte, 0);
rb = compute_tlbie_rb(v, r, ptex);
ppc_tlb_invalidate_one(env, rb);
- assert(!(ldq_p(hpte) & HPTE_V_HVLOCK));
return REMOVE_SUCCESS;
}
@@ -324,19 +298,12 @@ static target_ulong h_protect(CPUPPCState *env, sPAPREnvironment *spapr,
}
hpte = env->external_htab + (pte_index * HASH_PTE_SIZE_64);
- while (!lock_hpte(hpte, HPTE_V_HVLOCK)) {
- /* We have no real concurrency in qemu soft-emulation, so we
- * will never actually have a contested lock */
- assert(0);
- }
v = ldq_p(hpte);
r = ldq_p(hpte + (HASH_PTE_SIZE_64/2));
if ((v & HPTE_V_VALID) == 0 ||
((flags & H_AVPN) && (v & ~0x7fULL) != avpn)) {
- stq_p(hpte, v & ~HPTE_V_HVLOCK);
- assert(!(ldq_p(hpte) & HPTE_V_HVLOCK));
return H_NOT_FOUND;
}
@@ -350,8 +317,7 @@ static target_ulong h_protect(CPUPPCState *env, sPAPREnvironment *spapr,
ppc_tlb_invalidate_one(env, rb);
stq_p(hpte + (HASH_PTE_SIZE_64/2), r);
/* Don't need a memory barrier, due to qemu's global lock */
- stq_p(hpte, v & ~HPTE_V_HVLOCK);
- assert(!(ldq_p(hpte) & HPTE_V_HVLOCK));
+ stq_p(hpte, v);
return H_SUCCESS;
}
@@ -544,6 +510,8 @@ static target_ulong h_cede(CPUPPCState *env, sPAPREnvironment *spapr,
hreg_compute_hflags(env);
if (!cpu_has_work(env)) {
env->halted = 1;
+ env->exception_index = EXCP_HLT;
+ env->exit_request = 1;
}
return H_SUCCESS;
}
@@ -713,11 +681,6 @@ void spapr_register_hypercall(target_ulong opcode, spapr_hcall_fn fn)
target_ulong spapr_hypercall(CPUPPCState *env, target_ulong opcode,
target_ulong *args)
{
- if (msr_pr) {
- hcall_dprintf("Hypercall made with MSR[PR]=1\n");
- return H_PRIVILEGE;
- }
-
if ((opcode <= MAX_HCALL_OPCODE)
&& ((opcode & 0x3) == 0)) {
spapr_hcall_fn fn = papr_hypercall_table[opcode / 4];
diff --git a/hw/spapr_iommu.c b/hw/spapr_iommu.c
index 53b731773..38034c07b 100644
--- a/hw/spapr_iommu.c
+++ b/hw/spapr_iommu.c
@@ -42,6 +42,7 @@ struct sPAPRTCETable {
uint32_t liobn;
uint32_t window_size;
sPAPRTCE *table;
+ bool bypass;
int fd;
QLIST_ENTRY(sPAPRTCETable) list;
};
@@ -78,6 +79,12 @@ static int spapr_tce_translate(DMAContext *dma,
DMA_ADDR_FMT "\n", tcet->liobn, addr);
#endif
+ if (tcet->bypass) {
+ *paddr = addr;
+ *len = (target_phys_addr_t)-1;
+ return 0;
+ }
+
/* Check if we are in bound */
if (addr >= tcet->window_size) {
#ifdef DEBUG_TCE
@@ -162,6 +169,23 @@ void spapr_tce_free(DMAContext *dma)
}
}
+void spapr_tce_set_bypass(DMAContext *dma, bool bypass)
+{
+ sPAPRTCETable *tcet = DO_UPCAST(sPAPRTCETable, dma, dma);
+
+ tcet->bypass = bypass;
+}
+
+void spapr_tce_reset(DMAContext *dma)
+{
+ sPAPRTCETable *tcet = DO_UPCAST(sPAPRTCETable, dma, dma);
+ size_t table_size = (tcet->window_size >> SPAPR_TCE_PAGE_SHIFT)
+ * sizeof(sPAPRTCE);
+
+ tcet->bypass = false;
+ memset(tcet->table, 0, table_size);
+}
+
static target_ulong put_tce_emu(sPAPRTCETable *tcet, target_ulong ioba,
target_ulong tce)
{
diff --git a/hw/spapr_pci.c b/hw/spapr_pci.c
index 661c05bc3..b628f89a0 100644
--- a/hw/spapr_pci.c
+++ b/hw/spapr_pci.c
@@ -351,7 +351,7 @@ static void rtas_ibm_change_msi(sPAPREnvironment *spapr,
/* There is no cached config, allocate MSIs */
if (!phb->msi_table[ndev].nvec) {
- irq = spapr_allocate_irq_block(req_num, XICS_MSI);
+ irq = spapr_allocate_irq_block(req_num, true);
if (irq < 0) {
fprintf(stderr, "Cannot allocate MSIs for device#%d", ndev);
rtas_st(rets, 0, -1); /* Hardware error */
@@ -595,6 +595,15 @@ static int spapr_phb_init(SysBusDevice *s)
return 0;
}
+static void spapr_phb_reset(DeviceState *qdev)
+{
+ SysBusDevice *s = sysbus_from_qdev(qdev);
+ sPAPRPHBState *sphb = SPAPR_PCI_HOST_BRIDGE(s);
+
+ /* Reset the IOMMU state */
+ spapr_tce_reset(sphb->dma);
+}
+
static Property spapr_phb_properties[] = {
DEFINE_PROP_HEX64("buid", sPAPRPHBState, buid, 0),
DEFINE_PROP_STRING("busname", sPAPRPHBState, busname),
@@ -613,6 +622,7 @@ static void spapr_phb_class_init(ObjectClass *klass, void *data)
sdc->init = spapr_phb_init;
dc->props = spapr_phb_properties;
+ dc->reset = spapr_phb_reset;
}
static const TypeInfo spapr_phb_info = {
diff --git a/hw/spapr_rtas.c b/hw/spapr_rtas.c
index ae1859515..b808f8001 100644
--- a/hw/spapr_rtas.c
+++ b/hw/spapr_rtas.c
@@ -184,6 +184,11 @@ static void rtas_start_cpu(sPAPREnvironment *spapr,
return;
}
+ /* This will make sure qemu state is up to date with kvm, and
+ * mark it dirty so our changes get flushed back before the
+ * new cpu enters */
+ kvm_cpu_synchronize_state(env);
+
env->msr = (1ULL << MSR_SF) | (1ULL << MSR_ME);
env->nip = start;
env->gpr[3] = r3;
diff --git a/hw/spapr_vio.c b/hw/spapr_vio.c
index 7ca445216..848806d3f 100644
--- a/hw/spapr_vio.c
+++ b/hw/spapr_vio.c
@@ -316,17 +316,10 @@ int spapr_vio_send_crq(VIOsPAPRDevice *dev, uint8_t *crq)
static void spapr_vio_quiesce_one(VIOsPAPRDevice *dev)
{
- VIOsPAPRDeviceClass *pc = VIO_SPAPR_DEVICE_GET_CLASS(dev);
- uint32_t liobn = SPAPR_VIO_BASE_LIOBN | dev->reg;
-
if (dev->dma) {
- spapr_tce_free(dev->dma);
+ spapr_tce_reset(dev->dma);
}
- dev->dma = spapr_tce_new_dma_context(liobn, pc->rtce_window_size);
-
- dev->crq.qladdr = 0;
- dev->crq.qsize = 0;
- dev->crq.qnext = 0;
+ free_crq(dev);
}
static void rtas_set_tce_bypass(sPAPREnvironment *spapr, uint32_t token,
@@ -348,16 +341,14 @@ static void rtas_set_tce_bypass(sPAPREnvironment *spapr, uint32_t token,
rtas_st(rets, 0, -3);
return;
}
- if (enable) {
- spapr_tce_free(dev->dma);
- dev->dma = NULL;
- } else {
- VIOsPAPRDeviceClass *pc = VIO_SPAPR_DEVICE_GET_CLASS(dev);
- uint32_t liobn = SPAPR_VIO_BASE_LIOBN | dev->reg;
- dev->dma = spapr_tce_new_dma_context(liobn, pc->rtce_window_size);
+ if (!dev->dma) {
+ rtas_st(rets, 0, -3);
+ return;
}
+ spapr_tce_set_bypass(dev->dma, !!enable);
+
rtas_st(rets, 0, 0);
}
@@ -409,9 +400,10 @@ static void spapr_vio_busdev_reset(DeviceState *qdev)
VIOsPAPRDevice *dev = DO_UPCAST(VIOsPAPRDevice, qdev, qdev);
VIOsPAPRDeviceClass *pc = VIO_SPAPR_DEVICE_GET_CLASS(dev);
- if (dev->crq.qsize) {
- free_crq(dev);
- }
+ /* Shut down the request queue and TCEs if necessary */
+ spapr_vio_quiesce_one(dev);
+
+ dev->signal_state = 0;
if (pc->reset) {
pc->reset(dev);
@@ -422,7 +414,6 @@ static int spapr_vio_busdev_init(DeviceState *qdev)
{
VIOsPAPRDevice *dev = (VIOsPAPRDevice *)qdev;
VIOsPAPRDeviceClass *pc = VIO_SPAPR_DEVICE_GET_CLASS(dev);
- uint32_t liobn;
char *id;
if (dev->reg != -1) {
@@ -464,8 +455,10 @@ static int spapr_vio_busdev_init(DeviceState *qdev)
return -1;
}
- liobn = SPAPR_VIO_BASE_LIOBN | dev->reg;
- dev->dma = spapr_tce_new_dma_context(liobn, pc->rtce_window_size);
+ if (pc->rtce_window_size) {
+ uint32_t liobn = SPAPR_VIO_BASE_LIOBN | dev->reg;
+ dev->dma = spapr_tce_new_dma_context(liobn, pc->rtce_window_size);
+ }
return pc->init(dev);
}
diff --git a/hw/spapr_vio.h b/hw/spapr_vio.h
index ea6aa43e2..cc85d2610 100644
--- a/hw/spapr_vio.h
+++ b/hw/spapr_vio.h
@@ -60,7 +60,6 @@ typedef struct VIOsPAPRDeviceClass {
struct VIOsPAPRDevice {
DeviceState qdev;
uint32_t reg;
- uint32_t flags;
uint32_t irq;
target_ulong signal_state;
VIOsPAPR_CRQ crq;
@@ -132,7 +131,6 @@ void spapr_vscsi_create(VIOsPAPRBus *bus);
VIOsPAPRDevice *spapr_vty_get_default(VIOsPAPRBus *bus);
-int spapr_tce_set_bypass(uint32_t unit, uint32_t enable);
void spapr_vio_quiesce(void);
#endif /* _HW_SPAPR_VIO_H */
diff --git a/hw/spitz.c b/hw/spitz.c
index 20e783519..24346dcd5 100644
--- a/hw/spitz.c
+++ b/hw/spitz.c
@@ -1083,10 +1083,11 @@ static TypeInfo spitz_keyboard_info = {
static const VMStateDescription vmstate_corgi_ssp_regs = {
.name = "corgi-ssp",
- .version_id = 1,
- .minimum_version_id = 1,
- .minimum_version_id_old = 1,
+ .version_id = 2,
+ .minimum_version_id = 2,
+ .minimum_version_id_old = 2,
.fields = (VMStateField []) {
+ VMSTATE_SSI_SLAVE(ssidev, CorgiSSPState),
VMSTATE_UINT32_ARRAY(enable, CorgiSSPState, 3),
VMSTATE_END_OF_LIST(),
}
@@ -1115,6 +1116,7 @@ static const VMStateDescription vmstate_spitz_lcdtg_regs = {
.minimum_version_id = 1,
.minimum_version_id_old = 1,
.fields = (VMStateField []) {
+ VMSTATE_SSI_SLAVE(ssidev, SpitzLCDTG),
VMSTATE_UINT32(bl_intensity, SpitzLCDTG),
VMSTATE_UINT32(bl_power, SpitzLCDTG),
VMSTATE_END_OF_LIST(),
diff --git a/hw/ssd0323.c b/hw/ssd0323.c
index b101c5112..9c42d648e 100644
--- a/hw/ssd0323.c
+++ b/hw/ssd0323.c
@@ -279,6 +279,7 @@ static void ssd0323_cd(void *opaque, int n, int level)
static void ssd0323_save(QEMUFile *f, void *opaque)
{
+ SSISlave *ss = SSI_SLAVE(opaque);
ssd0323_state *s = (ssd0323_state *)opaque;
int i;
@@ -296,10 +297,13 @@ static void ssd0323_save(QEMUFile *f, void *opaque)
qemu_put_be32(f, s->remap);
qemu_put_be32(f, s->mode);
qemu_put_buffer(f, s->framebuffer, sizeof(s->framebuffer));
+
+ qemu_put_be32(f, ss->cs);
}
static int ssd0323_load(QEMUFile *f, void *opaque, int version_id)
{
+ SSISlave *ss = SSI_SLAVE(opaque);
ssd0323_state *s = (ssd0323_state *)opaque;
int i;
@@ -321,6 +325,8 @@ static int ssd0323_load(QEMUFile *f, void *opaque, int version_id)
s->mode = qemu_get_be32(f);
qemu_get_buffer(f, s->framebuffer, sizeof(s->framebuffer));
+ ss->cs = qemu_get_be32(f);
+
return 0;
}
@@ -348,6 +354,7 @@ static void ssd0323_class_init(ObjectClass *klass, void *data)
k->init = ssd0323_init;
k->transfer = ssd0323_transfer;
+ k->cs_polarity = SSI_CS_HIGH;
}
static TypeInfo ssd0323_info = {
diff --git a/hw/ssi-sd.c b/hw/ssi-sd.c
index b519bdb29..c5505ee24 100644
--- a/hw/ssi-sd.c
+++ b/hw/ssi-sd.c
@@ -197,6 +197,7 @@ static uint32_t ssi_sd_transfer(SSISlave *dev, uint32_t val)
static void ssi_sd_save(QEMUFile *f, void *opaque)
{
+ SSISlave *ss = SSI_SLAVE(opaque);
ssi_sd_state *s = (ssi_sd_state *)opaque;
int i;
@@ -209,10 +210,13 @@ static void ssi_sd_save(QEMUFile *f, void *opaque)
qemu_put_be32(f, s->arglen);
qemu_put_be32(f, s->response_pos);
qemu_put_be32(f, s->stopping);
+
+ qemu_put_be32(f, ss->cs);
}
static int ssi_sd_load(QEMUFile *f, void *opaque, int version_id)
{
+ SSISlave *ss = SSI_SLAVE(opaque);
ssi_sd_state *s = (ssi_sd_state *)opaque;
int i;
@@ -229,6 +233,8 @@ static int ssi_sd_load(QEMUFile *f, void *opaque, int version_id)
s->response_pos = qemu_get_be32(f);
s->stopping = qemu_get_be32(f);
+ ss->cs = qemu_get_be32(f);
+
return 0;
}
@@ -250,6 +256,7 @@ static void ssi_sd_class_init(ObjectClass *klass, void *data)
k->init = ssi_sd_init;
k->transfer = ssi_sd_transfer;
+ k->cs_polarity = SSI_CS_LOW;
}
static TypeInfo ssi_sd_info = {
diff --git a/hw/ssi.c b/hw/ssi.c
index e5f14a0ce..2b5635715 100644
--- a/hw/ssi.c
+++ b/hw/ssi.c
@@ -2,6 +2,8 @@
* QEMU Synchronous Serial Interface support
*
* Copyright (c) 2009 CodeSourcery.
+ * Copyright (c) 2012 Peter A.G. Crosthwaite (peter.crosthwaite@petalogix.com)
+ * Copyright (c) 2012 PetaLogix Pty Ltd.
* Written by Paul Brook
*
* This code is licensed under the GNU GPL v2.
@@ -25,17 +27,40 @@ static const TypeInfo ssi_bus_info = {
.instance_size = sizeof(SSIBus),
};
+static void ssi_cs_default(void *opaque, int n, int level)
+{
+ SSISlave *s = SSI_SLAVE(opaque);
+ bool cs = !!level;
+ assert(n == 0);
+ if (s->cs != cs) {
+ SSISlaveClass *ssc = SSI_SLAVE_GET_CLASS(s);
+ if (ssc->set_cs) {
+ ssc->set_cs(s, cs);
+ }
+ }
+ s->cs = cs;
+}
+
+static uint32_t ssi_transfer_raw_default(SSISlave *dev, uint32_t val)
+{
+ SSISlaveClass *ssc = SSI_SLAVE_GET_CLASS(dev);
+
+ if ((dev->cs && ssc->cs_polarity == SSI_CS_HIGH) ||
+ (!dev->cs && ssc->cs_polarity == SSI_CS_LOW) ||
+ ssc->cs_polarity == SSI_CS_NONE) {
+ return ssc->transfer(dev, val);
+ }
+ return 0;
+}
+
static int ssi_slave_init(DeviceState *dev)
{
SSISlave *s = SSI_SLAVE(dev);
SSISlaveClass *ssc = SSI_SLAVE_GET_CLASS(s);
- SSIBus *bus;
- BusChild *kid;
- bus = FROM_QBUS(SSIBus, qdev_get_parent_bus(dev));
- kid = QTAILQ_FIRST(&bus->qbus.children);
- if (kid->child != dev || QTAILQ_NEXT(kid, sibling) != NULL) {
- hw_error("Too many devices on SSI bus");
+ if (ssc->transfer_raw == ssi_transfer_raw_default &&
+ ssc->cs_polarity != SSI_CS_NONE) {
+ qdev_init_gpio_in(&s->qdev, ssi_cs_default, 1);
}
return ssc->init(s);
@@ -43,9 +68,14 @@ static int ssi_slave_init(DeviceState *dev)
static void ssi_slave_class_init(ObjectClass *klass, void *data)
{
+ SSISlaveClass *ssc = SSI_SLAVE_CLASS(klass);
DeviceClass *dc = DEVICE_CLASS(klass);
+
dc->init = ssi_slave_init;
dc->bus_type = TYPE_SSI_BUS;
+ if (!ssc->transfer_raw) {
+ ssc->transfer_raw = ssi_transfer_raw_default;
+ }
}
static TypeInfo ssi_slave_info = {
@@ -56,10 +86,15 @@ static TypeInfo ssi_slave_info = {
.abstract = true,
};
+DeviceState *ssi_create_slave_no_init(SSIBus *bus, const char *name)
+{
+ return qdev_create(&bus->qbus, name);
+}
+
DeviceState *ssi_create_slave(SSIBus *bus, const char *name)
{
- DeviceState *dev;
- dev = qdev_create(&bus->qbus, name);
+ DeviceState *dev = ssi_create_slave_no_init(bus, name);
+
qdev_init_nofail(dev);
return dev;
}
@@ -74,18 +109,29 @@ SSIBus *ssi_create_bus(DeviceState *parent, const char *name)
uint32_t ssi_transfer(SSIBus *bus, uint32_t val)
{
BusChild *kid;
- SSISlave *slave;
SSISlaveClass *ssc;
+ uint32_t r = 0;
- kid = QTAILQ_FIRST(&bus->qbus.children);
- if (!kid) {
- return 0;
+ QTAILQ_FOREACH(kid, &bus->qbus.children, sibling) {
+ SSISlave *slave = SSI_SLAVE(kid->child);
+ ssc = SSI_SLAVE_GET_CLASS(slave);
+ r |= ssc->transfer_raw(slave, val);
}
- slave = SSI_SLAVE(kid->child);
- ssc = SSI_SLAVE_GET_CLASS(slave);
- return ssc->transfer(slave, val);
+
+ return r;
}
+const VMStateDescription vmstate_ssi_slave = {
+ .name = "SSISlave",
+ .version_id = 1,
+ .minimum_version_id = 1,
+ .minimum_version_id_old = 1,
+ .fields = (VMStateField[]) {
+ VMSTATE_BOOL(cs, SSISlave),
+ VMSTATE_END_OF_LIST()
+ }
+};
+
static void ssi_slave_register_types(void)
{
type_register_static(&ssi_bus_info);
@@ -93,3 +139,36 @@ static void ssi_slave_register_types(void)
}
type_init(ssi_slave_register_types)
+
+typedef struct SSIAutoConnectArg {
+ qemu_irq **cs_linep;
+ SSIBus *bus;
+} SSIAutoConnectArg;
+
+static int ssi_auto_connect_slave(Object *child, void *opaque)
+{
+ SSIAutoConnectArg *arg = opaque;
+ SSISlave *dev = (SSISlave *)object_dynamic_cast(child, TYPE_SSI_SLAVE);
+ qemu_irq cs_line;
+
+ if (!dev) {
+ return 0;
+ }
+
+ cs_line = qdev_get_gpio_in(DEVICE(dev), 0);
+ qdev_set_parent_bus(DEVICE(dev), &arg->bus->qbus);
+ **arg->cs_linep = cs_line;
+ (*arg->cs_linep)++;
+ return 0;
+}
+
+void ssi_auto_connect_slaves(DeviceState *parent, qemu_irq *cs_line,
+ SSIBus *bus)
+{
+ SSIAutoConnectArg arg = {
+ .cs_linep = &cs_line,
+ .bus = bus
+ };
+
+ object_child_foreach(OBJECT(parent), ssi_auto_connect_slave, &arg);
+}
diff --git a/hw/ssi.h b/hw/ssi.h
index 06657d7c1..a05d60beb 100644
--- a/hw/ssi.h
+++ b/hw/ssi.h
@@ -23,28 +23,70 @@ typedef struct SSISlave SSISlave;
#define SSI_SLAVE_GET_CLASS(obj) \
OBJECT_GET_CLASS(SSISlaveClass, (obj), TYPE_SSI_SLAVE)
+typedef enum {
+ SSI_CS_NONE = 0,
+ SSI_CS_LOW,
+ SSI_CS_HIGH,
+} SSICSMode;
+
/* Slave devices. */
typedef struct SSISlaveClass {
DeviceClass parent_class;
int (*init)(SSISlave *dev);
+
+ /* if you have standard or no CS behaviour, just override transfer.
+ * This is called when the device cs is active (true by default).
+ */
uint32_t (*transfer)(SSISlave *dev, uint32_t val);
+ /* called when the CS line changes. Optional, devices only need to implement
+ * this if they have side effects associated with the cs line (beyond
+ * tristating the txrx lines).
+ */
+ int (*set_cs)(SSISlave *dev, bool select);
+ /* define whether or not CS exists and is active low/high */
+ SSICSMode cs_polarity;
+
+ /* if you have non-standard CS behaviour override this to take control
+ * of the CS behaviour at the device level. transfer, set_cs, and
+ * cs_polarity are unused if this is overwritten. Transfer_raw will
+ * always be called for the device for every txrx access to the parent bus
+ */
+ uint32_t (*transfer_raw)(SSISlave *dev, uint32_t val);
} SSISlaveClass;
struct SSISlave {
DeviceState qdev;
+
+ /* Chip select state */
+ bool cs;
};
#define SSI_SLAVE_FROM_QDEV(dev) DO_UPCAST(SSISlave, qdev, dev)
#define FROM_SSI_SLAVE(type, dev) DO_UPCAST(type, ssidev, dev)
+extern const VMStateDescription vmstate_ssi_slave;
+
+#define VMSTATE_SSI_SLAVE(_field, _state) { \
+ .name = (stringify(_field)), \
+ .size = sizeof(SSISlave), \
+ .vmsd = &vmstate_ssi_slave, \
+ .flags = VMS_STRUCT, \
+ .offset = vmstate_offset_value(_state, _field, SSISlave), \
+}
+
DeviceState *ssi_create_slave(SSIBus *bus, const char *name);
+DeviceState *ssi_create_slave_no_init(SSIBus *bus, const char *name);
/* Master interface. */
SSIBus *ssi_create_bus(DeviceState *parent, const char *name);
uint32_t ssi_transfer(SSIBus *bus, uint32_t val);
+/* Automatically connect all children nodes a spi controller as slaves */
+void ssi_auto_connect_slaves(DeviceState *parent, qemu_irq *cs_lines,
+ SSIBus *bus);
+
/* max111x.c */
void max111x_set_input(DeviceState *dev, int line, uint8_t value);
diff --git a/hw/stellaris.c b/hw/stellaris.c
index 562fbbf49..353ca4c04 100644
--- a/hw/stellaris.c
+++ b/hw/stellaris.c
@@ -1154,57 +1154,6 @@ static int stellaris_adc_init(SysBusDevice *dev)
return 0;
}
-/* Some boards have both an OLED controller and SD card connected to
- the same SSI port, with the SD card chip select connected to a
- GPIO pin. Technically the OLED chip select is connected to the SSI
- Fss pin. We do not bother emulating that as both devices should
- never be selected simultaneously, and our OLED controller ignores stray
- 0xff commands that occur when deselecting the SD card. */
-
-typedef struct {
- SSISlave ssidev;
- qemu_irq irq;
- int current_dev;
- SSIBus *bus[2];
-} stellaris_ssi_bus_state;
-
-static void stellaris_ssi_bus_select(void *opaque, int irq, int level)
-{
- stellaris_ssi_bus_state *s = (stellaris_ssi_bus_state *)opaque;
-
- s->current_dev = level;
-}
-
-static uint32_t stellaris_ssi_bus_transfer(SSISlave *dev, uint32_t val)
-{
- stellaris_ssi_bus_state *s = FROM_SSI_SLAVE(stellaris_ssi_bus_state, dev);
-
- return ssi_transfer(s->bus[s->current_dev], val);
-}
-
-static const VMStateDescription vmstate_stellaris_ssi_bus = {
- .name = "stellaris_ssi_bus",
- .version_id = 1,
- .minimum_version_id = 1,
- .minimum_version_id_old = 1,
- .fields = (VMStateField[]) {
- VMSTATE_INT32(current_dev, stellaris_ssi_bus_state),
- VMSTATE_END_OF_LIST()
- }
-};
-
-static int stellaris_ssi_bus_init(SSISlave *dev)
-{
- stellaris_ssi_bus_state *s = FROM_SSI_SLAVE(stellaris_ssi_bus_state, dev);
-
- s->bus[0] = ssi_create_bus(&dev->qdev, "ssi0");
- s->bus[1] = ssi_create_bus(&dev->qdev, "ssi1");
- qdev_init_gpio_in(&dev->qdev, stellaris_ssi_bus_select, 1);
-
- vmstate_register(&dev->qdev, -1, &vmstate_stellaris_ssi_bus, s);
- return 0;
-}
-
/* Board init. */
static stellaris_board_info stellaris_boards[] = {
{ "LM3S811EVB",
@@ -1305,19 +1254,25 @@ static void stellaris_init(const char *kernel_filename, const char *cpu_model,
if (board->dc2 & (1 << 4)) {
dev = sysbus_create_simple("pl022", 0x40008000, pic[7]);
if (board->peripherals & BP_OLED_SSI) {
- DeviceState *mux;
void *bus;
-
+ DeviceState *sddev;
+ DeviceState *ssddev;
+
+ /* Some boards have both an OLED controller and SD card connected to
+ * the same SSI port, with the SD card chip select connected to a
+ * GPIO pin. Technically the OLED chip select is connected to the
+ * SSI Fss pin. We do not bother emulating that as both devices
+ * should never be selected simultaneously, and our OLED controller
+ * ignores stray 0xff commands that occur when deselecting the SD
+ * card.
+ */
bus = qdev_get_child_bus(dev, "ssi");
- mux = ssi_create_slave(bus, "evb6965-ssi");
- gpio_out[GPIO_D][0] = qdev_get_gpio_in(mux, 0);
-
- bus = qdev_get_child_bus(mux, "ssi0");
- ssi_create_slave(bus, "ssi-sd");
- bus = qdev_get_child_bus(mux, "ssi1");
- dev = ssi_create_slave(bus, "ssd0323");
- gpio_out[GPIO_C][7] = qdev_get_gpio_in(dev, 0);
+ sddev = ssi_create_slave(bus, "ssi-sd");
+ ssddev = ssi_create_slave(bus, "ssd0323");
+ gpio_out[GPIO_D][0] = qemu_irq_split(qdev_get_gpio_in(sddev, 0),
+ qdev_get_gpio_in(ssddev, 0));
+ gpio_out[GPIO_C][7] = qdev_get_gpio_in(ssddev, 1);
/* Make sure the select pin is high. */
qemu_irq_raise(gpio_out[GPIO_D][0]);
@@ -1394,21 +1349,6 @@ static void stellaris_machine_init(void)
machine_init(stellaris_machine_init);
-static void stellaris_ssi_bus_class_init(ObjectClass *klass, void *data)
-{
- SSISlaveClass *k = SSI_SLAVE_CLASS(klass);
-
- k->init = stellaris_ssi_bus_init;
- k->transfer = stellaris_ssi_bus_transfer;
-}
-
-static TypeInfo stellaris_ssi_bus_info = {
- .name = "evb6965-ssi",
- .parent = TYPE_SSI_SLAVE,
- .instance_size = sizeof(stellaris_ssi_bus_state),
- .class_init = stellaris_ssi_bus_class_init,
-};
-
static void stellaris_i2c_class_init(ObjectClass *klass, void *data)
{
SysBusDeviceClass *sdc = SYS_BUS_DEVICE_CLASS(klass);
@@ -1456,7 +1396,6 @@ static void stellaris_register_types(void)
type_register_static(&stellaris_i2c_info);
type_register_static(&stellaris_gptm_info);
type_register_static(&stellaris_adc_info);
- type_register_static(&stellaris_ssi_bus_info);
}
type_init(stellaris_register_types)
diff --git a/hw/sun4u.c b/hw/sun4u.c
index 07cd04273..137a7c666 100644
--- a/hw/sun4u.c
+++ b/hw/sun4u.c
@@ -39,7 +39,6 @@
#include "elf.h"
#include "blockdev.h"
#include "exec-memory.h"
-#include "vga-pci.h"
//#define DEBUG_IRQ
//#define DEBUG_EBUS
diff --git a/hw/tcx.c b/hw/tcx.c
index 93994d644..2db2db123 100644
--- a/hw/tcx.c
+++ b/hw/tcx.c
@@ -472,7 +472,6 @@ static void tcx_dac_writel(void *opaque, target_phys_addr_t addr, uint64_t val,
default:
break;
}
- return;
}
static const MemoryRegionOps tcx_dac_ops = {
diff --git a/hw/usb/dev-uas.c b/hw/usb/dev-uas.c
index 5a0057a36..4389380e9 100644
--- a/hw/usb/dev-uas.c
+++ b/hw/usb/dev-uas.c
@@ -576,7 +576,6 @@ bad_target:
*/
usb_uas_queue_response(uas, req->tag, UAS_RC_INVALID_INFO_UNIT, 0);
g_free(req);
- return;
}
static void usb_uas_task(UASDevice *uas, uas_ui *ui)
@@ -640,7 +639,6 @@ bad_target:
incorrect_lun:
usb_uas_queue_response(uas, tag, UAS_RC_INCORRECT_LUN, 0);
- return;
}
static int usb_uas_handle_data(USBDevice *dev, USBPacket *p)
diff --git a/hw/usb/hcd-ohci.c b/hw/usb/hcd-ohci.c
index c36184ae4..59c7055cb 100644
--- a/hw/usb/hcd-ohci.c
+++ b/hw/usb/hcd-ohci.c
@@ -1470,8 +1470,6 @@ static void ohci_port_set_status(OHCIState *ohci, int portnum, uint32_t val)
if (old_state != port->ctrl)
ohci_set_interrupt(ohci, OHCI_INTR_RHSC);
-
- return;
}
static uint64_t ohci_mem_read(void *opaque,
diff --git a/hw/usb/hcd-xhci.c b/hw/usb/hcd-xhci.c
index e79a8724c..3a41b067c 100644
--- a/hw/usb/hcd-xhci.c
+++ b/hw/usb/hcd-xhci.c
@@ -807,7 +807,6 @@ static void xhci_events_update(XHCIState *xhci, int v)
DPRINTF("xhci_events_update(): event ring no longer full\n");
intr->er_full = 0;
}
- return;
}
static void xhci_event(XHCIState *xhci, XHCIEvent *event, int v)
diff --git a/hw/versatilepb.c b/hw/versatilepb.c
index 7a9203471..b3f807714 100644
--- a/hw/versatilepb.c
+++ b/hw/versatilepb.c
@@ -211,7 +211,8 @@ static void versatile_init(ram_addr_t ram_size,
cpu_pic = arm_pic_init_cpu(cpu);
dev = sysbus_create_varargs("pl190", 0x10140000,
- cpu_pic[0], cpu_pic[1], NULL);
+ cpu_pic[ARM_PIC_CPU_IRQ],
+ cpu_pic[ARM_PIC_CPU_FIQ], NULL);
for (n = 0; n < 32; n++) {
pic[n] = qdev_get_gpio_in(dev, n);
}
diff --git a/hw/vga-pci.c b/hw/vga-pci.c
index 9abbada8f..996d47f23 100644
--- a/hw/vga-pci.c
+++ b/hw/vga-pci.c
@@ -24,7 +24,6 @@
#include "hw.h"
#include "console.h"
#include "pci.h"
-#include "vga-pci.h"
#include "vga_int.h"
#include "pixel_ops.h"
#include "qemu-timer.h"
@@ -47,7 +46,7 @@ static const VMStateDescription vmstate_vga_pci = {
}
};
-static int pci_vga_initfn(PCIDevice *dev)
+static int pci_std_vga_initfn(PCIDevice *dev)
{
PCIVGAState *d = DO_UPCAST(PCIVGAState, dev, dev);
VGACommonState *s = &d->vga;
@@ -70,11 +69,6 @@ static int pci_vga_initfn(PCIDevice *dev)
return 0;
}
-DeviceState *pci_vga_init(PCIBus *bus)
-{
- return &pci_create_simple(bus, -1, "VGA")->qdev;
-}
-
static Property vga_pci_properties[] = {
DEFINE_PROP_UINT32("vgamem_mb", PCIVGAState, vga.vram_size_mb, 16),
DEFINE_PROP_END_OF_LIST(),
@@ -86,7 +80,7 @@ static void vga_class_init(ObjectClass *klass, void *data)
PCIDeviceClass *k = PCI_DEVICE_CLASS(klass);
k->no_hotplug = 1;
- k->init = pci_vga_initfn;
+ k->init = pci_std_vga_initfn;
k->romfile = "vgabios-stdvga.bin";
k->vendor_id = PCI_VENDOR_ID_QEMU;
k->device_id = PCI_DEVICE_ID_QEMU_VGA;
diff --git a/hw/vga-pci.h b/hw/vga-pci.h
deleted file mode 100644
index 49abf1309..000000000
--- a/hw/vga-pci.h
+++ /dev/null
@@ -1,12 +0,0 @@
-#ifndef VGA_PCI_H
-#define VGA_PCI_H
-
-#include "qemu-common.h"
-
-/* vga-pci.c */
-DeviceState *pci_vga_init(PCIBus *bus);
-
-/* cirrus_vga.c */
-DeviceState *pci_cirrus_vga_init(PCIBus *bus);
-
-#endif
diff --git a/hw/vmware_vga.c b/hw/vmware_vga.c
index e815a04e9..6f7074e55 100644
--- a/hw/vmware_vga.c
+++ b/hw/vmware_vga.c
@@ -25,7 +25,6 @@
#include "loader.h"
#include "console.h"
#include "pci.h"
-#include "vmware_vga.h"
#undef VERBOSE
#define HW_RECT_ACCEL
diff --git a/hw/vmware_vga.h b/hw/vmware_vga.h
deleted file mode 100644
index 000fbddc0..000000000
--- a/hw/vmware_vga.h
+++ /dev/null
@@ -1,15 +0,0 @@
-#ifndef QEMU_VMWARE_VGA_H
-#define QEMU_VMWARE_VGA_H
-
-#include "qemu-common.h"
-
-/* vmware_vga.c */
-static inline DeviceState *pci_vmsvga_init(PCIBus *bus)
-{
- PCIDevice *dev;
-
- dev = pci_create_simple(bus, -1, "vmware-svga");
- return &dev->qdev;
-}
-
-#endif
diff --git a/hw/xen_domainbuild.c b/hw/xen_domainbuild.c
index a6a12e593..db1497469 100644
--- a/hw/xen_domainbuild.c
+++ b/hw/xen_domainbuild.c
@@ -153,7 +153,6 @@ static void xen_domain_poll(void *opaque)
quit:
qemu_system_shutdown_request();
- return;
}
static int xen_domain_watcher(void)
diff --git a/hw/xics.c b/hw/xics.c
index b674771dc..ce88aa750 100644
--- a/hw/xics.c
+++ b/hw/xics.c
@@ -165,11 +165,12 @@ struct ics_irq_state {
int server;
uint8_t priority;
uint8_t saved_priority;
- enum xics_irq_type type;
- int asserted:1;
- int sent:1;
- int rejected:1;
- int masked_pending:1;
+#define XICS_STATUS_ASSERTED 0x1
+#define XICS_STATUS_SENT 0x2
+#define XICS_STATUS_REJECTED 0x4
+#define XICS_STATUS_MASKED_PENDING 0x8
+ uint8_t status;
+ bool lsi;
};
struct ics_state {
@@ -191,8 +192,8 @@ static void resend_msi(struct ics_state *ics, int srcno)
struct ics_irq_state *irq = ics->irqs + srcno;
/* FIXME: filter by server#? */
- if (irq->rejected) {
- irq->rejected = 0;
+ if (irq->status & XICS_STATUS_REJECTED) {
+ irq->status &= ~XICS_STATUS_REJECTED;
if (irq->priority != 0xff) {
icp_irq(ics->icp, irq->server, srcno + ics->offset,
irq->priority);
@@ -204,8 +205,10 @@ static void resend_lsi(struct ics_state *ics, int srcno)
{
struct ics_irq_state *irq = ics->irqs + srcno;
- if ((irq->priority != 0xff) && irq->asserted && !irq->sent) {
- irq->sent = 1;
+ if ((irq->priority != 0xff)
+ && (irq->status & XICS_STATUS_ASSERTED)
+ && !(irq->status & XICS_STATUS_SENT)) {
+ irq->status |= XICS_STATUS_SENT;
icp_irq(ics->icp, irq->server, srcno + ics->offset, irq->priority);
}
}
@@ -216,7 +219,7 @@ static void set_irq_msi(struct ics_state *ics, int srcno, int val)
if (val) {
if (irq->priority == 0xff) {
- irq->masked_pending = 1;
+ irq->status |= XICS_STATUS_MASKED_PENDING;
/* masked pending */ ;
} else {
icp_irq(ics->icp, irq->server, srcno + ics->offset, irq->priority);
@@ -228,7 +231,11 @@ static void set_irq_lsi(struct ics_state *ics, int srcno, int val)
{
struct ics_irq_state *irq = ics->irqs + srcno;
- irq->asserted = val;
+ if (val) {
+ irq->status |= XICS_STATUS_ASSERTED;
+ } else {
+ irq->status &= ~XICS_STATUS_ASSERTED;
+ }
resend_lsi(ics, srcno);
}
@@ -237,7 +244,7 @@ static void ics_set_irq(void *opaque, int srcno, int val)
struct ics_state *ics = (struct ics_state *)opaque;
struct ics_irq_state *irq = ics->irqs + srcno;
- if (irq->type == XICS_LSI) {
+ if (irq->lsi) {
set_irq_lsi(ics, srcno, val);
} else {
set_irq_msi(ics, srcno, val);
@@ -248,11 +255,12 @@ static void write_xive_msi(struct ics_state *ics, int srcno)
{
struct ics_irq_state *irq = ics->irqs + srcno;
- if (!irq->masked_pending || (irq->priority == 0xff)) {
+ if (!(irq->status & XICS_STATUS_MASKED_PENDING)
+ || (irq->priority == 0xff)) {
return;
}
- irq->masked_pending = 0;
+ irq->status &= ~XICS_STATUS_MASKED_PENDING;
icp_irq(ics->icp, irq->server, srcno + ics->offset, irq->priority);
}
@@ -262,15 +270,16 @@ static void write_xive_lsi(struct ics_state *ics, int srcno)
}
static void ics_write_xive(struct ics_state *ics, int nr, int server,
- uint8_t priority)
+ uint8_t priority, uint8_t saved_priority)
{
int srcno = nr - ics->offset;
struct ics_irq_state *irq = ics->irqs + srcno;
irq->server = server;
irq->priority = priority;
+ irq->saved_priority = saved_priority;
- if (irq->type == XICS_LSI) {
+ if (irq->lsi) {
write_xive_lsi(ics, srcno);
} else {
write_xive_msi(ics, srcno);
@@ -281,8 +290,8 @@ static void ics_reject(struct ics_state *ics, int nr)
{
struct ics_irq_state *irq = ics->irqs + nr - ics->offset;
- irq->rejected = 1; /* Irrelevant but harmless for LSI */
- irq->sent = 0; /* Irrelevant but harmless for MSI */
+ irq->status |= XICS_STATUS_REJECTED; /* Irrelevant but harmless for LSI */
+ irq->status &= ~XICS_STATUS_SENT; /* Irrelevant but harmless for MSI */
}
static void ics_resend(struct ics_state *ics)
@@ -293,7 +302,7 @@ static void ics_resend(struct ics_state *ics)
struct ics_irq_state *irq = ics->irqs + i;
/* FIXME: filter by server#? */
- if (irq->type == XICS_LSI) {
+ if (irq->lsi) {
resend_lsi(ics, i);
} else {
resend_msi(ics, i);
@@ -306,8 +315,8 @@ static void ics_eoi(struct ics_state *ics, int nr)
int srcno = nr - ics->offset;
struct ics_irq_state *irq = ics->irqs + srcno;
- if (irq->type == XICS_LSI) {
- irq->sent = 0;
+ if (irq->lsi) {
+ irq->status &= ~XICS_STATUS_SENT;
}
}
@@ -325,14 +334,12 @@ qemu_irq xics_get_qirq(struct icp_state *icp, int irq)
return icp->ics->qirqs[irq - icp->ics->offset];
}
-void xics_set_irq_type(struct icp_state *icp, int irq,
- enum xics_irq_type type)
+void xics_set_irq_type(struct icp_state *icp, int irq, bool lsi)
{
assert((irq >= icp->ics->offset)
&& (irq < (icp->ics->offset + icp->ics->nr_irqs)));
- assert((type == XICS_MSI) || (type == XICS_LSI));
- icp->ics->irqs[irq - icp->ics->offset].type = type;
+ icp->ics->irqs[irq - icp->ics->offset].lsi = lsi;
}
static target_ulong h_cppr(CPUPPCState *env, sPAPREnvironment *spapr,
@@ -399,7 +406,7 @@ static void rtas_set_xive(sPAPREnvironment *spapr, uint32_t token,
return;
}
- ics_write_xive(ics, nr, server, priority);
+ ics_write_xive(ics, nr, server, priority, priority);
rtas_st(rets, 0, 0); /* Success */
}
@@ -447,14 +454,8 @@ static void rtas_int_off(sPAPREnvironment *spapr, uint32_t token,
return;
}
- /* This is a NOP for now, since the described PAPR semantics don't
- * seem to gel with what Linux does */
-#if 0
- struct ics_irq_state *irq = xics->irqs + (nr - xics->offset);
-
- irq->saved_priority = irq->priority;
- ics_write_xive_msi(xics, nr, irq->server, 0xff);
-#endif
+ ics_write_xive(ics, nr, ics->irqs[nr - ics->offset].server, 0xff,
+ ics->irqs[nr - ics->offset].priority);
rtas_st(rets, 0, 0); /* Success */
}
@@ -478,22 +479,40 @@ static void rtas_int_on(sPAPREnvironment *spapr, uint32_t token,
return;
}
- /* This is a NOP for now, since the described PAPR semantics don't
- * seem to gel with what Linux does */
-#if 0
- struct ics_irq_state *irq = xics->irqs + (nr - xics->offset);
-
- ics_write_xive_msi(xics, nr, irq->server, irq->saved_priority);
-#endif
+ ics_write_xive(ics, nr, ics->irqs[nr - ics->offset].server,
+ ics->irqs[nr - ics->offset].saved_priority,
+ ics->irqs[nr - ics->offset].saved_priority);
rtas_st(rets, 0, 0); /* Success */
}
+static void xics_reset(void *opaque)
+{
+ struct icp_state *icp = (struct icp_state *)opaque;
+ struct ics_state *ics = icp->ics;
+ int i;
+
+ for (i = 0; i < icp->nr_servers; i++) {
+ icp->ss[i].xirr = 0;
+ icp->ss[i].pending_priority = 0;
+ icp->ss[i].mfrr = 0xff;
+ /* Make all outputs are deasserted */
+ qemu_set_irq(icp->ss[i].output, 0);
+ }
+
+ for (i = 0; i < ics->nr_irqs; i++) {
+ /* Reset everything *except* the type */
+ ics->irqs[i].server = 0;
+ ics->irqs[i].status = 0;
+ ics->irqs[i].priority = 0xff;
+ ics->irqs[i].saved_priority = 0xff;
+ }
+}
+
struct icp_state *xics_system_init(int nr_irqs)
{
CPUPPCState *env;
int max_server_num;
- int i;
struct icp_state *icp;
struct ics_state *ics;
@@ -508,10 +527,6 @@ struct icp_state *xics_system_init(int nr_irqs)
icp->nr_servers = max_server_num + 1;
icp->ss = g_malloc0(icp->nr_servers*sizeof(struct icp_server_state));
- for (i = 0; i < icp->nr_servers; i++) {
- icp->ss[i].mfrr = 0xff;
- }
-
for (env = first_cpu; env != NULL; env = env->next_cpu) {
struct icp_server_state *ss = &icp->ss[env->cpu_index];
@@ -539,11 +554,6 @@ struct icp_state *xics_system_init(int nr_irqs)
icp->ics = ics;
ics->icp = icp;
- for (i = 0; i < nr_irqs; i++) {
- ics->irqs[i].priority = 0xff;
- ics->irqs[i].saved_priority = 0xff;
- }
-
ics->qirqs = qemu_allocate_irqs(ics_set_irq, ics, nr_irqs);
spapr_register_hypercall(H_CPPR, h_cppr);
@@ -556,5 +566,7 @@ struct icp_state *xics_system_init(int nr_irqs)
spapr_rtas_register("ibm,int-off", rtas_int_off);
spapr_rtas_register("ibm,int-on", rtas_int_on);
+ qemu_register_reset(xics_reset, icp);
+
return icp;
}
diff --git a/hw/xics.h b/hw/xics.h
index 99b96ac85..681726869 100644
--- a/hw/xics.h
+++ b/hw/xics.h
@@ -31,14 +31,8 @@
struct icp_state;
-enum xics_irq_type {
- XICS_MSI, /* Message-signalled (edge) interrupt */
- XICS_LSI, /* Level-signalled interrupt */
-};
-
qemu_irq xics_get_qirq(struct icp_state *icp, int irq);
-void xics_set_irq_type(struct icp_state *icp, int irq,
- enum xics_irq_type type);
+void xics_set_irq_type(struct icp_state *icp, int irq, bool lsi);
struct icp_state *xics_system_init(int nr_irqs);
diff --git a/hw/xilinx_spi.c b/hw/xilinx_spi.c
new file mode 100644
index 000000000..5cdf967c2
--- /dev/null
+++ b/hw/xilinx_spi.c
@@ -0,0 +1,385 @@
+/*
+ * QEMU model of the Xilinx SPI Controller
+ *
+ * Copyright (C) 2010 Edgar E. Iglesias.
+ * Copyright (C) 2012 Peter A. G. Crosthwaite <peter.crosthwaite@petalogix.com>
+ * Copyright (C) 2012 PetaLogix
+ *
+ * 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 "sysbus.h"
+#include "sysemu.h"
+#include "qemu-log.h"
+#include "fifo.h"
+
+#include "ssi.h"
+
+#ifdef XILINX_SPI_ERR_DEBUG
+#define DB_PRINT(...) do { \
+ fprintf(stderr, ": %s: ", __func__); \
+ fprintf(stderr, ## __VA_ARGS__); \
+ } while (0);
+#else
+ #define DB_PRINT(...)
+#endif
+
+#define R_DGIER (0x1c / 4)
+#define R_DGIER_IE (1 << 31)
+
+#define R_IPISR (0x20 / 4)
+#define IRQ_DRR_NOT_EMPTY (1 << (31 - 23))
+#define IRQ_DRR_OVERRUN (1 << (31 - 26))
+#define IRQ_DRR_FULL (1 << (31 - 27))
+#define IRQ_TX_FF_HALF_EMPTY (1 << 6)
+#define IRQ_DTR_UNDERRUN (1 << 3)
+#define IRQ_DTR_EMPTY (1 << (31 - 29))
+
+#define R_IPIER (0x28 / 4)
+#define R_SRR (0x40 / 4)
+#define R_SPICR (0x60 / 4)
+#define R_SPICR_TXFF_RST (1 << 5)
+#define R_SPICR_RXFF_RST (1 << 6)
+#define R_SPICR_MTI (1 << 8)
+
+#define R_SPISR (0x64 / 4)
+#define SR_TX_FULL (1 << 3)
+#define SR_TX_EMPTY (1 << 2)
+#define SR_RX_FULL (1 << 1)
+#define SR_RX_EMPTY (1 << 0)
+
+#define R_SPIDTR (0x68 / 4)
+#define R_SPIDRR (0x6C / 4)
+#define R_SPISSR (0x70 / 4)
+#define R_TX_FF_OCY (0x74 / 4)
+#define R_RX_FF_OCY (0x78 / 4)
+#define R_MAX (0x7C / 4)
+
+#define FIFO_CAPACITY 256
+
+typedef struct XilinxSPI {
+ SysBusDevice busdev;
+ MemoryRegion mmio;
+
+ qemu_irq irq;
+ int irqline;
+
+ uint8_t num_cs;
+ qemu_irq *cs_lines;
+
+ SSIBus *spi;
+
+ Fifo8 rx_fifo;
+ Fifo8 tx_fifo;
+
+ uint32_t regs[R_MAX];
+} XilinxSPI;
+
+static void txfifo_reset(XilinxSPI *s)
+{
+ fifo8_reset(&s->tx_fifo);
+
+ s->regs[R_SPISR] &= ~SR_TX_FULL;
+ s->regs[R_SPISR] |= SR_TX_EMPTY;
+}
+
+static void rxfifo_reset(XilinxSPI *s)
+{
+ fifo8_reset(&s->rx_fifo);
+
+ s->regs[R_SPISR] |= SR_RX_EMPTY;
+ s->regs[R_SPISR] &= ~SR_RX_FULL;
+}
+
+static void xlx_spi_update_cs(XilinxSPI *s)
+{
+ int i;
+
+ for (i = 0; i < s->num_cs; ++i) {
+ qemu_set_irq(s->cs_lines[i], !(~s->regs[R_SPISSR] & 1 << i));
+ }
+}
+
+static void xlx_spi_update_irq(XilinxSPI *s)
+{
+ uint32_t pending;
+
+ s->regs[R_IPISR] |=
+ (!fifo8_is_empty(&s->rx_fifo) ? IRQ_DRR_NOT_EMPTY : 0) |
+ (fifo8_is_full(&s->rx_fifo) ? IRQ_DRR_FULL : 0);
+
+ pending = s->regs[R_IPISR] & s->regs[R_IPIER];
+
+ pending = pending && (s->regs[R_DGIER] & R_DGIER_IE);
+ pending = !!pending;
+
+ /* This call lies right in the data paths so don't call the
+ irq chain unless things really changed. */
+ if (pending != s->irqline) {
+ s->irqline = pending;
+ DB_PRINT("irq_change of state %d ISR:%x IER:%X\n",
+ pending, s->regs[R_IPISR], s->regs[R_IPIER]);
+ qemu_set_irq(s->irq, pending);
+ }
+
+}
+
+static void xlx_spi_do_reset(XilinxSPI *s)
+{
+ memset(s->regs, 0, sizeof s->regs);
+
+ rxfifo_reset(s);
+ txfifo_reset(s);
+
+ s->regs[R_SPISSR] = ~0;
+ xlx_spi_update_irq(s);
+ xlx_spi_update_cs(s);
+}
+
+static void xlx_spi_reset(DeviceState *d)
+{
+ xlx_spi_do_reset(DO_UPCAST(XilinxSPI, busdev.qdev, d));
+}
+
+static inline int spi_master_enabled(XilinxSPI *s)
+{
+ return !(s->regs[R_SPICR] & R_SPICR_MTI);
+}
+
+static void spi_flush_txfifo(XilinxSPI *s)
+{
+ uint32_t tx;
+ uint32_t rx;
+
+ while (!fifo8_is_empty(&s->tx_fifo)) {
+ tx = (uint32_t)fifo8_pop(&s->tx_fifo);
+ DB_PRINT("data tx:%x\n", tx);
+ rx = ssi_transfer(s->spi, tx);
+ DB_PRINT("data rx:%x\n", rx);
+ if (fifo8_is_full(&s->rx_fifo)) {
+ s->regs[R_IPISR] |= IRQ_DRR_OVERRUN;
+ } else {
+ fifo8_push(&s->rx_fifo, (uint8_t)rx);
+ if (fifo8_is_full(&s->rx_fifo)) {
+ s->regs[R_SPISR] |= SR_RX_FULL;
+ s->regs[R_IPISR] |= IRQ_DRR_FULL;
+ }
+ }
+
+ s->regs[R_SPISR] &= ~SR_RX_EMPTY;
+ s->regs[R_SPISR] &= ~SR_TX_FULL;
+ s->regs[R_SPISR] |= SR_TX_EMPTY;
+
+ s->regs[R_IPISR] |= IRQ_DTR_EMPTY;
+ s->regs[R_IPISR] |= IRQ_DRR_NOT_EMPTY;
+ }
+
+}
+
+static uint64_t
+spi_read(void *opaque, target_phys_addr_t addr, unsigned int size)
+{
+ XilinxSPI *s = opaque;
+ uint32_t r = 0;
+
+ addr >>= 2;
+ switch (addr) {
+ case R_SPIDRR:
+ if (fifo8_is_empty(&s->rx_fifo)) {
+ DB_PRINT("Read from empty FIFO!\n");
+ return 0xdeadbeef;
+ }
+
+ s->regs[R_SPISR] &= ~SR_RX_FULL;
+ r = fifo8_pop(&s->rx_fifo);
+ if (fifo8_is_empty(&s->rx_fifo)) {
+ s->regs[R_SPISR] |= SR_RX_EMPTY;
+ }
+ break;
+
+ case R_SPISR:
+ r = s->regs[addr];
+ break;
+
+ default:
+ if (addr < ARRAY_SIZE(s->regs)) {
+ r = s->regs[addr];
+ }
+ break;
+
+ }
+ DB_PRINT("addr=" TARGET_FMT_plx " = %x\n", addr * 4, r);
+ xlx_spi_update_irq(s);
+ return r;
+}
+
+static void
+spi_write(void *opaque, target_phys_addr_t addr,
+ uint64_t val64, unsigned int size)
+{
+ XilinxSPI *s = opaque;
+ uint32_t value = val64;
+
+ DB_PRINT("addr=" TARGET_FMT_plx " = %x\n", addr, value);
+ addr >>= 2;
+ switch (addr) {
+ case R_SRR:
+ if (value != 0xa) {
+ DB_PRINT("Invalid write to SRR %x\n", value);
+ } else {
+ xlx_spi_do_reset(s);
+ }
+ break;
+
+ case R_SPIDTR:
+ s->regs[R_SPISR] &= ~SR_TX_EMPTY;
+ fifo8_push(&s->tx_fifo, (uint8_t)value);
+ if (fifo8_is_full(&s->tx_fifo)) {
+ s->regs[R_SPISR] |= SR_TX_FULL;
+ }
+ if (!spi_master_enabled(s)) {
+ goto done;
+ } else {
+ DB_PRINT("DTR and master enabled\n");
+ }
+ spi_flush_txfifo(s);
+ break;
+
+ case R_SPISR:
+ DB_PRINT("Invalid write to SPISR %x\n", value);
+ break;
+
+ case R_IPISR:
+ /* Toggle the bits. */
+ s->regs[addr] ^= value;
+ break;
+
+ /* Slave Select Register. */
+ case R_SPISSR:
+ s->regs[addr] = value;
+ xlx_spi_update_cs(s);
+ break;
+
+ case R_SPICR:
+ /* FIXME: reset irq and sr state to empty queues. */
+ if (value & R_SPICR_RXFF_RST) {
+ rxfifo_reset(s);
+ }
+
+ if (value & R_SPICR_TXFF_RST) {
+ txfifo_reset(s);
+ }
+ value &= ~(R_SPICR_RXFF_RST | R_SPICR_TXFF_RST);
+ s->regs[addr] = value;
+
+ if (!(value & R_SPICR_MTI)) {
+ spi_flush_txfifo(s);
+ }
+ break;
+
+ default:
+ if (addr < ARRAY_SIZE(s->regs)) {
+ s->regs[addr] = value;
+ }
+ break;
+ }
+
+done:
+ xlx_spi_update_irq(s);
+}
+
+static const MemoryRegionOps spi_ops = {
+ .read = spi_read,
+ .write = spi_write,
+ .endianness = DEVICE_NATIVE_ENDIAN,
+ .valid = {
+ .min_access_size = 4,
+ .max_access_size = 4
+ }
+};
+
+static int xilinx_spi_init(SysBusDevice *dev)
+{
+ int i;
+ XilinxSPI *s = FROM_SYSBUS(typeof(*s), dev);
+
+ DB_PRINT("\n");
+
+ s->spi = ssi_create_bus(&dev->qdev, "spi");
+
+ sysbus_init_irq(dev, &s->irq);
+ s->cs_lines = g_new(qemu_irq, s->num_cs);
+ ssi_auto_connect_slaves(DEVICE(s), s->cs_lines, s->spi);
+ for (i = 0; i < s->num_cs; ++i) {
+ sysbus_init_irq(dev, &s->cs_lines[i]);
+ }
+
+ memory_region_init_io(&s->mmio, &spi_ops, s, "xilinx-spi", R_MAX * 4);
+ sysbus_init_mmio(dev, &s->mmio);
+
+ s->irqline = -1;
+
+ fifo8_create(&s->tx_fifo, FIFO_CAPACITY);
+ fifo8_create(&s->rx_fifo, FIFO_CAPACITY);
+
+ return 0;
+}
+
+static const VMStateDescription vmstate_xilinx_spi = {
+ .name = "xilinx_spi",
+ .version_id = 1,
+ .minimum_version_id = 1,
+ .minimum_version_id_old = 1,
+ .fields = (VMStateField[]) {
+ VMSTATE_FIFO8(tx_fifo, XilinxSPI),
+ VMSTATE_FIFO8(rx_fifo, XilinxSPI),
+ VMSTATE_UINT32_ARRAY(regs, XilinxSPI, R_MAX),
+ VMSTATE_END_OF_LIST()
+ }
+};
+
+static Property xilinx_spi_properties[] = {
+ DEFINE_PROP_UINT8("num-ss-bits", XilinxSPI, num_cs, 1),
+ DEFINE_PROP_END_OF_LIST(),
+};
+
+static void xilinx_spi_class_init(ObjectClass *klass, void *data)
+{
+ DeviceClass *dc = DEVICE_CLASS(klass);
+ SysBusDeviceClass *k = SYS_BUS_DEVICE_CLASS(klass);
+
+ k->init = xilinx_spi_init;
+ dc->reset = xlx_spi_reset;
+ dc->props = xilinx_spi_properties;
+ dc->vmsd = &vmstate_xilinx_spi;
+}
+
+static TypeInfo xilinx_spi_info = {
+ .name = "xlnx.xps-spi",
+ .parent = TYPE_SYS_BUS_DEVICE,
+ .instance_size = sizeof(XilinxSPI),
+ .class_init = xilinx_spi_class_init,
+};
+
+static void xilinx_spi_register_types(void)
+{
+ type_register_static(&xilinx_spi_info);
+}
+
+type_init(xilinx_spi_register_types)
diff --git a/hw/xilinx_spips.c b/hw/xilinx_spips.c
new file mode 100644
index 000000000..f64a7828f
--- /dev/null
+++ b/hw/xilinx_spips.c
@@ -0,0 +1,354 @@
+/*
+ * QEMU model of the Xilinx Zynq SPI controller
+ *
+ * Copyright (c) 2012 Peter A. G. Crosthwaite
+ *
+ * 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 "sysbus.h"
+#include "sysemu.h"
+#include "ptimer.h"
+#include "qemu-log.h"
+#include "fifo.h"
+#include "ssi.h"
+
+#ifdef XILINX_SPIPS_ERR_DEBUG
+#define DB_PRINT(...) do { \
+ fprintf(stderr, ": %s: ", __func__); \
+ fprintf(stderr, ## __VA_ARGS__); \
+ } while (0);
+#else
+ #define DB_PRINT(...)
+#endif
+
+/* config register */
+#define R_CONFIG (0x00 / 4)
+#define MODEFAIL_GEN_EN (1 << 17)
+#define MAN_START_COM (1 << 16)
+#define MAN_START_EN (1 << 15)
+#define MANUAL_CS (1 << 14)
+#define CS (0xF << 10)
+#define CS_SHIFT (10)
+#define PERI_SEL (1 << 9)
+#define REF_CLK (1 << 8)
+#define FIFO_WIDTH (3 << 6)
+#define BAUD_RATE_DIV (7 << 3)
+#define CLK_PH (1 << 2)
+#define CLK_POL (1 << 1)
+#define MODE_SEL (1 << 0)
+
+/* interrupt mechanism */
+#define R_INTR_STATUS (0x04 / 4)
+#define R_INTR_EN (0x08 / 4)
+#define R_INTR_DIS (0x0C / 4)
+#define R_INTR_MASK (0x10 / 4)
+#define IXR_TX_FIFO_UNDERFLOW (1 << 6)
+#define IXR_RX_FIFO_FULL (1 << 5)
+#define IXR_RX_FIFO_NOT_EMPTY (1 << 4)
+#define IXR_TX_FIFO_FULL (1 << 3)
+#define IXR_TX_FIFO_NOT_FULL (1 << 2)
+#define IXR_TX_FIFO_MODE_FAIL (1 << 1)
+#define IXR_RX_FIFO_OVERFLOW (1 << 0)
+#define IXR_ALL ((IXR_TX_FIFO_UNDERFLOW<<1)-1)
+
+#define R_EN (0x14 / 4)
+#define R_DELAY (0x18 / 4)
+#define R_TX_DATA (0x1C / 4)
+#define R_RX_DATA (0x20 / 4)
+#define R_SLAVE_IDLE_COUNT (0x24 / 4)
+#define R_TX_THRES (0x28 / 4)
+#define R_RX_THRES (0x2C / 4)
+#define R_MOD_ID (0xFC / 4)
+
+#define R_MAX (R_MOD_ID+1)
+
+/* size of TXRX FIFOs */
+#define NUM_CS_LINES 4
+#define RXFF_A 32
+#define TXFF_A 32
+
+typedef struct {
+ SysBusDevice busdev;
+ MemoryRegion iomem;
+ qemu_irq irq;
+ int irqline;
+
+ qemu_irq cs_lines[NUM_CS_LINES];
+ SSIBus *spi;
+
+ Fifo8 rx_fifo;
+ Fifo8 tx_fifo;
+
+ uint32_t regs[R_MAX];
+} XilinxSPIPS;
+
+static void xilinx_spips_update_cs_lines(XilinxSPIPS *s)
+{
+ int i;
+ bool found = false;
+ int field = s->regs[R_CONFIG] >> CS_SHIFT;
+
+ for (i = 0; i < NUM_CS_LINES; i++) {
+ if (~field & (1 << i) && !found) {
+ found = true;
+ DB_PRINT("selecting slave %d\n", i);
+ qemu_set_irq(s->cs_lines[i], 0);
+ } else {
+ qemu_set_irq(s->cs_lines[i], 1);
+ }
+ }
+}
+
+static void xilinx_spips_update_ixr(XilinxSPIPS *s)
+{
+ /* These are set/cleared as they occur */
+ s->regs[R_INTR_STATUS] &= (IXR_TX_FIFO_UNDERFLOW | IXR_RX_FIFO_OVERFLOW |
+ IXR_TX_FIFO_MODE_FAIL);
+ /* these are pure functions of fifo state, set them here */
+ s->regs[R_INTR_STATUS] |=
+ (fifo8_is_full(&s->rx_fifo) ? IXR_RX_FIFO_FULL : 0) |
+ (s->rx_fifo.num >= s->regs[R_RX_THRES] ? IXR_RX_FIFO_NOT_EMPTY : 0) |
+ (fifo8_is_full(&s->tx_fifo) ? IXR_TX_FIFO_FULL : 0) |
+ (s->tx_fifo.num < s->regs[R_TX_THRES] ? IXR_TX_FIFO_NOT_FULL : 0);
+ /* drive external interrupt pin */
+ int new_irqline = !!(s->regs[R_INTR_MASK] & s->regs[R_INTR_STATUS] &
+ IXR_ALL);
+ if (new_irqline != s->irqline) {
+ s->irqline = new_irqline;
+ qemu_set_irq(s->irq, s->irqline);
+ }
+}
+
+static void xilinx_spips_reset(DeviceState *d)
+{
+ XilinxSPIPS *s = DO_UPCAST(XilinxSPIPS, busdev.qdev, d);
+
+ int i;
+ for (i = 0; i < R_MAX; i++) {
+ s->regs[i] = 0;
+ }
+
+ fifo8_reset(&s->rx_fifo);
+ fifo8_reset(&s->rx_fifo);
+ /* non zero resets */
+ s->regs[R_CONFIG] |= MODEFAIL_GEN_EN;
+ s->regs[R_SLAVE_IDLE_COUNT] = 0xFF;
+ s->regs[R_TX_THRES] = 1;
+ s->regs[R_RX_THRES] = 1;
+ /* FIXME: move magic number definition somewhere sensible */
+ s->regs[R_MOD_ID] = 0x01090106;
+ xilinx_spips_update_ixr(s);
+ xilinx_spips_update_cs_lines(s);
+}
+
+static void xilinx_spips_flush_txfifo(XilinxSPIPS *s)
+{
+ for (;;) {
+ uint32_t r;
+ uint8_t value;
+
+ if (fifo8_is_empty(&s->tx_fifo)) {
+ s->regs[R_INTR_STATUS] |= IXR_TX_FIFO_UNDERFLOW;
+ break;
+ } else {
+ value = fifo8_pop(&s->tx_fifo);
+ }
+
+ r = ssi_transfer(s->spi, (uint32_t)value);
+ DB_PRINT("tx = %02x rx = %02x\n", value, r);
+ if (fifo8_is_full(&s->rx_fifo)) {
+ s->regs[R_INTR_STATUS] |= IXR_RX_FIFO_OVERFLOW;
+ DB_PRINT("rx FIFO overflow");
+ } else {
+ fifo8_push(&s->rx_fifo, (uint8_t)r);
+ }
+ }
+ xilinx_spips_update_ixr(s);
+}
+
+static uint64_t xilinx_spips_read(void *opaque, target_phys_addr_t addr,
+ unsigned size)
+{
+ XilinxSPIPS *s = opaque;
+ uint32_t mask = ~0;
+ uint32_t ret;
+
+ addr >>= 2;
+ switch (addr) {
+ case R_CONFIG:
+ mask = 0x0002FFFF;
+ break;
+ case R_INTR_STATUS:
+ case R_INTR_MASK:
+ mask = IXR_ALL;
+ break;
+ case R_EN:
+ mask = 0x1;
+ break;
+ case R_SLAVE_IDLE_COUNT:
+ mask = 0xFF;
+ break;
+ case R_MOD_ID:
+ mask = 0x01FFFFFF;
+ break;
+ case R_INTR_EN:
+ case R_INTR_DIS:
+ case R_TX_DATA:
+ mask = 0;
+ break;
+ case R_RX_DATA:
+ ret = (uint32_t)fifo8_pop(&s->rx_fifo);
+ DB_PRINT("addr=" TARGET_FMT_plx " = %x\n", addr * 4, ret);
+ xilinx_spips_update_ixr(s);
+ return ret;
+ }
+ DB_PRINT("addr=" TARGET_FMT_plx " = %x\n", addr * 4, s->regs[addr] & mask);
+ return s->regs[addr] & mask;
+
+}
+
+static void xilinx_spips_write(void *opaque, target_phys_addr_t addr,
+ uint64_t value, unsigned size)
+{
+ int mask = ~0;
+ int man_start_com = 0;
+ XilinxSPIPS *s = opaque;
+
+ DB_PRINT("addr=" TARGET_FMT_plx " = %x\n", addr, (unsigned)value);
+ addr >>= 2;
+ switch (addr) {
+ case R_CONFIG:
+ mask = 0x0002FFFF;
+ if (value & MAN_START_COM) {
+ man_start_com = 1;
+ }
+ break;
+ case R_INTR_STATUS:
+ mask = IXR_ALL;
+ s->regs[R_INTR_STATUS] &= ~(mask & value);
+ goto no_reg_update;
+ case R_INTR_DIS:
+ mask = IXR_ALL;
+ s->regs[R_INTR_MASK] &= ~(mask & value);
+ goto no_reg_update;
+ case R_INTR_EN:
+ mask = IXR_ALL;
+ s->regs[R_INTR_MASK] |= mask & value;
+ goto no_reg_update;
+ case R_EN:
+ mask = 0x1;
+ break;
+ case R_SLAVE_IDLE_COUNT:
+ mask = 0xFF;
+ break;
+ case R_RX_DATA:
+ case R_INTR_MASK:
+ case R_MOD_ID:
+ mask = 0;
+ break;
+ case R_TX_DATA:
+ fifo8_push(&s->tx_fifo, (uint8_t)value);
+ goto no_reg_update;
+ }
+ s->regs[addr] = (s->regs[addr] & ~mask) | (value & mask);
+no_reg_update:
+ if (man_start_com) {
+ xilinx_spips_flush_txfifo(s);
+ }
+ xilinx_spips_update_ixr(s);
+ xilinx_spips_update_cs_lines(s);
+}
+
+static const MemoryRegionOps spips_ops = {
+ .read = xilinx_spips_read,
+ .write = xilinx_spips_write,
+ .endianness = DEVICE_LITTLE_ENDIAN,
+};
+
+static int xilinx_spips_init(SysBusDevice *dev)
+{
+ XilinxSPIPS *s = FROM_SYSBUS(typeof(*s), dev);
+ int i;
+
+ DB_PRINT("inited device model\n");
+
+ s->spi = ssi_create_bus(&dev->qdev, "spi");
+
+ ssi_auto_connect_slaves(DEVICE(s), s->cs_lines, s->spi);
+ sysbus_init_irq(dev, &s->irq);
+ for (i = 0; i < NUM_CS_LINES; ++i) {
+ sysbus_init_irq(dev, &s->cs_lines[i]);
+ }
+
+ memory_region_init_io(&s->iomem, &spips_ops, s, "spi", R_MAX*4);
+ sysbus_init_mmio(dev, &s->iomem);
+
+ s->irqline = -1;
+
+ fifo8_create(&s->rx_fifo, RXFF_A);
+ fifo8_create(&s->tx_fifo, TXFF_A);
+
+ return 0;
+}
+
+static int xilinx_spips_post_load(void *opaque, int version_id)
+{
+ xilinx_spips_update_ixr((XilinxSPIPS *)opaque);
+ xilinx_spips_update_cs_lines((XilinxSPIPS *)opaque);
+ return 0;
+}
+
+static const VMStateDescription vmstate_xilinx_spips = {
+ .name = "xilinx_spips",
+ .version_id = 1,
+ .minimum_version_id = 1,
+ .minimum_version_id_old = 1,
+ .post_load = xilinx_spips_post_load,
+ .fields = (VMStateField[]) {
+ VMSTATE_FIFO8(tx_fifo, XilinxSPIPS),
+ VMSTATE_FIFO8(rx_fifo, XilinxSPIPS),
+ VMSTATE_UINT32_ARRAY(regs, XilinxSPIPS, R_MAX),
+ VMSTATE_END_OF_LIST()
+ }
+};
+
+static void xilinx_spips_class_init(ObjectClass *klass, void *data)
+{
+ DeviceClass *dc = DEVICE_CLASS(klass);
+ SysBusDeviceClass *sdc = SYS_BUS_DEVICE_CLASS(klass);
+
+ sdc->init = xilinx_spips_init;
+ dc->reset = xilinx_spips_reset;
+ dc->vmsd = &vmstate_xilinx_spips;
+}
+
+static const TypeInfo xilinx_spips_info = {
+ .name = "xilinx,spips",
+ .parent = TYPE_SYS_BUS_DEVICE,
+ .instance_size = sizeof(XilinxSPIPS),
+ .class_init = xilinx_spips_class_init,
+};
+
+static void xilinx_spips_register_types(void)
+{
+ type_register_static(&xilinx_spips_info);
+}
+
+type_init(xilinx_spips_register_types)
diff --git a/hw/xilinx_zynq.c b/hw/xilinx_zynq.c
index 7e6c27359..fd46ba252 100644
--- a/hw/xilinx_zynq.c
+++ b/hw/xilinx_zynq.c
@@ -24,6 +24,9 @@
#include "flash.h"
#include "blockdev.h"
#include "loader.h"
+#include "ssi.h"
+
+#define NUM_SPI_FLASHES 4
#define FLASH_SIZE (64 * 1024 * 1024)
#define FLASH_SECTOR_SIZE (128 * 1024)
@@ -46,6 +49,34 @@ static void gem_init(NICInfo *nd, uint32_t base, qemu_irq irq)
sysbus_connect_irq(s, 0, irq);
}
+static inline void zynq_init_spi_flashes(uint32_t base_addr, qemu_irq irq)
+{
+ DeviceState *dev;
+ SysBusDevice *busdev;
+ SSIBus *spi;
+ int i;
+
+ dev = qdev_create(NULL, "xilinx,spips");
+ qdev_init_nofail(dev);
+ busdev = sysbus_from_qdev(dev);
+ sysbus_mmio_map(busdev, 0, base_addr);
+ sysbus_connect_irq(busdev, 0, irq);
+
+ spi = (SSIBus *)qdev_get_child_bus(dev, "spi");
+
+ for (i = 0; i < NUM_SPI_FLASHES; ++i) {
+ qemu_irq cs_line;
+
+ dev = ssi_create_slave_no_init(spi, "m25p80");
+ qdev_prop_set_string(dev, "partname", "n25q128");
+ qdev_init_nofail(dev);
+
+ cs_line = qdev_get_gpio_in(dev, 0);
+ sysbus_connect_irq(busdev, i+1, cs_line);
+ }
+
+}
+
static void zynq_init(ram_addr_t ram_size, const char *boot_device,
const char *kernel_filename, const char *kernel_cmdline,
const char *initrd_filename, const char *cpu_model)
@@ -113,6 +144,9 @@ static void zynq_init(ram_addr_t ram_size, const char *boot_device,
pic[n] = qdev_get_gpio_in(dev, n);
}
+ zynq_init_spi_flashes(0xE0006000, pic[58-IRQ_OFFSET]);
+ zynq_init_spi_flashes(0xE0007000, pic[81-IRQ_OFFSET]);
+
sysbus_create_simple("cadence_uart", 0xE0000000, pic[59-IRQ_OFFSET]);
sysbus_create_simple("cadence_uart", 0xE0001000, pic[82-IRQ_OFFSET]);
diff --git a/hw/z2.c b/hw/z2.c
index 289cee90c..076fad20c 100644
--- a/hw/z2.c
+++ b/hw/z2.c
@@ -161,10 +161,11 @@ static int zipit_lcd_init(SSISlave *dev)
static VMStateDescription vmstate_zipit_lcd_state = {
.name = "zipit-lcd",
- .version_id = 1,
- .minimum_version_id = 1,
- .minimum_version_id_old = 1,
+ .version_id = 2,
+ .minimum_version_id = 2,
+ .minimum_version_id_old = 2,
.fields = (VMStateField[]) {
+ VMSTATE_SSI_SLAVE(ssidev, ZipitLCD),
VMSTATE_INT32(selected, ZipitLCD),
VMSTATE_INT32(enabled, ZipitLCD),
VMSTATE_BUFFER(buf, ZipitLCD),
diff --git a/libcacard/vcard.c b/libcacard/vcard.c
index b02556ee0..539177bb4 100644
--- a/libcacard/vcard.c
+++ b/libcacard/vcard.c
@@ -200,7 +200,6 @@ vcard_free(VCard *vcard)
}
vcard_buffer_response_delete(vcard->vcard_buffer_response);
g_free(vcard);
- return;
}
void
diff --git a/libcacard/vcard_emul_nss.c b/libcacard/vcard_emul_nss.c
index e1cae5bc5..5f565e0b4 100644
--- a/libcacard/vcard_emul_nss.c
+++ b/libcacard/vcard_emul_nss.c
@@ -168,7 +168,6 @@ vcard_emul_delete_key(VCardKey *key)
if (key->slot) {
PK11_FreeSlot(key->slot);
}
- return;
}
/*
@@ -418,7 +417,6 @@ vcard_emul_reset(VCard *card, VCardPower power)
/* TODO: we may also need to send insertion/removal events? */
slot = vcard_emul_card_get_slot(card);
PK11_Logout(slot); /* NOTE: ignoring SECStatus return value */
- return;
}
@@ -535,7 +533,6 @@ vcard_emul_get_atr(VCard *card, unsigned char *atr, int *atr_len)
memcpy(atr, nss_atr, len);
*atr_len = len;
- return;
}
/*
diff --git a/libcacard/vreader.c b/libcacard/vreader.c
index ec126dfa4..96d2407e7 100644
--- a/libcacard/vreader.c
+++ b/libcacard/vreader.c
@@ -93,7 +93,6 @@ vreader_free(VReader *reader)
reader->reader_private_free(reader->reader_private);
}
g_free(reader);
- return;
}
static VCard *
diff --git a/linux-user/signal.c b/linux-user/signal.c
index 78691473f..15bc4e8f6 100644
--- a/linux-user/signal.c
+++ b/linux-user/signal.c
@@ -2762,7 +2762,6 @@ static void setup_frame(int sig, struct target_sigaction * ka,
give_sigsegv:
unlock_user_struct(frame, frame_addr, 1);
force_sig(TARGET_SIGSEGV/*, current*/);
- return;
}
long do_sigreturn(CPUMIPSState *regs)
@@ -2871,7 +2870,6 @@ static void setup_rt_frame(int sig, struct target_sigaction *ka,
give_sigsegv:
unlock_user_struct(frame, frame_addr, 1);
force_sig(TARGET_SIGSEGV/*, current*/);
- return;
}
long do_rt_sigreturn(CPUMIPSState *env)
diff --git a/monitor.c b/monitor.c
index 6342972c1..6e828f91f 100644
--- a/monitor.c
+++ b/monitor.c
@@ -898,13 +898,7 @@ static void do_info_registers(Monitor *mon)
{
CPUArchState *env;
env = mon_get_cpu();
-#ifdef TARGET_I386
- cpu_dump_state(env, (FILE *)mon, monitor_fprintf,
- X86_DUMP_FPU);
-#else
- cpu_dump_state(env, (FILE *)mon, monitor_fprintf,
- 0);
-#endif
+ cpu_dump_state(env, (FILE *)mon, monitor_fprintf, CPU_DUMP_FPU);
}
static void do_cpu_set_nr(Monitor *mon, const QDict *qdict)
diff --git a/os-posix.c b/os-posix.c
index f855abb09..488e48005 100644
--- a/os-posix.c
+++ b/os-posix.c
@@ -193,7 +193,6 @@ void os_parse_cmd_args(int index, const char *optarg)
break;
#endif
}
- return;
}
static void change_process_uid(void)
diff --git a/qemu-barrier.h b/qemu-barrier.h
index 16f09429c..faa83d265 100644
--- a/qemu-barrier.h
+++ b/qemu-barrier.h
@@ -6,6 +6,8 @@
#if defined(__i386__)
+#include "compiler.h" /* QEMU_GNUC_PREREQ */
+
/*
* Because of the strongly ordered x86 storage model, wmb() and rmb() are nops
* on x86(well, a compiler barrier only). Well, at least as long as
diff --git a/qemu-common.h b/qemu-common.h
index 15d9e4ed7..b54612b1a 100644
--- a/qemu-common.h
+++ b/qemu-common.h
@@ -223,11 +223,19 @@ int qemu_pipe(int pipefd[2]);
#endif
#ifdef _WIN32
-/* MinGW needs a type cast for the 'buf' argument. */
+/* MinGW needs type casts for the 'buf' and 'optval' arguments. */
+#define qemu_getsockopt(sockfd, level, optname, optval, optlen) \
+ getsockopt(sockfd, level, optname, (void *)optval, optlen)
+#define qemu_setsockopt(sockfd, level, optname, optval, optlen) \
+ setsockopt(sockfd, level, optname, (const void *)optval, optlen)
#define qemu_recv(sockfd, buf, len, flags) recv(sockfd, (void *)buf, len, flags)
#define qemu_sendto(sockfd, buf, len, flags, destaddr, addrlen) \
sendto(sockfd, (const void *)buf, len, flags, destaddr, addrlen)
#else
+#define qemu_getsockopt(sockfd, level, optname, optval, optlen) \
+ getsockopt(sockfd, level, optname, optval, optlen)
+#define qemu_setsockopt(sockfd, level, optname, optval, optlen) \
+ setsockopt(sockfd, level, optname, optval, optlen)
#define qemu_recv(sockfd, buf, len, flags) recv(sockfd, buf, len, flags)
#define qemu_sendto(sockfd, buf, len, flags, destaddr, addrlen) \
sendto(sockfd, buf, len, flags, destaddr, addrlen)
diff --git a/qemu-sockets.c b/qemu-sockets.c
index 1f14e8bc6..2b1ed2f0e 100644
--- a/qemu-sockets.c
+++ b/qemu-sockets.c
@@ -266,7 +266,6 @@ static void wait_for_connect(void *opaque)
s->callback(s->fd, s->opaque);
}
g_free(s);
- return;
}
static int inet_connect_addr(struct addrinfo *addr, bool *in_progress,
@@ -282,7 +281,7 @@ static int inet_connect_addr(struct addrinfo *addr, bool *in_progress,
inet_strfamily(addr->ai_family), strerror(errno));
return -1;
}
- setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, &on, sizeof(on));
+ qemu_setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, &on, sizeof(on));
if (connect_state != NULL) {
socket_set_nonblock(sock);
}
diff --git a/qga/commands-posix.c b/qga/commands-posix.c
index b9f357cb9..726930a90 100644
--- a/qga/commands-posix.c
+++ b/qga/commands-posix.c
@@ -988,8 +988,6 @@ int64_t qmp_guest_fsfreeze_thaw(Error **err)
void qmp_guest_fstrim(bool has_minimum, int64_t minimum, Error **err)
{
error_set(err, QERR_UNSUPPORTED);
-
- return;
}
#endif
diff --git a/qga/commands-win32.c b/qga/commands-win32.c
index 54bc5462e..5bd8fb27f 100644
--- a/qga/commands-win32.c
+++ b/qga/commands-win32.c
@@ -180,8 +180,6 @@ int64_t qmp_guest_fsfreeze_thaw(Error **err)
void qmp_guest_fstrim(bool has_minimum, int64_t minimum, Error **err)
{
error_set(err, QERR_UNSUPPORTED);
-
- return;
}
typedef enum {
diff --git a/savevm.c b/savevm.c
index c7fe28314..31fd2e0ad 100644
--- a/savevm.c
+++ b/savevm.c
@@ -2201,7 +2201,6 @@ void qmp_xen_save_devices_state(const char *filename, Error **errp)
the_end:
if (saved_vm_running)
vm_start();
- return;
}
int load_vmstate(const char *name)
diff --git a/slirp/ip_icmp.h b/slirp/ip_icmp.h
index 1a1af91e1..be4426b8e 100644
--- a/slirp/ip_icmp.h
+++ b/slirp/ip_icmp.h
@@ -92,8 +92,8 @@ struct icmp {
/*
* Lower bounds on packet lengths for various types.
- * For the error advice packets must first insure that the
- * packet is large enought to contain the returned ip header.
+ * For the error advice packets must first ensure that the
+ * packet is large enough to contain the returned ip header.
* Only then can we do the check to see if 64 bits of packet
* data have been returned, since we need to check the returned
* ip header length.
diff --git a/slirp/ip_input.c b/slirp/ip_input.c
index ce24faf16..6f4cff8fd 100644
--- a/slirp/ip_input.c
+++ b/slirp/ip_input.c
@@ -213,7 +213,6 @@ ip_input(struct mbuf *m)
return;
bad:
m_free(m);
- return;
}
#define iptofrag(P) ((struct ipasfrag *)(((char*)(P)) - sizeof(struct qlink)))
diff --git a/slirp/tcp_input.c b/slirp/tcp_input.c
index 942aaf44f..6440eae7f 100644
--- a/slirp/tcp_input.c
+++ b/slirp/tcp_input.c
@@ -1281,8 +1281,6 @@ drop:
* Drop space held by incoming segment and return.
*/
m_free(m);
-
- return;
}
static void
diff --git a/slirp/udp.c b/slirp/udp.c
index ced509656..9286cb7d3 100644
--- a/slirp/udp.c
+++ b/slirp/udp.c
@@ -231,7 +231,6 @@ udp_input(register struct mbuf *m, int iphlen)
return;
bad:
m_free(m);
- return;
}
int udp_output2(struct socket *so, struct mbuf *m,
diff --git a/sysemu.h b/sysemu.h
index 1a63a7769..b38b1a35b 100644
--- a/sysemu.h
+++ b/sysemu.h
@@ -105,10 +105,7 @@ typedef enum {
} VGAInterfaceType;
extern int vga_interface_type;
-#define cirrus_vga_enabled (vga_interface_type == VGA_CIRRUS)
-#define std_vga_enabled (vga_interface_type == VGA_STD)
#define xenfb_enabled (vga_interface_type == VGA_XENFB)
-#define vmsvga_enabled (vga_interface_type == VGA_VMWARE)
#define qxl_enabled (vga_interface_type == VGA_QXL)
extern int graphic_width;
diff --git a/target-arm/cpu.h b/target-arm/cpu.h
index 7fac94f81..ff4de10f1 100644
--- a/target-arm/cpu.h
+++ b/target-arm/cpu.h
@@ -423,8 +423,6 @@ void armv7m_nvic_complete_irq(void *opaque, int irq);
(((cp) << 16) | ((is64) << 15) | ((crn) << 11) | \
((crm) << 7) | ((opc1) << 3) | (opc2))
-#define DECODE_CPREG_CRN(enc) (((enc) >> 7) & 0xf)
-
/* ARMCPRegInfo type field bits. If the SPECIAL bit is set this is a
* special-behaviour cp reg and bits [15..8] indicate what behaviour
* it has. Otherwise it is a simple cp reg, where CONST indicates that
diff --git a/target-arm/helper.h b/target-arm/helper.h
index afdb2b5b1..8b9adf131 100644
--- a/target-arm/helper.h
+++ b/target-arm/helper.h
@@ -1,8 +1,8 @@
#include "def-helper.h"
-DEF_HELPER_1(clz, i32, i32)
-DEF_HELPER_1(sxtb16, i32, i32)
-DEF_HELPER_1(uxtb16, i32, i32)
+DEF_HELPER_FLAGS_1(clz, TCG_CALL_CONST | TCG_CALL_PURE, i32, i32)
+DEF_HELPER_FLAGS_1(sxtb16, TCG_CALL_CONST | TCG_CALL_PURE, i32, i32)
+DEF_HELPER_FLAGS_1(uxtb16, TCG_CALL_CONST | TCG_CALL_PURE, i32, i32)
DEF_HELPER_3(add_setq, i32, env, i32, i32)
DEF_HELPER_3(add_saturate, i32, env, i32, i32)
@@ -10,10 +10,10 @@ DEF_HELPER_3(sub_saturate, i32, env, i32, i32)
DEF_HELPER_3(add_usaturate, i32, env, i32, i32)
DEF_HELPER_3(sub_usaturate, i32, env, i32, i32)
DEF_HELPER_2(double_saturate, i32, env, s32)
-DEF_HELPER_2(sdiv, s32, s32, s32)
-DEF_HELPER_2(udiv, i32, i32, i32)
-DEF_HELPER_1(rbit, i32, i32)
-DEF_HELPER_1(abs, i32, i32)
+DEF_HELPER_FLAGS_2(sdiv, TCG_CALL_CONST | TCG_CALL_PURE, s32, s32, s32)
+DEF_HELPER_FLAGS_2(udiv, TCG_CALL_CONST | TCG_CALL_PURE, i32, i32, i32)
+DEF_HELPER_FLAGS_1(rbit, TCG_CALL_CONST | TCG_CALL_PURE, i32, i32)
+DEF_HELPER_FLAGS_1(abs, TCG_CALL_CONST | TCG_CALL_PURE, i32, i32)
#define PAS_OP(pfx) \
DEF_HELPER_3(pfx ## add8, i32, i32, i32, ptr) \
@@ -45,11 +45,12 @@ DEF_HELPER_3(usat, i32, env, i32, i32)
DEF_HELPER_3(ssat16, i32, env, i32, i32)
DEF_HELPER_3(usat16, i32, env, i32, i32)
-DEF_HELPER_2(usad8, i32, i32, i32)
+DEF_HELPER_FLAGS_2(usad8, TCG_CALL_CONST | TCG_CALL_PURE, i32, i32, i32)
DEF_HELPER_1(logicq_cc, i32, i64)
-DEF_HELPER_3(sel_flags, i32, i32, i32, i32)
+DEF_HELPER_FLAGS_3(sel_flags, TCG_CALL_CONST | TCG_CALL_PURE,
+ i32, i32, i32, i32)
DEF_HELPER_2(exception, void, env, i32)
DEF_HELPER_1(wfi, void, env)
@@ -142,14 +143,9 @@ DEF_HELPER_2(recpe_u32, i32, i32, env)
DEF_HELPER_2(rsqrte_u32, i32, i32, env)
DEF_HELPER_5(neon_tbl, i32, env, i32, i32, i32, i32)
-DEF_HELPER_3(add_cc, i32, env, i32, i32)
DEF_HELPER_3(adc_cc, i32, env, i32, i32)
-DEF_HELPER_3(sub_cc, i32, env, i32, i32)
DEF_HELPER_3(sbc_cc, i32, env, i32, i32)
-DEF_HELPER_3(shl, i32, env, i32, i32)
-DEF_HELPER_3(shr, i32, env, i32, i32)
-DEF_HELPER_3(sar, i32, env, i32, i32)
DEF_HELPER_3(shl_cc, i32, env, i32, i32)
DEF_HELPER_3(shr_cc, i32, env, i32, i32)
DEF_HELPER_3(sar_cc, i32, env, i32, i32)
diff --git a/target-arm/op_helper.c b/target-arm/op_helper.c
index f13fc3ae5..aef592ab8 100644
--- a/target-arm/op_helper.c
+++ b/target-arm/op_helper.c
@@ -323,16 +323,6 @@ uint64_t HELPER(get_cp_reg64)(CPUARMState *env, void *rip)
The only way to do that in TCG is a conditional branch, which clobbers
all our temporaries. For now implement these as helper functions. */
-uint32_t HELPER (add_cc)(CPUARMState *env, uint32_t a, uint32_t b)
-{
- uint32_t result;
- result = a + b;
- env->NF = env->ZF = result;
- env->CF = result < a;
- env->VF = (a ^ b ^ -1) & (a ^ result);
- return result;
-}
-
uint32_t HELPER(adc_cc)(CPUARMState *env, uint32_t a, uint32_t b)
{
uint32_t result;
@@ -348,16 +338,6 @@ uint32_t HELPER(adc_cc)(CPUARMState *env, uint32_t a, uint32_t b)
return result;
}
-uint32_t HELPER(sub_cc)(CPUARMState *env, uint32_t a, uint32_t b)
-{
- uint32_t result;
- result = a - b;
- env->NF = env->ZF = result;
- env->CF = a >= b;
- env->VF = (a ^ b) & (a ^ result);
- return result;
-}
-
uint32_t HELPER(sbc_cc)(CPUARMState *env, uint32_t a, uint32_t b)
{
uint32_t result;
@@ -375,30 +355,6 @@ uint32_t HELPER(sbc_cc)(CPUARMState *env, uint32_t a, uint32_t b)
/* Similarly for variable shift instructions. */
-uint32_t HELPER(shl)(CPUARMState *env, uint32_t x, uint32_t i)
-{
- int shift = i & 0xff;
- if (shift >= 32)
- return 0;
- return x << shift;
-}
-
-uint32_t HELPER(shr)(CPUARMState *env, uint32_t x, uint32_t i)
-{
- int shift = i & 0xff;
- if (shift >= 32)
- return 0;
- return (uint32_t)x >> shift;
-}
-
-uint32_t HELPER(sar)(CPUARMState *env, uint32_t x, uint32_t i)
-{
- int shift = i & 0xff;
- if (shift >= 32)
- shift = 31;
- return (int32_t)x >> shift;
-}
-
uint32_t HELPER(shl_cc)(CPUARMState *env, uint32_t x, uint32_t i)
{
int shift = i & 0xff;
diff --git a/target-arm/translate.c b/target-arm/translate.c
index 5fded491e..c6840b783 100644
--- a/target-arm/translate.c
+++ b/target-arm/translate.c
@@ -85,6 +85,7 @@ static TCGv_ptr cpu_env;
/* We reuse the same 64-bit temporaries for efficiency. */
static TCGv_i64 cpu_V0, cpu_V1, cpu_M0;
static TCGv_i32 cpu_R[16];
+static TCGv_i32 cpu_CF, cpu_NF, cpu_VF, cpu_ZF;
static TCGv_i32 cpu_exclusive_addr;
static TCGv_i32 cpu_exclusive_val;
static TCGv_i32 cpu_exclusive_high;
@@ -115,6 +116,11 @@ void arm_translate_init(void)
offsetof(CPUARMState, regs[i]),
regnames[i]);
}
+ cpu_CF = tcg_global_mem_new_i32(TCG_AREG0, offsetof(CPUARMState, CF), "CF");
+ cpu_NF = tcg_global_mem_new_i32(TCG_AREG0, offsetof(CPUARMState, NF), "NF");
+ cpu_VF = tcg_global_mem_new_i32(TCG_AREG0, offsetof(CPUARMState, VF), "VF");
+ cpu_ZF = tcg_global_mem_new_i32(TCG_AREG0, offsetof(CPUARMState, ZF), "ZF");
+
cpu_exclusive_addr = tcg_global_mem_new_i32(TCG_AREG0,
offsetof(CPUARMState, exclusive_addr), "exclusive_addr");
cpu_exclusive_val = tcg_global_mem_new_i32(TCG_AREG0,
@@ -271,15 +277,6 @@ static void gen_sbfx(TCGv var, int shift, int width)
}
}
-/* Bitfield insertion. Insert val into base. Clobbers base and val. */
-static void gen_bfi(TCGv dest, TCGv base, TCGv val, int shift, uint32_t mask)
-{
- tcg_gen_andi_i32(val, val, mask);
- tcg_gen_shli_i32(val, val, shift);
- tcg_gen_andi_i32(base, base, ~(mask << shift));
- tcg_gen_or_i32(dest, base, val);
-}
-
/* Return (b << 32) + a. Mark inputs as dead */
static TCGv_i64 gen_addq_msw(TCGv_i64 a, TCGv b)
{
@@ -369,53 +366,100 @@ static void gen_add16(TCGv t0, TCGv t1)
tcg_temp_free_i32(t1);
}
-#define gen_set_CF(var) tcg_gen_st_i32(var, cpu_env, offsetof(CPUARMState, CF))
-
/* Set CF to the top bit of var. */
static void gen_set_CF_bit31(TCGv var)
{
- TCGv tmp = tcg_temp_new_i32();
- tcg_gen_shri_i32(tmp, var, 31);
- gen_set_CF(tmp);
- tcg_temp_free_i32(tmp);
+ tcg_gen_shri_i32(cpu_CF, var, 31);
}
/* Set N and Z flags from var. */
static inline void gen_logic_CC(TCGv var)
{
- tcg_gen_st_i32(var, cpu_env, offsetof(CPUARMState, NF));
- tcg_gen_st_i32(var, cpu_env, offsetof(CPUARMState, ZF));
+ tcg_gen_mov_i32(cpu_NF, var);
+ tcg_gen_mov_i32(cpu_ZF, var);
}
/* T0 += T1 + CF. */
static void gen_adc(TCGv t0, TCGv t1)
{
- TCGv tmp;
tcg_gen_add_i32(t0, t0, t1);
- tmp = load_cpu_field(CF);
- tcg_gen_add_i32(t0, t0, tmp);
- tcg_temp_free_i32(tmp);
+ tcg_gen_add_i32(t0, t0, cpu_CF);
}
/* dest = T0 + T1 + CF. */
static void gen_add_carry(TCGv dest, TCGv t0, TCGv t1)
{
- TCGv tmp;
tcg_gen_add_i32(dest, t0, t1);
- tmp = load_cpu_field(CF);
- tcg_gen_add_i32(dest, dest, tmp);
- tcg_temp_free_i32(tmp);
+ tcg_gen_add_i32(dest, dest, cpu_CF);
}
/* dest = T0 - T1 + CF - 1. */
static void gen_sub_carry(TCGv dest, TCGv t0, TCGv t1)
{
- TCGv tmp;
tcg_gen_sub_i32(dest, t0, t1);
- tmp = load_cpu_field(CF);
- tcg_gen_add_i32(dest, dest, tmp);
+ tcg_gen_add_i32(dest, dest, cpu_CF);
tcg_gen_subi_i32(dest, dest, 1);
+}
+
+/* dest = T0 + T1. Compute C, N, V and Z flags */
+static void gen_add_CC(TCGv dest, TCGv t0, TCGv t1)
+{
+ TCGv tmp;
+ tcg_gen_add_i32(cpu_NF, t0, t1);
+ tcg_gen_mov_i32(cpu_ZF, cpu_NF);
+ tcg_gen_setcond_i32(TCG_COND_LTU, cpu_CF, cpu_NF, t0);
+ tcg_gen_xor_i32(cpu_VF, cpu_NF, t0);
+ tmp = tcg_temp_new_i32();
+ tcg_gen_xor_i32(tmp, t0, t1);
+ tcg_gen_andc_i32(cpu_VF, cpu_VF, tmp);
tcg_temp_free_i32(tmp);
+ tcg_gen_mov_i32(dest, cpu_NF);
+}
+
+/* dest = T0 - T1. Compute C, N, V and Z flags */
+static void gen_sub_CC(TCGv dest, TCGv t0, TCGv t1)
+{
+ TCGv tmp;
+ tcg_gen_sub_i32(cpu_NF, t0, t1);
+ tcg_gen_mov_i32(cpu_ZF, cpu_NF);
+ tcg_gen_setcond_i32(TCG_COND_GEU, cpu_CF, t0, t1);
+ tcg_gen_xor_i32(cpu_VF, cpu_NF, t0);
+ tmp = tcg_temp_new_i32();
+ tcg_gen_xor_i32(tmp, t0, t1);
+ tcg_gen_and_i32(cpu_VF, cpu_VF, tmp);
+ tcg_temp_free_i32(tmp);
+ tcg_gen_mov_i32(dest, cpu_NF);
+}
+
+#define GEN_SHIFT(name) \
+static void gen_##name(TCGv dest, TCGv t0, TCGv t1) \
+{ \
+ TCGv tmp1, tmp2, tmp3; \
+ tmp1 = tcg_temp_new_i32(); \
+ tcg_gen_andi_i32(tmp1, t1, 0xff); \
+ tmp2 = tcg_const_i32(0); \
+ tmp3 = tcg_const_i32(0x1f); \
+ tcg_gen_movcond_i32(TCG_COND_GTU, tmp2, tmp1, tmp3, tmp2, t0); \
+ tcg_temp_free_i32(tmp3); \
+ tcg_gen_andi_i32(tmp1, tmp1, 0x1f); \
+ tcg_gen_##name##_i32(dest, tmp2, tmp1); \
+ tcg_temp_free_i32(tmp2); \
+ tcg_temp_free_i32(tmp1); \
+}
+GEN_SHIFT(shl)
+GEN_SHIFT(shr)
+#undef GEN_SHIFT
+
+static void gen_sar(TCGv dest, TCGv t0, TCGv t1)
+{
+ TCGv tmp1, tmp2;
+ tmp1 = tcg_temp_new_i32();
+ tcg_gen_andi_i32(tmp1, t1, 0xff);
+ tmp2 = tcg_const_i32(0x1f);
+ tcg_gen_movcond_i32(TCG_COND_GTU, tmp1, tmp1, tmp2, tmp2, tmp1);
+ tcg_temp_free_i32(tmp2);
+ tcg_gen_sar_i32(dest, t0, tmp1);
+ tcg_temp_free_i32(tmp1);
}
/* FIXME: Implement this natively. */
@@ -423,16 +467,14 @@ static void gen_sub_carry(TCGv dest, TCGv t0, TCGv t1)
static void shifter_out_im(TCGv var, int shift)
{
- TCGv tmp = tcg_temp_new_i32();
if (shift == 0) {
- tcg_gen_andi_i32(tmp, var, 1);
+ tcg_gen_andi_i32(cpu_CF, var, 1);
} else {
- tcg_gen_shri_i32(tmp, var, shift);
- if (shift != 31)
- tcg_gen_andi_i32(tmp, tmp, 1);
+ tcg_gen_shri_i32(cpu_CF, var, shift);
+ if (shift != 31) {
+ tcg_gen_andi_i32(cpu_CF, cpu_CF, 1);
+ }
}
- gen_set_CF(tmp);
- tcg_temp_free_i32(tmp);
}
/* Shift by immediate. Includes special handling for shift == 0. */
@@ -449,8 +491,7 @@ static inline void gen_arm_shift_im(TCGv var, int shiftop, int shift, int flags)
case 1: /* LSR */
if (shift == 0) {
if (flags) {
- tcg_gen_shri_i32(var, var, 31);
- gen_set_CF(var);
+ tcg_gen_shri_i32(cpu_CF, var, 31);
}
tcg_gen_movi_i32(var, 0);
} else {
@@ -474,11 +515,11 @@ static inline void gen_arm_shift_im(TCGv var, int shiftop, int shift, int flags)
shifter_out_im(var, shift - 1);
tcg_gen_rotri_i32(var, var, shift); break;
} else {
- TCGv tmp = load_cpu_field(CF);
+ TCGv tmp = tcg_temp_new_i32();
if (flags)
shifter_out_im(var, 0);
tcg_gen_shri_i32(var, var, 1);
- tcg_gen_shli_i32(tmp, tmp, 31);
+ tcg_gen_shli_i32(tmp, cpu_CF, 31);
tcg_gen_or_i32(var, var, tmp);
tcg_temp_free_i32(tmp);
}
@@ -497,9 +538,15 @@ static inline void gen_arm_shift_reg(TCGv var, int shiftop,
}
} else {
switch (shiftop) {
- case 0: gen_helper_shl(var, cpu_env, var, shift); break;
- case 1: gen_helper_shr(var, cpu_env, var, shift); break;
- case 2: gen_helper_sar(var, cpu_env, var, shift); break;
+ case 0:
+ gen_shl(var, var, shift);
+ break;
+ case 1:
+ gen_shr(var, var, shift);
+ break;
+ case 2:
+ gen_sar(var, var, shift);
+ break;
case 3: tcg_gen_andi_i32(shift, shift, 0x1f);
tcg_gen_rotr_i32(var, var, shift); break;
}
@@ -603,99 +650,75 @@ static void gen_thumb2_parallel_addsub(int op1, int op2, TCGv a, TCGv b)
static void gen_test_cc(int cc, int label)
{
TCGv tmp;
- TCGv tmp2;
int inv;
switch (cc) {
case 0: /* eq: Z */
- tmp = load_cpu_field(ZF);
- tcg_gen_brcondi_i32(TCG_COND_EQ, tmp, 0, label);
+ tcg_gen_brcondi_i32(TCG_COND_EQ, cpu_ZF, 0, label);
break;
case 1: /* ne: !Z */
- tmp = load_cpu_field(ZF);
- tcg_gen_brcondi_i32(TCG_COND_NE, tmp, 0, label);
+ tcg_gen_brcondi_i32(TCG_COND_NE, cpu_ZF, 0, label);
break;
case 2: /* cs: C */
- tmp = load_cpu_field(CF);
- tcg_gen_brcondi_i32(TCG_COND_NE, tmp, 0, label);
+ tcg_gen_brcondi_i32(TCG_COND_NE, cpu_CF, 0, label);
break;
case 3: /* cc: !C */
- tmp = load_cpu_field(CF);
- tcg_gen_brcondi_i32(TCG_COND_EQ, tmp, 0, label);
+ tcg_gen_brcondi_i32(TCG_COND_EQ, cpu_CF, 0, label);
break;
case 4: /* mi: N */
- tmp = load_cpu_field(NF);
- tcg_gen_brcondi_i32(TCG_COND_LT, tmp, 0, label);
+ tcg_gen_brcondi_i32(TCG_COND_LT, cpu_NF, 0, label);
break;
case 5: /* pl: !N */
- tmp = load_cpu_field(NF);
- tcg_gen_brcondi_i32(TCG_COND_GE, tmp, 0, label);
+ tcg_gen_brcondi_i32(TCG_COND_GE, cpu_NF, 0, label);
break;
case 6: /* vs: V */
- tmp = load_cpu_field(VF);
- tcg_gen_brcondi_i32(TCG_COND_LT, tmp, 0, label);
+ tcg_gen_brcondi_i32(TCG_COND_LT, cpu_VF, 0, label);
break;
case 7: /* vc: !V */
- tmp = load_cpu_field(VF);
- tcg_gen_brcondi_i32(TCG_COND_GE, tmp, 0, label);
+ tcg_gen_brcondi_i32(TCG_COND_GE, cpu_VF, 0, label);
break;
case 8: /* hi: C && !Z */
inv = gen_new_label();
- tmp = load_cpu_field(CF);
- tcg_gen_brcondi_i32(TCG_COND_EQ, tmp, 0, inv);
- tcg_temp_free_i32(tmp);
- tmp = load_cpu_field(ZF);
- tcg_gen_brcondi_i32(TCG_COND_NE, tmp, 0, label);
+ tcg_gen_brcondi_i32(TCG_COND_EQ, cpu_CF, 0, inv);
+ tcg_gen_brcondi_i32(TCG_COND_NE, cpu_ZF, 0, label);
gen_set_label(inv);
break;
case 9: /* ls: !C || Z */
- tmp = load_cpu_field(CF);
- tcg_gen_brcondi_i32(TCG_COND_EQ, tmp, 0, label);
- tcg_temp_free_i32(tmp);
- tmp = load_cpu_field(ZF);
- tcg_gen_brcondi_i32(TCG_COND_EQ, tmp, 0, label);
+ tcg_gen_brcondi_i32(TCG_COND_EQ, cpu_CF, 0, label);
+ tcg_gen_brcondi_i32(TCG_COND_EQ, cpu_ZF, 0, label);
break;
case 10: /* ge: N == V -> N ^ V == 0 */
- tmp = load_cpu_field(VF);
- tmp2 = load_cpu_field(NF);
- tcg_gen_xor_i32(tmp, tmp, tmp2);
- tcg_temp_free_i32(tmp2);
+ tmp = tcg_temp_new_i32();
+ tcg_gen_xor_i32(tmp, cpu_VF, cpu_NF);
tcg_gen_brcondi_i32(TCG_COND_GE, tmp, 0, label);
+ tcg_temp_free_i32(tmp);
break;
case 11: /* lt: N != V -> N ^ V != 0 */
- tmp = load_cpu_field(VF);
- tmp2 = load_cpu_field(NF);
- tcg_gen_xor_i32(tmp, tmp, tmp2);
- tcg_temp_free_i32(tmp2);
+ tmp = tcg_temp_new_i32();
+ tcg_gen_xor_i32(tmp, cpu_VF, cpu_NF);
tcg_gen_brcondi_i32(TCG_COND_LT, tmp, 0, label);
+ tcg_temp_free_i32(tmp);
break;
case 12: /* gt: !Z && N == V */
inv = gen_new_label();
- tmp = load_cpu_field(ZF);
- tcg_gen_brcondi_i32(TCG_COND_EQ, tmp, 0, inv);
- tcg_temp_free_i32(tmp);
- tmp = load_cpu_field(VF);
- tmp2 = load_cpu_field(NF);
- tcg_gen_xor_i32(tmp, tmp, tmp2);
- tcg_temp_free_i32(tmp2);
+ tcg_gen_brcondi_i32(TCG_COND_EQ, cpu_ZF, 0, inv);
+ tmp = tcg_temp_new_i32();
+ tcg_gen_xor_i32(tmp, cpu_VF, cpu_NF);
tcg_gen_brcondi_i32(TCG_COND_GE, tmp, 0, label);
+ tcg_temp_free_i32(tmp);
gen_set_label(inv);
break;
case 13: /* le: Z || N != V */
- tmp = load_cpu_field(ZF);
- tcg_gen_brcondi_i32(TCG_COND_EQ, tmp, 0, label);
- tcg_temp_free_i32(tmp);
- tmp = load_cpu_field(VF);
- tmp2 = load_cpu_field(NF);
- tcg_gen_xor_i32(tmp, tmp, tmp2);
- tcg_temp_free_i32(tmp2);
+ tcg_gen_brcondi_i32(TCG_COND_EQ, cpu_ZF, 0, label);
+ tmp = tcg_temp_new_i32();
+ tcg_gen_xor_i32(tmp, cpu_VF, cpu_NF);
tcg_gen_brcondi_i32(TCG_COND_LT, tmp, 0, label);
+ tcg_temp_free_i32(tmp);
break;
default:
fprintf(stderr, "Bad condition code 0x%x\n", cc);
abort();
}
- tcg_temp_free_i32(tmp);
}
static const uint8_t table_logic_cc[16] = {
@@ -2628,12 +2651,12 @@ static int disas_vfp_insn(CPUARMState * env, DisasContext *s, uint32_t insn)
switch (size) {
case 0:
tmp2 = neon_load_reg(rn, pass);
- gen_bfi(tmp, tmp2, tmp, offset, 0xff);
+ tcg_gen_deposit_i32(tmp, tmp2, tmp, offset, 8);
tcg_temp_free_i32(tmp2);
break;
case 1:
tmp2 = neon_load_reg(rn, pass);
- gen_bfi(tmp, tmp2, tmp, offset, 0xffff);
+ tcg_gen_deposit_i32(tmp, tmp2, tmp, offset, 16);
tcg_temp_free_i32(tmp2);
break;
case 2:
@@ -3989,7 +4012,8 @@ static int disas_neon_ls_insn(CPUARMState * env, DisasContext *s, uint32_t insn)
}
if (size != 2) {
tmp2 = neon_load_reg(rd, pass);
- gen_bfi(tmp, tmp2, tmp, shift, size ? 0xffff : 0xff);
+ tcg_gen_deposit_i32(tmp, tmp2, tmp,
+ shift, size ? 16 : 8);
tcg_temp_free_i32(tmp2);
}
neon_store_reg(rd, pass, tmp);
@@ -7005,11 +7029,11 @@ static void disas_arm_insn(CPUARMState * env, DisasContext *s)
if (IS_USER(s)) {
goto illegal_op;
}
- gen_helper_sub_cc(tmp, cpu_env, tmp, tmp2);
+ gen_sub_CC(tmp, tmp, tmp2);
gen_exception_return(s, tmp);
} else {
if (set_cc) {
- gen_helper_sub_cc(tmp, cpu_env, tmp, tmp2);
+ gen_sub_CC(tmp, tmp, tmp2);
} else {
tcg_gen_sub_i32(tmp, tmp, tmp2);
}
@@ -7018,7 +7042,7 @@ static void disas_arm_insn(CPUARMState * env, DisasContext *s)
break;
case 0x03:
if (set_cc) {
- gen_helper_sub_cc(tmp, cpu_env, tmp2, tmp);
+ gen_sub_CC(tmp, tmp2, tmp);
} else {
tcg_gen_sub_i32(tmp, tmp2, tmp);
}
@@ -7026,7 +7050,7 @@ static void disas_arm_insn(CPUARMState * env, DisasContext *s)
break;
case 0x04:
if (set_cc) {
- gen_helper_add_cc(tmp, cpu_env, tmp, tmp2);
+ gen_add_CC(tmp, tmp, tmp2);
} else {
tcg_gen_add_i32(tmp, tmp, tmp2);
}
@@ -7072,13 +7096,13 @@ static void disas_arm_insn(CPUARMState * env, DisasContext *s)
break;
case 0x0a:
if (set_cc) {
- gen_helper_sub_cc(tmp, cpu_env, tmp, tmp2);
+ gen_sub_CC(tmp, tmp, tmp2);
}
tcg_temp_free_i32(tmp);
break;
case 0x0b:
if (set_cc) {
- gen_helper_add_cc(tmp, cpu_env, tmp, tmp2);
+ gen_add_CC(tmp, tmp, tmp2);
}
tcg_temp_free_i32(tmp);
break;
@@ -7593,7 +7617,7 @@ static void disas_arm_insn(CPUARMState * env, DisasContext *s)
}
if (i != 32) {
tmp2 = load_reg(s, rd);
- gen_bfi(tmp, tmp2, tmp, shift, (1u << i) - 1);
+ tcg_gen_deposit_i32(tmp, tmp2, tmp, shift, i);
tcg_temp_free_i32(tmp2);
}
store_reg(s, rd, tmp);
@@ -7865,7 +7889,7 @@ gen_thumb2_data_op(DisasContext *s, int op, int conds, uint32_t shifter_out, TCG
break;
case 8: /* add */
if (conds)
- gen_helper_add_cc(t0, cpu_env, t0, t1);
+ gen_add_CC(t0, t0, t1);
else
tcg_gen_add_i32(t0, t0, t1);
break;
@@ -7883,13 +7907,13 @@ gen_thumb2_data_op(DisasContext *s, int op, int conds, uint32_t shifter_out, TCG
break;
case 13: /* sub */
if (conds)
- gen_helper_sub_cc(t0, cpu_env, t0, t1);
+ gen_sub_CC(t0, t0, t1);
else
tcg_gen_sub_i32(t0, t0, t1);
break;
case 14: /* rsb */
if (conds)
- gen_helper_sub_cc(t0, cpu_env, t1, t0);
+ gen_sub_CC(t0, t1, t0);
else
tcg_gen_sub_i32(t0, t1, t0);
break;
@@ -8704,7 +8728,7 @@ static int disas_thumb2_insn(CPUARMState *env, DisasContext *s, uint16_t insn_hw
imm = imm + 1 - shift;
if (imm != 32) {
tmp2 = load_reg(s, rd);
- gen_bfi(tmp, tmp2, tmp, shift, (1u << imm) - 1);
+ tcg_gen_deposit_i32(tmp, tmp2, tmp, shift, imm);
tcg_temp_free_i32(tmp2);
}
break;
@@ -9017,12 +9041,12 @@ static void disas_thumb_insn(CPUARMState *env, DisasContext *s)
if (s->condexec_mask)
tcg_gen_sub_i32(tmp, tmp, tmp2);
else
- gen_helper_sub_cc(tmp, cpu_env, tmp, tmp2);
+ gen_sub_CC(tmp, tmp, tmp2);
} else {
if (s->condexec_mask)
tcg_gen_add_i32(tmp, tmp, tmp2);
else
- gen_helper_add_cc(tmp, cpu_env, tmp, tmp2);
+ gen_add_CC(tmp, tmp, tmp2);
}
tcg_temp_free_i32(tmp2);
store_reg(s, rd, tmp);
@@ -9053,7 +9077,7 @@ static void disas_thumb_insn(CPUARMState *env, DisasContext *s)
tcg_gen_movi_i32(tmp2, insn & 0xff);
switch (op) {
case 1: /* cmp */
- gen_helper_sub_cc(tmp, cpu_env, tmp, tmp2);
+ gen_sub_CC(tmp, tmp, tmp2);
tcg_temp_free_i32(tmp);
tcg_temp_free_i32(tmp2);
break;
@@ -9061,7 +9085,7 @@ static void disas_thumb_insn(CPUARMState *env, DisasContext *s)
if (s->condexec_mask)
tcg_gen_add_i32(tmp, tmp, tmp2);
else
- gen_helper_add_cc(tmp, cpu_env, tmp, tmp2);
+ gen_add_CC(tmp, tmp, tmp2);
tcg_temp_free_i32(tmp2);
store_reg(s, rd, tmp);
break;
@@ -9069,7 +9093,7 @@ static void disas_thumb_insn(CPUARMState *env, DisasContext *s)
if (s->condexec_mask)
tcg_gen_sub_i32(tmp, tmp, tmp2);
else
- gen_helper_sub_cc(tmp, cpu_env, tmp, tmp2);
+ gen_sub_CC(tmp, tmp, tmp2);
tcg_temp_free_i32(tmp2);
store_reg(s, rd, tmp);
break;
@@ -9105,7 +9129,7 @@ static void disas_thumb_insn(CPUARMState *env, DisasContext *s)
case 1: /* cmp */
tmp = load_reg(s, rd);
tmp2 = load_reg(s, rm);
- gen_helper_sub_cc(tmp, cpu_env, tmp, tmp2);
+ gen_sub_CC(tmp, tmp, tmp2);
tcg_temp_free_i32(tmp2);
tcg_temp_free_i32(tmp);
break;
@@ -9166,7 +9190,7 @@ static void disas_thumb_insn(CPUARMState *env, DisasContext *s)
break;
case 0x2: /* lsl */
if (s->condexec_mask) {
- gen_helper_shl(tmp2, cpu_env, tmp2, tmp);
+ gen_shl(tmp2, tmp2, tmp);
} else {
gen_helper_shl_cc(tmp2, cpu_env, tmp2, tmp);
gen_logic_CC(tmp2);
@@ -9174,7 +9198,7 @@ static void disas_thumb_insn(CPUARMState *env, DisasContext *s)
break;
case 0x3: /* lsr */
if (s->condexec_mask) {
- gen_helper_shr(tmp2, cpu_env, tmp2, tmp);
+ gen_shr(tmp2, tmp2, tmp);
} else {
gen_helper_shr_cc(tmp2, cpu_env, tmp2, tmp);
gen_logic_CC(tmp2);
@@ -9182,7 +9206,7 @@ static void disas_thumb_insn(CPUARMState *env, DisasContext *s)
break;
case 0x4: /* asr */
if (s->condexec_mask) {
- gen_helper_sar(tmp2, cpu_env, tmp2, tmp);
+ gen_sar(tmp2, tmp2, tmp);
} else {
gen_helper_sar_cc(tmp2, cpu_env, tmp2, tmp);
gen_logic_CC(tmp2);
@@ -9218,14 +9242,14 @@ static void disas_thumb_insn(CPUARMState *env, DisasContext *s)
if (s->condexec_mask)
tcg_gen_neg_i32(tmp, tmp2);
else
- gen_helper_sub_cc(tmp, cpu_env, tmp, tmp2);
+ gen_sub_CC(tmp, tmp, tmp2);
break;
case 0xa: /* cmp */
- gen_helper_sub_cc(tmp, cpu_env, tmp, tmp2);
+ gen_sub_CC(tmp, tmp, tmp2);
rd = 16;
break;
case 0xb: /* cmn */
- gen_helper_add_cc(tmp, cpu_env, tmp, tmp2);
+ gen_add_CC(tmp, tmp, tmp2);
rd = 16;
break;
case 0xc: /* orr */
@@ -9970,19 +9994,6 @@ void cpu_dump_state(CPUARMState *env, FILE *f, fprintf_function cpu_fprintf,
int flags)
{
int i;
-#if 0
- union {
- uint32_t i;
- float s;
- } s0, s1;
- CPU_DoubleU d;
- /* ??? This assumes float64 and double have the same layout.
- Oh well, it's only debug dumps. */
- union {
- float64 f64;
- double d;
- } d0;
-#endif
uint32_t psr;
for(i=0;i<16;i++) {
@@ -10002,20 +10013,23 @@ void cpu_dump_state(CPUARMState *env, FILE *f, fprintf_function cpu_fprintf,
psr & CPSR_T ? 'T' : 'A',
cpu_mode_names[psr & 0xf], (psr & 0x10) ? 32 : 26);
-#if 0
- for (i = 0; i < 16; i++) {
- d.d = env->vfp.regs[i];
- s0.i = d.l.lower;
- s1.i = d.l.upper;
- d0.f64 = d.d;
- cpu_fprintf(f, "s%02d=%08x(%8g) s%02d=%08x(%8g) d%02d=%08x%08x(%8g)\n",
- i * 2, (int)s0.i, s0.s,
- i * 2 + 1, (int)s1.i, s1.s,
- i, (int)(uint32_t)d.l.upper, (int)(uint32_t)d.l.lower,
- d0.d);
+ if (flags & CPU_DUMP_FPU) {
+ int numvfpregs = 0;
+ if (arm_feature(env, ARM_FEATURE_VFP)) {
+ numvfpregs += 16;
+ }
+ if (arm_feature(env, ARM_FEATURE_VFP3)) {
+ numvfpregs += 16;
+ }
+ for (i = 0; i < numvfpregs; i++) {
+ uint64_t v = float64_val(env->vfp.regs[i]);
+ cpu_fprintf(f, "s%02d=%08x s%02d=%08x d%02d=%016" PRIx64 "\n",
+ i * 2, (uint32_t)v,
+ i * 2 + 1, (uint32_t)(v >> 32),
+ i, v);
+ }
+ cpu_fprintf(f, "FPSCR: %08x\n", (int)env->vfp.xregs[ARM_VFP_FPSCR]);
}
- cpu_fprintf(f, "FPSCR: %08x\n", (int)env->vfp.xregs[ARM_VFP_FPSCR]);
-#endif
}
void restore_state_to_opc(CPUARMState *env, TranslationBlock *tb, int pc_pos)
diff --git a/target-i386/cpu.c b/target-i386/cpu.c
index bb1e44eb0..f3708e63b 100644
--- a/target-i386/cpu.c
+++ b/target-i386/cpu.c
@@ -1759,7 +1759,7 @@ static void x86_cpu_reset(CPUState *s)
if (qemu_loglevel_mask(CPU_LOG_RESET)) {
qemu_log("CPU Reset (CPU %d)\n", env->cpu_index);
- log_cpu_state(env, X86_DUMP_FPU | X86_DUMP_CCOP);
+ log_cpu_state(env, CPU_DUMP_FPU | CPU_DUMP_CCOP);
}
xcc->parent_reset(s);
diff --git a/target-i386/cpu.h b/target-i386/cpu.h
index d28d155a0..bc60cdb06 100644
--- a/target-i386/cpu.h
+++ b/target-i386/cpu.h
@@ -996,10 +996,6 @@ void cpu_smm_update(CPUX86State *env);
uint64_t cpu_get_tsc(CPUX86State *env);
X86CPU *pc_new_cpu(const char *cpu_model);
-/* used to debug */
-#define X86_DUMP_FPU 0x0001 /* dump FPU state too */
-#define X86_DUMP_CCOP 0x0002 /* dump qemu flag cache */
-
#define TARGET_PAGE_BITS 12
#ifdef TARGET_X86_64
diff --git a/target-i386/helper.c b/target-i386/helper.c
index c635667d6..2ee7c6d1b 100644
--- a/target-i386/helper.c
+++ b/target-i386/helper.c
@@ -284,7 +284,7 @@ void cpu_dump_state(CPUX86State *env, FILE *f, fprintf_function cpu_fprintf,
cpu_fprintf(f, "\nDR6=" TARGET_FMT_lx " DR7=" TARGET_FMT_lx "\n",
env->dr[6], env->dr[7]);
}
- if (flags & X86_DUMP_CCOP) {
+ if (flags & CPU_DUMP_CCOP) {
if ((unsigned)env->cc_op < CC_OP_NB)
snprintf(cc_op_name, sizeof(cc_op_name), "%s", cc_op_str[env->cc_op]);
else
@@ -303,7 +303,7 @@ void cpu_dump_state(CPUX86State *env, FILE *f, fprintf_function cpu_fprintf,
}
}
cpu_fprintf(f, "EFER=%016" PRIx64 "\n", env->efer);
- if (flags & X86_DUMP_FPU) {
+ if (flags & CPU_DUMP_FPU) {
int fptag;
fptag = 0;
for(i = 0; i < 8; i++) {
diff --git a/target-i386/seg_helper.c b/target-i386/seg_helper.c
index 5fff8d59c..ff9337441 100644
--- a/target-i386/seg_helper.c
+++ b/target-i386/seg_helper.c
@@ -31,7 +31,7 @@
#ifdef DEBUG_PCALL
# define LOG_PCALL(...) qemu_log_mask(CPU_LOG_PCALL, ## __VA_ARGS__)
# define LOG_PCALL_STATE(env) \
- log_cpu_state_mask(CPU_LOG_PCALL, (env), X86_DUMP_CCOP)
+ log_cpu_state_mask(CPU_LOG_PCALL, (env), CPU_DUMP_CCOP)
#else
# define LOG_PCALL(...) do { } while (0)
# define LOG_PCALL_STATE(env) do { } while (0)
@@ -1177,7 +1177,7 @@ static void do_interrupt_all(CPUX86State *env, int intno, int is_int,
qemu_log(" EAX=" TARGET_FMT_lx, EAX);
}
qemu_log("\n");
- log_cpu_state(env, X86_DUMP_CCOP);
+ log_cpu_state(env, CPU_DUMP_CCOP);
#if 0
{
int i;
diff --git a/target-i386/smm_helper.c b/target-i386/smm_helper.c
index 8b04eb2e0..eea2fe978 100644
--- a/target-i386/smm_helper.c
+++ b/target-i386/smm_helper.c
@@ -47,7 +47,7 @@ void do_smm_enter(CPUX86State *env)
int i, offset;
qemu_log_mask(CPU_LOG_INT, "SMM: enter\n");
- log_cpu_state_mask(CPU_LOG_INT, env, X86_DUMP_CCOP);
+ log_cpu_state_mask(CPU_LOG_INT, env, CPU_DUMP_CCOP);
env->hflags |= HF_SMM_MASK;
cpu_smm_update(env);
@@ -295,7 +295,7 @@ void helper_rsm(CPUX86State *env)
cpu_smm_update(env);
qemu_log_mask(CPU_LOG_INT, "SMM: after RSM\n");
- log_cpu_state_mask(CPU_LOG_INT, env, X86_DUMP_CCOP);
+ log_cpu_state_mask(CPU_LOG_INT, env, CPU_DUMP_CCOP);
}
#endif /* !CONFIG_USER_ONLY */
diff --git a/target-ppc/cpu.h b/target-ppc/cpu.h
index ca2fc2198..faf440407 100644
--- a/target-ppc/cpu.h
+++ b/target-ppc/cpu.h
@@ -1079,7 +1079,6 @@ struct CPUPPCState {
int mmu_idx; /* precomputed MMU index to speed up mem accesses */
/* Power management */
- int power_mode;
int (*check_pow)(CPUPPCState *env);
#if !defined(CONFIG_USER_ONLY)
diff --git a/target-ppc/int_helper.c b/target-ppc/int_helper.c
index f638b2a07..f39b4f682 100644
--- a/target-ppc/int_helper.c
+++ b/target-ppc/int_helper.c
@@ -287,23 +287,6 @@ target_ulong helper_602_mfrom(target_ulong arg)
for (index = ARRAY_SIZE(r->element)-1; index >= 0; index--)
#endif
-/* If X is a NaN, store the corresponding QNaN into RESULT. Otherwise,
- * execute the following block. */
-#define DO_HANDLE_NAN(result, x) \
- if (float32_is_any_nan(x)) { \
- CPU_FloatU __f; \
- __f.f = x; \
- __f.l = __f.l | (1 << 22); /* Set QNaN bit. */ \
- result = __f.f; \
- } else
-
-#define HANDLE_NAN1(result, x) \
- DO_HANDLE_NAN(result, x)
-#define HANDLE_NAN2(result, x, y) \
- DO_HANDLE_NAN(result, x) DO_HANDLE_NAN(result, y)
-#define HANDLE_NAN3(result, x, y, z) \
- DO_HANDLE_NAN(result, x) DO_HANDLE_NAN(result, y) DO_HANDLE_NAN(result, z)
-
/* Saturating arithmetic helpers. */
#define SATCVT(from, to, from_type, to_type, min, max) \
static inline to_type cvt##from##to(from_type x, int *sat) \
@@ -409,15 +392,29 @@ VARITH(uwm, u32)
int i; \
\
for (i = 0; i < ARRAY_SIZE(r->f); i++) { \
- HANDLE_NAN2(r->f[i], a->f[i], b->f[i]) { \
- r->f[i] = func(a->f[i], b->f[i], &env->vec_status); \
- } \
+ r->f[i] = func(a->f[i], b->f[i], &env->vec_status); \
} \
}
VARITHFP(addfp, float32_add)
VARITHFP(subfp, float32_sub)
+VARITHFP(minfp, float32_min)
+VARITHFP(maxfp, float32_max)
#undef VARITHFP
+#define VARITHFPFMA(suffix, type) \
+ void helper_v##suffix(CPUPPCState *env, ppc_avr_t *r, ppc_avr_t *a, \
+ ppc_avr_t *b, ppc_avr_t *c) \
+ { \
+ int i; \
+ for (i = 0; i < ARRAY_SIZE(r->f); i++) { \
+ r->f[i] = float32_muladd(a->f[i], c->f[i], b->f[i], \
+ type, &env->vec_status); \
+ } \
+ }
+VARITHFPFMA(maddfp, 0);
+VARITHFPFMA(nmsubfp, float_muladd_negate_result | float_muladd_negate_c);
+#undef VARITHFPFMA
+
#define VARITHSAT_CASE(type, op, cvt, element) \
{ \
type result = (type)a->element[i] op (type)b->element[i]; \
@@ -649,27 +646,6 @@ VCT(uxs, cvtsduw, u32)
VCT(sxs, cvtsdsw, s32)
#undef VCT
-void helper_vmaddfp(CPUPPCState *env, ppc_avr_t *r, ppc_avr_t *a, ppc_avr_t *b,
- ppc_avr_t *c)
-{
- int i;
-
- for (i = 0; i < ARRAY_SIZE(r->f); i++) {
- HANDLE_NAN3(r->f[i], a->f[i], b->f[i], c->f[i]) {
- /* Need to do the computation in higher precision and round
- * once at the end. */
- float64 af, bf, cf, t;
-
- af = float32_to_float64(a->f[i], &env->vec_status);
- bf = float32_to_float64(b->f[i], &env->vec_status);
- cf = float32_to_float64(c->f[i], &env->vec_status);
- t = float64_mul(af, cf, &env->vec_status);
- t = float64_add(t, bf, &env->vec_status);
- r->f[i] = float64_to_float32(t, &env->vec_status);
- }
- }
-}
-
void helper_vmhaddshs(CPUPPCState *env, ppc_avr_t *r, ppc_avr_t *a,
ppc_avr_t *b, ppc_avr_t *c)
{
@@ -730,27 +706,6 @@ VMINMAX(uw, u32)
#undef VMINMAX_DO
#undef VMINMAX
-#define VMINMAXFP(suffix, rT, rF) \
- void helper_v##suffix(CPUPPCState *env, ppc_avr_t *r, ppc_avr_t *a, \
- ppc_avr_t *b) \
- { \
- int i; \
- \
- for (i = 0; i < ARRAY_SIZE(r->f); i++) { \
- HANDLE_NAN2(r->f[i], a->f[i], b->f[i]) { \
- if (float32_lt_quiet(a->f[i], b->f[i], \
- &env->vec_status)) { \
- r->f[i] = rT->f[i]; \
- } else { \
- r->f[i] = rF->f[i]; \
- } \
- } \
- } \
- }
-VMINMAXFP(minfp, a, b)
-VMINMAXFP(maxfp, b, a)
-#undef VMINMAXFP
-
void helper_vmladduhm(ppc_avr_t *r, ppc_avr_t *a, ppc_avr_t *b, ppc_avr_t *c)
{
int i;
@@ -930,28 +885,6 @@ VMUL(uh, u16, u32)
#undef VMUL_DO
#undef VMUL
-void helper_vnmsubfp(CPUPPCState *env, ppc_avr_t *r, ppc_avr_t *a,
- ppc_avr_t *b, ppc_avr_t *c)
-{
- int i;
-
- for (i = 0; i < ARRAY_SIZE(r->f); i++) {
- HANDLE_NAN3(r->f[i], a->f[i], b->f[i], c->f[i]) {
- /* Need to do the computation is higher precision and round
- * once at the end. */
- float64 af, bf, cf, t;
-
- af = float32_to_float64(a->f[i], &env->vec_status);
- bf = float32_to_float64(b->f[i], &env->vec_status);
- cf = float32_to_float64(c->f[i], &env->vec_status);
- t = float64_mul(af, cf, &env->vec_status);
- t = float64_sub(t, bf, &env->vec_status);
- t = float64_chs(t);
- r->f[i] = float64_to_float32(t, &env->vec_status);
- }
- }
-}
-
void helper_vperm(CPUPPCState *env, ppc_avr_t *r, ppc_avr_t *a, ppc_avr_t *b,
ppc_avr_t *c)
{
@@ -1039,9 +972,7 @@ void helper_vrefp(CPUPPCState *env, ppc_avr_t *r, ppc_avr_t *b)
int i;
for (i = 0; i < ARRAY_SIZE(r->f); i++) {
- HANDLE_NAN1(r->f[i], b->f[i]) {
- r->f[i] = float32_div(float32_one, b->f[i], &env->vec_status);
- }
+ r->f[i] = float32_div(float32_one, b->f[i], &env->vec_status);
}
}
@@ -1054,9 +985,7 @@ void helper_vrefp(CPUPPCState *env, ppc_avr_t *r, ppc_avr_t *b)
\
set_float_rounding_mode(rounding, &s); \
for (i = 0; i < ARRAY_SIZE(r->f); i++) { \
- HANDLE_NAN1(r->f[i], b->f[i]) { \
- r->f[i] = float32_round_to_int (b->f[i], &s); \
- } \
+ r->f[i] = float32_round_to_int (b->f[i], &s); \
} \
}
VRFI(n, float_round_nearest_even)
@@ -1089,11 +1018,9 @@ void helper_vrsqrtefp(CPUPPCState *env, ppc_avr_t *r, ppc_avr_t *b)
int i;
for (i = 0; i < ARRAY_SIZE(r->f); i++) {
- HANDLE_NAN1(r->f[i], b->f[i]) {
- float32 t = float32_sqrt(b->f[i], &env->vec_status);
+ float32 t = float32_sqrt(b->f[i], &env->vec_status);
- r->f[i] = float32_div(float32_one, t, &env->vec_status);
- }
+ r->f[i] = float32_div(float32_one, t, &env->vec_status);
}
}
@@ -1109,9 +1036,7 @@ void helper_vexptefp(CPUPPCState *env, ppc_avr_t *r, ppc_avr_t *b)
int i;
for (i = 0; i < ARRAY_SIZE(r->f); i++) {
- HANDLE_NAN1(r->f[i], b->f[i]) {
- r->f[i] = float32_exp2(b->f[i], &env->vec_status);
- }
+ r->f[i] = float32_exp2(b->f[i], &env->vec_status);
}
}
@@ -1120,9 +1045,7 @@ void helper_vlogefp(CPUPPCState *env, ppc_avr_t *r, ppc_avr_t *b)
int i;
for (i = 0; i < ARRAY_SIZE(r->f); i++) {
- HANDLE_NAN1(r->f[i], b->f[i]) {
- r->f[i] = float32_log2(b->f[i], &env->vec_status);
- }
+ r->f[i] = float32_log2(b->f[i], &env->vec_status);
}
}
@@ -1473,10 +1396,6 @@ VUPK(lsh, s32, s16, UPKLO)
#undef UPKHI
#undef UPKLO
-#undef DO_HANDLE_NAN
-#undef HANDLE_NAN1
-#undef HANDLE_NAN2
-#undef HANDLE_NAN3
#undef VECTOR_FOR_INORDER_I
#undef HI_IDX
#undef LO_IDX
diff --git a/target-ppc/kvm.c b/target-ppc/kvm.c
index 7f6e4e0b8..5cbe98a16 100644
--- a/target-ppc/kvm.c
+++ b/target-ppc/kvm.c
@@ -60,6 +60,7 @@ static int cap_booke_sregs;
static int cap_ppc_smt;
static int cap_ppc_rma;
static int cap_spapr_tce;
+static int cap_hior;
/* XXX We have a race condition where we actually have a level triggered
* interrupt, but the infrastructure can't expose that yet, so the guest
@@ -86,6 +87,7 @@ int kvm_arch_init(KVMState *s)
cap_ppc_smt = kvm_check_extension(s, KVM_CAP_PPC_SMT);
cap_ppc_rma = kvm_check_extension(s, KVM_CAP_PPC_RMA);
cap_spapr_tce = kvm_check_extension(s, KVM_CAP_SPAPR_TCE);
+ cap_hior = kvm_check_extension(s, KVM_CAP_PPC_HIOR);
if (!cap_interrupt_level) {
fprintf(stderr, "KVM: Couldn't find level irq capability. Expect the "
@@ -469,6 +471,54 @@ int kvm_arch_put_registers(CPUPPCState *env, int level)
env->tlb_dirty = false;
}
+ if (cap_segstate && (level >= KVM_PUT_RESET_STATE)) {
+ struct kvm_sregs sregs;
+
+ sregs.pvr = env->spr[SPR_PVR];
+
+ sregs.u.s.sdr1 = env->spr[SPR_SDR1];
+
+ /* Sync SLB */
+#ifdef TARGET_PPC64
+ for (i = 0; i < 64; i++) {
+ sregs.u.s.ppc64.slb[i].slbe = env->slb[i].esid;
+ sregs.u.s.ppc64.slb[i].slbv = env->slb[i].vsid;
+ }
+#endif
+
+ /* Sync SRs */
+ for (i = 0; i < 16; i++) {
+ sregs.u.s.ppc32.sr[i] = env->sr[i];
+ }
+
+ /* Sync BATs */
+ for (i = 0; i < 8; i++) {
+ /* Beware. We have to swap upper and lower bits here */
+ sregs.u.s.ppc32.dbat[i] = ((uint64_t)env->DBAT[0][i] << 32)
+ | env->DBAT[1][i];
+ sregs.u.s.ppc32.ibat[i] = ((uint64_t)env->IBAT[0][i] << 32)
+ | env->IBAT[1][i];
+ }
+
+ ret = kvm_vcpu_ioctl(env, KVM_SET_SREGS, &sregs);
+ if (ret) {
+ return ret;
+ }
+ }
+
+ if (cap_hior && (level >= KVM_PUT_RESET_STATE)) {
+ uint64_t hior = env->spr[SPR_HIOR];
+ struct kvm_one_reg reg = {
+ .id = KVM_REG_PPC_HIOR,
+ .addr = (uintptr_t) &hior,
+ };
+
+ ret = kvm_vcpu_ioctl(env, KVM_SET_ONE_REG, &reg);
+ if (ret) {
+ return ret;
+ }
+ }
+
return ret;
}
@@ -946,52 +996,14 @@ int kvmppc_get_hypercall(CPUPPCState *env, uint8_t *buf, int buf_len)
void kvmppc_set_papr(CPUPPCState *env)
{
struct kvm_enable_cap cap = {};
- struct kvm_one_reg reg = {};
- struct kvm_sregs sregs = {};
int ret;
- uint64_t hior = env->spr[SPR_HIOR];
cap.cap = KVM_CAP_PPC_PAPR;
ret = kvm_vcpu_ioctl(env, KVM_ENABLE_CAP, &cap);
if (ret) {
- goto fail;
- }
-
- /*
- * XXX We set HIOR here. It really should be a qdev property of
- * the CPU node, but we don't have CPUs converted to qdev yet.
- *
- * Once we have qdev CPUs, move HIOR to a qdev property and
- * remove this chunk.
- */
- reg.id = KVM_REG_PPC_HIOR;
- reg.addr = (uintptr_t)&hior;
- ret = kvm_vcpu_ioctl(env, KVM_SET_ONE_REG, &reg);
- if (ret) {
- fprintf(stderr, "Couldn't set HIOR. Maybe you're running an old \n"
- "kernel with support for HV KVM but no PAPR PR \n"
- "KVM in which case things will work. If they don't \n"
- "please update your host kernel!\n");
- }
-
- /* Set SDR1 so kernel space finds the HTAB */
- ret = kvm_vcpu_ioctl(env, KVM_GET_SREGS, &sregs);
- if (ret) {
- goto fail;
+ cpu_abort(env, "This KVM version does not support PAPR\n");
}
-
- sregs.u.s.sdr1 = env->spr[SPR_SDR1];
-
- ret = kvm_vcpu_ioctl(env, KVM_SET_SREGS, &sregs);
- if (ret) {
- goto fail;
- }
-
- return;
-
-fail:
- cpu_abort(env, "This KVM version does not support PAPR\n");
}
int kvmppc_smt_threads(void)
@@ -999,6 +1011,7 @@ int kvmppc_smt_threads(void)
return cap_ppc_smt ? cap_ppc_smt : 1;
}
+#ifdef TARGET_PPC64
off_t kvmppc_alloc_rma(const char *name, MemoryRegion *sysmem)
{
void *rma;
@@ -1042,6 +1055,16 @@ off_t kvmppc_alloc_rma(const char *name, MemoryRegion *sysmem)
return size;
}
+uint64_t kvmppc_rma_size(uint64_t current_size, unsigned int hash_shift)
+{
+ if (cap_ppc_rma >= 2) {
+ return current_size;
+ }
+ return MIN(current_size,
+ getrampagesize() << (hash_shift - 7));
+}
+#endif
+
void *kvmppc_create_spapr_tce(uint32_t liobn, uint32_t window_size, int *pfd)
{
struct kvm_create_spapr_tce args = {
@@ -1101,6 +1124,44 @@ int kvmppc_remove_spapr_tce(void *table, int fd, uint32_t window_size)
return 0;
}
+int kvmppc_reset_htab(int shift_hint)
+{
+ uint32_t shift = shift_hint;
+
+ if (!kvm_enabled()) {
+ /* Full emulation, tell caller to allocate htab itself */
+ return 0;
+ }
+ if (kvm_check_extension(kvm_state, KVM_CAP_PPC_ALLOC_HTAB)) {
+ int ret;
+ ret = kvm_vm_ioctl(kvm_state, KVM_PPC_ALLOCATE_HTAB, &shift);
+ if (ret == -ENOTTY) {
+ /* At least some versions of PR KVM advertise the
+ * capability, but don't implement the ioctl(). Oops.
+ * Return 0 so that we allocate the htab in qemu, as is
+ * correct for PR. */
+ return 0;
+ } else if (ret < 0) {
+ return ret;
+ }
+ return shift;
+ }
+
+ /* We have a kernel that predates the htab reset calls. For PR
+ * KVM, we need to allocate the htab ourselves, for an HV KVM of
+ * this era, it has allocated a 16MB fixed size hash table
+ * already. Kernels of this era have the GET_PVINFO capability
+ * only on PR, so we use this hack to determine the right
+ * answer */
+ if (kvm_check_extension(kvm_state, KVM_CAP_PPC_GET_PVINFO)) {
+ /* PR - tell caller to allocate htab */
+ return 0;
+ } else {
+ /* HV - assume 16MB kernel allocated htab */
+ return 24;
+ }
+}
+
static inline uint32_t mfpvr(void)
{
uint32_t pvr;
diff --git a/target-ppc/kvm_ppc.h b/target-ppc/kvm_ppc.h
index e2f870385..baad6eb75 100644
--- a/target-ppc/kvm_ppc.h
+++ b/target-ppc/kvm_ppc.h
@@ -27,6 +27,8 @@ int kvmppc_smt_threads(void);
off_t kvmppc_alloc_rma(const char *name, MemoryRegion *sysmem);
void *kvmppc_create_spapr_tce(uint32_t liobn, uint32_t window_size, int *pfd);
int kvmppc_remove_spapr_tce(void *table, int pfd, uint32_t window_size);
+int kvmppc_reset_htab(int shift_hint);
+uint64_t kvmppc_rma_size(uint64_t current_size, unsigned int hash_shift);
#endif /* !CONFIG_USER_ONLY */
const ppc_def_t *kvmppc_host_cpu_def(void);
int kvmppc_fixup_cpu(CPUPPCState *env);
@@ -94,6 +96,23 @@ static inline int kvmppc_remove_spapr_tce(void *table, int pfd,
{
return -1;
}
+
+static inline int kvmppc_reset_htab(int shift_hint)
+{
+ return -1;
+}
+
+static inline uint64_t kvmppc_rma_size(uint64_t current_size,
+ unsigned int hash_shift)
+{
+ return ram_size;
+}
+
+static inline int kvmppc_update_sdr1(CPUPPCState *env)
+{
+ return 0;
+}
+
#endif /* !CONFIG_USER_ONLY */
static inline const ppc_def_t *kvmppc_host_cpu_def(void)
diff --git a/target-ppc/machine.c b/target-ppc/machine.c
index d6c2ee41b..21ce7575e 100644
--- a/target-ppc/machine.c
+++ b/target-ppc/machine.c
@@ -82,7 +82,7 @@ void cpu_save(QEMUFile *f, void *opaque)
qemu_put_betls(f, &env->hflags);
qemu_put_betls(f, &env->hflags_nmsr);
qemu_put_sbe32s(f, &env->mmu_idx);
- qemu_put_sbe32s(f, &env->power_mode);
+ qemu_put_sbe32(f, 0);
}
int cpu_load(QEMUFile *f, void *opaque, int version_id)
@@ -167,7 +167,7 @@ int cpu_load(QEMUFile *f, void *opaque, int version_id)
qemu_get_betls(f, &env->hflags);
qemu_get_betls(f, &env->hflags_nmsr);
qemu_get_sbe32s(f, &env->mmu_idx);
- qemu_get_sbe32s(f, &env->power_mode);
+ qemu_get_sbe32(f); /* Discard unused power_mode */
return 0;
}
diff --git a/target-ppc/translate_init.c b/target-ppc/translate_init.c
index fba2b4242..a97228703 100644
--- a/target-ppc/translate_init.c
+++ b/target-ppc/translate_init.c
@@ -10423,6 +10423,14 @@ static void ppc_cpu_reset(CPUState *s)
env->pending_interrupts = 0;
env->exception_index = POWERPC_EXCP_NONE;
env->error_code = 0;
+
+#if defined(TARGET_PPC64) && !defined(CONFIG_USER_ONLY)
+ env->vpa = 0;
+ env->slb_shadow = 0;
+ env->dispatch_trace_log = 0;
+ env->dtl_size = 0;
+#endif /* TARGET_PPC64 */
+
/* Flush all TLBs */
tlb_flush(env, 1);
}
diff --git a/target-sparc/cpu.c b/target-sparc/cpu.c
index eb9f0e725..882d30642 100644
--- a/target-sparc/cpu.c
+++ b/target-sparc/cpu.c
@@ -792,7 +792,6 @@ void cpu_dump_state(CPUSPARCState *env, FILE *f, fprintf_function cpu_fprintf,
cpu_fprintf(f, "pc: " TARGET_FMT_lx " npc: " TARGET_FMT_lx "\n", env->pc,
env->npc);
- cpu_fprintf(f, "General Registers:\n");
for (i = 0; i < 8; i++) {
if (i % REGS_PER_LINE == 0) {
@@ -803,7 +802,6 @@ void cpu_dump_state(CPUSPARCState *env, FILE *f, fprintf_function cpu_fprintf,
cpu_fprintf(f, "\n");
}
}
- cpu_fprintf(f, "\nCurrent Register Window:\n");
for (x = 0; x < 3; x++) {
for (i = 0; i < 8; i++) {
if (i % REGS_PER_LINE == 0) {
@@ -817,10 +815,10 @@ void cpu_dump_state(CPUSPARCState *env, FILE *f, fprintf_function cpu_fprintf,
}
}
}
- cpu_fprintf(f, "\nFloating Point Registers:\n");
+
for (i = 0; i < TARGET_DPREGS; i++) {
if ((i & 3) == 0) {
- cpu_fprintf(f, "%%f%02d:", i * 2);
+ cpu_fprintf(f, "%%f%02d: ", i * 2);
}
cpu_fprintf(f, " %016" PRIx64, env->fpr[i].ll);
if ((i & 3) == 3) {
@@ -850,6 +848,7 @@ void cpu_dump_state(CPUSPARCState *env, FILE *f, fprintf_function cpu_fprintf,
cpu_fprintf(f, "fsr: " TARGET_FMT_lx " y: " TARGET_FMT_lx "\n",
env->fsr, env->y);
#endif
+ cpu_fprintf(f, "\n");
}
static void sparc_cpu_initfn(Object *obj)
diff --git a/target-sparc/cpu.h b/target-sparc/cpu.h
index e16b7b351..214d01dd7 100644
--- a/target-sparc/cpu.h
+++ b/target-sparc/cpu.h
@@ -714,6 +714,7 @@ trap_state* cpu_tsptr(CPUSPARCState* env);
void QEMU_NORETURN do_unaligned_access(CPUSPARCState *env, target_ulong addr,
int is_write, int is_user,
uintptr_t retaddr);
+void cpu_restore_state2(CPUSPARCState *env, uintptr_t retaddr);
#define TB_FLAG_FPU_ENABLED (1 << 4)
#define TB_FLAG_AM_ENABLED (1 << 5)
diff --git a/target-sparc/helper.c b/target-sparc/helper.c
index 65e1740e1..556ac286e 100644
--- a/target-sparc/helper.c
+++ b/target-sparc/helper.c
@@ -75,6 +75,7 @@ static target_ulong helper_udiv_common(CPUSPARCState *env, target_ulong a,
x1 = (b & 0xffffffff);
if (x1 == 0) {
+ cpu_restore_state2(env, GETPC());
helper_raise_exception(env, TT_DIV_ZERO);
}
@@ -113,6 +114,7 @@ static target_ulong helper_sdiv_common(CPUSPARCState *env, target_ulong a,
x1 = (b & 0xffffffff);
if (x1 == 0) {
+ cpu_restore_state2(env, GETPC());
helper_raise_exception(env, TT_DIV_ZERO);
}
@@ -139,3 +141,87 @@ target_ulong helper_sdiv_cc(CPUSPARCState *env, target_ulong a, target_ulong b)
{
return helper_sdiv_common(env, a, b, 1);
}
+
+#ifdef TARGET_SPARC64
+int64_t helper_sdivx(CPUSPARCState *env, int64_t a, int64_t b)
+{
+ if (b == 0) {
+ /* Raise divide by zero trap. */
+ cpu_restore_state2(env, GETPC());
+ helper_raise_exception(env, TT_DIV_ZERO);
+ } else if (b == -1) {
+ /* Avoid overflow trap with i386 divide insn. */
+ return -a;
+ } else {
+ return a / b;
+ }
+}
+
+uint64_t helper_udivx(CPUSPARCState *env, uint64_t a, uint64_t b)
+{
+ if (b == 0) {
+ /* Raise divide by zero trap. */
+ cpu_restore_state2(env, GETPC());
+ helper_raise_exception(env, TT_DIV_ZERO);
+ }
+ return a / b;
+}
+#endif
+
+target_ulong helper_taddcctv(CPUSPARCState *env, target_ulong src1,
+ target_ulong src2)
+{
+ target_ulong dst;
+
+ /* Tag overflow occurs if either input has bits 0 or 1 set. */
+ if ((src1 | src2) & 3) {
+ goto tag_overflow;
+ }
+
+ dst = src1 + src2;
+
+ /* Tag overflow occurs if the addition overflows. */
+ if (~(src1 ^ src2) & (src1 ^ dst) & (1u << 31)) {
+ goto tag_overflow;
+ }
+
+ /* Only modify the CC after any exceptions have been generated. */
+ env->cc_op = CC_OP_TADDTV;
+ env->cc_src = src1;
+ env->cc_src2 = src2;
+ env->cc_dst = dst;
+ return dst;
+
+ tag_overflow:
+ cpu_restore_state2(env, GETPC());
+ helper_raise_exception(env, TT_TOVF);
+}
+
+target_ulong helper_tsubcctv(CPUSPARCState *env, target_ulong src1,
+ target_ulong src2)
+{
+ target_ulong dst;
+
+ /* Tag overflow occurs if either input has bits 0 or 1 set. */
+ if ((src1 | src2) & 3) {
+ goto tag_overflow;
+ }
+
+ dst = src1 - src2;
+
+ /* Tag overflow occurs if the subtraction overflows. */
+ if ((src1 ^ src2) & (src1 ^ dst) & (1u << 31)) {
+ goto tag_overflow;
+ }
+
+ /* Only modify the CC after any exceptions have been generated. */
+ env->cc_op = CC_OP_TSUBTV;
+ env->cc_src = src1;
+ env->cc_src2 = src2;
+ env->cc_dst = dst;
+ return dst;
+
+ tag_overflow:
+ cpu_restore_state2(env, GETPC());
+ helper_raise_exception(env, TT_TOVF);
+}
diff --git a/target-sparc/helper.h b/target-sparc/helper.h
index e3c7fddbe..e1ae3c708 100644
--- a/target-sparc/helper.h
+++ b/target-sparc/helper.h
@@ -38,6 +38,12 @@ DEF_HELPER_3(udiv, tl, env, tl, tl)
DEF_HELPER_3(udiv_cc, tl, env, tl, tl)
DEF_HELPER_3(sdiv, tl, env, tl, tl)
DEF_HELPER_3(sdiv_cc, tl, env, tl, tl)
+DEF_HELPER_3(taddcctv, tl, env, tl, tl)
+DEF_HELPER_3(tsubcctv, tl, env, tl, tl)
+#ifdef TARGET_SPARC64
+DEF_HELPER_3(sdivx, s64, env, s64, s64)
+DEF_HELPER_3(udivx, i64, env, i64, i64)
+#endif
DEF_HELPER_3(ldqf, void, env, tl, int)
DEF_HELPER_3(stqf, void, env, tl, int)
#if !defined(CONFIG_USER_ONLY) || defined(TARGET_SPARC64)
diff --git a/target-sparc/int32_helper.c b/target-sparc/int32_helper.c
index 5e33d50e2..9ac5aac33 100644
--- a/target-sparc/int32_helper.c
+++ b/target-sparc/int32_helper.c
@@ -21,7 +21,7 @@
#include "trace.h"
#include "sysemu.h"
-//#define DEBUG_PCALL
+#define DEBUG_PCALL
#ifdef DEBUG_PCALL
static const char * const excp_names[0x80] = {
@@ -78,10 +78,7 @@ void do_interrupt(CPUSPARCState *env)
}
}
- qemu_log("%6d: %s (v=%02x) pc=%08x npc=%08x SP=%08x\n",
- count, name, intno,
- env->pc,
- env->npc, env->regwptr[6]);
+ qemu_log("%6d: %s (v=%02x)\n", count, name, intno);
log_cpu_state(env, 0);
#if 0
{
diff --git a/target-sparc/int64_helper.c b/target-sparc/int64_helper.c
index 5e3eff76d..5d0bc6c6d 100644
--- a/target-sparc/int64_helper.c
+++ b/target-sparc/int64_helper.c
@@ -21,7 +21,7 @@
#include "helper.h"
#include "trace.h"
-//#define DEBUG_PCALL
+#define DEBUG_PCALL
#ifdef DEBUG_PCALL
static const char * const excp_names[0x80] = {
@@ -84,11 +84,7 @@ void do_interrupt(CPUSPARCState *env)
}
}
- qemu_log("%6d: %s (v=%04x) pc=%016" PRIx64 " npc=%016" PRIx64
- " SP=%016" PRIx64 "\n",
- count, name, intno,
- env->pc,
- env->npc, env->regwptr[6]);
+ qemu_log("%6d: %s (v=%04x)\n", count, name, intno);
log_cpu_state(env, 0);
#if 0
{
diff --git a/target-sparc/ldst_helper.c b/target-sparc/ldst_helper.c
index 9bec7a92f..2ca9a5c4a 100644
--- a/target-sparc/ldst_helper.c
+++ b/target-sparc/ldst_helper.c
@@ -2390,9 +2390,8 @@ void cpu_unassigned_access(CPUSPARCState *env, target_phys_addr_t addr,
#endif
#endif
-#if !defined(CONFIG_USER_ONLY)
/* XXX: make it generic ? */
-static void cpu_restore_state2(CPUSPARCState *env, uintptr_t retaddr)
+void cpu_restore_state2(CPUSPARCState *env, uintptr_t retaddr)
{
TranslationBlock *tb;
@@ -2407,6 +2406,7 @@ static void cpu_restore_state2(CPUSPARCState *env, uintptr_t retaddr)
}
}
+#if !defined(CONFIG_USER_ONLY)
void do_unaligned_access(CPUSPARCState *env, target_ulong addr, int is_write,
int is_user, uintptr_t retaddr)
{
diff --git a/target-sparc/translate.c b/target-sparc/translate.c
index e5ebedfa2..472eb518c 100644
--- a/target-sparc/translate.c
+++ b/target-sparc/translate.c
@@ -86,6 +86,13 @@ typedef struct DisasContext {
int n_t32;
} DisasContext;
+typedef struct {
+ TCGCond cond;
+ bool is_bool;
+ bool g1, g2;
+ TCGv c1, c2;
+} DisasCompare;
+
// This function uses non-native bit order
#define GET_FIELD(X, FROM, TO) \
((X) >> (31 - (TO)) & ((1 << ((TO) - (FROM) + 1)) - 1))
@@ -329,43 +336,6 @@ static inline void gen_mov_reg_C(TCGv reg, TCGv_i32 src)
tcg_gen_andi_tl(reg, reg, 0x1);
}
-static inline void gen_add_tv(TCGv dst, TCGv src1, TCGv src2)
-{
- TCGv r_temp;
- TCGv_i32 r_const;
- int l1;
-
- l1 = gen_new_label();
-
- r_temp = tcg_temp_new();
- tcg_gen_xor_tl(r_temp, src1, src2);
- tcg_gen_not_tl(r_temp, r_temp);
- tcg_gen_xor_tl(cpu_tmp0, src1, dst);
- tcg_gen_and_tl(r_temp, r_temp, cpu_tmp0);
- tcg_gen_andi_tl(r_temp, r_temp, (1ULL << 31));
- tcg_gen_brcondi_tl(TCG_COND_EQ, r_temp, 0, l1);
- r_const = tcg_const_i32(TT_TOVF);
- gen_helper_raise_exception(cpu_env, r_const);
- tcg_temp_free_i32(r_const);
- gen_set_label(l1);
- tcg_temp_free(r_temp);
-}
-
-static inline void gen_tag_tv(TCGv src1, TCGv src2)
-{
- int l1;
- TCGv_i32 r_const;
-
- l1 = gen_new_label();
- tcg_gen_or_tl(cpu_tmp0, src1, src2);
- tcg_gen_andi_tl(cpu_tmp0, cpu_tmp0, 0x3);
- tcg_gen_brcondi_tl(TCG_COND_EQ, cpu_tmp0, 0, l1);
- r_const = tcg_const_i32(TT_TOVF);
- gen_helper_raise_exception(cpu_env, r_const);
- tcg_temp_free_i32(r_const);
- gen_set_label(l1);
-}
-
static inline void gen_op_addi_cc(TCGv dst, TCGv src1, target_long src2)
{
tcg_gen_mov_tl(cpu_cc_src, src1);
@@ -510,45 +480,6 @@ static void gen_op_addx_int(DisasContext *dc, TCGv dst, TCGv src1,
}
}
-static inline void gen_op_tadd_cc(TCGv dst, TCGv src1, TCGv src2)
-{
- tcg_gen_mov_tl(cpu_cc_src, src1);
- tcg_gen_mov_tl(cpu_cc_src2, src2);
- tcg_gen_add_tl(cpu_cc_dst, cpu_cc_src, cpu_cc_src2);
- tcg_gen_mov_tl(dst, cpu_cc_dst);
-}
-
-static inline void gen_op_tadd_ccTV(TCGv dst, TCGv src1, TCGv src2)
-{
- tcg_gen_mov_tl(cpu_cc_src, src1);
- tcg_gen_mov_tl(cpu_cc_src2, src2);
- gen_tag_tv(cpu_cc_src, cpu_cc_src2);
- tcg_gen_add_tl(cpu_cc_dst, cpu_cc_src, cpu_cc_src2);
- gen_add_tv(cpu_cc_dst, cpu_cc_src, cpu_cc_src2);
- tcg_gen_mov_tl(dst, cpu_cc_dst);
-}
-
-static inline void gen_sub_tv(TCGv dst, TCGv src1, TCGv src2)
-{
- TCGv r_temp;
- TCGv_i32 r_const;
- int l1;
-
- l1 = gen_new_label();
-
- r_temp = tcg_temp_new();
- tcg_gen_xor_tl(r_temp, src1, src2);
- tcg_gen_xor_tl(cpu_tmp0, src1, dst);
- tcg_gen_and_tl(r_temp, r_temp, cpu_tmp0);
- tcg_gen_andi_tl(r_temp, r_temp, (1ULL << 31));
- tcg_gen_brcondi_tl(TCG_COND_EQ, r_temp, 0, l1);
- r_const = tcg_const_i32(TT_TOVF);
- gen_helper_raise_exception(cpu_env, r_const);
- tcg_temp_free_i32(r_const);
- gen_set_label(l1);
- tcg_temp_free(r_temp);
-}
-
static inline void gen_op_subi_cc(TCGv dst, TCGv src1, target_long src2, DisasContext *dc)
{
tcg_gen_mov_tl(cpu_cc_src, src1);
@@ -649,42 +580,23 @@ static void gen_op_subx_int(DisasContext *dc, TCGv dst, TCGv src1,
}
}
-static inline void gen_op_tsub_cc(TCGv dst, TCGv src1, TCGv src2)
-{
- tcg_gen_mov_tl(cpu_cc_src, src1);
- tcg_gen_mov_tl(cpu_cc_src2, src2);
- tcg_gen_sub_tl(cpu_cc_dst, cpu_cc_src, cpu_cc_src2);
- tcg_gen_mov_tl(dst, cpu_cc_dst);
-}
-
-static inline void gen_op_tsub_ccTV(TCGv dst, TCGv src1, TCGv src2)
-{
- tcg_gen_mov_tl(cpu_cc_src, src1);
- tcg_gen_mov_tl(cpu_cc_src2, src2);
- gen_tag_tv(cpu_cc_src, cpu_cc_src2);
- tcg_gen_sub_tl(cpu_cc_dst, cpu_cc_src, cpu_cc_src2);
- gen_sub_tv(cpu_cc_dst, cpu_cc_src, cpu_cc_src2);
- tcg_gen_mov_tl(dst, cpu_cc_dst);
-}
-
static inline void gen_op_mulscc(TCGv dst, TCGv src1, TCGv src2)
{
- TCGv r_temp;
- int l1;
+ TCGv r_temp, zero;
- l1 = gen_new_label();
r_temp = tcg_temp_new();
/* old op:
if (!(env->y & 1))
T1 = 0;
*/
+ zero = tcg_const_tl(0);
tcg_gen_andi_tl(cpu_cc_src, src1, 0xffffffff);
tcg_gen_andi_tl(r_temp, cpu_y, 0x1);
tcg_gen_andi_tl(cpu_cc_src2, src2, 0xffffffff);
- tcg_gen_brcondi_tl(TCG_COND_NE, r_temp, 0, l1);
- tcg_gen_movi_tl(cpu_cc_src2, 0);
- gen_set_label(l1);
+ tcg_gen_movcond_tl(TCG_COND_EQ, cpu_cc_src2, r_temp, zero,
+ zero, cpu_cc_src2);
+ tcg_temp_free(zero);
// b2 = T0 & 1;
// env->y = (b2 << 31) | (env->y >> 1);
@@ -761,44 +673,6 @@ static inline void gen_op_smul(TCGv dst, TCGv src1, TCGv src2)
gen_op_multiply(dst, src1, src2, 1);
}
-#ifdef TARGET_SPARC64
-static inline void gen_trap_ifdivzero_tl(TCGv divisor)
-{
- TCGv_i32 r_const;
- int l1;
-
- l1 = gen_new_label();
- tcg_gen_brcondi_tl(TCG_COND_NE, divisor, 0, l1);
- r_const = tcg_const_i32(TT_DIV_ZERO);
- gen_helper_raise_exception(cpu_env, r_const);
- tcg_temp_free_i32(r_const);
- gen_set_label(l1);
-}
-
-static inline void gen_op_sdivx(TCGv dst, TCGv src1, TCGv src2)
-{
- int l1, l2;
- TCGv r_temp1, r_temp2;
-
- l1 = gen_new_label();
- l2 = gen_new_label();
- r_temp1 = tcg_temp_local_new();
- r_temp2 = tcg_temp_local_new();
- tcg_gen_mov_tl(r_temp1, src1);
- tcg_gen_mov_tl(r_temp2, src2);
- gen_trap_ifdivzero_tl(r_temp2);
- tcg_gen_brcondi_tl(TCG_COND_NE, r_temp1, INT64_MIN, l1);
- tcg_gen_brcondi_tl(TCG_COND_NE, r_temp2, -1, l1);
- tcg_gen_movi_i64(dst, INT64_MIN);
- tcg_gen_br(l2);
- gen_set_label(l1);
- tcg_gen_div_i64(dst, r_temp1, r_temp2);
- gen_set_label(l2);
- tcg_temp_free(r_temp1);
- tcg_temp_free(r_temp2);
-}
-#endif
-
// 1
static inline void gen_op_eval_ba(TCGv dst)
{
@@ -1098,45 +972,40 @@ static inline void gen_branch_a(DisasContext *dc, target_ulong pc1,
gen_goto_tb(dc, 1, pc2 + 4, pc2 + 8);
}
-static inline void gen_generic_branch(target_ulong npc1, target_ulong npc2,
- TCGv r_cond)
+static inline void gen_generic_branch(DisasContext *dc)
{
- int l1, l2;
+ TCGv npc0 = tcg_const_tl(dc->jump_pc[0]);
+ TCGv npc1 = tcg_const_tl(dc->jump_pc[1]);
+ TCGv zero = tcg_const_tl(0);
- l1 = gen_new_label();
- l2 = gen_new_label();
+ tcg_gen_movcond_tl(TCG_COND_NE, cpu_npc, cpu_cond, zero, npc0, npc1);
- tcg_gen_brcondi_tl(TCG_COND_EQ, r_cond, 0, l1);
-
- tcg_gen_movi_tl(cpu_npc, npc1);
- tcg_gen_br(l2);
-
- gen_set_label(l1);
- tcg_gen_movi_tl(cpu_npc, npc2);
- gen_set_label(l2);
+ tcg_temp_free(npc0);
+ tcg_temp_free(npc1);
+ tcg_temp_free(zero);
}
/* call this function before using the condition register as it may
have been set for a jump */
-static inline void flush_cond(DisasContext *dc, TCGv cond)
+static inline void flush_cond(DisasContext *dc)
{
if (dc->npc == JUMP_PC) {
- gen_generic_branch(dc->jump_pc[0], dc->jump_pc[1], cond);
+ gen_generic_branch(dc);
dc->npc = DYNAMIC_PC;
}
}
-static inline void save_npc(DisasContext *dc, TCGv cond)
+static inline void save_npc(DisasContext *dc)
{
if (dc->npc == JUMP_PC) {
- gen_generic_branch(dc->jump_pc[0], dc->jump_pc[1], cond);
+ gen_generic_branch(dc);
dc->npc = DYNAMIC_PC;
} else if (dc->npc != DYNAMIC_PC) {
tcg_gen_movi_tl(cpu_npc, dc->npc);
}
}
-static inline void save_state(DisasContext *dc, TCGv cond)
+static inline void save_state(DisasContext *dc)
{
tcg_gen_movi_tl(cpu_pc, dc->pc);
/* flush pending conditional evaluations before exposing cpu state */
@@ -1144,13 +1013,13 @@ static inline void save_state(DisasContext *dc, TCGv cond)
dc->cc_op = CC_OP_FLAGS;
gen_helper_compute_psr(cpu_env);
}
- save_npc(dc, cond);
+ save_npc(dc);
}
-static inline void gen_mov_pc_npc(DisasContext *dc, TCGv cond)
+static inline void gen_mov_pc_npc(DisasContext *dc)
{
if (dc->npc == JUMP_PC) {
- gen_generic_branch(dc->jump_pc[0], dc->jump_pc[1], cond);
+ gen_generic_branch(dc);
tcg_gen_mov_tl(cpu_pc, cpu_npc);
dc->pc = DYNAMIC_PC;
} else if (dc->npc == DYNAMIC_PC) {
@@ -1167,82 +1036,178 @@ static inline void gen_op_next_insn(void)
tcg_gen_addi_tl(cpu_npc, cpu_npc, 4);
}
-static inline void gen_cond(TCGv r_dst, unsigned int cc, unsigned int cond,
- DisasContext *dc)
+static void free_compare(DisasCompare *cmp)
{
+ if (!cmp->g1) {
+ tcg_temp_free(cmp->c1);
+ }
+ if (!cmp->g2) {
+ tcg_temp_free(cmp->c2);
+ }
+}
+
+static void gen_compare(DisasCompare *cmp, bool xcc, unsigned int cond,
+ DisasContext *dc)
+{
+ static int subcc_cond[16] = {
+ -1, /* never */
+ TCG_COND_EQ,
+ TCG_COND_LE,
+ TCG_COND_LT,
+ TCG_COND_LEU,
+ TCG_COND_LTU,
+ -1, /* neg */
+ -1, /* overflow */
+ -1, /* always */
+ TCG_COND_NE,
+ TCG_COND_GT,
+ TCG_COND_GE,
+ TCG_COND_GTU,
+ TCG_COND_GEU,
+ -1, /* pos */
+ -1, /* no overflow */
+ };
+
TCGv_i32 r_src;
+ TCGv r_dst;
#ifdef TARGET_SPARC64
- if (cc)
+ if (xcc) {
r_src = cpu_xcc;
- else
+ } else {
r_src = cpu_psr;
+ }
#else
r_src = cpu_psr;
#endif
+
switch (dc->cc_op) {
- case CC_OP_FLAGS:
+ case CC_OP_SUB:
+ switch (cond) {
+ case 6: /* neg */
+ case 14: /* pos */
+ cmp->cond = (cond == 6 ? TCG_COND_LT : TCG_COND_GE);
+ cmp->is_bool = false;
+ cmp->g2 = false;
+ cmp->c2 = tcg_const_tl(0);
+#ifdef TARGET_SPARC64
+ if (!xcc) {
+ cmp->g1 = false;
+ cmp->c1 = tcg_temp_new();
+ tcg_gen_ext32s_tl(cmp->c1, cpu_cc_dst);
+ break;
+ }
+#endif
+ cmp->g1 = true;
+ cmp->c1 = cpu_cc_dst;
+ break;
+
+ case 0: /* never */
+ case 8: /* always */
+ case 7: /* overflow */
+ case 15: /* !overflow */
+ goto do_dynamic;
+
+ default:
+ cmp->cond = subcc_cond[cond];
+ cmp->is_bool = false;
+#ifdef TARGET_SPARC64
+ if (!xcc) {
+ /* Note that sign-extension works for unsigned compares as
+ long as both operands are sign-extended. */
+ cmp->g1 = cmp->g2 = false;
+ cmp->c1 = tcg_temp_new();
+ cmp->c2 = tcg_temp_new();
+ tcg_gen_ext32s_tl(cmp->c1, cpu_cc_src);
+ tcg_gen_ext32s_tl(cmp->c2, cpu_cc_src2);
+ }
+#endif
+ cmp->g1 = cmp->g2 = true;
+ cmp->c1 = cpu_cc_src;
+ cmp->c2 = cpu_cc_src2;
+ break;
+ }
break;
+
default:
+ do_dynamic:
gen_helper_compute_psr(cpu_env);
dc->cc_op = CC_OP_FLAGS;
- break;
- }
- switch (cond) {
- case 0x0:
- gen_op_eval_bn(r_dst);
- break;
- case 0x1:
- gen_op_eval_be(r_dst, r_src);
- break;
- case 0x2:
- gen_op_eval_ble(r_dst, r_src);
- break;
- case 0x3:
- gen_op_eval_bl(r_dst, r_src);
- break;
- case 0x4:
- gen_op_eval_bleu(r_dst, r_src);
- break;
- case 0x5:
- gen_op_eval_bcs(r_dst, r_src);
- break;
- case 0x6:
- gen_op_eval_bneg(r_dst, r_src);
- break;
- case 0x7:
- gen_op_eval_bvs(r_dst, r_src);
- break;
- case 0x8:
- gen_op_eval_ba(r_dst);
- break;
- case 0x9:
- gen_op_eval_bne(r_dst, r_src);
- break;
- case 0xa:
- gen_op_eval_bg(r_dst, r_src);
- break;
- case 0xb:
- gen_op_eval_bge(r_dst, r_src);
- break;
- case 0xc:
- gen_op_eval_bgu(r_dst, r_src);
- break;
- case 0xd:
- gen_op_eval_bcc(r_dst, r_src);
- break;
- case 0xe:
- gen_op_eval_bpos(r_dst, r_src);
- break;
- case 0xf:
- gen_op_eval_bvc(r_dst, r_src);
+ /* FALLTHRU */
+
+ case CC_OP_FLAGS:
+ /* We're going to generate a boolean result. */
+ cmp->cond = TCG_COND_NE;
+ cmp->is_bool = true;
+ cmp->g1 = cmp->g2 = false;
+ cmp->c1 = r_dst = tcg_temp_new();
+ cmp->c2 = tcg_const_tl(0);
+
+ switch (cond) {
+ case 0x0:
+ gen_op_eval_bn(r_dst);
+ break;
+ case 0x1:
+ gen_op_eval_be(r_dst, r_src);
+ break;
+ case 0x2:
+ gen_op_eval_ble(r_dst, r_src);
+ break;
+ case 0x3:
+ gen_op_eval_bl(r_dst, r_src);
+ break;
+ case 0x4:
+ gen_op_eval_bleu(r_dst, r_src);
+ break;
+ case 0x5:
+ gen_op_eval_bcs(r_dst, r_src);
+ break;
+ case 0x6:
+ gen_op_eval_bneg(r_dst, r_src);
+ break;
+ case 0x7:
+ gen_op_eval_bvs(r_dst, r_src);
+ break;
+ case 0x8:
+ gen_op_eval_ba(r_dst);
+ break;
+ case 0x9:
+ gen_op_eval_bne(r_dst, r_src);
+ break;
+ case 0xa:
+ gen_op_eval_bg(r_dst, r_src);
+ break;
+ case 0xb:
+ gen_op_eval_bge(r_dst, r_src);
+ break;
+ case 0xc:
+ gen_op_eval_bgu(r_dst, r_src);
+ break;
+ case 0xd:
+ gen_op_eval_bcc(r_dst, r_src);
+ break;
+ case 0xe:
+ gen_op_eval_bpos(r_dst, r_src);
+ break;
+ case 0xf:
+ gen_op_eval_bvc(r_dst, r_src);
+ break;
+ }
break;
}
}
-static inline void gen_fcond(TCGv r_dst, unsigned int cc, unsigned int cond)
+static void gen_fcompare(DisasCompare *cmp, unsigned int cc, unsigned int cond)
{
unsigned int offset;
+ TCGv r_dst;
+
+ /* For now we still generate a straight boolean result. */
+ cmp->cond = TCG_COND_NE;
+ cmp->is_bool = true;
+ cmp->g1 = cmp->g2 = false;
+ cmp->c1 = r_dst = tcg_temp_new();
+ cmp->c2 = tcg_const_tl(0);
switch (cc) {
default:
@@ -1312,6 +1277,37 @@ static inline void gen_fcond(TCGv r_dst, unsigned int cc, unsigned int cond)
}
}
+static void gen_cond(TCGv r_dst, unsigned int cc, unsigned int cond,
+ DisasContext *dc)
+{
+ DisasCompare cmp;
+ gen_compare(&cmp, cc, cond, dc);
+
+ /* The interface is to return a boolean in r_dst. */
+ if (cmp.is_bool) {
+ tcg_gen_mov_tl(r_dst, cmp.c1);
+ } else {
+ tcg_gen_setcond_tl(cmp.cond, r_dst, cmp.c1, cmp.c2);
+ }
+
+ free_compare(&cmp);
+}
+
+static void gen_fcond(TCGv r_dst, unsigned int cc, unsigned int cond)
+{
+ DisasCompare cmp;
+ gen_fcompare(&cmp, cc, cond);
+
+ /* The interface is to return a boolean in r_dst. */
+ if (cmp.is_bool) {
+ tcg_gen_mov_tl(r_dst, cmp.c1);
+ } else {
+ tcg_gen_setcond_tl(cmp.cond, r_dst, cmp.c1, cmp.c2);
+ }
+
+ free_compare(&cmp);
+}
+
#ifdef TARGET_SPARC64
// Inverted logic
static const int gen_tcg_cond_reg[8] = {
@@ -1325,20 +1321,29 @@ static const int gen_tcg_cond_reg[8] = {
TCG_COND_LT,
};
+static void gen_compare_reg(DisasCompare *cmp, int cond, TCGv r_src)
+{
+ cmp->cond = tcg_invert_cond(gen_tcg_cond_reg[cond]);
+ cmp->is_bool = false;
+ cmp->g1 = true;
+ cmp->g2 = false;
+ cmp->c1 = r_src;
+ cmp->c2 = tcg_const_tl(0);
+}
+
static inline void gen_cond_reg(TCGv r_dst, int cond, TCGv r_src)
{
- int l1;
+ DisasCompare cmp;
+ gen_compare_reg(&cmp, cond, r_src);
- l1 = gen_new_label();
- tcg_gen_movi_tl(r_dst, 0);
- tcg_gen_brcondi_tl(gen_tcg_cond_reg[cond], r_src, 0, l1);
- tcg_gen_movi_tl(r_dst, 1);
- gen_set_label(l1);
+ /* The interface is to return a boolean in r_dst. */
+ tcg_gen_setcond_tl(cmp.cond, r_dst, cmp.c1, cmp.c2);
+
+ free_compare(&cmp);
}
#endif
-static void do_branch(DisasContext *dc, int32_t offset, uint32_t insn, int cc,
- TCGv r_cond)
+static void do_branch(DisasContext *dc, int32_t offset, uint32_t insn, int cc)
{
unsigned int cond = GET_FIELD(insn, 3, 6), a = (insn & (1 << 29));
target_ulong target = dc->pc + offset;
@@ -1368,10 +1373,10 @@ static void do_branch(DisasContext *dc, int32_t offset, uint32_t insn, int cc,
tcg_gen_mov_tl(cpu_pc, cpu_npc);
}
} else {
- flush_cond(dc, r_cond);
- gen_cond(r_cond, cc, cond, dc);
+ flush_cond(dc);
+ gen_cond(cpu_cond, cc, cond, dc);
if (a) {
- gen_branch_a(dc, target, dc->npc, r_cond);
+ gen_branch_a(dc, target, dc->npc, cpu_cond);
dc->is_br = 1;
} else {
dc->pc = dc->npc;
@@ -1387,8 +1392,7 @@ static void do_branch(DisasContext *dc, int32_t offset, uint32_t insn, int cc,
}
}
-static void do_fbranch(DisasContext *dc, int32_t offset, uint32_t insn, int cc,
- TCGv r_cond)
+static void do_fbranch(DisasContext *dc, int32_t offset, uint32_t insn, int cc)
{
unsigned int cond = GET_FIELD(insn, 3, 6), a = (insn & (1 << 29));
target_ulong target = dc->pc + offset;
@@ -1418,10 +1422,10 @@ static void do_fbranch(DisasContext *dc, int32_t offset, uint32_t insn, int cc,
tcg_gen_mov_tl(cpu_pc, cpu_npc);
}
} else {
- flush_cond(dc, r_cond);
- gen_fcond(r_cond, cc, cond);
+ flush_cond(dc);
+ gen_fcond(cpu_cond, cc, cond);
if (a) {
- gen_branch_a(dc, target, dc->npc, r_cond);
+ gen_branch_a(dc, target, dc->npc, cpu_cond);
dc->is_br = 1;
} else {
dc->pc = dc->npc;
@@ -1439,7 +1443,7 @@ static void do_fbranch(DisasContext *dc, int32_t offset, uint32_t insn, int cc,
#ifdef TARGET_SPARC64
static void do_branch_reg(DisasContext *dc, int32_t offset, uint32_t insn,
- TCGv r_cond, TCGv r_reg)
+ TCGv r_reg)
{
unsigned int cond = GET_FIELD_SP(insn, 25, 27), a = (insn & (1 << 29));
target_ulong target = dc->pc + offset;
@@ -1447,10 +1451,10 @@ static void do_branch_reg(DisasContext *dc, int32_t offset, uint32_t insn,
if (unlikely(AM_CHECK(dc))) {
target &= 0xffffffffULL;
}
- flush_cond(dc, r_cond);
- gen_cond_reg(r_cond, cond, r_reg);
+ flush_cond(dc);
+ gen_cond_reg(cpu_cond, cond, r_reg);
if (a) {
- gen_branch_a(dc, target, dc->npc, r_cond);
+ gen_branch_a(dc, target, dc->npc, cpu_cond);
dc->is_br = 1;
} else {
dc->pc = dc->npc;
@@ -1617,13 +1621,13 @@ static inline void gen_op_fpexception_im(int fsr_flags)
tcg_temp_free_i32(r_const);
}
-static int gen_trap_ifnofpu(DisasContext *dc, TCGv r_cond)
+static int gen_trap_ifnofpu(DisasContext *dc)
{
#if !defined(CONFIG_USER_ONLY)
if (!dc->fpu_enabled) {
TCGv_i32 r_const;
- save_state(dc, r_cond);
+ save_state(dc);
r_const = tcg_const_i32(TT_NFPU_INSN);
gen_helper_raise_exception(cpu_env, r_const);
tcg_temp_free_i32(r_const);
@@ -2210,6 +2214,57 @@ static inline TCGv get_src2(unsigned int insn, TCGv def)
}
#ifdef TARGET_SPARC64
+static void gen_fmovs(DisasContext *dc, DisasCompare *cmp, int rd, int rs)
+{
+ TCGv_i32 c32, zero, dst, s1, s2;
+
+ /* We have two choices here: extend the 32 bit data and use movcond_i64,
+ or fold the comparison down to 32 bits and use movcond_i32. Choose
+ the later. */
+ c32 = tcg_temp_new_i32();
+ if (cmp->is_bool) {
+ tcg_gen_trunc_i64_i32(c32, cmp->c1);
+ } else {
+ TCGv_i64 c64 = tcg_temp_new_i64();
+ tcg_gen_setcond_i64(cmp->cond, c64, cmp->c1, cmp->c2);
+ tcg_gen_trunc_i64_i32(c32, c64);
+ tcg_temp_free_i64(c64);
+ }
+
+ s1 = gen_load_fpr_F(dc, rs);
+ s2 = gen_load_fpr_F(dc, rd);
+ dst = gen_dest_fpr_F();
+ zero = tcg_const_i32(0);
+
+ tcg_gen_movcond_i32(TCG_COND_NE, dst, c32, zero, s1, s2);
+
+ tcg_temp_free_i32(c32);
+ tcg_temp_free_i32(zero);
+ gen_store_fpr_F(dc, rd, dst);
+}
+
+static void gen_fmovd(DisasContext *dc, DisasCompare *cmp, int rd, int rs)
+{
+ TCGv_i64 dst = gen_dest_fpr_D();
+ tcg_gen_movcond_i64(cmp->cond, dst, cmp->c1, cmp->c2,
+ gen_load_fpr_D(dc, rs),
+ gen_load_fpr_D(dc, rd));
+ gen_store_fpr_D(dc, rd, dst);
+}
+
+static void gen_fmovq(DisasContext *dc, DisasCompare *cmp, int rd, int rs)
+{
+ int qd = QFPREG(rd);
+ int qs = QFPREG(rs);
+
+ tcg_gen_movcond_i64(cmp->cond, cpu_fpr[qd / 2], cmp->c1, cmp->c2,
+ cpu_fpr[qs / 2], cpu_fpr[qd / 2]);
+ tcg_gen_movcond_i64(cmp->cond, cpu_fpr[qd / 2 + 1], cmp->c1, cmp->c2,
+ cpu_fpr[qs / 2 + 1], cpu_fpr[qd / 2 + 1]);
+
+ gen_update_fprs_dirty(qd);
+}
+
static inline void gen_load_trap_state_at_tl(TCGv_ptr r_tsptr, TCGv_ptr cpu_env)
{
TCGv_i32 r_tl = tcg_temp_new_i32();
@@ -2421,9 +2476,9 @@ static void disas_sparc_insn(DisasContext * dc, unsigned int insn)
target <<= 2;
cc = GET_FIELD_SP(insn, 20, 21);
if (cc == 0)
- do_branch(dc, target, insn, 0, cpu_cond);
+ do_branch(dc, target, insn, 0);
else if (cc == 2)
- do_branch(dc, target, insn, 1, cpu_cond);
+ do_branch(dc, target, insn, 1);
else
goto illegal_insn;
goto jmp_insn;
@@ -2435,18 +2490,19 @@ static void disas_sparc_insn(DisasContext * dc, unsigned int insn)
target = sign_extend(target, 16);
target <<= 2;
cpu_src1 = get_src1(insn, cpu_src1);
- do_branch_reg(dc, target, insn, cpu_cond, cpu_src1);
+ do_branch_reg(dc, target, insn, cpu_src1);
goto jmp_insn;
}
case 0x5: /* V9 FBPcc */
{
int cc = GET_FIELD_SP(insn, 20, 21);
- if (gen_trap_ifnofpu(dc, cpu_cond))
+ if (gen_trap_ifnofpu(dc)) {
goto jmp_insn;
+ }
target = GET_FIELD_SP(insn, 0, 18);
target = sign_extend(target, 19);
target <<= 2;
- do_fbranch(dc, target, insn, cc, cpu_cond);
+ do_fbranch(dc, target, insn, cc);
goto jmp_insn;
}
#else
@@ -2460,17 +2516,18 @@ static void disas_sparc_insn(DisasContext * dc, unsigned int insn)
target = GET_FIELD(insn, 10, 31);
target = sign_extend(target, 22);
target <<= 2;
- do_branch(dc, target, insn, 0, cpu_cond);
+ do_branch(dc, target, insn, 0);
goto jmp_insn;
}
case 0x6: /* FBN+x */
{
- if (gen_trap_ifnofpu(dc, cpu_cond))
+ if (gen_trap_ifnofpu(dc)) {
goto jmp_insn;
+ }
target = GET_FIELD(insn, 10, 31);
target = sign_extend(target, 22);
target <<= 2;
- do_fbranch(dc, target, insn, 0, cpu_cond);
+ do_fbranch(dc, target, insn, 0);
goto jmp_insn;
}
case 0x4: /* SETHI */
@@ -2499,7 +2556,7 @@ static void disas_sparc_insn(DisasContext * dc, unsigned int insn)
gen_movl_TN_reg(15, r_const);
tcg_temp_free(r_const);
target += dc->pc;
- gen_mov_pc_npc(dc, cpu_cond);
+ gen_mov_pc_npc(dc);
#ifdef TARGET_SPARC64
if (unlikely(AM_CHECK(dc))) {
target &= 0xffffffffULL;
@@ -2512,70 +2569,89 @@ static void disas_sparc_insn(DisasContext * dc, unsigned int insn)
{
unsigned int xop = GET_FIELD(insn, 7, 12);
if (xop == 0x3a) { /* generate trap */
- int cond;
+ int cond = GET_FIELD(insn, 3, 6);
+ TCGv_i32 trap;
+ int l1 = -1, mask;
- cpu_src1 = get_src1(insn, cpu_src1);
- if (IS_IMM) {
- rs2 = GET_FIELD(insn, 25, 31);
- tcg_gen_addi_tl(cpu_dst, cpu_src1, rs2);
- } else {
- rs2 = GET_FIELD(insn, 27, 31);
- if (rs2 != 0) {
- gen_movl_reg_TN(rs2, cpu_src2);
- tcg_gen_add_tl(cpu_dst, cpu_src1, cpu_src2);
- } else
- tcg_gen_mov_tl(cpu_dst, cpu_src1);
+ if (cond == 0) {
+ /* Trap never. */
+ break;
}
- cond = GET_FIELD(insn, 3, 6);
- if (cond == 0x8) { /* Trap Always */
- save_state(dc, cpu_cond);
- if ((dc->def->features & CPU_FEATURE_HYPV) &&
- supervisor(dc))
- tcg_gen_andi_tl(cpu_dst, cpu_dst, UA2005_HTRAP_MASK);
- else
- tcg_gen_andi_tl(cpu_dst, cpu_dst, V8_TRAP_MASK);
- tcg_gen_addi_tl(cpu_dst, cpu_dst, TT_TRAP);
- tcg_gen_trunc_tl_i32(cpu_tmp32, cpu_dst);
- gen_helper_raise_exception(cpu_env, cpu_tmp32);
-
- } else if (cond != 0) {
- TCGv r_cond = tcg_temp_new();
- int l1;
+ save_state(dc);
+
+ if (cond != 8) {
+ /* Conditional trap. */
+ DisasCompare cmp;
#ifdef TARGET_SPARC64
/* V9 icc/xcc */
int cc = GET_FIELD_SP(insn, 11, 12);
-
- save_state(dc, cpu_cond);
- if (cc == 0)
- gen_cond(r_cond, 0, cond, dc);
- else if (cc == 2)
- gen_cond(r_cond, 1, cond, dc);
- else
+ if (cc == 0) {
+ gen_compare(&cmp, 0, cond, dc);
+ } else if (cc == 2) {
+ gen_compare(&cmp, 1, cond, dc);
+ } else {
goto illegal_insn;
+ }
#else
- save_state(dc, cpu_cond);
- gen_cond(r_cond, 0, cond, dc);
+ gen_compare(&cmp, 0, cond, dc);
#endif
l1 = gen_new_label();
- tcg_gen_brcondi_tl(TCG_COND_EQ, r_cond, 0, l1);
+ tcg_gen_brcond_tl(tcg_invert_cond(cmp.cond),
+ cmp.c1, cmp.c2, l1);
+ free_compare(&cmp);
+ }
- if ((dc->def->features & CPU_FEATURE_HYPV) &&
- supervisor(dc))
- tcg_gen_andi_tl(cpu_dst, cpu_dst, UA2005_HTRAP_MASK);
- else
- tcg_gen_andi_tl(cpu_dst, cpu_dst, V8_TRAP_MASK);
- tcg_gen_addi_tl(cpu_dst, cpu_dst, TT_TRAP);
- tcg_gen_trunc_tl_i32(cpu_tmp32, cpu_dst);
- gen_helper_raise_exception(cpu_env, cpu_tmp32);
+ mask = ((dc->def->features & CPU_FEATURE_HYPV) && supervisor(dc)
+ ? UA2005_HTRAP_MASK : V8_TRAP_MASK);
+
+ /* Don't use the normal temporaries, as they may well have
+ gone out of scope with the branch above. While we're
+ doing that we might as well pre-truncate to 32-bit. */
+ trap = tcg_temp_new_i32();
+ rs1 = GET_FIELD_SP(insn, 14, 18);
+ if (IS_IMM) {
+ rs2 = GET_FIELD_SP(insn, 0, 6);
+ if (rs1 == 0) {
+ tcg_gen_movi_i32(trap, (rs2 & mask) + TT_TRAP);
+ /* Signal that the trap value is fully constant. */
+ mask = 0;
+ } else {
+ TCGv t1 = tcg_temp_new();
+ gen_movl_reg_TN(rs1, t1);
+ tcg_gen_trunc_tl_i32(trap, t1);
+ tcg_temp_free(t1);
+ tcg_gen_addi_i32(trap, trap, rs2);
+ }
+ } else {
+ TCGv t1 = tcg_temp_new();
+ TCGv t2 = tcg_temp_new();
+ rs2 = GET_FIELD_SP(insn, 0, 4);
+ gen_movl_reg_TN(rs1, t1);
+ gen_movl_reg_TN(rs2, t2);
+ tcg_gen_add_tl(t1, t1, t2);
+ tcg_gen_trunc_tl_i32(trap, t1);
+ tcg_temp_free(t1);
+ tcg_temp_free(t2);
+ }
+ if (mask != 0) {
+ tcg_gen_andi_i32(trap, trap, mask);
+ tcg_gen_addi_i32(trap, trap, TT_TRAP);
+ }
+
+ gen_helper_raise_exception(cpu_env, trap);
+ tcg_temp_free_i32(trap);
+
+ if (cond == 8) {
+ /* An unconditional trap ends the TB. */
+ dc->is_br = 1;
+ goto jmp_insn;
+ } else {
+ /* A conditional trap falls through to the next insn. */
gen_set_label(l1);
- tcg_temp_free(r_cond);
+ break;
}
- gen_op_next_insn();
- tcg_gen_exit_tb(0);
- dc->is_br = 1;
- goto jmp_insn;
} else if (xop == 0x28) {
rs1 = GET_FIELD(insn, 13, 17);
switch(rs1) {
@@ -2645,8 +2721,9 @@ static void disas_sparc_insn(DisasContext * dc, unsigned int insn)
case 0xf: /* V9 membar */
break; /* no effect */
case 0x13: /* Graphics Status */
- if (gen_trap_ifnofpu(dc, cpu_cond))
+ if (gen_trap_ifnofpu(dc)) {
goto jmp_insn;
+ }
gen_movl_TN_reg(rd, cpu_gsr);
break;
case 0x16: /* Softint */
@@ -2853,7 +2930,7 @@ static void disas_sparc_insn(DisasContext * dc, unsigned int insn)
break;
} else if (xop == 0x2b) { /* rdtbr / V9 flushw */
#ifdef TARGET_SPARC64
- save_state(dc, cpu_cond);
+ save_state(dc);
gen_helper_flushw(cpu_env);
#else
if (!supervisor(dc))
@@ -2863,13 +2940,14 @@ static void disas_sparc_insn(DisasContext * dc, unsigned int insn)
break;
#endif
} else if (xop == 0x34) { /* FPU Operations */
- if (gen_trap_ifnofpu(dc, cpu_cond))
+ if (gen_trap_ifnofpu(dc)) {
goto jmp_insn;
+ }
gen_op_clear_ieee_excp_and_FTT();
rs1 = GET_FIELD(insn, 13, 17);
rs2 = GET_FIELD(insn, 27, 31);
xop = GET_FIELD(insn, 18, 26);
- save_state(dc, cpu_cond);
+ save_state(dc);
switch (xop) {
case 0x1: /* fmovs */
cpu_src1_32 = gen_load_fpr_F(dc, rs2);
@@ -3037,216 +3115,121 @@ static void disas_sparc_insn(DisasContext * dc, unsigned int insn)
#ifdef TARGET_SPARC64
int cond;
#endif
- if (gen_trap_ifnofpu(dc, cpu_cond))
+ if (gen_trap_ifnofpu(dc)) {
goto jmp_insn;
+ }
gen_op_clear_ieee_excp_and_FTT();
rs1 = GET_FIELD(insn, 13, 17);
rs2 = GET_FIELD(insn, 27, 31);
xop = GET_FIELD(insn, 18, 26);
- save_state(dc, cpu_cond);
-#ifdef TARGET_SPARC64
- if ((xop & 0x11f) == 0x005) { // V9 fmovsr
- int l1;
+ save_state(dc);
- l1 = gen_new_label();
- cond = GET_FIELD_SP(insn, 14, 17);
- cpu_src1 = get_src1(insn, cpu_src1);
- tcg_gen_brcondi_tl(gen_tcg_cond_reg[cond], cpu_src1,
- 0, l1);
- cpu_src1_32 = gen_load_fpr_F(dc, rs2);
- gen_store_fpr_F(dc, rd, cpu_src1_32);
- gen_set_label(l1);
+#ifdef TARGET_SPARC64
+#define FMOVR(sz) \
+ do { \
+ DisasCompare cmp; \
+ cond = GET_FIELD_SP(insn, 14, 17); \
+ cpu_src1 = get_src1(insn, cpu_src1); \
+ gen_compare_reg(&cmp, cond, cpu_src1); \
+ gen_fmov##sz(dc, &cmp, rd, rs2); \
+ free_compare(&cmp); \
+ } while (0)
+
+ if ((xop & 0x11f) == 0x005) { /* V9 fmovsr */
+ FMOVR(s);
break;
} else if ((xop & 0x11f) == 0x006) { // V9 fmovdr
- int l1;
-
- l1 = gen_new_label();
- cond = GET_FIELD_SP(insn, 14, 17);
- cpu_src1 = get_src1(insn, cpu_src1);
- tcg_gen_brcondi_tl(gen_tcg_cond_reg[cond], cpu_src1,
- 0, l1);
- cpu_src1_64 = gen_load_fpr_D(dc, rs2);
- gen_store_fpr_D(dc, rd, cpu_src1_64);
- gen_set_label(l1);
+ FMOVR(d);
break;
} else if ((xop & 0x11f) == 0x007) { // V9 fmovqr
- int l1;
-
CHECK_FPU_FEATURE(dc, FLOAT128);
- l1 = gen_new_label();
- cond = GET_FIELD_SP(insn, 14, 17);
- cpu_src1 = get_src1(insn, cpu_src1);
- tcg_gen_brcondi_tl(gen_tcg_cond_reg[cond], cpu_src1,
- 0, l1);
- gen_move_Q(rd, rs2);
- gen_set_label(l1);
+ FMOVR(q);
break;
}
+#undef FMOVR
#endif
switch (xop) {
#ifdef TARGET_SPARC64
-#define FMOVSCC(fcc) \
- { \
- TCGv r_cond; \
- int l1; \
- \
- l1 = gen_new_label(); \
- r_cond = tcg_temp_new(); \
- cond = GET_FIELD_SP(insn, 14, 17); \
- gen_fcond(r_cond, fcc, cond); \
- tcg_gen_brcondi_tl(TCG_COND_EQ, r_cond, \
- 0, l1); \
- cpu_src1_32 = gen_load_fpr_F(dc, rs2); \
- gen_store_fpr_F(dc, rd, cpu_src1_32); \
- gen_set_label(l1); \
- tcg_temp_free(r_cond); \
- }
-#define FMOVDCC(fcc) \
- { \
- TCGv r_cond; \
- int l1; \
- \
- l1 = gen_new_label(); \
- r_cond = tcg_temp_new(); \
- cond = GET_FIELD_SP(insn, 14, 17); \
- gen_fcond(r_cond, fcc, cond); \
- tcg_gen_brcondi_tl(TCG_COND_EQ, r_cond, \
- 0, l1); \
- cpu_src1_64 = gen_load_fpr_D(dc, rs2); \
- gen_store_fpr_D(dc, rd, cpu_src1_64); \
- gen_set_label(l1); \
- tcg_temp_free(r_cond); \
- }
-#define FMOVQCC(fcc) \
- { \
- TCGv r_cond; \
- int l1; \
- \
- l1 = gen_new_label(); \
- r_cond = tcg_temp_new(); \
+#define FMOVCC(fcc, sz) \
+ do { \
+ DisasCompare cmp; \
cond = GET_FIELD_SP(insn, 14, 17); \
- gen_fcond(r_cond, fcc, cond); \
- tcg_gen_brcondi_tl(TCG_COND_EQ, r_cond, \
- 0, l1); \
- gen_move_Q(rd, rs2); \
- gen_set_label(l1); \
- tcg_temp_free(r_cond); \
- }
+ gen_fcompare(&cmp, fcc, cond); \
+ gen_fmov##sz(dc, &cmp, rd, rs2); \
+ free_compare(&cmp); \
+ } while (0)
+
case 0x001: /* V9 fmovscc %fcc0 */
- FMOVSCC(0);
+ FMOVCC(0, s);
break;
case 0x002: /* V9 fmovdcc %fcc0 */
- FMOVDCC(0);
+ FMOVCC(0, d);
break;
case 0x003: /* V9 fmovqcc %fcc0 */
CHECK_FPU_FEATURE(dc, FLOAT128);
- FMOVQCC(0);
+ FMOVCC(0, q);
break;
case 0x041: /* V9 fmovscc %fcc1 */
- FMOVSCC(1);
+ FMOVCC(1, s);
break;
case 0x042: /* V9 fmovdcc %fcc1 */
- FMOVDCC(1);
+ FMOVCC(1, d);
break;
case 0x043: /* V9 fmovqcc %fcc1 */
CHECK_FPU_FEATURE(dc, FLOAT128);
- FMOVQCC(1);
+ FMOVCC(1, q);
break;
case 0x081: /* V9 fmovscc %fcc2 */
- FMOVSCC(2);
+ FMOVCC(2, s);
break;
case 0x082: /* V9 fmovdcc %fcc2 */
- FMOVDCC(2);
+ FMOVCC(2, d);
break;
case 0x083: /* V9 fmovqcc %fcc2 */
CHECK_FPU_FEATURE(dc, FLOAT128);
- FMOVQCC(2);
+ FMOVCC(2, q);
break;
case 0x0c1: /* V9 fmovscc %fcc3 */
- FMOVSCC(3);
+ FMOVCC(3, s);
break;
case 0x0c2: /* V9 fmovdcc %fcc3 */
- FMOVDCC(3);
+ FMOVCC(3, d);
break;
case 0x0c3: /* V9 fmovqcc %fcc3 */
CHECK_FPU_FEATURE(dc, FLOAT128);
- FMOVQCC(3);
+ FMOVCC(3, q);
break;
-#undef FMOVSCC
-#undef FMOVDCC
-#undef FMOVQCC
-#define FMOVSCC(icc) \
- { \
- TCGv r_cond; \
- int l1; \
- \
- l1 = gen_new_label(); \
- r_cond = tcg_temp_new(); \
+#undef FMOVCC
+#define FMOVCC(xcc, sz) \
+ do { \
+ DisasCompare cmp; \
cond = GET_FIELD_SP(insn, 14, 17); \
- gen_cond(r_cond, icc, cond, dc); \
- tcg_gen_brcondi_tl(TCG_COND_EQ, r_cond, \
- 0, l1); \
- cpu_src1_32 = gen_load_fpr_F(dc, rs2); \
- gen_store_fpr_F(dc, rd, cpu_src1_32); \
- gen_set_label(l1); \
- tcg_temp_free(r_cond); \
- }
-#define FMOVDCC(icc) \
- { \
- TCGv r_cond; \
- int l1; \
- \
- l1 = gen_new_label(); \
- r_cond = tcg_temp_new(); \
- cond = GET_FIELD_SP(insn, 14, 17); \
- gen_cond(r_cond, icc, cond, dc); \
- tcg_gen_brcondi_tl(TCG_COND_EQ, r_cond, \
- 0, l1); \
- cpu_src1_64 = gen_load_fpr_D(dc, rs2); \
- gen_store_fpr_D(dc, rd, cpu_src1_64); \
- gen_update_fprs_dirty(DFPREG(rd)); \
- gen_set_label(l1); \
- tcg_temp_free(r_cond); \
- }
-#define FMOVQCC(icc) \
- { \
- TCGv r_cond; \
- int l1; \
- \
- l1 = gen_new_label(); \
- r_cond = tcg_temp_new(); \
- cond = GET_FIELD_SP(insn, 14, 17); \
- gen_cond(r_cond, icc, cond, dc); \
- tcg_gen_brcondi_tl(TCG_COND_EQ, r_cond, \
- 0, l1); \
- gen_move_Q(rd, rs2); \
- gen_set_label(l1); \
- tcg_temp_free(r_cond); \
- }
+ gen_compare(&cmp, xcc, cond, dc); \
+ gen_fmov##sz(dc, &cmp, rd, rs2); \
+ free_compare(&cmp); \
+ } while (0)
case 0x101: /* V9 fmovscc %icc */
- FMOVSCC(0);
+ FMOVCC(0, s);
break;
case 0x102: /* V9 fmovdcc %icc */
- FMOVDCC(0);
+ FMOVCC(0, d);
break;
case 0x103: /* V9 fmovqcc %icc */
CHECK_FPU_FEATURE(dc, FLOAT128);
- FMOVQCC(0);
+ FMOVCC(0, q);
break;
case 0x181: /* V9 fmovscc %xcc */
- FMOVSCC(1);
+ FMOVCC(1, s);
break;
case 0x182: /* V9 fmovdcc %xcc */
- FMOVDCC(1);
+ FMOVCC(1, d);
break;
case 0x183: /* V9 fmovqcc %xcc */
CHECK_FPU_FEATURE(dc, FLOAT128);
- FMOVQCC(1);
+ FMOVCC(1, q);
break;
-#undef FMOVSCC
-#undef FMOVDCC
-#undef FMOVQCC
+#undef FMOVCC
#endif
case 0x51: /* fcmps, V9 %fcc */
cpu_src1_32 = gen_load_fpr_F(dc, rs1);
@@ -3548,17 +3531,7 @@ static void disas_sparc_insn(DisasContext * dc, unsigned int insn)
break;
#ifdef TARGET_SPARC64
case 0xd: /* V9 udivx */
- {
- TCGv r_temp1, r_temp2;
- r_temp1 = tcg_temp_local_new();
- r_temp2 = tcg_temp_local_new();
- tcg_gen_mov_tl(r_temp1, cpu_src1);
- tcg_gen_mov_tl(r_temp2, cpu_src2);
- gen_trap_ifdivzero_tl(r_temp2);
- tcg_gen_divu_i64(cpu_dst, r_temp1, r_temp2);
- tcg_temp_free(r_temp1);
- tcg_temp_free(r_temp2);
- }
+ gen_helper_udivx(cpu_dst, cpu_env, cpu_src1, cpu_src2);
break;
#endif
case 0xe: /* udiv */
@@ -3592,29 +3565,27 @@ static void disas_sparc_insn(DisasContext * dc, unsigned int insn)
cpu_src2 = get_src2(insn, cpu_src2);
switch (xop) {
case 0x20: /* taddcc */
- gen_op_tadd_cc(cpu_dst, cpu_src1, cpu_src2);
+ gen_op_add_cc(cpu_dst, cpu_src1, cpu_src2);
gen_movl_TN_reg(rd, cpu_dst);
tcg_gen_movi_i32(cpu_cc_op, CC_OP_TADD);
dc->cc_op = CC_OP_TADD;
break;
case 0x21: /* tsubcc */
- gen_op_tsub_cc(cpu_dst, cpu_src1, cpu_src2);
+ gen_op_sub_cc(cpu_dst, cpu_src1, cpu_src2);
gen_movl_TN_reg(rd, cpu_dst);
tcg_gen_movi_i32(cpu_cc_op, CC_OP_TSUB);
dc->cc_op = CC_OP_TSUB;
break;
case 0x22: /* taddcctv */
- save_state(dc, cpu_cond);
- gen_op_tadd_ccTV(cpu_dst, cpu_src1, cpu_src2);
+ gen_helper_taddcctv(cpu_dst, cpu_env,
+ cpu_src1, cpu_src2);
gen_movl_TN_reg(rd, cpu_dst);
- tcg_gen_movi_i32(cpu_cc_op, CC_OP_TADDTV);
dc->cc_op = CC_OP_TADDTV;
break;
case 0x23: /* tsubcctv */
- save_state(dc, cpu_cond);
- gen_op_tsub_ccTV(cpu_dst, cpu_src1, cpu_src2);
+ gen_helper_tsubcctv(cpu_dst, cpu_env,
+ cpu_src1, cpu_src2);
gen_movl_TN_reg(rd, cpu_dst);
- tcg_gen_movi_i32(cpu_cc_op, CC_OP_TSUBTV);
dc->cc_op = CC_OP_TSUBTV;
break;
case 0x24: /* mulscc */
@@ -3688,7 +3659,7 @@ static void disas_sparc_insn(DisasContext * dc, unsigned int insn)
case 0x6: /* V9 wrfprs */
tcg_gen_xor_tl(cpu_dst, cpu_src1, cpu_src2);
tcg_gen_trunc_tl_i32(cpu_fprs, cpu_dst);
- save_state(dc, cpu_cond);
+ save_state(dc);
gen_op_next_insn();
tcg_gen_exit_tb(0);
dc->is_br = 1;
@@ -3701,8 +3672,9 @@ static void disas_sparc_insn(DisasContext * dc, unsigned int insn)
#endif
break;
case 0x13: /* Graphics Status */
- if (gen_trap_ifnofpu(dc, cpu_cond))
+ if (gen_trap_ifnofpu(dc)) {
goto jmp_insn;
+ }
tcg_gen_xor_tl(cpu_gsr, cpu_src1, cpu_src2);
break;
case 0x14: /* Softint set */
@@ -3814,7 +3786,7 @@ static void disas_sparc_insn(DisasContext * dc, unsigned int insn)
gen_helper_wrpsr(cpu_env, cpu_dst);
tcg_gen_movi_i32(cpu_cc_op, CC_OP_FLAGS);
dc->cc_op = CC_OP_FLAGS;
- save_state(dc, cpu_cond);
+ save_state(dc);
gen_op_next_insn();
tcg_gen_exit_tb(0);
dc->is_br = 1;
@@ -3894,7 +3866,7 @@ static void disas_sparc_insn(DisasContext * dc, unsigned int insn)
TCGv r_tmp = tcg_temp_local_new();
tcg_gen_mov_tl(r_tmp, cpu_tmp0);
- save_state(dc, cpu_cond);
+ save_state(dc);
gen_helper_wrpstate(cpu_env, r_tmp);
tcg_temp_free(r_tmp);
dc->npc = DYNAMIC_PC;
@@ -3905,7 +3877,7 @@ static void disas_sparc_insn(DisasContext * dc, unsigned int insn)
TCGv r_tmp = tcg_temp_local_new();
tcg_gen_mov_tl(r_tmp, cpu_tmp0);
- save_state(dc, cpu_cond);
+ save_state(dc);
tcg_gen_trunc_tl_i32(cpu_tmp32, r_tmp);
tcg_temp_free(r_tmp);
tcg_gen_st_i32(cpu_tmp32, cpu_env,
@@ -3987,7 +3959,7 @@ static void disas_sparc_insn(DisasContext * dc, unsigned int insn)
switch (rd) {
case 0: // hpstate
// XXX gen_op_wrhpstate();
- save_state(dc, cpu_cond);
+ save_state(dc);
gen_op_next_insn();
tcg_gen_exit_tb(0);
dc->is_br = 1;
@@ -4027,42 +3999,38 @@ static void disas_sparc_insn(DisasContext * dc, unsigned int insn)
{
int cc = GET_FIELD_SP(insn, 11, 12);
int cond = GET_FIELD_SP(insn, 14, 17);
- TCGv r_cond;
- int l1;
+ DisasCompare cmp;
- r_cond = tcg_temp_new();
if (insn & (1 << 18)) {
- if (cc == 0)
- gen_cond(r_cond, 0, cond, dc);
- else if (cc == 2)
- gen_cond(r_cond, 1, cond, dc);
- else
+ if (cc == 0) {
+ gen_compare(&cmp, 0, cond, dc);
+ } else if (cc == 2) {
+ gen_compare(&cmp, 1, cond, dc);
+ } else {
goto illegal_insn;
+ }
} else {
- gen_fcond(r_cond, cc, cond);
+ gen_fcompare(&cmp, cc, cond);
}
- l1 = gen_new_label();
-
- tcg_gen_brcondi_tl(TCG_COND_EQ, r_cond, 0, l1);
- if (IS_IMM) { /* immediate */
- TCGv r_const;
-
+ /* The get_src2 above loaded the normal 13-bit
+ immediate field, not the 11-bit field we have
+ in movcc. But it did handle the reg case. */
+ if (IS_IMM) {
simm = GET_FIELD_SPs(insn, 0, 10);
- r_const = tcg_const_tl(simm);
- gen_movl_TN_reg(rd, r_const);
- tcg_temp_free(r_const);
- } else {
- rs2 = GET_FIELD_SP(insn, 0, 4);
- gen_movl_reg_TN(rs2, cpu_tmp0);
- gen_movl_TN_reg(rd, cpu_tmp0);
+ tcg_gen_movi_tl(cpu_src2, simm);
}
- gen_set_label(l1);
- tcg_temp_free(r_cond);
+
+ gen_movl_reg_TN(rd, cpu_dst);
+ tcg_gen_movcond_tl(cmp.cond, cpu_dst,
+ cmp.c1, cmp.c2,
+ cpu_src2, cpu_dst);
+ free_compare(&cmp);
+ gen_movl_TN_reg(rd, cpu_dst);
break;
}
case 0x2d: /* V9 sdivx */
- gen_op_sdivx(cpu_dst, cpu_src1, cpu_src2);
+ gen_helper_sdivx(cpu_dst, cpu_env, cpu_src1, cpu_src2);
gen_movl_TN_reg(rd, cpu_dst);
break;
case 0x2e: /* V9 popc */
@@ -4074,27 +4042,24 @@ static void disas_sparc_insn(DisasContext * dc, unsigned int insn)
case 0x2f: /* V9 movr */
{
int cond = GET_FIELD_SP(insn, 10, 12);
- int l1;
-
- cpu_src1 = get_src1(insn, cpu_src1);
+ DisasCompare cmp;
- l1 = gen_new_label();
-
- tcg_gen_brcondi_tl(gen_tcg_cond_reg[cond],
- cpu_src1, 0, l1);
- if (IS_IMM) { /* immediate */
- TCGv r_const;
+ gen_compare_reg(&cmp, cond, cpu_src1);
+ /* The get_src2 above loaded the normal 13-bit
+ immediate field, not the 10-bit field we have
+ in movr. But it did handle the reg case. */
+ if (IS_IMM) {
simm = GET_FIELD_SPs(insn, 0, 9);
- r_const = tcg_const_tl(simm);
- gen_movl_TN_reg(rd, r_const);
- tcg_temp_free(r_const);
- } else {
- rs2 = GET_FIELD_SP(insn, 0, 4);
- gen_movl_reg_TN(rs2, cpu_tmp0);
- gen_movl_TN_reg(rd, cpu_tmp0);
+ tcg_gen_movi_tl(cpu_src2, simm);
}
- gen_set_label(l1);
+
+ gen_movl_reg_TN(rd, cpu_dst);
+ tcg_gen_movcond_tl(cmp.cond, cpu_dst,
+ cmp.c1, cmp.c2,
+ cpu_src2, cpu_dst);
+ free_compare(&cmp);
+ gen_movl_TN_reg(rd, cpu_dst);
break;
}
#endif
@@ -4107,8 +4072,9 @@ static void disas_sparc_insn(DisasContext * dc, unsigned int insn)
int opf = GET_FIELD_SP(insn, 5, 13);
rs1 = GET_FIELD(insn, 13, 17);
rs2 = GET_FIELD(insn, 27, 31);
- if (gen_trap_ifnofpu(dc, cpu_cond))
+ if (gen_trap_ifnofpu(dc)) {
goto jmp_insn;
+ }
switch (opf) {
case 0x000: /* VIS I edge8cc */
@@ -4554,7 +4520,7 @@ static void disas_sparc_insn(DisasContext * dc, unsigned int insn)
} else if (xop == 0x39) { /* V9 return */
TCGv_i32 r_const;
- save_state(dc, cpu_cond);
+ save_state(dc);
cpu_src1 = get_src1(insn, cpu_src1);
if (IS_IMM) { /* immediate */
simm = GET_FIELDs(insn, 19, 31);
@@ -4568,7 +4534,7 @@ static void disas_sparc_insn(DisasContext * dc, unsigned int insn)
tcg_gen_mov_tl(cpu_dst, cpu_src1);
}
gen_helper_restore(cpu_env);
- gen_mov_pc_npc(dc, cpu_cond);
+ gen_mov_pc_npc(dc);
r_const = tcg_const_i32(3);
gen_helper_check_align(cpu_env, cpu_dst, r_const);
tcg_temp_free_i32(r_const);
@@ -4598,7 +4564,7 @@ static void disas_sparc_insn(DisasContext * dc, unsigned int insn)
r_pc = tcg_const_tl(dc->pc);
gen_movl_TN_reg(rd, r_pc);
tcg_temp_free(r_pc);
- gen_mov_pc_npc(dc, cpu_cond);
+ gen_mov_pc_npc(dc);
r_const = tcg_const_i32(3);
gen_helper_check_align(cpu_env, cpu_dst, r_const);
tcg_temp_free_i32(r_const);
@@ -4614,7 +4580,7 @@ static void disas_sparc_insn(DisasContext * dc, unsigned int insn)
if (!supervisor(dc))
goto priv_insn;
- gen_mov_pc_npc(dc, cpu_cond);
+ gen_mov_pc_npc(dc);
r_const = tcg_const_i32(3);
gen_helper_check_align(cpu_env, cpu_dst, r_const);
tcg_temp_free_i32(r_const);
@@ -4630,12 +4596,12 @@ static void disas_sparc_insn(DisasContext * dc, unsigned int insn)
/* nop */
break;
case 0x3c: /* save */
- save_state(dc, cpu_cond);
+ save_state(dc);
gen_helper_save(cpu_env);
gen_movl_TN_reg(rd, cpu_dst);
break;
case 0x3d: /* restore */
- save_state(dc, cpu_cond);
+ save_state(dc);
gen_helper_restore(cpu_env);
gen_movl_TN_reg(rd, cpu_dst);
break;
@@ -4718,7 +4684,7 @@ static void disas_sparc_insn(DisasContext * dc, unsigned int insn)
else {
TCGv_i32 r_const;
- save_state(dc, cpu_cond);
+ save_state(dc);
r_const = tcg_const_i32(7);
/* XXX remove alignment check */
gen_helper_check_align(cpu_env, cpu_addr, r_const);
@@ -4769,7 +4735,7 @@ static void disas_sparc_insn(DisasContext * dc, unsigned int insn)
if (!supervisor(dc))
goto priv_insn;
#endif
- save_state(dc, cpu_cond);
+ save_state(dc);
gen_ld_asi(cpu_val, cpu_addr, insn, 4, 0);
break;
case 0x11: /* lduba, load unsigned byte alternate */
@@ -4779,7 +4745,7 @@ static void disas_sparc_insn(DisasContext * dc, unsigned int insn)
if (!supervisor(dc))
goto priv_insn;
#endif
- save_state(dc, cpu_cond);
+ save_state(dc);
gen_ld_asi(cpu_val, cpu_addr, insn, 1, 0);
break;
case 0x12: /* lduha, load unsigned halfword alternate */
@@ -4789,7 +4755,7 @@ static void disas_sparc_insn(DisasContext * dc, unsigned int insn)
if (!supervisor(dc))
goto priv_insn;
#endif
- save_state(dc, cpu_cond);
+ save_state(dc);
gen_ld_asi(cpu_val, cpu_addr, insn, 2, 0);
break;
case 0x13: /* ldda, load double word alternate */
@@ -4801,7 +4767,7 @@ static void disas_sparc_insn(DisasContext * dc, unsigned int insn)
#endif
if (rd & 1)
goto illegal_insn;
- save_state(dc, cpu_cond);
+ save_state(dc);
gen_ldda_asi(cpu_val, cpu_addr, insn, rd);
goto skip_move;
case 0x19: /* ldsba, load signed byte alternate */
@@ -4811,7 +4777,7 @@ static void disas_sparc_insn(DisasContext * dc, unsigned int insn)
if (!supervisor(dc))
goto priv_insn;
#endif
- save_state(dc, cpu_cond);
+ save_state(dc);
gen_ld_asi(cpu_val, cpu_addr, insn, 1, 1);
break;
case 0x1a: /* ldsha, load signed halfword alternate */
@@ -4821,7 +4787,7 @@ static void disas_sparc_insn(DisasContext * dc, unsigned int insn)
if (!supervisor(dc))
goto priv_insn;
#endif
- save_state(dc, cpu_cond);
+ save_state(dc);
gen_ld_asi(cpu_val, cpu_addr, insn, 2, 1);
break;
case 0x1d: /* ldstuba -- XXX: should be atomically */
@@ -4831,7 +4797,7 @@ static void disas_sparc_insn(DisasContext * dc, unsigned int insn)
if (!supervisor(dc))
goto priv_insn;
#endif
- save_state(dc, cpu_cond);
+ save_state(dc);
gen_ldstub_asi(cpu_val, cpu_addr, insn);
break;
case 0x1f: /* swapa, swap reg with alt. memory. Also
@@ -4843,7 +4809,7 @@ static void disas_sparc_insn(DisasContext * dc, unsigned int insn)
if (!supervisor(dc))
goto priv_insn;
#endif
- save_state(dc, cpu_cond);
+ save_state(dc);
gen_movl_reg_TN(rd, cpu_val);
gen_swap_asi(cpu_val, cpu_addr, insn);
break;
@@ -4865,28 +4831,28 @@ static void disas_sparc_insn(DisasContext * dc, unsigned int insn)
tcg_gen_qemu_ld64(cpu_val, cpu_addr, dc->mem_idx);
break;
case 0x18: /* V9 ldswa */
- save_state(dc, cpu_cond);
+ save_state(dc);
gen_ld_asi(cpu_val, cpu_addr, insn, 4, 1);
break;
case 0x1b: /* V9 ldxa */
- save_state(dc, cpu_cond);
+ save_state(dc);
gen_ld_asi(cpu_val, cpu_addr, insn, 8, 0);
break;
case 0x2d: /* V9 prefetch, no effect */
goto skip_move;
case 0x30: /* V9 ldfa */
- if (gen_trap_ifnofpu(dc, cpu_cond)) {
+ if (gen_trap_ifnofpu(dc)) {
goto jmp_insn;
}
- save_state(dc, cpu_cond);
+ save_state(dc);
gen_ldf_asi(cpu_addr, insn, 4, rd);
gen_update_fprs_dirty(rd);
goto skip_move;
case 0x33: /* V9 lddfa */
- if (gen_trap_ifnofpu(dc, cpu_cond)) {
+ if (gen_trap_ifnofpu(dc)) {
goto jmp_insn;
}
- save_state(dc, cpu_cond);
+ save_state(dc);
gen_ldf_asi(cpu_addr, insn, 8, DFPREG(rd));
gen_update_fprs_dirty(DFPREG(rd));
goto skip_move;
@@ -4894,10 +4860,10 @@ static void disas_sparc_insn(DisasContext * dc, unsigned int insn)
goto skip_move;
case 0x32: /* V9 ldqfa */
CHECK_FPU_FEATURE(dc, FLOAT128);
- if (gen_trap_ifnofpu(dc, cpu_cond)) {
+ if (gen_trap_ifnofpu(dc)) {
goto jmp_insn;
}
- save_state(dc, cpu_cond);
+ save_state(dc);
gen_ldf_asi(cpu_addr, insn, 16, QFPREG(rd));
gen_update_fprs_dirty(QFPREG(rd));
goto skip_move;
@@ -4910,9 +4876,10 @@ static void disas_sparc_insn(DisasContext * dc, unsigned int insn)
skip_move: ;
#endif
} else if (xop >= 0x20 && xop < 0x24) {
- if (gen_trap_ifnofpu(dc, cpu_cond))
+ if (gen_trap_ifnofpu(dc)) {
goto jmp_insn;
- save_state(dc, cpu_cond);
+ }
+ save_state(dc);
switch (xop) {
case 0x20: /* ldf, load fpreg */
gen_address_mask(dc, cpu_addr);
@@ -4983,7 +4950,7 @@ static void disas_sparc_insn(DisasContext * dc, unsigned int insn)
else {
TCGv_i32 r_const;
- save_state(dc, cpu_cond);
+ save_state(dc);
gen_address_mask(dc, cpu_addr);
r_const = tcg_const_i32(7);
/* XXX remove alignment check */
@@ -5002,7 +4969,7 @@ static void disas_sparc_insn(DisasContext * dc, unsigned int insn)
if (!supervisor(dc))
goto priv_insn;
#endif
- save_state(dc, cpu_cond);
+ save_state(dc);
gen_st_asi(cpu_val, cpu_addr, insn, 4);
dc->npc = DYNAMIC_PC;
break;
@@ -5013,7 +4980,7 @@ static void disas_sparc_insn(DisasContext * dc, unsigned int insn)
if (!supervisor(dc))
goto priv_insn;
#endif
- save_state(dc, cpu_cond);
+ save_state(dc);
gen_st_asi(cpu_val, cpu_addr, insn, 1);
dc->npc = DYNAMIC_PC;
break;
@@ -5024,7 +4991,7 @@ static void disas_sparc_insn(DisasContext * dc, unsigned int insn)
if (!supervisor(dc))
goto priv_insn;
#endif
- save_state(dc, cpu_cond);
+ save_state(dc);
gen_st_asi(cpu_val, cpu_addr, insn, 2);
dc->npc = DYNAMIC_PC;
break;
@@ -5038,7 +5005,7 @@ static void disas_sparc_insn(DisasContext * dc, unsigned int insn)
if (rd & 1)
goto illegal_insn;
else {
- save_state(dc, cpu_cond);
+ save_state(dc);
gen_stda_asi(cpu_val, cpu_addr, insn, rd);
}
break;
@@ -5049,7 +5016,7 @@ static void disas_sparc_insn(DisasContext * dc, unsigned int insn)
tcg_gen_qemu_st64(cpu_val, cpu_addr, dc->mem_idx);
break;
case 0x1e: /* V9 stxa */
- save_state(dc, cpu_cond);
+ save_state(dc);
gen_st_asi(cpu_val, cpu_addr, insn, 8);
dc->npc = DYNAMIC_PC;
break;
@@ -5058,9 +5025,10 @@ static void disas_sparc_insn(DisasContext * dc, unsigned int insn)
goto illegal_insn;
}
} else if (xop > 0x23 && xop < 0x28) {
- if (gen_trap_ifnofpu(dc, cpu_cond))
+ if (gen_trap_ifnofpu(dc)) {
goto jmp_insn;
- save_state(dc, cpu_cond);
+ }
+ save_state(dc);
switch (xop) {
case 0x24: /* stf, store fpreg */
gen_address_mask(dc, cpu_addr);
@@ -5102,8 +5070,9 @@ static void disas_sparc_insn(DisasContext * dc, unsigned int insn)
#else
if (!supervisor(dc))
goto priv_insn;
- if (gen_trap_ifnofpu(dc, cpu_cond))
+ if (gen_trap_ifnofpu(dc)) {
goto jmp_insn;
+ }
goto nfq_insn;
#endif
#endif
@@ -5116,11 +5085,11 @@ static void disas_sparc_insn(DisasContext * dc, unsigned int insn)
goto illegal_insn;
}
} else if (xop > 0x33 && xop < 0x3f) {
- save_state(dc, cpu_cond);
+ save_state(dc);
switch (xop) {
#ifdef TARGET_SPARC64
case 0x34: /* V9 stfa */
- if (gen_trap_ifnofpu(dc, cpu_cond)) {
+ if (gen_trap_ifnofpu(dc)) {
goto jmp_insn;
}
gen_stf_asi(cpu_addr, insn, 4, rd);
@@ -5130,7 +5099,7 @@ static void disas_sparc_insn(DisasContext * dc, unsigned int insn)
TCGv_i32 r_const;
CHECK_FPU_FEATURE(dc, FLOAT128);
- if (gen_trap_ifnofpu(dc, cpu_cond)) {
+ if (gen_trap_ifnofpu(dc)) {
goto jmp_insn;
}
r_const = tcg_const_i32(7);
@@ -5140,7 +5109,7 @@ static void disas_sparc_insn(DisasContext * dc, unsigned int insn)
}
break;
case 0x37: /* V9 stdfa */
- if (gen_trap_ifnofpu(dc, cpu_cond)) {
+ if (gen_trap_ifnofpu(dc)) {
goto jmp_insn;
}
gen_stf_asi(cpu_addr, insn, 8, DFPREG(rd));
@@ -5186,7 +5155,7 @@ static void disas_sparc_insn(DisasContext * dc, unsigned int insn)
{
TCGv_i32 r_const;
- save_state(dc, cpu_cond);
+ save_state(dc);
r_const = tcg_const_i32(TT_ILL_INSN);
gen_helper_raise_exception(cpu_env, r_const);
tcg_temp_free_i32(r_const);
@@ -5197,7 +5166,7 @@ static void disas_sparc_insn(DisasContext * dc, unsigned int insn)
{
TCGv_i32 r_const;
- save_state(dc, cpu_cond);
+ save_state(dc);
r_const = tcg_const_i32(TT_UNIMP_FLUSH);
gen_helper_raise_exception(cpu_env, r_const);
tcg_temp_free_i32(r_const);
@@ -5209,7 +5178,7 @@ static void disas_sparc_insn(DisasContext * dc, unsigned int insn)
{
TCGv_i32 r_const;
- save_state(dc, cpu_cond);
+ save_state(dc);
r_const = tcg_const_i32(TT_PRIV_INSN);
gen_helper_raise_exception(cpu_env, r_const);
tcg_temp_free_i32(r_const);
@@ -5218,13 +5187,13 @@ static void disas_sparc_insn(DisasContext * dc, unsigned int insn)
goto egress;
#endif
nfpu_insn:
- save_state(dc, cpu_cond);
+ save_state(dc);
gen_op_fpexception_im(FSR_FTT_UNIMPFPOP);
dc->is_br = 1;
goto egress;
#if !defined(CONFIG_USER_ONLY) && !defined(TARGET_SPARC64)
nfq_insn:
- save_state(dc, cpu_cond);
+ save_state(dc);
gen_op_fpexception_im(FSR_FTT_SEQ_ERROR);
dc->is_br = 1;
goto egress;
@@ -5234,7 +5203,7 @@ static void disas_sparc_insn(DisasContext * dc, unsigned int insn)
{
TCGv r_const;
- save_state(dc, cpu_cond);
+ save_state(dc);
r_const = tcg_const_i32(TT_NCP_INSN);
gen_helper_raise_exception(cpu_env, r_const);
tcg_temp_free(r_const);
@@ -5280,16 +5249,6 @@ static inline void gen_intermediate_code_internal(TranslationBlock * tb,
dc->singlestep = (env->singlestep_enabled || singlestep);
gen_opc_end = gen_opc_buf + OPC_MAX_SIZE;
- cpu_tmp0 = tcg_temp_new();
- cpu_tmp32 = tcg_temp_new_i32();
- cpu_tmp64 = tcg_temp_new_i64();
-
- cpu_dst = tcg_temp_local_new();
-
- // loads and stores
- cpu_val = tcg_temp_local_new();
- cpu_addr = tcg_temp_local_new();
-
num_insns = 0;
max_insns = tb->cflags & CF_COUNT_MASK;
if (max_insns == 0)
@@ -5300,7 +5259,7 @@ static inline void gen_intermediate_code_internal(TranslationBlock * tb,
QTAILQ_FOREACH(bp, &env->breakpoints, entry) {
if (bp->pc == dc->pc) {
if (dc->pc != pc_start)
- save_state(dc, cpu_cond);
+ save_state(dc);
gen_helper_debug(cpu_env);
tcg_gen_exit_tb(0);
dc->is_br = 1;
@@ -5325,9 +5284,24 @@ static inline void gen_intermediate_code_internal(TranslationBlock * tb,
gen_io_start();
last_pc = dc->pc;
insn = cpu_ldl_code(env, dc->pc);
+
+ cpu_tmp0 = tcg_temp_new();
+ cpu_tmp32 = tcg_temp_new_i32();
+ cpu_tmp64 = tcg_temp_new_i64();
+ cpu_dst = tcg_temp_new();
+ cpu_val = tcg_temp_new();
+ cpu_addr = tcg_temp_new();
+
disas_sparc_insn(dc, insn);
num_insns++;
+ tcg_temp_free(cpu_addr);
+ tcg_temp_free(cpu_val);
+ tcg_temp_free(cpu_dst);
+ tcg_temp_free_i64(cpu_tmp64);
+ tcg_temp_free_i32(cpu_tmp32);
+ tcg_temp_free(cpu_tmp0);
+
if (dc->is_br)
break;
/* if the next PC is different, we abort now */
@@ -5347,24 +5321,19 @@ static inline void gen_intermediate_code_internal(TranslationBlock * tb,
num_insns < max_insns);
exit_gen_loop:
- tcg_temp_free(cpu_addr);
- tcg_temp_free(cpu_val);
- tcg_temp_free(cpu_dst);
- tcg_temp_free_i64(cpu_tmp64);
- tcg_temp_free_i32(cpu_tmp32);
- tcg_temp_free(cpu_tmp0);
-
- if (tb->cflags & CF_LAST_IO)
+ if (tb->cflags & CF_LAST_IO) {
gen_io_end();
+ }
if (!dc->is_br) {
if (dc->pc != DYNAMIC_PC &&
(dc->npc != DYNAMIC_PC && dc->npc != JUMP_PC)) {
/* static PC and NPC: we can use direct chaining */
gen_goto_tb(dc, 0, dc->pc, dc->npc);
} else {
- if (dc->pc != DYNAMIC_PC)
+ if (dc->pc != DYNAMIC_PC) {
tcg_gen_movi_tl(cpu_pc, dc->pc);
- save_npc(dc, cpu_cond);
+ }
+ save_npc(dc);
tcg_gen_exit_tb(0);
}
}
diff --git a/target-unicore32/translate.c b/target-unicore32/translate.c
index 36f4f2f96..c3cdafa18 100644
--- a/target-unicore32/translate.c
+++ b/target-unicore32/translate.c
@@ -1932,8 +1932,6 @@ static void disas_uc32_insn(CPUUniCore32State *env, DisasContext *s)
}
ILLEGAL;
}
-
- return;
}
/* generate intermediate code in gen_opc_buf and gen_opparam_buf for
diff --git a/target-xtensa/translate.c b/target-xtensa/translate.c
index b9acd706c..82e8cccad 100644
--- a/target-xtensa/translate.c
+++ b/target-xtensa/translate.c
@@ -1829,26 +1829,8 @@ static void disas_xtensa_insn(DisasContext *dc)
int maskimm = (1 << (OP2 + 1)) - 1;
TCGv_i32 tmp = tcg_temp_new_i32();
-
- if (shiftimm) {
- tcg_gen_shri_i32(tmp, cpu_R[RRR_T], shiftimm);
- } else {
- tcg_gen_mov_i32(tmp, cpu_R[RRR_T]);
- }
-
- switch (maskimm) {
- case 0xff:
- tcg_gen_ext8u_i32(cpu_R[RRR_R], tmp);
- break;
-
- case 0xffff:
- tcg_gen_ext16u_i32(cpu_R[RRR_R], tmp);
- break;
-
- default:
- tcg_gen_andi_i32(cpu_R[RRR_R], tmp, maskimm);
- break;
- }
+ tcg_gen_shri_i32(tmp, cpu_R[RRR_T], shiftimm);
+ tcg_gen_andi_i32(cpu_R[RRR_R], tmp, maskimm);
tcg_temp_free(tmp);
}
break;
diff --git a/tcg/README b/tcg/README
index 27846f1ea..aa86992bc 100644
--- a/tcg/README
+++ b/tcg/README
@@ -88,8 +88,7 @@ supported.
* Branches:
-Use the instruction 'br' to jump to a label. Use 'jmp' to jump to an
-explicit address. Conditional branches can only jump to labels.
+Use the instruction 'br' to jump to a label.
3.3) Code Optimizations
@@ -129,10 +128,6 @@ call function 'ptr' (pointer type)
********* Jumps/Labels
-* jmp t0
-
-Absolute jump to address t0 (pointer type).
-
* set_label $label
Define label 'label' at the current program point.
diff --git a/tcg/arm/tcg-target.c b/tcg/arm/tcg-target.c
index 2bad0a2b1..737200e5e 100644
--- a/tcg/arm/tcg-target.c
+++ b/tcg/arm/tcg-target.c
@@ -335,7 +335,7 @@ enum arm_cond_code_e {
COND_AL = 0xe,
};
-static const uint8_t tcg_cond_to_arm_cond[10] = {
+static const uint8_t tcg_cond_to_arm_cond[] = {
[TCG_COND_EQ] = COND_EQ,
[TCG_COND_NE] = COND_NE,
[TCG_COND_LT] = COND_LT,
@@ -1197,20 +1197,11 @@ static inline void tcg_out_qemu_ld(TCGContext *s, const TCGArg *args, int opc)
case 1:
case 2:
default:
- if (data_reg != TCG_REG_R0) {
- tcg_out_dat_reg(s, COND_AL, ARITH_MOV,
- data_reg, 0, TCG_REG_R0, SHIFT_IMM_LSL(0));
- }
+ tcg_out_mov_reg(s, COND_AL, data_reg, TCG_REG_R0);
break;
case 3:
- if (data_reg != TCG_REG_R0) {
- tcg_out_dat_reg(s, COND_AL, ARITH_MOV,
- data_reg, 0, TCG_REG_R0, SHIFT_IMM_LSL(0));
- }
- if (data_reg2 != TCG_REG_R1) {
- tcg_out_dat_reg(s, COND_AL, ARITH_MOV,
- data_reg2, 0, TCG_REG_R1, SHIFT_IMM_LSL(0));
- }
+ tcg_out_mov_reg(s, COND_AL, data_reg, TCG_REG_R0);
+ tcg_out_mov_reg(s, COND_AL, data_reg2, TCG_REG_R1);
break;
}
@@ -1530,12 +1521,6 @@ static inline void tcg_out_op(TCGContext *s, TCGOpcode opc,
else
tcg_out_callr(s, COND_AL, args[0]);
break;
- case INDEX_op_jmp:
- if (const_args[0])
- tcg_out_goto(s, COND_AL, args[0]);
- else
- tcg_out_bx(s, COND_AL, args[0]);
- break;
case INDEX_op_br:
tcg_out_goto_label(s, COND_AL, args[0]);
break;
@@ -1769,7 +1754,6 @@ static const TCGTargetOpDef arm_op_defs[] = {
{ INDEX_op_exit_tb, { } },
{ INDEX_op_goto_tb, { } },
{ INDEX_op_call, { "ri" } },
- { INDEX_op_jmp, { "ri" } },
{ INDEX_op_br, { } },
{ INDEX_op_mov_i32, { "r", "r" } },
diff --git a/tcg/hppa/tcg-target.c b/tcg/hppa/tcg-target.c
index 2c79c1081..de500ae18 100644
--- a/tcg/hppa/tcg-target.c
+++ b/tcg/hppa/tcg-target.c
@@ -732,7 +732,7 @@ static void tcg_out_branch(TCGContext *s, int label_index, int nul)
}
}
-static const uint8_t tcg_cond_to_cmp_cond[10] =
+static const uint8_t tcg_cond_to_cmp_cond[] =
{
[TCG_COND_EQ] = COND_EQ,
[TCG_COND_NE] = COND_EQ | COND_FALSE,
@@ -814,19 +814,6 @@ static void tcg_out_comclr(TCGContext *s, int cond, TCGArg ret,
tcg_out32(s, op);
}
-static TCGCond const tcg_high_cond[] = {
- [TCG_COND_EQ] = TCG_COND_EQ,
- [TCG_COND_NE] = TCG_COND_NE,
- [TCG_COND_LT] = TCG_COND_LT,
- [TCG_COND_LE] = TCG_COND_LT,
- [TCG_COND_GT] = TCG_COND_GT,
- [TCG_COND_GE] = TCG_COND_GT,
- [TCG_COND_LTU] = TCG_COND_LTU,
- [TCG_COND_LEU] = TCG_COND_LTU,
- [TCG_COND_GTU] = TCG_COND_GTU,
- [TCG_COND_GEU] = TCG_COND_GTU
-};
-
static void tcg_out_brcond2(TCGContext *s, int cond, TCGArg al, TCGArg ah,
TCGArg bl, int blconst, TCGArg bh, int bhconst,
int label_index)
@@ -841,7 +828,7 @@ static void tcg_out_brcond2(TCGContext *s, int cond, TCGArg al, TCGArg ah,
tcg_out_brcond(s, TCG_COND_NE, ah, bh, bhconst, label_index);
break;
default:
- tcg_out_brcond(s, tcg_high_cond[cond], ah, bh, bhconst, label_index);
+ tcg_out_brcond(s, tcg_high_cond(cond), ah, bh, bhconst, label_index);
tcg_out_comclr(s, TCG_COND_NE, TCG_REG_R0, ah, bh, bhconst);
tcg_out_brcond(s, tcg_unsigned_cond(cond),
al, bl, blconst, label_index);
@@ -894,7 +881,7 @@ static void tcg_out_setcond2(TCGContext *s, int cond, TCGArg ret,
tcg_out_setcond(s, tcg_unsigned_cond(cond), scratch, al, bl, blconst);
tcg_out_comclr(s, TCG_COND_EQ, TCG_REG_R0, ah, bh, bhconst);
tcg_out_movi(s, TCG_TYPE_I32, scratch, 0);
- tcg_out_comclr(s, tcg_invert_cond(tcg_high_cond[cond]),
+ tcg_out_comclr(s, tcg_invert_cond(tcg_high_cond(cond)),
TCG_REG_R0, ah, bh, bhconst);
tcg_out_movi(s, TCG_TYPE_I32, scratch, 1);
break;
@@ -1353,11 +1340,6 @@ static inline void tcg_out_op(TCGContext *s, TCGOpcode opc, const TCGArg *args,
}
break;
- case INDEX_op_jmp:
- fprintf(stderr, "unimplemented jmp\n");
- tcg_abort();
- break;
-
case INDEX_op_br:
tcg_out_branch(s, args[0], 1);
break;
@@ -1592,7 +1574,6 @@ static const TCGTargetOpDef hppa_op_defs[] = {
{ INDEX_op_goto_tb, { } },
{ INDEX_op_call, { "ri" } },
- { INDEX_op_jmp, { "r" } },
{ INDEX_op_br, { } },
{ INDEX_op_mov_i32, { "r", "r" } },
diff --git a/tcg/i386/tcg-target.c b/tcg/i386/tcg-target.c
index 0e218c861..4952c057b 100644
--- a/tcg/i386/tcg-target.c
+++ b/tcg/i386/tcg-target.c
@@ -338,7 +338,7 @@ static inline int tcg_target_const_match(tcg_target_long val,
#define JCC_JLE 0xe
#define JCC_JG 0xf
-static const uint8_t tcg_cond_to_jcc[10] = {
+static const uint8_t tcg_cond_to_jcc[] = {
[TCG_COND_EQ] = JCC_JE,
[TCG_COND_NE] = JCC_JNE,
[TCG_COND_LT] = JCC_JL,
@@ -1513,14 +1513,6 @@ static inline void tcg_out_op(TCGContext *s, TCGOpcode opc,
tcg_out_modrm(s, OPC_GRP5, EXT5_CALLN_Ev, args[0]);
}
break;
- case INDEX_op_jmp:
- if (const_args[0]) {
- tcg_out_jmp(s, args[0]);
- } else {
- /* jmp *reg */
- tcg_out_modrm(s, OPC_GRP5, EXT5_JMPN_Ev, args[0]);
- }
- break;
case INDEX_op_br:
tcg_out_jxx(s, JCC_JMP, args[0], 0);
break;
@@ -1848,7 +1840,6 @@ static const TCGTargetOpDef x86_op_defs[] = {
{ INDEX_op_exit_tb, { } },
{ INDEX_op_goto_tb, { } },
{ INDEX_op_call, { "ri" } },
- { INDEX_op_jmp, { "ri" } },
{ INDEX_op_br, { } },
{ INDEX_op_mov_i32, { "r", "r" } },
{ INDEX_op_movi_i32, { "r" } },
diff --git a/tcg/ia64/tcg-target.c b/tcg/ia64/tcg-target.c
index dc9c12cf1..705712f77 100644
--- a/tcg/ia64/tcg-target.c
+++ b/tcg/ia64/tcg-target.c
@@ -1916,9 +1916,6 @@ static inline void tcg_out_op(TCGContext *s, TCGOpcode opc,
case INDEX_op_goto_tb:
tcg_out_goto_tb(s, args[0]);
break;
- case INDEX_op_jmp:
- tcg_out_jmp(s, args[0]);
- break;
case INDEX_op_movi_i32:
tcg_out_movi(s, TCG_TYPE_I32, args[0], args[1]);
@@ -2156,7 +2153,6 @@ static const TCGTargetOpDef ia64_op_defs[] = {
{ INDEX_op_call, { "r" } },
{ INDEX_op_exit_tb, { } },
{ INDEX_op_goto_tb, { } },
- { INDEX_op_jmp, { "r" } },
{ INDEX_op_mov_i32, { "r", "r" } },
{ INDEX_op_movi_i32, { "r" } },
diff --git a/tcg/mips/tcg-target.c b/tcg/mips/tcg-target.c
index 34e3e7f82..7e4013e1e 100644
--- a/tcg/mips/tcg-target.c
+++ b/tcg/mips/tcg-target.c
@@ -1322,10 +1322,6 @@ static inline void tcg_out_op(TCGContext *s, TCGOpcode opc,
tcg_out_opc_reg(s, OPC_JALR, TCG_REG_RA, args[0], 0);
tcg_out_nop(s);
break;
- case INDEX_op_jmp:
- tcg_out_opc_reg(s, OPC_JR, 0, args[0], 0);
- tcg_out_nop(s);
- break;
case INDEX_op_br:
tcg_out_brcond(s, TCG_COND_EQ, TCG_REG_ZERO, TCG_REG_ZERO, args[0]);
break;
@@ -1577,7 +1573,6 @@ static const TCGTargetOpDef mips_op_defs[] = {
{ INDEX_op_exit_tb, { } },
{ INDEX_op_goto_tb, { } },
{ INDEX_op_call, { "C" } },
- { INDEX_op_jmp, { "r" } },
{ INDEX_op_br, { } },
{ INDEX_op_mov_i32, { "r", "r" } },
diff --git a/tcg/optimize.c b/tcg/optimize.c
index 35532a1e0..edb2b0ea9 100644
--- a/tcg/optimize.c
+++ b/tcg/optimize.c
@@ -321,6 +321,8 @@ static TCGArg do_constant_folding_cond(TCGOpcode op, TCGArg x,
return (uint32_t)temps[x].val <= (uint32_t)temps[y].val;
case TCG_COND_GTU:
return (uint32_t)temps[x].val > (uint32_t)temps[y].val;
+ default:
+ break;
}
break;
case 64:
@@ -345,6 +347,8 @@ static TCGArg do_constant_folding_cond(TCGOpcode op, TCGArg x,
return (uint64_t)temps[x].val <= (uint64_t)temps[y].val;
case TCG_COND_GTU:
return (uint64_t)temps[x].val > (uint64_t)temps[y].val;
+ default:
+ break;
}
break;
}
@@ -362,6 +366,8 @@ static TCGArg do_constant_folding_cond(TCGOpcode op, TCGArg x,
case TCG_COND_LEU:
case TCG_COND_EQ:
return 1;
+ default:
+ break;
}
} else if (temps[y].state == TCG_TEMP_CONST && temps[y].val == 0) {
switch (c) {
diff --git a/tcg/ppc/tcg-target.c b/tcg/ppc/tcg-target.c
index 90c275d69..60b7b9262 100644
--- a/tcg/ppc/tcg-target.c
+++ b/tcg/ppc/tcg-target.c
@@ -437,7 +437,7 @@ enum {
CR_SO
};
-static const uint32_t tcg_to_bc[10] = {
+static const uint32_t tcg_to_bc[] = {
[TCG_COND_EQ] = BC | BI (7, CR_EQ) | BO_COND_TRUE,
[TCG_COND_NE] = BC | BI (7, CR_EQ) | BO_COND_FALSE,
[TCG_COND_LT] = BC | BI (7, CR_LT) | BO_COND_TRUE,
@@ -1417,15 +1417,6 @@ static void tcg_out_op(TCGContext *s, TCGOpcode opc, const TCGArg *args,
case INDEX_op_call:
tcg_out_call (s, args[0], const_args[0]);
break;
- case INDEX_op_jmp:
- if (const_args[0]) {
- tcg_out_b (s, 0, args[0]);
- }
- else {
- tcg_out32 (s, MTSPR | RS (args[0]) | CTR);
- tcg_out32 (s, BCCTR | BO_ALWAYS);
- }
- break;
case INDEX_op_movi_i32:
tcg_out_movi(s, TCG_TYPE_I32, args[0], args[1]);
break;
@@ -1904,7 +1895,6 @@ static const TCGTargetOpDef ppc_op_defs[] = {
{ INDEX_op_exit_tb, { } },
{ INDEX_op_goto_tb, { } },
{ INDEX_op_call, { "ri" } },
- { INDEX_op_jmp, { "ri" } },
{ INDEX_op_br, { } },
{ INDEX_op_mov_i32, { "r", "r" } },
diff --git a/tcg/ppc64/tcg-target.c b/tcg/ppc64/tcg-target.c
index 19944bc42..5403fc1f9 100644
--- a/tcg/ppc64/tcg-target.c
+++ b/tcg/ppc64/tcg-target.c
@@ -418,7 +418,7 @@ enum {
CR_SO
};
-static const uint32_t tcg_to_bc[10] = {
+static const uint32_t tcg_to_bc[] = {
[TCG_COND_EQ] = BC | BI (7, CR_EQ) | BO_COND_TRUE,
[TCG_COND_NE] = BC | BI (7, CR_EQ) | BO_COND_FALSE,
[TCG_COND_LT] = BC | BI (7, CR_LT) | BO_COND_TRUE,
@@ -1245,15 +1245,6 @@ static void tcg_out_op (TCGContext *s, TCGOpcode opc, const TCGArg *args,
case INDEX_op_call:
tcg_out_call (s, args[0], const_args[0]);
break;
- case INDEX_op_jmp:
- if (const_args[0]) {
- tcg_out_b (s, 0, args[0]);
- }
- else {
- tcg_out32 (s, MTSPR | RS (args[0]) | CTR);
- tcg_out32 (s, BCCTR | BO_ALWAYS);
- }
- break;
case INDEX_op_movi_i32:
tcg_out_movi (s, TCG_TYPE_I32, args[0], args[1]);
break;
@@ -1588,7 +1579,6 @@ static const TCGTargetOpDef ppc_op_defs[] = {
{ INDEX_op_exit_tb, { } },
{ INDEX_op_goto_tb, { } },
{ INDEX_op_call, { "ri" } },
- { INDEX_op_jmp, { "ri" } },
{ INDEX_op_br, { } },
{ INDEX_op_mov_i32, { "r", "r" } },
diff --git a/tcg/s390/tcg-target.c b/tcg/s390/tcg-target.c
index 3b90605fb..fd9286f52 100644
--- a/tcg/s390/tcg-target.c
+++ b/tcg/s390/tcg-target.c
@@ -268,7 +268,7 @@ static const int tcg_target_call_oarg_regs[] = {
#define S390_CC_ALWAYS 15
/* Condition codes that result from a COMPARE and COMPARE LOGICAL. */
-static const uint8_t tcg_cond_to_s390_cond[10] = {
+static const uint8_t tcg_cond_to_s390_cond[] = {
[TCG_COND_EQ] = S390_CC_EQ,
[TCG_COND_NE] = S390_CC_NE,
[TCG_COND_LT] = S390_CC_LT,
@@ -284,7 +284,7 @@ static const uint8_t tcg_cond_to_s390_cond[10] = {
/* Condition codes that result from a LOAD AND TEST. Here, we have no
unsigned instruction variation, however since the test is vs zero we
can re-map the outcomes appropriately. */
-static const uint8_t tcg_cond_to_ltr_cond[10] = {
+static const uint8_t tcg_cond_to_ltr_cond[] = {
[TCG_COND_EQ] = S390_CC_EQ,
[TCG_COND_NE] = S390_CC_NE,
[TCG_COND_LT] = S390_CC_LT,
@@ -1113,7 +1113,7 @@ static void tgen64_xori(TCGContext *s, TCGReg dest, tcg_target_ulong val)
static int tgen_cmp(TCGContext *s, TCGType type, TCGCond c, TCGReg r1,
TCGArg c2, int c2const)
{
- bool is_unsigned = (c > TCG_COND_GT);
+ bool is_unsigned = is_unsigned_cond(c);
if (c2const) {
if (c2 == 0) {
if (type == TCG_TYPE_I32) {
@@ -2037,11 +2037,6 @@ static inline void tcg_out_op(TCGContext *s, TCGOpcode opc,
break;
#endif /* TCG_TARGET_REG_BITS == 64 */
- case INDEX_op_jmp:
- /* This one is obsolete and never emitted. */
- tcg_abort();
- break;
-
default:
fprintf(stderr,"unimplemented opc 0x%x\n",opc);
tcg_abort();
@@ -2052,7 +2047,6 @@ static const TCGTargetOpDef s390_op_defs[] = {
{ INDEX_op_exit_tb, { } },
{ INDEX_op_goto_tb, { } },
{ INDEX_op_call, { "ri" } },
- { INDEX_op_jmp, { "ri" } },
{ INDEX_op_br, { } },
{ INDEX_op_mov_i32, { "r", "r" } },
diff --git a/tcg/sparc/tcg-target.c b/tcg/sparc/tcg-target.c
index 8fd7f86de..0c32baa50 100644
--- a/tcg/sparc/tcg-target.c
+++ b/tcg/sparc/tcg-target.c
@@ -512,7 +512,7 @@ static void tcg_out_branch_i64(TCGContext *s, int opc, int label_index)
}
#endif
-static const uint8_t tcg_cond_to_bcond[10] = {
+static const uint8_t tcg_cond_to_bcond[] = {
[TCG_COND_EQ] = COND_E,
[TCG_COND_NE] = COND_NE,
[TCG_COND_LT] = COND_L,
@@ -1097,7 +1097,6 @@ static inline void tcg_out_op(TCGContext *s, TCGOpcode opc, const TCGArg *args,
/* delay slot */
tcg_out_nop(s);
break;
- case INDEX_op_jmp:
case INDEX_op_br:
tcg_out_branch_i32(s, COND_A, args[0]);
tcg_out_nop(s);
@@ -1367,7 +1366,6 @@ static const TCGTargetOpDef sparc_op_defs[] = {
{ INDEX_op_exit_tb, { } },
{ INDEX_op_goto_tb, { } },
{ INDEX_op_call, { "ri" } },
- { INDEX_op_jmp, { "ri" } },
{ INDEX_op_br, { } },
{ INDEX_op_mov_i32, { "r", "r" } },
diff --git a/tcg/tcg-op.h b/tcg/tcg-op.h
index bd93fe4f0..551845801 100644
--- a/tcg/tcg-op.h
+++ b/tcg/tcg-op.h
@@ -646,29 +646,49 @@ static inline void tcg_gen_sari_i32(TCGv_i32 ret, TCGv_i32 arg1, int32_t arg2)
static inline void tcg_gen_brcond_i32(TCGCond cond, TCGv_i32 arg1,
TCGv_i32 arg2, int label_index)
{
- tcg_gen_op4ii_i32(INDEX_op_brcond_i32, arg1, arg2, cond, label_index);
+ if (cond == TCG_COND_ALWAYS) {
+ tcg_gen_br(label_index);
+ } else if (cond != TCG_COND_NEVER) {
+ tcg_gen_op4ii_i32(INDEX_op_brcond_i32, arg1, arg2, cond, label_index);
+ }
}
static inline void tcg_gen_brcondi_i32(TCGCond cond, TCGv_i32 arg1,
int32_t arg2, int label_index)
{
- TCGv_i32 t0 = tcg_const_i32(arg2);
- tcg_gen_brcond_i32(cond, arg1, t0, label_index);
- tcg_temp_free_i32(t0);
+ if (cond == TCG_COND_ALWAYS) {
+ tcg_gen_br(label_index);
+ } else if (cond != TCG_COND_NEVER) {
+ TCGv_i32 t0 = tcg_const_i32(arg2);
+ tcg_gen_brcond_i32(cond, arg1, t0, label_index);
+ tcg_temp_free_i32(t0);
+ }
}
static inline void tcg_gen_setcond_i32(TCGCond cond, TCGv_i32 ret,
TCGv_i32 arg1, TCGv_i32 arg2)
{
- tcg_gen_op4i_i32(INDEX_op_setcond_i32, ret, arg1, arg2, cond);
+ if (cond == TCG_COND_ALWAYS) {
+ tcg_gen_movi_i32(ret, 1);
+ } else if (cond == TCG_COND_NEVER) {
+ tcg_gen_movi_i32(ret, 0);
+ } else {
+ tcg_gen_op4i_i32(INDEX_op_setcond_i32, ret, arg1, arg2, cond);
+ }
}
static inline void tcg_gen_setcondi_i32(TCGCond cond, TCGv_i32 ret,
TCGv_i32 arg1, int32_t arg2)
{
- TCGv_i32 t0 = tcg_const_i32(arg2);
- tcg_gen_setcond_i32(cond, ret, arg1, t0);
- tcg_temp_free_i32(t0);
+ if (cond == TCG_COND_ALWAYS) {
+ tcg_gen_movi_i32(ret, 1);
+ } else if (cond == TCG_COND_NEVER) {
+ tcg_gen_movi_i32(ret, 0);
+ } else {
+ TCGv_i32 t0 = tcg_const_i32(arg2);
+ tcg_gen_setcond_i32(cond, ret, arg1, t0);
+ tcg_temp_free_i32(t0);
+ }
}
static inline void tcg_gen_mul_i32(TCGv_i32 ret, TCGv_i32 arg1, TCGv_i32 arg2)
@@ -964,17 +984,27 @@ static inline void tcg_gen_sari_i64(TCGv_i64 ret, TCGv_i64 arg1, int64_t arg2)
static inline void tcg_gen_brcond_i64(TCGCond cond, TCGv_i64 arg1,
TCGv_i64 arg2, int label_index)
{
- tcg_gen_op6ii_i32(INDEX_op_brcond2_i32,
- TCGV_LOW(arg1), TCGV_HIGH(arg1), TCGV_LOW(arg2),
- TCGV_HIGH(arg2), cond, label_index);
+ if (cond == TCG_COND_ALWAYS) {
+ tcg_gen_br(label_index);
+ } else if (cond != TCG_COND_NEVER) {
+ tcg_gen_op6ii_i32(INDEX_op_brcond2_i32,
+ TCGV_LOW(arg1), TCGV_HIGH(arg1), TCGV_LOW(arg2),
+ TCGV_HIGH(arg2), cond, label_index);
+ }
}
static inline void tcg_gen_setcond_i64(TCGCond cond, TCGv_i64 ret,
TCGv_i64 arg1, TCGv_i64 arg2)
{
- tcg_gen_op6i_i32(INDEX_op_setcond2_i32, TCGV_LOW(ret),
- TCGV_LOW(arg1), TCGV_HIGH(arg1),
- TCGV_LOW(arg2), TCGV_HIGH(arg2), cond);
+ if (cond == TCG_COND_ALWAYS) {
+ tcg_gen_movi_i32(TCGV_LOW(ret), 1);
+ } else if (cond == TCG_COND_NEVER) {
+ tcg_gen_movi_i32(TCGV_LOW(ret), 0);
+ } else {
+ tcg_gen_op6i_i32(INDEX_op_setcond2_i32, TCGV_LOW(ret),
+ TCGV_LOW(arg1), TCGV_HIGH(arg1),
+ TCGV_LOW(arg2), TCGV_HIGH(arg2), cond);
+ }
tcg_gen_movi_i32(TCGV_HIGH(ret), 0);
}
@@ -1273,13 +1303,23 @@ static inline void tcg_gen_sari_i64(TCGv_i64 ret, TCGv_i64 arg1, int64_t arg2)
static inline void tcg_gen_brcond_i64(TCGCond cond, TCGv_i64 arg1,
TCGv_i64 arg2, int label_index)
{
- tcg_gen_op4ii_i64(INDEX_op_brcond_i64, arg1, arg2, cond, label_index);
+ if (cond == TCG_COND_ALWAYS) {
+ tcg_gen_br(label_index);
+ } else if (cond != TCG_COND_NEVER) {
+ tcg_gen_op4ii_i64(INDEX_op_brcond_i64, arg1, arg2, cond, label_index);
+ }
}
static inline void tcg_gen_setcond_i64(TCGCond cond, TCGv_i64 ret,
TCGv_i64 arg1, TCGv_i64 arg2)
{
- tcg_gen_op4i_i64(INDEX_op_setcond_i64, ret, arg1, arg2, cond);
+ if (cond == TCG_COND_ALWAYS) {
+ tcg_gen_movi_i64(ret, 1);
+ } else if (cond == TCG_COND_NEVER) {
+ tcg_gen_movi_i64(ret, 0);
+ } else {
+ tcg_gen_op4i_i64(INDEX_op_setcond_i64, ret, arg1, arg2, cond);
+ }
}
static inline void tcg_gen_mul_i64(TCGv_i64 ret, TCGv_i64 arg1, TCGv_i64 arg2)
@@ -1397,9 +1437,13 @@ static inline void tcg_gen_subi_i64(TCGv_i64 ret, TCGv_i64 arg1, int64_t arg2)
static inline void tcg_gen_brcondi_i64(TCGCond cond, TCGv_i64 arg1,
int64_t arg2, int label_index)
{
- TCGv_i64 t0 = tcg_const_i64(arg2);
- tcg_gen_brcond_i64(cond, arg1, t0, label_index);
- tcg_temp_free_i64(t0);
+ if (cond == TCG_COND_ALWAYS) {
+ tcg_gen_br(label_index);
+ } else if (cond != TCG_COND_NEVER) {
+ TCGv_i64 t0 = tcg_const_i64(arg2);
+ tcg_gen_brcond_i64(cond, arg1, t0, label_index);
+ tcg_temp_free_i64(t0);
+ }
}
static inline void tcg_gen_setcondi_i64(TCGCond cond, TCGv_i64 ret,
diff --git a/tcg/tcg-opc.h b/tcg/tcg-opc.h
index dbb0e3916..04cb7ca03 100644
--- a/tcg/tcg-opc.h
+++ b/tcg/tcg-opc.h
@@ -38,7 +38,6 @@ DEF(discard, 1, 0, 0, 0)
DEF(set_label, 0, 0, 1, TCG_OPF_BB_END)
DEF(call, 0, 1, 2, TCG_OPF_SIDE_EFFECTS) /* variable number of parameters */
-DEF(jmp, 0, 1, 0, TCG_OPF_BB_END | TCG_OPF_SIDE_EFFECTS)
DEF(br, 0, 0, 1, TCG_OPF_BB_END | TCG_OPF_SIDE_EFFECTS)
#define IMPL(X) (X ? 0 : TCG_OPF_NOT_PRESENT)
diff --git a/tcg/tcg.c b/tcg/tcg.c
index c069e44a0..32cd0c6b6 100644
--- a/tcg/tcg.c
+++ b/tcg/tcg.c
@@ -242,7 +242,6 @@ void tcg_context_init(TCGContext *s)
int *sorted_args;
memset(s, 0, sizeof(*s));
- s->temps = s->static_temps;
s->nb_globals = 0;
/* Count total number of arguments and allocate the corresponding
@@ -864,6 +863,8 @@ static TCGHelperInfo *tcg_find_helper(TCGContext *s, tcg_target_ulong val)
static const char * const cond_name[] =
{
+ [TCG_COND_NEVER] = "never",
+ [TCG_COND_ALWAYS] = "always",
[TCG_COND_EQ] = "eq",
[TCG_COND_NE] = "ne",
[TCG_COND_LT] = "lt",
diff --git a/tcg/tcg.h b/tcg/tcg.h
index af7464a65..7bafe0eeb 100644
--- a/tcg/tcg.h
+++ b/tcg/tcg.h
@@ -266,18 +266,28 @@ typedef int TCGv_i64;
#define TCG_CALL_DUMMY_TCGV MAKE_TCGV_I32(-1)
#define TCG_CALL_DUMMY_ARG ((TCGArg)(-1))
+/* Conditions. Note that these are layed out for easy manipulation by
+ the the functions below:
+ bit 0 is used for inverting;
+ bit 1 is signed,
+ bit 2 is unsigned,
+ bit 3 is used with bit 0 for swapping signed/unsigned. */
typedef enum {
- TCG_COND_EQ,
- TCG_COND_NE,
- TCG_COND_LT,
- TCG_COND_GE,
- TCG_COND_LE,
- TCG_COND_GT,
+ /* non-signed */
+ TCG_COND_NEVER = 0 | 0 | 0 | 0,
+ TCG_COND_ALWAYS = 0 | 0 | 0 | 1,
+ TCG_COND_EQ = 8 | 0 | 0 | 0,
+ TCG_COND_NE = 8 | 0 | 0 | 1,
+ /* signed */
+ TCG_COND_LT = 0 | 0 | 2 | 0,
+ TCG_COND_GE = 0 | 0 | 2 | 1,
+ TCG_COND_LE = 8 | 0 | 2 | 0,
+ TCG_COND_GT = 8 | 0 | 2 | 1,
/* unsigned */
- TCG_COND_LTU,
- TCG_COND_GEU,
- TCG_COND_LEU,
- TCG_COND_GTU,
+ TCG_COND_LTU = 0 | 4 | 0 | 0,
+ TCG_COND_GEU = 0 | 4 | 0 | 1,
+ TCG_COND_LEU = 8 | 4 | 0 | 0,
+ TCG_COND_GTU = 8 | 4 | 0 | 1,
} TCGCond;
/* Invert the sense of the comparison. */
@@ -289,13 +299,34 @@ static inline TCGCond tcg_invert_cond(TCGCond c)
/* Swap the operands in a comparison. */
static inline TCGCond tcg_swap_cond(TCGCond c)
{
- int mask = (c < TCG_COND_LT ? 0 : c < TCG_COND_LTU ? 7 : 15);
- return (TCGCond)(c ^ mask);
+ return c & 6 ? (TCGCond)(c ^ 9) : c;
}
+/* Create an "unsigned" version of a "signed" comparison. */
static inline TCGCond tcg_unsigned_cond(TCGCond c)
{
- return (c >= TCG_COND_LT && c <= TCG_COND_GT ? c + 4 : c);
+ return c & 2 ? (TCGCond)(c ^ 6) : c;
+}
+
+/* Must a comparison be considered unsigned? */
+static inline bool is_unsigned_cond(TCGCond c)
+{
+ return (c & 4) != 0;
+}
+
+/* Create a "high" version of a double-word comparison.
+ This removes equality from a LTE or GTE comparison. */
+static inline TCGCond tcg_high_cond(TCGCond c)
+{
+ switch (c) {
+ case TCG_COND_GE:
+ case TCG_COND_LE:
+ case TCG_COND_GEU:
+ case TCG_COND_LEU:
+ return (TCGCond)(c ^ 8);
+ default:
+ return c;
+ }
}
#define TEMP_VAL_DEAD 0
@@ -336,7 +367,6 @@ struct TCGContext {
TCGPool *pool_first, *pool_current, *pool_first_large;
TCGLabel *labels;
int nb_labels;
- TCGTemp *temps; /* globals first, temps after */
int nb_globals;
int nb_temps;
/* index of free temps, -1 if none */
@@ -362,7 +392,7 @@ struct TCGContext {
int frame_reg;
uint8_t *code_ptr;
- TCGTemp static_temps[TCG_MAX_TEMPS];
+ TCGTemp temps[TCG_MAX_TEMPS]; /* globals first, temps after */
TCGHelperInfo *helpers;
int nb_helpers;
diff --git a/tcg/tci/tcg-target.c b/tcg/tci/tcg-target.c
index d272a906e..e93074083 100644
--- a/tcg/tci/tcg-target.c
+++ b/tcg/tci/tcg-target.c
@@ -69,7 +69,6 @@ static const TCGTargetOpDef tcg_target_op_defs[] = {
{ INDEX_op_exit_tb, { NULL } },
{ INDEX_op_goto_tb, { NULL } },
{ INDEX_op_call, { RI } },
- { INDEX_op_jmp, { RI } },
{ INDEX_op_br, { NULL } },
{ INDEX_op_mov_i32, { R, R } },
@@ -583,9 +582,6 @@ static void tcg_out_op(TCGContext *s, TCGOpcode opc, const TCGArg *args,
case INDEX_op_call:
tcg_out_ri(s, const_args[0], args[0]);
break;
- case INDEX_op_jmp:
- TODO();
- break;
case INDEX_op_setcond_i32:
tcg_out_r(s, args[0]);
tcg_out_r(s, args[1]);
diff --git a/tci.c b/tci.c
index a4f7b7841..98f5f713e 100644
--- a/tci.c
+++ b/tci.c
@@ -505,7 +505,6 @@ tcg_target_ulong tcg_qemu_tb_exec(CPUArchState *cpustate, uint8_t *tb_ptr)
tci_write_reg(TCG_REG_R0, tmp64);
#endif
break;
- case INDEX_op_jmp:
case INDEX_op_br:
label = tci_read_label(&tb_ptr);
assert(tb_ptr == old_code_ptr + op_size);
diff --git a/ui/vnc-auth-sasl.c b/ui/vnc-auth-sasl.c
index bfdcb46ef..f3ad75d52 100644
--- a/ui/vnc-auth-sasl.c
+++ b/ui/vnc-auth-sasl.c
@@ -617,7 +617,6 @@ void start_auth_sasl(VncState *vs)
authabort:
vnc_client_error(vs);
- return;
}
diff --git a/ui/vnc-tls.c b/ui/vnc-tls.c
index 3aaa93928..a7f7d07ac 100644
--- a/ui/vnc-tls.c
+++ b/ui/vnc-tls.c
@@ -49,7 +49,7 @@ static int vnc_tls_initialize(void)
if (gnutls_global_init () < 0)
return 0;
- /* XXX ought to re-generate diffie-hellmen params periodically */
+ /* XXX ought to re-generate diffie-hellman params periodically */
if (gnutls_dh_params_init (&dh_params) < 0)
return 0;
if (gnutls_dh_params_generate2 (dh_params, DH_BITS) < 0)
diff --git a/vl.c b/vl.c
index 19cdc7ede..a1c0aa7c5 100644
--- a/vl.c
+++ b/vl.c
@@ -1023,7 +1023,6 @@ static void numa_add(const char *optarg)
}
nb_numa_nodes++;
}
- return;
}
static void smp_parse(const char *optarg)
@@ -1700,17 +1699,23 @@ static const QEMUOption qemu_options[] = {
static bool vga_available(void)
{
- return qdev_exists("VGA") || qdev_exists("isa-vga");
+ return object_class_by_name("VGA") || object_class_by_name("isa-vga");
}
static bool cirrus_vga_available(void)
{
- return qdev_exists("cirrus-vga") || qdev_exists("isa-cirrus-vga");
+ return object_class_by_name("cirrus-vga")
+ || object_class_by_name("isa-cirrus-vga");
}
static bool vmware_vga_available(void)
{
- return qdev_exists("vmware-svga");
+ return object_class_by_name("vmware-svga");
+}
+
+static bool qxl_vga_available(void)
+{
+ return object_class_by_name("qxl-vga");
}
static void select_vgahw (const char *p)
@@ -1742,7 +1747,12 @@ static void select_vgahw (const char *p)
} else if (strstart(p, "xenfb", &opts)) {
vga_interface_type = VGA_XENFB;
} else if (strstart(p, "qxl", &opts)) {
- vga_interface_type = VGA_QXL;
+ if (qxl_vga_available()) {
+ vga_interface_type = VGA_QXL;
+ } else {
+ fprintf(stderr, "Error: QXL VGA not available\n");
+ exit(0);
+ }
} else if (!strstart(p, "none", &opts)) {
invalid_vga:
fprintf(stderr, "Unknown vga type: %s\n", p);
@@ -3641,8 +3651,12 @@ int main(int argc, char **argv, char **envp)
exit(1);
/* If no default VGA is requested, the default is "none". */
- if (default_vga && cirrus_vga_available()) {
- vga_model = "cirrus";
+ if (default_vga) {
+ if (cirrus_vga_available()) {
+ vga_model = "cirrus";
+ } else if (vga_available()) {
+ vga_model = "std";
+ }
}
select_vgahw(vga_model);
diff --git a/xen-all.c b/xen-all.c
index e6308be23..bcb7ef7c8 100644
--- a/xen-all.c
+++ b/xen-all.c
@@ -1092,7 +1092,6 @@ static void xen_read_physmap(XenIOState *state)
QLIST_INSERT_HEAD(&state->physmap, physmap, list);
}
free(entries);
- return;
}
int xen_hvm_init(void)