arch_ops/
clever.rs

1use std::{
2    convert::TryFrom,
3    io::{ErrorKind, Read, Write},
4    ops::{Range, RangeFrom, RangeFull, RangeInclusive, RangeTo, RangeToInclusive},
5};
6
7use crate::{
8    disasm::OpcodePrinter,
9    traits::{Address, InsnRead, InsnWrite, Reloc, RelocCode},
10};
11
12#[derive(Debug)]
13pub struct CleverExtensionFromStrError;
14
15impl core::fmt::Display for CleverExtensionFromStrError {
16    fn fmt(&self, f: &mut core::fmt::Formatter) -> core::fmt::Result {
17        f.write_str("Unknown clever")
18    }
19}
20
21impl std::error::Error for CleverExtensionFromStrError {}
22
23macro_rules! define_clever_features{
24    {
25        $(($enum:ident, $feature:literal)),* $(,)?
26    } => {
27        #[derive(Copy,Clone,Debug,Hash,PartialEq,Eq)]
28        #[non_exhaustive]
29        #[repr(i32)]
30        pub enum CleverExtension{
31            $($enum,)*
32        }
33
34        impl CleverExtension{
35            pub fn extension_name(&self) -> &'static str{
36                match self{
37                    $(#[allow(unreachable_patterns)] Self::$enum => $feature,)*
38                }
39            }
40        }
41
42        impl core::str::FromStr for CleverExtension{
43            type Err = CleverExtensionFromStrError;
44            fn from_str(x: &str) -> Result<Self,Self::Err>{
45                match x{
46
47                    $(#[allow(unreachable_patterns)] $feature => Ok(Self::$enum),)*
48                    _ => Err(CleverExtensionFromStrError)
49                }
50            }
51        }
52
53        impl core::fmt::Display for CleverExtension{
54            fn fmt(&self, f: &mut core::fmt::Formatter) -> core::fmt::Result{
55                match self{
56                    $(Self::$enum => f.write_str($feature),)*
57                }
58            }
59        }
60    }
61}
62
63define_clever_features! {
64    (Main, "main"),
65    (Float, "float"),
66    (FloatExt, "float-ext"),
67    (Vec, "vec"),
68    (Rand, "rand"),
69    (Virtualization, "virtualization"),
70}
71
72#[derive(Copy, Clone, Hash, PartialEq, Eq)]
73pub struct CleverRegister(pub u8);
74
75#[derive(Copy, Clone, Debug, Hash, PartialEq, Eq)]
76pub struct RegisterFromStrError;
77
78macro_rules! clever_registers{
79    {
80        $($name:ident $(| $altnames:ident)* => $val:expr),* $(,)?
81    } => {
82        #[allow(non_upper_case_globals)]
83        impl CleverRegister{
84            $(pub const $name: Self = Self($val); $(pub const $altnames: Self = Self($val);)*)*
85        }
86        impl ::core::str::FromStr for CleverRegister{
87            type Err = RegisterFromStrError;
88            fn from_str(st: &str) -> Result<Self,Self::Err>{
89                match st{
90                    $(
91                        ::core::stringify!($name) $(| ::core::stringify!($altnames))* => Ok(Self($val)),
92                    )*
93                    _ => Err(RegisterFromStrError)
94                }
95            }
96        }
97        impl ::core::fmt::Display for CleverRegister{
98            fn fmt(&self, f: &mut core::fmt::Formatter) -> core::fmt::Result{
99                match self{
100                    $(CleverRegister($val) => f.write_str(::core::stringify!($name)),)*
101                    CleverRegister(val) => f.write_fmt(::core::format_args!("r{}",val))
102                }
103            }
104        }
105
106        impl ::core::fmt::Debug for CleverRegister{
107            fn fmt(&self, f: &mut core::fmt::Formatter) -> ::core::fmt::Result{
108                struct DontEscape(&'static str);
109                impl ::core::fmt::Debug for DontEscape{
110                    fn fmt(&self, f: &mut core::fmt::Formatter) -> ::core::fmt::Result{
111                        f.write_str(self.0)
112                    }
113                }
114
115                match self{
116                    $(CleverRegister($val) => {
117                        f.debug_tuple("CleverRegister")
118                            .field(&DontEscape(::core::stringify!($name))).finish()
119                    })*
120                    CleverRegister(val) => f.debug_tuple("CleverRegister").field(&val).finish()
121                }
122            }
123        }
124    }
125}
126
127clever_registers! {
128    r0 | racc => 0,
129    r1 | rsrc => 1,
130    r2 | rdst => 2,
131    r3 | rcnt => 3,
132    r4 => 4,
133    r5 => 5,
134    r6 | fbase => 6,
135    r7 | sptr => 7,
136    r8 => 8,
137    r9 => 9,
138    r10 => 10,
139    r11 => 11,
140    r12 => 12,
141    r13 => 13,
142    r14 => 14,
143    r15 | link => 15,
144    ip => 16,
145    flags => 17,
146    mode => 18,
147    fpcw => 19,
148    f0 => 24,
149    f1 => 25,
150    f2 => 26,
151    f3 => 27,
152    f4 => 28,
153    f5 => 29,
154    f6 => 30,
155    f7 => 31,
156    v0l => 64,
157    v0h => 65,
158    v1l => 66,
159    v1h => 67,
160    v2l => 68,
161    v2h => 69,
162    v3l => 70,
163    v3h => 71,
164    v4l => 72,
165    v4h => 73,
166    v5l => 74,
167    v5h => 75,
168    v6l => 76,
169    v6h => 77,
170    v7l => 78,
171    v7h => 79,
172    v8l => 80,
173    v8h => 81,
174    v9l => 82,
175    v9h => 83,
176    v10l => 84,
177    v10h => 85,
178    v11l => 86,
179    v11h => 87,
180    v12l => 88,
181    v12h => 89,
182    v13l => 90,
183    v13h => 91,
184    v14l => 92,
185    v14h => 93,
186    v15l => 94,
187    v15h => 95,
188    cr0 => 128,
189    page | cr1 => 129,
190    flprotected | cr2 => 130,
191    scdp | cr3 => 131,
192    scsp | cr4 => 132,
193    sccr | cr5 => 133,
194    itabp | cr6 => 134,
195    ciread | cr7 => 135,
196    cpuidlo => 136,
197    cpuidhi => 137,
198    cpuex2 => 138,
199    cpuex3 => 139,
200    cpuex4 => 140,
201    cpuex5 => 141,
202    cpuex6 => 142,
203    mscpuex => 143,
204    fcode | cr8 => 144,
205    pfchar | cr9 => 145,
206    msr0 => 148,
207    msr1 => 149,
208    msr2 => 150,
209    msr3 => 151,
210    msr4 => 152,
211    msr5 => 153,
212    msr6 => 154,
213    rdinfo => 156
214}
215
216macro_rules! register_extensions{
217    ($($reg:ident: $ext:expr),* $(,)?) => {
218        impl CleverRegister{
219            pub fn extension(self) -> Option<CleverExtension>{
220                match self{
221                    $(Self:: $reg => Some($ext),)*
222                    #[allow(unreachable_patterns)] _ => None
223                }
224            }
225        }
226
227    }
228}
229
230use CleverExtension::Vec as Vector;
231
232register_extensions!(
233    r0: Main,
234    r1: Main,
235    r2: Main,
236    r3: Main,
237    r4: Main,
238    r5: Main,
239    r6: Main,
240    r7: Main,
241    r8: Main,
242    r9: Main,
243    r10: Main,
244    r11: Main,
245    r12: Main,
246    r13: Main,
247    r14: Main,
248    r15: Main,
249    ip: Main,
250    flags: Main,
251    mode: Main,
252    fpcw: Float,
253    f0: Float,
254    f1: Float,
255    f2: Float,
256    f3: Float,
257    f4: Float,
258    f5: Float,
259    f6: Float,
260    f7: Float,
261    v0l: Vector,
262    v0h: Vector,
263    v1l: Vector,
264    v1h: Vector,
265    v2l: Vector,
266    v2h: Vector,
267    v3l: Vector,
268    v3h: Vector,
269    v4l: Vector,
270    v4h: Vector,
271    v5l: Vector,
272    v5h: Vector,
273    v6l: Vector,
274    v6h: Vector,
275    v7l: Vector,
276    v7h: Vector,
277    v8l: Vector,
278    v8h: Vector,
279    v9l: Vector,
280    v9h: Vector,
281    v10l: Vector,
282    v10h: Vector,
283    v11l: Vector,
284    v11h: Vector,
285    v12l: Vector,
286    v12h: Vector,
287    v13l: Vector,
288    v13h: Vector,
289    v14l: Vector,
290    v14h: Vector,
291    v15l: Vector,
292    v15h: Vector,
293    cr0: Main,
294    cr1: Main,
295    cr2: Main,
296    cr3: Main,
297    cr4: Main,
298    cr5: Main,
299    cr6: Main,
300    cr7: Main,
301    cpuidlo: Main,
302    cpuidhi: Main,
303    cpuex2: Main,
304    cpuex3: Main,
305    cpuex4: Main,
306    cpuex5: Main,
307    cpuex6: Main,
308    mscpuex: Main,
309    cr8: Main,
310    cr9: Main,
311    msr0: Main,
312    msr1: Main,
313    msr2: Main,
314    msr3: Main,
315    msr4: Main,
316    msr5: Main,
317    msr6: Main,
318    rdinfo: Rand,
319);
320
321#[derive(Copy, Clone, Debug, Hash, PartialEq, Eq)]
322#[repr(u8)]
323pub enum ConditionCode {
324    Parity,
325    Carry,
326    Overflow,
327    Zero,
328    LessThan,
329    LessEq,
330    BelowEq,
331    Minus,
332    Plus,
333    Above,
334    Greater,
335    GreaterEq,
336    NotZero,
337    NoOverflow,
338    NoCarry,
339    NoParity,
340}
341
342#[derive(Copy, Clone, Debug, Hash, PartialEq, Eq)]
343pub enum CleverIndex {
344    Register(CleverRegister),
345    Abs(i16),
346}
347
348impl core::fmt::Display for CleverIndex {
349    fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
350        match self {
351            Self::Register(r) => r.fmt(f),
352            Self::Abs(n) => n.fmt(f),
353        }
354    }
355}
356
357trait HBits {
358    fn from_bits(bits: u16) -> Self;
359    fn to_hbits(self) -> u16;
360}
361
362impl HBits for bool {
363    fn from_bits(bits: u16) -> Self {
364        bits != 0
365    }
366
367    fn to_hbits(self) -> u16 {
368        self as u16
369    }
370}
371
372impl HBits for u8 {
373    fn from_bits(bits: u16) -> Self {
374        bits as u8
375    }
376    fn to_hbits(self) -> u16 {
377        self as u16
378    }
379}
380
381impl HBits for i8 {
382    fn from_bits(bits: u16) -> Self {
383        (bits as i8) | ((bits & 0x8).wrapping_neg() as i8)
384    }
385    fn to_hbits(self) -> u16 {
386        (self & 0xf) as u16
387    }
388}
389
390// Because ss is typically represented as `u16` for reasons
391impl HBits for u16 {
392    fn from_bits(bits: u16) -> Self {
393        bits
394    }
395    fn to_hbits(self) -> u16 {
396        self
397    }
398}
399
400impl HBits for CleverRegister {
401    fn from_bits(bits: u16) -> Self {
402        Self(bits as u8)
403    }
404
405    fn to_hbits(self) -> u16 {
406        self.0 as u16
407    }
408}
409
410impl HBits for ConditionCode {
411    fn from_bits(bits: u16) -> Self {
412        match bits {
413            0 => ConditionCode::Parity,
414            1 => ConditionCode::Carry,
415            2 => ConditionCode::Overflow,
416            3 => ConditionCode::Zero,
417            4 => ConditionCode::LessThan,
418            5 => ConditionCode::LessEq,
419            6 => ConditionCode::BelowEq,
420            7 => ConditionCode::Minus,
421            8 => ConditionCode::Plus,
422            9 => ConditionCode::Above,
423            10 => ConditionCode::Greater,
424            11 => ConditionCode::GreaterEq,
425            12 => ConditionCode::NotZero,
426            13 => ConditionCode::NoOverflow,
427            14 => ConditionCode::NoCarry,
428            15 => ConditionCode::NoParity,
429            _ => unreachable!(),
430        }
431    }
432
433    fn to_hbits(self) -> u16 {
434        self as u8 as u16
435    }
436}
437
438trait HBitRange<T> {
439    fn shift(&self) -> u32;
440    fn mask(&self) -> u16;
441}
442
443impl HBitRange<u32> for u32 {
444    fn shift(&self) -> u32 {
445        *self
446    }
447
448    fn mask(&self) -> u16 {
449        1u16 << (*self)
450    }
451}
452
453impl HBitRange<u32> for Range<u32> {
454    fn shift(&self) -> u32 {
455        self.start
456    }
457
458    fn mask(&self) -> u16 {
459        ((1u16 << (self.end - self.start)) - 1) << self.start
460    }
461}
462
463impl HBitRange<u32> for RangeInclusive<u32> {
464    fn shift(&self) -> u32 {
465        *self.start()
466    }
467
468    fn mask(&self) -> u16 {
469        ((1u16 << (self.end() - self.start())) - 1) << self.start()
470    }
471}
472
473impl HBitRange<u32> for RangeFrom<u32> {
474    fn shift(&self) -> u32 {
475        self.start
476    }
477
478    fn mask(&self) -> u16 {
479        ((1u16 << (4 - self.start)) - 1) << self.start
480    }
481}
482
483impl HBitRange<u32> for RangeTo<u32> {
484    fn shift(&self) -> u32 {
485        0
486    }
487
488    fn mask(&self) -> u16 {
489        (1u16 << (self.end - 1)) - 1
490    }
491}
492
493impl HBitRange<u32> for RangeToInclusive<u32> {
494    fn shift(&self) -> u32 {
495        0
496    }
497
498    fn mask(&self) -> u16 {
499        (1u16 << self.end) - 1
500    }
501}
502
503impl HBitRange<u32> for RangeFull {
504    fn shift(&self) -> u32 {
505        0
506    }
507
508    fn mask(&self) -> u16 {
509        0xf
510    }
511}
512
513#[derive(Copy, Clone, Debug, Hash, PartialEq, Eq)]
514pub enum CleverOperandKind {
515    Normal(u32),
516    AbsAddr,
517    RelAddr,
518    Size,
519    HRegister,
520    HImmediate,
521    // prefix
522    Insn,
523}
524
525macro_rules! clever_instructions{
526    {
527        $([$enum:ident, $insn:literal, $opcode:literal, $operands:expr, $ext:expr $(, { $($hfield:ident @ $range:expr => $ty:ty ),* $(,)?})? ]),* $(,)?
528    } => {
529
530        #[derive(Copy,Clone,Debug,Hash,PartialEq, Eq)]
531        #[non_exhaustive]
532        pub enum CleverOpcode{
533            $($enum $({$($hfield: $ty),*})?),*
534        }
535
536        impl CleverOpcode{
537
538            pub fn from_opcode(opc: u16) -> Option<CleverOpcode>{
539                match opc>>4{
540                    $(#[allow(unreachable_patterns)] $opcode => {
541                        #[allow(unused_mut)]
542                        let mut hmask = 0;
543
544                        $(#[allow(unused_parens, clippy::eval_order_dependence, clippy::mixed_read_write_in_expression)] let ($($hfield),*) = (
545                            $({
546                                fn range() -> impl HBitRange<u32>{
547                                    $range
548                                }
549                                let range = range();
550                                hmask |= HBitRange::mask(&range)<<HBitRange::shift(&range);
551                                HBits::from_bits((opc&HBitRange::mask(&range))>>HBitRange::shift(&range))
552                            }),*
553                        );)?
554                        if ((opc&0xf)&!hmask)!=0{
555                            return None
556                        }
557                        Some(Self:: $enum $({$($hfield),*})?)
558                    },)*
559                    _ => None
560                }
561            }
562
563            pub fn extension(&self) -> CleverExtension{
564                match self{
565                    $(Self:: $enum {..} => $ext,)*
566                }
567            }
568
569            pub fn name(&self) -> &'static str{
570                match self{
571                    $(Self:: $enum {..} => $insn,)*
572                }
573            }
574
575            pub fn opcode(&self) -> u16{
576                match self{
577                    $(Self:: $enum $({$($hfield),*})? => {
578                        let base: u16 = $opcode;
579                        #[allow(unused_mut)] // mut may be unused if the instruction doesn't have any h bits
580                        let mut opc = base<<4;
581                        $($({
582                            let range = $range;
583
584                            let bits = (HBits::to_hbits(*$hfield)<< HBitRange::shift(&range))&HBitRange::mask(&range);
585                            opc |= bits;
586                        })*)?
587                        opc
588                    })*
589                }
590            }
591
592            pub fn operands(&self) -> CleverOperandKind{
593                match self{
594                    $(Self:: $enum {..} => $operands,)*
595                }
596            }
597        }
598    }
599}
600
601use CleverExtension::{Float, FloatExt, Main, Rand, Virtualization};
602
603clever_instructions! {
604    // Undefined Instruction 0
605    [Und0, "und", 0x000, CleverOperandKind::Normal(0), Main],
606
607    // Arithmetic Instructions
608    [Add, "add", 0x001, CleverOperandKind::Normal(2), Main, {lock @ 3 => bool, flags @ 0 => bool}],
609    [Sub, "sub", 0x002, CleverOperandKind::Normal(2), Main, {lock @ 3 => bool, flags @ 0 => bool}],
610    [And, "and", 0x003, CleverOperandKind::Normal(2), Main, {lock @ 3 => bool, flags @ 0 => bool}],
611    [Or , "or" , 0x004, CleverOperandKind::Normal(2), Main, {lock @ 3 => bool, flags @ 0 => bool}],
612    [Xor, "xor", 0x005, CleverOperandKind::Normal(2), Main, {lock @ 3 => bool, flags @ 0 => bool}],
613
614    // Division and multiplication Instructions
615    [Mul, "mul", 0x006, CleverOperandKind::Normal(0), Main, {ss @ 2..4 => u16, flags @ 0 => bool}],
616    [Div, "div", 0x007, CleverOperandKind::Normal(0), Main, {ss @ 2..4 => u16, wide @ 1 => bool, flags @ 0 => bool}],
617
618    // Register Manipulation Instructions
619    [Mov, "mov", 0x008, CleverOperandKind::Normal(2), Main],
620    [Lea, "lea", 0x009, CleverOperandKind::Normal(2), Main],
621    [MovRD, "mov", 0x00A, CleverOperandKind::Normal(1), Main, {r @ .. => CleverRegister}],
622    [MovRS, "mov", 0x00B, CleverOperandKind::Normal(1), Main, {r @ .. => CleverRegister}],
623    [LeaRD, "lea", 0x00C, CleverOperandKind::Normal(1), Main, {r @ .. => CleverRegister}],
624
625    // Nops
626    [Nop10, "nop", 0x010, CleverOperandKind::Normal(0), Main, {any @ .. => u16}],
627    [Nop11, "nop", 0x011, CleverOperandKind::Normal(1), Main, {any @ .. => u16}],
628    [Nop12, "nop", 0x012, CleverOperandKind::Normal(2), Main, {any @ .. => u16}],
629    [Nop13, "nop", 0x013, CleverOperandKind::Normal(3), Main, {any @ .. => u16}],
630
631    // Stack Manipulation
632    [Push, "push", 0x014, CleverOperandKind::Normal(1), Main],
633    [Pop , "pop" , 0x015, CleverOperandKind::Normal(1), Main],
634    [PushR, "push", 0x016, CleverOperandKind::Normal(0), Main, {r @ .. => CleverRegister}],
635    [PopR , "pop" , 0x017, CleverOperandKind::Normal(0), Main, {r @ .. => CleverRegister}],
636
637    // Mass Register Storage
638    [Stogpr , "stogpr" , 0x018, CleverOperandKind::Normal(1), Main],
639    [Stoar  , "stoar"  , 0x019, CleverOperandKind::Normal(1), Main],
640    [Rstogpr, "rstogpr", 0x01A, CleverOperandKind::Normal(1), Main],
641    [Rstoar , "rstoar" , 0x01B, CleverOperandKind::Normal(1), Main],
642    [Pushgpr, "pushgpr", 0x01C, CleverOperandKind::Normal(0), Main],
643    [Pushar , "pushar" , 0x01D, CleverOperandKind::Normal(0), Main],
644    [Popgpr , "popgpr" , 0x01E, CleverOperandKind::Normal(0), Main],
645    [Popar  , "popar"  , 0x01F, CleverOperandKind::Normal(0), Main],
646
647    // Converting Moves
648    [Movsx, "movsx", 0x020, CleverOperandKind::Normal(2), Main, {flags @ 0 => bool}],
649    [Bswap, "bswap", 0x021, CleverOperandKind::Normal(2), Main, {flags @ 0 => bool}],
650    [Movsif, "movsif", 0x022, CleverOperandKind::Normal(2), Float, {flags @ 0 => bool}],
651    [Movxf, "movxf", 0x023, CleverOperandKind::Normal(2), Float, {ss @ 3..=4 => u16, int @ 2 => bool,flags @0 => bool}],
652    [Movfsi, "movfsi", 0x024, CleverOperandKind::Normal(2), Float, {flags @ 0 => bool}],
653    [Movfx, "movfx", 0x025, CleverOperandKind::Normal(2), Float,  {ss @ 3..=4 => u16, int @ 2 => bool,flags @0 => bool}],
654    [Cvtf, "cvtf", 0x026, CleverOperandKind::Normal(2), Float, {flags @ 0 => bool}],
655
656
657    // Block Instructions
658    [Repbi, "repbi", 0x028, CleverOperandKind::Insn, Main, {cc @ 0..4 => ConditionCode}],
659    [Repbc, "repbc", 0x029, CleverOperandKind::Insn, Main],
660    [Bcpy, "bcpy", 0x02a, CleverOperandKind::Normal(0), Main, {ss @ 0..2 => u16}],
661    [Bsto, "bsto", 0x02b, CleverOperandKind::Normal(0), Main, {ss @ 0..2 => u16}],
662    [Bsca, "bsca", 0x02c, CleverOperandKind::Normal(0), Main, {ss @ 0..2 => u16}],
663    [Bcmp, "bcmp", 0x02d, CleverOperandKind::Normal(0), Main, {ss @ 0..2 => u16}],
664    [Btst, "btst", 0x02e, CleverOperandKind::Normal(0), Main, {ss @ 0..2 => u16}],
665
666    // Integer Shifts
667    [Lsh, "lsh", 0x030, CleverOperandKind::Normal(2), Main, {l @ 3 => bool, f @ 0 => bool}],
668    [Rsh, "rsh", 0x031, CleverOperandKind::Normal(2), Main, {l @ 3 => bool, f @ 0 => bool}],
669    [Arsh, "arsh", 0x032, CleverOperandKind::Normal(2), Main, {l @ 3 => bool, f @ 0 => bool}],
670    [Lshc, "lshc", 0x033, CleverOperandKind::Normal(2), Main, {l @ 3 => bool, f @ 0 => bool}],
671    [Rshc, "rshc", 0x034, CleverOperandKind::Normal(2), Main, {l @ 3 => bool, f @ 0 => bool}],
672    [Lrot, "lrot", 0x035, CleverOperandKind::Normal(2), Main, {l @ 3 => bool, f @ 0 => bool}],
673    [Rrot, "rrot", 0x036, CleverOperandKind::Normal(2), Main, {l @ 3 => bool, f @ 0 => bool}],
674    [LshR, "lsh", 0x038, CleverOperandKind::Normal(2), Main, {r @ 0..4 => CleverRegister}],
675    [RshR, "rsh", 0x039, CleverOperandKind::Normal(2), Main, {r @ 0..4 => CleverRegister}],
676    [ArshR, "arsh", 0x03A, CleverOperandKind::Normal(2), Main, {r @ 0..4 => CleverRegister}],
677    [LshcR, "lshc", 0x03B, CleverOperandKind::Normal(2), Main, {r @ 0..4 => CleverRegister}],
678    [RshcR, "rshc", 0x03C, CleverOperandKind::Normal(2), Main, {r @ 0..4 => CleverRegister}],
679    [LrotR, "lrot", 0x03D, CleverOperandKind::Normal(2), Main, {r @ 0..4 => CleverRegister}],
680    [RrotR, "rrot", 0x03E, CleverOperandKind::Normal(2), Main, {r @ 0..4 => CleverRegister}],
681
682    // Arithmetic/Logic GPR Specifications
683    // Unary Operations
684    // Signed Multiplication/Division
685    [Imul, "imul", 0x040, CleverOperandKind::Normal(0), Main, {ss @ 2..4 => u16, flags @ 0 => bool}],
686    [AddRD, "add", 0x041, CleverOperandKind::Normal(1), Main, {r @ 0..4 => CleverRegister}],
687    [SubRD, "sub", 0x042, CleverOperandKind::Normal(1), Main, {r @ 0..4 => CleverRegister}],
688    [AndRD, "and", 0x043, CleverOperandKind::Normal(1), Main, {r @ 0..4 => CleverRegister}],
689    [OrRD, "or", 0x044, CleverOperandKind::Normal(1), Main, {r @ 0..4 => CleverRegister}],
690    [XorRD, "xor", 0x045, CleverOperandKind::Normal(1), Main, {r @ 0..4 => CleverRegister}],
691    [BNot, "bnot", 0x046, CleverOperandKind::Normal(1), Main, {l @ 3 => bool, f @ 0 => bool}],
692    [Neg, "neg", 0x047, CleverOperandKind::Normal(1), Main, {l @ 3 => bool, f @ 0 => bool}],
693    [Idiv, "idiv", 0x048, CleverOperandKind::Normal(1), Main, {ss @ 2..4 => u16, wide @ 1 => bool, flags @ 0 => bool}],
694    [AddRS, "add", 0x049, CleverOperandKind::Normal(1), Main, {r @ 0..4 => CleverRegister}],
695    [SubRS, "sub", 0x04A, CleverOperandKind::Normal(1), Main, {r @ 0..4 => CleverRegister}],
696    [AndRS, "and", 0x04B, CleverOperandKind::Normal(1), Main, {r @ 0..4 => CleverRegister}],
697    [OrRS, "or", 0x04C, CleverOperandKind::Normal(1), Main, {r @ 0..4 => CleverRegister}],
698    [XorRS, "xor", 0x04D, CleverOperandKind::Normal(1), Main, {r @ 0..4 => CleverRegister}],
699    [BNotR, "bnot", 0x046, CleverOperandKind::Normal(1), Main, {r @ 0..4 => CleverRegister}],
700    [NegR, "neg", 0x047, CleverOperandKind::Normal(1), Main, {r @ 0..4 => CleverRegister}],
701
702    // Comparison operations
703    [Cmp, "cmp", 0x06C, CleverOperandKind::Normal(2), Main],
704    [Test, "test", 0x06D, CleverOperandKind::Normal(2), Main],
705    [CmpR, "cmp", 0x06C, CleverOperandKind::Normal(1), Main, {r @ 0..4 => CleverRegister}],
706    [TestR, "test", 0x06D, CleverOperandKind::Normal(1), Main, {r @ 0..4 => CleverRegister}],
707
708    // Floating-Point Operations
709    [Round, "round", 0x100, CleverOperandKind::Normal(1), Float, {f @ 0 => bool}],
710    [Ceil, "ceil", 0x101, CleverOperandKind::Normal(1), Float, {f @ 0 => bool}],
711    [Floor, "floor", 0x102, CleverOperandKind::Normal(1), Float, {f @ 0 => bool}],
712    [FAbs, "fabs", 0x103, CleverOperandKind::Normal(1), Float, {f @ 0 => bool}],
713    [FNeg, "fneg", 0x104, CleverOperandKind::Normal(1), Float, {f @ 0 => bool}],
714    [FInv, "finv",0x105, CleverOperandKind::Normal(1), Float, {f @ 0 => bool}],
715    [FAdd, "fadd", 0x106, CleverOperandKind::Normal(2), Float, {f @ 0 => bool}],
716    [FSub, "fsub", 0x107, CleverOperandKind::Normal(2), Float, {f @ 0 => bool}],
717    [FMul, "fmul", 0x108, CleverOperandKind::Normal(2), Float, {f @ 0 => bool}],
718    [FDiv, "fdiv", 0x109, CleverOperandKind::Normal(2), Float, {f @ 0 => bool}],
719    [FRem, "frem", 0x10A, CleverOperandKind::Normal(2), Float, {f @ 0 => bool}],
720    [FFma, "ffma", 0x10B, CleverOperandKind::Normal(3), Float, {f @ 0 => bool}],
721
722    // Floating-point comparions
723    [FCmpz, "fcmpz", 0x118, CleverOperandKind::Normal(1), Float],
724    [FCmp, "fcmp", 0x119, CleverOperandKind::Normal(2), Float],
725
726    // Floating-point extra instructions
727    [Exp, "exp", 0x120, CleverOperandKind::Normal(1), FloatExt, {f @ 0 => bool}],
728    [Ln, "ln", 0x121, CleverOperandKind::Normal(1), FloatExt, {f @ 0 => bool}],
729    [Lg, "lg", 0x122, CleverOperandKind::Normal(1), FloatExt, {f @ 0 => bool}],
730    [Sin, "sin", 0x123, CleverOperandKind::Normal(1), FloatExt, {f @ 0 => bool}],
731    [Cos, "cos", 0x124, CleverOperandKind::Normal(1), FloatExt, {f @ 0 => bool}],
732    [Tan, "tan", 0x125, CleverOperandKind::Normal(1), FloatExt, {f @ 0 => bool}],
733    [Asin, "asin", 0x126, CleverOperandKind::Normal(1), FloatExt, {f @ 0 => bool}],
734    [Acos, "acos", 0x127, CleverOperandKind::Normal(1), FloatExt, {f @ 0 => bool}],
735    [Atan, "atan", 0x128, CleverOperandKind::Normal(1), FloatExt, {f @ 0 => bool}],
736    [Exp2,"exp2", 0x129, CleverOperandKind::Normal(1), FloatExt, {f @ 0 => bool}],
737    [Log10, "log10", 0x12A, CleverOperandKind::Normal(1), FloatExt, {f @ 0 => bool}],
738    [Lnp1, "lnp1", 0x12B, CleverOperandKind::Normal(1), FloatExt, {f @ 0 => bool}],
739    [Expm1, "expm1", 0x12C, CleverOperandKind::Normal(1), FloatExt, {f @ 0 => bool}],
740    [Sqrt, "sqrt", 0x12D, CleverOperandKind::Normal(1), FloatExt, {f @ 0 => bool}],
741
742    // Floating-point exception control
743    [FRaiseExcept, "fraiseexcept", 0x130, CleverOperandKind::Normal(0), Float],
744    [FTriggerExcept, "ftriggerexcept", 0x130, CleverOperandKind::Normal(0), Float],
745
746    // Atomic Operations
747    [Xchg, "xchg", 0x200, CleverOperandKind::Normal(2), Main],
748    [Cmpxchg, "cmpxchg", 0x201, CleverOperandKind::Normal(3), Main],
749    [Wcmpxchg, "wcmpxchg", 0x202, CleverOperandKind::Normal(3), Main],
750    [Fence, "fence", 0x203, CleverOperandKind::Normal(0), Main],
751
752    // Random Device Polling
753    [RPoll, "rpoll", 0x230, CleverOperandKind::Normal(0), Rand, {r @ .. => CleverRegister}],
754
755    // Vector Instructions
756    [Vec, "vec", 0x400, CleverOperandKind::Insn, CleverExtension::Vec],
757    [Vmov, "vmov",0x401, CleverOperandKind::Normal(2), CleverExtension::Vec],
758    [VShuffle, "vshuffle", 0x402, CleverOperandKind::Normal(2), CleverExtension::Vec],
759
760    // conditional Branches
761    [CBP0A , "jp" , 0x700, CleverOperandKind::AbsAddr, Main, {w @ .. => i8}],
762    [CBC0A , "jc" , 0x701, CleverOperandKind::AbsAddr, Main, {w @ .. => i8}],
763    [CBV0A , "jo" , 0x702, CleverOperandKind::AbsAddr, Main, {w @ .. => i8}],
764    [CBZ0A , "jz" , 0x703, CleverOperandKind::AbsAddr, Main, {w @ .. => i8}],
765    [CBL0A , "jlt", 0x704, CleverOperandKind::AbsAddr, Main, {w @ .. => i8}],
766    [CBLE0A, "jle", 0x705, CleverOperandKind::AbsAddr, Main, {w @ .. => i8}],
767    [CBBE0A, "jbe", 0x706, CleverOperandKind::AbsAddr, Main, {w @ .. => i8}],
768    [CBM0A , "jmi", 0x707, CleverOperandKind::AbsAddr, Main, {w @ .. => i8}],
769    [CBPS0A, "jps", 0x708, CleverOperandKind::AbsAddr, Main, {w @ .. => i8}],
770    [CBA0A , "ja" , 0x709, CleverOperandKind::AbsAddr, Main, {w @ .. => i8}],
771    [CBG0A , "jgt", 0x70A, CleverOperandKind::AbsAddr, Main, {w @ .. => i8}],
772    [CBGE0A, "jge", 0x70B, CleverOperandKind::AbsAddr, Main, {w @ .. => i8}],
773    [CBNZ0A, "jnz", 0x70C, CleverOperandKind::AbsAddr, Main, {w @ .. => i8}],
774    [CBNV0A, "jno", 0x70D, CleverOperandKind::AbsAddr, Main, {w @ .. => i8}],
775    [CBNC0A, "jnc", 0x70E, CleverOperandKind::AbsAddr, Main, {w @ .. => i8}],
776    [CBNP0A, "jnp", 0x70F, CleverOperandKind::AbsAddr, Main, {w @ .. => i8}],
777
778    [CBP0R , "jp" , 0x710, CleverOperandKind::RelAddr, Main, {w @ .. => i8}],
779    [CBC0R , "jc" , 0x711, CleverOperandKind::RelAddr, Main, {w @ .. => i8}],
780    [CBV0R , "jo" , 0x712, CleverOperandKind::RelAddr, Main, {w @ .. => i8}],
781    [CBZ0R , "jz" , 0x713, CleverOperandKind::RelAddr, Main, {w @ .. => i8}],
782    [CBL0R , "jlt", 0x714, CleverOperandKind::RelAddr, Main, {w @ .. => i8}],
783    [CBLE0R, "jle", 0x715, CleverOperandKind::RelAddr, Main, {w @ .. => i8}],
784    [CBBE0R, "jbe", 0x716, CleverOperandKind::RelAddr, Main, {w @ .. => i8}],
785    [CBM0R , "jmi", 0x717, CleverOperandKind::RelAddr, Main, {w @ .. => i8}],
786    [CBPS0R, "jps", 0x718, CleverOperandKind::RelAddr, Main, {w @ .. => i8}],
787    [CBA0R , "ja" , 0x719, CleverOperandKind::RelAddr, Main, {w @ .. => i8}],
788    [CBG0R , "jgt", 0x71A, CleverOperandKind::RelAddr, Main, {w @ .. => i8}],
789    [CBGE0R, "jge", 0x71B, CleverOperandKind::RelAddr, Main, {w @ .. => i8}],
790    [CBNZ0R, "jnz", 0x71C, CleverOperandKind::RelAddr, Main, {w @ .. => i8}],
791    [CBNV0R, "jno", 0x71D, CleverOperandKind::RelAddr, Main, {w @ .. => i8}],
792    [CBNC0R, "jnc", 0x71E, CleverOperandKind::RelAddr, Main, {w @ .. => i8}],
793    [CBNP0R, "jnp", 0x71F, CleverOperandKind::RelAddr, Main, {w @ .. => i8}],
794
795    [CBP1A , "jp" , 0x740, CleverOperandKind::AbsAddr, Main, {w @ .. => i8}],
796    [CBC1A , "jc" , 0x741, CleverOperandKind::AbsAddr, Main, {w @ .. => i8}],
797    [CBV1A , "jo" , 0x742, CleverOperandKind::AbsAddr, Main, {w @ .. => i8}],
798    [CBZ1A , "jz" , 0x743, CleverOperandKind::AbsAddr, Main, {w @ .. => i8}],
799    [CBL1A , "jlt", 0x744, CleverOperandKind::AbsAddr, Main, {w @ .. => i8}],
800    [CBLE1A, "jle", 0x745, CleverOperandKind::AbsAddr, Main, {w @ .. => i8}],
801    [CBBE1A, "jbe", 0x746, CleverOperandKind::AbsAddr, Main, {w @ .. => i8}],
802    [CBM1A , "jmi", 0x747, CleverOperandKind::AbsAddr, Main, {w @ .. => i8}],
803    [CBPS1A, "jps", 0x748, CleverOperandKind::AbsAddr, Main, {w @ .. => i8}],
804    [CBA1A , "ja" , 0x749, CleverOperandKind::AbsAddr, Main, {w @ .. => i8}],
805    [CBG1A , "jgt", 0x74A, CleverOperandKind::AbsAddr, Main, {w @ .. => i8}],
806    [CBGE1A, "jge", 0x74B, CleverOperandKind::AbsAddr, Main, {w @ .. => i8}],
807    [CBNZ1A, "jnz", 0x74C, CleverOperandKind::AbsAddr, Main, {w @ .. => i8}],
808    [CBNV1A, "jno", 0x74D, CleverOperandKind::AbsAddr, Main, {w @ .. => i8}],
809    [CBNC1A, "jnc", 0x74E, CleverOperandKind::AbsAddr, Main, {w @ .. => i8}],
810    [CBNP1A, "jnp", 0x74F, CleverOperandKind::AbsAddr, Main, {w @ .. => i8}],
811
812    [CBP1R , "jp" , 0x750, CleverOperandKind::RelAddr, Main, {w @ .. => i8}],
813    [CBC1R , "jc" , 0x751, CleverOperandKind::RelAddr, Main, {w @ .. => i8}],
814    [CBV1R , "jo" , 0x752, CleverOperandKind::RelAddr, Main, {w @ .. => i8}],
815    [CBZ1R , "jz" , 0x753, CleverOperandKind::RelAddr, Main, {w @ .. => i8}],
816    [CBL1R , "jlt", 0x754, CleverOperandKind::RelAddr, Main, {w @ .. => i8}],
817    [CBLE1R, "jle", 0x755, CleverOperandKind::RelAddr, Main, {w @ .. => i8}],
818    [CBBE1R, "jbe", 0x756, CleverOperandKind::RelAddr, Main, {w @ .. => i8}],
819    [CBM1R , "jmi", 0x757, CleverOperandKind::RelAddr, Main, {w @ .. => i8}],
820    [CBPS1R, "jps", 0x758, CleverOperandKind::RelAddr, Main, {w @ .. => i8}],
821    [CBA1R , "ja" , 0x759, CleverOperandKind::RelAddr, Main, {w @ .. => i8}],
822    [CBG1R , "jgt", 0x75A, CleverOperandKind::RelAddr, Main, {w @ .. => i8}],
823    [CBGE1R, "jge", 0x75B, CleverOperandKind::RelAddr, Main, {w @ .. => i8}],
824    [CBNZ1R, "jnz", 0x75C, CleverOperandKind::RelAddr, Main, {w @ .. => i8}],
825    [CBNV1R, "jno", 0x75D, CleverOperandKind::RelAddr, Main, {w @ .. => i8}],
826    [CBNC1R, "jnc", 0x75E, CleverOperandKind::RelAddr, Main, {w @ .. => i8}],
827    [CBNP1R, "jnp", 0x75F, CleverOperandKind::RelAddr, Main, {w @ .. => i8}],
828
829    [CBP2A , "jp" , 0x780, CleverOperandKind::AbsAddr, Main, {w @ .. => i8}],
830    [CBC2A , "jc" , 0x781, CleverOperandKind::AbsAddr, Main, {w @ .. => i8}],
831    [CBV2A , "jo" , 0x782, CleverOperandKind::AbsAddr, Main, {w @ .. => i8}],
832    [CBZ2A , "jz" , 0x783, CleverOperandKind::AbsAddr, Main, {w @ .. => i8}],
833    [CBL2A , "jlt", 0x784, CleverOperandKind::AbsAddr, Main, {w @ .. => i8}],
834    [CBLE2A, "jle", 0x785, CleverOperandKind::AbsAddr, Main, {w @ .. => i8}],
835    [CBBE2A, "jbe", 0x786, CleverOperandKind::AbsAddr, Main, {w @ .. => i8}],
836    [CBM2A , "jmi", 0x787, CleverOperandKind::AbsAddr, Main, {w @ .. => i8}],
837    [CBPS2A, "jps", 0x788, CleverOperandKind::AbsAddr, Main, {w @ .. => i8}],
838    [CBA2A , "ja" , 0x789, CleverOperandKind::AbsAddr, Main, {w @ .. => i8}],
839    [CBG2A , "jgt", 0x78A, CleverOperandKind::AbsAddr, Main, {w @ .. => i8}],
840    [CBGE2A, "jge", 0x78B, CleverOperandKind::AbsAddr, Main, {w @ .. => i8}],
841    [CBNZ2A, "jnz", 0x78C, CleverOperandKind::AbsAddr, Main, {w @ .. => i8}],
842    [CBNV2A, "jno", 0x78D, CleverOperandKind::AbsAddr, Main, {w @ .. => i8}],
843    [CBNC2A, "jnc", 0x78E, CleverOperandKind::AbsAddr, Main, {w @ .. => i8}],
844    [CBNP2A, "jnp", 0x78F, CleverOperandKind::AbsAddr, Main, {w @ .. => i8}],
845
846    [CBP2R , "jp" , 0x790, CleverOperandKind::RelAddr, Main, {w @ .. => i8}],
847    [CBC2R , "jc" , 0x791, CleverOperandKind::RelAddr, Main, {w @ .. => i8}],
848    [CBV2R , "jo" , 0x792, CleverOperandKind::RelAddr, Main, {w @ .. => i8}],
849    [CBZ2R , "jz" , 0x793, CleverOperandKind::RelAddr, Main, {w @ .. => i8}],
850    [CBL2R , "jlt", 0x794, CleverOperandKind::RelAddr, Main, {w @ .. => i8}],
851    [CBLE2R, "jle", 0x795, CleverOperandKind::RelAddr, Main, {w @ .. => i8}],
852    [CBBE2R, "jbe", 0x796, CleverOperandKind::RelAddr, Main, {w @ .. => i8}],
853    [CBM2R , "jmi", 0x797, CleverOperandKind::RelAddr, Main, {w @ .. => i8}],
854    [CBPS2R, "jps", 0x798, CleverOperandKind::RelAddr, Main, {w @ .. => i8}],
855    [CBA2R , "ja" , 0x799, CleverOperandKind::RelAddr, Main, {w @ .. => i8}],
856    [CBG2R , "jgt", 0x79A, CleverOperandKind::RelAddr, Main, {w @ .. => i8}],
857    [CBGE2R, "jge", 0x79B, CleverOperandKind::RelAddr, Main, {w @ .. => i8}],
858    [CBNZ2R, "jnz", 0x79C, CleverOperandKind::RelAddr, Main, {w @ .. => i8}],
859    [CBNV2R, "jno", 0x79D, CleverOperandKind::RelAddr, Main, {w @ .. => i8}],
860    [CBNC2R, "jnc", 0x79E, CleverOperandKind::RelAddr, Main, {w @ .. => i8}],
861    [CBNP2R, "jnp", 0x79F, CleverOperandKind::RelAddr, Main, {w @ .. => i8}],
862
863    // Unconditional Branches/Calls
864    [JmpA, "jmp", 0x7C0, CleverOperandKind::AbsAddr, Main, {ss @ 0..2 => u16}],
865    [CallA, "call", 0x7C1, CleverOperandKind::AbsAddr, Main, {ss @ 0..2 => u16}],
866    [FcallA, "fcall", 0x7C2, CleverOperandKind::AbsAddr, Main, {ss @ 0..2 => u16}],
867    [Ret, "ret", 0x7C3, CleverOperandKind::Normal(0), Main],
868    [Scall, "scall", 0x7C4, CleverOperandKind::Normal(0), Main],
869    [Int, "int", 0x7C5, CleverOperandKind::HImmediate, Main, {i @ .. => u16}],
870    [IjmpA, "ijmp", 0x7C8, CleverOperandKind::HRegister, Main, {r @ .. => CleverRegister}],
871    [IcallA, "icall", 0x7C9, CleverOperandKind::HRegister, Main, {r @ .. => CleverRegister}],
872    [IfcallA, "ifcall", 0x7CA, CleverOperandKind::HRegister, Main],
873    [JmpSM, "jsm", 0x7CB, CleverOperandKind::AbsAddr, Main, {ss @ 0..2 => u16}],
874    [CallSM, "callsm", 0x7CC, CleverOperandKind::AbsAddr, Main, {v @ 3 => bool, ss @ 0..2 => u16}],
875    [RetRSM, "retrsm", 0x7CD, CleverOperandKind::Normal(0), Main],
876    [JmpR, "jmp", 0x7D0, CleverOperandKind::AbsAddr, Main, {ss @ 0..2 => u16}],
877    [CallR, "call", 0x7D1, CleverOperandKind::AbsAddr, Main, {ss @ 0..2 => u16}],
878    [FcallR, "fcall", 0x7D2, CleverOperandKind::AbsAddr, Main, {ss @ 0..2 => u16}],
879    [IjmpR, "ijmp", 0x7D8, CleverOperandKind::HRegister, Main, {r @ .. => CleverRegister}],
880    [IcallR, "icall", 0x7D9, CleverOperandKind::HRegister, Main, {r @ .. => CleverRegister}],
881    [IfcallR, "ifcall", 0x7DA, CleverOperandKind::HRegister, Main],
882    [JmpSMR, "jsm", 0x7DB, CleverOperandKind::AbsAddr, Main, {ss @ 0..2 => u16}],
883    [CallSMR, "callsm", 0x7DC, CleverOperandKind::AbsAddr, Main, {ss @ 0..2 => u16, v @ 3 => bool}],
884
885    // Halt
886    [Halt, "halt", 0x801, CleverOperandKind::Normal(0), Main],
887
888    // Cache Control
889    [Pcfl, "pcfl", 0x802, CleverOperandKind::Normal(0), Main],
890    [FlAll, "flall", 0x803, CleverOperandKind::Normal(0), Main],
891    [Dflush, "dflush", 0x804, CleverOperandKind::Normal(1), Main],
892    [Iflush, "iflush", 0x805, CleverOperandKind::Normal(1), Main],
893
894    // I/O Transfers
895    [In, "in", 0x806, CleverOperandKind::Size, Main, {ss @ 0..2 => u16}],
896    [Out, "out", 0x807, CleverOperandKind::Size, Main, {ss @ 0..2 => u16}],
897
898    // Mass Register Storage
899    [StoRegF, "storegf", 0x808, CleverOperandKind::Normal(1), Main],
900    [RstRegF, "rstregf", 0x809, CleverOperandKind::Normal(1), Main],
901
902    // Supervisor Branches
903    [Scret, "scret", 0xFC6, CleverOperandKind::Normal(0), Main],
904    [Iret, "iret", 0xFC6, CleverOperandKind::Normal(0), Main],
905    [Hcall, "hcall", 0xFCB, CleverOperandKind::Normal(0), Main],
906    [Hret, "hret", 0xFD6, CleverOperandKind::Normal(0), Main],
907    [Hresume, "hresume", 0xFD7, CleverOperandKind::Normal(0), Main],
908
909    // VM Creation/Disposal
910    [VMCreate, "vmcreate", 0xFDA, CleverOperandKind::Normal(1), Virtualization],
911    [VMDestroy,"vmdestroy",0xFDB, CleverOperandKind::Normal(0), Virtualization],
912
913    [Und255, "und", 0xFFF, CleverOperandKind::Normal(0), Main]
914}
915
916macro_rules! prefix_valid_instructions{
917    ($($prefix:ident : {
918        $($insn:ident),*
919        $(,)?
920    })*) => {
921        impl CleverOpcode{
922            pub fn valid_prefix_for(&self, prefixed: &CleverOpcode) -> bool{
923                match (self,prefixed){
924                    $($((Self:: $prefix {..},Self:: $insn {..}) => true,)*)*
925                    #[allow(unreachable_patterns)] _ => false
926                }
927            }
928        }
929    }
930}
931
932prefix_valid_instructions! {
933    Repbc : { Bcpy, Bsto, Bsca, Bcmp, Btst, In, Out}
934    Repbi : { Bcpy, Bsto, Bsca, Bcmp, Btst, In, Out}
935    Vec : {Add, Sub, And, Or, Xor, Mov, MovRD, MovRS,
936         Lsh, Rsh, Arsh, Lshc, Rshc, Lrot, Rrot,
937         LshR, RshR, ArshR, LshcR, RshcR, LrotR, RrotR,
938         AddRD, SubRD, AndRD, OrRD, XorRD, BNot, Neg,
939         AddRS, SubRS, AndRS, OrRS, XorRS, BNotR, NegR,
940         Round, Ceil, Floor, FAbs, FNeg, FInv, FAdd, FSub, FMul, FDiv, FRem, FFma,
941         Exp, Ln, Lg, Sin, Cos, Tan, Asin, Acos, Atan, Exp2, Log10, Lnp1, Expm1, Sqrt,
942        }
943}
944
945macro_rules! gpr_specializations{
946    ($($base:ident : {
947        $left_spec:ident
948        $(, $right_spec:ident)?
949        $(,)?
950    })*) => {
951        impl CleverOpcode{
952            pub fn gpr_dest_specialization(&self,reg: CleverRegister) -> Option<CleverOpcode>{
953                match self{
954                    $(Self:: $base {..} => {
955                        Some(Self:: $left_spec {r: reg})
956                    },)*
957                    _ => None
958                }
959            }
960
961            pub fn gpr_src_specialization(&self,reg: CleverRegister) -> Option<CleverOpcode>{
962                match self{
963                    $($(Self:: $base {..} => {
964                        Some(Self:: $right_spec {r: reg})
965                    },)?)*
966                    _ => None
967                }
968            }
969
970            pub fn is_gpr_left_spec(&self) -> bool{
971                match self{
972                    $(Self::$left_spec {..} => {true},)*
973                    _ => false
974                }
975            }
976            pub fn is_gpr_right_spec(&self) -> bool{
977                match self{
978                    $($(Self::$right_spec {..} => {true},)?)*
979                    _ => false
980                }
981            }
982
983            pub fn get_spec_register(&self) -> Option<CleverRegister>{
984                match self{
985                    $(Self::$left_spec {r} => {Some(*r)},)*
986                    $($(Self::$right_spec {r} => {Some(*r)},)?)*
987                    _ => None
988                }
989            }
990        }
991    }
992}
993
994gpr_specializations! {
995    Add: {AddRD, AddRS}
996    Sub: {SubRD, SubRS}
997    And: {AndRD, AndRS}
998    Or:  {OrRD , OrRS }
999    Xor: {XorRD, XorRS}
1000    Mov: {MovRD, MovRS}
1001    Lea: {LeaRD}
1002    Lsh: {LshR}
1003    Rsh: {RshR}
1004    Arsh: {ArshR}
1005    Lshc: {LshcR}
1006    Rshc: {RshcR}
1007    Lrot: {LrotR}
1008    Rrot: {RrotR}
1009    Neg: {NegR}
1010    BNot: {BNotR}
1011}
1012
1013macro_rules! nop_instructions{
1014    ($($constant:ident: $var:ident),*) => {
1015        impl CleverOpcode{
1016            $(#[allow(non_upper_case_globals)] pub const $constant: Self = Self:: $var{any: 0};)*
1017        }
1018    }
1019}
1020
1021nop_instructions!(NOP0: Nop10, NOP1: Nop11, NOP2: Nop12, NOP3: Nop13);
1022
1023macro_rules! print_h_field{
1024    [$(($enum:ident {$($h:pat,)* $(, ..)?} => |$fmt:pat| $e:expr)),* $(,)?] => {
1025        impl core::fmt::Display for CleverOpcode{
1026            fn fmt(&self, f: &mut core::fmt::Formatter) -> core::fmt::Result{
1027                f.write_str(self.name())?;
1028
1029                match self{
1030                    $(Self:: $enum {$($h,)* ..} => (match f{
1031                        $fmt => $e
1032                    }),)*
1033                    _ => Ok(())
1034                }
1035            }
1036        }
1037    }
1038}
1039
1040print_h_field![];
1041
1042impl CleverOpcode {
1043    pub fn is_branch(&self) -> bool {
1044        (self.opcode() < 0xFD80) && (self.opcode() & 0x7200 == 0x7000)
1045    }
1046
1047    pub fn is_cbranch(&self) -> bool {
1048        matches!(self.opcode() & 0xFE00, 0x7000 | 0x7400 | 0x7800)
1049    }
1050
1051    pub fn branch_pcrel(&self) -> Option<bool> {
1052        if self.is_branch() {
1053            Some((self.opcode() & 0x100) != 0)
1054        } else {
1055            None
1056        }
1057    }
1058
1059    pub fn branch_set_relative(&self, isrel: bool) -> Option<CleverOpcode> {
1060        if self.is_branch() {
1061            let opc = (self.opcode() & !0x100) | (if isrel { 0x100 } else { 0x000 });
1062            CleverOpcode::from_opcode(opc)
1063        } else {
1064            None
1065        }
1066    }
1067
1068    pub fn branch_condition(&self) -> Option<ConditionCode> {
1069        match self.opcode() & 0xFE00 {
1070            0x7000 | 0x7400 | 0x7800 => Some(ConditionCode::from_bits((self.opcode() & 0xf0) >> 4)),
1071            _ => None,
1072        }
1073    }
1074
1075    pub fn branch_weight(&self) -> Option<i8> {
1076        match self.opcode() & 0xFE00 {
1077            0x7000 | 0x7400 | 0x7800 => Some(i8::from_bits(self.opcode() & 0xf)),
1078            _ => None,
1079        }
1080    }
1081
1082    pub fn branch_width(&self) -> Option<u16> {
1083        if self.opcode() & 0xFFF0 == 0x7C40 {
1084            return None;
1085        }
1086        match self.opcode() & 0xFE00 {
1087            0x7000 | 0x7400 | 0x7800 => Some(((self.opcode() & 0xC00) >> 10) + 1),
1088            0x7C00 => Some((self.opcode() & 0x2) + 1),
1089            _ => None,
1090        }
1091    }
1092
1093    pub fn cbranch(cc: ConditionCode, width: u16, pcrel: bool, weight: i8) -> Self {
1094        assert!(width - 1 < 3);
1095        let (width, pcrel, cc, weight) = (
1096            (width - 1) << 10,
1097            (pcrel as u16) << 8,
1098            cc.to_hbits() << 4,
1099            (weight & 0xf) as u16,
1100        );
1101
1102        Self::from_opcode(0x7000 | width | pcrel | cc | weight).unwrap()
1103    }
1104}
1105#[derive(Clone, Debug, Hash, PartialEq, Eq)]
1106pub enum CleverOperand {
1107    Register {
1108        size: u16,
1109        reg: CleverRegister,
1110    },
1111    Indirect {
1112        size: u16,
1113        base: CleverRegister,
1114        scale: u8,
1115        index: CleverIndex,
1116    },
1117    VecPair {
1118        size: u16,
1119        lo: CleverRegister,
1120    },
1121    Immediate(CleverImmediate),
1122}
1123
1124#[derive(Clone, Debug, Hash, PartialEq, Eq)]
1125pub enum CleverImmediate {
1126    Short(u16),
1127    ShortRel(i16),
1128    ShortAddr(Address),
1129    ShortAddrRel(Address),
1130    Long(u16, u64),
1131    LongRel(u16, i64),
1132    LongAddr(u16, Address),
1133    LongAddrRel(u16, Address),
1134    LongMem(u16, Address, u16),
1135    LongMemRel(u16, Address, u16),
1136    Vec(u128),
1137}
1138
1139impl CleverImmediate {
1140    pub fn addr(&self) -> Option<(u64, &Address, bool)> {
1141        match self {
1142            CleverImmediate::ShortAddr(addr) => Some((12, addr, false)),
1143            CleverImmediate::ShortAddrRel(addr) => Some((12, addr, true)),
1144            CleverImmediate::LongAddr(addrsize, addr) => Some((u64::from(*addrsize), addr, false)),
1145            CleverImmediate::LongAddrRel(addrsize, addr) => {
1146                Some((u64::from(*addrsize), addr, false))
1147            }
1148            CleverImmediate::LongMem(addrsize, addr, _) => {
1149                Some((u64::from(*addrsize), addr, false))
1150            }
1151            CleverImmediate::LongMemRel(addrsize, addr, _) => {
1152                Some((u64::from(*addrsize), addr, false))
1153            }
1154            _ => None,
1155        }
1156    }
1157
1158    pub fn is_short(&self) -> bool {
1159        matches!(
1160            self,
1161            Self::Short(_) | Self::ShortRel(_) | Self::ShortAddr(_) | Self::ShortAddrRel(_)
1162        )
1163    }
1164}
1165
1166fn write_immediate_size(size: u16, f: &mut core::fmt::Formatter) -> core::fmt::Result {
1167    match size {
1168        8 => f.write_str("byte"),
1169        16 => f.write_str("half"),
1170        32 => f.write_str("single"),
1171        64 => f.write_str("double"),
1172        128 => f.write_str("quad"),
1173        n => f.write_fmt(format_args!("<invalid-size {}>", n)),
1174    }
1175}
1176
1177impl core::fmt::Display for CleverImmediate {
1178    fn fmt(&self, f: &mut core::fmt::Formatter) -> core::fmt::Result {
1179        match self {
1180            CleverImmediate::Short(s) => f.write_fmt(format_args!("short {}", s)),
1181            CleverImmediate::ShortRel(s) => f.write_fmt(format_args!("short {}+ip", s)),
1182            CleverImmediate::ShortAddr(addr) => f.write_fmt(format_args!("short {}", addr)),
1183            CleverImmediate::ShortAddrRel(addr) => f.write_fmt(format_args!("short {}+ip", addr)),
1184            CleverImmediate::Long(size, val) => {
1185                write_immediate_size(*size, f)?;
1186                f.write_fmt(format_args!(" {}", val))
1187            }
1188            CleverImmediate::LongRel(size, val) => {
1189                write_immediate_size(*size, f)?;
1190                f.write_fmt(format_args!(" {}+ip", val))
1191            }
1192            CleverImmediate::LongAddr(size, val) => {
1193                write_immediate_size(*size, f)?;
1194                f.write_fmt(format_args!(" {}", val))
1195            }
1196            CleverImmediate::LongAddrRel(size, val) => {
1197                write_immediate_size(*size, f)?;
1198                f.write_fmt(format_args!(" {}+ip", val))
1199            }
1200            CleverImmediate::LongMem(asize, val, refsize) => {
1201                write_immediate_size(*refsize, f)?;
1202                f.write_str(" [")?;
1203                write_immediate_size(*asize, f)?;
1204                f.write_fmt(format_args!(" {}]", val))
1205            }
1206            CleverImmediate::LongMemRel(asize, val, refsize) => {
1207                write_immediate_size(*refsize, f)?;
1208                f.write_str(" [")?;
1209                write_immediate_size(*asize, f)?;
1210                f.write_fmt(format_args!(" {}+ip]", val))
1211            }
1212            CleverImmediate::Vec(v) => f.write_fmt(format_args!("quad {}", v)),
1213        }
1214    }
1215}
1216
1217impl CleverOperand {
1218    pub fn size(&self) -> u16 {
1219        match self {
1220            CleverOperand::Register { size, .. } => *size,
1221            CleverOperand::VecPair { size, .. } => *size,
1222            CleverOperand::Indirect { size, .. } => *size,
1223            CleverOperand::Immediate(
1224                CleverImmediate::Short(_)
1225                | CleverImmediate::ShortRel(_)
1226                | CleverImmediate::ShortAddr(_)
1227                | CleverImmediate::ShortAddrRel(_),
1228            ) => 12,
1229            CleverOperand::Immediate(
1230                CleverImmediate::Long(size, _)
1231                | CleverImmediate::LongRel(size, _)
1232                | CleverImmediate::LongAddr(size, _)
1233                | CleverImmediate::LongAddrRel(size, _),
1234            ) => *size,
1235            CleverOperand::Immediate(CleverImmediate::Vec(_)) => 16,
1236            CleverOperand::Immediate(
1237                CleverImmediate::LongMem(_, _, size) | CleverImmediate::LongMemRel(_, _, size),
1238            ) => *size,
1239        }
1240    }
1241
1242    pub fn size_ss(&self) -> Option<u16> {
1243        match self.size() {
1244            8 => Some(0),
1245            12 => None,
1246            16 => Some(1),
1247            32 => Some(2),
1248            64 => Some(3),
1249            128 => Some(4),
1250            size => panic!("Invalid register size {:?}", size),
1251        }
1252    }
1253
1254    pub fn as_control_structure(&self) -> u16 {
1255        match self {
1256            CleverOperand::Register { size, reg } => {
1257                let ss = match size {
1258                    8 => 0,
1259                    16 => 1,
1260                    32 => 2,
1261                    64 => 3,
1262                    size => panic!("Invalid register size {:?}", size),
1263                };
1264
1265                let r = reg.0 as u16;
1266                (ss << 8) | r
1267            }
1268            CleverOperand::Indirect {
1269                size,
1270                base,
1271                scale,
1272                index,
1273            } => {
1274                let ss = match size {
1275                    8 => 0,
1276                    16 => 1,
1277                    32 => 2,
1278                    64 => 3,
1279                    size => panic!("Invalid register size {:?}", size),
1280                };
1281
1282                let ll = match scale {
1283                    1 => 0,
1284                    2 => 1,
1285                    4 => 2,
1286                    8 => 3,
1287                    16 => 4,
1288                    32 => 5,
1289                    64 => 6,
1290                    128 => 7,
1291                    scale => panic!("Invalid scale {:?}", scale),
1292                };
1293
1294                let (o, k) = match index {
1295                    CleverIndex::Abs(val) => ((*val as u16) & 0xf, 1),
1296                    CleverIndex::Register(r) => ((r.0 as u16) & 0xf, 0),
1297                };
1298
1299                0x4000 | (o << 10) | (ll << 7) | (k << 6) | (ss << 4) | ((base.0 as u16) & 0xf)
1300            }
1301            CleverOperand::Immediate(imm) => match imm {
1302                CleverImmediate::Short(val) => 0x8000 | (*val),
1303                CleverImmediate::ShortRel(val) => 0x9000 | (*val as u16),
1304                CleverImmediate::ShortAddr(_) => 0x8000,
1305                CleverImmediate::ShortAddrRel(_) => 0x9000,
1306                CleverImmediate::Long(size, _) => {
1307                    let ss = match size {
1308                        16 => 0,
1309                        32 => 1,
1310                        64 => 2,
1311                        size => panic!("Invalid Immediate size {:?}", size),
1312                    };
1313
1314                    0xC000 | (ss << 8)
1315                }
1316                CleverImmediate::LongRel(size, _) => {
1317                    let ss = match size {
1318                        16 => 0,
1319                        32 => 1,
1320                        64 => 2,
1321                        size => panic!("Invalid Immediate size {:?}", size),
1322                    };
1323
1324                    0xC400 | (ss << 8)
1325                }
1326                CleverImmediate::LongAddr(size, _) => {
1327                    let ss = match size {
1328                        16 => 0,
1329                        32 => 1,
1330                        64 => 2,
1331                        size => panic!("Invalid Immediate size {:?}", size),
1332                    };
1333
1334                    0xC000 | (ss << 8)
1335                }
1336                CleverImmediate::LongAddrRel(size, _) => {
1337                    let ss = match size {
1338                        16 => 0,
1339                        32 => 1,
1340                        64 => 2,
1341                        size => panic!("Invalid Immediate size {:?}", size),
1342                    };
1343
1344                    0xC400 | (ss << 8)
1345                }
1346                CleverImmediate::LongMem(size, _, refsize) => {
1347                    let ss = match size {
1348                        16 => 0,
1349                        32 => 1,
1350                        64 => 2,
1351                        size => panic!("Invalid Immediate size {:?}", size),
1352                    };
1353
1354                    let zz = match refsize {
1355                        8 => 0,
1356                        16 => 1,
1357                        32 => 2,
1358                        64 => 3,
1359                        128 => 4,
1360                        size => panic!("Invalid reference size {:?}", size),
1361                    };
1362
1363                    0xE000 | (ss << 8) | (zz << 4)
1364                }
1365                CleverImmediate::LongMemRel(size, _, refsize) => {
1366                    let ss = match size {
1367                        16 => 0,
1368                        32 => 1,
1369                        64 => 2,
1370                        size => panic!("Invalid Immediate size {:?}", size),
1371                    };
1372
1373                    let zz = match refsize {
1374                        8 => 0,
1375                        16 => 1,
1376                        32 => 2,
1377                        64 => 3,
1378                        128 => 4,
1379                        size => panic!("Invalid reference size {:?}", size),
1380                    };
1381
1382                    0xE400 | (ss << 8) | (zz << 4)
1383                }
1384                CleverImmediate::Vec(_) => 0xC300,
1385            },
1386            CleverOperand::VecPair { size, lo } => {
1387                let ss = match size {
1388                    8 => 0,
1389                    16 => 1,
1390                    32 => 2,
1391                    64 => 3,
1392                    128 => 4,
1393                    size => panic!("Invalid register size {:?}", size),
1394                };
1395
1396                let r = lo.0 as u16;
1397                0x2000 | (ss << 8) | r
1398            }
1399        }
1400    }
1401
1402    pub fn immediate_value(&self) -> Option<&CleverImmediate> {
1403        match self {
1404            Self::Immediate(imm) => Some(imm),
1405            _ => None,
1406        }
1407    }
1408}
1409
1410impl core::fmt::Display for CleverOperand {
1411    fn fmt(&self, f: &mut core::fmt::Formatter) -> core::fmt::Result {
1412        match self {
1413            CleverOperand::Register { size, reg } => {
1414                write_immediate_size(*size, f)?;
1415                f.write_fmt(format_args!(" {}", reg))
1416            }
1417            CleverOperand::Indirect {
1418                size,
1419                base,
1420                scale: _,
1421                index: CleverIndex::Abs(0),
1422            } => {
1423                write_immediate_size(*size, f)?;
1424                f.write_fmt(format_args!("[{}]", base))
1425            }
1426            CleverOperand::Indirect {
1427                size,
1428                base,
1429                scale: 1,
1430                index,
1431            } => {
1432                write_immediate_size(*size, f)?;
1433                f.write_fmt(format_args!("[{}+{}]", index, base))
1434            }
1435            CleverOperand::Indirect {
1436                size,
1437                base,
1438                scale,
1439                index,
1440            } => {
1441                write_immediate_size(*size, f)?;
1442                f.write_fmt(format_args!("[{}*{}+{}]", scale, index, base))
1443            }
1444            CleverOperand::VecPair { size, lo } => {
1445                write_immediate_size(*size, f)?;
1446                f.write_fmt(format_args!(" {}", lo))
1447            }
1448            CleverOperand::Immediate(imm) => imm.fmt(f),
1449        }
1450    }
1451}
1452
1453#[derive(Clone, Debug, Hash, PartialEq, Eq)]
1454pub struct CleverInstruction {
1455    prefix: Option<CleverOpcode>,
1456    opcode: CleverOpcode,
1457    operands: Vec<CleverOperand>,
1458}
1459
1460impl CleverInstruction {
1461    pub const fn new(opcode: CleverOpcode, operands: Vec<CleverOperand>) -> Self {
1462        Self {
1463            prefix: None,
1464            opcode,
1465            operands,
1466        }
1467    }
1468    pub const fn new_prefixed(
1469        prefix: CleverOpcode,
1470        opcode: CleverOpcode,
1471        operands: Vec<CleverOperand>,
1472    ) -> Self {
1473        Self {
1474            prefix: Some(prefix),
1475            opcode,
1476            operands,
1477        }
1478    }
1479
1480    pub fn prefix(&self) -> Option<CleverOpcode> {
1481        self.prefix
1482    }
1483
1484    pub fn opcode(&self) -> CleverOpcode {
1485        self.opcode
1486    }
1487
1488    pub fn operands(&self) -> &[CleverOperand] {
1489        &self.operands
1490    }
1491
1492    pub fn set_prefix(&mut self, prefix: CleverOpcode) {
1493        self.prefix = Some(prefix);
1494    }
1495}
1496
1497impl core::fmt::Display for CleverInstruction {
1498    fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
1499        self.opcode().fmt(f)?;
1500
1501        match self.opcode().operands() {
1502            CleverOperandKind::Size => {
1503                let ss = self.opcode().opcode() & 0x3;
1504                match ss {
1505                    0 => f.write_str(" byte")?,
1506                    1 => f.write_str(" half")?,
1507                    2 => f.write_str(" single")?,
1508                    3 => f.write_str(" double")?,
1509                    _ => unreachable!(),
1510                }
1511            }
1512            CleverOperandKind::HImmediate => {
1513                let h = self.opcode().opcode() & 0xf;
1514                f.write_str(" ")?;
1515                h.fmt(f)?;
1516            }
1517            CleverOperandKind::HRegister => {
1518                let h = self.opcode().opcode() & 0xf;
1519                let r = CleverRegister(h as u8);
1520                f.write_str(" ")?;
1521                r.fmt(f)?;
1522            }
1523            _ => {
1524                let mut sep = " ";
1525
1526                if self.opcode().is_gpr_left_spec() {
1527                    sep = ", ";
1528                    f.write_str(" ")?;
1529                    self.opcode().get_spec_register().unwrap().fmt(f)?;
1530                }
1531                for opr in self.operands() {
1532                    f.write_str(sep)?;
1533                    sep = ", ";
1534                    opr.fmt(f)?;
1535                }
1536                if self.opcode().is_gpr_right_spec() {
1537                    f.write_str(sep)?;
1538                    self.opcode().get_spec_register().unwrap().fmt(f)?;
1539                }
1540            }
1541        }
1542
1543        Ok(())
1544    }
1545}
1546
1547pub struct CleverEncoder<W> {
1548    inner: W,
1549}
1550
1551impl<W> CleverEncoder<W> {
1552    pub const fn new(inner: W) -> Self {
1553        Self { inner }
1554    }
1555
1556    pub fn into_inner(self) -> W {
1557        self.inner
1558    }
1559
1560    pub fn inner_mut(&mut self) -> &mut W {
1561        &mut self.inner
1562    }
1563
1564    pub fn inner(&self) -> &W {
1565        &self.inner
1566    }
1567}
1568
1569impl<W: Write> Write for CleverEncoder<W> {
1570    fn write(&mut self, buf: &[u8]) -> std::io::Result<usize> {
1571        self.inner.write(buf)
1572    }
1573
1574    fn flush(&mut self) -> std::io::Result<()> {
1575        self.inner.flush()
1576    }
1577}
1578
1579impl<W: InsnWrite> InsnWrite for CleverEncoder<W> {
1580    fn write_addr(&mut self, size: usize, addr: Address, rel: bool) -> std::io::Result<()> {
1581        self.inner.write_addr(size, addr, rel)
1582    }
1583
1584    fn write_reloc(&mut self, reloc: crate::traits::Reloc) -> std::io::Result<()> {
1585        self.inner.write_reloc(reloc)
1586    }
1587
1588    fn offset(&self) -> usize {
1589        self.inner.offset()
1590    }
1591}
1592
1593impl<W: InsnWrite> CleverEncoder<W> {
1594    pub fn write_instruction(&mut self, insn: CleverInstruction) -> std::io::Result<()> {
1595        if let Some(prefix) = insn.prefix() {
1596            self.write_all(&prefix.opcode().to_be_bytes())?;
1597        }
1598        self.write_all(&insn.opcode().opcode().to_be_bytes())?;
1599        match insn.opcode().operands(){
1600            CleverOperandKind::Size | CleverOperandKind::HRegister | CleverOperandKind::HImmediate => {
1601                assert_eq!(insn.operands().len(),0);
1602            }
1603            CleverOperandKind::Normal(n) => {
1604                assert_eq!(insn.operands().len(), n as usize);
1605
1606                for op in insn.operands(){
1607                    let operand = op.as_control_structure();
1608
1609                    let imm = op.immediate_value();
1610
1611                    if let Some(imm) = imm{
1612                        match imm{
1613                            CleverImmediate::ShortAddr(Address::Abs(addr)) => self.write_all(&(operand | u16::try_from(*addr).unwrap()).to_be_bytes())?,
1614                            CleverImmediate::ShortAddrRel(Address::Disp(addr)) => self.write_all(&(operand | u16::try_from(*addr).unwrap()).to_be_bytes())?,
1615                            CleverImmediate::ShortAddr(addr) => {
1616                                let relocc = RelocCode::CleverShort;
1617                                let reloc = match addr{
1618                                    Address::Abs(_) => unreachable!(),
1619                                    Address::Disp(_) => todo!("Non-symbol short relocation"),
1620                                    Address::Symbol { name, disp } => {
1621                                        Reloc{
1622                                            code: relocc,
1623                                            symbol: name.clone(),
1624                                            addend: Some(*disp),
1625                                            offset: self.offset() as u64
1626                                        }
1627                                    },
1628                                    Address::PltSym { name: _ } => panic!("Cannot use explicit short relocation against GOT or PLT"),
1629                                };
1630                                self.write_all(&(operand.to_be_bytes()))?;
1631                                self.write_reloc(reloc)?;
1632                            },
1633                            CleverImmediate::ShortAddrRel(addr) => {
1634                                let relocc = RelocCode::CleverShortPcrel;
1635                                let reloc = match addr{
1636                                    Address::Abs(val) => Reloc { code: relocc, symbol: "*ABS*".to_string(), addend: Some(*val as i64), offset: self.offset() as u64},
1637                                    Address::Disp(_) => unreachable!(),
1638                                    Address::Symbol { name, disp } => {
1639                                        Reloc{
1640                                            code: relocc,
1641                                            symbol: name.clone(),
1642                                            addend: Some(*disp),
1643                                            offset: self.offset() as u64
1644                                        }
1645                                    },
1646                                    Address::PltSym { name: _ } => panic!("Cannot use explicit short relocation against GOT or PLT"),
1647                                };
1648                                self.write_all(&(operand.to_be_bytes()))?;
1649                                self.write_reloc(reloc)?;
1650                            },
1651                            CleverImmediate::Long(size, val) => {
1652                                let val_bytes = &(*val).to_le_bytes()[..((*size/8) as usize)];
1653                                self.write_all(&operand.to_be_bytes())?;
1654                                self.write_all(val_bytes)?;
1655                            }
1656                            CleverImmediate::LongRel(size, val) => {
1657                                let val_bytes = &(*val).to_le_bytes()[..((*size/8) as usize)];
1658                                self.write_all(&operand.to_be_bytes())?;
1659                                self.write_all(val_bytes)?;
1660                            }
1661                            CleverImmediate::LongAddr(size, addr) | CleverImmediate::LongMem(size,addr,_) => {
1662                                self.write_all(&operand.to_be_bytes())?;
1663                                self.write_addr(*size as usize, addr.clone(), false)?;
1664                            }
1665                            CleverImmediate::LongAddrRel(size, addr) | CleverImmediate::LongMemRel(size,addr,_) => {
1666                                self.write_all(&operand.to_be_bytes())?;
1667                                self.write_addr(*size as usize, addr.clone(), true)?;
1668                            }
1669                            CleverImmediate::Vec(vec) => {
1670                                self.write_all(&operand.to_be_bytes())?;
1671                                self.write_all(&vec.to_le_bytes())?;
1672                            }
1673                            _ => self.write_all(&operand.to_be_bytes())?
1674                        }
1675                    }else{
1676                        self.write_all(&operand.to_be_bytes())?;
1677                    }
1678                }
1679            },
1680            CleverOperandKind::AbsAddr => {
1681                assert_eq!(insn.operands().len(),1);
1682
1683                let imm = insn.operands()[0].immediate_value()
1684                    .unwrap();
1685
1686                let width = insn.opcode().branch_width().unwrap();
1687                match imm{
1688                    CleverImmediate::Long(_, a) => {
1689                        self.write_all(&((*a).to_be_bytes()[..(1<<width)]))?;
1690                    }
1691                    CleverImmediate::LongAddr(_, addr) => {
1692                        self.write_addr((8<<width) as usize, addr.clone(), false)?;
1693                    }
1694                    CleverImmediate::LongAddrRel(_, addr) => {
1695                        self.write_addr((8<<width) as usize, addr.clone(), false)?;
1696                    }
1697                    a => panic!("Got wrong operand type for a branch {:?}",a)
1698                }
1699            },
1700            CleverOperandKind::RelAddr => {
1701                assert_eq!(insn.operands().len(),1);
1702                let imm = insn.operands()[0].immediate_value()
1703                    .unwrap();
1704
1705                let width = insn.opcode().branch_width().unwrap();
1706
1707                match imm{
1708                    CleverImmediate::LongRel(_, a) => {
1709                        self.write_all(&((*a).to_be_bytes()[..(1<<width)]))?;
1710                    }
1711                    CleverImmediate::LongAddrRel(_, addr) => {
1712                        self.write_addr((8<<width) as usize, addr.clone(), true)?;
1713                    }
1714                    a => panic!("Got wrong operand type for a branch {:?}",a)
1715                }
1716            },
1717            CleverOperandKind::Insn => panic!("Cannot write a prefix as a primary instruction, use `CleverInstruction::new_with_prefix` instead"),
1718        }
1719        Ok(())
1720    }
1721}
1722
1723pub struct CleverDecoder<R> {
1724    inner: R,
1725}
1726
1727impl<R> CleverDecoder<R> {
1728    pub const fn new(inner: R) -> Self {
1729        Self { inner }
1730    }
1731
1732    pub fn into_inner(self) -> R {
1733        self.inner
1734    }
1735
1736    pub fn inner_mut(&mut self) -> &mut R {
1737        &mut self.inner
1738    }
1739
1740    pub fn inner(&self) -> &R {
1741        &self.inner
1742    }
1743}
1744
1745impl<R: Read> Read for CleverDecoder<R> {
1746    fn read(&mut self, buf: &mut [u8]) -> std::io::Result<usize> {
1747        self.inner.read(buf)
1748    }
1749}
1750
1751impl<R: InsnRead> InsnRead for CleverDecoder<R> {
1752    fn read_addr(&mut self, size: usize, rel: bool) -> std::io::Result<Address> {
1753        self.inner.read_addr(size, rel)
1754    }
1755
1756    fn read_reloc(
1757        &mut self,
1758        size: usize,
1759        rel: bool,
1760        offset: Option<isize>,
1761    ) -> std::io::Result<Option<Address>> {
1762        self.inner.read_reloc(size, rel, offset)
1763    }
1764}
1765
1766impl<R: InsnRead> CleverDecoder<R> {
1767    pub fn read_insn(&mut self) -> std::io::Result<CleverInstruction> {
1768        let mut opcode = [0u8; 2];
1769        self.read_exact(&mut opcode)?;
1770        let opcode = u16::from_be_bytes(opcode);
1771        let op = CleverOpcode::from_opcode(opcode).ok_or_else(|| {
1772            std::io::Error::new(
1773                ErrorKind::InvalidData,
1774                format!("Invalid opcode {:#x}", opcode),
1775            )
1776        })?;
1777        match op.operands() {
1778            CleverOperandKind::Insn => {
1779                let mut inner = self.read_insn()?;
1780                if let Some(prefix) = inner.prefix {
1781                    return Err(std::io::Error::new(
1782                        ErrorKind::InvalidData,
1783                        format!("Cannot combine multiple prefixes {:?} and {:?}", op, prefix),
1784                    ));
1785                } else {
1786                    inner.prefix = Some(op);
1787                }
1788                Ok(inner)
1789            }
1790            CleverOperandKind::Size
1791            | CleverOperandKind::HRegister
1792            | CleverOperandKind::HImmediate => Ok(CleverInstruction::new(op, Vec::new())),
1793            kind @ (CleverOperandKind::AbsAddr | CleverOperandKind::RelAddr) => {
1794                let bytes = 8 << (op.branch_width().unwrap() as u32);
1795                let rel = kind == CleverOperandKind::RelAddr;
1796                let addr = self.read_addr(bytes, rel)?;
1797
1798                Ok(CleverInstruction::new(
1799                    op,
1800                    vec![CleverOperand::Immediate(CleverImmediate::LongAddr(
1801                        bytes as u16,
1802                        addr,
1803                    ))],
1804                ))
1805            }
1806            CleverOperandKind::Normal(n) => {
1807                let mut ops = Vec::with_capacity(n as usize);
1808
1809                for _ in 0..n {
1810                    let mut ctrl = [0u8; 2];
1811                    self.read_exact(&mut ctrl)?;
1812                    let ctrl = u16::from_be_bytes(ctrl);
1813
1814                    let opr = match ctrl >> 14 {
1815                        0b00 => {
1816                            let v = (ctrl & 0x2000) != 0;
1817
1818                            let reg = CleverRegister(ctrl as u8);
1819
1820                            let ss = 8 << ((ctrl >> 8) & 0x7);
1821
1822                            if v {
1823                                CleverOperand::VecPair { size: ss, lo: reg }
1824                            } else {
1825                                CleverOperand::Register { size: ss, reg }
1826                            }
1827                        }
1828                        0b01 => {
1829                            let offset = (ctrl >> 10) & 0xf;
1830
1831                            let scale = 1 << ((ctrl >> 7) & 0x7);
1832
1833                            let ss = 8 << ((ctrl >> 4) & 0x3) as u32;
1834
1835                            let k = (ctrl & 0x40) != 0;
1836
1837                            let base = CleverRegister((ctrl & 0xf) as u8);
1838
1839                            let index = if k {
1840                                CleverIndex::Abs(offset as i16)
1841                            } else {
1842                                CleverIndex::Register(CleverRegister(offset as u8))
1843                            };
1844
1845                            CleverOperand::Indirect {
1846                                size: ss,
1847                                base,
1848                                scale,
1849                                index,
1850                            }
1851                        }
1852                        0b10 => {
1853                            let short = ctrl & 0xfff;
1854
1855                            let rel = (ctrl & 0x1000) != 0;
1856
1857                            let addr = self.read_reloc(12, rel, Some(-2))?;
1858
1859                            let imm = match (addr, rel) {
1860                                (Some(addr), true) => CleverImmediate::ShortAddrRel(addr),
1861                                (Some(addr), false) => CleverImmediate::ShortAddr(addr),
1862                                (None, true) => CleverImmediate::ShortRel(short as i16),
1863                                (None, false) => CleverImmediate::Short(short),
1864                            };
1865
1866                            CleverOperand::Immediate(imm)
1867                        }
1868                        0b11 => {
1869                            let mem = (ctrl & 0x2000) != 0;
1870                            let rel = (ctrl & 0x400) != 0;
1871                            let size = 8 << (1 + ((ctrl >> 8) & 0x3));
1872
1873                            let zize = 8 << ((ctrl >> 4) & 0xf);
1874
1875                            let val = self.read_addr(size as usize, rel)?;
1876
1877                            let imm = match (val, rel, mem) {
1878                                (Address::Abs(val), false, false) if size == 128 => {
1879                                    CleverImmediate::Vec(val)
1880                                }
1881                                _ if size == 128 => {
1882                                    return Err(std::io::Error::new(
1883                                        ErrorKind::InvalidData,
1884                                        "invalid immediate with size 128",
1885                                    ))
1886                                }
1887                                (Address::Disp(val), true, false) => {
1888                                    CleverImmediate::LongRel(size, val)
1889                                }
1890                                (Address::Abs(val), false, false) => {
1891                                    CleverImmediate::Long(size, val as u64)
1892                                }
1893                                (addr, true, false) => CleverImmediate::LongAddrRel(size, addr),
1894                                (addr, false, false) => CleverImmediate::LongAddr(size, addr),
1895                                (addr, true, true) => CleverImmediate::LongMemRel(size, addr, zize),
1896                                (addr, false, true) => CleverImmediate::LongMem(size, addr, zize),
1897                            };
1898
1899                            CleverOperand::Immediate(imm)
1900                        }
1901                        _ => unreachable!(),
1902                    };
1903
1904                    ops.push(opr);
1905                }
1906
1907                Ok(CleverInstruction::new(op, ops))
1908            }
1909        }
1910    }
1911}
1912
1913#[non_exhaustive]
1914#[derive(Clone, Debug, Hash, PartialEq, Eq)]
1915pub struct CleverPrinter {}
1916
1917impl CleverPrinter {
1918    pub const fn new() -> Self {
1919        Self {}
1920    }
1921}
1922
1923impl Default for CleverPrinter {
1924    fn default() -> Self {
1925        Self::new()
1926    }
1927}
1928
1929impl OpcodePrinter for CleverPrinter {
1930    fn print_opcode(
1931        &self,
1932        f: &mut core::fmt::Formatter,
1933        read: &mut dyn InsnRead,
1934    ) -> std::io::Result<()> {
1935        let insn = CleverDecoder::new(read).read_insn()?;
1936
1937        <CleverInstruction as core::fmt::Display>::fmt(&insn, f).unwrap();
1938        Ok(())
1939    }
1940}
1941
1942#[cfg(test)]
1943mod test {
1944    use crate::test::TestWriter;
1945
1946    use super::*;
1947    #[test]
1948    pub fn test_encode_nop() {
1949        let mut encoder = CleverEncoder::new(TestWriter { inner: Vec::new() });
1950        encoder
1951            .write_instruction(CleverInstruction::new(CleverOpcode::NOP0, vec![]))
1952            .unwrap();
1953
1954        assert_eq!(&*encoder.inner_mut().inner, &[0x01, 0x00]);
1955    }
1956
1957    #[test]
1958    pub fn test_encode_nop1() {
1959        let mut encoder = CleverEncoder::new(TestWriter { inner: Vec::new() });
1960        encoder
1961            .write_instruction(CleverInstruction::new(
1962                CleverOpcode::NOP1,
1963                vec![CleverOperand::Register {
1964                    size: 64,
1965                    reg: CleverRegister::r0,
1966                }],
1967            ))
1968            .unwrap();
1969
1970        assert_eq!(&*encoder.inner_mut().inner, &[0x01, 0x10, 0x03, 0x00]);
1971    }
1972
1973    #[test]
1974    pub fn test_encode_nop1_simm() {
1975        let mut encoder = CleverEncoder::new(TestWriter { inner: Vec::new() });
1976        encoder
1977            .write_instruction(CleverInstruction::new(
1978                CleverOpcode::NOP1,
1979                vec![CleverOperand::Immediate(CleverImmediate::Short(1337))],
1980            ))
1981            .unwrap();
1982
1983        assert_eq!(&*encoder.inner_mut().inner, &[0x01, 0x10, 0x85, 0x39]);
1984    }
1985
1986    #[test]
1987    pub fn test_encode_nop2() {
1988        let mut encoder = CleverEncoder::new(TestWriter { inner: Vec::new() });
1989        encoder
1990            .write_instruction(CleverInstruction::new(
1991                CleverOpcode::NOP2,
1992                vec![
1993                    CleverOperand::Register {
1994                        size: 64,
1995                        reg: CleverRegister::flags,
1996                    },
1997                    CleverOperand::Immediate(CleverImmediate::Long(16, 1337)),
1998                ],
1999            ))
2000            .unwrap();
2001
2002        assert_eq!(
2003            &*encoder.inner_mut().inner,
2004            &[0x01, 0x20, 0x03, 0x11, 0xC0, 0x00, 0x39, 0x05]
2005        );
2006    }
2007
2008    #[test]
2009
2010    pub fn test_encode_branch() {
2011        let mut encoder = CleverEncoder::new(TestWriter { inner: Vec::new() });
2012        encoder
2013            .write_instruction(CleverInstruction::new(
2014                CleverOpcode::cbranch(ConditionCode::Zero, 1, true, 0),
2015                vec![CleverOperand::Immediate(CleverImmediate::LongAddrRel(
2016                    16,
2017                    Address::Disp(-32),
2018                ))],
2019            ))
2020            .unwrap();
2021
2022        assert_eq!(
2023            &*encoder.inner().inner,
2024            &[0x71, 0x30, 0xe0, 0xff],
2025            "{:x?} != {:x?}",
2026            encoder.inner().inner,
2027            [0x71, 0x30, 0xe0, 0xff]
2028        );
2029    }
2030}