summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--llvm/lib/Target/Mips/AsmParser/MipsAsmParser.cpp19
-rw-r--r--llvm/lib/Target/Mips/MicroMipsInstrFormats.td12
-rw-r--r--llvm/lib/Target/Mips/MicroMipsInstrInfo.td10
-rw-r--r--llvm/test/MC/Mips/micromips-16-bit-instructions.s3
-rw-r--r--llvm/test/MC/Mips/micromips-invalid.s4
5 files changed, 48 insertions, 0 deletions
diff --git a/llvm/lib/Target/Mips/AsmParser/MipsAsmParser.cpp b/llvm/lib/Target/Mips/AsmParser/MipsAsmParser.cpp
index 21d2876fdd0..db9c679b767 100644
--- a/llvm/lib/Target/Mips/AsmParser/MipsAsmParser.cpp
+++ b/llvm/lib/Target/Mips/AsmParser/MipsAsmParser.cpp
@@ -1117,6 +1117,25 @@ bool MipsAsmParser::processInstruction(MCInst &Inst, SMLoc IDLoc,
} // for
} // if load/store
+ // TODO: Handle this with the AsmOperandClass.PredicateMethod.
+ if (inMicroMipsMode()) {
+ MCOperand Opnd;
+ int Imm;
+
+ switch (Inst.getOpcode()) {
+ default:
+ break;
+ case Mips::ADDIUS5_MM:
+ Opnd = Inst.getOperand(2);
+ if (!Opnd.isImm())
+ return Error(IDLoc, "expected immediate operand kind");
+ Imm = Opnd.getImm();
+ if (Imm < -8 || Imm > 7)
+ return Error(IDLoc, "immediate operand value out of range");
+ break;
+ }
+ }
+
if (needsExpansion(Inst))
return expandInstruction(Inst, IDLoc, Instructions);
else
diff --git a/llvm/lib/Target/Mips/MicroMipsInstrFormats.td b/llvm/lib/Target/Mips/MicroMipsInstrFormats.td
index 57f3dd540ef..9d403460cd8 100644
--- a/llvm/lib/Target/Mips/MicroMipsInstrFormats.td
+++ b/llvm/lib/Target/Mips/MicroMipsInstrFormats.td
@@ -41,6 +41,18 @@ class MicroMipsInst16<dag outs, dag ins, string asmstr, list<dag> pattern,
// MicroMIPS 16-bit Instruction Formats
//===----------------------------------------------------------------------===//
+class ADDIUS5_FM_MM16 {
+ bits<5> rd;
+ bits<4> imm;
+
+ bits<16> Inst;
+
+ let Inst{15-10} = 0x13;
+ let Inst{9-5} = rd;
+ let Inst{4-1} = imm;
+ let Inst{0} = 0;
+}
+
class MOVE_FM_MM16<bits<6> funct> {
bits<5> rs;
bits<5> rd;
diff --git a/llvm/lib/Target/Mips/MicroMipsInstrInfo.td b/llvm/lib/Target/Mips/MicroMipsInstrInfo.td
index 86b4b0f279e..71abfcd82ef 100644
--- a/llvm/lib/Target/Mips/MicroMipsInstrInfo.td
+++ b/llvm/lib/Target/Mips/MicroMipsInstrInfo.td
@@ -1,5 +1,7 @@
def addrimm12 : ComplexPattern<iPTR, 2, "selectIntAddrMM", [frameindex]>;
+def simm4 : Operand<i32>;
+
def simm12 : Operand<i32> {
let DecoderMethod = "DecodeSimm12";
}
@@ -84,6 +86,13 @@ class LoadMM<string opstr, DAGOperand RO, SDPatternOperator OpNode = null_frag,
let mayLoad = 1;
}
+class AddImmUS5<string opstr, RegisterOperand RO> :
+ MicroMipsInst16<(outs RO:$dst), (ins RO:$rd, simm4:$imm),
+ !strconcat(opstr, "\t$rd, $imm"), [], NoItinerary, FrmR> {
+ let Constraints = "$rd = $dst";
+ let isCommutable = 1;
+}
+
class MoveFromHILOMM<string opstr, RegisterOperand RO, Register UseReg> :
MicroMipsInst16<(outs RO:$rd), (ins), !strconcat(opstr, "\t$rd"),
[], II_MFHI_MFLO, FrmR> {
@@ -156,6 +165,7 @@ let isCall = 1, hasDelaySlot = 1, Defs = [RA] in {
!strconcat(opstr, "\t$rs, $offset"), [], IIBranch, FrmI, opstr>;
}
+def ADDIUS5_MM : AddImmUS5<"addius5", GPR32Opnd>, ADDIUS5_FM_MM16;
def MFHI16_MM : MoveFromHILOMM<"mfhi", GPR32Opnd, AC0>, MFHILO_FM_MM16<0x10>;
def MFLO16_MM : MoveFromHILOMM<"mflo", GPR32Opnd, AC0>, MFHILO_FM_MM16<0x12>;
def MOVE16_MM : MoveMM16<"move", GPR32Opnd>, MOVE_FM_MM16<0x03>;
diff --git a/llvm/test/MC/Mips/micromips-16-bit-instructions.s b/llvm/test/MC/Mips/micromips-16-bit-instructions.s
index 63ae5d0575c..c9d22936d32 100644
--- a/llvm/test/MC/Mips/micromips-16-bit-instructions.s
+++ b/llvm/test/MC/Mips/micromips-16-bit-instructions.s
@@ -9,6 +9,7 @@
#------------------------------------------------------------------------------
# Little endian
#------------------------------------------------------------------------------
+# CHECK-EL: addius5 $7, -2 # encoding: [0xfc,0x4c]
# CHECK-EL: mfhi $9 # encoding: [0x09,0x46]
# CHECK-EL: mflo $9 # encoding: [0x49,0x46]
# CHECK-EL: move $25, $1 # encoding: [0x21,0x0f]
@@ -21,6 +22,7 @@
#------------------------------------------------------------------------------
# Big endian
#------------------------------------------------------------------------------
+# CHECK-EB: addius5 $7, -2 # encoding: [0x4c,0xfc]
# CHECK-EB: mfhi $9 # encoding: [0x46,0x09]
# CHECK-EB: mflo $9 # encoding: [0x46,0x49]
# CHECK-EB: move $25, $1 # encoding: [0x0f,0x21]
@@ -31,6 +33,7 @@
# CHECK-EB: jalrs16 $9 # encoding: [0x45,0xe9]
# CHECK-EB: move $zero, $zero # encoding: [0x0c,0x00]
+ addius5 $7, -2
mfhi $9
mflo $9
move $25, $1
diff --git a/llvm/test/MC/Mips/micromips-invalid.s b/llvm/test/MC/Mips/micromips-invalid.s
new file mode 100644
index 00000000000..116628e8715
--- /dev/null
+++ b/llvm/test/MC/Mips/micromips-invalid.s
@@ -0,0 +1,4 @@
+# RUN: not llvm-mc %s -triple=mipsel -show-encoding -mattr=micromips 2>%t1
+# RUN: FileCheck %s < %t1
+
+ addius5 $7, 9 # CHECK: :[[@LINE]]:{{[0-9]+}}: error: immediate operand value out of range
OpenPOWER on IntegriCloud