cranelift_codegen/isa/riscv64/inst/
args.rs

1//! Riscv64 ISA definitions: instruction arguments.
2
3use 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
13/// A macro for defining a newtype of `Reg` that enforces some invariant about
14/// the wrapped `Reg` (such as that it is of a particular register class).
15macro_rules! newtype_of_reg {
16    (
17        $newtype_reg:ident,
18        $newtype_writable_reg:ident,
19        |$check_reg:ident| $check:expr
20    ) => {
21        /// A newtype wrapper around `Reg`.
22        #[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            /// Create this newtype from the given register, or return `None` if the register
39            /// is not a valid instance of this newtype.
40            pub fn new($check_reg: Reg) -> Option<Self> {
41                if $check {
42                    Some(Self($check_reg))
43                } else {
44                    None
45                }
46            }
47
48            /// Get this newtype's underlying `Reg`.
49            pub fn to_reg(self) -> Reg {
50                self.0
51            }
52        }
53
54        // Convenience impl so that people working with this newtype can use it
55        // "just like" a plain `Reg`.
56        //
57        // NB: We cannot implement `DerefMut` because that would let people do
58        // nasty stuff like `*my_xreg.deref_mut() = some_freg`, breaking the
59        // invariants that `XReg` provides.
60        impl std::ops::Deref for $newtype_reg {
61            type Target = Reg;
62
63            fn deref(&self) -> &Reg {
64                &self.0
65            }
66        }
67
68        /// Writable Reg.
69        pub type $newtype_writable_reg = Writable<$newtype_reg>;
70    };
71}
72
73// Newtypes for registers classes.
74newtype_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/// An addressing mode specified for a load/store operation.
79#[derive(Clone, Debug, Copy)]
80pub enum AMode {
81    /// Arbitrary offset from a register. Converted to generation of large
82    /// offsets with multiple instructions as necessary during code emission.
83    RegOffset(Reg, i64),
84    /// Offset from the stack pointer.
85    SPOffset(i64),
86
87    /// Offset from the frame pointer.
88    FPOffset(i64),
89
90    /// Offset into the slot area of the stack, which lies just above the
91    /// outgoing argument area that's setup by the function prologue.
92    /// At emission time, this is converted to `SPOffset` with a fixup added to
93    /// the offset constant. The fixup is a running value that is tracked as
94    /// emission iterates through instructions in linear order, and can be
95    /// adjusted up and down with [Inst::VirtualSPOffsetAdj].
96    ///
97    /// The standard ABI is in charge of handling this (by emitting the
98    /// adjustment meta-instructions). See the diagram in the documentation
99    /// for [crate::isa::aarch64::abi](the ABI module) for more details.
100    SlotOffset(i64),
101
102    /// Offset into the argument area.
103    IncomingArg(i64),
104
105    /// A reference to a constant which is placed outside of the function's
106    /// body, typically at the end.
107    Const(VCodeConstant),
108
109    /// A reference to a label.
110    Label(MachLabel),
111}
112
113impl AMode {
114    /// Add the registers referenced by this AMode to `collector`.
115    pub(crate) fn get_operands(&mut self, collector: &mut impl OperandVisitor) {
116        match self {
117            AMode::RegOffset(reg, ..) => collector.reg_use(reg),
118            // Registers used in these modes aren't allocatable.
119            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            // Compute the offset into the incoming argument area relative to SP
146            &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    /// Retrieve a MachLabel that corresponds to this addressing mode, if it exists.
164    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/// risc-v always take two register to compare
218#[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    // ==
227    Eq,
228    // !=
229    Ne,
230    // signed <
231    Lt,
232    // signed >=
233    Ge,
234    // unsigned <
235    Ltu,
236    // unsigned >=
237    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    // funct3 and if need inverse the register
259    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        // Convert the value into an F64, this allows us to represent
330        // values from both f32 and f64 in the same value.
331        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            // Since f64 can represent all f32 values, f32::min_positive won't be
341            // the same as f64::min_positive, so we need to check for both indepenendtly
342            (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            // NaN's are not guaranteed to preserve the sign / payload bits, so we need to check
376            // the original bits directly.
377            (F32, f) if f.is_nan() && imm == 0x7fc0_0000 => Self::new(31), // Canonical NaN
378            (F64, f) if f.is_nan() && imm == 0x7ff8_0000_0000_0000 => Self::new(31), // Canonical NaN
379            _ => return None,
380        })
381    }
382
383    pub(crate) fn format(self) -> &'static str {
384        // The preferred assembly syntax for entries 1, 30, and 31 is min, inf, and nan, respectively.
385        // For entries 0 through 29 (including entry 1), the assembler will accept decimal constants
386        // in C-like syntax.
387        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            // fmv instructions deviate from the normal encoding and instead
471            // encode the width as "w" instead of "s". The ISA manual gives this rationale:
472            //
473            // Instructions FMV.S.X and FMV.X.S were renamed to FMV.W.X and FMV.X.W respectively
474            // to be more consistent with their semantics, which did not change. The old names will continue
475            // to be supported in the tools.
476            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        // OP-FP Major opcode
500        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        // OP-FP Major opcode
570        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            // Zbb
754            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            // Zbkb
781            AluOPRRR::Pack => 0b100,
782            AluOPRRR::Packw => 0b100,
783            AluOPRRR::Packh => 0b111,
784
785            // ZiCond
786            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            // Zbkb
924            AluOPRRR::Pack => 0b0000100,
925            AluOPRRR::Packw => 0b0000100,
926            AluOPRRR::Packh => 0b0000100,
927
928            // ZiCond
929            AluOPRRR::CzeroEqz => 0b0000111,
930            AluOPRRR::CzeroNez => 0b0000111,
931        }
932    }
933
934    pub(crate) fn reverse_rs(self) -> bool {
935        // special case.
936        // sgt and sgtu is not defined in isa.
937        // emit should reverse rs1 and rs2.
938        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
1120/// float rounding mode.
1121impl 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    /// extract
1427    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        //
1436        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    /// like extract but sign extend the value.
1447    /// suitable for smax,etc.
1448    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        //
1462        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        // make rs into tmp.
1507        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    /// Merge reset part of rs into rd.
1530    /// Call this function must make sure that other part of value is already in rd.
1531    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///Atomic Memory ordering.
1545#[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    /// fence request bits.
1569    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        // https://five-embeddev.com/riscv-isa-manual/latest/rvc-opcode-map.html#rvcopcodemap
1708        match self {
1709            // `c.jr` has the same op/funct4 as C.MV, but RS2 is 0, which is illegal for mv.
1710            CrOp::CMv | CrOp::CJr => 0b1000,
1711            CrOp::CAdd | CrOp::CJalr | CrOp::CEbreak => 0b1001,
1712        }
1713    }
1714
1715    pub fn op(&self) -> COpcodeSpace {
1716        // https://five-embeddev.com/riscv-isa-manual/latest/rvc-opcode-map.html#rvcopcodemap
1717        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        // https://github.com/michaeljclark/riscv-meta/blob/master/opcodes
1726        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        // https://github.com/michaeljclark/riscv-meta/blob/master/opcodes
1739        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        // https://five-embeddev.com/riscv-isa-manual/latest/rvc-opcode-map.html#rvcopcodemap
1747        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        // https://github.com/michaeljclark/riscv-meta/blob/master/opcodes
1762        match self {
1763            CjOp::CJ => 0b101,
1764        }
1765    }
1766
1767    pub fn op(&self) -> COpcodeSpace {
1768        // https://five-embeddev.com/riscv-isa-manual/latest/rvc-opcode-map.html#rvcopcodemap
1769        match self {
1770            CjOp::CJ => COpcodeSpace::C1,
1771        }
1772    }
1773}
1774
1775impl CiOp {
1776    pub fn funct3(&self) -> u32 {
1777        // https://github.com/michaeljclark/riscv-meta/blob/master/opcodes
1778        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        // https://five-embeddev.com/riscv-isa-manual/latest/rvc-opcode-map.html#rvcopcodemap
1788        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        // https://github.com/michaeljclark/riscv-meta/blob/master/opcodes
1800        match self {
1801            CiwOp::CAddi4spn => 0b000,
1802        }
1803    }
1804
1805    pub fn op(&self) -> COpcodeSpace {
1806        // https://five-embeddev.com/riscv-isa-manual/latest/rvc-opcode-map.html#rvcopcodemap
1807        match self {
1808            CiwOp::CAddi4spn => COpcodeSpace::C0,
1809        }
1810    }
1811}
1812
1813impl CbOp {
1814    pub fn funct3(&self) -> u32 {
1815        // https://github.com/michaeljclark/riscv-meta/blob/master/opcodes
1816        match self {
1817            CbOp::CSrli | CbOp::CSrai | CbOp::CAndi => 0b100,
1818        }
1819    }
1820
1821    pub fn funct2(&self) -> u32 {
1822        // https://github.com/michaeljclark/riscv-meta/blob/master/opcodes
1823        match self {
1824            CbOp::CSrli => 0b00,
1825            CbOp::CSrai => 0b01,
1826            CbOp::CAndi => 0b10,
1827        }
1828    }
1829
1830    pub fn op(&self) -> COpcodeSpace {
1831        // https://five-embeddev.com/riscv-isa-manual/latest/rvc-opcode-map.html#rvcopcodemap
1832        match self {
1833            CbOp::CSrli | CbOp::CSrai | CbOp::CAndi => COpcodeSpace::C1,
1834        }
1835    }
1836}
1837
1838impl CssOp {
1839    pub fn funct3(&self) -> u32 {
1840        // https://github.com/michaeljclark/riscv-meta/blob/master/opcodes
1841        match self {
1842            CssOp::CFsdsp => 0b101,
1843            CssOp::CSwsp => 0b110,
1844            CssOp::CSdsp => 0b111,
1845        }
1846    }
1847
1848    pub fn op(&self) -> COpcodeSpace {
1849        // https://five-embeddev.com/riscv-isa-manual/latest/rvc-opcode-map.html#rvcopcodemap
1850        match self {
1851            CssOp::CSwsp | CssOp::CSdsp | CssOp::CFsdsp => COpcodeSpace::C2,
1852        }
1853    }
1854}
1855
1856impl CsOp {
1857    pub fn funct3(&self) -> u32 {
1858        // https://github.com/michaeljclark/riscv-meta/blob/master/opcodes
1859        match self {
1860            CsOp::CFsd => 0b101,
1861            CsOp::CSw => 0b110,
1862            CsOp::CSd => 0b111,
1863        }
1864    }
1865
1866    pub fn op(&self) -> COpcodeSpace {
1867        // https://five-embeddev.com/riscv-isa-manual/latest/rvc-opcode-map.html#rvcopcodemap
1868        match self {
1869            CsOp::CSw | CsOp::CSd | CsOp::CFsd => COpcodeSpace::C0,
1870        }
1871    }
1872}
1873
1874impl ClOp {
1875    pub fn funct3(&self) -> u32 {
1876        // https://github.com/michaeljclark/riscv-meta/blob/master/opcodes
1877        match self {
1878            ClOp::CFld => 0b001,
1879            ClOp::CLw => 0b010,
1880            ClOp::CLd => 0b011,
1881        }
1882    }
1883
1884    pub fn op(&self) -> COpcodeSpace {
1885        // https://five-embeddev.com/riscv-isa-manual/latest/rvc-opcode-map.html#rvcopcodemap
1886        match self {
1887            ClOp::CLw | ClOp::CLd | ClOp::CFld => COpcodeSpace::C0,
1888        }
1889    }
1890}
1891
1892impl CsznOp {
1893    pub fn funct6(&self) -> u32 {
1894        // https://github.com/michaeljclark/riscv-meta/blob/master/opcodes
1895        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        // https://github.com/michaeljclark/riscv-meta/blob/master/opcodes
1907        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        // https://five-embeddev.com/riscv-isa-manual/latest/rvc-opcode-map.html#rvcopcodemap
1919        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        // https://github.com/michaeljclark/riscv-meta/blob/master/opcodes
1933        match self {
1934            ZcbMemOp::CLbu => 0b100_000,
1935            // These two opcodes are differentiated in the imm field of the instruction.
1936            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        // https://five-embeddev.com/riscv-isa-manual/latest/rvc-opcode-map.html#rvcopcodemap
1951        match self {
1952            ZcbMemOp::CLbu | ZcbMemOp::CLhu | ZcbMemOp::CLh | ZcbMemOp::CSb | ZcbMemOp::CSh => {
1953                COpcodeSpace::C0
1954            }
1955        }
1956    }
1957}