On 11/28/24 04:42, Peter Maydell wrote:
+/*
+ * 3-input NaN propagation rule, for fused multiply-add. Individual
+ * architectures have different rules for which input NaN is
+ * propagated to the output when there is more than one NaN on the
+ * input.
+ *
+ * If default_nan_mode is enabled then it is valid not to set a NaN
+ * propagation rule, because the softfloat code guarantees not to try
+ * to pick a NaN to propagate in default NaN mode.  When not in
+ * default-NaN mode, it is an error for the target not to set the rule
+ * in float_status if it uses a muladd, and we will assert if we need
+ * to handle an input NaN and no rule was selected.
+ *
+ * For QEMU, the multiply-add operation is A * B + C.
+ *
+ * NB: we don't list all 12 possibilities here or implement them
+ * in pickNaNMulAdd; if your architecture needs one of the missing
+ * combinations you should add it.
+ */
+typedef enum __attribute__((__packed__)) {
+    /* No propagation rule specified */
+    float_3nan_prop_none = 0,
+    /* Prefer SNaN over QNaN, then operand A over B over C */
+    float_3nan_prop_s_abc,
+    /* Prefer SNaN over QNaN, then operand C over A over B */
+    float_3nan_prop_s_cab,
+    /* Prefer SNaN over QNaN, then operand C over B over A */
+    float_3nan_prop_s_cba,
+    /* Prefer A over B over C regardless of SNaN vs QNaN */
+    float_3nan_prop_abc,
+    /* Prefer A over C over B regardless of SNaN vs QNaN */
+    float_3nan_prop_acb,
+    /* Prefer C over B over A regardless of SNaN vs QNaN */
+    float_3nan_prop_cba,
+} Float3NaNPropRule;

Oof.  I was imagining a bit more data driven solution, rather than explicitly 
enumerating.

For instance:

FIELD(3NAN, 1ST, 0, 2)
FIELD(3NAN, 2ND, 2, 2)
FIELD(3NAN, 3RD, 4, 2)
FIELD(3NAN, SNAN, 6, 1)

float_3nan_prop_abc = (0 << R_3NAN_1ST_SHIFT)
                    | (1 << R_3NAN_2ND_SHIFT)
                    | (2 << R_3NAN_3RD_SHIFT),

float_3nan_prop_s_abc = float_3nan_prop_abc | R_3NAN_SNAN_MASK,


FloatClass cls[3] = { a_cls, b_cls, c_cls };
if (rule & R_3NAN_SNAN_MASK && abc_mask & float_cmask_snan) {
    do {
        which = rule & R_3NAN_1ST_MASK;
        rule >>= R_3NAN_1ST_LENGTH;
    } while (!is_snan(cls[which]));
} else {
    do {
        which = rule & R_3NAN_1ST_MASK;
        rule >>= R_3NAN_1ST_LENGTH;
    } while (!is_nan(cls[which]));
}
return which;


r~

Reply via email to