mirror of
https://github.com/RPCS3/llvm-mirror.git
synced 2024-11-24 03:33:20 +01:00
[RISCV] MC layer support for the standard RV32D instruction set extension
As the FPR32 and FPR64 registers have the same names, use validateTargetOperandClass in RISCVAsmParser to coerce a parsed FPR32 to an FPR64 when necessary. The rest of this patch is very similar to the RV32F patch. Differential Revision: https://reviews.llvm.org/D39895 llvm-svn: 320023
This commit is contained in:
parent
a2d7c39420
commit
e4dd444e6f
@ -32,6 +32,9 @@ struct RISCVOperand;
|
||||
class RISCVAsmParser : public MCTargetAsmParser {
|
||||
SMLoc getLoc() const { return getParser().getTok().getLoc(); }
|
||||
|
||||
unsigned validateTargetOperandClass(MCParsedAsmOperand &Op,
|
||||
unsigned Kind) override;
|
||||
|
||||
bool generateImmOutOfRangeError(OperandVector &Operands, uint64_t ErrorInfo,
|
||||
int Lower, int Upper, Twine Msg);
|
||||
|
||||
@ -381,6 +384,67 @@ public:
|
||||
#define GET_MATCHER_IMPLEMENTATION
|
||||
#include "RISCVGenAsmMatcher.inc"
|
||||
|
||||
// Return the matching FPR64 register for the given FPR32.
|
||||
// FIXME: Ideally this function could be removed in favour of using
|
||||
// information from TableGen.
|
||||
unsigned convertFPR32ToFPR64(unsigned Reg) {
|
||||
switch (Reg) {
|
||||
default:
|
||||
llvm_unreachable("Not a recognised FPR32 register");
|
||||
case RISCV::F0_32: return RISCV::F0_64;
|
||||
case RISCV::F1_32: return RISCV::F1_64;
|
||||
case RISCV::F2_32: return RISCV::F2_64;
|
||||
case RISCV::F3_32: return RISCV::F3_64;
|
||||
case RISCV::F4_32: return RISCV::F4_64;
|
||||
case RISCV::F5_32: return RISCV::F5_64;
|
||||
case RISCV::F6_32: return RISCV::F6_64;
|
||||
case RISCV::F7_32: return RISCV::F7_64;
|
||||
case RISCV::F8_32: return RISCV::F8_64;
|
||||
case RISCV::F9_32: return RISCV::F9_64;
|
||||
case RISCV::F10_32: return RISCV::F10_64;
|
||||
case RISCV::F11_32: return RISCV::F11_64;
|
||||
case RISCV::F12_32: return RISCV::F12_64;
|
||||
case RISCV::F13_32: return RISCV::F13_64;
|
||||
case RISCV::F14_32: return RISCV::F14_64;
|
||||
case RISCV::F15_32: return RISCV::F15_64;
|
||||
case RISCV::F16_32: return RISCV::F16_64;
|
||||
case RISCV::F17_32: return RISCV::F17_64;
|
||||
case RISCV::F18_32: return RISCV::F18_64;
|
||||
case RISCV::F19_32: return RISCV::F19_64;
|
||||
case RISCV::F20_32: return RISCV::F20_64;
|
||||
case RISCV::F21_32: return RISCV::F21_64;
|
||||
case RISCV::F22_32: return RISCV::F22_64;
|
||||
case RISCV::F23_32: return RISCV::F23_64;
|
||||
case RISCV::F24_32: return RISCV::F24_64;
|
||||
case RISCV::F25_32: return RISCV::F25_64;
|
||||
case RISCV::F26_32: return RISCV::F26_64;
|
||||
case RISCV::F27_32: return RISCV::F27_64;
|
||||
case RISCV::F28_32: return RISCV::F28_64;
|
||||
case RISCV::F29_32: return RISCV::F29_64;
|
||||
case RISCV::F30_32: return RISCV::F30_64;
|
||||
case RISCV::F31_32: return RISCV::F31_64;
|
||||
}
|
||||
}
|
||||
|
||||
unsigned RISCVAsmParser::validateTargetOperandClass(MCParsedAsmOperand &AsmOp,
|
||||
unsigned Kind) {
|
||||
RISCVOperand &Op = static_cast<RISCVOperand &>(AsmOp);
|
||||
if (!Op.isReg())
|
||||
return Match_InvalidOperand;
|
||||
|
||||
unsigned Reg = Op.getReg();
|
||||
bool IsRegFPR32 =
|
||||
RISCVMCRegisterClasses[RISCV::FPR32RegClassID].contains(Reg);
|
||||
|
||||
// As the parser couldn't differentiate an FPR32 from an FPR64, coerce the
|
||||
// register from FPR32 to FPR64 if necessary.
|
||||
if (IsRegFPR32 && Kind == MCK_FPR64) {
|
||||
Op.Reg.RegNum = convertFPR32ToFPR64(Reg);
|
||||
return Match_Success;
|
||||
}
|
||||
return Match_InvalidOperand;
|
||||
}
|
||||
|
||||
bool RISCVAsmParser::generateImmOutOfRangeError(
|
||||
OperandVector &Operands, uint64_t ErrorInfo, int Lower, int Upper,
|
||||
Twine Msg = "immediate must be an integer in the range") {
|
||||
|
@ -105,6 +105,31 @@ static DecodeStatus DecodeFPR32RegisterClass(MCInst &Inst, uint64_t RegNo,
|
||||
return MCDisassembler::Success;
|
||||
}
|
||||
|
||||
static const unsigned FPR64DecoderTable[] = {
|
||||
RISCV::F0_64, RISCV::F1_64, RISCV::F2_64, RISCV::F3_64,
|
||||
RISCV::F4_64, RISCV::F5_64, RISCV::F6_64, RISCV::F7_64,
|
||||
RISCV::F8_64, RISCV::F9_64, RISCV::F10_64, RISCV::F11_64,
|
||||
RISCV::F12_64, RISCV::F13_64, RISCV::F14_64, RISCV::F15_64,
|
||||
RISCV::F16_64, RISCV::F17_64, RISCV::F18_64, RISCV::F19_64,
|
||||
RISCV::F20_64, RISCV::F21_64, RISCV::F22_64, RISCV::F23_64,
|
||||
RISCV::F24_64, RISCV::F25_64, RISCV::F26_64, RISCV::F27_64,
|
||||
RISCV::F28_64, RISCV::F29_64, RISCV::F30_64, RISCV::F31_64
|
||||
};
|
||||
|
||||
static DecodeStatus DecodeFPR64RegisterClass(MCInst &Inst, uint64_t RegNo,
|
||||
uint64_t Address,
|
||||
const void *Decoder) {
|
||||
if (RegNo > sizeof(FPR64DecoderTable))
|
||||
return MCDisassembler::Fail;
|
||||
|
||||
// We must define our own mapping from RegNo to register identifier.
|
||||
// Accessing index RegNo in the register class will work in the case that
|
||||
// registers were added in ascending order, but not in general.
|
||||
unsigned Reg = FPR64DecoderTable[RegNo];
|
||||
Inst.addOperand(MCOperand::createReg(Reg));
|
||||
return MCDisassembler::Success;
|
||||
}
|
||||
|
||||
template <unsigned N>
|
||||
static DecodeStatus decodeUImmOperand(MCInst &Inst, uint64_t Imm,
|
||||
int64_t Address, const void *Decoder) {
|
||||
|
@ -31,6 +31,13 @@ def FeatureStdExtF
|
||||
def HasStdExtF : Predicate<"Subtarget->hasStdExtF()">,
|
||||
AssemblerPredicate<"FeatureStdExtF">;
|
||||
|
||||
def FeatureStdExtD
|
||||
: SubtargetFeature<"d", "HasStdExtD", "true",
|
||||
"'D' (Double-Precision Floating-Point)",
|
||||
[FeatureStdExtF]>;
|
||||
def HasStdExtD : Predicate<"Subtarget->hasStdExtD()">,
|
||||
AssemblerPredicate<"FeatureStdExtD">;
|
||||
|
||||
def Feature64Bit
|
||||
: SubtargetFeature<"64bit", "HasRV64", "true", "Implements RV64">;
|
||||
|
||||
@ -63,6 +70,7 @@ def RISCVInstrInfo : InstrInfo {
|
||||
|
||||
def RISCVAsmParser : AsmParser {
|
||||
let ShouldEmitMatchRegisterAltName = 1;
|
||||
let AllowDuplicateRegisterNames = 1;
|
||||
}
|
||||
|
||||
def RISCV : Target {
|
||||
|
@ -442,3 +442,4 @@ def ADJCALLSTACKUP : Pseudo<(outs), (ins i32imm:$amt1, i32imm:$amt2),
|
||||
include "RISCVInstrInfoM.td"
|
||||
include "RISCVInstrInfoA.td"
|
||||
include "RISCVInstrInfoF.td"
|
||||
include "RISCVInstrInfoD.td"
|
||||
|
131
lib/Target/RISCV/RISCVInstrInfoD.td
Normal file
131
lib/Target/RISCV/RISCVInstrInfoD.td
Normal file
@ -0,0 +1,131 @@
|
||||
//===-- RISCVInstrInfoD.td - RISC-V 'D' instructions -------*- tablegen -*-===//
|
||||
//
|
||||
// The LLVM Compiler Infrastructure
|
||||
//
|
||||
// This file is distributed under the University of Illinois Open Source
|
||||
// License. See LICENSE.TXT for details.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// This file describes the RISC-V instructions from the standard 'D',
|
||||
// Double-Precision Floating-Point instruction set extension.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
//===----------------------------------------------------------------------===//
|
||||
// Instruction Class Templates
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
let hasSideEffects = 0, mayLoad = 0, mayStore = 0 in
|
||||
class FPFMAD_rrr_frm<RISCVOpcode opcode, string opcodestr>
|
||||
: RVInstR4<0b01, opcode, (outs FPR64:$rd),
|
||||
(ins FPR64:$rs1, FPR64:$rs2, FPR64:$rs3, frmarg:$funct3),
|
||||
opcodestr, "$rd, $rs1, $rs2, $rs3, $funct3">;
|
||||
|
||||
class FPFMADDynFrmAlias<FPFMAD_rrr_frm Inst, string OpcodeStr>
|
||||
: InstAlias<OpcodeStr#" $rd, $rs1, $rs2, $rs3",
|
||||
(Inst FPR64:$rd, FPR64:$rs1, FPR64:$rs2, FPR64:$rs3, 0b111)>;
|
||||
|
||||
let hasSideEffects = 0, mayLoad = 0, mayStore = 0 in
|
||||
class FPALUD_rr<bits<7> funct7, bits<3> funct3, string opcodestr>
|
||||
: RVInstR<funct7, funct3, OPC_OP_FP, (outs FPR64:$rd),
|
||||
(ins FPR64:$rs1, FPR64:$rs2), opcodestr, "$rd, $rs1, $rs2">;
|
||||
|
||||
let hasSideEffects = 0, mayLoad = 0, mayStore = 0 in
|
||||
class FPALUD_rr_frm<bits<7> funct7, string opcodestr>
|
||||
: RVInstRFrm<funct7, OPC_OP_FP, (outs FPR64:$rd),
|
||||
(ins FPR64:$rs1, FPR64:$rs2, frmarg:$funct3), opcodestr,
|
||||
"$rd, $rs1, $rs2, $funct3">;
|
||||
|
||||
class FPALUDDynFrmAlias<FPALUD_rr_frm Inst, string OpcodeStr>
|
||||
: InstAlias<OpcodeStr#" $rd, $rs1, $rs2",
|
||||
(Inst FPR64:$rd, FPR64:$rs1, FPR64:$rs2, 0b111)>;
|
||||
|
||||
let hasSideEffects = 0, mayLoad = 0, mayStore = 0 in
|
||||
class FPCmpD_rr<bits<3> funct3, string opcodestr>
|
||||
: RVInstR<0b1010001, funct3, OPC_OP_FP, (outs GPR:$rd),
|
||||
(ins FPR64:$rs1, FPR64:$rs2), opcodestr, "$rd, $rs1, $rs2">;
|
||||
|
||||
//===----------------------------------------------------------------------===//
|
||||
// Instructions
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
let Predicates = [HasStdExtD] in {
|
||||
|
||||
let hasSideEffects = 0, mayLoad = 1, mayStore = 0 in
|
||||
def FLD : RVInstI<0b011, OPC_LOAD_FP, (outs FPR64:$rd),
|
||||
(ins GPR:$rs1, simm12:$imm12),
|
||||
"fld", "$rd, ${imm12}(${rs1})">;
|
||||
|
||||
// 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
|
||||
def FSD : RVInstS<0b011, OPC_STORE_FP, (outs),
|
||||
(ins FPR64:$rs2, GPR:$rs1, simm12:$imm12),
|
||||
"fsd", "$rs2, ${imm12}(${rs1})">;
|
||||
|
||||
def FMADD_D : FPFMAD_rrr_frm<OPC_MADD, "fmadd.d">;
|
||||
def : FPFMADDynFrmAlias<FMADD_D, "fmadd.d">;
|
||||
def FMSUB_D : FPFMAD_rrr_frm<OPC_MSUB, "fmsub.d">;
|
||||
def : FPFMADDynFrmAlias<FMSUB_D, "fmsub.d">;
|
||||
def FNMSUB_D : FPFMAD_rrr_frm<OPC_NMSUB, "fnmsub.d">;
|
||||
def : FPFMADDynFrmAlias<FNMSUB_D, "fnmsub.d">;
|
||||
def FNMADD_D : FPFMAD_rrr_frm<OPC_NMADD, "fnmadd.d">;
|
||||
def : FPFMADDynFrmAlias<FNMADD_D, "fnmadd.d">;
|
||||
|
||||
def FADD_D : FPALUD_rr_frm<0b0000001, "fadd.d">;
|
||||
def : FPALUDDynFrmAlias<FADD_D, "fadd.d">;
|
||||
def FSUB_D : FPALUD_rr_frm<0b0000101, "fsub.d">;
|
||||
def : FPALUDDynFrmAlias<FSUB_D, "fsub.d">;
|
||||
def FMUL_D : FPALUD_rr_frm<0b0001001, "fmul.d">;
|
||||
def : FPALUDDynFrmAlias<FMUL_D, "fmul.d">;
|
||||
def FDIV_D : FPALUD_rr_frm<0b0001101, "fdiv.d">;
|
||||
def : FPALUDDynFrmAlias<FDIV_D, "fdiv.d">;
|
||||
|
||||
def FSQRT_D : FPUnaryOp_r_frm<0b0101101, FPR64, FPR64, "fsqrt.d"> {
|
||||
let rs2 = 0b00000;
|
||||
}
|
||||
def : FPUnaryOpDynFrmAlias<FSQRT_D, "fsqrt.d", FPR64, FPR64>;
|
||||
|
||||
def FSGNJ_D : FPALUD_rr<0b0010001, 0b000, "fsgnj.d">;
|
||||
def FSGNJN_D : FPALUD_rr<0b0010001, 0b001, "fsgnjn.d">;
|
||||
def FSGNJX_D : FPALUD_rr<0b0010001, 0b010, "fsgnjx.d">;
|
||||
def FMIN_D : FPALUD_rr<0b0010101, 0b000, "fmin.d">;
|
||||
def FMAX_D : FPALUD_rr<0b0010101, 0b001, "fmax.d">;
|
||||
|
||||
def FCVT_S_D : FPUnaryOp_r_frm<0b0100000, FPR32, FPR64, "fcvt.s.d"> {
|
||||
let rs2 = 0b00001;
|
||||
}
|
||||
def : FPUnaryOpDynFrmAlias<FCVT_S_D, "fcvt.s.d", FPR32, FPR64>;
|
||||
|
||||
def FCVT_D_S : FPUnaryOp_r<0b0100001, 0b000, FPR64, FPR32, "fcvt.d.s"> {
|
||||
let rs2 = 0b00000;
|
||||
}
|
||||
|
||||
def FEQ_D : FPCmpD_rr<0b010, "feq.d">;
|
||||
def FLT_D : FPCmpD_rr<0b001, "flt.d">;
|
||||
def FLE_D : FPCmpD_rr<0b000, "fle.d">;
|
||||
|
||||
def FCLASS_D : FPUnaryOp_r<0b1110001, 0b001, GPR, FPR64, "fclass.d"> {
|
||||
let rs2 = 0b00000;
|
||||
}
|
||||
|
||||
def FCVT_W_D : FPUnaryOp_r_frm<0b1100001, GPR, FPR64, "fcvt.w.d"> {
|
||||
let rs2 = 0b00000;
|
||||
}
|
||||
def : FPUnaryOpDynFrmAlias<FCVT_W_D, "fcvt.w.d", GPR, FPR64>;
|
||||
|
||||
def FCVT_WU_D : FPUnaryOp_r_frm<0b1100001, GPR, FPR64, "fcvt.wu.d"> {
|
||||
let rs2 = 0b00001;
|
||||
}
|
||||
def : FPUnaryOpDynFrmAlias<FCVT_WU_D, "fcvt.wu.d", GPR, FPR64>;
|
||||
|
||||
def FCVT_D_W : FPUnaryOp_r<0b1101001, 0b000, FPR64, GPR, "fcvt.d.w"> {
|
||||
let rs2 = 0b00000;
|
||||
}
|
||||
|
||||
def FCVT_D_WU : FPUnaryOp_r<0b1101001, 0b000, FPR64, GPR, "fcvt.d.wu"> {
|
||||
let rs2 = 0b00001;
|
||||
}
|
||||
} // Predicates = [HasStdExtD]
|
@ -22,6 +22,18 @@ class RISCVReg32<bits<5> Enc, string n, list<string> alt = []> : Register<n> {
|
||||
let AltNames = alt;
|
||||
}
|
||||
|
||||
// Because RISCVReg64 register have AsmName and AltNames that alias with their
|
||||
// 32-bit sub-register, RISCVAsmParser will need to coerce a register number
|
||||
// from a RISCVReg32 to the equivalent RISCVReg64 when appropriate.
|
||||
def sub_32 : SubRegIndex<32>;
|
||||
class RISCVReg64<RISCVReg32 subreg> : Register<""> {
|
||||
let HWEncoding{4-0} = subreg.HWEncoding{4-0};
|
||||
let SubRegs = [subreg];
|
||||
let SubRegIndices = [sub_32];
|
||||
let AsmName = subreg.AsmName;
|
||||
let AltNames = subreg.AltNames;
|
||||
}
|
||||
|
||||
def ABIRegAltName : RegAltNameIndex;
|
||||
} // Namespace = "RISCV"
|
||||
|
||||
@ -113,6 +125,11 @@ let RegAltNameIndices = [ABIRegAltName] in {
|
||||
def F29_32 : RISCVReg32<29,"f29", ["ft9"]>, DwarfRegNum<[61]>;
|
||||
def F30_32 : RISCVReg32<30,"f30", ["ft10"]>, DwarfRegNum<[62]>;
|
||||
def F31_32 : RISCVReg32<31,"f31", ["ft11"]>, DwarfRegNum<[63]>;
|
||||
|
||||
foreach Index = 0-31 in {
|
||||
def F#Index#_64 : RISCVReg64<!cast<RISCVReg32>("F"#Index#"_32")>,
|
||||
DwarfRegNum<[!add(Index, 32)]>;
|
||||
}
|
||||
}
|
||||
|
||||
// The order of registers represents the preferred allocation sequence,
|
||||
@ -124,3 +141,13 @@ def FPR32 : RegisterClass<"RISCV", [f32], 32, (add
|
||||
(sequence "F%u_32", 8, 9),
|
||||
(sequence "F%u_32", 18, 27)
|
||||
)>;
|
||||
|
||||
// The order of registers represents the preferred allocation sequence,
|
||||
// meaning caller-save regs are listed before callee-save.
|
||||
def FPR64 : RegisterClass<"RISCV", [f64], 64, (add
|
||||
(sequence "F%u_64", 0, 7),
|
||||
(sequence "F%u_64", 10, 17),
|
||||
(sequence "F%u_64", 28, 31),
|
||||
(sequence "F%u_64", 8, 9),
|
||||
(sequence "F%u_64", 18, 27)
|
||||
)>;
|
||||
|
@ -33,6 +33,7 @@ class RISCVSubtarget : public RISCVGenSubtargetInfo {
|
||||
bool HasStdExtM = false;
|
||||
bool HasStdExtA = false;
|
||||
bool HasStdExtF = false;
|
||||
bool HasStdExtD = false;
|
||||
bool HasRV64 = false;
|
||||
unsigned XLen = 32;
|
||||
MVT XLenVT = MVT::i32;
|
||||
@ -72,6 +73,7 @@ public:
|
||||
bool hasStdExtM() const { return HasStdExtM; }
|
||||
bool hasStdExtA() const { return HasStdExtA; }
|
||||
bool hasStdExtF() const { return HasStdExtF; }
|
||||
bool hasStdExtD() const { return HasStdExtD; }
|
||||
bool is64Bit() const { return HasRV64; }
|
||||
MVT getXLenVT() const { return XLenVT; }
|
||||
unsigned getXLen() const { return XLen; }
|
||||
|
21
test/MC/RISCV/rv32d-invalid.s
Normal file
21
test/MC/RISCV/rv32d-invalid.s
Normal file
@ -0,0 +1,21 @@
|
||||
# RUN: not llvm-mc -triple riscv32 -mattr=+d < %s 2>&1 | FileCheck %s
|
||||
|
||||
# Out of range immediates
|
||||
## simm12
|
||||
fld ft1, -2049(a0) # CHECK: :[[@LINE]]:10: error: immediate must be an integer in the range [-2048, 2047]
|
||||
fsd ft2, 2048(a1) # CHECK: :[[@LINE]]:10: error: immediate must be an integer in the range [-2048, 2047]
|
||||
|
||||
# Memory operand not formatted correctly
|
||||
fld ft1, a0, -200 # CHECK: :[[@LINE]]:10: error: immediate must be an integer in the range [-2048, 2047]
|
||||
fsd ft2, a1, 100 # CHECK: :[[@LINE]]:10: error: immediate must be an integer in the range [-2048, 2047]
|
||||
|
||||
# Invalid register names
|
||||
fld ft15, 100(a0) # CHECK: :[[@LINE]]:5: error: invalid operand for instruction
|
||||
fld ft1, 100(a10) # CHECK: :[[@LINE]]:14: error: expected register
|
||||
fsgnjn.d fa100, fa2, fa3 # CHECK: :[[@LINE]]:10: error: invalid operand for instruction
|
||||
|
||||
# Integer registers where FP regs are expected
|
||||
fadd.d a2, a1, a0 # CHECK: :[[@LINE]]:8: error: invalid operand for instruction
|
||||
|
||||
# FP registers where integer regs are expected
|
||||
fcvt.wu.d ft2, a1 # CHECK: :[[@LINE]]:11: error: invalid operand for instruction
|
159
test/MC/RISCV/rv32d-valid.s
Normal file
159
test/MC/RISCV/rv32d-valid.s
Normal file
@ -0,0 +1,159 @@
|
||||
# RUN: llvm-mc %s -triple=riscv32 -mattr=+d -show-encoding \
|
||||
# RUN: | FileCheck -check-prefixes=CHECK,CHECK-INST %s
|
||||
# RUN: llvm-mc %s -triple=riscv64 -mattr=+d -show-encoding \
|
||||
# RUN: | FileCheck -check-prefixes=CHECK,CHECK-INST %s
|
||||
# RUN: llvm-mc -filetype=obj -triple riscv32 -mattr=+d < %s \
|
||||
# RUN: | llvm-objdump -mattr=+d -d - | FileCheck -check-prefix=CHECK-INST %s
|
||||
# RUN: llvm-mc -filetype=obj -triple riscv64 -mattr=+d < %s \
|
||||
# RUN: | llvm-objdump -mattr=+d -d - | FileCheck -check-prefix=CHECK-INST %s
|
||||
|
||||
# Support for the 'D' extension implies support for 'F'
|
||||
# CHECK-INST: fadd.s fs10, fs11, ft8
|
||||
# CHECK: encoding: [0x53,0xfd,0xcd,0x01]
|
||||
fadd.s f26, f27, f28
|
||||
|
||||
# CHECK-INST: fld ft0, 12(a0)
|
||||
# CHECK: encoding: [0x07,0x30,0xc5,0x00]
|
||||
fld f0, 12(a0)
|
||||
# CHECK-INST: fld ft1, 4(ra)
|
||||
# CHECK: encoding: [0x87,0xb0,0x40,0x00]
|
||||
fld f1, +4(ra)
|
||||
# CHECK-INST: fld ft2, -2048(a3)
|
||||
# CHECK: encoding: [0x07,0xb1,0x06,0x80]
|
||||
fld f2, -2048(x13)
|
||||
# CHECK-INST: fld ft3, -2048(s1)
|
||||
# CHECK: encoding: [0x87,0xb1,0x04,0x80]
|
||||
fld f3, %lo(2048)(s1)
|
||||
# CHECK-INST: fld ft4, 2047(s2)
|
||||
# CHECK: encoding: [0x07,0x32,0xf9,0x7f]
|
||||
fld f4, 2047(s2)
|
||||
# CHECK-INST: fld ft5, 0(s3)
|
||||
# CHECK: encoding: [0x87,0xb2,0x09,0x00]
|
||||
fld f5, 0(s3)
|
||||
|
||||
# CHECK-INST: fsd ft6, 2047(s4)
|
||||
# CHECK: encoding: [0xa7,0x3f,0x6a,0x7e]
|
||||
fsd f6, 2047(s4)
|
||||
# CHECK-INST: fsd ft7, -2048(s5)
|
||||
# CHECK: encoding: [0x27,0xb0,0x7a,0x80]
|
||||
fsd f7, -2048(s5)
|
||||
# CHECK-INST: fsd fs0, -2048(s6)
|
||||
# CHECK: encoding: [0x27,0x30,0x8b,0x80]
|
||||
fsd f8, %lo(2048)(s6)
|
||||
# CHECK-INST: fsd fs1, 999(s7)
|
||||
# CHECK: encoding: [0xa7,0xb3,0x9b,0x3e]
|
||||
fsd f9, 999(s7)
|
||||
|
||||
# CHECK-INST: fmadd.d fa0, fa1, fa2, fa3
|
||||
# CHECK: encoding: [0x43,0xf5,0xc5,0x6a]
|
||||
fmadd.d f10, f11, f12, f13
|
||||
# CHECK-INST: fmsub.d fa4, fa5, fa6, fa7
|
||||
# CHECK: encoding: [0x47,0xf7,0x07,0x8b]
|
||||
fmsub.d f14, f15, f16, f17
|
||||
# CHECK-INST: fnmsub.d fs2, fs3, fs4, fs5
|
||||
# CHECK: encoding: [0x4b,0xf9,0x49,0xab]
|
||||
fnmsub.d f18, f19, f20, f21
|
||||
# CHECK-INST: fnmadd.d fs6, fs7, fs8, fs9
|
||||
# CHECK: encoding: [0x4f,0xfb,0x8b,0xcb]
|
||||
fnmadd.d f22, f23, f24, f25
|
||||
|
||||
# CHECK-INST: fadd.d fs10, fs11, ft8
|
||||
# CHECK: encoding: [0x53,0xfd,0xcd,0x03]
|
||||
fadd.d f26, f27, f28
|
||||
# CHECK-INST: fsub.d ft9, ft10, ft11
|
||||
# CHECK: encoding: [0xd3,0x7e,0xff,0x0b]
|
||||
fsub.d f29, f30, f31
|
||||
# CHECK-INST: fmul.d ft0, ft1, ft2
|
||||
# CHECK: encoding: [0x53,0xf0,0x20,0x12]
|
||||
fmul.d ft0, ft1, ft2
|
||||
# CHECK-INST: fdiv.d ft3, ft4, ft5
|
||||
# CHECK: encoding: [0xd3,0x71,0x52,0x1a]
|
||||
fdiv.d ft3, ft4, ft5
|
||||
# CHECK-INST: fsqrt.d ft6, ft7
|
||||
# CHECK: encoding: [0x53,0xf3,0x03,0x5a]
|
||||
fsqrt.d ft6, ft7
|
||||
# CHECK-INST: fsgnj.d fs1, fa0, fa1
|
||||
# CHECK: encoding: [0xd3,0x04,0xb5,0x22]
|
||||
fsgnj.d fs1, fa0, fa1
|
||||
# CHECK-INST: fsgnjn.d fa1, fa3, fa4
|
||||
# CHECK: encoding: [0xd3,0x95,0xe6,0x22]
|
||||
fsgnjn.d fa1, fa3, fa4
|
||||
# CHECK-INST: fsgnjx.d fa3, fa2, fa1
|
||||
# CHECK: encoding: [0xd3,0x26,0xb6,0x22]
|
||||
fsgnjx.d fa3, fa2, fa1
|
||||
# CHECK-INST: fmin.d fa5, fa6, fa7
|
||||
# CHECK: encoding: [0xd3,0x07,0x18,0x2b]
|
||||
fmin.d fa5, fa6, fa7
|
||||
# CHECK-INST: fmax.d fs2, fs3, fs4
|
||||
# CHECK: encoding: [0x53,0x99,0x49,0x2b]
|
||||
fmax.d fs2, fs3, fs4
|
||||
|
||||
# CHECK-INST: fcvt.s.d fs5, fs6
|
||||
# CHECK: encoding: [0xd3,0x7a,0x1b,0x40]
|
||||
fcvt.s.d fs5, fs6
|
||||
# CHECK-INST: fcvt.d.s fs7, fs8
|
||||
# CHECK: encoding: [0xd3,0x0b,0x0c,0x42]
|
||||
fcvt.d.s fs7, fs8
|
||||
# CHECK-INST: feq.d a1, fs8, fs9
|
||||
# CHECK: encoding: [0xd3,0x25,0x9c,0xa3]
|
||||
feq.d a1, fs8, fs9
|
||||
# CHECK-INST: flt.d a2, fs10, fs11
|
||||
# CHECK: encoding: [0x53,0x16,0xbd,0xa3]
|
||||
flt.d a2, fs10, fs11
|
||||
# CHECK-INST: fle.d a3, ft8, ft9
|
||||
# CHECK: encoding: [0xd3,0x06,0xde,0xa3]
|
||||
fle.d a3, ft8, ft9
|
||||
# CHECK-INST: fclass.d a3, ft10
|
||||
# CHECK: encoding: [0xd3,0x16,0x0f,0xe2]
|
||||
fclass.d a3, ft10
|
||||
|
||||
# CHECK-INST: fcvt.w.d a4, ft11
|
||||
# CHECK: encoding: [0x53,0xf7,0x0f,0xc2]
|
||||
fcvt.w.d a4, ft11
|
||||
# CHECK-INST: fcvt.d.w ft0, a5
|
||||
# CHECK: encoding: [0x53,0x80,0x07,0xd2]
|
||||
fcvt.d.w ft0, a5
|
||||
# CHECK-INST: fcvt.d.wu ft1, a6
|
||||
# CHECK: encoding: [0xd3,0x00,0x18,0xd2]
|
||||
fcvt.d.wu ft1, a6
|
||||
|
||||
# Rounding modes
|
||||
|
||||
# CHECK-INST: fmadd.d fa0, fa1, fa2, fa3, rne
|
||||
# CHECK: encoding: [0x43,0x85,0xc5,0x6a]
|
||||
fmadd.d f10, f11, f12, f13, rne
|
||||
# CHECK-INST: fmsub.d fa4, fa5, fa6, fa7, rtz
|
||||
# CHECK: encoding: [0x47,0x97,0x07,0x8b]
|
||||
fmsub.d f14, f15, f16, f17, rtz
|
||||
# CHECK-INST: fnmsub.d fs2, fs3, fs4, fs5, rdn
|
||||
# CHECK: encoding: [0x4b,0xa9,0x49,0xab]
|
||||
fnmsub.d f18, f19, f20, f21, rdn
|
||||
# CHECK-INST: fnmadd.d fs6, fs7, fs8, fs9, rup
|
||||
# CHECK: encoding: [0x4f,0xbb,0x8b,0xcb]
|
||||
fnmadd.d f22, f23, f24, f25, rup
|
||||
|
||||
# CHECK-INST: fadd.d fs10, fs11, ft8, rmm
|
||||
# CHECK: encoding: [0x53,0xcd,0xcd,0x03]
|
||||
fadd.d f26, f27, f28, rmm
|
||||
# CHECK-INST: fsub.d ft9, ft10, ft11
|
||||
# CHECK: encoding: [0xd3,0x7e,0xff,0x0b]
|
||||
fsub.d f29, f30, f31, dyn
|
||||
# CHECK-INST: fmul.d ft0, ft1, ft2, rne
|
||||
# CHECK: encoding: [0x53,0x80,0x20,0x12]
|
||||
fmul.d ft0, ft1, ft2, rne
|
||||
# CHECK-INST: fdiv.d ft3, ft4, ft5, rtz
|
||||
# CHECK: encoding: [0xd3,0x11,0x52,0x1a]
|
||||
fdiv.d ft3, ft4, ft5, rtz
|
||||
|
||||
# CHECK-INST: fsqrt.d ft6, ft7, rdn
|
||||
# CHECK: encoding: [0x53,0xa3,0x03,0x5a]
|
||||
fsqrt.d ft6, ft7, rdn
|
||||
# CHECK-INST: fcvt.s.d fs5, fs6, rup
|
||||
# CHECK: encoding: [0xd3,0x3a,0x1b,0x40]
|
||||
fcvt.s.d fs5, fs6, rup
|
||||
# CHECK-INST: fcvt.w.d a4, ft11, rmm
|
||||
# CHECK: encoding: [0x53,0xc7,0x0f,0xc2]
|
||||
fcvt.w.d a4, ft11, rmm
|
||||
# CHECK-INST: fcvt.wu.d a5, ft10
|
||||
# CHECK: encoding: [0xd3,0x77,0x1f,0xc2]
|
||||
fcvt.wu.d a5, ft10, dyn
|
@ -27,3 +27,6 @@ fmadd.s f10, f11, f12, ree # CHECK: :[[@LINE]]:24: error: invalid operand for in
|
||||
fmadd.s f10, f11, f12, f13, ree # CHECK: :[[@LINE]]:29: error: operand must be a valid floating point rounding mode mnemonic
|
||||
fmsub.s f14, f15, f16, f17, 0 # CHECK: :[[@LINE]]:29: error: operand must be a valid floating point rounding mode mnemonic
|
||||
fnmsub.s f18, f19, f20, f21, 0b111 # CHECK: :[[@LINE]]:30: error: operand must be a valid floating point rounding mode mnemonic
|
||||
|
||||
# Using 'D' instructions for an 'F'-only target
|
||||
fadd.d ft0, ft1, ft2 # CHECK: :[[@LINE]]:1: error: instruction use requires an option to be enabled
|
||||
|
Loading…
Reference in New Issue
Block a user