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