mirror of
https://github.com/RPCS3/llvm-mirror.git
synced 2024-11-24 11:42:57 +01:00
[mips][microMIPS] Implement SWM16 and LWM16 instructions
Differential Revision: http://reviews.llvm.org/D5579 llvm-svn: 222901
This commit is contained in:
parent
c85a4a5656
commit
15712f82b0
@ -809,6 +809,29 @@ public:
|
||||
bool isMemWithGRPMM16Base() const {
|
||||
return isMem() && getMemBase()->isMM16AsmReg();
|
||||
}
|
||||
template <unsigned Bits> bool isMemWithUimmOffsetSP() const {
|
||||
return isMem() && isConstantMemOff() && isUInt<Bits>(getConstantMemOff())
|
||||
&& getMemBase()->isRegIdx() && (getMemBase()->getGPR32Reg() == Mips::SP);
|
||||
}
|
||||
bool isRegList16() const {
|
||||
if (!isRegList())
|
||||
return false;
|
||||
|
||||
int Size = RegList.List->size();
|
||||
if (Size < 2 || Size > 5 || *RegList.List->begin() != Mips::S0 ||
|
||||
RegList.List->back() != Mips::RA)
|
||||
return false;
|
||||
|
||||
int PrevReg = *RegList.List->begin();
|
||||
for (int i = 1; i < Size - 1; i++) {
|
||||
int Reg = (*(RegList.List))[i];
|
||||
if ( Reg != PrevReg + 1)
|
||||
return false;
|
||||
PrevReg = Reg;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
bool isInvNum() const { return Kind == k_Immediate; }
|
||||
bool isLSAImm() const {
|
||||
if (!isConstantImm())
|
||||
|
@ -380,6 +380,10 @@ static DecodeStatus DecodeRegListOperand(MCInst &Inst, unsigned Insn,
|
||||
uint64_t Address,
|
||||
const void *Decoder);
|
||||
|
||||
static DecodeStatus DecodeRegListOperand16(MCInst &Inst, unsigned Insn,
|
||||
uint64_t Address,
|
||||
const void *Decoder);
|
||||
|
||||
namespace llvm {
|
||||
extern Target TheMipselTarget, TheMipsTarget, TheMips64Target,
|
||||
TheMips64elTarget;
|
||||
@ -1609,3 +1613,23 @@ static DecodeStatus DecodeRegListOperand(MCInst &Inst,
|
||||
|
||||
return MCDisassembler::Success;
|
||||
}
|
||||
|
||||
static DecodeStatus DecodeRegListOperand16(MCInst &Inst, unsigned Insn,
|
||||
uint64_t Address,
|
||||
const void *Decoder) {
|
||||
unsigned Regs[] = {Mips::S0, Mips::S1, Mips::S2, Mips::S3};
|
||||
unsigned RegNum;
|
||||
|
||||
unsigned RegLst = fieldFromInstruction(Insn, 4, 2);
|
||||
// Empty register lists are not allowed.
|
||||
if (RegLst == 0)
|
||||
return MCDisassembler::Fail;
|
||||
|
||||
RegNum = RegLst & 0x3;
|
||||
for (unsigned i = 0; i < RegNum - 1; i++)
|
||||
Inst.addOperand(MCOperand::CreateReg(Regs[i]));
|
||||
|
||||
Inst.addOperand(MCOperand::CreateReg(Mips::RA));
|
||||
|
||||
return MCDisassembler::Success;
|
||||
}
|
||||
|
@ -233,6 +233,8 @@ printMemOperand(const MCInst *MI, int opNum, raw_ostream &O) {
|
||||
break;
|
||||
case Mips::SWM32_MM:
|
||||
case Mips::LWM32_MM:
|
||||
case Mips::SWM16_MM:
|
||||
case Mips::LWM16_MM:
|
||||
opNum = MI->getNumOperands() - 2;
|
||||
break;
|
||||
}
|
||||
|
@ -699,6 +699,30 @@ getMemEncodingMMImm12(const MCInst &MI, unsigned OpNo,
|
||||
return (OffBits & 0x0FFF) | RegBits;
|
||||
}
|
||||
|
||||
unsigned MipsMCCodeEmitter::
|
||||
getMemEncodingMMImm4sp(const MCInst &MI, unsigned OpNo,
|
||||
SmallVectorImpl<MCFixup> &Fixups,
|
||||
const MCSubtargetInfo &STI) const {
|
||||
// opNum can be invalid if instruction had reglist as operand
|
||||
// MemOperand is always last operand of instruction (base + offset)
|
||||
switch (MI.getOpcode()) {
|
||||
default:
|
||||
break;
|
||||
case Mips::SWM16_MM:
|
||||
case Mips::LWM16_MM:
|
||||
OpNo = MI.getNumOperands() - 2;
|
||||
break;
|
||||
}
|
||||
|
||||
// Offset is encoded in bits 4-0.
|
||||
assert(MI.getOperand(OpNo).isReg());
|
||||
// Base register is always SP - thus it is not encoded.
|
||||
assert(MI.getOperand(OpNo+1).isImm());
|
||||
unsigned OffBits = getMachineOpValue(MI, MI.getOperand(OpNo+1), Fixups, STI);
|
||||
|
||||
return ((OffBits >> 2) & 0x0F);
|
||||
}
|
||||
|
||||
unsigned
|
||||
MipsMCCodeEmitter::getSizeExtEncoding(const MCInst &MI, unsigned OpNo,
|
||||
SmallVectorImpl<MCFixup> &Fixups,
|
||||
@ -830,4 +854,11 @@ MipsMCCodeEmitter::getRegisterListOpValue(const MCInst &MI, unsigned OpNo,
|
||||
return res;
|
||||
}
|
||||
|
||||
unsigned
|
||||
MipsMCCodeEmitter::getRegisterListOpValue16(const MCInst &MI, unsigned OpNo,
|
||||
SmallVectorImpl<MCFixup> &Fixups,
|
||||
const MCSubtargetInfo &STI) const {
|
||||
return (MI.getNumOperands() - 4);
|
||||
}
|
||||
|
||||
#include "MipsGenMCCodeEmitter.inc"
|
||||
|
@ -154,6 +154,9 @@ public:
|
||||
unsigned getMemEncodingMMImm12(const MCInst &MI, unsigned OpNo,
|
||||
SmallVectorImpl<MCFixup> &Fixups,
|
||||
const MCSubtargetInfo &STI) const;
|
||||
unsigned getMemEncodingMMImm4sp(const MCInst &MI, unsigned OpNo,
|
||||
SmallVectorImpl<MCFixup> &Fixups,
|
||||
const MCSubtargetInfo &STI) const;
|
||||
unsigned getSizeExtEncoding(const MCInst &MI, unsigned OpNo,
|
||||
SmallVectorImpl<MCFixup> &Fixups,
|
||||
const MCSubtargetInfo &STI) const;
|
||||
@ -187,6 +190,10 @@ public:
|
||||
unsigned getRegisterListOpValue(const MCInst &MI, unsigned OpNo,
|
||||
SmallVectorImpl<MCFixup> &Fixups,
|
||||
const MCSubtargetInfo &STI) const;
|
||||
|
||||
unsigned getRegisterListOpValue16(const MCInst &MI, unsigned OpNo,
|
||||
SmallVectorImpl<MCFixup> &Fixups,
|
||||
const MCSubtargetInfo &STI) const;
|
||||
}; // class MipsMCCodeEmitter
|
||||
} // namespace llvm.
|
||||
|
||||
|
@ -838,3 +838,15 @@ class LWM_FM_MM<bits<4> funct> : MMArch {
|
||||
let Inst{15-12} = funct;
|
||||
let Inst{11-0} = addr{11-0};
|
||||
}
|
||||
|
||||
class LWM_FM_MM16<bits<4> funct> : MMArch {
|
||||
bits<2> rt;
|
||||
bits<4> addr;
|
||||
|
||||
bits<16> Inst;
|
||||
|
||||
let Inst{15-10} = 0x11;
|
||||
let Inst{9-6} = funct;
|
||||
let Inst{5-4} = rt;
|
||||
let Inst{3-0} = addr;
|
||||
}
|
||||
|
@ -86,6 +86,22 @@ def mem_mm_12 : Operand<i32> {
|
||||
let OperandType = "OPERAND_MEMORY";
|
||||
}
|
||||
|
||||
def MipsMemUimm4AsmOperand : AsmOperandClass {
|
||||
let Name = "MemOffsetUimm4";
|
||||
let SuperClasses = [MipsMemAsmOperand];
|
||||
let RenderMethod = "addMemOperands";
|
||||
let ParserMethod = "parseMemOperand";
|
||||
let PredicateMethod = "isMemWithUimmOffsetSP<6>";
|
||||
}
|
||||
|
||||
def mem_mm_4sp : Operand<i32> {
|
||||
let PrintMethod = "printMemOperand";
|
||||
let MIOperandInfo = (ops GPR32, uimm8);
|
||||
let EncoderMethod = "getMemEncodingMMImm4sp";
|
||||
let ParserMatchClass = MipsMemUimm4AsmOperand;
|
||||
let OperandType = "OPERAND_MEMORY";
|
||||
}
|
||||
|
||||
def jmptarget_mm : Operand<OtherVT> {
|
||||
let EncoderMethod = "getJumpTargetOpValueMM";
|
||||
}
|
||||
@ -339,6 +355,20 @@ def reglist : Operand<i32> {
|
||||
let DecoderMethod = "DecodeRegListOperand";
|
||||
}
|
||||
|
||||
def RegList16AsmOperand : AsmOperandClass {
|
||||
let Name = "RegList16";
|
||||
let ParserMethod = "parseRegisterList";
|
||||
let PredicateMethod = "isRegList16";
|
||||
let RenderMethod = "addRegListOperands";
|
||||
}
|
||||
|
||||
def reglist16 : Operand<i32> {
|
||||
let EncoderMethod = "getRegisterListOpValue16";
|
||||
let DecoderMethod = "DecodeRegListOperand16";
|
||||
let PrintMethod = "printRegisterList";
|
||||
let ParserMatchClass = RegList16AsmOperand;
|
||||
}
|
||||
|
||||
class StoreMultMM<string opstr,
|
||||
InstrItinClass Itin = NoItinerary, ComplexPattern Addr = addr> :
|
||||
InstSE<(outs), (ins reglist:$rt, mem_mm_12:$addr),
|
||||
@ -355,6 +385,22 @@ class LoadMultMM<string opstr,
|
||||
let mayLoad = 1;
|
||||
}
|
||||
|
||||
class StoreMultMM16<string opstr,
|
||||
InstrItinClass Itin = NoItinerary,
|
||||
ComplexPattern Addr = addr> :
|
||||
MicroMipsInst16<(outs), (ins reglist16:$rt, mem_mm_4sp:$addr),
|
||||
!strconcat(opstr, "\t$rt, $addr"), [], Itin, FrmI> {
|
||||
let mayStore = 1;
|
||||
}
|
||||
|
||||
class LoadMultMM16<string opstr,
|
||||
InstrItinClass Itin = NoItinerary,
|
||||
ComplexPattern Addr = addr> :
|
||||
MicroMipsInst16<(outs reglist16:$rt), (ins mem_mm_4sp:$addr),
|
||||
!strconcat(opstr, "\t$rt, $addr"), [], Itin, FrmI> {
|
||||
let mayLoad = 1;
|
||||
}
|
||||
|
||||
def ADDU16_MM : ArithRMM16<"addu16", GPRMM16Opnd, 1, II_ADDU, add>,
|
||||
ARITH_FM_MM16<0>;
|
||||
def SUBU16_MM : ArithRMM16<"subu16", GPRMM16Opnd, 0, II_SUBU, sub>,
|
||||
@ -504,6 +550,8 @@ let DecoderNamespace = "MicroMips", Predicates = [InMicroMips] in {
|
||||
/// Load and Store Instructions - multiple
|
||||
def SWM32_MM : StoreMultMM<"swm32">, LWM_FM_MM<0xd>;
|
||||
def LWM32_MM : LoadMultMM<"lwm32">, LWM_FM_MM<0x5>;
|
||||
def SWM16_MM : StoreMultMM16<"swm16">, LWM_FM_MM16<0x5>;
|
||||
def LWM16_MM : LoadMultMM16<"lwm16">, LWM_FM_MM16<0x4>;
|
||||
|
||||
/// Move Conditional
|
||||
def MOVZ_I_MM : MMRel, CMov_I_I_FT<"movz", GPR32Opnd, GPR32Opnd,
|
||||
|
@ -22,6 +22,15 @@
|
||||
li16 $4, -2 # CHECK: :[[@LINE]]:{{[0-9]+}}: error: immediate operand value out of range
|
||||
addiur2 $9, $7, -1 # CHECK: :[[@LINE]]:{{[0-9]+}}: error: invalid operand for instruction
|
||||
addiur2 $6, $7, 10 # CHECK: :[[@LINE]]:{{[0-9]+}}: error: immediate operand value out of range
|
||||
lwm16 $5, $6, $ra, 8($sp) # CHECK: :[[@LINE]]:{{[0-9]+}}: error: $16 or $31 expected
|
||||
lwm16 $16, $19, $ra, 8($sp) # CHECK: :[[@LINE]]:{{[0-9]+}}: error: consecutive register numbers expected
|
||||
lwm16 $16-$25, $ra, 8($sp) # CHECK: :[[@LINE]]:{{[0-9]+}}: error: invalid register operand
|
||||
lwm16 $16, 8($sp) # CHECK: :[[@LINE]]:{{[0-9]+}}: error: invalid operand for instruction
|
||||
lwm16 $16, $17, 8($sp) # CHECK: :[[@LINE]]:{{[0-9]+}}: error: invalid operand for instruction
|
||||
lwm16 $16-$20, 8($sp) # CHECK: :[[@LINE]]:{{[0-9]+}}: error: invalid operand for instruction
|
||||
swm16 $5, $6, $ra, 8($sp) # CHECK: :[[@LINE]]:{{[0-9]+}}: error: $16 or $31 expected
|
||||
swm16 $16, $19, $ra, 8($sp) # CHECK: :[[@LINE]]:{{[0-9]+}}: error: consecutive register numbers expected
|
||||
swm16 $16-$25, $ra, 8($sp) # CHECK: :[[@LINE]]:{{[0-9]+}}: error: invalid register operand
|
||||
lwm32 $5, $6, 8($4) # CHECK: :[[@LINE]]:{{[0-9]+}}: error: $16 or $31 expected
|
||||
lwm32 $16, $19, 8($4) # CHECK: :[[@LINE]]:{{[0-9]+}}: error: consecutive register numbers expected
|
||||
lwm32 $16-$25, 8($4) # CHECK: :[[@LINE]]:{{[0-9]+}}: error: invalid register operand
|
||||
|
@ -29,6 +29,8 @@
|
||||
# CHECK-EL: lwm32 $16, $17, $18, $19, $20, $21, $22, $23, $fp, $ra, 8($4) # encoding: [0x24,0x23,0x08,0x50]
|
||||
# CHECK-EL: swm32 $16, $17, 8($4) # encoding: [0x44,0x20,0x08,0xd0]
|
||||
# CHECK-EL: swm32 $16, $17, $18, $19, 8($4) # encoding: [0x84,0x20,0x08,0xd0]
|
||||
# CHECK-EL: lwm16 $16, $17, $ra, 8($sp) # encoding: [0x12,0x45]
|
||||
# CHECK-EL: swm16 $16, $17, $ra, 8($sp) # encoding: [0x52,0x45]
|
||||
#------------------------------------------------------------------------------
|
||||
# Big endian
|
||||
#------------------------------------------------------------------------------
|
||||
@ -52,6 +54,8 @@
|
||||
# CHECK-EB: lwm32 $16, $17, $18, $19, $20, $21, $22, $23, $fp, $ra, 8($4) # encoding: [0x23,0x24,0x50,0x08]
|
||||
# CHECK-EB: swm32 $16, $17, 8($4) # encoding: [0x20,0x44,0xd0,0x08]
|
||||
# CHECK-EB: swm32 $16, $17, $18, $19, 8($4) # encoding: [0x20,0x84,0xd0,0x08]
|
||||
# CHECK-EB: lwm16 $16, $17, $ra, 8($sp) # encoding: [0x45,0x12]
|
||||
# CHECK-EB: swm16 $16, $17, $ra, 8($sp) # encoding: [0x45,0x52]
|
||||
lb $5, 8($4)
|
||||
lbu $6, 8($4)
|
||||
lh $2, 8($4)
|
||||
@ -72,3 +76,5 @@
|
||||
lwm32 $16-$23, $30 - $31, 8($4)
|
||||
swm32 $16, $17, 8($4)
|
||||
swm32 $16 - $19, 8($4)
|
||||
lwm16 $16, $17, $ra, 8($sp)
|
||||
swm16 $16, $17, $ra, 8($sp)
|
||||
|
Loading…
Reference in New Issue
Block a user