[LLVM][MC] Introduce OrFail
variants of MCD ops (#138614)
Introduce `OrFail` variants for all MCD Decoder Ops that have `NumToSKip` encoded with them. This is intended to capture the common case of jumps to the end of the decoder table which has a `OP_Fail` at the end. Using the `OrFail` variants of these ops avoid encoding the `NumToSkip` jump offset for these cases, resulting in a reduction in the size of the decoder tables (from 5 - 17%). Additionally, for the AArch64 target, the table size reduces enough to switch to using 2-byte `NumToSkip` encoding instead of existing 3-bytes, resulting in a net 30% reduction in the size of the decoder table. The total reduction in the size of the decoder tables for different targets is as follows (computed using the following command: `for i in *.inc; do echo -n ``basename $i: ``; grep "MCD::OPC_Fail," $i | awk '{sum += $2} END { print sum}'; done`) ``` Target Old Size New Size % Reduction ================================================ AArch64 153268 106987 30.20 AMDGPU 412056 340856 17.28 ARC 5061 4605 9.01 ARM 73831 60847 17.59 AVR 1306 1158 11.33 BPF 1927 1795 6.85 CSKY 8692 6922 20.36 Hexagon 41965 34759 17.17 Lanai 982 924 5.91 LoongArch 21629 20035 7.37 M68k 13461 11689 13.16 MSP430 3716 3384 8.93 Mips 31415 25771 17.97 PPC 28931 24771 14.38 RISCV 34800 28352 18.53 Sparc 7432 6236 16.09 SystemZ 32248 29716 7.85 VE 42873 36923 13.88 XCore 2316 2196 5.18 Xtensa 3443 2793 18.88 ```
This commit is contained in:
parent
43bc5ea7fd
commit
e53ccb78e4
@ -10,24 +10,29 @@
|
|||||||
#ifndef LLVM_MC_MCDECODEROPS_H
|
#ifndef LLVM_MC_MCDECODEROPS_H
|
||||||
#define LLVM_MC_MCDECODEROPS_H
|
#define LLVM_MC_MCDECODEROPS_H
|
||||||
|
|
||||||
namespace llvm {
|
namespace llvm::MCD {
|
||||||
|
|
||||||
namespace MCD {
|
|
||||||
// Disassembler state machine opcodes.
|
// Disassembler state machine opcodes.
|
||||||
|
// nts_t is either uint16_t or uint24_t based on whether large decoder table is
|
||||||
|
// enabled.
|
||||||
enum DecoderOps {
|
enum DecoderOps {
|
||||||
OPC_ExtractField = 1, // OPC_ExtractField(uleb128 Start, uint8_t Len)
|
OPC_ExtractField = 1, // OPC_ExtractField(uleb128 Start, uint8_t Len)
|
||||||
OPC_FilterValue, // OPC_FilterValue(uleb128 Val, uint16_t NumToSkip)
|
OPC_FilterValue, // OPC_FilterValue(uleb128 Val, nts_t NumToSkip)
|
||||||
|
OPC_FilterValueOrFail, // OPC_FilterValueOrFail(uleb128 Val)
|
||||||
OPC_CheckField, // OPC_CheckField(uleb128 Start, uint8_t Len,
|
OPC_CheckField, // OPC_CheckField(uleb128 Start, uint8_t Len,
|
||||||
// uleb128 Val, uint16_t NumToSkip)
|
// uleb128 Val, nts_t NumToSkip)
|
||||||
OPC_CheckPredicate, // OPC_CheckPredicate(uleb128 PIdx, uint16_t NumToSkip)
|
OPC_CheckFieldOrFail, // OPC_CheckFieldOrFail(uleb128 Start, uint8_t Len,
|
||||||
|
// uleb128 Val)
|
||||||
|
OPC_CheckPredicate, // OPC_CheckPredicate(uleb128 PIdx, nts_t NumToSkip)
|
||||||
|
OPC_CheckPredicateOrFail, // OPC_CheckPredicateOrFail(uleb128 PIdx)
|
||||||
OPC_Decode, // OPC_Decode(uleb128 Opcode, uleb128 DIdx)
|
OPC_Decode, // OPC_Decode(uleb128 Opcode, uleb128 DIdx)
|
||||||
OPC_TryDecode, // OPC_TryDecode(uleb128 Opcode, uleb128 DIdx,
|
OPC_TryDecode, // OPC_TryDecode(uleb128 Opcode, uleb128 DIdx,
|
||||||
// uint16_t NumToSkip)
|
// nts_t NumToSkip)
|
||||||
|
OPC_TryDecodeOrFail, // OPC_TryDecodeOrFail(uleb128 Opcode, uleb128 DIdx)
|
||||||
OPC_SoftFail, // OPC_SoftFail(uleb128 PMask, uleb128 NMask)
|
OPC_SoftFail, // OPC_SoftFail(uleb128 PMask, uleb128 NMask)
|
||||||
OPC_Fail // OPC_Fail()
|
OPC_Fail // OPC_Fail()
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace MCD
|
} // namespace llvm::MCD
|
||||||
} // namespace llvm
|
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
@ -7,8 +7,7 @@ tablegen(LLVM AArch64GenAsmWriter.inc -gen-asm-writer)
|
|||||||
tablegen(LLVM AArch64GenAsmWriter1.inc -gen-asm-writer -asmwriternum=1)
|
tablegen(LLVM AArch64GenAsmWriter1.inc -gen-asm-writer -asmwriternum=1)
|
||||||
tablegen(LLVM AArch64GenCallingConv.inc -gen-callingconv)
|
tablegen(LLVM AArch64GenCallingConv.inc -gen-callingconv)
|
||||||
tablegen(LLVM AArch64GenDAGISel.inc -gen-dag-isel)
|
tablegen(LLVM AArch64GenDAGISel.inc -gen-dag-isel)
|
||||||
tablegen(LLVM AArch64GenDisassemblerTables.inc -gen-disassembler
|
tablegen(LLVM AArch64GenDisassemblerTables.inc -gen-disassembler)
|
||||||
--large-decoder-table)
|
|
||||||
tablegen(LLVM AArch64GenFastISel.inc -gen-fast-isel)
|
tablegen(LLVM AArch64GenFastISel.inc -gen-fast-isel)
|
||||||
tablegen(LLVM AArch64GenGlobalISel.inc -gen-global-isel)
|
tablegen(LLVM AArch64GenGlobalISel.inc -gen-global-isel)
|
||||||
tablegen(LLVM AArch64GenO0PreLegalizeGICombiner.inc -gen-global-isel-combiner
|
tablegen(LLVM AArch64GenO0PreLegalizeGICombiner.inc -gen-global-isel-combiner
|
||||||
|
@ -47,19 +47,19 @@ def FOO32 : MyVarInst<MemOp32> {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
// CHECK-SMALL: MCD::OPC_ExtractField, 3, 5, // Inst{7-3} ...
|
// CHECK-SMALL: /* 0 */ MCD::OPC_ExtractField, 3, 5, // Inst{7-3} ...
|
||||||
// CHECK-SMALL-NEXT: MCD::OPC_FilterValue, 8, 4, 0, // Skip to: 11
|
// CHECK-SMALL-NEXT: /* 3 */ MCD::OPC_FilterValue, 8, 4, 0, // Skip to: 11
|
||||||
// CHECK-SMALL-NEXT: MCD::OPC_Decode, {{[0-9]+}}, {{[0-9]+}}, 0, // Opcode: FOO16
|
// CHECK-SMALL-NEXT: /* 7 */ MCD::OPC_Decode, {{[0-9]+}}, {{[0-9]+}}, 0, // Opcode: FOO16
|
||||||
// CHECK-SMALL-NEXT: MCD::OPC_FilterValue, 9, 4, 0, // Skip to: 19
|
// CHECK-SMALL-NEXT: /* 11 */ MCD::OPC_FilterValueOrFail, 9,
|
||||||
// CHECK-SMALL-NEXT: MCD::OPC_Decode, {{[0-9]+}}, {{[0-9]+}}, 1, // Opcode: FOO32
|
// CHECK-SMALL-NEXT: /* 13 */ MCD::OPC_Decode, {{[0-9]+}}, {{[0-9]+}}, 1, // Opcode: FOO32
|
||||||
// CHECK-SMALL-NEXT: MCD::OPC_Fail,
|
// CHECK-SMALL-NEXT: /* 17 */ MCD::OPC_Fail,
|
||||||
|
|
||||||
// CHECK-LARGE: /* 0 */ MCD::OPC_ExtractField, 3, 5, // Inst{7-3} ...
|
// CHECK-LARGE: /* 0 */ MCD::OPC_ExtractField, 3, 5, // Inst{7-3} ...
|
||||||
// CHECK-LARGE-NEXT: /* 3 */ MCD::OPC_FilterValue, 8, 4, 0, 0, // Skip to: 12
|
// CHECK-LARGE-NEXT: /* 3 */ MCD::OPC_FilterValue, 8, 4, 0, 0, // Skip to: 12
|
||||||
// CHECK-LARGE-NEXT: /* 8 */ MCD::OPC_Decode, {{[0-9]+}}, {{[0-9]+}}, 0, // Opcode: FOO16
|
// CHECK-LARGE-NEXT: /* 8 */ MCD::OPC_Decode, {{[0-9]+}}, {{[0-9]+}}, 0, // Opcode: FOO16
|
||||||
// CHECK-LARGE-NEXT: /* 12 */ MCD::OPC_FilterValue, 9, 4, 0, 0, // Skip to: 21
|
// CHECK-LARGE-NEXT: /* 12 */ MCD::OPC_FilterValueOrFail, 9,
|
||||||
// CHECK-LARGE-NEXT: /* 17 */ MCD::OPC_Decode, {{[0-9]+}}, {{[0-9]+}}, 1, // Opcode: FOO32
|
// CHECK-LARGE-NEXT: /* 14 */ MCD::OPC_Decode, {{[0-9]+}}, {{[0-9]+}}, 1, // Opcode: FOO32
|
||||||
// CHECK-LARGE-NEXT: /* 21 */ MCD::OPC_Fail,
|
// CHECK-LARGE-NEXT: /* 18 */ MCD::OPC_Fail,
|
||||||
|
|
||||||
// Instruction length table
|
// Instruction length table
|
||||||
// CHECK: 27,
|
// CHECK: 27,
|
||||||
@ -88,7 +88,8 @@ def FOO32 : MyVarInst<MemOp32> {
|
|||||||
// CHECK-LABEL: case MCD::OPC_ExtractField: {
|
// CHECK-LABEL: case MCD::OPC_ExtractField: {
|
||||||
// CHECK: makeUp(insn, Start + Len);
|
// CHECK: makeUp(insn, Start + Len);
|
||||||
|
|
||||||
// CHECK-LABEL: case MCD::OPC_CheckField: {
|
// CHECK-LABEL: case MCD::OPC_CheckField:
|
||||||
|
// CHECK-NEXT: case MCD::OPC_CheckFieldOrFail: {
|
||||||
// CHECK: makeUp(insn, Start + Len);
|
// CHECK: makeUp(insn, Start + Len);
|
||||||
|
|
||||||
// CHECK-LABEL: case MCD::OPC_Decode: {
|
// CHECK-LABEL: case MCD::OPC_Decode: {
|
||||||
|
@ -35,11 +35,11 @@ def InstB : TestInstruction {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// CHECK: /* 0 */ MCD::OPC_ExtractField, 4, 4, // Inst{7-4} ...
|
// CHECK: /* 0 */ MCD::OPC_ExtractField, 4, 4, // Inst{7-4} ...
|
||||||
// CHECK-NEXT: /* 3 */ MCD::OPC_FilterValue, 0, 16, 0, // Skip to: 23
|
// CHECK-NEXT: /* 3 */ MCD::OPC_FilterValueOrFail, 0,
|
||||||
// CHECK-NEXT: /* 7 */ MCD::OPC_CheckField, 2, 2, 0, 6, 0, // Skip to: 19
|
// CHECK-NEXT: /* 5 */ MCD::OPC_CheckField, 2, 2, 0, 6, 0, // Skip to: 17
|
||||||
// CHECK-NEXT: /* 13 */ MCD::OPC_TryDecode, {{[0-9]+}}, {{[0-9]+}}, 0, 0, 0, // Opcode: InstB, skip to: 19
|
// CHECK-NEXT: /* 11 */ MCD::OPC_TryDecode, {{[0-9]+}}, {{[0-9]+}}, 0, 0, 0, // Opcode: InstB, Skip to: 17
|
||||||
// CHECK-NEXT: /* 19 */ MCD::OPC_Decode, {{[0-9]+}}, {{[0-9]+}}, 1, // Opcode: InstA
|
// CHECK-NEXT: /* 17 */ MCD::OPC_Decode, {{[0-9]+}}, {{[0-9]+}}, 1, // Opcode: InstA
|
||||||
// CHECK-NEXT: /* 23 */ MCD::OPC_Fail,
|
// CHECK-NEXT: /* 21 */ MCD::OPC_Fail,
|
||||||
|
|
||||||
// CHECK: if (!Check(S, DecodeInstB(MI, insn, Address, Decoder))) { DecodeComplete = false; return MCDisassembler::Fail; }
|
// CHECK: if (!Check(S, DecodeInstB(MI, insn, Address, Decoder))) { DecodeComplete = false; return MCDisassembler::Fail; }
|
||||||
|
|
||||||
@ -48,11 +48,11 @@ def InstB : TestInstruction {
|
|||||||
// CHECK-NEXT: return NumToSkip;
|
// CHECK-NEXT: return NumToSkip;
|
||||||
|
|
||||||
// CHECK-LARGE: /* 0 */ MCD::OPC_ExtractField, 4, 4, // Inst{7-4} ...
|
// CHECK-LARGE: /* 0 */ MCD::OPC_ExtractField, 4, 4, // Inst{7-4} ...
|
||||||
// CHECK-LARGE-NEXT: /* 3 */ MCD::OPC_FilterValue, 0, 18, 0, 0, // Skip to: 26
|
// CHECK-LARGE-NEXT: /* 3 */ MCD::OPC_FilterValueOrFail, 0,
|
||||||
// CHECK-LARGE-NEXT: /* 8 */ MCD::OPC_CheckField, 2, 2, 0, 7, 0, 0, // Skip to: 22
|
// CHECK-LARGE-NEXT: /* 5 */ MCD::OPC_CheckField, 2, 2, 0, 7, 0, 0, // Skip to: 19
|
||||||
// CHECK-LARGE-NEXT: /* 15 */ MCD::OPC_TryDecode, {{[0-9]+}}, {{[0-9]+}}, 0, 0, 0, 0, // Opcode: InstB, skip to: 22
|
// CHECK-LARGE-NEXT: /* 12 */ MCD::OPC_TryDecode, {{[0-9]+}}, {{[0-9]+}}, 0, 0, 0, 0, // Opcode: InstB, Skip to: 19
|
||||||
// CHECK-LARGE-NEXT: /* 22 */ MCD::OPC_Decode, {{[0-9]+}}, {{[0-9]+}}, 1, // Opcode: InstA
|
// CHECK-LARGE-NEXT: /* 19 */ MCD::OPC_Decode, {{[0-9]+}}, {{[0-9]+}}, 1, // Opcode: InstA
|
||||||
// CHECK-LARGE-NEXT: /* 26 */ MCD::OPC_Fail,
|
// CHECK-LARGE-NEXT: /* 23 */ MCD::OPC_Fail,
|
||||||
|
|
||||||
// CHECK-LARGE: if (!Check(S, DecodeInstB(MI, insn, Address, Decoder))) { DecodeComplete = false; return MCDisassembler::Fail; }
|
// CHECK-LARGE: if (!Check(S, DecodeInstB(MI, insn, Address, Decoder))) { DecodeComplete = false; return MCDisassembler::Fail; }
|
||||||
|
|
||||||
|
@ -32,27 +32,27 @@ def InstB : TestInstruction {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// CHECK: /* 0 */ MCD::OPC_ExtractField, 2, 1, // Inst{2} ...
|
// CHECK: /* 0 */ MCD::OPC_ExtractField, 2, 1, // Inst{2} ...
|
||||||
// CHECK-NEXT: /* 3 */ MCD::OPC_FilterValue, 0, 31, 0, // Skip to: 38
|
// CHECK-NEXT: /* 3 */ MCD::OPC_FilterValueOrFail, 0,
|
||||||
// CHECK-NEXT: /* 7 */ MCD::OPC_ExtractField, 5, 3, // Inst{7-5} ...
|
// CHECK-NEXT: /* 5 */ MCD::OPC_ExtractField, 5, 3, // Inst{7-5} ...
|
||||||
// CHECK-NEXT: /* 10 */ MCD::OPC_FilterValue, 0, 24, 0, // Skip to: 38
|
// CHECK-NEXT: /* 8 */ MCD::OPC_FilterValueOrFail, 0
|
||||||
// CHECK-NEXT: /* 14 */ MCD::OPC_CheckField, 0, 2, 3, 6, 0, // Skip to: 26
|
// CHECK-NEXT: /* 10 */ MCD::OPC_CheckField, 0, 2, 3, 6, 0, // Skip to: 22
|
||||||
// CHECK-NEXT: /* 20 */ MCD::OPC_TryDecode, {{[0-9]+}}, {{[0-9]+}}, 0, 0, 0, // Opcode: InstB, skip to: 26
|
// CHECK-NEXT: /* 16 */ MCD::OPC_TryDecode, {{[0-9]+}}, {{[0-9]+}}, 0, 0, 0, // Opcode: InstB, Skip to: 22
|
||||||
// CHECK-NEXT: /* 26 */ MCD::OPC_CheckField, 3, 2, 0, 6, 0, // Skip to: 38
|
// CHECK-NEXT: /* 22 */ MCD::OPC_CheckFieldOrFail, 3, 2, 0,
|
||||||
// CHECK-NEXT: /* 32 */ MCD::OPC_TryDecode, {{[0-9]+}}, {{[0-9]+}}, 1, 0, 0, // Opcode: InstA, skip to: 38
|
// CHECK-NEXT: /* 26 */ MCD::OPC_TryDecodeOrFail, {{[0-9]+}}, {{[0-9]+}}, 1,
|
||||||
// CHECK-NEXT: /* 38 */ MCD::OPC_Fail,
|
// CHECK-NEXT: /* 30 */ MCD::OPC_Fail,
|
||||||
|
|
||||||
// CHECK: if (!Check(S, DecodeInstB(MI, insn, Address, Decoder))) { DecodeComplete = false; return MCDisassembler::Fail; }
|
// CHECK: if (!Check(S, DecodeInstB(MI, insn, Address, Decoder))) { DecodeComplete = false; return MCDisassembler::Fail; }
|
||||||
// CHECK: if (!Check(S, DecodeInstA(MI, insn, Address, Decoder))) { DecodeComplete = false; return MCDisassembler::Fail; }
|
// CHECK: if (!Check(S, DecodeInstA(MI, insn, Address, Decoder))) { DecodeComplete = false; return MCDisassembler::Fail; }
|
||||||
|
|
||||||
// CHECK-LARGE: /* 0 */ MCD::OPC_ExtractField, 2, 1, // Inst{2} ...
|
// CHECK-LARGE: /* 0 */ MCD::OPC_ExtractField, 2, 1, // Inst{2} ...
|
||||||
// CHECK-LARGE-NEXT: /* 3 */ MCD::OPC_FilterValue, 0, 36, 0, 0, // Skip to: 44
|
// CHECK-LARGE-NEXT: /* 3 */ MCD::OPC_FilterValueOrFail, 0,
|
||||||
// CHECK-LARGE-NEXT: /* 8 */ MCD::OPC_ExtractField, 5, 3, // Inst{7-5} ...
|
// CHECK-LARGE-NEXT: /* 5 */ MCD::OPC_ExtractField, 5, 3, // Inst{7-5} ...
|
||||||
// CHECK-LARGE-NEXT: /* 11 */ MCD::OPC_FilterValue, 0, 28, 0, 0, // Skip to: 44
|
// CHECK-LARGE-NEXT: /* 8 */ MCD::OPC_FilterValueOrFail, 0,
|
||||||
// CHECK-LARGE-NEXT: /* 16 */ MCD::OPC_CheckField, 0, 2, 3, 7, 0, 0, // Skip to: 30
|
// CHECK-LARGE-NEXT: /* 10 */ MCD::OPC_CheckField, 0, 2, 3, 7, 0, 0, // Skip to: 24
|
||||||
// CHECK-LARGE-NEXT: /* 23 */ MCD::OPC_TryDecode, {{[0-9]+}}, {{[0-9]+}}, 0, 0, 0, 0, // Opcode: InstB, skip to: 30
|
// CHECK-LARGE-NEXT: /* 17 */ MCD::OPC_TryDecode, {{[0-9]+}}, {{[0-9]+}}, 0, 0, 0, 0, // Opcode: InstB, Skip to: 24
|
||||||
// CHECK-LARGE-NEXT: /* 30 */ MCD::OPC_CheckField, 3, 2, 0, 7, 0, 0, // Skip to: 44
|
// CHECK-LARGE-NEXT: /* 24 */ MCD::OPC_CheckFieldOrFail, 3, 2, 0,
|
||||||
// CHECK-LARGE-NEXT: /* 37 */ MCD::OPC_TryDecode, {{[0-9]+}}, {{[0-9]+}}, 1, 0, 0, 0, // Opcode: InstA, skip to: 44
|
// CHECK-LARGE-NEXT: /* 28 */ MCD::OPC_TryDecodeOrFail, {{[0-9]+}}, {{[0-9]+}}, 1,
|
||||||
// CHECK-LARGE-NEXT: /* 44 */ MCD::OPC_Fail,
|
// CHECK-LARGE-NEXT: /* 32 */ MCD::OPC_Fail,
|
||||||
|
|
||||||
// CHECK-LARGE: if (!Check(S, DecodeInstB(MI, insn, Address, Decoder))) { DecodeComplete = false; return MCDisassembler::Fail; }
|
// CHECK-LARGE: if (!Check(S, DecodeInstB(MI, insn, Address, Decoder))) { DecodeComplete = false; return MCDisassembler::Fail; }
|
||||||
// CHECK-LARGE: if (!Check(S, DecodeInstA(MI, insn, Address, Decoder))) { DecodeComplete = false; return MCDisassembler::Fail; }
|
// CHECK-LARGE: if (!Check(S, DecodeInstA(MI, insn, Address, Decoder))) { DecodeComplete = false; return MCDisassembler::Fail; }
|
||||||
|
@ -36,19 +36,19 @@ def InstB : TestInstruction {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// CHECK: /* 0 */ MCD::OPC_ExtractField, 4, 4, // Inst{7-4} ...
|
// CHECK: /* 0 */ MCD::OPC_ExtractField, 4, 4, // Inst{7-4} ...
|
||||||
// CHECK-NEXT: /* 3 */ MCD::OPC_FilterValue, 0, 16, 0, // Skip to: 23
|
// CHECK-NEXT: /* 3 */ MCD::OPC_FilterValueOrFail, 0,
|
||||||
// CHECK-NEXT: /* 7 */ MCD::OPC_CheckField, 2, 2, 0, 6, 0, // Skip to: 19
|
// CHECK-NEXT: /* 5 */ MCD::OPC_CheckField, 2, 2, 0, 6, 0, // Skip to: 17
|
||||||
// CHECK-NEXT: /* 13 */ MCD::OPC_TryDecode, {{[0-9]+}}, {{[0-9]+}}, 0, 0, 0, // Opcode: InstB, skip to: 19
|
// CHECK-NEXT: /* 11 */ MCD::OPC_TryDecode, {{[0-9]+}}, {{[0-9]+}}, 0, 0, 0, // Opcode: InstB, Skip to: 17
|
||||||
// CHECK-NEXT: /* 19 */ MCD::OPC_Decode, {{[0-9]+}}, {{[0-9]+}}, 1, // Opcode: InstA
|
// CHECK-NEXT: /* 17 */ MCD::OPC_Decode, {{[0-9]+}}, {{[0-9]+}}, 1, // Opcode: InstA
|
||||||
// CHECK-NEXT: /* 23 */ MCD::OPC_Fail,
|
// CHECK-NEXT: /* 21 */ MCD::OPC_Fail,
|
||||||
|
|
||||||
// CHECK: if (!Check(S, DecodeInstBOp(MI, tmp, Address, Decoder))) { DecodeComplete = false; return MCDisassembler::Fail; }
|
// CHECK: if (!Check(S, DecodeInstBOp(MI, tmp, Address, Decoder))) { DecodeComplete = false; return MCDisassembler::Fail; }
|
||||||
|
|
||||||
// CHECK-LARGE: /* 0 */ MCD::OPC_ExtractField, 4, 4, // Inst{7-4} ...
|
// CHECK-LARGE: /* 0 */ MCD::OPC_ExtractField, 4, 4, // Inst{7-4} ...
|
||||||
// CHECK-LARGE-NEXT: /* 3 */ MCD::OPC_FilterValue, 0, 18, 0, 0, // Skip to: 26
|
// CHECK-LARGE-NEXT: /* 3 */ MCD::OPC_FilterValueOrFail, 0,
|
||||||
// CHECK-LARGE-NEXT: /* 8 */ MCD::OPC_CheckField, 2, 2, 0, 7, 0, 0, // Skip to: 22
|
// CHECK-LARGE-NEXT: /* 5 */ MCD::OPC_CheckField, 2, 2, 0, 7, 0, 0, // Skip to: 19
|
||||||
// CHECK-LARGE-NEXT: /* 15 */ MCD::OPC_TryDecode, {{[0-9]+}}, {{[0-9]+}}, 0, 0, 0, 0, // Opcode: InstB, skip to: 22
|
// CHECK-LARGE-NEXT: /* 12 */ MCD::OPC_TryDecode, {{[0-9]+}}, {{[0-9]+}}, 0, 0, 0, 0, // Opcode: InstB, Skip to: 19
|
||||||
// CHECK-LARGE-NEXT: /* 22 */ MCD::OPC_Decode, {{[0-9]+}}, {{[0-9]+}}, 1, // Opcode: InstA
|
// CHECK-LARGE-NEXT: /* 19 */ MCD::OPC_Decode, {{[0-9]+}}, {{[0-9]+}}, 1, // Opcode: InstA
|
||||||
// CHECK-LARGE-NEXT: /* 26 */ MCD::OPC_Fail,
|
// CHECK-LARGE-NEXT: /* 23 */ MCD::OPC_Fail,
|
||||||
|
|
||||||
// CHECK-LARGE: if (!Check(S, DecodeInstBOp(MI, tmp, Address, Decoder))) { DecodeComplete = false; return MCDisassembler::Fail; }
|
// CHECK-LARGE: if (!Check(S, DecodeInstBOp(MI, tmp, Address, Decoder))) { DecodeComplete = false; return MCDisassembler::Fail; }
|
||||||
|
@ -34,21 +34,21 @@ def InstB : TestInstruction {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// CHECK: /* 0 */ MCD::OPC_ExtractField, 250, 3, 4, // Inst{509-506} ...
|
// CHECK: /* 0 */ MCD::OPC_ExtractField, 250, 3, 4, // Inst{509-506} ...
|
||||||
// CHECK-NEXT: /* 4 */ MCD::OPC_FilterValue, 0, 17, 0, // Skip to: 25
|
// CHECK-NEXT: /* 4 */ MCD::OPC_FilterValueOrFail, 0,
|
||||||
// CHECK-NEXT: /* 8 */ MCD::OPC_CheckField, 248, 3, 2, 0, 6, 0, // Skip to: 21
|
// CHECK-NEXT: /* 6 */ MCD::OPC_CheckField, 248, 3, 2, 0, 6, 0, // Skip to: 19
|
||||||
// CHECK-NEXT: /* 15 */ MCD::OPC_TryDecode, {{[0-9]+}}, {{[0-9]+}}, 0, 0, 0, // Opcode: InstB, skip to: 21
|
// CHECK-NEXT: /* 13 */ MCD::OPC_TryDecode, {{[0-9]+}}, {{[0-9]+}}, 0, 0, 0, // Opcode: InstB, Skip to: 19
|
||||||
// CHECK-NEXT: /* 21 */ MCD::OPC_Decode, {{[0-9]+}}, {{[0-9]+}}, 1, // Opcode: InstA
|
// CHECK-NEXT: /* 19 */ MCD::OPC_Decode, {{[0-9]+}}, {{[0-9]+}}, 1, // Opcode: InstA
|
||||||
// CHECK-NEXT: /* 25 */ MCD::OPC_Fail,
|
// CHECK-NEXT: /* 23 */ MCD::OPC_Fail,
|
||||||
|
|
||||||
// CHECK: if (!Check(S, DecodeInstB(MI, insn, Address, Decoder))) { DecodeComplete = false; return MCDisassembler::Fail; }
|
// CHECK: if (!Check(S, DecodeInstB(MI, insn, Address, Decoder))) { DecodeComplete = false; return MCDisassembler::Fail; }
|
||||||
|
|
||||||
|
|
||||||
// CHECK-LARGE: /* 0 */ MCD::OPC_ExtractField, 250, 3, 4, // Inst{509-506} ...
|
// CHECK-LARGE: /* 0 */ MCD::OPC_ExtractField, 250, 3, 4, // Inst{509-506} ...
|
||||||
// CHECK-LARGE-NEXT: /* 4 */ MCD::OPC_FilterValue, 0, 19, 0, 0, // Skip to: 28
|
// CHECK-LARGE-NEXT: /* 4 */ MCD::OPC_FilterValueOrFail, 0,
|
||||||
// CHECK-LARGE-NEXT: /* 9 */ MCD::OPC_CheckField, 248, 3, 2, 0, 7, 0, 0, // Skip to: 24
|
// CHECK-LARGE-NEXT: /* 6 */ MCD::OPC_CheckField, 248, 3, 2, 0, 7, 0, 0, // Skip to: 21
|
||||||
// CHECK-LARGE-NEXT: /* 17 */ MCD::OPC_TryDecode, {{[0-9]+}}, {{[0-9]+}}, 0, 0, 0, 0, // Opcode: InstB, skip to: 24
|
// CHECK-LARGE-NEXT: /* 14 */ MCD::OPC_TryDecode, {{[0-9]+}}, {{[0-9]+}}, 0, 0, 0, 0, // Opcode: InstB, Skip to: 21
|
||||||
// CHECK-LARGE-NEXT: /* 24 */ MCD::OPC_Decode, {{[0-9]+}}, {{[0-9]+}}, 1, // Opcode: InstA
|
// CHECK-LARGE-NEXT: /* 21 */ MCD::OPC_Decode, {{[0-9]+}}, {{[0-9]+}}, 1, // Opcode: InstA
|
||||||
// CHECK-LARGE-NEXT: /* 28 */ MCD::OPC_Fail,
|
// CHECK-LARGE-NEXT: /* 25 */ MCD::OPC_Fail,
|
||||||
|
|
||||||
// CHECK-LARGE: if (!Check(S, DecodeInstB(MI, insn, Address, Decoder))) { DecodeComplete = false; return MCDisassembler::Fail; }
|
// CHECK-LARGE: if (!Check(S, DecodeInstB(MI, insn, Address, Decoder))) { DecodeComplete = false; return MCDisassembler::Fail; }
|
||||||
|
|
||||||
|
@ -90,9 +90,9 @@ STATISTIC(NumInstructions, "Number of instructions considered");
|
|||||||
STATISTIC(NumEncodingsSupported, "Number of encodings supported");
|
STATISTIC(NumEncodingsSupported, "Number of encodings supported");
|
||||||
STATISTIC(NumEncodingsOmitted, "Number of encodings omitted");
|
STATISTIC(NumEncodingsOmitted, "Number of encodings omitted");
|
||||||
|
|
||||||
namespace {
|
static unsigned getNumToSkipInBytes() { return LargeTable ? 3 : 2; }
|
||||||
|
|
||||||
unsigned getNumToSkipInBytes() { return LargeTable ? 3 : 2; }
|
namespace {
|
||||||
|
|
||||||
struct EncodingField {
|
struct EncodingField {
|
||||||
unsigned Base, Width, Offset;
|
unsigned Base, Width, Offset;
|
||||||
@ -182,6 +182,8 @@ struct DecoderTableInfo {
|
|||||||
FixupScopeList FixupStack;
|
FixupScopeList FixupStack;
|
||||||
PredicateSet Predicates;
|
PredicateSet Predicates;
|
||||||
DecoderSet Decoders;
|
DecoderSet Decoders;
|
||||||
|
|
||||||
|
bool isOutermostScope() const { return FixupStack.size() == 1; }
|
||||||
};
|
};
|
||||||
|
|
||||||
struct EncodingAndInst {
|
struct EncodingAndInst {
|
||||||
@ -777,11 +779,21 @@ void Filter::emitTableEntry(DecoderTableInfo &TableInfo) const {
|
|||||||
|
|
||||||
PrevFilter = 0; // Don't re-process the filter's fallthrough.
|
PrevFilter = 0; // Don't re-process the filter's fallthrough.
|
||||||
} else {
|
} else {
|
||||||
Table.push_back(MCD::OPC_FilterValue);
|
// The last filtervalue emitted can be OPC_FilterValue if we are at
|
||||||
|
// outermost scope.
|
||||||
|
const uint8_t DecoderOp =
|
||||||
|
FilterVal == LastFilter && TableInfo.isOutermostScope()
|
||||||
|
? MCD::OPC_FilterValueOrFail
|
||||||
|
: MCD::OPC_FilterValue;
|
||||||
|
Table.push_back(DecoderOp);
|
||||||
Table.insertULEB128(FilterVal);
|
Table.insertULEB128(FilterVal);
|
||||||
|
if (DecoderOp == MCD::OPC_FilterValue) {
|
||||||
// Reserve space for the NumToSkip entry. We'll backpatch the value
|
// Reserve space for the NumToSkip entry. We'll backpatch the value
|
||||||
// later.
|
// later.
|
||||||
PrevFilter = Table.insertNumToSkip();
|
PrevFilter = Table.insertNumToSkip();
|
||||||
|
} else {
|
||||||
|
PrevFilter = 0;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// We arrive at a category of instructions with the same segment value.
|
// We arrive at a category of instructions with the same segment value.
|
||||||
@ -796,9 +808,10 @@ void Filter::emitTableEntry(DecoderTableInfo &TableInfo) const {
|
|||||||
Table.patchNumToSkip(PrevFilter, Table.size());
|
Table.patchNumToSkip(PrevFilter, Table.size());
|
||||||
}
|
}
|
||||||
|
|
||||||
// If there is no fallthrough, then the final filter should get fixed
|
// If there is no fallthrough and the final filter was not in the outermost
|
||||||
// up according to the enclosing scope rather than the current position.
|
// scope, then it must be fixed up according to the enclosing scope rather
|
||||||
if (!HasFallthrough)
|
// than the current position.
|
||||||
|
if (PrevFilter)
|
||||||
TableInfo.FixupStack.back().push_back(PrevFilter);
|
TableInfo.FixupStack.back().push_back(PrevFilter);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -863,6 +876,15 @@ void DecoderEmitter::emitTable(formatted_raw_ostream &OS, DecoderTable &Table,
|
|||||||
DecoderTable::const_iterator I = Table.begin();
|
DecoderTable::const_iterator I = Table.begin();
|
||||||
DecoderTable::const_iterator E = Table.end();
|
DecoderTable::const_iterator E = Table.end();
|
||||||
const uint8_t *const EndPtr = Table.data() + Table.size();
|
const uint8_t *const EndPtr = Table.data() + Table.size();
|
||||||
|
|
||||||
|
auto emitNumToSkipComment = [&](uint32_t NumToSkip, bool InComment = false) {
|
||||||
|
uint32_t Index = ((I - Table.begin()) + NumToSkip);
|
||||||
|
OS << (InComment ? ", " : "// ");
|
||||||
|
OS << "Skip to: " << Index;
|
||||||
|
if (*(I + NumToSkip) == MCD::OPC_Fail)
|
||||||
|
OS << " (Fail)";
|
||||||
|
};
|
||||||
|
|
||||||
while (I != E) {
|
while (I != E) {
|
||||||
assert(I < E && "incomplete decode table entry!");
|
assert(I < E && "incomplete decode table entry!");
|
||||||
|
|
||||||
@ -873,7 +895,8 @@ void DecoderEmitter::emitTable(formatted_raw_ostream &OS, DecoderTable &Table,
|
|||||||
const uint8_t DecoderOp = *I++;
|
const uint8_t DecoderOp = *I++;
|
||||||
switch (DecoderOp) {
|
switch (DecoderOp) {
|
||||||
default:
|
default:
|
||||||
PrintFatalError("Invalid decode table opcode: " + Twine(DecoderOp));
|
PrintFatalError("Invalid decode table opcode: " + Twine((int)DecoderOp) +
|
||||||
|
" at index " + Twine(Pos));
|
||||||
case MCD::OPC_ExtractField: {
|
case MCD::OPC_ExtractField: {
|
||||||
OS << Indent << "MCD::OPC_ExtractField, ";
|
OS << Indent << "MCD::OPC_ExtractField, ";
|
||||||
|
|
||||||
@ -890,17 +913,24 @@ void DecoderEmitter::emitTable(formatted_raw_ostream &OS, DecoderTable &Table,
|
|||||||
OS << Start << "} ...\n";
|
OS << Start << "} ...\n";
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case MCD::OPC_FilterValue: {
|
case MCD::OPC_FilterValue:
|
||||||
OS << Indent << "MCD::OPC_FilterValue, ";
|
case MCD::OPC_FilterValueOrFail: {
|
||||||
|
bool IsFail = DecoderOp == MCD::OPC_FilterValueOrFail;
|
||||||
|
OS << Indent << "MCD::OPC_FilterValue" << (IsFail ? "OrFail, " : ", ");
|
||||||
// The filter value is ULEB128 encoded.
|
// The filter value is ULEB128 encoded.
|
||||||
emitULEB128(I, OS);
|
emitULEB128(I, OS);
|
||||||
|
|
||||||
|
if (!IsFail) {
|
||||||
uint32_t NumToSkip = emitNumToSkip(I, OS);
|
uint32_t NumToSkip = emitNumToSkip(I, OS);
|
||||||
OS << "// Skip to: " << ((I - Table.begin()) + NumToSkip) << "\n";
|
emitNumToSkipComment(NumToSkip);
|
||||||
|
}
|
||||||
|
OS << '\n';
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case MCD::OPC_CheckField: {
|
case MCD::OPC_CheckField:
|
||||||
OS << Indent << "MCD::OPC_CheckField, ";
|
case MCD::OPC_CheckFieldOrFail: {
|
||||||
|
bool IsFail = DecoderOp == MCD::OPC_CheckFieldOrFail;
|
||||||
|
OS << Indent << "MCD::OPC_CheckField" << (IsFail ? "OrFail, " : ", ");
|
||||||
// ULEB128 encoded start value.
|
// ULEB128 encoded start value.
|
||||||
emitULEB128(I, OS);
|
emitULEB128(I, OS);
|
||||||
// 8-bit length.
|
// 8-bit length.
|
||||||
@ -909,27 +939,39 @@ void DecoderEmitter::emitTable(formatted_raw_ostream &OS, DecoderTable &Table,
|
|||||||
// ULEB128 encoded field value.
|
// ULEB128 encoded field value.
|
||||||
emitULEB128(I, OS);
|
emitULEB128(I, OS);
|
||||||
|
|
||||||
|
if (!IsFail) {
|
||||||
uint32_t NumToSkip = emitNumToSkip(I, OS);
|
uint32_t NumToSkip = emitNumToSkip(I, OS);
|
||||||
OS << "// Skip to: " << ((I - Table.begin()) + NumToSkip) << "\n";
|
emitNumToSkipComment(NumToSkip);
|
||||||
|
}
|
||||||
|
OS << '\n';
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case MCD::OPC_CheckPredicate: {
|
case MCD::OPC_CheckPredicate:
|
||||||
OS << Indent << "MCD::OPC_CheckPredicate, ";
|
case MCD::OPC_CheckPredicateOrFail: {
|
||||||
|
bool IsFail = DecoderOp == MCD::OPC_CheckPredicateOrFail;
|
||||||
|
|
||||||
|
OS << Indent << "MCD::OPC_CheckPredicate" << (IsFail ? "OrFail, " : ", ");
|
||||||
emitULEB128(I, OS);
|
emitULEB128(I, OS);
|
||||||
|
|
||||||
|
if (!IsFail) {
|
||||||
uint32_t NumToSkip = emitNumToSkip(I, OS);
|
uint32_t NumToSkip = emitNumToSkip(I, OS);
|
||||||
OS << "// Skip to: " << ((I - Table.begin()) + NumToSkip) << "\n";
|
emitNumToSkipComment(NumToSkip);
|
||||||
|
}
|
||||||
|
OS << '\n';
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case MCD::OPC_Decode:
|
case MCD::OPC_Decode:
|
||||||
case MCD::OPC_TryDecode: {
|
case MCD::OPC_TryDecode:
|
||||||
bool IsTry = DecoderOp == MCD::OPC_TryDecode;
|
case MCD::OPC_TryDecodeOrFail: {
|
||||||
|
bool IsFail = DecoderOp == MCD::OPC_TryDecodeOrFail;
|
||||||
|
bool IsTry = DecoderOp == MCD::OPC_TryDecode || IsFail;
|
||||||
// Decode the Opcode value.
|
// Decode the Opcode value.
|
||||||
const char *ErrMsg = nullptr;
|
const char *ErrMsg = nullptr;
|
||||||
unsigned Opc = decodeULEB128(&*I, nullptr, EndPtr, &ErrMsg);
|
unsigned Opc = decodeULEB128(&*I, nullptr, EndPtr, &ErrMsg);
|
||||||
assert(ErrMsg == nullptr && "ULEB128 value too large!");
|
assert(ErrMsg == nullptr && "ULEB128 value too large!");
|
||||||
|
|
||||||
OS << Indent << "MCD::OPC_" << (IsTry ? "Try" : "") << "Decode, ";
|
OS << Indent << "MCD::OPC_" << (IsTry ? "Try" : "") << "Decode"
|
||||||
|
<< (IsFail ? "OrFail, " : ", ");
|
||||||
emitULEB128(I, OS);
|
emitULEB128(I, OS);
|
||||||
|
|
||||||
// Decoder index.
|
// Decoder index.
|
||||||
@ -946,10 +988,14 @@ void DecoderEmitter::emitTable(formatted_raw_ostream &OS, DecoderTable &Table,
|
|||||||
|
|
||||||
// Fallthrough for OPC_TryDecode.
|
// Fallthrough for OPC_TryDecode.
|
||||||
|
|
||||||
|
if (!IsFail) {
|
||||||
uint32_t NumToSkip = emitNumToSkip(I, OS);
|
uint32_t NumToSkip = emitNumToSkip(I, OS);
|
||||||
|
OS << "// Opcode: " << NumberedEncodings[EncodingID];
|
||||||
OS << "// Opcode: " << NumberedEncodings[EncodingID]
|
emitNumToSkipComment(NumToSkip, /*InComment=*/true);
|
||||||
<< ", skip to: " << ((I - Table.begin()) + NumToSkip) << "\n";
|
} else {
|
||||||
|
OS << "// Opcode: " << NumberedEncodings[EncodingID];
|
||||||
|
}
|
||||||
|
OS << '\n';
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case MCD::OPC_SoftFail: {
|
case MCD::OPC_SoftFail: {
|
||||||
@ -971,12 +1017,11 @@ void DecoderEmitter::emitTable(formatted_raw_ostream &OS, DecoderTable &Table,
|
|||||||
OS << '\n';
|
OS << '\n';
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case MCD::OPC_Fail: {
|
case MCD::OPC_Fail:
|
||||||
OS << Indent << "MCD::OPC_Fail,\n";
|
OS << Indent << "MCD::OPC_Fail,\n";
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
OS << Indent << "0\n";
|
OS << Indent << "0\n";
|
||||||
|
|
||||||
Indent -= 2;
|
Indent -= 2;
|
||||||
@ -1337,12 +1382,17 @@ void FilterChooser::emitPredicateTableEntry(DecoderTableInfo &TableInfo,
|
|||||||
// computed.
|
// computed.
|
||||||
unsigned PIdx = getPredicateIndex(TableInfo, PS.str());
|
unsigned PIdx = getPredicateIndex(TableInfo, PS.str());
|
||||||
|
|
||||||
TableInfo.Table.push_back(MCD::OPC_CheckPredicate);
|
const uint8_t DecoderOp = TableInfo.isOutermostScope()
|
||||||
|
? MCD::OPC_CheckPredicateOrFail
|
||||||
|
: MCD::OPC_CheckPredicate;
|
||||||
|
TableInfo.Table.push_back(DecoderOp);
|
||||||
TableInfo.Table.insertULEB128(PIdx);
|
TableInfo.Table.insertULEB128(PIdx);
|
||||||
|
|
||||||
|
if (DecoderOp == MCD::OPC_CheckPredicate) {
|
||||||
// Push location for NumToSkip backpatching.
|
// Push location for NumToSkip backpatching.
|
||||||
TableInfo.FixupStack.back().push_back(TableInfo.Table.insertNumToSkip());
|
TableInfo.FixupStack.back().push_back(TableInfo.Table.insertNumToSkip());
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void FilterChooser::emitSoftFailTableEntry(DecoderTableInfo &TableInfo,
|
void FilterChooser::emitSoftFailTableEntry(DecoderTableInfo &TableInfo,
|
||||||
unsigned Opc) const {
|
unsigned Opc) const {
|
||||||
@ -1411,18 +1461,23 @@ void FilterChooser::emitSingletonTableEntry(DecoderTableInfo &TableInfo,
|
|||||||
for (const Island &Ilnd : reverse(Islands)) {
|
for (const Island &Ilnd : reverse(Islands)) {
|
||||||
unsigned NumBits = Ilnd.NumBits;
|
unsigned NumBits = Ilnd.NumBits;
|
||||||
assert(isUInt<8>(NumBits) && "NumBits overflowed uint8 table entry!");
|
assert(isUInt<8>(NumBits) && "NumBits overflowed uint8 table entry!");
|
||||||
TableInfo.Table.push_back(MCD::OPC_CheckField);
|
const uint8_t DecoderOp = TableInfo.isOutermostScope()
|
||||||
|
? MCD::OPC_CheckFieldOrFail
|
||||||
|
: MCD::OPC_CheckField;
|
||||||
|
TableInfo.Table.push_back(DecoderOp);
|
||||||
|
|
||||||
TableInfo.Table.insertULEB128(Ilnd.StartBit);
|
TableInfo.Table.insertULEB128(Ilnd.StartBit);
|
||||||
TableInfo.Table.push_back(NumBits);
|
TableInfo.Table.push_back(NumBits);
|
||||||
TableInfo.Table.insertULEB128(Ilnd.FieldVal);
|
TableInfo.Table.insertULEB128(Ilnd.FieldVal);
|
||||||
|
|
||||||
|
if (DecoderOp == MCD::OPC_CheckField) {
|
||||||
// Allocate space in the table for fixup so all our relative position
|
// Allocate space in the table for fixup so all our relative position
|
||||||
// calculations work OK even before we fully resolve the real value here.
|
// calculations work OK even before we fully resolve the real value here.
|
||||||
|
|
||||||
// Push location for NumToSkip backpatching.
|
// Push location for NumToSkip backpatching.
|
||||||
TableInfo.FixupStack.back().push_back(TableInfo.Table.insertNumToSkip());
|
TableInfo.FixupStack.back().push_back(TableInfo.Table.insertNumToSkip());
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Check for soft failure of the match.
|
// Check for soft failure of the match.
|
||||||
emitSoftFailTableEntry(TableInfo, Opc.EncodingID);
|
emitSoftFailTableEntry(TableInfo, Opc.EncodingID);
|
||||||
@ -1439,13 +1494,16 @@ void FilterChooser::emitSingletonTableEntry(DecoderTableInfo &TableInfo,
|
|||||||
// decoder method indicates that additional processing should be done to see
|
// decoder method indicates that additional processing should be done to see
|
||||||
// if there is any other instruction that also matches the bitpattern and
|
// if there is any other instruction that also matches the bitpattern and
|
||||||
// can decode it.
|
// can decode it.
|
||||||
TableInfo.Table.push_back(HasCompleteDecoder ? MCD::OPC_Decode
|
const uint8_t DecoderOp = HasCompleteDecoder ? MCD::OPC_Decode
|
||||||
|
: (TableInfo.isOutermostScope()
|
||||||
|
? MCD::OPC_TryDecodeOrFail
|
||||||
: MCD::OPC_TryDecode);
|
: MCD::OPC_TryDecode);
|
||||||
|
TableInfo.Table.push_back(DecoderOp);
|
||||||
NumEncodingsSupported++;
|
NumEncodingsSupported++;
|
||||||
TableInfo.Table.insertULEB128(Opc.Opcode);
|
TableInfo.Table.insertULEB128(Opc.Opcode);
|
||||||
TableInfo.Table.insertULEB128(DIdx);
|
TableInfo.Table.insertULEB128(DIdx);
|
||||||
|
|
||||||
if (!HasCompleteDecoder) {
|
if (DecoderOp == MCD::OPC_TryDecode) {
|
||||||
// Push location for NumToSkip backpatching.
|
// Push location for NumToSkip backpatching.
|
||||||
TableInfo.FixupStack.back().push_back(TableInfo.Table.insertNumToSkip());
|
TableInfo.FixupStack.back().push_back(TableInfo.Table.insertNumToSkip());
|
||||||
}
|
}
|
||||||
@ -2188,7 +2246,8 @@ static DecodeStatus decodeInstruction(const uint8_t DecodeTable[], MCInst &MI,
|
|||||||
DecodeStatus S = MCDisassembler::Success;
|
DecodeStatus S = MCDisassembler::Success;
|
||||||
while (true) {
|
while (true) {
|
||||||
ptrdiff_t Loc = Ptr - DecodeTable;
|
ptrdiff_t Loc = Ptr - DecodeTable;
|
||||||
switch (*Ptr++) {
|
const uint8_t DecoderOp = *Ptr++;
|
||||||
|
switch (DecoderOp) {
|
||||||
default:
|
default:
|
||||||
errs() << Loc << ": Unexpected decode table opcode!\n";
|
errs() << Loc << ": Unexpected decode table opcode!\n";
|
||||||
return MCDisassembler::Fail;
|
return MCDisassembler::Fail;
|
||||||
@ -2204,22 +2263,34 @@ static DecodeStatus decodeInstruction(const uint8_t DecodeTable[], MCInst &MI,
|
|||||||
<< Len << "): " << CurFieldValue << "\n");
|
<< Len << "): " << CurFieldValue << "\n");
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case MCD::OPC_FilterValue: {
|
case MCD::OPC_FilterValue:
|
||||||
|
case MCD::OPC_FilterValueOrFail: {
|
||||||
|
bool IsFail = DecoderOp == MCD::OPC_FilterValueOrFail;
|
||||||
// Decode the field value.
|
// Decode the field value.
|
||||||
uint64_t Val = decodeULEB128AndIncUnsafe(Ptr);
|
uint64_t Val = decodeULEB128AndIncUnsafe(Ptr);
|
||||||
bool Failed = Val != CurFieldValue;
|
bool Failed = Val != CurFieldValue;
|
||||||
unsigned NumToSkip = decodeNumToSkip(Ptr);
|
unsigned NumToSkip = IsFail ? 0 : decodeNumToSkip(Ptr);
|
||||||
|
|
||||||
|
// Note: Print NumToSkip even for OPC_FilterValueOrFail to simplify debug
|
||||||
|
// prints.
|
||||||
|
LLVM_DEBUG({
|
||||||
|
StringRef OpName = IsFail ? "OPC_FilterValueOrFail" : "OPC_FilterValue";
|
||||||
|
dbgs() << Loc << ": " << OpName << '(' << Val << ", " << NumToSkip
|
||||||
|
<< ") " << (Failed ? "FAIL:" : "PASS:")
|
||||||
|
<< " continuing at " << (Ptr - DecodeTable) << '\n';
|
||||||
|
});
|
||||||
|
|
||||||
// Perform the filter operation.
|
// Perform the filter operation.
|
||||||
if (Failed)
|
if (Failed) {
|
||||||
|
if (IsFail)
|
||||||
|
return MCDisassembler::Fail;
|
||||||
Ptr += NumToSkip;
|
Ptr += NumToSkip;
|
||||||
LLVM_DEBUG(dbgs() << Loc << ": OPC_FilterValue(" << Val << ", " << NumToSkip
|
}
|
||||||
<< "): " << (Failed ? "FAIL:" : "PASS:")
|
|
||||||
<< " continuing at " << (Ptr - DecodeTable) << "\n");
|
|
||||||
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case MCD::OPC_CheckField: {
|
case MCD::OPC_CheckField:
|
||||||
|
case MCD::OPC_CheckFieldOrFail: {
|
||||||
|
bool IsFail = DecoderOp == MCD::OPC_CheckFieldOrFail;
|
||||||
// Decode the start value.
|
// Decode the start value.
|
||||||
unsigned Start = decodeULEB128AndIncUnsafe(Ptr);
|
unsigned Start = decodeULEB128AndIncUnsafe(Ptr);
|
||||||
unsigned Len = *Ptr;)";
|
unsigned Len = *Ptr;)";
|
||||||
@ -2232,29 +2303,44 @@ static DecodeStatus decodeInstruction(const uint8_t DecodeTable[], MCInst &MI,
|
|||||||
uint64_t ExpectedValue = decodeULEB128(++Ptr, &PtrLen);
|
uint64_t ExpectedValue = decodeULEB128(++Ptr, &PtrLen);
|
||||||
Ptr += PtrLen;
|
Ptr += PtrLen;
|
||||||
bool Failed = ExpectedValue != FieldValue;
|
bool Failed = ExpectedValue != FieldValue;
|
||||||
unsigned NumToSkip = decodeNumToSkip(Ptr);
|
unsigned NumToSkip = IsFail ? 0 : decodeNumToSkip(Ptr);
|
||||||
|
|
||||||
// If the actual and expected values don't match, skip.
|
LLVM_DEBUG({
|
||||||
if (Failed)
|
StringRef OpName = IsFail ? "OPC_CheckFieldOrFail" : "OPC_CheckField";
|
||||||
|
dbgs() << Loc << ": " << OpName << '(' << Start << ", " << Len << ", "
|
||||||
|
<< ExpectedValue << ", " << NumToSkip << "): FieldValue = "
|
||||||
|
<< FieldValue << ", ExpectedValue = " << ExpectedValue << ": "
|
||||||
|
<< (Failed ? "FAIL\n" : "PASS\n");
|
||||||
|
});
|
||||||
|
|
||||||
|
// If the actual and expected values don't match, skip or fail.
|
||||||
|
if (Failed) {
|
||||||
|
if (IsFail)
|
||||||
|
return MCDisassembler::Fail;
|
||||||
Ptr += NumToSkip;
|
Ptr += NumToSkip;
|
||||||
LLVM_DEBUG(dbgs() << Loc << ": OPC_CheckField(" << Start << ", "
|
}
|
||||||
<< Len << ", " << ExpectedValue << ", " << NumToSkip
|
|
||||||
<< "): FieldValue = " << FieldValue << ", ExpectedValue = "
|
|
||||||
<< ExpectedValue << ": "
|
|
||||||
<< (Failed ? "FAIL\n" : "PASS\n"));
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case MCD::OPC_CheckPredicate: {
|
case MCD::OPC_CheckPredicate:
|
||||||
|
case MCD::OPC_CheckPredicateOrFail: {
|
||||||
|
bool IsFail = DecoderOp == MCD::OPC_CheckPredicateOrFail;
|
||||||
// Decode the Predicate Index value.
|
// Decode the Predicate Index value.
|
||||||
unsigned PIdx = decodeULEB128AndIncUnsafe(Ptr);
|
unsigned PIdx = decodeULEB128AndIncUnsafe(Ptr);
|
||||||
unsigned NumToSkip = decodeNumToSkip(Ptr);
|
unsigned NumToSkip = IsFail ? 0 : decodeNumToSkip(Ptr);
|
||||||
// Check the predicate.
|
// Check the predicate.
|
||||||
bool Failed = !checkDecoderPredicate(PIdx, Bits);
|
bool Failed = !checkDecoderPredicate(PIdx, Bits);
|
||||||
if (Failed)
|
|
||||||
Ptr += NumToSkip;
|
|
||||||
LLVM_DEBUG(dbgs() << Loc << ": OPC_CheckPredicate(" << PIdx << "): "
|
|
||||||
<< (Failed ? "FAIL\n" : "PASS\n"));
|
|
||||||
|
|
||||||
|
LLVM_DEBUG({
|
||||||
|
StringRef OpName = IsFail ? "OPC_CheckPredicateOrFail" : "OPC_CheckPredicate";
|
||||||
|
dbgs() << Loc << ": " << OpName << '(' << PIdx << ", " << NumToSkip
|
||||||
|
<< "): " << (Failed ? "FAIL\n" : "PASS\n");
|
||||||
|
});
|
||||||
|
|
||||||
|
if (Failed) {
|
||||||
|
if (IsFail)
|
||||||
|
return MCDisassembler::Fail;
|
||||||
|
Ptr += NumToSkip;
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case MCD::OPC_Decode: {
|
case MCD::OPC_Decode: {
|
||||||
@ -2275,14 +2361,16 @@ static DecodeStatus decodeInstruction(const uint8_t DecodeTable[], MCInst &MI,
|
|||||||
|
|
||||||
LLVM_DEBUG(dbgs() << Loc << ": OPC_Decode: opcode " << Opc
|
LLVM_DEBUG(dbgs() << Loc << ": OPC_Decode: opcode " << Opc
|
||||||
<< ", using decoder " << DecodeIdx << ": "
|
<< ", using decoder " << DecodeIdx << ": "
|
||||||
<< (S != MCDisassembler::Fail ? "PASS" : "FAIL") << "\n");
|
<< (S != MCDisassembler::Fail ? "PASS\n" : "FAIL\n"));
|
||||||
return S;
|
return S;
|
||||||
}
|
}
|
||||||
case MCD::OPC_TryDecode: {
|
case MCD::OPC_TryDecode:
|
||||||
|
case MCD::OPC_TryDecodeOrFail: {
|
||||||
|
bool IsFail = DecoderOp == MCD::OPC_TryDecodeOrFail;
|
||||||
// Decode the Opcode value.
|
// Decode the Opcode value.
|
||||||
unsigned Opc = decodeULEB128AndIncUnsafe(Ptr);
|
unsigned Opc = decodeULEB128AndIncUnsafe(Ptr);
|
||||||
unsigned DecodeIdx = decodeULEB128AndIncUnsafe(Ptr);
|
unsigned DecodeIdx = decodeULEB128AndIncUnsafe(Ptr);
|
||||||
unsigned NumToSkip = decodeNumToSkip(Ptr);
|
unsigned NumToSkip = IsFail ? 0 : decodeNumToSkip(Ptr);
|
||||||
|
|
||||||
// Perform the decode operation.
|
// Perform the decode operation.
|
||||||
MCInst TmpMI;
|
MCInst TmpMI;
|
||||||
@ -2294,28 +2382,31 @@ static DecodeStatus decodeInstruction(const uint8_t DecodeTable[], MCInst &MI,
|
|||||||
|
|
||||||
if (DecodeComplete) {
|
if (DecodeComplete) {
|
||||||
// Decoding complete.
|
// Decoding complete.
|
||||||
LLVM_DEBUG(dbgs() << (S != MCDisassembler::Fail ? "PASS" : "FAIL") << "\n");
|
LLVM_DEBUG(dbgs() << (S != MCDisassembler::Fail ? "PASS\n" : "FAIL\n"));
|
||||||
MI = TmpMI;
|
MI = TmpMI;
|
||||||
return S;
|
return S;
|
||||||
} else {
|
}
|
||||||
assert(S == MCDisassembler::Fail);
|
assert(S == MCDisassembler::Fail);
|
||||||
|
if (IsFail) {
|
||||||
|
LLVM_DEBUG(dbgs() << "FAIL: returning FAIL\n");
|
||||||
|
return MCDisassembler::Fail;
|
||||||
|
}
|
||||||
// If the decoding was incomplete, skip.
|
// If the decoding was incomplete, skip.
|
||||||
Ptr += NumToSkip;
|
Ptr += NumToSkip;
|
||||||
LLVM_DEBUG(dbgs() << "FAIL: continuing at " << (Ptr - DecodeTable) << "\n");
|
LLVM_DEBUG(dbgs() << "FAIL: continuing at " << (Ptr - DecodeTable) << "\n");
|
||||||
// Reset decode status. This also drops a SoftFail status that could be
|
// Reset decode status. This also drops a SoftFail status that could be
|
||||||
// set before the decode attempt.
|
// set before the decode attempt.
|
||||||
S = MCDisassembler::Success;
|
S = MCDisassembler::Success;
|
||||||
}
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case MCD::OPC_SoftFail: {
|
case MCD::OPC_SoftFail: {
|
||||||
// Decode the mask values.
|
// Decode the mask values.
|
||||||
uint64_t PositiveMask = decodeULEB128AndIncUnsafe(Ptr);
|
uint64_t PositiveMask = decodeULEB128AndIncUnsafe(Ptr);
|
||||||
uint64_t NegativeMask = decodeULEB128AndIncUnsafe(Ptr);
|
uint64_t NegativeMask = decodeULEB128AndIncUnsafe(Ptr);
|
||||||
bool Fail = (insn & PositiveMask) != 0 || (~insn & NegativeMask) != 0;
|
bool Failed = (insn & PositiveMask) != 0 || (~insn & NegativeMask) != 0;
|
||||||
if (Fail)
|
if (Failed)
|
||||||
S = MCDisassembler::SoftFail;
|
S = MCDisassembler::SoftFail;
|
||||||
LLVM_DEBUG(dbgs() << Loc << ": OPC_SoftFail: " << (Fail ? "FAIL\n" : "PASS\n"));
|
LLVM_DEBUG(dbgs() << Loc << ": OPC_SoftFail: " << (Failed ? "FAIL\n" : "PASS\n"));
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case MCD::OPC_Fail: {
|
case MCD::OPC_Fail: {
|
||||||
|
@ -2116,7 +2116,6 @@ llvm_target_lib_list = [lib for lib in [
|
|||||||
"lib/Target/AArch64/AArch64GenSubtargetInfo.inc": ["-gen-subtarget"],
|
"lib/Target/AArch64/AArch64GenSubtargetInfo.inc": ["-gen-subtarget"],
|
||||||
"lib/Target/AArch64/AArch64GenDisassemblerTables.inc": [
|
"lib/Target/AArch64/AArch64GenDisassemblerTables.inc": [
|
||||||
"-gen-disassembler",
|
"-gen-disassembler",
|
||||||
"--large-decoder-table",
|
|
||||||
],
|
],
|
||||||
"lib/Target/AArch64/AArch64GenSystemOperands.inc": ["-gen-searchable-tables"],
|
"lib/Target/AArch64/AArch64GenSystemOperands.inc": ["-gen-searchable-tables"],
|
||||||
"lib/Target/AArch64/AArch64GenExegesis.inc": ["-gen-exegesis"],
|
"lib/Target/AArch64/AArch64GenExegesis.inc": ["-gen-exegesis"],
|
||||||
|
Loading…
x
Reference in New Issue
Block a user