A32: Implement ASIMD VDUP (ARM core register)
This commit is contained in:
parent
15ee562dd0
commit
e8c460c167
4 changed files with 45 additions and 0 deletions
|
@ -44,6 +44,7 @@ INST(vfp_VMOV_2u32_2f32, "VMOV (2xcore to 2xf32)", "cccc11000100uuuutttt10100
|
||||||
INST(vfp_VMOV_2f32_2u32, "VMOV (2xf32 to 2xcore)", "cccc11000101uuuutttt101000M1mmmm") // VFPv2
|
INST(vfp_VMOV_2f32_2u32, "VMOV (2xf32 to 2xcore)", "cccc11000101uuuutttt101000M1mmmm") // VFPv2
|
||||||
INST(vfp_VMOV_2u32_f64, "VMOV (2xcore to f64)", "cccc11000100uuuutttt101100M1mmmm") // VFPv2
|
INST(vfp_VMOV_2u32_f64, "VMOV (2xcore to f64)", "cccc11000100uuuutttt101100M1mmmm") // VFPv2
|
||||||
INST(vfp_VMOV_f64_2u32, "VMOV (f64 to 2xcore)", "cccc11000101uuuutttt101100M1mmmm") // VFPv2
|
INST(vfp_VMOV_f64_2u32, "VMOV (f64 to 2xcore)", "cccc11000101uuuutttt101100M1mmmm") // VFPv2
|
||||||
|
INST(vfp_VDUP, "VDUP (from core)", "cccc11101BQ0ddddtttt1011D0E10000") // ASIMD
|
||||||
|
|
||||||
// Floating-point system register access
|
// Floating-point system register access
|
||||||
INST(vfp_VMSR, "VMSR", "cccc111011100001tttt101000010000") // VFPv2
|
INST(vfp_VMSR, "VMSR", "cccc111011100001tttt101000010000") // VFPv2
|
||||||
|
|
|
@ -119,6 +119,16 @@ public:
|
||||||
return fmt::format("{}{}", dp_operation ? 'd' : 's', reg_num + 1);
|
return fmt::format("{}{}", dp_operation ? 'd' : 's', reg_num + 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static std::string VectorStr(bool Q, size_t base, bool bit) {
|
||||||
|
size_t reg_num;
|
||||||
|
if (Q) {
|
||||||
|
reg_num = (base >> 1) + (bit ? 8 : 0);
|
||||||
|
} else {
|
||||||
|
reg_num = base + (bit ? 16 : 0);
|
||||||
|
}
|
||||||
|
return fmt::format("{}{}", Q ? 'q' : 'd', reg_num);
|
||||||
|
}
|
||||||
|
|
||||||
static std::string CondOrTwo(Cond cond) {
|
static std::string CondOrTwo(Cond cond) {
|
||||||
return cond == Cond::NV ? "2" : CondToString(cond);
|
return cond == Cond::NV ? "2" : CondToString(cond);
|
||||||
}
|
}
|
||||||
|
@ -1337,6 +1347,11 @@ public:
|
||||||
return fmt::format("vmov{} {}, {}, {}", CondToString(cond), t, t2, FPRegStr(true, Vm, M));
|
return fmt::format("vmov{} {}, {}, {}", CondToString(cond), t, t2, FPRegStr(true, Vm, M));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
std::string vfp_VDUP(Cond cond, Imm<1> B, bool Q, size_t Vd, Reg t, bool D, Imm<1> E) {
|
||||||
|
const size_t esize = 32u >> concatenate(B, E).ZeroExtend();
|
||||||
|
return fmt::format("vdup{}.{} {}, {}", CondToString(cond), esize, VectorStr(Q, Vd, D), t);
|
||||||
|
}
|
||||||
|
|
||||||
std::string vfp_VMOV_reg(Cond cond, bool D, size_t Vd, bool sz, bool M, size_t Vm){
|
std::string vfp_VMOV_reg(Cond cond, bool D, size_t Vd, bool sz, bool M, size_t Vm){
|
||||||
return fmt::format("vmov{}.{} {}, {}", CondToString(cond), sz ? "f64" : "f32", FPRegStr(sz, Vd, D), FPRegStr(sz, Vm, M));
|
return fmt::format("vmov{}.{} {}, {}", CondToString(cond), sz ? "f64" : "f32", FPRegStr(sz, Vd, D), FPRegStr(sz, Vm, M));
|
||||||
}
|
}
|
||||||
|
|
|
@ -407,6 +407,7 @@ struct ArmTranslatorVisitor final {
|
||||||
bool vfp_VMOV_2u32_f64(Cond cond, Reg t2, Reg t, bool M, size_t Vm);
|
bool vfp_VMOV_2u32_f64(Cond cond, Reg t2, Reg t, bool M, size_t Vm);
|
||||||
bool vfp_VMOV_f64_2u32(Cond cond, Reg t2, Reg t, bool M, size_t Vm);
|
bool vfp_VMOV_f64_2u32(Cond cond, Reg t2, Reg t, bool M, size_t Vm);
|
||||||
bool vfp_VMOV_reg(Cond cond, bool D, size_t Vd, bool sz, bool M, size_t Vm);
|
bool vfp_VMOV_reg(Cond cond, bool D, size_t Vd, bool sz, bool M, size_t Vm);
|
||||||
|
bool vfp_VDUP(Cond cond, Imm<1> B, bool Q, size_t Vd, Reg t, bool D, Imm<1> E);
|
||||||
|
|
||||||
// Floating-point misc instructions
|
// Floating-point misc instructions
|
||||||
bool vfp_VABS(Cond cond, bool D, size_t Vd, bool sz, bool M, size_t Vm);
|
bool vfp_VABS(Cond cond, bool D, size_t Vd, bool sz, bool M, size_t Vm);
|
||||||
|
|
|
@ -523,6 +523,34 @@ bool ArmTranslatorVisitor::vfp_VMOV_f64_2u32(Cond cond, Reg t2, Reg t, bool M, s
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// VDUP<c>.{8,16,32} <Qd>, <Rt>
|
||||||
|
// VDUP<c>.{8,16,32} <Dd>, <Rt>
|
||||||
|
bool ArmTranslatorVisitor::vfp_VDUP(Cond cond, Imm<1> B, bool Q, size_t Vd, Reg t, bool D, Imm<1> E) {
|
||||||
|
if (!ConditionPassed(cond)) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (Q && Common::Bit<0>(Vd)) {
|
||||||
|
return UndefinedInstruction();
|
||||||
|
}
|
||||||
|
if (t == Reg::R15) {
|
||||||
|
return UnpredictableInstruction();
|
||||||
|
}
|
||||||
|
|
||||||
|
const auto d = ToVector(Q, Vd, D);
|
||||||
|
const size_t BE = concatenate(B, E).ZeroExtend();
|
||||||
|
const size_t esize = 32u >> BE;
|
||||||
|
|
||||||
|
if (BE == 0b11) {
|
||||||
|
return UndefinedInstruction();
|
||||||
|
}
|
||||||
|
|
||||||
|
const auto scalar = ir.LeastSignificant(esize, ir.GetRegister(t));
|
||||||
|
const auto result = ir.VectorBroadcast(esize, scalar);
|
||||||
|
ir.SetVector(d, result);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
// VMOV<c>.F64 <Dd>, #<imm>
|
// VMOV<c>.F64 <Dd>, #<imm>
|
||||||
// VMOV<c>.F32 <Sd>, #<imm>
|
// VMOV<c>.F32 <Sd>, #<imm>
|
||||||
bool ArmTranslatorVisitor::vfp_VMOV_imm(Cond cond, bool D, Imm<4> imm4H, size_t Vd, bool sz, Imm<4> imm4L) {
|
bool ArmTranslatorVisitor::vfp_VMOV_imm(Cond cond, bool D, Imm<4> imm4H, size_t Vd, bool sz, Imm<4> imm4L) {
|
||||||
|
|
Loading…
Reference in a new issue