Pull patches queued for qemu 1.2.1

This commit is contained in:
Cole Robinson 2012-10-28 14:05:07 -04:00
parent ae1cd7de6a
commit 5544c1b492
309 changed files with 44371 additions and 1062 deletions

View File

@ -1,14 +0,0 @@
--- qemu-kvm-1.2.0/qemu-char.c~ 2012-09-12 19:46:36.491936229 +0100
+++ qemu-kvm-1.2.0/qemu-char.c 2012-09-12 19:47:33.349972760 +0100
@@ -2268,9 +2268,8 @@
}
return ret;
} else {
- /* (Re-)connect for unconnected writing */
- tcp_chr_connect(chr);
- return 0;
+ /* XXX: indicate an error ? */
+ return len;
}
}

View File

@ -0,0 +1,183 @@
From 707f294ca28977968fb85bf36f10c6b37b16f557 Mon Sep 17 00:00:00 2001
From: Max Filippov <jcmvbkbc@gmail.com>
Date: Wed, 29 Aug 2012 23:54:25 +0400
Subject: [PATCH] target-xtensa: convert host errno values to guest
Guest errno values are taken from the newlib. Convert only those errno
values that can be returned from used system calls.
Signed-off-by: Max Filippov <jcmvbkbc@gmail.com>
Signed-off-by: Blue Swirl <blauwirbel@gmail.com>
Signed-off-by: Michael Roth <mdroth@linux.vnet.ibm.com>
---
target-xtensa/xtensa-semi.c | 106 ++++++++++++++++++++++++++++++++++++++++----
1 file changed, 98 insertions(+), 8 deletions(-)
diff --git a/target-xtensa/xtensa-semi.c b/target-xtensa/xtensa-semi.c
index 6d001c2..e745bef 100644
--- a/target-xtensa/xtensa-semi.c
+++ b/target-xtensa/xtensa-semi.c
@@ -54,6 +54,96 @@ enum {
SELECT_ONE_EXCEPT = 3,
};
+enum {
+ TARGET_EPERM = 1,
+ TARGET_ENOENT = 2,
+ TARGET_ESRCH = 3,
+ TARGET_EINTR = 4,
+ TARGET_EIO = 5,
+ TARGET_ENXIO = 6,
+ TARGET_E2BIG = 7,
+ TARGET_ENOEXEC = 8,
+ TARGET_EBADF = 9,
+ TARGET_ECHILD = 10,
+ TARGET_EAGAIN = 11,
+ TARGET_ENOMEM = 12,
+ TARGET_EACCES = 13,
+ TARGET_EFAULT = 14,
+ TARGET_ENOTBLK = 15,
+ TARGET_EBUSY = 16,
+ TARGET_EEXIST = 17,
+ TARGET_EXDEV = 18,
+ TARGET_ENODEV = 19,
+ TARGET_ENOTDIR = 20,
+ TARGET_EISDIR = 21,
+ TARGET_EINVAL = 22,
+ TARGET_ENFILE = 23,
+ TARGET_EMFILE = 24,
+ TARGET_ENOTTY = 25,
+ TARGET_ETXTBSY = 26,
+ TARGET_EFBIG = 27,
+ TARGET_ENOSPC = 28,
+ TARGET_ESPIPE = 29,
+ TARGET_EROFS = 30,
+ TARGET_EMLINK = 31,
+ TARGET_EPIPE = 32,
+ TARGET_EDOM = 33,
+ TARGET_ERANGE = 34,
+ TARGET_ENOSYS = 88,
+ TARGET_ELOOP = 92,
+};
+
+static uint32_t errno_h2g(int host_errno)
+{
+ static const uint32_t guest_errno[] = {
+ [EPERM] = TARGET_EPERM,
+ [ENOENT] = TARGET_ENOENT,
+ [ESRCH] = TARGET_ESRCH,
+ [EINTR] = TARGET_EINTR,
+ [EIO] = TARGET_EIO,
+ [ENXIO] = TARGET_ENXIO,
+ [E2BIG] = TARGET_E2BIG,
+ [ENOEXEC] = TARGET_ENOEXEC,
+ [EBADF] = TARGET_EBADF,
+ [ECHILD] = TARGET_ECHILD,
+ [EAGAIN] = TARGET_EAGAIN,
+ [ENOMEM] = TARGET_ENOMEM,
+ [EACCES] = TARGET_EACCES,
+ [EFAULT] = TARGET_EFAULT,
+ [ENOTBLK] = TARGET_ENOTBLK,
+ [EBUSY] = TARGET_EBUSY,
+ [EEXIST] = TARGET_EEXIST,
+ [EXDEV] = TARGET_EXDEV,
+ [ENODEV] = TARGET_ENODEV,
+ [ENOTDIR] = TARGET_ENOTDIR,
+ [EISDIR] = TARGET_EISDIR,
+ [EINVAL] = TARGET_EINVAL,
+ [ENFILE] = TARGET_ENFILE,
+ [EMFILE] = TARGET_EMFILE,
+ [ENOTTY] = TARGET_ENOTTY,
+ [ETXTBSY] = TARGET_ETXTBSY,
+ [EFBIG] = TARGET_EFBIG,
+ [ENOSPC] = TARGET_ENOSPC,
+ [ESPIPE] = TARGET_ESPIPE,
+ [EROFS] = TARGET_EROFS,
+ [EMLINK] = TARGET_EMLINK,
+ [EPIPE] = TARGET_EPIPE,
+ [EDOM] = TARGET_EDOM,
+ [ERANGE] = TARGET_ERANGE,
+ [ENOSYS] = TARGET_ENOSYS,
+ [ELOOP] = TARGET_ELOOP,
+ };
+
+ if (host_errno == 0) {
+ return 0;
+ } else if (host_errno > 0 && host_errno < ARRAY_SIZE(guest_errno) &&
+ guest_errno[host_errno]) {
+ return guest_errno[host_errno];
+ } else {
+ return TARGET_EINVAL;
+ }
+}
+
void HELPER(simcall)(CPUXtensaState *env)
{
uint32_t *regs = env->regs;
@@ -87,14 +177,14 @@ void HELPER(simcall)(CPUXtensaState *env)
regs[2] = is_write ?
write(fd, buf, io_sz) :
read(fd, buf, io_sz);
- regs[3] = errno;
+ regs[3] = errno_h2g(errno);
cpu_physical_memory_unmap(buf, sz, is_write, sz);
if (regs[2] == -1) {
break;
}
} else {
regs[2] = -1;
- regs[3] = EINVAL;
+ regs[3] = TARGET_EINVAL;
break;
}
}
@@ -117,10 +207,10 @@ void HELPER(simcall)(CPUXtensaState *env)
if (rc == 0 && i < ARRAY_SIZE(name)) {
regs[2] = open(name, regs[4], regs[5]);
- regs[3] = errno;
+ regs[3] = errno_h2g(errno);
} else {
regs[2] = -1;
- regs[3] = EINVAL;
+ regs[3] = TARGET_EINVAL;
}
}
break;
@@ -130,13 +220,13 @@ void HELPER(simcall)(CPUXtensaState *env)
regs[2] = regs[3] = 0;
} else {
regs[2] = close(regs[3]);
- regs[3] = errno;
+ regs[3] = errno_h2g(errno);
}
break;
case TARGET_SYS_lseek:
regs[2] = lseek(regs[3], (off_t)(int32_t)regs[4], regs[5]);
- regs[3] = errno;
+ regs[3] = errno_h2g(errno);
break;
case TARGET_SYS_select_one:
@@ -163,7 +253,7 @@ void HELPER(simcall)(CPUXtensaState *env)
rq == SELECT_ONE_WRITE ? &fdset : NULL,
rq == SELECT_ONE_EXCEPT ? &fdset : NULL,
target_tv ? &tv : NULL);
- regs[3] = errno;
+ regs[3] = errno_h2g(errno);
}
break;
@@ -219,7 +309,7 @@ void HELPER(simcall)(CPUXtensaState *env)
default:
qemu_log("%s(%d): not implemented\n", __func__, regs[2]);
regs[2] = -1;
- regs[3] = ENOSYS;
+ regs[3] = TARGET_ENOSYS;
break;
}
}
--
1.7.12.1

View File

@ -0,0 +1,35 @@
From 8057ac10e8cba3acb89c11c94f04967306e55a9f Mon Sep 17 00:00:00 2001
From: Stefan Weil <sw@weilnetz.de>
Date: Fri, 7 Sep 2012 22:36:08 +0200
Subject: [PATCH] target-cris: Fix buffer overflow
Report from smatch:
target-cris/translate.c:3464 cpu_dump_state(32) error:
buffer overflow 'env->sregs' 4 <= 255
sregs is declared 'uint32_t sregs[4][16]', so the first index must be
less than 4 or ARRAY_SIZE(env->sregs).
Signed-off-by: Stefan Weil <sw@weilnetz.de>
Signed-off-by: Michael Roth <mdroth@linux.vnet.ibm.com>
---
target-cris/translate.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/target-cris/translate.c b/target-cris/translate.c
index 1ad9ec7..ad31877 100644
--- a/target-cris/translate.c
+++ b/target-cris/translate.c
@@ -3458,7 +3458,7 @@ void cpu_dump_state (CPUCRISState *env, FILE *f, fprintf_function cpu_fprintf,
}
srs = env->pregs[PR_SRS];
cpu_fprintf(f, "\nsupport function regs bank %x:\n", srs);
- if (srs < 256) {
+ if (srs < ARRAY_SIZE(env->sregs)) {
for (i = 0; i < 16; i++) {
cpu_fprintf(f, "s%2.2d=%8.8x ",
i, env->sregs[srs][i]);
--
1.7.12.1

View File

@ -0,0 +1,64 @@
From 33e25a4a6c6dc7632b15ee50637d33b4c3cf729e Mon Sep 17 00:00:00 2001
From: Max Filippov <jcmvbkbc@gmail.com>
Date: Thu, 6 Sep 2012 04:36:46 +0400
Subject: [PATCH] target-xtensa: fix missing errno codes for mingw32
Put the following errno value mappings under #ifdef:
xtensa-semi.c: In function 'errno_h2g':
xtensa-semi.c:113: error: 'ENOTBLK' undeclared (first use in this function)
xtensa-semi.c:113: error: (Each undeclared identifier is reported only once
xtensa-semi.c:113: error: for each function it appears in.)
xtensa-semi.c:113: error: array index in initializer not of integer type
xtensa-semi.c:113: error: (near initialization for 'guest_errno')
xtensa-semi.c:124: error: 'ETXTBSY' undeclared (first use in this function)
xtensa-semi.c:124: error: array index in initializer not of integer type
xtensa-semi.c:124: error: (near initialization for 'guest_errno')
xtensa-semi.c:134: error: 'ELOOP' undeclared (first use in this function)
xtensa-semi.c:134: error: array index in initializer not of integer type
xtensa-semi.c:134: error: (near initialization for 'guest_errno')
Signed-off-by: Max Filippov <jcmvbkbc@gmail.com>
Signed-off-by: Blue Swirl <blauwirbel@gmail.com>
Signed-off-by: Michael Roth <mdroth@linux.vnet.ibm.com>
---
target-xtensa/xtensa-semi.c | 6 ++++++
1 file changed, 6 insertions(+)
diff --git a/target-xtensa/xtensa-semi.c b/target-xtensa/xtensa-semi.c
index e745bef..52be07a 100644
--- a/target-xtensa/xtensa-semi.c
+++ b/target-xtensa/xtensa-semi.c
@@ -110,7 +110,9 @@ static uint32_t errno_h2g(int host_errno)
[ENOMEM] = TARGET_ENOMEM,
[EACCES] = TARGET_EACCES,
[EFAULT] = TARGET_EFAULT,
+#ifdef ENOTBLK
[ENOTBLK] = TARGET_ENOTBLK,
+#endif
[EBUSY] = TARGET_EBUSY,
[EEXIST] = TARGET_EEXIST,
[EXDEV] = TARGET_EXDEV,
@@ -121,7 +123,9 @@ static uint32_t errno_h2g(int host_errno)
[ENFILE] = TARGET_ENFILE,
[EMFILE] = TARGET_EMFILE,
[ENOTTY] = TARGET_ENOTTY,
+#ifdef ETXTBSY
[ETXTBSY] = TARGET_ETXTBSY,
+#endif
[EFBIG] = TARGET_EFBIG,
[ENOSPC] = TARGET_ENOSPC,
[ESPIPE] = TARGET_ESPIPE,
@@ -131,7 +135,9 @@ static uint32_t errno_h2g(int host_errno)
[EDOM] = TARGET_EDOM,
[ERANGE] = TARGET_ERANGE,
[ENOSYS] = TARGET_ENOSYS,
+#ifdef ELOOP
[ELOOP] = TARGET_ELOOP,
+#endif
};
if (host_errno == 0) {
--
1.7.12.1

View File

@ -0,0 +1,133 @@
From 5e955b895d4a92cdc49c7b4e76284483d49aa4b8 Mon Sep 17 00:00:00 2001
From: Aurelien Jarno <aurelien@aurel32.net>
Date: Fri, 7 Sep 2012 17:13:28 +0200
Subject: [PATCH] target-sparc: fix fcmp{s,d,q} instructions wrt exception
fcmp{s,d,q} instructions are supposed to ignore quiet NaN (contrary to
the fcmpe{s,d,q} instructions), but the current code is wrongly setting
the NV exception in that case. Moreover the current code is duplicated:
first the arguments are checked for NaN to generate an exception, and
later in case the comparison is unordered (which can only happens if one
of the argument is a NaN), the same check is done to generate an
exception.
Fix that by calling clear_float_exceptions() followed by
check_ieee_exceptions() as for the other floating point instructions.
Use the _compare_quiet functions for fcmp{s,d,q} and the _compare ones
for fcmpe{s,d,q}. Simplify the flag setting by not clearing a flag that
is set the line just below.
This fix allows the math glibc testsuite to pass.
Cc: Blue Swirl <blauwirbel@gmail.com>
Signed-off-by: Aurelien Jarno <aurelien@aurel32.net>
Signed-off-by: Blue Swirl <blauwirbel@gmail.com>
Signed-off-by: Michael Roth <mdroth@linux.vnet.ibm.com>
---
target-sparc/fop_helper.c | 67 +++++++++++++++++++----------------------------
1 file changed, 27 insertions(+), 40 deletions(-)
diff --git a/target-sparc/fop_helper.c b/target-sparc/fop_helper.c
index 9c64ef8..f4b62a5 100644
--- a/target-sparc/fop_helper.c
+++ b/target-sparc/fop_helper.c
@@ -334,34 +334,28 @@ void helper_fsqrtq(CPUSPARCState *env)
}
#define GEN_FCMP(name, size, reg1, reg2, FS, E) \
- void glue(helper_, name) (CPUSPARCState *env) \
+ void glue(helper_, name) (CPUSPARCState *env) \
{ \
- env->fsr &= FSR_FTT_NMASK; \
- if (E && (glue(size, _is_any_nan)(reg1) || \
- glue(size, _is_any_nan)(reg2)) && \
- (env->fsr & FSR_NVM)) { \
- env->fsr |= FSR_NVC; \
- env->fsr |= FSR_FTT_IEEE_EXCP; \
- helper_raise_exception(env, TT_FP_EXCP); \
+ int ret; \
+ clear_float_exceptions(env); \
+ if (E) { \
+ ret = glue(size, _compare)(reg1, reg2, &env->fp_status); \
+ } else { \
+ ret = glue(size, _compare_quiet)(reg1, reg2, \
+ &env->fp_status); \
} \
- switch (glue(size, _compare) (reg1, reg2, &env->fp_status)) { \
+ check_ieee_exceptions(env); \
+ switch (ret) { \
case float_relation_unordered: \
- if ((env->fsr & FSR_NVM)) { \
- env->fsr |= FSR_NVC; \
- env->fsr |= FSR_FTT_IEEE_EXCP; \
- helper_raise_exception(env, TT_FP_EXCP); \
- } else { \
- env->fsr &= ~((FSR_FCC1 | FSR_FCC0) << FS); \
- env->fsr |= (FSR_FCC1 | FSR_FCC0) << FS; \
- env->fsr |= FSR_NVA; \
- } \
+ env->fsr |= (FSR_FCC1 | FSR_FCC0) << FS; \
+ env->fsr |= FSR_NVA; \
break; \
case float_relation_less: \
- env->fsr &= ~((FSR_FCC1 | FSR_FCC0) << FS); \
+ env->fsr &= ~(FSR_FCC1) << FS; \
env->fsr |= FSR_FCC0 << FS; \
break; \
case float_relation_greater: \
- env->fsr &= ~((FSR_FCC1 | FSR_FCC0) << FS); \
+ env->fsr &= ~(FSR_FCC0) << FS; \
env->fsr |= FSR_FCC1 << FS; \
break; \
default: \
@@ -370,34 +364,27 @@ void helper_fsqrtq(CPUSPARCState *env)
} \
}
#define GEN_FCMP_T(name, size, FS, E) \
- void glue(helper_, name)(CPUSPARCState *env, size src1, size src2) \
+ void glue(helper_, name)(CPUSPARCState *env, size src1, size src2) \
{ \
- env->fsr &= FSR_FTT_NMASK; \
- if (E && (glue(size, _is_any_nan)(src1) || \
- glue(size, _is_any_nan)(src2)) && \
- (env->fsr & FSR_NVM)) { \
- env->fsr |= FSR_NVC; \
- env->fsr |= FSR_FTT_IEEE_EXCP; \
- helper_raise_exception(env, TT_FP_EXCP); \
+ int ret; \
+ clear_float_exceptions(env); \
+ if (E) { \
+ ret = glue(size, _compare)(src1, src2, &env->fp_status); \
+ } else { \
+ ret = glue(size, _compare_quiet)(src1, src2, \
+ &env->fp_status); \
} \
- switch (glue(size, _compare) (src1, src2, &env->fp_status)) { \
+ check_ieee_exceptions(env); \
+ switch (ret) { \
case float_relation_unordered: \
- if ((env->fsr & FSR_NVM)) { \
- env->fsr |= FSR_NVC; \
- env->fsr |= FSR_FTT_IEEE_EXCP; \
- helper_raise_exception(env, TT_FP_EXCP); \
- } else { \
- env->fsr &= ~((FSR_FCC1 | FSR_FCC0) << FS); \
- env->fsr |= (FSR_FCC1 | FSR_FCC0) << FS; \
- env->fsr |= FSR_NVA; \
- } \
+ env->fsr |= (FSR_FCC1 | FSR_FCC0) << FS; \
break; \
case float_relation_less: \
- env->fsr &= ~((FSR_FCC1 | FSR_FCC0) << FS); \
+ env->fsr &= ~(FSR_FCC1 << FS); \
env->fsr |= FSR_FCC0 << FS; \
break; \
case float_relation_greater: \
- env->fsr &= ~((FSR_FCC1 | FSR_FCC0) << FS); \
+ env->fsr &= ~(FSR_FCC0 << FS); \
env->fsr |= FSR_FCC1 << FS; \
break; \
default: \
--
1.7.12.1

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,444 @@
From e9f67c1f326a995ff0000a08a223435386867d8f Mon Sep 17 00:00:00 2001
From: Blue Swirl <blauwirbel@gmail.com>
Date: Sun, 2 Sep 2012 07:33:33 +0000
Subject: [PATCH] target-s390x: split integer helpers
Move integer helpers to int_helper.c.
Signed-off-by: Blue Swirl <blauwirbel@gmail.com>
Signed-off-by: Alexander Graf <agraf@suse.de>
Signed-off-by: Michael Roth <mdroth@linux.vnet.ibm.com>
---
target-s390x/Makefile.objs | 3 +-
target-s390x/int_helper.c | 201 +++++++++++++++++++++++++++++++++++++++++++++
target-s390x/op_helper.c | 170 --------------------------------------
3 files changed, 203 insertions(+), 171 deletions(-)
create mode 100644 target-s390x/int_helper.c
diff --git a/target-s390x/Makefile.objs b/target-s390x/Makefile.objs
index f9437d6..e8f66e9 100644
--- a/target-s390x/Makefile.objs
+++ b/target-s390x/Makefile.objs
@@ -1,8 +1,9 @@
obj-y += translate.o op_helper.o helper.o cpu.o interrupt.o
-obj-y += fpu_helper.o cc_helper.o
+obj-y += int_helper.o fpu_helper.o cc_helper.o
obj-$(CONFIG_SOFTMMU) += machine.o
obj-$(CONFIG_KVM) += kvm.o
$(obj)/op_helper.o: QEMU_CFLAGS += $(HELPER_CFLAGS)
+$(obj)/int_helper.o: QEMU_CFLAGS += $(HELPER_CFLAGS)
$(obj)/fpu_helper.o: QEMU_CFLAGS += $(HELPER_CFLAGS)
$(obj)/cc_helper.o: QEMU_CFLAGS += $(HELPER_CFLAGS)
diff --git a/target-s390x/int_helper.c b/target-s390x/int_helper.c
new file mode 100644
index 0000000..e2eeb07
--- /dev/null
+++ b/target-s390x/int_helper.c
@@ -0,0 +1,201 @@
+/*
+ * S/390 integer helper routines
+ *
+ * Copyright (c) 2009 Ulrich Hecht
+ * Copyright (c) 2009 Alexander Graf
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include "cpu.h"
+#include "dyngen-exec.h"
+#include "host-utils.h"
+#include "helper.h"
+
+/* #define DEBUG_HELPER */
+#ifdef DEBUG_HELPER
+#define HELPER_LOG(x...) qemu_log(x)
+#else
+#define HELPER_LOG(x...)
+#endif
+
+/* 64/64 -> 128 unsigned multiplication */
+void HELPER(mlg)(uint32_t r1, uint64_t v2)
+{
+#if HOST_LONG_BITS == 64 && defined(__GNUC__)
+ /* assuming 64-bit hosts have __uint128_t */
+ __uint128_t res = (__uint128_t)env->regs[r1 + 1];
+
+ res *= (__uint128_t)v2;
+ env->regs[r1] = (uint64_t)(res >> 64);
+ env->regs[r1 + 1] = (uint64_t)res;
+#else
+ mulu64(&env->regs[r1 + 1], &env->regs[r1], env->regs[r1 + 1], v2);
+#endif
+}
+
+/* 128 -> 64/64 unsigned division */
+void HELPER(dlg)(uint32_t r1, uint64_t v2)
+{
+ uint64_t divisor = v2;
+
+ if (!env->regs[r1]) {
+ /* 64 -> 64/64 case */
+ env->regs[r1] = env->regs[r1 + 1] % divisor;
+ env->regs[r1 + 1] = env->regs[r1 + 1] / divisor;
+ return;
+ } else {
+#if HOST_LONG_BITS == 64 && defined(__GNUC__)
+ /* assuming 64-bit hosts have __uint128_t */
+ __uint128_t dividend = (((__uint128_t)env->regs[r1]) << 64) |
+ (env->regs[r1 + 1]);
+ __uint128_t quotient = dividend / divisor;
+ __uint128_t remainder = dividend % divisor;
+
+ env->regs[r1 + 1] = quotient;
+ env->regs[r1] = remainder;
+#else
+ /* 32-bit hosts would need special wrapper functionality - just abort if
+ we encounter such a case; it's very unlikely anyways. */
+ cpu_abort(env, "128 -> 64/64 division not implemented\n");
+#endif
+ }
+}
+
+/* absolute value 32-bit */
+uint32_t HELPER(abs_i32)(int32_t val)
+{
+ if (val < 0) {
+ return -val;
+ } else {
+ return val;
+ }
+}
+
+/* negative absolute value 32-bit */
+int32_t HELPER(nabs_i32)(int32_t val)
+{
+ if (val < 0) {
+ return val;
+ } else {
+ return -val;
+ }
+}
+
+/* absolute value 64-bit */
+uint64_t HELPER(abs_i64)(int64_t val)
+{
+ HELPER_LOG("%s: val 0x%" PRIx64 "\n", __func__, val);
+
+ if (val < 0) {
+ return -val;
+ } else {
+ return val;
+ }
+}
+
+/* negative absolute value 64-bit */
+int64_t HELPER(nabs_i64)(int64_t val)
+{
+ if (val < 0) {
+ return val;
+ } else {
+ return -val;
+ }
+}
+
+/* add with carry 32-bit unsigned */
+uint32_t HELPER(addc_u32)(uint32_t cc, uint32_t v1, uint32_t v2)
+{
+ uint32_t res;
+
+ res = v1 + v2;
+ if (cc & 2) {
+ res++;
+ }
+
+ return res;
+}
+
+/* subtract unsigned v2 from v1 with borrow */
+uint32_t HELPER(slb)(uint32_t cc, uint32_t r1, uint32_t v2)
+{
+ uint32_t v1 = env->regs[r1];
+ uint32_t res = v1 + (~v2) + (cc >> 1);
+
+ env->regs[r1] = (env->regs[r1] & 0xffffffff00000000ULL) | res;
+ if (cc & 2) {
+ /* borrow */
+ return v1 ? 1 : 0;
+ } else {
+ return v1 ? 3 : 2;
+ }
+}
+
+/* subtract unsigned v2 from v1 with borrow */
+uint32_t HELPER(slbg)(uint32_t cc, uint32_t r1, uint64_t v1, uint64_t v2)
+{
+ uint64_t res = v1 + (~v2) + (cc >> 1);
+
+ env->regs[r1] = res;
+ if (cc & 2) {
+ /* borrow */
+ return v1 ? 1 : 0;
+ } else {
+ return v1 ? 3 : 2;
+ }
+}
+
+/* find leftmost one */
+uint32_t HELPER(flogr)(uint32_t r1, uint64_t v2)
+{
+ uint64_t res = 0;
+ uint64_t ov2 = v2;
+
+ while (!(v2 & 0x8000000000000000ULL) && v2) {
+ v2 <<= 1;
+ res++;
+ }
+
+ if (!v2) {
+ env->regs[r1] = 64;
+ env->regs[r1 + 1] = 0;
+ return 0;
+ } else {
+ env->regs[r1] = res;
+ env->regs[r1 + 1] = ov2 & ~(0x8000000000000000ULL >> res);
+ return 2;
+ }
+}
+
+uint64_t HELPER(cvd)(int32_t bin)
+{
+ /* positive 0 */
+ uint64_t dec = 0x0c;
+ int shift = 4;
+
+ if (bin < 0) {
+ bin = -bin;
+ dec = 0x0d;
+ }
+
+ for (shift = 4; (shift < 64) && bin; shift += 4) {
+ int current_number = bin % 10;
+
+ dec |= (current_number) << shift;
+ bin /= 10;
+ }
+
+ return dec;
+}
diff --git a/target-s390x/op_helper.c b/target-s390x/op_helper.c
index eced890..3b8b997 100644
--- a/target-s390x/op_helper.c
+++ b/target-s390x/op_helper.c
@@ -352,49 +352,6 @@ void HELPER(stcm)(uint32_t r1, uint32_t mask, uint64_t addr)
HELPER_LOG("\n");
}
-/* 64/64 -> 128 unsigned multiplication */
-void HELPER(mlg)(uint32_t r1, uint64_t v2)
-{
-#if HOST_LONG_BITS == 64 && defined(__GNUC__)
- /* assuming 64-bit hosts have __uint128_t */
- __uint128_t res = (__uint128_t)env->regs[r1 + 1];
-
- res *= (__uint128_t)v2;
- env->regs[r1] = (uint64_t)(res >> 64);
- env->regs[r1 + 1] = (uint64_t)res;
-#else
- mulu64(&env->regs[r1 + 1], &env->regs[r1], env->regs[r1 + 1], v2);
-#endif
-}
-
-/* 128 -> 64/64 unsigned division */
-void HELPER(dlg)(uint32_t r1, uint64_t v2)
-{
- uint64_t divisor = v2;
-
- if (!env->regs[r1]) {
- /* 64 -> 64/64 case */
- env->regs[r1] = env->regs[r1 + 1] % divisor;
- env->regs[r1 + 1] = env->regs[r1 + 1] / divisor;
- return;
- } else {
-#if HOST_LONG_BITS == 64 && defined(__GNUC__)
- /* assuming 64-bit hosts have __uint128_t */
- __uint128_t dividend = (((__uint128_t)env->regs[r1]) << 64) |
- (env->regs[r1 + 1]);
- __uint128_t quotient = dividend / divisor;
- __uint128_t remainder = dividend % divisor;
-
- env->regs[r1 + 1] = quotient;
- env->regs[r1] = remainder;
-#else
- /* 32-bit hosts would need special wrapper functionality - just abort if
- we encounter such a case; it's very unlikely anyways. */
- cpu_abort(env, "128 -> 64/64 division not implemented\n");
-#endif
- }
-}
-
static inline uint64_t get_address(int x2, int b2, int d2)
{
uint64_t r = d2;
@@ -677,61 +634,6 @@ uint32_t HELPER(ex)(uint32_t cc, uint64_t v1, uint64_t addr, uint64_t ret)
return cc;
}
-/* absolute value 32-bit */
-uint32_t HELPER(abs_i32)(int32_t val)
-{
- if (val < 0) {
- return -val;
- } else {
- return val;
- }
-}
-
-/* negative absolute value 32-bit */
-int32_t HELPER(nabs_i32)(int32_t val)
-{
- if (val < 0) {
- return val;
- } else {
- return -val;
- }
-}
-
-/* absolute value 64-bit */
-uint64_t HELPER(abs_i64)(int64_t val)
-{
- HELPER_LOG("%s: val 0x%" PRIx64 "\n", __func__, val);
-
- if (val < 0) {
- return -val;
- } else {
- return val;
- }
-}
-
-/* negative absolute value 64-bit */
-int64_t HELPER(nabs_i64)(int64_t val)
-{
- if (val < 0) {
- return val;
- } else {
- return -val;
- }
-}
-
-/* add with carry 32-bit unsigned */
-uint32_t HELPER(addc_u32)(uint32_t cc, uint32_t v1, uint32_t v2)
-{
- uint32_t res;
-
- res = v1 + v2;
- if (cc & 2) {
- res++;
- }
-
- return res;
-}
-
/* store character under mask high operates on the upper half of r1 */
void HELPER(stcmh)(uint32_t r1, uint64_t address, uint32_t mask)
{
@@ -936,57 +838,6 @@ uint32_t HELPER(clcle)(uint32_t r1, uint64_t a2, uint32_t r3)
return cc;
}
-/* subtract unsigned v2 from v1 with borrow */
-uint32_t HELPER(slb)(uint32_t cc, uint32_t r1, uint32_t v2)
-{
- uint32_t v1 = env->regs[r1];
- uint32_t res = v1 + (~v2) + (cc >> 1);
-
- env->regs[r1] = (env->regs[r1] & 0xffffffff00000000ULL) | res;
- if (cc & 2) {
- /* borrow */
- return v1 ? 1 : 0;
- } else {
- return v1 ? 3 : 2;
- }
-}
-
-/* subtract unsigned v2 from v1 with borrow */
-uint32_t HELPER(slbg)(uint32_t cc, uint32_t r1, uint64_t v1, uint64_t v2)
-{
- uint64_t res = v1 + (~v2) + (cc >> 1);
-
- env->regs[r1] = res;
- if (cc & 2) {
- /* borrow */
- return v1 ? 1 : 0;
- } else {
- return v1 ? 3 : 2;
- }
-}
-
-/* find leftmost one */
-uint32_t HELPER(flogr)(uint32_t r1, uint64_t v2)
-{
- uint64_t res = 0;
- uint64_t ov2 = v2;
-
- while (!(v2 & 0x8000000000000000ULL) && v2) {
- v2 <<= 1;
- res++;
- }
-
- if (!v2) {
- env->regs[r1] = 64;
- env->regs[r1 + 1] = 0;
- return 0;
- } else {
- env->regs[r1] = res;
- env->regs[r1 + 1] = ov2 & ~(0x8000000000000000ULL >> res);
- return 2;
- }
-}
-
/* checksum */
void HELPER(cksm)(uint32_t r1, uint32_t r2)
{
@@ -1026,27 +877,6 @@ void HELPER(cksm)(uint32_t r1, uint32_t r2)
((uint32_t)cksm + (cksm >> 32));
}
-uint64_t HELPER(cvd)(int32_t bin)
-{
- /* positive 0 */
- uint64_t dec = 0x0c;
- int shift = 4;
-
- if (bin < 0) {
- bin = -bin;
- dec = 0x0d;
- }
-
- for (shift = 4; (shift < 64) && bin; shift += 4) {
- int current_number = bin % 10;
-
- dec |= (current_number) << shift;
- bin /= 10;
- }
-
- return dec;
-}
-
void HELPER(unpk)(uint32_t len, uint64_t dest, uint64_t src)
{
int len_dest = len >> 4;
--
1.7.12.1

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,924 @@
From 56018228deac6e704a7ec8befd9e9dc69f2fe73f Mon Sep 17 00:00:00 2001
From: Blue Swirl <blauwirbel@gmail.com>
Date: Sun, 2 Sep 2012 07:33:35 +0000
Subject: [PATCH] target-s390x: rename op_helper.c to misc_helper.c
Now op_helper.c contains miscellaneous helpers, rename
it to misc_helper.c.
Signed-off-by: Blue Swirl <blauwirbel@gmail.com>
[agraf: fix conflict]
Signed-off-by: Alexander Graf <agraf@suse.de>
Signed-off-by: Michael Roth <mdroth@linux.vnet.ibm.com>
---
target-s390x/Makefile.objs | 6 +-
target-s390x/cpu.h | 2 +-
target-s390x/misc_helper.c | 428 +++++++++++++++++++++++++++++++++++++++++++++
target-s390x/op_helper.c | 428 ---------------------------------------------
4 files changed, 432 insertions(+), 432 deletions(-)
create mode 100644 target-s390x/misc_helper.c
delete mode 100644 target-s390x/op_helper.c
diff --git a/target-s390x/Makefile.objs b/target-s390x/Makefile.objs
index b9b3061..a87d26f 100644
--- a/target-s390x/Makefile.objs
+++ b/target-s390x/Makefile.objs
@@ -1,10 +1,10 @@
-obj-y += translate.o op_helper.o helper.o cpu.o interrupt.o
-obj-y += int_helper.o fpu_helper.o cc_helper.o mem_helper.o
+obj-y += translate.o helper.o cpu.o interrupt.o
+obj-y += int_helper.o fpu_helper.o cc_helper.o mem_helper.o misc_helper.o
obj-$(CONFIG_SOFTMMU) += machine.o
obj-$(CONFIG_KVM) += kvm.o
-$(obj)/op_helper.o: QEMU_CFLAGS += $(HELPER_CFLAGS)
$(obj)/int_helper.o: QEMU_CFLAGS += $(HELPER_CFLAGS)
$(obj)/fpu_helper.o: QEMU_CFLAGS += $(HELPER_CFLAGS)
$(obj)/cc_helper.o: QEMU_CFLAGS += $(HELPER_CFLAGS)
$(obj)/mem_helper.o: QEMU_CFLAGS += $(HELPER_CFLAGS)
+$(obj)/misc_helper.o: QEMU_CFLAGS += $(HELPER_CFLAGS)
diff --git a/target-s390x/cpu.h b/target-s390x/cpu.h
index 97fde5e..0ccb551 100644
--- a/target-s390x/cpu.h
+++ b/target-s390x/cpu.h
@@ -1005,7 +1005,7 @@ uint32_t set_cc_f64(float64 v1, float64 v2);
uint32_t set_cc_nz_f32(float32 v);
uint32_t set_cc_nz_f64(float64 v);
-/* op_helper.c */
+/* misc_helper.c */
void program_interrupt(CPUS390XState *env, uint32_t code, int ilc);
#endif
diff --git a/target-s390x/misc_helper.c b/target-s390x/misc_helper.c
new file mode 100644
index 0000000..1d5137f
--- /dev/null
+++ b/target-s390x/misc_helper.c
@@ -0,0 +1,428 @@
+/*
+ * S/390 misc helper routines
+ *
+ * Copyright (c) 2009 Ulrich Hecht
+ * Copyright (c) 2009 Alexander Graf
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include "cpu.h"
+#include "memory.h"
+#include "cputlb.h"
+#include "dyngen-exec.h"
+#include "host-utils.h"
+#include "helper.h"
+#include <string.h>
+#include "kvm.h"
+#include "qemu-timer.h"
+#ifdef CONFIG_KVM
+#include <linux/kvm.h>
+#endif
+
+#if !defined(CONFIG_USER_ONLY)
+#include "softmmu_exec.h"
+#include "sysemu.h"
+#endif
+
+/* #define DEBUG_HELPER */
+#ifdef DEBUG_HELPER
+#define HELPER_LOG(x...) qemu_log(x)
+#else
+#define HELPER_LOG(x...)
+#endif
+
+/* raise an exception */
+void HELPER(exception)(uint32_t excp)
+{
+ HELPER_LOG("%s: exception %d\n", __func__, excp);
+ env->exception_index = excp;
+ cpu_loop_exit(env);
+}
+
+#ifndef CONFIG_USER_ONLY
+void program_interrupt(CPUS390XState *env, uint32_t code, int ilc)
+{
+ qemu_log("program interrupt at %#" PRIx64 "\n", env->psw.addr);
+
+ if (kvm_enabled()) {
+#ifdef CONFIG_KVM
+ kvm_s390_interrupt(env, KVM_S390_PROGRAM_INT, code);
+#endif
+ } else {
+ env->int_pgm_code = code;
+ env->int_pgm_ilc = ilc;
+ env->exception_index = EXCP_PGM;
+ cpu_loop_exit(env);
+ }
+}
+
+/*
+ * ret < 0 indicates program check, ret = 0, 1, 2, 3 -> cc
+ */
+int sclp_service_call(CPUS390XState *env, uint32_t sccb, uint64_t code)
+{
+ int r = 0;
+ int shift = 0;
+
+#ifdef DEBUG_HELPER
+ printf("sclp(0x%x, 0x%" PRIx64 ")\n", sccb, code);
+#endif
+
+ /* basic checks */
+ if (!memory_region_is_ram(phys_page_find(sccb >> TARGET_PAGE_BITS)->mr)) {
+ return -PGM_ADDRESSING;
+ }
+ if (sccb & ~0x7ffffff8ul) {
+ return -PGM_SPECIFICATION;
+ }
+
+ switch (code) {
+ case SCLP_CMDW_READ_SCP_INFO:
+ case SCLP_CMDW_READ_SCP_INFO_FORCED:
+ while ((ram_size >> (20 + shift)) > 65535) {
+ shift++;
+ }
+ stw_phys(sccb + SCP_MEM_CODE, ram_size >> (20 + shift));
+ stb_phys(sccb + SCP_INCREMENT, 1 << shift);
+ stw_phys(sccb + SCP_RESPONSE_CODE, 0x10);
+
+ s390_sclp_extint(sccb & ~3);
+ break;
+ default:
+#ifdef DEBUG_HELPER
+ printf("KVM: invalid sclp call 0x%x / 0x%" PRIx64 "x\n", sccb, code);
+#endif
+ r = 3;
+ break;
+ }
+
+ return r;
+}
+
+/* SCLP service call */
+uint32_t HELPER(servc)(uint32_t r1, uint64_t r2)
+{
+ int r;
+
+ r = sclp_service_call(env, r1, r2);
+ if (r < 0) {
+ program_interrupt(env, -r, 4);
+ return 0;
+ }
+ return r;
+}
+
+/* DIAG */
+uint64_t HELPER(diag)(uint32_t num, uint64_t mem, uint64_t code)
+{
+ uint64_t r;
+
+ switch (num) {
+ case 0x500:
+ /* KVM hypercall */
+ r = s390_virtio_hypercall(env, mem, code);
+ break;
+ case 0x44:
+ /* yield */
+ r = 0;
+ break;
+ case 0x308:
+ /* ipl */
+ r = 0;
+ break;
+ default:
+ r = -1;
+ break;
+ }
+
+ if (r) {
+ program_interrupt(env, PGM_OPERATION, ILC_LATER_INC);
+ }
+
+ return r;
+}
+
+/* Store CPU ID */
+void HELPER(stidp)(uint64_t a1)
+{
+ stq(a1, env->cpu_num);
+}
+
+/* Set Prefix */
+void HELPER(spx)(uint64_t a1)
+{
+ uint32_t prefix;
+
+ prefix = ldl(a1);
+ env->psa = prefix & 0xfffff000;
+ qemu_log("prefix: %#x\n", prefix);
+ tlb_flush_page(env, 0);
+ tlb_flush_page(env, TARGET_PAGE_SIZE);
+}
+
+/* Set Clock */
+uint32_t HELPER(sck)(uint64_t a1)
+{
+ /* XXX not implemented - is it necessary? */
+
+ return 0;
+}
+
+static inline uint64_t clock_value(CPUS390XState *env)
+{
+ uint64_t time;
+
+ time = env->tod_offset +
+ time2tod(qemu_get_clock_ns(vm_clock) - env->tod_basetime);
+
+ return time;
+}
+
+/* Store Clock */
+uint32_t HELPER(stck)(uint64_t a1)
+{
+ stq(a1, clock_value(env));
+
+ return 0;
+}
+
+/* Store Clock Extended */
+uint32_t HELPER(stcke)(uint64_t a1)
+{
+ stb(a1, 0);
+ /* basically the same value as stck */
+ stq(a1 + 1, clock_value(env) | env->cpu_num);
+ /* more fine grained than stck */
+ stq(a1 + 9, 0);
+ /* XXX programmable fields */
+ stw(a1 + 17, 0);
+
+ return 0;
+}
+
+/* Set Clock Comparator */
+void HELPER(sckc)(uint64_t a1)
+{
+ uint64_t time = ldq(a1);
+
+ if (time == -1ULL) {
+ return;
+ }
+
+ /* difference between now and then */
+ time -= clock_value(env);
+ /* nanoseconds */
+ time = (time * 125) >> 9;
+
+ qemu_mod_timer(env->tod_timer, qemu_get_clock_ns(vm_clock) + time);
+}
+
+/* Store Clock Comparator */
+void HELPER(stckc)(uint64_t a1)
+{
+ /* XXX implement */
+ stq(a1, 0);
+}
+
+/* Set CPU Timer */
+void HELPER(spt)(uint64_t a1)
+{
+ uint64_t time = ldq(a1);
+
+ if (time == -1ULL) {
+ return;
+ }
+
+ /* nanoseconds */
+ time = (time * 125) >> 9;
+
+ qemu_mod_timer(env->cpu_timer, qemu_get_clock_ns(vm_clock) + time);
+}
+
+/* Store CPU Timer */
+void HELPER(stpt)(uint64_t a1)
+{
+ /* XXX implement */
+ stq(a1, 0);
+}
+
+/* Store System Information */
+uint32_t HELPER(stsi)(uint64_t a0, uint32_t r0, uint32_t r1)
+{
+ int cc = 0;
+ int sel1, sel2;
+
+ if ((r0 & STSI_LEVEL_MASK) <= STSI_LEVEL_3 &&
+ ((r0 & STSI_R0_RESERVED_MASK) || (r1 & STSI_R1_RESERVED_MASK))) {
+ /* valid function code, invalid reserved bits */
+ program_interrupt(env, PGM_SPECIFICATION, 2);
+ }
+
+ sel1 = r0 & STSI_R0_SEL1_MASK;
+ sel2 = r1 & STSI_R1_SEL2_MASK;
+
+ /* XXX: spec exception if sysib is not 4k-aligned */
+
+ switch (r0 & STSI_LEVEL_MASK) {
+ case STSI_LEVEL_1:
+ if ((sel1 == 1) && (sel2 == 1)) {
+ /* Basic Machine Configuration */
+ struct sysib_111 sysib;
+
+ memset(&sysib, 0, sizeof(sysib));
+ ebcdic_put(sysib.manuf, "QEMU ", 16);
+ /* same as machine type number in STORE CPU ID */
+ ebcdic_put(sysib.type, "QEMU", 4);
+ /* same as model number in STORE CPU ID */
+ ebcdic_put(sysib.model, "QEMU ", 16);
+ ebcdic_put(sysib.sequence, "QEMU ", 16);
+ ebcdic_put(sysib.plant, "QEMU", 4);
+ cpu_physical_memory_rw(a0, (uint8_t *)&sysib, sizeof(sysib), 1);
+ } else if ((sel1 == 2) && (sel2 == 1)) {
+ /* Basic Machine CPU */
+ struct sysib_121 sysib;
+
+ memset(&sysib, 0, sizeof(sysib));
+ /* XXX make different for different CPUs? */
+ ebcdic_put(sysib.sequence, "QEMUQEMUQEMUQEMU", 16);
+ ebcdic_put(sysib.plant, "QEMU", 4);
+ stw_p(&sysib.cpu_addr, env->cpu_num);
+ cpu_physical_memory_rw(a0, (uint8_t *)&sysib, sizeof(sysib), 1);
+ } else if ((sel1 == 2) && (sel2 == 2)) {
+ /* Basic Machine CPUs */
+ struct sysib_122 sysib;
+
+ memset(&sysib, 0, sizeof(sysib));
+ stl_p(&sysib.capability, 0x443afc29);
+ /* XXX change when SMP comes */
+ stw_p(&sysib.total_cpus, 1);
+ stw_p(&sysib.active_cpus, 1);
+ stw_p(&sysib.standby_cpus, 0);
+ stw_p(&sysib.reserved_cpus, 0);
+ cpu_physical_memory_rw(a0, (uint8_t *)&sysib, sizeof(sysib), 1);
+ } else {
+ cc = 3;
+ }
+ break;
+ case STSI_LEVEL_2:
+ {
+ if ((sel1 == 2) && (sel2 == 1)) {
+ /* LPAR CPU */
+ struct sysib_221 sysib;
+
+ memset(&sysib, 0, sizeof(sysib));
+ /* XXX make different for different CPUs? */
+ ebcdic_put(sysib.sequence, "QEMUQEMUQEMUQEMU", 16);
+ ebcdic_put(sysib.plant, "QEMU", 4);
+ stw_p(&sysib.cpu_addr, env->cpu_num);
+ stw_p(&sysib.cpu_id, 0);
+ cpu_physical_memory_rw(a0, (uint8_t *)&sysib, sizeof(sysib), 1);
+ } else if ((sel1 == 2) && (sel2 == 2)) {
+ /* LPAR CPUs */
+ struct sysib_222 sysib;
+
+ memset(&sysib, 0, sizeof(sysib));
+ stw_p(&sysib.lpar_num, 0);
+ sysib.lcpuc = 0;
+ /* XXX change when SMP comes */
+ stw_p(&sysib.total_cpus, 1);
+ stw_p(&sysib.conf_cpus, 1);
+ stw_p(&sysib.standby_cpus, 0);
+ stw_p(&sysib.reserved_cpus, 0);
+ ebcdic_put(sysib.name, "QEMU ", 8);
+ stl_p(&sysib.caf, 1000);
+ stw_p(&sysib.dedicated_cpus, 0);
+ stw_p(&sysib.shared_cpus, 0);
+ cpu_physical_memory_rw(a0, (uint8_t *)&sysib, sizeof(sysib), 1);
+ } else {
+ cc = 3;
+ }
+ break;
+ }
+ case STSI_LEVEL_3:
+ {
+ if ((sel1 == 2) && (sel2 == 2)) {
+ /* VM CPUs */
+ struct sysib_322 sysib;
+
+ memset(&sysib, 0, sizeof(sysib));
+ sysib.count = 1;
+ /* XXX change when SMP comes */
+ stw_p(&sysib.vm[0].total_cpus, 1);
+ stw_p(&sysib.vm[0].conf_cpus, 1);
+ stw_p(&sysib.vm[0].standby_cpus, 0);
+ stw_p(&sysib.vm[0].reserved_cpus, 0);
+ ebcdic_put(sysib.vm[0].name, "KVMguest", 8);
+ stl_p(&sysib.vm[0].caf, 1000);
+ ebcdic_put(sysib.vm[0].cpi, "KVM/Linux ", 16);
+ cpu_physical_memory_rw(a0, (uint8_t *)&sysib, sizeof(sysib), 1);
+ } else {
+ cc = 3;
+ }
+ break;
+ }
+ case STSI_LEVEL_CURRENT:
+ env->regs[0] = STSI_LEVEL_3;
+ break;
+ default:
+ cc = 3;
+ break;
+ }
+
+ return cc;
+}
+
+uint32_t HELPER(sigp)(uint64_t order_code, uint32_t r1, uint64_t cpu_addr)
+{
+ int cc = 0;
+
+ HELPER_LOG("%s: %016" PRIx64 " %08x %016" PRIx64 "\n",
+ __func__, order_code, r1, cpu_addr);
+
+ /* Remember: Use "R1 or R1 + 1, whichever is the odd-numbered register"
+ as parameter (input). Status (output) is always R1. */
+
+ switch (order_code) {
+ case SIGP_SET_ARCH:
+ /* switch arch */
+ break;
+ case SIGP_SENSE:
+ /* enumerate CPU status */
+ if (cpu_addr) {
+ /* XXX implement when SMP comes */
+ return 3;
+ }
+ env->regs[r1] &= 0xffffffff00000000ULL;
+ cc = 1;
+ break;
+#if !defined(CONFIG_USER_ONLY)
+ case SIGP_RESTART:
+ qemu_system_reset_request();
+ cpu_loop_exit(env);
+ break;
+ case SIGP_STOP:
+ qemu_system_shutdown_request();
+ cpu_loop_exit(env);
+ break;
+#endif
+ default:
+ /* unknown sigp */
+ fprintf(stderr, "XXX unknown sigp: 0x%" PRIx64 "\n", order_code);
+ cc = 3;
+ }
+
+ return cc;
+}
+#endif
diff --git a/target-s390x/op_helper.c b/target-s390x/op_helper.c
deleted file mode 100644
index bb8dbf5..0000000
--- a/target-s390x/op_helper.c
+++ /dev/null
@@ -1,428 +0,0 @@
-/*
- * S/390 helper routines
- *
- * Copyright (c) 2009 Ulrich Hecht
- * Copyright (c) 2009 Alexander Graf
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, see <http://www.gnu.org/licenses/>.
- */
-
-#include "cpu.h"
-#include "memory.h"
-#include "cputlb.h"
-#include "dyngen-exec.h"
-#include "host-utils.h"
-#include "helper.h"
-#include <string.h>
-#include "kvm.h"
-#include "qemu-timer.h"
-#ifdef CONFIG_KVM
-#include <linux/kvm.h>
-#endif
-
-#if !defined(CONFIG_USER_ONLY)
-#include "softmmu_exec.h"
-#include "sysemu.h"
-#endif
-
-/* #define DEBUG_HELPER */
-#ifdef DEBUG_HELPER
-#define HELPER_LOG(x...) qemu_log(x)
-#else
-#define HELPER_LOG(x...)
-#endif
-
-/* raise an exception */
-void HELPER(exception)(uint32_t excp)
-{
- HELPER_LOG("%s: exception %d\n", __func__, excp);
- env->exception_index = excp;
- cpu_loop_exit(env);
-}
-
-#ifndef CONFIG_USER_ONLY
-void program_interrupt(CPUS390XState *env, uint32_t code, int ilc)
-{
- qemu_log("program interrupt at %#" PRIx64 "\n", env->psw.addr);
-
- if (kvm_enabled()) {
-#ifdef CONFIG_KVM
- kvm_s390_interrupt(env, KVM_S390_PROGRAM_INT, code);
-#endif
- } else {
- env->int_pgm_code = code;
- env->int_pgm_ilc = ilc;
- env->exception_index = EXCP_PGM;
- cpu_loop_exit(env);
- }
-}
-
-/*
- * ret < 0 indicates program check, ret = 0, 1, 2, 3 -> cc
- */
-int sclp_service_call(CPUS390XState *env, uint32_t sccb, uint64_t code)
-{
- int r = 0;
- int shift = 0;
-
-#ifdef DEBUG_HELPER
- printf("sclp(0x%x, 0x%" PRIx64 ")\n", sccb, code);
-#endif
-
- /* basic checks */
- if (!memory_region_is_ram(phys_page_find(sccb >> TARGET_PAGE_BITS)->mr)) {
- return -PGM_ADDRESSING;
- }
- if (sccb & ~0x7ffffff8ul) {
- return -PGM_SPECIFICATION;
- }
-
- switch (code) {
- case SCLP_CMDW_READ_SCP_INFO:
- case SCLP_CMDW_READ_SCP_INFO_FORCED:
- while ((ram_size >> (20 + shift)) > 65535) {
- shift++;
- }
- stw_phys(sccb + SCP_MEM_CODE, ram_size >> (20 + shift));
- stb_phys(sccb + SCP_INCREMENT, 1 << shift);
- stw_phys(sccb + SCP_RESPONSE_CODE, 0x10);
-
- s390_sclp_extint(sccb & ~3);
- break;
- default:
-#ifdef DEBUG_HELPER
- printf("KVM: invalid sclp call 0x%x / 0x%" PRIx64 "x\n", sccb, code);
-#endif
- r = 3;
- break;
- }
-
- return r;
-}
-
-/* SCLP service call */
-uint32_t HELPER(servc)(uint32_t r1, uint64_t r2)
-{
- int r;
-
- r = sclp_service_call(env, r1, r2);
- if (r < 0) {
- program_interrupt(env, -r, 4);
- return 0;
- }
- return r;
-}
-
-/* DIAG */
-uint64_t HELPER(diag)(uint32_t num, uint64_t mem, uint64_t code)
-{
- uint64_t r;
-
- switch (num) {
- case 0x500:
- /* KVM hypercall */
- r = s390_virtio_hypercall(env, mem, code);
- break;
- case 0x44:
- /* yield */
- r = 0;
- break;
- case 0x308:
- /* ipl */
- r = 0;
- break;
- default:
- r = -1;
- break;
- }
-
- if (r) {
- program_interrupt(env, PGM_OPERATION, ILC_LATER_INC);
- }
-
- return r;
-}
-
-/* Store CPU ID */
-void HELPER(stidp)(uint64_t a1)
-{
- stq(a1, env->cpu_num);
-}
-
-/* Set Prefix */
-void HELPER(spx)(uint64_t a1)
-{
- uint32_t prefix;
-
- prefix = ldl(a1);
- env->psa = prefix & 0xfffff000;
- qemu_log("prefix: %#x\n", prefix);
- tlb_flush_page(env, 0);
- tlb_flush_page(env, TARGET_PAGE_SIZE);
-}
-
-/* Set Clock */
-uint32_t HELPER(sck)(uint64_t a1)
-{
- /* XXX not implemented - is it necessary? */
-
- return 0;
-}
-
-static inline uint64_t clock_value(CPUS390XState *env)
-{
- uint64_t time;
-
- time = env->tod_offset +
- time2tod(qemu_get_clock_ns(vm_clock) - env->tod_basetime);
-
- return time;
-}
-
-/* Store Clock */
-uint32_t HELPER(stck)(uint64_t a1)
-{
- stq(a1, clock_value(env));
-
- return 0;
-}
-
-/* Store Clock Extended */
-uint32_t HELPER(stcke)(uint64_t a1)
-{
- stb(a1, 0);
- /* basically the same value as stck */
- stq(a1 + 1, clock_value(env) | env->cpu_num);
- /* more fine grained than stck */
- stq(a1 + 9, 0);
- /* XXX programmable fields */
- stw(a1 + 17, 0);
-
- return 0;
-}
-
-/* Set Clock Comparator */
-void HELPER(sckc)(uint64_t a1)
-{
- uint64_t time = ldq(a1);
-
- if (time == -1ULL) {
- return;
- }
-
- /* difference between now and then */
- time -= clock_value(env);
- /* nanoseconds */
- time = (time * 125) >> 9;
-
- qemu_mod_timer(env->tod_timer, qemu_get_clock_ns(vm_clock) + time);
-}
-
-/* Store Clock Comparator */
-void HELPER(stckc)(uint64_t a1)
-{
- /* XXX implement */
- stq(a1, 0);
-}
-
-/* Set CPU Timer */
-void HELPER(spt)(uint64_t a1)
-{
- uint64_t time = ldq(a1);
-
- if (time == -1ULL) {
- return;
- }
-
- /* nanoseconds */
- time = (time * 125) >> 9;
-
- qemu_mod_timer(env->cpu_timer, qemu_get_clock_ns(vm_clock) + time);
-}
-
-/* Store CPU Timer */
-void HELPER(stpt)(uint64_t a1)
-{
- /* XXX implement */
- stq(a1, 0);
-}
-
-/* Store System Information */
-uint32_t HELPER(stsi)(uint64_t a0, uint32_t r0, uint32_t r1)
-{
- int cc = 0;
- int sel1, sel2;
-
- if ((r0 & STSI_LEVEL_MASK) <= STSI_LEVEL_3 &&
- ((r0 & STSI_R0_RESERVED_MASK) || (r1 & STSI_R1_RESERVED_MASK))) {
- /* valid function code, invalid reserved bits */
- program_interrupt(env, PGM_SPECIFICATION, 2);
- }
-
- sel1 = r0 & STSI_R0_SEL1_MASK;
- sel2 = r1 & STSI_R1_SEL2_MASK;
-
- /* XXX: spec exception if sysib is not 4k-aligned */
-
- switch (r0 & STSI_LEVEL_MASK) {
- case STSI_LEVEL_1:
- if ((sel1 == 1) && (sel2 == 1)) {
- /* Basic Machine Configuration */
- struct sysib_111 sysib;
-
- memset(&sysib, 0, sizeof(sysib));
- ebcdic_put(sysib.manuf, "QEMU ", 16);
- /* same as machine type number in STORE CPU ID */
- ebcdic_put(sysib.type, "QEMU", 4);
- /* same as model number in STORE CPU ID */
- ebcdic_put(sysib.model, "QEMU ", 16);
- ebcdic_put(sysib.sequence, "QEMU ", 16);
- ebcdic_put(sysib.plant, "QEMU", 4);
- cpu_physical_memory_rw(a0, (uint8_t *)&sysib, sizeof(sysib), 1);
- } else if ((sel1 == 2) && (sel2 == 1)) {
- /* Basic Machine CPU */
- struct sysib_121 sysib;
-
- memset(&sysib, 0, sizeof(sysib));
- /* XXX make different for different CPUs? */
- ebcdic_put(sysib.sequence, "QEMUQEMUQEMUQEMU", 16);
- ebcdic_put(sysib.plant, "QEMU", 4);
- stw_p(&sysib.cpu_addr, env->cpu_num);
- cpu_physical_memory_rw(a0, (uint8_t *)&sysib, sizeof(sysib), 1);
- } else if ((sel1 == 2) && (sel2 == 2)) {
- /* Basic Machine CPUs */
- struct sysib_122 sysib;
-
- memset(&sysib, 0, sizeof(sysib));
- stl_p(&sysib.capability, 0x443afc29);
- /* XXX change when SMP comes */
- stw_p(&sysib.total_cpus, 1);
- stw_p(&sysib.active_cpus, 1);
- stw_p(&sysib.standby_cpus, 0);
- stw_p(&sysib.reserved_cpus, 0);
- cpu_physical_memory_rw(a0, (uint8_t *)&sysib, sizeof(sysib), 1);
- } else {
- cc = 3;
- }
- break;
- case STSI_LEVEL_2:
- {
- if ((sel1 == 2) && (sel2 == 1)) {
- /* LPAR CPU */
- struct sysib_221 sysib;
-
- memset(&sysib, 0, sizeof(sysib));
- /* XXX make different for different CPUs? */
- ebcdic_put(sysib.sequence, "QEMUQEMUQEMUQEMU", 16);
- ebcdic_put(sysib.plant, "QEMU", 4);
- stw_p(&sysib.cpu_addr, env->cpu_num);
- stw_p(&sysib.cpu_id, 0);
- cpu_physical_memory_rw(a0, (uint8_t *)&sysib, sizeof(sysib), 1);
- } else if ((sel1 == 2) && (sel2 == 2)) {
- /* LPAR CPUs */
- struct sysib_222 sysib;
-
- memset(&sysib, 0, sizeof(sysib));
- stw_p(&sysib.lpar_num, 0);
- sysib.lcpuc = 0;
- /* XXX change when SMP comes */
- stw_p(&sysib.total_cpus, 1);
- stw_p(&sysib.conf_cpus, 1);
- stw_p(&sysib.standby_cpus, 0);
- stw_p(&sysib.reserved_cpus, 0);
- ebcdic_put(sysib.name, "QEMU ", 8);
- stl_p(&sysib.caf, 1000);
- stw_p(&sysib.dedicated_cpus, 0);
- stw_p(&sysib.shared_cpus, 0);
- cpu_physical_memory_rw(a0, (uint8_t *)&sysib, sizeof(sysib), 1);
- } else {
- cc = 3;
- }
- break;
- }
- case STSI_LEVEL_3:
- {
- if ((sel1 == 2) && (sel2 == 2)) {
- /* VM CPUs */
- struct sysib_322 sysib;
-
- memset(&sysib, 0, sizeof(sysib));
- sysib.count = 1;
- /* XXX change when SMP comes */
- stw_p(&sysib.vm[0].total_cpus, 1);
- stw_p(&sysib.vm[0].conf_cpus, 1);
- stw_p(&sysib.vm[0].standby_cpus, 0);
- stw_p(&sysib.vm[0].reserved_cpus, 0);
- ebcdic_put(sysib.vm[0].name, "KVMguest", 8);
- stl_p(&sysib.vm[0].caf, 1000);
- ebcdic_put(sysib.vm[0].cpi, "KVM/Linux ", 16);
- cpu_physical_memory_rw(a0, (uint8_t *)&sysib, sizeof(sysib), 1);
- } else {
- cc = 3;
- }
- break;
- }
- case STSI_LEVEL_CURRENT:
- env->regs[0] = STSI_LEVEL_3;
- break;
- default:
- cc = 3;
- break;
- }
-
- return cc;
-}
-
-uint32_t HELPER(sigp)(uint64_t order_code, uint32_t r1, uint64_t cpu_addr)
-{
- int cc = 0;
-
- HELPER_LOG("%s: %016" PRIx64 " %08x %016" PRIx64 "\n",
- __func__, order_code, r1, cpu_addr);
-
- /* Remember: Use "R1 or R1 + 1, whichever is the odd-numbered register"
- as parameter (input). Status (output) is always R1. */
-
- switch (order_code) {
- case SIGP_SET_ARCH:
- /* switch arch */
- break;
- case SIGP_SENSE:
- /* enumerate CPU status */
- if (cpu_addr) {
- /* XXX implement when SMP comes */
- return 3;
- }
- env->regs[r1] &= 0xffffffff00000000ULL;
- cc = 1;
- break;
-#if !defined(CONFIG_USER_ONLY)
- case SIGP_RESTART:
- qemu_system_reset_request();
- cpu_loop_exit(env);
- break;
- case SIGP_STOP:
- qemu_system_shutdown_request();
- cpu_loop_exit(env);
- break;
-#endif
- default:
- /* unknown sigp */
- fprintf(stderr, "XXX unknown sigp: 0x%" PRIx64 "\n", order_code);
- cc = 3;
- }
-
- return cc;
-}
-#endif
--
1.7.12.1

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,202 @@
From d44b8c2cacaa50e7420f0dfaf42c344bcf134431 Mon Sep 17 00:00:00 2001
From: Blue Swirl <blauwirbel@gmail.com>
Date: Sun, 2 Sep 2012 07:33:37 +0000
Subject: [PATCH] target-s390x: avoid AREG0 for integer helpers
Make integer helpers take a parameter for CPUState instead
of relying on global env.
Signed-off-by: Blue Swirl <blauwirbel@gmail.com>
Signed-off-by: Alexander Graf <agraf@suse.de>
Signed-off-by: Michael Roth <mdroth@linux.vnet.ibm.com>
---
target-s390x/Makefile.objs | 1 -
target-s390x/helper.h | 10 +++++-----
target-s390x/int_helper.c | 12 ++++++------
target-s390x/translate.c | 16 ++++++++--------
4 files changed, 19 insertions(+), 20 deletions(-)
diff --git a/target-s390x/Makefile.objs b/target-s390x/Makefile.objs
index 7d965e9..7b2c5c1 100644
--- a/target-s390x/Makefile.objs
+++ b/target-s390x/Makefile.objs
@@ -3,7 +3,6 @@ obj-y += int_helper.o fpu_helper.o cc_helper.o mem_helper.o misc_helper.o
obj-$(CONFIG_SOFTMMU) += machine.o
obj-$(CONFIG_KVM) += kvm.o
-$(obj)/int_helper.o: QEMU_CFLAGS += $(HELPER_CFLAGS)
$(obj)/cc_helper.o: QEMU_CFLAGS += $(HELPER_CFLAGS)
$(obj)/mem_helper.o: QEMU_CFLAGS += $(HELPER_CFLAGS)
$(obj)/misc_helper.o: QEMU_CFLAGS += $(HELPER_CFLAGS)
diff --git a/target-s390x/helper.h b/target-s390x/helper.h
index af98773..c03cd59 100644
--- a/target-s390x/helper.h
+++ b/target-s390x/helper.h
@@ -12,8 +12,8 @@ DEF_HELPER_FLAGS_1(set_cc_comp_s64, TCG_CALL_PURE|TCG_CALL_CONST, i32, s64)
DEF_HELPER_FLAGS_2(set_cc_icm, TCG_CALL_PURE|TCG_CALL_CONST, i32, i32, i32)
DEF_HELPER_3(clm, i32, i32, i32, i64)
DEF_HELPER_3(stcm, void, i32, i32, i64)
-DEF_HELPER_2(mlg, void, i32, i64)
-DEF_HELPER_2(dlg, void, i32, i64)
+DEF_HELPER_3(mlg, void, env, i32, i64)
+DEF_HELPER_3(dlg, void, env, i32, i64)
DEF_HELPER_FLAGS_3(set_cc_add64, TCG_CALL_PURE|TCG_CALL_CONST, i32, s64, s64, s64)
DEF_HELPER_FLAGS_3(set_cc_addu64, TCG_CALL_PURE|TCG_CALL_CONST, i32, i64, i64, i64)
DEF_HELPER_FLAGS_3(set_cc_add32, TCG_CALL_PURE|TCG_CALL_CONST, i32, s32, s32, s32)
@@ -43,8 +43,8 @@ DEF_HELPER_3(stam, void, i32, i64, i32)
DEF_HELPER_3(lam, void, i32, i64, i32)
DEF_HELPER_3(mvcle, i32, i32, i64, i32)
DEF_HELPER_3(clcle, i32, i32, i64, i32)
-DEF_HELPER_3(slb, i32, i32, i32, i32)
-DEF_HELPER_4(slbg, i32, i32, i32, i64, i64)
+DEF_HELPER_4(slb, i32, env, i32, i32, i32)
+DEF_HELPER_5(slbg, i32, env, i32, i32, i64, i64)
DEF_HELPER_3(cefbr, void, env, i32, s32)
DEF_HELPER_3(cdfbr, void, env, i32, s32)
DEF_HELPER_3(cxfbr, void, env, i32, s32)
@@ -107,7 +107,7 @@ DEF_HELPER_3(lxdb, void, env, i32, i64)
DEF_HELPER_FLAGS_3(tceb, TCG_CALL_PURE, i32, env, i32, i64)
DEF_HELPER_FLAGS_3(tcdb, TCG_CALL_PURE, i32, env, i32, i64)
DEF_HELPER_FLAGS_3(tcxb, TCG_CALL_PURE, i32, env, i32, i64)
-DEF_HELPER_2(flogr, i32, i32, i64)
+DEF_HELPER_3(flogr, i32, env, i32, i64)
DEF_HELPER_3(sqdbr, void, env, i32, i32)
DEF_HELPER_FLAGS_1(cvd, TCG_CALL_PURE|TCG_CALL_CONST, i64, s32)
DEF_HELPER_3(unpk, void, i32, i64, i64)
diff --git a/target-s390x/int_helper.c b/target-s390x/int_helper.c
index e2eeb07..f202a7e 100644
--- a/target-s390x/int_helper.c
+++ b/target-s390x/int_helper.c
@@ -19,7 +19,6 @@
*/
#include "cpu.h"
-#include "dyngen-exec.h"
#include "host-utils.h"
#include "helper.h"
@@ -31,7 +30,7 @@
#endif
/* 64/64 -> 128 unsigned multiplication */
-void HELPER(mlg)(uint32_t r1, uint64_t v2)
+void HELPER(mlg)(CPUS390XState *env, uint32_t r1, uint64_t v2)
{
#if HOST_LONG_BITS == 64 && defined(__GNUC__)
/* assuming 64-bit hosts have __uint128_t */
@@ -46,7 +45,7 @@ void HELPER(mlg)(uint32_t r1, uint64_t v2)
}
/* 128 -> 64/64 unsigned division */
-void HELPER(dlg)(uint32_t r1, uint64_t v2)
+void HELPER(dlg)(CPUS390XState *env, uint32_t r1, uint64_t v2)
{
uint64_t divisor = v2;
@@ -129,7 +128,7 @@ uint32_t HELPER(addc_u32)(uint32_t cc, uint32_t v1, uint32_t v2)
}
/* subtract unsigned v2 from v1 with borrow */
-uint32_t HELPER(slb)(uint32_t cc, uint32_t r1, uint32_t v2)
+uint32_t HELPER(slb)(CPUS390XState *env, uint32_t cc, uint32_t r1, uint32_t v2)
{
uint32_t v1 = env->regs[r1];
uint32_t res = v1 + (~v2) + (cc >> 1);
@@ -144,7 +143,8 @@ uint32_t HELPER(slb)(uint32_t cc, uint32_t r1, uint32_t v2)
}
/* subtract unsigned v2 from v1 with borrow */
-uint32_t HELPER(slbg)(uint32_t cc, uint32_t r1, uint64_t v1, uint64_t v2)
+uint32_t HELPER(slbg)(CPUS390XState *env, uint32_t cc, uint32_t r1,
+ uint64_t v1, uint64_t v2)
{
uint64_t res = v1 + (~v2) + (cc >> 1);
@@ -158,7 +158,7 @@ uint32_t HELPER(slbg)(uint32_t cc, uint32_t r1, uint64_t v1, uint64_t v2)
}
/* find leftmost one */
-uint32_t HELPER(flogr)(uint32_t r1, uint64_t v2)
+uint32_t HELPER(flogr)(CPUS390XState *env, uint32_t r1, uint64_t v2)
{
uint64_t res = 0;
uint64_t ov2 = v2;
diff --git a/target-s390x/translate.c b/target-s390x/translate.c
index b1f2071..2a61e92 100644
--- a/target-s390x/translate.c
+++ b/target-s390x/translate.c
@@ -1803,7 +1803,7 @@ static void disas_e3(DisasContext* s, int op, int r1, int x2, int b2, int d2)
tmp2 = tcg_temp_new_i64();
tmp32_1 = tcg_const_i32(r1);
tcg_gen_qemu_ld64(tmp2, addr, get_mem_index(s));
- gen_helper_mlg(tmp32_1, tmp2);
+ gen_helper_mlg(cpu_env, tmp32_1, tmp2);
tcg_temp_free_i64(tmp2);
tcg_temp_free_i32(tmp32_1);
break;
@@ -1811,7 +1811,7 @@ static void disas_e3(DisasContext* s, int op, int r1, int x2, int b2, int d2)
tmp2 = tcg_temp_new_i64();
tmp32_1 = tcg_const_i32(r1);
tcg_gen_qemu_ld64(tmp2, addr, get_mem_index(s));
- gen_helper_dlg(tmp32_1, tmp2);
+ gen_helper_dlg(cpu_env, tmp32_1, tmp2);
tcg_temp_free_i64(tmp2);
tcg_temp_free_i32(tmp32_1);
break;
@@ -1837,7 +1837,7 @@ static void disas_e3(DisasContext* s, int op, int r1, int x2, int b2, int d2)
tcg_gen_qemu_ld64(tmp2, addr, get_mem_index(s));
/* XXX possible optimization point */
gen_op_calc_cc(s);
- gen_helper_slbg(cc_op, cc_op, tmp32_1, regs[r1], tmp2);
+ gen_helper_slbg(cc_op, cpu_env, cc_op, tmp32_1, regs[r1], tmp2);
set_cc_static(s);
tcg_temp_free_i64(tmp2);
tcg_temp_free_i32(tmp32_1);
@@ -1917,7 +1917,7 @@ static void disas_e3(DisasContext* s, int op, int r1, int x2, int b2, int d2)
tcg_gen_trunc_i64_i32(tmp32_2, tmp2);
/* XXX possible optimization point */
gen_op_calc_cc(s);
- gen_helper_slb(cc_op, cc_op, tmp32_1, tmp32_2);
+ gen_helper_slb(cc_op, cpu_env, cc_op, tmp32_1, tmp32_2);
set_cc_static(s);
tcg_temp_free_i64(tmp2);
tcg_temp_free_i32(tmp32_1);
@@ -3535,7 +3535,7 @@ static void disas_b9(DisasContext *s, int op, int r1, int r2)
case 0x83: /* FLOGR R1,R2 [RRE] */
tmp = load_reg(r2);
tmp32_1 = tcg_const_i32(r1);
- gen_helper_flogr(cc_op, tmp32_1, tmp);
+ gen_helper_flogr(cc_op, cpu_env, tmp32_1, tmp);
set_cc_static(s);
tcg_temp_free_i64(tmp);
tcg_temp_free_i32(tmp32_1);
@@ -3555,7 +3555,7 @@ static void disas_b9(DisasContext *s, int op, int r1, int r2)
case 0x87: /* DLGR R1,R2 [RRE] */
tmp32_1 = tcg_const_i32(r1);
tmp = load_reg(r2);
- gen_helper_dlg(tmp32_1, tmp);
+ gen_helper_dlg(cpu_env, tmp32_1, tmp);
tcg_temp_free_i64(tmp);
tcg_temp_free_i32(tmp32_1);
break;
@@ -3580,7 +3580,7 @@ static void disas_b9(DisasContext *s, int op, int r1, int r2)
tmp2 = load_reg(r2);
tmp32_1 = tcg_const_i32(r1);
gen_op_calc_cc(s);
- gen_helper_slbg(cc_op, cc_op, tmp32_1, tmp, tmp2);
+ gen_helper_slbg(cc_op, cpu_env, cc_op, tmp32_1, tmp, tmp2);
set_cc_static(s);
tcg_temp_free_i64(tmp);
tcg_temp_free_i64(tmp2);
@@ -3647,7 +3647,7 @@ static void disas_b9(DisasContext *s, int op, int r1, int r2)
tmp32_1 = load_reg32(r2);
tmp32_2 = tcg_const_i32(r1);
gen_op_calc_cc(s);
- gen_helper_slb(cc_op, cc_op, tmp32_2, tmp32_1);
+ gen_helper_slb(cc_op, cpu_env, cc_op, tmp32_2, tmp32_1);
set_cc_static(s);
tcg_temp_free_i32(tmp32_1);
tcg_temp_free_i32(tmp32_2);
--
1.7.12.1

View File

@ -0,0 +1,190 @@
From ead7a100e907eddd0ba9f3cebb5f84c1afb120b8 Mon Sep 17 00:00:00 2001
From: Blue Swirl <blauwirbel@gmail.com>
Date: Sun, 2 Sep 2012 07:33:38 +0000
Subject: [PATCH] target-s390x: avoid AREG0 for condition code helpers
Make condition code helpers take a parameter for CPUState instead
of relying on global env.
Signed-off-by: Blue Swirl <blauwirbel@gmail.com>
Signed-off-by: Alexander Graf <agraf@suse.de>
Signed-off-by: Michael Roth <mdroth@linux.vnet.ibm.com>
---
target-s390x/Makefile.objs | 1 -
target-s390x/cc_helper.c | 11 +++++------
target-s390x/helper.h | 10 +++++-----
target-s390x/translate.c | 16 ++++++++--------
4 files changed, 18 insertions(+), 20 deletions(-)
diff --git a/target-s390x/Makefile.objs b/target-s390x/Makefile.objs
index 7b2c5c1..736cf33 100644
--- a/target-s390x/Makefile.objs
+++ b/target-s390x/Makefile.objs
@@ -3,6 +3,5 @@ obj-y += int_helper.o fpu_helper.o cc_helper.o mem_helper.o misc_helper.o
obj-$(CONFIG_SOFTMMU) += machine.o
obj-$(CONFIG_KVM) += kvm.o
-$(obj)/cc_helper.o: QEMU_CFLAGS += $(HELPER_CFLAGS)
$(obj)/mem_helper.o: QEMU_CFLAGS += $(HELPER_CFLAGS)
$(obj)/misc_helper.o: QEMU_CFLAGS += $(HELPER_CFLAGS)
diff --git a/target-s390x/cc_helper.c b/target-s390x/cc_helper.c
index 9c3a2c4..19ef145 100644
--- a/target-s390x/cc_helper.c
+++ b/target-s390x/cc_helper.c
@@ -19,7 +19,6 @@
*/
#include "cpu.h"
-#include "dyngen-exec.h"
#include "helper.h"
/* #define DEBUG_HELPER */
@@ -500,14 +499,14 @@ uint32_t calc_cc(CPUS390XState *env, uint32_t cc_op, uint64_t src, uint64_t dst,
return do_calc_cc(env, cc_op, src, dst, vr);
}
-uint32_t HELPER(calc_cc)(uint32_t cc_op, uint64_t src, uint64_t dst,
- uint64_t vr)
+uint32_t HELPER(calc_cc)(CPUS390XState *env, uint32_t cc_op, uint64_t src,
+ uint64_t dst, uint64_t vr)
{
return do_calc_cc(env, cc_op, src, dst, vr);
}
/* insert psw mask and condition code into r1 */
-void HELPER(ipm)(uint32_t cc, uint32_t r1)
+void HELPER(ipm)(CPUS390XState *env, uint32_t cc, uint32_t r1)
{
uint64_t r = env->regs[r1];
@@ -519,13 +518,13 @@ void HELPER(ipm)(uint32_t cc, uint32_t r1)
}
#ifndef CONFIG_USER_ONLY
-void HELPER(load_psw)(uint64_t mask, uint64_t addr)
+void HELPER(load_psw)(CPUS390XState *env, uint64_t mask, uint64_t addr)
{
load_psw(env, mask, addr);
cpu_loop_exit(env);
}
-void HELPER(sacf)(uint64_t a1)
+void HELPER(sacf)(CPUS390XState *env, uint64_t a1)
{
HELPER_LOG("%s: %16" PRIx64 "\n", __func__, a1);
diff --git a/target-s390x/helper.h b/target-s390x/helper.h
index c03cd59..876b88e 100644
--- a/target-s390x/helper.h
+++ b/target-s390x/helper.h
@@ -36,7 +36,7 @@ DEF_HELPER_FLAGS_1(abs_i64, TCG_CALL_PURE|TCG_CALL_CONST, i64, s64)
DEF_HELPER_FLAGS_1(nabs_i64, TCG_CALL_PURE|TCG_CALL_CONST, s64, s64)
DEF_HELPER_3(stcmh, void, i32, i64, i32)
DEF_HELPER_3(icmh, i32, i32, i64, i32)
-DEF_HELPER_2(ipm, void, i32, i32)
+DEF_HELPER_3(ipm, void, env, i32, i32)
DEF_HELPER_FLAGS_3(addc_u32, TCG_CALL_PURE|TCG_CALL_CONST, i32, i32, i32, i32)
DEF_HELPER_FLAGS_3(set_cc_addc_u64, TCG_CALL_PURE|TCG_CALL_CONST, i32, i64, i64, i64)
DEF_HELPER_3(stam, void, i32, i64, i32)
@@ -115,7 +115,7 @@ DEF_HELPER_3(tr, void, i32, i64, i64)
DEF_HELPER_2(servc, i32, i32, i64)
DEF_HELPER_3(diag, i64, i32, i64, i64)
-DEF_HELPER_2(load_psw, void, i64, i64)
+DEF_HELPER_3(load_psw, void, env, i64, i64)
DEF_HELPER_1(program_interrupt, void, i32)
DEF_HELPER_FLAGS_1(stidp, TCG_CALL_CONST, void, i64)
DEF_HELPER_FLAGS_1(spx, TCG_CALL_CONST, void, i64)
@@ -139,14 +139,14 @@ DEF_HELPER_2(csp, i32, i32, i32)
DEF_HELPER_3(mvcs, i32, i64, i64, i64)
DEF_HELPER_3(mvcp, i32, i64, i64, i64)
DEF_HELPER_3(sigp, i32, i64, i32, i64)
-DEF_HELPER_1(sacf, void, i64)
+DEF_HELPER_2(sacf, void, env, i64)
DEF_HELPER_FLAGS_2(ipte, TCG_CALL_CONST, void, i64, i64)
DEF_HELPER_FLAGS_0(ptlb, TCG_CALL_CONST, void)
DEF_HELPER_2(lra, i32, i64, i32)
DEF_HELPER_2(stura, void, i64, i32)
DEF_HELPER_2(cksm, void, i32, i32)
-DEF_HELPER_FLAGS_4(calc_cc, TCG_CALL_PURE|TCG_CALL_CONST,
- i32, i32, i64, i64, i64)
+DEF_HELPER_FLAGS_5(calc_cc, TCG_CALL_PURE|TCG_CALL_CONST,
+ i32, env, i32, i64, i64, i64)
#include "def-helper.h"
diff --git a/target-s390x/translate.c b/target-s390x/translate.c
index 2a61e92..1d87272 100644
--- a/target-s390x/translate.c
+++ b/target-s390x/translate.c
@@ -722,7 +722,7 @@ static void gen_op_calc_cc(DisasContext *s)
case CC_OP_NZ_F32:
case CC_OP_NZ_F64:
/* 1 argument */
- gen_helper_calc_cc(cc_op, local_cc_op, dummy, cc_dst, dummy);
+ gen_helper_calc_cc(cc_op, cpu_env, local_cc_op, dummy, cc_dst, dummy);
break;
case CC_OP_ICM:
case CC_OP_LTGT_32:
@@ -735,7 +735,7 @@ static void gen_op_calc_cc(DisasContext *s)
case CC_OP_LTGT_F64:
case CC_OP_SLAG:
/* 2 arguments */
- gen_helper_calc_cc(cc_op, local_cc_op, cc_src, cc_dst, dummy);
+ gen_helper_calc_cc(cc_op, cpu_env, local_cc_op, cc_src, cc_dst, dummy);
break;
case CC_OP_ADD_64:
case CC_OP_ADDU_64:
@@ -746,11 +746,11 @@ static void gen_op_calc_cc(DisasContext *s)
case CC_OP_SUB_32:
case CC_OP_SUBU_32:
/* 3 arguments */
- gen_helper_calc_cc(cc_op, local_cc_op, cc_src, cc_dst, cc_vr);
+ gen_helper_calc_cc(cc_op, cpu_env, local_cc_op, cc_src, cc_dst, cc_vr);
break;
case CC_OP_DYNAMIC:
/* unknown operation - assume 3 arguments and cc_op in env */
- gen_helper_calc_cc(cc_op, cc_op, cc_src, cc_dst, cc_vr);
+ gen_helper_calc_cc(cc_op, cpu_env, cc_op, cc_src, cc_dst, cc_vr);
break;
default:
tcg_abort();
@@ -2628,7 +2628,7 @@ static void disas_b2(DisasContext *s, int op, uint32_t insn)
case 0x22: /* IPM R1 [RRE] */
tmp32_1 = tcg_const_i32(r1);
gen_op_calc_cc(s);
- gen_helper_ipm(cc_op, tmp32_1);
+ gen_helper_ipm(cpu_env, cc_op, tmp32_1);
tcg_temp_free_i32(tmp32_1);
break;
case 0x41: /* CKSM R1,R2 [RRE] */
@@ -2916,7 +2916,7 @@ static void disas_b2(DisasContext *s, int op, uint32_t insn)
decode_rs(s, insn, &r1, &r3, &b2, &d2);
tmp = get_address(s, 0, b2, d2);
potential_page_fault(s);
- gen_helper_sacf(tmp);
+ gen_helper_sacf(cpu_env, tmp);
tcg_temp_free_i64(tmp);
/* addressing mode has changed, so end the block */
s->pc += ilc * 2;
@@ -2967,7 +2967,7 @@ static void disas_b2(DisasContext *s, int op, uint32_t insn)
tcg_gen_qemu_ld64(tmp2, tmp, get_mem_index(s));
tcg_gen_addi_i64(tmp, tmp, 8);
tcg_gen_qemu_ld64(tmp3, tmp, get_mem_index(s));
- gen_helper_load_psw(tmp2, tmp3);
+ gen_helper_load_psw(cpu_env, tmp2, tmp3);
/* we need to keep cc_op intact */
s->is_jmp = DISAS_JUMP;
tcg_temp_free_i64(tmp);
@@ -4527,7 +4527,7 @@ static void disas_s390_insn(DisasContext *s)
tcg_gen_qemu_ld32u(tmp2, tmp, get_mem_index(s));
tcg_gen_addi_i64(tmp, tmp, 4);
tcg_gen_qemu_ld32u(tmp3, tmp, get_mem_index(s));
- gen_helper_load_psw(tmp2, tmp3);
+ gen_helper_load_psw(cpu_env, tmp2, tmp3);
tcg_temp_free_i64(tmp);
tcg_temp_free_i64(tmp2);
tcg_temp_free_i64(tmp3);
--
1.7.12.1

View File

@ -0,0 +1,411 @@
From 208547c7afbe6ee8a9a1f81095e67a6cbe4a37ec Mon Sep 17 00:00:00 2001
From: Blue Swirl <blauwirbel@gmail.com>
Date: Sun, 2 Sep 2012 07:33:39 +0000
Subject: [PATCH] target-s390x: avoid AREG0 for misc helpers
Make misc helpers take a parameter for CPUState instead
of relying on global env.
Signed-off-by: Blue Swirl <blauwirbel@gmail.com>
[agraf: fix conflict]
Signed-off-by: Alexander Graf <agraf@suse.de>
Signed-off-by: Michael Roth <mdroth@linux.vnet.ibm.com>
---
target-s390x/Makefile.objs | 1 -
target-s390x/helper.h | 26 +++++++++++-----------
target-s390x/mem_helper.c | 2 +-
target-s390x/misc_helper.c | 55 +++++++++++++++++++++++++---------------------
target-s390x/translate.c | 32 +++++++++++++--------------
5 files changed, 60 insertions(+), 56 deletions(-)
diff --git a/target-s390x/Makefile.objs b/target-s390x/Makefile.objs
index 736cf33..156d946 100644
--- a/target-s390x/Makefile.objs
+++ b/target-s390x/Makefile.objs
@@ -4,4 +4,3 @@ obj-$(CONFIG_SOFTMMU) += machine.o
obj-$(CONFIG_KVM) += kvm.o
$(obj)/mem_helper.o: QEMU_CFLAGS += $(HELPER_CFLAGS)
-$(obj)/misc_helper.o: QEMU_CFLAGS += $(HELPER_CFLAGS)
diff --git a/target-s390x/helper.h b/target-s390x/helper.h
index 876b88e..f4e0b37 100644
--- a/target-s390x/helper.h
+++ b/target-s390x/helper.h
@@ -1,6 +1,6 @@
#include "def-helper.h"
-DEF_HELPER_1(exception, void, i32)
+DEF_HELPER_2(exception, void, env, i32)
DEF_HELPER_3(nc, i32, i32, i64, i64)
DEF_HELPER_3(oc, i32, i32, i64, i64)
DEF_HELPER_3(xc, i32, i32, i64, i64)
@@ -113,20 +113,20 @@ DEF_HELPER_FLAGS_1(cvd, TCG_CALL_PURE|TCG_CALL_CONST, i64, s32)
DEF_HELPER_3(unpk, void, i32, i64, i64)
DEF_HELPER_3(tr, void, i32, i64, i64)
-DEF_HELPER_2(servc, i32, i32, i64)
-DEF_HELPER_3(diag, i64, i32, i64, i64)
+DEF_HELPER_3(servc, i32, env, i32, i64)
+DEF_HELPER_4(diag, i64, env, i32, i64, i64)
DEF_HELPER_3(load_psw, void, env, i64, i64)
DEF_HELPER_1(program_interrupt, void, i32)
-DEF_HELPER_FLAGS_1(stidp, TCG_CALL_CONST, void, i64)
-DEF_HELPER_FLAGS_1(spx, TCG_CALL_CONST, void, i64)
+DEF_HELPER_FLAGS_2(stidp, TCG_CALL_CONST, void, env, i64)
+DEF_HELPER_FLAGS_2(spx, TCG_CALL_CONST, void, env, i64)
DEF_HELPER_FLAGS_1(sck, TCG_CALL_CONST, i32, i64)
-DEF_HELPER_1(stck, i32, i64)
-DEF_HELPER_1(stcke, i32, i64)
-DEF_HELPER_FLAGS_1(sckc, TCG_CALL_CONST, void, i64)
-DEF_HELPER_FLAGS_1(stckc, TCG_CALL_CONST, void, i64)
-DEF_HELPER_FLAGS_1(spt, TCG_CALL_CONST, void, i64)
-DEF_HELPER_FLAGS_1(stpt, TCG_CALL_CONST, void, i64)
-DEF_HELPER_3(stsi, i32, i64, i32, i32)
+DEF_HELPER_2(stck, i32, env, i64)
+DEF_HELPER_2(stcke, i32, env, i64)
+DEF_HELPER_FLAGS_2(sckc, TCG_CALL_CONST, void, env, i64)
+DEF_HELPER_FLAGS_2(stckc, TCG_CALL_CONST, void, env, i64)
+DEF_HELPER_FLAGS_2(spt, TCG_CALL_CONST, void, env, i64)
+DEF_HELPER_FLAGS_2(stpt, TCG_CALL_CONST, void, env, i64)
+DEF_HELPER_4(stsi, i32, env, i64, i32, i32)
DEF_HELPER_3(lctl, void, i32, i64, i32)
DEF_HELPER_3(lctlg, void, i32, i64, i32)
DEF_HELPER_3(stctl, void, i32, i64, i32)
@@ -138,7 +138,7 @@ DEF_HELPER_FLAGS_2(rrbe, TCG_CALL_CONST, i32, i32, i64)
DEF_HELPER_2(csp, i32, i32, i32)
DEF_HELPER_3(mvcs, i32, i64, i64, i64)
DEF_HELPER_3(mvcp, i32, i64, i64, i64)
-DEF_HELPER_3(sigp, i32, i64, i32, i64)
+DEF_HELPER_4(sigp, i32, env, i64, i32, i64)
DEF_HELPER_2(sacf, void, env, i64)
DEF_HELPER_FLAGS_2(ipte, TCG_CALL_CONST, void, i64, i64)
DEF_HELPER_FLAGS_0(ptlb, TCG_CALL_CONST, void)
diff --git a/target-s390x/mem_helper.c b/target-s390x/mem_helper.c
index 3f8b3ba..52f2602 100644
--- a/target-s390x/mem_helper.c
+++ b/target-s390x/mem_helper.c
@@ -595,7 +595,7 @@ uint32_t HELPER(ex)(uint32_t cc, uint64_t v1, uint64_t addr, uint64_t ret)
env->psw.addr = ret - 4;
env->int_svc_code = (insn | v1) & 0xff;
env->int_svc_ilc = 4;
- helper_exception(EXCP_SVC);
+ helper_exception(env, EXCP_SVC);
} else if ((insn & 0xff00) == 0xbf00) {
uint32_t insn2, r1, r3, b2, d2;
diff --git a/target-s390x/misc_helper.c b/target-s390x/misc_helper.c
index 1d5137f..ced26c6 100644
--- a/target-s390x/misc_helper.c
+++ b/target-s390x/misc_helper.c
@@ -21,7 +21,6 @@
#include "cpu.h"
#include "memory.h"
#include "cputlb.h"
-#include "dyngen-exec.h"
#include "host-utils.h"
#include "helper.h"
#include <string.h>
@@ -32,7 +31,10 @@
#endif
#if !defined(CONFIG_USER_ONLY)
+/* temporarily disabled due to wrapper use */
+#if 0
#include "softmmu_exec.h"
+#endif
#include "sysemu.h"
#endif
@@ -44,7 +46,7 @@
#endif
/* raise an exception */
-void HELPER(exception)(uint32_t excp)
+void HELPER(exception)(CPUS390XState *env, uint32_t excp)
{
HELPER_LOG("%s: exception %d\n", __func__, excp);
env->exception_index = excp;
@@ -112,7 +114,7 @@ int sclp_service_call(CPUS390XState *env, uint32_t sccb, uint64_t code)
}
/* SCLP service call */
-uint32_t HELPER(servc)(uint32_t r1, uint64_t r2)
+uint32_t HELPER(servc)(CPUS390XState *env, uint32_t r1, uint64_t r2)
{
int r;
@@ -125,7 +127,8 @@ uint32_t HELPER(servc)(uint32_t r1, uint64_t r2)
}
/* DIAG */
-uint64_t HELPER(diag)(uint32_t num, uint64_t mem, uint64_t code)
+uint64_t HELPER(diag)(CPUS390XState *env, uint32_t num, uint64_t mem,
+ uint64_t code)
{
uint64_t r;
@@ -155,17 +158,17 @@ uint64_t HELPER(diag)(uint32_t num, uint64_t mem, uint64_t code)
}
/* Store CPU ID */
-void HELPER(stidp)(uint64_t a1)
+void HELPER(stidp)(CPUS390XState *env, uint64_t a1)
{
- stq(a1, env->cpu_num);
+ cpu_stq_data(env, a1, env->cpu_num);
}
/* Set Prefix */
-void HELPER(spx)(uint64_t a1)
+void HELPER(spx)(CPUS390XState *env, uint64_t a1)
{
uint32_t prefix;
- prefix = ldl(a1);
+ prefix = cpu_ldl_data(env, a1);
env->psa = prefix & 0xfffff000;
qemu_log("prefix: %#x\n", prefix);
tlb_flush_page(env, 0);
@@ -191,31 +194,31 @@ static inline uint64_t clock_value(CPUS390XState *env)
}
/* Store Clock */
-uint32_t HELPER(stck)(uint64_t a1)
+uint32_t HELPER(stck)(CPUS390XState *env, uint64_t a1)
{
- stq(a1, clock_value(env));
+ cpu_stq_data(env, a1, clock_value(env));
return 0;
}
/* Store Clock Extended */
-uint32_t HELPER(stcke)(uint64_t a1)
+uint32_t HELPER(stcke)(CPUS390XState *env, uint64_t a1)
{
- stb(a1, 0);
+ cpu_stb_data(env, a1, 0);
/* basically the same value as stck */
- stq(a1 + 1, clock_value(env) | env->cpu_num);
+ cpu_stq_data(env, a1 + 1, clock_value(env) | env->cpu_num);
/* more fine grained than stck */
- stq(a1 + 9, 0);
+ cpu_stq_data(env, a1 + 9, 0);
/* XXX programmable fields */
- stw(a1 + 17, 0);
+ cpu_stw_data(env, a1 + 17, 0);
return 0;
}
/* Set Clock Comparator */
-void HELPER(sckc)(uint64_t a1)
+void HELPER(sckc)(CPUS390XState *env, uint64_t a1)
{
- uint64_t time = ldq(a1);
+ uint64_t time = cpu_ldq_data(env, a1);
if (time == -1ULL) {
return;
@@ -230,16 +233,16 @@ void HELPER(sckc)(uint64_t a1)
}
/* Store Clock Comparator */
-void HELPER(stckc)(uint64_t a1)
+void HELPER(stckc)(CPUS390XState *env, uint64_t a1)
{
/* XXX implement */
- stq(a1, 0);
+ cpu_stq_data(env, a1, 0);
}
/* Set CPU Timer */
-void HELPER(spt)(uint64_t a1)
+void HELPER(spt)(CPUS390XState *env, uint64_t a1)
{
- uint64_t time = ldq(a1);
+ uint64_t time = cpu_ldq_data(env, a1);
if (time == -1ULL) {
return;
@@ -252,14 +255,15 @@ void HELPER(spt)(uint64_t a1)
}
/* Store CPU Timer */
-void HELPER(stpt)(uint64_t a1)
+void HELPER(stpt)(CPUS390XState *env, uint64_t a1)
{
/* XXX implement */
- stq(a1, 0);
+ cpu_stq_data(env, a1, 0);
}
/* Store System Information */
-uint32_t HELPER(stsi)(uint64_t a0, uint32_t r0, uint32_t r1)
+uint32_t HELPER(stsi)(CPUS390XState *env, uint64_t a0, uint32_t r0,
+ uint32_t r1)
{
int cc = 0;
int sel1, sel2;
@@ -384,7 +388,8 @@ uint32_t HELPER(stsi)(uint64_t a0, uint32_t r0, uint32_t r1)
return cc;
}
-uint32_t HELPER(sigp)(uint64_t order_code, uint32_t r1, uint64_t cpu_addr)
+uint32_t HELPER(sigp)(CPUS390XState *env, uint64_t order_code, uint32_t r1,
+ uint64_t cpu_addr)
{
int cc = 0;
diff --git a/target-s390x/translate.c b/target-s390x/translate.c
index 1d87272..0c61e63 100644
--- a/target-s390x/translate.c
+++ b/target-s390x/translate.c
@@ -312,7 +312,7 @@ static inline void gen_debug(DisasContext *s)
TCGv_i32 tmp = tcg_const_i32(EXCP_DEBUG);
update_psw_addr(s);
gen_op_calc_cc(s);
- gen_helper_exception(tmp);
+ gen_helper_exception(cpu_env, tmp);
tcg_temp_free_i32(tmp);
s->is_jmp = DISAS_EXCP;
}
@@ -324,7 +324,7 @@ static void gen_illegal_opcode(DisasContext *s, int ilc)
TCGv_i32 tmp = tcg_const_i32(EXCP_SPEC);
update_psw_addr(s);
gen_op_calc_cc(s);
- gen_helper_exception(tmp);
+ gen_helper_exception(cpu_env, tmp);
tcg_temp_free_i32(tmp);
s->is_jmp = DISAS_EXCP;
}
@@ -377,7 +377,7 @@ static void gen_program_exception(DisasContext *s, int ilc, int code)
/* trigger exception */
tmp = tcg_const_i32(EXCP_PGM);
- gen_helper_exception(tmp);
+ gen_helper_exception(cpu_env, tmp);
tcg_temp_free_i32(tmp);
/* end TB here */
@@ -2712,7 +2712,7 @@ static void disas_b2(DisasContext *s, int op, uint32_t insn)
decode_rs(s, insn, &r1, &r3, &b2, &d2);
tmp = get_address(s, 0, b2, d2);
potential_page_fault(s);
- gen_helper_stidp(tmp);
+ gen_helper_stidp(cpu_env, tmp);
tcg_temp_free_i64(tmp);
break;
case 0x04: /* SCK D2(B2) [S] */
@@ -2730,7 +2730,7 @@ static void disas_b2(DisasContext *s, int op, uint32_t insn)
decode_rs(s, insn, &r1, &r3, &b2, &d2);
tmp = get_address(s, 0, b2, d2);
potential_page_fault(s);
- gen_helper_stck(cc_op, tmp);
+ gen_helper_stck(cc_op, cpu_env, tmp);
set_cc_static(s);
tcg_temp_free_i64(tmp);
break;
@@ -2740,7 +2740,7 @@ static void disas_b2(DisasContext *s, int op, uint32_t insn)
decode_rs(s, insn, &r1, &r3, &b2, &d2);
tmp = get_address(s, 0, b2, d2);
potential_page_fault(s);
- gen_helper_sckc(tmp);
+ gen_helper_sckc(cpu_env, tmp);
tcg_temp_free_i64(tmp);
break;
case 0x07: /* STCKC D2(B2) [S] */
@@ -2749,7 +2749,7 @@ static void disas_b2(DisasContext *s, int op, uint32_t insn)
decode_rs(s, insn, &r1, &r3, &b2, &d2);
tmp = get_address(s, 0, b2, d2);
potential_page_fault(s);
- gen_helper_stckc(tmp);
+ gen_helper_stckc(cpu_env, tmp);
tcg_temp_free_i64(tmp);
break;
case 0x08: /* SPT D2(B2) [S] */
@@ -2758,7 +2758,7 @@ static void disas_b2(DisasContext *s, int op, uint32_t insn)
decode_rs(s, insn, &r1, &r3, &b2, &d2);
tmp = get_address(s, 0, b2, d2);
potential_page_fault(s);
- gen_helper_spt(tmp);
+ gen_helper_spt(cpu_env, tmp);
tcg_temp_free_i64(tmp);
break;
case 0x09: /* STPT D2(B2) [S] */
@@ -2767,7 +2767,7 @@ static void disas_b2(DisasContext *s, int op, uint32_t insn)
decode_rs(s, insn, &r1, &r3, &b2, &d2);
tmp = get_address(s, 0, b2, d2);
potential_page_fault(s);
- gen_helper_stpt(tmp);
+ gen_helper_stpt(cpu_env, tmp);
tcg_temp_free_i64(tmp);
break;
case 0x0a: /* SPKA D2(B2) [S] */
@@ -2793,7 +2793,7 @@ static void disas_b2(DisasContext *s, int op, uint32_t insn)
decode_rs(s, insn, &r1, &r3, &b2, &d2);
tmp = get_address(s, 0, b2, d2);
potential_page_fault(s);
- gen_helper_spx(tmp);
+ gen_helper_spx(cpu_env, tmp);
tcg_temp_free_i64(tmp);
break;
case 0x11: /* STPX D2(B2) [S] */
@@ -2906,7 +2906,7 @@ static void disas_b2(DisasContext *s, int op, uint32_t insn)
decode_rs(s, insn, &r1, &r3, &b2, &d2);
tmp = get_address(s, 0, b2, d2);
potential_page_fault(s);
- gen_helper_stcke(cc_op, tmp);
+ gen_helper_stcke(cc_op, cpu_env, tmp);
set_cc_static(s);
tcg_temp_free_i64(tmp);
break;
@@ -2930,7 +2930,7 @@ static void disas_b2(DisasContext *s, int op, uint32_t insn)
tmp32_1 = load_reg32(0);
tmp32_2 = load_reg32(1);
potential_page_fault(s);
- gen_helper_stsi(cc_op, tmp, tmp32_1, tmp32_2);
+ gen_helper_stsi(cc_op, cpu_env, tmp, tmp32_1, tmp32_2);
set_cc_static(s);
tcg_temp_free_i64(tmp);
tcg_temp_free_i32(tmp32_1);
@@ -2980,7 +2980,7 @@ static void disas_b2(DisasContext *s, int op, uint32_t insn)
potential_page_fault(s);
tmp32_1 = load_reg32(r2);
tmp = load_reg(r1);
- gen_helper_servc(cc_op, tmp32_1, tmp);
+ gen_helper_servc(cc_op, cpu_env, tmp32_1, tmp);
set_cc_static(s);
tcg_temp_free_i32(tmp32_1);
tcg_temp_free_i64(tmp);
@@ -3926,7 +3926,7 @@ static void disas_s390_insn(DisasContext *s)
tmp32_3 = tcg_const_i32(EXCP_SVC);
tcg_gen_st_i32(tmp32_1, cpu_env, offsetof(CPUS390XState, int_svc_code));
tcg_gen_st_i32(tmp32_2, cpu_env, offsetof(CPUS390XState, int_svc_ilc));
- gen_helper_exception(tmp32_3);
+ gen_helper_exception(cpu_env, tmp32_3);
s->is_jmp = DISAS_EXCP;
tcg_temp_free_i32(tmp32_1);
tcg_temp_free_i32(tmp32_2);
@@ -4543,7 +4543,7 @@ static void disas_s390_insn(DisasContext *s)
tmp32_1 = tcg_const_i32(insn & 0xfff);
tmp2 = load_reg(2);
tmp3 = load_reg(1);
- gen_helper_diag(tmp2, tmp32_1, tmp2, tmp3);
+ gen_helper_diag(tmp2, cpu_env, tmp32_1, tmp2, tmp3);
store_reg(2, tmp2);
tcg_temp_free_i32(tmp32_1);
tcg_temp_free_i64(tmp2);
@@ -4777,7 +4777,7 @@ static void disas_s390_insn(DisasContext *s)
tmp2 = load_reg(r3);
tmp32_1 = tcg_const_i32(r1);
potential_page_fault(s);
- gen_helper_sigp(cc_op, tmp, tmp32_1, tmp2);
+ gen_helper_sigp(cc_op, cpu_env, tmp, tmp32_1, tmp2);
set_cc_static(s);
tcg_temp_free_i64(tmp);
tcg_temp_free_i64(tmp2);
--
1.7.12.1

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,64 @@
From 0b95df52ecad351c916108e9f3a9d1bc3327b495 Mon Sep 17 00:00:00 2001
From: Aurelien Jarno <aurelien@aurel32.net>
Date: Sat, 8 Sep 2012 03:45:43 +0000
Subject: [PATCH] tcg/s390: fix ld/st with CONFIG_TCG_PASS_AREG0
The load/store slow path has been broken in e141ab52d:
- We need to move 4 registers for store functions and 3 registers for
load functions and not the reverse.
- According to the s390x calling convention the arguments of a function
should be zero extended. This means that the register shift should be
done with TCG_TYPE_I64 to ensure the higher word is correctly zero
extended when needed.
I am aware that CONFIG_TCG_PASS_AREG0 is being removed and thus that
this patch can be improved, but doing so means it can also be applied to
the 1.1 and 1.2 stable branches.
Signed-off-by: Aurelien Jarno <aurelien@aurel32.net>
Signed-off-by: Alexander Graf <agraf@suse.de>
Signed-off-by: Michael Roth <mdroth@linux.vnet.ibm.com>
---
tcg/s390/tcg-target.c | 14 +++++++-------
1 file changed, 7 insertions(+), 7 deletions(-)
diff --git a/tcg/s390/tcg-target.c b/tcg/s390/tcg-target.c
index 04662c1..99b5339 100644
--- a/tcg/s390/tcg-target.c
+++ b/tcg/s390/tcg-target.c
@@ -1509,11 +1509,13 @@ static void tcg_prepare_qemu_ldst(TCGContext* s, TCGReg data_reg,
tcg_out_movi(s, TCG_TYPE_I32, TCG_REG_R4, mem_index);
#ifdef CONFIG_TCG_PASS_AREG0
/* XXX/FIXME: suboptimal */
- tcg_out_mov(s, TCG_TYPE_I32, tcg_target_call_iarg_regs[2],
+ tcg_out_mov(s, TCG_TYPE_I64, tcg_target_call_iarg_regs[3],
+ tcg_target_call_iarg_regs[2]);
+ tcg_out_mov(s, TCG_TYPE_I64, tcg_target_call_iarg_regs[2],
tcg_target_call_iarg_regs[1]);
- tcg_out_mov(s, TCG_TYPE_TL, tcg_target_call_iarg_regs[1],
+ tcg_out_mov(s, TCG_TYPE_I64, tcg_target_call_iarg_regs[1],
tcg_target_call_iarg_regs[0]);
- tcg_out_mov(s, TCG_TYPE_PTR, tcg_target_call_iarg_regs[0],
+ tcg_out_mov(s, TCG_TYPE_I64, tcg_target_call_iarg_regs[0],
TCG_AREG0);
#endif
tgen_calli(s, (tcg_target_ulong)qemu_st_helpers[s_bits]);
@@ -1521,13 +1523,11 @@ static void tcg_prepare_qemu_ldst(TCGContext* s, TCGReg data_reg,
tcg_out_movi(s, TCG_TYPE_I32, arg1, mem_index);
#ifdef CONFIG_TCG_PASS_AREG0
/* XXX/FIXME: suboptimal */
- tcg_out_mov(s, TCG_TYPE_I32, tcg_target_call_iarg_regs[3],
- tcg_target_call_iarg_regs[2]);
tcg_out_mov(s, TCG_TYPE_I64, tcg_target_call_iarg_regs[2],
tcg_target_call_iarg_regs[1]);
- tcg_out_mov(s, TCG_TYPE_TL, tcg_target_call_iarg_regs[1],
+ tcg_out_mov(s, TCG_TYPE_I64, tcg_target_call_iarg_regs[1],
tcg_target_call_iarg_regs[0]);
- tcg_out_mov(s, TCG_TYPE_PTR, tcg_target_call_iarg_regs[0],
+ tcg_out_mov(s, TCG_TYPE_I64, tcg_target_call_iarg_regs[0],
TCG_AREG0);
#endif
tgen_calli(s, (tcg_target_ulong)qemu_ld_helpers[s_bits]);
--
1.7.12.1

View File

@ -0,0 +1,47 @@
From e7c3f6b4365f3162f8e25d58f76410aca28719a2 Mon Sep 17 00:00:00 2001
From: Stefan Weil <sw@weilnetz.de>
Date: Tue, 4 Sep 2012 07:35:57 +0200
Subject: [PATCH] target-arm: Fix potential buffer overflow
Report from smatch:
target-arm/helper.c:651 arm946_prbs_read(6) error:
buffer overflow 'env->cp15.c6_region' 8 <= 8
target-arm/helper.c:661 arm946_prbs_write(6) error:
buffer overflow 'env->cp15.c6_region' 8 <= 8
c7_region is an array with 8 elements, so the index must be less than 8.
Signed-off-by: Stefan Weil <sw@weilnetz.de>
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
Signed-off-by: Aurelien Jarno <aurelien@aurel32.net>
Signed-off-by: Michael Roth <mdroth@linux.vnet.ibm.com>
---
target-arm/helper.c | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/target-arm/helper.c b/target-arm/helper.c
index dceaa95..e27df96 100644
--- a/target-arm/helper.c
+++ b/target-arm/helper.c
@@ -645,7 +645,7 @@ static int pmsav5_insn_ap_read(CPUARMState *env, const ARMCPRegInfo *ri,
static int arm946_prbs_read(CPUARMState *env, const ARMCPRegInfo *ri,
uint64_t *value)
{
- if (ri->crm > 8) {
+ if (ri->crm >= 8) {
return EXCP_UDEF;
}
*value = env->cp15.c6_region[ri->crm];
@@ -655,7 +655,7 @@ static int arm946_prbs_read(CPUARMState *env, const ARMCPRegInfo *ri,
static int arm946_prbs_write(CPUARMState *env, const ARMCPRegInfo *ri,
uint64_t value)
{
- if (ri->crm > 8) {
+ if (ri->crm >= 8) {
return EXCP_UDEF;
}
env->cp15.c6_region[ri->crm] = value;
--
1.7.12.1

View File

@ -0,0 +1,57 @@
From 16f29b266435c7eaffc5081c6bba4651d56a8ce8 Mon Sep 17 00:00:00 2001
From: Aurelien Jarno <aurelien@aurel32.net>
Date: Thu, 6 Sep 2012 16:47:13 +0200
Subject: [PATCH] tcg/optimize: split expression simplification
Split expression simplification in multiple parts so that a given op
can appear multiple times. This patch should not change anything.
Reviewed-by: Richard Henderson <rth@twiddle.net>
Signed-off-by: Aurelien Jarno <aurelien@aurel32.net>
Signed-off-by: Michael Roth <mdroth@linux.vnet.ibm.com>
---
tcg/optimize.c | 14 +++++++++++++-
1 file changed, 13 insertions(+), 1 deletion(-)
diff --git a/tcg/optimize.c b/tcg/optimize.c
index 9c65474..63f970d 100644
--- a/tcg/optimize.c
+++ b/tcg/optimize.c
@@ -322,7 +322,7 @@ static TCGArg *tcg_constant_folding(TCGContext *s, uint16_t *tcg_opc_ptr,
break;
}
- /* Simplify expression if possible. */
+ /* Simplify expression for "op r, a, 0 => mov r, a" cases */
switch (op) {
CASE_OP_32_64(add):
CASE_OP_32_64(sub):
@@ -352,6 +352,12 @@ static TCGArg *tcg_constant_folding(TCGContext *s, uint16_t *tcg_opc_ptr,
continue;
}
break;
+ default:
+ break;
+ }
+
+ /* Simplify expression for "op r, a, 0 => movi r, 0" cases */
+ switch (op) {
CASE_OP_32_64(mul):
if ((temps[args[2]].state == TCG_TEMP_CONST
&& temps[args[2]].val == 0)) {
@@ -362,6 +368,12 @@ static TCGArg *tcg_constant_folding(TCGContext *s, uint16_t *tcg_opc_ptr,
continue;
}
break;
+ default:
+ break;
+ }
+
+ /* Simplify expression for "op r, a, a => mov r, a" cases */
+ switch (op) {
CASE_OP_32_64(or):
CASE_OP_32_64(and):
if (args[1] == args[2]) {
--
1.7.12.1

View File

@ -0,0 +1,30 @@
From f69f9bd1a7a095ee153eea5422651780aef178b0 Mon Sep 17 00:00:00 2001
From: Aurelien Jarno <aurelien@aurel32.net>
Date: Thu, 6 Sep 2012 16:47:14 +0200
Subject: [PATCH] tcg/optimize: simplify or/xor r, a, 0 cases
or/xor r, a, 0 is equivalent to a mov r, a.
Reviewed-by: Richard Henderson <rth@twiddle.net>
Signed-off-by: Aurelien Jarno <aurelien@aurel32.net>
Signed-off-by: Michael Roth <mdroth@linux.vnet.ibm.com>
---
tcg/optimize.c | 2 ++
1 file changed, 2 insertions(+)
diff --git a/tcg/optimize.c b/tcg/optimize.c
index 63f970d..0db849e 100644
--- a/tcg/optimize.c
+++ b/tcg/optimize.c
@@ -331,6 +331,8 @@ static TCGArg *tcg_constant_folding(TCGContext *s, uint16_t *tcg_opc_ptr,
CASE_OP_32_64(sar):
CASE_OP_32_64(rotl):
CASE_OP_32_64(rotr):
+ CASE_OP_32_64(or):
+ CASE_OP_32_64(xor):
if (temps[args[1]].state == TCG_TEMP_CONST) {
/* Proceed with possible constant folding. */
break;
--
1.7.12.1

View File

@ -0,0 +1,29 @@
From f08c59ce7dee67a95cf06d9588b4312e7d071788 Mon Sep 17 00:00:00 2001
From: Aurelien Jarno <aurelien@aurel32.net>
Date: Thu, 6 Sep 2012 16:47:14 +0200
Subject: [PATCH] tcg/optimize: simplify and r, a, 0 cases
and r, a, 0 is equivalent to a movi r, 0.
Reviewed-by: Richard Henderson <rth@twiddle.net>
Signed-off-by: Aurelien Jarno <aurelien@aurel32.net>
Signed-off-by: Michael Roth <mdroth@linux.vnet.ibm.com>
---
tcg/optimize.c | 1 +
1 file changed, 1 insertion(+)
diff --git a/tcg/optimize.c b/tcg/optimize.c
index 0db849e..c12cb2b 100644
--- a/tcg/optimize.c
+++ b/tcg/optimize.c
@@ -360,6 +360,7 @@ static TCGArg *tcg_constant_folding(TCGContext *s, uint16_t *tcg_opc_ptr,
/* Simplify expression for "op r, a, 0 => movi r, 0" cases */
switch (op) {
+ CASE_OP_32_64(and):
CASE_OP_32_64(mul):
if ((temps[args[2]].state == TCG_TEMP_CONST
&& temps[args[2]].val == 0)) {
--
1.7.12.1

View File

@ -0,0 +1,48 @@
From bbed332c7ad12e9885d3f457f366fa0b29445dcd Mon Sep 17 00:00:00 2001
From: Aurelien Jarno <aurelien@aurel32.net>
Date: Thu, 6 Sep 2012 16:47:14 +0200
Subject: [PATCH] tcg/optimize: simplify shift/rot r, 0, a => movi r, 0 cases
shift/rot r, 0, a is equivalent to movi r, 0.
Reviewed-by: Richard Henderson <rth@twiddle.net>
Signed-off-by: Aurelien Jarno <aurelien@aurel32.net>
Signed-off-by: Michael Roth <mdroth@linux.vnet.ibm.com>
---
tcg/optimize.c | 20 ++++++++++++++++++++
1 file changed, 20 insertions(+)
diff --git a/tcg/optimize.c b/tcg/optimize.c
index c12cb2b..1698ba3 100644
--- a/tcg/optimize.c
+++ b/tcg/optimize.c
@@ -322,6 +322,26 @@ static TCGArg *tcg_constant_folding(TCGContext *s, uint16_t *tcg_opc_ptr,
break;
}
+ /* Simplify expressions for "shift/rot r, 0, a => movi r, 0" */
+ switch (op) {
+ CASE_OP_32_64(shl):
+ CASE_OP_32_64(shr):
+ CASE_OP_32_64(sar):
+ CASE_OP_32_64(rotl):
+ CASE_OP_32_64(rotr):
+ if (temps[args[1]].state == TCG_TEMP_CONST
+ && temps[args[1]].val == 0) {
+ gen_opc_buf[op_index] = op_to_movi(op);
+ tcg_opt_gen_movi(gen_args, args[0], 0, nb_temps, nb_globals);
+ args += 3;
+ gen_args += 2;
+ continue;
+ }
+ break;
+ default:
+ break;
+ }
+
/* Simplify expression for "op r, a, 0 => mov r, a" cases */
switch (op) {
CASE_OP_32_64(add):
--
1.7.12.1

View File

@ -0,0 +1,49 @@
From 1127ad0d084f0cef11b5658b3dbbf8505d8d3af0 Mon Sep 17 00:00:00 2001
From: Aurelien Jarno <aurelien@aurel32.net>
Date: Thu, 6 Sep 2012 16:47:14 +0200
Subject: [PATCH] tcg/optimize: swap brcond/setcond arguments when possible
brcond and setcond ops are not commutative, but it's easy to compute the
new condition after swapping the arguments. Try to always put the constant
argument in second position like for commutative ops, to help backends to
generate better code.
Reviewed-by: Richard Henderson <rth@twiddle.net>
Signed-off-by: Aurelien Jarno <aurelien@aurel32.net>
Signed-off-by: Michael Roth <mdroth@linux.vnet.ibm.com>
---
tcg/optimize.c | 18 ++++++++++++++++++
1 file changed, 18 insertions(+)
diff --git a/tcg/optimize.c b/tcg/optimize.c
index 1698ba3..7debc8a 100644
--- a/tcg/optimize.c
+++ b/tcg/optimize.c
@@ -318,6 +318,24 @@ static TCGArg *tcg_constant_folding(TCGContext *s, uint16_t *tcg_opc_ptr,
args[2] = tmp;
}
break;
+ CASE_OP_32_64(brcond):
+ if (temps[args[0]].state == TCG_TEMP_CONST
+ && temps[args[1]].state != TCG_TEMP_CONST) {
+ tmp = args[0];
+ args[0] = args[1];
+ args[1] = tmp;
+ args[2] = tcg_swap_cond(args[2]);
+ }
+ break;
+ CASE_OP_32_64(setcond):
+ if (temps[args[1]].state == TCG_TEMP_CONST
+ && temps[args[2]].state != TCG_TEMP_CONST) {
+ tmp = args[1];
+ args[1] = args[2];
+ args[2] = tmp;
+ args[3] = tcg_swap_cond(args[3]);
+ }
+ break;
default:
break;
}
--
1.7.12.1

View File

@ -0,0 +1,114 @@
From 1bbb9ac3e775b55d0d5c57c209f47e742a9be810 Mon Sep 17 00:00:00 2001
From: Aurelien Jarno <aurelien@aurel32.net>
Date: Thu, 6 Sep 2012 16:47:14 +0200
Subject: [PATCH] tcg/optimize: add constant folding for setcond
Reviewed-by: Richard Henderson <rth@twiddle.net>
Signed-off-by: Aurelien Jarno <aurelien@aurel32.net>
Signed-off-by: Michael Roth <mdroth@linux.vnet.ibm.com>
---
tcg/optimize.c | 81 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
1 file changed, 81 insertions(+)
diff --git a/tcg/optimize.c b/tcg/optimize.c
index 7debc8a..1cb1f36 100644
--- a/tcg/optimize.c
+++ b/tcg/optimize.c
@@ -267,6 +267,67 @@ static TCGArg do_constant_folding(TCGOpcode op, TCGArg x, TCGArg y)
return res;
}
+static TCGArg do_constant_folding_cond(TCGOpcode op, TCGArg x,
+ TCGArg y, TCGCond c)
+{
+ switch (op_bits(op)) {
+ case 32:
+ switch (c) {
+ case TCG_COND_EQ:
+ return (uint32_t)x == (uint32_t)y;
+ case TCG_COND_NE:
+ return (uint32_t)x != (uint32_t)y;
+ case TCG_COND_LT:
+ return (int32_t)x < (int32_t)y;
+ case TCG_COND_GE:
+ return (int32_t)x >= (int32_t)y;
+ case TCG_COND_LE:
+ return (int32_t)x <= (int32_t)y;
+ case TCG_COND_GT:
+ return (int32_t)x > (int32_t)y;
+ case TCG_COND_LTU:
+ return (uint32_t)x < (uint32_t)y;
+ case TCG_COND_GEU:
+ return (uint32_t)x >= (uint32_t)y;
+ case TCG_COND_LEU:
+ return (uint32_t)x <= (uint32_t)y;
+ case TCG_COND_GTU:
+ return (uint32_t)x > (uint32_t)y;
+ }
+ break;
+ case 64:
+ switch (c) {
+ case TCG_COND_EQ:
+ return (uint64_t)x == (uint64_t)y;
+ case TCG_COND_NE:
+ return (uint64_t)x != (uint64_t)y;
+ case TCG_COND_LT:
+ return (int64_t)x < (int64_t)y;
+ case TCG_COND_GE:
+ return (int64_t)x >= (int64_t)y;
+ case TCG_COND_LE:
+ return (int64_t)x <= (int64_t)y;
+ case TCG_COND_GT:
+ return (int64_t)x > (int64_t)y;
+ case TCG_COND_LTU:
+ return (uint64_t)x < (uint64_t)y;
+ case TCG_COND_GEU:
+ return (uint64_t)x >= (uint64_t)y;
+ case TCG_COND_LEU:
+ return (uint64_t)x <= (uint64_t)y;
+ case TCG_COND_GTU:
+ return (uint64_t)x > (uint64_t)y;
+ }
+ break;
+ }
+
+ fprintf(stderr,
+ "Unrecognized bitness %d or condition %d in "
+ "do_constant_folding_cond.\n", op_bits(op), c);
+ tcg_abort();
+}
+
+
/* Propagate constants and copies, fold constant expressions. */
static TCGArg *tcg_constant_folding(TCGContext *s, uint16_t *tcg_opc_ptr,
TCGArg *args, TCGOpDef *tcg_op_defs)
@@ -522,6 +583,26 @@ static TCGArg *tcg_constant_folding(TCGContext *s, uint16_t *tcg_opc_ptr,
args += 3;
break;
}
+ CASE_OP_32_64(setcond):
+ if (temps[args[1]].state == TCG_TEMP_CONST
+ && temps[args[2]].state == TCG_TEMP_CONST) {
+ gen_opc_buf[op_index] = op_to_movi(op);
+ tmp = do_constant_folding_cond(op, temps[args[1]].val,
+ temps[args[2]].val, args[3]);
+ tcg_opt_gen_movi(gen_args, args[0], tmp, nb_temps, nb_globals);
+ gen_args += 2;
+ args += 4;
+ break;
+ } else {
+ reset_temp(args[0], nb_temps, nb_globals);
+ gen_args[0] = args[0];
+ gen_args[1] = args[1];
+ gen_args[2] = args[2];
+ gen_args[3] = args[3];
+ gen_args += 4;
+ args += 4;
+ break;
+ }
case INDEX_op_call:
nb_call_args = (args[0] >> 16) + (args[0] & 0xffff);
if (!(args[nb_call_args + 1] & (TCG_CALL_CONST | TCG_CALL_PURE))) {
--
1.7.12.1

View File

@ -0,0 +1,60 @@
From 98dc31743b94d5719c02c589e7cd652e95570b25 Mon Sep 17 00:00:00 2001
From: Aurelien Jarno <aurelien@aurel32.net>
Date: Thu, 6 Sep 2012 16:47:14 +0200
Subject: [PATCH] tcg/optimize: add constant folding for brcond
Reviewed-by: Richard Henderson <rth@twiddle.net>
Signed-off-by: Aurelien Jarno <aurelien@aurel32.net>
Signed-off-by: Michael Roth <mdroth@linux.vnet.ibm.com>
---
tcg/optimize.c | 27 ++++++++++++++++++++++++++-
1 file changed, 26 insertions(+), 1 deletion(-)
diff --git a/tcg/optimize.c b/tcg/optimize.c
index 1cb1f36..156e8d9 100644
--- a/tcg/optimize.c
+++ b/tcg/optimize.c
@@ -603,6 +603,32 @@ static TCGArg *tcg_constant_folding(TCGContext *s, uint16_t *tcg_opc_ptr,
args += 4;
break;
}
+ CASE_OP_32_64(brcond):
+ if (temps[args[0]].state == TCG_TEMP_CONST
+ && temps[args[1]].state == TCG_TEMP_CONST) {
+ if (do_constant_folding_cond(op, temps[args[0]].val,
+ temps[args[1]].val, args[2])) {
+ memset(temps, 0, nb_temps * sizeof(struct tcg_temp_info));
+ gen_opc_buf[op_index] = INDEX_op_br;
+ gen_args[0] = args[3];
+ gen_args += 1;
+ args += 4;
+ } else {
+ gen_opc_buf[op_index] = INDEX_op_nop;
+ args += 4;
+ }
+ break;
+ } else {
+ memset(temps, 0, nb_temps * sizeof(struct tcg_temp_info));
+ reset_temp(args[0], nb_temps, nb_globals);
+ gen_args[0] = args[0];
+ gen_args[1] = args[1];
+ gen_args[2] = args[2];
+ gen_args[3] = args[3];
+ gen_args += 4;
+ args += 4;
+ break;
+ }
case INDEX_op_call:
nb_call_args = (args[0] >> 16) + (args[0] & 0xffff);
if (!(args[nb_call_args + 1] & (TCG_CALL_CONST | TCG_CALL_PURE))) {
@@ -624,7 +650,6 @@ static TCGArg *tcg_constant_folding(TCGContext *s, uint16_t *tcg_opc_ptr,
case INDEX_op_set_label:
case INDEX_op_jmp:
case INDEX_op_br:
- CASE_OP_32_64(brcond):
memset(temps, 0, nb_temps * sizeof(struct tcg_temp_info));
for (i = 0; i < def->nb_args; i++) {
*gen_args = *args;
--
1.7.12.1

View File

@ -0,0 +1,144 @@
From b7dc881b44c3698a0a81d226d6012d3c5833fd29 Mon Sep 17 00:00:00 2001
From: Aurelien Jarno <aurelien@aurel32.net>
Date: Fri, 7 Sep 2012 12:24:32 +0200
Subject: [PATCH] tcg/optimize: fix if/else/break coding style
optimizer.c contains some cases were the break is appearing in both the
if and the else parts. Fix that by moving it to the outer part. Also
move some common code there.
Reviewed-by: Richard Henderson <rth@twiddle.net>
Signed-off-by: Aurelien Jarno <aurelien@aurel32.net>
Signed-off-by: Michael Roth <mdroth@linux.vnet.ibm.com>
---
tcg/optimize.c | 34 +++++++++++-----------------------
1 file changed, 11 insertions(+), 23 deletions(-)
diff --git a/tcg/optimize.c b/tcg/optimize.c
index 156e8d9..fba0ed9 100644
--- a/tcg/optimize.c
+++ b/tcg/optimize.c
@@ -441,15 +441,14 @@ static TCGArg *tcg_constant_folding(TCGContext *s, uint16_t *tcg_opc_ptr,
if ((temps[args[0]].state == TCG_TEMP_COPY
&& temps[args[0]].val == args[1])
|| args[0] == args[1]) {
- args += 3;
gen_opc_buf[op_index] = INDEX_op_nop;
} else {
gen_opc_buf[op_index] = op_to_mov(op);
tcg_opt_gen_mov(s, gen_args, args[0], args[1],
nb_temps, nb_globals);
gen_args += 2;
- args += 3;
}
+ args += 3;
continue;
}
break;
@@ -480,15 +479,14 @@ static TCGArg *tcg_constant_folding(TCGContext *s, uint16_t *tcg_opc_ptr,
CASE_OP_32_64(and):
if (args[1] == args[2]) {
if (args[1] == args[0]) {
- args += 3;
gen_opc_buf[op_index] = INDEX_op_nop;
} else {
gen_opc_buf[op_index] = op_to_mov(op);
tcg_opt_gen_mov(s, gen_args, args[0], args[1], nb_temps,
nb_globals);
gen_args += 2;
- args += 3;
}
+ args += 3;
continue;
}
break;
@@ -538,17 +536,14 @@ static TCGArg *tcg_constant_folding(TCGContext *s, uint16_t *tcg_opc_ptr,
gen_opc_buf[op_index] = op_to_movi(op);
tmp = do_constant_folding(op, temps[args[1]].val, 0);
tcg_opt_gen_movi(gen_args, args[0], tmp, nb_temps, nb_globals);
- gen_args += 2;
- args += 2;
- break;
} else {
reset_temp(args[0], nb_temps, nb_globals);
gen_args[0] = args[0];
gen_args[1] = args[1];
- gen_args += 2;
- args += 2;
- break;
}
+ gen_args += 2;
+ args += 2;
+ break;
CASE_OP_32_64(add):
CASE_OP_32_64(sub):
CASE_OP_32_64(mul):
@@ -572,17 +567,15 @@ static TCGArg *tcg_constant_folding(TCGContext *s, uint16_t *tcg_opc_ptr,
temps[args[2]].val);
tcg_opt_gen_movi(gen_args, args[0], tmp, nb_temps, nb_globals);
gen_args += 2;
- args += 3;
- break;
} else {
reset_temp(args[0], nb_temps, nb_globals);
gen_args[0] = args[0];
gen_args[1] = args[1];
gen_args[2] = args[2];
gen_args += 3;
- args += 3;
- break;
}
+ args += 3;
+ break;
CASE_OP_32_64(setcond):
if (temps[args[1]].state == TCG_TEMP_CONST
&& temps[args[2]].state == TCG_TEMP_CONST) {
@@ -591,8 +584,6 @@ static TCGArg *tcg_constant_folding(TCGContext *s, uint16_t *tcg_opc_ptr,
temps[args[2]].val, args[3]);
tcg_opt_gen_movi(gen_args, args[0], tmp, nb_temps, nb_globals);
gen_args += 2;
- args += 4;
- break;
} else {
reset_temp(args[0], nb_temps, nb_globals);
gen_args[0] = args[0];
@@ -600,9 +591,9 @@ static TCGArg *tcg_constant_folding(TCGContext *s, uint16_t *tcg_opc_ptr,
gen_args[2] = args[2];
gen_args[3] = args[3];
gen_args += 4;
- args += 4;
- break;
}
+ args += 4;
+ break;
CASE_OP_32_64(brcond):
if (temps[args[0]].state == TCG_TEMP_CONST
&& temps[args[1]].state == TCG_TEMP_CONST) {
@@ -612,12 +603,9 @@ static TCGArg *tcg_constant_folding(TCGContext *s, uint16_t *tcg_opc_ptr,
gen_opc_buf[op_index] = INDEX_op_br;
gen_args[0] = args[3];
gen_args += 1;
- args += 4;
} else {
gen_opc_buf[op_index] = INDEX_op_nop;
- args += 4;
}
- break;
} else {
memset(temps, 0, nb_temps * sizeof(struct tcg_temp_info));
reset_temp(args[0], nb_temps, nb_globals);
@@ -626,9 +614,9 @@ static TCGArg *tcg_constant_folding(TCGContext *s, uint16_t *tcg_opc_ptr,
gen_args[2] = args[2];
gen_args[3] = args[3];
gen_args += 4;
- args += 4;
- break;
}
+ args += 4;
+ break;
case INDEX_op_call:
nb_call_args = (args[0] >> 16) + (args[0] & 0xffff);
if (!(args[nb_call_args + 1] & (TCG_CALL_CONST | TCG_CALL_PURE))) {
--
1.7.12.1

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,282 @@
From 25e9a95d0571c40738daa479467d757eb477739e Mon Sep 17 00:00:00 2001
From: Blue Swirl <blauwirbel@gmail.com>
Date: Sun, 2 Sep 2012 06:57:17 +0000
Subject: [PATCH] target-lm32: switch to AREG0 free mode
Add an explicit CPUState parameter instead of relying on AREG0
and switch to AREG0 free mode.
Signed-off-by: Blue Swirl <blauwirbel@gmail.com>
Signed-off-by: Michael Roth <mdroth@linux.vnet.ibm.com>
---
configure | 2 +-
target-lm32/Makefile.objs | 2 --
target-lm32/helper.h | 20 ++++++++++----------
target-lm32/op_helper.c | 29 +++++++++++------------------
target-lm32/translate.c | 28 +++++++++++++---------------
5 files changed, 35 insertions(+), 46 deletions(-)
diff --git a/configure b/configure
index 3ad6f74..1e3ea7f 100755
--- a/configure
+++ b/configure
@@ -3839,7 +3839,7 @@ symlink "$source_path/Makefile.target" "$target_dir/Makefile"
case "$target_arch2" in
- alpha | i386 | or32 | s390x | sparc* | x86_64 | xtensa* | ppc*)
+ alpha | i386 | lm32 | or32 | s390x | sparc* | x86_64 | xtensa* | ppc*)
echo "CONFIG_TCG_PASS_AREG0=y" >> $config_target_mak
;;
esac
diff --git a/target-lm32/Makefile.objs b/target-lm32/Makefile.objs
index 2e0e093..ca20f21 100644
--- a/target-lm32/Makefile.objs
+++ b/target-lm32/Makefile.objs
@@ -1,4 +1,2 @@
obj-y += translate.o op_helper.o helper.o cpu.o
obj-$(CONFIG_SOFTMMU) += machine.o
-
-$(obj)/op_helper.o: QEMU_CFLAGS += $(HELPER_CFLAGS)
diff --git a/target-lm32/helper.h b/target-lm32/helper.h
index 9d335ef..07f5670 100644
--- a/target-lm32/helper.h
+++ b/target-lm32/helper.h
@@ -1,14 +1,14 @@
#include "def-helper.h"
-DEF_HELPER_1(raise_exception, void, i32)
-DEF_HELPER_0(hlt, void)
-DEF_HELPER_1(wcsr_im, void, i32)
-DEF_HELPER_1(wcsr_ip, void, i32)
-DEF_HELPER_1(wcsr_jtx, void, i32)
-DEF_HELPER_1(wcsr_jrx, void, i32)
-DEF_HELPER_0(rcsr_im, i32)
-DEF_HELPER_0(rcsr_ip, i32)
-DEF_HELPER_0(rcsr_jtx, i32)
-DEF_HELPER_0(rcsr_jrx, i32)
+DEF_HELPER_2(raise_exception, void, env, i32)
+DEF_HELPER_1(hlt, void, env)
+DEF_HELPER_2(wcsr_im, void, env, i32)
+DEF_HELPER_2(wcsr_ip, void, env, i32)
+DEF_HELPER_2(wcsr_jtx, void, env, i32)
+DEF_HELPER_2(wcsr_jrx, void, env, i32)
+DEF_HELPER_1(rcsr_im, i32, env)
+DEF_HELPER_1(rcsr_ip, i32, env)
+DEF_HELPER_1(rcsr_jtx, i32, env)
+DEF_HELPER_1(rcsr_jrx, i32, env)
#include "def-helper.h"
diff --git a/target-lm32/op_helper.c b/target-lm32/op_helper.c
index 51edc1a..7b91d8c 100644
--- a/target-lm32/op_helper.c
+++ b/target-lm32/op_helper.c
@@ -1,6 +1,5 @@
#include <assert.h>
#include "cpu.h"
-#include "dyngen-exec.h"
#include "helper.h"
#include "host-utils.h"
@@ -18,55 +17,55 @@
#define SHIFT 3
#include "softmmu_template.h"
-void helper_raise_exception(uint32_t index)
+void helper_raise_exception(CPULM32State *env, uint32_t index)
{
env->exception_index = index;
cpu_loop_exit(env);
}
-void helper_hlt(void)
+void helper_hlt(CPULM32State *env)
{
env->halted = 1;
env->exception_index = EXCP_HLT;
cpu_loop_exit(env);
}
-void helper_wcsr_im(uint32_t im)
+void helper_wcsr_im(CPULM32State *env, uint32_t im)
{
lm32_pic_set_im(env->pic_state, im);
}
-void helper_wcsr_ip(uint32_t im)
+void helper_wcsr_ip(CPULM32State *env, uint32_t im)
{
lm32_pic_set_ip(env->pic_state, im);
}
-void helper_wcsr_jtx(uint32_t jtx)
+void helper_wcsr_jtx(CPULM32State *env, uint32_t jtx)
{
lm32_juart_set_jtx(env->juart_state, jtx);
}
-void helper_wcsr_jrx(uint32_t jrx)
+void helper_wcsr_jrx(CPULM32State *env, uint32_t jrx)
{
lm32_juart_set_jrx(env->juart_state, jrx);
}
-uint32_t helper_rcsr_im(void)
+uint32_t helper_rcsr_im(CPULM32State *env)
{
return lm32_pic_get_im(env->pic_state);
}
-uint32_t helper_rcsr_ip(void)
+uint32_t helper_rcsr_ip(CPULM32State *env)
{
return lm32_pic_get_ip(env->pic_state);
}
-uint32_t helper_rcsr_jtx(void)
+uint32_t helper_rcsr_jtx(CPULM32State *env)
{
return lm32_juart_get_jtx(env->juart_state);
}
-uint32_t helper_rcsr_jrx(void)
+uint32_t helper_rcsr_jrx(CPULM32State *env)
{
return lm32_juart_get_jrx(env->juart_state);
}
@@ -74,17 +73,12 @@ uint32_t helper_rcsr_jrx(void)
/* Try to fill the TLB and return an exception if error. If retaddr is
NULL, it means that the function was called in C code (i.e. not
from generated code or from helper.c) */
-/* XXX: fix it to restore all registers */
-void tlb_fill(CPULM32State *env1, target_ulong addr, int is_write, int mmu_idx,
+void tlb_fill(CPULM32State *env, target_ulong addr, int is_write, int mmu_idx,
uintptr_t retaddr)
{
TranslationBlock *tb;
- CPULM32State *saved_env;
int ret;
- saved_env = env;
- env = env1;
-
ret = cpu_lm32_handle_mmu_fault(env, addr, is_write, mmu_idx);
if (unlikely(ret)) {
if (retaddr) {
@@ -98,7 +92,6 @@ void tlb_fill(CPULM32State *env1, target_ulong addr, int is_write, int mmu_idx,
}
cpu_loop_exit(env);
}
- env = saved_env;
}
#endif
diff --git a/target-lm32/translate.c b/target-lm32/translate.c
index 872a2ba..5f6dcba 100644
--- a/target-lm32/translate.c
+++ b/target-lm32/translate.c
@@ -116,7 +116,7 @@ static inline void t_gen_raise_exception(DisasContext *dc, uint32_t index)
{
TCGv_i32 tmp = tcg_const_i32(index);
- gen_helper_raise_exception(tmp);
+ gen_helper_raise_exception(cpu_env, tmp);
tcg_temp_free_i32(tmp);
}
@@ -179,7 +179,7 @@ static void dec_and(DisasContext *dc)
} else {
if (dc->r0 == 0 && dc->r1 == 0 && dc->r2 == 0) {
tcg_gen_movi_tl(cpu_pc, dc->pc + 4);
- gen_helper_hlt();
+ gen_helper_hlt(cpu_env);
} else {
tcg_gen_and_tl(cpu_R[dc->r2], cpu_R[dc->r0], cpu_R[dc->r1]);
}
@@ -601,10 +601,10 @@ static void dec_rcsr(DisasContext *dc)
tcg_gen_mov_tl(cpu_R[dc->r2], cpu_ie);
break;
case CSR_IM:
- gen_helper_rcsr_im(cpu_R[dc->r2]);
+ gen_helper_rcsr_im(cpu_R[dc->r2], cpu_env);
break;
case CSR_IP:
- gen_helper_rcsr_ip(cpu_R[dc->r2]);
+ gen_helper_rcsr_ip(cpu_R[dc->r2], cpu_env);
break;
case CSR_CC:
tcg_gen_mov_tl(cpu_R[dc->r2], cpu_cc);
@@ -622,10 +622,10 @@ static void dec_rcsr(DisasContext *dc)
tcg_gen_mov_tl(cpu_R[dc->r2], cpu_deba);
break;
case CSR_JTX:
- gen_helper_rcsr_jtx(cpu_R[dc->r2]);
+ gen_helper_rcsr_jtx(cpu_R[dc->r2], cpu_env);
break;
case CSR_JRX:
- gen_helper_rcsr_jrx(cpu_R[dc->r2]);
+ gen_helper_rcsr_jrx(cpu_R[dc->r2], cpu_env);
break;
case CSR_ICC:
case CSR_DCC:
@@ -812,7 +812,7 @@ static void dec_wcsr(DisasContext *dc)
if (use_icount) {
gen_io_start();
}
- gen_helper_wcsr_im(cpu_R[dc->r1]);
+ gen_helper_wcsr_im(cpu_env, cpu_R[dc->r1]);
tcg_gen_movi_tl(cpu_pc, dc->pc + 4);
if (use_icount) {
gen_io_end();
@@ -824,7 +824,7 @@ static void dec_wcsr(DisasContext *dc)
if (use_icount) {
gen_io_start();
}
- gen_helper_wcsr_ip(cpu_R[dc->r1]);
+ gen_helper_wcsr_ip(cpu_env, cpu_R[dc->r1]);
tcg_gen_movi_tl(cpu_pc, dc->pc + 4);
if (use_icount) {
gen_io_end();
@@ -844,10 +844,10 @@ static void dec_wcsr(DisasContext *dc)
tcg_gen_mov_tl(cpu_deba, cpu_R[dc->r1]);
break;
case CSR_JTX:
- gen_helper_wcsr_jtx(cpu_R[dc->r1]);
+ gen_helper_wcsr_jtx(cpu_env, cpu_R[dc->r1]);
break;
case CSR_JRX:
- gen_helper_wcsr_jrx(cpu_R[dc->r1]);
+ gen_helper_wcsr_jrx(cpu_env, cpu_R[dc->r1]);
break;
case CSR_DC:
tcg_gen_mov_tl(cpu_dc, cpu_R[dc->r1]);
@@ -940,15 +940,13 @@ static const DecoderInfo decinfo[] = {
dec_cmpne
};
-static inline void decode(DisasContext *dc)
+static inline void decode(DisasContext *dc, uint32_t ir)
{
- uint32_t ir;
-
if (unlikely(qemu_loglevel_mask(CPU_LOG_TB_OP))) {
tcg_gen_debug_insn_start(dc->pc);
}
- dc->ir = ir = ldl_code(dc->pc);
+ dc->ir = ir;
LOG_DIS("%8.8x\t", dc->ir);
/* try guessing 'empty' instruction memory, although it may be a valid
@@ -1068,7 +1066,7 @@ static void gen_intermediate_code_internal(CPULM32State *env,
gen_io_start();
}
- decode(dc);
+ decode(dc, cpu_ldl_code(env, dc->pc));
dc->pc += 4;
num_insns++;
--
1.7.12.1

View File

@ -0,0 +1,502 @@
From 2ace9fd11db103aecebf451aff3bc23838248667 Mon Sep 17 00:00:00 2001
From: Blue Swirl <blauwirbel@gmail.com>
Date: Sun, 2 Sep 2012 07:27:38 +0000
Subject: [PATCH] target-m68k: switch to AREG0 free mode
Add an explicit CPUState parameter instead of relying on AREG0
and switch to AREG0 free mode.
Signed-off-by: Blue Swirl <blauwirbel@gmail.com>
Signed-off-by: Michael Roth <mdroth@linux.vnet.ibm.com>
---
configure | 2 +-
target-m68k/Makefile.objs | 2 --
target-m68k/helpers.h | 2 +-
target-m68k/op_helper.c | 68 +++++++++++++++++-------------------------
target-m68k/translate.c | 76 ++++++++++++++++++++++++-----------------------
5 files changed, 68 insertions(+), 82 deletions(-)
diff --git a/configure b/configure
index 1e3ea7f..af03942 100755
--- a/configure
+++ b/configure
@@ -3839,7 +3839,7 @@ symlink "$source_path/Makefile.target" "$target_dir/Makefile"
case "$target_arch2" in
- alpha | i386 | lm32 | or32 | s390x | sparc* | x86_64 | xtensa* | ppc*)
+ alpha | i386 | lm32 | m68k | or32 | s390x | sparc* | x86_64 | xtensa* | ppc*)
echo "CONFIG_TCG_PASS_AREG0=y" >> $config_target_mak
;;
esac
diff --git a/target-m68k/Makefile.objs b/target-m68k/Makefile.objs
index cda6015..7eccfab 100644
--- a/target-m68k/Makefile.objs
+++ b/target-m68k/Makefile.objs
@@ -1,5 +1,3 @@
obj-y += m68k-semi.o
obj-y += translate.o op_helper.o helper.o cpu.o
obj-$(CONFIG_SOFTMMU) += machine.o
-
-$(obj)/op_helper.o: QEMU_CFLAGS += $(HELPER_CFLAGS)
diff --git a/target-m68k/helpers.h b/target-m68k/helpers.h
index cb8a0c7..8112b44 100644
--- a/target-m68k/helpers.h
+++ b/target-m68k/helpers.h
@@ -49,6 +49,6 @@ DEF_HELPER_3(set_mac_exts, void, env, i32, i32)
DEF_HELPER_3(set_mac_extu, void, env, i32, i32)
DEF_HELPER_2(flush_flags, void, env, i32)
-DEF_HELPER_1(raise_exception, void, i32)
+DEF_HELPER_2(raise_exception, void, env, i32)
#include "def-helper.h"
diff --git a/target-m68k/op_helper.c b/target-m68k/op_helper.c
index 1971a57..3116287 100644
--- a/target-m68k/op_helper.c
+++ b/target-m68k/op_helper.c
@@ -17,17 +17,16 @@
* License along with this library; if not, see <http://www.gnu.org/licenses/>.
*/
#include "cpu.h"
-#include "dyngen-exec.h"
#include "helpers.h"
#if defined(CONFIG_USER_ONLY)
-void do_interrupt(CPUM68KState *env1)
+void do_interrupt(CPUM68KState *env)
{
- env1->exception_index = -1;
+ env->exception_index = -1;
}
-void do_interrupt_m68k_hardirq(CPUM68KState *env1)
+void do_interrupt_m68k_hardirq(CPUM68KState *env)
{
}
@@ -54,16 +53,12 @@ extern int semihosting_enabled;
/* Try to fill the TLB and return an exception if error. If retaddr is
NULL, it means that the function was called in C code (i.e. not
from generated code or from helper.c) */
-/* XXX: fix it to restore all registers */
-void tlb_fill(CPUM68KState *env1, target_ulong addr, int is_write, int mmu_idx,
+void tlb_fill(CPUM68KState *env, target_ulong addr, int is_write, int mmu_idx,
uintptr_t retaddr)
{
TranslationBlock *tb;
- CPUM68KState *saved_env;
int ret;
- saved_env = env;
- env = env1;
ret = cpu_m68k_handle_mmu_fault(env, addr, is_write, mmu_idx);
if (unlikely(ret)) {
if (retaddr) {
@@ -77,24 +72,23 @@ void tlb_fill(CPUM68KState *env1, target_ulong addr, int is_write, int mmu_idx,
}
cpu_loop_exit(env);
}
- env = saved_env;
}
-static void do_rte(void)
+static void do_rte(CPUM68KState *env)
{
uint32_t sp;
uint32_t fmt;
sp = env->aregs[7];
- fmt = ldl_kernel(sp);
- env->pc = ldl_kernel(sp + 4);
+ fmt = cpu_ldl_kernel(env, sp);
+ env->pc = cpu_ldl_kernel(env, sp + 4);
sp |= (fmt >> 28) & 3;
env->sr = fmt & 0xffff;
m68k_switch_sp(env);
env->aregs[7] = sp + 8;
}
-static void do_interrupt_all(int is_hw)
+static void do_interrupt_all(CPUM68KState *env, int is_hw)
{
uint32_t sp;
uint32_t fmt;
@@ -108,14 +102,14 @@ static void do_interrupt_all(int is_hw)
switch (env->exception_index) {
case EXCP_RTE:
/* Return from an exception. */
- do_rte();
+ do_rte(env);
return;
case EXCP_HALT_INSN:
if (semihosting_enabled
&& (env->sr & SR_S) != 0
&& (env->pc & 3) == 0
- && lduw_code(env->pc - 4) == 0x4e71
- && ldl_code(env->pc) == 0x4e7bf000) {
+ && cpu_lduw_code(env, env->pc - 4) == 0x4e71
+ && cpu_ldl_code(env, env->pc) == 0x4e7bf000) {
env->pc += 4;
do_m68k_semihosting(env, env->dregs[0]);
return;
@@ -151,44 +145,34 @@ static void do_interrupt_all(int is_hw)
/* ??? This could cause MMU faults. */
sp &= ~3;
sp -= 4;
- stl_kernel(sp, retaddr);
+ cpu_stl_kernel(env, sp, retaddr);
sp -= 4;
- stl_kernel(sp, fmt);
+ cpu_stl_kernel(env, sp, fmt);
env->aregs[7] = sp;
/* Jump to vector. */
- env->pc = ldl_kernel(env->vbr + vector);
+ env->pc = cpu_ldl_kernel(env, env->vbr + vector);
}
-void do_interrupt(CPUM68KState *env1)
+void do_interrupt(CPUM68KState *env)
{
- CPUM68KState *saved_env;
-
- saved_env = env;
- env = env1;
- do_interrupt_all(0);
- env = saved_env;
+ do_interrupt_all(env, 0);
}
-void do_interrupt_m68k_hardirq(CPUM68KState *env1)
+void do_interrupt_m68k_hardirq(CPUM68KState *env)
{
- CPUM68KState *saved_env;
-
- saved_env = env;
- env = env1;
- do_interrupt_all(1);
- env = saved_env;
+ do_interrupt_all(env, 1);
}
#endif
-static void raise_exception(int tt)
+static void raise_exception(CPUM68KState *env, int tt)
{
env->exception_index = tt;
cpu_loop_exit(env);
}
-void HELPER(raise_exception)(uint32_t tt)
+void HELPER(raise_exception)(CPUM68KState *env, uint32_t tt)
{
- raise_exception(tt);
+ raise_exception(env, tt);
}
void HELPER(divu)(CPUM68KState *env, uint32_t word)
@@ -202,8 +186,9 @@ void HELPER(divu)(CPUM68KState *env, uint32_t word)
num = env->div1;
den = env->div2;
/* ??? This needs to make sure the throwing location is accurate. */
- if (den == 0)
- raise_exception(EXCP_DIV0);
+ if (den == 0) {
+ raise_exception(env, EXCP_DIV0);
+ }
quot = num / den;
rem = num % den;
flags = 0;
@@ -231,8 +216,9 @@ void HELPER(divs)(CPUM68KState *env, uint32_t word)
num = env->div1;
den = env->div2;
- if (den == 0)
- raise_exception(EXCP_DIV0);
+ if (den == 0) {
+ raise_exception(env, EXCP_DIV0);
+ }
quot = num / den;
rem = num % den;
flags = 0;
diff --git a/target-m68k/translate.c b/target-m68k/translate.c
index 9fc1e31..10bb303 100644
--- a/target-m68k/translate.c
+++ b/target-m68k/translate.c
@@ -260,9 +260,9 @@ static TCGv gen_ldst(DisasContext *s, int opsize, TCGv addr, TCGv val,
static inline uint32_t read_im32(DisasContext *s)
{
uint32_t im;
- im = ((uint32_t)lduw_code(s->pc)) << 16;
+ im = ((uint32_t)cpu_lduw_code(cpu_single_env, s->pc)) << 16;
s->pc += 2;
- im |= lduw_code(s->pc);
+ im |= cpu_lduw_code(cpu_single_env, s->pc);
s->pc += 2;
return im;
}
@@ -297,7 +297,7 @@ static TCGv gen_lea_indexed(DisasContext *s, int opsize, TCGv base)
uint32_t bd, od;
offset = s->pc;
- ext = lduw_code(s->pc);
+ ext = cpu_lduw_code(cpu_single_env, s->pc);
s->pc += 2;
if ((ext & 0x800) == 0 && !m68k_feature(s->env, M68K_FEATURE_WORD_INDEX))
@@ -311,7 +311,7 @@ static TCGv gen_lea_indexed(DisasContext *s, int opsize, TCGv base)
if ((ext & 0x30) > 0x10) {
/* base displacement */
if ((ext & 0x30) == 0x20) {
- bd = (int16_t)lduw_code(s->pc);
+ bd = (int16_t)cpu_lduw_code(cpu_single_env, s->pc);
s->pc += 2;
} else {
bd = read_im32(s);
@@ -360,7 +360,7 @@ static TCGv gen_lea_indexed(DisasContext *s, int opsize, TCGv base)
if ((ext & 3) > 1) {
/* outer displacement */
if ((ext & 3) == 2) {
- od = (int16_t)lduw_code(s->pc);
+ od = (int16_t)cpu_lduw_code(cpu_single_env, s->pc);
s->pc += 2;
} else {
od = read_im32(s);
@@ -514,7 +514,7 @@ static TCGv gen_lea(DisasContext *s, uint16_t insn, int opsize)
case 5: /* Indirect displacement. */
reg = AREG(insn, 0);
tmp = tcg_temp_new();
- ext = lduw_code(s->pc);
+ ext = cpu_lduw_code(cpu_single_env, s->pc);
s->pc += 2;
tcg_gen_addi_i32(tmp, reg, (int16_t)ext);
return tmp;
@@ -524,7 +524,7 @@ static TCGv gen_lea(DisasContext *s, uint16_t insn, int opsize)
case 7: /* Other */
switch (insn & 7) {
case 0: /* Absolute short. */
- offset = ldsw_code(s->pc);
+ offset = cpu_ldsw_code(cpu_single_env, s->pc);
s->pc += 2;
return tcg_const_i32(offset);
case 1: /* Absolute long. */
@@ -532,7 +532,7 @@ static TCGv gen_lea(DisasContext *s, uint16_t insn, int opsize)
return tcg_const_i32(offset);
case 2: /* pc displacement */
offset = s->pc;
- offset += ldsw_code(s->pc);
+ offset += cpu_ldsw_code(cpu_single_env, s->pc);
s->pc += 2;
return tcg_const_i32(offset);
case 3: /* pc index+displacement. */
@@ -638,17 +638,19 @@ static TCGv gen_ea(DisasContext *s, uint16_t insn, int opsize, TCGv val,
/* Sign extend values for consistency. */
switch (opsize) {
case OS_BYTE:
- if (what == EA_LOADS)
- offset = ldsb_code(s->pc + 1);
- else
- offset = ldub_code(s->pc + 1);
+ if (what == EA_LOADS) {
+ offset = cpu_ldsb_code(cpu_single_env, s->pc + 1);
+ } else {
+ offset = cpu_ldub_code(cpu_single_env, s->pc + 1);
+ }
s->pc += 2;
break;
case OS_WORD:
- if (what == EA_LOADS)
- offset = ldsw_code(s->pc);
- else
- offset = lduw_code(s->pc);
+ if (what == EA_LOADS) {
+ offset = cpu_ldsw_code(cpu_single_env, s->pc);
+ } else {
+ offset = cpu_lduw_code(cpu_single_env, s->pc);
+ }
s->pc += 2;
break;
case OS_LONG:
@@ -815,7 +817,7 @@ static void gen_exception(DisasContext *s, uint32_t where, int nr)
{
gen_flush_cc_op(s);
gen_jmp_im(s, where);
- gen_helper_raise_exception(tcg_const_i32(nr));
+ gen_helper_raise_exception(cpu_env, tcg_const_i32(nr));
}
static inline void gen_addr_fault(DisasContext *s)
@@ -934,7 +936,7 @@ DISAS_INSN(divl)
TCGv reg;
uint16_t ext;
- ext = lduw_code(s->pc);
+ ext = cpu_lduw_code(cpu_single_env, s->pc);
s->pc += 2;
if (ext & 0x87f8) {
gen_exception(s, s->pc - 4, EXCP_UNSUPPORTED);
@@ -1086,7 +1088,7 @@ DISAS_INSN(movem)
TCGv tmp;
int is_load;
- mask = lduw_code(s->pc);
+ mask = cpu_lduw_code(cpu_single_env, s->pc);
s->pc += 2;
tmp = gen_lea(s, insn, OS_LONG);
if (IS_NULL_QREG(tmp)) {
@@ -1130,7 +1132,7 @@ DISAS_INSN(bitop_im)
opsize = OS_LONG;
op = (insn >> 6) & 3;
- bitnum = lduw_code(s->pc);
+ bitnum = cpu_lduw_code(cpu_single_env, s->pc);
s->pc += 2;
if (bitnum & 0xff00) {
disas_undef(s, insn);
@@ -1383,7 +1385,7 @@ static void gen_set_sr(DisasContext *s, uint16_t insn, int ccr_only)
else if ((insn & 0x3f) == 0x3c)
{
uint16_t val;
- val = lduw_code(s->pc);
+ val = cpu_lduw_code(cpu_single_env, s->pc);
s->pc += 2;
gen_set_sr_im(s, val, ccr_only);
}
@@ -1507,7 +1509,7 @@ DISAS_INSN(mull)
/* The upper 32 bits of the product are discarded, so
muls.l and mulu.l are functionally equivalent. */
- ext = lduw_code(s->pc);
+ ext = cpu_lduw_code(cpu_single_env, s->pc);
s->pc += 2;
if (ext & 0x87ff) {
gen_exception(s, s->pc - 4, EXCP_UNSUPPORTED);
@@ -1528,7 +1530,7 @@ DISAS_INSN(link)
TCGv reg;
TCGv tmp;
- offset = ldsw_code(s->pc);
+ offset = cpu_ldsw_code(cpu_single_env, s->pc);
s->pc += 2;
reg = AREG(insn, 0);
tmp = tcg_temp_new();
@@ -1649,7 +1651,7 @@ DISAS_INSN(branch)
op = (insn >> 8) & 0xf;
offset = (int8_t)insn;
if (offset == 0) {
- offset = ldsw_code(s->pc);
+ offset = cpu_ldsw_code(cpu_single_env, s->pc);
s->pc += 2;
} else if (offset == -1) {
offset = read_im32(s);
@@ -1934,13 +1936,13 @@ DISAS_INSN(strldsr)
uint32_t addr;
addr = s->pc - 2;
- ext = lduw_code(s->pc);
+ ext = cpu_lduw_code(cpu_single_env, s->pc);
s->pc += 2;
if (ext != 0x46FC) {
gen_exception(s, addr, EXCP_UNSUPPORTED);
return;
}
- ext = lduw_code(s->pc);
+ ext = cpu_lduw_code(cpu_single_env, s->pc);
s->pc += 2;
if (IS_USER(s) || (ext & SR_S) == 0) {
gen_exception(s, addr, EXCP_PRIVILEGE);
@@ -2008,7 +2010,7 @@ DISAS_INSN(stop)
return;
}
- ext = lduw_code(s->pc);
+ ext = cpu_lduw_code(cpu_single_env, s->pc);
s->pc += 2;
gen_set_sr_im(s, ext, 0);
@@ -2035,7 +2037,7 @@ DISAS_INSN(movec)
return;
}
- ext = lduw_code(s->pc);
+ ext = cpu_lduw_code(cpu_single_env, s->pc);
s->pc += 2;
if (ext & 0x8000) {
@@ -2100,7 +2102,7 @@ DISAS_INSN(fpu)
int set_dest;
int opsize;
- ext = lduw_code(s->pc);
+ ext = cpu_lduw_code(cpu_single_env, s->pc);
s->pc += 2;
opmode = ext & 0x7f;
switch ((ext >> 13) & 7) {
@@ -2136,7 +2138,7 @@ DISAS_INSN(fpu)
tcg_gen_addi_i32(tmp32, tmp32, -8);
break;
case 5:
- offset = ldsw_code(s->pc);
+ offset = cpu_ldsw_code(cpu_single_env, s->pc);
s->pc += 2;
tcg_gen_addi_i32(tmp32, tmp32, offset);
break;
@@ -2250,12 +2252,12 @@ DISAS_INSN(fpu)
tcg_gen_addi_i32(tmp32, tmp32, -8);
break;
case 5:
- offset = ldsw_code(s->pc);
+ offset = cpu_ldsw_code(cpu_single_env, s->pc);
s->pc += 2;
tcg_gen_addi_i32(tmp32, tmp32, offset);
break;
case 7:
- offset = ldsw_code(s->pc);
+ offset = cpu_ldsw_code(cpu_single_env, s->pc);
offset += s->pc - 2;
s->pc += 2;
tcg_gen_addi_i32(tmp32, tmp32, offset);
@@ -2381,10 +2383,10 @@ DISAS_INSN(fbcc)
int l1;
addr = s->pc;
- offset = ldsw_code(s->pc);
+ offset = cpu_ldsw_code(cpu_single_env, s->pc);
s->pc += 2;
if (insn & (1 << 6)) {
- offset = (offset << 16) | lduw_code(s->pc);
+ offset = (offset << 16) | cpu_lduw_code(cpu_single_env, s->pc);
s->pc += 2;
}
@@ -2506,7 +2508,7 @@ DISAS_INSN(mac)
s->done_mac = 1;
}
- ext = lduw_code(s->pc);
+ ext = cpu_lduw_code(cpu_single_env, s->pc);
s->pc += 2;
acc = ((insn >> 7) & 1) | ((ext >> 3) & 2);
@@ -2941,7 +2943,7 @@ static void disas_m68k_insn(CPUM68KState * env, DisasContext *s)
{
uint16_t insn;
- insn = lduw_code(s->pc);
+ insn = cpu_lduw_code(cpu_single_env, s->pc);
s->pc += 2;
opcode_table[insn](s, insn);
@@ -3028,7 +3030,7 @@ gen_intermediate_code_internal(CPUM68KState *env, TranslationBlock *tb,
gen_flush_cc_op(dc);
tcg_gen_movi_i32(QREG_PC, dc->pc);
}
- gen_helper_raise_exception(tcg_const_i32(EXCP_DEBUG));
+ gen_helper_raise_exception(cpu_env, tcg_const_i32(EXCP_DEBUG));
} else {
switch(dc->is_jmp) {
case DISAS_NEXT:
--
1.7.12.1

View File

@ -0,0 +1,901 @@
From 5560cd783146734a60c446f43227044cbb580edd Mon Sep 17 00:00:00 2001
From: Blue Swirl <blauwirbel@gmail.com>
Date: Sat, 8 Sep 2012 10:48:20 +0000
Subject: [PATCH] target-m68k: avoid using cpu_single_env
Pass around CPUState instead of using global cpu_single_env.
Signed-off-by: Blue Swirl <blauwirbel@gmail.com>
Signed-off-by: Michael Roth <mdroth@linux.vnet.ibm.com>
---
target-m68k/translate.c | 270 +++++++++++++++++++++++++-----------------------
1 file changed, 140 insertions(+), 130 deletions(-)
diff --git a/target-m68k/translate.c b/target-m68k/translate.c
index 10bb303..fb707f2 100644
--- a/target-m68k/translate.c
+++ b/target-m68k/translate.c
@@ -150,18 +150,24 @@ static void *gen_throws_exception;
#define OS_SINGLE 4
#define OS_DOUBLE 5
-typedef void (*disas_proc)(DisasContext *, uint16_t);
+typedef void (*disas_proc)(CPUM68KState *env, DisasContext *s, uint16_t insn);
#ifdef DEBUG_DISPATCH
-#define DISAS_INSN(name) \
- static void real_disas_##name (DisasContext *s, uint16_t insn); \
- static void disas_##name (DisasContext *s, uint16_t insn) { \
- qemu_log("Dispatch " #name "\n"); \
- real_disas_##name(s, insn); } \
- static void real_disas_##name (DisasContext *s, uint16_t insn)
+#define DISAS_INSN(name) \
+ static void real_disas_##name(CPUM68KState *env, DisasContext *s, \
+ uint16_t insn); \
+ static void disas_##name(CPUM68KState *env, DisasContext *s, \
+ uint16_t insn) \
+ { \
+ qemu_log("Dispatch " #name "\n"); \
+ real_disas_##name(s, env, insn); \
+ } \
+ static void real_disas_##name(CPUM68KState *env, DisasContext *s, \
+ uint16_t insn)
#else
-#define DISAS_INSN(name) \
- static void disas_##name (DisasContext *s, uint16_t insn)
+#define DISAS_INSN(name) \
+ static void disas_##name(CPUM68KState *env, DisasContext *s, \
+ uint16_t insn)
#endif
/* Generate a load from the specified address. Narrow values are
@@ -257,12 +263,12 @@ static TCGv gen_ldst(DisasContext *s, int opsize, TCGv addr, TCGv val,
}
/* Read a 32-bit immediate constant. */
-static inline uint32_t read_im32(DisasContext *s)
+static inline uint32_t read_im32(CPUM68KState *env, DisasContext *s)
{
uint32_t im;
- im = ((uint32_t)cpu_lduw_code(cpu_single_env, s->pc)) << 16;
+ im = ((uint32_t)cpu_lduw_code(env, s->pc)) << 16;
s->pc += 2;
- im |= cpu_lduw_code(cpu_single_env, s->pc);
+ im |= cpu_lduw_code(env, s->pc);
s->pc += 2;
return im;
}
@@ -288,7 +294,8 @@ static TCGv gen_addr_index(uint16_t ext, TCGv tmp)
/* Handle a base + index + displacement effective addresss.
A NULL_QREG base means pc-relative. */
-static TCGv gen_lea_indexed(DisasContext *s, int opsize, TCGv base)
+static TCGv gen_lea_indexed(CPUM68KState *env, DisasContext *s, int opsize,
+ TCGv base)
{
uint32_t offset;
uint16_t ext;
@@ -297,7 +304,7 @@ static TCGv gen_lea_indexed(DisasContext *s, int opsize, TCGv base)
uint32_t bd, od;
offset = s->pc;
- ext = cpu_lduw_code(cpu_single_env, s->pc);
+ ext = cpu_lduw_code(env, s->pc);
s->pc += 2;
if ((ext & 0x800) == 0 && !m68k_feature(s->env, M68K_FEATURE_WORD_INDEX))
@@ -311,10 +318,10 @@ static TCGv gen_lea_indexed(DisasContext *s, int opsize, TCGv base)
if ((ext & 0x30) > 0x10) {
/* base displacement */
if ((ext & 0x30) == 0x20) {
- bd = (int16_t)cpu_lduw_code(cpu_single_env, s->pc);
+ bd = (int16_t)cpu_lduw_code(env, s->pc);
s->pc += 2;
} else {
- bd = read_im32(s);
+ bd = read_im32(env, s);
}
} else {
bd = 0;
@@ -360,10 +367,10 @@ static TCGv gen_lea_indexed(DisasContext *s, int opsize, TCGv base)
if ((ext & 3) > 1) {
/* outer displacement */
if ((ext & 3) == 2) {
- od = (int16_t)cpu_lduw_code(cpu_single_env, s->pc);
+ od = (int16_t)cpu_lduw_code(env, s->pc);
s->pc += 2;
} else {
- od = read_im32(s);
+ od = read_im32(env, s);
}
} else {
od = 0;
@@ -492,7 +499,8 @@ static inline TCGv gen_extend(TCGv val, int opsize, int sign)
/* Generate code for an "effective address". Does not adjust the base
register for autoincrement addressing modes. */
-static TCGv gen_lea(DisasContext *s, uint16_t insn, int opsize)
+static TCGv gen_lea(CPUM68KState *env, DisasContext *s, uint16_t insn,
+ int opsize)
{
TCGv reg;
TCGv tmp;
@@ -514,29 +522,29 @@ static TCGv gen_lea(DisasContext *s, uint16_t insn, int opsize)
case 5: /* Indirect displacement. */
reg = AREG(insn, 0);
tmp = tcg_temp_new();
- ext = cpu_lduw_code(cpu_single_env, s->pc);
+ ext = cpu_lduw_code(env, s->pc);
s->pc += 2;
tcg_gen_addi_i32(tmp, reg, (int16_t)ext);
return tmp;
case 6: /* Indirect index + displacement. */
reg = AREG(insn, 0);
- return gen_lea_indexed(s, opsize, reg);
+ return gen_lea_indexed(env, s, opsize, reg);
case 7: /* Other */
switch (insn & 7) {
case 0: /* Absolute short. */
- offset = cpu_ldsw_code(cpu_single_env, s->pc);
+ offset = cpu_ldsw_code(env, s->pc);
s->pc += 2;
return tcg_const_i32(offset);
case 1: /* Absolute long. */
- offset = read_im32(s);
+ offset = read_im32(env, s);
return tcg_const_i32(offset);
case 2: /* pc displacement */
offset = s->pc;
- offset += cpu_ldsw_code(cpu_single_env, s->pc);
+ offset += cpu_ldsw_code(env, s->pc);
s->pc += 2;
return tcg_const_i32(offset);
case 3: /* pc index+displacement. */
- return gen_lea_indexed(s, opsize, NULL_QREG);
+ return gen_lea_indexed(env, s, opsize, NULL_QREG);
case 4: /* Immediate. */
default:
return NULL_QREG;
@@ -548,15 +556,16 @@ static TCGv gen_lea(DisasContext *s, uint16_t insn, int opsize)
/* Helper function for gen_ea. Reuse the computed address between the
for read/write operands. */
-static inline TCGv gen_ea_once(DisasContext *s, uint16_t insn, int opsize,
- TCGv val, TCGv *addrp, ea_what what)
+static inline TCGv gen_ea_once(CPUM68KState *env, DisasContext *s,
+ uint16_t insn, int opsize, TCGv val,
+ TCGv *addrp, ea_what what)
{
TCGv tmp;
if (addrp && what == EA_STORE) {
tmp = *addrp;
} else {
- tmp = gen_lea(s, insn, opsize);
+ tmp = gen_lea(env, s, insn, opsize);
if (IS_NULL_QREG(tmp))
return tmp;
if (addrp)
@@ -568,8 +577,8 @@ static inline TCGv gen_ea_once(DisasContext *s, uint16_t insn, int opsize,
/* Generate code to load/store a value ito/from an EA. If VAL > 0 this is
a write otherwise it is a read (0 == sign extend, -1 == zero extend).
ADDRP is non-null for readwrite operands. */
-static TCGv gen_ea(DisasContext *s, uint16_t insn, int opsize, TCGv val,
- TCGv *addrp, ea_what what)
+static TCGv gen_ea(CPUM68KState *env, DisasContext *s, uint16_t insn,
+ int opsize, TCGv val, TCGv *addrp, ea_what what)
{
TCGv reg;
TCGv result;
@@ -609,7 +618,7 @@ static TCGv gen_ea(DisasContext *s, uint16_t insn, int opsize, TCGv val,
if (addrp && what == EA_STORE) {
tmp = *addrp;
} else {
- tmp = gen_lea(s, insn, opsize);
+ tmp = gen_lea(env, s, insn, opsize);
if (IS_NULL_QREG(tmp))
return tmp;
if (addrp)
@@ -626,35 +635,35 @@ static TCGv gen_ea(DisasContext *s, uint16_t insn, int opsize, TCGv val,
return result;
case 5: /* Indirect displacement. */
case 6: /* Indirect index + displacement. */
- return gen_ea_once(s, insn, opsize, val, addrp, what);
+ return gen_ea_once(env, s, insn, opsize, val, addrp, what);
case 7: /* Other */
switch (insn & 7) {
case 0: /* Absolute short. */
case 1: /* Absolute long. */
case 2: /* pc displacement */
case 3: /* pc index+displacement. */
- return gen_ea_once(s, insn, opsize, val, addrp, what);
+ return gen_ea_once(env, s, insn, opsize, val, addrp, what);
case 4: /* Immediate. */
/* Sign extend values for consistency. */
switch (opsize) {
case OS_BYTE:
if (what == EA_LOADS) {
- offset = cpu_ldsb_code(cpu_single_env, s->pc + 1);
+ offset = cpu_ldsb_code(env, s->pc + 1);
} else {
- offset = cpu_ldub_code(cpu_single_env, s->pc + 1);
+ offset = cpu_ldub_code(env, s->pc + 1);
}
s->pc += 2;
break;
case OS_WORD:
if (what == EA_LOADS) {
- offset = cpu_ldsw_code(cpu_single_env, s->pc);
+ offset = cpu_ldsw_code(env, s->pc);
} else {
- offset = cpu_lduw_code(cpu_single_env, s->pc);
+ offset = cpu_lduw_code(env, s->pc);
}
s->pc += 2;
break;
case OS_LONG:
- offset = read_im32(s);
+ offset = read_im32(env, s);
break;
default:
qemu_assert(0, "Bad immediate operand");
@@ -825,20 +834,21 @@ static inline void gen_addr_fault(DisasContext *s)
gen_exception(s, s->insn_pc, EXCP_ADDRESS);
}
-#define SRC_EA(result, opsize, op_sign, addrp) do { \
- result = gen_ea(s, insn, opsize, NULL_QREG, addrp, op_sign ? EA_LOADS : EA_LOADU); \
- if (IS_NULL_QREG(result)) { \
- gen_addr_fault(s); \
- return; \
- } \
+#define SRC_EA(env, result, opsize, op_sign, addrp) do { \
+ result = gen_ea(env, s, insn, opsize, NULL_QREG, addrp, \
+ op_sign ? EA_LOADS : EA_LOADU); \
+ if (IS_NULL_QREG(result)) { \
+ gen_addr_fault(s); \
+ return; \
+ } \
} while (0)
-#define DEST_EA(insn, opsize, val, addrp) do { \
- TCGv ea_result = gen_ea(s, insn, opsize, val, addrp, EA_STORE); \
- if (IS_NULL_QREG(ea_result)) { \
- gen_addr_fault(s); \
- return; \
- } \
+#define DEST_EA(env, insn, opsize, val, addrp) do { \
+ TCGv ea_result = gen_ea(env, s, insn, opsize, val, addrp, EA_STORE); \
+ if (IS_NULL_QREG(ea_result)) { \
+ gen_addr_fault(s); \
+ return; \
+ } \
} while (0)
/* Generate a jump to an immediate address. */
@@ -874,8 +884,7 @@ DISAS_INSN(undef_fpu)
DISAS_INSN(undef)
{
gen_exception(s, s->pc - 2, EXCP_UNSUPPORTED);
- cpu_abort(cpu_single_env, "Illegal instruction: %04x @ %08x",
- insn, s->pc - 2);
+ cpu_abort(env, "Illegal instruction: %04x @ %08x", insn, s->pc - 2);
}
DISAS_INSN(mulw)
@@ -892,7 +901,7 @@ DISAS_INSN(mulw)
tcg_gen_ext16s_i32(tmp, reg);
else
tcg_gen_ext16u_i32(tmp, reg);
- SRC_EA(src, OS_WORD, sign, NULL);
+ SRC_EA(env, src, OS_WORD, sign, NULL);
tcg_gen_mul_i32(tmp, tmp, src);
tcg_gen_mov_i32(reg, tmp);
/* Unlike m68k, coldfire always clears the overflow bit. */
@@ -913,7 +922,7 @@ DISAS_INSN(divw)
} else {
tcg_gen_ext16u_i32(QREG_DIV1, reg);
}
- SRC_EA(src, OS_WORD, sign, NULL);
+ SRC_EA(env, src, OS_WORD, sign, NULL);
tcg_gen_mov_i32(QREG_DIV2, src);
if (sign) {
gen_helper_divs(cpu_env, tcg_const_i32(1));
@@ -936,7 +945,7 @@ DISAS_INSN(divl)
TCGv reg;
uint16_t ext;
- ext = cpu_lduw_code(cpu_single_env, s->pc);
+ ext = cpu_lduw_code(env, s->pc);
s->pc += 2;
if (ext & 0x87f8) {
gen_exception(s, s->pc - 4, EXCP_UNSUPPORTED);
@@ -945,7 +954,7 @@ DISAS_INSN(divl)
num = DREG(ext, 12);
reg = DREG(ext, 0);
tcg_gen_mov_i32(QREG_DIV1, num);
- SRC_EA(den, OS_LONG, 0, NULL);
+ SRC_EA(env, den, OS_LONG, 0, NULL);
tcg_gen_mov_i32(QREG_DIV2, den);
if (ext & 0x0800) {
gen_helper_divs(cpu_env, tcg_const_i32(0));
@@ -975,11 +984,11 @@ DISAS_INSN(addsub)
reg = DREG(insn, 9);
dest = tcg_temp_new();
if (insn & 0x100) {
- SRC_EA(tmp, OS_LONG, 0, &addr);
+ SRC_EA(env, tmp, OS_LONG, 0, &addr);
src = reg;
} else {
tmp = reg;
- SRC_EA(src, OS_LONG, 0, NULL);
+ SRC_EA(env, src, OS_LONG, 0, NULL);
}
if (add) {
tcg_gen_add_i32(dest, tmp, src);
@@ -992,7 +1001,7 @@ DISAS_INSN(addsub)
}
gen_update_cc_add(dest, src);
if (insn & 0x100) {
- DEST_EA(insn, OS_LONG, dest, &addr);
+ DEST_EA(env, insn, OS_LONG, dest, &addr);
} else {
tcg_gen_mov_i32(reg, dest);
}
@@ -1022,7 +1031,7 @@ DISAS_INSN(bitop_reg)
else
opsize = OS_LONG;
op = (insn >> 6) & 3;
- SRC_EA(src1, opsize, 0, op ? &addr: NULL);
+ SRC_EA(env, src1, opsize, 0, op ? &addr: NULL);
src2 = DREG(insn, 9);
dest = tcg_temp_new();
@@ -1057,7 +1066,7 @@ DISAS_INSN(bitop_reg)
break;
}
if (op)
- DEST_EA(insn, opsize, dest, &addr);
+ DEST_EA(env, insn, opsize, dest, &addr);
}
DISAS_INSN(sats)
@@ -1088,9 +1097,9 @@ DISAS_INSN(movem)
TCGv tmp;
int is_load;
- mask = cpu_lduw_code(cpu_single_env, s->pc);
+ mask = cpu_lduw_code(env, s->pc);
s->pc += 2;
- tmp = gen_lea(s, insn, OS_LONG);
+ tmp = gen_lea(env, s, insn, OS_LONG);
if (IS_NULL_QREG(tmp)) {
gen_addr_fault(s);
return;
@@ -1132,14 +1141,14 @@ DISAS_INSN(bitop_im)
opsize = OS_LONG;
op = (insn >> 6) & 3;
- bitnum = cpu_lduw_code(cpu_single_env, s->pc);
+ bitnum = cpu_lduw_code(env, s->pc);
s->pc += 2;
if (bitnum & 0xff00) {
- disas_undef(s, insn);
+ disas_undef(env, s, insn);
return;
}
- SRC_EA(src1, opsize, 0, op ? &addr: NULL);
+ SRC_EA(env, src1, opsize, 0, op ? &addr: NULL);
gen_flush_flags(s);
if (opsize == OS_BYTE)
@@ -1174,7 +1183,7 @@ DISAS_INSN(bitop_im)
default: /* btst */
break;
}
- DEST_EA(insn, opsize, tmp, &addr);
+ DEST_EA(env, insn, opsize, tmp, &addr);
}
}
@@ -1187,8 +1196,8 @@ DISAS_INSN(arith_im)
TCGv addr;
op = (insn >> 9) & 7;
- SRC_EA(src1, OS_LONG, 0, (op == 6) ? NULL : &addr);
- im = read_im32(s);
+ SRC_EA(env, src1, OS_LONG, 0, (op == 6) ? NULL : &addr);
+ im = read_im32(env, s);
dest = tcg_temp_new();
switch (op) {
case 0: /* ori */
@@ -1227,7 +1236,7 @@ DISAS_INSN(arith_im)
abort();
}
if (op != 6) {
- DEST_EA(insn, OS_LONG, dest, &addr);
+ DEST_EA(env, insn, OS_LONG, dest, &addr);
}
}
@@ -1259,7 +1268,7 @@ DISAS_INSN(move)
default:
abort();
}
- SRC_EA(src, opsize, 1, NULL);
+ SRC_EA(env, src, opsize, 1, NULL);
op = (insn >> 6) & 7;
if (op == 1) {
/* movea */
@@ -1270,7 +1279,7 @@ DISAS_INSN(move)
/* normal move */
uint16_t dest_ea;
dest_ea = ((insn >> 9) & 7) | (op << 3);
- DEST_EA(dest_ea, opsize, src, NULL);
+ DEST_EA(env, dest_ea, opsize, src, NULL);
/* This will be correct because loads sign extend. */
gen_logic_cc(s, src);
}
@@ -1291,7 +1300,7 @@ DISAS_INSN(lea)
TCGv tmp;
reg = AREG(insn, 9);
- tmp = gen_lea(s, insn, OS_LONG);
+ tmp = gen_lea(env, s, insn, OS_LONG);
if (IS_NULL_QREG(tmp)) {
gen_addr_fault(s);
return;
@@ -1316,7 +1325,7 @@ DISAS_INSN(clr)
default:
abort();
}
- DEST_EA(insn, opsize, tcg_const_i32(0), NULL);
+ DEST_EA(env, insn, opsize, tcg_const_i32(0), NULL);
gen_logic_cc(s, tcg_const_i32(0));
}
@@ -1365,7 +1374,8 @@ static void gen_set_sr_im(DisasContext *s, uint16_t val, int ccr_only)
}
}
-static void gen_set_sr(DisasContext *s, uint16_t insn, int ccr_only)
+static void gen_set_sr(CPUM68KState *env, DisasContext *s, uint16_t insn,
+ int ccr_only)
{
TCGv tmp;
TCGv reg;
@@ -1385,17 +1395,17 @@ static void gen_set_sr(DisasContext *s, uint16_t insn, int ccr_only)
else if ((insn & 0x3f) == 0x3c)
{
uint16_t val;
- val = cpu_lduw_code(cpu_single_env, s->pc);
+ val = cpu_lduw_code(env, s->pc);
s->pc += 2;
gen_set_sr_im(s, val, ccr_only);
}
else
- disas_undef(s, insn);
+ disas_undef(env, s, insn);
}
DISAS_INSN(move_to_ccr)
{
- gen_set_sr(s, insn, 1);
+ gen_set_sr(env, s, insn, 1);
}
DISAS_INSN(not)
@@ -1426,7 +1436,7 @@ DISAS_INSN(pea)
{
TCGv tmp;
- tmp = gen_lea(s, insn, OS_LONG);
+ tmp = gen_lea(env, s, insn, OS_LONG);
if (IS_NULL_QREG(tmp)) {
gen_addr_fault(s);
return;
@@ -1472,7 +1482,7 @@ DISAS_INSN(tst)
default:
abort();
}
- SRC_EA(tmp, opsize, 1, NULL);
+ SRC_EA(env, tmp, opsize, 1, NULL);
gen_logic_cc(s, tmp);
}
@@ -1494,10 +1504,10 @@ DISAS_INSN(tas)
TCGv addr;
dest = tcg_temp_new();
- SRC_EA(src1, OS_BYTE, 1, &addr);
+ SRC_EA(env, src1, OS_BYTE, 1, &addr);
gen_logic_cc(s, src1);
tcg_gen_ori_i32(dest, src1, 0x80);
- DEST_EA(insn, OS_BYTE, dest, &addr);
+ DEST_EA(env, insn, OS_BYTE, dest, &addr);
}
DISAS_INSN(mull)
@@ -1509,14 +1519,14 @@ DISAS_INSN(mull)
/* The upper 32 bits of the product are discarded, so
muls.l and mulu.l are functionally equivalent. */
- ext = cpu_lduw_code(cpu_single_env, s->pc);
+ ext = cpu_lduw_code(env, s->pc);
s->pc += 2;
if (ext & 0x87ff) {
gen_exception(s, s->pc - 4, EXCP_UNSUPPORTED);
return;
}
reg = DREG(ext, 12);
- SRC_EA(src1, OS_LONG, 0, NULL);
+ SRC_EA(env, src1, OS_LONG, 0, NULL);
dest = tcg_temp_new();
tcg_gen_mul_i32(dest, src1, reg);
tcg_gen_mov_i32(reg, dest);
@@ -1530,7 +1540,7 @@ DISAS_INSN(link)
TCGv reg;
TCGv tmp;
- offset = cpu_ldsw_code(cpu_single_env, s->pc);
+ offset = cpu_ldsw_code(env, s->pc);
s->pc += 2;
reg = AREG(insn, 0);
tmp = tcg_temp_new();
@@ -1574,7 +1584,7 @@ DISAS_INSN(jump)
/* Load the target address first to ensure correct exception
behavior. */
- tmp = gen_lea(s, insn, OS_LONG);
+ tmp = gen_lea(env, s, insn, OS_LONG);
if (IS_NULL_QREG(tmp)) {
gen_addr_fault(s);
return;
@@ -1594,7 +1604,7 @@ DISAS_INSN(addsubq)
int val;
TCGv addr;
- SRC_EA(src1, OS_LONG, 0, &addr);
+ SRC_EA(env, src1, OS_LONG, 0, &addr);
val = (insn >> 9) & 7;
if (val == 0)
val = 8;
@@ -1621,7 +1631,7 @@ DISAS_INSN(addsubq)
}
gen_update_cc_add(dest, src2);
}
- DEST_EA(insn, OS_LONG, dest, &addr);
+ DEST_EA(env, insn, OS_LONG, dest, &addr);
}
DISAS_INSN(tpf)
@@ -1636,7 +1646,7 @@ DISAS_INSN(tpf)
case 4: /* No extension words. */
break;
default:
- disas_undef(s, insn);
+ disas_undef(env, s, insn);
}
}
@@ -1651,10 +1661,10 @@ DISAS_INSN(branch)
op = (insn >> 8) & 0xf;
offset = (int8_t)insn;
if (offset == 0) {
- offset = cpu_ldsw_code(cpu_single_env, s->pc);
+ offset = cpu_ldsw_code(env, s->pc);
s->pc += 2;
} else if (offset == -1) {
- offset = read_im32(s);
+ offset = read_im32(env, s);
}
if (op == 1) {
/* bsr */
@@ -1693,7 +1703,7 @@ DISAS_INSN(mvzs)
opsize = OS_WORD;
else
opsize = OS_BYTE;
- SRC_EA(src, opsize, (insn & 0x80) == 0, NULL);
+ SRC_EA(env, src, opsize, (insn & 0x80) == 0, NULL);
reg = DREG(insn, 9);
tcg_gen_mov_i32(reg, src);
gen_logic_cc(s, src);
@@ -1709,11 +1719,11 @@ DISAS_INSN(or)
reg = DREG(insn, 9);
dest = tcg_temp_new();
if (insn & 0x100) {
- SRC_EA(src, OS_LONG, 0, &addr);
+ SRC_EA(env, src, OS_LONG, 0, &addr);
tcg_gen_or_i32(dest, src, reg);
- DEST_EA(insn, OS_LONG, dest, &addr);
+ DEST_EA(env, insn, OS_LONG, dest, &addr);
} else {
- SRC_EA(src, OS_LONG, 0, NULL);
+ SRC_EA(env, src, OS_LONG, 0, NULL);
tcg_gen_or_i32(dest, src, reg);
tcg_gen_mov_i32(reg, dest);
}
@@ -1725,7 +1735,7 @@ DISAS_INSN(suba)
TCGv src;
TCGv reg;
- SRC_EA(src, OS_LONG, 0, NULL);
+ SRC_EA(env, src, OS_LONG, 0, NULL);
reg = AREG(insn, 9);
tcg_gen_sub_i32(reg, reg, src);
}
@@ -1751,7 +1761,7 @@ DISAS_INSN(mov3q)
val = -1;
src = tcg_const_i32(val);
gen_logic_cc(s, src);
- DEST_EA(insn, OS_LONG, src, NULL);
+ DEST_EA(env, insn, OS_LONG, src, NULL);
}
DISAS_INSN(cmp)
@@ -1779,7 +1789,7 @@ DISAS_INSN(cmp)
default:
abort();
}
- SRC_EA(src, opsize, 1, NULL);
+ SRC_EA(env, src, opsize, 1, NULL);
reg = DREG(insn, 9);
dest = tcg_temp_new();
tcg_gen_sub_i32(dest, reg, src);
@@ -1798,7 +1808,7 @@ DISAS_INSN(cmpa)
} else {
opsize = OS_WORD;
}
- SRC_EA(src, opsize, 1, NULL);
+ SRC_EA(env, src, opsize, 1, NULL);
reg = AREG(insn, 9);
dest = tcg_temp_new();
tcg_gen_sub_i32(dest, reg, src);
@@ -1813,12 +1823,12 @@ DISAS_INSN(eor)
TCGv dest;
TCGv addr;
- SRC_EA(src, OS_LONG, 0, &addr);
+ SRC_EA(env, src, OS_LONG, 0, &addr);
reg = DREG(insn, 9);
dest = tcg_temp_new();
tcg_gen_xor_i32(dest, src, reg);
gen_logic_cc(s, dest);
- DEST_EA(insn, OS_LONG, dest, &addr);
+ DEST_EA(env, insn, OS_LONG, dest, &addr);
}
DISAS_INSN(and)
@@ -1831,11 +1841,11 @@ DISAS_INSN(and)
reg = DREG(insn, 9);
dest = tcg_temp_new();
if (insn & 0x100) {
- SRC_EA(src, OS_LONG, 0, &addr);
+ SRC_EA(env, src, OS_LONG, 0, &addr);
tcg_gen_and_i32(dest, src, reg);
- DEST_EA(insn, OS_LONG, dest, &addr);
+ DEST_EA(env, insn, OS_LONG, dest, &addr);
} else {
- SRC_EA(src, OS_LONG, 0, NULL);
+ SRC_EA(env, src, OS_LONG, 0, NULL);
tcg_gen_and_i32(dest, src, reg);
tcg_gen_mov_i32(reg, dest);
}
@@ -1847,7 +1857,7 @@ DISAS_INSN(adda)
TCGv src;
TCGv reg;
- SRC_EA(src, OS_LONG, 0, NULL);
+ SRC_EA(env, src, OS_LONG, 0, NULL);
reg = AREG(insn, 9);
tcg_gen_add_i32(reg, reg, src);
}
@@ -1936,13 +1946,13 @@ DISAS_INSN(strldsr)
uint32_t addr;
addr = s->pc - 2;
- ext = cpu_lduw_code(cpu_single_env, s->pc);
+ ext = cpu_lduw_code(env, s->pc);
s->pc += 2;
if (ext != 0x46FC) {
gen_exception(s, addr, EXCP_UNSUPPORTED);
return;
}
- ext = cpu_lduw_code(cpu_single_env, s->pc);
+ ext = cpu_lduw_code(env, s->pc);
s->pc += 2;
if (IS_USER(s) || (ext & SR_S) == 0) {
gen_exception(s, addr, EXCP_PRIVILEGE);
@@ -1972,7 +1982,7 @@ DISAS_INSN(move_to_sr)
gen_exception(s, s->pc - 2, EXCP_PRIVILEGE);
return;
}
- gen_set_sr(s, insn, 0);
+ gen_set_sr(env, s, insn, 0);
gen_lookup_tb(s);
}
@@ -2010,7 +2020,7 @@ DISAS_INSN(stop)
return;
}
- ext = cpu_lduw_code(cpu_single_env, s->pc);
+ ext = cpu_lduw_code(env, s->pc);
s->pc += 2;
gen_set_sr_im(s, ext, 0);
@@ -2037,7 +2047,7 @@ DISAS_INSN(movec)
return;
}
- ext = cpu_lduw_code(cpu_single_env, s->pc);
+ ext = cpu_lduw_code(env, s->pc);
s->pc += 2;
if (ext & 0x8000) {
@@ -2102,7 +2112,7 @@ DISAS_INSN(fpu)
int set_dest;
int opsize;
- ext = cpu_lduw_code(cpu_single_env, s->pc);
+ ext = cpu_lduw_code(env, s->pc);
s->pc += 2;
opmode = ext & 0x7f;
switch ((ext >> 13) & 7) {
@@ -2138,7 +2148,7 @@ DISAS_INSN(fpu)
tcg_gen_addi_i32(tmp32, tmp32, -8);
break;
case 5:
- offset = cpu_ldsw_code(cpu_single_env, s->pc);
+ offset = cpu_ldsw_code(env, s->pc);
s->pc += 2;
tcg_gen_addi_i32(tmp32, tmp32, offset);
break;
@@ -2164,7 +2174,7 @@ DISAS_INSN(fpu)
default:
goto undef;
}
- DEST_EA(insn, opsize, tmp32, NULL);
+ DEST_EA(env, insn, opsize, tmp32, NULL);
tcg_temp_free_i32(tmp32);
return;
case 4: /* fmove to control register. */
@@ -2192,7 +2202,7 @@ DISAS_INSN(fpu)
(ext >> 10) & 7);
goto undef;
}
- DEST_EA(insn, OS_LONG, tmp32, NULL);
+ DEST_EA(env, insn, OS_LONG, tmp32, NULL);
break;
case 6: /* fmovem */
case 7:
@@ -2202,7 +2212,7 @@ DISAS_INSN(fpu)
int i;
if ((ext & 0x1f00) != 0x1000 || (ext & 0xff) == 0)
goto undef;
- tmp32 = gen_lea(s, insn, OS_LONG);
+ tmp32 = gen_lea(env, s, insn, OS_LONG);
if (IS_NULL_QREG(tmp32)) {
gen_addr_fault(s);
return;
@@ -2252,12 +2262,12 @@ DISAS_INSN(fpu)
tcg_gen_addi_i32(tmp32, tmp32, -8);
break;
case 5:
- offset = cpu_ldsw_code(cpu_single_env, s->pc);
+ offset = cpu_ldsw_code(env, s->pc);
s->pc += 2;
tcg_gen_addi_i32(tmp32, tmp32, offset);
break;
case 7:
- offset = cpu_ldsw_code(cpu_single_env, s->pc);
+ offset = cpu_ldsw_code(env, s->pc);
offset += s->pc - 2;
s->pc += 2;
tcg_gen_addi_i32(tmp32, tmp32, offset);
@@ -2277,7 +2287,7 @@ DISAS_INSN(fpu)
}
tcg_temp_free_i32(tmp32);
} else {
- SRC_EA(tmp32, opsize, 1, NULL);
+ SRC_EA(env, tmp32, opsize, 1, NULL);
src = tcg_temp_new_i64();
switch (opsize) {
case OS_LONG:
@@ -2372,7 +2382,7 @@ DISAS_INSN(fpu)
undef:
/* FIXME: Is this right for offset addressing modes? */
s->pc -= 2;
- disas_undef_fpu(s, insn);
+ disas_undef_fpu(env, s, insn);
}
DISAS_INSN(fbcc)
@@ -2383,10 +2393,10 @@ DISAS_INSN(fbcc)
int l1;
addr = s->pc;
- offset = cpu_ldsw_code(cpu_single_env, s->pc);
+ offset = cpu_ldsw_code(env, s->pc);
s->pc += 2;
if (insn & (1 << 6)) {
- offset = (offset << 16) | cpu_lduw_code(cpu_single_env, s->pc);
+ offset = (offset << 16) | cpu_lduw_code(env, s->pc);
s->pc += 2;
}
@@ -2508,18 +2518,18 @@ DISAS_INSN(mac)
s->done_mac = 1;
}
- ext = cpu_lduw_code(cpu_single_env, s->pc);
+ ext = cpu_lduw_code(env, s->pc);
s->pc += 2;
acc = ((insn >> 7) & 1) | ((ext >> 3) & 2);
dual = ((insn & 0x30) != 0 && (ext & 3) != 0);
if (dual && !m68k_feature(s->env, M68K_FEATURE_CF_EMAC_B)) {
- disas_undef(s, insn);
+ disas_undef(env, s, insn);
return;
}
if (insn & 0x30) {
/* MAC with load. */
- tmp = gen_lea(s, insn, OS_LONG);
+ tmp = gen_lea(env, s, insn, OS_LONG);
addr = tcg_temp_new();
tcg_gen_and_i32(addr, tmp, QREG_MAC_MASK);
/* Load the value now to ensure correct exception behavior.
@@ -2733,7 +2743,7 @@ DISAS_INSN(to_mac)
int accnum;
accnum = (insn >> 9) & 3;
acc = MACREG(accnum);
- SRC_EA(val, OS_LONG, 0, NULL);
+ SRC_EA(env, val, OS_LONG, 0, NULL);
if (s->env->macsr & MACSR_FI) {
tcg_gen_ext_i32_i64(acc, val);
tcg_gen_shli_i64(acc, acc, 8);
@@ -2750,7 +2760,7 @@ DISAS_INSN(to_mac)
DISAS_INSN(to_macsr)
{
TCGv val;
- SRC_EA(val, OS_LONG, 0, NULL);
+ SRC_EA(env, val, OS_LONG, 0, NULL);
gen_helper_set_macsr(cpu_env, val);
gen_lookup_tb(s);
}
@@ -2758,7 +2768,7 @@ DISAS_INSN(to_macsr)
DISAS_INSN(to_mask)
{
TCGv val;
- SRC_EA(val, OS_LONG, 0, NULL);
+ SRC_EA(env, val, OS_LONG, 0, NULL);
tcg_gen_ori_i32(QREG_MAC_MASK, val, 0xffff0000);
}
@@ -2766,7 +2776,7 @@ DISAS_INSN(to_mext)
{
TCGv val;
TCGv acc;
- SRC_EA(val, OS_LONG, 0, NULL);
+ SRC_EA(env, val, OS_LONG, 0, NULL);
acc = tcg_const_i32((insn & 0x400) ? 2 : 0);
if (s->env->macsr & MACSR_FI)
gen_helper_set_mac_extf(cpu_env, val, acc);
@@ -2943,10 +2953,10 @@ static void disas_m68k_insn(CPUM68KState * env, DisasContext *s)
{
uint16_t insn;
- insn = cpu_lduw_code(cpu_single_env, s->pc);
+ insn = cpu_lduw_code(env, s->pc);
s->pc += 2;
- opcode_table[insn](s, insn);
+ opcode_table[insn](env, s, insn);
}
/* generate intermediate code for basic block 'tb'. */
--
1.7.12.1

View File

@ -0,0 +1,437 @@
From 23ff6fa6a883d210aab33e09d0bb9470df5083fc Mon Sep 17 00:00:00 2001
From: Blue Swirl <blauwirbel@gmail.com>
Date: Sun, 2 Sep 2012 07:42:33 +0000
Subject: [PATCH] target-unicore32: switch to AREG0 free mode
Add an explicit CPUState parameter instead of relying on AREG0
and switch to AREG0 free mode.
Tested-by: Guan Xuetao <gxt@mprc.pku.edu.cn>
Signed-off-by: Blue Swirl <blauwirbel@gmail.com>
Signed-off-by: Michael Roth <mdroth@linux.vnet.ibm.com>
---
configure | 2 +-
target-unicore32/Makefile.objs | 2 --
target-unicore32/helper.h | 26 ++++++++---------
target-unicore32/op_helper.c | 65 ++++++++++++++++--------------------------
target-unicore32/translate.c | 38 ++++++++++++------------
5 files changed, 58 insertions(+), 75 deletions(-)
diff --git a/configure b/configure
index af03942..a8827ba 100755
--- a/configure
+++ b/configure
@@ -3839,7 +3839,7 @@ symlink "$source_path/Makefile.target" "$target_dir/Makefile"
case "$target_arch2" in
- alpha | i386 | lm32 | m68k | or32 | s390x | sparc* | x86_64 | xtensa* | ppc*)
+ alpha | i386 | lm32 | m68k | or32 | s390x | sparc* | unicore32 | x86_64 | xtensa* | ppc*)
echo "CONFIG_TCG_PASS_AREG0=y" >> $config_target_mak
;;
esac
diff --git a/target-unicore32/Makefile.objs b/target-unicore32/Makefile.objs
index 777f01f..8e143da 100644
--- a/target-unicore32/Makefile.objs
+++ b/target-unicore32/Makefile.objs
@@ -2,5 +2,3 @@ obj-y += translate.o op_helper.o helper.o cpu.o
obj-y += ucf64_helper.o
obj-$(CONFIG_SOFTMMU) += machine.o softmmu.o
-
-$(obj)/op_helper.o: QEMU_CFLAGS += $(HELPER_CFLAGS)
diff --git a/target-unicore32/helper.h b/target-unicore32/helper.h
index 305318a..a4b8149 100644
--- a/target-unicore32/helper.h
+++ b/target-unicore32/helper.h
@@ -17,26 +17,26 @@ DEF_HELPER_1(cp1_putc, void, i32)
DEF_HELPER_1(clz, i32, i32)
DEF_HELPER_1(clo, i32, i32)
-DEF_HELPER_1(exception, void, i32)
+DEF_HELPER_2(exception, void, env, i32)
-DEF_HELPER_2(asr_write, void, i32, i32)
-DEF_HELPER_0(asr_read, i32)
+DEF_HELPER_3(asr_write, void, env, i32, i32)
+DEF_HELPER_1(asr_read, i32, env)
-DEF_HELPER_1(get_user_reg, i32, i32)
-DEF_HELPER_2(set_user_reg, void, i32, i32)
+DEF_HELPER_2(get_user_reg, i32, env, i32)
+DEF_HELPER_3(set_user_reg, void, env, i32, i32)
-DEF_HELPER_2(add_cc, i32, i32, i32)
-DEF_HELPER_2(adc_cc, i32, i32, i32)
-DEF_HELPER_2(sub_cc, i32, i32, i32)
-DEF_HELPER_2(sbc_cc, i32, i32, i32)
+DEF_HELPER_3(add_cc, i32, env, i32, i32)
+DEF_HELPER_3(adc_cc, i32, env, i32, i32)
+DEF_HELPER_3(sub_cc, i32, env, i32, i32)
+DEF_HELPER_3(sbc_cc, i32, env, i32, i32)
DEF_HELPER_2(shl, i32, i32, i32)
DEF_HELPER_2(shr, i32, i32, i32)
DEF_HELPER_2(sar, i32, i32, i32)
-DEF_HELPER_2(shl_cc, i32, i32, i32)
-DEF_HELPER_2(shr_cc, i32, i32, i32)
-DEF_HELPER_2(sar_cc, i32, i32, i32)
-DEF_HELPER_2(ror_cc, i32, i32, i32)
+DEF_HELPER_3(shl_cc, i32, env, i32, i32)
+DEF_HELPER_3(shr_cc, i32, env, i32, i32)
+DEF_HELPER_3(sar_cc, i32, env, i32, i32)
+DEF_HELPER_3(ror_cc, i32, env, i32, i32)
DEF_HELPER_1(ucf64_get_fpscr, i32, env)
DEF_HELPER_2(ucf64_set_fpscr, void, env, i32)
diff --git a/target-unicore32/op_helper.c b/target-unicore32/op_helper.c
index c63789d..f474d1b 100644
--- a/target-unicore32/op_helper.c
+++ b/target-unicore32/op_helper.c
@@ -9,19 +9,18 @@
* later version. See the COPYING file in the top-level directory.
*/
#include "cpu.h"
-#include "dyngen-exec.h"
#include "helper.h"
#define SIGNBIT (uint32_t)0x80000000
#define SIGNBIT64 ((uint64_t)1 << 63)
-void HELPER(exception)(uint32_t excp)
+void HELPER(exception)(CPUUniCore32State *env, uint32_t excp)
{
env->exception_index = excp;
cpu_loop_exit(env);
}
-static target_ulong asr_read(void)
+static target_ulong asr_read(CPUUniCore32State *env)
{
int ZF;
ZF = (env->ZF == 0);
@@ -29,24 +28,18 @@ static target_ulong asr_read(void)
(env->CF << 29) | ((env->VF & 0x80000000) >> 3);
}
-target_ulong cpu_asr_read(CPUUniCore32State *env1)
+target_ulong cpu_asr_read(CPUUniCore32State *env)
{
- CPUUniCore32State *saved_env;
- target_ulong ret;
-
- saved_env = env;
- env = env1;
- ret = asr_read();
- env = saved_env;
- return ret;
+ return asr_read(env);
}
-target_ulong HELPER(asr_read)(void)
+target_ulong HELPER(asr_read)(CPUUniCore32State *env)
{
- return asr_read();
+ return asr_read(env);
}
-static void asr_write(target_ulong val, target_ulong mask)
+static void asr_write(CPUUniCore32State *env, target_ulong val,
+ target_ulong mask)
{
if (mask & ASR_NZCV) {
env->ZF = (~val) & ASR_Z;
@@ -62,23 +55,19 @@ static void asr_write(target_ulong val, target_ulong mask)
env->uncached_asr = (env->uncached_asr & ~mask) | (val & mask);
}
-void cpu_asr_write(CPUUniCore32State *env1, target_ulong val, target_ulong mask)
+void cpu_asr_write(CPUUniCore32State *env, target_ulong val, target_ulong mask)
{
- CPUUniCore32State *saved_env;
-
- saved_env = env;
- env = env1;
- asr_write(val, mask);
- env = saved_env;
+ asr_write(env, val, mask);
}
-void HELPER(asr_write)(target_ulong val, target_ulong mask)
+void HELPER(asr_write)(CPUUniCore32State *env, target_ulong val,
+ target_ulong mask)
{
- asr_write(val, mask);
+ asr_write(env, val, mask);
}
/* Access to user mode registers from privileged modes. */
-uint32_t HELPER(get_user_reg)(uint32_t regno)
+uint32_t HELPER(get_user_reg)(CPUUniCore32State *env, uint32_t regno)
{
uint32_t val;
@@ -92,7 +81,7 @@ uint32_t HELPER(get_user_reg)(uint32_t regno)
return val;
}
-void HELPER(set_user_reg)(uint32_t regno, uint32_t val)
+void HELPER(set_user_reg)(CPUUniCore32State *env, uint32_t regno, uint32_t val)
{
if (regno == 29) {
env->banked_r29[0] = val;
@@ -107,7 +96,7 @@ void HELPER(set_user_reg)(uint32_t regno, uint32_t val)
The only way to do that in TCG is a conditional branch, which clobbers
all our temporaries. For now implement these as helper functions. */
-uint32_t HELPER(add_cc)(uint32_t a, uint32_t b)
+uint32_t HELPER(add_cc)(CPUUniCore32State *env, uint32_t a, uint32_t b)
{
uint32_t result;
result = a + b;
@@ -117,7 +106,7 @@ uint32_t HELPER(add_cc)(uint32_t a, uint32_t b)
return result;
}
-uint32_t HELPER(adc_cc)(uint32_t a, uint32_t b)
+uint32_t HELPER(adc_cc)(CPUUniCore32State *env, uint32_t a, uint32_t b)
{
uint32_t result;
if (!env->CF) {
@@ -132,7 +121,7 @@ uint32_t HELPER(adc_cc)(uint32_t a, uint32_t b)
return result;
}
-uint32_t HELPER(sub_cc)(uint32_t a, uint32_t b)
+uint32_t HELPER(sub_cc)(CPUUniCore32State *env, uint32_t a, uint32_t b)
{
uint32_t result;
result = a - b;
@@ -142,7 +131,7 @@ uint32_t HELPER(sub_cc)(uint32_t a, uint32_t b)
return result;
}
-uint32_t HELPER(sbc_cc)(uint32_t a, uint32_t b)
+uint32_t HELPER(sbc_cc)(CPUUniCore32State *env, uint32_t a, uint32_t b)
{
uint32_t result;
if (!env->CF) {
@@ -186,7 +175,7 @@ uint32_t HELPER(sar)(uint32_t x, uint32_t i)
return (int32_t)x >> shift;
}
-uint32_t HELPER(shl_cc)(uint32_t x, uint32_t i)
+uint32_t HELPER(shl_cc)(CPUUniCore32State *env, uint32_t x, uint32_t i)
{
int shift = i & 0xff;
if (shift >= 32) {
@@ -203,7 +192,7 @@ uint32_t HELPER(shl_cc)(uint32_t x, uint32_t i)
return x;
}
-uint32_t HELPER(shr_cc)(uint32_t x, uint32_t i)
+uint32_t HELPER(shr_cc)(CPUUniCore32State *env, uint32_t x, uint32_t i)
{
int shift = i & 0xff;
if (shift >= 32) {
@@ -220,7 +209,7 @@ uint32_t HELPER(shr_cc)(uint32_t x, uint32_t i)
return x;
}
-uint32_t HELPER(sar_cc)(uint32_t x, uint32_t i)
+uint32_t HELPER(sar_cc)(CPUUniCore32State *env, uint32_t x, uint32_t i)
{
int shift = i & 0xff;
if (shift >= 32) {
@@ -233,7 +222,7 @@ uint32_t HELPER(sar_cc)(uint32_t x, uint32_t i)
return x;
}
-uint32_t HELPER(ror_cc)(uint32_t x, uint32_t i)
+uint32_t HELPER(ror_cc)(CPUUniCore32State *env, uint32_t x, uint32_t i)
{
int shift1, shift;
shift1 = i & 0xff;
@@ -264,16 +253,13 @@ uint32_t HELPER(ror_cc)(uint32_t x, uint32_t i)
#define SHIFT 3
#include "softmmu_template.h"
-void tlb_fill(CPUUniCore32State *env1, target_ulong addr, int is_write,
- int mmu_idx, uintptr_t retaddr)
+void tlb_fill(CPUUniCore32State *env, target_ulong addr, int is_write,
+ int mmu_idx, uintptr_t retaddr)
{
TranslationBlock *tb;
- CPUUniCore32State *saved_env;
unsigned long pc;
int ret;
- saved_env = env;
- env = env1;
ret = uc32_cpu_handle_mmu_fault(env, addr, is_write, mmu_idx);
if (unlikely(ret)) {
if (retaddr) {
@@ -287,6 +273,5 @@ void tlb_fill(CPUUniCore32State *env1, target_ulong addr, int is_write,
}
cpu_loop_exit(env);
}
- env = saved_env;
}
#endif
diff --git a/target-unicore32/translate.c b/target-unicore32/translate.c
index 188bf8c..b786a6b 100644
--- a/target-unicore32/translate.c
+++ b/target-unicore32/translate.c
@@ -253,7 +253,7 @@ static void disas_ocd_insn(CPUUniCore32State *env, DisasContext *s,
static inline void gen_set_asr(TCGv var, uint32_t mask)
{
TCGv tmp_mask = tcg_const_i32(mask);
- gen_helper_asr_write(var, tmp_mask);
+ gen_helper_asr_write(cpu_env, var, tmp_mask);
tcg_temp_free_i32(tmp_mask);
}
/* Set NZCV flags from the high 4 bits of var. */
@@ -263,7 +263,7 @@ static void gen_exception(int excp)
{
TCGv tmp = new_tmp();
tcg_gen_movi_i32(tmp, excp);
- gen_helper_exception(tmp);
+ gen_helper_exception(cpu_env, tmp);
dead_tmp(tmp);
}
@@ -416,16 +416,16 @@ static inline void gen_uc32_shift_reg(TCGv var, int shiftop,
if (flags) {
switch (shiftop) {
case 0:
- gen_helper_shl_cc(var, var, shift);
+ gen_helper_shl_cc(var, cpu_env, var, shift);
break;
case 1:
- gen_helper_shr_cc(var, var, shift);
+ gen_helper_shr_cc(var, cpu_env, var, shift);
break;
case 2:
- gen_helper_sar_cc(var, var, shift);
+ gen_helper_sar_cc(var, cpu_env, var, shift);
break;
case 3:
- gen_helper_ror_cc(var, var, shift);
+ gen_helper_ror_cc(var, cpu_env, var, shift);
break;
}
} else {
@@ -1323,11 +1323,11 @@ static void do_datap(CPUUniCore32State *env, DisasContext *s, uint32_t insn)
if (IS_USER(s)) {
ILLEGAL;
}
- gen_helper_sub_cc(tmp, tmp, tmp2);
+ gen_helper_sub_cc(tmp, cpu_env, tmp, tmp2);
gen_exception_return(s, tmp);
} else {
if (UCOP_SET_S) {
- gen_helper_sub_cc(tmp, tmp, tmp2);
+ gen_helper_sub_cc(tmp, cpu_env, tmp, tmp2);
} else {
tcg_gen_sub_i32(tmp, tmp, tmp2);
}
@@ -1336,7 +1336,7 @@ static void do_datap(CPUUniCore32State *env, DisasContext *s, uint32_t insn)
break;
case 0x03:
if (UCOP_SET_S) {
- gen_helper_sub_cc(tmp, tmp2, tmp);
+ gen_helper_sub_cc(tmp, cpu_env, tmp2, tmp);
} else {
tcg_gen_sub_i32(tmp, tmp2, tmp);
}
@@ -1344,7 +1344,7 @@ static void do_datap(CPUUniCore32State *env, DisasContext *s, uint32_t insn)
break;
case 0x04:
if (UCOP_SET_S) {
- gen_helper_add_cc(tmp, tmp, tmp2);
+ gen_helper_add_cc(tmp, cpu_env, tmp, tmp2);
} else {
tcg_gen_add_i32(tmp, tmp, tmp2);
}
@@ -1352,7 +1352,7 @@ static void do_datap(CPUUniCore32State *env, DisasContext *s, uint32_t insn)
break;
case 0x05:
if (UCOP_SET_S) {
- gen_helper_adc_cc(tmp, tmp, tmp2);
+ gen_helper_adc_cc(tmp, cpu_env, tmp, tmp2);
} else {
gen_add_carry(tmp, tmp, tmp2);
}
@@ -1360,7 +1360,7 @@ static void do_datap(CPUUniCore32State *env, DisasContext *s, uint32_t insn)
break;
case 0x06:
if (UCOP_SET_S) {
- gen_helper_sbc_cc(tmp, tmp, tmp2);
+ gen_helper_sbc_cc(tmp, cpu_env, tmp, tmp2);
} else {
gen_sub_carry(tmp, tmp, tmp2);
}
@@ -1368,7 +1368,7 @@ static void do_datap(CPUUniCore32State *env, DisasContext *s, uint32_t insn)
break;
case 0x07:
if (UCOP_SET_S) {
- gen_helper_sbc_cc(tmp, tmp2, tmp);
+ gen_helper_sbc_cc(tmp, cpu_env, tmp2, tmp);
} else {
gen_sub_carry(tmp, tmp2, tmp);
}
@@ -1390,13 +1390,13 @@ static void do_datap(CPUUniCore32State *env, DisasContext *s, uint32_t insn)
break;
case 0x0a:
if (UCOP_SET_S) {
- gen_helper_sub_cc(tmp, tmp, tmp2);
+ gen_helper_sub_cc(tmp, cpu_env, tmp, tmp2);
}
dead_tmp(tmp);
break;
case 0x0b:
if (UCOP_SET_S) {
- gen_helper_add_cc(tmp, tmp, tmp2);
+ gen_helper_add_cc(tmp, cpu_env, tmp, tmp2);
}
dead_tmp(tmp);
break;
@@ -1536,7 +1536,7 @@ static void do_misc(CPUUniCore32State *env, DisasContext *s, uint32_t insn)
tmp = load_cpu_field(bsr);
} else {
tmp = new_tmp();
- gen_helper_asr_read(tmp);
+ gen_helper_asr_read(tmp, cpu_env);
}
store_reg(s, UCOP_REG_D, tmp);
return;
@@ -1760,7 +1760,7 @@ static void do_ldst_m(CPUUniCore32State *env, DisasContext *s, uint32_t insn)
gen_bx(s, tmp);
} else if (user) {
tmp2 = tcg_const_i32(reg);
- gen_helper_set_user_reg(tmp2, tmp);
+ gen_helper_set_user_reg(cpu_env, tmp2, tmp);
tcg_temp_free_i32(tmp2);
dead_tmp(tmp);
} else if (reg == UCOP_REG_N) {
@@ -1778,7 +1778,7 @@ static void do_ldst_m(CPUUniCore32State *env, DisasContext *s, uint32_t insn)
} else if (user) {
tmp = new_tmp();
tmp2 = tcg_const_i32(reg);
- gen_helper_get_user_reg(tmp, tmp2);
+ gen_helper_get_user_reg(tmp, cpu_env, tmp2);
tcg_temp_free_i32(tmp2);
} else {
tmp = load_reg(s, reg);
@@ -1861,7 +1861,7 @@ static void disas_uc32_insn(CPUUniCore32State *env, DisasContext *s)
{
unsigned int insn;
- insn = ldl_code(s->pc);
+ insn = cpu_ldl_code(env, s->pc);
s->pc += 4;
/* UniCore instructions class:
--
1.7.12.1

View File

@ -0,0 +1,181 @@
From 140048c58e4ceb4f3bac87d7154d2731bb2bcd5d Mon Sep 17 00:00:00 2001
From: Blue Swirl <blauwirbel@gmail.com>
Date: Tue, 4 Sep 2012 20:08:34 +0000
Subject: [PATCH] target-arm: convert void helpers
Add an explicit CPUState parameter instead of relying on AREG0.
For easier review, convert only op helpers which don't return any value.
Signed-off-by: Blue Swirl <blauwirbel@gmail.com>
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
Signed-off-by: Michael Roth <mdroth@linux.vnet.ibm.com>
---
target-arm/helper.h | 8 ++++----
target-arm/op_helper.c | 20 ++++++++++----------
target-arm/translate.c | 8 ++++----
3 files changed, 18 insertions(+), 18 deletions(-)
diff --git a/target-arm/helper.h b/target-arm/helper.h
index 21e9cfe..106aacd 100644
--- a/target-arm/helper.h
+++ b/target-arm/helper.h
@@ -50,10 +50,10 @@ DEF_HELPER_2(usad8, i32, i32, i32)
DEF_HELPER_1(logicq_cc, i32, i64)
DEF_HELPER_3(sel_flags, i32, i32, i32, i32)
-DEF_HELPER_1(exception, void, i32)
-DEF_HELPER_0(wfi, void)
+DEF_HELPER_2(exception, void, env, i32)
+DEF_HELPER_1(wfi, void, env)
-DEF_HELPER_2(cpsr_write, void, i32, i32)
+DEF_HELPER_3(cpsr_write, void, env, i32, i32)
DEF_HELPER_0(cpsr_read, i32)
DEF_HELPER_3(v7m_msr, void, env, i32, i32)
@@ -68,7 +68,7 @@ DEF_HELPER_2(get_r13_banked, i32, env, i32)
DEF_HELPER_3(set_r13_banked, void, env, i32, i32)
DEF_HELPER_1(get_user_reg, i32, i32)
-DEF_HELPER_2(set_user_reg, void, i32, i32)
+DEF_HELPER_3(set_user_reg, void, env, i32, i32)
DEF_HELPER_1(vfp_get_fpscr, i32, env)
DEF_HELPER_2(vfp_set_fpscr, void, env, i32)
diff --git a/target-arm/op_helper.c b/target-arm/op_helper.c
index d77bfab..b1adce3 100644
--- a/target-arm/op_helper.c
+++ b/target-arm/op_helper.c
@@ -23,7 +23,7 @@
#define SIGNBIT (uint32_t)0x80000000
#define SIGNBIT64 ((uint64_t)1 << 63)
-static void raise_exception(int tt)
+static void raise_exception(CPUARMState *env, int tt)
{
env->exception_index = tt;
cpu_loop_exit(env);
@@ -93,7 +93,7 @@ void tlb_fill(CPUARMState *env1, target_ulong addr, int is_write, int mmu_idx,
cpu_restore_state(tb, env, retaddr);
}
}
- raise_exception(env->exception_index);
+ raise_exception(env, env->exception_index);
}
env = saved_env;
}
@@ -230,14 +230,14 @@ uint32_t HELPER(usat16)(uint32_t x, uint32_t shift)
return res;
}
-void HELPER(wfi)(void)
+void HELPER(wfi)(CPUARMState *env)
{
env->exception_index = EXCP_HLT;
env->halted = 1;
cpu_loop_exit(env);
}
-void HELPER(exception)(uint32_t excp)
+void HELPER(exception)(CPUARMState *env, uint32_t excp)
{
env->exception_index = excp;
cpu_loop_exit(env);
@@ -248,7 +248,7 @@ uint32_t HELPER(cpsr_read)(void)
return cpsr_read(env) & ~CPSR_EXEC;
}
-void HELPER(cpsr_write)(uint32_t val, uint32_t mask)
+void HELPER(cpsr_write)(CPUARMState *env, uint32_t val, uint32_t mask)
{
cpsr_write(env, val, mask);
}
@@ -271,7 +271,7 @@ uint32_t HELPER(get_user_reg)(uint32_t regno)
return val;
}
-void HELPER(set_user_reg)(uint32_t regno, uint32_t val)
+void HELPER(set_user_reg)(CPUARMState *env, uint32_t regno, uint32_t val)
{
if (regno == 13) {
env->banked_r13[0] = val;
@@ -290,7 +290,7 @@ void HELPER(set_cp_reg)(CPUARMState *env, void *rip, uint32_t value)
const ARMCPRegInfo *ri = rip;
int excp = ri->writefn(env, ri, value);
if (excp) {
- raise_exception(excp);
+ raise_exception(env, excp);
}
}
@@ -300,7 +300,7 @@ uint32_t HELPER(get_cp_reg)(CPUARMState *env, void *rip)
uint64_t value;
int excp = ri->readfn(env, ri, &value);
if (excp) {
- raise_exception(excp);
+ raise_exception(env, excp);
}
return value;
}
@@ -310,7 +310,7 @@ void HELPER(set_cp_reg64)(CPUARMState *env, void *rip, uint64_t value)
const ARMCPRegInfo *ri = rip;
int excp = ri->writefn(env, ri, value);
if (excp) {
- raise_exception(excp);
+ raise_exception(env, excp);
}
}
@@ -320,7 +320,7 @@ uint64_t HELPER(get_cp_reg64)(CPUARMState *env, void *rip)
uint64_t value;
int excp = ri->readfn(env, ri, &value);
if (excp) {
- raise_exception(excp);
+ raise_exception(env, excp);
}
return value;
}
diff --git a/target-arm/translate.c b/target-arm/translate.c
index edef79a..6f651d9 100644
--- a/target-arm/translate.c
+++ b/target-arm/translate.c
@@ -199,7 +199,7 @@ static void store_reg(DisasContext *s, int reg, TCGv var)
static inline void gen_set_cpsr(TCGv var, uint32_t mask)
{
TCGv tmp_mask = tcg_const_i32(mask);
- gen_helper_cpsr_write(var, tmp_mask);
+ gen_helper_cpsr_write(cpu_env, var, tmp_mask);
tcg_temp_free_i32(tmp_mask);
}
/* Set NZCV flags from the high 4 bits of var. */
@@ -209,7 +209,7 @@ static void gen_exception(int excp)
{
TCGv tmp = tcg_temp_new_i32();
tcg_gen_movi_i32(tmp, excp);
- gen_helper_exception(tmp);
+ gen_helper_exception(cpu_env, tmp);
tcg_temp_free_i32(tmp);
}
@@ -7719,7 +7719,7 @@ static void disas_arm_insn(CPUARMState * env, DisasContext *s)
tmp = gen_ld32(addr, IS_USER(s));
if (user) {
tmp2 = tcg_const_i32(i);
- gen_helper_set_user_reg(tmp2, tmp);
+ gen_helper_set_user_reg(cpu_env, tmp2, tmp);
tcg_temp_free_i32(tmp2);
tcg_temp_free_i32(tmp);
} else if (i == rn) {
@@ -9913,7 +9913,7 @@ static inline void gen_intermediate_code_internal(CPUARMState *env,
/* nothing more to generate */
break;
case DISAS_WFI:
- gen_helper_wfi();
+ gen_helper_wfi(cpu_env);
break;
case DISAS_SWI:
gen_exception(EXCP_SWI);
--
1.7.12.1

View File

@ -0,0 +1,821 @@
From 18e713cf6b5ae2e7c48bb412c959c10322bef5e5 Mon Sep 17 00:00:00 2001
From: Blue Swirl <blauwirbel@gmail.com>
Date: Tue, 4 Sep 2012 20:19:15 +0000
Subject: [PATCH] target-arm: convert remaining helpers
Convert remaining helpers to AREG0 free mode: add an explicit
CPUState parameter instead of relying on AREG0.
Signed-off-by: Blue Swirl <blauwirbel@gmail.com>
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
Signed-off-by: Michael Roth <mdroth@linux.vnet.ibm.com>
---
target-arm/helper.h | 52 +++++++++----------
target-arm/op_helper.c | 64 +++++++++++------------
target-arm/translate.c | 134 ++++++++++++++++++++++++-------------------------
3 files changed, 125 insertions(+), 125 deletions(-)
diff --git a/target-arm/helper.h b/target-arm/helper.h
index 106aacd..afdb2b5 100644
--- a/target-arm/helper.h
+++ b/target-arm/helper.h
@@ -4,12 +4,12 @@ DEF_HELPER_1(clz, i32, i32)
DEF_HELPER_1(sxtb16, i32, i32)
DEF_HELPER_1(uxtb16, i32, i32)
-DEF_HELPER_2(add_setq, i32, i32, i32)
-DEF_HELPER_2(add_saturate, i32, i32, i32)
-DEF_HELPER_2(sub_saturate, i32, i32, i32)
-DEF_HELPER_2(add_usaturate, i32, i32, i32)
-DEF_HELPER_2(sub_usaturate, i32, i32, i32)
-DEF_HELPER_1(double_saturate, i32, s32)
+DEF_HELPER_3(add_setq, i32, env, i32, i32)
+DEF_HELPER_3(add_saturate, i32, env, i32, i32)
+DEF_HELPER_3(sub_saturate, i32, env, i32, i32)
+DEF_HELPER_3(add_usaturate, i32, env, i32, i32)
+DEF_HELPER_3(sub_usaturate, i32, env, i32, i32)
+DEF_HELPER_2(double_saturate, i32, env, s32)
DEF_HELPER_2(sdiv, s32, s32, s32)
DEF_HELPER_2(udiv, i32, i32, i32)
DEF_HELPER_1(rbit, i32, i32)
@@ -40,10 +40,10 @@ PAS_OP(uq)
PAS_OP(uh)
#undef PAS_OP
-DEF_HELPER_2(ssat, i32, i32, i32)
-DEF_HELPER_2(usat, i32, i32, i32)
-DEF_HELPER_2(ssat16, i32, i32, i32)
-DEF_HELPER_2(usat16, i32, i32, i32)
+DEF_HELPER_3(ssat, i32, env, i32, i32)
+DEF_HELPER_3(usat, i32, env, i32, i32)
+DEF_HELPER_3(ssat16, i32, env, i32, i32)
+DEF_HELPER_3(usat16, i32, env, i32, i32)
DEF_HELPER_2(usad8, i32, i32, i32)
@@ -54,7 +54,7 @@ DEF_HELPER_2(exception, void, env, i32)
DEF_HELPER_1(wfi, void, env)
DEF_HELPER_3(cpsr_write, void, env, i32, i32)
-DEF_HELPER_0(cpsr_read, i32)
+DEF_HELPER_1(cpsr_read, i32, env)
DEF_HELPER_3(v7m_msr, void, env, i32, i32)
DEF_HELPER_2(v7m_mrs, i32, env, i32)
@@ -67,7 +67,7 @@ DEF_HELPER_2(get_cp_reg64, i64, env, ptr)
DEF_HELPER_2(get_r13_banked, i32, env, i32)
DEF_HELPER_3(set_r13_banked, void, env, i32, i32)
-DEF_HELPER_1(get_user_reg, i32, i32)
+DEF_HELPER_2(get_user_reg, i32, env, i32)
DEF_HELPER_3(set_user_reg, void, env, i32, i32)
DEF_HELPER_1(vfp_get_fpscr, i32, env)
@@ -140,20 +140,20 @@ DEF_HELPER_2(recpe_f32, f32, f32, env)
DEF_HELPER_2(rsqrte_f32, f32, f32, env)
DEF_HELPER_2(recpe_u32, i32, i32, env)
DEF_HELPER_2(rsqrte_u32, i32, i32, env)
-DEF_HELPER_4(neon_tbl, i32, i32, i32, i32, i32)
-
-DEF_HELPER_2(add_cc, i32, i32, i32)
-DEF_HELPER_2(adc_cc, i32, i32, i32)
-DEF_HELPER_2(sub_cc, i32, i32, i32)
-DEF_HELPER_2(sbc_cc, i32, i32, i32)
-
-DEF_HELPER_2(shl, i32, i32, i32)
-DEF_HELPER_2(shr, i32, i32, i32)
-DEF_HELPER_2(sar, i32, i32, i32)
-DEF_HELPER_2(shl_cc, i32, i32, i32)
-DEF_HELPER_2(shr_cc, i32, i32, i32)
-DEF_HELPER_2(sar_cc, i32, i32, i32)
-DEF_HELPER_2(ror_cc, i32, i32, i32)
+DEF_HELPER_5(neon_tbl, i32, env, i32, i32, i32, i32)
+
+DEF_HELPER_3(add_cc, i32, env, i32, i32)
+DEF_HELPER_3(adc_cc, i32, env, i32, i32)
+DEF_HELPER_3(sub_cc, i32, env, i32, i32)
+DEF_HELPER_3(sbc_cc, i32, env, i32, i32)
+
+DEF_HELPER_3(shl, i32, env, i32, i32)
+DEF_HELPER_3(shr, i32, env, i32, i32)
+DEF_HELPER_3(sar, i32, env, i32, i32)
+DEF_HELPER_3(shl_cc, i32, env, i32, i32)
+DEF_HELPER_3(shr_cc, i32, env, i32, i32)
+DEF_HELPER_3(sar_cc, i32, env, i32, i32)
+DEF_HELPER_3(ror_cc, i32, env, i32, i32)
/* neon_helper.c */
DEF_HELPER_3(neon_qadd_u8, i32, env, i32, i32)
diff --git a/target-arm/op_helper.c b/target-arm/op_helper.c
index b1adce3..5b868bf 100644
--- a/target-arm/op_helper.c
+++ b/target-arm/op_helper.c
@@ -29,7 +29,7 @@ static void raise_exception(CPUARMState *env, int tt)
cpu_loop_exit(env);
}
-uint32_t HELPER(neon_tbl)(uint32_t ireg, uint32_t def,
+uint32_t HELPER(neon_tbl)(CPUARMState *env, uint32_t ireg, uint32_t def,
uint32_t rn, uint32_t maxindex)
{
uint32_t val;
@@ -101,7 +101,7 @@ void tlb_fill(CPUARMState *env1, target_ulong addr, int is_write, int mmu_idx,
/* FIXME: Pass an explicit pointer to QF to CPUARMState, and move saturating
instructions into helper.c */
-uint32_t HELPER(add_setq)(uint32_t a, uint32_t b)
+uint32_t HELPER(add_setq)(CPUARMState *env, uint32_t a, uint32_t b)
{
uint32_t res = a + b;
if (((res ^ a) & SIGNBIT) && !((a ^ b) & SIGNBIT))
@@ -109,7 +109,7 @@ uint32_t HELPER(add_setq)(uint32_t a, uint32_t b)
return res;
}
-uint32_t HELPER(add_saturate)(uint32_t a, uint32_t b)
+uint32_t HELPER(add_saturate)(CPUARMState *env, uint32_t a, uint32_t b)
{
uint32_t res = a + b;
if (((res ^ a) & SIGNBIT) && !((a ^ b) & SIGNBIT)) {
@@ -119,7 +119,7 @@ uint32_t HELPER(add_saturate)(uint32_t a, uint32_t b)
return res;
}
-uint32_t HELPER(sub_saturate)(uint32_t a, uint32_t b)
+uint32_t HELPER(sub_saturate)(CPUARMState *env, uint32_t a, uint32_t b)
{
uint32_t res = a - b;
if (((res ^ a) & SIGNBIT) && ((a ^ b) & SIGNBIT)) {
@@ -129,7 +129,7 @@ uint32_t HELPER(sub_saturate)(uint32_t a, uint32_t b)
return res;
}
-uint32_t HELPER(double_saturate)(int32_t val)
+uint32_t HELPER(double_saturate)(CPUARMState *env, int32_t val)
{
uint32_t res;
if (val >= 0x40000000) {
@@ -144,7 +144,7 @@ uint32_t HELPER(double_saturate)(int32_t val)
return res;
}
-uint32_t HELPER(add_usaturate)(uint32_t a, uint32_t b)
+uint32_t HELPER(add_usaturate)(CPUARMState *env, uint32_t a, uint32_t b)
{
uint32_t res = a + b;
if (res < a) {
@@ -154,7 +154,7 @@ uint32_t HELPER(add_usaturate)(uint32_t a, uint32_t b)
return res;
}
-uint32_t HELPER(sub_usaturate)(uint32_t a, uint32_t b)
+uint32_t HELPER(sub_usaturate)(CPUARMState *env, uint32_t a, uint32_t b)
{
uint32_t res = a - b;
if (res > a) {
@@ -165,7 +165,7 @@ uint32_t HELPER(sub_usaturate)(uint32_t a, uint32_t b)
}
/* Signed saturation. */
-static inline uint32_t do_ssat(int32_t val, int shift)
+static inline uint32_t do_ssat(CPUARMState *env, int32_t val, int shift)
{
int32_t top;
uint32_t mask;
@@ -183,7 +183,7 @@ static inline uint32_t do_ssat(int32_t val, int shift)
}
/* Unsigned saturation. */
-static inline uint32_t do_usat(int32_t val, int shift)
+static inline uint32_t do_usat(CPUARMState *env, int32_t val, int shift)
{
uint32_t max;
@@ -199,34 +199,34 @@ static inline uint32_t do_usat(int32_t val, int shift)
}
/* Signed saturate. */
-uint32_t HELPER(ssat)(uint32_t x, uint32_t shift)
+uint32_t HELPER(ssat)(CPUARMState *env, uint32_t x, uint32_t shift)
{
- return do_ssat(x, shift);
+ return do_ssat(env, x, shift);
}
/* Dual halfword signed saturate. */
-uint32_t HELPER(ssat16)(uint32_t x, uint32_t shift)
+uint32_t HELPER(ssat16)(CPUARMState *env, uint32_t x, uint32_t shift)
{
uint32_t res;
- res = (uint16_t)do_ssat((int16_t)x, shift);
- res |= do_ssat(((int32_t)x) >> 16, shift) << 16;
+ res = (uint16_t)do_ssat(env, (int16_t)x, shift);
+ res |= do_ssat(env, ((int32_t)x) >> 16, shift) << 16;
return res;
}
/* Unsigned saturate. */
-uint32_t HELPER(usat)(uint32_t x, uint32_t shift)
+uint32_t HELPER(usat)(CPUARMState *env, uint32_t x, uint32_t shift)
{
- return do_usat(x, shift);
+ return do_usat(env, x, shift);
}
/* Dual halfword unsigned saturate. */
-uint32_t HELPER(usat16)(uint32_t x, uint32_t shift)
+uint32_t HELPER(usat16)(CPUARMState *env, uint32_t x, uint32_t shift)
{
uint32_t res;
- res = (uint16_t)do_usat((int16_t)x, shift);
- res |= do_usat(((int32_t)x) >> 16, shift) << 16;
+ res = (uint16_t)do_usat(env, (int16_t)x, shift);
+ res |= do_usat(env, ((int32_t)x) >> 16, shift) << 16;
return res;
}
@@ -243,7 +243,7 @@ void HELPER(exception)(CPUARMState *env, uint32_t excp)
cpu_loop_exit(env);
}
-uint32_t HELPER(cpsr_read)(void)
+uint32_t HELPER(cpsr_read)(CPUARMState *env)
{
return cpsr_read(env) & ~CPSR_EXEC;
}
@@ -254,7 +254,7 @@ void HELPER(cpsr_write)(CPUARMState *env, uint32_t val, uint32_t mask)
}
/* Access to user mode registers from privileged modes. */
-uint32_t HELPER(get_user_reg)(uint32_t regno)
+uint32_t HELPER(get_user_reg)(CPUARMState *env, uint32_t regno)
{
uint32_t val;
@@ -329,7 +329,7 @@ uint64_t HELPER(get_cp_reg64)(CPUARMState *env, void *rip)
The only way to do that in TCG is a conditional branch, which clobbers
all our temporaries. For now implement these as helper functions. */
-uint32_t HELPER (add_cc)(uint32_t a, uint32_t b)
+uint32_t HELPER (add_cc)(CPUARMState *env, uint32_t a, uint32_t b)
{
uint32_t result;
result = a + b;
@@ -339,7 +339,7 @@ uint32_t HELPER (add_cc)(uint32_t a, uint32_t b)
return result;
}
-uint32_t HELPER(adc_cc)(uint32_t a, uint32_t b)
+uint32_t HELPER(adc_cc)(CPUARMState *env, uint32_t a, uint32_t b)
{
uint32_t result;
if (!env->CF) {
@@ -354,7 +354,7 @@ uint32_t HELPER(adc_cc)(uint32_t a, uint32_t b)
return result;
}
-uint32_t HELPER(sub_cc)(uint32_t a, uint32_t b)
+uint32_t HELPER(sub_cc)(CPUARMState *env, uint32_t a, uint32_t b)
{
uint32_t result;
result = a - b;
@@ -364,7 +364,7 @@ uint32_t HELPER(sub_cc)(uint32_t a, uint32_t b)
return result;
}
-uint32_t HELPER(sbc_cc)(uint32_t a, uint32_t b)
+uint32_t HELPER(sbc_cc)(CPUARMState *env, uint32_t a, uint32_t b)
{
uint32_t result;
if (!env->CF) {
@@ -381,7 +381,7 @@ uint32_t HELPER(sbc_cc)(uint32_t a, uint32_t b)
/* Similarly for variable shift instructions. */
-uint32_t HELPER(shl)(uint32_t x, uint32_t i)
+uint32_t HELPER(shl)(CPUARMState *env, uint32_t x, uint32_t i)
{
int shift = i & 0xff;
if (shift >= 32)
@@ -389,7 +389,7 @@ uint32_t HELPER(shl)(uint32_t x, uint32_t i)
return x << shift;
}
-uint32_t HELPER(shr)(uint32_t x, uint32_t i)
+uint32_t HELPER(shr)(CPUARMState *env, uint32_t x, uint32_t i)
{
int shift = i & 0xff;
if (shift >= 32)
@@ -397,7 +397,7 @@ uint32_t HELPER(shr)(uint32_t x, uint32_t i)
return (uint32_t)x >> shift;
}
-uint32_t HELPER(sar)(uint32_t x, uint32_t i)
+uint32_t HELPER(sar)(CPUARMState *env, uint32_t x, uint32_t i)
{
int shift = i & 0xff;
if (shift >= 32)
@@ -405,7 +405,7 @@ uint32_t HELPER(sar)(uint32_t x, uint32_t i)
return (int32_t)x >> shift;
}
-uint32_t HELPER(shl_cc)(uint32_t x, uint32_t i)
+uint32_t HELPER(shl_cc)(CPUARMState *env, uint32_t x, uint32_t i)
{
int shift = i & 0xff;
if (shift >= 32) {
@@ -421,7 +421,7 @@ uint32_t HELPER(shl_cc)(uint32_t x, uint32_t i)
return x;
}
-uint32_t HELPER(shr_cc)(uint32_t x, uint32_t i)
+uint32_t HELPER(shr_cc)(CPUARMState *env, uint32_t x, uint32_t i)
{
int shift = i & 0xff;
if (shift >= 32) {
@@ -437,7 +437,7 @@ uint32_t HELPER(shr_cc)(uint32_t x, uint32_t i)
return x;
}
-uint32_t HELPER(sar_cc)(uint32_t x, uint32_t i)
+uint32_t HELPER(sar_cc)(CPUARMState *env, uint32_t x, uint32_t i)
{
int shift = i & 0xff;
if (shift >= 32) {
@@ -450,7 +450,7 @@ uint32_t HELPER(sar_cc)(uint32_t x, uint32_t i)
return x;
}
-uint32_t HELPER(ror_cc)(uint32_t x, uint32_t i)
+uint32_t HELPER(ror_cc)(CPUARMState *env, uint32_t x, uint32_t i)
{
int shift1, shift;
shift1 = i & 0xff;
diff --git a/target-arm/translate.c b/target-arm/translate.c
index 6f651d9..9ae3b26 100644
--- a/target-arm/translate.c
+++ b/target-arm/translate.c
@@ -490,16 +490,16 @@ static inline void gen_arm_shift_reg(TCGv var, int shiftop,
{
if (flags) {
switch (shiftop) {
- case 0: gen_helper_shl_cc(var, var, shift); break;
- case 1: gen_helper_shr_cc(var, var, shift); break;
- case 2: gen_helper_sar_cc(var, var, shift); break;
- case 3: gen_helper_ror_cc(var, var, shift); break;
+ case 0: gen_helper_shl_cc(var, cpu_env, var, shift); break;
+ case 1: gen_helper_shr_cc(var, cpu_env, var, shift); break;
+ case 2: gen_helper_sar_cc(var, cpu_env, var, shift); break;
+ case 3: gen_helper_ror_cc(var, cpu_env, var, shift); break;
}
} else {
switch (shiftop) {
- case 0: gen_helper_shl(var, var, shift); break;
- case 1: gen_helper_shr(var, var, shift); break;
- case 2: gen_helper_sar(var, var, shift); break;
+ case 0: gen_helper_shl(var, cpu_env, var, shift); break;
+ case 1: gen_helper_shr(var, cpu_env, var, shift); break;
+ case 2: gen_helper_sar(var, cpu_env, var, shift); break;
case 3: tcg_gen_andi_i32(shift, shift, 0x1f);
tcg_gen_rotr_i32(var, var, shift); break;
}
@@ -6121,7 +6121,7 @@ static int disas_neon_data_insn(CPUARMState * env, DisasContext *s, uint32_t ins
tmp2 = neon_load_reg(rm, 0);
tmp4 = tcg_const_i32(rn);
tmp5 = tcg_const_i32(n);
- gen_helper_neon_tbl(tmp2, tmp2, tmp, tmp4, tmp5);
+ gen_helper_neon_tbl(tmp2, cpu_env, tmp2, tmp, tmp4, tmp5);
tcg_temp_free_i32(tmp);
if (insn & (1 << 6)) {
tmp = neon_load_reg(rd, 1);
@@ -6130,7 +6130,7 @@ static int disas_neon_data_insn(CPUARMState * env, DisasContext *s, uint32_t ins
tcg_gen_movi_i32(tmp, 0);
}
tmp3 = neon_load_reg(rm, 1);
- gen_helper_neon_tbl(tmp3, tmp3, tmp, tmp4, tmp5);
+ gen_helper_neon_tbl(tmp3, cpu_env, tmp3, tmp, tmp4, tmp5);
tcg_temp_free_i32(tmp5);
tcg_temp_free_i32(tmp4);
neon_store_reg(rd, 0, tmp2);
@@ -6818,7 +6818,7 @@ static void disas_arm_insn(CPUARMState * env, DisasContext *s)
tmp = load_cpu_field(spsr);
} else {
tmp = tcg_temp_new_i32();
- gen_helper_cpsr_read(tmp);
+ gen_helper_cpsr_read(tmp, cpu_env);
}
store_reg(s, rd, tmp);
}
@@ -6869,11 +6869,11 @@ static void disas_arm_insn(CPUARMState * env, DisasContext *s)
tmp = load_reg(s, rm);
tmp2 = load_reg(s, rn);
if (op1 & 2)
- gen_helper_double_saturate(tmp2, tmp2);
+ gen_helper_double_saturate(tmp2, cpu_env, tmp2);
if (op1 & 1)
- gen_helper_sub_saturate(tmp, tmp, tmp2);
+ gen_helper_sub_saturate(tmp, cpu_env, tmp, tmp2);
else
- gen_helper_add_saturate(tmp, tmp, tmp2);
+ gen_helper_add_saturate(tmp, cpu_env, tmp, tmp2);
tcg_temp_free_i32(tmp2);
store_reg(s, rd, tmp);
break;
@@ -6911,7 +6911,7 @@ static void disas_arm_insn(CPUARMState * env, DisasContext *s)
tcg_temp_free_i64(tmp64);
if ((sh & 2) == 0) {
tmp2 = load_reg(s, rn);
- gen_helper_add_setq(tmp, tmp, tmp2);
+ gen_helper_add_setq(tmp, cpu_env, tmp, tmp2);
tcg_temp_free_i32(tmp2);
}
store_reg(s, rd, tmp);
@@ -6931,7 +6931,7 @@ static void disas_arm_insn(CPUARMState * env, DisasContext *s)
} else {
if (op1 == 0) {
tmp2 = load_reg(s, rn);
- gen_helper_add_setq(tmp, tmp, tmp2);
+ gen_helper_add_setq(tmp, cpu_env, tmp, tmp2);
tcg_temp_free_i32(tmp2);
}
store_reg(s, rd, tmp);
@@ -7005,11 +7005,11 @@ static void disas_arm_insn(CPUARMState * env, DisasContext *s)
if (IS_USER(s)) {
goto illegal_op;
}
- gen_helper_sub_cc(tmp, tmp, tmp2);
+ gen_helper_sub_cc(tmp, cpu_env, tmp, tmp2);
gen_exception_return(s, tmp);
} else {
if (set_cc) {
- gen_helper_sub_cc(tmp, tmp, tmp2);
+ gen_helper_sub_cc(tmp, cpu_env, tmp, tmp2);
} else {
tcg_gen_sub_i32(tmp, tmp, tmp2);
}
@@ -7018,7 +7018,7 @@ static void disas_arm_insn(CPUARMState * env, DisasContext *s)
break;
case 0x03:
if (set_cc) {
- gen_helper_sub_cc(tmp, tmp2, tmp);
+ gen_helper_sub_cc(tmp, cpu_env, tmp2, tmp);
} else {
tcg_gen_sub_i32(tmp, tmp2, tmp);
}
@@ -7026,7 +7026,7 @@ static void disas_arm_insn(CPUARMState * env, DisasContext *s)
break;
case 0x04:
if (set_cc) {
- gen_helper_add_cc(tmp, tmp, tmp2);
+ gen_helper_add_cc(tmp, cpu_env, tmp, tmp2);
} else {
tcg_gen_add_i32(tmp, tmp, tmp2);
}
@@ -7034,7 +7034,7 @@ static void disas_arm_insn(CPUARMState * env, DisasContext *s)
break;
case 0x05:
if (set_cc) {
- gen_helper_adc_cc(tmp, tmp, tmp2);
+ gen_helper_adc_cc(tmp, cpu_env, tmp, tmp2);
} else {
gen_add_carry(tmp, tmp, tmp2);
}
@@ -7042,7 +7042,7 @@ static void disas_arm_insn(CPUARMState * env, DisasContext *s)
break;
case 0x06:
if (set_cc) {
- gen_helper_sbc_cc(tmp, tmp, tmp2);
+ gen_helper_sbc_cc(tmp, cpu_env, tmp, tmp2);
} else {
gen_sub_carry(tmp, tmp, tmp2);
}
@@ -7050,7 +7050,7 @@ static void disas_arm_insn(CPUARMState * env, DisasContext *s)
break;
case 0x07:
if (set_cc) {
- gen_helper_sbc_cc(tmp, tmp2, tmp);
+ gen_helper_sbc_cc(tmp, cpu_env, tmp2, tmp);
} else {
gen_sub_carry(tmp, tmp2, tmp);
}
@@ -7072,13 +7072,13 @@ static void disas_arm_insn(CPUARMState * env, DisasContext *s)
break;
case 0x0a:
if (set_cc) {
- gen_helper_sub_cc(tmp, tmp, tmp2);
+ gen_helper_sub_cc(tmp, cpu_env, tmp, tmp2);
}
tcg_temp_free_i32(tmp);
break;
case 0x0b:
if (set_cc) {
- gen_helper_add_cc(tmp, tmp, tmp2);
+ gen_helper_add_cc(tmp, cpu_env, tmp, tmp2);
}
tcg_temp_free_i32(tmp);
break;
@@ -7395,9 +7395,9 @@ static void disas_arm_insn(CPUARMState * env, DisasContext *s)
sh = (insn >> 16) & 0x1f;
tmp2 = tcg_const_i32(sh);
if (insn & (1 << 22))
- gen_helper_usat(tmp, tmp, tmp2);
+ gen_helper_usat(tmp, cpu_env, tmp, tmp2);
else
- gen_helper_ssat(tmp, tmp, tmp2);
+ gen_helper_ssat(tmp, cpu_env, tmp, tmp2);
tcg_temp_free_i32(tmp2);
store_reg(s, rd, tmp);
} else if ((insn & 0x00300fe0) == 0x00200f20) {
@@ -7406,9 +7406,9 @@ static void disas_arm_insn(CPUARMState * env, DisasContext *s)
sh = (insn >> 16) & 0x1f;
tmp2 = tcg_const_i32(sh);
if (insn & (1 << 22))
- gen_helper_usat16(tmp, tmp, tmp2);
+ gen_helper_usat16(tmp, cpu_env, tmp, tmp2);
else
- gen_helper_ssat16(tmp, tmp, tmp2);
+ gen_helper_ssat16(tmp, cpu_env, tmp, tmp2);
tcg_temp_free_i32(tmp2);
store_reg(s, rd, tmp);
} else if ((insn & 0x00700fe0) == 0x00000fa0) {
@@ -7518,7 +7518,7 @@ static void disas_arm_insn(CPUARMState * env, DisasContext *s)
* however it may overflow considered as a signed
* operation, in which case we must set the Q flag.
*/
- gen_helper_add_setq(tmp, tmp, tmp2);
+ gen_helper_add_setq(tmp, cpu_env, tmp, tmp2);
}
tcg_temp_free_i32(tmp2);
if (insn & (1 << 22)) {
@@ -7534,7 +7534,7 @@ static void disas_arm_insn(CPUARMState * env, DisasContext *s)
if (rd != 15)
{
tmp2 = load_reg(s, rd);
- gen_helper_add_setq(tmp, tmp, tmp2);
+ gen_helper_add_setq(tmp, cpu_env, tmp, tmp2);
tcg_temp_free_i32(tmp2);
}
store_reg(s, rn, tmp);
@@ -7738,7 +7738,7 @@ static void disas_arm_insn(CPUARMState * env, DisasContext *s)
} else if (user) {
tmp = tcg_temp_new_i32();
tmp2 = tcg_const_i32(i);
- gen_helper_get_user_reg(tmp, tmp2);
+ gen_helper_get_user_reg(tmp, cpu_env, tmp2);
tcg_temp_free_i32(tmp2);
} else {
tmp = load_reg(s, i);
@@ -7865,31 +7865,31 @@ gen_thumb2_data_op(DisasContext *s, int op, int conds, uint32_t shifter_out, TCG
break;
case 8: /* add */
if (conds)
- gen_helper_add_cc(t0, t0, t1);
+ gen_helper_add_cc(t0, cpu_env, t0, t1);
else
tcg_gen_add_i32(t0, t0, t1);
break;
case 10: /* adc */
if (conds)
- gen_helper_adc_cc(t0, t0, t1);
+ gen_helper_adc_cc(t0, cpu_env, t0, t1);
else
gen_adc(t0, t1);
break;
case 11: /* sbc */
if (conds)
- gen_helper_sbc_cc(t0, t0, t1);
+ gen_helper_sbc_cc(t0, cpu_env, t0, t1);
else
gen_sub_carry(t0, t0, t1);
break;
case 13: /* sub */
if (conds)
- gen_helper_sub_cc(t0, t0, t1);
+ gen_helper_sub_cc(t0, cpu_env, t0, t1);
else
tcg_gen_sub_i32(t0, t0, t1);
break;
case 14: /* rsb */
if (conds)
- gen_helper_sub_cc(t0, t1, t0);
+ gen_helper_sub_cc(t0, cpu_env, t1, t0);
else
tcg_gen_sub_i32(t0, t1, t0);
break;
@@ -8111,7 +8111,7 @@ static int disas_thumb2_insn(CPUARMState *env, DisasContext *s, uint16_t insn_hw
gen_st32(tmp, addr, 0);
tcg_gen_addi_i32(addr, addr, 4);
tmp = tcg_temp_new_i32();
- gen_helper_cpsr_read(tmp);
+ gen_helper_cpsr_read(tmp, cpu_env);
gen_st32(tmp, addr, 0);
if (insn & (1 << 21)) {
if ((insn & (1 << 24)) == 0) {
@@ -8293,11 +8293,11 @@ static int disas_thumb2_insn(CPUARMState *env, DisasContext *s, uint16_t insn_hw
tmp = load_reg(s, rn);
tmp2 = load_reg(s, rm);
if (op & 1)
- gen_helper_double_saturate(tmp, tmp);
+ gen_helper_double_saturate(tmp, cpu_env, tmp);
if (op & 2)
- gen_helper_sub_saturate(tmp, tmp2, tmp);
+ gen_helper_sub_saturate(tmp, cpu_env, tmp2, tmp);
else
- gen_helper_add_saturate(tmp, tmp, tmp2);
+ gen_helper_add_saturate(tmp, cpu_env, tmp, tmp2);
tcg_temp_free_i32(tmp2);
} else {
tmp = load_reg(s, rn);
@@ -8353,7 +8353,7 @@ static int disas_thumb2_insn(CPUARMState *env, DisasContext *s, uint16_t insn_hw
tcg_temp_free_i32(tmp2);
if (rs != 15) {
tmp2 = load_reg(s, rs);
- gen_helper_add_setq(tmp, tmp, tmp2);
+ gen_helper_add_setq(tmp, cpu_env, tmp, tmp2);
tcg_temp_free_i32(tmp2);
}
break;
@@ -8370,13 +8370,13 @@ static int disas_thumb2_insn(CPUARMState *env, DisasContext *s, uint16_t insn_hw
* however it may overflow considered as a signed
* operation, in which case we must set the Q flag.
*/
- gen_helper_add_setq(tmp, tmp, tmp2);
+ gen_helper_add_setq(tmp, cpu_env, tmp, tmp2);
}
tcg_temp_free_i32(tmp2);
if (rs != 15)
{
tmp2 = load_reg(s, rs);
- gen_helper_add_setq(tmp, tmp, tmp2);
+ gen_helper_add_setq(tmp, cpu_env, tmp, tmp2);
tcg_temp_free_i32(tmp2);
}
break;
@@ -8393,7 +8393,7 @@ static int disas_thumb2_insn(CPUARMState *env, DisasContext *s, uint16_t insn_hw
if (rs != 15)
{
tmp2 = load_reg(s, rs);
- gen_helper_add_setq(tmp, tmp, tmp2);
+ gen_helper_add_setq(tmp, cpu_env, tmp, tmp2);
tcg_temp_free_i32(tmp2);
}
break;
@@ -8632,7 +8632,7 @@ static int disas_thumb2_insn(CPUARMState *env, DisasContext *s, uint16_t insn_hw
gen_helper_v7m_mrs(tmp, cpu_env, addr);
tcg_temp_free_i32(addr);
} else {
- gen_helper_cpsr_read(tmp);
+ gen_helper_cpsr_read(tmp, cpu_env);
}
store_reg(s, rd, tmp);
break;
@@ -8721,15 +8721,15 @@ static int disas_thumb2_insn(CPUARMState *env, DisasContext *s, uint16_t insn_hw
if (op & 4) {
/* Unsigned. */
if ((op & 1) && shift == 0)
- gen_helper_usat16(tmp, tmp, tmp2);
+ gen_helper_usat16(tmp, cpu_env, tmp, tmp2);
else
- gen_helper_usat(tmp, tmp, tmp2);
+ gen_helper_usat(tmp, cpu_env, tmp, tmp2);
} else {
/* Signed. */
if ((op & 1) && shift == 0)
- gen_helper_ssat16(tmp, tmp, tmp2);
+ gen_helper_ssat16(tmp, cpu_env, tmp, tmp2);
else
- gen_helper_ssat(tmp, tmp, tmp2);
+ gen_helper_ssat(tmp, cpu_env, tmp, tmp2);
}
tcg_temp_free_i32(tmp2);
break;
@@ -9017,12 +9017,12 @@ static void disas_thumb_insn(CPUARMState *env, DisasContext *s)
if (s->condexec_mask)
tcg_gen_sub_i32(tmp, tmp, tmp2);
else
- gen_helper_sub_cc(tmp, tmp, tmp2);
+ gen_helper_sub_cc(tmp, cpu_env, tmp, tmp2);
} else {
if (s->condexec_mask)
tcg_gen_add_i32(tmp, tmp, tmp2);
else
- gen_helper_add_cc(tmp, tmp, tmp2);
+ gen_helper_add_cc(tmp, cpu_env, tmp, tmp2);
}
tcg_temp_free_i32(tmp2);
store_reg(s, rd, tmp);
@@ -9053,7 +9053,7 @@ static void disas_thumb_insn(CPUARMState *env, DisasContext *s)
tcg_gen_movi_i32(tmp2, insn & 0xff);
switch (op) {
case 1: /* cmp */
- gen_helper_sub_cc(tmp, tmp, tmp2);
+ gen_helper_sub_cc(tmp, cpu_env, tmp, tmp2);
tcg_temp_free_i32(tmp);
tcg_temp_free_i32(tmp2);
break;
@@ -9061,7 +9061,7 @@ static void disas_thumb_insn(CPUARMState *env, DisasContext *s)
if (s->condexec_mask)
tcg_gen_add_i32(tmp, tmp, tmp2);
else
- gen_helper_add_cc(tmp, tmp, tmp2);
+ gen_helper_add_cc(tmp, cpu_env, tmp, tmp2);
tcg_temp_free_i32(tmp2);
store_reg(s, rd, tmp);
break;
@@ -9069,7 +9069,7 @@ static void disas_thumb_insn(CPUARMState *env, DisasContext *s)
if (s->condexec_mask)
tcg_gen_sub_i32(tmp, tmp, tmp2);
else
- gen_helper_sub_cc(tmp, tmp, tmp2);
+ gen_helper_sub_cc(tmp, cpu_env, tmp, tmp2);
tcg_temp_free_i32(tmp2);
store_reg(s, rd, tmp);
break;
@@ -9105,7 +9105,7 @@ static void disas_thumb_insn(CPUARMState *env, DisasContext *s)
case 1: /* cmp */
tmp = load_reg(s, rd);
tmp2 = load_reg(s, rm);
- gen_helper_sub_cc(tmp, tmp, tmp2);
+ gen_helper_sub_cc(tmp, cpu_env, tmp, tmp2);
tcg_temp_free_i32(tmp2);
tcg_temp_free_i32(tmp);
break;
@@ -9166,25 +9166,25 @@ static void disas_thumb_insn(CPUARMState *env, DisasContext *s)
break;
case 0x2: /* lsl */
if (s->condexec_mask) {
- gen_helper_shl(tmp2, tmp2, tmp);
+ gen_helper_shl(tmp2, cpu_env, tmp2, tmp);
} else {
- gen_helper_shl_cc(tmp2, tmp2, tmp);
+ gen_helper_shl_cc(tmp2, cpu_env, tmp2, tmp);
gen_logic_CC(tmp2);
}
break;
case 0x3: /* lsr */
if (s->condexec_mask) {
- gen_helper_shr(tmp2, tmp2, tmp);
+ gen_helper_shr(tmp2, cpu_env, tmp2, tmp);
} else {
- gen_helper_shr_cc(tmp2, tmp2, tmp);
+ gen_helper_shr_cc(tmp2, cpu_env, tmp2, tmp);
gen_logic_CC(tmp2);
}
break;
case 0x4: /* asr */
if (s->condexec_mask) {
- gen_helper_sar(tmp2, tmp2, tmp);
+ gen_helper_sar(tmp2, cpu_env, tmp2, tmp);
} else {
- gen_helper_sar_cc(tmp2, tmp2, tmp);
+ gen_helper_sar_cc(tmp2, cpu_env, tmp2, tmp);
gen_logic_CC(tmp2);
}
break;
@@ -9192,20 +9192,20 @@ static void disas_thumb_insn(CPUARMState *env, DisasContext *s)
if (s->condexec_mask)
gen_adc(tmp, tmp2);
else
- gen_helper_adc_cc(tmp, tmp, tmp2);
+ gen_helper_adc_cc(tmp, cpu_env, tmp, tmp2);
break;
case 0x6: /* sbc */
if (s->condexec_mask)
gen_sub_carry(tmp, tmp, tmp2);
else
- gen_helper_sbc_cc(tmp, tmp, tmp2);
+ gen_helper_sbc_cc(tmp, cpu_env, tmp, tmp2);
break;
case 0x7: /* ror */
if (s->condexec_mask) {
tcg_gen_andi_i32(tmp, tmp, 0x1f);
tcg_gen_rotr_i32(tmp2, tmp2, tmp);
} else {
- gen_helper_ror_cc(tmp2, tmp2, tmp);
+ gen_helper_ror_cc(tmp2, cpu_env, tmp2, tmp);
gen_logic_CC(tmp2);
}
break;
@@ -9218,14 +9218,14 @@ static void disas_thumb_insn(CPUARMState *env, DisasContext *s)
if (s->condexec_mask)
tcg_gen_neg_i32(tmp, tmp2);
else
- gen_helper_sub_cc(tmp, tmp, tmp2);
+ gen_helper_sub_cc(tmp, cpu_env, tmp, tmp2);
break;
case 0xa: /* cmp */
- gen_helper_sub_cc(tmp, tmp, tmp2);
+ gen_helper_sub_cc(tmp, cpu_env, tmp, tmp2);
rd = 16;
break;
case 0xb: /* cmn */
- gen_helper_add_cc(tmp, tmp, tmp2);
+ gen_helper_add_cc(tmp, cpu_env, tmp, tmp2);
rd = 16;
break;
case 0xc: /* orr */
--
1.7.12.1

View File

@ -0,0 +1,179 @@
From 28b8f097f9fb107882aa51bd25ba87619beb033e Mon Sep 17 00:00:00 2001
From: Blue Swirl <blauwirbel@gmail.com>
Date: Tue, 4 Sep 2012 20:25:59 +0000
Subject: [PATCH] target-arm: final conversion to AREG0 free mode
Convert code load functions and switch to AREG0 free mode.
Signed-off-by: Blue Swirl <blauwirbel@gmail.com>
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
Signed-off-by: Michael Roth <mdroth@linux.vnet.ibm.com>
---
configure | 2 +-
target-arm/Makefile.objs | 2 --
target-arm/cpu.h | 10 ++++++----
target-arm/helper.c | 9 +++++----
target-arm/op_helper.c | 8 +-------
target-arm/translate.c | 6 +++---
6 files changed, 16 insertions(+), 21 deletions(-)
diff --git a/configure b/configure
index a8827ba..e8806f0 100755
--- a/configure
+++ b/configure
@@ -3839,7 +3839,7 @@ symlink "$source_path/Makefile.target" "$target_dir/Makefile"
case "$target_arch2" in
- alpha | i386 | lm32 | m68k | or32 | s390x | sparc* | unicore32 | x86_64 | xtensa* | ppc*)
+ alpha | arm* | i386 | lm32 | m68k | or32 | s390x | sparc* | unicore32 | x86_64 | xtensa* | ppc*)
echo "CONFIG_TCG_PASS_AREG0=y" >> $config_target_mak
;;
esac
diff --git a/target-arm/Makefile.objs b/target-arm/Makefile.objs
index f447c4f..b6f1a9e 100644
--- a/target-arm/Makefile.objs
+++ b/target-arm/Makefile.objs
@@ -2,5 +2,3 @@ obj-y += arm-semi.o
obj-$(CONFIG_SOFTMMU) += machine.o
obj-y += translate.o op_helper.o helper.o cpu.o
obj-y += neon_helper.o iwmmxt_helper.o
-
-$(obj)/op_helper.o: QEMU_CFLAGS += $(HELPER_CFLAGS)
diff --git a/target-arm/cpu.h b/target-arm/cpu.h
index d7f93d9..7fac94f 100644
--- a/target-arm/cpu.h
+++ b/target-arm/cpu.h
@@ -734,9 +734,10 @@ static inline void cpu_pc_from_tb(CPUARMState *env, TranslationBlock *tb)
}
/* Load an instruction and return it in the standard little-endian order */
-static inline uint32_t arm_ldl_code(uint32_t addr, bool do_swap)
+static inline uint32_t arm_ldl_code(CPUARMState *env, uint32_t addr,
+ bool do_swap)
{
- uint32_t insn = ldl_code(addr);
+ uint32_t insn = cpu_ldl_code(env, addr);
if (do_swap) {
return bswap32(insn);
}
@@ -744,9 +745,10 @@ static inline uint32_t arm_ldl_code(uint32_t addr, bool do_swap)
}
/* Ditto, for a halfword (Thumb) instruction */
-static inline uint16_t arm_lduw_code(uint32_t addr, bool do_swap)
+static inline uint16_t arm_lduw_code(CPUARMState *env, uint32_t addr,
+ bool do_swap)
{
- uint16_t insn = lduw_code(addr);
+ uint16_t insn = cpu_lduw_code(env, addr);
if (do_swap) {
return bswap16(insn);
}
diff --git a/target-arm/helper.c b/target-arm/helper.c
index e27df96..58340bd 100644
--- a/target-arm/helper.c
+++ b/target-arm/helper.c
@@ -1756,7 +1756,7 @@ static void do_interrupt_v7m(CPUARMState *env)
case EXCP_BKPT:
if (semihosting_enabled) {
int nr;
- nr = arm_lduw_code(env->regs[15], env->bswap_code) & 0xff;
+ nr = arm_lduw_code(env, env->regs[15], env->bswap_code) & 0xff;
if (nr == 0xab) {
env->regs[15] += 2;
env->regs[0] = do_arm_semihosting(env);
@@ -1828,9 +1828,10 @@ void do_interrupt(CPUARMState *env)
if (semihosting_enabled) {
/* Check for semihosting interrupt. */
if (env->thumb) {
- mask = arm_lduw_code(env->regs[15] - 2, env->bswap_code) & 0xff;
+ mask = arm_lduw_code(env, env->regs[15] - 2, env->bswap_code)
+ & 0xff;
} else {
- mask = arm_ldl_code(env->regs[15] - 4, env->bswap_code)
+ mask = arm_ldl_code(env, env->regs[15] - 4, env->bswap_code)
& 0xffffff;
}
/* Only intercept calls from privileged modes, to provide some
@@ -1851,7 +1852,7 @@ void do_interrupt(CPUARMState *env)
case EXCP_BKPT:
/* See if this is a semihosting syscall. */
if (env->thumb && semihosting_enabled) {
- mask = arm_lduw_code(env->regs[15], env->bswap_code) & 0xff;
+ mask = arm_lduw_code(env, env->regs[15], env->bswap_code) & 0xff;
if (mask == 0xab
&& (env->uncached_cpsr & CPSR_M) != ARM_CPU_MODE_USR) {
env->regs[15] += 2;
diff --git a/target-arm/op_helper.c b/target-arm/op_helper.c
index 5b868bf..f13fc3a 100644
--- a/target-arm/op_helper.c
+++ b/target-arm/op_helper.c
@@ -17,7 +17,6 @@
* License along with this library; if not, see <http://www.gnu.org/licenses/>.
*/
#include "cpu.h"
-#include "dyngen-exec.h"
#include "helper.h"
#define SIGNBIT (uint32_t)0x80000000
@@ -72,16 +71,12 @@ uint32_t HELPER(neon_tbl)(CPUARMState *env, uint32_t ireg, uint32_t def,
/* try to fill the TLB and return an exception if error. If retaddr is
NULL, it means that the function was called in C code (i.e. not
from generated code or from helper.c) */
-/* XXX: fix it to restore all registers */
-void tlb_fill(CPUARMState *env1, target_ulong addr, int is_write, int mmu_idx,
+void tlb_fill(CPUARMState *env, target_ulong addr, int is_write, int mmu_idx,
uintptr_t retaddr)
{
TranslationBlock *tb;
- CPUARMState *saved_env;
int ret;
- saved_env = env;
- env = env1;
ret = cpu_arm_handle_mmu_fault(env, addr, is_write, mmu_idx);
if (unlikely(ret)) {
if (retaddr) {
@@ -95,7 +90,6 @@ void tlb_fill(CPUARMState *env1, target_ulong addr, int is_write, int mmu_idx,
}
raise_exception(env, env->exception_index);
}
- env = saved_env;
}
#endif
diff --git a/target-arm/translate.c b/target-arm/translate.c
index 9ae3b26..f4b447a 100644
--- a/target-arm/translate.c
+++ b/target-arm/translate.c
@@ -6534,7 +6534,7 @@ static void disas_arm_insn(CPUARMState * env, DisasContext *s)
TCGv addr;
TCGv_i64 tmp64;
- insn = arm_ldl_code(s->pc, s->bswap_code);
+ insn = arm_ldl_code(env, s->pc, s->bswap_code);
s->pc += 4;
/* M variants do not implement ARM mode. */
@@ -7962,7 +7962,7 @@ static int disas_thumb2_insn(CPUARMState *env, DisasContext *s, uint16_t insn_hw
/* Fall through to 32-bit decode. */
}
- insn = arm_lduw_code(s->pc, s->bswap_code);
+ insn = arm_lduw_code(env, s->pc, s->bswap_code);
s->pc += 2;
insn |= (uint32_t)insn_hw1 << 16;
@@ -8992,7 +8992,7 @@ static void disas_thumb_insn(CPUARMState *env, DisasContext *s)
}
}
- insn = arm_lduw_code(s->pc, s->bswap_code);
+ insn = arm_lduw_code(env, s->pc, s->bswap_code);
s->pc += 2;
switch (insn >> 12) {
--
1.7.12.1

View File

@ -0,0 +1,715 @@
From 449d4f2cfbdd2b5fd00e3e82c78bf580bd81551d Mon Sep 17 00:00:00 2001
From: Blue Swirl <blauwirbel@gmail.com>
Date: Sun, 2 Sep 2012 08:39:22 +0000
Subject: [PATCH] target-microblaze: switch to AREG0 free mode
Add an explicit CPUState parameter instead of relying on AREG0
and switch to AREG0 free mode.
Signed-off-by: Blue Swirl <blauwirbel@gmail.com>
Signed-off-by: Michael Roth <mdroth@linux.vnet.ibm.com>
---
configure | 2 +-
target-microblaze/Makefile.objs | 2 -
target-microblaze/helper.h | 48 ++++++++---------
target-microblaze/op_helper.c | 115 ++++++++++++++++++----------------------
target-microblaze/translate.c | 61 +++++++++++----------
5 files changed, 110 insertions(+), 118 deletions(-)
diff --git a/configure b/configure
index e8806f0..0b4ef4a 100755
--- a/configure
+++ b/configure
@@ -3839,7 +3839,7 @@ symlink "$source_path/Makefile.target" "$target_dir/Makefile"
case "$target_arch2" in
- alpha | arm* | i386 | lm32 | m68k | or32 | s390x | sparc* | unicore32 | x86_64 | xtensa* | ppc*)
+ alpha | arm* | i386 | lm32 | m68k | microblaze* | or32 | s390x | sparc* | unicore32 | x86_64 | xtensa* | ppc*)
echo "CONFIG_TCG_PASS_AREG0=y" >> $config_target_mak
;;
esac
diff --git a/target-microblaze/Makefile.objs b/target-microblaze/Makefile.objs
index 4b09e8c..afb87bc 100644
--- a/target-microblaze/Makefile.objs
+++ b/target-microblaze/Makefile.objs
@@ -1,4 +1,2 @@
obj-y += translate.o op_helper.o helper.o cpu.o
obj-$(CONFIG_SOFTMMU) += mmu.o machine.o
-
-$(obj)/op_helper.o: QEMU_CFLAGS += $(HELPER_CFLAGS)
diff --git a/target-microblaze/helper.h b/target-microblaze/helper.h
index 9dcfb0f..a1a732c 100644
--- a/target-microblaze/helper.h
+++ b/target-microblaze/helper.h
@@ -1,39 +1,39 @@
#include "def-helper.h"
-DEF_HELPER_1(raise_exception, void, i32)
-DEF_HELPER_0(debug, void)
+DEF_HELPER_2(raise_exception, void, env, i32)
+DEF_HELPER_1(debug, void, env)
DEF_HELPER_FLAGS_3(carry, TCG_CALL_PURE | TCG_CALL_CONST, i32, i32, i32, i32)
DEF_HELPER_2(cmp, i32, i32, i32)
DEF_HELPER_2(cmpu, i32, i32, i32)
DEF_HELPER_FLAGS_1(clz, TCG_CALL_PURE | TCG_CALL_CONST, i32, i32)
-DEF_HELPER_2(divs, i32, i32, i32)
-DEF_HELPER_2(divu, i32, i32, i32)
-
-DEF_HELPER_2(fadd, i32, i32, i32)
-DEF_HELPER_2(frsub, i32, i32, i32)
-DEF_HELPER_2(fmul, i32, i32, i32)
-DEF_HELPER_2(fdiv, i32, i32, i32)
-DEF_HELPER_1(flt, i32, i32)
-DEF_HELPER_1(fint, i32, i32)
-DEF_HELPER_1(fsqrt, i32, i32)
-
-DEF_HELPER_2(fcmp_un, i32, i32, i32)
-DEF_HELPER_2(fcmp_lt, i32, i32, i32)
-DEF_HELPER_2(fcmp_eq, i32, i32, i32)
-DEF_HELPER_2(fcmp_le, i32, i32, i32)
-DEF_HELPER_2(fcmp_gt, i32, i32, i32)
-DEF_HELPER_2(fcmp_ne, i32, i32, i32)
-DEF_HELPER_2(fcmp_ge, i32, i32, i32)
+DEF_HELPER_3(divs, i32, env, i32, i32)
+DEF_HELPER_3(divu, i32, env, i32, i32)
+
+DEF_HELPER_3(fadd, i32, env, i32, i32)
+DEF_HELPER_3(frsub, i32, env, i32, i32)
+DEF_HELPER_3(fmul, i32, env, i32, i32)
+DEF_HELPER_3(fdiv, i32, env, i32, i32)
+DEF_HELPER_2(flt, i32, env, i32)
+DEF_HELPER_2(fint, i32, env, i32)
+DEF_HELPER_2(fsqrt, i32, env, i32)
+
+DEF_HELPER_3(fcmp_un, i32, env, i32, i32)
+DEF_HELPER_3(fcmp_lt, i32, env, i32, i32)
+DEF_HELPER_3(fcmp_eq, i32, env, i32, i32)
+DEF_HELPER_3(fcmp_le, i32, env, i32, i32)
+DEF_HELPER_3(fcmp_gt, i32, env, i32, i32)
+DEF_HELPER_3(fcmp_ne, i32, env, i32, i32)
+DEF_HELPER_3(fcmp_ge, i32, env, i32, i32)
DEF_HELPER_FLAGS_2(pcmpbf, TCG_CALL_PURE | TCG_CALL_CONST, i32, i32, i32)
#if !defined(CONFIG_USER_ONLY)
-DEF_HELPER_1(mmu_read, i32, i32)
-DEF_HELPER_2(mmu_write, void, i32, i32)
+DEF_HELPER_2(mmu_read, i32, env, i32)
+DEF_HELPER_3(mmu_write, void, env, i32, i32)
#endif
-DEF_HELPER_4(memalign, void, i32, i32, i32, i32)
-DEF_HELPER_1(stackprot, void, i32)
+DEF_HELPER_5(memalign, void, env, i32, i32, i32, i32)
+DEF_HELPER_2(stackprot, void, env, i32)
DEF_HELPER_2(get, i32, i32, i32)
DEF_HELPER_3(put, void, i32, i32, i32)
diff --git a/target-microblaze/op_helper.c b/target-microblaze/op_helper.c
index 3b1f072..c9789f4 100644
--- a/target-microblaze/op_helper.c
+++ b/target-microblaze/op_helper.c
@@ -20,7 +20,6 @@
#include <assert.h>
#include "cpu.h"
-#include "dyngen-exec.h"
#include "helper.h"
#include "host-utils.h"
@@ -42,17 +41,12 @@
/* Try to fill the TLB and return an exception if error. If retaddr is
NULL, it means that the function was called in C code (i.e. not
from generated code or from helper.c) */
-/* XXX: fix it to restore all registers */
-void tlb_fill(CPUMBState *env1, target_ulong addr, int is_write, int mmu_idx,
+void tlb_fill(CPUMBState *env, target_ulong addr, int is_write, int mmu_idx,
uintptr_t retaddr)
{
TranslationBlock *tb;
- CPUMBState *saved_env;
int ret;
- saved_env = env;
- env = env1;
-
ret = cpu_mb_handle_mmu_fault(env, addr, is_write, mmu_idx);
if (unlikely(ret)) {
if (retaddr) {
@@ -66,7 +60,6 @@ void tlb_fill(CPUMBState *env1, target_ulong addr, int is_write, int mmu_idx,
}
cpu_loop_exit(env);
}
- env = saved_env;
}
#endif
@@ -105,13 +98,13 @@ uint32_t helper_get(uint32_t id, uint32_t ctrl)
return 0xdead0000 | id;
}
-void helper_raise_exception(uint32_t index)
+void helper_raise_exception(CPUMBState *env, uint32_t index)
{
env->exception_index = index;
cpu_loop_exit(env);
}
-void helper_debug(void)
+void helper_debug(CPUMBState *env)
{
int i;
@@ -176,7 +169,7 @@ uint32_t helper_carry(uint32_t a, uint32_t b, uint32_t cf)
return ncf;
}
-static inline int div_prepare(uint32_t a, uint32_t b)
+static inline int div_prepare(CPUMBState *env, uint32_t a, uint32_t b)
{
if (b == 0) {
env->sregs[SR_MSR] |= MSR_DZ;
@@ -184,7 +177,7 @@ static inline int div_prepare(uint32_t a, uint32_t b)
if ((env->sregs[SR_MSR] & MSR_EE)
&& !(env->pvr.regs[2] & PVR2_DIV_ZERO_EXC_MASK)) {
env->sregs[SR_ESR] = ESR_EC_DIVZERO;
- helper_raise_exception(EXCP_HW_EXCP);
+ helper_raise_exception(env, EXCP_HW_EXCP);
}
return 0;
}
@@ -192,28 +185,30 @@ static inline int div_prepare(uint32_t a, uint32_t b)
return 1;
}
-uint32_t helper_divs(uint32_t a, uint32_t b)
+uint32_t helper_divs(CPUMBState *env, uint32_t a, uint32_t b)
{
- if (!div_prepare(a, b))
+ if (!div_prepare(env, a, b)) {
return 0;
+ }
return (int32_t)a / (int32_t)b;
}
-uint32_t helper_divu(uint32_t a, uint32_t b)
+uint32_t helper_divu(CPUMBState *env, uint32_t a, uint32_t b)
{
- if (!div_prepare(a, b))
+ if (!div_prepare(env, a, b)) {
return 0;
+ }
return a / b;
}
/* raise FPU exception. */
-static void raise_fpu_exception(void)
+static void raise_fpu_exception(CPUMBState *env)
{
env->sregs[SR_ESR] = ESR_EC_FPU;
- helper_raise_exception(EXCP_HW_EXCP);
+ helper_raise_exception(env, EXCP_HW_EXCP);
}
-static void update_fpu_flags(int flags)
+static void update_fpu_flags(CPUMBState *env, int flags)
{
int raise = 0;
@@ -236,11 +231,11 @@ static void update_fpu_flags(int flags)
if (raise
&& (env->pvr.regs[2] & PVR2_FPU_EXC_MASK)
&& (env->sregs[SR_MSR] & MSR_EE)) {
- raise_fpu_exception();
+ raise_fpu_exception(env);
}
}
-uint32_t helper_fadd(uint32_t a, uint32_t b)
+uint32_t helper_fadd(CPUMBState *env, uint32_t a, uint32_t b)
{
CPU_FloatU fd, fa, fb;
int flags;
@@ -251,11 +246,11 @@ uint32_t helper_fadd(uint32_t a, uint32_t b)
fd.f = float32_add(fa.f, fb.f, &env->fp_status);
flags = get_float_exception_flags(&env->fp_status);
- update_fpu_flags(flags);
+ update_fpu_flags(env, flags);
return fd.l;
}
-uint32_t helper_frsub(uint32_t a, uint32_t b)
+uint32_t helper_frsub(CPUMBState *env, uint32_t a, uint32_t b)
{
CPU_FloatU fd, fa, fb;
int flags;
@@ -265,11 +260,11 @@ uint32_t helper_frsub(uint32_t a, uint32_t b)
fb.l = b;
fd.f = float32_sub(fb.f, fa.f, &env->fp_status);
flags = get_float_exception_flags(&env->fp_status);
- update_fpu_flags(flags);
+ update_fpu_flags(env, flags);
return fd.l;
}
-uint32_t helper_fmul(uint32_t a, uint32_t b)
+uint32_t helper_fmul(CPUMBState *env, uint32_t a, uint32_t b)
{
CPU_FloatU fd, fa, fb;
int flags;
@@ -279,12 +274,12 @@ uint32_t helper_fmul(uint32_t a, uint32_t b)
fb.l = b;
fd.f = float32_mul(fa.f, fb.f, &env->fp_status);
flags = get_float_exception_flags(&env->fp_status);
- update_fpu_flags(flags);
+ update_fpu_flags(env, flags);
return fd.l;
}
-uint32_t helper_fdiv(uint32_t a, uint32_t b)
+uint32_t helper_fdiv(CPUMBState *env, uint32_t a, uint32_t b)
{
CPU_FloatU fd, fa, fb;
int flags;
@@ -294,12 +289,12 @@ uint32_t helper_fdiv(uint32_t a, uint32_t b)
fb.l = b;
fd.f = float32_div(fb.f, fa.f, &env->fp_status);
flags = get_float_exception_flags(&env->fp_status);
- update_fpu_flags(flags);
+ update_fpu_flags(env, flags);
return fd.l;
}
-uint32_t helper_fcmp_un(uint32_t a, uint32_t b)
+uint32_t helper_fcmp_un(CPUMBState *env, uint32_t a, uint32_t b)
{
CPU_FloatU fa, fb;
uint32_t r = 0;
@@ -308,7 +303,7 @@ uint32_t helper_fcmp_un(uint32_t a, uint32_t b)
fb.l = b;
if (float32_is_signaling_nan(fa.f) || float32_is_signaling_nan(fb.f)) {
- update_fpu_flags(float_flag_invalid);
+ update_fpu_flags(env, float_flag_invalid);
r = 1;
}
@@ -319,7 +314,7 @@ uint32_t helper_fcmp_un(uint32_t a, uint32_t b)
return r;
}
-uint32_t helper_fcmp_lt(uint32_t a, uint32_t b)
+uint32_t helper_fcmp_lt(CPUMBState *env, uint32_t a, uint32_t b)
{
CPU_FloatU fa, fb;
int r;
@@ -330,12 +325,12 @@ uint32_t helper_fcmp_lt(uint32_t a, uint32_t b)
fb.l = b;
r = float32_lt(fb.f, fa.f, &env->fp_status);
flags = get_float_exception_flags(&env->fp_status);
- update_fpu_flags(flags & float_flag_invalid);
+ update_fpu_flags(env, flags & float_flag_invalid);
return r;
}
-uint32_t helper_fcmp_eq(uint32_t a, uint32_t b)
+uint32_t helper_fcmp_eq(CPUMBState *env, uint32_t a, uint32_t b)
{
CPU_FloatU fa, fb;
int flags;
@@ -346,12 +341,12 @@ uint32_t helper_fcmp_eq(uint32_t a, uint32_t b)
fb.l = b;
r = float32_eq_quiet(fa.f, fb.f, &env->fp_status);
flags = get_float_exception_flags(&env->fp_status);
- update_fpu_flags(flags & float_flag_invalid);
+ update_fpu_flags(env, flags & float_flag_invalid);
return r;
}
-uint32_t helper_fcmp_le(uint32_t a, uint32_t b)
+uint32_t helper_fcmp_le(CPUMBState *env, uint32_t a, uint32_t b)
{
CPU_FloatU fa, fb;
int flags;
@@ -362,13 +357,13 @@ uint32_t helper_fcmp_le(uint32_t a, uint32_t b)
set_float_exception_flags(0, &env->fp_status);
r = float32_le(fa.f, fb.f, &env->fp_status);
flags = get_float_exception_flags(&env->fp_status);
- update_fpu_flags(flags & float_flag_invalid);
+ update_fpu_flags(env, flags & float_flag_invalid);
return r;
}
-uint32_t helper_fcmp_gt(uint32_t a, uint32_t b)
+uint32_t helper_fcmp_gt(CPUMBState *env, uint32_t a, uint32_t b)
{
CPU_FloatU fa, fb;
int flags, r;
@@ -378,11 +373,11 @@ uint32_t helper_fcmp_gt(uint32_t a, uint32_t b)
set_float_exception_flags(0, &env->fp_status);
r = float32_lt(fa.f, fb.f, &env->fp_status);
flags = get_float_exception_flags(&env->fp_status);
- update_fpu_flags(flags & float_flag_invalid);
+ update_fpu_flags(env, flags & float_flag_invalid);
return r;
}
-uint32_t helper_fcmp_ne(uint32_t a, uint32_t b)
+uint32_t helper_fcmp_ne(CPUMBState *env, uint32_t a, uint32_t b)
{
CPU_FloatU fa, fb;
int flags, r;
@@ -392,12 +387,12 @@ uint32_t helper_fcmp_ne(uint32_t a, uint32_t b)
set_float_exception_flags(0, &env->fp_status);
r = !float32_eq_quiet(fa.f, fb.f, &env->fp_status);
flags = get_float_exception_flags(&env->fp_status);
- update_fpu_flags(flags & float_flag_invalid);
+ update_fpu_flags(env, flags & float_flag_invalid);
return r;
}
-uint32_t helper_fcmp_ge(uint32_t a, uint32_t b)
+uint32_t helper_fcmp_ge(CPUMBState *env, uint32_t a, uint32_t b)
{
CPU_FloatU fa, fb;
int flags, r;
@@ -407,12 +402,12 @@ uint32_t helper_fcmp_ge(uint32_t a, uint32_t b)
set_float_exception_flags(0, &env->fp_status);
r = !float32_lt(fa.f, fb.f, &env->fp_status);
flags = get_float_exception_flags(&env->fp_status);
- update_fpu_flags(flags & float_flag_invalid);
+ update_fpu_flags(env, flags & float_flag_invalid);
return r;
}
-uint32_t helper_flt(uint32_t a)
+uint32_t helper_flt(CPUMBState *env, uint32_t a)
{
CPU_FloatU fd, fa;
@@ -421,7 +416,7 @@ uint32_t helper_flt(uint32_t a)
return fd.l;
}
-uint32_t helper_fint(uint32_t a)
+uint32_t helper_fint(CPUMBState *env, uint32_t a)
{
CPU_FloatU fa;
uint32_t r;
@@ -431,12 +426,12 @@ uint32_t helper_fint(uint32_t a)
fa.l = a;
r = float32_to_int32(fa.f, &env->fp_status);
flags = get_float_exception_flags(&env->fp_status);
- update_fpu_flags(flags);
+ update_fpu_flags(env, flags);
return r;
}
-uint32_t helper_fsqrt(uint32_t a)
+uint32_t helper_fsqrt(CPUMBState *env, uint32_t a)
{
CPU_FloatU fd, fa;
int flags;
@@ -445,7 +440,7 @@ uint32_t helper_fsqrt(uint32_t a)
fa.l = a;
fd.l = float32_sqrt(fa.f, &env->fp_status);
flags = get_float_exception_flags(&env->fp_status);
- update_fpu_flags(flags);
+ update_fpu_flags(env, flags);
return fd.l;
}
@@ -463,7 +458,8 @@ uint32_t helper_pcmpbf(uint32_t a, uint32_t b)
return 0;
}
-void helper_memalign(uint32_t addr, uint32_t dr, uint32_t wr, uint32_t mask)
+void helper_memalign(CPUMBState *env, uint32_t addr, uint32_t dr, uint32_t wr,
+ uint32_t mask)
{
if (addr & mask) {
qemu_log_mask(CPU_LOG_INT,
@@ -478,45 +474,39 @@ void helper_memalign(uint32_t addr, uint32_t dr, uint32_t wr, uint32_t mask)
if (!(env->sregs[SR_MSR] & MSR_EE)) {
return;
}
- helper_raise_exception(EXCP_HW_EXCP);
+ helper_raise_exception(env, EXCP_HW_EXCP);
}
}
-void helper_stackprot(uint32_t addr)
+void helper_stackprot(CPUMBState *env, uint32_t addr)
{
if (addr < env->slr || addr > env->shr) {
qemu_log("Stack protector violation at %x %x %x\n",
addr, env->slr, env->shr);
env->sregs[SR_EAR] = addr;
env->sregs[SR_ESR] = ESR_EC_STACKPROT;
- helper_raise_exception(EXCP_HW_EXCP);
+ helper_raise_exception(env, EXCP_HW_EXCP);
}
}
#if !defined(CONFIG_USER_ONLY)
/* Writes/reads to the MMU's special regs end up here. */
-uint32_t helper_mmu_read(uint32_t rn)
+uint32_t helper_mmu_read(CPUMBState *env, uint32_t rn)
{
return mmu_read(env, rn);
}
-void helper_mmu_write(uint32_t rn, uint32_t v)
+void helper_mmu_write(CPUMBState *env, uint32_t rn, uint32_t v)
{
mmu_write(env, rn, v);
}
-void cpu_unassigned_access(CPUMBState *env1, target_phys_addr_t addr,
+void cpu_unassigned_access(CPUMBState *env, target_phys_addr_t addr,
int is_write, int is_exec, int is_asi, int size)
{
- CPUMBState *saved_env;
-
- saved_env = env;
- env = env1;
-
qemu_log_mask(CPU_LOG_INT, "Unassigned " TARGET_FMT_plx " wr=%d exe=%d\n",
addr, is_write, is_exec);
if (!(env->sregs[SR_MSR] & MSR_EE)) {
- env = saved_env;
return;
}
@@ -524,14 +514,13 @@ void cpu_unassigned_access(CPUMBState *env1, target_phys_addr_t addr,
if (is_exec) {
if ((env->pvr.regs[2] & PVR2_IOPB_BUS_EXC_MASK)) {
env->sregs[SR_ESR] = ESR_EC_INSN_BUS;
- helper_raise_exception(EXCP_HW_EXCP);
+ helper_raise_exception(env, EXCP_HW_EXCP);
}
} else {
if ((env->pvr.regs[2] & PVR2_DOPB_BUS_EXC_MASK)) {
env->sregs[SR_ESR] = ESR_EC_DATA_BUS;
- helper_raise_exception(EXCP_HW_EXCP);
+ helper_raise_exception(env, EXCP_HW_EXCP);
}
}
- env = saved_env;
}
#endif
diff --git a/target-microblaze/translate.c b/target-microblaze/translate.c
index 7470149..9c7d77f 100644
--- a/target-microblaze/translate.c
+++ b/target-microblaze/translate.c
@@ -126,7 +126,7 @@ static inline void t_gen_raise_exception(DisasContext *dc, uint32_t index)
t_sync_flags(dc);
tcg_gen_movi_tl(cpu_SR[SR_PC], dc->pc);
- gen_helper_raise_exception(tmp);
+ gen_helper_raise_exception(cpu_env, tmp);
tcg_temp_free_i32(tmp);
dc->is_jmp = DISAS_UPDATE;
}
@@ -503,9 +503,9 @@ static void dec_msr(DisasContext *dc)
sr &= 7;
LOG_DIS("m%ss sr%d r%d imm=%x\n", to ? "t" : "f", sr, dc->ra, dc->imm);
if (to)
- gen_helper_mmu_write(tcg_const_tl(sr), cpu_R[dc->ra]);
+ gen_helper_mmu_write(cpu_env, tcg_const_tl(sr), cpu_R[dc->ra]);
else
- gen_helper_mmu_read(cpu_R[dc->rd], tcg_const_tl(sr));
+ gen_helper_mmu_read(cpu_R[dc->rd], cpu_env, tcg_const_tl(sr));
return;
}
#endif
@@ -704,9 +704,11 @@ static void dec_div(DisasContext *dc)
}
if (u)
- gen_helper_divu(cpu_R[dc->rd], *(dec_alu_op_b(dc)), cpu_R[dc->ra]);
+ gen_helper_divu(cpu_R[dc->rd], cpu_env, *(dec_alu_op_b(dc)),
+ cpu_R[dc->ra]);
else
- gen_helper_divs(cpu_R[dc->rd], *(dec_alu_op_b(dc)), cpu_R[dc->ra]);
+ gen_helper_divs(cpu_R[dc->rd], cpu_env, *(dec_alu_op_b(dc)),
+ cpu_R[dc->ra]);
if (!dc->rd)
tcg_gen_movi_tl(cpu_R[dc->rd], 0);
}
@@ -912,7 +914,7 @@ static inline TCGv *compute_ldst_addr(DisasContext *dc, TCGv *t)
tcg_gen_add_tl(*t, cpu_R[dc->ra], cpu_R[dc->rb]);
if (stackprot) {
- gen_helper_stackprot(*t);
+ gen_helper_stackprot(cpu_env, *t);
}
return t;
}
@@ -930,7 +932,7 @@ static inline TCGv *compute_ldst_addr(DisasContext *dc, TCGv *t)
}
if (stackprot) {
- gen_helper_stackprot(*t);
+ gen_helper_stackprot(cpu_env, *t);
}
return t;
}
@@ -1056,7 +1058,7 @@ static void dec_load(DisasContext *dc)
gen_load(dc, v, *addr, size);
tcg_gen_movi_tl(cpu_SR[SR_PC], dc->pc);
- gen_helper_memalign(*addr, tcg_const_tl(dc->rd),
+ gen_helper_memalign(cpu_env, *addr, tcg_const_tl(dc->rd),
tcg_const_tl(0), tcg_const_tl(size - 1));
if (dc->rd) {
if (rev) {
@@ -1218,7 +1220,7 @@ static void dec_store(DisasContext *dc)
* the alignment checks in between the probe and the mem
* access.
*/
- gen_helper_memalign(*addr, tcg_const_tl(dc->rd),
+ gen_helper_memalign(cpu_env, *addr, tcg_const_tl(dc->rd),
tcg_const_tl(1), tcg_const_tl(size - 1));
}
@@ -1493,49 +1495,53 @@ static void dec_fpu(DisasContext *dc)
switch (fpu_insn) {
case 0:
- gen_helper_fadd(cpu_R[dc->rd], cpu_R[dc->ra], cpu_R[dc->rb]);
+ gen_helper_fadd(cpu_R[dc->rd], cpu_env, cpu_R[dc->ra],
+ cpu_R[dc->rb]);
break;
case 1:
- gen_helper_frsub(cpu_R[dc->rd], cpu_R[dc->ra], cpu_R[dc->rb]);
+ gen_helper_frsub(cpu_R[dc->rd], cpu_env, cpu_R[dc->ra],
+ cpu_R[dc->rb]);
break;
case 2:
- gen_helper_fmul(cpu_R[dc->rd], cpu_R[dc->ra], cpu_R[dc->rb]);
+ gen_helper_fmul(cpu_R[dc->rd], cpu_env, cpu_R[dc->ra],
+ cpu_R[dc->rb]);
break;
case 3:
- gen_helper_fdiv(cpu_R[dc->rd], cpu_R[dc->ra], cpu_R[dc->rb]);
+ gen_helper_fdiv(cpu_R[dc->rd], cpu_env, cpu_R[dc->ra],
+ cpu_R[dc->rb]);
break;
case 4:
switch ((dc->ir >> 4) & 7) {
case 0:
- gen_helper_fcmp_un(cpu_R[dc->rd],
+ gen_helper_fcmp_un(cpu_R[dc->rd], cpu_env,
cpu_R[dc->ra], cpu_R[dc->rb]);
break;
case 1:
- gen_helper_fcmp_lt(cpu_R[dc->rd],
+ gen_helper_fcmp_lt(cpu_R[dc->rd], cpu_env,
cpu_R[dc->ra], cpu_R[dc->rb]);
break;
case 2:
- gen_helper_fcmp_eq(cpu_R[dc->rd],
+ gen_helper_fcmp_eq(cpu_R[dc->rd], cpu_env,
cpu_R[dc->ra], cpu_R[dc->rb]);
break;
case 3:
- gen_helper_fcmp_le(cpu_R[dc->rd],
+ gen_helper_fcmp_le(cpu_R[dc->rd], cpu_env,
cpu_R[dc->ra], cpu_R[dc->rb]);
break;
case 4:
- gen_helper_fcmp_gt(cpu_R[dc->rd],
+ gen_helper_fcmp_gt(cpu_R[dc->rd], cpu_env,
cpu_R[dc->ra], cpu_R[dc->rb]);
break;
case 5:
- gen_helper_fcmp_ne(cpu_R[dc->rd],
+ gen_helper_fcmp_ne(cpu_R[dc->rd], cpu_env,
cpu_R[dc->ra], cpu_R[dc->rb]);
break;
case 6:
- gen_helper_fcmp_ge(cpu_R[dc->rd],
+ gen_helper_fcmp_ge(cpu_R[dc->rd], cpu_env,
cpu_R[dc->ra], cpu_R[dc->rb]);
break;
default:
@@ -1552,21 +1558,21 @@ static void dec_fpu(DisasContext *dc)
if (!dec_check_fpuv2(dc)) {
return;
}
- gen_helper_flt(cpu_R[dc->rd], cpu_R[dc->ra]);
+ gen_helper_flt(cpu_R[dc->rd], cpu_env, cpu_R[dc->ra]);
break;
case 6:
if (!dec_check_fpuv2(dc)) {
return;
}
- gen_helper_fint(cpu_R[dc->rd], cpu_R[dc->ra]);
+ gen_helper_fint(cpu_R[dc->rd], cpu_env, cpu_R[dc->ra]);
break;
case 7:
if (!dec_check_fpuv2(dc)) {
return;
}
- gen_helper_fsqrt(cpu_R[dc->rd], cpu_R[dc->ra]);
+ gen_helper_fsqrt(cpu_R[dc->rd], cpu_env, cpu_R[dc->ra]);
break;
default:
@@ -1654,15 +1660,14 @@ static struct decoder_info {
{{0, 0}, dec_null}
};
-static inline void decode(DisasContext *dc)
+static inline void decode(DisasContext *dc, uint32_t ir)
{
- uint32_t ir;
int i;
if (unlikely(qemu_loglevel_mask(CPU_LOG_TB_OP)))
tcg_gen_debug_insn_start(dc->pc);
- dc->ir = ir = ldl_code(dc->pc);
+ dc->ir = ir;
LOG_DIS("%8.8x\t", dc->ir);
if (dc->ir)
@@ -1796,7 +1801,7 @@ gen_intermediate_code_internal(CPUMBState *env, TranslationBlock *tb,
gen_io_start();
dc->clear_imm = 1;
- decode(dc);
+ decode(dc, cpu_ldl_code(env, dc->pc));
if (dc->clear_imm)
dc->tb_flags &= ~IMM_FLAG;
dc->pc += 4;
@@ -1871,7 +1876,7 @@ gen_intermediate_code_internal(CPUMBState *env, TranslationBlock *tb,
if (dc->is_jmp != DISAS_JUMP) {
tcg_gen_movi_tl(cpu_SR[SR_PC], npc);
}
- gen_helper_raise_exception(tmp);
+ gen_helper_raise_exception(cpu_env, tmp);
tcg_temp_free_i32(tmp);
} else {
switch(dc->is_jmp) {
--
1.7.12.1

View File

@ -0,0 +1,523 @@
From 1e3916b0cbfd39cb3fc8996423d5574068583145 Mon Sep 17 00:00:00 2001
From: Aurelien Jarno <aurelien@aurel32.net>
Date: Thu, 30 Aug 2012 16:56:39 +0200
Subject: [PATCH] target-cris: Avoid AREG0 for helpers
Add an explicit CPUCRISState parameter instead of relying on AREG0.
Signed-off-by: Blue Swirl <blauwirbel@gmail.com>
Signed-off-by: Aurelien Jarno <aurelien@aurel32.net>
Signed-off-by: Michael Roth <mdroth@linux.vnet.ibm.com>
---
target-cris/helper.h | 37 +++++++++++----------
target-cris/op_helper.c | 80 ++++++++++++++++++++++++---------------------
target-cris/translate.c | 44 +++++++++++++------------
target-cris/translate_v10.c | 4 +--
4 files changed, 88 insertions(+), 77 deletions(-)
diff --git a/target-cris/helper.h b/target-cris/helper.h
index 093063a..99fb326 100644
--- a/target-cris/helper.h
+++ b/target-cris/helper.h
@@ -1,26 +1,29 @@
#include "def-helper.h"
-DEF_HELPER_1(raise_exception, void, i32)
-DEF_HELPER_1(tlb_flush_pid, void, i32)
-DEF_HELPER_1(spc_write, void, i32)
+DEF_HELPER_2(raise_exception, void, env, i32)
+DEF_HELPER_2(tlb_flush_pid, void, env, i32)
+DEF_HELPER_2(spc_write, void, env, i32)
DEF_HELPER_3(dump, void, i32, i32, i32)
-DEF_HELPER_0(rfe, void);
-DEF_HELPER_0(rfn, void);
+DEF_HELPER_1(rfe, void, env);
+DEF_HELPER_1(rfn, void, env);
-DEF_HELPER_2(movl_sreg_reg, void, i32, i32)
-DEF_HELPER_2(movl_reg_sreg, void, i32, i32)
+DEF_HELPER_3(movl_sreg_reg, void, env, i32, i32)
+DEF_HELPER_3(movl_reg_sreg, void, env, i32, i32)
DEF_HELPER_FLAGS_1(lz, TCG_CALL_PURE, i32, i32);
-DEF_HELPER_FLAGS_3(btst, TCG_CALL_PURE, i32, i32, i32, i32);
+DEF_HELPER_FLAGS_4(btst, TCG_CALL_PURE, i32, env, i32, i32, i32);
-DEF_HELPER_FLAGS_3(evaluate_flags_muls, TCG_CALL_PURE, i32, i32, i32, i32)
-DEF_HELPER_FLAGS_3(evaluate_flags_mulu, TCG_CALL_PURE, i32, i32, i32, i32)
-DEF_HELPER_FLAGS_4(evaluate_flags_mcp, TCG_CALL_PURE, i32, i32, i32, i32, i32)
-DEF_HELPER_FLAGS_4(evaluate_flags_alu_4, TCG_CALL_PURE, i32, i32, i32, i32, i32)
-DEF_HELPER_FLAGS_4(evaluate_flags_sub_4, TCG_CALL_PURE, i32, i32, i32, i32, i32)
-DEF_HELPER_FLAGS_2(evaluate_flags_move_4, TCG_CALL_PURE, i32, i32, i32)
-DEF_HELPER_FLAGS_2(evaluate_flags_move_2, TCG_CALL_PURE, i32, i32, i32)
-DEF_HELPER_0(evaluate_flags, void)
-DEF_HELPER_0(top_evaluate_flags, void)
+DEF_HELPER_FLAGS_4(evaluate_flags_muls, TCG_CALL_PURE, i32, env, i32, i32, i32)
+DEF_HELPER_FLAGS_4(evaluate_flags_mulu, TCG_CALL_PURE, i32, env, i32, i32, i32)
+DEF_HELPER_FLAGS_5(evaluate_flags_mcp, TCG_CALL_PURE, i32, env,
+ i32, i32, i32, i32)
+DEF_HELPER_FLAGS_5(evaluate_flags_alu_4, TCG_CALL_PURE, i32, env,
+ i32, i32, i32, i32)
+DEF_HELPER_FLAGS_5(evaluate_flags_sub_4, TCG_CALL_PURE, i32, env,
+ i32, i32, i32, i32)
+DEF_HELPER_FLAGS_3(evaluate_flags_move_4, TCG_CALL_PURE, i32, env, i32, i32)
+DEF_HELPER_FLAGS_3(evaluate_flags_move_2, TCG_CALL_PURE, i32, env, i32, i32)
+DEF_HELPER_1(evaluate_flags, void, env)
+DEF_HELPER_1(top_evaluate_flags, void, env)
#include "def-helper.h"
diff --git a/target-cris/op_helper.c b/target-cris/op_helper.c
index ac7c98c..5ca85a0 100644
--- a/target-cris/op_helper.c
+++ b/target-cris/op_helper.c
@@ -79,7 +79,7 @@ void tlb_fill(CPUCRISState *env1, target_ulong addr, int is_write, int mmu_idx,
cpu_restore_state(tb, env, retaddr);
/* Evaluate flags after retranslation. */
- helper_top_evaluate_flags();
+ helper_top_evaluate_flags(env);
}
}
cpu_loop_exit(env);
@@ -89,13 +89,13 @@ void tlb_fill(CPUCRISState *env1, target_ulong addr, int is_write, int mmu_idx,
#endif
-void helper_raise_exception(uint32_t index)
+void helper_raise_exception(CPUCRISState *env, uint32_t index)
{
env->exception_index = index;
cpu_loop_exit(env);
}
-void helper_tlb_flush_pid(uint32_t pid)
+void helper_tlb_flush_pid(CPUCRISState *env, uint32_t pid)
{
#if !defined(CONFIG_USER_ONLY)
pid &= 0xff;
@@ -104,7 +104,7 @@ void helper_tlb_flush_pid(uint32_t pid)
#endif
}
-void helper_spc_write(uint32_t new_spc)
+void helper_spc_write(CPUCRISState *env, uint32_t new_spc)
{
#if !defined(CONFIG_USER_ONLY)
tlb_flush_page(env, env->pregs[PR_SPC]);
@@ -121,7 +121,7 @@ void helper_dump(uint32_t a0, uint32_t a1, uint32_t a2)
#define EXTRACT_FIELD(src, start, end) \
(((src) >> start) & ((1 << (end - start + 1)) - 1))
-void helper_movl_sreg_reg (uint32_t sreg, uint32_t reg)
+void helper_movl_sreg_reg(CPUCRISState *env, uint32_t sreg, uint32_t reg)
{
uint32_t srs;
srs = env->pregs[PR_SRS];
@@ -171,7 +171,7 @@ void helper_movl_sreg_reg (uint32_t sreg, uint32_t reg)
#endif
}
-void helper_movl_reg_sreg (uint32_t reg, uint32_t sreg)
+void helper_movl_reg_sreg(CPUCRISState *env, uint32_t reg, uint32_t sreg)
{
uint32_t srs;
env->pregs[PR_SRS] &= 3;
@@ -216,7 +216,7 @@ static void cris_ccs_rshift(CPUCRISState *env)
env->pregs[PR_CCS] = ccs;
}
-void helper_rfe(void)
+void helper_rfe(CPUCRISState *env)
{
int rflag = env->pregs[PR_CCS] & R_FLAG;
@@ -232,7 +232,7 @@ void helper_rfe(void)
env->pregs[PR_CCS] |= P_FLAG;
}
-void helper_rfn(void)
+void helper_rfn(CPUCRISState *env)
{
int rflag = env->pregs[PR_CCS] & R_FLAG;
@@ -256,7 +256,7 @@ uint32_t helper_lz(uint32_t t0)
return clz32(t0);
}
-uint32_t helper_btst(uint32_t t0, uint32_t t1, uint32_t ccs)
+uint32_t helper_btst(CPUCRISState *env, uint32_t t0, uint32_t t1, uint32_t ccs)
{
/* FIXME: clean this up. */
@@ -284,7 +284,8 @@ uint32_t helper_btst(uint32_t t0, uint32_t t1, uint32_t ccs)
return ccs;
}
-static inline uint32_t evaluate_flags_writeback(uint32_t flags, uint32_t ccs)
+static inline uint32_t evaluate_flags_writeback(CPUCRISState *env,
+ uint32_t flags, uint32_t ccs)
{
unsigned int x, z, mask;
@@ -303,7 +304,8 @@ static inline uint32_t evaluate_flags_writeback(uint32_t flags, uint32_t ccs)
return ccs;
}
-uint32_t helper_evaluate_flags_muls(uint32_t ccs, uint32_t res, uint32_t mof)
+uint32_t helper_evaluate_flags_muls(CPUCRISState *env,
+ uint32_t ccs, uint32_t res, uint32_t mof)
{
uint32_t flags = 0;
int64_t tmp;
@@ -321,10 +323,11 @@ uint32_t helper_evaluate_flags_muls(uint32_t ccs, uint32_t res, uint32_t mof)
if ((dneg && mof != -1)
|| (!dneg && mof != 0))
flags |= V_FLAG;
- return evaluate_flags_writeback(flags, ccs);
+ return evaluate_flags_writeback(env, flags, ccs);
}
-uint32_t helper_evaluate_flags_mulu(uint32_t ccs, uint32_t res, uint32_t mof)
+uint32_t helper_evaluate_flags_mulu(CPUCRISState *env,
+ uint32_t ccs, uint32_t res, uint32_t mof)
{
uint32_t flags = 0;
uint64_t tmp;
@@ -339,10 +342,10 @@ uint32_t helper_evaluate_flags_mulu(uint32_t ccs, uint32_t res, uint32_t mof)
if (mof)
flags |= V_FLAG;
- return evaluate_flags_writeback(flags, ccs);
+ return evaluate_flags_writeback(env, flags, ccs);
}
-uint32_t helper_evaluate_flags_mcp(uint32_t ccs,
+uint32_t helper_evaluate_flags_mcp(CPUCRISState *env, uint32_t ccs,
uint32_t src, uint32_t dst, uint32_t res)
{
uint32_t flags = 0;
@@ -368,10 +371,10 @@ uint32_t helper_evaluate_flags_mcp(uint32_t ccs,
flags |= R_FLAG;
}
- return evaluate_flags_writeback(flags, ccs);
+ return evaluate_flags_writeback(env, flags, ccs);
}
-uint32_t helper_evaluate_flags_alu_4(uint32_t ccs,
+uint32_t helper_evaluate_flags_alu_4(CPUCRISState *env, uint32_t ccs,
uint32_t src, uint32_t dst, uint32_t res)
{
uint32_t flags = 0;
@@ -397,10 +400,10 @@ uint32_t helper_evaluate_flags_alu_4(uint32_t ccs,
flags |= C_FLAG;
}
- return evaluate_flags_writeback(flags, ccs);
+ return evaluate_flags_writeback(env, flags, ccs);
}
-uint32_t helper_evaluate_flags_sub_4(uint32_t ccs,
+uint32_t helper_evaluate_flags_sub_4(CPUCRISState *env, uint32_t ccs,
uint32_t src, uint32_t dst, uint32_t res)
{
uint32_t flags = 0;
@@ -427,10 +430,11 @@ uint32_t helper_evaluate_flags_sub_4(uint32_t ccs,
}
flags ^= C_FLAG;
- return evaluate_flags_writeback(flags, ccs);
+ return evaluate_flags_writeback(env, flags, ccs);
}
-uint32_t helper_evaluate_flags_move_4(uint32_t ccs, uint32_t res)
+uint32_t helper_evaluate_flags_move_4(CPUCRISState *env,
+ uint32_t ccs, uint32_t res)
{
uint32_t flags = 0;
@@ -439,9 +443,10 @@ uint32_t helper_evaluate_flags_move_4(uint32_t ccs, uint32_t res)
else if (res == 0L)
flags |= Z_FLAG;
- return evaluate_flags_writeback(flags, ccs);
+ return evaluate_flags_writeback(env, flags, ccs);
}
-uint32_t helper_evaluate_flags_move_2(uint32_t ccs, uint32_t res)
+uint32_t helper_evaluate_flags_move_2(CPUCRISState *env,
+ uint32_t ccs, uint32_t res)
{
uint32_t flags = 0;
@@ -450,12 +455,12 @@ uint32_t helper_evaluate_flags_move_2(uint32_t ccs, uint32_t res)
else if (res == 0)
flags |= Z_FLAG;
- return evaluate_flags_writeback(flags, ccs);
+ return evaluate_flags_writeback(env, flags, ccs);
}
/* TODO: This is expensive. We could split things up and only evaluate part of
CCR on a need to know basis. For now, we simply re-evaluate everything. */
-void helper_evaluate_flags(void)
+void helper_evaluate_flags(CPUCRISState *env)
{
uint32_t src, dst, res;
uint32_t flags = 0;
@@ -571,25 +576,26 @@ void helper_evaluate_flags(void)
if (env->cc_op == CC_OP_SUB || env->cc_op == CC_OP_CMP)
flags ^= C_FLAG;
- env->pregs[PR_CCS] = evaluate_flags_writeback(flags, env->pregs[PR_CCS]);
+ env->pregs[PR_CCS] = evaluate_flags_writeback(env, flags,
+ env->pregs[PR_CCS]);
}
-void helper_top_evaluate_flags(void)
+void helper_top_evaluate_flags(CPUCRISState *env)
{
switch (env->cc_op)
{
case CC_OP_MCP:
- env->pregs[PR_CCS] = helper_evaluate_flags_mcp(
+ env->pregs[PR_CCS] = helper_evaluate_flags_mcp(env,
env->pregs[PR_CCS], env->cc_src,
env->cc_dest, env->cc_result);
break;
case CC_OP_MULS:
- env->pregs[PR_CCS] = helper_evaluate_flags_muls(
+ env->pregs[PR_CCS] = helper_evaluate_flags_muls(env,
env->pregs[PR_CCS], env->cc_result,
env->pregs[PR_MOF]);
break;
case CC_OP_MULU:
- env->pregs[PR_CCS] = helper_evaluate_flags_mulu(
+ env->pregs[PR_CCS] = helper_evaluate_flags_mulu(env,
env->pregs[PR_CCS], env->cc_result,
env->pregs[PR_MOF]);
break;
@@ -604,18 +610,18 @@ void helper_top_evaluate_flags(void)
{
case 4:
env->pregs[PR_CCS] =
- helper_evaluate_flags_move_4(
+ helper_evaluate_flags_move_4(env,
env->pregs[PR_CCS],
env->cc_result);
break;
case 2:
env->pregs[PR_CCS] =
- helper_evaluate_flags_move_2(
+ helper_evaluate_flags_move_2(env,
env->pregs[PR_CCS],
env->cc_result);
break;
default:
- helper_evaluate_flags();
+ helper_evaluate_flags(env);
break;
}
break;
@@ -626,12 +632,12 @@ void helper_top_evaluate_flags(void)
case CC_OP_CMP:
if (env->cc_size == 4)
env->pregs[PR_CCS] =
- helper_evaluate_flags_sub_4(
+ helper_evaluate_flags_sub_4(env,
env->pregs[PR_CCS],
env->cc_src, env->cc_dest,
env->cc_result);
else
- helper_evaluate_flags();
+ helper_evaluate_flags(env);
break;
default:
{
@@ -639,13 +645,13 @@ void helper_top_evaluate_flags(void)
{
case 4:
env->pregs[PR_CCS] =
- helper_evaluate_flags_alu_4(
+ helper_evaluate_flags_alu_4(env,
env->pregs[PR_CCS],
env->cc_src, env->cc_dest,
env->cc_result);
break;
default:
- helper_evaluate_flags();
+ helper_evaluate_flags(env);
break;
}
}
diff --git a/target-cris/translate.c b/target-cris/translate.c
index ad31877..283dd98 100644
--- a/target-cris/translate.c
+++ b/target-cris/translate.c
@@ -211,9 +211,9 @@ static inline void t_gen_mov_preg_TN(DisasContext *dc, int r, TCGv tn)
tcg_gen_andi_tl(cpu_PR[r], tn, 3);
else {
if (r == PR_PID)
- gen_helper_tlb_flush_pid(tn);
+ gen_helper_tlb_flush_pid(cpu_env, tn);
if (dc->tb_flags & S_FLAG && r == PR_SPC)
- gen_helper_spc_write(tn);
+ gen_helper_spc_write(cpu_env, tn);
else if (r == PR_CCS)
dc->cpustate_changed = 1;
tcg_gen_mov_tl(cpu_PR[r], tn);
@@ -278,7 +278,7 @@ static void cris_lock_irq(DisasContext *dc)
static inline void t_gen_raise_exception(uint32_t index)
{
TCGv_i32 tmp = tcg_const_i32(index);
- gen_helper_raise_exception(tmp);
+ gen_helper_raise_exception(cpu_env, tmp);
tcg_temp_free_i32(tmp);
}
@@ -624,17 +624,17 @@ static void cris_evaluate_flags(DisasContext *dc)
switch (dc->cc_op)
{
case CC_OP_MCP:
- gen_helper_evaluate_flags_mcp(cpu_PR[PR_CCS],
+ gen_helper_evaluate_flags_mcp(cpu_PR[PR_CCS], cpu_env,
cpu_PR[PR_CCS], cc_src,
cc_dest, cc_result);
break;
case CC_OP_MULS:
- gen_helper_evaluate_flags_muls(cpu_PR[PR_CCS],
+ gen_helper_evaluate_flags_muls(cpu_PR[PR_CCS], cpu_env,
cpu_PR[PR_CCS], cc_result,
cpu_PR[PR_MOF]);
break;
case CC_OP_MULU:
- gen_helper_evaluate_flags_mulu(cpu_PR[PR_CCS],
+ gen_helper_evaluate_flags_mulu(cpu_PR[PR_CCS], cpu_env,
cpu_PR[PR_CCS], cc_result,
cpu_PR[PR_MOF]);
break;
@@ -648,15 +648,15 @@ static void cris_evaluate_flags(DisasContext *dc)
switch (dc->cc_size)
{
case 4:
- gen_helper_evaluate_flags_move_4(cpu_PR[PR_CCS],
- cpu_PR[PR_CCS], cc_result);
+ gen_helper_evaluate_flags_move_4(cpu_PR[PR_CCS],
+ cpu_env, cpu_PR[PR_CCS], cc_result);
break;
case 2:
- gen_helper_evaluate_flags_move_2(cpu_PR[PR_CCS],
- cpu_PR[PR_CCS], cc_result);
+ gen_helper_evaluate_flags_move_2(cpu_PR[PR_CCS],
+ cpu_env, cpu_PR[PR_CCS], cc_result);
break;
default:
- gen_helper_evaluate_flags();
+ gen_helper_evaluate_flags(cpu_env);
break;
}
break;
@@ -666,21 +666,21 @@ static void cris_evaluate_flags(DisasContext *dc)
case CC_OP_SUB:
case CC_OP_CMP:
if (dc->cc_size == 4)
- gen_helper_evaluate_flags_sub_4(cpu_PR[PR_CCS],
+ gen_helper_evaluate_flags_sub_4(cpu_PR[PR_CCS], cpu_env,
cpu_PR[PR_CCS], cc_src, cc_dest, cc_result);
else
- gen_helper_evaluate_flags();
+ gen_helper_evaluate_flags(cpu_env);
break;
default:
switch (dc->cc_size)
{
case 4:
- gen_helper_evaluate_flags_alu_4(cpu_PR[PR_CCS],
+ gen_helper_evaluate_flags_alu_4(cpu_PR[PR_CCS], cpu_env,
cpu_PR[PR_CCS], cc_src, cc_dest, cc_result);
break;
default:
- gen_helper_evaluate_flags();
+ gen_helper_evaluate_flags(cpu_env);
break;
}
break;
@@ -1475,7 +1475,7 @@ static int dec_btstq(DisasContext *dc)
cris_cc_mask(dc, CC_MASK_NZ);
cris_evaluate_flags(dc);
- gen_helper_btst(cpu_PR[PR_CCS], cpu_R[dc->op2],
+ gen_helper_btst(cpu_PR[PR_CCS], cpu_env, cpu_R[dc->op2],
tcg_const_tl(dc->op1), cpu_PR[PR_CCS]);
cris_alu(dc, CC_OP_MOVE,
cpu_R[dc->op2], cpu_R[dc->op2], cpu_R[dc->op2], 4);
@@ -1925,7 +1925,7 @@ static int dec_btst_r(DisasContext *dc)
dc->op1, dc->op2);
cris_cc_mask(dc, CC_MASK_NZ);
cris_evaluate_flags(dc);
- gen_helper_btst(cpu_PR[PR_CCS], cpu_R[dc->op2],
+ gen_helper_btst(cpu_PR[PR_CCS], cpu_env, cpu_R[dc->op2],
cpu_R[dc->op1], cpu_PR[PR_CCS]);
cris_alu(dc, CC_OP_MOVE, cpu_R[dc->op2],
cpu_R[dc->op2], cpu_R[dc->op2], 4);
@@ -2135,14 +2135,16 @@ static int dec_move_rs(DisasContext *dc)
{
LOG_DIS("move $r%u, $s%u\n", dc->op1, dc->op2);
cris_cc_mask(dc, 0);
- gen_helper_movl_sreg_reg(tcg_const_tl(dc->op2), tcg_const_tl(dc->op1));
+ gen_helper_movl_sreg_reg(cpu_env, tcg_const_tl(dc->op2),
+ tcg_const_tl(dc->op1));
return 2;
}
static int dec_move_sr(DisasContext *dc)
{
LOG_DIS("move $s%u, $r%u\n", dc->op2, dc->op1);
cris_cc_mask(dc, 0);
- gen_helper_movl_reg_sreg(tcg_const_tl(dc->op1), tcg_const_tl(dc->op2));
+ gen_helper_movl_reg_sreg(cpu_env, tcg_const_tl(dc->op1),
+ tcg_const_tl(dc->op2));
return 2;
}
@@ -2906,14 +2908,14 @@ static int dec_rfe_etc(DisasContext *dc)
/* rfe. */
LOG_DIS("rfe\n");
cris_evaluate_flags(dc);
- gen_helper_rfe();
+ gen_helper_rfe(cpu_env);
dc->is_jmp = DISAS_UPDATE;
break;
case 5:
/* rfn. */
LOG_DIS("rfn\n");
cris_evaluate_flags(dc);
- gen_helper_rfn();
+ gen_helper_rfn(cpu_env);
dc->is_jmp = DISAS_UPDATE;
break;
case 6:
diff --git a/target-cris/translate_v10.c b/target-cris/translate_v10.c
index 3629629..9a39c6a 100644
--- a/target-cris/translate_v10.c
+++ b/target-cris/translate_v10.c
@@ -289,7 +289,7 @@ static unsigned int dec10_quick_imm(DisasContext *dc)
} else {
/* BTST */
cris_update_cc_op(dc, CC_OP_FLAGS, 4);
- gen_helper_btst(cpu_PR[PR_CCS], cpu_R[dc->dst],
+ gen_helper_btst(cpu_PR[PR_CCS], cpu_env, cpu_R[dc->dst],
tcg_const_tl(imm), cpu_PR[PR_CCS]);
}
break;
@@ -723,7 +723,7 @@ static unsigned int dec10_reg(DisasContext *dc)
LOG_DIS("btst $r%d, $r%d sz=%d\n", dc->src, dc->dst, size);
cris_cc_mask(dc, CC_MASK_NZVC);
cris_update_cc_op(dc, CC_OP_FLAGS, 4);
- gen_helper_btst(cpu_PR[PR_CCS], cpu_R[dc->dst],
+ gen_helper_btst(cpu_PR[PR_CCS], cpu_env, cpu_R[dc->dst],
cpu_R[dc->src], cpu_PR[PR_CCS]);
break;
case CRISV10_REG_DSTEP:
--
1.7.12.1

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,114 @@
From 83b25655bcd988054a2bb2a0a38dc662d4901b08 Mon Sep 17 00:00:00 2001
From: Aurelien Jarno <aurelien@aurel32.net>
Date: Mon, 10 Sep 2012 13:56:24 +0200
Subject: [PATCH] tcg/i386: allow constants in load/store ops
On x86, it is possible to move a constant value to memory. Add code to
handle a constant argument to load/store ops.
Reviewed-by: Richard Henderson <rth@twiddle.net>
Signed-off-by: Aurelien Jarno <aurelien@aurel32.net>
Signed-off-by: Michael Roth <mdroth@linux.vnet.ibm.com>
---
tcg/i386/tcg-target.c | 50 +++++++++++++++++++++++++++++++++++++-------------
1 file changed, 37 insertions(+), 13 deletions(-)
diff --git a/tcg/i386/tcg-target.c b/tcg/i386/tcg-target.c
index 34c2df8..3017858 100644
--- a/tcg/i386/tcg-target.c
+++ b/tcg/i386/tcg-target.c
@@ -263,6 +263,7 @@ static inline int tcg_target_const_match(tcg_target_long val,
#define OPC_MOVB_EvGv (0x88) /* stores, more or less */
#define OPC_MOVL_EvGv (0x89) /* stores, more or less */
#define OPC_MOVL_GvEv (0x8b) /* loads, more or less */
+#define OPC_MOVB_EvIz (0xc6)
#define OPC_MOVL_EvIz (0xc7)
#define OPC_MOVL_Iv (0xb8)
#define OPC_MOVSBL (0xbe | P_EXT)
@@ -1543,18 +1544,35 @@ static inline void tcg_out_op(TCGContext *s, TCGOpcode opc,
break;
OP_32_64(st8):
- tcg_out_modrm_offset(s, OPC_MOVB_EvGv | P_REXB_R,
- args[0], args[1], args[2]);
+ if (const_args[0]) {
+ tcg_out_modrm_offset(s, OPC_MOVB_EvIz,
+ 0, args[1], args[2]);
+ tcg_out8(s, args[0]);
+ } else {
+ tcg_out_modrm_offset(s, OPC_MOVB_EvGv | P_REXB_R,
+ args[0], args[1], args[2]);
+ }
break;
OP_32_64(st16):
- tcg_out_modrm_offset(s, OPC_MOVL_EvGv | P_DATA16,
- args[0], args[1], args[2]);
+ if (const_args[0]) {
+ tcg_out_modrm_offset(s, OPC_MOVL_EvIz | P_DATA16,
+ 0, args[1], args[2]);
+ tcg_out16(s, args[0]);
+ } else {
+ tcg_out_modrm_offset(s, OPC_MOVL_EvGv | P_DATA16,
+ args[0], args[1], args[2]);
+ }
break;
#if TCG_TARGET_REG_BITS == 64
case INDEX_op_st32_i64:
#endif
case INDEX_op_st_i32:
- tcg_out_st(s, TCG_TYPE_I32, args[0], args[1], args[2]);
+ if (const_args[0]) {
+ tcg_out_modrm_offset(s, OPC_MOVL_EvIz, 0, args[1], args[2]);
+ tcg_out32(s, args[0]);
+ } else {
+ tcg_out_st(s, TCG_TYPE_I32, args[0], args[1], args[2]);
+ }
break;
OP_32_64(add):
@@ -1758,7 +1776,13 @@ static inline void tcg_out_op(TCGContext *s, TCGOpcode opc,
tcg_out_ld(s, TCG_TYPE_I64, args[0], args[1], args[2]);
break;
case INDEX_op_st_i64:
- tcg_out_st(s, TCG_TYPE_I64, args[0], args[1], args[2]);
+ if (const_args[0]) {
+ tcg_out_modrm_offset(s, OPC_MOVL_EvIz | P_REXW,
+ 0, args[1], args[2]);
+ tcg_out32(s, args[0]);
+ } else {
+ tcg_out_st(s, TCG_TYPE_I64, args[0], args[1], args[2]);
+ }
break;
case INDEX_op_qemu_ld32s:
tcg_out_qemu_ld(s, args, 2 | 4);
@@ -1820,9 +1844,9 @@ static const TCGTargetOpDef x86_op_defs[] = {
{ INDEX_op_ld16u_i32, { "r", "r" } },
{ INDEX_op_ld16s_i32, { "r", "r" } },
{ INDEX_op_ld_i32, { "r", "r" } },
- { INDEX_op_st8_i32, { "q", "r" } },
- { INDEX_op_st16_i32, { "r", "r" } },
- { INDEX_op_st_i32, { "r", "r" } },
+ { INDEX_op_st8_i32, { "qi", "r" } },
+ { INDEX_op_st16_i32, { "ri", "r" } },
+ { INDEX_op_st_i32, { "ri", "r" } },
{ INDEX_op_add_i32, { "r", "r", "ri" } },
{ INDEX_op_sub_i32, { "r", "0", "ri" } },
@@ -1873,10 +1897,10 @@ static const TCGTargetOpDef x86_op_defs[] = {
{ INDEX_op_ld32u_i64, { "r", "r" } },
{ INDEX_op_ld32s_i64, { "r", "r" } },
{ INDEX_op_ld_i64, { "r", "r" } },
- { INDEX_op_st8_i64, { "r", "r" } },
- { INDEX_op_st16_i64, { "r", "r" } },
- { INDEX_op_st32_i64, { "r", "r" } },
- { INDEX_op_st_i64, { "r", "r" } },
+ { INDEX_op_st8_i64, { "ri", "r" } },
+ { INDEX_op_st16_i64, { "ri", "r" } },
+ { INDEX_op_st32_i64, { "ri", "r" } },
+ { INDEX_op_st_i64, { "re", "r" } },
{ INDEX_op_add_i64, { "r", "0", "re" } },
{ INDEX_op_mul_i64, { "r", "0", "re" } },
--
1.7.12.1

View File

@ -0,0 +1,53 @@
From 1610a0e56c0be3e4bfd3034e5323188b1d05badd Mon Sep 17 00:00:00 2001
From: Aurelien Jarno <aurelien@aurel32.net>
Date: Mon, 10 Sep 2012 14:23:49 +0200
Subject: [PATCH] tcg: mark set_label with TCG_OPF_BB_END flag
set_label is effectively the end of a basic block, as no optimization
can be made accross it. It was treated as such in the liveness analysis
code, but as a special case.
Mark it with TCG_OPF_BB_END flag so that this information can be used
by other parts of the TCG code, and remove the special case in the liveness
analysis code.
Cc: Blue Swirl <blauwirbel@gmail.com>
Signed-off-by: Aurelien Jarno <aurelien@aurel32.net>
Signed-off-by: Michael Roth <mdroth@linux.vnet.ibm.com>
---
tcg/tcg-opc.h | 2 +-
tcg/tcg.c | 5 -----
2 files changed, 1 insertion(+), 6 deletions(-)
diff --git a/tcg/tcg-opc.h b/tcg/tcg-opc.h
index 8e06d03..d12e8d0 100644
--- a/tcg/tcg-opc.h
+++ b/tcg/tcg-opc.h
@@ -36,7 +36,7 @@ DEF(nopn, 0, 0, 1, 0) /* variable number of parameters */
DEF(discard, 1, 0, 0, 0)
-DEF(set_label, 0, 0, 1, 0)
+DEF(set_label, 0, 0, 1, TCG_OPF_BB_END)
DEF(call, 0, 1, 2, TCG_OPF_SIDE_EFFECTS) /* variable number of parameters */
DEF(jmp, 0, 1, 0, TCG_OPF_BB_END | TCG_OPF_SIDE_EFFECTS)
DEF(br, 0, 0, 1, TCG_OPF_BB_END | TCG_OPF_SIDE_EFFECTS)
diff --git a/tcg/tcg.c b/tcg/tcg.c
index 8386b70..c002a88 100644
--- a/tcg/tcg.c
+++ b/tcg/tcg.c
@@ -1297,11 +1297,6 @@ static void tcg_liveness_analysis(TCGContext *s)
args--;
}
break;
- case INDEX_op_set_label:
- args--;
- /* mark end of basic block */
- tcg_la_bb_end(s, dead_temps);
- break;
case INDEX_op_debug_insn_start:
args -= def->nb_args;
break;
--
1.7.12.1

View File

@ -0,0 +1,85 @@
From 2b8d0049e88c17749ccb978509d3f8fda180d35f Mon Sep 17 00:00:00 2001
From: Aurelien Jarno <aurelien@aurel32.net>
Date: Mon, 10 Sep 2012 13:14:12 +0200
Subject: [PATCH] revert "TCG: fix copy propagation"
Given the copy propagation breakage on 32-bit hosts has been fixed
commit e31b0a7c050711884ad570fe73df806520953618 can be reverted.
Cc: Blue Swirl <blauwirbel@gmail.com>
Signed-off-by: Aurelien Jarno <aurelien@aurel32.net>
Signed-off-by: Michael Roth <mdroth@linux.vnet.ibm.com>
---
tcg/optimize.c | 15 ++++++---------
tcg/tcg.h | 5 -----
2 files changed, 6 insertions(+), 14 deletions(-)
diff --git a/tcg/optimize.c b/tcg/optimize.c
index fba0ed9..10d9773 100644
--- a/tcg/optimize.c
+++ b/tcg/optimize.c
@@ -107,15 +107,12 @@ static TCGOpcode op_to_movi(TCGOpcode op)
}
}
-static void tcg_opt_gen_mov(TCGContext *s, TCGArg *gen_args, TCGArg dst,
- TCGArg src, int nb_temps, int nb_globals)
+static void tcg_opt_gen_mov(TCGArg *gen_args, TCGArg dst, TCGArg src,
+ int nb_temps, int nb_globals)
{
reset_temp(dst, nb_temps, nb_globals);
assert(temps[src].state != TCG_TEMP_COPY);
- /* Don't try to copy if one of temps is a global or either one
- is local and another is register */
- if (src >= nb_globals && dst >= nb_globals &&
- tcg_arg_is_local(s, src) == tcg_arg_is_local(s, dst)) {
+ if (src >= nb_globals) {
assert(temps[src].state != TCG_TEMP_CONST);
if (temps[src].state != TCG_TEMP_HAS_COPY) {
temps[src].state = TCG_TEMP_HAS_COPY;
@@ -444,7 +441,7 @@ static TCGArg *tcg_constant_folding(TCGContext *s, uint16_t *tcg_opc_ptr,
gen_opc_buf[op_index] = INDEX_op_nop;
} else {
gen_opc_buf[op_index] = op_to_mov(op);
- tcg_opt_gen_mov(s, gen_args, args[0], args[1],
+ tcg_opt_gen_mov(gen_args, args[0], args[1],
nb_temps, nb_globals);
gen_args += 2;
}
@@ -482,7 +479,7 @@ static TCGArg *tcg_constant_folding(TCGContext *s, uint16_t *tcg_opc_ptr,
gen_opc_buf[op_index] = INDEX_op_nop;
} else {
gen_opc_buf[op_index] = op_to_mov(op);
- tcg_opt_gen_mov(s, gen_args, args[0], args[1], nb_temps,
+ tcg_opt_gen_mov(gen_args, args[0], args[1], nb_temps,
nb_globals);
gen_args += 2;
}
@@ -507,7 +504,7 @@ static TCGArg *tcg_constant_folding(TCGContext *s, uint16_t *tcg_opc_ptr,
break;
}
if (temps[args[1]].state != TCG_TEMP_CONST) {
- tcg_opt_gen_mov(s, gen_args, args[0], args[1],
+ tcg_opt_gen_mov(gen_args, args[0], args[1],
nb_temps, nb_globals);
gen_args += 2;
args += 2;
diff --git a/tcg/tcg.h b/tcg/tcg.h
index d710694..8fbbc81 100644
--- a/tcg/tcg.h
+++ b/tcg/tcg.h
@@ -458,11 +458,6 @@ static inline TCGv_i64 tcg_temp_local_new_i64(void)
void tcg_temp_free_i64(TCGv_i64 arg);
char *tcg_get_arg_str_i64(TCGContext *s, char *buf, int buf_size, TCGv_i64 arg);
-static inline bool tcg_arg_is_local(TCGContext *s, TCGArg arg)
-{
- return s->temps[arg].temp_local;
-}
-
#if defined(CONFIG_DEBUG_TCG)
/* If you call tcg_clear_temp_count() at the start of a section of
* code which is not supposed to leak any TCG temporaries, then
--
1.7.12.1

View File

@ -0,0 +1,55 @@
From 3380afc68a701604e51fa22637ef48d93514d678 Mon Sep 17 00:00:00 2001
From: Richard Henderson <rth@twiddle.net>
Date: Tue, 18 Sep 2012 21:55:32 -0700
Subject: [PATCH] target-mips: Set opn in gen_ldst_multiple.
Used by MIPS_DEBUG, when enabled.
Signed-off-by: Richard Henderson <rth@twiddle.net>
Acked-by: Aurelien Jarno <aurelien@aurel32.net>
Signed-off-by: Aurelien Jarno <aurelien@aurel32.net>
Signed-off-by: Michael Roth <mdroth@linux.vnet.ibm.com>
---
target-mips/translate.c | 6 ++++++
1 file changed, 6 insertions(+)
diff --git a/target-mips/translate.c b/target-mips/translate.c
index 7ab769f..c31f91c 100644
--- a/target-mips/translate.c
+++ b/target-mips/translate.c
@@ -9855,6 +9855,7 @@ static void gen_andi16 (CPUMIPSState *env, DisasContext *ctx)
static void gen_ldst_multiple (DisasContext *ctx, uint32_t opc, int reglist,
int base, int16_t offset)
{
+ const char *opn = "ldst_multiple";
TCGv t0, t1;
TCGv_i32 t2;
@@ -9874,19 +9875,24 @@ static void gen_ldst_multiple (DisasContext *ctx, uint32_t opc, int reglist,
switch (opc) {
case LWM32:
gen_helper_lwm(cpu_env, t0, t1, t2);
+ opn = "lwm";
break;
case SWM32:
gen_helper_swm(cpu_env, t0, t1, t2);
+ opn = "swm";
break;
#ifdef TARGET_MIPS64
case LDM:
gen_helper_ldm(cpu_env, t0, t1, t2);
+ opn = "ldm";
break;
case SDM:
gen_helper_sdm(cpu_env, t0, t1, t2);
+ opn = "sdm";
break;
#endif
}
+ (void)opn;
MIPS_DEBUG("%s, %x, %d(%s)", opn, reglist, offset, regnames[base]);
tcg_temp_free(t0);
tcg_temp_free(t1);
--
1.7.12.1

View File

@ -0,0 +1,288 @@
From 5dd8e9207a39d8fe41eaa110edfdba5e37064562 Mon Sep 17 00:00:00 2001
From: Richard Henderson <rth@twiddle.net>
Date: Tue, 18 Sep 2012 21:55:33 -0700
Subject: [PATCH] target-mips: Fix MIPS_DEBUG.
The macro uses the DisasContext. Pass it around as needed.
Signed-off-by: Richard Henderson <rth@twiddle.net>
Acked-by: Aurelien Jarno <aurelien@aurel32.net>
Signed-off-by: Aurelien Jarno <aurelien@aurel32.net>
Signed-off-by: Michael Roth <mdroth@linux.vnet.ibm.com>
---
target-mips/translate.c | 74 +++++++++++++++++++++++++------------------------
1 file changed, 38 insertions(+), 36 deletions(-)
diff --git a/target-mips/translate.c b/target-mips/translate.c
index c31f91c..4937f6b 100644
--- a/target-mips/translate.c
+++ b/target-mips/translate.c
@@ -1431,7 +1431,8 @@ static void gen_arith_imm (CPUMIPSState *env, DisasContext *ctx, uint32_t opc,
}
/* Logic with immediate operand */
-static void gen_logic_imm (CPUMIPSState *env, uint32_t opc, int rt, int rs, int16_t imm)
+static void gen_logic_imm(CPUMIPSState *env, DisasContext *ctx, uint32_t opc,
+ int rt, int rs, int16_t imm)
{
target_ulong uimm;
const char *opn = "imm logic";
@@ -1474,7 +1475,8 @@ static void gen_logic_imm (CPUMIPSState *env, uint32_t opc, int rt, int rs, int1
}
/* Set on less than with immediate operand */
-static void gen_slt_imm (CPUMIPSState *env, uint32_t opc, int rt, int rs, int16_t imm)
+static void gen_slt_imm(CPUMIPSState *env, DisasContext *ctx, uint32_t opc,
+ int rt, int rs, int16_t imm)
{
target_ulong uimm = (target_long)imm; /* Sign extend to 32/64 bits */
const char *opn = "imm arith";
@@ -1775,7 +1777,8 @@ static void gen_arith (CPUMIPSState *env, DisasContext *ctx, uint32_t opc,
}
/* Conditional move */
-static void gen_cond_move (CPUMIPSState *env, uint32_t opc, int rd, int rs, int rt)
+static void gen_cond_move(CPUMIPSState *env, DisasContext *ctx, uint32_t opc,
+ int rd, int rs, int rt)
{
const char *opn = "cond move";
int l1;
@@ -1813,7 +1816,8 @@ static void gen_cond_move (CPUMIPSState *env, uint32_t opc, int rd, int rs, int
}
/* Logic */
-static void gen_logic (CPUMIPSState *env, uint32_t opc, int rd, int rs, int rt)
+static void gen_logic(CPUMIPSState *env, DisasContext *ctx, uint32_t opc,
+ int rd, int rs, int rt)
{
const char *opn = "logic";
@@ -1874,7 +1878,8 @@ static void gen_logic (CPUMIPSState *env, uint32_t opc, int rd, int rs, int rt)
}
/* Set on lower than */
-static void gen_slt (CPUMIPSState *env, uint32_t opc, int rd, int rs, int rt)
+static void gen_slt(CPUMIPSState *env, DisasContext *ctx, uint32_t opc,
+ int rd, int rs, int rt)
{
const char *opn = "slt";
TCGv t0, t1;
@@ -8778,10 +8783,10 @@ static int decode_extended_mips16_opc (CPUMIPSState *env, DisasContext *ctx,
gen_arith_imm(env, ctx, OPC_ADDIU, rx, rx, imm);
break;
case M16_OPC_SLTI:
- gen_slt_imm(env, OPC_SLTI, 24, rx, imm);
+ gen_slt_imm(env, ctx, OPC_SLTI, 24, rx, imm);
break;
case M16_OPC_SLTIU:
- gen_slt_imm(env, OPC_SLTIU, 24, rx, imm);
+ gen_slt_imm(env, ctx, OPC_SLTIU, 24, rx, imm);
break;
case M16_OPC_I8:
switch (funct) {
@@ -8992,15 +8997,13 @@ static int decode_mips16_opc (CPUMIPSState *env, DisasContext *ctx,
case M16_OPC_SLTI:
{
int16_t imm = (uint8_t) ctx->opcode;
-
- gen_slt_imm(env, OPC_SLTI, 24, rx, imm);
+ gen_slt_imm(env, ctx, OPC_SLTI, 24, rx, imm);
}
break;
case M16_OPC_SLTIU:
{
int16_t imm = (uint8_t) ctx->opcode;
-
- gen_slt_imm(env, OPC_SLTIU, 24, rx, imm);
+ gen_slt_imm(env, ctx, OPC_SLTIU, 24, rx, imm);
}
break;
case M16_OPC_I8:
@@ -9075,8 +9078,7 @@ static int decode_mips16_opc (CPUMIPSState *env, DisasContext *ctx,
case M16_OPC_CMPI:
{
int16_t imm = (uint8_t) ctx->opcode;
-
- gen_logic_imm(env, OPC_XORI, 24, rx, imm);
+ gen_logic_imm(env, ctx, OPC_XORI, 24, rx, imm);
}
break;
#if defined(TARGET_MIPS64)
@@ -9188,10 +9190,10 @@ static int decode_mips16_opc (CPUMIPSState *env, DisasContext *ctx,
}
break;
case RR_SLT:
- gen_slt(env, OPC_SLT, 24, rx, ry);
+ gen_slt(env, ctx, OPC_SLT, 24, rx, ry);
break;
case RR_SLTU:
- gen_slt(env, OPC_SLTU, 24, rx, ry);
+ gen_slt(env, ctx, OPC_SLTU, 24, rx, ry);
break;
case RR_BREAK:
generate_exception(ctx, EXCP_BREAK);
@@ -9212,22 +9214,22 @@ static int decode_mips16_opc (CPUMIPSState *env, DisasContext *ctx,
break;
#endif
case RR_CMP:
- gen_logic(env, OPC_XOR, 24, rx, ry);
+ gen_logic(env, ctx, OPC_XOR, 24, rx, ry);
break;
case RR_NEG:
gen_arith(env, ctx, OPC_SUBU, rx, 0, ry);
break;
case RR_AND:
- gen_logic(env, OPC_AND, rx, rx, ry);
+ gen_logic(env, ctx, OPC_AND, rx, rx, ry);
break;
case RR_OR:
- gen_logic(env, OPC_OR, rx, rx, ry);
+ gen_logic(env, ctx, OPC_OR, rx, rx, ry);
break;
case RR_XOR:
- gen_logic(env, OPC_XOR, rx, rx, ry);
+ gen_logic(env, ctx, OPC_XOR, rx, rx, ry);
break;
case RR_NOT:
- gen_logic(env, OPC_NOR, rx, ry, 0);
+ gen_logic(env, ctx, OPC_NOR, rx, ry, 0);
break;
case RR_MFHI:
gen_HILO(ctx, OPC_MFHI, rx);
@@ -9849,7 +9851,7 @@ static void gen_andi16 (CPUMIPSState *env, DisasContext *ctx)
int rs = mmreg(uMIPS_RS(ctx->opcode));
int encoded = ZIMM(ctx->opcode, 0, 4);
- gen_logic_imm(env, OPC_ANDI, rd, rs, decoded_imm[encoded]);
+ gen_logic_imm(env, ctx, OPC_ANDI, rd, rs, decoded_imm[encoded]);
}
static void gen_ldst_multiple (DisasContext *ctx, uint32_t opc, int reglist,
@@ -9911,25 +9913,25 @@ static void gen_pool16c_insn (CPUMIPSState *env, DisasContext *ctx, int *is_bran
case NOT16 + 1:
case NOT16 + 2:
case NOT16 + 3:
- gen_logic(env, OPC_NOR, rd, rs, 0);
+ gen_logic(env, ctx, OPC_NOR, rd, rs, 0);
break;
case XOR16 + 0:
case XOR16 + 1:
case XOR16 + 2:
case XOR16 + 3:
- gen_logic(env, OPC_XOR, rd, rd, rs);
+ gen_logic(env, ctx, OPC_XOR, rd, rd, rs);
break;
case AND16 + 0:
case AND16 + 1:
case AND16 + 2:
case AND16 + 3:
- gen_logic(env, OPC_AND, rd, rd, rs);
+ gen_logic(env, ctx, OPC_AND, rd, rd, rs);
break;
case OR16 + 0:
case OR16 + 1:
case OR16 + 2:
case OR16 + 3:
- gen_logic(env, OPC_OR, rd, rd, rs);
+ gen_logic(env, ctx, OPC_OR, rd, rd, rs);
break;
case LWM16 + 0:
case LWM16 + 1:
@@ -10743,7 +10745,7 @@ static void decode_micromips32_opc (CPUMIPSState *env, DisasContext *ctx,
case XOR32:
mips32_op = OPC_XOR;
do_logic:
- gen_logic(env, mips32_op, rd, rs, rt);
+ gen_logic(env, ctx, mips32_op, rd, rs, rt);
break;
/* Set less than */
case SLT:
@@ -10752,7 +10754,7 @@ static void decode_micromips32_opc (CPUMIPSState *env, DisasContext *ctx,
case SLTU:
mips32_op = OPC_SLTU;
do_slt:
- gen_slt(env, mips32_op, rd, rs, rt);
+ gen_slt(env, ctx, mips32_op, rd, rs, rt);
break;
default:
goto pool32a_invalid;
@@ -10768,7 +10770,7 @@ static void decode_micromips32_opc (CPUMIPSState *env, DisasContext *ctx,
case MOVZ:
mips32_op = OPC_MOVZ;
do_cmov:
- gen_cond_move(env, mips32_op, rd, rs, rt);
+ gen_cond_move(env, ctx, mips32_op, rd, rs, rt);
break;
case LWXS:
gen_ldxs(ctx, rs, rt, rd);
@@ -11181,7 +11183,7 @@ static void decode_micromips32_opc (CPUMIPSState *env, DisasContext *ctx,
target. */
break;
case LUI:
- gen_logic_imm(env, OPC_LUI, rs, -1, imm);
+ gen_logic_imm(env, ctx, OPC_LUI, rs, -1, imm);
break;
case SYNCI:
break;
@@ -11300,7 +11302,7 @@ static void decode_micromips32_opc (CPUMIPSState *env, DisasContext *ctx,
case ANDI32:
mips32_op = OPC_ANDI;
do_logici:
- gen_logic_imm(env, mips32_op, rt, rs, imm);
+ gen_logic_imm(env, ctx, mips32_op, rt, rs, imm);
break;
/* Set less than immediate */
@@ -11310,7 +11312,7 @@ static void decode_micromips32_opc (CPUMIPSState *env, DisasContext *ctx,
case SLTIU32:
mips32_op = OPC_SLTIU;
do_slti:
- gen_slt_imm(env, mips32_op, rt, rs, imm);
+ gen_slt_imm(env, ctx, mips32_op, rt, rs, imm);
break;
case JALX32:
offset = (int32_t)(ctx->opcode & 0x3FFFFFF) << 2;
@@ -11787,7 +11789,7 @@ static void decode_opc (CPUMIPSState *env, DisasContext *ctx, int *is_branch)
case OPC_MOVZ:
check_insn(env, ctx, ISA_MIPS4 | ISA_MIPS32 |
INSN_LOONGSON2E | INSN_LOONGSON2F);
- gen_cond_move(env, op1, rd, rs, rt);
+ gen_cond_move(env, ctx, op1, rd, rs, rt);
break;
case OPC_ADD ... OPC_SUBU:
gen_arith(env, ctx, op1, rd, rs, rt);
@@ -11814,13 +11816,13 @@ static void decode_opc (CPUMIPSState *env, DisasContext *ctx, int *is_branch)
break;
case OPC_SLT: /* Set on less than */
case OPC_SLTU:
- gen_slt(env, op1, rd, rs, rt);
+ gen_slt(env, ctx, op1, rd, rs, rt);
break;
case OPC_AND: /* Logic*/
case OPC_OR:
case OPC_NOR:
case OPC_XOR:
- gen_logic(env, op1, rd, rs, rt);
+ gen_logic(env, ctx, op1, rd, rs, rt);
break;
case OPC_MULT ... OPC_DIVU:
if (sa) {
@@ -12221,13 +12223,13 @@ static void decode_opc (CPUMIPSState *env, DisasContext *ctx, int *is_branch)
break;
case OPC_SLTI: /* Set on less than with immediate opcode */
case OPC_SLTIU:
- gen_slt_imm(env, op, rt, rs, imm);
+ gen_slt_imm(env, ctx, op, rt, rs, imm);
break;
case OPC_ANDI: /* Arithmetic with immediate opcode */
case OPC_LUI:
case OPC_ORI:
case OPC_XORI:
- gen_logic_imm(env, op, rt, rs, imm);
+ gen_logic_imm(env, ctx, op, rt, rs, imm);
break;
case OPC_J ... OPC_JAL: /* Jump */
offset = (int32_t)(ctx->opcode & 0x3FFFFFF) << 2;
--
1.7.12.1

View File

@ -0,0 +1,70 @@
From e6f923b4e3e71661343f6d2eecd7f102022e5635 Mon Sep 17 00:00:00 2001
From: Richard Henderson <rth@twiddle.net>
Date: Tue, 18 Sep 2012 21:55:34 -0700
Subject: [PATCH] target-mips: Always evaluate debugging macro arguments
this will prevent some of the compilation errors with debugging
enabled from creeping back in.
Signed-off-by: Richard Henderson <rth@twiddle.net>
Signed-off-by: Aurelien Jarno <aurelien@aurel32.net>
Signed-off-by: Michael Roth <mdroth@linux.vnet.ibm.com>
---
target-mips/translate.c | 31 +++++++++++++++++--------------
1 file changed, 17 insertions(+), 14 deletions(-)
diff --git a/target-mips/translate.c b/target-mips/translate.c
index 4937f6b..aba7935 100644
--- a/target-mips/translate.c
+++ b/target-mips/translate.c
@@ -28,7 +28,7 @@
#define GEN_HELPER 1
#include "helper.h"
-//#define MIPS_DEBUG_DISAS
+#define MIPS_DEBUG_DISAS 0
//#define MIPS_DEBUG_SIGN_EXTENSIONS
/* MIPS major opcodes */
@@ -566,22 +566,25 @@ static const char *fregnames[] =
"f16", "f17", "f18", "f19", "f20", "f21", "f22", "f23",
"f24", "f25", "f26", "f27", "f28", "f29", "f30", "f31", };
-#ifdef MIPS_DEBUG_DISAS
-#define MIPS_DEBUG(fmt, ...) \
- qemu_log_mask(CPU_LOG_TB_IN_ASM, \
- TARGET_FMT_lx ": %08x " fmt "\n", \
- ctx->pc, ctx->opcode , ## __VA_ARGS__)
-#define LOG_DISAS(...) qemu_log_mask(CPU_LOG_TB_IN_ASM, ## __VA_ARGS__)
-#else
-#define MIPS_DEBUG(fmt, ...) do { } while(0)
-#define LOG_DISAS(...) do { } while (0)
-#endif
+#define MIPS_DEBUG(fmt, ...) \
+ do { \
+ if (MIPS_DEBUG_DISAS) { \
+ qemu_log_mask(CPU_LOG_TB_IN_ASM, \
+ TARGET_FMT_lx ": %08x " fmt "\n", \
+ ctx->pc, ctx->opcode , ## __VA_ARGS__); \
+ } \
+ } while (0)
+
+#define LOG_DISAS(...) \
+ do { \
+ if (MIPS_DEBUG_DISAS) { \
+ qemu_log_mask(CPU_LOG_TB_IN_ASM, ## __VA_ARGS__); \
+ } \
+ } while (0)
#define MIPS_INVAL(op) \
-do { \
MIPS_DEBUG("Invalid %s %03x %03x %03x", op, ctx->opcode >> 26, \
- ctx->opcode & 0x3F, ((ctx->opcode >> 16) & 0x1F)); \
-} while (0)
+ ctx->opcode & 0x3F, ((ctx->opcode >> 16) & 0x1F))
/* General purpose registers moves. */
static inline void gen_load_gpr (TCGv t, int reg)
--
1.7.12.1

View File

@ -0,0 +1,62 @@
From 4ce7a1e0aaecb220016af9b4f390b76f7fffcce8 Mon Sep 17 00:00:00 2001
From: Aurelien Jarno <aurelien@aurel32.net>
Date: Wed, 19 Sep 2012 21:40:30 +0200
Subject: [PATCH] tcg/optimize: fix end of basic block detection
Commit e31b0a7c050711884ad570fe73df806520953618 fixed copy propagation on
32-bit host by restricting the copy between different types. This was the
wrong fix.
The real problem is that the all temps states should be reset at the end
of a basic block. This was done by adding such operations in the switch,
but brcond2 was forgotten (that's why the crash was only observed on 32-bit
hosts).
Fix that by looking at the TCG_OPF_BB_END instead. We need to keep the case
for op_set_label as temps might be modified through another path.
Cc: Blue Swirl <blauwirbel@gmail.com>
Signed-off-by: Aurelien Jarno <aurelien@aurel32.net>
Signed-off-by: Michael Roth <mdroth@linux.vnet.ibm.com>
---
tcg/optimize.c | 22 +++++++++-------------
1 file changed, 9 insertions(+), 13 deletions(-)
diff --git a/tcg/optimize.c b/tcg/optimize.c
index 10d9773..9da333c 100644
--- a/tcg/optimize.c
+++ b/tcg/optimize.c
@@ -632,21 +632,17 @@ static TCGArg *tcg_constant_folding(TCGContext *s, uint16_t *tcg_opc_ptr,
i--;
}
break;
- case INDEX_op_set_label:
- case INDEX_op_jmp:
- case INDEX_op_br:
- memset(temps, 0, nb_temps * sizeof(struct tcg_temp_info));
- for (i = 0; i < def->nb_args; i++) {
- *gen_args = *args;
- args++;
- gen_args++;
- }
- break;
default:
/* Default case: we do know nothing about operation so no
- propagation is done. We only trash output args. */
- for (i = 0; i < def->nb_oargs; i++) {
- reset_temp(args[i], nb_temps, nb_globals);
+ propagation is done. We trash everything if the operation
+ is the end of a basic block, otherwise we only trash the
+ output args. */
+ if (def->flags & TCG_OPF_BB_END) {
+ memset(temps, 0, nb_temps * sizeof(struct tcg_temp_info));
+ } else {
+ for (i = 0; i < def->nb_oargs; i++) {
+ reset_temp(args[i], nb_temps, nb_globals);
+ }
}
for (i = 0; i < def->nb_args; i++) {
gen_args[i] = args[i];
--
1.7.12.1

View File

@ -0,0 +1,57 @@
From 1c596a9498830485a1b2f4a4445643a149179b99 Mon Sep 17 00:00:00 2001
From: Max Filippov <jcmvbkbc@gmail.com>
Date: Fri, 21 Sep 2012 02:59:49 +0400
Subject: [PATCH] target-xtensa: fix extui shift amount
extui opcode only uses lowermost op1 bit for sa4.
Reported-by: malc <av1474@comtv.ru>
Signed-off-by: Max Filippov <jcmvbkbc@gmail.com>
Cc: qemu-stable <qemu-stable@nongnu.org>
Signed-off-by: malc <av1474@comtv.ru>
Signed-off-by: Michael Roth <mdroth@linux.vnet.ibm.com>
---
target-xtensa/translate.c | 24 +++++++++++++++++++++---
1 file changed, 21 insertions(+), 3 deletions(-)
diff --git a/target-xtensa/translate.c b/target-xtensa/translate.c
index 1900bd5..7a1c528 100644
--- a/target-xtensa/translate.c
+++ b/target-xtensa/translate.c
@@ -1778,12 +1778,30 @@ static void disas_xtensa_insn(DisasContext *dc)
case 5:
gen_window_check2(dc, RRR_R, RRR_T);
{
- int shiftimm = RRR_S | (OP1 << 4);
+ int shiftimm = RRR_S | ((OP1 & 1) << 4);
int maskimm = (1 << (OP2 + 1)) - 1;
TCGv_i32 tmp = tcg_temp_new_i32();
- tcg_gen_shri_i32(tmp, cpu_R[RRR_T], shiftimm);
- tcg_gen_andi_i32(cpu_R[RRR_R], tmp, maskimm);
+
+ if (shiftimm) {
+ tcg_gen_shri_i32(tmp, cpu_R[RRR_T], shiftimm);
+ } else {
+ tcg_gen_mov_i32(tmp, cpu_R[RRR_T]);
+ }
+
+ switch (maskimm) {
+ case 0xff:
+ tcg_gen_ext8u_i32(cpu_R[RRR_R], tmp);
+ break;
+
+ case 0xffff:
+ tcg_gen_ext16u_i32(cpu_R[RRR_R], tmp);
+ break;
+
+ default:
+ tcg_gen_andi_i32(cpu_R[RRR_R], tmp, maskimm);
+ break;
+ }
tcg_temp_free(tmp);
}
break;
--
1.7.12.1

View File

@ -0,0 +1,35 @@
From ba9c2acb955f0453ae80077a791a4d1c27b5d6e6 Mon Sep 17 00:00:00 2001
From: Max Filippov <jcmvbkbc@gmail.com>
Date: Fri, 21 Sep 2012 02:59:50 +0400
Subject: [PATCH] target-xtensa: don't emit extra tcg_gen_goto_tb
Unconditional gen_check_loop_end at the end of disas_xtensa_insn
can emit tcg_gen_goto_tb with slot id already used in the TB (e.g. when
TB ends at LEND with a branch).
Signed-off-by: Max Filippov <jcmvbkbc@gmail.com>
Cc: qemu-stable <qemu-stable@nongnu.org>
Signed-off-by: malc <av1474@comtv.ru>
Signed-off-by: Michael Roth <mdroth@linux.vnet.ibm.com>
---
target-xtensa/translate.c | 4 +++-
1 file changed, 3 insertions(+), 1 deletion(-)
diff --git a/target-xtensa/translate.c b/target-xtensa/translate.c
index 7a1c528..b6643eb 100644
--- a/target-xtensa/translate.c
+++ b/target-xtensa/translate.c
@@ -2520,7 +2520,9 @@ static void disas_xtensa_insn(DisasContext *dc)
break;
}
- gen_check_loop_end(dc, 0);
+ if (dc->is_jmp == DISAS_NEXT) {
+ gen_check_loop_end(dc, 0);
+ }
dc->pc = dc->next_pc;
return;
--
1.7.12.1

View File

@ -0,0 +1,333 @@
From a977d2c7f02eb2ed7fc879979d6f5525c017a881 Mon Sep 17 00:00:00 2001
From: Richard Henderson <rth@twiddle.net>
Date: Fri, 21 Sep 2012 10:13:34 -0700
Subject: [PATCH] tcg: Introduce movcond
Implemented with setcond if the target does not provide
the optional opcode.
Signed-off-by: Richard Henderson <rth@twiddle.net>
Signed-off-by: Aurelien Jarno <aurelien@aurel32.net>
Signed-off-by: Michael Roth <mdroth@linux.vnet.ibm.com>
---
tcg/README | 6 ++++++
tcg/arm/tcg-target.h | 1 +
tcg/hppa/tcg-target.h | 1 +
tcg/i386/tcg-target.h | 2 ++
tcg/ia64/tcg-target.h | 2 ++
tcg/mips/tcg-target.h | 1 +
tcg/ppc/tcg-target.h | 1 +
tcg/ppc64/tcg-target.h | 2 ++
tcg/s390/tcg-target.h | 2 ++
tcg/sparc/tcg-target.h | 2 ++
tcg/tcg-op.h | 40 ++++++++++++++++++++++++++++++++++++++++
tcg/tcg-opc.h | 2 ++
tcg/tcg.c | 11 +++++------
tcg/tcg.h | 1 +
tcg/tci/tcg-target.h | 2 ++
15 files changed, 70 insertions(+), 6 deletions(-)
diff --git a/tcg/README b/tcg/README
index cfdfd96..d03ae05 100644
--- a/tcg/README
+++ b/tcg/README
@@ -307,6 +307,12 @@ dest = (t1 cond t2)
Set DEST to 1 if (T1 cond T2) is true, otherwise set to 0.
+* movcond_i32/i64 cond, dest, c1, c2, v1, v2
+
+dest = (c1 cond c2 ? v1 : v2)
+
+Set DEST to V1 if (C1 cond C2) is true, otherwise set to V2.
+
********* Type conversions
* ext_i32_i64 t0, t1
diff --git a/tcg/arm/tcg-target.h b/tcg/arm/tcg-target.h
index c0b8f72..e2299ca 100644
--- a/tcg/arm/tcg-target.h
+++ b/tcg/arm/tcg-target.h
@@ -73,6 +73,7 @@ typedef enum {
#define TCG_TARGET_HAS_nand_i32 0
#define TCG_TARGET_HAS_nor_i32 0
#define TCG_TARGET_HAS_deposit_i32 0
+#define TCG_TARGET_HAS_movcond_i32 0
#define TCG_TARGET_HAS_GUEST_BASE
diff --git a/tcg/hppa/tcg-target.h b/tcg/hppa/tcg-target.h
index 01ef960..4defd28 100644
--- a/tcg/hppa/tcg-target.h
+++ b/tcg/hppa/tcg-target.h
@@ -96,6 +96,7 @@ typedef enum {
#define TCG_TARGET_HAS_nand_i32 0
#define TCG_TARGET_HAS_nor_i32 0
#define TCG_TARGET_HAS_deposit_i32 1
+#define TCG_TARGET_HAS_movcond_i32 0
/* optional instructions automatically implemented */
#define TCG_TARGET_HAS_neg_i32 0 /* sub rd, 0, rs */
diff --git a/tcg/i386/tcg-target.h b/tcg/i386/tcg-target.h
index 8be42f3..504f953 100644
--- a/tcg/i386/tcg-target.h
+++ b/tcg/i386/tcg-target.h
@@ -86,6 +86,7 @@ typedef enum {
#define TCG_TARGET_HAS_nand_i32 0
#define TCG_TARGET_HAS_nor_i32 0
#define TCG_TARGET_HAS_deposit_i32 1
+#define TCG_TARGET_HAS_movcond_i32 0
#if TCG_TARGET_REG_BITS == 64
#define TCG_TARGET_HAS_div2_i64 1
@@ -107,6 +108,7 @@ typedef enum {
#define TCG_TARGET_HAS_nand_i64 0
#define TCG_TARGET_HAS_nor_i64 0
#define TCG_TARGET_HAS_deposit_i64 1
+#define TCG_TARGET_HAS_movcond_i64 0
#endif
#define TCG_TARGET_deposit_i32_valid(ofs, len) \
diff --git a/tcg/ia64/tcg-target.h b/tcg/ia64/tcg-target.h
index c22962a..368aee4 100644
--- a/tcg/ia64/tcg-target.h
+++ b/tcg/ia64/tcg-target.h
@@ -133,6 +133,8 @@ typedef enum {
#define TCG_TARGET_HAS_rot_i64 1
#define TCG_TARGET_HAS_deposit_i32 0
#define TCG_TARGET_HAS_deposit_i64 0
+#define TCG_TARGET_HAS_movcond_i32 0
+#define TCG_TARGET_HAS_movcond_i64 0
/* optional instructions automatically implemented */
#define TCG_TARGET_HAS_neg_i32 0 /* sub r1, r0, r3 */
diff --git a/tcg/mips/tcg-target.h b/tcg/mips/tcg-target.h
index 1c61931..9c68a32 100644
--- a/tcg/mips/tcg-target.h
+++ b/tcg/mips/tcg-target.h
@@ -90,6 +90,7 @@ typedef enum {
#define TCG_TARGET_HAS_eqv_i32 0
#define TCG_TARGET_HAS_nand_i32 0
#define TCG_TARGET_HAS_deposit_i32 0
+#define TCG_TARGET_HAS_movcond_i32 0
/* optional instructions automatically implemented */
#define TCG_TARGET_HAS_neg_i32 0 /* sub rd, zero, rt */
diff --git a/tcg/ppc/tcg-target.h b/tcg/ppc/tcg-target.h
index 2f37fd2..177eea1 100644
--- a/tcg/ppc/tcg-target.h
+++ b/tcg/ppc/tcg-target.h
@@ -92,6 +92,7 @@ typedef enum {
#define TCG_TARGET_HAS_nand_i32 1
#define TCG_TARGET_HAS_nor_i32 1
#define TCG_TARGET_HAS_deposit_i32 1
+#define TCG_TARGET_HAS_movcond_i32 0
#define TCG_AREG0 TCG_REG_R27
diff --git a/tcg/ppc64/tcg-target.h b/tcg/ppc64/tcg-target.h
index 97eec08..57569e8 100644
--- a/tcg/ppc64/tcg-target.h
+++ b/tcg/ppc64/tcg-target.h
@@ -83,6 +83,7 @@ typedef enum {
#define TCG_TARGET_HAS_nand_i32 0
#define TCG_TARGET_HAS_nor_i32 0
#define TCG_TARGET_HAS_deposit_i32 0
+#define TCG_TARGET_HAS_movcond_i32 0
#define TCG_TARGET_HAS_div_i64 1
#define TCG_TARGET_HAS_rot_i64 0
@@ -103,6 +104,7 @@ typedef enum {
#define TCG_TARGET_HAS_nand_i64 0
#define TCG_TARGET_HAS_nor_i64 0
#define TCG_TARGET_HAS_deposit_i64 0
+#define TCG_TARGET_HAS_movcond_i64 0
#define TCG_AREG0 TCG_REG_R27
diff --git a/tcg/s390/tcg-target.h b/tcg/s390/tcg-target.h
index 4f7dfab..ed55c33 100644
--- a/tcg/s390/tcg-target.h
+++ b/tcg/s390/tcg-target.h
@@ -63,6 +63,7 @@ typedef enum TCGReg {
#define TCG_TARGET_HAS_nand_i32 0
#define TCG_TARGET_HAS_nor_i32 0
#define TCG_TARGET_HAS_deposit_i32 0
+#define TCG_TARGET_HAS_movcond_i32 0
#if TCG_TARGET_REG_BITS == 64
#define TCG_TARGET_HAS_div2_i64 1
@@ -84,6 +85,7 @@ typedef enum TCGReg {
#define TCG_TARGET_HAS_nand_i64 0
#define TCG_TARGET_HAS_nor_i64 0
#define TCG_TARGET_HAS_deposit_i64 0
+#define TCG_TARGET_HAS_movcond_i64 0
#endif
#define TCG_TARGET_HAS_GUEST_BASE
diff --git a/tcg/sparc/tcg-target.h b/tcg/sparc/tcg-target.h
index 0ea87be..d762574 100644
--- a/tcg/sparc/tcg-target.h
+++ b/tcg/sparc/tcg-target.h
@@ -102,6 +102,7 @@ typedef enum {
#define TCG_TARGET_HAS_nand_i32 0
#define TCG_TARGET_HAS_nor_i32 0
#define TCG_TARGET_HAS_deposit_i32 0
+#define TCG_TARGET_HAS_movcond_i32 0
#if TCG_TARGET_REG_BITS == 64
#define TCG_TARGET_HAS_div_i64 1
@@ -123,6 +124,7 @@ typedef enum {
#define TCG_TARGET_HAS_nand_i64 0
#define TCG_TARGET_HAS_nor_i64 0
#define TCG_TARGET_HAS_deposit_i64 0
+#define TCG_TARGET_HAS_movcond_i64 0
#endif
#ifdef CONFIG_SOLARIS
diff --git a/tcg/tcg-op.h b/tcg/tcg-op.h
index 169d3b2..6d28f82 100644
--- a/tcg/tcg-op.h
+++ b/tcg/tcg-op.h
@@ -2118,6 +2118,44 @@ static inline void tcg_gen_deposit_i64(TCGv_i64 ret, TCGv_i64 arg1,
tcg_temp_free_i64(t1);
}
+static inline void tcg_gen_movcond_i32(TCGCond cond, TCGv_i32 ret,
+ TCGv_i32 c1, TCGv_i32 c2,
+ TCGv_i32 v1, TCGv_i32 v2)
+{
+ if (TCG_TARGET_HAS_movcond_i32) {
+ tcg_gen_op6i_i32(INDEX_op_movcond_i32, ret, c1, c2, v1, v2, cond);
+ } else {
+ TCGv_i32 t0 = tcg_temp_new_i32();
+ TCGv_i32 t1 = tcg_temp_new_i32();
+ tcg_gen_setcond_i32(cond, t0, c1, c2);
+ tcg_gen_neg_i32(t0, t0);
+ tcg_gen_and_i32(t1, v1, t0);
+ tcg_gen_andc_i32(ret, v2, t0);
+ tcg_gen_or_i32(ret, ret, t1);
+ tcg_temp_free_i32(t0);
+ tcg_temp_free_i32(t1);
+ }
+}
+
+static inline void tcg_gen_movcond_i64(TCGCond cond, TCGv_i64 ret,
+ TCGv_i64 c1, TCGv_i64 c2,
+ TCGv_i64 v1, TCGv_i64 v2)
+{
+ if (TCG_TARGET_HAS_movcond_i64) {
+ tcg_gen_op6i_i64(INDEX_op_movcond_i64, ret, c1, c2, v1, v2, cond);
+ } else {
+ TCGv_i64 t0 = tcg_temp_new_i64();
+ TCGv_i64 t1 = tcg_temp_new_i64();
+ tcg_gen_setcond_i64(cond, t0, c1, c2);
+ tcg_gen_neg_i64(t0, t0);
+ tcg_gen_and_i64(t1, v1, t0);
+ tcg_gen_andc_i64(ret, v2, t0);
+ tcg_gen_or_i64(ret, ret, t1);
+ tcg_temp_free_i64(t0);
+ tcg_temp_free_i64(t1);
+ }
+}
+
/***************************************/
/* QEMU specific operations. Their type depend on the QEMU CPU
type. */
@@ -2434,6 +2472,7 @@ static inline void tcg_gen_qemu_st64(TCGv_i64 arg, TCGv addr, int mem_index)
#define tcg_gen_deposit_tl tcg_gen_deposit_i64
#define tcg_const_tl tcg_const_i64
#define tcg_const_local_tl tcg_const_local_i64
+#define tcg_gen_movcond_tl tcg_gen_movcond_i64
#else
#define tcg_gen_movi_tl tcg_gen_movi_i32
#define tcg_gen_mov_tl tcg_gen_mov_i32
@@ -2505,6 +2544,7 @@ static inline void tcg_gen_qemu_st64(TCGv_i64 arg, TCGv addr, int mem_index)
#define tcg_gen_deposit_tl tcg_gen_deposit_i32
#define tcg_const_tl tcg_const_i32
#define tcg_const_local_tl tcg_const_local_i32
+#define tcg_gen_movcond_tl tcg_gen_movcond_i32
#endif
#if TCG_TARGET_REG_BITS == 32
diff --git a/tcg/tcg-opc.h b/tcg/tcg-opc.h
index d12e8d0..dbb0e39 100644
--- a/tcg/tcg-opc.h
+++ b/tcg/tcg-opc.h
@@ -51,6 +51,7 @@ DEF(br, 0, 0, 1, TCG_OPF_BB_END | TCG_OPF_SIDE_EFFECTS)
DEF(mov_i32, 1, 1, 0, 0)
DEF(movi_i32, 1, 0, 1, 0)
DEF(setcond_i32, 1, 2, 1, 0)
+DEF(movcond_i32, 1, 4, 1, IMPL(TCG_TARGET_HAS_movcond_i32))
/* load/store */
DEF(ld8u_i32, 1, 1, 1, 0)
DEF(ld8s_i32, 1, 1, 1, 0)
@@ -107,6 +108,7 @@ DEF(nor_i32, 1, 2, 0, IMPL(TCG_TARGET_HAS_nor_i32))
DEF(mov_i64, 1, 1, 0, IMPL64)
DEF(movi_i64, 1, 0, 1, IMPL64)
DEF(setcond_i64, 1, 2, 1, IMPL64)
+DEF(movcond_i64, 1, 4, 1, IMPL64 | IMPL(TCG_TARGET_HAS_movcond_i64))
/* load/store */
DEF(ld8u_i64, 1, 1, 1, IMPL64)
DEF(ld8s_i64, 1, 1, 1, IMPL64)
diff --git a/tcg/tcg.c b/tcg/tcg.c
index c002a88..24ce830 100644
--- a/tcg/tcg.c
+++ b/tcg/tcg.c
@@ -991,16 +991,15 @@ void tcg_dump_ops(TCGContext *s)
}
switch (c) {
case INDEX_op_brcond_i32:
-#if TCG_TARGET_REG_BITS == 32
- case INDEX_op_brcond2_i32:
-#elif TCG_TARGET_REG_BITS == 64
- case INDEX_op_brcond_i64:
-#endif
case INDEX_op_setcond_i32:
+ case INDEX_op_movcond_i32:
#if TCG_TARGET_REG_BITS == 32
+ case INDEX_op_brcond2_i32:
case INDEX_op_setcond2_i32:
-#elif TCG_TARGET_REG_BITS == 64
+#else
+ case INDEX_op_brcond_i64:
case INDEX_op_setcond_i64:
+ case INDEX_op_movcond_i64:
#endif
if (args[k] < ARRAY_SIZE(cond_name) && cond_name[args[k]]) {
qemu_log(",%s", cond_name[args[k++]]);
diff --git a/tcg/tcg.h b/tcg/tcg.h
index 8fbbc81..f454107 100644
--- a/tcg/tcg.h
+++ b/tcg/tcg.h
@@ -79,6 +79,7 @@ typedef uint64_t TCGRegSet;
#define TCG_TARGET_HAS_nand_i64 0
#define TCG_TARGET_HAS_nor_i64 0
#define TCG_TARGET_HAS_deposit_i64 0
+#define TCG_TARGET_HAS_movcond_i64 0
#endif
#ifndef TCG_TARGET_deposit_i32_valid
diff --git a/tcg/tci/tcg-target.h b/tcg/tci/tcg-target.h
index 30a0f21..6d89495 100644
--- a/tcg/tci/tcg-target.h
+++ b/tcg/tci/tcg-target.h
@@ -75,6 +75,7 @@
#define TCG_TARGET_HAS_not_i32 1
#define TCG_TARGET_HAS_orc_i32 0
#define TCG_TARGET_HAS_rot_i32 1
+#define TCG_TARGET_HAS_movcond_i32 0
#if TCG_TARGET_REG_BITS == 64
#define TCG_TARGET_HAS_bswap16_i64 1
@@ -98,6 +99,7 @@
#define TCG_TARGET_HAS_not_i64 1
#define TCG_TARGET_HAS_orc_i64 0
#define TCG_TARGET_HAS_rot_i64 1
+#define TCG_TARGET_HAS_movcond_i64 0
#endif /* TCG_TARGET_REG_BITS == 64 */
/* Offset to user memory in user mode. */
--
1.7.12.1

View File

@ -0,0 +1,160 @@
From 4bf321d3f494134fe2e03c9cbc042e28ec3a1045 Mon Sep 17 00:00:00 2001
From: Richard Henderson <rth@twiddle.net>
Date: Fri, 21 Sep 2012 10:13:35 -0700
Subject: [PATCH] target-alpha: Use movcond
For proper cmov insns, as well as the non-goto-tb case
of conditional branch.
Signed-off-by: Richard Henderson <rth@twiddle.net>
Signed-off-by: Aurelien Jarno <aurelien@aurel32.net>
Signed-off-by: Michael Roth <mdroth@linux.vnet.ibm.com>
---
target-alpha/translate.c | 102 ++++++++++++++++++++++-------------------------
1 file changed, 48 insertions(+), 54 deletions(-)
diff --git a/target-alpha/translate.c b/target-alpha/translate.c
index 12de6a3..4a9011a 100644
--- a/target-alpha/translate.c
+++ b/target-alpha/translate.c
@@ -426,27 +426,15 @@ static ExitStatus gen_bcond_internal(DisasContext *ctx, TCGCond cond,
return EXIT_GOTO_TB;
} else {
- int lab_over = gen_new_label();
-
- /* ??? Consider using either
- movi pc, next
- addi tmp, pc, disp
- movcond pc, cond, 0, tmp, pc
- or
- setcond tmp, cond, 0
- movi pc, next
- neg tmp, tmp
- andi tmp, tmp, disp
- add pc, pc, tmp
- The current diamond subgraph surely isn't efficient. */
+ TCGv_i64 z = tcg_const_i64(0);
+ TCGv_i64 d = tcg_const_i64(dest);
+ TCGv_i64 p = tcg_const_i64(ctx->pc);
- tcg_gen_brcondi_i64(cond, cmp, 0, lab_true);
- tcg_gen_movi_i64(cpu_pc, ctx->pc);
- tcg_gen_br(lab_over);
- gen_set_label(lab_true);
- tcg_gen_movi_i64(cpu_pc, dest);
- gen_set_label(lab_over);
+ tcg_gen_movcond_i64(cond, cpu_pc, cmp, z, d, p);
+ tcg_temp_free_i64(z);
+ tcg_temp_free_i64(d);
+ tcg_temp_free_i64(p);
return EXIT_PC_UPDATED;
}
}
@@ -521,61 +509,67 @@ static ExitStatus gen_fbcond(DisasContext *ctx, TCGCond cond, int ra,
static void gen_cmov(TCGCond cond, int ra, int rb, int rc,
int islit, uint8_t lit, int mask)
{
- TCGCond inv_cond = tcg_invert_cond(cond);
- int l1;
+ TCGv_i64 c1, z, v1;
- if (unlikely(rc == 31))
+ if (unlikely(rc == 31)) {
return;
+ }
- l1 = gen_new_label();
-
- if (ra != 31) {
- if (mask) {
- TCGv tmp = tcg_temp_new();
- tcg_gen_andi_i64(tmp, cpu_ir[ra], 1);
- tcg_gen_brcondi_i64(inv_cond, tmp, 0, l1);
- tcg_temp_free(tmp);
- } else
- tcg_gen_brcondi_i64(inv_cond, cpu_ir[ra], 0, l1);
- } else {
+ if (ra == 31) {
/* Very uncommon case - Do not bother to optimize. */
- TCGv tmp = tcg_const_i64(0);
- tcg_gen_brcondi_i64(inv_cond, tmp, 0, l1);
- tcg_temp_free(tmp);
+ c1 = tcg_const_i64(0);
+ } else if (mask) {
+ c1 = tcg_const_i64(1);
+ tcg_gen_and_i64(c1, c1, cpu_ir[ra]);
+ } else {
+ c1 = cpu_ir[ra];
}
+ if (islit) {
+ v1 = tcg_const_i64(lit);
+ } else {
+ v1 = cpu_ir[rb];
+ }
+ z = tcg_const_i64(0);
- if (islit)
- tcg_gen_movi_i64(cpu_ir[rc], lit);
- else
- tcg_gen_mov_i64(cpu_ir[rc], cpu_ir[rb]);
- gen_set_label(l1);
+ tcg_gen_movcond_i64(cond, cpu_ir[rc], c1, z, v1, cpu_ir[rc]);
+
+ tcg_temp_free_i64(z);
+ if (ra == 31 || mask) {
+ tcg_temp_free_i64(c1);
+ }
+ if (islit) {
+ tcg_temp_free_i64(v1);
+ }
}
static void gen_fcmov(TCGCond cond, int ra, int rb, int rc)
{
- TCGv cmp_tmp;
- int l1;
+ TCGv_i64 c1, z, v1;
if (unlikely(rc == 31)) {
return;
}
- cmp_tmp = tcg_temp_new();
+ c1 = tcg_temp_new_i64();
if (unlikely(ra == 31)) {
- tcg_gen_movi_i64(cmp_tmp, 0);
+ tcg_gen_movi_i64(c1, 0);
+ } else {
+ gen_fold_mzero(cond, c1, cpu_fir[ra]);
+ }
+ if (rb == 31) {
+ v1 = tcg_const_i64(0);
} else {
- gen_fold_mzero(cond, cmp_tmp, cpu_fir[ra]);
+ v1 = cpu_fir[rb];
}
+ z = tcg_const_i64(0);
- l1 = gen_new_label();
- tcg_gen_brcondi_i64(tcg_invert_cond(cond), cmp_tmp, 0, l1);
- tcg_temp_free(cmp_tmp);
+ tcg_gen_movcond_i64(cond, cpu_fir[rc], c1, z, v1, cpu_fir[rc]);
- if (rb != 31)
- tcg_gen_mov_i64(cpu_fir[rc], cpu_fir[rb]);
- else
- tcg_gen_movi_i64(cpu_fir[rc], 0);
- gen_set_label(l1);
+ tcg_temp_free_i64(z);
+ tcg_temp_free_i64(c1);
+ if (rb == 31) {
+ tcg_temp_free_i64(v1);
+ }
}
#define QUAL_RM_N 0x080 /* Round mode nearest even */
--
1.7.12.1

View File

@ -0,0 +1,118 @@
From 7a6273e2995b6c439441316467ab19bd6a48f03f Mon Sep 17 00:00:00 2001
From: Richard Henderson <rth@twiddle.net>
Date: Fri, 21 Sep 2012 10:13:36 -0700
Subject: [PATCH] tcg-i386: Implement movcond
Signed-off-by: Richard Henderson <rth@twiddle.net>
Reviewed-by: Aurelien Jarno <aurelien@aurel32.net>
Signed-off-by: Aurelien Jarno <aurelien@aurel32.net>
Signed-off-by: Michael Roth <mdroth@linux.vnet.ibm.com>
---
tcg/i386/tcg-target.c | 29 +++++++++++++++++++++++++++++
tcg/i386/tcg-target.h | 7 ++++++-
2 files changed, 35 insertions(+), 1 deletion(-)
diff --git a/tcg/i386/tcg-target.c b/tcg/i386/tcg-target.c
index 3017858..aa1fa9f 100644
--- a/tcg/i386/tcg-target.c
+++ b/tcg/i386/tcg-target.c
@@ -249,6 +249,7 @@ static inline int tcg_target_const_match(tcg_target_long val,
#define OPC_ADD_GvEv (OPC_ARITH_GvEv | (ARITH_ADD << 3))
#define OPC_BSWAP (0xc8 | P_EXT)
#define OPC_CALL_Jz (0xe8)
+#define OPC_CMOVCC (0x40 | P_EXT) /* ... plus condition code */
#define OPC_CMP_GvEv (OPC_ARITH_GvEv | (ARITH_CMP << 3))
#define OPC_DEC_r32 (0x48)
#define OPC_IMUL_GvEv (0xaf | P_EXT)
@@ -936,6 +937,24 @@ static void tcg_out_setcond2(TCGContext *s, const TCGArg *args,
}
#endif
+static void tcg_out_movcond32(TCGContext *s, TCGCond cond, TCGArg dest,
+ TCGArg c1, TCGArg c2, int const_c2,
+ TCGArg v1)
+{
+ tcg_out_cmp(s, c1, c2, const_c2, 0);
+ tcg_out_modrm(s, OPC_CMOVCC | tcg_cond_to_jcc[cond], dest, v1);
+}
+
+#if TCG_TARGET_REG_BITS == 64
+static void tcg_out_movcond64(TCGContext *s, TCGCond cond, TCGArg dest,
+ TCGArg c1, TCGArg c2, int const_c2,
+ TCGArg v1)
+{
+ tcg_out_cmp(s, c1, c2, const_c2, P_REXW);
+ tcg_out_modrm(s, OPC_CMOVCC | tcg_cond_to_jcc[cond] | P_REXW, dest, v1);
+}
+#endif
+
static void tcg_out_branch(TCGContext *s, int call, tcg_target_long dest)
{
tcg_target_long disp = dest - (tcg_target_long)s->code_ptr - 5;
@@ -1668,6 +1687,10 @@ static inline void tcg_out_op(TCGContext *s, TCGOpcode opc,
tcg_out_setcond32(s, args[3], args[0], args[1],
args[2], const_args[2]);
break;
+ case INDEX_op_movcond_i32:
+ tcg_out_movcond32(s, args[5], args[0], args[1],
+ args[2], const_args[2], args[3]);
+ break;
OP_32_64(bswap16):
tcg_out_rolw_8(s, args[0]);
@@ -1796,6 +1819,10 @@ static inline void tcg_out_op(TCGContext *s, TCGOpcode opc,
tcg_out_setcond64(s, args[3], args[0], args[1],
args[2], const_args[2]);
break;
+ case INDEX_op_movcond_i64:
+ tcg_out_movcond64(s, args[5], args[0], args[1],
+ args[2], const_args[2], args[3]);
+ break;
case INDEX_op_bswap64_i64:
tcg_out_bswap64(s, args[0]);
@@ -1880,6 +1907,7 @@ static const TCGTargetOpDef x86_op_defs[] = {
{ INDEX_op_setcond_i32, { "q", "r", "ri" } },
{ INDEX_op_deposit_i32, { "Q", "0", "Q" } },
+ { INDEX_op_movcond_i32, { "r", "r", "ri", "r", "0" } },
#if TCG_TARGET_REG_BITS == 32
{ INDEX_op_mulu2_i32, { "a", "d", "a", "r" } },
@@ -1934,6 +1962,7 @@ static const TCGTargetOpDef x86_op_defs[] = {
{ INDEX_op_ext32u_i64, { "r", "r" } },
{ INDEX_op_deposit_i64, { "Q", "0", "Q" } },
+ { INDEX_op_movcond_i64, { "r", "r", "re", "r", "0" } },
#endif
#if TCG_TARGET_REG_BITS == 64
diff --git a/tcg/i386/tcg-target.h b/tcg/i386/tcg-target.h
index 504f953..b356d76 100644
--- a/tcg/i386/tcg-target.h
+++ b/tcg/i386/tcg-target.h
@@ -86,7 +86,12 @@ typedef enum {
#define TCG_TARGET_HAS_nand_i32 0
#define TCG_TARGET_HAS_nor_i32 0
#define TCG_TARGET_HAS_deposit_i32 1
+#if defined(__x86_64__) || defined(__i686__)
+/* Use cmov only if the compiler is already doing so. */
+#define TCG_TARGET_HAS_movcond_i32 1
+#else
#define TCG_TARGET_HAS_movcond_i32 0
+#endif
#if TCG_TARGET_REG_BITS == 64
#define TCG_TARGET_HAS_div2_i64 1
@@ -108,7 +113,7 @@ typedef enum {
#define TCG_TARGET_HAS_nand_i64 0
#define TCG_TARGET_HAS_nor_i64 0
#define TCG_TARGET_HAS_deposit_i64 1
-#define TCG_TARGET_HAS_movcond_i64 0
+#define TCG_TARGET_HAS_movcond_i64 1
#endif
#define TCG_TARGET_deposit_i32_valid(ofs, len) \
--
1.7.12.1

View File

@ -0,0 +1,73 @@
From c489b380d3f827be91b5f8b80b88585fb4014fbb Mon Sep 17 00:00:00 2001
From: Richard Henderson <rth@twiddle.net>
Date: Fri, 21 Sep 2012 10:13:37 -0700
Subject: [PATCH] tcg: Optimize movcond for constant comparisons
Signed-off-by: Richard Henderson <rth@twiddle.net>
Signed-off-by: Aurelien Jarno <aurelien@aurel32.net>
Signed-off-by: Michael Roth <mdroth@linux.vnet.ibm.com>
---
tcg/optimize.c | 40 ++++++++++++++++++++++++++++++++++++++++
1 file changed, 40 insertions(+)
diff --git a/tcg/optimize.c b/tcg/optimize.c
index 9da333c..26038a6 100644
--- a/tcg/optimize.c
+++ b/tcg/optimize.c
@@ -394,6 +394,14 @@ static TCGArg *tcg_constant_folding(TCGContext *s, uint16_t *tcg_opc_ptr,
args[3] = tcg_swap_cond(args[3]);
}
break;
+ CASE_OP_32_64(movcond):
+ if (temps[args[1]].state == TCG_TEMP_CONST
+ && temps[args[2]].state != TCG_TEMP_CONST) {
+ tmp = args[1];
+ args[1] = args[2];
+ args[2] = tmp;
+ args[5] = tcg_swap_cond(args[5]);
+ }
default:
break;
}
@@ -614,6 +622,38 @@ static TCGArg *tcg_constant_folding(TCGContext *s, uint16_t *tcg_opc_ptr,
}
args += 4;
break;
+ CASE_OP_32_64(movcond):
+ if (temps[args[1]].state == TCG_TEMP_CONST
+ && temps[args[2]].state == TCG_TEMP_CONST) {
+ tmp = do_constant_folding_cond(op, temps[args[1]].val,
+ temps[args[2]].val, args[5]);
+ if (args[0] == args[4-tmp]
+ || (temps[args[4-tmp]].state == TCG_TEMP_COPY
+ && temps[args[4-tmp]].val == args[0])) {
+ gen_opc_buf[op_index] = INDEX_op_nop;
+ } else if (temps[args[4-tmp]].state == TCG_TEMP_CONST) {
+ gen_opc_buf[op_index] = op_to_movi(op);
+ tcg_opt_gen_movi(gen_args, args[0], temps[args[4-tmp]].val,
+ nb_temps, nb_globals);
+ gen_args += 2;
+ } else {
+ gen_opc_buf[op_index] = op_to_mov(op);
+ tcg_opt_gen_mov(gen_args, args[0], args[4-tmp],
+ nb_temps, nb_globals);
+ gen_args += 2;
+ }
+ } else {
+ reset_temp(args[0], nb_temps, nb_globals);
+ gen_args[0] = args[0];
+ gen_args[1] = args[1];
+ gen_args[2] = args[2];
+ gen_args[3] = args[3];
+ gen_args[4] = args[4];
+ gen_args[5] = args[5];
+ gen_args += 6;
+ }
+ args += 6;
+ break;
case INDEX_op_call:
nb_call_args = (args[0] >> 16) + (args[0] & 0xffff);
if (!(args[nb_call_args + 1] & (TCG_CALL_CONST | TCG_CALL_PURE))) {
--
1.7.12.1

View File

@ -0,0 +1,57 @@
From af2bf6bcc6614622c87d28e9d763b57408c17500 Mon Sep 17 00:00:00 2001
From: Richard Henderson <rth@twiddle.net>
Date: Fri, 21 Sep 2012 10:13:38 -0700
Subject: [PATCH] tcg: Optimize two-address commutative operations
While swapping constants to the second operand, swap
sources matching destinations to the first operand.
Signed-off-by: Richard Henderson <rth@twiddle.net>
Signed-off-by: Aurelien Jarno <aurelien@aurel32.net>
Signed-off-by: Michael Roth <mdroth@linux.vnet.ibm.com>
---
tcg/optimize.c | 15 ++++++++++++++-
1 file changed, 14 insertions(+), 1 deletion(-)
diff --git a/tcg/optimize.c b/tcg/optimize.c
index 26038a6..1be7631 100644
--- a/tcg/optimize.c
+++ b/tcg/optimize.c
@@ -334,6 +334,8 @@ static TCGArg *tcg_constant_folding(TCGContext *s, uint16_t *tcg_opc_ptr,
const TCGOpDef *def;
TCGArg *gen_args;
TCGArg tmp;
+ TCGCond cond;
+
/* Array VALS has an element for each temp.
If this temp holds a constant then its value is kept in VALS' element.
If this temp is a copy of other ones then this equivalence class'
@@ -395,13 +397,24 @@ static TCGArg *tcg_constant_folding(TCGContext *s, uint16_t *tcg_opc_ptr,
}
break;
CASE_OP_32_64(movcond):
+ cond = args[5];
if (temps[args[1]].state == TCG_TEMP_CONST
&& temps[args[2]].state != TCG_TEMP_CONST) {
tmp = args[1];
args[1] = args[2];
args[2] = tmp;
- args[5] = tcg_swap_cond(args[5]);
+ cond = tcg_swap_cond(cond);
+ }
+ /* For movcond, we canonicalize the "false" input reg to match
+ the destination reg so that the tcg backend can implement
+ a "move if true" operation. */
+ if (args[0] == args[3]) {
+ tmp = args[3];
+ args[3] = args[4];
+ args[4] = tmp;
+ cond = tcg_invert_cond(cond);
}
+ args[5] = cond;
default:
break;
}
--
1.7.12.1

View File

@ -0,0 +1,192 @@
From b6407e30c30268cdeddec6e2b115f419647cc07f Mon Sep 17 00:00:00 2001
From: Aurelien Jarno <aurelien@aurel32.net>
Date: Sun, 16 Sep 2012 13:12:21 +0200
Subject: [PATCH] gdbstub/sh4: fix build with USE_SOFTFLOAT_STRUCT_TYPES
We have to use different type to access float values when
USE_SOFTFLOAT_STRUCT_TYPES is defined.
Rework SH4 version of cpu_gdb_{read,write}_register() using
a single case, and fixing the coding style. Use ldll_p() and
stfl_p() to access float values.
Signed-off-by: Aurelien Jarno <aurelien@aurel32.net>
Signed-off-by: Michael Roth <mdroth@linux.vnet.ibm.com>
---
gdbstub.c | 144 +++++++++++++++++++++++++++++++++++++++-----------------------
1 file changed, 90 insertions(+), 54 deletions(-)
diff --git a/gdbstub.c b/gdbstub.c
index 5d37dd9..a91709f 100644
--- a/gdbstub.c
+++ b/gdbstub.c
@@ -1226,33 +1226,48 @@ static int cpu_gdb_write_register(CPUOpenRISCState *env,
static int cpu_gdb_read_register(CPUSH4State *env, uint8_t *mem_buf, int n)
{
- if (n < 8) {
+ switch (n) {
+ case 0 ... 7:
if ((env->sr & (SR_MD | SR_RB)) == (SR_MD | SR_RB)) {
GET_REGL(env->gregs[n + 16]);
} else {
GET_REGL(env->gregs[n]);
}
- } else if (n < 16) {
+ case 8 ... 15:
GET_REGL(env->gregs[n]);
- } else if (n >= 25 && n < 41) {
- GET_REGL(env->fregs[(n - 25) + ((env->fpscr & FPSCR_FR) ? 16 : 0)]);
- } else if (n >= 43 && n < 51) {
- GET_REGL(env->gregs[n - 43]);
- } else if (n >= 51 && n < 59) {
- GET_REGL(env->gregs[n - (51 - 16)]);
- }
- switch (n) {
- case 16: GET_REGL(env->pc);
- case 17: GET_REGL(env->pr);
- case 18: GET_REGL(env->gbr);
- case 19: GET_REGL(env->vbr);
- case 20: GET_REGL(env->mach);
- case 21: GET_REGL(env->macl);
- case 22: GET_REGL(env->sr);
- case 23: GET_REGL(env->fpul);
- case 24: GET_REGL(env->fpscr);
- case 41: GET_REGL(env->ssr);
- case 42: GET_REGL(env->spc);
+ case 16:
+ GET_REGL(env->pc);
+ case 17:
+ GET_REGL(env->pr);
+ case 18:
+ GET_REGL(env->gbr);
+ case 19:
+ GET_REGL(env->vbr);
+ case 20:
+ GET_REGL(env->mach);
+ case 21:
+ GET_REGL(env->macl);
+ case 22:
+ GET_REGL(env->sr);
+ case 23:
+ GET_REGL(env->fpul);
+ case 24:
+ GET_REGL(env->fpscr);
+ case 25 ... 40:
+ if (env->fpscr & FPSCR_FR) {
+ stfl_p(mem_buf, env->fregs[n - 9]);
+ } else {
+ stfl_p(mem_buf, env->fregs[n - 25]);
+ }
+ return 4;
+ case 41:
+ GET_REGL(env->ssr);
+ case 42:
+ GET_REGL(env->spc);
+ case 43 ... 50:
+ GET_REGL(env->gregs[n - 43]);
+ case 51 ... 58:
+ GET_REGL(env->gregs[n - (51 - 16)]);
}
return 0;
@@ -1260,42 +1275,63 @@ static int cpu_gdb_read_register(CPUSH4State *env, uint8_t *mem_buf, int n)
static int cpu_gdb_write_register(CPUSH4State *env, uint8_t *mem_buf, int n)
{
- uint32_t tmp;
-
- tmp = ldl_p(mem_buf);
-
- if (n < 8) {
+ switch (n) {
+ case 0 ... 7:
if ((env->sr & (SR_MD | SR_RB)) == (SR_MD | SR_RB)) {
- env->gregs[n + 16] = tmp;
+ env->gregs[n + 16] = ldl_p(mem_buf);
} else {
- env->gregs[n] = tmp;
+ env->gregs[n] = ldl_p(mem_buf);
}
- return 4;
- } else if (n < 16) {
- env->gregs[n] = tmp;
- return 4;
- } else if (n >= 25 && n < 41) {
- env->fregs[(n - 25) + ((env->fpscr & FPSCR_FR) ? 16 : 0)] = tmp;
- return 4;
- } else if (n >= 43 && n < 51) {
- env->gregs[n - 43] = tmp;
- return 4;
- } else if (n >= 51 && n < 59) {
- env->gregs[n - (51 - 16)] = tmp;
- return 4;
- }
- switch (n) {
- case 16: env->pc = tmp; break;
- case 17: env->pr = tmp; break;
- case 18: env->gbr = tmp; break;
- case 19: env->vbr = tmp; break;
- case 20: env->mach = tmp; break;
- case 21: env->macl = tmp; break;
- case 22: env->sr = tmp; break;
- case 23: env->fpul = tmp; break;
- case 24: env->fpscr = tmp; break;
- case 41: env->ssr = tmp; break;
- case 42: env->spc = tmp; break;
+ break;
+ case 8 ... 15:
+ env->gregs[n] = ldl_p(mem_buf);
+ break;
+ case 16:
+ env->pc = ldl_p(mem_buf);
+ break;
+ case 17:
+ env->pr = ldl_p(mem_buf);
+ break;
+ case 18:
+ env->gbr = ldl_p(mem_buf);
+ break;
+ case 19:
+ env->vbr = ldl_p(mem_buf);
+ break;
+ case 20:
+ env->mach = ldl_p(mem_buf);
+ break;
+ case 21:
+ env->macl = ldl_p(mem_buf);
+ break;
+ case 22:
+ env->sr = ldl_p(mem_buf);
+ break;
+ case 23:
+ env->fpul = ldl_p(mem_buf);
+ break;
+ case 24:
+ env->fpscr = ldl_p(mem_buf);
+ break;
+ case 25 ... 40:
+ if (env->fpscr & FPSCR_FR) {
+ env->fregs[n - 9] = ldfl_p(mem_buf);
+ } else {
+ env->fregs[n - 25] = ldfl_p(mem_buf);
+ }
+ break;
+ case 41:
+ env->ssr = ldl_p(mem_buf);
+ break;
+ case 42:
+ env->spc = ldl_p(mem_buf);
+ break;
+ case 43 ... 50:
+ env->gregs[n - 43] = ldl_p(mem_buf);
+ break;
+ case 51 ... 58:
+ env->gregs[n - (51 - 16)] = ldl_p(mem_buf);
+ break;
default: return 0;
}
--
1.7.12.1

View File

@ -0,0 +1,35 @@
From 03ddebf0c48dc78070c846b7cfdc2665fe7df854 Mon Sep 17 00:00:00 2001
From: Richard Henderson <rth@twiddle.net>
Date: Mon, 17 Sep 2012 08:28:52 -0700
Subject: [PATCH] tcg: Fix !USE_DIRECT_JUMP
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
Commit 6375e09e changed the type of TranslationBlock.tb_next,
but failed to change the type of TCGContext.tb_next.
Signed-off-by: Richard Henderson <rth@twiddle.net>
Reviewed-by: Andreas Färber <afaerber@suse.de>
Signed-off-by: Aurelien Jarno <aurelien@aurel32.net>
Signed-off-by: Michael Roth <mdroth@linux.vnet.ibm.com>
---
tcg/tcg.h | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/tcg/tcg.h b/tcg/tcg.h
index f454107..609ed86 100644
--- a/tcg/tcg.h
+++ b/tcg/tcg.h
@@ -344,7 +344,7 @@ struct TCGContext {
/* goto_tb support */
uint8_t *code_buf;
- unsigned long *tb_next;
+ uintptr_t *tb_next;
uint16_t *tb_next_offset;
uint16_t *tb_jmp_offset; /* != NULL if USE_DIRECT_JUMP */
--
1.7.12.1

View File

@ -0,0 +1,108 @@
From 3616400bc0065f7114172ad7801d9d88332ef981 Mon Sep 17 00:00:00 2001
From: Richard Henderson <rth@twiddle.net>
Date: Tue, 18 Sep 2012 19:59:47 -0700
Subject: [PATCH] tcg-hppa: Fix brcond2 and setcond2
Neither of these functions were performing double-word
compares properly.
Signed-off-by: Richard Henderson <rth@twiddle.net>
Signed-off-by: Aurelien Jarno <aurelien@aurel32.net>
Signed-off-by: Michael Roth <mdroth@linux.vnet.ibm.com>
---
tcg/hppa/tcg-target.c | 51 ++++++++++++++++++++++++++++++++++++++++++---------
1 file changed, 42 insertions(+), 9 deletions(-)
diff --git a/tcg/hppa/tcg-target.c b/tcg/hppa/tcg-target.c
index 8b81b70..a76569d 100644
--- a/tcg/hppa/tcg-target.c
+++ b/tcg/hppa/tcg-target.c
@@ -820,19 +820,34 @@ static void tcg_out_comclr(TCGContext *s, int cond, TCGArg ret,
tcg_out32(s, op);
}
+static TCGCond const tcg_high_cond[] = {
+ [TCG_COND_EQ] = TCG_COND_EQ,
+ [TCG_COND_NE] = TCG_COND_NE,
+ [TCG_COND_LT] = TCG_COND_LT,
+ [TCG_COND_LE] = TCG_COND_LT,
+ [TCG_COND_GT] = TCG_COND_GT,
+ [TCG_COND_GE] = TCG_COND_GT,
+ [TCG_COND_LTU] = TCG_COND_LTU,
+ [TCG_COND_LEU] = TCG_COND_LTU,
+ [TCG_COND_GTU] = TCG_COND_GTU,
+ [TCG_COND_GEU] = TCG_COND_GTU
+};
+
static void tcg_out_brcond2(TCGContext *s, int cond, TCGArg al, TCGArg ah,
TCGArg bl, int blconst, TCGArg bh, int bhconst,
int label_index)
{
switch (cond) {
case TCG_COND_EQ:
+ tcg_out_comclr(s, TCG_COND_NE, TCG_REG_R0, al, bl, blconst);
+ tcg_out_brcond(s, TCG_COND_EQ, ah, bh, bhconst, label_index);
+ break;
case TCG_COND_NE:
- tcg_out_comclr(s, tcg_invert_cond(cond), TCG_REG_R0, al, bl, blconst);
- tcg_out_brcond(s, cond, ah, bh, bhconst, label_index);
+ tcg_out_brcond(s, TCG_COND_NE, al, bl, bhconst, label_index);
+ tcg_out_brcond(s, TCG_COND_NE, ah, bh, bhconst, label_index);
break;
-
default:
- tcg_out_brcond(s, cond, ah, bh, bhconst, label_index);
+ tcg_out_brcond(s, tcg_high_cond[cond], ah, bh, bhconst, label_index);
tcg_out_comclr(s, TCG_COND_NE, TCG_REG_R0, ah, bh, bhconst);
tcg_out_brcond(s, tcg_unsigned_cond(cond),
al, bl, blconst, label_index);
@@ -853,9 +868,8 @@ static void tcg_out_setcond2(TCGContext *s, int cond, TCGArg ret,
{
int scratch = TCG_REG_R20;
- if (ret != al && ret != ah
- && (blconst || ret != bl)
- && (bhconst || ret != bh)) {
+ /* Note that the low parts are fully consumed before scratch is set. */
+ if (ret != ah && (bhconst || ret != bh)) {
scratch = ret;
}
@@ -867,13 +881,32 @@ static void tcg_out_setcond2(TCGContext *s, int cond, TCGArg ret,
tcg_out_movi(s, TCG_TYPE_I32, scratch, cond == TCG_COND_NE);
break;
- default:
+ case TCG_COND_GE:
+ case TCG_COND_GEU:
+ case TCG_COND_LT:
+ case TCG_COND_LTU:
+ /* Optimize compares with low part zero. */
+ if (bl == 0) {
+ tcg_out_setcond(s, cond, ret, ah, bh, bhconst);
+ return;
+ }
+ /* FALLTHRU */
+
+ case TCG_COND_LE:
+ case TCG_COND_LEU:
+ case TCG_COND_GT:
+ case TCG_COND_GTU:
+ /* <= : ah < bh | (ah == bh && al <= bl) */
tcg_out_setcond(s, tcg_unsigned_cond(cond), scratch, al, bl, blconst);
tcg_out_comclr(s, TCG_COND_EQ, TCG_REG_R0, ah, bh, bhconst);
tcg_out_movi(s, TCG_TYPE_I32, scratch, 0);
- tcg_out_comclr(s, cond, TCG_REG_R0, ah, bh, bhconst);
+ tcg_out_comclr(s, tcg_invert_cond(tcg_high_cond[cond]),
+ TCG_REG_R0, ah, bh, bhconst);
tcg_out_movi(s, TCG_TYPE_I32, scratch, 1);
break;
+
+ default:
+ tcg_abort();
}
tcg_out_mov(s, TCG_TYPE_I32, ret, scratch);
--
1.7.12.1

View File

@ -0,0 +1,249 @@
From c13ecfea174994d3f7f7d392f0faaed6d40efd9e Mon Sep 17 00:00:00 2001
From: Richard Henderson <rth@twiddle.net>
Date: Tue, 18 Sep 2012 19:59:48 -0700
Subject: [PATCH] tcg-hppa: Fix broken load/store helpers
The CONFIG_TCG_PASS_AREG0 code for calling ld/st helpers
was not respecting the ABI requirement for 64-bit values
being aligned in registers.
Mirror the ARM port in use of helper functions to marshal
arguments into the correct registers.
Signed-off-by: Richard Henderson <rth@twiddle.net>
Signed-off-by: Aurelien Jarno <aurelien@aurel32.net>
Signed-off-by: Michael Roth <mdroth@linux.vnet.ibm.com>
---
tcg/hppa/tcg-target.c | 136 +++++++++++++++++++++++++++-----------------------
1 file changed, 74 insertions(+), 62 deletions(-)
diff --git a/tcg/hppa/tcg-target.c b/tcg/hppa/tcg-target.c
index a76569d..5385d45 100644
--- a/tcg/hppa/tcg-target.c
+++ b/tcg/hppa/tcg-target.c
@@ -976,10 +976,11 @@ static int tcg_out_tlb_read(TCGContext *s, int r0, int r1, int addrlo,
tcg_out_ld(s, TCG_TYPE_PTR, TCG_REG_R20, r1, offset);
}
- /* Compute the value that ought to appear in the TLB for a hit, namely, the page
- of the address. We include the low N bits of the address to catch unaligned
- accesses and force them onto the slow path. Do this computation after having
- issued the load from the TLB slot to give the load time to complete. */
+ /* Compute the value that ought to appear in the TLB for a hit, namely,
+ the page of the address. We include the low N bits of the address
+ to catch unaligned accesses and force them onto the slow path. Do
+ this computation after having issued the load from the TLB slot to
+ give the load time to complete. */
tcg_out_andi(s, r0, addrlo, TARGET_PAGE_MASK | ((1 << s_bits) - 1));
/* If not equal, jump to lab_miss. */
@@ -992,6 +993,36 @@ static int tcg_out_tlb_read(TCGContext *s, int r0, int r1, int addrlo,
return ret;
}
+
+static int tcg_out_arg_reg32(TCGContext *s, int argno, TCGArg v, bool vconst)
+{
+ if (argno < 4) {
+ if (vconst) {
+ tcg_out_movi(s, TCG_TYPE_I32, tcg_target_call_iarg_regs[argno], v);
+ } else {
+ tcg_out_mov(s, TCG_TYPE_I32, tcg_target_call_iarg_regs[argno], v);
+ }
+ } else {
+ if (vconst && v != 0) {
+ tcg_out_movi(s, TCG_TYPE_I32, TCG_REG_R20, v);
+ v = TCG_REG_R20;
+ }
+ tcg_out_st(s, TCG_TYPE_I32, v, TCG_REG_CALL_STACK,
+ TCG_TARGET_CALL_STACK_OFFSET - ((argno - 3) * 4));
+ }
+ return argno + 1;
+}
+
+static int tcg_out_arg_reg64(TCGContext *s, int argno, TCGArg vl, TCGArg vh)
+{
+ /* 64-bit arguments must go in even reg pairs and stack slots. */
+ if (argno & 1) {
+ argno++;
+ }
+ argno = tcg_out_arg_reg32(s, argno, vl, false);
+ argno = tcg_out_arg_reg32(s, argno, vh, false);
+ return argno;
+}
#endif
static void tcg_out_qemu_ld_direct(TCGContext *s, int datalo_reg, int datahi_reg,
@@ -1072,39 +1103,36 @@ static void tcg_out_qemu_ld(TCGContext *s, const TCGArg *args, int opc)
/* Note that addrhi_reg is only used for 64-bit guests. */
int addrhi_reg = (TARGET_LONG_BITS == 64 ? *args++ : TCG_REG_R0);
int mem_index = *args;
- int lab1, lab2, argreg, offset;
+ int lab1, lab2, argno, offset;
lab1 = gen_new_label();
lab2 = gen_new_label();
offset = offsetof(CPUArchState, tlb_table[mem_index][0].addr_read);
- offset = tcg_out_tlb_read(s, TCG_REG_R26, TCG_REG_R25, addrlo_reg, addrhi_reg,
- opc & 3, lab1, offset);
+ offset = tcg_out_tlb_read(s, TCG_REG_R26, TCG_REG_R25, addrlo_reg,
+ addrhi_reg, opc & 3, lab1, offset);
/* TLB Hit. */
- tcg_out_ld(s, TCG_TYPE_PTR, TCG_REG_R20, (offset ? TCG_REG_R1 : TCG_REG_R25),
+ tcg_out_ld(s, TCG_TYPE_PTR, TCG_REG_R20,
+ (offset ? TCG_REG_R1 : TCG_REG_R25),
offsetof(CPUArchState, tlb_table[mem_index][0].addend) - offset);
- tcg_out_qemu_ld_direct(s, datalo_reg, datahi_reg, addrlo_reg, TCG_REG_R20, opc);
+ tcg_out_qemu_ld_direct(s, datalo_reg, datahi_reg, addrlo_reg,
+ TCG_REG_R20, opc);
tcg_out_branch(s, lab2, 1);
/* TLB Miss. */
/* label1: */
tcg_out_label(s, lab1, s->code_ptr);
- argreg = TCG_REG_R26;
- tcg_out_mov(s, TCG_TYPE_I32, argreg--, addrlo_reg);
+ argno = 0;
+ argno = tcg_out_arg_reg32(s, argno, TCG_AREG0, false);
if (TARGET_LONG_BITS == 64) {
- tcg_out_mov(s, TCG_TYPE_I32, argreg--, addrhi_reg);
+ argno = tcg_out_arg_reg64(s, argno, addrlo_reg, addrhi_reg);
+ } else {
+ argno = tcg_out_arg_reg32(s, argno, addrlo_reg, false);
}
- tcg_out_movi(s, TCG_TYPE_I32, argreg, mem_index);
-
- /* XXX/FIXME: suboptimal */
- tcg_out_mov(s, TCG_TYPE_I32, tcg_target_call_iarg_regs[2],
- tcg_target_call_iarg_regs[1]);
- tcg_out_mov(s, TCG_TYPE_TL, tcg_target_call_iarg_regs[1],
- tcg_target_call_iarg_regs[0]);
- tcg_out_mov(s, TCG_TYPE_PTR, tcg_target_call_iarg_regs[0],
- TCG_AREG0);
+ argno = tcg_out_arg_reg32(s, argno, mem_index, true);
+
tcg_out_call(s, qemu_ld_helpers[opc & 3]);
switch (opc) {
@@ -1140,8 +1168,8 @@ static void tcg_out_qemu_ld(TCGContext *s, const TCGArg *args, int opc)
#endif
}
-static void tcg_out_qemu_st_direct(TCGContext *s, int datalo_reg, int datahi_reg,
- int addr_reg, int opc)
+static void tcg_out_qemu_st_direct(TCGContext *s, int datalo_reg,
+ int datahi_reg, int addr_reg, int opc)
{
#ifdef TARGET_WORDS_BIGENDIAN
const int bswap = 0;
@@ -1194,17 +1222,18 @@ static void tcg_out_qemu_st(TCGContext *s, const TCGArg *args, int opc)
/* Note that addrhi_reg is only used for 64-bit guests. */
int addrhi_reg = (TARGET_LONG_BITS == 64 ? *args++ : TCG_REG_R0);
int mem_index = *args;
- int lab1, lab2, argreg, offset;
+ int lab1, lab2, argno, next, offset;
lab1 = gen_new_label();
lab2 = gen_new_label();
offset = offsetof(CPUArchState, tlb_table[mem_index][0].addr_write);
- offset = tcg_out_tlb_read(s, TCG_REG_R26, TCG_REG_R25, addrlo_reg, addrhi_reg,
- opc, lab1, offset);
+ offset = tcg_out_tlb_read(s, TCG_REG_R26, TCG_REG_R25, addrlo_reg,
+ addrhi_reg, opc, lab1, offset);
/* TLB Hit. */
- tcg_out_ld(s, TCG_TYPE_PTR, TCG_REG_R20, (offset ? TCG_REG_R1 : TCG_REG_R25),
+ tcg_out_ld(s, TCG_TYPE_PTR, TCG_REG_R20,
+ (offset ? TCG_REG_R1 : TCG_REG_R25),
offsetof(CPUArchState, tlb_table[mem_index][0].addend) - offset);
/* There are no indexed stores, so we must do this addition explitly.
@@ -1217,63 +1246,46 @@ static void tcg_out_qemu_st(TCGContext *s, const TCGArg *args, int opc)
/* label1: */
tcg_out_label(s, lab1, s->code_ptr);
- argreg = TCG_REG_R26;
- tcg_out_mov(s, TCG_TYPE_I32, argreg--, addrlo_reg);
+ argno = 0;
+ argno = tcg_out_arg_reg32(s, argno, TCG_AREG0, false);
if (TARGET_LONG_BITS == 64) {
- tcg_out_mov(s, TCG_TYPE_I32, argreg--, addrhi_reg);
+ argno = tcg_out_arg_reg64(s, argno, addrlo_reg, addrhi_reg);
+ } else {
+ argno = tcg_out_arg_reg32(s, argno, addrlo_reg, false);
}
+ next = (argno < 4 ? tcg_target_call_iarg_regs[argno] : TCG_REG_R20);
switch(opc) {
case 0:
- tcg_out_andi(s, argreg--, datalo_reg, 0xff);
- tcg_out_movi(s, TCG_TYPE_I32, argreg, mem_index);
+ tcg_out_andi(s, next, datalo_reg, 0xff);
+ argno = tcg_out_arg_reg32(s, argno, next, false);
break;
case 1:
- tcg_out_andi(s, argreg--, datalo_reg, 0xffff);
- tcg_out_movi(s, TCG_TYPE_I32, argreg, mem_index);
+ tcg_out_andi(s, next, datalo_reg, 0xffff);
+ argno = tcg_out_arg_reg32(s, argno, next, false);
break;
case 2:
- tcg_out_mov(s, TCG_TYPE_I32, argreg--, datalo_reg);
- tcg_out_movi(s, TCG_TYPE_I32, argreg, mem_index);
+ argno = tcg_out_arg_reg32(s, argno, datalo_reg, false);
break;
case 3:
- /* Because of the alignment required by the 64-bit data argument,
- we will always use R23/R24. Also, we will always run out of
- argument registers for storing mem_index, so that will have
- to go on the stack. */
- if (mem_index == 0) {
- argreg = TCG_REG_R0;
- } else {
- argreg = TCG_REG_R20;
- tcg_out_movi(s, TCG_TYPE_I32, argreg, mem_index);
- }
- tcg_out_mov(s, TCG_TYPE_I32, TCG_REG_R23, datahi_reg);
- tcg_out_mov(s, TCG_TYPE_I32, TCG_REG_R24, datalo_reg);
- tcg_out_st(s, TCG_TYPE_I32, argreg, TCG_REG_CALL_STACK,
- TCG_TARGET_CALL_STACK_OFFSET - 4);
+ argno = tcg_out_arg_reg64(s, argno, datalo_reg, datahi_reg);
break;
default:
tcg_abort();
}
+ argno = tcg_out_arg_reg32(s, argno, mem_index, true);
- /* XXX/FIXME: suboptimal */
- tcg_out_mov(s, TCG_TYPE_I32, tcg_target_call_iarg_regs[3],
- tcg_target_call_iarg_regs[2]);
- tcg_out_mov(s, TCG_TYPE_I64, tcg_target_call_iarg_regs[2],
- tcg_target_call_iarg_regs[1]);
- tcg_out_mov(s, TCG_TYPE_TL, tcg_target_call_iarg_regs[1],
- tcg_target_call_iarg_regs[0]);
- tcg_out_mov(s, TCG_TYPE_PTR, tcg_target_call_iarg_regs[0],
- TCG_AREG0);
tcg_out_call(s, qemu_st_helpers[opc]);
/* label2: */
tcg_out_label(s, lab2, s->code_ptr);
#else
- /* There are no indexed stores, so if GUEST_BASE is set we must do the add
- explicitly. Careful to avoid R20, which is used for the bswaps to follow. */
+ /* There are no indexed stores, so if GUEST_BASE is set we must do
+ the add explicitly. Careful to avoid R20, which is used for the
+ bswaps to follow. */
if (GUEST_BASE != 0) {
- tcg_out_arith(s, TCG_REG_R31, addrlo_reg, TCG_GUEST_BASE_REG, INSN_ADDL);
+ tcg_out_arith(s, TCG_REG_R31, addrlo_reg,
+ TCG_GUEST_BASE_REG, INSN_ADDL);
addrlo_reg = TCG_REG_R31;
}
tcg_out_qemu_st_direct(s, datalo_reg, datahi_reg, addrlo_reg, opc);
--
1.7.12.1

View File

@ -0,0 +1,65 @@
From 061d22ad76512e8ec10af89eda1dcc7c185360d2 Mon Sep 17 00:00:00 2001
From: Aurelien Jarno <aurelien@aurel32.net>
Date: Fri, 21 Sep 2012 18:20:25 +0200
Subject: [PATCH] tcg-mips: fix wrong usage of 'Z' constraint
The 'Z' constraint has been introduced to map the zero register. However
when the op also accept a constant, there is no point to accept the zero
register in addition.
Reviewed-by: Richard Henderson <rth@twiddle.net>
Signed-off-by: Aurelien Jarno <aurelien@aurel32.net>
Signed-off-by: Michael Roth <mdroth@linux.vnet.ibm.com>
---
tcg/mips/tcg-target.c | 16 ++++++++--------
1 file changed, 8 insertions(+), 8 deletions(-)
diff --git a/tcg/mips/tcg-target.c b/tcg/mips/tcg-target.c
index 74db83d..9293745 100644
--- a/tcg/mips/tcg-target.c
+++ b/tcg/mips/tcg-target.c
@@ -1453,24 +1453,24 @@ static const TCGTargetOpDef mips_op_defs[] = {
{ INDEX_op_st16_i32, { "rZ", "r" } },
{ INDEX_op_st_i32, { "rZ", "r" } },
- { INDEX_op_add_i32, { "r", "rZ", "rJZ" } },
+ { INDEX_op_add_i32, { "r", "rZ", "rJ" } },
{ INDEX_op_mul_i32, { "r", "rZ", "rZ" } },
{ INDEX_op_mulu2_i32, { "r", "r", "rZ", "rZ" } },
{ INDEX_op_div_i32, { "r", "rZ", "rZ" } },
{ INDEX_op_divu_i32, { "r", "rZ", "rZ" } },
{ INDEX_op_rem_i32, { "r", "rZ", "rZ" } },
{ INDEX_op_remu_i32, { "r", "rZ", "rZ" } },
- { INDEX_op_sub_i32, { "r", "rZ", "rJZ" } },
+ { INDEX_op_sub_i32, { "r", "rZ", "rJ" } },
- { INDEX_op_and_i32, { "r", "rZ", "rIZ" } },
+ { INDEX_op_and_i32, { "r", "rZ", "rI" } },
{ INDEX_op_nor_i32, { "r", "rZ", "rZ" } },
{ INDEX_op_not_i32, { "r", "rZ" } },
{ INDEX_op_or_i32, { "r", "rZ", "rIZ" } },
{ INDEX_op_xor_i32, { "r", "rZ", "rIZ" } },
- { INDEX_op_shl_i32, { "r", "rZ", "riZ" } },
- { INDEX_op_shr_i32, { "r", "rZ", "riZ" } },
- { INDEX_op_sar_i32, { "r", "rZ", "riZ" } },
+ { INDEX_op_shl_i32, { "r", "rZ", "ri" } },
+ { INDEX_op_shr_i32, { "r", "rZ", "ri" } },
+ { INDEX_op_sar_i32, { "r", "rZ", "ri" } },
{ INDEX_op_ext8s_i32, { "r", "rZ" } },
{ INDEX_op_ext16s_i32, { "r", "rZ" } },
@@ -1479,8 +1479,8 @@ static const TCGTargetOpDef mips_op_defs[] = {
{ INDEX_op_setcond_i32, { "r", "rZ", "rZ" } },
{ INDEX_op_setcond2_i32, { "r", "rZ", "rZ", "rZ", "rZ" } },
- { INDEX_op_add2_i32, { "r", "r", "rZ", "rZ", "rJZ", "rJZ" } },
- { INDEX_op_sub2_i32, { "r", "r", "rZ", "rZ", "rJZ", "rJZ" } },
+ { INDEX_op_add2_i32, { "r", "r", "rZ", "rZ", "rJ", "rJ" } },
+ { INDEX_op_sub2_i32, { "r", "r", "rZ", "rZ", "rJ", "rJ" } },
{ INDEX_op_brcond2_i32, { "rZ", "rZ", "rZ", "rZ" } },
#if TARGET_LONG_BITS == 32
--
1.7.12.1

View File

@ -0,0 +1,166 @@
From e63a3c6c70c9933320c6d8b23c3ea4cf4724d316 Mon Sep 17 00:00:00 2001
From: Aurelien Jarno <aurelien@aurel32.net>
Date: Fri, 21 Sep 2012 18:20:25 +0200
Subject: [PATCH] tcg/mips: kill warnings in user mode
Recent versions of GCC emit warnings when compiling user mode targets.
Kill them by reordering a bit the #ifdef.
Reviewed-by: Richard Henderson <rth@twiddle.net>
Signed-off-by: Aurelien Jarno <aurelien@aurel32.net>
Signed-off-by: Michael Roth <mdroth@linux.vnet.ibm.com>
---
tcg/mips/tcg-target.c | 84 ++++++++++++++++++++++++++-------------------------
1 file changed, 43 insertions(+), 41 deletions(-)
diff --git a/tcg/mips/tcg-target.c b/tcg/mips/tcg-target.c
index 9293745..a09c0d6 100644
--- a/tcg/mips/tcg-target.c
+++ b/tcg/mips/tcg-target.c
@@ -842,18 +842,16 @@ static const void * const qemu_st_helpers[4] = {
static void tcg_out_qemu_ld(TCGContext *s, const TCGArg *args,
int opc)
{
- int addr_regl, addr_meml;
- int data_regl, data_regh, data_reg1, data_reg2;
- int mem_index, s_bits;
+ int addr_regl, data_regl, data_regh, data_reg1, data_reg2;
#if defined(CONFIG_SOFTMMU)
void *label1_ptr, *label2_ptr;
int arg_num;
-#endif
-#if TARGET_LONG_BITS == 64
-# if defined(CONFIG_SOFTMMU)
+ int mem_index, s_bits;
+ int addr_meml;
+# if TARGET_LONG_BITS == 64
uint8_t *label3_ptr;
-# endif
int addr_regh, addr_memh;
+# endif
#endif
data_regl = *args++;
if (opc == 3)
@@ -861,11 +859,22 @@ static void tcg_out_qemu_ld(TCGContext *s, const TCGArg *args,
else
data_regh = 0;
addr_regl = *args++;
-#if TARGET_LONG_BITS == 64
+#if defined(CONFIG_SOFTMMU)
+# if TARGET_LONG_BITS == 64
addr_regh = *args++;
-#endif
+# if defined(TCG_TARGET_WORDS_BIGENDIAN)
+ addr_memh = 0;
+ addr_meml = 4;
+# else
+ addr_memh = 4;
+ addr_meml = 0;
+# endif
+# else
+ addr_meml = 0;
+# endif
mem_index = *args;
s_bits = opc & 3;
+#endif
if (opc == 3) {
#if defined(TCG_TARGET_WORDS_BIGENDIAN)
@@ -879,18 +888,6 @@ static void tcg_out_qemu_ld(TCGContext *s, const TCGArg *args,
data_reg1 = data_regl;
data_reg2 = 0;
}
-#if TARGET_LONG_BITS == 64
-# if defined(TCG_TARGET_WORDS_BIGENDIAN)
- addr_memh = 0;
- addr_meml = 4;
-# else
- addr_memh = 4;
- addr_meml = 0;
-# endif
-#else
- addr_meml = 0;
-#endif
-
#if defined(CONFIG_SOFTMMU)
tcg_out_opc_sa(s, OPC_SRL, TCG_REG_A0, addr_regl, TARGET_PAGE_BITS - CPU_TLB_ENTRY_BITS);
tcg_out_opc_imm(s, OPC_ANDI, TCG_REG_A0, TCG_REG_A0, (CPU_TLB_SIZE - 1) << CPU_TLB_ENTRY_BITS);
@@ -1029,50 +1026,55 @@ static void tcg_out_qemu_ld(TCGContext *s, const TCGArg *args,
static void tcg_out_qemu_st(TCGContext *s, const TCGArg *args,
int opc)
{
- int addr_regl, addr_meml;
- int data_regl, data_regh, data_reg1, data_reg2;
- int mem_index, s_bits;
+ int addr_regl, data_regl, data_regh, data_reg1, data_reg2;
#if defined(CONFIG_SOFTMMU)
uint8_t *label1_ptr, *label2_ptr;
int arg_num;
+ int mem_index, s_bits;
+ int addr_meml;
#endif
#if TARGET_LONG_BITS == 64
# if defined(CONFIG_SOFTMMU)
uint8_t *label3_ptr;
-# endif
int addr_regh, addr_memh;
+# endif
#endif
-
data_regl = *args++;
if (opc == 3) {
data_regh = *args++;
-#if defined(TCG_TARGET_WORDS_BIGENDIAN)
- data_reg1 = data_regh;
- data_reg2 = data_regl;
-#else
- data_reg1 = data_regl;
- data_reg2 = data_regh;
-#endif
} else {
- data_reg1 = data_regl;
- data_reg2 = 0;
data_regh = 0;
}
addr_regl = *args++;
-#if TARGET_LONG_BITS == 64
+#if defined(CONFIG_SOFTMMU)
+# if TARGET_LONG_BITS == 64
addr_regh = *args++;
-# if defined(TCG_TARGET_WORDS_BIGENDIAN)
+# if defined(TCG_TARGET_WORDS_BIGENDIAN)
addr_memh = 0;
addr_meml = 4;
-# else
+# else
addr_memh = 4;
addr_meml = 0;
-# endif
-#else
+# endif
+# else
addr_meml = 0;
-#endif
+# endif
mem_index = *args;
s_bits = opc;
+#endif
+
+ if (opc == 3) {
+#if defined(TCG_TARGET_WORDS_BIGENDIAN)
+ data_reg1 = data_regh;
+ data_reg2 = data_regl;
+#else
+ data_reg1 = data_regl;
+ data_reg2 = data_regh;
+#endif
+ } else {
+ data_reg1 = data_regl;
+ data_reg2 = 0;
+ }
#if defined(CONFIG_SOFTMMU)
tcg_out_opc_sa(s, OPC_SRL, TCG_REG_A0, addr_regl, TARGET_PAGE_BITS - CPU_TLB_ENTRY_BITS);
--
1.7.12.1

View File

@ -0,0 +1,246 @@
From 7b817977fbb87ee2e34018d92b64907197974a75 Mon Sep 17 00:00:00 2001
From: Aurelien Jarno <aurelien@aurel32.net>
Date: Fri, 21 Sep 2012 18:20:26 +0200
Subject: [PATCH] tcg/mips: use TCGArg or TCGReg instead of int
Instead of int, use the correct TCGArg and TCGReg type: TCGReg when
representing a TCG target register, TCGArg when representing the latter
or a constant.
Reviewed-by: Richard Henderson <rth@twiddle.net>
Signed-off-by: Aurelien Jarno <aurelien@aurel32.net>
Signed-off-by: Michael Roth <mdroth@linux.vnet.ibm.com>
---
tcg/mips/tcg-target.c | 63 ++++++++++++++++++++++++++++-----------------------
1 file changed, 35 insertions(+), 28 deletions(-)
diff --git a/tcg/mips/tcg-target.c b/tcg/mips/tcg-target.c
index a09c0d6..8b38f98 100644
--- a/tcg/mips/tcg-target.c
+++ b/tcg/mips/tcg-target.c
@@ -68,7 +68,7 @@ static const char * const tcg_target_reg_names[TCG_TARGET_NB_REGS] = {
#endif
/* check if we really need so many registers :P */
-static const int tcg_target_reg_alloc_order[] = {
+static const TCGReg tcg_target_reg_alloc_order[] = {
TCG_REG_S0,
TCG_REG_S1,
TCG_REG_S2,
@@ -94,14 +94,14 @@ static const int tcg_target_reg_alloc_order[] = {
TCG_REG_V1
};
-static const int tcg_target_call_iarg_regs[4] = {
+static const TCGReg tcg_target_call_iarg_regs[4] = {
TCG_REG_A0,
TCG_REG_A1,
TCG_REG_A2,
TCG_REG_A3
};
-static const int tcg_target_call_oarg_regs[2] = {
+static const TCGReg tcg_target_call_oarg_regs[2] = {
TCG_REG_V0,
TCG_REG_V1
};
@@ -327,7 +327,8 @@ enum {
/*
* Type reg
*/
-static inline void tcg_out_opc_reg(TCGContext *s, int opc, int rd, int rs, int rt)
+static inline void tcg_out_opc_reg(TCGContext *s, int opc,
+ TCGReg rd, TCGReg rs, TCGReg rt)
{
int32_t inst;
@@ -341,7 +342,8 @@ static inline void tcg_out_opc_reg(TCGContext *s, int opc, int rd, int rs, int r
/*
* Type immediate
*/
-static inline void tcg_out_opc_imm(TCGContext *s, int opc, int rt, int rs, int imm)
+static inline void tcg_out_opc_imm(TCGContext *s, int opc,
+ TCGReg rt, TCGReg rs, TCGArg imm)
{
int32_t inst;
@@ -355,7 +357,8 @@ static inline void tcg_out_opc_imm(TCGContext *s, int opc, int rt, int rs, int i
/*
* Type branch
*/
-static inline void tcg_out_opc_br(TCGContext *s, int opc, int rt, int rs)
+static inline void tcg_out_opc_br(TCGContext *s, int opc,
+ TCGReg rt, TCGReg rs)
{
/* We pay attention here to not modify the branch target by reading
the existing value and using it again. This ensure that caches and
@@ -368,7 +371,8 @@ static inline void tcg_out_opc_br(TCGContext *s, int opc, int rt, int rs)
/*
* Type sa
*/
-static inline void tcg_out_opc_sa(TCGContext *s, int opc, int rd, int rt, int sa)
+static inline void tcg_out_opc_sa(TCGContext *s, int opc,
+ TCGReg rd, TCGReg rt, TCGArg sa)
{
int32_t inst;
@@ -407,7 +411,7 @@ static inline void tcg_out_movi(TCGContext *s, TCGType type,
}
}
-static inline void tcg_out_bswap16(TCGContext *s, int ret, int arg)
+static inline void tcg_out_bswap16(TCGContext *s, TCGReg ret, TCGReg arg)
{
/* ret and arg can't be register at */
if (ret == TCG_REG_AT || arg == TCG_REG_AT) {
@@ -422,7 +426,7 @@ static inline void tcg_out_bswap16(TCGContext *s, int ret, int arg)
tcg_out_opc_reg(s, OPC_OR, ret, ret, TCG_REG_AT);
}
-static inline void tcg_out_bswap16s(TCGContext *s, int ret, int arg)
+static inline void tcg_out_bswap16s(TCGContext *s, TCGReg ret, TCGReg arg)
{
/* ret and arg can't be register at */
if (ret == TCG_REG_AT || arg == TCG_REG_AT) {
@@ -437,7 +441,7 @@ static inline void tcg_out_bswap16s(TCGContext *s, int ret, int arg)
tcg_out_opc_reg(s, OPC_OR, ret, ret, TCG_REG_AT);
}
-static inline void tcg_out_bswap32(TCGContext *s, int ret, int arg)
+static inline void tcg_out_bswap32(TCGContext *s, TCGReg ret, TCGReg arg)
{
/* ret and arg must be different and can't be register at */
if (ret == arg || ret == TCG_REG_AT || arg == TCG_REG_AT) {
@@ -458,7 +462,7 @@ static inline void tcg_out_bswap32(TCGContext *s, int ret, int arg)
tcg_out_opc_reg(s, OPC_OR, ret, ret, TCG_REG_AT);
}
-static inline void tcg_out_ext8s(TCGContext *s, int ret, int arg)
+static inline void tcg_out_ext8s(TCGContext *s, TCGReg ret, TCGReg arg)
{
#ifdef _MIPS_ARCH_MIPS32R2
tcg_out_opc_reg(s, OPC_SEB, ret, 0, arg);
@@ -468,7 +472,7 @@ static inline void tcg_out_ext8s(TCGContext *s, int ret, int arg)
#endif
}
-static inline void tcg_out_ext16s(TCGContext *s, int ret, int arg)
+static inline void tcg_out_ext16s(TCGContext *s, TCGReg ret, TCGReg arg)
{
#ifdef _MIPS_ARCH_MIPS32R2
tcg_out_opc_reg(s, OPC_SEH, ret, 0, arg);
@@ -478,8 +482,8 @@ static inline void tcg_out_ext16s(TCGContext *s, int ret, int arg)
#endif
}
-static inline void tcg_out_ldst(TCGContext *s, int opc, int arg,
- int arg1, tcg_target_long arg2)
+static inline void tcg_out_ldst(TCGContext *s, int opc, TCGArg arg,
+ TCGReg arg1, TCGArg arg2)
{
if (arg2 == (int16_t) arg2) {
tcg_out_opc_imm(s, opc, arg, arg1, arg2);
@@ -502,7 +506,7 @@ static inline void tcg_out_st(TCGContext *s, TCGType type, TCGReg arg,
tcg_out_ldst(s, OPC_SW, arg, arg1, arg2);
}
-static inline void tcg_out_addi(TCGContext *s, int reg, tcg_target_long val)
+static inline void tcg_out_addi(TCGContext *s, TCGReg reg, TCGArg val)
{
if (val == (int16_t)val) {
tcg_out_opc_imm(s, OPC_ADDIU, reg, reg, val);
@@ -543,7 +547,7 @@ DEFINE_TCG_OUT_CALL_IARG(tcg_out_call_iarg_reg16, TCGReg arg)
#undef DEFINE_TCG_OUT_CALL_IARG_GET_ARG
#define DEFINE_TCG_OUT_CALL_IARG_GET_ARG(A) \
tcg_out_movi(s, TCG_TYPE_I32, A, arg);
-DEFINE_TCG_OUT_CALL_IARG(tcg_out_call_iarg_imm32, uint32_t arg)
+DEFINE_TCG_OUT_CALL_IARG(tcg_out_call_iarg_imm32, TCGArg arg)
#undef DEFINE_TCG_OUT_CALL_IARG_GET_ARG
/* We don't use the macro for this one to avoid an unnecessary reg-reg
@@ -573,8 +577,8 @@ static inline void tcg_out_call_iarg_reg64(TCGContext *s, int *arg_num,
#endif
}
-static void tcg_out_brcond(TCGContext *s, TCGCond cond, int arg1,
- int arg2, int label_index)
+static void tcg_out_brcond(TCGContext *s, TCGCond cond, TCGArg arg1,
+ TCGArg arg2, int label_index)
{
TCGLabel *l = &s->labels[label_index];
@@ -631,8 +635,9 @@ static void tcg_out_brcond(TCGContext *s, TCGCond cond, int arg1,
/* XXX: we implement it at the target level to avoid having to
handle cross basic blocks temporaries */
-static void tcg_out_brcond2(TCGContext *s, TCGCond cond, int arg1,
- int arg2, int arg3, int arg4, int label_index)
+static void tcg_out_brcond2(TCGContext *s, TCGCond cond, TCGArg arg1,
+ TCGArg arg2, TCGArg arg3, TCGArg arg4,
+ int label_index)
{
void *label_ptr;
@@ -694,8 +699,8 @@ static void tcg_out_brcond2(TCGContext *s, TCGCond cond, int arg1,
reloc_pc16(label_ptr, (tcg_target_long) s->code_ptr);
}
-static void tcg_out_setcond(TCGContext *s, TCGCond cond, int ret,
- int arg1, int arg2)
+static void tcg_out_setcond(TCGContext *s, TCGCond cond, TCGReg ret,
+ TCGArg arg1, TCGArg arg2)
{
switch (cond) {
case TCG_COND_EQ:
@@ -754,8 +759,8 @@ static void tcg_out_setcond(TCGContext *s, TCGCond cond, int ret,
/* XXX: we implement it at the target level to avoid having to
handle cross basic blocks temporaries */
-static void tcg_out_setcond2(TCGContext *s, TCGCond cond, int ret,
- int arg1, int arg2, int arg3, int arg4)
+static void tcg_out_setcond2(TCGContext *s, TCGCond cond, TCGReg ret,
+ TCGArg arg1, TCGArg arg2, TCGArg arg3, TCGArg arg4)
{
switch (cond) {
case TCG_COND_EQ:
@@ -842,7 +847,7 @@ static const void * const qemu_st_helpers[4] = {
static void tcg_out_qemu_ld(TCGContext *s, const TCGArg *args,
int opc)
{
- int addr_regl, data_regl, data_regh, data_reg1, data_reg2;
+ TCGReg addr_regl, data_regl, data_regh, data_reg1, data_reg2;
#if defined(CONFIG_SOFTMMU)
void *label1_ptr, *label2_ptr;
int arg_num;
@@ -850,7 +855,8 @@ static void tcg_out_qemu_ld(TCGContext *s, const TCGArg *args,
int addr_meml;
# if TARGET_LONG_BITS == 64
uint8_t *label3_ptr;
- int addr_regh, addr_memh;
+ TCGReg addr_regh;
+ int addr_memh;
# endif
#endif
data_regl = *args++;
@@ -1026,7 +1032,7 @@ static void tcg_out_qemu_ld(TCGContext *s, const TCGArg *args,
static void tcg_out_qemu_st(TCGContext *s, const TCGArg *args,
int opc)
{
- int addr_regl, data_regl, data_regh, data_reg1, data_reg2;
+ TCGReg addr_regl, data_regl, data_regh, data_reg1, data_reg2;
#if defined(CONFIG_SOFTMMU)
uint8_t *label1_ptr, *label2_ptr;
int arg_num;
@@ -1036,7 +1042,8 @@ static void tcg_out_qemu_st(TCGContext *s, const TCGArg *args,
#if TARGET_LONG_BITS == 64
# if defined(CONFIG_SOFTMMU)
uint8_t *label3_ptr;
- int addr_regh, addr_memh;
+ TCGReg addr_regh;
+ int addr_memh;
# endif
#endif
data_regl = *args++;
--
1.7.12.1

View File

@ -0,0 +1,37 @@
From 9a4f545e4526f946613548a427fcab4c2a089ac0 Mon Sep 17 00:00:00 2001
From: Aurelien Jarno <aurelien@aurel32.net>
Date: Fri, 21 Sep 2012 18:20:26 +0200
Subject: [PATCH] tcg/mips: don't use global pointer
Don't use the global pointer in TCG, in case helpers try access global
variables.
Signed-off-by: Aurelien Jarno <aurelien@aurel32.net>
Signed-off-by: Michael Roth <mdroth@linux.vnet.ibm.com>
---
tcg/mips/tcg-target.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/tcg/mips/tcg-target.c b/tcg/mips/tcg-target.c
index 8b38f98..0ea6a76 100644
--- a/tcg/mips/tcg-target.c
+++ b/tcg/mips/tcg-target.c
@@ -1529,7 +1529,6 @@ static int tcg_target_callee_save_regs[] = {
TCG_REG_S5,
TCG_REG_S6,
TCG_REG_S7,
- TCG_REG_GP,
TCG_REG_FP,
TCG_REG_RA, /* should be last for ABI compliance */
};
@@ -1595,6 +1594,7 @@ static void tcg_target_init(TCGContext *s)
tcg_regset_set_reg(s->reserved_regs, TCG_REG_T0); /* internal use */
tcg_regset_set_reg(s->reserved_regs, TCG_REG_RA); /* return address */
tcg_regset_set_reg(s->reserved_regs, TCG_REG_SP); /* stack pointer */
+ tcg_regset_set_reg(s->reserved_regs, TCG_REG_GP); /* global pointer */
tcg_add_target_add_op_defs(mips_op_defs);
tcg_set_frame(s, TCG_AREG0, offsetof(CPUArchState, temp_buf),
--
1.7.12.1

View File

@ -0,0 +1,47 @@
From c914ae50df4dc2f2ab589c87c0cd2ce2f14d9639 Mon Sep 17 00:00:00 2001
From: Aurelien Jarno <aurelien@aurel32.net>
Date: Fri, 21 Sep 2012 18:20:26 +0200
Subject: [PATCH] tcg/mips: use stack for TCG temps
Use stack instead of temp_buf array in CPUState for TCG
temps.
Reviewed-by: Richard Henderson <rth@twiddle.net>
Signed-off-by: Aurelien Jarno <aurelien@aurel32.net>
Signed-off-by: Michael Roth <mdroth@linux.vnet.ibm.com>
---
tcg/mips/tcg-target.c | 10 ++++++----
1 file changed, 6 insertions(+), 4 deletions(-)
diff --git a/tcg/mips/tcg-target.c b/tcg/mips/tcg-target.c
index 0ea6a76..c05169f 100644
--- a/tcg/mips/tcg-target.c
+++ b/tcg/mips/tcg-target.c
@@ -1538,11 +1538,15 @@ static void tcg_target_qemu_prologue(TCGContext *s)
{
int i, frame_size;
- /* reserve some stack space */
+ /* reserve some stack space, also for TCG temps. */
frame_size = ARRAY_SIZE(tcg_target_callee_save_regs) * 4
- + TCG_STATIC_CALL_ARGS_SIZE;
+ + TCG_STATIC_CALL_ARGS_SIZE
+ + CPU_TEMP_BUF_NLONGS * sizeof(long);
frame_size = (frame_size + TCG_TARGET_STACK_ALIGN - 1) &
~(TCG_TARGET_STACK_ALIGN - 1);
+ tcg_set_frame(s, TCG_REG_SP, ARRAY_SIZE(tcg_target_callee_save_regs) * 4
+ + TCG_STATIC_CALL_ARGS_SIZE,
+ CPU_TEMP_BUF_NLONGS * sizeof(long));
/* TB prologue */
tcg_out_addi(s, TCG_REG_SP, -frame_size);
@@ -1597,6 +1601,4 @@ static void tcg_target_init(TCGContext *s)
tcg_regset_set_reg(s->reserved_regs, TCG_REG_GP); /* global pointer */
tcg_add_target_add_op_defs(mips_op_defs);
- tcg_set_frame(s, TCG_AREG0, offsetof(CPUArchState, temp_buf),
- CPU_TEMP_BUF_NLONGS * sizeof(long));
}
--
1.7.12.1

View File

@ -0,0 +1,99 @@
From e30cf829e9d8200364b53b9189c76d2155a32876 Mon Sep 17 00:00:00 2001
From: Aurelien Jarno <aurelien@aurel32.net>
Date: Fri, 21 Sep 2012 18:20:26 +0200
Subject: [PATCH] tcg/mips: optimize brcond arg, 0
MIPS has some conditional branch instructions when comparing with zero.
Use them.
Reviewed-by: Richard Henderson <rth@twiddle.net>
Signed-off-by: Aurelien Jarno <aurelien@aurel32.net>
Signed-off-by: Michael Roth <mdroth@linux.vnet.ibm.com>
---
tcg/mips/tcg-target.c | 38 ++++++++++++++++++++++++++++++--------
1 file changed, 30 insertions(+), 8 deletions(-)
diff --git a/tcg/mips/tcg-target.c b/tcg/mips/tcg-target.c
index c05169f..6aa4527 100644
--- a/tcg/mips/tcg-target.c
+++ b/tcg/mips/tcg-target.c
@@ -278,6 +278,8 @@ static inline int tcg_target_const_match(tcg_target_long val,
enum {
OPC_BEQ = 0x04 << 26,
OPC_BNE = 0x05 << 26,
+ OPC_BLEZ = 0x06 << 26,
+ OPC_BGTZ = 0x07 << 26,
OPC_ADDIU = 0x09 << 26,
OPC_SLTI = 0x0A << 26,
OPC_SLTIU = 0x0B << 26,
@@ -319,6 +321,10 @@ enum {
OPC_SLT = OPC_SPECIAL | 0x2A,
OPC_SLTU = OPC_SPECIAL | 0x2B,
+ OPC_REGIMM = 0x01 << 26,
+ OPC_BLTZ = OPC_REGIMM | (0x00 << 16),
+ OPC_BGEZ = OPC_REGIMM | (0x01 << 16),
+
OPC_SPECIAL3 = 0x1f << 26,
OPC_SEB = OPC_SPECIAL3 | 0x420,
OPC_SEH = OPC_SPECIAL3 | 0x620,
@@ -590,32 +596,48 @@ static void tcg_out_brcond(TCGContext *s, TCGCond cond, TCGArg arg1,
tcg_out_opc_br(s, OPC_BNE, arg1, arg2);
break;
case TCG_COND_LT:
- tcg_out_opc_reg(s, OPC_SLT, TCG_REG_AT, arg1, arg2);
- tcg_out_opc_br(s, OPC_BNE, TCG_REG_AT, TCG_REG_ZERO);
+ if (arg2 == 0) {
+ tcg_out_opc_br(s, OPC_BLTZ, 0, arg1);
+ } else {
+ tcg_out_opc_reg(s, OPC_SLT, TCG_REG_AT, arg1, arg2);
+ tcg_out_opc_br(s, OPC_BNE, TCG_REG_AT, TCG_REG_ZERO);
+ }
break;
case TCG_COND_LTU:
tcg_out_opc_reg(s, OPC_SLTU, TCG_REG_AT, arg1, arg2);
tcg_out_opc_br(s, OPC_BNE, TCG_REG_AT, TCG_REG_ZERO);
break;
case TCG_COND_GE:
- tcg_out_opc_reg(s, OPC_SLT, TCG_REG_AT, arg1, arg2);
- tcg_out_opc_br(s, OPC_BEQ, TCG_REG_AT, TCG_REG_ZERO);
+ if (arg2 == 0) {
+ tcg_out_opc_br(s, OPC_BGEZ, 0, arg1);
+ } else {
+ tcg_out_opc_reg(s, OPC_SLT, TCG_REG_AT, arg1, arg2);
+ tcg_out_opc_br(s, OPC_BEQ, TCG_REG_AT, TCG_REG_ZERO);
+ }
break;
case TCG_COND_GEU:
tcg_out_opc_reg(s, OPC_SLTU, TCG_REG_AT, arg1, arg2);
tcg_out_opc_br(s, OPC_BEQ, TCG_REG_AT, TCG_REG_ZERO);
break;
case TCG_COND_LE:
- tcg_out_opc_reg(s, OPC_SLT, TCG_REG_AT, arg2, arg1);
- tcg_out_opc_br(s, OPC_BEQ, TCG_REG_AT, TCG_REG_ZERO);
+ if (arg2 == 0) {
+ tcg_out_opc_br(s, OPC_BLEZ, 0, arg1);
+ } else {
+ tcg_out_opc_reg(s, OPC_SLT, TCG_REG_AT, arg2, arg1);
+ tcg_out_opc_br(s, OPC_BEQ, TCG_REG_AT, TCG_REG_ZERO);
+ }
break;
case TCG_COND_LEU:
tcg_out_opc_reg(s, OPC_SLTU, TCG_REG_AT, arg2, arg1);
tcg_out_opc_br(s, OPC_BEQ, TCG_REG_AT, TCG_REG_ZERO);
break;
case TCG_COND_GT:
- tcg_out_opc_reg(s, OPC_SLT, TCG_REG_AT, arg2, arg1);
- tcg_out_opc_br(s, OPC_BNE, TCG_REG_AT, TCG_REG_ZERO);
+ if (arg2 == 0) {
+ tcg_out_opc_br(s, OPC_BGTZ, 0, arg1);
+ } else {
+ tcg_out_opc_reg(s, OPC_SLT, TCG_REG_AT, arg2, arg1);
+ tcg_out_opc_br(s, OPC_BNE, TCG_REG_AT, TCG_REG_ZERO);
+ }
break;
case TCG_COND_GTU:
tcg_out_opc_reg(s, OPC_SLTU, TCG_REG_AT, arg2, arg1);
--
1.7.12.1

View File

@ -0,0 +1,161 @@
From 879794c3d3974b1206bbc52011c8f2525709f396 Mon Sep 17 00:00:00 2001
From: Aurelien Jarno <aurelien@aurel32.net>
Date: Fri, 21 Sep 2012 18:20:26 +0200
Subject: [PATCH] tcg/mips: optimize bswap{16,16s,32} on MIPS32R2
bswap operations can be optimized on MIPS32 Release 2 using the ROTR,
WSBH and SEH instructions. We can't use the non-R2 code to implement the
ops due to registers constraints, so don't define the corresponding
TCG_TARGET_HAS_bswap* values.
Also bswap16* operations are supposed to be called with the 16 high bits
zeroed. This is the case everywhere (including for TCG by definition)
except when called from the store helper. Remove the AND instructions from
bswap16* and move it there.
Reviewed-by: Richard Henderson <rth@twiddle.net>
Signed-off-by: Aurelien Jarno <aurelien@aurel32.net>
Signed-off-by: Michael Roth <mdroth@linux.vnet.ibm.com>
---
tcg/mips/tcg-target.c | 34 +++++++++++++++++++++++++++++-----
tcg/mips/tcg-target.h | 11 +++++++++--
2 files changed, 38 insertions(+), 7 deletions(-)
diff --git a/tcg/mips/tcg-target.c b/tcg/mips/tcg-target.c
index 6aa4527..8b2f9fc 100644
--- a/tcg/mips/tcg-target.c
+++ b/tcg/mips/tcg-target.c
@@ -326,6 +326,7 @@ enum {
OPC_BGEZ = OPC_REGIMM | (0x01 << 16),
OPC_SPECIAL3 = 0x1f << 26,
+ OPC_WSBH = OPC_SPECIAL3 | 0x0a0,
OPC_SEB = OPC_SPECIAL3 | 0x420,
OPC_SEH = OPC_SPECIAL3 | 0x620,
};
@@ -419,36 +420,45 @@ static inline void tcg_out_movi(TCGContext *s, TCGType type,
static inline void tcg_out_bswap16(TCGContext *s, TCGReg ret, TCGReg arg)
{
+#ifdef _MIPS_ARCH_MIPS32R2
+ tcg_out_opc_reg(s, OPC_WSBH, ret, 0, arg);
+#else
/* ret and arg can't be register at */
if (ret == TCG_REG_AT || arg == TCG_REG_AT) {
tcg_abort();
}
tcg_out_opc_sa(s, OPC_SRL, TCG_REG_AT, arg, 8);
- tcg_out_opc_imm(s, OPC_ANDI, TCG_REG_AT, TCG_REG_AT, 0x00ff);
-
tcg_out_opc_sa(s, OPC_SLL, ret, arg, 8);
tcg_out_opc_imm(s, OPC_ANDI, ret, ret, 0xff00);
tcg_out_opc_reg(s, OPC_OR, ret, ret, TCG_REG_AT);
+#endif
}
static inline void tcg_out_bswap16s(TCGContext *s, TCGReg ret, TCGReg arg)
{
+#ifdef _MIPS_ARCH_MIPS32R2
+ tcg_out_opc_reg(s, OPC_WSBH, ret, 0, arg);
+ tcg_out_opc_reg(s, OPC_SEH, ret, 0, ret);
+#else
/* ret and arg can't be register at */
if (ret == TCG_REG_AT || arg == TCG_REG_AT) {
tcg_abort();
}
tcg_out_opc_sa(s, OPC_SRL, TCG_REG_AT, arg, 8);
- tcg_out_opc_imm(s, OPC_ANDI, TCG_REG_AT, TCG_REG_AT, 0xff);
-
tcg_out_opc_sa(s, OPC_SLL, ret, arg, 24);
tcg_out_opc_sa(s, OPC_SRA, ret, ret, 16);
tcg_out_opc_reg(s, OPC_OR, ret, ret, TCG_REG_AT);
+#endif
}
static inline void tcg_out_bswap32(TCGContext *s, TCGReg ret, TCGReg arg)
{
+#ifdef _MIPS_ARCH_MIPS32R2
+ tcg_out_opc_reg(s, OPC_WSBH, ret, 0, arg);
+ tcg_out_opc_sa(s, OPC_ROTR, ret, ret, 16);
+#else
/* ret and arg must be different and can't be register at */
if (ret == arg || ret == TCG_REG_AT || arg == TCG_REG_AT) {
tcg_abort();
@@ -466,6 +476,7 @@ static inline void tcg_out_bswap32(TCGContext *s, TCGReg ret, TCGReg arg)
tcg_out_opc_sa(s, OPC_SRL, TCG_REG_AT, arg, 8);
tcg_out_opc_imm(s, OPC_ANDI, TCG_REG_AT, TCG_REG_AT, 0xff00);
tcg_out_opc_reg(s, OPC_OR, ret, ret, TCG_REG_AT);
+#endif
}
static inline void tcg_out_ext8s(TCGContext *s, TCGReg ret, TCGReg arg)
@@ -1188,7 +1199,8 @@ static void tcg_out_qemu_st(TCGContext *s, const TCGArg *args,
break;
case 1:
if (TCG_NEED_BSWAP) {
- tcg_out_bswap16(s, TCG_REG_T0, data_reg1);
+ tcg_out_opc_imm(s, OPC_ANDI, TCG_REG_T0, data_reg1, 0xffff);
+ tcg_out_bswap16(s, TCG_REG_T0, TCG_REG_T0);
tcg_out_opc_imm(s, OPC_SH, TCG_REG_T0, TCG_REG_A0, 0);
} else {
tcg_out_opc_imm(s, OPC_SH, data_reg1, TCG_REG_A0, 0);
@@ -1409,6 +1421,15 @@ static inline void tcg_out_op(TCGContext *s, TCGOpcode opc,
}
break;
+ /* The bswap routines do not work on non-R2 CPU. In that case
+ we let TCG generating the corresponding code. */
+ case INDEX_op_bswap16_i32:
+ tcg_out_bswap16(s, args[0], args[1]);
+ break;
+ case INDEX_op_bswap32_i32:
+ tcg_out_bswap32(s, args[0], args[1]);
+ break;
+
case INDEX_op_ext8s_i32:
tcg_out_ext8s(s, args[0], args[1]);
break;
@@ -1503,6 +1524,9 @@ static const TCGTargetOpDef mips_op_defs[] = {
{ INDEX_op_shr_i32, { "r", "rZ", "ri" } },
{ INDEX_op_sar_i32, { "r", "rZ", "ri" } },
+ { INDEX_op_bswap16_i32, { "r", "r" } },
+ { INDEX_op_bswap32_i32, { "r", "r" } },
+
{ INDEX_op_ext8s_i32, { "r", "rZ" } },
{ INDEX_op_ext16s_i32, { "r", "rZ" } },
diff --git a/tcg/mips/tcg-target.h b/tcg/mips/tcg-target.h
index 9c68a32..c5c13f7 100644
--- a/tcg/mips/tcg-target.h
+++ b/tcg/mips/tcg-target.h
@@ -83,8 +83,6 @@ typedef enum {
#define TCG_TARGET_HAS_rot_i32 0
#define TCG_TARGET_HAS_ext8s_i32 1
#define TCG_TARGET_HAS_ext16s_i32 1
-#define TCG_TARGET_HAS_bswap32_i32 0
-#define TCG_TARGET_HAS_bswap16_i32 0
#define TCG_TARGET_HAS_andc_i32 0
#define TCG_TARGET_HAS_orc_i32 0
#define TCG_TARGET_HAS_eqv_i32 0
@@ -92,6 +90,15 @@ typedef enum {
#define TCG_TARGET_HAS_deposit_i32 0
#define TCG_TARGET_HAS_movcond_i32 0
+/* optional instructions only implemented on MIPS32R2 */
+#ifdef _MIPS_ARCH_MIPS32R2
+#define TCG_TARGET_HAS_bswap16_i32 1
+#define TCG_TARGET_HAS_bswap32_i32 1
+#else
+#define TCG_TARGET_HAS_bswap16_i32 0
+#define TCG_TARGET_HAS_bswap32_i32 0
+#endif
+
/* optional instructions automatically implemented */
#define TCG_TARGET_HAS_neg_i32 0 /* sub rd, zero, rt */
#define TCG_TARGET_HAS_ext8u_i32 0 /* andi rt, rs, 0xff */
--
1.7.12.1

View File

@ -0,0 +1,92 @@
From d19858a5515cd15dabf88b8f180754c1c3f3eb76 Mon Sep 17 00:00:00 2001
From: Aurelien Jarno <aurelien@aurel32.net>
Date: Fri, 21 Sep 2012 18:20:26 +0200
Subject: [PATCH] tcg/mips: implement rotl/rotr ops on MIPS32R2
rotr operations can be optimized on MIPS32 Release 2 using the ROTR and
ROTRV instructions. Also implemented rotl operations by subtracting the
shift from 32.
Reviewed-by: Richard Henderson <rth@twiddle.net>
Signed-off-by: Aurelien Jarno <aurelien@aurel32.net>
Signed-off-by: Michael Roth <mdroth@linux.vnet.ibm.com>
---
tcg/mips/tcg-target.c | 20 ++++++++++++++++++++
tcg/mips/tcg-target.h | 3 ++-
2 files changed, 22 insertions(+), 1 deletion(-)
diff --git a/tcg/mips/tcg-target.c b/tcg/mips/tcg-target.c
index 8b2f9fc..592e42a 100644
--- a/tcg/mips/tcg-target.c
+++ b/tcg/mips/tcg-target.c
@@ -300,9 +300,11 @@ enum {
OPC_SPECIAL = 0x00 << 26,
OPC_SLL = OPC_SPECIAL | 0x00,
OPC_SRL = OPC_SPECIAL | 0x02,
+ OPC_ROTR = OPC_SPECIAL | (0x01 << 21) | 0x02,
OPC_SRA = OPC_SPECIAL | 0x03,
OPC_SLLV = OPC_SPECIAL | 0x04,
OPC_SRLV = OPC_SPECIAL | 0x06,
+ OPC_ROTRV = OPC_SPECIAL | (0x01 << 6) | 0x06,
OPC_SRAV = OPC_SPECIAL | 0x07,
OPC_JR = OPC_SPECIAL | 0x08,
OPC_JALR = OPC_SPECIAL | 0x09,
@@ -1420,6 +1422,22 @@ static inline void tcg_out_op(TCGContext *s, TCGOpcode opc,
tcg_out_opc_reg(s, OPC_SRLV, args[0], args[2], args[1]);
}
break;
+ case INDEX_op_rotl_i32:
+ if (const_args[2]) {
+ tcg_out_opc_sa(s, OPC_ROTR, args[0], args[1], 0x20 - args[2]);
+ } else {
+ tcg_out_movi(s, TCG_TYPE_I32, TCG_REG_AT, 32);
+ tcg_out_opc_reg(s, OPC_SUBU, TCG_REG_AT, TCG_REG_AT, args[2]);
+ tcg_out_opc_reg(s, OPC_ROTRV, args[0], TCG_REG_AT, args[1]);
+ }
+ break;
+ case INDEX_op_rotr_i32:
+ if (const_args[2]) {
+ tcg_out_opc_sa(s, OPC_ROTR, args[0], args[1], args[2]);
+ } else {
+ tcg_out_opc_reg(s, OPC_ROTRV, args[0], args[2], args[1]);
+ }
+ break;
/* The bswap routines do not work on non-R2 CPU. In that case
we let TCG generating the corresponding code. */
@@ -1523,6 +1541,8 @@ static const TCGTargetOpDef mips_op_defs[] = {
{ INDEX_op_shl_i32, { "r", "rZ", "ri" } },
{ INDEX_op_shr_i32, { "r", "rZ", "ri" } },
{ INDEX_op_sar_i32, { "r", "rZ", "ri" } },
+ { INDEX_op_rotr_i32, { "r", "rZ", "ri" } },
+ { INDEX_op_rotl_i32, { "r", "rZ", "ri" } },
{ INDEX_op_bswap16_i32, { "r", "r" } },
{ INDEX_op_bswap32_i32, { "r", "r" } },
diff --git a/tcg/mips/tcg-target.h b/tcg/mips/tcg-target.h
index c5c13f7..470314c 100644
--- a/tcg/mips/tcg-target.h
+++ b/tcg/mips/tcg-target.h
@@ -80,7 +80,6 @@ typedef enum {
#define TCG_TARGET_HAS_div_i32 1
#define TCG_TARGET_HAS_not_i32 1
#define TCG_TARGET_HAS_nor_i32 1
-#define TCG_TARGET_HAS_rot_i32 0
#define TCG_TARGET_HAS_ext8s_i32 1
#define TCG_TARGET_HAS_ext16s_i32 1
#define TCG_TARGET_HAS_andc_i32 0
@@ -94,9 +93,11 @@ typedef enum {
#ifdef _MIPS_ARCH_MIPS32R2
#define TCG_TARGET_HAS_bswap16_i32 1
#define TCG_TARGET_HAS_bswap32_i32 1
+#define TCG_TARGET_HAS_rot_i32 1
#else
#define TCG_TARGET_HAS_bswap16_i32 0
#define TCG_TARGET_HAS_bswap32_i32 0
+#define TCG_TARGET_HAS_rot_i32 0
#endif
/* optional instructions automatically implemented */
--
1.7.12.1

View File

@ -0,0 +1,77 @@
From 7c3e573b364a65d4abce5266c376f4e77624b039 Mon Sep 17 00:00:00 2001
From: Aurelien Jarno <aurelien@aurel32.net>
Date: Fri, 21 Sep 2012 18:20:26 +0200
Subject: [PATCH] tcg/mips: implement deposit op on MIPS32R2
deposit operations can be optimized on MIPS32 Release 2 using the INS
instruction.
Reviewed-by: Richard Henderson <rth@twiddle.net>
Signed-off-by: Aurelien Jarno <aurelien@aurel32.net>
Signed-off-by: Michael Roth <mdroth@linux.vnet.ibm.com>
---
tcg/mips/tcg-target.c | 8 ++++++++
tcg/mips/tcg-target.h | 3 ++-
2 files changed, 10 insertions(+), 1 deletion(-)
diff --git a/tcg/mips/tcg-target.c b/tcg/mips/tcg-target.c
index 592e42a..b2e1056 100644
--- a/tcg/mips/tcg-target.c
+++ b/tcg/mips/tcg-target.c
@@ -328,6 +328,7 @@ enum {
OPC_BGEZ = OPC_REGIMM | (0x01 << 16),
OPC_SPECIAL3 = 0x1f << 26,
+ OPC_INS = OPC_SPECIAL3 | 0x004,
OPC_WSBH = OPC_SPECIAL3 | 0x0a0,
OPC_SEB = OPC_SPECIAL3 | 0x420,
OPC_SEH = OPC_SPECIAL3 | 0x620,
@@ -1455,6 +1456,11 @@ static inline void tcg_out_op(TCGContext *s, TCGOpcode opc,
tcg_out_ext16s(s, args[0], args[1]);
break;
+ case INDEX_op_deposit_i32:
+ tcg_out_opc_imm(s, OPC_INS, args[0], args[2],
+ ((args[3] + args[4] - 1) << 11) | (args[3] << 6));
+ break;
+
case INDEX_op_brcond_i32:
tcg_out_brcond(s, args[2], args[0], args[1], args[3]);
break;
@@ -1550,6 +1556,8 @@ static const TCGTargetOpDef mips_op_defs[] = {
{ INDEX_op_ext8s_i32, { "r", "rZ" } },
{ INDEX_op_ext16s_i32, { "r", "rZ" } },
+ { INDEX_op_deposit_i32, { "r", "0", "rZ" } },
+
{ INDEX_op_brcond_i32, { "rZ", "rZ" } },
{ INDEX_op_setcond_i32, { "r", "rZ", "rZ" } },
{ INDEX_op_setcond2_i32, { "r", "rZ", "rZ", "rZ", "rZ" } },
diff --git a/tcg/mips/tcg-target.h b/tcg/mips/tcg-target.h
index 470314c..897a737 100644
--- a/tcg/mips/tcg-target.h
+++ b/tcg/mips/tcg-target.h
@@ -86,7 +86,6 @@ typedef enum {
#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_deposit_i32 0
#define TCG_TARGET_HAS_movcond_i32 0
/* optional instructions only implemented on MIPS32R2 */
@@ -94,10 +93,12 @@ typedef enum {
#define TCG_TARGET_HAS_bswap16_i32 1
#define TCG_TARGET_HAS_bswap32_i32 1
#define TCG_TARGET_HAS_rot_i32 1
+#define TCG_TARGET_HAS_deposit_i32 1
#else
#define TCG_TARGET_HAS_bswap16_i32 0
#define TCG_TARGET_HAS_bswap32_i32 0
#define TCG_TARGET_HAS_rot_i32 0
+#define TCG_TARGET_HAS_deposit_i32 0
#endif
/* optional instructions automatically implemented */
--
1.7.12.1

View File

@ -0,0 +1,140 @@
From 552720cea4c1ca99dd1919cb8a80b6b8f3b13cda Mon Sep 17 00:00:00 2001
From: Aurelien Jarno <aurelien@aurel32.net>
Date: Fri, 21 Sep 2012 18:20:26 +0200
Subject: [PATCH] tcg/mips: implement movcond op on MIPS32R2
movcond operation can be implemented on MIPS32 Release 2 using the MOVN,
MOVZ, SLT and SLTU instructions.
Reviewed-by: Richard Henderson <rth@twiddle.net>
Signed-off-by: Aurelien Jarno <aurelien@aurel32.net>
Signed-off-by: Michael Roth <mdroth@linux.vnet.ibm.com>
---
tcg/mips/tcg-target.c | 69 +++++++++++++++++++++++++++++++++++++++++++++++++++
tcg/mips/tcg-target.h | 8 ++++++
2 files changed, 77 insertions(+)
diff --git a/tcg/mips/tcg-target.c b/tcg/mips/tcg-target.c
index b2e1056..c272b38 100644
--- a/tcg/mips/tcg-target.c
+++ b/tcg/mips/tcg-target.c
@@ -308,6 +308,8 @@ enum {
OPC_SRAV = OPC_SPECIAL | 0x07,
OPC_JR = OPC_SPECIAL | 0x08,
OPC_JALR = OPC_SPECIAL | 0x09,
+ OPC_MOVZ = OPC_SPECIAL | 0x0A,
+ OPC_MOVN = OPC_SPECIAL | 0x0B,
OPC_MFHI = OPC_SPECIAL | 0x10,
OPC_MFLO = OPC_SPECIAL | 0x12,
OPC_MULT = OPC_SPECIAL | 0x18,
@@ -735,6 +737,68 @@ static void tcg_out_brcond2(TCGContext *s, TCGCond cond, TCGArg arg1,
reloc_pc16(label_ptr, (tcg_target_long) s->code_ptr);
}
+static void tcg_out_movcond(TCGContext *s, TCGCond cond, TCGReg ret,
+ TCGArg c1, TCGArg c2, TCGArg v)
+{
+ switch (cond) {
+ case TCG_COND_EQ:
+ if (c1 == 0) {
+ tcg_out_opc_reg(s, OPC_MOVZ, ret, v, c2);
+ } else if (c2 == 0) {
+ tcg_out_opc_reg(s, OPC_MOVZ, ret, v, c1);
+ } else {
+ tcg_out_opc_reg(s, OPC_XOR, TCG_REG_AT, c1, c2);
+ tcg_out_opc_reg(s, OPC_MOVZ, ret, v, TCG_REG_AT);
+ }
+ break;
+ case TCG_COND_NE:
+ if (c1 == 0) {
+ tcg_out_opc_reg(s, OPC_MOVN, ret, v, c2);
+ } else if (c2 == 0) {
+ tcg_out_opc_reg(s, OPC_MOVN, ret, v, c1);
+ } else {
+ tcg_out_opc_reg(s, OPC_XOR, TCG_REG_AT, c1, c2);
+ tcg_out_opc_reg(s, OPC_MOVN, ret, v, TCG_REG_AT);
+ }
+ break;
+ case TCG_COND_LT:
+ tcg_out_opc_reg(s, OPC_SLT, TCG_REG_AT, c1, c2);
+ tcg_out_opc_reg(s, OPC_MOVN, ret, v, TCG_REG_AT);
+ break;
+ case TCG_COND_LTU:
+ tcg_out_opc_reg(s, OPC_SLTU, TCG_REG_AT, c1, c2);
+ tcg_out_opc_reg(s, OPC_MOVN, ret, v, TCG_REG_AT);
+ break;
+ case TCG_COND_GE:
+ tcg_out_opc_reg(s, OPC_SLT, TCG_REG_AT, c1, c2);
+ tcg_out_opc_reg(s, OPC_MOVZ, ret, v, TCG_REG_AT);
+ break;
+ case TCG_COND_GEU:
+ tcg_out_opc_reg(s, OPC_SLTU, TCG_REG_AT, c1, c2);
+ tcg_out_opc_reg(s, OPC_MOVZ, ret, v, TCG_REG_AT);
+ break;
+ case TCG_COND_LE:
+ tcg_out_opc_reg(s, OPC_SLT, TCG_REG_AT, c2, c1);
+ tcg_out_opc_reg(s, OPC_MOVZ, ret, v, TCG_REG_AT);
+ break;
+ case TCG_COND_LEU:
+ tcg_out_opc_reg(s, OPC_SLTU, TCG_REG_AT, c2, c1);
+ tcg_out_opc_reg(s, OPC_MOVZ, ret, v, TCG_REG_AT);
+ break;
+ case TCG_COND_GT:
+ tcg_out_opc_reg(s, OPC_SLT, TCG_REG_AT, c2, c1);
+ tcg_out_opc_reg(s, OPC_MOVN, ret, v, TCG_REG_AT);
+ break;
+ case TCG_COND_GTU:
+ tcg_out_opc_reg(s, OPC_SLTU, TCG_REG_AT, c2, c1);
+ tcg_out_opc_reg(s, OPC_MOVN, ret, v, TCG_REG_AT);
+ break;
+ default:
+ tcg_abort();
+ break;
+ }
+}
+
static void tcg_out_setcond(TCGContext *s, TCGCond cond, TCGReg ret,
TCGArg arg1, TCGArg arg2)
{
@@ -1468,6 +1532,10 @@ static inline void tcg_out_op(TCGContext *s, TCGOpcode opc,
tcg_out_brcond2(s, args[4], args[0], args[1], args[2], args[3], args[5]);
break;
+ case INDEX_op_movcond_i32:
+ tcg_out_movcond(s, args[5], args[0], args[1], args[2], args[3]);
+ break;
+
case INDEX_op_setcond_i32:
tcg_out_setcond(s, args[3], args[0], args[1], args[2]);
break;
@@ -1559,6 +1627,7 @@ static const TCGTargetOpDef mips_op_defs[] = {
{ INDEX_op_deposit_i32, { "r", "0", "rZ" } },
{ INDEX_op_brcond_i32, { "rZ", "rZ" } },
+ { INDEX_op_movcond_i32, { "r", "rZ", "rZ", "rZ", "0" } },
{ INDEX_op_setcond_i32, { "r", "rZ", "rZ" } },
{ INDEX_op_setcond2_i32, { "r", "rZ", "rZ", "rZ", "rZ" } },
diff --git a/tcg/mips/tcg-target.h b/tcg/mips/tcg-target.h
index 897a737..d147e70 100644
--- a/tcg/mips/tcg-target.h
+++ b/tcg/mips/tcg-target.h
@@ -86,7 +86,15 @@ typedef enum {
#define TCG_TARGET_HAS_orc_i32 0
#define TCG_TARGET_HAS_eqv_i32 0
#define TCG_TARGET_HAS_nand_i32 0
+
+/* optional instructions only implemented on MIPS4, MIPS32 and Loongson 2 */
+#if defined(_MIPS_ARCH_MIPS4) || defined(_MIPS_ARCH_MIPS32) || \
+ defined(_MIPS_ARCH_MIPS32R2) || defined(_MIPS_ARCH_LOONGSON2E) || \
+ defined(_MIPS_ARCH_LOONGSON2F)
+#define TCG_TARGET_HAS_movcond_i32 1
+#else
#define TCG_TARGET_HAS_movcond_i32 0
+#endif
/* optional instructions only implemented on MIPS32R2 */
#ifdef _MIPS_ARCH_MIPS32R2
--
1.7.12.1

View File

@ -0,0 +1,62 @@
From 848750a4acf9ea5c473be596d41720e702d770f0 Mon Sep 17 00:00:00 2001
From: Aurelien Jarno <aurelien@aurel32.net>
Date: Mon, 10 Sep 2012 23:51:42 +0200
Subject: [PATCH] tcg/optimize: remove TCG_TEMP_ANY
TCG_TEMP_ANY has no different meaning than TCG_TEMP_UNDEF, so use
the later instead.
Reviewed-by: Richard Henderson <rth@twiddle.net>
Signed-off-by: Aurelien Jarno <aurelien@aurel32.net>
Signed-off-by: Michael Roth <mdroth@linux.vnet.ibm.com>
---
tcg/optimize.c | 11 +++++------
1 file changed, 5 insertions(+), 6 deletions(-)
diff --git a/tcg/optimize.c b/tcg/optimize.c
index 1be7631..308b7f9 100644
--- a/tcg/optimize.c
+++ b/tcg/optimize.c
@@ -39,8 +39,7 @@ typedef enum {
TCG_TEMP_UNDEF = 0,
TCG_TEMP_CONST,
TCG_TEMP_COPY,
- TCG_TEMP_HAS_COPY,
- TCG_TEMP_ANY
+ TCG_TEMP_HAS_COPY
} tcg_temp_state;
struct tcg_temp_info {
@@ -52,7 +51,7 @@ struct tcg_temp_info {
static struct tcg_temp_info temps[TCG_MAX_TEMPS];
-/* Reset TEMP's state to TCG_TEMP_ANY. If TEMP was a representative of some
+/* Reset TEMP's state to TCG_TEMP_UNDEF. If TEMP was a representative of some
class of equivalent temp's, a new representative should be chosen in this
class. */
static void reset_temp(TCGArg temp, int nb_temps, int nb_globals)
@@ -69,7 +68,7 @@ static void reset_temp(TCGArg temp, int nb_temps, int nb_globals)
}
for (i = temps[temp].next_copy; i != temp; i = temps[i].next_copy) {
if (new_base == (TCGArg)-1) {
- temps[i].state = TCG_TEMP_ANY;
+ temps[i].state = TCG_TEMP_UNDEF;
} else {
temps[i].val = new_base;
}
@@ -81,9 +80,9 @@ static void reset_temp(TCGArg temp, int nb_temps, int nb_globals)
temps[temps[temp].prev_copy].next_copy = temps[temp].next_copy;
new_base = temps[temp].val;
}
- temps[temp].state = TCG_TEMP_ANY;
+ temps[temp].state = TCG_TEMP_UNDEF;
if (new_base != (TCGArg)-1 && temps[new_base].next_copy == new_base) {
- temps[new_base].state = TCG_TEMP_ANY;
+ temps[new_base].state = TCG_TEMP_UNDEF;
}
}
--
1.7.12.1

View File

@ -0,0 +1,78 @@
From 71f0bcf065ddd00d5659e846ddfdffb9a06ee896 Mon Sep 17 00:00:00 2001
From: Aurelien Jarno <aurelien@aurel32.net>
Date: Tue, 11 Sep 2012 12:26:23 +0200
Subject: [PATCH] tcg/optimize: check types in copy propagation
The copy propagation doesn't check the types of the temps during copy
propagation. However TCG is using the mov_i32 for the i64 to i32
conversion and thus the two are not equivalent.
With this patch tcg_opt_gen_mov() doesn't consider two temps of
different type as copies anymore.
So far it seems the optimization was not aggressive enough to trigger
this bug, but it will be triggered later in this series once the copy
propagation is improved.
Reviewed-by: Richard Henderson <rth@twiddle.net>
Signed-off-by: Aurelien Jarno <aurelien@aurel32.net>
Signed-off-by: Michael Roth <mdroth@linux.vnet.ibm.com>
---
tcg/optimize.c | 18 ++++++++----------
1 file changed, 8 insertions(+), 10 deletions(-)
diff --git a/tcg/optimize.c b/tcg/optimize.c
index 308b7f9..da8dffe 100644
--- a/tcg/optimize.c
+++ b/tcg/optimize.c
@@ -106,12 +106,13 @@ static TCGOpcode op_to_movi(TCGOpcode op)
}
}
-static void tcg_opt_gen_mov(TCGArg *gen_args, TCGArg dst, TCGArg src,
- int nb_temps, int nb_globals)
+static void tcg_opt_gen_mov(TCGContext *s, TCGArg *gen_args,
+ TCGArg dst, TCGArg src)
{
- reset_temp(dst, nb_temps, nb_globals);
+ reset_temp(dst, s->nb_temps, s->nb_globals);
assert(temps[src].state != TCG_TEMP_COPY);
- if (src >= nb_globals) {
+ /* Only consider temps with the same type (width) as copies. */
+ if (src >= s->nb_globals && s->temps[dst].type == s->temps[src].type) {
assert(temps[src].state != TCG_TEMP_CONST);
if (temps[src].state != TCG_TEMP_HAS_COPY) {
temps[src].state = TCG_TEMP_HAS_COPY;
@@ -461,8 +462,7 @@ static TCGArg *tcg_constant_folding(TCGContext *s, uint16_t *tcg_opc_ptr,
gen_opc_buf[op_index] = INDEX_op_nop;
} else {
gen_opc_buf[op_index] = op_to_mov(op);
- tcg_opt_gen_mov(gen_args, args[0], args[1],
- nb_temps, nb_globals);
+ tcg_opt_gen_mov(s, gen_args, args[0], args[1]);
gen_args += 2;
}
args += 3;
@@ -499,8 +499,7 @@ static TCGArg *tcg_constant_folding(TCGContext *s, uint16_t *tcg_opc_ptr,
gen_opc_buf[op_index] = INDEX_op_nop;
} else {
gen_opc_buf[op_index] = op_to_mov(op);
- tcg_opt_gen_mov(gen_args, args[0], args[1], nb_temps,
- nb_globals);
+ tcg_opt_gen_mov(s, gen_args, args[0], args[1]);
gen_args += 2;
}
args += 3;
@@ -524,8 +523,7 @@ static TCGArg *tcg_constant_folding(TCGContext *s, uint16_t *tcg_opc_ptr,
break;
}
if (temps[args[1]].state != TCG_TEMP_CONST) {
- tcg_opt_gen_mov(gen_args, args[0], args[1],
- nb_temps, nb_globals);
+ tcg_opt_gen_mov(s, gen_args, args[0], args[1]);
gen_args += 2;
args += 2;
break;
--
1.7.12.1

View File

@ -0,0 +1,377 @@
From bf408071104de13f79a0c3c8cac892f440462e7c Mon Sep 17 00:00:00 2001
From: Aurelien Jarno <aurelien@aurel32.net>
Date: Tue, 11 Sep 2012 12:31:21 +0200
Subject: [PATCH] tcg/optimize: rework copy progagation
The copy propagation pass tries to keep track what is a copy of what
and what has copy of what, and in addition it keep a circular list of
of all the copies. Unfortunately this doesn't fully work: a mov from
a temp which has a state "COPY" changed it into a state "HAS_COPY".
Later when this temp is used again, it is considered has not having
copy and thus no propagation is done.
This patch fixes that by removing the hiearchy between copies, and thus
only keeping a "COPY" state both meaning "is a copy" and "has a copy".
The decision of which copy to use is deferred to the actual temp
replacement. At this stage there is not one best choice to do, but only
better choices than others. For doing the best choice the operation
would have to be parsed in reversed to know if a temp is going to be
used later or not. That what is done by the liveness analysis. At this
stage it is known that globals will be always live, that local temps
will be dead at the end of the translation block, and that the temps
will be dead at the end of the basic block. This means that this stage
should try to replace temps by local temps or globals and local temps
by globals.
Reviewed-by: Richard Henderson <rth@twiddle.net>
Signed-off-by: Aurelien Jarno <aurelien@aurel32.net>
Signed-off-by: Michael Roth <mdroth@linux.vnet.ibm.com>
---
tcg/optimize.c | 167 +++++++++++++++++++++++++++++++--------------------------
1 file changed, 92 insertions(+), 75 deletions(-)
diff --git a/tcg/optimize.c b/tcg/optimize.c
index da8dffe..1904b39 100644
--- a/tcg/optimize.c
+++ b/tcg/optimize.c
@@ -39,7 +39,6 @@ typedef enum {
TCG_TEMP_UNDEF = 0,
TCG_TEMP_CONST,
TCG_TEMP_COPY,
- TCG_TEMP_HAS_COPY
} tcg_temp_state;
struct tcg_temp_info {
@@ -51,39 +50,19 @@ struct tcg_temp_info {
static struct tcg_temp_info temps[TCG_MAX_TEMPS];
-/* Reset TEMP's state to TCG_TEMP_UNDEF. If TEMP was a representative of some
- class of equivalent temp's, a new representative should be chosen in this
- class. */
-static void reset_temp(TCGArg temp, int nb_temps, int nb_globals)
+/* Reset TEMP's state to TCG_TEMP_UNDEF. If TEMP only had one copy, remove
+ the copy flag from the left temp. */
+static void reset_temp(TCGArg temp)
{
- int i;
- TCGArg new_base = (TCGArg)-1;
- if (temps[temp].state == TCG_TEMP_HAS_COPY) {
- for (i = temps[temp].next_copy; i != temp; i = temps[i].next_copy) {
- if (i >= nb_globals) {
- temps[i].state = TCG_TEMP_HAS_COPY;
- new_base = i;
- break;
- }
- }
- for (i = temps[temp].next_copy; i != temp; i = temps[i].next_copy) {
- if (new_base == (TCGArg)-1) {
- temps[i].state = TCG_TEMP_UNDEF;
- } else {
- temps[i].val = new_base;
- }
+ if (temps[temp].state == TCG_TEMP_COPY) {
+ if (temps[temp].prev_copy == temps[temp].next_copy) {
+ temps[temps[temp].next_copy].state = TCG_TEMP_UNDEF;
+ } else {
+ temps[temps[temp].next_copy].prev_copy = temps[temp].prev_copy;
+ temps[temps[temp].prev_copy].next_copy = temps[temp].next_copy;
}
- temps[temps[temp].next_copy].prev_copy = temps[temp].prev_copy;
- temps[temps[temp].prev_copy].next_copy = temps[temp].next_copy;
- } else if (temps[temp].state == TCG_TEMP_COPY) {
- temps[temps[temp].next_copy].prev_copy = temps[temp].prev_copy;
- temps[temps[temp].prev_copy].next_copy = temps[temp].next_copy;
- new_base = temps[temp].val;
}
temps[temp].state = TCG_TEMP_UNDEF;
- if (new_base != (TCGArg)-1 && temps[new_base].next_copy == new_base) {
- temps[new_base].state = TCG_TEMP_UNDEF;
- }
}
static int op_bits(TCGOpcode op)
@@ -106,34 +85,83 @@ static TCGOpcode op_to_movi(TCGOpcode op)
}
}
+static TCGArg find_better_copy(TCGContext *s, TCGArg temp)
+{
+ TCGArg i;
+
+ /* If this is already a global, we can't do better. */
+ if (temp < s->nb_globals) {
+ return temp;
+ }
+
+ /* Search for a global first. */
+ for (i = temps[temp].next_copy ; i != temp ; i = temps[i].next_copy) {
+ if (i < s->nb_globals) {
+ return i;
+ }
+ }
+
+ /* If it is a temp, search for a temp local. */
+ if (!s->temps[temp].temp_local) {
+ for (i = temps[temp].next_copy ; i != temp ; i = temps[i].next_copy) {
+ if (s->temps[i].temp_local) {
+ return i;
+ }
+ }
+ }
+
+ /* Failure to find a better representation, return the same temp. */
+ return temp;
+}
+
+static bool temps_are_copies(TCGArg arg1, TCGArg arg2)
+{
+ TCGArg i;
+
+ if (arg1 == arg2) {
+ return true;
+ }
+
+ if (temps[arg1].state != TCG_TEMP_COPY
+ || temps[arg2].state != TCG_TEMP_COPY) {
+ return false;
+ }
+
+ for (i = temps[arg1].next_copy ; i != arg1 ; i = temps[i].next_copy) {
+ if (i == arg2) {
+ return true;
+ }
+ }
+
+ return false;
+}
+
static void tcg_opt_gen_mov(TCGContext *s, TCGArg *gen_args,
TCGArg dst, TCGArg src)
{
- reset_temp(dst, s->nb_temps, s->nb_globals);
- assert(temps[src].state != TCG_TEMP_COPY);
- /* Only consider temps with the same type (width) as copies. */
- if (src >= s->nb_globals && s->temps[dst].type == s->temps[src].type) {
- assert(temps[src].state != TCG_TEMP_CONST);
- if (temps[src].state != TCG_TEMP_HAS_COPY) {
- temps[src].state = TCG_TEMP_HAS_COPY;
+ reset_temp(dst);
+ assert(temps[src].state != TCG_TEMP_CONST);
+
+ if (s->temps[src].type == s->temps[dst].type) {
+ if (temps[src].state != TCG_TEMP_COPY) {
+ temps[src].state = TCG_TEMP_COPY;
temps[src].next_copy = src;
temps[src].prev_copy = src;
}
temps[dst].state = TCG_TEMP_COPY;
- temps[dst].val = src;
temps[dst].next_copy = temps[src].next_copy;
temps[dst].prev_copy = src;
temps[temps[dst].next_copy].prev_copy = dst;
temps[src].next_copy = dst;
}
+
gen_args[0] = dst;
gen_args[1] = src;
}
-static void tcg_opt_gen_movi(TCGArg *gen_args, TCGArg dst, TCGArg val,
- int nb_temps, int nb_globals)
+static void tcg_opt_gen_movi(TCGArg *gen_args, TCGArg dst, TCGArg val)
{
- reset_temp(dst, nb_temps, nb_globals);
+ reset_temp(dst);
temps[dst].state = TCG_TEMP_CONST;
temps[dst].val = val;
gen_args[0] = dst;
@@ -324,7 +352,6 @@ static TCGArg do_constant_folding_cond(TCGOpcode op, TCGArg x,
tcg_abort();
}
-
/* Propagate constants and copies, fold constant expressions. */
static TCGArg *tcg_constant_folding(TCGContext *s, uint16_t *tcg_opc_ptr,
TCGArg *args, TCGOpDef *tcg_op_defs)
@@ -338,10 +365,8 @@ static TCGArg *tcg_constant_folding(TCGContext *s, uint16_t *tcg_opc_ptr,
/* Array VALS has an element for each temp.
If this temp holds a constant then its value is kept in VALS' element.
- If this temp is a copy of other ones then this equivalence class'
- representative is kept in VALS' element.
- If this temp is neither copy nor constant then corresponding VALS'
- element is unused. */
+ If this temp is a copy of other ones then the other copies are
+ available through the doubly linked circular list. */
nb_temps = s->nb_temps;
nb_globals = s->nb_globals;
@@ -357,7 +382,7 @@ static TCGArg *tcg_constant_folding(TCGContext *s, uint16_t *tcg_opc_ptr,
assert(op != INDEX_op_call);
for (i = def->nb_oargs; i < def->nb_oargs + def->nb_iargs; i++) {
if (temps[args[i]].state == TCG_TEMP_COPY) {
- args[i] = temps[args[i]].val;
+ args[i] = find_better_copy(s, args[i]);
}
}
}
@@ -429,7 +454,7 @@ static TCGArg *tcg_constant_folding(TCGContext *s, uint16_t *tcg_opc_ptr,
if (temps[args[1]].state == TCG_TEMP_CONST
&& temps[args[1]].val == 0) {
gen_opc_buf[op_index] = op_to_movi(op);
- tcg_opt_gen_movi(gen_args, args[0], 0, nb_temps, nb_globals);
+ tcg_opt_gen_movi(gen_args, args[0], 0);
args += 3;
gen_args += 2;
continue;
@@ -456,9 +481,7 @@ static TCGArg *tcg_constant_folding(TCGContext *s, uint16_t *tcg_opc_ptr,
}
if (temps[args[2]].state == TCG_TEMP_CONST
&& temps[args[2]].val == 0) {
- if ((temps[args[0]].state == TCG_TEMP_COPY
- && temps[args[0]].val == args[1])
- || args[0] == args[1]) {
+ if (temps_are_copies(args[0], args[1])) {
gen_opc_buf[op_index] = INDEX_op_nop;
} else {
gen_opc_buf[op_index] = op_to_mov(op);
@@ -480,7 +503,7 @@ static TCGArg *tcg_constant_folding(TCGContext *s, uint16_t *tcg_opc_ptr,
if ((temps[args[2]].state == TCG_TEMP_CONST
&& temps[args[2]].val == 0)) {
gen_opc_buf[op_index] = op_to_movi(op);
- tcg_opt_gen_movi(gen_args, args[0], 0, nb_temps, nb_globals);
+ tcg_opt_gen_movi(gen_args, args[0], 0);
args += 3;
gen_args += 2;
continue;
@@ -495,7 +518,7 @@ static TCGArg *tcg_constant_folding(TCGContext *s, uint16_t *tcg_opc_ptr,
CASE_OP_32_64(or):
CASE_OP_32_64(and):
if (args[1] == args[2]) {
- if (args[1] == args[0]) {
+ if (temps_are_copies(args[0], args[1])) {
gen_opc_buf[op_index] = INDEX_op_nop;
} else {
gen_opc_buf[op_index] = op_to_mov(op);
@@ -515,9 +538,7 @@ static TCGArg *tcg_constant_folding(TCGContext *s, uint16_t *tcg_opc_ptr,
allocator where needed and possible. Also detect copies. */
switch (op) {
CASE_OP_32_64(mov):
- if ((temps[args[1]].state == TCG_TEMP_COPY
- && temps[args[1]].val == args[0])
- || args[0] == args[1]) {
+ if (temps_are_copies(args[0], args[1])) {
args += 2;
gen_opc_buf[op_index] = INDEX_op_nop;
break;
@@ -535,7 +556,7 @@ static TCGArg *tcg_constant_folding(TCGContext *s, uint16_t *tcg_opc_ptr,
args[1] = temps[args[1]].val;
/* fallthrough */
CASE_OP_32_64(movi):
- tcg_opt_gen_movi(gen_args, args[0], args[1], nb_temps, nb_globals);
+ tcg_opt_gen_movi(gen_args, args[0], args[1]);
gen_args += 2;
args += 2;
break;
@@ -550,9 +571,9 @@ static TCGArg *tcg_constant_folding(TCGContext *s, uint16_t *tcg_opc_ptr,
if (temps[args[1]].state == TCG_TEMP_CONST) {
gen_opc_buf[op_index] = op_to_movi(op);
tmp = do_constant_folding(op, temps[args[1]].val, 0);
- tcg_opt_gen_movi(gen_args, args[0], tmp, nb_temps, nb_globals);
+ tcg_opt_gen_movi(gen_args, args[0], tmp);
} else {
- reset_temp(args[0], nb_temps, nb_globals);
+ reset_temp(args[0]);
gen_args[0] = args[0];
gen_args[1] = args[1];
}
@@ -580,10 +601,10 @@ static TCGArg *tcg_constant_folding(TCGContext *s, uint16_t *tcg_opc_ptr,
gen_opc_buf[op_index] = op_to_movi(op);
tmp = do_constant_folding(op, temps[args[1]].val,
temps[args[2]].val);
- tcg_opt_gen_movi(gen_args, args[0], tmp, nb_temps, nb_globals);
+ tcg_opt_gen_movi(gen_args, args[0], tmp);
gen_args += 2;
} else {
- reset_temp(args[0], nb_temps, nb_globals);
+ reset_temp(args[0]);
gen_args[0] = args[0];
gen_args[1] = args[1];
gen_args[2] = args[2];
@@ -597,10 +618,10 @@ static TCGArg *tcg_constant_folding(TCGContext *s, uint16_t *tcg_opc_ptr,
gen_opc_buf[op_index] = op_to_movi(op);
tmp = do_constant_folding_cond(op, temps[args[1]].val,
temps[args[2]].val, args[3]);
- tcg_opt_gen_movi(gen_args, args[0], tmp, nb_temps, nb_globals);
+ tcg_opt_gen_movi(gen_args, args[0], tmp);
gen_args += 2;
} else {
- reset_temp(args[0], nb_temps, nb_globals);
+ reset_temp(args[0]);
gen_args[0] = args[0];
gen_args[1] = args[1];
gen_args[2] = args[2];
@@ -623,7 +644,7 @@ static TCGArg *tcg_constant_folding(TCGContext *s, uint16_t *tcg_opc_ptr,
}
} else {
memset(temps, 0, nb_temps * sizeof(struct tcg_temp_info));
- reset_temp(args[0], nb_temps, nb_globals);
+ reset_temp(args[0]);
gen_args[0] = args[0];
gen_args[1] = args[1];
gen_args[2] = args[2];
@@ -637,23 +658,19 @@ static TCGArg *tcg_constant_folding(TCGContext *s, uint16_t *tcg_opc_ptr,
&& temps[args[2]].state == TCG_TEMP_CONST) {
tmp = do_constant_folding_cond(op, temps[args[1]].val,
temps[args[2]].val, args[5]);
- if (args[0] == args[4-tmp]
- || (temps[args[4-tmp]].state == TCG_TEMP_COPY
- && temps[args[4-tmp]].val == args[0])) {
+ if (temps_are_copies(args[0], args[4-tmp])) {
gen_opc_buf[op_index] = INDEX_op_nop;
} else if (temps[args[4-tmp]].state == TCG_TEMP_CONST) {
gen_opc_buf[op_index] = op_to_movi(op);
- tcg_opt_gen_movi(gen_args, args[0], temps[args[4-tmp]].val,
- nb_temps, nb_globals);
+ tcg_opt_gen_movi(gen_args, args[0], temps[args[4-tmp]].val);
gen_args += 2;
} else {
gen_opc_buf[op_index] = op_to_mov(op);
- tcg_opt_gen_mov(gen_args, args[0], args[4-tmp],
- nb_temps, nb_globals);
+ tcg_opt_gen_mov(s, gen_args, args[0], args[4-tmp]);
gen_args += 2;
}
} else {
- reset_temp(args[0], nb_temps, nb_globals);
+ reset_temp(args[0]);
gen_args[0] = args[0];
gen_args[1] = args[1];
gen_args[2] = args[2];
@@ -668,11 +685,11 @@ static TCGArg *tcg_constant_folding(TCGContext *s, uint16_t *tcg_opc_ptr,
nb_call_args = (args[0] >> 16) + (args[0] & 0xffff);
if (!(args[nb_call_args + 1] & (TCG_CALL_CONST | TCG_CALL_PURE))) {
for (i = 0; i < nb_globals; i++) {
- reset_temp(i, nb_temps, nb_globals);
+ reset_temp(i);
}
}
for (i = 0; i < (args[0] >> 16); i++) {
- reset_temp(args[i + 1], nb_temps, nb_globals);
+ reset_temp(args[i + 1]);
}
i = nb_call_args + 3;
while (i) {
@@ -691,7 +708,7 @@ static TCGArg *tcg_constant_folding(TCGContext *s, uint16_t *tcg_opc_ptr,
memset(temps, 0, nb_temps * sizeof(struct tcg_temp_info));
} else {
for (i = 0; i < def->nb_oargs; i++) {
- reset_temp(args[i], nb_temps, nb_globals);
+ reset_temp(args[i]);
}
}
for (i = 0; i < def->nb_args; i++) {
--
1.7.12.1

View File

@ -0,0 +1,42 @@
From 7c1a67bb734f364ea0643b549e030f04d4eed798 Mon Sep 17 00:00:00 2001
From: Aurelien Jarno <aurelien@aurel32.net>
Date: Tue, 11 Sep 2012 16:18:49 +0200
Subject: [PATCH] tcg/optimize: do copy propagation for all operations
It is possible to due copy propagation for all operations, even the one
that have side effects or clobber arguments (it only concerns input
arguments). That said, the call operation should be handled differently
due to the variable number of arguments.
Reviewed-by: Richard Henderson <rth@twiddle.net>
Signed-off-by: Aurelien Jarno <aurelien@aurel32.net>
Signed-off-by: Michael Roth <mdroth@linux.vnet.ibm.com>
---
tcg/optimize.c | 11 +++++++++--
1 file changed, 9 insertions(+), 2 deletions(-)
diff --git a/tcg/optimize.c b/tcg/optimize.c
index 1904b39..aeb2225 100644
--- a/tcg/optimize.c
+++ b/tcg/optimize.c
@@ -378,8 +378,15 @@ static TCGArg *tcg_constant_folding(TCGContext *s, uint16_t *tcg_opc_ptr,
op = gen_opc_buf[op_index];
def = &tcg_op_defs[op];
/* Do copy propagation */
- if (!(def->flags & (TCG_OPF_CALL_CLOBBER | TCG_OPF_SIDE_EFFECTS))) {
- assert(op != INDEX_op_call);
+ if (op == INDEX_op_call) {
+ int nb_oargs = args[0] >> 16;
+ int nb_iargs = args[0] & 0xffff;
+ for (i = nb_oargs + 1; i < nb_oargs + nb_iargs + 1; i++) {
+ if (temps[args[i]].state == TCG_TEMP_COPY) {
+ args[i] = find_better_copy(s, args[i]);
+ }
+ }
+ } else {
for (i = def->nb_oargs; i < def->nb_oargs + def->nb_iargs; i++) {
if (temps[args[i]].state == TCG_TEMP_COPY) {
args[i] = find_better_copy(s, args[i]);
--
1.7.12.1

View File

@ -0,0 +1,31 @@
From e38329760e40a354e37d11c7f5d8c86cdb90736c Mon Sep 17 00:00:00 2001
From: Aurelien Jarno <aurelien@aurel32.net>
Date: Tue, 18 Sep 2012 19:11:32 +0200
Subject: [PATCH] tcg/optimize: optimize "op r, a, a => mov r, a"
Now that we can easily detect all copies, we can optimize the
"op r, a, a => mov r, a" case a bit more.
Reviewed-by: Richard Henderson <rth@twiddle.net>
Signed-off-by: Aurelien Jarno <aurelien@aurel32.net>
Signed-off-by: Michael Roth <mdroth@linux.vnet.ibm.com>
---
tcg/optimize.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/tcg/optimize.c b/tcg/optimize.c
index aeb2225..b9a7da9 100644
--- a/tcg/optimize.c
+++ b/tcg/optimize.c
@@ -524,7 +524,7 @@ static TCGArg *tcg_constant_folding(TCGContext *s, uint16_t *tcg_opc_ptr,
switch (op) {
CASE_OP_32_64(or):
CASE_OP_32_64(and):
- if (args[1] == args[2]) {
+ if (temps_are_copies(args[1], args[2])) {
if (temps_are_copies(args[0], args[1])) {
gen_opc_buf[op_index] = INDEX_op_nop;
} else {
--
1.7.12.1

View File

@ -0,0 +1,46 @@
From 363479b4d4f729959eafb1209d48ad75e928c00a Mon Sep 17 00:00:00 2001
From: Aurelien Jarno <aurelien@aurel32.net>
Date: Tue, 18 Sep 2012 19:12:36 +0200
Subject: [PATCH] tcg/optimize: optimize "op r, a, a => movi r, 0"
Now that it's possible to detect copies, we can optimize the case
the "op r, a, a => movi r, 0". This helps in the computation of
overflow flags when one of the two args is 0.
Reviewed-by: Richard Henderson <rth@twiddle.net>
Signed-off-by: Aurelien Jarno <aurelien@aurel32.net>
Signed-off-by: Michael Roth <mdroth@linux.vnet.ibm.com>
---
tcg/optimize.c | 16 ++++++++++++++++
1 file changed, 16 insertions(+)
diff --git a/tcg/optimize.c b/tcg/optimize.c
index b9a7da9..ceea644 100644
--- a/tcg/optimize.c
+++ b/tcg/optimize.c
@@ -540,6 +540,22 @@ static TCGArg *tcg_constant_folding(TCGContext *s, uint16_t *tcg_opc_ptr,
break;
}
+ /* Simplify expression for "op r, a, a => movi r, 0" cases */
+ switch (op) {
+ CASE_OP_32_64(sub):
+ CASE_OP_32_64(xor):
+ if (temps_are_copies(args[1], args[2])) {
+ gen_opc_buf[op_index] = op_to_movi(op);
+ tcg_opt_gen_movi(gen_args, args[0], 0);
+ gen_args += 2;
+ args += 3;
+ continue;
+ }
+ break;
+ default:
+ break;
+ }
+
/* Propagate constants through copy operations and do constant
folding. Constants will be substituted to arguments by register
allocator where needed and possible. Also detect copies. */
--
1.7.12.1

View File

@ -0,0 +1,192 @@
From 8d5f3ca9ccace2374fd73d46fad56decc02e0a44 Mon Sep 17 00:00:00 2001
From: Aurelien Jarno <aurelien@aurel32.net>
Date: Tue, 18 Sep 2012 19:37:00 +0200
Subject: [PATCH] tcg/optimize: further optimize brcond/movcond/setcond
When both argument of brcond/movcond/setcond are the same or when one
of the two values is a constant equal to zero, it's possible to do
further optimizations.
Reviewed-by: Richard Henderson <rth@twiddle.net>
Signed-off-by: Aurelien Jarno <aurelien@aurel32.net>
Signed-off-by: Michael Roth <mdroth@linux.vnet.ibm.com>
---
tcg/optimize.c | 127 ++++++++++++++++++++++++++++++++++-----------------------
1 file changed, 76 insertions(+), 51 deletions(-)
diff --git a/tcg/optimize.c b/tcg/optimize.c
index ceea644..abe016a 100644
--- a/tcg/optimize.c
+++ b/tcg/optimize.c
@@ -292,58 +292,88 @@ static TCGArg do_constant_folding(TCGOpcode op, TCGArg x, TCGArg y)
return res;
}
+/* Return 2 if the condition can't be simplified, and the result
+ of the condition (0 or 1) if it can */
static TCGArg do_constant_folding_cond(TCGOpcode op, TCGArg x,
TCGArg y, TCGCond c)
{
- switch (op_bits(op)) {
- case 32:
+ if (temps[x].state == TCG_TEMP_CONST && temps[y].state == TCG_TEMP_CONST) {
+ switch (op_bits(op)) {
+ case 32:
+ switch (c) {
+ case TCG_COND_EQ:
+ return (uint32_t)temps[x].val == (uint32_t)temps[y].val;
+ case TCG_COND_NE:
+ return (uint32_t)temps[x].val != (uint32_t)temps[y].val;
+ case TCG_COND_LT:
+ return (int32_t)temps[x].val < (int32_t)temps[y].val;
+ case TCG_COND_GE:
+ return (int32_t)temps[x].val >= (int32_t)temps[y].val;
+ case TCG_COND_LE:
+ return (int32_t)temps[x].val <= (int32_t)temps[y].val;
+ case TCG_COND_GT:
+ return (int32_t)temps[x].val > (int32_t)temps[y].val;
+ case TCG_COND_LTU:
+ return (uint32_t)temps[x].val < (uint32_t)temps[y].val;
+ case TCG_COND_GEU:
+ return (uint32_t)temps[x].val >= (uint32_t)temps[y].val;
+ case TCG_COND_LEU:
+ return (uint32_t)temps[x].val <= (uint32_t)temps[y].val;
+ case TCG_COND_GTU:
+ return (uint32_t)temps[x].val > (uint32_t)temps[y].val;
+ }
+ break;
+ case 64:
+ switch (c) {
+ case TCG_COND_EQ:
+ return (uint64_t)temps[x].val == (uint64_t)temps[y].val;
+ case TCG_COND_NE:
+ return (uint64_t)temps[x].val != (uint64_t)temps[y].val;
+ case TCG_COND_LT:
+ return (int64_t)temps[x].val < (int64_t)temps[y].val;
+ case TCG_COND_GE:
+ return (int64_t)temps[x].val >= (int64_t)temps[y].val;
+ case TCG_COND_LE:
+ return (int64_t)temps[x].val <= (int64_t)temps[y].val;
+ case TCG_COND_GT:
+ return (int64_t)temps[x].val > (int64_t)temps[y].val;
+ case TCG_COND_LTU:
+ return (uint64_t)temps[x].val < (uint64_t)temps[y].val;
+ case TCG_COND_GEU:
+ return (uint64_t)temps[x].val >= (uint64_t)temps[y].val;
+ case TCG_COND_LEU:
+ return (uint64_t)temps[x].val <= (uint64_t)temps[y].val;
+ case TCG_COND_GTU:
+ return (uint64_t)temps[x].val > (uint64_t)temps[y].val;
+ }
+ break;
+ }
+ } else if (temps_are_copies(x, y)) {
switch (c) {
- case TCG_COND_EQ:
- return (uint32_t)x == (uint32_t)y;
- case TCG_COND_NE:
- return (uint32_t)x != (uint32_t)y;
- case TCG_COND_LT:
- return (int32_t)x < (int32_t)y;
- case TCG_COND_GE:
- return (int32_t)x >= (int32_t)y;
- case TCG_COND_LE:
- return (int32_t)x <= (int32_t)y;
case TCG_COND_GT:
- return (int32_t)x > (int32_t)y;
case TCG_COND_LTU:
- return (uint32_t)x < (uint32_t)y;
- case TCG_COND_GEU:
- return (uint32_t)x >= (uint32_t)y;
- case TCG_COND_LEU:
- return (uint32_t)x <= (uint32_t)y;
+ case TCG_COND_LT:
case TCG_COND_GTU:
- return (uint32_t)x > (uint32_t)y;
- }
- break;
- case 64:
- switch (c) {
- case TCG_COND_EQ:
- return (uint64_t)x == (uint64_t)y;
case TCG_COND_NE:
- return (uint64_t)x != (uint64_t)y;
- case TCG_COND_LT:
- return (int64_t)x < (int64_t)y;
+ return 0;
case TCG_COND_GE:
- return (int64_t)x >= (int64_t)y;
+ case TCG_COND_GEU:
case TCG_COND_LE:
- return (int64_t)x <= (int64_t)y;
- case TCG_COND_GT:
- return (int64_t)x > (int64_t)y;
+ case TCG_COND_LEU:
+ case TCG_COND_EQ:
+ return 1;
+ }
+ } else if (temps[y].state == TCG_TEMP_CONST && temps[y].val == 0) {
+ switch (c) {
case TCG_COND_LTU:
- return (uint64_t)x < (uint64_t)y;
+ return 0;
case TCG_COND_GEU:
- return (uint64_t)x >= (uint64_t)y;
- case TCG_COND_LEU:
- return (uint64_t)x <= (uint64_t)y;
- case TCG_COND_GTU:
- return (uint64_t)x > (uint64_t)y;
+ return 1;
+ default:
+ return 2;
}
- break;
+ } else {
+ return 2;
}
fprintf(stderr,
@@ -636,11 +666,9 @@ static TCGArg *tcg_constant_folding(TCGContext *s, uint16_t *tcg_opc_ptr,
args += 3;
break;
CASE_OP_32_64(setcond):
- if (temps[args[1]].state == TCG_TEMP_CONST
- && temps[args[2]].state == TCG_TEMP_CONST) {
+ tmp = do_constant_folding_cond(op, args[1], args[2], args[3]);
+ if (tmp != 2) {
gen_opc_buf[op_index] = op_to_movi(op);
- tmp = do_constant_folding_cond(op, temps[args[1]].val,
- temps[args[2]].val, args[3]);
tcg_opt_gen_movi(gen_args, args[0], tmp);
gen_args += 2;
} else {
@@ -654,10 +682,9 @@ static TCGArg *tcg_constant_folding(TCGContext *s, uint16_t *tcg_opc_ptr,
args += 4;
break;
CASE_OP_32_64(brcond):
- if (temps[args[0]].state == TCG_TEMP_CONST
- && temps[args[1]].state == TCG_TEMP_CONST) {
- if (do_constant_folding_cond(op, temps[args[0]].val,
- temps[args[1]].val, args[2])) {
+ tmp = do_constant_folding_cond(op, args[0], args[1], args[2]);
+ if (tmp != 2) {
+ if (tmp) {
memset(temps, 0, nb_temps * sizeof(struct tcg_temp_info));
gen_opc_buf[op_index] = INDEX_op_br;
gen_args[0] = args[3];
@@ -677,10 +704,8 @@ static TCGArg *tcg_constant_folding(TCGContext *s, uint16_t *tcg_opc_ptr,
args += 4;
break;
CASE_OP_32_64(movcond):
- if (temps[args[1]].state == TCG_TEMP_CONST
- && temps[args[2]].state == TCG_TEMP_CONST) {
- tmp = do_constant_folding_cond(op, temps[args[1]].val,
- temps[args[2]].val, args[5]);
+ tmp = do_constant_folding_cond(op, args[1], args[2], args[5]);
+ if (tmp != 2) {
if (temps_are_copies(args[0], args[4-tmp])) {
gen_opc_buf[op_index] = INDEX_op_nop;
} else if (temps[args[4-tmp]].state == TCG_TEMP_CONST) {
--
1.7.12.1

View File

@ -0,0 +1,38 @@
From a0b71ad6a3f8aeb8b5ea6d112a7afeadc7c004a4 Mon Sep 17 00:00:00 2001
From: Aurelien Jarno <aurelien@aurel32.net>
Date: Wed, 19 Sep 2012 22:00:22 +0200
Subject: [PATCH] tcg/optimize: prefer the "op a, a, b" form for commutative
ops
The "op a, a, b" form is better handled on non-RISC host than the "op
a, b, a" form, so swap the arguments to this form when possible, and
when b is not a constant.
This reduces the number of generated instructions by a tiny bit.
Reviewed-by: Richard Henderson <rth@twiddle.net>
Signed-off-by: Aurelien Jarno <aurelien@aurel32.net>
Signed-off-by: Michael Roth <mdroth@linux.vnet.ibm.com>
---
tcg/optimize.c | 5 ++++-
1 file changed, 4 insertions(+), 1 deletion(-)
diff --git a/tcg/optimize.c b/tcg/optimize.c
index abe016a..c8ae50b 100644
--- a/tcg/optimize.c
+++ b/tcg/optimize.c
@@ -434,7 +434,10 @@ static TCGArg *tcg_constant_folding(TCGContext *s, uint16_t *tcg_opc_ptr,
CASE_OP_32_64(eqv):
CASE_OP_32_64(nand):
CASE_OP_32_64(nor):
- if (temps[args[1]].state == TCG_TEMP_CONST) {
+ /* Prefer the constant in second argument, and then the form
+ op a, a, b, which is better handled on non-RISC hosts. */
+ if (temps[args[1]].state == TCG_TEMP_CONST || (args[0] == args[2]
+ && temps[args[2]].state != TCG_TEMP_CONST)) {
tmp = args[1];
args[1] = args[2];
args[2] = tmp;
--
1.7.12.1

View File

@ -0,0 +1,68 @@
From 3942910a66f682b98ac53ac2d2fba65b9c75eefd Mon Sep 17 00:00:00 2001
From: Aurelien Jarno <aurelien@aurel32.net>
Date: Fri, 21 Sep 2012 10:02:45 +0200
Subject: [PATCH] tcg: remove #ifdef #endif around TCGOpcode tests
Commit 25c4d9cc changed all TCGOpcode enums to be available, so we don't
need to #ifdef #endif the one that are available only on some targets.
This makes the code easier to read.
Reviewed-by: Richard Henderson <rth@twiddle.net>
Signed-off-by: Aurelien Jarno <aurelien@aurel32.net>
Signed-off-by: Michael Roth <mdroth@linux.vnet.ibm.com>
---
tcg/tcg.c | 13 +------------
1 file changed, 1 insertion(+), 12 deletions(-)
diff --git a/tcg/tcg.c b/tcg/tcg.c
index 24ce830..93421cd 100644
--- a/tcg/tcg.c
+++ b/tcg/tcg.c
@@ -937,11 +937,7 @@ void tcg_dump_ops(TCGContext *s)
args[nb_oargs + i]));
}
}
- } else if (c == INDEX_op_movi_i32
-#if TCG_TARGET_REG_BITS == 64
- || c == INDEX_op_movi_i64
-#endif
- ) {
+ } else if (c == INDEX_op_movi_i32 || c == INDEX_op_movi_i64) {
tcg_target_ulong val;
TCGHelperInfo *th;
@@ -993,14 +989,11 @@ void tcg_dump_ops(TCGContext *s)
case INDEX_op_brcond_i32:
case INDEX_op_setcond_i32:
case INDEX_op_movcond_i32:
-#if TCG_TARGET_REG_BITS == 32
case INDEX_op_brcond2_i32:
case INDEX_op_setcond2_i32:
-#else
case INDEX_op_brcond_i64:
case INDEX_op_setcond_i64:
case INDEX_op_movcond_i64:
-#endif
if (args[k] < ARRAY_SIZE(cond_name) && cond_name[args[k]]) {
qemu_log(",%s", cond_name[args[k++]]);
} else {
@@ -2095,16 +2088,12 @@ static inline int tcg_gen_code_common(TCGContext *s, uint8_t *gen_code_buf,
#endif
switch(opc) {
case INDEX_op_mov_i32:
-#if TCG_TARGET_REG_BITS == 64
case INDEX_op_mov_i64:
-#endif
dead_args = s->op_dead_args[op_index];
tcg_reg_alloc_mov(s, def, args, dead_args);
break;
case INDEX_op_movi_i32:
-#if TCG_TARGET_REG_BITS == 64
case INDEX_op_movi_i64:
-#endif
tcg_reg_alloc_movi(s, args);
break;
case INDEX_op_debug_insn_start:
--
1.7.12.1

View File

@ -0,0 +1,46 @@
From 04edfbcf025b5588e0f3b86c74356a4339745f35 Mon Sep 17 00:00:00 2001
From: Aurelien Jarno <aurelien@aurel32.net>
Date: Fri, 21 Sep 2012 11:07:29 +0200
Subject: [PATCH] tcg/optimize: add constant folding for deposit
Reviewed-by: Richard Henderson <rth@twiddle.net>
Signed-off-by: Aurelien Jarno <aurelien@aurel32.net>
Signed-off-by: Michael Roth <mdroth@linux.vnet.ibm.com>
---
tcg/optimize.c | 20 ++++++++++++++++++++
1 file changed, 20 insertions(+)
diff --git a/tcg/optimize.c b/tcg/optimize.c
index c8ae50b..35532a1 100644
--- a/tcg/optimize.c
+++ b/tcg/optimize.c
@@ -668,6 +668,26 @@ static TCGArg *tcg_constant_folding(TCGContext *s, uint16_t *tcg_opc_ptr,
}
args += 3;
break;
+ CASE_OP_32_64(deposit):
+ if (temps[args[1]].state == TCG_TEMP_CONST
+ && temps[args[2]].state == TCG_TEMP_CONST) {
+ 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]);
+ tcg_opt_gen_movi(gen_args, args[0], tmp);
+ gen_args += 2;
+ } else {
+ reset_temp(args[0]);
+ gen_args[0] = args[0];
+ gen_args[1] = args[1];
+ gen_args[2] = args[2];
+ gen_args[3] = args[3];
+ gen_args[4] = args[4];
+ gen_args += 5;
+ }
+ args += 5;
+ break;
CASE_OP_32_64(setcond):
tmp = do_constant_folding_cond(op, args[1], args[2], args[3]);
if (tmp != 2) {
--
1.7.12.1

View File

@ -0,0 +1,33 @@
From 08de143bdd34e906c3e89443cb6b24665f7c088d Mon Sep 17 00:00:00 2001
From: Max Filippov <jcmvbkbc@gmail.com>
Date: Fri, 21 Sep 2012 04:18:07 +0400
Subject: [PATCH] tcg/README: document tcg_gen_goto_tb restrictions
See
http://lists.nongnu.org/archive/html/qemu-devel/2012-09/msg03196.html
for the whole story.
Signed-off-by: Max Filippov <jcmvbkbc@gmail.com>
Signed-off-by: Aurelien Jarno <aurelien@aurel32.net>
Signed-off-by: Michael Roth <mdroth@linux.vnet.ibm.com>
---
tcg/README | 3 ++-
1 file changed, 2 insertions(+), 1 deletion(-)
diff --git a/tcg/README b/tcg/README
index d03ae05..33783ee 100644
--- a/tcg/README
+++ b/tcg/README
@@ -392,7 +392,8 @@ Exit the current TB and return the value t0 (word type).
Exit the current TB and jump to the TB index 'index' (constant) if the
current TB was linked to this TB. Otherwise execute the next
-instructions.
+instructions. Only indices 0 and 1 are valid and tcg_gen_goto_tb may be issued
+at most once with each slot index per TB.
* qemu_ld8u t0, t1, flags
qemu_ld8s t0, t1, flags
--
1.7.12.1

View File

@ -0,0 +1,57 @@
From e35e8b9bb446ff2693962151b8c80c5c88294959 Mon Sep 17 00:00:00 2001
From: Stefan Weil <sw@weilnetz.de>
Date: Thu, 13 Sep 2012 19:37:43 +0200
Subject: [PATCH] w64: Fix TCG helper functions with 5 arguments
TCG uses 6 registers for function arguments on 64 bit Linux hosts,
but only 4 registers on W64 hosts.
Commit 2999a0b20074a7e4a58f56572bb1436749368f59 increased the number
of arguments for some important helper functions from 4 to 5
which triggered a bug for W64 hosts: QEMU aborts when executing
helper_lcall_real in the guest's BIOS because function
tcg_target_get_call_iarg_regs_count always returned 6.
As W64 has only 4 registers for arguments, the 5th argument must be
passed on the stack using a correct stack offset.
Signed-off-by: Stefan Weil <sw@weilnetz.de>
Signed-off-by: Aurelien Jarno <aurelien@aurel32.net>
Signed-off-by: Michael Roth <mdroth@linux.vnet.ibm.com>
---
tcg/i386/tcg-target.c | 2 +-
tcg/i386/tcg-target.h | 4 ++++
2 files changed, 5 insertions(+), 1 deletion(-)
diff --git a/tcg/i386/tcg-target.c b/tcg/i386/tcg-target.c
index aa1fa9f..85c6b81 100644
--- a/tcg/i386/tcg-target.c
+++ b/tcg/i386/tcg-target.c
@@ -118,7 +118,7 @@ static void patch_reloc(uint8_t *code_ptr, int type,
static inline int tcg_target_get_call_iarg_regs_count(int flags)
{
if (TCG_TARGET_REG_BITS == 64) {
- return 6;
+ return ARRAY_SIZE(tcg_target_call_iarg_regs);
}
return 0;
diff --git a/tcg/i386/tcg-target.h b/tcg/i386/tcg-target.h
index b356d76..ace63ba 100644
--- a/tcg/i386/tcg-target.h
+++ b/tcg/i386/tcg-target.h
@@ -67,7 +67,11 @@ typedef enum {
/* used for function call generation */
#define TCG_REG_CALL_STACK TCG_REG_ESP
#define TCG_TARGET_STACK_ALIGN 16
+#if defined(_WIN64)
+#define TCG_TARGET_CALL_STACK_OFFSET 32
+#else
#define TCG_TARGET_CALL_STACK_OFFSET 0
+#endif
/* optional instructions */
#define TCG_TARGET_HAS_div2_i32 1
--
1.7.12.1

View File

@ -0,0 +1,137 @@
From d65d20819ac52207befffa9a7aa858cc7de9cbaf Mon Sep 17 00:00:00 2001
From: malc <av1474@comtv.ru>
Date: Sat, 22 Sep 2012 19:14:33 +0400
Subject: [PATCH] tcg/ppc32: Implement movcond32
Thanks to Richard Henderson
Signed-off-by: malc <av1474@comtv.ru>
Signed-off-by: Michael Roth <mdroth@linux.vnet.ibm.com>
---
tcg/ppc/tcg-target.c | 75 ++++++++++++++++++++++++++++++++++++++++++++++++++++
tcg/ppc/tcg-target.h | 2 +-
2 files changed, 76 insertions(+), 1 deletion(-)
diff --git a/tcg/ppc/tcg-target.c b/tcg/ppc/tcg-target.c
index 26c4b33..8f8b193 100644
--- a/tcg/ppc/tcg-target.c
+++ b/tcg/ppc/tcg-target.c
@@ -390,6 +390,7 @@ static int tcg_target_const_match(tcg_target_long val,
#define ORC XO31(412)
#define EQV XO31(284)
#define NAND XO31(476)
+#define ISEL XO31( 15)
#define LBZX XO31( 87)
#define LHZX XO31(279)
@@ -1269,6 +1270,72 @@ static void tcg_out_setcond2 (TCGContext *s, const TCGArg *args,
);
}
+static void tcg_out_movcond (TCGContext *s, TCGCond cond,
+ TCGArg dest,
+ TCGArg c1, TCGArg c2,
+ TCGArg v1, TCGArg v2,
+ int const_c2)
+{
+ tcg_out_cmp (s, cond, c1, c2, const_c2, 7);
+
+ if (1) {
+ /* At least here on 7747A bit twiddling hacks are outperformed
+ by jumpy code (the testing was not scientific) */
+ if (dest == v2) {
+ cond = tcg_invert_cond (cond);
+ v2 = v1;
+ }
+ else {
+ if (dest != v1) {
+ tcg_out_mov (s, TCG_TYPE_I32, dest, v1);
+ }
+ }
+ /* Branch forward over one insn */
+ tcg_out32 (s, tcg_to_bc[cond] | 8);
+ tcg_out_mov (s, TCG_TYPE_I32, dest, v2);
+ }
+ else {
+ /* isel version, "if (1)" above should be replaced once a way
+ to figure out availability of isel on the underlying
+ hardware is found */
+ int tab, bc;
+
+ switch (cond) {
+ case TCG_COND_EQ:
+ tab = TAB (dest, v1, v2);
+ bc = CR_EQ;
+ break;
+ case TCG_COND_NE:
+ tab = TAB (dest, v2, v1);
+ bc = CR_EQ;
+ break;
+ case TCG_COND_LTU:
+ case TCG_COND_LT:
+ tab = TAB (dest, v1, v2);
+ bc = CR_LT;
+ break;
+ case TCG_COND_GEU:
+ case TCG_COND_GE:
+ tab = TAB (dest, v2, v1);
+ bc = CR_LT;
+ break;
+ case TCG_COND_LEU:
+ case TCG_COND_LE:
+ tab = TAB (dest, v2, v1);
+ bc = CR_GT;
+ break;
+ case TCG_COND_GTU:
+ case TCG_COND_GT:
+ tab = TAB (dest, v1, v2);
+ bc = CR_GT;
+ break;
+ default:
+ tcg_abort ();
+ }
+ tcg_out32 (s, ISEL | tab | ((bc + 28) << 6));
+ }
+}
+
static void tcg_out_brcond (TCGContext *s, TCGCond cond,
TCGArg arg1, TCGArg arg2, int const_arg2,
int label_index)
@@ -1826,6 +1893,13 @@ static void tcg_out_op(TCGContext *s, TCGOpcode opc, const TCGArg *args,
);
break;
+ case INDEX_op_movcond_i32:
+ tcg_out_movcond (s, args[5], args[0],
+ args[1], args[2],
+ args[3], args[4],
+ const_args[2]);
+ break;
+
default:
tcg_dump_ops (s);
tcg_abort ();
@@ -1922,6 +1996,7 @@ static const TCGTargetOpDef ppc_op_defs[] = {
{ INDEX_op_ext16u_i32, { "r", "r" } },
{ INDEX_op_deposit_i32, { "r", "0", "r" } },
+ { INDEX_op_movcond_i32, { "r", "r", "ri", "r", "r" } },
{ -1 },
};
diff --git a/tcg/ppc/tcg-target.h b/tcg/ppc/tcg-target.h
index 177eea1..3259d89 100644
--- a/tcg/ppc/tcg-target.h
+++ b/tcg/ppc/tcg-target.h
@@ -92,7 +92,7 @@ typedef enum {
#define TCG_TARGET_HAS_nand_i32 1
#define TCG_TARGET_HAS_nor_i32 1
#define TCG_TARGET_HAS_deposit_i32 1
-#define TCG_TARGET_HAS_movcond_i32 0
+#define TCG_TARGET_HAS_movcond_i32 1
#define TCG_AREG0 TCG_REG_R27
--
1.7.12.1

View File

@ -0,0 +1,30 @@
From da65fa6c51ef1c999ffc75a162e95285d4cb915b Mon Sep 17 00:00:00 2001
From: Richard Henderson <rth@twiddle.net>
Date: Sat, 24 Mar 2012 21:30:20 +0100
Subject: [PATCH] tcg-sparc: Hack in qemu_ld/st64 for 32-bit.
Not actually implemented, but at least we avoid the tcg assert at startup.
Signed-off-by: Richard Henderson <rth@twiddle.net>
Signed-off-by: Michael Roth <mdroth@linux.vnet.ibm.com>
---
tcg/sparc/tcg-target.c | 3 +++
1 file changed, 3 insertions(+)
diff --git a/tcg/sparc/tcg-target.c b/tcg/sparc/tcg-target.c
index baed3b4..608fc46 100644
--- a/tcg/sparc/tcg-target.c
+++ b/tcg/sparc/tcg-target.c
@@ -1556,6 +1556,9 @@ static const TCGTargetOpDef sparc_op_defs[] = {
{ INDEX_op_brcond_i64, { "r", "rJ" } },
{ INDEX_op_setcond_i64, { "r", "r", "rJ" } },
+#else
+ { INDEX_op_qemu_ld64, { "L", "L", "L" } },
+ { INDEX_op_qemu_st64, { "L", "L", "L" } },
#endif
{ -1 },
};
--
1.7.12.1

View File

@ -0,0 +1,27 @@
From b92aceeb9604c74e4a66db8ea5dd399d892e94bc Mon Sep 17 00:00:00 2001
From: Richard Henderson <rth@twiddle.net>
Date: Fri, 23 Mar 2012 23:57:12 +0100
Subject: [PATCH] tcg-sparc: Fix ADDX opcode.
Signed-off-by: Richard Henderson <rth@twiddle.net>
Signed-off-by: Michael Roth <mdroth@linux.vnet.ibm.com>
---
tcg/sparc/tcg-target.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/tcg/sparc/tcg-target.c b/tcg/sparc/tcg-target.c
index 608fc46..0a19313 100644
--- a/tcg/sparc/tcg-target.c
+++ b/tcg/sparc/tcg-target.c
@@ -236,7 +236,7 @@ static inline int tcg_target_const_match(tcg_target_long val,
#define ARITH_XOR (INSN_OP(2) | INSN_OP3(0x03))
#define ARITH_SUB (INSN_OP(2) | INSN_OP3(0x04))
#define ARITH_SUBCC (INSN_OP(2) | INSN_OP3(0x14))
-#define ARITH_ADDX (INSN_OP(2) | INSN_OP3(0x10))
+#define ARITH_ADDX (INSN_OP(2) | INSN_OP3(0x08))
#define ARITH_SUBX (INSN_OP(2) | INSN_OP3(0x0c))
#define ARITH_UMUL (INSN_OP(2) | INSN_OP3(0x0a))
#define ARITH_UDIV (INSN_OP(2) | INSN_OP3(0x0e))
--
1.7.12.1

View File

@ -0,0 +1,45 @@
From 59aadb4f5b15eff968ed00ad29816ac19bef507d Mon Sep 17 00:00:00 2001
From: Richard Henderson <rth@twiddle.net>
Date: Fri, 21 Sep 2012 10:40:48 -0700
Subject: [PATCH] tcg-sparc: Don't MAP_FIXED on top of the program
The address we pick in sparc64.ld is also 0x60000000, so doing a fixed map
on top of that is guaranteed to blow up. Choosing 0x40000000 is exactly
right for the max of code_gen_buffer_size set below.
No need to ever use MAP_FIXED. While getting our desired address helps
optimize the generated code, we won't fail if we don't get it.
Signed-off-by: Richard Henderson <rth@twiddle.net>
Signed-off-by: Michael Roth <mdroth@linux.vnet.ibm.com>
---
exec.c | 6 ++----
1 file changed, 2 insertions(+), 4 deletions(-)
diff --git a/exec.c b/exec.c
index 5834766..871a68a 100644
--- a/exec.c
+++ b/exec.c
@@ -543,8 +543,7 @@ static void code_gen_alloc(unsigned long tb_size)
code_gen_buffer_size = (800 * 1024 * 1024);
#elif defined(__sparc_v9__)
// Map the buffer below 2G, so we can use direct calls and branches
- flags |= MAP_FIXED;
- start = (void *) 0x60000000UL;
+ start = (void *) 0x40000000UL;
if (code_gen_buffer_size > (512 * 1024 * 1024))
code_gen_buffer_size = (512 * 1024 * 1024);
#elif defined(__arm__)
@@ -584,8 +583,7 @@ static void code_gen_alloc(unsigned long tb_size)
code_gen_buffer_size = (800 * 1024 * 1024);
#elif defined(__sparc_v9__)
// Map the buffer below 2G, so we can use direct calls and branches
- flags |= MAP_FIXED;
- addr = (void *) 0x60000000UL;
+ addr = (void *) 0x40000000UL;
if (code_gen_buffer_size > (512 * 1024 * 1024)) {
code_gen_buffer_size = (512 * 1024 * 1024);
}
--
1.7.12.1

View File

@ -0,0 +1,286 @@
From cf873edf4227be439a9ffa5abb3da61ff1fd6527 Mon Sep 17 00:00:00 2001
From: Richard Henderson <rth@twiddle.net>
Date: Fri, 21 Sep 2012 10:34:21 -0700
Subject: [PATCH] tcg-sparc: Assume v9 cpu always, i.e. force v8plus in 32-bit
mode.
Current code doesn't actually work in 32-bit mode at all. Since
no one really noticed, drop the complication of v7 and v8 cpus.
Eliminate the --sparc_cpu configure option and standardize macro
testing on TCG_TARGET_REG_BITS / HOST_LONG_BITS
Signed-off-by: Richard Henderson <rth@twiddle.net>
Signed-off-by: Michael Roth <mdroth@linux.vnet.ibm.com>
---
configure | 40 ++++------------------------------------
disas.c | 2 --
exec.c | 6 +++---
qemu-timer.h | 8 +++++---
tcg/sparc/tcg-target.c | 20 +++++---------------
tcg/sparc/tcg-target.h | 7 ++++---
tcg/tcg.c | 3 ++-
7 files changed, 23 insertions(+), 63 deletions(-)
diff --git a/configure b/configure
index 816f0f9..0590f16 100755
--- a/configure
+++ b/configure
@@ -111,7 +111,6 @@ source_path=`dirname "$0"`
cpu=""
interp_prefix="/usr/gnemul/qemu-%M"
static="no"
-sparc_cpu=""
cross_prefix=""
audio_drv_list=""
audio_card_list="ac97 es1370 sb16 hda"
@@ -249,21 +248,6 @@ for opt do
;;
--disable-debug-info) debug_info="no"
;;
- --sparc_cpu=*)
- sparc_cpu="$optarg"
- case $sparc_cpu in
- v7|v8|v8plus|v8plusa)
- cpu="sparc"
- ;;
- v9)
- cpu="sparc64"
- ;;
- *)
- echo "undefined SPARC architecture. Exiting";
- exit 1
- ;;
- esac
- ;;
esac
done
# OS specific
@@ -351,8 +335,6 @@ elif check_define __i386__ ; then
elif check_define __x86_64__ ; then
cpu="x86_64"
elif check_define __sparc__ ; then
- # We can't check for 64 bit (when gcc is biarch) or V8PLUSA
- # They must be specified using --sparc_cpu
if check_define __arch64__ ; then
cpu="sparc64"
else
@@ -798,8 +780,6 @@ for opt do
;;
--enable-uname-release=*) uname_release="$optarg"
;;
- --sparc_cpu=*)
- ;;
--enable-werror) werror="yes"
;;
--disable-werror) werror="no"
@@ -883,31 +863,19 @@ for opt do
esac
done
-#
-# If cpu ~= sparc and sparc_cpu hasn't been defined, plug in the right
-# QEMU_CFLAGS/LDFLAGS (assume sparc_v8plus for 32-bit and sparc_v9 for 64-bit)
-#
host_guest_base="no"
case "$cpu" in
- sparc) case $sparc_cpu in
- v7|v8)
- QEMU_CFLAGS="-mcpu=${sparc_cpu} -D__sparc_${sparc_cpu}__ $QEMU_CFLAGS"
- ;;
- v8plus|v8plusa)
- QEMU_CFLAGS="-mcpu=ultrasparc -D__sparc_${sparc_cpu}__ $QEMU_CFLAGS"
- ;;
- *) # sparc_cpu not defined in the command line
- QEMU_CFLAGS="-mcpu=ultrasparc -D__sparc_v8plus__ $QEMU_CFLAGS"
- esac
+ sparc)
LDFLAGS="-m32 $LDFLAGS"
- QEMU_CFLAGS="-m32 -ffixed-g2 -ffixed-g3 $QEMU_CFLAGS"
+ QEMU_CFLAGS="-m32 -mcpu=ultrasparc $QEMU_CFLAGS"
+ QEMU_CFLAGS="-ffixed-g2 -ffixed-g3 $QEMU_CFLAGS"
if test "$solaris" = "no" ; then
QEMU_CFLAGS="-ffixed-g1 -ffixed-g6 $QEMU_CFLAGS"
fi
;;
sparc64)
- QEMU_CFLAGS="-m64 -mcpu=ultrasparc -D__sparc_v9__ $QEMU_CFLAGS"
LDFLAGS="-m64 $LDFLAGS"
+ QEMU_CFLAGS="-m64 -mcpu=ultrasparc $QEMU_CFLAGS"
QEMU_CFLAGS="-ffixed-g5 -ffixed-g6 -ffixed-g7 $QEMU_CFLAGS"
if test "$solaris" != "no" ; then
QEMU_CFLAGS="-ffixed-g1 $QEMU_CFLAGS"
diff --git a/disas.c b/disas.c
index 7b2acc9..b801c8f 100644
--- a/disas.c
+++ b/disas.c
@@ -316,9 +316,7 @@ void disas(FILE *out, void *code, unsigned long size)
print_insn = print_insn_alpha;
#elif defined(__sparc__)
print_insn = print_insn_sparc;
-#if defined(__sparc_v8plus__) || defined(__sparc_v8plusa__) || defined(__sparc_v9__)
disasm_info.mach = bfd_mach_sparc_v9b;
-#endif
#elif defined(__arm__)
print_insn = print_insn_arm;
#elif defined(__MIPSEB__)
diff --git a/exec.c b/exec.c
index 871a68a..ad175db 100644
--- a/exec.c
+++ b/exec.c
@@ -86,7 +86,7 @@ static int nb_tbs;
/* any access to the tbs or the page table must use this lock */
spinlock_t tb_lock = SPIN_LOCK_UNLOCKED;
-#if defined(__arm__) || defined(__sparc_v9__)
+#if defined(__arm__) || defined(__sparc__)
/* The prologue must be reachable with a direct jump. ARM and Sparc64
have limited branch ranges (possibly also PPC) so place it in a
section close to code segment. */
@@ -541,7 +541,7 @@ static void code_gen_alloc(unsigned long tb_size)
/* Cannot map more than that */
if (code_gen_buffer_size > (800 * 1024 * 1024))
code_gen_buffer_size = (800 * 1024 * 1024);
-#elif defined(__sparc_v9__)
+#elif defined(__sparc__) && HOST_LONG_BITS == 64
// Map the buffer below 2G, so we can use direct calls and branches
start = (void *) 0x40000000UL;
if (code_gen_buffer_size > (512 * 1024 * 1024))
@@ -581,7 +581,7 @@ static void code_gen_alloc(unsigned long tb_size)
/* Cannot map more than that */
if (code_gen_buffer_size > (800 * 1024 * 1024))
code_gen_buffer_size = (800 * 1024 * 1024);
-#elif defined(__sparc_v9__)
+#elif defined(__sparc__) && HOST_LONG_BITS == 64
// Map the buffer below 2G, so we can use direct calls and branches
addr = (void *) 0x40000000UL;
if (code_gen_buffer_size > (512 * 1024 * 1024)) {
diff --git a/qemu-timer.h b/qemu-timer.h
index f8af595..da7e97c 100644
--- a/qemu-timer.h
+++ b/qemu-timer.h
@@ -218,7 +218,7 @@ static inline int64_t cpu_get_real_ticks(void)
return val;
}
-#elif defined(__sparc_v8plus__) || defined(__sparc_v8plusa__) || defined(__sparc_v9__)
+#elif defined(__sparc__)
static inline int64_t cpu_get_real_ticks (void)
{
@@ -227,6 +227,8 @@ static inline int64_t cpu_get_real_ticks (void)
asm volatile("rd %%tick,%0" : "=r"(rval));
return rval;
#else
+ /* We need an %o or %g register for this. For recent enough gcc
+ there is an "h" constraint for that. Don't bother with that. */
union {
uint64_t i64;
struct {
@@ -234,8 +236,8 @@ static inline int64_t cpu_get_real_ticks (void)
uint32_t low;
} i32;
} rval;
- asm volatile("rd %%tick,%1; srlx %1,32,%0"
- : "=r"(rval.i32.high), "=r"(rval.i32.low));
+ asm volatile("rd %%tick,%%g1; srlx %%g1,32,%0; mov %%g1,%1"
+ : "=r"(rval.i32.high), "=r"(rval.i32.low) : : "g1");
return rval.i64;
#endif
}
diff --git a/tcg/sparc/tcg-target.c b/tcg/sparc/tcg-target.c
index 0a19313..23c2fda 100644
--- a/tcg/sparc/tcg-target.c
+++ b/tcg/sparc/tcg-target.c
@@ -621,18 +621,10 @@ static void tcg_out_setcond_i32(TCGContext *s, TCGCond cond, TCGArg ret,
default:
tcg_out_cmp(s, c1, c2, c2const);
-#if defined(__sparc_v9__) || defined(__sparc_v8plus__)
tcg_out_movi_imm13(s, ret, 0);
- tcg_out32 (s, ARITH_MOVCC | INSN_RD(ret)
- | INSN_RS1(tcg_cond_to_bcond[cond])
- | MOVCC_ICC | INSN_IMM11(1));
-#else
- t = gen_new_label();
- tcg_out_branch_i32(s, INSN_COND(tcg_cond_to_bcond[cond], 1), t);
- tcg_out_movi_imm13(s, ret, 1);
- tcg_out_movi_imm13(s, ret, 0);
- tcg_out_label(s, t, s->code_ptr);
-#endif
+ tcg_out32(s, ARITH_MOVCC | INSN_RD(ret)
+ | INSN_RS1(tcg_cond_to_bcond[cond])
+ | MOVCC_ICC | INSN_IMM11(1));
return;
}
@@ -742,7 +734,7 @@ static const void * const qemu_st_helpers[4] = {
#endif
#endif
-#ifdef __arch64__
+#if TCG_TARGET_REG_BITS == 64
#define HOST_LD_OP LDX
#define HOST_ST_OP STX
#define HOST_SLL_OP SHIFT_SLLX
@@ -1600,11 +1592,9 @@ static void tcg_target_init(TCGContext *s)
#if TCG_TARGET_REG_BITS == 64
# define ELF_HOST_MACHINE EM_SPARCV9
-#elif defined(__sparc_v8plus__)
+#else
# define ELF_HOST_MACHINE EM_SPARC32PLUS
# define ELF_HOST_FLAGS EF_SPARC_32PLUS
-#else
-# define ELF_HOST_MACHINE EM_SPARC
#endif
typedef struct {
diff --git a/tcg/sparc/tcg-target.h b/tcg/sparc/tcg-target.h
index d762574..adca1d2 100644
--- a/tcg/sparc/tcg-target.h
+++ b/tcg/sparc/tcg-target.h
@@ -67,7 +67,8 @@ typedef enum {
/* used for function call generation */
#define TCG_REG_CALL_STACK TCG_REG_I6
-#ifdef __arch64__
+
+#if TCG_TARGET_REG_BITS == 64
// Reserve space for AREG0
#define TCG_TARGET_STACK_MINFRAME (176 + 4 * (int)sizeof(long) + \
TCG_STATIC_CALL_ARGS_SIZE)
@@ -81,7 +82,7 @@ typedef enum {
#define TCG_TARGET_STACK_ALIGN 8
#endif
-#ifdef __arch64__
+#if TCG_TARGET_REG_BITS == 64
#define TCG_TARGET_EXTEND_ARGS 1
#endif
@@ -129,7 +130,7 @@ typedef enum {
#ifdef CONFIG_SOLARIS
#define TCG_AREG0 TCG_REG_G2
-#elif defined(__sparc_v9__)
+#elif HOST_LONG_BITS == 64
#define TCG_AREG0 TCG_REG_G5
#else
#define TCG_AREG0 TCG_REG_G6
diff --git a/tcg/tcg.c b/tcg/tcg.c
index 93421cd..16c4e1d 100644
--- a/tcg/tcg.c
+++ b/tcg/tcg.c
@@ -1450,7 +1450,8 @@ static void temp_allocate_frame(TCGContext *s, int temp)
{
TCGTemp *ts;
ts = &s->temps[temp];
-#ifndef __sparc_v9__ /* Sparc64 stack is accessed with offset of 2047 */
+#if !(defined(__sparc__) && TCG_TARGET_REG_BITS == 64)
+ /* Sparc64 stack is accessed with offset of 2047 */
s->current_frame_offset = (s->current_frame_offset +
(tcg_target_long)sizeof(tcg_target_long) - 1) &
~(sizeof(tcg_target_long) - 1);
--
1.7.12.1

View File

@ -0,0 +1,967 @@
From 138dfa905538bf918af390ff365a27de49364578 Mon Sep 17 00:00:00 2001
From: Richard Henderson <rth@twiddle.net>
Date: Fri, 23 Mar 2012 23:27:39 +0100
Subject: [PATCH] tcg-sparc: Fix qemu_ld/st to handle 32-bit host.
At the same time, split out the tlb load logic to a new function.
Fixes the cases of two data registers and two address registers.
Fixes the signature of, and adds missing, qemu_ld/st opcodes.
Signed-off-by: Richard Henderson <rth@twiddle.net>
Signed-off-by: Michael Roth <mdroth@linux.vnet.ibm.com>
---
tcg/sparc/tcg-target.c | 777 ++++++++++++++++++++++---------------------------
1 file changed, 348 insertions(+), 429 deletions(-)
diff --git a/tcg/sparc/tcg-target.c b/tcg/sparc/tcg-target.c
index 23c2fda..d89c19b 100644
--- a/tcg/sparc/tcg-target.c
+++ b/tcg/sparc/tcg-target.c
@@ -59,8 +59,6 @@ static const char * const tcg_target_reg_names[TCG_TARGET_NB_REGS] = {
};
#endif
-#define ARG_OFFSET 1
-
static const int tcg_target_reg_alloc_order[] = {
TCG_REG_L0,
TCG_REG_L1,
@@ -288,6 +286,16 @@ static inline int tcg_target_const_match(tcg_target_long val,
#define ASI_PRIMARY_LITTLE 0x88
#endif
+#define LDUH_LE (LDUHA | INSN_ASI(ASI_PRIMARY_LITTLE))
+#define LDSH_LE (LDSHA | INSN_ASI(ASI_PRIMARY_LITTLE))
+#define LDUW_LE (LDUWA | INSN_ASI(ASI_PRIMARY_LITTLE))
+#define LDSW_LE (LDSWA | INSN_ASI(ASI_PRIMARY_LITTLE))
+#define LDX_LE (LDXA | INSN_ASI(ASI_PRIMARY_LITTLE))
+
+#define STH_LE (STHA | INSN_ASI(ASI_PRIMARY_LITTLE))
+#define STW_LE (STWA | INSN_ASI(ASI_PRIMARY_LITTLE))
+#define STX_LE (STXA | INSN_ASI(ASI_PRIMARY_LITTLE))
+
static inline void tcg_out_arith(TCGContext *s, int rd, int rs1, int rs2,
int op)
{
@@ -360,64 +368,43 @@ static inline void tcg_out_movi(TCGContext *s, TCGType type,
}
}
-static inline void tcg_out_ld_raw(TCGContext *s, int ret,
- tcg_target_long arg)
-{
- tcg_out_sethi(s, ret, arg);
- tcg_out32(s, LDUW | INSN_RD(ret) | INSN_RS1(ret) |
- INSN_IMM13(arg & 0x3ff));
-}
-
-static inline void tcg_out_ld_ptr(TCGContext *s, int ret,
- tcg_target_long arg)
+static inline void tcg_out_ldst_rr(TCGContext *s, int data, int a1,
+ int a2, int op)
{
- if (!check_fit_tl(arg, 10))
- tcg_out_movi(s, TCG_TYPE_PTR, ret, arg & ~0x3ffULL);
- if (TCG_TARGET_REG_BITS == 64) {
- tcg_out32(s, LDX | INSN_RD(ret) | INSN_RS1(ret) |
- INSN_IMM13(arg & 0x3ff));
- } else {
- tcg_out32(s, LDUW | INSN_RD(ret) | INSN_RS1(ret) |
- INSN_IMM13(arg & 0x3ff));
- }
+ tcg_out32(s, op | INSN_RD(data) | INSN_RS1(a1) | INSN_RS2(a2));
}
-static inline void tcg_out_ldst(TCGContext *s, int ret, int addr, int offset, int op)
+static inline void tcg_out_ldst(TCGContext *s, int ret, int addr,
+ int offset, int op)
{
- if (check_fit_tl(offset, 13))
+ if (check_fit_tl(offset, 13)) {
tcg_out32(s, op | INSN_RD(ret) | INSN_RS1(addr) |
INSN_IMM13(offset));
- else {
+ } else {
tcg_out_movi(s, TCG_TYPE_PTR, TCG_REG_I5, offset);
- tcg_out32(s, op | INSN_RD(ret) | INSN_RS1(TCG_REG_I5) |
- INSN_RS2(addr));
+ tcg_out_ldst_rr(s, ret, addr, TCG_REG_I5, op);
}
}
-static inline void tcg_out_ldst_asi(TCGContext *s, int ret, int addr,
- int offset, int op, int asi)
-{
- tcg_out_movi(s, TCG_TYPE_PTR, TCG_REG_I5, offset);
- tcg_out32(s, op | INSN_RD(ret) | INSN_RS1(TCG_REG_I5) |
- INSN_ASI(asi) | INSN_RS2(addr));
-}
-
static inline void tcg_out_ld(TCGContext *s, TCGType type, TCGReg ret,
TCGReg arg1, tcg_target_long arg2)
{
- if (type == TCG_TYPE_I32)
- tcg_out_ldst(s, ret, arg1, arg2, LDUW);
- else
- tcg_out_ldst(s, ret, arg1, arg2, LDX);
+ tcg_out_ldst(s, ret, arg1, arg2, (type == TCG_TYPE_I32 ? LDUW : LDX));
}
static inline void tcg_out_st(TCGContext *s, TCGType type, TCGReg arg,
TCGReg arg1, tcg_target_long arg2)
{
- if (type == TCG_TYPE_I32)
- tcg_out_ldst(s, arg, arg1, arg2, STW);
- else
- tcg_out_ldst(s, arg, arg1, arg2, STX);
+ tcg_out_ldst(s, arg, arg1, arg2, (type == TCG_TYPE_I32 ? STW : STX));
+}
+
+static inline void tcg_out_ld_ptr(TCGContext *s, int ret,
+ tcg_target_long arg)
+{
+ if (!check_fit_tl(arg, 10)) {
+ tcg_out_movi(s, TCG_TYPE_PTR, ret, arg & ~0x3ff);
+ }
+ tcg_out_ld(s, TCG_TYPE_PTR, ret, ret, arg & 0x3ff);
}
static inline void tcg_out_sety(TCGContext *s, int rs)
@@ -442,14 +429,15 @@ static inline void tcg_out_addi(TCGContext *s, int reg, tcg_target_long val)
}
}
-static inline void tcg_out_andi(TCGContext *s, int reg, tcg_target_long val)
+static inline void tcg_out_andi(TCGContext *s, int rd, int rs,
+ tcg_target_long val)
{
if (val != 0) {
if (check_fit_tl(val, 13))
- tcg_out_arithi(s, reg, reg, val, ARITH_AND);
+ tcg_out_arithi(s, rd, rs, val, ARITH_AND);
else {
tcg_out_movi(s, TCG_TYPE_I32, TCG_REG_I5, val);
- tcg_out_arith(s, reg, reg, TCG_REG_I5, ARITH_AND);
+ tcg_out_arith(s, rd, rs, TCG_REG_I5, ARITH_AND);
}
}
}
@@ -718,418 +706,328 @@ static const void * const qemu_st_helpers[4] = {
helper_stl_mmu,
helper_stq_mmu,
};
-#endif
-#if TARGET_LONG_BITS == 32
-#define TARGET_LD_OP LDUW
-#else
-#define TARGET_LD_OP LDX
-#endif
+/* Perform the TLB load and compare.
-#if defined(CONFIG_SOFTMMU)
-#if HOST_LONG_BITS == 32
-#define TARGET_ADDEND_LD_OP LDUW
+ Inputs:
+ ADDRLO_IDX contains the index into ARGS of the low part of the
+ address; the high part of the address is at ADDR_LOW_IDX+1.
+
+ MEM_INDEX and S_BITS are the memory context and log2 size of the load.
+
+ WHICH is the offset into the CPUTLBEntry structure of the slot to read.
+ This should be offsetof addr_read or addr_write.
+
+ The result of the TLB comparison is in %[ix]cc. The sanitized address
+ is in the returned register, maybe %o0. The TLB addend is in %o1. */
+
+static int tcg_out_tlb_load(TCGContext *s, int addrlo_idx, int mem_index,
+ int s_bits, const TCGArg *args, int which)
+{
+ const int addrlo = args[addrlo_idx];
+ const int r0 = TCG_REG_O0;
+ const int r1 = TCG_REG_O1;
+ const int r2 = TCG_REG_O2;
+ int addr = addrlo;
+ int tlb_ofs;
+
+ if (TCG_TARGET_REG_BITS == 32 && TARGET_LONG_BITS == 64) {
+ /* Assemble the 64-bit address in R0. */
+ tcg_out_arithi(s, r0, addrlo, 0, SHIFT_SRL);
+ tcg_out_arithi(s, r1, args[addrlo_idx + 1], 32, SHIFT_SLLX);
+ tcg_out_arith(s, r0, r0, r1, ARITH_OR);
+ }
+
+ /* Shift the page number down to tlb-entry. */
+ tcg_out_arithi(s, r1, addrlo,
+ TARGET_PAGE_BITS - CPU_TLB_ENTRY_BITS, SHIFT_SRL);
+
+ /* Mask out the page offset, except for the required alignment. */
+ tcg_out_andi(s, r0, addr, TARGET_PAGE_MASK | ((1 << s_bits) - 1));
+
+ /* Compute tlb index, modulo tlb size. */
+ tcg_out_andi(s, r1, r1, (CPU_TLB_SIZE - 1) << CPU_TLB_ENTRY_BITS);
+
+ /* Relative to the current ENV. */
+ tcg_out_arith(s, r1, TCG_AREG0, r1, ARITH_ADD);
+
+ /* Find a base address that can load both tlb comparator and addend. */
+ tlb_ofs = offsetof(CPUArchState, tlb_table[mem_index][0]);
+ if (!check_fit_tl(tlb_ofs + sizeof(CPUTLBEntry), 13)) {
+ tcg_out_addi(s, r1, tlb_ofs);
+ tlb_ofs = 0;
+ }
+
+ /* Load the tlb comparator and the addend. */
+ tcg_out_ld(s, TCG_TYPE_TL, r2, r1, tlb_ofs + which);
+ tcg_out_ld(s, TCG_TYPE_PTR, r1, r1, tlb_ofs+offsetof(CPUTLBEntry, addend));
+
+ /* subcc arg0, arg2, %g0 */
+ tcg_out_cmp(s, r0, r2, 0);
+
+ /* If the guest address must be zero-extended, do so now. */
+ if (TCG_TARGET_REG_BITS == 64 && TARGET_LONG_BITS == 32) {
+ tcg_out_arithi(s, r0, addrlo, 0, SHIFT_SRL);
+ return r0;
+ }
+ return addrlo;
+}
+#endif /* CONFIG_SOFTMMU */
+
+static const int qemu_ld_opc[8] = {
+#ifdef TARGET_WORDS_BIGENDIAN
+ LDUB, LDUH, LDUW, LDX, LDSB, LDSH, LDSW, LDX
#else
-#define TARGET_ADDEND_LD_OP LDX
-#endif
+ LDUB, LDUH_LE, LDUW_LE, LDX_LE, LDSB, LDSH_LE, LDSW_LE, LDX_LE
#endif
+};
-#if TCG_TARGET_REG_BITS == 64
-#define HOST_LD_OP LDX
-#define HOST_ST_OP STX
-#define HOST_SLL_OP SHIFT_SLLX
-#define HOST_SRA_OP SHIFT_SRAX
+static const int qemu_st_opc[4] = {
+#ifdef TARGET_WORDS_BIGENDIAN
+ STB, STH, STW, STX
#else
-#define HOST_LD_OP LDUW
-#define HOST_ST_OP STW
-#define HOST_SLL_OP SHIFT_SLL
-#define HOST_SRA_OP SHIFT_SRA
+ STB, STH_LE, STW_LE, STX_LE
#endif
+};
-static void tcg_out_qemu_ld(TCGContext *s, const TCGArg *args,
- int opc)
+static void tcg_out_qemu_ld(TCGContext *s, const TCGArg *args, int sizeop)
{
- int addr_reg, data_reg, arg0, arg1, arg2, mem_index, s_bits;
+ int addrlo_idx = 1, datalo, datahi, addr_reg;
#if defined(CONFIG_SOFTMMU)
- uint32_t *label1_ptr, *label2_ptr;
+ int memi_idx, memi, s_bits, n;
+ uint32_t *label_ptr[2];
#endif
- data_reg = *args++;
- addr_reg = *args++;
- mem_index = *args;
- s_bits = opc & 3;
-
- arg0 = TCG_REG_O0;
- arg1 = TCG_REG_O1;
- arg2 = TCG_REG_O2;
+ datahi = datalo = args[0];
+ if (TCG_TARGET_REG_BITS == 32 && sizeop == 3) {
+ datahi = args[1];
+ addrlo_idx = 2;
+ }
#if defined(CONFIG_SOFTMMU)
- /* srl addr_reg, x, arg1 */
- tcg_out_arithi(s, arg1, addr_reg, TARGET_PAGE_BITS - CPU_TLB_ENTRY_BITS,
- SHIFT_SRL);
- /* and addr_reg, x, arg0 */
- tcg_out_arithi(s, arg0, addr_reg, TARGET_PAGE_MASK | ((1 << s_bits) - 1),
- ARITH_AND);
+ memi_idx = addrlo_idx + 1 + (TARGET_LONG_BITS > TCG_TARGET_REG_BITS);
+ memi = args[memi_idx];
+ s_bits = sizeop & 3;
+
+ addr_reg = tcg_out_tlb_load(s, addrlo_idx, memi, s_bits, args,
+ offsetof(CPUTLBEntry, addr_read));
+
+ if (TCG_TARGET_REG_BITS == 32 && sizeop == 3) {
+ int reg64;
+
+ /* bne,pn %[xi]cc, label0 */
+ label_ptr[0] = (uint32_t *)s->code_ptr;
+ tcg_out32(s, (INSN_OP(0) | INSN_COND(COND_NE, 0) | INSN_OP2(0x1)
+ | ((TARGET_LONG_BITS == 64) << 21)));
+
+ /* TLB Hit. */
+ /* Load all 64-bits into an O/G register. */
+ reg64 = (datalo < 16 ? datalo : TCG_REG_O0);
+ tcg_out_ldst_rr(s, reg64, addr_reg, TCG_REG_O1, qemu_ld_opc[sizeop]);
+
+ /* Move the two 32-bit pieces into the destination registers. */
+ tcg_out_arithi(s, datahi, reg64, 32, SHIFT_SRLX);
+ if (reg64 != datalo) {
+ tcg_out_mov(s, TCG_TYPE_I32, datalo, reg64);
+ }
- /* and arg1, x, arg1 */
- tcg_out_andi(s, arg1, (CPU_TLB_SIZE - 1) << CPU_TLB_ENTRY_BITS);
+ /* b,a,pt label1 */
+ label_ptr[1] = (uint32_t *)s->code_ptr;
+ tcg_out32(s, (INSN_OP(0) | INSN_COND(COND_A, 0) | INSN_OP2(0x1)
+ | (1 << 29) | (1 << 19)));
+ } else {
+ /* The fast path is exactly one insn. Thus we can perform the
+ entire TLB Hit in the (annulled) delay slot of the branch
+ over the TLB Miss case. */
+
+ /* beq,a,pt %[xi]cc, label0 */
+ label_ptr[0] = NULL;
+ label_ptr[1] = (uint32_t *)s->code_ptr;
+ tcg_out32(s, (INSN_OP(0) | INSN_COND(COND_E, 0) | INSN_OP2(0x1)
+ | ((TARGET_LONG_BITS == 64) << 21)
+ | (1 << 29) | (1 << 19)));
+ /* delay slot */
+ tcg_out_ldst_rr(s, datalo, addr_reg, TCG_REG_O1, qemu_ld_opc[sizeop]);
+ }
- /* add arg1, x, arg1 */
- tcg_out_addi(s, arg1, offsetof(CPUArchState,
- tlb_table[mem_index][0].addr_read));
+ /* TLB Miss. */
- /* add env, arg1, arg1 */
- tcg_out_arith(s, arg1, TCG_AREG0, arg1, ARITH_ADD);
+ if (label_ptr[0]) {
+ *label_ptr[0] |= INSN_OFF19((unsigned long)s->code_ptr -
+ (unsigned long)label_ptr[0]);
+ }
+ n = 0;
+ tcg_out_mov(s, TCG_TYPE_PTR, tcg_target_call_iarg_regs[n++], TCG_AREG0);
+ if (TARGET_LONG_BITS > TCG_TARGET_REG_BITS) {
+ tcg_out_mov(s, TCG_TYPE_REG, tcg_target_call_iarg_regs[n++],
+ args[addrlo_idx + 1]);
+ }
+ tcg_out_mov(s, TCG_TYPE_REG, tcg_target_call_iarg_regs[n++],
+ args[addrlo_idx]);
- /* ld [arg1], arg2 */
- tcg_out32(s, TARGET_LD_OP | INSN_RD(arg2) | INSN_RS1(arg1) |
- INSN_RS2(TCG_REG_G0));
+ /* Store AREG0 in stack to avoid ugly glibc bugs that mangle
+ global registers */
+ tcg_out_st(s, TCG_TYPE_REG, TCG_AREG0, TCG_REG_CALL_STACK,
+ TCG_TARGET_CALL_STACK_OFFSET - TCG_STATIC_CALL_ARGS_SIZE -
+ sizeof(long));
- /* subcc arg0, arg2, %g0 */
- tcg_out_arith(s, TCG_REG_G0, arg0, arg2, ARITH_SUBCC);
-
- /* will become:
- be label1
- or
- be,pt %xcc label1 */
- label1_ptr = (uint32_t *)s->code_ptr;
- tcg_out32(s, 0);
-
- /* mov (delay slot) */
- tcg_out_mov(s, TCG_TYPE_PTR, arg0, addr_reg);
-
- /* mov */
- tcg_out_movi(s, TCG_TYPE_I32, arg1, mem_index);
- /* XXX/FIXME: suboptimal */
- tcg_out_mov(s, TCG_TYPE_I32, tcg_target_call_iarg_regs[3],
- tcg_target_call_iarg_regs[2]);
- tcg_out_mov(s, TCG_TYPE_I64, tcg_target_call_iarg_regs[2],
- tcg_target_call_iarg_regs[1]);
- tcg_out_mov(s, TCG_TYPE_TL, tcg_target_call_iarg_regs[1],
- tcg_target_call_iarg_regs[0]);
- tcg_out_mov(s, TCG_TYPE_PTR, tcg_target_call_iarg_regs[0],
- TCG_AREG0);
-
- /* XXX: move that code at the end of the TB */
/* qemu_ld_helper[s_bits](arg0, arg1) */
tcg_out32(s, CALL | ((((tcg_target_ulong)qemu_ld_helpers[s_bits]
- (tcg_target_ulong)s->code_ptr) >> 2)
& 0x3fffffff));
- /* Store AREG0 in stack to avoid ugly glibc bugs that mangle
- global registers */
- // delay slot
- tcg_out_ldst(s, TCG_AREG0, TCG_REG_CALL_STACK,
- TCG_TARGET_CALL_STACK_OFFSET - TCG_STATIC_CALL_ARGS_SIZE -
- sizeof(long), HOST_ST_OP);
- tcg_out_ldst(s, TCG_AREG0, TCG_REG_CALL_STACK,
- TCG_TARGET_CALL_STACK_OFFSET - TCG_STATIC_CALL_ARGS_SIZE -
- sizeof(long), HOST_LD_OP);
-
- /* data_reg = sign_extend(arg0) */
- switch(opc) {
+ /* delay slot */
+ tcg_out_movi(s, TCG_TYPE_I32, tcg_target_call_iarg_regs[n], memi);
+
+ /* Reload AREG0. */
+ tcg_out_ld(s, TCG_TYPE_REG, TCG_AREG0, TCG_REG_CALL_STACK,
+ TCG_TARGET_CALL_STACK_OFFSET - TCG_STATIC_CALL_ARGS_SIZE -
+ sizeof(long));
+
+ n = tcg_target_call_oarg_regs[0];
+ /* datalo = sign_extend(arg0) */
+ switch (sizeop) {
case 0 | 4:
- /* sll arg0, 24/56, data_reg */
- tcg_out_arithi(s, data_reg, arg0, (int)sizeof(tcg_target_long) * 8 - 8,
- HOST_SLL_OP);
- /* sra data_reg, 24/56, data_reg */
- tcg_out_arithi(s, data_reg, data_reg,
- (int)sizeof(tcg_target_long) * 8 - 8, HOST_SRA_OP);
+ /* Recall that SRA sign extends from bit 31 through bit 63. */
+ tcg_out_arithi(s, datalo, n, 24, SHIFT_SLL);
+ tcg_out_arithi(s, datalo, datalo, 24, SHIFT_SRA);
break;
case 1 | 4:
- /* sll arg0, 16/48, data_reg */
- tcg_out_arithi(s, data_reg, arg0,
- (int)sizeof(tcg_target_long) * 8 - 16, HOST_SLL_OP);
- /* sra data_reg, 16/48, data_reg */
- tcg_out_arithi(s, data_reg, data_reg,
- (int)sizeof(tcg_target_long) * 8 - 16, HOST_SRA_OP);
+ tcg_out_arithi(s, datalo, n, 16, SHIFT_SLL);
+ tcg_out_arithi(s, datalo, datalo, 16, SHIFT_SRA);
break;
case 2 | 4:
- /* sll arg0, 32, data_reg */
- tcg_out_arithi(s, data_reg, arg0, 32, HOST_SLL_OP);
- /* sra data_reg, 32, data_reg */
- tcg_out_arithi(s, data_reg, data_reg, 32, HOST_SRA_OP);
+ tcg_out_arithi(s, datalo, n, 0, SHIFT_SRA);
break;
+ case 3:
+ if (TCG_TARGET_REG_BITS == 32) {
+ tcg_out_mov(s, TCG_TYPE_REG, datahi, n);
+ tcg_out_mov(s, TCG_TYPE_REG, datalo, n + 1);
+ break;
+ }
+ /* FALLTHRU */
case 0:
case 1:
case 2:
- case 3:
default:
/* mov */
- tcg_out_mov(s, TCG_TYPE_REG, data_reg, arg0);
+ tcg_out_mov(s, TCG_TYPE_REG, datalo, n);
break;
}
- /* will become:
- ba label2 */
- label2_ptr = (uint32_t *)s->code_ptr;
- tcg_out32(s, 0);
-
- /* nop (delay slot */
- tcg_out_nop(s);
-
- /* label1: */
-#if TARGET_LONG_BITS == 32
- /* be label1 */
- *label1_ptr = (INSN_OP(0) | INSN_COND(COND_E, 0) | INSN_OP2(0x2) |
- INSN_OFF22((unsigned long)s->code_ptr -
- (unsigned long)label1_ptr));
-#else
- /* be,pt %xcc label1 */
- *label1_ptr = (INSN_OP(0) | INSN_COND(COND_E, 0) | INSN_OP2(0x1) |
- (0x5 << 19) | INSN_OFF19((unsigned long)s->code_ptr -
- (unsigned long)label1_ptr));
-#endif
-
- /* ld [arg1 + x], arg1 */
- tcg_out_ldst(s, arg1, arg1, offsetof(CPUTLBEntry, addend) -
- offsetof(CPUTLBEntry, addr_read), TARGET_ADDEND_LD_OP);
-
-#if TARGET_LONG_BITS == 32
- /* and addr_reg, x, arg0 */
- tcg_out_movi(s, TCG_TYPE_I32, TCG_REG_I5, 0xffffffff);
- tcg_out_arith(s, arg0, addr_reg, TCG_REG_I5, ARITH_AND);
- /* add arg0, arg1, arg0 */
- tcg_out_arith(s, arg0, arg0, arg1, ARITH_ADD);
+ *label_ptr[1] |= INSN_OFF19((unsigned long)s->code_ptr -
+ (unsigned long)label_ptr[1]);
#else
- /* add addr_reg, arg1, arg0 */
- tcg_out_arith(s, arg0, addr_reg, arg1, ARITH_ADD);
-#endif
+ addr_reg = args[addrlo_idx];
+ if (TCG_TARGET_REG_BITS == 64 && TARGET_LONG_BITS == 32) {
+ tcg_out_arithi(s, TCG_REG_I5, addr_reg, 0, SHIFT_SRL);
+ addr_reg = TCG_REG_I5;
+ }
+ if (TCG_TARGET_REG_BITS == 32 && sizeop == 3) {
+ int reg64 = (datalo < 16 ? datalo : TCG_REG_O0);
-#else
- arg0 = addr_reg;
-#endif
+ tcg_out_ldst_rr(s, reg64, addr_reg, TCG_REG_G0, qemu_ld_opc[sizeop]);
- switch(opc) {
- case 0:
- /* ldub [arg0], data_reg */
- tcg_out_ldst(s, data_reg, arg0, 0, LDUB);
- break;
- case 0 | 4:
- /* ldsb [arg0], data_reg */
- tcg_out_ldst(s, data_reg, arg0, 0, LDSB);
- break;
- case 1:
-#ifdef TARGET_WORDS_BIGENDIAN
- /* lduh [arg0], data_reg */
- tcg_out_ldst(s, data_reg, arg0, 0, LDUH);
-#else
- /* lduha [arg0] ASI_PRIMARY_LITTLE, data_reg */
- tcg_out_ldst_asi(s, data_reg, arg0, 0, LDUHA, ASI_PRIMARY_LITTLE);
-#endif
- break;
- case 1 | 4:
-#ifdef TARGET_WORDS_BIGENDIAN
- /* ldsh [arg0], data_reg */
- tcg_out_ldst(s, data_reg, arg0, 0, LDSH);
-#else
- /* ldsha [arg0] ASI_PRIMARY_LITTLE, data_reg */
- tcg_out_ldst_asi(s, data_reg, arg0, 0, LDSHA, ASI_PRIMARY_LITTLE);
-#endif
- break;
- case 2:
-#ifdef TARGET_WORDS_BIGENDIAN
- /* lduw [arg0], data_reg */
- tcg_out_ldst(s, data_reg, arg0, 0, LDUW);
-#else
- /* lduwa [arg0] ASI_PRIMARY_LITTLE, data_reg */
- tcg_out_ldst_asi(s, data_reg, arg0, 0, LDUWA, ASI_PRIMARY_LITTLE);
-#endif
- break;
- case 2 | 4:
-#ifdef TARGET_WORDS_BIGENDIAN
- /* ldsw [arg0], data_reg */
- tcg_out_ldst(s, data_reg, arg0, 0, LDSW);
-#else
- /* ldswa [arg0] ASI_PRIMARY_LITTLE, data_reg */
- tcg_out_ldst_asi(s, data_reg, arg0, 0, LDSWA, ASI_PRIMARY_LITTLE);
-#endif
- break;
- case 3:
-#ifdef TARGET_WORDS_BIGENDIAN
- /* ldx [arg0], data_reg */
- tcg_out_ldst(s, data_reg, arg0, 0, LDX);
-#else
- /* ldxa [arg0] ASI_PRIMARY_LITTLE, data_reg */
- tcg_out_ldst_asi(s, data_reg, arg0, 0, LDXA, ASI_PRIMARY_LITTLE);
-#endif
- break;
- default:
- tcg_abort();
+ tcg_out_arithi(s, datahi, reg64, 32, SHIFT_SRLX);
+ if (reg64 != datalo) {
+ tcg_out_mov(s, TCG_TYPE_I32, datalo, reg64);
+ }
+ } else {
+ tcg_out_ldst_rr(s, datalo, addr_reg, TCG_REG_G0, qemu_ld_opc[sizeop]);
}
-
-#if defined(CONFIG_SOFTMMU)
- /* label2: */
- *label2_ptr = (INSN_OP(0) | INSN_COND(COND_A, 0) | INSN_OP2(0x2) |
- INSN_OFF22((unsigned long)s->code_ptr -
- (unsigned long)label2_ptr));
-#endif
+#endif /* CONFIG_SOFTMMU */
}
-static void tcg_out_qemu_st(TCGContext *s, const TCGArg *args,
- int opc)
+static void tcg_out_qemu_st(TCGContext *s, const TCGArg *args, int sizeop)
{
- int addr_reg, data_reg, arg0, arg1, arg2, mem_index, s_bits;
+ int addrlo_idx = 1, datalo, datahi, addr_reg;
#if defined(CONFIG_SOFTMMU)
- uint32_t *label1_ptr, *label2_ptr;
+ int memi_idx, memi, n;
+ uint32_t *label_ptr;
#endif
- data_reg = *args++;
- addr_reg = *args++;
- mem_index = *args;
-
- s_bits = opc;
-
- arg0 = TCG_REG_O0;
- arg1 = TCG_REG_O1;
- arg2 = TCG_REG_O2;
+ datahi = datalo = args[0];
+ if (TCG_TARGET_REG_BITS == 32 && sizeop == 3) {
+ datahi = args[1];
+ addrlo_idx = 2;
+ }
#if defined(CONFIG_SOFTMMU)
- /* srl addr_reg, x, arg1 */
- tcg_out_arithi(s, arg1, addr_reg, TARGET_PAGE_BITS - CPU_TLB_ENTRY_BITS,
- SHIFT_SRL);
-
- /* and addr_reg, x, arg0 */
- tcg_out_arithi(s, arg0, addr_reg, TARGET_PAGE_MASK | ((1 << s_bits) - 1),
- ARITH_AND);
-
- /* and arg1, x, arg1 */
- tcg_out_andi(s, arg1, (CPU_TLB_SIZE - 1) << CPU_TLB_ENTRY_BITS);
-
- /* add arg1, x, arg1 */
- tcg_out_addi(s, arg1, offsetof(CPUArchState,
- tlb_table[mem_index][0].addr_write));
+ memi_idx = addrlo_idx + 1 + (TARGET_LONG_BITS > TCG_TARGET_REG_BITS);
+ memi = args[memi_idx];
+
+ addr_reg = tcg_out_tlb_load(s, addrlo_idx, memi, sizeop, args,
+ offsetof(CPUTLBEntry, addr_write));
+
+ if (TCG_TARGET_REG_BITS == 32 && sizeop == 3) {
+ /* Reconstruct the full 64-bit value in %g1, using %o2 as temp. */
+ /* ??? Redefine the temps from %i4/%i5 so that we have a o/g temp. */
+ tcg_out_arithi(s, TCG_REG_G1, datalo, 0, SHIFT_SRL);
+ tcg_out_arithi(s, TCG_REG_O2, datahi, 32, SHIFT_SLLX);
+ tcg_out_arith(s, TCG_REG_G1, TCG_REG_G1, TCG_REG_O2, ARITH_OR);
+ datalo = TCG_REG_G1;
+ }
- /* add env, arg1, arg1 */
- tcg_out_arith(s, arg1, TCG_AREG0, arg1, ARITH_ADD);
+ /* The fast path is exactly one insn. Thus we can perform the entire
+ TLB Hit in the (annulled) delay slot of the branch over TLB Miss. */
+ /* beq,a,pt %[xi]cc, label0 */
+ label_ptr = (uint32_t *)s->code_ptr;
+ tcg_out32(s, (INSN_OP(0) | INSN_COND(COND_E, 0) | INSN_OP2(0x1)
+ | ((TARGET_LONG_BITS == 64) << 21)
+ | (1 << 29) | (1 << 19)));
+ /* delay slot */
+ tcg_out_ldst_rr(s, datalo, addr_reg, TCG_REG_O1, qemu_st_opc[sizeop]);
+
+ /* TLB Miss. */
+
+ n = 0;
+ tcg_out_mov(s, TCG_TYPE_PTR, tcg_target_call_iarg_regs[n++], TCG_AREG0);
+ if (TARGET_LONG_BITS > TCG_TARGET_REG_BITS) {
+ tcg_out_mov(s, TCG_TYPE_REG, tcg_target_call_iarg_regs[n++],
+ args[addrlo_idx + 1]);
+ }
+ tcg_out_mov(s, TCG_TYPE_REG, tcg_target_call_iarg_regs[n++],
+ args[addrlo_idx]);
+ if (TCG_TARGET_REG_BITS == 32 && sizeop == 3) {
+ tcg_out_mov(s, TCG_TYPE_REG, tcg_target_call_iarg_regs[n++], datahi);
+ }
+ tcg_out_mov(s, TCG_TYPE_REG, tcg_target_call_iarg_regs[n++], datalo);
- /* ld [arg1], arg2 */
- tcg_out32(s, TARGET_LD_OP | INSN_RD(arg2) | INSN_RS1(arg1) |
- INSN_RS2(TCG_REG_G0));
+ /* Store AREG0 in stack to avoid ugly glibc bugs that mangle
+ global registers */
+ tcg_out_st(s, TCG_TYPE_REG, TCG_AREG0, TCG_REG_CALL_STACK,
+ TCG_TARGET_CALL_STACK_OFFSET - TCG_STATIC_CALL_ARGS_SIZE -
+ sizeof(long));
- /* subcc arg0, arg2, %g0 */
- tcg_out_arith(s, TCG_REG_G0, arg0, arg2, ARITH_SUBCC);
-
- /* will become:
- be label1
- or
- be,pt %xcc label1 */
- label1_ptr = (uint32_t *)s->code_ptr;
- tcg_out32(s, 0);
-
- /* mov (delay slot) */
- tcg_out_mov(s, TCG_TYPE_PTR, arg0, addr_reg);
-
- /* mov */
- tcg_out_mov(s, TCG_TYPE_REG, arg1, data_reg);
-
- /* mov */
- tcg_out_movi(s, TCG_TYPE_I32, arg2, mem_index);
-
- /* XXX/FIXME: suboptimal */
- tcg_out_mov(s, TCG_TYPE_I32, tcg_target_call_iarg_regs[3],
- tcg_target_call_iarg_regs[2]);
- tcg_out_mov(s, TCG_TYPE_I64, tcg_target_call_iarg_regs[2],
- tcg_target_call_iarg_regs[1]);
- tcg_out_mov(s, TCG_TYPE_TL, tcg_target_call_iarg_regs[1],
- tcg_target_call_iarg_regs[0]);
- tcg_out_mov(s, TCG_TYPE_PTR, tcg_target_call_iarg_regs[0],
- TCG_AREG0);
- /* XXX: move that code at the end of the TB */
/* qemu_st_helper[s_bits](arg0, arg1, arg2) */
- tcg_out32(s, CALL | ((((tcg_target_ulong)qemu_st_helpers[s_bits]
+ tcg_out32(s, CALL | ((((tcg_target_ulong)qemu_st_helpers[sizeop]
- (tcg_target_ulong)s->code_ptr) >> 2)
& 0x3fffffff));
- /* Store AREG0 in stack to avoid ugly glibc bugs that mangle
- global registers */
- // delay slot
- tcg_out_ldst(s, TCG_AREG0, TCG_REG_CALL_STACK,
- TCG_TARGET_CALL_STACK_OFFSET - TCG_STATIC_CALL_ARGS_SIZE -
- sizeof(long), HOST_ST_OP);
- tcg_out_ldst(s, TCG_AREG0, TCG_REG_CALL_STACK,
- TCG_TARGET_CALL_STACK_OFFSET - TCG_STATIC_CALL_ARGS_SIZE -
- sizeof(long), HOST_LD_OP);
-
- /* will become:
- ba label2 */
- label2_ptr = (uint32_t *)s->code_ptr;
- tcg_out32(s, 0);
-
- /* nop (delay slot) */
- tcg_out_nop(s);
+ /* delay slot */
+ tcg_out_movi(s, TCG_TYPE_REG, tcg_target_call_iarg_regs[n], memi);
-#if TARGET_LONG_BITS == 32
- /* be label1 */
- *label1_ptr = (INSN_OP(0) | INSN_COND(COND_E, 0) | INSN_OP2(0x2) |
- INSN_OFF22((unsigned long)s->code_ptr -
- (unsigned long)label1_ptr));
-#else
- /* be,pt %xcc label1 */
- *label1_ptr = (INSN_OP(0) | INSN_COND(COND_E, 0) | INSN_OP2(0x1) |
- (0x5 << 19) | INSN_OFF19((unsigned long)s->code_ptr -
- (unsigned long)label1_ptr));
-#endif
-
- /* ld [arg1 + x], arg1 */
- tcg_out_ldst(s, arg1, arg1, offsetof(CPUTLBEntry, addend) -
- offsetof(CPUTLBEntry, addr_write), TARGET_ADDEND_LD_OP);
+ /* Reload AREG0. */
+ tcg_out_ld(s, TCG_TYPE_REG, TCG_AREG0, TCG_REG_CALL_STACK,
+ TCG_TARGET_CALL_STACK_OFFSET - TCG_STATIC_CALL_ARGS_SIZE -
+ sizeof(long));
-#if TARGET_LONG_BITS == 32
- /* and addr_reg, x, arg0 */
- tcg_out_movi(s, TCG_TYPE_I32, TCG_REG_I5, 0xffffffff);
- tcg_out_arith(s, arg0, addr_reg, TCG_REG_I5, ARITH_AND);
- /* add arg0, arg1, arg0 */
- tcg_out_arith(s, arg0, arg0, arg1, ARITH_ADD);
+ *label_ptr |= INSN_OFF19((unsigned long)s->code_ptr -
+ (unsigned long)label_ptr);
#else
- /* add addr_reg, arg1, arg0 */
- tcg_out_arith(s, arg0, addr_reg, arg1, ARITH_ADD);
-#endif
-
-#else
- arg0 = addr_reg;
-#endif
-
- switch(opc) {
- case 0:
- /* stb data_reg, [arg0] */
- tcg_out_ldst(s, data_reg, arg0, 0, STB);
- break;
- case 1:
-#ifdef TARGET_WORDS_BIGENDIAN
- /* sth data_reg, [arg0] */
- tcg_out_ldst(s, data_reg, arg0, 0, STH);
-#else
- /* stha data_reg, [arg0] ASI_PRIMARY_LITTLE */
- tcg_out_ldst_asi(s, data_reg, arg0, 0, STHA, ASI_PRIMARY_LITTLE);
-#endif
- break;
- case 2:
-#ifdef TARGET_WORDS_BIGENDIAN
- /* stw data_reg, [arg0] */
- tcg_out_ldst(s, data_reg, arg0, 0, STW);
-#else
- /* stwa data_reg, [arg0] ASI_PRIMARY_LITTLE */
- tcg_out_ldst_asi(s, data_reg, arg0, 0, STWA, ASI_PRIMARY_LITTLE);
-#endif
- break;
- case 3:
-#ifdef TARGET_WORDS_BIGENDIAN
- /* stx data_reg, [arg0] */
- tcg_out_ldst(s, data_reg, arg0, 0, STX);
-#else
- /* stxa data_reg, [arg0] ASI_PRIMARY_LITTLE */
- tcg_out_ldst_asi(s, data_reg, arg0, 0, STXA, ASI_PRIMARY_LITTLE);
-#endif
- break;
- default:
- tcg_abort();
+ addr_reg = args[addrlo_idx];
+ if (TCG_TARGET_REG_BITS == 64 && TARGET_LONG_BITS == 32) {
+ tcg_out_arithi(s, TCG_REG_I5, addr_reg, 0, SHIFT_SRL);
+ addr_reg = TCG_REG_I5;
}
-
-#if defined(CONFIG_SOFTMMU)
- /* label2: */
- *label2_ptr = (INSN_OP(0) | INSN_COND(COND_A, 0) | INSN_OP2(0x2) |
- INSN_OFF22((unsigned long)s->code_ptr -
- (unsigned long)label2_ptr));
-#endif
+ if (TCG_TARGET_REG_BITS == 32 && sizeop == 3) {
+ /* Reconstruct the full 64-bit value in %g1, using %o2 as temp. */
+ /* ??? Redefine the temps from %i4/%i5 so that we have a o/g temp. */
+ tcg_out_arithi(s, TCG_REG_G1, datalo, 0, SHIFT_SRL);
+ tcg_out_arithi(s, TCG_REG_O2, datahi, 32, SHIFT_SLLX);
+ tcg_out_arith(s, TCG_REG_G1, TCG_REG_G1, TCG_REG_O2, ARITH_OR);
+ datalo = TCG_REG_G1;
+ }
+ tcg_out_ldst_rr(s, datalo, addr_reg, TCG_REG_G0, qemu_st_opc[sizeop]);
+#endif /* CONFIG_SOFTMMU */
}
static inline void tcg_out_op(TCGContext *s, TCGOpcode opc, const TCGArg *args,
@@ -1175,12 +1073,12 @@ static inline void tcg_out_op(TCGContext *s, TCGOpcode opc, const TCGArg *args,
/* Store AREG0 in stack to avoid ugly glibc bugs that mangle
global registers */
// delay slot
- tcg_out_ldst(s, TCG_AREG0, TCG_REG_CALL_STACK,
- TCG_TARGET_CALL_STACK_OFFSET - TCG_STATIC_CALL_ARGS_SIZE -
- sizeof(long), HOST_ST_OP);
- tcg_out_ldst(s, TCG_AREG0, TCG_REG_CALL_STACK,
- TCG_TARGET_CALL_STACK_OFFSET - TCG_STATIC_CALL_ARGS_SIZE -
- sizeof(long), HOST_LD_OP);
+ tcg_out_st(s, TCG_TYPE_REG, TCG_AREG0, TCG_REG_CALL_STACK,
+ TCG_TARGET_CALL_STACK_OFFSET - TCG_STATIC_CALL_ARGS_SIZE -
+ sizeof(long));
+ tcg_out_ld(s, TCG_TYPE_REG, TCG_AREG0, TCG_REG_CALL_STACK,
+ TCG_TARGET_CALL_STACK_OFFSET - TCG_STATIC_CALL_ARGS_SIZE -
+ sizeof(long));
break;
case INDEX_op_jmp:
case INDEX_op_br:
@@ -1348,6 +1246,9 @@ static inline void tcg_out_op(TCGContext *s, TCGOpcode opc, const TCGArg *args,
tcg_out_qemu_ld(s, args, 2 | 4);
break;
#endif
+ case INDEX_op_qemu_ld64:
+ tcg_out_qemu_ld(s, args, 3);
+ break;
case INDEX_op_qemu_st8:
tcg_out_qemu_st(s, args, 0);
break;
@@ -1357,6 +1258,9 @@ static inline void tcg_out_op(TCGContext *s, TCGOpcode opc, const TCGArg *args,
case INDEX_op_qemu_st32:
tcg_out_qemu_st(s, args, 2);
break;
+ case INDEX_op_qemu_st64:
+ tcg_out_qemu_st(s, args, 3);
+ break;
#if TCG_TARGET_REG_BITS == 64
case INDEX_op_movi_i64:
@@ -1421,13 +1325,6 @@ static inline void tcg_out_op(TCGContext *s, TCGOpcode opc, const TCGArg *args,
args[2], const_args[2]);
break;
- case INDEX_op_qemu_ld64:
- tcg_out_qemu_ld(s, args, 3);
- break;
- case INDEX_op_qemu_st64:
- tcg_out_qemu_st(s, args, 3);
- break;
-
#endif
gen_arith:
tcg_out_arithc(s, args[0], args[1], args[2], const_args[2], c);
@@ -1492,20 +1389,6 @@ static const TCGTargetOpDef sparc_op_defs[] = {
{ INDEX_op_mulu2_i32, { "r", "r", "r", "rJ" } },
#endif
- { INDEX_op_qemu_ld8u, { "r", "L" } },
- { INDEX_op_qemu_ld8s, { "r", "L" } },
- { INDEX_op_qemu_ld16u, { "r", "L" } },
- { INDEX_op_qemu_ld16s, { "r", "L" } },
- { INDEX_op_qemu_ld32, { "r", "L" } },
-#if TCG_TARGET_REG_BITS == 64
- { INDEX_op_qemu_ld32u, { "r", "L" } },
- { INDEX_op_qemu_ld32s, { "r", "L" } },
-#endif
-
- { INDEX_op_qemu_st8, { "L", "L" } },
- { INDEX_op_qemu_st16, { "L", "L" } },
- { INDEX_op_qemu_st32, { "L", "L" } },
-
#if TCG_TARGET_REG_BITS == 64
{ INDEX_op_mov_i64, { "r", "r" } },
{ INDEX_op_movi_i64, { "r" } },
@@ -1520,8 +1403,6 @@ static const TCGTargetOpDef sparc_op_defs[] = {
{ INDEX_op_st16_i64, { "r", "r" } },
{ INDEX_op_st32_i64, { "r", "r" } },
{ INDEX_op_st_i64, { "r", "r" } },
- { INDEX_op_qemu_ld64, { "L", "L" } },
- { INDEX_op_qemu_st64, { "L", "L" } },
{ INDEX_op_add_i64, { "r", "r", "rJ" } },
{ INDEX_op_mul_i64, { "r", "r", "rJ" } },
@@ -1548,10 +1429,48 @@ static const TCGTargetOpDef sparc_op_defs[] = {
{ INDEX_op_brcond_i64, { "r", "rJ" } },
{ INDEX_op_setcond_i64, { "r", "r", "rJ" } },
-#else
- { INDEX_op_qemu_ld64, { "L", "L", "L" } },
+#endif
+
+#if TCG_TARGET_REG_BITS == 64
+ { INDEX_op_qemu_ld8u, { "r", "L" } },
+ { INDEX_op_qemu_ld8s, { "r", "L" } },
+ { INDEX_op_qemu_ld16u, { "r", "L" } },
+ { INDEX_op_qemu_ld16s, { "r", "L" } },
+ { INDEX_op_qemu_ld32, { "r", "L" } },
+ { INDEX_op_qemu_ld32u, { "r", "L" } },
+ { INDEX_op_qemu_ld32s, { "r", "L" } },
+ { INDEX_op_qemu_ld64, { "r", "L" } },
+
+ { INDEX_op_qemu_st8, { "L", "L" } },
+ { INDEX_op_qemu_st16, { "L", "L" } },
+ { INDEX_op_qemu_st32, { "L", "L" } },
+ { INDEX_op_qemu_st64, { "L", "L" } },
+#elif TARGET_LONG_BITS <= TCG_TARGET_REG_BITS
+ { INDEX_op_qemu_ld8u, { "r", "L" } },
+ { INDEX_op_qemu_ld8s, { "r", "L" } },
+ { INDEX_op_qemu_ld16u, { "r", "L" } },
+ { INDEX_op_qemu_ld16s, { "r", "L" } },
+ { INDEX_op_qemu_ld32, { "r", "L" } },
+ { INDEX_op_qemu_ld64, { "r", "r", "L" } },
+
+ { INDEX_op_qemu_st8, { "L", "L" } },
+ { INDEX_op_qemu_st16, { "L", "L" } },
+ { INDEX_op_qemu_st32, { "L", "L" } },
{ INDEX_op_qemu_st64, { "L", "L", "L" } },
+#else
+ { INDEX_op_qemu_ld8u, { "r", "L", "L" } },
+ { INDEX_op_qemu_ld8s, { "r", "L", "L" } },
+ { INDEX_op_qemu_ld16u, { "r", "L", "L" } },
+ { INDEX_op_qemu_ld16s, { "r", "L", "L" } },
+ { INDEX_op_qemu_ld32, { "r", "L", "L" } },
+ { INDEX_op_qemu_ld64, { "L", "L", "L", "L" } },
+
+ { INDEX_op_qemu_st8, { "L", "L", "L" } },
+ { INDEX_op_qemu_st16, { "L", "L", "L" } },
+ { INDEX_op_qemu_st32, { "L", "L", "L" } },
+ { INDEX_op_qemu_st64, { "L", "L", "L", "L" } },
#endif
+
{ -1 },
};
--
1.7.12.1

View File

@ -0,0 +1,113 @@
From fecc7bd255206876152baab622c61902133066bd Mon Sep 17 00:00:00 2001
From: Richard Henderson <rth@twiddle.net>
Date: Sat, 24 Mar 2012 22:11:25 +0100
Subject: [PATCH] tcg-sparc: Support GUEST_BASE.
Signed-off-by: Richard Henderson <rth@twiddle.net>
Signed-off-by: Michael Roth <mdroth@linux.vnet.ibm.com>
---
configure | 2 ++
tcg/sparc/tcg-target.c | 26 +++++++++++++++++++++++---
tcg/sparc/tcg-target.h | 2 ++
3 files changed, 27 insertions(+), 3 deletions(-)
diff --git a/configure b/configure
index 0590f16..9139b5c 100755
--- a/configure
+++ b/configure
@@ -872,6 +872,7 @@ case "$cpu" in
if test "$solaris" = "no" ; then
QEMU_CFLAGS="-ffixed-g1 -ffixed-g6 $QEMU_CFLAGS"
fi
+ host_guest_base="yes"
;;
sparc64)
LDFLAGS="-m64 $LDFLAGS"
@@ -880,6 +881,7 @@ case "$cpu" in
if test "$solaris" != "no" ; then
QEMU_CFLAGS="-ffixed-g1 $QEMU_CFLAGS"
fi
+ host_guest_base="yes"
;;
s390)
QEMU_CFLAGS="-m31 -march=z990 $QEMU_CFLAGS"
diff --git a/tcg/sparc/tcg-target.c b/tcg/sparc/tcg-target.c
index d89c19b..5acfeba 100644
--- a/tcg/sparc/tcg-target.c
+++ b/tcg/sparc/tcg-target.c
@@ -59,6 +59,12 @@ static const char * const tcg_target_reg_names[TCG_TARGET_NB_REGS] = {
};
#endif
+#ifdef CONFIG_USE_GUEST_BASE
+# define TCG_GUEST_BASE_REG TCG_REG_I3
+#else
+# define TCG_GUEST_BASE_REG TCG_REG_G0
+#endif
+
static const int tcg_target_reg_alloc_order[] = {
TCG_REG_L0,
TCG_REG_L1,
@@ -680,6 +686,14 @@ static void tcg_target_qemu_prologue(TCGContext *s)
tcg_out32(s, SAVE | INSN_RD(TCG_REG_O6) | INSN_RS1(TCG_REG_O6) |
INSN_IMM13(-(TCG_TARGET_STACK_MINFRAME +
CPU_TEMP_BUF_NLONGS * (int)sizeof(long))));
+
+#ifdef CONFIG_USE_GUEST_BASE
+ if (GUEST_BASE != 0) {
+ tcg_out_movi(s, TCG_TYPE_PTR, TCG_GUEST_BASE_REG, GUEST_BASE);
+ tcg_regset_set_reg(s->reserved_regs, TCG_GUEST_BASE_REG);
+ }
+#endif
+
tcg_out32(s, JMPL | INSN_RD(TCG_REG_G0) | INSN_RS1(TCG_REG_I1) |
INSN_RS2(TCG_REG_G0));
tcg_out_mov(s, TCG_TYPE_PTR, TCG_AREG0, TCG_REG_I0);
@@ -925,14 +939,18 @@ static void tcg_out_qemu_ld(TCGContext *s, const TCGArg *args, int sizeop)
if (TCG_TARGET_REG_BITS == 32 && sizeop == 3) {
int reg64 = (datalo < 16 ? datalo : TCG_REG_O0);
- tcg_out_ldst_rr(s, reg64, addr_reg, TCG_REG_G0, qemu_ld_opc[sizeop]);
+ tcg_out_ldst_rr(s, reg64, addr_reg,
+ (GUEST_BASE ? TCG_GUEST_BASE_REG : TCG_REG_G0),
+ qemu_ld_opc[sizeop]);
tcg_out_arithi(s, datahi, reg64, 32, SHIFT_SRLX);
if (reg64 != datalo) {
tcg_out_mov(s, TCG_TYPE_I32, datalo, reg64);
}
} else {
- tcg_out_ldst_rr(s, datalo, addr_reg, TCG_REG_G0, qemu_ld_opc[sizeop]);
+ tcg_out_ldst_rr(s, datalo, addr_reg,
+ (GUEST_BASE ? TCG_GUEST_BASE_REG : TCG_REG_G0),
+ qemu_ld_opc[sizeop]);
}
#endif /* CONFIG_SOFTMMU */
}
@@ -1026,7 +1044,9 @@ static void tcg_out_qemu_st(TCGContext *s, const TCGArg *args, int sizeop)
tcg_out_arith(s, TCG_REG_G1, TCG_REG_G1, TCG_REG_O2, ARITH_OR);
datalo = TCG_REG_G1;
}
- tcg_out_ldst_rr(s, datalo, addr_reg, TCG_REG_G0, qemu_st_opc[sizeop]);
+ tcg_out_ldst_rr(s, datalo, addr_reg,
+ (GUEST_BASE ? TCG_GUEST_BASE_REG : TCG_REG_G0),
+ qemu_st_opc[sizeop]);
#endif /* CONFIG_SOFTMMU */
}
diff --git a/tcg/sparc/tcg-target.h b/tcg/sparc/tcg-target.h
index adca1d2..99e9f57 100644
--- a/tcg/sparc/tcg-target.h
+++ b/tcg/sparc/tcg-target.h
@@ -128,6 +128,8 @@ typedef enum {
#define TCG_TARGET_HAS_movcond_i64 0
#endif
+#define TCG_TARGET_HAS_GUEST_BASE
+
#ifdef CONFIG_SOLARIS
#define TCG_AREG0 TCG_REG_G2
#elif HOST_LONG_BITS == 64
--
1.7.12.1

View File

@ -0,0 +1,51 @@
From d526285d4339f02e3be64a7287d1e009dd5bff3d Mon Sep 17 00:00:00 2001
From: Richard Henderson <rth@twiddle.net>
Date: Sun, 25 Mar 2012 19:52:11 +0200
Subject: [PATCH] tcg-sparc: Change AREG0 in generated code to %i0.
We can now move the TCG variable from %g[56] to a call-preserved
windowed register.
Signed-off-by: Richard Henderson <rth@twiddle.net>
Signed-off-by: Michael Roth <mdroth@linux.vnet.ibm.com>
---
tcg/sparc/tcg-target.c | 3 ++-
tcg/sparc/tcg-target.h | 8 +-------
2 files changed, 3 insertions(+), 8 deletions(-)
diff --git a/tcg/sparc/tcg-target.c b/tcg/sparc/tcg-target.c
index 5acfeba..9ab5746 100644
--- a/tcg/sparc/tcg-target.c
+++ b/tcg/sparc/tcg-target.c
@@ -696,7 +696,8 @@ static void tcg_target_qemu_prologue(TCGContext *s)
tcg_out32(s, JMPL | INSN_RD(TCG_REG_G0) | INSN_RS1(TCG_REG_I1) |
INSN_RS2(TCG_REG_G0));
- tcg_out_mov(s, TCG_TYPE_PTR, TCG_AREG0, TCG_REG_I0);
+ /* delay slot */
+ tcg_out_nop(s);
}
#if defined(CONFIG_SOFTMMU)
diff --git a/tcg/sparc/tcg-target.h b/tcg/sparc/tcg-target.h
index 99e9f57..ee154d0 100644
--- a/tcg/sparc/tcg-target.h
+++ b/tcg/sparc/tcg-target.h
@@ -130,13 +130,7 @@ typedef enum {
#define TCG_TARGET_HAS_GUEST_BASE
-#ifdef CONFIG_SOLARIS
-#define TCG_AREG0 TCG_REG_G2
-#elif HOST_LONG_BITS == 64
-#define TCG_AREG0 TCG_REG_G5
-#else
-#define TCG_AREG0 TCG_REG_G6
-#endif
+#define TCG_AREG0 TCG_REG_I0
static inline void flush_icache_range(tcg_target_ulong start,
tcg_target_ulong stop)
--
1.7.12.1

View File

@ -0,0 +1,203 @@
From 5767c23140f2c92b899d9caeaa8e08711cb63868 Mon Sep 17 00:00:00 2001
From: Richard Henderson <rth@twiddle.net>
Date: Sun, 25 Mar 2012 21:21:46 +0200
Subject: [PATCH] tcg-sparc: Clean up cruft stemming from attempts to use
global registers.
Don't use -ffixed-gN. Don't link statically. Don't save/restore
AREG0 around calls. Don't allocate space on the stack for AREG0 save.
Signed-off-by: Richard Henderson <rth@twiddle.net>
Signed-off-by: Michael Roth <mdroth@linux.vnet.ibm.com>
---
configure | 12 -----------
tcg/sparc/tcg-target.c | 55 +++++++++++++++++---------------------------------
tcg/sparc/tcg-target.h | 18 +++++++----------
3 files changed, 26 insertions(+), 59 deletions(-)
diff --git a/configure b/configure
index 9139b5c..8ffddf4 100755
--- a/configure
+++ b/configure
@@ -868,19 +868,11 @@ case "$cpu" in
sparc)
LDFLAGS="-m32 $LDFLAGS"
QEMU_CFLAGS="-m32 -mcpu=ultrasparc $QEMU_CFLAGS"
- QEMU_CFLAGS="-ffixed-g2 -ffixed-g3 $QEMU_CFLAGS"
- if test "$solaris" = "no" ; then
- QEMU_CFLAGS="-ffixed-g1 -ffixed-g6 $QEMU_CFLAGS"
- fi
host_guest_base="yes"
;;
sparc64)
LDFLAGS="-m64 $LDFLAGS"
QEMU_CFLAGS="-m64 -mcpu=ultrasparc $QEMU_CFLAGS"
- QEMU_CFLAGS="-ffixed-g5 -ffixed-g6 -ffixed-g7 $QEMU_CFLAGS"
- if test "$solaris" != "no" ; then
- QEMU_CFLAGS="-ffixed-g1 $QEMU_CFLAGS"
- fi
host_guest_base="yes"
;;
s390)
@@ -4055,10 +4047,6 @@ fi
if test "$target_linux_user" = "yes" -o "$target_bsd_user" = "yes" ; then
case "$ARCH" in
- sparc)
- # -static is used to avoid g1/g3 usage by the dynamic linker
- ldflags="$linker_script -static $ldflags"
- ;;
alpha | s390x)
# The default placement of the application is fine.
;;
diff --git a/tcg/sparc/tcg-target.c b/tcg/sparc/tcg-target.c
index 9ab5746..e625aa3 100644
--- a/tcg/sparc/tcg-target.c
+++ b/tcg/sparc/tcg-target.c
@@ -161,7 +161,6 @@ static int target_parse_constraint(TCGArgConstraint *ct, const char **pct_str)
tcg_regset_reset_reg(ct->u.regs, TCG_REG_O0);
tcg_regset_reset_reg(ct->u.regs, TCG_REG_O1);
tcg_regset_reset_reg(ct->u.regs, TCG_REG_O2);
- tcg_regset_reset_reg(ct->u.regs, TCG_REG_O3);
break;
case 'I':
ct->ct |= TCG_CT_CONST_S11;
@@ -681,11 +680,22 @@ static void tcg_out_setcond2_i32(TCGContext *s, TCGCond cond, TCGArg ret,
/* Generate global QEMU prologue and epilogue code */
static void tcg_target_qemu_prologue(TCGContext *s)
{
- tcg_set_frame(s, TCG_REG_I6, TCG_TARGET_CALL_STACK_OFFSET,
- CPU_TEMP_BUF_NLONGS * (int)sizeof(long));
+ int tmp_buf_size, frame_size;
+
+ /* The TCG temp buffer is at the top of the frame, immediately
+ below the frame pointer. */
+ tmp_buf_size = CPU_TEMP_BUF_NLONGS * (int)sizeof(long);
+ tcg_set_frame(s, TCG_REG_I6, TCG_TARGET_STACK_BIAS - tmp_buf_size,
+ tmp_buf_size);
+
+ /* TCG_TARGET_CALL_STACK_OFFSET includes the stack bias, but is
+ otherwise the minimal frame usable by callees. */
+ frame_size = TCG_TARGET_CALL_STACK_OFFSET - TCG_TARGET_STACK_BIAS;
+ frame_size += TCG_STATIC_CALL_ARGS_SIZE + tmp_buf_size;
+ frame_size += TCG_TARGET_STACK_ALIGN - 1;
+ frame_size &= -TCG_TARGET_STACK_ALIGN;
tcg_out32(s, SAVE | INSN_RD(TCG_REG_O6) | INSN_RS1(TCG_REG_O6) |
- INSN_IMM13(-(TCG_TARGET_STACK_MINFRAME +
- CPU_TEMP_BUF_NLONGS * (int)sizeof(long))));
+ INSN_IMM13(-frame_size));
#ifdef CONFIG_USE_GUEST_BASE
if (GUEST_BASE != 0) {
@@ -698,6 +708,8 @@ static void tcg_target_qemu_prologue(TCGContext *s)
INSN_RS2(TCG_REG_G0));
/* delay slot */
tcg_out_nop(s);
+
+ /* No epilogue required. We issue ret + restore directly in the TB. */
}
#if defined(CONFIG_SOFTMMU)
@@ -880,12 +892,6 @@ static void tcg_out_qemu_ld(TCGContext *s, const TCGArg *args, int sizeop)
tcg_out_mov(s, TCG_TYPE_REG, tcg_target_call_iarg_regs[n++],
args[addrlo_idx]);
- /* Store AREG0 in stack to avoid ugly glibc bugs that mangle
- global registers */
- tcg_out_st(s, TCG_TYPE_REG, TCG_AREG0, TCG_REG_CALL_STACK,
- TCG_TARGET_CALL_STACK_OFFSET - TCG_STATIC_CALL_ARGS_SIZE -
- sizeof(long));
-
/* qemu_ld_helper[s_bits](arg0, arg1) */
tcg_out32(s, CALL | ((((tcg_target_ulong)qemu_ld_helpers[s_bits]
- (tcg_target_ulong)s->code_ptr) >> 2)
@@ -893,11 +899,6 @@ static void tcg_out_qemu_ld(TCGContext *s, const TCGArg *args, int sizeop)
/* delay slot */
tcg_out_movi(s, TCG_TYPE_I32, tcg_target_call_iarg_regs[n], memi);
- /* Reload AREG0. */
- tcg_out_ld(s, TCG_TYPE_REG, TCG_AREG0, TCG_REG_CALL_STACK,
- TCG_TARGET_CALL_STACK_OFFSET - TCG_STATIC_CALL_ARGS_SIZE -
- sizeof(long));
-
n = tcg_target_call_oarg_regs[0];
/* datalo = sign_extend(arg0) */
switch (sizeop) {
@@ -1011,12 +1012,6 @@ static void tcg_out_qemu_st(TCGContext *s, const TCGArg *args, int sizeop)
}
tcg_out_mov(s, TCG_TYPE_REG, tcg_target_call_iarg_regs[n++], datalo);
- /* Store AREG0 in stack to avoid ugly glibc bugs that mangle
- global registers */
- tcg_out_st(s, TCG_TYPE_REG, TCG_AREG0, TCG_REG_CALL_STACK,
- TCG_TARGET_CALL_STACK_OFFSET - TCG_STATIC_CALL_ARGS_SIZE -
- sizeof(long));
-
/* qemu_st_helper[s_bits](arg0, arg1, arg2) */
tcg_out32(s, CALL | ((((tcg_target_ulong)qemu_st_helpers[sizeop]
- (tcg_target_ulong)s->code_ptr) >> 2)
@@ -1024,11 +1019,6 @@ static void tcg_out_qemu_st(TCGContext *s, const TCGArg *args, int sizeop)
/* delay slot */
tcg_out_movi(s, TCG_TYPE_REG, tcg_target_call_iarg_regs[n], memi);
- /* Reload AREG0. */
- tcg_out_ld(s, TCG_TYPE_REG, TCG_AREG0, TCG_REG_CALL_STACK,
- TCG_TARGET_CALL_STACK_OFFSET - TCG_STATIC_CALL_ARGS_SIZE -
- sizeof(long));
-
*label_ptr |= INSN_OFF19((unsigned long)s->code_ptr -
(unsigned long)label_ptr);
#else
@@ -1091,15 +1081,8 @@ static inline void tcg_out_op(TCGContext *s, TCGOpcode opc, const TCGArg *args,
tcg_out32(s, JMPL | INSN_RD(TCG_REG_O7) | INSN_RS1(TCG_REG_I5) |
INSN_RS2(TCG_REG_G0));
}
- /* Store AREG0 in stack to avoid ugly glibc bugs that mangle
- global registers */
- // delay slot
- tcg_out_st(s, TCG_TYPE_REG, TCG_AREG0, TCG_REG_CALL_STACK,
- TCG_TARGET_CALL_STACK_OFFSET - TCG_STATIC_CALL_ARGS_SIZE -
- sizeof(long));
- tcg_out_ld(s, TCG_TYPE_REG, TCG_AREG0, TCG_REG_CALL_STACK,
- TCG_TARGET_CALL_STACK_OFFSET - TCG_STATIC_CALL_ARGS_SIZE -
- sizeof(long));
+ /* delay slot */
+ tcg_out_nop(s);
break;
case INDEX_op_jmp:
case INDEX_op_br:
diff --git a/tcg/sparc/tcg-target.h b/tcg/sparc/tcg-target.h
index ee154d0..6314ffb 100644
--- a/tcg/sparc/tcg-target.h
+++ b/tcg/sparc/tcg-target.h
@@ -66,20 +66,16 @@ typedef enum {
#define TCG_CT_CONST_S13 0x200
/* used for function call generation */
-#define TCG_REG_CALL_STACK TCG_REG_I6
+#define TCG_REG_CALL_STACK TCG_REG_O6
#if TCG_TARGET_REG_BITS == 64
-// Reserve space for AREG0
-#define TCG_TARGET_STACK_MINFRAME (176 + 4 * (int)sizeof(long) + \
- TCG_STATIC_CALL_ARGS_SIZE)
-#define TCG_TARGET_CALL_STACK_OFFSET (2047 - 16)
-#define TCG_TARGET_STACK_ALIGN 16
+#define TCG_TARGET_STACK_BIAS 2047
+#define TCG_TARGET_STACK_ALIGN 16
+#define TCG_TARGET_CALL_STACK_OFFSET (128 + 6*8 + TCG_TARGET_STACK_BIAS)
#else
-// AREG0 + one word for alignment
-#define TCG_TARGET_STACK_MINFRAME (92 + (2 + 1) * (int)sizeof(long) + \
- TCG_STATIC_CALL_ARGS_SIZE)
-#define TCG_TARGET_CALL_STACK_OFFSET TCG_TARGET_STACK_MINFRAME
-#define TCG_TARGET_STACK_ALIGN 8
+#define TCG_TARGET_STACK_BIAS 0
+#define TCG_TARGET_STACK_ALIGN 8
+#define TCG_TARGET_CALL_STACK_OFFSET (64 + 4 + 6*4)
#endif
#if TCG_TARGET_REG_BITS == 64
--
1.7.12.1

View File

@ -0,0 +1,62 @@
From 12e60f780a097837840ab1e7bb7d54b8c15112e8 Mon Sep 17 00:00:00 2001
From: Richard Henderson <rth@twiddle.net>
Date: Sun, 25 Mar 2012 21:36:28 +0200
Subject: [PATCH] tcg-sparc: Mask shift immediates to avoid illegal insns.
The xtensa-test image generates a sra_i32 with count 0x40.
Whether this is accident of tcg constant propagation or
originating directly from the instruction stream is immaterial.
Signed-off-by: Richard Henderson <rth@twiddle.net>
Signed-off-by: Michael Roth <mdroth@linux.vnet.ibm.com>
---
tcg/sparc/tcg-target.c | 18 ++++++++++++------
1 file changed, 12 insertions(+), 6 deletions(-)
diff --git a/tcg/sparc/tcg-target.c b/tcg/sparc/tcg-target.c
index e625aa3..be5c170 100644
--- a/tcg/sparc/tcg-target.c
+++ b/tcg/sparc/tcg-target.c
@@ -1154,13 +1154,16 @@ static inline void tcg_out_op(TCGContext *s, TCGOpcode opc, const TCGArg *args,
goto gen_arith;
case INDEX_op_shl_i32:
c = SHIFT_SLL;
- goto gen_arith;
+ do_shift32:
+ /* Limit immediate shift count lest we create an illegal insn. */
+ tcg_out_arithc(s, args[0], args[1], args[2] & 31, const_args[2], c);
+ break;
case INDEX_op_shr_i32:
c = SHIFT_SRL;
- goto gen_arith;
+ goto do_shift32;
case INDEX_op_sar_i32:
c = SHIFT_SRA;
- goto gen_arith;
+ goto do_shift32;
case INDEX_op_mul_i32:
c = ARITH_UMUL;
goto gen_arith;
@@ -1281,13 +1284,16 @@ static inline void tcg_out_op(TCGContext *s, TCGOpcode opc, const TCGArg *args,
break;
case INDEX_op_shl_i64:
c = SHIFT_SLLX;
- goto gen_arith;
+ do_shift64:
+ /* Limit immediate shift count lest we create an illegal insn. */
+ tcg_out_arithc(s, args[0], args[1], args[2] & 63, const_args[2], c);
+ break;
case INDEX_op_shr_i64:
c = SHIFT_SRLX;
- goto gen_arith;
+ goto do_shift64;
case INDEX_op_sar_i64:
c = SHIFT_SRAX;
- goto gen_arith;
+ goto do_shift64;
case INDEX_op_mul_i64:
c = ARITH_MULX;
goto gen_arith;
--
1.7.12.1

View File

@ -0,0 +1,275 @@
From fc9726f880dea515a2cf98456c5f03a1388e4e14 Mon Sep 17 00:00:00 2001
From: Richard Henderson <rth@twiddle.net>
Date: Sun, 25 Mar 2012 22:04:59 +0200
Subject: [PATCH] tcg-sparc: Use defines for temporaries.
And change from %i4/%i5 to %g1/%o7 to remove a v8plus fixme.
Signed-off-by: Richard Henderson <rth@twiddle.net>
Signed-off-by: Michael Roth <mdroth@linux.vnet.ibm.com>
---
tcg/sparc/tcg-target.c | 115 +++++++++++++++++++++++++------------------------
1 file changed, 59 insertions(+), 56 deletions(-)
diff --git a/tcg/sparc/tcg-target.c b/tcg/sparc/tcg-target.c
index be5c170..d401f8e 100644
--- a/tcg/sparc/tcg-target.c
+++ b/tcg/sparc/tcg-target.c
@@ -59,8 +59,12 @@ static const char * const tcg_target_reg_names[TCG_TARGET_NB_REGS] = {
};
#endif
+/* Define some temporary registers. T2 is used for constant generation. */
+#define TCG_REG_T1 TCG_REG_G1
+#define TCG_REG_T2 TCG_REG_O7
+
#ifdef CONFIG_USE_GUEST_BASE
-# define TCG_GUEST_BASE_REG TCG_REG_I3
+# define TCG_GUEST_BASE_REG TCG_REG_I5
#else
# define TCG_GUEST_BASE_REG TCG_REG_G0
#endif
@@ -79,6 +83,7 @@ static const int tcg_target_reg_alloc_order[] = {
TCG_REG_I2,
TCG_REG_I3,
TCG_REG_I4,
+ TCG_REG_I5,
};
static const int tcg_target_call_iarg_regs[6] = {
@@ -366,10 +371,10 @@ static inline void tcg_out_movi(TCGContext *s, TCGType type,
tcg_out_sethi(s, ret, ~arg);
tcg_out_arithi(s, ret, ret, (arg & 0x3ff) | -0x400, ARITH_XOR);
} else {
- tcg_out_movi_imm32(s, TCG_REG_I4, arg >> (TCG_TARGET_REG_BITS / 2));
- tcg_out_arithi(s, TCG_REG_I4, TCG_REG_I4, 32, SHIFT_SLLX);
- tcg_out_movi_imm32(s, ret, arg);
- tcg_out_arith(s, ret, ret, TCG_REG_I4, ARITH_OR);
+ tcg_out_movi_imm32(s, ret, arg >> (TCG_TARGET_REG_BITS / 2));
+ tcg_out_arithi(s, ret, ret, 32, SHIFT_SLLX);
+ tcg_out_movi_imm32(s, TCG_REG_T2, arg);
+ tcg_out_arith(s, ret, ret, TCG_REG_T2, ARITH_OR);
}
}
@@ -386,8 +391,8 @@ static inline void tcg_out_ldst(TCGContext *s, int ret, int addr,
tcg_out32(s, op | INSN_RD(ret) | INSN_RS1(addr) |
INSN_IMM13(offset));
} else {
- tcg_out_movi(s, TCG_TYPE_PTR, TCG_REG_I5, offset);
- tcg_out_ldst_rr(s, ret, addr, TCG_REG_I5, op);
+ tcg_out_movi(s, TCG_TYPE_PTR, TCG_REG_T1, offset);
+ tcg_out_ldst_rr(s, ret, addr, TCG_REG_T1, op);
}
}
@@ -428,8 +433,8 @@ static inline void tcg_out_addi(TCGContext *s, int reg, tcg_target_long val)
if (check_fit_tl(val, 13))
tcg_out_arithi(s, reg, reg, val, ARITH_ADD);
else {
- tcg_out_movi(s, TCG_TYPE_PTR, TCG_REG_I5, val);
- tcg_out_arith(s, reg, reg, TCG_REG_I5, ARITH_ADD);
+ tcg_out_movi(s, TCG_TYPE_PTR, TCG_REG_T1, val);
+ tcg_out_arith(s, reg, reg, TCG_REG_T1, ARITH_ADD);
}
}
}
@@ -441,8 +446,8 @@ static inline void tcg_out_andi(TCGContext *s, int rd, int rs,
if (check_fit_tl(val, 13))
tcg_out_arithi(s, rd, rs, val, ARITH_AND);
else {
- tcg_out_movi(s, TCG_TYPE_I32, TCG_REG_I5, val);
- tcg_out_arith(s, rd, rs, TCG_REG_I5, ARITH_AND);
+ tcg_out_movi(s, TCG_TYPE_I32, TCG_REG_T1, val);
+ tcg_out_arith(s, rd, rs, TCG_REG_T1, ARITH_AND);
}
}
}
@@ -454,8 +459,8 @@ static void tcg_out_div32(TCGContext *s, int rd, int rs1,
if (uns) {
tcg_out_sety(s, TCG_REG_G0);
} else {
- tcg_out_arithi(s, TCG_REG_I5, rs1, 31, SHIFT_SRA);
- tcg_out_sety(s, TCG_REG_I5);
+ tcg_out_arithi(s, TCG_REG_T1, rs1, 31, SHIFT_SRA);
+ tcg_out_sety(s, TCG_REG_T1);
}
tcg_out_arithc(s, rd, rs1, val2, val2const,
@@ -601,8 +606,8 @@ static void tcg_out_setcond_i32(TCGContext *s, TCGCond cond, TCGArg ret,
case TCG_COND_GTU:
case TCG_COND_GEU:
if (c2const && c2 != 0) {
- tcg_out_movi_imm13(s, TCG_REG_I5, c2);
- c2 = TCG_REG_I5;
+ tcg_out_movi_imm13(s, TCG_REG_T1, c2);
+ c2 = TCG_REG_T1;
}
t = c1, c1 = c2, c2 = t, c2const = 0;
cond = tcg_swap_cond(cond);
@@ -649,15 +654,15 @@ static void tcg_out_setcond2_i32(TCGContext *s, TCGCond cond, TCGArg ret,
switch (cond) {
case TCG_COND_EQ:
- tcg_out_setcond_i32(s, TCG_COND_EQ, TCG_REG_I5, al, bl, blconst);
+ tcg_out_setcond_i32(s, TCG_COND_EQ, TCG_REG_T1, al, bl, blconst);
tcg_out_setcond_i32(s, TCG_COND_EQ, ret, ah, bh, bhconst);
- tcg_out_arith(s, ret, ret, TCG_REG_I5, ARITH_AND);
+ tcg_out_arith(s, ret, ret, TCG_REG_T1, ARITH_AND);
break;
case TCG_COND_NE:
- tcg_out_setcond_i32(s, TCG_COND_NE, TCG_REG_I5, al, al, blconst);
+ tcg_out_setcond_i32(s, TCG_COND_NE, TCG_REG_T1, al, al, blconst);
tcg_out_setcond_i32(s, TCG_COND_NE, ret, ah, bh, bhconst);
- tcg_out_arith(s, ret, ret, TCG_REG_I5, ARITH_OR);
+ tcg_out_arith(s, ret, ret, TCG_REG_T1, ARITH_OR);
break;
default:
@@ -935,8 +940,8 @@ static void tcg_out_qemu_ld(TCGContext *s, const TCGArg *args, int sizeop)
#else
addr_reg = args[addrlo_idx];
if (TCG_TARGET_REG_BITS == 64 && TARGET_LONG_BITS == 32) {
- tcg_out_arithi(s, TCG_REG_I5, addr_reg, 0, SHIFT_SRL);
- addr_reg = TCG_REG_I5;
+ tcg_out_arithi(s, TCG_REG_T1, addr_reg, 0, SHIFT_SRL);
+ addr_reg = TCG_REG_T1;
}
if (TCG_TARGET_REG_BITS == 32 && sizeop == 3) {
int reg64 = (datalo < 16 ? datalo : TCG_REG_O0);
@@ -979,12 +984,11 @@ static void tcg_out_qemu_st(TCGContext *s, const TCGArg *args, int sizeop)
offsetof(CPUTLBEntry, addr_write));
if (TCG_TARGET_REG_BITS == 32 && sizeop == 3) {
- /* Reconstruct the full 64-bit value in %g1, using %o2 as temp. */
- /* ??? Redefine the temps from %i4/%i5 so that we have a o/g temp. */
- tcg_out_arithi(s, TCG_REG_G1, datalo, 0, SHIFT_SRL);
+ /* Reconstruct the full 64-bit value. */
+ tcg_out_arithi(s, TCG_REG_T1, datalo, 0, SHIFT_SRL);
tcg_out_arithi(s, TCG_REG_O2, datahi, 32, SHIFT_SLLX);
- tcg_out_arith(s, TCG_REG_G1, TCG_REG_G1, TCG_REG_O2, ARITH_OR);
- datalo = TCG_REG_G1;
+ tcg_out_arith(s, TCG_REG_O2, TCG_REG_T1, TCG_REG_O2, ARITH_OR);
+ datalo = TCG_REG_O2;
}
/* The fast path is exactly one insn. Thus we can perform the entire
@@ -1024,16 +1028,14 @@ static void tcg_out_qemu_st(TCGContext *s, const TCGArg *args, int sizeop)
#else
addr_reg = args[addrlo_idx];
if (TCG_TARGET_REG_BITS == 64 && TARGET_LONG_BITS == 32) {
- tcg_out_arithi(s, TCG_REG_I5, addr_reg, 0, SHIFT_SRL);
- addr_reg = TCG_REG_I5;
+ tcg_out_arithi(s, TCG_REG_T1, addr_reg, 0, SHIFT_SRL);
+ addr_reg = TCG_REG_T1;
}
if (TCG_TARGET_REG_BITS == 32 && sizeop == 3) {
- /* Reconstruct the full 64-bit value in %g1, using %o2 as temp. */
- /* ??? Redefine the temps from %i4/%i5 so that we have a o/g temp. */
- tcg_out_arithi(s, TCG_REG_G1, datalo, 0, SHIFT_SRL);
+ tcg_out_arithi(s, TCG_REG_T1, datalo, 0, SHIFT_SRL);
tcg_out_arithi(s, TCG_REG_O2, datahi, 32, SHIFT_SLLX);
- tcg_out_arith(s, TCG_REG_G1, TCG_REG_G1, TCG_REG_O2, ARITH_OR);
- datalo = TCG_REG_G1;
+ tcg_out_arith(s, TCG_REG_O2, TCG_REG_T1, TCG_REG_O2, ARITH_OR);
+ datalo = TCG_REG_O2;
}
tcg_out_ldst_rr(s, datalo, addr_reg,
(GUEST_BASE ? TCG_GUEST_BASE_REG : TCG_REG_G0),
@@ -1057,28 +1059,29 @@ static inline void tcg_out_op(TCGContext *s, TCGOpcode opc, const TCGArg *args,
case INDEX_op_goto_tb:
if (s->tb_jmp_offset) {
/* direct jump method */
- tcg_out_sethi(s, TCG_REG_I5, args[0] & 0xffffe000);
- tcg_out32(s, JMPL | INSN_RD(TCG_REG_G0) | INSN_RS1(TCG_REG_I5) |
+ tcg_out_sethi(s, TCG_REG_T1, args[0] & 0xffffe000);
+ tcg_out32(s, JMPL | INSN_RD(TCG_REG_G0) | INSN_RS1(TCG_REG_T1) |
INSN_IMM13((args[0] & 0x1fff)));
s->tb_jmp_offset[args[0]] = s->code_ptr - s->code_buf;
} else {
/* indirect jump method */
- tcg_out_ld_ptr(s, TCG_REG_I5, (tcg_target_long)(s->tb_next + args[0]));
- tcg_out32(s, JMPL | INSN_RD(TCG_REG_G0) | INSN_RS1(TCG_REG_I5) |
+ tcg_out_ld_ptr(s, TCG_REG_T1,
+ (tcg_target_long)(s->tb_next + args[0]));
+ tcg_out32(s, JMPL | INSN_RD(TCG_REG_G0) | INSN_RS1(TCG_REG_T1) |
INSN_RS2(TCG_REG_G0));
}
tcg_out_nop(s);
s->tb_next_offset[args[0]] = s->code_ptr - s->code_buf;
break;
case INDEX_op_call:
- if (const_args[0])
+ if (const_args[0]) {
tcg_out32(s, CALL | ((((tcg_target_ulong)args[0]
- (tcg_target_ulong)s->code_ptr) >> 2)
& 0x3fffffff));
- else {
- tcg_out_ld_ptr(s, TCG_REG_I5,
+ } else {
+ tcg_out_ld_ptr(s, TCG_REG_T1,
(tcg_target_long)(s->tb_next + args[0]));
- tcg_out32(s, JMPL | INSN_RD(TCG_REG_O7) | INSN_RS1(TCG_REG_I5) |
+ tcg_out32(s, JMPL | INSN_RD(TCG_REG_O7) | INSN_RS1(TCG_REG_T1) |
INSN_RS2(TCG_REG_G0));
}
/* delay slot */
@@ -1184,11 +1187,11 @@ static inline void tcg_out_op(TCGContext *s, TCGOpcode opc, const TCGArg *args,
case INDEX_op_rem_i32:
case INDEX_op_remu_i32:
- tcg_out_div32(s, TCG_REG_I5, args[1], args[2], const_args[2],
+ tcg_out_div32(s, TCG_REG_T1, args[1], args[2], const_args[2],
opc == INDEX_op_remu_i32);
- tcg_out_arithc(s, TCG_REG_I5, TCG_REG_I5, args[2], const_args[2],
+ tcg_out_arithc(s, TCG_REG_T1, TCG_REG_T1, args[2], const_args[2],
ARITH_UMUL);
- tcg_out_arith(s, args[0], args[1], TCG_REG_I5, ARITH_SUB);
+ tcg_out_arith(s, args[0], args[1], TCG_REG_T1, ARITH_SUB);
break;
case INDEX_op_brcond_i32:
@@ -1305,11 +1308,11 @@ static inline void tcg_out_op(TCGContext *s, TCGOpcode opc, const TCGArg *args,
goto gen_arith;
case INDEX_op_rem_i64:
case INDEX_op_remu_i64:
- tcg_out_arithc(s, TCG_REG_I5, args[1], args[2], const_args[2],
+ tcg_out_arithc(s, TCG_REG_T1, args[1], args[2], const_args[2],
opc == INDEX_op_rem_i64 ? ARITH_SDIVX : ARITH_UDIVX);
- tcg_out_arithc(s, TCG_REG_I5, TCG_REG_I5, args[2], const_args[2],
+ tcg_out_arithc(s, TCG_REG_T1, TCG_REG_T1, args[2], const_args[2],
ARITH_MULX);
- tcg_out_arith(s, args[0], args[1], TCG_REG_I5, ARITH_SUB);
+ tcg_out_arith(s, args[0], args[1], TCG_REG_T1, ARITH_SUB);
break;
case INDEX_op_ext32s_i64:
if (const_args[1]) {
@@ -1507,15 +1510,15 @@ static void tcg_target_init(TCGContext *s)
(1 << TCG_REG_O7));
tcg_regset_clear(s->reserved_regs);
- tcg_regset_set_reg(s->reserved_regs, TCG_REG_G0);
-#if TCG_TARGET_REG_BITS == 64
- tcg_regset_set_reg(s->reserved_regs, TCG_REG_I4); // for internal use
-#endif
- tcg_regset_set_reg(s->reserved_regs, TCG_REG_I5); // for internal use
- tcg_regset_set_reg(s->reserved_regs, TCG_REG_I6);
- tcg_regset_set_reg(s->reserved_regs, TCG_REG_I7);
- tcg_regset_set_reg(s->reserved_regs, TCG_REG_O6);
- tcg_regset_set_reg(s->reserved_regs, TCG_REG_O7);
+ tcg_regset_set_reg(s->reserved_regs, TCG_REG_G0); /* zero */
+ tcg_regset_set_reg(s->reserved_regs, TCG_REG_G6); /* reserved for os */
+ tcg_regset_set_reg(s->reserved_regs, TCG_REG_G7); /* thread pointer */
+ tcg_regset_set_reg(s->reserved_regs, TCG_REG_I6); /* frame pointer */
+ tcg_regset_set_reg(s->reserved_regs, TCG_REG_I7); /* return address */
+ tcg_regset_set_reg(s->reserved_regs, TCG_REG_O6); /* stack pointer */
+ tcg_regset_set_reg(s->reserved_regs, TCG_REG_T1); /* for internal use */
+ tcg_regset_set_reg(s->reserved_regs, TCG_REG_T2); /* for internal use */
+
tcg_add_target_add_op_defs(sparc_op_defs);
}
--
1.7.12.1

View File

@ -0,0 +1,44 @@
From ca72cdf648b56d851c4bc9145a1abfcbeeec0579 Mon Sep 17 00:00:00 2001
From: Richard Henderson <rth@twiddle.net>
Date: Sun, 25 Mar 2012 22:43:17 +0200
Subject: [PATCH] tcg-sparc: Add %g/%o registers to alloc_order
Signed-off-by: Richard Henderson <rth@twiddle.net>
Signed-off-by: Michael Roth <mdroth@linux.vnet.ibm.com>
---
tcg/sparc/tcg-target.c | 13 +++++++++++++
1 file changed, 13 insertions(+)
diff --git a/tcg/sparc/tcg-target.c b/tcg/sparc/tcg-target.c
index d401f8e..03c385a 100644
--- a/tcg/sparc/tcg-target.c
+++ b/tcg/sparc/tcg-target.c
@@ -78,12 +78,25 @@ static const int tcg_target_reg_alloc_order[] = {
TCG_REG_L5,
TCG_REG_L6,
TCG_REG_L7,
+
TCG_REG_I0,
TCG_REG_I1,
TCG_REG_I2,
TCG_REG_I3,
TCG_REG_I4,
TCG_REG_I5,
+
+ TCG_REG_G2,
+ TCG_REG_G3,
+ TCG_REG_G4,
+ TCG_REG_G5,
+
+ TCG_REG_O0,
+ TCG_REG_O1,
+ TCG_REG_O2,
+ TCG_REG_O3,
+ TCG_REG_O4,
+ TCG_REG_O5,
};
static const int tcg_target_call_iarg_regs[6] = {
--
1.7.12.1

View File

@ -0,0 +1,79 @@
From 1338a6f18ff9b651c12ee1f7edd1d2b7684bd6aa Mon Sep 17 00:00:00 2001
From: Richard Henderson <rth@twiddle.net>
Date: Fri, 21 Sep 2012 10:48:51 -0700
Subject: [PATCH] tcg-sparc: Fix and enable direct TB chaining.
Signed-off-by: Richard Henderson <rth@twiddle.net>
Signed-off-by: Michael Roth <mdroth@linux.vnet.ibm.com>
---
exec-all.h | 9 ++++++---
tcg/sparc/tcg-target.c | 21 ++++++++++++++++++---
2 files changed, 24 insertions(+), 6 deletions(-)
diff --git a/exec-all.h b/exec-all.h
index c5d3a13..1f81da7 100644
--- a/exec-all.h
+++ b/exec-all.h
@@ -132,9 +132,10 @@ static inline void tlb_flush(CPUArchState *env, int flush_global)
#define CODE_GEN_AVG_BLOCK_SIZE 64
#endif
-#if defined(_ARCH_PPC) || defined(__x86_64__) || defined(__arm__) || defined(__i386__)
-#define USE_DIRECT_JUMP
-#elif defined(CONFIG_TCG_INTERPRETER)
+#if defined(__arm__) || defined(_ARCH_PPC) \
+ || defined(__x86_64__) || defined(__i386__) \
+ || defined(__sparc__) \
+ || defined(CONFIG_TCG_INTERPRETER)
#define USE_DIRECT_JUMP
#endif
@@ -244,6 +245,8 @@ static inline void tb_set_jmp_target1(uintptr_t jmp_addr, uintptr_t addr)
__asm __volatile__ ("swi 0x9f0002" : : "r" (_beg), "r" (_end), "r" (_flg));
#endif
}
+#elif defined(__sparc__)
+void tb_set_jmp_target1(uintptr_t jmp_addr, uintptr_t addr);
#else
#error tb_set_jmp_target1 is missing
#endif
diff --git a/tcg/sparc/tcg-target.c b/tcg/sparc/tcg-target.c
index 03c385a..1db0c9d 100644
--- a/tcg/sparc/tcg-target.c
+++ b/tcg/sparc/tcg-target.c
@@ -1072,10 +1072,10 @@ static inline void tcg_out_op(TCGContext *s, TCGOpcode opc, const TCGArg *args,
case INDEX_op_goto_tb:
if (s->tb_jmp_offset) {
/* direct jump method */
- tcg_out_sethi(s, TCG_REG_T1, args[0] & 0xffffe000);
- tcg_out32(s, JMPL | INSN_RD(TCG_REG_G0) | INSN_RS1(TCG_REG_T1) |
- INSN_IMM13((args[0] & 0x1fff)));
+ uint32_t old_insn = *(uint32_t *)s->code_ptr;
s->tb_jmp_offset[args[0]] = s->code_ptr - s->code_buf;
+ /* Make sure to preserve links during retranslation. */
+ tcg_out32(s, CALL | (old_insn & ~INSN_OP(-1)));
} else {
/* indirect jump method */
tcg_out_ld_ptr(s, TCG_REG_T1,
@@ -1595,3 +1595,18 @@ void tcg_register_jit(void *buf, size_t buf_size)
tcg_register_jit_int(buf, buf_size, &debug_frame, sizeof(debug_frame));
}
+
+void tb_set_jmp_target1(uintptr_t jmp_addr, uintptr_t addr)
+{
+ uint32_t *ptr = (uint32_t *)jmp_addr;
+ tcg_target_long disp = (tcg_target_long)(addr - jmp_addr) >> 2;
+
+ /* We can reach the entire address space for 32-bit. For 64-bit
+ the code_gen_buffer can't be larger than 2GB. */
+ if (TCG_TARGET_REG_BITS == 64 && !check_fit_tl(disp, 30)) {
+ tcg_abort();
+ }
+
+ *ptr = CALL | (disp & 0x3fffffff);
+ flush_icache_range(jmp_addr, jmp_addr + 4);
+}
--
1.7.12.1

View File

@ -0,0 +1,60 @@
From 2cbc27913eb9eb7cdc4a41fc6efafccf3db7ebe6 Mon Sep 17 00:00:00 2001
From: Richard Henderson <rth@twiddle.net>
Date: Fri, 21 Sep 2012 11:00:23 -0700
Subject: [PATCH] tcg-sparc: Preserve branch destinations during retranslation
Signed-off-by: Richard Henderson <rth@twiddle.net>
Signed-off-by: Michael Roth <mdroth@linux.vnet.ibm.com>
---
tcg/sparc/tcg-target.c | 19 +++++++++++--------
1 file changed, 11 insertions(+), 8 deletions(-)
diff --git a/tcg/sparc/tcg-target.c b/tcg/sparc/tcg-target.c
index 1db0c9d..876da4f 100644
--- a/tcg/sparc/tcg-target.c
+++ b/tcg/sparc/tcg-target.c
@@ -488,30 +488,33 @@ static inline void tcg_out_nop(TCGContext *s)
static void tcg_out_branch_i32(TCGContext *s, int opc, int label_index)
{
TCGLabel *l = &s->labels[label_index];
+ uint32_t off22;
if (l->has_value) {
- tcg_out32(s, (INSN_OP(0) | INSN_COND(opc, 0) | INSN_OP2(0x2)
- | INSN_OFF22(l->u.value - (unsigned long)s->code_ptr)));
+ off22 = INSN_OFF22(l->u.value - (unsigned long)s->code_ptr);
} else {
+ /* Make sure to preserve destinations during retranslation. */
+ off22 = *(uint32_t *)s->code_ptr & INSN_OFF22(-1);
tcg_out_reloc(s, s->code_ptr, R_SPARC_WDISP22, label_index, 0);
- tcg_out32(s, (INSN_OP(0) | INSN_COND(opc, 0) | INSN_OP2(0x2) | 0));
}
+ tcg_out32(s, INSN_OP(0) | INSN_COND(opc, 0) | INSN_OP2(0x2) | off22);
}
#if TCG_TARGET_REG_BITS == 64
static void tcg_out_branch_i64(TCGContext *s, int opc, int label_index)
{
TCGLabel *l = &s->labels[label_index];
+ uint32_t off19;
if (l->has_value) {
- tcg_out32(s, (INSN_OP(0) | INSN_COND(opc, 0) | INSN_OP2(0x1) |
- (0x5 << 19) |
- INSN_OFF19(l->u.value - (unsigned long)s->code_ptr)));
+ off19 = INSN_OFF19(l->u.value - (unsigned long)s->code_ptr);
} else {
+ /* Make sure to preserve destinations during retranslation. */
+ off19 = *(uint32_t *)s->code_ptr & INSN_OFF19(-1);
tcg_out_reloc(s, s->code_ptr, R_SPARC_WDISP19, label_index, 0);
- tcg_out32(s, (INSN_OP(0) | INSN_COND(opc, 0) | INSN_OP2(0x1) |
- (0x5 << 19) | 0));
}
+ tcg_out32(s, (INSN_OP(0) | INSN_COND(opc, 0) | INSN_OP2(0x1) |
+ (0x5 << 19) | off19));
}
#endif
--
1.7.12.1

View File

@ -0,0 +1,33 @@
From fcf8cef0c7d8d197e863c1e8b7bcb567fa1fe729 Mon Sep 17 00:00:00 2001
From: Richard Henderson <rth@twiddle.net>
Date: Fri, 21 Sep 2012 14:15:36 +0200
Subject: [PATCH] target-alpha: Initialize env->cpu_model_str
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
Save the cpu_model_str so that we have a non-null value when
creating a new cpu during clone.
Signed-off-by: Richard Henderson <rth@twiddle.net>
Signed-off-by: Andreas Färber <afaerber@suse.de>
Signed-off-by: Michael Roth <mdroth@linux.vnet.ibm.com>
---
target-alpha/translate.c | 1 +
1 file changed, 1 insertion(+)
diff --git a/target-alpha/translate.c b/target-alpha/translate.c
index 4a9011a..3f9aee1 100644
--- a/target-alpha/translate.c
+++ b/target-alpha/translate.c
@@ -3543,6 +3543,7 @@ CPUAlphaState * cpu_alpha_init (const char *cpu_model)
}
env->implver = implver;
env->amask = amask;
+ env->cpu_model_str = cpu_model;
qemu_init_vcpu(env);
return env;
--
1.7.12.1

View File

@ -0,0 +1,93 @@
From 66588d01b8cb710d746c249a34f31f7f353bc697 Mon Sep 17 00:00:00 2001
From: Aurelien Jarno <aurelien@aurel32.net>
Date: Sat, 22 Sep 2012 23:08:38 +0200
Subject: [PATCH] tcg/mips: fix MIPS32(R2) detection
Fix the MIPS32(R2) cpu detection so that it also works with
-march=octeon. Thanks to Andrew Pinski for the hint.
Cc: Andrew Pinski <apinski@cavium.com>
Signed-off-by: Aurelien Jarno <aurelien@aurel32.net>
Signed-off-by: Michael Roth <mdroth@linux.vnet.ibm.com>
---
tcg/mips/tcg-target.c | 10 +++++-----
tcg/mips/tcg-target.h | 8 ++++----
2 files changed, 9 insertions(+), 9 deletions(-)
diff --git a/tcg/mips/tcg-target.c b/tcg/mips/tcg-target.c
index c272b38..e9a1ffb 100644
--- a/tcg/mips/tcg-target.c
+++ b/tcg/mips/tcg-target.c
@@ -425,7 +425,7 @@ static inline void tcg_out_movi(TCGContext *s, TCGType type,
static inline void tcg_out_bswap16(TCGContext *s, TCGReg ret, TCGReg arg)
{
-#ifdef _MIPS_ARCH_MIPS32R2
+#if defined(__mips_isa_rev) && (__mips_isa_rev >= 2)
tcg_out_opc_reg(s, OPC_WSBH, ret, 0, arg);
#else
/* ret and arg can't be register at */
@@ -442,7 +442,7 @@ static inline void tcg_out_bswap16(TCGContext *s, TCGReg ret, TCGReg arg)
static inline void tcg_out_bswap16s(TCGContext *s, TCGReg ret, TCGReg arg)
{
-#ifdef _MIPS_ARCH_MIPS32R2
+#if defined(__mips_isa_rev) && (__mips_isa_rev >= 2)
tcg_out_opc_reg(s, OPC_WSBH, ret, 0, arg);
tcg_out_opc_reg(s, OPC_SEH, ret, 0, ret);
#else
@@ -460,7 +460,7 @@ static inline void tcg_out_bswap16s(TCGContext *s, TCGReg ret, TCGReg arg)
static inline void tcg_out_bswap32(TCGContext *s, TCGReg ret, TCGReg arg)
{
-#ifdef _MIPS_ARCH_MIPS32R2
+#if defined(__mips_isa_rev) && (__mips_isa_rev >= 2)
tcg_out_opc_reg(s, OPC_WSBH, ret, 0, arg);
tcg_out_opc_sa(s, OPC_ROTR, ret, ret, 16);
#else
@@ -486,7 +486,7 @@ static inline void tcg_out_bswap32(TCGContext *s, TCGReg ret, TCGReg arg)
static inline void tcg_out_ext8s(TCGContext *s, TCGReg ret, TCGReg arg)
{
-#ifdef _MIPS_ARCH_MIPS32R2
+#if defined(__mips_isa_rev) && (__mips_isa_rev >= 2)
tcg_out_opc_reg(s, OPC_SEB, ret, 0, arg);
#else
tcg_out_opc_sa(s, OPC_SLL, ret, arg, 24);
@@ -496,7 +496,7 @@ static inline void tcg_out_ext8s(TCGContext *s, TCGReg ret, TCGReg arg)
static inline void tcg_out_ext16s(TCGContext *s, TCGReg ret, TCGReg arg)
{
-#ifdef _MIPS_ARCH_MIPS32R2
+#if defined(__mips_isa_rev) && (__mips_isa_rev >= 2)
tcg_out_opc_reg(s, OPC_SEH, ret, 0, arg);
#else
tcg_out_opc_sa(s, OPC_SLL, ret, arg, 16);
diff --git a/tcg/mips/tcg-target.h b/tcg/mips/tcg-target.h
index d147e70..7020d65 100644
--- a/tcg/mips/tcg-target.h
+++ b/tcg/mips/tcg-target.h
@@ -88,16 +88,16 @@ typedef enum {
#define TCG_TARGET_HAS_nand_i32 0
/* optional instructions only implemented on MIPS4, MIPS32 and Loongson 2 */
-#if defined(_MIPS_ARCH_MIPS4) || defined(_MIPS_ARCH_MIPS32) || \
- defined(_MIPS_ARCH_MIPS32R2) || defined(_MIPS_ARCH_LOONGSON2E) || \
- defined(_MIPS_ARCH_LOONGSON2F)
+#if (defined(__mips_isa_rev) && (__mips_isa_rev >= 1)) || \
+ defined(_MIPS_ARCH_LOONGSON2E) || defined(_MIPS_ARCH_LOONGSON2F) || \
+ defined(_MIPS_ARCH_MIPS4)
#define TCG_TARGET_HAS_movcond_i32 1
#else
#define TCG_TARGET_HAS_movcond_i32 0
#endif
/* optional instructions only implemented on MIPS32R2 */
-#ifdef _MIPS_ARCH_MIPS32R2
+#if defined(__mips_isa_rev) && (__mips_isa_rev >= 2)
#define TCG_TARGET_HAS_bswap16_i32 1
#define TCG_TARGET_HAS_bswap32_i32 1
#define TCG_TARGET_HAS_rot_i32 1
--
1.7.12.1

View File

@ -0,0 +1,67 @@
From a2c90b264762d3ddcc9a830653315a6fe9107055 Mon Sep 17 00:00:00 2001
From: Richard Henderson <rth@twiddle.net>
Date: Fri, 21 Sep 2012 17:18:09 -0700
Subject: [PATCH] tcg: Adjust descriptions of *cond opcodes
The README file documented the operand ordering of the tcg_gen_*
functions. Since we're documenting opcodes here, use the true
operand ordering.
Signed-off-by: Richard Henderson <rth@twiddle.net>
Cc: malc <av1474@comtv.ru>
Signed-off-by: Aurelien Jarno <aurelien@aurel32.net>
Signed-off-by: Michael Roth <mdroth@linux.vnet.ibm.com>
---
tcg/README | 10 +++++-----
1 file changed, 5 insertions(+), 5 deletions(-)
diff --git a/tcg/README b/tcg/README
index 33783ee..27846f1 100644
--- a/tcg/README
+++ b/tcg/README
@@ -141,7 +141,7 @@ Define label 'label' at the current program point.
Jump to label.
-* brcond_i32/i64 cond, t0, t1, label
+* brcond_i32/i64 t0, t1, cond, label
Conditional jump if t0 cond t1 is true. cond can be:
TCG_COND_EQ
@@ -301,13 +301,13 @@ This operation would be equivalent to
********* Conditional moves
-* setcond_i32/i64 cond, dest, t1, t2
+* setcond_i32/i64 dest, t1, t2, cond
dest = (t1 cond t2)
Set DEST to 1 if (T1 cond T2) is true, otherwise set to 0.
-* movcond_i32/i64 cond, dest, c1, c2, v1, v2
+* movcond_i32/i64 dest, c1, c2, v1, v2, cond
dest = (c1 cond c2 ? v1 : v2)
@@ -360,7 +360,7 @@ The following opcodes are internal to TCG. Thus they are to be implemented by
32-bit host code generators, but are not to be emitted by guest translators.
They are emitted as needed by inline functions within "tcg-op.h".
-* brcond2_i32 cond, t0_low, t0_high, t1_low, t1_high, label
+* brcond2_i32 t0_low, t0_high, t1_low, t1_high, cond, label
Similar to brcond, except that the 64-bit values T0 and T1
are formed from two 32-bit arguments.
@@ -377,7 +377,7 @@ is returned in two 32-bit outputs.
Similar to mul, except two 32-bit (unsigned) inputs T1 and T2 yielding
the full 64-bit product T0. The later is returned in two 32-bit outputs.
-* setcond2_i32 cond, dest, t1_low, t1_high, t2_low, t2_high
+* setcond2_i32 dest, t1_low, t1_high, t2_low, t2_high, cond
Similar to setcond, except that the 64-bit values T1 and T2 are
formed from two 32-bit arguments. The result is a 32-bit value.
--
1.7.12.1

View File

@ -0,0 +1,34 @@
From 5d3868bb343df0c13240521e36d0cc942c7a2d04 Mon Sep 17 00:00:00 2001
From: Aurelien Jarno <aurelien@aurel32.net>
Date: Wed, 26 Sep 2012 00:30:12 +0200
Subject: [PATCH] tcg/i386: fix build with -march < i686
The movcond_i32 op has to be protected with TCG_TARGET_HAS_movcond_i32
to fix the build with -march < i686.
Thanks to Richard Henderson for the hint.
Reported-by: Alex Barcelo <abarcelo@ac.upc.edu>
Signed-off-by: Aurelien Jarno <aurelien@aurel32.net>
Signed-off-by: Michael Roth <mdroth@linux.vnet.ibm.com>
---
tcg/i386/tcg-target.c | 2 ++
1 file changed, 2 insertions(+)
diff --git a/tcg/i386/tcg-target.c b/tcg/i386/tcg-target.c
index 85c6b81..616ef23 100644
--- a/tcg/i386/tcg-target.c
+++ b/tcg/i386/tcg-target.c
@@ -1907,7 +1907,9 @@ static const TCGTargetOpDef x86_op_defs[] = {
{ INDEX_op_setcond_i32, { "q", "r", "ri" } },
{ INDEX_op_deposit_i32, { "Q", "0", "Q" } },
+#if TCG_TARGET_HAS_movcond_i32
{ INDEX_op_movcond_i32, { "r", "r", "ri", "r", "0" } },
+#endif
#if TCG_TARGET_REG_BITS == 32
{ INDEX_op_mulu2_i32, { "a", "d", "a", "r" } },
--
1.7.12.1

View File

@ -0,0 +1,52 @@
From 86aeba1e72542270a2ae2570cdfcfa6b9e59eeb8 Mon Sep 17 00:00:00 2001
From: Stefan Weil <sw@weilnetz.de>
Date: Wed, 12 Sep 2012 19:18:55 +0200
Subject: [PATCH] tcg: Fix MAX_OPC_PARAM_IARGS
DEF_HELPER_FLAGS_5 was added some time ago without adjusting
MAX_OPC_PARAM_IARGS.
Fixing the definition becomes more important as QEMU is using
an increasing number of helper functions called with 5 arguments.
Add also a comment to avoid future problems when DEF_HELPER_FLAGS_6
will be added.
Signed-off-by: Stefan Weil <sw@weilnetz.de>
Reviewed-by: Richard Henderson <rth@twiddle.net>
Signed-off-by: Blue Swirl <blauwirbel@gmail.com>
Signed-off-by: Michael Roth <mdroth@linux.vnet.ibm.com>
---
def-helper.h | 2 ++
exec-all.h | 2 +-
2 files changed, 3 insertions(+), 1 deletion(-)
diff --git a/def-helper.h b/def-helper.h
index b98ff69..022a9ce 100644
--- a/def-helper.h
+++ b/def-helper.h
@@ -128,6 +128,8 @@
#define DEF_HELPER_5(name, ret, t1, t2, t3, t4, t5) \
DEF_HELPER_FLAGS_5(name, 0, ret, t1, t2, t3, t4, t5)
+/* MAX_OPC_PARAM_IARGS must be set to n if last entry is DEF_HELPER_FLAGS_n. */
+
#endif /* DEF_HELPER_H */
#ifndef GEN_HELPER
diff --git a/exec-all.h b/exec-all.h
index 1f81da7..6516da0 100644
--- a/exec-all.h
+++ b/exec-all.h
@@ -51,7 +51,7 @@ typedef struct TranslationBlock TranslationBlock;
#else
#define MAX_OPC_PARAM_PER_ARG 1
#endif
-#define MAX_OPC_PARAM_IARGS 4
+#define MAX_OPC_PARAM_IARGS 5
#define MAX_OPC_PARAM_OARGS 1
#define MAX_OPC_PARAM_ARGS (MAX_OPC_PARAM_IARGS + MAX_OPC_PARAM_OARGS)
--
1.7.12.1

View File

@ -0,0 +1,119 @@
From 2acbc7d596b022dca4fc147eb89e3d5f297acb1f Mon Sep 17 00:00:00 2001
From: Stefan Weil <sw@weilnetz.de>
Date: Tue, 18 Sep 2012 22:43:38 +0200
Subject: [PATCH] tci: Fix for AREG0 free mode
Support for helper functions with 5 arguments was missing
in the code generator and in the interpreter.
There is no need to pass the constant TCG_AREG0 from the
code generator to the interpreter. Remove that code for
the INDEX_op_qemu_st* opcodes.
Signed-off-by: Stefan Weil <sw@weilnetz.de>
Signed-off-by: Aurelien Jarno <aurelien@aurel32.net>
Signed-off-by: Michael Roth <mdroth@linux.vnet.ibm.com>
---
tcg/tci/tcg-target.c | 10 +++++-----
tci.c | 13 +++++++++----
2 files changed, 14 insertions(+), 9 deletions(-)
diff --git a/tcg/tci/tcg-target.c b/tcg/tci/tcg-target.c
index 003244c..c8c2f1d 100644
--- a/tcg/tci/tcg-target.c
+++ b/tcg/tci/tcg-target.c
@@ -300,7 +300,7 @@ static const int tcg_target_reg_alloc_order[] = {
#endif
};
-#if MAX_OPC_PARAM_IARGS != 4
+#if MAX_OPC_PARAM_IARGS != 5
# error Fix needed, number of supported input arguments changed!
#endif
@@ -309,16 +309,18 @@ static const int tcg_target_call_iarg_regs[] = {
TCG_REG_R1,
TCG_REG_R2,
TCG_REG_R3,
-#if TCG_TARGET_REG_BITS == 32
- /* 32 bit hosts need 2 * MAX_OPC_PARAM_IARGS registers. */
#if 0 /* used for TCG_REG_CALL_STACK */
TCG_REG_R4,
#endif
TCG_REG_R5,
+#if TCG_TARGET_REG_BITS == 32
+ /* 32 bit hosts need 2 * MAX_OPC_PARAM_IARGS registers. */
TCG_REG_R6,
TCG_REG_R7,
#if TCG_TARGET_NB_REGS >= 16
TCG_REG_R8,
+ TCG_REG_R9,
+ TCG_REG_R10,
#else
# error Too few input registers available
#endif
@@ -798,7 +800,6 @@ static void tcg_out_op(TCGContext *s, TCGOpcode opc, const TCGArg *args,
case INDEX_op_qemu_st8:
case INDEX_op_qemu_st16:
case INDEX_op_qemu_st32:
- tcg_out_r(s, TCG_AREG0);
tcg_out_r(s, *args++);
tcg_out_r(s, *args++);
#if TARGET_LONG_BITS > TCG_TARGET_REG_BITS
@@ -809,7 +810,6 @@ static void tcg_out_op(TCGContext *s, TCGOpcode opc, const TCGArg *args,
#endif
break;
case INDEX_op_qemu_st64:
- tcg_out_r(s, TCG_AREG0);
tcg_out_r(s, *args++);
#if TCG_TARGET_REG_BITS == 32
tcg_out_r(s, *args++);
diff --git a/tci.c b/tci.c
index ce8a988..a4f7b78 100644
--- a/tci.c
+++ b/tci.c
@@ -36,17 +36,19 @@
tcg_abort(); \
} while (0)
-#if MAX_OPC_PARAM_IARGS != 4
+#if MAX_OPC_PARAM_IARGS != 5
# error Fix needed, number of supported input arguments changed!
#endif
#if TCG_TARGET_REG_BITS == 32
typedef uint64_t (*helper_function)(tcg_target_ulong, tcg_target_ulong,
tcg_target_ulong, tcg_target_ulong,
tcg_target_ulong, tcg_target_ulong,
+ tcg_target_ulong, tcg_target_ulong,
tcg_target_ulong, tcg_target_ulong);
#else
typedef uint64_t (*helper_function)(tcg_target_ulong, tcg_target_ulong,
- tcg_target_ulong, tcg_target_ulong);
+ tcg_target_ulong, tcg_target_ulong,
+ tcg_target_ulong);
#endif
/* TCI can optionally use a global register variable for env. */
@@ -489,14 +491,17 @@ tcg_target_ulong tcg_qemu_tb_exec(CPUArchState *cpustate, uint8_t *tb_ptr)
tci_read_reg(TCG_REG_R5),
tci_read_reg(TCG_REG_R6),
tci_read_reg(TCG_REG_R7),
- tci_read_reg(TCG_REG_R8));
+ tci_read_reg(TCG_REG_R8),
+ tci_read_reg(TCG_REG_R9),
+ tci_read_reg(TCG_REG_R10));
tci_write_reg(TCG_REG_R0, tmp64);
tci_write_reg(TCG_REG_R1, tmp64 >> 32);
#else
tmp64 = ((helper_function)t0)(tci_read_reg(TCG_REG_R0),
tci_read_reg(TCG_REG_R1),
tci_read_reg(TCG_REG_R2),
- tci_read_reg(TCG_REG_R3));
+ tci_read_reg(TCG_REG_R3),
+ tci_read_reg(TCG_REG_R5));
tci_write_reg(TCG_REG_R0, tmp64);
#endif
break;
--
1.7.12.1

Some files were not shown because too many files have changed in this diff Show More