aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorJacob Bramley <jacob.bramley@arm.com>2019-01-18 16:01:08 +0000
committerJacob Bramley <jacob.bramley@arm.com>2019-02-21 13:18:51 +0000
commit18c97bde7e79589210a1b156f56e35964174b331 (patch)
treea752e7b4555f9f0ee043ad5d966266760fc2eb86 /src
parentaf0ca0a8e5a90c116e09c359323ef428839df372 (diff)
Add support for UDF.
This is a backwards-incompatible change because we have to add a visitor to keep the semantics correct. Change-Id: I7a5aa95928c9183f85ba833d34d6b024e4ca0e3c
Diffstat (limited to 'src')
-rw-r--r--src/aarch64/assembler-aarch64.cc2
-rw-r--r--src/aarch64/assembler-aarch64.h8
-rw-r--r--src/aarch64/constants-aarch64.h9
-rw-r--r--src/aarch64/cpu-features-auditor-aarch64.cc5
-rw-r--r--src/aarch64/decoder-aarch64.cc1
-rw-r--r--src/aarch64/decoder-aarch64.h14
-rw-r--r--src/aarch64/decoder-constants-aarch64.h10
-rw-r--r--src/aarch64/disasm-aarch64.cc11
-rw-r--r--src/aarch64/instrument-aarch64.cc8
-rw-r--r--src/aarch64/macro-assembler-aarch64.h6
-rw-r--r--src/aarch64/simulator-aarch64.cc12
-rw-r--r--src/aarch64/simulator-aarch64.h13
12 files changed, 88 insertions, 11 deletions
diff --git a/src/aarch64/assembler-aarch64.cc b/src/aarch64/assembler-aarch64.cc
index 094bf86d..74a89fef 100644
--- a/src/aarch64/assembler-aarch64.cc
+++ b/src/aarch64/assembler-aarch64.cc
@@ -5335,6 +5335,8 @@ void Assembler::brk(int code) {
void Assembler::svc(int code) { Emit(SVC | ImmException(code)); }
+void Assembler::udf(int code) { Emit(UDF | ImmUdf(code)); }
+
// TODO(all): The third parameter should be passed by reference but gcc 4.8.2
// reports a bogus uninitialised warning then.
diff --git a/src/aarch64/assembler-aarch64.h b/src/aarch64/assembler-aarch64.h
index ad5773d5..250a0bc3 100644
--- a/src/aarch64/assembler-aarch64.h
+++ b/src/aarch64/assembler-aarch64.h
@@ -2148,6 +2148,9 @@ class Assembler : public vixl::internal::AssemblerBase {
// Generate exception targeting EL1.
void svc(int code);
+ // Generate undefined instruction exception.
+ void udf(int code);
+
// Move register to register.
void mov(const Register& rd, const Register& rn);
@@ -3872,6 +3875,11 @@ class Assembler : public vixl::internal::AssemblerBase {
return imm16 << ImmException_offset;
}
+ static Instr ImmUdf(int imm16) {
+ VIXL_ASSERT(IsUint16(imm16));
+ return imm16 << ImmUdf_offset;
+ }
+
static Instr ImmSystemRegister(int imm16) {
VIXL_ASSERT(IsUint16(imm16));
return imm16 << ImmSystemRegister_offset;
diff --git a/src/aarch64/constants-aarch64.h b/src/aarch64/constants-aarch64.h
index 696bc9ce..30d2a56d 100644
--- a/src/aarch64/constants-aarch64.h
+++ b/src/aarch64/constants-aarch64.h
@@ -131,6 +131,7 @@ V_(ImmException, 20, 5, ExtractBits) \
V_(ImmHint, 11, 5, ExtractBits) \
V_(ImmBarrierDomain, 11, 10, ExtractBits) \
V_(ImmBarrierType, 9, 8, ExtractBits) \
+V_(ImmUdf, 15, 0, ExtractBits) \
\
/* System (MRS, MSR, SYS) */ \
V_(ImmSystemRegister, 20, 5, ExtractBits) \
@@ -2643,6 +2644,14 @@ enum NEONScalarShiftImmediateOp {
NEON_FCVTZU_imm_scalar = NEON_Q | NEONScalar | NEON_FCVTZU_imm
};
+enum ReservedOp {
+ ReservedFixed = 0x00000000,
+ ReservedFMask = 0x1E000000,
+ ReservedMask = 0xFFFF0000,
+
+ UDF = ReservedFixed | 0x00000000
+};
+
// Unimplemented and unallocated instructions. These are defined to make fixed
// bit assertion easier.
enum UnimplementedOp {
diff --git a/src/aarch64/cpu-features-auditor-aarch64.cc b/src/aarch64/cpu-features-auditor-aarch64.cc
index 0a55a780..3207e73b 100644
--- a/src/aarch64/cpu-features-auditor-aarch64.cc
+++ b/src/aarch64/cpu-features-auditor-aarch64.cc
@@ -1167,6 +1167,11 @@ void CPUFeaturesAuditor::VisitUnconditionalBranchToRegister(
}
}
+void CPUFeaturesAuditor::VisitReserved(const Instruction* instr) {
+ RecordInstructionFeaturesScope scope(this);
+ USE(instr);
+}
+
void CPUFeaturesAuditor::VisitUnimplemented(const Instruction* instr) {
RecordInstructionFeaturesScope scope(this);
USE(instr);
diff --git a/src/aarch64/decoder-aarch64.cc b/src/aarch64/decoder-aarch64.cc
index fe72512d..b089e158 100644
--- a/src/aarch64/decoder-aarch64.cc
+++ b/src/aarch64/decoder-aarch64.cc
@@ -292,6 +292,7 @@ BitExtractFn DecodeNode::GetBitExtractFunction(uint32_t mask, uint32_t value) {
INSTANTIATE_TEMPLATE(0xc4000000, 0xc4000000);
INSTANTIATE_TEMPLATE(0xe0000010, 0xa0000000);
INSTANTIATE_TEMPLATE(0xe01c0000, 0x20000000);
+ INSTANTIATE_TEMPLATE(0xe1ff0000, 0x00000000);
#undef INSTANTIATE_TEMPLATE
if (!instantiated) {
diff --git a/src/aarch64/decoder-aarch64.h b/src/aarch64/decoder-aarch64.h
index 5f467152..2deb5789 100644
--- a/src/aarch64/decoder-aarch64.h
+++ b/src/aarch64/decoder-aarch64.h
@@ -119,12 +119,18 @@
V(UnconditionalBranch) \
V(UnconditionalBranchToRegister)
-#define VISITOR_LIST_THAT_DONT_RETURN(V) \
- V(Unallocated) \
+// TODO: We shouldn't expose debug-only behaviour like this. Instead, we should
+// use release-mode aborts where appropriate, and merge thse into a single
+// no-return list.
+#define VISITOR_LIST_THAT_DONT_RETURN_IN_DEBUG_MODE(V) \
+ V(Unallocated) \
V(Unimplemented)
-#define VISITOR_LIST(V) \
- VISITOR_LIST_THAT_RETURN(V) \
+#define VISITOR_LIST_THAT_DONT_RETURN(V) V(Reserved)
+
+#define VISITOR_LIST(V) \
+ VISITOR_LIST_THAT_RETURN(V) \
+ VISITOR_LIST_THAT_DONT_RETURN_IN_DEBUG_MODE(V) \
VISITOR_LIST_THAT_DONT_RETURN(V)
namespace vixl {
diff --git a/src/aarch64/decoder-constants-aarch64.h b/src/aarch64/decoder-constants-aarch64.h
index c0235555..ef048fe8 100644
--- a/src/aarch64/decoder-constants-aarch64.h
+++ b/src/aarch64/decoder-constants-aarch64.h
@@ -38,7 +38,8 @@ namespace aarch64 {
static const DecodeMapping kDecodeMapping[] = {
{ "Root",
{28, 27, 26, 25},
- { {"100x", "DecodeDataProcessingImmediate"},
+ { {"0000", "DecodeReserved"},
+ {"100x", "DecodeDataProcessingImmediate"},
{"101x", "DecodeBranchesExceptionAndSystem"},
{"x1x0", "DecodeLoadsAndStores"},
{"x101", "DecodeDataProcessingRegister"},
@@ -46,6 +47,13 @@ static const DecodeMapping kDecodeMapping[] = {
},
},
+ { "DecodeReserved",
+ {31, 30, 29, 24, 23, 22, 21, 20, 19, 18, 17, 16},
+ { {"000000000000", "VisitReserved"},
+ {"otherwise", "VisitUnallocated"},
+ },
+ },
+
{ "DecodeDataProcessingImmediate",
{25, 24, 23},
{ {"00x", "VisitPCRelAddressing"},
diff --git a/src/aarch64/disasm-aarch64.cc b/src/aarch64/disasm-aarch64.cc
index c3527eec..ab986e1e 100644
--- a/src/aarch64/disasm-aarch64.cc
+++ b/src/aarch64/disasm-aarch64.cc
@@ -4905,6 +4905,13 @@ void Disassembler::VisitNEONPerm(const Instruction *instr) {
}
+void Disassembler::VisitReserved(const Instruction *instr) {
+ // UDF is the only instruction in this group, and the Decoder is precise.
+ VIXL_ASSERT(instr->Mask(ReservedMask) == UDF);
+ Format(instr, "udf", "'IUdf");
+}
+
+
void Disassembler::VisitUnimplemented(const Instruction *instr) {
Format(instr, "unimplemented", "(Unimplemented)");
}
@@ -5443,6 +5450,10 @@ int Disassembler::SubstituteImmediateField(const Instruction *instr,
AppendToOutput("#0x%" PRIx32, instr->GetImmException());
return 6;
}
+ case 'U': { // IUdf - UDF immediate.
+ AppendToOutput("#0x%" PRIx32, instr->GetImmUdf());
+ return 4;
+ }
case 'V': { // Immediate Vector.
switch (format[2]) {
case 'F': {
diff --git a/src/aarch64/instrument-aarch64.cc b/src/aarch64/instrument-aarch64.cc
index 02a1083e..72132877 100644
--- a/src/aarch64/instrument-aarch64.cc
+++ b/src/aarch64/instrument-aarch64.cc
@@ -947,6 +947,14 @@ void Instrument::VisitNEONPerm(const Instruction* instr) {
}
+void Instrument::VisitReserved(const Instruction* instr) {
+ USE(instr);
+ Update();
+ static Counter* counter = GetCounter("Other");
+ counter->Increment();
+}
+
+
void Instrument::VisitUnallocated(const Instruction* instr) {
USE(instr);
Update();
diff --git a/src/aarch64/macro-assembler-aarch64.h b/src/aarch64/macro-assembler-aarch64.h
index fe95b831..d2f41132 100644
--- a/src/aarch64/macro-assembler-aarch64.h
+++ b/src/aarch64/macro-assembler-aarch64.h
@@ -2585,9 +2585,9 @@ class MacroAssembler : public Assembler, public MacroAssemblerInterface {
if (generate_simulator_code_) {
hlt(kUnreachableOpcode);
} else {
- // Branch to 0 to generate a segfault.
- // lr - kInstructionSize is the address of the offending instruction.
- blr(xzr);
+ // Use the architecturally-defined UDF instruction to abort on hardware,
+ // because using HLT and BRK tends to make the process difficult to debug.
+ udf(kUnreachableOpcode);
}
}
void Uxtb(const Register& rd, const Register& rn) {
diff --git a/src/aarch64/simulator-aarch64.cc b/src/aarch64/simulator-aarch64.cc
index 80a99c74..b2b06d92 100644
--- a/src/aarch64/simulator-aarch64.cc
+++ b/src/aarch64/simulator-aarch64.cc
@@ -1050,6 +1050,18 @@ void Simulator::PrintTakenBranch(const Instruction* target) {
// Visitors---------------------------------------------------------------------
+
+void Simulator::VisitReserved(const Instruction* instr) {
+ // UDF is the only instruction in this group, and the Decoder is precise here.
+ VIXL_ASSERT(instr->Mask(ReservedMask) == UDF);
+
+ printf("UDF (permanently undefined) instruction at %p: 0x%08" PRIx32 "\n",
+ reinterpret_cast<const void*>(instr),
+ instr->GetInstructionBits());
+ VIXL_ABORT_WITH_MSG("UNDEFINED (UDF)\n");
+}
+
+
void Simulator::VisitUnimplemented(const Instruction* instr) {
printf("Unimplemented instruction at %p: 0x%08" PRIx32 "\n",
reinterpret_cast<const void*>(instr),
diff --git a/src/aarch64/simulator-aarch64.h b/src/aarch64/simulator-aarch64.h
index 13803e4f..3c9d146f 100644
--- a/src/aarch64/simulator-aarch64.h
+++ b/src/aarch64/simulator-aarch64.h
@@ -767,13 +767,20 @@ class Simulator : public DecoderVisitor {
VISITOR_LIST_THAT_RETURN(DECLARE)
#undef DECLARE
-#define DECLARE(A) \
- VIXL_DEBUG_NO_RETURN virtual void Visit##A(const Instruction* instr) \
- VIXL_OVERRIDE;
+
+#define DECLARE(A) \
+ VIXL_NO_RETURN virtual void Visit##A(const Instruction* instr) VIXL_OVERRIDE;
VISITOR_LIST_THAT_DONT_RETURN(DECLARE)
#undef DECLARE
+#define DECLARE(A) \
+ VIXL_NO_RETURN_IN_DEBUG_MODE virtual void Visit##A(const Instruction* instr) \
+ VIXL_OVERRIDE;
+ VISITOR_LIST_THAT_DONT_RETURN_IN_DEBUG_MODE(DECLARE)
+#undef DECLARE
+
+
// Integer register accessors.
// Basic accessor: Read the register as the specified type.