Index: lib/Target/Mips/AsmParser/MipsAsmParser.cpp =================================================================== --- lib/Target/Mips/AsmParser/MipsAsmParser.cpp +++ lib/Target/Mips/AsmParser/MipsAsmParser.cpp @@ -1113,6 +1113,17 @@ } // for } // if load/store + if (inMicroMipsMode() && Inst.getOpcode() == Mips::ADDIUPC_MM) { + MCOperand Opnd = Inst.getOperand(1); + if (!Opnd.isImm()) + return Error(IDLoc, "expected immediate operand kind"); + int Imm = Opnd.getImm(); + if (!isIntN(25, Imm)) + return Error(IDLoc, "immediate operand value out of range"); + if (OffsetToAlignment(Imm, 4LL)) + return Error(IDLoc, "immediate operand value out of range"); + } + if (needsExpansion(Inst)) return expandInstruction(Inst, IDLoc, Instructions); else Index: lib/Target/Mips/Disassembler/MipsDisassembler.cpp =================================================================== --- lib/Target/Mips/Disassembler/MipsDisassembler.cpp +++ lib/Target/Mips/Disassembler/MipsDisassembler.cpp @@ -305,6 +305,9 @@ static DecodeStatus DecodeSimm18Lsl3(MCInst &Inst, unsigned Insn, uint64_t Address, const void *Decoder); +static DecodeStatus DecodeSimm23Lsl2(MCInst &Inst, unsigned Insn, + uint64_t Address, const void *Decoder); + /// INSVE_[BHWD] have an implicit operand that the generated decoder doesn't /// handle. template @@ -1338,3 +1341,9 @@ Inst.addOperand(MCOperand::CreateImm(SignExtend32<18>(Insn) * 8)); return MCDisassembler::Success; } + +static DecodeStatus DecodeSimm23Lsl2(MCInst &Inst, unsigned Insn, + uint64_t Address, const void *Decoder) { + Inst.addOperand(MCOperand::CreateImm(SignExtend32<23>(Insn) * 4)); + return MCDisassembler::Success; +} Index: lib/Target/Mips/MCTargetDesc/MipsMCCodeEmitter.h =================================================================== --- lib/Target/Mips/MCTargetDesc/MipsMCCodeEmitter.h +++ lib/Target/Mips/MCTargetDesc/MipsMCCodeEmitter.h @@ -145,6 +145,10 @@ SmallVectorImpl &Fixups, const MCSubtargetInfo &STI) const; + unsigned getSimm23Lsl2Encoding(const MCInst &MI, unsigned OpNo, + SmallVectorImpl &Fixups, + const MCSubtargetInfo &STI) const; + unsigned getExprOpValue(const MCExpr *Expr, SmallVectorImpl &Fixups, const MCSubtargetInfo &STI) const; Index: lib/Target/Mips/MCTargetDesc/MipsMCCodeEmitter.cpp =================================================================== --- lib/Target/Mips/MCTargetDesc/MipsMCCodeEmitter.cpp +++ lib/Target/Mips/MCTargetDesc/MipsMCCodeEmitter.cpp @@ -659,4 +659,16 @@ return 0; } +unsigned +MipsMCCodeEmitter::getSimm23Lsl2Encoding(const MCInst &MI, unsigned OpNo, + SmallVectorImpl &Fixups, + const MCSubtargetInfo &STI) const { + const MCOperand &MO = MI.getOperand(OpNo); + assert(MO.isImm() && "getSimm23Lsl2Encoding expects only an immediate"); + // The immediate is encoded as 'immediate << 2'. + unsigned Res = static_cast(MO.getImm()); + assert((Res & 3) == 0); + return Res >> 2; +} + #include "MipsGenMCCodeEmitter.inc" Index: lib/Target/Mips/MicroMipsInstrFormats.td =================================================================== --- lib/Target/Mips/MicroMipsInstrFormats.td +++ lib/Target/Mips/MicroMipsInstrFormats.td @@ -633,3 +633,14 @@ let Inst{20-16} = rs; let Inst{15-0} = offset; } + +class ADDIUPC_FM_MM { + bits<3> rs; + bits<23> imm; + + bits<32> Inst; + + let Inst{31-26} = 0x1e; + let Inst{25-23} = rs; + let Inst{22-0} = imm; +} Index: lib/Target/Mips/MicroMipsInstrInfo.td =================================================================== --- lib/Target/Mips/MicroMipsInstrInfo.td +++ lib/Target/Mips/MicroMipsInstrInfo.td @@ -26,6 +26,11 @@ let DecoderMethod = "DecodeBranchTargetMM"; } +def simm23_lsl2 : Operand { + let EncoderMethod = "getSimm23Lsl2Encoding"; + let DecoderMethod = "DecodeSimm23Lsl2"; +} + class CompactBranchMM : InstSE<(outs), (ins RO:$rs, opnd:$offset), @@ -104,6 +109,11 @@ let Defs = [RA]; } +class AddImmUPC : + InstSE<(outs RO:$rd), (ins simm23_lsl2:$imm), + !strconcat(opstr, "\t$rd, $imm"), [], NoItinerary, FrmR> { +} + def MFHI16_MM : MoveFromHILOMM<"mfhi", GPR32Opnd, AC0>, MFHILO_FM_MM16<0x10>; def MFLO16_MM : MoveFromHILOMM<"mflo", GPR32Opnd, AC0>, MFHILO_FM_MM16<0x12>; def MOVE16_MM : MoveMM16<"move", GPR32Opnd>, MOVE_FM_MM16<0x03>; @@ -165,6 +175,9 @@ def UDIV_MM : MMRel, Div<"divu", II_DIVU, GPR32Opnd, [HI0, LO0]>, MULT_FM_MM<0x2ec>; + /// Arithmetic Instructions with PC and Immediate + def ADDIUPC_MM : AddImmUPC<"addiupc", GPRMM16Opnd>, ADDIUPC_FM_MM; + /// Shift Instructions def SLL_MM : MMRel, shift_rotate_imm<"sll", uimm5, GPR32Opnd, II_SLL>, SRA_FM_MM<0, 0>; Index: test/MC/Mips/micromips-alu-instructions.s =================================================================== --- test/MC/Mips/micromips-alu-instructions.s +++ test/MC/Mips/micromips-alu-instructions.s @@ -38,6 +38,9 @@ # CHECK-EL: multu $9, $7 # encoding: [0xe9,0x00,0x3c,0x9b] # CHECK-EL: div $zero, $9, $7 # encoding: [0xe9,0x00,0x3c,0xab] # CHECK-EL: divu $zero, $9, $7 # encoding: [0xe9,0x00,0x3c,0xbb] +# CHECK-EL: addiupc $2, 20 # encoding: [0x00,0x79,0x05,0x00] +# CHECK-EL: addiupc $7, 16777212 # encoding: [0xbf,0x7b,0xff,0xff] +# CHECK-EL: addiupc $7, -16777216 # encoding: [0xc0,0x7b,0x00,0x00] #------------------------------------------------------------------------------ # Big endian #------------------------------------------------------------------------------ @@ -72,6 +75,9 @@ # CHECK-EB: multu $9, $7 # encoding: [0x00,0xe9,0x9b,0x3c] # CHECK-EB: div $zero, $9, $7 # encoding: [0x00,0xe9,0xab,0x3c] # CHECK-EB: divu $zero, $9, $7 # encoding: [0x00,0xe9,0xbb,0x3c] +# CHECK-EB: addiupc $2, 20 # encoding: [0x79,0x00,0x00,0x05] +# CHECK-EB: addiupc $7, 16777212 # encoding: [0x7b,0xbf,0xff,0xff] +# CHECK-EB: addiupc $7, -16777216 # encoding: [0x7b,0xc0,0x00,0x00] add $9, $6, $7 add $9, $6, 17767 addu $9, $6, -15001 @@ -104,3 +110,6 @@ multu $9, $7 div $0, $9, $7 divu $0, $9, $7 + addiupc $2, 20 + addiupc $7, 16777212 + addiupc $7, -16777216 Index: test/MC/Mips/micromips-invalid.s =================================================================== --- /dev/null +++ test/MC/Mips/micromips-invalid.s @@ -0,0 +1,6 @@ +# RUN: not llvm-mc %s -triple=mipsel -show-encoding -mattr=micromips 2>%t1 +# RUN: FileCheck %s < %t1 + + addiupc $7, 16777216 # CHECK: :[[@LINE]]:{{[0-9]+}}: error: immediate operand value out of range + addiupc $6, -16777220 # CHECK: :[[@LINE]]:{{[0-9]+}}: error: immediate operand value out of range + addiupc $3, 3 # CHECK: :[[@LINE]]:{{[0-9]+}}: error: immediate operand value out of range