diff --git a/cranelift/codegen/src/isa/aarch64/inst/emit.rs b/cranelift/codegen/src/isa/aarch64/inst/emit.rs index f19ce9e0cf..ef05a600dc 100644 --- a/cranelift/codegen/src/isa/aarch64/inst/emit.rs +++ b/cranelift/codegen/src/isa/aarch64/inst/emit.rs @@ -502,16 +502,8 @@ impl MachInstEmit for Inst { ALUOp::UDiv64 => 0b10011010_110, ALUOp::RotR32 | ALUOp::Lsr32 | ALUOp::Asr32 | ALUOp::Lsl32 => 0b00011010_110, ALUOp::RotR64 | ALUOp::Lsr64 | ALUOp::Asr64 | ALUOp::Lsl64 => 0b10011010_110, - - ALUOp::MAdd32 - | ALUOp::MAdd64 - | ALUOp::MSub32 - | ALUOp::MSub64 - | ALUOp::SMulH - | ALUOp::UMulH => { - //// RRRR ops. - panic!("Bad ALUOp {:?} in RRR form!", alu_op); - } + ALUOp::SMulH => 0b10011011_010, + ALUOp::UMulH => 0b10011011_110, }; let bit15_10 = match alu_op { ALUOp::SDiv64 => 0b000011, @@ -521,6 +513,7 @@ impl MachInstEmit for Inst { ALUOp::Asr32 | ALUOp::Asr64 => 0b001010, ALUOp::Lsl32 | ALUOp::Lsl64 => 0b001000, ALUOp::SubS64XR => 0b011000, + ALUOp::SMulH | ALUOp::UMulH => 0b011111, _ => 0b000000, }; debug_assert_ne!(writable_stack_reg(), rd); @@ -541,13 +534,10 @@ impl MachInstEmit for Inst { ra, } => { let (top11, bit15) = match alu_op { - ALUOp::MAdd32 => (0b0_00_11011_000, 0), - ALUOp::MSub32 => (0b0_00_11011_000, 1), - ALUOp::MAdd64 => (0b1_00_11011_000, 0), - ALUOp::MSub64 => (0b1_00_11011_000, 1), - ALUOp::SMulH => (0b1_00_11011_010, 0), - ALUOp::UMulH => (0b1_00_11011_110, 0), - _ => unimplemented!("{:?}", alu_op), + ALUOp3::MAdd32 => (0b0_00_11011_000, 0), + ALUOp3::MSub32 => (0b0_00_11011_000, 1), + ALUOp3::MAdd64 => (0b1_00_11011_000, 0), + ALUOp3::MSub64 => (0b1_00_11011_000, 1), }; sink.put4(enc_arith_rrrr(top11, rm, bit15, ra, rn, rd)); } @@ -1005,7 +995,7 @@ impl MachInstEmit for Inst { } } } - &Inst::Mov { rd, rm } => { + &Inst::Mov64 { rd, rm } => { assert!(rd.to_reg().get_class() == rm.get_class()); assert!(rm.get_class() == RegClass::I64); diff --git a/cranelift/codegen/src/isa/aarch64/inst/emit_tests.rs b/cranelift/codegen/src/isa/aarch64/inst/emit_tests.rs index 25fb934a0d..a629a07933 100644 --- a/cranelift/codegen/src/isa/aarch64/inst/emit_tests.rs +++ b/cranelift/codegen/src/isa/aarch64/inst/emit_tests.rs @@ -789,7 +789,7 @@ fn test_aarch64_binemit() { insns.push(( Inst::AluRRRR { - alu_op: ALUOp::MAdd32, + alu_op: ALUOp3::MAdd32, rd: writable_xreg(1), rn: xreg(2), rm: xreg(3), @@ -800,7 +800,7 @@ fn test_aarch64_binemit() { )); insns.push(( Inst::AluRRRR { - alu_op: ALUOp::MAdd64, + alu_op: ALUOp3::MAdd64, rd: writable_xreg(1), rn: xreg(2), rm: xreg(3), @@ -811,7 +811,7 @@ fn test_aarch64_binemit() { )); insns.push(( Inst::AluRRRR { - alu_op: ALUOp::MSub32, + alu_op: ALUOp3::MSub32, rd: writable_xreg(1), rn: xreg(2), rm: xreg(3), @@ -822,7 +822,7 @@ fn test_aarch64_binemit() { )); insns.push(( Inst::AluRRRR { - alu_op: ALUOp::MSub64, + alu_op: ALUOp3::MSub64, rd: writable_xreg(1), rn: xreg(2), rm: xreg(3), @@ -832,23 +832,21 @@ fn test_aarch64_binemit() { "msub x1, x2, x3, x4", )); insns.push(( - Inst::AluRRRR { + Inst::AluRRR { alu_op: ALUOp::SMulH, rd: writable_xreg(1), rn: xreg(2), rm: xreg(3), - ra: zero_reg(), }, "417C439B", "smulh x1, x2, x3", )); insns.push(( - Inst::AluRRRR { + Inst::AluRRR { alu_op: ALUOp::UMulH, rd: writable_xreg(1), rn: xreg(2), rm: xreg(3), - ra: zero_reg(), }, "417CC39B", "umulh x1, x2, x3", @@ -1654,7 +1652,7 @@ fn test_aarch64_binemit() { )); insns.push(( - Inst::Mov { + Inst::Mov64 { rd: writable_xreg(8), rm: xreg(9), }, diff --git a/cranelift/codegen/src/isa/aarch64/inst/mod.rs b/cranelift/codegen/src/isa/aarch64/inst/mod.rs index 50788300b3..e729b5ee4b 100644 --- a/cranelift/codegen/src/isa/aarch64/inst/mod.rs +++ b/cranelift/codegen/src/isa/aarch64/inst/mod.rs @@ -73,14 +73,6 @@ pub enum ALUOp { SubS64, /// Sub, setting flags, using extended registers SubS64XR, - /// Multiply-add - MAdd32, - /// Multiply-add - MAdd64, - /// Multiply-sub - MSub32, - /// Multiply-sub - MSub64, /// Signed multiply, high-word result SMulH, /// Unsigned multiply, high-word result @@ -97,6 +89,19 @@ pub enum ALUOp { Lsl64, } +/// An ALU operation with three arguments. +#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash)] +pub enum ALUOp3 { + /// Multiply-add + MAdd32, + /// Multiply-add + MAdd64, + /// Multiply-sub + MSub32, + /// Multiply-sub + MSub64, +} + /// A floating-point unit (FPU) operation with one arg. #[derive(Copy, Clone, Debug, PartialEq, Eq, Hash)] pub enum FPUOp1 { @@ -433,7 +438,7 @@ pub enum Inst { }, /// An ALU operation with three register sources and a register destination. AluRRRR { - alu_op: ALUOp, + alu_op: ALUOp3, rd: Writable, rn: Reg, rm: Reg, @@ -571,7 +576,7 @@ pub enum Inst { /// A MOV instruction. These are encoded as ORR's (AluRRR form) but we /// keep them separate at the `Inst` level for better pretty-printing /// and faster `is_move()` logic. - Mov { + Mov64 { rd: Writable, rm: Reg, }, @@ -1149,7 +1154,7 @@ impl Inst { pub fn mov(to_reg: Writable, from_reg: Reg) -> Inst { assert!(to_reg.to_reg().get_class() == from_reg.get_class()); if from_reg.get_class() == RegClass::I64 { - Inst::Mov { + Inst::Mov64 { rd: to_reg, rm: from_reg, } @@ -1458,7 +1463,7 @@ fn aarch64_get_regs(inst: &Inst, collector: &mut RegUsageCollector) { collector.add_def(rt2); pairmemarg_regs(mem, collector); } - &Inst::Mov { rd, rm } => { + &Inst::Mov64 { rd, rm } => { collector.add_def(rd); collector.add_use(rm); } @@ -1991,7 +1996,7 @@ fn aarch64_map_regs(inst: &mut Inst, mapper: &RUM) { map_def(mapper, rt2); map_pairmem(mapper, mem); } - &mut Inst::Mov { + &mut Inst::Mov64 { ref mut rd, ref mut rm, } => { @@ -2456,7 +2461,7 @@ impl MachInst for Inst { fn is_move(&self) -> Option<(Writable, Reg)> { match self { - &Inst::Mov { rd, rm } => Some((rd, rm)), + &Inst::Mov64 { rd, rm } => Some((rd, rm)), &Inst::FpuMove64 { rd, rn } => Some((rd, rn)), &Inst::FpuMove128 { rd, rn } => Some((rd, rn)), _ => None, @@ -2628,10 +2633,6 @@ impl Inst { ALUOp::SubS32 => ("subs", OperandSize::Size32), ALUOp::SubS64 => ("subs", OperandSize::Size64), ALUOp::SubS64XR => ("subs", OperandSize::Size64), - ALUOp::MAdd32 => ("madd", OperandSize::Size32), - ALUOp::MAdd64 => ("madd", OperandSize::Size64), - ALUOp::MSub32 => ("msub", OperandSize::Size32), - ALUOp::MSub64 => ("msub", OperandSize::Size64), ALUOp::SMulH => ("smulh", OperandSize::Size64), ALUOp::UMulH => ("umulh", OperandSize::Size64), ALUOp::SDiv64 => ("sdiv", OperandSize::Size64), @@ -2670,19 +2671,18 @@ impl Inst { rm, ra, } => { - let (op, size) = op_name_size(alu_op); - let four_args = alu_op != ALUOp::SMulH && alu_op != ALUOp::UMulH; + let (op, size) = match alu_op { + ALUOp3::MAdd32 => ("madd", OperandSize::Size32), + ALUOp3::MAdd64 => ("madd", OperandSize::Size64), + ALUOp3::MSub32 => ("msub", OperandSize::Size32), + ALUOp3::MSub64 => ("msub", OperandSize::Size64), + }; let rd = show_ireg_sized(rd.to_reg(), mb_rru, size); let rn = show_ireg_sized(rn, mb_rru, size); let rm = show_ireg_sized(rm, mb_rru, size); let ra = show_ireg_sized(ra, mb_rru, size); - if four_args { - format!("{} {}, {}, {}, {}", op, rd, rn, rm, ra) - } else { - // smulh and umulh have Ra "hard-wired" to the zero register - // and the canonical assembly form has only three regs. - format!("{} {}, {}, {}", op, rd, rn, rm) - } + + format!("{} {}, {}, {}, {}", op, rd, rn, rm, ra) } &Inst::AluRRImm12 { alu_op, @@ -2878,7 +2878,7 @@ impl Inst { let mem = mem.show_rru_sized(mb_rru, /* size = */ 8); format!("ldp {}, {}, {}", rt, rt2, mem) } - &Inst::Mov { rd, rm } => { + &Inst::Mov64 { rd, rm } => { let rd = rd.to_reg().show_rru(mb_rru); let rm = rm.show_rru(mb_rru); format!("mov {}, {}", rd, rm) diff --git a/cranelift/codegen/src/isa/aarch64/lower_inst.rs b/cranelift/codegen/src/isa/aarch64/lower_inst.rs index c434159916..7917f9c374 100644 --- a/cranelift/codegen/src/isa/aarch64/lower_inst.rs +++ b/cranelift/codegen/src/isa/aarch64/lower_inst.rs @@ -212,7 +212,7 @@ pub(crate) fn lower_insn_to_regs>( let rm = put_input_in_reg(ctx, inputs[1], NarrowValueMode::None); let ty = ty.unwrap(); if !ty.is_vector() { - let alu_op = choose_32_64(ty, ALUOp::MAdd32, ALUOp::MAdd64); + let alu_op = choose_32_64(ty, ALUOp3::MAdd32, ALUOp3::MAdd64); ctx.emit(Inst::AluRRRR { alu_op, rd, @@ -349,19 +349,12 @@ pub(crate) fn lower_insn_to_regs>( I64 => { let rn = put_input_in_reg(ctx, inputs[0], NarrowValueMode::None); let rm = put_input_in_reg(ctx, inputs[1], NarrowValueMode::None); - let ra = zero_reg(); let alu_op = if is_signed { ALUOp::SMulH } else { ALUOp::UMulH }; - ctx.emit(Inst::AluRRRR { - alu_op, - rd, - rn, - rm, - ra, - }); + ctx.emit(Inst::AluRRR { alu_op, rd, rn, rm }); } I32 | I16 | I8 => { let narrow_mode = if is_signed { @@ -373,7 +366,7 @@ pub(crate) fn lower_insn_to_regs>( let rm = put_input_in_reg(ctx, inputs[1], narrow_mode); let ra = zero_reg(); ctx.emit(Inst::AluRRRR { - alu_op: ALUOp::MAdd64, + alu_op: ALUOp3::MAdd64, rd, rn, rm, @@ -462,7 +455,7 @@ pub(crate) fn lower_insn_to_regs>( }); ctx.emit(Inst::AluRRRR { - alu_op: ALUOp::MSub64, + alu_op: ALUOp3::MSub64, rd: rd, rn: rd.to_reg(), rm: rm,