Skip to content

Commit 74591a0

Browse files
ArcaneNibblezznop
authored andcommitted
[RISCV] Implement the remaining Zbb instructions
1 parent eab3411 commit 74591a0

2 files changed

Lines changed: 188 additions & 1 deletion

File tree

arch/riscv/disasm/src/lib.rs

Lines changed: 54 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -224,6 +224,15 @@ pub enum Op<D: RiscVDisassembler> {
224224
RolW(RTypeIntInst<D>),
225225
RorW(RTypeIntInst<D>),
226226
RorIW(ITypeIntInst<D>),
227+
228+
Clz(ITypeIntInst<D>),
229+
ClzW(ITypeIntInst<D>),
230+
Ctz(ITypeIntInst<D>),
231+
CtzW(ITypeIntInst<D>),
232+
Cpop(ITypeIntInst<D>),
233+
CpopW(ITypeIntInst<D>),
234+
Orcb(ITypeIntInst<D>),
235+
Rev8(ITypeIntInst<D>),
227236
}
228237

229238
pub trait Register {
@@ -1910,7 +1919,16 @@ impl<D: RiscVDisassembler> Instr<D> {
19101919
ops.push(Operand::R(r.rs1()));
19111920
ops.push(Operand::R(r.rs2()));
19121921
}
1913-
Op::SextB(ref i) | Op::SextH(ref i) => {
1922+
Op::SextB(ref i)
1923+
| Op::SextH(ref i)
1924+
| Op::Clz(ref i)
1925+
| Op::ClzW(ref i)
1926+
| Op::Ctz(ref i)
1927+
| Op::CtzW(ref i)
1928+
| Op::Cpop(ref i)
1929+
| Op::CpopW(ref i)
1930+
| Op::Orcb(ref i)
1931+
| Op::Rev8(ref i) => {
19141932
ops.push(Operand::R(i.rd()));
19151933
ops.push(Operand::R(i.rs1()));
19161934
}
@@ -2216,6 +2234,15 @@ impl<'a, D: RiscVDisassembler + 'a> Mnem<'a, D> {
22162234
Op::RolW(..) => "rolw",
22172235
Op::RorW(..) => "rorw",
22182236
Op::RorIW(..) => "roriw",
2237+
2238+
Op::Clz(..) => "clz",
2239+
Op::ClzW(..) => "clzw",
2240+
Op::Ctz(..) => "ctz",
2241+
Op::CtzW(..) => "ctzw",
2242+
Op::Cpop(..) => "cpop",
2243+
Op::CpopW(..) => "cpopw",
2244+
Op::Orcb(..) => "orc.b",
2245+
Op::Rev8(..) => "rev8",
22192246
},
22202247
}
22212248
}
@@ -2927,6 +2954,9 @@ pub trait RiscVDisassembler: 'static + Debug + Sized + Copy + Clone + Send + Syn
29272954
}
29282955
0b011000 if Self::BitmanipZbbExtension::supported() => {
29292956
match orig_imm & 0b11111 {
2957+
0b00000 => Op::Clz(itype),
2958+
0b00001 => Op::Ctz(itype),
2959+
0b00010 => Op::Cpop(itype),
29302960
0b00100 => Op::SextB(itype),
29312961
0b00101 => Op::SextH(itype),
29322962
_ => return Err(InvalidSubop),
@@ -2937,6 +2967,7 @@ pub trait RiscVDisassembler: 'static + Debug + Sized + Copy + Clone + Send + Syn
29372967
}
29382968
0b101 => {
29392969
let shift_opc = inst.0 >> 26;
2970+
let orig_imm = inst.i_imm();
29402971

29412972
// pretty terrible hack to clear bits for shamt
29422973
if int_width > 4 {
@@ -2947,13 +2978,26 @@ pub trait RiscVDisassembler: 'static + Debug + Sized + Copy + Clone + Send + Syn
29472978

29482979
match shift_opc {
29492980
0b000000 => Op::SrlI(itype),
2981+
0b001010 if Self::BitmanipZbbExtension::supported() => {
2982+
match orig_imm & 0b111111 {
2983+
0b000111 => Op::Orcb(itype),
2984+
_ => return Err(InvalidSubop),
2985+
}
2986+
}
29502987
0b010000 => Op::SraI(itype),
29512988
0b010010 if Self::BitmanipZbsExtension::supported() => {
29522989
Op::BextI(itype)
29532990
}
29542991
0b011000 if Self::BitmanipZbbExtension::supported() => {
29552992
Op::RorI(itype)
29562993
}
2994+
0b011010 if Self::BitmanipZbbExtension::supported() => {
2995+
match orig_imm & 0b111111 {
2996+
0b011000 if int_width == 4 => Op::Rev8(itype),
2997+
0b111000 if int_width == 8 => Op::Rev8(itype),
2998+
_ => return Err(InvalidSubop),
2999+
}
3000+
}
29573001
_ => return Err(InvalidSubop),
29583002
}
29593003
}
@@ -2970,12 +3014,21 @@ pub trait RiscVDisassembler: 'static + Debug + Sized + Copy + Clone + Send + Syn
29703014
0b000 => Op::AddIW(itype),
29713015
0b001 => {
29723016
let shift_opc = inst.0 >> 26;
3017+
let orig_imm = inst.i_imm();
29733018
// pretty terrible hack to clear bits for shamt
29743019
itype.inst.0 &= !0xfc000000;
29753020

29763021
match shift_opc {
29773022
0b000000 => Op::SllIW(itype),
29783023
0b000010 => Op::SllIUW(itype),
3024+
0b011000 if Self::BitmanipZbbExtension::supported() => {
3025+
match orig_imm & 0b11111 {
3026+
0b00000 => Op::ClzW(itype),
3027+
0b00001 => Op::CtzW(itype),
3028+
0b00010 => Op::CpopW(itype),
3029+
_ => return Err(InvalidSubop),
3030+
}
3031+
}
29793032
_ => return Err(InvalidSubop),
29803033
}
29813034
}

arch/riscv/src/lib.rs

Lines changed: 134 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -84,6 +84,11 @@ enum Intrinsic {
8484
FcvtUToF(u8, u8, RoundMode),
8585
FcvtFToU(u8, u8, RoundMode),
8686
Fence,
87+
Clz,
88+
Ctz,
89+
Popcount,
90+
OrCombine,
91+
Rev8,
8792
}
8893

8994
#[derive(Copy, Clone)]
@@ -341,6 +346,11 @@ impl<D: RiscVDisassembler> RiscVIntrinsic<D> {
341346
Some((23, usize, fsize, rm)) => Some(Intrinsic::FcvtUToF(usize, fsize, rm).into()),
342347
Some((24, fsize, usize, rm)) => Some(Intrinsic::FcvtFToU(fsize, usize, rm).into()),
343348
Some((25, _, _, _)) => Some(Intrinsic::Fence.into()),
349+
Some((26, _, _, _)) => Some(Intrinsic::Clz.into()),
350+
Some((27, _, _, _)) => Some(Intrinsic::Ctz.into()),
351+
Some((28, _, _, _)) => Some(Intrinsic::Popcount.into()),
352+
Some((29, _, _, _)) => Some(Intrinsic::OrCombine.into()),
353+
Some((30, _, _, _)) => Some(Intrinsic::Rev8.into()),
344354
_ => None,
345355
}
346356
}
@@ -475,6 +485,11 @@ impl<D: RiscVDisassembler> architecture::Intrinsic for RiscVIntrinsic<D> {
475485
)
476486
.into(),
477487
Intrinsic::Fence => "_fence".into(),
488+
Intrinsic::Clz => "_clz".into(),
489+
Intrinsic::Ctz => "_ctz".into(),
490+
Intrinsic::Popcount => "_popcount".into(),
491+
Intrinsic::OrCombine => "_orc_b".into(),
492+
Intrinsic::Rev8 => "_rev8".into(),
478493
}
479494
}
480495

@@ -516,6 +531,11 @@ impl<D: RiscVDisassembler> architecture::Intrinsic for RiscVIntrinsic<D> {
516531
Self::id_from_parts(24, Some(usize), Some(fsize), Some(rm))
517532
}
518533
Intrinsic::Fence => Self::id_from_parts(25, None, None, None),
534+
Intrinsic::Clz => Self::id_from_parts(26, None, None, None),
535+
Intrinsic::Ctz => Self::id_from_parts(27, None, None, None),
536+
Intrinsic::Popcount => Self::id_from_parts(28, None, None, None),
537+
Intrinsic::OrCombine => Self::id_from_parts(29, None, None, None),
538+
Intrinsic::Rev8 => Self::id_from_parts(30, None, None, None),
519539
}
520540
}
521541

@@ -584,6 +604,19 @@ impl<D: RiscVDisassembler> architecture::Intrinsic for RiscVIntrinsic<D> {
584604
Conf::new(Type::int(4, false), MIN_CONFIDENCE),
585605
)]
586606
}
607+
Intrinsic::Clz
608+
| Intrinsic::Ctz
609+
| Intrinsic::Popcount
610+
| Intrinsic::OrCombine
611+
| Intrinsic::Rev8 => {
612+
vec![NameAndType::new(
613+
"input",
614+
Conf::new(
615+
Type::int(<D::RegFile as RegFile>::Int::width(), false),
616+
MIN_CONFIDENCE,
617+
),
618+
)]
619+
}
587620
}
588621
}
589622

@@ -627,6 +660,16 @@ impl<D: RiscVDisassembler> architecture::Intrinsic for RiscVIntrinsic<D> {
627660
Intrinsic::FcvtFToU(_, size, _) => {
628661
vec![Conf::new(Type::int(size as usize, false), MAX_CONFIDENCE)]
629662
}
663+
Intrinsic::Clz
664+
| Intrinsic::Ctz
665+
| Intrinsic::Popcount
666+
| Intrinsic::OrCombine
667+
| Intrinsic::Rev8 => {
668+
vec![Conf::new(
669+
Type::int(<D::RegFile as RegFile>::Int::width(), false),
670+
MIN_CONFIDENCE,
671+
)]
672+
}
630673
}
631674
}
632675
}
@@ -1214,6 +1257,61 @@ impl<D: RiscVDisassembler> Architecture for RiscVArch<D> {
12141257
}),
12151258

12161259
Op::RorI(i) => simple_i!(i, |rs1, imm| il.ror(max_width, rs1, imm)),
1260+
Op::Clz(i) => {
1261+
let rd = Register::from(i.rd());
1262+
let rs1 = LiftableLowLevelIL::lift(il, Register::from(i.rs1()));
1263+
1264+
if i.rd().id() == 0 {
1265+
il.nop().append();
1266+
} else {
1267+
il.intrinsic([rd], RiscVIntrinsic::<D>::from(Intrinsic::Clz), [rs1])
1268+
.append();
1269+
}
1270+
}
1271+
Op::Ctz(i) => {
1272+
let rd = Register::from(i.rd());
1273+
let rs1 = LiftableLowLevelIL::lift(il, Register::from(i.rs1()));
1274+
1275+
if i.rd().id() == 0 {
1276+
il.nop().append();
1277+
} else {
1278+
il.intrinsic([rd], RiscVIntrinsic::<D>::from(Intrinsic::Ctz), [rs1])
1279+
.append();
1280+
}
1281+
}
1282+
Op::Cpop(i) => {
1283+
let rd = Register::from(i.rd());
1284+
let rs1 = LiftableLowLevelIL::lift(il, Register::from(i.rs1()));
1285+
1286+
if i.rd().id() == 0 {
1287+
il.nop().append();
1288+
} else {
1289+
il.intrinsic([rd], RiscVIntrinsic::<D>::from(Intrinsic::Popcount), [rs1])
1290+
.append();
1291+
}
1292+
}
1293+
Op::Orcb(i) => {
1294+
let rd = Register::from(i.rd());
1295+
let rs1 = LiftableLowLevelIL::lift(il, Register::from(i.rs1()));
1296+
1297+
if i.rd().id() == 0 {
1298+
il.nop().append();
1299+
} else {
1300+
il.intrinsic([rd], RiscVIntrinsic::<D>::from(Intrinsic::OrCombine), [rs1])
1301+
.append();
1302+
}
1303+
}
1304+
Op::Rev8(i) => {
1305+
let rd = Register::from(i.rd());
1306+
let rs1 = LiftableLowLevelIL::lift(il, Register::from(i.rs1()));
1307+
1308+
if i.rd().id() == 0 {
1309+
il.nop().append();
1310+
} else {
1311+
il.intrinsic([rd], RiscVIntrinsic::<D>::from(Intrinsic::Rev8), [rs1])
1312+
.append();
1313+
}
1314+
}
12171315

12181316
// r-type
12191317
Op::Add(r) => simple_r!(r, |rs1, rs2| il.add(max_width, rs1, rs2)),
@@ -1311,6 +1409,42 @@ impl<D: RiscVDisassembler> Architecture for RiscVArch<D> {
13111409
}),
13121410

13131411
Op::RorIW(i) => simple_i!(i, |rs1, imm| il.sx(max_width, il.ror(4, rs1, imm))),
1412+
Op::ClzW(i) => {
1413+
let rd = Register::from(i.rd());
1414+
let rs1 =
1415+
LiftableLowLevelILWithSize::lift_with_size(il, Register::from(i.rs1()), 4);
1416+
1417+
if i.rd().id() == 0 {
1418+
il.nop().append();
1419+
} else {
1420+
il.intrinsic([rd], RiscVIntrinsic::<D>::from(Intrinsic::Clz), [rs1])
1421+
.append();
1422+
}
1423+
}
1424+
Op::CtzW(i) => {
1425+
let rd = Register::from(i.rd());
1426+
let rs1 =
1427+
LiftableLowLevelILWithSize::lift_with_size(il, Register::from(i.rs1()), 4);
1428+
1429+
if i.rd().id() == 0 {
1430+
il.nop().append();
1431+
} else {
1432+
il.intrinsic([rd], RiscVIntrinsic::<D>::from(Intrinsic::Ctz), [rs1])
1433+
.append();
1434+
}
1435+
}
1436+
Op::CpopW(i) => {
1437+
let rd = Register::from(i.rd());
1438+
let rs1 =
1439+
LiftableLowLevelILWithSize::lift_with_size(il, Register::from(i.rs1()), 4);
1440+
1441+
if i.rd().id() == 0 {
1442+
il.nop().append();
1443+
} else {
1444+
il.intrinsic([rd], RiscVIntrinsic::<D>::from(Intrinsic::Popcount), [rs1])
1445+
.append();
1446+
}
1447+
}
13141448

13151449
// r-type 32-bit
13161450
Op::AddW(r) => simple_r!(r, |rs1, rs2| il.sx(max_width, il.add(4, rs1, rs2))),

0 commit comments

Comments
 (0)