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