Index: lib/Target/Mips/AsmParser/MipsAsmParser.cpp =================================================================== --- lib/Target/Mips/AsmParser/MipsAsmParser.cpp +++ lib/Target/Mips/AsmParser/MipsAsmParser.cpp @@ -147,6 +147,9 @@ MipsAsmParser::OperandMatchResultTy parseLSAImm(OperandVector &Operands); + MipsAsmParser::OperandMatchResultTy + parseRegisterList (OperandVector &Operands); + bool searchSymbolAlias(OperandVector &Operands); bool parseOperand(OperandVector &, StringRef Mnemonic); @@ -423,7 +426,8 @@ k_Memory, /// Base + Offset Memory Address k_PhysRegister, /// A physical register from the Mips namespace k_RegisterIndex, /// A register index in one or more RegKind. - k_Token /// A simple token + k_Token, /// A simple token + k_RegList /// A physical register list } Kind; public: @@ -458,12 +462,17 @@ const MCExpr *Off; }; + struct RegListOp { + SmallVector *List; + }; + union { struct Token Tok; struct PhysRegOp PhysReg; struct RegIdxOp RegIdx; struct ImmOp Imm; struct MemOp Mem; + struct RegListOp RegList; }; SMLoc StartLoc, EndLoc; @@ -737,6 +746,13 @@ addExpr(Inst, Expr); } + void addRegListOperands(MCInst &Inst, unsigned N) const { + assert(N == 1 && "Invalid number of operands!"); + + for (auto RegNo : getRegList()) + Inst.addOperand(MCOperand::CreateReg(RegNo)); + } + bool isReg() const override { // As a special case until we sort out the definition of div/divu, pretend // that $0/$zero are k_PhysRegister so that MCK_ZERO works correctly. @@ -769,6 +785,7 @@ int64_t Val = getConstantImm(); return 1 <= Val && Val <= 4; } + bool isRegList() const { return Kind == k_RegList; } StringRef getToken() const { assert(Kind == k_Token && "Invalid access!"); @@ -810,6 +827,11 @@ return static_cast(getMemOff())->getValue(); } + const SmallVectorImpl &getRegList() const { + assert((Kind == k_RegList) && "Invalid access!"); + return *(RegList.List); + } + static std::unique_ptr CreateToken(StringRef Str, SMLoc S, MipsAsmParser &Parser) { auto Op = make_unique(k_Token, Parser); @@ -897,6 +919,20 @@ return Op; } + static std::unique_ptr + CreateRegList(SmallVectorImpl &Regs, SMLoc StartLoc, SMLoc EndLoc, + MipsAsmParser &Parser) { + assert (Regs.size() > 0 && "Empty list not allowed"); + + auto Op = make_unique(k_RegList, Parser); + Op->RegList.List = new SmallVector(); + for (auto Reg : Regs) + Op->RegList.List->push_back(Reg); + Op->StartLoc = StartLoc; + Op->EndLoc = EndLoc; + return Op; + } + bool isGPRAsmReg() const { return isRegIdx() && RegIdx.Kind & RegKind_GPR && RegIdx.Index <= 31; } @@ -945,6 +981,8 @@ case k_Memory: delete Mem.Base; break; + case k_RegList: + delete RegList.List; case k_PhysRegister: case k_RegisterIndex: case k_Token: @@ -975,6 +1013,12 @@ case k_Token: OS << Tok.Data; break; + case k_RegList: + OS << "RegList< "; + for (auto Reg : (*RegList.List)) + OS << Reg << " "; + OS << ">"; + break; } } }; // class MipsOperand @@ -2417,6 +2461,74 @@ return MatchOperand_Success; } +MipsAsmParser::OperandMatchResultTy +MipsAsmParser::parseRegisterList(OperandVector &Operands) { + SmallVector Regs; + unsigned RegNo; + unsigned PrevReg = Mips::NoRegister; + bool RegRange = false; + SmallVector, 8> TmpOperands; + + if(Parser.getTok().isNot(AsmToken::Dollar)) + return MatchOperand_ParseFail; + + SMLoc S = Parser.getTok().getLoc(); + while (parseAnyRegister(TmpOperands) == MatchOperand_Success) { + SMLoc E = getLexer().getLoc(); + MipsOperand &Reg = static_cast(*TmpOperands.back()); + RegNo = isGP64bit() ? Reg.getGPR64Reg() : Reg.getGPR32Reg(); + if (RegRange) { + // Remove last register operand because registers from register range + // should be inserted first. + TmpOperands.pop_back(); + unsigned TmpReg = PrevReg + 1; + while ( TmpReg <= RegNo) { + if ((TmpReg < Mips::S0) || (TmpReg > Mips::S7)) { + Error(E, "invalid register operand"); + return MatchOperand_ParseFail; + } + PrevReg = TmpReg; + Regs.push_back(TmpReg++); + } + } else { + if ((PrevReg != Mips::NoRegister) && (RegNo != PrevReg + 1) + && (RegNo != Mips::FP) && (RegNo != Mips::RA)) { + Error(E, "consecutive register numbers expected"); + return MatchOperand_ParseFail; + } else if ((PrevReg == Mips::NoRegister) && (RegNo != Mips::S0) && + (RegNo != Mips::RA)) { + Error(E, "$16 or $31 expected"); + return MatchOperand_ParseFail; + } else if ((RegNo < Mips::S0) && (RegNo > Mips::S7) && + (RegNo != Mips::FP) && (RegNo != Mips::RA)) { + Error(E, "invalid register operand"); + return MatchOperand_ParseFail; + } + Regs.push_back(RegNo); + } + + if (Parser.getTok().is(AsmToken::Minus)) + RegRange = true; + + if (!Parser.getTok().isNot(AsmToken::Minus) + && !Parser.getTok().isNot(AsmToken::Comma)) { + Error(E, "',' or '-' expected"); + return MatchOperand_ParseFail; + } + + Lex(); // Consume comma or minus + if(Parser.getTok().isNot(AsmToken::Dollar)) + break; + + PrevReg = RegNo; + } + + SMLoc E = Parser.getTok().getLoc(); + Operands.push_back(MipsOperand::CreateRegList(Regs, S, E, *this)); + parseMemOperand(Operands); + return MatchOperand_Success; +} + MCSymbolRefExpr::VariantKind MipsAsmParser::getVariantKind(StringRef Symbol) { MCSymbolRefExpr::VariantKind VK = Index: lib/Target/Mips/Disassembler/MipsDisassembler.cpp =================================================================== --- lib/Target/Mips/Disassembler/MipsDisassembler.cpp +++ lib/Target/Mips/Disassembler/MipsDisassembler.cpp @@ -349,6 +349,10 @@ DecodeBlezGroupBranch(MCInst &MI, InsnType insn, uint64_t Address, const void *Decoder); +static DecodeStatus DecodeRegListOperand(MCInst &Inst, unsigned Insn, + uint64_t Address, + const void *Decoder); + namespace llvm { extern Target TheMipselTarget, TheMipsTarget, TheMips64Target, TheMips64elTarget; @@ -1051,12 +1055,23 @@ Reg = getReg(Decoder, Mips::GPR32RegClassID, Reg); Base = getReg(Decoder, Mips::GPR32RegClassID, Base); - if (Inst.getOpcode() == Mips::SC_MM) + switch (Inst.getOpcode()) { + case Mips::SWM32_MM: + case Mips::LWM32_MM: + if (DecodeRegListOperand(Inst, Insn, Address, Decoder) + == MCDisassembler::Fail) + return MCDisassembler::Fail; + Inst.addOperand(MCOperand::CreateReg(Base)); + Inst.addOperand(MCOperand::CreateImm(Offset)); + break; + case Mips::SC_MM: Inst.addOperand(MCOperand::CreateReg(Reg)); - - Inst.addOperand(MCOperand::CreateReg(Reg)); - Inst.addOperand(MCOperand::CreateReg(Base)); - Inst.addOperand(MCOperand::CreateImm(Offset)); + // fallthrough + default: + Inst.addOperand(MCOperand::CreateReg(Reg)); + Inst.addOperand(MCOperand::CreateReg(Base)); + Inst.addOperand(MCOperand::CreateImm(Offset)); + } return MCDisassembler::Success; } @@ -1392,3 +1407,26 @@ Inst.addOperand(MCOperand::CreateImm(SignExtend32<18>(Insn) * 8)); return MCDisassembler::Success; } + +static DecodeStatus DecodeRegListOperand(MCInst &Inst, + unsigned Insn, + uint64_t Address, + const void *Decoder) { + unsigned Regs[] = {Mips::S0, Mips::S1, Mips::S2, Mips::S3, Mips::S4, Mips::S5, + Mips::S6, Mips::FP}; + unsigned RegNum; + + unsigned RegLst = fieldFromInstruction(Insn, 21, 5); + // Empty register lists are not allowed. + if (RegLst == 0) + return MCDisassembler::Fail; + + RegNum = RegLst & 0xf; + for (unsigned i = 0; i < RegNum; i++) + Inst.addOperand(MCOperand::CreateReg(Regs[i])); + + if(RegLst & 0x10) + Inst.addOperand(MCOperand::CreateReg(Mips::RA)); + + return MCDisassembler::Success; +} Index: lib/Target/Mips/InstPrinter/MipsInstPrinter.h =================================================================== --- lib/Target/Mips/InstPrinter/MipsInstPrinter.h +++ lib/Target/Mips/InstPrinter/MipsInstPrinter.h @@ -107,6 +107,7 @@ unsigned OpNo1, raw_ostream &OS); bool printAlias(const MCInst &MI, raw_ostream &OS); void printSaveRestore(const MCInst *MI, raw_ostream &O); + void printRegisterList(const MCInst *MI, int opNum, raw_ostream &O); }; } // end namespace llvm Index: lib/Target/Mips/InstPrinter/MipsInstPrinter.cpp =================================================================== --- lib/Target/Mips/InstPrinter/MipsInstPrinter.cpp +++ lib/Target/Mips/InstPrinter/MipsInstPrinter.cpp @@ -225,6 +225,18 @@ // Load/Store memory operands -- imm($reg) // If PIC target the target is loaded as the // pattern lw $25,%call16($28) + + // 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::SWM32_MM: + case Mips::LWM32_MM: + opNum = MI->getNumOperands() - 2; + break; + } + printOperand(MI, opNum+1, O); O << "("; printOperand(MI, opNum, O); @@ -324,3 +336,13 @@ } } +void MipsInstPrinter:: +printRegisterList(const MCInst *MI, int opNum, raw_ostream &O) { + // - 2 because regiter List is always first operand of instruction and iti is + // always followed by memory operand (base + offset). + for (int i = opNum, e = MI->getNumOperands() - 2; i != e; ++i) { + if (i != opNum) + O << ", "; + printRegName(O, MI->getOperand(i).getReg()); + } +} Index: lib/Target/Mips/MCTargetDesc/MipsMCCodeEmitter.h =================================================================== --- lib/Target/Mips/MCTargetDesc/MipsMCCodeEmitter.h +++ lib/Target/Mips/MCTargetDesc/MipsMCCodeEmitter.h @@ -160,6 +160,9 @@ unsigned getExprOpValue(const MCExpr *Expr, SmallVectorImpl &Fixups, const MCSubtargetInfo &STI) const; + unsigned getRegisterListOpValue(const MCInst &MI, unsigned OpNo, + SmallVectorImpl &Fixups, + const MCSubtargetInfo &STI) const; }; // class MipsMCCodeEmitter } // namespace llvm. Index: lib/Target/Mips/MCTargetDesc/MipsMCCodeEmitter.cpp =================================================================== --- lib/Target/Mips/MCTargetDesc/MipsMCCodeEmitter.cpp +++ lib/Target/Mips/MCTargetDesc/MipsMCCodeEmitter.cpp @@ -610,6 +610,17 @@ getMemEncodingMMImm12(const MCInst &MI, unsigned OpNo, SmallVectorImpl &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::SWM32_MM: + case Mips::LWM32_MM: + OpNo = MI.getNumOperands() - 2; + break; + } + // Base register is encoded in bits 20-16, offset is encoded in bits 11-0. assert(MI.getOperand(OpNo).isReg()); unsigned RegBits = getMachineOpValue(MI, MI.getOperand(OpNo), Fixups, STI) << 16; @@ -692,4 +703,24 @@ return 0; } +unsigned +MipsMCCodeEmitter::getRegisterListOpValue(const MCInst &MI, unsigned OpNo, + SmallVectorImpl &Fixups, + const MCSubtargetInfo &STI) const { + unsigned res = 0; + + // Register list operand is always first operand of instruction and it is + // placed before memory operand (register + imm). + + for (unsigned I = OpNo, E = MI.getNumOperands() - 2; I < E; ++I) { + unsigned Reg = MI.getOperand(I).getReg(); + unsigned RegNo = Ctx.getRegisterInfo()->getEncodingValue(Reg); + if (RegNo != 31) + res++; + else + res |= 0x10; + } + return res; +} + #include "MipsGenMCCodeEmitter.inc" Index: lib/Target/Mips/MicroMipsInstrFormats.td =================================================================== --- lib/Target/Mips/MicroMipsInstrFormats.td +++ lib/Target/Mips/MicroMipsInstrFormats.td @@ -675,3 +675,16 @@ let Inst{15-6} = op; let Inst{5-0} = 0x3c; } + +class LWM_FM_MM funct> : MMArch { + bits<5> rt; + bits<21> addr; + + bits<32> Inst; + + let Inst{31-26} = 0x8; + let Inst{25-21} = rt; + let Inst{20-16} = addr{20-16}; + let Inst{15-12} = funct; + let Inst{11-0} = addr{11-0}; +} Index: lib/Target/Mips/MicroMipsInstrInfo.td =================================================================== --- lib/Target/Mips/MicroMipsInstrInfo.td +++ lib/Target/Mips/MicroMipsInstrInfo.td @@ -182,6 +182,35 @@ !strconcat(opstr, "\t$rs, $offset"), [], IIBranch, FrmI, opstr>; } +/// A list of registers used by load/store multiple instructions. +def RegListAsmOperand : AsmOperandClass { + let Name = "RegList"; + let ParserMethod = "parseRegisterList"; +} + +def reglist : Operand { + let EncoderMethod = "getRegisterListOpValue"; + let ParserMatchClass = RegListAsmOperand; + let PrintMethod = "printRegisterList"; + let DecoderMethod = "DecodeRegListOperand"; +} + +class StoreMultMM : + InstSE<(outs), (ins reglist:$rt, mem_mm_12:$addr), + !strconcat(opstr, "\t$rt, $addr"), [], Itin, FrmI, opstr> { + let DecoderMethod = "DecodeMemMMImm12"; + let mayStore = 1; +} + +class LoadMultMM : + InstSE<(outs reglist:$rt), (ins mem_mm_12:$addr), + !strconcat(opstr, "\t$rt, $addr"), [], Itin, FrmI, opstr> { + let DecoderMethod = "DecodeMemMMImm12"; + let mayLoad = 1; +} + def ADDIUS5_MM : AddImmUS5<"addius5", GPR32Opnd>, ADDIUS5_FM_MM16; def ADDIUSP_MM : AddImmUSP<"addiusp">, ADDIUSP_FM_MM16; def MFHI16_MM : MoveFromHILOMM<"mfhi", GPR32Opnd, AC0>, MFHILO_FM_MM16<0x10>; @@ -291,6 +320,10 @@ def SWR_MM : StoreLeftRightMM<"swr", MipsSWR, GPR32Opnd, mem_mm_12>, LWL_FM_MM<0x9>; + /// Load and Store Instructions - multiple + def SWM32_MM : StoreMultMM<"swm32">, LWM_FM_MM<0xd>; + def LWM32_MM : LoadMultMM<"lwm32">, LWM_FM_MM<0x5>; + /// Move Conditional def MOVZ_I_MM : MMRel, CMov_I_I_FT<"movz", GPR32Opnd, GPR32Opnd, NoItinerary>, ADD_FM_MM<0, 0x58>; Index: lib/Target/Mips/MipsAsmPrinter.h =================================================================== --- lib/Target/Mips/MipsAsmPrinter.h +++ lib/Target/Mips/MipsAsmPrinter.h @@ -134,6 +134,7 @@ void printMemOperandEA(const MachineInstr *MI, int opNum, raw_ostream &O); void printFCCOperand(const MachineInstr *MI, int opNum, raw_ostream &O, const char *Modifier = nullptr); + void printRegisterList(const MachineInstr *MI, int opNum, raw_ostream &O); void EmitStartOfAsmFile(Module &M) override; void EmitEndOfAsmFile(Module &M) override; void PrintDebugValueComment(const MachineInstr *MI, raw_ostream &OS); Index: lib/Target/Mips/MipsAsmPrinter.cpp =================================================================== --- lib/Target/Mips/MipsAsmPrinter.cpp +++ lib/Target/Mips/MipsAsmPrinter.cpp @@ -647,6 +647,18 @@ // Load/Store memory operands -- imm($reg) // If PIC target the target is loaded as the // pattern lw $25,%call16($28) + + // opNum can be invalid if instruction has reglist as operand + // MemOperand is always last operand of instruction (base + offset) + switch (MI->getOpcode()) { + default: + break; + case Mips::SWM32_MM: + case Mips::LWM32_MM: + opNum = MI->getNumOperands() - 2; + break; + } + printOperand(MI, opNum+1, O); O << "("; printOperand(MI, opNum, O); @@ -670,6 +682,14 @@ O << Mips::MipsFCCToString((Mips::CondCode)MO.getImm()); } +void MipsAsmPrinter:: +printRegisterList(const MachineInstr *MI, int opNum, raw_ostream &O) { + for (int i = opNum, e = MI->getNumOperands(); i != e; ++i) { + if (i != opNum) O << ", "; + printOperand(MI, i, O); + } +} + void MipsAsmPrinter::EmitStartOfAsmFile(Module &M) { bool IsABICalls = Subtarget->isABICalls(); if (IsABICalls) { Index: test/MC/Disassembler/Mips/micromips.txt =================================================================== --- test/MC/Disassembler/Mips/micromips.txt +++ test/MC/Disassembler/Mips/micromips.txt @@ -294,3 +294,9 @@ # CHECK: sc $2, 8($4) 0x60 0x44 0xb0 0x08 + +# CHECK: lwm32 $16, $17, 8($4) +0x20 0x44 0x50 0x08 + +# CHECK: swm32 $16, $17, 8($4) +0x20 0x44 0xd0 0x08 Index: test/MC/Disassembler/Mips/micromips_le.txt =================================================================== --- test/MC/Disassembler/Mips/micromips_le.txt +++ test/MC/Disassembler/Mips/micromips_le.txt @@ -294,3 +294,9 @@ # CHECK: sc $2, 8($4) 0x44 0x60 0x08 0xb0 + +# CHECK: lwm32 $16, $17, 8($4) +0x44 0x20 0x08 0x50 + +# CHECK: swm32 $16, $17, 8($4) +0x44 0x20 0x08 0xd0 Index: test/MC/Mips/micromips-invalid.s =================================================================== --- test/MC/Mips/micromips-invalid.s +++ test/MC/Mips/micromips-invalid.s @@ -3,3 +3,9 @@ addius5 $7, 9 # CHECK: :[[@LINE]]:{{[0-9]+}}: error: immediate operand value out of range addiusp 1032 # CHECK: :[[@LINE]]:{{[0-9]+}}: error: immediate operand value out of range + 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 + swm32 $5, $6, 8($4) # CHECK: :[[@LINE]]:{{[0-9]+}}: error: $16 or $31 expected + 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 Index: test/MC/Mips/micromips-loadstore-instructions.s =================================================================== --- test/MC/Mips/micromips-loadstore-instructions.s +++ test/MC/Mips/micromips-loadstore-instructions.s @@ -9,31 +9,35 @@ #------------------------------------------------------------------------------ # Little endian #------------------------------------------------------------------------------ -# CHECK-EL: lb $5, 8($4) # encoding: [0xa4,0x1c,0x08,0x00] -# CHECK-EL: lbu $6, 8($4) # encoding: [0xc4,0x14,0x08,0x00] -# CHECK-EL: lh $2, 8($4) # encoding: [0x44,0x3c,0x08,0x00] -# CHECK-EL: lhu $4, 8($2) # encoding: [0x82,0x34,0x08,0x00] -# CHECK-EL: lw $6, 4($5) # encoding: [0xc5,0xfc,0x04,0x00] -# CHECK-EL: sb $5, 8($4) # encoding: [0xa4,0x18,0x08,0x00] -# CHECK-EL: sh $2, 8($4) # encoding: [0x44,0x38,0x08,0x00] -# CHECK-EL: sw $5, 4($6) # encoding: [0xa6,0xf8,0x04,0x00] -# CHECK-EL: ll $2, 8($4) # encoding: [0x44,0x60,0x08,0x30] -# CHECK-EL: sc $2, 8($4) # encoding: [0x44,0x60,0x08,0xb0] -# CHECK-EL: lwu $2, 8($4) # encoding: [0x44,0x60,0x08,0xe0] +# CHECK-EL: lb $5, 8($4) # encoding: [0xa4,0x1c,0x08,0x00] +# CHECK-EL: lbu $6, 8($4) # encoding: [0xc4,0x14,0x08,0x00] +# CHECK-EL: lh $2, 8($4) # encoding: [0x44,0x3c,0x08,0x00] +# CHECK-EL: lhu $4, 8($2) # encoding: [0x82,0x34,0x08,0x00] +# CHECK-EL: lw $6, 4($5) # encoding: [0xc5,0xfc,0x04,0x00] +# CHECK-EL: sb $5, 8($4) # encoding: [0xa4,0x18,0x08,0x00] +# CHECK-EL: sh $2, 8($4) # encoding: [0x44,0x38,0x08,0x00] +# CHECK-EL: sw $5, 4($6) # encoding: [0xa6,0xf8,0x04,0x00] +# CHECK-EL: ll $2, 8($4) # encoding: [0x44,0x60,0x08,0x30] +# CHECK-EL: sc $2, 8($4) # encoding: [0x44,0x60,0x08,0xb0] +# CHECK-EL: lwu $2, 8($4) # encoding: [0x44,0x60,0x08,0xe0] +# CHECK-EL: lwm32 $16, $17, 8($4) # encoding: [0x44,0x20,0x08,0x50] +# CHECK-EL: lwm32 $16, $17, $18, $19, 8($4) # encoding: [0x84,0x20,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] #------------------------------------------------------------------------------ # Big endian #------------------------------------------------------------------------------ -# CHECK-EB: lb $5, 8($4) # encoding: [0x1c,0xa4,0x00,0x08] -# CHECK-EB: lbu $6, 8($4) # encoding: [0x14,0xc4,0x00,0x08] -# CHECK-EB: lh $2, 8($4) # encoding: [0x3c,0x44,0x00,0x08] -# CHECK-EB: lhu $4, 8($2) # encoding: [0x34,0x82,0x00,0x08] -# CHECK-EB: lw $6, 4($5) # encoding: [0xfc,0xc5,0x00,0x04] -# CHECK-EB: sb $5, 8($4) # encoding: [0x18,0xa4,0x00,0x08] -# CHECK-EB: sh $2, 8($4) # encoding: [0x38,0x44,0x00,0x08] -# CHECK-EB: sw $5, 4($6) # encoding: [0xf8,0xa6,0x00,0x04] -# CHECK-EB: ll $2, 8($4) # encoding: [0x60,0x44,0x30,0x08] -# CHECK-EB: sc $2, 8($4) # encoding: [0x60,0x44,0xb0,0x08] -# CHECK-EB: lwu $2, 8($4) # encoding: [0x60,0x44,0xe0,0x08] +# CHECK-EB: lb $5, 8($4) # encoding: [0x1c,0xa4,0x00,0x08] +# CHECK-EB: lbu $6, 8($4) # encoding: [0x14,0xc4,0x00,0x08] +# CHECK-EB: lh $2, 8($4) # encoding: [0x3c,0x44,0x00,0x08] +# CHECK-EB: lhu $4, 8($2) # encoding: [0x34,0x82,0x00,0x08] +# CHECK-EB: lw $6, 4($5) # encoding: [0xfc,0xc5,0x00,0x04] +# CHECK-EB: sb $5, 8($4) # encoding: [0x18,0xa4,0x00,0x08] +# CHECK-EB: sh $2, 8($4) # encoding: [0x38,0x44,0x00,0x08] +# CHECK-EB: lwm32 $16, $17, 8($4) # encoding: [0x20,0x44,0x50,0x08] +# CHECK-EB: lwm32 $16, $17, $18, $19, 8($4) # encoding: [0x20,0x84,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] lb $5, 8($4) lbu $6, 8($4) lh $2, 8($4) @@ -45,3 +49,7 @@ ll $2, 8($4) sc $2, 8($4) lwu $2, 8($4) + lwm32 $16, $17, 8($4) + lwm32 $16 - $19, 8($4) + swm32 $16, $17, 8($4) + swm32 $16 - $19, 8($4)