diff options
| -rw-r--r-- | llvm/lib/Target/Mips/AsmParser/MipsAsmParser.cpp | 11 | ||||
| -rw-r--r-- | llvm/lib/Target/Mips/Disassembler/MipsDisassembler.cpp | 16 | ||||
| -rw-r--r-- | llvm/lib/Target/Mips/MCTargetDesc/MipsAsmBackend.cpp | 10 | ||||
| -rw-r--r-- | llvm/lib/Target/Mips/MCTargetDesc/MipsELFObjectWriter.cpp | 3 | ||||
| -rw-r--r-- | llvm/lib/Target/Mips/MCTargetDesc/MipsFixupKinds.h | 3 | ||||
| -rw-r--r-- | llvm/lib/Target/Mips/MCTargetDesc/MipsMCCodeEmitter.cpp | 22 | ||||
| -rw-r--r-- | llvm/lib/Target/Mips/MCTargetDesc/MipsMCCodeEmitter.h | 7 | ||||
| -rw-r--r-- | llvm/lib/Target/Mips/MicroMipsInstrFormats.td | 11 | ||||
| -rw-r--r-- | llvm/lib/Target/Mips/MicroMipsInstrInfo.td | 20 | ||||
| -rw-r--r-- | llvm/lib/Target/Mips/MipsLongBranch.cpp | 4 | ||||
| -rw-r--r-- | llvm/test/MC/Disassembler/Mips/micromips.txt | 6 | ||||
| -rw-r--r-- | llvm/test/MC/Disassembler/Mips/micromips_le.txt | 6 | ||||
| -rw-r--r-- | llvm/test/MC/Mips/micromips-16-bit-instructions.s | 10 | ||||
| -rw-r--r-- | llvm/test/MC/Mips/micromips-bad-branches.s | 8 | ||||
| -rw-r--r-- | llvm/test/MC/Mips/micromips-branch7.s | 27 | ||||
| -rw-r--r-- | llvm/test/MC/Mips/micromips-invalid.s | 2 | 
16 files changed, 166 insertions, 0 deletions
diff --git a/llvm/lib/Target/Mips/AsmParser/MipsAsmParser.cpp b/llvm/lib/Target/Mips/AsmParser/MipsAsmParser.cpp index 2eb757a9291..e7b336ef33e 100644 --- a/llvm/lib/Target/Mips/AsmParser/MipsAsmParser.cpp +++ b/llvm/lib/Target/Mips/AsmParser/MipsAsmParser.cpp @@ -1207,6 +1207,17 @@ bool MipsAsmParser::processInstruction(MCInst &Inst, SMLoc IDLoc,                              1LL << (inMicroMipsMode() ? 1 : 2)))          return Error(IDLoc, "branch to misaligned address");        break; +    case Mips::BEQZ16_MM: +    case Mips::BNEZ16_MM: +      assert(MCID.getNumOperands() == 2 && "unexpected number of operands"); +      Offset = Inst.getOperand(1); +      if (!Offset.isImm()) +        break; // We'll deal with this situation later on when applying fixups. +      if (!isIntN(8, Offset.getImm())) +        return Error(IDLoc, "branch target out of range"); +      if (OffsetToAlignment(Offset.getImm(), 2LL)) +        return Error(IDLoc, "branch to misaligned address"); +      break;      }    } diff --git a/llvm/lib/Target/Mips/Disassembler/MipsDisassembler.cpp b/llvm/lib/Target/Mips/Disassembler/MipsDisassembler.cpp index 3648211a0f9..da33f3b913c 100644 --- a/llvm/lib/Target/Mips/Disassembler/MipsDisassembler.cpp +++ b/llvm/lib/Target/Mips/Disassembler/MipsDisassembler.cpp @@ -228,6 +228,13 @@ static DecodeStatus DecodeBranchTarget26(MCInst &Inst,                                           uint64_t Address,                                           const void *Decoder); +// DecodeBranchTarget7MM - Decode microMIPS branch offset, which is +// shifted left by 1 bit. +static DecodeStatus DecodeBranchTarget7MM(MCInst &Inst, +                                          unsigned Offset, +                                          uint64_t Address, +                                          const void *Decoder); +  // DecodeBranchTargetMM - Decode microMIPS branch offset, which is  // shifted left by 1 bit.  static DecodeStatus DecodeBranchTargetMM(MCInst &Inst, @@ -1540,6 +1547,15 @@ static DecodeStatus DecodeBranchTarget26(MCInst &Inst,    return MCDisassembler::Success;  } +static DecodeStatus DecodeBranchTarget7MM(MCInst &Inst, +                                          unsigned Offset, +                                          uint64_t Address, +                                          const void *Decoder) { +  int32_t BranchOffset = SignExtend32<7>(Offset) << 1; +  Inst.addOperand(MCOperand::CreateImm(BranchOffset)); +  return MCDisassembler::Success; +} +  static DecodeStatus DecodeBranchTargetMM(MCInst &Inst,                                           unsigned Offset,                                           uint64_t Address, diff --git a/llvm/lib/Target/Mips/MCTargetDesc/MipsAsmBackend.cpp b/llvm/lib/Target/Mips/MCTargetDesc/MipsAsmBackend.cpp index efeb54d91b8..6670dc20855 100644 --- a/llvm/lib/Target/Mips/MCTargetDesc/MipsAsmBackend.cpp +++ b/llvm/lib/Target/Mips/MCTargetDesc/MipsAsmBackend.cpp @@ -103,6 +103,14 @@ static unsigned adjustFixupValue(const MCFixup &Fixup, uint64_t Value,    case Mips::fixup_MICROMIPS_26_S1:      Value >>= 1;      break; +  case Mips::fixup_MICROMIPS_PC7_S1: +    Value -= 4; +    // Forcing a signed division because Value can be negative. +    Value = (int64_t) Value / 2; +    // We now check if Value can be encoded as a 7-bit signed immediate. +    if (!isIntN(7, Value) && Ctx) +      Ctx->FatalError(Fixup.getLoc(), "out of range PC7 fixup"); +    break;    case Mips::fixup_MICROMIPS_PC16_S1:      Value -= 4;      // Forcing a signed division because Value can be negative. @@ -271,6 +279,7 @@ getFixupKindInfo(MCFixupKind Kind) const {      { "fixup_MICROMIPS_HI16",    0,     16,   0 },      { "fixup_MICROMIPS_LO16",    0,     16,   0 },      { "fixup_MICROMIPS_GOT16",   0,     16,   0 }, +    { "fixup_MICROMIPS_PC7_S1",  0,      7,   MCFixupKindInfo::FKF_IsPCRel },      { "fixup_MICROMIPS_PC16_S1", 0,     16,   MCFixupKindInfo::FKF_IsPCRel },      { "fixup_MICROMIPS_CALL16",  0,     16,   0 },      { "fixup_MICROMIPS_GOT_DISP",        0,     16,   0 }, @@ -334,6 +343,7 @@ getFixupKindInfo(MCFixupKind Kind) const {      { "fixup_MICROMIPS_HI16",   16,     16,   0 },      { "fixup_MICROMIPS_LO16",   16,     16,   0 },      { "fixup_MICROMIPS_GOT16",  16,     16,   0 }, +    { "fixup_MICROMIPS_PC7_S1",  9,      7,   MCFixupKindInfo::FKF_IsPCRel },      { "fixup_MICROMIPS_PC16_S1",16,     16,   MCFixupKindInfo::FKF_IsPCRel },      { "fixup_MICROMIPS_CALL16", 16,     16,   0 },      { "fixup_MICROMIPS_GOT_DISP",        16,     16,   0 }, diff --git a/llvm/lib/Target/Mips/MCTargetDesc/MipsELFObjectWriter.cpp b/llvm/lib/Target/Mips/MCTargetDesc/MipsELFObjectWriter.cpp index 7d03e903640..56aac4eaea4 100644 --- a/llvm/lib/Target/Mips/MCTargetDesc/MipsELFObjectWriter.cpp +++ b/llvm/lib/Target/Mips/MCTargetDesc/MipsELFObjectWriter.cpp @@ -162,6 +162,9 @@ unsigned MipsELFObjectWriter::GetRelocType(const MCValue &Target,    case Mips::fixup_MICROMIPS_GOT16:      Type = ELF::R_MICROMIPS_GOT16;      break; +  case Mips::fixup_MICROMIPS_PC7_S1: +    Type = ELF::R_MICROMIPS_PC7_S1; +    break;    case Mips::fixup_MICROMIPS_PC16_S1:      Type = ELF::R_MICROMIPS_PC16_S1;      break; diff --git a/llvm/lib/Target/Mips/MCTargetDesc/MipsFixupKinds.h b/llvm/lib/Target/Mips/MCTargetDesc/MipsFixupKinds.h index 317db1633a0..71c11d76b31 100644 --- a/llvm/lib/Target/Mips/MCTargetDesc/MipsFixupKinds.h +++ b/llvm/lib/Target/Mips/MCTargetDesc/MipsFixupKinds.h @@ -158,6 +158,9 @@ namespace Mips {      // resulting in - R_MICROMIPS_GOT16      fixup_MICROMIPS_GOT16, +    // resulting in - R_MICROMIPS_PC7_S1 +    fixup_MICROMIPS_PC7_S1, +      // resulting in - R_MICROMIPS_PC16_S1      fixup_MICROMIPS_PC16_S1, diff --git a/llvm/lib/Target/Mips/MCTargetDesc/MipsMCCodeEmitter.cpp b/llvm/lib/Target/Mips/MCTargetDesc/MipsMCCodeEmitter.cpp index 223a95a698a..0dc444c0f1c 100644 --- a/llvm/lib/Target/Mips/MCTargetDesc/MipsMCCodeEmitter.cpp +++ b/llvm/lib/Target/Mips/MCTargetDesc/MipsMCCodeEmitter.cpp @@ -220,6 +220,28 @@ getBranchTargetOpValue(const MCInst &MI, unsigned OpNo,    return 0;  } +/// getBranchTarget7OpValueMM - Return binary encoding of the microMIPS branch +/// target operand. If the machine operand requires relocation, +/// record the relocation and return zero. +unsigned MipsMCCodeEmitter:: +getBranchTarget7OpValueMM(const MCInst &MI, unsigned OpNo, +                          SmallVectorImpl<MCFixup> &Fixups, +                          const MCSubtargetInfo &STI) const { + +  const MCOperand &MO = MI.getOperand(OpNo); + +  // If the destination is an immediate, divide by 2. +  if (MO.isImm()) return MO.getImm() >> 1; + +  assert(MO.isExpr() && +         "getBranchTargetOpValueMM expects only expressions or immediates"); + +  const MCExpr *Expr = MO.getExpr(); +  Fixups.push_back(MCFixup::Create(0, Expr, +                                   MCFixupKind(Mips::fixup_MICROMIPS_PC7_S1))); +  return 0; +} +  /// getBranchTargetOpValue - Return binary encoding of the microMIPS branch  /// target operand. If the machine operand requires relocation,  /// record the relocation and return zero. diff --git a/llvm/lib/Target/Mips/MCTargetDesc/MipsMCCodeEmitter.h b/llvm/lib/Target/Mips/MCTargetDesc/MipsMCCodeEmitter.h index 863dd3b1527..0f0f49ddb97 100644 --- a/llvm/lib/Target/Mips/MCTargetDesc/MipsMCCodeEmitter.h +++ b/llvm/lib/Target/Mips/MCTargetDesc/MipsMCCodeEmitter.h @@ -101,6 +101,13 @@ public:                                    SmallVectorImpl<MCFixup> &Fixups,                                    const MCSubtargetInfo &STI) const; +  // getBranchTarget7OpValue - Return binary encoding of the microMIPS branch +  // target operand. If the machine operand requires relocation, +  // record the relocation and return zero. +  unsigned getBranchTarget7OpValueMM(const MCInst &MI, unsigned OpNo, +                                     SmallVectorImpl<MCFixup> &Fixups, +                                     const MCSubtargetInfo &STI) const; +    // getBranchTargetOpValue - Return binary encoding of the microMIPS branch    // target operand. If the machine operand requires relocation,    // record the relocation and return zero. diff --git a/llvm/lib/Target/Mips/MicroMipsInstrFormats.td b/llvm/lib/Target/Mips/MicroMipsInstrFormats.td index 978e39abf14..51b5c0cd612 100644 --- a/llvm/lib/Target/Mips/MicroMipsInstrFormats.td +++ b/llvm/lib/Target/Mips/MicroMipsInstrFormats.td @@ -227,6 +227,17 @@ class BRKSDBBP16_FM_MM<bits<6> op> {    let Inst{3-0}   = code_;  } +class BEQNEZ_FM_MM16<bits<6> op> { +  bits<3> rs; +  bits<7> offset; + +  bits<16> Inst; + +  let Inst{15-10} = op; +  let Inst{9-7}   = rs; +  let Inst{6-0}   = offset; +} +  //===----------------------------------------------------------------------===//  // MicroMIPS 32-bit Instruction Formats  //===----------------------------------------------------------------------===// diff --git a/llvm/lib/Target/Mips/MicroMipsInstrInfo.td b/llvm/lib/Target/Mips/MicroMipsInstrInfo.td index 77686290ecb..241f4528658 100644 --- a/llvm/lib/Target/Mips/MicroMipsInstrInfo.td +++ b/llvm/lib/Target/Mips/MicroMipsInstrInfo.td @@ -128,6 +128,13 @@ def calltarget_mm : Operand<iPTR> {    let EncoderMethod = "getJumpTargetOpValueMM";  } +def brtarget7_mm : Operand<OtherVT> { +  let EncoderMethod = "getBranchTarget7OpValueMM"; +  let OperandType   = "OPERAND_PCREL"; +  let DecoderMethod = "DecodeBranchTarget7MM"; +  let ParserMatchClass = MipsJumpTargetAsmOperand; +} +  def brtarget_mm : Operand<OtherVT> {    let EncoderMethod = "getBranchTargetOpValueMM";    let OperandType   = "OPERAND_PCREL"; @@ -382,6 +389,15 @@ class BrkSdbbp16MM<string opstr> :                    !strconcat(opstr, "\t$code_"),                    [], NoItinerary, FrmOther>; +class CBranchZeroMM<string opstr, DAGOperand opnd, RegisterOperand RO> : +  MicroMipsInst16<(outs), (ins RO:$rs, opnd:$offset), +                  !strconcat(opstr, "\t$rs, $offset"), [], IIBranch, FrmI> { +  let isBranch = 1; +  let isTerminator = 1; +  let hasDelaySlot = 1; +  let Defs = [AT]; +} +  // MicroMIPS Jump and Link (Call) - Short Delay Slot  let isCall = 1, hasDelaySlot = 1, Defs = [RA] in {    class JumpLinkMM<string opstr, DAGOperand opnd> : @@ -512,6 +528,10 @@ def JALRS16_MM : JumpLinkRegSMM16<"jalrs16", GPR32Opnd>, JALR_FM_MM16<0x0f>;  def JRC16_MM : JumpRegCMM16<"jrc", GPR32Opnd>, JALR_FM_MM16<0x0d>;  def JRADDIUSP : JumpRAddiuStackMM16, JRADDIUSP_FM_MM16<0x18>;  def JR16_MM : JumpRegMM16<"jr16", GPR32Opnd>, JALR_FM_MM16<0x0c>; +def BEQZ16_MM : CBranchZeroMM<"beqz16", brtarget7_mm, GPRMM16Opnd>, +                BEQNEZ_FM_MM16<0x23>; +def BNEZ16_MM : CBranchZeroMM<"bnez16", brtarget7_mm, GPRMM16Opnd>, +                BEQNEZ_FM_MM16<0x2b>;  def BREAK16_MM : BrkSdbbp16MM<"break16">, BRKSDBBP16_FM_MM<0x28>;  def SDBBP16_MM : BrkSdbbp16MM<"sdbbp16">, BRKSDBBP16_FM_MM<0x2C>; diff --git a/llvm/lib/Target/Mips/MipsLongBranch.cpp b/llvm/lib/Target/Mips/MipsLongBranch.cpp index 9d873052cab..aae0922e79e 100644 --- a/llvm/lib/Target/Mips/MipsLongBranch.cpp +++ b/llvm/lib/Target/Mips/MipsLongBranch.cpp @@ -247,6 +247,10 @@ void MipsLongBranch::replaceBranch(MachineBasicBlock &MBB, Iter Br,  }  // Expand branch instructions to long branches. +// TODO: This function has to be fixed for beqz16 and bnez16, because it +// currently assumes that all branches have 16-bit offsets, and will produce +// wrong code if branches whose allowed offsets are [-128, -126, ..., 126] +// are present.  void MipsLongBranch::expandToLongBranch(MBBInfo &I) {    MachineBasicBlock::iterator Pos;    MachineBasicBlock *MBB = I.Br->getParent(), *TgtMBB = getTargetMBB(*I.Br); diff --git a/llvm/test/MC/Disassembler/Mips/micromips.txt b/llvm/test/MC/Disassembler/Mips/micromips.txt index 9acad9f8692..07c1df91441 100644 --- a/llvm/test/MC/Disassembler/Mips/micromips.txt +++ b/llvm/test/MC/Disassembler/Mips/micromips.txt @@ -468,3 +468,9 @@  # CHECK: sw $4, 124($sp)  0xc8 0x9f + +# CHECK: beqz16 $6, 20 +0x8f 0x0a + +# CHECK: bnez16 $6, 20 +0xaf 0x0a diff --git a/llvm/test/MC/Disassembler/Mips/micromips_le.txt b/llvm/test/MC/Disassembler/Mips/micromips_le.txt index 1015c24c159..9a8c4a94530 100644 --- a/llvm/test/MC/Disassembler/Mips/micromips_le.txt +++ b/llvm/test/MC/Disassembler/Mips/micromips_le.txt @@ -468,3 +468,9 @@  # CHECK: sw $4, 124($sp)  0x9f 0xc8 + +# CHECK: beqz16 $6, 20 +0x0a 0x8f + +# CHECK: bnez16 $6, 20 +0x0a 0xaf diff --git a/llvm/test/MC/Mips/micromips-16-bit-instructions.s b/llvm/test/MC/Mips/micromips-16-bit-instructions.s index 7a9e84baa3d..8fd6d450ac9 100644 --- a/llvm/test/MC/Mips/micromips-16-bit-instructions.s +++ b/llvm/test/MC/Mips/micromips-16-bit-instructions.s @@ -49,6 +49,10 @@  # CHECK-EL: nop                     # encoding: [0x00,0x0c]  # CHECK-EL: jr16    $9              # encoding: [0x89,0x45]  # CHECK-EL: nop                     # encoding: [0x00,0x00,0x00,0x00] +# CHECK-EL: beqz16 $6, 20           # encoding: [0x0a,0x8f] +# CHECK-EL: nop                     # encoding: [0x00,0x00,0x00,0x00] +# CHECK-EL: bnez16 $6, 20           # encoding: [0x0a,0xaf] +# CHECK-EL: nop                     # encoding: [0x00,0x00,0x00,0x00]  # CHECK-EL: break16 8               # encoding: [0x88,0x46]  # CHECK-EL: sdbbp16 14              # encoding: [0xce,0x46]  #------------------------------------------------------------------------------ @@ -94,6 +98,10 @@  # CHECK-EB: nop                     # encoding: [0x0c,0x00]  # CHECK-EB: jr16    $9              # encoding: [0x45,0x89]  # CHECK-EB: nop                     # encoding: [0x00,0x00,0x00,0x00] +# CHECK-EB: beqz16 $6, 20           # encoding: [0x8f,0x0a] +# CHECK-EB: nop                     # encoding: [0x00,0x00,0x00,0x00] +# CHECK-EB: bnez16 $6, 20           # encoding: [0xaf,0x0a] +# CHECK-EB: nop                     # encoding: [0x00,0x00,0x00,0x00]  # CHECK-EB: break16 8               # encoding: [0x46,0x88]  # CHECK-EB: sdbbp16 14              # encoding: [0x46,0xce] @@ -135,5 +143,7 @@      jraddiusp 20      jalrs16 $9      jr16    $9 +    beqz16 $6, 20 +    bnez16 $6, 20      break16 8      sdbbp16 14 diff --git a/llvm/test/MC/Mips/micromips-bad-branches.s b/llvm/test/MC/Mips/micromips-bad-branches.s index 573605e18d6..f64cd9f9e5b 100644 --- a/llvm/test/MC/Mips/micromips-bad-branches.s +++ b/llvm/test/MC/Mips/micromips-bad-branches.s @@ -126,6 +126,11 @@  # CHECK: error: branch target out of range  # CHECK:        bc1t $fcc0, 65536 +# CHECK: error: branch to misaligned address +# CHECK:        beqz16 $6, 31 +# CHECK: error: branch target out of range +# CHECK:        beqz16 $6, 130 +          b -65535          b -65536          b -65537 @@ -223,3 +228,6 @@          bc1t $fcc0, 65534          bc1t $fcc0, 65535          bc1t $fcc0, 65536 + +        beqz16 $6, 31 +        beqz16 $6, 130 diff --git a/llvm/test/MC/Mips/micromips-branch7.s b/llvm/test/MC/Mips/micromips-branch7.s new file mode 100644 index 00000000000..deb7307e938 --- /dev/null +++ b/llvm/test/MC/Mips/micromips-branch7.s @@ -0,0 +1,27 @@ +# RUN: llvm-mc %s -triple=mipsel-unknown-linux -show-encoding \ +# RUN: -mattr=micromips | FileCheck %s -check-prefix=CHECK-FIXUP +# RUN: llvm-mc %s -filetype=obj -triple=mipsel-unknown-linux \ +# RUN: -mattr=micromips | llvm-readobj -r \ +# RUN: | FileCheck %s -check-prefix=CHECK-ELF +#------------------------------------------------------------------------------ +# Check that the assembler can handle the documented syntax +# for relocations. +#------------------------------------------------------------------------------ +# CHECK-FIXUP: beqz16 $6, bar  # encoding: [0b0AAAAAAA,0x8f] +# CHECK-FIXUP:                 #   fixup A - offset: 0, +# CHECK-FIXUP:                     value: bar, kind: fixup_MICROMIPS_PC7_S1 +# CHECK-FIXUP: nop             # encoding: [0x00,0x00,0x00,0x00] +# CHECK-FIXUP: bnez16 $6, bar  # encoding: [0b0AAAAAAA,0xaf] +# CHECK-FIXUP:                 #   fixup A - offset: 0, +# CHECK-FIXUP:                     value: bar, kind: fixup_MICROMIPS_PC7_S1 +# CHECK-FIXUP: nop             # encoding: [0x00,0x00,0x00,0x00] +#------------------------------------------------------------------------------ +# Check that the appropriate relocations were created. +#------------------------------------------------------------------------------ +# CHECK-ELF: Relocations [ +# CHECK-ELF:     0x{{[0-9,A-F]+}} R_MICROMIPS_PC7_S1 +# CHECK-ELF:     0x{{[0-9,A-F]+}} R_MICROMIPS_PC7_S1 +# CHECK-ELF: ] + +  beqz16 $6, bar +  bnez16 $6, bar diff --git a/llvm/test/MC/Mips/micromips-invalid.s b/llvm/test/MC/Mips/micromips-invalid.s index b94313a7fc1..1dbfb113a2c 100644 --- a/llvm/test/MC/Mips/micromips-invalid.s +++ b/llvm/test/MC/Mips/micromips-invalid.s @@ -64,3 +64,5 @@    sw16  $7, 4($10)  # CHECK: :[[@LINE]]:{{[0-9]+}}: error: invalid operand for instruction    cache 256, 8($5)  # CHECK: :[[@LINE]]:{{[0-9]+}}: error: immediate operand value out of range    pref 256, 8($5)   # CHECK: :[[@LINE]]:{{[0-9]+}}: error: immediate operand value out of range +  beqz16 $9, 20 # CHECK: :[[@LINE]]:{{[0-9]+}}: error: invalid operand for instruction +  bnez16 $9, 20 # CHECK: :[[@LINE]]:{{[0-9]+}}: error: invalid operand for instruction  | 

