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);
case Mips::LoadAddr32Imm:
case Mips::LoadAddr32Reg:
case Mips::LoadImm64Reg:
+ case Mips::B_MM_Pseudo:
return true;
default:
return false;
return expandLoadAddressImm(Inst, IDLoc, Instructions);
case Mips::LoadAddr32Reg:
return expandLoadAddressReg(Inst, IDLoc, Instructions);
+ case Mips::B_MM_Pseudo:
+ return expandUncondBranchMMPseudo(Inst, IDLoc, Instructions);
}
}
}
}
+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) {