diff --git a/llvm/lib/Target/RISCV/AsmParser/RISCVAsmParser.cpp b/llvm/lib/Target/RISCV/AsmParser/RISCVAsmParser.cpp --- a/llvm/lib/Target/RISCV/AsmParser/RISCVAsmParser.cpp +++ b/llvm/lib/Target/RISCV/AsmParser/RISCVAsmParser.cpp @@ -161,7 +161,7 @@ OperandMatchResultTy parseRegister(OperandVector &Operands, bool AllowParens = false); OperandMatchResultTy parseMemOpBaseReg(OperandVector &Operands); - OperandMatchResultTy parseAtomicMemOp(OperandVector &Operands); + OperandMatchResultTy parseZeroOffsetMemOp(OperandVector &Operands); OperandMatchResultTy parseOperandWithModifier(OperandVector &Operands); OperandMatchResultTy parseBareSymbol(OperandVector &Operands); OperandMatchResultTy parseCallSymbol(OperandVector &Operands); @@ -1793,7 +1793,8 @@ return MatchOperand_Success; } -OperandMatchResultTy RISCVAsmParser::parseAtomicMemOp(OperandVector &Operands) { +OperandMatchResultTy +RISCVAsmParser::parseZeroOffsetMemOp(OperandVector &Operands) { // Atomic operations such as lr.w, sc.w, and amo*.w accept a "memory operand" // as one of their register operands, such as `(a0)`. This just denotes that // the register (in this case `a0`) contains a memory address. @@ -1809,9 +1810,9 @@ // offset if it is zero; require (and discard) parentheses; and add only the // parsed register operand to `Operands`. // - // These operands are printed with RISCVInstPrinter::printAtomicMemOp, which - // will only print the register surrounded by parentheses (which GNU as also - // uses as its canonical representation for these operands). + // These operands are printed with RISCVInstPrinter::printZeroOffsetMemOp, + // which will only print the register surrounded by parentheses (which GNU as + // also uses as its canonical representation for these operands). std::unique_ptr OptionalImmOp; if (getLexer().isNot(AsmToken::LParen)) { diff --git a/llvm/lib/Target/RISCV/MCTargetDesc/RISCVInstPrinter.h b/llvm/lib/Target/RISCV/MCTargetDesc/RISCVInstPrinter.h --- a/llvm/lib/Target/RISCV/MCTargetDesc/RISCVInstPrinter.h +++ b/llvm/lib/Target/RISCV/MCTargetDesc/RISCVInstPrinter.h @@ -40,8 +40,8 @@ const MCSubtargetInfo &STI, raw_ostream &O); void printFRMArg(const MCInst *MI, unsigned OpNo, const MCSubtargetInfo &STI, raw_ostream &O); - void printAtomicMemOp(const MCInst *MI, unsigned OpNo, - const MCSubtargetInfo &STI, raw_ostream &O); + void printZeroOffsetMemOp(const MCInst *MI, unsigned OpNo, + const MCSubtargetInfo &STI, raw_ostream &O); void printVTypeI(const MCInst *MI, unsigned OpNo, const MCSubtargetInfo &STI, raw_ostream &O); void printVMaskReg(const MCInst *MI, unsigned OpNo, diff --git a/llvm/lib/Target/RISCV/MCTargetDesc/RISCVInstPrinter.cpp b/llvm/lib/Target/RISCV/MCTargetDesc/RISCVInstPrinter.cpp --- a/llvm/lib/Target/RISCV/MCTargetDesc/RISCVInstPrinter.cpp +++ b/llvm/lib/Target/RISCV/MCTargetDesc/RISCVInstPrinter.cpp @@ -156,12 +156,12 @@ O << RISCVFPRndMode::roundingModeToString(FRMArg); } -void RISCVInstPrinter::printAtomicMemOp(const MCInst *MI, unsigned OpNo, - const MCSubtargetInfo &STI, - raw_ostream &O) { +void RISCVInstPrinter::printZeroOffsetMemOp(const MCInst *MI, unsigned OpNo, + const MCSubtargetInfo &STI, + raw_ostream &O) { const MCOperand &MO = MI->getOperand(OpNo); - assert(MO.isReg() && "printAtomicMemOp can only print register operands"); + assert(MO.isReg() && "printZeroOffsetMemOp can only print register operands"); O << "("; printRegName(O, MO.getReg()); O << ")"; diff --git a/llvm/lib/Target/RISCV/RISCVInstrInfo.td b/llvm/lib/Target/RISCV/RISCVInstrInfo.td --- a/llvm/lib/Target/RISCV/RISCVInstrInfo.td +++ b/llvm/lib/Target/RISCV/RISCVInstrInfo.td @@ -103,6 +103,20 @@ let DiagnosticType = !strconcat("Invalid", Name); } +// A parse method for (${gpr}) or 0(${gpr}), where the 0 is be silently ignored. +// Used for GNU as Compatibility. +def ZeroOffsetMemOpOperand : AsmOperandClass { + let Name = "ZeroOffsetMemOpOperand"; + let RenderMethod = "addRegOperands"; + let PredicateMethod = "isGPR"; + let ParserMethod = "parseZeroOffsetMemOp"; +} + +def GPRMemZeroOffset : RegisterOperand { + let ParserMatchClass = ZeroOffsetMemOpOperand; + let PrintMethod = "printZeroOffsetMemOp"; +} + class SImmAsmOperand : ImmAsmOperand<"S", width, suffix> { } @@ -435,20 +449,35 @@ let isTerminator = 1; } -let hasSideEffects = 0, mayLoad = 1, mayStore = 0 in +let hasSideEffects = 0, mayLoad = 1, mayStore = 0 in { class Load_ri funct3, string opcodestr> : RVInstI; +class HLoad_r funct7, bits<5> funct5, string opcodestr> + : RVInstR { + let rs2 = funct5; +} +} + // Operands for stores are in the order srcreg, base, offset rather than // reflecting the order these fields are specified in the instruction // encoding. -let hasSideEffects = 0, mayLoad = 0, mayStore = 1 in +let hasSideEffects = 0, mayLoad = 0, mayStore = 1 in { class Store_rri funct3, string opcodestr> : RVInstS; +class HStore_r funct7, string opcodestr> + : RVInstR { + let rd = 0; +} +} + let hasSideEffects = 0, mayLoad = 0, mayStore = 0 in class ALU_ri funct3, string opcodestr> : RVInstI, Sched<[]>; } +def HLV_B : HLoad_r<0b0110000, 0b00000, "hlv.b">, Sched<[]>; +def HLV_BU : HLoad_r<0b0110000, 0b00001, "hlv.bu">, Sched<[]>; +def HLV_H : HLoad_r<0b0110010, 0b00000, "hlv.h">, Sched<[]>; +def HLV_HU : HLoad_r<0b0110010, 0b00001, "hlv.hu">, Sched<[]>; +def HLVX_HU : HLoad_r<0b0110010, 0b00011, "hlvx.hu">, Sched<[]>; +def HLV_W : HLoad_r<0b0110100, 0b00000, "hlv.w">, Sched<[]>; +def HLVX_WU : HLoad_r<0b0110100, 0b00011, "hlvx.wu">, Sched<[]>; +let Predicates = [IsRV64] in { +def HLV_WU : HLoad_r<0b0110100, 0b00001, "hlv.wu">, Sched<[]>; +def HLV_D : HLoad_r<0b0110110, 0b00000, "hlv.d">, Sched<[]>; +} + +def HSV_B : HStore_r<0b0110001, "hsv.b">, Sched<[]>; +def HSV_H : HStore_r<0b0110011, "hsv.h">, Sched<[]>; +def HSV_W : HStore_r<0b0110101, "hsv.w">, Sched<[]>; +let Predicates = [IsRV64] in +def HSV_D : HStore_r<0b0110111, "hsv.d">, Sched<[]>; + //===----------------------------------------------------------------------===// // Debug instructions //===----------------------------------------------------------------------===// diff --git a/llvm/lib/Target/RISCV/RISCVInstrInfoA.td b/llvm/lib/Target/RISCV/RISCVInstrInfoA.td --- a/llvm/lib/Target/RISCV/RISCVInstrInfoA.td +++ b/llvm/lib/Target/RISCV/RISCVInstrInfoA.td @@ -11,24 +11,6 @@ // //===----------------------------------------------------------------------===// -//===----------------------------------------------------------------------===// -// Operand and SDNode transformation definitions. -//===----------------------------------------------------------------------===// - -// A parse method for (${gpr}) or 0(${gpr}), where the 0 is be silently ignored. -// Used for GNU as Compatibility. -def AtomicMemOpOperand : AsmOperandClass { - let Name = "AtomicMemOpOperand"; - let RenderMethod = "addRegOperands"; - let PredicateMethod = "isGPR"; - let ParserMethod = "parseAtomicMemOp"; -} - -def GPRMemAtomic : RegisterOperand { - let ParserMatchClass = AtomicMemOpOperand; - let PrintMethod = "printAtomicMemOp"; -} - //===----------------------------------------------------------------------===// // Instruction class templates //===----------------------------------------------------------------------===// @@ -36,7 +18,7 @@ let hasSideEffects = 0, mayLoad = 1, mayStore = 0 in class LR_r funct3, string opcodestr> : RVInstRAtomic<0b00010, aq, rl, funct3, OPC_AMO, - (outs GPR:$rd), (ins GPRMemAtomic:$rs1), + (outs GPR:$rd), (ins GPRMemZeroOffset:$rs1), opcodestr, "$rd, $rs1"> { let rs2 = 0; } @@ -51,7 +33,7 @@ let hasSideEffects = 0, mayLoad = 1, mayStore = 1 in class AMO_rr funct5, bit aq, bit rl, bits<3> funct3, string opcodestr> : RVInstRAtomic; multiclass AMO_rr_aq_rl funct5, bits<3> funct3, string opcodestr> { diff --git a/llvm/test/MC/RISCV/priv-aliases-valid.s b/llvm/test/MC/RISCV/priv-aliases-valid.s new file mode 100644 --- /dev/null +++ b/llvm/test/MC/RISCV/priv-aliases-valid.s @@ -0,0 +1,50 @@ +# RUN: llvm-mc %s -triple=riscv32 -riscv-no-aliases -show-encoding \ +# RUN: | FileCheck -check-prefixes=CHECK,CHECK-INST %s +# RUN: llvm-mc %s -triple=riscv64 -riscv-no-aliases -show-encoding \ +# RUN: | FileCheck -check-prefixes=CHECK,CHECK-INST %s +# RUN: llvm-mc -filetype=obj -triple riscv32 < %s \ +# RUN: | llvm-objdump -M no-aliases -d - \ +# RUN: | FileCheck -check-prefix=CHECK-INST %s +# RUN: llvm-mc -filetype=obj -triple riscv64 < %s \ +# RUN: | llvm-objdump -M no-aliases -d - \ +# RUN: | FileCheck -check-prefix=CHECK-INST %s + +# CHECK-INST: hlv.b a0, (a1) +# CHECK: encoding: [0x73,0xc5,0x05,0x60] +hlv.b a0, 0(a1) + +# CHECK-INST: hlv.bu a0, (a1) +# CHECK: encoding: [0x73,0xc5,0x15,0x60] +hlv.bu a0, 0(a1) + +# CHECK-INST: hlv.h a1, (a2) +# CHECK: encoding: [0xf3,0x45,0x06,0x64] +hlv.h a1, 0(a2) + +# CHECK-INST: hlv.hu a1, (a1) +# CHECK: encoding: [0xf3,0xc5,0x15,0x64] +hlv.hu a1, 0(a1) + +# CHECK-INST: hlvx.hu a1, (a2) +# CHECK: encoding: [0xf3,0x45,0x36,0x64] +hlvx.hu a1, 0(a2) + +# CHECK-INST: hlv.w a2, (a2) +# CHECK: encoding: [0x73,0x46,0x06,0x68] +hlv.w a2, 0(a2) + +# CHECK-INST: hlvx.wu a2, (a3) +# CHECK: encoding: [0x73,0xc6,0x36,0x68] +hlvx.wu a2, 0(a3) + +# CHECK-INST: hsv.b a0, (a1) +# CHECK: encoding: [0x73,0xc0,0xa5,0x62] +hsv.b a0, 0(a1) + +# CHECK-INST: hsv.h a0, (a1) +# CHECK: encoding: [0x73,0xc0,0xa5,0x66] +hsv.h a0, 0(a1) + +# CHECK-INST: hsv.w a0, (a1) +# CHECK: encoding: [0x73,0xc0,0xa5,0x6a] +hsv.w a0, 0(a1) diff --git a/llvm/test/MC/RISCV/priv-invalid.s b/llvm/test/MC/RISCV/priv-invalid.s --- a/llvm/test/MC/RISCV/priv-invalid.s +++ b/llvm/test/MC/RISCV/priv-invalid.s @@ -1,4 +1,4 @@ -# RUN: not llvm-mc -triple riscv32 < %s 2>&1 | FileCheck %s +# RUN: not llvm-mc -triple riscv64 < %s 2>&1 | FileCheck %s mret 0x10 # CHECK: :[[@LINE]]:6: error: invalid operand for instruction @@ -29,3 +29,81 @@ hinval.gvma zero, a1, a2 # CHECK: :[[@LINE]]:23: error: invalid operand for instruction hinval.gvma a0, 0x10 # CHECK: :[[@LINE]]:17: error: invalid operand for instruction + +hlv.b a0, 0x10 # CHECK: :[[@LINE]]:16: error: expected '(' after optional integer offset + +hlv.b a0, a1 # CHECK: :[[@LINE]]:11: error: expected '(' or optional integer offset + +hlv.b a0, 1(a1) # CHECK: :[[@LINE]]:11: error: optional integer offset must be 0 + +hlv.bu a0, 0x10 # CHECK: :[[@LINE]]:17: error: expected '(' after optional integer offset + +hlv.bu a0, a1 # CHECK: :[[@LINE]]:12: error: expected '(' or optional integer offset + +hlv.bu a0, 1(a1) # CHECK: :[[@LINE]]:12: error: optional integer offset must be 0 + +hlv.h a0, 0x10 # CHECK: :[[@LINE]]:16: error: expected '(' after optional integer offset + +hlv.h a0, a1 # CHECK: :[[@LINE]]:11: error: expected '(' or optional integer offset + +hlv.h a0, 1(a1) # CHECK: :[[@LINE]]:11: error: optional integer offset must be 0 + +hlv.hu a0, 0x10 # CHECK: :[[@LINE]]:17: error: expected '(' after optional integer offset + +hlv.hu a0, a1 # CHECK: :[[@LINE]]:12: error: expected '(' or optional integer offset + +hlv.hu a0, 1(a1) # CHECK: :[[@LINE]]:12: error: optional integer offset must be 0 + +hlvx.hu a0, 0x10 # CHECK: :[[@LINE]]:18: error: expected '(' after optional integer offset + +hlvx.hu a0, a1 # CHECK: :[[@LINE]]:13: error: expected '(' or optional integer offset + +hlvx.hu a0, 1(a1) # CHECK: :[[@LINE]]:13: error: optional integer offset must be 0 + +hlv.w a0, 0x10 # CHECK: :[[@LINE]]:16: error: expected '(' after optional integer offset + +hlv.w a0, a1 # CHECK: :[[@LINE]]:11: error: expected '(' or optional integer offset + +hlv.w a0, 1(a1) # CHECK: :[[@LINE]]:11: error: optional integer offset must be 0 + +hlv.wu a0, 0x10 # CHECK: :[[@LINE]]:17: error: expected '(' after optional integer offset + +hlv.wu a0, a1 # CHECK: :[[@LINE]]:12: error: expected '(' or optional integer offset + +hlv.wu a0, 1(a1) # CHECK: :[[@LINE]]:12: error: optional integer offset must be 0 + +hlvx.wu a0, 0x10 # CHECK: :[[@LINE]]:18: error: expected '(' after optional integer offset + +hlvx.wu a0, a1 # CHECK: :[[@LINE]]:13: error: expected '(' or optional integer offset + +hlvx.wu a0, 1(a1) # CHECK: :[[@LINE]]:13: error: optional integer offset must be 0 + +hlv.d a0, 0x10 # CHECK: :[[@LINE]]:16: error: expected '(' after optional integer offset + +hlv.d a0, a1 # CHECK: :[[@LINE]]:11: error: expected '(' or optional integer offset + +hlv.d a0, 1(a1) # CHECK: :[[@LINE]]:11: error: optional integer offset must be 0 + +hsv.b a0, 0x10 # CHECK: :[[@LINE]]:16: error: expected '(' after optional integer offset + +hsv.b a0, a1 # CHECK: :[[@LINE]]:11: error: expected '(' or optional integer offset + +hsv.b a0, 1(a1) # CHECK: :[[@LINE]]:11: error: optional integer offset must be 0 + +hsv.h a0, 0x10 # CHECK: :[[@LINE]]:16: error: expected '(' after optional integer offset + +hsv.h a0, a1 # CHECK: :[[@LINE]]:11: error: expected '(' or optional integer offset + +hsv.h a0, 1(a1) # CHECK: :[[@LINE]]:11: error: optional integer offset must be 0 + +hsv.w a0, 0x10 # CHECK: :[[@LINE]]:16: error: expected '(' after optional integer offset + +hsv.w a0, a1 # CHECK: :[[@LINE]]:11: error: expected '(' or optional integer offset + +hsv.w a0, 1(a1) # CHECK: :[[@LINE]]:11: error: optional integer offset must be 0 + +hsv.d a0, 0x10 # CHECK: :[[@LINE]]:16: error: expected '(' after optional integer offset + +hsv.d a0, a1 # CHECK: :[[@LINE]]:11: error: expected '(' or optional integer offset + +hsv.d a0, 1(a1) # CHECK: :[[@LINE]]:11: error: optional integer offset must be 0 diff --git a/llvm/test/MC/RISCV/priv-rv64-valid.s b/llvm/test/MC/RISCV/priv-rv64-valid.s new file mode 100644 --- /dev/null +++ b/llvm/test/MC/RISCV/priv-rv64-valid.s @@ -0,0 +1,29 @@ +# RUN: llvm-mc %s -triple=riscv64 -riscv-no-aliases -show-encoding \ +# RUN: | FileCheck -check-prefixes=CHECK,CHECK-INST %s +# RUN: llvm-mc -filetype=obj -triple riscv64 < %s \ +# RUN: | llvm-objdump -M no-aliases -d - \ +# RUN: | FileCheck -check-prefix=CHECK-INST %s + +# CHECK-INST: hlv.wu a0, (a1) +# CHECK: encoding: [0x73,0xc5,0x15,0x68] +hlv.wu a0, (a1) + +# CHECK-INST: hlv.wu a0, (a1) +# CHECK: encoding: [0x73,0xc5,0x15,0x68] +hlv.wu a0, 0(a1) + +# CHECK-INST: hlv.d a0, (a1) +# CHECK: encoding: [0x73,0xc5,0x05,0x6c] +hlv.d a0, (a1) + +# CHECK-INST: hlv.d a0, (a1) +# CHECK: encoding: [0x73,0xc5,0x05,0x6c] +hlv.d a0, 0(a1) + +# CHECK-INST: hsv.d a0, (a1) +# CHECK: encoding: [0x73,0xc0,0xa5,0x6e] +hsv.d a0, (a1) + +# CHECK-INST: hsv.d a0, (a1) +# CHECK: encoding: [0x73,0xc0,0xa5,0x6e] +hsv.d a0, 0(a1) diff --git a/llvm/test/MC/RISCV/priv-valid.s b/llvm/test/MC/RISCV/priv-valid.s --- a/llvm/test/MC/RISCV/priv-valid.s +++ b/llvm/test/MC/RISCV/priv-valid.s @@ -76,3 +76,43 @@ # CHECK-INST: hinval.gvma a0, a1 # CHECK: encoding: [0x73,0x00,0xb5,0x66] hinval.gvma a0, a1 + +# CHECK-INST: hlv.b a0, (a1) +# CHECK: encoding: [0x73,0xc5,0x05,0x60] +hlv.b a0, (a1) + +# CHECK-INST: hlv.bu a0, (a1) +# CHECK: encoding: [0x73,0xc5,0x15,0x60] +hlv.bu a0, (a1) + +# CHECK-INST: hlv.h a1, (a2) +# CHECK: encoding: [0xf3,0x45,0x06,0x64] +hlv.h a1, (a2) + +# CHECK-INST: hlv.hu a1, (a1) +# CHECK: encoding: [0xf3,0xc5,0x15,0x64] +hlv.hu a1, (a1) + +# CHECK-INST: hlvx.hu a1, (a2) +# CHECK: encoding: [0xf3,0x45,0x36,0x64] +hlvx.hu a1, (a2) + +# CHECK-INST: hlv.w a2, (a2) +# CHECK: encoding: [0x73,0x46,0x06,0x68] +hlv.w a2, (a2) + +# CHECK-INST: hlvx.wu a2, (a3) +# CHECK: encoding: [0x73,0xc6,0x36,0x68] +hlvx.wu a2, (a3) + +# CHECK-INST: hsv.b a0, (a1) +# CHECK: encoding: [0x73,0xc0,0xa5,0x62] +hsv.b a0, (a1) + +# CHECK-INST: hsv.h a0, (a1) +# CHECK: encoding: [0x73,0xc0,0xa5,0x66] +hsv.h a0, (a1) + +# CHECK-INST: hsv.w a0, (a1) +# CHECK: encoding: [0x73,0xc0,0xa5,0x6a] +hsv.w a0, (a1)