Skip to main content

citadel_backend/asm/elements/
mod.rs

1//! This module contains data structures and ast-like representations
2//! of assembly concepts. This is used to represent the assembly
3//! the compiler outputs.
4
5pub 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    /// Returns size in bytes
20    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    // 64 bit
94    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    // 32 bit
114    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    // 16 bit
134    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    // 8 bit
154    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}