Merge pull request #2388 from cfallin/sourceloc
MachInst backends: handle SourceLocs out-of-band, not in Insts.
This commit is contained in:
@@ -3,7 +3,6 @@
|
|||||||
use crate::ir;
|
use crate::ir;
|
||||||
use crate::ir::types;
|
use crate::ir::types;
|
||||||
use crate::ir::types::*;
|
use crate::ir::types::*;
|
||||||
use crate::ir::SourceLoc;
|
|
||||||
use crate::isa;
|
use crate::isa;
|
||||||
use crate::isa::aarch64::{inst::EmitState, inst::*};
|
use crate::isa::aarch64::{inst::EmitState, inst::*};
|
||||||
use crate::machinst::*;
|
use crate::machinst::*;
|
||||||
@@ -380,7 +379,7 @@ impl ABIMachineSpec for AArch64MachineDeps {
|
|||||||
extendop: ExtendOp::UXTX,
|
extendop: ExtendOp::UXTX,
|
||||||
});
|
});
|
||||||
insts.push(Inst::TrapIf {
|
insts.push(Inst::TrapIf {
|
||||||
trap_info: (ir::SourceLoc::default(), ir::TrapCode::StackOverflow),
|
trap_code: ir::TrapCode::StackOverflow,
|
||||||
// Here `Lo` == "less than" when interpreting the two
|
// Here `Lo` == "less than" when interpreting the two
|
||||||
// operands as unsigned integers.
|
// operands as unsigned integers.
|
||||||
kind: CondBrKind::Cond(Cond::Lo),
|
kind: CondBrKind::Cond(Cond::Lo),
|
||||||
@@ -554,7 +553,6 @@ impl ABIMachineSpec for AArch64MachineDeps {
|
|||||||
stack_reg(),
|
stack_reg(),
|
||||||
SImm9::maybe_from_i64((vec_offset + (i * 16)) as i64).unwrap(),
|
SImm9::maybe_from_i64((vec_offset + (i * 16)) as i64).unwrap(),
|
||||||
),
|
),
|
||||||
srcloc: None,
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -603,7 +601,6 @@ impl ABIMachineSpec for AArch64MachineDeps {
|
|||||||
stack_reg(),
|
stack_reg(),
|
||||||
SImm9::maybe_from_i64(((i * 16) + int_save_bytes) as i64).unwrap(),
|
SImm9::maybe_from_i64(((i * 16) + int_save_bytes) as i64).unwrap(),
|
||||||
),
|
),
|
||||||
srcloc: None,
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -634,7 +631,6 @@ impl ABIMachineSpec for AArch64MachineDeps {
|
|||||||
dest: &CallDest,
|
dest: &CallDest,
|
||||||
uses: Vec<Reg>,
|
uses: Vec<Reg>,
|
||||||
defs: Vec<Writable<Reg>>,
|
defs: Vec<Writable<Reg>>,
|
||||||
loc: SourceLoc,
|
|
||||||
opcode: ir::Opcode,
|
opcode: ir::Opcode,
|
||||||
tmp: Writable<Reg>,
|
tmp: Writable<Reg>,
|
||||||
callee_conv: isa::CallConv,
|
callee_conv: isa::CallConv,
|
||||||
@@ -649,7 +645,6 @@ impl ABIMachineSpec for AArch64MachineDeps {
|
|||||||
dest: name.clone(),
|
dest: name.clone(),
|
||||||
uses,
|
uses,
|
||||||
defs,
|
defs,
|
||||||
loc,
|
|
||||||
opcode,
|
opcode,
|
||||||
caller_callconv: caller_conv,
|
caller_callconv: caller_conv,
|
||||||
callee_callconv: callee_conv,
|
callee_callconv: callee_conv,
|
||||||
@@ -663,7 +658,6 @@ impl ABIMachineSpec for AArch64MachineDeps {
|
|||||||
rd: tmp,
|
rd: tmp,
|
||||||
name: Box::new(name.clone()),
|
name: Box::new(name.clone()),
|
||||||
offset: 0,
|
offset: 0,
|
||||||
srcloc: loc,
|
|
||||||
},
|
},
|
||||||
));
|
));
|
||||||
insts.push((
|
insts.push((
|
||||||
@@ -673,7 +667,6 @@ impl ABIMachineSpec for AArch64MachineDeps {
|
|||||||
rn: tmp.to_reg(),
|
rn: tmp.to_reg(),
|
||||||
uses,
|
uses,
|
||||||
defs,
|
defs,
|
||||||
loc,
|
|
||||||
opcode,
|
opcode,
|
||||||
caller_callconv: caller_conv,
|
caller_callconv: caller_conv,
|
||||||
callee_callconv: callee_conv,
|
callee_callconv: callee_conv,
|
||||||
@@ -688,7 +681,6 @@ impl ABIMachineSpec for AArch64MachineDeps {
|
|||||||
rn: *reg,
|
rn: *reg,
|
||||||
uses,
|
uses,
|
||||||
defs,
|
defs,
|
||||||
loc,
|
|
||||||
opcode,
|
opcode,
|
||||||
caller_callconv: caller_conv,
|
caller_callconv: caller_conv,
|
||||||
callee_callconv: callee_conv,
|
callee_callconv: callee_conv,
|
||||||
|
|||||||
@@ -462,6 +462,8 @@ pub struct EmitState {
|
|||||||
pub(crate) nominal_sp_to_fp: i64,
|
pub(crate) nominal_sp_to_fp: i64,
|
||||||
/// Safepoint stack map for upcoming instruction, as provided to `pre_safepoint()`.
|
/// Safepoint stack map for upcoming instruction, as provided to `pre_safepoint()`.
|
||||||
stack_map: Option<StackMap>,
|
stack_map: Option<StackMap>,
|
||||||
|
/// Current source-code location corresponding to instruction to be emitted.
|
||||||
|
cur_srcloc: SourceLoc,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl MachInstEmitState<Inst> for EmitState {
|
impl MachInstEmitState<Inst> for EmitState {
|
||||||
@@ -470,12 +472,17 @@ impl MachInstEmitState<Inst> for EmitState {
|
|||||||
virtual_sp_offset: 0,
|
virtual_sp_offset: 0,
|
||||||
nominal_sp_to_fp: abi.frame_size() as i64,
|
nominal_sp_to_fp: abi.frame_size() as i64,
|
||||||
stack_map: None,
|
stack_map: None,
|
||||||
|
cur_srcloc: SourceLoc::default(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn pre_safepoint(&mut self, stack_map: StackMap) {
|
fn pre_safepoint(&mut self, stack_map: StackMap) {
|
||||||
self.stack_map = Some(stack_map);
|
self.stack_map = Some(stack_map);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn pre_sourceloc(&mut self, srcloc: SourceLoc) {
|
||||||
|
self.cur_srcloc = srcloc;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl EmitState {
|
impl EmitState {
|
||||||
@@ -486,6 +493,10 @@ impl EmitState {
|
|||||||
fn clear_post_insn(&mut self) {
|
fn clear_post_insn(&mut self) {
|
||||||
self.stack_map = None;
|
self.stack_map = None;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn cur_srcloc(&self) -> SourceLoc {
|
||||||
|
self.cur_srcloc
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Constant state used during function compilation.
|
/// Constant state used during function compilation.
|
||||||
@@ -730,57 +741,16 @@ impl MachInstEmit for Inst {
|
|||||||
sink.put4(enc_bit_rr(size, op1, op2, rn, rd))
|
sink.put4(enc_bit_rr(size, op1, op2, rn, rd))
|
||||||
}
|
}
|
||||||
|
|
||||||
&Inst::ULoad8 {
|
&Inst::ULoad8 { rd, ref mem }
|
||||||
rd,
|
| &Inst::SLoad8 { rd, ref mem }
|
||||||
ref mem,
|
| &Inst::ULoad16 { rd, ref mem }
|
||||||
srcloc,
|
| &Inst::SLoad16 { rd, ref mem }
|
||||||
}
|
| &Inst::ULoad32 { rd, ref mem }
|
||||||
| &Inst::SLoad8 {
|
| &Inst::SLoad32 { rd, ref mem }
|
||||||
rd,
|
| &Inst::ULoad64 { rd, ref mem, .. }
|
||||||
ref mem,
|
| &Inst::FpuLoad32 { rd, ref mem }
|
||||||
srcloc,
|
| &Inst::FpuLoad64 { rd, ref mem }
|
||||||
}
|
| &Inst::FpuLoad128 { rd, ref mem } => {
|
||||||
| &Inst::ULoad16 {
|
|
||||||
rd,
|
|
||||||
ref mem,
|
|
||||||
srcloc,
|
|
||||||
}
|
|
||||||
| &Inst::SLoad16 {
|
|
||||||
rd,
|
|
||||||
ref mem,
|
|
||||||
srcloc,
|
|
||||||
}
|
|
||||||
| &Inst::ULoad32 {
|
|
||||||
rd,
|
|
||||||
ref mem,
|
|
||||||
srcloc,
|
|
||||||
}
|
|
||||||
| &Inst::SLoad32 {
|
|
||||||
rd,
|
|
||||||
ref mem,
|
|
||||||
srcloc,
|
|
||||||
}
|
|
||||||
| &Inst::ULoad64 {
|
|
||||||
rd,
|
|
||||||
ref mem,
|
|
||||||
srcloc,
|
|
||||||
..
|
|
||||||
}
|
|
||||||
| &Inst::FpuLoad32 {
|
|
||||||
rd,
|
|
||||||
ref mem,
|
|
||||||
srcloc,
|
|
||||||
}
|
|
||||||
| &Inst::FpuLoad64 {
|
|
||||||
rd,
|
|
||||||
ref mem,
|
|
||||||
srcloc,
|
|
||||||
}
|
|
||||||
| &Inst::FpuLoad128 {
|
|
||||||
rd,
|
|
||||||
ref mem,
|
|
||||||
srcloc,
|
|
||||||
} => {
|
|
||||||
let (mem_insts, mem) = mem_finalize(sink.cur_offset(), mem, state);
|
let (mem_insts, mem) = mem_finalize(sink.cur_offset(), mem, state);
|
||||||
|
|
||||||
for inst in mem_insts.into_iter() {
|
for inst in mem_insts.into_iter() {
|
||||||
@@ -807,7 +777,8 @@ impl MachInstEmit for Inst {
|
|||||||
_ => unreachable!(),
|
_ => unreachable!(),
|
||||||
};
|
};
|
||||||
|
|
||||||
if let Some(srcloc) = srcloc {
|
let srcloc = state.cur_srcloc();
|
||||||
|
if srcloc != SourceLoc::default() {
|
||||||
// Register the offset at which the actual load instruction starts.
|
// Register the offset at which the actual load instruction starts.
|
||||||
sink.add_trap(srcloc, TrapCode::HeapOutOfBounds);
|
sink.add_trap(srcloc, TrapCode::HeapOutOfBounds);
|
||||||
}
|
}
|
||||||
@@ -890,42 +861,13 @@ impl MachInstEmit for Inst {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
&Inst::Store8 {
|
&Inst::Store8 { rd, ref mem }
|
||||||
rd,
|
| &Inst::Store16 { rd, ref mem }
|
||||||
ref mem,
|
| &Inst::Store32 { rd, ref mem }
|
||||||
srcloc,
|
| &Inst::Store64 { rd, ref mem, .. }
|
||||||
}
|
| &Inst::FpuStore32 { rd, ref mem }
|
||||||
| &Inst::Store16 {
|
| &Inst::FpuStore64 { rd, ref mem }
|
||||||
rd,
|
| &Inst::FpuStore128 { rd, ref mem } => {
|
||||||
ref mem,
|
|
||||||
srcloc,
|
|
||||||
}
|
|
||||||
| &Inst::Store32 {
|
|
||||||
rd,
|
|
||||||
ref mem,
|
|
||||||
srcloc,
|
|
||||||
}
|
|
||||||
| &Inst::Store64 {
|
|
||||||
rd,
|
|
||||||
ref mem,
|
|
||||||
srcloc,
|
|
||||||
..
|
|
||||||
}
|
|
||||||
| &Inst::FpuStore32 {
|
|
||||||
rd,
|
|
||||||
ref mem,
|
|
||||||
srcloc,
|
|
||||||
}
|
|
||||||
| &Inst::FpuStore64 {
|
|
||||||
rd,
|
|
||||||
ref mem,
|
|
||||||
srcloc,
|
|
||||||
}
|
|
||||||
| &Inst::FpuStore128 {
|
|
||||||
rd,
|
|
||||||
ref mem,
|
|
||||||
srcloc,
|
|
||||||
} => {
|
|
||||||
let (mem_insts, mem) = mem_finalize(sink.cur_offset(), mem, state);
|
let (mem_insts, mem) = mem_finalize(sink.cur_offset(), mem, state);
|
||||||
|
|
||||||
for inst in mem_insts.into_iter() {
|
for inst in mem_insts.into_iter() {
|
||||||
@@ -943,7 +885,8 @@ impl MachInstEmit for Inst {
|
|||||||
_ => unreachable!(),
|
_ => unreachable!(),
|
||||||
};
|
};
|
||||||
|
|
||||||
if let Some(srcloc) = srcloc {
|
let srcloc = state.cur_srcloc();
|
||||||
|
if srcloc != SourceLoc::default() {
|
||||||
// Register the offset at which the actual load instruction starts.
|
// Register the offset at which the actual load instruction starts.
|
||||||
sink.add_trap(srcloc, TrapCode::HeapOutOfBounds);
|
sink.add_trap(srcloc, TrapCode::HeapOutOfBounds);
|
||||||
}
|
}
|
||||||
@@ -1086,7 +1029,7 @@ impl MachInstEmit for Inst {
|
|||||||
} => {
|
} => {
|
||||||
sink.put4(enc_ccmp_imm(size, rn, imm, nzcv, cond));
|
sink.put4(enc_ccmp_imm(size, rn, imm, nzcv, cond));
|
||||||
}
|
}
|
||||||
&Inst::AtomicRMW { ty, op, srcloc } => {
|
&Inst::AtomicRMW { ty, op } => {
|
||||||
/* Emit this:
|
/* Emit this:
|
||||||
dmb ish
|
dmb ish
|
||||||
again:
|
again:
|
||||||
@@ -1124,7 +1067,8 @@ impl MachInstEmit for Inst {
|
|||||||
|
|
||||||
// again:
|
// again:
|
||||||
sink.bind_label(again_label);
|
sink.bind_label(again_label);
|
||||||
if let Some(srcloc) = srcloc {
|
let srcloc = state.cur_srcloc();
|
||||||
|
if srcloc != SourceLoc::default() {
|
||||||
sink.add_trap(srcloc, TrapCode::HeapOutOfBounds);
|
sink.add_trap(srcloc, TrapCode::HeapOutOfBounds);
|
||||||
}
|
}
|
||||||
sink.put4(enc_ldxr(ty, x27wr, x25)); // ldxr x27, [x25]
|
sink.put4(enc_ldxr(ty, x27wr, x25)); // ldxr x27, [x25]
|
||||||
@@ -1145,7 +1089,8 @@ impl MachInstEmit for Inst {
|
|||||||
sink.put4(enc_arith_rrr(bits_31_21, 0b000000, x28wr, x27, x26));
|
sink.put4(enc_arith_rrr(bits_31_21, 0b000000, x28wr, x27, x26));
|
||||||
}
|
}
|
||||||
|
|
||||||
if let Some(srcloc) = srcloc {
|
let srcloc = state.cur_srcloc();
|
||||||
|
if srcloc != SourceLoc::default() {
|
||||||
sink.add_trap(srcloc, TrapCode::HeapOutOfBounds);
|
sink.add_trap(srcloc, TrapCode::HeapOutOfBounds);
|
||||||
}
|
}
|
||||||
sink.put4(enc_stxr(ty, x24wr, x28, x25)); // stxr w24, x28, [x25]
|
sink.put4(enc_stxr(ty, x24wr, x28, x25)); // stxr w24, x28, [x25]
|
||||||
@@ -1162,7 +1107,7 @@ impl MachInstEmit for Inst {
|
|||||||
|
|
||||||
sink.put4(enc_dmb_ish()); // dmb ish
|
sink.put4(enc_dmb_ish()); // dmb ish
|
||||||
}
|
}
|
||||||
&Inst::AtomicCAS { ty, srcloc } => {
|
&Inst::AtomicCAS { ty } => {
|
||||||
/* Emit this:
|
/* Emit this:
|
||||||
dmb ish
|
dmb ish
|
||||||
again:
|
again:
|
||||||
@@ -1195,7 +1140,8 @@ impl MachInstEmit for Inst {
|
|||||||
|
|
||||||
// again:
|
// again:
|
||||||
sink.bind_label(again_label);
|
sink.bind_label(again_label);
|
||||||
if let Some(srcloc) = srcloc {
|
let srcloc = state.cur_srcloc();
|
||||||
|
if srcloc != SourceLoc::default() {
|
||||||
sink.add_trap(srcloc, TrapCode::HeapOutOfBounds);
|
sink.add_trap(srcloc, TrapCode::HeapOutOfBounds);
|
||||||
}
|
}
|
||||||
sink.put4(enc_ldxr(ty, x27wr, x25)); // ldxr x27, [x25]
|
sink.put4(enc_ldxr(ty, x27wr, x25)); // ldxr x27, [x25]
|
||||||
@@ -1230,7 +1176,8 @@ impl MachInstEmit for Inst {
|
|||||||
));
|
));
|
||||||
sink.use_label_at_offset(br_out_offset, out_label, LabelUse::Branch19);
|
sink.use_label_at_offset(br_out_offset, out_label, LabelUse::Branch19);
|
||||||
|
|
||||||
if let Some(srcloc) = srcloc {
|
let srcloc = state.cur_srcloc();
|
||||||
|
if srcloc != SourceLoc::default() {
|
||||||
sink.add_trap(srcloc, TrapCode::HeapOutOfBounds);
|
sink.add_trap(srcloc, TrapCode::HeapOutOfBounds);
|
||||||
}
|
}
|
||||||
sink.put4(enc_stxr(ty, x24wr, x28, x25)); // stxr w24, x28, [x25]
|
sink.put4(enc_stxr(ty, x24wr, x28, x25)); // stxr w24, x28, [x25]
|
||||||
@@ -1249,12 +1196,7 @@ impl MachInstEmit for Inst {
|
|||||||
sink.bind_label(out_label);
|
sink.bind_label(out_label);
|
||||||
sink.put4(enc_dmb_ish()); // dmb ish
|
sink.put4(enc_dmb_ish()); // dmb ish
|
||||||
}
|
}
|
||||||
&Inst::AtomicLoad {
|
&Inst::AtomicLoad { ty, r_data, r_addr } => {
|
||||||
ty,
|
|
||||||
r_data,
|
|
||||||
r_addr,
|
|
||||||
srcloc,
|
|
||||||
} => {
|
|
||||||
let op = match ty {
|
let op = match ty {
|
||||||
I8 => 0b0011100001,
|
I8 => 0b0011100001,
|
||||||
I16 => 0b0111100001,
|
I16 => 0b0111100001,
|
||||||
@@ -1264,7 +1206,8 @@ impl MachInstEmit for Inst {
|
|||||||
};
|
};
|
||||||
sink.put4(enc_dmb_ish()); // dmb ish
|
sink.put4(enc_dmb_ish()); // dmb ish
|
||||||
|
|
||||||
if let Some(srcloc) = srcloc {
|
let srcloc = state.cur_srcloc();
|
||||||
|
if srcloc != SourceLoc::default() {
|
||||||
sink.add_trap(srcloc, TrapCode::HeapOutOfBounds);
|
sink.add_trap(srcloc, TrapCode::HeapOutOfBounds);
|
||||||
}
|
}
|
||||||
let uimm12scaled_zero = UImm12Scaled::zero(I8 /*irrelevant*/);
|
let uimm12scaled_zero = UImm12Scaled::zero(I8 /*irrelevant*/);
|
||||||
@@ -1275,12 +1218,7 @@ impl MachInstEmit for Inst {
|
|||||||
r_data.to_reg(),
|
r_data.to_reg(),
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
&Inst::AtomicStore {
|
&Inst::AtomicStore { ty, r_data, r_addr } => {
|
||||||
ty,
|
|
||||||
r_data,
|
|
||||||
r_addr,
|
|
||||||
srcloc,
|
|
||||||
} => {
|
|
||||||
let op = match ty {
|
let op = match ty {
|
||||||
I8 => 0b0011100000,
|
I8 => 0b0011100000,
|
||||||
I16 => 0b0111100000,
|
I16 => 0b0111100000,
|
||||||
@@ -1289,7 +1227,8 @@ impl MachInstEmit for Inst {
|
|||||||
_ => unreachable!(),
|
_ => unreachable!(),
|
||||||
};
|
};
|
||||||
|
|
||||||
if let Some(srcloc) = srcloc {
|
let srcloc = state.cur_srcloc();
|
||||||
|
if srcloc != SourceLoc::default() {
|
||||||
sink.add_trap(srcloc, TrapCode::HeapOutOfBounds);
|
sink.add_trap(srcloc, TrapCode::HeapOutOfBounds);
|
||||||
}
|
}
|
||||||
let uimm12scaled_zero = UImm12Scaled::zero(I8 /*irrelevant*/);
|
let uimm12scaled_zero = UImm12Scaled::zero(I8 /*irrelevant*/);
|
||||||
@@ -1607,7 +1546,6 @@ impl MachInstEmit for Inst {
|
|||||||
let inst = Inst::FpuLoad64 {
|
let inst = Inst::FpuLoad64 {
|
||||||
rd,
|
rd,
|
||||||
mem: AMode::Label(MemLabel::PCRel(8)),
|
mem: AMode::Label(MemLabel::PCRel(8)),
|
||||||
srcloc: None,
|
|
||||||
};
|
};
|
||||||
inst.emit(sink, emit_info, state);
|
inst.emit(sink, emit_info, state);
|
||||||
let inst = Inst::Jump {
|
let inst = Inst::Jump {
|
||||||
@@ -1620,7 +1558,6 @@ impl MachInstEmit for Inst {
|
|||||||
let inst = Inst::FpuLoad128 {
|
let inst = Inst::FpuLoad128 {
|
||||||
rd,
|
rd,
|
||||||
mem: AMode::Label(MemLabel::PCRel(8)),
|
mem: AMode::Label(MemLabel::PCRel(8)),
|
||||||
srcloc: None,
|
|
||||||
};
|
};
|
||||||
inst.emit(sink, emit_info, state);
|
inst.emit(sink, emit_info, state);
|
||||||
let inst = Inst::Jump {
|
let inst = Inst::Jump {
|
||||||
@@ -1961,15 +1898,11 @@ impl MachInstEmit for Inst {
|
|||||||
};
|
};
|
||||||
sink.put4(enc_vec_rrr(top11, rm, bit15_10, rn, rd));
|
sink.put4(enc_vec_rrr(top11, rm, bit15_10, rn, rd));
|
||||||
}
|
}
|
||||||
&Inst::VecLoadReplicate {
|
&Inst::VecLoadReplicate { rd, rn, size } => {
|
||||||
rd,
|
|
||||||
rn,
|
|
||||||
size,
|
|
||||||
srcloc,
|
|
||||||
} => {
|
|
||||||
let (q, size) = size.enc_size();
|
let (q, size) = size.enc_size();
|
||||||
|
|
||||||
if let Some(srcloc) = srcloc {
|
let srcloc = state.cur_srcloc();
|
||||||
|
if srcloc != SourceLoc::default() {
|
||||||
// Register the offset at which the actual load instruction starts.
|
// Register the offset at which the actual load instruction starts.
|
||||||
sink.add_trap(srcloc, TrapCode::HeapOutOfBounds);
|
sink.add_trap(srcloc, TrapCode::HeapOutOfBounds);
|
||||||
}
|
}
|
||||||
@@ -2073,10 +2006,11 @@ impl MachInstEmit for Inst {
|
|||||||
if let Some(s) = state.take_stack_map() {
|
if let Some(s) = state.take_stack_map() {
|
||||||
sink.add_stack_map(StackMapExtent::UpcomingBytes(4), s);
|
sink.add_stack_map(StackMapExtent::UpcomingBytes(4), s);
|
||||||
}
|
}
|
||||||
sink.add_reloc(info.loc, Reloc::Arm64Call, &info.dest, 0);
|
let loc = state.cur_srcloc();
|
||||||
|
sink.add_reloc(loc, Reloc::Arm64Call, &info.dest, 0);
|
||||||
sink.put4(enc_jump26(0b100101, 0));
|
sink.put4(enc_jump26(0b100101, 0));
|
||||||
if info.opcode.is_call() {
|
if info.opcode.is_call() {
|
||||||
sink.add_call_site(info.loc, info.opcode);
|
sink.add_call_site(loc, info.opcode);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
&Inst::CallInd { ref info } => {
|
&Inst::CallInd { ref info } => {
|
||||||
@@ -2084,8 +2018,9 @@ impl MachInstEmit for Inst {
|
|||||||
sink.add_stack_map(StackMapExtent::UpcomingBytes(4), s);
|
sink.add_stack_map(StackMapExtent::UpcomingBytes(4), s);
|
||||||
}
|
}
|
||||||
sink.put4(0b1101011_0001_11111_000000_00000_00000 | (machreg_to_gpr(info.rn) << 5));
|
sink.put4(0b1101011_0001_11111_000000_00000_00000 | (machreg_to_gpr(info.rn) << 5));
|
||||||
|
let loc = state.cur_srcloc();
|
||||||
if info.opcode.is_call() {
|
if info.opcode.is_call() {
|
||||||
sink.add_call_site(info.loc, info.opcode);
|
sink.add_call_site(loc, info.opcode);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
&Inst::CondBr {
|
&Inst::CondBr {
|
||||||
@@ -2110,7 +2045,7 @@ impl MachInstEmit for Inst {
|
|||||||
}
|
}
|
||||||
sink.put4(enc_jump26(0b000101, not_taken.as_offset26_or_zero()));
|
sink.put4(enc_jump26(0b000101, not_taken.as_offset26_or_zero()));
|
||||||
}
|
}
|
||||||
&Inst::TrapIf { kind, trap_info } => {
|
&Inst::TrapIf { kind, trap_code } => {
|
||||||
// condbr KIND, LABEL
|
// condbr KIND, LABEL
|
||||||
let off = sink.cur_offset();
|
let off = sink.cur_offset();
|
||||||
let label = sink.get_label();
|
let label = sink.get_label();
|
||||||
@@ -2120,7 +2055,7 @@ impl MachInstEmit for Inst {
|
|||||||
));
|
));
|
||||||
sink.use_label_at_offset(off, label, LabelUse::Branch19);
|
sink.use_label_at_offset(off, label, LabelUse::Branch19);
|
||||||
// udf
|
// udf
|
||||||
let trap = Inst::Udf { trap_info };
|
let trap = Inst::Udf { trap_code };
|
||||||
trap.emit(sink, emit_info, state);
|
trap.emit(sink, emit_info, state);
|
||||||
// LABEL:
|
// LABEL:
|
||||||
sink.bind_label(label);
|
sink.bind_label(label);
|
||||||
@@ -2135,9 +2070,9 @@ impl MachInstEmit for Inst {
|
|||||||
&Inst::Brk => {
|
&Inst::Brk => {
|
||||||
sink.put4(0xd4200000);
|
sink.put4(0xd4200000);
|
||||||
}
|
}
|
||||||
&Inst::Udf { trap_info } => {
|
&Inst::Udf { trap_code } => {
|
||||||
let (srcloc, code) = trap_info;
|
let srcloc = state.cur_srcloc();
|
||||||
sink.add_trap(srcloc, code);
|
sink.add_trap(srcloc, trap_code);
|
||||||
if let Some(s) = state.take_stack_map() {
|
if let Some(s) = state.take_stack_map() {
|
||||||
sink.add_stack_map(StackMapExtent::UpcomingBytes(4), s);
|
sink.add_stack_map(StackMapExtent::UpcomingBytes(4), s);
|
||||||
}
|
}
|
||||||
@@ -2192,7 +2127,6 @@ impl MachInstEmit for Inst {
|
|||||||
I32,
|
I32,
|
||||||
ExtendOp::UXTW,
|
ExtendOp::UXTW,
|
||||||
),
|
),
|
||||||
srcloc: None, // can't cause a user trap.
|
|
||||||
};
|
};
|
||||||
inst.emit(sink, emit_info, state);
|
inst.emit(sink, emit_info, state);
|
||||||
// Add base of jump table to jump-table-sourced block offset
|
// Add base of jump table to jump-table-sourced block offset
|
||||||
@@ -2235,18 +2169,17 @@ impl MachInstEmit for Inst {
|
|||||||
rd,
|
rd,
|
||||||
ref name,
|
ref name,
|
||||||
offset,
|
offset,
|
||||||
srcloc,
|
|
||||||
} => {
|
} => {
|
||||||
let inst = Inst::ULoad64 {
|
let inst = Inst::ULoad64 {
|
||||||
rd,
|
rd,
|
||||||
mem: AMode::Label(MemLabel::PCRel(8)),
|
mem: AMode::Label(MemLabel::PCRel(8)),
|
||||||
srcloc: None, // can't cause a user trap.
|
|
||||||
};
|
};
|
||||||
inst.emit(sink, emit_info, state);
|
inst.emit(sink, emit_info, state);
|
||||||
let inst = Inst::Jump {
|
let inst = Inst::Jump {
|
||||||
dest: BranchTarget::ResolvedOffset(12),
|
dest: BranchTarget::ResolvedOffset(12),
|
||||||
};
|
};
|
||||||
inst.emit(sink, emit_info, state);
|
inst.emit(sink, emit_info, state);
|
||||||
|
let srcloc = state.cur_srcloc();
|
||||||
sink.add_reloc(srcloc, Reloc::Abs8, name, offset);
|
sink.add_reloc(srcloc, Reloc::Abs8, name, offset);
|
||||||
if emit_info.flags().emit_all_ones_funcaddrs() {
|
if emit_info.flags().emit_all_ones_funcaddrs() {
|
||||||
sink.put8(u64::max_value());
|
sink.put8(u64::max_value());
|
||||||
|
|||||||
@@ -1079,7 +1079,6 @@ fn test_aarch64_binemit() {
|
|||||||
Inst::ULoad8 {
|
Inst::ULoad8 {
|
||||||
rd: writable_xreg(1),
|
rd: writable_xreg(1),
|
||||||
mem: AMode::Unscaled(xreg(2), SImm9::zero()),
|
mem: AMode::Unscaled(xreg(2), SImm9::zero()),
|
||||||
srcloc: None,
|
|
||||||
},
|
},
|
||||||
"41004038",
|
"41004038",
|
||||||
"ldurb w1, [x2]",
|
"ldurb w1, [x2]",
|
||||||
@@ -1088,7 +1087,6 @@ fn test_aarch64_binemit() {
|
|||||||
Inst::ULoad8 {
|
Inst::ULoad8 {
|
||||||
rd: writable_xreg(1),
|
rd: writable_xreg(1),
|
||||||
mem: AMode::UnsignedOffset(xreg(2), UImm12Scaled::zero(I8)),
|
mem: AMode::UnsignedOffset(xreg(2), UImm12Scaled::zero(I8)),
|
||||||
srcloc: None,
|
|
||||||
},
|
},
|
||||||
"41004039",
|
"41004039",
|
||||||
"ldrb w1, [x2]",
|
"ldrb w1, [x2]",
|
||||||
@@ -1097,7 +1095,6 @@ fn test_aarch64_binemit() {
|
|||||||
Inst::ULoad8 {
|
Inst::ULoad8 {
|
||||||
rd: writable_xreg(1),
|
rd: writable_xreg(1),
|
||||||
mem: AMode::RegReg(xreg(2), xreg(5)),
|
mem: AMode::RegReg(xreg(2), xreg(5)),
|
||||||
srcloc: None,
|
|
||||||
},
|
},
|
||||||
"41686538",
|
"41686538",
|
||||||
"ldrb w1, [x2, x5]",
|
"ldrb w1, [x2, x5]",
|
||||||
@@ -1106,7 +1103,6 @@ fn test_aarch64_binemit() {
|
|||||||
Inst::SLoad8 {
|
Inst::SLoad8 {
|
||||||
rd: writable_xreg(1),
|
rd: writable_xreg(1),
|
||||||
mem: AMode::Unscaled(xreg(2), SImm9::zero()),
|
mem: AMode::Unscaled(xreg(2), SImm9::zero()),
|
||||||
srcloc: None,
|
|
||||||
},
|
},
|
||||||
"41008038",
|
"41008038",
|
||||||
"ldursb x1, [x2]",
|
"ldursb x1, [x2]",
|
||||||
@@ -1115,7 +1111,6 @@ fn test_aarch64_binemit() {
|
|||||||
Inst::SLoad8 {
|
Inst::SLoad8 {
|
||||||
rd: writable_xreg(1),
|
rd: writable_xreg(1),
|
||||||
mem: AMode::UnsignedOffset(xreg(2), UImm12Scaled::maybe_from_i64(63, I8).unwrap()),
|
mem: AMode::UnsignedOffset(xreg(2), UImm12Scaled::maybe_from_i64(63, I8).unwrap()),
|
||||||
srcloc: None,
|
|
||||||
},
|
},
|
||||||
"41FC8039",
|
"41FC8039",
|
||||||
"ldrsb x1, [x2, #63]",
|
"ldrsb x1, [x2, #63]",
|
||||||
@@ -1124,7 +1119,6 @@ fn test_aarch64_binemit() {
|
|||||||
Inst::SLoad8 {
|
Inst::SLoad8 {
|
||||||
rd: writable_xreg(1),
|
rd: writable_xreg(1),
|
||||||
mem: AMode::RegReg(xreg(2), xreg(5)),
|
mem: AMode::RegReg(xreg(2), xreg(5)),
|
||||||
srcloc: None,
|
|
||||||
},
|
},
|
||||||
"4168A538",
|
"4168A538",
|
||||||
"ldrsb x1, [x2, x5]",
|
"ldrsb x1, [x2, x5]",
|
||||||
@@ -1133,7 +1127,6 @@ fn test_aarch64_binemit() {
|
|||||||
Inst::ULoad16 {
|
Inst::ULoad16 {
|
||||||
rd: writable_xreg(1),
|
rd: writable_xreg(1),
|
||||||
mem: AMode::Unscaled(xreg(2), SImm9::maybe_from_i64(5).unwrap()),
|
mem: AMode::Unscaled(xreg(2), SImm9::maybe_from_i64(5).unwrap()),
|
||||||
srcloc: None,
|
|
||||||
},
|
},
|
||||||
"41504078",
|
"41504078",
|
||||||
"ldurh w1, [x2, #5]",
|
"ldurh w1, [x2, #5]",
|
||||||
@@ -1142,7 +1135,6 @@ fn test_aarch64_binemit() {
|
|||||||
Inst::ULoad16 {
|
Inst::ULoad16 {
|
||||||
rd: writable_xreg(1),
|
rd: writable_xreg(1),
|
||||||
mem: AMode::UnsignedOffset(xreg(2), UImm12Scaled::maybe_from_i64(8, I16).unwrap()),
|
mem: AMode::UnsignedOffset(xreg(2), UImm12Scaled::maybe_from_i64(8, I16).unwrap()),
|
||||||
srcloc: None,
|
|
||||||
},
|
},
|
||||||
"41104079",
|
"41104079",
|
||||||
"ldrh w1, [x2, #8]",
|
"ldrh w1, [x2, #8]",
|
||||||
@@ -1151,7 +1143,6 @@ fn test_aarch64_binemit() {
|
|||||||
Inst::ULoad16 {
|
Inst::ULoad16 {
|
||||||
rd: writable_xreg(1),
|
rd: writable_xreg(1),
|
||||||
mem: AMode::RegScaled(xreg(2), xreg(3), I16),
|
mem: AMode::RegScaled(xreg(2), xreg(3), I16),
|
||||||
srcloc: None,
|
|
||||||
},
|
},
|
||||||
"41786378",
|
"41786378",
|
||||||
"ldrh w1, [x2, x3, LSL #1]",
|
"ldrh w1, [x2, x3, LSL #1]",
|
||||||
@@ -1160,7 +1151,6 @@ fn test_aarch64_binemit() {
|
|||||||
Inst::SLoad16 {
|
Inst::SLoad16 {
|
||||||
rd: writable_xreg(1),
|
rd: writable_xreg(1),
|
||||||
mem: AMode::Unscaled(xreg(2), SImm9::zero()),
|
mem: AMode::Unscaled(xreg(2), SImm9::zero()),
|
||||||
srcloc: None,
|
|
||||||
},
|
},
|
||||||
"41008078",
|
"41008078",
|
||||||
"ldursh x1, [x2]",
|
"ldursh x1, [x2]",
|
||||||
@@ -1169,7 +1159,6 @@ fn test_aarch64_binemit() {
|
|||||||
Inst::SLoad16 {
|
Inst::SLoad16 {
|
||||||
rd: writable_xreg(28),
|
rd: writable_xreg(28),
|
||||||
mem: AMode::UnsignedOffset(xreg(20), UImm12Scaled::maybe_from_i64(24, I16).unwrap()),
|
mem: AMode::UnsignedOffset(xreg(20), UImm12Scaled::maybe_from_i64(24, I16).unwrap()),
|
||||||
srcloc: None,
|
|
||||||
},
|
},
|
||||||
"9C328079",
|
"9C328079",
|
||||||
"ldrsh x28, [x20, #24]",
|
"ldrsh x28, [x20, #24]",
|
||||||
@@ -1178,7 +1167,6 @@ fn test_aarch64_binemit() {
|
|||||||
Inst::SLoad16 {
|
Inst::SLoad16 {
|
||||||
rd: writable_xreg(28),
|
rd: writable_xreg(28),
|
||||||
mem: AMode::RegScaled(xreg(20), xreg(20), I16),
|
mem: AMode::RegScaled(xreg(20), xreg(20), I16),
|
||||||
srcloc: None,
|
|
||||||
},
|
},
|
||||||
"9C7AB478",
|
"9C7AB478",
|
||||||
"ldrsh x28, [x20, x20, LSL #1]",
|
"ldrsh x28, [x20, x20, LSL #1]",
|
||||||
@@ -1187,7 +1175,6 @@ fn test_aarch64_binemit() {
|
|||||||
Inst::ULoad32 {
|
Inst::ULoad32 {
|
||||||
rd: writable_xreg(1),
|
rd: writable_xreg(1),
|
||||||
mem: AMode::Unscaled(xreg(2), SImm9::zero()),
|
mem: AMode::Unscaled(xreg(2), SImm9::zero()),
|
||||||
srcloc: None,
|
|
||||||
},
|
},
|
||||||
"410040B8",
|
"410040B8",
|
||||||
"ldur w1, [x2]",
|
"ldur w1, [x2]",
|
||||||
@@ -1196,7 +1183,6 @@ fn test_aarch64_binemit() {
|
|||||||
Inst::ULoad32 {
|
Inst::ULoad32 {
|
||||||
rd: writable_xreg(12),
|
rd: writable_xreg(12),
|
||||||
mem: AMode::UnsignedOffset(xreg(0), UImm12Scaled::maybe_from_i64(204, I32).unwrap()),
|
mem: AMode::UnsignedOffset(xreg(0), UImm12Scaled::maybe_from_i64(204, I32).unwrap()),
|
||||||
srcloc: None,
|
|
||||||
},
|
},
|
||||||
"0CCC40B9",
|
"0CCC40B9",
|
||||||
"ldr w12, [x0, #204]",
|
"ldr w12, [x0, #204]",
|
||||||
@@ -1205,7 +1191,6 @@ fn test_aarch64_binemit() {
|
|||||||
Inst::ULoad32 {
|
Inst::ULoad32 {
|
||||||
rd: writable_xreg(1),
|
rd: writable_xreg(1),
|
||||||
mem: AMode::RegScaled(xreg(2), xreg(12), I32),
|
mem: AMode::RegScaled(xreg(2), xreg(12), I32),
|
||||||
srcloc: None,
|
|
||||||
},
|
},
|
||||||
"41786CB8",
|
"41786CB8",
|
||||||
"ldr w1, [x2, x12, LSL #2]",
|
"ldr w1, [x2, x12, LSL #2]",
|
||||||
@@ -1214,7 +1199,6 @@ fn test_aarch64_binemit() {
|
|||||||
Inst::SLoad32 {
|
Inst::SLoad32 {
|
||||||
rd: writable_xreg(1),
|
rd: writable_xreg(1),
|
||||||
mem: AMode::Unscaled(xreg(2), SImm9::zero()),
|
mem: AMode::Unscaled(xreg(2), SImm9::zero()),
|
||||||
srcloc: None,
|
|
||||||
},
|
},
|
||||||
"410080B8",
|
"410080B8",
|
||||||
"ldursw x1, [x2]",
|
"ldursw x1, [x2]",
|
||||||
@@ -1223,7 +1207,6 @@ fn test_aarch64_binemit() {
|
|||||||
Inst::SLoad32 {
|
Inst::SLoad32 {
|
||||||
rd: writable_xreg(12),
|
rd: writable_xreg(12),
|
||||||
mem: AMode::UnsignedOffset(xreg(1), UImm12Scaled::maybe_from_i64(16380, I32).unwrap()),
|
mem: AMode::UnsignedOffset(xreg(1), UImm12Scaled::maybe_from_i64(16380, I32).unwrap()),
|
||||||
srcloc: None,
|
|
||||||
},
|
},
|
||||||
"2CFCBFB9",
|
"2CFCBFB9",
|
||||||
"ldrsw x12, [x1, #16380]",
|
"ldrsw x12, [x1, #16380]",
|
||||||
@@ -1232,7 +1215,6 @@ fn test_aarch64_binemit() {
|
|||||||
Inst::SLoad32 {
|
Inst::SLoad32 {
|
||||||
rd: writable_xreg(1),
|
rd: writable_xreg(1),
|
||||||
mem: AMode::RegScaled(xreg(5), xreg(1), I32),
|
mem: AMode::RegScaled(xreg(5), xreg(1), I32),
|
||||||
srcloc: None,
|
|
||||||
},
|
},
|
||||||
"A178A1B8",
|
"A178A1B8",
|
||||||
"ldrsw x1, [x5, x1, LSL #2]",
|
"ldrsw x1, [x5, x1, LSL #2]",
|
||||||
@@ -1241,7 +1223,6 @@ fn test_aarch64_binemit() {
|
|||||||
Inst::ULoad64 {
|
Inst::ULoad64 {
|
||||||
rd: writable_xreg(1),
|
rd: writable_xreg(1),
|
||||||
mem: AMode::Unscaled(xreg(2), SImm9::zero()),
|
mem: AMode::Unscaled(xreg(2), SImm9::zero()),
|
||||||
srcloc: None,
|
|
||||||
},
|
},
|
||||||
"410040F8",
|
"410040F8",
|
||||||
"ldur x1, [x2]",
|
"ldur x1, [x2]",
|
||||||
@@ -1250,7 +1231,6 @@ fn test_aarch64_binemit() {
|
|||||||
Inst::ULoad64 {
|
Inst::ULoad64 {
|
||||||
rd: writable_xreg(1),
|
rd: writable_xreg(1),
|
||||||
mem: AMode::Unscaled(xreg(2), SImm9::maybe_from_i64(-256).unwrap()),
|
mem: AMode::Unscaled(xreg(2), SImm9::maybe_from_i64(-256).unwrap()),
|
||||||
srcloc: None,
|
|
||||||
},
|
},
|
||||||
"410050F8",
|
"410050F8",
|
||||||
"ldur x1, [x2, #-256]",
|
"ldur x1, [x2, #-256]",
|
||||||
@@ -1259,7 +1239,6 @@ fn test_aarch64_binemit() {
|
|||||||
Inst::ULoad64 {
|
Inst::ULoad64 {
|
||||||
rd: writable_xreg(1),
|
rd: writable_xreg(1),
|
||||||
mem: AMode::Unscaled(xreg(2), SImm9::maybe_from_i64(255).unwrap()),
|
mem: AMode::Unscaled(xreg(2), SImm9::maybe_from_i64(255).unwrap()),
|
||||||
srcloc: None,
|
|
||||||
},
|
},
|
||||||
"41F04FF8",
|
"41F04FF8",
|
||||||
"ldur x1, [x2, #255]",
|
"ldur x1, [x2, #255]",
|
||||||
@@ -1268,7 +1247,6 @@ fn test_aarch64_binemit() {
|
|||||||
Inst::ULoad64 {
|
Inst::ULoad64 {
|
||||||
rd: writable_xreg(1),
|
rd: writable_xreg(1),
|
||||||
mem: AMode::UnsignedOffset(xreg(2), UImm12Scaled::maybe_from_i64(32760, I64).unwrap()),
|
mem: AMode::UnsignedOffset(xreg(2), UImm12Scaled::maybe_from_i64(32760, I64).unwrap()),
|
||||||
srcloc: None,
|
|
||||||
},
|
},
|
||||||
"41FC7FF9",
|
"41FC7FF9",
|
||||||
"ldr x1, [x2, #32760]",
|
"ldr x1, [x2, #32760]",
|
||||||
@@ -1277,7 +1255,6 @@ fn test_aarch64_binemit() {
|
|||||||
Inst::ULoad64 {
|
Inst::ULoad64 {
|
||||||
rd: writable_xreg(1),
|
rd: writable_xreg(1),
|
||||||
mem: AMode::RegReg(xreg(2), xreg(3)),
|
mem: AMode::RegReg(xreg(2), xreg(3)),
|
||||||
srcloc: None,
|
|
||||||
},
|
},
|
||||||
"416863F8",
|
"416863F8",
|
||||||
"ldr x1, [x2, x3]",
|
"ldr x1, [x2, x3]",
|
||||||
@@ -1286,7 +1263,6 @@ fn test_aarch64_binemit() {
|
|||||||
Inst::ULoad64 {
|
Inst::ULoad64 {
|
||||||
rd: writable_xreg(1),
|
rd: writable_xreg(1),
|
||||||
mem: AMode::RegScaled(xreg(2), xreg(3), I64),
|
mem: AMode::RegScaled(xreg(2), xreg(3), I64),
|
||||||
srcloc: None,
|
|
||||||
},
|
},
|
||||||
"417863F8",
|
"417863F8",
|
||||||
"ldr x1, [x2, x3, LSL #3]",
|
"ldr x1, [x2, x3, LSL #3]",
|
||||||
@@ -1295,7 +1271,6 @@ fn test_aarch64_binemit() {
|
|||||||
Inst::ULoad64 {
|
Inst::ULoad64 {
|
||||||
rd: writable_xreg(1),
|
rd: writable_xreg(1),
|
||||||
mem: AMode::RegScaledExtended(xreg(2), xreg(3), I64, ExtendOp::SXTW),
|
mem: AMode::RegScaledExtended(xreg(2), xreg(3), I64, ExtendOp::SXTW),
|
||||||
srcloc: None,
|
|
||||||
},
|
},
|
||||||
"41D863F8",
|
"41D863F8",
|
||||||
"ldr x1, [x2, w3, SXTW #3]",
|
"ldr x1, [x2, w3, SXTW #3]",
|
||||||
@@ -1304,7 +1279,6 @@ fn test_aarch64_binemit() {
|
|||||||
Inst::ULoad64 {
|
Inst::ULoad64 {
|
||||||
rd: writable_xreg(1),
|
rd: writable_xreg(1),
|
||||||
mem: AMode::RegExtended(xreg(2), xreg(3), ExtendOp::SXTW),
|
mem: AMode::RegExtended(xreg(2), xreg(3), ExtendOp::SXTW),
|
||||||
srcloc: None,
|
|
||||||
},
|
},
|
||||||
"41C863F8",
|
"41C863F8",
|
||||||
"ldr x1, [x2, w3, SXTW]",
|
"ldr x1, [x2, w3, SXTW]",
|
||||||
@@ -1313,7 +1287,6 @@ fn test_aarch64_binemit() {
|
|||||||
Inst::ULoad64 {
|
Inst::ULoad64 {
|
||||||
rd: writable_xreg(1),
|
rd: writable_xreg(1),
|
||||||
mem: AMode::Label(MemLabel::PCRel(64)),
|
mem: AMode::Label(MemLabel::PCRel(64)),
|
||||||
srcloc: None,
|
|
||||||
},
|
},
|
||||||
"01020058",
|
"01020058",
|
||||||
"ldr x1, pc+64",
|
"ldr x1, pc+64",
|
||||||
@@ -1322,7 +1295,6 @@ fn test_aarch64_binemit() {
|
|||||||
Inst::ULoad64 {
|
Inst::ULoad64 {
|
||||||
rd: writable_xreg(1),
|
rd: writable_xreg(1),
|
||||||
mem: AMode::PreIndexed(writable_xreg(2), SImm9::maybe_from_i64(16).unwrap()),
|
mem: AMode::PreIndexed(writable_xreg(2), SImm9::maybe_from_i64(16).unwrap()),
|
||||||
srcloc: None,
|
|
||||||
},
|
},
|
||||||
"410C41F8",
|
"410C41F8",
|
||||||
"ldr x1, [x2, #16]!",
|
"ldr x1, [x2, #16]!",
|
||||||
@@ -1331,7 +1303,6 @@ fn test_aarch64_binemit() {
|
|||||||
Inst::ULoad64 {
|
Inst::ULoad64 {
|
||||||
rd: writable_xreg(1),
|
rd: writable_xreg(1),
|
||||||
mem: AMode::PostIndexed(writable_xreg(2), SImm9::maybe_from_i64(16).unwrap()),
|
mem: AMode::PostIndexed(writable_xreg(2), SImm9::maybe_from_i64(16).unwrap()),
|
||||||
srcloc: None,
|
|
||||||
},
|
},
|
||||||
"410441F8",
|
"410441F8",
|
||||||
"ldr x1, [x2], #16",
|
"ldr x1, [x2], #16",
|
||||||
@@ -1340,7 +1311,6 @@ fn test_aarch64_binemit() {
|
|||||||
Inst::ULoad64 {
|
Inst::ULoad64 {
|
||||||
rd: writable_xreg(1),
|
rd: writable_xreg(1),
|
||||||
mem: AMode::FPOffset(32768, I8),
|
mem: AMode::FPOffset(32768, I8),
|
||||||
srcloc: None,
|
|
||||||
},
|
},
|
||||||
"100090D2B063308B010240F9",
|
"100090D2B063308B010240F9",
|
||||||
"movz x16, #32768 ; add x16, fp, x16, UXTX ; ldr x1, [x16]",
|
"movz x16, #32768 ; add x16, fp, x16, UXTX ; ldr x1, [x16]",
|
||||||
@@ -1349,7 +1319,6 @@ fn test_aarch64_binemit() {
|
|||||||
Inst::ULoad64 {
|
Inst::ULoad64 {
|
||||||
rd: writable_xreg(1),
|
rd: writable_xreg(1),
|
||||||
mem: AMode::FPOffset(-32768, I8),
|
mem: AMode::FPOffset(-32768, I8),
|
||||||
srcloc: None,
|
|
||||||
},
|
},
|
||||||
"F0FF8F92B063308B010240F9",
|
"F0FF8F92B063308B010240F9",
|
||||||
"movn x16, #32767 ; add x16, fp, x16, UXTX ; ldr x1, [x16]",
|
"movn x16, #32767 ; add x16, fp, x16, UXTX ; ldr x1, [x16]",
|
||||||
@@ -1358,7 +1327,6 @@ fn test_aarch64_binemit() {
|
|||||||
Inst::ULoad64 {
|
Inst::ULoad64 {
|
||||||
rd: writable_xreg(1),
|
rd: writable_xreg(1),
|
||||||
mem: AMode::FPOffset(1048576, I8), // 2^20
|
mem: AMode::FPOffset(1048576, I8), // 2^20
|
||||||
srcloc: None,
|
|
||||||
},
|
},
|
||||||
"1002A0D2B063308B010240F9",
|
"1002A0D2B063308B010240F9",
|
||||||
"movz x16, #16, LSL #16 ; add x16, fp, x16, UXTX ; ldr x1, [x16]",
|
"movz x16, #16, LSL #16 ; add x16, fp, x16, UXTX ; ldr x1, [x16]",
|
||||||
@@ -1367,7 +1335,6 @@ fn test_aarch64_binemit() {
|
|||||||
Inst::ULoad64 {
|
Inst::ULoad64 {
|
||||||
rd: writable_xreg(1),
|
rd: writable_xreg(1),
|
||||||
mem: AMode::FPOffset(1048576 + 1, I8), // 2^20 + 1
|
mem: AMode::FPOffset(1048576 + 1, I8), // 2^20 + 1
|
||||||
srcloc: None,
|
|
||||||
},
|
},
|
||||||
"300080521002A072B063308B010240F9",
|
"300080521002A072B063308B010240F9",
|
||||||
"movz w16, #1 ; movk w16, #16, LSL #16 ; add x16, fp, x16, UXTX ; ldr x1, [x16]",
|
"movz w16, #1 ; movk w16, #16, LSL #16 ; add x16, fp, x16, UXTX ; ldr x1, [x16]",
|
||||||
@@ -1377,7 +1344,6 @@ fn test_aarch64_binemit() {
|
|||||||
Inst::ULoad64 {
|
Inst::ULoad64 {
|
||||||
rd: writable_xreg(1),
|
rd: writable_xreg(1),
|
||||||
mem: AMode::RegOffset(xreg(7), 8, I64),
|
mem: AMode::RegOffset(xreg(7), 8, I64),
|
||||||
srcloc: None,
|
|
||||||
},
|
},
|
||||||
"E18040F8",
|
"E18040F8",
|
||||||
"ldur x1, [x7, #8]",
|
"ldur x1, [x7, #8]",
|
||||||
@@ -1387,7 +1353,6 @@ fn test_aarch64_binemit() {
|
|||||||
Inst::ULoad64 {
|
Inst::ULoad64 {
|
||||||
rd: writable_xreg(1),
|
rd: writable_xreg(1),
|
||||||
mem: AMode::RegOffset(xreg(7), 1024, I64),
|
mem: AMode::RegOffset(xreg(7), 1024, I64),
|
||||||
srcloc: None,
|
|
||||||
},
|
},
|
||||||
"E10042F9",
|
"E10042F9",
|
||||||
"ldr x1, [x7, #1024]",
|
"ldr x1, [x7, #1024]",
|
||||||
@@ -1397,7 +1362,6 @@ fn test_aarch64_binemit() {
|
|||||||
Inst::ULoad64 {
|
Inst::ULoad64 {
|
||||||
rd: writable_xreg(1),
|
rd: writable_xreg(1),
|
||||||
mem: AMode::RegOffset(xreg(7), 1048576, I64),
|
mem: AMode::RegOffset(xreg(7), 1048576, I64),
|
||||||
srcloc: None,
|
|
||||||
},
|
},
|
||||||
"1002A0D2F060308B010240F9",
|
"1002A0D2F060308B010240F9",
|
||||||
"movz x16, #16, LSL #16 ; add x16, x7, x16, UXTX ; ldr x1, [x16]",
|
"movz x16, #16, LSL #16 ; add x16, x7, x16, UXTX ; ldr x1, [x16]",
|
||||||
@@ -1407,7 +1371,6 @@ fn test_aarch64_binemit() {
|
|||||||
Inst::Store8 {
|
Inst::Store8 {
|
||||||
rd: xreg(1),
|
rd: xreg(1),
|
||||||
mem: AMode::Unscaled(xreg(2), SImm9::zero()),
|
mem: AMode::Unscaled(xreg(2), SImm9::zero()),
|
||||||
srcloc: None,
|
|
||||||
},
|
},
|
||||||
"41000038",
|
"41000038",
|
||||||
"sturb w1, [x2]",
|
"sturb w1, [x2]",
|
||||||
@@ -1416,7 +1379,6 @@ fn test_aarch64_binemit() {
|
|||||||
Inst::Store8 {
|
Inst::Store8 {
|
||||||
rd: xreg(1),
|
rd: xreg(1),
|
||||||
mem: AMode::UnsignedOffset(xreg(2), UImm12Scaled::maybe_from_i64(4095, I8).unwrap()),
|
mem: AMode::UnsignedOffset(xreg(2), UImm12Scaled::maybe_from_i64(4095, I8).unwrap()),
|
||||||
srcloc: None,
|
|
||||||
},
|
},
|
||||||
"41FC3F39",
|
"41FC3F39",
|
||||||
"strb w1, [x2, #4095]",
|
"strb w1, [x2, #4095]",
|
||||||
@@ -1425,7 +1387,6 @@ fn test_aarch64_binemit() {
|
|||||||
Inst::Store16 {
|
Inst::Store16 {
|
||||||
rd: xreg(1),
|
rd: xreg(1),
|
||||||
mem: AMode::Unscaled(xreg(2), SImm9::zero()),
|
mem: AMode::Unscaled(xreg(2), SImm9::zero()),
|
||||||
srcloc: None,
|
|
||||||
},
|
},
|
||||||
"41000078",
|
"41000078",
|
||||||
"sturh w1, [x2]",
|
"sturh w1, [x2]",
|
||||||
@@ -1434,7 +1395,6 @@ fn test_aarch64_binemit() {
|
|||||||
Inst::Store16 {
|
Inst::Store16 {
|
||||||
rd: xreg(1),
|
rd: xreg(1),
|
||||||
mem: AMode::UnsignedOffset(xreg(2), UImm12Scaled::maybe_from_i64(8190, I16).unwrap()),
|
mem: AMode::UnsignedOffset(xreg(2), UImm12Scaled::maybe_from_i64(8190, I16).unwrap()),
|
||||||
srcloc: None,
|
|
||||||
},
|
},
|
||||||
"41FC3F79",
|
"41FC3F79",
|
||||||
"strh w1, [x2, #8190]",
|
"strh w1, [x2, #8190]",
|
||||||
@@ -1443,7 +1403,6 @@ fn test_aarch64_binemit() {
|
|||||||
Inst::Store32 {
|
Inst::Store32 {
|
||||||
rd: xreg(1),
|
rd: xreg(1),
|
||||||
mem: AMode::Unscaled(xreg(2), SImm9::zero()),
|
mem: AMode::Unscaled(xreg(2), SImm9::zero()),
|
||||||
srcloc: None,
|
|
||||||
},
|
},
|
||||||
"410000B8",
|
"410000B8",
|
||||||
"stur w1, [x2]",
|
"stur w1, [x2]",
|
||||||
@@ -1452,7 +1411,6 @@ fn test_aarch64_binemit() {
|
|||||||
Inst::Store32 {
|
Inst::Store32 {
|
||||||
rd: xreg(1),
|
rd: xreg(1),
|
||||||
mem: AMode::UnsignedOffset(xreg(2), UImm12Scaled::maybe_from_i64(16380, I32).unwrap()),
|
mem: AMode::UnsignedOffset(xreg(2), UImm12Scaled::maybe_from_i64(16380, I32).unwrap()),
|
||||||
srcloc: None,
|
|
||||||
},
|
},
|
||||||
"41FC3FB9",
|
"41FC3FB9",
|
||||||
"str w1, [x2, #16380]",
|
"str w1, [x2, #16380]",
|
||||||
@@ -1461,7 +1419,6 @@ fn test_aarch64_binemit() {
|
|||||||
Inst::Store64 {
|
Inst::Store64 {
|
||||||
rd: xreg(1),
|
rd: xreg(1),
|
||||||
mem: AMode::Unscaled(xreg(2), SImm9::zero()),
|
mem: AMode::Unscaled(xreg(2), SImm9::zero()),
|
||||||
srcloc: None,
|
|
||||||
},
|
},
|
||||||
"410000F8",
|
"410000F8",
|
||||||
"stur x1, [x2]",
|
"stur x1, [x2]",
|
||||||
@@ -1470,7 +1427,6 @@ fn test_aarch64_binemit() {
|
|||||||
Inst::Store64 {
|
Inst::Store64 {
|
||||||
rd: xreg(1),
|
rd: xreg(1),
|
||||||
mem: AMode::UnsignedOffset(xreg(2), UImm12Scaled::maybe_from_i64(32760, I64).unwrap()),
|
mem: AMode::UnsignedOffset(xreg(2), UImm12Scaled::maybe_from_i64(32760, I64).unwrap()),
|
||||||
srcloc: None,
|
|
||||||
},
|
},
|
||||||
"41FC3FF9",
|
"41FC3FF9",
|
||||||
"str x1, [x2, #32760]",
|
"str x1, [x2, #32760]",
|
||||||
@@ -1479,7 +1435,6 @@ fn test_aarch64_binemit() {
|
|||||||
Inst::Store64 {
|
Inst::Store64 {
|
||||||
rd: xreg(1),
|
rd: xreg(1),
|
||||||
mem: AMode::RegReg(xreg(2), xreg(3)),
|
mem: AMode::RegReg(xreg(2), xreg(3)),
|
||||||
srcloc: None,
|
|
||||||
},
|
},
|
||||||
"416823F8",
|
"416823F8",
|
||||||
"str x1, [x2, x3]",
|
"str x1, [x2, x3]",
|
||||||
@@ -1488,7 +1443,6 @@ fn test_aarch64_binemit() {
|
|||||||
Inst::Store64 {
|
Inst::Store64 {
|
||||||
rd: xreg(1),
|
rd: xreg(1),
|
||||||
mem: AMode::RegScaled(xreg(2), xreg(3), I64),
|
mem: AMode::RegScaled(xreg(2), xreg(3), I64),
|
||||||
srcloc: None,
|
|
||||||
},
|
},
|
||||||
"417823F8",
|
"417823F8",
|
||||||
"str x1, [x2, x3, LSL #3]",
|
"str x1, [x2, x3, LSL #3]",
|
||||||
@@ -1497,7 +1451,6 @@ fn test_aarch64_binemit() {
|
|||||||
Inst::Store64 {
|
Inst::Store64 {
|
||||||
rd: xreg(1),
|
rd: xreg(1),
|
||||||
mem: AMode::RegScaledExtended(xreg(2), xreg(3), I64, ExtendOp::UXTW),
|
mem: AMode::RegScaledExtended(xreg(2), xreg(3), I64, ExtendOp::UXTW),
|
||||||
srcloc: None,
|
|
||||||
},
|
},
|
||||||
"415823F8",
|
"415823F8",
|
||||||
"str x1, [x2, w3, UXTW #3]",
|
"str x1, [x2, w3, UXTW #3]",
|
||||||
@@ -1506,7 +1459,6 @@ fn test_aarch64_binemit() {
|
|||||||
Inst::Store64 {
|
Inst::Store64 {
|
||||||
rd: xreg(1),
|
rd: xreg(1),
|
||||||
mem: AMode::RegExtended(xreg(2), xreg(3), ExtendOp::UXTW),
|
mem: AMode::RegExtended(xreg(2), xreg(3), ExtendOp::UXTW),
|
||||||
srcloc: None,
|
|
||||||
},
|
},
|
||||||
"414823F8",
|
"414823F8",
|
||||||
"str x1, [x2, w3, UXTW]",
|
"str x1, [x2, w3, UXTW]",
|
||||||
@@ -1515,7 +1467,6 @@ fn test_aarch64_binemit() {
|
|||||||
Inst::Store64 {
|
Inst::Store64 {
|
||||||
rd: xreg(1),
|
rd: xreg(1),
|
||||||
mem: AMode::PreIndexed(writable_xreg(2), SImm9::maybe_from_i64(16).unwrap()),
|
mem: AMode::PreIndexed(writable_xreg(2), SImm9::maybe_from_i64(16).unwrap()),
|
||||||
srcloc: None,
|
|
||||||
},
|
},
|
||||||
"410C01F8",
|
"410C01F8",
|
||||||
"str x1, [x2, #16]!",
|
"str x1, [x2, #16]!",
|
||||||
@@ -1524,7 +1475,6 @@ fn test_aarch64_binemit() {
|
|||||||
Inst::Store64 {
|
Inst::Store64 {
|
||||||
rd: xreg(1),
|
rd: xreg(1),
|
||||||
mem: AMode::PostIndexed(writable_xreg(2), SImm9::maybe_from_i64(16).unwrap()),
|
mem: AMode::PostIndexed(writable_xreg(2), SImm9::maybe_from_i64(16).unwrap()),
|
||||||
srcloc: None,
|
|
||||||
},
|
},
|
||||||
"410401F8",
|
"410401F8",
|
||||||
"str x1, [x2], #16",
|
"str x1, [x2], #16",
|
||||||
@@ -3911,7 +3861,7 @@ fn test_aarch64_binemit() {
|
|||||||
Inst::VecLoadReplicate {
|
Inst::VecLoadReplicate {
|
||||||
rd: writable_vreg(31),
|
rd: writable_vreg(31),
|
||||||
rn: xreg(0),
|
rn: xreg(0),
|
||||||
srcloc: None,
|
|
||||||
size: VectorSize::Size64x2,
|
size: VectorSize::Size64x2,
|
||||||
},
|
},
|
||||||
"1FCC404D",
|
"1FCC404D",
|
||||||
@@ -3922,7 +3872,7 @@ fn test_aarch64_binemit() {
|
|||||||
Inst::VecLoadReplicate {
|
Inst::VecLoadReplicate {
|
||||||
rd: writable_vreg(0),
|
rd: writable_vreg(0),
|
||||||
rn: xreg(25),
|
rn: xreg(25),
|
||||||
srcloc: None,
|
|
||||||
size: VectorSize::Size8x8,
|
size: VectorSize::Size8x8,
|
||||||
},
|
},
|
||||||
"20C3400D",
|
"20C3400D",
|
||||||
@@ -4050,7 +4000,7 @@ fn test_aarch64_binemit() {
|
|||||||
|
|
||||||
insns.push((
|
insns.push((
|
||||||
Inst::TrapIf {
|
Inst::TrapIf {
|
||||||
trap_info: (SourceLoc::default(), TrapCode::Interrupt),
|
trap_code: TrapCode::Interrupt,
|
||||||
kind: CondBrKind::NotZero(xreg(8)),
|
kind: CondBrKind::NotZero(xreg(8)),
|
||||||
},
|
},
|
||||||
"480000B40000A0D4",
|
"480000B40000A0D4",
|
||||||
@@ -4058,7 +4008,7 @@ fn test_aarch64_binemit() {
|
|||||||
));
|
));
|
||||||
insns.push((
|
insns.push((
|
||||||
Inst::TrapIf {
|
Inst::TrapIf {
|
||||||
trap_info: (SourceLoc::default(), TrapCode::Interrupt),
|
trap_code: TrapCode::Interrupt,
|
||||||
kind: CondBrKind::Zero(xreg(8)),
|
kind: CondBrKind::Zero(xreg(8)),
|
||||||
},
|
},
|
||||||
"480000B50000A0D4",
|
"480000B50000A0D4",
|
||||||
@@ -4066,7 +4016,7 @@ fn test_aarch64_binemit() {
|
|||||||
));
|
));
|
||||||
insns.push((
|
insns.push((
|
||||||
Inst::TrapIf {
|
Inst::TrapIf {
|
||||||
trap_info: (SourceLoc::default(), TrapCode::Interrupt),
|
trap_code: TrapCode::Interrupt,
|
||||||
kind: CondBrKind::Cond(Cond::Ne),
|
kind: CondBrKind::Cond(Cond::Ne),
|
||||||
},
|
},
|
||||||
"400000540000A0D4",
|
"400000540000A0D4",
|
||||||
@@ -4074,7 +4024,7 @@ fn test_aarch64_binemit() {
|
|||||||
));
|
));
|
||||||
insns.push((
|
insns.push((
|
||||||
Inst::TrapIf {
|
Inst::TrapIf {
|
||||||
trap_info: (SourceLoc::default(), TrapCode::Interrupt),
|
trap_code: TrapCode::Interrupt,
|
||||||
kind: CondBrKind::Cond(Cond::Eq),
|
kind: CondBrKind::Cond(Cond::Eq),
|
||||||
},
|
},
|
||||||
"410000540000A0D4",
|
"410000540000A0D4",
|
||||||
@@ -4082,7 +4032,7 @@ fn test_aarch64_binemit() {
|
|||||||
));
|
));
|
||||||
insns.push((
|
insns.push((
|
||||||
Inst::TrapIf {
|
Inst::TrapIf {
|
||||||
trap_info: (SourceLoc::default(), TrapCode::Interrupt),
|
trap_code: TrapCode::Interrupt,
|
||||||
kind: CondBrKind::Cond(Cond::Lo),
|
kind: CondBrKind::Cond(Cond::Lo),
|
||||||
},
|
},
|
||||||
"420000540000A0D4",
|
"420000540000A0D4",
|
||||||
@@ -4090,7 +4040,7 @@ fn test_aarch64_binemit() {
|
|||||||
));
|
));
|
||||||
insns.push((
|
insns.push((
|
||||||
Inst::TrapIf {
|
Inst::TrapIf {
|
||||||
trap_info: (SourceLoc::default(), TrapCode::Interrupt),
|
trap_code: TrapCode::Interrupt,
|
||||||
kind: CondBrKind::Cond(Cond::Hs),
|
kind: CondBrKind::Cond(Cond::Hs),
|
||||||
},
|
},
|
||||||
"430000540000A0D4",
|
"430000540000A0D4",
|
||||||
@@ -4098,7 +4048,7 @@ fn test_aarch64_binemit() {
|
|||||||
));
|
));
|
||||||
insns.push((
|
insns.push((
|
||||||
Inst::TrapIf {
|
Inst::TrapIf {
|
||||||
trap_info: (SourceLoc::default(), TrapCode::Interrupt),
|
trap_code: TrapCode::Interrupt,
|
||||||
kind: CondBrKind::Cond(Cond::Pl),
|
kind: CondBrKind::Cond(Cond::Pl),
|
||||||
},
|
},
|
||||||
"440000540000A0D4",
|
"440000540000A0D4",
|
||||||
@@ -4106,7 +4056,7 @@ fn test_aarch64_binemit() {
|
|||||||
));
|
));
|
||||||
insns.push((
|
insns.push((
|
||||||
Inst::TrapIf {
|
Inst::TrapIf {
|
||||||
trap_info: (SourceLoc::default(), TrapCode::Interrupt),
|
trap_code: TrapCode::Interrupt,
|
||||||
kind: CondBrKind::Cond(Cond::Mi),
|
kind: CondBrKind::Cond(Cond::Mi),
|
||||||
},
|
},
|
||||||
"450000540000A0D4",
|
"450000540000A0D4",
|
||||||
@@ -4114,7 +4064,7 @@ fn test_aarch64_binemit() {
|
|||||||
));
|
));
|
||||||
insns.push((
|
insns.push((
|
||||||
Inst::TrapIf {
|
Inst::TrapIf {
|
||||||
trap_info: (SourceLoc::default(), TrapCode::Interrupt),
|
trap_code: TrapCode::Interrupt,
|
||||||
kind: CondBrKind::Cond(Cond::Vc),
|
kind: CondBrKind::Cond(Cond::Vc),
|
||||||
},
|
},
|
||||||
"460000540000A0D4",
|
"460000540000A0D4",
|
||||||
@@ -4122,7 +4072,7 @@ fn test_aarch64_binemit() {
|
|||||||
));
|
));
|
||||||
insns.push((
|
insns.push((
|
||||||
Inst::TrapIf {
|
Inst::TrapIf {
|
||||||
trap_info: (SourceLoc::default(), TrapCode::Interrupt),
|
trap_code: TrapCode::Interrupt,
|
||||||
kind: CondBrKind::Cond(Cond::Vs),
|
kind: CondBrKind::Cond(Cond::Vs),
|
||||||
},
|
},
|
||||||
"470000540000A0D4",
|
"470000540000A0D4",
|
||||||
@@ -4130,7 +4080,7 @@ fn test_aarch64_binemit() {
|
|||||||
));
|
));
|
||||||
insns.push((
|
insns.push((
|
||||||
Inst::TrapIf {
|
Inst::TrapIf {
|
||||||
trap_info: (SourceLoc::default(), TrapCode::Interrupt),
|
trap_code: TrapCode::Interrupt,
|
||||||
kind: CondBrKind::Cond(Cond::Ls),
|
kind: CondBrKind::Cond(Cond::Ls),
|
||||||
},
|
},
|
||||||
"480000540000A0D4",
|
"480000540000A0D4",
|
||||||
@@ -4138,7 +4088,7 @@ fn test_aarch64_binemit() {
|
|||||||
));
|
));
|
||||||
insns.push((
|
insns.push((
|
||||||
Inst::TrapIf {
|
Inst::TrapIf {
|
||||||
trap_info: (SourceLoc::default(), TrapCode::Interrupt),
|
trap_code: TrapCode::Interrupt,
|
||||||
kind: CondBrKind::Cond(Cond::Hi),
|
kind: CondBrKind::Cond(Cond::Hi),
|
||||||
},
|
},
|
||||||
"490000540000A0D4",
|
"490000540000A0D4",
|
||||||
@@ -4146,7 +4096,7 @@ fn test_aarch64_binemit() {
|
|||||||
));
|
));
|
||||||
insns.push((
|
insns.push((
|
||||||
Inst::TrapIf {
|
Inst::TrapIf {
|
||||||
trap_info: (SourceLoc::default(), TrapCode::Interrupt),
|
trap_code: TrapCode::Interrupt,
|
||||||
kind: CondBrKind::Cond(Cond::Lt),
|
kind: CondBrKind::Cond(Cond::Lt),
|
||||||
},
|
},
|
||||||
"4A0000540000A0D4",
|
"4A0000540000A0D4",
|
||||||
@@ -4154,7 +4104,7 @@ fn test_aarch64_binemit() {
|
|||||||
));
|
));
|
||||||
insns.push((
|
insns.push((
|
||||||
Inst::TrapIf {
|
Inst::TrapIf {
|
||||||
trap_info: (SourceLoc::default(), TrapCode::Interrupt),
|
trap_code: TrapCode::Interrupt,
|
||||||
kind: CondBrKind::Cond(Cond::Ge),
|
kind: CondBrKind::Cond(Cond::Ge),
|
||||||
},
|
},
|
||||||
"4B0000540000A0D4",
|
"4B0000540000A0D4",
|
||||||
@@ -4162,7 +4112,7 @@ fn test_aarch64_binemit() {
|
|||||||
));
|
));
|
||||||
insns.push((
|
insns.push((
|
||||||
Inst::TrapIf {
|
Inst::TrapIf {
|
||||||
trap_info: (SourceLoc::default(), TrapCode::Interrupt),
|
trap_code: TrapCode::Interrupt,
|
||||||
kind: CondBrKind::Cond(Cond::Le),
|
kind: CondBrKind::Cond(Cond::Le),
|
||||||
},
|
},
|
||||||
"4C0000540000A0D4",
|
"4C0000540000A0D4",
|
||||||
@@ -4170,7 +4120,7 @@ fn test_aarch64_binemit() {
|
|||||||
));
|
));
|
||||||
insns.push((
|
insns.push((
|
||||||
Inst::TrapIf {
|
Inst::TrapIf {
|
||||||
trap_info: (SourceLoc::default(), TrapCode::Interrupt),
|
trap_code: TrapCode::Interrupt,
|
||||||
kind: CondBrKind::Cond(Cond::Gt),
|
kind: CondBrKind::Cond(Cond::Gt),
|
||||||
},
|
},
|
||||||
"4D0000540000A0D4",
|
"4D0000540000A0D4",
|
||||||
@@ -4178,7 +4128,7 @@ fn test_aarch64_binemit() {
|
|||||||
));
|
));
|
||||||
insns.push((
|
insns.push((
|
||||||
Inst::TrapIf {
|
Inst::TrapIf {
|
||||||
trap_info: (SourceLoc::default(), TrapCode::Interrupt),
|
trap_code: TrapCode::Interrupt,
|
||||||
kind: CondBrKind::Cond(Cond::Nv),
|
kind: CondBrKind::Cond(Cond::Nv),
|
||||||
},
|
},
|
||||||
"4E0000540000A0D4",
|
"4E0000540000A0D4",
|
||||||
@@ -4186,7 +4136,7 @@ fn test_aarch64_binemit() {
|
|||||||
));
|
));
|
||||||
insns.push((
|
insns.push((
|
||||||
Inst::TrapIf {
|
Inst::TrapIf {
|
||||||
trap_info: (SourceLoc::default(), TrapCode::Interrupt),
|
trap_code: TrapCode::Interrupt,
|
||||||
kind: CondBrKind::Cond(Cond::Al),
|
kind: CondBrKind::Cond(Cond::Al),
|
||||||
},
|
},
|
||||||
"4F0000540000A0D4",
|
"4F0000540000A0D4",
|
||||||
@@ -4209,7 +4159,6 @@ fn test_aarch64_binemit() {
|
|||||||
dest: ExternalName::testcase("test0"),
|
dest: ExternalName::testcase("test0"),
|
||||||
uses: Vec::new(),
|
uses: Vec::new(),
|
||||||
defs: Vec::new(),
|
defs: Vec::new(),
|
||||||
loc: SourceLoc::default(),
|
|
||||||
opcode: Opcode::Call,
|
opcode: Opcode::Call,
|
||||||
caller_callconv: CallConv::SystemV,
|
caller_callconv: CallConv::SystemV,
|
||||||
callee_callconv: CallConv::SystemV,
|
callee_callconv: CallConv::SystemV,
|
||||||
@@ -4225,7 +4174,6 @@ fn test_aarch64_binemit() {
|
|||||||
rn: xreg(10),
|
rn: xreg(10),
|
||||||
uses: Vec::new(),
|
uses: Vec::new(),
|
||||||
defs: Vec::new(),
|
defs: Vec::new(),
|
||||||
loc: SourceLoc::default(),
|
|
||||||
opcode: Opcode::CallIndirect,
|
opcode: Opcode::CallIndirect,
|
||||||
caller_callconv: CallConv::SystemV,
|
caller_callconv: CallConv::SystemV,
|
||||||
callee_callconv: CallConv::SystemV,
|
callee_callconv: CallConv::SystemV,
|
||||||
@@ -4797,7 +4745,6 @@ fn test_aarch64_binemit() {
|
|||||||
Inst::FpuLoad32 {
|
Inst::FpuLoad32 {
|
||||||
rd: writable_vreg(16),
|
rd: writable_vreg(16),
|
||||||
mem: AMode::RegScaled(xreg(8), xreg(9), F32),
|
mem: AMode::RegScaled(xreg(8), xreg(9), F32),
|
||||||
srcloc: None,
|
|
||||||
},
|
},
|
||||||
"107969BC",
|
"107969BC",
|
||||||
"ldr s16, [x8, x9, LSL #2]",
|
"ldr s16, [x8, x9, LSL #2]",
|
||||||
@@ -4807,7 +4754,6 @@ fn test_aarch64_binemit() {
|
|||||||
Inst::FpuLoad64 {
|
Inst::FpuLoad64 {
|
||||||
rd: writable_vreg(16),
|
rd: writable_vreg(16),
|
||||||
mem: AMode::RegScaled(xreg(8), xreg(9), F64),
|
mem: AMode::RegScaled(xreg(8), xreg(9), F64),
|
||||||
srcloc: None,
|
|
||||||
},
|
},
|
||||||
"107969FC",
|
"107969FC",
|
||||||
"ldr d16, [x8, x9, LSL #3]",
|
"ldr d16, [x8, x9, LSL #3]",
|
||||||
@@ -4817,7 +4763,6 @@ fn test_aarch64_binemit() {
|
|||||||
Inst::FpuLoad128 {
|
Inst::FpuLoad128 {
|
||||||
rd: writable_vreg(16),
|
rd: writable_vreg(16),
|
||||||
mem: AMode::RegScaled(xreg(8), xreg(9), I128),
|
mem: AMode::RegScaled(xreg(8), xreg(9), I128),
|
||||||
srcloc: None,
|
|
||||||
},
|
},
|
||||||
"1079E93C",
|
"1079E93C",
|
||||||
"ldr q16, [x8, x9, LSL #4]",
|
"ldr q16, [x8, x9, LSL #4]",
|
||||||
@@ -4827,7 +4772,6 @@ fn test_aarch64_binemit() {
|
|||||||
Inst::FpuLoad32 {
|
Inst::FpuLoad32 {
|
||||||
rd: writable_vreg(16),
|
rd: writable_vreg(16),
|
||||||
mem: AMode::Label(MemLabel::PCRel(8)),
|
mem: AMode::Label(MemLabel::PCRel(8)),
|
||||||
srcloc: None,
|
|
||||||
},
|
},
|
||||||
"5000001C",
|
"5000001C",
|
||||||
"ldr s16, pc+8",
|
"ldr s16, pc+8",
|
||||||
@@ -4837,7 +4781,6 @@ fn test_aarch64_binemit() {
|
|||||||
Inst::FpuLoad64 {
|
Inst::FpuLoad64 {
|
||||||
rd: writable_vreg(16),
|
rd: writable_vreg(16),
|
||||||
mem: AMode::Label(MemLabel::PCRel(8)),
|
mem: AMode::Label(MemLabel::PCRel(8)),
|
||||||
srcloc: None,
|
|
||||||
},
|
},
|
||||||
"5000005C",
|
"5000005C",
|
||||||
"ldr d16, pc+8",
|
"ldr d16, pc+8",
|
||||||
@@ -4847,7 +4790,6 @@ fn test_aarch64_binemit() {
|
|||||||
Inst::FpuLoad128 {
|
Inst::FpuLoad128 {
|
||||||
rd: writable_vreg(16),
|
rd: writable_vreg(16),
|
||||||
mem: AMode::Label(MemLabel::PCRel(8)),
|
mem: AMode::Label(MemLabel::PCRel(8)),
|
||||||
srcloc: None,
|
|
||||||
},
|
},
|
||||||
"5000009C",
|
"5000009C",
|
||||||
"ldr q16, pc+8",
|
"ldr q16, pc+8",
|
||||||
@@ -4857,7 +4799,6 @@ fn test_aarch64_binemit() {
|
|||||||
Inst::FpuStore32 {
|
Inst::FpuStore32 {
|
||||||
rd: vreg(16),
|
rd: vreg(16),
|
||||||
mem: AMode::RegScaled(xreg(8), xreg(9), F32),
|
mem: AMode::RegScaled(xreg(8), xreg(9), F32),
|
||||||
srcloc: None,
|
|
||||||
},
|
},
|
||||||
"107929BC",
|
"107929BC",
|
||||||
"str s16, [x8, x9, LSL #2]",
|
"str s16, [x8, x9, LSL #2]",
|
||||||
@@ -4867,7 +4808,6 @@ fn test_aarch64_binemit() {
|
|||||||
Inst::FpuStore64 {
|
Inst::FpuStore64 {
|
||||||
rd: vreg(16),
|
rd: vreg(16),
|
||||||
mem: AMode::RegScaled(xreg(8), xreg(9), F64),
|
mem: AMode::RegScaled(xreg(8), xreg(9), F64),
|
||||||
srcloc: None,
|
|
||||||
},
|
},
|
||||||
"107929FC",
|
"107929FC",
|
||||||
"str d16, [x8, x9, LSL #3]",
|
"str d16, [x8, x9, LSL #3]",
|
||||||
@@ -4877,7 +4817,6 @@ fn test_aarch64_binemit() {
|
|||||||
Inst::FpuStore128 {
|
Inst::FpuStore128 {
|
||||||
rd: vreg(16),
|
rd: vreg(16),
|
||||||
mem: AMode::RegScaled(xreg(8), xreg(9), I128),
|
mem: AMode::RegScaled(xreg(8), xreg(9), I128),
|
||||||
srcloc: None,
|
|
||||||
},
|
},
|
||||||
"1079A93C",
|
"1079A93C",
|
||||||
"str q16, [x8, x9, LSL #4]",
|
"str q16, [x8, x9, LSL #4]",
|
||||||
@@ -5000,7 +4939,6 @@ fn test_aarch64_binemit() {
|
|||||||
Inst::AtomicRMW {
|
Inst::AtomicRMW {
|
||||||
ty: I16,
|
ty: I16,
|
||||||
op: inst_common::AtomicRmwOp::Xor,
|
op: inst_common::AtomicRmwOp::Xor,
|
||||||
srcloc: None,
|
|
||||||
},
|
},
|
||||||
"BF3B03D53B7F5F487C031ACA3C7F1848B8FFFFB5BF3B03D5",
|
"BF3B03D53B7F5F487C031ACA3C7F1848B8FFFFB5BF3B03D5",
|
||||||
"atomically { 16_bits_at_[x25]) Xor= x26 ; x27 = old_value_at_[x25]; x24,x28 = trash }",
|
"atomically { 16_bits_at_[x25]) Xor= x26 ; x27 = old_value_at_[x25]; x24,x28 = trash }",
|
||||||
@@ -5010,7 +4948,6 @@ fn test_aarch64_binemit() {
|
|||||||
Inst::AtomicRMW {
|
Inst::AtomicRMW {
|
||||||
ty: I32,
|
ty: I32,
|
||||||
op: inst_common::AtomicRmwOp::Xchg,
|
op: inst_common::AtomicRmwOp::Xchg,
|
||||||
srcloc: None,
|
|
||||||
},
|
},
|
||||||
"BF3B03D53B7F5F88FC031AAA3C7F1888B8FFFFB5BF3B03D5",
|
"BF3B03D53B7F5F88FC031AAA3C7F1888B8FFFFB5BF3B03D5",
|
||||||
"atomically { 32_bits_at_[x25]) Xchg= x26 ; x27 = old_value_at_[x25]; x24,x28 = trash }",
|
"atomically { 32_bits_at_[x25]) Xchg= x26 ; x27 = old_value_at_[x25]; x24,x28 = trash }",
|
||||||
@@ -5019,7 +4956,6 @@ fn test_aarch64_binemit() {
|
|||||||
insns.push((
|
insns.push((
|
||||||
Inst::AtomicCAS {
|
Inst::AtomicCAS {
|
||||||
ty: I8,
|
ty: I8,
|
||||||
srcloc: None,
|
|
||||||
},
|
},
|
||||||
"BF3B03D53B7F5F08581F40927F0318EB610000543C7F180878FFFFB5BF3B03D5",
|
"BF3B03D53B7F5F08581F40927F0318EB610000543C7F180878FFFFB5BF3B03D5",
|
||||||
"atomically { compare-and-swap(8_bits_at_[x25], x26 -> x28), x27 = old_value_at_[x25]; x24 = trash }"
|
"atomically { compare-and-swap(8_bits_at_[x25], x26 -> x28), x27 = old_value_at_[x25]; x24 = trash }"
|
||||||
@@ -5028,7 +4964,6 @@ fn test_aarch64_binemit() {
|
|||||||
insns.push((
|
insns.push((
|
||||||
Inst::AtomicCAS {
|
Inst::AtomicCAS {
|
||||||
ty: I64,
|
ty: I64,
|
||||||
srcloc: None,
|
|
||||||
},
|
},
|
||||||
"BF3B03D53B7F5FC8F8031AAA7F0318EB610000543C7F18C878FFFFB5BF3B03D5",
|
"BF3B03D53B7F5FC8F8031AAA7F0318EB610000543C7F18C878FFFFB5BF3B03D5",
|
||||||
"atomically { compare-and-swap(64_bits_at_[x25], x26 -> x28), x27 = old_value_at_[x25]; x24 = trash }"
|
"atomically { compare-and-swap(64_bits_at_[x25], x26 -> x28), x27 = old_value_at_[x25]; x24 = trash }"
|
||||||
@@ -5039,7 +4974,6 @@ fn test_aarch64_binemit() {
|
|||||||
ty: I8,
|
ty: I8,
|
||||||
r_data: writable_xreg(7),
|
r_data: writable_xreg(7),
|
||||||
r_addr: xreg(28),
|
r_addr: xreg(28),
|
||||||
srcloc: None,
|
|
||||||
},
|
},
|
||||||
"BF3B03D587034039",
|
"BF3B03D587034039",
|
||||||
"atomically { x7 = zero_extend_8_bits_at[x28] }",
|
"atomically { x7 = zero_extend_8_bits_at[x28] }",
|
||||||
@@ -5050,7 +4984,6 @@ fn test_aarch64_binemit() {
|
|||||||
ty: I64,
|
ty: I64,
|
||||||
r_data: writable_xreg(28),
|
r_data: writable_xreg(28),
|
||||||
r_addr: xreg(7),
|
r_addr: xreg(7),
|
||||||
srcloc: None,
|
|
||||||
},
|
},
|
||||||
"BF3B03D5FC0040F9",
|
"BF3B03D5FC0040F9",
|
||||||
"atomically { x28 = zero_extend_64_bits_at[x7] }",
|
"atomically { x28 = zero_extend_64_bits_at[x7] }",
|
||||||
@@ -5061,7 +4994,6 @@ fn test_aarch64_binemit() {
|
|||||||
ty: I16,
|
ty: I16,
|
||||||
r_data: xreg(17),
|
r_data: xreg(17),
|
||||||
r_addr: xreg(8),
|
r_addr: xreg(8),
|
||||||
srcloc: None,
|
|
||||||
},
|
},
|
||||||
"11010079BF3B03D5",
|
"11010079BF3B03D5",
|
||||||
"atomically { 16_bits_at[x8] = x17 }",
|
"atomically { 16_bits_at[x8] = x17 }",
|
||||||
@@ -5072,7 +5004,6 @@ fn test_aarch64_binemit() {
|
|||||||
ty: I32,
|
ty: I32,
|
||||||
r_data: xreg(18),
|
r_data: xreg(18),
|
||||||
r_addr: xreg(7),
|
r_addr: xreg(7),
|
||||||
srcloc: None,
|
|
||||||
},
|
},
|
||||||
"F20000B9BF3B03D5",
|
"F20000B9BF3B03D5",
|
||||||
"atomically { 32_bits_at[x7] = x18 }",
|
"atomically { 32_bits_at[x7] = x18 }",
|
||||||
|
|||||||
@@ -420,7 +420,6 @@ pub struct CallInfo {
|
|||||||
pub dest: ExternalName,
|
pub dest: ExternalName,
|
||||||
pub uses: Vec<Reg>,
|
pub uses: Vec<Reg>,
|
||||||
pub defs: Vec<Writable<Reg>>,
|
pub defs: Vec<Writable<Reg>>,
|
||||||
pub loc: SourceLoc,
|
|
||||||
pub opcode: Opcode,
|
pub opcode: Opcode,
|
||||||
pub caller_callconv: CallConv,
|
pub caller_callconv: CallConv,
|
||||||
pub callee_callconv: CallConv,
|
pub callee_callconv: CallConv,
|
||||||
@@ -433,7 +432,6 @@ pub struct CallIndInfo {
|
|||||||
pub rn: Reg,
|
pub rn: Reg,
|
||||||
pub uses: Vec<Reg>,
|
pub uses: Vec<Reg>,
|
||||||
pub defs: Vec<Writable<Reg>>,
|
pub defs: Vec<Writable<Reg>>,
|
||||||
pub loc: SourceLoc,
|
|
||||||
pub opcode: Opcode,
|
pub opcode: Opcode,
|
||||||
pub caller_callconv: CallConv,
|
pub caller_callconv: CallConv,
|
||||||
pub callee_callconv: CallConv,
|
pub callee_callconv: CallConv,
|
||||||
@@ -524,68 +522,57 @@ pub enum Inst {
|
|||||||
ULoad8 {
|
ULoad8 {
|
||||||
rd: Writable<Reg>,
|
rd: Writable<Reg>,
|
||||||
mem: AMode,
|
mem: AMode,
|
||||||
srcloc: Option<SourceLoc>,
|
|
||||||
},
|
},
|
||||||
/// A signed (sign-extending) 8-bit load.
|
/// A signed (sign-extending) 8-bit load.
|
||||||
SLoad8 {
|
SLoad8 {
|
||||||
rd: Writable<Reg>,
|
rd: Writable<Reg>,
|
||||||
mem: AMode,
|
mem: AMode,
|
||||||
srcloc: Option<SourceLoc>,
|
|
||||||
},
|
},
|
||||||
/// An unsigned (zero-extending) 16-bit load.
|
/// An unsigned (zero-extending) 16-bit load.
|
||||||
ULoad16 {
|
ULoad16 {
|
||||||
rd: Writable<Reg>,
|
rd: Writable<Reg>,
|
||||||
mem: AMode,
|
mem: AMode,
|
||||||
srcloc: Option<SourceLoc>,
|
|
||||||
},
|
},
|
||||||
/// A signed (sign-extending) 16-bit load.
|
/// A signed (sign-extending) 16-bit load.
|
||||||
SLoad16 {
|
SLoad16 {
|
||||||
rd: Writable<Reg>,
|
rd: Writable<Reg>,
|
||||||
mem: AMode,
|
mem: AMode,
|
||||||
srcloc: Option<SourceLoc>,
|
|
||||||
},
|
},
|
||||||
/// An unsigned (zero-extending) 32-bit load.
|
/// An unsigned (zero-extending) 32-bit load.
|
||||||
ULoad32 {
|
ULoad32 {
|
||||||
rd: Writable<Reg>,
|
rd: Writable<Reg>,
|
||||||
mem: AMode,
|
mem: AMode,
|
||||||
srcloc: Option<SourceLoc>,
|
|
||||||
},
|
},
|
||||||
/// A signed (sign-extending) 32-bit load.
|
/// A signed (sign-extending) 32-bit load.
|
||||||
SLoad32 {
|
SLoad32 {
|
||||||
rd: Writable<Reg>,
|
rd: Writable<Reg>,
|
||||||
mem: AMode,
|
mem: AMode,
|
||||||
srcloc: Option<SourceLoc>,
|
|
||||||
},
|
},
|
||||||
/// A 64-bit load.
|
/// A 64-bit load.
|
||||||
ULoad64 {
|
ULoad64 {
|
||||||
rd: Writable<Reg>,
|
rd: Writable<Reg>,
|
||||||
mem: AMode,
|
mem: AMode,
|
||||||
srcloc: Option<SourceLoc>,
|
|
||||||
},
|
},
|
||||||
|
|
||||||
/// An 8-bit store.
|
/// An 8-bit store.
|
||||||
Store8 {
|
Store8 {
|
||||||
rd: Reg,
|
rd: Reg,
|
||||||
mem: AMode,
|
mem: AMode,
|
||||||
srcloc: Option<SourceLoc>,
|
|
||||||
},
|
},
|
||||||
/// A 16-bit store.
|
/// A 16-bit store.
|
||||||
Store16 {
|
Store16 {
|
||||||
rd: Reg,
|
rd: Reg,
|
||||||
mem: AMode,
|
mem: AMode,
|
||||||
srcloc: Option<SourceLoc>,
|
|
||||||
},
|
},
|
||||||
/// A 32-bit store.
|
/// A 32-bit store.
|
||||||
Store32 {
|
Store32 {
|
||||||
rd: Reg,
|
rd: Reg,
|
||||||
mem: AMode,
|
mem: AMode,
|
||||||
srcloc: Option<SourceLoc>,
|
|
||||||
},
|
},
|
||||||
/// A 64-bit store.
|
/// A 64-bit store.
|
||||||
Store64 {
|
Store64 {
|
||||||
rd: Reg,
|
rd: Reg,
|
||||||
mem: AMode,
|
mem: AMode,
|
||||||
srcloc: Option<SourceLoc>,
|
|
||||||
},
|
},
|
||||||
|
|
||||||
/// A store of a pair of registers.
|
/// A store of a pair of registers.
|
||||||
@@ -686,7 +673,6 @@ pub enum Inst {
|
|||||||
AtomicRMW {
|
AtomicRMW {
|
||||||
ty: Type, // I8, I16, I32 or I64
|
ty: Type, // I8, I16, I32 or I64
|
||||||
op: inst_common::AtomicRmwOp,
|
op: inst_common::AtomicRmwOp,
|
||||||
srcloc: Option<SourceLoc>,
|
|
||||||
},
|
},
|
||||||
|
|
||||||
/// Similar to AtomicRMW, a compare-and-swap operation implemented using a load-linked
|
/// Similar to AtomicRMW, a compare-and-swap operation implemented using a load-linked
|
||||||
@@ -703,7 +689,6 @@ pub enum Inst {
|
|||||||
/// x24 (wr) scratch reg; value afterwards has no meaning
|
/// x24 (wr) scratch reg; value afterwards has no meaning
|
||||||
AtomicCAS {
|
AtomicCAS {
|
||||||
ty: Type, // I8, I16, I32 or I64
|
ty: Type, // I8, I16, I32 or I64
|
||||||
srcloc: Option<SourceLoc>,
|
|
||||||
},
|
},
|
||||||
|
|
||||||
/// Read `ty` bits from address `r_addr`, zero extend the loaded value to 64 bits and put it
|
/// Read `ty` bits from address `r_addr`, zero extend the loaded value to 64 bits and put it
|
||||||
@@ -713,7 +698,6 @@ pub enum Inst {
|
|||||||
ty: Type, // I8, I16, I32 or I64
|
ty: Type, // I8, I16, I32 or I64
|
||||||
r_data: Writable<Reg>,
|
r_data: Writable<Reg>,
|
||||||
r_addr: Reg,
|
r_addr: Reg,
|
||||||
srcloc: Option<SourceLoc>,
|
|
||||||
},
|
},
|
||||||
|
|
||||||
/// Write the lowest `ty` bits of `r_data` to address `r_addr`, with a memory fence
|
/// Write the lowest `ty` bits of `r_data` to address `r_addr`, with a memory fence
|
||||||
@@ -723,7 +707,6 @@ pub enum Inst {
|
|||||||
ty: Type, // I8, I16, I32 or I64
|
ty: Type, // I8, I16, I32 or I64
|
||||||
r_data: Reg,
|
r_data: Reg,
|
||||||
r_addr: Reg,
|
r_addr: Reg,
|
||||||
srcloc: Option<SourceLoc>,
|
|
||||||
},
|
},
|
||||||
|
|
||||||
/// A memory fence. This must provide ordering to ensure that, at a minimum, neither loads
|
/// A memory fence. This must provide ordering to ensure that, at a minimum, neither loads
|
||||||
@@ -798,37 +781,31 @@ pub enum Inst {
|
|||||||
FpuLoad32 {
|
FpuLoad32 {
|
||||||
rd: Writable<Reg>,
|
rd: Writable<Reg>,
|
||||||
mem: AMode,
|
mem: AMode,
|
||||||
srcloc: Option<SourceLoc>,
|
|
||||||
},
|
},
|
||||||
/// Floating-point store, single-precision (32 bit).
|
/// Floating-point store, single-precision (32 bit).
|
||||||
FpuStore32 {
|
FpuStore32 {
|
||||||
rd: Reg,
|
rd: Reg,
|
||||||
mem: AMode,
|
mem: AMode,
|
||||||
srcloc: Option<SourceLoc>,
|
|
||||||
},
|
},
|
||||||
/// Floating-point load, double-precision (64 bit).
|
/// Floating-point load, double-precision (64 bit).
|
||||||
FpuLoad64 {
|
FpuLoad64 {
|
||||||
rd: Writable<Reg>,
|
rd: Writable<Reg>,
|
||||||
mem: AMode,
|
mem: AMode,
|
||||||
srcloc: Option<SourceLoc>,
|
|
||||||
},
|
},
|
||||||
/// Floating-point store, double-precision (64 bit).
|
/// Floating-point store, double-precision (64 bit).
|
||||||
FpuStore64 {
|
FpuStore64 {
|
||||||
rd: Reg,
|
rd: Reg,
|
||||||
mem: AMode,
|
mem: AMode,
|
||||||
srcloc: Option<SourceLoc>,
|
|
||||||
},
|
},
|
||||||
/// Floating-point/vector load, 128 bit.
|
/// Floating-point/vector load, 128 bit.
|
||||||
FpuLoad128 {
|
FpuLoad128 {
|
||||||
rd: Writable<Reg>,
|
rd: Writable<Reg>,
|
||||||
mem: AMode,
|
mem: AMode,
|
||||||
srcloc: Option<SourceLoc>,
|
|
||||||
},
|
},
|
||||||
/// Floating-point/vector store, 128 bit.
|
/// Floating-point/vector store, 128 bit.
|
||||||
FpuStore128 {
|
FpuStore128 {
|
||||||
rd: Reg,
|
rd: Reg,
|
||||||
mem: AMode,
|
mem: AMode,
|
||||||
srcloc: Option<SourceLoc>,
|
|
||||||
},
|
},
|
||||||
|
|
||||||
LoadFpuConst64 {
|
LoadFpuConst64 {
|
||||||
@@ -1037,7 +1014,6 @@ pub enum Inst {
|
|||||||
rd: Writable<Reg>,
|
rd: Writable<Reg>,
|
||||||
rn: Reg,
|
rn: Reg,
|
||||||
size: VectorSize,
|
size: VectorSize,
|
||||||
srcloc: Option<SourceLoc>,
|
|
||||||
},
|
},
|
||||||
|
|
||||||
/// Move to the NZCV flags (actually a `MSR NZCV, Xn` insn).
|
/// Move to the NZCV flags (actually a `MSR NZCV, Xn` insn).
|
||||||
@@ -1095,7 +1071,7 @@ pub enum Inst {
|
|||||||
/// of this condition in a branch that skips the trap instruction.)
|
/// of this condition in a branch that skips the trap instruction.)
|
||||||
TrapIf {
|
TrapIf {
|
||||||
kind: CondBrKind,
|
kind: CondBrKind,
|
||||||
trap_info: (SourceLoc, TrapCode),
|
trap_code: TrapCode,
|
||||||
},
|
},
|
||||||
|
|
||||||
/// An indirect branch through a register, augmented with set of all
|
/// An indirect branch through a register, augmented with set of all
|
||||||
@@ -1111,7 +1087,7 @@ pub enum Inst {
|
|||||||
/// An instruction guaranteed to always be undefined and to trigger an illegal instruction at
|
/// An instruction guaranteed to always be undefined and to trigger an illegal instruction at
|
||||||
/// runtime.
|
/// runtime.
|
||||||
Udf {
|
Udf {
|
||||||
trap_info: (SourceLoc, TrapCode),
|
trap_code: TrapCode,
|
||||||
},
|
},
|
||||||
|
|
||||||
/// Compute the address (using a PC-relative offset) of a memory location, using the `ADR`
|
/// Compute the address (using a PC-relative offset) of a memory location, using the `ADR`
|
||||||
@@ -1146,7 +1122,6 @@ pub enum Inst {
|
|||||||
LoadExtName {
|
LoadExtName {
|
||||||
rd: Writable<Reg>,
|
rd: Writable<Reg>,
|
||||||
name: Box<ExternalName>,
|
name: Box<ExternalName>,
|
||||||
srcloc: SourceLoc,
|
|
||||||
offset: i64,
|
offset: i64,
|
||||||
},
|
},
|
||||||
|
|
||||||
@@ -1457,47 +1432,22 @@ impl Inst {
|
|||||||
/// Generic constructor for a load (zero-extending where appropriate).
|
/// Generic constructor for a load (zero-extending where appropriate).
|
||||||
pub fn gen_load(into_reg: Writable<Reg>, mem: AMode, ty: Type) -> Inst {
|
pub fn gen_load(into_reg: Writable<Reg>, mem: AMode, ty: Type) -> Inst {
|
||||||
match ty {
|
match ty {
|
||||||
B1 | B8 | I8 => Inst::ULoad8 {
|
B1 | B8 | I8 => Inst::ULoad8 { rd: into_reg, mem },
|
||||||
rd: into_reg,
|
B16 | I16 => Inst::ULoad16 { rd: into_reg, mem },
|
||||||
mem,
|
B32 | I32 | R32 => Inst::ULoad32 { rd: into_reg, mem },
|
||||||
srcloc: None,
|
B64 | I64 | R64 => Inst::ULoad64 { rd: into_reg, mem },
|
||||||
},
|
F32 => Inst::FpuLoad32 { rd: into_reg, mem },
|
||||||
B16 | I16 => Inst::ULoad16 {
|
F64 => Inst::FpuLoad64 { rd: into_reg, mem },
|
||||||
rd: into_reg,
|
|
||||||
mem,
|
|
||||||
srcloc: None,
|
|
||||||
},
|
|
||||||
B32 | I32 | R32 => Inst::ULoad32 {
|
|
||||||
rd: into_reg,
|
|
||||||
mem,
|
|
||||||
srcloc: None,
|
|
||||||
},
|
|
||||||
B64 | I64 | R64 => Inst::ULoad64 {
|
|
||||||
rd: into_reg,
|
|
||||||
mem,
|
|
||||||
srcloc: None,
|
|
||||||
},
|
|
||||||
F32 => Inst::FpuLoad32 {
|
|
||||||
rd: into_reg,
|
|
||||||
mem,
|
|
||||||
srcloc: None,
|
|
||||||
},
|
|
||||||
F64 => Inst::FpuLoad64 {
|
|
||||||
rd: into_reg,
|
|
||||||
mem,
|
|
||||||
srcloc: None,
|
|
||||||
},
|
|
||||||
_ => {
|
_ => {
|
||||||
if ty.is_vector() {
|
if ty.is_vector() {
|
||||||
let bits = ty_bits(ty);
|
let bits = ty_bits(ty);
|
||||||
let rd = into_reg;
|
let rd = into_reg;
|
||||||
let srcloc = None;
|
|
||||||
|
|
||||||
if bits == 128 {
|
if bits == 128 {
|
||||||
Inst::FpuLoad128 { rd, mem, srcloc }
|
Inst::FpuLoad128 { rd, mem }
|
||||||
} else {
|
} else {
|
||||||
assert_eq!(bits, 64);
|
assert_eq!(bits, 64);
|
||||||
Inst::FpuLoad64 { rd, mem, srcloc }
|
Inst::FpuLoad64 { rd, mem }
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
unimplemented!("gen_load({})", ty);
|
unimplemented!("gen_load({})", ty);
|
||||||
@@ -1509,47 +1459,22 @@ impl Inst {
|
|||||||
/// Generic constructor for a store.
|
/// Generic constructor for a store.
|
||||||
pub fn gen_store(mem: AMode, from_reg: Reg, ty: Type) -> Inst {
|
pub fn gen_store(mem: AMode, from_reg: Reg, ty: Type) -> Inst {
|
||||||
match ty {
|
match ty {
|
||||||
B1 | B8 | I8 => Inst::Store8 {
|
B1 | B8 | I8 => Inst::Store8 { rd: from_reg, mem },
|
||||||
rd: from_reg,
|
B16 | I16 => Inst::Store16 { rd: from_reg, mem },
|
||||||
mem,
|
B32 | I32 | R32 => Inst::Store32 { rd: from_reg, mem },
|
||||||
srcloc: None,
|
B64 | I64 | R64 => Inst::Store64 { rd: from_reg, mem },
|
||||||
},
|
F32 => Inst::FpuStore32 { rd: from_reg, mem },
|
||||||
B16 | I16 => Inst::Store16 {
|
F64 => Inst::FpuStore64 { rd: from_reg, mem },
|
||||||
rd: from_reg,
|
|
||||||
mem,
|
|
||||||
srcloc: None,
|
|
||||||
},
|
|
||||||
B32 | I32 | R32 => Inst::Store32 {
|
|
||||||
rd: from_reg,
|
|
||||||
mem,
|
|
||||||
srcloc: None,
|
|
||||||
},
|
|
||||||
B64 | I64 | R64 => Inst::Store64 {
|
|
||||||
rd: from_reg,
|
|
||||||
mem,
|
|
||||||
srcloc: None,
|
|
||||||
},
|
|
||||||
F32 => Inst::FpuStore32 {
|
|
||||||
rd: from_reg,
|
|
||||||
mem,
|
|
||||||
srcloc: None,
|
|
||||||
},
|
|
||||||
F64 => Inst::FpuStore64 {
|
|
||||||
rd: from_reg,
|
|
||||||
mem,
|
|
||||||
srcloc: None,
|
|
||||||
},
|
|
||||||
_ => {
|
_ => {
|
||||||
if ty.is_vector() {
|
if ty.is_vector() {
|
||||||
let bits = ty_bits(ty);
|
let bits = ty_bits(ty);
|
||||||
let rd = from_reg;
|
let rd = from_reg;
|
||||||
let srcloc = None;
|
|
||||||
|
|
||||||
if bits == 128 {
|
if bits == 128 {
|
||||||
Inst::FpuStore128 { rd, mem, srcloc }
|
Inst::FpuStore128 { rd, mem }
|
||||||
} else {
|
} else {
|
||||||
assert_eq!(bits, 64);
|
assert_eq!(bits, 64);
|
||||||
Inst::FpuStore64 { rd, mem, srcloc }
|
Inst::FpuStore64 { rd, mem }
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
unimplemented!("gen_store({})", ty);
|
unimplemented!("gen_store({})", ty);
|
||||||
@@ -3024,37 +2949,30 @@ impl Inst {
|
|||||||
&Inst::ULoad8 {
|
&Inst::ULoad8 {
|
||||||
rd,
|
rd,
|
||||||
ref mem,
|
ref mem,
|
||||||
srcloc: _srcloc,
|
|
||||||
}
|
}
|
||||||
| &Inst::SLoad8 {
|
| &Inst::SLoad8 {
|
||||||
rd,
|
rd,
|
||||||
ref mem,
|
ref mem,
|
||||||
srcloc: _srcloc,
|
|
||||||
}
|
}
|
||||||
| &Inst::ULoad16 {
|
| &Inst::ULoad16 {
|
||||||
rd,
|
rd,
|
||||||
ref mem,
|
ref mem,
|
||||||
srcloc: _srcloc,
|
|
||||||
}
|
}
|
||||||
| &Inst::SLoad16 {
|
| &Inst::SLoad16 {
|
||||||
rd,
|
rd,
|
||||||
ref mem,
|
ref mem,
|
||||||
srcloc: _srcloc,
|
|
||||||
}
|
}
|
||||||
| &Inst::ULoad32 {
|
| &Inst::ULoad32 {
|
||||||
rd,
|
rd,
|
||||||
ref mem,
|
ref mem,
|
||||||
srcloc: _srcloc,
|
|
||||||
}
|
}
|
||||||
| &Inst::SLoad32 {
|
| &Inst::SLoad32 {
|
||||||
rd,
|
rd,
|
||||||
ref mem,
|
ref mem,
|
||||||
srcloc: _srcloc,
|
|
||||||
}
|
}
|
||||||
| &Inst::ULoad64 {
|
| &Inst::ULoad64 {
|
||||||
rd,
|
rd,
|
||||||
ref mem,
|
ref mem,
|
||||||
srcloc: _srcloc,
|
|
||||||
..
|
..
|
||||||
} => {
|
} => {
|
||||||
let (mem_str, mem) = mem_finalize_for_show(mem, mb_rru, state);
|
let (mem_str, mem) = mem_finalize_for_show(mem, mb_rru, state);
|
||||||
@@ -3087,22 +3005,18 @@ impl Inst {
|
|||||||
&Inst::Store8 {
|
&Inst::Store8 {
|
||||||
rd,
|
rd,
|
||||||
ref mem,
|
ref mem,
|
||||||
srcloc: _srcloc,
|
|
||||||
}
|
}
|
||||||
| &Inst::Store16 {
|
| &Inst::Store16 {
|
||||||
rd,
|
rd,
|
||||||
ref mem,
|
ref mem,
|
||||||
srcloc: _srcloc,
|
|
||||||
}
|
}
|
||||||
| &Inst::Store32 {
|
| &Inst::Store32 {
|
||||||
rd,
|
rd,
|
||||||
ref mem,
|
ref mem,
|
||||||
srcloc: _srcloc,
|
|
||||||
}
|
}
|
||||||
| &Inst::Store64 {
|
| &Inst::Store64 {
|
||||||
rd,
|
rd,
|
||||||
ref mem,
|
ref mem,
|
||||||
srcloc: _srcloc,
|
|
||||||
..
|
..
|
||||||
} => {
|
} => {
|
||||||
let (mem_str, mem) = mem_finalize_for_show(mem, mb_rru, state);
|
let (mem_str, mem) = mem_finalize_for_show(mem, mb_rru, state);
|
||||||
@@ -3841,7 +3755,6 @@ impl Inst {
|
|||||||
rd,
|
rd,
|
||||||
ref name,
|
ref name,
|
||||||
offset,
|
offset,
|
||||||
srcloc: _srcloc,
|
|
||||||
} => {
|
} => {
|
||||||
let rd = rd.show_rru(mb_rru);
|
let rd = rd.show_rru(mb_rru);
|
||||||
format!("ldr {}, 8 ; b 12 ; data {:?} + {}", rd, name, offset)
|
format!("ldr {}, 8 ; b 12 ; data {:?} + {}", rd, name, offset)
|
||||||
|
|||||||
@@ -484,9 +484,9 @@ pub(crate) fn lower_insn_to_regs<C: LowerCtx<I = Inst>>(
|
|||||||
// msub rd, rd, rm, rn ; rd = rn - rd * rm
|
// msub rd, rd, rm, rn ; rd = rn - rd * rm
|
||||||
|
|
||||||
// Check for divide by 0.
|
// Check for divide by 0.
|
||||||
let trap_info = (ctx.srcloc(insn), TrapCode::IntegerDivisionByZero);
|
let trap_code = TrapCode::IntegerDivisionByZero;
|
||||||
ctx.emit(Inst::TrapIf {
|
ctx.emit(Inst::TrapIf {
|
||||||
trap_info,
|
trap_code,
|
||||||
kind: CondBrKind::Zero(rm),
|
kind: CondBrKind::Zero(rm),
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -507,9 +507,9 @@ pub(crate) fn lower_insn_to_regs<C: LowerCtx<I = Inst>>(
|
|||||||
// udf ; signed overflow
|
// udf ; signed overflow
|
||||||
|
|
||||||
// Check for divide by 0.
|
// Check for divide by 0.
|
||||||
let trap_info = (ctx.srcloc(insn), TrapCode::IntegerDivisionByZero);
|
let trap_code = TrapCode::IntegerDivisionByZero;
|
||||||
ctx.emit(Inst::TrapIf {
|
ctx.emit(Inst::TrapIf {
|
||||||
trap_info,
|
trap_code,
|
||||||
kind: CondBrKind::Zero(rm),
|
kind: CondBrKind::Zero(rm),
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -535,9 +535,9 @@ pub(crate) fn lower_insn_to_regs<C: LowerCtx<I = Inst>>(
|
|||||||
nzcv: NZCV::new(false, false, false, false),
|
nzcv: NZCV::new(false, false, false, false),
|
||||||
cond: Cond::Eq,
|
cond: Cond::Eq,
|
||||||
});
|
});
|
||||||
let trap_info = (ctx.srcloc(insn), TrapCode::IntegerOverflow);
|
let trap_code = TrapCode::IntegerOverflow;
|
||||||
ctx.emit(Inst::TrapIf {
|
ctx.emit(Inst::TrapIf {
|
||||||
trap_info,
|
trap_code,
|
||||||
kind: CondBrKind::Cond(Cond::Vs),
|
kind: CondBrKind::Cond(Cond::Vs),
|
||||||
});
|
});
|
||||||
} else {
|
} else {
|
||||||
@@ -545,9 +545,9 @@ pub(crate) fn lower_insn_to_regs<C: LowerCtx<I = Inst>>(
|
|||||||
// udf ; divide by zero
|
// udf ; divide by zero
|
||||||
|
|
||||||
// Check for divide by 0.
|
// Check for divide by 0.
|
||||||
let trap_info = (ctx.srcloc(insn), TrapCode::IntegerDivisionByZero);
|
let trap_code = TrapCode::IntegerDivisionByZero;
|
||||||
ctx.emit(Inst::TrapIf {
|
ctx.emit(Inst::TrapIf {
|
||||||
trap_info,
|
trap_code,
|
||||||
kind: CondBrKind::Zero(rm),
|
kind: CondBrKind::Zero(rm),
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@@ -1161,27 +1161,20 @@ pub(crate) fn lower_insn_to_regs<C: LowerCtx<I = Inst>>(
|
|||||||
let mem = lower_address(ctx, elem_ty, &inputs[..], off);
|
let mem = lower_address(ctx, elem_ty, &inputs[..], off);
|
||||||
let rd = get_output_reg(ctx, outputs[0]);
|
let rd = get_output_reg(ctx, outputs[0]);
|
||||||
|
|
||||||
let memflags = ctx.memflags(insn).expect("memory flags");
|
|
||||||
let srcloc = if !memflags.notrap() {
|
|
||||||
Some(ctx.srcloc(insn))
|
|
||||||
} else {
|
|
||||||
None
|
|
||||||
};
|
|
||||||
|
|
||||||
ctx.emit(match (ty_bits(elem_ty), sign_extend, is_float) {
|
ctx.emit(match (ty_bits(elem_ty), sign_extend, is_float) {
|
||||||
(1, _, _) => Inst::ULoad8 { rd, mem, srcloc },
|
(1, _, _) => Inst::ULoad8 { rd, mem },
|
||||||
(8, false, _) => Inst::ULoad8 { rd, mem, srcloc },
|
(8, false, _) => Inst::ULoad8 { rd, mem },
|
||||||
(8, true, _) => Inst::SLoad8 { rd, mem, srcloc },
|
(8, true, _) => Inst::SLoad8 { rd, mem },
|
||||||
(16, false, _) => Inst::ULoad16 { rd, mem, srcloc },
|
(16, false, _) => Inst::ULoad16 { rd, mem },
|
||||||
(16, true, _) => Inst::SLoad16 { rd, mem, srcloc },
|
(16, true, _) => Inst::SLoad16 { rd, mem },
|
||||||
(32, false, false) => Inst::ULoad32 { rd, mem, srcloc },
|
(32, false, false) => Inst::ULoad32 { rd, mem },
|
||||||
(32, true, false) => Inst::SLoad32 { rd, mem, srcloc },
|
(32, true, false) => Inst::SLoad32 { rd, mem },
|
||||||
(32, _, true) => Inst::FpuLoad32 { rd, mem, srcloc },
|
(32, _, true) => Inst::FpuLoad32 { rd, mem },
|
||||||
(64, _, false) => Inst::ULoad64 { rd, mem, srcloc },
|
(64, _, false) => Inst::ULoad64 { rd, mem },
|
||||||
// Note that we treat some of the vector loads as scalar floating-point loads,
|
// Note that we treat some of the vector loads as scalar floating-point loads,
|
||||||
// which is correct in a little endian environment.
|
// which is correct in a little endian environment.
|
||||||
(64, _, true) => Inst::FpuLoad64 { rd, mem, srcloc },
|
(64, _, true) => Inst::FpuLoad64 { rd, mem },
|
||||||
(128, _, _) => Inst::FpuLoad128 { rd, mem, srcloc },
|
(128, _, _) => Inst::FpuLoad128 { rd, mem },
|
||||||
_ => panic!("Unsupported size in load"),
|
_ => panic!("Unsupported size in load"),
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -1209,14 +1202,8 @@ pub(crate) fn lower_insn_to_regs<C: LowerCtx<I = Inst>>(
|
|||||||
let off = ctx.data(insn).load_store_offset().unwrap();
|
let off = ctx.data(insn).load_store_offset().unwrap();
|
||||||
let ty = ty.unwrap();
|
let ty = ty.unwrap();
|
||||||
let mem = lower_address(ctx, ty.lane_type(), &inputs[..], off);
|
let mem = lower_address(ctx, ty.lane_type(), &inputs[..], off);
|
||||||
let memflags = ctx.memflags(insn).expect("memory flags");
|
|
||||||
let rd = get_output_reg(ctx, outputs[0]);
|
let rd = get_output_reg(ctx, outputs[0]);
|
||||||
let size = VectorSize::from_ty(ty);
|
let size = VectorSize::from_ty(ty);
|
||||||
let srcloc = if memflags.notrap() {
|
|
||||||
None
|
|
||||||
} else {
|
|
||||||
Some(ctx.srcloc(insn))
|
|
||||||
};
|
|
||||||
let tmp = ctx.alloc_tmp(RegClass::I64, I64);
|
let tmp = ctx.alloc_tmp(RegClass::I64, I64);
|
||||||
|
|
||||||
ctx.emit(Inst::LoadAddr { rd: tmp, mem });
|
ctx.emit(Inst::LoadAddr { rd: tmp, mem });
|
||||||
@@ -1224,7 +1211,6 @@ pub(crate) fn lower_insn_to_regs<C: LowerCtx<I = Inst>>(
|
|||||||
rd,
|
rd,
|
||||||
rn: tmp.to_reg(),
|
rn: tmp.to_reg(),
|
||||||
size,
|
size,
|
||||||
srcloc,
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1249,21 +1235,14 @@ pub(crate) fn lower_insn_to_regs<C: LowerCtx<I = Inst>>(
|
|||||||
let mem = lower_address(ctx, elem_ty, &inputs[1..], off);
|
let mem = lower_address(ctx, elem_ty, &inputs[1..], off);
|
||||||
let rd = put_input_in_reg(ctx, inputs[0], NarrowValueMode::None);
|
let rd = put_input_in_reg(ctx, inputs[0], NarrowValueMode::None);
|
||||||
|
|
||||||
let memflags = ctx.memflags(insn).expect("memory flags");
|
|
||||||
let srcloc = if !memflags.notrap() {
|
|
||||||
Some(ctx.srcloc(insn))
|
|
||||||
} else {
|
|
||||||
None
|
|
||||||
};
|
|
||||||
|
|
||||||
ctx.emit(match (ty_bits(elem_ty), is_float) {
|
ctx.emit(match (ty_bits(elem_ty), is_float) {
|
||||||
(1, _) | (8, _) => Inst::Store8 { rd, mem, srcloc },
|
(1, _) | (8, _) => Inst::Store8 { rd, mem },
|
||||||
(16, _) => Inst::Store16 { rd, mem, srcloc },
|
(16, _) => Inst::Store16 { rd, mem },
|
||||||
(32, false) => Inst::Store32 { rd, mem, srcloc },
|
(32, false) => Inst::Store32 { rd, mem },
|
||||||
(32, true) => Inst::FpuStore32 { rd, mem, srcloc },
|
(32, true) => Inst::FpuStore32 { rd, mem },
|
||||||
(64, false) => Inst::Store64 { rd, mem, srcloc },
|
(64, false) => Inst::Store64 { rd, mem },
|
||||||
(64, true) => Inst::FpuStore64 { rd, mem, srcloc },
|
(64, true) => Inst::FpuStore64 { rd, mem },
|
||||||
(128, _) => Inst::FpuStore128 { rd, mem, srcloc },
|
(128, _) => Inst::FpuStore128 { rd, mem },
|
||||||
_ => panic!("Unsupported size in store"),
|
_ => panic!("Unsupported size in store"),
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@@ -1291,12 +1270,6 @@ pub(crate) fn lower_insn_to_regs<C: LowerCtx<I = Inst>>(
|
|||||||
let mut r_arg2 = put_input_in_reg(ctx, inputs[1], NarrowValueMode::None);
|
let mut r_arg2 = put_input_in_reg(ctx, inputs[1], NarrowValueMode::None);
|
||||||
let ty_access = ty.unwrap();
|
let ty_access = ty.unwrap();
|
||||||
assert!(is_valid_atomic_transaction_ty(ty_access));
|
assert!(is_valid_atomic_transaction_ty(ty_access));
|
||||||
let memflags = ctx.memflags(insn).expect("memory flags");
|
|
||||||
let srcloc = if !memflags.notrap() {
|
|
||||||
Some(ctx.srcloc(insn))
|
|
||||||
} else {
|
|
||||||
None
|
|
||||||
};
|
|
||||||
// Make sure that both args are in virtual regs, since in effect
|
// Make sure that both args are in virtual regs, since in effect
|
||||||
// we have to do a parallel copy to get them safely to the AtomicRMW input
|
// we have to do a parallel copy to get them safely to the AtomicRMW input
|
||||||
// regs, and that's not guaranteed safe if either is in a real reg.
|
// regs, and that's not guaranteed safe if either is in a real reg.
|
||||||
@@ -1307,11 +1280,7 @@ pub(crate) fn lower_insn_to_regs<C: LowerCtx<I = Inst>>(
|
|||||||
ctx.emit(Inst::gen_move(Writable::from_reg(xreg(26)), r_arg2, I64));
|
ctx.emit(Inst::gen_move(Writable::from_reg(xreg(26)), r_arg2, I64));
|
||||||
// Now the AtomicRMW insn itself
|
// Now the AtomicRMW insn itself
|
||||||
let op = inst_common::AtomicRmwOp::from(ctx.data(insn).atomic_rmw_op().unwrap());
|
let op = inst_common::AtomicRmwOp::from(ctx.data(insn).atomic_rmw_op().unwrap());
|
||||||
ctx.emit(Inst::AtomicRMW {
|
ctx.emit(Inst::AtomicRMW { ty: ty_access, op });
|
||||||
ty: ty_access,
|
|
||||||
op,
|
|
||||||
srcloc,
|
|
||||||
});
|
|
||||||
// And finally, copy the preordained AtomicRMW output reg to its destination.
|
// And finally, copy the preordained AtomicRMW output reg to its destination.
|
||||||
ctx.emit(Inst::gen_move(r_dst, xreg(27), I64));
|
ctx.emit(Inst::gen_move(r_dst, xreg(27), I64));
|
||||||
// Also, x24 and x28 are trashed. `fn aarch64_get_regs` must mention that.
|
// Also, x24 and x28 are trashed. `fn aarch64_get_regs` must mention that.
|
||||||
@@ -1327,12 +1296,6 @@ pub(crate) fn lower_insn_to_regs<C: LowerCtx<I = Inst>>(
|
|||||||
let mut r_replacement = put_input_in_reg(ctx, inputs[2], NarrowValueMode::None);
|
let mut r_replacement = put_input_in_reg(ctx, inputs[2], NarrowValueMode::None);
|
||||||
let ty_access = ty.unwrap();
|
let ty_access = ty.unwrap();
|
||||||
assert!(is_valid_atomic_transaction_ty(ty_access));
|
assert!(is_valid_atomic_transaction_ty(ty_access));
|
||||||
let memflags = ctx.memflags(insn).expect("memory flags");
|
|
||||||
let srcloc = if !memflags.notrap() {
|
|
||||||
Some(ctx.srcloc(insn))
|
|
||||||
} else {
|
|
||||||
None
|
|
||||||
};
|
|
||||||
// Make sure that all three args are in virtual regs. See corresponding comment
|
// Make sure that all three args are in virtual regs. See corresponding comment
|
||||||
// for `Opcode::AtomicRmw` above.
|
// for `Opcode::AtomicRmw` above.
|
||||||
r_addr = ctx.ensure_in_vreg(r_addr, I64);
|
r_addr = ctx.ensure_in_vreg(r_addr, I64);
|
||||||
@@ -1351,10 +1314,7 @@ pub(crate) fn lower_insn_to_regs<C: LowerCtx<I = Inst>>(
|
|||||||
I64,
|
I64,
|
||||||
));
|
));
|
||||||
// Now the AtomicCAS itself, implemented in the normal way, with an LL-SC loop
|
// Now the AtomicCAS itself, implemented in the normal way, with an LL-SC loop
|
||||||
ctx.emit(Inst::AtomicCAS {
|
ctx.emit(Inst::AtomicCAS { ty: ty_access });
|
||||||
ty: ty_access,
|
|
||||||
srcloc,
|
|
||||||
});
|
|
||||||
// And finally, copy the preordained AtomicCAS output reg to its destination.
|
// And finally, copy the preordained AtomicCAS output reg to its destination.
|
||||||
ctx.emit(Inst::gen_move(r_dst, xreg(27), I64));
|
ctx.emit(Inst::gen_move(r_dst, xreg(27), I64));
|
||||||
// Also, x24 and x28 are trashed. `fn aarch64_get_regs` must mention that.
|
// Also, x24 and x28 are trashed. `fn aarch64_get_regs` must mention that.
|
||||||
@@ -1365,17 +1325,10 @@ pub(crate) fn lower_insn_to_regs<C: LowerCtx<I = Inst>>(
|
|||||||
let r_addr = put_input_in_reg(ctx, inputs[0], NarrowValueMode::None);
|
let r_addr = put_input_in_reg(ctx, inputs[0], NarrowValueMode::None);
|
||||||
let ty_access = ty.unwrap();
|
let ty_access = ty.unwrap();
|
||||||
assert!(is_valid_atomic_transaction_ty(ty_access));
|
assert!(is_valid_atomic_transaction_ty(ty_access));
|
||||||
let memflags = ctx.memflags(insn).expect("memory flags");
|
|
||||||
let srcloc = if !memflags.notrap() {
|
|
||||||
Some(ctx.srcloc(insn))
|
|
||||||
} else {
|
|
||||||
None
|
|
||||||
};
|
|
||||||
ctx.emit(Inst::AtomicLoad {
|
ctx.emit(Inst::AtomicLoad {
|
||||||
ty: ty_access,
|
ty: ty_access,
|
||||||
r_data,
|
r_data,
|
||||||
r_addr,
|
r_addr,
|
||||||
srcloc,
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1384,17 +1337,10 @@ pub(crate) fn lower_insn_to_regs<C: LowerCtx<I = Inst>>(
|
|||||||
let r_addr = put_input_in_reg(ctx, inputs[1], NarrowValueMode::None);
|
let r_addr = put_input_in_reg(ctx, inputs[1], NarrowValueMode::None);
|
||||||
let ty_access = ctx.input_ty(insn, 0);
|
let ty_access = ctx.input_ty(insn, 0);
|
||||||
assert!(is_valid_atomic_transaction_ty(ty_access));
|
assert!(is_valid_atomic_transaction_ty(ty_access));
|
||||||
let memflags = ctx.memflags(insn).expect("memory flags");
|
|
||||||
let srcloc = if !memflags.notrap() {
|
|
||||||
Some(ctx.srcloc(insn))
|
|
||||||
} else {
|
|
||||||
None
|
|
||||||
};
|
|
||||||
ctx.emit(Inst::AtomicStore {
|
ctx.emit(Inst::AtomicStore {
|
||||||
ty: ty_access,
|
ty: ty_access,
|
||||||
r_data,
|
r_data,
|
||||||
r_addr,
|
r_addr,
|
||||||
srcloc,
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1811,12 +1757,12 @@ pub(crate) fn lower_insn_to_regs<C: LowerCtx<I = Inst>>(
|
|||||||
}
|
}
|
||||||
|
|
||||||
Opcode::Trap | Opcode::ResumableTrap => {
|
Opcode::Trap | Opcode::ResumableTrap => {
|
||||||
let trap_info = (ctx.srcloc(insn), ctx.data(insn).trap_code().unwrap());
|
let trap_code = ctx.data(insn).trap_code().unwrap();
|
||||||
ctx.emit_safepoint(Inst::Udf { trap_info });
|
ctx.emit_safepoint(Inst::Udf { trap_code });
|
||||||
}
|
}
|
||||||
|
|
||||||
Opcode::Trapif | Opcode::Trapff => {
|
Opcode::Trapif | Opcode::Trapff => {
|
||||||
let trap_info = (ctx.srcloc(insn), ctx.data(insn).trap_code().unwrap());
|
let trap_code = ctx.data(insn).trap_code().unwrap();
|
||||||
|
|
||||||
let cond = if maybe_input_insn(ctx, inputs[0], Opcode::IaddIfcout).is_some() {
|
let cond = if maybe_input_insn(ctx, inputs[0], Opcode::IaddIfcout).is_some() {
|
||||||
let condcode = ctx.data(insn).cond_code().unwrap();
|
let condcode = ctx.data(insn).cond_code().unwrap();
|
||||||
@@ -1847,7 +1793,7 @@ pub(crate) fn lower_insn_to_regs<C: LowerCtx<I = Inst>>(
|
|||||||
};
|
};
|
||||||
|
|
||||||
ctx.emit_safepoint(Inst::TrapIf {
|
ctx.emit_safepoint(Inst::TrapIf {
|
||||||
trap_info,
|
trap_code,
|
||||||
kind: CondBrKind::Cond(cond),
|
kind: CondBrKind::Cond(cond),
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@@ -1864,11 +1810,9 @@ pub(crate) fn lower_insn_to_regs<C: LowerCtx<I = Inst>>(
|
|||||||
let rd = get_output_reg(ctx, outputs[0]);
|
let rd = get_output_reg(ctx, outputs[0]);
|
||||||
let (extname, _) = ctx.call_target(insn).unwrap();
|
let (extname, _) = ctx.call_target(insn).unwrap();
|
||||||
let extname = extname.clone();
|
let extname = extname.clone();
|
||||||
let loc = ctx.srcloc(insn);
|
|
||||||
ctx.emit(Inst::LoadExtName {
|
ctx.emit(Inst::LoadExtName {
|
||||||
rd,
|
rd,
|
||||||
name: Box::new(extname),
|
name: Box::new(extname),
|
||||||
srcloc: loc,
|
|
||||||
offset: 0,
|
offset: 0,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@@ -1881,17 +1825,14 @@ pub(crate) fn lower_insn_to_regs<C: LowerCtx<I = Inst>>(
|
|||||||
let rd = get_output_reg(ctx, outputs[0]);
|
let rd = get_output_reg(ctx, outputs[0]);
|
||||||
let (extname, _, offset) = ctx.symbol_value(insn).unwrap();
|
let (extname, _, offset) = ctx.symbol_value(insn).unwrap();
|
||||||
let extname = extname.clone();
|
let extname = extname.clone();
|
||||||
let loc = ctx.srcloc(insn);
|
|
||||||
ctx.emit(Inst::LoadExtName {
|
ctx.emit(Inst::LoadExtName {
|
||||||
rd,
|
rd,
|
||||||
name: Box::new(extname),
|
name: Box::new(extname),
|
||||||
srcloc: loc,
|
|
||||||
offset,
|
offset,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
Opcode::Call | Opcode::CallIndirect => {
|
Opcode::Call | Opcode::CallIndirect => {
|
||||||
let loc = ctx.srcloc(insn);
|
|
||||||
let caller_conv = ctx.abi().call_conv();
|
let caller_conv = ctx.abi().call_conv();
|
||||||
let (mut abi, inputs) = match op {
|
let (mut abi, inputs) = match op {
|
||||||
Opcode::Call => {
|
Opcode::Call => {
|
||||||
@@ -1901,7 +1842,7 @@ pub(crate) fn lower_insn_to_regs<C: LowerCtx<I = Inst>>(
|
|||||||
assert!(inputs.len() == sig.params.len());
|
assert!(inputs.len() == sig.params.len());
|
||||||
assert!(outputs.len() == sig.returns.len());
|
assert!(outputs.len() == sig.returns.len());
|
||||||
(
|
(
|
||||||
AArch64ABICaller::from_func(sig, &extname, dist, loc, caller_conv)?,
|
AArch64ABICaller::from_func(sig, &extname, dist, caller_conv)?,
|
||||||
&inputs[..],
|
&inputs[..],
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
@@ -1911,7 +1852,7 @@ pub(crate) fn lower_insn_to_regs<C: LowerCtx<I = Inst>>(
|
|||||||
assert!(inputs.len() - 1 == sig.params.len());
|
assert!(inputs.len() - 1 == sig.params.len());
|
||||||
assert!(outputs.len() == sig.returns.len());
|
assert!(outputs.len() == sig.returns.len());
|
||||||
(
|
(
|
||||||
AArch64ABICaller::from_ptr(sig, ptr, loc, op, caller_conv)?,
|
AArch64ABICaller::from_ptr(sig, ptr, op, caller_conv)?,
|
||||||
&inputs[1..],
|
&inputs[1..],
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
@@ -2687,9 +2628,9 @@ pub(crate) fn lower_insn_to_regs<C: LowerCtx<I = Inst>>(
|
|||||||
} else {
|
} else {
|
||||||
ctx.emit(Inst::FpuCmp64 { rn, rm: rn });
|
ctx.emit(Inst::FpuCmp64 { rn, rm: rn });
|
||||||
}
|
}
|
||||||
let trap_info = (ctx.srcloc(insn), TrapCode::BadConversionToInteger);
|
let trap_code = TrapCode::BadConversionToInteger;
|
||||||
ctx.emit(Inst::TrapIf {
|
ctx.emit(Inst::TrapIf {
|
||||||
trap_info,
|
trap_code,
|
||||||
kind: CondBrKind::Cond(lower_fp_condcode(FloatCC::Unordered)),
|
kind: CondBrKind::Cond(lower_fp_condcode(FloatCC::Unordered)),
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -2739,9 +2680,9 @@ pub(crate) fn lower_insn_to_regs<C: LowerCtx<I = Inst>>(
|
|||||||
rn,
|
rn,
|
||||||
rm: tmp.to_reg(),
|
rm: tmp.to_reg(),
|
||||||
});
|
});
|
||||||
let trap_info = (ctx.srcloc(insn), TrapCode::IntegerOverflow);
|
let trap_code = TrapCode::IntegerOverflow;
|
||||||
ctx.emit(Inst::TrapIf {
|
ctx.emit(Inst::TrapIf {
|
||||||
trap_info,
|
trap_code,
|
||||||
kind: CondBrKind::Cond(lower_fp_condcode(low_cond).invert()),
|
kind: CondBrKind::Cond(lower_fp_condcode(low_cond).invert()),
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -2751,9 +2692,9 @@ pub(crate) fn lower_insn_to_regs<C: LowerCtx<I = Inst>>(
|
|||||||
rn,
|
rn,
|
||||||
rm: tmp.to_reg(),
|
rm: tmp.to_reg(),
|
||||||
});
|
});
|
||||||
let trap_info = (ctx.srcloc(insn), TrapCode::IntegerOverflow);
|
let trap_code = TrapCode::IntegerOverflow;
|
||||||
ctx.emit(Inst::TrapIf {
|
ctx.emit(Inst::TrapIf {
|
||||||
trap_info,
|
trap_code,
|
||||||
kind: CondBrKind::Cond(lower_fp_condcode(FloatCC::LessThan).invert()),
|
kind: CondBrKind::Cond(lower_fp_condcode(FloatCC::LessThan).invert()),
|
||||||
});
|
});
|
||||||
} else {
|
} else {
|
||||||
@@ -2792,9 +2733,9 @@ pub(crate) fn lower_insn_to_regs<C: LowerCtx<I = Inst>>(
|
|||||||
rn,
|
rn,
|
||||||
rm: tmp.to_reg(),
|
rm: tmp.to_reg(),
|
||||||
});
|
});
|
||||||
let trap_info = (ctx.srcloc(insn), TrapCode::IntegerOverflow);
|
let trap_code = TrapCode::IntegerOverflow;
|
||||||
ctx.emit(Inst::TrapIf {
|
ctx.emit(Inst::TrapIf {
|
||||||
trap_info,
|
trap_code,
|
||||||
kind: CondBrKind::Cond(lower_fp_condcode(low_cond).invert()),
|
kind: CondBrKind::Cond(lower_fp_condcode(low_cond).invert()),
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -2804,9 +2745,9 @@ pub(crate) fn lower_insn_to_regs<C: LowerCtx<I = Inst>>(
|
|||||||
rn,
|
rn,
|
||||||
rm: tmp.to_reg(),
|
rm: tmp.to_reg(),
|
||||||
});
|
});
|
||||||
let trap_info = (ctx.srcloc(insn), TrapCode::IntegerOverflow);
|
let trap_code = TrapCode::IntegerOverflow;
|
||||||
ctx.emit(Inst::TrapIf {
|
ctx.emit(Inst::TrapIf {
|
||||||
trap_info,
|
trap_code,
|
||||||
kind: CondBrKind::Cond(lower_fp_condcode(FloatCC::LessThan).invert()),
|
kind: CondBrKind::Cond(lower_fp_condcode(FloatCC::LessThan).invert()),
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -2,7 +2,6 @@
|
|||||||
|
|
||||||
use crate::ir;
|
use crate::ir;
|
||||||
use crate::ir::types::*;
|
use crate::ir::types::*;
|
||||||
use crate::ir::SourceLoc;
|
|
||||||
use crate::isa;
|
use crate::isa;
|
||||||
use crate::isa::arm32::inst::*;
|
use crate::isa::arm32::inst::*;
|
||||||
use crate::machinst::*;
|
use crate::machinst::*;
|
||||||
@@ -217,7 +216,7 @@ impl ABIMachineSpec for Arm32MachineDeps {
|
|||||||
rm: limit_reg,
|
rm: limit_reg,
|
||||||
});
|
});
|
||||||
insts.push(Inst::TrapIf {
|
insts.push(Inst::TrapIf {
|
||||||
trap_info: (ir::SourceLoc::default(), ir::TrapCode::StackOverflow),
|
trap_info: ir::TrapCode::StackOverflow,
|
||||||
// Here `Lo` == "less than" when interpreting the two
|
// Here `Lo` == "less than" when interpreting the two
|
||||||
// operands as unsigned integers.
|
// operands as unsigned integers.
|
||||||
cond: Cond::Lo,
|
cond: Cond::Lo,
|
||||||
@@ -366,7 +365,6 @@ impl ABIMachineSpec for Arm32MachineDeps {
|
|||||||
dest: &CallDest,
|
dest: &CallDest,
|
||||||
uses: Vec<Reg>,
|
uses: Vec<Reg>,
|
||||||
defs: Vec<Writable<Reg>>,
|
defs: Vec<Writable<Reg>>,
|
||||||
loc: SourceLoc,
|
|
||||||
opcode: ir::Opcode,
|
opcode: ir::Opcode,
|
||||||
tmp: Writable<Reg>,
|
tmp: Writable<Reg>,
|
||||||
_callee_conv: isa::CallConv,
|
_callee_conv: isa::CallConv,
|
||||||
@@ -381,7 +379,6 @@ impl ABIMachineSpec for Arm32MachineDeps {
|
|||||||
dest: name.clone(),
|
dest: name.clone(),
|
||||||
uses,
|
uses,
|
||||||
defs,
|
defs,
|
||||||
loc,
|
|
||||||
opcode,
|
opcode,
|
||||||
}),
|
}),
|
||||||
},
|
},
|
||||||
@@ -393,7 +390,6 @@ impl ABIMachineSpec for Arm32MachineDeps {
|
|||||||
rt: tmp,
|
rt: tmp,
|
||||||
name: Box::new(name.clone()),
|
name: Box::new(name.clone()),
|
||||||
offset: 0,
|
offset: 0,
|
||||||
srcloc: loc,
|
|
||||||
},
|
},
|
||||||
));
|
));
|
||||||
insts.push((
|
insts.push((
|
||||||
@@ -403,7 +399,6 @@ impl ABIMachineSpec for Arm32MachineDeps {
|
|||||||
rm: tmp.to_reg(),
|
rm: tmp.to_reg(),
|
||||||
uses,
|
uses,
|
||||||
defs,
|
defs,
|
||||||
loc,
|
|
||||||
opcode,
|
opcode,
|
||||||
}),
|
}),
|
||||||
},
|
},
|
||||||
@@ -416,7 +411,6 @@ impl ABIMachineSpec for Arm32MachineDeps {
|
|||||||
rm: *reg,
|
rm: *reg,
|
||||||
uses,
|
uses,
|
||||||
defs,
|
defs,
|
||||||
loc,
|
|
||||||
opcode,
|
opcode,
|
||||||
}),
|
}),
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
//! 32-bit ARM ISA: binary code emission.
|
//! 32-bit ARM ISA: binary code emission.
|
||||||
|
|
||||||
use crate::binemit::{Reloc, StackMap};
|
use crate::binemit::{Reloc, StackMap};
|
||||||
|
use crate::ir::SourceLoc;
|
||||||
use crate::isa::arm32::inst::*;
|
use crate::isa::arm32::inst::*;
|
||||||
|
|
||||||
use core::convert::TryFrom;
|
use core::convert::TryFrom;
|
||||||
@@ -229,6 +230,8 @@ pub struct EmitState {
|
|||||||
pub(crate) nominal_sp_to_fp: i64,
|
pub(crate) nominal_sp_to_fp: i64,
|
||||||
/// Safepoint stack map for upcoming instruction, as provided to `pre_safepoint()`.
|
/// Safepoint stack map for upcoming instruction, as provided to `pre_safepoint()`.
|
||||||
stack_map: Option<StackMap>,
|
stack_map: Option<StackMap>,
|
||||||
|
/// Source location of next machine code instruction to be emitted.
|
||||||
|
cur_srcloc: SourceLoc,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl MachInstEmitState<Inst> for EmitState {
|
impl MachInstEmitState<Inst> for EmitState {
|
||||||
@@ -237,12 +240,17 @@ impl MachInstEmitState<Inst> for EmitState {
|
|||||||
virtual_sp_offset: 0,
|
virtual_sp_offset: 0,
|
||||||
nominal_sp_to_fp: abi.frame_size() as i64,
|
nominal_sp_to_fp: abi.frame_size() as i64,
|
||||||
stack_map: None,
|
stack_map: None,
|
||||||
|
cur_srcloc: SourceLoc::default(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn pre_safepoint(&mut self, stack_map: StackMap) {
|
fn pre_safepoint(&mut self, stack_map: StackMap) {
|
||||||
self.stack_map = Some(stack_map);
|
self.stack_map = Some(stack_map);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn pre_sourceloc(&mut self, srcloc: SourceLoc) {
|
||||||
|
self.cur_srcloc = srcloc;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl EmitState {
|
impl EmitState {
|
||||||
@@ -253,6 +261,10 @@ impl EmitState {
|
|||||||
fn clear_post_insn(&mut self) {
|
fn clear_post_insn(&mut self) {
|
||||||
self.stack_map = None;
|
self.stack_map = None;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn cur_srcloc(&self) -> SourceLoc {
|
||||||
|
self.cur_srcloc
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct EmitInfo {
|
pub struct EmitInfo {
|
||||||
@@ -456,17 +468,13 @@ impl MachInstEmit for Inst {
|
|||||||
let inst = enc_32_regs(inst, None, None, None, Some(rn));
|
let inst = enc_32_regs(inst, None, None, None, Some(rn));
|
||||||
emit_32(inst, sink);
|
emit_32(inst, sink);
|
||||||
}
|
}
|
||||||
&Inst::Store {
|
&Inst::Store { rt, ref mem, bits } => {
|
||||||
rt,
|
|
||||||
ref mem,
|
|
||||||
srcloc,
|
|
||||||
bits,
|
|
||||||
} => {
|
|
||||||
let (mem_insts, mem) = mem_finalize(mem, state);
|
let (mem_insts, mem) = mem_finalize(mem, state);
|
||||||
for inst in mem_insts.into_iter() {
|
for inst in mem_insts.into_iter() {
|
||||||
inst.emit(sink, emit_info, state);
|
inst.emit(sink, emit_info, state);
|
||||||
}
|
}
|
||||||
if let Some(srcloc) = srcloc {
|
let srcloc = state.cur_srcloc();
|
||||||
|
if srcloc != SourceLoc::default() {
|
||||||
// Register the offset at which the store instruction starts.
|
// Register the offset at which the store instruction starts.
|
||||||
sink.add_trap(srcloc, TrapCode::HeapOutOfBounds);
|
sink.add_trap(srcloc, TrapCode::HeapOutOfBounds);
|
||||||
}
|
}
|
||||||
@@ -496,7 +504,6 @@ impl MachInstEmit for Inst {
|
|||||||
&Inst::Load {
|
&Inst::Load {
|
||||||
rt,
|
rt,
|
||||||
ref mem,
|
ref mem,
|
||||||
srcloc,
|
|
||||||
bits,
|
bits,
|
||||||
sign_extend,
|
sign_extend,
|
||||||
} => {
|
} => {
|
||||||
@@ -504,7 +511,8 @@ impl MachInstEmit for Inst {
|
|||||||
for inst in mem_insts.into_iter() {
|
for inst in mem_insts.into_iter() {
|
||||||
inst.emit(sink, emit_info, state);
|
inst.emit(sink, emit_info, state);
|
||||||
}
|
}
|
||||||
if let Some(srcloc) = srcloc {
|
let srcloc = state.cur_srcloc();
|
||||||
|
if srcloc != SourceLoc::default() {
|
||||||
// Register the offset at which the load instruction starts.
|
// Register the offset at which the load instruction starts.
|
||||||
sink.add_trap(srcloc, TrapCode::HeapOutOfBounds);
|
sink.add_trap(srcloc, TrapCode::HeapOutOfBounds);
|
||||||
}
|
}
|
||||||
@@ -696,23 +704,24 @@ impl MachInstEmit for Inst {
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
&Inst::Call { ref info } => {
|
&Inst::Call { ref info } => {
|
||||||
sink.add_reloc(info.loc, Reloc::Arm32Call, &info.dest, 0);
|
let srcloc = state.cur_srcloc();
|
||||||
|
sink.add_reloc(srcloc, Reloc::Arm32Call, &info.dest, 0);
|
||||||
emit_32(0b11110_0_0000000000_11_0_1_0_00000000000, sink);
|
emit_32(0b11110_0_0000000000_11_0_1_0_00000000000, sink);
|
||||||
if info.opcode.is_call() {
|
if info.opcode.is_call() {
|
||||||
sink.add_call_site(info.loc, info.opcode);
|
sink.add_call_site(srcloc, info.opcode);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
&Inst::CallInd { ref info } => {
|
&Inst::CallInd { ref info } => {
|
||||||
|
let srcloc = state.cur_srcloc();
|
||||||
sink.put2(0b01000111_1_0000_000 | (machreg_to_gpr(info.rm) << 3));
|
sink.put2(0b01000111_1_0000_000 | (machreg_to_gpr(info.rm) << 3));
|
||||||
if info.opcode.is_call() {
|
if info.opcode.is_call() {
|
||||||
sink.add_call_site(info.loc, info.opcode);
|
sink.add_call_site(srcloc, info.opcode);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
&Inst::LoadExtName {
|
&Inst::LoadExtName {
|
||||||
rt,
|
rt,
|
||||||
ref name,
|
ref name,
|
||||||
offset,
|
offset,
|
||||||
srcloc,
|
|
||||||
} => {
|
} => {
|
||||||
// maybe nop2 (0|2) bytes (pc is now 4-aligned)
|
// maybe nop2 (0|2) bytes (pc is now 4-aligned)
|
||||||
// ldr rt, [pc, #4] 4 bytes
|
// ldr rt, [pc, #4] 4 bytes
|
||||||
@@ -729,7 +738,6 @@ impl MachInstEmit for Inst {
|
|||||||
let inst = Inst::Load {
|
let inst = Inst::Load {
|
||||||
rt,
|
rt,
|
||||||
mem,
|
mem,
|
||||||
srcloc: Some(srcloc),
|
|
||||||
bits: 32,
|
bits: 32,
|
||||||
sign_extend: false,
|
sign_extend: false,
|
||||||
};
|
};
|
||||||
@@ -740,6 +748,7 @@ impl MachInstEmit for Inst {
|
|||||||
};
|
};
|
||||||
inst.emit(sink, emit_info, state);
|
inst.emit(sink, emit_info, state);
|
||||||
|
|
||||||
|
let srcloc = state.cur_srcloc();
|
||||||
sink.add_reloc(srcloc, Reloc::Abs4, name, offset.into());
|
sink.add_reloc(srcloc, Reloc::Abs4, name, offset.into());
|
||||||
sink.put4(0);
|
sink.put4(0);
|
||||||
}
|
}
|
||||||
@@ -784,7 +793,8 @@ impl MachInstEmit for Inst {
|
|||||||
sink.put2(inst);
|
sink.put2(inst);
|
||||||
}
|
}
|
||||||
&Inst::Udf { trap_info } => {
|
&Inst::Udf { trap_info } => {
|
||||||
let (srcloc, code) = trap_info;
|
let srcloc = state.cur_srcloc();
|
||||||
|
let code = trap_info;
|
||||||
sink.add_trap(srcloc, code);
|
sink.add_trap(srcloc, code);
|
||||||
sink.put2(0b11011110_00000000);
|
sink.put2(0b11011110_00000000);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1244,7 +1244,6 @@ fn test_arm32_emit() {
|
|||||||
Inst::Store {
|
Inst::Store {
|
||||||
rt: rreg(0),
|
rt: rreg(0),
|
||||||
mem: AMode::reg_plus_reg(rreg(1), rreg(2), 0),
|
mem: AMode::reg_plus_reg(rreg(1), rreg(2), 0),
|
||||||
srcloc: None,
|
|
||||||
bits: 32,
|
bits: 32,
|
||||||
},
|
},
|
||||||
"41F80200",
|
"41F80200",
|
||||||
@@ -1254,7 +1253,6 @@ fn test_arm32_emit() {
|
|||||||
Inst::Store {
|
Inst::Store {
|
||||||
rt: rreg(8),
|
rt: rreg(8),
|
||||||
mem: AMode::reg_plus_reg(rreg(9), rreg(10), 3),
|
mem: AMode::reg_plus_reg(rreg(9), rreg(10), 3),
|
||||||
srcloc: None,
|
|
||||||
bits: 32,
|
bits: 32,
|
||||||
},
|
},
|
||||||
"49F83A80",
|
"49F83A80",
|
||||||
@@ -1264,7 +1262,6 @@ fn test_arm32_emit() {
|
|||||||
Inst::Store {
|
Inst::Store {
|
||||||
rt: rreg(0),
|
rt: rreg(0),
|
||||||
mem: AMode::RegOffset(rreg(1), 4095),
|
mem: AMode::RegOffset(rreg(1), 4095),
|
||||||
srcloc: None,
|
|
||||||
bits: 32,
|
bits: 32,
|
||||||
},
|
},
|
||||||
"C1F8FF0F",
|
"C1F8FF0F",
|
||||||
@@ -1274,7 +1271,6 @@ fn test_arm32_emit() {
|
|||||||
Inst::Store {
|
Inst::Store {
|
||||||
rt: rreg(8),
|
rt: rreg(8),
|
||||||
mem: AMode::RegOffset(rreg(9), 0),
|
mem: AMode::RegOffset(rreg(9), 0),
|
||||||
srcloc: None,
|
|
||||||
bits: 32,
|
bits: 32,
|
||||||
},
|
},
|
||||||
"C9F80080",
|
"C9F80080",
|
||||||
@@ -1284,7 +1280,6 @@ fn test_arm32_emit() {
|
|||||||
Inst::Store {
|
Inst::Store {
|
||||||
rt: rreg(7),
|
rt: rreg(7),
|
||||||
mem: AMode::RegOffset(rreg(11), 65535),
|
mem: AMode::RegOffset(rreg(11), 65535),
|
||||||
srcloc: None,
|
|
||||||
bits: 32,
|
bits: 32,
|
||||||
},
|
},
|
||||||
"4FF6FF7C4BF80C70",
|
"4FF6FF7C4BF80C70",
|
||||||
@@ -1294,7 +1289,6 @@ fn test_arm32_emit() {
|
|||||||
Inst::Store {
|
Inst::Store {
|
||||||
rt: rreg(10),
|
rt: rreg(10),
|
||||||
mem: AMode::RegOffset(rreg(4), 16777215),
|
mem: AMode::RegOffset(rreg(4), 16777215),
|
||||||
srcloc: None,
|
|
||||||
bits: 32,
|
bits: 32,
|
||||||
},
|
},
|
||||||
"4FF6FF7CC0F2FF0C44F80CA0",
|
"4FF6FF7CC0F2FF0C44F80CA0",
|
||||||
@@ -1304,7 +1298,6 @@ fn test_arm32_emit() {
|
|||||||
Inst::Store {
|
Inst::Store {
|
||||||
rt: rreg(0),
|
rt: rreg(0),
|
||||||
mem: AMode::reg_plus_reg(rreg(1), rreg(2), 0),
|
mem: AMode::reg_plus_reg(rreg(1), rreg(2), 0),
|
||||||
srcloc: None,
|
|
||||||
bits: 16,
|
bits: 16,
|
||||||
},
|
},
|
||||||
"21F80200",
|
"21F80200",
|
||||||
@@ -1314,7 +1307,6 @@ fn test_arm32_emit() {
|
|||||||
Inst::Store {
|
Inst::Store {
|
||||||
rt: rreg(8),
|
rt: rreg(8),
|
||||||
mem: AMode::reg_plus_reg(rreg(9), rreg(10), 2),
|
mem: AMode::reg_plus_reg(rreg(9), rreg(10), 2),
|
||||||
srcloc: None,
|
|
||||||
bits: 16,
|
bits: 16,
|
||||||
},
|
},
|
||||||
"29F82A80",
|
"29F82A80",
|
||||||
@@ -1324,7 +1316,6 @@ fn test_arm32_emit() {
|
|||||||
Inst::Store {
|
Inst::Store {
|
||||||
rt: rreg(0),
|
rt: rreg(0),
|
||||||
mem: AMode::RegOffset(rreg(1), 3210),
|
mem: AMode::RegOffset(rreg(1), 3210),
|
||||||
srcloc: None,
|
|
||||||
bits: 16,
|
bits: 16,
|
||||||
},
|
},
|
||||||
"A1F88A0C",
|
"A1F88A0C",
|
||||||
@@ -1334,7 +1325,6 @@ fn test_arm32_emit() {
|
|||||||
Inst::Store {
|
Inst::Store {
|
||||||
rt: rreg(8),
|
rt: rreg(8),
|
||||||
mem: AMode::RegOffset(rreg(9), 1),
|
mem: AMode::RegOffset(rreg(9), 1),
|
||||||
srcloc: None,
|
|
||||||
bits: 16,
|
bits: 16,
|
||||||
},
|
},
|
||||||
"A9F80180",
|
"A9F80180",
|
||||||
@@ -1344,7 +1334,6 @@ fn test_arm32_emit() {
|
|||||||
Inst::Store {
|
Inst::Store {
|
||||||
rt: rreg(7),
|
rt: rreg(7),
|
||||||
mem: AMode::RegOffset(rreg(11), 65535),
|
mem: AMode::RegOffset(rreg(11), 65535),
|
||||||
srcloc: None,
|
|
||||||
bits: 16,
|
bits: 16,
|
||||||
},
|
},
|
||||||
"4FF6FF7C2BF80C70",
|
"4FF6FF7C2BF80C70",
|
||||||
@@ -1354,7 +1343,6 @@ fn test_arm32_emit() {
|
|||||||
Inst::Store {
|
Inst::Store {
|
||||||
rt: rreg(10),
|
rt: rreg(10),
|
||||||
mem: AMode::RegOffset(rreg(4), 16777215),
|
mem: AMode::RegOffset(rreg(4), 16777215),
|
||||||
srcloc: None,
|
|
||||||
bits: 16,
|
bits: 16,
|
||||||
},
|
},
|
||||||
"4FF6FF7CC0F2FF0C24F80CA0",
|
"4FF6FF7CC0F2FF0C24F80CA0",
|
||||||
@@ -1364,7 +1352,6 @@ fn test_arm32_emit() {
|
|||||||
Inst::Store {
|
Inst::Store {
|
||||||
rt: rreg(0),
|
rt: rreg(0),
|
||||||
mem: AMode::reg_plus_reg(rreg(1), rreg(2), 0),
|
mem: AMode::reg_plus_reg(rreg(1), rreg(2), 0),
|
||||||
srcloc: None,
|
|
||||||
bits: 8,
|
bits: 8,
|
||||||
},
|
},
|
||||||
"01F80200",
|
"01F80200",
|
||||||
@@ -1374,7 +1361,6 @@ fn test_arm32_emit() {
|
|||||||
Inst::Store {
|
Inst::Store {
|
||||||
rt: rreg(8),
|
rt: rreg(8),
|
||||||
mem: AMode::reg_plus_reg(rreg(9), rreg(10), 1),
|
mem: AMode::reg_plus_reg(rreg(9), rreg(10), 1),
|
||||||
srcloc: None,
|
|
||||||
bits: 8,
|
bits: 8,
|
||||||
},
|
},
|
||||||
"09F81A80",
|
"09F81A80",
|
||||||
@@ -1384,7 +1370,6 @@ fn test_arm32_emit() {
|
|||||||
Inst::Store {
|
Inst::Store {
|
||||||
rt: rreg(0),
|
rt: rreg(0),
|
||||||
mem: AMode::RegOffset(rreg(1), 4),
|
mem: AMode::RegOffset(rreg(1), 4),
|
||||||
srcloc: None,
|
|
||||||
bits: 8,
|
bits: 8,
|
||||||
},
|
},
|
||||||
"81F80400",
|
"81F80400",
|
||||||
@@ -1394,7 +1379,6 @@ fn test_arm32_emit() {
|
|||||||
Inst::Store {
|
Inst::Store {
|
||||||
rt: rreg(8),
|
rt: rreg(8),
|
||||||
mem: AMode::RegOffset(rreg(9), 777),
|
mem: AMode::RegOffset(rreg(9), 777),
|
||||||
srcloc: None,
|
|
||||||
bits: 8,
|
bits: 8,
|
||||||
},
|
},
|
||||||
"89F80983",
|
"89F80983",
|
||||||
@@ -1404,7 +1388,6 @@ fn test_arm32_emit() {
|
|||||||
Inst::Store {
|
Inst::Store {
|
||||||
rt: rreg(7),
|
rt: rreg(7),
|
||||||
mem: AMode::RegOffset(rreg(11), 65535),
|
mem: AMode::RegOffset(rreg(11), 65535),
|
||||||
srcloc: None,
|
|
||||||
bits: 8,
|
bits: 8,
|
||||||
},
|
},
|
||||||
"4FF6FF7C0BF80C70",
|
"4FF6FF7C0BF80C70",
|
||||||
@@ -1414,7 +1397,6 @@ fn test_arm32_emit() {
|
|||||||
Inst::Store {
|
Inst::Store {
|
||||||
rt: rreg(10),
|
rt: rreg(10),
|
||||||
mem: AMode::RegOffset(rreg(4), 16777215),
|
mem: AMode::RegOffset(rreg(4), 16777215),
|
||||||
srcloc: None,
|
|
||||||
bits: 8,
|
bits: 8,
|
||||||
},
|
},
|
||||||
"4FF6FF7CC0F2FF0C04F80CA0",
|
"4FF6FF7CC0F2FF0C04F80CA0",
|
||||||
@@ -1424,7 +1406,6 @@ fn test_arm32_emit() {
|
|||||||
Inst::Load {
|
Inst::Load {
|
||||||
rt: writable_rreg(0),
|
rt: writable_rreg(0),
|
||||||
mem: AMode::reg_plus_reg(rreg(1), rreg(2), 0),
|
mem: AMode::reg_plus_reg(rreg(1), rreg(2), 0),
|
||||||
srcloc: None,
|
|
||||||
bits: 32,
|
bits: 32,
|
||||||
sign_extend: false,
|
sign_extend: false,
|
||||||
},
|
},
|
||||||
@@ -1435,7 +1416,6 @@ fn test_arm32_emit() {
|
|||||||
Inst::Load {
|
Inst::Load {
|
||||||
rt: writable_rreg(8),
|
rt: writable_rreg(8),
|
||||||
mem: AMode::reg_plus_reg(rreg(9), rreg(10), 1),
|
mem: AMode::reg_plus_reg(rreg(9), rreg(10), 1),
|
||||||
srcloc: None,
|
|
||||||
bits: 32,
|
bits: 32,
|
||||||
sign_extend: false,
|
sign_extend: false,
|
||||||
},
|
},
|
||||||
@@ -1446,7 +1426,6 @@ fn test_arm32_emit() {
|
|||||||
Inst::Load {
|
Inst::Load {
|
||||||
rt: writable_rreg(0),
|
rt: writable_rreg(0),
|
||||||
mem: AMode::RegOffset(rreg(1), 55),
|
mem: AMode::RegOffset(rreg(1), 55),
|
||||||
srcloc: None,
|
|
||||||
bits: 32,
|
bits: 32,
|
||||||
sign_extend: false,
|
sign_extend: false,
|
||||||
},
|
},
|
||||||
@@ -1457,7 +1436,6 @@ fn test_arm32_emit() {
|
|||||||
Inst::Load {
|
Inst::Load {
|
||||||
rt: writable_rreg(8),
|
rt: writable_rreg(8),
|
||||||
mem: AMode::RegOffset(rreg(9), 1234),
|
mem: AMode::RegOffset(rreg(9), 1234),
|
||||||
srcloc: None,
|
|
||||||
bits: 32,
|
bits: 32,
|
||||||
sign_extend: false,
|
sign_extend: false,
|
||||||
},
|
},
|
||||||
@@ -1468,7 +1446,6 @@ fn test_arm32_emit() {
|
|||||||
Inst::Load {
|
Inst::Load {
|
||||||
rt: writable_rreg(7),
|
rt: writable_rreg(7),
|
||||||
mem: AMode::RegOffset(rreg(11), 9876),
|
mem: AMode::RegOffset(rreg(11), 9876),
|
||||||
srcloc: None,
|
|
||||||
bits: 32,
|
bits: 32,
|
||||||
sign_extend: false,
|
sign_extend: false,
|
||||||
},
|
},
|
||||||
@@ -1479,7 +1456,6 @@ fn test_arm32_emit() {
|
|||||||
Inst::Load {
|
Inst::Load {
|
||||||
rt: writable_rreg(10),
|
rt: writable_rreg(10),
|
||||||
mem: AMode::RegOffset(rreg(4), 252645135),
|
mem: AMode::RegOffset(rreg(4), 252645135),
|
||||||
srcloc: None,
|
|
||||||
bits: 32,
|
bits: 32,
|
||||||
sign_extend: false,
|
sign_extend: false,
|
||||||
},
|
},
|
||||||
@@ -1490,7 +1466,6 @@ fn test_arm32_emit() {
|
|||||||
Inst::Load {
|
Inst::Load {
|
||||||
rt: writable_rreg(0),
|
rt: writable_rreg(0),
|
||||||
mem: AMode::PCRel(-56),
|
mem: AMode::PCRel(-56),
|
||||||
srcloc: None,
|
|
||||||
bits: 32,
|
bits: 32,
|
||||||
sign_extend: false,
|
sign_extend: false,
|
||||||
},
|
},
|
||||||
@@ -1501,7 +1476,6 @@ fn test_arm32_emit() {
|
|||||||
Inst::Load {
|
Inst::Load {
|
||||||
rt: writable_rreg(8),
|
rt: writable_rreg(8),
|
||||||
mem: AMode::PCRel(1024),
|
mem: AMode::PCRel(1024),
|
||||||
srcloc: None,
|
|
||||||
bits: 32,
|
bits: 32,
|
||||||
sign_extend: false,
|
sign_extend: false,
|
||||||
},
|
},
|
||||||
@@ -1512,7 +1486,6 @@ fn test_arm32_emit() {
|
|||||||
Inst::Load {
|
Inst::Load {
|
||||||
rt: writable_rreg(0),
|
rt: writable_rreg(0),
|
||||||
mem: AMode::reg_plus_reg(rreg(1), rreg(2), 0),
|
mem: AMode::reg_plus_reg(rreg(1), rreg(2), 0),
|
||||||
srcloc: None,
|
|
||||||
bits: 16,
|
bits: 16,
|
||||||
sign_extend: true,
|
sign_extend: true,
|
||||||
},
|
},
|
||||||
@@ -1523,7 +1496,6 @@ fn test_arm32_emit() {
|
|||||||
Inst::Load {
|
Inst::Load {
|
||||||
rt: writable_rreg(8),
|
rt: writable_rreg(8),
|
||||||
mem: AMode::reg_plus_reg(rreg(9), rreg(10), 2),
|
mem: AMode::reg_plus_reg(rreg(9), rreg(10), 2),
|
||||||
srcloc: None,
|
|
||||||
bits: 16,
|
bits: 16,
|
||||||
sign_extend: false,
|
sign_extend: false,
|
||||||
},
|
},
|
||||||
@@ -1534,7 +1506,6 @@ fn test_arm32_emit() {
|
|||||||
Inst::Load {
|
Inst::Load {
|
||||||
rt: writable_rreg(0),
|
rt: writable_rreg(0),
|
||||||
mem: AMode::RegOffset(rreg(1), 55),
|
mem: AMode::RegOffset(rreg(1), 55),
|
||||||
srcloc: None,
|
|
||||||
bits: 16,
|
bits: 16,
|
||||||
sign_extend: false,
|
sign_extend: false,
|
||||||
},
|
},
|
||||||
@@ -1545,7 +1516,6 @@ fn test_arm32_emit() {
|
|||||||
Inst::Load {
|
Inst::Load {
|
||||||
rt: writable_rreg(8),
|
rt: writable_rreg(8),
|
||||||
mem: AMode::RegOffset(rreg(9), 1234),
|
mem: AMode::RegOffset(rreg(9), 1234),
|
||||||
srcloc: None,
|
|
||||||
bits: 16,
|
bits: 16,
|
||||||
sign_extend: true,
|
sign_extend: true,
|
||||||
},
|
},
|
||||||
@@ -1556,7 +1526,6 @@ fn test_arm32_emit() {
|
|||||||
Inst::Load {
|
Inst::Load {
|
||||||
rt: writable_rreg(7),
|
rt: writable_rreg(7),
|
||||||
mem: AMode::RegOffset(rreg(11), 9876),
|
mem: AMode::RegOffset(rreg(11), 9876),
|
||||||
srcloc: None,
|
|
||||||
bits: 16,
|
bits: 16,
|
||||||
sign_extend: true,
|
sign_extend: true,
|
||||||
},
|
},
|
||||||
@@ -1567,7 +1536,6 @@ fn test_arm32_emit() {
|
|||||||
Inst::Load {
|
Inst::Load {
|
||||||
rt: writable_rreg(10),
|
rt: writable_rreg(10),
|
||||||
mem: AMode::RegOffset(rreg(4), 252645135),
|
mem: AMode::RegOffset(rreg(4), 252645135),
|
||||||
srcloc: None,
|
|
||||||
bits: 16,
|
bits: 16,
|
||||||
sign_extend: false,
|
sign_extend: false,
|
||||||
},
|
},
|
||||||
@@ -1578,7 +1546,6 @@ fn test_arm32_emit() {
|
|||||||
Inst::Load {
|
Inst::Load {
|
||||||
rt: writable_rreg(0),
|
rt: writable_rreg(0),
|
||||||
mem: AMode::PCRel(56),
|
mem: AMode::PCRel(56),
|
||||||
srcloc: None,
|
|
||||||
bits: 16,
|
bits: 16,
|
||||||
sign_extend: false,
|
sign_extend: false,
|
||||||
},
|
},
|
||||||
@@ -1589,7 +1556,6 @@ fn test_arm32_emit() {
|
|||||||
Inst::Load {
|
Inst::Load {
|
||||||
rt: writable_rreg(8),
|
rt: writable_rreg(8),
|
||||||
mem: AMode::PCRel(-1000),
|
mem: AMode::PCRel(-1000),
|
||||||
srcloc: None,
|
|
||||||
bits: 16,
|
bits: 16,
|
||||||
sign_extend: true,
|
sign_extend: true,
|
||||||
},
|
},
|
||||||
@@ -1600,7 +1566,6 @@ fn test_arm32_emit() {
|
|||||||
Inst::Load {
|
Inst::Load {
|
||||||
rt: writable_rreg(0),
|
rt: writable_rreg(0),
|
||||||
mem: AMode::reg_plus_reg(rreg(1), rreg(2), 0),
|
mem: AMode::reg_plus_reg(rreg(1), rreg(2), 0),
|
||||||
srcloc: None,
|
|
||||||
bits: 8,
|
bits: 8,
|
||||||
sign_extend: true,
|
sign_extend: true,
|
||||||
},
|
},
|
||||||
@@ -1611,7 +1576,6 @@ fn test_arm32_emit() {
|
|||||||
Inst::Load {
|
Inst::Load {
|
||||||
rt: writable_rreg(8),
|
rt: writable_rreg(8),
|
||||||
mem: AMode::reg_plus_reg(rreg(9), rreg(10), 3),
|
mem: AMode::reg_plus_reg(rreg(9), rreg(10), 3),
|
||||||
srcloc: None,
|
|
||||||
bits: 8,
|
bits: 8,
|
||||||
sign_extend: false,
|
sign_extend: false,
|
||||||
},
|
},
|
||||||
@@ -1622,7 +1586,6 @@ fn test_arm32_emit() {
|
|||||||
Inst::Load {
|
Inst::Load {
|
||||||
rt: writable_rreg(0),
|
rt: writable_rreg(0),
|
||||||
mem: AMode::RegOffset(rreg(1), 55),
|
mem: AMode::RegOffset(rreg(1), 55),
|
||||||
srcloc: None,
|
|
||||||
bits: 8,
|
bits: 8,
|
||||||
sign_extend: false,
|
sign_extend: false,
|
||||||
},
|
},
|
||||||
@@ -1633,7 +1596,6 @@ fn test_arm32_emit() {
|
|||||||
Inst::Load {
|
Inst::Load {
|
||||||
rt: writable_rreg(8),
|
rt: writable_rreg(8),
|
||||||
mem: AMode::RegOffset(rreg(9), 1234),
|
mem: AMode::RegOffset(rreg(9), 1234),
|
||||||
srcloc: None,
|
|
||||||
bits: 8,
|
bits: 8,
|
||||||
sign_extend: true,
|
sign_extend: true,
|
||||||
},
|
},
|
||||||
@@ -1644,7 +1606,6 @@ fn test_arm32_emit() {
|
|||||||
Inst::Load {
|
Inst::Load {
|
||||||
rt: writable_rreg(7),
|
rt: writable_rreg(7),
|
||||||
mem: AMode::RegOffset(rreg(11), 9876),
|
mem: AMode::RegOffset(rreg(11), 9876),
|
||||||
srcloc: None,
|
|
||||||
bits: 8,
|
bits: 8,
|
||||||
sign_extend: true,
|
sign_extend: true,
|
||||||
},
|
},
|
||||||
@@ -1655,7 +1616,6 @@ fn test_arm32_emit() {
|
|||||||
Inst::Load {
|
Inst::Load {
|
||||||
rt: writable_rreg(10),
|
rt: writable_rreg(10),
|
||||||
mem: AMode::RegOffset(rreg(4), 252645135),
|
mem: AMode::RegOffset(rreg(4), 252645135),
|
||||||
srcloc: None,
|
|
||||||
bits: 8,
|
bits: 8,
|
||||||
sign_extend: false,
|
sign_extend: false,
|
||||||
},
|
},
|
||||||
@@ -1666,7 +1626,6 @@ fn test_arm32_emit() {
|
|||||||
Inst::Load {
|
Inst::Load {
|
||||||
rt: writable_rreg(0),
|
rt: writable_rreg(0),
|
||||||
mem: AMode::PCRel(72),
|
mem: AMode::PCRel(72),
|
||||||
srcloc: None,
|
|
||||||
bits: 8,
|
bits: 8,
|
||||||
sign_extend: false,
|
sign_extend: false,
|
||||||
},
|
},
|
||||||
@@ -1677,7 +1636,6 @@ fn test_arm32_emit() {
|
|||||||
Inst::Load {
|
Inst::Load {
|
||||||
rt: writable_rreg(8),
|
rt: writable_rreg(8),
|
||||||
mem: AMode::PCRel(-1234),
|
mem: AMode::PCRel(-1234),
|
||||||
srcloc: None,
|
|
||||||
bits: 8,
|
bits: 8,
|
||||||
sign_extend: true,
|
sign_extend: true,
|
||||||
},
|
},
|
||||||
@@ -1961,7 +1919,7 @@ fn test_arm32_emit() {
|
|||||||
insns.push((
|
insns.push((
|
||||||
Inst::TrapIf {
|
Inst::TrapIf {
|
||||||
cond: Cond::Eq,
|
cond: Cond::Eq,
|
||||||
trap_info: (SourceLoc::default(), TrapCode::Interrupt),
|
trap_info: TrapCode::Interrupt,
|
||||||
},
|
},
|
||||||
"40F0018000DE",
|
"40F0018000DE",
|
||||||
"bne 2 ; udf #0",
|
"bne 2 ; udf #0",
|
||||||
@@ -1969,14 +1927,14 @@ fn test_arm32_emit() {
|
|||||||
insns.push((
|
insns.push((
|
||||||
Inst::TrapIf {
|
Inst::TrapIf {
|
||||||
cond: Cond::Hs,
|
cond: Cond::Hs,
|
||||||
trap_info: (SourceLoc::default(), TrapCode::Interrupt),
|
trap_info: TrapCode::Interrupt,
|
||||||
},
|
},
|
||||||
"C0F0018000DE",
|
"C0F0018000DE",
|
||||||
"blo 2 ; udf #0",
|
"blo 2 ; udf #0",
|
||||||
));
|
));
|
||||||
insns.push((
|
insns.push((
|
||||||
Inst::Udf {
|
Inst::Udf {
|
||||||
trap_info: (SourceLoc::default(), TrapCode::Interrupt),
|
trap_info: TrapCode::Interrupt,
|
||||||
},
|
},
|
||||||
"00DE",
|
"00DE",
|
||||||
"udf #0",
|
"udf #0",
|
||||||
|
|||||||
@@ -4,7 +4,7 @@
|
|||||||
|
|
||||||
use crate::binemit::CodeOffset;
|
use crate::binemit::CodeOffset;
|
||||||
use crate::ir::types::{B1, B16, B32, B8, I16, I32, I8, IFLAGS};
|
use crate::ir::types::{B1, B16, B32, B8, I16, I32, I8, IFLAGS};
|
||||||
use crate::ir::{ExternalName, Opcode, SourceLoc, TrapCode, Type};
|
use crate::ir::{ExternalName, Opcode, TrapCode, Type};
|
||||||
use crate::machinst::*;
|
use crate::machinst::*;
|
||||||
use crate::{settings, CodegenError, CodegenResult};
|
use crate::{settings, CodegenError, CodegenResult};
|
||||||
|
|
||||||
@@ -83,7 +83,6 @@ pub struct CallInfo {
|
|||||||
pub dest: ExternalName,
|
pub dest: ExternalName,
|
||||||
pub uses: Vec<Reg>,
|
pub uses: Vec<Reg>,
|
||||||
pub defs: Vec<Writable<Reg>>,
|
pub defs: Vec<Writable<Reg>>,
|
||||||
pub loc: SourceLoc,
|
|
||||||
pub opcode: Opcode,
|
pub opcode: Opcode,
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -94,7 +93,6 @@ pub struct CallIndInfo {
|
|||||||
pub rm: Reg,
|
pub rm: Reg,
|
||||||
pub uses: Vec<Reg>,
|
pub uses: Vec<Reg>,
|
||||||
pub defs: Vec<Writable<Reg>>,
|
pub defs: Vec<Writable<Reg>>,
|
||||||
pub loc: SourceLoc,
|
|
||||||
pub opcode: Opcode,
|
pub opcode: Opcode,
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -218,7 +216,6 @@ pub enum Inst {
|
|||||||
Store {
|
Store {
|
||||||
rt: Reg,
|
rt: Reg,
|
||||||
mem: AMode,
|
mem: AMode,
|
||||||
srcloc: Option<SourceLoc>,
|
|
||||||
bits: u8,
|
bits: u8,
|
||||||
},
|
},
|
||||||
|
|
||||||
@@ -227,7 +224,6 @@ pub enum Inst {
|
|||||||
Load {
|
Load {
|
||||||
rt: Writable<Reg>,
|
rt: Writable<Reg>,
|
||||||
mem: AMode,
|
mem: AMode,
|
||||||
srcloc: Option<SourceLoc>,
|
|
||||||
bits: u8,
|
bits: u8,
|
||||||
sign_extend: bool,
|
sign_extend: bool,
|
||||||
},
|
},
|
||||||
@@ -276,7 +272,6 @@ pub enum Inst {
|
|||||||
LoadExtName {
|
LoadExtName {
|
||||||
rt: Writable<Reg>,
|
rt: Writable<Reg>,
|
||||||
name: Box<ExternalName>,
|
name: Box<ExternalName>,
|
||||||
srcloc: SourceLoc,
|
|
||||||
offset: i32,
|
offset: i32,
|
||||||
},
|
},
|
||||||
|
|
||||||
@@ -308,13 +303,13 @@ pub enum Inst {
|
|||||||
/// unit to the register allocator.
|
/// unit to the register allocator.
|
||||||
TrapIf {
|
TrapIf {
|
||||||
cond: Cond,
|
cond: Cond,
|
||||||
trap_info: (SourceLoc, TrapCode),
|
trap_info: TrapCode,
|
||||||
},
|
},
|
||||||
|
|
||||||
/// An instruction guaranteed to always be undefined and to trigger an illegal instruction at
|
/// An instruction guaranteed to always be undefined and to trigger an illegal instruction at
|
||||||
/// runtime.
|
/// runtime.
|
||||||
Udf {
|
Udf {
|
||||||
trap_info: (SourceLoc, TrapCode),
|
trap_info: TrapCode,
|
||||||
},
|
},
|
||||||
|
|
||||||
/// A "breakpoint" instruction, used for e.g. traps and debug breakpoints.
|
/// A "breakpoint" instruction, used for e.g. traps and debug breakpoints.
|
||||||
@@ -390,7 +385,6 @@ impl Inst {
|
|||||||
Inst::Load {
|
Inst::Load {
|
||||||
rt: into_reg,
|
rt: into_reg,
|
||||||
mem,
|
mem,
|
||||||
srcloc: None,
|
|
||||||
bits,
|
bits,
|
||||||
sign_extend: false,
|
sign_extend: false,
|
||||||
}
|
}
|
||||||
@@ -405,7 +399,6 @@ impl Inst {
|
|||||||
Inst::Store {
|
Inst::Store {
|
||||||
rt: from_reg,
|
rt: from_reg,
|
||||||
mem,
|
mem,
|
||||||
srcloc: None,
|
|
||||||
bits,
|
bits,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1189,7 +1182,6 @@ impl Inst {
|
|||||||
rt,
|
rt,
|
||||||
ref name,
|
ref name,
|
||||||
offset,
|
offset,
|
||||||
srcloc: _srcloc,
|
|
||||||
} => {
|
} => {
|
||||||
let rt = rt.show_rru(mb_rru);
|
let rt = rt.show_rru(mb_rru);
|
||||||
format!("ldr {}, [pc, #4] ; b 4 ; data {:?} + {}", rt, name, offset)
|
format!("ldr {}, [pc, #4] ; b 4 ; data {:?} + {}", rt, name, offset)
|
||||||
|
|||||||
@@ -386,19 +386,8 @@ pub(crate) fn lower_insn_to_regs<C: LowerCtx<I = Inst>>(
|
|||||||
let base = input_to_reg(ctx, inputs[1], NarrowValueMode::None);
|
let base = input_to_reg(ctx, inputs[1], NarrowValueMode::None);
|
||||||
|
|
||||||
let mem = AMode::RegOffset(base, i64::from(off));
|
let mem = AMode::RegOffset(base, i64::from(off));
|
||||||
let memflags = ctx.memflags(insn).expect("memory flags");
|
|
||||||
|
|
||||||
let srcloc = if !memflags.notrap() {
|
ctx.emit(Inst::Store { rt, mem, bits });
|
||||||
Some(ctx.srcloc(insn))
|
|
||||||
} else {
|
|
||||||
None
|
|
||||||
};
|
|
||||||
ctx.emit(Inst::Store {
|
|
||||||
rt,
|
|
||||||
mem,
|
|
||||||
srcloc,
|
|
||||||
bits,
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
Opcode::Load
|
Opcode::Load
|
||||||
| Opcode::Uload8
|
| Opcode::Uload8
|
||||||
@@ -429,17 +418,10 @@ pub(crate) fn lower_insn_to_regs<C: LowerCtx<I = Inst>>(
|
|||||||
assert_eq!(inputs.len(), 2, "only one input for store memory operands");
|
assert_eq!(inputs.len(), 2, "only one input for store memory operands");
|
||||||
let base = input_to_reg(ctx, inputs[1], NarrowValueMode::None);
|
let base = input_to_reg(ctx, inputs[1], NarrowValueMode::None);
|
||||||
let mem = AMode::RegOffset(base, i64::from(off));
|
let mem = AMode::RegOffset(base, i64::from(off));
|
||||||
let memflags = ctx.memflags(insn).expect("memory flags");
|
|
||||||
|
|
||||||
let srcloc = if !memflags.notrap() {
|
|
||||||
Some(ctx.srcloc(insn))
|
|
||||||
} else {
|
|
||||||
None
|
|
||||||
};
|
|
||||||
ctx.emit(Inst::Load {
|
ctx.emit(Inst::Load {
|
||||||
rt: out_reg,
|
rt: out_reg,
|
||||||
mem,
|
mem,
|
||||||
srcloc,
|
|
||||||
bits,
|
bits,
|
||||||
sign_extend,
|
sign_extend,
|
||||||
});
|
});
|
||||||
@@ -484,7 +466,7 @@ pub(crate) fn lower_insn_to_regs<C: LowerCtx<I = Inst>>(
|
|||||||
ctx.emit(Inst::Bkpt);
|
ctx.emit(Inst::Bkpt);
|
||||||
}
|
}
|
||||||
Opcode::Trap => {
|
Opcode::Trap => {
|
||||||
let trap_info = (ctx.srcloc(insn), inst_trapcode(ctx.data(insn)).unwrap());
|
let trap_info = inst_trapcode(ctx.data(insn)).unwrap();
|
||||||
ctx.emit(Inst::Udf { trap_info })
|
ctx.emit(Inst::Udf { trap_info })
|
||||||
}
|
}
|
||||||
Opcode::Trapif => {
|
Opcode::Trapif => {
|
||||||
@@ -496,7 +478,7 @@ pub(crate) fn lower_insn_to_regs<C: LowerCtx<I = Inst>>(
|
|||||||
debug_assert_eq!(ctx.data(cmp_insn).opcode(), Opcode::Ifcmp);
|
debug_assert_eq!(ctx.data(cmp_insn).opcode(), Opcode::Ifcmp);
|
||||||
emit_cmp(ctx, cmp_insn);
|
emit_cmp(ctx, cmp_insn);
|
||||||
|
|
||||||
let trap_info = (ctx.srcloc(insn), inst_trapcode(ctx.data(insn)).unwrap());
|
let trap_info = inst_trapcode(ctx.data(insn)).unwrap();
|
||||||
let condcode = inst_condcode(ctx.data(insn)).unwrap();
|
let condcode = inst_condcode(ctx.data(insn)).unwrap();
|
||||||
let cond = lower_condcode(condcode);
|
let cond = lower_condcode(condcode);
|
||||||
|
|
||||||
@@ -512,7 +494,6 @@ pub(crate) fn lower_insn_to_regs<C: LowerCtx<I = Inst>>(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
Opcode::Call | Opcode::CallIndirect => {
|
Opcode::Call | Opcode::CallIndirect => {
|
||||||
let loc = ctx.srcloc(insn);
|
|
||||||
let caller_conv = ctx.abi().call_conv();
|
let caller_conv = ctx.abi().call_conv();
|
||||||
let (mut abi, inputs) = match op {
|
let (mut abi, inputs) = match op {
|
||||||
Opcode::Call => {
|
Opcode::Call => {
|
||||||
@@ -522,7 +503,7 @@ pub(crate) fn lower_insn_to_regs<C: LowerCtx<I = Inst>>(
|
|||||||
assert_eq!(inputs.len(), sig.params.len());
|
assert_eq!(inputs.len(), sig.params.len());
|
||||||
assert_eq!(outputs.len(), sig.returns.len());
|
assert_eq!(outputs.len(), sig.returns.len());
|
||||||
(
|
(
|
||||||
Arm32ABICaller::from_func(sig, &extname, dist, loc, caller_conv)?,
|
Arm32ABICaller::from_func(sig, &extname, dist, caller_conv)?,
|
||||||
&inputs[..],
|
&inputs[..],
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
@@ -532,7 +513,7 @@ pub(crate) fn lower_insn_to_regs<C: LowerCtx<I = Inst>>(
|
|||||||
assert_eq!(inputs.len() - 1, sig.params.len());
|
assert_eq!(inputs.len() - 1, sig.params.len());
|
||||||
assert_eq!(outputs.len(), sig.returns.len());
|
assert_eq!(outputs.len(), sig.returns.len());
|
||||||
(
|
(
|
||||||
Arm32ABICaller::from_ptr(sig, ptr, loc, op, caller_conv)?,
|
Arm32ABICaller::from_ptr(sig, ptr, op, caller_conv)?,
|
||||||
&inputs[1..],
|
&inputs[1..],
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
//! Implementation of the standard x64 ABI.
|
//! Implementation of the standard x64 ABI.
|
||||||
|
|
||||||
use crate::ir::types::*;
|
use crate::ir::types::*;
|
||||||
use crate::ir::{self, types, SourceLoc, TrapCode, Type};
|
use crate::ir::{self, types, TrapCode, Type};
|
||||||
use crate::isa;
|
use crate::isa;
|
||||||
use crate::isa::{x64::inst::*, CallConv};
|
use crate::isa::{x64::inst::*, CallConv};
|
||||||
use crate::machinst::abi_impl::*;
|
use crate::machinst::abi_impl::*;
|
||||||
@@ -252,11 +252,11 @@ impl ABIMachineSpec for X64ABIMachineSpec {
|
|||||||
_ if ty.bytes() == 16 => ExtKind::None,
|
_ if ty.bytes() == 16 => ExtKind::None,
|
||||||
_ => panic!("load_stack({})", ty),
|
_ => panic!("load_stack({})", ty),
|
||||||
};
|
};
|
||||||
Inst::load(ty, mem, into_reg, ext_kind, /* infallible */ None)
|
Inst::load(ty, mem, into_reg, ext_kind)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn gen_store_stack(mem: StackAMode, from_reg: Reg, ty: Type) -> Self::I {
|
fn gen_store_stack(mem: StackAMode, from_reg: Reg, ty: Type) -> Self::I {
|
||||||
Inst::store(ty, from_reg, mem, /* infallible */ None)
|
Inst::store(ty, from_reg, mem)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn gen_move(to_reg: Writable<Reg>, from_reg: Reg, ty: Type) -> Self::I {
|
fn gen_move(to_reg: Writable<Reg>, from_reg: Reg, ty: Type) -> Self::I {
|
||||||
@@ -274,9 +274,9 @@ impl ABIMachineSpec for X64ABIMachineSpec {
|
|||||||
let ext_mode = ExtMode::new(from_bits as u16, to_bits as u16)
|
let ext_mode = ExtMode::new(from_bits as u16, to_bits as u16)
|
||||||
.expect(&format!("invalid extension: {} -> {}", from_bits, to_bits));
|
.expect(&format!("invalid extension: {} -> {}", from_bits, to_bits));
|
||||||
if is_signed {
|
if is_signed {
|
||||||
Inst::movsx_rm_r(ext_mode, RegMem::reg(from_reg), to_reg, None)
|
Inst::movsx_rm_r(ext_mode, RegMem::reg(from_reg), to_reg)
|
||||||
} else {
|
} else {
|
||||||
Inst::movzx_rm_r(ext_mode, RegMem::reg(from_reg), to_reg, None)
|
Inst::movzx_rm_r(ext_mode, RegMem::reg(from_reg), to_reg)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -308,7 +308,6 @@ impl ABIMachineSpec for X64ABIMachineSpec {
|
|||||||
Inst::TrapIf {
|
Inst::TrapIf {
|
||||||
// NBE == "> unsigned"; args above are reversed; this tests limit_reg > rsp.
|
// NBE == "> unsigned"; args above are reversed; this tests limit_reg > rsp.
|
||||||
cc: CC::NBE,
|
cc: CC::NBE,
|
||||||
srcloc: SourceLoc::default(),
|
|
||||||
trap_code: TrapCode::StackOverflow,
|
trap_code: TrapCode::StackOverflow,
|
||||||
},
|
},
|
||||||
]
|
]
|
||||||
@@ -335,13 +334,13 @@ impl ABIMachineSpec for X64ABIMachineSpec {
|
|||||||
assert_eq!(ty, I64);
|
assert_eq!(ty, I64);
|
||||||
let simm32 = offset as u32;
|
let simm32 = offset as u32;
|
||||||
let mem = Amode::imm_reg(simm32, base);
|
let mem = Amode::imm_reg(simm32, base);
|
||||||
Inst::load(ty, mem, into_reg, ExtKind::None, None)
|
Inst::load(ty, mem, into_reg, ExtKind::None)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn gen_store_base_offset(base: Reg, offset: i32, from_reg: Reg, ty: Type) -> Self::I {
|
fn gen_store_base_offset(base: Reg, offset: i32, from_reg: Reg, ty: Type) -> Self::I {
|
||||||
let simm32 = offset as u32;
|
let simm32 = offset as u32;
|
||||||
let mem = Amode::imm_reg(simm32, base);
|
let mem = Amode::imm_reg(simm32, base);
|
||||||
Inst::store(ty, from_reg, mem, None)
|
Inst::store(ty, from_reg, mem)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn gen_sp_reg_adjust(amount: i32) -> SmallVec<[Self::I; 2]> {
|
fn gen_sp_reg_adjust(amount: i32) -> SmallVec<[Self::I; 2]> {
|
||||||
@@ -426,7 +425,6 @@ impl ABIMachineSpec for X64ABIMachineSpec {
|
|||||||
/* bytes = */ 8,
|
/* bytes = */ 8,
|
||||||
r_reg.to_reg(),
|
r_reg.to_reg(),
|
||||||
Amode::imm_reg(cur_offset, regs::rsp()),
|
Amode::imm_reg(cur_offset, regs::rsp()),
|
||||||
None,
|
|
||||||
));
|
));
|
||||||
cur_offset += 8;
|
cur_offset += 8;
|
||||||
}
|
}
|
||||||
@@ -461,7 +459,6 @@ impl ABIMachineSpec for X64ABIMachineSpec {
|
|||||||
insts.push(Inst::mov64_m_r(
|
insts.push(Inst::mov64_m_r(
|
||||||
Amode::imm_reg(cur_offset, regs::rsp()),
|
Amode::imm_reg(cur_offset, regs::rsp()),
|
||||||
Writable::from_reg(rreg.to_reg()),
|
Writable::from_reg(rreg.to_reg()),
|
||||||
None,
|
|
||||||
));
|
));
|
||||||
cur_offset += 8;
|
cur_offset += 8;
|
||||||
}
|
}
|
||||||
@@ -486,7 +483,6 @@ impl ABIMachineSpec for X64ABIMachineSpec {
|
|||||||
insts.push(Inst::mov64_m_r(
|
insts.push(Inst::mov64_m_r(
|
||||||
Amode::imm_reg(off as u32, regs::rbp()),
|
Amode::imm_reg(off as u32, regs::rbp()),
|
||||||
Writable::from_reg(regs::r14()),
|
Writable::from_reg(regs::r14()),
|
||||||
None,
|
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -498,7 +494,6 @@ impl ABIMachineSpec for X64ABIMachineSpec {
|
|||||||
dest: &CallDest,
|
dest: &CallDest,
|
||||||
uses: Vec<Reg>,
|
uses: Vec<Reg>,
|
||||||
defs: Vec<Writable<Reg>>,
|
defs: Vec<Writable<Reg>>,
|
||||||
loc: SourceLoc,
|
|
||||||
opcode: ir::Opcode,
|
opcode: ir::Opcode,
|
||||||
tmp: Writable<Reg>,
|
tmp: Writable<Reg>,
|
||||||
_callee_conv: isa::CallConv,
|
_callee_conv: isa::CallConv,
|
||||||
@@ -509,7 +504,7 @@ impl ABIMachineSpec for X64ABIMachineSpec {
|
|||||||
&CallDest::ExtName(ref name, RelocDistance::Near) => {
|
&CallDest::ExtName(ref name, RelocDistance::Near) => {
|
||||||
insts.push((
|
insts.push((
|
||||||
InstIsSafepoint::Yes,
|
InstIsSafepoint::Yes,
|
||||||
Inst::call_known(name.clone(), uses, defs, loc, opcode),
|
Inst::call_known(name.clone(), uses, defs, opcode),
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
&CallDest::ExtName(ref name, RelocDistance::Far) => {
|
&CallDest::ExtName(ref name, RelocDistance::Far) => {
|
||||||
@@ -519,18 +514,17 @@ impl ABIMachineSpec for X64ABIMachineSpec {
|
|||||||
dst: tmp,
|
dst: tmp,
|
||||||
name: Box::new(name.clone()),
|
name: Box::new(name.clone()),
|
||||||
offset: 0,
|
offset: 0,
|
||||||
srcloc: loc,
|
|
||||||
},
|
},
|
||||||
));
|
));
|
||||||
insts.push((
|
insts.push((
|
||||||
InstIsSafepoint::Yes,
|
InstIsSafepoint::Yes,
|
||||||
Inst::call_unknown(RegMem::reg(tmp.to_reg()), uses, defs, loc, opcode),
|
Inst::call_unknown(RegMem::reg(tmp.to_reg()), uses, defs, opcode),
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
&CallDest::Reg(reg) => {
|
&CallDest::Reg(reg) => {
|
||||||
insts.push((
|
insts.push((
|
||||||
InstIsSafepoint::Yes,
|
InstIsSafepoint::Yes,
|
||||||
Inst::call_unknown(RegMem::reg(reg), uses, defs, loc, opcode),
|
Inst::call_unknown(RegMem::reg(reg), uses, defs, opcode),
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
use crate::binemit::Reloc;
|
use crate::binemit::{Addend, Reloc};
|
||||||
use crate::ir::immediates::{Ieee32, Ieee64};
|
use crate::ir::immediates::{Ieee32, Ieee64};
|
||||||
use crate::ir::TrapCode;
|
use crate::ir::TrapCode;
|
||||||
use crate::isa::x64::inst::args::*;
|
use crate::isa::x64::inst::args::*;
|
||||||
@@ -181,6 +181,7 @@ impl LegacyPrefixes {
|
|||||||
/// indicate a 64-bit operation.
|
/// indicate a 64-bit operation.
|
||||||
fn emit_std_enc_mem(
|
fn emit_std_enc_mem(
|
||||||
sink: &mut MachBuffer<Inst>,
|
sink: &mut MachBuffer<Inst>,
|
||||||
|
state: &EmitState,
|
||||||
prefixes: LegacyPrefixes,
|
prefixes: LegacyPrefixes,
|
||||||
opcodes: u32,
|
opcodes: u32,
|
||||||
mut num_opcodes: usize,
|
mut num_opcodes: usize,
|
||||||
@@ -192,6 +193,11 @@ fn emit_std_enc_mem(
|
|||||||
// 64-bit integer registers, because they are part of an address
|
// 64-bit integer registers, because they are part of an address
|
||||||
// expression. But `enc_g` can be derived from a register of any class.
|
// expression. But `enc_g` can be derived from a register of any class.
|
||||||
|
|
||||||
|
let srcloc = state.cur_srcloc();
|
||||||
|
if srcloc != SourceLoc::default() {
|
||||||
|
sink.add_trap(srcloc, TrapCode::HeapOutOfBounds);
|
||||||
|
}
|
||||||
|
|
||||||
prefixes.emit(sink);
|
prefixes.emit(sink);
|
||||||
|
|
||||||
match mem_e {
|
match mem_e {
|
||||||
@@ -342,6 +348,7 @@ fn emit_std_enc_enc(
|
|||||||
|
|
||||||
fn emit_std_reg_mem(
|
fn emit_std_reg_mem(
|
||||||
sink: &mut MachBuffer<Inst>,
|
sink: &mut MachBuffer<Inst>,
|
||||||
|
state: &EmitState,
|
||||||
prefixes: LegacyPrefixes,
|
prefixes: LegacyPrefixes,
|
||||||
opcodes: u32,
|
opcodes: u32,
|
||||||
num_opcodes: usize,
|
num_opcodes: usize,
|
||||||
@@ -350,7 +357,16 @@ fn emit_std_reg_mem(
|
|||||||
rex: RexFlags,
|
rex: RexFlags,
|
||||||
) {
|
) {
|
||||||
let enc_g = reg_enc(reg_g);
|
let enc_g = reg_enc(reg_g);
|
||||||
emit_std_enc_mem(sink, prefixes, opcodes, num_opcodes, enc_g, mem_e, rex);
|
emit_std_enc_mem(
|
||||||
|
sink,
|
||||||
|
state,
|
||||||
|
prefixes,
|
||||||
|
opcodes,
|
||||||
|
num_opcodes,
|
||||||
|
enc_g,
|
||||||
|
mem_e,
|
||||||
|
rex,
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
fn emit_std_reg_reg(
|
fn emit_std_reg_reg(
|
||||||
@@ -407,6 +423,18 @@ fn one_way_jmp(sink: &mut MachBuffer<Inst>, cc: CC, label: MachLabel) {
|
|||||||
sink.put4(0x0);
|
sink.put4(0x0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Emits a relocation, attaching the current source location as well.
|
||||||
|
fn emit_reloc(
|
||||||
|
sink: &mut MachBuffer<Inst>,
|
||||||
|
state: &EmitState,
|
||||||
|
kind: Reloc,
|
||||||
|
name: &ExternalName,
|
||||||
|
addend: Addend,
|
||||||
|
) {
|
||||||
|
let srcloc = state.cur_srcloc();
|
||||||
|
sink.add_reloc(srcloc, kind, name, addend);
|
||||||
|
}
|
||||||
|
|
||||||
/// The top-level emit function.
|
/// The top-level emit function.
|
||||||
///
|
///
|
||||||
/// Important! Do not add improved (shortened) encoding cases to existing
|
/// Important! Do not add improved (shortened) encoding cases to existing
|
||||||
@@ -505,13 +533,15 @@ pub(crate) fn emit(
|
|||||||
}
|
}
|
||||||
|
|
||||||
RegMemImm::Mem { addr } => {
|
RegMemImm::Mem { addr } => {
|
||||||
|
let amode = addr.finalize(state);
|
||||||
emit_std_reg_mem(
|
emit_std_reg_mem(
|
||||||
sink,
|
sink,
|
||||||
|
state,
|
||||||
LegacyPrefixes::None,
|
LegacyPrefixes::None,
|
||||||
0x0FAF,
|
0x0FAF,
|
||||||
2,
|
2,
|
||||||
reg_g.to_reg(),
|
reg_g.to_reg(),
|
||||||
&addr.finalize(state),
|
&amode,
|
||||||
rex,
|
rex,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
@@ -562,13 +592,15 @@ pub(crate) fn emit(
|
|||||||
|
|
||||||
RegMemImm::Mem { addr } => {
|
RegMemImm::Mem { addr } => {
|
||||||
// Here we revert to the "normal" G-E ordering.
|
// Here we revert to the "normal" G-E ordering.
|
||||||
|
let amode = addr.finalize(state);
|
||||||
emit_std_reg_mem(
|
emit_std_reg_mem(
|
||||||
sink,
|
sink,
|
||||||
|
state,
|
||||||
LegacyPrefixes::None,
|
LegacyPrefixes::None,
|
||||||
opcode_m,
|
opcode_m,
|
||||||
1,
|
1,
|
||||||
reg_g.to_reg(),
|
reg_g.to_reg(),
|
||||||
&addr.finalize(state),
|
&amode,
|
||||||
rex,
|
rex,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
@@ -616,15 +648,19 @@ pub(crate) fn emit(
|
|||||||
*src,
|
*src,
|
||||||
rex_flags,
|
rex_flags,
|
||||||
),
|
),
|
||||||
RegMem::Mem { addr: src } => emit_std_reg_mem(
|
RegMem::Mem { addr: src } => {
|
||||||
|
let amode = src.finalize(state);
|
||||||
|
emit_std_reg_mem(
|
||||||
sink,
|
sink,
|
||||||
|
state,
|
||||||
prefix,
|
prefix,
|
||||||
opcode,
|
opcode,
|
||||||
num_opcodes,
|
num_opcodes,
|
||||||
dst.to_reg(),
|
dst.to_reg(),
|
||||||
&src.finalize(state),
|
&amode,
|
||||||
rex_flags,
|
rex_flags,
|
||||||
),
|
);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -660,7 +696,6 @@ pub(crate) fn emit(
|
|||||||
size,
|
size,
|
||||||
signed,
|
signed,
|
||||||
divisor,
|
divisor,
|
||||||
loc,
|
|
||||||
} => {
|
} => {
|
||||||
let (opcode, prefix, rex_flags) = match size {
|
let (opcode, prefix, rex_flags) = match size {
|
||||||
1 => (0xF6, LegacyPrefixes::None, RexFlags::clear_w()),
|
1 => (0xF6, LegacyPrefixes::None, RexFlags::clear_w()),
|
||||||
@@ -670,7 +705,8 @@ pub(crate) fn emit(
|
|||||||
_ => unreachable!("{}", size),
|
_ => unreachable!("{}", size),
|
||||||
};
|
};
|
||||||
|
|
||||||
sink.add_trap(*loc, TrapCode::IntegerDivisionByZero);
|
let loc = state.cur_srcloc();
|
||||||
|
sink.add_trap(loc, TrapCode::IntegerDivisionByZero);
|
||||||
|
|
||||||
let subopcode = if *signed { 7 } else { 6 };
|
let subopcode = if *signed { 7 } else { 6 };
|
||||||
match divisor {
|
match divisor {
|
||||||
@@ -678,15 +714,10 @@ pub(crate) fn emit(
|
|||||||
let src = int_reg_enc(*reg);
|
let src = int_reg_enc(*reg);
|
||||||
emit_std_enc_enc(sink, prefix, opcode, 1, subopcode, src, rex_flags)
|
emit_std_enc_enc(sink, prefix, opcode, 1, subopcode, src, rex_flags)
|
||||||
}
|
}
|
||||||
RegMem::Mem { addr: src } => emit_std_enc_mem(
|
RegMem::Mem { addr: src } => {
|
||||||
sink,
|
let amode = src.finalize(state);
|
||||||
prefix,
|
emit_std_enc_mem(sink, state, prefix, opcode, 1, subopcode, &amode, rex_flags);
|
||||||
opcode,
|
}
|
||||||
1,
|
|
||||||
subopcode,
|
|
||||||
&src.finalize(state),
|
|
||||||
rex_flags,
|
|
||||||
),
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -704,15 +735,10 @@ pub(crate) fn emit(
|
|||||||
let src = int_reg_enc(*reg);
|
let src = int_reg_enc(*reg);
|
||||||
emit_std_enc_enc(sink, prefix, 0xF7, 1, subopcode, src, rex_flags)
|
emit_std_enc_enc(sink, prefix, 0xF7, 1, subopcode, src, rex_flags)
|
||||||
}
|
}
|
||||||
RegMem::Mem { addr: src } => emit_std_enc_mem(
|
RegMem::Mem { addr: src } => {
|
||||||
sink,
|
let amode = src.finalize(state);
|
||||||
prefix,
|
emit_std_enc_mem(sink, state, prefix, 0xF7, 1, subopcode, &amode, rex_flags);
|
||||||
0xF7,
|
}
|
||||||
1,
|
|
||||||
subopcode,
|
|
||||||
&src.finalize(state),
|
|
||||||
rex_flags,
|
|
||||||
),
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -737,7 +763,6 @@ pub(crate) fn emit(
|
|||||||
kind,
|
kind,
|
||||||
size,
|
size,
|
||||||
divisor,
|
divisor,
|
||||||
loc,
|
|
||||||
tmp,
|
tmp,
|
||||||
} => {
|
} => {
|
||||||
// Generates the following code sequence:
|
// Generates the following code sequence:
|
||||||
@@ -773,7 +798,7 @@ pub(crate) fn emit(
|
|||||||
let inst = Inst::cmp_rmi_r(*size, RegMemImm::imm(0), divisor.to_reg());
|
let inst = Inst::cmp_rmi_r(*size, RegMemImm::imm(0), divisor.to_reg());
|
||||||
inst.emit(sink, info, state);
|
inst.emit(sink, info, state);
|
||||||
|
|
||||||
let inst = Inst::trap_if(CC::Z, TrapCode::IntegerDivisionByZero, *loc);
|
let inst = Inst::trap_if(CC::Z, TrapCode::IntegerDivisionByZero);
|
||||||
inst.emit(sink, info, state);
|
inst.emit(sink, info, state);
|
||||||
|
|
||||||
let (do_op, done_label) = if kind.is_signed() {
|
let (do_op, done_label) = if kind.is_signed() {
|
||||||
@@ -818,7 +843,7 @@ pub(crate) fn emit(
|
|||||||
}
|
}
|
||||||
|
|
||||||
// If not equal, jump over the trap.
|
// If not equal, jump over the trap.
|
||||||
let inst = Inst::trap_if(CC::Z, TrapCode::IntegerOverflow, *loc);
|
let inst = Inst::trap_if(CC::Z, TrapCode::IntegerOverflow);
|
||||||
inst.emit(sink, info, state);
|
inst.emit(sink, info, state);
|
||||||
|
|
||||||
(Some(do_op), None)
|
(Some(do_op), None)
|
||||||
@@ -847,7 +872,7 @@ pub(crate) fn emit(
|
|||||||
inst.emit(sink, info, state);
|
inst.emit(sink, info, state);
|
||||||
}
|
}
|
||||||
|
|
||||||
let inst = Inst::div(*size, kind.is_signed(), RegMem::reg(divisor.to_reg()), *loc);
|
let inst = Inst::div(*size, kind.is_signed(), RegMem::reg(divisor.to_reg()));
|
||||||
inst.emit(sink, info, state);
|
inst.emit(sink, info, state);
|
||||||
|
|
||||||
// Lowering takes care of moving the result back into the right register, see comment
|
// Lowering takes care of moving the result back into the right register, see comment
|
||||||
@@ -900,12 +925,7 @@ pub(crate) fn emit(
|
|||||||
emit_std_reg_reg(sink, LegacyPrefixes::None, 0x89, 1, *src, dst.to_reg(), rex);
|
emit_std_reg_reg(sink, LegacyPrefixes::None, 0x89, 1, *src, dst.to_reg(), rex);
|
||||||
}
|
}
|
||||||
|
|
||||||
Inst::MovzxRmR {
|
Inst::MovzxRmR { ext_mode, src, dst } => {
|
||||||
ext_mode,
|
|
||||||
src,
|
|
||||||
dst,
|
|
||||||
srcloc,
|
|
||||||
} => {
|
|
||||||
let (opcodes, num_opcodes, mut rex_flags) = match ext_mode {
|
let (opcodes, num_opcodes, mut rex_flags) = match ext_mode {
|
||||||
ExtMode::BL => {
|
ExtMode::BL => {
|
||||||
// MOVZBL is (REX.W==0) 0F B6 /r
|
// MOVZBL is (REX.W==0) 0F B6 /r
|
||||||
@@ -963,13 +983,9 @@ pub(crate) fn emit(
|
|||||||
RegMem::Mem { addr: src } => {
|
RegMem::Mem { addr: src } => {
|
||||||
let src = &src.finalize(state);
|
let src = &src.finalize(state);
|
||||||
|
|
||||||
if let Some(srcloc) = *srcloc {
|
|
||||||
// Register the offset at which the actual load instruction starts.
|
|
||||||
sink.add_trap(srcloc, TrapCode::HeapOutOfBounds);
|
|
||||||
}
|
|
||||||
|
|
||||||
emit_std_reg_mem(
|
emit_std_reg_mem(
|
||||||
sink,
|
sink,
|
||||||
|
state,
|
||||||
LegacyPrefixes::None,
|
LegacyPrefixes::None,
|
||||||
opcodes,
|
opcodes,
|
||||||
num_opcodes,
|
num_opcodes,
|
||||||
@@ -981,16 +997,12 @@ pub(crate) fn emit(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Inst::Mov64MR { src, dst, srcloc } => {
|
Inst::Mov64MR { src, dst } => {
|
||||||
let src = &src.finalize(state);
|
let src = &src.finalize(state);
|
||||||
|
|
||||||
if let Some(srcloc) = *srcloc {
|
|
||||||
// Register the offset at which the actual load instruction starts.
|
|
||||||
sink.add_trap(srcloc, TrapCode::HeapOutOfBounds);
|
|
||||||
}
|
|
||||||
|
|
||||||
emit_std_reg_mem(
|
emit_std_reg_mem(
|
||||||
sink,
|
sink,
|
||||||
|
state,
|
||||||
LegacyPrefixes::None,
|
LegacyPrefixes::None,
|
||||||
0x8B,
|
0x8B,
|
||||||
1,
|
1,
|
||||||
@@ -1000,22 +1012,22 @@ pub(crate) fn emit(
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
Inst::LoadEffectiveAddress { addr, dst } => emit_std_reg_mem(
|
Inst::LoadEffectiveAddress { addr, dst } => {
|
||||||
|
let amode = addr.finalize(state);
|
||||||
|
|
||||||
|
emit_std_reg_mem(
|
||||||
sink,
|
sink,
|
||||||
|
state,
|
||||||
LegacyPrefixes::None,
|
LegacyPrefixes::None,
|
||||||
0x8D,
|
0x8D,
|
||||||
1,
|
1,
|
||||||
dst.to_reg(),
|
dst.to_reg(),
|
||||||
&addr.finalize(state),
|
&amode,
|
||||||
RexFlags::set_w(),
|
RexFlags::set_w(),
|
||||||
),
|
);
|
||||||
|
}
|
||||||
|
|
||||||
Inst::MovsxRmR {
|
Inst::MovsxRmR { ext_mode, src, dst } => {
|
||||||
ext_mode,
|
|
||||||
src,
|
|
||||||
dst,
|
|
||||||
srcloc,
|
|
||||||
} => {
|
|
||||||
let (opcodes, num_opcodes, mut rex_flags) = match ext_mode {
|
let (opcodes, num_opcodes, mut rex_flags) = match ext_mode {
|
||||||
ExtMode::BL => {
|
ExtMode::BL => {
|
||||||
// MOVSBL is (REX.W==0) 0F BE /r
|
// MOVSBL is (REX.W==0) 0F BE /r
|
||||||
@@ -1065,13 +1077,9 @@ pub(crate) fn emit(
|
|||||||
RegMem::Mem { addr: src } => {
|
RegMem::Mem { addr: src } => {
|
||||||
let src = &src.finalize(state);
|
let src = &src.finalize(state);
|
||||||
|
|
||||||
if let Some(srcloc) = *srcloc {
|
|
||||||
// Register the offset at which the actual load instruction starts.
|
|
||||||
sink.add_trap(srcloc, TrapCode::HeapOutOfBounds);
|
|
||||||
}
|
|
||||||
|
|
||||||
emit_std_reg_mem(
|
emit_std_reg_mem(
|
||||||
sink,
|
sink,
|
||||||
|
state,
|
||||||
LegacyPrefixes::None,
|
LegacyPrefixes::None,
|
||||||
opcodes,
|
opcodes,
|
||||||
num_opcodes,
|
num_opcodes,
|
||||||
@@ -1083,19 +1091,9 @@ pub(crate) fn emit(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Inst::MovRM {
|
Inst::MovRM { size, src, dst } => {
|
||||||
size,
|
|
||||||
src,
|
|
||||||
dst,
|
|
||||||
srcloc,
|
|
||||||
} => {
|
|
||||||
let dst = &dst.finalize(state);
|
let dst = &dst.finalize(state);
|
||||||
|
|
||||||
if let Some(srcloc) = *srcloc {
|
|
||||||
// Register the offset at which the actual load instruction starts.
|
|
||||||
sink.add_trap(srcloc, TrapCode::HeapOutOfBounds);
|
|
||||||
}
|
|
||||||
|
|
||||||
match size {
|
match size {
|
||||||
1 => {
|
1 => {
|
||||||
// This is one of the few places where the presence of a
|
// This is one of the few places where the presence of a
|
||||||
@@ -1109,13 +1107,14 @@ pub(crate) fn emit(
|
|||||||
};
|
};
|
||||||
|
|
||||||
// MOV r8, r/m8 is (REX.W==0) 88 /r
|
// MOV r8, r/m8 is (REX.W==0) 88 /r
|
||||||
emit_std_reg_mem(sink, LegacyPrefixes::None, 0x88, 1, *src, dst, rex)
|
emit_std_reg_mem(sink, state, LegacyPrefixes::None, 0x88, 1, *src, dst, rex)
|
||||||
}
|
}
|
||||||
|
|
||||||
2 => {
|
2 => {
|
||||||
// MOV r16, r/m16 is 66 (REX.W==0) 89 /r
|
// MOV r16, r/m16 is 66 (REX.W==0) 89 /r
|
||||||
emit_std_reg_mem(
|
emit_std_reg_mem(
|
||||||
sink,
|
sink,
|
||||||
|
state,
|
||||||
LegacyPrefixes::_66,
|
LegacyPrefixes::_66,
|
||||||
0x89,
|
0x89,
|
||||||
1,
|
1,
|
||||||
@@ -1129,6 +1128,7 @@ pub(crate) fn emit(
|
|||||||
// MOV r32, r/m32 is (REX.W==0) 89 /r
|
// MOV r32, r/m32 is (REX.W==0) 89 /r
|
||||||
emit_std_reg_mem(
|
emit_std_reg_mem(
|
||||||
sink,
|
sink,
|
||||||
|
state,
|
||||||
LegacyPrefixes::None,
|
LegacyPrefixes::None,
|
||||||
0x89,
|
0x89,
|
||||||
1,
|
1,
|
||||||
@@ -1142,6 +1142,7 @@ pub(crate) fn emit(
|
|||||||
// MOV r64, r/m64 is (REX.W==1) 89 /r
|
// MOV r64, r/m64 is (REX.W==1) 89 /r
|
||||||
emit_std_reg_mem(
|
emit_std_reg_mem(
|
||||||
sink,
|
sink,
|
||||||
|
state,
|
||||||
LegacyPrefixes::None,
|
LegacyPrefixes::None,
|
||||||
0x89,
|
0x89,
|
||||||
1,
|
1,
|
||||||
@@ -1248,7 +1249,16 @@ pub(crate) fn emit(
|
|||||||
}
|
}
|
||||||
RegMemImm::Mem { addr } => {
|
RegMemImm::Mem { addr } => {
|
||||||
let addr = &addr.finalize(state);
|
let addr = &addr.finalize(state);
|
||||||
emit_std_reg_mem(sink, prefix, opcode_bytes, 2, dst.to_reg(), addr, rex);
|
emit_std_reg_mem(
|
||||||
|
sink,
|
||||||
|
state,
|
||||||
|
prefix,
|
||||||
|
opcode_bytes,
|
||||||
|
2,
|
||||||
|
dst.to_reg(),
|
||||||
|
addr,
|
||||||
|
rex,
|
||||||
|
);
|
||||||
}
|
}
|
||||||
RegMemImm::Imm { .. } => unreachable!(),
|
RegMemImm::Imm { .. } => unreachable!(),
|
||||||
}
|
}
|
||||||
@@ -1300,7 +1310,7 @@ pub(crate) fn emit(
|
|||||||
let addr = &addr.finalize(state);
|
let addr = &addr.finalize(state);
|
||||||
// Whereas here we revert to the "normal" G-E ordering.
|
// Whereas here we revert to the "normal" G-E ordering.
|
||||||
let opcode = if *size == 1 { 0x3A } else { 0x3B };
|
let opcode = if *size == 1 { 0x3A } else { 0x3B };
|
||||||
emit_std_reg_mem(sink, prefix, opcode, 1, *reg_g, addr, rex);
|
emit_std_reg_mem(sink, state, prefix, opcode, 1, *reg_g, addr, rex);
|
||||||
}
|
}
|
||||||
|
|
||||||
RegMemImm::Imm { simm32 } => {
|
RegMemImm::Imm { simm32 } => {
|
||||||
@@ -1358,7 +1368,16 @@ pub(crate) fn emit(
|
|||||||
}
|
}
|
||||||
RegMem::Mem { addr } => {
|
RegMem::Mem { addr } => {
|
||||||
let addr = &addr.finalize(state);
|
let addr = &addr.finalize(state);
|
||||||
emit_std_reg_mem(sink, prefix, opcode, 2, reg_g.to_reg(), addr, rex_flags);
|
emit_std_reg_mem(
|
||||||
|
sink,
|
||||||
|
state,
|
||||||
|
prefix,
|
||||||
|
opcode,
|
||||||
|
2,
|
||||||
|
reg_g.to_reg(),
|
||||||
|
addr,
|
||||||
|
rex_flags,
|
||||||
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1402,6 +1421,7 @@ pub(crate) fn emit(
|
|||||||
let addr = &addr.finalize(state);
|
let addr = &addr.finalize(state);
|
||||||
emit_std_enc_mem(
|
emit_std_enc_mem(
|
||||||
sink,
|
sink,
|
||||||
|
state,
|
||||||
LegacyPrefixes::None,
|
LegacyPrefixes::None,
|
||||||
0xFF,
|
0xFF,
|
||||||
1,
|
1,
|
||||||
@@ -1432,25 +1452,22 @@ pub(crate) fn emit(
|
|||||||
sink.put1(0x58 + (enc_dst & 7));
|
sink.put1(0x58 + (enc_dst & 7));
|
||||||
}
|
}
|
||||||
|
|
||||||
Inst::CallKnown {
|
Inst::CallKnown { dest, opcode, .. } => {
|
||||||
dest, loc, opcode, ..
|
|
||||||
} => {
|
|
||||||
if let Some(s) = state.take_stack_map() {
|
if let Some(s) = state.take_stack_map() {
|
||||||
sink.add_stack_map(StackMapExtent::UpcomingBytes(5), s);
|
sink.add_stack_map(StackMapExtent::UpcomingBytes(5), s);
|
||||||
}
|
}
|
||||||
sink.put1(0xE8);
|
sink.put1(0xE8);
|
||||||
// The addend adjusts for the difference between the end of the instruction and the
|
// The addend adjusts for the difference between the end of the instruction and the
|
||||||
// beginning of the immediate field.
|
// beginning of the immediate field.
|
||||||
sink.add_reloc(*loc, Reloc::X86CallPCRel4, &dest, -4);
|
emit_reloc(sink, state, Reloc::X86CallPCRel4, &dest, -4);
|
||||||
sink.put4(0);
|
sink.put4(0);
|
||||||
if opcode.is_call() {
|
if opcode.is_call() {
|
||||||
sink.add_call_site(*loc, *opcode);
|
let loc = state.cur_srcloc();
|
||||||
|
sink.add_call_site(loc, *opcode);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Inst::CallUnknown {
|
Inst::CallUnknown { dest, opcode, .. } => {
|
||||||
dest, opcode, loc, ..
|
|
||||||
} => {
|
|
||||||
let start_offset = sink.cur_offset();
|
let start_offset = sink.cur_offset();
|
||||||
match dest {
|
match dest {
|
||||||
RegMem::Reg { reg } => {
|
RegMem::Reg { reg } => {
|
||||||
@@ -1470,6 +1487,7 @@ pub(crate) fn emit(
|
|||||||
let addr = &addr.finalize(state);
|
let addr = &addr.finalize(state);
|
||||||
emit_std_enc_mem(
|
emit_std_enc_mem(
|
||||||
sink,
|
sink,
|
||||||
|
state,
|
||||||
LegacyPrefixes::None,
|
LegacyPrefixes::None,
|
||||||
0xFF,
|
0xFF,
|
||||||
1,
|
1,
|
||||||
@@ -1483,7 +1501,8 @@ pub(crate) fn emit(
|
|||||||
sink.add_stack_map(StackMapExtent::StartedAtOffset(start_offset), s);
|
sink.add_stack_map(StackMapExtent::StartedAtOffset(start_offset), s);
|
||||||
}
|
}
|
||||||
if opcode.is_call() {
|
if opcode.is_call() {
|
||||||
sink.add_call_site(*loc, *opcode);
|
let loc = state.cur_srcloc();
|
||||||
|
sink.add_call_site(loc, *opcode);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1566,6 +1585,7 @@ pub(crate) fn emit(
|
|||||||
let addr = &addr.finalize(state);
|
let addr = &addr.finalize(state);
|
||||||
emit_std_enc_mem(
|
emit_std_enc_mem(
|
||||||
sink,
|
sink,
|
||||||
|
state,
|
||||||
LegacyPrefixes::None,
|
LegacyPrefixes::None,
|
||||||
0xFF,
|
0xFF,
|
||||||
1,
|
1,
|
||||||
@@ -1609,7 +1629,7 @@ pub(crate) fn emit(
|
|||||||
one_way_jmp(sink, CC::NB, *default_target); // idx unsigned >= jmp table size
|
one_way_jmp(sink, CC::NB, *default_target); // idx unsigned >= jmp table size
|
||||||
|
|
||||||
// Copy the index (and make sure to clear the high 32-bits lane of tmp2).
|
// Copy the index (and make sure to clear the high 32-bits lane of tmp2).
|
||||||
let inst = Inst::movzx_rm_r(ExtMode::LQ, RegMem::reg(*idx), *tmp2, None);
|
let inst = Inst::movzx_rm_r(ExtMode::LQ, RegMem::reg(*idx), *tmp2);
|
||||||
inst.emit(sink, info, state);
|
inst.emit(sink, info, state);
|
||||||
|
|
||||||
// Load base address of jump table.
|
// Load base address of jump table.
|
||||||
@@ -1623,7 +1643,6 @@ pub(crate) fn emit(
|
|||||||
ExtMode::LQ,
|
ExtMode::LQ,
|
||||||
RegMem::mem(Amode::imm_reg_reg_shift(0, tmp1.to_reg(), tmp2.to_reg(), 2)),
|
RegMem::mem(Amode::imm_reg_reg_shift(0, tmp1.to_reg(), tmp2.to_reg(), 2)),
|
||||||
*tmp2,
|
*tmp2,
|
||||||
None,
|
|
||||||
);
|
);
|
||||||
inst.emit(sink, info, state);
|
inst.emit(sink, info, state);
|
||||||
|
|
||||||
@@ -1655,18 +1674,14 @@ pub(crate) fn emit(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Inst::TrapIf {
|
Inst::TrapIf { cc, trap_code } => {
|
||||||
cc,
|
|
||||||
trap_code,
|
|
||||||
srcloc,
|
|
||||||
} => {
|
|
||||||
let else_label = sink.get_label();
|
let else_label = sink.get_label();
|
||||||
|
|
||||||
// Jump over if the invert of CC is set (i.e. CC is not set).
|
// Jump over if the invert of CC is set (i.e. CC is not set).
|
||||||
one_way_jmp(sink, cc.invert(), else_label);
|
one_way_jmp(sink, cc.invert(), else_label);
|
||||||
|
|
||||||
// Trap!
|
// Trap!
|
||||||
let inst = Inst::trap(*srcloc, *trap_code);
|
let inst = Inst::trap(*trap_code);
|
||||||
inst.emit(sink, info, state);
|
inst.emit(sink, info, state);
|
||||||
|
|
||||||
sink.bind_label(else_label);
|
sink.bind_label(else_label);
|
||||||
@@ -1676,7 +1691,6 @@ pub(crate) fn emit(
|
|||||||
op,
|
op,
|
||||||
src: src_e,
|
src: src_e,
|
||||||
dst: reg_g,
|
dst: reg_g,
|
||||||
srcloc,
|
|
||||||
} => {
|
} => {
|
||||||
let rex = RexFlags::clear_w();
|
let rex = RexFlags::clear_w();
|
||||||
|
|
||||||
@@ -1715,11 +1729,16 @@ pub(crate) fn emit(
|
|||||||
}
|
}
|
||||||
RegMem::Mem { addr } => {
|
RegMem::Mem { addr } => {
|
||||||
let addr = &addr.finalize(state);
|
let addr = &addr.finalize(state);
|
||||||
if let Some(srcloc) = *srcloc {
|
emit_std_reg_mem(
|
||||||
// Register the offset at which the actual load instruction starts.
|
sink,
|
||||||
sink.add_trap(srcloc, TrapCode::HeapOutOfBounds);
|
state,
|
||||||
}
|
prefix,
|
||||||
emit_std_reg_mem(sink, prefix, opcode, num_opcodes, reg_g.to_reg(), addr, rex);
|
opcode,
|
||||||
|
num_opcodes,
|
||||||
|
reg_g.to_reg(),
|
||||||
|
addr,
|
||||||
|
rex,
|
||||||
|
);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
@@ -1728,7 +1747,6 @@ pub(crate) fn emit(
|
|||||||
op,
|
op,
|
||||||
src: src_e,
|
src: src_e,
|
||||||
dst: reg_g,
|
dst: reg_g,
|
||||||
srcloc,
|
|
||||||
} => {
|
} => {
|
||||||
let rex = RexFlags::clear_w();
|
let rex = RexFlags::clear_w();
|
||||||
let (prefix, opcode, length) = match op {
|
let (prefix, opcode, length) = match op {
|
||||||
@@ -1823,12 +1841,17 @@ pub(crate) fn emit(
|
|||||||
emit_std_reg_reg(sink, prefix, opcode, length, reg_g.to_reg(), *reg_e, rex);
|
emit_std_reg_reg(sink, prefix, opcode, length, reg_g.to_reg(), *reg_e, rex);
|
||||||
}
|
}
|
||||||
RegMem::Mem { addr } => {
|
RegMem::Mem { addr } => {
|
||||||
if let Some(srcloc) = *srcloc {
|
|
||||||
// Register the offset at which the actual load instruction starts.
|
|
||||||
sink.add_trap(srcloc, TrapCode::HeapOutOfBounds);
|
|
||||||
}
|
|
||||||
let addr = &addr.finalize(state);
|
let addr = &addr.finalize(state);
|
||||||
emit_std_reg_mem(sink, prefix, opcode, length, reg_g.to_reg(), addr, rex);
|
emit_std_reg_mem(
|
||||||
|
sink,
|
||||||
|
state,
|
||||||
|
prefix,
|
||||||
|
opcode,
|
||||||
|
length,
|
||||||
|
reg_g.to_reg(),
|
||||||
|
addr,
|
||||||
|
rex,
|
||||||
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1897,7 +1920,7 @@ pub(crate) fn emit(
|
|||||||
// and negative zero. These instructions merge the sign bits in that
|
// and negative zero. These instructions merge the sign bits in that
|
||||||
// case, and are no-ops otherwise.
|
// case, and are no-ops otherwise.
|
||||||
let op = if *is_min { or_op } else { and_op };
|
let op = if *is_min { or_op } else { and_op };
|
||||||
let inst = Inst::xmm_rm_r(op, RegMem::reg(*lhs), *rhs_dst, None);
|
let inst = Inst::xmm_rm_r(op, RegMem::reg(*lhs), *rhs_dst);
|
||||||
inst.emit(sink, info, state);
|
inst.emit(sink, info, state);
|
||||||
|
|
||||||
let inst = Inst::jmp_known(done);
|
let inst = Inst::jmp_known(done);
|
||||||
@@ -1907,13 +1930,13 @@ pub(crate) fn emit(
|
|||||||
// read-only operand: perform an addition between the two operands, which has the
|
// read-only operand: perform an addition between the two operands, which has the
|
||||||
// desired NaN propagation effects.
|
// desired NaN propagation effects.
|
||||||
sink.bind_label(propagate_nan);
|
sink.bind_label(propagate_nan);
|
||||||
let inst = Inst::xmm_rm_r(add_op, RegMem::reg(*lhs), *rhs_dst, None);
|
let inst = Inst::xmm_rm_r(add_op, RegMem::reg(*lhs), *rhs_dst);
|
||||||
inst.emit(sink, info, state);
|
inst.emit(sink, info, state);
|
||||||
|
|
||||||
one_way_jmp(sink, CC::P, done);
|
one_way_jmp(sink, CC::P, done);
|
||||||
|
|
||||||
sink.bind_label(do_min_max);
|
sink.bind_label(do_min_max);
|
||||||
let inst = Inst::xmm_rm_r(min_max_op, RegMem::reg(*lhs), *rhs_dst, None);
|
let inst = Inst::xmm_rm_r(min_max_op, RegMem::reg(*lhs), *rhs_dst);
|
||||||
inst.emit(sink, info, state);
|
inst.emit(sink, info, state);
|
||||||
|
|
||||||
sink.bind_label(done);
|
sink.bind_label(done);
|
||||||
@@ -1925,7 +1948,6 @@ pub(crate) fn emit(
|
|||||||
dst,
|
dst,
|
||||||
imm,
|
imm,
|
||||||
is64,
|
is64,
|
||||||
srcloc,
|
|
||||||
} => {
|
} => {
|
||||||
let (prefix, opcode, len) = match op {
|
let (prefix, opcode, len) = match op {
|
||||||
SseOpcode::Cmpps => (LegacyPrefixes::None, 0x0FC2, 2),
|
SseOpcode::Cmpps => (LegacyPrefixes::None, 0x0FC2, 2),
|
||||||
@@ -1964,16 +1986,12 @@ pub(crate) fn emit(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
RegMem::Mem { addr } => {
|
RegMem::Mem { addr } => {
|
||||||
if let Some(srcloc) = *srcloc {
|
|
||||||
// Register the offset at which the actual load instruction starts.
|
|
||||||
sink.add_trap(srcloc, TrapCode::HeapOutOfBounds);
|
|
||||||
}
|
|
||||||
let addr = &addr.finalize(state);
|
let addr = &addr.finalize(state);
|
||||||
assert!(
|
assert!(
|
||||||
!regs_swapped,
|
!regs_swapped,
|
||||||
"No existing way to encode a mem argument in the ModRM r/m field."
|
"No existing way to encode a mem argument in the ModRM r/m field."
|
||||||
);
|
);
|
||||||
emit_std_reg_mem(sink, prefix, opcode, len, dst.to_reg(), addr, rex);
|
emit_std_reg_mem(sink, state, prefix, opcode, len, dst.to_reg(), addr, rex);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
sink.put1(*imm);
|
sink.put1(*imm);
|
||||||
@@ -1981,7 +1999,7 @@ pub(crate) fn emit(
|
|||||||
|
|
||||||
Inst::XmmLoadConst { src, dst, ty } => {
|
Inst::XmmLoadConst { src, dst, ty } => {
|
||||||
let load_offset = Amode::rip_relative(sink.get_label_for_constant(*src));
|
let load_offset = Amode::rip_relative(sink.get_label_for_constant(*src));
|
||||||
let load = Inst::load(*ty, load_offset, *dst, ExtKind::None, None);
|
let load = Inst::load(*ty, load_offset, *dst, ExtKind::None);
|
||||||
load.emit(sink, info, state);
|
load.emit(sink, info, state);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1990,12 +2008,7 @@ pub(crate) fn emit(
|
|||||||
// emitted.
|
// emitted.
|
||||||
}
|
}
|
||||||
|
|
||||||
Inst::XmmMovRM {
|
Inst::XmmMovRM { op, src, dst } => {
|
||||||
op,
|
|
||||||
src,
|
|
||||||
dst,
|
|
||||||
srcloc,
|
|
||||||
} => {
|
|
||||||
let (prefix, opcode) = match op {
|
let (prefix, opcode) = match op {
|
||||||
SseOpcode::Movaps => (LegacyPrefixes::None, 0x0F29),
|
SseOpcode::Movaps => (LegacyPrefixes::None, 0x0F29),
|
||||||
SseOpcode::Movapd => (LegacyPrefixes::_66, 0x0F29),
|
SseOpcode::Movapd => (LegacyPrefixes::_66, 0x0F29),
|
||||||
@@ -2008,11 +2021,16 @@ pub(crate) fn emit(
|
|||||||
_ => unimplemented!("Opcode {:?} not implemented", op),
|
_ => unimplemented!("Opcode {:?} not implemented", op),
|
||||||
};
|
};
|
||||||
let dst = &dst.finalize(state);
|
let dst = &dst.finalize(state);
|
||||||
if let Some(srcloc) = *srcloc {
|
emit_std_reg_mem(
|
||||||
// Register the offset at which the actual load instruction starts.
|
sink,
|
||||||
sink.add_trap(srcloc, TrapCode::HeapOutOfBounds);
|
state,
|
||||||
}
|
prefix,
|
||||||
emit_std_reg_mem(sink, prefix, opcode, 2, *src, dst, RexFlags::clear_w());
|
opcode,
|
||||||
|
2,
|
||||||
|
*src,
|
||||||
|
dst,
|
||||||
|
RexFlags::clear_w(),
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
Inst::XmmToGpr {
|
Inst::XmmToGpr {
|
||||||
@@ -2070,7 +2088,7 @@ pub(crate) fn emit(
|
|||||||
}
|
}
|
||||||
RegMem::Mem { addr } => {
|
RegMem::Mem { addr } => {
|
||||||
let addr = &addr.finalize(state);
|
let addr = &addr.finalize(state);
|
||||||
emit_std_reg_mem(sink, prefix, opcode, 2, reg_g.to_reg(), addr, rex);
|
emit_std_reg_mem(sink, state, prefix, opcode, 2, reg_g.to_reg(), addr, rex);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -2090,7 +2108,7 @@ pub(crate) fn emit(
|
|||||||
}
|
}
|
||||||
RegMem::Mem { addr } => {
|
RegMem::Mem { addr } => {
|
||||||
let addr = &addr.finalize(state);
|
let addr = &addr.finalize(state);
|
||||||
emit_std_reg_mem(sink, prefix, opcode, len, *dst, addr, rex);
|
emit_std_reg_mem(sink, state, prefix, opcode, len, *dst, addr, rex);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -2185,7 +2203,7 @@ pub(crate) fn emit(
|
|||||||
} else {
|
} else {
|
||||||
SseOpcode::Addss
|
SseOpcode::Addss
|
||||||
};
|
};
|
||||||
let inst = Inst::xmm_rm_r(add_op, RegMem::reg(dst.to_reg()), *dst, None);
|
let inst = Inst::xmm_rm_r(add_op, RegMem::reg(dst.to_reg()), *dst);
|
||||||
inst.emit(sink, info, state);
|
inst.emit(sink, info, state);
|
||||||
|
|
||||||
sink.bind_label(done);
|
sink.bind_label(done);
|
||||||
@@ -2199,7 +2217,6 @@ pub(crate) fn emit(
|
|||||||
dst,
|
dst,
|
||||||
tmp_gpr,
|
tmp_gpr,
|
||||||
tmp_xmm,
|
tmp_xmm,
|
||||||
srcloc,
|
|
||||||
} => {
|
} => {
|
||||||
// Emits the following common sequence:
|
// Emits the following common sequence:
|
||||||
//
|
//
|
||||||
@@ -2292,12 +2309,8 @@ pub(crate) fn emit(
|
|||||||
// If the input was positive, saturate to INT_MAX.
|
// If the input was positive, saturate to INT_MAX.
|
||||||
|
|
||||||
// Zero out tmp_xmm.
|
// Zero out tmp_xmm.
|
||||||
let inst = Inst::xmm_rm_r(
|
let inst =
|
||||||
SseOpcode::Xorpd,
|
Inst::xmm_rm_r(SseOpcode::Xorpd, RegMem::reg(tmp_xmm.to_reg()), *tmp_xmm);
|
||||||
RegMem::reg(tmp_xmm.to_reg()),
|
|
||||||
*tmp_xmm,
|
|
||||||
None,
|
|
||||||
);
|
|
||||||
inst.emit(sink, info, state);
|
inst.emit(sink, info, state);
|
||||||
|
|
||||||
let inst = Inst::xmm_cmp_rm_r(cmp_op, RegMem::reg(src), tmp_xmm.to_reg());
|
let inst = Inst::xmm_cmp_rm_r(cmp_op, RegMem::reg(src), tmp_xmm.to_reg());
|
||||||
@@ -2317,7 +2330,7 @@ pub(crate) fn emit(
|
|||||||
} else {
|
} else {
|
||||||
let check_positive = sink.get_label();
|
let check_positive = sink.get_label();
|
||||||
|
|
||||||
let inst = Inst::trap(*srcloc, TrapCode::BadConversionToInteger);
|
let inst = Inst::trap(TrapCode::BadConversionToInteger);
|
||||||
inst.emit(sink, info, state);
|
inst.emit(sink, info, state);
|
||||||
|
|
||||||
// Check if INT_MIN was the correct result: determine the smallest floating point
|
// Check if INT_MIN was the correct result: determine the smallest floating point
|
||||||
@@ -2360,7 +2373,7 @@ pub(crate) fn emit(
|
|||||||
// jump over trap if src >= or > threshold
|
// jump over trap if src >= or > threshold
|
||||||
one_way_jmp(sink, no_overflow_cc, check_positive);
|
one_way_jmp(sink, no_overflow_cc, check_positive);
|
||||||
|
|
||||||
let inst = Inst::trap(*srcloc, TrapCode::IntegerOverflow);
|
let inst = Inst::trap(TrapCode::IntegerOverflow);
|
||||||
inst.emit(sink, info, state);
|
inst.emit(sink, info, state);
|
||||||
|
|
||||||
// If positive, it was a real overflow.
|
// If positive, it was a real overflow.
|
||||||
@@ -2368,12 +2381,8 @@ pub(crate) fn emit(
|
|||||||
sink.bind_label(check_positive);
|
sink.bind_label(check_positive);
|
||||||
|
|
||||||
// Zero out the tmp_xmm register.
|
// Zero out the tmp_xmm register.
|
||||||
let inst = Inst::xmm_rm_r(
|
let inst =
|
||||||
SseOpcode::Xorpd,
|
Inst::xmm_rm_r(SseOpcode::Xorpd, RegMem::reg(tmp_xmm.to_reg()), *tmp_xmm);
|
||||||
RegMem::reg(tmp_xmm.to_reg()),
|
|
||||||
*tmp_xmm,
|
|
||||||
None,
|
|
||||||
);
|
|
||||||
inst.emit(sink, info, state);
|
inst.emit(sink, info, state);
|
||||||
|
|
||||||
let inst = Inst::xmm_cmp_rm_r(cmp_op, RegMem::reg(src), tmp_xmm.to_reg());
|
let inst = Inst::xmm_cmp_rm_r(cmp_op, RegMem::reg(src), tmp_xmm.to_reg());
|
||||||
@@ -2381,7 +2390,7 @@ pub(crate) fn emit(
|
|||||||
|
|
||||||
one_way_jmp(sink, CC::NB, done); // jump over trap if 0 >= src
|
one_way_jmp(sink, CC::NB, done); // jump over trap if 0 >= src
|
||||||
|
|
||||||
let inst = Inst::trap(*srcloc, TrapCode::IntegerOverflow);
|
let inst = Inst::trap(TrapCode::IntegerOverflow);
|
||||||
inst.emit(sink, info, state);
|
inst.emit(sink, info, state);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -2396,7 +2405,6 @@ pub(crate) fn emit(
|
|||||||
dst,
|
dst,
|
||||||
tmp_gpr,
|
tmp_gpr,
|
||||||
tmp_xmm,
|
tmp_xmm,
|
||||||
srcloc,
|
|
||||||
} => {
|
} => {
|
||||||
// The only difference in behavior between saturating and non-saturating is how we
|
// The only difference in behavior between saturating and non-saturating is how we
|
||||||
// handle errors. Emits the following sequence:
|
// handle errors. Emits the following sequence:
|
||||||
@@ -2487,7 +2495,7 @@ pub(crate) fn emit(
|
|||||||
inst.emit(sink, info, state);
|
inst.emit(sink, info, state);
|
||||||
} else {
|
} else {
|
||||||
// Trap.
|
// Trap.
|
||||||
let inst = Inst::trap(*srcloc, TrapCode::BadConversionToInteger);
|
let inst = Inst::trap(TrapCode::BadConversionToInteger);
|
||||||
inst.emit(sink, info, state);
|
inst.emit(sink, info, state);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -2519,7 +2527,7 @@ pub(crate) fn emit(
|
|||||||
inst.emit(sink, info, state);
|
inst.emit(sink, info, state);
|
||||||
} else {
|
} else {
|
||||||
// Trap.
|
// Trap.
|
||||||
let inst = Inst::trap(*srcloc, TrapCode::IntegerOverflow);
|
let inst = Inst::trap(TrapCode::IntegerOverflow);
|
||||||
inst.emit(sink, info, state);
|
inst.emit(sink, info, state);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -2527,7 +2535,7 @@ pub(crate) fn emit(
|
|||||||
|
|
||||||
sink.bind_label(handle_large);
|
sink.bind_label(handle_large);
|
||||||
|
|
||||||
let inst = Inst::xmm_rm_r(sub_op, RegMem::reg(tmp_xmm.to_reg()), *src, None);
|
let inst = Inst::xmm_rm_r(sub_op, RegMem::reg(tmp_xmm.to_reg()), *src);
|
||||||
inst.emit(sink, info, state);
|
inst.emit(sink, info, state);
|
||||||
|
|
||||||
let inst = Inst::xmm_to_gpr(trunc_op, src.to_reg(), *dst, *dst_size);
|
let inst = Inst::xmm_to_gpr(trunc_op, src.to_reg(), *dst, *dst_size);
|
||||||
@@ -2556,7 +2564,7 @@ pub(crate) fn emit(
|
|||||||
let inst = Inst::jmp_known(done);
|
let inst = Inst::jmp_known(done);
|
||||||
inst.emit(sink, info, state);
|
inst.emit(sink, info, state);
|
||||||
} else {
|
} else {
|
||||||
let inst = Inst::trap(*srcloc, TrapCode::IntegerOverflow);
|
let inst = Inst::trap(TrapCode::IntegerOverflow);
|
||||||
inst.emit(sink, info, state);
|
inst.emit(sink, info, state);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -2582,18 +2590,13 @@ pub(crate) fn emit(
|
|||||||
sink.bind_label(done);
|
sink.bind_label(done);
|
||||||
}
|
}
|
||||||
|
|
||||||
Inst::LoadExtName {
|
Inst::LoadExtName { dst, name, offset } => {
|
||||||
dst,
|
|
||||||
name,
|
|
||||||
offset,
|
|
||||||
srcloc,
|
|
||||||
} => {
|
|
||||||
// The full address can be encoded in the register, with a relocation.
|
// The full address can be encoded in the register, with a relocation.
|
||||||
// Generates: movabsq $name, %dst
|
// Generates: movabsq $name, %dst
|
||||||
let enc_dst = int_reg_enc(dst.to_reg());
|
let enc_dst = int_reg_enc(dst.to_reg());
|
||||||
sink.put1(0x48 | ((enc_dst >> 3) & 1));
|
sink.put1(0x48 | ((enc_dst >> 3) & 1));
|
||||||
sink.put1(0xB8 | (enc_dst & 7));
|
sink.put1(0xB8 | (enc_dst & 7));
|
||||||
sink.add_reloc(*srcloc, Reloc::Abs8, name, *offset);
|
emit_reloc(sink, state, Reloc::Abs8, name, *offset);
|
||||||
if info.flags().emit_all_ones_funcaddrs() {
|
if info.flags().emit_all_ones_funcaddrs() {
|
||||||
sink.put8(u64::max_value());
|
sink.put8(u64::max_value());
|
||||||
} else {
|
} else {
|
||||||
@@ -2601,15 +2604,7 @@ pub(crate) fn emit(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Inst::LockCmpxchg {
|
Inst::LockCmpxchg { ty, src, dst } => {
|
||||||
ty,
|
|
||||||
src,
|
|
||||||
dst,
|
|
||||||
srcloc,
|
|
||||||
} => {
|
|
||||||
if let Some(srcloc) = srcloc {
|
|
||||||
sink.add_trap(*srcloc, TrapCode::HeapOutOfBounds);
|
|
||||||
}
|
|
||||||
// lock cmpxchg{b,w,l,q} %src, (dst)
|
// lock cmpxchg{b,w,l,q} %src, (dst)
|
||||||
// Note that 0xF0 is the Lock prefix.
|
// Note that 0xF0 is the Lock prefix.
|
||||||
let (prefix, rex, opcodes) = match *ty {
|
let (prefix, rex, opcodes) = match *ty {
|
||||||
@@ -2626,10 +2621,11 @@ pub(crate) fn emit(
|
|||||||
types::I64 => (LegacyPrefixes::_F0, RexFlags::set_w(), 0x0FB1),
|
types::I64 => (LegacyPrefixes::_F0, RexFlags::set_w(), 0x0FB1),
|
||||||
_ => unreachable!(),
|
_ => unreachable!(),
|
||||||
};
|
};
|
||||||
emit_std_reg_mem(sink, prefix, opcodes, 2, *src, &dst.finalize(state), rex);
|
let amode = dst.finalize(state);
|
||||||
|
emit_std_reg_mem(sink, state, prefix, opcodes, 2, *src, &amode, rex);
|
||||||
}
|
}
|
||||||
|
|
||||||
Inst::AtomicRmwSeq { ty, op, srcloc } => {
|
Inst::AtomicRmwSeq { ty, op } => {
|
||||||
// Emit this:
|
// Emit this:
|
||||||
//
|
//
|
||||||
// mov{zbq,zwq,zlq,q} (%r9), %rax // rax = old value
|
// mov{zbq,zwq,zlq,q} (%r9), %rax // rax = old value
|
||||||
@@ -2657,7 +2653,7 @@ pub(crate) fn emit(
|
|||||||
|
|
||||||
// mov{zbq,zwq,zlq,q} (%r9), %rax
|
// mov{zbq,zwq,zlq,q} (%r9), %rax
|
||||||
// No need to call `add_trap` here, since the `i1` emit will do that.
|
// No need to call `add_trap` here, since the `i1` emit will do that.
|
||||||
let i1 = Inst::load(*ty, amode.clone(), rax_w, ExtKind::ZeroExtend, *srcloc);
|
let i1 = Inst::load(*ty, amode.clone(), rax_w, ExtKind::ZeroExtend);
|
||||||
i1.emit(sink, info, state);
|
i1.emit(sink, info, state);
|
||||||
|
|
||||||
// again:
|
// again:
|
||||||
@@ -2690,7 +2686,6 @@ pub(crate) fn emit(
|
|||||||
ty: *ty,
|
ty: *ty,
|
||||||
src: r11,
|
src: r11,
|
||||||
dst: amode.into(),
|
dst: amode.into(),
|
||||||
srcloc: *srcloc,
|
|
||||||
};
|
};
|
||||||
i4.emit(sink, info, state);
|
i4.emit(sink, info, state);
|
||||||
|
|
||||||
@@ -2712,8 +2707,9 @@ pub(crate) fn emit(
|
|||||||
sink.put1(0xcc);
|
sink.put1(0xcc);
|
||||||
}
|
}
|
||||||
|
|
||||||
Inst::Ud2 { trap_info } => {
|
Inst::Ud2 { trap_code } => {
|
||||||
sink.add_trap(trap_info.0, trap_info.1);
|
let cur_srcloc = state.cur_srcloc();
|
||||||
|
sink.add_trap(cur_srcloc, *trap_code);
|
||||||
if let Some(s) = state.take_stack_map() {
|
if let Some(s) = state.take_stack_map() {
|
||||||
sink.add_stack_map(StackMapExtent::UpcomingBytes(2), s);
|
sink.add_stack_map(StackMapExtent::UpcomingBytes(2), s);
|
||||||
}
|
}
|
||||||
|
|||||||
File diff suppressed because it is too large
Load Diff
@@ -71,7 +71,6 @@ pub enum Inst {
|
|||||||
size: u8, // 1, 2, 4 or 8
|
size: u8, // 1, 2, 4 or 8
|
||||||
signed: bool,
|
signed: bool,
|
||||||
divisor: RegMem,
|
divisor: RegMem,
|
||||||
loc: SourceLoc,
|
|
||||||
},
|
},
|
||||||
|
|
||||||
/// The high bits (RDX) of a (un)signed multiply: RDX:RAX := RAX * rhs.
|
/// The high bits (RDX) of a (un)signed multiply: RDX:RAX := RAX * rhs.
|
||||||
@@ -95,7 +94,6 @@ pub enum Inst {
|
|||||||
/// different from the temporary.
|
/// different from the temporary.
|
||||||
divisor: Writable<Reg>,
|
divisor: Writable<Reg>,
|
||||||
tmp: Option<Writable<Reg>>,
|
tmp: Option<Writable<Reg>>,
|
||||||
loc: SourceLoc,
|
|
||||||
},
|
},
|
||||||
|
|
||||||
/// Do a sign-extend based on the sign of the value in rax into rdx: (cwd cdq cqo)
|
/// Do a sign-extend based on the sign of the value in rax into rdx: (cwd cdq cqo)
|
||||||
@@ -126,16 +124,12 @@ pub enum Inst {
|
|||||||
ext_mode: ExtMode,
|
ext_mode: ExtMode,
|
||||||
src: RegMem,
|
src: RegMem,
|
||||||
dst: Writable<Reg>,
|
dst: Writable<Reg>,
|
||||||
/// Source location, if the memory access can be out-of-bounds.
|
|
||||||
srcloc: Option<SourceLoc>,
|
|
||||||
},
|
},
|
||||||
|
|
||||||
/// A plain 64-bit integer load, since MovZX_RM_R can't represent that.
|
/// A plain 64-bit integer load, since MovZX_RM_R can't represent that.
|
||||||
Mov64MR {
|
Mov64MR {
|
||||||
src: SyntheticAmode,
|
src: SyntheticAmode,
|
||||||
dst: Writable<Reg>,
|
dst: Writable<Reg>,
|
||||||
/// Source location, if the memory access can be out-of-bounds.
|
|
||||||
srcloc: Option<SourceLoc>,
|
|
||||||
},
|
},
|
||||||
|
|
||||||
/// Loads the memory address of addr into dst.
|
/// Loads the memory address of addr into dst.
|
||||||
@@ -149,8 +143,6 @@ pub enum Inst {
|
|||||||
ext_mode: ExtMode,
|
ext_mode: ExtMode,
|
||||||
src: RegMem,
|
src: RegMem,
|
||||||
dst: Writable<Reg>,
|
dst: Writable<Reg>,
|
||||||
/// Source location, if the memory access can be out-of-bounds.
|
|
||||||
srcloc: Option<SourceLoc>,
|
|
||||||
},
|
},
|
||||||
|
|
||||||
/// Integer stores: mov (b w l q) reg addr.
|
/// Integer stores: mov (b w l q) reg addr.
|
||||||
@@ -158,8 +150,6 @@ pub enum Inst {
|
|||||||
size: u8, // 1, 2, 4 or 8.
|
size: u8, // 1, 2, 4 or 8.
|
||||||
src: Reg,
|
src: Reg,
|
||||||
dst: SyntheticAmode,
|
dst: SyntheticAmode,
|
||||||
/// Source location, if the memory access can be out-of-bounds.
|
|
||||||
srcloc: Option<SourceLoc>,
|
|
||||||
},
|
},
|
||||||
|
|
||||||
/// Arithmetic shifts: (shl shr sar) (b w l q) imm reg.
|
/// Arithmetic shifts: (shl shr sar) (b w l q) imm reg.
|
||||||
@@ -213,7 +203,6 @@ pub enum Inst {
|
|||||||
op: SseOpcode,
|
op: SseOpcode,
|
||||||
src: RegMem,
|
src: RegMem,
|
||||||
dst: Writable<Reg>,
|
dst: Writable<Reg>,
|
||||||
srcloc: Option<SourceLoc>,
|
|
||||||
},
|
},
|
||||||
|
|
||||||
/// XMM (scalar or vector) unary op: mov between XMM registers (32 64) (reg addr) reg, sqrt,
|
/// XMM (scalar or vector) unary op: mov between XMM registers (32 64) (reg addr) reg, sqrt,
|
||||||
@@ -226,8 +215,6 @@ pub enum Inst {
|
|||||||
op: SseOpcode,
|
op: SseOpcode,
|
||||||
src: RegMem,
|
src: RegMem,
|
||||||
dst: Writable<Reg>,
|
dst: Writable<Reg>,
|
||||||
/// Source location, if the memory access can be out-of-bounds.
|
|
||||||
srcloc: Option<SourceLoc>,
|
|
||||||
},
|
},
|
||||||
|
|
||||||
/// XMM (scalar or vector) unary op (from xmm to reg/mem): stores, movd, movq
|
/// XMM (scalar or vector) unary op (from xmm to reg/mem): stores, movd, movq
|
||||||
@@ -235,8 +222,6 @@ pub enum Inst {
|
|||||||
op: SseOpcode,
|
op: SseOpcode,
|
||||||
src: Reg,
|
src: Reg,
|
||||||
dst: SyntheticAmode,
|
dst: SyntheticAmode,
|
||||||
/// Source location, if the memory access can be out-of-bounds.
|
|
||||||
srcloc: Option<SourceLoc>,
|
|
||||||
},
|
},
|
||||||
|
|
||||||
/// XMM (vector) unary op (to move a constant value into an xmm register): movups
|
/// XMM (vector) unary op (to move a constant value into an xmm register): movups
|
||||||
@@ -289,7 +274,6 @@ pub enum Inst {
|
|||||||
dst: Writable<Reg>,
|
dst: Writable<Reg>,
|
||||||
tmp_gpr: Writable<Reg>,
|
tmp_gpr: Writable<Reg>,
|
||||||
tmp_xmm: Writable<Reg>,
|
tmp_xmm: Writable<Reg>,
|
||||||
srcloc: SourceLoc,
|
|
||||||
},
|
},
|
||||||
|
|
||||||
/// Converts a scalar xmm to an unsigned int32/int64.
|
/// Converts a scalar xmm to an unsigned int32/int64.
|
||||||
@@ -305,7 +289,6 @@ pub enum Inst {
|
|||||||
dst: Writable<Reg>,
|
dst: Writable<Reg>,
|
||||||
tmp_gpr: Writable<Reg>,
|
tmp_gpr: Writable<Reg>,
|
||||||
tmp_xmm: Writable<Reg>,
|
tmp_xmm: Writable<Reg>,
|
||||||
srcloc: SourceLoc,
|
|
||||||
},
|
},
|
||||||
|
|
||||||
/// A sequence to compute min/max with the proper NaN semantics for xmm registers.
|
/// A sequence to compute min/max with the proper NaN semantics for xmm registers.
|
||||||
@@ -340,7 +323,6 @@ pub enum Inst {
|
|||||||
dst: Writable<Reg>,
|
dst: Writable<Reg>,
|
||||||
imm: u8,
|
imm: u8,
|
||||||
is64: bool,
|
is64: bool,
|
||||||
srcloc: Option<SourceLoc>,
|
|
||||||
},
|
},
|
||||||
|
|
||||||
// =====================================
|
// =====================================
|
||||||
@@ -350,7 +332,6 @@ pub enum Inst {
|
|||||||
dest: ExternalName,
|
dest: ExternalName,
|
||||||
uses: Vec<Reg>,
|
uses: Vec<Reg>,
|
||||||
defs: Vec<Writable<Reg>>,
|
defs: Vec<Writable<Reg>>,
|
||||||
loc: SourceLoc,
|
|
||||||
opcode: Opcode,
|
opcode: Opcode,
|
||||||
},
|
},
|
||||||
|
|
||||||
@@ -359,7 +340,6 @@ pub enum Inst {
|
|||||||
dest: RegMem,
|
dest: RegMem,
|
||||||
uses: Vec<Reg>,
|
uses: Vec<Reg>,
|
||||||
defs: Vec<Writable<Reg>>,
|
defs: Vec<Writable<Reg>>,
|
||||||
loc: SourceLoc,
|
|
||||||
opcode: Opcode,
|
opcode: Opcode,
|
||||||
},
|
},
|
||||||
|
|
||||||
@@ -408,23 +388,18 @@ pub enum Inst {
|
|||||||
JmpUnknown { target: RegMem },
|
JmpUnknown { target: RegMem },
|
||||||
|
|
||||||
/// Traps if the condition code is set.
|
/// Traps if the condition code is set.
|
||||||
TrapIf {
|
TrapIf { cc: CC, trap_code: TrapCode },
|
||||||
cc: CC,
|
|
||||||
trap_code: TrapCode,
|
|
||||||
srcloc: SourceLoc,
|
|
||||||
},
|
|
||||||
|
|
||||||
/// A debug trap.
|
/// A debug trap.
|
||||||
Hlt,
|
Hlt,
|
||||||
|
|
||||||
/// An instruction that will always trigger the illegal instruction exception.
|
/// An instruction that will always trigger the illegal instruction exception.
|
||||||
Ud2 { trap_info: (SourceLoc, TrapCode) },
|
Ud2 { trap_code: TrapCode },
|
||||||
|
|
||||||
/// Loads an external symbol in a register, with a relocation: movabsq $name, dst
|
/// Loads an external symbol in a register, with a relocation: movabsq $name, dst
|
||||||
LoadExtName {
|
LoadExtName {
|
||||||
dst: Writable<Reg>,
|
dst: Writable<Reg>,
|
||||||
name: Box<ExternalName>,
|
name: Box<ExternalName>,
|
||||||
srcloc: SourceLoc,
|
|
||||||
offset: i64,
|
offset: i64,
|
||||||
},
|
},
|
||||||
|
|
||||||
@@ -443,7 +418,6 @@ pub enum Inst {
|
|||||||
ty: Type, // I8, I16, I32 or I64
|
ty: Type, // I8, I16, I32 or I64
|
||||||
src: Reg,
|
src: Reg,
|
||||||
dst: SyntheticAmode,
|
dst: SyntheticAmode,
|
||||||
srcloc: Option<SourceLoc>,
|
|
||||||
},
|
},
|
||||||
|
|
||||||
/// A synthetic instruction, based on a loop around a native `lock cmpxchg` instruction.
|
/// A synthetic instruction, based on a loop around a native `lock cmpxchg` instruction.
|
||||||
@@ -472,7 +446,6 @@ pub enum Inst {
|
|||||||
AtomicRmwSeq {
|
AtomicRmwSeq {
|
||||||
ty: Type, // I8, I16, I32 or I64
|
ty: Type, // I8, I16, I32 or I64
|
||||||
op: inst_common::AtomicRmwOp,
|
op: inst_common::AtomicRmwOp,
|
||||||
srcloc: Option<SourceLoc>,
|
|
||||||
},
|
},
|
||||||
|
|
||||||
/// A memory fence (mfence, lfence or sfence).
|
/// A memory fence (mfence, lfence or sfence).
|
||||||
@@ -617,14 +590,13 @@ impl Inst {
|
|||||||
Inst::Neg { size, src }
|
Inst::Neg { size, src }
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) fn div(size: u8, signed: bool, divisor: RegMem, loc: SourceLoc) -> Inst {
|
pub(crate) fn div(size: u8, signed: bool, divisor: RegMem) -> Inst {
|
||||||
divisor.assert_regclass_is(RegClass::I64);
|
divisor.assert_regclass_is(RegClass::I64);
|
||||||
debug_assert!(size == 8 || size == 4 || size == 2 || size == 1);
|
debug_assert!(size == 8 || size == 4 || size == 2 || size == 1);
|
||||||
Inst::Div {
|
Inst::Div {
|
||||||
size,
|
size,
|
||||||
signed,
|
signed,
|
||||||
divisor,
|
divisor,
|
||||||
loc,
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -639,7 +611,6 @@ impl Inst {
|
|||||||
size: u8,
|
size: u8,
|
||||||
divisor: Writable<Reg>,
|
divisor: Writable<Reg>,
|
||||||
tmp: Option<Writable<Reg>>,
|
tmp: Option<Writable<Reg>>,
|
||||||
loc: SourceLoc,
|
|
||||||
) -> Inst {
|
) -> Inst {
|
||||||
debug_assert!(size == 8 || size == 4 || size == 2 || size == 1);
|
debug_assert!(size == 8 || size == 4 || size == 2 || size == 1);
|
||||||
debug_assert!(divisor.to_reg().get_class() == RegClass::I64);
|
debug_assert!(divisor.to_reg().get_class() == RegClass::I64);
|
||||||
@@ -651,7 +622,6 @@ impl Inst {
|
|||||||
size,
|
size,
|
||||||
divisor,
|
divisor,
|
||||||
tmp,
|
tmp,
|
||||||
loc,
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -679,20 +649,10 @@ impl Inst {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// TODO Can be replaced by `Inst::move` (high-level) and `Inst::unary_rm_r` (low-level)
|
// TODO Can be replaced by `Inst::move` (high-level) and `Inst::unary_rm_r` (low-level)
|
||||||
pub(crate) fn xmm_mov(
|
pub(crate) fn xmm_mov(op: SseOpcode, src: RegMem, dst: Writable<Reg>) -> Inst {
|
||||||
op: SseOpcode,
|
|
||||||
src: RegMem,
|
|
||||||
dst: Writable<Reg>,
|
|
||||||
srcloc: Option<SourceLoc>,
|
|
||||||
) -> Inst {
|
|
||||||
src.assert_regclass_is(RegClass::V128);
|
src.assert_regclass_is(RegClass::V128);
|
||||||
debug_assert!(dst.to_reg().get_class() == RegClass::V128);
|
debug_assert!(dst.to_reg().get_class() == RegClass::V128);
|
||||||
Inst::XmmUnaryRmR {
|
Inst::XmmUnaryRmR { op, src, dst }
|
||||||
op,
|
|
||||||
src,
|
|
||||||
dst,
|
|
||||||
srcloc,
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) fn xmm_load_const(src: VCodeConstant, dst: Writable<Reg>, ty: Type) -> Inst {
|
pub(crate) fn xmm_load_const(src: VCodeConstant, dst: Writable<Reg>, ty: Type) -> Inst {
|
||||||
@@ -705,28 +665,13 @@ impl Inst {
|
|||||||
pub(crate) fn xmm_unary_rm_r(op: SseOpcode, src: RegMem, dst: Writable<Reg>) -> Inst {
|
pub(crate) fn xmm_unary_rm_r(op: SseOpcode, src: RegMem, dst: Writable<Reg>) -> Inst {
|
||||||
src.assert_regclass_is(RegClass::V128);
|
src.assert_regclass_is(RegClass::V128);
|
||||||
debug_assert!(dst.to_reg().get_class() == RegClass::V128);
|
debug_assert!(dst.to_reg().get_class() == RegClass::V128);
|
||||||
Inst::XmmUnaryRmR {
|
Inst::XmmUnaryRmR { op, src, dst }
|
||||||
op,
|
|
||||||
src,
|
|
||||||
dst,
|
|
||||||
srcloc: None,
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) fn xmm_rm_r(
|
pub(crate) fn xmm_rm_r(op: SseOpcode, src: RegMem, dst: Writable<Reg>) -> Self {
|
||||||
op: SseOpcode,
|
|
||||||
src: RegMem,
|
|
||||||
dst: Writable<Reg>,
|
|
||||||
srcloc: Option<SourceLoc>,
|
|
||||||
) -> Self {
|
|
||||||
src.assert_regclass_is(RegClass::V128);
|
src.assert_regclass_is(RegClass::V128);
|
||||||
debug_assert!(dst.to_reg().get_class() == RegClass::V128);
|
debug_assert!(dst.to_reg().get_class() == RegClass::V128);
|
||||||
Inst::XmmRmR {
|
Inst::XmmRmR { op, src, dst }
|
||||||
op,
|
|
||||||
src,
|
|
||||||
dst,
|
|
||||||
srcloc,
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) fn xmm_uninit_value(dst: Writable<Reg>) -> Self {
|
pub(crate) fn xmm_uninit_value(dst: Writable<Reg>) -> Self {
|
||||||
@@ -734,18 +679,12 @@ impl Inst {
|
|||||||
Inst::XmmUninitializedValue { dst }
|
Inst::XmmUninitializedValue { dst }
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) fn xmm_mov_r_m(
|
pub(crate) fn xmm_mov_r_m(op: SseOpcode, src: Reg, dst: impl Into<SyntheticAmode>) -> Inst {
|
||||||
op: SseOpcode,
|
|
||||||
src: Reg,
|
|
||||||
dst: impl Into<SyntheticAmode>,
|
|
||||||
srcloc: Option<SourceLoc>,
|
|
||||||
) -> Inst {
|
|
||||||
debug_assert!(src.get_class() == RegClass::V128);
|
debug_assert!(src.get_class() == RegClass::V128);
|
||||||
Inst::XmmMovRM {
|
Inst::XmmMovRM {
|
||||||
op,
|
op,
|
||||||
src,
|
src,
|
||||||
dst: dst.into(),
|
dst: dst.into(),
|
||||||
srcloc,
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -815,7 +754,6 @@ impl Inst {
|
|||||||
dst: Writable<Reg>,
|
dst: Writable<Reg>,
|
||||||
tmp_gpr: Writable<Reg>,
|
tmp_gpr: Writable<Reg>,
|
||||||
tmp_xmm: Writable<Reg>,
|
tmp_xmm: Writable<Reg>,
|
||||||
srcloc: SourceLoc,
|
|
||||||
) -> Inst {
|
) -> Inst {
|
||||||
debug_assert!(src.to_reg().get_class() == RegClass::V128);
|
debug_assert!(src.to_reg().get_class() == RegClass::V128);
|
||||||
debug_assert!(tmp_xmm.to_reg().get_class() == RegClass::V128);
|
debug_assert!(tmp_xmm.to_reg().get_class() == RegClass::V128);
|
||||||
@@ -829,7 +767,6 @@ impl Inst {
|
|||||||
dst,
|
dst,
|
||||||
tmp_gpr,
|
tmp_gpr,
|
||||||
tmp_xmm,
|
tmp_xmm,
|
||||||
srcloc,
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -841,7 +778,6 @@ impl Inst {
|
|||||||
dst: Writable<Reg>,
|
dst: Writable<Reg>,
|
||||||
tmp_gpr: Writable<Reg>,
|
tmp_gpr: Writable<Reg>,
|
||||||
tmp_xmm: Writable<Reg>,
|
tmp_xmm: Writable<Reg>,
|
||||||
srcloc: SourceLoc,
|
|
||||||
) -> Inst {
|
) -> Inst {
|
||||||
debug_assert!(src.to_reg().get_class() == RegClass::V128);
|
debug_assert!(src.to_reg().get_class() == RegClass::V128);
|
||||||
debug_assert!(tmp_xmm.to_reg().get_class() == RegClass::V128);
|
debug_assert!(tmp_xmm.to_reg().get_class() == RegClass::V128);
|
||||||
@@ -855,7 +791,6 @@ impl Inst {
|
|||||||
dst,
|
dst,
|
||||||
tmp_gpr,
|
tmp_gpr,
|
||||||
tmp_xmm,
|
tmp_xmm,
|
||||||
srcloc,
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -881,7 +816,6 @@ impl Inst {
|
|||||||
dst: Writable<Reg>,
|
dst: Writable<Reg>,
|
||||||
imm: u8,
|
imm: u8,
|
||||||
is64: bool,
|
is64: bool,
|
||||||
srcloc: Option<SourceLoc>,
|
|
||||||
) -> Inst {
|
) -> Inst {
|
||||||
Inst::XmmRmRImm {
|
Inst::XmmRmRImm {
|
||||||
op,
|
op,
|
||||||
@@ -889,24 +823,13 @@ impl Inst {
|
|||||||
dst,
|
dst,
|
||||||
imm,
|
imm,
|
||||||
is64,
|
is64,
|
||||||
srcloc,
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) fn movzx_rm_r(
|
pub(crate) fn movzx_rm_r(ext_mode: ExtMode, src: RegMem, dst: Writable<Reg>) -> Inst {
|
||||||
ext_mode: ExtMode,
|
|
||||||
src: RegMem,
|
|
||||||
dst: Writable<Reg>,
|
|
||||||
srcloc: Option<SourceLoc>,
|
|
||||||
) -> Inst {
|
|
||||||
src.assert_regclass_is(RegClass::I64);
|
src.assert_regclass_is(RegClass::I64);
|
||||||
debug_assert!(dst.to_reg().get_class() == RegClass::I64);
|
debug_assert!(dst.to_reg().get_class() == RegClass::I64);
|
||||||
Inst::MovzxRmR {
|
Inst::MovzxRmR { ext_mode, src, dst }
|
||||||
ext_mode,
|
|
||||||
src,
|
|
||||||
dst,
|
|
||||||
srcloc,
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) fn xmm_rmi_reg(opcode: SseOpcode, src: RegMemImm, dst: Writable<Reg>) -> Inst {
|
pub(crate) fn xmm_rmi_reg(opcode: SseOpcode, src: RegMemImm, dst: Writable<Reg>) -> Inst {
|
||||||
@@ -915,41 +838,26 @@ impl Inst {
|
|||||||
Inst::XmmRmiReg { opcode, src, dst }
|
Inst::XmmRmiReg { opcode, src, dst }
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) fn movsx_rm_r(
|
pub(crate) fn movsx_rm_r(ext_mode: ExtMode, src: RegMem, dst: Writable<Reg>) -> Inst {
|
||||||
ext_mode: ExtMode,
|
|
||||||
src: RegMem,
|
|
||||||
dst: Writable<Reg>,
|
|
||||||
srcloc: Option<SourceLoc>,
|
|
||||||
) -> Inst {
|
|
||||||
src.assert_regclass_is(RegClass::I64);
|
src.assert_regclass_is(RegClass::I64);
|
||||||
debug_assert!(dst.to_reg().get_class() == RegClass::I64);
|
debug_assert!(dst.to_reg().get_class() == RegClass::I64);
|
||||||
Inst::MovsxRmR {
|
Inst::MovsxRmR { ext_mode, src, dst }
|
||||||
ext_mode,
|
|
||||||
src,
|
|
||||||
dst,
|
|
||||||
srcloc,
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) fn mov64_m_r(
|
pub(crate) fn mov64_m_r(src: impl Into<SyntheticAmode>, dst: Writable<Reg>) -> Inst {
|
||||||
src: impl Into<SyntheticAmode>,
|
|
||||||
dst: Writable<Reg>,
|
|
||||||
srcloc: Option<SourceLoc>,
|
|
||||||
) -> Inst {
|
|
||||||
debug_assert!(dst.to_reg().get_class() == RegClass::I64);
|
debug_assert!(dst.to_reg().get_class() == RegClass::I64);
|
||||||
Inst::Mov64MR {
|
Inst::Mov64MR {
|
||||||
src: src.into(),
|
src: src.into(),
|
||||||
dst,
|
dst,
|
||||||
srcloc,
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// A convenience function to be able to use a RegMem as the source of a move.
|
/// A convenience function to be able to use a RegMem as the source of a move.
|
||||||
pub(crate) fn mov64_rm_r(src: RegMem, dst: Writable<Reg>, srcloc: Option<SourceLoc>) -> Inst {
|
pub(crate) fn mov64_rm_r(src: RegMem, dst: Writable<Reg>) -> Inst {
|
||||||
src.assert_regclass_is(RegClass::I64);
|
src.assert_regclass_is(RegClass::I64);
|
||||||
match src {
|
match src {
|
||||||
RegMem::Reg { reg } => Self::mov_r_r(true, reg, dst),
|
RegMem::Reg { reg } => Self::mov_r_r(true, reg, dst),
|
||||||
RegMem::Mem { addr } => Self::mov64_m_r(addr, dst, srcloc),
|
RegMem::Mem { addr } => Self::mov64_m_r(addr, dst),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -957,7 +865,6 @@ impl Inst {
|
|||||||
size: u8, // 1, 2, 4 or 8
|
size: u8, // 1, 2, 4 or 8
|
||||||
src: Reg,
|
src: Reg,
|
||||||
dst: impl Into<SyntheticAmode>,
|
dst: impl Into<SyntheticAmode>,
|
||||||
srcloc: Option<SourceLoc>,
|
|
||||||
) -> Inst {
|
) -> Inst {
|
||||||
debug_assert!(size == 8 || size == 4 || size == 2 || size == 1);
|
debug_assert!(size == 8 || size == 4 || size == 2 || size == 1);
|
||||||
debug_assert!(src.get_class() == RegClass::I64);
|
debug_assert!(src.get_class() == RegClass::I64);
|
||||||
@@ -965,7 +872,6 @@ impl Inst {
|
|||||||
size,
|
size,
|
||||||
src,
|
src,
|
||||||
dst: dst.into(),
|
dst: dst.into(),
|
||||||
srcloc,
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1011,9 +917,9 @@ impl Inst {
|
|||||||
Inst::CmpRmiR { size, src, dst }
|
Inst::CmpRmiR { size, src, dst }
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) fn trap(srcloc: SourceLoc, trap_code: TrapCode) -> Inst {
|
pub(crate) fn trap(trap_code: TrapCode) -> Inst {
|
||||||
Inst::Ud2 {
|
Inst::Ud2 {
|
||||||
trap_info: (srcloc, trap_code),
|
trap_code: trap_code,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1053,14 +959,12 @@ impl Inst {
|
|||||||
dest: ExternalName,
|
dest: ExternalName,
|
||||||
uses: Vec<Reg>,
|
uses: Vec<Reg>,
|
||||||
defs: Vec<Writable<Reg>>,
|
defs: Vec<Writable<Reg>>,
|
||||||
loc: SourceLoc,
|
|
||||||
opcode: Opcode,
|
opcode: Opcode,
|
||||||
) -> Inst {
|
) -> Inst {
|
||||||
Inst::CallKnown {
|
Inst::CallKnown {
|
||||||
dest,
|
dest,
|
||||||
uses,
|
uses,
|
||||||
defs,
|
defs,
|
||||||
loc,
|
|
||||||
opcode,
|
opcode,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1069,7 +973,6 @@ impl Inst {
|
|||||||
dest: RegMem,
|
dest: RegMem,
|
||||||
uses: Vec<Reg>,
|
uses: Vec<Reg>,
|
||||||
defs: Vec<Writable<Reg>>,
|
defs: Vec<Writable<Reg>>,
|
||||||
loc: SourceLoc,
|
|
||||||
opcode: Opcode,
|
opcode: Opcode,
|
||||||
) -> Inst {
|
) -> Inst {
|
||||||
dest.assert_regclass_is(RegClass::I64);
|
dest.assert_regclass_is(RegClass::I64);
|
||||||
@@ -1077,7 +980,6 @@ impl Inst {
|
|||||||
dest,
|
dest,
|
||||||
uses,
|
uses,
|
||||||
defs,
|
defs,
|
||||||
loc,
|
|
||||||
opcode,
|
opcode,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1111,12 +1013,8 @@ impl Inst {
|
|||||||
Inst::JmpUnknown { target }
|
Inst::JmpUnknown { target }
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) fn trap_if(cc: CC, trap_code: TrapCode, srcloc: SourceLoc) -> Inst {
|
pub(crate) fn trap_if(cc: CC, trap_code: TrapCode) -> Inst {
|
||||||
Inst::TrapIf {
|
Inst::TrapIf { cc, trap_code }
|
||||||
cc,
|
|
||||||
trap_code,
|
|
||||||
srcloc,
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Choose which instruction to use for loading a register value from memory. For loads smaller
|
/// Choose which instruction to use for loading a register value from memory. For loads smaller
|
||||||
@@ -1127,7 +1025,6 @@ impl Inst {
|
|||||||
from_addr: impl Into<SyntheticAmode>,
|
from_addr: impl Into<SyntheticAmode>,
|
||||||
to_reg: Writable<Reg>,
|
to_reg: Writable<Reg>,
|
||||||
ext_kind: ExtKind,
|
ext_kind: ExtKind,
|
||||||
srcloc: Option<SourceLoc>,
|
|
||||||
) -> Inst {
|
) -> Inst {
|
||||||
let rc = to_reg.to_reg().get_class();
|
let rc = to_reg.to_reg().get_class();
|
||||||
match rc {
|
match rc {
|
||||||
@@ -1143,10 +1040,10 @@ impl Inst {
|
|||||||
// Values smaller than 64 bits must be extended in some way.
|
// Values smaller than 64 bits must be extended in some way.
|
||||||
match ext_kind {
|
match ext_kind {
|
||||||
ExtKind::SignExtend => {
|
ExtKind::SignExtend => {
|
||||||
Inst::movsx_rm_r(ext_mode, RegMem::mem(from_addr), to_reg, srcloc)
|
Inst::movsx_rm_r(ext_mode, RegMem::mem(from_addr), to_reg)
|
||||||
}
|
}
|
||||||
ExtKind::ZeroExtend => {
|
ExtKind::ZeroExtend => {
|
||||||
Inst::movzx_rm_r(ext_mode, RegMem::mem(from_addr), to_reg, srcloc)
|
Inst::movzx_rm_r(ext_mode, RegMem::mem(from_addr), to_reg)
|
||||||
}
|
}
|
||||||
ExtKind::None => panic!(
|
ExtKind::None => panic!(
|
||||||
"expected an extension kind for extension mode: {:?}",
|
"expected an extension kind for extension mode: {:?}",
|
||||||
@@ -1155,7 +1052,7 @@ impl Inst {
|
|||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
// 64-bit values can be moved directly.
|
// 64-bit values can be moved directly.
|
||||||
Inst::mov64_m_r(from_addr, to_reg, srcloc)
|
Inst::mov64_m_r(from_addr, to_reg)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
RegClass::V128 => {
|
RegClass::V128 => {
|
||||||
@@ -1174,18 +1071,13 @@ impl Inst {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Choose which instruction to use for storing a register value to memory.
|
/// Choose which instruction to use for storing a register value to memory.
|
||||||
pub(crate) fn store(
|
pub(crate) fn store(ty: Type, from_reg: Reg, to_addr: impl Into<SyntheticAmode>) -> Inst {
|
||||||
ty: Type,
|
|
||||||
from_reg: Reg,
|
|
||||||
to_addr: impl Into<SyntheticAmode>,
|
|
||||||
srcloc: Option<SourceLoc>,
|
|
||||||
) -> Inst {
|
|
||||||
let rc = from_reg.get_class();
|
let rc = from_reg.get_class();
|
||||||
match rc {
|
match rc {
|
||||||
RegClass::I64 => {
|
RegClass::I64 => {
|
||||||
// Always store the full register, to ensure that the high bits are properly set
|
// Always store the full register, to ensure that the high bits are properly set
|
||||||
// when doing a full reload.
|
// when doing a full reload.
|
||||||
Inst::mov_r_m(8 /* bytes */, from_reg, to_addr, srcloc)
|
Inst::mov_r_m(8 /* bytes */, from_reg, to_addr)
|
||||||
}
|
}
|
||||||
RegClass::V128 => {
|
RegClass::V128 => {
|
||||||
let opcode = match ty {
|
let opcode = match ty {
|
||||||
@@ -1196,7 +1088,7 @@ impl Inst {
|
|||||||
_ if ty.is_vector() && ty.bits() == 128 => SseOpcode::Movdqu,
|
_ if ty.is_vector() && ty.bits() == 128 => SseOpcode::Movdqu,
|
||||||
_ => unimplemented!("unable to store type: {}", ty),
|
_ => unimplemented!("unable to store type: {}", ty),
|
||||||
};
|
};
|
||||||
Inst::xmm_mov_r_m(opcode, from_reg, to_addr, srcloc)
|
Inst::xmm_mov_r_m(opcode, from_reg, to_addr)
|
||||||
}
|
}
|
||||||
_ => panic!("unable to generate store for register class: {:?}", rc),
|
_ => panic!("unable to generate store for register class: {:?}", rc),
|
||||||
}
|
}
|
||||||
@@ -1247,26 +1139,16 @@ impl Inst {
|
|||||||
/// Choose which instruction to use for comparing two values for equality.
|
/// Choose which instruction to use for comparing two values for equality.
|
||||||
pub(crate) fn equals(ty: Type, from: RegMem, to: Writable<Reg>) -> Inst {
|
pub(crate) fn equals(ty: Type, from: RegMem, to: Writable<Reg>) -> Inst {
|
||||||
match ty {
|
match ty {
|
||||||
types::I8X16 | types::B8X16 => Inst::xmm_rm_r(SseOpcode::Pcmpeqb, from, to, None),
|
types::I8X16 | types::B8X16 => Inst::xmm_rm_r(SseOpcode::Pcmpeqb, from, to),
|
||||||
types::I16X8 | types::B16X8 => Inst::xmm_rm_r(SseOpcode::Pcmpeqw, from, to, None),
|
types::I16X8 | types::B16X8 => Inst::xmm_rm_r(SseOpcode::Pcmpeqw, from, to),
|
||||||
types::I32X4 | types::B32X4 => Inst::xmm_rm_r(SseOpcode::Pcmpeqd, from, to, None),
|
types::I32X4 | types::B32X4 => Inst::xmm_rm_r(SseOpcode::Pcmpeqd, from, to),
|
||||||
types::I64X2 | types::B64X2 => Inst::xmm_rm_r(SseOpcode::Pcmpeqq, from, to, None),
|
types::I64X2 | types::B64X2 => Inst::xmm_rm_r(SseOpcode::Pcmpeqq, from, to),
|
||||||
types::F32X4 => Inst::xmm_rm_r_imm(
|
types::F32X4 => {
|
||||||
SseOpcode::Cmpps,
|
Inst::xmm_rm_r_imm(SseOpcode::Cmpps, from, to, FcmpImm::Equal.encode(), false)
|
||||||
from,
|
}
|
||||||
to,
|
types::F64X2 => {
|
||||||
FcmpImm::Equal.encode(),
|
Inst::xmm_rm_r_imm(SseOpcode::Cmppd, from, to, FcmpImm::Equal.encode(), false)
|
||||||
false,
|
}
|
||||||
None,
|
|
||||||
),
|
|
||||||
types::F64X2 => Inst::xmm_rm_r_imm(
|
|
||||||
SseOpcode::Cmppd,
|
|
||||||
from,
|
|
||||||
to,
|
|
||||||
FcmpImm::Equal.encode(),
|
|
||||||
false,
|
|
||||||
None,
|
|
||||||
),
|
|
||||||
_ => unimplemented!("unimplemented type for Inst::equals: {}", ty),
|
_ => unimplemented!("unimplemented type for Inst::equals: {}", ty),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1274,11 +1156,9 @@ impl Inst {
|
|||||||
/// Choose which instruction to use for computing a bitwise AND on two values.
|
/// Choose which instruction to use for computing a bitwise AND on two values.
|
||||||
pub(crate) fn and(ty: Type, from: RegMem, to: Writable<Reg>) -> Inst {
|
pub(crate) fn and(ty: Type, from: RegMem, to: Writable<Reg>) -> Inst {
|
||||||
match ty {
|
match ty {
|
||||||
types::F32X4 => Inst::xmm_rm_r(SseOpcode::Andps, from, to, None),
|
types::F32X4 => Inst::xmm_rm_r(SseOpcode::Andps, from, to),
|
||||||
types::F64X2 => Inst::xmm_rm_r(SseOpcode::Andpd, from, to, None),
|
types::F64X2 => Inst::xmm_rm_r(SseOpcode::Andpd, from, to),
|
||||||
_ if ty.is_vector() && ty.bits() == 128 => {
|
_ if ty.is_vector() && ty.bits() == 128 => Inst::xmm_rm_r(SseOpcode::Pand, from, to),
|
||||||
Inst::xmm_rm_r(SseOpcode::Pand, from, to, None)
|
|
||||||
}
|
|
||||||
_ => unimplemented!("unimplemented type for Inst::and: {}", ty),
|
_ => unimplemented!("unimplemented type for Inst::and: {}", ty),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1286,11 +1166,9 @@ impl Inst {
|
|||||||
/// Choose which instruction to use for computing a bitwise AND NOT on two values.
|
/// Choose which instruction to use for computing a bitwise AND NOT on two values.
|
||||||
pub(crate) fn and_not(ty: Type, from: RegMem, to: Writable<Reg>) -> Inst {
|
pub(crate) fn and_not(ty: Type, from: RegMem, to: Writable<Reg>) -> Inst {
|
||||||
match ty {
|
match ty {
|
||||||
types::F32X4 => Inst::xmm_rm_r(SseOpcode::Andnps, from, to, None),
|
types::F32X4 => Inst::xmm_rm_r(SseOpcode::Andnps, from, to),
|
||||||
types::F64X2 => Inst::xmm_rm_r(SseOpcode::Andnpd, from, to, None),
|
types::F64X2 => Inst::xmm_rm_r(SseOpcode::Andnpd, from, to),
|
||||||
_ if ty.is_vector() && ty.bits() == 128 => {
|
_ if ty.is_vector() && ty.bits() == 128 => Inst::xmm_rm_r(SseOpcode::Pandn, from, to),
|
||||||
Inst::xmm_rm_r(SseOpcode::Pandn, from, to, None)
|
|
||||||
}
|
|
||||||
_ => unimplemented!("unimplemented type for Inst::and_not: {}", ty),
|
_ => unimplemented!("unimplemented type for Inst::and_not: {}", ty),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1298,11 +1176,9 @@ impl Inst {
|
|||||||
/// Choose which instruction to use for computing a bitwise OR on two values.
|
/// Choose which instruction to use for computing a bitwise OR on two values.
|
||||||
pub(crate) fn or(ty: Type, from: RegMem, to: Writable<Reg>) -> Inst {
|
pub(crate) fn or(ty: Type, from: RegMem, to: Writable<Reg>) -> Inst {
|
||||||
match ty {
|
match ty {
|
||||||
types::F32X4 => Inst::xmm_rm_r(SseOpcode::Orps, from, to, None),
|
types::F32X4 => Inst::xmm_rm_r(SseOpcode::Orps, from, to),
|
||||||
types::F64X2 => Inst::xmm_rm_r(SseOpcode::Orpd, from, to, None),
|
types::F64X2 => Inst::xmm_rm_r(SseOpcode::Orpd, from, to),
|
||||||
_ if ty.is_vector() && ty.bits() == 128 => {
|
_ if ty.is_vector() && ty.bits() == 128 => Inst::xmm_rm_r(SseOpcode::Por, from, to),
|
||||||
Inst::xmm_rm_r(SseOpcode::Por, from, to, None)
|
|
||||||
}
|
|
||||||
_ => unimplemented!("unimplemented type for Inst::or: {}", ty),
|
_ => unimplemented!("unimplemented type for Inst::or: {}", ty),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1310,11 +1186,9 @@ impl Inst {
|
|||||||
/// Choose which instruction to use for computing a bitwise XOR on two values.
|
/// Choose which instruction to use for computing a bitwise XOR on two values.
|
||||||
pub(crate) fn xor(ty: Type, from: RegMem, to: Writable<Reg>) -> Inst {
|
pub(crate) fn xor(ty: Type, from: RegMem, to: Writable<Reg>) -> Inst {
|
||||||
match ty {
|
match ty {
|
||||||
types::F32X4 => Inst::xmm_rm_r(SseOpcode::Xorps, from, to, None),
|
types::F32X4 => Inst::xmm_rm_r(SseOpcode::Xorps, from, to),
|
||||||
types::F64X2 => Inst::xmm_rm_r(SseOpcode::Xorpd, from, to, None),
|
types::F64X2 => Inst::xmm_rm_r(SseOpcode::Xorpd, from, to),
|
||||||
_ if ty.is_vector() && ty.bits() == 128 => {
|
_ if ty.is_vector() && ty.bits() == 128 => Inst::xmm_rm_r(SseOpcode::Pxor, from, to),
|
||||||
Inst::xmm_rm_r(SseOpcode::Pxor, from, to, None)
|
|
||||||
}
|
|
||||||
_ => unimplemented!("unimplemented type for Inst::xor: {}", ty),
|
_ => unimplemented!("unimplemented type for Inst::xor: {}", ty),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1839,7 +1713,7 @@ impl PrettyPrint for Inst {
|
|||||||
|
|
||||||
Inst::Hlt => "hlt".into(),
|
Inst::Hlt => "hlt".into(),
|
||||||
|
|
||||||
Inst::Ud2 { trap_info } => format!("ud2 {}", trap_info.1),
|
Inst::Ud2 { trap_code } => format!("ud2 {}", trap_code),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -2627,7 +2501,6 @@ impl MachInst for Inst {
|
|||||||
SseOpcode::Xorps,
|
SseOpcode::Xorps,
|
||||||
RegMem::reg(to_reg.to_reg()),
|
RegMem::reg(to_reg.to_reg()),
|
||||||
to_reg,
|
to_reg,
|
||||||
None,
|
|
||||||
));
|
));
|
||||||
} else {
|
} else {
|
||||||
let tmp = alloc_tmp(RegClass::I64, types::I32);
|
let tmp = alloc_tmp(RegClass::I64, types::I32);
|
||||||
@@ -2646,7 +2519,6 @@ impl MachInst for Inst {
|
|||||||
SseOpcode::Xorpd,
|
SseOpcode::Xorpd,
|
||||||
RegMem::reg(to_reg.to_reg()),
|
RegMem::reg(to_reg.to_reg()),
|
||||||
to_reg,
|
to_reg,
|
||||||
None,
|
|
||||||
));
|
));
|
||||||
} else {
|
} else {
|
||||||
let tmp = alloc_tmp(RegClass::I64, types::I64);
|
let tmp = alloc_tmp(RegClass::I64, types::I64);
|
||||||
@@ -2717,6 +2589,8 @@ pub struct EmitState {
|
|||||||
pub(crate) nominal_sp_to_fp: i64,
|
pub(crate) nominal_sp_to_fp: i64,
|
||||||
/// Safepoint stack map for upcoming instruction, as provided to `pre_safepoint()`.
|
/// Safepoint stack map for upcoming instruction, as provided to `pre_safepoint()`.
|
||||||
stack_map: Option<StackMap>,
|
stack_map: Option<StackMap>,
|
||||||
|
/// Current source location.
|
||||||
|
cur_srcloc: SourceLoc,
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Constant state used during emissions of a sequence of instructions.
|
/// Constant state used during emissions of a sequence of instructions.
|
||||||
@@ -2757,12 +2631,17 @@ impl MachInstEmitState<Inst> for EmitState {
|
|||||||
virtual_sp_offset: 0,
|
virtual_sp_offset: 0,
|
||||||
nominal_sp_to_fp: abi.frame_size() as i64,
|
nominal_sp_to_fp: abi.frame_size() as i64,
|
||||||
stack_map: None,
|
stack_map: None,
|
||||||
|
cur_srcloc: SourceLoc::default(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn pre_safepoint(&mut self, stack_map: StackMap) {
|
fn pre_safepoint(&mut self, stack_map: StackMap) {
|
||||||
self.stack_map = Some(stack_map);
|
self.stack_map = Some(stack_map);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn pre_sourceloc(&mut self, srcloc: SourceLoc) {
|
||||||
|
self.cur_srcloc = srcloc;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl EmitState {
|
impl EmitState {
|
||||||
@@ -2773,6 +2652,10 @@ impl EmitState {
|
|||||||
fn clear_post_insn(&mut self) {
|
fn clear_post_insn(&mut self) {
|
||||||
self.stack_map = None;
|
self.stack_map = None;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn cur_srcloc(&self) -> SourceLoc {
|
||||||
|
self.cur_srcloc
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// A label-use (internal relocation) in generated code.
|
/// A label-use (internal relocation) in generated code.
|
||||||
|
|||||||
File diff suppressed because it is too large
Load Diff
@@ -111,7 +111,7 @@
|
|||||||
use super::abi::*;
|
use super::abi::*;
|
||||||
use crate::binemit::StackMap;
|
use crate::binemit::StackMap;
|
||||||
use crate::ir::types::*;
|
use crate::ir::types::*;
|
||||||
use crate::ir::{ArgumentExtension, SourceLoc, StackSlot};
|
use crate::ir::{ArgumentExtension, StackSlot};
|
||||||
use crate::machinst::*;
|
use crate::machinst::*;
|
||||||
use crate::settings;
|
use crate::settings;
|
||||||
use crate::CodegenResult;
|
use crate::CodegenResult;
|
||||||
@@ -350,7 +350,6 @@ pub trait ABIMachineSpec {
|
|||||||
dest: &CallDest,
|
dest: &CallDest,
|
||||||
uses: Vec<Reg>,
|
uses: Vec<Reg>,
|
||||||
defs: Vec<Writable<Reg>>,
|
defs: Vec<Writable<Reg>>,
|
||||||
loc: SourceLoc,
|
|
||||||
opcode: ir::Opcode,
|
opcode: ir::Opcode,
|
||||||
tmp: Writable<Reg>,
|
tmp: Writable<Reg>,
|
||||||
callee_conv: isa::CallConv,
|
callee_conv: isa::CallConv,
|
||||||
@@ -1102,8 +1101,6 @@ pub struct ABICallerImpl<M: ABIMachineSpec> {
|
|||||||
defs: Vec<Writable<Reg>>,
|
defs: Vec<Writable<Reg>>,
|
||||||
/// Call destination.
|
/// Call destination.
|
||||||
dest: CallDest,
|
dest: CallDest,
|
||||||
/// Location of callsite.
|
|
||||||
loc: ir::SourceLoc,
|
|
||||||
/// Actual call opcode; used to distinguish various types of calls.
|
/// Actual call opcode; used to distinguish various types of calls.
|
||||||
opcode: ir::Opcode,
|
opcode: ir::Opcode,
|
||||||
/// Caller's calling convention.
|
/// Caller's calling convention.
|
||||||
@@ -1127,7 +1124,6 @@ impl<M: ABIMachineSpec> ABICallerImpl<M> {
|
|||||||
sig: &ir::Signature,
|
sig: &ir::Signature,
|
||||||
extname: &ir::ExternalName,
|
extname: &ir::ExternalName,
|
||||||
dist: RelocDistance,
|
dist: RelocDistance,
|
||||||
loc: ir::SourceLoc,
|
|
||||||
caller_conv: isa::CallConv,
|
caller_conv: isa::CallConv,
|
||||||
) -> CodegenResult<ABICallerImpl<M>> {
|
) -> CodegenResult<ABICallerImpl<M>> {
|
||||||
let sig = ABISig::from_func_sig::<M>(sig)?;
|
let sig = ABISig::from_func_sig::<M>(sig)?;
|
||||||
@@ -1137,7 +1133,6 @@ impl<M: ABIMachineSpec> ABICallerImpl<M> {
|
|||||||
uses,
|
uses,
|
||||||
defs,
|
defs,
|
||||||
dest: CallDest::ExtName(extname.clone(), dist),
|
dest: CallDest::ExtName(extname.clone(), dist),
|
||||||
loc,
|
|
||||||
opcode: ir::Opcode::Call,
|
opcode: ir::Opcode::Call,
|
||||||
caller_conv,
|
caller_conv,
|
||||||
_mach: PhantomData,
|
_mach: PhantomData,
|
||||||
@@ -1149,7 +1144,6 @@ impl<M: ABIMachineSpec> ABICallerImpl<M> {
|
|||||||
pub fn from_ptr(
|
pub fn from_ptr(
|
||||||
sig: &ir::Signature,
|
sig: &ir::Signature,
|
||||||
ptr: Reg,
|
ptr: Reg,
|
||||||
loc: ir::SourceLoc,
|
|
||||||
opcode: ir::Opcode,
|
opcode: ir::Opcode,
|
||||||
caller_conv: isa::CallConv,
|
caller_conv: isa::CallConv,
|
||||||
) -> CodegenResult<ABICallerImpl<M>> {
|
) -> CodegenResult<ABICallerImpl<M>> {
|
||||||
@@ -1160,7 +1154,6 @@ impl<M: ABIMachineSpec> ABICallerImpl<M> {
|
|||||||
uses,
|
uses,
|
||||||
defs,
|
defs,
|
||||||
dest: CallDest::Reg(ptr),
|
dest: CallDest::Reg(ptr),
|
||||||
loc,
|
|
||||||
opcode,
|
opcode,
|
||||||
caller_conv,
|
caller_conv,
|
||||||
_mach: PhantomData,
|
_mach: PhantomData,
|
||||||
@@ -1311,7 +1304,6 @@ impl<M: ABIMachineSpec> ABICaller for ABICallerImpl<M> {
|
|||||||
&self.dest,
|
&self.dest,
|
||||||
uses,
|
uses,
|
||||||
defs,
|
defs,
|
||||||
self.loc,
|
|
||||||
self.opcode,
|
self.opcode,
|
||||||
tmp,
|
tmp,
|
||||||
self.sig.call_conv,
|
self.sig.call_conv,
|
||||||
|
|||||||
@@ -1535,7 +1535,7 @@ mod test {
|
|||||||
|
|
||||||
buf.bind_label(label(1));
|
buf.bind_label(label(1));
|
||||||
let inst = Inst::Udf {
|
let inst = Inst::Udf {
|
||||||
trap_info: (SourceLoc::default(), TrapCode::Interrupt),
|
trap_code: TrapCode::Interrupt,
|
||||||
};
|
};
|
||||||
inst.emit(&mut buf, &info, &mut state);
|
inst.emit(&mut buf, &info, &mut state);
|
||||||
|
|
||||||
@@ -1551,7 +1551,7 @@ mod test {
|
|||||||
let mut state = Default::default();
|
let mut state = Default::default();
|
||||||
let inst = Inst::TrapIf {
|
let inst = Inst::TrapIf {
|
||||||
kind: CondBrKind::NotZero(xreg(0)),
|
kind: CondBrKind::NotZero(xreg(0)),
|
||||||
trap_info: (SourceLoc::default(), TrapCode::Interrupt),
|
trap_code: TrapCode::Interrupt,
|
||||||
};
|
};
|
||||||
inst.emit(&mut buf2, &info, &mut state);
|
inst.emit(&mut buf2, &info, &mut state);
|
||||||
let inst = Inst::Nop4;
|
let inst = Inst::Nop4;
|
||||||
|
|||||||
@@ -98,7 +98,7 @@
|
|||||||
|
|
||||||
use crate::binemit::{CodeInfo, CodeOffset, StackMap};
|
use crate::binemit::{CodeInfo, CodeOffset, StackMap};
|
||||||
use crate::ir::condcodes::IntCC;
|
use crate::ir::condcodes::IntCC;
|
||||||
use crate::ir::{Function, Type};
|
use crate::ir::{Function, SourceLoc, Type};
|
||||||
use crate::isa::unwind::input as unwind_input;
|
use crate::isa::unwind::input as unwind_input;
|
||||||
use crate::result::CodegenResult;
|
use crate::result::CodegenResult;
|
||||||
use crate::settings::Flags;
|
use crate::settings::Flags;
|
||||||
@@ -302,6 +302,9 @@ pub trait MachInstEmitState<I: MachInst>: Default + Clone + Debug {
|
|||||||
/// Update the emission state before emitting an instruction that is a
|
/// Update the emission state before emitting an instruction that is a
|
||||||
/// safepoint.
|
/// safepoint.
|
||||||
fn pre_safepoint(&mut self, _stack_map: StackMap) {}
|
fn pre_safepoint(&mut self, _stack_map: StackMap) {}
|
||||||
|
/// Update the emission state to indicate instructions are associated with a
|
||||||
|
/// particular SourceLoc.
|
||||||
|
fn pre_sourceloc(&mut self, _srcloc: SourceLoc) {}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// The result of a `MachBackend::compile_function()` call. Contains machine
|
/// The result of a `MachBackend::compile_function()` call. Contains machine
|
||||||
|
|||||||
@@ -509,6 +509,7 @@ impl<I: VCodeInst> VCode<I> {
|
|||||||
buffer.start_srcloc(srcloc);
|
buffer.start_srcloc(srcloc);
|
||||||
cur_srcloc = Some(srcloc);
|
cur_srcloc = Some(srcloc);
|
||||||
}
|
}
|
||||||
|
state.pre_sourceloc(cur_srcloc.unwrap_or(SourceLoc::default()));
|
||||||
|
|
||||||
if safepoint_idx < self.safepoint_insns.len()
|
if safepoint_idx < self.safepoint_insns.len()
|
||||||
&& self.safepoint_insns[safepoint_idx] == iix
|
&& self.safepoint_insns[safepoint_idx] == iix
|
||||||
|
|||||||
Reference in New Issue
Block a user