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 | |
parent | f658ca1813c32f483f20f75a4be0947ef66b442f (diff) | |
download | vixl-364c82b15129b5f168e450356ee0abd0e62ffa15.tar.gz |
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
-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 | ||||
-rw-r--r-- | test/aarch64/test-disasm-aarch64.cc | 6 |
5 files changed, 46 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: diff --git a/test/aarch64/test-disasm-aarch64.cc b/test/aarch64/test-disasm-aarch64.cc index 64be553d..426319ff 100644 --- a/test/aarch64/test-disasm-aarch64.cc +++ b/test/aarch64/test-disasm-aarch64.cc @@ -4735,6 +4735,12 @@ TEST(neon_3same_extra_fcadd) { COMPARE_MACRO(Fcmla(v21.V2D(), v22.V2D(), v23.V2D(), 0), "fcmla v21.2d, v22.2d, v23.2d, #0"); + // The FC* instructions span multiple opcodes, so they have special cases in + // the disassembler. Verify that similar encodings don't get disassembled as + // FC* instructions. + COMPARE(dci(0x2e00ec00), "unallocated (Unallocated)"); // opcode = 0x1101 + COMPARE(dci(0x2e00fc00), "unallocated (Unallocated)"); // opcode = 0x1111 + CLEANUP(); } |