Index: lib/Target/Mips/AsmParser/MipsAsmParser.cpp =================================================================== --- lib/Target/Mips/AsmParser/MipsAsmParser.cpp +++ lib/Target/Mips/AsmParser/MipsAsmParser.cpp @@ -179,13 +179,17 @@ bool expandJalWithRegs(MCInst &Inst, SMLoc IDLoc, SmallVectorImpl &Instructions); + bool loadImmediate(const MCOperand *ImmOp, const MCOperand *DstRegOp, + const MCOperand *SrcRegOp, bool Is32BitImm, SMLoc IDLoc, + SmallVectorImpl &Instructions); + bool expandLoadImm(MCInst &Inst, bool Is32BitImm, SMLoc IDLoc, SmallVectorImpl &Instructions); - bool expandLoadAddressImm(MCInst &Inst, SMLoc IDLoc, + bool expandLoadAddressImm(MCInst &Inst, bool Is32BitImm, SMLoc IDLoc, SmallVectorImpl &Instructions); - bool expandLoadAddressReg(MCInst &Inst, SMLoc IDLoc, + bool expandLoadAddressReg(MCInst &Inst, bool Is32BitImm, SMLoc IDLoc, SmallVectorImpl &Instructions); bool expandUncondBranchMMPseudo(MCInst &Inst, SMLoc IDLoc, SmallVectorImpl &Instructions); @@ -1613,9 +1617,9 @@ case Mips::LoadImm64: return expandLoadImm(Inst, false, IDLoc, Instructions); case Mips::LoadAddrImm32: - return expandLoadAddressImm(Inst, IDLoc, Instructions); + return expandLoadAddressImm(Inst, true, IDLoc, Instructions); case Mips::LoadAddrReg32: - return expandLoadAddressReg(Inst, IDLoc, Instructions); + return expandLoadAddressReg(Inst, true, IDLoc, Instructions); case Mips::B_MM_Pseudo: return expandUncondBranchMMPseudo(Inst, IDLoc, Instructions); case Mips::SWM_MM: @@ -1711,21 +1715,27 @@ return false; } -bool MipsAsmParser::expandLoadImm(MCInst &Inst, bool Is32BitImm, SMLoc IDLoc, +bool MipsAsmParser::loadImmediate(const MCOperand *ImmOp, + const MCOperand *DstRegOp, + const MCOperand *SrcRegOp, bool Is32BitImm, + SMLoc IDLoc, SmallVectorImpl &Instructions) { if (!Is32BitImm && !isGP64bit()) { Error(IDLoc, "instruction requires a 64-bit architecture"); return true; } + unsigned SrcReg = 0; + bool UseSrcReg = false; + if (SrcRegOp) { + SrcReg = SrcRegOp->getReg(); + UseSrcReg = true; + } + + int64_t ImmValue = ImmOp->getImm(); + unsigned DstReg = DstRegOp->getReg(); MCInst tmpInst; - const MCOperand &ImmOp = Inst.getOperand(1); - assert(ImmOp.isImm() && "expected immediate operand kind"); - const MCOperand &RegOp = Inst.getOperand(0); - assert(RegOp.isReg() && "expected register operand kind"); - int64_t ImmValue = ImmOp.getImm(); - unsigned Reg = RegOp.getReg(); tmpInst.setLoc(IDLoc); // FIXME: gas has a special case for values that are 000...1111, which // becomes a li -1 and then a dsrl @@ -1733,16 +1743,16 @@ // For unsigned and positive signed 16-bit values (0 <= j <= 65535): // li d,j => ori d,$zero,j tmpInst.setOpcode(Mips::ORi); - tmpInst.addOperand(MCOperand::CreateReg(Reg)); - tmpInst.addOperand(MCOperand::CreateReg(Mips::ZERO)); + tmpInst.addOperand(MCOperand::CreateReg(DstReg)); + tmpInst.addOperand(MCOperand::CreateReg(UseSrcReg ? SrcReg : Mips::ZERO)); tmpInst.addOperand(MCOperand::CreateImm(ImmValue)); Instructions.push_back(tmpInst); } else if (ImmValue < 0 && ImmValue >= -32768) { // For negative signed 16-bit values (-32768 <= j < 0): // li d,j => addiu d,$zero,j tmpInst.setOpcode(Mips::ADDiu); - tmpInst.addOperand(MCOperand::CreateReg(Reg)); - tmpInst.addOperand(MCOperand::CreateReg(Mips::ZERO)); + tmpInst.addOperand(MCOperand::CreateReg(DstReg)); + tmpInst.addOperand(MCOperand::CreateReg(UseSrcReg ? SrcReg : Mips::ZERO)); tmpInst.addOperand(MCOperand::CreateImm(ImmValue)); Instructions.push_back(tmpInst); } else if ((ImmValue & 0xffffffff) == ImmValue) { @@ -1753,10 +1763,19 @@ uint16_t Bits15To0 = ImmValue & 0xffff; tmpInst.setOpcode(Mips::LUi); - tmpInst.addOperand(MCOperand::CreateReg(Reg)); + tmpInst.addOperand(MCOperand::CreateReg(DstReg)); tmpInst.addOperand(MCOperand::CreateImm(Bits31To16)); Instructions.push_back(tmpInst); - createLShiftOri<0>(Bits15To0, Reg, IDLoc, Instructions); + createLShiftOri<0>(Bits15To0, DstReg, IDLoc, Instructions); + + if (UseSrcReg) { + tmpInst.clear(); + tmpInst.setOpcode(Mips::ADDu); + tmpInst.addOperand(MCOperand::CreateReg(DstReg)); + tmpInst.addOperand(MCOperand::CreateReg(DstReg)); + tmpInst.addOperand(MCOperand::CreateReg(SrcReg)); + Instructions.push_back(tmpInst); + } } else if ((ImmValue & (0xffffLL << 48)) == 0) { if (Is32BitImm) { Error(IDLoc, "instruction requires a 32-bit immediate"); @@ -1781,11 +1800,20 @@ uint16_t Bits15To0 = ImmValue & 0xffff; tmpInst.setOpcode(Mips::LUi); - tmpInst.addOperand(MCOperand::CreateReg(Reg)); + tmpInst.addOperand(MCOperand::CreateReg(DstReg)); tmpInst.addOperand(MCOperand::CreateImm(Bits47To32)); Instructions.push_back(tmpInst); - createLShiftOri<0>(Bits31To16, Reg, IDLoc, Instructions); - createLShiftOri<16>(Bits15To0, Reg, IDLoc, Instructions); + createLShiftOri<0>(Bits31To16, DstReg, IDLoc, Instructions); + createLShiftOri<16>(Bits15To0, DstReg, IDLoc, Instructions); + + if (UseSrcReg) { + tmpInst.clear(); + tmpInst.setOpcode(Mips::ADDu); + tmpInst.addOperand(MCOperand::CreateReg(DstReg)); + tmpInst.addOperand(MCOperand::CreateReg(DstReg)); + tmpInst.addOperand(MCOperand::CreateReg(SrcReg)); + Instructions.push_back(tmpInst); + } } else { if (Is32BitImm) { Error(IDLoc, "instruction requires a 32-bit immediate"); @@ -1812,109 +1840,82 @@ uint16_t Bits15To0 = ImmValue & 0xffff; tmpInst.setOpcode(Mips::LUi); - tmpInst.addOperand(MCOperand::CreateReg(Reg)); + tmpInst.addOperand(MCOperand::CreateReg(DstReg)); tmpInst.addOperand(MCOperand::CreateImm(Bits63To48)); Instructions.push_back(tmpInst); - createLShiftOri<0>(Bits47To32, Reg, IDLoc, Instructions); + createLShiftOri<0>(Bits47To32, DstReg, IDLoc, Instructions); // When Bits31To16 is 0, do a left shift of 32 bits instead of doing // two left shifts of 16 bits. if (Bits31To16 == 0) { - createLShiftOri<32>(Bits15To0, Reg, IDLoc, Instructions); + createLShiftOri<32>(Bits15To0, DstReg, IDLoc, Instructions); } else { - createLShiftOri<16>(Bits31To16, Reg, IDLoc, Instructions); - createLShiftOri<16>(Bits15To0, Reg, IDLoc, Instructions); + createLShiftOri<16>(Bits31To16, DstReg, IDLoc, Instructions); + createLShiftOri<16>(Bits15To0, DstReg, IDLoc, Instructions); + } + + if (UseSrcReg) { + tmpInst.clear(); + tmpInst.setOpcode(Mips::ADDu); + tmpInst.addOperand(MCOperand::CreateReg(DstReg)); + tmpInst.addOperand(MCOperand::CreateReg(DstReg)); + tmpInst.addOperand(MCOperand::CreateReg(SrcReg)); + Instructions.push_back(tmpInst); } } return false; } +bool MipsAsmParser::expandLoadImm(MCInst &Inst, bool Is32BitImm, SMLoc IDLoc, + SmallVectorImpl &Instructions) { + const MCOperand *ImmOp = &Inst.getOperand(1); + assert(ImmOp->isImm() && "expected immediate operand kind"); + const MCOperand *DstRegOp = &Inst.getOperand(0); + assert(DstRegOp->isReg() && "expected register operand kind"); + + if (loadImmediate(ImmOp, DstRegOp, nullptr, Is32BitImm, IDLoc, Instructions)) + return true; + + return false; +} + bool -MipsAsmParser::expandLoadAddressReg(MCInst &Inst, SMLoc IDLoc, +MipsAsmParser::expandLoadAddressReg(MCInst &Inst, bool Is32BitImm, SMLoc IDLoc, SmallVectorImpl &Instructions) { - MCInst tmpInst; - const MCOperand &ImmOp = Inst.getOperand(2); - assert((ImmOp.isImm() || ImmOp.isExpr()) && + const MCOperand *ImmOp = &Inst.getOperand(2); + assert((ImmOp->isImm() || ImmOp->isExpr()) && "expected immediate operand kind"); - if (!ImmOp.isImm()) { + if (!ImmOp->isImm()) { expandLoadAddressSym(Inst, IDLoc, Instructions); return false; } - const MCOperand &SrcRegOp = Inst.getOperand(1); - assert(SrcRegOp.isReg() && "expected register operand kind"); - const MCOperand &DstRegOp = Inst.getOperand(0); - assert(DstRegOp.isReg() && "expected register operand kind"); - int ImmValue = ImmOp.getImm(); - if (-32768 <= ImmValue && ImmValue <= 65535) { - // For -32768 <= j <= 65535. - // la d,j(s) => addiu d,s,j - tmpInst.setOpcode(Mips::ADDiu); - tmpInst.addOperand(MCOperand::CreateReg(DstRegOp.getReg())); - tmpInst.addOperand(MCOperand::CreateReg(SrcRegOp.getReg())); - tmpInst.addOperand(MCOperand::CreateImm(ImmValue)); - Instructions.push_back(tmpInst); - } else { - // For any other value of j that is representable as a 32-bit integer. - // la d,j(s) => lui d,hi16(j) - // ori d,d,lo16(j) - // addu d,d,s - tmpInst.setOpcode(Mips::LUi); - tmpInst.addOperand(MCOperand::CreateReg(DstRegOp.getReg())); - tmpInst.addOperand(MCOperand::CreateImm((ImmValue & 0xffff0000) >> 16)); - Instructions.push_back(tmpInst); - tmpInst.clear(); - tmpInst.setOpcode(Mips::ORi); - tmpInst.addOperand(MCOperand::CreateReg(DstRegOp.getReg())); - tmpInst.addOperand(MCOperand::CreateReg(DstRegOp.getReg())); - tmpInst.addOperand(MCOperand::CreateImm(ImmValue & 0xffff)); - Instructions.push_back(tmpInst); - tmpInst.clear(); - tmpInst.setOpcode(Mips::ADDu); - tmpInst.addOperand(MCOperand::CreateReg(DstRegOp.getReg())); - tmpInst.addOperand(MCOperand::CreateReg(DstRegOp.getReg())); - tmpInst.addOperand(MCOperand::CreateReg(SrcRegOp.getReg())); - Instructions.push_back(tmpInst); - } + const MCOperand *SrcRegOp = &Inst.getOperand(1); + assert(SrcRegOp->isReg() && "expected register operand kind"); + const MCOperand *DstRegOp = &Inst.getOperand(0); + assert(DstRegOp->isReg() && "expected register operand kind"); + + if (loadImmediate(ImmOp, DstRegOp, SrcRegOp, Is32BitImm, IDLoc, Instructions)) + return true; + return false; } bool -MipsAsmParser::expandLoadAddressImm(MCInst &Inst, SMLoc IDLoc, +MipsAsmParser::expandLoadAddressImm(MCInst &Inst, bool Is32BitImm, SMLoc IDLoc, SmallVectorImpl &Instructions) { - MCInst tmpInst; - const MCOperand &ImmOp = Inst.getOperand(1); - assert((ImmOp.isImm() || ImmOp.isExpr()) && + const MCOperand *ImmOp = &Inst.getOperand(1); + assert((ImmOp->isImm() || ImmOp->isExpr()) && "expected immediate operand kind"); - if (!ImmOp.isImm()) { + if (!ImmOp->isImm()) { expandLoadAddressSym(Inst, IDLoc, Instructions); return false; } - const MCOperand &RegOp = Inst.getOperand(0); - assert(RegOp.isReg() && "expected register operand kind"); - int ImmValue = ImmOp.getImm(); - if (-32768 <= ImmValue && ImmValue <= 65535) { - // For -32768 <= j <= 65535. - // la d,j => addiu d,$zero,j - tmpInst.setOpcode(Mips::ADDiu); - tmpInst.addOperand(MCOperand::CreateReg(RegOp.getReg())); - tmpInst.addOperand(MCOperand::CreateReg(Mips::ZERO)); - tmpInst.addOperand(MCOperand::CreateImm(ImmValue)); - Instructions.push_back(tmpInst); - } else { - // For any other value of j that is representable as a 32-bit integer. - // la d,j => lui d,hi16(j) - // ori d,d,lo16(j) - tmpInst.setOpcode(Mips::LUi); - tmpInst.addOperand(MCOperand::CreateReg(RegOp.getReg())); - tmpInst.addOperand(MCOperand::CreateImm((ImmValue & 0xffff0000) >> 16)); - Instructions.push_back(tmpInst); - tmpInst.clear(); - tmpInst.setOpcode(Mips::ORi); - tmpInst.addOperand(MCOperand::CreateReg(RegOp.getReg())); - tmpInst.addOperand(MCOperand::CreateReg(RegOp.getReg())); - tmpInst.addOperand(MCOperand::CreateImm(ImmValue & 0xffff)); - Instructions.push_back(tmpInst); - } + const MCOperand *DstRegOp = &Inst.getOperand(0); + assert(DstRegOp->isReg() && "expected register operand kind"); + + if (loadImmediate(ImmOp, DstRegOp, nullptr, Is32BitImm, IDLoc, Instructions)) + return true; + return false; } Index: test/MC/Mips/micromips-expansions.s =================================================================== --- test/MC/Mips/micromips-expansions.s +++ test/MC/Mips/micromips-expansions.s @@ -9,10 +9,10 @@ # CHECK: addiu $6, $zero, -2345 # encoding: [0xc0,0x30,0xd7,0xf6] # CHECK: lui $7, 1 # encoding: [0xa7,0x41,0x01,0x00] # CHECK: ori $7, $7, 2 # encoding: [0xe7,0x50,0x02,0x00] -# CHECK: addiu $4, $zero, 20 # encoding: [0x80,0x30,0x14,0x00] +# CHECK: ori $4, $zero, 20 # encoding: [0x80,0x50,0x14,0x00] # CHECK: lui $7, 1 # encoding: [0xa7,0x41,0x01,0x00] # CHECK: ori $7, $7, 2 # encoding: [0xe7,0x50,0x02,0x00] -# CHECK: addiu $4, $5, 20 # encoding: [0x85,0x30,0x14,0x00] +# CHECK: ori $4, $5, 20 # encoding: [0x85,0x50,0x14,0x00] # CHECK: lui $7, 1 # encoding: [0xa7,0x41,0x01,0x00] # CHECK: ori $7, $7, 2 # encoding: [0xe7,0x50,0x02,0x00] # CHECK: addu $7, $7, $8 # encoding: [0x07,0x01,0x50,0x39] Index: test/MC/Mips/mips-expansions-bad.s =================================================================== --- test/MC/Mips/mips-expansions-bad.s +++ test/MC/Mips/mips-expansions-bad.s @@ -7,5 +7,11 @@ li $5, 0x100000000 # 32-BIT: :[[@LINE-1]]:3: error: instruction requires a 32-bit immediate # 64-BIT: :[[@LINE-2]]:3: error: instruction requires a 32-bit immediate + la $5, 0x100000000 + # 32-BIT: :[[@LINE-1]]:3: error: instruction requires a 32-bit immediate + # 64-BIT: :[[@LINE-2]]:3: error: instruction requires a 32-bit immediate + la $5, 0x100000000($6) + # 32-BIT: :[[@LINE-1]]:3: error: instruction requires a 32-bit immediate + # 64-BIT: :[[@LINE-2]]:3: error: instruction requires a 32-bit immediate dli $5, 1 # 32-BIT: :[[@LINE-1]]:3: error: instruction requires a 64-bit architecture Index: test/MC/Mips/mips-expansions.s =================================================================== --- test/MC/Mips/mips-expansions.s +++ test/MC/Mips/mips-expansions.s @@ -12,10 +12,10 @@ # CHECK: lui $9, 1 # encoding: [0x01,0x00,0x09,0x3c] # CHECK-NOT: ori $9, $9, 0 # encoding: [0x00,0x00,0x29,0x35] -# CHECK: addiu $4, $zero, 20 # encoding: [0x14,0x00,0x04,0x24] +# CHECK: ori $4, $zero, 20 # encoding: [0x14,0x00,0x04,0x34] # CHECK: lui $7, 1 # encoding: [0x01,0x00,0x07,0x3c] # CHECK: ori $7, $7, 2 # encoding: [0x02,0x00,0xe7,0x34] -# CHECK: addiu $4, $5, 20 # encoding: [0x14,0x00,0xa4,0x24] +# CHECK: ori $4, $5, 20 # encoding: [0x14,0x00,0xa4,0x34] # CHECK: lui $7, 1 # encoding: [0x01,0x00,0x07,0x3c] # CHECK: ori $7, $7, 2 # encoding: [0x02,0x00,0xe7,0x34] # CHECK: addu $7, $7, $8 # encoding: [0x21,0x38,0xe8,0x00]