aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorMartyn Capewell <martyn.capewell@arm.com>2020-10-28 14:55:49 +0000
committerArtem Serov <artem.serov@linaro.org>2021-02-19 15:12:56 +0000
commite739be0b8a46d3e35b8a21870cadf44f0ef86c8e (patch)
treecf484e52da486c01126e8da20c89d2793b70b9ff /src
parentcd42a2b85f4c3e25e21f71fd45c870f84174999c (diff)
downloadvixl-e739be0b8a46d3e35b8a21870cadf44f0ef86c8e.tar.gz
[sve] Fix while simulation corner case
The simulation of while was computing differences using 64-bit variables, which didn't handle the overflow cases correctly for W-sized registers. Fix and add a regression test. Note: this is a cherry-pick patch from VIXL usptream; it affects VIXL simulator only, no impact for the ART release build. Author: Martyn Capewell. Commiter: Artem Serov. Change-Id: I681f6ecb137d52830a58816fa34545342e6eb6bf
Diffstat (limited to 'src')
-rw-r--r--src/aarch64/simulator-aarch64.cc22
1 files changed, 15 insertions, 7 deletions
diff --git a/src/aarch64/simulator-aarch64.cc b/src/aarch64/simulator-aarch64.cc
index cae59b21..04f1165d 100644
--- a/src/aarch64/simulator-aarch64.cc
+++ b/src/aarch64/simulator-aarch64.cc
@@ -8964,25 +8964,33 @@ void Simulator::VisitSVEIntCompareScalarCountAndLimit(
unsigned rm_code = instr->GetRm();
SimPRegister& pd = ReadPRegister(instr->GetPd());
VectorFormat vform = instr->GetSVEVectorFormat();
+
bool is_64_bit = instr->ExtractBit(12) == 1;
- int64_t src1 = is_64_bit ? ReadXRegister(rn_code) : ReadWRegister(rn_code);
- int64_t src2 = is_64_bit ? ReadXRegister(rm_code) : ReadWRegister(rm_code);
+ int rsize = is_64_bit ? kXRegSize : kWRegSize;
+ uint64_t mask = is_64_bit ? kXRegMask : kWRegMask;
+
+ uint64_t usrc1 = ReadXRegister(rn_code);
+ int64_t ssrc2 = is_64_bit ? ReadXRegister(rm_code) : ReadWRegister(rm_code);
+ uint64_t usrc2 = ssrc2 & mask;
bool last = true;
for (int lane = 0; lane < LaneCountFromFormat(vform); lane++) {
+ usrc1 &= mask;
+ int64_t ssrc1 = ExtractSignedBitfield64(rsize - 1, 0, usrc1);
+
bool cond = false;
switch (instr->Mask(SVEIntCompareScalarCountAndLimitMask)) {
case WHILELE_p_p_rr:
- cond = src1 <= src2;
+ cond = ssrc1 <= ssrc2;
break;
case WHILELO_p_p_rr:
- cond = static_cast<uint64_t>(src1) < static_cast<uint64_t>(src2);
+ cond = usrc1 < usrc2;
break;
case WHILELS_p_p_rr:
- cond = static_cast<uint64_t>(src1) <= static_cast<uint64_t>(src2);
+ cond = usrc1 <= usrc2;
break;
case WHILELT_p_p_rr:
- cond = src1 < src2;
+ cond = ssrc1 < ssrc2;
break;
default:
VIXL_UNIMPLEMENTED();
@@ -8991,7 +8999,7 @@ void Simulator::VisitSVEIntCompareScalarCountAndLimit(
last = last && cond;
LogicPRegister dst(pd);
dst.SetActive(vform, lane, last);
- src1 += 1;
+ usrc1++;
}
PredTest(vform, GetPTrue(), pd);