void shuffle2(Asm& as, PhysReg s0, PhysReg s1, PhysReg d0, PhysReg d1) { if (s0 == InvalidReg && s1 == InvalidReg && d0 == InvalidReg && d1 == InvalidReg) return; assert(s0 != s1); assert(!s0.isSIMD() || s1 == InvalidReg); // never 2 XMMs assert(!d0.isSIMD() || d1 == InvalidReg); // never 2 XMMs if (d0 == s1 && d1 != InvalidReg) { assert(d0 != d1); if (d1 == s0) { as. xchgq (s1, s0); } else { as. movq (s1, d1); // save s1 first; d1 != s0 as. movq (s0, d0); } } else if (d0.isSIMD() && s0.isGP() && s1.isGP()) { // move 2 gpr to 1 xmm assert(d0 != rCgXMM0); // xmm0 is reserved for scratch as. movq_rx(s0, d0); as. movq_rx(s1, rCgXMM0); as. unpcklpd(rCgXMM0, d0); // s1 -> d0[1] } else { if (d0 != InvalidReg) emitMovRegReg(as, s0, d0); // d0 != s1 if (d1 != InvalidReg) emitMovRegReg(as, s1, d1); } }
PhysReg lookup(Vreg vreg, VregKind kind) { auto ivl = xls.intervals[vreg]; if (!ivl || vreg.isPhys()) return vreg; PhysReg reg = ivl->childAt(pos)->reg; assert((kind == VregKind::Gpr && reg.isGP()) || (kind == VregKind::Simd && reg.isSIMD()) || (kind == VregKind::Any && reg != InvalidReg)); return reg; }
// Logical register move: ensures the value in src will be in dest // after execution, but might do so in strange ways. Do not count on // being able to smash dest to a different register in the future, e.g. void emitMovRegReg(Asm& as, PhysReg srcReg, PhysReg dstReg) { assert(srcReg != InvalidReg); assert(dstReg != InvalidReg); if (srcReg == dstReg) return; if (srcReg.isGP()) { if (dstReg.isGP()) { // GP => GP as. movq(srcReg, dstReg); } else { // GP => XMM // This generates a movq x86 instruction, which zero extends // the 64-bit value in srcReg into a 128-bit XMM register as. mov_reg64_xmm(srcReg, dstReg); } } else { if (dstReg.isGP()) { // XMM => GP as. mov_xmm_reg64(srcReg, dstReg); } else { // XMM => XMM // This copies all 128 bits in XMM, // thus avoiding partial register stalls as. movdqa(srcReg, dstReg); } } }
std::string show(PhysReg r) { switch (arch()) { case Arch::X64: return r.type() == PhysReg::GP ? reg::regname(Reg64(r)) : r.type() == PhysReg::SIMD ? reg::regname(RegXMM(r)) : /* r.type() == PhysReg::SF) ? */ reg::regname(RegSF(r)); case Arch::ARM: if (r.isSF()) return "SF"; return folly::to<std::string>( r.isGP() ? (vixl::Register(r).size() == vixl::kXRegSize ? 'x' : 'w') : (vixl::FPRegister(r).size() == vixl::kSRegSize ? 's' : 'd'), ((vixl::CPURegister)r).code() ); case Arch::PPC64: return r.type() == PhysReg::GP ? ppc64_asm::reg::regname(Reg64(r)) : r.type() == PhysReg::SIMD ? ppc64_asm::reg::regname(RegXMM(r)) : /* r.type() == PhysReg::SF) ? */ ppc64_asm::reg::regname(RegSF(r)); } not_reached(); }