* [Qemu-devel] [PATCH] fix gcc warnings when RESERVED_VA is 0
@ 2012-09-16 0:05 Mike Frysinger
2012-09-16 9:58 ` Peter Maydell
0 siblings, 1 reply; 28+ messages in thread
From: Mike Frysinger @ 2012-09-16 0:05 UTC (permalink / raw)
To: qemu-devel
The current code, while correct, triggers a bunch of gcc warnings when
RESERVED_VA is 0 like so:
linux-user/syscall.c: In function 'do_shmat':
linux-user/syscall.c:3058: warning: comparison of unsigned expression < 0 is always false
linux-user/syscall.c: In function 'open_self_maps':
linux-user/syscall.c:4960: warning: comparison of unsigned expression < 0 is always false
linux-user/syscall.c:4960: warning: comparison of unsigned expression < 0 is always false
Signed-off-by: Mike Frysinger <vapier@gentoo.org>
---
cpu-all.h | 8 +++++++-
1 file changed, 7 insertions(+), 1 deletion(-)
diff --git a/cpu-all.h b/cpu-all.h
index 5e07d28..0e5dcf0 100644
--- a/cpu-all.h
+++ b/cpu-all.h
@@ -202,10 +202,16 @@ extern unsigned long reserved_va;
#if HOST_LONG_BITS <= TARGET_VIRT_ADDR_SPACE_BITS
#define h2g_valid(x) 1
#else
+/* Gcc likes to warn about comparing unsigned longs to < 0, so cpp it away. */
+# if RESERVED_VA
+# define _h2g_reserved_va(x) ((x) < RESERVED_VA)
+# else
+# define _h2g_reserved_va(x) 1
+# endif
#define h2g_valid(x) ({ \
unsigned long __guest = (unsigned long)(x) - GUEST_BASE; \
(__guest < (1ul << TARGET_VIRT_ADDR_SPACE_BITS)) && \
- (!RESERVED_VA || (__guest < RESERVED_VA)); \
+ _h2g_reserved_va(__guest); \
})
#endif
--
1.7.9.7
^ permalink raw reply related [flat|nested] 28+ messages in thread
* Re: [Qemu-devel] [PATCH] fix gcc warnings when RESERVED_VA is 0
2012-09-16 0:05 [Qemu-devel] [PATCH] fix gcc warnings when RESERVED_VA is 0 Mike Frysinger
@ 2012-09-16 9:58 ` Peter Maydell
2012-09-16 10:25 ` Blue Swirl
0 siblings, 1 reply; 28+ messages in thread
From: Peter Maydell @ 2012-09-16 9:58 UTC (permalink / raw)
To: Mike Frysinger; +Cc: qemu-devel
On 16 September 2012 01:05, Mike Frysinger <vapier@gentoo.org> wrote:
> The current code, while correct, triggers a bunch of gcc warnings when
> RESERVED_VA is 0 like so:
> linux-user/syscall.c: In function 'do_shmat':
> linux-user/syscall.c:3058: warning: comparison of unsigned expression < 0 is always false
> linux-user/syscall.c: In function 'open_self_maps':
> linux-user/syscall.c:4960: warning: comparison of unsigned expression < 0 is always false
> linux-user/syscall.c:4960: warning: comparison of unsigned expression < 0 is always false
>
> Signed-off-by: Mike Frysinger <vapier@gentoo.org>
> ---
> cpu-all.h | 8 +++++++-
> 1 file changed, 7 insertions(+), 1 deletion(-)
>
> diff --git a/cpu-all.h b/cpu-all.h
> index 5e07d28..0e5dcf0 100644
> --- a/cpu-all.h
> +++ b/cpu-all.h
> @@ -202,10 +202,16 @@ extern unsigned long reserved_va;
> #if HOST_LONG_BITS <= TARGET_VIRT_ADDR_SPACE_BITS
> #define h2g_valid(x) 1
> #else
> +/* Gcc likes to warn about comparing unsigned longs to < 0, so cpp it away. */
> +# if RESERVED_VA
This won't do the right thing. In the CONFIG_USE_GUEST_BASE case
RESERVED_VA is #defined to 'reserved_va'. Since that's not a
cpp identifier then (a) cpp should complain since we use -Wundef
and (b) cpp will treat it as zero, meaning that we take the #else
branch regardless, which isn't what we want.
In the longer term it would be nice to add guest-base support to
the SPARC tcg backend, and then we could just unconditionally
enable CONFIG_USE_GUEST_BASE for -user targets.
> +# define _h2g_reserved_va(x) ((x) < RESERVED_VA)
> +# else
> +# define _h2g_reserved_va(x) 1
> +# endif
> #define h2g_valid(x) ({ \
> unsigned long __guest = (unsigned long)(x) - GUEST_BASE; \
> (__guest < (1ul << TARGET_VIRT_ADDR_SPACE_BITS)) && \
> - (!RESERVED_VA || (__guest < RESERVED_VA)); \
> + _h2g_reserved_va(__guest); \
> })
> #endif
-- PMM
^ permalink raw reply [flat|nested] 28+ messages in thread
* Re: [Qemu-devel] [PATCH] fix gcc warnings when RESERVED_VA is 0
2012-09-16 9:58 ` Peter Maydell
@ 2012-09-16 10:25 ` Blue Swirl
2012-09-17 15:28 ` [Qemu-devel] [PATCH v2 00/13] Sparc TCG cleanup Richard Henderson
0 siblings, 1 reply; 28+ messages in thread
From: Blue Swirl @ 2012-09-16 10:25 UTC (permalink / raw)
To: Peter Maydell, Richard Henderson; +Cc: Mike Frysinger, qemu-devel
On Sun, Sep 16, 2012 at 9:58 AM, Peter Maydell <peter.maydell@linaro.org> wrote:
> On 16 September 2012 01:05, Mike Frysinger <vapier@gentoo.org> wrote:
>> The current code, while correct, triggers a bunch of gcc warnings when
>> RESERVED_VA is 0 like so:
>> linux-user/syscall.c: In function 'do_shmat':
>> linux-user/syscall.c:3058: warning: comparison of unsigned expression < 0 is always false
>> linux-user/syscall.c: In function 'open_self_maps':
>> linux-user/syscall.c:4960: warning: comparison of unsigned expression < 0 is always false
>> linux-user/syscall.c:4960: warning: comparison of unsigned expression < 0 is always false
>>
>> Signed-off-by: Mike Frysinger <vapier@gentoo.org>
>> ---
>> cpu-all.h | 8 +++++++-
>> 1 file changed, 7 insertions(+), 1 deletion(-)
>>
>> diff --git a/cpu-all.h b/cpu-all.h
>> index 5e07d28..0e5dcf0 100644
>> --- a/cpu-all.h
>> +++ b/cpu-all.h
>> @@ -202,10 +202,16 @@ extern unsigned long reserved_va;
>> #if HOST_LONG_BITS <= TARGET_VIRT_ADDR_SPACE_BITS
>> #define h2g_valid(x) 1
>> #else
>> +/* Gcc likes to warn about comparing unsigned longs to < 0, so cpp it away. */
>> +# if RESERVED_VA
>
> This won't do the right thing. In the CONFIG_USE_GUEST_BASE case
> RESERVED_VA is #defined to 'reserved_va'. Since that's not a
> cpp identifier then (a) cpp should complain since we use -Wundef
> and (b) cpp will treat it as zero, meaning that we take the #else
> branch regardless, which isn't what we want.
>
> In the longer term it would be nice to add guest-base support to
> the SPARC tcg backend, and then we could just unconditionally
> enable CONFIG_USE_GUEST_BASE for -user targets.
IIRC Richard's Sparc TCG patch set implemented guest base. Any chance
of refreshing that?
>
>> +# define _h2g_reserved_va(x) ((x) < RESERVED_VA)
>> +# else
>> +# define _h2g_reserved_va(x) 1
>> +# endif
>> #define h2g_valid(x) ({ \
>> unsigned long __guest = (unsigned long)(x) - GUEST_BASE; \
>> (__guest < (1ul << TARGET_VIRT_ADDR_SPACE_BITS)) && \
>> - (!RESERVED_VA || (__guest < RESERVED_VA)); \
>> + _h2g_reserved_va(__guest); \
>> })
>> #endif
>
> -- PMM
>
^ permalink raw reply [flat|nested] 28+ messages in thread
* [Qemu-devel] [PATCH v2 00/13] Sparc TCG cleanup
2012-09-16 10:25 ` Blue Swirl
@ 2012-09-17 15:28 ` Richard Henderson
2012-09-17 15:28 ` [Qemu-devel] [PATCH 01/13] linux-user: Use memcpy in get_user/put_user Richard Henderson
` (12 more replies)
0 siblings, 13 replies; 28+ messages in thread
From: Richard Henderson @ 2012-09-17 15:28 UTC (permalink / raw)
To: qemu-devel; +Cc: blauwirbel
A refreshed version of an old patchset that got mislaid.
I've re-tested it on arm and xtensa system images, and
several linux-user images.
r~
Richard Henderson (13):
linux-user: Use memcpy in get_user/put_user.
tcg-sparc: Hack in qemu_ld/st64 for 32-bit.
tcg-sparc: Fix ADDX opcode.
tcg-sparc: Assume v9 cpu always, i.e. force v8plus in 32-bit mode.
tcg-sparc: Fix qemu_ld/st to handle 32-bit host.
tcg-sparc: Support GUEST_BASE.
tcg-sparc: Change AREG0 in generated code to %i0.
tcg-sparc: Clean up cruft stemming from attempts to use global
registers.
tcg-sparc: Mask shift immediates to avoid illegal insns.
tcg-sparc: Use defines for temporaries.
tcg-sparc: Add %g/%o registers to alloc_order
tcg-sparc: Fix and enable direct TB chaining.
tcg: Fix !USE_DIRECT_JUMP
configure | 52 +--
disas.c | 2 -
exec-all.h | 9 +-
exec.c | 12 +-
linux-user/qemu.h | 47 +--
qemu-timer.h | 8 +-
tcg/sparc/tcg-target.c | 949 +++++++++++++++++++++++--------------------------
tcg/sparc/tcg-target.h | 33 +-
tcg/tcg.c | 3 +-
tcg/tcg.h | 2 +-
10 files changed, 502 insertions(+), 615 deletions(-)
--
1.7.11.4
^ permalink raw reply [flat|nested] 28+ messages in thread
* [Qemu-devel] [PATCH 01/13] linux-user: Use memcpy in get_user/put_user.
2012-09-17 15:28 ` [Qemu-devel] [PATCH v2 00/13] Sparc TCG cleanup Richard Henderson
@ 2012-09-17 15:28 ` Richard Henderson
2012-09-17 15:35 ` Peter Maydell
2012-09-17 16:06 ` Peter Maydell
2012-09-17 15:28 ` [Qemu-devel] [PATCH 02/13] tcg-sparc: Hack in qemu_ld/st64 for 32-bit Richard Henderson
` (11 subsequent siblings)
12 siblings, 2 replies; 28+ messages in thread
From: Richard Henderson @ 2012-09-17 15:28 UTC (permalink / raw)
To: qemu-devel; +Cc: blauwirbel
Not sure whether this is a gcc bug, but on sparc we wind up
trying to use std to an unaligned address. The patch does
work around the problem.
Signed-off-by: Richard Henderson <rth@twiddle.net>
---
linux-user/qemu.h | 47 +++++++++++++++--------------------------------
1 file changed, 15 insertions(+), 32 deletions(-)
diff --git a/linux-user/qemu.h b/linux-user/qemu.h
index 69b27d7..fc4cc00 100644
--- a/linux-user/qemu.h
+++ b/linux-user/qemu.h
@@ -289,46 +289,29 @@ static inline int access_ok(int type, abi_ulong addr, abi_ulong size)
* struct has been locked - usually with lock_user_struct().
*/
#define __put_user(x, hptr)\
-({\
+({ __typeof(*hptr) pu_ = (x);\
switch(sizeof(*hptr)) {\
- case 1:\
- *(uint8_t *)(hptr) = (uint8_t)(typeof(*hptr))(x);\
- break;\
- case 2:\
- *(uint16_t *)(hptr) = tswap16((uint16_t)(typeof(*hptr))(x));\
- break;\
- case 4:\
- *(uint32_t *)(hptr) = tswap32((uint32_t)(typeof(*hptr))(x));\
- break;\
- case 8:\
- *(uint64_t *)(hptr) = tswap64((typeof(*hptr))(x));\
- break;\
- default:\
- abort();\
+ case 1: break;\
+ case 2: pu_ = tswap16(pu_); break; \
+ case 4: pu_ = tswap32(pu_); break; \
+ case 8: pu_ = tswap64(pu_); break; \
+ default: abort();\
}\
+ memcpy(hptr, &pu_, sizeof(pu_)); \
0;\
})
#define __get_user(x, hptr) \
-({\
+({ __typeof(*hptr) gu_; \
+ memcpy(&gu_, hptr, sizeof(gu_)); \
switch(sizeof(*hptr)) {\
- case 1:\
- x = (typeof(*hptr))*(uint8_t *)(hptr);\
- break;\
- case 2:\
- x = (typeof(*hptr))tswap16(*(uint16_t *)(hptr));\
- break;\
- case 4:\
- x = (typeof(*hptr))tswap32(*(uint32_t *)(hptr));\
- break;\
- case 8:\
- x = (typeof(*hptr))tswap64(*(uint64_t *)(hptr));\
- break;\
- default:\
- /* avoid warning */\
- x = 0;\
- abort();\
+ case 1: break; \
+ case 2: gu_ = tswap16(gu_); break; \
+ case 4: gu_ = tswap32(gu_); break; \
+ case 8: gu_ = tswap64(gu_); break; \
+ default: abort();\
}\
+ (x) = gu_; \
0;\
})
--
1.7.11.4
^ permalink raw reply related [flat|nested] 28+ messages in thread
* [Qemu-devel] [PATCH 02/13] tcg-sparc: Hack in qemu_ld/st64 for 32-bit.
2012-09-17 15:28 ` [Qemu-devel] [PATCH v2 00/13] Sparc TCG cleanup Richard Henderson
2012-09-17 15:28 ` [Qemu-devel] [PATCH 01/13] linux-user: Use memcpy in get_user/put_user Richard Henderson
@ 2012-09-17 15:28 ` Richard Henderson
2012-09-17 15:28 ` [Qemu-devel] [PATCH 03/13] tcg-sparc: Fix ADDX opcode Richard Henderson
` (10 subsequent siblings)
12 siblings, 0 replies; 28+ messages in thread
From: Richard Henderson @ 2012-09-17 15:28 UTC (permalink / raw)
To: qemu-devel; +Cc: blauwirbel
Not actually implemented, but at least we avoid the tcg assert at startup.
Signed-off-by: Richard Henderson <rth@twiddle.net>
---
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.11.4
^ permalink raw reply related [flat|nested] 28+ messages in thread
* [Qemu-devel] [PATCH 03/13] tcg-sparc: Fix ADDX opcode.
2012-09-17 15:28 ` [Qemu-devel] [PATCH v2 00/13] Sparc TCG cleanup Richard Henderson
2012-09-17 15:28 ` [Qemu-devel] [PATCH 01/13] linux-user: Use memcpy in get_user/put_user Richard Henderson
2012-09-17 15:28 ` [Qemu-devel] [PATCH 02/13] tcg-sparc: Hack in qemu_ld/st64 for 32-bit Richard Henderson
@ 2012-09-17 15:28 ` Richard Henderson
2012-09-17 15:28 ` [Qemu-devel] [PATCH 04/13] tcg-sparc: Assume v9 cpu always, i.e. force v8plus in 32-bit mode Richard Henderson
` (9 subsequent siblings)
12 siblings, 0 replies; 28+ messages in thread
From: Richard Henderson @ 2012-09-17 15:28 UTC (permalink / raw)
To: qemu-devel; +Cc: blauwirbel
Signed-off-by: Richard Henderson <rth@twiddle.net>
---
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.11.4
^ permalink raw reply related [flat|nested] 28+ messages in thread
* [Qemu-devel] [PATCH 04/13] tcg-sparc: Assume v9 cpu always, i.e. force v8plus in 32-bit mode.
2012-09-17 15:28 ` [Qemu-devel] [PATCH v2 00/13] Sparc TCG cleanup Richard Henderson
` (2 preceding siblings ...)
2012-09-17 15:28 ` [Qemu-devel] [PATCH 03/13] tcg-sparc: Fix ADDX opcode Richard Henderson
@ 2012-09-17 15:28 ` Richard Henderson
2012-09-17 16:04 ` Andreas Färber
2012-09-17 15:28 ` [Qemu-devel] [PATCH 05/13] tcg-sparc: Fix qemu_ld/st to handle 32-bit host Richard Henderson
` (8 subsequent siblings)
12 siblings, 1 reply; 28+ messages in thread
From: Richard Henderson @ 2012-09-17 15:28 UTC (permalink / raw)
To: qemu-devel; +Cc: blauwirbel
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
Also, a bug fix: don't MAP_FIXED right on top of the program
address space set in sparc64.ld.
Signed-off-by: Richard Henderson <rth@twiddle.net>
---
configure | 40 ++++------------------------------------
disas.c | 2 --
exec.c | 12 +++++-------
qemu-timer.h | 8 +++++---
tcg/sparc/tcg-target.c | 20 +++++---------------
tcg/sparc/tcg-target.h | 7 ++++---
tcg/tcg.c | 3 ++-
7 files changed, 25 insertions(+), 67 deletions(-)
diff --git a/configure b/configure
index 7e23309..07702b5 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"
@@ -241,21 +240,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
@@ -343,8 +327,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
@@ -792,8 +774,6 @@ for opt do
;;
--enable-uname-release=*) uname_release="$optarg"
;;
- --sparc_cpu=*)
- ;;
--enable-werror) werror="yes"
;;
--disable-werror) werror="no"
@@ -881,31 +861,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 5834766..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,10 +541,9 @@ 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
- 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__)
@@ -582,10 +581,9 @@ 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
- flags |= MAP_FIXED;
- addr = (void *) 0x60000000UL;
+ addr = (void *) 0x40000000UL;
if (code_gen_buffer_size > (512 * 1024 * 1024)) {
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 0ea87be..3b897d5 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
@@ -127,7 +128,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 a4e7f42..3943d09 100644
--- a/tcg/tcg.c
+++ b/tcg/tcg.c
@@ -1463,7 +1463,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.11.4
^ permalink raw reply related [flat|nested] 28+ messages in thread
* [Qemu-devel] [PATCH 05/13] tcg-sparc: Fix qemu_ld/st to handle 32-bit host.
2012-09-17 15:28 ` [Qemu-devel] [PATCH v2 00/13] Sparc TCG cleanup Richard Henderson
` (3 preceding siblings ...)
2012-09-17 15:28 ` [Qemu-devel] [PATCH 04/13] tcg-sparc: Assume v9 cpu always, i.e. force v8plus in 32-bit mode Richard Henderson
@ 2012-09-17 15:28 ` Richard Henderson
2012-09-17 15:28 ` [Qemu-devel] [PATCH 06/13] tcg-sparc: Support GUEST_BASE Richard Henderson
` (7 subsequent siblings)
12 siblings, 0 replies; 28+ messages in thread
From: Richard Henderson @ 2012-09-17 15:28 UTC (permalink / raw)
To: qemu-devel; +Cc: blauwirbel
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>
---
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.11.4
^ permalink raw reply related [flat|nested] 28+ messages in thread
* [Qemu-devel] [PATCH 06/13] tcg-sparc: Support GUEST_BASE.
2012-09-17 15:28 ` [Qemu-devel] [PATCH v2 00/13] Sparc TCG cleanup Richard Henderson
` (4 preceding siblings ...)
2012-09-17 15:28 ` [Qemu-devel] [PATCH 05/13] tcg-sparc: Fix qemu_ld/st to handle 32-bit host Richard Henderson
@ 2012-09-17 15:28 ` Richard Henderson
2012-09-17 15:28 ` [Qemu-devel] [PATCH 07/13] tcg-sparc: Change AREG0 in generated code to %i0 Richard Henderson
` (6 subsequent siblings)
12 siblings, 0 replies; 28+ messages in thread
From: Richard Henderson @ 2012-09-17 15:28 UTC (permalink / raw)
To: qemu-devel; +Cc: blauwirbel
Signed-off-by: Richard Henderson <rth@twiddle.net>
---
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 07702b5..9cab09a 100755
--- a/configure
+++ b/configure
@@ -870,6 +870,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"
@@ -878,6 +879,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 3b897d5..4092e29 100644
--- a/tcg/sparc/tcg-target.h
+++ b/tcg/sparc/tcg-target.h
@@ -126,6 +126,8 @@ typedef enum {
#define TCG_TARGET_HAS_deposit_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.11.4
^ permalink raw reply related [flat|nested] 28+ messages in thread
* [Qemu-devel] [PATCH 07/13] tcg-sparc: Change AREG0 in generated code to %i0.
2012-09-17 15:28 ` [Qemu-devel] [PATCH v2 00/13] Sparc TCG cleanup Richard Henderson
` (5 preceding siblings ...)
2012-09-17 15:28 ` [Qemu-devel] [PATCH 06/13] tcg-sparc: Support GUEST_BASE Richard Henderson
@ 2012-09-17 15:28 ` Richard Henderson
2012-09-17 15:28 ` [Qemu-devel] [PATCH 08/13] tcg-sparc: Clean up cruft stemming from attempts to use global registers Richard Henderson
` (5 subsequent siblings)
12 siblings, 0 replies; 28+ messages in thread
From: Richard Henderson @ 2012-09-17 15:28 UTC (permalink / raw)
To: qemu-devel; +Cc: blauwirbel
We can now move the TCG variable from %g[56] to a call-preserved
windowed register.
Signed-off-by: Richard Henderson <rth@twiddle.net>
---
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 4092e29..31b98e2 100644
--- a/tcg/sparc/tcg-target.h
+++ b/tcg/sparc/tcg-target.h
@@ -128,13 +128,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.11.4
^ permalink raw reply related [flat|nested] 28+ messages in thread
* [Qemu-devel] [PATCH 08/13] tcg-sparc: Clean up cruft stemming from attempts to use global registers.
2012-09-17 15:28 ` [Qemu-devel] [PATCH v2 00/13] Sparc TCG cleanup Richard Henderson
` (6 preceding siblings ...)
2012-09-17 15:28 ` [Qemu-devel] [PATCH 07/13] tcg-sparc: Change AREG0 in generated code to %i0 Richard Henderson
@ 2012-09-17 15:28 ` Richard Henderson
2012-09-17 15:28 ` [Qemu-devel] [PATCH 09/13] tcg-sparc: Mask shift immediates to avoid illegal insns Richard Henderson
` (4 subsequent siblings)
12 siblings, 0 replies; 28+ messages in thread
From: Richard Henderson @ 2012-09-17 15:28 UTC (permalink / raw)
To: qemu-devel; +Cc: blauwirbel
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>
---
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 9cab09a..0e92bcc 100755
--- a/configure
+++ b/configure
@@ -866,19 +866,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)
@@ -4089,10 +4081,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 31b98e2..b7afa7b 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.11.4
^ permalink raw reply related [flat|nested] 28+ messages in thread
* [Qemu-devel] [PATCH 09/13] tcg-sparc: Mask shift immediates to avoid illegal insns.
2012-09-17 15:28 ` [Qemu-devel] [PATCH v2 00/13] Sparc TCG cleanup Richard Henderson
` (7 preceding siblings ...)
2012-09-17 15:28 ` [Qemu-devel] [PATCH 08/13] tcg-sparc: Clean up cruft stemming from attempts to use global registers Richard Henderson
@ 2012-09-17 15:28 ` Richard Henderson
2012-09-17 15:28 ` [Qemu-devel] [PATCH 10/13] tcg-sparc: Use defines for temporaries Richard Henderson
` (3 subsequent siblings)
12 siblings, 0 replies; 28+ messages in thread
From: Richard Henderson @ 2012-09-17 15:28 UTC (permalink / raw)
To: qemu-devel; +Cc: blauwirbel
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>
---
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.11.4
^ permalink raw reply related [flat|nested] 28+ messages in thread
* [Qemu-devel] [PATCH 10/13] tcg-sparc: Use defines for temporaries.
2012-09-17 15:28 ` [Qemu-devel] [PATCH v2 00/13] Sparc TCG cleanup Richard Henderson
` (8 preceding siblings ...)
2012-09-17 15:28 ` [Qemu-devel] [PATCH 09/13] tcg-sparc: Mask shift immediates to avoid illegal insns Richard Henderson
@ 2012-09-17 15:28 ` Richard Henderson
2012-09-17 15:28 ` [Qemu-devel] [PATCH 11/13] tcg-sparc: Add %g/%o registers to alloc_order Richard Henderson
` (2 subsequent siblings)
12 siblings, 0 replies; 28+ messages in thread
From: Richard Henderson @ 2012-09-17 15:28 UTC (permalink / raw)
To: qemu-devel; +Cc: blauwirbel
And change from %i4/%i5 to %g1/%o7 to remove a v8plus fixme.
Signed-off-by: Richard Henderson <rth@twiddle.net>
---
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.11.4
^ permalink raw reply related [flat|nested] 28+ messages in thread
* [Qemu-devel] [PATCH 11/13] tcg-sparc: Add %g/%o registers to alloc_order
2012-09-17 15:28 ` [Qemu-devel] [PATCH v2 00/13] Sparc TCG cleanup Richard Henderson
` (9 preceding siblings ...)
2012-09-17 15:28 ` [Qemu-devel] [PATCH 10/13] tcg-sparc: Use defines for temporaries Richard Henderson
@ 2012-09-17 15:28 ` Richard Henderson
2012-09-17 15:28 ` [Qemu-devel] [PATCH 12/13] tcg-sparc: Fix and enable direct TB chaining Richard Henderson
2012-09-17 15:28 ` [Qemu-devel] [PATCH 13/13] tcg: Fix !USE_DIRECT_JUMP Richard Henderson
12 siblings, 0 replies; 28+ messages in thread
From: Richard Henderson @ 2012-09-17 15:28 UTC (permalink / raw)
To: qemu-devel; +Cc: blauwirbel
Signed-off-by: Richard Henderson <rth@twiddle.net>
---
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.11.4
^ permalink raw reply related [flat|nested] 28+ messages in thread
* [Qemu-devel] [PATCH 12/13] tcg-sparc: Fix and enable direct TB chaining.
2012-09-17 15:28 ` [Qemu-devel] [PATCH v2 00/13] Sparc TCG cleanup Richard Henderson
` (10 preceding siblings ...)
2012-09-17 15:28 ` [Qemu-devel] [PATCH 11/13] tcg-sparc: Add %g/%o registers to alloc_order Richard Henderson
@ 2012-09-17 15:28 ` Richard Henderson
2012-09-17 15:28 ` [Qemu-devel] [PATCH 13/13] tcg: Fix !USE_DIRECT_JUMP Richard Henderson
12 siblings, 0 replies; 28+ messages in thread
From: Richard Henderson @ 2012-09-17 15:28 UTC (permalink / raw)
To: qemu-devel; +Cc: blauwirbel
Signed-off-by: Richard Henderson <rth@twiddle.net>
---
exec-all.h | 9 ++++++---
tcg/sparc/tcg-target.c | 19 ++++++++++++++++---
2 files changed, 22 insertions(+), 6 deletions(-)
diff --git a/exec-all.h b/exec-all.h
index dba9609..6516da0 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..58d7a3d 100644
--- a/tcg/sparc/tcg-target.c
+++ b/tcg/sparc/tcg-target.c
@@ -1072,10 +1072,8 @@ 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)));
s->tb_jmp_offset[args[0]] = s->code_ptr - s->code_buf;
+ tcg_out32(s, CALL | (8 >> 2));
} else {
/* indirect jump method */
tcg_out_ld_ptr(s, TCG_REG_T1,
@@ -1595,3 +1593,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.11.4
^ permalink raw reply related [flat|nested] 28+ messages in thread
* [Qemu-devel] [PATCH 13/13] tcg: Fix !USE_DIRECT_JUMP
2012-09-17 15:28 ` [Qemu-devel] [PATCH v2 00/13] Sparc TCG cleanup Richard Henderson
` (11 preceding siblings ...)
2012-09-17 15:28 ` [Qemu-devel] [PATCH 12/13] tcg-sparc: Fix and enable direct TB chaining Richard Henderson
@ 2012-09-17 15:28 ` Richard Henderson
2012-09-17 15:50 ` Andreas Färber
` (2 more replies)
12 siblings, 3 replies; 28+ messages in thread
From: Richard Henderson @ 2012-09-17 15:28 UTC (permalink / raw)
To: qemu-devel; +Cc: blauwirbel
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>
---
tcg/tcg.h | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/tcg/tcg.h b/tcg/tcg.h
index 7a72729..21016ec 100644
--- a/tcg/tcg.h
+++ b/tcg/tcg.h
@@ -343,7 +343,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.11.4
^ permalink raw reply related [flat|nested] 28+ messages in thread
* Re: [Qemu-devel] [PATCH 01/13] linux-user: Use memcpy in get_user/put_user.
2012-09-17 15:28 ` [Qemu-devel] [PATCH 01/13] linux-user: Use memcpy in get_user/put_user Richard Henderson
@ 2012-09-17 15:35 ` Peter Maydell
2012-09-17 15:40 ` Richard Henderson
2012-09-17 16:06 ` Peter Maydell
1 sibling, 1 reply; 28+ messages in thread
From: Peter Maydell @ 2012-09-17 15:35 UTC (permalink / raw)
To: Richard Henderson; +Cc: blauwirbel, qemu-devel
On 17 September 2012 16:28, Richard Henderson <rth@twiddle.net> wrote:
> Not sure whether this is a gcc bug, but on sparc we wind up
> trying to use std to an unaligned address. The patch does
> work around the problem.
Hmm. I guess this is guest and host having differing alignment
requirements for 64 bit types? What case does it fail on?
-- PMM
^ permalink raw reply [flat|nested] 28+ messages in thread
* Re: [Qemu-devel] [PATCH 01/13] linux-user: Use memcpy in get_user/put_user.
2012-09-17 15:35 ` Peter Maydell
@ 2012-09-17 15:40 ` Richard Henderson
0 siblings, 0 replies; 28+ messages in thread
From: Richard Henderson @ 2012-09-17 15:40 UTC (permalink / raw)
To: Peter Maydell; +Cc: blauwirbel, qemu-devel
On 09/17/2012 08:35 AM, Peter Maydell wrote:
> On 17 September 2012 16:28, Richard Henderson <rth@twiddle.net> wrote:
>> Not sure whether this is a gcc bug, but on sparc we wind up
>> trying to use std to an unaligned address. The patch does
>> work around the problem.
>
> Hmm. I guess this is guest and host having differing alignment
> requirements for 64 bit types? What case does it fail on?
I'll have to re-check. I'm pretty sure this was sparc32 hosting arm-linux-user.
r~
^ permalink raw reply [flat|nested] 28+ messages in thread
* Re: [Qemu-devel] [PATCH 13/13] tcg: Fix !USE_DIRECT_JUMP
2012-09-17 15:28 ` [Qemu-devel] [PATCH 13/13] tcg: Fix !USE_DIRECT_JUMP Richard Henderson
@ 2012-09-17 15:50 ` Andreas Färber
2012-09-21 20:21 ` Stefan Weil
2012-09-21 10:28 ` Aurelien Jarno
2012-09-21 18:16 ` Aurelien Jarno
2 siblings, 1 reply; 28+ messages in thread
From: Andreas Färber @ 2012-09-17 15:50 UTC (permalink / raw)
To: Richard Henderson; +Cc: blauwirbel, Stefan Weil, qemu-devel
Am 17.09.2012 17:28, schrieb Richard Henderson:
> 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>
/-F
> ---
> tcg/tcg.h | 2 +-
> 1 file changed, 1 insertion(+), 1 deletion(-)
>
> diff --git a/tcg/tcg.h b/tcg/tcg.h
> index 7a72729..21016ec 100644
> --- a/tcg/tcg.h
> +++ b/tcg/tcg.h
> @@ -343,7 +343,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 */
>
--
SUSE LINUX Products GmbH, Maxfeldstr. 5, 90409 Nürnberg, Germany
GF: Jeff Hawn, Jennifer Guild, Felix Imendörffer; HRB 16746 AG Nürnberg
^ permalink raw reply [flat|nested] 28+ messages in thread
* Re: [Qemu-devel] [PATCH 04/13] tcg-sparc: Assume v9 cpu always, i.e. force v8plus in 32-bit mode.
2012-09-17 15:28 ` [Qemu-devel] [PATCH 04/13] tcg-sparc: Assume v9 cpu always, i.e. force v8plus in 32-bit mode Richard Henderson
@ 2012-09-17 16:04 ` Andreas Färber
2012-09-17 17:05 ` Richard Henderson
0 siblings, 1 reply; 28+ messages in thread
From: Andreas Färber @ 2012-09-17 16:04 UTC (permalink / raw)
To: Richard Henderson; +Cc: blauwirbel, qemu-devel
Am 17.09.2012 17:28, schrieb Richard Henderson:
> 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
>
> Also, a bug fix: don't MAP_FIXED right on top of the program
> address space set in sparc64.ld.
>
> Signed-off-by: Richard Henderson <rth@twiddle.net>
Without knowing the code, this does not strike me as the best of ideas:
SPARC CPUs are rather uncommon these days, so being able to emulate it
in sparc32-softmmu may be helpful for keeping it working.
Could you elaborate on what exactly is broken and what would need to be
done as alternative?
The MAP_FIXED bugfix (keyword "also") should probably go into its own
patch either way.
Regards,
Andreas
--
SUSE LINUX Products GmbH, Maxfeldstr. 5, 90409 Nürnberg, Germany
GF: Jeff Hawn, Jennifer Guild, Felix Imendörffer; HRB 16746 AG Nürnberg
^ permalink raw reply [flat|nested] 28+ messages in thread
* Re: [Qemu-devel] [PATCH 01/13] linux-user: Use memcpy in get_user/put_user.
2012-09-17 15:28 ` [Qemu-devel] [PATCH 01/13] linux-user: Use memcpy in get_user/put_user Richard Henderson
2012-09-17 15:35 ` Peter Maydell
@ 2012-09-17 16:06 ` Peter Maydell
1 sibling, 0 replies; 28+ messages in thread
From: Peter Maydell @ 2012-09-17 16:06 UTC (permalink / raw)
To: Richard Henderson; +Cc: blauwirbel, qemu-devel
On 17 September 2012 16:28, Richard Henderson <rth@twiddle.net> wrote:
> Not sure whether this is a gcc bug, but on sparc we wind up
> trying to use std to an unaligned address. The patch does
> work around the problem.
>
> Signed-off-by: Richard Henderson <rth@twiddle.net>
As far as the code is concerned:
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
but please rewrite the commit message to be more sure of itself :-)
Specifically, this is required because the guest's alignment
requirements may be laxer than those of the host, so we can't
take a hptr for a 16/32/64 bit type (which only has the alignment
restrictions of the guest) and do a gcc pointer dereference on it
(which may assume the alignment restrictions of the host).
Does anybody know the semantics of the kernel's copy_from_user()?
Does it fail on misaligned userspace structs or does it allow
them?
-- PMM
^ permalink raw reply [flat|nested] 28+ messages in thread
* Re: [Qemu-devel] [PATCH 04/13] tcg-sparc: Assume v9 cpu always, i.e. force v8plus in 32-bit mode.
2012-09-17 16:04 ` Andreas Färber
@ 2012-09-17 17:05 ` Richard Henderson
2012-09-17 19:25 ` Blue Swirl
0 siblings, 1 reply; 28+ messages in thread
From: Richard Henderson @ 2012-09-17 17:05 UTC (permalink / raw)
To: Andreas Färber; +Cc: blauwirbel, qemu-devel
On 09/17/2012 09:04 AM, Andreas Färber wrote:
> Without knowing the code, this does not strike me as the best of ideas:
> SPARC CPUs are rather uncommon these days, so being able to emulate it
> in sparc32-softmmu may be helpful for keeping it working.
>
> Could you elaborate on what exactly is broken and what would need to be
> done as alternative?
See, for instance, patch 2. INDEX_op_qemu_ld64 and INDEX_op_qemu_st64
were unimplemented, caught during tcg startup with --enable-tcg-debug,
and crashing later without.
Handling only sparcv9 host cpus means that lots of code paths are able
to be cleaned up:
(1) Multiply and divide insns are available
(Conditional support for these is not easy.)
(2) Endian-swapping load/store insns are available
(Vastly cleans up qemu_ld/st; by the end of my patch set the
fast path through the tlb is a single insn in the delay slot
of the branch over the call to the helper.)
(3) Conditional move insns are available
(For setcond this is tidier than playing subtract-with-borrow games).
But sparcv9 is now coming up on 20 years old. The amount of hardware
still live that isn't v9 capable is bound to be vanishingly small -- in
much the same way that i386 hosts without i486 bswap. I don't think we
need to use the QEMU TCG code generator as a test case that keeps sparcv7
code alive.
r~
^ permalink raw reply [flat|nested] 28+ messages in thread
* Re: [Qemu-devel] [PATCH 04/13] tcg-sparc: Assume v9 cpu always, i.e. force v8plus in 32-bit mode.
2012-09-17 17:05 ` Richard Henderson
@ 2012-09-17 19:25 ` Blue Swirl
2012-09-17 21:52 ` Richard Henderson
0 siblings, 1 reply; 28+ messages in thread
From: Blue Swirl @ 2012-09-17 19:25 UTC (permalink / raw)
To: Richard Henderson; +Cc: Andreas Färber, qemu-devel
On Mon, Sep 17, 2012 at 5:05 PM, Richard Henderson <rth@twiddle.net> wrote:
> On 09/17/2012 09:04 AM, Andreas Färber wrote:
>> Without knowing the code, this does not strike me as the best of ideas:
>> SPARC CPUs are rather uncommon these days, so being able to emulate it
>> in sparc32-softmmu may be helpful for keeping it working.
>>
>> Could you elaborate on what exactly is broken and what would need to be
>> done as alternative?
>
> See, for instance, patch 2. INDEX_op_qemu_ld64 and INDEX_op_qemu_st64
> were unimplemented, caught during tcg startup with --enable-tcg-debug,
> and crashing later without.
>
> Handling only sparcv9 host cpus means that lots of code paths are able
> to be cleaned up:
>
> (1) Multiply and divide insns are available
> (Conditional support for these is not easy.)
>
> (2) Endian-swapping load/store insns are available
> (Vastly cleans up qemu_ld/st; by the end of my patch set the
> fast path through the tlb is a single insn in the delay slot
> of the branch over the call to the helper.)
>
> (3) Conditional move insns are available
> (For setcond this is tidier than playing subtract-with-borrow games).
>
> But sparcv9 is now coming up on 20 years old. The amount of hardware
> still live that isn't v9 capable is bound to be vanishingly small -- in
> much the same way that i386 hosts without i486 bswap. I don't think we
> need to use the QEMU TCG code generator as a test case that keeps sparcv7
> code alive.
No Linux distros supports Sparc32 anymore. There's NetBSD and OpenBSD though.
Would it make sense to break up tcg/sparc into tcg/sparc32 and
tcg/sparc64? That way it would be possible to give Sparc32 a chance of
getting fixed. But I wouldn't object removal either.
>
>
> r~
^ permalink raw reply [flat|nested] 28+ messages in thread
* Re: [Qemu-devel] [PATCH 04/13] tcg-sparc: Assume v9 cpu always, i.e. force v8plus in 32-bit mode.
2012-09-17 19:25 ` Blue Swirl
@ 2012-09-17 21:52 ` Richard Henderson
0 siblings, 0 replies; 28+ messages in thread
From: Richard Henderson @ 2012-09-17 21:52 UTC (permalink / raw)
To: Blue Swirl; +Cc: Andreas Färber, qemu-devel
On 09/17/2012 12:25 PM, Blue Swirl wrote:
> Would it make sense to break up tcg/sparc into tcg/sparc32 and
> tcg/sparc64? That way it would be possible to give Sparc32 a chance of
> getting fixed. But I wouldn't object removal either.
IMO someone would have to actively step forward to maintain sparcv8
before we should even consider keeping it. It has been actively
broken for so long and no one has complained.
r~
^ permalink raw reply [flat|nested] 28+ messages in thread
* Re: [Qemu-devel] [PATCH 13/13] tcg: Fix !USE_DIRECT_JUMP
2012-09-17 15:28 ` [Qemu-devel] [PATCH 13/13] tcg: Fix !USE_DIRECT_JUMP Richard Henderson
2012-09-17 15:50 ` Andreas Färber
@ 2012-09-21 10:28 ` Aurelien Jarno
2012-09-21 18:16 ` Aurelien Jarno
2 siblings, 0 replies; 28+ messages in thread
From: Aurelien Jarno @ 2012-09-21 10:28 UTC (permalink / raw)
To: Richard Henderson; +Cc: blauwirbel, qemu-devel
On Mon, Sep 17, 2012 at 08:28:52AM -0700, Richard Henderson wrote:
> 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>
> ---
> tcg/tcg.h | 2 +-
> 1 file changed, 1 insertion(+), 1 deletion(-)
>
> diff --git a/tcg/tcg.h b/tcg/tcg.h
> index 7a72729..21016ec 100644
> --- a/tcg/tcg.h
> +++ b/tcg/tcg.h
> @@ -343,7 +343,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 */
>
Not directly sparc related, and definitely correct.
Reviewed-by: Aurelien Jarno <aurelien@aurel32.net>
--
Aurelien Jarno GPG: 1024D/F1BCDB73
aurelien@aurel32.net http://www.aurel32.net
^ permalink raw reply [flat|nested] 28+ messages in thread
* Re: [Qemu-devel] [PATCH 13/13] tcg: Fix !USE_DIRECT_JUMP
2012-09-17 15:28 ` [Qemu-devel] [PATCH 13/13] tcg: Fix !USE_DIRECT_JUMP Richard Henderson
2012-09-17 15:50 ` Andreas Färber
2012-09-21 10:28 ` Aurelien Jarno
@ 2012-09-21 18:16 ` Aurelien Jarno
2 siblings, 0 replies; 28+ messages in thread
From: Aurelien Jarno @ 2012-09-21 18:16 UTC (permalink / raw)
To: Richard Henderson; +Cc: blauwirbel, qemu-devel
On Mon, Sep 17, 2012 at 08:28:52AM -0700, Richard Henderson wrote:
> 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>
> ---
> tcg/tcg.h | 2 +-
> 1 file changed, 1 insertion(+), 1 deletion(-)
>
> diff --git a/tcg/tcg.h b/tcg/tcg.h
> index 7a72729..21016ec 100644
> --- a/tcg/tcg.h
> +++ b/tcg/tcg.h
> @@ -343,7 +343,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 */
>
I have applied this patch, given it's not directly SPARC related, and
fixes the problem for other hosts too.
--
Aurelien Jarno GPG: 1024D/F1BCDB73
aurelien@aurel32.net http://www.aurel32.net
^ permalink raw reply [flat|nested] 28+ messages in thread
* Re: [Qemu-devel] [PATCH 13/13] tcg: Fix !USE_DIRECT_JUMP
2012-09-17 15:50 ` Andreas Färber
@ 2012-09-21 20:21 ` Stefan Weil
0 siblings, 0 replies; 28+ messages in thread
From: Stefan Weil @ 2012-09-21 20:21 UTC (permalink / raw)
To: Andreas Färber
Cc: blauwirbel, qemu-stable, qemu-devel, Aurelien Jarno,
Richard Henderson
Am 17.09.2012 17:50, schrieb Andreas Färber:
> Am 17.09.2012 17:28, schrieb Richard Henderson:
>> 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>
>
> /-F
>
>> ---
>> tcg/tcg.h | 2 +-
>> 1 file changed, 1 insertion(+), 1 deletion(-)
>>
>> diff --git a/tcg/tcg.h b/tcg/tcg.h
>> index 7a72729..21016ec 100644
>> --- a/tcg/tcg.h
>> +++ b/tcg/tcg.h
>> @@ -343,7 +343,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 */
Thanks for fixing and reviewing this issue.
I expect problems caused by the wrong old code for w64 hosts
when QEMU is run with more than 4 GiB (that's a rare scenario
because it is much slower than QEMU with kvm on Linux).
All UNIX/Linux based hosts and also w32 hosts are unharmed.
Nevertheless I suggest to apply the patch to QEMU 1.2 as well.
Regards
Stefan Weil
^ permalink raw reply [flat|nested] 28+ messages in thread
end of thread, other threads:[~2012-09-21 20:22 UTC | newest]
Thread overview: 28+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2012-09-16 0:05 [Qemu-devel] [PATCH] fix gcc warnings when RESERVED_VA is 0 Mike Frysinger
2012-09-16 9:58 ` Peter Maydell
2012-09-16 10:25 ` Blue Swirl
2012-09-17 15:28 ` [Qemu-devel] [PATCH v2 00/13] Sparc TCG cleanup Richard Henderson
2012-09-17 15:28 ` [Qemu-devel] [PATCH 01/13] linux-user: Use memcpy in get_user/put_user Richard Henderson
2012-09-17 15:35 ` Peter Maydell
2012-09-17 15:40 ` Richard Henderson
2012-09-17 16:06 ` Peter Maydell
2012-09-17 15:28 ` [Qemu-devel] [PATCH 02/13] tcg-sparc: Hack in qemu_ld/st64 for 32-bit Richard Henderson
2012-09-17 15:28 ` [Qemu-devel] [PATCH 03/13] tcg-sparc: Fix ADDX opcode Richard Henderson
2012-09-17 15:28 ` [Qemu-devel] [PATCH 04/13] tcg-sparc: Assume v9 cpu always, i.e. force v8plus in 32-bit mode Richard Henderson
2012-09-17 16:04 ` Andreas Färber
2012-09-17 17:05 ` Richard Henderson
2012-09-17 19:25 ` Blue Swirl
2012-09-17 21:52 ` Richard Henderson
2012-09-17 15:28 ` [Qemu-devel] [PATCH 05/13] tcg-sparc: Fix qemu_ld/st to handle 32-bit host Richard Henderson
2012-09-17 15:28 ` [Qemu-devel] [PATCH 06/13] tcg-sparc: Support GUEST_BASE Richard Henderson
2012-09-17 15:28 ` [Qemu-devel] [PATCH 07/13] tcg-sparc: Change AREG0 in generated code to %i0 Richard Henderson
2012-09-17 15:28 ` [Qemu-devel] [PATCH 08/13] tcg-sparc: Clean up cruft stemming from attempts to use global registers Richard Henderson
2012-09-17 15:28 ` [Qemu-devel] [PATCH 09/13] tcg-sparc: Mask shift immediates to avoid illegal insns Richard Henderson
2012-09-17 15:28 ` [Qemu-devel] [PATCH 10/13] tcg-sparc: Use defines for temporaries Richard Henderson
2012-09-17 15:28 ` [Qemu-devel] [PATCH 11/13] tcg-sparc: Add %g/%o registers to alloc_order Richard Henderson
2012-09-17 15:28 ` [Qemu-devel] [PATCH 12/13] tcg-sparc: Fix and enable direct TB chaining Richard Henderson
2012-09-17 15:28 ` [Qemu-devel] [PATCH 13/13] tcg: Fix !USE_DIRECT_JUMP Richard Henderson
2012-09-17 15:50 ` Andreas Färber
2012-09-21 20:21 ` Stefan Weil
2012-09-21 10:28 ` Aurelien Jarno
2012-09-21 18:16 ` Aurelien Jarno
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).