udb 0.1.4 → 0.1.6
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/.data/cfgs/mc100-32-full-example.yaml +0 -35
- data/.data/cfgs/qc_iu.yaml +0 -33
- data/.data/cfgs/rv32-riscv-tests.yaml +5 -1
- data/.data/cfgs/rv64-riscv-tests.yaml +4 -1
- data/.data/spec/std/isa/inst/F/fadd.s.yaml +16 -1
- data/.data/spec/std/isa/inst/F/fclass.s.yaml +7 -0
- data/.data/spec/std/isa/inst/F/fcvt.l.s.yaml +3 -0
- data/.data/spec/std/isa/inst/F/fcvt.lu.s.yaml +3 -0
- data/.data/spec/std/isa/inst/F/fcvt.s.l.yaml +4 -0
- data/.data/spec/std/isa/inst/F/fcvt.s.lu.yaml +4 -0
- data/.data/spec/std/isa/inst/F/fcvt.w.s.yaml +1 -1
- data/.data/spec/std/isa/inst/F/fcvt.wu.s.yaml +1 -1
- data/.data/spec/std/isa/inst/F/fdiv.s.yaml +4 -0
- data/.data/spec/std/isa/inst/F/feq.s.yaml +1 -1
- data/.data/spec/std/isa/inst/F/fle.s.yaml +14 -7
- data/.data/spec/std/isa/inst/F/fleq.s.yaml +30 -0
- data/.data/spec/std/isa/inst/F/flt.s.yaml +13 -8
- data/.data/spec/std/isa/inst/F/fltq.s.yaml +21 -0
- data/.data/spec/std/isa/inst/F/fmadd.s.yaml +4 -0
- data/.data/spec/std/isa/inst/F/fmax.s.yaml +30 -0
- data/.data/spec/std/isa/inst/F/fmin.s.yaml +30 -0
- data/.data/spec/std/isa/inst/F/fmsub.s.yaml +4 -0
- data/.data/spec/std/isa/inst/F/fmul.s.yaml +4 -0
- data/.data/spec/std/isa/inst/F/fnmadd.s.yaml +7 -0
- data/.data/spec/std/isa/inst/F/fnmsub.s.yaml +4 -0
- data/.data/spec/std/isa/inst/F/fsqrt.s.yaml +4 -0
- data/.data/spec/std/isa/isa/fp.idl +911 -101
- data/.data/spec/std/isa/isa/globals.isa +2 -0
- data/.data/spec/std/isa/isa/util.idl +22 -0
- data/.data/spec/std/isa/param/SCOUNTENABLE_EN.yaml +1 -1
- data/lib/udb/cfg_arch.rb +42 -6
- data/lib/udb/condition.rb +66 -2
- data/lib/udb/logic.rb +27 -1
- data/lib/udb/version.rb +1 -1
- metadata +2 -2
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: e3ee0e5cbe7e1f156b670b2851038ac508058f5ded02fcfa77b1d37dfd3b2801
|
|
4
|
+
data.tar.gz: d29e24404ee97a185b1d77a364e6d9f62d7d803e6f5cdb8f023554e61610f9e0
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: da552e97506e8c03646f6d3c8d9da8dc6ee4d69f4d73d4766595d831ae92e7cfc12930bb71b42853582ad94f14e23c08c5b2912da1f522ed5d209d6f573f8717
|
|
7
|
+
data.tar.gz: 4de7021d90135149aa34fcf3dc9c1028b41a21eb7fcc7a7fbd0d5afb9bbc5b71398a37e57a969196ba3daafebfaa9465fc82b849fe0cf3d7b66e58f5fca099c4
|
|
@@ -161,38 +161,3 @@ params:
|
|
|
161
161
|
false,
|
|
162
162
|
false,
|
|
163
163
|
]
|
|
164
|
-
SCOUNTENABLE_EN:
|
|
165
|
-
[
|
|
166
|
-
false,
|
|
167
|
-
false,
|
|
168
|
-
false,
|
|
169
|
-
false,
|
|
170
|
-
false,
|
|
171
|
-
false,
|
|
172
|
-
false,
|
|
173
|
-
false,
|
|
174
|
-
false,
|
|
175
|
-
false,
|
|
176
|
-
false,
|
|
177
|
-
false,
|
|
178
|
-
false,
|
|
179
|
-
false,
|
|
180
|
-
false,
|
|
181
|
-
false,
|
|
182
|
-
false,
|
|
183
|
-
false,
|
|
184
|
-
false,
|
|
185
|
-
false,
|
|
186
|
-
false,
|
|
187
|
-
false,
|
|
188
|
-
false,
|
|
189
|
-
false,
|
|
190
|
-
false,
|
|
191
|
-
false,
|
|
192
|
-
false,
|
|
193
|
-
false,
|
|
194
|
-
false,
|
|
195
|
-
false,
|
|
196
|
-
false,
|
|
197
|
-
false,
|
|
198
|
-
]
|
data/.data/cfgs/qc_iu.yaml
CHANGED
|
@@ -115,39 +115,6 @@ params:
|
|
|
115
115
|
- false # HPM29
|
|
116
116
|
- false # HPM30
|
|
117
117
|
- false # HPM31
|
|
118
|
-
SCOUNTENABLE_EN:
|
|
119
|
-
- false # CY
|
|
120
|
-
- false # empty
|
|
121
|
-
- false # IR
|
|
122
|
-
- false # HPM3
|
|
123
|
-
- false # HPM4
|
|
124
|
-
- false # HPM5
|
|
125
|
-
- false # HPM6
|
|
126
|
-
- false # HPM7
|
|
127
|
-
- false # HPM8
|
|
128
|
-
- false # HPM9
|
|
129
|
-
- false # HPM10
|
|
130
|
-
- false # HPM11
|
|
131
|
-
- false # HPM12
|
|
132
|
-
- false # HPM13
|
|
133
|
-
- false # HPM14
|
|
134
|
-
- false # HPM15
|
|
135
|
-
- false # HPM16
|
|
136
|
-
- false # HPM17
|
|
137
|
-
- false # HPM18
|
|
138
|
-
- false # HPM19
|
|
139
|
-
- false # HPM20
|
|
140
|
-
- false # HPM21
|
|
141
|
-
- false # HPM22
|
|
142
|
-
- false # HPM23
|
|
143
|
-
- false # HPM24
|
|
144
|
-
- false # HPM25
|
|
145
|
-
- false # HPM26
|
|
146
|
-
- false # HPM27
|
|
147
|
-
- false # HPM28
|
|
148
|
-
- false # HPM29
|
|
149
|
-
- false # HPM30
|
|
150
|
-
- false # HPM31
|
|
151
118
|
COUNTINHIBIT_EN:
|
|
152
119
|
- true # CY
|
|
153
120
|
- false # empty
|
|
@@ -19,6 +19,8 @@ implemented_extensions:
|
|
|
19
19
|
- [U, "1.0.0"]
|
|
20
20
|
- [Zifencei, "2.0.0"]
|
|
21
21
|
- [Sv32, "1.11.0"]
|
|
22
|
+
- [F, "2.2.0"]
|
|
23
|
+
- [Zcf, "1.0"]
|
|
22
24
|
|
|
23
25
|
params:
|
|
24
26
|
MXLEN: 32
|
|
@@ -191,7 +193,7 @@ params:
|
|
|
191
193
|
TRAP_ON_ECALL_FROM_S: true
|
|
192
194
|
TRAP_ON_SFENCE_VMA_WHEN_SATP_MODE_IS_READ_ONLY: false
|
|
193
195
|
MSTATUS_VS_LEGAL_VALUES: [0]
|
|
194
|
-
MSTATUS_FS_LEGAL_VALUES: [0]
|
|
196
|
+
MSTATUS_FS_LEGAL_VALUES: [3, 2, 1, 0]
|
|
195
197
|
MSTATUS_TVM_IMPLEMENTED: false
|
|
196
198
|
NUM_PMP_ENTRIES: 16
|
|
197
199
|
PMP_GRANULARITY: 12
|
|
@@ -240,3 +242,5 @@ params:
|
|
|
240
242
|
# MSTATEEN_CSRIND_TYPE: rw
|
|
241
243
|
# MSTATEEN_IMSIC_TYPE: rw
|
|
242
244
|
# MSTATEEN_JVT_TYPE: rw
|
|
245
|
+
HW_MSTATUS_FS_DIRTY_UPDATE: precise
|
|
246
|
+
MUTABLE_MISA_F: false
|
|
@@ -19,6 +19,7 @@ implemented_extensions:
|
|
|
19
19
|
- [Zifencei, "2.0.0"]
|
|
20
20
|
- [Sv39, "1.11.0"]
|
|
21
21
|
- [Zca, "1.0.0"]
|
|
22
|
+
- [F, "2.2.0"]
|
|
22
23
|
|
|
23
24
|
params:
|
|
24
25
|
MXLEN: 64
|
|
@@ -191,7 +192,7 @@ params:
|
|
|
191
192
|
TRAP_ON_ECALL_FROM_U: true
|
|
192
193
|
TRAP_ON_SFENCE_VMA_WHEN_SATP_MODE_IS_READ_ONLY: false
|
|
193
194
|
MSTATUS_VS_LEGAL_VALUES: [0]
|
|
194
|
-
MSTATUS_FS_LEGAL_VALUES: [0]
|
|
195
|
+
MSTATUS_FS_LEGAL_VALUES: [3, 2, 1, 0]
|
|
195
196
|
MSTATUS_TVM_IMPLEMENTED: false
|
|
196
197
|
NUM_PMP_ENTRIES: 16
|
|
197
198
|
PMP_GRANULARITY: 12
|
|
@@ -199,6 +200,8 @@ params:
|
|
|
199
200
|
U_MODE_ENDIANNESS: little
|
|
200
201
|
UXLEN: [64]
|
|
201
202
|
MSTATEEN_ENVCFG_TYPE: rw
|
|
203
|
+
HW_MSTATUS_FS_DIRTY_UPDATE: precise
|
|
204
|
+
MUTABLE_MISA_F: false
|
|
202
205
|
HPM_COUNTER_EN:
|
|
203
206
|
[
|
|
204
207
|
false,
|
|
@@ -34,4 +34,19 @@ data_independent_timing: true
|
|
|
34
34
|
operation(): |
|
|
35
35
|
check_f_ok($encoding);
|
|
36
36
|
RoundingMode mode = rm_to_mode(rm, $encoding);
|
|
37
|
-
|
|
37
|
+
Bits<32> a = f[fs1];
|
|
38
|
+
Bits<32> b = f[fs2];
|
|
39
|
+
|
|
40
|
+
if (implemented?(ExtensionName::D)) {
|
|
41
|
+
# check for incorrectly NaN-boxed inputs
|
|
42
|
+
if (f[fs1][63:32] != 32'hffffffff) {
|
|
43
|
+
a = SP_CANONICAL_NAN;
|
|
44
|
+
}
|
|
45
|
+
if (f[fs2][63:32] != 32'hffffffff) {
|
|
46
|
+
b = SP_CANONICAL_NAN;
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
f[fd] = f32_add(a, b, mode);
|
|
51
|
+
|
|
52
|
+
mark_f_state_dirty();
|
|
@@ -53,6 +53,13 @@ operation(): |
|
|
|
53
53
|
|
|
54
54
|
Bits<32> sp_value = f[fs1][31:0];
|
|
55
55
|
|
|
56
|
+
if (implemented?(ExtensionName::D)) {
|
|
57
|
+
# check for an incorrectly NaN-boxed value
|
|
58
|
+
if (f[fs1][63:32] != 32'hffffffff) {
|
|
59
|
+
sp_value = SP_CANONICAL_NAN;
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
|
|
56
63
|
if (is_sp_neg_inf?(sp_value)) {
|
|
57
64
|
X[xd] = 1 << 0;
|
|
58
65
|
} else if (is_sp_neg_norm?(sp_value)) {
|
|
@@ -35,7 +35,7 @@ operation(): |
|
|
|
35
35
|
check_f_ok($encoding);
|
|
36
36
|
|
|
37
37
|
Bits<32> sp_value_a = f[fs1][31:0];
|
|
38
|
-
Bits<32> sp_value_b = f[
|
|
38
|
+
Bits<32> sp_value_b = f[fs2][31:0];
|
|
39
39
|
|
|
40
40
|
if (is_sp_nan?(sp_value_a) || is_sp_nan?(sp_value_b)) {
|
|
41
41
|
if (is_sp_signaling_nan?(sp_value_a) || is_sp_signaling_nan?(sp_value_b)) {
|
|
@@ -36,15 +36,22 @@ operation(): |
|
|
|
36
36
|
|
|
37
37
|
Bits<32> sp_value_a = f[fs1][31:0];
|
|
38
38
|
Bits<32> sp_value_b = f[fs2][31:0];
|
|
39
|
+
Bits<1> sign_a = sp_value_a[31];
|
|
40
|
+
Bits<1> sign_b = sp_value_b[31];
|
|
39
41
|
|
|
40
42
|
if (is_sp_nan?(sp_value_a) || is_sp_nan?(sp_value_b)) {
|
|
41
|
-
|
|
42
|
-
set_fp_flag(FpFlag::NV);
|
|
43
|
-
}
|
|
43
|
+
set_fp_flag(FpFlag::NV);
|
|
44
44
|
X[xd] = 0;
|
|
45
45
|
} else {
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
46
|
+
if (sign_a != sign_b) {
|
|
47
|
+
X[xd] = (
|
|
48
|
+
(sign_a == 1) || # b is pos and a neg
|
|
49
|
+
((sp_value_a[30:0] | sp_value_b[30:0]) == 0) # both are zero (one pos, one neg)
|
|
50
|
+
) ? 1 : 0;
|
|
51
|
+
} else {
|
|
52
|
+
X[xd] = (
|
|
53
|
+
(sp_value_a == sp_value_b) || # a and b are equal
|
|
54
|
+
(sign_a ^ ((sp_value_a < sp_value_b) ? 1 : 0)) == 1 # a < b
|
|
55
|
+
) ? 1 : 0;
|
|
56
|
+
}
|
|
50
57
|
}
|
|
@@ -30,3 +30,33 @@ access:
|
|
|
30
30
|
vu: always
|
|
31
31
|
data_independent_timing: true
|
|
32
32
|
operation(): |
|
|
33
|
+
check_f_ok($encoding);
|
|
34
|
+
|
|
35
|
+
Bits<32> sp_value_a = f[fs1][31:0];
|
|
36
|
+
Bits<32> sp_value_b = f[fs2][31:0];
|
|
37
|
+
|
|
38
|
+
if (is_sp_nan?(sp_value_a) || is_sp_nan?(sp_value_b)) {
|
|
39
|
+
# Quiet comparison: only set NV for signaling NaN
|
|
40
|
+
if (is_sp_signaling_nan?(sp_value_a) || is_sp_signaling_nan?(sp_value_b)) {
|
|
41
|
+
set_fp_flag(FpFlag::NV);
|
|
42
|
+
}
|
|
43
|
+
X[xd] = 0;
|
|
44
|
+
} else {
|
|
45
|
+
Boolean sign_a = sp_value_a[31] == 1;
|
|
46
|
+
Boolean sign_b = sp_value_b[31] == 1;
|
|
47
|
+
|
|
48
|
+
# Check equality first (including -0.0 == +0.0)
|
|
49
|
+
Boolean a_eq_b =
|
|
50
|
+
(sp_value_a == sp_value_b)
|
|
51
|
+
|| ((sp_value_a | sp_value_b)[30:0] == 0);
|
|
52
|
+
|
|
53
|
+
# Check a < b
|
|
54
|
+
Boolean a_lt_b;
|
|
55
|
+
if (sign_a != sign_b) {
|
|
56
|
+
a_lt_b = sign_a && ((sp_value_a[30:0] | sp_value_b[30:0]) != 0);
|
|
57
|
+
} else {
|
|
58
|
+
a_lt_b = (sp_value_a != sp_value_b) && (sign_a != (sp_value_a < sp_value_b));
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
X[xd] = (a_lt_b || a_eq_b) ? 1 : 0;
|
|
62
|
+
}
|
|
@@ -36,17 +36,22 @@ operation(): |
|
|
|
36
36
|
|
|
37
37
|
Bits<32> sp_value_a = f[fs1][31:0];
|
|
38
38
|
Bits<32> sp_value_b = f[fs2][31:0];
|
|
39
|
+
Bits<1> sign_a = sp_value_a[31];
|
|
40
|
+
Bits<1> sign_b = sp_value_b[31];
|
|
39
41
|
|
|
40
42
|
if (is_sp_nan?(sp_value_a) || is_sp_nan?(sp_value_b)) {
|
|
41
43
|
set_fp_flag(FpFlag::NV);
|
|
42
44
|
X[xd] = 0;
|
|
43
45
|
} else {
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
46
|
+
if (sign_a != sign_b) {
|
|
47
|
+
X[xd] = (
|
|
48
|
+
(sign_a == 1) # a is neg and b is pos
|
|
49
|
+
&& ((sp_value_a[30:0] | sp_value_b[30:0]) != 0) # a and b are not both zero
|
|
50
|
+
) ? 1 : 0;
|
|
51
|
+
} else {
|
|
52
|
+
X[xd] = (
|
|
53
|
+
(sp_value_a != sp_value_b) # a and b are not equal
|
|
54
|
+
&& ((sign_a ^ ((sp_value_a < sp_value_b) ? 1 : 0)) != 0)# a < b
|
|
55
|
+
) ? 1 : 0;
|
|
56
|
+
}
|
|
52
57
|
}
|
|
@@ -30,3 +30,24 @@ access:
|
|
|
30
30
|
vu: always
|
|
31
31
|
data_independent_timing: true
|
|
32
32
|
operation(): |
|
|
33
|
+
check_f_ok($encoding);
|
|
34
|
+
|
|
35
|
+
Bits<32> sp_value_a = f[fs1][31:0];
|
|
36
|
+
Bits<32> sp_value_b = f[fs2][31:0];
|
|
37
|
+
|
|
38
|
+
if (is_sp_nan?(sp_value_a) || is_sp_nan?(sp_value_b)) {
|
|
39
|
+
# Quiet comparison: only set NV for signaling NaN
|
|
40
|
+
if (is_sp_signaling_nan?(sp_value_a) || is_sp_signaling_nan?(sp_value_b)) {
|
|
41
|
+
set_fp_flag(FpFlag::NV);
|
|
42
|
+
}
|
|
43
|
+
X[xd] = 0;
|
|
44
|
+
} else {
|
|
45
|
+
Boolean sign_a = sp_value_a[31] == 1;
|
|
46
|
+
Boolean sign_b = sp_value_b[31] == 1;
|
|
47
|
+
|
|
48
|
+
Boolean a_lt_b =
|
|
49
|
+
(sign_a != sign_b)
|
|
50
|
+
? (sign_a && ((sp_value_a[30:0] | sp_value_b[30:0]) != 0))
|
|
51
|
+
: ((sp_value_a != sp_value_b) && (sign_a != (sp_value_a < sp_value_b)));
|
|
52
|
+
X[xd] = a_lt_b ? 1 : 0;
|
|
53
|
+
}
|
|
@@ -39,3 +39,33 @@ access:
|
|
|
39
39
|
vu: always
|
|
40
40
|
data_independent_timing: true
|
|
41
41
|
operation(): |
|
|
42
|
+
check_f_ok($encoding);
|
|
43
|
+
|
|
44
|
+
Bits<32> sp_value_a = f[fs1][31:0];
|
|
45
|
+
Bits<32> sp_value_b = f[fs2][31:0];
|
|
46
|
+
|
|
47
|
+
if (is_sp_nan?(sp_value_a) || is_sp_nan?(sp_value_b)) {
|
|
48
|
+
if (is_sp_signaling_nan?(sp_value_a) || is_sp_signaling_nan?(sp_value_b)) {
|
|
49
|
+
set_fp_flag(FpFlag::NV);
|
|
50
|
+
}
|
|
51
|
+
# If both are NaN, return canonical NaN; otherwise return the non-NaN operand
|
|
52
|
+
if (is_sp_nan?(sp_value_a) && is_sp_nan?(sp_value_b)) {
|
|
53
|
+
f[fd] = SP_CANONICAL_NAN;
|
|
54
|
+
} else if (is_sp_nan?(sp_value_a)) {
|
|
55
|
+
f[fd] = sp_value_b;
|
|
56
|
+
} else {
|
|
57
|
+
f[fd] = sp_value_a;
|
|
58
|
+
}
|
|
59
|
+
} else {
|
|
60
|
+
Boolean sign_a = sp_value_a[31] == 1;
|
|
61
|
+
Boolean sign_b = sp_value_b[31] == 1;
|
|
62
|
+
Boolean a_lt_b;
|
|
63
|
+
if (sign_a != sign_b) {
|
|
64
|
+
# -0.0 is considered less than +0.0, so it's not a special case
|
|
65
|
+
a_lt_b = sign_a;
|
|
66
|
+
} else {
|
|
67
|
+
a_lt_b = (sp_value_a != sp_value_b) && (sign_a != (sp_value_a < sp_value_b));
|
|
68
|
+
}
|
|
69
|
+
f[fd] = a_lt_b ? sp_value_b : sp_value_a;
|
|
70
|
+
}
|
|
71
|
+
mark_f_state_dirty();
|
|
@@ -39,3 +39,33 @@ access:
|
|
|
39
39
|
vu: always
|
|
40
40
|
data_independent_timing: true
|
|
41
41
|
operation(): |
|
|
42
|
+
check_f_ok($encoding);
|
|
43
|
+
|
|
44
|
+
Bits<32> sp_value_a = f[fs1][31:0];
|
|
45
|
+
Bits<32> sp_value_b = f[fs2][31:0];
|
|
46
|
+
|
|
47
|
+
if (is_sp_nan?(sp_value_a) || is_sp_nan?(sp_value_b)) {
|
|
48
|
+
if (is_sp_signaling_nan?(sp_value_a) || is_sp_signaling_nan?(sp_value_b)) {
|
|
49
|
+
set_fp_flag(FpFlag::NV);
|
|
50
|
+
}
|
|
51
|
+
# If both are NaN, return canonical NaN; otherwise return the non-NaN operand
|
|
52
|
+
if (is_sp_nan?(sp_value_a) && is_sp_nan?(sp_value_b)) {
|
|
53
|
+
f[fd] = SP_CANONICAL_NAN;
|
|
54
|
+
} else if (is_sp_nan?(sp_value_a)) {
|
|
55
|
+
f[fd] = sp_value_b;
|
|
56
|
+
} else {
|
|
57
|
+
f[fd] = sp_value_a;
|
|
58
|
+
}
|
|
59
|
+
} else {
|
|
60
|
+
Boolean sign_a = sp_value_a[31] == 1;
|
|
61
|
+
Boolean sign_b = sp_value_b[31] == 1;
|
|
62
|
+
Boolean a_lt_b;
|
|
63
|
+
if (sign_a != sign_b) {
|
|
64
|
+
# -0.0 is considered less than +0.0, so it's not a special case
|
|
65
|
+
a_lt_b = sign_a;
|
|
66
|
+
} else {
|
|
67
|
+
a_lt_b = (sp_value_a != sp_value_b) && (sign_a != (sp_value_a < sp_value_b));
|
|
68
|
+
}
|
|
69
|
+
f[fd] = a_lt_b ? sp_value_a : sp_value_b;
|
|
70
|
+
}
|
|
71
|
+
mark_f_state_dirty();
|
|
@@ -34,3 +34,10 @@ access:
|
|
|
34
34
|
vu: always
|
|
35
35
|
data_independent_timing: true
|
|
36
36
|
operation(): |
|
|
37
|
+
check_f_ok($encoding);
|
|
38
|
+
RoundingMode mode = rm_to_mode(rm, $encoding);
|
|
39
|
+
# fnmadd: -(fs1 * fs2) - fs3 = -(fs1 * fs2) + (-fs3)
|
|
40
|
+
# Negate fs3 by flipping its sign bit, then use subProd op
|
|
41
|
+
Bits<32> fs3_negated = f[fs3][31:0] ^ 32'h80000000;
|
|
42
|
+
f[fd] = f32_muladd(f[fs1], f[fs2], fs3_negated, F32MulAddOp::Softfloat_mulAdd_subProd, mode);
|
|
43
|
+
mark_f_state_dirty();
|
|
@@ -34,3 +34,7 @@ access:
|
|
|
34
34
|
vu: always
|
|
35
35
|
data_independent_timing: true
|
|
36
36
|
operation(): |
|
|
37
|
+
check_f_ok($encoding);
|
|
38
|
+
RoundingMode mode = rm_to_mode(rm, $encoding);
|
|
39
|
+
f[fd] = f32_muladd(f[fs1], f[fs2], f[fs3], F32MulAddOp::Softfloat_mulAdd_subProd, mode);
|
|
40
|
+
mark_f_state_dirty();
|