Skip to content

Commit

Permalink
Merge branch 'main' of https://github.com/Cr0a3/ygen
Browse files Browse the repository at this point in the history
  • Loading branch information
Cr0a3 committed Oct 28, 2024
2 parents aff5b8f + bac42b6 commit d28c00b
Show file tree
Hide file tree
Showing 5 changed files with 223 additions and 92 deletions.
107 changes: 97 additions & 10 deletions src/Target/x64/asm/instr.rs
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,8 @@ pub struct X64MCInstr {
pub op1: Option<Operand>,
/// Second operand
pub op2: Option<Operand>,
/// Third operand
pub op3: Option<Operand>,

// for far calls
pub(crate) far: bool,
Expand All @@ -28,6 +30,7 @@ impl X64MCInstr {
mnemonic: mne,
op1: None,
op2: None,
op3: None,
far: false,
}
}
Expand All @@ -38,6 +41,7 @@ impl X64MCInstr {
mnemonic: self.mnemonic.to_owned(),
op1: self.op1.to_owned(),
op2: self.op2.to_owned(),
op3: self.op3.to_owned(),
far: true,
}
}
Expand All @@ -48,6 +52,7 @@ impl X64MCInstr {
mnemonic: mne,
op1: Some(op),
op2: None,
op3: None,
far: false,
}
}
Expand All @@ -58,6 +63,18 @@ impl X64MCInstr {
mnemonic: mne,
op1: Some(op1),
op2: Some(op2),
op3: None,
far: false,
}
}

/// Creates the instruction with 3 operands
pub fn with3(mne: Mnemonic, op1: Operand, op2: Operand, op3: Operand) -> Self {
Self {
mnemonic: mne,
op1: Some(op1),
op2: Some(op2),
op3: Some(op3),
far: false,
}
}
Expand Down Expand Up @@ -563,15 +580,49 @@ impl X64MCInstr {
Mnemonic::Ret => Instruction::with(Code::Retnq),
Mnemonic::Imul => {
if let Some(Operand::Reg(op1)) = &self.op1 {
if op1.is_gr64() {
Instruction::with1::<Register>(Code::Imul_rm64, (*op1).into())?
} else if op1.is_gr32() {
Instruction::with1::<Register>(Code::Imul_rm32, (*op1).into())?
} else if op1.is_gr16() {
Instruction::with1::<Register>(Code::Imul_rm16, (*op1).into())?
} else if op1.is_gr8() {
Instruction::with1::<Register>(Code::Imul_rm8, (*op1).into())?
} else { todo!("{}", self)}
if let Some(Operand::Reg(op2)) = &self.op2 {
if let Some(Operand::Imm(op3)) = &self.op3 {
if op1.is_gr16() {
Instruction::with3::<Register, Register, i32>(Code::Imul_r16_rm16_imm16, (*op1).into(), (*op2).into(), *op3 as i32)?
} else if op1.is_gr32() {
Instruction::with3::<Register, Register, i32>(Code::Imul_r32_rm32_imm32, (*op1).into(), (*op2).into(), *op3 as i32)?
} else if op1.is_gr64() {
Instruction::with3::<Register, Register, i32>(Code::Imul_r64_rm64_imm32, (*op1).into(), (*op2).into(), *op3 as i32)?
} else { todo!("{}", self)}
} else if op1.is_gr64() {
Instruction::with2::<Register, Register>(Code::Imul_r64_rm64, (*op1).into(), (*op2).into())?
} else if op1.is_gr32() {
Instruction::with2::<Register, Register>(Code::Imul_r32_rm32, (*op1).into(), (*op2).into())?
} else if op1.is_gr16() {
Instruction::with2::<Register, Register>(Code::Imul_r16_rm16, (*op1).into(), (*op2).into())?
} else { todo!("{}", self)}
} else if let Some(Operand::Mem(op2)) = &self.op2 {
if let Some(Operand::Imm(op3)) = &self.op3 {
if op1.is_gr16() {
Instruction::with3::<Register, MemoryOperand, i32>(Code::Imul_r16_rm16_imm16, (*op1).into(), op2.into(), *op3 as i32)?
} else if op1.is_gr32() {
Instruction::with3::<Register, MemoryOperand, i32>(Code::Imul_r32_rm32_imm32, (*op1).into(), op2.into(), *op3 as i32)?
} else if op1.is_gr64() {
Instruction::with3::<Register, MemoryOperand, i32>(Code::Imul_r64_rm64_imm32, (*op1).into(), op2.into(), *op3 as i32)?
} else { todo!("{}", self)}
} else if op1.is_gr64() {
Instruction::with2::<Register, MemoryOperand>(Code::Imul_r64_rm64, (*op1).into(), op2.into())?
} else if op1.is_gr32() {
Instruction::with2::<Register, MemoryOperand>(Code::Imul_r32_rm32, (*op1).into(), op2.into())?
} else if op1.is_gr16() {
Instruction::with2::<Register, MemoryOperand>(Code::Imul_r16_rm16, (*op1).into(), op2.into())?
} else { todo!("{}", self)}
} else {
if op1.is_gr64() {
Instruction::with1::<Register>(Code::Imul_rm64, (*op1).into())?
} else if op1.is_gr32() {
Instruction::with1::<Register>(Code::Imul_rm32, (*op1).into())?
} else if op1.is_gr16() {
Instruction::with1::<Register>(Code::Imul_rm16, (*op1).into())?
} else if op1.is_gr8() {
Instruction::with1::<Register>(Code::Imul_rm8, (*op1).into())?
} else { todo!("{}", self)}
}
} else if let Some(Operand::Mem(op1)) = &self.op1 {
Instruction::with1::<MemoryOperand>(Code::Imul_rm64, op1.into())?
} else { todo!("{}", self) }
Expand Down Expand Up @@ -1119,7 +1170,10 @@ impl X64MCInstr {
} else { todo!("{}", self) }
} else { todo!("{}", self) }
},

Mnemonic::Cbw => Instruction::with(Code::Cbw),
Mnemonic::Cwd => Instruction::with(Code::Cwd),
Mnemonic::Cdq => Instruction::with(Code::Cdq),
Mnemonic::Cqo => Instruction::with(Code::Cqo),
};

//instr.as_near_branch();
Expand Down Expand Up @@ -1247,6 +1301,9 @@ impl Display for X64MCInstr {
string.push_str(&format!(" {}", op1));
if let Some(op2) = &self.op2 {
string.push_str(&format!(", {}", op2));
if let Some(op3) = &self.op3 {
string.push_str(&format!(", {}", op3));
}
}
}

Expand Down Expand Up @@ -1361,6 +1418,11 @@ pub enum Mnemonic {
Jl,
Jge,
Jle,

Cbw,
Cwd,
Cdq,
Cqo,
}

impl FromStr for Mnemonic {
Expand Down Expand Up @@ -1428,6 +1490,10 @@ impl FromStr for Mnemonic {
"jl" => Ok(Mnemonic::Jl),
"jge" => Ok(Mnemonic::Jge),
"jle" => Ok(Mnemonic::Jle),
"cbw" => Ok(Mnemonic::Cbw),
"cwd" => Ok(Mnemonic::Cwd),
"cdq" => Ok(Mnemonic::Cdq),
"cqo" => Ok(Mnemonic::Cqo),
_ => Err(()),
}
}
Expand Down Expand Up @@ -1500,6 +1566,10 @@ impl Display for Mnemonic {
Mnemonic::Jl => "jl",
Mnemonic::Jge => "jge",
Mnemonic::Jle => "jle",
Mnemonic::Cbw => "cbw",
Mnemonic::Cwd => "cwd",
Mnemonic::Cdq => "cdq",
Mnemonic::Cqo => "cqo",
})
}
}
Expand All @@ -1523,6 +1593,23 @@ pub enum Operand {
RipRelative(String),
}

impl Operand {
/// Returns if the operand is a register
pub fn is_reg(&self) -> bool {
matches!(self, Operand::Reg(_))
}

/// Returns if the operand is a imm
pub fn is_imm(&self) -> bool {
matches!(self, Operand::Imm(_))
}

/// Returns if the operand is a memory displacmenet or rip relative
pub fn is_mem(&self) -> bool {
matches!(self, Operand::Mem(_) | Operand::RipRelative(_))
}
}

impl PartialEq for Operand {
fn eq(&self, other: &Self) -> bool {
match (self, other) {
Expand Down
28 changes: 25 additions & 3 deletions src/Target/x64/asm/parser.rs
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,7 @@ impl x64Parser {
mnemonic: mne,
op1: None,
op2: None,
op3: None,
far: false,
};

Expand All @@ -68,6 +69,7 @@ impl x64Parser {
self.tokens.pop_front(); // advance over ]
}

let mut second_op = false;
if first_op {
if let Some(Token::Comma) = self.tokens.front() {
self.tokens.pop_front(); // advance
Expand All @@ -83,11 +85,31 @@ impl x64Parser {
self.tokens.pop_front(); // advance
} else if let Some(Token::L_Bracket) = self.tokens.front() {
instr.op2 = Some(Operand::Mem(self.parse_mem()?));
}else {
} else {
Err(ParsingError::CommaWithoutOperandAfter)?
}
}
second_op = true;
}

if second_op {
if let Some(Token::Comma) = self.tokens.front() {
self.tokens.pop_front(); // advance
if let Some(Token::Num(n)) = self.tokens.front() {
instr.op3 = Some(Operand::Imm(*n));
self.tokens.pop_front(); // advance
} else if let Some(Token::Ident(reg)) = self.tokens.front() {
if let Some(reg) = X64Reg::parse(reg.to_string()) {
instr.op3 = Some(Operand::Reg(reg))
} else {
Err(ParsingError::UnknownRegOrUnexpectedIdent(reg.to_string()))?
}
self.tokens.pop_front(); // advance
} else if let Some(Token::L_Bracket) = self.tokens.front() {
instr.op3 = Some(Operand::Mem(self.parse_mem()?));
} else {
Err(ParsingError::CommaWithoutOperandAfter)?
}
} else if self.tokens.len() > 0 {
Err(ParsingError::UnexpectedTokens(self.tokens.clone().into()))?
}
} else if self.tokens.len() > 0 {
Err(ParsingError::UnexpectedTokens(self.tokens.clone().into()))?
Expand Down
9 changes: 7 additions & 2 deletions src/Target/x64/compilation.rs
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,11 @@ pub(crate) fn construct_compilation_helper(call_conv: CallConv) -> CompilationHe
alloc.free_registers.push(Arch::X86_64, Reg::x64(X64Reg::R12));
alloc.free_registers.push(Arch::X86_64, Reg::x64(X64Reg::R13));
alloc.free_registers.push(Arch::X86_64, Reg::x64(X64Reg::R14));
alloc.free_registers.push(Arch::X86_64, Reg::x64(X64Reg::R15));

// Used as temporary storage
// alloc.free_registers.push(Arch::X86_64, Reg::x64(X64Reg::Rax));
// alloc.free_registers.push(Arch::X86_64, Reg::x64(X64Reg::Rbx));
// alloc.free_registers.push(Arch::X86_64, Reg::x64(X64Reg::R15));

alloc.free_fpregs.push(Arch::X86_64, Reg::x64(X64Reg::Xmm0));
alloc.free_fpregs.push(Arch::X86_64, Reg::x64(X64Reg::Xmm1));
Expand All @@ -37,11 +41,12 @@ pub(crate) fn construct_compilation_helper(call_conv: CallConv) -> CompilationHe
alloc.free_fpregs.push(Arch::X86_64, Reg::x64(X64Reg::Xmm11));
alloc.free_fpregs.push(Arch::X86_64, Reg::x64(X64Reg::Xmm12));
alloc.free_fpregs.push(Arch::X86_64, Reg::x64(X64Reg::Xmm13));

// Used as temporary storage
// alloc.free_fpregs.push(Arch::X86_64, Reg::x64(x64Reg::Xmm14));
// alloc.free_fpregs.push(Arch::X86_64, Reg::x64(x64Reg::Xmm15));
alloc.free_fpregs.reverse(Arch::X86_64);

alloc.free_fpregs.reverse(Arch::X86_64);
alloc.free_registers.reverse(Arch::X86_64);

let mut helper = CompilationHelper::new(
Expand Down
Loading

0 comments on commit d28c00b

Please sign in to comment.