llvm.org GIT mirror llvm / 3524723
AArch64/ARM64: implement diagnosis of unpredictable loads & stores git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@208091 91177308-0d34-0410-b5e6-96231b3b80d8 Tim Northover 6 years ago
3 changed file(s) with 70 addition(s) and 21 deletion(s). Raw diff Collapse all Expand all
169169 static DecodeStatus DecodeVecShiftL8Imm(llvm::MCInst &Inst, unsigned Imm,
170170 uint64_t Addr, const void *Decoder);
171171
172 static bool Check(DecodeStatus &Out, DecodeStatus In) {
173 switch (In) {
174 case MCDisassembler::Success:
175 // Out stays the same.
176 return true;
177 case MCDisassembler::SoftFail:
178 Out = In;
179 return true;
180 case MCDisassembler::Fail:
181 Out = In;
182 return false;
183 }
184 llvm_unreachable("Invalid DecodeStatus!");
185 }
186
172187 #include "ARM64GenDisassemblerTables.inc"
173188 #include "ARM64GenInstrInfo.inc"
174189
175190 #define Success llvm::MCDisassembler::Success
176191 #define Fail llvm::MCDisassembler::Fail
192 #define SoftFail llvm::MCDisassembler::SoftFail
177193
178194 static MCDisassembler *createARM64Disassembler(const Target &T,
179195 const MCSubtargetInfo &STI,
201217 (bytes[3] << 24) | (bytes[2] << 16) | (bytes[1] << 8) | (bytes[0] << 0);
202218
203219 // Calling the auto-generated decoder function.
204 DecodeStatus result =
205 decodeInstruction(DecoderTable32, MI, insn, Address, this, STI);
206 if (!result)
207 return Fail;
208
209 return Success;
220 return decodeInstruction(DecoderTable32, MI, insn, Address, this, STI);
210221 }
211222
212223 static MCSymbolizer *
966977
967978 DecodeGPR64spRegisterClass(Inst, Rn, Addr, Decoder);
968979 Inst.addOperand(MCOperand::CreateImm(offset));
980
981 bool IsLoad = fieldFromInstruction(insn, 22, 1);
982 bool IsIndexed = fieldFromInstruction(insn, 10, 2) != 0;
983 bool IsFP = fieldFromInstruction(insn, 26, 1);
984
985 // Cannot write back to a transfer register (but xzr != sp).
986 if (IsLoad && IsIndexed && !IsFP && Rn != 31 && Rt == Rn)
987 return SoftFail;
988
969989 return Success;
970990 }
971991
977997 unsigned Rt2 = fieldFromInstruction(insn, 10, 5);
978998 unsigned Rs = fieldFromInstruction(insn, 16, 5);
979999
980 switch (Inst.getOpcode()) {
1000 unsigned Opcode = Inst.getOpcode();
1001 switch (Opcode) {
9811002 default:
9821003 return Fail;
9831004 case ARM64::STLXRW:
10331054 }
10341055
10351056 DecodeGPR64spRegisterClass(Inst, Rn, Addr, Decoder);
1057
1058 // You shouldn't load to the same register twice in an instruction...
1059 if ((Opcode == ARM64::LDAXPW || Opcode == ARM64::LDXPW ||
1060 Opcode == ARM64::LDAXPX || Opcode == ARM64::LDXPX) &&
1061 Rt == Rt2)
1062 return SoftFail;
1063
10361064 return Success;
10371065 }
10381066
10431071 unsigned Rn = fieldFromInstruction(insn, 5, 5);
10441072 unsigned Rt2 = fieldFromInstruction(insn, 10, 5);
10451073 int64_t offset = fieldFromInstruction(insn, 15, 7);
1074 bool IsLoad = fieldFromInstruction(insn, 22, 1);
10461075
10471076 // offset is a 7-bit signed immediate, so sign extend it to
10481077 // fill the unsigned.
10491078 if (offset & (1 << (7 - 1)))
10501079 offset |= ~((1LL << 7) - 1);
10511080
1052 switch (Inst.getOpcode()) {
1081 unsigned Opcode = Inst.getOpcode();
1082 bool NeedsDisjointWritebackTransfer = false;
1083 switch (Opcode) {
10531084 default:
10541085 return Fail;
1055 case ARM64::LDNPXi:
1056 case ARM64::STNPXi:
10571086 case ARM64::LDPXpost:
10581087 case ARM64::STPXpost:
10591088 case ARM64::LDPSWpost:
1089 case ARM64::LDPXpre:
1090 case ARM64::STPXpre:
1091 case ARM64::LDPSWpre:
1092 NeedsDisjointWritebackTransfer = true;
1093 // Fallthrough
1094 case ARM64::LDNPXi:
1095 case ARM64::STNPXi:
10601096 case ARM64::LDPXi:
10611097 case ARM64::STPXi:
10621098 case ARM64::LDPSWi:
1063 case ARM64::LDPXpre:
1064 case ARM64::STPXpre:
1065 case ARM64::LDPSWpre:
10661099 DecodeGPR64RegisterClass(Inst, Rt, Addr, Decoder);
10671100 DecodeGPR64RegisterClass(Inst, Rt2, Addr, Decoder);
10681101 break;
1102 case ARM64::LDPWpost:
1103 case ARM64::STPWpost:
1104 case ARM64::LDPWpre:
1105 case ARM64::STPWpre:
1106 NeedsDisjointWritebackTransfer = true;
1107 // Fallthrough
10691108 case ARM64::LDNPWi:
10701109 case ARM64::STNPWi:
1071 case ARM64::LDPWpost:
1072 case ARM64::STPWpost:
10731110 case ARM64::LDPWi:
10741111 case ARM64::STPWi:
1075 case ARM64::LDPWpre:
1076 case ARM64::STPWpre:
10771112 DecodeGPR32RegisterClass(Inst, Rt, Addr, Decoder);
10781113 DecodeGPR32RegisterClass(Inst, Rt2, Addr, Decoder);
10791114 break;
11141149
11151150 DecodeGPR64spRegisterClass(Inst, Rn, Addr, Decoder);
11161151 Inst.addOperand(MCOperand::CreateImm(offset));
1152
1153 // You shouldn't load to the same register twice in an instruction...
1154 if (IsLoad && Rt == Rt2)
1155 return SoftFail;
1156
1157 // ... or do any operation that writes-back to a transfer register. But note
1158 // that "stp xzr, xzr, [sp], #4" is fine because xzr and sp are different.
1159 if (NeedsDisjointWritebackTransfer && Rn != 31 && (Rt == Rn || Rt2 == Rn))
1160 return SoftFail;
1161
11171162 return Success;
11181163 }
11191164
0 # RUN: llvm-mc -triple=aarch64 -mattr=+fp-armv8 -disassemble < %s 2>&1 | FileCheck %s
1 # RUN: llvm-mc -triple=arm64 -mattr=+fp-armv8 -disassemble < %s 2>&1 | FileCheck %s
12
23 #------------------------------------------------------------------------------
34 # Load-store exclusive
126126 }
127127
128128 // ARM and Thumb have a CHECK() macro to deal with DecodeStatuses.
129 if (Target.getName() == "ARM" ||
130 Target.getName() == "Thumb" ||
131 Target.getName() == "AArch64") {
132 EmitFixedLenDecoder(Records, OS, Target.getName() == "AArch64" ? "AArch64" : "ARM",
129 if (Target.getName() == "ARM" || Target.getName() == "Thumb" ||
130 Target.getName() == "AArch64" || Target.getName() == "ARM64") {
131 std::string PredicateNamespace = Target.getName();
132 if (PredicateNamespace == "Thumb")
133 PredicateNamespace = "ARM";
134
135 EmitFixedLenDecoder(Records, OS, PredicateNamespace,
133136 "if (!Check(S, ", ")) return MCDisassembler::Fail;",
134137 "S", "MCDisassembler::Fail",
135138 " MCDisassembler::DecodeStatus S = "