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) {
- assert(getInstDesc(Inst.getOpcode()).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) {
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,
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,
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) &&
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.
// microMIPS: x | x | a | b
static bool needsMMLEByteOrder(unsigned Kind) {
- return Kind != Mips::fixup_MICROMIPS_PC10_S1 &&
- Kind >= Mips::fixup_MICROMIPS_26_S1 &&
+ return Kind >= Mips::fixup_MICROMIPS_26_S1 &&
Kind < Mips::LastTargetFixupKind;
}
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:
{ "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 },
{ "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 },
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;
// 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,
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.
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.
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
//===----------------------------------------------------------------------===//
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;
}
class CompactBranchMM<string opstr, DAGOperand opnd, PatFrag cond_op,
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>,
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>;
// 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>;
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",
# CHECK: bnez16 $6, 20
0xaf 0x0a
-
-# CHECK: b16 132
-0xcc 0x42
# CHECK: bnez16 $6, 20
0x0a 0xaf
-
-# CHECK: b16 132
-0x42 0xcc
# 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]
#------------------------------------------------------------------------------
# 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]
jr16 $9
beqz16 $6, 20
bnez16 $6, 20
- b 132
- b16 132
break16 8
sdbbp16 14
+++ /dev/null
-# 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-FIXUP: b16 bar # encoding: [A,0b110011AA]
-# CHECK-FIXUP: # fixup A - offset: 0,
-# CHECK-FIXUP: value: bar, kind: fixup_MICROMIPS_PC10_S1
-# CHECK-FIXUP: nop # encoding: [0x00,0x00,0x00,0x00]
-# CHECK-FIXUP: b bar # encoding: [A,0x94'A',0x00,0x00]
-# CHECK-FIXUP: # fixup A - offset: 0,
-# CHECK-FIXUP: value: bar, kind: fixup_MICROMIPS_PC16_S1
-# CHECK-FIXUP: nop # encoding: [0x00,0x0c]
-# CHECK-FIXUP: beq $3, $4, bar # encoding: [0x83'A',0x94'A',0x00,0x00]
-# CHECK-FIXUP: # fixup A - offset: 0,
-# CHECK-FIXUP: value: bar, kind: fixup_MICROMIPS_PC16_S1
-# CHECK-FIXUP: nop # encoding: [0x00,0x00,0x00,0x00]
-# CHECK-FIXUP: bne $3, $4, bar # encoding: [0x83'A',0xb4'A',0x00,0x00]
-# CHECK-FIXUP: # fixup A - offset: 0,
-# CHECK-FIXUP: value: bar, kind: fixup_MICROMIPS_PC16_S1
-# CHECK-FIXUP: nop # encoding: [0x00,0x00,0x00,0x00]
-# CHECK-FIXUP: bgez $4, bar # encoding: [0x44'A',0x40'A',0x00,0x00]
-# CHECK-FIXUP: # fixup A - offset: 0,
-# CHECK-FIXUP: value: bar, kind: fixup_MICROMIPS_PC16_S1
-# CHECK-FIXUP: nop # encoding: [0x00,0x00,0x00,0x00]
-# CHECK-FIXUP: bgtz $4, bar # encoding: [0xc4'A',0x40'A',0x00,0x00]
-# CHECK-FIXUP: # fixup A - offset: 0,
-# CHECK-FIXUP: value: bar, kind: fixup_MICROMIPS_PC16_S1
-# CHECK-FIXUP: nop # encoding: [0x00,0x00,0x00,0x00]
-# CHECK-FIXUP: blez $4, bar # encoding: [0x84'A',0x40'A',0x00,0x00]
-# CHECK-FIXUP: # fixup A - offset: 0,
-# CHECK-FIXUP: value: bar, kind: fixup_MICROMIPS_PC16_S1
-# CHECK-FIXUP: nop # encoding: [0x00,0x00,0x00,0x00]
-# CHECK-FIXUP: bltz $4, bar # encoding: [0x04'A',0x40'A',0x00,0x00]
-# CHECK-FIXUP: # fixup A - offset: 0,
-# CHECK-FIXUP: value: bar, kind: fixup_MICROMIPS_PC16_S1
-# CHECK-FIXUP: nop # encoding: [0x00,0x00,0x00,0x00]
-# CHECK-FIXUP: bgezal $4, bar # encoding: [0x64'A',0x40'A',0x00,0x00]
-# CHECK-FIXUP: # fixup A - offset: 0,
-# CHECK-FIXUP: value: bar, kind: fixup_MICROMIPS_PC16_S1
-# CHECK-FIXUP: nop # encoding: [0x00,0x00,0x00,0x00]
-# CHECK-FIXUP: bltzal $4, bar # encoding: [0x24'A',0x40'A',0x00,0x00]
-# CHECK-FIXUP: # fixup A - offset: 0,
-# CHECK-FIXUP: value: bar, kind: fixup_MICROMIPS_PC16_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: 0x{{[0-9,A-F]+}} R_MICROMIPS_PC10_S1
-# CHECK-ELF: 0x{{[0-9,A-F]+}} R_MICROMIPS_PC16_S1
-# CHECK-ELF: 0x{{[0-9,A-F]+}} R_MICROMIPS_PC16_S1
-# CHECK-ELF: 0x{{[0-9,A-F]+}} R_MICROMIPS_PC16_S1
-# CHECK-ELF: 0x{{[0-9,A-F]+}} R_MICROMIPS_PC16_S1
-# CHECK-ELF: 0x{{[0-9,A-F]+}} R_MICROMIPS_PC16_S1
-# CHECK-ELF: 0x{{[0-9,A-F]+}} R_MICROMIPS_PC16_S1
-# CHECK-ELF: 0x{{[0-9,A-F]+}} R_MICROMIPS_PC16_S1
-# CHECK-ELF: 0x{{[0-9,A-F]+}} R_MICROMIPS_PC16_S1
-# CHECK-ELF: 0x{{[0-9,A-F]+}} R_MICROMIPS_PC16_S1
-# CHECK-ELF: ]
-
- .text
- .type main, @function
- .set micromips
-main:
- beqz16 $6, bar
- bnez16 $6, bar
- b16 bar
- b bar
- beq $3, $4, bar
- bne $3, $4, bar
- bgez $4, bar
- bgtz $4, bar
- blez $4, bar
- bltz $4, bar
- bgezal $4, bar
- bltzal $4, bar
#------------------------------------------------------------------------------
# Little endian
#------------------------------------------------------------------------------
-# CHECK-EL: b 1332 # encoding: [0x00,0x94,0x9a,0x02]
-# CHECK-EL: nop # encoding: [0x00,0x0c]
+# CHECK-EL: b 1332 # encoding: [0x00,0x94,0x9a,0x02]
+# CHECK-EL: nop # encoding: [0x00,0x00,0x00,0x00]
# CHECK-EL: beq $9, $6, 1332 # encoding: [0xc9,0x94,0x9a,0x02]
# CHECK-EL: nop # encoding: [0x00,0x00,0x00,0x00]
# CHECK-EL: bgez $6, 1332 # encoding: [0x46,0x40,0x9a,0x02]
#------------------------------------------------------------------------------
# Big endian
#------------------------------------------------------------------------------
-# CHECK-EB: b 1332 # encoding: [0x94,0x00,0x02,0x9a]
-# CHECK-EB: nop # encoding: [0x0c,0x00]
+# CHECK-EB: b 1332 # encoding: [0x94,0x00,0x02,0x9a]
+# CHECK-EB: nop # encoding: [0x00,0x00,0x00,0x00]
# CHECK-EB: beq $9, $6, 1332 # encoding: [0x94,0xc9,0x02,0x9a]
# CHECK-EB: nop # encoding: [0x00,0x00,0x00,0x00]
# CHECK-EB: bgez $6, 1332 # encoding: [0x40,0x46,0x02,0x9a]
# CHECK-EB: bltzals $6, 1332 # encoding: [0x42,0x26,0x02,0x9a]
# CHECK-EB: nop # encoding: [0x0c,0x00]
- .text
- .type main, @function
- .set micromips
-main:
b 1332
beq $9,$6,1332
bgez $6,1332
.text
b foo
- .space 65536 - 6, 1 # -6 = size of b instr plus size of automatically inserted nop
+ .space 65536 - 8, 1 # -8 = size of b instr plus size of automatically inserted nop
nop # This instr makes the branch too long to fit into a 17-bit offset
foo:
add $0,$0,$0