diff --git a/lib/Target/PowerPC/AsmParser/PPCAsmParser.cpp b/lib/Target/PowerPC/AsmParser/PPCAsmParser.cpp index ae24c8a88e6..d1664febd39 100644 --- a/lib/Target/PowerPC/AsmParser/PPCAsmParser.cpp +++ b/lib/Target/PowerPC/AsmParser/PPCAsmParser.cpp @@ -665,6 +665,29 @@ void PPCOperand::print(raw_ostream &OS) const { } } +static void +addNegOperand(MCInst &Inst, MCOperand &Op, MCContext &Ctx) { + if (Op.isImm()) { + Inst.addOperand(MCOperand::CreateImm(-Op.getImm())); + return; + } + const MCExpr *Expr = Op.getExpr(); + if (const MCUnaryExpr *UnExpr = dyn_cast(Expr)) { + if (UnExpr->getOpcode() == MCUnaryExpr::Minus) { + Inst.addOperand(MCOperand::CreateExpr(UnExpr->getSubExpr())); + return; + } + } else if (const MCBinaryExpr *BinExpr = dyn_cast(Expr)) { + if (BinExpr->getOpcode() == MCBinaryExpr::Sub) { + const MCExpr *NE = MCBinaryExpr::CreateSub(BinExpr->getRHS(), + BinExpr->getLHS(), Ctx); + Inst.addOperand(MCOperand::CreateExpr(NE)); + return; + } + } + Inst.addOperand(MCOperand::CreateExpr(MCUnaryExpr::CreateMinus(Expr, Ctx))); +} + void PPCAsmParser::ProcessInstruction(MCInst &Inst, const OperandVector &Operands) { int Opcode = Inst.getOpcode(); @@ -680,41 +703,37 @@ void PPCAsmParser::ProcessInstruction(MCInst &Inst, } case PPC::SUBI: { MCInst TmpInst; - int64_t N = Inst.getOperand(2).getImm(); TmpInst.setOpcode(PPC::ADDI); TmpInst.addOperand(Inst.getOperand(0)); TmpInst.addOperand(Inst.getOperand(1)); - TmpInst.addOperand(MCOperand::CreateImm(-N)); + addNegOperand(TmpInst, Inst.getOperand(2), getContext()); Inst = TmpInst; break; } case PPC::SUBIS: { MCInst TmpInst; - int64_t N = Inst.getOperand(2).getImm(); TmpInst.setOpcode(PPC::ADDIS); TmpInst.addOperand(Inst.getOperand(0)); TmpInst.addOperand(Inst.getOperand(1)); - TmpInst.addOperand(MCOperand::CreateImm(-N)); + addNegOperand(TmpInst, Inst.getOperand(2), getContext()); Inst = TmpInst; break; } case PPC::SUBIC: { MCInst TmpInst; - int64_t N = Inst.getOperand(2).getImm(); TmpInst.setOpcode(PPC::ADDIC); TmpInst.addOperand(Inst.getOperand(0)); TmpInst.addOperand(Inst.getOperand(1)); - TmpInst.addOperand(MCOperand::CreateImm(-N)); + addNegOperand(TmpInst, Inst.getOperand(2), getContext()); Inst = TmpInst; break; } case PPC::SUBICo: { MCInst TmpInst; - int64_t N = Inst.getOperand(2).getImm(); TmpInst.setOpcode(PPC::ADDICo); TmpInst.addOperand(Inst.getOperand(0)); TmpInst.addOperand(Inst.getOperand(1)); - TmpInst.addOperand(MCOperand::CreateImm(-N)); + addNegOperand(TmpInst, Inst.getOperand(2), getContext()); Inst = TmpInst; break; } diff --git a/test/MC/PowerPC/ppc64-fixup-apply.s b/test/MC/PowerPC/ppc64-fixup-apply.s index 16934052477..24bd83ffd18 100644 --- a/test/MC/PowerPC/ppc64-fixup-apply.s +++ b/test/MC/PowerPC/ppc64-fixup-apply.s @@ -14,13 +14,13 @@ addis 1, 1, target .set target, 0x1234 -addi 1, 1, target2@l -addis 1, 1, target2@ha +subi 1, 1, -target2@l +subis 1, 1, -target2@ha .set target2, 0x12345678 addi 1, 1, target3-target4@l -addis 1, 1, target3-target4@ha +subis 1, 1, target4-target3@ha .set target3, 0x23455678 .set target4, 0x12341234