Skip to content

Commit

Permalink
Support for microMIPS jump instructions
Browse files Browse the repository at this point in the history
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@193623 91177308-0d34-0410-b5e6-96231b3b80d8
  • Loading branch information
Zoran Jovanovic committed Oct 29, 2013
1 parent 54328c7 commit 1aaf43c
Show file tree
Hide file tree
Showing 18 changed files with 253 additions and 21 deletions.
1 change: 1 addition & 0 deletions include/llvm/Support/ELF.h
Original file line number Diff line number Diff line change
Expand Up @@ -881,6 +881,7 @@ enum {
R_MIPS_GLOB_DAT = 51,
R_MIPS_COPY = 126,
R_MIPS_JUMP_SLOT = 127,
R_MICROMIPS_26_S1 = 133,
R_MICROMIPS_HI16 = 134,
R_MICROMIPS_LO16 = 135,
R_MICROMIPS_GOT16 = 138,
Expand Down
1 change: 1 addition & 0 deletions lib/Object/ELF.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -161,6 +161,7 @@ StringRef getELFRelocationTypeName(uint32_t Machine, uint32_t Type) {
LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_MIPS_GLOB_DAT);
LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_MIPS_COPY);
LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_MIPS_JUMP_SLOT);
LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_MICROMIPS_26_S1);
LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_MICROMIPS_HI16);
LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_MICROMIPS_LO16);
LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_MICROMIPS_GOT16);
Expand Down
15 changes: 15 additions & 0 deletions lib/Target/Mips/Disassembler/MipsDisassembler.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -205,6 +205,13 @@ static DecodeStatus DecodeJumpTarget(MCInst &Inst,
uint64_t Address,
const void *Decoder);

// DecodeJumpTargetMM - Decode microMIPS jump target, which is
// shifted left by 1 bit.
static DecodeStatus DecodeJumpTargetMM(MCInst &Inst,
unsigned Insn,
uint64_t Address,
const void *Decoder);

static DecodeStatus DecodeMem(MCInst &Inst,
unsigned Insn,
uint64_t Address,
Expand Down Expand Up @@ -744,6 +751,14 @@ static DecodeStatus DecodeJumpTarget(MCInst &Inst,
return MCDisassembler::Success;
}

static DecodeStatus DecodeJumpTargetMM(MCInst &Inst,
unsigned Insn,
uint64_t Address,
const void *Decoder) {
unsigned JumpOffset = fieldFromInstruction(Insn, 0, 26) << 1;
Inst.addOperand(MCOperand::CreateImm(JumpOffset));
return MCDisassembler::Success;
}

static DecodeStatus DecodeSimm16(MCInst &Inst,
unsigned Insn,
Expand Down
4 changes: 4 additions & 0 deletions lib/Target/Mips/MCTargetDesc/MipsAsmBackend.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -81,6 +81,9 @@ static unsigned adjustFixupValue(unsigned Kind, uint64_t Value) {
// Get the 4th 16-bits.
Value = ((Value + 0x800080008000LL) >> 48) & 0xffff;
break;
case Mips::fixup_MICROMIPS_26_S1:
Value >>= 1;
break;
}

return Value;
Expand Down Expand Up @@ -194,6 +197,7 @@ class MipsAsmBackend : public MCAsmBackend {
{ "fixup_Mips_GOT_LO16", 0, 16, 0 },
{ "fixup_Mips_CALL_HI16", 0, 16, 0 },
{ "fixup_Mips_CALL_LO16", 0, 16, 0 },
{ "fixup_MICROMIPS_26_S1", 0, 26, 0 },
{ "fixup_MICROMIPS_HI16", 0, 16, 0 },
{ "fixup_MICROMIPS_LO16", 0, 16, 0 },
{ "fixup_MICROMIPS_GOT16", 0, 16, 0 },
Expand Down
3 changes: 3 additions & 0 deletions lib/Target/Mips/MCTargetDesc/MipsELFObjectWriter.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -183,6 +183,9 @@ unsigned MipsELFObjectWriter::GetRelocType(const MCValue &Target,
case Mips::fixup_Mips_CALL_LO16:
Type = ELF::R_MIPS_CALL_LO16;
break;
case Mips::fixup_MICROMIPS_26_S1:
Type = ELF::R_MICROMIPS_26_S1;
break;
case Mips::fixup_MICROMIPS_HI16:
Type = ELF::R_MICROMIPS_HI16;
break;
Expand Down
3 changes: 3 additions & 0 deletions lib/Target/Mips/MCTargetDesc/MipsFixupKinds.h
Original file line number Diff line number Diff line change
Expand Up @@ -128,6 +128,9 @@ namespace Mips {
// resulting in - R_MIPS_CALL_LO16
fixup_Mips_CALL_LO16,

// resulting in - R_MICROMIPS_26_S1
fixup_MICROMIPS_26_S1,

// resulting in - R_MICROMIPS_HI16
fixup_MICROMIPS_HI16,

Expand Down
23 changes: 23 additions & 0 deletions lib/Target/Mips/MCTargetDesc/MipsMCCodeEmitter.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -84,6 +84,12 @@ class MipsMCCodeEmitter : public MCCodeEmitter {
unsigned getJumpTargetOpValue(const MCInst &MI, unsigned OpNo,
SmallVectorImpl<MCFixup> &Fixups) const;

// getBranchJumpOpValueMM - Return binary encoding of the microMIPS jump
// target operand. If the machine operand requires relocation,
// record the relocation and return zero.
unsigned getJumpTargetOpValueMM(const MCInst &MI, unsigned OpNo,
SmallVectorImpl<MCFixup> &Fixups) const;

// getBranchTargetOpValue - Return binary encoding of the branch
// target operand. If the machine operand requires relocation,
// record the relocation and return zero.
Expand Down Expand Up @@ -290,6 +296,23 @@ getJumpTargetOpValue(const MCInst &MI, unsigned OpNo,
return 0;
}

unsigned MipsMCCodeEmitter::
getJumpTargetOpValueMM(const MCInst &MI, unsigned OpNo,
SmallVectorImpl<MCFixup> &Fixups) 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() &&
"getJumpTargetOpValueMM expects only expressions or an immediate");

const MCExpr *Expr = MO.getExpr();
Fixups.push_back(MCFixup::Create(0, Expr,
MCFixupKind(Mips::fixup_MICROMIPS_26_S1)));
return 0;
}

unsigned MipsMCCodeEmitter::
getExprOpValue(const MCExpr *Expr,SmallVectorImpl<MCFixup> &Fixups) const {
int64_t Res;
Expand Down
34 changes: 34 additions & 0 deletions lib/Target/Mips/MicroMipsInstrFormats.td
Original file line number Diff line number Diff line change
Expand Up @@ -204,3 +204,37 @@ class EXT_FM_MM<bits<6> funct> : MMArch {
let Inst{10-6} = pos;
let Inst{5-0} = funct;
}

class J_FM_MM<bits<6> op> : MMArch {
bits<26> target;

bits<32> Inst;

let Inst{31-26} = op;
let Inst{25-0} = target;
}

class JR_FM_MM<bits<8> funct> : MMArch {
bits<5> rs;

bits<32> Inst;

let Inst{31-21} = 0x00;
let Inst{20-16} = rs;
let Inst{15-14} = 0x0;
let Inst{13-6} = funct;
let Inst{5-0} = 0x3c;
}

class JALR_FM_MM<bits<10> funct> : MMArch {
bits<5> rs;
bits<5> rd;

bits<32> Inst;

let Inst{31-26} = 0x00;
let Inst{25-21} = rd;
let Inst{20-16} = rs;
let Inst{15-6} = funct;
let Inst{5-0} = 0x3c;
}
22 changes: 22 additions & 0 deletions lib/Target/Mips/MicroMipsInstrInfo.td
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,14 @@ def mem_mm_12 : Operand<i32> {
let OperandType = "OPERAND_MEMORY";
}

def jmptarget_mm : Operand<OtherVT> {
let EncoderMethod = "getJumpTargetOpValueMM";
}

def calltarget_mm : Operand<iPTR> {
let EncoderMethod = "getJumpTargetOpValueMM";
}

let canFoldAsLoad = 1 in
class LoadLeftRightMM<string opstr, SDNode OpNode, RegisterOperand RO,
Operand MemOpnd> :
Expand Down Expand Up @@ -155,4 +163,18 @@ let DecoderNamespace = "MicroMips", Predicates = [InMicroMips] in {
EXT_FM_MM<0x2c>;
def INS_MM : MMRel, InsBase<"ins", GPR32Opnd, uimm5, MipsIns>,
EXT_FM_MM<0x0c>;

/// Jump Instructions
let DecoderMethod = "DecodeJumpTargetMM" in {
def J_MM : MMRel, JumpFJ<jmptarget_mm, "j", br, bb, "j">,
J_FM_MM<0x35>;
def JAL_MM : MMRel, JumpLink<"jal", calltarget_mm>, J_FM_MM<0x3d>;
def TAILCALL_MM : MMRel, JumpFJ<calltarget_mm, "j", MipsTailCall, imm,
"tcall">, J_FM_MM<0x3d>, IsTailCall;
}
def JR_MM : MMRel, IndirectBranch<"jr", GPR32Opnd>, JR_FM_MM<0x3c>;
def JALR_MM : MMRel, JumpLinkReg<"jalr", GPR32Opnd>, JALR_FM_MM<0x03c>;
def TAILCALL_R_MM : MMRel, JumpFR<"tcallr", GPR32Opnd, MipsTailCall>,
JR_FM_MM<0x3c>, IsTailCall;
def RET_MM : MMRel, RetBase<"ret", GPR32Opnd>, JR_FM_MM<0x3c>;
}
5 changes: 3 additions & 2 deletions lib/Target/Mips/Mips64InstrInfo.td
Original file line number Diff line number Diff line change
Expand Up @@ -150,7 +150,7 @@ def SCD : SCBase<"scd", GPR64Opnd>, LW_FM<0x3c>;

/// Jump and Branch Instructions
let isCodeGenOnly = 1 in {
def JR64 : IndirectBranch<GPR64Opnd>, MTLO_FM<8>;
def JR64 : IndirectBranch<"jr", GPR64Opnd>, MTLO_FM<8>;
def BEQ64 : CBranch<"beq", seteq, GPR64Opnd>, BEQ_FM<4>;
def BNE64 : CBranch<"bne", setne, GPR64Opnd>, BEQ_FM<5>;
def BGEZ64 : CBranchZero<"bgez", setge, GPR64Opnd>, BGEZ_FM<1, 1>;
Expand All @@ -159,7 +159,8 @@ def BLEZ64 : CBranchZero<"blez", setle, GPR64Opnd>, BGEZ_FM<6, 0>;
def BLTZ64 : CBranchZero<"bltz", setlt, GPR64Opnd>, BGEZ_FM<1, 0>;
def JALR64 : JumpLinkReg<"jalr", GPR64Opnd>, JALR_FM;
def JALR64Pseudo : JumpLinkRegPseudo<GPR64Opnd, JALR, RA, GPR32Opnd>;
def TAILCALL64_R : JumpFR<GPR64Opnd, MipsTailCall>, MTLO_FM<8>, IsTailCall;
def TAILCALL64_R : JumpFR<"tcallr", GPR64Opnd, MipsTailCall>,
MTLO_FM<8>, IsTailCall;
}

/// Multiply and Divide Instructions.
Expand Down
7 changes: 7 additions & 0 deletions lib/Target/Mips/MipsCodeEmitter.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -105,6 +105,7 @@ class MipsCodeEmitter : public MachineFunctionPass {
const MachineOperand &MO) const;

unsigned getJumpTargetOpValue(const MachineInstr &MI, unsigned OpNo) const;
unsigned getJumpTargetOpValueMM(const MachineInstr &MI, unsigned OpNo) const;

unsigned getBranchTargetOpValue(const MachineInstr &MI, unsigned OpNo) const;
unsigned getMemEncoding(const MachineInstr &MI, unsigned OpNo) const;
Expand Down Expand Up @@ -187,6 +188,12 @@ unsigned MipsCodeEmitter::getJumpTargetOpValue(const MachineInstr &MI,
return 0;
}

unsigned MipsCodeEmitter::getJumpTargetOpValueMM(const MachineInstr &MI,
unsigned OpNo) const {
llvm_unreachable("Unimplemented function.");
return 0;
}

unsigned MipsCodeEmitter::getBranchTargetOpValue(const MachineInstr &MI,
unsigned OpNo) const {
MachineOperand MO = MI.getOperand(OpNo);
Expand Down
4 changes: 2 additions & 2 deletions lib/Target/Mips/MipsInstrFormats.td
Original file line number Diff line number Diff line change
Expand Up @@ -183,7 +183,7 @@ class BranchBase<bits<6> op, dag outs, dag ins, string asmstr,
// Format J instruction class in Mips : <|opcode|address|>
//===----------------------------------------------------------------------===//

class FJ<bits<6> op>
class FJ<bits<6> op> : StdArch
{
bits<26> target;

Expand Down Expand Up @@ -375,7 +375,7 @@ class LUI_FM : StdArch {
let Inst{15-0} = imm16;
}

class JALR_FM {
class JALR_FM : StdArch {
bits<5> rd;
bits<5> rs;

Expand Down
39 changes: 22 additions & 17 deletions lib/Target/Mips/MipsInstrInfo.td
Original file line number Diff line number Diff line change
Expand Up @@ -541,9 +541,9 @@ class SetCC_I<string opstr, PatFrag cond_op, Operand Od, PatLeaf imm_type,

// Jump
class JumpFJ<DAGOperand opnd, string opstr, SDPatternOperator operator,
SDPatternOperator targetoperator> :
SDPatternOperator targetoperator, string bopstr> :
InstSE<(outs), (ins opnd:$target), !strconcat(opstr, "\t$target"),
[(operator targetoperator:$target)], IIBranch, FrmJ> {
[(operator targetoperator:$target)], IIBranch, FrmJ, bopstr> {
let isTerminator=1;
let isBarrier=1;
let hasDelaySlot = 1;
Expand All @@ -565,17 +565,20 @@ class UncondBranch<Instruction BEQInst> :

// Base class for indirect branch and return instruction classes.
let isTerminator=1, isBarrier=1, hasDelaySlot = 1 in
class JumpFR<RegisterOperand RO, SDPatternOperator operator = null_frag>:
InstSE<(outs), (ins RO:$rs), "jr\t$rs", [(operator RO:$rs)], IIBranch, FrmR>;
class JumpFR<string opstr, RegisterOperand RO,
SDPatternOperator operator = null_frag>:
InstSE<(outs), (ins RO:$rs), "jr\t$rs", [(operator RO:$rs)], IIBranch,
FrmR, opstr>;

// Indirect branch
class IndirectBranch<RegisterOperand RO>: JumpFR<RO, brind> {
class IndirectBranch<string opstr, RegisterOperand RO> :
JumpFR<opstr, RO, brind> {
let isBranch = 1;
let isIndirectBranch = 1;
}

// Return instruction
class RetBase<RegisterOperand RO>: JumpFR<RO> {
class RetBase<string opstr, RegisterOperand RO>: JumpFR<opstr, RO> {
let isReturn = 1;
let isCodeGenOnly = 1;
let hasCtrlDep = 1;
Expand All @@ -584,9 +587,9 @@ class RetBase<RegisterOperand RO>: JumpFR<RO> {

// Jump and Link (Call)
let isCall=1, hasDelaySlot=1, Defs = [RA] in {
class JumpLink<string opstr> :
InstSE<(outs), (ins calltarget:$target), !strconcat(opstr, "\t$target"),
[(MipsJmpLink imm:$target)], IIBranch, FrmJ> {
class JumpLink<string opstr, DAGOperand opnd> :
InstSE<(outs), (ins opnd:$target), !strconcat(opstr, "\t$target"),
[(MipsJmpLink imm:$target)], IIBranch, FrmJ, opstr> {
let DecoderMethod = "DecodeJumpTarget";
}

Expand All @@ -597,7 +600,7 @@ let isCall=1, hasDelaySlot=1, Defs = [RA] in {

class JumpLinkReg<string opstr, RegisterOperand RO>:
InstSE<(outs RO:$rd), (ins RO:$rs), !strconcat(opstr, "\t$rd, $rs"),
[], IIBranch, FrmR>;
[], IIBranch, FrmR, opstr>;

class BGEZAL_FT<string opstr, RegisterOperand RO> :
InstSE<(outs), (ins RO:$rs, brtarget:$offset),
Expand Down Expand Up @@ -988,9 +991,9 @@ def LL : LLBase<"ll", GPR32Opnd>, LW_FM<0x30>;
def SC : SCBase<"sc", GPR32Opnd>, LW_FM<0x38>;

/// Jump and Branch Instructions
def J : JumpFJ<jmptarget, "j", br, bb>, FJ<2>,
def J : MMRel, JumpFJ<jmptarget, "j", br, bb, "j">, FJ<2>,
Requires<[RelocStatic, HasStdEnc]>, IsBranch;
def JR : IndirectBranch<GPR32Opnd>, MTLO_FM<8>;
def JR : MMRel, IndirectBranch<"jr", GPR32Opnd>, MTLO_FM<8>;
def BEQ : CBranch<"beq", seteq, GPR32Opnd>, BEQ_FM<4>;
def BNE : CBranch<"bne", setne, GPR32Opnd>, BEQ_FM<5>;
def BGEZ : CBranchZero<"bgez", setge, GPR32Opnd>, BGEZ_FM<1, 1>;
Expand All @@ -999,16 +1002,18 @@ def BLEZ : CBranchZero<"blez", setle, GPR32Opnd>, BGEZ_FM<6, 0>;
def BLTZ : CBranchZero<"bltz", setlt, GPR32Opnd>, BGEZ_FM<1, 0>;
def B : UncondBranch<BEQ>;

def JAL : JumpLink<"jal">, FJ<3>;
def JALR : JumpLinkReg<"jalr", GPR32Opnd>, JALR_FM;
def JAL : MMRel, JumpLink<"jal", calltarget>, FJ<3>;
def JALR : MMRel, JumpLinkReg<"jalr", GPR32Opnd>, JALR_FM;
def JALRPseudo : JumpLinkRegPseudo<GPR32Opnd, JALR, RA>;
def BGEZAL : BGEZAL_FT<"bgezal", GPR32Opnd>, BGEZAL_FM<0x11>;
def BLTZAL : BGEZAL_FT<"bltzal", GPR32Opnd>, BGEZAL_FM<0x10>;
def BAL_BR : BAL_BR_Pseudo<BGEZAL>;
def TAILCALL : JumpFJ<calltarget, "j", MipsTailCall, imm>, FJ<2>, IsTailCall;
def TAILCALL_R : JumpFR<GPR32Opnd, MipsTailCall>, MTLO_FM<8>, IsTailCall;
def TAILCALL : MMRel, JumpFJ<calltarget, "j", MipsTailCall, imm, "tcall">,
FJ<2>, IsTailCall;
def TAILCALL_R : MMRel, JumpFR<"tcallr", GPR32Opnd, MipsTailCall>, MTLO_FM<8>,
IsTailCall;

def RET : RetBase<GPR32Opnd>, MTLO_FM<8>;
def RET : MMRel, RetBase<"ret", GPR32Opnd>, MTLO_FM<8>;

// Exception handling related node and instructions.
// The conversion sequence is:
Expand Down
12 changes: 12 additions & 0 deletions test/MC/Disassembler/Mips/micromips.txt
Original file line number Diff line number Diff line change
Expand Up @@ -213,3 +213,15 @@

# CHECK: ins $9, $6, 3, 7
0x01 0x26 0x48 0xcc

# CHECK: j 1328
0xd4 0x00 0x02 0x98

# CHECK: jal 1328
0xf4 0x00 0x02 0x98

# CHECK: jalr $ra, $6
0x03 0xe6 0x0f 0x3c

# CHECK: jr $7
0x00 0x07 0x0f 0x3c
12 changes: 12 additions & 0 deletions test/MC/Disassembler/Mips/micromips_le.txt
Original file line number Diff line number Diff line change
Expand Up @@ -213,3 +213,15 @@

# CHECK: ins $9, $6, 3, 7
0x26 0x01 0xcc 0x48

# CHECK: j 1328
0x00 0xd4 0x98 0x02

# CHECK: jal 1328
0x00 0xf4 0x98 0x02

# CHECK: jalr $ra, $6
0xe6 0x03 0x3c 0x0f

# CHECK: jr $7
0x07 0x00 0x3c 0x0f
Loading

0 comments on commit 1aaf43c

Please sign in to comment.