diff options
author | Martyn Capewell <martyn.capewell@arm.com> | 2020-06-23 16:10:54 +0100 |
---|---|---|
committer | Jacob Bramley <jacob.bramley@arm.com> | 2020-06-25 09:46:15 +0000 |
commit | 89820250683b61d6faef8d7ed443f46821cc8690 (patch) | |
tree | 509978f6a3abae4e80a01122065ebd4d689f4984 /src | |
parent | 1f1ab9b9db73d908d73e0be6c19f81434ed86aaf (diff) | |
download | vixl-89820250683b61d6faef8d7ed443f46821cc8690.tar.gz |
[sve] Ternary substitution for disassembler
Introduce a ternary substitution placeholder in the disassembler, making some
addressing modes and merging/zeroing forms simpler.
Change-Id: I75d0c3cf40c73dd2e1ebce30c3753fd79368326d
Diffstat (limited to 'src')
-rw-r--r-- | src/aarch64/disasm-aarch64.cc | 94 | ||||
-rw-r--r-- | src/aarch64/disasm-aarch64.h | 1 |
2 files changed, 43 insertions, 52 deletions
diff --git a/src/aarch64/disasm-aarch64.cc b/src/aarch64/disasm-aarch64.cc index 35dee0b5..53d6a52b 100644 --- a/src/aarch64/disasm-aarch64.cc +++ b/src/aarch64/disasm-aarch64.cc @@ -4928,9 +4928,7 @@ void Disassembler:: VisitSVE32BitGatherLoadHalfwords_ScalarPlus32BitScaledOffsets( const Instruction *instr) { const char *mnemonic = "unimplemented"; - const char *form = (instr->ExtractBit(22) == 0) - ? "{ 'Zt.s }, 'Pgl/z, ['Xns, 'Zm.s, uxtw #1]" - : "{ 'Zt.s }, 'Pgl/z, ['Xns, 'Zm.s, sxtw #1]"; + const char *form = "{ 'Zt.s }, 'Pgl/z, ['Xns, 'Zm.s, '?22:suxtw #1]"; switch (instr->Mask( SVE32BitGatherLoadHalfwords_ScalarPlus32BitScaledOffsetsMask)) { @@ -4956,9 +4954,7 @@ void Disassembler:: void Disassembler::VisitSVE32BitGatherLoadWords_ScalarPlus32BitScaledOffsets( const Instruction *instr) { const char *mnemonic = "unimplemented"; - const char *form = (instr->ExtractBit(22) == 0) - ? "{ 'Zt.s }, 'Pgl/z, ['Xns, 'Zm.s, uxtw #2]" - : "{ 'Zt.s }, 'Pgl/z, ['Xns, 'Zm.s, sxtw #2]"; + const char *form = "{ 'Zt.s }, 'Pgl/z, ['Xns, 'Zm.s, '?22:suxtw #2]"; switch ( instr->Mask(SVE32BitGatherLoadWords_ScalarPlus32BitScaledOffsetsMask)) { @@ -4977,9 +4973,7 @@ void Disassembler::VisitSVE32BitGatherLoadWords_ScalarPlus32BitScaledOffsets( void Disassembler::VisitSVE32BitGatherLoad_ScalarPlus32BitUnscaledOffsets( const Instruction *instr) { - const char *form = (instr->ExtractBit(22) == 0) - ? "{ 'Zt.s }, 'Pgl/z, ['Xns, 'Zm.s, uxtw]" - : "{ 'Zt.s }, 'Pgl/z, ['Xns, 'Zm.s, sxtw]"; + const char *form = "{ 'Zt.s }, 'Pgl/z, ['Xns, 'Zm.s, '?22:suxtw]"; const char *mnemonic = "unimplemented"; switch (instr->Mask(SVE32BitGatherLoad_ScalarPlus32BitUnscaledOffsetsMask)) { @@ -5083,9 +5077,7 @@ void Disassembler::VisitSVE32BitGatherLoad_VectorPlusImm( void Disassembler::VisitSVE32BitGatherPrefetch_ScalarPlus32BitScaledOffsets( const Instruction *instr) { const char *mnemonic = "unimplemented"; - const char *form = (instr->ExtractBit(22) == 0) - ? "'prefSVEOp, 'Pgl, ['Xns, 'Zm.s, uxtw" - : "'prefSVEOp, 'Pgl, ['Xns, 'Zm.s, sxtw"; + const char *form = "'prefSVEOp, 'Pgl, ['Xns, 'Zm.s, '?22:suxtw"; const char *suffix = NULL; switch ( @@ -5142,9 +5134,7 @@ void Disassembler::VisitSVE32BitGatherPrefetch_VectorPlusImm( void Disassembler::VisitSVE32BitScatterStore_ScalarPlus32BitScaledOffsets( const Instruction *instr) { const char *mnemonic = "unimplemented"; - const char *form = "{ 'Zt.s }, 'Pgl, ['Xns, 'Zm.s, "; - const char *suffix = - (instr->ExtractBit(14) == 0) ? "uxtw #'u2423]" : "sxtw #'u2423]"; + const char *form = "{ 'Zt.s }, 'Pgl, ['Xns, 'Zm.s, '?14:suxtw #'u2423]"; switch (instr->Mask(SVE32BitScatterStore_ScalarPlus32BitScaledOffsetsMask)) { case ST1H_z_p_bz_s_x32_scaled: @@ -5157,14 +5147,13 @@ void Disassembler::VisitSVE32BitScatterStore_ScalarPlus32BitScaledOffsets( form = "(SVE32BitScatterStore_ScalarPlus32BitScaledOffsets)"; break; } - Format(instr, mnemonic, form, suffix); + Format(instr, mnemonic, form); } void Disassembler::VisitSVE32BitScatterStore_ScalarPlus32BitUnscaledOffsets( const Instruction *instr) { const char *mnemonic = "unimplemented"; - const char *form = "{ 'Zt.s }, 'Pgl, ['Xns, 'Zm.s, "; - const char *suffix = (instr->ExtractBit(14) == 0) ? "uxtw]" : "sxtw]"; + const char *form = "{ 'Zt.s }, 'Pgl, ['Xns, 'Zm.s, '?14:suxtw]"; switch ( instr->Mask(SVE32BitScatterStore_ScalarPlus32BitUnscaledOffsetsMask)) { @@ -5181,7 +5170,7 @@ void Disassembler::VisitSVE32BitScatterStore_ScalarPlus32BitUnscaledOffsets( form = "(SVE32BitScatterStore_ScalarPlus32BitUnscaledOffsets)"; break; } - Format(instr, mnemonic, form, suffix); + Format(instr, mnemonic, form); } void Disassembler::VisitSVE32BitScatterStore_VectorPlusImm( @@ -5215,9 +5204,7 @@ void Disassembler::VisitSVE32BitScatterStore_VectorPlusImm( void Disassembler::VisitSVE64BitGatherLoad_ScalarPlus32BitUnpackedScaledOffsets( const Instruction *instr) { const char *mnemonic = "unimplemented"; - const char *form = "{ 'Zt.d }, 'Pgl/z, ['Xns, 'Zm.d, "; - const char *suffix = - (instr->ExtractBit(22) == 0) ? "uxtw #'u2423]" : "sxtw #'u2423]"; + const char *form = "{ 'Zt.d }, 'Pgl/z, ['Xns, 'Zm.d, '?22:suxtw #'u2423]"; switch (instr->Mask( SVE64BitGatherLoad_ScalarPlus32BitUnpackedScaledOffsetsMask)) { @@ -5253,10 +5240,9 @@ void Disassembler::VisitSVE64BitGatherLoad_ScalarPlus32BitUnpackedScaledOffsets( break; default: form = "(SVE64BitGatherLoad_ScalarPlus32BitUnpackedScaledOffsetsMask)"; - suffix = NULL; break; } - Format(instr, mnemonic, form, suffix); + Format(instr, mnemonic, form); } void Disassembler::VisitSVE64BitGatherLoad_ScalarPlus64BitScaledOffsets( @@ -5375,8 +5361,7 @@ void Disassembler:: VisitSVE64BitGatherLoad_ScalarPlusUnpacked32BitUnscaledOffsets( const Instruction *instr) { const char *mnemonic = "unimplemented"; - const char *form = "{ 'Zt.d }, 'Pgl/z, ['Xns, 'Zm.d, "; - const char *suffix = (instr->ExtractBit(22) == 0) ? "uxtw]" : "sxtw]"; + const char *form = "{ 'Zt.d }, 'Pgl/z, ['Xns, 'Zm.d, '?22:suxtw]"; switch (instr->Mask( SVE64BitGatherLoad_ScalarPlusUnpacked32BitUnscaledOffsetsMask)) { @@ -5424,10 +5409,9 @@ void Disassembler:: break; default: form = "(SVE64BitGatherLoad_ScalarPlusUnpacked32BitUnscaledOffsetsMask)"; - suffix = NULL; break; } - Format(instr, mnemonic, form, suffix); + Format(instr, mnemonic, form); } void Disassembler::VisitSVE64BitGatherLoad_VectorPlusImm( @@ -5532,9 +5516,7 @@ void Disassembler:: VisitSVE64BitGatherPrefetch_ScalarPlusUnpacked32BitScaledOffsets( const Instruction *instr) { const char *mnemonic = "unimplemented"; - const char *form = (instr->ExtractBit(22) == 0) - ? "'prefSVEOp, 'Pgl, ['Xns, 'Zm.d, uxtw" - : "'prefSVEOp, 'Pgl, ['Xns, 'Zm.d, sxtw"; + const char *form = "'prefSVEOp, 'Pgl, ['Xns, 'Zm.d, '?22:suxtw"; const char *suffix = NULL; switch (instr->Mask( @@ -5640,9 +5622,7 @@ void Disassembler:: VisitSVE64BitScatterStore_ScalarPlusUnpacked32BitScaledOffsets( const Instruction *instr) { const char *mnemonic = "unimplemented"; - const char *form = "{ 'Zt.d }, 'Pgl, ['Xns, 'Zm.d, "; - const char *suffix = - (instr->ExtractBit(14) == 0) ? "uxtw #'u2423]" : "sxtw #'u2423]"; + const char *form = "{ 'Zt.d }, 'Pgl, ['Xns, 'Zm.d, '?14:suxtw #'u2423]"; switch (instr->Mask( SVE64BitScatterStore_ScalarPlusUnpacked32BitScaledOffsetsMask)) { @@ -5659,15 +5639,14 @@ void Disassembler:: form = "(SVE64BitScatterStore_ScalarPlusUnpacked32BitScaledOffsets)"; break; } - Format(instr, mnemonic, form, suffix); + Format(instr, mnemonic, form); } void Disassembler:: VisitSVE64BitScatterStore_ScalarPlusUnpacked32BitUnscaledOffsets( const Instruction *instr) { const char *mnemonic = "unimplemented"; - const char *form = "{ 'Zt.d }, 'Pgl, ['Xns, 'Zm.d, "; - const char *suffix = (instr->ExtractBit(14) == 0) ? "uxtw]" : "sxtw]"; + const char *form = "{ 'Zt.d }, 'Pgl, ['Xns, 'Zm.d, '?14:suxtw]"; switch (instr->Mask( SVE64BitScatterStore_ScalarPlusUnpacked32BitUnscaledOffsetsMask)) { @@ -5687,7 +5666,7 @@ void Disassembler:: form = "(SVE64BitScatterStore_ScalarPlusUnpacked32BitUnscaledOffsets)"; break; } - Format(instr, mnemonic, form, suffix); + Format(instr, mnemonic, form); } void Disassembler::VisitSVE64BitScatterStore_VectorPlusImm( @@ -6543,13 +6522,8 @@ void Disassembler::VisitSVECopyIntImm_Predicated(const Instruction *instr) { case CPY_z_p_i: { // The preferred disassembly for cpy is "mov". mnemonic = "mov"; - suffix = (instr->ExtractBit(13) == 0) ? "" : ", lsl #8"; - bool m = instr->ExtractBit(14) != 0; - if (m) { - form = "'Zd.'t, 'Pm/m, #'s1205"; - } else { - form = "'Zd.'t, 'Pm/z, #'s1205"; - } + form = "'Zd.'t, 'Pm/'?14:mz, #'s1205"; + if (instr->ExtractBit(13) != 0) suffix = ", lsl #8"; break; } default: @@ -7760,8 +7734,7 @@ void Disassembler::VisitSVELoadVectorRegister(const Instruction *instr) { void Disassembler::VisitSVEPartitionBreakCondition(const Instruction *instr) { const char *mnemonic = "unimplemented"; - const char *form = (instr->ExtractBit(4) == 1) ? "'Pd.b, p'u1310/m, 'Pn.b" - : "'Pd.b, p'u1310/z, 'Pn.b"; + const char *form = "'Pd.b, p'u1310/'?04:mz, 'Pn.b"; switch (instr->Mask(SVEPartitionBreakConditionMask)) { case BRKAS_p_p_p_z: @@ -7777,6 +7750,7 @@ void Disassembler::VisitSVEPartitionBreakCondition(const Instruction *instr) { mnemonic = "brkb"; break; default: + form = "(SVEPartitionBreakCondition)"; break; } Format(instr, mnemonic, form); @@ -9186,11 +9160,7 @@ void Disassembler::VisitSVEMovprfx(const Instruction *instr) { if (instr->Mask(SVEMovprfxMask) == MOVPRFX_z_p_z) { mnemonic = "movprfx"; - if (instr->ExtractBit(16) == 0) { - form = "'Zd.'t, 'Pgl/z, 'Zn.'t"; - } else { - form = "'Zd.'t, 'Pgl/m, 'Zn.'t"; - } + form = "'Zd.'t, 'Pgl/'?16:mz, 'Zn.'t"; } Format(instr, mnemonic, form); @@ -9926,6 +9896,8 @@ int Disassembler::SubstituteField(const Instruction *instr, return SubstituteIntField(instr, format); case 't': return SubstituteSVESize(instr, format); + case '?': + return SubstituteTernary(instr, format); default: { VIXL_UNREACHABLE(); return 1; @@ -11088,6 +11060,24 @@ int Disassembler::SubstituteSVESize(const Instruction *instr, return placeholder_length; } +int Disassembler::SubstituteTernary(const Instruction *instr, + const char *format) { + VIXL_ASSERT((format[0] == '?') && (format[3] == ':')); + + // The ternary substitution of the format "'?bb:TF" is replaced by a single + // character, either T or F, depending on the value of the bit at position + // bb in the instruction. For example, "'?31:xw" is substituted with "x" if + // bit 31 is true, and "w" otherwise. + VIXL_ASSERT(strspn(&format[1], "0123456789") == 2); + char *c; + uint64_t value = strtoul(&format[1], &c, 10); + VIXL_ASSERT(value < (kInstructionSize * kBitsPerByte)); + VIXL_ASSERT((*c == ':') && (strlen(c) >= 3)); // Minimum of ":TF" + c++; + AppendToOutput("%c", c[1 - instr->ExtractBit(static_cast<int>(value))]); + return 6; +} + void Disassembler::ResetOutput() { buffer_pos_ = 0; buffer_[buffer_pos_] = 0; diff --git a/src/aarch64/disasm-aarch64.h b/src/aarch64/disasm-aarch64.h index 2ca960c8..b59840aa 100644 --- a/src/aarch64/disasm-aarch64.h +++ b/src/aarch64/disasm-aarch64.h @@ -137,6 +137,7 @@ class Disassembler : public DecoderVisitor { int SubstituteCrField(const Instruction* instr, const char* format); int SubstituteIntField(const Instruction* instr, const char* format); int SubstituteSVESize(const Instruction* instr, const char* format); + int SubstituteTernary(const Instruction* instr, const char* format); std::pair<unsigned, unsigned> GetRegNumForField(const Instruction* instr, char reg_prefix, |