1use alloc::{
2 format,
3 string::{String, ToString},
4};
5use core::convert::{From, TryFrom};
6use core::fmt;
7use core::str::FromStr;
8use strum_macros::{Display, EnumString};
9
10#[derive(Debug)]
11pub enum RegParseError {
12 RegParseError(String),
13}
14
15#[derive(Debug, PartialEq, Eq)]
16pub struct Target(pub u32);
17
18#[derive(Debug, PartialEq, Eq)]
19pub struct Immediate(pub u16);
20
21struct Signed(u16);
22impl fmt::LowerHex for Signed {
25 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
26 let val = self.0 as i16;
27 let p = if f.alternate() { "0x" } else { "" };
28 let x = format!("{:x}", val.abs());
29 f.pad_integral(val >= 0, p, &x)
30 }
31}
32
33#[derive(PartialEq, Eq)]
34pub enum Instruction {
35 Immediate {
36 op: ITypeOp,
37 rs: Register,
38 rt: Register,
39 imm: Immediate,
40 },
41 Jump {
42 op: JTypeOp,
43 target: Target,
44 },
45 Register {
46 op: RTypeOp,
47 rs: Register,
48 rt: Register,
49 rd: Register,
50 sa: u32,
51 },
52}
53
54type I = ITypeOp;
55type R = RTypeOp;
56
57impl fmt::Display for Instruction {
58 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
59 match &self {
60 Instruction::Immediate {
61 op,
62 rs,
63 rt,
64 imm: Immediate(imm),
65 } => match op {
66 I::Lb
67 | I::Lbu
68 | I::Ld
69 | I::Ldl
70 | I::Ldr
71 | I::Lh
72 | I::Lhu
73 | I::Ll
74 | I::Lld
75 | I::Lw
76 | I::Lwl
77 | I::Lwr
78 | I::Lwu
79 | I::Sb
80 | I::Sc
81 | I::Scd
82 | I::Sd
83 | I::Sdl
84 | I::Sdr
85 | I::Sh
86 | I::Sw
87 | I::Swl
88 | I::Swr => {
89 write!(f, "{:7} {}, {:#x}({})", op, rt, Signed(*imm), rs)
90 }
91 I::Lbv => {
92 write!(
93 f,
94 "{:7} {}[{}], {:#x}({})",
95 op,
96 rt,
97 *imm >> 7,
98 *imm & 0b1111111,
99 rs
100 )
101 }
102 I::Cache => {
103 write!(
104 f,
105 "{:7} {:#x}, {:#x}({})",
106 op,
107 rt.as_num(),
108 Signed(*imm),
109 rs
110 )
111 }
112 I::Addi | I::Addiu | I::Daddi | I::Daddiu | I::Slti | I::Sltiu => {
113 write!(f, "{:7} {}, {}, {:#x}", op, rt, rs, Signed(*imm))
114 }
115 I::Andi | I::Ori | I::Xori => write!(f, "{:7} {}, {}, {:#x}", op, rt, rs, imm),
116 I::Lui => write!(f, "{:7} {}, {:#x}", op, rt, imm),
117 I::Beqz | I::Bgtz | I::Bgtzl | I::Blez | I::Blezl | I::Bnez => {
118 write!(f, "{:7} {}, {:#x}", op, rs, Signed(*imm))
119 }
120 I::Beq | I::Beql | I::Bne | I::Bnel => {
121 write!(f, "{:7} {}, {}, {:#x}", op, rs, rt, Signed(*imm))
122 }
123 I::Bgez
124 | I::Bgezal
125 | I::Bgezall
126 | I::Bgezl
127 | I::Bltz
128 | I::Bltzal
129 | I::Bltzall
130 | I::Bltzl
131 | I::Teqi
132 | I::Tgei
133 | I::Tgeiu
134 | I::Tlti
135 | I::Tltiu
136 | I::Tnei => {
137 write!(f, "{:7} {}, {:#x}", op, rs, Signed(*imm))
138 }
139 I::Bc0f
140 | I::Bc1f
141 | I::Bc0fl
142 | I::Bc1fl
143 | I::Bc0t
144 | I::Bc1t
145 | I::Bc0tl
146 | I::Bc1tl => {
147 write!(f, "{:7}{:#x}", op, Signed(*imm))
148 }
149 I::Ldc1 | I::Lwc1 | I::Sdc1 | I::Swc1 => {
150 write!(
151 f,
152 "{:7} {}, {:#x}({})",
153 op,
154 FloatRegister::from(*rt),
155 Signed(*imm),
156 rs
157 )
158 }
159 e => panic!("Unhandled immediate instruction: {:?}", e),
160 },
161 Instruction::Jump {
162 op,
163 target: Target(target),
164 } => {
165 write!(f, "{:7}{:#X?}", op, target)
166 }
167 Instruction::Register { op, rs, rt, rd, sa } => match op {
168 R::Sync => write!(f, "{}", op),
169 R::Add
170 | R::Addu
171 | R::And
172 | R::Dadd
173 | R::Daddu
174 | R::Dsub
175 | R::Dsubu
176 | R::Nor
177 | R::Or
178 | R::Slt
179 | R::Sltu
180 | R::Sub
181 | R::Subu
182 | R::Xor => {
183 write!(f, "{:7} {}, {}, {}", op, rd, rs, rt)
184 }
185 R::Dsll
186 | R::Dsll32
187 | R::Dsra
188 | R::Dsra32
189 | R::Dsrl
190 | R::Dsrl32
191 | R::Sll
192 | R::Sra
193 | R::Srl => {
194 write!(f, "{:7} {}, {}, {:#x?}", op, rd, rt, sa)
195 }
196 R::Dsllv | R::Dsrav | R::Dsrlv | R::Sllv | R::Srav | R::Srlv => {
197 write!(f, "{:7} {}, {}, {}", op, rd, rt, rs)
198 }
199 R::Break | R::Syscall => {
200 if *sa == 0 {
201 write!(f, "{}", op)
202 } else {
203 write!(f, "{:7} {:#x?}", op, sa)
204 }
205 }
206 R::Ddiv
207 | R::Ddivu
208 | R::Div
209 | R::Divu
210 | R::Dmult
211 | R::Dmultu
212 | R::Mult
213 | R::Multu
214 | R::Teq
215 | R::Tge
216 | R::Tgeu
217 | R::Tlt
218 | R::Tltu
219 | R::Tne => {
220 write!(f, "{:7} {}, {}", op, rs, rt)
221 }
222 R::Jalr => {
223 if let &Register::Ra = rd {
224 write!(f, "{:7} {}", op, rs)
225 } else {
226 write!(f, "{:7} {}, {}", op, rd, rs)
227 }
228 }
229 R::Jr | R::Mthi | R::Mtlo => {
230 write!(f, "{:7} {}", op, rs)
231 }
232 R::Mfhi | R::Mflo => {
233 write!(f, "{:7} {}", op, rd)
234 }
235 R::Cfc0 | R::Ctc0 | R::Dmfc0 | R::Dmtc0 | R::Mfc0 | R::Mtc0 => {
236 write!(f, "{:7} {}, {}", op, rt, Cop0Register::from(*rd))
237 }
238 R::Cfc1 | R::Ctc1 | R::Dmfc1 | R::Dmtc1 | R::Mfc1 | R::Mtc1 => {
239 write!(f, "{:7} {}, {}", op, rt, FloatRegister::from(*rd))
240 }
241 R::Eret | R::Tlbp | R::Tlbr | R::Tlbwi | R::Tlbwr => {
242 write!(f, "{}", op)
243 }
244 R::AddS | R::AddD | R::SubS | R::SubD | R::MulS | R::MulD | R::DivS | R::DivD => {
245 let x = op.to_string().replace('_', ".");
246 write!(
247 f,
248 "{:7} {}, {}, {}",
249 x,
250 FloatRegister::from(*rd),
251 FloatRegister::from(*rs),
252 FloatRegister::from(*rt)
253 )
254 }
255 R::AbsS
256 | R::AbsD
257 | R::CvtDS
258 | R::CvtDW
259 | R::CvtDL
260 | R::CvtLS
261 | R::CvtLD
262 | R::CvtSD
263 | R::CvtSW
264 | R::CvtSL
265 | R::CvtWD
266 | R::CvtWS
267 | R::MovS
268 | R::MovD
269 | R::NegS
270 | R::NegD
271 | R::SqrtS
272 | R::SqrtD => {
273 let x = op.to_string().replace('_', ".");
274 write!(
275 f,
276 "{:7} {}, {}",
277 x,
278 FloatRegister::from(*rd),
279 FloatRegister::from(*rs)
280 )
281 }
282 R::CeilLS | R::CeilLD | R::CeilWS | R::CeilWD => {
283 let x = op.to_string().replace('_', ".");
284 write!(
285 f,
286 "{} {}, {}",
287 x,
288 FloatRegister::from(*rd),
289 FloatRegister::from(*rs)
290 )
291 }
292 R::FloorLS
293 | R::FloorLD
294 | R::FloorWS
295 | R::FloorWD
296 | R::RoundLS
297 | R::RoundLD
298 | R::RoundWS
299 | R::RoundWD
300 | R::TruncLS
301 | R::TruncLD
302 | R::TruncWS
303 | R::TruncWD => {
304 let x = op.to_string().replace('_', ".");
305 write!(
306 f,
307 "{} {}, {}",
308 x,
309 FloatRegister::from(*rd),
310 FloatRegister::from(*rs)
311 )
312 }
313 R::Cs => {
314 write!(
315 f,
316 "c.{}.s {}, {}",
317 FloatCond::try_from(*sa).unwrap(),
318 FloatRegister::from(*rs),
319 FloatRegister::from(*rt)
320 )
321 }
322 R::Cd => {
323 write!(
324 f,
325 "c.{}.d {}, {}",
326 FloatCond::try_from(*sa).unwrap(),
327 FloatRegister::from(*rs),
328 FloatRegister::from(*rt)
329 )
330 }
331 e => panic!("{:?} not implemented", e),
332 },
333 }
334 }
335}
336
337#[derive(Clone, Copy, Debug, Display, PartialEq, Eq)]
338#[strum(serialize_all = "snake_case")]
339pub enum Register {
340 Zero,
341 At,
342 V0,
343 V1,
344 A0,
345 A1,
346 A2,
347 A3,
348 T0,
349 T1,
350 T2,
351 T3,
352 T4,
353 T5,
354 T6,
355 T7,
356 S0,
357 S1,
358 S2,
359 S3,
360 S4,
361 S5,
362 S6,
363 S7,
364 T8,
365 T9,
366 K0,
367 K1,
368 Gp,
369 Sp,
370 Fp,
371 Ra,
372}
373
374impl Register {
375 pub fn null() -> Self {
376 Register::Zero
377 }
378
379 pub fn as_num(&self) -> u32 {
380 *self as u32
381 }
382}
383
384impl TryFrom<u32> for Register {
385 type Error = RegParseError;
386
387 fn try_from(reg: u32) -> Result<Self, Self::Error> {
388 match reg {
389 0 => Ok(Register::Zero),
390 1 => Ok(Register::At),
391 2 => Ok(Register::V0),
392 3 => Ok(Register::V1),
393 4 => Ok(Register::A0),
394 5 => Ok(Register::A1),
395 6 => Ok(Register::A2),
396 7 => Ok(Register::A3),
397 8 => Ok(Register::T0),
398 9 => Ok(Register::T1),
399 10 => Ok(Register::T2),
400 11 => Ok(Register::T3),
401 12 => Ok(Register::T4),
402 13 => Ok(Register::T5),
403 14 => Ok(Register::T6),
404 15 => Ok(Register::T7),
405 16 => Ok(Register::S0),
406 17 => Ok(Register::S1),
407 18 => Ok(Register::S2),
408 19 => Ok(Register::S3),
409 20 => Ok(Register::S4),
410 21 => Ok(Register::S5),
411 22 => Ok(Register::S6),
412 23 => Ok(Register::S7),
413 24 => Ok(Register::T8),
414 25 => Ok(Register::T9),
415 26 => Ok(Register::K0),
416 27 => Ok(Register::K1),
417 28 => Ok(Register::Gp),
418 29 => Ok(Register::Sp),
419 30 => Ok(Register::Fp),
420 31 => Ok(Register::Ra),
421 e => Err(RegParseError::RegParseError(e.to_string())),
422 }
423 }
424}
425
426impl From<FloatRegister> for Register {
427 fn from(reg: FloatRegister) -> Self {
428 Register::try_from(reg as u32).unwrap()
429 }
430}
431
432impl From<Cop0Register> for Register {
433 fn from(reg: Cop0Register) -> Self {
434 Register::try_from(reg as u32).unwrap()
435 }
436}
437
438#[derive(Clone, Copy, Debug, Display)]
439#[strum(serialize_all = "snake_case")]
440pub enum FloatRegister {
441 Fv0,
442 Fv0f,
443 Fv1,
444 Fv1f,
445 Ft0,
446 Ft0f,
447 Ft1,
448 Ft1f,
449 Ft2,
450 Ft2f,
451 Ft3,
452 Ft3f,
453 Fa0,
454 Fa0f,
455 Fa1,
456 Fa1f,
457 Ft4,
458 Ft4f,
459 Ft5,
460 Ft5f,
461 Fs0,
462 Fs0f,
463 Fs1,
464 Fs1f,
465 Fs2,
466 Fs2f,
467 Fs3,
468 Fs3f,
469 Fs4,
470 Fs4f,
471 Fs5,
472 Fs5f,
473}
474
475impl TryFrom<u32> for FloatRegister {
476 type Error = RegParseError;
477
478 fn try_from(reg: u32) -> Result<Self, Self::Error> {
479 match reg {
480 0 => Ok(FloatRegister::Fv0),
481 1 => Ok(FloatRegister::Fv0f),
482 2 => Ok(FloatRegister::Fv1),
483 3 => Ok(FloatRegister::Fv1f),
484 4 => Ok(FloatRegister::Ft0),
485 5 => Ok(FloatRegister::Ft0f),
486 6 => Ok(FloatRegister::Ft1),
487 7 => Ok(FloatRegister::Ft1f),
488 8 => Ok(FloatRegister::Ft2),
489 9 => Ok(FloatRegister::Ft2f),
490 10 => Ok(FloatRegister::Ft3),
491 11 => Ok(FloatRegister::Ft3f),
492 12 => Ok(FloatRegister::Fa0),
493 13 => Ok(FloatRegister::Fa0f),
494 14 => Ok(FloatRegister::Fa1),
495 15 => Ok(FloatRegister::Fa1f),
496 16 => Ok(FloatRegister::Ft4),
497 17 => Ok(FloatRegister::Ft4f),
498 18 => Ok(FloatRegister::Ft5),
499 19 => Ok(FloatRegister::Ft5f),
500 20 => Ok(FloatRegister::Fs0),
501 21 => Ok(FloatRegister::Fs0f),
502 22 => Ok(FloatRegister::Fs1),
503 23 => Ok(FloatRegister::Fs1f),
504 24 => Ok(FloatRegister::Fs2),
505 25 => Ok(FloatRegister::Fs2f),
506 26 => Ok(FloatRegister::Fs3),
507 27 => Ok(FloatRegister::Fs3f),
508 28 => Ok(FloatRegister::Fs4),
509 29 => Ok(FloatRegister::Fs4f),
510 30 => Ok(FloatRegister::Fs5),
511 31 => Ok(FloatRegister::Fs5f),
512 e => Err(RegParseError::RegParseError(e.to_string())),
513 }
514 }
515}
516
517impl FromStr for FloatRegister {
518 type Err = RegParseError;
519
520 fn from_str(reg: &str) -> Result<Self, Self::Err> {
521 let reg = reg.trim().trim_start_matches('$');
522
523 if let Ok(x) = reg.parse::<u32>() {
524 return FloatRegister::try_from(x);
525 }
526
527 match reg.to_lowercase().as_str() {
528 "f0" | "fv0" => Ok(FloatRegister::Fv0),
529 "f1" | "fv0f" => Ok(FloatRegister::Fv0f),
530 "f2" | "fv1" => Ok(FloatRegister::Fv1),
531 "f3" | "fv1f" => Ok(FloatRegister::Fv1f),
532 "f4" | "ft0" => Ok(FloatRegister::Ft0),
533 "f5" | "ft0f" => Ok(FloatRegister::Ft0f),
534 "f6" | "ft1" => Ok(FloatRegister::Ft1),
535 "f7" | "ft1f" => Ok(FloatRegister::Ft1f),
536 "f8" | "ft2" => Ok(FloatRegister::Ft2),
537 "f9" | "ft2f" => Ok(FloatRegister::Ft2f),
538 "f10" | "ft3" => Ok(FloatRegister::Ft3),
539 "f11" | "ft3f" => Ok(FloatRegister::Ft3f),
540 "f12" | "fa0" => Ok(FloatRegister::Fa0),
541 "f13" | "fa0f" => Ok(FloatRegister::Fa0f),
542 "f14" | "fa1" => Ok(FloatRegister::Fa1),
543 "f15" | "fa1f" => Ok(FloatRegister::Fa1f),
544 "f16" | "ft4" => Ok(FloatRegister::Ft4),
545 "f17" | "ft4f" => Ok(FloatRegister::Ft4f),
546 "f18" | "ft5" => Ok(FloatRegister::Ft5),
547 "f19" | "ft5f" => Ok(FloatRegister::Ft5f),
548 "f20" | "fs0" => Ok(FloatRegister::Fs0),
549 "f21" | "fs0f" => Ok(FloatRegister::Fs0f),
550 "f22" | "fs1" => Ok(FloatRegister::Fs1),
551 "f23" | "fs1f" => Ok(FloatRegister::Fs1f),
552 "f24" | "fs2" => Ok(FloatRegister::Fs2),
553 "f25" | "fs2f" => Ok(FloatRegister::Fs2f),
554 "f26" | "fs3" => Ok(FloatRegister::Fs3),
555 "f27" | "fs3f" => Ok(FloatRegister::Fs3f),
556 "f28" | "fs4" => Ok(FloatRegister::Fs4),
557 "f29" | "fs4f" => Ok(FloatRegister::Fs4f),
558 "f30" | "fs5" => Ok(FloatRegister::Fs5),
559 "f31" | "fs5f" => Ok(FloatRegister::Fs5f),
560 e => {
561 if let Ok(x) = u32::from_str_radix(reg, 16) {
562 return FloatRegister::try_from(x);
563 }
564 Err(RegParseError::RegParseError(e.to_string()))
565 }
566 }
567 }
568}
569
570impl From<Register> for FloatRegister {
571 fn from(reg: Register) -> Self {
572 FloatRegister::try_from(reg as u32).unwrap()
573 }
574}
575
576#[derive(Clone, Copy, Debug, Display)]
577#[strum(serialize_all = "PascalCase")]
578pub enum Cop0Register {
579 IDMemAddressForDMA,
580 DramAddressForDMA,
581 DmaReadLength,
582 DmaWriteLength,
583 RspStatus,
584 DmaFull,
585 DmaBusy,
586 CpuRspSemaphore,
587 RdpCommandBufferStart,
588 RdpCommandBufferEnd,
589 RdpCommandBufferCurrent,
590 RdpStatus,
591 RdpClockCounter,
592 RdpCommandBufferBusyCounter,
593 RdpPipeBusyCounter,
594 RdpTmemBusyCounter,
595}
596
597impl TryFrom<u32> for Cop0Register {
598 type Error = RegParseError;
599
600 fn try_from(reg: u32) -> Result<Self, Self::Error> {
601 match reg {
602 0 => Ok(Cop0Register::IDMemAddressForDMA),
603 1 => Ok(Cop0Register::DramAddressForDMA),
604 2 => Ok(Cop0Register::DmaReadLength),
605 3 => Ok(Cop0Register::DmaWriteLength),
606 4 => Ok(Cop0Register::RspStatus),
607 5 => Ok(Cop0Register::DmaFull),
608 6 => Ok(Cop0Register::DmaBusy),
609 7 => Ok(Cop0Register::CpuRspSemaphore),
610 8 => Ok(Cop0Register::RdpCommandBufferStart),
611 9 => Ok(Cop0Register::RdpCommandBufferEnd),
612 10 => Ok(Cop0Register::RdpCommandBufferCurrent),
613 11 => Ok(Cop0Register::RdpStatus),
614 12 => Ok(Cop0Register::RdpClockCounter),
615 13 => Ok(Cop0Register::RdpCommandBufferBusyCounter),
616 14 => Ok(Cop0Register::RdpPipeBusyCounter),
617 15 => Ok(Cop0Register::RdpTmemBusyCounter),
618 e => Err(RegParseError::RegParseError(e.to_string())),
619 }
620 }
621}
622
623impl From<Register> for Cop0Register {
624 fn from(reg: Register) -> Self {
625 Cop0Register::try_from(reg as u32).unwrap()
626 }
627}
628
629#[derive(Clone, Copy, Debug, Display, EnumString, PartialEq, Eq)]
630#[strum(ascii_case_insensitive)]
631#[strum(serialize_all = "snake_case")]
632pub enum ITypeOp {
633 Addi,
634 Addiu,
635 Andi,
636 Bc0f,
637 Bc0fl,
638 Bc0t,
639 Bc0tl,
640 Bc1f,
641 Bc1fl,
642 Bc1t,
643 Bc1tl,
644 Beq,
645 Beql,
646 Bgez,
647 Bgezal,
648 Bgezall,
649 Bgezl,
650 Bgtz,
651 Bgtzl,
652 Blez,
653 Blezl,
654 Bltz,
655 Bltzal,
656 Bltzall,
657 Bltzl,
658 Bne,
659 Bnel,
660 Cache,
661 Daddi,
662 Daddiu,
663 Lb,
664 Lbu,
665 Ld,
666 Ldc1,
667 Ldl,
668 Ldr,
669 Lh,
670 Lhu,
671 Ll,
672 Lld,
673 Lui,
674 Lw,
675 Lwc1,
676 Lbv,
677 Lwl,
678 Lwr,
679 Lwu,
680 Ori,
681 Sb,
682 Sc,
683 Scd,
684 Sd,
685 Sdc1,
686 Sdl,
687 Sdr,
688 Sh,
689 Slti,
690 Sltiu,
691 Sw,
692 Swc1,
693 Swl,
694 Swr,
695 Teqi,
696 Tgei,
697 Tgeiu,
698 Tlti,
699 Tltiu,
700 Tnei,
701 Xori,
702 B,
704 Bal,
705 Beqz,
706 Bnez,
707 Beqzl,
708 Bnezl,
709 Bge,
710 Bgt,
711 Ble,
712 Blt,
713 Bgeu,
714 Bgtu,
715 Bleu,
716 Bltu,
717 Bgel,
718 Bgtl,
719 Blel,
720 Bltl,
721 Bgeul,
722 Bgtul,
723 Bleul,
724 Bltul,
725 Dli,
726 Dsubi,
727 Dsubiu,
728 Lli,
729 Li,
730 Subi,
731 Subiu,
732}
733
734#[derive(Clone, Copy, Debug, Display, EnumString, PartialEq, Eq)]
735#[strum(ascii_case_insensitive)]
736#[strum(serialize_all = "snake_case")]
737pub enum JTypeOp {
738 J,
739 Jal,
740}
741
742#[derive(Clone, Copy, Debug, Display, EnumString, PartialEq, Eq)]
743#[strum(ascii_case_insensitive)]
744#[strum(serialize_all = "snake_case")]
745pub enum RTypeOp {
746 #[strum(to_string = "abs.s")]
747 AbsS,
748 #[strum(to_string = "abs.d")]
749 AbsD,
750 Add,
751 Addu,
752 #[strum(to_string = "add.s")]
753 AddS,
754 #[strum(to_string = "add.d")]
755 AddD,
756 And,
757 Break,
758 #[strum(to_string = "c.s")]
759 Cs,
760 #[strum(to_string = "c.d")]
761 Cd,
762 #[strum(to_string = "ceil.l.s")]
763 CeilLS,
764 #[strum(to_string = "ceil.l.d")]
765 CeilLD,
766 #[strum(to_string = "ceil.w.s")]
767 CeilWS,
768 #[strum(to_string = "ceil.w.d")]
769 CeilWD,
770 Cfc0,
771 Cfc1,
772 Ctc0,
773 Ctc1,
774 #[strum(to_string = "cvt.d.s")]
775 CvtDS,
776 #[strum(to_string = "cvt.d.w")]
777 CvtDW,
778 #[strum(to_string = "cvt.d.l")]
779 CvtDL,
780 #[strum(to_string = "cvt.l.s")]
781 CvtLS,
782 #[strum(to_string = "cvt.l.d")]
783 CvtLD,
784 #[strum(to_string = "cvt.s.d")]
785 CvtSD,
786 #[strum(to_string = "cvt.s.w")]
787 CvtSW,
788 #[strum(to_string = "cvt.s.l")]
789 CvtSL,
790 #[strum(to_string = "cvt.w.s")]
791 CvtWS,
792 #[strum(to_string = "cvt.w.d")]
793 CvtWD,
794 Dadd,
795 Daddu,
796 Ddiv,
797 Ddivu,
798 Div,
799 Divu,
800 #[strum(to_string = "div.s")]
801 DivS,
802 #[strum(to_string = "div.d")]
803 DivD,
804 Dmfc0,
805 Dmfc1,
806 Dmtc0,
807 Dmtc1,
808 Dmult,
809 Dmultu,
810 Dsll,
811 Dsll32,
812 Dsllv,
813 Dsra,
814 Dsra32,
815 Dsrav,
816 Dsrl,
817 Dsrl32,
818 Dsrlv,
819 Dsub,
820 Dsubu,
821 Eret,
822 #[strum(to_string = "floor.l.s")]
823 FloorLS,
824 #[strum(to_string = "floor.l.d")]
825 FloorLD,
826 #[strum(to_string = "floor.w.s")]
827 FloorWS,
828 #[strum(to_string = "floor.w.d")]
829 FloorWD,
830 Jalr,
831 Jr,
832 Mfc0,
833 Mfc1,
834 Mfhi,
835 Mflo,
836 #[strum(to_string = "mov.s")]
837 MovS,
838 #[strum(to_string = "mov.d")]
839 MovD,
840 Mtc0,
841 Mtc1,
842 Mthi,
843 Mtlo,
844 #[strum(to_string = "mul.s")]
845 MulS,
846 #[strum(to_string = "mul.d")]
847 MulD,
848 Mult,
849 Multu,
850 #[strum(to_string = "neg.s")]
851 NegS,
852 #[strum(to_string = "neg.d")]
853 NegD,
854 Nor,
855 Or,
856 #[strum(to_string = "round.l.s")]
857 RoundLS,
858 #[strum(to_string = "round.l.d")]
859 RoundLD,
860 #[strum(to_string = "round.w.s")]
861 RoundWS,
862 #[strum(to_string = "round.w.d")]
863 RoundWD,
864 Sll,
865 Sllv,
866 Slt,
867 Sltu,
868 #[strum(to_string = "sqrt.s")]
869 SqrtS,
870 #[strum(to_string = "sqrt.d")]
871 SqrtD,
872 Sra,
873 Srav,
874 Srl,
875 Srlv,
876 Sub,
877 Subu,
878 #[strum(to_string = "sub.s")]
879 SubS,
880 #[strum(to_string = "sub.d")]
881 SubD,
882 Sync,
883 Syscall,
884 Teq,
885 Tge,
886 Tgeu,
887 Tlbp,
888 Tlbr,
889 Tlbwi,
890 Tlbwr,
891 Tlt,
892 Tltu,
893 Tne,
894 #[strum(to_string = "trunc.l.s")]
895 TruncLS,
896 #[strum(to_string = "trunc.l.d")]
897 TruncLD,
898 #[strum(to_string = "trunc.w.s")]
899 TruncWS,
900 #[strum(to_string = "trunc.w.d")]
901 TruncWD,
902 Xor,
903 Abs,
905 Clear,
906 Dabs,
907 Dmove,
908 Dmul,
909 Dmulu,
910 Dmulo,
911 Dmulou,
912 Dneg,
913 Dnegu,
914 Drem,
915 Dremu,
916 Drol,
917 Dror,
918 Move,
919 Mul,
920 Mulu,
921 Mulo,
922 Mulou,
923 Neg,
924 Negu,
925 Nop,
926 Not,
927 Rem,
928 Remu,
929 Seq,
930 Sge,
931 Sgeu,
932 Sgt,
933 Sgtu,
934 Sle,
935 Sleu,
936 Sne,
937}
938
939#[derive(Clone, Copy, Debug, Display, EnumString)]
940#[strum(ascii_case_insensitive)]
941#[strum(serialize_all = "snake_case")]
942pub enum FloatCond {
943 F,
944 Un,
945 Eq,
946 Ueq,
947 Olt,
948 Ult,
949 Ole,
950 Ule,
951 Sf,
952 Ngle,
953 Seq,
954 Ngl,
955 Lt,
956 Nge,
957 Le,
958 Ngt,
959}
960
961impl TryFrom<u32> for FloatCond {
962 type Error = RegParseError;
963
964 fn try_from(cond: u32) -> Result<Self, Self::Error> {
965 match cond {
966 0 => Ok(FloatCond::F),
967 1 => Ok(FloatCond::Un),
968 2 => Ok(FloatCond::Eq),
969 3 => Ok(FloatCond::Ueq),
970 4 => Ok(FloatCond::Olt),
971 5 => Ok(FloatCond::Ult),
972 6 => Ok(FloatCond::Ole),
973 7 => Ok(FloatCond::Ule),
974 8 => Ok(FloatCond::Sf),
975 9 => Ok(FloatCond::Ngle),
976 10 => Ok(FloatCond::Seq),
977 11 => Ok(FloatCond::Ngl),
978 12 => Ok(FloatCond::Lt),
979 13 => Ok(FloatCond::Nge),
980 14 => Ok(FloatCond::Le),
981 15 => Ok(FloatCond::Ngt),
982 e => Err(RegParseError::RegParseError(e.to_string())),
983 }
984 }
985}