* [PATCH] target/arm: Permit T32 LDM with single register
@ 2023-09-27 10:18 Peter Maydell
2023-09-27 10:58 ` Alex Bennée
2023-09-28 20:49 ` Richard Henderson
0 siblings, 2 replies; 3+ messages in thread
From: Peter Maydell @ 2023-09-27 10:18 UTC (permalink / raw)
To: qemu-arm, qemu-devel
For the Thumb T32 encoding of LDM, if only a single register is
specified in the register list this instruction is UNPREDICTABLE,
with the following choices:
* instruction UNDEFs
* instruction is a NOP
* instruction loads a single register
* instruction loads an unspecified set of registers
Currently we choose to UNDEF (a behaviour chosen in commit
4b222545dbf30 in 2019; previously we treated it as "load the
specified single register").
Unfortunately there is real world code out there (which shipped in at
least Android 11, 12 and 13) which incorrectly uses this
UNPREDICTABLE insn on the assumption that it does a single register
load, which is (presumably) what it happens to do on real hardware,
and is also what it does on the equivalent A32 encoding.
Revert to the pre-4b222545dbf30 behaviour of not UNDEFing
for this T32 encoding.
Resolves: https://gitlab.com/qemu-project/qemu/-/issues/1799
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
---
target/arm/tcg/translate.c | 37 +++++++++++++++++++++++--------------
1 file changed, 23 insertions(+), 14 deletions(-)
diff --git a/target/arm/tcg/translate.c b/target/arm/tcg/translate.c
index d83a0e772cd..32a0fa1d1fb 100644
--- a/target/arm/tcg/translate.c
+++ b/target/arm/tcg/translate.c
@@ -7882,7 +7882,7 @@ static void op_addr_block_post(DisasContext *s, arg_ldst_block *a,
}
}
-static bool op_stm(DisasContext *s, arg_ldst_block *a, int min_n)
+static bool op_stm(DisasContext *s, arg_ldst_block *a)
{
int i, j, n, list, mem_idx;
bool user = a->u;
@@ -7899,7 +7899,14 @@ static bool op_stm(DisasContext *s, arg_ldst_block *a, int min_n)
list = a->list;
n = ctpop16(list);
- if (n < min_n || a->rn == 15) {
+ /*
+ * This is UNPREDICTABLE for n < 1 in all encodings, and we choose
+ * to UNDEF. In the T32 STM encoding n == 1 is also UNPREDICTABLE,
+ * but hardware treats it like the A32 version and implements the
+ * single-register-store, and some in-the-wild (buggy) software
+ * assumes that, so we don't UNDEF on that case.
+ */
+ if (n < 1 || a->rn == 15) {
unallocated_encoding(s);
return true;
}
@@ -7935,8 +7942,7 @@ static bool op_stm(DisasContext *s, arg_ldst_block *a, int min_n)
static bool trans_STM(DisasContext *s, arg_ldst_block *a)
{
- /* BitCount(list) < 1 is UNPREDICTABLE */
- return op_stm(s, a, 1);
+ return op_stm(s, a);
}
static bool trans_STM_t32(DisasContext *s, arg_ldst_block *a)
@@ -7946,11 +7952,10 @@ static bool trans_STM_t32(DisasContext *s, arg_ldst_block *a)
unallocated_encoding(s);
return true;
}
- /* BitCount(list) < 2 is UNPREDICTABLE */
- return op_stm(s, a, 2);
+ return op_stm(s, a);
}
-static bool do_ldm(DisasContext *s, arg_ldst_block *a, int min_n)
+static bool do_ldm(DisasContext *s, arg_ldst_block *a)
{
int i, j, n, list, mem_idx;
bool loaded_base;
@@ -7979,7 +7984,14 @@ static bool do_ldm(DisasContext *s, arg_ldst_block *a, int min_n)
list = a->list;
n = ctpop16(list);
- if (n < min_n || a->rn == 15) {
+ /*
+ * This is UNPREDICTABLE for n < 1 in all encodings, and we choose
+ * to UNDEF. In the T32 LDM encoding n == 1 is also UNPREDICTABLE,
+ * but hardware treats it like the A32 version and implements the
+ * single-register-load, and some in-the-wild (buggy) software
+ * assumes that, so we don't UNDEF on that case.
+ */
+ if (n < 1 || a->rn == 15) {
unallocated_encoding(s);
return true;
}
@@ -8045,8 +8057,7 @@ static bool trans_LDM_a32(DisasContext *s, arg_ldst_block *a)
unallocated_encoding(s);
return true;
}
- /* BitCount(list) < 1 is UNPREDICTABLE */
- return do_ldm(s, a, 1);
+ return do_ldm(s, a);
}
static bool trans_LDM_t32(DisasContext *s, arg_ldst_block *a)
@@ -8056,16 +8067,14 @@ static bool trans_LDM_t32(DisasContext *s, arg_ldst_block *a)
unallocated_encoding(s);
return true;
}
- /* BitCount(list) < 2 is UNPREDICTABLE */
- return do_ldm(s, a, 2);
+ return do_ldm(s, a);
}
static bool trans_LDM_t16(DisasContext *s, arg_ldst_block *a)
{
/* Writeback is conditional on the base register not being loaded. */
a->w = !(a->list & (1 << a->rn));
- /* BitCount(list) < 1 is UNPREDICTABLE */
- return do_ldm(s, a, 1);
+ return do_ldm(s, a);
}
static bool trans_CLRM(DisasContext *s, arg_CLRM *a)
--
2.34.1
^ permalink raw reply related [flat|nested] 3+ messages in thread
* Re: [PATCH] target/arm: Permit T32 LDM with single register
2023-09-27 10:18 [PATCH] target/arm: Permit T32 LDM with single register Peter Maydell
@ 2023-09-27 10:58 ` Alex Bennée
2023-09-28 20:49 ` Richard Henderson
1 sibling, 0 replies; 3+ messages in thread
From: Alex Bennée @ 2023-09-27 10:58 UTC (permalink / raw)
To: Peter Maydell; +Cc: qemu-devel, qemu-arm
Peter Maydell <peter.maydell@linaro.org> writes:
> For the Thumb T32 encoding of LDM, if only a single register is
> specified in the register list this instruction is UNPREDICTABLE,
> with the following choices:
> * instruction UNDEFs
> * instruction is a NOP
> * instruction loads a single register
> * instruction loads an unspecified set of registers
>
> Currently we choose to UNDEF (a behaviour chosen in commit
> 4b222545dbf30 in 2019; previously we treated it as "load the
> specified single register").
>
> Unfortunately there is real world code out there (which shipped in at
> least Android 11, 12 and 13) which incorrectly uses this
> UNPREDICTABLE insn on the assumption that it does a single register
> load, which is (presumably) what it happens to do on real hardware,
> and is also what it does on the equivalent A32 encoding.
>
> Revert to the pre-4b222545dbf30 behaviour of not UNDEFing
> for this T32 encoding.
>
> Resolves: https://gitlab.com/qemu-project/qemu/-/issues/1799
> Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
Reviewed-by: Alex Bennée <alex.bennee@linaro.org>
--
Alex Bennée
Virtualisation Tech Lead @ Linaro
^ permalink raw reply [flat|nested] 3+ messages in thread
* Re: [PATCH] target/arm: Permit T32 LDM with single register
2023-09-27 10:18 [PATCH] target/arm: Permit T32 LDM with single register Peter Maydell
2023-09-27 10:58 ` Alex Bennée
@ 2023-09-28 20:49 ` Richard Henderson
1 sibling, 0 replies; 3+ messages in thread
From: Richard Henderson @ 2023-09-28 20:49 UTC (permalink / raw)
To: Peter Maydell, qemu-arm, qemu-devel
On 9/27/23 06:18, Peter Maydell wrote:
> For the Thumb T32 encoding of LDM, if only a single register is
> specified in the register list this instruction is UNPREDICTABLE,
> with the following choices:
> * instruction UNDEFs
> * instruction is a NOP
> * instruction loads a single register
> * instruction loads an unspecified set of registers
>
> Currently we choose to UNDEF (a behaviour chosen in commit
> 4b222545dbf30 in 2019; previously we treated it as "load the
> specified single register").
>
> Unfortunately there is real world code out there (which shipped in at
> least Android 11, 12 and 13) which incorrectly uses this
> UNPREDICTABLE insn on the assumption that it does a single register
> load, which is (presumably) what it happens to do on real hardware,
> and is also what it does on the equivalent A32 encoding.
>
> Revert to the pre-4b222545dbf30 behaviour of not UNDEFing
> for this T32 encoding.
>
> Resolves:https://gitlab.com/qemu-project/qemu/-/issues/1799
> Signed-off-by: Peter Maydell<peter.maydell@linaro.org>
> ---
> target/arm/tcg/translate.c | 37 +++++++++++++++++++++++--------------
> 1 file changed, 23 insertions(+), 14 deletions(-)
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
r~
^ permalink raw reply [flat|nested] 3+ messages in thread
end of thread, other threads:[~2023-09-28 20:50 UTC | newest]
Thread overview: 3+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2023-09-27 10:18 [PATCH] target/arm: Permit T32 LDM with single register Peter Maydell
2023-09-27 10:58 ` Alex Bennée
2023-09-28 20:49 ` Richard Henderson
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).