From 09140c07e13ddd3951c231e1fb7cbe2d3d41f7aa Mon Sep 17 00:00:00 2001 From: Philipp Tomsich Date: Fri, 17 Mar 2023 20:38:34 +0100 Subject: Implement Zfa. This passes our developer test suite, when comparing output (signature) against the SAIL implementation. If any corner-cases require additional changes after ACT goes upstream, we can apply an add-on patch. --- riscv/insns/fcvtmod_w_d.h | 58 +++++++++++++++++++++++++++++++++++++++++++++++ riscv/insns/fleq_d.h | 4 ++++ riscv/insns/fleq_h.h | 4 ++++ riscv/insns/fleq_q.h | 4 ++++ riscv/insns/fleq_s.h | 4 ++++ riscv/insns/fli_d.h | 40 ++++++++++++++++++++++++++++++++ riscv/insns/fli_h.h | 40 ++++++++++++++++++++++++++++++++ riscv/insns/fli_q.h | 46 +++++++++++++++++++++++++++++++++++++ riscv/insns/fli_s.h | 40 ++++++++++++++++++++++++++++++++ riscv/insns/fltq_d.h | 4 ++++ riscv/insns/fltq_h.h | 4 ++++ riscv/insns/fltq_q.h | 4 ++++ riscv/insns/fltq_s.h | 4 ++++ riscv/insns/fmaxm_d.h | 10 ++++++++ riscv/insns/fmaxm_h.h | 10 ++++++++ riscv/insns/fmaxm_q.h | 17 ++++++++++++++ riscv/insns/fmaxm_s.h | 10 ++++++++ riscv/insns/fminm_d.h | 10 ++++++++ riscv/insns/fminm_h.h | 10 ++++++++ riscv/insns/fminm_q.h | 17 ++++++++++++++ riscv/insns/fminm_s.h | 10 ++++++++ riscv/insns/fmvh_x_d.h | 7 ++++++ riscv/insns/fmvh_x_q.h | 7 ++++++ riscv/insns/fmvp_d_x.h | 8 +++++++ riscv/insns/fmvp_q_x.h | 8 +++++++ riscv/insns/fround_d.h | 5 ++++ riscv/insns/fround_h.h | 5 ++++ riscv/insns/fround_q.h | 5 ++++ riscv/insns/fround_s.h | 5 ++++ riscv/insns/froundnx_d.h | 5 ++++ riscv/insns/froundnx_h.h | 5 ++++ riscv/insns/froundnx_q.h | 5 ++++ riscv/insns/froundnx_s.h | 5 ++++ riscv/isa_parser.cc | 2 ++ riscv/isa_parser.h | 1 + riscv/riscv.mk.in | 45 ++++++++++++++++++++++++++++++++++++ 36 files changed, 468 insertions(+) create mode 100644 riscv/insns/fcvtmod_w_d.h create mode 100644 riscv/insns/fleq_d.h create mode 100644 riscv/insns/fleq_h.h create mode 100644 riscv/insns/fleq_q.h create mode 100644 riscv/insns/fleq_s.h create mode 100644 riscv/insns/fli_d.h create mode 100644 riscv/insns/fli_h.h create mode 100644 riscv/insns/fli_q.h create mode 100644 riscv/insns/fli_s.h create mode 100644 riscv/insns/fltq_d.h create mode 100644 riscv/insns/fltq_h.h create mode 100644 riscv/insns/fltq_q.h create mode 100644 riscv/insns/fltq_s.h create mode 100644 riscv/insns/fmaxm_d.h create mode 100644 riscv/insns/fmaxm_h.h create mode 100644 riscv/insns/fmaxm_q.h create mode 100644 riscv/insns/fmaxm_s.h create mode 100644 riscv/insns/fminm_d.h create mode 100644 riscv/insns/fminm_h.h create mode 100644 riscv/insns/fminm_q.h create mode 100644 riscv/insns/fminm_s.h create mode 100644 riscv/insns/fmvh_x_d.h create mode 100644 riscv/insns/fmvh_x_q.h create mode 100644 riscv/insns/fmvp_d_x.h create mode 100644 riscv/insns/fmvp_q_x.h create mode 100644 riscv/insns/fround_d.h create mode 100644 riscv/insns/fround_h.h create mode 100644 riscv/insns/fround_q.h create mode 100644 riscv/insns/fround_s.h create mode 100644 riscv/insns/froundnx_d.h create mode 100644 riscv/insns/froundnx_h.h create mode 100644 riscv/insns/froundnx_q.h create mode 100644 riscv/insns/froundnx_s.h diff --git a/riscv/insns/fcvtmod_w_d.h b/riscv/insns/fcvtmod_w_d.h new file mode 100644 index 0000000..89b9b95 --- /dev/null +++ b/riscv/insns/fcvtmod_w_d.h @@ -0,0 +1,58 @@ +require_extension('D'); +require_extension(EXT_ZFA); +require_fp; +uint64_t a = FRS1_D.v; + +uint32_t sign = signF64UI(a); +uint32_t exp = expF64UI(a); +uint64_t frac = fracF64UI(a); + +bool inexact = false; +bool invalid = false; + +if (exp == 0) { + inexact = (frac != 0); + frac = 0; +} else if (exp == 0x7ff) { + /* inf or NaN */ + invalid = true; + frac = 0; +} else { + int true_exp = exp - 1023; + int shift = true_exp - 52; + + /* Restore implicit bit. */ + frac |= 1ull << 52; + + /* Shift the fraction into place. */ + if (shift >= 64) { + /* The fraction is shifted out entirely. */ + frac = 0; + } else if ((shift >= 0) && (shift < 64)) { + /* The number is so large we must shift the fraction left. */ + frac <<= shift; + } else if ((shift > -64) && (shift < 0)) { + /* Normal case -- shift right and notice if bits shift out. */ + inexact = (frac << (64 + shift)) != 0; + frac >>= -shift; + } else { + /* The fraction is shifted out entirely. */ + frac = 0; + } + + /* Notice overflow or inexact exceptions. */ + if (true_exp > 31 || frac > (sign ? 0x80000000ull : 0x7fffffff)) { + /* Overflow, for which this operation raises invalid. */ + invalid = true; + } + + /* Honor the sign. */ + if (sign) { + frac = -frac; + } +} + +WRITE_RD(sext32(frac)); +STATE.fflags->write(STATE.fflags->read() | + (inexact ? softfloat_flag_inexact : 0) | + (invalid ? softfloat_flag_invalid : 0)); diff --git a/riscv/insns/fleq_d.h b/riscv/insns/fleq_d.h new file mode 100644 index 0000000..762e147 --- /dev/null +++ b/riscv/insns/fleq_d.h @@ -0,0 +1,4 @@ +require_extension('D'); +require_extension(EXT_ZFA); +require_fp; +WRITE_RD(f64_le_quiet(FRS1_D, FRS2_D)); diff --git a/riscv/insns/fleq_h.h b/riscv/insns/fleq_h.h new file mode 100644 index 0000000..7e6db59 --- /dev/null +++ b/riscv/insns/fleq_h.h @@ -0,0 +1,4 @@ +require_extension(EXT_ZFH); +require_extension(EXT_ZFA); +require_fp; +WRITE_RD(f16_le_quiet(FRS1_H, FRS2_H)); diff --git a/riscv/insns/fleq_q.h b/riscv/insns/fleq_q.h new file mode 100644 index 0000000..8533d11 --- /dev/null +++ b/riscv/insns/fleq_q.h @@ -0,0 +1,4 @@ +require_extension('Q'); +require_extension(EXT_ZFA); +require_fp; +WRITE_RD(f128_le_quiet(f128(FRS1), f128(FRS2))); diff --git a/riscv/insns/fleq_s.h b/riscv/insns/fleq_s.h new file mode 100644 index 0000000..8c0a909 --- /dev/null +++ b/riscv/insns/fleq_s.h @@ -0,0 +1,4 @@ +require_extension('F'); +require_extension(EXT_ZFA); +require_fp; +WRITE_RD(f32_le_quiet(FRS1_F, FRS2_F)); diff --git a/riscv/insns/fli_d.h b/riscv/insns/fli_d.h new file mode 100644 index 0000000..090e88c --- /dev/null +++ b/riscv/insns/fli_d.h @@ -0,0 +1,40 @@ +require_extension('D'); +require_extension(EXT_ZFA); +require_fp; +{ + const uint64_t bits[32] = { + [0b00000] = 0xbff0000000000000ull, /* -1.0 */ + [0b00001] = 0x0010000000000000ull, /* minimum positive normal */ + [0b00010] = 0x3ef0000000000000ull, /* 1.0 * 2^-16 */ + [0b00011] = 0x3f00000000000000ull, /* 1.0 * 2^-15 */ + [0b00100] = 0x3f70000000000000ull, /* 1.0 * 2^-8 */ + [0b00101] = 0x3f80000000000000ull, /* 1.0 * 2^-7 */ + [0b00110] = 0x3fb0000000000000ull, /* 1.0 * 2^-4 */ + [0b00111] = 0x3fc0000000000000ull, /* 1.0 * 2^-3 */ + [0b01000] = 0x3fd0000000000000ull, /* 0.25 */ + [0b01001] = 0x3fd4000000000000ull, /* 0.3125 */ + [0b01010] = 0x3fd8000000000000ull, /* 0.375 */ + [0b01011] = 0x3fdc000000000000ull, /* 0.4375 */ + [0b01100] = 0x3fe0000000000000ull, /* 0.5 */ + [0b01101] = 0x3fe4000000000000ull, /* 0.625 */ + [0b01110] = 0x3fe8000000000000ull, /* 0.75 */ + [0b01111] = 0x3fec000000000000ull, /* 0.875 */ + [0b10000] = 0x3ff0000000000000ull, /* 1.0 */ + [0b10001] = 0x3ff4000000000000ull, /* 1.25 */ + [0b10010] = 0x3ff8000000000000ull, /* 1.5 */ + [0b10011] = 0x3ffc000000000000ull, /* 1.75 */ + [0b10100] = 0x4000000000000000ull, /* 2.0 */ + [0b10101] = 0x4004000000000000ull, /* 2.5 */ + [0b10110] = 0x4008000000000000ull, /* 3 */ + [0b10111] = 0x4010000000000000ull, /* 4 */ + [0b11000] = 0x4020000000000000ull, /* 8 */ + [0b11001] = 0x4030000000000000ull, /* 16 */ + [0b11010] = 0x4060000000000000ull, /* 2^7 */ + [0b11011] = 0x4070000000000000ull, /* 2^8 */ + [0b11100] = 0x40e0000000000000ull, /* 2^15 */ + [0b11101] = 0x40f0000000000000ull, /* 2^16 */ + [0b11110] = 0x7ff0000000000000ull, /* +inf */ + [0b11111] = defaultNaNF64UI + }; + WRITE_FRD_D(f64(bits[insn.rs1()])); +} diff --git a/riscv/insns/fli_h.h b/riscv/insns/fli_h.h new file mode 100644 index 0000000..ddf41a9 --- /dev/null +++ b/riscv/insns/fli_h.h @@ -0,0 +1,40 @@ +require_extension(EXT_ZFH); +require_extension(EXT_ZFA); +require_fp; +{ + static const uint16_t bits[32] = { + [0b00000] = 0xbc00, /* -1.0 */ + [0b00001] = 0x0400, /* minimum positive normal */ + [0b00010] = 0x0100, /* 1.0 * 2^-16 */ + [0b00011] = 0x0200, /* 1.0 * 2^-15 */ + [0b00100] = 0x1c00, /* 1.0 * 2^-8 */ + [0b00101] = 0x2000, /* 1.0 * 2^-7 */ + [0b00110] = 0x2c00, /* 1.0 * 2^-4 */ + [0b00111] = 0x3000, /* 1.0 * 2^-3 */ + [0b01000] = 0x3400, /* 0.25 */ + [0b01001] = 0x3500, /* 0.3125 */ + [0b01010] = 0x3600, /* 0.375 */ + [0b01011] = 0x3700, /* 0.4375 */ + [0b01100] = 0x3800, /* 0.5 */ + [0b01101] = 0x3900, /* 0.625 */ + [0b01110] = 0x3a00, /* 0.75 */ + [0b01111] = 0x3b00, /* 0.875 */ + [0b10000] = 0x3c00, /* 1.0 */ + [0b10001] = 0x3d00, /* 1.25 */ + [0b10010] = 0x3e00, /* 1.5 */ + [0b10011] = 0x3f00, /* 1.75 */ + [0b10100] = 0x4000, /* 2.0 */ + [0b10101] = 0x4100, /* 2.5 */ + [0b10110] = 0x4200, /* 3 */ + [0b10111] = 0x4400, /* 4 */ + [0b11000] = 0x4800, /* 8 */ + [0b11001] = 0x4c00, /* 16 */ + [0b11010] = 0x5800, /* 2^7 */ + [0b11011] = 0x5c00, /* 2^8 */ + [0b11100] = 0x7800, /* 2^15 */ + [0b11101] = 0x7c00, /* +inf (2^16 is not expressible) */ + [0b11110] = 0x7c00, /* +inf */ + [0b11111] = defaultNaNF16UI + }; + WRITE_FRD_H(f16(bits[insn.rs1()])); +} diff --git a/riscv/insns/fli_q.h b/riscv/insns/fli_q.h new file mode 100644 index 0000000..7ba569b --- /dev/null +++ b/riscv/insns/fli_q.h @@ -0,0 +1,46 @@ +require_extension('D'); +require_extension(EXT_ZFA); +require_fp; +{ + const uint64_t bits[32] = { + [0b00000] = 0xBFFF000000000000ull, /* -1.0 */ + [0b00001] = 0x0001000000000000ull, /* minimum positive normal */ + [0b00010] = 0x3FEF000000000000ull, /* 1.0 * 2^-16 */ + [0b00011] = 0x3FF0000000000000ull, /* 1.0 * 2^-15 */ + [0b00100] = 0x3FF7000000000000ull, /* 1.0 * 2^-8 */ + [0b00101] = 0x3FF8000000000000ull, /* 1.0 * 2^-7 */ + [0b00110] = 0x3FFB000000000000ull, /* 1.0 * 2^-4 */ + [0b00111] = 0x3FF9000000000000ull, /* 1.0 * 2^-3 */ + [0b01000] = 0x3FFD000000000000ull, /* 0.25 */ + [0b01001] = 0x3FFD400000000000ull, /* 0.3125 */ + [0b01010] = 0x3FFD800000000000ull, /* 0.375 */ + [0b01011] = 0x3FFDC00000000000ull, /* 0.4375 */ + [0b01100] = 0x3FFE000000000000ull, /* 0.5 */ + [0b01101] = 0x3FFE400000000000ull, /* 0.625 */ + [0b01110] = 0x3FFE800000000000ull, /* 0.75 */ + [0b01111] = 0x3FFEC00000000000ull, /* 0.875 */ + [0b10000] = 0x3FFF000000000000ull, /* 1.0 */ + [0b10001] = 0x3FFF400000000000ull, /* 1.25 */ + [0b10010] = 0x3FFFC00000000000ull, /* 1.5 */ + [0b10011] = 0x4000000000000000ull, /* 1.75 */ + [0b10100] = 0x4000400000000000ull, /* 2.0 */ + [0b10101] = 0x4000800000000000ull, /* 2.5 */ + [0b10110] = 0x4001000000000000ull, /* 3 */ + [0b10111] = 0x4002000000000000ull, /* 4 */ + [0b11000] = 0x4003000000000000ull, /* 8 */ + [0b11001] = 0x400D000000000000ull, /* 16 */ + [0b11010] = 0x4006000000000000ull, /* 2^7 */ + [0b11011] = 0x4007000000000000ull, /* 2^8 */ + [0b11100] = 0x400E000000000000ull, /* 2^15 */ + [0b11101] = 0x400F000000000000ull, /* 2^16 */ + [0b11110] = 0x7FFF000000000000ull, /* +inf */ + [0b11111] = defaultNaNF128UI64 + }; + + static_assert(defaultNaNF128UI0 == 0, "LSBs of quad-precision NaN must be zero"); + + ui128_f128 ui; + ui.ui.v64 = bits[insn.rs1()]; + ui.ui.v0 = 0; + WRITE_FRD(f128(ui.f)); +} diff --git a/riscv/insns/fli_s.h b/riscv/insns/fli_s.h new file mode 100644 index 0000000..e03b3b7 --- /dev/null +++ b/riscv/insns/fli_s.h @@ -0,0 +1,40 @@ +require_extension('F'); +require_extension(EXT_ZFA); +require_fp; +{ + const uint32_t bits[32] = { + [0b00000] = 0xbf800000, /* -1.0 */ + [0b00001] = 0x00800000, /* minimum positive normal */ + [0b00010] = 0x37800000, /* 1.0 * 2^-16 */ + [0b00011] = 0x38000000, /* 1.0 * 2^-15 */ + [0b00100] = 0x3b800000, /* 1.0 * 2^-8 */ + [0b00101] = 0x3c000000, /* 1.0 * 2^-7 */ + [0b00110] = 0x3d800000, /* 1.0 * 2^-4 */ + [0b00111] = 0x3e000000, /* 1.0 * 2^-3 */ + [0b01000] = 0x3e800000, /* 0.25 */ + [0b01001] = 0x3ea00000, /* 0.3125 */ + [0b01010] = 0x3ec00000, /* 0.375 */ + [0b01011] = 0x3ee00000, /* 0.4375 */ + [0b01100] = 0x3f000000, /* 0.5 */ + [0b01101] = 0x3f200000, /* 0.625 */ + [0b01110] = 0x3f400000, /* 0.75 */ + [0b01111] = 0x3f600000, /* 0.875 */ + [0b10000] = 0x3f800000, /* 1.0 */ + [0b10001] = 0x3fa00000, /* 1.25 */ + [0b10010] = 0x3fc00000, /* 1.5 */ + [0b10011] = 0x3fe00000, /* 1.75 */ + [0b10100] = 0x40000000, /* 2.0 */ + [0b10101] = 0x40200000, /* 2.5 */ + [0b10110] = 0x40400000, /* 3 */ + [0b10111] = 0x40800000, /* 4 */ + [0b11000] = 0x41000000, /* 8 */ + [0b11001] = 0x41800000, /* 16 */ + [0b11010] = 0x43000000, /* 2^7 */ + [0b11011] = 0x43800000, /* 2^8 */ + [0b11100] = 0x47000000, /* 2^15 */ + [0b11101] = 0x47800000, /* 2^16 */ + [0b11110] = 0x7f800000, /* +inf */ + [0b11111] = defaultNaNF32UI + }; + WRITE_FRD_F(f32(bits[insn.rs1()])); +} diff --git a/riscv/insns/fltq_d.h b/riscv/insns/fltq_d.h new file mode 100644 index 0000000..c7ec9f1 --- /dev/null +++ b/riscv/insns/fltq_d.h @@ -0,0 +1,4 @@ +require_extension('D'); +require_extension(EXT_ZFA); +require_fp; +WRITE_RD(f64_lt_quiet(FRS1_D, FRS2_D)); diff --git a/riscv/insns/fltq_h.h b/riscv/insns/fltq_h.h new file mode 100644 index 0000000..84d880a --- /dev/null +++ b/riscv/insns/fltq_h.h @@ -0,0 +1,4 @@ +require_extension(EXT_ZFH); +require_extension(EXT_ZFA); +require_fp; +WRITE_RD(f16_lt_quiet(FRS1_H, FRS2_H)); diff --git a/riscv/insns/fltq_q.h b/riscv/insns/fltq_q.h new file mode 100644 index 0000000..a65ca76 --- /dev/null +++ b/riscv/insns/fltq_q.h @@ -0,0 +1,4 @@ +require_extension('Q'); +require_extension(EXT_ZFA); +require_fp; +WRITE_RD(f128_lt_quiet(f128(FRS1), f128(FRS2))); diff --git a/riscv/insns/fltq_s.h b/riscv/insns/fltq_s.h new file mode 100644 index 0000000..1ee0983 --- /dev/null +++ b/riscv/insns/fltq_s.h @@ -0,0 +1,4 @@ +require_extension('F'); +require_extension(EXT_ZFA); +require_fp; +WRITE_RD(f32_lt_quiet(FRS1_F, FRS2_F)); diff --git a/riscv/insns/fmaxm_d.h b/riscv/insns/fmaxm_d.h new file mode 100644 index 0000000..0cecd64 --- /dev/null +++ b/riscv/insns/fmaxm_d.h @@ -0,0 +1,10 @@ +require_extension('D'); +require_extension(EXT_ZFA); +require_fp; +bool greater = f64_lt_quiet(FRS2_D, FRS1_D) || + (f64_eq(FRS2_D, FRS1_D) && (FRS2_D.v & F64_SIGN)); +if (isNaNF64UI(FRS1_D.v) || isNaNF64UI(FRS2_D.v)) + WRITE_FRD_D(f64(defaultNaNF64UI)); +else + WRITE_FRD_D(greater ? FRS1_D : FRS2_D); +set_fp_exceptions; diff --git a/riscv/insns/fmaxm_h.h b/riscv/insns/fmaxm_h.h new file mode 100644 index 0000000..0eb00ea --- /dev/null +++ b/riscv/insns/fmaxm_h.h @@ -0,0 +1,10 @@ +require_extension(EXT_ZFH); +require_extension(EXT_ZFA); +require_fp; +bool greater = f16_lt_quiet(FRS2_H, FRS1_H) || + (f16_eq(FRS2_H, FRS1_H) && (FRS2_H.v & F16_SIGN)); +if (isNaNF16UI(FRS1_H.v) || isNaNF16UI(FRS2_H.v)) + WRITE_FRD_H(f16(defaultNaNF16UI)); +else + WRITE_FRD_H(greater ? FRS1_H : FRS2_H); +set_fp_exceptions; diff --git a/riscv/insns/fmaxm_q.h b/riscv/insns/fmaxm_q.h new file mode 100644 index 0000000..a48031e --- /dev/null +++ b/riscv/insns/fmaxm_q.h @@ -0,0 +1,17 @@ +require_extension('D'); +require_extension(EXT_ZFA); +require_fp; +ui128_f128 ui1; +ui1.f = f128(FRS1); +ui128_f128 ui2; +ui2.f = f128(FRS2); +bool greater = f128_lt_quiet(f128(FRS2), f128(FRS1)) || + (f128_eq(f128(FRS1), f128(FRS2)) && (signF128UI64(ui2.ui.v64))); +if (isNaNF128UI(ui1.ui.v64, ui1.ui.v0) || isNaNF128UI(ui2.ui.v64, ui2.ui.v0)) { + ui128_f128 ui; + ui.ui.v64 = defaultNaNF128UI64; + ui.ui.v0 = defaultNaNF128UI0; + WRITE_FRD(f128(ui.f)); + } else + WRITE_FRD(greater ? f128(FRS1) : f128(FRS2)); +set_fp_exceptions; diff --git a/riscv/insns/fmaxm_s.h b/riscv/insns/fmaxm_s.h new file mode 100644 index 0000000..ebf195a --- /dev/null +++ b/riscv/insns/fmaxm_s.h @@ -0,0 +1,10 @@ +require_extension('F'); +require_extension(EXT_ZFA); +require_fp; +bool greater = f32_lt_quiet(FRS2_F, FRS1_F) || + (f32_eq(FRS2_F, FRS1_F) && (FRS2_F.v & F32_SIGN)); +if (isNaNF32UI(FRS1_F.v) || isNaNF32UI(FRS2_F.v)) + WRITE_FRD_F(f32(defaultNaNF32UI)); +else + WRITE_FRD_F(greater ? FRS1_F : FRS2_F); +set_fp_exceptions; diff --git a/riscv/insns/fminm_d.h b/riscv/insns/fminm_d.h new file mode 100644 index 0000000..a60d3e8 --- /dev/null +++ b/riscv/insns/fminm_d.h @@ -0,0 +1,10 @@ +require_extension('D'); +require_extension(EXT_ZFA); +require_fp; +bool less = f64_lt_quiet(FRS1_D, FRS2_D) || + (f64_eq(FRS2_D, FRS1_D) && (FRS1_D.v & F64_SIGN)); +if (isNaNF64UI(FRS1_D.v) || isNaNF64UI(FRS2_D.v)) + WRITE_FRD_D(f64(defaultNaNF64UI)); +else + WRITE_FRD_D(less ? FRS1_D : FRS2_D); +set_fp_exceptions; diff --git a/riscv/insns/fminm_h.h b/riscv/insns/fminm_h.h new file mode 100644 index 0000000..0f207e8 --- /dev/null +++ b/riscv/insns/fminm_h.h @@ -0,0 +1,10 @@ +require_extension(EXT_ZFH); +require_extension(EXT_ZFA); +require_fp; +bool less = f16_lt_quiet(FRS1_H, FRS2_H) || + (f16_eq(FRS2_H, FRS1_H) && (FRS1_H.v & F16_SIGN)); +if (isNaNF16UI(FRS1_H.v) || isNaNF16UI(FRS2_H.v)) + WRITE_FRD_H(f16(defaultNaNF16UI)); +else + WRITE_FRD_H(less ? FRS1_H : FRS2_H); +set_fp_exceptions; diff --git a/riscv/insns/fminm_q.h b/riscv/insns/fminm_q.h new file mode 100644 index 0000000..bccd7ed --- /dev/null +++ b/riscv/insns/fminm_q.h @@ -0,0 +1,17 @@ +require_extension('Q'); +require_extension(EXT_ZFA); +require_fp; +ui128_f128 ui1; +ui1.f = f128(FRS1); +ui128_f128 ui2; +ui2.f = f128(FRS2); +bool less = f128_lt_quiet(f128(FRS1), f128(FRS2)) || + (f128_eq(f128(FRS1), f128(FRS2)) && (signF128UI64(ui1.ui.v64))); +if (isNaNF128UI(ui1.ui.v64, ui1.ui.v0) || isNaNF128UI(ui2.ui.v64, ui2.ui.v0)) { + ui128_f128 ui; + ui.ui.v64 = defaultNaNF128UI64; + ui.ui.v0 = defaultNaNF128UI0; + WRITE_FRD(f128(ui.f)); + } else + WRITE_FRD(less ? f128(FRS1) : f128(FRS2)); +set_fp_exceptions; diff --git a/riscv/insns/fminm_s.h b/riscv/insns/fminm_s.h new file mode 100644 index 0000000..b1c60f8 --- /dev/null +++ b/riscv/insns/fminm_s.h @@ -0,0 +1,10 @@ +require_extension('F'); +require_extension(EXT_ZFA); +require_fp; +bool less = f32_lt_quiet(FRS1_F, FRS2_F) || + (f32_eq(FRS2_F, FRS1_F) && (FRS1_F.v & F32_SIGN)); +if (isNaNF32UI(FRS1_F.v) || isNaNF32UI(FRS2_F.v)) + WRITE_FRD_F(f32(defaultNaNF32UI)); +else + WRITE_FRD_F(less ? FRS1_F : FRS2_F); +set_fp_exceptions; diff --git a/riscv/insns/fmvh_x_d.h b/riscv/insns/fmvh_x_d.h new file mode 100644 index 0000000..961ad76 --- /dev/null +++ b/riscv/insns/fmvh_x_d.h @@ -0,0 +1,7 @@ +require_rv32; +require_extension('D'); +require_extension(EXT_ZFA); +require_fp; +ui64_f64 ui; +ui.f = FRS1_D; +WRITE_RD(ui.ui >> 32); diff --git a/riscv/insns/fmvh_x_q.h b/riscv/insns/fmvh_x_q.h new file mode 100644 index 0000000..12a3923 --- /dev/null +++ b/riscv/insns/fmvh_x_q.h @@ -0,0 +1,7 @@ +require_rv64; +require_extension('Q'); +require_extension(EXT_ZFA); +require_fp; +ui128_f128 ui; +ui.f = f128(FRS1); +WRITE_RD(ui.ui.v64); diff --git a/riscv/insns/fmvp_d_x.h b/riscv/insns/fmvp_d_x.h new file mode 100644 index 0000000..f95cfe9 --- /dev/null +++ b/riscv/insns/fmvp_d_x.h @@ -0,0 +1,8 @@ +require_rv32; +require_extension('D'); +require_extension(EXT_ZFA); +require_fp; +ui64_f64 ui; +ui.ui = ((uint64_t)RS2) << 32; +ui.ui |= RS1; +WRITE_FRD_D(f64(ui.ui)); diff --git a/riscv/insns/fmvp_q_x.h b/riscv/insns/fmvp_q_x.h new file mode 100644 index 0000000..99c7bfd --- /dev/null +++ b/riscv/insns/fmvp_q_x.h @@ -0,0 +1,8 @@ +require_rv64; +require_extension('Q'); +require_extension(EXT_ZFA); +require_fp; +ui128_f128 ui; +ui.ui.v64 = RS2; +ui.ui.v0 = RS1; +WRITE_FRD(f128(ui.f)); diff --git a/riscv/insns/fround_d.h b/riscv/insns/fround_d.h new file mode 100644 index 0000000..1127135 --- /dev/null +++ b/riscv/insns/fround_d.h @@ -0,0 +1,5 @@ +require_extension('D'); +require_extension(EXT_ZFA); +require_fp; +WRITE_FRD_D(f64_roundToInt(FRS1_D, RM, true)); +set_fp_exceptions; diff --git a/riscv/insns/fround_h.h b/riscv/insns/fround_h.h new file mode 100644 index 0000000..6417a39 --- /dev/null +++ b/riscv/insns/fround_h.h @@ -0,0 +1,5 @@ +require_extension(EXT_ZFH); +require_extension(EXT_ZFA); +require_fp; +WRITE_FRD_H(f16_roundToInt(FRS1_H, RM, true)); +set_fp_exceptions; diff --git a/riscv/insns/fround_q.h b/riscv/insns/fround_q.h new file mode 100644 index 0000000..51ebce2 --- /dev/null +++ b/riscv/insns/fround_q.h @@ -0,0 +1,5 @@ +require_extension('Q'); +require_extension(EXT_ZFA); +require_fp; +WRITE_FRD(f128_roundToInt(f128(FRS1), RM, true)); +set_fp_exceptions; diff --git a/riscv/insns/fround_s.h b/riscv/insns/fround_s.h new file mode 100644 index 0000000..272897e --- /dev/null +++ b/riscv/insns/fround_s.h @@ -0,0 +1,5 @@ +require_extension('F'); +require_extension(EXT_ZFA); +require_fp; +WRITE_FRD_F(f32_roundToInt(FRS1_F, RM, true)); +set_fp_exceptions; diff --git a/riscv/insns/froundnx_d.h b/riscv/insns/froundnx_d.h new file mode 100644 index 0000000..0e8a1ba --- /dev/null +++ b/riscv/insns/froundnx_d.h @@ -0,0 +1,5 @@ +require_extension('D'); +require_extension(EXT_ZFA); +require_fp; +WRITE_FRD_D(f64_roundToInt(FRS1_D, RM, false)); +set_fp_exceptions; diff --git a/riscv/insns/froundnx_h.h b/riscv/insns/froundnx_h.h new file mode 100644 index 0000000..0c6cdae --- /dev/null +++ b/riscv/insns/froundnx_h.h @@ -0,0 +1,5 @@ +require_extension(EXT_ZFH); +require_extension(EXT_ZFA); +require_fp; +WRITE_FRD_H(f16_roundToInt(FRS1_H, RM, false)); +set_fp_exceptions; diff --git a/riscv/insns/froundnx_q.h b/riscv/insns/froundnx_q.h new file mode 100644 index 0000000..91bab77 --- /dev/null +++ b/riscv/insns/froundnx_q.h @@ -0,0 +1,5 @@ +require_extension('Q'); +require_extension(EXT_ZFA); +require_fp; +WRITE_FRD(f128_roundToInt(f128(FRS1), RM, false)); +set_fp_exceptions; diff --git a/riscv/insns/froundnx_s.h b/riscv/insns/froundnx_s.h new file mode 100644 index 0000000..f6e75f5 --- /dev/null +++ b/riscv/insns/froundnx_s.h @@ -0,0 +1,5 @@ +require_extension('F'); +require_extension(EXT_ZFA); +require_fp; +WRITE_FRD_F(f32_roundToInt(FRS1_F, RM, false)); +set_fp_exceptions; diff --git a/riscv/isa_parser.cc b/riscv/isa_parser.cc index 2a8e33f..7335a14 100644 --- a/riscv/isa_parser.cc +++ b/riscv/isa_parser.cc @@ -219,6 +219,8 @@ isa_parser_t::isa_parser_t(const char* str, const char *priv) extension_table[EXT_SVPBMT] = true; } else if (ext_str == "svinval") { extension_table[EXT_SVINVAL] = true; + } else if (ext_str == "zfa") { + extension_table[EXT_ZFA] = true; } else if (ext_str == "zicbom") { extension_table[EXT_ZICBOM] = true; } else if (ext_str == "zicboz") { diff --git a/riscv/isa_parser.h b/riscv/isa_parser.h index 090a9b5..9effd16 100644 --- a/riscv/isa_parser.h +++ b/riscv/isa_parser.h @@ -48,6 +48,7 @@ typedef enum { EXT_SVPBMT, EXT_SVINVAL, EXT_ZDINX, + EXT_ZFA, EXT_ZFINX, EXT_ZHINX, EXT_ZHINXMIN, diff --git a/riscv/riscv.mk.in b/riscv/riscv.mk.in index f64711a..f1b29aa 100644 --- a/riscv/riscv.mk.in +++ b/riscv/riscv.mk.in @@ -239,6 +239,15 @@ riscv_insn_ext_f = \ fsub_s \ fsw \ +riscv_insn_ext_f_zfa= \ + fli_s \ + fmaxm_s \ + fminm_s \ + fround_s \ + froundnx_s \ + fleq_s \ + fltq_s + riscv_insn_ext_d = \ fadd_d \ fclass_d \ @@ -274,6 +283,18 @@ riscv_insn_ext_d = \ fsqrt_d \ fsub_d \ +riscv_insn_ext_d_zfa = \ + fli_d \ + fmaxm_d \ + fminm_d \ + fround_d \ + froundnx_d \ + fmvh_x_d \ + fmvp_d_x \ + fcvtmod_w_d \ + fleq_d \ + fltq_d + riscv_insn_ext_zfh = \ fadd_h \ fclass_h \ @@ -312,6 +333,15 @@ riscv_insn_ext_zfh = \ fsqrt_h \ fsub_h \ +riscv_insn_ext_zfh_zfa = \ + fli_h \ + fmaxm_h \ + fminm_h \ + fround_h \ + froundnx_h \ + fleq_h \ + fltq_h + riscv_insn_ext_q = \ fadd_q \ fclass_q \ @@ -345,6 +375,17 @@ riscv_insn_ext_q = \ fsqrt_q \ fsub_q \ +riscv_insn_ext_q_zfa = \ + fli_q \ + fmaxm_q \ + fminm_q \ + fround_q \ + froundnx_q \ + fmvh_x_q \ + fmvp_q_x \ + fleq_q \ + fltq_q + riscv_insn_ext_b = \ add_uw \ andn \ @@ -1321,9 +1362,13 @@ riscv_insn_list = \ $(riscv_insn_ext_i) \ $(riscv_insn_ext_m) \ $(riscv_insn_ext_f) \ + $(riscv_insn_ext_f_zfa) \ $(riscv_insn_ext_d) \ + $(riscv_insn_ext_d_zfa) \ $(riscv_insn_ext_zfh) \ + $(riscv_insn_ext_zfh_zfa) \ $(riscv_insn_ext_q) \ + $(riscv_insn_ext_q_zfa) \ $(riscv_insn_ext_b) \ $(riscv_insn_ext_k) \ $(if $(HAVE_INT128),$(riscv_insn_ext_v),) \ -- cgit v1.1