#include "MipsRegisterInfo.h"
#include "MipsTargetObjectFile.h"
#include "MipsTargetStreamer.h"
+#include "MCTargetDesc/MipsBaseInfo.h"
#include "llvm/ADT/SmallVector.h"
#include "llvm/ADT/StringSwitch.h"
#include "llvm/MC/MCContext.h"
}
template <unsigned Bits, unsigned ShiftLeftAmount>
bool isScaledSImm() const {
- return isConstantImm() &&
- isShiftedInt<Bits, ShiftLeftAmount>(getConstantImm());
+ if (isConstantImm() && isShiftedInt<Bits, ShiftLeftAmount>(getConstantImm()))
+ return true;
+ // Operand can also be a symbol or symbol plus offset in case of relocations.
+ if (Kind != k_Immediate)
+ return false;
+ MCValue Res;
+ bool Success = getImm()->evaluateAsRelocatable(Res, nullptr, nullptr);
+ return Success && isShiftedInt<Bits, ShiftLeftAmount>(Res.getConstant());
}
bool isRegList16() const {
if (!isRegList())
ExpandedJalSym = true;
}
- if (MCID.mayLoad() || MCID.mayStore()) {
+ bool IsPCRelativeLoad = (MCID.TSFlags & MipsII::IsPCRelativeLoad) != 0;
+ if ((MCID.mayLoad() || MCID.mayStore()) && !IsPCRelativeLoad) {
// Check the offset of memory operand, if it is a symbol
// reference or immediate we may have to expand instructions.
for (unsigned i = 0; i < MCID.getNumOperands(); i++) {
case Match_SImm16_Relaxed:
return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
"expected 16-bit signed immediate");
+ case Match_SImm19_Lsl2:
+ return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
+ "expected both 19-bit signed immediate and multiple of 4");
case Match_UImm20_0:
return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
"expected 20-bit unsigned immediate");
/// IsCTI - Instruction is a Control Transfer Instruction.
IsCTI = 1 << 4,
/// HasForbiddenSlot - Instruction has a forbidden slot.
- HasForbiddenSlot = 1 << 5
+ HasForbiddenSlot = 1 << 5,
+ /// IsPCRelativeLoad - A Load instruction with implicit source register
+ /// ($pc) with explicit offset and destination register
+ IsPCRelativeLoad = 1 << 6
};
}
let Inst{10-9} = 0b00;
let Inst{8-0} = funct;
}
+
+class POOL32S_DBITSWAP_FM_MMR6<string instr_asm> : MMR6Arch<instr_asm>,
+ MipsR6Inst {
+ bits<5> rt;
+ bits<5> rd;
+
+ bits<32> Inst;
+
+ let Inst{31-26} = 0b010110;
+ let Inst{25-21} = rt;
+ let Inst{20-16} = rd;
+ let Inst{15-12} = 0b0000;
+ let Inst{11-6} = 0b101100;
+ let Inst{5-0} = 0b111100;
+}
+
+class POOL32S_3RSA_FM_MMR6<string instr_asm> : MMR6Arch<instr_asm>,
+ MipsR6Inst {
+ bits<5> rt;
+ bits<5> rs;
+ bits<5> rd;
+ bits<2> sa;
+
+ bits<32> Inst;
+
+ let Inst{31-26} = 0b010110;
+ let Inst{25-21} = rt;
+ let Inst{20-16} = rs;
+ let Inst{15-11} = rd;
+ let Inst{10-9} = sa;
+ let Inst{8-6} = 0b100;
+ let Inst{5-0} = 0b000100;
+}
+
+class PCREL_1ROFFSET19_FM_MMR6<string instr_asm> : MMR6Arch<instr_asm>,
+ MipsR6Inst {
+ bits<5> rt;
+ bits<19> offset;
+
+ bits<32> Inst;
+
+ let Inst{31-26} = 0b011110;
+ let Inst{25-21} = rt;
+ let Inst{20-19} = 0b10;
+ let Inst{18-0} = offset;
+}
class DSRL_MM64R6_ENC : POOL32S_2RSA5B0_FM_MMR6<"dsrl", 0b001000000>;
class DSRL32_MM64R6_ENC : POOL32S_2RSA5B0_FM_MMR6<"dsrl32", 0b001001000>;
class DSRLV_MM64R6_ENC : POOL32S_3R_FM_MMR6<"dsrlv", 0b001010000>;
+class DBITSWAP_MM64R6_ENC : POOL32S_DBITSWAP_FM_MMR6<"dbitswap">;
+class DLSA_MM64R6_ENC : POOL32S_3RSA_FM_MMR6<"dlsa">;
+class LWUPC_MM64R6_ENC : PCREL_1ROFFSET19_FM_MMR6<"lwupc">;
//===----------------------------------------------------------------------===//
//
string DecoderMethod = "DecodeMemMMImm16";
}
+class DBITSWAP_MM64R6_DESC {
+ dag OutOperandList = (outs GPR64Opnd:$rd);
+ dag InOperandList = (ins GPR64Opnd:$rt);
+ string AsmString = !strconcat("dbitswap", "\t$rd, $rt");
+ list<dag> Pattern = [];
+ InstrItinClass Itinerary = II_DBITSWAP;
+}
+
+class DLSA_MM64R6_DESC {
+ dag OutOperandList = (outs GPR64Opnd:$rd);
+ dag InOperandList = (ins GPR64Opnd:$rt, GPR64Opnd:$rs, uimm2_plus1:$sa);
+ string AsmString = "dlsa\t$rt, $rs, $rd, $sa";
+ list<dag> Pattern = [];
+ InstrItinClass Itinerary = II_DLSA;
+}
+
+class LWUPC_MM64R6_DESC {
+ dag OutOperandList = (outs GPR64Opnd:$rt);
+ dag InOperandList = (ins simm19_lsl2:$offset);
+ string AsmString = "lwupc\t$rt, $offset";
+ list<dag> Pattern = [];
+ InstrItinClass Itinerary = II_LWUPC;
+ bit mayLoad = 1;
+ bit IsPCRelativeLoad = 1;
+}
+
//===----------------------------------------------------------------------===//
//
// Instruction Definitions
ISA_MICROMIPS64R6;
def DSRLV_MM64R6 : StdMMR6Rel, DSRLV_MM64R6_ENC, DSRLV_MM64R6_DESC,
ISA_MICROMIPS64R6;
+ def DBITSWAP_MM64R6 : R6MMR6Rel, DBITSWAP_MM64R6_ENC, DBITSWAP_MM64R6_DESC,
+ ISA_MICROMIPS64R6;
+ def DLSA_MM64R6 : R6MMR6Rel, DLSA_MM64R6_ENC, DLSA_MM64R6_DESC,
+ ISA_MICROMIPS64R6;
+ def LWUPC_MM64R6 : R6MMR6Rel, LWUPC_MM64R6_ENC, LWUPC_MM64R6_DESC,
+ ISA_MICROMIPS64R6;
}
let AdditionalPredicates = [InMicroMips] in
def LWC2_R6 : LWC2_R6_ENC, LWC2_R6_DESC, ISA_MIPS32R6;
}
def LWPC : R6MMR6Rel, LWPC_ENC, LWPC_DESC, ISA_MIPS32R6;
-def LWUPC : LWUPC_ENC, LWUPC_DESC, ISA_MIPS32R6;
let AdditionalPredicates = [NotInMicroMips] in {
+ def LWUPC : R6MMR6Rel, LWUPC_ENC, LWUPC_DESC, ISA_MIPS32R6;
def MADDF_S : MADDF_S_ENC, MADDF_S_DESC, ISA_MIPS32R6, HARDFLOAT;
def MADDF_D : MADDF_D_ENC, MADDF_D_DESC, ISA_MIPS32R6, HARDFLOAT;
def MAXA_D : MAXA_D_ENC, MAXA_D_DESC, ISA_MIPS32R6, HARDFLOAT;
def DAHI : DAHI_ENC, DAHI_DESC, ISA_MIPS64R6;
def DAUI : DAUI_ENC, DAUI_DESC, ISA_MIPS64R6;
def DALIGN : DALIGN_ENC, DALIGN_DESC, ISA_MIPS64R6;
-}
-def DBITSWAP : DBITSWAP_ENC, DBITSWAP_DESC, ISA_MIPS64R6;
-let AdditionalPredicates = [NotInMicroMips] in {
+ def DBITSWAP : R6MMR6Rel, DBITSWAP_ENC, DBITSWAP_DESC, ISA_MIPS64R6;
def DCLO_R6 : R6MMR6Rel, DCLO_R6_ENC, DCLO_R6_DESC, ISA_MIPS64R6;
def DCLZ_R6 : R6MMR6Rel, DCLZ_R6_ENC, DCLZ_R6_DESC, ISA_MIPS64R6;
def DDIV : DDIV_ENC, DDIV_DESC, ISA_MIPS64R6;
def DDIVU : DDIVU_ENC, DDIVU_DESC, ISA_MIPS64R6;
def DMOD : DMOD_ENC, DMOD_DESC, ISA_MIPS64R6;
def DMODU : DMODU_ENC, DMODU_DESC, ISA_MIPS64R6;
-}
-def DLSA_R6 : DLSA_R6_ENC, DLSA_R6_DESC, ISA_MIPS64R6;
-let AdditionalPredicates = [NotInMicroMips] in {
+ def DLSA_R6 : R6MMR6Rel, DLSA_R6_ENC, DLSA_R6_DESC, ISA_MIPS64R6;
def DMUH: DMUH_ENC, DMUH_DESC, ISA_MIPS64R6;
def DMUHU: DMUHU_ENC, DMUHU_DESC, ISA_MIPS64R6;
def DMUL_R6: DMUL_R6_ENC, DMUL_R6_DESC, ISA_MIPS64R6;
bit isCTI = 0; // Any form of Control Transfer Instruction.
// Required for MIPSR6
bit hasForbiddenSlot = 0; // Instruction has a forbidden slot.
+ bit IsPCRelativeLoad = 0; // Load instruction with implicit source register
+ // ($pc) and with explicit offset and destination
+ // register
// TSFlags layout should be kept in sync with MipsInstrInfo.h.
let TSFlags{3-0} = FormBits;
let TSFlags{4} = isCTI;
let TSFlags{5} = hasForbiddenSlot;
+ let TSFlags{6} = IsPCRelativeLoad;
let DecoderNamespace = "Mips";
let DiagnosticType = "SImm" # Bits # "_" # Offset;
}
+class SimmLslAsmOperandClass<int Bits, list<AsmOperandClass> Supers = [],
+ int Shift = 0> : AsmOperandClass {
+ let Name = "Simm" # Bits # "_Lsl" # Shift;
+ let RenderMethod = "addImmOperands";
+ let PredicateMethod = "isScaledSImm<" # Bits # ", " # Shift # ">";
+ let SuperClasses = Supers;
+ let DiagnosticType = "SImm" # Bits # "_Lsl" # Shift;
+}
+
class ConstantUImmAsmOperandClass<int Bits, list<AsmOperandClass> Supers = [],
int Offset = 0> : AsmOperandClass {
let Name = "ConstantUImm" # Bits # "_" # Offset;
: ConstantUImmAsmOperandClass<26, [SImm32AsmOperandClass]>;
def ConstantUImm20AsmOperandClass
: ConstantUImmAsmOperandClass<20, [ConstantUImm26AsmOperandClass]>;
+def ConstantSImm19Lsl2AsmOperandClass : AsmOperandClass {
+ let Name = "SImm19Lsl2";
+ let RenderMethod = "addImmOperands";
+ let PredicateMethod = "isScaledSImm<19, 2>";
+ let SuperClasses = [ConstantUImm20AsmOperandClass];
+ let DiagnosticType = "SImm19_Lsl2";
+}
def UImm16RelaxedAsmOperandClass
: UImmAsmOperandClass<16, [ConstantUImm20AsmOperandClass]> {
let Name = "UImm16_Relaxed";
let DiagnosticType = "Immz";
}
+def Simm19Lsl2AsmOperand
+ : SimmLslAsmOperandClass<19, [], 2>;
+
def MipsJumpTargetAsmOperand : AsmOperandClass {
let Name = "JumpTarget";
let ParserMethod = "parseJumpTarget";
def simm19_lsl2 : Operand<i32> {
let EncoderMethod = "getSimm19Lsl2Encoding";
let DecoderMethod = "DecodeSimm19Lsl2";
- let ParserMatchClass = MipsJumpTargetAsmOperand;
+ let ParserMatchClass = Simm19Lsl2AsmOperand;
}
def simm18_lsl3 : Operand<i32> {
0xf4 0x40 0x00 0x40 # CHECK: blezc $2, 260
0xf6 0x10 0x00 0x80 # CHECK: bgezc $16, 516
0xd5 0x80 0x01 0x00 # CHECK: bgtzc $12, 1028
+0x10 0x64 0x01 0x00 # CHECK: aui $3, $4, 256
+0x58 0x83 0x0b 0x3c # CHECK: dbitswap $3, $4
+0x58 0x64 0x2d 0x04 # CHECK: dlsa $3, $4, $5, 3
+0x78 0x50 0x00 0x43 # CHECK: lwupc $2, 268
bnezc $2, -4194303 # CHECK: :[[@LINE]]:{{[0-9]+}}: error: branch to misaligned address
bnezc $2, 4194304 # CHECK: :[[@LINE]]:{{[0-9]+}}: error: branch target out of range
bnezc $2, 4194303 # CHECK: :[[@LINE]]:{{[0-9]+}}: error: branch to misaligned address
+ dlsa $3, $4, $5, 5 # CHECK: :[[@LINE]]:{{[0-9]+}}: error: expected immediate in range 1 .. 4
+ dlsa $3, $4, $5, -1 # CHECK: :[[@LINE]]:{{[0-9]+}}: error: expected immediate in range 1 .. 4
+ dlsa $3, $4, $5, 0 # CHECK: :[[@LINE]]:{{[0-9]+}}: error: expected immediate in range 1 .. 4
+ lwupc $2, 262145 # CHECK: :[[@LINE]]:13: error: expected both 19-bit signed immediate and multiple of 4
+ lwupc $2, 5 # CHECK: :[[@LINE]]:13: error: expected both 19-bit signed immediate and multiple of 4
+ lwupc $2, -262145 # CHECK: :[[@LINE]]:13: error: expected both 19-bit signed immediate and multiple of 4
+ lwupc $2, $2 # CHECK: :[[@LINE]]:13: error: expected both 19-bit signed immediate and multiple of 4
+ lwupc $2, bar+267 # CHECK: :[[@LINE]]:13: error: expected both 19-bit signed immediate and multiple of 4
+ aui $3, $4, 32768 # CHECK: :[[@LINE]]:15: error: expected 16-bit signed immediate
+ aui $3, $4, -32769 # CHECK: :[[@LINE]]:15: error: expected 16-bit signed immediate
blezc $2, 256 # CHECK: blezc $2, 256 # encoding: [0xf4,0x40,0x00,0x40]
bgezc $16, 512 # CHECK: bgezc $16, 512 # encoding: [0xf6,0x10,0x00,0x80]
bgtzc $12, 1024 # CHECK: bgtzc $12, 1024 # encoding: [0xd5,0x80,0x01,0x00]
+ aui $3, $4, 256 # CHECK: aui $3, $4, 256 # encoding: [0x10,0x64,0x01,0x00]
+ dbitswap $3, $4 # CHECK: dbitswap $3, $4 # encoding: [0x58,0x83,0x0b,0x3c]
+ dlsa $3, $4, $5, 3 # CHECK: dlsa $3, $4, $5, 3 # encoding: [0x58,0x64,0x2d,0x04]
+ lwupc $2, 268 # CHECK: lwupc $2, 268 # encoding: [0x78,0x50,0x00,0x43]
+ lwupc $2, bar # CHECK: lwupc $2, bar # encoding: [0x78,0b01010AAA,A,A]
+ lwupc $2, bar+268 # CHECK: lwupc $2, bar+268 # encoding: [0x78,0b01010AAA,A,A]
1: