summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--.dir-locals.el2
-rw-r--r--.travis.yml10
-rw-r--r--MAINTAINERS1
-rw-r--r--block/ssh.c5
-rw-r--r--bsd-user/main.c2
-rwxr-xr-xconfigure2
-rw-r--r--cpus.c6
-rw-r--r--docs/tracing.txt10
-rw-r--r--gdb-xml/s390-virt.xml18
-rw-r--r--hw/char/etraxfs_ser.c4
-rw-r--r--hw/char/imx_serial.c4
-rw-r--r--hw/i386/kvm/pci-assign.c1
-rw-r--r--hw/i386/pc.c4
-rw-r--r--hw/intc/xics.c2
-rw-r--r--hw/mem/pc-dimm.c5
-rw-r--r--hw/net/rocker/rocker.c2
-rw-r--r--hw/net/rocker/rocker_desc.c4
-rw-r--r--hw/net/rocker/rocker_fp.c2
-rw-r--r--hw/net/rocker/rocker_of_dpa.c9
-rw-r--r--hw/ppc/ppc.c4
-rw-r--r--hw/s390x/event-facility.c20
-rw-r--r--hw/s390x/s390-virtio-ccw.c2
-rw-r--r--hw/sd/sdhci.c43
-rw-r--r--hw/timer/m48t59.c4
-rw-r--r--hw/vfio/common.c140
-rw-r--r--hw/vfio/platform.c116
-rw-r--r--include/exec/exec-all.h23
-rw-r--r--include/exec/memory.h13
-rw-r--r--include/hw/vfio/vfio-common.h23
-rw-r--r--include/hw/vfio/vfio-platform.h4
-rw-r--r--include/qemu/timer.h20
-rw-r--r--include/qom/cpu.h16
-rw-r--r--linux-user/elfload.c2
-rw-r--r--linux-user/main.c45
-rw-r--r--linux-user/signal.c159
-rw-r--r--linux-user/syscall.c10
-rw-r--r--linux-user/syscall_defs.h11
-rw-r--r--linux-user/tilegx/syscall.h3
-rw-r--r--memory.c20
-rw-r--r--pc-bios/s390-ccw/Makefile3
-rw-r--r--qapi/block.json2
-rw-r--r--target-alpha/cpu.h1
-rw-r--r--target-alpha/sys_helper.c2
-rw-r--r--target-alpha/translate.c70
-rw-r--r--target-arm/cpu.h2
-rw-r--r--target-arm/translate-a64.c48
-rw-r--r--target-arm/translate.c83
-rw-r--r--target-arm/translate.h8
-rw-r--r--target-cris/cpu.h1
-rw-r--r--target-cris/translate.c93
-rw-r--r--target-cris/translate_v10.c3
-rw-r--r--target-i386/cpu.h2
-rw-r--r--target-i386/translate.c106
-rw-r--r--target-lm32/cpu.h1
-rw-r--r--target-lm32/translate.c83
-rw-r--r--target-m68k/cpu.h1
-rw-r--r--target-m68k/translate.c82
-rw-r--r--target-microblaze/cpu.h1
-rw-r--r--target-microblaze/op_helper.c4
-rw-r--r--target-microblaze/translate.c83
-rw-r--r--target-mips/cpu.h2
-rw-r--r--target-mips/translate.c98
-rw-r--r--target-moxie/cpu.h1
-rw-r--r--target-moxie/translate.c82
-rw-r--r--target-openrisc/cpu.h1
-rw-r--r--target-openrisc/translate.c78
-rw-r--r--target-ppc/cpu.h1
-rw-r--r--target-ppc/kvm.c3
-rw-r--r--target-ppc/translate.c72
-rw-r--r--target-s390x/cpu.h4
-rw-r--r--target-s390x/gdbstub.c82
-rw-r--r--target-s390x/misc_helper.c4
-rw-r--r--target-s390x/translate.c80
-rw-r--r--target-sh4/cpu.h2
-rw-r--r--target-sh4/translate.c91
-rw-r--r--target-sparc/cpu.h2
-rw-r--r--target-sparc/translate.c185
-rw-r--r--target-tilegx/cpu.c7
-rw-r--r--target-tilegx/cpu.h9
-rw-r--r--target-tilegx/helper.c81
-rw-r--r--target-tilegx/helper.h16
-rw-r--r--target-tilegx/simd_helper.c118
-rw-r--r--target-tilegx/translate.c496
-rw-r--r--target-tricore/translate.c59
-rw-r--r--target-unicore32/translate.c83
-rw-r--r--target-xtensa/cpu.h1
-rw-r--r--target-xtensa/translate.c79
-rw-r--r--tcg/tcg-op.h52
-rw-r--r--tcg/tcg-opc.h4
-rw-r--r--tcg/tcg.c168
-rw-r--r--tcg/tcg.h20
-rw-r--r--tci.c9
-rw-r--r--tests/test-string-output-visitor.c16
-rw-r--r--trace-events7
-rw-r--r--translate-all.c520
-rw-r--r--vl.c27
96 files changed, 2176 insertions, 1834 deletions
diff --git a/.dir-locals.el b/.dir-locals.el
new file mode 100644
index 0000000..3ac0cfc
--- /dev/null
+++ b/.dir-locals.el
@@ -0,0 +1,2 @@
+((c-mode . ((c-file-style . "stroustrup")
+ (indent-tabs-mode . nil))))
diff --git a/.travis.yml b/.travis.yml
index 0ac170b..6ca0260 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -54,15 +54,7 @@ matrix:
include:
# Make check target (we only do this once)
- env:
- - TARGETS=alpha-softmmu,arm-softmmu,aarch64-softmmu,cris-softmmu,
- i386-softmmu,x86_64-softmmu,m68k-softmmu,microblaze-softmmu,
- microblazeel-softmmu,mips-softmmu,mips64-softmmu,
- mips64el-softmmu,mipsel-softmmu,or32-softmmu,ppc-softmmu,
- ppc64-softmmu,ppcemb-softmmu,s390x-softmmu,sh4-softmmu,
- sh4eb-softmmu,sparc-softmmu,sparc64-softmmu,
- unicore32-softmmu,unicore32-linux-user,
- lm32-softmmu,moxie-softmmu,tricore-softmmu,xtensa-softmmu,
- xtensaeb-softmmu
+ - TARGETS=alpha-softmmu,arm-softmmu,aarch64-softmmu,cris-softmmu,i386-softmmu,x86_64-softmmu,m68k-softmmu,microblaze-softmmu,microblazeel-softmmu,mips-softmmu,mips64-softmmu,mips64el-softmmu,mipsel-softmmu,or32-softmmu,ppc-softmmu,ppc64-softmmu,ppcemb-softmmu,s390x-softmmu,sh4-softmmu,sh4eb-softmmu,sparc-softmmu,sparc64-softmmu,unicore32-softmmu,unicore32-linux-user,lm32-softmmu,moxie-softmmu,tricore-softmmu,xtensa-softmmu,xtensaeb-softmmu
TEST_CMD="make check"
compiler: gcc
# Debug related options
diff --git a/MAINTAINERS b/MAINTAINERS
index 7603ea2..9bde832 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -275,6 +275,7 @@ L: qemu-devel@nongnu.org
M: Stefan Weil <sw@weilnetz.de>
S: Maintained
F: *win32*
+F: qemu.nsi
ARM Machines
------------
diff --git a/block/ssh.c b/block/ssh.c
index 8d06739..d35b51f 100644
--- a/block/ssh.c
+++ b/block/ssh.c
@@ -193,7 +193,7 @@ sftp_error_report(BDRVSSHState *s, const char *fs, ...)
static int parse_uri(const char *filename, QDict *options, Error **errp)
{
URI *uri = NULL;
- QueryParams *qp = NULL;
+ QueryParams *qp;
int i;
uri = uri_parse(filename);
@@ -249,9 +249,6 @@ static int parse_uri(const char *filename, QDict *options, Error **errp)
return 0;
err:
- if (qp) {
- query_params_free(qp);
- }
if (uri) {
uri_free(uri);
}
diff --git a/bsd-user/main.c b/bsd-user/main.c
index f0a1268..adf2de0 100644
--- a/bsd-user/main.c
+++ b/bsd-user/main.c
@@ -108,7 +108,7 @@ void cpu_list_unlock(void)
uint64_t cpu_get_tsc(CPUX86State *env)
{
- return cpu_get_real_ticks();
+ return cpu_get_host_ticks();
}
static void write_dt(void *ptr, unsigned long addr, unsigned long limit,
diff --git a/configure b/configure
index 1d0559a..f08327e 100755
--- a/configure
+++ b/configure
@@ -5497,7 +5497,7 @@ case "$target_name" in
echo "TARGET_ABI32=y" >> $config_target_mak
;;
s390x)
- gdb_xml_files="s390x-core64.xml s390-acr.xml s390-fpr.xml s390-vx.xml s390-cr.xml"
+ gdb_xml_files="s390x-core64.xml s390-acr.xml s390-fpr.xml s390-vx.xml s390-cr.xml s390-virt.xml"
;;
tilegx)
;;
diff --git a/cpus.c b/cpus.c
index d44c0ed..d2e9e4f 100644
--- a/cpus.c
+++ b/cpus.c
@@ -199,7 +199,7 @@ int64_t cpu_get_ticks(void)
ticks = timers_state.cpu_ticks_offset;
if (timers_state.cpu_ticks_enabled) {
- ticks += cpu_get_real_ticks();
+ ticks += cpu_get_host_ticks();
}
if (timers_state.cpu_ticks_prev > ticks) {
@@ -247,7 +247,7 @@ void cpu_enable_ticks(void)
/* Here, the really thing protected by seqlock is cpu_clock_offset. */
seqlock_write_lock(&timers_state.vm_clock_seqlock);
if (!timers_state.cpu_ticks_enabled) {
- timers_state.cpu_ticks_offset -= cpu_get_real_ticks();
+ timers_state.cpu_ticks_offset -= cpu_get_host_ticks();
timers_state.cpu_clock_offset -= get_clock();
timers_state.cpu_ticks_enabled = 1;
}
@@ -263,7 +263,7 @@ void cpu_disable_ticks(void)
/* Here, the really thing protected by seqlock is cpu_clock_offset. */
seqlock_write_lock(&timers_state.vm_clock_seqlock);
if (timers_state.cpu_ticks_enabled) {
- timers_state.cpu_ticks_offset += cpu_get_real_ticks();
+ timers_state.cpu_ticks_offset += cpu_get_host_ticks();
timers_state.cpu_clock_offset = cpu_get_clock_locked();
timers_state.cpu_ticks_enabled = 0;
}
diff --git a/docs/tracing.txt b/docs/tracing.txt
index 7117c5e..3853a6a 100644
--- a/docs/tracing.txt
+++ b/docs/tracing.txt
@@ -258,11 +258,11 @@ is generated to make use in scripts more convenient. This step can also be
performed manually after a build in order to change the binary name in the .stp
probes:
- scripts/tracetool --dtrace --stap \
- --binary path/to/qemu-binary \
- --target-type system \
- --target-name x86_64 \
- <trace-events >qemu.stp
+ scripts/tracetool.py --backends=dtrace --format=stap \
+ --binary path/to/qemu-binary \
+ --target-type system \
+ --target-name x86_64 \
+ <trace-events >qemu.stp
== Trace event properties ==
diff --git a/gdb-xml/s390-virt.xml b/gdb-xml/s390-virt.xml
new file mode 100644
index 0000000..e2e9a7a
--- /dev/null
+++ b/gdb-xml/s390-virt.xml
@@ -0,0 +1,18 @@
+<?xml version="1.0"?>
+<!-- Copyright 2015 IBM Corp.
+
+ This work is licensed under the terms of the GNU GPL, version 2 or
+ (at your option) any later version. See the COPYING file in the
+ top-level directory. -->
+
+<!DOCTYPE feature SYSTEM "gdb-target.dtd">
+<feature name="org.gnu.gdb.s390.virt">
+ <reg name="ckc" bitsize="64" type="uint64" group="system"/>
+ <reg name="cputm" bitsize="64" type="uint64" group="system"/>
+ <reg name="last_break" bitsize="64" type="code_ptr" group="system"/>
+ <reg name="prefix" bitsize="64" type="data_ptr" group="system"/>
+ <reg name="pp" bitsize="64" type="uint64" group="system"/>
+ <reg name="pfault_token" bitsize="64" type="uint64" group="system"/>
+ <reg name="pfault_select" bitsize="64" type="uint64" group="system"/>
+ <reg name="pfault_compare" bitsize="64" type="uint64" group="system"/>
+</feature>
diff --git a/hw/char/etraxfs_ser.c b/hw/char/etraxfs_ser.c
index 857c136..562021e 100644
--- a/hw/char/etraxfs_ser.c
+++ b/hw/char/etraxfs_ser.c
@@ -182,15 +182,13 @@ static void serial_receive(void *opaque, const uint8_t *buf, int size)
static int serial_can_receive(void *opaque)
{
ETRAXSerial *s = opaque;
- int r;
/* Is the receiver enabled? */
if (!(s->regs[RW_REC_CTRL] & (1 << 3))) {
return 0;
}
- r = sizeof(s->rx_fifo) - s->rx_fifo_len;
- return r;
+ return sizeof(s->rx_fifo) - s->rx_fifo_len;
}
static void serial_event(void *opaque, int event)
diff --git a/hw/char/imx_serial.c b/hw/char/imx_serial.c
index e8f32c4..f0c4c72 100644
--- a/hw/char/imx_serial.c
+++ b/hw/char/imx_serial.c
@@ -66,7 +66,9 @@ static void imx_update(IMXSerialState *s)
uint32_t flags;
flags = (s->usr1 & s->ucr1) & (USR1_TRDY|USR1_RRDY);
- if (!(s->ucr1 & UCR1_TXMPTYEN)) {
+ if (s->ucr1 & UCR1_TXMPTYEN) {
+ flags |= (s->uts1 & UTS1_TXEMPTY);
+ } else {
flags &= ~USR1_TRDY;
}
diff --git a/hw/i386/kvm/pci-assign.c b/hw/i386/kvm/pci-assign.c
index b1beaa6..44beee3 100644
--- a/hw/i386/kvm/pci-assign.c
+++ b/hw/i386/kvm/pci-assign.c
@@ -22,7 +22,6 @@
*/
#include <stdio.h>
#include <unistd.h>
-#include <sys/io.h>
#include <sys/mman.h>
#include <sys/types.h>
#include <sys/stat.h>
diff --git a/hw/i386/pc.c b/hw/i386/pc.c
index 9275297..682867a 100644
--- a/hw/i386/pc.c
+++ b/hw/i386/pc.c
@@ -985,6 +985,10 @@ static void load_linux(PCMachineState *pcms,
setup_size = 4;
}
setup_size = (setup_size+1)*512;
+ if (setup_size > kernel_size) {
+ fprintf(stderr, "qemu: invalid kernel header\n");
+ exit(1);
+ }
kernel_size -= setup_size;
setup = g_malloc(setup_size);
diff --git a/hw/intc/xics.c b/hw/intc/xics.c
index 67881c7..9ff5796 100644
--- a/hw/intc/xics.c
+++ b/hw/intc/xics.c
@@ -848,7 +848,7 @@ static target_ulong h_xirr_x(PowerPCCPU *cpu, sPAPRMachineState *spapr,
uint32_t xirr = icp_accept(ss);
args[0] = xirr;
- args[1] = cpu_get_real_ticks();
+ args[1] = cpu_get_host_ticks();
return H_SUCCESS;
}
diff --git a/hw/mem/pc-dimm.c b/hw/mem/pc-dimm.c
index 6cc6ac3..506fe0d 100644
--- a/hw/mem/pc-dimm.c
+++ b/hw/mem/pc-dimm.c
@@ -417,10 +417,11 @@ static void pc_dimm_realize(DeviceState *dev, Error **errp)
error_setg(errp, "'" PC_DIMM_MEMDEV_PROP "' property is not set");
return;
}
- if ((nb_numa_nodes > 0) && (dimm->node >= nb_numa_nodes)) {
+ if (((nb_numa_nodes > 0) && (dimm->node >= nb_numa_nodes)) ||
+ (!nb_numa_nodes && dimm->node)) {
error_setg(errp, "'DIMM property " PC_DIMM_NODE_PROP " has value %"
PRIu32 "' which exceeds the number of numa nodes: %d",
- dimm->node, nb_numa_nodes);
+ dimm->node, nb_numa_nodes ? nb_numa_nodes : 1);
return;
}
}
diff --git a/hw/net/rocker/rocker.c b/hw/net/rocker/rocker.c
index 7e7bda4..bb6fdc3 100644
--- a/hw/net/rocker/rocker.c
+++ b/hw/net/rocker/rocker.c
@@ -1362,7 +1362,7 @@ static int pci_rocker_init(PCIDevice *dev)
r->fp_ports = ROCKER_FP_PORTS_MAX;
}
- r->rings = g_malloc(sizeof(DescRing *) * rocker_pci_ring_count(r));
+ r->rings = g_new(DescRing *, rocker_pci_ring_count(r));
if (!r->rings) {
goto err_rings_alloc;
}
diff --git a/hw/net/rocker/rocker_desc.c b/hw/net/rocker/rocker_desc.c
index b5c0b4a..5e697b1 100644
--- a/hw/net/rocker/rocker_desc.c
+++ b/hw/net/rocker/rocker_desc.c
@@ -142,7 +142,7 @@ bool desc_ring_set_size(DescRing *ring, uint32_t size)
ring->size = size;
ring->head = ring->tail = 0;
- ring->info = g_realloc(ring->info, size * sizeof(DescInfo));
+ ring->info = g_renew(DescInfo, ring->info, size);
if (!ring->info) {
return false;
}
@@ -345,7 +345,7 @@ DescRing *desc_ring_alloc(Rocker *r, int index)
{
DescRing *ring;
- ring = g_malloc0(sizeof(DescRing));
+ ring = g_new0(DescRing, 1);
if (!ring) {
return NULL;
}
diff --git a/hw/net/rocker/rocker_fp.c b/hw/net/rocker/rocker_fp.c
index c693ae5..5906396 100644
--- a/hw/net/rocker/rocker_fp.c
+++ b/hw/net/rocker/rocker_fp.c
@@ -218,7 +218,7 @@ FpPort *fp_port_alloc(Rocker *r, char *sw_name,
MACAddr *start_mac, unsigned int index,
NICPeers *peers)
{
- FpPort *port = g_malloc0(sizeof(FpPort));
+ FpPort *port = g_new0(FpPort, 1);
if (!port) {
return NULL;
diff --git a/hw/net/rocker/rocker_of_dpa.c b/hw/net/rocker/rocker_of_dpa.c
index 874fb01..1ad2791 100644
--- a/hw/net/rocker/rocker_of_dpa.c
+++ b/hw/net/rocker/rocker_of_dpa.c
@@ -367,7 +367,7 @@ static OfDpaFlow *of_dpa_flow_alloc(uint64_t cookie)
OfDpaFlow *flow;
int64_t now = qemu_clock_get_ms(QEMU_CLOCK_VIRTUAL) / 1000;
- flow = g_malloc0(sizeof(OfDpaFlow));
+ flow = g_new0(OfDpaFlow, 1);
if (!flow) {
return NULL;
}
@@ -811,7 +811,7 @@ static int of_dpa_group_get_stats(OfDpa *of_dpa, uint32_t id)
static OfDpaGroup *of_dpa_group_alloc(uint32_t id)
{
- OfDpaGroup *group = g_malloc0(sizeof(OfDpaGroup));
+ OfDpaGroup *group = g_new0(OfDpaGroup, 1);
if (!group) {
return NULL;
@@ -2039,15 +2039,14 @@ static int of_dpa_cmd_add_l2_flood(OfDpa *of_dpa, OfDpaGroup *group,
group->l2_flood.group_count =
rocker_tlv_get_le16(group_tlvs[ROCKER_TLV_OF_DPA_GROUP_COUNT]);
- tlvs = g_malloc0((group->l2_flood.group_count + 1) *
- sizeof(RockerTlv *));
+ tlvs = g_new0(RockerTlv *, group->l2_flood.group_count + 1);
if (!tlvs) {
return -ROCKER_ENOMEM;
}
g_free(group->l2_flood.group_ids);
group->l2_flood.group_ids =
- g_malloc0(group->l2_flood.group_count * sizeof(uint32_t));
+ g_new0(uint32_t, group->l2_flood.group_count);
if (!group->l2_flood.group_ids) {
err = -ROCKER_ENOMEM;
goto err_out;
diff --git a/hw/ppc/ppc.c b/hw/ppc/ppc.c
index b77e303..2c604ef 100644
--- a/hw/ppc/ppc.c
+++ b/hw/ppc/ppc.c
@@ -834,7 +834,7 @@ static void cpu_ppc_set_tb_clk (void *opaque, uint32_t freq)
static void timebase_pre_save(void *opaque)
{
PPCTimebase *tb = opaque;
- uint64_t ticks = cpu_get_real_ticks();
+ uint64_t ticks = cpu_get_host_ticks();
PowerPCCPU *first_ppc_cpu = POWERPC_CPU(first_cpu);
if (!first_ppc_cpu->env.tb_env) {
@@ -878,7 +878,7 @@ static int timebase_post_load(void *opaque, int version_id)
NANOSECONDS_PER_SECOND);
guest_tb = tb_remote->guest_timebase + MIN(0, migration_duration_tb);
- tb_off_adj = guest_tb - cpu_get_real_ticks();
+ tb_off_adj = guest_tb - cpu_get_host_ticks();
tb_off = first_ppc_cpu->env.tb_env->tb_offset;
trace_ppc_tb_adjust(tb_off, tb_off_adj, tb_off_adj - tb_off,
diff --git a/hw/s390x/event-facility.c b/hw/s390x/event-facility.c
index ef2a051..907b485 100644
--- a/hw/s390x/event-facility.c
+++ b/hw/s390x/event-facility.c
@@ -27,8 +27,6 @@ typedef struct SCLPEventsBus {
struct SCLPEventFacility {
SysBusDevice parent_obj;
SCLPEventsBus sbus;
- SCLPEvent quiesce_event;
- SCLPEvent cpu_hotplug_event;
/* guest' receive mask */
unsigned int receive_mask;
};
@@ -347,19 +345,21 @@ static void init_event_facility(Object *obj)
{
SCLPEventFacility *event_facility = EVENT_FACILITY(obj);
DeviceState *sdev = DEVICE(obj);
+ Object *new;
/* Spawn a new bus for SCLP events */
qbus_create_inplace(&event_facility->sbus, sizeof(event_facility->sbus),
TYPE_SCLP_EVENTS_BUS, sdev, NULL);
- object_initialize(&event_facility->quiesce_event, sizeof(SCLPEvent),
- TYPE_SCLP_QUIESCE);
- qdev_set_parent_bus(DEVICE(&event_facility->quiesce_event),
- &event_facility->sbus.qbus);
- object_initialize(&event_facility->cpu_hotplug_event, sizeof(SCLPEvent),
- TYPE_SCLP_CPU_HOTPLUG);
- qdev_set_parent_bus(DEVICE(&event_facility->cpu_hotplug_event),
- &event_facility->sbus.qbus);
+ new = object_new(TYPE_SCLP_QUIESCE);
+ object_property_add_child(obj, TYPE_SCLP_QUIESCE, new, NULL);
+ object_unref(new);
+ qdev_set_parent_bus(DEVICE(new), &event_facility->sbus.qbus);
+
+ new = object_new(TYPE_SCLP_CPU_HOTPLUG);
+ object_property_add_child(obj, TYPE_SCLP_CPU_HOTPLUG, new, NULL);
+ object_unref(new);
+ qdev_set_parent_bus(DEVICE(new), &event_facility->sbus.qbus);
/* the facility will automatically realize the devices via the bus */
}
diff --git a/hw/s390x/s390-virtio-ccw.c b/hw/s390x/s390-virtio-ccw.c
index c53ebc1..6195f13 100644
--- a/hw/s390x/s390-virtio-ccw.c
+++ b/hw/s390x/s390-virtio-ccw.c
@@ -35,7 +35,7 @@ typedef struct S390CcwMachineState {
bool dea_key_wrap;
} S390CcwMachineState;
-void io_subsystem_reset(void)
+void subsystem_reset(void)
{
DeviceState *css, *sclp, *flic, *diag288;
diff --git a/hw/sd/sdhci.c b/hw/sd/sdhci.c
index 65304cf..8b0f9f0 100644
--- a/hw/sd/sdhci.c
+++ b/hw/sd/sdhci.c
@@ -22,6 +22,7 @@
* with this program; if not, see <http://www.gnu.org/licenses/>.
*/
+#include <inttypes.h>
#include "hw/hw.h"
#include "sysemu/block-backend.h"
#include "sysemu/blockdev.h"
@@ -36,24 +37,24 @@
#define SDHC_DEBUG 0
#endif
-#if SDHC_DEBUG == 0
- #define DPRINT_L1(fmt, args...) do { } while (0)
- #define DPRINT_L2(fmt, args...) do { } while (0)
- #define ERRPRINT(fmt, args...) do { } while (0)
-#elif SDHC_DEBUG == 1
- #define DPRINT_L1(fmt, args...) \
- do {fprintf(stderr, "QEMU SDHC: "fmt, ## args); } while (0)
- #define DPRINT_L2(fmt, args...) do { } while (0)
- #define ERRPRINT(fmt, args...) \
- do {fprintf(stderr, "QEMU SDHC ERROR: "fmt, ## args); } while (0)
-#else
- #define DPRINT_L1(fmt, args...) \
- do {fprintf(stderr, "QEMU SDHC: "fmt, ## args); } while (0)
- #define DPRINT_L2(fmt, args...) \
- do {fprintf(stderr, "QEMU SDHC: "fmt, ## args); } while (0)
- #define ERRPRINT(fmt, args...) \
- do {fprintf(stderr, "QEMU SDHC ERROR: "fmt, ## args); } while (0)
-#endif
+#define DPRINT_L1(fmt, args...) \
+ do { \
+ if (SDHC_DEBUG) { \
+ fprintf(stderr, "QEMU SDHC: " fmt, ## args); \
+ } \
+ } while (0)
+#define DPRINT_L2(fmt, args...) \
+ do { \
+ if (SDHC_DEBUG > 1) { \
+ fprintf(stderr, "QEMU SDHC: " fmt, ## args); \
+ } \
+ } while (0)
+#define ERRPRINT(fmt, args...) \
+ do { \
+ if (SDHC_DEBUG) { \
+ fprintf(stderr, "QEMU SDHC ERROR: " fmt, ## args); \
+ } \
+ } while (0)
/* Default SD/MMC host controller features information, which will be
* presented in CAPABILITIES register of generic SD host controller at reset.
@@ -719,7 +720,8 @@ static void sdhci_do_adma(SDHCIState *s)
break;
case SDHC_ADMA_ATTR_ACT_LINK: /* link to next descriptor table */
s->admasysaddr = dscr.addr;
- DPRINT_L1("ADMA link: admasysaddr=0x%lx\n", s->admasysaddr);
+ DPRINT_L1("ADMA link: admasysaddr=0x%" PRIx64 "\n",
+ s->admasysaddr);
break;
default:
s->admasysaddr += dscr.incr;
@@ -727,7 +729,8 @@ static void sdhci_do_adma(SDHCIState *s)
}
if (dscr.attr & SDHC_ADMA_ATTR_INT) {
- DPRINT_L1("ADMA interrupt: admasysaddr=0x%lx\n", s->admasysaddr);
+ DPRINT_L1("ADMA interrupt: admasysaddr=0x%" PRIx64 "\n",
+ s->admasysaddr);
if (s->norintstsen & SDHC_NISEN_DMA) {
s->norintsts |= SDHC_NIS_DMA;
}
diff --git a/hw/timer/m48t59.c b/hw/timer/m48t59.c
index 8ab683d..b3df8f9 100644
--- a/hw/timer/m48t59.c
+++ b/hw/timer/m48t59.c
@@ -590,10 +590,8 @@ static void nvram_writel (void *opaque, hwaddr addr, uint32_t value)
static uint32_t nvram_readb (void *opaque, hwaddr addr)
{
M48t59State *NVRAM = opaque;
- uint32_t retval;
- retval = m48t59_read(NVRAM, addr);
- return retval;
+ return m48t59_read(NVRAM, addr);
}
static uint32_t nvram_readw (void *opaque, hwaddr addr)
diff --git a/hw/vfio/common.c b/hw/vfio/common.c
index 0d341a3..6797208 100644
--- a/hw/vfio/common.c
+++ b/hw/vfio/common.c
@@ -312,11 +312,15 @@ out:
rcu_read_unlock();
}
+static hwaddr vfio_container_granularity(VFIOContainer *container)
+{
+ return (hwaddr)1 << ctz64(container->iova_pgsizes);
+}
+
static void vfio_listener_region_add(MemoryListener *listener,
MemoryRegionSection *section)
{
- VFIOContainer *container = container_of(listener, VFIOContainer,
- iommu_data.type1.listener);
+ VFIOContainer *container = container_of(listener, VFIOContainer, listener);
hwaddr iova, end;
Int128 llend;
void *vaddr;
@@ -344,14 +348,22 @@ static void vfio_listener_region_add(MemoryListener *listener,
if (int128_ge(int128_make64(iova), llend)) {
return;
}
+ end = int128_get64(llend);
+
+ if ((iova < container->min_iova) || ((end - 1) > container->max_iova)) {
+ error_report("vfio: IOMMU container %p can't map guest IOVA region"
+ " 0x%"HWADDR_PRIx"..0x%"HWADDR_PRIx,
+ container, iova, end - 1);
+ ret = -EFAULT;
+ goto fail;
+ }
memory_region_ref(section->mr);
if (memory_region_is_iommu(section->mr)) {
VFIOGuestIOMMU *giommu;
- trace_vfio_listener_region_add_iommu(iova,
- int128_get64(int128_sub(llend, int128_one())));
+ trace_vfio_listener_region_add_iommu(iova, end - 1);
/*
* FIXME: We should do some checking to see if the
* capabilities of the host VFIO IOMMU are adequate to model
@@ -362,33 +374,22 @@ static void vfio_listener_region_add(MemoryListener *listener,
* would be the right place to wire that up (tell the KVM
* device emulation the VFIO iommu handles to use).
*/
- /*
- * This assumes that the guest IOMMU is empty of
- * mappings at this point.
- *
- * One way of doing this is:
- * 1. Avoid sharing IOMMUs between emulated devices or different
- * IOMMU groups.
- * 2. Implement VFIO_IOMMU_ENABLE in the host kernel to fail if
- * there are some mappings in IOMMU.
- *
- * VFIO on SPAPR does that. Other IOMMU models may do that different,
- * they must make sure there are no existing mappings or
- * loop through existing mappings to map them into VFIO.
- */
giommu = g_malloc0(sizeof(*giommu));
giommu->iommu = section->mr;
giommu->container = container;
giommu->n.notify = vfio_iommu_map_notify;
QLIST_INSERT_HEAD(&container->giommu_list, giommu, giommu_next);
+
memory_region_register_iommu_notifier(giommu->iommu, &giommu->n);
+ memory_region_iommu_replay(giommu->iommu, &giommu->n,
+ vfio_container_granularity(container),
+ false);
return;
}
/* Here we assume that memory_region_is_ram(section->mr)==true */
- end = int128_get64(llend);
vaddr = memory_region_get_ram_ptr(section->mr) +
section->offset_within_region +
(iova - section->offset_within_address_space);
@@ -400,27 +401,30 @@ static void vfio_listener_region_add(MemoryListener *listener,
error_report("vfio_dma_map(%p, 0x%"HWADDR_PRIx", "
"0x%"HWADDR_PRIx", %p) = %d (%m)",
container, iova, end - iova, vaddr, ret);
+ goto fail;
+ }
- /*
- * On the initfn path, store the first error in the container so we
- * can gracefully fail. Runtime, there's not much we can do other
- * than throw a hardware error.
- */
- if (!container->iommu_data.type1.initialized) {
- if (!container->iommu_data.type1.error) {
- container->iommu_data.type1.error = ret;
- }
- } else {
- hw_error("vfio: DMA mapping failed, unable to continue");
+ return;
+
+fail:
+ /*
+ * On the initfn path, store the first error in the container so we
+ * can gracefully fail. Runtime, there's not much we can do other
+ * than throw a hardware error.
+ */
+ if (!container->initialized) {
+ if (!container->error) {
+ container->error = ret;
}
+ } else {
+ hw_error("vfio: DMA mapping failed, unable to continue");
}
}
static void vfio_listener_region_del(MemoryListener *listener,
MemoryRegionSection *section)
{
- VFIOContainer *container = container_of(listener, VFIOContainer,
- iommu_data.type1.listener);
+ VFIOContainer *container = container_of(listener, VFIOContainer, listener);
hwaddr iova, end;
int ret;
@@ -485,7 +489,7 @@ static const MemoryListener vfio_memory_listener = {
static void vfio_listener_release(VFIOContainer *container)
{
- memory_listener_unregister(&container->iommu_data.type1.listener);
+ memory_listener_unregister(&container->listener);
}
int vfio_mmap_region(Object *obj, VFIORegion *region,
@@ -668,6 +672,7 @@ static int vfio_connect_container(VFIOGroup *group, AddressSpace *as)
if (ioctl(fd, VFIO_CHECK_EXTENSION, VFIO_TYPE1_IOMMU) ||
ioctl(fd, VFIO_CHECK_EXTENSION, VFIO_TYPE1v2_IOMMU)) {
bool v2 = !!ioctl(fd, VFIO_CHECK_EXTENSION, VFIO_TYPE1v2_IOMMU);
+ struct vfio_iommu_type1_info info;
ret = ioctl(group->fd, VFIO_GROUP_SET_CONTAINER, &fd);
if (ret) {
@@ -684,21 +689,27 @@ static int vfio_connect_container(VFIOGroup *group, AddressSpace *as)
goto free_container_exit;
}
- container->iommu_data.type1.listener = vfio_memory_listener;
- container->iommu_data.release = vfio_listener_release;
-
- memory_listener_register(&container->iommu_data.type1.listener,
- container->space->as);
-
- if (container->iommu_data.type1.error) {
- ret = container->iommu_data.type1.error;
- error_report("vfio: memory listener initialization failed for container");
- goto listener_release_exit;
+ /*
+ * FIXME: This assumes that a Type1 IOMMU can map any 64-bit
+ * IOVA whatsoever. That's not actually true, but the current
+ * kernel interface doesn't tell us what it can map, and the
+ * existing Type1 IOMMUs generally support any IOVA we're
+ * going to actually try in practice.
+ */
+ container->min_iova = 0;
+ container->max_iova = (hwaddr)-1;
+
+ /* Assume just 4K IOVA page size */
+ container->iova_pgsizes = 0x1000;
+ info.argsz = sizeof(info);
+ ret = ioctl(fd, VFIO_IOMMU_GET_INFO, &info);
+ /* Ignore errors */
+ if ((ret == 0) && (info.flags & VFIO_IOMMU_INFO_PGSIZES)) {
+ container->iova_pgsizes = info.iova_pgsizes;
}
-
- container->iommu_data.type1.initialized = true;
-
} else if (ioctl(fd, VFIO_CHECK_EXTENSION, VFIO_SPAPR_TCE_IOMMU)) {
+ struct vfio_iommu_spapr_tce_info info;
+
ret = ioctl(group->fd, VFIO_GROUP_SET_CONTAINER, &fd);
if (ret) {
error_report("vfio: failed to set group container: %m");
@@ -724,18 +735,41 @@ static int vfio_connect_container(VFIOGroup *group, AddressSpace *as)
goto free_container_exit;
}
- container->iommu_data.type1.listener = vfio_memory_listener;
- container->iommu_data.release = vfio_listener_release;
-
- memory_listener_register(&container->iommu_data.type1.listener,
- container->space->as);
+ /*
+ * This only considers the host IOMMU's 32-bit window. At
+ * some point we need to add support for the optional 64-bit
+ * window and dynamic windows
+ */
+ info.argsz = sizeof(info);
+ ret = ioctl(fd, VFIO_IOMMU_SPAPR_TCE_GET_INFO, &info);
+ if (ret) {
+ error_report("vfio: VFIO_IOMMU_SPAPR_TCE_GET_INFO failed: %m");
+ ret = -errno;
+ goto free_container_exit;
+ }
+ container->min_iova = info.dma32_window_start;
+ container->max_iova = container->min_iova + info.dma32_window_size - 1;
+ /* Assume just 4K IOVA pages for now */
+ container->iova_pgsizes = 0x1000;
} else {
error_report("vfio: No available IOMMU models");
ret = -EINVAL;
goto free_container_exit;
}
+ container->listener = vfio_memory_listener;
+
+ memory_listener_register(&container->listener, container->space->as);
+
+ if (container->error) {
+ ret = container->error;
+ error_report("vfio: memory listener initialization failed for container");
+ goto listener_release_exit;
+ }
+
+ container->initialized = true;
+
QLIST_INIT(&container->group_list);
QLIST_INSERT_HEAD(&space->containers, container, next);
@@ -774,9 +808,7 @@ static void vfio_disconnect_container(VFIOGroup *group)
VFIOAddressSpace *space = container->space;
VFIOGuestIOMMU *giommu, *tmp;
- if (container->iommu_data.release) {
- container->iommu_data.release(container);
- }
+ vfio_listener_release(container);
QLIST_REMOVE(container, next);
QLIST_FOREACH_SAFE(giommu, &container->giommu_list, giommu_next, tmp) {
diff --git a/hw/vfio/platform.c b/hw/vfio/platform.c
index a6726cd..5c1156c 100644
--- a/hw/vfio/platform.c
+++ b/hw/vfio/platform.c
@@ -32,6 +32,11 @@
* Functions used whatever the injection method
*/
+static inline bool vfio_irq_is_automasked(VFIOINTp *intp)
+{
+ return intp->flags & VFIO_IRQ_INFO_AUTOMASKED;
+}
+
/**
* vfio_init_intp - allocate, initialize the IRQ struct pointer
* and add it into the list of IRQs
@@ -57,18 +62,25 @@ static VFIOINTp *vfio_init_intp(VFIODevice *vbasedev,
sysbus_init_irq(sbdev, &intp->qemuirq);
/* Get an eventfd for trigger */
- ret = event_notifier_init(&intp->interrupt, 0);
+ intp->interrupt = g_malloc0(sizeof(EventNotifier));
+ ret = event_notifier_init(intp->interrupt, 0);
if (ret) {
+ g_free(intp->interrupt);
g_free(intp);
error_report("vfio: Error: trigger event_notifier_init failed ");
return NULL;
}
- /* Get an eventfd for resample/unmask */
- ret = event_notifier_init(&intp->unmask, 0);
- if (ret) {
- g_free(intp);
- error_report("vfio: Error: resamplefd event_notifier_init failed");
- return NULL;
+ if (vfio_irq_is_automasked(intp)) {
+ /* Get an eventfd for resample/unmask */
+ intp->unmask = g_malloc0(sizeof(EventNotifier));
+ ret = event_notifier_init(intp->unmask, 0);
+ if (ret) {
+ g_free(intp->interrupt);
+ g_free(intp->unmask);
+ g_free(intp);
+ error_report("vfio: Error: resamplefd event_notifier_init failed");
+ return NULL;
+ }
}
QLIST_INSERT_HEAD(&vdev->intp_list, intp, next);
@@ -100,7 +112,7 @@ static int vfio_set_trigger_eventfd(VFIOINTp *intp,
irq_set->start = 0;
irq_set->count = 1;
pfd = (int32_t *)&irq_set->data;
- *pfd = event_notifier_get_fd(&intp->interrupt);
+ *pfd = event_notifier_get_fd(intp->interrupt);
qemu_set_fd_handler(*pfd, (IOHandler *)handler, NULL, intp);
ret = ioctl(vbasedev->fd, VFIO_DEVICE_SET_IRQS, irq_set);
g_free(irq_set);
@@ -182,7 +194,7 @@ static void vfio_intp_mmap_enable(void *opaque)
static void vfio_intp_inject_pending_lockheld(VFIOINTp *intp)
{
trace_vfio_platform_intp_inject_pending_lockheld(intp->pin,
- event_notifier_get_fd(&intp->interrupt));
+ event_notifier_get_fd(intp->interrupt));
intp->state = VFIO_IRQ_ACTIVE;
@@ -224,18 +236,18 @@ static void vfio_intp_interrupt(VFIOINTp *intp)
trace_vfio_intp_interrupt_set_pending(intp->pin);
QSIMPLEQ_INSERT_TAIL(&vdev->pending_intp_queue,
intp, pqnext);
- ret = event_notifier_test_and_clear(&intp->interrupt);
+ ret = event_notifier_test_and_clear(intp->interrupt);
qemu_mutex_unlock(&vdev->intp_mutex);
return;
}
trace_vfio_platform_intp_interrupt(intp->pin,
- event_notifier_get_fd(&intp->interrupt));
+ event_notifier_get_fd(intp->interrupt));
- ret = event_notifier_test_and_clear(&intp->interrupt);
+ ret = event_notifier_test_and_clear(intp->interrupt);
if (!ret) {
error_report("Error when clearing fd=%d (ret = %d)",
- event_notifier_get_fd(&intp->interrupt), ret);
+ event_notifier_get_fd(intp->interrupt), ret);
}
intp->state = VFIO_IRQ_ACTIVE;
@@ -283,13 +295,13 @@ static void vfio_platform_eoi(VFIODevice *vbasedev)
QLIST_FOREACH(intp, &vdev->intp_list, next) {
if (intp->state == VFIO_IRQ_ACTIVE) {
trace_vfio_platform_eoi(intp->pin,
- event_notifier_get_fd(&intp->interrupt));
+ event_notifier_get_fd(intp->interrupt));
intp->state = VFIO_IRQ_INACTIVE;
/* deassert the virtual IRQ */
qemu_set_irq(intp->qemuirq, 0);
- if (intp->flags & VFIO_IRQ_INFO_AUTOMASKED) {
+ if (vfio_irq_is_automasked(intp)) {
/* unmasks the physical level-sensitive IRQ */
vfio_unmask_single_irqindex(vbasedev, intp->pin);
}
@@ -310,18 +322,29 @@ static void vfio_platform_eoi(VFIODevice *vbasedev)
/**
* vfio_start_eventfd_injection - starts the virtual IRQ injection using
* user-side handled eventfds
- * @intp: the IRQ struct pointer
+ * @sbdev: the sysbus device handle
+ * @irq: the qemu irq handle
*/
-static int vfio_start_eventfd_injection(VFIOINTp *intp)
+static void vfio_start_eventfd_injection(SysBusDevice *sbdev, qemu_irq irq)
{
int ret;
+ VFIOPlatformDevice *vdev = VFIO_PLATFORM_DEVICE(sbdev);
+ VFIOINTp *intp;
+
+ QLIST_FOREACH(intp, &vdev->intp_list, next) {
+ if (intp->qemuirq == irq) {
+ break;
+ }
+ }
+ assert(intp);
ret = vfio_set_trigger_eventfd(intp, vfio_intp_interrupt);
if (ret) {
- error_report("vfio: Error: Failed to pass IRQ fd to the driver: %m");
+ error_report("vfio: failed to start eventfd signaling for IRQ %d: %m",
+ intp->pin);
+ abort();
}
- return ret;
}
/*
@@ -349,7 +372,7 @@ static int vfio_set_resample_eventfd(VFIOINTp *intp)
irq_set->start = 0;
irq_set->count = 1;
pfd = (int32_t *)&irq_set->data;
- *pfd = event_notifier_get_fd(&intp->unmask);
+ *pfd = event_notifier_get_fd(intp->unmask);
qemu_set_fd_handler(*pfd, NULL, NULL, NULL);
ret = ioctl(vbasedev->fd, VFIO_DEVICE_SET_IRQS, irq_set);
g_free(irq_set);
@@ -359,6 +382,15 @@ static int vfio_set_resample_eventfd(VFIOINTp *intp)
return ret;
}
+/**
+ * vfio_start_irqfd_injection - starts the virtual IRQ injection using
+ * irqfd
+ *
+ * @sbdev: the sysbus device handle
+ * @irq: the qemu irq handle
+ *
+ * In case the irqfd setup fails, we fallback to userspace handled eventfd
+ */
static void vfio_start_irqfd_injection(SysBusDevice *sbdev, qemu_irq irq)
{
VFIOPlatformDevice *vdev = VFIO_PLATFORM_DEVICE(sbdev);
@@ -366,7 +398,7 @@ static void vfio_start_irqfd_injection(SysBusDevice *sbdev, qemu_irq irq)
if (!kvm_irqfds_enabled() || !kvm_resamplefds_enabled() ||
!vdev->irqfd_allowed) {
- return;
+ goto fail_irqfd;
}
QLIST_FOREACH(intp, &vdev->intp_list, next) {
@@ -376,39 +408,36 @@ static void vfio_start_irqfd_injection(SysBusDevice *sbdev, qemu_irq irq)
}
assert(intp);
- /* Get to a known interrupt state */
- qemu_set_fd_handler(event_notifier_get_fd(&intp->interrupt),
- NULL, NULL, vdev);
-
- vfio_mask_single_irqindex(&vdev->vbasedev, intp->pin);
- qemu_set_irq(intp->qemuirq, 0);
-
- if (kvm_irqchip_add_irqfd_notifier(kvm_state, &intp->interrupt,
- &intp->unmask, irq) < 0) {
+ if (kvm_irqchip_add_irqfd_notifier(kvm_state, intp->interrupt,
+ intp->unmask, irq) < 0) {
goto fail_irqfd;
}
if (vfio_set_trigger_eventfd(intp, NULL) < 0) {
goto fail_vfio;
}
- if (vfio_set_resample_eventfd(intp) < 0) {
- goto fail_vfio;
+ if (vfio_irq_is_automasked(intp)) {
+ if (vfio_set_resample_eventfd(intp) < 0) {
+ goto fail_vfio;
+ }
+ trace_vfio_platform_start_level_irqfd_injection(intp->pin,
+ event_notifier_get_fd(intp->interrupt),
+ event_notifier_get_fd(intp->unmask));
+ } else {
+ trace_vfio_platform_start_edge_irqfd_injection(intp->pin,
+ event_notifier_get_fd(intp->interrupt));
}
- /* Let's resume injection with irqfd setup */
- vfio_unmask_single_irqindex(&vdev->vbasedev, intp->pin);
-
intp->kvm_accel = true;
- trace_vfio_platform_start_irqfd_injection(intp->pin,
- event_notifier_get_fd(&intp->interrupt),
- event_notifier_get_fd(&intp->unmask));
return;
fail_vfio:
- kvm_irqchip_remove_irqfd_notifier(kvm_state, &intp->interrupt, irq);
+ kvm_irqchip_remove_irqfd_notifier(kvm_state, intp->interrupt, irq);
+ error_report("vfio: failed to start eventfd signaling for IRQ %d: %m",
+ intp->pin);
+ abort();
fail_irqfd:
- vfio_start_eventfd_injection(intp);
- vfio_unmask_single_irqindex(&vdev->vbasedev, intp->pin);
+ vfio_start_eventfd_injection(sbdev, irq);
return;
}
@@ -646,7 +675,6 @@ static void vfio_platform_realize(DeviceState *dev, Error **errp)
VFIOPlatformDevice *vdev = VFIO_PLATFORM_DEVICE(dev);
SysBusDevice *sbdev = SYS_BUS_DEVICE(dev);
VFIODevice *vbasedev = &vdev->vbasedev;
- VFIOINTp *intp;
int i, ret;
vbasedev->type = VFIO_DEVICE_TYPE_PLATFORM;
@@ -665,10 +693,6 @@ static void vfio_platform_realize(DeviceState *dev, Error **errp)
vfio_map_region(vdev, i);
sysbus_init_mmio(sbdev, &vdev->regions[i]->mem);
}
-
- QLIST_FOREACH(intp, &vdev->intp_list, next) {
- vfio_start_eventfd_injection(intp);
- }
}
static const VMStateDescription vfio_platform_vmstate = {
diff --git a/include/exec/exec-all.h b/include/exec/exec-all.h
index a3719b7..a63fd60 100644
--- a/include/exec/exec-all.h
+++ b/include/exec/exec-all.h
@@ -62,24 +62,15 @@ typedef struct TranslationBlock TranslationBlock;
#define OPC_BUF_SIZE 640
#define OPC_MAX_SIZE (OPC_BUF_SIZE - MAX_OP_PER_INSTR)
-/* Maximum size a TCG op can expand to. This is complicated because a
- single op may require several host instructions and register reloads.
- For now take a wild guess at 192 bytes, which should allow at least
- a couple of fixup instructions per argument. */
-#define TCG_MAX_OP_SIZE 192
-
#define OPPARAM_BUF_SIZE (OPC_BUF_SIZE * MAX_OPC_PARAM)
#include "qemu/log.h"
void gen_intermediate_code(CPUArchState *env, struct TranslationBlock *tb);
-void gen_intermediate_code_pc(CPUArchState *env, struct TranslationBlock *tb);
void restore_state_to_opc(CPUArchState *env, struct TranslationBlock *tb,
- int pc_pos);
+ target_ulong *data);
void cpu_gen_init(void);
-int cpu_gen_code(CPUArchState *env, struct TranslationBlock *tb,
- int *gen_code_size_ptr);
bool cpu_restore_state(CPUState *cpu, uintptr_t searched_pc);
void page_size_init(void);
@@ -170,13 +161,14 @@ static inline void tlb_flush_by_mmuidx(CPUState *cpu, ...)
#define CODE_GEN_PHYS_HASH_BITS 15
#define CODE_GEN_PHYS_HASH_SIZE (1 << CODE_GEN_PHYS_HASH_BITS)
-/* estimated block size for TB allocation */
-/* XXX: use a per code average code fragment size and modulate it
- according to the host CPU */
+/* Estimated block size for TB allocation. */
+/* ??? The following is based on a 2015 survey of x86_64 host output.
+ Better would seem to be some sort of dynamically sized TB array,
+ adapting to the block sizes actually being produced. */
#if defined(CONFIG_SOFTMMU)
-#define CODE_GEN_AVG_BLOCK_SIZE 128
+#define CODE_GEN_AVG_BLOCK_SIZE 400
#else
-#define CODE_GEN_AVG_BLOCK_SIZE 64
+#define CODE_GEN_AVG_BLOCK_SIZE 150
#endif
#if defined(__arm__) || defined(_ARCH_PPC) \
@@ -201,6 +193,7 @@ struct TranslationBlock {
#define CF_USE_ICOUNT 0x20000
void *tc_ptr; /* pointer to the translated code */
+ uint8_t *tc_search; /* pointer to search data */
/* next matching tb for physical address. */
struct TranslationBlock *phys_hash_next;
/* original tb when cflags has CF_NOCACHE */
diff --git a/include/exec/memory.h b/include/exec/memory.h
index 5baaf48..0f07159 100644
--- a/include/exec/memory.h
+++ b/include/exec/memory.h
@@ -583,6 +583,19 @@ void memory_region_notify_iommu(MemoryRegion *mr,
void memory_region_register_iommu_notifier(MemoryRegion *mr, Notifier *n);
/**
+ * memory_region_iommu_replay: replay existing IOMMU translations to
+ * a notifier
+ *
+ * @mr: the memory region to observe
+ * @n: the notifier to which to replay iommu mappings
+ * @granularity: Minimum page granularity to replay notifications for
+ * @is_write: Whether to treat the replay as a translate "write"
+ * through the iommu
+ */
+void memory_region_iommu_replay(MemoryRegion *mr, Notifier *n,
+ hwaddr granularity, bool is_write);
+
+/**
* memory_region_unregister_iommu_notifier: unregister a notifier for
* changes to IOMMU translation entries.
*
diff --git a/include/hw/vfio/vfio-common.h b/include/hw/vfio/vfio-common.h
index 9b9901f..f037f3c 100644
--- a/include/hw/vfio/vfio-common.h
+++ b/include/hw/vfio/vfio-common.h
@@ -59,22 +59,19 @@ typedef struct VFIOAddressSpace {
struct VFIOGroup;
-typedef struct VFIOType1 {
- MemoryListener listener;
- int error;
- bool initialized;
-} VFIOType1;
-
typedef struct VFIOContainer {
VFIOAddressSpace *space;
int fd; /* /dev/vfio/vfio, empowered by the attached groups */
- struct {
- /* enable abstraction to support various iommu backends */
- union {
- VFIOType1 type1;
- };
- void (*release)(struct VFIOContainer *);
- } iommu_data;
+ MemoryListener listener;
+ int error;
+ bool initialized;
+ /*
+ * This assumes the host IOMMU can support only a single
+ * contiguous IOVA window. We may need to generalize that in
+ * future
+ */
+ hwaddr min_iova, max_iova;
+ uint64_t iova_pgsizes;
QLIST_HEAD(, VFIOGuestIOMMU) giommu_list;
QLIST_HEAD(, VFIOGroup) group_list;
QLIST_ENTRY(VFIOContainer) next;
diff --git a/include/hw/vfio/vfio-platform.h b/include/hw/vfio/vfio-platform.h
index c5cf1d7..b468f80 100644
--- a/include/hw/vfio/vfio-platform.h
+++ b/include/hw/vfio/vfio-platform.h
@@ -34,8 +34,8 @@ enum {
typedef struct VFIOINTp {
QLIST_ENTRY(VFIOINTp) next; /* entry for IRQ list */
QSIMPLEQ_ENTRY(VFIOINTp) pqnext; /* entry for pending IRQ queue */
- EventNotifier interrupt; /* eventfd triggered on interrupt */
- EventNotifier unmask; /* eventfd for unmask on QEMU bypass */
+ EventNotifier *interrupt; /* eventfd triggered on interrupt */
+ EventNotifier *unmask; /* eventfd for unmask on QEMU bypass */
qemu_irq qemuirq;
struct VFIOPlatformDevice *vdev; /* back pointer to device */
int state; /* inactive, pending, active */
diff --git a/include/qemu/timer.h b/include/qemu/timer.h
index 9939246..d0946cb 100644
--- a/include/qemu/timer.h
+++ b/include/qemu/timer.h
@@ -857,7 +857,7 @@ int64_t cpu_icount_to_ns(int64_t icount);
#if defined(_ARCH_PPC)
-static inline int64_t cpu_get_real_ticks(void)
+static inline int64_t cpu_get_host_ticks(void)
{
int64_t retval;
#ifdef _ARCH_PPC64
@@ -883,7 +883,7 @@ static inline int64_t cpu_get_real_ticks(void)
#elif defined(__i386__)
-static inline int64_t cpu_get_real_ticks(void)
+static inline int64_t cpu_get_host_ticks(void)
{
int64_t val;
asm volatile ("rdtsc" : "=A" (val));
@@ -892,7 +892,7 @@ static inline int64_t cpu_get_real_ticks(void)
#elif defined(__x86_64__)
-static inline int64_t cpu_get_real_ticks(void)
+static inline int64_t cpu_get_host_ticks(void)
{
uint32_t low,high;
int64_t val;
@@ -905,7 +905,7 @@ static inline int64_t cpu_get_real_ticks(void)
#elif defined(__hppa__)
-static inline int64_t cpu_get_real_ticks(void)
+static inline int64_t cpu_get_host_ticks(void)
{
int val;
asm volatile ("mfctl %%cr16, %0" : "=r"(val));
@@ -914,7 +914,7 @@ static inline int64_t cpu_get_real_ticks(void)
#elif defined(__ia64)
-static inline int64_t cpu_get_real_ticks(void)
+static inline int64_t cpu_get_host_ticks(void)
{
int64_t val;
asm volatile ("mov %0 = ar.itc" : "=r"(val) :: "memory");
@@ -923,7 +923,7 @@ static inline int64_t cpu_get_real_ticks(void)
#elif defined(__s390__)
-static inline int64_t cpu_get_real_ticks(void)
+static inline int64_t cpu_get_host_ticks(void)
{
int64_t val;
asm volatile("stck 0(%1)" : "=m" (val) : "a" (&val) : "cc");
@@ -932,7 +932,7 @@ static inline int64_t cpu_get_real_ticks(void)
#elif defined(__sparc__)
-static inline int64_t cpu_get_real_ticks (void)
+static inline int64_t cpu_get_host_ticks (void)
{
#if defined(_LP64)
uint64_t rval;
@@ -970,7 +970,7 @@ static inline int64_t cpu_get_real_ticks (void)
: "=r" (value)); \
}
-static inline int64_t cpu_get_real_ticks(void)
+static inline int64_t cpu_get_host_ticks(void)
{
/* On kernels >= 2.6.25 rdhwr <reg>, $2 and $3 are emulated */
uint32_t count;
@@ -986,7 +986,7 @@ static inline int64_t cpu_get_real_ticks(void)
#elif defined(__alpha__)
-static inline int64_t cpu_get_real_ticks(void)
+static inline int64_t cpu_get_host_ticks(void)
{
uint64_t cc;
uint32_t cur, ofs;
@@ -1001,7 +1001,7 @@ static inline int64_t cpu_get_real_ticks(void)
/* The host CPU doesn't have an easily accessible cycle counter.
Just return a monotonically increasing value. This will be
totally wrong, but hopefully better than nothing. */
-static inline int64_t cpu_get_real_ticks (void)
+static inline int64_t cpu_get_host_ticks (void)
{
static int64_t ticks = 0;
return ticks++;
diff --git a/include/qom/cpu.h b/include/qom/cpu.h
index 9405554..b613ff0 100644
--- a/include/qom/cpu.h
+++ b/include/qom/cpu.h
@@ -721,6 +721,7 @@ void cpu_single_step(CPUState *cpu, int enabled);
/* 0x08 currently unused */
#define BP_GDB 0x10
#define BP_CPU 0x20
+#define BP_ANY (BP_GDB | BP_CPU)
#define BP_WATCHPOINT_HIT_READ 0x40
#define BP_WATCHPOINT_HIT_WRITE 0x80
#define BP_WATCHPOINT_HIT (BP_WATCHPOINT_HIT_READ | BP_WATCHPOINT_HIT_WRITE)
@@ -731,6 +732,21 @@ int cpu_breakpoint_remove(CPUState *cpu, vaddr pc, int flags);
void cpu_breakpoint_remove_by_ref(CPUState *cpu, CPUBreakpoint *breakpoint);
void cpu_breakpoint_remove_all(CPUState *cpu, int mask);
+/* Return true if PC matches an installed breakpoint. */
+static inline bool cpu_breakpoint_test(CPUState *cpu, vaddr pc, int mask)
+{
+ CPUBreakpoint *bp;
+
+ if (unlikely(!QTAILQ_EMPTY(&cpu->breakpoints))) {
+ QTAILQ_FOREACH(bp, &cpu->breakpoints, entry) {
+ if (bp->pc == pc && (bp->flags & mask)) {
+ return true;
+ }
+ }
+ }
+ return false;
+}
+
int cpu_watchpoint_insert(CPUState *cpu, vaddr addr, vaddr len,
int flags, CPUWatchpoint **watchpoint);
int cpu_watchpoint_remove(CPUState *cpu, vaddr addr,
diff --git a/linux-user/elfload.c b/linux-user/elfload.c
index fdae6a6..d68f5a1 100644
--- a/linux-user/elfload.c
+++ b/linux-user/elfload.c
@@ -2853,7 +2853,7 @@ static int fill_note_info(struct elf_note_info *info,
TaskState *ts = (TaskState *)cpu->opaque;
int i;
- info->notes = g_malloc0(NUMNOTES * sizeof (struct memelfnote));
+ info->notes = g_new0(struct memelfnote, NUMNOTES);
if (info->notes == NULL)
return (-ENOMEM);
info->prstatus = g_malloc0(sizeof (*info->prstatus));
diff --git a/linux-user/main.c b/linux-user/main.c
index 6599a41..8acfe0f 100644
--- a/linux-user/main.c
+++ b/linux-user/main.c
@@ -215,7 +215,7 @@ void cpu_list_unlock(void)
uint64_t cpu_get_tsc(CPUX86State *env)
{
- return cpu_get_real_ticks();
+ return cpu_get_host_ticks();
}
static void write_dt(void *ptr, unsigned long addr, unsigned long limit,
@@ -1425,7 +1425,7 @@ void cpu_loop (CPUSPARCState *env)
#ifdef TARGET_PPC
static inline uint64_t cpu_ppc_get_tb(CPUPPCState *env)
{
- return cpu_get_real_ticks();
+ return cpu_get_host_ticks();
}
uint64_t cpu_ppc_load_tbl(CPUPPCState *env)
@@ -3414,28 +3414,47 @@ void cpu_loop(CPUS390XState *env)
#ifdef TARGET_TILEGX
-static void gen_sigsegv_maperr(CPUTLGState *env, target_ulong addr)
+static void gen_sigill_reg(CPUTLGState *env)
{
target_siginfo_t info;
- info.si_signo = TARGET_SIGSEGV;
+ info.si_signo = TARGET_SIGILL;
info.si_errno = 0;
- info.si_code = TARGET_SEGV_MAPERR;
- info._sifields._sigfault._addr = addr;
+ info.si_code = TARGET_ILL_PRVREG;
+ info._sifields._sigfault._addr = env->pc;
queue_signal(env, info.si_signo, &info);
}
-static void gen_sigill_reg(CPUTLGState *env)
+static void do_signal(CPUTLGState *env, int signo, int sigcode)
{
target_siginfo_t info;
- info.si_signo = TARGET_SIGILL;
+ info.si_signo = signo;
info.si_errno = 0;
- info.si_code = TARGET_ILL_PRVREG;
info._sifields._sigfault._addr = env->pc;
+
+ if (signo == TARGET_SIGSEGV) {
+ /* The passed in sigcode is a dummy; check for a page mapping
+ and pass either MAPERR or ACCERR. */
+ target_ulong addr = env->excaddr;
+ info._sifields._sigfault._addr = addr;
+ if (page_check_range(addr, 1, PAGE_VALID) < 0) {
+ sigcode = TARGET_SEGV_MAPERR;
+ } else {
+ sigcode = TARGET_SEGV_ACCERR;
+ }
+ }
+ info.si_code = sigcode;
+
queue_signal(env, info.si_signo, &info);
}
+static void gen_sigsegv_maperr(CPUTLGState *env, target_ulong addr)
+{
+ env->excaddr = addr;
+ do_signal(env, TARGET_SIGSEGV, 0);
+}
+
static void set_regval(CPUTLGState *env, uint8_t reg, uint64_t val)
{
if (unlikely(reg >= TILEGX_R_COUNT)) {
@@ -3622,13 +3641,13 @@ void cpu_loop(CPUTLGState *env)
case TILEGX_EXCP_OPCODE_FETCHOR4:
do_fetch(env, trapnr, false);
break;
+ case TILEGX_EXCP_SIGNAL:
+ do_signal(env, env->signo, env->sigcode);
+ break;
case TILEGX_EXCP_REG_IDN_ACCESS:
case TILEGX_EXCP_REG_UDN_ACCESS:
gen_sigill_reg(env);
break;
- case TILEGX_EXCP_SEGV:
- gen_sigsegv_maperr(env, env->excaddr);
- break;
default:
fprintf(stderr, "trapnr is %d[0x%x].\n", trapnr, trapnr);
g_assert_not_reached();
@@ -4251,7 +4270,7 @@ int main(int argc, char **argv, char **envp)
}
target_argv[target_argc] = NULL;
- ts = g_malloc0 (sizeof(TaskState));
+ ts = g_new0(TaskState, 1);
init_task_state(ts);
/* build Task State */
ts->info = info;
diff --git a/linux-user/signal.c b/linux-user/signal.c
index ac82baa..9d62e02 100644
--- a/linux-user/signal.c
+++ b/linux-user/signal.c
@@ -5537,6 +5537,163 @@ long do_rt_sigreturn(CPUAlphaState *env)
force_sig(TARGET_SIGSEGV);
}
+#elif defined(TARGET_TILEGX)
+
+struct target_sigcontext {
+ union {
+ /* General-purpose registers. */
+ abi_ulong gregs[56];
+ struct {
+ abi_ulong __gregs[53];
+ abi_ulong tp; /* Aliases gregs[TREG_TP]. */
+ abi_ulong sp; /* Aliases gregs[TREG_SP]. */
+ abi_ulong lr; /* Aliases gregs[TREG_LR]. */
+ };
+ };
+ abi_ulong pc; /* Program counter. */
+ abi_ulong ics; /* In Interrupt Critical Section? */
+ abi_ulong faultnum; /* Fault number. */
+ abi_ulong pad[5];
+};
+
+struct target_ucontext {
+ abi_ulong tuc_flags;
+ abi_ulong tuc_link;
+ target_stack_t tuc_stack;
+ struct target_sigcontext tuc_mcontext;
+ target_sigset_t tuc_sigmask; /* mask last for extensibility */
+};
+
+struct target_rt_sigframe {
+ unsigned char save_area[16]; /* caller save area */
+ struct target_siginfo info;
+ struct target_ucontext uc;
+};
+
+static void setup_sigcontext(struct target_sigcontext *sc,
+ CPUArchState *env, int signo)
+{
+ int i;
+
+ for (i = 0; i < TILEGX_R_COUNT; ++i) {
+ __put_user(env->regs[i], &sc->gregs[i]);
+ }
+
+ __put_user(env->pc, &sc->pc);
+ __put_user(0, &sc->ics);
+ __put_user(signo, &sc->faultnum);
+}
+
+static void restore_sigcontext(CPUTLGState *env, struct target_sigcontext *sc)
+{
+ int i;
+
+ for (i = 0; i < TILEGX_R_COUNT; ++i) {
+ __get_user(env->regs[i], &sc->gregs[i]);
+ }
+
+ __get_user(env->pc, &sc->pc);
+}
+
+static abi_ulong get_sigframe(struct target_sigaction *ka, CPUArchState *env,
+ size_t frame_size)
+{
+ unsigned long sp = env->regs[TILEGX_R_SP];
+
+ if (on_sig_stack(sp) && !likely(on_sig_stack(sp - frame_size))) {
+ return -1UL;
+ }
+
+ if ((ka->sa_flags & SA_ONSTACK) && !sas_ss_flags(sp)) {
+ sp = target_sigaltstack_used.ss_sp + target_sigaltstack_used.ss_size;
+ }
+
+ sp -= frame_size;
+ sp &= -16UL;
+ return sp;
+}
+
+static void setup_rt_frame(int sig, struct target_sigaction *ka,
+ target_siginfo_t *info,
+ target_sigset_t *set, CPUArchState *env)
+{
+ abi_ulong frame_addr;
+ struct target_rt_sigframe *frame;
+ unsigned long restorer;
+
+ frame_addr = get_sigframe(ka, env, sizeof(*frame));
+ if (!lock_user_struct(VERIFY_WRITE, frame, frame_addr, 0)) {
+ goto give_sigsegv;
+ }
+
+ /* Always write at least the signal number for the stack backtracer. */
+ if (ka->sa_flags & TARGET_SA_SIGINFO) {
+ /* At sigreturn time, restore the callee-save registers too. */
+ tswap_siginfo(&frame->info, info);
+ /* regs->flags |= PT_FLAGS_RESTORE_REGS; FIXME: we can skip it? */
+ } else {
+ __put_user(info->si_signo, &frame->info.si_signo);
+ }
+
+ /* Create the ucontext. */
+ __put_user(0, &frame->uc.tuc_flags);
+ __put_user(0, &frame->uc.tuc_link);
+ __put_user(target_sigaltstack_used.ss_sp, &frame->uc.tuc_stack.ss_sp);
+ __put_user(sas_ss_flags(env->regs[TILEGX_R_SP]),
+ &frame->uc.tuc_stack.ss_flags);
+ __put_user(target_sigaltstack_used.ss_size, &frame->uc.tuc_stack.ss_size);
+ setup_sigcontext(&frame->uc.tuc_mcontext, env, info->si_signo);
+
+ restorer = (unsigned long) do_rt_sigreturn;
+ if (ka->sa_flags & TARGET_SA_RESTORER) {
+ restorer = (unsigned long) ka->sa_restorer;
+ }
+ env->pc = (unsigned long) ka->_sa_handler;
+ env->regs[TILEGX_R_SP] = (unsigned long) frame;
+ env->regs[TILEGX_R_LR] = restorer;
+ env->regs[0] = (unsigned long) sig;
+ env->regs[1] = (unsigned long) &frame->info;
+ env->regs[2] = (unsigned long) &frame->uc;
+ /* regs->flags |= PT_FLAGS_CALLER_SAVES; FIXME: we can skip it? */
+
+ unlock_user_struct(frame, frame_addr, 1);
+ return;
+
+give_sigsegv:
+ if (sig == TARGET_SIGSEGV) {
+ ka->_sa_handler = TARGET_SIG_DFL;
+ }
+ force_sig(TARGET_SIGSEGV /* , current */);
+}
+
+long do_rt_sigreturn(CPUTLGState *env)
+{
+ abi_ulong frame_addr = env->regs[TILEGX_R_SP];
+ struct target_rt_sigframe *frame;
+ sigset_t set;
+
+ if (!lock_user_struct(VERIFY_READ, frame, frame_addr, 1)) {
+ goto badframe;
+ }
+ target_to_host_sigset(&set, &frame->uc.tuc_sigmask);
+ do_sigprocmask(SIG_SETMASK, &set, NULL);
+
+ restore_sigcontext(env, &frame->uc.tuc_mcontext);
+ if (do_sigaltstack(frame_addr + offsetof(struct target_rt_sigframe,
+ uc.tuc_stack),
+ 0, env->regs[TILEGX_R_SP]) == -EFAULT) {
+ goto badframe;
+ }
+
+ unlock_user_struct(frame, frame_addr, 0);
+ return env->regs[TILEGX_R_RE];
+
+
+ badframe:
+ unlock_user_struct(frame, frame_addr, 0);
+ force_sig(TARGET_SIGSEGV);
+}
+
#else
static void setup_frame(int sig, struct target_sigaction *ka,
@@ -5657,7 +5814,7 @@ void process_pending_signals(CPUArchState *cpu_env)
#endif
/* prepare the stack frame of the virtual CPU */
#if defined(TARGET_ABI_MIPSN32) || defined(TARGET_ABI_MIPSN64) \
- || defined(TARGET_OPENRISC)
+ || defined(TARGET_OPENRISC) || defined(TARGET_TILEGX)
/* These targets do not have traditional signals. */
setup_rt_frame(sig, sa, &q->info, &target_old_set, cpu_env);
#else
diff --git a/linux-user/syscall.c b/linux-user/syscall.c
index 98b5766..8bfb24f 100644
--- a/linux-user/syscall.c
+++ b/linux-user/syscall.c
@@ -2728,8 +2728,9 @@ static inline abi_long host_to_target_semarray(int semid, abi_ulong target_addr,
}
static inline abi_long do_semctl(int semid, int semnum, int cmd,
- union target_semun target_su)
+ abi_ulong target_arg)
{
+ union target_semun target_su = { .buf = target_arg };
union semun arg;
struct semid_ds dsarg;
unsigned short *array = NULL;
@@ -3251,8 +3252,7 @@ static abi_long do_ipc(unsigned int call, abi_long first,
* ptr argument. */
abi_ulong atptr;
get_user_ual(atptr, ptr);
- ret = do_semctl(first, second, third,
- (union target_semun) atptr);
+ ret = do_semctl(first, second, third, atptr);
break;
}
@@ -4566,7 +4566,7 @@ static int do_fork(CPUArchState *env, unsigned int flags, abi_ulong newsp,
new_thread_info info;
pthread_attr_t attr;
- ts = g_malloc0(sizeof(TaskState));
+ ts = g_new0(TaskState, 1);
init_task_state(ts);
/* we create a new CPU instance. */
new_env = cpu_copy(env);
@@ -7550,7 +7550,7 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1,
#endif
#ifdef TARGET_NR_semctl
case TARGET_NR_semctl:
- ret = do_semctl(arg1, arg2, arg3, (union target_semun)(abi_ulong)arg4);
+ ret = do_semctl(arg1, arg2, arg3, arg4);
break;
#endif
#ifdef TARGET_NR_msgctl
diff --git a/linux-user/syscall_defs.h b/linux-user/syscall_defs.h
index 7ca33a6..f996acf 100644
--- a/linux-user/syscall_defs.h
+++ b/linux-user/syscall_defs.h
@@ -748,6 +748,10 @@ typedef struct target_siginfo {
#define TARGET_ILL_PRVREG (6) /* privileged register */
#define TARGET_ILL_COPROC (7) /* coprocessor error */
#define TARGET_ILL_BADSTK (8) /* internal stack error */
+#ifdef TARGET_TILEGX
+#define TARGET_ILL_DBLFLT (9) /* double fault */
+#define TARGET_ILL_HARDWALL (10) /* user networks hardwall violation */
+#endif
/*
* SIGFPE si_codes
@@ -767,6 +771,7 @@ typedef struct target_siginfo {
*/
#define TARGET_SEGV_MAPERR (1) /* address not mapped to object */
#define TARGET_SEGV_ACCERR (2) /* invalid permissions for mapped object */
+#define TARGET_SEGV_BNDERR (3) /* failed address bound checks */
/*
* SIGBUS si_codes
@@ -774,12 +779,18 @@ typedef struct target_siginfo {
#define TARGET_BUS_ADRALN (1) /* invalid address alignment */
#define TARGET_BUS_ADRERR (2) /* non-existent physical address */
#define TARGET_BUS_OBJERR (3) /* object specific hardware error */
+/* hardware memory error consumed on a machine check: action required */
+#define TARGET_BUS_MCEERR_AR (4)
+/* hardware memory error detected in process but not consumed: action optional*/
+#define TARGET_BUS_MCEERR_AO (5)
/*
* SIGTRAP si_codes
*/
#define TARGET_TRAP_BRKPT (1) /* process breakpoint */
#define TARGET_TRAP_TRACE (2) /* process trace trap */
+#define TARGET_TRAP_BRANCH (3) /* process taken branch trap */
+#define TARGET_TRAP_HWBKPT (4) /* hardware breakpoint/watchpoint */
#endif /* defined(TARGET_I386) || defined(TARGET_ARM) */
diff --git a/linux-user/tilegx/syscall.h b/linux-user/tilegx/syscall.h
index 653ece1..a938d4e 100644
--- a/linux-user/tilegx/syscall.h
+++ b/linux-user/tilegx/syscall.h
@@ -37,4 +37,7 @@ struct target_pt_regs {
#define TARGET_MLOCKALL_MCL_CURRENT 1
#define TARGET_MLOCKALL_MCL_FUTURE 2
+/* For faultnum */
+#define TARGET_INT_SWINT_1 14
+
#endif
diff --git a/memory.c b/memory.c
index ef87363..1b03d22 100644
--- a/memory.c
+++ b/memory.c
@@ -1403,6 +1403,26 @@ void memory_region_register_iommu_notifier(MemoryRegion *mr, Notifier *n)
notifier_list_add(&mr->iommu_notify, n);
}
+void memory_region_iommu_replay(MemoryRegion *mr, Notifier *n,
+ hwaddr granularity, bool is_write)
+{
+ hwaddr addr;
+ IOMMUTLBEntry iotlb;
+
+ for (addr = 0; addr < memory_region_size(mr); addr += granularity) {
+ iotlb = mr->iommu_ops->translate(mr, addr, is_write);
+ if (iotlb.perm != IOMMU_NONE) {
+ n->notify(n, &iotlb);
+ }
+
+ /* if (2^64 - MR size) < granularity, it's possible to get an
+ * infinite loop here. This should catch such a wraparound */
+ if ((addr + granularity) < addr) {
+ break;
+ }
+ }
+}
+
void memory_region_unregister_iommu_notifier(Notifier *n)
{
notifier_remove(n);
diff --git a/pc-bios/s390-ccw/Makefile b/pc-bios/s390-ccw/Makefile
index 746603a..15e4232 100644
--- a/pc-bios/s390-ccw/Makefile
+++ b/pc-bios/s390-ccw/Makefile
@@ -10,7 +10,8 @@ $(call set-vpath, $(SRC_PATH)/pc-bios/s390-ccw)
.PHONY : all clean build-all
OBJECTS = start.o main.o bootmap.o sclp-ascii.o virtio.o
-CFLAGS += -fPIE -fno-stack-protector -ffreestanding -fno-delete-null-pointer-checks
+CFLAGS += -fPIE -fno-stack-protector -ffreestanding
+CFLAGS += -fno-delete-null-pointer-checks -msoft-float
LDFLAGS += -Wl,-pie -nostdlib
build-all: s390-ccw.img
diff --git a/qapi/block.json b/qapi/block.json
index aad645c..84022f1 100644
--- a/qapi/block.json
+++ b/qapi/block.json
@@ -6,7 +6,7 @@
{ 'include': 'block-core.json' }
##
-# BiosAtaTranslation:
+# @BiosAtaTranslation:
#
# Policy that BIOS should use to interpret cylinder/head/sector
# addresses. Note that Bochs BIOS and SeaBIOS will not actually
diff --git a/target-alpha/cpu.h b/target-alpha/cpu.h
index 097637e..bcd8076 100644
--- a/target-alpha/cpu.h
+++ b/target-alpha/cpu.h
@@ -287,7 +287,6 @@ struct CPUAlphaState {
#define cpu_list alpha_cpu_list
#define cpu_exec cpu_alpha_exec
-#define cpu_gen_code cpu_alpha_gen_code
#define cpu_signal_handler cpu_alpha_signal_handler
#include "exec/cpu-all.h"
diff --git a/target-alpha/sys_helper.c b/target-alpha/sys_helper.c
index 1f0e1a9..75c96c1 100644
--- a/target-alpha/sys_helper.c
+++ b/target-alpha/sys_helper.c
@@ -34,7 +34,7 @@ uint64_t helper_load_pcc(CPUAlphaState *env)
#else
/* In user-mode, QEMU_CLOCK_VIRTUAL doesn't exist. Just pass through the host cpu
clock ticks. Also, don't bother taking PCC_OFS into account. */
- return (uint32_t)cpu_get_real_ticks();
+ return (uint32_t)cpu_get_host_ticks();
#endif
}
diff --git a/target-alpha/translate.c b/target-alpha/translate.c
index 2ba5fb8..f936d1b 100644
--- a/target-alpha/translate.c
+++ b/target-alpha/translate.c
@@ -2858,18 +2858,14 @@ static ExitStatus translate_one(DisasContext *ctx, uint32_t insn)
return ret;
}
-static inline void gen_intermediate_code_internal(AlphaCPU *cpu,
- TranslationBlock *tb,
- bool search_pc)
+void gen_intermediate_code(CPUAlphaState *env, struct TranslationBlock *tb)
{
+ AlphaCPU *cpu = alpha_env_get_cpu(env);
CPUState *cs = CPU(cpu);
- CPUAlphaState *env = &cpu->env;
DisasContext ctx, *ctxp = &ctx;
target_ulong pc_start;
target_ulong pc_mask;
uint32_t insn;
- CPUBreakpoint *bp;
- int j, lj = -1;
ExitStatus ret;
int num_insns;
int max_insns;
@@ -2904,6 +2900,9 @@ static inline void gen_intermediate_code_internal(AlphaCPU *cpu,
if (max_insns == 0) {
max_insns = CF_COUNT_MASK;
}
+ if (max_insns > TCG_MAX_INSNS) {
+ max_insns = TCG_MAX_INSNS;
+ }
if (in_superpage(&ctx, pc_start)) {
pc_mask = (1ULL << 41) - 1;
@@ -2913,35 +2912,17 @@ static inline void gen_intermediate_code_internal(AlphaCPU *cpu,
gen_tb_start(tb);
do {
- if (unlikely(!QTAILQ_EMPTY(&cs->breakpoints))) {
- QTAILQ_FOREACH(bp, &cs->breakpoints, entry) {
- if (bp->pc == ctx.pc) {
- gen_excp(&ctx, EXCP_DEBUG, 0);
- break;
- }
- }
- }
- if (search_pc) {
- j = tcg_op_buf_count();
- if (lj < j) {
- lj++;
- while (lj < j) {
- tcg_ctx.gen_opc_instr_start[lj++] = 0;
- }
- }
- tcg_ctx.gen_opc_pc[lj] = ctx.pc;
- tcg_ctx.gen_opc_instr_start[lj] = 1;
- tcg_ctx.gen_opc_icount[lj] = num_insns;
+ tcg_gen_insn_start(ctx.pc);
+ num_insns++;
+
+ if (unlikely(cpu_breakpoint_test(cs, ctx.pc, BP_ANY))) {
+ gen_excp(&ctx, EXCP_DEBUG, 0);
+ break;
}
- if (num_insns + 1 == max_insns && (tb->cflags & CF_LAST_IO)) {
+ if (num_insns == max_insns && (tb->cflags & CF_LAST_IO)) {
gen_io_start();
}
insn = cpu_ldl_code(env, ctx.pc);
- num_insns++;
-
- if (unlikely(qemu_loglevel_mask(CPU_LOG_TB_OP | CPU_LOG_TB_OP_OPT))) {
- tcg_gen_debug_insn_start(ctx.pc);
- }
TCGV_UNUSED_I64(ctx.zero);
TCGV_UNUSED_I64(ctx.sink);
@@ -2997,16 +2978,8 @@ static inline void gen_intermediate_code_internal(AlphaCPU *cpu,
gen_tb_end(tb, num_insns);
- if (search_pc) {
- j = tcg_op_buf_count();
- lj++;
- while (lj <= j) {
- tcg_ctx.gen_opc_instr_start[lj++] = 0;
- }
- } else {
- tb->size = ctx.pc - pc_start;
- tb->icount = num_insns;
- }
+ tb->size = ctx.pc - pc_start;
+ tb->icount = num_insns;
#ifdef DEBUG_DISAS
if (qemu_loglevel_mask(CPU_LOG_TB_IN_ASM)) {
@@ -3017,17 +2990,8 @@ static inline void gen_intermediate_code_internal(AlphaCPU *cpu,
#endif
}
-void gen_intermediate_code (CPUAlphaState *env, struct TranslationBlock *tb)
-{
- gen_intermediate_code_internal(alpha_env_get_cpu(env), tb, false);
-}
-
-void gen_intermediate_code_pc (CPUAlphaState *env, struct TranslationBlock *tb)
-{
- gen_intermediate_code_internal(alpha_env_get_cpu(env), tb, true);
-}
-
-void restore_state_to_opc(CPUAlphaState *env, TranslationBlock *tb, int pc_pos)
+void restore_state_to_opc(CPUAlphaState *env, TranslationBlock *tb,
+ target_ulong *data)
{
- env->pc = tcg_ctx.gen_opc_pc[pc_pos];
+ env->pc = data[0];
}
diff --git a/target-arm/cpu.h b/target-arm/cpu.h
index cc1578c..493f9d0 100644
--- a/target-arm/cpu.h
+++ b/target-arm/cpu.h
@@ -95,6 +95,7 @@
struct arm_boot_info;
#define NB_MMU_MODES 7
+#define TARGET_INSN_START_EXTRA_WORDS 1
/* We currently assume float and double are IEEE single and double
precision respectively.
@@ -1600,7 +1601,6 @@ static inline bool arm_excp_unmasked(CPUState *cs, unsigned int excp_idx,
#define cpu_init(cpu_model) CPU(cpu_arm_init(cpu_model))
#define cpu_exec cpu_arm_exec
-#define cpu_gen_code cpu_arm_gen_code
#define cpu_signal_handler cpu_arm_signal_handler
#define cpu_list arm_cpu_list
diff --git a/target-arm/translate-a64.c b/target-arm/translate-a64.c
index ec0936c..e65e309 100644
--- a/target-arm/translate-a64.c
+++ b/target-arm/translate-a64.c
@@ -11000,15 +11000,11 @@ static void disas_a64_insn(CPUARMState *env, DisasContext *s)
free_tmp_a64(s);
}
-void gen_intermediate_code_internal_a64(ARMCPU *cpu,
- TranslationBlock *tb,
- bool search_pc)
+void gen_intermediate_code_a64(ARMCPU *cpu, TranslationBlock *tb)
{
CPUState *cs = CPU(cpu);
CPUARMState *env = &cpu->env;
DisasContext dc1, *dc = &dc1;
- CPUBreakpoint *bp;
- int j, lj;
target_ulong pc_start;
target_ulong next_page_start;
int num_insns;
@@ -11067,19 +11063,25 @@ void gen_intermediate_code_internal_a64(ARMCPU *cpu,
init_tmp_a64_array(dc);
next_page_start = (pc_start & TARGET_PAGE_MASK) + TARGET_PAGE_SIZE;
- lj = -1;
num_insns = 0;
max_insns = tb->cflags & CF_COUNT_MASK;
if (max_insns == 0) {
max_insns = CF_COUNT_MASK;
}
+ if (max_insns > TCG_MAX_INSNS) {
+ max_insns = TCG_MAX_INSNS;
+ }
gen_tb_start(tb);
tcg_clear_temp_count();
do {
+ tcg_gen_insn_start(dc->pc, 0);
+ num_insns++;
+
if (unlikely(!QTAILQ_EMPTY(&cs->breakpoints))) {
+ CPUBreakpoint *bp;
QTAILQ_FOREACH(bp, &cs->breakpoints, entry) {
if (bp->pc == dc->pc) {
gen_exception_internal_insn(dc, 0, EXCP_DEBUG);
@@ -11091,27 +11093,10 @@ void gen_intermediate_code_internal_a64(ARMCPU *cpu,
}
}
- if (search_pc) {
- j = tcg_op_buf_count();
- if (lj < j) {
- lj++;
- while (lj < j) {
- tcg_ctx.gen_opc_instr_start[lj++] = 0;
- }
- }
- tcg_ctx.gen_opc_pc[lj] = dc->pc;
- tcg_ctx.gen_opc_instr_start[lj] = 1;
- tcg_ctx.gen_opc_icount[lj] = num_insns;
- }
-
- if (num_insns + 1 == max_insns && (tb->cflags & CF_LAST_IO)) {
+ if (num_insns == max_insns && (tb->cflags & CF_LAST_IO)) {
gen_io_start();
}
- if (unlikely(qemu_loglevel_mask(CPU_LOG_TB_OP | CPU_LOG_TB_OP_OPT))) {
- tcg_gen_debug_insn_start(dc->pc);
- }
-
if (dc->ss_active && !dc->pstate_ss) {
/* Singlestep state is Active-pending.
* If we're in this state at the start of a TB then either
@@ -11123,7 +11108,7 @@ void gen_intermediate_code_internal_a64(ARMCPU *cpu,
* "did not step an insn" case, and so the syndrome ISV and EX
* bits should be zero.
*/
- assert(num_insns == 0);
+ assert(num_insns == 1);
gen_exception(EXCP_UDEF, syn_swstep(dc->ss_same_el, 0, 0),
default_exception_el(dc));
dc->is_jmp = DISAS_EXC;
@@ -11142,7 +11127,6 @@ void gen_intermediate_code_internal_a64(ARMCPU *cpu,
* Also stop translation when a page boundary is reached. This
* ensures prefetch aborts occur at the right place.
*/
- num_insns++;
} while (!dc->is_jmp && !tcg_op_buf_full() &&
!cs->singlestep_enabled &&
!singlestep &&
@@ -11221,14 +11205,6 @@ done_generating:
qemu_log("\n");
}
#endif
- if (search_pc) {
- j = tcg_op_buf_count();
- lj++;
- while (lj <= j) {
- tcg_ctx.gen_opc_instr_start[lj++] = 0;
- }
- } else {
- tb->size = dc->pc - pc_start;
- tb->icount = num_insns;
- }
+ tb->size = dc->pc - pc_start;
+ tb->icount = num_insns;
}
diff --git a/target-arm/translate.c b/target-arm/translate.c
index 84a21ac..22c3587 100644
--- a/target-arm/translate.c
+++ b/target-arm/translate.c
@@ -52,7 +52,6 @@
#define ARCH(x) do { if (!ENABLE_ARCH_##x) goto illegal_op; } while(0)
#include "translate.h"
-static uint32_t gen_opc_condexec_bits[OPC_BUF_SIZE];
#if defined(CONFIG_USER_ONLY)
#define IS_USER(s) 1
@@ -11168,17 +11167,12 @@ undef:
}
/* generate intermediate code in gen_opc_buf and gen_opparam_buf for
- basic block 'tb'. If search_pc is TRUE, also generate PC
- information for each intermediate instruction. */
-static inline void gen_intermediate_code_internal(ARMCPU *cpu,
- TranslationBlock *tb,
- bool search_pc)
+ basic block 'tb'. */
+void gen_intermediate_code(CPUARMState *env, TranslationBlock *tb)
{
+ ARMCPU *cpu = arm_env_get_cpu(env);
CPUState *cs = CPU(cpu);
- CPUARMState *env = &cpu->env;
DisasContext dc1, *dc = &dc1;
- CPUBreakpoint *bp;
- int j, lj;
target_ulong pc_start;
target_ulong next_page_start;
int num_insns;
@@ -11190,7 +11184,7 @@ static inline void gen_intermediate_code_internal(ARMCPU *cpu,
* the A32/T32 complexity to do with conditional execution/IT blocks/etc.
*/
if (ARM_TBFLAG_AARCH64_STATE(tb->flags)) {
- gen_intermediate_code_internal_a64(cpu, tb, search_pc);
+ gen_intermediate_code_a64(cpu, tb);
return;
}
@@ -11256,11 +11250,14 @@ static inline void gen_intermediate_code_internal(ARMCPU *cpu,
/* FIXME: cpu_M0 can probably be the same as cpu_V0. */
cpu_M0 = tcg_temp_new_i64();
next_page_start = (pc_start & TARGET_PAGE_MASK) + TARGET_PAGE_SIZE;
- lj = -1;
num_insns = 0;
max_insns = tb->cflags & CF_COUNT_MASK;
- if (max_insns == 0)
+ if (max_insns == 0) {
max_insns = CF_COUNT_MASK;
+ }
+ if (max_insns > TCG_MAX_INSNS) {
+ max_insns = TCG_MAX_INSNS;
+ }
gen_tb_start(tb);
@@ -11286,10 +11283,9 @@ static inline void gen_intermediate_code_internal(ARMCPU *cpu,
* (3) if we leave the TB unexpectedly (eg a data abort on a load)
* then the CPUARMState will be wrong and we need to reset it.
* This is handled in the same way as restoration of the
- * PC in these situations: we will be called again with search_pc=1
- * and generate a mapping of the condexec bits for each PC in
- * gen_opc_condexec_bits[]. restore_state_to_opc() then uses
- * this to restore the condexec bits.
+ * PC in these situations; we save the value of the condexec bits
+ * for each PC via tcg_gen_insn_start(), and restore_state_to_opc()
+ * then uses this to restore them after an exception.
*
* Note that there are no instructions which can read the condexec
* bits, and none which can write non-static values to them, so
@@ -11306,6 +11302,10 @@ static inline void gen_intermediate_code_internal(ARMCPU *cpu,
store_cpu_field(tmp, condexec_bits);
}
do {
+ tcg_gen_insn_start(dc->pc,
+ (dc->condexec_cond << 4) | (dc->condexec_mask >> 1));
+ num_insns++;
+
#ifdef CONFIG_USER_ONLY
/* Intercept jump to the magic kernel page. */
if (dc->pc >= 0xffff0000) {
@@ -11326,6 +11326,7 @@ static inline void gen_intermediate_code_internal(ARMCPU *cpu,
#endif
if (unlikely(!QTAILQ_EMPTY(&cs->breakpoints))) {
+ CPUBreakpoint *bp;
QTAILQ_FOREACH(bp, &cs->breakpoints, entry) {
if (bp->pc == dc->pc) {
gen_exception_internal_insn(dc, 0, EXCP_DEBUG);
@@ -11336,24 +11337,9 @@ static inline void gen_intermediate_code_internal(ARMCPU *cpu,
}
}
}
- if (search_pc) {
- j = tcg_op_buf_count();
- if (lj < j) {
- lj++;
- while (lj < j)
- tcg_ctx.gen_opc_instr_start[lj++] = 0;
- }
- tcg_ctx.gen_opc_pc[lj] = dc->pc;
- gen_opc_condexec_bits[lj] = (dc->condexec_cond << 4) | (dc->condexec_mask >> 1);
- tcg_ctx.gen_opc_instr_start[lj] = 1;
- tcg_ctx.gen_opc_icount[lj] = num_insns;
- }
- if (num_insns + 1 == max_insns && (tb->cflags & CF_LAST_IO))
+ if (num_insns == max_insns && (tb->cflags & CF_LAST_IO)) {
gen_io_start();
-
- if (unlikely(qemu_loglevel_mask(CPU_LOG_TB_OP | CPU_LOG_TB_OP_OPT))) {
- tcg_gen_debug_insn_start(dc->pc);
}
if (dc->ss_active && !dc->pstate_ss) {
@@ -11367,7 +11353,7 @@ static inline void gen_intermediate_code_internal(ARMCPU *cpu,
* "did not step an insn" case, and so the syndrome ISV and EX
* bits should be zero.
*/
- assert(num_insns == 0);
+ assert(num_insns == 1);
gen_exception(EXCP_UDEF, syn_swstep(dc->ss_same_el, 0, 0),
default_exception_el(dc));
goto done_generating;
@@ -11403,7 +11389,6 @@ static inline void gen_intermediate_code_internal(ARMCPU *cpu,
* Otherwise the subsequent code could get translated several times.
* Also stop translation when a page boundary is reached. This
* ensures prefetch aborts occur at the right place. */
- num_insns ++;
} while (!dc->is_jmp && !tcg_op_buf_full() &&
!cs->singlestep_enabled &&
!singlestep &&
@@ -11533,25 +11518,8 @@ done_generating:
qemu_log("\n");
}
#endif
- if (search_pc) {
- j = tcg_op_buf_count();
- lj++;
- while (lj <= j)
- tcg_ctx.gen_opc_instr_start[lj++] = 0;
- } else {
- tb->size = dc->pc - pc_start;
- tb->icount = num_insns;
- }
-}
-
-void gen_intermediate_code(CPUARMState *env, TranslationBlock *tb)
-{
- gen_intermediate_code_internal(arm_env_get_cpu(env), tb, false);
-}
-
-void gen_intermediate_code_pc(CPUARMState *env, TranslationBlock *tb)
-{
- gen_intermediate_code_internal(arm_env_get_cpu(env), tb, true);
+ tb->size = dc->pc - pc_start;
+ tb->icount = num_insns;
}
static const char *cpu_mode_names[16] = {
@@ -11608,13 +11576,14 @@ void arm_cpu_dump_state(CPUState *cs, FILE *f, fprintf_function cpu_fprintf,
}
}
-void restore_state_to_opc(CPUARMState *env, TranslationBlock *tb, int pc_pos)
+void restore_state_to_opc(CPUARMState *env, TranslationBlock *tb,
+ target_ulong *data)
{
if (is_a64(env)) {
- env->pc = tcg_ctx.gen_opc_pc[pc_pos];
+ env->pc = data[0];
env->condexec_bits = 0;
} else {
- env->regs[15] = tcg_ctx.gen_opc_pc[pc_pos];
- env->condexec_bits = gen_opc_condexec_bits[pc_pos];
+ env->regs[15] = data[0];
+ env->condexec_bits = data[1];
}
}
diff --git a/target-arm/translate.h b/target-arm/translate.h
index b8fe37a..53ef971 100644
--- a/target-arm/translate.h
+++ b/target-arm/translate.h
@@ -122,9 +122,7 @@ static inline int default_exception_el(DisasContext *s)
#ifdef TARGET_AARCH64
void a64_translate_init(void);
-void gen_intermediate_code_internal_a64(ARMCPU *cpu,
- TranslationBlock *tb,
- bool search_pc);
+void gen_intermediate_code_a64(ARMCPU *cpu, TranslationBlock *tb);
void gen_a64_set_pc_im(uint64_t val);
void aarch64_cpu_dump_state(CPUState *cs, FILE *f,
fprintf_function cpu_fprintf, int flags);
@@ -133,9 +131,7 @@ static inline void a64_translate_init(void)
{
}
-static inline void gen_intermediate_code_internal_a64(ARMCPU *cpu,
- TranslationBlock *tb,
- bool search_pc)
+static inline void gen_intermediate_code_a64(ARMCPU *cpu, TranslationBlock *tb)
{
}
diff --git a/target-cris/cpu.h b/target-cris/cpu.h
index d47fad4..3220460 100644
--- a/target-cris/cpu.h
+++ b/target-cris/cpu.h
@@ -223,7 +223,6 @@ enum {
#define cpu_init(cpu_model) CPU(cpu_cris_init(cpu_model))
#define cpu_exec cpu_cris_exec
-#define cpu_gen_code cpu_cris_gen_code
#define cpu_signal_handler cpu_cris_signal_handler
/* MMU modes definitions */
diff --git a/target-cris/translate.c b/target-cris/translate.c
index d5b54e1..964845c 100644
--- a/target-cris/translate.c
+++ b/target-cris/translate.c
@@ -2994,10 +2994,6 @@ static unsigned int crisv32_decoder(CPUCRISState *env, DisasContext *dc)
int insn_len = 2;
int i;
- if (unlikely(qemu_loglevel_mask(CPU_LOG_TB_OP | CPU_LOG_TB_OP_OPT))) {
- tcg_gen_debug_insn_start(dc->pc);
- }
-
/* Load a halfword onto the instruction register. */
dc->ir = cris_fetch(env, dc, dc->pc, 2, 0);
@@ -3034,23 +3030,6 @@ static unsigned int crisv32_decoder(CPUCRISState *env, DisasContext *dc)
return insn_len;
}
-static void check_breakpoint(CPUCRISState *env, DisasContext *dc)
-{
- CPUState *cs = CPU(cris_env_get_cpu(env));
- CPUBreakpoint *bp;
-
- if (unlikely(!QTAILQ_EMPTY(&cs->breakpoints))) {
- QTAILQ_FOREACH(bp, &cs->breakpoints, entry) {
- if (bp->pc == dc->pc) {
- cris_evaluate_flags(dc);
- tcg_gen_movi_tl(env_pc, dc->pc);
- t_gen_raise_exception(EXCP_DEBUG);
- dc->is_jmp = DISAS_UPDATE;
- }
- }
- }
-}
-
#include "translate_v10.c"
/*
@@ -3088,15 +3067,12 @@ static void check_breakpoint(CPUCRISState *env, DisasContext *dc)
*/
/* generate intermediate code for basic block 'tb'. */
-static inline void
-gen_intermediate_code_internal(CRISCPU *cpu, TranslationBlock *tb,
- bool search_pc)
+void gen_intermediate_code(CPUCRISState *env, struct TranslationBlock *tb)
{
+ CRISCPU *cpu = cris_env_get_cpu(env);
CPUState *cs = CPU(cpu);
- CPUCRISState *env = &cpu->env;
uint32_t pc_start;
unsigned int insn_len;
- int j, lj;
struct DisasContext ctx;
struct DisasContext *dc = &ctx;
uint32_t next_page_start;
@@ -3148,13 +3124,13 @@ gen_intermediate_code_internal(CRISCPU *cpu, TranslationBlock *tb,
if (qemu_loglevel_mask(CPU_LOG_TB_IN_ASM)) {
qemu_log(
- "srch=%d pc=%x %x flg=%" PRIx64 " bt=%x ds=%u ccs=%x\n"
+ "pc=%x %x flg=%" PRIx64 " bt=%x ds=%u ccs=%x\n"
"pid=%x usp=%x\n"
"%x.%x.%x.%x\n"
"%x.%x.%x.%x\n"
"%x.%x.%x.%x\n"
"%x.%x.%x.%x\n",
- search_pc, dc->pc, dc->ppc,
+ dc->pc, dc->ppc,
(uint64_t)tb->flags,
env->btarget, (unsigned)tb->flags & 7,
env->pregs[PR_CCS],
@@ -3170,38 +3146,33 @@ gen_intermediate_code_internal(CRISCPU *cpu, TranslationBlock *tb,
}
next_page_start = (pc_start & TARGET_PAGE_MASK) + TARGET_PAGE_SIZE;
- lj = -1;
num_insns = 0;
max_insns = tb->cflags & CF_COUNT_MASK;
if (max_insns == 0) {
max_insns = CF_COUNT_MASK;
}
+ if (max_insns > TCG_MAX_INSNS) {
+ max_insns = TCG_MAX_INSNS;
+ }
gen_tb_start(tb);
do {
- check_breakpoint(env, dc);
-
- if (search_pc) {
- j = tcg_op_buf_count();
- if (lj < j) {
- lj++;
- while (lj < j) {
- tcg_ctx.gen_opc_instr_start[lj++] = 0;
- }
- }
- if (dc->delayed_branch == 1) {
- tcg_ctx.gen_opc_pc[lj] = dc->ppc | 1;
- } else {
- tcg_ctx.gen_opc_pc[lj] = dc->pc;
- }
- tcg_ctx.gen_opc_instr_start[lj] = 1;
- tcg_ctx.gen_opc_icount[lj] = num_insns;
+ tcg_gen_insn_start(dc->delayed_branch == 1
+ ? dc->ppc | 1 : dc->pc);
+ num_insns++;
+
+ if (unlikely(cpu_breakpoint_test(cs, dc->pc, BP_ANY))) {
+ cris_evaluate_flags(dc);
+ tcg_gen_movi_tl(env_pc, dc->pc);
+ t_gen_raise_exception(EXCP_DEBUG);
+ dc->is_jmp = DISAS_UPDATE;
+ break;
}
/* Pretty disas. */
LOG_DIS("%8.8x:\t", dc->pc);
- if (num_insns + 1 == max_insns && (tb->cflags & CF_LAST_IO)) {
+ if (num_insns == max_insns && (tb->cflags & CF_LAST_IO)) {
gen_io_start();
}
dc->clear_x = 1;
@@ -3213,7 +3184,6 @@ gen_intermediate_code_internal(CRISCPU *cpu, TranslationBlock *tb,
cris_clear_x_flag(dc);
}
- num_insns++;
/* Check for delayed branches here. If we do it before
actually generating any host code, the simulator will just
loop doing nothing for on this program location. */
@@ -3318,16 +3288,8 @@ gen_intermediate_code_internal(CRISCPU *cpu, TranslationBlock *tb,
}
gen_tb_end(tb, num_insns);
- if (search_pc) {
- j = tcg_op_buf_count();
- lj++;
- while (lj <= j) {
- tcg_ctx.gen_opc_instr_start[lj++] = 0;
- }
- } else {
- tb->size = dc->pc - pc_start;
- tb->icount = num_insns;
- }
+ tb->size = dc->pc - pc_start;
+ tb->icount = num_insns;
#ifdef DEBUG_DISAS
#if !DISAS_CRIS
@@ -3341,16 +3303,6 @@ gen_intermediate_code_internal(CRISCPU *cpu, TranslationBlock *tb,
#endif
}
-void gen_intermediate_code (CPUCRISState *env, struct TranslationBlock *tb)
-{
- gen_intermediate_code_internal(cris_env_get_cpu(env), tb, false);
-}
-
-void gen_intermediate_code_pc (CPUCRISState *env, struct TranslationBlock *tb)
-{
- gen_intermediate_code_internal(cris_env_get_cpu(env), tb, true);
-}
-
void cris_cpu_dump_state(CPUState *cs, FILE *f, fprintf_function cpu_fprintf,
int flags)
{
@@ -3443,7 +3395,8 @@ void cris_initialize_tcg(void)
}
}
-void restore_state_to_opc(CPUCRISState *env, TranslationBlock *tb, int pc_pos)
+void restore_state_to_opc(CPUCRISState *env, TranslationBlock *tb,
+ target_ulong *data)
{
- env->pc = tcg_ctx.gen_opc_pc[pc_pos];
+ env->pc = data[0];
}
diff --git a/target-cris/translate_v10.c b/target-cris/translate_v10.c
index da0b2ca..3ab1c39 100644
--- a/target-cris/translate_v10.c
+++ b/target-cris/translate_v10.c
@@ -1199,9 +1199,6 @@ static unsigned int crisv10_decoder(CPUCRISState *env, DisasContext *dc)
{
unsigned int insn_len = 2;
- if (unlikely(qemu_loglevel_mask(CPU_LOG_TB_OP)))
- tcg_gen_debug_insn_start(dc->pc);
-
/* Load a halfword onto the instruction register. */
dc->ir = cpu_lduw_code(env, dc->pc);
diff --git a/target-i386/cpu.h b/target-i386/cpu.h
index 8926780..54d9d50 100644
--- a/target-i386/cpu.h
+++ b/target-i386/cpu.h
@@ -794,6 +794,7 @@ typedef struct {
#define MAX_GP_COUNTERS (MSR_IA32_PERF_STATUS - MSR_P6_EVNTSEL0)
#define NB_MMU_MODES 3
+#define TARGET_INSN_START_EXTRA_WORDS 1
#define NB_OPMASK_REGS 8
@@ -1188,7 +1189,6 @@ uint64_t cpu_get_tsc(CPUX86State *env);
#define cpu_init(cpu_model) CPU(cpu_x86_init(cpu_model))
#define cpu_exec cpu_x86_exec
-#define cpu_gen_code cpu_x86_gen_code
#define cpu_signal_handler cpu_x86_signal_handler
#define cpu_list x86_cpu_list
#define cpudef_setup x86_cpudef_setup
diff --git a/target-i386/translate.c b/target-i386/translate.c
index 8b35de1..ef10e68 100644
--- a/target-i386/translate.c
+++ b/target-i386/translate.c
@@ -75,8 +75,6 @@ static TCGv_ptr cpu_ptr0, cpu_ptr1;
static TCGv_i32 cpu_tmp2_i32, cpu_tmp3_i32;
static TCGv_i64 cpu_tmp1_i64;
-static uint8_t gen_opc_cc_op[OPC_BUF_SIZE];
-
#include "exec/gen-icount.h"
#ifdef TARGET_X86_64
@@ -4401,9 +4399,6 @@ static target_ulong disas_insn(CPUX86State *env, DisasContext *s,
target_ulong next_eip, tval;
int rex_w, rex_r;
- if (unlikely(qemu_loglevel_mask(CPU_LOG_TB_OP | CPU_LOG_TB_OP_OPT))) {
- tcg_gen_debug_insn_start(pc_start);
- }
s->pc = pc_start;
prefixes = 0;
s->override = -1;
@@ -7842,18 +7837,13 @@ void optimize_flags_init(void)
}
/* generate intermediate code in gen_opc_buf and gen_opparam_buf for
- basic block 'tb'. If search_pc is TRUE, also generate PC
- information for each intermediate instruction. */
-static inline void gen_intermediate_code_internal(X86CPU *cpu,
- TranslationBlock *tb,
- bool search_pc)
+ basic block 'tb'. */
+void gen_intermediate_code(CPUX86State *env, TranslationBlock *tb)
{
+ X86CPU *cpu = x86_env_get_cpu(env);
CPUState *cs = CPU(cpu);
- CPUX86State *env = &cpu->env;
DisasContext dc1, *dc = &dc1;
target_ulong pc_ptr;
- CPUBreakpoint *bp;
- int j, lj;
uint64_t flags;
target_ulong pc_start;
target_ulong cs_base;
@@ -7933,40 +7923,32 @@ static inline void gen_intermediate_code_internal(X86CPU *cpu,
dc->is_jmp = DISAS_NEXT;
pc_ptr = pc_start;
- lj = -1;
num_insns = 0;
max_insns = tb->cflags & CF_COUNT_MASK;
- if (max_insns == 0)
+ if (max_insns == 0) {
max_insns = CF_COUNT_MASK;
+ }
+ if (max_insns > TCG_MAX_INSNS) {
+ max_insns = TCG_MAX_INSNS;
+ }
gen_tb_start(tb);
for(;;) {
- if (unlikely(!QTAILQ_EMPTY(&cs->breakpoints))) {
- QTAILQ_FOREACH(bp, &cs->breakpoints, entry) {
- if (bp->pc == pc_ptr &&
- !((bp->flags & BP_CPU) && (tb->flags & HF_RF_MASK))) {
- gen_debug(dc, pc_ptr - dc->cs_base);
- goto done_generating;
- }
- }
- }
- if (search_pc) {
- j = tcg_op_buf_count();
- if (lj < j) {
- lj++;
- while (lj < j)
- tcg_ctx.gen_opc_instr_start[lj++] = 0;
- }
- tcg_ctx.gen_opc_pc[lj] = pc_ptr;
- gen_opc_cc_op[lj] = dc->cc_op;
- tcg_ctx.gen_opc_instr_start[lj] = 1;
- tcg_ctx.gen_opc_icount[lj] = num_insns;
+ tcg_gen_insn_start(pc_ptr, dc->cc_op);
+ num_insns++;
+
+ /* If RF is set, suppress an internally generated breakpoint. */
+ if (unlikely(cpu_breakpoint_test(cs, pc_ptr,
+ tb->flags & HF_RF_MASK
+ ? BP_GDB : BP_ANY))) {
+ gen_debug(dc, pc_ptr - dc->cs_base);
+ goto done_generating;
}
- if (num_insns + 1 == max_insns && (tb->cflags & CF_LAST_IO))
+ if (num_insns == max_insns && (tb->cflags & CF_LAST_IO)) {
gen_io_start();
+ }
pc_ptr = disas_insn(env, dc, pc_ptr);
- num_insns++;
/* stop translation if indicated */
if (dc->is_jmp)
break;
@@ -8014,14 +7996,6 @@ static inline void gen_intermediate_code_internal(X86CPU *cpu,
done_generating:
gen_tb_end(tb, num_insns);
- /* we don't forget to fill the last values */
- if (search_pc) {
- j = tcg_op_buf_count();
- lj++;
- while (lj <= j)
- tcg_ctx.gen_opc_instr_start[lj++] = 0;
- }
-
#ifdef DEBUG_DISAS
if (qemu_loglevel_mask(CPU_LOG_TB_IN_ASM)) {
int disas_flags;
@@ -8038,42 +8012,16 @@ done_generating:
}
#endif
- if (!search_pc) {
- tb->size = pc_ptr - pc_start;
- tb->icount = num_insns;
- }
+ tb->size = pc_ptr - pc_start;
+ tb->icount = num_insns;
}
-void gen_intermediate_code(CPUX86State *env, TranslationBlock *tb)
+void restore_state_to_opc(CPUX86State *env, TranslationBlock *tb,
+ target_ulong *data)
{
- gen_intermediate_code_internal(x86_env_get_cpu(env), tb, false);
-}
-
-void gen_intermediate_code_pc(CPUX86State *env, TranslationBlock *tb)
-{
- gen_intermediate_code_internal(x86_env_get_cpu(env), tb, true);
-}
-
-void restore_state_to_opc(CPUX86State *env, TranslationBlock *tb, int pc_pos)
-{
- int cc_op;
-#ifdef DEBUG_DISAS
- if (qemu_loglevel_mask(CPU_LOG_TB_OP)) {
- int i;
- qemu_log("RESTORE:\n");
- for(i = 0;i <= pc_pos; i++) {
- if (tcg_ctx.gen_opc_instr_start[i]) {
- qemu_log("0x%04x: " TARGET_FMT_lx "\n", i,
- tcg_ctx.gen_opc_pc[i]);
- }
- }
- qemu_log("pc_pos=0x%x eip=" TARGET_FMT_lx " cs_base=%x\n",
- pc_pos, tcg_ctx.gen_opc_pc[pc_pos] - tb->cs_base,
- (uint32_t)tb->cs_base);
- }
-#endif
- env->eip = tcg_ctx.gen_opc_pc[pc_pos] - tb->cs_base;
- cc_op = gen_opc_cc_op[pc_pos];
- if (cc_op != CC_OP_DYNAMIC)
+ int cc_op = data[1];
+ env->eip = data[0] - tb->cs_base;
+ if (cc_op != CC_OP_DYNAMIC) {
env->cc_op = cc_op;
+ }
}
diff --git a/target-lm32/cpu.h b/target-lm32/cpu.h
index 3f874d5..2b7620c 100644
--- a/target-lm32/cpu.h
+++ b/target-lm32/cpu.h
@@ -219,7 +219,6 @@ bool lm32_cpu_do_semihosting(CPUState *cs);
#define cpu_list lm32_cpu_list
#define cpu_exec cpu_lm32_exec
-#define cpu_gen_code cpu_lm32_gen_code
#define cpu_signal_handler cpu_lm32_signal_handler
int lm32_cpu_handle_mmu_fault(CPUState *cpu, vaddr address, int rw,
diff --git a/target-lm32/translate.c b/target-lm32/translate.c
index cf7042e..c61ad0f 100644
--- a/target-lm32/translate.c
+++ b/target-lm32/translate.c
@@ -1005,10 +1005,6 @@ static const DecoderInfo decinfo[] = {
static inline void decode(DisasContext *dc, uint32_t ir)
{
- if (unlikely(qemu_loglevel_mask(CPU_LOG_TB_OP | CPU_LOG_TB_OP_OPT))) {
- tcg_gen_debug_insn_start(dc->pc);
- }
-
dc->ir = ir;
LOG_DIS("%8.8x\t", dc->ir);
@@ -1036,32 +1032,13 @@ static inline void decode(DisasContext *dc, uint32_t ir)
decinfo[dc->opcode](dc);
}
-static void check_breakpoint(CPULM32State *env, DisasContext *dc)
-{
- CPUState *cs = CPU(lm32_env_get_cpu(env));
- CPUBreakpoint *bp;
-
- if (unlikely(!QTAILQ_EMPTY(&cs->breakpoints))) {
- QTAILQ_FOREACH(bp, &cs->breakpoints, entry) {
- if (bp->pc == dc->pc) {
- tcg_gen_movi_tl(cpu_pc, dc->pc);
- t_gen_raise_exception(dc, EXCP_DEBUG);
- dc->is_jmp = DISAS_UPDATE;
- }
- }
- }
-}
-
/* generate intermediate code for basic block 'tb'. */
-static inline
-void gen_intermediate_code_internal(LM32CPU *cpu,
- TranslationBlock *tb, bool search_pc)
+void gen_intermediate_code(CPULM32State *env, struct TranslationBlock *tb)
{
+ LM32CPU *cpu = lm32_env_get_cpu(env);
CPUState *cs = CPU(cpu);
- CPULM32State *env = &cpu->env;
struct DisasContext ctx, *dc = &ctx;
uint32_t pc_start;
- int j, lj;
uint32_t next_page_start;
int num_insns;
int max_insns;
@@ -1083,41 +1060,36 @@ void gen_intermediate_code_internal(LM32CPU *cpu,
}
next_page_start = (pc_start & TARGET_PAGE_MASK) + TARGET_PAGE_SIZE;
- lj = -1;
num_insns = 0;
max_insns = tb->cflags & CF_COUNT_MASK;
if (max_insns == 0) {
max_insns = CF_COUNT_MASK;
}
+ if (max_insns > TCG_MAX_INSNS) {
+ max_insns = TCG_MAX_INSNS;
+ }
gen_tb_start(tb);
do {
- check_breakpoint(env, dc);
-
- if (search_pc) {
- j = tcg_op_buf_count();
- if (lj < j) {
- lj++;
- while (lj < j) {
- tcg_ctx.gen_opc_instr_start[lj++] = 0;
- }
- }
- tcg_ctx.gen_opc_pc[lj] = dc->pc;
- tcg_ctx.gen_opc_instr_start[lj] = 1;
- tcg_ctx.gen_opc_icount[lj] = num_insns;
+ tcg_gen_insn_start(dc->pc);
+ num_insns++;
+
+ if (unlikely(cpu_breakpoint_test(cs, dc->pc, BP_ANY))) {
+ tcg_gen_movi_tl(cpu_pc, dc->pc);
+ t_gen_raise_exception(dc, EXCP_DEBUG);
+ dc->is_jmp = DISAS_UPDATE;
+ break;
}
/* Pretty disas. */
LOG_DIS("%8.8x:\t", dc->pc);
- if (num_insns + 1 == max_insns && (tb->cflags & CF_LAST_IO)) {
+ if (num_insns == max_insns && (tb->cflags & CF_LAST_IO)) {
gen_io_start();
}
decode(dc, cpu_ldl_code(env, dc->pc));
dc->pc += 4;
- num_insns++;
-
} while (!dc->is_jmp
&& !tcg_op_buf_full()
&& !cs->singlestep_enabled
@@ -1154,16 +1126,8 @@ void gen_intermediate_code_internal(LM32CPU *cpu,
gen_tb_end(tb, num_insns);
- if (search_pc) {
- j = tcg_op_buf_count();
- lj++;
- while (lj <= j) {
- tcg_ctx.gen_opc_instr_start[lj++] = 0;
- }
- } else {
- tb->size = dc->pc - pc_start;
- tb->icount = num_insns;
- }
+ tb->size = dc->pc - pc_start;
+ tb->icount = num_insns;
#ifdef DEBUG_DISAS
if (qemu_loglevel_mask(CPU_LOG_TB_IN_ASM)) {
@@ -1175,16 +1139,6 @@ void gen_intermediate_code_internal(LM32CPU *cpu,
#endif
}
-void gen_intermediate_code(CPULM32State *env, struct TranslationBlock *tb)
-{
- gen_intermediate_code_internal(lm32_env_get_cpu(env), tb, false);
-}
-
-void gen_intermediate_code_pc(CPULM32State *env, struct TranslationBlock *tb)
-{
- gen_intermediate_code_internal(lm32_env_get_cpu(env), tb, true);
-}
-
void lm32_cpu_dump_state(CPUState *cs, FILE *f, fprintf_function cpu_fprintf,
int flags)
{
@@ -1219,9 +1173,10 @@ void lm32_cpu_dump_state(CPUState *cs, FILE *f, fprintf_function cpu_fprintf,
cpu_fprintf(f, "\n\n");
}
-void restore_state_to_opc(CPULM32State *env, TranslationBlock *tb, int pc_pos)
+void restore_state_to_opc(CPULM32State *env, TranslationBlock *tb,
+ target_ulong *data)
{
- env->pc = tcg_ctx.gen_opc_pc[pc_pos];
+ env->pc = data[0];
}
void lm32_translate_init(void)
diff --git a/target-m68k/cpu.h b/target-m68k/cpu.h
index d195706..224c169 100644
--- a/target-m68k/cpu.h
+++ b/target-m68k/cpu.h
@@ -213,7 +213,6 @@ void register_m68k_insns (CPUM68KState *env);
#define cpu_init(cpu_model) CPU(cpu_m68k_init(cpu_model))
#define cpu_exec cpu_m68k_exec
-#define cpu_gen_code cpu_m68k_gen_code
#define cpu_signal_handler cpu_m68k_signal_handler
#define cpu_list m68k_cpu_list
diff --git a/target-m68k/translate.c b/target-m68k/translate.c
index 3cdf665..5995cce 100644
--- a/target-m68k/translate.c
+++ b/target-m68k/translate.c
@@ -2955,10 +2955,6 @@ static void disas_m68k_insn(CPUM68KState * env, DisasContext *s)
{
uint16_t insn;
- if (unlikely(qemu_loglevel_mask(CPU_LOG_TB_OP | CPU_LOG_TB_OP_OPT))) {
- tcg_gen_debug_insn_start(s->pc);
- }
-
insn = cpu_lduw_code(env, s->pc);
s->pc += 2;
@@ -2966,15 +2962,11 @@ static void disas_m68k_insn(CPUM68KState * env, DisasContext *s)
}
/* generate intermediate code for basic block 'tb'. */
-static inline void
-gen_intermediate_code_internal(M68kCPU *cpu, TranslationBlock *tb,
- bool search_pc)
+void gen_intermediate_code(CPUM68KState *env, TranslationBlock *tb)
{
+ M68kCPU *cpu = m68k_env_get_cpu(env);
CPUState *cs = CPU(cpu);
- CPUM68KState *env = &cpu->env;
DisasContext dc1, *dc = &dc1;
- CPUBreakpoint *bp;
- int j, lj;
target_ulong pc_start;
int pc_offset;
int num_insns;
@@ -2993,43 +2985,34 @@ gen_intermediate_code_internal(M68kCPU *cpu, TranslationBlock *tb,
dc->fpcr = env->fpcr;
dc->user = (env->sr & SR_S) == 0;
dc->done_mac = 0;
- lj = -1;
num_insns = 0;
max_insns = tb->cflags & CF_COUNT_MASK;
- if (max_insns == 0)
+ if (max_insns == 0) {
max_insns = CF_COUNT_MASK;
+ }
+ if (max_insns > TCG_MAX_INSNS) {
+ max_insns = TCG_MAX_INSNS;
+ }
gen_tb_start(tb);
do {
pc_offset = dc->pc - pc_start;
gen_throws_exception = NULL;
- if (unlikely(!QTAILQ_EMPTY(&cs->breakpoints))) {
- QTAILQ_FOREACH(bp, &cs->breakpoints, entry) {
- if (bp->pc == dc->pc) {
- gen_exception(dc, dc->pc, EXCP_DEBUG);
- dc->is_jmp = DISAS_JUMP;
- break;
- }
- }
- if (dc->is_jmp)
- break;
- }
- if (search_pc) {
- j = tcg_op_buf_count();
- if (lj < j) {
- lj++;
- while (lj < j)
- tcg_ctx.gen_opc_instr_start[lj++] = 0;
- }
- tcg_ctx.gen_opc_pc[lj] = dc->pc;
- tcg_ctx.gen_opc_instr_start[lj] = 1;
- tcg_ctx.gen_opc_icount[lj] = num_insns;
+ tcg_gen_insn_start(dc->pc);
+ num_insns++;
+
+ if (unlikely(cpu_breakpoint_test(cs, dc->pc, BP_ANY))) {
+ gen_exception(dc, dc->pc, EXCP_DEBUG);
+ dc->is_jmp = DISAS_JUMP;
+ break;
}
- if (num_insns + 1 == max_insns && (tb->cflags & CF_LAST_IO))
+
+ if (num_insns == max_insns && (tb->cflags & CF_LAST_IO)) {
gen_io_start();
+ }
+
dc->insn_pc = dc->pc;
disas_m68k_insn(env, dc);
- num_insns++;
} while (!dc->is_jmp && !tcg_op_buf_full() &&
!cs->singlestep_enabled &&
!singlestep &&
@@ -3073,28 +3056,8 @@ gen_intermediate_code_internal(M68kCPU *cpu, TranslationBlock *tb,
qemu_log("\n");
}
#endif
- if (search_pc) {
- j = tcg_op_buf_count();
- lj++;
- while (lj <= j)
- tcg_ctx.gen_opc_instr_start[lj++] = 0;
- } else {
- tb->size = dc->pc - pc_start;
- tb->icount = num_insns;
- }
-
- //optimize_flags();
- //expand_target_qops();
-}
-
-void gen_intermediate_code(CPUM68KState *env, TranslationBlock *tb)
-{
- gen_intermediate_code_internal(m68k_env_get_cpu(env), tb, false);
-}
-
-void gen_intermediate_code_pc(CPUM68KState *env, TranslationBlock *tb)
-{
- gen_intermediate_code_internal(m68k_env_get_cpu(env), tb, true);
+ tb->size = dc->pc - pc_start;
+ tb->icount = num_insns;
}
void m68k_cpu_dump_state(CPUState *cs, FILE *f, fprintf_function cpu_fprintf,
@@ -3120,7 +3083,8 @@ void m68k_cpu_dump_state(CPUState *cs, FILE *f, fprintf_function cpu_fprintf,
cpu_fprintf (f, "FPRESULT = %12g\n", *(double *)&env->fp_result);
}
-void restore_state_to_opc(CPUM68KState *env, TranslationBlock *tb, int pc_pos)
+void restore_state_to_opc(CPUM68KState *env, TranslationBlock *tb,
+ target_ulong *data)
{
- env->pc = tcg_ctx.gen_opc_pc[pc_pos];
+ env->pc = data[0];
}
diff --git a/target-microblaze/cpu.h b/target-microblaze/cpu.h
index b707c71..6b212ab 100644
--- a/target-microblaze/cpu.h
+++ b/target-microblaze/cpu.h
@@ -295,7 +295,6 @@ int cpu_mb_signal_handler(int host_signum, void *pinfo,
#define cpu_init(cpu_model) CPU(cpu_mb_init(cpu_model))
#define cpu_exec cpu_mb_exec
-#define cpu_gen_code cpu_mb_gen_code
#define cpu_signal_handler cpu_mb_signal_handler
/* MMU modes definitions */
diff --git a/target-microblaze/op_helper.c b/target-microblaze/op_helper.c
index 092c4b5..d324347 100644
--- a/target-microblaze/op_helper.c
+++ b/target-microblaze/op_helper.c
@@ -150,9 +150,7 @@ uint32_t helper_clz(uint32_t t0)
uint32_t helper_carry(uint32_t a, uint32_t b, uint32_t cf)
{
- uint32_t ncf;
- ncf = compute_carry(a, b, cf);
- return ncf;
+ return compute_carry(a, b, cf);
}
static inline int div_prepare(CPUMBState *env, uint32_t a, uint32_t b)
diff --git a/target-microblaze/translate.c b/target-microblaze/translate.c
index 3de8944..a9c5010 100644
--- a/target-microblaze/translate.c
+++ b/target-microblaze/translate.c
@@ -1588,10 +1588,6 @@ static inline void decode(DisasContext *dc, uint32_t ir)
{
int i;
- if (unlikely(qemu_loglevel_mask(CPU_LOG_TB_OP | CPU_LOG_TB_OP_OPT))) {
- tcg_gen_debug_insn_start(dc->pc);
- }
-
dc->ir = ir;
LOG_DIS("%8.8x\t", dc->ir);
@@ -1630,30 +1626,12 @@ static inline void decode(DisasContext *dc, uint32_t ir)
}
}
-static void check_breakpoint(CPUMBState *env, DisasContext *dc)
-{
- CPUState *cs = CPU(mb_env_get_cpu(env));
- CPUBreakpoint *bp;
-
- if (unlikely(!QTAILQ_EMPTY(&cs->breakpoints))) {
- QTAILQ_FOREACH(bp, &cs->breakpoints, entry) {
- if (bp->pc == dc->pc) {
- t_gen_raise_exception(dc, EXCP_DEBUG);
- dc->is_jmp = DISAS_UPDATE;
- }
- }
- }
-}
-
/* generate intermediate code for basic block 'tb'. */
-static inline void
-gen_intermediate_code_internal(MicroBlazeCPU *cpu, TranslationBlock *tb,
- bool search_pc)
+void gen_intermediate_code(CPUMBState *env, struct TranslationBlock *tb)
{
+ MicroBlazeCPU *cpu = mb_env_get_cpu(env);
CPUState *cs = CPU(cpu);
- CPUMBState *env = &cpu->env;
uint32_t pc_start;
- int j, lj;
struct DisasContext ctx;
struct DisasContext *dc = &ctx;
uint32_t next_page_start, org_flags;
@@ -1690,47 +1668,46 @@ gen_intermediate_code_internal(MicroBlazeCPU *cpu, TranslationBlock *tb,
}
next_page_start = (pc_start & TARGET_PAGE_MASK) + TARGET_PAGE_SIZE;
- lj = -1;
num_insns = 0;
max_insns = tb->cflags & CF_COUNT_MASK;
- if (max_insns == 0)
+ if (max_insns == 0) {
max_insns = CF_COUNT_MASK;
+ }
+ if (max_insns > TCG_MAX_INSNS) {
+ max_insns = TCG_MAX_INSNS;
+ }
gen_tb_start(tb);
do
{
+ tcg_gen_insn_start(dc->pc);
+ num_insns++;
+
#if SIM_COMPAT
if (qemu_loglevel_mask(CPU_LOG_TB_IN_ASM)) {
tcg_gen_movi_tl(cpu_SR[SR_PC], dc->pc);
gen_helper_debug();
}
#endif
- check_breakpoint(env, dc);
-
- if (search_pc) {
- j = tcg_op_buf_count();
- if (lj < j) {
- lj++;
- while (lj < j)
- tcg_ctx.gen_opc_instr_start[lj++] = 0;
- }
- tcg_ctx.gen_opc_pc[lj] = dc->pc;
- tcg_ctx.gen_opc_instr_start[lj] = 1;
- tcg_ctx.gen_opc_icount[lj] = num_insns;
+
+ if (unlikely(cpu_breakpoint_test(cs, dc->pc, BP_ANY))) {
+ t_gen_raise_exception(dc, EXCP_DEBUG);
+ dc->is_jmp = DISAS_UPDATE;
+ break;
}
/* Pretty disas. */
LOG_DIS("%8.8x:\t", dc->pc);
- if (num_insns + 1 == max_insns && (tb->cflags & CF_LAST_IO))
+ if (num_insns == max_insns && (tb->cflags & CF_LAST_IO)) {
gen_io_start();
+ }
dc->clear_imm = 1;
decode(dc, cpu_ldl_code(env, dc->pc));
if (dc->clear_imm)
dc->tb_flags &= ~IMM_FLAG;
dc->pc += 4;
- num_insns++;
if (dc->delayed_branch) {
dc->delayed_branch--;
@@ -1821,15 +1798,8 @@ gen_intermediate_code_internal(MicroBlazeCPU *cpu, TranslationBlock *tb,
}
gen_tb_end(tb, num_insns);
- if (search_pc) {
- j = tcg_op_buf_count();
- lj++;
- while (lj <= j)
- tcg_ctx.gen_opc_instr_start[lj++] = 0;
- } else {
- tb->size = dc->pc - pc_start;
- tb->icount = num_insns;
- }
+ tb->size = dc->pc - pc_start;
+ tb->icount = num_insns;
#ifdef DEBUG_DISAS
#if !SIM_COMPAT
@@ -1846,16 +1816,6 @@ gen_intermediate_code_internal(MicroBlazeCPU *cpu, TranslationBlock *tb,
assert(!dc->abort_at_next_insn);
}
-void gen_intermediate_code (CPUMBState *env, struct TranslationBlock *tb)
-{
- gen_intermediate_code_internal(mb_env_get_cpu(env), tb, false);
-}
-
-void gen_intermediate_code_pc (CPUMBState *env, struct TranslationBlock *tb)
-{
- gen_intermediate_code_internal(mb_env_get_cpu(env), tb, true);
-}
-
void mb_cpu_dump_state(CPUState *cs, FILE *f, fprintf_function cpu_fprintf,
int flags)
{
@@ -1936,7 +1896,8 @@ void mb_tcg_init(void)
}
}
-void restore_state_to_opc(CPUMBState *env, TranslationBlock *tb, int pc_pos)
+void restore_state_to_opc(CPUMBState *env, TranslationBlock *tb,
+ target_ulong *data)
{
- env->sregs[SR_PC] = tcg_ctx.gen_opc_pc[pc_pos];
+ env->sregs[SR_PC] = data[0];
}
diff --git a/target-mips/cpu.h b/target-mips/cpu.h
index ec5f991..f32a0fd 100644
--- a/target-mips/cpu.h
+++ b/target-mips/cpu.h
@@ -130,6 +130,7 @@ struct CPUMIPSFPUContext {
};
#define NB_MMU_MODES 3
+#define TARGET_INSN_START_EXTRA_WORDS 2
typedef struct CPUMIPSMVPContext CPUMIPSMVPContext;
struct CPUMIPSMVPContext {
@@ -619,7 +620,6 @@ void mips_cpu_unassigned_access(CPUState *cpu, hwaddr addr,
void mips_cpu_list (FILE *f, fprintf_function cpu_fprintf);
#define cpu_exec cpu_mips_exec
-#define cpu_gen_code cpu_mips_gen_code
#define cpu_signal_handler cpu_mips_signal_handler
#define cpu_list mips_cpu_list
diff --git a/target-mips/translate.c b/target-mips/translate.c
index 87d4959..897839c 100644
--- a/target-mips/translate.c
+++ b/target-mips/translate.c
@@ -1359,9 +1359,6 @@ static TCGv_i32 fpu_fcr0, fpu_fcr31;
static TCGv_i64 fpu_f64[32];
static TCGv_i64 msa_wr_d[64];
-static uint32_t gen_opc_hflags[OPC_BUF_SIZE];
-static target_ulong gen_opc_btarget[OPC_BUF_SIZE];
-
#include "exec/gen-icount.h"
#define gen_helper_0e0i(name, arg) do { \
@@ -18904,10 +18901,6 @@ static void decode_opc(CPUMIPSState *env, DisasContext *ctx)
gen_set_label(l1);
}
- if (unlikely(qemu_loglevel_mask(CPU_LOG_TB_OP | CPU_LOG_TB_OP_OPT))) {
- tcg_gen_debug_insn_start(ctx->pc);
- }
-
op = MASK_OP_MAJOR(ctx->opcode);
rs = (ctx->opcode >> 21) & 0x1f;
rt = (ctx->opcode >> 16) & 0x1f;
@@ -19539,25 +19532,18 @@ static void decode_opc(CPUMIPSState *env, DisasContext *ctx)
}
}
-static inline void
-gen_intermediate_code_internal(MIPSCPU *cpu, TranslationBlock *tb,
- bool search_pc)
+void gen_intermediate_code(CPUMIPSState *env, struct TranslationBlock *tb)
{
+ MIPSCPU *cpu = mips_env_get_cpu(env);
CPUState *cs = CPU(cpu);
- CPUMIPSState *env = &cpu->env;
DisasContext ctx;
target_ulong pc_start;
target_ulong next_page_start;
- CPUBreakpoint *bp;
- int j, lj = -1;
int num_insns;
int max_insns;
int insn_bytes;
int is_slot;
- if (search_pc)
- qemu_log("search pc %d\n", search_pc);
-
pc_start = tb->pc;
next_page_start = (pc_start & TARGET_PAGE_MASK) + TARGET_PAGE_SIZE;
ctx.pc = pc_start;
@@ -19567,6 +19553,7 @@ gen_intermediate_code_internal(MIPSCPU *cpu, TranslationBlock *tb,
ctx.CP0_Config1 = env->CP0_Config1;
ctx.tb = tb;
ctx.bstate = BS_NONE;
+ ctx.btarget = 0;
ctx.kscrexist = (env->CP0_Config4 >> CP0C4_KScrExist) & 0xff;
ctx.rxi = (env->CP0_Config3 >> CP0C3_RXI) & 1;
ctx.ie = (env->CP0_Config4 >> CP0C4_IE) & 3;
@@ -19590,40 +19577,32 @@ gen_intermediate_code_internal(MIPSCPU *cpu, TranslationBlock *tb,
MO_UNALN : MO_ALIGN;
num_insns = 0;
max_insns = tb->cflags & CF_COUNT_MASK;
- if (max_insns == 0)
+ if (max_insns == 0) {
max_insns = CF_COUNT_MASK;
+ }
+ if (max_insns > TCG_MAX_INSNS) {
+ max_insns = TCG_MAX_INSNS;
+ }
+
LOG_DISAS("\ntb %p idx %d hflags %04x\n", tb, ctx.mem_idx, ctx.hflags);
gen_tb_start(tb);
while (ctx.bstate == BS_NONE) {
- if (unlikely(!QTAILQ_EMPTY(&cs->breakpoints))) {
- QTAILQ_FOREACH(bp, &cs->breakpoints, entry) {
- if (bp->pc == ctx.pc) {
- save_cpu_state(&ctx, 1);
- ctx.bstate = BS_BRANCH;
- gen_helper_raise_exception_debug(cpu_env);
- /* Include the breakpoint location or the tb won't
- * be flushed when it must be. */
- ctx.pc += 4;
- goto done_generating;
- }
- }
- }
+ tcg_gen_insn_start(ctx.pc, ctx.hflags & MIPS_HFLAG_BMASK, ctx.btarget);
+ num_insns++;
- if (search_pc) {
- j = tcg_op_buf_count();
- if (lj < j) {
- lj++;
- while (lj < j)
- tcg_ctx.gen_opc_instr_start[lj++] = 0;
- }
- tcg_ctx.gen_opc_pc[lj] = ctx.pc;
- gen_opc_hflags[lj] = ctx.hflags & MIPS_HFLAG_BMASK;
- gen_opc_btarget[lj] = ctx.btarget;
- tcg_ctx.gen_opc_instr_start[lj] = 1;
- tcg_ctx.gen_opc_icount[lj] = num_insns;
+ if (unlikely(cpu_breakpoint_test(cs, ctx.pc, BP_ANY))) {
+ save_cpu_state(&ctx, 1);
+ ctx.bstate = BS_BRANCH;
+ gen_helper_raise_exception_debug(cpu_env);
+ /* Include the breakpoint location or the tb won't
+ * be flushed when it must be. */
+ ctx.pc += 4;
+ goto done_generating;
}
- if (num_insns + 1 == max_insns && (tb->cflags & CF_LAST_IO))
+
+ if (num_insns == max_insns && (tb->cflags & CF_LAST_IO)) {
gen_io_start();
+ }
is_slot = ctx.hflags & MIPS_HFLAG_BMASK;
if (!(ctx.hflags & MIPS_HFLAG_M16)) {
@@ -19660,8 +19639,6 @@ gen_intermediate_code_internal(MIPSCPU *cpu, TranslationBlock *tb,
}
ctx.pc += insn_bytes;
- num_insns++;
-
/* Execute a branch and its delay slot as a single instruction.
This is what GDB expects and is consistent with what the
hardware does (e.g. if a delay slot instruction faults, the
@@ -19710,15 +19687,9 @@ gen_intermediate_code_internal(MIPSCPU *cpu, TranslationBlock *tb,
done_generating:
gen_tb_end(tb, num_insns);
- if (search_pc) {
- j = tcg_op_buf_count();
- lj++;
- while (lj <= j)
- tcg_ctx.gen_opc_instr_start[lj++] = 0;
- } else {
- tb->size = ctx.pc - pc_start;
- tb->icount = num_insns;
- }
+ tb->size = ctx.pc - pc_start;
+ tb->icount = num_insns;
+
#ifdef DEBUG_DISAS
LOG_DISAS("\n");
if (qemu_loglevel_mask(CPU_LOG_TB_IN_ASM)) {
@@ -19729,16 +19700,6 @@ done_generating:
#endif
}
-void gen_intermediate_code (CPUMIPSState *env, struct TranslationBlock *tb)
-{
- gen_intermediate_code_internal(mips_env_get_cpu(env), tb, false);
-}
-
-void gen_intermediate_code_pc (CPUMIPSState *env, struct TranslationBlock *tb)
-{
- gen_intermediate_code_internal(mips_env_get_cpu(env), tb, true);
-}
-
static void fpu_dump_state(CPUMIPSState *env, FILE *f, fprintf_function fpu_fprintf,
int flags)
{
@@ -20062,18 +20023,19 @@ void cpu_state_reset(CPUMIPSState *env)
}
}
-void restore_state_to_opc(CPUMIPSState *env, TranslationBlock *tb, int pc_pos)
+void restore_state_to_opc(CPUMIPSState *env, TranslationBlock *tb,
+ target_ulong *data)
{
- env->active_tc.PC = tcg_ctx.gen_opc_pc[pc_pos];
+ env->active_tc.PC = data[0];
env->hflags &= ~MIPS_HFLAG_BMASK;
- env->hflags |= gen_opc_hflags[pc_pos];
+ env->hflags |= data[1];
switch (env->hflags & MIPS_HFLAG_BMASK_BASE) {
case MIPS_HFLAG_BR:
break;
case MIPS_HFLAG_BC:
case MIPS_HFLAG_BL:
case MIPS_HFLAG_B:
- env->btarget = gen_opc_btarget[pc_pos];
+ env->btarget = data[2];
break;
}
}
diff --git a/target-moxie/cpu.h b/target-moxie/cpu.h
index 2bac15b..a612744 100644
--- a/target-moxie/cpu.h
+++ b/target-moxie/cpu.h
@@ -122,7 +122,6 @@ int cpu_moxie_signal_handler(int host_signum, void *pinfo,
#define cpu_init(cpu_model) CPU(cpu_moxie_init(cpu_model))
#define cpu_exec cpu_moxie_exec
-#define cpu_gen_code cpu_moxie_gen_code
#define cpu_signal_handler cpu_moxie_signal_handler
static inline int cpu_mmu_index(CPUMoxieState *env, bool ifetch)
diff --git a/target-moxie/translate.c b/target-moxie/translate.c
index cc77366..f84841e 100644
--- a/target-moxie/translate.c
+++ b/target-moxie/translate.c
@@ -153,10 +153,6 @@ static int decode_opc(MoxieCPU *cpu, DisasContext *ctx)
/* Set the default instruction length. */
int length = 2;
- if (unlikely(qemu_loglevel_mask(CPU_LOG_TB_OP | CPU_LOG_TB_OP_OPT))) {
- tcg_gen_debug_insn_start(ctx->pc);
- }
-
/* Examine the 16-bit opcode. */
opcode = ctx->opcode;
@@ -819,17 +815,13 @@ static int decode_opc(MoxieCPU *cpu, DisasContext *ctx)
}
/* generate intermediate code for basic block 'tb'. */
-static inline void
-gen_intermediate_code_internal(MoxieCPU *cpu, TranslationBlock *tb,
- bool search_pc)
+void gen_intermediate_code(CPUMoxieState *env, struct TranslationBlock *tb)
{
+ MoxieCPU *cpu = moxie_env_get_cpu(env);
CPUState *cs = CPU(cpu);
DisasContext ctx;
target_ulong pc_start;
- CPUBreakpoint *bp;
- int j, lj = -1;
- CPUMoxieState *env = &cpu->env;
- int num_insns;
+ int num_insns, max_insns;
pc_start = tb->pc;
ctx.pc = pc_start;
@@ -839,40 +831,35 @@ gen_intermediate_code_internal(MoxieCPU *cpu, TranslationBlock *tb,
ctx.singlestep_enabled = 0;
ctx.bstate = BS_NONE;
num_insns = 0;
+ max_insns = tb->cflags & CF_COUNT_MASK;
+ if (max_insns == 0) {
+ max_insns = CF_COUNT_MASK;
+ }
+ if (max_insns > TCG_MAX_INSNS) {
+ max_insns = TCG_MAX_INSNS;
+ }
gen_tb_start(tb);
do {
- if (unlikely(!QTAILQ_EMPTY(&cs->breakpoints))) {
- QTAILQ_FOREACH(bp, &cs->breakpoints, entry) {
- if (ctx.pc == bp->pc) {
- tcg_gen_movi_i32(cpu_pc, ctx.pc);
- gen_helper_debug(cpu_env);
- ctx.bstate = BS_EXCP;
- goto done_generating;
- }
- }
- }
+ tcg_gen_insn_start(ctx.pc);
+ num_insns++;
- if (search_pc) {
- j = tcg_op_buf_count();
- if (lj < j) {
- lj++;
- while (lj < j) {
- tcg_ctx.gen_opc_instr_start[lj++] = 0;
- }
- }
- tcg_ctx.gen_opc_pc[lj] = ctx.pc;
- tcg_ctx.gen_opc_instr_start[lj] = 1;
- tcg_ctx.gen_opc_icount[lj] = num_insns;
+ if (unlikely(cpu_breakpoint_test(cs, ctx.pc, BP_ANY))) {
+ tcg_gen_movi_i32(cpu_pc, ctx.pc);
+ gen_helper_debug(cpu_env);
+ ctx.bstate = BS_EXCP;
+ goto done_generating;
}
+
ctx.opcode = cpu_lduw_code(env, ctx.pc);
ctx.pc += decode_opc(cpu, &ctx);
- num_insns++;
+ if (num_insns >= max_insns) {
+ break;
+ }
if (cs->singlestep_enabled) {
break;
}
-
if ((ctx.pc & (TARGET_PAGE_SIZE - 1)) == 0) {
break;
}
@@ -898,29 +885,12 @@ gen_intermediate_code_internal(MoxieCPU *cpu, TranslationBlock *tb,
done_generating:
gen_tb_end(tb, num_insns);
- if (search_pc) {
- j = tcg_op_buf_count();
- lj++;
- while (lj <= j) {
- tcg_ctx.gen_opc_instr_start[lj++] = 0;
- }
- } else {
- tb->size = ctx.pc - pc_start;
- tb->icount = num_insns;
- }
-}
-
-void gen_intermediate_code(CPUMoxieState *env, struct TranslationBlock *tb)
-{
- gen_intermediate_code_internal(moxie_env_get_cpu(env), tb, false);
-}
-
-void gen_intermediate_code_pc(CPUMoxieState *env, struct TranslationBlock *tb)
-{
- gen_intermediate_code_internal(moxie_env_get_cpu(env), tb, true);
+ tb->size = ctx.pc - pc_start;
+ tb->icount = num_insns;
}
-void restore_state_to_opc(CPUMoxieState *env, TranslationBlock *tb, int pc_pos)
+void restore_state_to_opc(CPUMoxieState *env, TranslationBlock *tb,
+ target_ulong *data)
{
- env->pc = tcg_ctx.gen_opc_pc[pc_pos];
+ env->pc = data[0];
}
diff --git a/target-openrisc/cpu.h b/target-openrisc/cpu.h
index 1ff1c9e..eb71607 100644
--- a/target-openrisc/cpu.h
+++ b/target-openrisc/cpu.h
@@ -360,7 +360,6 @@ int cpu_openrisc_signal_handler(int host_signum, void *pinfo, void *puc);
#define cpu_list cpu_openrisc_list
#define cpu_exec cpu_openrisc_exec
-#define cpu_gen_code cpu_openrisc_gen_code
#define cpu_signal_handler cpu_openrisc_signal_handler
#ifndef CONFIG_USER_ONLY
diff --git a/target-openrisc/translate.c b/target-openrisc/translate.c
index 473556e..b66fde1 100644
--- a/target-openrisc/translate.c
+++ b/target-openrisc/translate.c
@@ -1618,30 +1618,12 @@ static void disas_openrisc_insn(DisasContext *dc, OpenRISCCPU *cpu)
}
}
-static void check_breakpoint(OpenRISCCPU *cpu, DisasContext *dc)
-{
- CPUState *cs = CPU(cpu);
- CPUBreakpoint *bp;
-
- if (unlikely(!QTAILQ_EMPTY(&cs->breakpoints))) {
- QTAILQ_FOREACH(bp, &cs->breakpoints, entry) {
- if (bp->pc == dc->pc) {
- tcg_gen_movi_tl(cpu_pc, dc->pc);
- gen_exception(dc, EXCP_DEBUG);
- dc->is_jmp = DISAS_UPDATE;
- }
- }
- }
-}
-
-static inline void gen_intermediate_code_internal(OpenRISCCPU *cpu,
- TranslationBlock *tb,
- int search_pc)
+void gen_intermediate_code(CPUOpenRISCState *env, struct TranslationBlock *tb)
{
+ OpenRISCCPU *cpu = openrisc_env_get_cpu(env);
CPUState *cs = CPU(cpu);
struct DisasContext ctx, *dc = &ctx;
uint32_t pc_start;
- int j, k;
uint32_t next_page_start;
int num_insns;
int max_insns;
@@ -1663,36 +1645,30 @@ static inline void gen_intermediate_code_internal(OpenRISCCPU *cpu,
}
next_page_start = (pc_start & TARGET_PAGE_MASK) + TARGET_PAGE_SIZE;
- k = -1;
num_insns = 0;
max_insns = tb->cflags & CF_COUNT_MASK;
if (max_insns == 0) {
max_insns = CF_COUNT_MASK;
}
+ if (max_insns > TCG_MAX_INSNS) {
+ max_insns = TCG_MAX_INSNS;
+ }
gen_tb_start(tb);
do {
- check_breakpoint(cpu, dc);
- if (search_pc) {
- j = tcg_op_buf_count();
- if (k < j) {
- k++;
- while (k < j) {
- tcg_ctx.gen_opc_instr_start[k++] = 0;
- }
- }
- tcg_ctx.gen_opc_pc[k] = dc->pc;
- tcg_ctx.gen_opc_instr_start[k] = 1;
- tcg_ctx.gen_opc_icount[k] = num_insns;
- }
+ tcg_gen_insn_start(dc->pc);
+ num_insns++;
- if (unlikely(qemu_loglevel_mask(CPU_LOG_TB_OP | CPU_LOG_TB_OP_OPT))) {
- tcg_gen_debug_insn_start(dc->pc);
+ if (unlikely(cpu_breakpoint_test(cs, dc->pc, BP_ANY))) {
+ tcg_gen_movi_tl(cpu_pc, dc->pc);
+ gen_exception(dc, EXCP_DEBUG);
+ dc->is_jmp = DISAS_UPDATE;
+ break;
}
- if (num_insns + 1 == max_insns && (tb->cflags & CF_LAST_IO)) {
+ if (num_insns == max_insns && (tb->cflags & CF_LAST_IO)) {
gen_io_start();
}
dc->ppc = dc->pc - 4;
@@ -1701,7 +1677,6 @@ static inline void gen_intermediate_code_internal(OpenRISCCPU *cpu,
tcg_gen_movi_tl(cpu_npc, dc->npc);
disas_openrisc_insn(dc, cpu);
dc->pc = dc->npc;
- num_insns++;
/* delay slot */
if (dc->delayed_branch) {
dc->delayed_branch--;
@@ -1756,16 +1731,8 @@ static inline void gen_intermediate_code_internal(OpenRISCCPU *cpu,
gen_tb_end(tb, num_insns);
- if (search_pc) {
- j = tcg_op_buf_count();
- k++;
- while (k <= j) {
- tcg_ctx.gen_opc_instr_start[k++] = 0;
- }
- } else {
- tb->size = dc->pc - pc_start;
- tb->icount = num_insns;
- }
+ tb->size = dc->pc - pc_start;
+ tb->icount = num_insns;
#ifdef DEBUG_DISAS
if (qemu_loglevel_mask(CPU_LOG_TB_IN_ASM)) {
@@ -1777,17 +1744,6 @@ static inline void gen_intermediate_code_internal(OpenRISCCPU *cpu,
#endif
}
-void gen_intermediate_code(CPUOpenRISCState *env, struct TranslationBlock *tb)
-{
- gen_intermediate_code_internal(openrisc_env_get_cpu(env), tb, 0);
-}
-
-void gen_intermediate_code_pc(CPUOpenRISCState *env,
- struct TranslationBlock *tb)
-{
- gen_intermediate_code_internal(openrisc_env_get_cpu(env), tb, 1);
-}
-
void openrisc_cpu_dump_state(CPUState *cs, FILE *f,
fprintf_function cpu_fprintf,
int flags)
@@ -1804,7 +1760,7 @@ void openrisc_cpu_dump_state(CPUState *cs, FILE *f,
}
void restore_state_to_opc(CPUOpenRISCState *env, TranslationBlock *tb,
- int pc_pos)
+ target_ulong *data)
{
- env->pc = tcg_ctx.gen_opc_pc[pc_pos];
+ env->pc = data[0];
}
diff --git a/target-ppc/cpu.h b/target-ppc/cpu.h
index c6dbb38..98ce5a7 100644
--- a/target-ppc/cpu.h
+++ b/target-ppc/cpu.h
@@ -1241,7 +1241,6 @@ int ppc_dcr_write (ppc_dcr_t *dcr_env, int dcrn, uint32_t val);
#define cpu_init(cpu_model) CPU(cpu_ppc_init(cpu_model))
#define cpu_exec cpu_ppc_exec
-#define cpu_gen_code cpu_ppc_gen_code
#define cpu_signal_handler cpu_ppc_signal_handler
#define cpu_list ppc_cpu_list
diff --git a/target-ppc/kvm.c b/target-ppc/kvm.c
index e641680..f8ea783 100644
--- a/target-ppc/kvm.c
+++ b/target-ppc/kvm.c
@@ -1782,8 +1782,7 @@ uint32_t kvmppc_get_tbfreq(void)
ns++;
- retval = atoi(ns);
- return retval;
+ return atoi(ns);
}
bool kvmppc_get_host_serial(char **value)
diff --git a/target-ppc/translate.c b/target-ppc/translate.c
index c0eed13..c2bc1a7 100644
--- a/target-ppc/translate.c
+++ b/target-ppc/translate.c
@@ -11409,17 +11409,13 @@ void ppc_cpu_dump_statistics(CPUState *cs, FILE*f,
}
/*****************************************************************************/
-static inline void gen_intermediate_code_internal(PowerPCCPU *cpu,
- TranslationBlock *tb,
- bool search_pc)
+void gen_intermediate_code(CPUPPCState *env, struct TranslationBlock *tb)
{
+ PowerPCCPU *cpu = ppc_env_get_cpu(env);
CPUState *cs = CPU(cpu);
- CPUPPCState *env = &cpu->env;
DisasContext ctx, *ctxp = &ctx;
opc_handler_t **table, *handler;
target_ulong pc_start;
- CPUBreakpoint *bp;
- int j, lj = -1;
int num_insns;
int max_insns;
@@ -11476,36 +11472,29 @@ static inline void gen_intermediate_code_internal(PowerPCCPU *cpu,
#endif
num_insns = 0;
max_insns = tb->cflags & CF_COUNT_MASK;
- if (max_insns == 0)
+ if (max_insns == 0) {
max_insns = CF_COUNT_MASK;
+ }
+ if (max_insns > TCG_MAX_INSNS) {
+ max_insns = TCG_MAX_INSNS;
+ }
gen_tb_start(tb);
tcg_clear_temp_count();
/* Set env in case of segfault during code fetch */
while (ctx.exception == POWERPC_EXCP_NONE && !tcg_op_buf_full()) {
- if (unlikely(!QTAILQ_EMPTY(&cs->breakpoints))) {
- QTAILQ_FOREACH(bp, &cs->breakpoints, entry) {
- if (bp->pc == ctx.nip) {
- gen_debug_exception(ctxp);
- break;
- }
- }
- }
- if (unlikely(search_pc)) {
- j = tcg_op_buf_count();
- if (lj < j) {
- lj++;
- while (lj < j)
- tcg_ctx.gen_opc_instr_start[lj++] = 0;
- }
- tcg_ctx.gen_opc_pc[lj] = ctx.nip;
- tcg_ctx.gen_opc_instr_start[lj] = 1;
- tcg_ctx.gen_opc_icount[lj] = num_insns;
+ tcg_gen_insn_start(ctx.nip);
+ num_insns++;
+
+ if (unlikely(cpu_breakpoint_test(cs, ctx.nip, BP_ANY))) {
+ gen_debug_exception(ctxp);
+ break;
}
+
LOG_DISAS("----------------\n");
LOG_DISAS("nip=" TARGET_FMT_lx " super=%d ir=%d\n",
ctx.nip, ctx.mem_idx, (int)msr_ir);
- if (num_insns + 1 == max_insns && (tb->cflags & CF_LAST_IO))
+ if (num_insns == max_insns && (tb->cflags & CF_LAST_IO))
gen_io_start();
if (unlikely(need_byteswap(&ctx))) {
ctx.opcode = bswap32(cpu_ldl_code(env, ctx.nip));
@@ -11515,12 +11504,8 @@ static inline void gen_intermediate_code_internal(PowerPCCPU *cpu,
LOG_DISAS("translate opcode %08x (%02x %02x %02x) (%s)\n",
ctx.opcode, opc1(ctx.opcode), opc2(ctx.opcode),
opc3(ctx.opcode), ctx.le_mode ? "little" : "big");
- if (unlikely(qemu_loglevel_mask(CPU_LOG_TB_OP | CPU_LOG_TB_OP_OPT))) {
- tcg_gen_debug_insn_start(ctx.nip);
- }
ctx.nip += 4;
table = env->opcodes;
- num_insns++;
handler = table[opc1(ctx.opcode)];
if (is_indirect_opcode(handler)) {
table = ind_table(handler);
@@ -11599,15 +11584,9 @@ static inline void gen_intermediate_code_internal(PowerPCCPU *cpu,
}
gen_tb_end(tb, num_insns);
- if (unlikely(search_pc)) {
- j = tcg_op_buf_count();
- lj++;
- while (lj <= j)
- tcg_ctx.gen_opc_instr_start[lj++] = 0;
- } else {
- tb->size = ctx.nip - pc_start;
- tb->icount = num_insns;
- }
+ tb->size = ctx.nip - pc_start;
+ tb->icount = num_insns;
+
#if defined(DEBUG_DISAS)
if (qemu_loglevel_mask(CPU_LOG_TB_IN_ASM)) {
int flags;
@@ -11620,17 +11599,8 @@ static inline void gen_intermediate_code_internal(PowerPCCPU *cpu,
#endif
}
-void gen_intermediate_code (CPUPPCState *env, struct TranslationBlock *tb)
-{
- gen_intermediate_code_internal(ppc_env_get_cpu(env), tb, false);
-}
-
-void gen_intermediate_code_pc (CPUPPCState *env, struct TranslationBlock *tb)
-{
- gen_intermediate_code_internal(ppc_env_get_cpu(env), tb, true);
-}
-
-void restore_state_to_opc(CPUPPCState *env, TranslationBlock *tb, int pc_pos)
+void restore_state_to_opc(CPUPPCState *env, TranslationBlock *tb,
+ target_ulong *data)
{
- env->nip = tcg_ctx.gen_opc_pc[pc_pos];
+ env->nip = data[0];
}
diff --git a/target-s390x/cpu.h b/target-s390x/cpu.h
index 5acd54c..e4de863 100644
--- a/target-s390x/cpu.h
+++ b/target-s390x/cpu.h
@@ -42,6 +42,7 @@
#include "fpu/softfloat.h"
#define NB_MMU_MODES 3
+#define TARGET_INSN_START_EXTRA_WORDS 1
#define MMU_MODE0_SUFFIX _primary
#define MMU_MODE1_SUFFIX _secondary
@@ -568,7 +569,7 @@ void cpu_unlock(void);
typedef struct SubchDev SubchDev;
#ifndef CONFIG_USER_ONLY
-extern void io_subsystem_reset(void);
+extern void subsystem_reset(void);
SubchDev *css_find_subch(uint8_t m, uint8_t cssid, uint8_t ssid,
uint16_t schid);
bool css_subch_visible(SubchDev *sch);
@@ -597,7 +598,6 @@ bool css_present(uint8_t cssid);
#define cpu_init(model) CPU(cpu_s390x_init(model))
#define cpu_exec cpu_s390x_exec
-#define cpu_gen_code cpu_s390x_gen_code
#define cpu_signal_handler cpu_s390x_signal_handler
void s390_cpu_list(FILE *f, fprintf_function cpu_fprintf);
diff --git a/target-s390x/gdbstub.c b/target-s390x/gdbstub.c
index 0c39a3c..a05d1cd 100644
--- a/target-s390x/gdbstub.c
+++ b/target-s390x/gdbstub.c
@@ -205,6 +205,82 @@ static int cpu_write_c_reg(CPUS390XState *env, uint8_t *mem_buf, int n)
return 0;
}
}
+
+/* the values represent the positions in s390-virt.xml */
+#define S390_VIRT_CKC_REGNUM 0
+#define S390_VIRT_CPUTM_REGNUM 1
+#define S390_VIRT_BEA_REGNUM 2
+#define S390_VIRT_PREFIX_REGNUM 3
+#define S390_VIRT_PP_REGNUM 4
+#define S390_VIRT_PFT_REGNUM 5
+#define S390_VIRT_PFS_REGNUM 6
+#define S390_VIRT_PFC_REGNUM 7
+/* total number of registers in s390-virt.xml */
+#define S390_NUM_VIRT_REGS 8
+
+static int cpu_read_virt_reg(CPUS390XState *env, uint8_t *mem_buf, int n)
+{
+ switch (n) {
+ case S390_VIRT_CKC_REGNUM:
+ return gdb_get_regl(mem_buf, env->ckc);
+ case S390_VIRT_CPUTM_REGNUM:
+ return gdb_get_regl(mem_buf, env->cputm);
+ case S390_VIRT_BEA_REGNUM:
+ return gdb_get_regl(mem_buf, env->gbea);
+ case S390_VIRT_PREFIX_REGNUM:
+ return gdb_get_regl(mem_buf, env->psa);
+ case S390_VIRT_PP_REGNUM:
+ return gdb_get_regl(mem_buf, env->pp);
+ case S390_VIRT_PFT_REGNUM:
+ return gdb_get_regl(mem_buf, env->pfault_token);
+ case S390_VIRT_PFS_REGNUM:
+ return gdb_get_regl(mem_buf, env->pfault_select);
+ case S390_VIRT_PFC_REGNUM:
+ return gdb_get_regl(mem_buf, env->pfault_compare);
+ default:
+ return 0;
+ }
+}
+
+static int cpu_write_virt_reg(CPUS390XState *env, uint8_t *mem_buf, int n)
+{
+ switch (n) {
+ case S390_VIRT_CKC_REGNUM:
+ env->ckc = ldtul_p(mem_buf);
+ cpu_synchronize_post_init(ENV_GET_CPU(env));
+ return 8;
+ case S390_VIRT_CPUTM_REGNUM:
+ env->cputm = ldtul_p(mem_buf);
+ cpu_synchronize_post_init(ENV_GET_CPU(env));
+ return 8;
+ case S390_VIRT_BEA_REGNUM:
+ env->gbea = ldtul_p(mem_buf);
+ cpu_synchronize_post_init(ENV_GET_CPU(env));
+ return 8;
+ case S390_VIRT_PREFIX_REGNUM:
+ env->psa = ldtul_p(mem_buf);
+ cpu_synchronize_post_init(ENV_GET_CPU(env));
+ return 8;
+ case S390_VIRT_PP_REGNUM:
+ env->pp = ldtul_p(mem_buf);
+ cpu_synchronize_post_init(ENV_GET_CPU(env));
+ return 8;
+ case S390_VIRT_PFT_REGNUM:
+ env->pfault_token = ldtul_p(mem_buf);
+ cpu_synchronize_post_init(ENV_GET_CPU(env));
+ return 8;
+ case S390_VIRT_PFS_REGNUM:
+ env->pfault_select = ldtul_p(mem_buf);
+ cpu_synchronize_post_init(ENV_GET_CPU(env));
+ return 8;
+ case S390_VIRT_PFC_REGNUM:
+ env->pfault_compare = ldtul_p(mem_buf);
+ cpu_synchronize_post_init(ENV_GET_CPU(env));
+ return 8;
+ default:
+ return 0;
+ }
+}
#endif
void s390_cpu_gdb_init(CPUState *cs)
@@ -225,5 +301,11 @@ void s390_cpu_gdb_init(CPUState *cs)
gdb_register_coprocessor(cs, cpu_read_c_reg,
cpu_write_c_reg,
S390_NUM_C_REGS, "s390-cr.xml", 0);
+
+ if (kvm_enabled()) {
+ gdb_register_coprocessor(cs, cpu_read_virt_reg,
+ cpu_write_virt_reg,
+ S390_NUM_VIRT_REGS, "s390-virt.xml", 0);
+ }
#endif
}
diff --git a/target-s390x/misc_helper.c b/target-s390x/misc_helper.c
index 8eac0e1..3a19e32 100644
--- a/target-s390x/misc_helper.c
+++ b/target-s390x/misc_helper.c
@@ -128,7 +128,7 @@ static int modified_clear_reset(S390CPU *cpu)
run_on_cpu(t, s390_do_cpu_full_reset, t);
}
cmma_reset(cpu);
- io_subsystem_reset();
+ subsystem_reset();
scc->load_normal(CPU(cpu));
cpu_synchronize_all_post_reset();
resume_all_vcpus();
@@ -146,7 +146,7 @@ static int load_normal_reset(S390CPU *cpu)
run_on_cpu(t, s390_do_cpu_reset, t);
}
cmma_reset(cpu);
- io_subsystem_reset();
+ subsystem_reset();
scc->initial_cpu_reset(CPU(cpu));
scc->load_normal(CPU(cpu));
cpu_synchronize_all_post_reset();
diff --git a/target-s390x/translate.c b/target-s390x/translate.c
index 2bca33a..05d51fe 100644
--- a/target-s390x/translate.c
+++ b/target-s390x/translate.c
@@ -124,7 +124,7 @@ void s390_cpu_dump_state(CPUState *cs, FILE *f, fprintf_function cpu_fprintf,
for (i = 0; i < 32; i++) {
cpu_fprintf(f, "V%02d=%016" PRIx64 "%016" PRIx64, i,
env->vregs[i][0].ll, env->vregs[i][1].ll);
- cpu_fprintf(f, (i % 2) ? " " : "\n");
+ cpu_fprintf(f, (i % 2) ? "\n" : " ");
}
#ifndef CONFIG_USER_ONLY
@@ -161,8 +161,6 @@ static char cpu_reg_names[32][4];
static TCGv_i64 regs[16];
static TCGv_i64 fregs[16];
-static uint8_t gen_opc_cc_op[OPC_BUF_SIZE];
-
void s390x_translate_init(void)
{
int i;
@@ -5319,18 +5317,14 @@ static ExitStatus translate_one(CPUS390XState *env, DisasContext *s)
return ret;
}
-static inline void gen_intermediate_code_internal(S390CPU *cpu,
- TranslationBlock *tb,
- bool search_pc)
+void gen_intermediate_code(CPUS390XState *env, struct TranslationBlock *tb)
{
+ S390CPU *cpu = s390_env_get_cpu(env);
CPUState *cs = CPU(cpu);
- CPUS390XState *env = &cpu->env;
DisasContext dc;
target_ulong pc_start;
uint64_t next_page_start;
- int j, lj = -1;
int num_insns, max_insns;
- CPUBreakpoint *bp;
ExitStatus status;
bool do_debug;
@@ -5353,41 +5347,27 @@ static inline void gen_intermediate_code_internal(S390CPU *cpu,
if (max_insns == 0) {
max_insns = CF_COUNT_MASK;
}
+ if (max_insns > TCG_MAX_INSNS) {
+ max_insns = TCG_MAX_INSNS;
+ }
gen_tb_start(tb);
do {
- if (search_pc) {
- j = tcg_op_buf_count();
- if (lj < j) {
- lj++;
- while (lj < j) {
- tcg_ctx.gen_opc_instr_start[lj++] = 0;
- }
- }
- tcg_ctx.gen_opc_pc[lj] = dc.pc;
- gen_opc_cc_op[lj] = dc.cc_op;
- tcg_ctx.gen_opc_instr_start[lj] = 1;
- tcg_ctx.gen_opc_icount[lj] = num_insns;
- }
- if (++num_insns == max_insns && (tb->cflags & CF_LAST_IO)) {
- gen_io_start();
+ tcg_gen_insn_start(dc.pc, dc.cc_op);
+ num_insns++;
+
+ if (unlikely(cpu_breakpoint_test(cs, dc.pc, BP_ANY))) {
+ status = EXIT_PC_STALE;
+ do_debug = true;
+ break;
}
- if (unlikely(qemu_loglevel_mask(CPU_LOG_TB_OP | CPU_LOG_TB_OP_OPT))) {
- tcg_gen_debug_insn_start(dc.pc);
+ if (num_insns == max_insns && (tb->cflags & CF_LAST_IO)) {
+ gen_io_start();
}
status = NO_EXIT;
- if (unlikely(!QTAILQ_EMPTY(&cs->breakpoints))) {
- QTAILQ_FOREACH(bp, &cs->breakpoints, entry) {
- if (bp->pc == dc.pc) {
- status = EXIT_PC_STALE;
- do_debug = true;
- break;
- }
- }
- }
if (status == NO_EXIT) {
status = translate_one(env, &dc);
}
@@ -5432,16 +5412,8 @@ static inline void gen_intermediate_code_internal(S390CPU *cpu,
gen_tb_end(tb, num_insns);
- if (search_pc) {
- j = tcg_op_buf_count();
- lj++;
- while (lj <= j) {
- tcg_ctx.gen_opc_instr_start[lj++] = 0;
- }
- } else {
- tb->size = dc.pc - pc_start;
- tb->icount = num_insns;
- }
+ tb->size = dc.pc - pc_start;
+ tb->icount = num_insns;
#if defined(S390X_DEBUG_DISAS)
if (qemu_loglevel_mask(CPU_LOG_TB_IN_ASM)) {
@@ -5452,21 +5424,11 @@ static inline void gen_intermediate_code_internal(S390CPU *cpu,
#endif
}
-void gen_intermediate_code (CPUS390XState *env, struct TranslationBlock *tb)
-{
- gen_intermediate_code_internal(s390_env_get_cpu(env), tb, false);
-}
-
-void gen_intermediate_code_pc (CPUS390XState *env, struct TranslationBlock *tb)
-{
- gen_intermediate_code_internal(s390_env_get_cpu(env), tb, true);
-}
-
-void restore_state_to_opc(CPUS390XState *env, TranslationBlock *tb, int pc_pos)
+void restore_state_to_opc(CPUS390XState *env, TranslationBlock *tb,
+ target_ulong *data)
{
- int cc_op;
- env->psw.addr = tcg_ctx.gen_opc_pc[pc_pos];
- cc_op = gen_opc_cc_op[pc_pos];
+ int cc_op = data[1];
+ env->psw.addr = data[0];
if ((cc_op != CC_OP_DYNAMIC) && (cc_op != CC_OP_STATIC)) {
env->cc_op = cc_op;
}
diff --git a/target-sh4/cpu.h b/target-sh4/cpu.h
index 6fb6321..5b022c5 100644
--- a/target-sh4/cpu.h
+++ b/target-sh4/cpu.h
@@ -120,6 +120,7 @@ typedef struct tlb_t {
#define ITLB_SIZE 4
#define NB_MMU_MODES 2
+#define TARGET_INSN_START_EXTRA_WORDS 1
enum sh_features {
SH_FEATURE_SH4A = 1,
@@ -225,7 +226,6 @@ void cpu_load_tlb(CPUSH4State * env);
#define cpu_init(cpu_model) CPU(cpu_sh4_init(cpu_model))
#define cpu_exec cpu_sh4_exec
-#define cpu_gen_code cpu_sh4_gen_code
#define cpu_signal_handler cpu_sh4_signal_handler
#define cpu_list sh4_cpu_list
diff --git a/target-sh4/translate.c b/target-sh4/translate.c
index 724c0e7..f764bc2 100644
--- a/target-sh4/translate.c
+++ b/target-sh4/translate.c
@@ -70,8 +70,6 @@ static TCGv cpu_fregs[32];
/* internal register indexes */
static TCGv cpu_flags, cpu_delayed_pc;
-static uint32_t gen_opc_hflags[OPC_BUF_SIZE];
-
#include "exec/gen-icount.h"
void sh4_translate_init(void)
@@ -1790,10 +1788,6 @@ static void decode_opc(DisasContext * ctx)
{
uint32_t old_flags = ctx->flags;
- if (unlikely(qemu_loglevel_mask(CPU_LOG_TB_OP | CPU_LOG_TB_OP_OPT))) {
- tcg_gen_debug_insn_start(ctx->pc);
- }
-
_decode_opc(ctx);
if (old_flags & (DELAY_SLOT | DELAY_SLOT_CONDITIONAL)) {
@@ -1820,16 +1814,12 @@ static void decode_opc(DisasContext * ctx)
gen_store_flags(ctx->flags);
}
-static inline void
-gen_intermediate_code_internal(SuperHCPU *cpu, TranslationBlock *tb,
- bool search_pc)
+void gen_intermediate_code(CPUSH4State * env, struct TranslationBlock *tb)
{
+ SuperHCPU *cpu = sh_env_get_cpu(env);
CPUState *cs = CPU(cpu);
- CPUSH4State *env = &cpu->env;
DisasContext ctx;
target_ulong pc_start;
- CPUBreakpoint *bp;
- int i, ii;
int num_insns;
int max_insns;
@@ -1846,45 +1836,34 @@ gen_intermediate_code_internal(SuperHCPU *cpu, TranslationBlock *tb,
ctx.features = env->features;
ctx.has_movcal = (ctx.flags & TB_FLAG_PENDING_MOVCA);
- ii = -1;
num_insns = 0;
max_insns = tb->cflags & CF_COUNT_MASK;
- if (max_insns == 0)
+ if (max_insns == 0) {
max_insns = CF_COUNT_MASK;
+ }
+ if (max_insns > TCG_MAX_INSNS) {
+ max_insns = TCG_MAX_INSNS;
+ }
+
gen_tb_start(tb);
while (ctx.bstate == BS_NONE && !tcg_op_buf_full()) {
- if (unlikely(!QTAILQ_EMPTY(&cs->breakpoints))) {
- QTAILQ_FOREACH(bp, &cs->breakpoints, entry) {
- if (ctx.pc == bp->pc) {
- /* We have hit a breakpoint - make sure PC is up-to-date */
- tcg_gen_movi_i32(cpu_pc, ctx.pc);
- gen_helper_debug(cpu_env);
- ctx.bstate = BS_BRANCH;
- break;
- }
- }
- }
- if (search_pc) {
- i = tcg_op_buf_count();
- if (ii < i) {
- ii++;
- while (ii < i)
- tcg_ctx.gen_opc_instr_start[ii++] = 0;
- }
- tcg_ctx.gen_opc_pc[ii] = ctx.pc;
- gen_opc_hflags[ii] = ctx.flags;
- tcg_ctx.gen_opc_instr_start[ii] = 1;
- tcg_ctx.gen_opc_icount[ii] = num_insns;
+ tcg_gen_insn_start(ctx.pc, ctx.flags);
+ num_insns++;
+
+ if (unlikely(cpu_breakpoint_test(cs, ctx.pc, BP_ANY))) {
+ /* We have hit a breakpoint - make sure PC is up-to-date */
+ tcg_gen_movi_i32(cpu_pc, ctx.pc);
+ gen_helper_debug(cpu_env);
+ ctx.bstate = BS_BRANCH;
+ break;
}
- if (num_insns + 1 == max_insns && (tb->cflags & CF_LAST_IO))
+
+ if (num_insns == max_insns && (tb->cflags & CF_LAST_IO)) {
gen_io_start();
-#if 0
- fprintf(stderr, "Loading opcode at address 0x%08x\n", ctx.pc);
- fflush(stderr);
-#endif
+ }
+
ctx.opcode = cpu_lduw_code(env, ctx.pc);
decode_opc(&ctx);
- num_insns++;
ctx.pc += 2;
if ((ctx.pc & (TARGET_PAGE_SIZE - 1)) == 0)
break;
@@ -1924,15 +1903,8 @@ gen_intermediate_code_internal(SuperHCPU *cpu, TranslationBlock *tb,
gen_tb_end(tb, num_insns);
- if (search_pc) {
- i = tcg_op_buf_count();
- ii++;
- while (ii <= i)
- tcg_ctx.gen_opc_instr_start[ii++] = 0;
- } else {
- tb->size = ctx.pc - pc_start;
- tb->icount = num_insns;
- }
+ tb->size = ctx.pc - pc_start;
+ tb->icount = num_insns;
#ifdef DEBUG_DISAS
if (qemu_loglevel_mask(CPU_LOG_TB_IN_ASM)) {
@@ -1943,18 +1915,9 @@ gen_intermediate_code_internal(SuperHCPU *cpu, TranslationBlock *tb,
#endif
}
-void gen_intermediate_code(CPUSH4State * env, struct TranslationBlock *tb)
-{
- gen_intermediate_code_internal(sh_env_get_cpu(env), tb, false);
-}
-
-void gen_intermediate_code_pc(CPUSH4State * env, struct TranslationBlock *tb)
-{
- gen_intermediate_code_internal(sh_env_get_cpu(env), tb, true);
-}
-
-void restore_state_to_opc(CPUSH4State *env, TranslationBlock *tb, int pc_pos)
+void restore_state_to_opc(CPUSH4State *env, TranslationBlock *tb,
+ target_ulong *data)
{
- env->pc = tcg_ctx.gen_opc_pc[pc_pos];
- env->flags = gen_opc_hflags[pc_pos];
+ env->pc = data[0];
+ env->flags = data[1];
}
diff --git a/target-sparc/cpu.h b/target-sparc/cpu.h
index 053edd5..9fa770b 100644
--- a/target-sparc/cpu.h
+++ b/target-sparc/cpu.h
@@ -230,6 +230,7 @@ typedef struct trap_state {
uint32_t tt;
} trap_state;
#endif
+#define TARGET_INSN_START_EXTRA_WORDS 1
typedef struct sparc_def_t {
const char *name;
@@ -592,7 +593,6 @@ int cpu_sparc_signal_handler(int host_signum, void *pinfo, void *puc);
#endif
#define cpu_exec cpu_sparc_exec
-#define cpu_gen_code cpu_sparc_gen_code
#define cpu_signal_handler cpu_sparc_signal_handler
#define cpu_list sparc_cpu_list
diff --git a/target-sparc/translate.c b/target-sparc/translate.c
index 4690b46..b59742a 100644
--- a/target-sparc/translate.c
+++ b/target-sparc/translate.c
@@ -64,9 +64,6 @@ static TCGv cpu_wim;
/* Floating point registers */
static TCGv_i64 cpu_fpr[TARGET_DPREGS];
-static target_ulong gen_opc_npc[OPC_BUF_SIZE];
-static target_ulong gen_opc_jump_pc[2];
-
#include "exec/gen-icount.h"
typedef struct DisasContext {
@@ -955,17 +952,44 @@ static inline void gen_branch2(DisasContext *dc, target_ulong pc1,
gen_goto_tb(dc, 1, pc2, pc2 + 4);
}
-static inline void gen_branch_a(DisasContext *dc, target_ulong pc1,
- target_ulong pc2, TCGv r_cond)
+static void gen_branch_a(DisasContext *dc, target_ulong pc1)
{
TCGLabel *l1 = gen_new_label();
+ target_ulong npc = dc->npc;
- tcg_gen_brcondi_tl(TCG_COND_EQ, r_cond, 0, l1);
+ tcg_gen_brcondi_tl(TCG_COND_EQ, cpu_cond, 0, l1);
- gen_goto_tb(dc, 0, pc2, pc1);
+ gen_goto_tb(dc, 0, npc, pc1);
gen_set_label(l1);
- gen_goto_tb(dc, 1, pc2 + 4, pc2 + 8);
+ gen_goto_tb(dc, 1, npc + 4, npc + 8);
+
+ dc->is_br = 1;
+}
+
+static void gen_branch_n(DisasContext *dc, target_ulong pc1)
+{
+ target_ulong npc = dc->npc;
+
+ if (likely(npc != DYNAMIC_PC)) {
+ dc->pc = npc;
+ dc->jump_pc[0] = pc1;
+ dc->jump_pc[1] = npc + 4;
+ dc->npc = JUMP_PC;
+ } else {
+ TCGv t, z;
+
+ tcg_gen_mov_tl(cpu_pc, cpu_npc);
+
+ tcg_gen_addi_tl(cpu_npc, cpu_npc, 4);
+ t = tcg_const_tl(pc1);
+ z = tcg_const_tl(0);
+ tcg_gen_movcond_tl(TCG_COND_NE, cpu_npc, cpu_cond, z, t, cpu_npc);
+ tcg_temp_free(t);
+ tcg_temp_free(z);
+
+ dc->pc = DYNAMIC_PC;
+ }
}
static inline void gen_generic_branch(DisasContext *dc)
@@ -1398,18 +1422,9 @@ static void do_branch(DisasContext *dc, int32_t offset, uint32_t insn, int cc)
flush_cond(dc);
gen_cond(cpu_cond, cc, cond, dc);
if (a) {
- gen_branch_a(dc, target, dc->npc, cpu_cond);
- dc->is_br = 1;
+ gen_branch_a(dc, target);
} else {
- dc->pc = dc->npc;
- dc->jump_pc[0] = target;
- if (unlikely(dc->npc == DYNAMIC_PC)) {
- dc->jump_pc[1] = DYNAMIC_PC;
- tcg_gen_addi_tl(cpu_pc, cpu_npc, 4);
- } else {
- dc->jump_pc[1] = dc->npc + 4;
- dc->npc = JUMP_PC;
- }
+ gen_branch_n(dc, target);
}
}
}
@@ -1447,18 +1462,9 @@ static void do_fbranch(DisasContext *dc, int32_t offset, uint32_t insn, int cc)
flush_cond(dc);
gen_fcond(cpu_cond, cc, cond);
if (a) {
- gen_branch_a(dc, target, dc->npc, cpu_cond);
- dc->is_br = 1;
+ gen_branch_a(dc, target);
} else {
- dc->pc = dc->npc;
- dc->jump_pc[0] = target;
- if (unlikely(dc->npc == DYNAMIC_PC)) {
- dc->jump_pc[1] = DYNAMIC_PC;
- tcg_gen_addi_tl(cpu_pc, cpu_npc, 4);
- } else {
- dc->jump_pc[1] = dc->npc + 4;
- dc->npc = JUMP_PC;
- }
+ gen_branch_n(dc, target);
}
}
}
@@ -1476,18 +1482,9 @@ static void do_branch_reg(DisasContext *dc, int32_t offset, uint32_t insn,
flush_cond(dc);
gen_cond_reg(cpu_cond, cond, r_reg);
if (a) {
- gen_branch_a(dc, target, dc->npc, cpu_cond);
- dc->is_br = 1;
+ gen_branch_a(dc, target);
} else {
- dc->pc = dc->npc;
- dc->jump_pc[0] = target;
- if (unlikely(dc->npc == DYNAMIC_PC)) {
- dc->jump_pc[1] = DYNAMIC_PC;
- tcg_gen_addi_tl(cpu_pc, cpu_npc, 4);
- } else {
- dc->jump_pc[1] = dc->npc + 4;
- dc->npc = JUMP_PC;
- }
+ gen_branch_n(dc, target);
}
}
@@ -2482,10 +2479,6 @@ static void disas_sparc_insn(DisasContext * dc, unsigned int insn)
TCGv_i64 cpu_src1_64, cpu_src2_64, cpu_dst_64;
target_long simm;
- if (unlikely(qemu_loglevel_mask(CPU_LOG_TB_OP | CPU_LOG_TB_OP_OPT))) {
- tcg_gen_debug_insn_start(dc->pc);
- }
-
opc = GET_FIELD(insn, 0, 1);
rd = GET_FIELD(insn, 2, 6);
@@ -5213,16 +5206,12 @@ static void disas_sparc_insn(DisasContext * dc, unsigned int insn)
}
}
-static inline void gen_intermediate_code_internal(SPARCCPU *cpu,
- TranslationBlock *tb,
- bool spc)
+void gen_intermediate_code(CPUSPARCState * env, TranslationBlock * tb)
{
+ SPARCCPU *cpu = sparc_env_get_cpu(env);
CPUState *cs = CPU(cpu);
- CPUSPARCState *env = &cpu->env;
target_ulong pc_start, last_pc;
DisasContext dc1, *dc = &dc1;
- CPUBreakpoint *bp;
- int j, lj = -1;
int num_insns;
int max_insns;
unsigned int insn;
@@ -5242,42 +5231,41 @@ static inline void gen_intermediate_code_internal(SPARCCPU *cpu,
num_insns = 0;
max_insns = tb->cflags & CF_COUNT_MASK;
- if (max_insns == 0)
+ if (max_insns == 0) {
max_insns = CF_COUNT_MASK;
+ }
+ if (max_insns > TCG_MAX_INSNS) {
+ max_insns = TCG_MAX_INSNS;
+ }
+
gen_tb_start(tb);
do {
- if (unlikely(!QTAILQ_EMPTY(&cs->breakpoints))) {
- QTAILQ_FOREACH(bp, &cs->breakpoints, entry) {
- if (bp->pc == dc->pc) {
- if (dc->pc != pc_start)
- save_state(dc);
- gen_helper_debug(cpu_env);
- tcg_gen_exit_tb(0);
- dc->is_br = 1;
- goto exit_gen_loop;
- }
- }
+ if (dc->npc & JUMP_PC) {
+ assert(dc->jump_pc[1] == dc->pc + 4);
+ tcg_gen_insn_start(dc->pc, dc->jump_pc[0] | JUMP_PC);
+ } else {
+ tcg_gen_insn_start(dc->pc, dc->npc);
}
- if (spc) {
- qemu_log("Search PC...\n");
- j = tcg_op_buf_count();
- if (lj < j) {
- lj++;
- while (lj < j)
- tcg_ctx.gen_opc_instr_start[lj++] = 0;
- tcg_ctx.gen_opc_pc[lj] = dc->pc;
- gen_opc_npc[lj] = dc->npc;
- tcg_ctx.gen_opc_instr_start[lj] = 1;
- tcg_ctx.gen_opc_icount[lj] = num_insns;
+ num_insns++;
+
+ if (unlikely(cpu_breakpoint_test(cs, dc->pc, BP_ANY))) {
+ if (dc->pc != pc_start) {
+ save_state(dc);
}
+ gen_helper_debug(cpu_env);
+ tcg_gen_exit_tb(0);
+ dc->is_br = 1;
+ goto exit_gen_loop;
}
- if (num_insns + 1 == max_insns && (tb->cflags & CF_LAST_IO))
+
+ if (num_insns == max_insns && (tb->cflags & CF_LAST_IO)) {
gen_io_start();
+ }
+
last_pc = dc->pc;
insn = cpu_ldl_code(env, dc->pc);
disas_sparc_insn(dc, insn);
- num_insns++;
if (dc->is_br)
break;
@@ -5316,20 +5304,9 @@ static inline void gen_intermediate_code_internal(SPARCCPU *cpu,
}
gen_tb_end(tb, num_insns);
- if (spc) {
- j = tcg_op_buf_count();
- lj++;
- while (lj <= j)
- tcg_ctx.gen_opc_instr_start[lj++] = 0;
-#if 0
- log_page_dump();
-#endif
- gen_opc_jump_pc[0] = dc->jump_pc[0];
- gen_opc_jump_pc[1] = dc->jump_pc[1];
- } else {
- tb->size = last_pc + 4 - pc_start;
- tb->icount = num_insns;
- }
+ tb->size = last_pc + 4 - pc_start;
+ tb->icount = num_insns;
+
#ifdef DEBUG_DISAS
if (qemu_loglevel_mask(CPU_LOG_TB_IN_ASM)) {
qemu_log("--------------\n");
@@ -5340,16 +5317,6 @@ static inline void gen_intermediate_code_internal(SPARCCPU *cpu,
#endif
}
-void gen_intermediate_code(CPUSPARCState * env, TranslationBlock * tb)
-{
- gen_intermediate_code_internal(sparc_env_get_cpu(env), tb, false);
-}
-
-void gen_intermediate_code_pc(CPUSPARCState * env, TranslationBlock * tb)
-{
- gen_intermediate_code_internal(sparc_env_get_cpu(env), tb, true);
-}
-
void gen_intermediate_code_init(CPUSPARCState *env)
{
unsigned int i;
@@ -5451,19 +5418,21 @@ void gen_intermediate_code_init(CPUSPARCState *env)
}
}
-void restore_state_to_opc(CPUSPARCState *env, TranslationBlock *tb, int pc_pos)
+void restore_state_to_opc(CPUSPARCState *env, TranslationBlock *tb,
+ target_ulong *data)
{
- target_ulong npc;
- env->pc = tcg_ctx.gen_opc_pc[pc_pos];
- npc = gen_opc_npc[pc_pos];
- if (npc == 1) {
+ target_ulong pc = data[0];
+ target_ulong npc = data[1];
+
+ env->pc = pc;
+ if (npc == DYNAMIC_PC) {
/* dynamic NPC: already stored */
- } else if (npc == 2) {
+ } else if (npc & JUMP_PC) {
/* jump PC: use 'cond' and the jump targets of the translation */
if (env->cond) {
- env->npc = gen_opc_jump_pc[0];
+ env->npc = npc & ~3;
} else {
- env->npc = gen_opc_jump_pc[1];
+ env->npc = pc + 4;
}
} else {
env->npc = npc;
diff --git a/target-tilegx/cpu.c b/target-tilegx/cpu.c
index 78b73e4..3c5481d 100644
--- a/target-tilegx/cpu.c
+++ b/target-tilegx/cpu.c
@@ -22,6 +22,7 @@
#include "qemu-common.h"
#include "hw/qdev-properties.h"
#include "migration/vmstate.h"
+#include "linux-user/syscall_defs.h"
static void tilegx_cpu_dump_state(CPUState *cs, FILE *f,
fprintf_function cpu_fprintf, int flags)
@@ -121,8 +122,12 @@ static int tilegx_cpu_handle_mmu_fault(CPUState *cs, vaddr address, int rw,
{
TileGXCPU *cpu = TILEGX_CPU(cs);
- cs->exception_index = TILEGX_EXCP_SEGV;
+ /* The sigcode field will be filled in by do_signal in main.c. */
+ cs->exception_index = TILEGX_EXCP_SIGNAL;
cpu->env.excaddr = address;
+ cpu->env.signo = TARGET_SIGSEGV;
+ cpu->env.sigcode = 0;
+
return 1;
}
diff --git a/target-tilegx/cpu.h b/target-tilegx/cpu.h
index b9f5082..03df107 100644
--- a/target-tilegx/cpu.h
+++ b/target-tilegx/cpu.h
@@ -53,6 +53,8 @@ enum {
TILEGX_SPR_CMPEXCH = 0,
TILEGX_SPR_CRITICAL_SEC = 1,
TILEGX_SPR_SIM_CONTROL = 2,
+ TILEGX_SPR_EX_CONTEXT_0_0 = 3,
+ TILEGX_SPR_EX_CONTEXT_0_1 = 4,
TILEGX_SPR_COUNT
};
@@ -60,7 +62,7 @@ enum {
typedef enum {
TILEGX_EXCP_NONE = 0,
TILEGX_EXCP_SYSCALL = 1,
- TILEGX_EXCP_SEGV = 2,
+ TILEGX_EXCP_SIGNAL = 2,
TILEGX_EXCP_OPCODE_UNKNOWN = 0x101,
TILEGX_EXCP_OPCODE_UNIMPLEMENTED = 0x102,
TILEGX_EXCP_OPCODE_CMPEXCH = 0x103,
@@ -87,10 +89,12 @@ typedef struct CPUTLGState {
uint64_t pc; /* Current pc */
#if defined(CONFIG_USER_ONLY)
+ uint64_t excaddr; /* exception address */
uint64_t atomic_srca; /* Arguments to atomic "exceptions" */
uint64_t atomic_srcb;
uint32_t atomic_dstr;
- uint64_t excaddr; /* exception address */
+ uint32_t signo; /* Signal number */
+ uint32_t sigcode; /* Signal code */
#endif
CPU_COMMON
@@ -163,7 +167,6 @@ TileGXCPU *cpu_tilegx_init(const char *cpu_model);
#define cpu_init(cpu_model) CPU(cpu_tilegx_init(cpu_model))
#define cpu_exec cpu_tilegx_exec
-#define cpu_gen_code cpu_tilegx_gen_code
#define cpu_signal_handler cpu_tilegx_signal_handler
static inline void cpu_get_tb_cpu_state(CPUTLGState *env, target_ulong *pc,
diff --git a/target-tilegx/helper.c b/target-tilegx/helper.c
index a01bb8d..dda821f 100644
--- a/target-tilegx/helper.c
+++ b/target-tilegx/helper.c
@@ -21,6 +21,8 @@
#include "cpu.h"
#include "qemu-common.h"
#include "exec/helper-proto.h"
+#include <zlib.h> /* For crc32 */
+#include "syscall_defs.h"
void helper_exception(CPUTLGState *env, uint32_t excp)
{
@@ -30,6 +32,27 @@ void helper_exception(CPUTLGState *env, uint32_t excp)
cpu_loop_exit(cs);
}
+void helper_ext01_ics(CPUTLGState *env)
+{
+ uint64_t val = env->spregs[TILEGX_SPR_EX_CONTEXT_0_1];
+
+ switch (val) {
+ case 0:
+ case 1:
+ env->spregs[TILEGX_SPR_CRITICAL_SEC] = val;
+ break;
+ default:
+#if defined(CONFIG_USER_ONLY)
+ env->signo = TARGET_SIGILL;
+ env->sigcode = TARGET_ILL_ILLOPC;
+ helper_exception(env, TILEGX_EXCP_SIGNAL);
+#else
+ helper_exception(env, TILEGX_EXCP_OPCODE_UNIMPLEMENTED);
+#endif
+ break;
+ }
+}
+
uint64_t helper_cntlz(uint64_t arg)
{
return clz64(arg);
@@ -78,3 +101,61 @@ uint64_t helper_shufflebytes(uint64_t dest, uint64_t srca, uint64_t srcb)
return vdst;
}
+
+uint64_t helper_crc32_8(uint64_t accum, uint64_t input)
+{
+ uint8_t buf = input;
+
+ /* zlib crc32 converts the accumulator and output to one's complement. */
+ return crc32(accum ^ 0xffffffff, &buf, 1) ^ 0xffffffff;
+}
+
+uint64_t helper_crc32_32(uint64_t accum, uint64_t input)
+{
+ uint8_t buf[4];
+
+ stl_le_p(buf, input);
+
+ /* zlib crc32 converts the accumulator and output to one's complement. */
+ return crc32(accum ^ 0xffffffff, buf, 4) ^ 0xffffffff;
+}
+
+uint64_t helper_cmula(uint64_t srcd, uint64_t srca, uint64_t srcb)
+{
+ uint32_t reala = (int16_t)srca;
+ uint32_t imaga = (int16_t)(srca >> 16);
+ uint32_t realb = (int16_t)srcb;
+ uint32_t imagb = (int16_t)(srcb >> 16);
+ uint32_t reald = srcd;
+ uint32_t imagd = srcd >> 32;
+ uint32_t realr = reala * realb - imaga * imagb + reald;
+ uint32_t imagr = reala * imagb + imaga * realb + imagd;
+
+ return deposit64(realr, 32, 32, imagr);
+}
+
+uint64_t helper_cmulaf(uint64_t srcd, uint64_t srca, uint64_t srcb)
+{
+ uint32_t reala = (int16_t)srca;
+ uint32_t imaga = (int16_t)(srca >> 16);
+ uint32_t realb = (int16_t)srcb;
+ uint32_t imagb = (int16_t)(srcb >> 16);
+ uint32_t reald = (int16_t)srcd;
+ uint32_t imagd = (int16_t)(srcd >> 16);
+ int32_t realr = reala * realb - imaga * imagb;
+ int32_t imagr = reala * imagb + imaga * realb;
+
+ return deposit32((realr >> 15) + reald, 16, 16, (imagr >> 15) + imagd);
+}
+
+uint64_t helper_cmul2(uint64_t srca, uint64_t srcb, int shift, int round)
+{
+ uint32_t reala = (int16_t)srca;
+ uint32_t imaga = (int16_t)(srca >> 16);
+ uint32_t realb = (int16_t)srcb;
+ uint32_t imagb = (int16_t)(srcb >> 16);
+ int32_t realr = reala * realb - imaga * imagb + round;
+ int32_t imagr = reala * imagb + imaga * realb + round;
+
+ return deposit32(realr >> shift, 16, 16, imagr >> shift);
+}
diff --git a/target-tilegx/helper.h b/target-tilegx/helper.h
index 766f5f2..9281d0f 100644
--- a/target-tilegx/helper.h
+++ b/target-tilegx/helper.h
@@ -1,10 +1,26 @@
DEF_HELPER_2(exception, noreturn, env, i32)
+DEF_HELPER_1(ext01_ics, void, env)
DEF_HELPER_FLAGS_1(cntlz, TCG_CALL_NO_RWG_SE, i64, i64)
DEF_HELPER_FLAGS_1(cnttz, TCG_CALL_NO_RWG_SE, i64, i64)
DEF_HELPER_FLAGS_1(pcnt, TCG_CALL_NO_RWG_SE, i64, i64)
DEF_HELPER_FLAGS_1(revbits, TCG_CALL_NO_RWG_SE, i64, i64)
DEF_HELPER_FLAGS_3(shufflebytes, TCG_CALL_NO_RWG_SE, i64, i64, i64, i64)
+DEF_HELPER_FLAGS_2(crc32_8, TCG_CALL_NO_RWG_SE, i64, i64, i64)
+DEF_HELPER_FLAGS_2(crc32_32, TCG_CALL_NO_RWG_SE, i64, i64, i64)
+DEF_HELPER_FLAGS_3(cmula, TCG_CALL_NO_RWG_SE, i64, i64, i64, i64)
+DEF_HELPER_FLAGS_3(cmulaf, TCG_CALL_NO_RWG_SE, i64, i64, i64, i64)
+DEF_HELPER_FLAGS_4(cmul2, TCG_CALL_NO_RWG_SE, i64, i64, i64, int, int)
+DEF_HELPER_FLAGS_2(v1int_h, TCG_CALL_NO_RWG_SE, i64, i64, i64)
+DEF_HELPER_FLAGS_2(v1int_l, TCG_CALL_NO_RWG_SE, i64, i64, i64)
+DEF_HELPER_FLAGS_2(v2int_h, TCG_CALL_NO_RWG_SE, i64, i64, i64)
+DEF_HELPER_FLAGS_2(v2int_l, TCG_CALL_NO_RWG_SE, i64, i64, i64)
+
+DEF_HELPER_FLAGS_2(v1multu, TCG_CALL_NO_RWG_SE, i64, i64, i64)
+DEF_HELPER_FLAGS_2(v2mults, TCG_CALL_NO_RWG_SE, i64, i64, i64)
DEF_HELPER_FLAGS_2(v1shl, TCG_CALL_NO_RWG_SE, i64, i64, i64)
DEF_HELPER_FLAGS_2(v1shru, TCG_CALL_NO_RWG_SE, i64, i64, i64)
DEF_HELPER_FLAGS_2(v1shrs, TCG_CALL_NO_RWG_SE, i64, i64, i64)
+DEF_HELPER_FLAGS_2(v2shl, TCG_CALL_NO_RWG_SE, i64, i64, i64)
+DEF_HELPER_FLAGS_2(v2shru, TCG_CALL_NO_RWG_SE, i64, i64, i64)
+DEF_HELPER_FLAGS_2(v2shrs, TCG_CALL_NO_RWG_SE, i64, i64, i64)
diff --git a/target-tilegx/simd_helper.c b/target-tilegx/simd_helper.c
index b931929..6d7bb5c 100644
--- a/target-tilegx/simd_helper.c
+++ b/target-tilegx/simd_helper.c
@@ -23,12 +23,54 @@
#include "exec/helper-proto.h"
+/* Broadcast a value to all elements of a vector. */
+#define V1(X) (((X) & 0xff) * 0x0101010101010101ull)
+#define V2(X) (((X) & 0xffff) * 0x0001000100010001ull)
+
+
+uint64_t helper_v1multu(uint64_t a, uint64_t b)
+{
+ uint64_t r = 0;
+ int i;
+
+ for (i = 0; i < 64; i += 8) {
+ unsigned ae = extract64(a, i, 8);
+ unsigned be = extract64(b, i, 8);
+ r = deposit64(r, i, 8, ae * be);
+ }
+ return r;
+}
+
+uint64_t helper_v2mults(uint64_t a, uint64_t b)
+{
+ uint64_t r = 0;
+ int i;
+
+ /* While the instruction talks about signed inputs, with a
+ truncated result the sign of the inputs doesn't matter. */
+ for (i = 0; i < 64; i += 16) {
+ unsigned ae = extract64(a, i, 16);
+ unsigned be = extract64(b, i, 16);
+ r = deposit64(r, i, 16, ae * be);
+ }
+ return r;
+}
+
uint64_t helper_v1shl(uint64_t a, uint64_t b)
{
uint64_t m;
b &= 7;
- m = 0x0101010101010101ULL * (0xff >> b);
+ m = V1(0xff >> b);
+ return (a & m) << b;
+}
+
+uint64_t helper_v2shl(uint64_t a, uint64_t b)
+{
+ uint64_t m;
+
+ b &= 15;
+ m = V2(0xffff >> b);
return (a & m) << b;
}
@@ -37,7 +79,16 @@ uint64_t helper_v1shru(uint64_t a, uint64_t b)
uint64_t m;
b &= 7;
- m = 0x0101010101010101ULL * ((0xff << b) & 0xff);
+ m = V1(0xff << b);
+ return (a & m) >> b;
+}
+
+uint64_t helper_v2shru(uint64_t a, uint64_t b)
+{
+ uint64_t m;
+
+ b &= 15;
+ m = V2(0xffff << b);
return (a & m) >> b;
}
@@ -48,8 +99,67 @@ uint64_t helper_v1shrs(uint64_t a, uint64_t b)
b &= 7;
for (i = 0; i < 64; i += 8) {
- int64_t ae = (int8_t)(a >> i);
- r |= ((ae >> b) & 0xff) << i;
+ r = deposit64(r, i, 8, sextract64(a, i + b, 8 - b));
+ }
+ return r;
+}
+
+uint64_t helper_v2shrs(uint64_t a, uint64_t b)
+{
+ uint64_t r = 0;
+ int i;
+
+ b &= 15;
+ for (i = 0; i < 64; i += 16) {
+ r = deposit64(r, i, 16, sextract64(a, i + b, 16 - b));
+ }
+ return r;
+}
+
+uint64_t helper_v1int_h(uint64_t a, uint64_t b)
+{
+ uint64_t r = 0;
+ int i;
+
+ for (i = 0; i < 32; i += 8) {
+ r = deposit64(r, 2 * i + 8, 8, extract64(a, i + 32, 8));
+ r = deposit64(r, 2 * i, 8, extract64(b, i + 32, 8));
+ }
+ return r;
+}
+
+uint64_t helper_v1int_l(uint64_t a, uint64_t b)
+{
+ uint64_t r = 0;
+ int i;
+
+ for (i = 0; i < 32; i += 8) {
+ r = deposit64(r, 2 * i + 8, 8, extract64(a, i, 8));
+ r = deposit64(r, 2 * i, 8, extract64(b, i, 8));
+ }
+ return r;
+}
+
+uint64_t helper_v2int_h(uint64_t a, uint64_t b)
+{
+ uint64_t r = 0;
+ int i;
+
+ for (i = 0; i < 32; i += 16) {
+ r = deposit64(r, 2 * i + 16, 16, extract64(a, i + 32, 16));
+ r = deposit64(r, 2 * i, 16, extract64(b, i + 32, 16));
+ }
+ return r;
+}
+
+uint64_t helper_v2int_l(uint64_t a, uint64_t b)
+{
+ uint64_t r = 0;
+ int i;
+
+ for (i = 0; i < 32; i += 16) {
+ r = deposit64(r, 2 * i + 16, 16, extract64(a, i, 16));
+ r = deposit64(r, 2 * i, 16, extract64(b, i, 16));
}
return r;
}
diff --git a/target-tilegx/translate.c b/target-tilegx/translate.c
index e70c3e5..34d45f8 100644
--- a/target-tilegx/translate.c
+++ b/target-tilegx/translate.c
@@ -23,6 +23,8 @@
#include "disas/disas.h"
#include "tcg-op.h"
#include "exec/cpu_ldst.h"
+#include "linux-user/syscall_defs.h"
+
#include "opcode_tilegx.h"
#include "spr_def_64.h"
@@ -96,6 +98,7 @@ typedef struct {
#define OE_SH(E,XY) OE(SHIFT_OPCODE_##XY, E##_SHIFT_OPCODE_##XY, XY)
#define V1_IMM(X) (((X) & 0xff) * 0x0101010101010101ull)
+#define V2_IMM(X) (((X) & 0xffff) * 0x0001000100010001ull)
static void gen_exception(DisasContext *dc, TileExcp num)
@@ -275,6 +278,44 @@ static void gen_mul_half(TCGv tdest, TCGv tsrca, TCGv tsrcb,
tcg_temp_free(t);
}
+static void gen_cmul2(TCGv tdest, TCGv tsrca, TCGv tsrcb, int sh, int rd)
+{
+ TCGv_i32 tsh = tcg_const_i32(sh);
+ TCGv_i32 trd = tcg_const_i32(rd);
+ gen_helper_cmul2(tdest, tsrca, tsrcb, tsh, trd);
+ tcg_temp_free_i32(tsh);
+ tcg_temp_free_i32(trd);
+}
+
+static TileExcp gen_st_opcode(DisasContext *dc, unsigned dest, unsigned srca,
+ unsigned srcb, TCGMemOp memop, const char *name)
+{
+ if (dest) {
+ return TILEGX_EXCP_OPCODE_UNKNOWN;
+ }
+
+ tcg_gen_qemu_st_tl(load_gr(dc, srcb), load_gr(dc, srca),
+ dc->mmuidx, memop);
+
+ qemu_log_mask(CPU_LOG_TB_IN_ASM, "%s %s, %s", name,
+ reg_names[srca], reg_names[srcb]);
+ return TILEGX_EXCP_NONE;
+}
+
+static TileExcp gen_st_add_opcode(DisasContext *dc, unsigned srca, unsigned srcb,
+ int imm, TCGMemOp memop, const char *name)
+{
+ TCGv tsrca = load_gr(dc, srca);
+ TCGv tsrcb = load_gr(dc, srcb);
+
+ tcg_gen_qemu_st_tl(tsrcb, tsrca, dc->mmuidx, memop);
+ tcg_gen_addi_tl(dest_gr(dc, srca), tsrca, imm);
+
+ qemu_log_mask(CPU_LOG_TB_IN_ASM, "%s %s, %s, %d", name,
+ reg_names[srca], reg_names[srcb], imm);
+ return TILEGX_EXCP_NONE;
+}
+
/* Equality comparison with zero can be done quickly and efficiently. */
static void gen_v1cmpeq0(TCGv v)
{
@@ -310,42 +351,152 @@ static void gen_v1cmpne0(TCGv v)
tcg_temp_free(c);
}
-static TileExcp gen_st_opcode(DisasContext *dc, unsigned dest, unsigned srca,
- unsigned srcb, TCGMemOp memop, const char *name)
+/* Vector addition can be performed via arithmetic plus masking. It is
+ efficient this way only for 4 or more elements. */
+static void gen_v12add(TCGv tdest, TCGv tsrca, TCGv tsrcb, uint64_t sign)
{
- if (dest) {
- return TILEGX_EXCP_OPCODE_UNIMPLEMENTED;
- }
+ TCGv tmask = tcg_const_tl(~sign);
+ TCGv t0 = tcg_temp_new();
+ TCGv t1 = tcg_temp_new();
- tcg_gen_qemu_st_tl(load_gr(dc, srcb), load_gr(dc, srca),
- dc->mmuidx, memop);
+ /* ((a & ~sign) + (b & ~sign)) ^ ((a ^ b) & sign). */
+ tcg_gen_and_tl(t0, tsrca, tmask);
+ tcg_gen_and_tl(t1, tsrcb, tmask);
+ tcg_gen_add_tl(tdest, t0, t1);
+ tcg_gen_xor_tl(t0, tsrca, tsrcb);
+ tcg_gen_andc_tl(t0, t0, tmask);
+ tcg_gen_xor_tl(tdest, tdest, t0);
- qemu_log_mask(CPU_LOG_TB_IN_ASM, "%s %s, %s", name,
- reg_names[srca], reg_names[srcb]);
- return TILEGX_EXCP_NONE;
+ tcg_temp_free(t1);
+ tcg_temp_free(t0);
+ tcg_temp_free(tmask);
}
-static TileExcp gen_st_add_opcode(DisasContext *dc, unsigned srca, unsigned srcb,
- int imm, TCGMemOp memop, const char *name)
+/* Similarly for vector subtraction. */
+static void gen_v12sub(TCGv tdest, TCGv tsrca, TCGv tsrcb, uint64_t sign)
{
- TCGv tsrca = load_gr(dc, srca);
- TCGv tsrcb = load_gr(dc, srcb);
+ TCGv tsign = tcg_const_tl(sign);
+ TCGv t0 = tcg_temp_new();
+ TCGv t1 = tcg_temp_new();
- tcg_gen_qemu_st_tl(tsrcb, tsrca, dc->mmuidx, memop);
- tcg_gen_addi_tl(dest_gr(dc, srca), tsrca, imm);
+ /* ((a | sign) - (b & ~sign)) ^ ((a ^ ~b) & sign). */
+ tcg_gen_or_tl(t0, tsrca, tsign);
+ tcg_gen_andc_tl(t1, tsrcb, tsign);
+ tcg_gen_sub_tl(tdest, t0, t1);
+ tcg_gen_eqv_tl(t0, tsrca, tsrcb);
+ tcg_gen_and_tl(t0, t0, tsign);
+ tcg_gen_xor_tl(tdest, tdest, t0);
- qemu_log_mask(CPU_LOG_TB_IN_ASM, "%s %s, %s, %d", name,
- reg_names[srca], reg_names[srcb], imm);
- return TILEGX_EXCP_NONE;
+ tcg_temp_free(t1);
+ tcg_temp_free(t0);
+ tcg_temp_free(tsign);
+}
+
+static void gen_v4sh(TCGv d64, TCGv a64, TCGv b64,
+ void (*generate)(TCGv_i32, TCGv_i32, TCGv_i32))
+{
+ TCGv_i32 al = tcg_temp_new_i32();
+ TCGv_i32 ah = tcg_temp_new_i32();
+ TCGv_i32 bl = tcg_temp_new_i32();
+
+ tcg_gen_extr_i64_i32(al, ah, a64);
+ tcg_gen_extrl_i64_i32(bl, b64);
+ tcg_gen_andi_i32(bl, bl, 31);
+ generate(al, al, bl);
+ generate(ah, ah, bl);
+ tcg_gen_concat_i32_i64(d64, al, ah);
+
+ tcg_temp_free_i32(al);
+ tcg_temp_free_i32(ah);
+ tcg_temp_free_i32(bl);
+}
+
+static void gen_v4op(TCGv d64, TCGv a64, TCGv b64,
+ void (*generate)(TCGv_i32, TCGv_i32, TCGv_i32))
+{
+ TCGv_i32 al = tcg_temp_new_i32();
+ TCGv_i32 ah = tcg_temp_new_i32();
+ TCGv_i32 bl = tcg_temp_new_i32();
+ TCGv_i32 bh = tcg_temp_new_i32();
+
+ tcg_gen_extr_i64_i32(al, ah, a64);
+ tcg_gen_extr_i64_i32(bl, bh, b64);
+ generate(al, al, bl);
+ generate(ah, ah, bh);
+ tcg_gen_concat_i32_i64(d64, al, ah);
+
+ tcg_temp_free_i32(al);
+ tcg_temp_free_i32(ah);
+ tcg_temp_free_i32(bl);
+ tcg_temp_free_i32(bh);
+}
+
+static TileExcp gen_signal(DisasContext *dc, int signo, int sigcode,
+ const char *mnemonic)
+{
+ TCGv_i32 t0 = tcg_const_i32(signo);
+ TCGv_i32 t1 = tcg_const_i32(sigcode);
+
+ tcg_gen_st_i32(t0, cpu_env, offsetof(CPUTLGState, signo));
+ tcg_gen_st_i32(t1, cpu_env, offsetof(CPUTLGState, sigcode));
+
+ tcg_temp_free_i32(t1);
+ tcg_temp_free_i32(t0);
+
+ qemu_log_mask(CPU_LOG_TB_IN_ASM, "%s", mnemonic);
+ return TILEGX_EXCP_SIGNAL;
+}
+
+static bool parse_from_addli(uint64_t bundle, int *signo, int *sigcode)
+{
+ int imm;
+
+ if ((get_Opcode_X0(bundle) != ADDLI_OPCODE_X0)
+ || (get_Dest_X0(bundle) != TILEGX_R_ZERO)
+ || (get_SrcA_X0(bundle) != TILEGX_R_ZERO)) {
+ return false;
+ }
+
+ imm = get_Imm16_X0(bundle);
+ *signo = imm & 0x3f;
+ *sigcode = (imm >> 6) & 0xf;
+
+ /* ??? The linux kernel validates both signo and the sigcode vs the
+ known max for each signal. Don't bother here. */
+ return true;
+}
+
+static TileExcp gen_specill(DisasContext *dc, unsigned dest, unsigned srca,
+ uint64_t bundle)
+{
+ const char *mnemonic;
+ int signo;
+ int sigcode;
+
+ if (dest == 0x1c && srca == 0x25) {
+ signo = TARGET_SIGTRAP;
+ sigcode = TARGET_TRAP_BRKPT;
+ mnemonic = "bpt";
+ } else if (dest == 0x1d && srca == 0x25
+ && parse_from_addli(bundle, &signo, &sigcode)) {
+ mnemonic = "raise";
+ } else {
+ signo = TARGET_SIGILL;
+ sigcode = TARGET_ILL_ILLOPC;
+ mnemonic = "ill";
+ }
+
+ return gen_signal(dc, signo, sigcode, mnemonic);
}
static TileExcp gen_rr_opcode(DisasContext *dc, unsigned opext,
- unsigned dest, unsigned srca)
+ unsigned dest, unsigned srca, uint64_t bundle)
{
TCGv tdest, tsrca;
const char *mnemonic;
TCGMemOp memop;
TileExcp ret = TILEGX_EXCP_NONE;
+ bool prefetch_nofault = false;
/* Eliminate instructions with no output before doing anything else. */
switch (opext) {
@@ -368,10 +519,9 @@ static TileExcp gen_rr_opcode(DisasContext *dc, unsigned opext,
mnemonic = "flushwb";
goto done0;
case OE_RR_X1(ILL):
+ return gen_specill(dc, dest, srca, bundle);
case OE_RR_Y1(ILL):
- mnemonic = (dest == 0x1c && srca == 0x25 ? "bpt" : "ill");
- qemu_log_mask(CPU_LOG_TB_IN_ASM, "%s", mnemonic);
- return TILEGX_EXCP_OPCODE_UNKNOWN;
+ return gen_signal(dc, TARGET_SIGILL, TARGET_ILL_ILLOPC, "ill");
case OE_RR_X1(MF):
mnemonic = "mf";
goto done0;
@@ -379,6 +529,15 @@ static TileExcp gen_rr_opcode(DisasContext *dc, unsigned opext,
/* ??? This should yield, especially in system mode. */
mnemonic = "nap";
goto done0;
+ case OE_RR_X1(IRET):
+ gen_helper_ext01_ics(cpu_env);
+ dc->jmp.cond = TCG_COND_ALWAYS;
+ dc->jmp.dest = tcg_temp_new();
+ tcg_gen_ld_tl(dc->jmp.dest, cpu_env,
+ offsetof(CPUTLGState, spregs[TILEGX_SPR_EX_CONTEXT_0_0]));
+ tcg_gen_andi_tl(dc->jmp.dest, dc->jmp.dest, ~7);
+ mnemonic = "iret";
+ goto done0;
case OE_RR_X1(SWINT0):
case OE_RR_X1(SWINT2):
case OE_RR_X1(SWINT3):
@@ -388,7 +547,7 @@ static TileExcp gen_rr_opcode(DisasContext *dc, unsigned opext,
mnemonic = "swint1";
done0:
if (srca || dest) {
- return TILEGX_EXCP_OPCODE_UNIMPLEMENTED;
+ return TILEGX_EXCP_OPCODE_UNKNOWN;
}
qemu_log_mask(CPU_LOG_TB_IN_ASM, "%s", mnemonic);
return ret;
@@ -434,7 +593,7 @@ static TileExcp gen_rr_opcode(DisasContext *dc, unsigned opext,
tcg_gen_andi_tl(dc->jmp.dest, load_gr(dc, srca), ~7);
done1:
if (dest) {
- return TILEGX_EXCP_OPCODE_UNIMPLEMENTED;
+ return TILEGX_EXCP_OPCODE_UNKNOWN;
}
qemu_log_mask(CPU_LOG_TB_IN_ASM, "%s %s", mnemonic, reg_names[srca]);
return ret;
@@ -456,31 +615,33 @@ static TileExcp gen_rr_opcode(DisasContext *dc, unsigned opext,
break;
case OE_RR_X0(FSINGLE_PACK1):
case OE_RR_Y0(FSINGLE_PACK1):
- case OE_RR_X1(IRET):
return TILEGX_EXCP_OPCODE_UNIMPLEMENTED;
case OE_RR_X1(LD1S):
memop = MO_SB;
- mnemonic = "ld1s";
+ mnemonic = "ld1s"; /* prefetch_l1_fault */
goto do_load;
case OE_RR_X1(LD1U):
memop = MO_UB;
- mnemonic = "ld1u";
+ mnemonic = "ld1u"; /* prefetch, prefetch_l1 */
+ prefetch_nofault = (dest == TILEGX_R_ZERO);
goto do_load;
case OE_RR_X1(LD2S):
memop = MO_TESW;
- mnemonic = "ld2s";
+ mnemonic = "ld2s"; /* prefetch_l2_fault */
goto do_load;
case OE_RR_X1(LD2U):
memop = MO_TEUW;
- mnemonic = "ld2u";
+ mnemonic = "ld2u"; /* prefetch_l2 */
+ prefetch_nofault = (dest == TILEGX_R_ZERO);
goto do_load;
case OE_RR_X1(LD4S):
memop = MO_TESL;
- mnemonic = "ld4s";
+ mnemonic = "ld4s"; /* prefetch_l3_fault */
goto do_load;
case OE_RR_X1(LD4U):
memop = MO_TEUL;
- mnemonic = "ld4u";
+ mnemonic = "ld4u"; /* prefetch_l3 */
+ prefetch_nofault = (dest == TILEGX_R_ZERO);
goto do_load;
case OE_RR_X1(LDNT1S):
memop = MO_SB;
@@ -514,7 +675,9 @@ static TileExcp gen_rr_opcode(DisasContext *dc, unsigned opext,
memop = MO_TEQ;
mnemonic = "ld";
do_load:
- tcg_gen_qemu_ld_tl(tdest, tsrca, dc->mmuidx, memop);
+ if (!prefetch_nofault) {
+ tcg_gen_qemu_ld_tl(tdest, tsrca, dc->mmuidx, memop);
+ }
break;
case OE_RR_X1(LDNA):
tcg_gen_andi_tl(tdest, tsrca, ~7);
@@ -524,7 +687,7 @@ static TileExcp gen_rr_opcode(DisasContext *dc, unsigned opext,
case OE_RR_X1(LNK):
case OE_RR_Y1(LNK):
if (srca) {
- return TILEGX_EXCP_OPCODE_UNIMPLEMENTED;
+ return TILEGX_EXCP_OPCODE_UNKNOWN;
}
tcg_gen_movi_tl(tdest, dc->pc + TILEGX_BUNDLE_SIZE_IN_BYTES);
mnemonic = "lnk";
@@ -546,14 +709,29 @@ static TileExcp gen_rr_opcode(DisasContext *dc, unsigned opext,
break;
case OE_RR_X0(TBLIDXB0):
case OE_RR_Y0(TBLIDXB0):
+ tcg_gen_deposit_tl(tdest, load_gr(dc, dest), tsrca, 2, 8);
+ mnemonic = "tblidxb0";
+ break;
case OE_RR_X0(TBLIDXB1):
case OE_RR_Y0(TBLIDXB1):
+ tcg_gen_shri_tl(tdest, tsrca, 8);
+ tcg_gen_deposit_tl(tdest, load_gr(dc, dest), tdest, 2, 8);
+ mnemonic = "tblidxb1";
+ break;
case OE_RR_X0(TBLIDXB2):
case OE_RR_Y0(TBLIDXB2):
+ tcg_gen_shri_tl(tdest, tsrca, 16);
+ tcg_gen_deposit_tl(tdest, load_gr(dc, dest), tdest, 2, 8);
+ mnemonic = "tblidxb2";
+ break;
case OE_RR_X0(TBLIDXB3):
case OE_RR_Y0(TBLIDXB3):
+ tcg_gen_shri_tl(tdest, tsrca, 24);
+ tcg_gen_deposit_tl(tdest, load_gr(dc, dest), tdest, 2, 8);
+ mnemonic = "tblidxb3";
+ break;
default:
- return TILEGX_EXCP_OPCODE_UNIMPLEMENTED;
+ return TILEGX_EXCP_OPCODE_UNKNOWN;
}
qemu_log_mask(CPU_LOG_TB_IN_ASM, "%s %s, %s", mnemonic,
@@ -663,15 +841,41 @@ static TileExcp gen_rrr_opcode(DisasContext *dc, unsigned opext,
mnemonic = "cmpne";
break;
case OE_RRR(CMULAF, 0, X0):
+ gen_helper_cmulaf(tdest, load_gr(dc, dest), tsrca, tsrcb);
+ mnemonic = "cmulaf";
+ break;
case OE_RRR(CMULA, 0, X0):
+ gen_helper_cmula(tdest, load_gr(dc, dest), tsrca, tsrcb);
+ mnemonic = "cmula";
+ break;
case OE_RRR(CMULFR, 0, X0):
+ gen_cmul2(tdest, tsrca, tsrcb, 15, 1 << 14);
+ mnemonic = "cmulfr";
+ break;
case OE_RRR(CMULF, 0, X0):
+ gen_cmul2(tdest, tsrca, tsrcb, 15, 0);
+ mnemonic = "cmulf";
+ break;
case OE_RRR(CMULHR, 0, X0):
+ gen_cmul2(tdest, tsrca, tsrcb, 16, 1 << 15);
+ mnemonic = "cmulhr";
+ break;
case OE_RRR(CMULH, 0, X0):
+ gen_cmul2(tdest, tsrca, tsrcb, 16, 0);
+ mnemonic = "cmulh";
+ break;
case OE_RRR(CMUL, 0, X0):
+ gen_helper_cmula(tdest, load_zero(dc), tsrca, tsrcb);
+ mnemonic = "cmul";
+ break;
case OE_RRR(CRC32_32, 0, X0):
+ gen_helper_crc32_32(tdest, tsrca, tsrcb);
+ mnemonic = "crc32_32";
+ break;
case OE_RRR(CRC32_8, 0, X0):
- return TILEGX_EXCP_OPCODE_UNIMPLEMENTED;
+ gen_helper_crc32_8(tdest, tsrca, tsrcb);
+ mnemonic = "crc32_8";
+ break;
case OE_RRR(DBLALIGN2, 0, X0):
case OE_RRR(DBLALIGN2, 0, X1):
gen_dblaligni(tdest, tsrca, tsrcb, 16);
@@ -1024,8 +1228,12 @@ static TileExcp gen_rrr_opcode(DisasContext *dc, unsigned opext,
break;
case OE_RRR(V1ADDUC, 0, X0):
case OE_RRR(V1ADDUC, 0, X1):
+ return TILEGX_EXCP_OPCODE_UNIMPLEMENTED;
case OE_RRR(V1ADD, 0, X0):
case OE_RRR(V1ADD, 0, X1):
+ gen_v12add(tdest, tsrca, tsrcb, V1_IMM(0x80));
+ mnemonic = "v1add";
+ break;
case OE_RRR(V1ADIFFU, 0, X0):
case OE_RRR(V1AVGU, 0, X0):
return TILEGX_EXCP_OPCODE_UNIMPLEMENTED;
@@ -1060,17 +1268,28 @@ static TileExcp gen_rrr_opcode(DisasContext *dc, unsigned opext,
case OE_RRR(V1DOTPUS, 0, X0):
case OE_RRR(V1DOTPU, 0, X0):
case OE_RRR(V1DOTP, 0, X0):
+ return TILEGX_EXCP_OPCODE_UNIMPLEMENTED;
case OE_RRR(V1INT_H, 0, X0):
case OE_RRR(V1INT_H, 0, X1):
+ gen_helper_v1int_h(tdest, tsrca, tsrcb);
+ mnemonic = "v1int_h";
+ break;
case OE_RRR(V1INT_L, 0, X0):
case OE_RRR(V1INT_L, 0, X1):
+ gen_helper_v1int_l(tdest, tsrca, tsrcb);
+ mnemonic = "v1int_l";
+ break;
case OE_RRR(V1MAXU, 0, X0):
case OE_RRR(V1MAXU, 0, X1):
case OE_RRR(V1MINU, 0, X0):
case OE_RRR(V1MINU, 0, X1):
case OE_RRR(V1MNZ, 0, X0):
case OE_RRR(V1MNZ, 0, X1):
+ return TILEGX_EXCP_OPCODE_UNIMPLEMENTED;
case OE_RRR(V1MULTU, 0, X0):
+ gen_helper_v1multu(tdest, tsrca, tsrcb);
+ mnemonic = "v1multu";
+ break;
case OE_RRR(V1MULUS, 0, X0):
case OE_RRR(V1MULU, 0, X0):
case OE_RRR(V1MZ, 0, X0):
@@ -1095,12 +1314,20 @@ static TileExcp gen_rrr_opcode(DisasContext *dc, unsigned opext,
break;
case OE_RRR(V1SUBUC, 0, X0):
case OE_RRR(V1SUBUC, 0, X1):
+ return TILEGX_EXCP_OPCODE_UNIMPLEMENTED;
case OE_RRR(V1SUB, 0, X0):
case OE_RRR(V1SUB, 0, X1):
+ gen_v12sub(tdest, tsrca, tsrcb, V1_IMM(0x80));
+ mnemonic = "v1sub";
+ break;
case OE_RRR(V2ADDSC, 0, X0):
case OE_RRR(V2ADDSC, 0, X1):
+ return TILEGX_EXCP_OPCODE_UNIMPLEMENTED;
case OE_RRR(V2ADD, 0, X0):
case OE_RRR(V2ADD, 0, X1):
+ gen_v12add(tdest, tsrca, tsrcb, V2_IMM(0x8000));
+ mnemonic = "v2add";
+ break;
case OE_RRR(V2ADIFFS, 0, X0):
case OE_RRR(V2AVGS, 0, X0):
case OE_RRR(V2CMPEQ, 0, X0):
@@ -1117,10 +1344,17 @@ static TileExcp gen_rrr_opcode(DisasContext *dc, unsigned opext,
case OE_RRR(V2CMPNE, 0, X1):
case OE_RRR(V2DOTPA, 0, X0):
case OE_RRR(V2DOTP, 0, X0):
+ return TILEGX_EXCP_OPCODE_UNIMPLEMENTED;
case OE_RRR(V2INT_H, 0, X0):
case OE_RRR(V2INT_H, 0, X1):
+ gen_helper_v2int_h(tdest, tsrca, tsrcb);
+ mnemonic = "v2int_h";
+ break;
case OE_RRR(V2INT_L, 0, X0):
case OE_RRR(V2INT_L, 0, X1):
+ gen_helper_v2int_l(tdest, tsrca, tsrcb);
+ mnemonic = "v2int_l";
+ break;
case OE_RRR(V2MAXS, 0, X0):
case OE_RRR(V2MAXS, 0, X1):
case OE_RRR(V2MINS, 0, X0):
@@ -1129,7 +1363,11 @@ static TileExcp gen_rrr_opcode(DisasContext *dc, unsigned opext,
case OE_RRR(V2MNZ, 0, X1):
case OE_RRR(V2MULFSC, 0, X0):
case OE_RRR(V2MULS, 0, X0):
+ return TILEGX_EXCP_OPCODE_UNIMPLEMENTED;
case OE_RRR(V2MULTS, 0, X0):
+ gen_helper_v2mults(tdest, tsrca, tsrcb);
+ mnemonic = "v2mults";
+ break;
case OE_RRR(V2MZ, 0, X0):
case OE_RRR(V2MZ, 0, X1):
case OE_RRR(V2PACKH, 0, X0):
@@ -1144,21 +1382,38 @@ static TileExcp gen_rrr_opcode(DisasContext *dc, unsigned opext,
case OE_RRR(V2SADU, 0, X0):
case OE_RRR(V2SHLSC, 0, X0):
case OE_RRR(V2SHLSC, 0, X1):
+ return TILEGX_EXCP_OPCODE_UNIMPLEMENTED;
case OE_RRR(V2SHL, 0, X0):
case OE_RRR(V2SHL, 0, X1):
+ gen_helper_v2shl(tdest, tsrca, tsrcb);
+ mnemonic = "v2shl";
+ break;
case OE_RRR(V2SHRS, 0, X0):
case OE_RRR(V2SHRS, 0, X1):
+ gen_helper_v2shrs(tdest, tsrca, tsrcb);
+ mnemonic = "v2shrs";
+ break;
case OE_RRR(V2SHRU, 0, X0):
case OE_RRR(V2SHRU, 0, X1):
+ gen_helper_v2shru(tdest, tsrca, tsrcb);
+ mnemonic = "v2shru";
+ break;
case OE_RRR(V2SUBSC, 0, X0):
case OE_RRR(V2SUBSC, 0, X1):
+ return TILEGX_EXCP_OPCODE_UNIMPLEMENTED;
case OE_RRR(V2SUB, 0, X0):
case OE_RRR(V2SUB, 0, X1):
+ gen_v12sub(tdest, tsrca, tsrcb, V2_IMM(0x8000));
+ mnemonic = "v2sub";
+ break;
case OE_RRR(V4ADDSC, 0, X0):
case OE_RRR(V4ADDSC, 0, X1):
+ return TILEGX_EXCP_OPCODE_UNIMPLEMENTED;
case OE_RRR(V4ADD, 0, X0):
case OE_RRR(V4ADD, 0, X1):
- return TILEGX_EXCP_OPCODE_UNIMPLEMENTED;
+ gen_v4op(tdest, tsrca, tsrcb, tcg_gen_add_i32);
+ mnemonic = "v4add";
+ break;
case OE_RRR(V4INT_H, 0, X0):
case OE_RRR(V4INT_H, 0, X1):
tcg_gen_shri_tl(tdest, tsrcb, 32);
@@ -1174,17 +1429,30 @@ static TileExcp gen_rrr_opcode(DisasContext *dc, unsigned opext,
case OE_RRR(V4PACKSC, 0, X1):
case OE_RRR(V4SHLSC, 0, X0):
case OE_RRR(V4SHLSC, 0, X1):
+ return TILEGX_EXCP_OPCODE_UNIMPLEMENTED;
case OE_RRR(V4SHL, 0, X0):
case OE_RRR(V4SHL, 0, X1):
+ gen_v4sh(tdest, tsrca, tsrcb, tcg_gen_shl_i32);
+ mnemonic = "v4shl";
+ break;
case OE_RRR(V4SHRS, 0, X0):
case OE_RRR(V4SHRS, 0, X1):
+ gen_v4sh(tdest, tsrca, tsrcb, tcg_gen_sar_i32);
+ mnemonic = "v4shrs";
+ break;
case OE_RRR(V4SHRU, 0, X0):
case OE_RRR(V4SHRU, 0, X1):
+ gen_v4sh(tdest, tsrca, tsrcb, tcg_gen_shr_i32);
+ mnemonic = "v4shru";
+ break;
case OE_RRR(V4SUBSC, 0, X0):
case OE_RRR(V4SUBSC, 0, X1):
+ return TILEGX_EXCP_OPCODE_UNIMPLEMENTED;
case OE_RRR(V4SUB, 0, X0):
case OE_RRR(V4SUB, 0, X1):
- return TILEGX_EXCP_OPCODE_UNIMPLEMENTED;
+ gen_v4op(tdest, tsrca, tsrcb, tcg_gen_sub_i32);
+ mnemonic = "v2sub";
+ break;
case OE_RRR(XOR, 0, X0):
case OE_RRR(XOR, 0, X1):
case OE_RRR(XOR, 5, Y0):
@@ -1193,7 +1461,7 @@ static TileExcp gen_rrr_opcode(DisasContext *dc, unsigned opext,
mnemonic = "xor";
break;
default:
- return TILEGX_EXCP_OPCODE_UNIMPLEMENTED;
+ return TILEGX_EXCP_OPCODE_UNKNOWN;
}
qemu_log_mask(CPU_LOG_TB_IN_ASM, "%s %s, %s, %s", mnemonic,
@@ -1206,6 +1474,7 @@ static TileExcp gen_rri_opcode(DisasContext *dc, unsigned opext,
{
TCGv tdest = dest_gr(dc, dest);
TCGv tsrca = load_gr(dc, srca);
+ bool prefetch_nofault = false;
const char *mnemonic;
TCGMemOp memop;
int i2, i3;
@@ -1255,27 +1524,30 @@ static TileExcp gen_rri_opcode(DisasContext *dc, unsigned opext,
break;
case OE_IM(LD1S_ADD, X1):
memop = MO_SB;
- mnemonic = "ld1s_add";
+ mnemonic = "ld1s_add"; /* prefetch_add_l1_fault */
goto do_load_add;
case OE_IM(LD1U_ADD, X1):
memop = MO_UB;
- mnemonic = "ld1u_add";
+ mnemonic = "ld1u_add"; /* prefetch_add_l1 */
+ prefetch_nofault = (dest == TILEGX_R_ZERO);
goto do_load_add;
case OE_IM(LD2S_ADD, X1):
memop = MO_TESW;
- mnemonic = "ld2s_add";
+ mnemonic = "ld2s_add"; /* prefetch_add_l2_fault */
goto do_load_add;
case OE_IM(LD2U_ADD, X1):
memop = MO_TEUW;
- mnemonic = "ld2u_add";
+ mnemonic = "ld2u_add"; /* prefetch_add_l2 */
+ prefetch_nofault = (dest == TILEGX_R_ZERO);
goto do_load_add;
case OE_IM(LD4S_ADD, X1):
memop = MO_TESL;
- mnemonic = "ld4s_add";
+ mnemonic = "ld4s_add"; /* prefetch_add_l3_fault */
goto do_load_add;
case OE_IM(LD4U_ADD, X1):
memop = MO_TEUL;
- mnemonic = "ld4u_add";
+ mnemonic = "ld4u_add"; /* prefetch_add_l3 */
+ prefetch_nofault = (dest == TILEGX_R_ZERO);
goto do_load_add;
case OE_IM(LDNT1S_ADD, X1):
memop = MO_SB;
@@ -1307,9 +1579,11 @@ static TileExcp gen_rri_opcode(DisasContext *dc, unsigned opext,
goto do_load_add;
case OE_IM(LD_ADD, X1):
memop = MO_TEQ;
- mnemonic = "ldnt_add";
+ mnemonic = "ld_add";
do_load_add:
- tcg_gen_qemu_ld_tl(tdest, tsrca, dc->mmuidx, memop);
+ if (!prefetch_nofault) {
+ tcg_gen_qemu_ld_tl(tdest, tsrca, dc->mmuidx, memop);
+ }
tcg_gen_addi_tl(dest_gr(dc, srca), tsrca, imm);
break;
case OE_IM(LDNA_ADD, X1):
@@ -1325,6 +1599,11 @@ static TileExcp gen_rri_opcode(DisasContext *dc, unsigned opext,
break;
case OE_IM(V1ADDI, X0):
case OE_IM(V1ADDI, X1):
+ t0 = tcg_const_tl(V1_IMM(imm));
+ gen_v12add(tdest, tsrca, t0, V1_IMM(0x80));
+ tcg_temp_free(t0);
+ mnemonic = "v1addi";
+ break;
case OE_IM(V1CMPEQI, X0):
case OE_IM(V1CMPEQI, X1):
tcg_gen_xori_tl(tdest, tsrca, V1_IMM(imm));
@@ -1339,8 +1618,14 @@ static TileExcp gen_rri_opcode(DisasContext *dc, unsigned opext,
case OE_IM(V1MAXUI, X1):
case OE_IM(V1MINUI, X0):
case OE_IM(V1MINUI, X1):
+ return TILEGX_EXCP_OPCODE_UNIMPLEMENTED;
case OE_IM(V2ADDI, X0):
case OE_IM(V2ADDI, X1):
+ t0 = tcg_const_tl(V2_IMM(imm));
+ gen_v12add(tdest, tsrca, t0, V2_IMM(0x8000));
+ tcg_temp_free(t0);
+ mnemonic = "v2addi";
+ break;
case OE_IM(V2CMPEQI, X0):
case OE_IM(V2CMPEQI, X1):
case OE_IM(V2CMPLTSI, X0):
@@ -1427,11 +1712,27 @@ static TileExcp gen_rri_opcode(DisasContext *dc, unsigned opext,
break;
case OE_SH(V2SHLI, X0):
case OE_SH(V2SHLI, X1):
+ i2 = imm & 15;
+ i3 = 0xffff >> i2;
+ tcg_gen_andi_tl(tdest, tsrca, V2_IMM(i3));
+ tcg_gen_shli_tl(tdest, tdest, i2);
+ mnemonic = "v2shli";
+ break;
case OE_SH(V2SHRSI, X0):
case OE_SH(V2SHRSI, X1):
+ t0 = tcg_const_tl(imm & 15);
+ gen_helper_v2shrs(tdest, tsrca, t0);
+ tcg_temp_free(t0);
+ mnemonic = "v2shrsi";
+ break;
case OE_SH(V2SHRUI, X0):
case OE_SH(V2SHRUI, X1):
- return TILEGX_EXCP_OPCODE_UNIMPLEMENTED;
+ i2 = imm & 15;
+ i3 = (0xffff << i2) & 0xffff;
+ tcg_gen_andi_tl(tdest, tsrca, V2_IMM(i3));
+ tcg_gen_shri_tl(tdest, tdest, i2);
+ mnemonic = "v2shrui";
+ break;
case OE(ADDLI_OPCODE_X0, 0, X0):
case OE(ADDLI_OPCODE_X1, 0, X1):
@@ -1452,7 +1753,7 @@ static TileExcp gen_rri_opcode(DisasContext *dc, unsigned opext,
break;
default:
- return TILEGX_EXCP_OPCODE_UNIMPLEMENTED;
+ return TILEGX_EXCP_OPCODE_UNKNOWN;
}
qemu_log_mask(CPU_LOG_TB_IN_ASM, "%s %s, %s, %d", mnemonic,
@@ -1546,7 +1847,7 @@ static TileExcp gen_bf_opcode_x0(DisasContext *dc, unsigned ext,
break;
default:
- return TILEGX_EXCP_OPCODE_UNIMPLEMENTED;
+ return TILEGX_EXCP_OPCODE_UNKNOWN;
}
qemu_log_mask(CPU_LOG_TB_IN_ASM, "%s %s, %s, %u, %u", mnemonic,
@@ -1602,7 +1903,7 @@ static TileExcp gen_branch_opcode_x1(DisasContext *dc, unsigned ext,
mnemonic = "blbs";
break;
default:
- return TILEGX_EXCP_OPCODE_UNIMPLEMENTED;
+ return TILEGX_EXCP_OPCODE_UNKNOWN;
}
if (qemu_loglevel_mask(CPU_LOG_TB_IN_ASM)) {
@@ -1654,6 +1955,10 @@ static const TileSPR *find_spr(unsigned spr)
offsetof(CPUTLGState, spregs[TILEGX_SPR_CRITICAL_SEC]), 0, 0)
D(SIM_CONTROL,
offsetof(CPUTLGState, spregs[TILEGX_SPR_SIM_CONTROL]), 0, 0)
+ D(EX_CONTEXT_0_0,
+ offsetof(CPUTLGState, spregs[TILEGX_SPR_EX_CONTEXT_0_0]), 0, 0)
+ D(EX_CONTEXT_0_1,
+ offsetof(CPUTLGState, spregs[TILEGX_SPR_EX_CONTEXT_0_1]), 0, 0)
}
#undef D
@@ -1669,7 +1974,7 @@ static TileExcp gen_mtspr_x1(DisasContext *dc, unsigned spr, unsigned srca)
if (def == NULL) {
qemu_log_mask(CPU_LOG_TB_IN_ASM, "mtspr spr[%u], %s", spr, reg_names[srca]);
- return TILEGX_EXCP_OPCODE_UNKNOWN;
+ return TILEGX_EXCP_OPCODE_UNIMPLEMENTED;
}
tsrca = load_gr(dc, srca);
@@ -1689,7 +1994,7 @@ static TileExcp gen_mfspr_x1(DisasContext *dc, unsigned dest, unsigned spr)
if (def == NULL) {
qemu_log_mask(CPU_LOG_TB_IN_ASM, "mtspr %s, spr[%u]", reg_names[dest], spr);
- return TILEGX_EXCP_OPCODE_UNKNOWN;
+ return TILEGX_EXCP_OPCODE_UNIMPLEMENTED;
}
tdest = dest_gr(dc, dest);
@@ -1715,7 +2020,7 @@ static TileExcp decode_y0(DisasContext *dc, tilegx_bundle_bits bundle)
case RRR_1_OPCODE_Y0:
if (ext == UNARY_RRR_1_OPCODE_Y0) {
ext = get_UnaryOpcodeExtension_Y0(bundle);
- return gen_rr_opcode(dc, OE(opc, ext, Y0), dest, srca);
+ return gen_rr_opcode(dc, OE(opc, ext, Y0), dest, srca, bundle);
}
/* fallthru */
case RRR_0_OPCODE_Y0:
@@ -1744,7 +2049,7 @@ static TileExcp decode_y0(DisasContext *dc, tilegx_bundle_bits bundle)
return gen_rri_opcode(dc, OE(opc, 0, Y0), dest, srca, imm);
default:
- return TILEGX_EXCP_OPCODE_UNIMPLEMENTED;
+ return TILEGX_EXCP_OPCODE_UNKNOWN;
}
}
@@ -1761,7 +2066,7 @@ static TileExcp decode_y1(DisasContext *dc, tilegx_bundle_bits bundle)
case RRR_1_OPCODE_Y1:
if (ext == UNARY_RRR_1_OPCODE_Y0) {
ext = get_UnaryOpcodeExtension_Y1(bundle);
- return gen_rr_opcode(dc, OE(opc, ext, Y1), dest, srca);
+ return gen_rr_opcode(dc, OE(opc, ext, Y1), dest, srca, bundle);
}
/* fallthru */
case RRR_0_OPCODE_Y1:
@@ -1788,7 +2093,7 @@ static TileExcp decode_y1(DisasContext *dc, tilegx_bundle_bits bundle)
return gen_rri_opcode(dc, OE(opc, 0, Y1), dest, srca, imm);
default:
- return TILEGX_EXCP_OPCODE_UNIMPLEMENTED;
+ return TILEGX_EXCP_OPCODE_UNKNOWN;
}
}
@@ -1846,7 +2151,7 @@ static TileExcp decode_y2(DisasContext *dc, tilegx_bundle_bits bundle)
return gen_st_opcode(dc, 0, srca, srcbdest, MO_TEQ, "st");
default:
- return TILEGX_EXCP_OPCODE_UNIMPLEMENTED;
+ return TILEGX_EXCP_OPCODE_UNKNOWN;
}
}
@@ -1863,7 +2168,7 @@ static TileExcp decode_x0(DisasContext *dc, tilegx_bundle_bits bundle)
ext = get_RRROpcodeExtension_X0(bundle);
if (ext == UNARY_RRR_0_OPCODE_X0) {
ext = get_UnaryOpcodeExtension_X0(bundle);
- return gen_rr_opcode(dc, OE(opc, ext, X0), dest, srca);
+ return gen_rr_opcode(dc, OE(opc, ext, X0), dest, srca, bundle);
}
srcb = get_SrcB_X0(bundle);
return gen_rrr_opcode(dc, OE(opc, ext, X0), dest, srca, srcb);
@@ -1891,7 +2196,7 @@ static TileExcp decode_x0(DisasContext *dc, tilegx_bundle_bits bundle)
return gen_rri_opcode(dc, OE(opc, 0, X0), dest, srca, imm);
default:
- return TILEGX_EXCP_OPCODE_UNIMPLEMENTED;
+ return TILEGX_EXCP_OPCODE_UNKNOWN;
}
}
@@ -1910,7 +2215,7 @@ static TileExcp decode_x1(DisasContext *dc, tilegx_bundle_bits bundle)
switch (ext) {
case UNARY_RRR_0_OPCODE_X1:
ext = get_UnaryOpcodeExtension_X1(bundle);
- return gen_rr_opcode(dc, OE(opc, ext, X1), dest, srca);
+ return gen_rr_opcode(dc, OE(opc, ext, X1), dest, srca, bundle);
case ST1_RRR_0_OPCODE_X1:
return gen_st_opcode(dc, dest, srca, srcb, MO_UB, "st1");
case ST2_RRR_0_OPCODE_X1:
@@ -1981,7 +2286,7 @@ static TileExcp decode_x1(DisasContext *dc, tilegx_bundle_bits bundle)
return gen_rri_opcode(dc, OE(opc, 0, X1), dest, srca, imm);
default:
- return TILEGX_EXCP_OPCODE_UNIMPLEMENTED;
+ return TILEGX_EXCP_OPCODE_UNKNOWN;
}
}
@@ -1992,8 +2297,15 @@ static void notice_excp(DisasContext *dc, uint64_t bundle,
return;
}
gen_exception(dc, excp);
- if (excp == TILEGX_EXCP_OPCODE_UNIMPLEMENTED) {
+ switch (excp) {
+ case TILEGX_EXCP_OPCODE_UNIMPLEMENTED:
qemu_log_mask(LOG_UNIMP, "UNIMP %s, [" FMT64X "]\n", type, bundle);
+ break;
+ case TILEGX_EXCP_OPCODE_UNKNOWN:
+ qemu_log_mask(LOG_UNIMP, "UNKNOWN %s, [" FMT64X "]\n", type, bundle);
+ break;
+ default:
+ break;
}
}
@@ -2008,10 +2320,6 @@ static void translate_one_bundle(DisasContext *dc, uint64_t bundle)
}
dc->num_wb = 0;
- if (unlikely(qemu_loglevel_mask(CPU_LOG_TB_OP | CPU_LOG_TB_OP_OPT))) {
- tcg_gen_debug_insn_start(dc->pc);
- }
-
qemu_log_mask(CPU_LOG_TB_IN_ASM, " %" PRIx64 ": { ", dc->pc);
if (get_Mode(bundle)) {
notice_excp(dc, bundle, "y0", decode_y0(dc, bundle));
@@ -2053,17 +2361,14 @@ static void translate_one_bundle(DisasContext *dc, uint64_t bundle)
}
}
-static inline void gen_intermediate_code_internal(TileGXCPU *cpu,
- TranslationBlock *tb,
- bool search_pc)
+void gen_intermediate_code(CPUTLGState *env, struct TranslationBlock *tb)
{
+ TileGXCPU *cpu = tilegx_env_get_cpu(env);
DisasContext ctx;
DisasContext *dc = &ctx;
CPUState *cs = CPU(cpu);
- CPUTLGState *env = &cpu->env;
uint64_t pc_start = tb->pc;
uint64_t next_page_start = (pc_start & TARGET_PAGE_MASK) + TARGET_PAGE_SIZE;
- int j, lj = -1;
int num_insns = 0;
int max_insns = tb->cflags & CF_COUNT_MASK;
@@ -2085,21 +2390,15 @@ static inline void gen_intermediate_code_internal(TileGXCPU *cpu,
if (cs->singlestep_enabled || singlestep) {
max_insns = 1;
}
+ if (max_insns > TCG_MAX_INSNS) {
+ max_insns = TCG_MAX_INSNS;
+ }
gen_tb_start(tb);
while (1) {
- if (search_pc) {
- j = tcg_op_buf_count();
- if (lj < j) {
- lj++;
- while (lj < j) {
- tcg_ctx.gen_opc_instr_start[lj++] = 0;
- }
- }
- tcg_ctx.gen_opc_pc[lj] = dc->pc;
- tcg_ctx.gen_opc_instr_start[lj] = 1;
- tcg_ctx.gen_opc_icount[lj] = num_insns;
- }
+ tcg_gen_insn_start(dc->pc);
+ num_insns++;
+
translate_one_bundle(dc, cpu_ldq_data(env, dc->pc));
if (dc->exit_tb) {
@@ -2107,7 +2406,7 @@ static inline void gen_intermediate_code_internal(TileGXCPU *cpu,
break;
}
dc->pc += TILEGX_BUNDLE_SIZE_IN_BYTES;
- if (++num_insns >= max_insns
+ if (num_insns >= max_insns
|| dc->pc >= next_page_start
|| tcg_op_buf_full()) {
/* Ending the TB due to TB size or page boundary. Set PC. */
@@ -2118,33 +2417,16 @@ static inline void gen_intermediate_code_internal(TileGXCPU *cpu,
}
gen_tb_end(tb, num_insns);
- if (search_pc) {
- j = tcg_op_buf_count();
- lj++;
- while (lj <= j) {
- tcg_ctx.gen_opc_instr_start[lj++] = 0;
- }
- } else {
- tb->size = dc->pc - pc_start;
- tb->icount = num_insns;
- }
+ tb->size = dc->pc - pc_start;
+ tb->icount = num_insns;
qemu_log_mask(CPU_LOG_TB_IN_ASM, "\n");
}
-void gen_intermediate_code(CPUTLGState *env, struct TranslationBlock *tb)
-{
- gen_intermediate_code_internal(tilegx_env_get_cpu(env), tb, false);
-}
-
-void gen_intermediate_code_pc(CPUTLGState *env, struct TranslationBlock *tb)
-{
- gen_intermediate_code_internal(tilegx_env_get_cpu(env), tb, true);
-}
-
-void restore_state_to_opc(CPUTLGState *env, TranslationBlock *tb, int pc_pos)
+void restore_state_to_opc(CPUTLGState *env, TranslationBlock *tb,
+ target_ulong *data)
{
- env->pc = tcg_ctx.gen_opc_pc[pc_pos];
+ env->pc = data[0];
}
void tilegx_tcg_init(void)
diff --git a/target-tricore/translate.c b/target-tricore/translate.c
index 440f30a..135c583 100644
--- a/target-tricore/translate.c
+++ b/target-tricore/translate.c
@@ -8266,21 +8266,26 @@ static void decode_opc(CPUTriCoreState *env, DisasContext *ctx, int *is_branch)
}
}
-static inline void
-gen_intermediate_code_internal(TriCoreCPU *cpu, struct TranslationBlock *tb,
- int search_pc)
+void gen_intermediate_code(CPUTriCoreState *env, struct TranslationBlock *tb)
{
+ TriCoreCPU *cpu = tricore_env_get_cpu(env);
CPUState *cs = CPU(cpu);
- CPUTriCoreState *env = &cpu->env;
DisasContext ctx;
target_ulong pc_start;
- int num_insns;
+ int num_insns, max_insns;
- if (search_pc) {
- qemu_log("search pc %d\n", search_pc);
+ num_insns = 0;
+ max_insns = tb->cflags & CF_COUNT_MASK;
+ if (max_insns == 0) {
+ max_insns = CF_COUNT_MASK;
+ }
+ if (singlestep) {
+ max_insns = 1;
+ }
+ if (max_insns > TCG_MAX_INSNS) {
+ max_insns = TCG_MAX_INSNS;
}
- num_insns = 0;
pc_start = tb->pc;
ctx.pc = pc_start;
ctx.saved_pc = -1;
@@ -8292,17 +8297,13 @@ gen_intermediate_code_internal(TriCoreCPU *cpu, struct TranslationBlock *tb,
tcg_clear_temp_count();
gen_tb_start(tb);
while (ctx.bstate == BS_NONE) {
+ tcg_gen_insn_start(ctx.pc);
+ num_insns++;
+
ctx.opcode = cpu_ldl_code(env, ctx.pc);
decode_opc(env, &ctx, 0);
- num_insns++;
-
- if (tcg_op_buf_full()) {
- gen_save_pc(ctx.next_pc);
- tcg_gen_exit_tb(0);
- break;
- }
- if (singlestep) {
+ if (num_insns >= max_insns || tcg_op_buf_full()) {
gen_save_pc(ctx.next_pc);
tcg_gen_exit_tb(0);
break;
@@ -8311,12 +8312,9 @@ gen_intermediate_code_internal(TriCoreCPU *cpu, struct TranslationBlock *tb,
}
gen_tb_end(tb, num_insns);
- if (search_pc) {
- printf("done_generating search pc\n");
- } else {
- tb->size = ctx.pc - pc_start;
- tb->icount = num_insns;
- }
+ tb->size = ctx.pc - pc_start;
+ tb->icount = num_insns;
+
if (tcg_check_temp_count()) {
printf("LEAK at %08x\n", env->PC);
}
@@ -8331,21 +8329,10 @@ gen_intermediate_code_internal(TriCoreCPU *cpu, struct TranslationBlock *tb,
}
void
-gen_intermediate_code(CPUTriCoreState *env, struct TranslationBlock *tb)
-{
- gen_intermediate_code_internal(tricore_env_get_cpu(env), tb, false);
-}
-
-void
-gen_intermediate_code_pc(CPUTriCoreState *env, struct TranslationBlock *tb)
-{
- gen_intermediate_code_internal(tricore_env_get_cpu(env), tb, true);
-}
-
-void
-restore_state_to_opc(CPUTriCoreState *env, TranslationBlock *tb, int pc_pos)
+restore_state_to_opc(CPUTriCoreState *env, TranslationBlock *tb,
+ target_ulong *data)
{
- env->PC = tcg_ctx.gen_opc_pc[pc_pos];
+ env->PC = data[0];
}
/*
*
diff --git a/target-unicore32/translate.c b/target-unicore32/translate.c
index 2fc78e6..48f89fb 100644
--- a/target-unicore32/translate.c
+++ b/target-unicore32/translate.c
@@ -1794,10 +1794,6 @@ static void disas_uc32_insn(CPUUniCore32State *env, DisasContext *s)
UniCore32CPU *cpu = uc32_env_get_cpu(env);
unsigned int insn;
- if (unlikely(qemu_loglevel_mask(CPU_LOG_TB_OP | CPU_LOG_TB_OP_OPT))) {
- tcg_gen_debug_insn_start(s->pc);
- }
-
insn = cpu_ldl_code(env, s->pc);
s->pc += 4;
@@ -1868,16 +1864,12 @@ static void disas_uc32_insn(CPUUniCore32State *env, DisasContext *s)
}
/* generate intermediate code in gen_opc_buf and gen_opparam_buf for
- basic block 'tb'. If search_pc is TRUE, also generate PC
- information for each intermediate instruction. */
-static inline void gen_intermediate_code_internal(UniCore32CPU *cpu,
- TranslationBlock *tb, bool search_pc)
+ basic block 'tb'. */
+void gen_intermediate_code(CPUUniCore32State *env, TranslationBlock *tb)
{
+ UniCore32CPU *cpu = uc32_env_get_cpu(env);
CPUState *cs = CPU(cpu);
- CPUUniCore32State *env = &cpu->env;
DisasContext dc1, *dc = &dc1;
- CPUBreakpoint *bp;
- int j, lj;
target_ulong pc_start;
uint32_t next_page_start;
int num_insns;
@@ -1899,12 +1891,14 @@ static inline void gen_intermediate_code_internal(UniCore32CPU *cpu,
cpu_F0d = tcg_temp_new_i64();
cpu_F1d = tcg_temp_new_i64();
next_page_start = (pc_start & TARGET_PAGE_MASK) + TARGET_PAGE_SIZE;
- lj = -1;
num_insns = 0;
max_insns = tb->cflags & CF_COUNT_MASK;
if (max_insns == 0) {
max_insns = CF_COUNT_MASK;
}
+ if (max_insns > TCG_MAX_INSNS) {
+ max_insns = TCG_MAX_INSNS;
+ }
#ifndef CONFIG_USER_ONLY
if ((env->uncached_asr & ASR_M) == ASR_MODE_USER) {
@@ -1916,33 +1910,20 @@ static inline void gen_intermediate_code_internal(UniCore32CPU *cpu,
gen_tb_start(tb);
do {
- if (unlikely(!QTAILQ_EMPTY(&cs->breakpoints))) {
- QTAILQ_FOREACH(bp, &cs->breakpoints, entry) {
- if (bp->pc == dc->pc) {
- gen_set_pc_im(dc->pc);
- gen_exception(EXCP_DEBUG);
- dc->is_jmp = DISAS_JUMP;
- /* Advance PC so that clearing the breakpoint will
- invalidate this TB. */
- dc->pc += 2; /* FIXME */
- goto done_generating;
- }
- }
- }
- if (search_pc) {
- j = tcg_op_buf_count();
- if (lj < j) {
- lj++;
- while (lj < j) {
- tcg_ctx.gen_opc_instr_start[lj++] = 0;
- }
- }
- tcg_ctx.gen_opc_pc[lj] = dc->pc;
- tcg_ctx.gen_opc_instr_start[lj] = 1;
- tcg_ctx.gen_opc_icount[lj] = num_insns;
+ tcg_gen_insn_start(dc->pc);
+ num_insns++;
+
+ if (unlikely(cpu_breakpoint_test(cs, dc->pc, BP_ANY))) {
+ gen_set_pc_im(dc->pc);
+ gen_exception(EXCP_DEBUG);
+ dc->is_jmp = DISAS_JUMP;
+ /* Advance PC so that clearing the breakpoint will
+ invalidate this TB. */
+ dc->pc += 2; /* FIXME */
+ goto done_generating;
}
- if (num_insns + 1 == max_insns && (tb->cflags & CF_LAST_IO)) {
+ if (num_insns == max_insns && (tb->cflags & CF_LAST_IO)) {
gen_io_start();
}
@@ -1961,7 +1942,6 @@ static inline void gen_intermediate_code_internal(UniCore32CPU *cpu,
* Otherwise the subsequent code could get translated several times.
* Also stop translation when a page boundary is reached. This
* ensures prefetch aborts occur at the right place. */
- num_insns++;
} while (!dc->is_jmp && !tcg_op_buf_full() &&
!cs->singlestep_enabled &&
!singlestep &&
@@ -2043,26 +2023,8 @@ done_generating:
qemu_log("\n");
}
#endif
- if (search_pc) {
- j = tcg_op_buf_count();
- lj++;
- while (lj <= j) {
- tcg_ctx.gen_opc_instr_start[lj++] = 0;
- }
- } else {
- tb->size = dc->pc - pc_start;
- tb->icount = num_insns;
- }
-}
-
-void gen_intermediate_code(CPUUniCore32State *env, TranslationBlock *tb)
-{
- gen_intermediate_code_internal(uc32_env_get_cpu(env), tb, false);
-}
-
-void gen_intermediate_code_pc(CPUUniCore32State *env, TranslationBlock *tb)
-{
- gen_intermediate_code_internal(uc32_env_get_cpu(env), tb, true);
+ tb->size = dc->pc - pc_start;
+ tb->icount = num_insns;
}
static const char *cpu_mode_names[16] = {
@@ -2133,7 +2095,8 @@ void uc32_cpu_dump_state(CPUState *cs, FILE *f,
cpu_dump_state_ucf64(env, f, cpu_fprintf, flags);
}
-void restore_state_to_opc(CPUUniCore32State *env, TranslationBlock *tb, int pc_pos)
+void restore_state_to_opc(CPUUniCore32State *env, TranslationBlock *tb,
+ target_ulong *data)
{
- env->regs[31] = tcg_ctx.gen_opc_pc[pc_pos];
+ env->regs[31] = data[0];
}
diff --git a/target-xtensa/cpu.h b/target-xtensa/cpu.h
index 148a0f8..006bcb7 100644
--- a/target-xtensa/cpu.h
+++ b/target-xtensa/cpu.h
@@ -382,7 +382,6 @@ typedef struct CPUXtensaState {
#include "cpu-qom.h"
#define cpu_exec cpu_xtensa_exec
-#define cpu_gen_code cpu_xtensa_gen_code
#define cpu_signal_handler cpu_xtensa_signal_handler
#define cpu_list xtensa_cpu_list
diff --git a/target-xtensa/translate.c b/target-xtensa/translate.c
index a29b3e6..fda91b7 100644
--- a/target-xtensa/translate.c
+++ b/target-xtensa/translate.c
@@ -2984,22 +2984,6 @@ static inline unsigned xtensa_insn_len(CPUXtensaState *env, DisasContext *dc)
return xtensa_op0_insn_len(OP0);
}
-static void check_breakpoint(CPUXtensaState *env, DisasContext *dc)
-{
- CPUState *cs = CPU(xtensa_env_get_cpu(env));
- CPUBreakpoint *bp;
-
- if (unlikely(!QTAILQ_EMPTY(&cs->breakpoints))) {
- QTAILQ_FOREACH(bp, &cs->breakpoints, entry) {
- if (bp->pc == dc->pc) {
- tcg_gen_movi_i32(cpu_pc, dc->pc);
- gen_exception(dc, EXCP_DEBUG);
- dc->is_jmp = DISAS_UPDATE;
- }
- }
- }
-}
-
static void gen_ibreak_check(CPUXtensaState *env, DisasContext *dc)
{
unsigned i;
@@ -3013,15 +2997,12 @@ static void gen_ibreak_check(CPUXtensaState *env, DisasContext *dc)
}
}
-static inline
-void gen_intermediate_code_internal(XtensaCPU *cpu,
- TranslationBlock *tb, bool search_pc)
+void gen_intermediate_code(CPUXtensaState *env, TranslationBlock *tb)
{
+ XtensaCPU *cpu = xtensa_env_get_cpu(env);
CPUState *cs = CPU(cpu);
- CPUXtensaState *env = &cpu->env;
DisasContext dc;
int insn_count = 0;
- int j, lj = -1;
int max_insns = tb->cflags & CF_COUNT_MASK;
uint32_t pc_start = tb->pc;
uint32_t next_page_start =
@@ -3030,6 +3011,9 @@ void gen_intermediate_code_internal(XtensaCPU *cpu,
if (max_insns == 0) {
max_insns = CF_COUNT_MASK;
}
+ if (max_insns > TCG_MAX_INSNS) {
+ max_insns = TCG_MAX_INSNS;
+ }
dc.config = env->config;
dc.singlestep_enabled = cs->singlestep_enabled;
@@ -3062,28 +3046,19 @@ void gen_intermediate_code_internal(XtensaCPU *cpu,
}
do {
- check_breakpoint(env, &dc);
+ tcg_gen_insn_start(dc.pc);
+ ++insn_count;
- if (search_pc) {
- j = tcg_op_buf_count();
- if (lj < j) {
- lj++;
- while (lj < j) {
- tcg_ctx.gen_opc_instr_start[lj++] = 0;
- }
- }
- tcg_ctx.gen_opc_pc[lj] = dc.pc;
- tcg_ctx.gen_opc_instr_start[lj] = 1;
- tcg_ctx.gen_opc_icount[lj] = insn_count;
- }
+ ++dc.ccount_delta;
- if (unlikely(qemu_loglevel_mask(CPU_LOG_TB_OP | CPU_LOG_TB_OP_OPT))) {
- tcg_gen_debug_insn_start(dc.pc);
+ if (unlikely(cpu_breakpoint_test(cs, dc.pc, BP_ANY))) {
+ tcg_gen_movi_i32(cpu_pc, dc.pc);
+ gen_exception(&dc, EXCP_DEBUG);
+ dc.is_jmp = DISAS_UPDATE;
+ break;
}
- ++dc.ccount_delta;
-
- if (insn_count + 1 == max_insns && (tb->cflags & CF_LAST_IO)) {
+ if (insn_count == max_insns && (tb->cflags & CF_LAST_IO)) {
gen_io_start();
}
@@ -3104,7 +3079,6 @@ void gen_intermediate_code_internal(XtensaCPU *cpu,
}
disas_xtensa_insn(env, &dc);
- ++insn_count;
if (dc.icount) {
tcg_gen_mov_i32(cpu_SR[ICOUNT], dc.next_icount);
}
@@ -3142,24 +3116,8 @@ void gen_intermediate_code_internal(XtensaCPU *cpu,
qemu_log("\n");
}
#endif
- if (search_pc) {
- j = tcg_op_buf_count();
- memset(tcg_ctx.gen_opc_instr_start + lj + 1, 0,
- (j - lj) * sizeof(tcg_ctx.gen_opc_instr_start[0]));
- } else {
- tb->size = dc.pc - pc_start;
- tb->icount = insn_count;
- }
-}
-
-void gen_intermediate_code(CPUXtensaState *env, TranslationBlock *tb)
-{
- gen_intermediate_code_internal(xtensa_env_get_cpu(env), tb, false);
-}
-
-void gen_intermediate_code_pc(CPUXtensaState *env, TranslationBlock *tb)
-{
- gen_intermediate_code_internal(xtensa_env_get_cpu(env), tb, true);
+ tb->size = dc.pc - pc_start;
+ tb->icount = insn_count;
}
void xtensa_cpu_dump_state(CPUState *cs, FILE *f,
@@ -3213,7 +3171,8 @@ void xtensa_cpu_dump_state(CPUState *cs, FILE *f,
}
}
-void restore_state_to_opc(CPUXtensaState *env, TranslationBlock *tb, int pc_pos)
+void restore_state_to_opc(CPUXtensaState *env, TranslationBlock *tb,
+ target_ulong *data)
{
- env->pc = tcg_ctx.gen_opc_pc[pc_pos];
+ env->pc = data[0];
}
diff --git a/tcg/tcg-op.h b/tcg/tcg-op.h
index 6da083a..4e20dc1 100644
--- a/tcg/tcg-op.h
+++ b/tcg/tcg-op.h
@@ -700,17 +700,53 @@ static inline void tcg_gen_concat32_i64(TCGv_i64 ret, TCGv_i64 lo, TCGv_i64 hi)
#error must include QEMU headers
#endif
-/* debug info: write the PC of the corresponding QEMU CPU instruction */
-static inline void tcg_gen_debug_insn_start(uint64_t pc)
+#if TARGET_INSN_START_WORDS == 1
+# if TARGET_LONG_BITS <= TCG_TARGET_REG_BITS
+static inline void tcg_gen_insn_start(target_ulong pc)
{
- /* XXX: must really use a 32 bit size for TCGArg in all cases */
-#if TARGET_LONG_BITS > TCG_TARGET_REG_BITS
- tcg_gen_op2ii(INDEX_op_debug_insn_start,
- (uint32_t)(pc), (uint32_t)(pc >> 32));
+ tcg_gen_op1(&tcg_ctx, INDEX_op_insn_start, pc);
+}
+# else
+static inline void tcg_gen_insn_start(target_ulong pc)
+{
+ tcg_gen_op2(&tcg_ctx, INDEX_op_insn_start,
+ (uint32_t)pc, (uint32_t)(pc >> 32));
+}
+# endif
+#elif TARGET_INSN_START_WORDS == 2
+# if TARGET_LONG_BITS <= TCG_TARGET_REG_BITS
+static inline void tcg_gen_insn_start(target_ulong pc, target_ulong a1)
+{
+ tcg_gen_op2(&tcg_ctx, INDEX_op_insn_start, pc, a1);
+}
+# else
+static inline void tcg_gen_insn_start(target_ulong pc, target_ulong a1)
+{
+ tcg_gen_op4(&tcg_ctx, INDEX_op_insn_start,
+ (uint32_t)pc, (uint32_t)(pc >> 32),
+ (uint32_t)a1, (uint32_t)(a1 >> 32));
+}
+# endif
+#elif TARGET_INSN_START_WORDS == 3
+# if TARGET_LONG_BITS <= TCG_TARGET_REG_BITS
+static inline void tcg_gen_insn_start(target_ulong pc, target_ulong a1,
+ target_ulong a2)
+{
+ tcg_gen_op3(&tcg_ctx, INDEX_op_insn_start, pc, a1, a2);
+}
+# else
+static inline void tcg_gen_insn_start(target_ulong pc, target_ulong a1,
+ target_ulong a2)
+{
+ tcg_gen_op6(&tcg_ctx, INDEX_op_insn_start,
+ (uint32_t)pc, (uint32_t)(pc >> 32),
+ (uint32_t)a1, (uint32_t)(a1 >> 32),
+ (uint32_t)a2, (uint32_t)(a2 >> 32));
+}
+# endif
#else
- tcg_gen_op1i(INDEX_op_debug_insn_start, pc);
+# error "Unhandled number of operands to insn_start"
#endif
-}
static inline void tcg_gen_exit_tb(uintptr_t val)
{
diff --git a/tcg/tcg-opc.h b/tcg/tcg-opc.h
index 02bbf30..c6f9570 100644
--- a/tcg/tcg-opc.h
+++ b/tcg/tcg-opc.h
@@ -175,9 +175,9 @@ DEF(mulsh_i64, 1, 2, 0, IMPL(TCG_TARGET_HAS_mulsh_i64))
/* QEMU specific */
#if TARGET_LONG_BITS > TCG_TARGET_REG_BITS
-DEF(debug_insn_start, 0, 0, 2, TCG_OPF_NOT_PRESENT)
+DEF(insn_start, 0, 0, 2 * TARGET_INSN_START_WORDS, TCG_OPF_NOT_PRESENT)
#else
-DEF(debug_insn_start, 0, 0, 1, TCG_OPF_NOT_PRESENT)
+DEF(insn_start, 0, 0, TARGET_INSN_START_WORDS, TCG_OPF_NOT_PRESENT)
#endif
DEF(exit_tb, 0, 0, 1, TCG_OPF_BB_END)
DEF(goto_tb, 0, 0, 1, TCG_OPF_BB_END)
diff --git a/tcg/tcg.c b/tcg/tcg.c
index a2cb027..682af8a 100644
--- a/tcg/tcg.c
+++ b/tcg/tcg.c
@@ -363,17 +363,39 @@ void tcg_context_init(TCGContext *s)
void tcg_prologue_init(TCGContext *s)
{
- /* init global prologue and epilogue */
- s->code_buf = s->code_gen_prologue;
- s->code_ptr = s->code_buf;
+ size_t prologue_size, total_size;
+ void *buf0, *buf1;
+
+ /* Put the prologue at the beginning of code_gen_buffer. */
+ buf0 = s->code_gen_buffer;
+ s->code_ptr = buf0;
+ s->code_buf = buf0;
+ s->code_gen_prologue = buf0;
+
+ /* Generate the prologue. */
tcg_target_qemu_prologue(s);
- flush_icache_range((uintptr_t)s->code_buf, (uintptr_t)s->code_ptr);
+ buf1 = s->code_ptr;
+ flush_icache_range((uintptr_t)buf0, (uintptr_t)buf1);
+
+ /* Deduct the prologue from the buffer. */
+ prologue_size = tcg_current_code_size(s);
+ s->code_gen_ptr = buf1;
+ s->code_gen_buffer = buf1;
+ s->code_buf = buf1;
+ total_size = s->code_gen_buffer_size - prologue_size;
+ s->code_gen_buffer_size = total_size;
+
+ /* Compute a high-water mark, at which we voluntarily flush the buffer
+ and start over. The size here is arbitrary, significantly larger
+ than we expect the code generation for any one opcode to require. */
+ s->code_gen_highwater = s->code_gen_buffer + (total_size - 1024);
+
+ tcg_register_jit(s->code_gen_buffer, total_size);
#ifdef DEBUG_DISAS
if (qemu_loglevel_mask(CPU_LOG_TB_OUT_ASM)) {
- size_t size = tcg_current_code_size(s);
- qemu_log("PROLOGUE: [size=%zu]\n", size);
- log_disas(s->code_buf, size);
+ qemu_log("PROLOGUE: [size=%zu]\n", prologue_size);
+ log_disas(buf0, prologue_size);
qemu_log("\n");
qemu_log_flush();
}
@@ -990,17 +1012,18 @@ void tcg_dump_ops(TCGContext *s)
def = &tcg_op_defs[c];
args = &s->gen_opparam_buf[op->args];
- if (c == INDEX_op_debug_insn_start) {
- uint64_t pc;
+ if (c == INDEX_op_insn_start) {
+ qemu_log("%s ----", oi != s->gen_first_op_idx ? "\n" : "");
+
+ for (i = 0; i < TARGET_INSN_START_WORDS; ++i) {
+ target_ulong a;
#if TARGET_LONG_BITS > TCG_TARGET_REG_BITS
- pc = ((uint64_t)args[1] << 32) | args[0];
+ a = ((target_ulong)args[i * 2 + 1] << 32) | args[i * 2];
#else
- pc = args[0];
+ a = args[i];
#endif
- if (oi != s->gen_first_op_idx) {
- qemu_log("\n");
+ qemu_log(" " TARGET_FMT_lx, a);
}
- qemu_log(" ---- 0x%" PRIx64, pc);
} else if (c == INDEX_op_call) {
/* variable number of arguments */
nb_oargs = op->callo;
@@ -1400,7 +1423,7 @@ static void tcg_liveness_analysis(TCGContext *s)
}
}
break;
- case INDEX_op_debug_insn_start:
+ case INDEX_op_insn_start:
break;
case INDEX_op_discard:
/* mark the temporary as dead */
@@ -2289,11 +2312,27 @@ void tcg_dump_op_count(FILE *f, fprintf_function cpu_fprintf)
#endif
-static inline int tcg_gen_code_common(TCGContext *s,
- tcg_insn_unit *gen_code_buf,
- long search_pc)
+int tcg_gen_code(TCGContext *s, tcg_insn_unit *gen_code_buf)
{
- int oi, oi_next;
+ int i, oi, oi_next, num_insns;
+
+#ifdef CONFIG_PROFILER
+ {
+ int n;
+
+ n = s->gen_last_op_idx + 1;
+ s->op_count += n;
+ if (n > s->op_count_max) {
+ s->op_count_max = n;
+ }
+
+ n = s->nb_temps;
+ s->temp_count += n;
+ if (n > s->temp_count_max) {
+ s->temp_count_max = n;
+ }
+ }
+#endif
#ifdef DEBUG_DISAS
if (unlikely(qemu_loglevel_mask(CPU_LOG_TB_OP))) {
@@ -2337,6 +2376,7 @@ static inline int tcg_gen_code_common(TCGContext *s,
tcg_out_tb_init(s);
+ num_insns = -1;
for (oi = s->gen_first_op_idx; oi >= 0; oi = oi_next) {
TCGOp * const op = &s->gen_op_buf[oi];
TCGArg * const args = &s->gen_opparam_buf[op->args];
@@ -2359,7 +2399,20 @@ static inline int tcg_gen_code_common(TCGContext *s,
case INDEX_op_movi_i64:
tcg_reg_alloc_movi(s, args, dead_args, sync_args);
break;
- case INDEX_op_debug_insn_start:
+ case INDEX_op_insn_start:
+ if (num_insns >= 0) {
+ s->gen_insn_end_off[num_insns] = tcg_current_code_size(s);
+ }
+ num_insns++;
+ for (i = 0; i < TARGET_INSN_START_WORDS; ++i) {
+ target_ulong a;
+#if TARGET_LONG_BITS > TCG_TARGET_REG_BITS
+ a = ((target_ulong)args[i * 2 + 1] << 32) | args[i * 2];
+#else
+ a = args[i];
+#endif
+ s->gen_insn_data[num_insns][i] = a;
+ }
break;
case INDEX_op_discard:
temp_dead(s, args[0]);
@@ -2383,40 +2436,22 @@ static inline int tcg_gen_code_common(TCGContext *s,
tcg_reg_alloc_op(s, def, opc, args, dead_args, sync_args);
break;
}
- if (search_pc >= 0 && search_pc < tcg_current_code_size(s)) {
- return oi;
- }
#ifndef NDEBUG
check_regs(s);
#endif
+ /* Test for (pending) buffer overflow. The assumption is that any
+ one operation beginning below the high water mark cannot overrun
+ the buffer completely. Thus we can test for overflow after
+ generating code without having to check during generation. */
+ if (unlikely(s->code_gen_ptr > s->code_gen_highwater)) {
+ return -1;
+ }
}
+ tcg_debug_assert(num_insns >= 0);
+ s->gen_insn_end_off[num_insns] = tcg_current_code_size(s);
/* Generate TB finalization at the end of block */
tcg_out_tb_finalize(s);
- return -1;
-}
-
-int tcg_gen_code(TCGContext *s, tcg_insn_unit *gen_code_buf)
-{
-#ifdef CONFIG_PROFILER
- {
- int n;
-
- n = s->gen_last_op_idx + 1;
- s->op_count += n;
- if (n > s->op_count_max) {
- s->op_count_max = n;
- }
-
- n = s->nb_temps;
- s->temp_count += n;
- if (n > s->temp_count_max) {
- s->temp_count_max = n;
- }
- }
-#endif
-
- tcg_gen_code_common(s, gen_code_buf, -1);
/* flush instruction cache */
flush_icache_range((uintptr_t)s->code_buf, (uintptr_t)s->code_ptr);
@@ -2424,38 +2459,30 @@ int tcg_gen_code(TCGContext *s, tcg_insn_unit *gen_code_buf)
return tcg_current_code_size(s);
}
-/* Return the index of the micro operation such as the pc after is <
- offset bytes from the start of the TB. The contents of gen_code_buf must
- not be changed, though writing the same values is ok.
- Return -1 if not found. */
-int tcg_gen_code_search_pc(TCGContext *s, tcg_insn_unit *gen_code_buf,
- long offset)
-{
- return tcg_gen_code_common(s, gen_code_buf, offset);
-}
-
#ifdef CONFIG_PROFILER
void tcg_dump_info(FILE *f, fprintf_function cpu_fprintf)
{
TCGContext *s = &tcg_ctx;
- int64_t tot;
+ int64_t tb_count = s->tb_count;
+ int64_t tb_div_count = tb_count ? tb_count : 1;
+ int64_t tot = s->interm_time + s->code_time;
- tot = s->interm_time + s->code_time;
cpu_fprintf(f, "JIT cycles %" PRId64 " (%0.3f s at 2.4 GHz)\n",
tot, tot / 2.4e9);
cpu_fprintf(f, "translated TBs %" PRId64 " (aborted=%" PRId64 " %0.1f%%)\n",
- s->tb_count,
- s->tb_count1 - s->tb_count,
- s->tb_count1 ? (double)(s->tb_count1 - s->tb_count) / s->tb_count1 * 100.0 : 0);
+ tb_count, s->tb_count1 - tb_count,
+ (double)(s->tb_count1 - s->tb_count)
+ / (s->tb_count1 ? s->tb_count1 : 1) * 100.0);
cpu_fprintf(f, "avg ops/TB %0.1f max=%d\n",
- s->tb_count ? (double)s->op_count / s->tb_count : 0, s->op_count_max);
+ (double)s->op_count / tb_div_count, s->op_count_max);
cpu_fprintf(f, "deleted ops/TB %0.2f\n",
- s->tb_count ?
- (double)s->del_op_count / s->tb_count : 0);
+ (double)s->del_op_count / tb_div_count);
cpu_fprintf(f, "avg temps/TB %0.2f max=%d\n",
- s->tb_count ?
- (double)s->temp_count / s->tb_count : 0,
- s->temp_count_max);
+ (double)s->temp_count / tb_div_count, s->temp_count_max);
+ cpu_fprintf(f, "avg host code/TB %0.1f\n",
+ (double)s->code_out_len / tb_div_count);
+ cpu_fprintf(f, "avg search data/TB %0.1f\n",
+ (double)s->search_out_len / tb_div_count);
cpu_fprintf(f, "cycles/op %0.1f\n",
s->op_count ? (double)tot / s->op_count : 0);
@@ -2463,8 +2490,11 @@ void tcg_dump_info(FILE *f, fprintf_function cpu_fprintf)
s->code_in_len ? (double)tot / s->code_in_len : 0);
cpu_fprintf(f, "cycles/out byte %0.1f\n",
s->code_out_len ? (double)tot / s->code_out_len : 0);
- if (tot == 0)
+ cpu_fprintf(f, "cycles/search byte %0.1f\n",
+ s->search_out_len ? (double)tot / s->search_out_len : 0);
+ if (tot == 0) {
tot = 1;
+ }
cpu_fprintf(f, " gen_interm time %0.1f%%\n",
(double)s->interm_time / tot * 100.0);
cpu_fprintf(f, " gen_code time %0.1f%%\n",
diff --git a/tcg/tcg.h b/tcg/tcg.h
index 879a665..a696922 100644
--- a/tcg/tcg.h
+++ b/tcg/tcg.h
@@ -129,6 +129,12 @@ typedef uint64_t TCGRegSet;
# error "Missing unsigned widening multiply"
#endif
+#ifndef TARGET_INSN_START_EXTRA_WORDS
+# define TARGET_INSN_START_WORDS 1
+#else
+# define TARGET_INSN_START_WORDS (1 + TARGET_INSN_START_EXTRA_WORDS)
+#endif
+
typedef enum TCGOpcode {
#define DEF(name, oargs, iargs, cargs, flags) INDEX_op_ ## name,
#include "tcg-opc.h"
@@ -188,6 +194,7 @@ typedef struct TCGPool {
#define TCG_POOL_CHUNK_SIZE 32768
#define TCG_MAX_TEMPS 512
+#define TCG_MAX_INSNS 512
/* when the size of the arguments of a called function is smaller than
this value, they are statically allocated in the TB stack frame */
@@ -525,6 +532,7 @@ struct TCGContext {
int64_t del_op_count;
int64_t code_in_len;
int64_t code_out_len;
+ int64_t search_out_len;
int64_t interm_time;
int64_t code_time;
int64_t la_time;
@@ -551,10 +559,11 @@ struct TCGContext {
void *code_gen_prologue;
void *code_gen_buffer;
size_t code_gen_buffer_size;
- /* threshold to flush the translated code buffer */
- size_t code_gen_buffer_max_size;
void *code_gen_ptr;
+ /* Threshold to flush the translated code buffer. */
+ void *code_gen_highwater;
+
TBContext tb_ctx;
/* The TCGBackendData structure is private to tcg-target.c. */
@@ -570,9 +579,8 @@ struct TCGContext {
TCGOp gen_op_buf[OPC_BUF_SIZE];
TCGArg gen_opparam_buf[OPPARAM_BUF_SIZE];
- target_ulong gen_opc_pc[OPC_BUF_SIZE];
- uint16_t gen_opc_icount[OPC_BUF_SIZE];
- uint8_t gen_opc_instr_start[OPC_BUF_SIZE];
+ uint16_t gen_insn_end_off[TCG_MAX_INSNS];
+ target_ulong gen_insn_data[TCG_MAX_INSNS][TARGET_INSN_START_WORDS];
};
extern TCGContext tcg_ctx;
@@ -619,8 +627,6 @@ void tcg_prologue_init(TCGContext *s);
void tcg_func_start(TCGContext *s);
int tcg_gen_code(TCGContext *s, tcg_insn_unit *gen_code_buf);
-int tcg_gen_code_search_pc(TCGContext *s, tcg_insn_unit *gen_code_buf,
- long offset);
void tcg_set_frame(TCGContext *s, int reg, intptr_t start, intptr_t size);
diff --git a/tci.c b/tci.c
index 70eaab2..b5ed7b1 100644
--- a/tci.c
+++ b/tci.c
@@ -1081,15 +1081,6 @@ uintptr_t tcg_qemu_tb_exec(CPUArchState *env, uint8_t *tb_ptr)
/* QEMU specific operations. */
-#if TARGET_LONG_BITS > TCG_TARGET_REG_BITS
- case INDEX_op_debug_insn_start:
- TODO();
- break;
-#else
- case INDEX_op_debug_insn_start:
- TODO();
- break;
-#endif
case INDEX_op_exit_tb:
next_tb = *(uint64_t *)tb_ptr;
goto exit;
diff --git a/tests/test-string-output-visitor.c b/tests/test-string-output-visitor.c
index 101fb27..fd5e67b 100644
--- a/tests/test-string-output-visitor.c
+++ b/tests/test-string-output-visitor.c
@@ -248,39 +248,39 @@ int main(int argc, char **argv)
output_visitor_test_add("/string-visitor/output/int",
&out_visitor_data, test_visitor_out_int, false);
- output_visitor_test_add("/string-visitor/output/int",
+ output_visitor_test_add("/string-visitor/output/int-human",
&out_visitor_data, test_visitor_out_int, true);
output_visitor_test_add("/string-visitor/output/bool",
&out_visitor_data, test_visitor_out_bool, false);
- output_visitor_test_add("/string-visitor/output/bool",
+ output_visitor_test_add("/string-visitor/output/bool-human",
&out_visitor_data, test_visitor_out_bool, true);
output_visitor_test_add("/string-visitor/output/number",
&out_visitor_data, test_visitor_out_number, false);
- output_visitor_test_add("/string-visitor/output/number",
+ output_visitor_test_add("/string-visitor/output/number-human",
&out_visitor_data, test_visitor_out_number, true);
output_visitor_test_add("/string-visitor/output/string",
&out_visitor_data, test_visitor_out_string, false);
- output_visitor_test_add("/string-visitor/output/string",
+ output_visitor_test_add("/string-visitor/output/string-human",
&out_visitor_data, test_visitor_out_string, true);
output_visitor_test_add("/string-visitor/output/no-string",
&out_visitor_data, test_visitor_out_no_string,
false);
- output_visitor_test_add("/string-visitor/output/no-string",
+ output_visitor_test_add("/string-visitor/output/no-string-human",
&out_visitor_data, test_visitor_out_no_string,
true);
output_visitor_test_add("/string-visitor/output/enum",
&out_visitor_data, test_visitor_out_enum, false);
- output_visitor_test_add("/string-visitor/output/enum",
+ output_visitor_test_add("/string-visitor/output/enum-human",
&out_visitor_data, test_visitor_out_enum, true);
output_visitor_test_add("/string-visitor/output/enum-errors",
&out_visitor_data, test_visitor_out_enum_errors,
false);
- output_visitor_test_add("/string-visitor/output/enum-errors",
+ output_visitor_test_add("/string-visitor/output/enum-errors-human",
&out_visitor_data, test_visitor_out_enum_errors,
true);
output_visitor_test_add("/string-visitor/output/intList",
&out_visitor_data, test_visitor_out_intList, false);
- output_visitor_test_add("/string-visitor/output/intList",
+ output_visitor_test_add("/string-visitor/output/intList-human",
&out_visitor_data, test_visitor_out_intList, true);
g_test_run();
diff --git a/trace-events b/trace-events
index 2da6832..a0ddc6b 100644
--- a/trace-events
+++ b/trace-events
@@ -603,9 +603,6 @@ scsi_request_sense(int target, int lun, int tag) "target %d lun %d tag %d"
vm_state_notify(int running, int reason) "running %d reason %d"
load_file(const char *name, const char *path) "name %s location %s"
runstate_set(int new_state) "new state %d"
-g_malloc(size_t size, void *ptr) "size %zu ptr %p"
-g_realloc(void *ptr, size_t size, void *newptr) "ptr %p size %zu newptr %p"
-g_free(void *ptr) "ptr %p"
system_wakeup_request(int reason) "reason=%d"
qemu_system_shutdown_request(void) ""
qemu_system_powerdown_request(void) ""
@@ -1633,7 +1630,9 @@ vfio_platform_intp_interrupt(int pin, int fd) "Inject IRQ #%d (fd = %d)"
vfio_platform_intp_inject_pending_lockheld(int pin, int fd) "Inject pending IRQ #%d (fd = %d)"
vfio_platform_populate_interrupts(int pin, int count, int flags) "- IRQ index %d: count %d, flags=0x%x"
vfio_intp_interrupt_set_pending(int index) "irq %d is set PENDING"
-vfio_platform_start_irqfd_injection(int index, int fd, int resamplefd) "IRQ index=%d, fd = %d, resamplefd = %d"
+vfio_platform_start_level_irqfd_injection(int index, int fd, int resamplefd) "IRQ index=%d, fd = %d, resamplefd = %d"
+vfio_platform_start_edge_irqfd_injection(int index, int fd) "IRQ index=%d, fd = %d"
+
#hw/acpi/memory_hotplug.c
mhp_acpi_invalid_slot_selected(uint32_t slot) "0x%"PRIx32
diff --git a/translate-all.c b/translate-all.c
index 4a9ee33..333eba4 100644
--- a/translate-all.c
+++ b/translate-all.c
@@ -168,127 +168,137 @@ void cpu_gen_init(void)
tcg_context_init(&tcg_ctx);
}
-/* return non zero if the very first instruction is invalid so that
- * the virtual CPU can trigger an exception.
- *
- * '*gen_code_size_ptr' contains the size of the generated code (host
- * code).
- *
- * Called with mmap_lock held for user-mode emulation.
- */
-int cpu_gen_code(CPUArchState *env, TranslationBlock *tb, int *gen_code_size_ptr)
+/* Encode VAL as a signed leb128 sequence at P.
+ Return P incremented past the encoded value. */
+static uint8_t *encode_sleb128(uint8_t *p, target_long val)
{
- TCGContext *s = &tcg_ctx;
- tcg_insn_unit *gen_code_buf;
- int gen_code_size;
-#ifdef CONFIG_PROFILER
- int64_t ti;
-#endif
+ int more, byte;
+
+ do {
+ byte = val & 0x7f;
+ val >>= 7;
+ more = !((val == 0 && (byte & 0x40) == 0)
+ || (val == -1 && (byte & 0x40) != 0));
+ if (more) {
+ byte |= 0x80;
+ }
+ *p++ = byte;
+ } while (more);
-#ifdef CONFIG_PROFILER
- s->tb_count1++; /* includes aborted translations because of
- exceptions */
- ti = profile_getclock();
-#endif
- tcg_func_start(s);
+ return p;
+}
- gen_intermediate_code(env, tb);
+/* Decode a signed leb128 sequence at *PP; increment *PP past the
+ decoded value. Return the decoded value. */
+static target_long decode_sleb128(uint8_t **pp)
+{
+ uint8_t *p = *pp;
+ target_long val = 0;
+ int byte, shift = 0;
- trace_translate_block(tb, tb->pc, tb->tc_ptr);
+ do {
+ byte = *p++;
+ val |= (target_ulong)(byte & 0x7f) << shift;
+ shift += 7;
+ } while (byte & 0x80);
+ if (shift < TARGET_LONG_BITS && (byte & 0x40)) {
+ val |= -(target_ulong)1 << shift;
+ }
- /* generate machine code */
- gen_code_buf = tb->tc_ptr;
- tb->tb_next_offset[0] = 0xffff;
- tb->tb_next_offset[1] = 0xffff;
- s->tb_next_offset = tb->tb_next_offset;
-#ifdef USE_DIRECT_JUMP
- s->tb_jmp_offset = tb->tb_jmp_offset;
- s->tb_next = NULL;
-#else
- s->tb_jmp_offset = NULL;
- s->tb_next = tb->tb_next;
-#endif
+ *pp = p;
+ return val;
+}
-#ifdef CONFIG_PROFILER
- s->tb_count++;
- s->interm_time += profile_getclock() - ti;
- s->code_time -= profile_getclock();
-#endif
- gen_code_size = tcg_gen_code(s, gen_code_buf);
- *gen_code_size_ptr = gen_code_size;
-#ifdef CONFIG_PROFILER
- s->code_time += profile_getclock();
- s->code_in_len += tb->size;
- s->code_out_len += gen_code_size;
-#endif
+/* Encode the data collected about the instructions while compiling TB.
+ Place the data at BLOCK, and return the number of bytes consumed.
-#ifdef DEBUG_DISAS
- if (qemu_loglevel_mask(CPU_LOG_TB_OUT_ASM)) {
- qemu_log("OUT: [size=%d]\n", gen_code_size);
- log_disas(tb->tc_ptr, gen_code_size);
- qemu_log("\n");
- qemu_log_flush();
+ The logical table consisits of TARGET_INSN_START_WORDS target_ulong's,
+ which come from the target's insn_start data, followed by a uintptr_t
+ which comes from the host pc of the end of the code implementing the insn.
+
+ Each line of the table is encoded as sleb128 deltas from the previous
+ line. The seed for the first line is { tb->pc, 0..., tb->tc_ptr }.
+ That is, the first column is seeded with the guest pc, the last column
+ with the host pc, and the middle columns with zeros. */
+
+static int encode_search(TranslationBlock *tb, uint8_t *block)
+{
+ uint8_t *highwater = tcg_ctx.code_gen_highwater;
+ uint8_t *p = block;
+ int i, j, n;
+
+ tb->tc_search = block;
+
+ for (i = 0, n = tb->icount; i < n; ++i) {
+ target_ulong prev;
+
+ for (j = 0; j < TARGET_INSN_START_WORDS; ++j) {
+ if (i == 0) {
+ prev = (j == 0 ? tb->pc : 0);
+ } else {
+ prev = tcg_ctx.gen_insn_data[i - 1][j];
+ }
+ p = encode_sleb128(p, tcg_ctx.gen_insn_data[i][j] - prev);
+ }
+ prev = (i == 0 ? 0 : tcg_ctx.gen_insn_end_off[i - 1]);
+ p = encode_sleb128(p, tcg_ctx.gen_insn_end_off[i] - prev);
+
+ /* Test for (pending) buffer overflow. The assumption is that any
+ one row beginning below the high water mark cannot overrun
+ the buffer completely. Thus we can test for overflow after
+ encoding a row without having to check during encoding. */
+ if (unlikely(p > highwater)) {
+ return -1;
+ }
}
-#endif
- return 0;
+
+ return p - block;
}
-/* The cpu state corresponding to 'searched_pc' is restored.
- */
+/* The cpu state corresponding to 'searched_pc' is restored. */
static int cpu_restore_state_from_tb(CPUState *cpu, TranslationBlock *tb,
uintptr_t searched_pc)
{
+ target_ulong data[TARGET_INSN_START_WORDS] = { tb->pc };
+ uintptr_t host_pc = (uintptr_t)tb->tc_ptr;
CPUArchState *env = cpu->env_ptr;
- TCGContext *s = &tcg_ctx;
- int j;
- uintptr_t tc_ptr;
+ uint8_t *p = tb->tc_search;
+ int i, j, num_insns = tb->icount;
#ifdef CONFIG_PROFILER
- int64_t ti;
+ int64_t ti = profile_getclock();
#endif
-#ifdef CONFIG_PROFILER
- ti = profile_getclock();
-#endif
- tcg_func_start(s);
+ if (searched_pc < host_pc) {
+ return -1;
+ }
- gen_intermediate_code_pc(env, tb);
+ /* Reconstruct the stored insn data while looking for the point at
+ which the end of the insn exceeds the searched_pc. */
+ for (i = 0; i < num_insns; ++i) {
+ for (j = 0; j < TARGET_INSN_START_WORDS; ++j) {
+ data[j] += decode_sleb128(&p);
+ }
+ host_pc += decode_sleb128(&p);
+ if (host_pc > searched_pc) {
+ goto found;
+ }
+ }
+ return -1;
+ found:
if (tb->cflags & CF_USE_ICOUNT) {
assert(use_icount);
/* Reset the cycle counter to the start of the block. */
- cpu->icount_decr.u16.low += tb->icount;
+ cpu->icount_decr.u16.low += num_insns;
/* Clear the IO flag. */
cpu->can_do_io = 0;
}
-
- /* find opc index corresponding to search_pc */
- tc_ptr = (uintptr_t)tb->tc_ptr;
- if (searched_pc < tc_ptr)
- return -1;
-
- s->tb_next_offset = tb->tb_next_offset;
-#ifdef USE_DIRECT_JUMP
- s->tb_jmp_offset = tb->tb_jmp_offset;
- s->tb_next = NULL;
-#else
- s->tb_jmp_offset = NULL;
- s->tb_next = tb->tb_next;
-#endif
- j = tcg_gen_code_search_pc(s, (tcg_insn_unit *)tc_ptr,
- searched_pc - tc_ptr);
- if (j < 0)
- return -1;
- /* now find start of instruction before */
- while (s->gen_opc_instr_start[j] == 0) {
- j--;
- }
- cpu->icount_decr.u16.low -= s->gen_opc_icount[j];
-
- restore_state_to_opc(env, tb, j);
+ cpu->icount_decr.u16.low -= i;
+ restore_state_to_opc(env, tb, data);
#ifdef CONFIG_PROFILER
- s->restore_time += profile_getclock() - ti;
- s->restore_count++;
+ tcg_ctx.restore_time += profile_getclock() - ti;
+ tcg_ctx.restore_count++;
#endif
return 0;
}
@@ -311,31 +321,6 @@ bool cpu_restore_state(CPUState *cpu, uintptr_t retaddr)
return false;
}
-#ifdef _WIN32
-static __attribute__((unused)) void map_exec(void *addr, long size)
-{
- DWORD old_protect;
- VirtualProtect(addr, size,
- PAGE_EXECUTE_READWRITE, &old_protect);
-}
-#else
-static __attribute__((unused)) void map_exec(void *addr, long size)
-{
- unsigned long start, end, page_size;
-
- page_size = getpagesize();
- start = (unsigned long)addr;
- start &= ~(page_size - 1);
-
- end = (unsigned long)addr + size;
- end += page_size - 1;
- end &= ~(page_size - 1);
-
- mprotect((void *)start, end - start,
- PROT_READ | PROT_WRITE | PROT_EXEC);
-}
-#endif
-
void page_size_init(void)
{
/* NOTE: we can always suppose that qemu_host_page_size >=
@@ -472,14 +457,6 @@ static inline PageDesc *page_find(tb_page_addr_t index)
#define USE_STATIC_CODE_GEN_BUFFER
#endif
-/* ??? Should configure for this, not list operating systems here. */
-#if (defined(__linux__) \
- || defined(__FreeBSD__) || defined(__FreeBSD_kernel__) \
- || defined(__DragonFly__) || defined(__OpenBSD__) \
- || defined(__NetBSD__))
-# define USE_MMAP
-#endif
-
/* Minimum size of the code gen buffer. This number is randomly chosen,
but not so small that we can't have a fair number of TB's live. */
#define MIN_CODE_GEN_BUFFER_SIZE (1024u * 1024)
@@ -567,22 +544,102 @@ static inline void *split_cross_256mb(void *buf1, size_t size1)
static uint8_t static_code_gen_buffer[DEFAULT_CODE_GEN_BUFFER_SIZE]
__attribute__((aligned(CODE_GEN_ALIGN)));
+# ifdef _WIN32
+static inline void do_protect(void *addr, long size, int prot)
+{
+ DWORD old_protect;
+ VirtualProtect(addr, size, prot, &old_protect);
+}
+
+static inline void map_exec(void *addr, long size)
+{
+ do_protect(addr, size, PAGE_EXECUTE_READWRITE);
+}
+
+static inline void map_none(void *addr, long size)
+{
+ do_protect(addr, size, PAGE_NOACCESS);
+}
+# else
+static inline void do_protect(void *addr, long size, int prot)
+{
+ uintptr_t start, end;
+
+ start = (uintptr_t)addr;
+ start &= qemu_real_host_page_mask;
+
+ end = (uintptr_t)addr + size;
+ end = ROUND_UP(end, qemu_real_host_page_size);
+
+ mprotect((void *)start, end - start, prot);
+}
+
+static inline void map_exec(void *addr, long size)
+{
+ do_protect(addr, size, PROT_READ | PROT_WRITE | PROT_EXEC);
+}
+
+static inline void map_none(void *addr, long size)
+{
+ do_protect(addr, size, PROT_NONE);
+}
+# endif /* WIN32 */
+
static inline void *alloc_code_gen_buffer(void)
{
void *buf = static_code_gen_buffer;
+ size_t full_size, size;
+
+ /* The size of the buffer, rounded down to end on a page boundary. */
+ full_size = (((uintptr_t)buf + sizeof(static_code_gen_buffer))
+ & qemu_real_host_page_mask) - (uintptr_t)buf;
+
+ /* Reserve a guard page. */
+ size = full_size - qemu_real_host_page_size;
+
+ /* Honor a command-line option limiting the size of the buffer. */
+ if (size > tcg_ctx.code_gen_buffer_size) {
+ size = (((uintptr_t)buf + tcg_ctx.code_gen_buffer_size)
+ & qemu_real_host_page_mask) - (uintptr_t)buf;
+ }
+ tcg_ctx.code_gen_buffer_size = size;
+
#ifdef __mips__
- if (cross_256mb(buf, tcg_ctx.code_gen_buffer_size)) {
- buf = split_cross_256mb(buf, tcg_ctx.code_gen_buffer_size);
+ if (cross_256mb(buf, size)) {
+ buf = split_cross_256mb(buf, size);
+ size = tcg_ctx.code_gen_buffer_size;
}
#endif
- map_exec(buf, tcg_ctx.code_gen_buffer_size);
+
+ map_exec(buf, size);
+ map_none(buf + size, qemu_real_host_page_size);
+ qemu_madvise(buf, size, QEMU_MADV_HUGEPAGE);
+
return buf;
}
-#elif defined(USE_MMAP)
+#elif defined(_WIN32)
+static inline void *alloc_code_gen_buffer(void)
+{
+ size_t size = tcg_ctx.code_gen_buffer_size;
+ void *buf1, *buf2;
+
+ /* Perform the allocation in two steps, so that the guard page
+ is reserved but uncommitted. */
+ buf1 = VirtualAlloc(NULL, size + qemu_real_host_page_size,
+ MEM_RESERVE, PAGE_NOACCESS);
+ if (buf1 != NULL) {
+ buf2 = VirtualAlloc(buf1, size, MEM_COMMIT, PAGE_EXECUTE_READWRITE);
+ assert(buf1 == buf2);
+ }
+
+ return buf1;
+}
+#else
static inline void *alloc_code_gen_buffer(void)
{
int flags = MAP_PRIVATE | MAP_ANONYMOUS;
uintptr_t start = 0;
+ size_t size = tcg_ctx.code_gen_buffer_size;
void *buf;
/* Constrain the position of the buffer based on the host cpu.
@@ -598,86 +655,70 @@ static inline void *alloc_code_gen_buffer(void)
Leave the choice of exact location with the kernel. */
flags |= MAP_32BIT;
/* Cannot expect to map more than 800MB in low memory. */
- if (tcg_ctx.code_gen_buffer_size > 800u * 1024 * 1024) {
- tcg_ctx.code_gen_buffer_size = 800u * 1024 * 1024;
+ if (size > 800u * 1024 * 1024) {
+ tcg_ctx.code_gen_buffer_size = size = 800u * 1024 * 1024;
}
# elif defined(__sparc__)
start = 0x40000000ul;
# elif defined(__s390x__)
start = 0x90000000ul;
# elif defined(__mips__)
- /* ??? We ought to more explicitly manage layout for softmmu too. */
-# ifdef CONFIG_USER_ONLY
- start = 0x68000000ul;
-# elif _MIPS_SIM == _ABI64
+# if _MIPS_SIM == _ABI64
start = 0x128000000ul;
# else
start = 0x08000000ul;
# endif
# endif
- buf = mmap((void *)start, tcg_ctx.code_gen_buffer_size,
- PROT_WRITE | PROT_READ | PROT_EXEC, flags, -1, 0);
+ buf = mmap((void *)start, size + qemu_real_host_page_size,
+ PROT_NONE, flags, -1, 0);
if (buf == MAP_FAILED) {
return NULL;
}
#ifdef __mips__
- if (cross_256mb(buf, tcg_ctx.code_gen_buffer_size)) {
+ if (cross_256mb(buf, size)) {
/* Try again, with the original still mapped, to avoid re-acquiring
that 256mb crossing. This time don't specify an address. */
- size_t size2, size1 = tcg_ctx.code_gen_buffer_size;
- void *buf2 = mmap(NULL, size1, PROT_WRITE | PROT_READ | PROT_EXEC,
- flags, -1, 0);
- if (buf2 != MAP_FAILED) {
- if (!cross_256mb(buf2, size1)) {
+ size_t size2;
+ void *buf2 = mmap(NULL, size + qemu_real_host_page_size,
+ PROT_NONE, flags, -1, 0);
+ switch (buf2 != MAP_FAILED) {
+ case 1:
+ if (!cross_256mb(buf2, size)) {
/* Success! Use the new buffer. */
- munmap(buf, size1);
- return buf2;
+ munmap(buf, size);
+ break;
}
/* Failure. Work with what we had. */
- munmap(buf2, size1);
+ munmap(buf2, size);
+ /* fallthru */
+ default:
+ /* Split the original buffer. Free the smaller half. */
+ buf2 = split_cross_256mb(buf, size);
+ size2 = tcg_ctx.code_gen_buffer_size;
+ if (buf == buf2) {
+ munmap(buf + size2 + qemu_real_host_page_size, size - size2);
+ } else {
+ munmap(buf, size - size2);
+ }
+ size = size2;
+ break;
}
-
- /* Split the original buffer. Free the smaller half. */
- buf2 = split_cross_256mb(buf, size1);
- size2 = tcg_ctx.code_gen_buffer_size;
- munmap(buf + (buf == buf2 ? size2 : 0), size1 - size2);
- return buf2;
+ buf = buf2;
}
#endif
- return buf;
-}
-#else
-static inline void *alloc_code_gen_buffer(void)
-{
- void *buf = g_try_malloc(tcg_ctx.code_gen_buffer_size);
+ /* Make the final buffer accessible. The guard page at the end
+ will remain inaccessible with PROT_NONE. */
+ mprotect(buf, size, PROT_WRITE | PROT_READ | PROT_EXEC);
- if (buf == NULL) {
- return NULL;
- }
+ /* Request large pages for the buffer. */
+ qemu_madvise(buf, size, QEMU_MADV_HUGEPAGE);
-#ifdef __mips__
- if (cross_256mb(buf, tcg_ctx.code_gen_buffer_size)) {
- void *buf2 = g_malloc(tcg_ctx.code_gen_buffer_size);
- if (buf2 != NULL && !cross_256mb(buf2, size1)) {
- /* Success! Use the new buffer. */
- free(buf);
- buf = buf2;
- } else {
- /* Failure. Work with what we had. Since this is malloc
- and not mmap, we can't free the other half. */
- free(buf2);
- buf = split_cross_256mb(buf, tcg_ctx.code_gen_buffer_size);
- }
- }
-#endif
-
- map_exec(buf, tcg_ctx.code_gen_buffer_size);
return buf;
}
-#endif /* USE_STATIC_CODE_GEN_BUFFER, USE_MMAP */
+#endif /* USE_STATIC_CODE_GEN_BUFFER, WIN32, POSIX */
static inline void code_gen_alloc(size_t tb_size)
{
@@ -688,24 +729,13 @@ static inline void code_gen_alloc(size_t tb_size)
exit(1);
}
- qemu_madvise(tcg_ctx.code_gen_buffer, tcg_ctx.code_gen_buffer_size,
- QEMU_MADV_HUGEPAGE);
-
- /* Steal room for the prologue at the end of the buffer. This ensures
- (via the MAX_CODE_GEN_BUFFER_SIZE limits above) that direct branches
- from TB's to the prologue are going to be in range. It also means
- that we don't need to mark (additional) portions of the data segment
- as executable. */
- tcg_ctx.code_gen_prologue = tcg_ctx.code_gen_buffer +
- tcg_ctx.code_gen_buffer_size - 1024;
- tcg_ctx.code_gen_buffer_size -= 1024;
-
- tcg_ctx.code_gen_buffer_max_size = tcg_ctx.code_gen_buffer_size -
- (TCG_MAX_OP_SIZE * OPC_BUF_SIZE);
- tcg_ctx.code_gen_max_blocks = tcg_ctx.code_gen_buffer_size /
- CODE_GEN_AVG_BLOCK_SIZE;
- tcg_ctx.tb_ctx.tbs =
- g_malloc(tcg_ctx.code_gen_max_blocks * sizeof(TranslationBlock));
+ /* Estimate a good size for the number of TBs we can support. We
+ still haven't deducted the prologue from the buffer size here,
+ but that's minimal and won't affect the estimate much. */
+ tcg_ctx.code_gen_max_blocks
+ = tcg_ctx.code_gen_buffer_size / CODE_GEN_AVG_BLOCK_SIZE;
+ tcg_ctx.tb_ctx.tbs = g_new(TranslationBlock, tcg_ctx.code_gen_max_blocks);
+
qemu_mutex_init(&tcg_ctx.tb_ctx.tb_lock);
}
@@ -715,10 +745,8 @@ static inline void code_gen_alloc(size_t tb_size)
void tcg_exec_init(unsigned long tb_size)
{
cpu_gen_init();
- code_gen_alloc(tb_size);
- tcg_ctx.code_gen_ptr = tcg_ctx.code_gen_buffer;
- tcg_register_jit(tcg_ctx.code_gen_buffer, tcg_ctx.code_gen_buffer_size);
page_init();
+ code_gen_alloc(tb_size);
#if defined(CONFIG_SOFTMMU)
/* There's no guest base to take into account, so go ahead and
initialize the prologue now. */
@@ -737,9 +765,7 @@ static TranslationBlock *tb_alloc(target_ulong pc)
{
TranslationBlock *tb;
- if (tcg_ctx.tb_ctx.nb_tbs >= tcg_ctx.code_gen_max_blocks ||
- (tcg_ctx.code_gen_ptr - tcg_ctx.code_gen_buffer) >=
- tcg_ctx.code_gen_buffer_max_size) {
+ if (tcg_ctx.tb_ctx.nb_tbs >= tcg_ctx.code_gen_max_blocks) {
return NULL;
}
tb = &tcg_ctx.tb_ctx.tbs[tcg_ctx.tb_ctx.nb_tbs++];
@@ -1034,28 +1060,98 @@ TranslationBlock *tb_gen_code(CPUState *cpu,
TranslationBlock *tb;
tb_page_addr_t phys_pc, phys_page2;
target_ulong virt_page2;
- int code_gen_size;
+ tcg_insn_unit *gen_code_buf;
+ int gen_code_size, search_size;
+#ifdef CONFIG_PROFILER
+ int64_t ti;
+#endif
phys_pc = get_page_addr_code(env, pc);
if (use_icount) {
cflags |= CF_USE_ICOUNT;
}
+
tb = tb_alloc(pc);
- if (!tb) {
+ if (unlikely(!tb)) {
+ buffer_overflow:
/* flush must be done */
tb_flush(cpu);
/* cannot fail at this point */
tb = tb_alloc(pc);
+ assert(tb != NULL);
/* Don't forget to invalidate previous TB info. */
tcg_ctx.tb_ctx.tb_invalidated_flag = 1;
}
- tb->tc_ptr = tcg_ctx.code_gen_ptr;
+
+ gen_code_buf = tcg_ctx.code_gen_ptr;
+ tb->tc_ptr = gen_code_buf;
tb->cs_base = cs_base;
tb->flags = flags;
tb->cflags = cflags;
- cpu_gen_code(env, tb, &code_gen_size);
- tcg_ctx.code_gen_ptr = (void *)(((uintptr_t)tcg_ctx.code_gen_ptr +
- code_gen_size + CODE_GEN_ALIGN - 1) & ~(CODE_GEN_ALIGN - 1));
+
+#ifdef CONFIG_PROFILER
+ tcg_ctx.tb_count1++; /* includes aborted translations because of
+ exceptions */
+ ti = profile_getclock();
+#endif
+
+ tcg_func_start(&tcg_ctx);
+
+ gen_intermediate_code(env, tb);
+
+ trace_translate_block(tb, tb->pc, tb->tc_ptr);
+
+ /* generate machine code */
+ tb->tb_next_offset[0] = 0xffff;
+ tb->tb_next_offset[1] = 0xffff;
+ tcg_ctx.tb_next_offset = tb->tb_next_offset;
+#ifdef USE_DIRECT_JUMP
+ tcg_ctx.tb_jmp_offset = tb->tb_jmp_offset;
+ tcg_ctx.tb_next = NULL;
+#else
+ tcg_ctx.tb_jmp_offset = NULL;
+ tcg_ctx.tb_next = tb->tb_next;
+#endif
+
+#ifdef CONFIG_PROFILER
+ tcg_ctx.tb_count++;
+ tcg_ctx.interm_time += profile_getclock() - ti;
+ tcg_ctx.code_time -= profile_getclock();
+#endif
+
+ /* ??? Overflow could be handled better here. In particular, we
+ don't need to re-do gen_intermediate_code, nor should we re-do
+ the tcg optimization currently hidden inside tcg_gen_code. All
+ that should be required is to flush the TBs, allocate a new TB,
+ re-initialize it per above, and re-do the actual code generation. */
+ gen_code_size = tcg_gen_code(&tcg_ctx, gen_code_buf);
+ if (unlikely(gen_code_size < 0)) {
+ goto buffer_overflow;
+ }
+ search_size = encode_search(tb, (void *)gen_code_buf + gen_code_size);
+ if (unlikely(search_size < 0)) {
+ goto buffer_overflow;
+ }
+
+#ifdef CONFIG_PROFILER
+ tcg_ctx.code_time += profile_getclock();
+ tcg_ctx.code_in_len += tb->size;
+ tcg_ctx.code_out_len += gen_code_size;
+ tcg_ctx.search_out_len += search_size;
+#endif
+
+#ifdef DEBUG_DISAS
+ if (qemu_loglevel_mask(CPU_LOG_TB_OUT_ASM)) {
+ qemu_log("OUT: [size=%d]\n", gen_code_size);
+ log_disas(tb->tc_ptr, gen_code_size);
+ qemu_log("\n");
+ qemu_log_flush();
+ }
+#endif
+
+ tcg_ctx.code_gen_ptr = (void *)
+ ROUND_UP((uintptr_t)gen_code_buf + gen_code_size + search_size,
+ CODE_GEN_ALIGN);
/* check next page if needed */
virt_page2 = (pc + tb->size - 1) & TARGET_PAGE_MASK;
@@ -1606,7 +1702,7 @@ void dump_exec_info(FILE *f, fprintf_function cpu_fprintf)
cpu_fprintf(f, "Translation buffer state:\n");
cpu_fprintf(f, "gen code size %td/%zd\n",
tcg_ctx.code_gen_ptr - tcg_ctx.code_gen_buffer,
- tcg_ctx.code_gen_buffer_max_size);
+ tcg_ctx.code_gen_highwater - tcg_ctx.code_gen_buffer);
cpu_fprintf(f, "TB count %d/%d\n",
tcg_ctx.tb_ctx.nb_tbs, tcg_ctx.code_gen_max_blocks);
cpu_fprintf(f, "TB avg target size %d max=%d bytes\n",
diff --git a/vl.c b/vl.c
index f2bd8d2..ea9e0e6 100644
--- a/vl.c
+++ b/vl.c
@@ -2703,26 +2703,6 @@ static const QEMUOption *lookup_opt(int argc, char **argv,
return popt;
}
-static gpointer malloc_and_trace(gsize n_bytes)
-{
- void *ptr = malloc(n_bytes);
- trace_g_malloc(n_bytes, ptr);
- return ptr;
-}
-
-static gpointer realloc_and_trace(gpointer mem, gsize n_bytes)
-{
- void *ptr = realloc(mem, n_bytes);
- trace_g_realloc(mem, n_bytes, ptr);
- return ptr;
-}
-
-static void free_and_trace(gpointer mem)
-{
- trace_g_free(mem);
- free(mem);
-}
-
static int machine_set_property(void *opaque,
const char *name, const char *value,
Error **errp)
@@ -2950,11 +2930,6 @@ int main(int argc, char **argv, char **envp)
bool userconfig = true;
const char *log_mask = NULL;
const char *log_file = NULL;
- GMemVTable mem_trace = {
- .malloc = malloc_and_trace,
- .realloc = realloc_and_trace,
- .free = free_and_trace,
- };
const char *trace_events = NULL;
const char *trace_file = NULL;
ram_addr_t maxram_size;
@@ -2970,8 +2945,6 @@ int main(int argc, char **argv, char **envp)
error_set_progname(argv[0]);
qemu_init_exec_dir(argv[0]);
- g_mem_set_vtable(&mem_trace);
-
module_call_init(MODULE_INIT_QOM);
qemu_add_opts(&qemu_drive_opts);
OpenPOWER on IntegriCloud