From 3306408100e9fa24289e36e6a610756bc919c200 Mon Sep 17 00:00:00 2001 From: Kasey Carrothers Date: Sat, 30 Jan 2021 18:39:10 -0800 Subject: [PATCH] Refactor x64::Inst to use OperandSize instead of u8s. TODO: some types take a 'is_64_bit' bool. Those are left unchanged for now. --- cranelift/codegen/src/isa/x64/abi.rs | 4 +- cranelift/codegen/src/isa/x64/inst/args.rs | 10 +- cranelift/codegen/src/isa/x64/inst/emit.rs | 142 +++-- .../codegen/src/isa/x64/inst/emit_tests.rs | 570 ++++++++++++------ cranelift/codegen/src/isa/x64/inst/mod.rs | 153 +++-- cranelift/codegen/src/isa/x64/lower.rs | 359 +++++++---- 6 files changed, 780 insertions(+), 458 deletions(-) diff --git a/cranelift/codegen/src/isa/x64/abi.rs b/cranelift/codegen/src/isa/x64/abi.rs index d4f7d5c60c..98f3c17c3b 100644 --- a/cranelift/codegen/src/isa/x64/abi.rs +++ b/cranelift/codegen/src/isa/x64/abi.rs @@ -339,7 +339,7 @@ impl ABIMachineSpec for X64ABIMachineSpec { fn gen_stack_lower_bound_trap(limit_reg: Reg) -> SmallInstVec { smallvec![ - Inst::cmp_rmi_r(/* bytes = */ 8, RegMemImm::reg(regs::rsp()), limit_reg), + Inst::cmp_rmi_r(OperandSize::Size64, RegMemImm::reg(regs::rsp()), limit_reg), Inst::TrapIf { // NBE == "> unsigned"; args above are reversed; this tests limit_reg > rsp. cc: CC::NBE, @@ -474,7 +474,7 @@ impl ABIMachineSpec for X64ABIMachineSpec { match r_reg.get_class() { RegClass::I64 => { insts.push(Inst::mov_r_m( - /* bytes = */ 8, + OperandSize::Size64, r_reg.to_reg(), Amode::imm_reg(cur_offset, regs::rsp()), )); diff --git a/cranelift/codegen/src/isa/x64/inst/args.rs b/cranelift/codegen/src/isa/x64/inst/args.rs index 51732ff0d2..5c16498db0 100644 --- a/cranelift/codegen/src/isa/x64/inst/args.rs +++ b/cranelift/codegen/src/isa/x64/inst/args.rs @@ -3,7 +3,7 @@ use super::regs::{self, show_ireg_sized}; use super::EmitState; use crate::ir::condcodes::{FloatCC, IntCC}; -use crate::ir::MemFlags; +use crate::ir::{MemFlags, Type}; use crate::isa::x64::inst::Inst; use crate::machinst::*; use regalloc::{ @@ -1336,10 +1336,16 @@ impl OperandSize { 2 => OperandSize::Size16, 4 => OperandSize::Size32, 8 => OperandSize::Size64, - _ => unreachable!(), + _ => unreachable!("Invalid OperandSize: {}", num_bytes), } } + // Computes the OperandSize for a given type. + // For vectors, the OperandSize of the lanes is returned. + pub(crate) fn from_ty(ty: Type) -> Self { + Self::from_bytes(ty.lane_type().bytes()) + } + // 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() { diff --git a/cranelift/codegen/src/isa/x64/inst/emit.rs b/cranelift/codegen/src/isa/x64/inst/emit.rs index b82b7909a0..02570ef249 100644 --- a/cranelift/codegen/src/isa/x64/inst/emit.rs +++ b/cranelift/codegen/src/isa/x64/inst/emit.rs @@ -676,18 +676,18 @@ pub(crate) fn emit( Inst::UnaryRmR { size, op, src, dst } => { let rex_flags = match size { - 2 | 4 => RexFlags::clear_w(), - 8 => RexFlags::set_w(), + OperandSize::Size16 | OperandSize::Size32 => RexFlags::clear_w(), + OperandSize::Size64 => RexFlags::set_w(), _ => unreachable!(), }; use UnaryRmROpcode::*; let prefix = match size { - 2 => match op { + OperandSize::Size16 => match op { Bsr | Bsf => LegacyPrefixes::_66, Lzcnt | Tzcnt | Popcnt => LegacyPrefixes::_66F3, }, - 4 | 8 => match op { + OperandSize::Size32 | OperandSize::Size64 => match op { Bsr | Bsf => LegacyPrefixes::None, Lzcnt | Tzcnt | Popcnt => LegacyPrefixes::_F3, }, @@ -732,15 +732,14 @@ pub(crate) fn emit( Inst::Not { size, src } => { let src = int_reg_enc(src.to_reg()); let (opcode, prefix, rex_flags) = match size { - 1 => ( + OperandSize::Size8 => ( 0xF6, LegacyPrefixes::None, *RexFlags::clear_w().always_emit_if_8bit_needed(src), ), - 2 => (0xF7, LegacyPrefixes::_66, RexFlags::clear_w()), - 4 => (0xF7, LegacyPrefixes::None, RexFlags::clear_w()), - 8 => (0xF7, LegacyPrefixes::None, RexFlags::set_w()), - _ => unreachable!("{}", size), + OperandSize::Size16 => (0xF7, LegacyPrefixes::_66, RexFlags::clear_w()), + OperandSize::Size32 => (0xF7, LegacyPrefixes::None, RexFlags::clear_w()), + OperandSize::Size64 => (0xF7, LegacyPrefixes::None, RexFlags::set_w()), }; let subopcode = 2; @@ -750,15 +749,14 @@ pub(crate) fn emit( Inst::Neg { size, src } => { let src = int_reg_enc(src.to_reg()); let (opcode, prefix, rex_flags) = match size { - 1 => ( + OperandSize::Size8 => ( 0xF6, LegacyPrefixes::None, *RexFlags::clear_w().always_emit_if_8bit_needed(src), ), - 2 => (0xF7, LegacyPrefixes::_66, RexFlags::clear_w()), - 4 => (0xF7, LegacyPrefixes::None, RexFlags::clear_w()), - 8 => (0xF7, LegacyPrefixes::None, RexFlags::set_w()), - _ => unreachable!("{}", size), + OperandSize::Size16 => (0xF7, LegacyPrefixes::_66, RexFlags::clear_w()), + OperandSize::Size32 => (0xF7, LegacyPrefixes::None, RexFlags::clear_w()), + OperandSize::Size64 => (0xF7, LegacyPrefixes::None, RexFlags::set_w()), }; let subopcode = 3; @@ -771,11 +769,10 @@ pub(crate) fn emit( divisor, } => { let (opcode, prefix, mut rex_flags) = match size { - 1 => (0xF6, LegacyPrefixes::None, RexFlags::clear_w()), - 2 => (0xF7, LegacyPrefixes::_66, RexFlags::clear_w()), - 4 => (0xF7, LegacyPrefixes::None, RexFlags::clear_w()), - 8 => (0xF7, LegacyPrefixes::None, RexFlags::set_w()), - _ => unreachable!("{}", size), + OperandSize::Size8 => (0xF6, LegacyPrefixes::None, RexFlags::clear_w()), + OperandSize::Size16 => (0xF7, LegacyPrefixes::_66, RexFlags::clear_w()), + OperandSize::Size32 => (0xF7, LegacyPrefixes::None, RexFlags::clear_w()), + OperandSize::Size64 => (0xF7, LegacyPrefixes::None, RexFlags::set_w()), }; let loc = state.cur_srcloc(); @@ -785,7 +782,7 @@ pub(crate) fn emit( match divisor { RegMem::Reg { reg } => { let src = int_reg_enc(*reg); - if *size == 1 { + if *size == OperandSize::Size8 { rex_flags.always_emit_if_8bit_needed(src); } emit_std_enc_enc(sink, prefix, opcode, 1, subopcode, src, rex_flags) @@ -801,9 +798,9 @@ pub(crate) fn emit( Inst::MulHi { size, signed, rhs } => { let (prefix, rex_flags) = match size { - 2 => (LegacyPrefixes::_66, RexFlags::clear_w()), - 4 => (LegacyPrefixes::None, RexFlags::clear_w()), - 8 => (LegacyPrefixes::None, RexFlags::set_w()), + OperandSize::Size16 => (LegacyPrefixes::_66, RexFlags::clear_w()), + OperandSize::Size32 => (LegacyPrefixes::None, RexFlags::clear_w()), + OperandSize::Size64 => (LegacyPrefixes::None, RexFlags::set_w()), _ => unreachable!(), }; @@ -823,20 +820,19 @@ pub(crate) fn emit( } Inst::SignExtendData { size } => match size { - 1 => { + OperandSize::Size8 => { sink.put1(0x66); sink.put1(0x98); } - 2 => { + OperandSize::Size16 => { sink.put1(0x66); sink.put1(0x99); } - 4 => sink.put1(0x99), - 8 => { + OperandSize::Size32 => sink.put1(0x99), + OperandSize::Size64 => { sink.put1(0x48); sink.put1(0x99); } - _ => unreachable!(), }, Inst::CheckedDivOrRemSeq { @@ -896,11 +892,7 @@ pub(crate) fn emit( // x % -1 = 0; put the result into the destination, $rdx. let done_label = sink.get_label(); - let inst = Inst::imm( - OperandSize::from_bytes(*size as u32), - 0, - Writable::from_reg(regs::rdx()), - ); + let inst = Inst::imm(*size, 0, Writable::from_reg(regs::rdx())); inst.emit(sink, info, state); let inst = Inst::jmp_known(done_label); @@ -909,13 +901,17 @@ pub(crate) fn emit( (Some(do_op), Some(done_label)) } else { // Check for integer overflow. - if *size == 8 { + if *size == OperandSize::Size64 { let tmp = tmp.expect("temporary for i64 sdiv"); let inst = Inst::imm(OperandSize::Size64, 0x8000000000000000, tmp); inst.emit(sink, info, state); - let inst = Inst::cmp_rmi_r(8, RegMemImm::reg(tmp.to_reg()), regs::rax()); + let inst = Inst::cmp_rmi_r( + OperandSize::Size64, + RegMemImm::reg(tmp.to_reg()), + regs::rax(), + ); inst.emit(sink, info, state); } else { let inst = Inst::cmp_rmi_r(*size, RegMemImm::imm(0x80000000), regs::rax()); @@ -937,7 +933,7 @@ pub(crate) fn emit( } assert!( - *size > 1, + *size != OperandSize::Size8, "CheckedDivOrRemSeq for i8 is not yet implemented" ); @@ -1175,7 +1171,7 @@ pub(crate) fn emit( let dst = &dst.finalize(state, sink); match size { - 1 => { + OperandSize::Size8 => { // This is one of the few places where the presence of a // redundant REX prefix changes the meaning of the // instruction. @@ -1198,7 +1194,7 @@ pub(crate) fn emit( ) } - 2 => { + OperandSize::Size16 => { // MOV r16, r/m16 is 66 (REX.W==0) 89 /r emit_std_reg_mem( sink, @@ -1213,7 +1209,7 @@ pub(crate) fn emit( ) } - 4 => { + OperandSize::Size32 => { // MOV r32, r/m32 is (REX.W==0) 89 /r emit_std_reg_mem( sink, @@ -1228,7 +1224,7 @@ pub(crate) fn emit( ) } - 8 => { + OperandSize::Size64 => { // MOV r64, r/m64 is (REX.W==1) 89 /r emit_std_reg_mem( sink, @@ -1242,8 +1238,6 @@ pub(crate) fn emit( RexFlags::set_w(), ) } - - _ => panic!("x64::Inst::Mov_R_M::emit: unreachable"), } } @@ -1265,15 +1259,14 @@ pub(crate) fn emit( match num_bits { None => { let (opcode, prefix, rex_flags) = match size { - 1 => ( + OperandSize::Size8 => ( 0xD2, LegacyPrefixes::None, *RexFlags::clear_w().always_emit_if_8bit_needed(enc_dst), ), - 2 => (0xD3, LegacyPrefixes::_66, RexFlags::clear_w()), - 4 => (0xD3, LegacyPrefixes::None, RexFlags::clear_w()), - 8 => (0xD3, LegacyPrefixes::None, RexFlags::set_w()), - _ => unreachable!("{}", size), + OperandSize::Size16 => (0xD3, LegacyPrefixes::_66, RexFlags::clear_w()), + OperandSize::Size32 => (0xD3, LegacyPrefixes::None, RexFlags::clear_w()), + OperandSize::Size64 => (0xD3, LegacyPrefixes::None, RexFlags::set_w()), }; // SHL/SHR/SAR %cl, reg8 is (REX.W==0) D2 /subopcode @@ -1285,15 +1278,14 @@ pub(crate) fn emit( Some(num_bits) => { let (opcode, prefix, rex_flags) = match size { - 1 => ( + OperandSize::Size8 => ( 0xC0, LegacyPrefixes::None, *RexFlags::clear_w().always_emit_if_8bit_needed(enc_dst), ), - 2 => (0xC1, LegacyPrefixes::_66, RexFlags::clear_w()), - 4 => (0xC1, LegacyPrefixes::None, RexFlags::clear_w()), - 8 => (0xC1, LegacyPrefixes::None, RexFlags::set_w()), - _ => unreachable!("{}", size), + OperandSize::Size16 => (0xC1, LegacyPrefixes::_66, RexFlags::clear_w()), + OperandSize::Size32 => (0xC1, LegacyPrefixes::None, RexFlags::clear_w()), + OperandSize::Size64 => (0xC1, LegacyPrefixes::None, RexFlags::set_w()), }; // SHL/SHR/SAR $ib, reg8 is (REX.W==0) C0 /subopcode @@ -1377,26 +1369,25 @@ pub(crate) fn emit( }; let mut prefix = LegacyPrefixes::None; - if *size == 2 { + if *size == OperandSize::Size16 { prefix = LegacyPrefixes::_66; } let mut rex = match size { - 8 => RexFlags::set_w(), - 4 | 2 => RexFlags::clear_w(), - 1 => { + OperandSize::Size64 => RexFlags::set_w(), + OperandSize::Size16 | OperandSize::Size32 => RexFlags::clear_w(), + OperandSize::Size8 => { let mut rex = RexFlags::clear_w(); // Here, a redundant REX prefix changes the meaning of the instruction. let enc_g = int_reg_enc(*reg_g); rex.always_emit_if_8bit_needed(enc_g); rex } - _ => panic!("x64::Inst::Cmp_RMI_R::emit: unreachable"), }; match src_e { RegMemImm::Reg { reg: reg_e } => { - if *size == 1 { + if *size == OperandSize::Size8 { // Check whether the E register forces the use of a redundant REX. let enc_e = int_reg_enc(*reg_e); rex.always_emit_if_8bit_needed(enc_e); @@ -1405,9 +1396,9 @@ pub(crate) fn emit( // Use the swapped operands encoding for CMP, to stay consistent with the output of // gcc/llvm. let opcode = match (*size, is_cmp) { - (1, true) => 0x38, + (OperandSize::Size8, true) => 0x38, (_, true) => 0x39, - (1, false) => 0x84, + (OperandSize::Size8, false) => 0x84, (_, false) => 0x85, }; emit_std_reg_reg(sink, prefix, opcode, 1, *reg_e, *reg_g, rex); @@ -1417,9 +1408,9 @@ pub(crate) fn emit( let addr = &addr.finalize(state, sink); // Whereas here we revert to the "normal" G-E ordering for CMP. let opcode = match (*size, is_cmp) { - (1, true) => 0x3A, + (OperandSize::Size8, true) => 0x3A, (_, true) => 0x3B, - (1, false) => 0x84, + (OperandSize::Size8, false) => 0x84, (_, false) => 0x85, }; emit_std_reg_mem(sink, state, info, prefix, opcode, 1, *reg_g, addr, rex); @@ -1432,7 +1423,7 @@ pub(crate) fn emit( // And also here we use the "normal" G-E ordering. let opcode = if is_cmp { - if *size == 1 { + if *size == OperandSize::Size8 { 0x80 } else if use_imm8 { 0x83 @@ -1440,7 +1431,7 @@ pub(crate) fn emit( 0x81 } } else { - if *size == 1 { + if *size == OperandSize::Size8 { 0xF6 } else { 0xF7 @@ -1450,7 +1441,7 @@ pub(crate) fn emit( let enc_g = int_reg_enc(*reg_g); emit_std_enc_enc(sink, prefix, opcode, 1, subopcode, enc_g, rex); - emit_simm(sink, if use_imm8 { 1 } else { *size }, *simm32); + emit_simm(sink, if use_imm8 { 1 } else { size.to_bytes() }, *simm32); } } } @@ -1477,9 +1468,9 @@ pub(crate) fn emit( dst: reg_g, } => { let (prefix, rex_flags) = match size { - 2 => (LegacyPrefixes::_66, RexFlags::clear_w()), - 4 => (LegacyPrefixes::None, RexFlags::clear_w()), - 8 => (LegacyPrefixes::None, RexFlags::set_w()), + OperandSize::Size16 => (LegacyPrefixes::_66, RexFlags::clear_w()), + OperandSize::Size32 => (LegacyPrefixes::None, RexFlags::clear_w()), + OperandSize::Size64 => (LegacyPrefixes::None, RexFlags::set_w()), _ => unreachable!("invalid size spec for cmove"), }; let opcode = 0x0F40 + cc.get_enc() as u32; @@ -2338,7 +2329,7 @@ pub(crate) fn emit( // If x seen as a signed int64 is not negative, a signed-conversion will do the right // thing. // TODO use tst src, src here. - let inst = Inst::cmp_rmi_r(8, RegMemImm::imm(0), src.to_reg()); + let inst = Inst::cmp_rmi_r(OperandSize::Size64, RegMemImm::imm(0), src.to_reg()); inst.emit(sink, info, state); one_way_jmp(sink, CC::L, handle_negative); @@ -2358,7 +2349,12 @@ pub(crate) fn emit( inst.emit(sink, info, state); // tmp_gpr1 := src >> 1 - let inst = Inst::shift_r(8, ShiftKind::ShiftRightLogical, Some(1), *tmp_gpr1); + let inst = Inst::shift_r( + OperandSize::Size64, + ShiftKind::ShiftRightLogical, + Some(1), + *tmp_gpr1, + ); inst.emit(sink, info, state); let inst = Inst::gen_move(*tmp_gpr2, src.to_reg(), types::I64); @@ -2464,7 +2460,7 @@ pub(crate) fn emit( 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()); + let inst = Inst::cmp_rmi_r(*dst_size, RegMemImm::imm(1), dst.to_reg()); inst.emit(sink, info, state); one_way_jmp(sink, CC::NO, done); // no overflow => done @@ -2693,7 +2689,7 @@ pub(crate) fn emit( let inst = Inst::xmm_to_gpr(trunc_op, src.to_reg(), *dst, *dst_size); inst.emit(sink, info, state); - let inst = Inst::cmp_rmi_r(dst_size.to_bytes(), RegMemImm::imm(0), dst.to_reg()); + let inst = Inst::cmp_rmi_r(*dst_size, RegMemImm::imm(0), dst.to_reg()); inst.emit(sink, info, state); one_way_jmp(sink, CC::NL, done); // if dst >= 0, jump to done @@ -2727,7 +2723,7 @@ pub(crate) fn emit( let inst = Inst::xmm_to_gpr(trunc_op, src.to_reg(), *dst, *dst_size); inst.emit(sink, info, state); - let inst = Inst::cmp_rmi_r(dst_size.to_bytes(), RegMemImm::imm(0), dst.to_reg()); + let inst = Inst::cmp_rmi_r(*dst_size, RegMemImm::imm(0), dst.to_reg()); inst.emit(sink, info, state); let next_is_large = sink.get_label(); diff --git a/cranelift/codegen/src/isa/x64/inst/emit_tests.rs b/cranelift/codegen/src/isa/x64/inst/emit_tests.rs index a3e1c9b658..0fbd3a7429 100644 --- a/cranelift/codegen/src/isa/x64/inst/emit_tests.rs +++ b/cranelift/codegen/src/isa/x64/inst/emit_tests.rs @@ -1211,12 +1211,22 @@ fn test_x64_emit() { // UnaryRmR insns.push(( - Inst::unary_rm_r(4, UnaryRmROpcode::Bsr, RegMem::reg(rsi), w_rdi), + Inst::unary_rm_r( + OperandSize::Size32, + UnaryRmROpcode::Bsr, + RegMem::reg(rsi), + w_rdi, + ), "0FBDFE", "bsrl %esi, %edi", )); insns.push(( - Inst::unary_rm_r(8, UnaryRmROpcode::Bsr, RegMem::reg(r15), w_rax), + Inst::unary_rm_r( + OperandSize::Size64, + UnaryRmROpcode::Bsr, + RegMem::reg(r15), + w_rax, + ), "490FBDC7", "bsrq %r15, %rax", )); @@ -1224,32 +1234,32 @@ fn test_x64_emit() { // ======================================================== // Not insns.push(( - Inst::not(4, Writable::from_reg(regs::rsi())), + Inst::not(OperandSize::Size32, Writable::from_reg(regs::rsi())), "F7D6", "notl %esi", )); insns.push(( - Inst::not(8, Writable::from_reg(regs::r15())), + Inst::not(OperandSize::Size64, Writable::from_reg(regs::r15())), "49F7D7", "notq %r15", )); insns.push(( - Inst::not(4, Writable::from_reg(regs::r14())), + Inst::not(OperandSize::Size32, Writable::from_reg(regs::r14())), "41F7D6", "notl %r14d", )); insns.push(( - Inst::not(2, Writable::from_reg(regs::rdi())), + Inst::not(OperandSize::Size16, Writable::from_reg(regs::rdi())), "66F7D7", "notw %di", )); insns.push(( - Inst::not(1, Writable::from_reg(regs::rdi())), + Inst::not(OperandSize::Size8, Writable::from_reg(regs::rdi())), "40F6D7", "notb %dil", )); insns.push(( - Inst::not(1, Writable::from_reg(regs::rax())), + Inst::not(OperandSize::Size8, Writable::from_reg(regs::rax())), "F6D0", "notb %al", )); @@ -1257,32 +1267,32 @@ fn test_x64_emit() { // ======================================================== // Neg insns.push(( - Inst::neg(4, Writable::from_reg(regs::rsi())), + Inst::neg(OperandSize::Size32, Writable::from_reg(regs::rsi())), "F7DE", "negl %esi", )); insns.push(( - Inst::neg(8, Writable::from_reg(regs::r15())), + Inst::neg(OperandSize::Size64, Writable::from_reg(regs::r15())), "49F7DF", "negq %r15", )); insns.push(( - Inst::neg(4, Writable::from_reg(regs::r14())), + Inst::neg(OperandSize::Size32, Writable::from_reg(regs::r14())), "41F7DE", "negl %r14d", )); insns.push(( - Inst::neg(2, Writable::from_reg(regs::rdi())), + Inst::neg(OperandSize::Size16, Writable::from_reg(regs::rdi())), "66F7DF", "negw %di", )); insns.push(( - Inst::neg(1, Writable::from_reg(regs::rdi())), + Inst::neg(OperandSize::Size8, Writable::from_reg(regs::rdi())), "40F6DF", "negb %dil", )); insns.push(( - Inst::neg(1, Writable::from_reg(regs::rax())), + Inst::neg(OperandSize::Size8, Writable::from_reg(regs::rax())), "F6D8", "negb %al", )); @@ -1290,32 +1300,48 @@ fn test_x64_emit() { // ======================================================== // Div insns.push(( - Inst::div(4, true /*signed*/, RegMem::reg(regs::rsi())), + Inst::div( + OperandSize::Size32, + true, /*signed*/ + RegMem::reg(regs::rsi()), + ), "F7FE", "idiv %esi", )); insns.push(( - Inst::div(8, true /*signed*/, RegMem::reg(regs::r15())), + Inst::div( + OperandSize::Size64, + true, /*signed*/ + RegMem::reg(regs::r15()), + ), "49F7FF", "idiv %r15", )); insns.push(( - Inst::div(4, false /*signed*/, RegMem::reg(regs::r14())), + Inst::div( + OperandSize::Size32, + false, /*signed*/ + RegMem::reg(regs::r14()), + ), "41F7F6", "div %r14d", )); insns.push(( - Inst::div(8, false /*signed*/, RegMem::reg(regs::rdi())), + Inst::div( + OperandSize::Size64, + false, /*signed*/ + RegMem::reg(regs::rdi()), + ), "48F7F7", "div %rdi", )); insns.push(( - Inst::div(1, false, RegMem::reg(regs::rax())), + Inst::div(OperandSize::Size8, false, RegMem::reg(regs::rax())), "F6F0", "div %al", )); insns.push(( - Inst::div(1, false, RegMem::reg(regs::rsi())), + Inst::div(OperandSize::Size8, false, RegMem::reg(regs::rsi())), "40F6F6", "div %sil", )); @@ -1323,35 +1349,51 @@ fn test_x64_emit() { // ======================================================== // MulHi insns.push(( - Inst::mul_hi(4, true /*signed*/, RegMem::reg(regs::rsi())), + Inst::mul_hi( + OperandSize::Size32, + true, /*signed*/ + RegMem::reg(regs::rsi()), + ), "F7EE", "imul %esi", )); insns.push(( - Inst::mul_hi(8, true /*signed*/, RegMem::reg(regs::r15())), + Inst::mul_hi( + OperandSize::Size64, + true, /*signed*/ + RegMem::reg(regs::r15()), + ), "49F7EF", "imul %r15", )); insns.push(( - Inst::mul_hi(4, false /*signed*/, RegMem::reg(regs::r14())), + Inst::mul_hi( + OperandSize::Size32, + false, /*signed*/ + RegMem::reg(regs::r14()), + ), "41F7E6", "mul %r14d", )); insns.push(( - Inst::mul_hi(8, false /*signed*/, RegMem::reg(regs::rdi())), + Inst::mul_hi( + OperandSize::Size64, + false, /*signed*/ + RegMem::reg(regs::rdi()), + ), "48F7E7", "mul %rdi", )); // ======================================================== // cbw - insns.push((Inst::sign_extend_data(1), "6698", "cbw")); + insns.push((Inst::sign_extend_data(OperandSize::Size8), "6698", "cbw")); // ======================================================== // cdq family: SignExtendRaxRdx - insns.push((Inst::sign_extend_data(2), "6699", "cwd")); - insns.push((Inst::sign_extend_data(4), "99", "cdq")); - insns.push((Inst::sign_extend_data(8), "4899", "cqo")); + insns.push((Inst::sign_extend_data(OperandSize::Size16), "6699", "cwd")); + insns.push((Inst::sign_extend_data(OperandSize::Size32), "99", "cdq")); + insns.push((Inst::sign_extend_data(OperandSize::Size64), "4899", "cqo")); // ======================================================== // Imm_R @@ -1980,325 +2022,325 @@ fn test_x64_emit() { // ======================================================== // Mov_R_M. Byte stores are tricky. Check everything carefully. insns.push(( - Inst::mov_r_m(8, rax, Amode::imm_reg(99, rdi)), + Inst::mov_r_m(OperandSize::Size64, rax, Amode::imm_reg(99, rdi)), "48894763", "movq %rax, 99(%rdi)", )); insns.push(( - Inst::mov_r_m(8, rbx, Amode::imm_reg(99, r8)), + Inst::mov_r_m(OperandSize::Size64, rbx, Amode::imm_reg(99, r8)), "49895863", "movq %rbx, 99(%r8)", )); insns.push(( - Inst::mov_r_m(8, rcx, Amode::imm_reg(99, rsi)), + Inst::mov_r_m(OperandSize::Size64, rcx, Amode::imm_reg(99, rsi)), "48894E63", "movq %rcx, 99(%rsi)", )); insns.push(( - Inst::mov_r_m(8, rdx, Amode::imm_reg(99, r9)), + Inst::mov_r_m(OperandSize::Size64, rdx, Amode::imm_reg(99, r9)), "49895163", "movq %rdx, 99(%r9)", )); insns.push(( - Inst::mov_r_m(8, rsi, Amode::imm_reg(99, rax)), + Inst::mov_r_m(OperandSize::Size64, rsi, Amode::imm_reg(99, rax)), "48897063", "movq %rsi, 99(%rax)", )); insns.push(( - Inst::mov_r_m(8, rdi, Amode::imm_reg(99, r15)), + Inst::mov_r_m(OperandSize::Size64, rdi, Amode::imm_reg(99, r15)), "49897F63", "movq %rdi, 99(%r15)", )); insns.push(( - Inst::mov_r_m(8, rsp, Amode::imm_reg(99, rcx)), + Inst::mov_r_m(OperandSize::Size64, rsp, Amode::imm_reg(99, rcx)), "48896163", "movq %rsp, 99(%rcx)", )); insns.push(( - Inst::mov_r_m(8, rbp, Amode::imm_reg(99, r14)), + Inst::mov_r_m(OperandSize::Size64, rbp, Amode::imm_reg(99, r14)), "49896E63", "movq %rbp, 99(%r14)", )); insns.push(( - Inst::mov_r_m(8, r8, Amode::imm_reg(99, rdi)), + Inst::mov_r_m(OperandSize::Size64, r8, Amode::imm_reg(99, rdi)), "4C894763", "movq %r8, 99(%rdi)", )); insns.push(( - Inst::mov_r_m(8, r9, Amode::imm_reg(99, r8)), + Inst::mov_r_m(OperandSize::Size64, r9, Amode::imm_reg(99, r8)), "4D894863", "movq %r9, 99(%r8)", )); insns.push(( - Inst::mov_r_m(8, r10, Amode::imm_reg(99, rsi)), + Inst::mov_r_m(OperandSize::Size64, r10, Amode::imm_reg(99, rsi)), "4C895663", "movq %r10, 99(%rsi)", )); insns.push(( - Inst::mov_r_m(8, r11, Amode::imm_reg(99, r9)), + Inst::mov_r_m(OperandSize::Size64, r11, Amode::imm_reg(99, r9)), "4D895963", "movq %r11, 99(%r9)", )); insns.push(( - Inst::mov_r_m(8, r12, Amode::imm_reg(99, rax)), + Inst::mov_r_m(OperandSize::Size64, r12, Amode::imm_reg(99, rax)), "4C896063", "movq %r12, 99(%rax)", )); insns.push(( - Inst::mov_r_m(8, r13, Amode::imm_reg(99, r15)), + Inst::mov_r_m(OperandSize::Size64, r13, Amode::imm_reg(99, r15)), "4D896F63", "movq %r13, 99(%r15)", )); insns.push(( - Inst::mov_r_m(8, r14, Amode::imm_reg(99, rcx)), + Inst::mov_r_m(OperandSize::Size64, r14, Amode::imm_reg(99, rcx)), "4C897163", "movq %r14, 99(%rcx)", )); insns.push(( - Inst::mov_r_m(8, r15, Amode::imm_reg(99, r14)), + Inst::mov_r_m(OperandSize::Size64, r15, Amode::imm_reg(99, r14)), "4D897E63", "movq %r15, 99(%r14)", )); // insns.push(( - Inst::mov_r_m(4, rax, Amode::imm_reg(99, rdi)), + Inst::mov_r_m(OperandSize::Size32, rax, Amode::imm_reg(99, rdi)), "894763", "movl %eax, 99(%rdi)", )); insns.push(( - Inst::mov_r_m(4, rbx, Amode::imm_reg(99, r8)), + Inst::mov_r_m(OperandSize::Size32, rbx, Amode::imm_reg(99, r8)), "41895863", "movl %ebx, 99(%r8)", )); insns.push(( - Inst::mov_r_m(4, rcx, Amode::imm_reg(99, rsi)), + Inst::mov_r_m(OperandSize::Size32, rcx, Amode::imm_reg(99, rsi)), "894E63", "movl %ecx, 99(%rsi)", )); insns.push(( - Inst::mov_r_m(4, rdx, Amode::imm_reg(99, r9)), + Inst::mov_r_m(OperandSize::Size32, rdx, Amode::imm_reg(99, r9)), "41895163", "movl %edx, 99(%r9)", )); insns.push(( - Inst::mov_r_m(4, rsi, Amode::imm_reg(99, rax)), + Inst::mov_r_m(OperandSize::Size32, rsi, Amode::imm_reg(99, rax)), "897063", "movl %esi, 99(%rax)", )); insns.push(( - Inst::mov_r_m(4, rdi, Amode::imm_reg(99, r15)), + Inst::mov_r_m(OperandSize::Size32, rdi, Amode::imm_reg(99, r15)), "41897F63", "movl %edi, 99(%r15)", )); insns.push(( - Inst::mov_r_m(4, rsp, Amode::imm_reg(99, rcx)), + Inst::mov_r_m(OperandSize::Size32, rsp, Amode::imm_reg(99, rcx)), "896163", "movl %esp, 99(%rcx)", )); insns.push(( - Inst::mov_r_m(4, rbp, Amode::imm_reg(99, r14)), + Inst::mov_r_m(OperandSize::Size32, rbp, Amode::imm_reg(99, r14)), "41896E63", "movl %ebp, 99(%r14)", )); insns.push(( - Inst::mov_r_m(4, r8, Amode::imm_reg(99, rdi)), + Inst::mov_r_m(OperandSize::Size32, r8, Amode::imm_reg(99, rdi)), "44894763", "movl %r8d, 99(%rdi)", )); insns.push(( - Inst::mov_r_m(4, r9, Amode::imm_reg(99, r8)), + Inst::mov_r_m(OperandSize::Size32, r9, Amode::imm_reg(99, r8)), "45894863", "movl %r9d, 99(%r8)", )); insns.push(( - Inst::mov_r_m(4, r10, Amode::imm_reg(99, rsi)), + Inst::mov_r_m(OperandSize::Size32, r10, Amode::imm_reg(99, rsi)), "44895663", "movl %r10d, 99(%rsi)", )); insns.push(( - Inst::mov_r_m(4, r11, Amode::imm_reg(99, r9)), + Inst::mov_r_m(OperandSize::Size32, r11, Amode::imm_reg(99, r9)), "45895963", "movl %r11d, 99(%r9)", )); insns.push(( - Inst::mov_r_m(4, r12, Amode::imm_reg(99, rax)), + Inst::mov_r_m(OperandSize::Size32, r12, Amode::imm_reg(99, rax)), "44896063", "movl %r12d, 99(%rax)", )); insns.push(( - Inst::mov_r_m(4, r13, Amode::imm_reg(99, r15)), + Inst::mov_r_m(OperandSize::Size32, r13, Amode::imm_reg(99, r15)), "45896F63", "movl %r13d, 99(%r15)", )); insns.push(( - Inst::mov_r_m(4, r14, Amode::imm_reg(99, rcx)), + Inst::mov_r_m(OperandSize::Size32, r14, Amode::imm_reg(99, rcx)), "44897163", "movl %r14d, 99(%rcx)", )); insns.push(( - Inst::mov_r_m(4, r15, Amode::imm_reg(99, r14)), + Inst::mov_r_m(OperandSize::Size32, r15, Amode::imm_reg(99, r14)), "45897E63", "movl %r15d, 99(%r14)", )); // insns.push(( - Inst::mov_r_m(2, rax, Amode::imm_reg(99, rdi)), + Inst::mov_r_m(OperandSize::Size16, rax, Amode::imm_reg(99, rdi)), "66894763", "movw %ax, 99(%rdi)", )); insns.push(( - Inst::mov_r_m(2, rbx, Amode::imm_reg(99, r8)), + Inst::mov_r_m(OperandSize::Size16, rbx, Amode::imm_reg(99, r8)), "6641895863", "movw %bx, 99(%r8)", )); insns.push(( - Inst::mov_r_m(2, rcx, Amode::imm_reg(99, rsi)), + Inst::mov_r_m(OperandSize::Size16, rcx, Amode::imm_reg(99, rsi)), "66894E63", "movw %cx, 99(%rsi)", )); insns.push(( - Inst::mov_r_m(2, rdx, Amode::imm_reg(99, r9)), + Inst::mov_r_m(OperandSize::Size16, rdx, Amode::imm_reg(99, r9)), "6641895163", "movw %dx, 99(%r9)", )); insns.push(( - Inst::mov_r_m(2, rsi, Amode::imm_reg(99, rax)), + Inst::mov_r_m(OperandSize::Size16, rsi, Amode::imm_reg(99, rax)), "66897063", "movw %si, 99(%rax)", )); insns.push(( - Inst::mov_r_m(2, rdi, Amode::imm_reg(99, r15)), + Inst::mov_r_m(OperandSize::Size16, rdi, Amode::imm_reg(99, r15)), "6641897F63", "movw %di, 99(%r15)", )); insns.push(( - Inst::mov_r_m(2, rsp, Amode::imm_reg(99, rcx)), + Inst::mov_r_m(OperandSize::Size16, rsp, Amode::imm_reg(99, rcx)), "66896163", "movw %sp, 99(%rcx)", )); insns.push(( - Inst::mov_r_m(2, rbp, Amode::imm_reg(99, r14)), + Inst::mov_r_m(OperandSize::Size16, rbp, Amode::imm_reg(99, r14)), "6641896E63", "movw %bp, 99(%r14)", )); insns.push(( - Inst::mov_r_m(2, r8, Amode::imm_reg(99, rdi)), + Inst::mov_r_m(OperandSize::Size16, r8, Amode::imm_reg(99, rdi)), "6644894763", "movw %r8w, 99(%rdi)", )); insns.push(( - Inst::mov_r_m(2, r9, Amode::imm_reg(99, r8)), + Inst::mov_r_m(OperandSize::Size16, r9, Amode::imm_reg(99, r8)), "6645894863", "movw %r9w, 99(%r8)", )); insns.push(( - Inst::mov_r_m(2, r10, Amode::imm_reg(99, rsi)), + Inst::mov_r_m(OperandSize::Size16, r10, Amode::imm_reg(99, rsi)), "6644895663", "movw %r10w, 99(%rsi)", )); insns.push(( - Inst::mov_r_m(2, r11, Amode::imm_reg(99, r9)), + Inst::mov_r_m(OperandSize::Size16, r11, Amode::imm_reg(99, r9)), "6645895963", "movw %r11w, 99(%r9)", )); insns.push(( - Inst::mov_r_m(2, r12, Amode::imm_reg(99, rax)), + Inst::mov_r_m(OperandSize::Size16, r12, Amode::imm_reg(99, rax)), "6644896063", "movw %r12w, 99(%rax)", )); insns.push(( - Inst::mov_r_m(2, r13, Amode::imm_reg(99, r15)), + Inst::mov_r_m(OperandSize::Size16, r13, Amode::imm_reg(99, r15)), "6645896F63", "movw %r13w, 99(%r15)", )); insns.push(( - Inst::mov_r_m(2, r14, Amode::imm_reg(99, rcx)), + Inst::mov_r_m(OperandSize::Size16, r14, Amode::imm_reg(99, rcx)), "6644897163", "movw %r14w, 99(%rcx)", )); insns.push(( - Inst::mov_r_m(2, r15, Amode::imm_reg(99, r14)), + Inst::mov_r_m(OperandSize::Size16, r15, Amode::imm_reg(99, r14)), "6645897E63", "movw %r15w, 99(%r14)", )); // insns.push(( - Inst::mov_r_m(1, rax, Amode::imm_reg(99, rdi)), + Inst::mov_r_m(OperandSize::Size8, rax, Amode::imm_reg(99, rdi)), "884763", "movb %al, 99(%rdi)", )); insns.push(( - Inst::mov_r_m(1, rbx, Amode::imm_reg(99, r8)), + Inst::mov_r_m(OperandSize::Size8, rbx, Amode::imm_reg(99, r8)), "41885863", "movb %bl, 99(%r8)", )); insns.push(( - Inst::mov_r_m(1, rcx, Amode::imm_reg(99, rsi)), + Inst::mov_r_m(OperandSize::Size8, rcx, Amode::imm_reg(99, rsi)), "884E63", "movb %cl, 99(%rsi)", )); insns.push(( - Inst::mov_r_m(1, rdx, Amode::imm_reg(99, r9)), + Inst::mov_r_m(OperandSize::Size8, rdx, Amode::imm_reg(99, r9)), "41885163", "movb %dl, 99(%r9)", )); insns.push(( - Inst::mov_r_m(1, rsi, Amode::imm_reg(99, rax)), + Inst::mov_r_m(OperandSize::Size8, rsi, Amode::imm_reg(99, rax)), "40887063", "movb %sil, 99(%rax)", )); insns.push(( - Inst::mov_r_m(1, rdi, Amode::imm_reg(99, r15)), + Inst::mov_r_m(OperandSize::Size8, rdi, Amode::imm_reg(99, r15)), "41887F63", "movb %dil, 99(%r15)", )); insns.push(( - Inst::mov_r_m(1, rsp, Amode::imm_reg(99, rcx)), + Inst::mov_r_m(OperandSize::Size8, rsp, Amode::imm_reg(99, rcx)), "40886163", "movb %spl, 99(%rcx)", )); insns.push(( - Inst::mov_r_m(1, rbp, Amode::imm_reg(99, r14)), + Inst::mov_r_m(OperandSize::Size8, rbp, Amode::imm_reg(99, r14)), "41886E63", "movb %bpl, 99(%r14)", )); insns.push(( - Inst::mov_r_m(1, r8, Amode::imm_reg(99, rdi)), + Inst::mov_r_m(OperandSize::Size8, r8, Amode::imm_reg(99, rdi)), "44884763", "movb %r8b, 99(%rdi)", )); insns.push(( - Inst::mov_r_m(1, r9, Amode::imm_reg(99, r8)), + Inst::mov_r_m(OperandSize::Size8, r9, Amode::imm_reg(99, r8)), "45884863", "movb %r9b, 99(%r8)", )); insns.push(( - Inst::mov_r_m(1, r10, Amode::imm_reg(99, rsi)), + Inst::mov_r_m(OperandSize::Size8, r10, Amode::imm_reg(99, rsi)), "44885663", "movb %r10b, 99(%rsi)", )); insns.push(( - Inst::mov_r_m(1, r11, Amode::imm_reg(99, r9)), + Inst::mov_r_m(OperandSize::Size8, r11, Amode::imm_reg(99, r9)), "45885963", "movb %r11b, 99(%r9)", )); insns.push(( - Inst::mov_r_m(1, r12, Amode::imm_reg(99, rax)), + Inst::mov_r_m(OperandSize::Size8, r12, Amode::imm_reg(99, rax)), "44886063", "movb %r12b, 99(%rax)", )); insns.push(( - Inst::mov_r_m(1, r13, Amode::imm_reg(99, r15)), + Inst::mov_r_m(OperandSize::Size8, r13, Amode::imm_reg(99, r15)), "45886F63", "movb %r13b, 99(%r15)", )); insns.push(( - Inst::mov_r_m(1, r14, Amode::imm_reg(99, rcx)), + Inst::mov_r_m(OperandSize::Size8, r14, Amode::imm_reg(99, rcx)), "44887163", "movb %r14b, 99(%rcx)", )); insns.push(( - Inst::mov_r_m(1, r15, Amode::imm_reg(99, r14)), + Inst::mov_r_m(OperandSize::Size8, r15, Amode::imm_reg(99, r14)), "45887E63", "movb %r15b, 99(%r14)", )); @@ -2306,152 +2348,212 @@ fn test_x64_emit() { // ======================================================== // Shift_R insns.push(( - Inst::shift_r(4, ShiftKind::ShiftLeft, None, w_rdi), + Inst::shift_r(OperandSize::Size32, ShiftKind::ShiftLeft, None, w_rdi), "D3E7", "shll %cl, %edi", )); insns.push(( - Inst::shift_r(4, ShiftKind::ShiftLeft, None, w_r12), + Inst::shift_r(OperandSize::Size32, ShiftKind::ShiftLeft, None, w_r12), "41D3E4", "shll %cl, %r12d", )); insns.push(( - Inst::shift_r(4, ShiftKind::ShiftLeft, Some(2), w_r8), + Inst::shift_r(OperandSize::Size32, ShiftKind::ShiftLeft, Some(2), w_r8), "41C1E002", "shll $2, %r8d", )); insns.push(( - Inst::shift_r(4, ShiftKind::ShiftLeft, Some(31), w_r13), + Inst::shift_r(OperandSize::Size32, ShiftKind::ShiftLeft, Some(31), w_r13), "41C1E51F", "shll $31, %r13d", )); insns.push(( - Inst::shift_r(8, ShiftKind::ShiftLeft, None, w_r13), + Inst::shift_r(OperandSize::Size64, ShiftKind::ShiftLeft, None, w_r13), "49D3E5", "shlq %cl, %r13", )); insns.push(( - Inst::shift_r(8, ShiftKind::ShiftLeft, None, w_rdi), + Inst::shift_r(OperandSize::Size64, ShiftKind::ShiftLeft, None, w_rdi), "48D3E7", "shlq %cl, %rdi", )); insns.push(( - Inst::shift_r(8, ShiftKind::ShiftLeft, Some(2), w_r8), + Inst::shift_r(OperandSize::Size64, ShiftKind::ShiftLeft, Some(2), w_r8), "49C1E002", "shlq $2, %r8", )); insns.push(( - Inst::shift_r(8, ShiftKind::ShiftLeft, Some(3), w_rbx), + Inst::shift_r(OperandSize::Size64, ShiftKind::ShiftLeft, Some(3), w_rbx), "48C1E303", "shlq $3, %rbx", )); insns.push(( - Inst::shift_r(8, ShiftKind::ShiftLeft, Some(63), w_r13), + Inst::shift_r(OperandSize::Size64, ShiftKind::ShiftLeft, Some(63), w_r13), "49C1E53F", "shlq $63, %r13", )); insns.push(( - Inst::shift_r(4, ShiftKind::ShiftRightLogical, None, w_rdi), + Inst::shift_r( + OperandSize::Size32, + ShiftKind::ShiftRightLogical, + None, + w_rdi, + ), "D3EF", "shrl %cl, %edi", )); insns.push(( - Inst::shift_r(4, ShiftKind::ShiftRightLogical, Some(2), w_r8), + Inst::shift_r( + OperandSize::Size32, + ShiftKind::ShiftRightLogical, + Some(2), + w_r8, + ), "41C1E802", "shrl $2, %r8d", )); insns.push(( - Inst::shift_r(4, ShiftKind::ShiftRightLogical, Some(31), w_r13), + Inst::shift_r( + OperandSize::Size32, + ShiftKind::ShiftRightLogical, + Some(31), + w_r13, + ), "41C1ED1F", "shrl $31, %r13d", )); insns.push(( - Inst::shift_r(8, ShiftKind::ShiftRightLogical, None, w_rdi), + Inst::shift_r( + OperandSize::Size64, + ShiftKind::ShiftRightLogical, + None, + w_rdi, + ), "48D3EF", "shrq %cl, %rdi", )); insns.push(( - Inst::shift_r(8, ShiftKind::ShiftRightLogical, Some(2), w_r8), + Inst::shift_r( + OperandSize::Size64, + ShiftKind::ShiftRightLogical, + Some(2), + w_r8, + ), "49C1E802", "shrq $2, %r8", )); insns.push(( - Inst::shift_r(8, ShiftKind::ShiftRightLogical, Some(63), w_r13), + Inst::shift_r( + OperandSize::Size64, + ShiftKind::ShiftRightLogical, + Some(63), + w_r13, + ), "49C1ED3F", "shrq $63, %r13", )); insns.push(( - Inst::shift_r(4, ShiftKind::ShiftRightArithmetic, None, w_rdi), + Inst::shift_r( + OperandSize::Size32, + ShiftKind::ShiftRightArithmetic, + None, + w_rdi, + ), "D3FF", "sarl %cl, %edi", )); insns.push(( - Inst::shift_r(4, ShiftKind::ShiftRightArithmetic, Some(2), w_r8), + Inst::shift_r( + OperandSize::Size32, + ShiftKind::ShiftRightArithmetic, + Some(2), + w_r8, + ), "41C1F802", "sarl $2, %r8d", )); insns.push(( - Inst::shift_r(4, ShiftKind::ShiftRightArithmetic, Some(31), w_r13), + Inst::shift_r( + OperandSize::Size32, + ShiftKind::ShiftRightArithmetic, + Some(31), + w_r13, + ), "41C1FD1F", "sarl $31, %r13d", )); insns.push(( - Inst::shift_r(8, ShiftKind::ShiftRightArithmetic, None, w_rdi), + Inst::shift_r( + OperandSize::Size64, + ShiftKind::ShiftRightArithmetic, + None, + w_rdi, + ), "48D3FF", "sarq %cl, %rdi", )); insns.push(( - Inst::shift_r(8, ShiftKind::ShiftRightArithmetic, Some(2), w_r8), + Inst::shift_r( + OperandSize::Size64, + ShiftKind::ShiftRightArithmetic, + Some(2), + w_r8, + ), "49C1F802", "sarq $2, %r8", )); insns.push(( - Inst::shift_r(8, ShiftKind::ShiftRightArithmetic, Some(63), w_r13), + Inst::shift_r( + OperandSize::Size64, + ShiftKind::ShiftRightArithmetic, + Some(63), + w_r13, + ), "49C1FD3F", "sarq $63, %r13", )); insns.push(( - Inst::shift_r(8, ShiftKind::RotateLeft, None, w_r8), + Inst::shift_r(OperandSize::Size64, ShiftKind::RotateLeft, None, w_r8), "49D3C0", "rolq %cl, %r8", )); insns.push(( - Inst::shift_r(4, ShiftKind::RotateLeft, Some(3), w_r9), + Inst::shift_r(OperandSize::Size32, ShiftKind::RotateLeft, Some(3), w_r9), "41C1C103", "roll $3, %r9d", )); insns.push(( - Inst::shift_r(4, ShiftKind::RotateRight, None, w_rsi), + Inst::shift_r(OperandSize::Size32, ShiftKind::RotateRight, None, w_rsi), "D3CE", "rorl %cl, %esi", )); insns.push(( - Inst::shift_r(8, ShiftKind::RotateRight, Some(5), w_r15), + Inst::shift_r(OperandSize::Size64, ShiftKind::RotateRight, Some(5), w_r15), "49C1CF05", "rorq $5, %r15", )); insns.push(( - Inst::shift_r(1, ShiftKind::RotateRight, None, w_rsi), + Inst::shift_r(OperandSize::Size8, ShiftKind::RotateRight, None, w_rsi), "40D2CE", "rorb %cl, %sil", )); insns.push(( - Inst::shift_r(1, ShiftKind::RotateRight, None, w_rax), + Inst::shift_r(OperandSize::Size8, ShiftKind::RotateRight, None, w_rax), "D2C8", "rorb %cl, %al", )); insns.push(( - Inst::shift_r(1, ShiftKind::RotateRight, Some(5), w_r15), + Inst::shift_r(OperandSize::Size8, ShiftKind::RotateRight, Some(5), w_r15), "41C0CF05", "rorb $5, %r15b", )); insns.push(( - Inst::shift_r(2, ShiftKind::RotateRight, None, w_rsi), + Inst::shift_r(OperandSize::Size16, ShiftKind::RotateRight, None, w_rsi), "66D3CE", "rorw %cl, %si", )); insns.push(( - Inst::shift_r(2, ShiftKind::RotateRight, Some(5), w_r15), + Inst::shift_r(OperandSize::Size16, ShiftKind::RotateRight, Some(5), w_r15), "6641C1CF05", "rorw $5, %r15w", )); @@ -2459,276 +2561,324 @@ fn test_x64_emit() { // ======================================================== // CmpRMIR insns.push(( - Inst::cmp_rmi_r(8, RegMemImm::reg(r15), rdx), + Inst::cmp_rmi_r(OperandSize::Size64, RegMemImm::reg(r15), rdx), "4C39FA", "cmpq %r15, %rdx", )); insns.push(( - Inst::cmp_rmi_r(8, RegMemImm::reg(rcx), r8), + Inst::cmp_rmi_r(OperandSize::Size64, RegMemImm::reg(rcx), r8), "4939C8", "cmpq %rcx, %r8", )); insns.push(( - Inst::cmp_rmi_r(8, RegMemImm::reg(rcx), rsi), + Inst::cmp_rmi_r(OperandSize::Size64, RegMemImm::reg(rcx), rsi), "4839CE", "cmpq %rcx, %rsi", )); insns.push(( - Inst::cmp_rmi_r(8, RegMemImm::mem(Amode::imm_reg(99, rdi)), rdx), + Inst::cmp_rmi_r( + OperandSize::Size64, + RegMemImm::mem(Amode::imm_reg(99, rdi)), + rdx, + ), "483B5763", "cmpq 99(%rdi), %rdx", )); insns.push(( - Inst::cmp_rmi_r(8, RegMemImm::mem(Amode::imm_reg(99, rdi)), r8), + Inst::cmp_rmi_r( + OperandSize::Size64, + RegMemImm::mem(Amode::imm_reg(99, rdi)), + r8, + ), "4C3B4763", "cmpq 99(%rdi), %r8", )); insns.push(( - Inst::cmp_rmi_r(8, RegMemImm::mem(Amode::imm_reg(99, rdi)), rsi), + Inst::cmp_rmi_r( + OperandSize::Size64, + RegMemImm::mem(Amode::imm_reg(99, rdi)), + rsi, + ), "483B7763", "cmpq 99(%rdi), %rsi", )); insns.push(( - Inst::cmp_rmi_r(8, RegMemImm::imm(76543210), rdx), + Inst::cmp_rmi_r(OperandSize::Size64, RegMemImm::imm(76543210), rdx), "4881FAEAF48F04", "cmpq $76543210, %rdx", )); insns.push(( - Inst::cmp_rmi_r(8, RegMemImm::imm(-76543210i32 as u32), r8), + Inst::cmp_rmi_r(OperandSize::Size64, RegMemImm::imm(-76543210i32 as u32), r8), "4981F8160B70FB", "cmpq $-76543210, %r8", )); insns.push(( - Inst::cmp_rmi_r(8, RegMemImm::imm(76543210), rsi), + Inst::cmp_rmi_r(OperandSize::Size64, RegMemImm::imm(76543210), rsi), "4881FEEAF48F04", "cmpq $76543210, %rsi", )); // insns.push(( - Inst::cmp_rmi_r(4, RegMemImm::reg(r15), rdx), + Inst::cmp_rmi_r(OperandSize::Size32, RegMemImm::reg(r15), rdx), "4439FA", "cmpl %r15d, %edx", )); insns.push(( - Inst::cmp_rmi_r(4, RegMemImm::reg(rcx), r8), + Inst::cmp_rmi_r(OperandSize::Size32, RegMemImm::reg(rcx), r8), "4139C8", "cmpl %ecx, %r8d", )); insns.push(( - Inst::cmp_rmi_r(4, RegMemImm::reg(rcx), rsi), + Inst::cmp_rmi_r(OperandSize::Size32, RegMemImm::reg(rcx), rsi), "39CE", "cmpl %ecx, %esi", )); insns.push(( - Inst::cmp_rmi_r(4, RegMemImm::mem(Amode::imm_reg(99, rdi)), rdx), + Inst::cmp_rmi_r( + OperandSize::Size32, + RegMemImm::mem(Amode::imm_reg(99, rdi)), + rdx, + ), "3B5763", "cmpl 99(%rdi), %edx", )); insns.push(( - Inst::cmp_rmi_r(4, RegMemImm::mem(Amode::imm_reg(99, rdi)), r8), + Inst::cmp_rmi_r( + OperandSize::Size32, + RegMemImm::mem(Amode::imm_reg(99, rdi)), + r8, + ), "443B4763", "cmpl 99(%rdi), %r8d", )); insns.push(( - Inst::cmp_rmi_r(4, RegMemImm::mem(Amode::imm_reg(99, rdi)), rsi), + Inst::cmp_rmi_r( + OperandSize::Size32, + RegMemImm::mem(Amode::imm_reg(99, rdi)), + rsi, + ), "3B7763", "cmpl 99(%rdi), %esi", )); insns.push(( - Inst::cmp_rmi_r(4, RegMemImm::imm(76543210), rdx), + Inst::cmp_rmi_r(OperandSize::Size32, RegMemImm::imm(76543210), rdx), "81FAEAF48F04", "cmpl $76543210, %edx", )); insns.push(( - Inst::cmp_rmi_r(4, RegMemImm::imm(-76543210i32 as u32), r8), + Inst::cmp_rmi_r(OperandSize::Size32, RegMemImm::imm(-76543210i32 as u32), r8), "4181F8160B70FB", "cmpl $-76543210, %r8d", )); insns.push(( - Inst::cmp_rmi_r(4, RegMemImm::imm(76543210), rsi), + Inst::cmp_rmi_r(OperandSize::Size32, RegMemImm::imm(76543210), rsi), "81FEEAF48F04", "cmpl $76543210, %esi", )); // insns.push(( - Inst::cmp_rmi_r(2, RegMemImm::reg(r15), rdx), + Inst::cmp_rmi_r(OperandSize::Size16, RegMemImm::reg(r15), rdx), "664439FA", "cmpw %r15w, %dx", )); insns.push(( - Inst::cmp_rmi_r(2, RegMemImm::reg(rcx), r8), + Inst::cmp_rmi_r(OperandSize::Size16, RegMemImm::reg(rcx), r8), "664139C8", "cmpw %cx, %r8w", )); insns.push(( - Inst::cmp_rmi_r(2, RegMemImm::reg(rcx), rsi), + Inst::cmp_rmi_r(OperandSize::Size16, RegMemImm::reg(rcx), rsi), "6639CE", "cmpw %cx, %si", )); insns.push(( - Inst::cmp_rmi_r(2, RegMemImm::mem(Amode::imm_reg(99, rdi)), rdx), + Inst::cmp_rmi_r( + OperandSize::Size16, + RegMemImm::mem(Amode::imm_reg(99, rdi)), + rdx, + ), "663B5763", "cmpw 99(%rdi), %dx", )); insns.push(( - Inst::cmp_rmi_r(2, RegMemImm::mem(Amode::imm_reg(99, rdi)), r8), + Inst::cmp_rmi_r( + OperandSize::Size16, + RegMemImm::mem(Amode::imm_reg(99, rdi)), + r8, + ), "66443B4763", "cmpw 99(%rdi), %r8w", )); insns.push(( - Inst::cmp_rmi_r(2, RegMemImm::mem(Amode::imm_reg(99, rdi)), rsi), + Inst::cmp_rmi_r( + OperandSize::Size16, + RegMemImm::mem(Amode::imm_reg(99, rdi)), + rsi, + ), "663B7763", "cmpw 99(%rdi), %si", )); insns.push(( - Inst::cmp_rmi_r(2, RegMemImm::imm(23210), rdx), + Inst::cmp_rmi_r(OperandSize::Size16, RegMemImm::imm(23210), rdx), "6681FAAA5A", "cmpw $23210, %dx", )); insns.push(( - Inst::cmp_rmi_r(2, RegMemImm::imm(-7654i32 as u32), r8), + Inst::cmp_rmi_r(OperandSize::Size16, RegMemImm::imm(-7654i32 as u32), r8), "664181F81AE2", "cmpw $-7654, %r8w", )); insns.push(( - Inst::cmp_rmi_r(2, RegMemImm::imm(7654), rsi), + Inst::cmp_rmi_r(OperandSize::Size16, RegMemImm::imm(7654), rsi), "6681FEE61D", "cmpw $7654, %si", )); // insns.push(( - Inst::cmp_rmi_r(1, RegMemImm::reg(r15), rdx), + Inst::cmp_rmi_r(OperandSize::Size8, RegMemImm::reg(r15), rdx), "4438FA", "cmpb %r15b, %dl", )); insns.push(( - Inst::cmp_rmi_r(1, RegMemImm::reg(rcx), r8), + Inst::cmp_rmi_r(OperandSize::Size8, RegMemImm::reg(rcx), r8), "4138C8", "cmpb %cl, %r8b", )); insns.push(( - Inst::cmp_rmi_r(1, RegMemImm::reg(rcx), rsi), + Inst::cmp_rmi_r(OperandSize::Size8, RegMemImm::reg(rcx), rsi), "4038CE", "cmpb %cl, %sil", )); insns.push(( - Inst::cmp_rmi_r(1, RegMemImm::mem(Amode::imm_reg(99, rdi)), rdx), + Inst::cmp_rmi_r( + OperandSize::Size8, + RegMemImm::mem(Amode::imm_reg(99, rdi)), + rdx, + ), "3A5763", "cmpb 99(%rdi), %dl", )); insns.push(( - Inst::cmp_rmi_r(1, RegMemImm::mem(Amode::imm_reg(99, rdi)), r8), + Inst::cmp_rmi_r( + OperandSize::Size8, + RegMemImm::mem(Amode::imm_reg(99, rdi)), + r8, + ), "443A4763", "cmpb 99(%rdi), %r8b", )); insns.push(( - Inst::cmp_rmi_r(1, RegMemImm::mem(Amode::imm_reg(99, rdi)), rsi), + Inst::cmp_rmi_r( + OperandSize::Size8, + RegMemImm::mem(Amode::imm_reg(99, rdi)), + rsi, + ), "403A7763", "cmpb 99(%rdi), %sil", )); insns.push(( - Inst::cmp_rmi_r(1, RegMemImm::imm(70), rdx), + Inst::cmp_rmi_r(OperandSize::Size8, RegMemImm::imm(70), rdx), "80FA46", "cmpb $70, %dl", )); insns.push(( - Inst::cmp_rmi_r(1, RegMemImm::imm(-76i32 as u32), r8), + Inst::cmp_rmi_r(OperandSize::Size8, RegMemImm::imm(-76i32 as u32), r8), "4180F8B4", "cmpb $-76, %r8b", )); insns.push(( - Inst::cmp_rmi_r(1, RegMemImm::imm(76), rsi), + Inst::cmp_rmi_r(OperandSize::Size8, RegMemImm::imm(76), rsi), "4080FE4C", "cmpb $76, %sil", )); // Extra byte-cases (paranoia!) for cmp_rmi_r for first operand = R insns.push(( - Inst::cmp_rmi_r(1, RegMemImm::reg(rax), rbx), + Inst::cmp_rmi_r(OperandSize::Size8, RegMemImm::reg(rax), rbx), "38C3", "cmpb %al, %bl", )); insns.push(( - Inst::cmp_rmi_r(1, RegMemImm::reg(rbx), rax), + Inst::cmp_rmi_r(OperandSize::Size8, RegMemImm::reg(rbx), rax), "38D8", "cmpb %bl, %al", )); insns.push(( - Inst::cmp_rmi_r(1, RegMemImm::reg(rcx), rdx), + Inst::cmp_rmi_r(OperandSize::Size8, RegMemImm::reg(rcx), rdx), "38CA", "cmpb %cl, %dl", )); insns.push(( - Inst::cmp_rmi_r(1, RegMemImm::reg(rcx), rsi), + Inst::cmp_rmi_r(OperandSize::Size8, RegMemImm::reg(rcx), rsi), "4038CE", "cmpb %cl, %sil", )); insns.push(( - Inst::cmp_rmi_r(1, RegMemImm::reg(rcx), r10), + Inst::cmp_rmi_r(OperandSize::Size8, RegMemImm::reg(rcx), r10), "4138CA", "cmpb %cl, %r10b", )); insns.push(( - Inst::cmp_rmi_r(1, RegMemImm::reg(rcx), r14), + Inst::cmp_rmi_r(OperandSize::Size8, RegMemImm::reg(rcx), r14), "4138CE", "cmpb %cl, %r14b", )); insns.push(( - Inst::cmp_rmi_r(1, RegMemImm::reg(rbp), rdx), + Inst::cmp_rmi_r(OperandSize::Size8, RegMemImm::reg(rbp), rdx), "4038EA", "cmpb %bpl, %dl", )); insns.push(( - Inst::cmp_rmi_r(1, RegMemImm::reg(rbp), rsi), + Inst::cmp_rmi_r(OperandSize::Size8, RegMemImm::reg(rbp), rsi), "4038EE", "cmpb %bpl, %sil", )); insns.push(( - Inst::cmp_rmi_r(1, RegMemImm::reg(rbp), r10), + Inst::cmp_rmi_r(OperandSize::Size8, RegMemImm::reg(rbp), r10), "4138EA", "cmpb %bpl, %r10b", )); insns.push(( - Inst::cmp_rmi_r(1, RegMemImm::reg(rbp), r14), + Inst::cmp_rmi_r(OperandSize::Size8, RegMemImm::reg(rbp), r14), "4138EE", "cmpb %bpl, %r14b", )); insns.push(( - Inst::cmp_rmi_r(1, RegMemImm::reg(r9), rdx), + Inst::cmp_rmi_r(OperandSize::Size8, RegMemImm::reg(r9), rdx), "4438CA", "cmpb %r9b, %dl", )); insns.push(( - Inst::cmp_rmi_r(1, RegMemImm::reg(r9), rsi), + Inst::cmp_rmi_r(OperandSize::Size8, RegMemImm::reg(r9), rsi), "4438CE", "cmpb %r9b, %sil", )); insns.push(( - Inst::cmp_rmi_r(1, RegMemImm::reg(r9), r10), + Inst::cmp_rmi_r(OperandSize::Size8, RegMemImm::reg(r9), r10), "4538CA", "cmpb %r9b, %r10b", )); insns.push(( - Inst::cmp_rmi_r(1, RegMemImm::reg(r9), r14), + Inst::cmp_rmi_r(OperandSize::Size8, RegMemImm::reg(r9), r14), "4538CE", "cmpb %r9b, %r14b", )); insns.push(( - Inst::cmp_rmi_r(1, RegMemImm::reg(r13), rdx), + Inst::cmp_rmi_r(OperandSize::Size8, RegMemImm::reg(r13), rdx), "4438EA", "cmpb %r13b, %dl", )); insns.push(( - Inst::cmp_rmi_r(1, RegMemImm::reg(r13), rsi), + Inst::cmp_rmi_r(OperandSize::Size8, RegMemImm::reg(r13), rsi), "4438EE", "cmpb %r13b, %sil", )); insns.push(( - Inst::cmp_rmi_r(1, RegMemImm::reg(r13), r10), + Inst::cmp_rmi_r(OperandSize::Size8, RegMemImm::reg(r13), r10), "4538EA", "cmpb %r13b, %r10b", )); insns.push(( - Inst::cmp_rmi_r(1, RegMemImm::reg(r13), r14), + Inst::cmp_rmi_r(OperandSize::Size8, RegMemImm::reg(r13), r14), "4538EE", "cmpb %r13b, %r14b", )); @@ -2736,81 +2886,97 @@ fn test_x64_emit() { // ======================================================== // TestRmiR insns.push(( - Inst::test_rmi_r(8, RegMemImm::reg(r15), rdx), + Inst::test_rmi_r(OperandSize::Size64, RegMemImm::reg(r15), rdx), "4C85FA", "testq %r15, %rdx", )); insns.push(( - Inst::test_rmi_r(8, RegMemImm::mem(Amode::imm_reg(99, rdi)), rdx), + Inst::test_rmi_r( + OperandSize::Size64, + RegMemImm::mem(Amode::imm_reg(99, rdi)), + rdx, + ), "48855763", "testq 99(%rdi), %rdx", )); insns.push(( - Inst::test_rmi_r(8, RegMemImm::imm(76543210), rdx), + Inst::test_rmi_r(OperandSize::Size64, RegMemImm::imm(76543210), rdx), "48F7C2EAF48F04", "testq $76543210, %rdx", )); // insns.push(( - Inst::test_rmi_r(4, RegMemImm::reg(r15), rdx), + Inst::test_rmi_r(OperandSize::Size32, RegMemImm::reg(r15), rdx), "4485FA", "testl %r15d, %edx", )); insns.push(( - Inst::test_rmi_r(4, RegMemImm::mem(Amode::imm_reg(99, rdi)), rdx), + Inst::test_rmi_r( + OperandSize::Size32, + RegMemImm::mem(Amode::imm_reg(99, rdi)), + rdx, + ), "855763", "testl 99(%rdi), %edx", )); insns.push(( - Inst::test_rmi_r(4, RegMemImm::imm(76543210), rdx), + Inst::test_rmi_r(OperandSize::Size32, RegMemImm::imm(76543210), rdx), "F7C2EAF48F04", "testl $76543210, %edx", )); // insns.push(( - Inst::test_rmi_r(2, RegMemImm::reg(r15), rdx), + Inst::test_rmi_r(OperandSize::Size16, RegMemImm::reg(r15), rdx), "664485FA", "testw %r15w, %dx", )); insns.push(( - Inst::test_rmi_r(2, RegMemImm::mem(Amode::imm_reg(99, rdi)), rdx), + Inst::test_rmi_r( + OperandSize::Size16, + RegMemImm::mem(Amode::imm_reg(99, rdi)), + rdx, + ), "66855763", "testw 99(%rdi), %dx", )); insns.push(( - Inst::test_rmi_r(2, RegMemImm::imm(23210), rdx), + Inst::test_rmi_r(OperandSize::Size16, RegMemImm::imm(23210), rdx), "66F7C2AA5A", "testw $23210, %dx", )); // insns.push(( - Inst::test_rmi_r(1, RegMemImm::reg(r15), rdx), + Inst::test_rmi_r(OperandSize::Size8, RegMemImm::reg(r15), rdx), "4484FA", "testb %r15b, %dl", )); insns.push(( - Inst::test_rmi_r(1, RegMemImm::mem(Amode::imm_reg(99, rdi)), rdx), + Inst::test_rmi_r( + OperandSize::Size8, + RegMemImm::mem(Amode::imm_reg(99, rdi)), + rdx, + ), "845763", "testb 99(%rdi), %dl", )); insns.push(( - Inst::test_rmi_r(1, RegMemImm::imm(70), rdx), + Inst::test_rmi_r(OperandSize::Size8, RegMemImm::imm(70), rdx), "F6C246", "testb $70, %dl", )); // Extra byte-cases (paranoia!) for test_rmi_r for first operand = R insns.push(( - Inst::test_rmi_r(1, RegMemImm::reg(rax), rbx), + Inst::test_rmi_r(OperandSize::Size8, RegMemImm::reg(rax), rbx), "84C3", "testb %al, %bl", )); insns.push(( - Inst::test_rmi_r(1, RegMemImm::reg(rcx), rsi), + Inst::test_rmi_r(OperandSize::Size8, RegMemImm::reg(rcx), rsi), "4084CE", "testb %cl, %sil", )); insns.push(( - Inst::test_rmi_r(1, RegMemImm::reg(rcx), r10), + Inst::test_rmi_r(OperandSize::Size8, RegMemImm::reg(rcx), r10), "4184CA", "testb %cl, %r10b", )); @@ -2826,13 +2992,13 @@ fn test_x64_emit() { // ======================================================== // Cmove insns.push(( - Inst::cmove(2, CC::O, RegMem::reg(rdi), w_rsi), + Inst::cmove(OperandSize::Size16, CC::O, RegMem::reg(rdi), w_rsi), "660F40F7", "cmovow %di, %si", )); insns.push(( Inst::cmove( - 2, + OperandSize::Size16, CC::NO, RegMem::mem(Amode::imm_reg_reg_shift(37, rdi, rsi, 2)), w_r15, @@ -2841,22 +3007,32 @@ fn test_x64_emit() { "cmovnow 37(%rdi,%rsi,4), %r15w", )); insns.push(( - Inst::cmove(4, CC::LE, RegMem::reg(rdi), w_rsi), + Inst::cmove(OperandSize::Size32, CC::LE, RegMem::reg(rdi), w_rsi), "0F4EF7", "cmovlel %edi, %esi", )); insns.push(( - Inst::cmove(4, CC::NLE, RegMem::mem(Amode::imm_reg(0, r15)), w_rsi), + Inst::cmove( + OperandSize::Size32, + CC::NLE, + RegMem::mem(Amode::imm_reg(0, r15)), + w_rsi, + ), "410F4F37", "cmovnlel 0(%r15), %esi", )); insns.push(( - Inst::cmove(8, CC::Z, RegMem::reg(rdi), w_r14), + Inst::cmove(OperandSize::Size64, CC::Z, RegMem::reg(rdi), w_r14), "4C0F44F7", "cmovzq %rdi, %r14", )); insns.push(( - Inst::cmove(8, CC::NZ, RegMem::mem(Amode::imm_reg(13, rdi)), w_r14), + Inst::cmove( + OperandSize::Size64, + CC::NZ, + RegMem::mem(Amode::imm_reg(13, rdi)), + w_r14, + ), "4C0F45770D", "cmovnzq 13(%rdi), %r14", )); diff --git a/cranelift/codegen/src/isa/x64/inst/mod.rs b/cranelift/codegen/src/isa/x64/inst/mod.rs index 6b33db51ab..11e2244d35 100644 --- a/cranelift/codegen/src/isa/x64/inst/mod.rs +++ b/cranelift/codegen/src/isa/x64/inst/mod.rs @@ -50,7 +50,7 @@ pub enum Inst { /// Instructions on GPR that only read src and defines dst (dst is not modified): bsr, etc. UnaryRmR { - size: u8, // 2, 4 or 8 + size: OperandSize, // 2, 4 or 8 op: UnaryRmROpcode, src: RegMem, dst: Writable, @@ -58,25 +58,29 @@ pub enum Inst { /// Bitwise not Not { - size: u8, // 1, 2, 4 or 8 + size: OperandSize, // 1, 2, 4 or 8 src: Writable, }, /// Integer negation Neg { - size: u8, // 1, 2, 4 or 8 + size: OperandSize, // 1, 2, 4 or 8 src: Writable, }, /// Integer quotient and remainder: (div idiv) $rax $rdx (reg addr) Div { - size: u8, // 1, 2, 4 or 8 + size: OperandSize, // 1, 2, 4 or 8 signed: bool, divisor: RegMem, }, /// The high bits (RDX) of a (un)signed multiply: RDX:RAX := RAX * rhs. - MulHi { size: u8, signed: bool, rhs: RegMem }, + MulHi { + size: OperandSize, // 2, 4, or 8 + signed: bool, + rhs: RegMem, + }, /// A synthetic sequence to implement the right inline checks for remainder and division, /// assuming the dividend is in %rax. @@ -91,7 +95,7 @@ pub enum Inst { /// def! CheckedDivOrRemSeq { kind: DivOrRemKind, - size: u8, + size: OperandSize, /// The divisor operand. Note it's marked as modified so that it gets assigned a register /// different from the temporary. divisor: Writable, @@ -101,7 +105,7 @@ pub enum Inst { /// Do a sign-extend based on the sign of the value in rax into rdx: (cwd cdq cqo) /// or al into ah: (cbw) SignExtendData { - size: u8, // 1, 2, 4 or 8 + size: OperandSize, // 1, 2, 4 or 8 }, /// Constant materialization: (imm32 imm64) reg. @@ -149,14 +153,14 @@ pub enum Inst { /// Integer stores: mov (b w l q) reg addr. MovRM { - size: u8, // 1, 2, 4 or 8. + size: OperandSize, // 1, 2, 4 or 8. src: Reg, dst: SyntheticAmode, }, /// Arithmetic shifts: (shl shr sar) (b w l q) imm reg. ShiftR { - size: u8, // 1, 2, 4 or 8 + size: OperandSize, // 1, 2, 4 or 8 kind: ShiftKind, /// shift count: Some(0 .. #bits-in-type - 1), or None to mean "%cl". num_bits: Option, @@ -172,7 +176,7 @@ pub enum Inst { /// Integer comparisons/tests: cmp or test (b w l q) (reg addr imm) reg. CmpRmiR { - size: u8, // 1, 2, 4 or 8 + size: OperandSize, // 1, 2, 4 or 8 opcode: CmpOpcode, src: RegMemImm, dst: Reg, @@ -184,8 +188,7 @@ pub enum Inst { /// Integer conditional move. /// Overwrites the destination register. Cmove { - /// Possible values are 2, 4 or 8. Checked in the related factory. - size: u8, + size: OperandSize, // 2, 4, or 8 cc: CC, src: RegMem, dst: Writable, @@ -588,32 +591,33 @@ impl Inst { } pub(crate) fn unary_rm_r( - size: u8, + size: OperandSize, op: UnaryRmROpcode, src: RegMem, dst: Writable, ) -> Self { src.assert_regclass_is(RegClass::I64); debug_assert!(dst.to_reg().get_class() == RegClass::I64); - debug_assert!(size == 8 || size == 4 || size == 2); + debug_assert!(size.is_size(&[ + OperandSize::Size16, + OperandSize::Size32, + OperandSize::Size64 + ])); Self::UnaryRmR { size, op, src, dst } } - pub(crate) fn not(size: u8, src: Writable) -> Inst { + pub(crate) fn not(size: OperandSize, src: Writable) -> Inst { debug_assert_eq!(src.to_reg().get_class(), RegClass::I64); - debug_assert!(size == 8 || size == 4 || size == 2 || size == 1); Inst::Not { size, src } } - pub(crate) fn neg(size: u8, src: Writable) -> Inst { + pub(crate) fn neg(size: OperandSize, src: Writable) -> Inst { debug_assert_eq!(src.to_reg().get_class(), RegClass::I64); - debug_assert!(size == 8 || size == 4 || size == 2 || size == 1); Inst::Neg { size, src } } - pub(crate) fn div(size: u8, signed: bool, divisor: RegMem) -> Inst { + pub(crate) fn div(size: OperandSize, signed: bool, divisor: RegMem) -> Inst { divisor.assert_regclass_is(RegClass::I64); - debug_assert!(size == 8 || size == 4 || size == 2 || size == 1); Inst::Div { size, signed, @@ -621,19 +625,22 @@ impl Inst { } } - pub(crate) fn mul_hi(size: u8, signed: bool, rhs: RegMem) -> Inst { + pub(crate) fn mul_hi(size: OperandSize, signed: bool, rhs: RegMem) -> Inst { + debug_assert!(size.is_size(&[ + OperandSize::Size16, + OperandSize::Size32, + OperandSize::Size64 + ])); rhs.assert_regclass_is(RegClass::I64); - debug_assert!(size == 8 || size == 4 || size == 2 || size == 1); Inst::MulHi { size, signed, rhs } } pub(crate) fn checked_div_or_rem_seq( kind: DivOrRemKind, - size: u8, + size: OperandSize, divisor: Writable, tmp: Option>, ) -> Inst { - debug_assert!(size == 8 || size == 4 || size == 2 || size == 1); debug_assert!(divisor.to_reg().get_class() == RegClass::I64); debug_assert!(tmp .map(|tmp| tmp.to_reg().get_class() == RegClass::I64) @@ -646,8 +653,7 @@ impl Inst { } } - pub(crate) fn sign_extend_data(size: u8) -> Inst { - debug_assert!(size == 8 || size == 4 || size == 2 || size == 1); + pub(crate) fn sign_extend_data(size: OperandSize) -> Inst { Inst::SignExtendData { size } } @@ -889,12 +895,7 @@ impl Inst { } } - pub(crate) fn mov_r_m( - size: u8, // 1, 2, 4 or 8 - src: Reg, - dst: impl Into, - ) -> Inst { - debug_assert!(size == 8 || size == 4 || size == 2 || size == 1); + pub(crate) fn mov_r_m(size: OperandSize, src: Reg, dst: impl Into) -> Inst { debug_assert!(src.get_class() == RegClass::I64); Inst::MovRM { size, @@ -912,14 +913,13 @@ impl Inst { } pub(crate) fn shift_r( - size: u8, + size: OperandSize, kind: ShiftKind, num_bits: Option, dst: Writable, ) -> Inst { - debug_assert!(size == 8 || size == 4 || size == 2 || size == 1); debug_assert!(if let Some(num_bits) = num_bits { - num_bits < size * 8 + num_bits < size.to_bits() } else { true }); @@ -934,13 +934,8 @@ impl Inst { /// Does a comparison of dst - src for operands of size `size`, as stated by the machine /// instruction semantics. Be careful with the order of parameters! - pub(crate) fn cmp_rmi_r( - size: u8, // 1, 2, 4 or 8 - src: RegMemImm, - dst: Reg, - ) -> Inst { + pub(crate) fn cmp_rmi_r(size: OperandSize, src: RegMemImm, dst: Reg) -> Inst { src.assert_regclass_is(RegClass::I64); - debug_assert!(size == 8 || size == 4 || size == 2 || size == 1); debug_assert_eq!(dst.get_class(), RegClass::I64); Inst::CmpRmiR { size, @@ -951,13 +946,8 @@ impl Inst { } /// Does a comparison of dst & src for operands of size `size`. - pub(crate) fn test_rmi_r( - size: u8, // 1, 2, 4 or 8 - src: RegMemImm, - dst: Reg, - ) -> Inst { + pub(crate) fn test_rmi_r(size: OperandSize, src: RegMemImm, dst: Reg) -> Inst { src.assert_regclass_is(RegClass::I64); - debug_assert!(size == 8 || size == 4 || size == 2 || size == 1); debug_assert_eq!(dst.get_class(), RegClass::I64); Inst::CmpRmiR { size, @@ -978,8 +968,12 @@ impl Inst { Inst::Setcc { cc, dst } } - pub(crate) fn cmove(size: u8, cc: CC, src: RegMem, dst: Writable) -> Inst { - debug_assert!(size == 8 || size == 4 || size == 2); + pub(crate) fn cmove(size: OperandSize, cc: CC, src: RegMem, dst: Writable) -> Inst { + debug_assert!(size.is_size(&[ + OperandSize::Size16, + OperandSize::Size32, + OperandSize::Size64 + ])); debug_assert!(dst.to_reg().get_class() == RegClass::I64); Inst::Cmove { size, cc, src, dst } } @@ -1127,7 +1121,7 @@ impl Inst { RegClass::I64 => { // Always store the full register, to ensure that the high bits are properly set // when doing a full reload. - Inst::mov_r_m(8 /* bytes */, from_reg, to_addr) + Inst::mov_r_m(OperandSize::Size64, from_reg, to_addr) } RegClass::V128 => { let opcode = match ty { @@ -1293,13 +1287,12 @@ impl PrettyPrint for Inst { } } - fn suffix_bwlq(size: u8) -> String { + fn suffix_bwlq(size: OperandSize) -> String { match size { - 1 => "b".to_string(), - 2 => "w".to_string(), - 4 => "l".to_string(), - 8 => "q".to_string(), - _ => panic!("Inst(x64).show.suffixBWLQ: size={}", size), + OperandSize::Size8 => "b".to_string(), + OperandSize::Size16 => "w".to_string(), + OperandSize::Size32 => "l".to_string(), + OperandSize::Size64 => "q".to_string(), } } @@ -1321,20 +1314,20 @@ impl PrettyPrint for Inst { Inst::UnaryRmR { src, dst, op, size } => format!( "{} {}, {}", ljustify2(op.to_string(), suffix_bwlq(*size)), - src.show_rru_sized(mb_rru, *size), - show_ireg_sized(dst.to_reg(), mb_rru, *size), + src.show_rru_sized(mb_rru, size.to_bytes()), + show_ireg_sized(dst.to_reg(), mb_rru, size.to_bytes()), ), Inst::Not { size, src } => format!( "{} {}", ljustify2("not".to_string(), suffix_bwlq(*size)), - show_ireg_sized(src.to_reg(), mb_rru, *size) + show_ireg_sized(src.to_reg(), mb_rru, size.to_bytes()) ), Inst::Neg { size, src } => format!( "{} {}", ljustify2("neg".to_string(), suffix_bwlq(*size)), - show_ireg_sized(src.to_reg(), mb_rru, *size) + show_ireg_sized(src.to_reg(), mb_rru, size.to_bytes()) ), Inst::Div { @@ -1349,7 +1342,7 @@ impl PrettyPrint for Inst { } else { "div".into() }), - divisor.show_rru_sized(mb_rru, *size) + divisor.show_rru_sized(mb_rru, size.to_bytes()) ), Inst::MulHi { @@ -1361,7 +1354,7 @@ impl PrettyPrint for Inst { } else { "mul".to_string() }), - rhs.show_rru_sized(mb_rru, *size) + rhs.show_rru_sized(mb_rru, size.to_bytes()) ), Inst::CheckedDivOrRemSeq { @@ -1377,15 +1370,14 @@ impl PrettyPrint for Inst { DivOrRemKind::SignedRem => "srem", DivOrRemKind::UnsignedRem => "urem", }, - show_ireg_sized(divisor.to_reg(), mb_rru, *size), + show_ireg_sized(divisor.to_reg(), mb_rru, size.to_bytes()), ), Inst::SignExtendData { size } => match size { - 1 => "cbw", - 2 => "cwd", - 4 => "cdq", - 8 => "cqo", - _ => unreachable!(), + OperandSize::Size8 => "cbw", + OperandSize::Size16 => "cwd", + OperandSize::Size32 => "cdq", + OperandSize::Size64 => "cqo", } .into(), @@ -1611,7 +1603,7 @@ impl PrettyPrint for Inst { Inst::MovRM { size, src, dst, .. } => format!( "{} {}, {}", ljustify2("mov".to_string(), suffix_bwlq(*size)), - show_ireg_sized(*src, mb_rru, *size), + show_ireg_sized(*src, mb_rru, size.to_bytes()), dst.show_rru(mb_rru) ), @@ -1624,14 +1616,14 @@ impl PrettyPrint for Inst { None => format!( "{} %cl, {}", ljustify2(kind.to_string(), suffix_bwlq(*size)), - show_ireg_sized(dst.to_reg(), mb_rru, *size) + show_ireg_sized(dst.to_reg(), mb_rru, size.to_bytes()) ), Some(num_bits) => format!( "{} ${}, {}", ljustify2(kind.to_string(), suffix_bwlq(*size)), num_bits, - show_ireg_sized(dst.to_reg(), mb_rru, *size) + show_ireg_sized(dst.to_reg(), mb_rru, size.to_bytes()) ), }, @@ -1655,8 +1647,8 @@ impl PrettyPrint for Inst { format!( "{} {}, {}", ljustify2(op.to_string(), suffix_bwlq(*size)), - src.show_rru_sized(mb_rru, *size), - show_ireg_sized(*dst, mb_rru, *size) + src.show_rru_sized(mb_rru, size.to_bytes()), + show_ireg_sized(*dst, mb_rru, size.to_bytes()) ) } @@ -1669,8 +1661,8 @@ impl PrettyPrint for Inst { Inst::Cmove { size, cc, src, dst } => format!( "{} {}, {}", ljustify(format!("cmov{}{}", cc.to_string(), suffix_bwlq(*size))), - src.show_rru_sized(mb_rru, *size), - show_ireg_sized(dst.to_reg(), mb_rru, *size) + src.show_rru_sized(mb_rru, size.to_bytes()), + show_ireg_sized(dst.to_reg(), mb_rru, size.to_bytes()) ), Inst::XmmCmove { @@ -1758,7 +1750,7 @@ impl PrettyPrint for Inst { let size = ty.bytes() as u8; format!( "lock cmpxchg{} {}, {}", - suffix_bwlq(size), + suffix_bwlq(OperandSize::from_bytes(size as u32)), show_ireg_sized(*src, mb_rru, size), dst.show_rru(mb_rru) ) @@ -1828,7 +1820,7 @@ fn x64_get_regs(inst: &Inst, collector: &mut RegUsageCollector) { } Inst::Div { size, divisor, .. } => { collector.add_mod(Writable::from_reg(regs::rax())); - if *size == 1 { + if *size == OperandSize::Size8 { collector.add_def(Writable::from_reg(regs::rdx())); } else { collector.add_mod(Writable::from_reg(regs::rdx())); @@ -1852,12 +1844,11 @@ fn x64_get_regs(inst: &Inst, collector: &mut RegUsageCollector) { } } Inst::SignExtendData { size } => match size { - 1 => collector.add_mod(Writable::from_reg(regs::rax())), - 2 | 4 | 8 => { + OperandSize::Size8 => collector.add_mod(Writable::from_reg(regs::rax())), + _ => { collector.add_use(regs::rax()); collector.add_def(Writable::from_reg(regs::rdx())); } - _ => unreachable!(), }, Inst::UnaryRmR { src, dst, .. } | Inst::XmmUnaryRmR { src, dst, .. } => { src.get_regs_as_uses(collector); @@ -2547,7 +2538,7 @@ impl MachInst for Inst { match self { Self::VirtualSPOffsetAdj { offset } => Some(MachInstStackOpInfo::NomSPAdj(*offset)), Self::MovRM { - size: 8, + size: OperandSize::Size8, src, dst: SyntheticAmode::NominalSPOffset { simm32 }, } => Some(MachInstStackOpInfo::StoreNomSPOff(*src, *simm32 as i64)), diff --git a/cranelift/codegen/src/isa/x64/lower.rs b/cranelift/codegen/src/isa/x64/lower.rs index 1319ac2f94..5e9a8e826d 100644 --- a/cranelift/codegen/src/isa/x64/lower.rs +++ b/cranelift/codegen/src/isa/x64/lower.rs @@ -399,9 +399,9 @@ fn emit_cmp>(ctx: &mut C, insn: IRInst, cc: IntCC) -> IntC let rhs_hi = RegMemImm::reg(rhs.regs()[1]); match cc { IntCC::Equal => { - ctx.emit(Inst::cmp_rmi_r(8, rhs_hi, lhs_hi)); + ctx.emit(Inst::cmp_rmi_r(OperandSize::Size64, rhs_hi, lhs_hi)); ctx.emit(Inst::setcc(CC::Z, cmp1)); - ctx.emit(Inst::cmp_rmi_r(8, rhs_lo, lhs_lo)); + ctx.emit(Inst::cmp_rmi_r(OperandSize::Size64, rhs_lo, lhs_lo)); ctx.emit(Inst::setcc(CC::Z, cmp2)); ctx.emit(Inst::alu_rmi_r( true, @@ -418,9 +418,9 @@ fn emit_cmp>(ctx: &mut C, insn: IRInst, cc: IntCC) -> IntC IntCC::NotEqual } IntCC::NotEqual => { - ctx.emit(Inst::cmp_rmi_r(8, rhs_hi, lhs_hi)); + ctx.emit(Inst::cmp_rmi_r(OperandSize::Size64, rhs_hi, lhs_hi)); ctx.emit(Inst::setcc(CC::NZ, cmp1)); - ctx.emit(Inst::cmp_rmi_r(8, rhs_lo, lhs_lo)); + ctx.emit(Inst::cmp_rmi_r(OperandSize::Size64, rhs_lo, lhs_lo)); ctx.emit(Inst::setcc(CC::NZ, cmp2)); ctx.emit(Inst::alu_rmi_r( true, @@ -447,10 +447,10 @@ fn emit_cmp>(ctx: &mut C, insn: IRInst, cc: IntCC) -> IntC // Result = (lhs_hi <> rhs_hi) || // (lhs_hi == rhs_hi && lhs_lo <> rhs_lo) let cmp3 = ctx.alloc_tmp(types::I64).only_reg().unwrap(); - ctx.emit(Inst::cmp_rmi_r(8, rhs_hi, lhs_hi)); + ctx.emit(Inst::cmp_rmi_r(OperandSize::Size64, rhs_hi, lhs_hi)); ctx.emit(Inst::setcc(CC::from_intcc(cc.without_equal()), cmp1)); ctx.emit(Inst::setcc(CC::Z, cmp2)); - ctx.emit(Inst::cmp_rmi_r(8, rhs_lo, lhs_lo)); + ctx.emit(Inst::cmp_rmi_r(OperandSize::Size64, rhs_lo, lhs_lo)); ctx.emit(Inst::setcc(CC::from_intcc(cc.unsigned()), cmp3)); ctx.emit(Inst::alu_rmi_r( true, @@ -488,7 +488,11 @@ fn emit_cmp>(ctx: &mut C, insn: IRInst, cc: IntCC) -> IntC // Cranelift's icmp semantics want to compare lhs - rhs, while Intel gives // us dst - src at the machine instruction level, so invert operands. - ctx.emit(Inst::cmp_rmi_r(ty.bytes() as u8, RegMemImm::reg(rhs), lhs)); + ctx.emit(Inst::cmp_rmi_r( + OperandSize::from_ty(ty), + RegMemImm::reg(rhs), + lhs, + )); cc } } @@ -612,7 +616,7 @@ fn emit_bitrev>(ctx: &mut C, src: Reg, dst: Writable, )); // tmp1 = src >> 1 ctx.emit(Inst::shift_r( - 8, + OperandSize::Size64, ShiftKind::ShiftRightLogical, Some(1), tmp1, @@ -632,7 +636,12 @@ fn emit_bitrev>(ctx: &mut C, src: Reg, dst: Writable, tmp2, )); // tmp2 = (src & 0b0101..) << 1 - ctx.emit(Inst::shift_r(8, ShiftKind::ShiftLeft, Some(1), tmp2)); + ctx.emit(Inst::shift_r( + OperandSize::Size64, + ShiftKind::ShiftLeft, + Some(1), + tmp2, + )); // tmp0 = (src >> 1) & 0b0101.. | (src & 0b0101..) << 1 ctx.emit(Inst::gen_move(tmp0, tmp2.to_reg(), types::I64)); ctx.emit(Inst::alu_rmi_r( @@ -650,7 +659,7 @@ fn emit_bitrev>(ctx: &mut C, src: Reg, dst: Writable, tmp2, )); ctx.emit(Inst::shift_r( - 8, + OperandSize::Size64, ShiftKind::ShiftRightLogical, Some(2), tmp1, @@ -667,7 +676,12 @@ fn emit_bitrev>(ctx: &mut C, src: Reg, dst: Writable, RegMemImm::reg(tmp0.to_reg()), tmp2, )); - ctx.emit(Inst::shift_r(8, ShiftKind::ShiftLeft, Some(2), tmp2)); + ctx.emit(Inst::shift_r( + OperandSize::Size64, + ShiftKind::ShiftLeft, + Some(2), + tmp2, + )); ctx.emit(Inst::gen_move(tmp0, tmp2.to_reg(), types::I64)); ctx.emit(Inst::alu_rmi_r( true, @@ -684,7 +698,7 @@ fn emit_bitrev>(ctx: &mut C, src: Reg, dst: Writable, tmp2, )); ctx.emit(Inst::shift_r( - 8, + OperandSize::Size64, ShiftKind::ShiftRightLogical, Some(4), tmp1, @@ -701,7 +715,12 @@ fn emit_bitrev>(ctx: &mut C, src: Reg, dst: Writable, RegMemImm::reg(tmp0.to_reg()), tmp2, )); - ctx.emit(Inst::shift_r(8, ShiftKind::ShiftLeft, Some(4), tmp2)); + ctx.emit(Inst::shift_r( + OperandSize::Size64, + ShiftKind::ShiftLeft, + Some(4), + tmp2, + )); ctx.emit(Inst::gen_move(tmp0, tmp2.to_reg(), types::I64)); ctx.emit(Inst::alu_rmi_r( true, @@ -719,7 +738,7 @@ fn emit_bitrev>(ctx: &mut C, src: Reg, dst: Writable, tmp2, )); ctx.emit(Inst::shift_r( - 8, + OperandSize::Size64, ShiftKind::ShiftRightLogical, Some(8), tmp1, @@ -736,7 +755,12 @@ fn emit_bitrev>(ctx: &mut C, src: Reg, dst: Writable, RegMemImm::reg(tmp0.to_reg()), tmp2, )); - ctx.emit(Inst::shift_r(8, ShiftKind::ShiftLeft, Some(8), tmp2)); + ctx.emit(Inst::shift_r( + OperandSize::Size64, + ShiftKind::ShiftLeft, + Some(8), + tmp2, + )); ctx.emit(Inst::gen_move(tmp0, tmp2.to_reg(), types::I64)); ctx.emit(Inst::alu_rmi_r( true, @@ -755,7 +779,7 @@ fn emit_bitrev>(ctx: &mut C, src: Reg, dst: Writable, tmp2, )); ctx.emit(Inst::shift_r( - 8, + OperandSize::Size64, ShiftKind::ShiftRightLogical, Some(16), tmp1, @@ -772,7 +796,12 @@ fn emit_bitrev>(ctx: &mut C, src: Reg, dst: Writable, RegMemImm::reg(tmp0.to_reg()), tmp2, )); - ctx.emit(Inst::shift_r(8, ShiftKind::ShiftLeft, Some(16), tmp2)); + ctx.emit(Inst::shift_r( + OperandSize::Size64, + ShiftKind::ShiftLeft, + Some(16), + tmp2, + )); ctx.emit(Inst::gen_move(tmp0, tmp2.to_reg(), types::I64)); ctx.emit(Inst::alu_rmi_r( true, @@ -791,7 +820,7 @@ fn emit_bitrev>(ctx: &mut C, src: Reg, dst: Writable, tmp2, )); ctx.emit(Inst::shift_r( - 8, + OperandSize::Size64, ShiftKind::ShiftRightLogical, Some(32), tmp1, @@ -808,7 +837,12 @@ fn emit_bitrev>(ctx: &mut C, src: Reg, dst: Writable, RegMemImm::reg(tmp0.to_reg()), tmp2, )); - ctx.emit(Inst::shift_r(8, ShiftKind::ShiftLeft, Some(32), tmp2)); + ctx.emit(Inst::shift_r( + OperandSize::Size64, + ShiftKind::ShiftLeft, + Some(32), + tmp2, + )); ctx.emit(Inst::gen_move(tmp0, tmp2.to_reg(), types::I64)); ctx.emit(Inst::alu_rmi_r( true, @@ -859,7 +893,12 @@ fn emit_shl_i128>( amt_src, types::I64, )); - ctx.emit(Inst::shift_r(8, ShiftKind::ShiftLeft, None, tmp1)); + ctx.emit(Inst::shift_r( + OperandSize::Size64, + ShiftKind::ShiftLeft, + None, + tmp1, + )); ctx.emit(Inst::gen_move(tmp2, src_hi, types::I64)); ctx.emit(Inst::gen_move( @@ -867,7 +906,12 @@ fn emit_shl_i128>( amt_src, types::I64, )); - ctx.emit(Inst::shift_r(8, ShiftKind::ShiftLeft, None, tmp2)); + ctx.emit(Inst::shift_r( + OperandSize::Size64, + ShiftKind::ShiftLeft, + None, + tmp2, + )); ctx.emit(Inst::imm(OperandSize::Size64, 64, amt)); ctx.emit(Inst::alu_rmi_r( @@ -883,7 +927,12 @@ fn emit_shl_i128>( amt.to_reg(), types::I64, )); - ctx.emit(Inst::shift_r(8, ShiftKind::ShiftRightLogical, None, tmp3)); + ctx.emit(Inst::shift_r( + OperandSize::Size64, + ShiftKind::ShiftRightLogical, + None, + tmp3, + )); ctx.emit(Inst::alu_rmi_r( true, @@ -915,9 +964,24 @@ fn emit_shl_i128>( RegMemImm::imm(64), amt, )); - ctx.emit(Inst::cmove(8, CC::Z, RegMem::reg(tmp3.to_reg()), dst_hi)); - ctx.emit(Inst::cmove(8, CC::Z, RegMem::reg(tmp1.to_reg()), dst_lo)); - ctx.emit(Inst::cmove(8, CC::NZ, RegMem::reg(tmp1.to_reg()), dst_hi)); + ctx.emit(Inst::cmove( + OperandSize::Size64, + CC::Z, + RegMem::reg(tmp3.to_reg()), + dst_hi, + )); + ctx.emit(Inst::cmove( + OperandSize::Size64, + CC::Z, + RegMem::reg(tmp1.to_reg()), + dst_lo, + )); + ctx.emit(Inst::cmove( + OperandSize::Size64, + CC::NZ, + RegMem::reg(tmp1.to_reg()), + dst_hi, + )); } fn emit_shr_i128>( @@ -969,7 +1033,7 @@ fn emit_shr_i128>( amt_src, types::I64, )); - ctx.emit(Inst::shift_r(8, shift_kind, None, tmp1)); + ctx.emit(Inst::shift_r(OperandSize::Size64, shift_kind, None, tmp1)); ctx.emit(Inst::gen_move(tmp2, src_lo, types::I64)); ctx.emit(Inst::gen_move( @@ -977,7 +1041,7 @@ fn emit_shr_i128>( amt_src, types::I64, )); - ctx.emit(Inst::shift_r(8, shift_kind, None, tmp2)); + ctx.emit(Inst::shift_r(OperandSize::Size64, shift_kind, None, tmp2)); ctx.emit(Inst::imm(OperandSize::Size64, 64, amt)); ctx.emit(Inst::alu_rmi_r( @@ -993,7 +1057,12 @@ fn emit_shr_i128>( amt.to_reg(), types::I64, )); - ctx.emit(Inst::shift_r(8, ShiftKind::ShiftLeft, None, tmp3)); + ctx.emit(Inst::shift_r( + OperandSize::Size64, + ShiftKind::ShiftLeft, + None, + tmp3, + )); ctx.emit(Inst::alu_rmi_r( true, @@ -1005,7 +1074,7 @@ fn emit_shr_i128>( if is_signed { ctx.emit(Inst::gen_move(dst_hi, src_hi, types::I64)); ctx.emit(Inst::shift_r( - 8, + OperandSize::Size64, ShiftKind::ShiftRightArithmetic, Some(63), dst_hi, @@ -1035,9 +1104,24 @@ fn emit_shr_i128>( RegMemImm::imm(64), amt, )); - ctx.emit(Inst::cmove(8, CC::Z, RegMem::reg(tmp1.to_reg()), dst_hi)); - ctx.emit(Inst::cmove(8, CC::Z, RegMem::reg(tmp3.to_reg()), dst_lo)); - ctx.emit(Inst::cmove(8, CC::NZ, RegMem::reg(tmp1.to_reg()), dst_lo)); + ctx.emit(Inst::cmove( + OperandSize::Size64, + CC::Z, + RegMem::reg(tmp1.to_reg()), + dst_hi, + )); + ctx.emit(Inst::cmove( + OperandSize::Size64, + CC::Z, + RegMem::reg(tmp3.to_reg()), + dst_lo, + )); + ctx.emit(Inst::cmove( + OperandSize::Size64, + CC::NZ, + RegMem::reg(tmp1.to_reg()), + dst_lo, + )); } fn make_libcall_sig>( @@ -1249,7 +1333,12 @@ fn emit_cmoves>( let size = size / src.len() as u8; let size = u8::max(size, 4); // at least 32 bits for (dst, src) in dst.regs().iter().zip(src.regs().iter()) { - ctx.emit(Inst::cmove(size, cc, RegMem::reg(*src), *dst)); + ctx.emit(Inst::cmove( + OperandSize::from_bytes(size.into()), + cc, + RegMem::reg(*src), + *dst, + )); } } @@ -1262,28 +1351,24 @@ fn emit_clz>( ) { let src = RegMem::reg(src); let tmp = ctx.alloc_tmp(ty).only_reg().unwrap(); - ctx.emit(Inst::imm( - OperandSize::from_bytes(ty.bytes()), - u64::max_value(), - dst, - )); + ctx.emit(Inst::imm(OperandSize::from_ty(ty), u64::max_value(), dst)); ctx.emit(Inst::unary_rm_r( - ty.bytes() as u8, + OperandSize::from_ty(ty), UnaryRmROpcode::Bsr, src, tmp, )); ctx.emit(Inst::cmove( - ty.bytes() as u8, + OperandSize::from_ty(ty), CC::Z, RegMem::reg(dst.to_reg()), tmp, )); ctx.emit(Inst::imm( - OperandSize::from_bytes(ty.bytes()), + OperandSize::from_ty(ty), orig_ty.bits() as u64 - 1, dst, )); @@ -1308,14 +1393,14 @@ fn emit_ctz>( ctx.emit(Inst::imm(OperandSize::Size32, orig_ty.bits() as u64, tmp)); ctx.emit(Inst::unary_rm_r( - ty.bytes() as u8, + OperandSize::from_ty(ty), UnaryRmROpcode::Bsf, src, dst, )); ctx.emit(Inst::cmove( - ty.bytes() as u8, + OperandSize::from_ty(ty), CC::Z, RegMem::reg(tmp.to_reg()), dst, @@ -1630,7 +1715,7 @@ fn lower_insn_to_regs>( types::I64, )); ctx.emit(Inst::mul_hi( - /* size = */ 8, + OperandSize::Size64, /* signed = */ false, RegMem::reg(rhs.regs()[0]), )); @@ -1764,7 +1849,6 @@ fn lower_insn_to_regs>( Opcode::Bnot => { let ty = ty.unwrap(); - let size = ty.bytes() as u8; if ty.is_vector() { let src = put_input_in_reg(ctx, inputs[0]); @@ -1777,16 +1861,16 @@ fn lower_insn_to_regs>( let src = put_input_in_regs(ctx, inputs[0]); let dst = get_output_reg(ctx, outputs[0]); ctx.emit(Inst::gen_move(dst.regs()[0], src.regs()[0], types::I64)); - ctx.emit(Inst::not(8, dst.regs()[0])); + ctx.emit(Inst::not(OperandSize::Size64, dst.regs()[0])); ctx.emit(Inst::gen_move(dst.regs()[1], src.regs()[1], types::I64)); - ctx.emit(Inst::not(8, dst.regs()[1])); + ctx.emit(Inst::not(OperandSize::Size64, dst.regs()[1])); } else if ty.is_bool() { unimplemented!("bool bnot") } else { let src = put_input_in_reg(ctx, inputs[0]); let dst = get_output_reg(ctx, outputs[0]).only_reg().unwrap(); ctx.emit(Inst::gen_move(dst, src, ty)); - ctx.emit(Inst::not(size, dst)); + ctx.emit(Inst::not(OperandSize::from_ty(ty), dst)); } } @@ -1825,23 +1909,25 @@ fn lower_insn_to_regs>( // This implementation uses the last two encoding methods. let (size, lhs) = match dst_ty { types::I8 | types::I16 => match op { - Opcode::Ishl => (4, put_input_in_reg(ctx, inputs[0])), + Opcode::Ishl => (OperandSize::Size32, put_input_in_reg(ctx, inputs[0])), Opcode::Ushr => ( - 4, + OperandSize::Size32, extend_input_to_reg(ctx, inputs[0], ExtSpec::ZeroExtendTo32), ), Opcode::Sshr => ( - 4, + OperandSize::Size32, extend_input_to_reg(ctx, inputs[0], ExtSpec::SignExtendTo32), ), - Opcode::Rotl | Opcode::Rotr => { - (dst_ty.bytes() as u8, put_input_in_reg(ctx, inputs[0])) - } + Opcode::Rotl | Opcode::Rotr => ( + OperandSize::from_ty(dst_ty), + put_input_in_reg(ctx, inputs[0]), + ), _ => unreachable!(), }, - types::I32 | types::I64 => { - (dst_ty.bytes() as u8, put_input_in_reg(ctx, inputs[0])) - } + types::I32 | types::I64 => ( + OperandSize::from_ty(dst_ty), + put_input_in_reg(ctx, inputs[0]), + ), _ => unreachable!("unhandled output type for shift/rotates: {}", dst_ty), }; @@ -2048,7 +2134,12 @@ fn lower_insn_to_regs>( base_mask_address, )); ctx.emit(Inst::gen_move(mask_offset, reg, types::I64)); - ctx.emit(Inst::shift_r(8, ShiftKind::ShiftLeft, Some(4), mask_offset)); + ctx.emit(Inst::shift_r( + OperandSize::Size64, + ShiftKind::ShiftLeft, + Some(4), + mask_offset, + )); Amode::imm_reg_reg_shift( 0, base_mask_address.to_reg(), @@ -2170,12 +2261,17 @@ fn lower_insn_to_regs>( if let Some(shift_by) = ctx.get_input_as_source_or_const(insn, 1).constant { // Mask the shift amount according to Cranelift's semantics. let shift_by = (shift_by as u8) & (types::I64.bits() as u8 - 1); - ctx.emit(Inst::shift_r(8, kind, Some(shift_by), reg)); + ctx.emit(Inst::shift_r( + OperandSize::Size64, + kind, + Some(shift_by), + reg, + )); } else { let dynamic_shift_by = put_input_in_reg(ctx, inputs[1]); let w_rcx = Writable::from_reg(regs::rcx()); ctx.emit(Inst::mov_r_r(true, dynamic_shift_by, w_rcx)); - ctx.emit(Inst::shift_r(8, kind, None, reg)); + ctx.emit(Inst::shift_r(OperandSize::Size64, kind, None, reg)); }; }; shift(lower_lane); @@ -2268,10 +2364,9 @@ fn lower_insn_to_regs>( dst, )); } else { - let size = ty.bytes() as u8; let src = put_input_in_reg(ctx, inputs[0]); ctx.emit(Inst::gen_move(dst, src, ty)); - ctx.emit(Inst::neg(size, dst)); + ctx.emit(Inst::neg(OperandSize::from_ty(ty), dst)); } } @@ -2285,7 +2380,7 @@ fn lower_insn_to_regs>( let src = input_to_reg_mem(ctx, inputs[0]); let dst = get_output_reg(ctx, outputs[0]).only_reg().unwrap(); ctx.emit(Inst::unary_rm_r( - orig_ty.bytes() as u8, + OperandSize::from_ty(orig_ty), UnaryRmROpcode::Lzcnt, src, dst, @@ -2320,8 +2415,17 @@ fn lower_insn_to_regs>( RegMemImm::imm(64), dst, )); - ctx.emit(Inst::cmp_rmi_r(8, RegMemImm::imm(64), tmp1.to_reg())); - ctx.emit(Inst::cmove(8, CC::NZ, RegMem::reg(tmp1.to_reg()), dst)); + ctx.emit(Inst::cmp_rmi_r( + OperandSize::Size64, + RegMemImm::imm(64), + tmp1.to_reg(), + )); + ctx.emit(Inst::cmove( + OperandSize::Size64, + CC::NZ, + RegMem::reg(tmp1.to_reg()), + dst, + )); ctx.emit(Inst::alu_rmi_r( true, AluRmiROpcode::Xor, @@ -2355,7 +2459,7 @@ fn lower_insn_to_regs>( let src = input_to_reg_mem(ctx, inputs[0]); let dst = get_output_reg(ctx, outputs[0]).only_reg().unwrap(); ctx.emit(Inst::unary_rm_r( - orig_ty.bytes() as u8, + OperandSize::from_ty(orig_ty), UnaryRmROpcode::Tzcnt, src, dst, @@ -2387,8 +2491,17 @@ fn lower_insn_to_regs>( RegMemImm::imm(64), tmp1, )); - ctx.emit(Inst::cmp_rmi_r(8, RegMemImm::imm(64), dst.to_reg())); - ctx.emit(Inst::cmove(8, CC::Z, RegMem::reg(tmp1.to_reg()), dst)); + ctx.emit(Inst::cmp_rmi_r( + OperandSize::Size64, + RegMemImm::imm(64), + dst.to_reg(), + )); + ctx.emit(Inst::cmove( + OperandSize::Size64, + CC::Z, + RegMem::reg(tmp1.to_reg()), + dst, + )); ctx.emit(Inst::alu_rmi_r( true, AluRmiROpcode::Xor, @@ -2422,7 +2535,7 @@ fn lower_insn_to_regs>( let src = input_to_reg_mem(ctx, inputs[0]); let dst = get_output_reg(ctx, outputs[0]).only_reg().unwrap(); ctx.emit(Inst::unary_rm_r( - ty.bytes() as u8, + OperandSize::from_ty(ty), UnaryRmROpcode::Popcnt, src, dst, @@ -2441,13 +2554,13 @@ fn lower_insn_to_regs>( let src_hi = srcs.regs()[1]; ctx.emit(Inst::unary_rm_r( - 8, + OperandSize::Size64, UnaryRmROpcode::Popcnt, RegMem::reg(src_lo), dst, )); ctx.emit(Inst::unary_rm_r( - 8, + OperandSize::Size64, UnaryRmROpcode::Popcnt, RegMem::reg(src_hi), tmp, @@ -2507,7 +2620,7 @@ fn lower_insn_to_regs>( // shr $1, tmp1 ctx.emit(Inst::shift_r( - 8, + OperandSize::Size64, ShiftKind::ShiftRightLogical, Some(1), tmp1, @@ -2537,7 +2650,7 @@ fn lower_insn_to_regs>( // shr $1, tmp1 ctx.emit(Inst::shift_r( - 8, + OperandSize::Size64, ShiftKind::ShiftRightLogical, Some(1), tmp1, @@ -2561,7 +2674,7 @@ fn lower_insn_to_regs>( // shr $1, tmp1 ctx.emit(Inst::shift_r( - 8, + OperandSize::Size64, ShiftKind::ShiftRightLogical, Some(1), tmp1, @@ -2587,7 +2700,12 @@ fn lower_insn_to_regs>( ctx.emit(Inst::mov64_rm_r(RegMem::reg(tmp2.to_reg()), dst)); // shr $4, dst - ctx.emit(Inst::shift_r(8, ShiftKind::ShiftRightLogical, Some(4), dst)); + ctx.emit(Inst::shift_r( + OperandSize::Size64, + ShiftKind::ShiftRightLogical, + Some(4), + dst, + )); // add tmp2, dst ctx.emit(Inst::alu_rmi_r( @@ -2621,7 +2739,7 @@ fn lower_insn_to_regs>( // shr $56, dst ctx.emit(Inst::shift_r( - 8, + OperandSize::Size64, ShiftKind::ShiftRightLogical, Some(56), dst, @@ -2638,7 +2756,7 @@ fn lower_insn_to_regs>( // shr $1, tmp1 ctx.emit(Inst::shift_r( - 4, + OperandSize::Size32, ShiftKind::ShiftRightLogical, Some(1), tmp1, @@ -2665,7 +2783,7 @@ fn lower_insn_to_regs>( // shr $1, tmp1 ctx.emit(Inst::shift_r( - 4, + OperandSize::Size32, ShiftKind::ShiftRightLogical, Some(1), tmp1, @@ -2689,7 +2807,7 @@ fn lower_insn_to_regs>( // shr $1, tmp1 ctx.emit(Inst::shift_r( - 4, + OperandSize::Size32, ShiftKind::ShiftRightLogical, Some(1), tmp1, @@ -2715,7 +2833,12 @@ fn lower_insn_to_regs>( ctx.emit(Inst::mov64_rm_r(RegMem::reg(tmp2.to_reg()), dst)); // shr $4, dst - ctx.emit(Inst::shift_r(4, ShiftKind::ShiftRightLogical, Some(4), dst)); + ctx.emit(Inst::shift_r( + OperandSize::Size32, + ShiftKind::ShiftRightLogical, + Some(4), + dst, + )); // add tmp2, dst ctx.emit(Inst::alu_rmi_r( @@ -2743,7 +2866,7 @@ fn lower_insn_to_regs>( // shr $24, dst ctx.emit(Inst::shift_r( - 4, + OperandSize::Size32, ShiftKind::ShiftRightLogical, Some(24), dst, @@ -2814,7 +2937,11 @@ fn lower_insn_to_regs>( } _ => unreachable!(), }; - ctx.emit(Inst::cmp_rmi_r(ty.bytes() as u8, RegMemImm::imm(imm), src)); + ctx.emit(Inst::cmp_rmi_r( + OperandSize::from_ty(ty), + RegMemImm::imm(imm), + src, + )); ctx.emit(Inst::setcc(CC::Z, dst)); } @@ -2861,7 +2988,7 @@ fn lower_insn_to_regs>( types::I64, )); ctx.emit(Inst::shift_r( - 8, + OperandSize::Size64, ShiftKind::ShiftRightArithmetic, Some(63), dst.regs()[1], @@ -4555,8 +4682,16 @@ fn lower_insn_to_regs>( if elem_ty == types::I128 { let srcs = put_input_in_regs(ctx, inputs[0]); - ctx.emit(Inst::mov_r_m(8, srcs.regs()[0], addr.clone())); - ctx.emit(Inst::mov_r_m(8, srcs.regs()[1], addr.offset(8))); + ctx.emit(Inst::mov_r_m( + OperandSize::Size64, + srcs.regs()[0], + addr.clone(), + )); + ctx.emit(Inst::mov_r_m( + OperandSize::Size64, + srcs.regs()[1], + addr.offset(8), + )); } else { let src = put_input_in_reg(ctx, inputs[0]); @@ -4567,7 +4702,7 @@ fn lower_insn_to_regs>( // TODO Specialize for different types: MOVUPD, MOVDQU, etc. Inst::xmm_mov_r_m(SseOpcode::Movups, src, addr) } - _ => Inst::mov_r_m(elem_ty.bytes() as u8, src, addr), + _ => Inst::mov_r_m(OperandSize::from_ty(elem_ty), src, addr), }); } } @@ -4672,7 +4807,7 @@ fn lower_insn_to_regs>( let ty_access = ctx.input_ty(insn, 0); assert!(is_valid_atomic_transaction_ty(ty_access)); - ctx.emit(Inst::mov_r_m(ty_access.bytes() as u8, data, addr)); + ctx.emit(Inst::mov_r_m(OperandSize::from_ty(ty_access), data, addr)); ctx.emit(Inst::Fence { kind: FenceKind::MFence, }); @@ -4808,7 +4943,7 @@ fn lower_insn_to_regs>( CC::from_intcc(cond_code) } else { let sel_ty = ctx.input_ty(insn, 0); - let size = ctx.input_ty(insn, 0).bytes() as u8; + let size = OperandSize::from_ty(ctx.input_ty(insn, 0)); let test = put_input_in_reg(ctx, flag_input); let test_input = if sel_ty == types::B1 { // The input is a boolean value; test the LSB for nonzero with: @@ -4891,7 +5026,7 @@ fn lower_insn_to_regs>( let is_div = kind.is_div(); let input_ty = ctx.input_ty(insn, 0); - let size = input_ty.bytes() as u8; + let size = OperandSize::from_ty(input_ty); let dividend = put_input_in_reg(ctx, inputs[0]); let dst = get_output_reg(ctx, outputs[0]).only_reg().unwrap(); @@ -4915,7 +5050,7 @@ fn lower_insn_to_regs>( let divisor_copy = ctx.alloc_tmp(types::I64).only_reg().unwrap(); ctx.emit(Inst::gen_move(divisor_copy, divisor, types::I64)); - let tmp = if op == Opcode::Sdiv && size == 8 { + let tmp = if op == Opcode::Sdiv && size == OperandSize::Size64 { Some(ctx.alloc_tmp(types::I64).only_reg().unwrap()) } else { None @@ -4959,10 +5094,10 @@ fn lower_insn_to_regs>( // The quotient is in rax. ctx.emit(Inst::gen_move(dst, regs::rax(), input_ty)); } else { - if size == 1 { + if size == OperandSize::Size8 { // The remainder is in AH. Right-shift by 8 bits then move from rax. ctx.emit(Inst::shift_r( - 8, + OperandSize::Size64, ShiftKind::ShiftRightLogical, Some(8), Writable::from_reg(regs::rax()), @@ -4977,7 +5112,6 @@ fn lower_insn_to_regs>( Opcode::Umulhi | Opcode::Smulhi => { let input_ty = ctx.input_ty(insn, 0); - let size = input_ty.bytes() as u8; let lhs = put_input_in_reg(ctx, inputs[0]); let rhs = input_to_reg_mem(ctx, inputs[1]); @@ -4992,7 +5126,7 @@ fn lower_insn_to_regs>( // Emit the actual mul or imul. let signed = op == Opcode::Smulhi; - ctx.emit(Inst::mul_hi(size, signed, rhs)); + ctx.emit(Inst::mul_hi(OperandSize::from_ty(input_ty), signed, rhs)); // Read the result from the high part (stored in %rdx). ctx.emit(Inst::gen_move(dst, regs::rdx(), input_ty)); @@ -5367,7 +5501,12 @@ fn lower_insn_to_regs>( dst, size, )); - ctx.emit(Inst::shift_r(8, ShiftKind::ShiftRightLogical, Some(8), dst)); + ctx.emit(Inst::shift_r( + OperandSize::Size64, + ShiftKind::ShiftRightLogical, + Some(8), + dst, + )); } _ => unimplemented!("unknown input type {} for {}", src_ty, op), } @@ -5562,9 +5701,17 @@ impl LowerBackend for X64Backend { }; let tmp1 = ctx.alloc_tmp(types::I64).only_reg().unwrap(); let tmp2 = ctx.alloc_tmp(types::I64).only_reg().unwrap(); - ctx.emit(Inst::cmp_rmi_r(8, RegMemImm::imm(0), src.regs()[0])); + ctx.emit(Inst::cmp_rmi_r( + OperandSize::Size64, + RegMemImm::imm(0), + src.regs()[0], + )); ctx.emit(Inst::setcc(half_cc, tmp1)); - ctx.emit(Inst::cmp_rmi_r(8, RegMemImm::imm(0), src.regs()[1])); + ctx.emit(Inst::cmp_rmi_r( + OperandSize::Size64, + RegMemImm::imm(0), + src.regs()[1], + )); ctx.emit(Inst::setcc(half_cc, tmp2)); ctx.emit(Inst::alu_rmi_r( false, @@ -5586,7 +5733,6 @@ impl LowerBackend for X64Backend { Opcode::Brnz => CC::NZ, _ => unreachable!(), }; - let size_bytes = src_ty.bytes() as u8; // See case for `Opcode::Select` above re: testing the // boolean input. let test_input = if src_ty == types::B1 { @@ -5598,7 +5744,11 @@ impl LowerBackend for X64Backend { RegMemImm::reg(src) }; - ctx.emit(Inst::test_rmi_r(size_bytes, test_input, src)); + ctx.emit(Inst::test_rmi_r( + OperandSize::from_ty(src_ty), + test_input, + src, + )); ctx.emit(Inst::jmp_cond(cc, taken, not_taken)); } else { unimplemented!("brz/brnz with non-int type {:?}", src_ty); @@ -5623,10 +5773,9 @@ impl LowerBackend for X64Backend { }, ); let cc = CC::from_intcc(ctx.data(branches[0]).cond_code().unwrap()); - let byte_size = src_ty.bytes() as u8; // Cranelift's icmp semantics want to compare lhs - rhs, while Intel gives // us dst - src at the machine instruction level, so invert operands. - ctx.emit(Inst::cmp_rmi_r(byte_size, rhs, lhs)); + ctx.emit(Inst::cmp_rmi_r(OperandSize::from_ty(src_ty), rhs, lhs)); ctx.emit(Inst::jmp_cond(cc, taken, not_taken)); } else { unimplemented!("bricmp with non-int type {:?}", src_ty); @@ -5654,7 +5803,7 @@ impl LowerBackend for X64Backend { ); let ty = ctx.input_ty(ifcmp_sp, 0); ctx.emit(Inst::cmp_rmi_r( - ty.bytes() as u8, + OperandSize::from_ty(ty), RegMemImm::reg(regs::rsp()), operand, )); @@ -5721,7 +5870,11 @@ impl LowerBackend for X64Backend { ); // Bounds-check (compute flags from idx - jt_size) and branch to default. - ctx.emit(Inst::cmp_rmi_r(4, RegMemImm::imm(jt_size), idx)); + ctx.emit(Inst::cmp_rmi_r( + OperandSize::Size32, + RegMemImm::imm(jt_size), + idx, + )); // Emit the compound instruction that does: //