dynasm\arch\x64/
mod.rs

1use syn::parse;
2use proc_macro_error2::emit_error;
3
4mod ast;
5mod compiler;
6mod parser;
7mod debug;
8mod x64data;
9
10use crate::State;
11use crate::arch::Arch;
12use crate::common::{Size, Stmt, Jump};
13
14#[cfg(feature = "dynasm_opmap")]
15pub use debug::create_opmap;
16
17#[derive(Debug, Clone, Copy, PartialEq, Eq)]
18pub enum X86Mode {
19    Long,
20    Protected
21}
22
23struct Context<'a, 'b: 'a> {
24    pub state: &'a mut State<'b>,
25    pub mode: X86Mode,
26    pub features: x64data::Features
27}
28
29#[derive(Clone, Debug)]
30pub struct Archx64 {
31    features: x64data::Features
32}
33
34impl Default for Archx64 {
35    fn default() -> Archx64 {
36        Archx64 { features: x64data::Features::all() }
37    }
38}
39
40impl Arch for Archx64 {
41    fn set_features(&mut self, features: &[syn::Ident]) {
42        let mut new_features = x64data::Features::empty();
43        for ident in features {
44            new_features |= match x64data::Features::from_str(&ident.to_string()) {
45                Some(feature) => feature,
46                None => {
47                    emit_error!(ident, "Architecture x64 does not support feature '{}'", ident);
48                    continue;
49                }
50            }
51        }
52        self.features = new_features;
53    }
54
55    fn handle_static_reloc(&self, stmts: &mut Vec<Stmt>, reloc: Jump, size: Size) {
56        stmts.push(Stmt::Const(0, size));
57        // field_offset of size. Relative to the start of the field so matching ref_offset. Type is size and relative
58        stmts.push(reloc.encode(size.in_bytes(), size.in_bytes(), &[size.in_bytes(), 0]));
59    }
60
61    fn default_align(&self) -> u8 {
62        0x90
63    }
64
65    fn compile_instruction(&self, state: &mut State, input: parse::ParseStream) -> parse::Result<()> {
66        let mut ctx = Context {
67            state,
68            mode: X86Mode::Long,
69            features: self.features
70        };
71        let (instruction, args) = parser::parse_instruction(&mut ctx, input)?;
72        let span = instruction.span;
73
74        if let Err(Some(e)) = compiler::compile_instruction(&mut ctx, instruction, args) {
75            emit_error!(span, e);
76        }
77        Ok(())
78    }
79}
80
81#[derive(Clone, Debug)]
82pub struct Archx86 {
83    features: x64data::Features
84}
85
86impl Default for Archx86 {
87    fn default() -> Archx86 {
88        Archx86 { features: x64data::Features::all() }
89    }
90}
91
92impl Arch for Archx86 {
93    fn set_features(&mut self, features: &[syn::Ident]) {
94        let mut new_features = x64data::Features::empty();
95        for ident in features {
96            new_features |= match x64data::Features::from_str(&ident.to_string()) {
97                Some(feature) => feature,
98                None => {
99                    emit_error!(ident, "Architecture x86 does not support feature '{}'", ident);
100                    continue;
101                }
102            }
103        }
104        self.features = new_features;
105    }
106
107    fn handle_static_reloc(&self, stmts: &mut Vec<Stmt>, reloc: Jump, size: Size) {
108        stmts.push(Stmt::Const(0, size));
109        // field_offset of size. Relative to the start of the field so matching ref_offset. Type is simply the size.
110        stmts.push(reloc.encode(size.in_bytes(), size.in_bytes(), &[size.in_bytes()]));
111    }
112
113    fn default_align(&self) -> u8 {
114        0x90
115    }
116
117    fn compile_instruction(&self, state: &mut State, input: parse::ParseStream) -> parse::Result<()> {
118        let mut ctx = Context {
119            state,
120            mode: X86Mode::Protected,
121            features: self.features
122        };
123        let (instruction, args) = parser::parse_instruction(&mut ctx, input)?;
124        let span = instruction.span;
125
126        if let Err(Some(e)) = compiler::compile_instruction(&mut ctx, instruction, args) {
127            emit_error!(span, e);
128        }
129        Ok(())
130    }
131}