Expand x64 OperandSize to support 8 and 16-bit operands.
This is in preparation for refactoring all x64::Inst arms to use OperandSize. Current uses of OperandSize fall into two categories: 1. XMM operations which require 32/64 bit operands 2. Immediates which only care about 64-bit or not. Adds assertions to existing Inst constructors to check that they are passed valid sizes. This change also removes the implicit widening of 1 and 2 byte values to 4 bytes. from_bytes() is only used by category 2, so removing this behavior will not change any visible behavior. Overall this change should be a no-op.
This commit is contained in:
committed by
Andrew Brown
parent
7aecd6dac9
commit
b12d41bfe9
@@ -1323,6 +1323,8 @@ impl RoundImm {
|
|||||||
/// An operand's size in bits.
|
/// An operand's size in bits.
|
||||||
#[derive(Clone, Copy, PartialEq)]
|
#[derive(Clone, Copy, PartialEq)]
|
||||||
pub enum OperandSize {
|
pub enum OperandSize {
|
||||||
|
Size8,
|
||||||
|
Size16,
|
||||||
Size32,
|
Size32,
|
||||||
Size64,
|
Size64,
|
||||||
}
|
}
|
||||||
@@ -1330,24 +1332,35 @@ pub enum OperandSize {
|
|||||||
impl OperandSize {
|
impl OperandSize {
|
||||||
pub(crate) fn from_bytes(num_bytes: u32) -> Self {
|
pub(crate) fn from_bytes(num_bytes: u32) -> Self {
|
||||||
match num_bytes {
|
match num_bytes {
|
||||||
1 | 2 | 4 => OperandSize::Size32,
|
1 => OperandSize::Size8,
|
||||||
|
2 => OperandSize::Size16,
|
||||||
|
4 => OperandSize::Size32,
|
||||||
8 => OperandSize::Size64,
|
8 => OperandSize::Size64,
|
||||||
_ => unreachable!(),
|
_ => unreachable!(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Check that the value of self is one of the allowed sizes.
|
||||||
|
pub(crate) fn is_size(&self, sizes: &[Self]) -> bool {
|
||||||
|
for val in sizes.iter() {
|
||||||
|
if *self == *val {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
false
|
||||||
|
}
|
||||||
|
|
||||||
pub(crate) fn to_bytes(&self) -> u8 {
|
pub(crate) fn to_bytes(&self) -> u8 {
|
||||||
match self {
|
match self {
|
||||||
|
Self::Size8 => 1,
|
||||||
|
Self::Size16 => 2,
|
||||||
Self::Size32 => 4,
|
Self::Size32 => 4,
|
||||||
Self::Size64 => 8,
|
Self::Size64 => 8,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) fn to_bits(&self) -> u8 {
|
pub(crate) fn to_bits(&self) -> u8 {
|
||||||
match self {
|
self.to_bytes() * 8
|
||||||
Self::Size32 => 32,
|
|
||||||
Self::Size64 => 64,
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -2063,6 +2063,7 @@ pub(crate) fn emit(
|
|||||||
SseOpcode::Maxsd
|
SseOpcode::Maxsd
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
|
_ => unreachable!(),
|
||||||
};
|
};
|
||||||
|
|
||||||
let inst = Inst::xmm_cmp_rm_r(cmp_op, RegMem::reg(*lhs), rhs_dst.to_reg());
|
let inst = Inst::xmm_cmp_rm_r(cmp_op, RegMem::reg(*lhs), rhs_dst.to_reg());
|
||||||
@@ -2224,6 +2225,7 @@ pub(crate) fn emit(
|
|||||||
let rex = match dst_size {
|
let rex = match dst_size {
|
||||||
OperandSize::Size32 => RexFlags::clear_w(),
|
OperandSize::Size32 => RexFlags::clear_w(),
|
||||||
OperandSize::Size64 => RexFlags::set_w(),
|
OperandSize::Size64 => RexFlags::set_w(),
|
||||||
|
_ => unreachable!(),
|
||||||
};
|
};
|
||||||
|
|
||||||
let (src, dst) = if dst_first {
|
let (src, dst) = if dst_first {
|
||||||
@@ -2252,6 +2254,7 @@ pub(crate) fn emit(
|
|||||||
let rex = match *src_size {
|
let rex = match *src_size {
|
||||||
OperandSize::Size32 => RexFlags::clear_w(),
|
OperandSize::Size32 => RexFlags::clear_w(),
|
||||||
OperandSize::Size64 => RexFlags::set_w(),
|
OperandSize::Size64 => RexFlags::set_w(),
|
||||||
|
_ => unreachable!(),
|
||||||
};
|
};
|
||||||
match src_e {
|
match src_e {
|
||||||
RegMem::Reg { reg: reg_e } => {
|
RegMem::Reg { reg: reg_e } => {
|
||||||
@@ -2450,6 +2453,7 @@ pub(crate) fn emit(
|
|||||||
let (cast_op, cmp_op, trunc_op) = match src_size {
|
let (cast_op, cmp_op, trunc_op) = match src_size {
|
||||||
OperandSize::Size64 => (SseOpcode::Movq, SseOpcode::Ucomisd, SseOpcode::Cvttsd2si),
|
OperandSize::Size64 => (SseOpcode::Movq, SseOpcode::Ucomisd, SseOpcode::Cvttsd2si),
|
||||||
OperandSize::Size32 => (SseOpcode::Movd, SseOpcode::Ucomiss, SseOpcode::Cvttss2si),
|
OperandSize::Size32 => (SseOpcode::Movd, SseOpcode::Ucomiss, SseOpcode::Cvttss2si),
|
||||||
|
_ => unreachable!(),
|
||||||
};
|
};
|
||||||
|
|
||||||
let done = sink.get_label();
|
let done = sink.get_label();
|
||||||
@@ -2542,6 +2546,7 @@ pub(crate) fn emit(
|
|||||||
let inst = Inst::imm(OperandSize::Size64, cst.bits(), *tmp_gpr);
|
let inst = Inst::imm(OperandSize::Size64, cst.bits(), *tmp_gpr);
|
||||||
inst.emit(sink, info, state);
|
inst.emit(sink, info, state);
|
||||||
}
|
}
|
||||||
|
_ => unreachable!(),
|
||||||
}
|
}
|
||||||
|
|
||||||
let inst =
|
let inst =
|
||||||
@@ -2622,28 +2627,28 @@ pub(crate) fn emit(
|
|||||||
|
|
||||||
assert_ne!(tmp_xmm, src, "tmp_xmm clobbers src!");
|
assert_ne!(tmp_xmm, src, "tmp_xmm clobbers src!");
|
||||||
|
|
||||||
let (sub_op, cast_op, cmp_op, trunc_op) = if *src_size == OperandSize::Size64 {
|
let (sub_op, cast_op, cmp_op, trunc_op) = match src_size {
|
||||||
(
|
OperandSize::Size32 => (
|
||||||
SseOpcode::Subsd,
|
|
||||||
SseOpcode::Movq,
|
|
||||||
SseOpcode::Ucomisd,
|
|
||||||
SseOpcode::Cvttsd2si,
|
|
||||||
)
|
|
||||||
} else {
|
|
||||||
(
|
|
||||||
SseOpcode::Subss,
|
SseOpcode::Subss,
|
||||||
SseOpcode::Movd,
|
SseOpcode::Movd,
|
||||||
SseOpcode::Ucomiss,
|
SseOpcode::Ucomiss,
|
||||||
SseOpcode::Cvttss2si,
|
SseOpcode::Cvttss2si,
|
||||||
)
|
),
|
||||||
|
OperandSize::Size64 => (
|
||||||
|
SseOpcode::Subsd,
|
||||||
|
SseOpcode::Movq,
|
||||||
|
SseOpcode::Ucomisd,
|
||||||
|
SseOpcode::Cvttsd2si,
|
||||||
|
),
|
||||||
|
_ => unreachable!(),
|
||||||
};
|
};
|
||||||
|
|
||||||
let done = sink.get_label();
|
let done = sink.get_label();
|
||||||
|
|
||||||
let cst = if *src_size == OperandSize::Size64 {
|
let cst = match src_size {
|
||||||
Ieee64::pow2(dst_size.to_bits() - 1).bits()
|
OperandSize::Size32 => Ieee32::pow2(dst_size.to_bits() - 1).bits() as u64,
|
||||||
} else {
|
OperandSize::Size64 => Ieee64::pow2(dst_size.to_bits() - 1).bits(),
|
||||||
Ieee32::pow2(dst_size.to_bits() - 1).bits() as u64
|
_ => unreachable!(),
|
||||||
};
|
};
|
||||||
|
|
||||||
let inst = Inst::imm(*src_size, cst, *tmp_gpr);
|
let inst = Inst::imm(*src_size, cst, *tmp_gpr);
|
||||||
|
|||||||
@@ -717,6 +717,7 @@ impl Inst {
|
|||||||
) -> Inst {
|
) -> Inst {
|
||||||
debug_assert!(src.get_class() == RegClass::V128);
|
debug_assert!(src.get_class() == RegClass::V128);
|
||||||
debug_assert!(dst.to_reg().get_class() == RegClass::I64);
|
debug_assert!(dst.to_reg().get_class() == RegClass::I64);
|
||||||
|
debug_assert!(dst_size.is_size(&[OperandSize::Size32, OperandSize::Size64]));
|
||||||
Inst::XmmToGpr {
|
Inst::XmmToGpr {
|
||||||
op,
|
op,
|
||||||
src,
|
src,
|
||||||
@@ -732,6 +733,7 @@ impl Inst {
|
|||||||
dst: Writable<Reg>,
|
dst: Writable<Reg>,
|
||||||
) -> Inst {
|
) -> Inst {
|
||||||
src.assert_regclass_is(RegClass::I64);
|
src.assert_regclass_is(RegClass::I64);
|
||||||
|
debug_assert!(src_size.is_size(&[OperandSize::Size32, OperandSize::Size64]));
|
||||||
debug_assert!(dst.to_reg().get_class() == RegClass::V128);
|
debug_assert!(dst.to_reg().get_class() == RegClass::V128);
|
||||||
Inst::GprToXmm {
|
Inst::GprToXmm {
|
||||||
op,
|
op,
|
||||||
@@ -776,6 +778,8 @@ impl Inst {
|
|||||||
tmp_gpr: Writable<Reg>,
|
tmp_gpr: Writable<Reg>,
|
||||||
tmp_xmm: Writable<Reg>,
|
tmp_xmm: Writable<Reg>,
|
||||||
) -> Inst {
|
) -> Inst {
|
||||||
|
debug_assert!(src_size.is_size(&[OperandSize::Size32, OperandSize::Size64]));
|
||||||
|
debug_assert!(dst_size.is_size(&[OperandSize::Size32, OperandSize::Size64]));
|
||||||
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);
|
||||||
debug_assert!(tmp_gpr.to_reg().get_class() == RegClass::I64);
|
debug_assert!(tmp_gpr.to_reg().get_class() == RegClass::I64);
|
||||||
@@ -800,6 +804,8 @@ impl Inst {
|
|||||||
tmp_gpr: Writable<Reg>,
|
tmp_gpr: Writable<Reg>,
|
||||||
tmp_xmm: Writable<Reg>,
|
tmp_xmm: Writable<Reg>,
|
||||||
) -> Inst {
|
) -> Inst {
|
||||||
|
debug_assert!(src_size.is_size(&[OperandSize::Size32, OperandSize::Size64]));
|
||||||
|
debug_assert!(dst_size.is_size(&[OperandSize::Size32, OperandSize::Size64]));
|
||||||
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);
|
||||||
debug_assert!(tmp_gpr.to_reg().get_class() == RegClass::I64);
|
debug_assert!(tmp_gpr.to_reg().get_class() == RegClass::I64);
|
||||||
@@ -821,6 +827,7 @@ impl Inst {
|
|||||||
lhs: Reg,
|
lhs: Reg,
|
||||||
rhs_dst: Writable<Reg>,
|
rhs_dst: Writable<Reg>,
|
||||||
) -> Inst {
|
) -> Inst {
|
||||||
|
debug_assert!(size.is_size(&[OperandSize::Size32, OperandSize::Size64]));
|
||||||
debug_assert_eq!(lhs.get_class(), RegClass::V128);
|
debug_assert_eq!(lhs.get_class(), RegClass::V128);
|
||||||
debug_assert_eq!(rhs_dst.to_reg().get_class(), RegClass::V128);
|
debug_assert_eq!(rhs_dst.to_reg().get_class(), RegClass::V128);
|
||||||
Inst::XmmMinMaxSeq {
|
Inst::XmmMinMaxSeq {
|
||||||
@@ -1416,11 +1423,7 @@ impl PrettyPrint for Inst {
|
|||||||
} else {
|
} else {
|
||||||
"xmm max seq ".to_string()
|
"xmm max seq ".to_string()
|
||||||
},
|
},
|
||||||
match size {
|
format!("f{}", size.to_bits())
|
||||||
OperandSize::Size32 => "f32",
|
|
||||||
OperandSize::Size64 => "f64",
|
|
||||||
}
|
|
||||||
.into()
|
|
||||||
),
|
),
|
||||||
show_ireg_sized(*lhs, mb_rru, 8),
|
show_ireg_sized(*lhs, mb_rru, 8),
|
||||||
show_ireg_sized(rhs_dst.to_reg(), mb_rru, 8),
|
show_ireg_sized(rhs_dst.to_reg(), mb_rru, 8),
|
||||||
@@ -1459,10 +1462,7 @@ impl PrettyPrint for Inst {
|
|||||||
dst,
|
dst,
|
||||||
dst_size,
|
dst_size,
|
||||||
} => {
|
} => {
|
||||||
let dst_size = match dst_size {
|
let dst_size = dst_size.to_bytes();
|
||||||
OperandSize::Size32 => 4,
|
|
||||||
OperandSize::Size64 => 8,
|
|
||||||
};
|
|
||||||
format!(
|
format!(
|
||||||
"{} {}, {}",
|
"{} {}, {}",
|
||||||
ljustify(op.to_string()),
|
ljustify(op.to_string()),
|
||||||
@@ -1512,16 +1512,8 @@ impl PrettyPrint for Inst {
|
|||||||
"{} {}, {}",
|
"{} {}, {}",
|
||||||
ljustify(format!(
|
ljustify(format!(
|
||||||
"cvt_float{}_to_sint{}_seq",
|
"cvt_float{}_to_sint{}_seq",
|
||||||
if *src_size == OperandSize::Size64 {
|
src_size.to_bits(),
|
||||||
"64"
|
dst_size.to_bits()
|
||||||
} else {
|
|
||||||
"32"
|
|
||||||
},
|
|
||||||
if *dst_size == OperandSize::Size64 {
|
|
||||||
"64"
|
|
||||||
} else {
|
|
||||||
"32"
|
|
||||||
}
|
|
||||||
)),
|
)),
|
||||||
show_ireg_sized(src.to_reg(), mb_rru, 8),
|
show_ireg_sized(src.to_reg(), mb_rru, 8),
|
||||||
show_ireg_sized(dst.to_reg(), mb_rru, dst_size.to_bytes()),
|
show_ireg_sized(dst.to_reg(), mb_rru, dst_size.to_bytes()),
|
||||||
@@ -1537,16 +1529,8 @@ impl PrettyPrint for Inst {
|
|||||||
"{} {}, {}",
|
"{} {}, {}",
|
||||||
ljustify(format!(
|
ljustify(format!(
|
||||||
"cvt_float{}_to_uint{}_seq",
|
"cvt_float{}_to_uint{}_seq",
|
||||||
if *src_size == OperandSize::Size64 {
|
src_size.to_bits(),
|
||||||
"64"
|
dst_size.to_bits()
|
||||||
} else {
|
|
||||||
"32"
|
|
||||||
},
|
|
||||||
if *dst_size == OperandSize::Size64 {
|
|
||||||
"64"
|
|
||||||
} else {
|
|
||||||
"32"
|
|
||||||
}
|
|
||||||
)),
|
)),
|
||||||
show_ireg_sized(src.to_reg(), mb_rru, 8),
|
show_ireg_sized(src.to_reg(), mb_rru, 8),
|
||||||
show_ireg_sized(dst.to_reg(), mb_rru, dst_size.to_bytes()),
|
show_ireg_sized(dst.to_reg(), mb_rru, dst_size.to_bytes()),
|
||||||
|
|||||||
Reference in New Issue
Block a user