aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorJacob Bramley <jacob.bramley@arm.com>2018-08-24 17:51:52 +0100
committerJacob Bramley <jacob.bramley@arm.com>2018-08-28 15:33:22 +0100
commit364c82b15129b5f168e450356ee0abd0e62ffa15 (patch)
treee89f3c234f7fd410d0c161da877cbade81167823 /src
parentf658ca1813c32f483f20f75a4be0947ef66b442f (diff)
Make disassembly of FC* more precise.
FCADD and FCMLA both span multiple opcodes, so it is not easy to represent them with the Fixed/FMask/Mask structure that we usually use. In particular, the Disassembler and Simulator would handle some unallocated encodings as FCADD instructions. This patch makes disassembly precise. Change-Id: Ia0bda19489b2a1744b52a717ee7d6dc1b309184d
Diffstat (limited to 'src')
-rw-r--r--src/aarch64/constants-aarch64.h8
-rw-r--r--src/aarch64/decoder-aarch64.cc26
-rw-r--r--src/aarch64/disasm-aarch64.cc19
-rw-r--r--src/aarch64/simulator-aarch64.cc20
4 files changed, 40 insertions, 33 deletions
diff --git a/src/aarch64/constants-aarch64.h b/src/aarch64/constants-aarch64.h
index b0a5975f..d3d403fd 100644
--- a/src/aarch64/constants-aarch64.h
+++ b/src/aarch64/constants-aarch64.h
@@ -1608,10 +1608,14 @@ enum NEON3SameExtraOp {
/* v8.3 Complex Numbers */
NEON3SameExtraFCFixed = 0x2E00C400,
- NEON3SameExtraFCFMask = 0xBE20C400,
- NEON3SameExtraFCMask = 0xBE20E400,
+ NEON3SameExtraFCFMask = 0xBF20C400,
+ // FCMLA fixes opcode<3:2>, and uses opcode<1:0> to encode <rotate>.
+ NEON3SameExtraFCMLAMask = NEON3SameExtraFCFMask | 0x00006000,
NEON_FCMLA = NEON3SameExtraFCFixed,
+ // FCADD fixes opcode<3:2, 0>, and uses opcode<1> to encode <rotate>.
+ NEON3SameExtraFCADDMask = NEON3SameExtraFCFMask | 0x00006800,
NEON_FCADD = NEON3SameExtraFCFixed | 0x00002000
+ // Other encodings under NEON3SameExtraFCFMask are UNALLOCATED.
};
// NEON instructions with three different-type operands.
diff --git a/src/aarch64/decoder-aarch64.cc b/src/aarch64/decoder-aarch64.cc
index 77900441..9db8b516 100644
--- a/src/aarch64/decoder-aarch64.cc
+++ b/src/aarch64/decoder-aarch64.cc
@@ -756,12 +756,28 @@ void Decoder::DecodeNEONVectorDataProcessing(const Instruction* instr) {
}
} else if (instr->ExtractBit(10) == 0) {
VisitUnallocated(instr);
- } else if ((instr->ExtractBits(14, 11) <= 0xE &&
- instr->ExtractBits(14, 11) >= 0x8) ||
- instr->ExtractBits(14, 11) <= 0x2) {
- VisitNEON3SameExtra(instr);
- } else {
+ } else if ((instr->ExtractBits(14, 11) == 0x3) ||
+ (instr->ExtractBits(14, 13) == 0x1)) {
+ // opcode = 0b0011
+ // opcode = 0b01xx
VisitUnallocated(instr);
+ } else if (instr->ExtractBit(29) == 0) {
+ // U == 0
+ if (instr->ExtractBits(14, 11) == 0x2) {
+ // opcode = 0b0010
+ VisitNEON3SameExtra(instr);
+ } else {
+ VisitUnallocated(instr);
+ }
+ } else {
+ // U == 1
+ if ((instr->ExtractBits(14, 11) == 0xd) ||
+ (instr->ExtractBits(14, 11) == 0xf)) {
+ // opcode = 0b11x1
+ VisitUnallocated(instr);
+ } else {
+ VisitNEON3SameExtra(instr);
+ }
}
} else {
if (instr->ExtractBit(10) == 0) {
diff --git a/src/aarch64/disasm-aarch64.cc b/src/aarch64/disasm-aarch64.cc
index 7e5e6e3a..42235d4d 100644
--- a/src/aarch64/disasm-aarch64.cc
+++ b/src/aarch64/disasm-aarch64.cc
@@ -2312,22 +2312,17 @@ void Disassembler::VisitNEON3Same(const Instruction *instr) {
void Disassembler::VisitNEON3SameExtra(const Instruction *instr) {
static const NEONFormatMap map_usdot = {{30}, {NF_8B, NF_16B}};
- const char *mnemonic = "unimplemented";
+ const char *mnemonic = "unallocated";
const char *form = "(NEON3SameExtra)";
NEONFormatDecoder nfd(instr);
- if (instr->Mask(NEON3SameExtraFCFMask) == NEON3SameExtraFCFixed) {
- switch (instr->Mask(NEON3SameExtraFCMask)) {
- case NEON_FCMLA:
- mnemonic = "fcmla";
- form = "'Vd.%s, 'Vn.%s, 'Vm.%s, 'IVFCNM";
- break;
- case NEON_FCADD:
- mnemonic = "fcadd";
- form = "'Vd.%s, 'Vn.%s, 'Vm.%s, 'IVFCNA";
- break;
- }
+ if (instr->Mask(NEON3SameExtraFCMLAMask) == NEON_FCMLA) {
+ mnemonic = "fcmla";
+ form = "'Vd.%s, 'Vn.%s, 'Vm.%s, 'IVFCNM";
+ } else if (instr->Mask(NEON3SameExtraFCADDMask) == NEON_FCADD) {
+ mnemonic = "fcadd";
+ form = "'Vd.%s, 'Vn.%s, 'Vm.%s, 'IVFCNA";
} else {
form = "'Vd.%s, 'Vn.%s, 'Vm.%s";
switch (instr->Mask(NEON3SameExtraMask)) {
diff --git a/src/aarch64/simulator-aarch64.cc b/src/aarch64/simulator-aarch64.cc
index 787ee2ec..51b8fd7d 100644
--- a/src/aarch64/simulator-aarch64.cc
+++ b/src/aarch64/simulator-aarch64.cc
@@ -3750,20 +3750,12 @@ void Simulator::VisitNEON3SameExtra(const Instruction* instr) {
SimVRegister& rm = ReadVRegister(instr->GetRm());
int rot = 0;
VectorFormat vf = nfd.GetVectorFormat();
- if (instr->Mask(NEON3SameExtraFCFMask) == NEON3SameExtraFCFixed) {
- switch (instr->Mask(NEON3SameExtraFCMask)) {
- case NEON_FCADD:
- rot = instr->GetImmRotFcadd();
- fcadd(vf, rd, rn, rm, rot);
- break;
- case NEON_FCMLA:
- rot = instr->GetImmRotFcmlaVec();
- fcmla(vf, rd, rn, rm, rot);
- break;
- default:
- VIXL_UNIMPLEMENTED();
- break;
- }
+ if (instr->Mask(NEON3SameExtraFCMLAMask) == NEON_FCMLA) {
+ rot = instr->GetImmRotFcmlaVec();
+ fcmla(vf, rd, rn, rm, rot);
+ } else if (instr->Mask(NEON3SameExtraFCADDMask) == NEON_FCADD) {
+ rot = instr->GetImmRotFcadd();
+ fcadd(vf, rd, rn, rm, rot);
} else {
switch (instr->Mask(NEON3SameExtraMask)) {
case NEON_SDOT: