diff --git a/src/mapleall/maple_be/src/cg/aarch64/aarch64_cgfunc.cpp b/src/mapleall/maple_be/src/cg/aarch64/aarch64_cgfunc.cpp index fd448b6af410849a7975520c02e4e243b1efca1b..aee06045bea208c427a69ec8a48bb1987bfd47d3 100644 --- a/src/mapleall/maple_be/src/cg/aarch64/aarch64_cgfunc.cpp +++ b/src/mapleall/maple_be/src/cg/aarch64/aarch64_cgfunc.cpp @@ -2274,12 +2274,68 @@ void AArch64CGFunc::SelectBlkassignoff(BlkassignoffNode &bNode, Operand *src) IncLmbcTotalArgs(); /* copy large agg arg to offset below */ } - std::vector opndVec; - opndVec.push_back(regResult); /* result */ - opndVec.push_back(PrepareMemcpyParamOpnd(offset, *dest)); /* param 0 */ - opndVec.push_back(src); /* param 1 */ - opndVec.push_back(PrepareMemcpyParamOpnd(static_cast(static_cast(bNode.blockSize)))); /* param 2 */ - SelectLibCall("memcpy", opndVec, PTY_a64, PTY_a64); + RegOperand *param0 = PrepareMemcpyParamOpnd(offset, *dest); + RegOperand *param1 = static_cast(src); + RegOperand *param2 = PrepareMemcpyParamOpnd(bNode.blockSize); + if (bNode.blockSize > kParmMemcpySize) { + std::vector opndVec; + opndVec.push_back(regResult); /* result */ + opndVec.push_back(param0); /* param 0 */ + opndVec.push_back(src); /* param 1 */ + opndVec.push_back(param2); /* param 2 */ + SelectLibCall("memcpy", opndVec, PTY_a64, PTY_a64); + } else { + int32 copyOffset = 0; + int32 inc = 0; + bool isPair; + for (uint32 sz = bNode.blockSize; sz > 0; ) { + isPair = false; + MOperator ldOp, stOp; + if (sz >= k16ByteSize) { + sz -= k16ByteSize; + inc = k16ByteSize; + ldOp = MOP_xldp; + stOp = MOP_xstp; + isPair = true; + } else if (sz >= k8ByteSize) { + sz -= k8ByteSize; + inc = k8ByteSize; + ldOp = MOP_xldr; + stOp = MOP_xstr; + } else if (sz >= k4ByteSize) { + sz -= k4ByteSize; + inc = k4ByteSize; + ldOp = MOP_wldr; + stOp = MOP_wstr; + } else if (sz >= k2ByteSize) { + sz -= k2ByteSize; + inc = k2ByteSize; + ldOp = MOP_wldrh; + stOp = MOP_wstrh; + } else { + sz -= k1ByteSize; + inc = k1ByteSize; + ldOp = MOP_wldrb; + stOp = MOP_wstrb; + } + AArch64reg ldBaseReg = static_cast(param1->GetRegisterNumber()); + MemOperand &ldMem = CreateMemOpnd(ldBaseReg, copyOffset, k8ByteSize); + + AArch64reg stBaseReg = static_cast(param0->GetRegisterNumber()); + MemOperand &stMem = CreateMemOpnd(stBaseReg, copyOffset, k8ByteSize); + if (isPair) { + RegOperand &ldResult = CreateVirtualRegisterOperand(NewVReg(kRegTyInt, k8ByteSize)); + RegOperand &ldResult2 = CreateVirtualRegisterOperand(NewVReg(kRegTyInt, k8ByteSize)); + GetCurBB()->AppendInsn(GetCG()->BuildInstruction(ldOp, ldResult, ldResult2, ldMem)); + GetCurBB()->AppendInsn(GetCG()->BuildInstruction(stOp, ldResult, ldResult2, stMem)); + } else { + RegOperand &ldResult = CreateVirtualRegisterOperand(NewVReg(kRegTyInt, k8ByteSize)); + GetCurBB()->AppendInsn(GetCG()->BuildInstruction(ldOp, ldResult, ldMem)); + GetCurBB()->AppendInsn(GetCG()->BuildInstruction(stOp, ldResult, stMem)); + } + copyOffset += inc; + } + } } void AArch64CGFunc::SelectAggIassign(IassignNode &stmt, Operand &addrOpnd) {