return Error(IDLoc, "branch to misaligned address");
break;
case Mips::BEQZ16_MM:
+ case Mips::BEQZC16_MMR6:
case Mips::BNEZ16_MM:
+ case Mips::BNEZC16_MMR6:
assert(MCID.getNumOperands() == 2 && "unexpected number of operands");
Offset = Inst.getOperand(1);
if (!Offset.isImm())
case Mips::LoadAddrReg32:
case Mips::LoadAddrReg64:
case Mips::B_MM_Pseudo:
+ case Mips::B_MMR6_Pseudo:
case Mips::LWM_MM:
case Mips::SWM_MM:
case Mips::JalOneReg:
Inst.getOperand(0).getReg(), Inst.getOperand(1).getReg(), Inst.getOperand(2),
Inst.getOpcode() == Mips::LoadAddrReg32, IDLoc, Instructions);
case Mips::B_MM_Pseudo:
+ case Mips::B_MMR6_Pseudo:
return expandUncondBranchMMPseudo(Inst, IDLoc, Instructions);
case Mips::SWM_MM:
case Mips::LWM_MM:
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);
+ if (inMicroMipsMode())
+ Inst.setOpcode(hasMips32r6() ? Mips::BC16_MMR6 : Mips::B16_MM);
} else {
if (!isIntN(17, Offset.getImm()))
Error(IDLoc, "branch target out of range");
}
Instructions.push_back(Inst);
- // If .set reorder is active, emit a NOP after the branch instruction.
- if (AssemblerOptions.back()->isReorder())
+ // If .set reorder is active and branch instruction has a delay slot,
+ // emit a NOP after it.
+ const MCInstrDesc &MCID = getInstDesc(Inst.getOpcode());
+ if (MCID.hasDelaySlot() && AssemblerOptions.back()->isReorder())
createNop(true, IDLoc, Instructions);
return false;
if (IsMicroMips) {
Result = readInstruction16(Bytes, Address, Size, Insn, IsBigEndian);
+ if (hasMips32r6()) {
+ DEBUG(dbgs() << "Trying MicroMipsR616 table (16-bit instructions):\n");
+ // Calling the auto-generated decoder function for microMIPS32R6
+ // (and microMIPS64R6) 16-bit instructions.
+ Result = decodeInstruction(DecoderTableMicroMipsR616, Instr, Insn,
+ Address, this, STI);
+ if (Result != MCDisassembler::Fail) {
+ Size = 2;
+ return Result;
+ }
+ }
+
DEBUG(dbgs() << "Trying MicroMips16 table (16-bit instructions):\n");
- // Calling the auto-generated decoder function.
+ // Calling the auto-generated decoder function for microMIPS 16-bit
+ // instructions.
Result = decodeInstruction(DecoderTableMicroMips16, Instr, Insn, Address,
this, STI);
if (Result != MCDisassembler::Fail) {
// Calling the auto-generated decoder function.
Result = decodeInstruction(DecoderTableMicroMipsR632, Instr, Insn, Address,
this, STI);
- } else {
- DEBUG(dbgs() << "Trying MicroMips32 table (32-bit instructions):\n");
- // Calling the auto-generated decoder function.
- Result = decodeInstruction(DecoderTableMicroMips32, Instr, Insn, Address,
- this, STI);
+ if (Result != MCDisassembler::Fail) {
+ Size = 4;
+ return Result;
+ }
}
+ DEBUG(dbgs() << "Trying MicroMips32 table (32-bit instructions):\n");
+ // Calling the auto-generated decoder function.
+ Result = decodeInstruction(DecoderTableMicroMips32, Instr, Insn, Address,
+ this, STI);
if (Result != MCDisassembler::Fail) {
Size = 4;
return Result;
string BaseOpcode = opstr;
}
+// Class used for microMIPS32r6 and microMIPS64r6 instructions.
+class MicroMipsR6Inst16 : PredicateControl {
+ string DecoderNamespace = "MicroMipsR6";
+ let InsnPredicates = [HasMicroMips32r6];
+}
+
+class BC16_FM_MM16R6 {
+ bits<10> offset;
+
+ bits<16> Inst;
+
+ let Inst{15-10} = 0x33;
+ let Inst{9-0} = offset;
+}
+
+class BEQZC_BNEZC_FM_MM16R6<bits<6> op> : MicroMipsR6Inst16 {
+ bits<3> rs;
+ bits<7> offset;
+
+ bits<16> Inst;
+
+ let Inst{15-10} = op;
+ let Inst{9-7} = rs;
+ let Inst{6-0} = offset;
+}
+
class POOL32A_BITSWAP_FM_MMR6<bits<6> funct> : MipsR6Inst {
bits<5> rd;
bits<5> rt;
class AUI_MMR6_ENC : AUI_FM_MMR6;
class BALC_MMR6_ENC : BRANCH_OFF26_FM<0b101101>;
class BC_MMR6_ENC : BRANCH_OFF26_FM<0b100101>;
+class BC16_MMR6_ENC : BC16_FM_MM16R6;
+class BEQZC16_MMR6_ENC : BEQZC_BNEZC_FM_MM16R6<0x23>;
+class BNEZC16_MMR6_ENC : BEQZC_BNEZC_FM_MM16R6<0x2b>;
class BITSWAP_MMR6_ENC : POOL32A_BITSWAP_FM_MMR6<0b101100>;
class BRK_MMR6_ENC : BREAK_MMR6_ENC<"break">;
class BEQZALC_MMR6_ENC : CMP_BRANCH_1R_RT_OFF16_FM_MMR6<0b011101>;
list<Register> Defs = [RA];
}
class BC_MMR6_DESC : BC_MMR6_DESC_BASE<"bc", brtarget26>;
+
+class BC16_MMR6_DESC : MicroMipsInst16<(outs), (ins brtarget10_mm:$offset),
+ !strconcat("bc16", "\t$offset"), [],
+ IIBranch, FrmI>,
+ MMR6Arch<"bc16">, MicroMipsR6Inst16 {
+ let isBranch = 1;
+ let isTerminator = 1;
+ let isBarrier = 1;
+ let hasDelaySlot = 0;
+ let AdditionalPredicates = [RelocPIC];
+ let Defs = [AT];
+}
+
+class BEQZC_BNEZC_MM16R6_DESC_BASE<string instr_asm>
+ : CBranchZeroMM<instr_asm, brtarget7_mm, GPRMM16Opnd>, MMR6Arch<instr_asm> {
+ let isBranch = 1;
+ let isTerminator = 1;
+ let hasDelaySlot = 0;
+ let Defs = [AT];
+}
+class BEQZC16_MMR6_DESC : BEQZC_BNEZC_MM16R6_DESC_BASE<"beqzc16">;
+class BNEZC16_MMR6_DESC : BEQZC_BNEZC_MM16R6_DESC_BASE<"bnezc16">;
+
class SUB_MMR6_DESC : ArithLogicR<"sub", GPR32Opnd>;
class SUBU_MMR6_DESC : ArithLogicR<"subu", GPR32Opnd>;
def AUI_MMR6 : R6MMR6Rel, AUI_MMR6_ENC, AUI_MMR6_DESC, ISA_MICROMIPS32R6;
def BALC_MMR6 : R6MMR6Rel, BALC_MMR6_ENC, BALC_MMR6_DESC, ISA_MICROMIPS32R6;
def BC_MMR6 : R6MMR6Rel, BC_MMR6_ENC, BC_MMR6_DESC, ISA_MICROMIPS32R6;
+def BC16_MMR6 : StdMMR6Rel, BC16_MMR6_DESC, BC16_MMR6_ENC, ISA_MICROMIPS32R6;
+def BEQZC16_MMR6 : StdMMR6Rel, BEQZC16_MMR6_DESC, BEQZC16_MMR6_ENC,
+ ISA_MICROMIPS32R6;
+def BNEZC16_MMR6 : StdMMR6Rel, BNEZC16_MMR6_DESC, BNEZC16_MMR6_ENC,
+ ISA_MICROMIPS32R6;
def BITSWAP_MMR6 : R6MMR6Rel, BITSWAP_MMR6_ENC, BITSWAP_MMR6_DESC,
ISA_MICROMIPS32R6;
def BEQZALC_MMR6 : R6MMR6Rel, BEQZALC_MMR6_ENC, BEQZALC_MMR6_DESC,
def : MipsInstAlias<"ei", (EI_MMR6 ZERO), 1>, ISA_MICROMIPS32R6;
def : MipsInstAlias<"nop", (SLL_MMR6 ZERO, ZERO, 0), 1>, ISA_MICROMIPS32R6;
+def B_MMR6_Pseudo : MipsAsmPseudoInst<(outs), (ins brtarget_mm:$offset),
+ !strconcat("b", "\t$offset")>,
+ MicroMipsR6Inst16;
MipsAsmPseudoInst<(outs), (ins brtarget_mm:$offset),
!strconcat(opstr, "\t$offset")>;
- def B_MM_Pseudo : UncondBranchMMPseudo<"b">;
+def B_MM_Pseudo : UncondBranchMMPseudo<"b">, ISA_MICROMIPS;
def : MipsInstAlias<"wait", (WAIT_MM 0x0), 1>;
def : MipsInstAlias<"nop", (SLL_MM ZERO, ZERO, 0), 1>;
class ISA_MIPS64R2 { list<Predicate> InsnPredicates = [HasMips64r2]; }
class ISA_MIPS32R6 { list<Predicate> InsnPredicates = [HasMips32r6]; }
class ISA_MIPS64R6 { list<Predicate> InsnPredicates = [HasMips64r6]; }
+class ISA_MICROMIPS { list<Predicate> InsnPredicates = [InMicroMips]; }
class ISA_MICROMIPS32R6 {
list<Predicate> InsnPredicates = [HasMicroMips32r6];
}
0x94 0x37 0x96 0xb8 # CHECK: bc 14572256
+0xcc 0x42 # CHECK: bc16 132
+
+0x8f 0x0a # CHECK: beqzc16 $6, 20
+
+0xaf 0x0a # CHECK: bnezc16 $6, 20
+
0x00 0x44 0x0b 0x3c # CHECK: bitswap $4, $2
0x00 0x00 0x00 0x07 # CHECK: break
0x4f 0xf9 # CHECK: addiusp -16
+0xcc 0x42 # CHECK: bc16 132
+
+0x8f 0x0a # CHECK: beqzc16 $6, 20
+
+0xaf 0x0a # CHECK: bnezc16 $6, 20
+
0xf0 0x64 0x00 0x05 # CHECK: daui $3, $4, 5
0x42 0x23 0x00 0x04 # CHECK: dahi $3, 4
addiur2 $6, $7, 10 # CHECK: :[[@LINE]]:{{[0-9]+}}: error: immediate operand value out of range
addius5 $7, 9 # CHECK: :[[@LINE]]:{{[0-9]+}}: error: immediate operand value out of range
addiusp 1032 # CHECK: :[[@LINE]]:{{[0-9]+}}: error: immediate operand value out of range
+ beqzc16 $9, 20 # CHECK: :[[@LINE]]:{{[0-9]+}}: error: invalid operand for instruction
+ beqzc16 $6, 31 # CHECK: :[[@LINE]]:{{[0-9]+}}: error: branch to misaligned address
+ beqzc16 $6, 130 # CHECK: :[[@LINE]]:{{[0-9]+}}: error: branch target out of range
+ bnezc16 $9, 20 # CHECK: :[[@LINE]]:{{[0-9]+}}: error: invalid operand for instruction
+ bnezc16 $6, 31 # CHECK: :[[@LINE]]:{{[0-9]+}}: error: branch to misaligned address
+ bnezc16 $6, 130 # CHECK: :[[@LINE]]:{{[0-9]+}}: error: branch target out of range
break 1024 # CHECK: :[[@LINE]]:{{[0-9]+}}: error: invalid operand for instruction
break 1023, 1024 # CHECK: :[[@LINE]]:{{[0-9]+}}: error: invalid operand for instruction
ei $32 # CHECK: :[[@LINE]]:{{[0-9]+}}: error: invalid operand for instruction
bltzalc $2, 1332 # CHECK: bltzalc $2, 1332 # encoding: [0xe0,0x42,0x02,0x9a]
blezalc $2, 1332 # CHECK: blezalc $2, 1332 # encoding: [0xc0,0x40,0x02,0x9a]
balc 14572256 # CHECK: balc 14572256 # encoding: [0xb4,0x37,0x96,0xb8]
+ b 132 # CHECK: bc16 132 # encoding: [0xcc,0x42]
bc 14572256 # CHECK: bc 14572256 # encoding: [0x94,0x37,0x96,0xb8]
+ bc16 132 # CHECK: bc16 132 # encoding: [0xcc,0x42]
+ beqzc16 $6, 20 # CHECK: beqzc16 $6, 20 # encoding: [0x8f,0x0a]
+ bnezc16 $6, 20 # CHECK: bnezc16 $6, 20 # encoding: [0xaf,0x0a]
bitswap $4, $2 # CHECK: bitswap $4, $2 # encoding: [0x00,0x44,0x0b,0x3c]
break # CHECK: break # encoding: [0x00,0x00,0x00,0x07]
break 7 # CHECK: break 7 # encoding: [0x00,0x07,0x00,0x07]
addiur2 $6, $7, 10 # CHECK: :[[@LINE]]:{{[0-9]+}}: error: immediate operand value out of range
addius5 $7, 9 # CHECK: :[[@LINE]]:{{[0-9]+}}: error: immediate operand value out of range
addiusp 1032 # CHECK: :[[@LINE]]:{{[0-9]+}}: error: immediate operand value out of range
+ beqzc16 $9, 20 # CHECK: :[[@LINE]]:{{[0-9]+}}: error: invalid operand for instruction
+ beqzc16 $6, 31 # CHECK: :[[@LINE]]:{{[0-9]+}}: error: branch to misaligned address
+ beqzc16 $6, 130 # CHECK: :[[@LINE]]:{{[0-9]+}}: error: branch target out of range
+ bnezc16 $9, 20 # CHECK: :[[@LINE]]:{{[0-9]+}}: error: invalid operand for instruction
+ bnezc16 $6, 31 # CHECK: :[[@LINE]]:{{[0-9]+}}: error: branch to misaligned address
+ bnezc16 $6, 130 # CHECK: :[[@LINE]]:{{[0-9]+}}: error: branch target out of range
ddiv $32, $4, $5 # CHECK: :[[@LINE]]:{{[0-9]+}}: error: invalid operand for instruction
ddiv $3, $34, $5 # CHECK: :[[@LINE]]:{{[0-9]+}}: error: invalid operand for instruction
ddiv $3, $4, $35 # CHECK: :[[@LINE]]:{{[0-9]+}}: error: invalid operand for instruction
addiusp 1024 # CHECK: addiusp 1024 # encoding: [0x4c,0x01]
addiusp 1028 # CHECK: addiusp 1028 # encoding: [0x4c,0x03]
addiusp -16 # CHECK: addiusp -16 # encoding: [0x4f,0xf9]
+ b 132 # CHECK: bc16 132 # encoding: [0xcc,0x42]
+ bc16 132 # CHECK: bc16 132 # encoding: [0xcc,0x42]
+ beqzc16 $6, 20 # CHECK: beqzc16 $6, 20 # encoding: [0x8f,0x0a]
+ bnezc16 $6, 20 # CHECK: bnezc16 $6, 20 # encoding: [0xaf,0x0a]
daui $3, $4, 5 # CHECK: daui $3, $4, 5 # encoding: [0xf0,0x64,0x00,0x05]
dahi $3, 4 # CHECK: dahi $3, 4 # encoding: [0x42,0x23,0x00,0x04]
dati $3, 4 # CHECK: dati $3, 4 # encoding: [0x42,0x03,0x00,0x04]