Skip to content

Commit

Permalink
[x64] implementing lea, mov
Browse files Browse the repository at this point in the history
  • Loading branch information
Cr0a3 committed Aug 4, 2024
1 parent 39af83f commit 39018df
Show file tree
Hide file tree
Showing 2 changed files with 181 additions and 4 deletions.
4 changes: 3 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
@@ -1,2 +1,4 @@
/target
*.asm
*.asm
*.o
*.c
181 changes: 178 additions & 3 deletions src/Target/x64/asm/instr.rs
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,6 @@ impl Instr {

Ok(match self.mnemonic {
Mnemonic::Add | Mnemonic::Adc | Mnemonic::And | Mnemonic::Or | Mnemonic::Sub | Mnemonic::Xor => {

let mandatory = if let Some(Operand::Reg(reg)) = &self.op1 {
if reg.is_gr16() { Some(MandatoryPrefix::t16BitOps)}
else { None }
Expand Down Expand Up @@ -207,8 +206,184 @@ impl Instr {
}
}
},
Mnemonic::Lea => todo!(),
Mnemonic::Mov => todo!(),
Mnemonic::Lea => {
let op0 = if let Operand::Reg(reg) = &self.op1.clone().expect("verify faild") {
*reg.as_any().downcast_ref::<x64Reg>().unwrap()
} else { panic!() };

let mandatory = if op0.is_gr16() { Some(MandatoryPrefix::t16BitOps) } else { None };
let mut rex = {
if op0.is_gr64() {
Some(RexPrefix { w: true, r: op0.extended(), x: false, b: false })
} else if op0.extended() {
Some(RexPrefix { w: false, r: true, x: false, b: false })
} else { None }
};

let mut op = vec![];

if let Some(Operand::Mem(mem)) = &self.op2 {
if let Some(rext) = rex {
rex = Some(rext.sync(mem.rex()));
}

op.push(0x8D);
op.extend_from_slice(&ModRm::regM(op0, mem.clone()));
} else { todo!() }

buildOpcode(mandatory, rex, op)
},
Mnemonic::Mov => {
let mandatory = if let Some(Operand::Reg(reg)) = &self.op1 {
if reg.is_gr16() { Some(MandatoryPrefix::t16BitOps)}
else { None }
} else { None };

let rex: Option<RexPrefix> = if let Some(Operand::Reg(reg)) = &self.op1 {
if reg.is_gr64() { Some(RexPrefix { w: true, r: false, x: false, b: false })}
else { None }
} else { None };

let (mut r, mut m, mut i) = (0x89, 0x8B, 0xC7);

if let Some(Operand::Reg(reg)) = &self.op1 {
if reg.is_gr8() { r -= 1; m -= 1; i -= 1; }
}

match self.op2.as_ref().expect("verifycation failed") {
Operand::Reg(reg) => {
let reg = reg.as_any().downcast_ref::<x64Reg>().expect("expected x64 registers and not the ones from other archs");

let mut rex = if reg.extended() {
if let Some(mut rex) = rex {
rex.r = true;
Some(rex)
} else {
Some(RexPrefix { w: false, r: true, x: false, b: false })
}
} else { rex };

if reg.is_gr64() {
if let Some(mut rex) = rex {
rex.w = true;
} else {
rex = Some(RexPrefix { w: true, r: false, x: false, b: false })
}
}

let mut op = vec![];

if let Some(Operand::Reg(op0)) = &self.op1 {
let op0 = op0.as_any().downcast_ref::<x64Reg>().expect("expected x64 registers and not the ones from other archs");

if op0.extended() {
if let Some(mut rex) = rex {
rex.b = true;
} else {
rex = Some(RexPrefix { w: false, r: false, x: false, b: true })
};
}
if op0.is_gr64() {
if let Some(mut rex) = rex {
rex.w = true;
} else {
rex = Some(RexPrefix { w: true, r: false, x: false, b: false })
};
}

if reg.extended() || op0.extended() {
op.push(r);
op.extend_from_slice(&ModRm::reg2(
*op0,
*reg
));
}
else {
op.push(m);
op.extend_from_slice(&ModRm::reg2(
*reg,
*op0
));
}

} else if let Some(Operand::Mem(mem)) = &self.op1 {
op.push(r);
if let Some(rex) = rex.as_mut() {
rex.sync(mem.rex());
}
op.extend_from_slice(&ModRm::memR(
mem.clone(),
*reg.as_any().downcast_ref::<x64Reg>().expect("expected x64 registers and not the ones from other archs")
))
} else { todo!() }

buildOpcode(mandatory, rex, op)
},
Operand::Mem(mem) => {
let mut op = vec![];
let mut rex = None;

if let Some(Operand::Reg(op0)) = &self.op1 {
let op0 = op0.as_any().downcast_ref::<x64Reg>().expect("expected x64 registers and not the ones from other archs");

if op0.extended() {
if op0.is_gr64() { rex = Some(RexPrefix { w: true, r: false, x: false, b: true }); }
else { rex = Some(RexPrefix { w: false, r: false, x: false, b: true }); }
} else if op0.is_gr64() { rex = Some(RexPrefix { w: true, r: false, x: false, b: false }); }
op.push(m);

if let Some(rext) = rex {
rex = Some(rext.sync(mem.rex()));
}



op.extend_from_slice(&ModRm::regM(
*op0,
mem.clone()
));

} else { todo!() }

buildOpcode(mandatory, rex, op)
},
Operand::Imm(num) => {
let mut mandatory = None;
let mut rex = None;
let mut op = vec![];

if let Some(Operand::Reg(op0)) = &self.op1 {
let op0 = op0.as_any().downcast_ref::<x64Reg>().expect("expected x64 registers and not the ones from other archs");

if op0.extended() {
rex = Some(RexPrefix { w: false, r: false, x: false, b: true });
}
if op0.is_gr64() {
rex = Some(RexPrefix { w: true, r: false, x: false, b: false });
}
if op0.is_gr16() {
mandatory = Some(MandatoryPrefix::t16BitOps);
}

op.push(i);
op.extend_from_slice(&ModRm::regWimm(0, *op0));

let bytes = (*num).to_be_bytes();

if op0.is_gr64() || op0.is_gr32() {
op.push(bytes[7]); op.push(bytes[6]);
op.push(bytes[5]); op.push(bytes[4]);
} else if op0.is_gr16() {
op.push(bytes[7]); op.push(bytes[6]);
} else if op0.is_gr8() {
op.push(*num as u8);
}
} else { todo!() }

buildOpcode(mandatory, rex, op)
}
}
},
Mnemonic::Push | Mnemonic::Pop => {
let mut mandatory = None;
let mut rex = None;
Expand Down

0 comments on commit 39018df

Please sign in to comment.