Index: lib/Target/RISCV/AsmParser/RISCVAsmParser.cpp =================================================================== --- lib/Target/RISCV/AsmParser/RISCVAsmParser.cpp +++ lib/Target/RISCV/AsmParser/RISCVAsmParser.cpp @@ -30,6 +30,9 @@ class RISCVAsmParser : public MCTargetAsmParser { SMLoc getLoc() const { return getParser().getTok().getLoc(); } + bool generateImmOutOfRangeError(OperandVector &Operands, uint64_t ErrorInfo, + int Lower, int Upper, Twine Msg); + bool MatchAndEmitInstruction(SMLoc IDLoc, unsigned &Opcode, OperandVector &Operands, MCStreamer &Out, uint64_t &ErrorInfo, @@ -48,6 +51,7 @@ OperandMatchResultTy parseImmediate(OperandVector &Operands); OperandMatchResultTy parseRegister(OperandVector &Operands); + OperandMatchResultTy parseMemOpBaseReg(OperandVector &Operands); bool parseOperand(OperandVector &Operands); @@ -125,10 +129,36 @@ return static_cast(Val)->getValue(); } + // Predicate methods for AsmOperands defined in RISCVInstrInfo.td + + bool isUImm4() const { + return (isConstantImm() && isUInt<4>(getConstantImm())); + } + + bool isUImm5() const { + return (isConstantImm() && isUInt<5>(getConstantImm())); + } + bool isSImm12() const { return (isConstantImm() && isInt<12>(getConstantImm())); } + bool isUImm12() const { + return (isConstantImm() && isUInt<12>(getConstantImm())); + } + + bool isSImm13Lsb0() const { + return (isConstantImm() && isShiftedInt<12, 1>(getConstantImm())); + } + + bool isUImm20() const { + return (isConstantImm() && isUInt<20>(getConstantImm())); + } + + bool isSImm21Lsb0() const { + return (isConstantImm() && isShiftedInt<20, 1>(getConstantImm())); + } + /// getStartLoc - Gets location of the first token of this operand SMLoc getStartLoc() const override { return StartLoc; } /// getEndLoc - Gets location of the last token of this operand @@ -216,13 +246,19 @@ #define GET_SUBTARGET_FEATURE_NAME #include "RISCVGenAsmMatcher.inc" +bool RISCVAsmParser::generateImmOutOfRangeError( + OperandVector &Operands, uint64_t ErrorInfo, int Lower, int Upper, + Twine Msg = "immediate must be an integer in the range") { + SMLoc ErrorLoc = ((RISCVOperand &)*Operands[ErrorInfo]).getStartLoc(); + return Error(ErrorLoc, Msg + " [" + Twine(Lower) + ", " + Twine(Upper) + "]"); +} + bool RISCVAsmParser::MatchAndEmitInstruction(SMLoc IDLoc, unsigned &Opcode, OperandVector &Operands, MCStreamer &Out, uint64_t &ErrorInfo, bool MatchingInlineAsm) { MCInst Inst; - SMLoc ErrorLoc; switch (MatchInstructionImpl(Operands, Inst, ErrorInfo, MatchingInlineAsm)) { default: @@ -235,8 +271,8 @@ return Error(IDLoc, "instruction use requires an option to be enabled"); case Match_MnemonicFail: return Error(IDLoc, "unrecognized instruction mnemonic"); - case Match_InvalidOperand: - ErrorLoc = IDLoc; + case Match_InvalidOperand: { + SMLoc ErrorLoc = IDLoc; if (ErrorInfo != ~0U) { if (ErrorInfo >= Operands.size()) return Error(ErrorLoc, "too few operands for instruction"); @@ -246,10 +282,26 @@ ErrorLoc = IDLoc; } return Error(ErrorLoc, "invalid operand for instruction"); + } + case Match_InvalidUImm4: + return generateImmOutOfRangeError(Operands, ErrorInfo, 0, (1 << 4) - 1); + case Match_InvalidUImm5: + return generateImmOutOfRangeError(Operands, ErrorInfo, 0, (1 << 5) - 1); case Match_InvalidSImm12: - SMLoc ErrorLoc = ((RISCVOperand &)*Operands[ErrorInfo]).getStartLoc(); - return Error(ErrorLoc, - "immediate must be an integer in the range [-2048, 2047]"); + return generateImmOutOfRangeError(Operands, ErrorInfo, -(1 << 11), + (1 << 11) - 1); + case Match_InvalidUImm12: + return generateImmOutOfRangeError(Operands, ErrorInfo, 0, (1 << 12) - 1); + case Match_InvalidSImm13Lsb0: + return generateImmOutOfRangeError( + Operands, ErrorInfo, -(1 << 12), (1 << 12) - 2, + "immediate must be a multiple of 2 bytes in the range"); + case Match_InvalidUImm20: + return generateImmOutOfRangeError(Operands, ErrorInfo, 0, (1 << 20) - 1); + case Match_InvalidSImm21Lsb0: + return generateImmOutOfRangeError( + Operands, ErrorInfo, -(1 << 20), (1 << 20) - 2, + "immediate must be a multiple of 2 bytes in the range"); } llvm_unreachable("Unknown match type detected!"); @@ -314,6 +366,31 @@ return MatchOperand_Success; } +OperandMatchResultTy RISCVAsmParser::parseMemOpBaseReg(OperandVector &Operands) { + if (getLexer().getKind() != AsmToken::LParen) { + Error(getLoc(), "expected '('"); + return MatchOperand_ParseFail; + } + + getParser().Lex(); // Eat '(' + Operands.push_back(RISCVOperand::createToken("(", getLoc())); + + if (parseRegister(Operands) != MatchOperand_Success) { + Error(getLoc(), "expected register"); + return MatchOperand_ParseFail; + } + + if (getLexer().getKind() != AsmToken::RParen) { + Error(getLoc(), "expected ')'"); + return MatchOperand_ParseFail; + } + + getParser().Lex(); // Eat ')' + Operands.push_back(RISCVOperand::createToken(")", getLoc())); + + return MatchOperand_Success; +} + /// Looks at a token type and creates the relevant operand /// from this information, adding to Operands. /// If operand was parsed, returns false, else true. @@ -323,8 +400,13 @@ return false; // Attempt to parse token as an immediate - if (parseImmediate(Operands) == MatchOperand_Success) + if (parseImmediate(Operands) == MatchOperand_Success) { + // Parse memory base register if present + if (getLexer().getKind() == AsmToken::LParen) { + return parseMemOpBaseReg(Operands) != MatchOperand_Success; + } return false; + } // Finally we have exhausted all options and must declare defeat. Error(getLoc(), "unknown operand"); Index: lib/Target/RISCV/MCTargetDesc/RISCVMCCodeEmitter.cpp =================================================================== --- lib/Target/RISCV/MCTargetDesc/RISCVMCCodeEmitter.cpp +++ lib/Target/RISCV/MCTargetDesc/RISCVMCCodeEmitter.cpp @@ -55,6 +55,10 @@ unsigned getMachineOpValue(const MCInst &MI, const MCOperand &MO, SmallVectorImpl &Fixups, const MCSubtargetInfo &STI) const; + + unsigned getImmOpValueAsr1(const MCInst &MI, unsigned OpNo, + SmallVectorImpl &Fixups, + const MCSubtargetInfo &STI) const; }; } // end anonymous namespace @@ -88,4 +92,19 @@ return 0; } +unsigned +RISCVMCCodeEmitter::getImmOpValueAsr1(const MCInst &MI, unsigned OpNo, + SmallVectorImpl &Fixups, + const MCSubtargetInfo &STI) const { + const MCOperand &MO = MI.getOperand(OpNo); + + if (MO.isImm()) { + unsigned Res = MO.getImm(); + assert((Res & 1) == 0 && "LSB is non-zero"); + return Res >> 1; + } + + llvm_unreachable("Unhandled expression!"); +} + #include "RISCVGenMCCodeEmitter.inc" Index: lib/Target/RISCV/RISCVInstrInfo.td =================================================================== --- lib/Target/RISCV/RISCVInstrInfo.td +++ lib/Target/RISCV/RISCVInstrInfo.td @@ -13,17 +13,52 @@ include "RISCVInstrFormats.td" -class SImmAsmOperand - : AsmOperandClass { - let Name = "SImm" # width; +class ImmAsmOperand : AsmOperandClass { + let Name = prefix # "Imm" # width # suffix; let RenderMethod = "addImmOperands"; let DiagnosticType = !strconcat("Invalid", Name); } +class SImmAsmOperand + : ImmAsmOperand<"S", width, suffix> { +} + +class UImmAsmOperand + : ImmAsmOperand<"U", width, suffix> { +} + +def uimm4 : Operand { + let ParserMatchClass = UImmAsmOperand<4>; +} + +def uimm5 : Operand { + let ParserMatchClass = UImmAsmOperand<5>; +} + def simm12 : Operand { let ParserMatchClass = SImmAsmOperand<12>; } +def uimm12 : Operand { + let ParserMatchClass = UImmAsmOperand<12>; +} + +// A 13-bit signed immediate where the least significant bit is zero. +def simm13_lsb0 : Operand { + let ParserMatchClass = SImmAsmOperand<13, "Lsb0">; + let EncoderMethod = "getImmOpValueAsr1"; +} + +def uimm20 : Operand { + let ParserMatchClass = UImmAsmOperand<20>; +} + +// A 21-bit signed immediate where the least significant bit is zero. +def simm21_lsb0 : Operand { + let ParserMatchClass = SImmAsmOperand<21, "Lsb0">; + let EncoderMethod = "getImmOpValueAsr1"; +} + // As noted in RISCVRegisterInfo.td, the hope is that support for // variable-sized register classes will mean that instruction definitions do // not need to be duplicated for 32-bit and 64-bit register classes. For now @@ -32,6 +67,52 @@ // like // is adopted. +def LUI : FU<0b0110111, (outs GPR:$rd), (ins uimm20:$imm20), + "lui\t$rd, $imm20", []>; + +def AUIPC : FU<0b0010111, (outs GPR:$rd), (ins uimm20:$imm20), + "auipc\t$rd, $imm20", []>; + +def JAL : FUJ<0b1101111, (outs GPR:$rd), (ins simm21_lsb0:$imm20), + "jal\t$rd, $imm20", []>; + +def JALR : FI<0b000, 0b1100111, (outs GPR:$rd), (ins GPR:$rs1, simm12:$imm12), + "jalr\t$rd, $rs1, $imm12", []>; + +class Bcc funct3, string OpcodeStr> : + FSB { +} + +def BEQ : Bcc<0b000, "beq">; +def BNE : Bcc<0b001, "bne">; +def BLT : Bcc<0b100, "blt">; +def BGE : Bcc<0b101, "bge">; +def BLTU : Bcc<0b110, "bltu">; +def BGEU : Bcc<0b111, "bgeu">; + +class LD_ri funct3, string OpcodeStr> : + FI { + let mayLoad = 1; +} + +def LB : LD_ri<0b000, "lb">; +def LH : LD_ri<0b001, "lh">; +def LW : LD_ri<0b010, "lw">; +def LBU : LD_ri<0b100, "lbu">; +def LHU : LD_ri<0b101, "lhu">; + +class ST_ri funct3, string OpcodeStr> : + FS { + let mayStore = 1; +} + +def SB : ST_ri<0b000, "sb">; +def SH : ST_ri<0b001, "sh">; +def SW : ST_ri<0b010, "sw">; + class ALU_ri funct3, string OpcodeStr> : FI @@ -45,6 +126,16 @@ def ORI : ALU_ri<0b110, "ori">; def ANDI : ALU_ri<0b111, "andi">; +class SHIFT32_ri funct3, string OpcodeStr> : + FI32Shift +{ +} + +def SLLI : SHIFT32_ri<0, 0b001, "slli">; +def SRLI : SHIFT32_ri<0, 0b101, "srli">; +def SRAI : SHIFT32_ri<1, 0b101, "srai">; + class ALU_rr funct7, bits<3> funct3, string OpcodeStr> : FR @@ -62,3 +153,47 @@ def OR : ALU_rr<0b0000000, 0b110, "or">; def AND : ALU_rr<0b0000000, 0b111, "and">; +def FENCE : FI<0b000, 0b0001111, (outs), (ins uimm4:$pred, uimm4:$succ), + "fence\t$pred, $succ", []> { + bits<4> pred; + bits<4> succ; + + let rs1 = 0; + let rd = 0; + let imm12 = {0b0000,pred,succ}; +} + +def FENCEI : FI<0b001, 0b0001111, (outs), (ins), "fence.i", []> { + let rs1 = 0; + let rd = 0; + let imm12 = 0; +} + +let rs1=0, rd=0 in { + def ECALL : FI<0b000, 0b1110011, (outs), (ins), "ecall", []> { + let imm12=0; + } + def EBREAK : FI<0b000, 0b1110011, (outs), (ins), "ebreak", []> { + let imm12=1; + } +} + +class CSR_rr funct3, string OpcodeStr> : + FI +{ +} + +def CSRRW : CSR_rr<0b001, "csrrw">; +def CSRRS : CSR_rr<0b010, "csrrs">; +def CSRRC : CSR_rr<0b011, "csrrc">; + +class CSR_ri funct3, string OpcodeStr> : + FI +{ +} + +def CSRRWI : CSR_ri<0b101, "csrrwi">; +def CSRRSI : CSR_ri<0b110, "csrrsi">; +def CSRRCI : CSR_ri<0b111, "csrrci">; Index: test/MC/RISCV/rv32i-invalid.s =================================================================== --- test/MC/RISCV/rv32i-invalid.s +++ test/MC/RISCV/rv32i-invalid.s @@ -1,9 +1,53 @@ # RUN: not llvm-mc -triple riscv32 < %s 2>&1 | FileCheck %s # Out of range immediates +## simm12 ori a0, a1, -2049 # CHECK: :[[@LINE]]:13: error: immediate must be an integer in the range [-2048, 2047] andi ra, sp, 2048 # CHECK: :[[@LINE]]:14: error: immediate must be an integer in the range [-2048, 2047] +## imm20 +lui a0, -1 # CHECK: :[[@LINE]]:9: error: immediate must be an integer in the range [0, 1048575] +lui s0, 1048576 # CHECK: :[[@LINE]]:9: error: immediate must be an integer in the range [0, 1048575] +auipc zero, -0xf # CHECK: :[[@LINE]]:13: error: immediate must be an integer in the range [0, 1048575] + +## simm21_mask1 +jal gp, -1048578 # CHECK: :[[@LINE]]:9: error: immediate must be a multiple of 2 bytes in the range [-1048576, 1048574] +jal gp, -1048577 # CHECK: :[[@LINE]]:9: error: immediate must be a multiple of 2 bytes in the range [-1048576, 1048574] +jal gp, 1048575 # CHECK: :[[@LINE]]:9: error: immediate must be a multiple of 2 bytes in the range [-1048576, 1048574] +jal gp, 1048576 # CHECK: :[[@LINE]]:9: error: immediate must be a multiple of 2 bytes in the range [-1048576, 1048574] +jal gp, 1 # CHECK: :[[@LINE]]:9: error: immediate must be a multiple of 2 bytes in the range [-1048576, 1048574] + +## simm13_mask1 +beq t0, t1, -4098 # CHECK: :[[@LINE]]:13: error: immediate must be a multiple of 2 bytes in the range [-4096, 4094] +bne t0, t1, -4097 # CHECK: :[[@LINE]]:13: error: immediate must be a multiple of 2 bytes in the range [-4096, 4094] +blt t0, t1, 4095 # CHECK: :[[@LINE]]:13: error: immediate must be a multiple of 2 bytes in the range [-4096, 4094] +bge t0, t1, 4096 # CHECK: :[[@LINE]]:13: error: immediate must be a multiple of 2 bytes in the range [-4096, 4094] +bltu t0, t1, 13 # CHECK: :[[@LINE]]:14: error: immediate must be a multiple of 2 bytes in the range [-4096, 4094] +bgeu t0, t1, -13 # CHECK: :[[@LINE]]:14: error: immediate must be a multiple of 2 bytes in the range [-4096, 4094] + +## imm5 +slli a0, a0, 32 # CHECK: :[[@LINE]]:14: error: immediate must be an integer in the range [0, 31] +srli a0, a0, -1 # CHECK: :[[@LINE]]:14: error: immediate must be an integer in the range [0, 31] +srai a0, a0, -19 # CHECK: :[[@LINE]]:14: error: immediate must be an integer in the range [0, 31] +csrrwi a1, 0x1, -1 # CHECK: :[[@LINE]]:17: error: immediate must be an integer in the range [0, 31] +csrrsi t1, 999, 32 # CHECK: :[[@LINE]]:17: error: immediate must be an integer in the range [0, 31] +csrrci x0, 43, -90 # CHECK: :[[@LINE]]:16: error: immediate must be an integer in the range [0, 31] + +## imm4 +fence -1, 0 # CHECK: :[[@LINE]]:7: error: immediate must be an integer in the range [0, 15] +fence 0, -1 # CHECK: :[[@LINE]]:10: error: immediate must be an integer in the range [0, 15] +fence 16, 0 # CHECK: :[[@LINE]]:7: error: immediate must be an integer in the range [0, 15] +fence 0, 16 # CHECK: :[[@LINE]]:10: error: immediate must be an integer in the range [0, 15] + +## imm12 +csrrw a0, -1, a0 # CHECK: :[[@LINE]]:11: error: immediate must be an integer in the range [0, 4095] +csrrs a0, 4096, a0 # CHECK: :[[@LINE]]:11: error: immediate must be an integer in the range [0, 4095] +csrrs a0, -0xf, a0 # CHECK: :[[@LINE]]:11: error: immediate must be an integer in the range [0, 4095] +csrrc a0, 0x1000, a0 # CHECK: :[[@LINE]]:11: error: immediate must be an integer in the range [0, 4095] +csrrwi a0, -50, 0 # CHECK: :[[@LINE]]:12: error: immediate must be an integer in the range [0, 4095] +csrrsi a0, 4097, a0 # CHECK: :[[@LINE]]:12: error: immediate must be an integer in the range [0, 4095] +csrrci a0, 0xffff, a0 # CHECK: :[[@LINE]]:12: error: immediate must be an integer in the range [0, 4095] + # Invalid mnemonics subs t0, t2, t1 # CHECK: :[[@LINE]]:1: error: unrecognized instruction mnemonic nandi t0, zero, 0 # CHECK: :[[@LINE]]:1: error: unrecognized instruction mnemonic Index: test/MC/RISCV/rv32i-valid.s =================================================================== --- test/MC/RISCV/rv32i-valid.s +++ test/MC/RISCV/rv32i-valid.s @@ -3,6 +3,100 @@ # RUN: llvm-mc %s -triple=riscv64 -show-encoding \ # RUN: | FileCheck -check-prefixes=CHECK,CHECK-INST %s +# CHECK-INST: lui a0, 2 +# CHECK: encoding: [0x37,0x25,0x00,0x00] +lui a0, 2 +# CHECK-INST: lui s11, 552960 +# CHECK: encoding: [0xb7,0x0d,0x00,0x87] +lui s11, (0x87000000>>12) +# CHECK-INST: lui t0, 1048575 +# CHECK: encoding: [0xb7,0xf2,0xff,0xff] +lui t0, 1048575 +# CHECK-INST: lui gp, 0 +# CHECK: encoding: [0xb7,0x01,0x00,0x00] +lui gp, 0 + +# CHECK-INST: auipc a0, 2 +# CHECK: encoding: [0x17,0x25,0x00,0x00] +auipc a0, 2 +# CHECK-INST: auipc s11, 552960 +# CHECK: encoding: [0x97,0x0d,0x00,0x87] +auipc s11, (0x87000000>>12) +# CHECK-INST: auipc t0, 1048575 +# CHECK: encoding: [0x97,0xf2,0xff,0xff] +auipc t0, 1048575 +# CHECK-INST: auipc gp, 0 +# CHECK: encoding: [0x97,0x01,0x00,0x00] +auipc gp, 0 + +# CHECK-INST: jal a2, 1048574 +# CHECK: encoding: [0x6f,0xf6,0xff,0x7f] +jal a2, 1048574 +# CHECK-INST: jal a3, 256 +# CHECK: encoding: [0xef,0x06,0x00,0x10] +jal a3, 256 + +# CHECK-INST: jalr a0, a1, -2048 +# CHECK: encoding: [0x67,0x85,0x05,0x80] +jalr a0, a1, -2048 +# CHECK-INST: jalr t2, t1, 2047 +# CHECK: encoding: [0xe7,0x03,0xf3,0x7f] +jalr t2, t1, 2047 +# CHECK-INST: jalr sp, zero, 256 +# CHECK: encoding: [0x67,0x01,0x00,0x10] +jalr sp, zero, 256 + +# CHECK-INST: beq s1, s1, 102 +# CHECK: encoding: [0x63,0x83,0x94,0x06] +beq s1, s1, 102 +# CHECK-INST: bne a4, a5, -4096 +# CHECK: encoding: [0x63,0x10,0xf7,0x80] +bne a4, a5, -4096 +# CHECK-INST: blt sp, gp, 4094 +# CHECK: encoding: [0xe3,0x4f,0x31,0x7e] +blt sp, gp, 4094 +# CHECK-INST: bge s2, ra, -224 +# CHECK: encoding: [0xe3,0x50,0x19,0xf2] +bge s2, ra, -224 +# CHECK-INST: bltu zero, zero, 0 +# CHECK: encoding: [0x63,0x60,0x00,0x00] +bltu zero, zero, 0 +# CHECK-INST: bgeu s8, sp, 512 +# CHECK: encoding: [0x63,0x70,0x2c,0x20] +bgeu s8, sp, 512 + +# CHECK-INST: lb s3, 4(ra) +# CHECK: encoding: [0x83,0x89,0x40,0x00] +lb s3, 4(ra) +# CHECK-INST: lb s3, 4(ra) +# CHECK: encoding: [0x83,0x89,0x40,0x00] +lb s3, +4(ra) +# CHECK-INST: lh t1, -2048(zero) +# CHECK: encoding: [0x03,0x13,0x00,0x80] +lh t1, -2048(zero) +# CHECK-INST: lh sp, 2047(a0) +# CHECK: encoding: [0x03,0x11,0xf5,0x7f] +lh sp, 2047(a0) +# CHECK-INST: lw a0, 97(a2) +# CHECK: encoding: [0x03,0x25,0x16,0x06] +lw a0, 97(a2) +# CHECK-INST: lbu s5, 0(s6) +# CHECK: encoding: [0x83,0x4a,0x0b,0x00] +lbu s5, 0(s6) +# CHECK-INST: lhu t3, 255(t3) +# CHECK: encoding: [0x03,0x5e,0xfe,0x0f] +lhu t3, 255(t3) + +# CHECK-INST: sb a0, 2047(a2) +# CHECK: encoding: [0xa3,0x0f,0xa6,0x7e] +sb a0, 2047(a2) +# CHECK-INST: sh t3, -2048(t5) +# CHECK: encoding: [0x23,0x10,0xcf,0x81] +sh t3, -2048(t5) +# CHECK-INST: sw ra, 999(zero) +# CHECK: encoding: [0xa3,0x23,0x10,0x3e] +sw ra, 999(zero) + # CHECK-INST: addi ra, sp, 2 # CHECK: encoding: [0x93,0x00,0x21,0x00] addi ra, sp, 2 @@ -25,6 +119,16 @@ # CHECK: encoding: [0x93,0x70,0xf1,0x7f] andi x1, x2, 2047 +# CHECK-INST: slli t3, t3, 31 +# CHECK: encoding: [0x13,0x1e,0xfe,0x01] +slli t3, t3, 31 +# CHECK-INST: srli a0, a4, 0 +# CHECK: encoding: [0x13,0x55,0x07,0x00] +srli a0, a4, 0 +# CHECK-INST: srai a2, sp, 15 +# CHECK: encoding: [0x13,0x56,0xf1,0x40] +srai a2, sp, 15 + # CHECK-INST: add ra, zero, zero # CHECK: encoding: [0xb3,0x00,0x00,0x00] add ra, zero, zero @@ -61,3 +165,46 @@ # CHECK-INST: and a0, s2, s3 # CHECK: encoding: [0x33,0x75,0x39,0x01] and a0, s2, s3 + +# TODO: gnu assembler supports fence with no arguments +# CHECK-INST: fence 0, 15 +# # CHECK: encoding: [0x0f,0x00,0xf0,0x00] +fence 0, 15 +# CHECK-INST: fence 15, 0 +# CHECK: encoding: [0x0f,0x00,0x00,0x0f] +fence 15, 0 +# CHECK-INST: fence 4, 9 +# CHECK: encoding: [0x0f,0x00,0x90,0x04] +fence 4, 9 +# CHECK-INST: fence.i +# CHECK: encoding: [0x0f,0x10,0x00,0x00] +fence.i + +# CHECK-INST: ecall +# CHECK: encoding: [0x73,0x00,0x00,0x00] +ecall +# CHECK-INST: ebreak +# CHECK: encoding: [0x73,0x00,0x10,0x00] +ebreak + +# CHECK-INST: csrrw t0, 4095, t1 +# CHECK: encoding: [0xf3,0x12,0xf3,0xff] +csrrw t0, 0xfff, t1 +# CHECK-INST: csrrs s0, 3072, zero +# CHECK: encoding: [0x73,0x24,0x00,0xc0] +csrrs s0, 0xc00, x0 +# CHECK-INST: csrrs s3, 1, s5 +# CHECK: encoding: [0xf3,0xa9,0x1a,0x00] +csrrs s3, 0x001, s5 +# CHECK-INST: csrrc sp, 0, ra +# CHECK: encoding: [0x73,0xb1,0x00,0x00] +csrrc sp, 0x000, ra +# CHECK-INST: csrrwi a5, 0, 0 +# CHECK: encoding: [0xf3,0x57,0x00,0x00] +csrrwi a5, 0x000, 0 +# CHECK-INST: csrrsi t2, 4095, 31 +# CHECK: encoding: [0xf3,0xe3,0xff,0xff] +csrrsi t2, 0xfff, 31 +# CHECK-INST: csrrci t1, 320, 5 +# CHECK: encoding: [0x73,0xf3,0x02,0x14] +csrrci t1, 0x140, 5