1
0
mirror of https://github.com/RPCS3/llvm-mirror.git synced 2024-10-19 19:12:56 +02:00

[mips][microMIPS] Implement DBITSWAP, DLSA and LWUPC and add tests for AUI instructions

Differential Revision: https://reviews.llvm.org/D16452

llvm-svn: 280909
This commit is contained in:
Hrvoje Varga 2016-09-08 07:41:43 +00:00
parent 7d1d65f593
commit 12f4bb1c14
11 changed files with 146 additions and 12 deletions

View File

@ -13,6 +13,7 @@
#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"
@ -1166,8 +1167,14 @@ public:
}
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())
@ -1839,7 +1846,8 @@ bool MipsAsmParser::processInstruction(MCInst &Inst, SMLoc IDLoc,
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++) {
@ -4030,6 +4038,9 @@ bool MipsAsmParser::MatchAndEmitInstruction(SMLoc IDLoc, unsigned &Opcode,
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");

View File

@ -120,7 +120,10 @@ namespace MipsII {
/// 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
};
}

View File

@ -219,3 +219,49 @@ class POOL32S_3R_FM_MMR6<string instr_asm, bits<9> funct>
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;
}

View File

@ -67,6 +67,9 @@ class SD_MM64R6_ENC : LD_SD_32_2R_OFFSET16_FM_MMR6<"sd", 0b110110>;
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">;
//===----------------------------------------------------------------------===//
//
@ -323,6 +326,32 @@ class SD_MM64R6_DESC {
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
@ -427,6 +456,12 @@ let DecoderNamespace = "MicroMipsR6" in {
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

View File

@ -831,8 +831,8 @@ let AdditionalPredicates = [NotInMicroMips] 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;

View File

@ -115,18 +115,14 @@ let AdditionalPredicates = [NotInMicroMips] in {
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;

View File

@ -98,11 +98,15 @@ class MipsInst<dag outs, dag ins, string asmstr, list<dag> pattern,
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";

View File

@ -413,6 +413,15 @@ class ConstantSImmAsmOperandClass<int Bits, list<AsmOperandClass> Supers = [],
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;
@ -485,6 +494,13 @@ def ConstantUImm26AsmOperandClass
: 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";
@ -611,6 +627,9 @@ def ConstantImmzAsmOperandClass : AsmOperandClass {
let DiagnosticType = "Immz";
}
def Simm19Lsl2AsmOperand
: SimmLslAsmOperandClass<19, [], 2>;
def MipsJumpTargetAsmOperand : AsmOperandClass {
let Name = "JumpTarget";
let ParserMethod = "parseJumpTarget";
@ -645,7 +664,7 @@ def imm64: Operand<i64>;
def simm19_lsl2 : Operand<i32> {
let EncoderMethod = "getSimm19Lsl2Encoding";
let DecoderMethod = "DecodeSimm19Lsl2";
let ParserMatchClass = MipsJumpTargetAsmOperand;
let ParserMatchClass = Simm19Lsl2AsmOperand;
}
def simm18_lsl3 : Operand<i32> {

View File

@ -314,3 +314,7 @@
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

View File

@ -391,3 +391,13 @@
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

View File

@ -330,5 +330,11 @@ a:
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: