summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--bootdevice.c73
-rw-r--r--cpus.c3
-rw-r--r--exec.c4
-rw-r--r--hw/core/qdev-properties-system.c82
-rw-r--r--hw/i386/pc.c22
-rw-r--r--hw/net/e1000.c21
-rw-r--r--hw/ppc/mac_newworld.c4
-rw-r--r--hw/ppc/mac_oldworld.c5
-rw-r--r--hw/sparc/sun4m.c4
-rw-r--r--hw/sparc64/sun4u.c4
-rw-r--r--include/hw/hw.h6
-rw-r--r--include/sysemu/sysemu.h8
-rw-r--r--include/ui/sdl2.h32
-rw-r--r--monitor.c14
-rw-r--r--net/l2tpv3.c9
-rw-r--r--net/queue.c2
-rw-r--r--net/slirp.c2
-rw-r--r--net/tap.c12
-rw-r--r--pc-bios/efi-e1000.rombin194560 -> 197120 bytes
-rw-r--r--pc-bios/efi-eepro100.rombin196096 -> 197632 bytes
-rw-r--r--pc-bios/efi-ne2k_pci.rombin194560 -> 195584 bytes
-rw-r--r--pc-bios/efi-pcnet.rombin194560 -> 195584 bytes
-rw-r--r--pc-bios/efi-rtl8139.rombin198144 -> 200192 bytes
-rw-r--r--pc-bios/efi-virtio.rombin192000 -> 194048 bytes
-rw-r--r--qom/cpu.c1
m---------roms/ipxe0
-rw-r--r--target-tricore/helper.h59
-rw-r--r--target-tricore/op_helper.c1086
-rw-r--r--target-tricore/translate.c1034
-rw-r--r--target-tricore/tricore-opcodes.h19
-rw-r--r--ui/Makefile.objs7
-rw-r--r--ui/sdl.c3
-rw-r--r--ui/sdl2-2d.c122
-rw-r--r--ui/sdl2-input.c106
-rw-r--r--ui/sdl2.c343
-rw-r--r--vl.c75
36 files changed, 2665 insertions, 497 deletions
diff --git a/bootdevice.c b/bootdevice.c
index b29970c7a3..5914417027 100644
--- a/bootdevice.c
+++ b/bootdevice.c
@@ -25,6 +25,7 @@
#include "sysemu/sysemu.h"
#include "qapi/visitor.h"
#include "qemu/error-report.h"
+#include "hw/hw.h"
typedef struct FWBootEntry FWBootEntry;
@@ -37,6 +38,78 @@ struct FWBootEntry {
static QTAILQ_HEAD(, FWBootEntry) fw_boot_order =
QTAILQ_HEAD_INITIALIZER(fw_boot_order);
+static QEMUBootSetHandler *boot_set_handler;
+static void *boot_set_opaque;
+
+void qemu_register_boot_set(QEMUBootSetHandler *func, void *opaque)
+{
+ boot_set_handler = func;
+ boot_set_opaque = opaque;
+}
+
+void qemu_boot_set(const char *boot_order, Error **errp)
+{
+ Error *local_err = NULL;
+
+ if (!boot_set_handler) {
+ error_setg(errp, "no function defined to set boot device list for"
+ " this architecture");
+ return;
+ }
+
+ validate_bootdevices(boot_order, &local_err);
+ if (local_err) {
+ error_propagate(errp, local_err);
+ return;
+ }
+
+ boot_set_handler(boot_set_opaque, boot_order, errp);
+}
+
+void validate_bootdevices(const char *devices, Error **errp)
+{
+ /* We just do some generic consistency checks */
+ const char *p;
+ int bitmap = 0;
+
+ for (p = devices; *p != '\0'; p++) {
+ /* Allowed boot devices are:
+ * a-b: floppy disk drives
+ * c-f: IDE disk drives
+ * g-m: machine implementation dependent drives
+ * n-p: network devices
+ * It's up to each machine implementation to check if the given boot
+ * devices match the actual hardware implementation and firmware
+ * features.
+ */
+ if (*p < 'a' || *p > 'p') {
+ error_setg(errp, "Invalid boot device '%c'", *p);
+ return;
+ }
+ if (bitmap & (1 << (*p - 'a'))) {
+ error_setg(errp, "Boot device '%c' was given twice", *p);
+ return;
+ }
+ bitmap |= 1 << (*p - 'a');
+ }
+}
+
+void restore_boot_order(void *opaque)
+{
+ char *normal_boot_order = opaque;
+ static int first = 1;
+
+ /* Restore boot order and remove ourselves after the first boot */
+ if (first) {
+ first = 0;
+ return;
+ }
+
+ qemu_boot_set(normal_boot_order, NULL);
+
+ qemu_unregister_reset(restore_boot_order, normal_boot_order);
+ g_free(normal_boot_order);
+}
void check_boot_index(int32_t bootindex, Error **errp)
{
diff --git a/cpus.c b/cpus.c
index 1b5168a1db..2edb5cd807 100644
--- a/cpus.c
+++ b/cpus.c
@@ -940,7 +940,6 @@ static void *qemu_kvm_cpu_thread_fn(void *arg)
qemu_mutex_lock(&qemu_global_mutex);
qemu_thread_get_self(cpu->thread);
cpu->thread_id = qemu_get_thread_id();
- cpu->exception_index = -1;
cpu->can_do_io = 1;
current_cpu = cpu;
@@ -982,7 +981,6 @@ static void *qemu_dummy_cpu_thread_fn(void *arg)
qemu_mutex_lock_iothread();
qemu_thread_get_self(cpu->thread);
cpu->thread_id = qemu_get_thread_id();
- cpu->exception_index = -1;
cpu->can_do_io = 1;
sigemptyset(&waitset);
@@ -1026,7 +1024,6 @@ static void *qemu_tcg_cpu_thread_fn(void *arg)
CPU_FOREACH(cpu) {
cpu->thread_id = qemu_get_thread_id();
cpu->created = true;
- cpu->exception_index = -1;
cpu->can_do_io = 1;
}
qemu_cond_signal(&qemu_cpu_cond);
diff --git a/exec.c b/exec.c
index 963481a181..c2ed10a2d6 100644
--- a/exec.c
+++ b/exec.c
@@ -434,7 +434,7 @@ static int cpu_common_pre_load(void *opaque)
{
CPUState *cpu = opaque;
- cpu->exception_index = 0;
+ cpu->exception_index = -1;
return 0;
}
@@ -443,7 +443,7 @@ static bool cpu_common_exception_index_needed(void *opaque)
{
CPUState *cpu = opaque;
- return cpu->exception_index != 0;
+ return tcg_enabled() && cpu->exception_index != -1;
}
static const VMStateDescription vmstate_cpu_common_exception_index = {
diff --git a/hw/core/qdev-properties-system.c b/hw/core/qdev-properties-system.c
index 65901ef10e..a2e44bd4e8 100644
--- a/hw/core/qdev-properties-system.c
+++ b/hw/core/qdev-properties-system.c
@@ -177,42 +177,69 @@ PropertyInfo qdev_prop_chr = {
};
/* --- netdev device --- */
+static void get_netdev(Object *obj, Visitor *v, void *opaque,
+ const char *name, Error **errp)
+{
+ DeviceState *dev = DEVICE(obj);
+ Property *prop = opaque;
+ NICPeers *peers_ptr = qdev_get_prop_ptr(dev, prop);
+ char *p = g_strdup(peers_ptr->ncs[0] ? peers_ptr->ncs[0]->name : "");
-static int parse_netdev(DeviceState *dev, const char *str, void **ptr)
+ visit_type_str(v, &p, name, errp);
+ g_free(p);
+}
+
+static void set_netdev(Object *obj, Visitor *v, void *opaque,
+ const char *name, Error **errp)
{
- NICPeers *peers_ptr = (NICPeers *)ptr;
+ DeviceState *dev = DEVICE(obj);
+ Property *prop = opaque;
+ NICPeers *peers_ptr = qdev_get_prop_ptr(dev, prop);
NetClientState **ncs = peers_ptr->ncs;
NetClientState *peers[MAX_QUEUE_NUM];
- int queues, i = 0;
- int ret;
+ Error *local_err = NULL;
+ int queues, err = 0, i = 0;
+ char *str;
+
+ if (dev->realized) {
+ qdev_prop_set_after_realize(dev, name, errp);
+ return;
+ }
+
+ visit_type_str(v, &str, name, &local_err);
+ if (local_err) {
+ error_propagate(errp, local_err);
+ return;
+ }
queues = qemu_find_net_clients_except(str, peers,
NET_CLIENT_OPTIONS_KIND_NIC,
MAX_QUEUE_NUM);
if (queues == 0) {
- ret = -ENOENT;
- goto err;
+ err = -ENOENT;
+ goto out;
}
if (queues > MAX_QUEUE_NUM) {
- ret = -E2BIG;
- goto err;
+ error_setg(errp, "queues of backend '%s'(%d) exceeds QEMU limitation(%d)",
+ str, queues, MAX_QUEUE_NUM);
+ goto out;
}
for (i = 0; i < queues; i++) {
if (peers[i] == NULL) {
- ret = -ENOENT;
- goto err;
+ err = -ENOENT;
+ goto out;
}
if (peers[i]->peer) {
- ret = -EEXIST;
- goto err;
+ err = -EEXIST;
+ goto out;
}
if (ncs[i]) {
- ret = -EINVAL;
- goto err;
+ err = -EINVAL;
+ goto out;
}
ncs[i] = peers[i];
@@ -221,30 +248,9 @@ static int parse_netdev(DeviceState *dev, const char *str, void **ptr)
peers_ptr->queues = queues;
- return 0;
-
-err:
- return ret;
-}
-
-static char *print_netdev(void *ptr)
-{
- NetClientState *netdev = ptr;
- const char *val = netdev->name ? netdev->name : "";
-
- return g_strdup(val);
-}
-
-static void get_netdev(Object *obj, Visitor *v, void *opaque,
- const char *name, Error **errp)
-{
- get_pointer(obj, v, opaque, print_netdev, name, errp);
-}
-
-static void set_netdev(Object *obj, Visitor *v, void *opaque,
- const char *name, Error **errp)
-{
- set_pointer(obj, v, opaque, parse_netdev, name, errp);
+out:
+ error_set_from_qdev_prop_error(errp, err, dev, prop, str);
+ g_free(str);
}
PropertyInfo qdev_prop_netdev = {
diff --git a/hw/i386/pc.c b/hw/i386/pc.c
index c0e55a6446..1ec7290dca 100644
--- a/hw/i386/pc.c
+++ b/hw/i386/pc.c
@@ -282,7 +282,7 @@ static int boot_device2nibble(char boot_device)
return 0;
}
-static int set_boot_dev(ISADevice *s, const char *boot_device)
+static void set_boot_dev(ISADevice *s, const char *boot_device, Error **errp)
{
#define PC_MAX_BOOT_DEVICES 3
int nbds, bds[3] = { 0, };
@@ -290,25 +290,24 @@ static int set_boot_dev(ISADevice *s, const char *boot_device)
nbds = strlen(boot_device);
if (nbds > PC_MAX_BOOT_DEVICES) {
- error_report("Too many boot devices for PC");
- return(1);
+ error_setg(errp, "Too many boot devices for PC");
+ return;
}
for (i = 0; i < nbds; i++) {
bds[i] = boot_device2nibble(boot_device[i]);
if (bds[i] == 0) {
- error_report("Invalid boot device for PC: '%c'",
- boot_device[i]);
- return(1);
+ error_setg(errp, "Invalid boot device for PC: '%c'",
+ boot_device[i]);
+ return;
}
}
rtc_set_memory(s, 0x3d, (bds[1] << 4) | bds[0]);
rtc_set_memory(s, 0x38, (bds[2] << 4) | (fd_bootchk ? 0x0 : 0x1));
- return(0);
}
-static int pc_boot_set(void *opaque, const char *boot_device)
+static void pc_boot_set(void *opaque, const char *boot_device, Error **errp)
{
- return set_boot_dev(opaque, boot_device);
+ set_boot_dev(opaque, boot_device, errp);
}
typedef struct pc_cmos_init_late_arg {
@@ -365,6 +364,7 @@ void pc_cmos_init(ram_addr_t ram_size, ram_addr_t above_4g_mem_size,
FDriveType fd_type[2] = { FDRIVE_DRV_NONE, FDRIVE_DRV_NONE };
static pc_cmos_init_late_arg arg;
PCMachineState *pc_machine = PC_MACHINE(machine);
+ Error *local_err = NULL;
/* various important CMOS locations needed by PC/Bochs bios */
@@ -412,7 +412,9 @@ void pc_cmos_init(ram_addr_t ram_size, ram_addr_t above_4g_mem_size,
object_property_set_link(OBJECT(machine), OBJECT(s),
"rtc_state", &error_abort);
- if (set_boot_dev(s, boot_device)) {
+ set_boot_dev(s, boot_device, &local_err);
+ if (local_err) {
+ error_report("%s", error_get_pretty(local_err));
exit(1);
}
diff --git a/hw/net/e1000.c b/hw/net/e1000.c
index e33a4da9fa..89c5788b1c 100644
--- a/hw/net/e1000.c
+++ b/hw/net/e1000.c
@@ -33,6 +33,7 @@
#include "sysemu/sysemu.h"
#include "sysemu/dma.h"
#include "qemu/iov.h"
+#include "qemu/range.h"
#include "e1000_regs.h"
@@ -923,7 +924,9 @@ e1000_can_receive(NetClientState *nc)
E1000State *s = qemu_get_nic_opaque(nc);
return (s->mac_reg[STATUS] & E1000_STATUS_LU) &&
- (s->mac_reg[RCTL] & E1000_RCTL_EN) && e1000_has_rxbufs(s, 1);
+ (s->mac_reg[RCTL] & E1000_RCTL_EN) &&
+ (s->parent_obj.config[PCI_COMMAND] & PCI_COMMAND_MASTER) &&
+ e1000_has_rxbufs(s, 1);
}
static uint64_t rx_desc_base(E1000State *s)
@@ -1529,6 +1532,20 @@ static NetClientInfo net_e1000_info = {
.link_status_changed = e1000_set_link_status,
};
+static void e1000_write_config(PCIDevice *pci_dev, uint32_t address,
+ uint32_t val, int len)
+{
+ E1000State *s = E1000(pci_dev);
+
+ pci_default_write_config(pci_dev, address, val, len);
+
+ if (range_covers_byte(address, len, PCI_COMMAND) &&
+ (pci_dev->config[PCI_COMMAND] & PCI_COMMAND_MASTER)) {
+ qemu_flush_queued_packets(qemu_get_queue(s->nic));
+ }
+}
+
+
static int pci_e1000_init(PCIDevice *pci_dev)
{
DeviceState *dev = DEVICE(pci_dev);
@@ -1539,6 +1556,8 @@ static int pci_e1000_init(PCIDevice *pci_dev)
int i;
uint8_t *macaddr;
+ pci_dev->config_write = e1000_write_config;
+
pci_conf = pci_dev->config;
/* TODO: RST# value should be 0, PCI spec 6.2.4 */
diff --git a/hw/ppc/mac_newworld.c b/hw/ppc/mac_newworld.c
index 89aee716d4..ee1ed8a344 100644
--- a/hw/ppc/mac_newworld.c
+++ b/hw/ppc/mac_newworld.c
@@ -116,10 +116,10 @@ static const MemoryRegionOps unin_ops = {
.endianness = DEVICE_NATIVE_ENDIAN,
};
-static int fw_cfg_boot_set(void *opaque, const char *boot_device)
+static void fw_cfg_boot_set(void *opaque, const char *boot_device,
+ Error **errp)
{
fw_cfg_add_i16(opaque, FW_CFG_BOOT_DEVICE, boot_device[0]);
- return 0;
}
static uint64_t translate_kernel_address(void *opaque, uint64_t addr)
diff --git a/hw/ppc/mac_oldworld.c b/hw/ppc/mac_oldworld.c
index 32c21a4286..15109c294a 100644
--- a/hw/ppc/mac_oldworld.c
+++ b/hw/ppc/mac_oldworld.c
@@ -49,13 +49,12 @@
#define CLOCKFREQ 266000000UL
#define BUSFREQ 66000000UL
-static int fw_cfg_boot_set(void *opaque, const char *boot_device)
+static void fw_cfg_boot_set(void *opaque, const char *boot_device,
+ Error **errp)
{
fw_cfg_add_i16(opaque, FW_CFG_BOOT_DEVICE, boot_device[0]);
- return 0;
}
-
static uint64_t translate_kernel_address(void *opaque, uint64_t addr)
{
return (addr & 0x0fffffff) + KERNEL_LOAD_ADDR;
diff --git a/hw/sparc/sun4m.c b/hw/sparc/sun4m.c
index 8273199f11..df259ad605 100644
--- a/hw/sparc/sun4m.c
+++ b/hw/sparc/sun4m.c
@@ -121,10 +121,10 @@ void DMA_register_channel (int nchan,
{
}
-static int fw_cfg_boot_set(void *opaque, const char *boot_device)
+static void fw_cfg_boot_set(void *opaque, const char *boot_device,
+ Error **errp)
{
fw_cfg_add_i16(opaque, FW_CFG_BOOT_DEVICE, boot_device[0]);
- return 0;
}
static void nvram_init(M48t59State *nvram, uint8_t *macaddr,
diff --git a/hw/sparc64/sun4u.c b/hw/sparc64/sun4u.c
index f42112c1b2..acac8f9ed0 100644
--- a/hw/sparc64/sun4u.c
+++ b/hw/sparc64/sun4u.c
@@ -124,10 +124,10 @@ void DMA_register_channel (int nchan,
{
}
-static int fw_cfg_boot_set(void *opaque, const char *boot_device)
+static void fw_cfg_boot_set(void *opaque, const char *boot_device,
+ Error **errp)
{
fw_cfg_add_i16(opaque, FW_CFG_BOOT_DEVICE, boot_device[0]);
- return 0;
}
static int sun4u_NVRAM_set_params(M48t59State *nvram, uint16_t NVRAM_size,
diff --git a/include/hw/hw.h b/include/hw/hw.h
index 33bdb92712..c78adae06a 100644
--- a/include/hw/hw.h
+++ b/include/hw/hw.h
@@ -41,12 +41,6 @@ typedef void QEMUResetHandler(void *opaque);
void qemu_register_reset(QEMUResetHandler *func, void *opaque);
void qemu_unregister_reset(QEMUResetHandler *func, void *opaque);
-/* handler to set the boot_device order for a specific type of QEMUMachine */
-/* return 0 if success */
-typedef int QEMUBootSetHandler(void *opaque, const char *boot_order);
-void qemu_register_boot_set(QEMUBootSetHandler *func, void *opaque);
-int qemu_boot_set(const char *boot_order);
-
#ifdef NEED_CPU_H
#if TARGET_LONG_BITS == 64
#define VMSTATE_UINTTL_V(_f, _s, _v) \
diff --git a/include/sysemu/sysemu.h b/include/sysemu/sysemu.h
index 9fea3bc3af..503e5a48a7 100644
--- a/include/sysemu/sysemu.h
+++ b/include/sysemu/sysemu.h
@@ -216,6 +216,14 @@ void del_boot_device_path(DeviceState *dev, const char *suffix);
void device_add_bootindex_property(Object *obj, int32_t *bootindex,
const char *name, const char *suffix,
DeviceState *dev, Error **errp);
+void restore_boot_order(void *opaque);
+void validate_bootdevices(const char *devices, Error **errp);
+
+/* handler to set the boot_device order for a specific type of QEMUMachine */
+typedef void QEMUBootSetHandler(void *opaque, const char *boot_order,
+ Error **errp);
+void qemu_register_boot_set(QEMUBootSetHandler *func, void *opaque);
+void qemu_boot_set(const char *boot_order, Error **errp);
QemuOpts *qemu_get_machine_opts(void);
diff --git a/include/ui/sdl2.h b/include/ui/sdl2.h
new file mode 100644
index 0000000000..f56c596e31
--- /dev/null
+++ b/include/ui/sdl2.h
@@ -0,0 +1,32 @@
+#ifndef SDL2_H
+#define SDL2_H
+
+struct sdl2_console {
+ DisplayChangeListener dcl;
+ DisplaySurface *surface;
+ SDL_Texture *texture;
+ SDL_Window *real_window;
+ SDL_Renderer *real_renderer;
+ int idx;
+ int last_vm_running; /* per console for caption reasons */
+ int x, y;
+ int hidden;
+};
+
+void sdl2_window_create(struct sdl2_console *scon);
+void sdl2_window_destroy(struct sdl2_console *scon);
+void sdl2_window_resize(struct sdl2_console *scon);
+void sdl2_poll_events(struct sdl2_console *scon);
+
+void sdl2_reset_keys(struct sdl2_console *scon);
+void sdl2_process_key(struct sdl2_console *scon,
+ SDL_KeyboardEvent *ev);
+
+void sdl2_2d_update(DisplayChangeListener *dcl,
+ int x, int y, int w, int h);
+void sdl2_2d_switch(DisplayChangeListener *dcl,
+ DisplaySurface *new_surface);
+void sdl2_2d_refresh(DisplayChangeListener *dcl);
+void sdl2_2d_redraw(struct sdl2_console *scon);
+
+#endif /* SDL2_H */
diff --git a/monitor.c b/monitor.c
index 503cf515ad..1808e41932 100644
--- a/monitor.c
+++ b/monitor.c
@@ -1494,17 +1494,15 @@ static void do_ioport_write(Monitor *mon, const QDict *qdict)
static void do_boot_set(Monitor *mon, const QDict *qdict)
{
- int res;
+ Error *local_err = NULL;
const char *bootdevice = qdict_get_str(qdict, "bootdevice");
- res = qemu_boot_set(bootdevice);
- if (res == 0) {
- monitor_printf(mon, "boot device list now set to %s\n", bootdevice);
- } else if (res > 0) {
- monitor_printf(mon, "setting boot device list failed\n");
+ qemu_boot_set(bootdevice, &local_err);
+ if (local_err) {
+ monitor_printf(mon, "%s\n", error_get_pretty(local_err));
+ error_free(local_err);
} else {
- monitor_printf(mon, "no function defined to set boot device list for "
- "this architecture\n");
+ monitor_printf(mon, "boot device list now set to %s\n", bootdevice);
}
}
diff --git a/net/l2tpv3.c b/net/l2tpv3.c
index 3b805a7a4c..8c598b09bc 100644
--- a/net/l2tpv3.c
+++ b/net/l2tpv3.c
@@ -489,12 +489,12 @@ static struct mmsghdr *build_l2tpv3_vector(NetL2TPV3State *s, int count)
struct iovec *iov;
struct mmsghdr *msgvec, *result;
- msgvec = g_malloc(sizeof(struct mmsghdr) * count);
+ msgvec = g_new(struct mmsghdr, count);
result = msgvec;
for (i = 0; i < count ; i++) {
msgvec->msg_hdr.msg_name = NULL;
msgvec->msg_hdr.msg_namelen = 0;
- iov = g_malloc(sizeof(struct iovec) * IOVSIZE);
+ iov = g_new(struct iovec, IOVSIZE);
msgvec->msg_hdr.msg_iov = iov;
iov->iov_base = g_malloc(s->header_size);
iov->iov_len = s->header_size;
@@ -695,8 +695,7 @@ int net_init_l2tpv3(const NetClientOptions *opts,
goto outerr;
}
- s->dgram_dst = g_malloc(sizeof(struct sockaddr_storage));
- memset(s->dgram_dst, '\0' , sizeof(struct sockaddr_storage));
+ s->dgram_dst = g_new0(struct sockaddr_storage, 1);
memcpy(s->dgram_dst, result->ai_addr, result->ai_addrlen);
s->dst_size = result->ai_addrlen;
@@ -730,7 +729,7 @@ int net_init_l2tpv3(const NetClientOptions *opts,
}
s->msgvec = build_l2tpv3_vector(s, MAX_L2TPV3_MSGCNT);
- s->vec = g_malloc(sizeof(struct iovec) * MAX_L2TPV3_IOVCNT);
+ s->vec = g_new(struct iovec, MAX_L2TPV3_IOVCNT);
s->header_buf = g_malloc(s->header_size);
qemu_set_nonblock(fd);
diff --git a/net/queue.c b/net/queue.c
index f948318718..ebbe2bb93b 100644
--- a/net/queue.c
+++ b/net/queue.c
@@ -62,7 +62,7 @@ NetQueue *qemu_new_net_queue(void *opaque)
{
NetQueue *queue;
- queue = g_malloc0(sizeof(NetQueue));
+ queue = g_new0(NetQueue, 1);
queue->opaque = opaque;
queue->nq_maxlen = 10000;
diff --git a/net/slirp.c b/net/slirp.c
index 377d7ef8c0..0cbca3cc83 100644
--- a/net/slirp.c
+++ b/net/slirp.c
@@ -652,7 +652,7 @@ static int slirp_guestfwd(SlirpState *s, const char *config_str,
return -1;
}
} else {
- fwd = g_malloc(sizeof(struct GuestFwd));
+ fwd = g_new(struct GuestFwd, 1);
fwd->hd = qemu_chr_new(buf, p, NULL);
if (!fwd->hd) {
error_report("could not open guest forwarding device '%s'", buf);
diff --git a/net/tap.c b/net/tap.c
index bde6b58b17..1fe0edfdf7 100644
--- a/net/tap.c
+++ b/net/tap.c
@@ -189,6 +189,7 @@ static void tap_send(void *opaque)
{
TAPState *s = opaque;
int size;
+ int packets = 0;
while (qemu_can_send_packet(&s->nc)) {
uint8_t *buf = s->buf;
@@ -210,6 +211,17 @@ static void tap_send(void *opaque)
} else if (size < 0) {
break;
}
+
+ /*
+ * When the host keeps receiving more packets while tap_send() is
+ * running we can hog the QEMU global mutex. Limit the number of
+ * packets that are processed per tap_send() callback to prevent
+ * stalling the guest.
+ */
+ packets++;
+ if (packets >= 50) {
+ break;
+ }
}
}
diff --git a/pc-bios/efi-e1000.rom b/pc-bios/efi-e1000.rom
index 776e217a61..4e29d9d1ad 100644
--- a/pc-bios/efi-e1000.rom
+++ b/pc-bios/efi-e1000.rom
Binary files differ
diff --git a/pc-bios/efi-eepro100.rom b/pc-bios/efi-eepro100.rom
index 677a8c373e..2a92d6f32f 100644
--- a/pc-bios/efi-eepro100.rom
+++ b/pc-bios/efi-eepro100.rom
Binary files differ
diff --git a/pc-bios/efi-ne2k_pci.rom b/pc-bios/efi-ne2k_pci.rom
index 9dd6d91e31..6366017009 100644
--- a/pc-bios/efi-ne2k_pci.rom
+++ b/pc-bios/efi-ne2k_pci.rom
Binary files differ
diff --git a/pc-bios/efi-pcnet.rom b/pc-bios/efi-pcnet.rom
index cae3a85887..a61f586eeb 100644
--- a/pc-bios/efi-pcnet.rom
+++ b/pc-bios/efi-pcnet.rom
Binary files differ
diff --git a/pc-bios/efi-rtl8139.rom b/pc-bios/efi-rtl8139.rom
index 477f9b9b91..c9c77ea7f0 100644
--- a/pc-bios/efi-rtl8139.rom
+++ b/pc-bios/efi-rtl8139.rom
Binary files differ
diff --git a/pc-bios/efi-virtio.rom b/pc-bios/efi-virtio.rom
index 935c927400..eec2790990 100644
--- a/pc-bios/efi-virtio.rom
+++ b/pc-bios/efi-virtio.rom
Binary files differ
diff --git a/qom/cpu.c b/qom/cpu.c
index 79d22285f3..9c68fa4810 100644
--- a/qom/cpu.c
+++ b/qom/cpu.c
@@ -249,6 +249,7 @@ static void cpu_common_reset(CPUState *cpu)
cpu->icount_extra = 0;
cpu->icount_decr.u32 = 0;
cpu->can_do_io = 0;
+ cpu->exception_index = -1;
memset(cpu->tb_jmp_cache, 0, TB_JMP_CACHE_SIZE * sizeof(void *));
}
diff --git a/roms/ipxe b/roms/ipxe
-Subproject 69313edad85f8958acc8a47272b3c3da494835e
+Subproject 35c5379760aa1fea5e38f7a78b090f92bb7813e
diff --git a/target-tricore/helper.h b/target-tricore/helper.h
index 6c07bd7f28..068dc7b422 100644
--- a/target-tricore/helper.h
+++ b/target-tricore/helper.h
@@ -18,8 +18,12 @@
/* Arithmetic */
DEF_HELPER_3(add_ssov, i32, env, i32, i32)
DEF_HELPER_3(add_suov, i32, env, i32, i32)
+DEF_HELPER_3(add_h_ssov, i32, env, i32, i32)
+DEF_HELPER_3(add_h_suov, i32, env, i32, i32)
DEF_HELPER_3(sub_ssov, i32, env, i32, i32)
DEF_HELPER_3(sub_suov, i32, env, i32, i32)
+DEF_HELPER_3(sub_h_ssov, i32, env, i32, i32)
+DEF_HELPER_3(sub_h_suov, i32, env, i32, i32)
DEF_HELPER_3(mul_ssov, i32, env, i32, i32)
DEF_HELPER_3(mul_suov, i32, env, i32, i32)
DEF_HELPER_3(sha_ssov, i32, env, i32, i32)
@@ -32,6 +36,61 @@ DEF_HELPER_4(msub32_ssov, i32, env, i32, i32, i32)
DEF_HELPER_4(msub32_suov, i32, env, i32, i32, i32)
DEF_HELPER_4(msub64_ssov, i64, env, i32, i64, i32)
DEF_HELPER_4(msub64_suov, i64, env, i32, i64, i32)
+DEF_HELPER_3(absdif_h_ssov, i32, env, i32, i32)
+DEF_HELPER_2(abs_ssov, i32, env, i32)
+DEF_HELPER_2(abs_h_ssov, i32, env, i32)
+/* hword/byte arithmetic */
+DEF_HELPER_2(abs_b, i32, env, i32)
+DEF_HELPER_2(abs_h, i32, env, i32)
+DEF_HELPER_3(absdif_b, i32, env, i32, i32)
+DEF_HELPER_3(absdif_h, i32, env, i32, i32)
+DEF_HELPER_3(add_b, i32, env, i32, i32)
+DEF_HELPER_3(add_h, i32, env, i32, i32)
+DEF_HELPER_3(sub_b, i32, env, i32, i32)
+DEF_HELPER_3(sub_h, i32, env, i32, i32)
+DEF_HELPER_FLAGS_2(eq_b, TCG_CALL_NO_RWG_SE, i32, i32, i32)
+DEF_HELPER_FLAGS_2(eq_h, TCG_CALL_NO_RWG_SE, i32, i32, i32)
+DEF_HELPER_FLAGS_2(eqany_b, TCG_CALL_NO_RWG_SE, i32, i32, i32)
+DEF_HELPER_FLAGS_2(eqany_h, TCG_CALL_NO_RWG_SE, i32, i32, i32)
+DEF_HELPER_FLAGS_2(lt_b, TCG_CALL_NO_RWG_SE, i32, i32, i32)
+DEF_HELPER_FLAGS_2(lt_bu, TCG_CALL_NO_RWG_SE, i32, i32, i32)
+DEF_HELPER_FLAGS_2(lt_h, TCG_CALL_NO_RWG_SE, i32, i32, i32)
+DEF_HELPER_FLAGS_2(lt_hu, TCG_CALL_NO_RWG_SE, i32, i32, i32)
+DEF_HELPER_FLAGS_2(max_b, TCG_CALL_NO_RWG_SE, i32, i32, i32)
+DEF_HELPER_FLAGS_2(max_bu, TCG_CALL_NO_RWG_SE, i32, i32, i32)
+DEF_HELPER_FLAGS_2(max_h, TCG_CALL_NO_RWG_SE, i32, i32, i32)
+DEF_HELPER_FLAGS_2(max_hu, TCG_CALL_NO_RWG_SE, i32, i32, i32)
+DEF_HELPER_FLAGS_2(min_b, TCG_CALL_NO_RWG_SE, i32, i32, i32)
+DEF_HELPER_FLAGS_2(min_bu, TCG_CALL_NO_RWG_SE, i32, i32, i32)
+DEF_HELPER_FLAGS_2(min_h, TCG_CALL_NO_RWG_SE, i32, i32, i32)
+DEF_HELPER_FLAGS_2(min_hu, TCG_CALL_NO_RWG_SE, i32, i32, i32)
+/* count leading ... */
+DEF_HELPER_FLAGS_1(clo, TCG_CALL_NO_RWG_SE, i32, i32)
+DEF_HELPER_FLAGS_1(clo_h, TCG_CALL_NO_RWG_SE, i32, i32)
+DEF_HELPER_FLAGS_1(clz, TCG_CALL_NO_RWG_SE, i32, i32)
+DEF_HELPER_FLAGS_1(clz_h, TCG_CALL_NO_RWG_SE, i32, i32)
+DEF_HELPER_FLAGS_1(cls, TCG_CALL_NO_RWG_SE, i32, i32)
+DEF_HELPER_FLAGS_1(cls_h, TCG_CALL_NO_RWG_SE, i32, i32)
+/* sh */
+DEF_HELPER_FLAGS_2(sh, TCG_CALL_NO_RWG_SE, i32, i32, i32)
+DEF_HELPER_FLAGS_2(sh_h, TCG_CALL_NO_RWG_SE, i32, i32, i32)
+DEF_HELPER_3(sha, i32, env, i32, i32)
+DEF_HELPER_2(sha_h, i32, i32, i32)
+/* merge/split/parity */
+DEF_HELPER_FLAGS_2(bmerge, TCG_CALL_NO_RWG_SE, i32, i32, i32)
+DEF_HELPER_FLAGS_1(bsplit, TCG_CALL_NO_RWG_SE, i64, i32)
+DEF_HELPER_FLAGS_1(parity, TCG_CALL_NO_RWG_SE, i32, i32)
+/* float */
+DEF_HELPER_1(unpack, i64, i32)
+/* dvinit */
+DEF_HELPER_3(dvinit_b_13, i64, env, i32, i32)
+DEF_HELPER_3(dvinit_b_131, i64, env, i32, i32)
+DEF_HELPER_3(dvinit_h_13, i64, env, i32, i32)
+DEF_HELPER_3(dvinit_h_131, i64, env, i32, i32)
+/* mulh */
+DEF_HELPER_FLAGS_5(mul_h, TCG_CALL_NO_RWG_SE, i64, i32, i32, i32, i32, i32)
+DEF_HELPER_FLAGS_5(mulm_h, TCG_CALL_NO_RWG_SE, i64, i32, i32, i32, i32, i32)
+DEF_HELPER_FLAGS_5(mulr_h, TCG_CALL_NO_RWG_SE, i32, i32, i32, i32, i32, i32)
/* CSA */
DEF_HELPER_2(call, void, env, i32)
DEF_HELPER_1(ret, void, env)
diff --git a/target-tricore/op_helper.c b/target-tricore/op_helper.c
index 4da76ff232..13e27291c1 100644
--- a/target-tricore/op_helper.c
+++ b/target-tricore/op_helper.c
@@ -56,118 +56,211 @@ uint32_t helper_circ_update(uint32_t reg, uint32_t off)
return reg - index + new_index;
}
-#define SSOV(env, ret, arg, len) do { \
- int64_t max_pos = INT##len ##_MAX; \
- int64_t max_neg = INT##len ##_MIN; \
- if (arg > max_pos) { \
- env->PSW_USB_V = (1 << 31); \
- env->PSW_USB_SV = (1 << 31); \
- ret = (target_ulong)max_pos; \
- } else { \
- if (arg < max_neg) { \
- env->PSW_USB_V = (1 << 31); \
- env->PSW_USB_SV = (1 << 31); \
- ret = (target_ulong)max_neg; \
- } else { \
- env->PSW_USB_V = 0; \
- ret = (target_ulong)arg; \
- } \
- } \
- env->PSW_USB_AV = arg ^ arg * 2u; \
- env->PSW_USB_SAV |= env->PSW_USB_AV; \
-} while (0)
-
-#define SUOV(env, ret, arg, len) do { \
- int64_t max_pos = UINT##len ##_MAX; \
- if (arg > max_pos) { \
- env->PSW_USB_V = (1 << 31); \
- env->PSW_USB_SV = (1 << 31); \
- ret = (target_ulong)max_pos; \
- } else { \
- if (arg < 0) { \
- env->PSW_USB_V = (1 << 31); \
- env->PSW_USB_SV = (1 << 31); \
- ret = 0; \
- } else { \
- env->PSW_USB_V = 0; \
- ret = (target_ulong)arg; \
- } \
- } \
- env->PSW_USB_AV = arg ^ arg * 2u; \
- env->PSW_USB_SAV |= env->PSW_USB_AV; \
-} while (0)
+static uint32_t ssov32(CPUTriCoreState *env, int64_t arg)
+{
+ uint32_t ret;
+ int64_t max_pos = INT32_MAX;
+ int64_t max_neg = INT32_MIN;
+ if (arg > max_pos) {
+ env->PSW_USB_V = (1 << 31);
+ env->PSW_USB_SV = (1 << 31);
+ ret = (target_ulong)max_pos;
+ } else {
+ if (arg < max_neg) {
+ env->PSW_USB_V = (1 << 31);
+ env->PSW_USB_SV = (1 << 31);
+ ret = (target_ulong)max_neg;
+ } else {
+ env->PSW_USB_V = 0;
+ ret = (target_ulong)arg;
+ }
+ }
+ env->PSW_USB_AV = arg ^ arg * 2u;
+ env->PSW_USB_SAV |= env->PSW_USB_AV;
+ return ret;
+}
+
+static uint32_t suov32(CPUTriCoreState *env, int64_t arg)
+{
+ uint32_t ret;
+ int64_t max_pos = UINT32_MAX;
+ if (arg > max_pos) {
+ env->PSW_USB_V = (1 << 31);
+ env->PSW_USB_SV = (1 << 31);
+ ret = (target_ulong)max_pos;
+ } else {
+ if (arg < 0) {
+ env->PSW_USB_V = (1 << 31);
+ env->PSW_USB_SV = (1 << 31);
+ ret = 0;
+ } else {
+ env->PSW_USB_V = 0;
+ ret = (target_ulong)arg;
+ }
+ }
+ env->PSW_USB_AV = arg ^ arg * 2u;
+ env->PSW_USB_SAV |= env->PSW_USB_AV;
+ return ret;
+}
+static uint32_t ssov16(CPUTriCoreState *env, int32_t hw0, int32_t hw1)
+{
+ int32_t max_pos = INT16_MAX;
+ int32_t max_neg = INT16_MIN;
+ int32_t av0, av1;
+
+ env->PSW_USB_V = 0;
+ av0 = hw0 ^ hw0 * 2u;
+ if (hw0 > max_pos) {
+ env->PSW_USB_V = (1 << 31);
+ hw0 = max_pos;
+ } else if (hw0 < max_neg) {
+ env->PSW_USB_V = (1 << 31);
+ hw0 = max_neg;
+ }
+
+ av1 = hw1 ^ hw1 * 2u;
+ if (hw1 > max_pos) {
+ env->PSW_USB_V = (1 << 31);
+ hw1 = max_pos;
+ } else if (hw1 < max_neg) {
+ env->PSW_USB_V = (1 << 31);
+ hw1 = max_neg;
+ }
+
+ env->PSW_USB_SV |= env->PSW_USB_V;
+ env->PSW_USB_AV = (av0 | av1) << 16;
+ env->PSW_USB_SAV |= env->PSW_USB_AV;
+ return (hw0 & 0xffff) | (hw1 << 16);
+}
+
+static uint32_t suov16(CPUTriCoreState *env, int32_t hw0, int32_t hw1)
+{
+ int32_t max_pos = UINT16_MAX;
+ int32_t av0, av1;
+
+ env->PSW_USB_V = 0;
+ av0 = hw0 ^ hw0 * 2u;
+ if (hw0 > max_pos) {
+ env->PSW_USB_V = (1 << 31);
+ hw0 = max_pos;
+ } else if (hw0 < 0) {
+ env->PSW_USB_V = (1 << 31);
+ hw0 = 0;
+ }
+
+ av1 = hw1 ^ hw1 * 2u;
+ if (hw1 > max_pos) {
+ env->PSW_USB_V = (1 << 31);
+ hw1 = max_pos;
+ } else if (hw1 < 0) {
+ env->PSW_USB_V = (1 << 31);
+ hw1 = 0;
+ }
+
+ env->PSW_USB_SV |= env->PSW_USB_V;
+ env->PSW_USB_AV = (av0 | av1) << 16;
+ env->PSW_USB_SAV |= env->PSW_USB_AV;
+ return (hw0 & 0xffff) | (hw1 << 16);
+}
target_ulong helper_add_ssov(CPUTriCoreState *env, target_ulong r1,
target_ulong r2)
{
- target_ulong ret;
int64_t t1 = sextract64(r1, 0, 32);
int64_t t2 = sextract64(r2, 0, 32);
int64_t result = t1 + t2;
- SSOV(env, ret, result, 32);
- return ret;
+ return ssov32(env, result);
+}
+
+target_ulong helper_add_h_ssov(CPUTriCoreState *env, target_ulong r1,
+ target_ulong r2)
+{
+ int32_t ret_hw0, ret_hw1;
+
+ ret_hw0 = sextract32(r1, 0, 16) + sextract32(r2, 0, 16);
+ ret_hw1 = sextract32(r1, 16, 16) + sextract32(r2, 16, 16);
+ return ssov16(env, ret_hw0, ret_hw1);
}
target_ulong helper_add_suov(CPUTriCoreState *env, target_ulong r1,
target_ulong r2)
{
- target_ulong ret;
int64_t t1 = extract64(r1, 0, 32);
int64_t t2 = extract64(r2, 0, 32);
int64_t result = t1 + t2;
- SUOV(env, ret, result, 32);
- return ret;
+ return suov32(env, result);
+}
+
+target_ulong helper_add_h_suov(CPUTriCoreState *env, target_ulong r1,
+ target_ulong r2)
+{
+ int32_t ret_hw0, ret_hw1;
+
+ ret_hw0 = extract32(r1, 0, 16) + extract32(r2, 0, 16);
+ ret_hw1 = extract32(r1, 16, 16) + extract32(r2, 16, 16);
+ return suov16(env, ret_hw0, ret_hw1);
}
target_ulong helper_sub_ssov(CPUTriCoreState *env, target_ulong r1,
target_ulong r2)
{
- target_ulong ret;
int64_t t1 = sextract64(r1, 0, 32);
int64_t t2 = sextract64(r2, 0, 32);
int64_t result = t1 - t2;
- SSOV(env, ret, result, 32);
- return ret;
+ return ssov32(env, result);
+}
+
+target_ulong helper_sub_h_ssov(CPUTriCoreState *env, target_ulong r1,
+ target_ulong r2)
+{
+ int32_t ret_hw0, ret_hw1;
+
+ ret_hw0 = sextract32(r1, 0, 16) - sextract32(r2, 0, 16);
+ ret_hw1 = sextract32(r1, 16, 16) - sextract32(r2, 16, 16);
+ return ssov16(env, ret_hw0, ret_hw1);
}
target_ulong helper_sub_suov(CPUTriCoreState *env, target_ulong r1,
target_ulong r2)
{
- target_ulong ret;
int64_t t1 = extract64(r1, 0, 32);
int64_t t2 = extract64(r2, 0, 32);
int64_t result = t1 - t2;
- SUOV(env, ret, result, 32);
- return ret;
+ return suov32(env, result);
+}
+
+target_ulong helper_sub_h_suov(CPUTriCoreState *env, target_ulong r1,
+ target_ulong r2)
+{
+ int32_t ret_hw0, ret_hw1;
+
+ ret_hw0 = extract32(r1, 0, 16) - extract32(r2, 0, 16);
+ ret_hw1 = extract32(r1, 16, 16) - extract32(r2, 16, 16);
+ return suov16(env, ret_hw0, ret_hw1);
}
target_ulong helper_mul_ssov(CPUTriCoreState *env, target_ulong r1,
target_ulong r2)
{
- target_ulong ret;
int64_t t1 = sextract64(r1, 0, 32);
int64_t t2 = sextract64(r2, 0, 32);
int64_t result = t1 * t2;
- SSOV(env, ret, result, 32);
- return ret;
+ return ssov32(env, result);
}
target_ulong helper_mul_suov(CPUTriCoreState *env, target_ulong r1,
target_ulong r2)
{
- target_ulong ret;
int64_t t1 = extract64(r1, 0, 32);
int64_t t2 = extract64(r2, 0, 32);
int64_t result = t1 * t2;
- SUOV(env, ret, result, 32);
- return ret;
+ return suov32(env, result);
}
target_ulong helper_sha_ssov(CPUTriCoreState *env, target_ulong r1,
target_ulong r2)
{
- target_ulong ret;
int64_t t1 = sextract64(r1, 0, 32);
int32_t t2 = sextract64(r2, 0, 6);
int64_t result;
@@ -178,14 +271,32 @@ target_ulong helper_sha_ssov(CPUTriCoreState *env, target_ulong r1,
} else {
result = t1 >> -t2;
}
- SSOV(env, ret, result, 32);
- return ret;
+ return ssov32(env, result);
+}
+
+uint32_t helper_abs_ssov(CPUTriCoreState *env, target_ulong r1)
+{
+ target_ulong result;
+ result = ((int32_t)r1 >= 0) ? r1 : (0 - r1);
+ return ssov32(env, result);
+}
+
+uint32_t helper_abs_h_ssov(CPUTriCoreState *env, target_ulong r1)
+{
+ int32_t ret_h0, ret_h1;
+
+ ret_h0 = sextract32(r1, 0, 16);
+ ret_h0 = (ret_h0 >= 0) ? ret_h0 : (0 - ret_h0);
+
+ ret_h1 = sextract32(r1, 16, 16);
+ ret_h1 = (ret_h1 >= 0) ? ret_h1 : (0 - ret_h1);
+
+ return ssov16(env, ret_h0, ret_h1);
}
target_ulong helper_absdif_ssov(CPUTriCoreState *env, target_ulong r1,
target_ulong r2)
{
- target_ulong ret;
int64_t t1 = sextract64(r1, 0, 32);
int64_t t2 = sextract64(r2, 0, 32);
int64_t result;
@@ -195,36 +306,56 @@ target_ulong helper_absdif_ssov(CPUTriCoreState *env, target_ulong r1,
} else {
result = t2 - t1;
}
- SSOV(env, ret, result, 32);
- return ret;
+ return ssov32(env, result);
+}
+
+uint32_t helper_absdif_h_ssov(CPUTriCoreState *env, target_ulong r1,
+ target_ulong r2)
+{
+ int32_t t1, t2;
+ int32_t ret_h0, ret_h1;
+
+ t1 = sextract32(r1, 0, 16);
+ t2 = sextract32(r2, 0, 16);
+ if (t1 > t2) {
+ ret_h0 = t1 - t2;
+ } else {
+ ret_h0 = t2 - t1;
+ }
+
+ t1 = sextract32(r1, 16, 16);
+ t2 = sextract32(r2, 16, 16);
+ if (t1 > t2) {
+ ret_h1 = t1 - t2;
+ } else {
+ ret_h1 = t2 - t1;
+ }
+
+ return ssov16(env, ret_h0, ret_h1);
}
target_ulong helper_madd32_ssov(CPUTriCoreState *env, target_ulong r1,
target_ulong r2, target_ulong r3)
{
- target_ulong ret;
int64_t t1 = sextract64(r1, 0, 32);
int64_t t2 = sextract64(r2, 0, 32);
int64_t t3 = sextract64(r3, 0, 32);
int64_t result;
result = t2 + (t1 * t3);
- SSOV(env, ret, result, 32);
- return ret;
+ return ssov32(env, result);
}
target_ulong helper_madd32_suov(CPUTriCoreState *env, target_ulong r1,
target_ulong r2, target_ulong r3)
{
- target_ulong ret;
uint64_t t1 = extract64(r1, 0, 32);
uint64_t t2 = extract64(r2, 0, 32);
uint64_t t3 = extract64(r3, 0, 32);
int64_t result;
result = t2 + (t1 * t3);
- SUOV(env, ret, result, 32);
- return ret;
+ return suov32(env, result);
}
uint64_t helper_madd64_ssov(CPUTriCoreState *env, target_ulong r1,
@@ -286,29 +417,25 @@ uint64_t helper_madd64_suov(CPUTriCoreState *env, target_ulong r1,
target_ulong helper_msub32_ssov(CPUTriCoreState *env, target_ulong r1,
target_ulong r2, target_ulong r3)
{
- target_ulong ret;
int64_t t1 = sextract64(r1, 0, 32);
int64_t t2 = sextract64(r2, 0, 32);
int64_t t3 = sextract64(r3, 0, 32);
int64_t result;
result = t2 - (t1 * t3);
- SSOV(env, ret, result, 32);
- return ret;
+ return ssov32(env, result);
}
target_ulong helper_msub32_suov(CPUTriCoreState *env, target_ulong r1,
target_ulong r2, target_ulong r3)
{
- target_ulong ret;
int64_t t1 = extract64(r1, 0, 32);
int64_t t2 = extract64(r2, 0, 32);
int64_t t3 = extract64(r3, 0, 32);
int64_t result;
result = t2 - (t1 * t3);
- SUOV(env, ret, result, 32);
- return ret;
+ return suov32(env, result);
}
uint64_t helper_msub64_ssov(CPUTriCoreState *env, target_ulong r1,
@@ -366,6 +493,813 @@ uint64_t helper_msub64_suov(CPUTriCoreState *env, target_ulong r1,
return ret;
}
+uint32_t helper_abs_b(CPUTriCoreState *env, target_ulong arg)
+{
+ int32_t b, i;
+ int32_t ovf = 0;
+ int32_t avf = 0;
+ int32_t ret = 0;
+
+ for (i = 0; i < 4; i++) {
+ b = sextract32(arg, i * 8, 8);
+ b = (b >= 0) ? b : (0 - b);
+ ovf |= (b > 0x7F) || (b < -0x80);
+ avf |= b ^ b * 2u;
+ ret |= (b & 0xff) << (i * 8);
+ }
+
+ env->PSW_USB_V = ovf << 31;
+ env->PSW_USB_SV |= env->PSW_USB_V;
+ env->PSW_USB_AV = avf << 24;
+ env->PSW_USB_SAV |= env->PSW_USB_AV;
+
+ return ret;
+}
+
+uint32_t helper_abs_h(CPUTriCoreState *env, target_ulong arg)
+{
+ int32_t h, i;
+ int32_t ovf = 0;
+ int32_t avf = 0;
+ int32_t ret = 0;
+
+ for (i = 0; i < 2; i++) {
+ h = sextract32(arg, i * 16, 16);
+ h = (h >= 0) ? h : (0 - h);
+ ovf |= (h > 0x7FFF) || (h < -0x8000);
+ avf |= h ^ h * 2u;
+ ret |= (h & 0xffff) << (i * 16);
+ }
+
+ env->PSW_USB_V = ovf << 31;
+ env->PSW_USB_SV |= env->PSW_USB_V;
+ env->PSW_USB_AV = avf << 16;
+ env->PSW_USB_SAV |= env->PSW_USB_AV;
+
+ return ret;
+}
+
+uint32_t helper_absdif_b(CPUTriCoreState *env, target_ulong r1, target_ulong r2)
+{
+ int32_t b, i;
+ int32_t extr_r2;
+ int32_t ovf = 0;
+ int32_t avf = 0;
+ int32_t ret = 0;
+
+ for (i = 0; i < 4; i++) {
+ extr_r2 = sextract32(r2, i * 8, 8);
+ b = sextract32(r1, i * 8, 8);
+ b = (b > extr_r2) ? (b - extr_r2) : (extr_r2 - b);
+ ovf |= (b > 0x7F) || (b < -0x80);
+ avf |= b ^ b * 2u;
+ ret |= (b & 0xff) << (i * 8);
+ }
+
+ env->PSW_USB_V = ovf << 31;
+ env->PSW_USB_SV |= env->PSW_USB_V;
+ env->PSW_USB_AV = avf << 24;
+ env->PSW_USB_SAV |= env->PSW_USB_AV;
+ return ret;
+}
+
+uint32_t helper_absdif_h(CPUTriCoreState *env, target_ulong r1, target_ulong r2)
+{
+ int32_t h, i;
+ int32_t extr_r2;
+ int32_t ovf = 0;
+ int32_t avf = 0;
+ int32_t ret = 0;
+
+ for (i = 0; i < 2; i++) {
+ extr_r2 = sextract32(r2, i * 16, 16);
+ h = sextract32(r1, i * 16, 16);
+ h = (h > extr_r2) ? (h - extr_r2) : (extr_r2 - h);
+ ovf |= (h > 0x7FFF) || (h < -0x8000);
+ avf |= h ^ h * 2u;
+ ret |= (h & 0xffff) << (i * 16);
+ }
+
+ env->PSW_USB_V = ovf << 31;
+ env->PSW_USB_SV |= env->PSW_USB_V;
+ env->PSW_USB_AV = avf << 16;
+ env->PSW_USB_SAV |= env->PSW_USB_AV;
+
+ return ret;
+}
+
+uint32_t helper_add_b(CPUTriCoreState *env, target_ulong r1, target_ulong r2)
+{
+ int32_t b, i;
+ int32_t extr_r1, extr_r2;
+ int32_t ovf = 0;
+ int32_t avf = 0;
+ uint32_t ret = 0;
+
+ for (i = 0; i < 4; i++) {
+ extr_r1 = sextract32(r1, i * 8, 8);
+ extr_r2 = sextract32(r2, i * 8, 8);
+
+ b = extr_r1 + extr_r2;
+ ovf |= ((b > 0x7f) || (b < -0x80));
+ avf |= b ^ b * 2u;
+ ret |= ((b & 0xff) << (i*8));
+ }
+
+ env->PSW_USB_V = (ovf << 31);
+ env->PSW_USB_SV |= env->PSW_USB_V;
+ env->PSW_USB_AV = avf << 24;
+ env->PSW_USB_SAV |= env->PSW_USB_AV;
+
+ return ret;
+}
+
+uint32_t helper_add_h(CPUTriCoreState *env, target_ulong r1, target_ulong r2)
+{
+ int32_t h, i;
+ int32_t extr_r1, extr_r2;
+ int32_t ovf = 0;
+ int32_t avf = 0;
+ int32_t ret = 0;
+
+ for (i = 0; i < 2; i++) {
+ extr_r1 = sextract32(r1, i * 16, 16);
+ extr_r2 = sextract32(r2, i * 16, 16);
+ h = extr_r1 + extr_r2;
+ ovf |= ((h > 0x7fff) || (h < -0x8000));
+ avf |= h ^ h * 2u;
+ ret |= (h & 0xffff) << (i * 16);
+ }
+
+ env->PSW_USB_V = (ovf << 31);
+ env->PSW_USB_SV |= env->PSW_USB_V;
+ env->PSW_USB_AV = (avf << 16);
+ env->PSW_USB_SAV |= env->PSW_USB_AV;
+
+ return ret;
+}
+
+uint32_t helper_sub_b(CPUTriCoreState *env, target_ulong r1, target_ulong r2)
+{
+ int32_t b, i;
+ int32_t extr_r1, extr_r2;
+ int32_t ovf = 0;
+ int32_t avf = 0;
+ uint32_t ret = 0;
+
+ for (i = 0; i < 4; i++) {
+ extr_r1 = sextract32(r1, i * 8, 8);
+ extr_r2 = sextract32(r2, i * 8, 8);
+
+ b = extr_r1 - extr_r2;
+ ovf |= ((b > 0x7f) || (b < -0x80));
+ avf |= b ^ b * 2u;
+ ret |= ((b & 0xff) << (i*8));
+ }
+
+ env->PSW_USB_V = (ovf << 31);
+ env->PSW_USB_SV |= env->PSW_USB_V;
+ env->PSW_USB_AV = avf << 24;
+ env->PSW_USB_SAV |= env->PSW_USB_AV;
+
+ return ret;
+}
+
+uint32_t helper_sub_h(CPUTriCoreState *env, target_ulong r1, target_ulong r2)
+{
+ int32_t h, i;
+ int32_t extr_r1, extr_r2;
+ int32_t ovf = 0;
+ int32_t avf = 0;
+ int32_t ret = 0;
+
+ for (i = 0; i < 2; i++) {
+ extr_r1 = sextract32(r1, i * 16, 16);
+ extr_r2 = sextract32(r2, i * 16, 16);
+ h = extr_r1 - extr_r2;
+ ovf |= ((h > 0x7fff) || (h < -0x8000));
+ avf |= h ^ h * 2u;
+ ret |= (h & 0xffff) << (i * 16);
+ }
+
+ env->PSW_USB_V = (ovf << 31);
+ env->PSW_USB_SV |= env->PSW_USB_V;
+ env->PSW_USB_AV = avf << 16;
+ env->PSW_USB_SAV |= env->PSW_USB_AV;
+
+ return ret;
+}
+
+uint32_t helper_eq_b(target_ulong r1, target_ulong r2)
+{
+ int32_t ret;
+ int32_t i, msk;
+
+ ret = 0;
+ msk = 0xff;
+ for (i = 0; i < 4; i++) {
+ if ((r1 & msk) == (r2 & msk)) {
+ ret |= msk;
+ }
+ msk = msk << 8;
+ }
+
+ return ret;
+}
+
+uint32_t helper_eq_h(target_ulong r1, target_ulong r2)
+{
+ int32_t ret = 0;
+
+ if ((r1 & 0xffff) == (r2 & 0xffff)) {
+ ret = 0xffff;
+ }
+
+ if ((r1 & 0xffff0000) == (r2 & 0xffff0000)) {
+ ret |= 0xffff0000;
+ }
+
+ return ret;
+}
+
+uint32_t helper_eqany_b(target_ulong r1, target_ulong r2)
+{
+ int32_t i;
+ uint32_t ret = 0;
+
+ for (i = 0; i < 4; i++) {
+ ret |= (sextract32(r1, i * 8, 8) == sextract32(r2, i * 8, 8));
+ }
+
+ return ret;
+}
+
+uint32_t helper_eqany_h(target_ulong r1, target_ulong r2)
+{
+ uint32_t ret;
+
+ ret = (sextract32(r1, 0, 16) == sextract32(r2, 0, 16));
+ ret |= (sextract32(r1, 16, 16) == sextract32(r2, 16, 16));
+
+ return ret;
+}
+
+uint32_t helper_lt_b(target_ulong r1, target_ulong r2)
+{
+ int32_t i;
+ uint32_t ret = 0;
+
+ for (i = 0; i < 4; i++) {
+ if (sextract32(r1, i * 8, 8) < sextract32(r2, i * 8, 8)) {
+ ret |= (0xff << (i * 8));
+ }
+ }
+
+ return ret;
+}
+
+uint32_t helper_lt_bu(target_ulong r1, target_ulong r2)
+{
+ int32_t i;
+ uint32_t ret = 0;
+
+ for (i = 0; i < 4; i++) {
+ if (extract32(r1, i * 8, 8) < extract32(r2, i * 8, 8)) {
+ ret |= (0xff << (i * 8));
+ }
+ }
+
+ return ret;
+}
+
+uint32_t helper_lt_h(target_ulong r1, target_ulong r2)
+{
+ uint32_t ret = 0;
+
+ if (sextract32(r1, 0, 16) < sextract32(r2, 0, 16)) {
+ ret |= 0xffff;
+ }
+
+ if (sextract32(r1, 16, 16) < sextract32(r2, 16, 16)) {
+ ret |= 0xffff0000;
+ }
+
+ return ret;
+}
+
+uint32_t helper_lt_hu(target_ulong r1, target_ulong r2)
+{
+ uint32_t ret = 0;
+
+ if (extract32(r1, 0, 16) < extract32(r2, 0, 16)) {
+ ret |= 0xffff;
+ }
+
+ if (extract32(r1, 16, 16) < extract32(r2, 16, 16)) {
+ ret |= 0xffff0000;
+ }
+
+ return ret;
+}
+
+#define EXTREMA_H_B(name, op) \
+uint32_t helper_##name ##_b(target_ulong r1, target_ulong r2) \
+{ \
+ int32_t i, extr_r1, extr_r2; \
+ uint32_t ret = 0; \
+ \
+ for (i = 0; i < 4; i++) { \
+ extr_r1 = sextract32(r1, i * 8, 8); \
+ extr_r2 = sextract32(r2, i * 8, 8); \
+ extr_r1 = (extr_r1 op extr_r2) ? extr_r1 : extr_r2; \
+ ret |= (extr_r1 & 0xff) << (i * 8); \
+ } \
+ return ret; \
+} \
+ \
+uint32_t helper_##name ##_bu(target_ulong r1, target_ulong r2)\
+{ \
+ int32_t i; \
+ uint32_t extr_r1, extr_r2; \
+ uint32_t ret = 0; \
+ \
+ for (i = 0; i < 4; i++) { \
+ extr_r1 = extract32(r1, i * 8, 8); \
+ extr_r2 = extract32(r2, i * 8, 8); \
+ extr_r1 = (extr_r1 op extr_r2) ? extr_r1 : extr_r2; \
+ ret |= (extr_r1 & 0xff) << (i * 8); \
+ } \
+ return ret; \
+} \
+ \
+uint32_t helper_##name ##_h(target_ulong r1, target_ulong r2) \
+{ \
+ int32_t extr_r1, extr_r2; \
+ uint32_t ret = 0; \
+ \
+ extr_r1 = sextract32(r1, 0, 16); \
+ extr_r2 = sextract32(r2, 0, 16); \
+ ret = (extr_r1 op extr_r2) ? extr_r1 : extr_r2; \
+ ret = ret & 0xffff; \
+ \
+ extr_r1 = sextract32(r1, 16, 16); \
+ extr_r2 = sextract32(r2, 16, 16); \
+ extr_r1 = (extr_r1 op extr_r2) ? extr_r1 : extr_r2; \
+ ret |= extr_r1 << 16; \
+ \
+ return ret; \
+} \
+ \
+uint32_t helper_##name ##_hu(target_ulong r1, target_ulong r2)\
+{ \
+ uint32_t extr_r1, extr_r2; \
+ uint32_t ret = 0; \
+ \
+ extr_r1 = extract32(r1, 0, 16); \
+ extr_r2 = extract32(r2, 0, 16); \
+ ret = (extr_r1 op extr_r2) ? extr_r1 : extr_r2; \
+ ret = ret & 0xffff; \
+ \
+ extr_r1 = extract32(r1, 16, 16); \
+ extr_r2 = extract32(r2, 16, 16); \
+ extr_r1 = (extr_r1 op extr_r2) ? extr_r1 : extr_r2; \
+ ret |= extr_r1 << (16); \
+ \
+ return ret; \
+} \
+
+EXTREMA_H_B(max, >)
+EXTREMA_H_B(min, <)
+
+#undef EXTREMA_H_B
+
+uint32_t helper_clo(target_ulong r1)
+{
+ return clo32(r1);
+}
+
+uint32_t helper_clo_h(target_ulong r1)
+{
+ uint32_t ret_hw0 = extract32(r1, 0, 16);
+ uint32_t ret_hw1 = extract32(r1, 16, 16);
+
+ ret_hw0 = clo32(ret_hw0 << 16);
+ ret_hw1 = clo32(ret_hw1 << 16);
+
+ if (ret_hw0 > 16) {
+ ret_hw0 = 16;
+ }
+ if (ret_hw1 > 16) {
+ ret_hw1 = 16;
+ }
+
+ return ret_hw0 | (ret_hw1 << 16);
+}
+
+uint32_t helper_clz(target_ulong r1)
+{
+ return clz32(r1);
+}
+
+uint32_t helper_clz_h(target_ulong r1)
+{
+ uint32_t ret_hw0 = extract32(r1, 0, 16);
+ uint32_t ret_hw1 = extract32(r1, 16, 16);
+
+ ret_hw0 = clz32(ret_hw0 << 16);
+ ret_hw1 = clz32(ret_hw1 << 16);
+
+ if (ret_hw0 > 16) {
+ ret_hw0 = 16;
+ }
+ if (ret_hw1 > 16) {
+ ret_hw1 = 16;
+ }
+
+ return ret_hw0 | (ret_hw1 << 16);
+}
+
+uint32_t helper_cls(target_ulong r1)
+{
+ return clrsb32(r1);
+}
+
+uint32_t helper_cls_h(target_ulong r1)
+{
+ uint32_t ret_hw0 = extract32(r1, 0, 16);
+ uint32_t ret_hw1 = extract32(r1, 16, 16);
+
+ ret_hw0 = clrsb32(ret_hw0 << 16);
+ ret_hw1 = clrsb32(ret_hw1 << 16);
+
+ if (ret_hw0 > 15) {
+ ret_hw0 = 15;
+ }
+ if (ret_hw1 > 15) {
+ ret_hw1 = 15;
+ }
+
+ return ret_hw0 | (ret_hw1 << 16);
+}
+
+uint32_t helper_sh(target_ulong r1, target_ulong r2)
+{
+ int32_t shift_count = sextract32(r2, 0, 6);
+
+ if (shift_count == -32) {
+ return 0;
+ } else if (shift_count < 0) {
+ return r1 >> -shift_count;
+ } else {
+ return r1 << shift_count;
+ }
+}
+
+uint32_t helper_sh_h(target_ulong r1, target_ulong r2)
+{
+ int32_t ret_hw0, ret_hw1;
+ int32_t shift_count;
+
+ shift_count = sextract32(r2, 0, 5);
+
+ if (shift_count == -16) {
+ return 0;
+ } else if (shift_count < 0) {
+ ret_hw0 = extract32(r1, 0, 16) >> -shift_count;
+ ret_hw1 = extract32(r1, 16, 16) >> -shift_count;
+ return (ret_hw0 & 0xffff) | (ret_hw1 << 16);
+ } else {
+ ret_hw0 = extract32(r1, 0, 16) << shift_count;
+ ret_hw1 = extract32(r1, 16, 16) << shift_count;
+ return (ret_hw0 & 0xffff) | (ret_hw1 << 16);
+ }
+}
+
+uint32_t helper_sha(CPUTriCoreState *env, target_ulong r1, target_ulong r2)
+{
+ int32_t shift_count;
+ int64_t result, t1;
+ uint32_t ret;
+
+ shift_count = sextract32(r2, 0, 6);
+ t1 = sextract32(r1, 0, 32);
+
+ if (shift_count == 0) {
+ env->PSW_USB_C = env->PSW_USB_V = 0;
+ ret = r1;
+ } else if (shift_count == -32) {
+ env->PSW_USB_C = r1;
+ env->PSW_USB_V = 0;
+ ret = t1 >> 31;
+ } else if (shift_count > 0) {
+ result = t1 << shift_count;
+ /* calc carry */
+ env->PSW_USB_C = ((result & 0xffffffff00000000) != 0);
+ /* calc v */
+ env->PSW_USB_V = (((result > 0x7fffffffLL) ||
+ (result < -0x80000000LL)) << 31);
+ /* calc sv */
+ env->PSW_USB_SV |= env->PSW_USB_V;
+ ret = (uint32_t)result;
+ } else {
+ env->PSW_USB_V = 0;
+ env->PSW_USB_C = (r1 & ((1 << -shift_count) - 1));
+ ret = t1 >> -shift_count;
+ }
+
+ env->PSW_USB_AV = ret ^ ret * 2u;
+ env->PSW_USB_SAV |= env->PSW_USB_AV;
+
+ return ret;
+}
+
+uint32_t helper_sha_h(target_ulong r1, target_ulong r2)
+{
+ int32_t shift_count;
+ int32_t ret_hw0, ret_hw1;
+
+ shift_count = sextract32(r2, 0, 5);
+
+ if (shift_count == 0) {
+ return r1;
+ } else if (shift_count < 0) {
+ ret_hw0 = sextract32(r1, 0, 16) >> -shift_count;
+ ret_hw1 = sextract32(r1, 16, 16) >> -shift_count;
+ return (ret_hw0 & 0xffff) | (ret_hw1 << 16);
+ } else {
+ ret_hw0 = sextract32(r1, 0, 16) << shift_count;
+ ret_hw1 = sextract32(r1, 16, 16) << shift_count;
+ return (ret_hw0 & 0xffff) | (ret_hw1 << 16);
+ }
+}
+
+uint32_t helper_bmerge(target_ulong r1, target_ulong r2)
+{
+ uint32_t i, ret;
+
+ ret = 0;
+ for (i = 0; i < 16; i++) {
+ ret |= (r1 & 1) << (2 * i + 1);
+ ret |= (r2 & 1) << (2 * i);
+ r1 = r1 >> 1;
+ r2 = r2 >> 1;
+ }
+ return ret;
+}
+
+uint64_t helper_bsplit(uint32_t r1)
+{
+ int32_t i;
+ uint64_t ret;
+
+ ret = 0;
+ for (i = 0; i < 32; i = i + 2) {
+ /* even */
+ ret |= (r1 & 1) << (i/2);
+ r1 = r1 >> 1;
+ /* odd */
+ ret |= (uint64_t)(r1 & 1) << (i/2 + 32);
+ r1 = r1 >> 1;
+ }
+ return ret;
+}
+
+uint32_t helper_parity(target_ulong r1)
+{
+ uint32_t ret;
+ uint32_t nOnes, i;
+
+ ret = 0;
+ nOnes = 0;
+ for (i = 0; i < 8; i++) {
+ ret ^= (r1 & 1);
+ r1 = r1 >> 1;
+ }
+ /* second byte */
+ nOnes = 0;
+ for (i = 0; i < 8; i++) {
+ nOnes ^= (r1 & 1);
+ r1 = r1 >> 1;
+ }
+ ret |= nOnes << 8;
+ /* third byte */
+ nOnes = 0;
+ for (i = 0; i < 8; i++) {
+ nOnes ^= (r1 & 1);
+ r1 = r1 >> 1;
+ }
+ ret |= nOnes << 16;
+ /* fourth byte */
+ nOnes = 0;
+ for (i = 0; i < 8; i++) {
+ nOnes ^= (r1 & 1);
+ r1 = r1 >> 1;
+ }
+ ret |= nOnes << 24;
+
+ return ret;
+}
+
+uint64_t helper_unpack(target_ulong arg1)
+{
+ int32_t fp_exp = extract32(arg1, 23, 8);
+ int32_t fp_frac = extract32(arg1, 0, 23);
+ uint64_t ret;
+ int32_t int_exp, int_mant;
+
+ if (fp_exp == 255) {
+ int_exp = 255;
+ int_mant = (fp_frac << 7);
+ } else if ((fp_exp == 0) && (fp_frac == 0)) {
+ int_exp = -127;
+ int_mant = 0;
+ } else if ((fp_exp == 0) && (fp_frac != 0)) {
+ int_exp = -126;
+ int_mant = (fp_frac << 7);
+ } else {
+ int_exp = fp_exp - 127;
+ int_mant = (fp_frac << 7);
+ int_mant |= (1 << 30);
+ }
+ ret = int_exp;
+ ret = ret << 32;
+ ret |= int_mant;
+
+ return ret;
+}
+
+uint64_t helper_dvinit_b_13(CPUTriCoreState *env, uint32_t r1, uint32_t r2)
+{
+ uint64_t ret;
+ int32_t abs_sig_dividend, abs_base_dividend, abs_divisor;
+ int32_t quotient_sign;
+
+ ret = sextract32(r1, 0, 32);
+ ret = ret << 24;
+ quotient_sign = 0;
+ if (!((r1 & 0x80000000) == (r2 & 0x80000000))) {
+ ret |= 0xffffff;
+ quotient_sign = 1;
+ }
+
+ abs_sig_dividend = abs(r1) >> 7;
+ abs_base_dividend = abs(r1) & 0x7f;
+ abs_divisor = abs(r1);
+ /* calc overflow */
+ env->PSW_USB_V = 0;
+ if ((quotient_sign) && (abs_divisor)) {
+ env->PSW_USB_V = (((abs_sig_dividend == abs_divisor) &&
+ (abs_base_dividend >= abs_divisor)) ||
+ (abs_sig_dividend > abs_divisor));
+ } else {
+ env->PSW_USB_V = (abs_sig_dividend >= abs_divisor);
+ }
+ env->PSW_USB_V = env->PSW_USB_V << 31;
+ env->PSW_USB_SV |= env->PSW_USB_V;
+ env->PSW_USB_AV = 0;
+
+ return ret;
+}
+
+uint64_t helper_dvinit_b_131(CPUTriCoreState *env, uint32_t r1, uint32_t r2)
+{
+ uint64_t ret = sextract32(r1, 0, 32);
+
+ ret = ret << 24;
+ if (!((r1 & 0x80000000) == (r2 & 0x80000000))) {
+ ret |= 0xffffff;
+ }
+ /* calc overflow */
+ env->PSW_USB_V = ((r2 == 0) || ((r2 == 0xffffffff) && (r1 == 0xffffff80)));
+ env->PSW_USB_V = env->PSW_USB_V << 31;
+ env->PSW_USB_SV |= env->PSW_USB_V;
+ env->PSW_USB_AV = 0;
+
+ return ret;
+}
+
+uint64_t helper_dvinit_h_13(CPUTriCoreState *env, uint32_t r1, uint32_t r2)
+{
+ uint64_t ret;
+ int32_t abs_sig_dividend, abs_base_dividend, abs_divisor;
+ int32_t quotient_sign;
+
+ ret = sextract32(r1, 0, 32);
+ ret = ret << 16;
+ quotient_sign = 0;
+ if (!((r1 & 0x80000000) == (r2 & 0x80000000))) {
+ ret |= 0xffff;
+ quotient_sign = 1;
+ }
+
+ abs_sig_dividend = abs(r1) >> 7;
+ abs_base_dividend = abs(r1) & 0x7f;
+ abs_divisor = abs(r1);
+ /* calc overflow */
+ env->PSW_USB_V = 0;
+ if ((quotient_sign) && (abs_divisor)) {
+ env->PSW_USB_V = (((abs_sig_dividend == abs_divisor) &&
+ (abs_base_dividend >= abs_divisor)) ||
+ (abs_sig_dividend > abs_divisor));
+ } else {
+ env->PSW_USB_V = (abs_sig_dividend >= abs_divisor);
+ }
+ env->PSW_USB_V = env->PSW_USB_V << 31;
+ env->PSW_USB_SV |= env->PSW_USB_V;
+ env->PSW_USB_AV = 0;
+
+ return ret;
+}
+
+uint64_t helper_dvinit_h_131(CPUTriCoreState *env, uint32_t r1, uint32_t r2)
+{
+ uint64_t ret = sextract32(r1, 0, 32);
+
+ ret = ret << 16;
+ if (!((r1 & 0x80000000) == (r2 & 0x80000000))) {
+ ret |= 0xffff;
+ }
+ /* calc overflow */
+ env->PSW_USB_V = ((r2 == 0) || ((r2 == 0xffffffff) && (r1 == 0xffff8000)));
+ env->PSW_USB_V = env->PSW_USB_V << 31;
+ env->PSW_USB_SV |= env->PSW_USB_V;
+ env->PSW_USB_AV = 0;
+
+ return ret;
+}
+
+uint64_t helper_mul_h(uint32_t arg00, uint32_t arg01,
+ uint32_t arg10, uint32_t arg11, uint32_t n)
+{
+ uint64_t ret;
+ uint32_t result0, result1;
+
+ int32_t sc1 = ((arg00 & 0xffff) == 0x8000) &&
+ ((arg10 & 0xffff) == 0x8000) && (n == 1);
+ int32_t sc0 = ((arg01 & 0xffff) == 0x8000) &&
+ ((arg11 & 0xffff) == 0x8000) && (n == 1);
+ if (sc1) {
+ result1 = 0x7fffffff;
+ } else {
+ result1 = (((uint32_t)(arg00 * arg10)) << n);
+ }
+ if (sc0) {
+ result0 = 0x7fffffff;
+ } else {
+ result0 = (((uint32_t)(arg01 * arg11)) << n);
+ }
+ ret = (((uint64_t)result1 << 32)) | result0;
+ return ret;
+}
+
+uint64_t helper_mulm_h(uint32_t arg00, uint32_t arg01,
+ uint32_t arg10, uint32_t arg11, uint32_t n)
+{
+ uint64_t ret;
+ int64_t result0, result1;
+
+ int32_t sc1 = ((arg00 & 0xffff) == 0x8000) &&
+ ((arg10 & 0xffff) == 0x8000) && (n == 1);
+ int32_t sc0 = ((arg01 & 0xffff) == 0x8000) &&
+ ((arg11 & 0xffff) == 0x8000) && (n == 1);
+
+ if (sc1) {
+ result1 = 0x7fffffff;
+ } else {
+ result1 = (((int32_t)arg00 * (int32_t)arg10) << n);
+ }
+ if (sc0) {
+ result0 = 0x7fffffff;
+ } else {
+ result0 = (((int32_t)arg01 * (int32_t)arg11) << n);
+ }
+ ret = (result1 + result0);
+ ret = ret << 16;
+ return ret;
+}
+uint32_t helper_mulr_h(uint32_t arg00, uint32_t arg01,
+ uint32_t arg10, uint32_t arg11, uint32_t n)
+{
+ uint32_t result0, result1;
+
+ int32_t sc1 = ((arg00 & 0xffff) == 0x8000) &&
+ ((arg10 & 0xffff) == 0x8000) && (n == 1);
+ int32_t sc0 = ((arg01 & 0xffff) == 0x8000) &&
+ ((arg11 & 0xffff) == 0x8000) && (n == 1);
+
+ if (sc1) {
+ result1 = 0x7fffffff;
+ } else {
+ result1 = ((arg00 * arg10) << n) + 0x8000;
+ }
+ if (sc0) {
+ result0 = 0x7fffffff;
+ } else {
+ result0 = ((arg01 * arg11) << n) + 0x8000;
+ }
+ return (result1 & 0xffff0000) | (result0 >> 16);
+}
+
/* context save area (CSA) related helpers */
static int cdc_increment(target_ulong *psw)
diff --git a/target-tricore/translate.c b/target-tricore/translate.c
index 65abf453f0..dbcf87e383 100644
--- a/target-tricore/translate.c
+++ b/target-tricore/translate.c
@@ -85,22 +85,31 @@ void tricore_cpu_dump_state(CPUState *cs, FILE *f,
{
TriCoreCPU *cpu = TRICORE_CPU(cs);
CPUTriCoreState *env = &cpu->env;
+ uint32_t psw;
int i;
- cpu_fprintf(f, "PC=%08x\n", env->PC);
+ psw = psw_read(env);
+
+ cpu_fprintf(f, "PC: " TARGET_FMT_lx, env->PC);
+ cpu_fprintf(f, " PSW: " TARGET_FMT_lx, psw);
+ cpu_fprintf(f, " ICR: " TARGET_FMT_lx, env->ICR);
+ cpu_fprintf(f, "\nPCXI: " TARGET_FMT_lx, env->PCXI);
+ cpu_fprintf(f, " FCX: " TARGET_FMT_lx, env->FCX);
+ cpu_fprintf(f, " LCX: " TARGET_FMT_lx, env->LCX);
+
for (i = 0; i < 16; ++i) {
if ((i & 3) == 0) {
- cpu_fprintf(f, "GPR A%02d:", i);
+ cpu_fprintf(f, "\nGPR A%02d:", i);
}
- cpu_fprintf(f, " %s " TARGET_FMT_lx, regnames_a[i], env->gpr_a[i]);
+ cpu_fprintf(f, " " TARGET_FMT_lx, env->gpr_a[i]);
}
for (i = 0; i < 16; ++i) {
if ((i & 3) == 0) {
- cpu_fprintf(f, "GPR D%02d:", i);
+ cpu_fprintf(f, "\nGPR D%02d:", i);
}
- cpu_fprintf(f, " %s " TARGET_FMT_lx, regnames_d[i], env->gpr_d[i]);
+ cpu_fprintf(f, " " TARGET_FMT_lx, env->gpr_d[i]);
}
-
+ cpu_fprintf(f, "\n");
}
/*
@@ -115,6 +124,64 @@ void tricore_cpu_dump_state(CPUState *cs, FILE *f,
tcg_temp_free_i32(helper_tmp); \
} while (0)
+#define GEN_HELPER_LL(name, ret, arg0, arg1, n) do { \
+ TCGv arg00 = tcg_temp_new(); \
+ TCGv arg01 = tcg_temp_new(); \
+ TCGv arg11 = tcg_temp_new(); \
+ tcg_gen_sari_tl(arg00, arg0, 16); \
+ tcg_gen_ext16s_tl(arg01, arg0); \
+ tcg_gen_ext16s_tl(arg11, arg1); \
+ gen_helper_##name(ret, arg00, arg01, arg11, arg11, n); \
+ tcg_temp_free(arg00); \
+ tcg_temp_free(arg01); \
+ tcg_temp_free(arg11); \
+} while (0)
+
+#define GEN_HELPER_LU(name, ret, arg0, arg1, n) do { \
+ TCGv arg00 = tcg_temp_new(); \
+ TCGv arg01 = tcg_temp_new(); \
+ TCGv arg10 = tcg_temp_new(); \
+ TCGv arg11 = tcg_temp_new(); \
+ tcg_gen_sari_tl(arg00, arg0, 16); \
+ tcg_gen_ext16s_tl(arg01, arg0); \
+ tcg_gen_sari_tl(arg11, arg1, 16); \
+ tcg_gen_ext16s_tl(arg10, arg1); \
+ gen_helper_##name(ret, arg00, arg01, arg10, arg11, n); \
+ tcg_temp_free(arg00); \
+ tcg_temp_free(arg01); \
+ tcg_temp_free(arg10); \
+ tcg_temp_free(arg11); \
+} while (0)
+
+#define GEN_HELPER_UL(name, ret, arg0, arg1, n) do { \
+ TCGv arg00 = tcg_temp_new(); \
+ TCGv arg01 = tcg_temp_new(); \
+ TCGv arg10 = tcg_temp_new(); \
+ TCGv arg11 = tcg_temp_new(); \
+ tcg_gen_sari_tl(arg00, arg0, 16); \
+ tcg_gen_ext16s_tl(arg01, arg0); \
+ tcg_gen_sari_tl(arg10, arg1, 16); \
+ tcg_gen_ext16s_tl(arg11, arg1); \
+ gen_helper_##name(ret, arg00, arg01, arg10, arg11, n); \
+ tcg_temp_free(arg00); \
+ tcg_temp_free(arg01); \
+ tcg_temp_free(arg10); \
+ tcg_temp_free(arg11); \
+} while (0)
+
+#define GEN_HELPER_UU(name, ret, arg0, arg1, n) do { \
+ TCGv arg00 = tcg_temp_new(); \
+ TCGv arg01 = tcg_temp_new(); \
+ TCGv arg11 = tcg_temp_new(); \
+ tcg_gen_sari_tl(arg01, arg0, 16); \
+ tcg_gen_ext16s_tl(arg00, arg0); \
+ tcg_gen_sari_tl(arg11, arg1, 16); \
+ gen_helper_##name(ret, arg00, arg01, arg11, arg11, n); \
+ tcg_temp_free(arg00); \
+ tcg_temp_free(arg01); \
+ tcg_temp_free(arg11); \
+} while (0)
+
#define EA_ABS_FORMAT(con) (((con & 0x3C000) << 14) + (con & 0x3FFF))
#define EA_B_ABSOLUT(con) (((offset & 0xf00000) << 8) | \
((offset & 0x0fffff) << 1))
@@ -719,6 +786,62 @@ static inline void gen_sub_d(TCGv ret, TCGv r1, TCGv r2)
tcg_temp_free(result);
}
+static inline void gen_sub_CC(TCGv ret, TCGv r1, TCGv r2)
+{
+ TCGv result = tcg_temp_new();
+ TCGv temp = tcg_temp_new();
+
+ tcg_gen_sub_tl(result, r1, r2);
+ /* calc C bit */
+ tcg_gen_setcond_tl(TCG_COND_GEU, cpu_PSW_C, r1, r2);
+ /* calc V bit */
+ tcg_gen_xor_tl(cpu_PSW_V, result, r1);
+ tcg_gen_xor_tl(temp, r1, r2);
+ tcg_gen_and_tl(cpu_PSW_V, cpu_PSW_V, temp);
+ /* calc SV bit */
+ tcg_gen_or_tl(cpu_PSW_SV, cpu_PSW_SV, cpu_PSW_V);
+ /* Calc AV bit */
+ tcg_gen_add_tl(cpu_PSW_AV, result, result);
+ tcg_gen_xor_tl(cpu_PSW_AV, result, cpu_PSW_AV);
+ /* calc SAV bit */
+ tcg_gen_or_tl(cpu_PSW_SAV, cpu_PSW_SAV, cpu_PSW_AV);
+ /* write back result */
+ tcg_gen_mov_tl(ret, result);
+
+ tcg_temp_free(result);
+ tcg_temp_free(temp);
+}
+
+static inline void gen_subc_CC(TCGv ret, TCGv r1, TCGv r2)
+{
+ TCGv temp = tcg_temp_new();
+ tcg_gen_not_tl(temp, r2);
+ gen_addc_CC(ret, r1, temp);
+ tcg_temp_free(temp);
+}
+
+static inline void gen_abs(TCGv ret, TCGv r1)
+{
+ TCGv temp = tcg_temp_new();
+ TCGv t0 = tcg_const_i32(0);
+
+ tcg_gen_neg_tl(temp, r1);
+ tcg_gen_movcond_tl(TCG_COND_GE, ret, r1, t0, r1, temp);
+ /* overflow can only happen, if r1 = 0x80000000 */
+ tcg_gen_setcondi_tl(TCG_COND_EQ, cpu_PSW_V, r1, 0x80000000);
+ tcg_gen_shli_tl(cpu_PSW_V, cpu_PSW_V, 31);
+ /* calc SV bit */
+ tcg_gen_or_tl(cpu_PSW_SV, cpu_PSW_SV, cpu_PSW_V);
+ /* Calc AV bit */
+ tcg_gen_add_tl(cpu_PSW_AV, ret, ret);
+ tcg_gen_xor_tl(cpu_PSW_AV, ret, cpu_PSW_AV);
+ /* calc SAV bit */
+ tcg_gen_or_tl(cpu_PSW_SAV, cpu_PSW_SAV, cpu_PSW_AV);
+
+ tcg_temp_free(temp);
+ tcg_temp_free(t0);
+}
+
static inline void gen_absdif(TCGv ret, TCGv r1, TCGv r2)
{
TCGv temp = tcg_temp_new_i32();
@@ -1208,6 +1331,13 @@ gen_accumulating_condi(int cond, TCGv ret, TCGv r1, int32_t con,
tcg_temp_free(temp);
}
+/* ret = (r1 cond r2) ? 0xFFFFFFFF ? 0x00000000;*/
+static inline void gen_cond_w(TCGCond cond, TCGv ret, TCGv r1, TCGv r2)
+{
+ tcg_gen_setcond_tl(cond, ret, r1, r2);
+ tcg_gen_neg_tl(ret, ret);
+}
+
static inline void gen_eqany_bi(TCGv ret, TCGv r1, int32_t con)
{
TCGv b0 = tcg_temp_new();
@@ -1284,6 +1414,86 @@ static inline void gen_insert(TCGv ret, TCGv r1, TCGv r2, TCGv width, TCGv pos)
tcg_temp_free(temp2);
}
+static inline void gen_bsplit(TCGv rl, TCGv rh, TCGv r1)
+{
+ TCGv_i64 temp = tcg_temp_new_i64();
+
+ gen_helper_bsplit(temp, r1);
+ tcg_gen_extr_i64_i32(rl, rh, temp);
+
+ tcg_temp_free_i64(temp);
+}
+
+static inline void gen_unpack(TCGv rl, TCGv rh, TCGv r1)
+{
+ TCGv_i64 temp = tcg_temp_new_i64();
+
+ gen_helper_unpack(temp, r1);
+ tcg_gen_extr_i64_i32(rl, rh, temp);
+
+ tcg_temp_free_i64(temp);
+}
+
+static inline void
+gen_dvinit_b(CPUTriCoreState *env, TCGv rl, TCGv rh, TCGv r1, TCGv r2)
+{
+ TCGv_i64 ret = tcg_temp_new_i64();
+
+ if (!tricore_feature(env, TRICORE_FEATURE_131)) {
+ gen_helper_dvinit_b_13(ret, cpu_env, r1, r2);
+ } else {
+ gen_helper_dvinit_b_131(ret, cpu_env, r1, r2);
+ }
+ tcg_gen_extr_i64_i32(rl, rh, ret);
+
+ tcg_temp_free_i64(ret);
+}
+
+static inline void
+gen_dvinit_h(CPUTriCoreState *env, TCGv rl, TCGv rh, TCGv r1, TCGv r2)
+{
+ TCGv_i64 ret = tcg_temp_new_i64();
+
+ if (!tricore_feature(env, TRICORE_FEATURE_131)) {
+ gen_helper_dvinit_h_13(ret, cpu_env, r1, r2);
+ } else {
+ gen_helper_dvinit_h_131(ret, cpu_env, r1, r2);
+ }
+ tcg_gen_extr_i64_i32(rl, rh, ret);
+
+ tcg_temp_free_i64(ret);
+}
+
+static void gen_calc_usb_mul_h(TCGv arg_low, TCGv arg_high)
+{
+ TCGv temp = tcg_temp_new();
+ /* calc AV bit */
+ tcg_gen_add_tl(temp, arg_low, arg_low);
+ tcg_gen_xor_tl(temp, temp, arg_low);
+ tcg_gen_add_tl(cpu_PSW_AV, arg_high, arg_high);
+ tcg_gen_xor_tl(cpu_PSW_AV, cpu_PSW_AV, arg_high);
+ tcg_gen_or_tl(cpu_PSW_AV, cpu_PSW_AV, temp);
+ /* calc SAV bit */
+ tcg_gen_or_tl(cpu_PSW_SAV, cpu_PSW_SAV, cpu_PSW_AV);
+ tcg_gen_movi_tl(cpu_PSW_V, 0);
+ tcg_temp_free(temp);
+}
+
+static void gen_calc_usb_mulr_h(TCGv arg)
+{
+ TCGv temp = tcg_temp_new();
+ /* calc AV bit */
+ tcg_gen_add_tl(temp, arg, arg);
+ tcg_gen_xor_tl(temp, temp, arg);
+ tcg_gen_shli_tl(cpu_PSW_AV, temp, 16);
+ tcg_gen_or_tl(cpu_PSW_AV, cpu_PSW_AV, temp);
+ /* calc SAV bit */
+ tcg_gen_or_tl(cpu_PSW_SAV, cpu_PSW_SAV, cpu_PSW_AV);
+ /* clear V bit */
+ tcg_gen_movi_tl(cpu_PSW_V, 0);
+ tcg_temp_free(temp);
+}
+
/* helpers for generating program flow micro-ops */
static inline void gen_save_pc(target_ulong pc)
@@ -3203,7 +3413,7 @@ static void decode_bol_opc(CPUTriCoreState *env, DisasContext *ctx, int32_t op1)
tcg_gen_qemu_ld_tl(cpu_gpr_a[r1], temp, ctx->mem_idx, MO_LEUL);
tcg_temp_free(temp);
break;
- case OPC1_32_BOL_LD_W_LONFOFF:
+ case OPC1_32_BOL_LD_W_LONGOFF:
temp = tcg_temp_new();
tcg_gen_addi_tl(temp, cpu_gpr_a[r2], address);
tcg_gen_qemu_ld_tl(cpu_gpr_d[r1], temp, ctx->mem_idx, MO_LEUL);
@@ -3222,8 +3432,49 @@ static void decode_bol_opc(CPUTriCoreState *env, DisasContext *ctx, int32_t op1)
case OPC1_32_BOL_ST_W_LONGOFF:
gen_offset_st(ctx, cpu_gpr_d[r1], cpu_gpr_a[r2], address, MO_LEUL);
break;
+ case OPC1_32_BOL_LD_B_LONGOFF:
+ if (tricore_feature(env, TRICORE_FEATURE_16)) {
+ gen_offset_ld(ctx, cpu_gpr_d[r1], cpu_gpr_a[r2], address, MO_SB);
+ } else {
+ /* raise illegal opcode trap */
+ }
+ break;
+ case OPC1_32_BOL_LD_BU_LONGOFF:
+ if (tricore_feature(env, TRICORE_FEATURE_16)) {
+ gen_offset_ld(ctx, cpu_gpr_d[r1], cpu_gpr_a[r2], address, MO_UB);
+ } else {
+ /* raise illegal opcode trap */
+ }
+ break;
+ case OPC1_32_BOL_LD_H_LONGOFF:
+ if (tricore_feature(env, TRICORE_FEATURE_16)) {
+ gen_offset_ld(ctx, cpu_gpr_d[r1], cpu_gpr_a[r2], address, MO_LESW);
+ } else {
+ /* raise illegal opcode trap */
+ }
+ break;
+ case OPC1_32_BOL_LD_HU_LONGOFF:
+ if (tricore_feature(env, TRICORE_FEATURE_16)) {
+ gen_offset_ld(ctx, cpu_gpr_d[r1], cpu_gpr_a[r2], address, MO_LEUW);
+ } else {
+ /* raise illegal opcode trap */
+ }
+ break;
+ case OPC1_32_BOL_ST_B_LONGOFF:
+ if (tricore_feature(env, TRICORE_FEATURE_16)) {
+ gen_offset_st(ctx, cpu_gpr_d[r1], cpu_gpr_a[r2], address, MO_SB);
+ } else {
+ /* raise illegal opcode trap */
+ }
+ break;
+ case OPC1_32_BOL_ST_H_LONGOFF:
+ if (tricore_feature(env, TRICORE_FEATURE_16)) {
+ gen_offset_ld(ctx, cpu_gpr_d[r1], cpu_gpr_a[r2], address, MO_LESW);
+ } else {
+ /* raise illegal opcode trap */
+ }
+ break;
}
-
}
/* RC format */
@@ -3776,11 +4027,23 @@ static void decode_rlc_opc(CPUTriCoreState *env, DisasContext *ctx,
tcg_gen_addi_tl(cpu_gpr_a[r2], cpu_gpr_a[r1], const16 << 16);
break;
case OPC1_32_RLC_MFCR:
+ const16 = MASK_OP_RLC_CONST16(ctx->opcode);
gen_mfcr(env, cpu_gpr_d[r2], const16);
break;
case OPC1_32_RLC_MOV:
tcg_gen_movi_tl(cpu_gpr_d[r2], const16);
break;
+ case OPC1_32_RLC_MOV_64:
+ if (tricore_feature(env, TRICORE_FEATURE_16)) {
+ if ((r2 & 0x1) != 0) {
+ /* TODO: raise OPD trap */
+ }
+ tcg_gen_movi_tl(cpu_gpr_d[r2], const16);
+ tcg_gen_movi_tl(cpu_gpr_d[r2+1], const16 >> 15);
+ } else {
+ /* TODO: raise illegal opcode trap */
+ }
+ break;
case OPC1_32_RLC_MOV_U:
const16 = MASK_OP_RLC_CONST16(ctx->opcode);
tcg_gen_movi_tl(cpu_gpr_d[r2], const16);
@@ -3792,11 +4055,729 @@ static void decode_rlc_opc(CPUTriCoreState *env, DisasContext *ctx,
tcg_gen_movi_tl(cpu_gpr_a[r2], const16 << 16);
break;
case OPC1_32_RLC_MTCR:
- gen_mtcr(env, ctx, cpu_gpr_d[r2], const16);
+ const16 = MASK_OP_RLC_CONST16(ctx->opcode);
+ gen_mtcr(env, ctx, cpu_gpr_d[r1], const16);
break;
}
}
+/* RR format */
+static void decode_rr_accumulator(CPUTriCoreState *env, DisasContext *ctx)
+{
+ uint32_t op2;
+ int r3, r2, r1;
+
+ r3 = MASK_OP_RR_D(ctx->opcode);
+ r2 = MASK_OP_RR_S2(ctx->opcode);
+ r1 = MASK_OP_RR_S1(ctx->opcode);
+ op2 = MASK_OP_RR_OP2(ctx->opcode);
+
+ switch (op2) {
+ case OPC2_32_RR_ABS:
+ gen_abs(cpu_gpr_d[r3], cpu_gpr_d[r2]);
+ break;
+ case OPC2_32_RR_ABS_B:
+ gen_helper_abs_b(cpu_gpr_d[r3], cpu_env, cpu_gpr_d[r2]);
+ break;
+ case OPC2_32_RR_ABS_H:
+ gen_helper_abs_h(cpu_gpr_d[r3], cpu_env, cpu_gpr_d[r2]);
+ break;
+ case OPC2_32_RR_ABSDIF:
+ gen_absdif(cpu_gpr_d[r3], cpu_gpr_d[r1], cpu_gpr_d[r2]);
+ break;
+ case OPC2_32_RR_ABSDIF_B:
+ gen_helper_absdif_b(cpu_gpr_d[r3], cpu_env, cpu_gpr_d[r1],
+ cpu_gpr_d[r2]);
+ break;
+ case OPC2_32_RR_ABSDIF_H:
+ gen_helper_absdif_h(cpu_gpr_d[r3], cpu_env, cpu_gpr_d[r1],
+ cpu_gpr_d[r2]);
+ break;
+ case OPC2_32_RR_ABSDIFS:
+ gen_helper_absdif_ssov(cpu_gpr_d[r3], cpu_env, cpu_gpr_d[r1],
+ cpu_gpr_d[r2]);
+ break;
+ case OPC2_32_RR_ABSDIFS_H:
+ gen_helper_absdif_h_ssov(cpu_gpr_d[r3], cpu_env, cpu_gpr_d[r1],
+ cpu_gpr_d[r2]);
+ break;
+ case OPC2_32_RR_ABSS:
+ gen_helper_abs_ssov(cpu_gpr_d[r3], cpu_env, cpu_gpr_d[r2]);
+ break;
+ case OPC2_32_RR_ABSS_H:
+ gen_helper_abs_h_ssov(cpu_gpr_d[r3], cpu_env, cpu_gpr_d[r2]);
+ break;
+ case OPC2_32_RR_ADD:
+ gen_add_d(cpu_gpr_d[r3], cpu_gpr_d[r1], cpu_gpr_d[r2]);
+ break;
+ case OPC2_32_RR_ADD_B:
+ gen_helper_add_b(cpu_gpr_d[r3], cpu_env, cpu_gpr_d[r1], cpu_gpr_d[r2]);
+ break;
+ case OPC2_32_RR_ADD_H:
+ gen_helper_add_h(cpu_gpr_d[r3], cpu_env, cpu_gpr_d[r1], cpu_gpr_d[r2]);
+ break;
+ case OPC2_32_RR_ADDC:
+ gen_addc_CC(cpu_gpr_d[r3], cpu_gpr_d[r1], cpu_gpr_d[r2]);
+ break;
+ case OPC2_32_RR_ADDS:
+ gen_adds(cpu_gpr_d[r3], cpu_gpr_d[r1], cpu_gpr_d[r2]);
+ break;
+ case OPC2_32_RR_ADDS_H:
+ gen_helper_add_h_ssov(cpu_gpr_d[r3], cpu_env, cpu_gpr_d[r1],
+ cpu_gpr_d[r2]);
+ break;
+ case OPC2_32_RR_ADDS_HU:
+ gen_helper_add_h_suov(cpu_gpr_d[r3], cpu_env, cpu_gpr_d[r1],
+ cpu_gpr_d[r2]);
+ break;
+ case OPC2_32_RR_ADDS_U:
+ gen_helper_add_suov(cpu_gpr_d[r3], cpu_env, cpu_gpr_d[r1],
+ cpu_gpr_d[r2]);
+ break;
+ case OPC2_32_RR_ADDX:
+ gen_add_CC(cpu_gpr_d[r3], cpu_gpr_d[r1], cpu_gpr_d[r2]);
+ break;
+ case OPC2_32_RR_AND_EQ:
+ gen_accumulating_cond(TCG_COND_EQ, cpu_gpr_d[r3], cpu_gpr_d[r1],
+ cpu_gpr_d[r2], &tcg_gen_and_tl);
+ break;
+ case OPC2_32_RR_AND_GE:
+ gen_accumulating_cond(TCG_COND_GE, cpu_gpr_d[r3], cpu_gpr_d[r1],
+ cpu_gpr_d[r2], &tcg_gen_and_tl);
+ break;
+ case OPC2_32_RR_AND_GE_U:
+ gen_accumulating_cond(TCG_COND_GEU, cpu_gpr_d[r3], cpu_gpr_d[r1],
+ cpu_gpr_d[r2], &tcg_gen_and_tl);
+ break;
+ case OPC2_32_RR_AND_LT:
+ gen_accumulating_cond(TCG_COND_LT, cpu_gpr_d[r3], cpu_gpr_d[r1],
+ cpu_gpr_d[r2], &tcg_gen_and_tl);
+ break;
+ case OPC2_32_RR_AND_LT_U:
+ gen_accumulating_cond(TCG_COND_LTU, cpu_gpr_d[r3], cpu_gpr_d[r1],
+ cpu_gpr_d[r2], &tcg_gen_and_tl);
+ break;
+ case OPC2_32_RR_AND_NE:
+ gen_accumulating_cond(TCG_COND_NE, cpu_gpr_d[r3], cpu_gpr_d[r1],
+ cpu_gpr_d[r2], &tcg_gen_and_tl);
+ break;
+ case OPC2_32_RR_EQ:
+ tcg_gen_setcond_tl(TCG_COND_EQ, cpu_gpr_d[r3], cpu_gpr_d[r1],
+ cpu_gpr_d[r2]);
+ break;
+ case OPC2_32_RR_EQ_B:
+ gen_helper_eq_b(cpu_gpr_d[r3], cpu_gpr_d[r1], cpu_gpr_d[r2]);
+ break;
+ case OPC2_32_RR_EQ_H:
+ gen_helper_eq_h(cpu_gpr_d[r3], cpu_gpr_d[r1], cpu_gpr_d[r2]);
+ break;
+ case OPC2_32_RR_EQ_W:
+ gen_cond_w(TCG_COND_EQ, cpu_gpr_d[r3], cpu_gpr_d[r1], cpu_gpr_d[r2]);
+ break;
+ case OPC2_32_RR_EQANY_B:
+ gen_helper_eqany_b(cpu_gpr_d[r3], cpu_gpr_d[r1], cpu_gpr_d[r2]);
+ break;
+ case OPC2_32_RR_EQANY_H:
+ gen_helper_eqany_h(cpu_gpr_d[r3], cpu_gpr_d[r1], cpu_gpr_d[r2]);
+ break;
+ case OPC2_32_RR_GE:
+ tcg_gen_setcond_tl(TCG_COND_GE, cpu_gpr_d[r3], cpu_gpr_d[r1],
+ cpu_gpr_d[r2]);
+ break;
+ case OPC2_32_RR_GE_U:
+ tcg_gen_setcond_tl(TCG_COND_GEU, cpu_gpr_d[r3], cpu_gpr_d[r1],
+ cpu_gpr_d[r2]);
+ break;
+ case OPC2_32_RR_LT:
+ tcg_gen_setcond_tl(TCG_COND_LT, cpu_gpr_d[r3], cpu_gpr_d[r1],
+ cpu_gpr_d[r2]);
+ break;
+ case OPC2_32_RR_LT_U:
+ tcg_gen_setcond_tl(TCG_COND_LTU, cpu_gpr_d[r3], cpu_gpr_d[r1],
+ cpu_gpr_d[r2]);
+ break;
+ case OPC2_32_RR_LT_B:
+ gen_helper_lt_b(cpu_gpr_d[r3], cpu_gpr_d[r1], cpu_gpr_d[r2]);
+ break;
+ case OPC2_32_RR_LT_BU:
+ gen_helper_lt_bu(cpu_gpr_d[r3], cpu_gpr_d[r1], cpu_gpr_d[r2]);
+ break;
+ case OPC2_32_RR_LT_H:
+ gen_helper_lt_h(cpu_gpr_d[r3], cpu_gpr_d[r1], cpu_gpr_d[r2]);
+ break;
+ case OPC2_32_RR_LT_HU:
+ gen_helper_lt_hu(cpu_gpr_d[r3], cpu_gpr_d[r1], cpu_gpr_d[r2]);
+ break;
+ case OPC2_32_RR_LT_W:
+ gen_cond_w(TCG_COND_LT, cpu_gpr_d[r3], cpu_gpr_d[r1], cpu_gpr_d[r2]);
+ break;
+ case OPC2_32_RR_LT_WU:
+ gen_cond_w(TCG_COND_LTU, cpu_gpr_d[r3], cpu_gpr_d[r1], cpu_gpr_d[r2]);
+ break;
+ case OPC2_32_RR_MAX:
+ tcg_gen_movcond_tl(TCG_COND_GT, cpu_gpr_d[r3], cpu_gpr_d[r1],
+ cpu_gpr_d[r2], cpu_gpr_d[r1], cpu_gpr_d[r2]);
+ break;
+ case OPC2_32_RR_MAX_U:
+ tcg_gen_movcond_tl(TCG_COND_GTU, cpu_gpr_d[r3], cpu_gpr_d[r1],
+ cpu_gpr_d[r2], cpu_gpr_d[r1], cpu_gpr_d[r2]);
+ break;
+ case OPC2_32_RR_MAX_B:
+ gen_helper_max_b(cpu_gpr_d[r3], cpu_gpr_d[r1], cpu_gpr_d[r2]);
+ break;
+ case OPC2_32_RR_MAX_BU:
+ gen_helper_max_bu(cpu_gpr_d[r3], cpu_gpr_d[r1], cpu_gpr_d[r2]);
+ break;
+ case OPC2_32_RR_MAX_H:
+ gen_helper_max_h(cpu_gpr_d[r3], cpu_gpr_d[r1], cpu_gpr_d[r2]);
+ break;
+ case OPC2_32_RR_MAX_HU:
+ gen_helper_max_hu(cpu_gpr_d[r3], cpu_gpr_d[r1], cpu_gpr_d[r2]);
+ break;
+ case OPC2_32_RR_MIN:
+ tcg_gen_movcond_tl(TCG_COND_LT, cpu_gpr_d[r3], cpu_gpr_d[r1],
+ cpu_gpr_d[r2], cpu_gpr_d[r1], cpu_gpr_d[r2]);
+ break;
+ case OPC2_32_RR_MIN_U:
+ tcg_gen_movcond_tl(TCG_COND_LTU, cpu_gpr_d[r3], cpu_gpr_d[r1],
+ cpu_gpr_d[r2], cpu_gpr_d[r1], cpu_gpr_d[r2]);
+ break;
+ case OPC2_32_RR_MIN_B:
+ gen_helper_min_b(cpu_gpr_d[r3], cpu_gpr_d[r1], cpu_gpr_d[r2]);
+ break;
+ case OPC2_32_RR_MIN_BU:
+ gen_helper_min_bu(cpu_gpr_d[r3], cpu_gpr_d[r1], cpu_gpr_d[r2]);
+ break;
+ case OPC2_32_RR_MIN_H:
+ gen_helper_min_h(cpu_gpr_d[r3], cpu_gpr_d[r1], cpu_gpr_d[r2]);
+ break;
+ case OPC2_32_RR_MIN_HU:
+ gen_helper_min_hu(cpu_gpr_d[r3], cpu_gpr_d[r1], cpu_gpr_d[r2]);
+ break;
+ case OPC2_32_RR_MOV:
+ tcg_gen_mov_tl(cpu_gpr_d[r3], cpu_gpr_d[r2]);
+ break;
+ case OPC2_32_RR_NE:
+ tcg_gen_setcond_tl(TCG_COND_NE, cpu_gpr_d[r3], cpu_gpr_d[r1],
+ cpu_gpr_d[r2]);
+ break;
+ case OPC2_32_RR_OR_EQ:
+ gen_accumulating_cond(TCG_COND_EQ, cpu_gpr_d[r3], cpu_gpr_d[r1],
+ cpu_gpr_d[r2], &tcg_gen_or_tl);
+ break;
+ case OPC2_32_RR_OR_GE:
+ gen_accumulating_cond(TCG_COND_GE, cpu_gpr_d[r3], cpu_gpr_d[r1],
+ cpu_gpr_d[r2], &tcg_gen_or_tl);
+ break;
+ case OPC2_32_RR_OR_GE_U:
+ gen_accumulating_cond(TCG_COND_GEU, cpu_gpr_d[r3], cpu_gpr_d[r1],
+ cpu_gpr_d[r2], &tcg_gen_or_tl);
+ break;
+ case OPC2_32_RR_OR_LT:
+ gen_accumulating_cond(TCG_COND_LT, cpu_gpr_d[r3], cpu_gpr_d[r1],
+ cpu_gpr_d[r2], &tcg_gen_or_tl);
+ break;
+ case OPC2_32_RR_OR_LT_U:
+ gen_accumulating_cond(TCG_COND_LTU, cpu_gpr_d[r3], cpu_gpr_d[r1],
+ cpu_gpr_d[r2], &tcg_gen_or_tl);
+ break;
+ case OPC2_32_RR_OR_NE:
+ gen_accumulating_cond(TCG_COND_NE, cpu_gpr_d[r3], cpu_gpr_d[r1],
+ cpu_gpr_d[r2], &tcg_gen_or_tl);
+ break;
+ case OPC2_32_RR_SAT_B:
+ gen_saturate(cpu_gpr_d[r3], cpu_gpr_d[r1], 0x7f, -0x80);
+ break;
+ case OPC2_32_RR_SAT_BU:
+ gen_saturate_u(cpu_gpr_d[r3], cpu_gpr_d[r1], 0xff);
+ break;
+ case OPC2_32_RR_SAT_H:
+ gen_saturate(cpu_gpr_d[r3], cpu_gpr_d[r1], 0x7fff, -0x8000);
+ break;
+ case OPC2_32_RR_SAT_HU:
+ gen_saturate_u(cpu_gpr_d[r3], cpu_gpr_d[r1], 0xffff);
+ break;
+ case OPC2_32_RR_SH_EQ:
+ gen_sh_cond(TCG_COND_EQ, cpu_gpr_d[r3], cpu_gpr_d[r1],
+ cpu_gpr_d[r2]);
+ break;
+ case OPC2_32_RR_SH_GE:
+ gen_sh_cond(TCG_COND_GE, cpu_gpr_d[r3], cpu_gpr_d[r1],
+ cpu_gpr_d[r2]);
+ break;
+ case OPC2_32_RR_SH_GE_U:
+ gen_sh_cond(TCG_COND_GEU, cpu_gpr_d[r3], cpu_gpr_d[r1],
+ cpu_gpr_d[r2]);
+ break;
+ case OPC2_32_RR_SH_LT:
+ gen_sh_cond(TCG_COND_LT, cpu_gpr_d[r3], cpu_gpr_d[r1],
+ cpu_gpr_d[r2]);
+ break;
+ case OPC2_32_RR_SH_LT_U:
+ gen_sh_cond(TCG_COND_LTU, cpu_gpr_d[r3], cpu_gpr_d[r1],
+ cpu_gpr_d[r2]);
+ break;
+ case OPC2_32_RR_SH_NE:
+ gen_sh_cond(TCG_COND_NE, cpu_gpr_d[r3], cpu_gpr_d[r1],
+ cpu_gpr_d[r2]);
+ break;
+ case OPC2_32_RR_SUB:
+ gen_sub_d(cpu_gpr_d[r3], cpu_gpr_d[r1], cpu_gpr_d[r2]);
+ break;
+ case OPC2_32_RR_SUB_B:
+ gen_helper_sub_b(cpu_gpr_d[r3], cpu_env, cpu_gpr_d[r1], cpu_gpr_d[r2]);
+ break;
+ case OPC2_32_RR_SUB_H:
+ gen_helper_sub_h(cpu_gpr_d[r3], cpu_env, cpu_gpr_d[r1], cpu_gpr_d[r2]);
+ break;
+ case OPC2_32_RR_SUBC:
+ gen_subc_CC(cpu_gpr_d[r3], cpu_gpr_d[r1], cpu_gpr_d[r2]);
+ break;
+ case OPC2_32_RR_SUBS:
+ gen_subs(cpu_gpr_d[r3], cpu_gpr_d[r1], cpu_gpr_d[r2]);
+ break;
+ case OPC2_32_RR_SUBS_U:
+ gen_subsu(cpu_gpr_d[r3], cpu_gpr_d[r1], cpu_gpr_d[r2]);
+ break;
+ case OPC2_32_RR_SUBS_H:
+ gen_helper_sub_h_ssov(cpu_gpr_d[r3], cpu_env, cpu_gpr_d[r1],
+ cpu_gpr_d[r2]);
+ break;
+ case OPC2_32_RR_SUBS_HU:
+ gen_helper_sub_h_suov(cpu_gpr_d[r3], cpu_env, cpu_gpr_d[r1],
+ cpu_gpr_d[r2]);
+ break;
+ case OPC2_32_RR_SUBX:
+ gen_sub_CC(cpu_gpr_d[r3], cpu_gpr_d[r1], cpu_gpr_d[r2]);
+ break;
+ case OPC2_32_RR_XOR_EQ:
+ gen_accumulating_cond(TCG_COND_EQ, cpu_gpr_d[r3], cpu_gpr_d[r1],
+ cpu_gpr_d[r2], &tcg_gen_xor_tl);
+ break;
+ case OPC2_32_RR_XOR_GE:
+ gen_accumulating_cond(TCG_COND_GE, cpu_gpr_d[r3], cpu_gpr_d[r1],
+ cpu_gpr_d[r2], &tcg_gen_xor_tl);
+ break;
+ case OPC2_32_RR_XOR_GE_U:
+ gen_accumulating_cond(TCG_COND_GEU, cpu_gpr_d[r3], cpu_gpr_d[r1],
+ cpu_gpr_d[r2], &tcg_gen_xor_tl);
+ break;
+ case OPC2_32_RR_XOR_LT:
+ gen_accumulating_cond(TCG_COND_LT, cpu_gpr_d[r3], cpu_gpr_d[r1],
+ cpu_gpr_d[r2], &tcg_gen_xor_tl);
+ break;
+ case OPC2_32_RR_XOR_LT_U:
+ gen_accumulating_cond(TCG_COND_LTU, cpu_gpr_d[r3], cpu_gpr_d[r1],
+ cpu_gpr_d[r2], &tcg_gen_xor_tl);
+ break;
+ case OPC2_32_RR_XOR_NE:
+ gen_accumulating_cond(TCG_COND_NE, cpu_gpr_d[r3], cpu_gpr_d[r1],
+ cpu_gpr_d[r2], &tcg_gen_xor_tl);
+ break;
+ }
+}
+
+static void decode_rr_logical_shift(CPUTriCoreState *env, DisasContext *ctx)
+{
+ uint32_t op2;
+ int r3, r2, r1;
+ TCGv temp;
+
+ r3 = MASK_OP_RR_D(ctx->opcode);
+ r2 = MASK_OP_RR_S2(ctx->opcode);
+ r1 = MASK_OP_RR_S1(ctx->opcode);
+
+ temp = tcg_temp_new();
+ op2 = MASK_OP_RR_OP2(ctx->opcode);
+
+ switch (op2) {
+ case OPC2_32_RR_AND:
+ tcg_gen_and_tl(cpu_gpr_d[r3], cpu_gpr_d[r1], cpu_gpr_d[r2]);
+ break;
+ case OPC2_32_RR_ANDN:
+ tcg_gen_andc_tl(cpu_gpr_d[r3], cpu_gpr_d[r1], cpu_gpr_d[r2]);
+ break;
+ case OPC2_32_RR_CLO:
+ gen_helper_clo(cpu_gpr_d[r3], cpu_gpr_d[r1]);
+ break;
+ case OPC2_32_RR_CLO_H:
+ gen_helper_clo_h(cpu_gpr_d[r3], cpu_gpr_d[r1]);
+ break;
+ case OPC2_32_RR_CLS:
+ gen_helper_cls(cpu_gpr_d[r3], cpu_gpr_d[r1]);
+ break;
+ case OPC2_32_RR_CLS_H:
+ gen_helper_cls_h(cpu_gpr_d[r3], cpu_gpr_d[r1]);
+ break;
+ case OPC2_32_RR_CLZ:
+ gen_helper_clz(cpu_gpr_d[r3], cpu_gpr_d[r1]);
+ break;
+ case OPC2_32_RR_CLZ_H:
+ gen_helper_clz_h(cpu_gpr_d[r3], cpu_gpr_d[r1]);
+ break;
+ case OPC2_32_RR_NAND:
+ tcg_gen_nand_tl(cpu_gpr_d[r3], cpu_gpr_d[r1], cpu_gpr_d[r2]);
+ break;
+ case OPC2_32_RR_NOR:
+ tcg_gen_nor_tl(cpu_gpr_d[r3], cpu_gpr_d[r1], cpu_gpr_d[r2]);
+ break;
+ case OPC2_32_RR_OR:
+ tcg_gen_or_tl(cpu_gpr_d[r3], cpu_gpr_d[r1], cpu_gpr_d[r2]);
+ break;
+ case OPC2_32_RR_ORN:
+ tcg_gen_orc_tl(cpu_gpr_d[r3], cpu_gpr_d[r1], cpu_gpr_d[r2]);
+ break;
+ case OPC2_32_RR_SH:
+ gen_helper_sh(cpu_gpr_d[r3], cpu_gpr_d[r1], cpu_gpr_d[r2]);
+ break;
+ case OPC2_32_RR_SH_H:
+ gen_helper_sh_h(cpu_gpr_d[r3], cpu_gpr_d[r1], cpu_gpr_d[r2]);
+ break;
+ case OPC2_32_RR_SHA:
+ gen_helper_sha(cpu_gpr_d[r3], cpu_env, cpu_gpr_d[r1], cpu_gpr_d[r2]);
+ break;
+ case OPC2_32_RR_SHA_H:
+ gen_helper_sha_h(cpu_gpr_d[r3], cpu_gpr_d[r1], cpu_gpr_d[r2]);
+ break;
+ case OPC2_32_RR_SHAS:
+ gen_shas(cpu_gpr_d[r3], cpu_gpr_d[r1], cpu_gpr_d[r2]);
+ break;
+ case OPC2_32_RR_XNOR:
+ tcg_gen_eqv_tl(cpu_gpr_d[r3], cpu_gpr_d[r1], cpu_gpr_d[r2]);
+ break;
+ case OPC2_32_RR_XOR:
+ tcg_gen_xor_tl(cpu_gpr_d[r3], cpu_gpr_d[r1], cpu_gpr_d[r2]);
+ break;
+ }
+ tcg_temp_free(temp);
+}
+
+static void decode_rr_address(CPUTriCoreState *env, DisasContext *ctx)
+{
+ uint32_t op2, n;
+ int r1, r2, r3;
+ TCGv temp;
+
+ op2 = MASK_OP_RR_OP2(ctx->opcode);
+ r3 = MASK_OP_RR_D(ctx->opcode);
+ r2 = MASK_OP_RR_S2(ctx->opcode);
+ r1 = MASK_OP_RR_S1(ctx->opcode);
+ n = MASK_OP_RR_N(ctx->opcode);
+
+ switch (op2) {
+ case OPC2_32_RR_ADD_A:
+ tcg_gen_add_tl(cpu_gpr_a[r3], cpu_gpr_a[r1], cpu_gpr_a[r2]);
+ break;
+ case OPC2_32_RR_ADDSC_A:
+ temp = tcg_temp_new();
+ tcg_gen_shli_tl(temp, cpu_gpr_d[r1], n);
+ tcg_gen_add_tl(cpu_gpr_a[r3], cpu_gpr_a[r2], temp);
+ tcg_temp_free(temp);
+ break;
+ case OPC2_32_RR_ADDSC_AT:
+ temp = tcg_temp_new();
+ tcg_gen_sari_tl(temp, cpu_gpr_d[r1], 3);
+ tcg_gen_add_tl(temp, cpu_gpr_a[r2], temp);
+ tcg_gen_andi_tl(cpu_gpr_a[r3], temp, 0xFFFFFFFC);
+ tcg_temp_free(temp);
+ break;
+ case OPC2_32_RR_EQ_A:
+ tcg_gen_setcond_tl(TCG_COND_EQ, cpu_gpr_d[r3], cpu_gpr_a[r1],
+ cpu_gpr_a[r2]);
+ break;
+ case OPC2_32_RR_EQZ:
+ tcg_gen_setcondi_tl(TCG_COND_EQ, cpu_gpr_d[r3], cpu_gpr_a[r1], 0);
+ break;
+ case OPC2_32_RR_GE_A:
+ tcg_gen_setcond_tl(TCG_COND_GEU, cpu_gpr_d[r3], cpu_gpr_a[r1],
+ cpu_gpr_a[r2]);
+ break;
+ case OPC2_32_RR_LT_A:
+ tcg_gen_setcond_tl(TCG_COND_LTU, cpu_gpr_d[r3], cpu_gpr_a[r1],
+ cpu_gpr_a[r2]);
+ break;
+ case OPC2_32_RR_MOV_A:
+ tcg_gen_mov_tl(cpu_gpr_a[r3], cpu_gpr_d[r2]);
+ break;
+ case OPC2_32_RR_MOV_AA:
+ tcg_gen_mov_tl(cpu_gpr_a[r3], cpu_gpr_a[r2]);
+ break;
+ case OPC2_32_RR_MOV_D:
+ tcg_gen_mov_tl(cpu_gpr_d[r3], cpu_gpr_a[r2]);
+ break;
+ case OPC2_32_RR_NE_A:
+ tcg_gen_setcond_tl(TCG_COND_NE, cpu_gpr_d[r3], cpu_gpr_a[r1],
+ cpu_gpr_a[r2]);
+ break;
+ case OPC2_32_RR_NEZ_A:
+ tcg_gen_setcondi_tl(TCG_COND_NE, cpu_gpr_d[r3], cpu_gpr_a[r1], 0);
+ break;
+ case OPC2_32_RR_SUB_A:
+ tcg_gen_sub_tl(cpu_gpr_a[r3], cpu_gpr_a[r1], cpu_gpr_a[r2]);
+ break;
+ }
+}
+
+static void decode_rr_idirect(CPUTriCoreState *env, DisasContext *ctx)
+{
+ uint32_t op2;
+ int r1;
+
+ op2 = MASK_OP_RR_OP2(ctx->opcode);
+ r1 = MASK_OP_RR_S1(ctx->opcode);
+
+ switch (op2) {
+ case OPC2_32_RR_JI:
+ tcg_gen_andi_tl(cpu_PC, cpu_gpr_a[r1], ~0x1);
+ break;
+ case OPC2_32_RR_JLI:
+ tcg_gen_movi_tl(cpu_gpr_a[11], ctx->next_pc);
+ tcg_gen_andi_tl(cpu_PC, cpu_gpr_a[r1], ~0x1);
+ break;
+ case OPC2_32_RR_CALLI:
+ gen_helper_1arg(call, ctx->next_pc);
+ tcg_gen_andi_tl(cpu_PC, cpu_gpr_a[r1], ~0x1);
+ break;
+ }
+ tcg_gen_exit_tb(0);
+ ctx->bstate = BS_BRANCH;
+}
+
+static void decode_rr_divide(CPUTriCoreState *env, DisasContext *ctx)
+{
+ uint32_t op2;
+ int r1, r2, r3;
+
+ TCGv temp, temp2;
+
+ op2 = MASK_OP_RR_OP2(ctx->opcode);
+ r3 = MASK_OP_RR_D(ctx->opcode);
+ r2 = MASK_OP_RR_S2(ctx->opcode);
+ r1 = MASK_OP_RR_S1(ctx->opcode);
+
+ switch (op2) {
+ case OPC2_32_RR_BMERGE:
+ gen_helper_bmerge(cpu_gpr_d[r3], cpu_gpr_d[r1], cpu_gpr_d[r2]);
+ break;
+ case OPC2_32_RR_BSPLIT:
+ gen_bsplit(cpu_gpr_d[r3], cpu_gpr_d[r3+1], cpu_gpr_d[r1]);
+ break;
+ case OPC2_32_RR_DVINIT_B:
+ gen_dvinit_b(env, cpu_gpr_d[r3], cpu_gpr_d[r3+1], cpu_gpr_d[r1],
+ cpu_gpr_d[r2]);
+ break;
+ case OPC2_32_RR_DVINIT_BU:
+ temp = tcg_temp_new();
+ temp2 = tcg_temp_new();
+ /* reset av */
+ tcg_gen_movi_tl(cpu_PSW_AV, 0);
+ if (!tricore_feature(env, TRICORE_FEATURE_131)) {
+ /* overflow = (abs(D[r3+1]) >= abs(D[r2])) */
+ tcg_gen_neg_tl(temp, cpu_gpr_d[r3+1]);
+ /* use cpu_PSW_AV to compare against 0 */
+ tcg_gen_movcond_tl(TCG_COND_LT, temp, cpu_gpr_d[r3+1], cpu_PSW_AV,
+ temp, cpu_gpr_d[r3+1]);
+ tcg_gen_neg_tl(temp2, cpu_gpr_d[r2]);
+ tcg_gen_movcond_tl(TCG_COND_LT, temp2, cpu_gpr_d[r2], cpu_PSW_AV,
+ temp2, cpu_gpr_d[r2]);
+ tcg_gen_setcond_tl(TCG_COND_GE, cpu_PSW_V, temp, temp2);
+ } else {
+ /* overflow = (D[b] == 0) */
+ tcg_gen_setcondi_tl(TCG_COND_EQ, cpu_PSW_V, cpu_gpr_d[r2], 0);
+ }
+ tcg_gen_shli_tl(cpu_PSW_V, cpu_PSW_V, 31);
+ /* sv */
+ tcg_gen_or_tl(cpu_PSW_SV, cpu_PSW_SV, cpu_PSW_V);
+ /* write result */
+ tcg_gen_shri_tl(temp, cpu_gpr_d[r1], 8);
+ tcg_gen_shli_tl(cpu_gpr_d[r3], cpu_gpr_d[r1], 24);
+ tcg_gen_mov_tl(cpu_gpr_d[r3+1], temp);
+
+ tcg_temp_free(temp);
+ tcg_temp_free(temp2);
+ break;
+ case OPC2_32_RR_DVINIT_H:
+ gen_dvinit_h(env, cpu_gpr_d[r3], cpu_gpr_d[r3+1], cpu_gpr_d[r1],
+ cpu_gpr_d[r2]);
+ break;
+ case OPC2_32_RR_DVINIT_HU:
+ temp = tcg_temp_new();
+ temp2 = tcg_temp_new();
+ /* reset av */
+ tcg_gen_movi_tl(cpu_PSW_AV, 0);
+ if (!tricore_feature(env, TRICORE_FEATURE_131)) {
+ /* overflow = (abs(D[r3+1]) >= abs(D[r2])) */
+ tcg_gen_neg_tl(temp, cpu_gpr_d[r3+1]);
+ /* use cpu_PSW_AV to compare against 0 */
+ tcg_gen_movcond_tl(TCG_COND_LT, temp, cpu_gpr_d[r3+1], cpu_PSW_AV,
+ temp, cpu_gpr_d[r3+1]);
+ tcg_gen_neg_tl(temp2, cpu_gpr_d[r2]);
+ tcg_gen_movcond_tl(TCG_COND_LT, temp2, cpu_gpr_d[r2], cpu_PSW_AV,
+ temp2, cpu_gpr_d[r2]);
+ tcg_gen_setcond_tl(TCG_COND_GE, cpu_PSW_V, temp, temp2);
+ } else {
+ /* overflow = (D[b] == 0) */
+ tcg_gen_setcondi_tl(TCG_COND_EQ, cpu_PSW_V, cpu_gpr_d[r2], 0);
+ }
+ tcg_gen_shli_tl(cpu_PSW_V, cpu_PSW_V, 31);
+ /* sv */
+ tcg_gen_or_tl(cpu_PSW_SV, cpu_PSW_SV, cpu_PSW_V);
+ /* write result */
+ tcg_gen_mov_tl(temp, cpu_gpr_d[r1]);
+ tcg_gen_shri_tl(cpu_gpr_d[r3+1], temp, 16);
+ tcg_gen_shli_tl(cpu_gpr_d[r3], temp, 16);
+ tcg_temp_free(temp);
+ tcg_temp_free(temp2);
+ break;
+ case OPC2_32_RR_DVINIT:
+ temp = tcg_temp_new();
+ temp2 = tcg_temp_new();
+ /* overflow = ((D[b] == 0) ||
+ ((D[b] == 0xFFFFFFFF) && (D[a] == 0x80000000))) */
+ tcg_gen_setcondi_tl(TCG_COND_EQ, temp, cpu_gpr_d[r2], 0xffffffff);
+ tcg_gen_setcondi_tl(TCG_COND_EQ, temp2, cpu_gpr_d[r1], 0x80000000);
+ tcg_gen_and_tl(temp, temp, temp2);
+ tcg_gen_setcondi_tl(TCG_COND_EQ, temp2, cpu_gpr_d[r2], 0);
+ tcg_gen_or_tl(cpu_PSW_V, temp, temp2);
+ tcg_gen_shli_tl(cpu_PSW_V, cpu_PSW_V, 31);
+ /* sv */
+ tcg_gen_or_tl(cpu_PSW_SV, cpu_PSW_SV, cpu_PSW_V);
+ /* reset av */
+ tcg_gen_movi_tl(cpu_PSW_AV, 0);
+ /* write result */
+ tcg_gen_mov_tl(cpu_gpr_d[r3], cpu_gpr_d[r1]);
+ /* sign extend to high reg */
+ tcg_gen_sari_tl(cpu_gpr_d[r3+1], cpu_gpr_d[r1], 31);
+ tcg_temp_free(temp);
+ tcg_temp_free(temp2);
+ break;
+ case OPC2_32_RR_DVINIT_U:
+ /* overflow = (D[b] == 0) */
+ tcg_gen_setcondi_tl(TCG_COND_EQ, cpu_PSW_V, cpu_gpr_d[r2], 0);
+ tcg_gen_shli_tl(cpu_PSW_V, cpu_PSW_V, 31);
+ /* sv */
+ tcg_gen_or_tl(cpu_PSW_SV, cpu_PSW_SV, cpu_PSW_V);
+ /* reset av */
+ tcg_gen_movi_tl(cpu_PSW_AV, 0);
+ /* write result */
+ tcg_gen_mov_tl(cpu_gpr_d[r3], cpu_gpr_d[r1]);
+ /* zero extend to high reg*/
+ tcg_gen_movi_tl(cpu_gpr_d[r3+1], 0);
+ break;
+ case OPC2_32_RR_PARITY:
+ gen_helper_parity(cpu_gpr_d[r3], cpu_gpr_d[r1]);
+ break;
+ case OPC2_32_RR_UNPACK:
+ gen_unpack(cpu_gpr_d[r3], cpu_gpr_d[r3+1], cpu_gpr_d[r1]);
+ break;
+ }
+}
+
+/* RR1 Format */
+static void decode_rr1_mul(CPUTriCoreState *env, DisasContext *ctx)
+{
+ uint32_t op2;
+
+ int r1, r2, r3;
+ TCGv n;
+ TCGv_i64 temp64;
+
+ r1 = MASK_OP_RR1_S1(ctx->opcode);
+ r2 = MASK_OP_RR1_S2(ctx->opcode);
+ r3 = MASK_OP_RR1_D(ctx->opcode);
+ n = tcg_const_i32(MASK_OP_RR1_N(ctx->opcode));
+ op2 = MASK_OP_RR1_OP2(ctx->opcode);
+
+ switch (op2) {
+ case OPC2_32_RR1_MUL_H_32_LL:
+ temp64 = tcg_temp_new_i64();
+ GEN_HELPER_LL(mul_h, temp64, cpu_gpr_d[r1], cpu_gpr_d[r2], n);
+ tcg_gen_extr_i64_i32(cpu_gpr_d[r3], cpu_gpr_d[r3+1], temp64);
+ gen_calc_usb_mul_h(cpu_gpr_d[r3], cpu_gpr_d[r3+1]);
+ tcg_temp_free_i64(temp64);
+ break;
+ case OPC2_32_RR1_MUL_H_32_LU:
+ temp64 = tcg_temp_new_i64();
+ GEN_HELPER_LU(mul_h, temp64, cpu_gpr_d[r1], cpu_gpr_d[r2], n);
+ tcg_gen_extr_i64_i32(cpu_gpr_d[r3], cpu_gpr_d[r3+1], temp64);
+ gen_calc_usb_mul_h(cpu_gpr_d[r3], cpu_gpr_d[r3+1]);
+ tcg_temp_free_i64(temp64);
+ break;
+ case OPC2_32_RR1_MUL_H_32_UL:
+ temp64 = tcg_temp_new_i64();
+ GEN_HELPER_UL(mul_h, temp64, cpu_gpr_d[r1], cpu_gpr_d[r2], n);
+ tcg_gen_extr_i64_i32(cpu_gpr_d[r3], cpu_gpr_d[r3+1], temp64);
+ gen_calc_usb_mul_h(cpu_gpr_d[r3], cpu_gpr_d[r3+1]);
+ tcg_temp_free_i64(temp64);
+ break;
+ case OPC2_32_RR1_MUL_H_32_UU:
+ temp64 = tcg_temp_new_i64();
+ GEN_HELPER_UU(mul_h, temp64, cpu_gpr_d[r1], cpu_gpr_d[r2], n);
+ tcg_gen_extr_i64_i32(cpu_gpr_d[r3], cpu_gpr_d[r3+1], temp64);
+ gen_calc_usb_mul_h(cpu_gpr_d[r3], cpu_gpr_d[r3+1]);
+ tcg_temp_free_i64(temp64);
+ break;
+ case OPC2_32_RR1_MULM_H_64_LL:
+ temp64 = tcg_temp_new_i64();
+ GEN_HELPER_LL(mulm_h, temp64, cpu_gpr_d[r1], cpu_gpr_d[r2], n);
+ tcg_gen_extr_i64_i32(cpu_gpr_d[r3], cpu_gpr_d[r3+1], temp64);
+ /* reset V bit */
+ tcg_gen_movi_tl(cpu_PSW_V, 0);
+ /* reset AV bit */
+ tcg_gen_mov_tl(cpu_PSW_AV, cpu_PSW_V);
+ tcg_temp_free_i64(temp64);
+ break;
+ case OPC2_32_RR1_MULM_H_64_LU:
+ temp64 = tcg_temp_new_i64();
+ GEN_HELPER_LU(mulm_h, temp64, cpu_gpr_d[r1], cpu_gpr_d[r2], n);
+ tcg_gen_extr_i64_i32(cpu_gpr_d[r3], cpu_gpr_d[r3+1], temp64);
+ /* reset V bit */
+ tcg_gen_movi_tl(cpu_PSW_V, 0);
+ /* reset AV bit */
+ tcg_gen_mov_tl(cpu_PSW_AV, cpu_PSW_V);
+ tcg_temp_free_i64(temp64);
+ break;
+ case OPC2_32_RR1_MULM_H_64_UL:
+ temp64 = tcg_temp_new_i64();
+ GEN_HELPER_UL(mulm_h, temp64, cpu_gpr_d[r1], cpu_gpr_d[r2], n);
+ tcg_gen_extr_i64_i32(cpu_gpr_d[r3], cpu_gpr_d[r3+1], temp64);
+ /* reset V bit */
+ tcg_gen_movi_tl(cpu_PSW_V, 0);
+ /* reset AV bit */
+ tcg_gen_mov_tl(cpu_PSW_AV, cpu_PSW_V);
+ tcg_temp_free_i64(temp64);
+ break;
+ case OPC2_32_RR1_MULM_H_64_UU:
+ temp64 = tcg_temp_new_i64();
+ GEN_HELPER_UU(mulm_h, temp64, cpu_gpr_d[r1], cpu_gpr_d[r2], n);
+ tcg_gen_extr_i64_i32(cpu_gpr_d[r3], cpu_gpr_d[r3+1], temp64);
+ /* reset V bit */
+ tcg_gen_movi_tl(cpu_PSW_V, 0);
+ /* reset AV bit */
+ tcg_gen_mov_tl(cpu_PSW_AV, cpu_PSW_V);
+ tcg_temp_free_i64(temp64);
+
+ break;
+ case OPC2_32_RR1_MULR_H_16_LL:
+ GEN_HELPER_LL(mulr_h, cpu_gpr_d[r3], cpu_gpr_d[r1], cpu_gpr_d[r2], n);
+ gen_calc_usb_mulr_h(cpu_gpr_d[r3]);
+ break;
+ case OPC2_32_RR1_MULR_H_16_LU:
+ GEN_HELPER_LU(mulr_h, cpu_gpr_d[r3], cpu_gpr_d[r1], cpu_gpr_d[r2], n);
+ gen_calc_usb_mulr_h(cpu_gpr_d[r3]);
+ break;
+ case OPC2_32_RR1_MULR_H_16_UL:
+ GEN_HELPER_UL(mulr_h, cpu_gpr_d[r3], cpu_gpr_d[r1], cpu_gpr_d[r2], n);
+ gen_calc_usb_mulr_h(cpu_gpr_d[r3]);
+ break;
+ case OPC2_32_RR1_MULR_H_16_UU:
+ GEN_HELPER_UU(mulr_h, cpu_gpr_d[r3], cpu_gpr_d[r1], cpu_gpr_d[r2], n);
+ gen_calc_usb_mulr_h(cpu_gpr_d[r3]);
+ break;
+ }
+ tcg_temp_free(n);
+}
+
static void decode_32Bit_opc(CPUTriCoreState *env, DisasContext *ctx)
{
int op1;
@@ -3808,8 +4789,8 @@ static void decode_32Bit_opc(CPUTriCoreState *env, DisasContext *ctx)
op1 = MASK_OP_MAJOR(ctx->opcode);
- /* handle JNZ.T opcode only being 6 bit long */
- if (unlikely((op1 & 0x3f) == OPCM_32_BRN_JTT)) {
+ /* handle JNZ.T opcode only being 7 bit long */
+ if (unlikely((op1 & 0x7f) == OPCM_32_BRN_JTT)) {
op1 = OPCM_32_BRN_JTT;
}
@@ -3884,7 +4865,7 @@ static void decode_32Bit_opc(CPUTriCoreState *env, DisasContext *ctx)
case OPC1_32_B_JA:
case OPC1_32_B_JL:
case OPC1_32_B_JLA:
- address = MASK_OP_B_DISP24(ctx->opcode);
+ address = MASK_OP_B_DISP24_SEXT(ctx->opcode);
gen_compute_branch(ctx, op1, 0, 0, 0, address);
break;
/* Bit-format */
@@ -3930,10 +4911,16 @@ static void decode_32Bit_opc(CPUTriCoreState *env, DisasContext *ctx)
break;
/* BOL-format */
case OPC1_32_BOL_LD_A_LONGOFF:
- case OPC1_32_BOL_LD_W_LONFOFF:
+ case OPC1_32_BOL_LD_W_LONGOFF:
case OPC1_32_BOL_LEA_LONGOFF:
case OPC1_32_BOL_ST_W_LONGOFF:
case OPC1_32_BOL_ST_A_LONGOFF:
+ case OPC1_32_BOL_LD_B_LONGOFF:
+ case OPC1_32_BOL_LD_BU_LONGOFF:
+ case OPC1_32_BOL_LD_H_LONGOFF:
+ case OPC1_32_BOL_LD_HU_LONGOFF:
+ case OPC1_32_BOL_ST_B_LONGOFF:
+ case OPC1_32_BOL_ST_H_LONGOFF:
decode_bol_opc(env, ctx, op1);
break;
/* BRC Format */
@@ -4021,12 +5008,33 @@ static void decode_32Bit_opc(CPUTriCoreState *env, DisasContext *ctx)
case OPC1_32_RLC_ADDIH_A:
case OPC1_32_RLC_MFCR:
case OPC1_32_RLC_MOV:
+ case OPC1_32_RLC_MOV_64:
case OPC1_32_RLC_MOV_U:
case OPC1_32_RLC_MOV_H:
case OPC1_32_RLC_MOVH_A:
case OPC1_32_RLC_MTCR:
decode_rlc_opc(env, ctx, op1);
break;
+/* RR Format */
+ case OPCM_32_RR_ACCUMULATOR:
+ decode_rr_accumulator(env, ctx);
+ break;
+ case OPCM_32_RR_LOGICAL_SHIFT:
+ decode_rr_logical_shift(env, ctx);
+ break;
+ case OPCM_32_RR_ADRESS:
+ decode_rr_address(env, ctx);
+ break;
+ case OPCM_32_RR_IDIRECT:
+ decode_rr_idirect(env, ctx);
+ break;
+ case OPCM_32_RR_DIVIDE:
+ decode_rr_divide(env, ctx);
+ break;
+/* RR1 Format */
+ case OPCM_32_RR1_MUL:
+ decode_rr1_mul(env, ctx);
+ break;
}
}
diff --git a/target-tricore/tricore-opcodes.h b/target-tricore/tricore-opcodes.h
index 0a9122cfb9..919063e422 100644
--- a/target-tricore/tricore-opcodes.h
+++ b/target-tricore/tricore-opcodes.h
@@ -94,6 +94,8 @@
/* B Format */
#define MASK_OP_B_DISP24(op) (MASK_BITS_SHIFT(op, 16, 31) + \
(MASK_BITS_SHIFT(op, 8, 15) << 16))
+#define MASK_OP_B_DISP24_SEXT(op) (MASK_BITS_SHIFT(op, 16, 31) + \
+ (MASK_BITS_SHIFT_SEXT(op, 8, 15) << 16))
/* BIT Format */
#define MASK_OP_BIT_D(op) MASK_BITS_SHIFT(op, 28, 31)
#define MASK_OP_BIT_POS2(op) MASK_BITS_SHIFT(op, 23, 27)
@@ -114,7 +116,7 @@
/* BOL Format */
#define MASK_OP_BOL_OFF16(op) ((MASK_BITS_SHIFT(op, 16, 21) + \
(MASK_BITS_SHIFT(op, 28, 31) << 6)) + \
- (MASK_BITS_SHIFT(op, 22, 27) >> 10))
+ (MASK_BITS_SHIFT(op, 22, 27) << 10))
#define MASK_OP_BOL_OFF16_SEXT(op) ((MASK_BITS_SHIFT(op, 16, 21) + \
(MASK_BITS_SHIFT(op, 28, 31) << 6)) + \
(MASK_BITS_SHIFT_SEXT(op, 22, 27) << 10))
@@ -447,10 +449,16 @@ enum {
OPCM_32_BO_ADDRMODE_LDMST_BITREVERSE_CIRCULAR = 0x69,
/* BOL Format */
OPC1_32_BOL_LD_A_LONGOFF = 0x99,
- OPC1_32_BOL_LD_W_LONFOFF = 0x19,
+ OPC1_32_BOL_LD_W_LONGOFF = 0x19,
OPC1_32_BOL_LEA_LONGOFF = 0xd9,
OPC1_32_BOL_ST_W_LONGOFF = 0x59,
OPC1_32_BOL_ST_A_LONGOFF = 0xb5, /* 1.6 only */
+ OPC1_32_BOL_LD_B_LONGOFF = 0x79, /* 1.6 only */
+ OPC1_32_BOL_LD_BU_LONGOFF = 0x39, /* 1.6 only */
+ OPC1_32_BOL_LD_H_LONGOFF = 0xc9, /* 1.6 only */
+ OPC1_32_BOL_LD_HU_LONGOFF = 0xb9, /* 1.6 only */
+ OPC1_32_BOL_ST_B_LONGOFF = 0xe9, /* 1.6 only */
+ OPC1_32_BOL_ST_H_LONGOFF = 0xf9, /* 1.6 only */
/* BRC Format */
OPCM_32_BRC_EQ_NEQ = 0xdf,
OPCM_32_BRC_GE = 0xff,
@@ -487,6 +495,7 @@ enum {
OPC1_32_RLC_ADDIH_A = 0x11,
OPC1_32_RLC_MFCR = 0x4d,
OPC1_32_RLC_MOV = 0x3b,
+ OPC1_32_RLC_MOV_64 = 0xfb, /* 1.6 only */
OPC1_32_RLC_MOV_U = 0xbb,
OPC1_32_RLC_MOV_H = 0x7b,
OPC1_32_RLC_MOVH_A = 0x91,
@@ -495,7 +504,7 @@ enum {
OPCM_32_RR_LOGICAL_SHIFT = 0x0f,
OPCM_32_RR_ACCUMULATOR = 0x0b,
OPCM_32_RR_ADRESS = 0x01,
- OPCM_32_RR_FLOAT = 0x4b,
+ OPCM_32_RR_DIVIDE = 0x4b,
OPCM_32_RR_IDIRECT = 0x2d,
/* RR1 Format */
OPCM_32_RR1_MUL = 0xb3,
@@ -1033,8 +1042,8 @@ enum {
OPC2_32_RR_MAX_BU = 0x5b,
OPC2_32_RR_MAX_H = 0x7a,
OPC2_32_RR_MAX_HU = 0x7b,
- OPC2_32_RR_MIN = 0x19,
- OPC2_32_RR_MIN_U = 0x18,
+ OPC2_32_RR_MIN = 0x18,
+ OPC2_32_RR_MIN_U = 0x19,
OPC2_32_RR_MIN_B = 0x58,
OPC2_32_RR_MIN_BU = 0x59,
OPC2_32_RR_MIN_H = 0x78,
diff --git a/ui/Makefile.objs b/ui/Makefile.objs
index 801cba2675..13b5cfbe41 100644
--- a/ui/Makefile.objs
+++ b/ui/Makefile.objs
@@ -16,7 +16,12 @@ common-obj-$(CONFIG_CURSES) += curses.o
common-obj-$(CONFIG_VNC) += $(vnc-obj-y)
common-obj-$(CONFIG_GTK) += gtk.o x_keymap.o
-sdl.mo-objs := sdl.o sdl_zoom.o sdl2.o
+ifeq ($(CONFIG_SDLABI),1.2)
+sdl.mo-objs := sdl.o sdl_zoom.o
+endif
+ifeq ($(CONFIG_SDLABI),2.0)
+sdl.mo-objs := sdl2.o sdl2-input.o sdl2-2d.o
+endif
sdl.mo-cflags := $(SDL_CFLAGS)
gtk.o-cflags := $(GTK_CFLAGS) $(VTE_CFLAGS)
diff --git a/ui/sdl.c b/ui/sdl.c
index 94c1d9dc3a..3e9d81076b 100644
--- a/ui/sdl.c
+++ b/ui/sdl.c
@@ -26,8 +26,6 @@
#undef WIN32_LEAN_AND_MEAN
#include <SDL.h>
-
-#if SDL_MAJOR_VERSION == 1
#include <SDL_syswm.h>
#include "qemu-common.h"
@@ -958,4 +956,3 @@ void sdl_display_init(DisplayState *ds, int full_screen, int no_frame)
atexit(sdl_cleanup);
}
-#endif
diff --git a/ui/sdl2-2d.c b/ui/sdl2-2d.c
new file mode 100644
index 0000000000..9264817e76
--- /dev/null
+++ b/ui/sdl2-2d.c
@@ -0,0 +1,122 @@
+/*
+ * QEMU SDL display driver
+ *
+ * Copyright (c) 2003 Fabrice Bellard
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+/* Ported SDL 1.2 code to 2.0 by Dave Airlie. */
+
+/* Avoid compiler warning because macro is redefined in SDL_syswm.h. */
+#undef WIN32_LEAN_AND_MEAN
+
+#include <SDL.h>
+#include <SDL_syswm.h>
+
+#include "qemu-common.h"
+#include "ui/console.h"
+#include "ui/input.h"
+#include "ui/sdl2.h"
+#include "sysemu/sysemu.h"
+
+void sdl2_2d_update(DisplayChangeListener *dcl,
+ int x, int y, int w, int h)
+{
+ struct sdl2_console *scon = container_of(dcl, struct sdl2_console, dcl);
+ DisplaySurface *surf = qemu_console_surface(dcl->con);
+ SDL_Rect rect;
+
+ if (!surf) {
+ return;
+ }
+ if (!scon->texture) {
+ return;
+ }
+
+ rect.x = x;
+ rect.y = y;
+ rect.w = w;
+ rect.h = h;
+
+ SDL_UpdateTexture(scon->texture, NULL, surface_data(surf),
+ surface_stride(surf));
+ SDL_RenderCopy(scon->real_renderer, scon->texture, &rect, &rect);
+ SDL_RenderPresent(scon->real_renderer);
+}
+
+void sdl2_2d_switch(DisplayChangeListener *dcl,
+ DisplaySurface *new_surface)
+{
+ struct sdl2_console *scon = container_of(dcl, struct sdl2_console, dcl);
+ DisplaySurface *old_surface = scon->surface;
+ int format = 0;
+
+ scon->surface = new_surface;
+
+ if (scon->texture) {
+ SDL_DestroyTexture(scon->texture);
+ scon->texture = NULL;
+ }
+
+ if (!new_surface) {
+ sdl2_window_destroy(scon);
+ return;
+ }
+
+ if (!scon->real_window) {
+ sdl2_window_create(scon);
+ } else if (old_surface &&
+ ((surface_width(old_surface) != surface_width(new_surface)) ||
+ (surface_height(old_surface) != surface_height(new_surface)))) {
+ sdl2_window_resize(scon);
+ }
+
+ SDL_RenderSetLogicalSize(scon->real_renderer,
+ surface_width(new_surface),
+ surface_height(new_surface));
+
+ if (surface_bits_per_pixel(scon->surface) == 16) {
+ format = SDL_PIXELFORMAT_RGB565;
+ } else if (surface_bits_per_pixel(scon->surface) == 32) {
+ format = SDL_PIXELFORMAT_ARGB8888;
+ }
+ scon->texture = SDL_CreateTexture(scon->real_renderer, format,
+ SDL_TEXTUREACCESS_STREAMING,
+ surface_width(new_surface),
+ surface_height(new_surface));
+ sdl2_2d_redraw(scon);
+}
+
+void sdl2_2d_refresh(DisplayChangeListener *dcl)
+{
+ struct sdl2_console *scon = container_of(dcl, struct sdl2_console, dcl);
+
+ graphic_hw_update(dcl->con);
+ sdl2_poll_events(scon);
+}
+
+void sdl2_2d_redraw(struct sdl2_console *scon)
+{
+ if (!scon->surface) {
+ return;
+ }
+ sdl2_2d_update(&scon->dcl, 0, 0,
+ surface_width(scon->surface),
+ surface_height(scon->surface));
+}
diff --git a/ui/sdl2-input.c b/ui/sdl2-input.c
new file mode 100644
index 0000000000..a1973fc2e0
--- /dev/null
+++ b/ui/sdl2-input.c
@@ -0,0 +1,106 @@
+/*
+ * QEMU SDL display driver
+ *
+ * Copyright (c) 2003 Fabrice Bellard
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+/* Ported SDL 1.2 code to 2.0 by Dave Airlie. */
+
+/* Avoid compiler warning because macro is redefined in SDL_syswm.h. */
+#undef WIN32_LEAN_AND_MEAN
+
+#include <SDL.h>
+#include <SDL_syswm.h>
+
+#include "qemu-common.h"
+#include "ui/console.h"
+#include "ui/input.h"
+#include "ui/sdl2.h"
+#include "sysemu/sysemu.h"
+
+#include "sdl2-keymap.h"
+
+static uint8_t modifiers_state[SDL_NUM_SCANCODES];
+
+void sdl2_reset_keys(struct sdl2_console *scon)
+{
+ QemuConsole *con = scon ? scon->dcl.con : NULL;
+ int i;
+
+ for (i = 0; i < SDL_NUM_SCANCODES; i++) {
+ if (modifiers_state[i]) {
+ int qcode = sdl2_scancode_to_qcode[i];
+ qemu_input_event_send_key_qcode(con, qcode, false);
+ modifiers_state[i] = 0;
+ }
+ }
+}
+
+void sdl2_process_key(struct sdl2_console *scon,
+ SDL_KeyboardEvent *ev)
+{
+ int qcode = sdl2_scancode_to_qcode[ev->keysym.scancode];
+ QemuConsole *con = scon ? scon->dcl.con : NULL;
+
+ if (!qemu_console_is_graphic(con)) {
+ if (ev->type == SDL_KEYDOWN) {
+ switch (ev->keysym.scancode) {
+ case SDL_SCANCODE_RETURN:
+ kbd_put_keysym_console(con, '\n');
+ break;
+ case SDL_SCANCODE_BACKSPACE:
+ kbd_put_keysym_console(con, QEMU_KEY_BACKSPACE);
+ break;
+ default:
+ kbd_put_qcode_console(con, qcode);
+ break;
+ }
+ }
+ return;
+ }
+
+ switch (ev->keysym.scancode) {
+#if 0
+ case SDL_SCANCODE_NUMLOCKCLEAR:
+ case SDL_SCANCODE_CAPSLOCK:
+ /* SDL does not send the key up event, so we generate it */
+ qemu_input_event_send_key_qcode(con, qcode, true);
+ qemu_input_event_send_key_qcode(con, qcode, false);
+ return;
+#endif
+ case SDL_SCANCODE_LCTRL:
+ case SDL_SCANCODE_LSHIFT:
+ case SDL_SCANCODE_LALT:
+ case SDL_SCANCODE_LGUI:
+ case SDL_SCANCODE_RCTRL:
+ case SDL_SCANCODE_RSHIFT:
+ case SDL_SCANCODE_RALT:
+ case SDL_SCANCODE_RGUI:
+ if (ev->type == SDL_KEYUP) {
+ modifiers_state[ev->keysym.scancode] = 0;
+ } else {
+ modifiers_state[ev->keysym.scancode] = 1;
+ }
+ /* fall though */
+ default:
+ qemu_input_event_send_key_qcode(con, qcode,
+ ev->type == SDL_KEYDOWN);
+ }
+}
diff --git a/ui/sdl2.c b/ui/sdl2.c
index 1ad74baafc..1ae2781624 100644
--- a/ui/sdl2.c
+++ b/ui/sdl2.c
@@ -27,55 +27,37 @@
#undef WIN32_LEAN_AND_MEAN
#include <SDL.h>
-
-#if SDL_MAJOR_VERSION == 2
#include <SDL_syswm.h>
#include "qemu-common.h"
#include "ui/console.h"
#include "ui/input.h"
+#include "ui/sdl2.h"
#include "sysemu/sysemu.h"
-#include "sdl2-keymap.h"
-
static int sdl2_num_outputs;
-static struct sdl2_state {
- DisplayChangeListener dcl;
- DisplaySurface *surface;
- SDL_Texture *texture;
- SDL_Window *real_window;
- SDL_Renderer *real_renderer;
- int idx;
- int last_vm_running; /* per console for caption reasons */
- int x, y;
- int hidden;
-} *sdl2_console;
+static struct sdl2_console *sdl2_console;
static SDL_Surface *guest_sprite_surface;
static int gui_grab; /* if true, all keyboard/mouse events are grabbed */
-static bool gui_saved_scaling;
-static int gui_saved_width;
-static int gui_saved_height;
static int gui_saved_grab;
static int gui_fullscreen;
static int gui_noframe;
static int gui_key_modifier_pressed;
static int gui_keysym;
static int gui_grab_code = KMOD_LALT | KMOD_LCTRL;
-static uint8_t modifiers_state[SDL_NUM_SCANCODES];
static SDL_Cursor *sdl_cursor_normal;
static SDL_Cursor *sdl_cursor_hidden;
static int absolute_enabled;
static int guest_cursor;
static int guest_x, guest_y;
static SDL_Cursor *guest_sprite;
-static int scaling_active;
static Notifier mouse_mode_notifier;
-static void sdl_update_caption(struct sdl2_state *scon);
+static void sdl_update_caption(struct sdl2_console *scon);
-static struct sdl2_state *get_scon_from_window(uint32_t window_id)
+static struct sdl2_console *get_scon_from_window(uint32_t window_id)
{
int i;
for (i = 0; i < sdl2_num_outputs; i++) {
@@ -86,180 +68,57 @@ static struct sdl2_state *get_scon_from_window(uint32_t window_id)
return NULL;
}
-static void sdl_update(DisplayChangeListener *dcl,
- int x, int y, int w, int h)
+void sdl2_window_create(struct sdl2_console *scon)
{
- struct sdl2_state *scon = container_of(dcl, struct sdl2_state, dcl);
- SDL_Rect rect;
- DisplaySurface *surf = qemu_console_surface(dcl->con);
+ int flags = 0;
- if (!surf) {
+ if (!scon->surface) {
return;
}
- if (!scon->texture) {
- return;
- }
-
- rect.x = x;
- rect.y = y;
- rect.w = w;
- rect.h = h;
-
- SDL_UpdateTexture(scon->texture, NULL, surface_data(surf),
- surface_stride(surf));
- SDL_RenderCopy(scon->real_renderer, scon->texture, &rect, &rect);
- SDL_RenderPresent(scon->real_renderer);
-}
-
-static void do_sdl_resize(struct sdl2_state *scon, int width, int height,
- int bpp)
-{
- int flags;
-
- if (scon->real_window && scon->real_renderer) {
- if (width && height) {
- SDL_RenderSetLogicalSize(scon->real_renderer, width, height);
- SDL_SetWindowSize(scon->real_window, width, height);
- } else {
- SDL_DestroyRenderer(scon->real_renderer);
- SDL_DestroyWindow(scon->real_window);
- scon->real_renderer = NULL;
- scon->real_window = NULL;
- }
- } else {
- if (!width || !height) {
- return;
- }
- flags = 0;
- if (gui_fullscreen) {
- flags |= SDL_WINDOW_FULLSCREEN;
- } else {
- flags |= SDL_WINDOW_RESIZABLE;
- }
- if (scon->hidden) {
- flags |= SDL_WINDOW_HIDDEN;
- }
-
- scon->real_window = SDL_CreateWindow("", SDL_WINDOWPOS_UNDEFINED,
- SDL_WINDOWPOS_UNDEFINED,
- width, height, flags);
- scon->real_renderer = SDL_CreateRenderer(scon->real_window, -1, 0);
- sdl_update_caption(scon);
- }
-}
-
-static void sdl_switch(DisplayChangeListener *dcl,
- DisplaySurface *new_surface)
-{
- struct sdl2_state *scon = container_of(dcl, struct sdl2_state, dcl);
- int format = 0;
- int idx = scon->idx;
- DisplaySurface *old_surface = scon->surface;
-
- /* temporary hack: allows to call sdl_switch to handle scaling changes */
- if (new_surface) {
- scon->surface = new_surface;
- }
-
- if (!new_surface && idx > 0) {
- scon->surface = NULL;
- }
+ assert(!scon->real_window);
- if (new_surface == NULL) {
- do_sdl_resize(scon, 0, 0, 0);
+ if (gui_fullscreen) {
+ flags |= SDL_WINDOW_FULLSCREEN_DESKTOP;
} else {
- do_sdl_resize(scon, surface_width(scon->surface),
- surface_height(scon->surface), 0);
+ flags |= SDL_WINDOW_RESIZABLE;
}
-
- if (old_surface && scon->texture) {
- SDL_DestroyTexture(scon->texture);
- scon->texture = NULL;
+ if (scon->hidden) {
+ flags |= SDL_WINDOW_HIDDEN;
}
- if (new_surface) {
- if (!scon->texture) {
- if (surface_bits_per_pixel(scon->surface) == 16) {
- format = SDL_PIXELFORMAT_RGB565;
- } else if (surface_bits_per_pixel(scon->surface) == 32) {
- format = SDL_PIXELFORMAT_ARGB8888;
- }
-
- scon->texture = SDL_CreateTexture(scon->real_renderer, format,
- SDL_TEXTUREACCESS_STREAMING,
- surface_width(new_surface),
- surface_height(new_surface));
- }
- }
+ scon->real_window = SDL_CreateWindow("", SDL_WINDOWPOS_UNDEFINED,
+ SDL_WINDOWPOS_UNDEFINED,
+ surface_width(scon->surface),
+ surface_height(scon->surface),
+ flags);
+ scon->real_renderer = SDL_CreateRenderer(scon->real_window, -1, 0);
+ sdl_update_caption(scon);
}
-static void reset_keys(struct sdl2_state *scon)
+void sdl2_window_destroy(struct sdl2_console *scon)
{
- QemuConsole *con = scon ? scon->dcl.con : NULL;
- int i;
-
- for (i = 0; i < 256; i++) {
- if (modifiers_state[i]) {
- int qcode = sdl2_scancode_to_qcode[i];
- qemu_input_event_send_key_qcode(con, qcode, false);
- modifiers_state[i] = 0;
- }
+ if (!scon->real_window) {
+ return;
}
+
+ SDL_DestroyRenderer(scon->real_renderer);
+ scon->real_renderer = NULL;
+ SDL_DestroyWindow(scon->real_window);
+ scon->real_window = NULL;
}
-static void sdl_process_key(struct sdl2_state *scon,
- SDL_KeyboardEvent *ev)
+void sdl2_window_resize(struct sdl2_console *scon)
{
- int qcode = sdl2_scancode_to_qcode[ev->keysym.scancode];
- QemuConsole *con = scon ? scon->dcl.con : NULL;
-
- if (!qemu_console_is_graphic(con)) {
- if (ev->type == SDL_KEYDOWN) {
- switch (ev->keysym.scancode) {
- case SDL_SCANCODE_RETURN:
- kbd_put_keysym_console(con, '\n');
- break;
- case SDL_SCANCODE_BACKSPACE:
- kbd_put_keysym_console(con, QEMU_KEY_BACKSPACE);
- break;
- default:
- kbd_put_qcode_console(con, qcode);
- break;
- }
- }
+ if (!scon->real_window) {
return;
}
- switch (ev->keysym.scancode) {
-#if 0
- case SDL_SCANCODE_NUMLOCKCLEAR:
- case SDL_SCANCODE_CAPSLOCK:
- /* SDL does not send the key up event, so we generate it */
- qemu_input_event_send_key_qcode(con, qcode, true);
- qemu_input_event_send_key_qcode(con, qcode, false);
- return;
-#endif
- case SDL_SCANCODE_LCTRL:
- case SDL_SCANCODE_LSHIFT:
- case SDL_SCANCODE_LALT:
- case SDL_SCANCODE_LGUI:
- case SDL_SCANCODE_RCTRL:
- case SDL_SCANCODE_RSHIFT:
- case SDL_SCANCODE_RALT:
- case SDL_SCANCODE_RGUI:
- if (ev->type == SDL_KEYUP) {
- modifiers_state[ev->keysym.scancode] = 0;
- } else {
- modifiers_state[ev->keysym.scancode] = 1;
- }
- /* fall though */
- default:
- qemu_input_event_send_key_qcode(con, qcode,
- ev->type == SDL_KEYDOWN);
- }
+ SDL_SetWindowSize(scon->real_window,
+ surface_width(scon->surface),
+ surface_height(scon->surface));
}
-static void sdl_update_caption(struct sdl2_state *scon)
+static void sdl_update_caption(struct sdl2_console *scon)
{
char win_title[1024];
char icon_title[1024];
@@ -269,11 +128,11 @@ static void sdl_update_caption(struct sdl2_state *scon)
status = " [Stopped]";
} else if (gui_grab) {
if (alt_grab) {
- status = " - Press Ctrl-Alt-Shift to exit mouse grab";
+ status = " - Press Ctrl-Alt-Shift to exit grab";
} else if (ctrl_grab) {
- status = " - Press Right-Ctrl to exit mouse grab";
+ status = " - Press Right-Ctrl to exit grab";
} else {
- status = " - Press Ctrl-Alt to exit mouse grab";
+ status = " - Press Ctrl-Alt to exit grab";
}
}
@@ -323,7 +182,7 @@ static void sdl_show_cursor(void)
}
}
-static void sdl_grab_start(struct sdl2_state *scon)
+static void sdl_grab_start(struct sdl2_console *scon)
{
QemuConsole *con = scon ? scon->dcl.con : NULL;
@@ -351,7 +210,7 @@ static void sdl_grab_start(struct sdl2_state *scon)
sdl_update_caption(scon);
}
-static void sdl_grab_end(struct sdl2_state *scon)
+static void sdl_grab_end(struct sdl2_console *scon)
{
SDL_SetWindowGrab(scon->real_window, SDL_FALSE);
gui_grab = 0;
@@ -359,7 +218,7 @@ static void sdl_grab_end(struct sdl2_state *scon)
sdl_update_caption(scon);
}
-static void absolute_mouse_grab(struct sdl2_state *scon)
+static void absolute_mouse_grab(struct sdl2_console *scon)
{
int mouse_x, mouse_y;
int scr_w, scr_h;
@@ -386,7 +245,7 @@ static void sdl_mouse_mode_change(Notifier *notify, void *data)
}
}
-static void sdl_send_mouse_event(struct sdl2_state *scon, int dx, int dy,
+static void sdl_send_mouse_event(struct sdl2_console *scon, int dx, int dy,
int x, int y, int state)
{
static uint32_t bmap[INPUT_BUTTON_MAX] = {
@@ -409,7 +268,7 @@ static void sdl_send_mouse_event(struct sdl2_state *scon, int dx, int dy,
int i;
for (i = 0; i < sdl2_num_outputs; i++) {
- struct sdl2_state *thiscon = &sdl2_console[i];
+ struct sdl2_console *thiscon = &sdl2_console[i];
if (thiscon->real_window && thiscon->surface) {
SDL_GetWindowSize(thiscon->real_window, &scr_w, &scr_h);
cur_off_x = thiscon->x;
@@ -443,48 +302,27 @@ static void sdl_send_mouse_event(struct sdl2_state *scon, int dx, int dy,
qemu_input_event_sync();
}
-static void sdl_scale(struct sdl2_state *scon, int width, int height)
-{
- int bpp = 0;
- do_sdl_resize(scon, width, height, bpp);
- scaling_active = 1;
-}
-
-static void toggle_full_screen(struct sdl2_state *scon)
+static void toggle_full_screen(struct sdl2_console *scon)
{
- int width = surface_width(scon->surface);
- int height = surface_height(scon->surface);
- int bpp = surface_bits_per_pixel(scon->surface);
-
gui_fullscreen = !gui_fullscreen;
if (gui_fullscreen) {
- SDL_GetWindowSize(scon->real_window,
- &gui_saved_width, &gui_saved_height);
- gui_saved_scaling = scaling_active;
-
- do_sdl_resize(scon, width, height, bpp);
- scaling_active = 0;
-
+ SDL_SetWindowFullscreen(scon->real_window,
+ SDL_WINDOW_FULLSCREEN_DESKTOP);
gui_saved_grab = gui_grab;
sdl_grab_start(scon);
} else {
- if (gui_saved_scaling) {
- sdl_scale(scon, gui_saved_width, gui_saved_height);
- } else {
- do_sdl_resize(scon, width, height, 0);
- }
if (!gui_saved_grab) {
sdl_grab_end(scon);
}
+ SDL_SetWindowFullscreen(scon->real_window, 0);
}
- graphic_hw_invalidate(scon->dcl.con);
- graphic_hw_update(scon->dcl.con);
+ sdl2_2d_redraw(scon);
}
static void handle_keydown(SDL_Event *ev)
{
int mod_state, win;
- struct sdl2_state *scon = get_scon_from_window(ev->key.windowID);
+ struct sdl2_console *scon = get_scon_from_window(ev->key.windowID);
if (alt_grab) {
mod_state = (SDL_GetModState() & (gui_grab_code | KMOD_LSHIFT)) ==
@@ -524,14 +362,13 @@ static void handle_keydown(SDL_Event *ev)
gui_keysym = 1;
break;
case SDL_SCANCODE_U:
- if (scaling_active) {
- scaling_active = 0;
- sdl_switch(&scon->dcl, NULL);
- graphic_hw_invalidate(scon->dcl.con);
- graphic_hw_update(scon->dcl.con);
- }
+ sdl2_window_destroy(scon);
+ sdl2_window_create(scon);
+ /* re-create texture */
+ sdl2_2d_switch(&scon->dcl, scon->surface);
gui_keysym = 1;
break;
+#if 0
case SDL_SCANCODE_KP_PLUS:
case SDL_SCANCODE_KP_MINUS:
if (!gui_fullscreen) {
@@ -544,25 +381,26 @@ static void handle_keydown(SDL_Event *ev)
160);
height = (surface_height(scon->surface) * width) /
surface_width(scon->surface);
-
+ fprintf(stderr, "%s: scale to %dx%d\n",
+ __func__, width, height);
sdl_scale(scon, width, height);
- graphic_hw_invalidate(NULL);
- graphic_hw_update(NULL);
+ sdl2_2d_redraw(scon);
gui_keysym = 1;
}
+#endif
default:
break;
}
}
if (!gui_keysym) {
- sdl_process_key(scon, &ev->key);
+ sdl2_process_key(scon, &ev->key);
}
}
static void handle_keyup(SDL_Event *ev)
{
int mod_state;
- struct sdl2_state *scon = get_scon_from_window(ev->key.windowID);
+ struct sdl2_console *scon = get_scon_from_window(ev->key.windowID);
if (!alt_grab) {
mod_state = (ev->key.keysym.mod & gui_grab_code);
@@ -580,19 +418,19 @@ static void handle_keyup(SDL_Event *ev)
}
/* SDL does not send back all the modifiers key, so we must
* correct it. */
- reset_keys(scon);
+ sdl2_reset_keys(scon);
return;
}
gui_keysym = 0;
}
if (!gui_keysym) {
- sdl_process_key(scon, &ev->key);
+ sdl2_process_key(scon, &ev->key);
}
}
static void handle_textinput(SDL_Event *ev)
{
- struct sdl2_state *scon = get_scon_from_window(ev->key.windowID);
+ struct sdl2_console *scon = get_scon_from_window(ev->key.windowID);
QemuConsole *con = scon ? scon->dcl.con : NULL;
if (qemu_console_is_graphic(con)) {
@@ -604,7 +442,7 @@ static void handle_textinput(SDL_Event *ev)
static void handle_mousemotion(SDL_Event *ev)
{
int max_x, max_y;
- struct sdl2_state *scon = get_scon_from_window(ev->key.windowID);
+ struct sdl2_console *scon = get_scon_from_window(ev->key.windowID);
if (qemu_input_is_absolute() || absolute_enabled) {
int scr_w, scr_h;
@@ -631,7 +469,7 @@ static void handle_mousebutton(SDL_Event *ev)
{
int buttonstate = SDL_GetMouseState(NULL, NULL);
SDL_MouseButtonEvent *bev;
- struct sdl2_state *scon = get_scon_from_window(ev->key.windowID);
+ struct sdl2_console *scon = get_scon_from_window(ev->key.windowID);
bev = &ev->button;
if (!gui_grab && !qemu_input_is_absolute()) {
@@ -651,7 +489,7 @@ static void handle_mousebutton(SDL_Event *ev)
static void handle_mousewheel(SDL_Event *ev)
{
- struct sdl2_state *scon = get_scon_from_window(ev->key.windowID);
+ struct sdl2_console *scon = get_scon_from_window(ev->key.windowID);
SDL_MouseWheelEvent *wev = &ev->wheel;
InputButton btn;
@@ -669,14 +507,12 @@ static void handle_mousewheel(SDL_Event *ev)
qemu_input_event_sync();
}
-static void handle_windowevent(DisplayChangeListener *dcl, SDL_Event *ev)
+static void handle_windowevent(SDL_Event *ev)
{
- int w, h;
- struct sdl2_state *scon = get_scon_from_window(ev->key.windowID);
+ struct sdl2_console *scon = get_scon_from_window(ev->window.windowID);
switch (ev->window.event) {
case SDL_WINDOWEVENT_RESIZED:
- sdl_scale(scon, ev->window.data1, ev->window.data2);
{
QemuUIInfo info;
memset(&info, 0, sizeof(info));
@@ -684,12 +520,10 @@ static void handle_windowevent(DisplayChangeListener *dcl, SDL_Event *ev)
info.height = ev->window.data2;
dpy_set_ui_info(scon->dcl.con, &info);
}
- graphic_hw_invalidate(scon->dcl.con);
- graphic_hw_update(scon->dcl.con);
+ sdl2_2d_redraw(scon);
break;
case SDL_WINDOWEVENT_EXPOSED:
- SDL_GetWindowSize(SDL_GetWindowFromID(ev->window.windowID), &w, &h);
- sdl_update(dcl, 0, 0, w, h);
+ sdl2_2d_redraw(scon);
break;
case SDL_WINDOWEVENT_FOCUS_GAINED:
case SDL_WINDOWEVENT_ENTER:
@@ -703,10 +537,10 @@ static void handle_windowevent(DisplayChangeListener *dcl, SDL_Event *ev)
}
break;
case SDL_WINDOWEVENT_RESTORED:
- update_displaychangelistener(dcl, GUI_REFRESH_INTERVAL_DEFAULT);
+ update_displaychangelistener(&scon->dcl, GUI_REFRESH_INTERVAL_DEFAULT);
break;
case SDL_WINDOWEVENT_MINIMIZED:
- update_displaychangelistener(dcl, 500);
+ update_displaychangelistener(&scon->dcl, 500);
break;
case SDL_WINDOWEVENT_CLOSE:
if (!no_quit) {
@@ -714,12 +548,21 @@ static void handle_windowevent(DisplayChangeListener *dcl, SDL_Event *ev)
qemu_system_shutdown_request();
}
break;
+ case SDL_WINDOWEVENT_SHOWN:
+ if (scon->hidden) {
+ SDL_HideWindow(scon->real_window);
+ }
+ break;
+ case SDL_WINDOWEVENT_HIDDEN:
+ if (!scon->hidden) {
+ SDL_ShowWindow(scon->real_window);
+ }
+ break;
}
}
-static void sdl_refresh(DisplayChangeListener *dcl)
+void sdl2_poll_events(struct sdl2_console *scon)
{
- struct sdl2_state *scon = container_of(dcl, struct sdl2_state, dcl);
SDL_Event ev1, *ev = &ev1;
if (scon->last_vm_running != runstate_is_running()) {
@@ -727,8 +570,6 @@ static void sdl_refresh(DisplayChangeListener *dcl)
sdl_update_caption(scon);
}
- graphic_hw_update(dcl->con);
-
while (SDL_PollEvent(ev)) {
switch (ev->type) {
case SDL_KEYDOWN:
@@ -757,7 +598,7 @@ static void sdl_refresh(DisplayChangeListener *dcl)
handle_mousewheel(ev);
break;
case SDL_WINDOWEVENT:
- handle_windowevent(dcl, ev);
+ handle_windowevent(ev);
break;
default:
break;
@@ -768,7 +609,7 @@ static void sdl_refresh(DisplayChangeListener *dcl)
static void sdl_mouse_warp(DisplayChangeListener *dcl,
int x, int y, int on)
{
- struct sdl2_state *scon = container_of(dcl, struct sdl2_state, dcl);
+ struct sdl2_console *scon = container_of(dcl, struct sdl2_console, dcl);
if (on) {
if (!guest_cursor) {
sdl_show_cursor();
@@ -826,11 +667,11 @@ static void sdl_cleanup(void)
SDL_QuitSubSystem(SDL_INIT_VIDEO);
}
-static const DisplayChangeListenerOps dcl_ops = {
- .dpy_name = "sdl",
- .dpy_gfx_update = sdl_update,
- .dpy_gfx_switch = sdl_switch,
- .dpy_refresh = sdl_refresh,
+static const DisplayChangeListenerOps dcl_2d_ops = {
+ .dpy_name = "sdl2-2d",
+ .dpy_gfx_update = sdl2_2d_update,
+ .dpy_gfx_switch = sdl2_2d_switch,
+ .dpy_refresh = sdl2_2d_refresh,
.dpy_mouse_set = sdl_mouse_warp,
.dpy_cursor_define = sdl_mouse_define,
};
@@ -865,6 +706,7 @@ void sdl_display_init(DisplayState *ds, int full_screen, int no_frame)
SDL_GetError());
exit(1);
}
+ SDL_SetHint(SDL_HINT_GRAB_KEYBOARD, "1");
for (i = 0;; i++) {
QemuConsole *con = qemu_console_lookup_by_index(i);
@@ -873,13 +715,13 @@ void sdl_display_init(DisplayState *ds, int full_screen, int no_frame)
}
}
sdl2_num_outputs = i;
- sdl2_console = g_new0(struct sdl2_state, sdl2_num_outputs);
+ sdl2_console = g_new0(struct sdl2_console, sdl2_num_outputs);
for (i = 0; i < sdl2_num_outputs; i++) {
QemuConsole *con = qemu_console_lookup_by_index(i);
if (!qemu_console_is_graphic(con)) {
sdl2_console[i].hidden = true;
}
- sdl2_console[i].dcl.ops = &dcl_ops;
+ sdl2_console[i].dcl.ops = &dcl_2d_ops;
sdl2_console[i].dcl.con = con;
register_displaychangelistener(&sdl2_console[i].dcl);
sdl2_console[i].idx = i;
@@ -912,4 +754,3 @@ void sdl_display_init(DisplayState *ds, int full_screen, int no_frame)
atexit(sdl_cleanup);
}
-#endif
diff --git a/vl.c b/vl.c
index 113e98e56b..a824a7d8b4 100644
--- a/vl.c
+++ b/vl.c
@@ -196,9 +196,6 @@ NodeInfo numa_info[MAX_NODES];
uint8_t qemu_uuid[16];
bool qemu_uuid_set;
-static QEMUBootSetHandler *boot_set_handler;
-static void *boot_set_opaque;
-
static NotifierList exit_notifiers =
NOTIFIER_LIST_INITIALIZER(exit_notifiers);
@@ -1198,65 +1195,6 @@ static void default_drive(int enable, int snapshot, BlockInterfaceType type,
}
-void qemu_register_boot_set(QEMUBootSetHandler *func, void *opaque)
-{
- boot_set_handler = func;
- boot_set_opaque = opaque;
-}
-
-int qemu_boot_set(const char *boot_order)
-{
- if (!boot_set_handler) {
- return -EINVAL;
- }
- return boot_set_handler(boot_set_opaque, boot_order);
-}
-
-static void validate_bootdevices(const char *devices)
-{
- /* We just do some generic consistency checks */
- const char *p;
- int bitmap = 0;
-
- for (p = devices; *p != '\0'; p++) {
- /* Allowed boot devices are:
- * a-b: floppy disk drives
- * c-f: IDE disk drives
- * g-m: machine implementation dependent drives
- * n-p: network devices
- * It's up to each machine implementation to check if the given boot
- * devices match the actual hardware implementation and firmware
- * features.
- */
- if (*p < 'a' || *p > 'p') {
- fprintf(stderr, "Invalid boot device '%c'\n", *p);
- exit(1);
- }
- if (bitmap & (1 << (*p - 'a'))) {
- fprintf(stderr, "Boot device '%c' was given twice\n", *p);
- exit(1);
- }
- bitmap |= 1 << (*p - 'a');
- }
-}
-
-static void restore_boot_order(void *opaque)
-{
- char *normal_boot_order = opaque;
- static int first = 1;
-
- /* Restore boot order and remove ourselves after the first boot */
- if (first) {
- first = 0;
- return;
- }
-
- qemu_boot_set(normal_boot_order);
-
- qemu_unregister_reset(restore_boot_order, normal_boot_order);
- g_free(normal_boot_order);
-}
-
static QemuOptsList qemu_smp_opts = {
.name = "smp-opts",
.implied_opt_name = "cpus",
@@ -4149,16 +4087,25 @@ int main(int argc, char **argv, char **envp)
if (opts) {
char *normal_boot_order;
const char *order, *once;
+ Error *local_err = NULL;
order = qemu_opt_get(opts, "order");
if (order) {
- validate_bootdevices(order);
+ validate_bootdevices(order, &local_err);
+ if (local_err) {
+ error_report("%s", error_get_pretty(local_err));
+ exit(1);
+ }
boot_order = order;
}
once = qemu_opt_get(opts, "once");
if (once) {
- validate_bootdevices(once);
+ validate_bootdevices(once, &local_err);
+ if (local_err) {
+ error_report("%s", error_get_pretty(local_err));
+ exit(1);
+ }
normal_boot_order = g_strdup(boot_order);
boot_order = once;
qemu_register_reset(restore_boot_order, normal_boot_order);