in erts/emulator/asmjit/x86/x86rapass.cpp [792:992]
Error X86RACFGBuilder::moveRegToStackArg(InvokeNode* invokeNode, const FuncValue& arg, const BaseReg& reg) noexcept {
DebugUtils::unused(invokeNode);
ASMJIT_ASSERT(arg.isStack());
Mem stackPtr = ptr(_pass->_sp.as<Gp>(), arg.stackOffset());
Reg r0, r1;
VirtReg* vr = cc()->virtRegById(reg.id());
uint32_t registerSize = cc()->registerSize();
uint32_t instId = 0;
uint32_t dstTypeId = arg.typeId();
uint32_t srcTypeId = vr->typeId();
switch (dstTypeId) {
case Type::kIdI64:
case Type::kIdU64:
// Extend BYTE->QWORD (GP).
if (Type::isGp8(srcTypeId)) {
r1.setRegT<Reg::kTypeGpbLo>(reg.id());
instId = (dstTypeId == Type::kIdI64 && srcTypeId == Type::kIdI8) ? Inst::kIdMovsx : Inst::kIdMovzx;
goto ExtendMovGpXQ;
}
// Extend WORD->QWORD (GP).
if (Type::isGp16(srcTypeId)) {
r1.setRegT<Reg::kTypeGpw>(reg.id());
instId = (dstTypeId == Type::kIdI64 && srcTypeId == Type::kIdI16) ? Inst::kIdMovsx : Inst::kIdMovzx;
goto ExtendMovGpXQ;
}
// Extend DWORD->QWORD (GP).
if (Type::isGp32(srcTypeId)) {
r1.setRegT<Reg::kTypeGpd>(reg.id());
instId = Inst::kIdMovsxd;
if (dstTypeId == Type::kIdI64 && srcTypeId == Type::kIdI32)
goto ExtendMovGpXQ;
else
goto ZeroExtendGpDQ;
}
// Move QWORD (GP).
if (Type::isGp64(srcTypeId)) goto MovGpQ;
if (Type::isMmx(srcTypeId)) goto MovMmQ;
if (Type::isVec(srcTypeId)) goto MovXmmQ;
break;
case Type::kIdI32:
case Type::kIdU32:
case Type::kIdI16:
case Type::kIdU16:
// DWORD <- WORD (Zero|Sign Extend).
if (Type::isGp16(srcTypeId)) {
bool isDstSigned = dstTypeId == Type::kIdI16 || dstTypeId == Type::kIdI32;
bool isSrcSigned = srcTypeId == Type::kIdI8 || srcTypeId == Type::kIdI16;
r1.setRegT<Reg::kTypeGpw>(reg.id());
instId = isDstSigned && isSrcSigned ? Inst::kIdMovsx : Inst::kIdMovzx;
goto ExtendMovGpD;
}
// DWORD <- BYTE (Zero|Sign Extend).
if (Type::isGp8(srcTypeId)) {
bool isDstSigned = dstTypeId == Type::kIdI16 || dstTypeId == Type::kIdI32;
bool isSrcSigned = srcTypeId == Type::kIdI8 || srcTypeId == Type::kIdI16;
r1.setRegT<Reg::kTypeGpbLo>(reg.id());
instId = isDstSigned && isSrcSigned ? Inst::kIdMovsx : Inst::kIdMovzx;
goto ExtendMovGpD;
}
ASMJIT_FALLTHROUGH;
case Type::kIdI8:
case Type::kIdU8:
if (Type::isInt(srcTypeId)) goto MovGpD;
if (Type::isMmx(srcTypeId)) goto MovMmD;
if (Type::isVec(srcTypeId)) goto MovXmmD;
break;
case Type::kIdMmx32:
case Type::kIdMmx64:
// Extend BYTE->QWORD (GP).
if (Type::isGp8(srcTypeId)) {
r1.setRegT<Reg::kTypeGpbLo>(reg.id());
instId = Inst::kIdMovzx;
goto ExtendMovGpXQ;
}
// Extend WORD->QWORD (GP).
if (Type::isGp16(srcTypeId)) {
r1.setRegT<Reg::kTypeGpw>(reg.id());
instId = Inst::kIdMovzx;
goto ExtendMovGpXQ;
}
if (Type::isGp32(srcTypeId)) goto ExtendMovGpDQ;
if (Type::isGp64(srcTypeId)) goto MovGpQ;
if (Type::isMmx(srcTypeId)) goto MovMmQ;
if (Type::isVec(srcTypeId)) goto MovXmmQ;
break;
case Type::kIdF32:
case Type::kIdF32x1:
if (Type::isVec(srcTypeId)) goto MovXmmD;
break;
case Type::kIdF64:
case Type::kIdF64x1:
if (Type::isVec(srcTypeId)) goto MovXmmQ;
break;
default:
if (Type::isVec(dstTypeId) && reg.as<Reg>().isVec()) {
stackPtr.setSize(Type::sizeOf(dstTypeId));
uint32_t vMovInstId = choose(Inst::kIdMovaps, Inst::kIdVmovaps);
if (Type::isVec128(dstTypeId))
r0.setRegT<Reg::kTypeXmm>(reg.id());
else if (Type::isVec256(dstTypeId))
r0.setRegT<Reg::kTypeYmm>(reg.id());
else if (Type::isVec512(dstTypeId))
r0.setRegT<Reg::kTypeZmm>(reg.id());
else
break;
return cc()->emit(vMovInstId, stackPtr, r0);
}
break;
}
return DebugUtils::errored(kErrorInvalidAssignment);
// Extend+Move Gp.
ExtendMovGpD:
stackPtr.setSize(4);
r0.setRegT<Reg::kTypeGpd>(reg.id());
ASMJIT_PROPAGATE(cc()->emit(instId, r0, r1));
ASMJIT_PROPAGATE(cc()->emit(Inst::kIdMov, stackPtr, r0));
return kErrorOk;
ExtendMovGpXQ:
if (registerSize == 8) {
stackPtr.setSize(8);
r0.setRegT<Reg::kTypeGpq>(reg.id());
ASMJIT_PROPAGATE(cc()->emit(instId, r0, r1));
ASMJIT_PROPAGATE(cc()->emit(Inst::kIdMov, stackPtr, r0));
}
else {
stackPtr.setSize(4);
r0.setRegT<Reg::kTypeGpd>(reg.id());
ASMJIT_PROPAGATE(cc()->emit(instId, r0, r1));
ExtendMovGpDQ:
ASMJIT_PROPAGATE(cc()->emit(Inst::kIdMov, stackPtr, r0));
stackPtr.addOffsetLo32(4);
ASMJIT_PROPAGATE(cc()->emit(Inst::kIdAnd, stackPtr, 0));
}
return kErrorOk;
ZeroExtendGpDQ:
stackPtr.setSize(4);
r0.setRegT<Reg::kTypeGpd>(reg.id());
goto ExtendMovGpDQ;
MovGpD:
stackPtr.setSize(4);
r0.setRegT<Reg::kTypeGpd>(reg.id());
return cc()->emit(Inst::kIdMov, stackPtr, r0);
MovGpQ:
stackPtr.setSize(8);
r0.setRegT<Reg::kTypeGpq>(reg.id());
return cc()->emit(Inst::kIdMov, stackPtr, r0);
MovMmD:
stackPtr.setSize(4);
r0.setRegT<Reg::kTypeMm>(reg.id());
return cc()->emit(choose(Inst::kIdMovd, Inst::kIdVmovd), stackPtr, r0);
MovMmQ:
stackPtr.setSize(8);
r0.setRegT<Reg::kTypeMm>(reg.id());
return cc()->emit(choose(Inst::kIdMovq, Inst::kIdVmovq), stackPtr, r0);
MovXmmD:
stackPtr.setSize(4);
r0.setRegT<Reg::kTypeXmm>(reg.id());
return cc()->emit(choose(Inst::kIdMovss, Inst::kIdVmovss), stackPtr, r0);
MovXmmQ:
stackPtr.setSize(8);
r0.setRegT<Reg::kTypeXmm>(reg.id());
return cc()->emit(choose(Inst::kIdMovlps, Inst::kIdVmovlps), stackPtr, r0);
}