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 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 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}