Index: lib/Target/Mips/AsmParser/MipsAsmParser.cpp =================================================================== --- lib/Target/Mips/AsmParser/MipsAsmParser.cpp +++ lib/Target/Mips/AsmParser/MipsAsmParser.cpp @@ -204,6 +204,9 @@ bool expandLoadStoreMultiple(MCInst &Inst, SMLoc IDLoc, SmallVectorImpl &Instructions); + bool expandBranchImm(MCInst &Inst, SMLoc IDLoc, + SmallVectorImpl &Instructions); + void createNop(bool hasShortDelaySlot, SMLoc IDLoc, SmallVectorImpl &Instructions); @@ -1607,6 +1610,8 @@ case Mips::SWM_MM: case Mips::JalOneReg: case Mips::JalTwoReg: + case Mips::BneImm: + case Mips::BeqImm: return true; default: return false; @@ -1633,6 +1638,9 @@ case Mips::JalOneReg: case Mips::JalTwoReg: return expandJalWithRegs(Inst, IDLoc, Instructions); + case Mips::BneImm: + case Mips::BeqImm: + return expandBranchImm(Inst, IDLoc, Instructions); } } @@ -2009,6 +2017,57 @@ return false; } +bool MipsAsmParser::expandBranchImm(MCInst &Inst, SMLoc IDLoc, + SmallVectorImpl &Instructions) { + const MCOperand &DstRegOp = Inst.getOperand(0); + assert(DstRegOp.isReg() && "expected register operand kind"); + + const MCOperand &ImmOp = Inst.getOperand(1); + assert(ImmOp.isImm() && "expected immediate operand kind"); + + const MCOperand &MemOffsetOp = Inst.getOperand(2); + assert(MemOffsetOp.isImm() && "expected immediate operand kind"); + + unsigned OpCode = 0; + switch(Inst.getOpcode()) { + case Mips::BneImm: + OpCode = Mips::BNE; + break; + case Mips::BeqImm: + OpCode = Mips::BEQ; + break; + default: + llvm_unreachable("Unknown immediate branch pseudo-instruction."); + break; + } + + int64_t ImmValue = ImmOp.getImm(); + if (ImmValue == 0) { + MCInst BranchInst; + BranchInst.setOpcode(OpCode); + BranchInst.addOperand(DstRegOp); + BranchInst.addOperand(MCOperand::CreateReg(Mips::ZERO)); + BranchInst.addOperand(MemOffsetOp); + Instructions.push_back(BranchInst); + } else { + unsigned ATReg = getATReg(IDLoc); + if (!ATReg) + return true; + + if (loadImmediate(ImmValue, ATReg, Mips::NoRegister, !isGP64bit(), IDLoc, + Instructions)) + return true; + + MCInst BranchInst; + BranchInst.setOpcode(OpCode); + BranchInst.addOperand(DstRegOp); + BranchInst.addOperand(MCOperand::CreateReg(ATReg)); + BranchInst.addOperand(MemOffsetOp); + Instructions.push_back(BranchInst); + } + return false; +} + void MipsAsmParser::expandMemInst(MCInst &Inst, SMLoc IDLoc, SmallVectorImpl &Instructions, bool isLoad, bool isImmOpnd) { Index: lib/Target/Mips/MipsInstrInfo.td =================================================================== --- lib/Target/Mips/MipsInstrInfo.td +++ lib/Target/Mips/MipsInstrInfo.td @@ -1671,6 +1671,15 @@ def JalOneReg : MipsAsmPseudoInst<(outs), (ins GPR32Opnd:$rs), "jal\t$rs"> ; +let hasDelaySlot = 1 in { +def BneImm : MipsAsmPseudoInst<(outs GPR32Opnd:$rt), + (ins uimm5:$imm32, brtarget:$offset), + "bne\t$rt, $imm32, $offset">; +def BeqImm : MipsAsmPseudoInst<(outs GPR32Opnd:$rt), + (ins uimm5:$imm32, brtarget:$offset), + "beq\t$rt, $imm32, $offset">; +} + //===----------------------------------------------------------------------===// // Arbitrary patterns that map to one or more instructions //===----------------------------------------------------------------------===// Index: test/MC/Mips/mips-expansions.s =================================================================== --- test/MC/Mips/mips-expansions.s +++ test/MC/Mips/mips-expansions.s @@ -68,6 +68,44 @@ # CHECK: lui $1, %hi(symbol) # CHECK: sdc1 $f0, %lo(symbol)($1) +# CHECK: bnez $2, 1332 # encoding: [0x4d,0x01,0x40,0x14] +# CHECK: nop # encoding: [0x00,0x00,0x00,0x00] +# CHECK: ori $1, $zero, 123 # encoding: [0x7b,0x00,0x01,0x34] +# CHECK: bne $2, $1, 1332 # encoding: [0x4d,0x01,0x41,0x14] +# CHECK: nop # encoding: [0x00,0x00,0x00,0x00] +# CHECK: addiu $1, $zero, -2345 # encoding: [0xd7,0xf6,0x01,0x24] +# CHECK: bne $2, $1, 1332 # encoding: [0x4d,0x01,0x41,0x14] +# CHECK: nop # encoding: [0x00,0x00,0x00,0x00] +# CHECK: lui $1, 1 # encoding: [0x01,0x00,0x01,0x3c] +# CHECK: ori $1, $1, 2 # encoding: [0x02,0x00,0x21,0x34] +# CHECK: bne $2, $1, 1332 # encoding: [0x4d,0x01,0x41,0x14] +# CHECK: nop # encoding: [0x00,0x00,0x00,0x00] +# CHECK: addiu $1, $zero, -8 # encoding: [0xf8,0xff,0x01,0x24] +# CHECK: bne $2, $1, 1332 # encoding: [0x4d,0x01,0x41,0x14] +# CHECK: nop # encoding: [0x00,0x00,0x00,0x00] +# CHECK: lui $1, 1 # encoding: [0x01,0x00,0x01,0x3c] +# CHECK: bne $2, $1, 1332 # encoding: [0x4d,0x01,0x41,0x14] +# CHECK: nop # encoding: [0x00,0x00,0x00,0x00] + +# CHECK: beqz $2, 1332 # encoding: [0x4d,0x01,0x40,0x10] +# CHECK: nop # encoding: [0x00,0x00,0x00,0x00] +# CHECK: ori $1, $zero, 123 # encoding: [0x7b,0x00,0x01,0x34] +# CHECK: beq $2, $1, 1332 # encoding: [0x4d,0x01,0x41,0x10] +# CHECK: nop # encoding: [0x00,0x00,0x00,0x00] +# CHECK: addiu $1, $zero, -2345 # encoding: [0xd7,0xf6,0x01,0x24] +# CHECK: beq $2, $1, 1332 # encoding: [0x4d,0x01,0x41,0x10] +# CHECK: nop # encoding: [0x00,0x00,0x00,0x00] +# CHECK: lui $1, 1 # encoding: [0x01,0x00,0x01,0x3c] +# CHECK: ori $1, $1, 2 # encoding: [0x02,0x00,0x21,0x34] +# CHECK: beq $2, $1, 1332 # encoding: [0x4d,0x01,0x41,0x10] +# CHECK: nop # encoding: [0x00,0x00,0x00,0x00] +# CHECK: addiu $1, $zero, -8 # encoding: [0xf8,0xff,0x01,0x24] +# CHECK: beq $2, $1, 1332 # encoding: [0x4d,0x01,0x41,0x10] +# CHECK: nop # encoding: [0x00,0x00,0x00,0x00] +# CHECK: lui $1, 1 # encoding: [0x01,0x00,0x01,0x3c] +# CHECK: beq $2, $1, 1332 # encoding: [0x4d,0x01,0x41,0x10] +# CHECK: nop # encoding: [0x00,0x00,0x00,0x00] + li $5,123 li $6,-2345 li $7,65538 @@ -96,3 +134,17 @@ ldc1 $f0, symbol sdc1 $f0, symbol + + bne $2, 0, 1332 + bne $2, 123, 1332 + bne $2, -2345, 1332 + bne $2, 65538, 1332 + bne $2, ~7, 1332 + bne $2, 0x10000, 1332 + + beq $2, 0, 1332 + beq $2, 123, 1332 + beq $2, -2345, 1332 + beq $2, 65538, 1332 + beq $2, ~7, 1332 + beq $2, 0x10000, 1332 Index: test/MC/Mips/mips64-expansions.s =================================================================== --- test/MC/Mips/mips64-expansions.s +++ test/MC/Mips/mips64-expansions.s @@ -178,3 +178,81 @@ # CHECK: ori $8, $8, 65534 # encoding: [0xfe,0xff,0x08,0x35] # CHECK: dsll $8, $8, 16 # encoding: [0x38,0x44,0x08,0x00] # CHECK: ori $8, $8, 65535 # encoding: [0xff,0xff,0x08,0x35] + +# Test bne with an immediate as the 2nd operand. + bne $2, 0x100010001, 1332 +# CHECK: lui $1, 1 # encoding: [0x01,0x00,0x01,0x3c] +# CHECK: ori $1, $1, 1 # encoding: [0x01,0x00,0x21,0x34] +# CHECK: dsll $1, $1, 16 # encoding: [0x38,0x0c,0x01,0x00] +# CHECK: ori $1, $1, 1 # encoding: [0x01,0x00,0x21,0x34] +# CHECK: bne $2, $1, 1332 # encoding: [0x4d,0x01,0x41,0x14] +# CHECK: nop # encoding: [0x00,0x00,0x00,0x00] + + bne $2, 0x1000100010001, 1332 +# CHECK: lui $1, 1 # encoding: [0x01,0x00,0x01,0x3c] +# CHECK: ori $1, $1, 1 # encoding: [0x01,0x00,0x21,0x34] +# CHECK: dsll $1, $1, 16 # encoding: [0x38,0x0c,0x01,0x00] +# CHECK: ori $1, $1, 1 # encoding: [0x01,0x00,0x21,0x34] +# CHECK: dsll $1, $1, 16 # encoding: [0x38,0x0c,0x01,0x00] +# CHECK: ori $1, $1, 1 # encoding: [0x01,0x00,0x21,0x34] +# CHECK: bne $2, $1, 1332 # encoding: [0x4d,0x01,0x41,0x14] +# CHECK: nop # encoding: [0x00,0x00,0x00,0x00] + + bne $2, -0x100010001, 1332 +# CHECK: lui $1, 65535 # encoding: [0xff,0xff,0x01,0x3c] +# CHECK: ori $1, $1, 65534 # encoding: [0xfe,0xff,0x21,0x34] +# CHECK: dsll $1, $1, 16 # encoding: [0x38,0x0c,0x01,0x00] +# CHECK: ori $1, $1, 65534 # encoding: [0xfe,0xff,0x21,0x34] +# CHECK: dsll $1, $1, 16 # encoding: [0x38,0x0c,0x01,0x00] +# CHECK: ori $1, $1, 65535 # encoding: [0xff,0xff,0x21,0x34] +# CHECK: bne $2, $1, 1332 # encoding: [0x4d,0x01,0x41,0x14] +# CHECK: nop # encoding: [0x00,0x00,0x00,0x00] + + bne $2, -0x1000100010001, 1332 +# CHECK: lui $1, 65534 # encoding: [0xfe,0xff,0x01,0x3c] +# CHECK: ori $1, $1, 65534 # encoding: [0xfe,0xff,0x21,0x34] +# CHECK: dsll $1, $1, 16 # encoding: [0x38,0x0c,0x01,0x00] +# CHECK: ori $1, $1, 65534 # encoding: [0xfe,0xff,0x21,0x34] +# CHECK: dsll $1, $1, 16 # encoding: [0x38,0x0c,0x01,0x00] +# CHECK: ori $1, $1, 65535 # encoding: [0xff,0xff,0x21,0x34] +# CHECK: bne $2, $1, 1332 # encoding: [0x4d,0x01,0x41,0x14] +# CHECK: nop # encoding: [0x00,0x00,0x00,0x00] + +# Test beq with an immediate as the 2nd operand. + beq $2, 0x100010001, 1332 +# CHECK: lui $1, 1 # encoding: [0x01,0x00,0x01,0x3c] +# CHECK: ori $1, $1, 1 # encoding: [0x01,0x00,0x21,0x34] +# CHECK: dsll $1, $1, 16 # encoding: [0x38,0x0c,0x01,0x00] +# CHECK: ori $1, $1, 1 # encoding: [0x01,0x00,0x21,0x34] +# CHECK: beq $2, $1, 1332 # encoding: [0x4d,0x01,0x41,0x10] +# CHECK: nop # encoding: [0x00,0x00,0x00,0x00] + + beq $2, 0x1000100010001, 1332 +# CHECK: lui $1, 1 # encoding: [0x01,0x00,0x01,0x3c] +# CHECK: ori $1, $1, 1 # encoding: [0x01,0x00,0x21,0x34] +# CHECK: dsll $1, $1, 16 # encoding: [0x38,0x0c,0x01,0x00] +# CHECK: ori $1, $1, 1 # encoding: [0x01,0x00,0x21,0x34] +# CHECK: dsll $1, $1, 16 # encoding: [0x38,0x0c,0x01,0x00] +# CHECK: ori $1, $1, 1 # encoding: [0x01,0x00,0x21,0x34] +# CHECK: beq $2, $1, 1332 # encoding: [0x4d,0x01,0x41,0x10] +# CHECK: nop # encoding: [0x00,0x00,0x00,0x00] + + beq $2, -0x100010001, 1332 +# CHECK: lui $1, 65535 # encoding: [0xff,0xff,0x01,0x3c] +# CHECK: ori $1, $1, 65534 # encoding: [0xfe,0xff,0x21,0x34] +# CHECK: dsll $1, $1, 16 # encoding: [0x38,0x0c,0x01,0x00] +# CHECK: ori $1, $1, 65534 # encoding: [0xfe,0xff,0x21,0x34] +# CHECK: dsll $1, $1, 16 # encoding: [0x38,0x0c,0x01,0x00] +# CHECK: ori $1, $1, 65535 # encoding: [0xff,0xff,0x21,0x34] +# CHECK: beq $2, $1, 1332 # encoding: [0x4d,0x01,0x41,0x10] +# CHECK: nop # encoding: [0x00,0x00,0x00,0x00] + + beq $2, -0x1000100010001, 1332 +# CHECK: lui $1, 65534 # encoding: [0xfe,0xff,0x01,0x3c] +# CHECK: ori $1, $1, 65534 # encoding: [0xfe,0xff,0x21,0x34] +# CHECK: dsll $1, $1, 16 # encoding: [0x38,0x0c,0x01,0x00] +# CHECK: ori $1, $1, 65534 # encoding: [0xfe,0xff,0x21,0x34] +# CHECK: dsll $1, $1, 16 # encoding: [0x38,0x0c,0x01,0x00] +# CHECK: ori $1, $1, 65535 # encoding: [0xff,0xff,0x21,0x34] +# CHECK: beq $2, $1, 1332 # encoding: [0x4d,0x01,0x41,0x10] +# CHECK: nop # encoding: [0x00,0x00,0x00,0x00]