AArch64: port load and store operations to ISLE. (#4785)
This retains `lower_amode` in the handwritten code (@akirilov-arm reports that there is an upcoming patch to port this), but tweaks it slightly to take a `Value` rather than an `Inst`.
This commit is contained in:
@@ -101,133 +101,10 @@ pub(crate) fn lower_insn_to_regs(
|
||||
| Opcode::Sload16x4
|
||||
| Opcode::Uload16x4
|
||||
| Opcode::Sload32x2
|
||||
| Opcode::Uload32x2 => {
|
||||
let sign_extend = match op {
|
||||
Opcode::Sload8 | Opcode::Sload16 | Opcode::Sload32 => true,
|
||||
_ => false,
|
||||
};
|
||||
let flags = ctx
|
||||
.memflags(insn)
|
||||
.expect("Load instruction should have memflags");
|
||||
|
||||
let out_ty = ctx.output_ty(insn, 0);
|
||||
if out_ty == I128 {
|
||||
let off = ctx.data(insn).load_store_offset().unwrap();
|
||||
let mem = lower_pair_address(ctx, &inputs[..], off);
|
||||
let dst = get_output_reg(ctx, outputs[0]);
|
||||
ctx.emit(Inst::LoadP64 {
|
||||
rt: dst.regs()[0],
|
||||
rt2: dst.regs()[1],
|
||||
mem,
|
||||
flags,
|
||||
});
|
||||
} else {
|
||||
lower_load(
|
||||
ctx,
|
||||
insn,
|
||||
&inputs[..],
|
||||
outputs[0],
|
||||
|ctx, dst, mut elem_ty, mem| {
|
||||
if elem_ty.is_dynamic_vector() {
|
||||
elem_ty = dynamic_to_fixed(elem_ty);
|
||||
}
|
||||
let rd = dst.only_reg().unwrap();
|
||||
let is_float = ty_has_float_or_vec_representation(elem_ty);
|
||||
ctx.emit(match (ty_bits(elem_ty), sign_extend, is_float) {
|
||||
(1, _, _) => Inst::ULoad8 { rd, mem, flags },
|
||||
(8, false, _) => Inst::ULoad8 { rd, mem, flags },
|
||||
(8, true, _) => Inst::SLoad8 { rd, mem, flags },
|
||||
(16, false, _) => Inst::ULoad16 { rd, mem, flags },
|
||||
(16, true, _) => Inst::SLoad16 { rd, mem, flags },
|
||||
(32, false, false) => Inst::ULoad32 { rd, mem, flags },
|
||||
(32, true, false) => Inst::SLoad32 { rd, mem, flags },
|
||||
(32, _, true) => Inst::FpuLoad32 { rd, mem, flags },
|
||||
(64, _, false) => Inst::ULoad64 { rd, mem, flags },
|
||||
// Note that we treat some of the vector loads as scalar floating-point loads,
|
||||
// which is correct in a little endian environment.
|
||||
(64, _, true) => Inst::FpuLoad64 { rd, mem, flags },
|
||||
(128, _, true) => Inst::FpuLoad128 { rd, mem, flags },
|
||||
_ => {
|
||||
return Err(CodegenError::Unsupported(format!(
|
||||
"Unsupported type in load: {:?}",
|
||||
elem_ty
|
||||
)))
|
||||
}
|
||||
});
|
||||
|
||||
let vec_extend = match op {
|
||||
Opcode::Sload8x8 => Some((VecExtendOp::Sxtl, ScalarSize::Size16)),
|
||||
Opcode::Uload8x8 => Some((VecExtendOp::Uxtl, ScalarSize::Size16)),
|
||||
Opcode::Sload16x4 => Some((VecExtendOp::Sxtl, ScalarSize::Size32)),
|
||||
Opcode::Uload16x4 => Some((VecExtendOp::Uxtl, ScalarSize::Size32)),
|
||||
Opcode::Sload32x2 => Some((VecExtendOp::Sxtl, ScalarSize::Size64)),
|
||||
Opcode::Uload32x2 => Some((VecExtendOp::Uxtl, ScalarSize::Size64)),
|
||||
_ => None,
|
||||
};
|
||||
|
||||
if let Some((t, lane_size)) = vec_extend {
|
||||
let rd = dst.only_reg().unwrap();
|
||||
ctx.emit(Inst::VecExtend {
|
||||
t,
|
||||
rd,
|
||||
rn: rd.to_reg(),
|
||||
high_half: false,
|
||||
lane_size,
|
||||
});
|
||||
}
|
||||
|
||||
Ok(())
|
||||
},
|
||||
)?;
|
||||
}
|
||||
}
|
||||
| Opcode::Uload32x2 => implemented_in_isle(ctx),
|
||||
|
||||
Opcode::Store | Opcode::Istore8 | Opcode::Istore16 | Opcode::Istore32 => {
|
||||
let off = ctx.data(insn).load_store_offset().unwrap();
|
||||
let mut elem_ty = match op {
|
||||
Opcode::Istore8 => I8,
|
||||
Opcode::Istore16 => I16,
|
||||
Opcode::Istore32 => I32,
|
||||
Opcode::Store => ctx.input_ty(insn, 0),
|
||||
_ => unreachable!(),
|
||||
};
|
||||
let is_float = ty_has_float_or_vec_representation(elem_ty);
|
||||
let flags = ctx
|
||||
.memflags(insn)
|
||||
.expect("Store instruction should have memflags");
|
||||
|
||||
let dst = put_input_in_regs(ctx, inputs[0]);
|
||||
|
||||
if elem_ty == I128 {
|
||||
let mem = lower_pair_address(ctx, &inputs[1..], off);
|
||||
ctx.emit(Inst::StoreP64 {
|
||||
rt: dst.regs()[0],
|
||||
rt2: dst.regs()[1],
|
||||
mem,
|
||||
flags,
|
||||
});
|
||||
} else {
|
||||
if elem_ty.is_dynamic_vector() {
|
||||
elem_ty = dynamic_to_fixed(elem_ty);
|
||||
}
|
||||
let rd = dst.only_reg().unwrap();
|
||||
let mem = lower_address(ctx, elem_ty, &inputs[1..], off);
|
||||
ctx.emit(match (ty_bits(elem_ty), is_float) {
|
||||
(1, _) | (8, _) => Inst::Store8 { rd, mem, flags },
|
||||
(16, _) => Inst::Store16 { rd, mem, flags },
|
||||
(32, false) => Inst::Store32 { rd, mem, flags },
|
||||
(32, true) => Inst::FpuStore32 { rd, mem, flags },
|
||||
(64, false) => Inst::Store64 { rd, mem, flags },
|
||||
(64, true) => Inst::FpuStore64 { rd, mem, flags },
|
||||
(128, _) => Inst::FpuStore128 { rd, mem, flags },
|
||||
_ => {
|
||||
return Err(CodegenError::Unsupported(format!(
|
||||
"Unsupported type in store: {:?}",
|
||||
elem_ty
|
||||
)))
|
||||
}
|
||||
});
|
||||
}
|
||||
implemented_in_isle(ctx)
|
||||
}
|
||||
|
||||
Opcode::StackAddr => implemented_in_isle(ctx),
|
||||
|
||||
Reference in New Issue
Block a user