1pub mod traits;
6
7use super::codegen::CodeGenerator;
8
9#[derive(Debug, Clone, PartialEq)]
10pub enum AsmElement {
11 Label(Label),
12 Instruction(Instruction),
13 Directive(Directive),
14 Operand(Operand),
15 Declaration(Declaration),
16}
17
18pub trait Size {
19 fn size(&self) -> u8;
21}
22
23#[derive(Debug, Clone, PartialEq)]
24pub struct Directive {
25 pub _type: DirectiveType,
26}
27
28#[derive(Debug, Clone, PartialEq)]
29pub enum Declaration {
30 Global(String),
31 DefineBytes(String, Literal, Option<u8>),
32}
33
34#[derive(Debug, Clone, PartialEq)]
35pub struct Label {
36 pub name: String,
37}
38
39#[derive(Debug, Clone, PartialEq)]
40pub struct Instruction {
41 pub opcode: Opcode,
42 pub args: Vec<Operand>,
43}
44
45#[derive(Debug, Clone, PartialEq)]
46pub enum DirectiveType {
47 Data,
48 Rodata,
49 Text,
50}
51
52#[derive(Debug, Clone, PartialEq)]
53pub enum Operand {
54 Ident(String),
55 Register(Register),
56 MemAddr(MemAddr),
57 Literal(Literal),
58 SizedLiteral(SizedLiteral),
59}
60
61#[derive(Debug, Clone, PartialEq)]
62pub struct SizedLiteral(pub Literal, pub DataSize);
63
64#[derive(Debug, Clone, PartialEq)]
65pub enum DataSize {
66 Byte,
67 Word,
68 DWord,
69 QWord,
70}
71
72#[derive(Debug, Clone, PartialEq)]
73pub enum MemAddr {
74 Register(Register),
75 RegisterPos(Register, i32),
76 Literal(Literal),
77 Ident(String),
78}
79
80#[derive(Debug, Clone, Copy, PartialEq)]
81pub enum Literal {
82 Int8(i8),
83 Int16(i16),
84 Int32(i32),
85 Int64(i64),
86
87 Float32(f32),
88 Float64(f64),
89}
90
91#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
92pub enum Register {
93 Rax,
95 Rbx,
96 Rcx,
97 Rdx,
98
99 Rsi,
100 Rdi,
101 Rsp,
102 Rbp,
103
104 R8,
105 R9,
106 R10,
107 R11,
108 R12,
109 R13,
110 R14,
111 R15,
112
113 Eax,
115 Ebx,
116 Ecx,
117 Edx,
118
119 Edi,
120 Esi,
121 Ebp,
122 Esp,
123
124 R8d,
125 R9d,
126 R10d,
127 R11d,
128 R12d,
129 R13d,
130 R14d,
131 R15d,
132
133 Ax,
135 Bx,
136 Cx,
137 Dx,
138
139 Si,
140 Di,
141 Sp,
142 Bp,
143
144 R8w,
145 R9w,
146 R10w,
147 R11w,
148 R12w,
149 R13w,
150 R14w,
151 R15w,
152
153 Al,
155 Bl,
156 Cl,
157 Dl,
158
159 Sil,
160 Dil,
161 Spl,
162 Bpl,
163
164 R8b,
165 R9b,
166 R10b,
167 R11b,
168 R12b,
169 R13b,
170 R14b,
171 R15b,
172}
173
174#[derive(Debug, Clone, PartialEq)]
175pub enum Opcode {
176 Mov,
177 Syscall,
178
179 Add,
180 Sub,
181 Mul,
182 Div,
183
184 And,
185 Or,
186 XOr,
187 Not,
188 Cmp,
189
190 Jmp,
191 JE,
192 JNe,
193 JZ,
194 JNz,
195
196 Call,
197 Ret,
198
199 Push,
200 Pop,
201
202 Shl,
203 Shr,
204
205 Movsb,
206 Movsw,
207 Int,
208
209 Fadd,
210 Fsub,
211 FMul,
212 FDiv,
213
214 FCmp,
215 FAbs,
216
217 Dec,
218 Inc,
219}
220
221pub trait BuiltinFunction {
222 fn generate(&self, codegen: &mut CodeGenerator);
223
224 fn name(&self) -> &str;
225}
226
227#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
228pub enum StdFunction {
229 Print,
230}
231
232impl BuiltinFunction for StdFunction {
233 fn generate(&self, codegen: &mut CodeGenerator) {
234 match self {
235 Self::Print => builtins::generate_print(codegen),
236 }
237 }
238
239 fn name(&self) -> &str {
240 match self {
241 Self::Print => "print",
242 }
243 }
244}
245
246pub(super) mod builtins {
247 use crate::asm::{codegen::CodeGenerator, utils::codegen as cutils};
248
249 use super::{AsmElement, Declaration, Label, Literal, MemAddr, Operand, Register};
250
251 pub fn generate_print(codegen: &mut CodeGenerator) {
252 let out = &mut codegen.out;
253
254 codegen.data.push(Declaration::DefineBytes(
255 "msg".into(),
256 Literal::Int8(8),
257 None,
258 ));
259
260 let instructions = vec![
261 AsmElement::Label(Label {
262 name: "print".to_string(),
263 }),
264 cutils::gen_mov_ins(
265 Operand::MemAddr(MemAddr::Ident("msg".to_string())),
266 Operand::Register(Register::Rsi),
267 ),
268 cutils::gen_mov_ins(
269 Operand::Register(Register::Rsi),
270 Operand::Ident("msg".to_string()),
271 ),
272 cutils::gen_mov_ins(
273 Operand::Register(Register::Rax),
274 Operand::Literal(Literal::Int32(1)),
275 ),
276 cutils::gen_mov_ins(
277 Operand::Register(Register::Rdi),
278 Operand::Literal(Literal::Int32(1)),
279 ),
280 cutils::gen_syscall(),
281 cutils::gen_ret(),
282 ];
283
284 out.extend(instructions);
285 }
286}