Commit 9d0b3cd8 authored by Lu Yahan's avatar Lu Yahan Committed by V8 LUCI CQ

[riscv64] Implement RVV float

Bug: v8:11976
Change-Id: I19e1ef43f073c8155dbc2890de0f331782eb7aac
Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/3156588
Commit-Queue: Ji Qiu <qiuji@iscas.ac.cn>
Reviewed-by: 's avatarJi Qiu <qiuji@iscas.ac.cn>
Cr-Commit-Position: refs/heads/main@{#76835}
parent 23b4cc8e
...@@ -1151,6 +1151,16 @@ void Assembler::GenInstrV(uint8_t funct6, Opcode opcode, VRegister vd, ...@@ -1151,6 +1151,16 @@ void Assembler::GenInstrV(uint8_t funct6, Opcode opcode, VRegister vd,
((vs2.code() & 0x1F) << kRvvVs2Shift); ((vs2.code() & 0x1F) << kRvvVs2Shift);
emit(instr); emit(instr);
} }
void Assembler::GenInstrV(uint8_t funct6, Opcode opcode, VRegister vd,
int8_t vs1, VRegister vs2, MaskType mask) {
DCHECK(opcode == OP_MVV || opcode == OP_FVV || opcode == OP_IVV);
Instr instr = (funct6 << kRvvFunct6Shift) | opcode | (mask << kRvvVmShift) |
((vd.code() & 0x1F) << kRvvVdShift) |
((vs1 & 0x1F) << kRvvVs1Shift) |
((vs2.code() & 0x1F) << kRvvVs2Shift);
emit(instr);
}
// OPMVV OPFVV // OPMVV OPFVV
void Assembler::GenInstrV(uint8_t funct6, Opcode opcode, Register rd, void Assembler::GenInstrV(uint8_t funct6, Opcode opcode, Register rd,
VRegister vs1, VRegister vs2, MaskType mask) { VRegister vs1, VRegister vs2, MaskType mask) {
...@@ -1162,10 +1172,10 @@ void Assembler::GenInstrV(uint8_t funct6, Opcode opcode, Register rd, ...@@ -1162,10 +1172,10 @@ void Assembler::GenInstrV(uint8_t funct6, Opcode opcode, Register rd,
emit(instr); emit(instr);
} }
// OPIVX OPFVF OPMVX // OPIVX OPMVX
void Assembler::GenInstrV(uint8_t funct6, Opcode opcode, VRegister vd, void Assembler::GenInstrV(uint8_t funct6, Opcode opcode, VRegister vd,
Register rs1, VRegister vs2, MaskType mask) { Register rs1, VRegister vs2, MaskType mask) {
DCHECK(opcode == OP_IVX || opcode == OP_FVF || opcode == OP_MVX); DCHECK(opcode == OP_IVX || opcode == OP_MVX);
Instr instr = (funct6 << kRvvFunct6Shift) | opcode | (mask << kRvvVmShift) | Instr instr = (funct6 << kRvvFunct6Shift) | opcode | (mask << kRvvVmShift) |
((vd.code() & 0x1F) << kRvvVdShift) | ((vd.code() & 0x1F) << kRvvVdShift) |
((rs1.code() & 0x1F) << kRvvRs1Shift) | ((rs1.code() & 0x1F) << kRvvRs1Shift) |
...@@ -1173,6 +1183,17 @@ void Assembler::GenInstrV(uint8_t funct6, Opcode opcode, VRegister vd, ...@@ -1173,6 +1183,17 @@ void Assembler::GenInstrV(uint8_t funct6, Opcode opcode, VRegister vd,
emit(instr); emit(instr);
} }
// OPFVF
void Assembler::GenInstrV(uint8_t funct6, Opcode opcode, VRegister vd,
FPURegister fs1, VRegister vs2, MaskType mask) {
DCHECK(opcode == OP_FVF);
Instr instr = (funct6 << kRvvFunct6Shift) | opcode | (mask << kRvvVmShift) |
((vd.code() & 0x1F) << kRvvVdShift) |
((fs1.code() & 0x1F) << kRvvRs1Shift) |
((vs2.code() & 0x1F) << kRvvVs2Shift);
emit(instr);
}
// OPMVX // OPMVX
void Assembler::GenInstrV(uint8_t funct6, Register rd, Register rs1, void Assembler::GenInstrV(uint8_t funct6, Register rd, Register rs1,
VRegister vs2, MaskType mask) { VRegister vs2, MaskType mask) {
...@@ -2491,6 +2512,12 @@ void Assembler::vmadc_vi(VRegister vd, uint8_t imm5, VRegister vs2) { ...@@ -2491,6 +2512,12 @@ void Assembler::vmadc_vi(VRegister vd, uint8_t imm5, VRegister vs2) {
GenInstrV(funct6, OP_IVV, vd, vs1, vs2, mask); \ GenInstrV(funct6, OP_IVV, vd, vs1, vs2, mask); \
} }
#define DEFINE_OPFVV(name, funct6) \
void Assembler::name##_vv(VRegister vd, VRegister vs2, VRegister vs1, \
MaskType mask) { \
GenInstrV(funct6, OP_FVV, vd, vs1, vs2, mask); \
}
#define DEFINE_OPIVX(name, funct6) \ #define DEFINE_OPIVX(name, funct6) \
void Assembler::name##_vx(VRegister vd, VRegister vs2, Register rs1, \ void Assembler::name##_vx(VRegister vd, VRegister vs2, Register rs1, \
MaskType mask) { \ MaskType mask) { \
...@@ -2509,6 +2536,12 @@ void Assembler::vmadc_vi(VRegister vd, uint8_t imm5, VRegister vs2) { ...@@ -2509,6 +2536,12 @@ void Assembler::vmadc_vi(VRegister vd, uint8_t imm5, VRegister vs2) {
GenInstrV(funct6, OP_MVV, vd, vs1, vs2, mask); \ GenInstrV(funct6, OP_MVV, vd, vs1, vs2, mask); \
} }
#define DEFINE_OPFVF(name, funct6) \
void Assembler::name##_vf(VRegister vd, VRegister vs2, FPURegister fs1, \
MaskType mask) { \
GenInstrV(funct6, OP_FVF, vd, fs1, vs2, mask); \
}
DEFINE_OPIVV(vadd, VADD_FUNCT6) DEFINE_OPIVV(vadd, VADD_FUNCT6)
DEFINE_OPIVX(vadd, VADD_FUNCT6) DEFINE_OPIVX(vadd, VADD_FUNCT6)
DEFINE_OPIVI(vadd, VADD_FUNCT6) DEFINE_OPIVI(vadd, VADD_FUNCT6)
...@@ -2592,9 +2625,33 @@ DEFINE_OPMVV(vredmaxu, VREDMAXU_FUNCT6) ...@@ -2592,9 +2625,33 @@ DEFINE_OPMVV(vredmaxu, VREDMAXU_FUNCT6)
DEFINE_OPMVV(vredmax, VREDMAX_FUNCT6) DEFINE_OPMVV(vredmax, VREDMAX_FUNCT6)
DEFINE_OPMVV(vredmin, VREDMIN_FUNCT6) DEFINE_OPMVV(vredmin, VREDMIN_FUNCT6)
DEFINE_OPMVV(vredminu, VREDMINU_FUNCT6) DEFINE_OPMVV(vredminu, VREDMINU_FUNCT6)
DEFINE_OPFVV(vfadd, VFADD_FUNCT6)
DEFINE_OPFVF(vfadd, VFADD_FUNCT6)
DEFINE_OPFVV(vfsub, VFSUB_FUNCT6)
DEFINE_OPFVF(vfsub, VFSUB_FUNCT6)
DEFINE_OPFVV(vfdiv, VFDIV_FUNCT6)
DEFINE_OPFVF(vfdiv, VFDIV_FUNCT6)
DEFINE_OPFVV(vfmul, VFMUL_FUNCT6)
DEFINE_OPFVF(vfmul, VFMUL_FUNCT6)
DEFINE_OPFVV(vmfeq, VMFEQ_FUNCT6)
DEFINE_OPFVV(vmfne, VMFNE_FUNCT6)
DEFINE_OPFVV(vmflt, VMFLT_FUNCT6)
DEFINE_OPFVV(vmfle, VMFLE_FUNCT6)
DEFINE_OPFVV(vfmax, VFMAX_FUNCT6)
DEFINE_OPFVV(vfmin, VFMIN_FUNCT6)
DEFINE_OPFVV(vfsngj, VFSGNJ_FUNCT6)
DEFINE_OPFVF(vfsngj, VFSGNJ_FUNCT6)
DEFINE_OPFVV(vfsngjn, VFSGNJN_FUNCT6)
DEFINE_OPFVF(vfsngjn, VFSGNJN_FUNCT6)
DEFINE_OPFVV(vfsngjx, VFSGNJX_FUNCT6)
DEFINE_OPFVF(vfsngjx, VFSGNJX_FUNCT6)
#undef DEFINE_OPIVI #undef DEFINE_OPIVI
#undef DEFINE_OPIVV #undef DEFINE_OPIVV
#undef DEFINE_OPIVX #undef DEFINE_OPIVX
#undef DEFINE_OPFVV
#undef DEFINE_OPFVF
void Assembler::vsetvli(Register rd, Register rs1, VSew vsew, Vlmul vlmul, void Assembler::vsetvli(Register rd, Register rs1, VSew vsew, Vlmul vlmul,
TailAgnosticType tail, MaskAgnosticType mask) { TailAgnosticType tail, MaskAgnosticType mask) {
......
...@@ -358,11 +358,9 @@ class V8_EXPORT_PRIVATE Assembler : public AssemblerBase { ...@@ -358,11 +358,9 @@ class V8_EXPORT_PRIVATE Assembler : public AssemblerBase {
// invalidated. For instance, when the assembler buffer grows or a GC happens // invalidated. For instance, when the assembler buffer grows or a GC happens
// between Code object allocation and Code object finalization. // between Code object allocation and Code object finalization.
void FixOnHeapReferences(bool update_embedded_objects = true); void FixOnHeapReferences(bool update_embedded_objects = true);
// This function is called when we fallback from on-heap to off-heap // This function is called when we fallback from on-heap to off-heap
// compilation and patch on-heap references to handles. // compilation and patch on-heap references to handles.
void FixOnHeapReferencesToHandles(); void FixOnHeapReferencesToHandles();
// Insert the smallest number of nop instructions // Insert the smallest number of nop instructions
// possible to align the pc offset to a multiple // possible to align the pc offset to a multiple
// of m. m must be a power of 2 (>= 4). // of m. m must be a power of 2 (>= 4).
...@@ -775,6 +773,14 @@ class V8_EXPORT_PRIVATE Assembler : public AssemblerBase { ...@@ -775,6 +773,14 @@ class V8_EXPORT_PRIVATE Assembler : public AssemblerBase {
void name##_vx(VRegister vd, VRegister vs2, Register rs1, \ void name##_vx(VRegister vd, VRegister vs2, Register rs1, \
MaskType mask = NoMask); MaskType mask = NoMask);
#define DEFINE_OPFVV(name, funct6) \
void name##_vv(VRegister vd, VRegister vs2, VRegister vs1, \
MaskType mask = NoMask);
#define DEFINE_OPFVF(name, funct6) \
void name##_vf(VRegister vd, VRegister vs2, FPURegister fs1, \
MaskType mask = NoMask);
DEFINE_OPIVV(vadd, VADD_FUNCT6) DEFINE_OPIVV(vadd, VADD_FUNCT6)
DEFINE_OPIVX(vadd, VADD_FUNCT6) DEFINE_OPIVX(vadd, VADD_FUNCT6)
DEFINE_OPIVI(vadd, VADD_FUNCT6) DEFINE_OPIVI(vadd, VADD_FUNCT6)
...@@ -858,15 +864,58 @@ class V8_EXPORT_PRIVATE Assembler : public AssemblerBase { ...@@ -858,15 +864,58 @@ class V8_EXPORT_PRIVATE Assembler : public AssemblerBase {
DEFINE_OPMVV(vredmax, VREDMAX_FUNCT6) DEFINE_OPMVV(vredmax, VREDMAX_FUNCT6)
DEFINE_OPMVV(vredmin, VREDMIN_FUNCT6) DEFINE_OPMVV(vredmin, VREDMIN_FUNCT6)
DEFINE_OPMVV(vredminu, VREDMINU_FUNCT6) DEFINE_OPMVV(vredminu, VREDMINU_FUNCT6)
DEFINE_OPFVV(vfadd, VFADD_FUNCT6)
DEFINE_OPFVF(vfadd, VFADD_FUNCT6)
DEFINE_OPFVV(vfsub, VFSUB_FUNCT6)
DEFINE_OPFVF(vfsub, VFSUB_FUNCT6)
DEFINE_OPFVV(vfdiv, VFDIV_FUNCT6)
DEFINE_OPFVF(vfdiv, VFDIV_FUNCT6)
DEFINE_OPFVV(vfmul, VFMUL_FUNCT6)
DEFINE_OPFVF(vfmul, VFMUL_FUNCT6)
DEFINE_OPFVV(vmfeq, VMFEQ_FUNCT6)
DEFINE_OPFVV(vmfne, VMFNE_FUNCT6)
DEFINE_OPFVV(vmflt, VMFLT_FUNCT6)
DEFINE_OPFVV(vmfle, VMFLE_FUNCT6)
DEFINE_OPFVV(vfmax, VMFMAX_FUNCT6)
DEFINE_OPFVV(vfmin, VMFMIN_FUNCT6)
DEFINE_OPFVV(vfsngj, VFSGNJ_FUNCT6)
DEFINE_OPFVF(vfsngj, VFSGNJ_FUNCT6)
DEFINE_OPFVV(vfsngjn, VFSGNJN_FUNCT6)
DEFINE_OPFVF(vfsngjn, VFSGNJN_FUNCT6)
DEFINE_OPFVV(vfsngjx, VFSGNJX_FUNCT6)
DEFINE_OPFVF(vfsngjx, VFSGNJX_FUNCT6)
#undef DEFINE_OPIVI #undef DEFINE_OPIVI
#undef DEFINE_OPIVV #undef DEFINE_OPIVV
#undef DEFINE_OPIVX #undef DEFINE_OPIVX
#undef DEFINE_OPMVV #undef DEFINE_OPMVV
#undef DEFINE_OPMVX #undef DEFINE_OPMVX
#undef DEFINE_OPFVV
#undef DEFINE_OPFVF
#define DEFINE_VFUNARY(name, funct6, vs1) \
void name(VRegister vd, VRegister vs2, MaskType mask = NoMask) { \
GenInstrV(funct6, OP_FVV, vd, vs1, vs2, mask); \
}
DEFINE_VFUNARY(vfcvt_xu_f_v, VFUNARY0_FUNCT6, VFCVT_XU_F_V)
DEFINE_VFUNARY(vfcvt_x_f_v, VFUNARY0_FUNCT6, VFCVT_X_F_V)
DEFINE_VFUNARY(vfcvt_f_x_v, VFUNARY0_FUNCT6, VFCVT_F_X_V)
DEFINE_VFUNARY(vfcvt_f_xu_v, VFUNARY0_FUNCT6, VFCVT_F_XU_V)
DEFINE_VFUNARY(vfncvt_f_f_w, VFUNARY0_FUNCT6, VFNCVT_F_F_W)
DEFINE_VFUNARY(vfclass_v, VFUNARY1_FUNCT6, VFCLASS_V)
#undef DEFINE_VFUNARY
void vnot_vv(VRegister dst, VRegister src) { vxor_vi(dst, src, -1); } void vnot_vv(VRegister dst, VRegister src) { vxor_vi(dst, src, -1); }
void vneg_vv(VRegister dst, VRegister src) { vrsub_vx(dst, src, zero_reg); } void vneg_vv(VRegister dst, VRegister src) { vrsub_vx(dst, src, zero_reg); }
void vfneg_vv(VRegister dst, VRegister src) { vfsngjn_vv(dst, src, src); }
void vfabs_vv(VRegister dst, VRegister src) { vfsngjx_vv(dst, src, src); }
// Privileged // Privileged
void uret(); void uret();
void sret(); void sret();
...@@ -1166,6 +1215,13 @@ class V8_EXPORT_PRIVATE Assembler : public AssemblerBase { ...@@ -1166,6 +1215,13 @@ class V8_EXPORT_PRIVATE Assembler : public AssemblerBase {
} }
} }
void set(RoundingMode mode) {
if (mode_ != mode) {
assm_->addi(kScratchReg, zero_reg, mode << kFcsrFrmShift);
assm_->fscsr(kScratchReg);
mode_ = mode;
}
}
void set(Register rd, Register rs1, VSew sew, Vlmul lmul) { void set(Register rd, Register rs1, VSew sew, Vlmul lmul) {
if (sew != sew_ || lmul != lmul_) { if (sew != sew_ || lmul != lmul_) {
sew_ = sew; sew_ = sew;
...@@ -1188,6 +1244,7 @@ class V8_EXPORT_PRIVATE Assembler : public AssemblerBase { ...@@ -1188,6 +1244,7 @@ class V8_EXPORT_PRIVATE Assembler : public AssemblerBase {
Vlmul lmul_ = m1; Vlmul lmul_ = m1;
int32_t vl = 0; int32_t vl = 0;
Assembler* assm_; Assembler* assm_;
RoundingMode mode_ = RNE;
}; };
VectorUnit VU; VectorUnit VU;
...@@ -1450,14 +1507,18 @@ class V8_EXPORT_PRIVATE Assembler : public AssemblerBase { ...@@ -1450,14 +1507,18 @@ class V8_EXPORT_PRIVATE Assembler : public AssemblerBase {
// OPIVV OPFVV OPMVV // OPIVV OPFVV OPMVV
void GenInstrV(uint8_t funct6, Opcode opcode, VRegister vd, VRegister vs1, void GenInstrV(uint8_t funct6, Opcode opcode, VRegister vd, VRegister vs1,
VRegister vs2, MaskType mask = NoMask); VRegister vs2, MaskType mask = NoMask);
void GenInstrV(uint8_t funct6, Opcode opcode, VRegister vd, int8_t vs1,
VRegister vs2, MaskType mask = NoMask);
// OPMVV OPFVV // OPMVV OPFVV
void GenInstrV(uint8_t funct6, Opcode opcode, Register rd, VRegister vs1, void GenInstrV(uint8_t funct6, Opcode opcode, Register rd, VRegister vs1,
VRegister vs2, MaskType mask = NoMask); VRegister vs2, MaskType mask = NoMask);
// OPIVX OPFVF OPMVX // OPIVX OPMVX
void GenInstrV(uint8_t funct6, Opcode opcode, VRegister vd, Register rs1, void GenInstrV(uint8_t funct6, Opcode opcode, VRegister vd, Register rs1,
VRegister vs2, MaskType mask = NoMask); VRegister vs2, MaskType mask = NoMask);
// OPFVF
void GenInstrV(uint8_t funct6, Opcode opcode, VRegister vd, FPURegister fs1,
VRegister vs2, MaskType mask = NoMask);
// OPMVX // OPMVX
void GenInstrV(uint8_t funct6, Register rd, Register rs1, VRegister vs2, void GenInstrV(uint8_t funct6, Register rd, Register rs1, VRegister vs2,
MaskType mask = NoMask); MaskType mask = NoMask);
......
...@@ -858,6 +858,77 @@ enum Opcode : uint32_t { ...@@ -858,6 +858,77 @@ enum Opcode : uint32_t {
RO_V_VREDMINU = OP_MVV | (VREDMINU_FUNCT6 << kRvvFunct6Shift), RO_V_VREDMINU = OP_MVV | (VREDMINU_FUNCT6 << kRvvFunct6Shift),
VREDMIN_FUNCT6 = 0b000101, VREDMIN_FUNCT6 = 0b000101,
RO_V_VREDMIN = OP_MVV | (VREDMIN_FUNCT6 << kRvvFunct6Shift), RO_V_VREDMIN = OP_MVV | (VREDMIN_FUNCT6 << kRvvFunct6Shift),
VFUNARY0_FUNCT6 = 0b010010,
RO_V_VFUNARY0 = OP_FVV | (VFUNARY0_FUNCT6 << kRvvFunct6Shift),
VFUNARY1_FUNCT6 = 0b010011,
RO_V_VFUNARY1 = OP_FVV | (VFUNARY1_FUNCT6 << kRvvFunct6Shift),
VFCVT_XU_F_V = 0b00000,
VFCVT_X_F_V = 0b00001,
VFCVT_F_XU_V = 0b00010,
VFCVT_F_X_V = 0b00011,
VFNCVT_F_F_W = 0b10100,
VFCLASS_V = 0b10000,
VFADD_FUNCT6 = 0b000000,
RO_V_VFADD_VV = OP_FVV | (VFADD_FUNCT6 << kRvvFunct6Shift),
RO_V_VFADD_VF = OP_FVF | (VFADD_FUNCT6 << kRvvFunct6Shift),
VFSUB_FUNCT6 = 0b000010,
RO_V_VFSUB_VV = OP_FVV | (VFSUB_FUNCT6 << kRvvFunct6Shift),
RO_V_VFSUB_VF = OP_FVF | (VFSUB_FUNCT6 << kRvvFunct6Shift),
VFDIV_FUNCT6 = 0b100000,
RO_V_VFDIV_VV = OP_FVV | (VFDIV_FUNCT6 << kRvvFunct6Shift),
RO_V_VFDIV_VF = OP_FVF | (VFDIV_FUNCT6 << kRvvFunct6Shift),
VFMUL_FUNCT6 = 0b100100,
RO_V_VFMUL_VV = OP_FVV | (VFMUL_FUNCT6 << kRvvFunct6Shift),
RO_V_VFMUL_VF = OP_FVF | (VFMUL_FUNCT6 << kRvvFunct6Shift),
VMFEQ_FUNCT6 = 0b011000,
RO_V_VMFEQ_VV = OP_FVV | (VMFEQ_FUNCT6 << kRvvFunct6Shift),
RO_V_VMFEQ_VF = OP_FVF | (VMFEQ_FUNCT6 << kRvvFunct6Shift),
VMFNE_FUNCT6 = 0b011100,
RO_V_VMFNE_VV = OP_FVV | (VMFNE_FUNCT6 << kRvvFunct6Shift),
RO_V_VMFNE_VF = OP_FVF | (VMFNE_FUNCT6 << kRvvFunct6Shift),
VMFLT_FUNCT6 = 0b011011,
RO_V_VMFLT_VV = OP_FVV | (VMFLT_FUNCT6 << kRvvFunct6Shift),
RO_V_VMFLT_VF = OP_FVF | (VMFLT_FUNCT6 << kRvvFunct6Shift),
VMFLE_FUNCT6 = 0b011001,
RO_V_VMFLE_VV = OP_FVV | (VMFLE_FUNCT6 << kRvvFunct6Shift),
RO_V_VMFLE_VF = OP_FVF | (VMFLE_FUNCT6 << kRvvFunct6Shift),
VMFGE_FUNCT6 = 0b011111,
RO_V_VMFGE_VF = OP_FVF | (VMFGE_FUNCT6 << kRvvFunct6Shift),
VMFGT_FUNCT6 = 0b011101,
RO_V_VMFGT_VF = OP_FVF | (VMFGT_FUNCT6 << kRvvFunct6Shift),
VFMAX_FUNCT6 = 0b000110,
RO_V_VFMAX_VV = OP_FVV | (VFMAX_FUNCT6 << kRvvFunct6Shift),
RO_V_VFMAX_VF = OP_FVF | (VFMAX_FUNCT6 << kRvvFunct6Shift),
VFMIN_FUNCT6 = 0b000100,
RO_V_VFMIN_VV = OP_FVV | (VFMIN_FUNCT6 << kRvvFunct6Shift),
RO_V_VFMIN_VF = OP_FVF | (VFMIN_FUNCT6 << kRvvFunct6Shift),
VFSGNJ_FUNCT6 = 0b001000,
RO_V_VFSGNJ_VV = OP_FVV | (VFSGNJ_FUNCT6 << kRvvFunct6Shift),
RO_V_VFSGNJ_VF = OP_FVF | (VFSGNJ_FUNCT6 << kRvvFunct6Shift),
VFSGNJN_FUNCT6 = 0b001001,
RO_V_VFSGNJN_VV = OP_FVV | (VFSGNJN_FUNCT6 << kRvvFunct6Shift),
RO_V_VFSGNJN_VF = OP_FVF | (VFSGNJN_FUNCT6 << kRvvFunct6Shift),
VFSGNJX_FUNCT6 = 0b001010,
RO_V_VFSGNJX_VV = OP_FVV | (VFSGNJX_FUNCT6 << kRvvFunct6Shift),
RO_V_VFSGNJX_VF = OP_FVF | (VFSGNJX_FUNCT6 << kRvvFunct6Shift),
}; };
// ----- Emulated conditions. // ----- Emulated conditions.
...@@ -991,6 +1062,13 @@ enum MemoryOdering { ...@@ -991,6 +1062,13 @@ enum MemoryOdering {
PSIORW = PSI | PSO | PSR | PSW PSIORW = PSI | PSO | PSR | PSW
}; };
const int kFloat32ExponentBias = 127;
const int kFloat32MantissaBits = 23;
const int kFloat32ExponentBits = 8;
const int kFloat64ExponentBias = 1023;
const int kFloat64MantissaBits = 52;
const int kFloat64ExponentBits = 11;
enum FClassFlag { enum FClassFlag {
kNegativeInfinity = 1, kNegativeInfinity = 1,
kNegativeNormalNumber = 1 << 1, kNegativeNormalNumber = 1 << 1,
......
...@@ -2045,19 +2045,12 @@ void TurboAssembler::RoundHelper(FPURegister dst, FPURegister src, ...@@ -2045,19 +2045,12 @@ void TurboAssembler::RoundHelper(FPURegister dst, FPURegister src,
// Need at least two FPRs, so check against dst == src == fpu_scratch // Need at least two FPRs, so check against dst == src == fpu_scratch
DCHECK(!(dst == src && dst == fpu_scratch)); DCHECK(!(dst == src && dst == fpu_scratch));
const int kFloat32ExponentBias = 127;
const int kFloat32MantissaBits = 23;
const int kFloat32ExponentBits = 8;
const int kFloat64ExponentBias = 1023;
const int kFloat64MantissaBits = 52;
const int kFloat64ExponentBits = 11;
const int kFloatMantissaBits = const int kFloatMantissaBits =
sizeof(F) == 4 ? kFloat32MantissaBits : kFloat64MantissaBits; sizeof(F) == 4 ? kFloat32MantissaBits : kFloat64MantissaBits;
const int kFloatExponentBits = const int kFloatExponentBits =
sizeof(F) == 4 ? kFloat32ExponentBits : kFloat64ExponentBits; sizeof(F) == 4 ? kFloat32ExponentBits : kFloat64ExponentBits;
const int kFloatExponentBias = const int kFloatExponentBias =
sizeof(F) == 4 ? kFloat32ExponentBias : kFloat64ExponentBias; sizeof(F) == 4 ? kFloat32ExponentBias : kFloat64ExponentBias;
Label done; Label done;
{ {
...@@ -2156,6 +2149,72 @@ void TurboAssembler::RoundHelper(FPURegister dst, FPURegister src, ...@@ -2156,6 +2149,72 @@ void TurboAssembler::RoundHelper(FPURegister dst, FPURegister src,
bind(&done); bind(&done);
} }
// According to JS ECMA specification, for floating-point round operations, if
// the input is NaN, +/-infinity, or +/-0, the same input is returned as the
// rounded result; this differs from behavior of RISCV fcvt instructions (which
// round out-of-range values to the nearest max or min value), therefore special
// handling is needed by NaN, +/-Infinity, +/-0
template <typename F>
void TurboAssembler::RoundHelper(VRegister dst, VRegister src, Register scratch,
VRegister v_scratch, RoundingMode frm) {
VU.set(scratch, std::is_same<F, float>::value ? E32 : E64, m1);
// if src is NaN/+-Infinity/+-Zero or if the exponent is larger than # of bits
// in mantissa, the result is the same as src, so move src to dest (to avoid
// generating another branch)
// If real exponent (i.e., scratch2 - kFloatExponentBias) is greater than
// kFloat32MantissaBits, it means the floating-point value has no fractional
// part, thus the input is already rounded, jump to done. Note that, NaN and
// Infinity in floating-point representation sets maximal exponent value, so
// they also satisfy (scratch2 - kFloatExponentBias >= kFloatMantissaBits),
// and JS round semantics specify that rounding of NaN (Infinity) returns NaN
// (Infinity), so NaN and Infinity are considered rounded value too.
li(scratch, 64 - kFloat32MantissaBits - kFloat32ExponentBits);
vsll_vx(v_scratch, src, scratch);
li(scratch, 64 - kFloat32ExponentBits);
vsrl_vx(v_scratch, v_scratch, scratch);
li(scratch, kFloat32ExponentBias + kFloat32MantissaBits);
vmslt_vx(v0, v_scratch, scratch);
VU.set(frm);
vmv_vv(dst, src);
if (dst == src) {
vmv_vv(v_scratch, src);
}
vfcvt_x_f_v(dst, src, MaskType::Mask);
vfcvt_f_x_v(dst, dst, MaskType::Mask);
// A special handling is needed if the input is a very small positive/negative
// number that rounds to zero. JS semantics requires that the rounded result
// retains the sign of the input, so a very small positive (negative)
// floating-point number should be rounded to positive (negative) 0.
if (dst == src) {
vfsngj_vv(dst, dst, v_scratch);
} else {
vfsngj_vv(dst, dst, src);
}
}
void TurboAssembler::Ceil_f(VRegister vdst, VRegister vsrc, Register scratch,
VRegister v_scratch) {
RoundHelper<float>(vdst, vsrc, scratch, v_scratch, RUP);
}
void TurboAssembler::Ceil_d(VRegister vdst, VRegister vsrc, Register scratch,
VRegister v_scratch) {
RoundHelper<double>(vdst, vsrc, scratch, v_scratch, RUP);
}
void TurboAssembler::Floor_f(VRegister vdst, VRegister vsrc, Register scratch,
VRegister v_scratch) {
RoundHelper<float>(vdst, vsrc, scratch, v_scratch, RDN);
}
void TurboAssembler::Floor_d(VRegister vdst, VRegister vsrc, Register scratch,
VRegister v_scratch) {
RoundHelper<double>(vdst, vsrc, scratch, v_scratch, RDN);
}
void TurboAssembler::Floor_d_d(FPURegister dst, FPURegister src, void TurboAssembler::Floor_d_d(FPURegister dst, FPURegister src,
FPURegister fpu_scratch) { FPURegister fpu_scratch) {
RoundHelper<double>(dst, src, fpu_scratch, RDN); RoundHelper<double>(dst, src, fpu_scratch, RDN);
......
...@@ -837,6 +837,16 @@ class V8_EXPORT_PRIVATE TurboAssembler : public TurboAssemblerBase { ...@@ -837,6 +837,16 @@ class V8_EXPORT_PRIVATE TurboAssembler : public TurboAssemblerBase {
void Floor_s_s(FPURegister fd, FPURegister fs, FPURegister fpu_scratch); void Floor_s_s(FPURegister fd, FPURegister fs, FPURegister fpu_scratch);
void Ceil_s_s(FPURegister fd, FPURegister fs, FPURegister fpu_scratch); void Ceil_s_s(FPURegister fd, FPURegister fs, FPURegister fpu_scratch);
void Ceil_f(VRegister dst, VRegister src, Register scratch,
VRegister v_scratch);
void Ceil_d(VRegister dst, VRegister src, Register scratch,
VRegister v_scratch);
void Floor_f(VRegister dst, VRegister src, Register scratch,
VRegister v_scratch);
void Floor_d(VRegister dst, VRegister src, Register scratch,
VRegister v_scratch);
// Jump the register contains a smi. // Jump the register contains a smi.
void JumpIfSmi(Register value, Label* smi_label); void JumpIfSmi(Register value, Label* smi_label);
...@@ -978,6 +988,10 @@ class V8_EXPORT_PRIVATE TurboAssembler : public TurboAssemblerBase { ...@@ -978,6 +988,10 @@ class V8_EXPORT_PRIVATE TurboAssembler : public TurboAssemblerBase {
void RoundHelper(FPURegister dst, FPURegister src, FPURegister fpu_scratch, void RoundHelper(FPURegister dst, FPURegister src, FPURegister fpu_scratch,
RoundingMode mode); RoundingMode mode);
template <typename F>
void RoundHelper(VRegister dst, VRegister src, Register scratch,
VRegister v_scratch, RoundingMode frm);
template <typename TruncFunc> template <typename TruncFunc>
void RoundFloatingPointToInteger(Register rd, FPURegister fs, Register result, void RoundFloatingPointToInteger(Register rd, FPURegister fs, Register result,
TruncFunc trunc); TruncFunc trunc);
......
...@@ -23,8 +23,8 @@ namespace internal { ...@@ -23,8 +23,8 @@ namespace internal {
// s3: scratch register s4: scratch register 2 used in code-generator-riscv64 // s3: scratch register s4: scratch register 2 used in code-generator-riscv64
// s6: roots in Javascript code s7: context register // s6: roots in Javascript code s7: context register
// s11: PtrComprCageBaseRegister // s11: PtrComprCageBaseRegister
// t3 t5 s10 : scratch register used in scratch_register_list // t3 t5 : scratch register used in scratch_register_list
// t6 : call reg.
// t0 t1 t2 t4:caller saved scratch register can be used in macroassembler and // t0 t1 t2 t4:caller saved scratch register can be used in macroassembler and
// builtin-riscv64 // builtin-riscv64
#define ALWAYS_ALLOCATABLE_GENERAL_REGISTERS(V) \ #define ALWAYS_ALLOCATABLE_GENERAL_REGISTERS(V) \
......
...@@ -2049,6 +2049,18 @@ CodeGenerator::CodeGenResult CodeGenerator::AssembleArchInstruction( ...@@ -2049,6 +2049,18 @@ CodeGenerator::CodeGenResult CodeGenerator::AssembleArchInstruction(
__ vmv_vx(i.OutputSimd128Register(), i.InputRegister(0)); __ vmv_vx(i.OutputSimd128Register(), i.InputRegister(0));
break; break;
} }
case kRiscvF32x4Splat: {
(__ VU).set(kScratchReg, E32, m1);
__ fmv_x_w(kScratchReg, i.InputSingleRegister(0));
__ vmv_vx(i.OutputSimd128Register(), kScratchReg);
break;
}
case kRiscvF64x2Splat: {
(__ VU).set(kScratchReg, E64, m1);
__ fmv_x_d(kScratchReg, i.InputDoubleRegister(0));
__ vmv_vx(i.OutputSimd128Register(), kScratchReg);
break;
}
case kRiscvI32x4Abs: { case kRiscvI32x4Abs: {
__ VU.set(kScratchReg, E32, m1); __ VU.set(kScratchReg, E32, m1);
__ vmv_vx(kSimd128RegZero, zero_reg); __ vmv_vx(kSimd128RegZero, zero_reg);
...@@ -2392,6 +2404,173 @@ CodeGenerator::CodeGenResult CodeGenerator::AssembleArchInstruction( ...@@ -2392,6 +2404,173 @@ CodeGenerator::CodeGenResult CodeGenerator::AssembleArchInstruction(
__ vor_vv(dst, dst, kSimd128ScratchReg); __ vor_vv(dst, dst, kSimd128ScratchReg);
break; break;
} }
case kRiscvF32x4Abs: {
__ VU.set(kScratchReg, VSew::E32, Vlmul::m1);
__ vfabs_vv(i.OutputSimd128Register(), i.InputSimd128Register(0));
break;
}
case kRiscvF64x2Abs: {
__ VU.set(kScratchReg, VSew::E64, Vlmul::m1);
__ vfabs_vv(i.OutputSimd128Register(), i.InputSimd128Register(0));
break;
}
case kRiscvF32x4Neg: {
__ VU.set(kScratchReg, VSew::E32, Vlmul::m1);
__ vfneg_vv(i.OutputSimd128Register(), i.InputSimd128Register(0));
break;
}
case kRiscvF64x2Neg: {
__ VU.set(kScratchReg, VSew::E64, Vlmul::m1);
__ vfneg_vv(i.OutputSimd128Register(), i.InputSimd128Register(0));
break;
}
case kRiscvF32x4DemoteF64x2Zero: {
__ VU.set(kScratchReg, E32, m1);
__ vfncvt_f_f_w(i.OutputSimd128Register(), i.InputSimd128Register(0));
__ vmv_vi(v0, 12);
__ vmerge_vx(i.OutputSimd128Register(), zero_reg,
i.OutputSimd128Register());
break;
}
case kRiscvF32x4Add: {
__ VU.set(kScratchReg, E32, m1);
__ vfadd_vv(i.OutputSimd128Register(), i.InputSimd128Register(0),
i.InputSimd128Register(1));
break;
}
case kRiscvF32x4Sub: {
__ VU.set(kScratchReg, E32, m1);
__ vfsub_vv(i.OutputSimd128Register(), i.InputSimd128Register(0),
i.InputSimd128Register(1));
break;
}
case kRiscvF64x2Add: {
__ VU.set(kScratchReg, E64, m1);
__ vfadd_vv(i.OutputSimd128Register(), i.InputSimd128Register(0),
i.InputSimd128Register(1));
break;
}
case kRiscvF64x2Sub: {
__ VU.set(kScratchReg, E64, m1);
__ vfsub_vv(i.OutputSimd128Register(), i.InputSimd128Register(0),
i.InputSimd128Register(1));
break;
}
case kRiscvF32x4Ceil: {
__ Ceil_f(i.OutputSimd128Register(), i.InputSimd128Register(0),
kScratchReg, kSimd128ScratchReg);
break;
}
case kRiscvF64x2Ceil: {
__ Ceil_d(i.OutputSimd128Register(), i.InputSimd128Register(0),
kScratchReg, kSimd128ScratchReg);
break;
}
case kRiscvF32x4Floor: {
__ Floor_f(i.OutputSimd128Register(), i.InputSimd128Register(0),
kScratchReg, kSimd128ScratchReg);
break;
}
case kRiscvF64x2Floor: {
__ Floor_d(i.OutputSimd128Register(), i.InputSimd128Register(0),
kScratchReg, kSimd128ScratchReg);
break;
}
case kRiscvS128Select: {
__ VU.set(kScratchReg, E8, m1);
__ vand_vv(kSimd128ScratchReg, i.InputSimd128Register(1),
i.InputSimd128Register(0));
__ vnot_vv(kSimd128ScratchReg2, i.InputSimd128Register(0));
__ vand_vv(kSimd128ScratchReg2, i.InputSimd128Register(2),
kSimd128ScratchReg2);
__ vor_vv(i.OutputSimd128Register(), kSimd128ScratchReg,
kSimd128ScratchReg2);
break;
}
case kRiscvF32x4UConvertI32x4: {
__ VU.set(kScratchReg, E32, m1);
__ VU.set(RoundingMode::RTZ);
__ vfcvt_f_xu_v(i.OutputSimd128Register(), i.InputSimd128Register(0));
break;
}
case kRiscvF32x4SConvertI32x4: {
__ VU.set(kScratchReg, E32, m1);
__ VU.set(RoundingMode::RTZ);
__ vfcvt_f_x_v(i.OutputSimd128Register(), i.InputSimd128Register(0));
break;
}
case kRiscvF32x4Div: {
__ VU.set(kScratchReg, E32, m1);
__ VU.set(RoundingMode::RTZ);
__ vfdiv_vv(i.OutputSimd128Register(), i.InputSimd128Register(1),
i.InputSimd128Register(0));
break;
}
case kRiscvF32x4Mul: {
__ VU.set(kScratchReg, E32, m1);
__ VU.set(RoundingMode::RTZ);
__ vfmul_vv(i.OutputSimd128Register(), i.InputSimd128Register(1),
i.InputSimd128Register(0));
break;
}
case kRiscvF32x4Eq: {
__ VU.set(kScratchReg, E32, m1);
__ vmfeq_vv(v0, i.InputSimd128Register(1), i.InputSimd128Register(0));
__ vmv_vx(i.OutputSimd128Register(), zero_reg);
__ vmerge_vi(i.OutputSimd128Register(), -1, i.OutputSimd128Register());
break;
}
case kRiscvF32x4Ne: {
__ VU.set(kScratchReg, E32, m1);
__ vmfne_vv(v0, i.InputSimd128Register(1), i.InputSimd128Register(0));
__ vmv_vx(i.OutputSimd128Register(), zero_reg);
__ vmerge_vi(i.OutputSimd128Register(), -1, i.OutputSimd128Register());
break;
}
case kRiscvF32x4Lt: {
__ VU.set(kScratchReg, E32, m1);
__ vmflt_vv(v0, i.InputSimd128Register(1), i.InputSimd128Register(0));
__ vmv_vx(i.OutputSimd128Register(), zero_reg);
__ vmerge_vi(i.OutputSimd128Register(), -1, i.OutputSimd128Register());
break;
}
case kRiscvF32x4Le: {
__ VU.set(kScratchReg, E32, m1);
__ vmfle_vv(v0, i.InputSimd128Register(1), i.InputSimd128Register(0));
__ vmv_vx(i.OutputSimd128Register(), zero_reg);
__ vmerge_vi(i.OutputSimd128Register(), -1, i.OutputSimd128Register());
break;
}
case kRiscvF32x4Max: {
__ VU.set(kScratchReg, E32, m1);
const int32_t kNaN = 0x7FC00000;
__ vmfeq_vv(v0, i.InputSimd128Register(0), i.InputSimd128Register(0));
__ vmfeq_vv(kSimd128ScratchReg, i.InputSimd128Register(1),
i.InputSimd128Register(1));
__ vand_vv(v0, v0, kSimd128ScratchReg);
__ li(kScratchReg, kNaN);
__ vmv_vx(i.OutputSimd128Register(), kScratchReg);
DCHECK_NE(i.OutputSimd128Register(), i.InputSimd128Register(1));
DCHECK_NE(i.OutputSimd128Register(), i.InputSimd128Register(0));
__ vfmax_vv(i.OutputSimd128Register(), i.InputSimd128Register(1),
i.InputSimd128Register(0), Mask);
break;
}
case kRiscvF32x4Min: {
__ VU.set(kScratchReg, E32, m1);
const int32_t kNaN = 0x7FC00000;
__ vmfeq_vv(v0, i.InputSimd128Register(0), i.InputSimd128Register(0));
__ vmfeq_vv(kSimd128ScratchReg, i.InputSimd128Register(1),
i.InputSimd128Register(1));
__ vand_vv(v0, v0, kSimd128ScratchReg);
__ li(kScratchReg, kNaN);
__ vmv_vx(i.OutputSimd128Register(), kScratchReg);
DCHECK_NE(i.OutputSimd128Register(), i.InputSimd128Register(1));
DCHECK_NE(i.OutputSimd128Register(), i.InputSimd128Register(0));
__ vfmin_vv(i.OutputSimd128Register(), i.InputSimd128Register(1),
i.InputSimd128Register(0));
break;
}
default: default:
#ifdef DEBUG #ifdef DEBUG
switch (arch_opcode) { switch (arch_opcode) {
......
...@@ -134,6 +134,8 @@ class Decoder { ...@@ -134,6 +134,8 @@ class Decoder {
void DecodeVType(Instruction* instr); void DecodeVType(Instruction* instr);
void DecodeRvvIVV(Instruction* instr); void DecodeRvvIVV(Instruction* instr);
void DecodeRvvFVV(Instruction* instr);
void DecodeRvvFVF(Instruction* instr);
void DecodeRvvIVI(Instruction* instr); void DecodeRvvIVI(Instruction* instr);
void DecodeRvvIVX(Instruction* instr); void DecodeRvvIVX(Instruction* instr);
void DecodeRvvVL(Instruction* instr); void DecodeRvvVL(Instruction* instr);
...@@ -800,7 +802,7 @@ int Decoder::FormatOption(Instruction* instr, const char* format) { ...@@ -800,7 +802,7 @@ int Decoder::FormatOption(Instruction* instr, const char* format) {
} }
UNREACHABLE(); UNREACHABLE();
} }
case 'v': { // 'vs1: Raw values from register fields case 'v': {
if (format[1] == 'd') { if (format[1] == 'd') {
DCHECK(STRING_STARTS_WITH(format, "vd")); DCHECK(STRING_STARTS_WITH(format, "vd"));
PrintVd(instr); PrintVd(instr);
...@@ -2155,6 +2157,12 @@ void Decoder::DecodeRvvIVX(Instruction* instr) { ...@@ -2155,6 +2157,12 @@ void Decoder::DecodeRvvIVX(Instruction* instr) {
UNREACHABLE(); UNREACHABLE();
} }
break; break;
case RO_V_VSLL_VX:
Format(instr, "vsll.vx 'vd, 'vs2, 'rs1");
break;
case RO_V_VSRL_VX:
Format(instr, "vsrl.vx 'vd, 'vs2, 'rs1");
break;
default: default:
UNSUPPORTED_RISCV(); UNSUPPORTED_RISCV();
break; break;
...@@ -2205,13 +2213,118 @@ void Decoder::DecodeRvvMVX(Instruction* instr) { ...@@ -2205,13 +2213,118 @@ void Decoder::DecodeRvvMVX(Instruction* instr) {
} }
} }
void Decoder::DecodeRvvFVV(Instruction* instr) {
DCHECK_EQ(instr->InstructionBits() & (kBaseOpcodeMask | kFunct3Mask), OP_FVV);
switch (instr->InstructionBits() & kVTypeMask) {
case RO_V_VFUNARY0:
switch (instr->Vs1Value()) {
case VFCVT_XU_F_V:
Format(instr, "vfcvt.xu.f.v 'vd, 'vs2'vm");
break;
case VFCVT_X_F_V:
Format(instr, "vfcvt.x.f.v 'vd, 'vs2'vm");
break;
case VFNCVT_F_F_W:
Format(instr, "vfncvt.f.f.w 'vd, 'vs2'vm");
break;
case VFCVT_F_X_V:
Format(instr, "vfcvt.f.x.v 'vd, 'vs2'vm");
break;
case VFCVT_F_XU_V:
Format(instr, "vfcvt.f.xu.v 'vd, 'vs2'vm");
break;
default:
UNSUPPORTED_RISCV();
break;
}
break;
case RO_V_VFUNARY1:
switch (instr->Vs1Value()) {
case VFCLASS_V:
Format(instr, "vfclass.v 'vd, 'vs2'vm");
break;
default:
break;
}
break;
case RO_V_VMFEQ_VV:
Format(instr, "vmfeq.vv 'vd, 'vs2, 'vs1'vm");
break;
case RO_V_VMFNE_VV:
Format(instr, "vmfne.vv 'vd, 'vs2, 'vs1'vm");
break;
case RO_V_VMFLT_VV:
Format(instr, "vmflt.vv 'vd, 'vs2, 'vs1'vm");
break;
case RO_V_VMFLE_VV:
Format(instr, "vmfle.vv 'vd, 'vs2, 'vs1'vm");
break;
case RO_V_VFMAX_VV:
Format(instr, "vfmax.vv 'vd, 'vs2, 'vs1'vm");
break;
case RO_V_VFMIN_VV:
Format(instr, "vfmin.vv 'vd, 'vs2, 'vs1'vm");
break;
case RO_V_VFSGNJ_VV:
Format(instr, "vfsgnj.vv 'vd, 'vs2, 'vs1'vm");
break;
case RO_V_VFSGNJN_VV:
if (instr->Vs1Value() == instr->Vs2Value()) {
Format(instr, "vneg.vv 'vd, 'vs1'vm");
} else {
Format(instr, "vfsgnjn.vv 'vd, 'vs2, 'vs1'vm");
}
break;
case RO_V_VFSGNJX_VV:
if (instr->Vs1Value() == instr->Vs2Value()) {
Format(instr, "vabs.vv 'vd, 'vs1'vm");
} else {
Format(instr, "vfsgnjn.vv 'vd, 'vs2, 'vs1'vm");
}
break;
case RO_V_VFADD_VV:
Format(instr, "vfadd.vv 'vd, 'vs2, 'vs1'vm");
break;
case RO_V_VFSUB_VV:
Format(instr, "vfsub.vv 'vd, 'vs2, 'vs1'vm");
break;
case RO_V_VFDIV_VV:
Format(instr, "vfdiv.vv 'vd, 'vs2, 'vs1'vm");
break;
case RO_V_VFMUL_VV:
Format(instr, "vfmul.vv 'vd, 'vs2, 'vs1'vm");
break;
default:
UNSUPPORTED_RISCV();
break;
}
}
void Decoder::DecodeRvvFVF(Instruction* instr) {
DCHECK_EQ(instr->InstructionBits() & (kBaseOpcodeMask | kFunct3Mask), OP_FVF);
switch (instr->InstructionBits() & kVTypeMask) {
case RO_V_VFSGNJ_VF:
Format(instr, "vfsgnj.vf 'vd, 'vs2, 'fs1'vm");
break;
case RO_V_VFSGNJN_VF:
Format(instr, "vfsgnjn.vf 'vd, 'vs2, 'fs1'vm");
break;
case RO_V_VFSGNJX_VF:
Format(instr, "vfsgnjn.vf 'vd, 'vs2, 'fs1'vm");
break;
default:
UNSUPPORTED_RISCV();
break;
}
}
void Decoder::DecodeVType(Instruction* instr) { void Decoder::DecodeVType(Instruction* instr) {
switch (instr->InstructionBits() & (kBaseOpcodeMask | kFunct3Mask)) { switch (instr->InstructionBits() & (kBaseOpcodeMask | kFunct3Mask)) {
case OP_IVV: case OP_IVV:
DecodeRvvIVV(instr); DecodeRvvIVV(instr);
return; return;
case OP_FVV: case OP_FVV:
UNSUPPORTED_RISCV(); DecodeRvvFVV(instr);
return; return;
case OP_MVV: case OP_MVV:
DecodeRvvMVV(instr); DecodeRvvMVV(instr);
...@@ -2502,7 +2615,7 @@ const char* NameConverter::NameOfXMMRegister(int reg) const { ...@@ -2502,7 +2615,7 @@ const char* NameConverter::NameOfXMMRegister(int reg) const {
const char* NameConverter::NameOfByteCPURegister(int reg) const { const char* NameConverter::NameOfByteCPURegister(int reg) const {
UNREACHABLE(); // RISC-V does not have the concept of a byte register. UNREACHABLE(); // RISC-V does not have the concept of a byte register.
//return "nobytereg"; // return "nobytereg";
} }
const char* NameConverter::NameInCode(byte* addr) const { const char* NameConverter::NameInCode(byte* addr) const {
......
This diff is collapsed.
...@@ -132,8 +132,11 @@ union u32_f32 { ...@@ -132,8 +132,11 @@ union u32_f32 {
inline float fsgnj32(float rs1, float rs2, bool n, bool x) { inline float fsgnj32(float rs1, float rs2, bool n, bool x) {
u32_f32 a = {.f = rs1}, b = {.f = rs2}; u32_f32 a = {.f = rs1}, b = {.f = rs2};
u32_f32 res; u32_f32 res;
res.u = res.u = (a.u & ~F32_SIGN) | ((((x) ? a.u
(a.u & ~F32_SIGN) | ((((x) ? a.u : (n) ? F32_SIGN : 0) ^ b.u) & F32_SIGN); : (n) ? F32_SIGN
: 0) ^
b.u) &
F32_SIGN);
return res.f; return res.f;
} }
#define F64_SIGN ((uint64_t)1 << 63) #define F64_SIGN ((uint64_t)1 << 63)
...@@ -144,8 +147,11 @@ union u64_f64 { ...@@ -144,8 +147,11 @@ union u64_f64 {
inline double fsgnj64(double rs1, double rs2, bool n, bool x) { inline double fsgnj64(double rs1, double rs2, bool n, bool x) {
u64_f64 a = {.d = rs1}, b = {.d = rs2}; u64_f64 a = {.d = rs1}, b = {.d = rs2};
u64_f64 res; u64_f64 res;
res.u = res.u = (a.u & ~F64_SIGN) | ((((x) ? a.u
(a.u & ~F64_SIGN) | ((((x) ? a.u : (n) ? F64_SIGN : 0) ^ b.u) & F64_SIGN); : (n) ? F64_SIGN
: 0) ^
b.u) &
F64_SIGN);
return res.d; return res.d;
} }
...@@ -923,6 +929,22 @@ class Simulator : public SimulatorBase { ...@@ -923,6 +929,22 @@ class Simulator : public SimulatorBase {
return alu_out; return alu_out;
} }
template <typename Func>
inline float CanonicalizeDoubleToFloatOperation(Func fn, double frs) {
float alu_out = fn(frs);
if (std::isnan(alu_out) || std::isnan(drs1()))
alu_out = std::numeric_limits<float>::quiet_NaN();
return alu_out;
}
template <typename Func>
inline float CanonicalizeFloatToDoubleOperation(Func fn, float frs) {
double alu_out = fn(frs);
if (std::isnan(alu_out) || std::isnan(frs1()))
alu_out = std::numeric_limits<double>::quiet_NaN();
return alu_out;
}
template <typename Func> template <typename Func>
inline float CanonicalizeFloatToDoubleOperation(Func fn) { inline float CanonicalizeFloatToDoubleOperation(Func fn) {
double alu_out = fn(frs1()); double alu_out = fn(frs1());
...@@ -957,6 +979,8 @@ class Simulator : public SimulatorBase { ...@@ -957,6 +979,8 @@ class Simulator : public SimulatorBase {
void DecodeRvvIVX(); void DecodeRvvIVX();
void DecodeRvvMVV(); void DecodeRvvMVV();
void DecodeRvvMVX(); void DecodeRvvMVX();
void DecodeRvvFVV();
void DecodeRvvFVF();
bool DecodeRvvVL(); bool DecodeRvvVL();
bool DecodeRvvVS(); bool DecodeRvvVS();
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment