addExpr(Inst, getImm());
}
- void addSImm5Plus1Operands(MCInst &Inst, unsigned N) const {
- assert(N == 1 && "Invalid number of operands!");
- int64_t Imm = 0;
- RISCVMCExpr::VariantKind VK = RISCVMCExpr::VK_RISCV_None;
- bool IsConstant = evaluateConstantImm(getImm(), Imm, VK);
- assert(IsConstant && "Expect constant value!");
- (void)IsConstant;
- Inst.addOperand(MCOperand::createImm(Imm - 1));
- }
-
void addFenceArgOperands(MCInst &Inst, unsigned N) const {
assert(N == 1 && "Invalid number of operands!");
// isFenceArg has validated the operand, meaning this cast is safe
case RISCV::PseudoVMSGE_VX_M_T:
emitVMSGE(Inst, RISCV::VMSLT_VX, IDLoc, Out);
return false;
+ case RISCV::PseudoVMSGE_VI:
+ case RISCV::PseudoVMSLT_VI: {
+ // These instructions are signed and so is immediate so we can subtract one
+ // and change the opcode.
+ int64_t Imm = Inst.getOperand(2).getImm();
+ unsigned Opc = Inst.getOpcode() == RISCV::PseudoVMSGE_VI ? RISCV::VMSGT_VI
+ : RISCV::VMSLE_VI;
+ emitToStreamer(Out, MCInstBuilder(Opc)
+ .addOperand(Inst.getOperand(0))
+ .addOperand(Inst.getOperand(1))
+ .addImm(Imm - 1)
+ .addOperand(Inst.getOperand(3)));
+ return false;
+ }
+ case RISCV::PseudoVMSGEU_VI:
+ case RISCV::PseudoVMSLTU_VI: {
+ int64_t Imm = Inst.getOperand(2).getImm();
+ // Unsigned comparisons are tricky because the immediate is signed. If the
+ // immediate is 0 we can't just subtract one. vmsltu.vi v0, v1, 0 is always
+ // false, but vmsle.vi v0, v1, -1 is always true. Instead we use
+ // vmsne v0, v1, v1 which is always false.
+ if (Imm == 0) {
+ unsigned Opc = Inst.getOpcode() == RISCV::PseudoVMSGEU_VI
+ ? RISCV::VMSEQ_VV
+ : RISCV::VMSNE_VV;
+ emitToStreamer(Out, MCInstBuilder(Opc)
+ .addOperand(Inst.getOperand(0))
+ .addOperand(Inst.getOperand(1))
+ .addOperand(Inst.getOperand(1))
+ .addOperand(Inst.getOperand(3)));
+ } else {
+ // Other immediate values can subtract one like signed.
+ unsigned Opc = Inst.getOpcode() == RISCV::PseudoVMSGEU_VI
+ ? RISCV::VMSGTU_VI
+ : RISCV::VMSLEU_VI;
+ emitToStreamer(Out, MCInstBuilder(Opc)
+ .addOperand(Inst.getOperand(0))
+ .addOperand(Inst.getOperand(1))
+ .addImm(Imm - 1)
+ .addOperand(Inst.getOperand(3)));
+ }
+
+ return false;
+ }
}
emitToStreamer(Out, Inst);
def SImm5Plus1AsmOperand : AsmOperandClass {
let Name = "SImm5Plus1";
- let RenderMethod = "addSImm5Plus1Operands";
+ let RenderMethod = "addImmOperands";
let DiagnosticType = "InvalidSImm5Plus1";
}
(VMSLEU_VV VR:$vd, VR:$vb, VR:$va, VMaskOp:$vm), 0>;
def : InstAlias<"vmsge.vv $vd, $va, $vb$vm",
(VMSLE_VV VR:$vd, VR:$vb, VR:$va, VMaskOp:$vm), 0>;
-def : InstAlias<"vmsltu.vi $vd, $va, $imm$vm",
- (VMSLEU_VI VR:$vd, VR:$va, simm5_plus1:$imm,
- VMaskOp:$vm), 0>;
-def : InstAlias<"vmslt.vi $vd, $va, $imm$vm",
- (VMSLE_VI VR:$vd, VR:$va, simm5_plus1:$imm,
- VMaskOp:$vm), 0>;
-def : InstAlias<"vmsgeu.vi $vd, $va, $imm$vm",
- (VMSGTU_VI VR:$vd, VR:$va, simm5_plus1:$imm,
- VMaskOp:$vm), 0>;
-def : InstAlias<"vmsge.vi $vd, $va, $imm$vm",
- (VMSGT_VI VR:$vd, VR:$va, simm5_plus1:$imm,
- VMaskOp:$vm), 0>;
+
+let isCodeGenOnly = 0, isAsmParserOnly = 1, hasSideEffects = 0, mayLoad = 0,
+ mayStore = 0 in {
+// For unsigned comparisons we need to special case 0 immediate to maintain
+// the always true/false semantics we would invert if we just decremented the
+// immediate like we do for signed. To match the GNU assembler we will use
+// vmseq/vmsne.vv with the same register for both operands which we can't do
+// from an InstAlias.
+def PseudoVMSGEU_VI : Pseudo<(outs VR:$vd),
+ (ins VR:$vs2, simm5_plus1:$imm, VMaskOp:$vm),
+ [], "vmsgeu.vi", "$vd, $vs2, $imm$vm">;
+def PseudoVMSLTU_VI : Pseudo<(outs VR:$vd),
+ (ins VR:$vs2, simm5_plus1:$imm, VMaskOp:$vm),
+ [], "vmsltu.vi", "$vd, $vs2, $imm$vm">;
+// Handle signed with pseudos as well for more consistency in the
+// implementation.
+def PseudoVMSGE_VI : Pseudo<(outs VR:$vd),
+ (ins VR:$vs2, simm5_plus1:$imm, VMaskOp:$vm),
+ [], "vmsge.vi", "$vd, $vs2, $imm$vm">;
+def PseudoVMSLT_VI : Pseudo<(outs VR:$vd),
+ (ins VR:$vs2, simm5_plus1:$imm, VMaskOp:$vm),
+ [], "vmslt.vi", "$vd, $vs2, $imm$vm">;
+}
let isAsmParserOnly = 1, hasSideEffects = 0, mayLoad = 0, mayStore = 0 in {
def PseudoVMSGEU_VX : Pseudo<(outs VR:$vd),
# CHECK-ERROR: instruction requires the following: 'V' (Vector Instructions)
# CHECK-UNKNOWN: 57 b4 47 72 <unknown>
+vmsltu.vi v8, v4, 0, v0.t
+# CHECK-INST: vmsne.vv v8, v4, v4, v0.t
+# CHECK-ENCODING: [0x57,0x04,0x42,0x64]
+# CHECK-ERROR: instruction requires the following: 'V' (Vector Instructions)
+# CHECK-UNKNOWN: 57 04 42 64 <unknown>
+
+vmsltu.vi v8, v4, 0
+# CHECK-INST: vmsne.vv v8, v4, v4
+# CHECK-ENCODING: [0x57,0x04,0x42,0x66]
+# CHECK-ERROR: instruction requires the following: 'V' (Vector Instructions)
+# CHECK-UNKNOWN: 57 04 42 66 <unknown>
+
vmslt.vi v8, v4, 16, v0.t
# CHECK-INST: vmsle.vi v8, v4, 15, v0.t
# CHECK-ENCODING: [0x57,0xb4,0x47,0x74]
# CHECK-ERROR: instruction requires the following: 'V' (Vector Instructions)
# CHECK-UNKNOWN: 57 b4 47 7a <unknown>
+vmsgeu.vi v8, v4, 0, v0.t
+# CHECK-INST: vmseq.vv v8, v4, v4, v0.t
+# CHECK-ENCODING: [0x57,0x04,0x42,0x60]
+# CHECK-ERROR: instruction requires the following: 'V' (Vector Instructions)
+# CHECK-UNKNOWN: 57 04 42 60 <unknown>
+
+vmsgeu.vi v8, v4, 0
+# CHECK-INST: vmseq.vv v8, v4, v4
+# CHECK-ENCODING: [0x57,0x04,0x42,0x62]
+# CHECK-ERROR: instruction requires the following: 'V' (Vector Instructions)
+# CHECK-UNKNOWN: 57 04 42 62 <unknown>
+
vmsge.vi v8, v4, 16, v0.t
# CHECK-INST: vmsgt.vi v8, v4, 15, v0.t
# CHECK-ENCODING: [0x57,0xb4,0x47,0x7c]