Disassemble system registers in mrs/msr.
When a system register's name is not known to VIXL, disassemble it in
S<op0>_<op1>_<Cn>_<Cm>_<op2> format.
Change-Id: Ieee267ce758e39670d8440f7fd1b37fdbbbba735
diff --git a/src/aarch64/assembler-aarch64.h b/src/aarch64/assembler-aarch64.h
index 82f90dc..0931f46 100644
--- a/src/aarch64/assembler-aarch64.h
+++ b/src/aarch64/assembler-aarch64.h
@@ -2804,9 +2804,9 @@
return imm16 << ImmException_offset;
}
- static Instr ImmSystemRegister(int imm15) {
- VIXL_ASSERT(IsUint15(imm15));
- return imm15 << ImmSystemRegister_offset;
+ static Instr ImmSystemRegister(int imm16) {
+ VIXL_ASSERT(IsUint16(imm16));
+ return imm16 << ImmSystemRegister_offset;
}
static Instr ImmHint(int imm7) {
diff --git a/src/aarch64/constants-aarch64.h b/src/aarch64/constants-aarch64.h
index 3b2b5da..984c765 100644
--- a/src/aarch64/constants-aarch64.h
+++ b/src/aarch64/constants-aarch64.h
@@ -130,9 +130,10 @@
V_(ImmBarrierType, 9, 8, ExtractBits) \
\
/* System (MRS, MSR, SYS) */ \
-V_(ImmSystemRegister, 19, 5, ExtractBits) \
+V_(ImmSystemRegister, 20, 5, ExtractBits) \
V_(SysO0, 19, 19, ExtractBits) \
V_(SysOp, 18, 5, ExtractBits) \
+V_(SysOp0, 20, 19, ExtractBits) \
V_(SysOp1, 18, 16, ExtractBits) \
V_(SysOp2, 7, 5, ExtractBits) \
V_(CRn, 15, 12, ExtractBits) \
@@ -338,20 +339,23 @@
PSTL3STRM = 0x15
};
+template<int op0, int op1, int crn, int crm, int op2>
+class SystemRegisterEncoder {
+ public:
+ static const uint32_t value =
+ ((op0 << SysO0_offset) |
+ (op1 << SysOp1_offset) |
+ (crn << CRn_offset) |
+ (crm << CRm_offset) |
+ (op2 << SysOp2_offset)) >> ImmSystemRegister_offset;
+};
+
// System/special register names.
// This information is not encoded as one field but as the concatenation of
// multiple fields (Op0<0>, Op1, Crn, Crm, Op2).
enum SystemRegister {
- NZCV = ((0x1 << SysO0_offset) |
- (0x3 << SysOp1_offset) |
- (0x4 << CRn_offset) |
- (0x2 << CRm_offset) |
- (0x0 << SysOp2_offset)) >> ImmSystemRegister_offset,
- FPCR = ((0x1 << SysO0_offset) |
- (0x3 << SysOp1_offset) |
- (0x4 << CRn_offset) |
- (0x4 << CRm_offset) |
- (0x0 << SysOp2_offset)) >> ImmSystemRegister_offset
+ NZCV = SystemRegisterEncoder<3, 3, 4, 2, 0>::value,
+ FPCR = SystemRegisterEncoder<3, 3, 4, 4, 0>::value
};
enum InstructionCacheOp {
diff --git a/src/aarch64/disasm-aarch64.cc b/src/aarch64/disasm-aarch64.cc
index b8cd644..4139190 100644
--- a/src/aarch64/disasm-aarch64.cc
+++ b/src/aarch64/disasm-aarch64.cc
@@ -1740,32 +1740,12 @@
switch (instr->Mask(SystemSysRegMask)) {
case MRS: {
mnemonic = "mrs";
- switch (instr->GetImmSystemRegister()) {
- case NZCV:
- form = "'Xt, nzcv";
- break;
- case FPCR:
- form = "'Xt, fpcr";
- break;
- default:
- form = "'Xt, (unknown)";
- break;
- }
+ form = "'Xt, 'IY";
break;
}
case MSR: {
mnemonic = "msr";
- switch (instr->GetImmSystemRegister()) {
- case NZCV:
- form = "nzcv, 'Xt";
- break;
- case FPCR:
- form = "fpcr, 'Xt";
- break;
- default:
- form = "(unknown), 'Xt";
- break;
- }
+ form = "'IY, 'Xt";
break;
}
}
@@ -4589,6 +4569,25 @@
AppendToOutput("#0x%" PRIx32, instr->GetCRm());
return 2;
}
+ case 'Y': { // IY - system register immediate.
+ switch (instr->GetImmSystemRegister()) {
+ case NZCV:
+ AppendToOutput("nzcv");
+ break;
+ case FPCR:
+ AppendToOutput("fpcr");
+ break;
+ default:
+ AppendToOutput("S%d_%d_%d_%d_%d",
+ instr->GetSysOp0(),
+ instr->GetSysOp1(),
+ instr->GetCRn(),
+ instr->GetCRm(),
+ instr->GetSysOp2());
+ break;
+ }
+ return 2;
+ }
default: {
VIXL_UNIMPLEMENTED();
return 0;
diff --git a/test/aarch64/test-disasm-aarch64.cc b/test/aarch64/test-disasm-aarch64.cc
index a4789d7..b4dc79e 100644
--- a/test/aarch64/test-disasm-aarch64.cc
+++ b/test/aarch64/test-disasm-aarch64.cc
@@ -2790,6 +2790,10 @@
COMPARE(mrs(x30, NZCV), "mrs x30, nzcv");
COMPARE(mrs(x15, FPCR), "mrs x15, fpcr");
+ // Test mrs that use system registers we haven't named.
+ COMPARE(dci(MRS | (0x5555 << 5)), "mrs x0, S3_2_10_10_5");
+ COMPARE(dci(0xd53e1000), "mrs x0, S3_6_1_0_0");
+
CLEANUP();
}
@@ -2801,6 +2805,10 @@
COMPARE(msr(NZCV, x30), "msr nzcv, x30");
COMPARE(msr(FPCR, x15), "msr fpcr, x15");
+ // Test msr that use system registers we haven't named.
+ COMPARE(dci(MSR | (0x1234 << 5)), "msr S2_2_4_6_4, x0");
+ COMPARE(dci(0xd51e1000), "msr S3_6_1_0_0, x0");
+
CLEANUP();
}