Skip to content

Commit

Permalink
[mips][microMIPS] MicroMIPS 16-bit unconditional branch instruction B
Browse files Browse the repository at this point in the history
Implement microMIPS 16-bit unconditional branch instruction B.

Implemented 16-bit microMIPS unconditional instruction has real name B16, and
B is an alias which expands to either B16 or BEQ according to the rules:
b 256 --> b16 256 # R_MICROMIPS_PC10_S1
b 12256 --> beq $zero, $zero, 12256 # R_MICROMIPS_PC16_S1
b label --> beq $zero, $zero, label # R_MICROMIPS_PC16_S1

Differential Revision: http://reviews.llvm.org/D3514

llvm-svn: 226657
  • Loading branch information
Jozef Kolek committed Jan 21, 2015
1 parent 2c6d732 commit 5cfebdd
Show file tree
Hide file tree
Showing 18 changed files with 202 additions and 35 deletions.
50 changes: 50 additions & 0 deletions llvm/lib/Target/Mips/AsmParser/MipsAsmParser.cpp
Expand Up @@ -171,6 +171,8 @@ class MipsAsmParser : public MCTargetAsmParser {

bool expandLoadAddressReg(MCInst &Inst, SMLoc IDLoc,
SmallVectorImpl<MCInst> &Instructions);
bool expandUncondBranchMMPseudo(MCInst &Inst, SMLoc IDLoc,
SmallVectorImpl<MCInst> &Instructions);

void expandLoadAddressSym(MCInst &Inst, SMLoc IDLoc,
SmallVectorImpl<MCInst> &Instructions);
Expand Down Expand Up @@ -1422,6 +1424,7 @@ bool MipsAsmParser::needsExpansion(MCInst &Inst) {
case Mips::LoadAddr32Imm:
case Mips::LoadAddr32Reg:
case Mips::LoadImm64Reg:
case Mips::B_MM_Pseudo:
return true;
default:
return false;
Expand All @@ -1444,6 +1447,8 @@ bool MipsAsmParser::expandInstruction(MCInst &Inst, SMLoc IDLoc,
return expandLoadAddressImm(Inst, IDLoc, Instructions);
case Mips::LoadAddr32Reg:
return expandLoadAddressReg(Inst, IDLoc, Instructions);
case Mips::B_MM_Pseudo:
return expandUncondBranchMMPseudo(Inst, IDLoc, Instructions);
}
}

Expand Down Expand Up @@ -1729,6 +1734,51 @@ MipsAsmParser::expandLoadAddressSym(MCInst &Inst, SMLoc IDLoc,
}
}

bool MipsAsmParser::
expandUncondBranchMMPseudo(MCInst &Inst, SMLoc IDLoc,
SmallVectorImpl<MCInst> &Instructions) {
const MCInstrDesc &MCID = getInstDesc(Inst.getOpcode());

assert(MCID.getNumOperands() == 1 && "unexpected number of operands");

MCOperand Offset = Inst.getOperand(0);
if (Offset.isExpr()) {
Inst.clear();
Inst.setOpcode(Mips::BEQ_MM);
Inst.addOperand(MCOperand::CreateReg(Mips::ZERO));
Inst.addOperand(MCOperand::CreateReg(Mips::ZERO));
Inst.addOperand(MCOperand::CreateExpr(Offset.getExpr()));
} else {
assert(Offset.isImm() && "expected immediate operand kind");
if (isIntN(11, Offset.getImm())) {
// If offset fits into 11 bits then this instruction becomes microMIPS
// 16-bit unconditional branch instruction.
Inst.setOpcode(Mips::B16_MM);
} else {
if (!isIntN(17, Offset.getImm()))
Error(IDLoc, "branch target out of range");
if (OffsetToAlignment(Offset.getImm(), 1LL << 1))
Error(IDLoc, "branch to misaligned address");
Inst.clear();
Inst.setOpcode(Mips::BEQ_MM);
Inst.addOperand(MCOperand::CreateReg(Mips::ZERO));
Inst.addOperand(MCOperand::CreateReg(Mips::ZERO));
Inst.addOperand(MCOperand::CreateImm(Offset.getImm()));
}
}
Instructions.push_back(Inst);

if (AssemblerOptions.back()->isReorder()) {
// If .set reorder is active, emit a NOP after the branch instruction.
MCInst NopInst;
NopInst.setOpcode(Mips::MOVE16_MM);
NopInst.addOperand(MCOperand::CreateReg(Mips::ZERO));
NopInst.addOperand(MCOperand::CreateReg(Mips::ZERO));
Instructions.push_back(NopInst);
}
return false;
}

void MipsAsmParser::expandMemInst(MCInst &Inst, SMLoc IDLoc,
SmallVectorImpl<MCInst> &Instructions,
bool isLoad, bool isImmOpnd) {
Expand Down
16 changes: 16 additions & 0 deletions llvm/lib/Target/Mips/Disassembler/MipsDisassembler.cpp
Expand Up @@ -235,6 +235,13 @@ static DecodeStatus DecodeBranchTarget7MM(MCInst &Inst,
uint64_t Address,
const void *Decoder);

// DecodeBranchTarget10MM - Decode microMIPS branch offset, which is
// shifted left by 1 bit.
static DecodeStatus DecodeBranchTarget10MM(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,
Expand Down Expand Up @@ -1580,6 +1587,15 @@ static DecodeStatus DecodeBranchTarget7MM(MCInst &Inst,
return MCDisassembler::Success;
}

static DecodeStatus DecodeBranchTarget10MM(MCInst &Inst,
unsigned Offset,
uint64_t Address,
const void *Decoder) {
int32_t BranchOffset = SignExtend32<10>(Offset) << 1;
Inst.addOperand(MCOperand::CreateImm(BranchOffset));
return MCDisassembler::Success;
}

static DecodeStatus DecodeBranchTargetMM(MCInst &Inst,
unsigned Offset,
uint64_t Address,
Expand Down
1 change: 1 addition & 0 deletions llvm/lib/Target/Mips/InstPrinter/MipsInstPrinter.cpp
Expand Up @@ -290,6 +290,7 @@ bool MipsInstPrinter::printAlias(const char *Str, const MCInst &MI,
bool MipsInstPrinter::printAlias(const MCInst &MI, raw_ostream &OS) {
switch (MI.getOpcode()) {
case Mips::BEQ:
case Mips::BEQ_MM:
// beq $zero, $zero, $L2 => b $L2
// beq $r0, $zero, $L2 => beqz $r0, $L2
return (isReg<Mips::ZERO>(MI, 0) && isReg<Mips::ZERO>(MI, 1) &&
Expand Down
14 changes: 13 additions & 1 deletion llvm/lib/Target/Mips/MCTargetDesc/MipsAsmBackend.cpp
Expand Up @@ -111,6 +111,14 @@ static unsigned adjustFixupValue(const MCFixup &Fixup, uint64_t Value,
if (!isIntN(7, Value) && Ctx)
Ctx->FatalError(Fixup.getLoc(), "out of range PC7 fixup");
break;
case Mips::fixup_MICROMIPS_PC10_S1:
Value -= 2;
// Forcing a signed division because Value can be negative.
Value = (int64_t) Value / 2;
// We now check if Value can be encoded as a 10-bit signed immediate.
if (!isIntN(10, Value) && Ctx)
Ctx->FatalError(Fixup.getLoc(), "out of range PC10 fixup");
break;
case Mips::fixup_MICROMIPS_PC16_S1:
Value -= 4;
// Forcing a signed division because Value can be negative.
Expand Down Expand Up @@ -157,7 +165,8 @@ MCObjectWriter *MipsAsmBackend::createObjectWriter(raw_ostream &OS) const {
// microMIPS: x | x | a | b

static bool needsMMLEByteOrder(unsigned Kind) {
return Kind >= Mips::fixup_MICROMIPS_26_S1 &&
return Kind != Mips::fixup_MICROMIPS_PC10_S1 &&
Kind >= Mips::fixup_MICROMIPS_26_S1 &&
Kind < Mips::LastTargetFixupKind;
}

Expand Down Expand Up @@ -190,6 +199,7 @@ void MipsAsmBackend::applyFixup(const MCFixup &Fixup, char *Data,
switch ((unsigned)Kind) {
case FK_Data_2:
case Mips::fixup_Mips_16:
case Mips::fixup_MICROMIPS_PC10_S1:
FullSize = 2;
break;
case FK_Data_8:
Expand Down Expand Up @@ -280,6 +290,7 @@ getFixupKindInfo(MCFixupKind Kind) const {
{ "fixup_MICROMIPS_LO16", 0, 16, 0 },
{ "fixup_MICROMIPS_GOT16", 0, 16, 0 },
{ "fixup_MICROMIPS_PC7_S1", 0, 7, MCFixupKindInfo::FKF_IsPCRel },
{ "fixup_MICROMIPS_PC10_S1", 0, 10, 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 },
Expand Down Expand Up @@ -344,6 +355,7 @@ getFixupKindInfo(MCFixupKind Kind) const {
{ "fixup_MICROMIPS_LO16", 16, 16, 0 },
{ "fixup_MICROMIPS_GOT16", 16, 16, 0 },
{ "fixup_MICROMIPS_PC7_S1", 9, 7, MCFixupKindInfo::FKF_IsPCRel },
{ "fixup_MICROMIPS_PC10_S1", 6, 10, 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 },
Expand Down
3 changes: 3 additions & 0 deletions llvm/lib/Target/Mips/MCTargetDesc/MipsELFObjectWriter.cpp
Expand Up @@ -165,6 +165,9 @@ unsigned MipsELFObjectWriter::GetRelocType(const MCValue &Target,
case Mips::fixup_MICROMIPS_PC7_S1:
Type = ELF::R_MICROMIPS_PC7_S1;
break;
case Mips::fixup_MICROMIPS_PC10_S1:
Type = ELF::R_MICROMIPS_PC10_S1;
break;
case Mips::fixup_MICROMIPS_PC16_S1:
Type = ELF::R_MICROMIPS_PC16_S1;
break;
Expand Down
3 changes: 3 additions & 0 deletions llvm/lib/Target/Mips/MCTargetDesc/MipsFixupKinds.h
Expand Up @@ -161,6 +161,9 @@ namespace Mips {
// resulting in - R_MICROMIPS_PC7_S1
fixup_MICROMIPS_PC7_S1,

// resulting in - R_MICROMIPS_PC10_S1
fixup_MICROMIPS_PC10_S1,

// resulting in - R_MICROMIPS_PC16_S1
fixup_MICROMIPS_PC16_S1,

Expand Down
22 changes: 22 additions & 0 deletions llvm/lib/Target/Mips/MCTargetDesc/MipsMCCodeEmitter.cpp
Expand Up @@ -242,6 +242,28 @@ getBranchTarget7OpValueMM(const MCInst &MI, unsigned OpNo,
return 0;
}

/// getBranchTargetOpValueMMPC10 - Return binary encoding of the microMIPS
/// 10-bit branch target operand. If the machine operand requires relocation,
/// record the relocation and return zero.
unsigned MipsMCCodeEmitter::
getBranchTargetOpValueMMPC10(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() &&
"getBranchTargetOpValuePC10 expects only expressions or immediates");

const MCExpr *Expr = MO.getExpr();
Fixups.push_back(MCFixup::Create(0, Expr,
MCFixupKind(Mips::fixup_MICROMIPS_PC10_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.
Expand Down
7 changes: 7 additions & 0 deletions llvm/lib/Target/Mips/MCTargetDesc/MipsMCCodeEmitter.h
Expand Up @@ -108,6 +108,13 @@ class MipsMCCodeEmitter : public MCCodeEmitter {
SmallVectorImpl<MCFixup> &Fixups,
const MCSubtargetInfo &STI) const;

// getBranchTargetOpValueMMPC10 - Return binary encoding of the microMIPS
// 10-bit branch target operand. If the machine operand requires relocation,
// record the relocation and return zero.
unsigned getBranchTargetOpValueMMPC10(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.
Expand Down
9 changes: 9 additions & 0 deletions llvm/lib/Target/Mips/MicroMipsInstrFormats.td
Expand Up @@ -238,6 +238,15 @@ class BEQNEZ_FM_MM16<bits<6> op> {
let Inst{6-0} = offset;
}

class B16_FM {
bits<10> offset;

bits<16> Inst;

let Inst{15-10} = 0x33;
let Inst{9-0} = offset;
}

//===----------------------------------------------------------------------===//
// MicroMIPS 32-bit Instruction Formats
//===----------------------------------------------------------------------===//
Expand Down
27 changes: 27 additions & 0 deletions llvm/lib/Target/Mips/MicroMipsInstrInfo.td
Expand Up @@ -135,10 +135,18 @@ def brtarget7_mm : Operand<OtherVT> {
let ParserMatchClass = MipsJumpTargetAsmOperand;
}

def brtarget10_mm : Operand<OtherVT> {
let EncoderMethod = "getBranchTargetOpValueMMPC10";
let OperandType = "OPERAND_PCREL";
let DecoderMethod = "DecodeBranchTarget10MM";
let ParserMatchClass = MipsJumpTargetAsmOperand;
}

def brtarget_mm : Operand<OtherVT> {
let EncoderMethod = "getBranchTargetOpValueMM";
let OperandType = "OPERAND_PCREL";
let DecoderMethod = "DecodeBranchTargetMM";
let ParserMatchClass = MipsJumpTargetAsmOperand;
}

def simm23_lsl2 : Operand<i32> {
Expand Down Expand Up @@ -490,6 +498,18 @@ class LoadMultMM16<string opstr,
let mayLoad = 1;
}

class UncondBranchMM16<string opstr> :
MicroMipsInst16<(outs), (ins brtarget10_mm:$offset),
!strconcat(opstr, "\t$offset"),
[], IIBranch, FrmI> {
let isBranch = 1;
let isTerminator = 1;
let isBarrier = 1;
let hasDelaySlot = 1;
let Predicates = [RelocPIC, InMicroMips];
let Defs = [AT];
}

def ADDU16_MM : ArithRMM16<"addu16", GPRMM16Opnd, 1, II_ADDU, add>,
ARITH_FM_MM16<0>;
def SUBU16_MM : ArithRMM16<"subu16", GPRMM16Opnd, 0, II_SUBU, sub>,
Expand Down Expand Up @@ -541,6 +561,7 @@ 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 B16_MM : UncondBranchMM16<"b16">, B16_FM;
def BREAK16_MM : BrkSdbbp16MM<"break16">, BRKSDBBP16_FM_MM<0x28>;
def SDBBP16_MM : BrkSdbbp16MM<"sdbbp16">, BRKSDBBP16_FM_MM<0x2C>;

Expand Down Expand Up @@ -830,6 +851,12 @@ def : MipsPat<(srl GPR32:$src, immZExt5:$imm),
// MicroMips instruction aliases
//===----------------------------------------------------------------------===//

class UncondBranchMMPseudo<string opstr> :
MipsAsmPseudoInst<(outs), (ins brtarget_mm:$offset),
!strconcat(opstr, "\t$offset")>;

def B_MM_Pseudo : UncondBranchMMPseudo<"b">;

def : MipsInstAlias<"wait", (WAIT_MM 0x0), 1>;
def : MipsInstAlias<"nop", (SLL_MM ZERO, ZERO, 0), 1>;
def : MipsInstAlias<"nop", (MOVE16_MM ZERO, ZERO), 1>;
Expand Down
2 changes: 2 additions & 0 deletions llvm/lib/Target/Mips/MipsInstrInfo.td
Expand Up @@ -1582,7 +1582,9 @@ def : MipsInstAlias<"mfc0 $rt, $rd", (MFC0 GPR32Opnd:$rt, GPR32Opnd:$rd, 0), 0>;
def : MipsInstAlias<"mtc0 $rt, $rd", (MTC0 GPR32Opnd:$rt, GPR32Opnd:$rd, 0), 0>;
def : MipsInstAlias<"mfc2 $rt, $rd", (MFC2 GPR32Opnd:$rt, GPR32Opnd:$rd, 0), 0>;
def : MipsInstAlias<"mtc2 $rt, $rd", (MTC2 GPR32Opnd:$rt, GPR32Opnd:$rd, 0), 0>;
let AdditionalPredicates = [NotInMicroMips] in {
def : MipsInstAlias<"b $offset", (BEQ ZERO, ZERO, brtarget:$offset), 0>;
}
def : MipsInstAlias<"bnez $rs,$offset",
(BNE GPR32Opnd:$rs, ZERO, brtarget:$offset), 0>;
def : MipsInstAlias<"beqz $rs,$offset",
Expand Down
3 changes: 3 additions & 0 deletions llvm/test/MC/Disassembler/Mips/micromips.txt
Expand Up @@ -483,3 +483,6 @@

# CHECK: bnez16 $6, 20
0xaf 0x0a

# CHECK: b16 132
0xcc 0x42
3 changes: 3 additions & 0 deletions llvm/test/MC/Disassembler/Mips/micromips_le.txt
Expand Up @@ -483,3 +483,6 @@

# CHECK: bnez16 $6, 20
0x0a 0xaf

# CHECK: b16 132
0x42 0xcc
10 changes: 10 additions & 0 deletions llvm/test/MC/Mips/micromips-16-bit-instructions.s
Expand Up @@ -53,6 +53,10 @@
# 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: b16 132 # encoding: [0x42,0xcc]
# CHECK-EL: nop
# CHECK-EL: b16 132 # encoding: [0x42,0xcc]
# CHECK-EL: nop
# CHECK-EL: break16 8 # encoding: [0x88,0x46]
# CHECK-EL: sdbbp16 14 # encoding: [0xce,0x46]
#------------------------------------------------------------------------------
Expand Down Expand Up @@ -102,6 +106,10 @@
# 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: b16 132 # encoding: [0xcc,0x42]
# CHECK-EB: nop
# CHECK-EB: b16 132 # encoding: [0xcc,0x42]
# CHECK-EB: nop
# CHECK-EB: break16 8 # encoding: [0x46,0x88]
# CHECK-EB: sdbbp16 14 # encoding: [0x46,0xce]

Expand Down Expand Up @@ -145,5 +153,7 @@
jr16 $9
beqz16 $6, 20
bnez16 $6, 20
b 132
b16 132
break16 8
sdbbp16 14

0 comments on commit 5cfebdd

Please sign in to comment.