Merge remote-tracking branch 'remotes/kraxel/tags/pull-usb-5' into staging
usb: mtp filesharing
# gpg: Signature made Wed 23 Apr 2014 09:28:37 BST using RSA key ID D3E87138
# gpg: Good signature from "Gerd Hoffmann (work) <kraxel@redhat.com>"
# gpg: aka "Gerd Hoffmann <gerd@kraxel.org>"
# gpg: aka "Gerd Hoffmann (private) <kraxel@gmail.com>"
* remotes/kraxel/tags/pull-usb-5:
usb: mtp filesharing
usb: add CompatibleID support to msos
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
diff --git a/configure b/configure
index 69b9f56..b08afc3 100755
--- a/configure
+++ b/configure
@@ -1217,8 +1217,8 @@
--enable-modules enable modules support
--enable-debug-tcg enable TCG debugging
--disable-debug-tcg disable TCG debugging (default)
- --enable-debug-info enable debugging information (default)
- --disable-debug-info disable debugging information
+ --enable-debug-info enable debugging information (default)
+ --disable-debug-info disable debugging information
--enable-debug enable common debug build options
--enable-sparse enable sparse checker
--disable-sparse disable sparse checker (default)
@@ -4095,7 +4095,6 @@
echo "strip binaries $strip_opt"
echo "profiler $profiler"
echo "static build $static"
-echo "-Werror enabled $werror"
if test "$darwin" = "yes" ; then
echo "Cocoa support $cocoa"
fi
diff --git a/hw/i2c/smbus_eeprom.c b/hw/i2c/smbus_eeprom.c
index 86f35c1..72c09cb 100644
--- a/hw/i2c/smbus_eeprom.c
+++ b/hw/i2c/smbus_eeprom.c
@@ -71,7 +71,7 @@
printf("eeprom_write_byte: addr=0x%02x cmd=0x%02x val=0x%02x\n",
dev->i2c.address, cmd, buf[0]);
#endif
- /* An page write operation is not a valid SMBus command.
+ /* A page write operation is not a valid SMBus command.
It is a block write without a length byte. Fortunately we
get the full block anyway. */
/* TODO: Should this set the current location? */
diff --git a/hw/ide/ahci.c b/hw/ide/ahci.c
index bfe633f..50327ff 100644
--- a/hw/ide/ahci.c
+++ b/hw/ide/ahci.c
@@ -438,9 +438,9 @@
if ((pr->cmd & PORT_CMD_START) && pr->cmd_issue) {
for (slot = 0; (slot < 32) && pr->cmd_issue; slot++) {
- if ((pr->cmd_issue & (1 << slot)) &&
+ if ((pr->cmd_issue & (1U << slot)) &&
!handle_cmd(s, port, slot)) {
- pr->cmd_issue &= ~(1 << slot);
+ pr->cmd_issue &= ~(1U << slot);
}
}
}
diff --git a/include/qemu/int128.h b/include/qemu/int128.h
index 9ed47aa..f597031 100644
--- a/include/qemu/int128.h
+++ b/include/qemu/int128.h
@@ -53,7 +53,7 @@
if (n >= 64) {
return (Int128) { h, h >> 63 };
} else {
- return (Int128) { (a.lo >> n) | (a.hi << (64 - n)), h };
+ return (Int128) { (a.lo >> n) | ((uint64_t)a.hi << (64 - n)), h };
}
}
@@ -78,7 +78,7 @@
static inline Int128 int128_sub(Int128 a, Int128 b)
{
- return (Int128){ a.lo - b.lo, a.hi - b.hi - (a.lo < b.lo) };
+ return (Int128){ a.lo - b.lo, (uint64_t)a.hi - b.hi - (a.lo < b.lo) };
}
static inline bool int128_nonneg(Int128 a)
diff --git a/net/net.c b/net/net.c
index e3ef1e4..a4aadff 100644
--- a/net/net.c
+++ b/net/net.c
@@ -952,10 +952,12 @@
nc = net_hub_find_client_by_name(vlan_id, device);
if (!nc) {
+ error_report("Host network device '%s' on hub '%d' not found",
+ device, vlan_id);
return;
}
if (!net_host_check_device(nc->model)) {
- monitor_printf(mon, "invalid host network device %s\n", device);
+ error_report("invalid host network device '%s'", device);
return;
}
qemu_del_net_client(nc);
diff --git a/qemu-doc.texi b/qemu-doc.texi
index e6e20eb..88ec9bb 100644
--- a/qemu-doc.texi
+++ b/qemu-doc.texi
@@ -823,7 +823,7 @@
qemu-nbd --socket=/tmp/my_socket my_disk.qcow2
@end example
-The use of qemu-nbd allows to share a disk between several guests:
+The use of qemu-nbd allows sharing of a disk between several guests:
@example
qemu-nbd --socket=/tmp/my_socket --share=2 my_disk.qcow2
@end example
diff --git a/qemu-options.hx b/qemu-options.hx
index 2d33815..6457034 100644
--- a/qemu-options.hx
+++ b/qemu-options.hx
@@ -444,7 +444,8 @@
@item cyls=@var{c},heads=@var{h},secs=@var{s}[,trans=@var{t}]
These options have the same definition as they have in @option{-hdachs}.
@item snapshot=@var{snapshot}
-@var{snapshot} is "on" or "off" and allows to enable snapshot for given drive (see @option{-snapshot}).
+@var{snapshot} is "on" or "off" and controls snapshot mode for the given drive
+(see @option{-snapshot}).
@item cache=@var{cache}
@var{cache} is "none", "writeback", "unsafe", "directsync" or "writethrough" and controls how the host cache is used to access block data.
@item aio=@var{aio}
@@ -1242,7 +1243,7 @@
An adaptive encoding will try to detect frequently updated screen regions,
and send updates in these regions using a lossy encoding (like JPEG).
This can be really helpful to save bandwidth when playing videos. Disabling
-adaptive encodings allows to restore the original static behavior of encodings
+adaptive encodings restores the original static behavior of encodings
like Tight.
@item share=[allow-exclusive|force-shared|ignore]
@@ -2805,7 +2806,7 @@
MS-DOS or Windows. To start at a specific point in time, provide @var{date} in the
format @code{2006-06-17T16:01:21} or @code{2006-06-17}. The default base is UTC.
-By default the RTC is driven by the host system time. This allows to use the
+By default the RTC is driven by the host system time. This allows using of the
RTC as accurate reference clock inside the guest, specifically if the host
time is smoothly following an accurate external reference clock, e.g. via NTP.
If you want to isolate the guest time from the host, you can set @option{clock}
diff --git a/qga/commands-posix.c b/qga/commands-posix.c
index 6b5f11f..935a4ec 100644
--- a/qga/commands-posix.c
+++ b/qga/commands-posix.c
@@ -171,7 +171,7 @@
/* Now, if user has passed a time to set and the system time is set, we
* just need to synchronize the hardware clock. However, if no time was
* passed, user is requesting the opposite: set the system time from the
- * hardware clock. */
+ * hardware clock (RTC). */
pid = fork();
if (pid == 0) {
setsid();
diff --git a/qga/qapi-schema.json b/qga/qapi-schema.json
index 80edca1..a8cdcb3 100644
--- a/qga/qapi-schema.json
+++ b/qga/qapi-schema.json
@@ -96,8 +96,8 @@
##
# @guest-get-time:
#
-# Get the information about guest time relative to the Epoch
-# of 1970-01-01 in UTC.
+# Get the information about guest's System Time relative to
+# the Epoch of 1970-01-01 in UTC.
#
# Returns: Time in nanoseconds.
#
@@ -117,11 +117,11 @@
# gap was, NTP might not be able to resynchronize the
# guest.
#
-# This command tries to set guest time to the given value,
-# then sets the Hardware Clock to the current System Time.
-# This will make it easier for a guest to resynchronize
-# without waiting for NTP. If no @time is specified, then
-# the time to set is read from RTC.
+# This command tries to set guest's System Time to the
+# given value, then sets the Hardware Clock (RTC) to the
+# current System Time. This will make it easier for a guest
+# to resynchronize without waiting for NTP. If no @time is
+# specified, then the time to set is read from RTC.
#
# @time: #optional time of nanoseconds, relative to the Epoch
# of 1970-01-01 in UTC.
diff --git a/scripts/coverity-model.c b/scripts/coverity-model.c
new file mode 100644
index 0000000..4c99a85
--- /dev/null
+++ b/scripts/coverity-model.c
@@ -0,0 +1,183 @@
+/* Coverity Scan model
+ *
+ * Copyright (C) 2014 Red Hat, Inc.
+ *
+ * Authors:
+ * Markus Armbruster <armbru@redhat.com>
+ * Paolo Bonzini <pbonzini@redhat.com>
+ *
+ * This work is licensed under the terms of the GNU GPL, version 2 or, at your
+ * option, any later version. See the COPYING file in the top-level directory.
+ */
+
+
+/*
+ * This is the source code for our Coverity user model file. The
+ * purpose of user models is to increase scanning accuracy by explaining
+ * code Coverity can't see (out of tree libraries) or doesn't
+ * sufficiently understand. Better accuracy means both fewer false
+ * positives and more true defects. Memory leaks in particular.
+ *
+ * - A model file can't import any header files. Some built-in primitives are
+ * available but not wchar_t, NULL etc.
+ * - Modeling doesn't need full structs and typedefs. Rudimentary structs
+ * and similar types are sufficient.
+ * - An uninitialized local variable signifies that the variable could be
+ * any value.
+ *
+ * The model file must be uploaded by an admin in the analysis settings of
+ * http://scan.coverity.com/projects/378
+ */
+
+#define NULL ((void *)0)
+
+typedef unsigned char uint8_t;
+typedef char int8_t;
+typedef unsigned int uint32_t;
+typedef int int32_t;
+typedef long ssize_t;
+typedef unsigned long long uint64_t;
+typedef long long int64_t;
+typedef _Bool bool;
+
+/* exec.c */
+
+typedef struct AddressSpace AddressSpace;
+typedef uint64_t hwaddr;
+
+static void __write(uint8_t *buf, ssize_t len)
+{
+ int first, last;
+ __coverity_negative_sink__(len);
+ if (len == 0) return;
+ buf[0] = first;
+ buf[len-1] = last;
+ __coverity_writeall__(buf);
+}
+
+static void __read(uint8_t *buf, ssize_t len)
+{
+ __coverity_negative_sink__(len);
+ if (len == 0) return;
+ int first = buf[0];
+ int last = buf[len-1];
+}
+
+bool address_space_rw(AddressSpace *as, hwaddr addr, uint8_t *buf,
+ int len, bool is_write)
+{
+ bool result;
+
+ // TODO: investigate impact of treating reads as producing
+ // tainted data, with __coverity_tainted_data_argument__(buf).
+ if (is_write) __write(buf, len); else __read(buf, len);
+
+ return result;
+}
+
+/* Tainting */
+
+typedef struct {} name2keysym_t;
+static int get_keysym(const name2keysym_t *table,
+ const char *name)
+{
+ int result;
+ if (result > 0) {
+ __coverity_tainted_string_sanitize_content__(name);
+ return result;
+ } else {
+ return 0;
+ }
+}
+
+/* glib memory allocation functions.
+ *
+ * Note that we ignore the fact that g_malloc of 0 bytes returns NULL,
+ * and g_realloc of 0 bytes frees the pointer.
+ *
+ * Modeling this would result in Coverity flagging a lot of memory
+ * allocations as potentially returning NULL, and asking us to check
+ * whether the result of the allocation is NULL or not. However, the
+ * resulting pointer should never be dereferenced anyway, and in fact
+ * it is not in the vast majority of cases.
+ *
+ * If a dereference did happen, this would suppress a defect report
+ * for an actual null pointer dereference. But it's too unlikely to
+ * be worth wading through the false positives, and with some luck
+ * we'll get a buffer overflow reported anyway.
+ */
+
+void *malloc(size_t);
+void *calloc(size_t, size_t);
+void *realloc(void *, size_t);
+void free(void *);
+
+void *
+g_malloc(size_t n_bytes)
+{
+ void *mem;
+ __coverity_negative_sink__(n_bytes);
+ mem = malloc(n_bytes == 0 ? 1 : n_bytes);
+ if (!mem) __coverity_panic__();
+ return mem;
+}
+
+void *
+g_malloc0(size_t n_bytes)
+{
+ void *mem;
+ __coverity_negative_sink__(n_bytes);
+ mem = calloc(1, n_bytes == 0 ? 1 : n_bytes);
+ if (!mem) __coverity_panic__();
+ return mem;
+}
+
+void g_free(void *mem)
+{
+ free(mem);
+}
+
+void *g_realloc(void * mem, size_t n_bytes)
+{
+ __coverity_negative_sink__(n_bytes);
+ mem = realloc(mem, n_bytes == 0 ? 1 : n_bytes);
+ if (!mem) __coverity_panic__();
+ return mem;
+}
+
+void *g_try_malloc(size_t n_bytes)
+{
+ __coverity_negative_sink__(n_bytes);
+ return malloc(n_bytes == 0 ? 1 : n_bytes);
+}
+
+void *g_try_malloc0(size_t n_bytes)
+{
+ __coverity_negative_sink__(n_bytes);
+ return calloc(1, n_bytes == 0 ? 1 : n_bytes);
+}
+
+void *g_try_realloc(void *mem, size_t n_bytes)
+{
+ __coverity_negative_sink__(n_bytes);
+ return realloc(mem, n_bytes == 0 ? 1 : n_bytes);
+}
+
+/* Other glib functions */
+
+typedef struct _GIOChannel GIOChannel;
+GIOChannel *g_io_channel_unix_new(int fd)
+{
+ GIOChannel *c = g_malloc0(sizeof(GIOChannel));
+ __coverity_escape__(fd);
+ return c;
+}
+
+void g_assertion_message_expr(const char *domain,
+ const char *file,
+ int line,
+ const char *func,
+ const char *expr)
+{
+ __coverity_panic__();
+}
diff --git a/tcg/README b/tcg/README
index f178212..776e925 100644
--- a/tcg/README
+++ b/tcg/README
@@ -36,6 +36,12 @@
A TCG "basic block" corresponds to a list of instructions terminated
by a branch instruction.
+An operation with "undefined behavior" may result in a crash.
+
+An operation with "unspecified behavior" shall not crash. However,
+the result may be one of several possibilities so may be considered
+an "undefined result".
+
3) Intermediate representation
3.1) Introduction
@@ -239,23 +245,25 @@
* shl_i32/i64 t0, t1, t2
-t0=t1 << t2. Undefined behavior if t2 < 0 or t2 >= 32 (resp 64)
+t0=t1 << t2. Unspecified behavior if t2 < 0 or t2 >= 32 (resp 64)
* shr_i32/i64 t0, t1, t2
-t0=t1 >> t2 (unsigned). Undefined behavior if t2 < 0 or t2 >= 32 (resp 64)
+t0=t1 >> t2 (unsigned). Unspecified behavior if t2 < 0 or t2 >= 32 (resp 64)
* sar_i32/i64 t0, t1, t2
-t0=t1 >> t2 (signed). Undefined behavior if t2 < 0 or t2 >= 32 (resp 64)
+t0=t1 >> t2 (signed). Unspecified behavior if t2 < 0 or t2 >= 32 (resp 64)
* rotl_i32/i64 t0, t1, t2
-Rotation of t2 bits to the left. Undefined behavior if t2 < 0 or t2 >= 32 (resp 64)
+Rotation of t2 bits to the left.
+Unspecified behavior if t2 < 0 or t2 >= 32 (resp 64)
* rotr_i32/i64 t0, t1, t2
-Rotation of t2 bits to the right. Undefined behavior if t2 < 0 or t2 >= 32 (resp 64)
+Rotation of t2 bits to the right.
+Unspecified behavior if t2 < 0 or t2 >= 32 (resp 64)
********* Misc
diff --git a/tcg/aarch64/tcg-target.c b/tcg/aarch64/tcg-target.c
index 73ed658..0a580b6 100644
--- a/tcg/aarch64/tcg-target.c
+++ b/tcg/aarch64/tcg-target.c
@@ -102,11 +102,10 @@
}
}
-#define TCG_CT_CONST_IS32 0x100
-#define TCG_CT_CONST_AIMM 0x200
-#define TCG_CT_CONST_LIMM 0x400
-#define TCG_CT_CONST_ZERO 0x800
-#define TCG_CT_CONST_MONE 0x1000
+#define TCG_CT_CONST_AIMM 0x100
+#define TCG_CT_CONST_LIMM 0x200
+#define TCG_CT_CONST_ZERO 0x400
+#define TCG_CT_CONST_MONE 0x800
/* parse target specific constraints */
static int target_parse_constraint(TCGArgConstraint *ct,
@@ -131,9 +130,6 @@
tcg_regset_reset_reg(ct->u.regs, TCG_REG_X3);
#endif
break;
- case 'w': /* The operand should be considered 32-bit. */
- ct->ct |= TCG_CT_CONST_IS32;
- break;
case 'A': /* Valid for arithmetic immediate (positive or negative). */
ct->ct |= TCG_CT_CONST_AIMM;
break;
@@ -180,7 +176,7 @@
return (val & (val - 1)) == 0;
}
-static int tcg_target_const_match(tcg_target_long val,
+static int tcg_target_const_match(tcg_target_long val, TCGType type,
const TCGArgConstraint *arg_ct)
{
int ct = arg_ct->ct;
@@ -188,7 +184,7 @@
if (ct & TCG_CT_CONST) {
return 1;
}
- if (ct & TCG_CT_CONST_IS32) {
+ if (type == TCG_TYPE_I32) {
val = (int32_t)val;
}
if ((ct & TCG_CT_CONST_AIMM) && (is_aimm(val) || is_aimm(-val))) {
@@ -1053,7 +1049,7 @@
tcg_out_goto(s, (intptr_t)lb->raddr);
}
-static void add_qemu_ldst_label(TCGContext *s, int is_ld, TCGMemOp opc,
+static void add_qemu_ldst_label(TCGContext *s, bool is_ld, TCGMemOp opc,
TCGReg data_reg, TCGReg addr_reg,
int mem_index,
uint8_t *raddr, uint8_t *label_ptr)
@@ -1226,7 +1222,7 @@
tcg_out_tlb_read(s, addr_reg, s_bits, &label_ptr, mem_index, 1);
tcg_out_qemu_ld_direct(s, memop, data_reg, addr_reg, TCG_REG_X1);
- add_qemu_ldst_label(s, 1, memop, data_reg, addr_reg,
+ add_qemu_ldst_label(s, true, memop, data_reg, addr_reg,
mem_index, s->code_ptr, label_ptr);
#else /* !CONFIG_SOFTMMU */
tcg_out_qemu_ld_direct(s, memop, data_reg, addr_reg,
@@ -1243,7 +1239,7 @@
tcg_out_tlb_read(s, addr_reg, s_bits, &label_ptr, mem_index, 0);
tcg_out_qemu_st_direct(s, memop, data_reg, addr_reg, TCG_REG_X1);
- add_qemu_ldst_label(s, 0, memop, data_reg, addr_reg,
+ add_qemu_ldst_label(s, false, memop, data_reg, addr_reg,
mem_index, s->code_ptr, label_ptr);
#else /* !CONFIG_SOFTMMU */
tcg_out_qemu_st_direct(s, memop, data_reg, addr_reg,
@@ -1663,9 +1659,9 @@
{ INDEX_op_st32_i64, { "rZ", "r" } },
{ INDEX_op_st_i64, { "rZ", "r" } },
- { INDEX_op_add_i32, { "r", "r", "rwA" } },
+ { INDEX_op_add_i32, { "r", "r", "rA" } },
{ INDEX_op_add_i64, { "r", "r", "rA" } },
- { INDEX_op_sub_i32, { "r", "r", "rwA" } },
+ { INDEX_op_sub_i32, { "r", "r", "rA" } },
{ INDEX_op_sub_i64, { "r", "r", "rA" } },
{ INDEX_op_mul_i32, { "r", "r", "r" } },
{ INDEX_op_mul_i64, { "r", "r", "r" } },
@@ -1677,17 +1673,17 @@
{ INDEX_op_rem_i64, { "r", "r", "r" } },
{ INDEX_op_remu_i32, { "r", "r", "r" } },
{ INDEX_op_remu_i64, { "r", "r", "r" } },
- { INDEX_op_and_i32, { "r", "r", "rwL" } },
+ { INDEX_op_and_i32, { "r", "r", "rL" } },
{ INDEX_op_and_i64, { "r", "r", "rL" } },
- { INDEX_op_or_i32, { "r", "r", "rwL" } },
+ { INDEX_op_or_i32, { "r", "r", "rL" } },
{ INDEX_op_or_i64, { "r", "r", "rL" } },
- { INDEX_op_xor_i32, { "r", "r", "rwL" } },
+ { INDEX_op_xor_i32, { "r", "r", "rL" } },
{ INDEX_op_xor_i64, { "r", "r", "rL" } },
- { INDEX_op_andc_i32, { "r", "r", "rwL" } },
+ { INDEX_op_andc_i32, { "r", "r", "rL" } },
{ INDEX_op_andc_i64, { "r", "r", "rL" } },
- { INDEX_op_orc_i32, { "r", "r", "rwL" } },
+ { INDEX_op_orc_i32, { "r", "r", "rL" } },
{ INDEX_op_orc_i64, { "r", "r", "rL" } },
- { INDEX_op_eqv_i32, { "r", "r", "rwL" } },
+ { INDEX_op_eqv_i32, { "r", "r", "rL" } },
{ INDEX_op_eqv_i64, { "r", "r", "rL" } },
{ INDEX_op_neg_i32, { "r", "r" } },
@@ -1706,11 +1702,11 @@
{ INDEX_op_rotl_i64, { "r", "r", "ri" } },
{ INDEX_op_rotr_i64, { "r", "r", "ri" } },
- { INDEX_op_brcond_i32, { "r", "rwA" } },
+ { INDEX_op_brcond_i32, { "r", "rA" } },
{ INDEX_op_brcond_i64, { "r", "rA" } },
- { INDEX_op_setcond_i32, { "r", "r", "rwA" } },
+ { INDEX_op_setcond_i32, { "r", "r", "rA" } },
{ INDEX_op_setcond_i64, { "r", "r", "rA" } },
- { INDEX_op_movcond_i32, { "r", "r", "rwA", "rZ", "rZ" } },
+ { INDEX_op_movcond_i32, { "r", "r", "rA", "rZ", "rZ" } },
{ INDEX_op_movcond_i64, { "r", "r", "rA", "rZ", "rZ" } },
{ INDEX_op_qemu_ld_i32, { "r", "l" } },
@@ -1739,9 +1735,9 @@
{ INDEX_op_deposit_i32, { "r", "0", "rZ" } },
{ INDEX_op_deposit_i64, { "r", "0", "rZ" } },
- { INDEX_op_add2_i32, { "r", "r", "rZ", "rZ", "rwA", "rwMZ" } },
+ { INDEX_op_add2_i32, { "r", "r", "rZ", "rZ", "rA", "rMZ" } },
{ INDEX_op_add2_i64, { "r", "r", "rZ", "rZ", "rA", "rMZ" } },
- { INDEX_op_sub2_i32, { "r", "r", "rZ", "rZ", "rwA", "rwMZ" } },
+ { INDEX_op_sub2_i32, { "r", "r", "rZ", "rZ", "rA", "rMZ" } },
{ INDEX_op_sub2_i64, { "r", "r", "rZ", "rZ", "rA", "rMZ" } },
{ INDEX_op_muluh_i64, { "r", "r", "r" } },
diff --git a/tcg/aarch64/tcg-target.h b/tcg/aarch64/tcg-target.h
index adf0261..eff1d68 100644
--- a/tcg/aarch64/tcg-target.h
+++ b/tcg/aarch64/tcg-target.h
@@ -13,7 +13,6 @@
#ifndef TCG_TARGET_AARCH64
#define TCG_TARGET_AARCH64 1
-#undef TCG_TARGET_WORDS_BIGENDIAN
#undef TCG_TARGET_STACK_GROWSUP
typedef enum {
diff --git a/tcg/arm/tcg-target.c b/tcg/arm/tcg-target.c
index a65fc65..7535175 100644
--- a/tcg/arm/tcg-target.c
+++ b/tcg/arm/tcg-target.c
@@ -261,7 +261,7 @@
* mov operand2: values represented with x << (2 * y), x < 0x100
* add, sub, eor...: ditto
*/
-static inline int tcg_target_const_match(tcg_target_long val,
+static inline int tcg_target_const_match(tcg_target_long val, TCGType type,
const TCGArgConstraint *arg_ct)
{
int ct;
@@ -1253,7 +1253,7 @@
/* Record the context of a call to the out of line helper code for the slow
path for a load or store, so that we can later generate the correct
helper code. */
-static void add_qemu_ldst_label(TCGContext *s, int is_ld, TCGMemOp opc,
+static void add_qemu_ldst_label(TCGContext *s, bool is_ld, TCGMemOp opc,
TCGReg datalo, TCGReg datahi, TCGReg addrlo,
TCGReg addrhi, int mem_index,
uint8_t *raddr, uint8_t *label_ptr)
@@ -1519,7 +1519,7 @@
tcg_out_qemu_ld_index(s, opc, datalo, datahi, addrlo, addend);
- add_qemu_ldst_label(s, 1, opc, datalo, datahi, addrlo, addrhi,
+ add_qemu_ldst_label(s, true, opc, datalo, datahi, addrlo, addrhi,
mem_index, s->code_ptr, label_ptr);
#else /* !CONFIG_SOFTMMU */
if (GUEST_BASE) {
@@ -1647,7 +1647,7 @@
label_ptr = s->code_ptr;
tcg_out_bl_noaddr(s, COND_NE);
- add_qemu_ldst_label(s, 0, opc, datalo, datahi, addrlo, addrhi,
+ add_qemu_ldst_label(s, false, opc, datalo, datahi, addrlo, addrhi,
mem_index, s->code_ptr, label_ptr);
#else /* !CONFIG_SOFTMMU */
if (GUEST_BASE) {
diff --git a/tcg/arm/tcg-target.h b/tcg/arm/tcg-target.h
index 3746b6e..1bc5dac 100644
--- a/tcg/arm/tcg-target.h
+++ b/tcg/arm/tcg-target.h
@@ -25,7 +25,6 @@
#ifndef TCG_TARGET_ARM
#define TCG_TARGET_ARM 1
-#undef TCG_TARGET_WORDS_BIGENDIAN
#undef TCG_TARGET_STACK_GROWSUP
typedef enum {
@@ -79,6 +78,7 @@
#define TCG_TARGET_HAS_nor_i32 0
#define TCG_TARGET_HAS_deposit_i32 1
#define TCG_TARGET_HAS_movcond_i32 1
+#define TCG_TARGET_HAS_mulu2_i32 1
#define TCG_TARGET_HAS_muls2_i32 1
#define TCG_TARGET_HAS_muluh_i32 0
#define TCG_TARGET_HAS_mulsh_i32 0
diff --git a/tcg/i386/tcg-target.c b/tcg/i386/tcg-target.c
index f832282..34ece1f 100644
--- a/tcg/i386/tcg-target.c
+++ b/tcg/i386/tcg-target.c
@@ -257,7 +257,7 @@
}
/* test if a constant matches the constraint */
-static inline int tcg_target_const_match(tcg_target_long val,
+static inline int tcg_target_const_match(tcg_target_long val, TCGType type,
const TCGArgConstraint *arg_ct)
{
int ct = arg_ct->ct;
@@ -1244,7 +1244,7 @@
* Record the context of a call to the out of line helper code for the slow path
* for a load or store, so that we can later generate the correct helper code
*/
-static void add_qemu_ldst_label(TCGContext *s, int is_ld, TCGMemOp opc,
+static void add_qemu_ldst_label(TCGContext *s, bool is_ld, TCGMemOp opc,
TCGReg datalo, TCGReg datahi,
TCGReg addrlo, TCGReg addrhi,
int mem_index, uint8_t *raddr,
@@ -1554,7 +1554,7 @@
tcg_out_qemu_ld_direct(s, datalo, datahi, TCG_REG_L1, 0, 0, opc);
/* Record the current context of a load into ldst label */
- add_qemu_ldst_label(s, 1, opc, datalo, datahi, addrlo, addrhi,
+ add_qemu_ldst_label(s, true, opc, datalo, datahi, addrlo, addrhi,
mem_index, s->code_ptr, label_ptr);
#else
{
@@ -1685,7 +1685,7 @@
tcg_out_qemu_st_direct(s, datalo, datahi, TCG_REG_L1, 0, 0, opc);
/* Record the current context of a store into ldst label */
- add_qemu_ldst_label(s, 0, opc, datalo, datahi, addrlo, addrhi,
+ add_qemu_ldst_label(s, false, opc, datalo, datahi, addrlo, addrhi,
mem_index, s->code_ptr, label_ptr);
#else
{
diff --git a/tcg/i386/tcg-target.h b/tcg/i386/tcg-target.h
index bdf2222..ababca0 100644
--- a/tcg/i386/tcg-target.h
+++ b/tcg/i386/tcg-target.h
@@ -24,8 +24,6 @@
#ifndef TCG_TARGET_I386
#define TCG_TARGET_I386 1
-#undef TCG_TARGET_WORDS_BIGENDIAN
-
#ifdef __x86_64__
# define TCG_TARGET_REG_BITS 64
# define TCG_TARGET_NB_REGS 16
diff --git a/tcg/ia64/tcg-target.c b/tcg/ia64/tcg-target.c
index 2d8e00c..1f523d6 100644
--- a/tcg/ia64/tcg-target.c
+++ b/tcg/ia64/tcg-target.c
@@ -23,8 +23,6 @@
* THE SOFTWARE.
*/
-#include "tcg-be-null.h"
-
/*
* Register definitions
*/
@@ -221,10 +219,12 @@
OPC_ALLOC_M34 = 0x02c00000000ull,
OPC_BR_DPTK_FEW_B1 = 0x08400000000ull,
OPC_BR_SPTK_MANY_B1 = 0x08000001000ull,
+ OPC_BR_CALL_SPNT_FEW_B3 = 0x0a200000000ull,
OPC_BR_SPTK_MANY_B4 = 0x00100001000ull,
OPC_BR_CALL_SPTK_MANY_B5 = 0x02100001000ull,
OPC_BR_RET_SPTK_MANY_B4 = 0x00108001100ull,
OPC_BRL_SPTK_MANY_X3 = 0x18000001000ull,
+ OPC_BRL_CALL_SPNT_MANY_X4 = 0x1a200001000ull,
OPC_BRL_CALL_SPTK_MANY_X4 = 0x1a000001000ull,
OPC_CMP_LT_A6 = 0x18000000000ull,
OPC_CMP_LTU_A6 = 0x1a000000000ull,
@@ -356,6 +356,15 @@
| (qp & 0x3f);
}
+static inline uint64_t tcg_opc_b3(int qp, uint64_t opc, int b1, uint64_t imm)
+{
+ return opc
+ | ((imm & 0x100000) << 16) /* s */
+ | ((imm & 0x0fffff) << 13) /* imm20b */
+ | ((b1 & 0x7) << 6)
+ | (qp & 0x3f);
+}
+
static inline uint64_t tcg_opc_b4(int qp, uint64_t opc, int b2)
{
return opc
@@ -815,6 +824,7 @@
#if defined(CONFIG_SOFTMMU)
tcg_regset_reset_reg(ct->u.regs, TCG_REG_R56);
tcg_regset_reset_reg(ct->u.regs, TCG_REG_R57);
+ tcg_regset_reset_reg(ct->u.regs, TCG_REG_R58);
#endif
break;
case 'Z':
@@ -832,7 +842,7 @@
}
/* test if a constant matches the constraint */
-static inline int tcg_target_const_match(tcg_target_long val,
+static inline int tcg_target_const_match(tcg_target_long val, TCGType type,
const TCGArgConstraint *arg_ct)
{
int ct;
@@ -950,15 +960,21 @@
static void tcg_out_exit_tb(TCGContext *s, tcg_target_long arg)
{
int64_t disp;
- uint64_t imm;
+ uint64_t imm, opc1;
- tcg_out_movi(s, TCG_TYPE_PTR, TCG_REG_R8, arg);
+ /* At least arg == 0 is a common operation. */
+ if (arg == sextract64(arg, 0, 22)) {
+ opc1 = tcg_opc_movi_a(TCG_REG_P0, TCG_REG_R8, arg);
+ } else {
+ tcg_out_movi(s, TCG_TYPE_PTR, TCG_REG_R8, arg);
+ opc1 = INSN_NOP_M;
+ }
disp = tb_ret_addr - s->code_ptr;
imm = (uint64_t)disp >> 4;
tcg_out_bundle(s, mLX,
- INSN_NOP_M,
+ opc1,
tcg_opc_l3 (imm),
tcg_opc_x3 (TCG_REG_P0, OPC_BRL_SPTK_MANY_X3, imm));
}
@@ -1558,238 +1574,284 @@
}
#if defined(CONFIG_SOFTMMU)
+/* We're expecting to use an signed 22-bit immediate add. */
+QEMU_BUILD_BUG_ON(offsetof(CPUArchState, tlb_table[NB_MMU_MODES - 1][1])
+ > 0x1fffff)
+
/* Load and compare a TLB entry, and return the result in (p6, p7).
- R2 is loaded with the address of the addend TLB entry.
- R57 is loaded with the address, zero extented on 32-bit targets. */
-static inline void tcg_out_qemu_tlb(TCGContext *s, TCGArg addr_reg,
- TCGMemOp s_bits, uint64_t offset_rw,
- uint64_t offset_addend)
+ R2 is loaded with the addend TLB entry.
+ R57 is loaded with the address, zero extented on 32-bit targets.
+ R1, R3 are clobbered, leaving R56 free for...
+ BSWAP_1, BSWAP_2 and I-slot insns for swapping data for store. */
+static inline void tcg_out_qemu_tlb(TCGContext *s, TCGReg addr_reg,
+ TCGMemOp s_bits, int off_rw, int off_add,
+ uint64_t bswap1, uint64_t bswap2)
{
- tcg_out_bundle(s, mII,
- INSN_NOP_M,
- tcg_opc_i11(TCG_REG_P0, OPC_EXTR_U_I11, TCG_REG_R2,
+ /*
+ .mii
+ mov r2 = off_rw
+ extr.u r3 = addr_reg, ... # extract tlb page
+ zxt4 r57 = addr_reg # or mov for 64-bit guest
+ ;;
+ .mii
+ addl r2 = r2, areg0
+ shl r3 = r3, cteb # via dep.z
+ dep r1 = 0, r57, ... # zero page ofs, keep align
+ ;;
+ .mmi
+ add r2 = r2, r3
+ ;;
+ ld4 r3 = [r2], off_add-off_rw # or ld8 for 64-bit guest
+ nop
+ ;;
+ .mmi
+ nop
+ cmp.eq p6, p7 = r3, r58
+ nop
+ ;;
+ */
+ tcg_out_bundle(s, miI,
+ tcg_opc_movi_a(TCG_REG_P0, TCG_REG_R2, off_rw),
+ tcg_opc_i11(TCG_REG_P0, OPC_EXTR_U_I11, TCG_REG_R3,
addr_reg, TARGET_PAGE_BITS, CPU_TLB_BITS - 1),
- tcg_opc_i12(TCG_REG_P0, OPC_DEP_Z_I12, TCG_REG_R2,
- TCG_REG_R2, 63 - CPU_TLB_ENTRY_BITS,
- 63 - CPU_TLB_ENTRY_BITS));
- tcg_out_bundle(s, mII,
- tcg_opc_a5 (TCG_REG_P0, OPC_ADDL_A5, TCG_REG_R2,
- offset_rw, TCG_REG_R2),
tcg_opc_ext_i(TCG_REG_P0,
TARGET_LONG_BITS == 32 ? MO_UL : MO_Q,
- TCG_REG_R57, addr_reg),
+ TCG_REG_R57, addr_reg));
+ tcg_out_bundle(s, miI,
tcg_opc_a1 (TCG_REG_P0, OPC_ADD_A1, TCG_REG_R2,
- TCG_REG_R2, TCG_AREG0));
- tcg_out_bundle(s, mII,
+ TCG_REG_R2, TCG_AREG0),
+ tcg_opc_i12(TCG_REG_P0, OPC_DEP_Z_I12, TCG_REG_R3,
+ TCG_REG_R3, 63 - CPU_TLB_ENTRY_BITS,
+ 63 - CPU_TLB_ENTRY_BITS),
+ tcg_opc_i14(TCG_REG_P0, OPC_DEP_I14, TCG_REG_R1, 0,
+ TCG_REG_R57, 63 - s_bits,
+ TARGET_PAGE_BITS - s_bits - 1));
+ tcg_out_bundle(s, MmI,
+ tcg_opc_a1 (TCG_REG_P0, OPC_ADD_A1,
+ TCG_REG_R2, TCG_REG_R2, TCG_REG_R3),
tcg_opc_m3 (TCG_REG_P0,
(TARGET_LONG_BITS == 32
- ? OPC_LD4_M3 : OPC_LD8_M3), TCG_REG_R56,
- TCG_REG_R2, offset_addend - offset_rw),
- tcg_opc_i14(TCG_REG_P0, OPC_DEP_I14, TCG_REG_R3, 0,
- TCG_REG_R57, 63 - s_bits,
- TARGET_PAGE_BITS - s_bits - 1),
+ ? OPC_LD4_M3 : OPC_LD8_M3), TCG_REG_R3,
+ TCG_REG_R2, off_add - off_rw),
+ bswap1);
+ tcg_out_bundle(s, mmI,
+ tcg_opc_m1 (TCG_REG_P0, OPC_LD8_M1, TCG_REG_R2, TCG_REG_R2),
tcg_opc_a6 (TCG_REG_P0, OPC_CMP_EQ_A6, TCG_REG_P6,
- TCG_REG_P7, TCG_REG_R3, TCG_REG_R56));
+ TCG_REG_P7, TCG_REG_R1, TCG_REG_R3),
+ bswap2);
}
-/* helper signature: helper_ld_mmu(CPUState *env, target_ulong addr,
- int mmu_idx) */
-static const void * const qemu_ld_helpers[4] = {
- helper_ldb_mmu,
- helper_ldw_mmu,
- helper_ldl_mmu,
- helper_ldq_mmu,
-};
+#define TCG_MAX_QEMU_LDST 640
-static inline void tcg_out_qemu_ld(TCGContext *s, const TCGArg *args,
- TCGMemOp opc)
+typedef struct TCGLabelQemuLdst {
+ bool is_ld;
+ TCGMemOp size;
+ uint8_t *label_ptr; /* label pointers to be updated */
+} TCGLabelQemuLdst;
+
+typedef struct TCGBackendData {
+ int nb_ldst_labels;
+ TCGLabelQemuLdst ldst_labels[TCG_MAX_QEMU_LDST];
+} TCGBackendData;
+
+static inline void tcg_out_tb_init(TCGContext *s)
+{
+ s->be->nb_ldst_labels = 0;
+}
+
+static void add_qemu_ldst_label(TCGContext *s, bool is_ld, TCGMemOp opc,
+ uint8_t *label_ptr)
+{
+ TCGBackendData *be = s->be;
+ TCGLabelQemuLdst *l = &be->ldst_labels[be->nb_ldst_labels++];
+
+ assert(be->nb_ldst_labels <= TCG_MAX_QEMU_LDST);
+ l->is_ld = is_ld;
+ l->size = opc & MO_SIZE;
+ l->label_ptr = label_ptr;
+}
+
+static void tcg_out_tb_finalize(TCGContext *s)
+{
+ static const void * const helpers[8] = {
+ helper_ret_stb_mmu,
+ helper_le_stw_mmu,
+ helper_le_stl_mmu,
+ helper_le_stq_mmu,
+ helper_ret_ldub_mmu,
+ helper_le_lduw_mmu,
+ helper_le_ldul_mmu,
+ helper_le_ldq_mmu,
+ };
+ uintptr_t thunks[8] = { };
+ TCGBackendData *be = s->be;
+ size_t i, n = be->nb_ldst_labels;
+
+ for (i = 0; i < n; i++) {
+ TCGLabelQemuLdst *l = &be->ldst_labels[i];
+ long x = l->is_ld * 4 + l->size;
+ uintptr_t dest = thunks[x];
+
+ /* The out-of-line thunks are all the same; load the return address
+ from B0, load the GP, and branch to the code. Note that we are
+ always post-call, so the register window has rolled, so we're
+ using incomming parameter register numbers, not outgoing. */
+ if (dest == 0) {
+ uintptr_t disp, *desc = (uintptr_t *)helpers[x];
+
+ thunks[x] = dest = (uintptr_t)s->code_ptr;
+
+ tcg_out_bundle(s, mlx,
+ INSN_NOP_M,
+ tcg_opc_l2 (desc[1]),
+ tcg_opc_x2 (TCG_REG_P0, OPC_MOVL_X2,
+ TCG_REG_R1, desc[1]));
+ tcg_out_bundle(s, mii,
+ INSN_NOP_M,
+ INSN_NOP_I,
+ tcg_opc_i22(TCG_REG_P0, OPC_MOV_I22,
+ l->is_ld ? TCG_REG_R35 : TCG_REG_R36,
+ TCG_REG_B0));
+ disp = (desc[0] - (uintptr_t)s->code_ptr) >> 4;
+ tcg_out_bundle(s, mLX,
+ INSN_NOP_M,
+ tcg_opc_l3 (disp),
+ tcg_opc_x3 (TCG_REG_P0, OPC_BRL_SPTK_MANY_X3, disp));
+ }
+
+ reloc_pcrel21b(l->label_ptr, dest);
+ }
+}
+
+static inline void tcg_out_qemu_ld(TCGContext *s, const TCGArg *args)
{
static const uint64_t opc_ld_m1[4] = {
OPC_LD1_M1, OPC_LD2_M1, OPC_LD4_M1, OPC_LD8_M1
};
int addr_reg, data_reg, mem_index;
- TCGMemOp s_bits, bswap;
+ TCGMemOp opc, s_bits;
+ uint64_t fin1, fin2;
+ uint8_t *label_ptr;
- data_reg = *args++;
- addr_reg = *args++;
- mem_index = *args;
+ data_reg = args[0];
+ addr_reg = args[1];
+ opc = args[2];
+ mem_index = args[3];
s_bits = opc & MO_SIZE;
- bswap = opc & MO_BSWAP;
/* Read the TLB entry */
tcg_out_qemu_tlb(s, addr_reg, s_bits,
offsetof(CPUArchState, tlb_table[mem_index][0].addr_read),
- offsetof(CPUArchState, tlb_table[mem_index][0].addend));
+ offsetof(CPUArchState, tlb_table[mem_index][0].addend),
+ INSN_NOP_I, INSN_NOP_I);
/* P6 is the fast path, and P7 the slow path */
- tcg_out_bundle(s, mLX,
- tcg_opc_mov_a(TCG_REG_P7, TCG_REG_R56, TCG_AREG0),
- tcg_opc_l2 ((tcg_target_long) qemu_ld_helpers[s_bits]),
- tcg_opc_x2 (TCG_REG_P7, OPC_MOVL_X2, TCG_REG_R2,
- (tcg_target_long) qemu_ld_helpers[s_bits]));
- tcg_out_bundle(s, MmI,
- tcg_opc_m3 (TCG_REG_P0, OPC_LD8_M3, TCG_REG_R3,
- TCG_REG_R2, 8),
- tcg_opc_a1 (TCG_REG_P6, OPC_ADD_A1, TCG_REG_R3,
- TCG_REG_R3, TCG_REG_R57),
- tcg_opc_i21(TCG_REG_P7, OPC_MOV_I21, TCG_REG_B6,
- TCG_REG_R3, 0));
- if (bswap && s_bits == MO_16) {
- tcg_out_bundle(s, MmI,
- tcg_opc_m1 (TCG_REG_P6, opc_ld_m1[s_bits],
- TCG_REG_R8, TCG_REG_R3),
- tcg_opc_m1 (TCG_REG_P7, OPC_LD8_M1, TCG_REG_R1, TCG_REG_R2),
- tcg_opc_i12(TCG_REG_P6, OPC_DEP_Z_I12,
- TCG_REG_R8, TCG_REG_R8, 15, 15));
- } else if (bswap && s_bits == MO_32) {
- tcg_out_bundle(s, MmI,
- tcg_opc_m1 (TCG_REG_P6, opc_ld_m1[s_bits],
- TCG_REG_R8, TCG_REG_R3),
- tcg_opc_m1 (TCG_REG_P7, OPC_LD8_M1, TCG_REG_R1, TCG_REG_R2),
- tcg_opc_i12(TCG_REG_P6, OPC_DEP_Z_I12,
- TCG_REG_R8, TCG_REG_R8, 31, 31));
+
+ fin2 = 0;
+ if (opc & MO_BSWAP) {
+ fin1 = tcg_opc_bswap64_i(TCG_REG_P0, data_reg, TCG_REG_R8);
+ if (s_bits < MO_64) {
+ int shift = 64 - (8 << s_bits);
+ fin2 = (opc & MO_SIGN ? OPC_EXTR_I11 : OPC_EXTR_U_I11);
+ fin2 = tcg_opc_i11(TCG_REG_P0, fin2,
+ data_reg, data_reg, shift, 63 - shift);
+ }
} else {
- tcg_out_bundle(s, mmI,
- tcg_opc_m1 (TCG_REG_P6, opc_ld_m1[s_bits],
- TCG_REG_R8, TCG_REG_R3),
- tcg_opc_m1 (TCG_REG_P7, OPC_LD8_M1, TCG_REG_R1, TCG_REG_R2),
- INSN_NOP_I);
- }
- if (!bswap) {
- tcg_out_bundle(s, miB,
- tcg_opc_movi_a(TCG_REG_P7, TCG_REG_R58, mem_index),
- INSN_NOP_I,
- tcg_opc_b5 (TCG_REG_P7, OPC_BR_CALL_SPTK_MANY_B5,
- TCG_REG_B0, TCG_REG_B6));
- } else {
- tcg_out_bundle(s, miB,
- tcg_opc_movi_a(TCG_REG_P7, TCG_REG_R58, mem_index),
- tcg_opc_bswap64_i(TCG_REG_P6, TCG_REG_R8, TCG_REG_R8),
- tcg_opc_b5 (TCG_REG_P7, OPC_BR_CALL_SPTK_MANY_B5,
- TCG_REG_B0, TCG_REG_B6));
+ fin1 = tcg_opc_ext_i(TCG_REG_P0, opc, data_reg, TCG_REG_R8);
}
- tcg_out_bundle(s, miI,
- INSN_NOP_M,
+ tcg_out_bundle(s, mmI,
+ tcg_opc_mov_a(TCG_REG_P7, TCG_REG_R56, TCG_AREG0),
+ tcg_opc_a1 (TCG_REG_P6, OPC_ADD_A1, TCG_REG_R2,
+ TCG_REG_R2, TCG_REG_R57),
+ tcg_opc_movi_a(TCG_REG_P7, TCG_REG_R58, mem_index));
+ label_ptr = s->code_ptr + 2;
+ tcg_out_bundle(s, miB,
+ tcg_opc_m1 (TCG_REG_P6, opc_ld_m1[s_bits],
+ TCG_REG_R8, TCG_REG_R2),
INSN_NOP_I,
- tcg_opc_ext_i(TCG_REG_P0, opc, data_reg, TCG_REG_R8));
+ tcg_opc_b3 (TCG_REG_P7, OPC_BR_CALL_SPNT_FEW_B3, TCG_REG_B0,
+ get_reloc_pcrel21b(label_ptr)));
+
+ add_qemu_ldst_label(s, 1, opc, label_ptr);
+
+ /* Note that we always use LE helper functions, so the bswap insns
+ here for the fast path also apply to the slow path. */
+ tcg_out_bundle(s, (fin2 ? mII : miI),
+ INSN_NOP_M,
+ fin1,
+ fin2 ? fin2 : INSN_NOP_I);
}
-/* helper signature: helper_st_mmu(CPUState *env, target_ulong addr,
- uintxx_t val, int mmu_idx) */
-static const void * const qemu_st_helpers[4] = {
- helper_stb_mmu,
- helper_stw_mmu,
- helper_stl_mmu,
- helper_stq_mmu,
-};
-
-static inline void tcg_out_qemu_st(TCGContext *s, const TCGArg *args,
- TCGMemOp opc)
+static inline void tcg_out_qemu_st(TCGContext *s, const TCGArg *args)
{
static const uint64_t opc_st_m4[4] = {
OPC_ST1_M4, OPC_ST2_M4, OPC_ST4_M4, OPC_ST8_M4
};
- int addr_reg, data_reg, mem_index;
- TCGMemOp s_bits;
+ TCGReg addr_reg, data_reg;
+ int mem_index;
+ uint64_t pre1, pre2;
+ TCGMemOp opc, s_bits;
+ uint8_t *label_ptr;
- data_reg = *args++;
- addr_reg = *args++;
- mem_index = *args;
+ data_reg = args[0];
+ addr_reg = args[1];
+ opc = args[2];
+ mem_index = args[3];
s_bits = opc & MO_SIZE;
+ /* Note that we always use LE helper functions, so the bswap insns
+ that are here for the fast path also apply to the slow path,
+ and move the data into the argument register. */
+ pre2 = INSN_NOP_I;
+ if (opc & MO_BSWAP) {
+ pre1 = tcg_opc_bswap64_i(TCG_REG_P0, TCG_REG_R58, data_reg);
+ if (s_bits < MO_64) {
+ int shift = 64 - (8 << s_bits);
+ pre2 = tcg_opc_i11(TCG_REG_P0, OPC_EXTR_U_I11,
+ TCG_REG_R58, TCG_REG_R58, shift, 63 - shift);
+ }
+ } else {
+ /* Just move the data into place for the slow path. */
+ pre1 = tcg_opc_ext_i(TCG_REG_P0, opc, TCG_REG_R58, data_reg);
+ }
+
tcg_out_qemu_tlb(s, addr_reg, s_bits,
offsetof(CPUArchState, tlb_table[mem_index][0].addr_write),
- offsetof(CPUArchState, tlb_table[mem_index][0].addend));
+ offsetof(CPUArchState, tlb_table[mem_index][0].addend),
+ pre1, pre2);
/* P6 is the fast path, and P7 the slow path */
- tcg_out_bundle(s, mLX,
+ tcg_out_bundle(s, mmI,
tcg_opc_mov_a(TCG_REG_P7, TCG_REG_R56, TCG_AREG0),
- tcg_opc_l2 ((tcg_target_long) qemu_st_helpers[s_bits]),
- tcg_opc_x2 (TCG_REG_P7, OPC_MOVL_X2, TCG_REG_R2,
- (tcg_target_long) qemu_st_helpers[s_bits]));
- tcg_out_bundle(s, MmI,
- tcg_opc_m3 (TCG_REG_P0, OPC_LD8_M3, TCG_REG_R3,
- TCG_REG_R2, 8),
- tcg_opc_a1 (TCG_REG_P6, OPC_ADD_A1, TCG_REG_R3,
- TCG_REG_R3, TCG_REG_R57),
- tcg_opc_i21(TCG_REG_P7, OPC_MOV_I21, TCG_REG_B6,
- TCG_REG_R3, 0));
-
- switch (opc) {
- case MO_8:
- case MO_16:
- case MO_32:
- case MO_64:
- tcg_out_bundle(s, mii,
- tcg_opc_m1 (TCG_REG_P7, OPC_LD8_M1,
- TCG_REG_R1, TCG_REG_R2),
- tcg_opc_mov_a(TCG_REG_P7, TCG_REG_R58, data_reg),
- INSN_NOP_I);
- break;
-
- case MO_16 | MO_BSWAP:
- tcg_out_bundle(s, miI,
- tcg_opc_m1 (TCG_REG_P7, OPC_LD8_M1,
- TCG_REG_R1, TCG_REG_R2),
- INSN_NOP_I,
- tcg_opc_i12(TCG_REG_P6, OPC_DEP_Z_I12,
- TCG_REG_R2, data_reg, 15, 15));
- tcg_out_bundle(s, miI,
- tcg_opc_mov_a(TCG_REG_P7, TCG_REG_R58, data_reg),
- INSN_NOP_I,
- tcg_opc_bswap64_i(TCG_REG_P6, TCG_REG_R2, TCG_REG_R2));
- data_reg = TCG_REG_R2;
- break;
-
- case MO_32 | MO_BSWAP:
- tcg_out_bundle(s, miI,
- tcg_opc_m1 (TCG_REG_P7, OPC_LD8_M1,
- TCG_REG_R1, TCG_REG_R2),
- INSN_NOP_I,
- tcg_opc_i12(TCG_REG_P6, OPC_DEP_Z_I12,
- TCG_REG_R2, data_reg, 31, 31));
- tcg_out_bundle(s, miI,
- tcg_opc_mov_a(TCG_REG_P7, TCG_REG_R58, data_reg),
- INSN_NOP_I,
- tcg_opc_bswap64_i(TCG_REG_P6, TCG_REG_R2, TCG_REG_R2));
- data_reg = TCG_REG_R2;
- break;
-
- case MO_64 | MO_BSWAP:
- tcg_out_bundle(s, miI,
- tcg_opc_m1 (TCG_REG_P7, OPC_LD8_M1,
- TCG_REG_R1, TCG_REG_R2),
- tcg_opc_mov_a(TCG_REG_P7, TCG_REG_R58, data_reg),
- tcg_opc_bswap64_i(TCG_REG_P6, TCG_REG_R2, data_reg));
- data_reg = TCG_REG_R2;
- break;
-
- default:
- tcg_abort();
- }
-
+ tcg_opc_a1 (TCG_REG_P6, OPC_ADD_A1, TCG_REG_R2,
+ TCG_REG_R2, TCG_REG_R57),
+ tcg_opc_movi_a(TCG_REG_P7, TCG_REG_R59, mem_index));
+ label_ptr = s->code_ptr + 2;
tcg_out_bundle(s, miB,
tcg_opc_m4 (TCG_REG_P6, opc_st_m4[s_bits],
- data_reg, TCG_REG_R3),
- tcg_opc_movi_a(TCG_REG_P7, TCG_REG_R59, mem_index),
- tcg_opc_b5 (TCG_REG_P7, OPC_BR_CALL_SPTK_MANY_B5,
- TCG_REG_B0, TCG_REG_B6));
+ TCG_REG_R58, TCG_REG_R2),
+ INSN_NOP_I,
+ tcg_opc_b3 (TCG_REG_P7, OPC_BR_CALL_SPNT_FEW_B3, TCG_REG_B0,
+ get_reloc_pcrel21b(label_ptr)));
+
+ add_qemu_ldst_label(s, 0, opc, label_ptr);
}
#else /* !CONFIG_SOFTMMU */
+# include "tcg-be-null.h"
-static inline void tcg_out_qemu_ld(TCGContext *s, const TCGArg *args,
- TCGMemOp opc)
+static inline void tcg_out_qemu_ld(TCGContext *s, const TCGArg *args)
{
static uint64_t const opc_ld_m1[4] = {
OPC_LD1_M1, OPC_LD2_M1, OPC_LD4_M1, OPC_LD8_M1
};
int addr_reg, data_reg;
- TCGMemOp s_bits, bswap;
+ TCGMemOp opc, s_bits, bswap;
- data_reg = *args++;
- addr_reg = *args++;
+ data_reg = args[0];
+ addr_reg = args[1];
+ opc = args[2];
s_bits = opc & MO_SIZE;
bswap = opc & MO_BSWAP;
@@ -1900,8 +1962,7 @@
#endif
}
-static inline void tcg_out_qemu_st(TCGContext *s, const TCGArg *args,
- TCGMemOp opc)
+static inline void tcg_out_qemu_st(TCGContext *s, const TCGArg *args)
{
static uint64_t const opc_st_m4[4] = {
OPC_ST1_M4, OPC_ST2_M4, OPC_ST4_M4, OPC_ST8_M4
@@ -1910,10 +1971,11 @@
#if TARGET_LONG_BITS == 64
uint64_t add_guest_base;
#endif
- TCGMemOp s_bits, bswap;
+ TCGMemOp opc, s_bits, bswap;
- data_reg = *args++;
- addr_reg = *args++;
+ data_reg = args[0];
+ addr_reg = args[1];
+ opc = args[2];
s_bits = opc & MO_SIZE;
bswap = opc & MO_BSWAP;
@@ -2237,40 +2299,17 @@
args[3], const_args[3], args[4], const_args[4], 0);
break;
- case INDEX_op_qemu_ld8u:
- tcg_out_qemu_ld(s, args, MO_UB);
+ case INDEX_op_qemu_ld_i32:
+ tcg_out_qemu_ld(s, args);
break;
- case INDEX_op_qemu_ld8s:
- tcg_out_qemu_ld(s, args, MO_SB);
+ case INDEX_op_qemu_ld_i64:
+ tcg_out_qemu_ld(s, args);
break;
- case INDEX_op_qemu_ld16u:
- tcg_out_qemu_ld(s, args, MO_TEUW);
+ case INDEX_op_qemu_st_i32:
+ tcg_out_qemu_st(s, args);
break;
- case INDEX_op_qemu_ld16s:
- tcg_out_qemu_ld(s, args, MO_TESW);
- break;
- case INDEX_op_qemu_ld32:
- case INDEX_op_qemu_ld32u:
- tcg_out_qemu_ld(s, args, MO_TEUL);
- break;
- case INDEX_op_qemu_ld32s:
- tcg_out_qemu_ld(s, args, MO_TESL);
- break;
- case INDEX_op_qemu_ld64:
- tcg_out_qemu_ld(s, args, MO_TEQ);
- break;
-
- case INDEX_op_qemu_st8:
- tcg_out_qemu_st(s, args, MO_UB);
- break;
- case INDEX_op_qemu_st16:
- tcg_out_qemu_st(s, args, MO_TEUW);
- break;
- case INDEX_op_qemu_st32:
- tcg_out_qemu_st(s, args, MO_TEUL);
- break;
- case INDEX_op_qemu_st64:
- tcg_out_qemu_st(s, args, MO_TEQ);
+ case INDEX_op_qemu_st_i64:
+ tcg_out_qemu_st(s, args);
break;
default:
@@ -2381,19 +2420,10 @@
{ INDEX_op_deposit_i32, { "r", "rZ", "ri" } },
{ INDEX_op_deposit_i64, { "r", "rZ", "ri" } },
- { INDEX_op_qemu_ld8u, { "r", "r" } },
- { INDEX_op_qemu_ld8s, { "r", "r" } },
- { INDEX_op_qemu_ld16u, { "r", "r" } },
- { INDEX_op_qemu_ld16s, { "r", "r" } },
- { INDEX_op_qemu_ld32, { "r", "r" } },
- { INDEX_op_qemu_ld32u, { "r", "r" } },
- { INDEX_op_qemu_ld32s, { "r", "r" } },
- { INDEX_op_qemu_ld64, { "r", "r" } },
-
- { INDEX_op_qemu_st8, { "SZ", "r" } },
- { INDEX_op_qemu_st16, { "SZ", "r" } },
- { INDEX_op_qemu_st32, { "SZ", "r" } },
- { INDEX_op_qemu_st64, { "SZ", "r" } },
+ { INDEX_op_qemu_ld_i32, { "r", "r" } },
+ { INDEX_op_qemu_ld_i64, { "r", "r" } },
+ { INDEX_op_qemu_st_i32, { "SZ", "r" } },
+ { INDEX_op_qemu_st_i64, { "SZ", "r" } },
{ -1 },
};
diff --git a/tcg/ia64/tcg-target.h b/tcg/ia64/tcg-target.h
index 52a939c..09c3ba8 100644
--- a/tcg/ia64/tcg-target.h
+++ b/tcg/ia64/tcg-target.h
@@ -153,7 +153,7 @@
#define TCG_TARGET_HAS_mulsh_i32 0
#define TCG_TARGET_HAS_mulsh_i64 0
-#define TCG_TARGET_HAS_new_ldst 0
+#define TCG_TARGET_HAS_new_ldst 1
#define TCG_TARGET_deposit_i32_valid(ofs, len) ((len) <= 16)
#define TCG_TARGET_deposit_i64_valid(ofs, len) ((len) <= 16)
diff --git a/tcg/mips/tcg-target.c b/tcg/mips/tcg-target.c
index 40551cd..37241b2 100644
--- a/tcg/mips/tcg-target.c
+++ b/tcg/mips/tcg-target.c
@@ -26,7 +26,7 @@
#include "tcg-be-null.h"
-#if defined(TCG_TARGET_WORDS_BIGENDIAN) == defined(TARGET_WORDS_BIGENDIAN)
+#if defined(HOST_WORDS_BIGENDIAN) == defined(TARGET_WORDS_BIGENDIAN)
# define TCG_NEED_BSWAP 0
#else
# define TCG_NEED_BSWAP 1
@@ -253,7 +253,7 @@
}
/* test if a constant matches the constraint */
-static inline int tcg_target_const_match(tcg_target_long val,
+static inline int tcg_target_const_match(tcg_target_long val, TCGType type,
const TCGArgConstraint *arg_ct)
{
int ct;
@@ -589,7 +589,7 @@
{
(*arg_num) = (*arg_num + 1) & ~1;
-#if defined(TCG_TARGET_WORDS_BIGENDIAN)
+#if defined(HOST_WORDS_BIGENDIAN)
tcg_out_call_iarg_reg32(s, arg_num, arg_high);
tcg_out_call_iarg_reg32(s, arg_num, arg_low);
#else
@@ -964,7 +964,7 @@
#if defined(CONFIG_SOFTMMU)
# if TARGET_LONG_BITS == 64
addr_regh = *args++;
-# if defined(TCG_TARGET_WORDS_BIGENDIAN)
+# if defined(HOST_WORDS_BIGENDIAN)
addr_memh = 0;
addr_meml = 4;
# else
@@ -979,7 +979,7 @@
#endif
if (opc == 3) {
-#if defined(TCG_TARGET_WORDS_BIGENDIAN)
+#if defined(HOST_WORDS_BIGENDIAN)
data_reg1 = data_regh;
data_reg2 = data_regl;
#else
@@ -1152,7 +1152,7 @@
#if defined(CONFIG_SOFTMMU)
# if TARGET_LONG_BITS == 64
addr_regh = *args++;
-# if defined(TCG_TARGET_WORDS_BIGENDIAN)
+# if defined(HOST_WORDS_BIGENDIAN)
addr_memh = 0;
addr_meml = 4;
# else
@@ -1167,7 +1167,7 @@
#endif
if (opc == 3) {
-#if defined(TCG_TARGET_WORDS_BIGENDIAN)
+#if defined(HOST_WORDS_BIGENDIAN)
data_reg1 = data_regh;
data_reg2 = data_regl;
#else
diff --git a/tcg/mips/tcg-target.h b/tcg/mips/tcg-target.h
index 683c6af..9576db5 100644
--- a/tcg/mips/tcg-target.h
+++ b/tcg/mips/tcg-target.h
@@ -26,10 +26,6 @@
#ifndef TCG_TARGET_MIPS
#define TCG_TARGET_MIPS 1
-#ifdef __MIPSEB__
-# define TCG_TARGET_WORDS_BIGENDIAN
-#endif
-
#define TCG_TARGET_NB_REGS 32
typedef enum {
@@ -109,6 +105,7 @@
#define TCG_TARGET_HAS_orc_i32 0
#define TCG_TARGET_HAS_eqv_i32 0
#define TCG_TARGET_HAS_nand_i32 0
+#define TCG_TARGET_HAS_mulu2_i32 1
#define TCG_TARGET_HAS_muls2_i32 1
#define TCG_TARGET_HAS_muluh_i32 1
#define TCG_TARGET_HAS_mulsh_i32 1
diff --git a/tcg/optimize.c b/tcg/optimize.c
index 7777743..c447062 100644
--- a/tcg/optimize.c
+++ b/tcg/optimize.c
@@ -220,34 +220,34 @@
return x ^ y;
case INDEX_op_shl_i32:
- return (uint32_t)x << (uint32_t)y;
+ return (uint32_t)x << (y & 31);
case INDEX_op_shl_i64:
- return (uint64_t)x << (uint64_t)y;
+ return (uint64_t)x << (y & 63);
case INDEX_op_shr_i32:
- return (uint32_t)x >> (uint32_t)y;
+ return (uint32_t)x >> (y & 31);
case INDEX_op_shr_i64:
- return (uint64_t)x >> (uint64_t)y;
+ return (uint64_t)x >> (y & 63);
case INDEX_op_sar_i32:
- return (int32_t)x >> (int32_t)y;
+ return (int32_t)x >> (y & 31);
case INDEX_op_sar_i64:
- return (int64_t)x >> (int64_t)y;
+ return (int64_t)x >> (y & 63);
case INDEX_op_rotr_i32:
- return ror32(x, y);
+ return ror32(x, y & 31);
case INDEX_op_rotr_i64:
- return ror64(x, y);
+ return ror64(x, y & 63);
case INDEX_op_rotl_i32:
- return rol32(x, y);
+ return rol32(x, y & 31);
case INDEX_op_rotl_i64:
- return rol64(x, y);
+ return rol64(x, y & 63);
CASE_OP_32_64(not):
return ~x;
@@ -806,29 +806,34 @@
case INDEX_op_sar_i32:
if (temps[args[2]].state == TCG_TEMP_CONST) {
- mask = (int32_t)temps[args[1]].mask >> temps[args[2]].val;
+ tmp = temps[args[2]].val & 31;
+ mask = (int32_t)temps[args[1]].mask >> tmp;
}
break;
case INDEX_op_sar_i64:
if (temps[args[2]].state == TCG_TEMP_CONST) {
- mask = (int64_t)temps[args[1]].mask >> temps[args[2]].val;
+ tmp = temps[args[2]].val & 63;
+ mask = (int64_t)temps[args[1]].mask >> tmp;
}
break;
case INDEX_op_shr_i32:
if (temps[args[2]].state == TCG_TEMP_CONST) {
- mask = (uint32_t)temps[args[1]].mask >> temps[args[2]].val;
+ tmp = temps[args[2]].val & 31;
+ mask = (uint32_t)temps[args[1]].mask >> tmp;
}
break;
case INDEX_op_shr_i64:
if (temps[args[2]].state == TCG_TEMP_CONST) {
- mask = (uint64_t)temps[args[1]].mask >> temps[args[2]].val;
+ tmp = temps[args[2]].val & 63;
+ mask = (uint64_t)temps[args[1]].mask >> tmp;
}
break;
CASE_OP_32_64(shl):
if (temps[args[2]].state == TCG_TEMP_CONST) {
- mask = temps[args[1]].mask << temps[args[2]].val;
+ tmp = temps[args[2]].val & (TCG_TARGET_REG_BITS - 1);
+ mask = temps[args[1]].mask << tmp;
}
break;
@@ -838,9 +843,8 @@
break;
CASE_OP_32_64(deposit):
- tmp = ((1ull << args[4]) - 1);
- mask = ((temps[args[1]].mask & ~(tmp << args[3]))
- | ((temps[args[2]].mask & tmp) << args[3]));
+ mask = deposit64(temps[args[1]].mask, args[3], args[4],
+ temps[args[2]].mask);
break;
CASE_OP_32_64(or):
@@ -1055,9 +1059,8 @@
if (temps[args[1]].state == TCG_TEMP_CONST
&& temps[args[2]].state == TCG_TEMP_CONST) {
s->gen_opc_buf[op_index] = op_to_movi(op);
- tmp = ((1ull << args[4]) - 1);
- tmp = (temps[args[1]].val & ~(tmp << args[3]))
- | ((temps[args[2]].val & tmp) << args[3]);
+ tmp = deposit64(temps[args[1]].val, args[3], args[4],
+ temps[args[2]].val);
tcg_opt_gen_movi(gen_args, args[0], tmp);
gen_args += 2;
args += 5;
diff --git a/tcg/ppc/tcg-target.c b/tcg/ppc/tcg-target.c
index dc2c2df..83d9340 100644
--- a/tcg/ppc/tcg-target.c
+++ b/tcg/ppc/tcg-target.c
@@ -298,7 +298,7 @@
}
/* test if a constant matches the constraint */
-static int tcg_target_const_match(tcg_target_long val,
+static int tcg_target_const_match(tcg_target_long val, TCGType type,
const TCGArgConstraint *arg_ct)
{
int ct;
@@ -524,7 +524,7 @@
#if defined(CONFIG_SOFTMMU)
static void add_qemu_ldst_label (TCGContext *s,
- int is_ld,
+ bool is_ld,
TCGMemOp opc,
int data_reg,
int data_reg2,
@@ -720,7 +720,7 @@
break;
}
#ifdef CONFIG_SOFTMMU
- add_qemu_ldst_label(s, 1, opc, datalo, datahi, addrlo,
+ add_qemu_ldst_label(s, true, opc, datalo, datahi, addrlo,
addrhi, mem_index, s->code_ptr, label_ptr);
#endif
}
@@ -779,7 +779,7 @@
}
#ifdef CONFIG_SOFTMMU
- add_qemu_ldst_label(s, 0, opc, datalo, datahi, addrlo, addrhi,
+ add_qemu_ldst_label(s, false, opc, datalo, datahi, addrlo, addrhi,
mem_index, s->code_ptr, label_ptr);
#endif
}
diff --git a/tcg/ppc/tcg-target.h b/tcg/ppc/tcg-target.h
index e3395e3..0d4f595 100644
--- a/tcg/ppc/tcg-target.h
+++ b/tcg/ppc/tcg-target.h
@@ -24,7 +24,6 @@
#ifndef TCG_TARGET_PPC
#define TCG_TARGET_PPC 1
-#define TCG_TARGET_WORDS_BIGENDIAN
#define TCG_TARGET_NB_REGS 32
typedef enum {
@@ -95,6 +94,7 @@
#define TCG_TARGET_HAS_nor_i32 1
#define TCG_TARGET_HAS_deposit_i32 1
#define TCG_TARGET_HAS_movcond_i32 1
+#define TCG_TARGET_HAS_mulu2_i32 1
#define TCG_TARGET_HAS_muls2_i32 0
#define TCG_TARGET_HAS_muluh_i32 0
#define TCG_TARGET_HAS_mulsh_i32 0
diff --git a/tcg/ppc64/tcg-target.c b/tcg/ppc64/tcg-target.c
index 06e440f..45b1c06 100644
--- a/tcg/ppc64/tcg-target.c
+++ b/tcg/ppc64/tcg-target.c
@@ -290,13 +290,21 @@
}
/* test if a constant matches the constraint */
-static int tcg_target_const_match(tcg_target_long val,
+static int tcg_target_const_match(tcg_target_long val, TCGType type,
const TCGArgConstraint *arg_ct)
{
int ct = arg_ct->ct;
if (ct & TCG_CT_CONST) {
return 1;
- } else if ((ct & TCG_CT_CONST_S16) && val == (int16_t)val) {
+ }
+
+ /* The only 32-bit constraint we use aside from
+ TCG_CT_CONST is TCG_CT_CONST_S16. */
+ if (type == TCG_TYPE_I32) {
+ val = (int32_t)val;
+ }
+
+ if ((ct & TCG_CT_CONST_S16) && val == (int16_t)val) {
return 1;
} else if ((ct & TCG_CT_CONST_U16) && val == (uint16_t)val) {
return 1;
diff --git a/tcg/ppc64/tcg-target.h b/tcg/ppc64/tcg-target.h
index 7ee50b6..78bbf7a 100644
--- a/tcg/ppc64/tcg-target.h
+++ b/tcg/ppc64/tcg-target.h
@@ -24,7 +24,6 @@
#ifndef TCG_TARGET_PPC64
#define TCG_TARGET_PPC64 1
-#define TCG_TARGET_WORDS_BIGENDIAN
#define TCG_TARGET_NB_REGS 32
typedef enum {
diff --git a/tcg/s390/tcg-target.c b/tcg/s390/tcg-target.c
index 907d9d1..1d912a7 100644
--- a/tcg/s390/tcg-target.c
+++ b/tcg/s390/tcg-target.c
@@ -38,11 +38,10 @@
a 32-bit displacement here Just In Case. */
#define USE_LONG_BRANCHES 0
-#define TCG_CT_CONST_32 0x0100
-#define TCG_CT_CONST_MULI 0x0800
-#define TCG_CT_CONST_ORI 0x2000
-#define TCG_CT_CONST_XORI 0x4000
-#define TCG_CT_CONST_CMPI 0x8000
+#define TCG_CT_CONST_MULI 0x100
+#define TCG_CT_CONST_ORI 0x200
+#define TCG_CT_CONST_XORI 0x400
+#define TCG_CT_CONST_CMPI 0x800
/* Several places within the instruction set 0 means "no register"
rather than TCG_REG_R0. */
@@ -407,9 +406,6 @@
tcg_regset_clear(ct->u.regs);
tcg_regset_set_reg(ct->u.regs, TCG_REG_R3);
break;
- case 'W': /* force 32-bit ("word") immediate */
- ct->ct |= TCG_CT_CONST_32;
- break;
case 'K':
ct->ct |= TCG_CT_CONST_MULI;
break;
@@ -437,10 +433,10 @@
can load efficiently, and the immediate load plus the reg-reg OR is
smaller than the sequential OI's. */
-static int tcg_match_ori(int ct, tcg_target_long val)
+static int tcg_match_ori(TCGType type, tcg_target_long val)
{
if (facilities & FACILITY_EXT_IMM) {
- if (ct & TCG_CT_CONST_32) {
+ if (type == TCG_TYPE_I32) {
/* All 32-bit ORs can be performed with 1 48-bit insn. */
return 1;
}
@@ -466,13 +462,13 @@
extended-immediate facility. That said, there are a few patterns for
which it is better to load the value into a register first. */
-static int tcg_match_xori(int ct, tcg_target_long val)
+static int tcg_match_xori(TCGType type, tcg_target_long val)
{
if ((facilities & FACILITY_EXT_IMM) == 0) {
return 0;
}
- if (ct & TCG_CT_CONST_32) {
+ if (type == TCG_TYPE_I32) {
/* All 32-bit XORs can be performed with 1 48-bit insn. */
return 1;
}
@@ -487,11 +483,11 @@
/* Imediates to be used with comparisons. */
-static int tcg_match_cmpi(int ct, tcg_target_long val)
+static int tcg_match_cmpi(TCGType type, tcg_target_long val)
{
if (facilities & FACILITY_EXT_IMM) {
/* The COMPARE IMMEDIATE instruction is available. */
- if (ct & TCG_CT_CONST_32) {
+ if (type == TCG_TYPE_I32) {
/* We have a 32-bit immediate and can compare against anything. */
return 1;
} else {
@@ -515,7 +511,7 @@
}
/* Test if a constant matches the constraint. */
-static int tcg_target_const_match(tcg_target_long val,
+static int tcg_target_const_match(tcg_target_long val, TCGType type,
const TCGArgConstraint *arg_ct)
{
int ct = arg_ct->ct;
@@ -524,8 +520,7 @@
return 1;
}
- /* Handle the modifiers. */
- if (ct & TCG_CT_CONST_32) {
+ if (type == TCG_TYPE_I32) {
val = (int32_t)val;
}
@@ -541,11 +536,11 @@
return val == (int16_t)val;
}
} else if (ct & TCG_CT_CONST_ORI) {
- return tcg_match_ori(ct, val);
+ return tcg_match_ori(type, val);
} else if (ct & TCG_CT_CONST_XORI) {
- return tcg_match_xori(ct, val);
+ return tcg_match_xori(type, val);
} else if (ct & TCG_CT_CONST_CMPI) {
- return tcg_match_cmpi(ct, val);
+ return tcg_match_cmpi(type, val);
}
return 0;
@@ -2112,8 +2107,8 @@
{ INDEX_op_divu2_i32, { "b", "a", "0", "1", "r" } },
{ INDEX_op_and_i32, { "r", "0", "ri" } },
- { INDEX_op_or_i32, { "r", "0", "rWO" } },
- { INDEX_op_xor_i32, { "r", "0", "rWX" } },
+ { INDEX_op_or_i32, { "r", "0", "rO" } },
+ { INDEX_op_xor_i32, { "r", "0", "rX" } },
{ INDEX_op_neg_i32, { "r", "r" } },
@@ -2135,9 +2130,9 @@
{ INDEX_op_add2_i32, { "r", "r", "0", "1", "r", "r" } },
{ INDEX_op_sub2_i32, { "r", "r", "0", "1", "r", "r" } },
- { INDEX_op_brcond_i32, { "r", "rWC" } },
- { INDEX_op_setcond_i32, { "r", "r", "rWC" } },
- { INDEX_op_movcond_i32, { "r", "r", "rWC", "r", "0" } },
+ { INDEX_op_brcond_i32, { "r", "rC" } },
+ { INDEX_op_setcond_i32, { "r", "r", "rC" } },
+ { INDEX_op_movcond_i32, { "r", "r", "rC", "r", "0" } },
{ INDEX_op_deposit_i32, { "r", "0", "r" } },
{ INDEX_op_qemu_ld8u, { "r", "L" } },
diff --git a/tcg/s390/tcg-target.h b/tcg/s390/tcg-target.h
index 10adb77..b3bfdcc 100644
--- a/tcg/s390/tcg-target.h
+++ b/tcg/s390/tcg-target.h
@@ -24,8 +24,6 @@
#ifndef TCG_TARGET_S390
#define TCG_TARGET_S390 1
-#define TCG_TARGET_WORDS_BIGENDIAN
-
typedef enum TCGReg {
TCG_REG_R0 = 0,
TCG_REG_R1,
diff --git a/tcg/sparc/tcg-target.c b/tcg/sparc/tcg-target.c
index 152335c..35089b8 100644
--- a/tcg/sparc/tcg-target.c
+++ b/tcg/sparc/tcg-target.c
@@ -327,14 +327,20 @@
}
/* test if a constant matches the constraint */
-static inline int tcg_target_const_match(tcg_target_long val,
+static inline int tcg_target_const_match(tcg_target_long val, TCGType type,
const TCGArgConstraint *arg_ct)
{
int ct = arg_ct->ct;
if (ct & TCG_CT_CONST) {
return 1;
- } else if ((ct & TCG_CT_CONST_ZERO) && val == 0) {
+ }
+
+ if (type == TCG_TYPE_I32) {
+ val = (int32_t)val;
+ }
+
+ if ((ct & TCG_CT_CONST_ZERO) && val == 0) {
return 1;
} else if ((ct & TCG_CT_CONST_S11) && check_fit_tl(val, 11)) {
return 1;
diff --git a/tcg/sparc/tcg-target.h b/tcg/sparc/tcg-target.h
index 3abf1b4..4519c64 100644
--- a/tcg/sparc/tcg-target.h
+++ b/tcg/sparc/tcg-target.h
@@ -32,8 +32,6 @@
# error Unknown pointer size for tcg target
#endif
-#define TCG_TARGET_WORDS_BIGENDIAN
-
#define TCG_TARGET_NB_REGS 32
typedef enum {
diff --git a/tcg/tcg-be-ldst.h b/tcg/tcg-be-ldst.h
index 284db0c..ad94c0c 100644
--- a/tcg/tcg-be-ldst.h
+++ b/tcg/tcg-be-ldst.h
@@ -24,7 +24,7 @@
#define TCG_MAX_QEMU_LDST 640
typedef struct TCGLabelQemuLdst {
- int is_ld:1; /* qemu_ld: 1, qemu_st: 0 */
+ bool is_ld:1; /* qemu_ld: true, qemu_st: false */
TCGMemOp opc:4;
TCGReg addrlo_reg; /* reg index for low word of guest virtual addr */
TCGReg addrhi_reg; /* reg index for high word of guest virtual addr */
diff --git a/tcg/tcg-op.h b/tcg/tcg-op.h
index 7eabf22..8d4ff7d 100644
--- a/tcg/tcg-op.h
+++ b/tcg/tcg-op.h
@@ -858,7 +858,7 @@
{
/* since arg2 and ret have different types, they cannot be the
same temporary */
-#ifdef TCG_TARGET_WORDS_BIGENDIAN
+#ifdef HOST_WORDS_BIGENDIAN
tcg_gen_ld_i32(TCGV_HIGH(ret), arg2, offset);
tcg_gen_ld_i32(TCGV_LOW(ret), arg2, offset + 4);
#else
@@ -888,7 +888,7 @@
static inline void tcg_gen_st_i64(TCGv_i64 arg1, TCGv_ptr arg2,
tcg_target_long offset)
{
-#ifdef TCG_TARGET_WORDS_BIGENDIAN
+#ifdef HOST_WORDS_BIGENDIAN
tcg_gen_st_i32(TCGV_HIGH(arg1), arg2, offset);
tcg_gen_st_i32(TCGV_LOW(arg1), arg2, offset + 4);
#else
@@ -2437,14 +2437,12 @@
tcg_gen_op3_i32(INDEX_op_mulsh_i32, rh, arg1, arg2);
tcg_gen_mov_i32(rl, t);
tcg_temp_free_i32(t);
- } else if (TCG_TARGET_REG_BITS == 32 && TCG_TARGET_HAS_mulu2_i32) {
+ } else if (TCG_TARGET_REG_BITS == 32) {
TCGv_i32 t0 = tcg_temp_new_i32();
TCGv_i32 t1 = tcg_temp_new_i32();
TCGv_i32 t2 = tcg_temp_new_i32();
TCGv_i32 t3 = tcg_temp_new_i32();
- tcg_gen_op4_i32(INDEX_op_mulu2_i32, t0, t1, arg1, arg2);
- /* Allow the optimizer room to replace mulu2 with two moves. */
- tcg_gen_op0(INDEX_op_nop);
+ tcg_gen_mulu2_i32(t0, t1, arg1, arg2);
/* Adjust for negative inputs. */
tcg_gen_sari_i32(t2, arg1, 31);
tcg_gen_sari_i32(t3, arg2, 31);
@@ -2522,26 +2520,6 @@
tcg_gen_op3_i64(INDEX_op_muluh_i64, rh, arg1, arg2);
tcg_gen_mov_i64(rl, t);
tcg_temp_free_i64(t);
- } else if (TCG_TARGET_HAS_mulu2_i64) {
- TCGv_i64 t0 = tcg_temp_new_i64();
- TCGv_i64 t1 = tcg_temp_new_i64();
- TCGv_i64 t2 = tcg_temp_new_i64();
- TCGv_i64 t3 = tcg_temp_new_i64();
- tcg_gen_op4_i64(INDEX_op_mulu2_i64, t0, t1, arg1, arg2);
- /* Allow the optimizer room to replace mulu2 with two moves. */
- tcg_gen_op0(INDEX_op_nop);
- /* Adjust for negative inputs. */
- tcg_gen_sari_i64(t2, arg1, 63);
- tcg_gen_sari_i64(t3, arg2, 63);
- tcg_gen_and_i64(t2, t2, arg2);
- tcg_gen_and_i64(t3, t3, arg1);
- tcg_gen_sub_i64(rh, t1, t2);
- tcg_gen_sub_i64(rh, rh, t3);
- tcg_gen_mov_i64(rl, t0);
- tcg_temp_free_i64(t0);
- tcg_temp_free_i64(t1);
- tcg_temp_free_i64(t2);
- tcg_temp_free_i64(t3);
} else {
TCGv_i64 t0 = tcg_temp_new_i64();
int sizemask = 0;
@@ -2569,6 +2547,24 @@
tcg_gen_op3_i64(INDEX_op_mulsh_i64, rh, arg1, arg2);
tcg_gen_mov_i64(rl, t);
tcg_temp_free_i64(t);
+ } else if (TCG_TARGET_HAS_mulu2_i64 || TCG_TARGET_HAS_muluh_i64) {
+ TCGv_i64 t0 = tcg_temp_new_i64();
+ TCGv_i64 t1 = tcg_temp_new_i64();
+ TCGv_i64 t2 = tcg_temp_new_i64();
+ TCGv_i64 t3 = tcg_temp_new_i64();
+ tcg_gen_mulu2_i64(t0, t1, arg1, arg2);
+ /* Adjust for negative inputs. */
+ tcg_gen_sari_i64(t2, arg1, 63);
+ tcg_gen_sari_i64(t3, arg2, 63);
+ tcg_gen_and_i64(t2, t2, arg2);
+ tcg_gen_and_i64(t3, t3, arg1);
+ tcg_gen_sub_i64(rh, t1, t2);
+ tcg_gen_sub_i64(rh, rh, t3);
+ tcg_gen_mov_i64(rl, t0);
+ tcg_temp_free_i64(t0);
+ tcg_temp_free_i64(t1);
+ tcg_temp_free_i64(t2);
+ tcg_temp_free_i64(t3);
} else {
TCGv_i64 t0 = tcg_temp_new_i64();
int sizemask = 0;
diff --git a/tcg/tcg.c b/tcg/tcg.c
index f1e0763..21ce9fb 100644
--- a/tcg/tcg.c
+++ b/tcg/tcg.c
@@ -101,7 +101,7 @@
const int *const_args);
static void tcg_out_st(TCGContext *s, TCGType type, TCGReg arg, TCGReg arg1,
intptr_t arg2);
-static int tcg_target_const_match(tcg_target_long val,
+static int tcg_target_const_match(tcg_target_long val, TCGType type,
const TCGArgConstraint *arg_ct);
static void tcg_out_tb_init(TCGContext *s);
static void tcg_out_tb_finalize(TCGContext *s);
@@ -444,7 +444,7 @@
ts->fixed_reg = 0;
ts->mem_allocated = 1;
ts->mem_reg = reg;
-#ifdef TCG_TARGET_WORDS_BIGENDIAN
+#ifdef HOST_WORDS_BIGENDIAN
ts->mem_offset = offset + 4;
#else
ts->mem_offset = offset;
@@ -459,7 +459,7 @@
ts->fixed_reg = 0;
ts->mem_allocated = 1;
ts->mem_reg = reg;
-#ifdef TCG_TARGET_WORDS_BIGENDIAN
+#ifdef HOST_WORDS_BIGENDIAN
ts->mem_offset = offset;
#else
ts->mem_offset = offset + 4;
@@ -686,7 +686,7 @@
if (ret != TCG_CALL_DUMMY_ARG) {
#if TCG_TARGET_REG_BITS < 64
if (sizemask & 1) {
-#ifdef TCG_TARGET_WORDS_BIGENDIAN
+#ifdef HOST_WORDS_BIGENDIAN
*s->gen_opparam_ptr++ = ret + 1;
*s->gen_opparam_ptr++ = ret;
#else
@@ -725,7 +725,7 @@
order. If another such target is added, this logic may
have to get more complicated to differentiate between
stack arguments and register arguments. */
-#if defined(TCG_TARGET_WORDS_BIGENDIAN) != defined(TCG_TARGET_STACK_GROWSUP)
+#if defined(HOST_WORDS_BIGENDIAN) != defined(TCG_TARGET_STACK_GROWSUP)
*s->gen_opparam_ptr++ = args[i] + 1;
*s->gen_opparam_ptr++ = args[i];
#else
@@ -2121,7 +2121,7 @@
ts->mem_coherent = 1;
s->reg_to_temp[reg] = arg;
} else if (ts->val_type == TEMP_VAL_CONST) {
- if (tcg_target_const_match(ts->val, arg_ct)) {
+ if (tcg_target_const_match(ts->val, ts->type, arg_ct)) {
/* constant is OK for instruction */
const_args[i] = 1;
new_args[i] = ts->val;
@@ -2365,7 +2365,7 @@
func_arg = reg;
tcg_regset_set_reg(allocated_regs, reg);
} else if (ts->val_type == TEMP_VAL_CONST) {
- if (tcg_target_const_match(func_addr, arg_ct)) {
+ if (tcg_target_const_match(func_addr, ts->type, arg_ct)) {
const_func_arg = 1;
func_arg = func_addr;
} else {
diff --git a/tcg/tcg.h b/tcg/tcg.h
index f7efcb4..0bb6677 100644
--- a/tcg/tcg.h
+++ b/tcg/tcg.h
@@ -97,7 +97,6 @@
/* Turn some undef macros into true macros. */
#define TCG_TARGET_HAS_add2_i32 1
#define TCG_TARGET_HAS_sub2_i32 1
-#define TCG_TARGET_HAS_mulu2_i32 1
#endif
#ifndef TCG_TARGET_deposit_i32_valid
@@ -121,6 +120,13 @@
#define TCG_TARGET_HAS_rem_i64 0
#endif
+/* For 32-bit targets, some sort of unsigned widening multiply is required. */
+#if TCG_TARGET_REG_BITS == 32 \
+ && !(defined(TCG_TARGET_HAS_mulu2_i32) \
+ || defined(TCG_TARGET_HAS_muluh_i32))
+# error "Missing unsigned widening multiply"
+#endif
+
typedef enum TCGOpcode {
#define DEF(name, oargs, iargs, cargs, flags) INDEX_op_ ## name,
#include "tcg-opc.h"
diff --git a/tcg/tci/tcg-target.c b/tcg/tci/tcg-target.c
index fc80704..47c0b85 100644
--- a/tcg/tci/tcg-target.c
+++ b/tcg/tci/tcg-target.c
@@ -859,7 +859,7 @@
}
/* Test if a constant matches the constraint. */
-static int tcg_target_const_match(tcg_target_long val,
+static int tcg_target_const_match(tcg_target_long val, TCGType type,
const TCGArgConstraint *arg_ct)
{
/* No need to return 0 or 1, 0 or != 0 is good enough. */
diff --git a/tcg/tci/tcg-target.h b/tcg/tci/tcg-target.h
index 6e1da8c..f43492c 100644
--- a/tcg/tci/tcg-target.h
+++ b/tcg/tci/tcg-target.h
@@ -57,12 +57,6 @@
#define CONFIG_DEBUG_TCG_INTERPRETER
#endif
-#if 0 /* TCI tries to emulate a little endian host. */
-#if defined(HOST_WORDS_BIGENDIAN)
-# define TCG_TARGET_WORDS_BIGENDIAN
-#endif
-#endif
-
/* Optional instructions. */
#define TCG_TARGET_HAS_bswap16_i32 1
@@ -118,6 +112,8 @@
#define TCG_TARGET_HAS_mulu2_i64 0
#define TCG_TARGET_HAS_muluh_i64 0
#define TCG_TARGET_HAS_mulsh_i64 0
+#else
+#define TCG_TARGET_HAS_mulu2_i32 1
#endif /* TCG_TARGET_REG_BITS == 64 */
#define TCG_TARGET_HAS_new_ldst 0
diff --git a/tci.c b/tci.c
index 0202ed9..6523ab8 100644
--- a/tci.c
+++ b/tci.c
@@ -669,32 +669,32 @@
t0 = *tb_ptr++;
t1 = tci_read_ri32(&tb_ptr);
t2 = tci_read_ri32(&tb_ptr);
- tci_write_reg32(t0, t1 << t2);
+ tci_write_reg32(t0, t1 << (t2 & 31));
break;
case INDEX_op_shr_i32:
t0 = *tb_ptr++;
t1 = tci_read_ri32(&tb_ptr);
t2 = tci_read_ri32(&tb_ptr);
- tci_write_reg32(t0, t1 >> t2);
+ tci_write_reg32(t0, t1 >> (t2 & 31));
break;
case INDEX_op_sar_i32:
t0 = *tb_ptr++;
t1 = tci_read_ri32(&tb_ptr);
t2 = tci_read_ri32(&tb_ptr);
- tci_write_reg32(t0, ((int32_t)t1 >> t2));
+ tci_write_reg32(t0, ((int32_t)t1 >> (t2 & 31)));
break;
#if TCG_TARGET_HAS_rot_i32
case INDEX_op_rotl_i32:
t0 = *tb_ptr++;
t1 = tci_read_ri32(&tb_ptr);
t2 = tci_read_ri32(&tb_ptr);
- tci_write_reg32(t0, rol32(t1, t2));
+ tci_write_reg32(t0, rol32(t1, t2 & 31));
break;
case INDEX_op_rotr_i32:
t0 = *tb_ptr++;
t1 = tci_read_ri32(&tb_ptr);
t2 = tci_read_ri32(&tb_ptr);
- tci_write_reg32(t0, ror32(t1, t2));
+ tci_write_reg32(t0, ror32(t1, t2 & 31));
break;
#endif
#if TCG_TARGET_HAS_deposit_i32
@@ -936,32 +936,32 @@
t0 = *tb_ptr++;
t1 = tci_read_ri64(&tb_ptr);
t2 = tci_read_ri64(&tb_ptr);
- tci_write_reg64(t0, t1 << t2);
+ tci_write_reg64(t0, t1 << (t2 & 63));
break;
case INDEX_op_shr_i64:
t0 = *tb_ptr++;
t1 = tci_read_ri64(&tb_ptr);
t2 = tci_read_ri64(&tb_ptr);
- tci_write_reg64(t0, t1 >> t2);
+ tci_write_reg64(t0, t1 >> (t2 & 63));
break;
case INDEX_op_sar_i64:
t0 = *tb_ptr++;
t1 = tci_read_ri64(&tb_ptr);
t2 = tci_read_ri64(&tb_ptr);
- tci_write_reg64(t0, ((int64_t)t1 >> t2));
+ tci_write_reg64(t0, ((int64_t)t1 >> (t2 & 63)));
break;
#if TCG_TARGET_HAS_rot_i64
case INDEX_op_rotl_i64:
t0 = *tb_ptr++;
t1 = tci_read_ri64(&tb_ptr);
t2 = tci_read_ri64(&tb_ptr);
- tci_write_reg64(t0, rol64(t1, t2));
+ tci_write_reg64(t0, rol64(t1, t2 & 63));
break;
case INDEX_op_rotr_i64:
t0 = *tb_ptr++;
t1 = tci_read_ri64(&tb_ptr);
t2 = tci_read_ri64(&tb_ptr);
- tci_write_reg64(t0, ror64(t1, t2));
+ tci_write_reg64(t0, ror64(t1, t2 & 63));
break;
#endif
#if TCG_TARGET_HAS_deposit_i64
diff --git a/vl.c b/vl.c
index 9975e5a..db9ea90 100644
--- a/vl.c
+++ b/vl.c
@@ -2740,7 +2740,7 @@
if (!accel_list[i].available()) {
printf("%s not supported for this target\n",
accel_list[i].name);
- continue;
+ break;
}
*(accel_list[i].allowed) = true;
ret = accel_list[i].init(machine);
diff --git a/xbzrle.c b/xbzrle.c
index fbcb35d..8e220bf 100644
--- a/xbzrle.c
+++ b/xbzrle.c
@@ -28,7 +28,7 @@
{
uint32_t zrun_len = 0, nzrun_len = 0;
int d = 0, i = 0;
- long res, xor;
+ long res;
uint8_t *nzrun_start = NULL;
g_assert(!(((uintptr_t)old_buf | (uintptr_t)new_buf | slen) %
@@ -93,9 +93,11 @@
/* word at a time for speed, use of 32-bit long okay */
if (!res) {
/* truncation to 32-bit long okay */
- long mask = (long)0x0101010101010101ULL;
+ unsigned long mask = (unsigned long)0x0101010101010101ULL;
while (i < slen) {
- xor = *(long *)(old_buf + i) ^ *(long *)(new_buf + i);
+ unsigned long xor;
+ xor = *(unsigned long *)(old_buf + i)
+ ^ *(unsigned long *)(new_buf + i);
if ((xor - mask) & ~xor & (mask << 7)) {
/* found the end of an nzrun within the current long */
while (old_buf[i] != new_buf[i]) {