dynasm\arch\x64/
x64data.rs

1use std::collections::{HashMap, hash_map};
2
3use super::compiler::Opdata;
4use std::fmt::{self, Display};
5
6use lazy_static::lazy_static;
7use bitflags::bitflags;
8
9macro_rules! constify {
10    ($t:ty, $e:expr) => { {const C: &$t = &$e; C} }
11}
12
13macro_rules! OpInner {
14    ($fmt:expr, $ops:expr, $reg:expr)          => { Opdata {args: $fmt, ops: constify!([u8], $ops), reg: $reg, flags: Flags::DEFAULT,  features: Features::X64_IMPLICIT}  };
15    ($fmt:expr, $ops:expr, $reg:expr, $f:expr) => { Opdata {args: $fmt, ops: constify!([u8], $ops), reg: $reg, flags: Flags::make($f), features: Features::X64_IMPLICIT}  };
16    ($fmt:expr, $ops:expr, $reg:expr, $f:expr, $ft:expr) => { Opdata {args: $fmt, ops: constify!([u8], $ops), reg: $reg, flags: Flags::make($f), features: Features::make($ft)}  };
17
18}
19
20macro_rules! Ops {
21    ( $( $name:tt = [ $( $( $e:expr ),+ ; )+ ] )* ) => {
22        [ $(
23            (
24                $name,
25                {
26                    const OPDATA: &[Opdata] = &[$( OpInner!($( $e ),*) ,)+];
27                    OPDATA
28                }
29            )
30        ),* ]
31    };
32}
33
34pub fn get_mnemnonic_data(name: &str) -> Option<&'static [Opdata]> {
35    OPMAP.get(&name).cloned()
36}
37
38bitflags! {
39    #[derive(Clone, Copy, Debug, Default, Eq, Hash, Ord, PartialEq, PartialOrd)]
40    pub struct Flags: u32 {
41        const DEFAULT   = 0x0000_0000; // this instruction has default encoding
42        const VEX_OP    = 0x0000_0001; // this instruction requires a VEX prefix to be encoded
43        const XOP_OP    = 0x0000_0002; // this instruction requires a XOP prefix to be encoded
44        const IMM_OP    = 0x0000_0004; // this instruction encodes the final opcode byte in the immediate position, like 3DNow! ops.
45
46        // note: the first 4 in this block are mutually exclusive
47        const AUTO_SIZE = 0x0000_0008; // 16 bit -> OPSIZE , 32-bit -> None     , 64-bit -> REX.W/VEX.W/XOP.W
48        const AUTO_NO32 = 0x0000_0010; // 16 bit -> OPSIZE , 32-bit -> None(x86), 64-bit -> None(x64)
49        const AUTO_REXW = 0x0000_0020; // 16 bit -> illegal, 32-bit -> None     , 64-bit -> REX.W/VEX.W/XOP.W
50        const AUTO_VEXL = 0x0000_0040; // 128bit -> None   , 256bit -> VEX.L
51        const WORD_SIZE = 0x0000_0080; // implies opsize prefix
52        const WITH_REXW = 0x0000_0100; // implies REX.W/VEX.W/XOP.W
53        const WITH_VEXL = 0x0000_0200; // implies VEX.L/XOP.L
54        const EXACT_SIZE= 0x0000_0400; // operands with unknown sizes cannot be assumed to match
55
56        const PREF_66   = WORD_SIZE;   // mandatory prefix (same as WORD_SIZE)
57        const PREF_67   = 0x0000_0800; // mandatory prefix (same as SMALL_ADDRESS)
58        const PREF_F0   = 0x0000_1000; // mandatory prefix (same as LOCK)
59        const PREF_F2   = 0x0000_2000; // mandatory prefix (REPNE)
60        const PREF_F3   = 0x0000_4000; // mandatory prefix (REP)
61
62        const LOCK      = 0x0000_8000; // user lock prefix is valid with this instruction
63        const REP       = 0x0001_0000; // user rep prefix is valid with this instruction
64        const REPE      = 0x0002_0000;
65
66        const SHORT_ARG = 0x0004_0000; // a register argument is encoded in the last byte of the opcode
67        const ENC_MR    = 0x0008_0000; // select alternate arg encoding
68        const ENC_VM    = 0x0010_0000; // select alternate arg encoding
69        const ENC_MIB   = 0x0020_0000; // A special encoding using the SIB to specify an immediate and two registers
70        const X86_ONLY  = 0x0040_0000; // instructions available in protected mode, but not long mode
71    }
72}
73
74impl Flags {
75    const fn make(bits: u32) -> Flags {
76        Flags::from_bits_truncate(bits)
77    }
78}
79
80bitflags! {
81    #[derive(Clone, Copy, Debug, Default, Eq, Hash, Ord, PartialEq, PartialOrd)]
82    pub struct Features: u32 {
83        const X64_IMPLICIT = 0x0000_0000;
84        const FPU          = 0x0000_0001;
85          const MMX          = 0x0000_0002;
86        const TDNOW        = 0x0000_0004;
87        const SSE          = 0x0000_0008;
88        const SSE2         = 0x0000_0010;
89        const SSE3         = 0x0000_0020;
90        const VMX          = 0x0000_0040;
91        const SSSE3        = 0x0000_0080;
92        const SSE4A        = 0x0000_0100;
93        const SSE41        = 0x0000_0200;
94        const SSE42        = 0x0000_0400;
95        const SSE5         = 0x0000_0800;
96        const AVX          = 0x0000_1000;
97        const AVX2         = 0x0000_2000;
98        const FMA          = 0x0000_4000;
99        const BMI1         = 0x0000_8000;
100        const BMI2         = 0x0001_0000;
101        const TBM          = 0x0002_0000;
102        const RTM          = 0x0004_0000;
103        const INVPCID      = 0x0008_0000;
104        const MPX          = 0x0010_0000;
105        const SHA          = 0x0020_0000;
106        const PREFETCHWT1  = 0x0040_0000;
107        const CYRIX        = 0x0080_0000;
108        const AMD          = 0x0100_0000;
109        const DIRECTSTORES = 0x0200_0000;
110    }
111}
112
113impl Features {
114    const fn make(bits: u32) -> Features {
115        Features::from_bits_truncate(bits)
116    }
117
118    pub fn from_str(name: &str) -> Option<Features> {
119        match name {
120            "fpu"   => Some(Features::FPU),
121            "mmx"   => Some(Features::MMX),
122            "tdnow" => Some(Features::TDNOW),
123            "sse"   => Some(Features::SSE),
124            "sse2"  => Some(Features::SSE2),
125            "sse3"  => Some(Features::SSE3),
126            "vmx"   => Some(Features::VMX),
127            "ssse3" => Some(Features::SSSE3),
128            "sse4a" => Some(Features::SSE4A),
129            "sse41" => Some(Features::SSE41),
130            "sse42" => Some(Features::SSE42),
131            "sse5"  => Some(Features::SSE5),
132            "avx"   => Some(Features::AVX),
133            "avx2"  => Some(Features::AVX2),
134            "fma"   => Some(Features::FMA),
135            "bmi1"  => Some(Features::BMI1),
136            "bmi2"  => Some(Features::BMI2),
137            "tbm"   => Some(Features::TBM),
138            "rtm"   => Some(Features::RTM),
139            "invpcid" => Some(Features::INVPCID),
140            "mpx"   => Some(Features::MPX),
141            "sha"   => Some(Features::SHA),
142            "prefetchwt1" => Some(Features::PREFETCHWT1),
143            "cyrix" => Some(Features::CYRIX),
144            "amd"   => Some(Features::AMD),
145            "directstores"   => Some(Features::DIRECTSTORES),
146            _ => None
147        }
148    }
149}
150
151impl Display for Features {
152    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
153        let mut keys = Vec::new();
154        if self.contains(Features::FPU)   { keys.push("fpu"); }
155        if self.contains(Features::MMX)   { keys.push("mmx"); }
156        if self.contains(Features::TDNOW) { keys.push("tdnow"); }
157        if self.contains(Features::SSE)   { keys.push("sse"); }
158        if self.contains(Features::SSE2)  { keys.push("sse2"); }
159        if self.contains(Features::SSE3)  { keys.push("sse3"); }
160        if self.contains(Features::VMX)   { keys.push("vmx"); }
161        if self.contains(Features::SSSE3) { keys.push("ssse3"); }
162        if self.contains(Features::SSE4A) { keys.push("sse4a"); }
163        if self.contains(Features::SSE41) { keys.push("sse41"); }
164        if self.contains(Features::SSE42) { keys.push("sse42"); }
165        if self.contains(Features::SSE5)  { keys.push("sse5"); }
166        if self.contains(Features::AVX)   { keys.push("avx"); }
167        if self.contains(Features::AVX2)  { keys.push("avx2"); }
168        if self.contains(Features::FMA)   { keys.push("fma"); }
169        if self.contains(Features::BMI1)  { keys.push("bmi1"); }
170        if self.contains(Features::BMI2)  { keys.push("bmi2"); }
171        if self.contains(Features::TBM)   { keys.push("tbm"); }
172        if self.contains(Features::RTM)   { keys.push("rtm"); }
173        if self.contains(Features::INVPCID) { keys.push("invpcid"); }
174        if self.contains(Features::MPX)   { keys.push("mpx"); }
175        if self.contains(Features::SHA)   { keys.push("sha"); }
176        if self.contains(Features::PREFETCHWT1) { keys.push("prefetchwt1"); }
177        if self.contains(Features::CYRIX) { keys.push("cyrix"); }
178        if self.contains(Features::AMD)   { keys.push("amd"); }
179        if self.contains(Features::DIRECTSTORES)   { keys.push("directstores"); }
180        for (i, k) in keys.into_iter().enumerate() {
181            if i != 0 {
182                f.write_str(", ")?;
183            }
184            f.write_str(k)?;
185        }
186        Ok(())
187    }
188}
189
190#[allow(dead_code)]
191pub fn mnemnonics() -> hash_map::Keys<'static, &'static str, &'static [Opdata]> {
192    OPMAP.keys()
193}
194
195// workaround until bitflags can be used in const
196const DEFAULT    : u32 = Flags::DEFAULT.bits();
197const VEX_OP     : u32 = Flags::VEX_OP.bits();
198const XOP_OP     : u32 = Flags::XOP_OP.bits();
199const IMM_OP     : u32 = Flags::IMM_OP.bits();
200const SHORT_ARG  : u32 = Flags::SHORT_ARG.bits();
201const AUTO_SIZE  : u32 = Flags::AUTO_SIZE.bits();
202const AUTO_NO32  : u32 = Flags::AUTO_NO32.bits();
203const AUTO_REXW  : u32 = Flags::AUTO_REXW.bits();
204const AUTO_VEXL  : u32 = Flags::AUTO_VEXL.bits();
205const WORD_SIZE  : u32 = Flags::WORD_SIZE.bits();
206const WITH_REXW  : u32 = Flags::WITH_REXW.bits();
207const WITH_VEXL  : u32 = Flags::WITH_VEXL.bits();
208const EXACT_SIZE : u32 = Flags::EXACT_SIZE.bits();
209const PREF_66    : u32 = Flags::PREF_66.bits();
210const PREF_67    : u32 = Flags::PREF_67.bits();
211const PREF_F0    : u32 = Flags::PREF_F0.bits();
212const PREF_F2    : u32 = Flags::PREF_F2.bits();
213const PREF_F3    : u32 = Flags::PREF_F3.bits();
214const LOCK       : u32 = Flags::LOCK.bits();
215const REP        : u32 = Flags::REP.bits();
216const REPE       : u32 = Flags::REPE.bits();
217const ENC_MR     : u32 = Flags::ENC_MR.bits();
218const ENC_VM     : u32 = Flags::ENC_VM.bits();
219const ENC_MIB    : u32 = Flags::ENC_MIB.bits();
220const X86_ONLY   : u32 = Flags::X86_ONLY.bits();
221
222#[allow(dead_code)]
223const X64_IMPLICIT : u32 = Features::X64_IMPLICIT.bits();
224const FPU          : u32 = Features::FPU.bits();
225const MMX          : u32 = Features::MMX.bits();
226const TDNOW        : u32 = Features::TDNOW.bits();
227const SSE          : u32 = Features::SSE.bits();
228const SSE2         : u32 = Features::SSE2.bits();
229const SSE3         : u32 = Features::SSE3.bits();
230const VMX          : u32 = Features::VMX.bits();
231const SSSE3        : u32 = Features::SSSE3.bits();
232const SSE4A        : u32 = Features::SSE4A.bits();
233const SSE41        : u32 = Features::SSE41.bits();
234const SSE42        : u32 = Features::SSE42.bits();
235const SSE5         : u32 = Features::SSE5.bits();
236const AVX          : u32 = Features::AVX.bits();
237const AVX2         : u32 = Features::AVX2.bits();
238const FMA          : u32 = Features::FMA.bits();
239const BMI1         : u32 = Features::BMI1.bits();
240const BMI2         : u32 = Features::BMI2.bits();
241const TBM          : u32 = Features::TBM.bits();
242const RTM          : u32 = Features::RTM.bits();
243const INVPCID      : u32 = Features::INVPCID.bits();
244const MPX          : u32 = Features::MPX.bits();
245const SHA          : u32 = Features::SHA.bits();
246const PREFETCHWT1  : u32 = Features::PREFETCHWT1.bits();
247const CYRIX        : u32 = Features::CYRIX.bits();
248const AMD          : u32 = Features::AMD.bits();
249const DIRECTSTORES : u32 = Features::DIRECTSTORES.bits();
250
251
252lazy_static! {
253    static ref OPMAP: HashMap<&'static str, &'static [Opdata]> = {
254        const X: u8 = 0xFF;
255        static MAP: &[(&str, &[Opdata])] = &include!("gen_opmap.rs");
256        MAP.iter().cloned().collect()
257    };
258}