1use super::*;
4use crate::ir::condcodes::CondCode;
5
6use crate::isa::riscv64::lower::isle::generated_code::{
7 COpcodeSpace, CaOp, CbOp, CiOp, CiwOp, ClOp, CrOp, CsOp, CssOp, CsznOp, FpuOPWidth, ZcbMemOp,
8};
9use crate::machinst::isle::WritableReg;
10
11use core::fmt::Result;
12
13macro_rules! newtype_of_reg {
16 (
17 $newtype_reg:ident,
18 $newtype_writable_reg:ident,
19 |$check_reg:ident| $check:expr
20 ) => {
21 #[derive(Clone, Copy, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)]
23 pub struct $newtype_reg(Reg);
24
25 impl PartialEq<Reg> for $newtype_reg {
26 fn eq(&self, other: &Reg) -> bool {
27 self.0 == *other
28 }
29 }
30
31 impl From<$newtype_reg> for Reg {
32 fn from(r: $newtype_reg) -> Self {
33 r.0
34 }
35 }
36
37 impl $newtype_reg {
38 pub fn new($check_reg: Reg) -> Option<Self> {
41 if $check { Some(Self($check_reg)) } else { None }
42 }
43
44 pub fn to_reg(self) -> Reg {
46 self.0
47 }
48 }
49
50 impl core::ops::Deref for $newtype_reg {
57 type Target = Reg;
58
59 fn deref(&self) -> &Reg {
60 &self.0
61 }
62 }
63
64 pub type $newtype_writable_reg = Writable<$newtype_reg>;
66 };
67}
68
69newtype_of_reg!(XReg, WritableXReg, |reg| reg.class() == RegClass::Int);
71newtype_of_reg!(FReg, WritableFReg, |reg| reg.class() == RegClass::Float);
72newtype_of_reg!(VReg, WritableVReg, |reg| reg.class() == RegClass::Vector);
73
74#[derive(Clone, Debug, Copy)]
76pub enum AMode {
77 RegOffset(Reg, i64),
80 SPOffset(i64),
82
83 FPOffset(i64),
85
86 SlotOffset(i64),
97
98 IncomingArg(i64),
100
101 Const(VCodeConstant),
104
105 Label(MachLabel),
107}
108
109impl AMode {
110 pub(crate) fn get_operands(&mut self, collector: &mut impl OperandVisitor) {
112 match self {
113 AMode::RegOffset(reg, ..) => collector.reg_use(reg),
114 AMode::SPOffset(..)
116 | AMode::FPOffset(..)
117 | AMode::SlotOffset(..)
118 | AMode::IncomingArg(..)
119 | AMode::Const(..)
120 | AMode::Label(..) => {}
121 }
122 }
123
124 pub(crate) fn get_base_register(&self) -> Option<Reg> {
125 match self {
126 &AMode::RegOffset(reg, ..) => Some(reg),
127 &AMode::SPOffset(..) => Some(stack_reg()),
128 &AMode::FPOffset(..) => Some(fp_reg()),
129 &AMode::SlotOffset(..) => Some(stack_reg()),
130 &AMode::IncomingArg(..) => Some(stack_reg()),
131 &AMode::Const(..) | AMode::Label(..) => None,
132 }
133 }
134
135 pub(crate) fn get_offset_with_state(&self, state: &EmitState) -> i64 {
136 match self {
137 &AMode::SlotOffset(offset) => {
138 offset + i64::from(state.frame_layout().outgoing_args_size)
139 }
140
141 &AMode::IncomingArg(offset) => {
143 let frame_layout = state.frame_layout();
144 let sp_offset = frame_layout.tail_args_size
145 + frame_layout.setup_area_size
146 + frame_layout.clobber_size
147 + frame_layout.fixed_frame_storage_size
148 + frame_layout.outgoing_args_size;
149 i64::from(sp_offset) - offset
150 }
151
152 &AMode::RegOffset(_, offset) => offset,
153 &AMode::SPOffset(offset) => offset,
154 &AMode::FPOffset(offset) => offset,
155 &AMode::Const(_) | &AMode::Label(_) => 0,
156 }
157 }
158
159 pub(crate) fn get_label_with_sink(&self, sink: &mut MachBuffer<Inst>) -> Option<MachLabel> {
161 match self {
162 &AMode::Const(addr) => Some(sink.get_label_for_constant(addr)),
163 &AMode::Label(label) => Some(label),
164 &AMode::RegOffset(..)
165 | &AMode::SPOffset(..)
166 | &AMode::FPOffset(..)
167 | &AMode::IncomingArg(..)
168 | &AMode::SlotOffset(..) => None,
169 }
170 }
171}
172
173impl Display for AMode {
174 fn fmt(&self, f: &mut Formatter<'_>) -> Result {
175 match self {
176 &AMode::RegOffset(r, offset, ..) => {
177 write!(f, "{}({})", offset, reg_name(r))
178 }
179 &AMode::SPOffset(offset, ..) => {
180 write!(f, "{offset}(sp)")
181 }
182 &AMode::SlotOffset(offset, ..) => {
183 write!(f, "{offset}(slot)")
184 }
185 &AMode::IncomingArg(offset) => {
186 write!(f, "-{offset}(incoming_arg)")
187 }
188 &AMode::FPOffset(offset, ..) => {
189 write!(f, "{offset}(fp)")
190 }
191 &AMode::Const(addr, ..) => {
192 write!(f, "[const({})]", addr.as_u32())
193 }
194 &AMode::Label(label) => {
195 write!(f, "[label{}]", label.as_u32())
196 }
197 }
198 }
199}
200
201impl From<StackAMode> for AMode {
202 fn from(stack: StackAMode) -> AMode {
203 match stack {
204 StackAMode::IncomingArg(offset, stack_args_size) => {
205 AMode::IncomingArg(i64::from(stack_args_size) - offset)
206 }
207 StackAMode::OutgoingArg(offset) => AMode::SPOffset(offset),
208 StackAMode::Slot(offset) => AMode::SlotOffset(offset),
209 }
210 }
211}
212
213#[derive(Clone, Copy, Debug)]
215pub struct IntegerCompare {
216 pub(crate) kind: IntCC,
217 pub(crate) rs1: Reg,
218 pub(crate) rs2: Reg,
219}
220
221pub(crate) enum BranchFunct3 {
222 Eq,
224 Ne,
226 Lt,
228 Ge,
230 Ltu,
232 Geu,
234}
235
236impl BranchFunct3 {
237 pub(crate) fn funct3(self) -> u32 {
238 match self {
239 BranchFunct3::Eq => 0b000,
240 BranchFunct3::Ne => 0b001,
241 BranchFunct3::Lt => 0b100,
242 BranchFunct3::Ge => 0b101,
243 BranchFunct3::Ltu => 0b110,
244 BranchFunct3::Geu => 0b111,
245 }
246 }
247}
248
249impl IntegerCompare {
250 pub(crate) fn op_code(self) -> u32 {
251 0b1100011
252 }
253
254 pub(crate) fn funct3(&self) -> (BranchFunct3, bool) {
256 match self.kind {
257 IntCC::Equal => (BranchFunct3::Eq, false),
258 IntCC::NotEqual => (BranchFunct3::Ne, false),
259 IntCC::SignedLessThan => (BranchFunct3::Lt, false),
260 IntCC::SignedGreaterThanOrEqual => (BranchFunct3::Ge, false),
261
262 IntCC::SignedGreaterThan => (BranchFunct3::Lt, true),
263 IntCC::SignedLessThanOrEqual => (BranchFunct3::Ge, true),
264
265 IntCC::UnsignedLessThan => (BranchFunct3::Ltu, false),
266 IntCC::UnsignedGreaterThanOrEqual => (BranchFunct3::Geu, false),
267
268 IntCC::UnsignedGreaterThan => (BranchFunct3::Ltu, true),
269 IntCC::UnsignedLessThanOrEqual => (BranchFunct3::Geu, true),
270 }
271 }
272
273 #[inline]
274 pub(crate) fn op_name(&self) -> &'static str {
275 match self.kind {
276 IntCC::Equal => "beq",
277 IntCC::NotEqual => "bne",
278 IntCC::SignedLessThan => "blt",
279 IntCC::SignedGreaterThanOrEqual => "bge",
280 IntCC::SignedGreaterThan => "bgt",
281 IntCC::SignedLessThanOrEqual => "ble",
282 IntCC::UnsignedLessThan => "bltu",
283 IntCC::UnsignedGreaterThanOrEqual => "bgeu",
284 IntCC::UnsignedGreaterThan => "bgtu",
285 IntCC::UnsignedLessThanOrEqual => "bleu",
286 }
287 }
288
289 pub(crate) fn emit(self) -> u32 {
290 let (funct3, reverse) = self.funct3();
291 let (rs1, rs2) = if reverse {
292 (self.rs2, self.rs1)
293 } else {
294 (self.rs1, self.rs2)
295 };
296
297 self.op_code()
298 | funct3.funct3() << 12
299 | reg_to_gpr_num(rs1) << 15
300 | reg_to_gpr_num(rs2) << 20
301 }
302
303 pub(crate) fn inverse(self) -> Self {
304 Self {
305 kind: self.kind.complement(),
306 ..self
307 }
308 }
309
310 pub(crate) fn regs(&self) -> [Reg; 2] {
311 [self.rs1, self.rs2]
312 }
313}
314
315#[derive(Debug, Clone, Copy, PartialEq)]
316pub struct FliConstant(u8);
317
318impl FliConstant {
319 pub(crate) fn new(value: u8) -> Self {
320 debug_assert!(value <= 31, "Invalid FliConstant: {value}");
321 Self(value)
322 }
323
324 pub(crate) fn maybe_from_u64(ty: Type, imm: u64) -> Option<Self> {
325 let value = match ty {
328 F16 => {
329 match imm {
332 0x0400 => return Some(Self::new(1)),
334 0x0100 => return Some(Self::new(2)),
336 0x0200 => return Some(Self::new(3)),
338 0x7c00 => return Some(Self::new(30)),
340 0x7e00 => return Some(Self::new(31)),
342 _ => {
343 let exponent_bits = imm & 0x7c00;
344 if exponent_bits == 0 || exponent_bits == 0x7c00 {
345 return None;
347 }
348 let sign = (imm & 0x8000) << 48;
349 let exponent = (exponent_bits + ((1023 - 15) << 10)) << 42;
352 let significand = (imm & 0x3ff) << 42;
353 f64::from_bits(sign | exponent | significand)
354 }
355 }
356 }
357 F32 => f32::from_bits(imm as u32) as f64,
358 F64 => f64::from_bits(imm),
359 _ => unimplemented!(),
360 };
361
362 Some(match (ty, value) {
363 (_, f) if f == -1.0 => Self::new(0),
364
365 (F32, f) if f == (f32::MIN_POSITIVE as f64) => Self::new(1),
368 (F64, f) if f == f64::MIN_POSITIVE => Self::new(1),
369
370 (_, f) if f == libm::pow(2.0, -16.0) => Self::new(2),
371 (_, f) if f == libm::pow(2.0, -15.0) => Self::new(3),
372 (_, f) if f == libm::pow(2.0, -8.0) => Self::new(4),
373 (_, f) if f == libm::pow(2.0, -7.0) => Self::new(5),
374 (_, f) if f == 0.0625 => Self::new(6),
375 (_, f) if f == 0.125 => Self::new(7),
376 (_, f) if f == 0.25 => Self::new(8),
377 (_, f) if f == 0.3125 => Self::new(9),
378 (_, f) if f == 0.375 => Self::new(10),
379 (_, f) if f == 0.4375 => Self::new(11),
380 (_, f) if f == 0.5 => Self::new(12),
381 (_, f) if f == 0.625 => Self::new(13),
382 (_, f) if f == 0.75 => Self::new(14),
383 (_, f) if f == 0.875 => Self::new(15),
384 (_, f) if f == 1.0 => Self::new(16),
385 (_, f) if f == 1.25 => Self::new(17),
386 (_, f) if f == 1.5 => Self::new(18),
387 (_, f) if f == 1.75 => Self::new(19),
388 (_, f) if f == 2.0 => Self::new(20),
389 (_, f) if f == 2.5 => Self::new(21),
390 (_, f) if f == 3.0 => Self::new(22),
391 (_, f) if f == 4.0 => Self::new(23),
392 (_, f) if f == 8.0 => Self::new(24),
393 (_, f) if f == 16.0 => Self::new(25),
394 (_, f) if f == 128.0 => Self::new(26),
395 (_, f) if f == 256.0 => Self::new(27),
396 (_, f) if f == 32768.0 => Self::new(28),
397 (_, f) if f == 65536.0 => Self::new(29),
398 (_, f) if f == f64::INFINITY => Self::new(30),
399
400 (F32, f) if f.is_nan() && imm == 0x7fc0_0000 => Self::new(31), (F64, f) if f.is_nan() && imm == 0x7ff8_0000_0000_0000 => Self::new(31), _ => return None,
405 })
406 }
407
408 pub(crate) fn format(self) -> &'static str {
409 match self.0 {
413 0 => "-1.0",
414 1 => "min",
415 2 => "2^-16",
416 3 => "2^-15",
417 4 => "2^-8",
418 5 => "2^-7",
419 6 => "0.0625",
420 7 => "0.125",
421 8 => "0.25",
422 9 => "0.3125",
423 10 => "0.375",
424 11 => "0.4375",
425 12 => "0.5",
426 13 => "0.625",
427 14 => "0.75",
428 15 => "0.875",
429 16 => "1.0",
430 17 => "1.25",
431 18 => "1.5",
432 19 => "1.75",
433 20 => "2.0",
434 21 => "2.5",
435 22 => "3.0",
436 23 => "4.0",
437 24 => "8.0",
438 25 => "16.0",
439 26 => "128.0",
440 27 => "256.0",
441 28 => "32768.0",
442 29 => "65536.0",
443 30 => "inf",
444 31 => "nan",
445 _ => panic!("Invalid FliConstant"),
446 }
447 }
448
449 pub(crate) fn bits(self) -> u8 {
450 self.0
451 }
452}
453
454impl FpuOPRRRR {
455 pub(crate) fn op_name(self, width: FpuOPWidth) -> String {
456 match self {
457 Self::Fmadd => format!("fmadd.{width}"),
458 Self::Fmsub => format!("fmsub.{width}"),
459 Self::Fnmsub => format!("fnmsub.{width}"),
460 Self::Fnmadd => format!("fnmadd.{width}"),
461 }
462 }
463
464 pub(crate) fn opcode(self) -> u32 {
465 match self {
466 Self::Fmadd => 0b1000011,
467 Self::Fmsub => 0b1000111,
468 Self::Fnmsub => 0b1001011,
469 Self::Fnmadd => 0b1001111,
470 }
471 }
472}
473
474impl FpuOPRR {
475 pub(crate) fn op_name(self, width: FpuOPWidth) -> String {
476 let fmv_width = match width {
477 FpuOPWidth::H => "h",
478 FpuOPWidth::S => "w",
479 FpuOPWidth::D => "d",
480 FpuOPWidth::Q => "q",
481 };
482 match self {
483 Self::Fsqrt => format!("fsqrt.{width}"),
484 Self::Fround => format!("fround.{width}"),
485 Self::Fclass => format!("fclass.{width}"),
486 Self::FcvtWFmt => format!("fcvt.w.{width}"),
487 Self::FcvtWuFmt => format!("fcvt.wu.{width}"),
488 Self::FcvtLFmt => format!("fcvt.l.{width}"),
489 Self::FcvtLuFmt => format!("fcvt.lu.{width}"),
490 Self::FcvtFmtW => format!("fcvt.{width}.w"),
491 Self::FcvtFmtWu => format!("fcvt.{width}.wu"),
492 Self::FcvtFmtL => format!("fcvt.{width}.l"),
493 Self::FcvtFmtLu => format!("fcvt.{width}.lu"),
494
495 Self::FmvXFmt => format!("fmv.x.{fmv_width}"),
502 Self::FmvFmtX => format!("fmv.{fmv_width}.x"),
503
504 Self::FcvtSH => "fcvt.s.h".to_string(),
505 Self::FcvtHS => "fcvt.h.s".to_string(),
506 Self::FcvtSD => "fcvt.s.d".to_string(),
507 Self::FcvtDS => "fcvt.d.s".to_string(),
508 Self::FcvtDH => "fcvt.d.h".to_string(),
509 Self::FcvtHD => "fcvt.h.d".to_string(),
510 }
511 }
512
513 pub(crate) fn is_convert_to_int(self) -> bool {
514 match self {
515 Self::FcvtWFmt | Self::FcvtWuFmt | Self::FcvtLFmt | Self::FcvtLuFmt => true,
516 _ => false,
517 }
518 }
519
520 pub(crate) fn has_frm(self) -> bool {
521 match self {
522 FpuOPRR::FmvXFmt | FpuOPRR::FmvFmtX | FpuOPRR::Fclass => false,
523 _ => true,
524 }
525 }
526
527 pub(crate) fn opcode(self) -> u32 {
528 0b1010011
530 }
531
532 pub(crate) fn rs2(self) -> u32 {
533 match self {
534 Self::Fsqrt => 0b00000,
535 Self::Fround => 0b00100,
536 Self::Fclass => 0b00000,
537 Self::FcvtWFmt => 0b00000,
538 Self::FcvtWuFmt => 0b00001,
539 Self::FcvtLFmt => 0b00010,
540 Self::FcvtLuFmt => 0b00011,
541 Self::FcvtFmtW => 0b00000,
542 Self::FcvtFmtWu => 0b00001,
543 Self::FcvtFmtL => 0b00010,
544 Self::FcvtFmtLu => 0b00011,
545 Self::FmvXFmt => 0b00000,
546 Self::FmvFmtX => 0b00000,
547 Self::FcvtSH => 0b00010,
548 Self::FcvtHS => 0b00000,
549 Self::FcvtSD => 0b00001,
550 Self::FcvtDS => 0b00000,
551 Self::FcvtDH => 0b00010,
552 Self::FcvtHD => 0b00001,
553 }
554 }
555
556 pub(crate) fn funct5(self) -> u32 {
557 match self {
558 Self::Fsqrt => 0b01011,
559 Self::Fround => 0b01000,
560 Self::Fclass => 0b11100,
561 Self::FcvtWFmt => 0b11000,
562 Self::FcvtWuFmt => 0b11000,
563 Self::FcvtLFmt => 0b11000,
564 Self::FcvtLuFmt => 0b11000,
565 Self::FcvtFmtW => 0b11010,
566 Self::FcvtFmtWu => 0b11010,
567 Self::FcvtFmtL => 0b11010,
568 Self::FcvtFmtLu => 0b11010,
569 Self::FmvXFmt => 0b11100,
570 Self::FmvFmtX => 0b11110,
571 Self::FcvtSH
572 | Self::FcvtHS
573 | Self::FcvtSD
574 | Self::FcvtDS
575 | Self::FcvtDH
576 | Self::FcvtHD => 0b01000,
577 }
578 }
579
580 pub(crate) fn funct7(self, width: FpuOPWidth) -> u32 {
581 (self.funct5() << 2) | width.as_u32()
582 }
583}
584
585impl FpuOPRRR {
586 pub(crate) fn op_name(self, width: FpuOPWidth) -> String {
587 match self {
588 Self::Fadd => format!("fadd.{width}"),
589 Self::Fsub => format!("fsub.{width}"),
590 Self::Fmul => format!("fmul.{width}"),
591 Self::Fdiv => format!("fdiv.{width}"),
592 Self::Fsgnj => format!("fsgnj.{width}"),
593 Self::Fsgnjn => format!("fsgnjn.{width}"),
594 Self::Fsgnjx => format!("fsgnjx.{width}"),
595 Self::Fmin => format!("fmin.{width}"),
596 Self::Fmax => format!("fmax.{width}"),
597 Self::Feq => format!("feq.{width}"),
598 Self::Flt => format!("flt.{width}"),
599 Self::Fle => format!("fle.{width}"),
600 Self::Fminm => format!("fminm.{width}"),
601 Self::Fmaxm => format!("fmaxm.{width}"),
602 }
603 }
604
605 pub(crate) fn opcode(self) -> u32 {
606 0b1010011
608 }
609
610 pub(crate) const fn funct5(self) -> u32 {
611 match self {
612 Self::Fadd => 0b00000,
613 Self::Fsub => 0b00001,
614 Self::Fmul => 0b00010,
615 Self::Fdiv => 0b00011,
616 Self::Fsgnj => 0b00100,
617 Self::Fsgnjn => 0b00100,
618 Self::Fsgnjx => 0b00100,
619 Self::Fmin => 0b00101,
620 Self::Fmax => 0b00101,
621 Self::Feq => 0b10100,
622 Self::Flt => 0b10100,
623 Self::Fle => 0b10100,
624 Self::Fminm => 0b00101,
625 Self::Fmaxm => 0b00101,
626 }
627 }
628
629 pub(crate) fn funct7(self, width: FpuOPWidth) -> u32 {
630 (self.funct5() << 2) | width.as_u32()
631 }
632
633 pub(crate) fn has_frm(self) -> bool {
634 match self {
635 FpuOPRRR::Fsgnj
636 | FpuOPRRR::Fsgnjn
637 | FpuOPRRR::Fsgnjx
638 | FpuOPRRR::Fmin
639 | FpuOPRRR::Fmax
640 | FpuOPRRR::Feq
641 | FpuOPRRR::Flt
642 | FpuOPRRR::Fle => false,
643 _ => true,
644 }
645 }
646}
647
648impl Display for FpuOPWidth {
649 fn fmt(&self, f: &mut Formatter<'_>) -> Result {
650 write!(
651 f,
652 "{}",
653 match self {
654 FpuOPWidth::H => "h",
655 FpuOPWidth::S => "s",
656 FpuOPWidth::D => "d",
657 FpuOPWidth::Q => "q",
658 }
659 )
660 }
661}
662
663impl TryFrom<Type> for FpuOPWidth {
664 type Error = &'static str;
665
666 fn try_from(value: Type) -> core::result::Result<Self, Self::Error> {
667 match value {
668 F16 => Ok(FpuOPWidth::H),
669 F32 => Ok(FpuOPWidth::S),
670 F64 => Ok(FpuOPWidth::D),
671 F128 => Ok(FpuOPWidth::Q),
672 _ => Err("Invalid type for FpuOPWidth"),
673 }
674 }
675}
676
677impl FpuOPWidth {
678 pub(crate) fn as_u32(&self) -> u32 {
679 match self {
680 FpuOPWidth::S => 0b00,
681 FpuOPWidth::D => 0b01,
682 FpuOPWidth::H => 0b10,
683 FpuOPWidth::Q => 0b11,
684 }
685 }
686}
687
688impl AluOPRRR {
689 pub(crate) const fn op_name(self) -> &'static str {
690 match self {
691 Self::Add => "add",
692 Self::Sub => "sub",
693 Self::Sll => "sll",
694 Self::Slt => "slt",
695 Self::Sgt => "sgt",
696 Self::SltU => "sltu",
697 Self::Sgtu => "sgtu",
698 Self::Xor => "xor",
699 Self::Srl => "srl",
700 Self::Sra => "sra",
701 Self::Or => "or",
702 Self::And => "and",
703 Self::Addw => "addw",
704 Self::Subw => "subw",
705 Self::Sllw => "sllw",
706 Self::Srlw => "srlw",
707 Self::Sraw => "sraw",
708 Self::Mul => "mul",
709 Self::Mulh => "mulh",
710 Self::Mulhsu => "mulhsu",
711 Self::Mulhu => "mulhu",
712 Self::Div => "div",
713 Self::DivU => "divu",
714 Self::Rem => "rem",
715 Self::RemU => "remu",
716 Self::Mulw => "mulw",
717 Self::Divw => "divw",
718 Self::Divuw => "divuw",
719 Self::Remw => "remw",
720 Self::Remuw => "remuw",
721 Self::Adduw => "add.uw",
722 Self::Andn => "andn",
723 Self::Bclr => "bclr",
724 Self::Bext => "bext",
725 Self::Binv => "binv",
726 Self::Bset => "bset",
727 Self::Clmul => "clmul",
728 Self::Clmulh => "clmulh",
729 Self::Clmulr => "clmulr",
730 Self::Max => "max",
731 Self::Maxu => "maxu",
732 Self::Min => "min",
733 Self::Minu => "minu",
734 Self::Orn => "orn",
735 Self::Rol => "rol",
736 Self::Rolw => "rolw",
737 Self::Ror => "ror",
738 Self::Rorw => "rorw",
739 Self::Sh1add => "sh1add",
740 Self::Sh1adduw => "sh1add.uw",
741 Self::Sh2add => "sh2add",
742 Self::Sh2adduw => "sh2add.uw",
743 Self::Sh3add => "sh3add",
744 Self::Sh3adduw => "sh3add.uw",
745 Self::Xnor => "xnor",
746 Self::Pack => "pack",
747 Self::Packw => "packw",
748 Self::Packh => "packh",
749 Self::CzeroEqz => "czero.eqz",
750 Self::CzeroNez => "czero.nez",
751 }
752 }
753
754 pub fn funct3(self) -> u32 {
755 match self {
756 AluOPRRR::Add => 0b000,
757 AluOPRRR::Sll => 0b001,
758 AluOPRRR::Slt => 0b010,
759 AluOPRRR::Sgt => 0b010,
760 AluOPRRR::SltU => 0b011,
761 AluOPRRR::Sgtu => 0b011,
762 AluOPRRR::Xor => 0b100,
763 AluOPRRR::Srl => 0b101,
764 AluOPRRR::Sra => 0b101,
765 AluOPRRR::Or => 0b110,
766 AluOPRRR::And => 0b111,
767 AluOPRRR::Sub => 0b000,
768
769 AluOPRRR::Addw => 0b000,
770 AluOPRRR::Subw => 0b000,
771 AluOPRRR::Sllw => 0b001,
772 AluOPRRR::Srlw => 0b101,
773 AluOPRRR::Sraw => 0b101,
774
775 AluOPRRR::Mul => 0b000,
776 AluOPRRR::Mulh => 0b001,
777 AluOPRRR::Mulhsu => 0b010,
778 AluOPRRR::Mulhu => 0b011,
779 AluOPRRR::Div => 0b100,
780 AluOPRRR::DivU => 0b101,
781 AluOPRRR::Rem => 0b110,
782 AluOPRRR::RemU => 0b111,
783
784 AluOPRRR::Mulw => 0b000,
785 AluOPRRR::Divw => 0b100,
786 AluOPRRR::Divuw => 0b101,
787 AluOPRRR::Remw => 0b110,
788 AluOPRRR::Remuw => 0b111,
789
790 AluOPRRR::Adduw => 0b000,
792 AluOPRRR::Andn => 0b111,
793 AluOPRRR::Bclr => 0b001,
794 AluOPRRR::Bext => 0b101,
795 AluOPRRR::Binv => 0b001,
796 AluOPRRR::Bset => 0b001,
797 AluOPRRR::Clmul => 0b001,
798 AluOPRRR::Clmulh => 0b011,
799 AluOPRRR::Clmulr => 0b010,
800 AluOPRRR::Max => 0b110,
801 AluOPRRR::Maxu => 0b111,
802 AluOPRRR::Min => 0b100,
803 AluOPRRR::Minu => 0b101,
804 AluOPRRR::Orn => 0b110,
805 AluOPRRR::Rol => 0b001,
806 AluOPRRR::Rolw => 0b001,
807 AluOPRRR::Ror => 0b101,
808 AluOPRRR::Rorw => 0b101,
809 AluOPRRR::Sh1add => 0b010,
810 AluOPRRR::Sh1adduw => 0b010,
811 AluOPRRR::Sh2add => 0b100,
812 AluOPRRR::Sh2adduw => 0b100,
813 AluOPRRR::Sh3add => 0b110,
814 AluOPRRR::Sh3adduw => 0b110,
815 AluOPRRR::Xnor => 0b100,
816
817 AluOPRRR::Pack => 0b100,
819 AluOPRRR::Packw => 0b100,
820 AluOPRRR::Packh => 0b111,
821
822 AluOPRRR::CzeroEqz => 0b101,
824 AluOPRRR::CzeroNez => 0b111,
825 }
826 }
827
828 pub fn op_code(self) -> u32 {
829 match self {
830 AluOPRRR::Add
831 | AluOPRRR::Sub
832 | AluOPRRR::Sll
833 | AluOPRRR::Slt
834 | AluOPRRR::Sgt
835 | AluOPRRR::SltU
836 | AluOPRRR::Sgtu
837 | AluOPRRR::Xor
838 | AluOPRRR::Srl
839 | AluOPRRR::Sra
840 | AluOPRRR::Or
841 | AluOPRRR::And
842 | AluOPRRR::Pack
843 | AluOPRRR::Packh => 0b0110011,
844
845 AluOPRRR::Addw
846 | AluOPRRR::Subw
847 | AluOPRRR::Sllw
848 | AluOPRRR::Srlw
849 | AluOPRRR::Sraw
850 | AluOPRRR::Packw => 0b0111011,
851
852 AluOPRRR::Mul
853 | AluOPRRR::Mulh
854 | AluOPRRR::Mulhsu
855 | AluOPRRR::Mulhu
856 | AluOPRRR::Div
857 | AluOPRRR::DivU
858 | AluOPRRR::Rem
859 | AluOPRRR::RemU => 0b0110011,
860
861 AluOPRRR::Mulw
862 | AluOPRRR::Divw
863 | AluOPRRR::Divuw
864 | AluOPRRR::Remw
865 | AluOPRRR::Remuw => 0b0111011,
866
867 AluOPRRR::Adduw => 0b0111011,
868 AluOPRRR::Andn
869 | AluOPRRR::Bclr
870 | AluOPRRR::Bext
871 | AluOPRRR::Binv
872 | AluOPRRR::Bset
873 | AluOPRRR::Clmul
874 | AluOPRRR::Clmulh
875 | AluOPRRR::Clmulr
876 | AluOPRRR::Max
877 | AluOPRRR::Maxu
878 | AluOPRRR::Min
879 | AluOPRRR::Minu
880 | AluOPRRR::Orn
881 | AluOPRRR::Rol
882 | AluOPRRR::Ror
883 | AluOPRRR::Sh1add
884 | AluOPRRR::Sh2add
885 | AluOPRRR::Sh3add
886 | AluOPRRR::Xnor
887 | AluOPRRR::CzeroEqz
888 | AluOPRRR::CzeroNez => 0b0110011,
889
890 AluOPRRR::Rolw
891 | AluOPRRR::Rorw
892 | AluOPRRR::Sh2adduw
893 | AluOPRRR::Sh3adduw
894 | AluOPRRR::Sh1adduw => 0b0111011,
895 }
896 }
897
898 pub const fn funct7(self) -> u32 {
899 match self {
900 AluOPRRR::Add => 0b0000000,
901 AluOPRRR::Sub => 0b0100000,
902 AluOPRRR::Sll => 0b0000000,
903 AluOPRRR::Slt => 0b0000000,
904 AluOPRRR::Sgt => 0b0000000,
905 AluOPRRR::SltU => 0b0000000,
906 AluOPRRR::Sgtu => 0b0000000,
907
908 AluOPRRR::Xor => 0b0000000,
909 AluOPRRR::Srl => 0b0000000,
910 AluOPRRR::Sra => 0b0100000,
911 AluOPRRR::Or => 0b0000000,
912 AluOPRRR::And => 0b0000000,
913
914 AluOPRRR::Addw => 0b0000000,
915 AluOPRRR::Subw => 0b0100000,
916 AluOPRRR::Sllw => 0b0000000,
917 AluOPRRR::Srlw => 0b0000000,
918 AluOPRRR::Sraw => 0b0100000,
919
920 AluOPRRR::Mul => 0b0000001,
921 AluOPRRR::Mulh => 0b0000001,
922 AluOPRRR::Mulhsu => 0b0000001,
923 AluOPRRR::Mulhu => 0b0000001,
924 AluOPRRR::Div => 0b0000001,
925 AluOPRRR::DivU => 0b0000001,
926 AluOPRRR::Rem => 0b0000001,
927 AluOPRRR::RemU => 0b0000001,
928
929 AluOPRRR::Mulw => 0b0000001,
930 AluOPRRR::Divw => 0b0000001,
931 AluOPRRR::Divuw => 0b0000001,
932 AluOPRRR::Remw => 0b0000001,
933 AluOPRRR::Remuw => 0b0000001,
934 AluOPRRR::Adduw => 0b0000100,
935 AluOPRRR::Andn => 0b0100000,
936 AluOPRRR::Bclr => 0b0100100,
937 AluOPRRR::Bext => 0b0100100,
938 AluOPRRR::Binv => 0b0110100,
939 AluOPRRR::Bset => 0b0010100,
940 AluOPRRR::Clmul => 0b0000101,
941 AluOPRRR::Clmulh => 0b0000101,
942 AluOPRRR::Clmulr => 0b0000101,
943 AluOPRRR::Max => 0b0000101,
944 AluOPRRR::Maxu => 0b0000101,
945 AluOPRRR::Min => 0b0000101,
946 AluOPRRR::Minu => 0b0000101,
947 AluOPRRR::Orn => 0b0100000,
948 AluOPRRR::Rol => 0b0110000,
949 AluOPRRR::Rolw => 0b0110000,
950 AluOPRRR::Ror => 0b0110000,
951 AluOPRRR::Rorw => 0b0110000,
952 AluOPRRR::Sh1add => 0b0010000,
953 AluOPRRR::Sh1adduw => 0b0010000,
954 AluOPRRR::Sh2add => 0b0010000,
955 AluOPRRR::Sh2adduw => 0b0010000,
956 AluOPRRR::Sh3add => 0b0010000,
957 AluOPRRR::Sh3adduw => 0b0010000,
958 AluOPRRR::Xnor => 0b0100000,
959
960 AluOPRRR::Pack => 0b0000100,
962 AluOPRRR::Packw => 0b0000100,
963 AluOPRRR::Packh => 0b0000100,
964
965 AluOPRRR::CzeroEqz => 0b0000111,
967 AluOPRRR::CzeroNez => 0b0000111,
968 }
969 }
970
971 pub(crate) fn reverse_rs(self) -> bool {
972 self == AluOPRRR::Sgt || self == AluOPRRR::Sgtu
976 }
977}
978
979impl AluOPRRI {
980 pub(crate) fn option_funct6(self) -> Option<u32> {
981 let x: Option<u32> = match self {
982 Self::Slli => Some(0b00_0000),
983 Self::Srli => Some(0b00_0000),
984 Self::Srai => Some(0b01_0000),
985 Self::Bclri => Some(0b010010),
986 Self::Bexti => Some(0b010010),
987 Self::Binvi => Some(0b011010),
988 Self::Bseti => Some(0b001010),
989 Self::Rori => Some(0b011000),
990 Self::SlliUw => Some(0b000010),
991 _ => None,
992 };
993 x
994 }
995
996 pub(crate) fn option_funct7(self) -> Option<u32> {
997 let x = match self {
998 Self::Slliw => Some(0b000_0000),
999 Self::SrliW => Some(0b000_0000),
1000 Self::Sraiw => Some(0b010_0000),
1001 Self::Roriw => Some(0b0110000),
1002 _ => None,
1003 };
1004 x
1005 }
1006
1007 pub(crate) fn imm12(self, imm12: Imm12) -> u32 {
1008 let x = imm12.bits();
1009 if let Some(func) = self.option_funct6() {
1010 func << 6 | (x & 0b11_1111)
1011 } else if let Some(func) = self.option_funct7() {
1012 func << 5 | (x & 0b1_1111)
1013 } else if let Some(func) = self.option_funct12() {
1014 func
1015 } else {
1016 x
1017 }
1018 }
1019
1020 pub(crate) fn option_funct12(self) -> Option<u32> {
1021 match self {
1022 Self::Clz => Some(0b011000000000),
1023 Self::Clzw => Some(0b011000000000),
1024 Self::Cpop => Some(0b011000000010),
1025 Self::Cpopw => Some(0b011000000010),
1026 Self::Ctz => Some(0b011000000001),
1027 Self::Ctzw => Some(0b011000000001),
1028 Self::Rev8 => Some(0b011010111000),
1029 Self::Sextb => Some(0b011000000100),
1030 Self::Sexth => Some(0b011000000101),
1031 Self::Zexth => Some(0b000010000000),
1032 Self::Orcb => Some(0b001010000111),
1033 Self::Brev8 => Some(0b0110_1000_0111),
1034 _ => None,
1035 }
1036 }
1037
1038 pub(crate) fn op_name(self) -> &'static str {
1039 match self {
1040 Self::Addi => "addi",
1041 Self::Slti => "slti",
1042 Self::SltiU => "sltiu",
1043 Self::Xori => "xori",
1044 Self::Ori => "ori",
1045 Self::Andi => "andi",
1046 Self::Slli => "slli",
1047 Self::Srli => "srli",
1048 Self::Srai => "srai",
1049 Self::Addiw => "addiw",
1050 Self::Slliw => "slliw",
1051 Self::SrliW => "srliw",
1052 Self::Sraiw => "sraiw",
1053 Self::Bclri => "bclri",
1054 Self::Bexti => "bexti",
1055 Self::Binvi => "binvi",
1056 Self::Bseti => "bseti",
1057 Self::Rori => "rori",
1058 Self::Roriw => "roriw",
1059 Self::SlliUw => "slli.uw",
1060 Self::Clz => "clz",
1061 Self::Clzw => "clzw",
1062 Self::Cpop => "cpop",
1063 Self::Cpopw => "cpopw",
1064 Self::Ctz => "ctz",
1065 Self::Ctzw => "ctzw",
1066 Self::Rev8 => "rev8",
1067 Self::Sextb => "sext.b",
1068 Self::Sexth => "sext.h",
1069 Self::Zexth => "zext.h",
1070 Self::Orcb => "orc.b",
1071 Self::Brev8 => "brev8",
1072 }
1073 }
1074
1075 pub fn funct3(self) -> u32 {
1076 match self {
1077 AluOPRRI::Addi => 0b000,
1078 AluOPRRI::Slti => 0b010,
1079 AluOPRRI::SltiU => 0b011,
1080 AluOPRRI::Xori => 0b100,
1081 AluOPRRI::Ori => 0b110,
1082 AluOPRRI::Andi => 0b111,
1083 AluOPRRI::Slli => 0b001,
1084 AluOPRRI::Srli => 0b101,
1085 AluOPRRI::Srai => 0b101,
1086 AluOPRRI::Addiw => 0b000,
1087 AluOPRRI::Slliw => 0b001,
1088 AluOPRRI::SrliW => 0b101,
1089 AluOPRRI::Sraiw => 0b101,
1090 AluOPRRI::Bclri => 0b001,
1091 AluOPRRI::Bexti => 0b101,
1092 AluOPRRI::Binvi => 0b001,
1093 AluOPRRI::Bseti => 0b001,
1094 AluOPRRI::Rori => 0b101,
1095 AluOPRRI::Roriw => 0b101,
1096 AluOPRRI::SlliUw => 0b001,
1097 AluOPRRI::Clz => 0b001,
1098 AluOPRRI::Clzw => 0b001,
1099 AluOPRRI::Cpop => 0b001,
1100 AluOPRRI::Cpopw => 0b001,
1101 AluOPRRI::Ctz => 0b001,
1102 AluOPRRI::Ctzw => 0b001,
1103 AluOPRRI::Rev8 => 0b101,
1104 AluOPRRI::Sextb => 0b001,
1105 AluOPRRI::Sexth => 0b001,
1106 AluOPRRI::Zexth => 0b100,
1107 AluOPRRI::Orcb => 0b101,
1108 AluOPRRI::Brev8 => 0b101,
1109 }
1110 }
1111
1112 pub fn op_code(self) -> u32 {
1113 match self {
1114 AluOPRRI::Addi
1115 | AluOPRRI::Slti
1116 | AluOPRRI::SltiU
1117 | AluOPRRI::Xori
1118 | AluOPRRI::Ori
1119 | AluOPRRI::Andi
1120 | AluOPRRI::Slli
1121 | AluOPRRI::Srli
1122 | AluOPRRI::Srai
1123 | AluOPRRI::Bclri
1124 | AluOPRRI::Bexti
1125 | AluOPRRI::Binvi
1126 | AluOPRRI::Bseti
1127 | AluOPRRI::Rori
1128 | AluOPRRI::Clz
1129 | AluOPRRI::Cpop
1130 | AluOPRRI::Ctz
1131 | AluOPRRI::Rev8
1132 | AluOPRRI::Sextb
1133 | AluOPRRI::Sexth
1134 | AluOPRRI::Orcb
1135 | AluOPRRI::Brev8 => 0b0010011,
1136
1137 AluOPRRI::Addiw
1138 | AluOPRRI::Slliw
1139 | AluOPRRI::SrliW
1140 | AluOPRRI::Sraiw
1141 | AluOPRRI::Roriw
1142 | AluOPRRI::SlliUw
1143 | AluOPRRI::Clzw
1144 | AluOPRRI::Cpopw
1145 | AluOPRRI::Ctzw => 0b0011011,
1146 AluOPRRI::Zexth => 0b0111011,
1147 }
1148 }
1149}
1150
1151impl Default for FRM {
1152 fn default() -> Self {
1153 Self::Fcsr
1154 }
1155}
1156
1157impl FRM {
1159 pub(crate) fn to_static_str(self) -> &'static str {
1160 match self {
1161 FRM::RNE => "rne",
1162 FRM::RTZ => "rtz",
1163 FRM::RDN => "rdn",
1164 FRM::RUP => "rup",
1165 FRM::RMM => "rmm",
1166 FRM::Fcsr => "fcsr",
1167 }
1168 }
1169
1170 #[inline]
1171 pub(crate) fn bits(self) -> u8 {
1172 match self {
1173 FRM::RNE => 0b000,
1174 FRM::RTZ => 0b001,
1175 FRM::RDN => 0b010,
1176 FRM::RUP => 0b011,
1177 FRM::RMM => 0b100,
1178 FRM::Fcsr => 0b111,
1179 }
1180 }
1181 pub(crate) fn as_u32(self) -> u32 {
1182 self.bits() as u32
1183 }
1184}
1185
1186impl FFlagsException {
1187 #[inline]
1188 #[expect(dead_code, reason = "here for future use")]
1189 pub(crate) fn mask(self) -> u32 {
1190 match self {
1191 FFlagsException::NV => 1 << 4,
1192 FFlagsException::DZ => 1 << 3,
1193 FFlagsException::OF => 1 << 2,
1194 FFlagsException::UF => 1 << 1,
1195 FFlagsException::NX => 1 << 0,
1196 }
1197 }
1198}
1199
1200impl LoadOP {
1201 pub(crate) fn op_name(self) -> &'static str {
1202 match self {
1203 Self::Lb => "lb",
1204 Self::Lh => "lh",
1205 Self::Lw => "lw",
1206 Self::Lbu => "lbu",
1207 Self::Lhu => "lhu",
1208 Self::Lwu => "lwu",
1209 Self::Ld => "ld",
1210 Self::Flh => "flh",
1211 Self::Flw => "flw",
1212 Self::Fld => "fld",
1213 }
1214 }
1215
1216 pub(crate) fn from_type(ty: Type) -> Self {
1217 match ty {
1218 F16 => Self::Flh,
1219 F32 => Self::Flw,
1220 F64 => Self::Fld,
1221 I8 => Self::Lb,
1222 I16 => Self::Lh,
1223 I32 => Self::Lw,
1224 I64 => Self::Ld,
1225 _ => unreachable!(),
1226 }
1227 }
1228
1229 pub(crate) fn size(&self) -> i64 {
1230 match self {
1231 Self::Lb | Self::Lbu => 1,
1232 Self::Lh | Self::Lhu | Self::Flh => 2,
1233 Self::Lw | Self::Lwu | Self::Flw => 4,
1234 Self::Ld | Self::Fld => 8,
1235 }
1236 }
1237
1238 pub(crate) fn op_code(self) -> u32 {
1239 match self {
1240 Self::Lb | Self::Lh | Self::Lw | Self::Lbu | Self::Lhu | Self::Lwu | Self::Ld => {
1241 0b0000011
1242 }
1243 Self::Flh | Self::Flw | Self::Fld => 0b0000111,
1244 }
1245 }
1246 pub(crate) fn funct3(self) -> u32 {
1247 match self {
1248 Self::Lb => 0b000,
1249 Self::Lh => 0b001,
1250 Self::Lw => 0b010,
1251 Self::Lwu => 0b110,
1252 Self::Lbu => 0b100,
1253 Self::Lhu => 0b101,
1254 Self::Ld => 0b011,
1255 Self::Flh => 0b001,
1256 Self::Flw => 0b010,
1257 Self::Fld => 0b011,
1258 }
1259 }
1260}
1261
1262impl StoreOP {
1263 pub(crate) fn op_name(self) -> &'static str {
1264 match self {
1265 Self::Sb => "sb",
1266 Self::Sh => "sh",
1267 Self::Sw => "sw",
1268 Self::Sd => "sd",
1269 Self::Fsh => "fsh",
1270 Self::Fsw => "fsw",
1271 Self::Fsd => "fsd",
1272 }
1273 }
1274 pub(crate) fn from_type(ty: Type) -> Self {
1275 match ty {
1276 F16 => Self::Fsh,
1277 F32 => Self::Fsw,
1278 F64 => Self::Fsd,
1279 I8 => Self::Sb,
1280 I16 => Self::Sh,
1281 I32 => Self::Sw,
1282 I64 => Self::Sd,
1283 _ => unreachable!(),
1284 }
1285 }
1286
1287 pub(crate) fn size(&self) -> i64 {
1288 match self {
1289 Self::Sb => 1,
1290 Self::Sh | Self::Fsh => 2,
1291 Self::Sw | Self::Fsw => 4,
1292 Self::Sd | Self::Fsd => 8,
1293 }
1294 }
1295
1296 pub(crate) fn op_code(self) -> u32 {
1297 match self {
1298 Self::Sb | Self::Sh | Self::Sw | Self::Sd => 0b0100011,
1299 Self::Fsh | Self::Fsw | Self::Fsd => 0b0100111,
1300 }
1301 }
1302 pub(crate) fn funct3(self) -> u32 {
1303 match self {
1304 Self::Sb => 0b000,
1305 Self::Sh => 0b001,
1306 Self::Sw => 0b010,
1307 Self::Sd => 0b011,
1308 Self::Fsh => 0b001,
1309 Self::Fsw => 0b010,
1310 Self::Fsd => 0b011,
1311 }
1312 }
1313}
1314
1315impl FClassResult {
1316 pub(crate) const fn bit(self) -> u32 {
1317 match self {
1318 FClassResult::NegInfinite => 1 << 0,
1319 FClassResult::NegNormal => 1 << 1,
1320 FClassResult::NegSubNormal => 1 << 2,
1321 FClassResult::NegZero => 1 << 3,
1322 FClassResult::PosZero => 1 << 4,
1323 FClassResult::PosSubNormal => 1 << 5,
1324 FClassResult::PosNormal => 1 << 6,
1325 FClassResult::PosInfinite => 1 << 7,
1326 FClassResult::SNaN => 1 << 8,
1327 FClassResult::QNaN => 1 << 9,
1328 }
1329 }
1330
1331 #[inline]
1332 #[expect(dead_code, reason = "here for future use")]
1333 pub(crate) const fn is_nan_bits() -> u32 {
1334 Self::SNaN.bit() | Self::QNaN.bit()
1335 }
1336 #[inline]
1337 #[expect(dead_code, reason = "here for future use")]
1338 pub(crate) fn is_zero_bits() -> u32 {
1339 Self::NegZero.bit() | Self::PosZero.bit()
1340 }
1341
1342 #[inline]
1343 #[expect(dead_code, reason = "here for future use")]
1344 pub(crate) fn is_infinite_bits() -> u32 {
1345 Self::PosInfinite.bit() | Self::NegInfinite.bit()
1346 }
1347}
1348
1349impl AtomicOP {
1350 #[inline]
1351 pub(crate) fn is_load(self) -> bool {
1352 match self {
1353 Self::LrW | Self::LrD => true,
1354 _ => false,
1355 }
1356 }
1357
1358 #[inline]
1359 pub(crate) fn op_name(self, amo: AMO) -> String {
1360 let s = match self {
1361 Self::LrW => "lr.w",
1362 Self::ScW => "sc.w",
1363
1364 Self::AmoswapW => "amoswap.w",
1365 Self::AmoaddW => "amoadd.w",
1366 Self::AmoxorW => "amoxor.w",
1367 Self::AmoandW => "amoand.w",
1368 Self::AmoorW => "amoor.w",
1369 Self::AmominW => "amomin.w",
1370 Self::AmomaxW => "amomax.w",
1371 Self::AmominuW => "amominu.w",
1372 Self::AmomaxuW => "amomaxu.w",
1373 Self::LrD => "lr.d",
1374 Self::ScD => "sc.d",
1375 Self::AmoswapD => "amoswap.d",
1376 Self::AmoaddD => "amoadd.d",
1377 Self::AmoxorD => "amoxor.d",
1378 Self::AmoandD => "amoand.d",
1379 Self::AmoorD => "amoor.d",
1380 Self::AmominD => "amomin.d",
1381 Self::AmomaxD => "amomax.d",
1382 Self::AmominuD => "amominu.d",
1383 Self::AmomaxuD => "amomaxu.d",
1384 };
1385 format!("{}{}", s, amo.to_static_str())
1386 }
1387 #[inline]
1388 pub(crate) fn op_code(self) -> u32 {
1389 0b0101111
1390 }
1391
1392 #[inline]
1393 pub(crate) fn funct7(self, amo: AMO) -> u32 {
1394 self.funct5() << 2 | amo.as_u32() & 0b11
1395 }
1396
1397 pub(crate) fn funct3(self) -> u32 {
1398 match self {
1399 AtomicOP::LrW
1400 | AtomicOP::ScW
1401 | AtomicOP::AmoswapW
1402 | AtomicOP::AmoaddW
1403 | AtomicOP::AmoxorW
1404 | AtomicOP::AmoandW
1405 | AtomicOP::AmoorW
1406 | AtomicOP::AmominW
1407 | AtomicOP::AmomaxW
1408 | AtomicOP::AmominuW
1409 | AtomicOP::AmomaxuW => 0b010,
1410 AtomicOP::LrD
1411 | AtomicOP::ScD
1412 | AtomicOP::AmoswapD
1413 | AtomicOP::AmoaddD
1414 | AtomicOP::AmoxorD
1415 | AtomicOP::AmoandD
1416 | AtomicOP::AmoorD
1417 | AtomicOP::AmominD
1418 | AtomicOP::AmomaxD
1419 | AtomicOP::AmominuD
1420 | AtomicOP::AmomaxuD => 0b011,
1421 }
1422 }
1423 pub(crate) fn funct5(self) -> u32 {
1424 match self {
1425 AtomicOP::LrW => 0b00010,
1426 AtomicOP::ScW => 0b00011,
1427 AtomicOP::AmoswapW => 0b00001,
1428 AtomicOP::AmoaddW => 0b00000,
1429 AtomicOP::AmoxorW => 0b00100,
1430 AtomicOP::AmoandW => 0b01100,
1431 AtomicOP::AmoorW => 0b01000,
1432 AtomicOP::AmominW => 0b10000,
1433 AtomicOP::AmomaxW => 0b10100,
1434 AtomicOP::AmominuW => 0b11000,
1435 AtomicOP::AmomaxuW => 0b11100,
1436 AtomicOP::LrD => 0b00010,
1437 AtomicOP::ScD => 0b00011,
1438 AtomicOP::AmoswapD => 0b00001,
1439 AtomicOP::AmoaddD => 0b00000,
1440 AtomicOP::AmoxorD => 0b00100,
1441 AtomicOP::AmoandD => 0b01100,
1442 AtomicOP::AmoorD => 0b01000,
1443 AtomicOP::AmominD => 0b10000,
1444 AtomicOP::AmomaxD => 0b10100,
1445 AtomicOP::AmominuD => 0b11000,
1446 AtomicOP::AmomaxuD => 0b11100,
1447 }
1448 }
1449
1450 pub(crate) fn load_op(t: Type) -> Self {
1451 if t.bits() <= 32 { Self::LrW } else { Self::LrD }
1452 }
1453 pub(crate) fn store_op(t: Type) -> Self {
1454 if t.bits() <= 32 { Self::ScW } else { Self::ScD }
1455 }
1456
1457 pub(crate) fn extract(rd: WritableReg, offset: Reg, rs: Reg, ty: Type) -> SmallInstVec<Inst> {
1459 let mut insts = SmallInstVec::new();
1460 insts.push(Inst::AluRRR {
1461 alu_op: AluOPRRR::Srl,
1462 rd,
1463 rs1: rs,
1464 rs2: offset,
1465 });
1466 insts.push(Inst::Extend {
1468 rd,
1469 rn: rd.to_reg(),
1470 signed: false,
1471 from_bits: ty.bits() as u8,
1472 to_bits: 64,
1473 });
1474 insts
1475 }
1476
1477 pub(crate) fn extract_sext(
1480 rd: WritableReg,
1481 offset: Reg,
1482 rs: Reg,
1483 ty: Type,
1484 ) -> SmallInstVec<Inst> {
1485 let mut insts = SmallInstVec::new();
1486 insts.push(Inst::AluRRR {
1487 alu_op: AluOPRRR::Srl,
1488 rd,
1489 rs1: rs,
1490 rs2: offset,
1491 });
1492 insts.push(Inst::Extend {
1494 rd,
1495 rn: rd.to_reg(),
1496 signed: true,
1497 from_bits: ty.bits() as u8,
1498 to_bits: 64,
1499 });
1500 insts
1501 }
1502
1503 pub(crate) fn unset(
1504 rd: WritableReg,
1505 tmp: WritableReg,
1506 offset: Reg,
1507 ty: Type,
1508 ) -> SmallInstVec<Inst> {
1509 assert!(rd != tmp);
1510 let mut insts = SmallInstVec::new();
1511 insts.extend(Inst::load_int_mask(tmp, ty));
1512 insts.push(Inst::AluRRR {
1513 alu_op: AluOPRRR::Sll,
1514 rd: tmp,
1515 rs1: tmp.to_reg(),
1516 rs2: offset,
1517 });
1518 insts.push(Inst::construct_bit_not(tmp, tmp.to_reg()));
1519 insts.push(Inst::AluRRR {
1520 alu_op: AluOPRRR::And,
1521 rd,
1522 rs1: rd.to_reg(),
1523 rs2: tmp.to_reg(),
1524 });
1525 insts
1526 }
1527
1528 pub(crate) fn set(
1529 rd: WritableReg,
1530 tmp: WritableReg,
1531 offset: Reg,
1532 rs: Reg,
1533 ty: Type,
1534 ) -> SmallInstVec<Inst> {
1535 assert!(rd != tmp);
1536 let mut insts = SmallInstVec::new();
1537 insts.push(Inst::Extend {
1539 rd: tmp,
1540 rn: rs,
1541 signed: false,
1542 from_bits: ty.bits() as u8,
1543 to_bits: 64,
1544 });
1545 insts.push(Inst::AluRRR {
1546 alu_op: AluOPRRR::Sll,
1547 rd: tmp,
1548 rs1: tmp.to_reg(),
1549 rs2: offset,
1550 });
1551 insts.push(Inst::AluRRR {
1552 alu_op: AluOPRRR::Or,
1553 rd,
1554 rs1: rd.to_reg(),
1555 rs2: tmp.to_reg(),
1556 });
1557 insts
1558 }
1559
1560 pub(crate) fn merge(
1563 rd: WritableReg,
1564 tmp: WritableReg,
1565 offset: Reg,
1566 rs: Reg,
1567 ty: Type,
1568 ) -> SmallInstVec<Inst> {
1569 let mut insts = Self::unset(rd, tmp, offset, ty);
1570 insts.extend(Self::set(rd, tmp, offset, rs, ty));
1571 insts
1572 }
1573}
1574
1575#[derive(Copy, Clone, Debug)]
1577pub enum AMO {
1578 #[allow(dead_code, reason = "used only in emit tests for now")]
1579 Relax = 0b00,
1580 #[allow(dead_code, reason = "used only in emit tests for now")]
1581 Release = 0b01,
1582 #[allow(dead_code, reason = "used only in emit tests for now")]
1583 Acquire = 0b10,
1584 SeqCst = 0b11,
1585}
1586
1587impl AMO {
1588 pub(crate) fn to_static_str(self) -> &'static str {
1589 match self {
1590 AMO::Relax => "",
1591 AMO::Release => ".rl",
1592 AMO::Acquire => ".aq",
1593 AMO::SeqCst => ".aqrl",
1594 }
1595 }
1596 pub(crate) fn as_u32(self) -> u32 {
1597 self as u32
1598 }
1599}
1600
1601impl Inst {
1602 pub(crate) const FENCE_REQ_I: u8 = 1 << 3;
1604 pub(crate) const FENCE_REQ_O: u8 = 1 << 2;
1605 pub(crate) const FENCE_REQ_R: u8 = 1 << 1;
1606 pub(crate) const FENCE_REQ_W: u8 = 1 << 0;
1607 pub(crate) fn fence_req_to_string(x: u8) -> String {
1608 let mut s = String::default();
1609 if x & Self::FENCE_REQ_I != 0 {
1610 s.push_str("i");
1611 }
1612 if x & Self::FENCE_REQ_O != 0 {
1613 s.push_str("o");
1614 }
1615 if x & Self::FENCE_REQ_R != 0 {
1616 s.push_str("r");
1617 }
1618 if x & Self::FENCE_REQ_W != 0 {
1619 s.push_str("w");
1620 }
1621 s
1622 }
1623}
1624
1625impl CsrRegOP {
1626 pub(crate) fn funct3(self) -> u32 {
1627 match self {
1628 CsrRegOP::CsrRW => 0b001,
1629 CsrRegOP::CsrRS => 0b010,
1630 CsrRegOP::CsrRC => 0b011,
1631 }
1632 }
1633
1634 pub(crate) fn opcode(self) -> u32 {
1635 0b1110011
1636 }
1637
1638 pub(crate) fn name(self) -> &'static str {
1639 match self {
1640 CsrRegOP::CsrRW => "csrrw",
1641 CsrRegOP::CsrRS => "csrrs",
1642 CsrRegOP::CsrRC => "csrrc",
1643 }
1644 }
1645}
1646
1647impl Display for CsrRegOP {
1648 fn fmt(&self, f: &mut Formatter<'_>) -> Result {
1649 write!(f, "{}", self.name())
1650 }
1651}
1652
1653impl CsrImmOP {
1654 pub(crate) fn funct3(self) -> u32 {
1655 match self {
1656 CsrImmOP::CsrRWI => 0b101,
1657 CsrImmOP::CsrRSI => 0b110,
1658 CsrImmOP::CsrRCI => 0b111,
1659 }
1660 }
1661
1662 pub(crate) fn opcode(self) -> u32 {
1663 0b1110011
1664 }
1665
1666 pub(crate) fn name(self) -> &'static str {
1667 match self {
1668 CsrImmOP::CsrRWI => "csrrwi",
1669 CsrImmOP::CsrRSI => "csrrsi",
1670 CsrImmOP::CsrRCI => "csrrci",
1671 }
1672 }
1673}
1674
1675impl Display for CsrImmOP {
1676 fn fmt(&self, f: &mut Formatter<'_>) -> Result {
1677 write!(f, "{}", self.name())
1678 }
1679}
1680
1681impl CSR {
1682 pub(crate) fn bits(self) -> Imm12 {
1683 Imm12::from_i16(match self {
1684 CSR::Frm => 0x0002,
1685 })
1686 }
1687
1688 pub(crate) fn name(self) -> &'static str {
1689 match self {
1690 CSR::Frm => "frm",
1691 }
1692 }
1693}
1694
1695impl Display for CSR {
1696 fn fmt(&self, f: &mut Formatter<'_>) -> Result {
1697 write!(f, "{}", self.name())
1698 }
1699}
1700
1701impl COpcodeSpace {
1702 pub fn bits(&self) -> u32 {
1703 match self {
1704 COpcodeSpace::C0 => 0b00,
1705 COpcodeSpace::C1 => 0b01,
1706 COpcodeSpace::C2 => 0b10,
1707 }
1708 }
1709}
1710
1711impl CrOp {
1712 pub fn funct4(&self) -> u32 {
1713 match self {
1715 CrOp::CMv | CrOp::CJr => 0b1000,
1717 CrOp::CAdd | CrOp::CJalr | CrOp::CEbreak => 0b1001,
1718 }
1719 }
1720
1721 pub fn op(&self) -> COpcodeSpace {
1722 match self {
1724 CrOp::CMv | CrOp::CAdd | CrOp::CJr | CrOp::CJalr | CrOp::CEbreak => COpcodeSpace::C2,
1725 }
1726 }
1727}
1728
1729impl CaOp {
1730 pub fn funct2(&self) -> u32 {
1731 match self {
1733 CaOp::CAnd => 0b11,
1734 CaOp::COr => 0b10,
1735 CaOp::CXor => 0b01,
1736 CaOp::CSub => 0b00,
1737 CaOp::CAddw => 0b01,
1738 CaOp::CSubw => 0b00,
1739 CaOp::CMul => 0b10,
1740 }
1741 }
1742
1743 pub fn funct6(&self) -> u32 {
1744 match self {
1746 CaOp::CAnd | CaOp::COr | CaOp::CXor | CaOp::CSub => 0b100_011,
1747 CaOp::CSubw | CaOp::CAddw | CaOp::CMul => 0b100_111,
1748 }
1749 }
1750
1751 pub fn op(&self) -> COpcodeSpace {
1752 match self {
1754 CaOp::CAnd
1755 | CaOp::COr
1756 | CaOp::CXor
1757 | CaOp::CSub
1758 | CaOp::CAddw
1759 | CaOp::CSubw
1760 | CaOp::CMul => COpcodeSpace::C1,
1761 }
1762 }
1763}
1764
1765impl CjOp {
1766 pub fn funct3(&self) -> u32 {
1767 match self {
1769 CjOp::CJ => 0b101,
1770 }
1771 }
1772
1773 pub fn op(&self) -> COpcodeSpace {
1774 match self {
1776 CjOp::CJ => COpcodeSpace::C1,
1777 }
1778 }
1779}
1780
1781impl CiOp {
1782 pub fn funct3(&self) -> u32 {
1783 match self {
1785 CiOp::CAddi | CiOp::CSlli => 0b000,
1786 CiOp::CAddiw | CiOp::CFldsp => 0b001,
1787 CiOp::CLi | CiOp::CLwsp => 0b010,
1788 CiOp::CAddi16sp | CiOp::CLui | CiOp::CLdsp => 0b011,
1789 }
1790 }
1791
1792 pub fn op(&self) -> COpcodeSpace {
1793 match self {
1795 CiOp::CAddi | CiOp::CAddiw | CiOp::CAddi16sp | CiOp::CLi | CiOp::CLui => {
1796 COpcodeSpace::C1
1797 }
1798 CiOp::CSlli | CiOp::CLwsp | CiOp::CLdsp | CiOp::CFldsp => COpcodeSpace::C2,
1799 }
1800 }
1801}
1802
1803impl CiwOp {
1804 pub fn funct3(&self) -> u32 {
1805 match self {
1807 CiwOp::CAddi4spn => 0b000,
1808 }
1809 }
1810
1811 pub fn op(&self) -> COpcodeSpace {
1812 match self {
1814 CiwOp::CAddi4spn => COpcodeSpace::C0,
1815 }
1816 }
1817}
1818
1819impl CbOp {
1820 pub fn funct3(&self) -> u32 {
1821 match self {
1823 CbOp::CSrli | CbOp::CSrai | CbOp::CAndi => 0b100,
1824 }
1825 }
1826
1827 pub fn funct2(&self) -> u32 {
1828 match self {
1830 CbOp::CSrli => 0b00,
1831 CbOp::CSrai => 0b01,
1832 CbOp::CAndi => 0b10,
1833 }
1834 }
1835
1836 pub fn op(&self) -> COpcodeSpace {
1837 match self {
1839 CbOp::CSrli | CbOp::CSrai | CbOp::CAndi => COpcodeSpace::C1,
1840 }
1841 }
1842}
1843
1844impl CssOp {
1845 pub fn funct3(&self) -> u32 {
1846 match self {
1848 CssOp::CFsdsp => 0b101,
1849 CssOp::CSwsp => 0b110,
1850 CssOp::CSdsp => 0b111,
1851 }
1852 }
1853
1854 pub fn op(&self) -> COpcodeSpace {
1855 match self {
1857 CssOp::CSwsp | CssOp::CSdsp | CssOp::CFsdsp => COpcodeSpace::C2,
1858 }
1859 }
1860}
1861
1862impl CsOp {
1863 pub fn funct3(&self) -> u32 {
1864 match self {
1866 CsOp::CFsd => 0b101,
1867 CsOp::CSw => 0b110,
1868 CsOp::CSd => 0b111,
1869 }
1870 }
1871
1872 pub fn op(&self) -> COpcodeSpace {
1873 match self {
1875 CsOp::CSw | CsOp::CSd | CsOp::CFsd => COpcodeSpace::C0,
1876 }
1877 }
1878}
1879
1880impl ClOp {
1881 pub fn funct3(&self) -> u32 {
1882 match self {
1884 ClOp::CFld => 0b001,
1885 ClOp::CLw => 0b010,
1886 ClOp::CLd => 0b011,
1887 }
1888 }
1889
1890 pub fn op(&self) -> COpcodeSpace {
1891 match self {
1893 ClOp::CLw | ClOp::CLd | ClOp::CFld => COpcodeSpace::C0,
1894 }
1895 }
1896}
1897
1898impl CsznOp {
1899 pub fn funct6(&self) -> u32 {
1900 match self {
1902 CsznOp::CNot
1903 | CsznOp::CZextw
1904 | CsznOp::CZextb
1905 | CsznOp::CZexth
1906 | CsznOp::CSextb
1907 | CsznOp::CSexth => 0b100_111,
1908 }
1909 }
1910
1911 pub fn funct5(&self) -> u32 {
1912 match self {
1914 CsznOp::CNot => 0b11_101,
1915 CsznOp::CZextb => 0b11_000,
1916 CsznOp::CZexth => 0b11_010,
1917 CsznOp::CZextw => 0b11_100,
1918 CsznOp::CSextb => 0b11_001,
1919 CsznOp::CSexth => 0b11_011,
1920 }
1921 }
1922
1923 pub fn op(&self) -> COpcodeSpace {
1924 match self {
1926 CsznOp::CNot
1927 | CsznOp::CZextb
1928 | CsznOp::CZexth
1929 | CsznOp::CZextw
1930 | CsznOp::CSextb
1931 | CsznOp::CSexth => COpcodeSpace::C1,
1932 }
1933 }
1934}
1935
1936impl ZcbMemOp {
1937 pub fn funct6(&self) -> u32 {
1938 match self {
1940 ZcbMemOp::CLbu => 0b100_000,
1941 ZcbMemOp::CLhu | ZcbMemOp::CLh => 0b100_001,
1943 ZcbMemOp::CSb => 0b100_010,
1944 ZcbMemOp::CSh => 0b100_011,
1945 }
1946 }
1947
1948 pub fn imm_bits(&self) -> u8 {
1949 match self {
1950 ZcbMemOp::CLhu | ZcbMemOp::CLh | ZcbMemOp::CSh => 1,
1951 ZcbMemOp::CLbu | ZcbMemOp::CSb => 2,
1952 }
1953 }
1954
1955 pub fn op(&self) -> COpcodeSpace {
1956 match self {
1958 ZcbMemOp::CLbu | ZcbMemOp::CLhu | ZcbMemOp::CLh | ZcbMemOp::CSb | ZcbMemOp::CSh => {
1959 COpcodeSpace::C0
1960 }
1961 }
1962 }
1963}