target/arm: Make FEAT_MOPS SET* insns handle Xs == XZR correctly
Most of the registers used by the FEAT_MOPS instructions cannot use 31 as a register field value; this is CONSTRAINED UNPREDICTABLE to NOP or UNDEF (we UNDEF). However, it is permitted for the "source value" register for the memset insns SET* to be 31, which (as usual for most data-processing insns) means it should be the zero register XZR. We forgot to handle this case, with the effect that trying to set memory to zero with a "SET* Xd, Xn, XZR" sets the memory to the value that happens to be in the low byte of SP. Handle XZR when getting the SET* data value from the register file. Signed-off-by: Peter Maydell <peter.maydell@linaro.org> Reviewed-by: Richard Henderson <richard.henderson@linaro.org> Reviewed-by: Philippe Mathieu-Daudé <philmd@linaro.org> Message-id: 20231030174000.3792225-4-peter.maydell@linaro.org
This commit is contained in:
parent
63c1b7de0a
commit
854c001f12
@ -1206,6 +1206,15 @@ static void check_setg_alignment(CPUARMState *env, uint64_t ptr, uint64_t size,
|
||||
}
|
||||
}
|
||||
|
||||
static uint64_t arm_reg_or_xzr(CPUARMState *env, int reg)
|
||||
{
|
||||
/*
|
||||
* Runtime equivalent of cpu_reg() -- return the CPU register value,
|
||||
* for contexts when index 31 means XZR (not SP).
|
||||
*/
|
||||
return reg == 31 ? 0 : env->xregs[reg];
|
||||
}
|
||||
|
||||
/*
|
||||
* For the Memory Set operation, our implementation chooses
|
||||
* always to use "option A", where we update Xd to the final
|
||||
@ -1226,7 +1235,7 @@ static void do_setp(CPUARMState *env, uint32_t syndrome, uint32_t mtedesc,
|
||||
int rd = mops_destreg(syndrome);
|
||||
int rs = mops_srcreg(syndrome);
|
||||
int rn = mops_sizereg(syndrome);
|
||||
uint8_t data = env->xregs[rs];
|
||||
uint8_t data = arm_reg_or_xzr(env, rs);
|
||||
uint32_t memidx = FIELD_EX32(mtedesc, MTEDESC, MIDX);
|
||||
uint64_t toaddr = env->xregs[rd];
|
||||
uint64_t setsize = env->xregs[rn];
|
||||
@ -1286,7 +1295,7 @@ static void do_setm(CPUARMState *env, uint32_t syndrome, uint32_t mtedesc,
|
||||
int rd = mops_destreg(syndrome);
|
||||
int rs = mops_srcreg(syndrome);
|
||||
int rn = mops_sizereg(syndrome);
|
||||
uint8_t data = env->xregs[rs];
|
||||
uint8_t data = arm_reg_or_xzr(env, rs);
|
||||
uint64_t toaddr = env->xregs[rd] + env->xregs[rn];
|
||||
uint64_t setsize = -env->xregs[rn];
|
||||
uint32_t memidx = FIELD_EX32(mtedesc, MTEDESC, MIDX);
|
||||
@ -1349,7 +1358,7 @@ static void do_sete(CPUARMState *env, uint32_t syndrome, uint32_t mtedesc,
|
||||
int rd = mops_destreg(syndrome);
|
||||
int rs = mops_srcreg(syndrome);
|
||||
int rn = mops_sizereg(syndrome);
|
||||
uint8_t data = env->xregs[rs];
|
||||
uint8_t data = arm_reg_or_xzr(env, rs);
|
||||
uint64_t toaddr = env->xregs[rd] + env->xregs[rn];
|
||||
uint64_t setsize = -env->xregs[rn];
|
||||
uint32_t memidx = FIELD_EX32(mtedesc, MTEDESC, MIDX);
|
||||
|
Loading…
Reference in New Issue
Block a user