machinst: allow passing constant information to the instruction emitter;
A new associated type Info is added to MachInstEmit, which is the immutable counterpart to State. It can't easily be constructed from an ABICallee, since it would require adding an associated type to the latter, and making so leaks the associated type in a lot of places in the code base and makes the code harder to read. Instead, the EmitInfo state can simply be passed to the `Vcode::emit` function directly.
This commit is contained in:
@@ -390,7 +390,7 @@ fn emit_simm(sink: &mut MachBuffer<Inst>, size: u8, simm32: u32) {
|
||||
/// A small helper to generate a signed conversion instruction.
|
||||
fn emit_signed_cvt(
|
||||
sink: &mut MachBuffer<Inst>,
|
||||
flags: &settings::Flags,
|
||||
info: &EmitInfo,
|
||||
state: &mut EmitState,
|
||||
src: Reg,
|
||||
dst: Writable<Reg>,
|
||||
@@ -404,7 +404,7 @@ fn emit_signed_cvt(
|
||||
SseOpcode::Cvtsi2ss
|
||||
};
|
||||
let inst = Inst::gpr_to_xmm(op, RegMem::reg(src), OperandSize::Size64, dst);
|
||||
inst.emit(sink, flags, state);
|
||||
inst.emit(sink, info, state);
|
||||
}
|
||||
|
||||
/// Emits a one way conditional jump if CC is set (true).
|
||||
@@ -472,7 +472,7 @@ fn one_way_jmp(sink: &mut MachBuffer<Inst>, cc: CC, label: MachLabel) {
|
||||
pub(crate) fn emit(
|
||||
inst: &Inst,
|
||||
sink: &mut MachBuffer<Inst>,
|
||||
flags: &settings::Flags,
|
||||
info: &EmitInfo,
|
||||
state: &mut EmitState,
|
||||
) {
|
||||
match inst {
|
||||
@@ -767,19 +767,19 @@ pub(crate) fn emit(
|
||||
// idiv %divisor
|
||||
//
|
||||
// $done:
|
||||
debug_assert!(flags.avoid_div_traps());
|
||||
debug_assert!(info.flags().avoid_div_traps());
|
||||
|
||||
// Check if the divisor is zero, first.
|
||||
let inst = Inst::cmp_rmi_r(*size, RegMemImm::imm(0), divisor.to_reg());
|
||||
inst.emit(sink, flags, state);
|
||||
inst.emit(sink, info, state);
|
||||
|
||||
let inst = Inst::trap_if(CC::Z, TrapCode::IntegerDivisionByZero, *loc);
|
||||
inst.emit(sink, flags, state);
|
||||
inst.emit(sink, info, state);
|
||||
|
||||
let (do_op, done_label) = if kind.is_signed() {
|
||||
// Now check if the divisor is -1.
|
||||
let inst = Inst::cmp_rmi_r(*size, RegMemImm::imm(0xffffffff), divisor.to_reg());
|
||||
inst.emit(sink, flags, state);
|
||||
inst.emit(sink, info, state);
|
||||
|
||||
let do_op = sink.get_label();
|
||||
|
||||
@@ -796,10 +796,10 @@ pub(crate) fn emit(
|
||||
0,
|
||||
Writable::from_reg(regs::rdx()),
|
||||
);
|
||||
inst.emit(sink, flags, state);
|
||||
inst.emit(sink, info, state);
|
||||
|
||||
let inst = Inst::jmp_known(BranchTarget::Label(done_label));
|
||||
inst.emit(sink, flags, state);
|
||||
inst.emit(sink, info, state);
|
||||
|
||||
(Some(do_op), Some(done_label))
|
||||
} else {
|
||||
@@ -808,18 +808,18 @@ pub(crate) fn emit(
|
||||
let tmp = tmp.expect("temporary for i64 sdiv");
|
||||
|
||||
let inst = Inst::imm(OperandSize::Size64, 0x8000000000000000, tmp);
|
||||
inst.emit(sink, flags, state);
|
||||
inst.emit(sink, info, state);
|
||||
|
||||
let inst = Inst::cmp_rmi_r(8, RegMemImm::reg(tmp.to_reg()), regs::rax());
|
||||
inst.emit(sink, flags, state);
|
||||
inst.emit(sink, info, state);
|
||||
} else {
|
||||
let inst = Inst::cmp_rmi_r(*size, RegMemImm::imm(0x80000000), regs::rax());
|
||||
inst.emit(sink, flags, state);
|
||||
inst.emit(sink, info, state);
|
||||
}
|
||||
|
||||
// If not equal, jump over the trap.
|
||||
let inst = Inst::trap_if(CC::Z, TrapCode::IntegerOverflow, *loc);
|
||||
inst.emit(sink, flags, state);
|
||||
inst.emit(sink, info, state);
|
||||
|
||||
(Some(do_op), None)
|
||||
}
|
||||
@@ -840,15 +840,15 @@ pub(crate) fn emit(
|
||||
if kind.is_signed() {
|
||||
// sign-extend the sign-bit of rax into rdx, for signed opcodes.
|
||||
let inst = Inst::sign_extend_data(*size);
|
||||
inst.emit(sink, flags, state);
|
||||
inst.emit(sink, info, state);
|
||||
} else {
|
||||
// zero for unsigned opcodes.
|
||||
let inst = Inst::imm(OperandSize::Size64, 0, Writable::from_reg(regs::rdx()));
|
||||
inst.emit(sink, flags, state);
|
||||
inst.emit(sink, info, state);
|
||||
}
|
||||
|
||||
let inst = Inst::div(*size, kind.is_signed(), RegMem::reg(divisor.to_reg()), *loc);
|
||||
inst.emit(sink, flags, state);
|
||||
inst.emit(sink, info, state);
|
||||
|
||||
// Lowering takes care of moving the result back into the right register, see comment
|
||||
// there.
|
||||
@@ -1382,7 +1382,7 @@ pub(crate) fn emit(
|
||||
SseOpcode::Movss
|
||||
};
|
||||
let inst = Inst::xmm_unary_rm_r(op, src.clone(), *dst);
|
||||
inst.emit(sink, flags, state);
|
||||
inst.emit(sink, info, state);
|
||||
|
||||
sink.bind_label(next);
|
||||
}
|
||||
@@ -1623,7 +1623,7 @@ pub(crate) fn emit(
|
||||
|
||||
// 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);
|
||||
inst.emit(sink, flags, state);
|
||||
inst.emit(sink, info, state);
|
||||
|
||||
// Load base address of jump table.
|
||||
let start_of_jumptable = sink.get_label();
|
||||
@@ -1631,7 +1631,7 @@ pub(crate) fn emit(
|
||||
Amode::rip_relative(BranchTarget::Label(start_of_jumptable)),
|
||||
*tmp1,
|
||||
);
|
||||
inst.emit(sink, flags, state);
|
||||
inst.emit(sink, info, state);
|
||||
|
||||
// Load value out of the jump table. It's a relative offset to the target block, so it
|
||||
// might be negative; use a sign-extension.
|
||||
@@ -1641,7 +1641,7 @@ pub(crate) fn emit(
|
||||
*tmp2,
|
||||
None,
|
||||
);
|
||||
inst.emit(sink, flags, state);
|
||||
inst.emit(sink, info, state);
|
||||
|
||||
// Add base of jump table to jump-table-sourced block offset.
|
||||
let inst = Inst::alu_rmi_r(
|
||||
@@ -1650,11 +1650,11 @@ pub(crate) fn emit(
|
||||
RegMemImm::reg(tmp2.to_reg()),
|
||||
*tmp1,
|
||||
);
|
||||
inst.emit(sink, flags, state);
|
||||
inst.emit(sink, info, state);
|
||||
|
||||
// Branch to computed address.
|
||||
let inst = Inst::jmp_unknown(RegMem::reg(tmp1.to_reg()));
|
||||
inst.emit(sink, flags, state);
|
||||
inst.emit(sink, info, state);
|
||||
|
||||
// Emit jump table (table of 32-bit offsets).
|
||||
sink.bind_label(start_of_jumptable);
|
||||
@@ -1683,7 +1683,7 @@ pub(crate) fn emit(
|
||||
|
||||
// Trap!
|
||||
let inst = Inst::trap(*srcloc, *trap_code);
|
||||
inst.emit(sink, flags, state);
|
||||
inst.emit(sink, info, state);
|
||||
|
||||
sink.bind_label(else_label);
|
||||
}
|
||||
@@ -1890,7 +1890,7 @@ pub(crate) fn emit(
|
||||
};
|
||||
|
||||
let inst = Inst::xmm_cmp_rm_r(cmp_op, RegMem::reg(*lhs), rhs_dst.to_reg());
|
||||
inst.emit(sink, flags, state);
|
||||
inst.emit(sink, info, state);
|
||||
|
||||
one_way_jmp(sink, CC::NZ, do_min_max);
|
||||
one_way_jmp(sink, CC::P, propagate_nan);
|
||||
@@ -1900,23 +1900,23 @@ pub(crate) fn emit(
|
||||
// case, and are no-ops otherwise.
|
||||
let op = if *is_min { or_op } else { and_op };
|
||||
let inst = Inst::xmm_rm_r(op, RegMem::reg(*lhs), *rhs_dst);
|
||||
inst.emit(sink, flags, state);
|
||||
inst.emit(sink, info, state);
|
||||
|
||||
let inst = Inst::jmp_known(BranchTarget::Label(done));
|
||||
inst.emit(sink, flags, state);
|
||||
inst.emit(sink, info, state);
|
||||
|
||||
// x86's min/max are not symmetric; if either operand is a NaN, they return the
|
||||
// read-only operand: perform an addition between the two operands, which has the
|
||||
// desired NaN propagation effects.
|
||||
sink.bind_label(propagate_nan);
|
||||
let inst = Inst::xmm_rm_r(add_op, RegMem::reg(*lhs), *rhs_dst);
|
||||
inst.emit(sink, flags, state);
|
||||
inst.emit(sink, info, state);
|
||||
|
||||
one_way_jmp(sink, CC::P, done);
|
||||
|
||||
sink.bind_label(do_min_max);
|
||||
let inst = Inst::xmm_rm_r(min_max_op, RegMem::reg(*lhs), *rhs_dst);
|
||||
inst.emit(sink, flags, state);
|
||||
inst.emit(sink, info, state);
|
||||
|
||||
sink.bind_label(done);
|
||||
}
|
||||
@@ -1986,13 +1986,13 @@ pub(crate) fn emit(
|
||||
let constant_start_label = sink.get_label();
|
||||
let load_offset = Amode::rip_relative(BranchTarget::Label(constant_start_label));
|
||||
let load = Inst::load(*ty, load_offset, *dst, ExtKind::None, None);
|
||||
load.emit(sink, flags, state);
|
||||
load.emit(sink, info, state);
|
||||
|
||||
// Jump over the constant.
|
||||
let constant_end_label = sink.get_label();
|
||||
let continue_at_offset = BranchTarget::Label(constant_end_label);
|
||||
let jump = Inst::jmp_known(continue_at_offset);
|
||||
jump.emit(sink, flags, state);
|
||||
jump.emit(sink, info, state);
|
||||
|
||||
// Emit the constant.
|
||||
sink.bind_label(constant_start_label);
|
||||
@@ -2151,30 +2151,30 @@ pub(crate) fn emit(
|
||||
// thing.
|
||||
// TODO use tst src, src here.
|
||||
let inst = Inst::cmp_rmi_r(8, RegMemImm::imm(0), src.to_reg());
|
||||
inst.emit(sink, flags, state);
|
||||
inst.emit(sink, info, state);
|
||||
|
||||
one_way_jmp(sink, CC::L, handle_negative);
|
||||
|
||||
// Handle a positive int64, which is the "easy" case: a signed conversion will do the
|
||||
// right thing.
|
||||
emit_signed_cvt(sink, flags, state, src.to_reg(), *dst, *to_f64);
|
||||
emit_signed_cvt(sink, info, state, src.to_reg(), *dst, *to_f64);
|
||||
|
||||
let inst = Inst::jmp_known(BranchTarget::Label(done));
|
||||
inst.emit(sink, flags, state);
|
||||
inst.emit(sink, info, state);
|
||||
|
||||
sink.bind_label(handle_negative);
|
||||
|
||||
// Divide x by two to get it in range for the signed conversion, keep the LSB, and
|
||||
// scale it back up on the FP side.
|
||||
let inst = Inst::gen_move(*tmp_gpr1, src.to_reg(), types::I64);
|
||||
inst.emit(sink, flags, state);
|
||||
inst.emit(sink, info, state);
|
||||
|
||||
// tmp_gpr1 := src >> 1
|
||||
let inst = Inst::shift_r(8, ShiftKind::ShiftRightLogical, Some(1), *tmp_gpr1);
|
||||
inst.emit(sink, flags, state);
|
||||
inst.emit(sink, info, state);
|
||||
|
||||
let inst = Inst::gen_move(*tmp_gpr2, src.to_reg(), types::I64);
|
||||
inst.emit(sink, flags, state);
|
||||
inst.emit(sink, info, state);
|
||||
|
||||
let inst = Inst::alu_rmi_r(
|
||||
true, /* 64bits */
|
||||
@@ -2182,7 +2182,7 @@ pub(crate) fn emit(
|
||||
RegMemImm::imm(1),
|
||||
*tmp_gpr2,
|
||||
);
|
||||
inst.emit(sink, flags, state);
|
||||
inst.emit(sink, info, state);
|
||||
|
||||
let inst = Inst::alu_rmi_r(
|
||||
true, /* 64bits */
|
||||
@@ -2190,9 +2190,9 @@ pub(crate) fn emit(
|
||||
RegMemImm::reg(tmp_gpr1.to_reg()),
|
||||
*tmp_gpr2,
|
||||
);
|
||||
inst.emit(sink, flags, state);
|
||||
inst.emit(sink, info, state);
|
||||
|
||||
emit_signed_cvt(sink, flags, state, tmp_gpr2.to_reg(), *dst, *to_f64);
|
||||
emit_signed_cvt(sink, info, state, tmp_gpr2.to_reg(), *dst, *to_f64);
|
||||
|
||||
let add_op = if *to_f64 {
|
||||
SseOpcode::Addsd
|
||||
@@ -2200,7 +2200,7 @@ pub(crate) fn emit(
|
||||
SseOpcode::Addss
|
||||
};
|
||||
let inst = Inst::xmm_rm_r(add_op, RegMem::reg(dst.to_reg()), *dst);
|
||||
inst.emit(sink, flags, state);
|
||||
inst.emit(sink, info, state);
|
||||
|
||||
sink.bind_label(done);
|
||||
}
|
||||
@@ -2273,18 +2273,18 @@ pub(crate) fn emit(
|
||||
|
||||
// The truncation.
|
||||
let inst = Inst::xmm_to_gpr(trunc_op, src, *dst, *dst_size);
|
||||
inst.emit(sink, flags, state);
|
||||
inst.emit(sink, info, state);
|
||||
|
||||
// Compare against 1, in case of overflow the dst operand was INT_MIN.
|
||||
let inst = Inst::cmp_rmi_r(dst_size.to_bytes(), RegMemImm::imm(1), dst.to_reg());
|
||||
inst.emit(sink, flags, state);
|
||||
inst.emit(sink, info, state);
|
||||
|
||||
one_way_jmp(sink, CC::NO, done); // no overflow => done
|
||||
|
||||
// Check for NaN.
|
||||
|
||||
let inst = Inst::xmm_cmp_rm_r(cmp_op, RegMem::reg(src), src);
|
||||
inst.emit(sink, flags, state);
|
||||
inst.emit(sink, info, state);
|
||||
|
||||
one_way_jmp(sink, CC::NP, not_nan); // go to not_nan if not a NaN
|
||||
|
||||
@@ -2296,10 +2296,10 @@ pub(crate) fn emit(
|
||||
RegMemImm::reg(dst.to_reg()),
|
||||
*dst,
|
||||
);
|
||||
inst.emit(sink, flags, state);
|
||||
inst.emit(sink, info, state);
|
||||
|
||||
let inst = Inst::jmp_known(BranchTarget::Label(done));
|
||||
inst.emit(sink, flags, state);
|
||||
inst.emit(sink, info, state);
|
||||
|
||||
sink.bind_label(not_nan);
|
||||
|
||||
@@ -2308,10 +2308,10 @@ pub(crate) fn emit(
|
||||
// Zero out tmp_xmm.
|
||||
let inst =
|
||||
Inst::xmm_rm_r(SseOpcode::Xorpd, RegMem::reg(tmp_xmm.to_reg()), *tmp_xmm);
|
||||
inst.emit(sink, flags, state);
|
||||
inst.emit(sink, info, state);
|
||||
|
||||
let inst = Inst::xmm_cmp_rm_r(cmp_op, RegMem::reg(src), tmp_xmm.to_reg());
|
||||
inst.emit(sink, flags, state);
|
||||
inst.emit(sink, info, state);
|
||||
|
||||
// Jump if >= to done.
|
||||
one_way_jmp(sink, CC::NB, done);
|
||||
@@ -2319,16 +2319,16 @@ pub(crate) fn emit(
|
||||
// Otherwise, put INT_MAX.
|
||||
if *dst_size == OperandSize::Size64 {
|
||||
let inst = Inst::imm(OperandSize::Size64, 0x7fffffffffffffff, *dst);
|
||||
inst.emit(sink, flags, state);
|
||||
inst.emit(sink, info, state);
|
||||
} else {
|
||||
let inst = Inst::imm(OperandSize::Size32, 0x7fffffff, *dst);
|
||||
inst.emit(sink, flags, state);
|
||||
inst.emit(sink, info, state);
|
||||
}
|
||||
} else {
|
||||
let check_positive = sink.get_label();
|
||||
|
||||
let inst = Inst::trap(*srcloc, TrapCode::BadConversionToInteger);
|
||||
inst.emit(sink, flags, state);
|
||||
inst.emit(sink, info, state);
|
||||
|
||||
// Check if INT_MIN was the correct result: determine the smallest floating point
|
||||
// number that would convert to INT_MIN, put it in a temporary register, and compare
|
||||
@@ -2344,7 +2344,7 @@ pub(crate) fn emit(
|
||||
OperandSize::Size32 => {
|
||||
let cst = Ieee32::pow2(output_bits - 1).neg().bits();
|
||||
let inst = Inst::imm(OperandSize::Size32, cst as u64, *tmp_gpr);
|
||||
inst.emit(sink, flags, state);
|
||||
inst.emit(sink, info, state);
|
||||
}
|
||||
OperandSize::Size64 => {
|
||||
// An f64 can represent `i32::min_value() - 1` exactly with precision to spare,
|
||||
@@ -2356,22 +2356,22 @@ pub(crate) fn emit(
|
||||
Ieee64::pow2(output_bits - 1).neg()
|
||||
};
|
||||
let inst = Inst::imm(OperandSize::Size64, cst.bits(), *tmp_gpr);
|
||||
inst.emit(sink, flags, state);
|
||||
inst.emit(sink, info, state);
|
||||
}
|
||||
}
|
||||
|
||||
let inst =
|
||||
Inst::gpr_to_xmm(cast_op, RegMem::reg(tmp_gpr.to_reg()), *src_size, *tmp_xmm);
|
||||
inst.emit(sink, flags, state);
|
||||
inst.emit(sink, info, state);
|
||||
|
||||
let inst = Inst::xmm_cmp_rm_r(cmp_op, RegMem::reg(tmp_xmm.to_reg()), src);
|
||||
inst.emit(sink, flags, state);
|
||||
inst.emit(sink, info, state);
|
||||
|
||||
// jump over trap if src >= or > threshold
|
||||
one_way_jmp(sink, no_overflow_cc, check_positive);
|
||||
|
||||
let inst = Inst::trap(*srcloc, TrapCode::IntegerOverflow);
|
||||
inst.emit(sink, flags, state);
|
||||
inst.emit(sink, info, state);
|
||||
|
||||
// If positive, it was a real overflow.
|
||||
|
||||
@@ -2380,15 +2380,15 @@ pub(crate) fn emit(
|
||||
// Zero out the tmp_xmm register.
|
||||
let inst =
|
||||
Inst::xmm_rm_r(SseOpcode::Xorpd, RegMem::reg(tmp_xmm.to_reg()), *tmp_xmm);
|
||||
inst.emit(sink, flags, state);
|
||||
inst.emit(sink, info, state);
|
||||
|
||||
let inst = Inst::xmm_cmp_rm_r(cmp_op, RegMem::reg(src), tmp_xmm.to_reg());
|
||||
inst.emit(sink, flags, state);
|
||||
inst.emit(sink, info, state);
|
||||
|
||||
one_way_jmp(sink, CC::NB, done); // jump over trap if 0 >= src
|
||||
|
||||
let inst = Inst::trap(*srcloc, TrapCode::IntegerOverflow);
|
||||
inst.emit(sink, flags, state);
|
||||
inst.emit(sink, info, state);
|
||||
}
|
||||
|
||||
sink.bind_label(done);
|
||||
@@ -2464,14 +2464,14 @@ pub(crate) fn emit(
|
||||
};
|
||||
|
||||
let inst = Inst::imm(*src_size, cst, *tmp_gpr);
|
||||
inst.emit(sink, flags, state);
|
||||
inst.emit(sink, info, state);
|
||||
|
||||
let inst =
|
||||
Inst::gpr_to_xmm(cast_op, RegMem::reg(tmp_gpr.to_reg()), *src_size, *tmp_xmm);
|
||||
inst.emit(sink, flags, state);
|
||||
inst.emit(sink, info, state);
|
||||
|
||||
let inst = Inst::xmm_cmp_rm_r(cmp_op, RegMem::reg(tmp_xmm.to_reg()), src.to_reg());
|
||||
inst.emit(sink, flags, state);
|
||||
inst.emit(sink, info, state);
|
||||
|
||||
let handle_large = sink.get_label();
|
||||
one_way_jmp(sink, CC::NB, handle_large); // jump to handle_large if src >= large_threshold
|
||||
@@ -2487,14 +2487,14 @@ pub(crate) fn emit(
|
||||
RegMemImm::reg(dst.to_reg()),
|
||||
*dst,
|
||||
);
|
||||
inst.emit(sink, flags, state);
|
||||
inst.emit(sink, info, state);
|
||||
|
||||
let inst = Inst::jmp_known(BranchTarget::Label(done));
|
||||
inst.emit(sink, flags, state);
|
||||
inst.emit(sink, info, state);
|
||||
} else {
|
||||
// Trap.
|
||||
let inst = Inst::trap(*srcloc, TrapCode::BadConversionToInteger);
|
||||
inst.emit(sink, flags, state);
|
||||
inst.emit(sink, info, state);
|
||||
}
|
||||
|
||||
sink.bind_label(not_nan);
|
||||
@@ -2503,10 +2503,10 @@ pub(crate) fn emit(
|
||||
// overflow.
|
||||
|
||||
let inst = Inst::xmm_to_gpr(trunc_op, src.to_reg(), *dst, *dst_size);
|
||||
inst.emit(sink, flags, state);
|
||||
inst.emit(sink, info, state);
|
||||
|
||||
let inst = Inst::cmp_rmi_r(dst_size.to_bytes(), RegMemImm::imm(0), dst.to_reg());
|
||||
inst.emit(sink, flags, state);
|
||||
inst.emit(sink, info, state);
|
||||
|
||||
one_way_jmp(sink, CC::NL, done); // if dst >= 0, jump to done
|
||||
|
||||
@@ -2519,14 +2519,14 @@ pub(crate) fn emit(
|
||||
RegMemImm::reg(dst.to_reg()),
|
||||
*dst,
|
||||
);
|
||||
inst.emit(sink, flags, state);
|
||||
inst.emit(sink, info, state);
|
||||
|
||||
let inst = Inst::jmp_known(BranchTarget::Label(done));
|
||||
inst.emit(sink, flags, state);
|
||||
inst.emit(sink, info, state);
|
||||
} else {
|
||||
// Trap.
|
||||
let inst = Inst::trap(*srcloc, TrapCode::IntegerOverflow);
|
||||
inst.emit(sink, flags, state);
|
||||
inst.emit(sink, info, state);
|
||||
}
|
||||
|
||||
// Now handle large inputs.
|
||||
@@ -2534,13 +2534,13 @@ pub(crate) fn emit(
|
||||
sink.bind_label(handle_large);
|
||||
|
||||
let inst = Inst::xmm_rm_r(sub_op, RegMem::reg(tmp_xmm.to_reg()), *src);
|
||||
inst.emit(sink, flags, state);
|
||||
inst.emit(sink, info, state);
|
||||
|
||||
let inst = Inst::xmm_to_gpr(trunc_op, src.to_reg(), *dst, *dst_size);
|
||||
inst.emit(sink, flags, state);
|
||||
inst.emit(sink, info, state);
|
||||
|
||||
let inst = Inst::cmp_rmi_r(dst_size.to_bytes(), RegMemImm::imm(0), dst.to_reg());
|
||||
inst.emit(sink, flags, state);
|
||||
inst.emit(sink, info, state);
|
||||
|
||||
let next_is_large = sink.get_label();
|
||||
one_way_jmp(sink, CC::NL, next_is_large); // if dst >= 0, jump to next_is_large
|
||||
@@ -2557,20 +2557,20 @@ pub(crate) fn emit(
|
||||
},
|
||||
*dst,
|
||||
);
|
||||
inst.emit(sink, flags, state);
|
||||
inst.emit(sink, info, state);
|
||||
|
||||
let inst = Inst::jmp_known(BranchTarget::Label(done));
|
||||
inst.emit(sink, flags, state);
|
||||
inst.emit(sink, info, state);
|
||||
} else {
|
||||
let inst = Inst::trap(*srcloc, TrapCode::IntegerOverflow);
|
||||
inst.emit(sink, flags, state);
|
||||
inst.emit(sink, info, state);
|
||||
}
|
||||
|
||||
sink.bind_label(next_is_large);
|
||||
|
||||
if *dst_size == OperandSize::Size64 {
|
||||
let inst = Inst::imm(OperandSize::Size64, 1 << 63, *tmp_gpr);
|
||||
inst.emit(sink, flags, state);
|
||||
inst.emit(sink, info, state);
|
||||
|
||||
let inst = Inst::alu_rmi_r(
|
||||
true,
|
||||
@@ -2578,11 +2578,11 @@ pub(crate) fn emit(
|
||||
RegMemImm::reg(tmp_gpr.to_reg()),
|
||||
*dst,
|
||||
);
|
||||
inst.emit(sink, flags, state);
|
||||
inst.emit(sink, info, state);
|
||||
} else {
|
||||
let inst =
|
||||
Inst::alu_rmi_r(false, AluRmiROpcode::Add, RegMemImm::imm(1 << 31), *dst);
|
||||
inst.emit(sink, flags, state);
|
||||
inst.emit(sink, info, state);
|
||||
}
|
||||
|
||||
sink.bind_label(done);
|
||||
@@ -2600,7 +2600,7 @@ pub(crate) fn emit(
|
||||
sink.put1(0x48 | ((enc_dst >> 3) & 1));
|
||||
sink.put1(0xB8 | (enc_dst & 7));
|
||||
sink.add_reloc(*srcloc, Reloc::Abs8, name, *offset);
|
||||
if flags.emit_all_ones_funcaddrs() {
|
||||
if info.flags().emit_all_ones_funcaddrs() {
|
||||
sink.put8(u64::max_value());
|
||||
} else {
|
||||
sink.put8(0);
|
||||
@@ -2664,14 +2664,14 @@ pub(crate) fn emit(
|
||||
// mov{zbq,zwq,zlq,q} (%r9), %rax
|
||||
// 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);
|
||||
i1.emit(sink, flags, state);
|
||||
i1.emit(sink, info, state);
|
||||
|
||||
// again:
|
||||
sink.bind_label(again_label);
|
||||
|
||||
// movq %rax, %r11
|
||||
let i2 = Inst::mov_r_r(true, rax, r11_w);
|
||||
i2.emit(sink, flags, state);
|
||||
i2.emit(sink, info, state);
|
||||
|
||||
// opq %r10, %r11
|
||||
let r10_rmi = RegMemImm::reg(r10);
|
||||
@@ -2688,7 +2688,7 @@ pub(crate) fn emit(
|
||||
};
|
||||
Inst::alu_rmi_r(true, alu_op, r10_rmi, r11_w)
|
||||
};
|
||||
i3.emit(sink, flags, state);
|
||||
i3.emit(sink, info, state);
|
||||
|
||||
// lock cmpxchg{b,w,l,q} %r11, (%r9)
|
||||
// No need to call `add_trap` here, since the `i4` emit will do that.
|
||||
@@ -2698,7 +2698,7 @@ pub(crate) fn emit(
|
||||
dst: amode.into(),
|
||||
srcloc: *srcloc,
|
||||
};
|
||||
i4.emit(sink, flags, state);
|
||||
i4.emit(sink, info, state);
|
||||
|
||||
// jnz again
|
||||
one_way_jmp(sink, CC::NZ, again_label);
|
||||
|
||||
Reference in New Issue
Block a user