diff options
-rw-r--r-- | bootdevice.c | 73 | ||||
-rw-r--r-- | cpus.c | 3 | ||||
-rw-r--r-- | exec.c | 4 | ||||
-rw-r--r-- | hw/core/qdev-properties-system.c | 82 | ||||
-rw-r--r-- | hw/i386/pc.c | 22 | ||||
-rw-r--r-- | hw/net/e1000.c | 21 | ||||
-rw-r--r-- | hw/ppc/mac_newworld.c | 4 | ||||
-rw-r--r-- | hw/ppc/mac_oldworld.c | 5 | ||||
-rw-r--r-- | hw/sparc/sun4m.c | 4 | ||||
-rw-r--r-- | hw/sparc64/sun4u.c | 4 | ||||
-rw-r--r-- | include/hw/hw.h | 6 | ||||
-rw-r--r-- | include/sysemu/sysemu.h | 8 | ||||
-rw-r--r-- | include/ui/sdl2.h | 32 | ||||
-rw-r--r-- | monitor.c | 14 | ||||
-rw-r--r-- | net/l2tpv3.c | 9 | ||||
-rw-r--r-- | net/queue.c | 2 | ||||
-rw-r--r-- | net/slirp.c | 2 | ||||
-rw-r--r-- | net/tap.c | 12 | ||||
-rw-r--r-- | pc-bios/efi-e1000.rom | bin | 194560 -> 197120 bytes | |||
-rw-r--r-- | pc-bios/efi-eepro100.rom | bin | 196096 -> 197632 bytes | |||
-rw-r--r-- | pc-bios/efi-ne2k_pci.rom | bin | 194560 -> 195584 bytes | |||
-rw-r--r-- | pc-bios/efi-pcnet.rom | bin | 194560 -> 195584 bytes | |||
-rw-r--r-- | pc-bios/efi-rtl8139.rom | bin | 198144 -> 200192 bytes | |||
-rw-r--r-- | pc-bios/efi-virtio.rom | bin | 192000 -> 194048 bytes | |||
-rw-r--r-- | qom/cpu.c | 1 | ||||
m--------- | roms/ipxe | 0 | ||||
-rw-r--r-- | target-tricore/helper.h | 59 | ||||
-rw-r--r-- | target-tricore/op_helper.c | 1086 | ||||
-rw-r--r-- | target-tricore/translate.c | 1034 | ||||
-rw-r--r-- | target-tricore/tricore-opcodes.h | 19 | ||||
-rw-r--r-- | ui/Makefile.objs | 7 | ||||
-rw-r--r-- | ui/sdl.c | 3 | ||||
-rw-r--r-- | ui/sdl2-2d.c | 122 | ||||
-rw-r--r-- | ui/sdl2-input.c | 106 | ||||
-rw-r--r-- | ui/sdl2.c | 343 | ||||
-rw-r--r-- | vl.c | 75 |
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) { @@ -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); @@ -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 */ @@ -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); @@ -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 Binary files differindex 776e217a61..4e29d9d1ad 100644 --- a/pc-bios/efi-e1000.rom +++ b/pc-bios/efi-e1000.rom diff --git a/pc-bios/efi-eepro100.rom b/pc-bios/efi-eepro100.rom Binary files differindex 677a8c373e..2a92d6f32f 100644 --- a/pc-bios/efi-eepro100.rom +++ b/pc-bios/efi-eepro100.rom diff --git a/pc-bios/efi-ne2k_pci.rom b/pc-bios/efi-ne2k_pci.rom Binary files differindex 9dd6d91e31..6366017009 100644 --- a/pc-bios/efi-ne2k_pci.rom +++ b/pc-bios/efi-ne2k_pci.rom diff --git a/pc-bios/efi-pcnet.rom b/pc-bios/efi-pcnet.rom Binary files differindex cae3a85887..a61f586eeb 100644 --- a/pc-bios/efi-pcnet.rom +++ b/pc-bios/efi-pcnet.rom diff --git a/pc-bios/efi-rtl8139.rom b/pc-bios/efi-rtl8139.rom Binary files differindex 477f9b9b91..c9c77ea7f0 100644 --- a/pc-bios/efi-rtl8139.rom +++ b/pc-bios/efi-rtl8139.rom diff --git a/pc-bios/efi-virtio.rom b/pc-bios/efi-virtio.rom Binary files differindex 935c927400..eec2790990 100644 --- a/pc-bios/efi-virtio.rom +++ b/pc-bios/efi-virtio.rom @@ -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) @@ -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); + } +} @@ -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 @@ -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); |