aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPhilipp Tomsich <philipp.tomsich@vrull.eu>2023-03-17 20:38:34 +0100
committerPhilipp Tomsich <philipp.tomsich@vrull.eu>2023-04-03 16:55:14 -0700
commit09140c07e13ddd3951c231e1fb7cbe2d3d41f7aa (patch)
tree36b92616ad46d34ab23606a883f6e835a11f0f2d
parentf002b931d076af91c35dad05dd54580112b4a9d6 (diff)
downloadriscv-isa-sim-09140c07e13ddd3951c231e1fb7cbe2d3d41f7aa.zip
riscv-isa-sim-09140c07e13ddd3951c231e1fb7cbe2d3d41f7aa.tar.gz
riscv-isa-sim-09140c07e13ddd3951c231e1fb7cbe2d3d41f7aa.tar.bz2
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.
-rw-r--r--riscv/insns/fcvtmod_w_d.h58
-rw-r--r--riscv/insns/fleq_d.h4
-rw-r--r--riscv/insns/fleq_h.h4
-rw-r--r--riscv/insns/fleq_q.h4
-rw-r--r--riscv/insns/fleq_s.h4
-rw-r--r--riscv/insns/fli_d.h40
-rw-r--r--riscv/insns/fli_h.h40
-rw-r--r--riscv/insns/fli_q.h46
-rw-r--r--riscv/insns/fli_s.h40
-rw-r--r--riscv/insns/fltq_d.h4
-rw-r--r--riscv/insns/fltq_h.h4
-rw-r--r--riscv/insns/fltq_q.h4
-rw-r--r--riscv/insns/fltq_s.h4
-rw-r--r--riscv/insns/fmaxm_d.h10
-rw-r--r--riscv/insns/fmaxm_h.h10
-rw-r--r--riscv/insns/fmaxm_q.h17
-rw-r--r--riscv/insns/fmaxm_s.h10
-rw-r--r--riscv/insns/fminm_d.h10
-rw-r--r--riscv/insns/fminm_h.h10
-rw-r--r--riscv/insns/fminm_q.h17
-rw-r--r--riscv/insns/fminm_s.h10
-rw-r--r--riscv/insns/fmvh_x_d.h7
-rw-r--r--riscv/insns/fmvh_x_q.h7
-rw-r--r--riscv/insns/fmvp_d_x.h8
-rw-r--r--riscv/insns/fmvp_q_x.h8
-rw-r--r--riscv/insns/fround_d.h5
-rw-r--r--riscv/insns/fround_h.h5
-rw-r--r--riscv/insns/fround_q.h5
-rw-r--r--riscv/insns/fround_s.h5
-rw-r--r--riscv/insns/froundnx_d.h5
-rw-r--r--riscv/insns/froundnx_h.h5
-rw-r--r--riscv/insns/froundnx_q.h5
-rw-r--r--riscv/insns/froundnx_s.h5
-rw-r--r--riscv/isa_parser.cc2
-rw-r--r--riscv/isa_parser.h1
-rw-r--r--riscv/riscv.mk.in45
36 files changed, 468 insertions, 0 deletions
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),) \