Index: lib/Target/Mips/AsmParser/MipsAsmParser.cpp =================================================================== --- lib/Target/Mips/AsmParser/MipsAsmParser.cpp +++ lib/Target/Mips/AsmParser/MipsAsmParser.cpp @@ -1055,9 +1055,11 @@ bool isConstantMemOff() const { return isMem() && isa(getMemOff()); } - template bool isMemWithSimmOffset() const { - return isMem() && isConstantMemOff() && isInt(getConstantMemOff()) - && getMemBase()->isGPRAsmReg(); + template + bool isMemWithSimmOffset() const { + return isMem() && isConstantMemOff() && + isShiftedInt(getConstantMemOff()) && + getMemBase()->isGPRAsmReg(); } template bool isMemWithSimmOffsetGPR() const { return isMem() && isConstantMemOff() && isInt(getConstantMemOff()) && @@ -3800,6 +3802,18 @@ case Match_MemGPSImm9: return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo), "expected memory with $gp and 9-bit signed offset"); + case Match_MemSImm10: + return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo), + "expected memory with 10-bit signed offset"); + case Match_MemSImm10Lsl1: + return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo), + "expected memory with 11-bit signed offset and multiple of 2"); + case Match_MemSImm10Lsl2: + return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo), + "expected memory with 12-bit signed offset and multiple of 4"); + case Match_MemSImm10Lsl3: + return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo), + "expected memory with 13-bit signed offset and multiple of 8"); } llvm_unreachable("Implement any new match types added!"); Index: lib/Target/Mips/MCTargetDesc/MipsMCCodeEmitter.h =================================================================== --- lib/Target/Mips/MCTargetDesc/MipsMCCodeEmitter.h +++ lib/Target/Mips/MCTargetDesc/MipsMCCodeEmitter.h @@ -161,6 +161,7 @@ SmallVectorImpl &Fixups, const MCSubtargetInfo &STI) const; + template unsigned getMemEncoding(const MCInst &MI, unsigned OpNo, SmallVectorImpl &Fixups, const MCSubtargetInfo &STI) const; Index: lib/Target/Mips/MCTargetDesc/MipsMCCodeEmitter.cpp =================================================================== --- lib/Target/Mips/MCTargetDesc/MipsMCCodeEmitter.cpp +++ lib/Target/Mips/MCTargetDesc/MipsMCCodeEmitter.cpp @@ -653,61 +653,20 @@ return getExprOpValue(MO.getExpr(),Fixups, STI); } -/// getMSAMemEncoding - Return binary encoding of memory operand for LD/ST -/// instructions. -unsigned -MipsMCCodeEmitter::getMSAMemEncoding(const MCInst &MI, unsigned OpNo, - SmallVectorImpl &Fixups, - const MCSubtargetInfo &STI) const { - // Base register is encoded in bits 20-16, offset is encoded in bits 15-0. - assert(MI.getOperand(OpNo).isReg()); - unsigned RegBits = getMachineOpValue(MI, MI.getOperand(OpNo),Fixups, STI) << 16; - unsigned OffBits = getMachineOpValue(MI, MI.getOperand(OpNo+1), Fixups, STI); - - // The immediate field of an LD/ST instruction is scaled which means it must - // be divided (when encoding) by the size (in bytes) of the instructions' - // data format. - // .b - 1 byte - // .h - 2 bytes - // .w - 4 bytes - // .d - 8 bytes - switch(MI.getOpcode()) - { - default: - assert (0 && "Unexpected instruction"); - break; - case Mips::LD_B: - case Mips::ST_B: - // We don't need to scale the offset in this case - break; - case Mips::LD_H: - case Mips::ST_H: - OffBits >>= 1; - break; - case Mips::LD_W: - case Mips::ST_W: - OffBits >>= 2; - break; - case Mips::LD_D: - case Mips::ST_D: - OffBits >>= 3; - break; - } - - return (OffBits & 0xFFFF) | RegBits; -} - -/// getMemEncoding - Return binary encoding of memory related operand. +/// Return binary encoding of memory related operand. /// If the offset operand requires relocation, record the relocation. -unsigned -MipsMCCodeEmitter::getMemEncoding(const MCInst &MI, unsigned OpNo, - SmallVectorImpl &Fixups, - const MCSubtargetInfo &STI) const { +template +unsigned MipsMCCodeEmitter::getMemEncoding(const MCInst &MI, unsigned OpNo, + SmallVectorImpl &Fixups, + const MCSubtargetInfo &STI) const { // Base register is encoded in bits 20-16, offset is encoded in bits 15-0. assert(MI.getOperand(OpNo).isReg()); unsigned RegBits = getMachineOpValue(MI, MI.getOperand(OpNo),Fixups, STI) << 16; unsigned OffBits = getMachineOpValue(MI, MI.getOperand(OpNo+1), Fixups, STI); + // Apply the scale factor if there is one. + OffBits >>= ShiftAmount; + return (OffBits & 0xFFFF) | RegBits; } Index: lib/Target/Mips/MipsInstrInfo.td =================================================================== --- lib/Target/Mips/MipsInstrInfo.td +++ lib/Target/Mips/MipsInstrInfo.td @@ -465,8 +465,29 @@ } def UImm16AsmOperandClass : UImmAsmOperandClass<16, [UImm16RelaxedAsmOperandClass]>; +def ConstantSImm10Lsl3AsmOperandClass : AsmOperandClass { + let Name = "SImm10Lsl3"; + let RenderMethod = "addImmOperands"; + let PredicateMethod = "isScaledSImm<10, 3>"; + let SuperClasses = [UImm16AsmOperandClass]; + let DiagnosticType = "SImm10_Lsl3"; +} +def ConstantSImm10Lsl2AsmOperandClass : AsmOperandClass { + let Name = "SImm10Lsl2"; + let RenderMethod = "addImmOperands"; + let PredicateMethod = "isScaledSImm<10, 2>"; + let SuperClasses = [ConstantSImm10Lsl3AsmOperandClass]; + let DiagnosticType = "SImm10_Lsl2"; +} +def ConstantSImm10Lsl1AsmOperandClass : AsmOperandClass { + let Name = "SImm10Lsl1"; + let RenderMethod = "addImmOperands"; + let PredicateMethod = "isScaledSImm<10, 1>"; + let SuperClasses = [ConstantSImm10Lsl2AsmOperandClass]; + let DiagnosticType = "SImm10_Lsl1"; +} def ConstantUImm10AsmOperandClass - : ConstantUImmAsmOperandClass<10, [UImm16AsmOperandClass]>; + : ConstantUImmAsmOperandClass<10, [ConstantSImm10Lsl1AsmOperandClass]>; def ConstantSImm10AsmOperandClass : ConstantSImmAsmOperandClass<10, [ConstantUImm10AsmOperandClass]>; def ConstantSImm9AsmOperandClass @@ -577,7 +598,6 @@ def imm64: Operand; -def simm10 : Operand; def simm11 : Operand; def simm16 : Operand { @@ -743,13 +763,20 @@ } // Signed operands -foreach I = {4, 5, 6, 9} in +foreach I = {4, 5, 6, 9, 10} in def simm # I : Operand { let DecoderMethod = "DecodeSImmWithOffsetAndScale<" # I # ">"; let ParserMatchClass = !cast("ConstantSImm" # I # "AsmOperandClass"); } +foreach I = {1, 2, 3} in + def simm10_lsl # I : Operand { + let DecoderMethod = "DecodeSImmWithOffsetAndScale<10, " # I # ">"; + let ParserMatchClass = + !cast("ConstantSImm10Lsl" # I # "AsmOperandClass"); + } + foreach I = {10} in def simm # I # _64 : Operand { let DecoderMethod = "DecodeSImmWithOffsetAndScale<" # I # ">"; @@ -793,6 +820,25 @@ let DiagnosticType = "MemSImm9"; } +def MipsMemSimm10AsmOperand : AsmOperandClass { + let Name = "MemOffsetSimm10"; + let SuperClasses = [MipsMemAsmOperand]; + let RenderMethod = "addMemOperands"; + let ParserMethod = "parseMemOperand"; + let PredicateMethod = "isMemWithSimmOffset<10>"; + let DiagnosticType = "MemSImm10"; +} + +foreach I = {1, 2, 3} in + def MipsMemSimm10Lsl # I # AsmOperand : AsmOperandClass { + let Name = "MemOffsetSimm10_" # I; + let SuperClasses = [MipsMemAsmOperand]; + let RenderMethod = "addMemOperands"; + let ParserMethod = "parseMemOperand"; + let PredicateMethod = "isMemWithSimmOffset<10, " # I # ">"; + let DiagnosticType = "MemSImm10Lsl" # I; + } + def MipsMemSimm9GPRAsmOperand : AsmOperandClass { let Name = "MemOffsetSimm9GPR"; let SuperClasses = [MipsMemAsmOperand]; @@ -855,6 +901,20 @@ let ParserMatchClass = MipsMemSimm9AsmOperand; } +def mem_simm10 : mem_generic { + let MIOperandInfo = (ops ptr_rc, simm10); + let EncoderMethod = "getMemEncoding"; + let ParserMatchClass = MipsMemSimm10AsmOperand; +} + +foreach I = {1, 2, 3} in + def mem_simm10_lsl # I : mem_generic { + let MIOperandInfo = (ops ptr_rc, !cast("simm10_lsl" # I)); + let EncoderMethod = "getMemEncoding<" # I # ">"; + let ParserMatchClass = + !cast("MipsMemSimm10Lsl" # I # "AsmOperand"); + } + def mem_simm9gpr : mem_generic { let MIOperandInfo = (ops ptr_rc, simm9); let EncoderMethod = "getMemEncoding"; Index: lib/Target/Mips/MipsMSAInstrInfo.td =================================================================== --- lib/Target/Mips/MipsMSAInstrInfo.td +++ lib/Target/Mips/MipsMSAInstrInfo.td @@ -2297,7 +2297,7 @@ class LD_DESC_BASE { dag OutOperandList = (outs ROWD:$wd); dag InOperandList = (ins MemOpnd:$addr); @@ -2307,10 +2307,10 @@ string DecoderMethod = "DecodeMSA128Mem"; } -class LD_B_DESC : LD_DESC_BASE<"ld.b", load, v16i8, MSA128BOpnd>; -class LD_H_DESC : LD_DESC_BASE<"ld.h", load, v8i16, MSA128HOpnd>; -class LD_W_DESC : LD_DESC_BASE<"ld.w", load, v4i32, MSA128WOpnd>; -class LD_D_DESC : LD_DESC_BASE<"ld.d", load, v2i64, MSA128DOpnd>; +class LD_B_DESC : LD_DESC_BASE<"ld.b", load, v16i8, MSA128BOpnd, mem_simm10>; +class LD_H_DESC : LD_DESC_BASE<"ld.h", load, v8i16, MSA128HOpnd, mem_simm10_lsl1>; +class LD_W_DESC : LD_DESC_BASE<"ld.w", load, v4i32, MSA128WOpnd, mem_simm10_lsl2>; +class LD_D_DESC : LD_DESC_BASE<"ld.d", load, v2i64, MSA128DOpnd, mem_simm10_lsl3>; class LDI_B_DESC : MSA_I10_LDI_DESC_BASE<"ldi.b", MSA128BOpnd>; class LDI_H_DESC : MSA_I10_LDI_DESC_BASE<"ldi.h", MSA128HOpnd>; @@ -2631,7 +2631,7 @@ class ST_DESC_BASE { dag OutOperandList = (outs); dag InOperandList = (ins ROWD:$wd, MemOpnd:$addr); @@ -2641,10 +2641,10 @@ string DecoderMethod = "DecodeMSA128Mem"; } -class ST_B_DESC : ST_DESC_BASE<"st.b", store, v16i8, MSA128BOpnd>; -class ST_H_DESC : ST_DESC_BASE<"st.h", store, v8i16, MSA128HOpnd>; -class ST_W_DESC : ST_DESC_BASE<"st.w", store, v4i32, MSA128WOpnd>; -class ST_D_DESC : ST_DESC_BASE<"st.d", store, v2i64, MSA128DOpnd>; +class ST_B_DESC : ST_DESC_BASE<"st.b", store, v16i8, MSA128BOpnd, mem_simm10>; +class ST_H_DESC : ST_DESC_BASE<"st.h", store, v8i16, MSA128HOpnd, mem_simm10_lsl1>; +class ST_W_DESC : ST_DESC_BASE<"st.w", store, v4i32, MSA128WOpnd, mem_simm10_lsl2>; +class ST_D_DESC : ST_DESC_BASE<"st.d", store, v2i64, MSA128DOpnd, mem_simm10_lsl3>; class SUBS_S_B_DESC : MSA_3R_DESC_BASE<"subs_s.b", int_mips_subs_s_b, MSA128BOpnd>; Index: test/MC/Mips/msa/invalid.s =================================================================== --- test/MC/Mips/msa/invalid.s +++ test/MC/Mips/msa/invalid.s @@ -135,6 +135,14 @@ insve.h $w24[2], $w2[1] # CHECK: :[[@LINE]]:26: error: expected '0' insve.w $w0[2], $w13[1] # CHECK: :[[@LINE]]:26: error: expected '0' insve.d $w3[0], $w18[1] # CHECK: :[[@LINE]]:26: error: expected '0' + ld.b $w0, -513($2) # CHECK: :[[@LINE]]:15: error: expected memory with 10-bit signed offset + ld.b $w0, 512($2) # CHECK: :[[@LINE]]:15: error: expected memory with 10-bit signed offset + ld.h $w0, -1025($2) # CHECK: :[[@LINE]]:15: error: expected memory with 11-bit signed offset and multiple of 2 + ld.h $w0, 1024($2) # CHECK: :[[@LINE]]:15: error: expected memory with 11-bit signed offset and multiple of 2 + ld.w $w0, -2049($2) # CHECK: :[[@LINE]]:15: error: expected memory with 12-bit signed offset and multiple of 4 + ld.w $w0, 2048($2) # CHECK: :[[@LINE]]:15: error: expected memory with 12-bit signed offset and multiple of 4 + ld.d $w0, -4097($2) # CHECK: :[[@LINE]]:15: error: expected memory with 13-bit signed offset and multiple of 8 + ld.d $w0, 4096($2) # CHECK: :[[@LINE]]:15: error: expected memory with 13-bit signed offset and multiple of 8 ldi.b $w1, -1025 # CHECK: :[[@LINE]]:16: error: expected 10-bit signed immediate ldi.b $w1, 1024 # CHECK: :[[@LINE]]:16: error: expected 10-bit signed immediate ldi.h $w1, -1025 # CHECK: :[[@LINE]]:16: error: expected 10-bit signed immediate @@ -259,6 +267,14 @@ srlri.w $w18, $w3, 32 # CHECK: :[[@LINE]]:24: error: expected 5-bit unsigned immediate srlri.d $w18, $w3, -1 # CHECK: :[[@LINE]]:24: error: expected 6-bit unsigned immediate srlri.d $w18, $w3, 64 # CHECK: :[[@LINE]]:24: error: expected 6-bit unsigned immediate + st.b $w0, -513($2) # CHECK: :[[@LINE]]:15: error: expected memory with 10-bit signed offset + st.b $w0, 512($2) # CHECK: :[[@LINE]]:15: error: expected memory with 10-bit signed offset + st.h $w0, -1025($2) # CHECK: :[[@LINE]]:15: error: expected memory with 11-bit signed offset and multiple of 2 + st.h $w0, 1024($2) # CHECK: :[[@LINE]]:15: error: expected memory with 11-bit signed offset and multiple of 2 + st.w $w0, -2049($2) # CHECK: :[[@LINE]]:15: error: expected memory with 12-bit signed offset and multiple of 4 + st.w $w0, 2048($2) # CHECK: :[[@LINE]]:15: error: expected memory with 12-bit signed offset and multiple of 4 + st.d $w0, -4097($2) # CHECK: :[[@LINE]]:15: error: expected memory with 13-bit signed offset and multiple of 8 + st.d $w0, 4096($2) # CHECK: :[[@LINE]]:15: error: expected memory with 13-bit signed offset and multiple of 8 subvi.b $w1, $w2, -1 # CHECK: :[[@LINE]]:23: error: expected 5-bit unsigned immediate subvi.b $w1, $w2, 32 # CHECK: :[[@LINE]]:23: error: expected 5-bit unsigned immediate subvi.h $w1, $w2, -1 # CHECK: :[[@LINE]]:23: error: expected 5-bit unsigned immediate Index: test/MC/Mips/msa/test_mi10.s =================================================================== --- test/MC/Mips/msa/test_mi10.s +++ test/MC/Mips/msa/test_mi10.s @@ -1,55 +1,28 @@ # RUN: llvm-mc %s -arch=mips -mcpu=mips32r2 -mattr=+msa -show-encoding | FileCheck %s # -# CHECK: ld.b $w0, -512($1) # encoding: [0x7a,0x00,0x08,0x20] -# CHECK: ld.b $w1, 0($2) # encoding: [0x78,0x00,0x10,0x60] -# CHECK: ld.b $w2, 511($3) # encoding: [0x79,0xff,0x18,0xa0] + ld.b $w0, -512($1) # CHECK: ld.b $w0, -512($1) # encoding: [0x7a,0x00,0x08,0x20] + ld.b $w1, 0($2) # CHECK: ld.b $w1, 0($2) # encoding: [0x78,0x00,0x10,0x60] + ld.b $w2, 511($3) # CHECK: ld.b $w2, 511($3) # encoding: [0x79,0xff,0x18,0xa0] -# CHECK: ld.h $w3, -1024($4) # encoding: [0x7a,0x00,0x20,0xe1] -# CHECK: ld.h $w4, -512($5) # encoding: [0x7b,0x00,0x29,0x21] -# CHECK: ld.h $w5, 0($6) # encoding: [0x78,0x00,0x31,0x61] -# CHECK: ld.h $w6, 512($7) # encoding: [0x79,0x00,0x39,0xa1] -# CHECK: ld.h $w7, 1022($8) # encoding: [0x79,0xff,0x41,0xe1] + ld.h $w3, -1024($4) # CHECK: ld.h $w3, -1024($4) # encoding: [0x7a,0x00,0x20,0xe1] + ld.h $w4, -512($5) # CHECK: ld.h $w4, -512($5) # encoding: [0x7b,0x00,0x29,0x21] + ld.h $w5, 0($6) # CHECK: ld.h $w5, 0($6) # encoding: [0x78,0x00,0x31,0x61] + ld.h $w6, 512($7) # CHECK: ld.h $w6, 512($7) # encoding: [0x79,0x00,0x39,0xa1] + ld.h $w7, 1022($8) # CHECK: ld.h $w7, 1022($8) # encoding: [0x79,0xff,0x41,0xe1] -# CHECK: ld.w $w8, -2048($9) # encoding: [0x7a,0x00,0x4a,0x22] -# CHECK: ld.w $w9, -1024($10) # encoding: [0x7b,0x00,0x52,0x62] -# CHECK: ld.w $w10, -512($11) # encoding: [0x7b,0x80,0x5a,0xa2] -# CHECK: ld.w $w11, 512($12) # encoding: [0x78,0x80,0x62,0xe2] -# CHECK: ld.w $w12, 1024($13) # encoding: [0x79,0x00,0x6b,0x22] -# CHECK: ld.w $w13, 2044($14) # encoding: [0x79,0xff,0x73,0x62] + ld.w $w8, -2048($9) # CHECK: ld.w $w8, -2048($9) # encoding: [0x7a,0x00,0x4a,0x22] + ld.w $w9, -1024($10) # CHECK: ld.w $w9, -1024($10) # encoding: [0x7b,0x00,0x52,0x62] + ld.w $w10, -512($11) # CHECK: ld.w $w10, -512($11) # encoding: [0x7b,0x80,0x5a,0xa2] + ld.w $w11, 512($12) # CHECK: ld.w $w11, 512($12) # encoding: [0x78,0x80,0x62,0xe2] + ld.w $w12, 1024($13) # CHECK: ld.w $w12, 1024($13) # encoding: [0x79,0x00,0x6b,0x22] + ld.w $w13, 2044($14) # CHECK: ld.w $w13, 2044($14) # encoding: [0x79,0xff,0x73,0x62] -# CHECK: ld.d $w14, -4096($15) # encoding: [0x7a,0x00,0x7b,0xa3] -# CHECK: ld.d $w15, -2048($16) # encoding: [0x7b,0x00,0x83,0xe3] -# CHECK: ld.d $w16, -1024($17) # encoding: [0x7b,0x80,0x8c,0x23] -# CHECK: ld.d $w17, -512($18) # encoding: [0x7b,0xc0,0x94,0x63] -# CHECK: ld.d $w18, 0($19) # encoding: [0x78,0x00,0x9c,0xa3] -# CHECK: ld.d $w19, 512($20) # encoding: [0x78,0x40,0xa4,0xe3] -# CHECK: ld.d $w20, 1024($21) # encoding: [0x78,0x80,0xad,0x23] -# CHECK: ld.d $w21, 2048($22) # encoding: [0x79,0x00,0xb5,0x63] -# CHECK: ld.d $w22, 4088($23) # encoding: [0x79,0xff,0xbd,0xa3] - - ld.b $w0, -512($1) - ld.b $w1, 0($2) - ld.b $w2, 511($3) - - ld.h $w3, -1024($4) - ld.h $w4, -512($5) - ld.h $w5, 0($6) - ld.h $w6, 512($7) - ld.h $w7, 1022($8) - - ld.w $w8, -2048($9) - ld.w $w9, -1024($10) - ld.w $w10, -512($11) - ld.w $w11, 512($12) - ld.w $w12, 1024($13) - ld.w $w13, 2044($14) - - ld.d $w14, -4096($15) - ld.d $w15, -2048($16) - ld.d $w16, -1024($17) - ld.d $w17, -512($18) - ld.d $w18, 0($19) - ld.d $w19, 512($20) - ld.d $w20, 1024($21) - ld.d $w21, 2048($22) - ld.d $w22, 4088($23) + ld.d $w14, -4096($15) # CHECK: ld.d $w14, -4096($15) # encoding: [0x7a,0x00,0x7b,0xa3] + ld.d $w15, -2048($16) # CHECK: ld.d $w15, -2048($16) # encoding: [0x7b,0x00,0x83,0xe3] + ld.d $w16, -1024($17) # CHECK: ld.d $w16, -1024($17) # encoding: [0x7b,0x80,0x8c,0x23] + ld.d $w17, -512($18) # CHECK: ld.d $w17, -512($18) # encoding: [0x7b,0xc0,0x94,0x63] + ld.d $w18, 0($19) # CHECK: ld.d $w18, 0($19) # encoding: [0x78,0x00,0x9c,0xa3] + ld.d $w19, 512($20) # CHECK: ld.d $w19, 512($20) # encoding: [0x78,0x40,0xa4,0xe3] + ld.d $w20, 1024($21) # CHECK: ld.d $w20, 1024($21) # encoding: [0x78,0x80,0xad,0x23] + ld.d $w21, 2048($22) # CHECK: ld.d $w21, 2048($22) # encoding: [0x79,0x00,0xb5,0x63] + ld.d $w22, 4088($23) # CHECK: ld.d $w22, 4088($23) # encoding: [0x79,0xff,0xbd,0xa3]