Use with_flags for 128-bith arith in aarch64
Also move the `with_flags` bits and pieces to `prelude.isle` so it can be shared between backends if necessary.
This commit is contained in:
@@ -1420,6 +1420,34 @@
|
||||
(_ Unit (emit (MInst.AluRRRR op dst src1 src2 src3))))
|
||||
(writable_reg_to_reg dst)))
|
||||
|
||||
;; Helper for emitting `adds` instructions.
|
||||
(decl add64_with_flags (Reg Reg) ProducesFlags)
|
||||
(rule (add64_with_flags src1 src2)
|
||||
(let ((dst WritableReg (temp_writable_reg $I64)))
|
||||
(ProducesFlags.ProducesFlags (MInst.AluRRR (ALUOp.AddS64) dst src1 src2)
|
||||
(writable_reg_to_reg dst))))
|
||||
|
||||
;; Helper for emitting `adc` instructions.
|
||||
(decl adc64 (Reg Reg) ConsumesFlags)
|
||||
(rule (adc64 src1 src2)
|
||||
(let ((dst WritableReg (temp_writable_reg $I64)))
|
||||
(ConsumesFlags.ConsumesFlags (MInst.AluRRR (ALUOp.Adc64) dst src1 src2)
|
||||
(writable_reg_to_reg dst))))
|
||||
|
||||
;; Helper for emitting `subs` instructions.
|
||||
(decl sub64_with_flags (Reg Reg) ProducesFlags)
|
||||
(rule (sub64_with_flags src1 src2)
|
||||
(let ((dst WritableReg (temp_writable_reg $I64)))
|
||||
(ProducesFlags.ProducesFlags (MInst.AluRRR (ALUOp.SubS64) dst src1 src2)
|
||||
(writable_reg_to_reg dst))))
|
||||
|
||||
;; Helper for emitting `sbc` instructions.
|
||||
(decl sbc64 (Reg Reg) ConsumesFlags)
|
||||
(rule (sbc64 src1 src2)
|
||||
(let ((dst WritableReg (temp_writable_reg $I64)))
|
||||
(ConsumesFlags.ConsumesFlags (MInst.AluRRR (ALUOp.Sbc64) dst src1 src2)
|
||||
(writable_reg_to_reg dst))))
|
||||
|
||||
;; Immediate value helpers ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||
|
||||
(decl imm (Type u64) Reg)
|
||||
|
||||
@@ -105,9 +105,9 @@
|
||||
)
|
||||
;; the actual addition is `adds` followed by `adc` which comprises the
|
||||
;; low/high bits of the result
|
||||
(value_regs
|
||||
(alu_rrr (ALUOp.AddS64) x_lo y_lo)
|
||||
(alu_rrr (ALUOp.Adc64) x_hi y_hi))))
|
||||
(with_flags
|
||||
(add64_with_flags x_lo y_lo)
|
||||
(adc64 x_hi y_hi))))
|
||||
|
||||
;;;; Rules for `isub` ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||
|
||||
@@ -156,6 +156,6 @@
|
||||
)
|
||||
;; the actual subtraction is `subs` followed by `sbc` which comprises
|
||||
;; the low/high bits of the result
|
||||
(value_regs
|
||||
(alu_rrr (ALUOp.SubS64) x_lo y_lo)
|
||||
(alu_rrr (ALUOp.Sbc64) x_hi y_hi))))
|
||||
(with_flags
|
||||
(sub64_with_flags x_lo y_lo)
|
||||
(sbc64 x_hi y_hi))))
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
src/clif.isle 9c0563583e5500de00ec5e226edc0547ac3ea789c8d76f1da0401c80ec619320fdc9a6f17fd76bbcac74a5894f85385c1f51c900c2b83bc9906d03d0f29bf5cb
|
||||
src/prelude.isle 6ae74a46b3b1f8099397cb8472d75359bc100a05a9bf38532cc41b423f7e600618d83bdb1f5565e0167696e94df2a18e489e6faabb6cc1b3e3af301ab8de55b8
|
||||
src/isa/aarch64/inst.isle 11e77cbb9a0f9c7779dea64db47aaa0b2a90bc1fac851dd0a7f0a37b4234c22b6543469f2a8d477116b2feab563fbf499eb71e414c6e2615e4cc8719e8c0ab1c
|
||||
src/isa/aarch64/lower.isle 5a36aa28fabb75cb281e67cf23313feaec5e7e08471af9be03253903c7e33531cf3b42c2ed57c7a1864d7dfb923adcd47971d8ad88d66a1df35ad8edb06a1f9a
|
||||
src/prelude.isle 07dff11e5630f23a6a6b3ba54513097754d8d9feed49e8eb4ccc1e874f32c9ab053dc69e49cb39a82a2f49320515741a2e544f51816c5c71fd2df21957cc0c7c
|
||||
src/isa/aarch64/inst.isle 67a43022bb2e0b8ae06b71c7c49f9b9997a9c6ca109e35f5018b9cd64105a0fe8b103943fb34ca7da45cea9db7327e00954e88606845d5ebc370bc6c3045a04f
|
||||
src/isa/aarch64/lower.isle 56c3c3f709d2ca18d91e14d8c4cec804990cfa3d85f9ce4fac4eef4861c4c159acee1b5fe6deff7d89337092b35ecf67418da7ce29e6217fa1ab47b0deaf1759
|
||||
|
||||
@@ -62,6 +62,18 @@ pub trait Context {
|
||||
fn load_constant64_full(&mut self, arg0: u64) -> Reg;
|
||||
}
|
||||
|
||||
/// Internal type ProducesFlags: defined at src/prelude.isle line 230.
|
||||
#[derive(Clone, Debug)]
|
||||
pub enum ProducesFlags {
|
||||
ProducesFlags { inst: MInst, result: Reg },
|
||||
}
|
||||
|
||||
/// Internal type ConsumesFlags: defined at src/prelude.isle line 233.
|
||||
#[derive(Clone, Debug)]
|
||||
pub enum ConsumesFlags {
|
||||
ConsumesFlags { inst: MInst, result: Reg },
|
||||
}
|
||||
|
||||
/// Internal type MInst: defined at src/isa/aarch64/inst.isle line 2.
|
||||
#[derive(Clone, Debug)]
|
||||
pub enum MInst {
|
||||
@@ -952,6 +964,98 @@ pub fn constructor_lo_reg<C: Context>(ctx: &mut C, arg0: Value) -> Option<Reg> {
|
||||
return Some(expr2_0);
|
||||
}
|
||||
|
||||
// Generated as internal constructor for term with_flags.
|
||||
pub fn constructor_with_flags<C: Context>(
|
||||
ctx: &mut C,
|
||||
arg0: &ProducesFlags,
|
||||
arg1: &ConsumesFlags,
|
||||
) -> Option<ValueRegs> {
|
||||
let pattern0_0 = arg0;
|
||||
if let &ProducesFlags::ProducesFlags {
|
||||
inst: ref pattern1_0,
|
||||
result: pattern1_1,
|
||||
} = pattern0_0
|
||||
{
|
||||
let pattern2_0 = arg1;
|
||||
if let &ConsumesFlags::ConsumesFlags {
|
||||
inst: ref pattern3_0,
|
||||
result: pattern3_1,
|
||||
} = pattern2_0
|
||||
{
|
||||
// Rule at src/prelude.isle line 243.
|
||||
let expr0_0 = C::emit(ctx, &pattern1_0);
|
||||
let expr1_0 = C::emit(ctx, &pattern3_0);
|
||||
let expr2_0 = C::value_regs(ctx, pattern1_1, pattern3_1);
|
||||
return Some(expr2_0);
|
||||
}
|
||||
}
|
||||
return None;
|
||||
}
|
||||
|
||||
// Generated as internal constructor for term with_flags_1.
|
||||
pub fn constructor_with_flags_1<C: Context>(
|
||||
ctx: &mut C,
|
||||
arg0: &ProducesFlags,
|
||||
arg1: &ConsumesFlags,
|
||||
) -> Option<Reg> {
|
||||
let pattern0_0 = arg0;
|
||||
if let &ProducesFlags::ProducesFlags {
|
||||
inst: ref pattern1_0,
|
||||
result: pattern1_1,
|
||||
} = pattern0_0
|
||||
{
|
||||
let pattern2_0 = arg1;
|
||||
if let &ConsumesFlags::ConsumesFlags {
|
||||
inst: ref pattern3_0,
|
||||
result: pattern3_1,
|
||||
} = pattern2_0
|
||||
{
|
||||
// Rule at src/prelude.isle line 251.
|
||||
let expr0_0 = C::emit(ctx, &pattern1_0);
|
||||
let expr1_0 = C::emit(ctx, &pattern3_0);
|
||||
return Some(pattern3_1);
|
||||
}
|
||||
}
|
||||
return None;
|
||||
}
|
||||
|
||||
// Generated as internal constructor for term with_flags_2.
|
||||
pub fn constructor_with_flags_2<C: Context>(
|
||||
ctx: &mut C,
|
||||
arg0: &ProducesFlags,
|
||||
arg1: &ConsumesFlags,
|
||||
arg2: &ConsumesFlags,
|
||||
) -> Option<ValueRegs> {
|
||||
let pattern0_0 = arg0;
|
||||
if let &ProducesFlags::ProducesFlags {
|
||||
inst: ref pattern1_0,
|
||||
result: pattern1_1,
|
||||
} = pattern0_0
|
||||
{
|
||||
let pattern2_0 = arg1;
|
||||
if let &ConsumesFlags::ConsumesFlags {
|
||||
inst: ref pattern3_0,
|
||||
result: pattern3_1,
|
||||
} = pattern2_0
|
||||
{
|
||||
let pattern4_0 = arg2;
|
||||
if let &ConsumesFlags::ConsumesFlags {
|
||||
inst: ref pattern5_0,
|
||||
result: pattern5_1,
|
||||
} = pattern4_0
|
||||
{
|
||||
// Rule at src/prelude.isle line 261.
|
||||
let expr0_0 = C::emit(ctx, &pattern1_0);
|
||||
let expr1_0 = C::emit(ctx, &pattern3_0);
|
||||
let expr2_0 = C::emit(ctx, &pattern5_0);
|
||||
let expr3_0 = C::value_regs(ctx, pattern3_1, pattern5_1);
|
||||
return Some(expr3_0);
|
||||
}
|
||||
}
|
||||
}
|
||||
return None;
|
||||
}
|
||||
|
||||
// Generated as internal constructor for term vector_size.
|
||||
pub fn constructor_vector_size<C: Context>(ctx: &mut C, arg0: Type) -> Option<VectorSize> {
|
||||
let pattern0_0 = arg0;
|
||||
@@ -1227,31 +1331,127 @@ pub fn constructor_alu_rrrr<C: Context>(
|
||||
return Some(expr4_0);
|
||||
}
|
||||
|
||||
// Generated as internal constructor for term add64_with_flags.
|
||||
pub fn constructor_add64_with_flags<C: Context>(
|
||||
ctx: &mut C,
|
||||
arg0: Reg,
|
||||
arg1: Reg,
|
||||
) -> Option<ProducesFlags> {
|
||||
let pattern0_0 = arg0;
|
||||
let pattern1_0 = arg1;
|
||||
// Rule at src/isa/aarch64/inst.isle line 1425.
|
||||
let expr0_0: Type = I64;
|
||||
let expr1_0 = C::temp_writable_reg(ctx, expr0_0);
|
||||
let expr2_0 = ALUOp::AddS64;
|
||||
let expr3_0 = MInst::AluRRR {
|
||||
alu_op: expr2_0,
|
||||
rd: expr1_0,
|
||||
rn: pattern0_0,
|
||||
rm: pattern1_0,
|
||||
};
|
||||
let expr4_0 = C::writable_reg_to_reg(ctx, expr1_0);
|
||||
let expr5_0 = ProducesFlags::ProducesFlags {
|
||||
inst: expr3_0,
|
||||
result: expr4_0,
|
||||
};
|
||||
return Some(expr5_0);
|
||||
}
|
||||
|
||||
// Generated as internal constructor for term adc64.
|
||||
pub fn constructor_adc64<C: Context>(ctx: &mut C, arg0: Reg, arg1: Reg) -> Option<ConsumesFlags> {
|
||||
let pattern0_0 = arg0;
|
||||
let pattern1_0 = arg1;
|
||||
// Rule at src/isa/aarch64/inst.isle line 1432.
|
||||
let expr0_0: Type = I64;
|
||||
let expr1_0 = C::temp_writable_reg(ctx, expr0_0);
|
||||
let expr2_0 = ALUOp::Adc64;
|
||||
let expr3_0 = MInst::AluRRR {
|
||||
alu_op: expr2_0,
|
||||
rd: expr1_0,
|
||||
rn: pattern0_0,
|
||||
rm: pattern1_0,
|
||||
};
|
||||
let expr4_0 = C::writable_reg_to_reg(ctx, expr1_0);
|
||||
let expr5_0 = ConsumesFlags::ConsumesFlags {
|
||||
inst: expr3_0,
|
||||
result: expr4_0,
|
||||
};
|
||||
return Some(expr5_0);
|
||||
}
|
||||
|
||||
// Generated as internal constructor for term sub64_with_flags.
|
||||
pub fn constructor_sub64_with_flags<C: Context>(
|
||||
ctx: &mut C,
|
||||
arg0: Reg,
|
||||
arg1: Reg,
|
||||
) -> Option<ProducesFlags> {
|
||||
let pattern0_0 = arg0;
|
||||
let pattern1_0 = arg1;
|
||||
// Rule at src/isa/aarch64/inst.isle line 1439.
|
||||
let expr0_0: Type = I64;
|
||||
let expr1_0 = C::temp_writable_reg(ctx, expr0_0);
|
||||
let expr2_0 = ALUOp::SubS64;
|
||||
let expr3_0 = MInst::AluRRR {
|
||||
alu_op: expr2_0,
|
||||
rd: expr1_0,
|
||||
rn: pattern0_0,
|
||||
rm: pattern1_0,
|
||||
};
|
||||
let expr4_0 = C::writable_reg_to_reg(ctx, expr1_0);
|
||||
let expr5_0 = ProducesFlags::ProducesFlags {
|
||||
inst: expr3_0,
|
||||
result: expr4_0,
|
||||
};
|
||||
return Some(expr5_0);
|
||||
}
|
||||
|
||||
// Generated as internal constructor for term sbc64.
|
||||
pub fn constructor_sbc64<C: Context>(ctx: &mut C, arg0: Reg, arg1: Reg) -> Option<ConsumesFlags> {
|
||||
let pattern0_0 = arg0;
|
||||
let pattern1_0 = arg1;
|
||||
// Rule at src/isa/aarch64/inst.isle line 1446.
|
||||
let expr0_0: Type = I64;
|
||||
let expr1_0 = C::temp_writable_reg(ctx, expr0_0);
|
||||
let expr2_0 = ALUOp::Sbc64;
|
||||
let expr3_0 = MInst::AluRRR {
|
||||
alu_op: expr2_0,
|
||||
rd: expr1_0,
|
||||
rn: pattern0_0,
|
||||
rm: pattern1_0,
|
||||
};
|
||||
let expr4_0 = C::writable_reg_to_reg(ctx, expr1_0);
|
||||
let expr5_0 = ConsumesFlags::ConsumesFlags {
|
||||
inst: expr3_0,
|
||||
result: expr4_0,
|
||||
};
|
||||
return Some(expr5_0);
|
||||
}
|
||||
|
||||
// Generated as internal constructor for term imm.
|
||||
pub fn constructor_imm<C: Context>(ctx: &mut C, arg0: Type, arg1: u64) -> Option<Reg> {
|
||||
let pattern0_0 = arg0;
|
||||
if let Some(pattern1_0) = C::integral_ty(ctx, pattern0_0) {
|
||||
let pattern2_0 = arg1;
|
||||
if let Some(pattern3_0) = C::imm_logic_from_u64(ctx, pattern2_0) {
|
||||
// Rule at src/isa/aarch64/inst.isle line 1436.
|
||||
// Rule at src/isa/aarch64/inst.isle line 1464.
|
||||
let expr0_0 = ALUOp::Orr64;
|
||||
let expr1_0 = C::zero_reg(ctx);
|
||||
let expr2_0 = constructor_alu_rr_imm_logic(ctx, &expr0_0, expr1_0, pattern3_0)?;
|
||||
return Some(expr2_0);
|
||||
}
|
||||
if let Some(pattern3_0) = C::move_wide_const_from_u64(ctx, pattern2_0) {
|
||||
// Rule at src/isa/aarch64/inst.isle line 1428.
|
||||
// Rule at src/isa/aarch64/inst.isle line 1456.
|
||||
let expr0_0 = OperandSize::Size64;
|
||||
let expr1_0 = constructor_movz(ctx, pattern3_0, &expr0_0)?;
|
||||
return Some(expr1_0);
|
||||
}
|
||||
if let Some(pattern3_0) = C::move_wide_const_from_negated_u64(ctx, pattern2_0) {
|
||||
// Rule at src/isa/aarch64/inst.isle line 1432.
|
||||
// Rule at src/isa/aarch64/inst.isle line 1460.
|
||||
let expr0_0 = OperandSize::Size64;
|
||||
let expr1_0 = constructor_movn(ctx, pattern3_0, &expr0_0)?;
|
||||
return Some(expr1_0);
|
||||
}
|
||||
// Rule at src/isa/aarch64/inst.isle line 1443.
|
||||
// Rule at src/isa/aarch64/inst.isle line 1471.
|
||||
let expr0_0 = C::load_constant64_full(ctx, pattern2_0);
|
||||
return Some(expr0_0);
|
||||
}
|
||||
@@ -1284,12 +1484,10 @@ pub fn constructor_lower<C: Context>(ctx: &mut C, arg0: Inst) -> Option<ValueReg
|
||||
let expr7_0 = C::value_regs_get(ctx, expr5_0, expr6_0);
|
||||
let expr8_0: usize = 1;
|
||||
let expr9_0 = C::value_regs_get(ctx, expr5_0, expr8_0);
|
||||
let expr10_0 = ALUOp::AddS64;
|
||||
let expr11_0 = constructor_alu_rrr(ctx, &expr10_0, expr2_0, expr7_0)?;
|
||||
let expr12_0 = ALUOp::Adc64;
|
||||
let expr13_0 = constructor_alu_rrr(ctx, &expr12_0, expr4_0, expr9_0)?;
|
||||
let expr14_0 = C::value_regs(ctx, expr11_0, expr13_0);
|
||||
return Some(expr14_0);
|
||||
let expr10_0 = constructor_add64_with_flags(ctx, expr2_0, expr7_0)?;
|
||||
let expr11_0 = constructor_adc64(ctx, expr4_0, expr9_0)?;
|
||||
let expr12_0 = constructor_with_flags(ctx, &expr10_0, &expr11_0)?;
|
||||
return Some(expr12_0);
|
||||
}
|
||||
&Opcode::Isub => {
|
||||
let (pattern7_0, pattern7_1) = C::unpack_value_array_2(ctx, &pattern5_1);
|
||||
@@ -1304,12 +1502,10 @@ pub fn constructor_lower<C: Context>(ctx: &mut C, arg0: Inst) -> Option<ValueReg
|
||||
let expr7_0 = C::value_regs_get(ctx, expr5_0, expr6_0);
|
||||
let expr8_0: usize = 1;
|
||||
let expr9_0 = C::value_regs_get(ctx, expr5_0, expr8_0);
|
||||
let expr10_0 = ALUOp::SubS64;
|
||||
let expr11_0 = constructor_alu_rrr(ctx, &expr10_0, expr2_0, expr7_0)?;
|
||||
let expr12_0 = ALUOp::Sbc64;
|
||||
let expr13_0 = constructor_alu_rrr(ctx, &expr12_0, expr4_0, expr9_0)?;
|
||||
let expr14_0 = C::value_regs(ctx, expr11_0, expr13_0);
|
||||
return Some(expr14_0);
|
||||
let expr10_0 = constructor_sub64_with_flags(ctx, expr2_0, expr7_0)?;
|
||||
let expr11_0 = constructor_sbc64(ctx, expr4_0, expr9_0)?;
|
||||
let expr12_0 = constructor_with_flags(ctx, &expr10_0, &expr11_0)?;
|
||||
return Some(expr12_0);
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user