Index: lib/Target/Mips/AsmParser/MipsAsmParser.cpp =================================================================== --- lib/Target/Mips/AsmParser/MipsAsmParser.cpp +++ lib/Target/Mips/AsmParser/MipsAsmParser.cpp @@ -214,6 +214,11 @@ bool expandCondBranches(MCInst &Inst, SMLoc IDLoc, SmallVectorImpl &Instructions); + bool expandRotation(MCInst &Inst, SMLoc IDLoc, + SmallVectorImpl &Instructions); + bool expandRotationImm(MCInst &Inst, SMLoc IDLoc, + SmallVectorImpl &Instructions); + void createNop(bool hasShortDelaySlot, SMLoc IDLoc, SmallVectorImpl &Instructions); @@ -372,11 +377,11 @@ // Initialize the set of available features. setAvailableFeatures(ComputeAvailableFeatures(STI.getFeatureBits())); - + // Remember the initial assembler options. The user can not modify these. AssemblerOptions.push_back( llvm::make_unique(STI.getFeatureBits())); - + // Create an assembler options environment for the user to modify. AssemblerOptions.push_back( llvm::make_unique(STI.getFeatureBits())); @@ -1635,6 +1640,10 @@ case Mips::BLEU: case Mips::BGEU: case Mips::BGTU: + case Mips::ROL: + case Mips::ROLImm: + case Mips::ROR: + case Mips::RORImm: return true; default: return false; @@ -1673,6 +1682,12 @@ case Mips::BGEU: case Mips::BGTU: return expandCondBranches(Inst, IDLoc, Instructions); + case Mips::ROL: + case Mips::ROR: + return expandRotation(Inst, IDLoc, Instructions); + case Mips::ROLImm: + case Mips::RORImm: + return expandRotationImm(Inst, IDLoc, Instructions); } } @@ -2449,6 +2464,137 @@ return false; } +bool MipsAsmParser::expandRotation(MCInst &Inst, SMLoc IDLoc, SmallVectorImpl &Instructions) { + + unsigned ATReg = Mips::NoRegister; + unsigned DReg = Mips::NoRegister; + unsigned SReg = Mips::NoRegister; + unsigned TReg = Mips::NoRegister; + + unsigned FrstShift = Mips::NOP; + unsigned ScndShift = Mips::NOP; + + switch (Inst.getOpcode()) { + default: + llvm_unreachable("unexpected instruction opcode"); + case Mips::ROL: + case Mips::ROLImm: + FrstShift = Mips::SRLV; + ScndShift = Mips::SLLV; + break; + case Mips::ROR: + case Mips::RORImm: + FrstShift = Mips::SLLV; + ScndShift = Mips::SRLV; + break; + } + + DReg = Inst.getOperand(0).getReg(); + SReg = Inst.getOperand(1).getReg(); + if (Inst.getOperand(2).isReg()) { + TReg = Inst.getOperand(2).getReg(); + } + + ATReg = getATReg(Inst.getLoc()); + + MCInst tmpInst; + + tmpInst.clear(); + tmpInst.setLoc(Inst.getLoc()); + tmpInst.setOpcode(Mips::SUBu); + tmpInst.addOperand(MCOperand::createReg(ATReg)); + tmpInst.addOperand(MCOperand::createReg(Mips::ZERO)); + tmpInst.addOperand(MCOperand::createReg(TReg)); + Instructions.push_back(tmpInst); + + tmpInst.clear(); + tmpInst.setLoc(Inst.getLoc()); + tmpInst.setOpcode(FrstShift); + tmpInst.addOperand(MCOperand::createReg(ATReg)); + tmpInst.addOperand(MCOperand::createReg(SReg)); + tmpInst.addOperand(MCOperand::createReg(ATReg)); + Instructions.push_back(tmpInst); + + tmpInst.clear(); + tmpInst.setLoc(Inst.getLoc()); + tmpInst.setOpcode(ScndShift); + tmpInst.addOperand(MCOperand::createReg(DReg)); + tmpInst.addOperand(MCOperand::createReg(SReg)); + tmpInst.addOperand(MCOperand::createReg(TReg)); + Instructions.push_back(tmpInst); + + tmpInst.clear(); + tmpInst.setLoc(Inst.getLoc()); + tmpInst.setOpcode(Mips::OR); + tmpInst.addOperand(MCOperand::createReg(DReg)); + tmpInst.addOperand(MCOperand::createReg(DReg)); + tmpInst.addOperand(MCOperand::createReg(ATReg)); + Instructions.push_back(tmpInst); + + return false; +} + +bool MipsAsmParser::expandRotationImm(MCInst &Inst, SMLoc IDLoc, + SmallVectorImpl &Instructions) { + + unsigned ATReg = Mips::NoRegister; + unsigned DReg = Mips::NoRegister; + unsigned SReg = Mips::NoRegister; + int64_t ImmValue = 0; + + unsigned FrstShift = Mips::NOP; + unsigned ScndShift = Mips::NOP; + + switch (Inst.getOpcode()) { + default: + llvm_unreachable("unexpected instruction opcode"); + case Mips::ROLImm: + FrstShift = Mips::SLL; + ScndShift = Mips::SRL; + break; + case Mips::RORImm: + FrstShift = Mips::SRL; + ScndShift = Mips::SLL; + break; + } + + DReg = Inst.getOperand(0).getReg(); + SReg = Inst.getOperand(1).getReg(); + if (Inst.getOperand(2).isImm()) { + ImmValue = Inst.getOperand(2).getImm(); + } + + ATReg = getATReg(Inst.getLoc()); + + MCInst tmpInst; + + tmpInst.clear(); + tmpInst.setLoc(Inst.getLoc()); + tmpInst.setOpcode(FrstShift); + tmpInst.addOperand(MCOperand::createReg(ATReg)); + tmpInst.addOperand(MCOperand::createReg(SReg)); + tmpInst.addOperand(MCOperand::createImm(ImmValue)); + Instructions.push_back(tmpInst); + + tmpInst.clear(); + tmpInst.setLoc(Inst.getLoc()); + tmpInst.setOpcode(ScndShift); + tmpInst.addOperand(MCOperand::createReg(DReg)); + tmpInst.addOperand(MCOperand::createReg(SReg)); + tmpInst.addOperand(MCOperand::createImm(32 - ImmValue)); + Instructions.push_back(tmpInst); + + tmpInst.clear(); + tmpInst.setLoc(Inst.getLoc()); + tmpInst.setOpcode(Mips::OR); + tmpInst.addOperand(MCOperand::createReg(DReg)); + tmpInst.addOperand(MCOperand::createReg(DReg)); + tmpInst.addOperand(MCOperand::createReg(ATReg)); + Instructions.push_back(tmpInst); + + return false; +} + void MipsAsmParser::createNop(bool hasShortDelaySlot, SMLoc IDLoc, SmallVectorImpl &Instructions) { MCInst NopInst; @@ -4341,7 +4487,7 @@ getParser().getStreamer().EmitGPRel32Value(Value); if (getLexer().isNot(AsmToken::EndOfStatement)) - return Error(getLexer().getLoc(), + return Error(getLexer().getLoc(), "unexpected token, expected end of statement"); Parser.Lex(); // Eat EndOfStatement token. return false; @@ -4359,7 +4505,7 @@ getParser().getStreamer().EmitGPRel64Value(Value); if (getLexer().isNot(AsmToken::EndOfStatement)) - return Error(getLexer().getLoc(), + return Error(getLexer().getLoc(), "unexpected token, expected end of statement"); Parser.Lex(); // Eat EndOfStatement token. return false; @@ -4401,7 +4547,7 @@ } // Unknown option. - Warning(Parser.getTok().getLoc(), + Warning(Parser.getTok().getLoc(), "unknown option, expected 'pic0' or 'pic2'"); Parser.eatToEndOfStatement(); return false; @@ -4800,7 +4946,7 @@ if (IDVal == ".abicalls") { getTargetStreamer().emitDirectiveAbiCalls(); if (Parser.getTok().isNot(AsmToken::EndOfStatement)) { - Error(Parser.getTok().getLoc(), + Error(Parser.getTok().getLoc(), "unexpected token, expected end of statement"); // Clear line Parser.eatToEndOfStatement(); Index: lib/Target/Mips/MipsInstrInfo.td =================================================================== --- lib/Target/Mips/MipsInstrInfo.td +++ lib/Target/Mips/MipsInstrInfo.td @@ -1554,6 +1554,24 @@ def PREF : MMRel, CacheOp<"pref", mem>, CACHEOP_FM<0b110011>, INSN_MIPS3_32_NOT_32R6_64R6; +def ROL : MipsAsmPseudoInst<(outs), (ins GPR32Opnd:$rs, GPR32Opnd:$rt, GPR32Opnd:$rd), + "rol\t$rs, $rt, $rd"> ; +def ROLImm : MipsAsmPseudoInst<(outs), (ins GPR32Opnd:$rs, GPR32Opnd:$rt, simm16:$imm), + "rol\t$rs, $rt, $imm"> ; +def : MipsInstAlias<"rol $rd, $rs", + (ROL GPR32Opnd:$rd, GPR32Opnd:$rd, GPR32Opnd:$rs), 0>; +def : MipsInstAlias<"rol $rd, $imm", + (ROLImm GPR32Opnd:$rd, GPR32Opnd:$rd, simm16:$imm), 0>; + +def ROR : MipsAsmPseudoInst<(outs), (ins GPR32Opnd:$rs, GPR32Opnd:$rt, GPR32Opnd:$rd), + "ror\t$rs, $rt, $rd"> ; +def RORImm : MipsAsmPseudoInst<(outs), (ins GPR32Opnd:$rs, GPR32Opnd:$rt, simm16:$imm), + "ror\t$rs, $rt, $imm"> ; +def : MipsInstAlias<"ror $rd, $rs", + (ROR GPR32Opnd:$rd, GPR32Opnd:$rd, GPR32Opnd:$rs), 0>; +def : MipsInstAlias<"ror $rd, $imm", + (RORImm GPR32Opnd:$rd, GPR32Opnd:$rd, simm16:$imm), 0>; + //===----------------------------------------------------------------------===// // Instruction aliases //===----------------------------------------------------------------------===// @@ -1620,7 +1638,7 @@ def : MipsInstAlias<"beqzl $rs,$offset", (BEQL GPR32Opnd:$rs, ZERO, brtarget:$offset), 0>; def : MipsInstAlias<"syscall", (SYSCALL 0), 1>; - + def : MipsInstAlias<"break", (BREAK 0, 0), 1>; def : MipsInstAlias<"break $imm", (BREAK uimm10:$imm, 0), 1>; def : MipsInstAlias<"ei", (EI ZERO), 1>, ISA_MIPS32R2; Index: test/MC/Mips/rotations.s =================================================================== --- test/MC/Mips/rotations.s +++ test/MC/Mips/rotations.s @@ -0,0 +1,73 @@ +# RUN: llvm-mc %s -triple mips-unknown-linux -show-encoding | FileCheck %s + + .text +foo: + rol $4,$5 +# CHECK: negu $1, $5 # encoding: [0x00,0x05,0x08,0x23] +# CHECK: srlv $1, $4, $1 # encoding: [0x00,0x24,0x08,0x06] +# CHECK: sllv $4, $4, $5 # encoding: [0x00,0xa4,0x20,0x04] +# CHECK: or $4, $4, $1 # encoding: [0x00,0x81,0x20,0x25] + rol $4,$5,$6 +# CHECK: negu $1, $6 # encoding: [0x00,0x06,0x08,0x23] +# CHECK: srlv $1, $5, $1 # encoding: [0x00,0x25,0x08,0x06] +# CHECK: sllv $4, $5, $6 # encoding: [0x00,0xc5,0x20,0x04] +# CHECK: or $4, $4, $1 # encoding: [0x00,0x81,0x20,0x25] + rol $4,0 +# CHECK: sll $1, $4, 0 # encoding: [0x00,0x04,0x08,0x00] +# CHECK: srl $4, $4, 32 # encoding: [0x00,0x04,0x20,0x02] +# CHECK: or $4, $4, $1 # encoding: [0x00,0x81,0x20,0x25] + rol $4,$5,0 +# CHECK: sll $1, $5, 0 # encoding: [0x00,0x05,0x08,0x00] +# CHECK: srl $4, $5, 32 # encoding: [0x00,0x05,0x20,0x02] +# CHECK: or $4, $4, $1 # encoding: [0x00,0x81,0x20,0x25] + rol $4,1 +# CHECK: sll $1, $4, 1 # encoding: [0x00,0x04,0x08,0x40] +# CHECK: srl $4, $4, 31 # encoding: [0x00,0x04,0x27,0xc2] +# CHECK: or $4, $4, $1 # encoding: [0x00,0x81,0x20,0x25] + rol $4,$5,1 +# CHECK: sll $1, $5, 1 # encoding: [0x00,0x05,0x08,0x40] +# CHECK: srl $4, $5, 31 # encoding: [0x00,0x05,0x27,0xc2] +# CHECK: or $4, $4, $1 # encoding: [0x00,0x81,0x20,0x25] + rol $4,2 +# CHECK: sll $1, $4, 2 # encoding: [0x00,0x04,0x08,0x80] +# CHECK: srl $4, $4, 30 # encoding: [0x00,0x04,0x27,0x82] +# CHECK: or $4, $4, $1 # encoding: [0x00,0x81,0x20,0x25] + rol $4,$5,2 +# CHECK: sll $1, $5, 2 # encoding: [0x00,0x05,0x08,0x80] +# CHECK: srl $4, $5, 30 # encoding: [0x00,0x05,0x27,0x82] +# CHECK: or $4, $4, $1 # encoding: [0x00,0x81,0x20,0x25] + + ror $4,$5 +# CHECK: negu $1, $5 # encoding: [0x00,0x05,0x08,0x23] +# CHECK: sllv $1, $4, $1 # encoding: [0x00,0x24,0x08,0x04] +# CHECK: srlv $4, $4, $5 # encoding: [0x00,0xa4,0x20,0x06] +# CHECK: or $4, $4, $1 # encoding: [0x00,0x81,0x20,0x25] + ror $4,$5,$6 +# CHECK: negu $1, $6 # encoding: [0x00,0x06,0x08,0x23] +# CHECK: sllv $1, $5, $1 # encoding: [0x00,0x25,0x08,0x04] +# CHECK: srlv $4, $5, $6 # encoding: [0x00,0xc5,0x20,0x06] +# CHECK: or $4, $4, $1 # encoding: [0x00,0x81,0x20,0x25] + ror $4,0 +# CHECK: srl $1, $4, 0 # encoding: [0x00,0x04,0x08,0x02] +# CHECK: sll $4, $4, 32 # encoding: [0x00,0x04,0x20,0x00] +# CHECK: or $4, $4, $1 # encoding: [0x00,0x81,0x20,0x25] + ror $4,$5,0 +# CHECK: srl $1, $5, 0 # encoding: [0x00,0x05,0x08,0x02] +# CHECK: sll $4, $5, 32 # encoding: [0x00,0x05,0x20,0x00] +# CHECK: or $4, $4, $1 # encoding: [0x00,0x81,0x20,0x25] + ror $4,1 +# CHECK: srl $1, $4, 1 # encoding: [0x00,0x04,0x08,0x42] +# CHECK: sll $4, $4, 31 # encoding: [0x00,0x04,0x27,0xc0] +# CHECK: or $4, $4, $1 # encoding: [0x00,0x81,0x20,0x25] + ror $4,$5,1 +# CHECK: srl $1, $5, 1 # encoding: [0x00,0x05,0x08,0x42] +# CHECK: sll $4, $5, 31 # encoding: [0x00,0x05,0x27,0xc0] +# CHECK: or $4, $4, $1 # encoding: [0x00,0x81,0x20,0x25] + ror $4,2 +# CHECK: srl $1, $4, 2 # encoding: [0x00,0x04,0x08,0x82] +# CHECK: sll $4, $4, 30 # encoding: [0x00,0x04,0x27,0x80] +# CHECK: or $4, $4, $1 # encoding: [0x00,0x81,0x20,0x25] + ror $4,$5,2 +# CHECK: srl $1, $5, 2 # encoding: [0x00,0x05,0x08,0x82] +# CHECK: sll $4, $5, 30 # encoding: [0x00,0x05,0x27,0x80] +# CHECK: or $4, $4, $1 # encoding: [0x00,0x81,0x20,0x25]