diff options
author | Martyn Capewell <martyn.capewell@arm.com> | 2020-08-11 16:19:43 +0100 |
---|---|---|
committer | Martyn Capewell <martyn.capewell@arm.com> | 2020-08-13 14:20:36 +0000 |
commit | 8ed835274dc2846cd60d34cdcd79ecfa07ac6ed9 (patch) | |
tree | 2da9f40da06da9635241bdf08f72f9cd5e71327d /src | |
parent | 32a7cd97fbcef211d5812e2eef2d4dd134f736b0 (diff) | |
download | vixl-8ed835274dc2846cd60d34cdcd79ecfa07ac6ed9.tar.gz |
[sve] Disallow dup with shift on byte-sized lanes
The Arm ARM states dup-immediate with shift on byte-sized lanes is an undefined
encoding, so add assertions in the assembler to disallow this, and handle
the encoding appropriately in the disassembler and simulator.
Change-Id: Ibce08d2577e2b780dbb7e4fa478d2f8d18e99a39
Diffstat (limited to 'src')
-rw-r--r-- | src/aarch64/assembler-sve-aarch64.cc | 1 | ||||
-rw-r--r-- | src/aarch64/disasm-aarch64.cc | 5 | ||||
-rw-r--r-- | src/aarch64/simulator-aarch64.cc | 11 |
3 files changed, 15 insertions, 2 deletions
diff --git a/src/aarch64/assembler-sve-aarch64.cc b/src/aarch64/assembler-sve-aarch64.cc index c33e8552..f7cf8b21 100644 --- a/src/aarch64/assembler-sve-aarch64.cc +++ b/src/aarch64/assembler-sve-aarch64.cc @@ -3615,6 +3615,7 @@ void Assembler::dup(const ZRegister& zd, int imm8, int shift) { VIXL_ASSERT(CPUHas(CPUFeatures::kSVE)); ResolveSVEImm8Shift(&imm8, &shift); + VIXL_ASSERT((shift < 8) || !zd.IsLaneSizeB()); Instr shift_bit = (shift > 0) ? (1 << 13) : 0; Emit(DUP_z_i | SVESize(zd) | Rd(zd) | shift_bit | ImmField<12, 5>(imm8)); diff --git a/src/aarch64/disasm-aarch64.cc b/src/aarch64/disasm-aarch64.cc index 4e2bca35..d8ac2d24 100644 --- a/src/aarch64/disasm-aarch64.cc +++ b/src/aarch64/disasm-aarch64.cc @@ -5996,6 +5996,11 @@ void Disassembler::VisitSVEBroadcastIntImm_Unpredicated( switch (instr->Mask(SVEBroadcastIntImm_UnpredicatedMask)) { case DUP_z_i: + // The encoding of byte-sized lanes with lsl #8 is undefined. + if ((instr->GetSVEVectorFormat() == kFormatVnB) && + (instr->ExtractBit(13) == 1)) + break; + // The preferred disassembly for dup is "mov". mnemonic = "mov"; form = (instr->ExtractBit(13) == 0) ? "'Zd.'t, #'s1205" diff --git a/src/aarch64/simulator-aarch64.cc b/src/aarch64/simulator-aarch64.cc index e1026cec..6d6d1677 100644 --- a/src/aarch64/simulator-aarch64.cc +++ b/src/aarch64/simulator-aarch64.cc @@ -9474,12 +9474,19 @@ void Simulator::VisitSVEIntAddSubtractImm_Unpredicated( void Simulator::VisitSVEBroadcastIntImm_Unpredicated(const Instruction* instr) { SimVRegister& zd = ReadVRegister(instr->GetRd()); + VectorFormat format = instr->GetSVEVectorFormat(); int64_t imm = instr->GetImmSVEIntWideSigned(); - imm <<= instr->ExtractBit(13) * 8; + int shift = instr->ExtractBit(13) * 8; + imm *= 1 << shift; switch (instr->Mask(SVEBroadcastIntImm_UnpredicatedMask)) { case DUP_z_i: - dup_immediate(instr->GetSVEVectorFormat(), zd, imm); + // The encoding of byte-sized lanes with lsl #8 is undefined. + if ((format == kFormatVnB) && (shift == 8)) { + VIXL_UNIMPLEMENTED(); + } else { + dup_immediate(format, zd, imm); + } break; default: VIXL_UNIMPLEMENTED(); |