From: Jozef Kolek Date: Mon, 24 Nov 2014 14:39:13 +0000 (+0000) Subject: [mips][microMIPS] Implement LBU16, LHU16, LW16, SB16, SH16 and SW16 instructions X-Git-Url: http://plrg.eecs.uci.edu/git/?p=oota-llvm.git;a=commitdiff_plain;h=b955bed064d5f10ab72adf028bb8ef438901377c [mips][microMIPS] Implement LBU16, LHU16, LW16, SB16, SH16 and SW16 instructions Differential Revision: http://reviews.llvm.org/D5122 git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@222653 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/lib/Target/Mips/AsmParser/MipsAsmParser.cpp b/lib/Target/Mips/AsmParser/MipsAsmParser.cpp index ec7d5074d39..f458b5bf520 100644 --- a/lib/Target/Mips/AsmParser/MipsAsmParser.cpp +++ b/lib/Target/Mips/AsmParser/MipsAsmParser.cpp @@ -765,6 +765,15 @@ public: addExpr(Inst, Expr); } + void addMicroMipsMemOperands(MCInst &Inst, unsigned N) const { + assert(N == 2 && "Invalid number of operands!"); + + Inst.addOperand(MCOperand::CreateReg(getMemBase()->getGPRMM16Reg())); + + const MCExpr *Expr = getMemOff(); + addExpr(Inst, Expr); + } + void addRegListOperands(MCInst &Inst, unsigned N) const { assert(N == 1 && "Invalid number of operands!"); @@ -797,6 +806,9 @@ public: template bool isMemWithSimmOffset() const { return isMem() && isConstantMemOff() && isInt(getConstantMemOff()); } + bool isMemWithGRPMM16Base() const { + return isMem() && getMemBase()->isMM16AsmReg(); + } bool isInvNum() const { return Kind == k_Immediate; } bool isLSAImm() const { if (!isConstantImm()) @@ -1272,6 +1284,40 @@ bool MipsAsmParser::processInstruction(MCInst &Inst, SMLoc IDLoc, Imm == 64 || Imm == 255 || Imm == 32768 || Imm == 65535)) return Error(IDLoc, "immediate operand value out of range"); break; + case Mips::LBU16_MM: + Opnd = Inst.getOperand(2); + if (!Opnd.isImm()) + return Error(IDLoc, "expected immediate operand kind"); + Imm = Opnd.getImm(); + if (Imm < -1 || Imm > 14) + return Error(IDLoc, "immediate operand value out of range"); + break; + case Mips::SB16_MM: + Opnd = Inst.getOperand(2); + if (!Opnd.isImm()) + return Error(IDLoc, "expected immediate operand kind"); + Imm = Opnd.getImm(); + if (Imm < 0 || Imm > 15) + return Error(IDLoc, "immediate operand value out of range"); + break; + case Mips::LHU16_MM: + case Mips::SH16_MM: + Opnd = Inst.getOperand(2); + if (!Opnd.isImm()) + return Error(IDLoc, "expected immediate operand kind"); + Imm = Opnd.getImm(); + if (Imm < 0 || Imm > 30 || (Imm % 2 != 0)) + return Error(IDLoc, "immediate operand value out of range"); + break; + case Mips::LW16_MM: + case Mips::SW16_MM: + Opnd = Inst.getOperand(2); + if (!Opnd.isImm()) + return Error(IDLoc, "expected immediate operand kind"); + Imm = Opnd.getImm(); + if (Imm < 0 || Imm > 60 || (Imm % 4 != 0)) + return Error(IDLoc, "immediate operand value out of range"); + break; } } diff --git a/lib/Target/Mips/MCTargetDesc/MipsMCCodeEmitter.cpp b/lib/Target/Mips/MCTargetDesc/MipsMCCodeEmitter.cpp index d632c2736de..6cd1eb2e622 100644 --- a/lib/Target/Mips/MCTargetDesc/MipsMCCodeEmitter.cpp +++ b/lib/Target/Mips/MCTargetDesc/MipsMCCodeEmitter.cpp @@ -634,6 +634,48 @@ MipsMCCodeEmitter::getMemEncoding(const MCInst &MI, unsigned OpNo, return (OffBits & 0xFFFF) | RegBits; } +unsigned MipsMCCodeEmitter:: +getMemEncodingMMImm4(const MCInst &MI, unsigned OpNo, + SmallVectorImpl &Fixups, + const MCSubtargetInfo &STI) const { + // Base register is encoded in bits 6-4, offset is encoded in bits 3-0. + assert(MI.getOperand(OpNo).isReg()); + unsigned RegBits = getMachineOpValue(MI, MI.getOperand(OpNo), + Fixups, STI) << 4; + unsigned OffBits = getMachineOpValue(MI, MI.getOperand(OpNo+1), + Fixups, STI); + + return (OffBits & 0xF) | RegBits; +} + +unsigned MipsMCCodeEmitter:: +getMemEncodingMMImm4Lsl1(const MCInst &MI, unsigned OpNo, + SmallVectorImpl &Fixups, + const MCSubtargetInfo &STI) const { + // Base register is encoded in bits 6-4, offset is encoded in bits 3-0. + assert(MI.getOperand(OpNo).isReg()); + unsigned RegBits = getMachineOpValue(MI, MI.getOperand(OpNo), + Fixups, STI) << 4; + unsigned OffBits = getMachineOpValue(MI, MI.getOperand(OpNo+1), + Fixups, STI) >> 1; + + return (OffBits & 0xF) | RegBits; +} + +unsigned MipsMCCodeEmitter:: +getMemEncodingMMImm4Lsl2(const MCInst &MI, unsigned OpNo, + SmallVectorImpl &Fixups, + const MCSubtargetInfo &STI) const { + // Base register is encoded in bits 6-4, offset is encoded in bits 3-0. + assert(MI.getOperand(OpNo).isReg()); + unsigned RegBits = getMachineOpValue(MI, MI.getOperand(OpNo), + Fixups, STI) << 4; + unsigned OffBits = getMachineOpValue(MI, MI.getOperand(OpNo+1), + Fixups, STI) >> 2; + + return (OffBits & 0xF) | RegBits; +} + unsigned MipsMCCodeEmitter:: getMemEncodingMMImm12(const MCInst &MI, unsigned OpNo, SmallVectorImpl &Fixups, diff --git a/lib/Target/Mips/MCTargetDesc/MipsMCCodeEmitter.h b/lib/Target/Mips/MCTargetDesc/MipsMCCodeEmitter.h index 9016fcfedc0..24d0b45bb45 100644 --- a/lib/Target/Mips/MCTargetDesc/MipsMCCodeEmitter.h +++ b/lib/Target/Mips/MCTargetDesc/MipsMCCodeEmitter.h @@ -142,6 +142,15 @@ public: unsigned getMemEncoding(const MCInst &MI, unsigned OpNo, SmallVectorImpl &Fixups, const MCSubtargetInfo &STI) const; + unsigned getMemEncodingMMImm4(const MCInst &MI, unsigned OpNo, + SmallVectorImpl &Fixups, + const MCSubtargetInfo &STI) const; + unsigned getMemEncodingMMImm4Lsl1(const MCInst &MI, unsigned OpNo, + SmallVectorImpl &Fixups, + const MCSubtargetInfo &STI) const; + unsigned getMemEncodingMMImm4Lsl2(const MCInst &MI, unsigned OpNo, + SmallVectorImpl &Fixups, + const MCSubtargetInfo &STI) const; unsigned getMemEncodingMMImm12(const MCInst &MI, unsigned OpNo, SmallVectorImpl &Fixups, const MCSubtargetInfo &STI) const; diff --git a/lib/Target/Mips/MicroMipsInstrFormats.td b/lib/Target/Mips/MicroMipsInstrFormats.td index 59bf94989a1..8a924e90509 100644 --- a/lib/Target/Mips/MicroMipsInstrFormats.td +++ b/lib/Target/Mips/MicroMipsInstrFormats.td @@ -108,6 +108,18 @@ class ADDIUR2_FM_MM16 { let Inst{0} = 0; } +class LOAD_STORE_FM_MM16 op> { + bits<3> rt; + bits<7> addr; + + bits<16> Inst; + + let Inst{15-10} = op; + let Inst{9-7} = rt; + let Inst{6-4} = addr{6-4}; + let Inst{3-0} = addr{3-0}; +} + class ADDIUS5_FM_MM16 { bits<5> rd; bits<4> imm; diff --git a/lib/Target/Mips/MicroMipsInstrInfo.td b/lib/Target/Mips/MicroMipsInstrInfo.td index e85462057ec..59100a402e9 100644 --- a/lib/Target/Mips/MicroMipsInstrInfo.td +++ b/lib/Target/Mips/MicroMipsInstrInfo.td @@ -46,6 +46,32 @@ def immZExt2Shift : ImmLeaf= 1 && Imm <= 8;}]>; def immLi16 : ImmLeaf= -1 && Imm <= 126;}]>; +def MicroMipsMemGPRMM16AsmOperand : AsmOperandClass { + let Name = "MicroMipsMem"; + let RenderMethod = "addMicroMipsMemOperands"; + let ParserMethod = "parseMemOperand"; + let PredicateMethod = "isMemWithGRPMM16Base"; +} + +class mem_mm_4_generic : Operand { + let PrintMethod = "printMemOperand"; + let MIOperandInfo = (ops ptr_rc, simm4); + let OperandType = "OPERAND_MEMORY"; + let ParserMatchClass = MicroMipsMemGPRMM16AsmOperand; +} + +def mem_mm_4 : mem_mm_4_generic { + let EncoderMethod = "getMemEncodingMMImm4"; +} + +def mem_mm_4_lsl1 : mem_mm_4_generic { + let EncoderMethod = "getMemEncodingMMImm4Lsl1"; +} + +def mem_mm_4_lsl2 : mem_mm_4_generic { + let EncoderMethod = "getMemEncodingMMImm4Lsl2"; +} + def mem_mm_12 : Operand { let PrintMethod = "printMemOperand"; let MIOperandInfo = (ops GPR32, simm12); @@ -156,6 +182,22 @@ class ShiftIMM16; +class LoadMM16 : + MicroMipsInst16<(outs RO:$rt), (ins MemOpnd:$addr), + !strconcat(opstr, "\t$rt, $addr"), [], Itin, FrmI> { + let canFoldAsLoad = 1; + let mayLoad = 1; +} + +class StoreMM16 : + MicroMipsInst16<(outs), (ins RTOpnd:$rt, MemOpnd:$addr), + !strconcat(opstr, "\t$rt, $addr"), [], Itin, FrmI> { + let mayStore = 1; +} + class AddImmUR2 : MicroMipsInst16<(outs RO:$rd), (ins RO:$rs, simm3_lsa2:$imm), !strconcat(opstr, "\t$rd, $rs, $imm"), @@ -316,6 +358,19 @@ def SLL16_MM : ShiftIMM16<"sll16", uimm3_shift, GPRMM16Opnd, II_SLL>, SHIFT_FM_MM16<0>; def SRL16_MM : ShiftIMM16<"srl16", uimm3_shift, GPRMM16Opnd, II_SRL>, SHIFT_FM_MM16<1>; +def LBU16_MM : LoadMM16<"lbu16", GPRMM16Opnd, zextloadi8, II_LBU, + mem_mm_4>, LOAD_STORE_FM_MM16<0x02>; +def LHU16_MM : LoadMM16<"lhu16", GPRMM16Opnd, zextloadi16, II_LHU, + mem_mm_4_lsl1>, LOAD_STORE_FM_MM16<0x0a>; +def LW16_MM : LoadMM16<"lw16", GPRMM16Opnd, load, II_LW, mem_mm_4_lsl2>, + LOAD_STORE_FM_MM16<0x1a>; +def SB16_MM : StoreMM16<"sb16", GPRMM16OpndZero, GPRMM16Opnd, truncstorei8, + II_SB, mem_mm_4>, LOAD_STORE_FM_MM16<0x22>; +def SH16_MM : StoreMM16<"sh16", GPRMM16OpndZero, GPRMM16Opnd, truncstorei16, + II_SH, mem_mm_4_lsl1>, + LOAD_STORE_FM_MM16<0x2a>; +def SW16_MM : StoreMM16<"sw16", GPRMM16OpndZero, GPRMM16Opnd, store, II_SW, + mem_mm_4_lsl2>, LOAD_STORE_FM_MM16<0x3a>; def ADDIUR1SP_MM : AddImmUR1SP<"addiur1sp", GPRMM16Opnd>, ADDIUR1SP_FM_MM16; def ADDIUR2_MM : AddImmUR2<"addiur2", GPRMM16Opnd>, ADDIUR2_FM_MM16; def ADDIUS5_MM : AddImmUS5<"addius5", GPR32Opnd>, ADDIUS5_FM_MM16; diff --git a/test/MC/Mips/micromips-16-bit-instructions.s b/test/MC/Mips/micromips-16-bit-instructions.s index 35855e1a995..176584fb2dd 100644 --- a/test/MC/Mips/micromips-16-bit-instructions.s +++ b/test/MC/Mips/micromips-16-bit-instructions.s @@ -18,6 +18,13 @@ # CHECK-EL: xor16 $17, $5 # encoding: [0x4d,0x44] # CHECK-EL: sll16 $3, $16, 5 # encoding: [0x8a,0x25] # CHECK-EL: srl16 $4, $17, 6 # encoding: [0x1d,0x26] +# CHECK-EL: lbu16 $3, 4($17) # encoding: [0x94,0x09] +# CHECK-EL: lhu16 $3, 4($16) # encoding: [0x82,0x29] +# CHECK-EL: lw16 $4, 8($17) # encoding: [0x12,0x6a] +# CHECK-EL: sb16 $3, 4($16) # encoding: [0x84,0x89] +# CHECK-EL: sh16 $4, 8($17) # encoding: [0x14,0xaa] +# CHECK-EL: sw16 $4, 4($17) # encoding: [0x11,0xea] +# CHECK-EL: sw16 $zero, 4($17) # encoding: [0x11,0xe8] # CHECK-EL: li16 $3, -1 # encoding: [0xff,0xed] # CHECK-EL: li16 $3, 126 # encoding: [0xfe,0xed] # CHECK-EL: addiur1sp $7, 4 # encoding: [0x83,0x6f] @@ -48,6 +55,13 @@ # CHECK-EB: xor16 $17, $5 # encoding: [0x44,0x4d] # CHECK-EB: sll16 $3, $16, 5 # encoding: [0x25,0x8a] # CHECK-EB: srl16 $4, $17, 6 # encoding: [0x26,0x1d] +# CHECK-EB: lbu16 $3, 4($17) # encoding: [0x09,0x94] +# CHECK-EB: lhu16 $3, 4($16) # encoding: [0x29,0x82] +# CHECK-EB: lw16 $4, 8($17) # encoding: [0x6a,0x12] +# CHECK-EB: sb16 $3, 4($16) # encoding: [0x89,0x84] +# CHECK-EB: sh16 $4, 8($17) # encoding: [0xaa,0x14] +# CHECK-EB: sw16 $4, 4($17) # encoding: [0xea,0x11] +# CHECK-EB: sw16 $zero, 4($17) # encoding: [0xe8,0x11] # CHECK-EB: li16 $3, -1 # encoding: [0xed,0xff] # CHECK-EB: li16 $3, 126 # encoding: [0xed,0xfe] # CHECK-EB: addiur1sp $7, 4 # encoding: [0x6f,0x83] @@ -76,6 +90,13 @@ xor16 $17, $5 sll16 $3, $16, 5 srl16 $4, $17, 6 + lbu16 $3, 4($17) + lhu16 $3, 4($16) + lw16 $4, 8($17) + sb16 $3, 4($16) + sh16 $4, 8($17) + sw16 $4, 4($17) + sw16 $0, 4($17) li16 $3, -1 li16 $3, 126 addiur1sp $7, 4 diff --git a/test/MC/Mips/micromips-invalid.s b/test/MC/Mips/micromips-invalid.s index 779e66e0d61..62c4bf59751 100644 --- a/test/MC/Mips/micromips-invalid.s +++ b/test/MC/Mips/micromips-invalid.s @@ -29,3 +29,27 @@ swm32 $16, $19, 8($4) # CHECK: :[[@LINE]]:{{[0-9]+}}: error: consecutive register numbers expected swm32 $16-$25, 8($4) # CHECK: :[[@LINE]]:{{[0-9]+}}: error: invalid register operand lwm32 $16, $17, $18, $19, $20, $21, $22, $23, $24, 8($4) # CHECK: :[[@LINE]]:{{[0-9]+}}: error: invalid register operand + lbu16 $9, 8($16) # CHECK: :[[@LINE]]:{{[0-9]+}}: error: invalid operand for instruction + lhu16 $9, 4($16) # CHECK: :[[@LINE]]:{{[0-9]+}}: error: invalid operand for instruction + lw16 $9, 8($17) # CHECK: :[[@LINE]]:{{[0-9]+}}: error: invalid operand for instruction + sb16 $9, 4($16) # CHECK: :[[@LINE]]:{{[0-9]+}}: error: invalid operand for instruction + sh16 $9, 8($17) # CHECK: :[[@LINE]]:{{[0-9]+}}: error: invalid operand for instruction + sw16 $9, 4($17) # CHECK: :[[@LINE]]:{{[0-9]+}}: error: invalid operand for instruction + lbu16 $3, -2($16) # CHECK: :[[@LINE]]:{{[0-9]+}}: error: immediate operand value out of range + lhu16 $3, 64($16) # CHECK: :[[@LINE]]:{{[0-9]+}}: error: immediate operand value out of range + lw16 $4, 68($17) # CHECK: :[[@LINE]]:{{[0-9]+}}: error: immediate operand value out of range + sb16 $3, 64($16) # CHECK: :[[@LINE]]:{{[0-9]+}}: error: immediate operand value out of range + sh16 $4, 68($17) # CHECK: :[[@LINE]]:{{[0-9]+}}: error: immediate operand value out of range + sw16 $4, 64($17) # CHECK: :[[@LINE]]:{{[0-9]+}}: error: immediate operand value out of range + lbu16 $3, -2($16) # CHECK: :[[@LINE]]:{{[0-9]+}}: error: immediate operand value out of range + lhu16 $3, 64($16) # CHECK: :[[@LINE]]:{{[0-9]+}}: error: immediate operand value out of range + lw16 $4, 68($17) # CHECK: :[[@LINE]]:{{[0-9]+}}: error: immediate operand value out of range + sb16 $16, 4($16) # CHECK: :[[@LINE]]:{{[0-9]+}}: error: invalid operand for instruction + sh16 $16, 8($17) # CHECK: :[[@LINE]]:{{[0-9]+}}: error: invalid operand for instruction + sw16 $16, 4($17) # CHECK: :[[@LINE]]:{{[0-9]+}}: error: invalid operand for instruction + lbu16 $16, 8($9) # CHECK: :[[@LINE]]:{{[0-9]+}}: error: invalid operand for instruction + lhu16 $16, 4($9) # CHECK: :[[@LINE]]:{{[0-9]+}}: error: invalid operand for instruction + lw16 $17, 8($10) # CHECK: :[[@LINE]]:{{[0-9]+}}: error: invalid operand for instruction + sb16 $7, 4($9) # CHECK: :[[@LINE]]:{{[0-9]+}}: error: invalid operand for instruction + sh16 $7, 8($9) # CHECK: :[[@LINE]]:{{[0-9]+}}: error: invalid operand for instruction + sw16 $7, 4($10) # CHECK: :[[@LINE]]:{{[0-9]+}}: error: invalid operand for instruction