aboutsummaryrefslogtreecommitdiff
path: root/llvm/lib/Target/RISCV/Disassembler/RISCVDisassembler.cpp
diff options
context:
space:
mode:
authorCraig Topper <craig.topper@sifive.com>2024-04-29 10:11:28 -0700
committerGitHub <noreply@github.com>2024-04-29 10:11:28 -0700
commit618adc762e95b33576c42be8912bb48dd0fdff94 (patch)
treefc5107357d9cea965b6c12b6cc7ca7572e655d5d /llvm/lib/Target/RISCV/Disassembler/RISCVDisassembler.cpp
parent99df06ac71b12bc5a38240e71cfc37383687b48e (diff)
downloadllvm-618adc762e95b33576c42be8912bb48dd0fdff94.zip
llvm-618adc762e95b33576c42be8912bb48dd0fdff94.tar.gz
llvm-618adc762e95b33576c42be8912bb48dd0fdff94.tar.bz2
[RISCV] Support instruction sizes up to 176-bits in disassembler. (#90371)
We don't have any instructions defined yet, but that we can still read the correct number of bytes when disassembling. This should better match GNU objdump behavior.
Diffstat (limited to 'llvm/lib/Target/RISCV/Disassembler/RISCVDisassembler.cpp')
-rw-r--r--llvm/lib/Target/RISCV/Disassembler/RISCVDisassembler.cpp42
1 files changed, 37 insertions, 5 deletions
diff --git a/llvm/lib/Target/RISCV/Disassembler/RISCVDisassembler.cpp b/llvm/lib/Target/RISCV/Disassembler/RISCVDisassembler.cpp
index 7ca2019..b9e8e1f 100644
--- a/llvm/lib/Target/RISCV/Disassembler/RISCVDisassembler.cpp
+++ b/llvm/lib/Target/RISCV/Disassembler/RISCVDisassembler.cpp
@@ -656,12 +656,44 @@ DecodeStatus RISCVDisassembler::getInstruction(MCInst &MI, uint64_t &Size,
ArrayRef<uint8_t> Bytes,
uint64_t Address,
raw_ostream &CS) const {
- // TODO: This will need modification when supporting instruction set
- // extensions with instructions > 32-bits (up to 176 bits wide).
+ // It's a 16 bit instruction if bit 0 and 1 are not 0b11.
+ if ((Bytes[0] & 0b11) != 0b11)
+ return getInstruction16(MI, Size, Bytes, Address, CS);
- // It's a 32 bit instruction if bit 0 and 1 are 1.
- if ((Bytes[0] & 0x3) == 0x3)
+ // It's a 32 bit instruction if bit 1:0 are 0b11(checked above) and bits 4:2
+ // are not 0b111.
+ if ((Bytes[0] & 0b1'1100) != 0b1'1100)
return getInstruction32(MI, Size, Bytes, Address, CS);
- return getInstruction16(MI, Size, Bytes, Address, CS);
+ // 48-bit instructions are encoded as 0bxx011111.
+ if ((Bytes[0] & 0b11'1111) == 0b01'1111) {
+ Size = Bytes.size() >= 6 ? 6 : 0;
+ return MCDisassembler::Fail;
+ }
+
+ // 64-bit instructions are encoded as 0x0111111.
+ if ((Bytes[0] & 0b111'1111) == 0b011'1111) {
+ Size = Bytes.size() >= 8 ? 8 : 0;
+ return MCDisassembler::Fail;
+ }
+
+ // Remaining cases need to check a second byte.
+ if (Bytes.size() < 2) {
+ Size = 0;
+ return MCDisassembler::Fail;
+ }
+
+ // 80-bit through 176-bit instructions are encoded as 0bxnnnxxxx_x1111111.
+ // Where the number of bits is (80 + (nnn * 16)) for nnn != 0b111.
+ unsigned nnn = (Bytes[1] >> 4) & 0b111;
+ if (nnn != 0b111) {
+ Size = 10 + (nnn * 2);
+ if (Bytes.size() < Size)
+ Size = 0;
+ return MCDisassembler::Fail;
+ }
+
+ // Remaining encodings are reserved for > 176-bit instructions.
+ Size = 0;
+ return MCDisassembler::Fail;
}