diff mbox

[1/2] target-arm: Use sextract32() in branch decode

Message ID 1377274359-8707-2-git-send-email-peter.maydell@linaro.org
State Superseded
Headers show

Commit Message

Peter Maydell Aug. 23, 2013, 4:12 p.m. UTC
In the decode of ARM B and BL insns, swap the order of the
"append 2 implicit zeros to imm24" and the sign extend, and
use the new sextract32() utility function to do the latter.
This avoids a direct dependency on the undefined C behaviour
of shifting into the sign bit of an integer.

Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
---
 target-arm/translate.c |    5 +++--
 1 file changed, 3 insertions(+), 2 deletions(-)

Comments

Richard Henderson Aug. 23, 2013, 6:09 p.m. UTC | #1
On 08/23/2013 09:12 AM, Peter Maydell wrote:
> -                offset = (((int32_t)insn << 8) >> 8);
> -                val += (offset << 2) + 4;
> +                offset = sextract32(insn << 2, 0, 26);
> +                val += offset + 4;

I read this incorrectly at first, considering the shift of insn, and
I wonder if it's really the best way to write this because of that.

What about just changing the one line to sextract(insn, 0, 24)?

The second line by itself ought not trigger a warning from clang,
because the << 2 never changes the sign bit.  If it still does,
perhaps just multiply by 4 instead...

It's a stupid warning.  When was the last ones-compliment machine built?


r~
Peter Maydell Aug. 24, 2013, 10:21 a.m. UTC | #2
On 23 August 2013 19:09, Richard Henderson <rth@twiddle.net> wrote:
> On 08/23/2013 09:12 AM, Peter Maydell wrote:
>> -                offset = (((int32_t)insn << 8) >> 8);
>> -                val += (offset << 2) + 4;
>> +                offset = sextract32(insn << 2, 0, 26);
>> +                val += offset + 4;
>
> I read this incorrectly at first, considering the shift of insn, and
> I wonder if it's really the best way to write this because of that.
>
> What about just changing the one line to sextract(insn, 0, 24)?
>
> The second line by itself ought not trigger a warning from clang,
> because the << 2 never changes the sign bit.  If it still does,
> perhaps just multiply by 4 instead...

No, left shift of a negative value is undefined: "If E1 has a signed type
and nonnegative value, and E1 × 2E2 is representable in the result
type, then that is the resulting value; otherwise, the behavior is
undefined."

Also the ARM ARM pseudocode defines this operation as "first
append two zero bits and then sign extend" so I prefer it if we
actually implement it that way round.

> It's a stupid warning.  When was the last ones-compliment machine built?

The stupidity is that the C standard hasn't mandated 2s-complement.

-- PMM
diff mbox

Patch

diff --git a/target-arm/translate.c b/target-arm/translate.c
index d1e8538..ebf5d4f 100644
--- a/target-arm/translate.c
+++ b/target-arm/translate.c
@@ -28,6 +28,7 @@ 
 #include "disas/disas.h"
 #include "tcg-op.h"
 #include "qemu/log.h"
+#include "qemu/bitops.h"
 
 #include "helper.h"
 #define GEN_HELPER 1
@@ -7956,8 +7957,8 @@  static void disas_arm_insn(CPUARMState * env, DisasContext *s)
                     tcg_gen_movi_i32(tmp, val);
                     store_reg(s, 14, tmp);
                 }
-                offset = (((int32_t)insn << 8) >> 8);
-                val += (offset << 2) + 4;
+                offset = sextract32(insn << 2, 0, 26);
+                val += offset + 4;
                 gen_jmp(s, val);
             }
             break;