qemu-devel
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[Qemu-devel] [PATCH] target/mips: Fix microMIPS jumps in 128MB block


From: James Hogan
Subject: [Qemu-devel] [PATCH] target/mips: Fix microMIPS jumps in 128MB block
Date: Wed, 19 Jul 2017 16:21:42 +0100

Three microMIPS jump instruction encodings (namely J32, JAL32, JALS32)
shift their 26-bit immediate field by 1 instead of 2, allowing a jump
only within the 128MB aligned block rather than the more common 256MB
aligned block.

This wasn't being taken into account when masking the address of the
delay slot in gen_compute_branch(), resulting in bit 27 of the PC being
cleared. This meant that any such jump in an odd 128MB block incorrectly
jumped to the even 128MB block before it.

For example this jals jumped to 0x17000010:
1f00000a:       7780 0008       jals    1f000010 <.L11>

And this jal jumped to 0x17000022:
1f00001a:       f780 0011       jal     1f000022 <.L12>

And this j jumped to 0x17000030:
1f00002a:       d780 0018       j       1f000030 <.L13>

All three encodings pass OPC_J or OPC_JAL to gen_compute_branch(), so
allow the mask applied to the delay slot address to be changed from
0xF0000000 to 0xF8000000 for these opcodes, but only when microMIPS is
in use.

Fixes: 3c824109da07 ("target-mips: microMIPS ASE support")
Signed-off-by: James Hogan <address@hidden>
Cc: Yongbok Kim <address@hidden>
Cc: Aurelien Jarno <address@hidden>
Cc: Nathan Froyd <address@hidden>
---
 target/mips/translate.c |  9 ++++++++-
 1 file changed, 8 insertions(+), 1 deletion(-)

diff --git a/target/mips/translate.c b/target/mips/translate.c
index 3022f349cb2a..7071b124344a 100644
--- a/target/mips/translate.c
+++ b/target/mips/translate.c
@@ -4248,6 +4248,7 @@ static void gen_compute_branch (DisasContext *ctx, 
uint32_t opc,
     int bcond_compute = 0;
     TCGv t0 = tcg_temp_new();
     TCGv t1 = tcg_temp_new();
+    int32_t seg_mask = 0xF0000000;      /* 256 MB-aligned region */
 
     if (ctx->hflags & MIPS_HFLAG_BMASK) {
 #ifdef MIPS_DEBUG_DISAS
@@ -4303,9 +4304,15 @@ static void gen_compute_branch (DisasContext *ctx, 
uint32_t opc,
         break;
     case OPC_J:
     case OPC_JAL:
+        /* microMIPS J32, JAL32 & JALS32 offsets are in 128 MB region not 256 
*/
+        if ((ctx->hflags & MIPS_HFLAG_M16) &&
+            (ctx->insn_flags & ASE_MICROMIPS)) {
+            seg_mask = 0xF8000000;      /* 128 MB-aligned region */
+        }
+        /* fall through */
     case OPC_JALX:
         /* Jump to immediate */
-        btgt = ((ctx->pc + insn_bytes) & (int32_t)0xF0000000) | 
(uint32_t)offset;
+        btgt = ((ctx->pc + insn_bytes) & seg_mask) | (uint32_t)offset;
         break;
     case OPC_JR:
     case OPC_JALR:
-- 
git-series 0.8.10



reply via email to

[Prev in Thread] Current Thread [Next in Thread]