Index: lib/Target/Mips/AsmParser/MipsAsmParser.cpp =================================================================== --- lib/Target/Mips/AsmParser/MipsAsmParser.cpp +++ lib/Target/Mips/AsmParser/MipsAsmParser.cpp @@ -953,6 +953,9 @@ bool isConstantImm() const { return isImm() && dyn_cast(getImm()); } + template bool isSImm() const { + return isImm() && isConstantImm() && isInt(getConstantImm()); + } template bool isUImm() const { return isImm() && isConstantImm() && isUInt(getConstantImm()); } Index: lib/Target/Mips/MicroMipsDSPInstrFormats.td =================================================================== --- lib/Target/Mips/MicroMipsDSPInstrFormats.td +++ lib/Target/Mips/MicroMipsDSPInstrFormats.td @@ -16,6 +16,12 @@ let DecoderNamespace = "MicroMips"; } +class MMDSPInstAlias + : InstAlias, PredicateControl { + let InsnPredicates = [HasDSP]; + let AdditionalPredicates = [InMicroMips]; +} + class POOL32A_3R_FMT op> : MMDSPInst { bits<5> rd; bits<5> rs; @@ -102,3 +108,38 @@ let Inst{10} = 0b0; let Inst{9-0} = op; } + +class POOL32A_4B0SHIFT6AC4B0_FMT op> : MMDSPInst { + bits<6> shift; + bits<2> ac; + + let Inst{31-26} = 0b000000; + let Inst{25-22} = 0b0000; + let Inst{21-16} = shift; + let Inst{15-14} = ac; + let Inst{13-10} = 0b0000; + let Inst{9-0} = op; +} + +class POOL32A_5B01RAC_FMT op> : MMDSPInst { + bits<5> rs; + bits<2> ac; + + let Inst{31-26} = 0b000000; + let Inst{25-21} = 0b00000; + let Inst{20-16} = rs; + let Inst{15-14} = ac; + let Inst{13-6} = op; + let Inst{5-0} = 0b111100; +} + +class POOL32A_1RMASK7_FMT op> : MMDSPInst { + bits<5> rt; + bits<7> mask; + + let Inst{31-26} = 0b000000; + let Inst{25-21} = rt; + let Inst{20-14} = mask; + let Inst{13-6} = op; + let Inst{5-0} = 0b111100; +} Index: lib/Target/Mips/MicroMipsDSPInstrInfo.td =================================================================== --- lib/Target/Mips/MicroMipsDSPInstrInfo.td +++ lib/Target/Mips/MicroMipsDSPInstrInfo.td @@ -11,6 +11,13 @@ // //===----------------------------------------------------------------------===// +// Instruction operand defs. +def uimm7 : Operand { + let PrintMethod = "printUnsignedImm"; + let ParserMatchClass = MipsUImmAsmOperand<7>; + let OperandType = "OPERAND_IMMEDIATE"; +} + // Instruction encoding. class ADDQ_PH_MM_ENC : POOL32A_3R_FMT<"addq.ph", 0b00000001101>; class ADDQ_S_PH_MM_ENC : POOL32A_3R_FMT<"addq_s.ph", 0b10000001101>; @@ -55,6 +62,12 @@ class SHLL_S_W_MM_ENC : POOL32A_2RSA5B0_FMT<"shll_s.w", 0b1111110101>; class SHRA_QB_MMR2_ENC : POOL32A_2RSA3_FMT<"shra.qb", 0b0000111>; class SHRA_R_QB_MMR2_ENC : POOL32A_2RSA3_FMT<"shra_r.qb", 0b1000111>; +class PACKRL_PH_MM_ENC : POOL32A_3RB0_FMT<"packrl.ph", 0b0110101101>; +class PICK_PH_MM_ENC : POOL32A_3RB0_FMT<"pick.ph", 0b1000101101>; +class PICK_QB_MM_ENC : POOL32A_3RB0_FMT<"pick.qb", 0b0111101101>; +class SHILO_MM_ENC : POOL32A_4B0SHIFT6AC4B0_FMT<"shilo", 0b0000011101>; +class SHILOV_MM_ENC : POOL32A_5B01RAC_FMT<"shilov", 0b01001001>; +class WRDSP_MM_ENC : POOL32A_1RMASK7_FMT<"wrdsp", 0b01011001>; // Instruction desc. class ABSQ_S_PH_MM_R2_DESC_BASE, Defs<[DSPOutFlag22]>; +class WRDSP_MM_DESC { + dag OutOperandList = (outs); + dag InOperandList = (ins GPR32Opnd:$rt, uimm7:$mask); + string AsmString = !strconcat("wrdsp", "\t$rt, $mask"); + list Pattern = [(int_mips_wrdsp GPR32Opnd:$rt, immZExt7:$mask)]; + InstrItinClass Itinerary = NoItinerary; +} + // Instruction defs. // microMIPS DSP Rev 1 def ADDQ_PH_MM : DspMMRel, ADDQ_PH_MM_ENC, ADDQ_PH_DESC; @@ -148,6 +169,12 @@ def SHLLV_QB_MM : DspMMRel, SHLLV_QB_MM_ENC, SHLLV_QB_MM_DESC; def SHLLV_S_W_MM : DspMMRel, SHLLV_S_W_MM_ENC, SHLLV_S_W_MM_DESC; def SHLL_S_W_MM : DspMMRel, SHLL_S_W_MM_ENC, SHLL_S_W_MM_DESC; +def PACKRL_PH_MM : DspMMRel, PACKRL_PH_MM_ENC, PACKRL_PH_DESC; +def PICK_PH_MM : DspMMRel, PICK_PH_MM_ENC, PICK_PH_DESC; +def PICK_QB_MM : DspMMRel, PICK_QB_MM_ENC, PICK_QB_DESC; +def SHILO_MM : DspMMRel, SHILO_MM_ENC, SHILO_DESC; +def SHILOV_MM : DspMMRel, SHILOV_MM_ENC, SHILOV_DESC; +def WRDSP_MM : DspMMRel, WRDSP_MM_ENC, WRDSP_MM_DESC; // microMIPS DSP Rev 2 def ABSQ_S_QB_MMR2 : DspMMRel, ABSQ_S_QB_MMR2_ENC, ABSQ_S_QB_MMR2_DESC, ISA_DSPR2; @@ -168,3 +195,6 @@ def SHRA_QB_MMR2 : DspMMRel, SHRA_QB_MMR2_ENC, SHRA_QB_MMR2_DESC, ISA_DSPR2; def SHRA_R_QB_MMR2 : DspMMRel, SHRA_R_QB_MMR2_ENC, SHRA_R_QB_MMR2_DESC, ISA_DSPR2; + +// Instruction alias. +def : MMDSPInstAlias<"wrdsp $rt", (WRDSP_MM GPR32Opnd:$rt, 0x1F), 1>; Index: lib/Target/Mips/MipsDSPInstrInfo.td =================================================================== --- lib/Target/Mips/MipsDSPInstrInfo.td +++ lib/Target/Mips/MipsDSPInstrInfo.td @@ -11,11 +11,25 @@ // //===----------------------------------------------------------------------===// +// Instruction operand defs. +class MipsSImmAsmOperand : AsmOperandClass { + let Name = "SImm" # Bits; + let RenderMethod = "addImmOperands"; + let ParserMethod = "parseImm"; + let PredicateMethod = "isSImm<" # Bits # ">"; +} + +def simm6 : Operand { + let ParserMatchClass = MipsSImmAsmOperand<6>; + let OperandType = "OPERAND_IMMEDIATE"; +} + // ImmLeaf def immZExt1 : ImmLeaf(Imm);}]>; def immZExt2 : ImmLeaf(Imm);}]>; def immZExt3 : ImmLeaf(Imm);}]>; def immZExt4 : ImmLeaf(Imm);}]>; +def immZExt7 : ImmLeaf(Imm);}]>; def immZExt8 : ImmLeaf(Imm);}]>; def immZExt10 : ImmLeaf(Imm);}]>; def immSExt6 : ImmLeaf(Imm);}]>; @@ -295,6 +309,7 @@ string AsmString = !strconcat(instr_asm, "\t$rd, $rs, $rt"); list Pattern = [(set ROD:$rd, (OpNode ROS:$rs, ROT:$rt))]; InstrItinClass Itinerary = itin; + string BaseOpcode = instr_asm; } class PRECR_SRA_PH_W_DESC_BASE { dag OutOperandList = (outs ACC64DSPOpnd:$ac); - dag InOperandList = (ins simm16:$shift, ACC64DSPOpnd:$acin); + dag InOperandList = (ins simm6:$shift, ACC64DSPOpnd:$acin); string AsmString = !strconcat(instr_asm, "\t$ac, $shift"); list Pattern = [(set ACC64DSPOpnd:$ac, (OpNode immSExt6:$shift, ACC64DSPOpnd:$acin))]; string Constraints = "$acin = $ac"; + string BaseOpcode = instr_asm; } class SHILO_R2_DESC_BASE { @@ -414,6 +430,7 @@ list Pattern = [(set ACC64DSPOpnd:$ac, (OpNode GPR32Opnd:$rs, ACC64DSPOpnd:$acin))]; string Constraints = "$acin = $ac"; + string BaseOpcode = instr_asm; } class MTHLIP_DESC_BASE { @@ -437,10 +454,11 @@ class WRDSP_DESC_BASE { dag OutOperandList = (outs); - dag InOperandList = (ins GPR32Opnd:$rs, uimm16:$mask); + dag InOperandList = (ins GPR32Opnd:$rs, uimm10:$mask); string AsmString = !strconcat(instr_asm, "\t$rs, $mask"); list Pattern = [(OpNode GPR32Opnd:$rs, immZExt10:$mask)]; InstrItinClass Itinerary = itin; + string BaseOpcode = instr_asm; } class DPA_W_PH_DESC_BASE { @@ -1166,13 +1184,13 @@ def CMP_LT_PH : CMP_LT_PH_ENC, CMP_LT_PH_DESC; def CMP_LE_PH : CMP_LE_PH_ENC, CMP_LE_PH_DESC; def BITREV : BITREV_ENC, BITREV_DESC; -def PACKRL_PH : PACKRL_PH_ENC, PACKRL_PH_DESC; +def PACKRL_PH : DspMMRel, PACKRL_PH_ENC, PACKRL_PH_DESC; def REPL_QB : REPL_QB_ENC, REPL_QB_DESC; def REPL_PH : REPL_PH_ENC, REPL_PH_DESC; def REPLV_QB : REPLV_QB_ENC, REPLV_QB_DESC; def REPLV_PH : REPLV_PH_ENC, REPLV_PH_DESC; -def PICK_QB : PICK_QB_ENC, PICK_QB_DESC; -def PICK_PH : PICK_PH_ENC, PICK_PH_DESC; +def PICK_QB : DspMMRel, PICK_QB_ENC, PICK_QB_DESC; +def PICK_PH : DspMMRel, PICK_PH_ENC, PICK_PH_DESC; def LWX : LWX_ENC, LWX_DESC; def LHX : LHX_ENC, LHX_DESC; def LBUX : LBUX_ENC, LBUX_DESC; @@ -1190,11 +1208,13 @@ def EXTRV_RS_W : EXTRV_RS_W_ENC, EXTRV_RS_W_DESC; def EXTR_S_H : EXTR_S_H_ENC, EXTR_S_H_DESC; def EXTRV_S_H : EXTRV_S_H_ENC, EXTRV_S_H_DESC; -def SHILO : SHILO_ENC, SHILO_DESC; -def SHILOV : SHILOV_ENC, SHILOV_DESC; +def SHILO : DspMMRel, SHILO_ENC, SHILO_DESC; +def SHILOV : DspMMRel, SHILOV_ENC, SHILOV_DESC; def MTHLIP : MTHLIP_ENC, MTHLIP_DESC; def RDDSP : RDDSP_ENC, RDDSP_DESC; -def WRDSP : WRDSP_ENC, WRDSP_DESC; +let Predicates = [HasDSP, NotInMicroMips] in { + def WRDSP : WRDSP_ENC, WRDSP_DESC; +} // MIPS DSP Rev 2 let Predicates = [HasDSPR2] in { @@ -1425,3 +1445,8 @@ def : IndexedLoadPat; def : IndexedLoadPat; } + +// Instruction alias. +let Predicates = [HasDSP, NotInMicroMips] in { + def : MipsInstAlias<"wrdsp $rt", (WRDSP GPR32Opnd:$rt, 0x1F), 1>; +} Index: lib/Target/Mips/MipsInstrInfo.td =================================================================== --- lib/Target/Mips/MipsInstrInfo.td +++ lib/Target/Mips/MipsInstrInfo.td @@ -432,15 +432,16 @@ def uimm20 : Operand { } -def MipsUImm10AsmOperand : AsmOperandClass { - let Name = "UImm10"; +class MipsUImmAsmOperand : AsmOperandClass { + let Name = "UImm" # Bits; let RenderMethod = "addImmOperands"; let ParserMethod = "parseImm"; - let PredicateMethod = "isUImm<10>"; + let PredicateMethod = "isUImm<" # Bits # ">"; } def uimm10 : Operand { - let ParserMatchClass = MipsUImm10AsmOperand; + let ParserMatchClass = MipsUImmAsmOperand<10>; + let OperandType = "OPERAND_IMMEDIATE"; } def simm16_64 : Operand { Index: test/MC/Disassembler/Mips/dsp/valid-el.txt =================================================================== --- test/MC/Disassembler/Mips/dsp/valid-el.txt +++ test/MC/Disassembler/Mips/dsp/valid-el.txt @@ -7,3 +7,6 @@ 0x8a 0x51 0x54 0x7f # CHECK: lbux $10, $20($26) 0x0a 0x59 0x75 0x7f # CHECK: lhx $11, $21($27) 0x0a 0x60 0x96 0x7f # CHECK: lwx $12, $22($gp) +0xb8 0x0e 0x30 0x7c # CHECK: shilo $ac1, 3 +0xf8 0x14 0xa0 0x7c # CHECK: wrdsp $5, 2 +0xf8 0xfc 0xa0 0x7c # CHECK: wrdsp $5 Index: test/MC/Disassembler/Mips/micromips-dsp/valid.txt =================================================================== --- test/MC/Disassembler/Mips/micromips-dsp/valid.txt +++ test/MC/Disassembler/Mips/micromips-dsp/valid.txt @@ -28,3 +28,10 @@ 0x00 0x85 0x1b 0x95 # CHECK: shllv.qb $3, $4, $5 0x00 0x85 0x1b 0xd5 # CHECK: shllv_s.w $3, $4, $5 0x00 0x64 0x2b 0xf5 # CHECK: shll_s.w $3, $4, 5 +0x00 0xa4 0x19 0xad # CHECK: packrl.ph $3, $4, $5 +0x00 0xa4 0x1a 0x2d # CHECK: pick.ph $3, $4, $5 +0x00 0xa4 0x19 0xed # CHECK: pick.qb $3, $4, $5 +0x00 0x03 0x40 0x1d # CHECK: shilo $ac1, 3 +0x00 0x05 0x52 0x7c # CHECK: shilov $ac1, $5 +0x00 0xa0 0x96 0x7c # CHECK: wrdsp $5, 2 +0x00 0xa7 0xd6 0x7c # CHECK: wrdsp $5 Index: test/MC/Mips/micromips-dsp/invalid.s =================================================================== --- /dev/null +++ test/MC/Mips/micromips-dsp/invalid.s @@ -0,0 +1,7 @@ +# RUN: not llvm-mc %s -triple=mips-unknown-linux -show-encoding -mcpu=mips32r6 -mattr=micromips -mattr=+dsp 2>%t1 +# RUN: FileCheck %s < %t1 + + shilo $ac1, 64 # CHECK: :[[@LINE]]:{{[0-9]+}}: error: invalid operand for instruction + shilo $ac1, -64 # CHECK: :[[@LINE]]:{{[0-9]+}}: error: invalid operand for instruction + wrdsp $5, 128 # CHECK: :[[@LINE]]:{{[0-9]+}}: error: instruction requires a CPU feature not currently enabled + wrdsp $5, -1 # CHECK: :[[@LINE]]:{{[0-9]+}}: error: invalid operand for instruction Index: test/MC/Mips/micromips-dsp/valid.s =================================================================== --- test/MC/Mips/micromips-dsp/valid.s +++ test/MC/Mips/micromips-dsp/valid.s @@ -29,3 +29,11 @@ shllv.qb $3, $4, $5 # CHECK: shllv.qb $3, $4, $5 # encoding: [0x00,0x85,0x1b,0x95] shllv_s.w $3, $4, $5 # CHECK: shllv_s.w $3, $4, $5 # encoding: [0x00,0x85,0x1b,0xd5] shll_s.w $3, $4, 5 # CHECK: shll_s.w $3, $4, 5 # encoding: [0x00,0x64,0x2b,0xf5] + packrl.ph $3, $4, $5 # CHECK: packrl.ph $3, $4, $5 # encoding: [0x00,0xa4,0x19,0xad] + pick.ph $3, $4, $5 # CHECK: pick.ph $3, $4, $5 # encoding: [0x00,0xa4,0x1a,0x2d] + pick.qb $3, $4, $5 # CHECK: pick.qb $3, $4, $5 # encoding: [0x00,0xa4,0x19,0xed] + shilo $ac1, 3 # CHECK: shilo $ac1, 3 # encoding: [0x00,0x03,0x40,0x1d] + shilov $ac1, $5 # CHECK: shilov $ac1, $5 # encoding: [0x00,0x05,0x52,0x7c] + wrdsp $5, 2 # CHECK: wrdsp $5, 2 # encoding: [0x00,0xa0,0x96,0x7c] + wrdsp $5 # CHECK: wrdsp $5 # encoding: [0x00,0xa7,0xd6,0x7c] + wrdsp $5, 31 # CHECK: wrdsp $5 # encoding: [0x00,0xa7,0xd6,0x7c] Index: test/MC/Mips/mips-dsp-instructions.s =================================================================== --- test/MC/Mips/mips-dsp-instructions.s +++ test/MC/Mips/mips-dsp-instructions.s @@ -48,6 +48,10 @@ # CHECK: mthi $16 # encoding: [0x02,0x00,0x00,0x11] # CHECK: mtlo $17 # encoding: [0x02,0x20,0x00,0x13] +# CHECK: shilo $ac1, 3 # encoding: [0x7c,0x30,0x0e,0xb8] +# CHECK: wrdsp $5, 2 # encoding: [0x7c,0xa0,0x14,0xf8] +# CHECK: wrdsp $5 # encoding: [0x7c,0xa0,0xfc,0xf8] +# CHECK: wrdsp $5 # encoding: [0x7c,0xa0,0xfc,0xf8] precrq.qb.ph $16,$17,$18 precrq.ph.w $17,$18,$19 @@ -95,3 +99,8 @@ mflo $15 mthi $16 mtlo $17 + + shilo $ac1, 3 + wrdsp $5, 2 + wrdsp $5 + wrdsp $5, 31 Index: test/MC/Mips/mips-dsp-invalid.s =================================================================== --- /dev/null +++ test/MC/Mips/mips-dsp-invalid.s @@ -0,0 +1,7 @@ +# RUN: not llvm-mc %s -triple=mips-unknown-unknown -show-encoding -mattr=dspr2 2>%t1 +# RUN: FileCheck %s < %t1 + + shilo $ac1, 64 # CHECK: :[[@LINE]]:{{[0-9]+}}: error: invalid operand for instruction + shilo $ac1, -64 # CHECK: :[[@LINE]]:{{[0-9]+}}: error: invalid operand for instruction + wrdsp $5, 1024 # CHECK: :[[@LINE]]:{{[0-9]+}}: error: invalid operand for instruction + wrdsp $5, -1 # CHECK: :[[@LINE]]:{{[0-9]+}}: error: invalid operand for instruction