diff options
author | Jacob Bramley <jacob.bramley@arm.com> | 2018-08-24 17:51:52 +0100 |
---|---|---|
committer | Jacob Bramley <jacob.bramley@arm.com> | 2018-08-28 15:33:22 +0100 |
commit | 364c82b15129b5f168e450356ee0abd0e62ffa15 (patch) | |
tree | e89f3c234f7fd410d0c161da877cbade81167823 /src | |
parent | f658ca1813c32f483f20f75a4be0947ef66b442f (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.h | 8 | ||||
-rw-r--r-- | src/aarch64/decoder-aarch64.cc | 26 | ||||
-rw-r--r-- | src/aarch64/disasm-aarch64.cc | 19 | ||||
-rw-r--r-- | src/aarch64/simulator-aarch64.cc | 20 |
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: |