From: Doug Kwan <dougkwan@google.com>
To: qemu-devel@nongnu.org, qemu-ppc@nongnu.org
Cc: riku.voipio@iki.fi, Doug Kwan <dougkwan@google.com>, agraf@suse.de
Subject: [Qemu-devel] [PATCH 2/3] PPC: Allow little-endian user mode.
Date: Thu, 8 May 2014 01:26:42 -0700 [thread overview]
Message-ID: <1399537603-6905-3-git-send-email-dougkwan@google.com> (raw)
In-Reply-To: <1399537603-6905-1-git-send-email-dougkwan@google.com>
This all running PPC64 little-endian in user mode if target is configured
that way. In PPC64 LE user mode we set MSR.LE during initialization.
Byteswapping logic is reversed also when QEMU is running in that mode.
Signed-off-by: Doug Kwan <dougkwan@google.com>
---
target-ppc/mem_helper.c | 16 ++++++++++++++--
target-ppc/translate.c | 45 ++++++++++++++++++++++++++++++---------------
target-ppc/translate_init.c | 9 +++++++++
3 files changed, 53 insertions(+), 17 deletions(-)
diff --git a/target-ppc/mem_helper.c b/target-ppc/mem_helper.c
index f35ed03..7bacdab 100644
--- a/target-ppc/mem_helper.c
+++ b/target-ppc/mem_helper.c
@@ -202,6 +202,14 @@ target_ulong helper_lscbx(CPUPPCState *env, target_ulong addr, uint32_t reg,
#define LO_IDX 0
#endif
+static inline bool element_needs_byteswap(CPUPPCState *env) {
+#if defined(TARGET_WORDS_BIGENDIAN)
+ return msr_le;
+#else
+ return !msr_le;
+#endif
+}
+
#define LVE(name, access, swap, element) \
void helper_##name(CPUPPCState *env, ppc_avr_t *r, \
target_ulong addr) \
@@ -210,9 +218,11 @@ target_ulong helper_lscbx(CPUPPCState *env, target_ulong addr, uint32_t reg,
int adjust = HI_IDX*(n_elems - 1); \
int sh = sizeof(r->element[0]) >> 1; \
int index = (addr & 0xf) >> sh; \
- \
if (msr_le) { \
index = n_elems - index - 1; \
+ } \
+ \
+ if (element_needs_byteswap(env)) { \
r->element[LO_IDX ? index : (adjust - index)] = \
swap(access(env, addr)); \
} else { \
@@ -235,9 +245,11 @@ LVE(lvewx, cpu_ldl_data, bswap32, u32)
int adjust = HI_IDX * (n_elems - 1); \
int sh = sizeof(r->element[0]) >> 1; \
int index = (addr & 0xf) >> sh; \
- \
if (msr_le) { \
index = n_elems - index - 1; \
+ } \
+ \
+ if (element_needs_byteswap(env)) { \
access(env, addr, swap(r->element[LO_IDX ? index : \
(adjust - index)])); \
} else { \
diff --git a/target-ppc/translate.c b/target-ppc/translate.c
index e3fcb03..4b11c5a 100644
--- a/target-ppc/translate.c
+++ b/target-ppc/translate.c
@@ -210,6 +210,15 @@ typedef struct DisasContext {
uint64_t insns_flags2;
} DisasContext;
+/* Return true iff byteswap is needed in a scalar memop */
+static inline bool need_byteswap(const DisasContext *ctx) {
+#if defined(TARGET_WORDS_BIGENDIAN)
+ return ctx->le_mode;
+#else
+ return !ctx->le_mode;
+#endif
+}
+
/* True when active word size < size of target_long. */
#ifdef TARGET_PPC64
# define NARROW_MODE(C) (!(C)->sf_mode)
@@ -2653,14 +2662,14 @@ static inline void gen_qemu_ld8s(DisasContext *ctx, TCGv arg1, TCGv arg2)
static inline void gen_qemu_ld16u(DisasContext *ctx, TCGv arg1, TCGv arg2)
{
tcg_gen_qemu_ld16u(arg1, arg2, ctx->mem_idx);
- if (unlikely(ctx->le_mode)) {
+ if (unlikely(need_byteswap(ctx))) {
tcg_gen_bswap16_tl(arg1, arg1);
}
}
static inline void gen_qemu_ld16s(DisasContext *ctx, TCGv arg1, TCGv arg2)
{
- if (unlikely(ctx->le_mode)) {
+ if (unlikely(need_byteswap(ctx))) {
tcg_gen_qemu_ld16u(arg1, arg2, ctx->mem_idx);
tcg_gen_bswap16_tl(arg1, arg1);
tcg_gen_ext16s_tl(arg1, arg1);
@@ -2672,7 +2681,7 @@ static inline void gen_qemu_ld16s(DisasContext *ctx, TCGv arg1, TCGv arg2)
static inline void gen_qemu_ld32u(DisasContext *ctx, TCGv arg1, TCGv arg2)
{
tcg_gen_qemu_ld32u(arg1, arg2, ctx->mem_idx);
- if (unlikely(ctx->le_mode)) {
+ if (unlikely(need_byteswap(ctx))) {
tcg_gen_bswap32_tl(arg1, arg1);
}
}
@@ -2687,7 +2696,7 @@ static void gen_qemu_ld32u_i64(DisasContext *ctx, TCGv_i64 val, TCGv addr)
static inline void gen_qemu_ld32s(DisasContext *ctx, TCGv arg1, TCGv arg2)
{
- if (unlikely(ctx->le_mode)) {
+ if (unlikely(need_byteswap(ctx))) {
tcg_gen_qemu_ld32u(arg1, arg2, ctx->mem_idx);
tcg_gen_bswap32_tl(arg1, arg1);
tcg_gen_ext32s_tl(arg1, arg1);
@@ -2706,7 +2715,7 @@ static void gen_qemu_ld32s_i64(DisasContext *ctx, TCGv_i64 val, TCGv addr)
static inline void gen_qemu_ld64(DisasContext *ctx, TCGv_i64 arg1, TCGv arg2)
{
tcg_gen_qemu_ld64(arg1, arg2, ctx->mem_idx);
- if (unlikely(ctx->le_mode)) {
+ if (unlikely(need_byteswap(ctx))) {
tcg_gen_bswap64_i64(arg1, arg1);
}
}
@@ -2718,7 +2727,7 @@ static inline void gen_qemu_st8(DisasContext *ctx, TCGv arg1, TCGv arg2)
static inline void gen_qemu_st16(DisasContext *ctx, TCGv arg1, TCGv arg2)
{
- if (unlikely(ctx->le_mode)) {
+ if (unlikely(need_byteswap(ctx))) {
TCGv t0 = tcg_temp_new();
tcg_gen_ext16u_tl(t0, arg1);
tcg_gen_bswap16_tl(t0, t0);
@@ -2731,7 +2740,7 @@ static inline void gen_qemu_st16(DisasContext *ctx, TCGv arg1, TCGv arg2)
static inline void gen_qemu_st32(DisasContext *ctx, TCGv arg1, TCGv arg2)
{
- if (unlikely(ctx->le_mode)) {
+ if (unlikely(need_byteswap(ctx))) {
TCGv t0 = tcg_temp_new();
tcg_gen_ext32u_tl(t0, arg1);
tcg_gen_bswap32_tl(t0, t0);
@@ -2752,7 +2761,7 @@ static void gen_qemu_st32_i64(DisasContext *ctx, TCGv_i64 val, TCGv addr)
static inline void gen_qemu_st64(DisasContext *ctx, TCGv_i64 arg1, TCGv arg2)
{
- if (unlikely(ctx->le_mode)) {
+ if (unlikely(need_byteswap(ctx))) {
TCGv_i64 t0 = tcg_temp_new_i64();
tcg_gen_bswap64_i64(t0, arg1);
tcg_gen_qemu_st64(t0, arg2, ctx->mem_idx);
@@ -3049,11 +3058,17 @@ static void gen_std(DisasContext *ctx)
}
#endif
/*** Integer load and store with byte reverse ***/
+
+/* Logic for byteswap test is reversed since these instructions require
+ * a byteswap already. If we need another byteswap due to endianness of
+ * translation context, the two byteswaps cancel out each other.
+ */
+
/* lhbrx */
static inline void gen_qemu_ld16ur(DisasContext *ctx, TCGv arg1, TCGv arg2)
{
tcg_gen_qemu_ld16u(arg1, arg2, ctx->mem_idx);
- if (likely(!ctx->le_mode)) {
+ if (likely(!need_byteswap(ctx))) {
tcg_gen_bswap16_tl(arg1, arg1);
}
}
@@ -3063,7 +3078,7 @@ GEN_LDX(lhbr, ld16ur, 0x16, 0x18, PPC_INTEGER);
static inline void gen_qemu_ld32ur(DisasContext *ctx, TCGv arg1, TCGv arg2)
{
tcg_gen_qemu_ld32u(arg1, arg2, ctx->mem_idx);
- if (likely(!ctx->le_mode)) {
+ if (likely(!need_byteswap(ctx))) {
tcg_gen_bswap32_tl(arg1, arg1);
}
}
@@ -3074,7 +3089,7 @@ GEN_LDX(lwbr, ld32ur, 0x16, 0x10, PPC_INTEGER);
static inline void gen_qemu_ld64ur(DisasContext *ctx, TCGv arg1, TCGv arg2)
{
tcg_gen_qemu_ld64(arg1, arg2, ctx->mem_idx);
- if (likely(!ctx->le_mode)) {
+ if (likely(!need_byteswap(ctx))) {
tcg_gen_bswap64_tl(arg1, arg1);
}
}
@@ -3084,7 +3099,7 @@ GEN_LDX_E(ldbr, ld64ur, 0x14, 0x10, PPC_NONE, PPC2_DBRX);
/* sthbrx */
static inline void gen_qemu_st16r(DisasContext *ctx, TCGv arg1, TCGv arg2)
{
- if (likely(!ctx->le_mode)) {
+ if (likely(!need_byteswap(ctx))) {
TCGv t0 = tcg_temp_new();
tcg_gen_ext16u_tl(t0, arg1);
tcg_gen_bswap16_tl(t0, t0);
@@ -3099,7 +3114,7 @@ GEN_STX(sthbr, st16r, 0x16, 0x1C, PPC_INTEGER);
/* stwbrx */
static inline void gen_qemu_st32r(DisasContext *ctx, TCGv arg1, TCGv arg2)
{
- if (likely(!ctx->le_mode)) {
+ if (likely(!need_byteswap(ctx))) {
TCGv t0 = tcg_temp_new();
tcg_gen_ext32u_tl(t0, arg1);
tcg_gen_bswap32_tl(t0, t0);
@@ -3115,7 +3130,7 @@ GEN_STX(stwbr, st32r, 0x16, 0x14, PPC_INTEGER);
/* stdbrx */
static inline void gen_qemu_st64r(DisasContext *ctx, TCGv arg1, TCGv arg2)
{
- if (likely(!ctx->le_mode)) {
+ if (likely(!need_byteswap(ctx))) {
TCGv t0 = tcg_temp_new();
tcg_gen_bswap64_tl(t0, arg1);
tcg_gen_qemu_st64(t0, arg2, ctx->mem_idx);
@@ -11401,7 +11416,7 @@ static inline void gen_intermediate_code_internal(PowerPCCPU *cpu,
ctx.nip, ctx.mem_idx, (int)msr_ir);
if (num_insns + 1 == max_insns && (tb->cflags & CF_LAST_IO))
gen_io_start();
- if (unlikely(ctx.le_mode)) {
+ if (unlikely(need_byteswap(&ctx))) {
ctx.opcode = bswap32(cpu_ldl_code(env, ctx.nip));
} else {
ctx.opcode = cpu_ldl_code(env, ctx.nip);
diff --git a/target-ppc/translate_init.c b/target-ppc/translate_init.c
index 4d94015..84381ae 100644
--- a/target-ppc/translate_init.c
+++ b/target-ppc/translate_init.c
@@ -8418,6 +8418,9 @@ static void ppc_cpu_reset(CPUState *s)
msr |= (target_ulong)1 << MSR_VR; /* Allow altivec usage */
msr |= (target_ulong)1 << MSR_SPE; /* Allow SPE usage */
msr |= (target_ulong)1 << MSR_PR;
+#if !defined(TARGET_WORDS_BIGENDIAN)
+ msr |= (target_ulong)1 << MSR_LE; /* Little-endian user mode */
+#endif
#endif
#if defined(TARGET_PPC64)
@@ -8461,6 +8464,12 @@ static void ppc_cpu_reset(CPUState *s)
/* Flush all TLBs */
tlb_flush(s, 1);
+
+#if defined(CONFIG_USER_ONLY) && !defined(TARGET_WORDS_BIGENDIAN)
+ if (!msr_le) {
+ cpu_abort(CPU(cpu), "Cannot set QEMU to little-endian user mode\n");
+ }
+#endif
}
static void ppc_cpu_initfn(Object *obj)
--
1.9.1.423.g4596e3a
next prev parent reply other threads:[~2014-05-08 8:27 UTC|newest]
Thread overview: 33+ messages / expand[flat|nested] mbox.gz Atom feed top
2014-05-08 8:26 [Qemu-devel] [PATCH 0/3] Adding new user mode target ppc64el-linux-user Doug Kwan
2014-05-08 8:26 ` [Qemu-devel] [PATCH 1/3] linux-user: Handle ELFv2 PPC64 binaries in user mode Doug Kwan
2014-05-08 8:36 ` Alexander Graf
2014-05-08 8:43 ` Doug Kwan (關振德)
2014-05-08 8:45 ` Alexander Graf
2014-05-08 13:30 ` Ulrich Weigand
2014-05-08 8:26 ` Doug Kwan [this message]
2014-05-08 8:39 ` [Qemu-devel] [PATCH 2/3] PPC: Allow little-endian " Alexander Graf
2014-05-08 8:49 ` Doug Kwan (關振德)
2014-05-08 8:55 ` Alexander Graf
2014-05-08 9:05 ` Doug Kwan (關振德)
2014-05-08 9:11 ` Alexander Graf
2014-05-08 9:24 ` Doug Kwan (關振德)
2014-05-08 12:39 ` Peter Maydell
2014-05-08 12:44 ` Alexander Graf
2014-05-08 8:26 ` [Qemu-devel] [PATCH 3/3] configure: Add new target ppc64el-linux-user Doug Kwan
2014-05-08 8:41 ` Alexander Graf
2014-05-08 8:46 ` Doug Kwan (關振德)
2014-05-08 8:56 ` Alexander Graf
2014-05-08 9:09 ` Doug Kwan (關振德)
2014-05-08 12:18 ` Andreas Färber
2014-05-08 12:28 ` Peter Maydell
2014-05-08 12:45 ` Alexander Graf
2014-05-08 15:57 ` Doug Kwan (關振德)
2014-05-08 14:41 ` Tom Musta
2014-05-08 15:19 ` Doug Kwan (關振德)
2014-05-08 15:25 ` Peter Maydell
2014-05-08 15:32 ` Doug Kwan (關振德)
2014-05-08 15:41 ` Peter Maydell
2014-05-08 15:51 ` Doug Kwan (關振德)
2014-05-08 15:56 ` Peter Maydell
2014-05-08 15:39 ` Tom Musta
2014-05-08 15:43 ` Peter Maydell
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=1399537603-6905-3-git-send-email-dougkwan@google.com \
--to=dougkwan@google.com \
--cc=agraf@suse.de \
--cc=qemu-devel@nongnu.org \
--cc=qemu-ppc@nongnu.org \
--cc=riku.voipio@iki.fi \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
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).