Skip to content

Commit c8136da

Browse files
authored
[RISCV] Correctly Decode Unsigned Immediates with Ranges (llvm#128584)
We currently have two operands upstream that are an unsigned immediate with a range constraint - `uimm8ge32` (for `cm.jalt`) and `uimm5gt3` (for `qc.shladd`). Both of these were using `decodeUImmOperand<N>` for decoding. For `Zcmt` this worked, because the generated decoder automatically checked for `cm.jt` first because the 8 undefined bits in `cm.jalt` are `000?????` in `cm.jt` (this is to do with the range lower-bound being a power-of-two). For Zcmt, this patch is NFC. We have less luck with `Xqciac` - `qc.shladd` is being decoded where the `uimm5` field is 3 or lower. This patch fixes this by introducing a `decodeUImmOperandGE<Width, LowerBound>` helper, which will corretly return `MCDisassembler::Fail` when the immediate is below the lower bound. I have added a test to show the encoding where `uimm5` is equal to 3 is no longer disassembled as `qc.shladd`.
1 parent 9102afc commit c8136da

File tree

4 files changed

+25
-2
lines changed

4 files changed

+25
-2
lines changed

llvm/lib/Target/RISCV/Disassembler/RISCVDisassembler.cpp

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -328,6 +328,19 @@ static DecodeStatus decodeUImmOperand(MCInst &Inst, uint32_t Imm,
328328
return MCDisassembler::Success;
329329
}
330330

331+
template <unsigned Width, unsigned LowerBound>
332+
static DecodeStatus decodeUImmOperandGE(MCInst &Inst, uint32_t Imm,
333+
int64_t Address,
334+
const MCDisassembler *Decoder) {
335+
assert(isUInt<Width>(Imm) && "Invalid immediate");
336+
337+
if (Imm < LowerBound)
338+
return MCDisassembler::Fail;
339+
340+
Inst.addOperand(MCOperand::createImm(Imm));
341+
return MCDisassembler::Success;
342+
}
343+
331344
static DecodeStatus decodeUImmLog2XLenOperand(MCInst &Inst, uint32_t Imm,
332345
int64_t Address,
333346
const MCDisassembler *Decoder) {

llvm/lib/Target/RISCV/RISCVInstrInfoXqci.td

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@ def uimm5nonzero : RISCVOp<XLenVT>,
2424
def uimm5gt3 : RISCVOp<XLenVT>, ImmLeaf<XLenVT,
2525
[{return (Imm > 3) && isUInt<5>(Imm);}]> {
2626
let ParserMatchClass = UImmAsmOperand<5, "GT3">;
27-
let DecoderMethod = "decodeUImmOperand<5>";
27+
let DecoderMethod = "decodeUImmOperandGE<5, 4>";
2828
let OperandType = "OPERAND_UIMM5_GT3";
2929
}
3030

llvm/lib/Target/RISCV/RISCVInstrInfoZc.td

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,7 @@ def uimm2_lsb0 : RISCVOp,
3131

3232
def uimm8ge32 : RISCVOp {
3333
let ParserMatchClass = UImmAsmOperand<8, "GE32">;
34-
let DecoderMethod = "decodeUImmOperand<8>";
34+
let DecoderMethod = "decodeUImmOperandGE<8, 32>";
3535
let OperandType = "OPERAND_UIMM8_GE32";
3636
}
3737

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
# RUN: not llvm-mc -disassemble -triple=riscv32 -mattr=+experimental-xqciac %s | FileCheck %s
2+
3+
[0x00,0x00]
4+
# CHECK: unimp
5+
6+
[0x8b,0x30,0x31,0x46]
7+
# CHECK-NOT: qc.shladd x1, x2, x3, {{[0-9]+}}
8+
9+
[0x00,0x00]
10+
# CHECK: unimp

0 commit comments

Comments
 (0)