void moveRR(Context* con, unsigned srcSize, lir::Register* src, unsigned dstSize, lir::Register* dst) { bool srcIsFpr = isFpr(src); bool dstIsFpr = isFpr(dst); if (srcIsFpr || dstIsFpr) { // FPR(s) involved assert(con, srcSize == dstSize); const bool dprec = srcSize == 8; if (srcIsFpr && dstIsFpr) { // FPR to FPR if (dprec) emit(con, fcpyd(fpr64(dst), fpr64(src))); // double else emit(con, fcpys(fpr32(dst), fpr32(src))); // single } else if (srcIsFpr) { // FPR to GPR if (dprec) emit(con, fmrrd(dst->low, dst->high, fpr64(src))); else emit(con, fmrs(dst->low, fpr32(src))); } else { // GPR to FPR if (dprec) emit(con, fmdrr(fpr64(dst->low), src->low, src->high)); else emit(con, fmsr(fpr32(dst), src->low)); } return; } switch (srcSize) { case 1: emit(con, lsli(dst->low, src->low, 24)); emit(con, asri(dst->low, dst->low, 24)); break; case 2: emit(con, lsli(dst->low, src->low, 16)); emit(con, asri(dst->low, dst->low, 16)); break; case 4: case 8: if (srcSize == 4 and dstSize == 8) { moveRR(con, 4, src, 4, dst); emit(con, asri(dst->high, src->low, 31)); } else if (srcSize == 8 and dstSize == 8) { lir::Register srcHigh(src->high); lir::Register dstHigh(dst->high); if (src->high == dst->low) { if (src->low == dst->high) { swapRR(con, 4, src, 4, dst); } else { moveRR(con, 4, &srcHigh, 4, &dstHigh); moveRR(con, 4, src, 4, dst); } } else { moveRR(con, 4, src, 4, dst); moveRR(con, 4, &srcHigh, 4, &dstHigh); } } else if (src->low != dst->low) { emit(con, mov(dst->low, src->low)); } break; default: abort(con); } }
std::string Move::format() const { std::stringstream ret; ret << "MOVE [" << srcLow() << ", " << srcHigh() << ") to [" << destLow() << ", " << destHigh() << ")"; return ret.str(); }