mirror of
https://github.com/fluencelabs/wasmer
synced 2025-04-14 05:06:07 +00:00
Implement more instructions.
This commit is contained in:
parent
0f26ee40de
commit
6ac81a3c84
@ -35,6 +35,12 @@ pub struct X64ModuleCodeGenerator {
|
|||||||
func_import_count: usize,
|
func_import_count: usize,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Copy, Clone, Debug, Eq, PartialEq)]
|
||||||
|
enum LocalOrTemp {
|
||||||
|
Local,
|
||||||
|
Temp
|
||||||
|
}
|
||||||
|
|
||||||
pub struct X64FunctionCode {
|
pub struct X64FunctionCode {
|
||||||
signatures: Arc<Map<SigIndex, FuncSig>>,
|
signatures: Arc<Map<SigIndex, FuncSig>>,
|
||||||
function_signatures: Arc<Map<FuncIndex, SigIndex>>,
|
function_signatures: Arc<Map<FuncIndex, SigIndex>>,
|
||||||
@ -46,7 +52,7 @@ pub struct X64FunctionCode {
|
|||||||
returns: Vec<WpType>,
|
returns: Vec<WpType>,
|
||||||
locals: Vec<Location>,
|
locals: Vec<Location>,
|
||||||
num_params: usize,
|
num_params: usize,
|
||||||
value_stack: Vec<Location>,
|
value_stack: Vec<(Location, LocalOrTemp)>,
|
||||||
control_stack: Vec<ControlFrame>,
|
control_stack: Vec<ControlFrame>,
|
||||||
machine: Machine,
|
machine: Machine,
|
||||||
unreachable_depth: usize,
|
unreachable_depth: usize,
|
||||||
@ -346,6 +352,99 @@ impl X64FunctionCode {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn emit_binop_i32<F: FnOnce(&mut Assembler, Size, Location, Location)>(
|
||||||
|
a: &mut Assembler,
|
||||||
|
m: &mut Machine,
|
||||||
|
value_stack: &mut Vec<(Location, LocalOrTemp)>,
|
||||||
|
f: F,
|
||||||
|
) {
|
||||||
|
// Using Red Zone here.
|
||||||
|
let loc_b = get_location_released(a, m, value_stack.pop().unwrap());
|
||||||
|
let loc_a = get_location_released(a, m, value_stack.pop().unwrap());
|
||||||
|
let ret = m.acquire_locations(a, &[WpType::I32], false)[0];
|
||||||
|
assert_eq!(loc_a, ret);
|
||||||
|
Self::emit_relaxed_binop(
|
||||||
|
a, m, f,
|
||||||
|
Size::S32, loc_b, ret,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
fn emit_cmpop_i32_dynamic_b(
|
||||||
|
a: &mut Assembler,
|
||||||
|
m: &mut Machine,
|
||||||
|
value_stack: &mut Vec<(Location, LocalOrTemp)>,
|
||||||
|
c: Condition,
|
||||||
|
loc_b: Location,
|
||||||
|
) {
|
||||||
|
// Using Red Zone here.
|
||||||
|
let loc_a = get_location_released(a, m, value_stack.pop().unwrap());
|
||||||
|
let ret = m.acquire_locations(a, &[WpType::I32], false)[0];
|
||||||
|
match ret {
|
||||||
|
Location::GPR(x) => {
|
||||||
|
a.emit_xor(Size::S32, Location::GPR(x), Location::GPR(x));
|
||||||
|
Self::emit_relaxed_binop(
|
||||||
|
a, m, Assembler::emit_cmp,
|
||||||
|
Size::S32, loc_b, loc_a,
|
||||||
|
);
|
||||||
|
a.emit_set(c, x);
|
||||||
|
},
|
||||||
|
Location::Memory(_, _) => {
|
||||||
|
let tmp = m.acquire_temp_gpr().unwrap();
|
||||||
|
a.emit_xor(Size::S32, Location::GPR(tmp), Location::GPR(tmp));
|
||||||
|
Self::emit_relaxed_binop(
|
||||||
|
a, m, Assembler::emit_cmp,
|
||||||
|
Size::S32, loc_b, loc_a,
|
||||||
|
);
|
||||||
|
a.emit_set(c, tmp);
|
||||||
|
a.emit_mov(Size::S32, Location::GPR(tmp), ret);
|
||||||
|
m.release_temp_gpr(tmp);
|
||||||
|
},
|
||||||
|
_ => unreachable!()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn emit_cmpop_i32(
|
||||||
|
a: &mut Assembler,
|
||||||
|
m: &mut Machine,
|
||||||
|
value_stack: &mut Vec<(Location, LocalOrTemp)>,
|
||||||
|
c: Condition,
|
||||||
|
) {
|
||||||
|
let loc_b = get_location_released(a, m, value_stack.pop().unwrap());
|
||||||
|
Self::emit_cmpop_i32_dynamic_b(a, m, value_stack, c, loc_b);
|
||||||
|
}
|
||||||
|
|
||||||
|
fn emit_xcnt_i32<F: FnOnce(&mut Assembler, Size, Location, Location)>(
|
||||||
|
a: &mut Assembler,
|
||||||
|
m: &mut Machine,
|
||||||
|
value_stack: &mut Vec<(Location, LocalOrTemp)>,
|
||||||
|
f: F,
|
||||||
|
) {
|
||||||
|
let loc = get_location_released(a, m, value_stack.pop().unwrap());
|
||||||
|
let ret = m.acquire_locations(a, &[WpType::I32], false)[0];
|
||||||
|
if let Location::Imm32(x) = loc {
|
||||||
|
let tmp = m.acquire_temp_gpr().unwrap();
|
||||||
|
a.emit_mov(Size::S32, loc, Location::GPR(tmp));
|
||||||
|
if let Location::Memory(_, _) = ret {
|
||||||
|
let out_tmp = m.acquire_temp_gpr().unwrap();
|
||||||
|
f(a, Size::S32, Location::GPR(tmp), Location::GPR(out_tmp));
|
||||||
|
a.emit_mov(Size::S32, Location::GPR(out_tmp), ret);
|
||||||
|
m.release_temp_gpr(out_tmp);
|
||||||
|
} else {
|
||||||
|
f(a, Size::S32, Location::GPR(tmp), ret);
|
||||||
|
}
|
||||||
|
m.release_temp_gpr(tmp);
|
||||||
|
} else {
|
||||||
|
if let Location::Memory(_, _) = ret {
|
||||||
|
let out_tmp = m.acquire_temp_gpr().unwrap();
|
||||||
|
f(a, Size::S32, loc, Location::GPR(out_tmp));
|
||||||
|
a.emit_mov(Size::S32, Location::GPR(out_tmp), ret);
|
||||||
|
m.release_temp_gpr(out_tmp);
|
||||||
|
} else {
|
||||||
|
f(a, Size::S32, loc, ret);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
fn get_param_location(
|
fn get_param_location(
|
||||||
idx: usize
|
idx: usize
|
||||||
) -> Location {
|
) -> Location {
|
||||||
@ -372,13 +471,13 @@ impl FunctionCodeGenerator for X64FunctionCode {
|
|||||||
self.locals.push(Self::get_param_location(
|
self.locals.push(Self::get_param_location(
|
||||||
self.num_params + 1
|
self.num_params + 1
|
||||||
));
|
));
|
||||||
|
self.num_params += 1;
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn feed_local(&mut self, ty: WpType, n: usize) -> Result<(), CodegenError> {
|
fn feed_local(&mut self, ty: WpType, n: usize) -> Result<(), CodegenError> {
|
||||||
let a = self.assembler.as_mut().unwrap();
|
let a = self.assembler.as_mut().unwrap();
|
||||||
let types: Vec<_> = ::std::iter::repeat(ty).take(n).collect();
|
self.machine.acquire_stack_locations(a, n, true);
|
||||||
self.machine.acquire_locations(a, &types, true);
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -434,6 +533,166 @@ impl FunctionCodeGenerator for X64FunctionCode {
|
|||||||
}
|
}
|
||||||
|
|
||||||
let a = self.assembler.as_mut().unwrap();
|
let a = self.assembler.as_mut().unwrap();
|
||||||
unimplemented!();
|
match op {
|
||||||
|
Operator::GetGlobal { global_index } => {
|
||||||
|
let mut global_index = global_index as usize;
|
||||||
|
let loc = self.machine.acquire_locations(
|
||||||
|
a,
|
||||||
|
&[type_to_wp_type(
|
||||||
|
module_info.globals[LocalGlobalIndex::new(global_index)]
|
||||||
|
.desc
|
||||||
|
.ty,
|
||||||
|
)],
|
||||||
|
false
|
||||||
|
)[0];
|
||||||
|
self.value_stack.push((loc, LocalOrTemp::Temp));
|
||||||
|
|
||||||
|
let tmp = self.machine.acquire_temp_gpr().unwrap();
|
||||||
|
|
||||||
|
if global_index < module_info.imported_globals.len() {
|
||||||
|
a.emit_mov(Size::S64, Location::Memory(GPR::RDI, vm::Ctx::offset_imported_globals() as i32), Location::GPR(tmp));
|
||||||
|
} else {
|
||||||
|
global_index -= module_info.imported_globals.len();
|
||||||
|
assert!(global_index < module_info.globals.len());
|
||||||
|
a.emit_mov(Size::S64, Location::Memory(GPR::RDI, vm::Ctx::offset_globals() as i32), Location::GPR(tmp));
|
||||||
|
}
|
||||||
|
a.emit_mov(Size::S64, Location::Memory(tmp, (global_index as i32) * 8), Location::GPR(tmp));
|
||||||
|
Self::emit_relaxed_binop(
|
||||||
|
a, &mut self.machine, Assembler::emit_mov,
|
||||||
|
Size::S64, Location::Memory(tmp, LocalGlobal::offset_data() as i32), loc
|
||||||
|
);
|
||||||
|
|
||||||
|
self.machine.release_temp_gpr(tmp);
|
||||||
|
}
|
||||||
|
Operator::SetGlobal { global_index } => {
|
||||||
|
let mut global_index = global_index as usize;
|
||||||
|
let (loc, local_or_temp) = self.value_stack.pop().unwrap();
|
||||||
|
|
||||||
|
let tmp = self.machine.acquire_temp_gpr().unwrap();
|
||||||
|
|
||||||
|
if global_index < module_info.imported_globals.len() {
|
||||||
|
a.emit_mov(Size::S64, Location::Memory(GPR::RDI, vm::Ctx::offset_imported_globals() as i32), Location::GPR(tmp));
|
||||||
|
} else {
|
||||||
|
global_index -= module_info.imported_globals.len();
|
||||||
|
assert!(global_index < module_info.globals.len());
|
||||||
|
a.emit_mov(Size::S64, Location::Memory(GPR::RDI, vm::Ctx::offset_globals() as i32), Location::GPR(tmp));
|
||||||
|
}
|
||||||
|
a.emit_mov(Size::S64, Location::Memory(tmp, (global_index as i32) * 8), Location::GPR(tmp));
|
||||||
|
Self::emit_relaxed_binop(
|
||||||
|
a, &mut self.machine, Assembler::emit_mov,
|
||||||
|
Size::S64, loc, Location::Memory(tmp, LocalGlobal::offset_data() as i32)
|
||||||
|
);
|
||||||
|
|
||||||
|
self.machine.release_temp_gpr(tmp);
|
||||||
|
if local_or_temp == LocalOrTemp::Temp {
|
||||||
|
self.machine.release_locations(a, &[loc]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Operator::GetLocal { local_index } => {
|
||||||
|
let local_index = local_index as usize;
|
||||||
|
self.value_stack.push((self.locals[local_index], LocalOrTemp::Local));
|
||||||
|
}
|
||||||
|
Operator::SetLocal { local_index } => {
|
||||||
|
let local_index = local_index as usize;
|
||||||
|
let (loc, local_or_temp) = self.value_stack.pop().unwrap();
|
||||||
|
|
||||||
|
Self::emit_relaxed_binop(
|
||||||
|
a, &mut self.machine, Assembler::emit_mov,
|
||||||
|
Size::S64, loc, self.locals[local_index],
|
||||||
|
);
|
||||||
|
if local_or_temp == LocalOrTemp::Temp {
|
||||||
|
self.machine.release_locations(a, &[loc]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Operator::TeeLocal { local_index } => {
|
||||||
|
let local_index = local_index as usize;
|
||||||
|
let (loc, _) = *self.value_stack.last().unwrap();
|
||||||
|
|
||||||
|
Self::emit_relaxed_binop(
|
||||||
|
a, &mut self.machine, Assembler::emit_mov,
|
||||||
|
Size::S64, loc, self.locals[local_index],
|
||||||
|
);
|
||||||
|
}
|
||||||
|
Operator::I32Const { value } => self.value_stack.push((Location::Imm32(value as u32), LocalOrTemp::Temp)),
|
||||||
|
Operator::I32Add => Self::emit_binop_i32(a, &mut self.machine, &mut self.value_stack, Assembler::emit_add),
|
||||||
|
Operator::I32Sub => Self::emit_binop_i32(a, &mut self.machine, &mut self.value_stack, Assembler::emit_sub),
|
||||||
|
Operator::I32Mul => Self::emit_binop_i32(a, &mut self.machine, &mut self.value_stack, Assembler::emit_imul),
|
||||||
|
Operator::I32DivU => {
|
||||||
|
// We assume that RAX and RDX are temporary registers here.
|
||||||
|
let loc_b = get_location_released(a, &mut self.machine, self.value_stack.pop().unwrap());
|
||||||
|
let loc_a = get_location_released(a, &mut self.machine, self.value_stack.pop().unwrap());
|
||||||
|
let ret = self.machine.acquire_locations(a, &[WpType::I32], false)[0];
|
||||||
|
a.emit_mov(Size::S32, loc_a, Location::GPR(GPR::RAX));
|
||||||
|
a.emit_xor(Size::S32, Location::GPR(GPR::RDX), Location::GPR(GPR::RDX));
|
||||||
|
a.emit_div(Size::S32, loc_b);
|
||||||
|
a.emit_mov(Size::S32, Location::GPR(GPR::RAX), ret);
|
||||||
|
}
|
||||||
|
Operator::I32DivS => {
|
||||||
|
// We assume that RAX and RDX are temporary registers here.
|
||||||
|
let loc_b = get_location_released(a, &mut self.machine, self.value_stack.pop().unwrap());
|
||||||
|
let loc_a = get_location_released(a, &mut self.machine, self.value_stack.pop().unwrap());
|
||||||
|
let ret = self.machine.acquire_locations(a, &[WpType::I32], false)[0];
|
||||||
|
a.emit_mov(Size::S32, loc_a, Location::GPR(GPR::RAX));
|
||||||
|
a.emit_xor(Size::S32, Location::GPR(GPR::RDX), Location::GPR(GPR::RDX));
|
||||||
|
a.emit_idiv(Size::S32, loc_b);
|
||||||
|
a.emit_mov(Size::S32, Location::GPR(GPR::RAX), ret);
|
||||||
|
}
|
||||||
|
Operator::I32RemU => {
|
||||||
|
// We assume that RAX and RDX are temporary registers here.
|
||||||
|
let loc_b = get_location_released(a, &mut self.machine, self.value_stack.pop().unwrap());
|
||||||
|
let loc_a = get_location_released(a, &mut self.machine, self.value_stack.pop().unwrap());
|
||||||
|
let ret = self.machine.acquire_locations(a, &[WpType::I32], false)[0];
|
||||||
|
a.emit_mov(Size::S32, loc_a, Location::GPR(GPR::RAX));
|
||||||
|
a.emit_xor(Size::S32, Location::GPR(GPR::RDX), Location::GPR(GPR::RDX));
|
||||||
|
a.emit_div(Size::S32, loc_b);
|
||||||
|
a.emit_mov(Size::S32, Location::GPR(GPR::RDX), ret);
|
||||||
|
}
|
||||||
|
Operator::I32RemS => {
|
||||||
|
// We assume that RAX and RDX are temporary registers here.
|
||||||
|
let loc_b = get_location_released(a, &mut self.machine, self.value_stack.pop().unwrap());
|
||||||
|
let loc_a = get_location_released(a, &mut self.machine, self.value_stack.pop().unwrap());
|
||||||
|
let ret = self.machine.acquire_locations(a, &[WpType::I32], false)[0];
|
||||||
|
a.emit_mov(Size::S32, loc_a, Location::GPR(GPR::RAX));
|
||||||
|
a.emit_xor(Size::S32, Location::GPR(GPR::RDX), Location::GPR(GPR::RDX));
|
||||||
|
a.emit_idiv(Size::S32, loc_b);
|
||||||
|
a.emit_mov(Size::S32, Location::GPR(GPR::RDX), ret);
|
||||||
|
}
|
||||||
|
Operator::I32And => Self::emit_binop_i32(a, &mut self.machine, &mut self.value_stack, Assembler::emit_and),
|
||||||
|
Operator::I32Or => Self::emit_binop_i32(a, &mut self.machine, &mut self.value_stack, Assembler::emit_or),
|
||||||
|
Operator::I32Xor => Self::emit_binop_i32(a, &mut self.machine, &mut self.value_stack, Assembler::emit_xor),
|
||||||
|
Operator::I32Eq => Self::emit_cmpop_i32(a, &mut self.machine, &mut self.value_stack, Condition::Equal),
|
||||||
|
Operator::I32Ne => Self::emit_cmpop_i32(a, &mut self.machine, &mut self.value_stack, Condition::NotEqual),
|
||||||
|
Operator::I32LtU => Self::emit_cmpop_i32(a, &mut self.machine, &mut self.value_stack, Condition::Below),
|
||||||
|
Operator::I32LeU => Self::emit_cmpop_i32(a, &mut self.machine, &mut self.value_stack, Condition::BelowEqual),
|
||||||
|
Operator::I32GtU => Self::emit_cmpop_i32(a, &mut self.machine, &mut self.value_stack, Condition::Above),
|
||||||
|
Operator::I32GeU => Self::emit_cmpop_i32(a, &mut self.machine, &mut self.value_stack, Condition::AboveEqual),
|
||||||
|
Operator::I32LtS => Self::emit_cmpop_i32(a, &mut self.machine, &mut self.value_stack, Condition::Less),
|
||||||
|
Operator::I32LeS => Self::emit_cmpop_i32(a, &mut self.machine, &mut self.value_stack, Condition::LessEqual),
|
||||||
|
Operator::I32GtS => Self::emit_cmpop_i32(a, &mut self.machine, &mut self.value_stack, Condition::Greater),
|
||||||
|
Operator::I32GeS => Self::emit_cmpop_i32(a, &mut self.machine, &mut self.value_stack, Condition::GreaterEqual),
|
||||||
|
Operator::I32Eqz => Self::emit_cmpop_i32_dynamic_b(a, &mut self.machine, &mut self.value_stack, Condition::Equal, Location::Imm32(0)),
|
||||||
|
Operator::I32Clz => Self::emit_xcnt_i32(a, &mut self.machine, &mut self.value_stack, Emitter::emit_lzcnt),
|
||||||
|
Operator::I32Ctz => Self::emit_xcnt_i32(a, &mut self.machine, &mut self.value_stack, Emitter::emit_tzcnt),
|
||||||
|
Operator::I32Popcnt => Self::emit_xcnt_i32(a, &mut self.machine, &mut self.value_stack, Emitter::emit_popcnt),
|
||||||
|
_ => unimplemented!()
|
||||||
|
}
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn type_to_wp_type(ty: Type) -> WpType {
|
||||||
|
match ty {
|
||||||
|
Type::I32 => WpType::I32,
|
||||||
|
Type::I64 => WpType::I64,
|
||||||
|
Type::F32 => WpType::F32,
|
||||||
|
Type::F64 => WpType::F64,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn get_location_released(a: &mut Assembler, m: &mut Machine, (loc, lot): (Location, LocalOrTemp)) -> Location {
|
||||||
|
if lot == LocalOrTemp::Temp {
|
||||||
|
m.release_locations(a, &[loc]);
|
||||||
|
}
|
||||||
|
loc
|
||||||
|
}
|
||||||
|
@ -91,6 +91,11 @@ pub trait Emitter {
|
|||||||
fn emit_shl(&mut self, sz: Size, src: Location, dst: Location);
|
fn emit_shl(&mut self, sz: Size, src: Location, dst: Location);
|
||||||
fn emit_shr(&mut self, sz: Size, src: Location, dst: Location);
|
fn emit_shr(&mut self, sz: Size, src: Location, dst: Location);
|
||||||
fn emit_sar(&mut self, sz: Size, src: Location, dst: Location);
|
fn emit_sar(&mut self, sz: Size, src: Location, dst: Location);
|
||||||
|
fn emit_and(&mut self, sz: Size, src: Location, dst: Location);
|
||||||
|
fn emit_or(&mut self, sz: Size, src: Location, dst: Location);
|
||||||
|
fn emit_lzcnt(&mut self, sz: Size, src: Location, dst: Location);
|
||||||
|
fn emit_tzcnt(&mut self, sz: Size, src: Location, dst: Location);
|
||||||
|
fn emit_popcnt(&mut self, sz: Size, src: Location, dst: Location);
|
||||||
|
|
||||||
fn emit_ud2(&mut self);
|
fn emit_ud2(&mut self);
|
||||||
}
|
}
|
||||||
@ -390,6 +395,27 @@ impl Emitter for Assembler {
|
|||||||
fn emit_sar(&mut self, sz: Size, src: Location, dst: Location) {
|
fn emit_sar(&mut self, sz: Size, src: Location, dst: Location) {
|
||||||
binop_shift!(sar, self, sz, src, dst, { unreachable!() });
|
binop_shift!(sar, self, sz, src, dst, { unreachable!() });
|
||||||
}
|
}
|
||||||
|
fn emit_and(&mut self, sz: Size, src: Location, dst: Location) {
|
||||||
|
binop_all_nofp!(and, self, sz, src, dst, {unreachable!()});
|
||||||
|
}
|
||||||
|
fn emit_or(&mut self, sz: Size, src: Location, dst: Location) {
|
||||||
|
binop_all_nofp!(or, self, sz, src, dst, {unreachable!()});
|
||||||
|
}
|
||||||
|
fn emit_lzcnt(&mut self, sz: Size, src: Location, dst: Location) {
|
||||||
|
binop_gpr_gpr!(lzcnt, self, sz, src, dst, {
|
||||||
|
binop_mem_gpr!(lzcnt, self, sz, src, dst, {unreachable!()})
|
||||||
|
});
|
||||||
|
}
|
||||||
|
fn emit_tzcnt(&mut self, sz: Size, src: Location, dst: Location) {
|
||||||
|
binop_gpr_gpr!(tzcnt, self, sz, src, dst, {
|
||||||
|
binop_mem_gpr!(tzcnt, self, sz, src, dst, {unreachable!()})
|
||||||
|
});
|
||||||
|
}
|
||||||
|
fn emit_popcnt(&mut self, sz: Size, src: Location, dst: Location) {
|
||||||
|
binop_gpr_gpr!(popcnt, self, sz, src, dst, {
|
||||||
|
binop_mem_gpr!(popcnt, self, sz, src, dst, {unreachable!()})
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
fn emit_ud2(&mut self) {
|
fn emit_ud2(&mut self) {
|
||||||
dynasm!(self ; ud2);
|
dynasm!(self ; ud2);
|
||||||
|
@ -25,8 +25,6 @@ impl Machine {
|
|||||||
pub fn pick_gpr(&self) -> Option<GPR> {
|
pub fn pick_gpr(&self) -> Option<GPR> {
|
||||||
use GPR::*;
|
use GPR::*;
|
||||||
static REGS: &'static [GPR] = &[
|
static REGS: &'static [GPR] = &[
|
||||||
RCX,
|
|
||||||
RDX,
|
|
||||||
RBX,
|
RBX,
|
||||||
RSI,
|
RSI,
|
||||||
RDI,
|
RDI,
|
||||||
@ -34,6 +32,8 @@ impl Machine {
|
|||||||
R9,
|
R9,
|
||||||
R10,
|
R10,
|
||||||
R11,
|
R11,
|
||||||
|
R12,
|
||||||
|
R13,
|
||||||
];
|
];
|
||||||
for r in REGS {
|
for r in REGS {
|
||||||
if !self.used_gprs.contains(r) {
|
if !self.used_gprs.contains(r) {
|
||||||
@ -50,8 +50,8 @@ impl Machine {
|
|||||||
use GPR::*;
|
use GPR::*;
|
||||||
static REGS: &'static [GPR] = &[
|
static REGS: &'static [GPR] = &[
|
||||||
RAX,
|
RAX,
|
||||||
R12,
|
RCX,
|
||||||
R13,
|
RDX,
|
||||||
R14,
|
R14,
|
||||||
R15
|
R15
|
||||||
];
|
];
|
||||||
@ -129,6 +129,34 @@ impl Machine {
|
|||||||
assert_eq!(self.used_xmms.remove(&xmm), true);
|
assert_eq!(self.used_xmms.remove(&xmm), true);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Acquires stack locations from the machine state.
|
||||||
|
pub fn acquire_stack_locations<E: Emitter>(
|
||||||
|
&mut self,
|
||||||
|
assembler: &mut E,
|
||||||
|
n: usize,
|
||||||
|
zeroed: bool,
|
||||||
|
) -> Vec<Location> {
|
||||||
|
let mut ret = vec![];
|
||||||
|
let mut delta_stack_offset: usize = 0;
|
||||||
|
|
||||||
|
for _ in 0..n {
|
||||||
|
let loc = {
|
||||||
|
self.stack_offset.0 += 8;
|
||||||
|
delta_stack_offset += 8;
|
||||||
|
Location::Memory(GPR::RBP, -(self.stack_offset.0 as i32))
|
||||||
|
};
|
||||||
|
ret.push(loc);
|
||||||
|
}
|
||||||
|
|
||||||
|
assembler.emit_sub(Size::S64, Location::Imm32(delta_stack_offset as u32), Location::GPR(GPR::RSP));
|
||||||
|
if zeroed {
|
||||||
|
for i in 0..n {
|
||||||
|
assembler.emit_mov(Size::S64, Location::Imm32(0), ret[i]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
ret
|
||||||
|
}
|
||||||
|
|
||||||
/// Acquires locations from the machine state.
|
/// Acquires locations from the machine state.
|
||||||
///
|
///
|
||||||
/// If the returned locations are used for stack value, `release_location` needs to be called on them;
|
/// If the returned locations are used for stack value, `release_location` needs to be called on them;
|
||||||
@ -173,7 +201,7 @@ impl Machine {
|
|||||||
assembler.emit_sub(Size::S64, Location::Imm32(delta_stack_offset as u32), Location::GPR(GPR::RSP));
|
assembler.emit_sub(Size::S64, Location::Imm32(delta_stack_offset as u32), Location::GPR(GPR::RSP));
|
||||||
if zeroed {
|
if zeroed {
|
||||||
for i in 0..tys.len() {
|
for i in 0..tys.len() {
|
||||||
assembler.emit_mov(Size::S64, Location::Imm32(0), Location::Memory(GPR::RSP, (i * 8) as i32));
|
assembler.emit_mov(Size::S64, Location::Imm32(0), ret[i]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
ret
|
ret
|
||||||
|
Loading…
x
Reference in New Issue
Block a user