[machinst x64]: calculate extension modes in one place
This commit is contained in:
@@ -226,12 +226,8 @@ impl ABIMachineSpec for X64ABIMachineSpec {
|
|||||||
from_bits: u8,
|
from_bits: u8,
|
||||||
to_bits: u8,
|
to_bits: u8,
|
||||||
) -> Self::I {
|
) -> Self::I {
|
||||||
let ext_mode = match from_bits {
|
let ext_mode = ExtMode::new(from_bits as u16, to_bits as u16)
|
||||||
1 | 8 => ExtMode::BQ,
|
.expect(&format!("invalid extension: {} -> {}", from_bits, to_bits));
|
||||||
16 => ExtMode::WQ,
|
|
||||||
32 => ExtMode::LQ,
|
|
||||||
_ => panic!("Bad extension: {} bits to {} bits", 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, None)
|
||||||
} else {
|
} else {
|
||||||
|
|||||||
@@ -760,6 +760,19 @@ pub enum ExtMode {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl ExtMode {
|
impl ExtMode {
|
||||||
|
/// Calculate the `ExtMode` from passed bit lengths of the from/to types.
|
||||||
|
pub(crate) fn new(from_bits: u16, to_bits: u16) -> Option<ExtMode> {
|
||||||
|
match (from_bits, to_bits) {
|
||||||
|
(1, 8) | (1, 16) | (1, 32) | (8, 16) | (8, 32) => Some(ExtMode::BL),
|
||||||
|
(1, 64) | (8, 64) => Some(ExtMode::BQ),
|
||||||
|
(16, 32) => Some(ExtMode::WL),
|
||||||
|
(16, 64) => Some(ExtMode::WQ),
|
||||||
|
(32, 64) => Some(ExtMode::LQ),
|
||||||
|
_ => None,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Return the source register size in bytes.
|
||||||
pub(crate) fn src_size(&self) -> u8 {
|
pub(crate) fn src_size(&self) -> u8 {
|
||||||
match self {
|
match self {
|
||||||
ExtMode::BL | ExtMode::BQ => 1,
|
ExtMode::BL | ExtMode::BQ => 1,
|
||||||
@@ -767,6 +780,8 @@ impl ExtMode {
|
|||||||
ExtMode::LQ => 4,
|
ExtMode::LQ => 4,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Return the destination register size in bytes.
|
||||||
pub(crate) fn dst_size(&self) -> u8 {
|
pub(crate) fn dst_size(&self) -> u8 {
|
||||||
match self {
|
match self {
|
||||||
ExtMode::BL | ExtMode::WL => 4,
|
ExtMode::BL | ExtMode::WL => 4,
|
||||||
|
|||||||
@@ -131,12 +131,7 @@ fn extend_input_to_reg(ctx: Ctx, spec: InsnInput, ext_spec: ExtSpec) -> Reg {
|
|||||||
let ext_mode = match (input_size, requested_size) {
|
let ext_mode = match (input_size, requested_size) {
|
||||||
(a, b) if a == b => return put_input_in_reg(ctx, spec),
|
(a, b) if a == b => return put_input_in_reg(ctx, spec),
|
||||||
(1, 8) => return put_input_in_reg(ctx, spec),
|
(1, 8) => return put_input_in_reg(ctx, spec),
|
||||||
(a, 16) | (a, 32) if a == 1 || a == 8 => ExtMode::BL,
|
(a, b) => ExtMode::new(a, b).expect(&format!("invalid extension: {} -> {}", a, b)),
|
||||||
(a, 64) if a == 1 || a == 8 => ExtMode::BQ,
|
|
||||||
(16, 32) => ExtMode::WL,
|
|
||||||
(16, 64) => ExtMode::WQ,
|
|
||||||
(32, 64) => ExtMode::LQ,
|
|
||||||
_ => unreachable!("extend {} -> {}", input_size, requested_size),
|
|
||||||
};
|
};
|
||||||
|
|
||||||
let src = input_to_reg_mem(ctx, spec);
|
let src = input_to_reg_mem(ctx, spec);
|
||||||
@@ -1266,18 +1261,13 @@ fn lower_insn_to_regs<C: LowerCtx<I = Inst>>(
|
|||||||
let src = input_to_reg_mem(ctx, inputs[0]);
|
let src = input_to_reg_mem(ctx, inputs[0]);
|
||||||
let dst = get_output_reg(ctx, outputs[0]);
|
let dst = get_output_reg(ctx, outputs[0]);
|
||||||
|
|
||||||
let ext_mode = match (src_ty.bits(), dst_ty.bits()) {
|
let ext_mode = ExtMode::new(src_ty.bits(), dst_ty.bits());
|
||||||
(1, 8) | (1, 16) | (1, 32) | (8, 16) | (8, 32) => Some(ExtMode::BL),
|
assert!(
|
||||||
(1, 64) | (8, 64) => Some(ExtMode::BQ),
|
(src_ty.bits() < dst_ty.bits() && ext_mode.is_some()) || ext_mode.is_none(),
|
||||||
(16, 32) => Some(ExtMode::WL),
|
"unexpected extension: {} -> {}",
|
||||||
(16, 64) => Some(ExtMode::WQ),
|
src_ty,
|
||||||
(32, 64) => Some(ExtMode::LQ),
|
dst_ty
|
||||||
(x, y) if x >= y => None,
|
);
|
||||||
_ => unreachable!(
|
|
||||||
"unexpected extension kind from {:?} to {:?}",
|
|
||||||
src_ty, dst_ty
|
|
||||||
),
|
|
||||||
};
|
|
||||||
|
|
||||||
// All of these other opcodes are simply a move from a zero-extended source. Here
|
// All of these other opcodes are simply a move from a zero-extended source. Here
|
||||||
// is why this works, in each case:
|
// is why this works, in each case:
|
||||||
@@ -2015,12 +2005,7 @@ fn lower_insn_to_regs<C: LowerCtx<I = Inst>>(
|
|||||||
_ => unimplemented!(),
|
_ => unimplemented!(),
|
||||||
};
|
};
|
||||||
|
|
||||||
let ext_mode = match elem_ty.bytes() {
|
let ext_mode = ExtMode::new(elem_ty.bits(), 64);
|
||||||
1 => Some(ExtMode::BQ),
|
|
||||||
2 => Some(ExtMode::WQ),
|
|
||||||
4 => Some(ExtMode::LQ),
|
|
||||||
_ => None,
|
|
||||||
};
|
|
||||||
|
|
||||||
let sign_extend = match op {
|
let sign_extend = match op {
|
||||||
Opcode::Sload8
|
Opcode::Sload8
|
||||||
@@ -2275,12 +2260,11 @@ fn lower_insn_to_regs<C: LowerCtx<I = Inst>>(
|
|||||||
if ty_access == types::I64 {
|
if ty_access == types::I64 {
|
||||||
ctx.emit(Inst::mov64_rm_r(rm, data, srcloc));
|
ctx.emit(Inst::mov64_rm_r(rm, data, srcloc));
|
||||||
} else {
|
} else {
|
||||||
let ext_mode = match ty_access {
|
let ext_mode = ExtMode::new(ty_access.bits(), 64).expect(&format!(
|
||||||
types::I8 => ExtMode::BQ,
|
"invalid extension during AtomicLoad: {} -> {}",
|
||||||
types::I16 => ExtMode::WQ,
|
ty_access.bits(),
|
||||||
types::I32 => ExtMode::LQ,
|
64
|
||||||
_ => panic!("lowering AtomicLoad: invalid type"),
|
));
|
||||||
};
|
|
||||||
ctx.emit(Inst::movzx_rm_r(ext_mode, rm, data, srcloc));
|
ctx.emit(Inst::movzx_rm_r(ext_mode, rm, data, srcloc));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user