[machinst x64]: calculate extension modes in one place

This commit is contained in:
Andrew Brown
2020-09-28 12:54:53 -07:00
parent eb650f6fe0
commit 4484a00ea5
3 changed files with 31 additions and 36 deletions

View File

@@ -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 {

View File

@@ -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,

View File

@@ -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));
} }
} }