Skip to content

Commit 45f7f9c

Browse files
author
Jozef Kolek
committedJan 20, 2015
[mips][microMIPS] MicroMIPS 16-bit unconditional branch instruction B
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: 226577
1 parent 4b8985b commit 45f7f9c

17 files changed

+269
-6
lines changed
 

‎llvm/lib/Target/Mips/AsmParser/MipsAsmParser.cpp

+50
Original file line numberDiff line numberDiff line change
@@ -171,6 +171,8 @@ class MipsAsmParser : public MCTargetAsmParser {
171171

172172
bool expandLoadAddressReg(MCInst &Inst, SMLoc IDLoc,
173173
SmallVectorImpl<MCInst> &Instructions);
174+
bool expandUncondBranchMMPseudo(MCInst &Inst, SMLoc IDLoc,
175+
SmallVectorImpl<MCInst> &Instructions);
174176

175177
void expandLoadAddressSym(MCInst &Inst, SMLoc IDLoc,
176178
SmallVectorImpl<MCInst> &Instructions);
@@ -1414,6 +1416,7 @@ bool MipsAsmParser::needsExpansion(MCInst &Inst) {
14141416
case Mips::LoadAddr32Imm:
14151417
case Mips::LoadAddr32Reg:
14161418
case Mips::LoadImm64Reg:
1419+
case Mips::B_MM_Pseudo:
14171420
return true;
14181421
default:
14191422
return false;
@@ -1436,6 +1439,8 @@ bool MipsAsmParser::expandInstruction(MCInst &Inst, SMLoc IDLoc,
14361439
return expandLoadAddressImm(Inst, IDLoc, Instructions);
14371440
case Mips::LoadAddr32Reg:
14381441
return expandLoadAddressReg(Inst, IDLoc, Instructions);
1442+
case Mips::B_MM_Pseudo:
1443+
return expandUncondBranchMMPseudo(Inst, IDLoc, Instructions);
14391444
}
14401445
}
14411446

@@ -1721,6 +1726,51 @@ MipsAsmParser::expandLoadAddressSym(MCInst &Inst, SMLoc IDLoc,
17211726
}
17221727
}
17231728

1729+
bool MipsAsmParser::
1730+
expandUncondBranchMMPseudo(MCInst &Inst, SMLoc IDLoc,
1731+
SmallVectorImpl<MCInst> &Instructions) {
1732+
const MCInstrDesc &MCID = getInstDesc(Inst.getOpcode());
1733+
1734+
assert(MCID.getNumOperands() == 1 && "unexpected number of operands");
1735+
1736+
MCOperand Offset = Inst.getOperand(0);
1737+
if (Offset.isExpr()) {
1738+
Inst.clear();
1739+
Inst.setOpcode(Mips::BEQ_MM);
1740+
Inst.addOperand(MCOperand::CreateReg(Mips::ZERO));
1741+
Inst.addOperand(MCOperand::CreateReg(Mips::ZERO));
1742+
Inst.addOperand(MCOperand::CreateExpr(Offset.getExpr()));
1743+
} else {
1744+
assert(Offset.isImm() && "expected immediate operand kind");
1745+
if (isIntN(11, Offset.getImm())) {
1746+
// If offset fits into 11 bits then this instruction becomes microMIPS
1747+
// 16-bit unconditional branch instruction.
1748+
Inst.setOpcode(Mips::B16_MM);
1749+
} else {
1750+
if (!isIntN(17, Offset.getImm()))
1751+
Error(IDLoc, "branch target out of range");
1752+
if (OffsetToAlignment(Offset.getImm(), 1LL << 1))
1753+
Error(IDLoc, "branch to misaligned address");
1754+
Inst.clear();
1755+
Inst.setOpcode(Mips::BEQ_MM);
1756+
Inst.addOperand(MCOperand::CreateReg(Mips::ZERO));
1757+
Inst.addOperand(MCOperand::CreateReg(Mips::ZERO));
1758+
Inst.addOperand(MCOperand::CreateImm(Offset.getImm()));
1759+
}
1760+
}
1761+
Instructions.push_back(Inst);
1762+
1763+
if (AssemblerOptions.back()->isReorder()) {
1764+
// If .set reorder is active, emit a NOP after the branch instruction.
1765+
MCInst NopInst;
1766+
NopInst.setOpcode(Mips::MOVE16_MM);
1767+
NopInst.addOperand(MCOperand::CreateReg(Mips::ZERO));
1768+
NopInst.addOperand(MCOperand::CreateReg(Mips::ZERO));
1769+
Instructions.push_back(NopInst);
1770+
}
1771+
return false;
1772+
}
1773+
17241774
void MipsAsmParser::expandMemInst(MCInst &Inst, SMLoc IDLoc,
17251775
SmallVectorImpl<MCInst> &Instructions,
17261776
bool isLoad, bool isImmOpnd) {

‎llvm/lib/Target/Mips/Disassembler/MipsDisassembler.cpp

+16
Original file line numberDiff line numberDiff line change
@@ -235,6 +235,13 @@ static DecodeStatus DecodeBranchTarget7MM(MCInst &Inst,
235235
uint64_t Address,
236236
const void *Decoder);
237237

238+
// DecodeBranchTarget10MM - Decode microMIPS branch offset, which is
239+
// shifted left by 1 bit.
240+
static DecodeStatus DecodeBranchTarget10MM(MCInst &Inst,
241+
unsigned Offset,
242+
uint64_t Address,
243+
const void *Decoder);
244+
238245
// DecodeBranchTargetMM - Decode microMIPS branch offset, which is
239246
// shifted left by 1 bit.
240247
static DecodeStatus DecodeBranchTargetMM(MCInst &Inst,
@@ -1556,6 +1563,15 @@ static DecodeStatus DecodeBranchTarget7MM(MCInst &Inst,
15561563
return MCDisassembler::Success;
15571564
}
15581565

1566+
static DecodeStatus DecodeBranchTarget10MM(MCInst &Inst,
1567+
unsigned Offset,
1568+
uint64_t Address,
1569+
const void *Decoder) {
1570+
int32_t BranchOffset = SignExtend32<10>(Offset) << 1;
1571+
Inst.addOperand(MCOperand::CreateImm(BranchOffset));
1572+
return MCDisassembler::Success;
1573+
}
1574+
15591575
static DecodeStatus DecodeBranchTargetMM(MCInst &Inst,
15601576
unsigned Offset,
15611577
uint64_t Address,

‎llvm/lib/Target/Mips/InstPrinter/MipsInstPrinter.cpp

+1
Original file line numberDiff line numberDiff line change
@@ -290,6 +290,7 @@ bool MipsInstPrinter::printAlias(const char *Str, const MCInst &MI,
290290
bool MipsInstPrinter::printAlias(const MCInst &MI, raw_ostream &OS) {
291291
switch (MI.getOpcode()) {
292292
case Mips::BEQ:
293+
case Mips::BEQ_MM:
293294
// beq $zero, $zero, $L2 => b $L2
294295
// beq $r0, $zero, $L2 => beqz $r0, $L2
295296
return (isReg<Mips::ZERO>(MI, 0) && isReg<Mips::ZERO>(MI, 1) &&

‎llvm/lib/Target/Mips/MCTargetDesc/MipsAsmBackend.cpp

+13-1
Original file line numberDiff line numberDiff line change
@@ -111,6 +111,14 @@ static unsigned adjustFixupValue(const MCFixup &Fixup, uint64_t Value,
111111
if (!isIntN(7, Value) && Ctx)
112112
Ctx->FatalError(Fixup.getLoc(), "out of range PC7 fixup");
113113
break;
114+
case Mips::fixup_MICROMIPS_PC10_S1:
115+
Value -= 2;
116+
// Forcing a signed division because Value can be negative.
117+
Value = (int64_t) Value / 2;
118+
// We now check if Value can be encoded as a 10-bit signed immediate.
119+
if (!isIntN(10, Value) && Ctx)
120+
Ctx->FatalError(Fixup.getLoc(), "out of range PC10 fixup");
121+
break;
114122
case Mips::fixup_MICROMIPS_PC16_S1:
115123
Value -= 4;
116124
// Forcing a signed division because Value can be negative.
@@ -157,7 +165,8 @@ MCObjectWriter *MipsAsmBackend::createObjectWriter(raw_ostream &OS) const {
157165
// microMIPS: x | x | a | b
158166

159167
static bool needsMMLEByteOrder(unsigned Kind) {
160-
return Kind >= Mips::fixup_MICROMIPS_26_S1 &&
168+
return Kind != Mips::fixup_MICROMIPS_PC10_S1 &&
169+
Kind >= Mips::fixup_MICROMIPS_26_S1 &&
161170
Kind < Mips::LastTargetFixupKind;
162171
}
163172

@@ -190,6 +199,7 @@ void MipsAsmBackend::applyFixup(const MCFixup &Fixup, char *Data,
190199
switch ((unsigned)Kind) {
191200
case FK_Data_2:
192201
case Mips::fixup_Mips_16:
202+
case Mips::fixup_MICROMIPS_PC10_S1:
193203
FullSize = 2;
194204
break;
195205
case FK_Data_8:
@@ -280,6 +290,7 @@ getFixupKindInfo(MCFixupKind Kind) const {
280290
{ "fixup_MICROMIPS_LO16", 0, 16, 0 },
281291
{ "fixup_MICROMIPS_GOT16", 0, 16, 0 },
282292
{ "fixup_MICROMIPS_PC7_S1", 0, 7, MCFixupKindInfo::FKF_IsPCRel },
293+
{ "fixup_MICROMIPS_PC10_S1", 0, 10, MCFixupKindInfo::FKF_IsPCRel },
283294
{ "fixup_MICROMIPS_PC16_S1", 0, 16, MCFixupKindInfo::FKF_IsPCRel },
284295
{ "fixup_MICROMIPS_CALL16", 0, 16, 0 },
285296
{ "fixup_MICROMIPS_GOT_DISP", 0, 16, 0 },
@@ -344,6 +355,7 @@ getFixupKindInfo(MCFixupKind Kind) const {
344355
{ "fixup_MICROMIPS_LO16", 16, 16, 0 },
345356
{ "fixup_MICROMIPS_GOT16", 16, 16, 0 },
346357
{ "fixup_MICROMIPS_PC7_S1", 9, 7, MCFixupKindInfo::FKF_IsPCRel },
358+
{ "fixup_MICROMIPS_PC10_S1", 6, 10, MCFixupKindInfo::FKF_IsPCRel },
347359
{ "fixup_MICROMIPS_PC16_S1",16, 16, MCFixupKindInfo::FKF_IsPCRel },
348360
{ "fixup_MICROMIPS_CALL16", 16, 16, 0 },
349361
{ "fixup_MICROMIPS_GOT_DISP", 16, 16, 0 },

‎llvm/lib/Target/Mips/MCTargetDesc/MipsELFObjectWriter.cpp

+3
Original file line numberDiff line numberDiff line change
@@ -165,6 +165,9 @@ unsigned MipsELFObjectWriter::GetRelocType(const MCValue &Target,
165165
case Mips::fixup_MICROMIPS_PC7_S1:
166166
Type = ELF::R_MICROMIPS_PC7_S1;
167167
break;
168+
case Mips::fixup_MICROMIPS_PC10_S1:
169+
Type = ELF::R_MICROMIPS_PC10_S1;
170+
break;
168171
case Mips::fixup_MICROMIPS_PC16_S1:
169172
Type = ELF::R_MICROMIPS_PC16_S1;
170173
break;

‎llvm/lib/Target/Mips/MCTargetDesc/MipsFixupKinds.h

+3
Original file line numberDiff line numberDiff line change
@@ -161,6 +161,9 @@ namespace Mips {
161161
// resulting in - R_MICROMIPS_PC7_S1
162162
fixup_MICROMIPS_PC7_S1,
163163

164+
// resulting in - R_MICROMIPS_PC10_S1
165+
fixup_MICROMIPS_PC10_S1,
166+
164167
// resulting in - R_MICROMIPS_PC16_S1
165168
fixup_MICROMIPS_PC16_S1,
166169

‎llvm/lib/Target/Mips/MCTargetDesc/MipsMCCodeEmitter.cpp

+22
Original file line numberDiff line numberDiff line change
@@ -242,6 +242,28 @@ getBranchTarget7OpValueMM(const MCInst &MI, unsigned OpNo,
242242
return 0;
243243
}
244244

245+
/// getBranchTargetOpValueMMPC10 - Return binary encoding of the microMIPS
246+
/// 10-bit branch target operand. If the machine operand requires relocation,
247+
/// record the relocation and return zero.
248+
unsigned MipsMCCodeEmitter::
249+
getBranchTargetOpValueMMPC10(const MCInst &MI, unsigned OpNo,
250+
SmallVectorImpl<MCFixup> &Fixups,
251+
const MCSubtargetInfo &STI) const {
252+
253+
const MCOperand &MO = MI.getOperand(OpNo);
254+
255+
// If the destination is an immediate, divide by 2.
256+
if (MO.isImm()) return MO.getImm() >> 1;
257+
258+
assert(MO.isExpr() &&
259+
"getBranchTargetOpValuePC10 expects only expressions or immediates");
260+
261+
const MCExpr *Expr = MO.getExpr();
262+
Fixups.push_back(MCFixup::Create(0, Expr,
263+
MCFixupKind(Mips::fixup_MICROMIPS_PC10_S1)));
264+
return 0;
265+
}
266+
245267
/// getBranchTargetOpValue - Return binary encoding of the microMIPS branch
246268
/// target operand. If the machine operand requires relocation,
247269
/// record the relocation and return zero.

‎llvm/lib/Target/Mips/MCTargetDesc/MipsMCCodeEmitter.h

+7
Original file line numberDiff line numberDiff line change
@@ -108,6 +108,13 @@ class MipsMCCodeEmitter : public MCCodeEmitter {
108108
SmallVectorImpl<MCFixup> &Fixups,
109109
const MCSubtargetInfo &STI) const;
110110

111+
// getBranchTargetOpValueMMPC10 - Return binary encoding of the microMIPS
112+
// 10-bit branch target operand. If the machine operand requires relocation,
113+
// record the relocation and return zero.
114+
unsigned getBranchTargetOpValueMMPC10(const MCInst &MI, unsigned OpNo,
115+
SmallVectorImpl<MCFixup> &Fixups,
116+
const MCSubtargetInfo &STI) const;
117+
111118
// getBranchTargetOpValue - Return binary encoding of the microMIPS branch
112119
// target operand. If the machine operand requires relocation,
113120
// record the relocation and return zero.

‎llvm/lib/Target/Mips/MicroMipsInstrFormats.td

+9
Original file line numberDiff line numberDiff line change
@@ -238,6 +238,15 @@ class BEQNEZ_FM_MM16<bits<6> op> {
238238
let Inst{6-0} = offset;
239239
}
240240

241+
class B16_FM {
242+
bits<10> offset;
243+
244+
bits<16> Inst;
245+
246+
let Inst{15-10} = 0x33;
247+
let Inst{9-0} = offset;
248+
}
249+
241250
//===----------------------------------------------------------------------===//
242251
// MicroMIPS 32-bit Instruction Formats
243252
//===----------------------------------------------------------------------===//

‎llvm/lib/Target/Mips/MicroMipsInstrInfo.td

+27
Original file line numberDiff line numberDiff line change
@@ -135,10 +135,18 @@ def brtarget7_mm : Operand<OtherVT> {
135135
let ParserMatchClass = MipsJumpTargetAsmOperand;
136136
}
137137

138+
def brtarget10_mm : Operand<OtherVT> {
139+
let EncoderMethod = "getBranchTargetOpValueMMPC10";
140+
let OperandType = "OPERAND_PCREL";
141+
let DecoderMethod = "DecodeBranchTarget10MM";
142+
let ParserMatchClass = MipsJumpTargetAsmOperand;
143+
}
144+
138145
def brtarget_mm : Operand<OtherVT> {
139146
let EncoderMethod = "getBranchTargetOpValueMM";
140147
let OperandType = "OPERAND_PCREL";
141148
let DecoderMethod = "DecodeBranchTargetMM";
149+
let ParserMatchClass = MipsJumpTargetAsmOperand;
142150
}
143151

144152
class CompactBranchMM<string opstr, DAGOperand opnd, PatFrag cond_op,
@@ -481,6 +489,18 @@ class LoadMultMM16<string opstr,
481489
let mayLoad = 1;
482490
}
483491

492+
class UncondBranchMM16<string opstr> :
493+
MicroMipsInst16<(outs), (ins brtarget10_mm:$offset),
494+
!strconcat(opstr, "\t$offset"),
495+
[], IIBranch, FrmI> {
496+
let isBranch = 1;
497+
let isTerminator = 1;
498+
let isBarrier = 1;
499+
let hasDelaySlot = 1;
500+
let Predicates = [RelocPIC, InMicroMips];
501+
let Defs = [AT];
502+
}
503+
484504
def ADDU16_MM : ArithRMM16<"addu16", GPRMM16Opnd, 1, II_ADDU, add>,
485505
ARITH_FM_MM16<0>;
486506
def SUBU16_MM : ArithRMM16<"subu16", GPRMM16Opnd, 0, II_SUBU, sub>,
@@ -532,6 +552,7 @@ def BEQZ16_MM : CBranchZeroMM<"beqz16", brtarget7_mm, GPRMM16Opnd>,
532552
BEQNEZ_FM_MM16<0x23>;
533553
def BNEZ16_MM : CBranchZeroMM<"bnez16", brtarget7_mm, GPRMM16Opnd>,
534554
BEQNEZ_FM_MM16<0x2b>;
555+
def B16_MM : UncondBranchMM16<"b16">, B16_FM;
535556
def BREAK16_MM : BrkSdbbp16MM<"break16">, BRKSDBBP16_FM_MM<0x28>;
536557
def SDBBP16_MM : BrkSdbbp16MM<"sdbbp16">, BRKSDBBP16_FM_MM<0x2C>;
537558

@@ -818,6 +839,12 @@ def : MipsPat<(srl GPR32:$src, immZExt5:$imm),
818839
// MicroMips instruction aliases
819840
//===----------------------------------------------------------------------===//
820841

842+
class UncondBranchMMPseudo<string opstr> :
843+
MipsAsmPseudoInst<(outs), (ins brtarget_mm:$offset),
844+
!strconcat(opstr, "\t$offset")>;
845+
846+
def B_MM_Pseudo : UncondBranchMMPseudo<"b">;
847+
821848
def : MipsInstAlias<"wait", (WAIT_MM 0x0), 1>;
822849
def : MipsInstAlias<"nop", (SLL_MM ZERO, ZERO, 0), 1>;
823850
def : MipsInstAlias<"nop", (MOVE16_MM ZERO, ZERO), 1>;

‎llvm/lib/Target/Mips/MipsInstrInfo.td

+2
Original file line numberDiff line numberDiff line change
@@ -1582,7 +1582,9 @@ def : MipsInstAlias<"mfc0 $rt, $rd", (MFC0 GPR32Opnd:$rt, GPR32Opnd:$rd, 0), 0>;
15821582
def : MipsInstAlias<"mtc0 $rt, $rd", (MTC0 GPR32Opnd:$rt, GPR32Opnd:$rd, 0), 0>;
15831583
def : MipsInstAlias<"mfc2 $rt, $rd", (MFC2 GPR32Opnd:$rt, GPR32Opnd:$rd, 0), 0>;
15841584
def : MipsInstAlias<"mtc2 $rt, $rd", (MTC2 GPR32Opnd:$rt, GPR32Opnd:$rd, 0), 0>;
1585+
let AdditionalPredicates = [NotInMicroMips] in {
15851586
def : MipsInstAlias<"b $offset", (BEQ ZERO, ZERO, brtarget:$offset), 0>;
1587+
}
15861588
def : MipsInstAlias<"bnez $rs,$offset",
15871589
(BNE GPR32Opnd:$rs, ZERO, brtarget:$offset), 0>;
15881590
def : MipsInstAlias<"beqz $rs,$offset",

‎llvm/test/MC/Disassembler/Mips/micromips.txt

+3
Original file line numberDiff line numberDiff line change
@@ -474,3 +474,6 @@
474474

475475
# CHECK: bnez16 $6, 20
476476
0xaf 0x0a
477+
478+
# CHECK: b16 132
479+
0xcc 0x42

‎llvm/test/MC/Disassembler/Mips/micromips_le.txt

+3
Original file line numberDiff line numberDiff line change
@@ -474,3 +474,6 @@
474474

475475
# CHECK: bnez16 $6, 20
476476
0x0a 0xaf
477+
478+
# CHECK: b16 132
479+
0x42 0xcc

‎llvm/test/MC/Mips/micromips-16-bit-instructions.s

+10
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,10 @@
5353
# CHECK-EL: nop # encoding: [0x00,0x00,0x00,0x00]
5454
# CHECK-EL: bnez16 $6, 20 # encoding: [0x0a,0xaf]
5555
# CHECK-EL: nop # encoding: [0x00,0x00,0x00,0x00]
56+
# CHECK-EL: b16 132 # encoding: [0x42,0xcc]
57+
# CHECK-EL: nop
58+
# CHECK-EL: b16 132 # encoding: [0x42,0xcc]
59+
# CHECK-EL: nop
5660
# CHECK-EL: break16 8 # encoding: [0x88,0x46]
5761
# CHECK-EL: sdbbp16 14 # encoding: [0xce,0x46]
5862
#------------------------------------------------------------------------------
@@ -102,6 +106,10 @@
102106
# CHECK-EB: nop # encoding: [0x00,0x00,0x00,0x00]
103107
# CHECK-EB: bnez16 $6, 20 # encoding: [0xaf,0x0a]
104108
# CHECK-EB: nop # encoding: [0x00,0x00,0x00,0x00]
109+
# CHECK-EB: b16 132 # encoding: [0xcc,0x42]
110+
# CHECK-EB: nop
111+
# CHECK-EB: b16 132 # encoding: [0xcc,0x42]
112+
# CHECK-EB: nop
105113
# CHECK-EB: break16 8 # encoding: [0x46,0x88]
106114
# CHECK-EB: sdbbp16 14 # encoding: [0x46,0xce]
107115

@@ -145,5 +153,7 @@
145153
jr16 $9
146154
beqz16 $6, 20
147155
bnez16 $6, 20
156+
b 132
157+
b16 132
148158
break16 8
149159
sdbbp16 14

0 commit comments

Comments
 (0)