minor cleanups

This commit is contained in:
lifning 2021-10-26 02:26:42 -07:00
parent a9a808373b
commit 3a84b868f0
3 changed files with 61 additions and 83 deletions

4
Cargo.lock generated
View File

@ -672,7 +672,3 @@ dependencies = [
"serde_derive",
"yaxpeax-arch",
]
[[patch.unused]]
name = "lightning-sys"
version = "0.2.2"

View File

@ -4,7 +4,6 @@ version = "0.1.0"
edition = "2021"
[dependencies]
# lightning-sys = "0.2.2"
lightning-sys = { git = "https://github.com/petelliott/lightning-sys" }
yaxpeax-arm = "0.1"
yaxpeax-arch = "0.2"
@ -12,8 +11,7 @@ structopt = "0.3"
hex = "0.4"
num-traits = "0.2"
elf-utilities = "0.2"
# llama = "0.9"
syscall-numbers = "2.0"
[patch.crates-io]
lightning-sys = { path = "../lightning-sys" }
#lightning-sys = "0.2.2"
#[patch.crates-io]
#lightning-sys = { path = "../lightning-sys" }

View File

@ -13,7 +13,6 @@ use yaxpeax_arm::armv8::a64::{Opcode, Operand, SizeCode, ShiftStyle};
use num_traits::identities::Zero;
use lightning_sys::{Jit, JitState, JitWord, Reg};
use std::collections::HashMap;
mod _arch {
pub use yaxpeax_arm::armv8::a64::ARMv8;
@ -42,7 +41,7 @@ fn main() -> Result<()> {
//println!("entry: {}", elf.ehdr.e_entry);
let text_section = elf.first_section_by(|p| p.name == ".text")
.ok_or("No .text section in ELF")?;
println!("text_section header: {:?}", text_section.header);
println!("text_section header: {:?}\n", text_section.header);
if let Contents64::Raw(bytes) = &text_section.contents {
decode_input::<_arch::ARMv8>(&bytes[..], opt.verbose);
} else {
@ -57,17 +56,13 @@ struct ExtJitState<'a> {
reg_checkouts: [Option<Reg>; GP_REG_COUNT], // index is guest reg id
reg_recency: Vec<(Reg, usize)>,
regs_free: Vec<Reg>,
stack_base: i64,
stack_ptr: i64,
}
const STACK_WORDS: usize = 64;
// baker's 32. need a spare for ARM's barrel shifter.
const GP_REG_COUNT: usize = 33;
const REG_BARREL_TMP: usize = 32; // index
impl<'a> ExtJitState<'a> {
fn new(mut js: JitState<'a>) -> Self {
let stack = js.allocai(size_of::<[JitWord; STACK_WORDS]>() as i32) as i64;
let reg_storage = js.allocai(size_of::<[JitWord; GP_REG_COUNT]>() as i32) as i64;
let reg_checkouts = [None; GP_REG_COUNT];
let mut reg_recency = Vec::new();
@ -82,26 +77,6 @@ impl<'a> ExtJitState<'a> {
reg_checkouts,
reg_recency,
regs_free,
stack_base: stack,
stack_ptr: stack,
}
}
fn reg_from_operand(&mut self, operand: &Operand) -> Result<Reg> {
match operand {
Operand::RegisterOrSP(_, value)
| Operand::Register(_, value) => self.reg(*value),
_ => Err(format!("non-register operand: {:?}", operand).into()),
}
}
fn imm_from_operand(&self, operand: &Operand) -> Result<JitWord> {
match operand {
Operand::Immediate(value) => Ok((*value).into()),
Operand::Imm64(value) => Ok(*value as JitWord),
Operand::Imm16(value) => Ok((*value).into()),
Operand::ImmShift(base, shift) => Ok((*base as JitWord) << shift),
_ => Err(format!("non-immediate operand: {:?}", operand).into()),
}
}
@ -141,30 +116,6 @@ impl<'a> ExtJitState<'a> {
Err("not enough host registers to support this architecture?".into())
}
}
fn push(&mut self, reg: Reg) -> Result<()> {
let sp = self.stack_ptr;
self.stxi(sp, Reg::FP, reg);
self.stack_ptr += size_of::<JitWord>() as i64;
if self.stack_ptr > self.stack_base + size_of::<[JitWord; STACK_WORDS]>() as i64 {
Err(format!("stack overflow trying to push {:?}", reg).into())
} else {
Ok(())
}
}
fn pop(&mut self, reg: Reg) -> Result<()> {
self.stack_ptr -= size_of::<JitWord>() as i64;
let sp = self.stack_ptr;
self.ldxi(reg, Reg::FP, sp);
if self.stack_ptr < self.stack_base {
Err(format!("compiler stack underflow trying to pop {:?}", reg).into())
} else {
Ok(())
}
}
}
impl<'a> Deref for ExtJitState<'a> {
@ -181,58 +132,91 @@ impl<'a> DerefMut for ExtJitState<'a> {
}
}
trait OperandHelpers {
fn reg_id(&self) -> Result<usize>;
fn immediate(&self) -> Result<JitWord>;
}
impl OperandHelpers for Operand {
fn reg_id(&self) -> Result<usize> {
match self {
Operand::RegisterOrSP(_, value)
| Operand::Register(_, value) => Ok(*value as usize),
_ => Err(format!("non-register operand: {:?}", self).into()),
}
}
fn immediate(&self) -> Result<JitWord> {
match self {
Operand::Immediate(value) => Ok((*value).into()),
Operand::Imm64(value) => Ok(*value as JitWord),
Operand::Imm16(value) => Ok((*value).into()),
Operand::ImmShift(base, shift) => Ok((*base as JitWord) << shift),
_ => Err(format!("non-immediate operand: {:?}", self).into()),
}
}
}
trait ToLightning {
fn translate(&self, js: &mut ExtJitState);
fn translate(&self, js: &mut ExtJitState) -> Result<()>;
}
impl ToLightning for _arch::ARMv8_Instr {
fn translate(&self, js: &mut ExtJitState) {
fn translate(&self, js: &mut ExtJitState) -> Result<()> {
let _arch::ARMv8_Instr { opcode, operands } = self;
match opcode {
Opcode::Invalid => { panic!("Invalid ARMv8 instruction: {:?}", self); }
Opcode::Invalid => return Err(format!("Invalid ARMv8 instruction: {:?}", self).into()),
Opcode::MOVZ => {
let [dest, src, _, _] = operands;
let dest = js.reg_from_operand(dest).expect("dest");
let src = js.imm_from_operand(src).expect("src");
js.movi(dest, src);
let [dest_orig, src, _, _] = operands;
match dest_orig {
Operand::Register(size, id)
| Operand::RegisterOrSP(size, id) => {
let dest = js.reg(*id)?;
js.movi(dest, src.immediate()?);
if *size == SizeCode::W {
js.extr_i(dest, dest);
}
}
_ => return Err(format!("Invalid target for MOVZ: {:?}", dest_orig).into()),
}
}
Opcode::ADD => {
let [dest_orig, src1_orig, src2_orig, _] = operands;
let src1 = js.reg_from_operand(src1_orig).expect("src1");
let src1 = js.reg(src1_orig.reg_id()?)?;
// we decode dest last for correctness in super-scarce register situations where
// our register LRU cache may need to evict a jit register for it.
// we return it from this match statement for later sign-extension in 32-bit ops.
let dest = match src2_orig {
Operand::Register(_, id)
| Operand::RegisterOrSP(_, id) => {
let src2 = js.reg(*id).expect("src2");
let dest = js.reg_from_operand(dest_orig).expect("dest");
let src2 = js.reg(*id)?;
let dest = js.reg(dest_orig.reg_id()?)?;
js.addr(dest, src1, src2);
dest
}
Operand::RegShift(shift_style, shift, _, id) => {
let src2 = js.reg(*id).expect("src2");
let src2_tmp = js.reg(REG_BARREL_TMP).expect("src2_tmp");
let src2 = js.reg(*id)?;
let src2_tmp = js.reg(REG_BARREL_TMP)?;
match shift_style {
ShiftStyle::LSL => js.lshi(src2_tmp, src2, (*shift).into()),
ShiftStyle::LSR => js.rshi_u(src2_tmp, src2, (*shift).into()),
ShiftStyle::ASR => js.rshi(src2_tmp, src2, (*shift).into()),
_ => panic!("invalid shift style for ADD"),
_ => return Err(format!("invalid shift style for ADD").into()),
};
let dest = js.reg_from_operand(dest_orig).expect("dest");
let dest = js.reg(dest_orig.reg_id()?)?;
js.addr(dest, src1, src2_tmp);
dest
}
Operand::Immediate(_)
| Operand::Imm64(_)
| Operand::Imm16(_)
Operand::Immediate(..)
| Operand::Imm64(..)
| Operand::Imm16(..)
| Operand::ImmShift(..) => {
let src2 = js.imm_from_operand(src2_orig).expect("src2");
let dest = js.reg_from_operand(dest_orig).expect("dest");
let src2 = src2_orig.immediate()?;
let dest = js.reg(dest_orig.reg_id()?)?;
js.addi(dest, src1, src2);
dest
}
_ => { panic!("Invalid second operand to ADD: {:?}", src2_orig); }
_ => return Err(format!("Invalid second operand to ADD: {:?}", src2_orig).into()),
};
// sign-extend if it's a 32-bit operation
@ -354,7 +338,7 @@ impl ToLightning for _arch::ARMv8_Instr {
Opcode::PACIA => {}
Opcode::PACIZA => {}
}
()
Ok(())
}
}
@ -384,9 +368,9 @@ where
let mut reader = U8Reader::new(&buf[addr.to_linear()..]);
match decoder.decode(&mut reader) {
Ok(inst) => {
inst.translate(&mut ejs);
inst.translate(&mut ejs).unwrap();
println!(
"{:#010x}: {:14}: {}",
"{:#06x}: {:8}: {}",
addr.to_linear(),
hex::encode(
&buf[addr.to_linear()..]
@ -417,5 +401,5 @@ where
let code: extern fn() -> JitWord = unsafe { ejs.cast_emit() };
ejs.clear_state();
println!("exit code of jit: {}", code());
println!("\nreturn value of jit execution: {}", code());
}