]>
Commit | Line | Data |
---|---|---|
1d506c26 | 1 | # Copyright 2022-2024 Free Software Foundation, Inc. |
3095d926 AB |
2 | # |
3 | # This program is free software; you can redistribute it and/or modify | |
4 | # it under the terms of the GNU General Public License as published by | |
5 | # the Free Software Foundation; either version 3 of the License, or | |
6 | # (at your option) any later version. | |
7 | # | |
8 | # This program is distributed in the hope that it will be useful, | |
9 | # but WITHOUT ANY WARRANTY; without even the implied warranty of | |
10 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
11 | # GNU General Public License for more details. | |
12 | # | |
13 | # You should have received a copy of the GNU General Public License | |
14 | # along with this program. If not, see <http://www.gnu.org/licenses/>. | |
15 | ||
16 | # Check the formatting of the fcsr, fflags, and frm registers in the | |
17 | # output of the 'info registers' command. | |
18 | ||
73c06197 | 19 | require {istarget "riscv*-*-*"} allow_float_test |
3095d926 AB |
20 | |
21 | standard_testfile | |
22 | ||
23 | if {[prepare_for_testing "failed to prepare" $testfile $srcfile debug]} { | |
24 | return -1 | |
25 | } | |
26 | ||
75b6f386 | 27 | if {![runto_main]} { |
3095d926 AB |
28 | return 0 |
29 | } | |
30 | ||
31 | # Merge FFLAGS_VALUE and FRM_VALUE into a single hexadecimal value | |
32 | # that can be written to the fcsr register. The two arguments should | |
33 | # be the value of each of the two fields within the fcsr register. | |
34 | proc merge_fflags_and_frm { fflags_value frm_value } { | |
35 | set fcsr_value 0x[format %x [expr $fflags_value | ($frm_value << 5)]] | |
36 | return $fcsr_value | |
37 | } | |
38 | ||
39 | # Use 'info registers' to check the current values of the fflags, frm, | |
40 | # and fcsr registers. The value in fcsr should consist of the | |
41 | # FFLAGS_VALUE and FRM_VALUE, and the frm field of the fcsr register | |
42 | # should have the text FRM_STRING associated with it. | |
43 | proc check_fcsr { fflags_value frm_value frm_string } { | |
44 | # Merge fflags and frm values into a single fcsr value. | |
45 | set fcsr_value [merge_fflags_and_frm $fflags_value $frm_value] | |
46 | ||
47 | # Build up all the patterns we will need for this test. | |
48 | set frm_str_re [string_to_regexp "$frm_string"] | |
49 | set frm_val_re [format %d ${frm_value}] | |
50 | ||
51 | set nv [format %d [expr ($fflags_value >> 4) & 0x1]] | |
52 | set dz [format %d [expr ($fflags_value >> 3) & 0x1]] | |
53 | set of [format %d [expr ($fflags_value >> 2) & 0x1]] | |
54 | set uf [format %d [expr ($fflags_value >> 1) & 0x1]] | |
55 | set nx [format %d [expr ($fflags_value >> 0) & 0x1]] | |
56 | ||
57 | set fflags_pattern "NV:${nv} DZ:${dz} OF:${of} UF:${uf} NX:${nx}" | |
58 | set frm_pattern "FRM:${frm_val_re} \\\[${frm_str_re}\\\]" | |
59 | set fcsr_pattern "${fflags_pattern} ${frm_pattern}" | |
60 | ||
61 | # Now use 'info registers' to check the register values. | |
62 | array set reg_counts {} | |
63 | gdb_test_multiple "info registers \$fflags \$frm \$fcsr" "" { | |
64 | -re "^info registers\[^\r\n\]+\r\n" { | |
65 | exp_continue | |
66 | } | |
67 | ||
3095d926 AB |
68 | -re "^(frm)\\s+${frm_value}\\s+${frm_pattern}\r\n" { |
69 | set reg_name $expect_out(1,string) | |
70 | incr reg_counts($reg_name) | |
71 | exp_continue | |
72 | } | |
73 | ||
74 | -re "^(fflags)\\s+${fflags_value}\\s+${fflags_pattern}\r\n" { | |
75 | set reg_name $expect_out(1,string) | |
76 | incr reg_counts($reg_name) | |
77 | exp_continue | |
78 | } | |
79 | ||
80 | -re "^(fcsr)\\s+${fcsr_value}\\s+${fcsr_pattern}\r\n" { | |
81 | set reg_name $expect_out(1,string) | |
82 | incr reg_counts($reg_name) | |
83 | exp_continue | |
84 | } | |
85 | ||
86 | -re "^$::gdb_prompt $" { | |
87 | pass $gdb_test_name | |
88 | } | |
89 | } | |
90 | ||
91 | # Check that each register is seen only once. | |
92 | foreach reg {fflags frm fcsr} { | |
93 | gdb_assert { $reg_counts($reg) == 1 } \ | |
94 | "check we saw $reg just once" | |
95 | } | |
96 | } | |
97 | ||
98 | # Set the fcsr register based on FFLAGS_VALUE and FRM_VALUE, then | |
99 | # check that the value is displayed correctly in the 'info registers' | |
100 | # output. FRM_STRING should appear in the 'info registers' output | |
101 | # next to the frm field. | |
102 | proc test_fcsr { fflags_value frm_value frm_string } { | |
103 | # Merge fflags and frm values into a single fcsr value. | |
104 | set fcsr_value [merge_fflags_and_frm $fflags_value $frm_value] | |
105 | ||
106 | with_test_prefix "fcsr=${fcsr_value}" { | |
107 | # Set the fcsr value directly. | |
108 | gdb_test_no_output "set \$fcsr = ${fcsr_value}" | |
109 | ||
110 | with_test_prefix "set through fcsr" { | |
111 | check_fcsr $fflags_value $frm_value $frm_string | |
112 | } | |
4749b84b AB |
113 | |
114 | # Reset fcsr register back to zero. | |
115 | gdb_test_no_output "set \$fcsr = 0x0" \ | |
116 | "reset fcsr back to 0x0" | |
117 | gdb_test "p/x \$fcsr" " = 0x0" | |
118 | ||
119 | # Now set fcsr value through fflags and frm. | |
120 | gdb_test_no_output "set \$fflags = ${fflags_value}" | |
121 | gdb_test_no_output "set \$frm = ${frm_value}" | |
122 | ||
123 | with_test_prefix "set through fflags and frm" { | |
124 | check_fcsr $fflags_value $frm_value $frm_string | |
125 | } | |
3095d926 AB |
126 | } |
127 | } | |
128 | ||
129 | # Check each valid value of the fflags register. | |
130 | for { set i 0 } { $i < 32 } { incr i } { | |
131 | test_fcsr 0x[format %x $i] 0x0 "RNE (round to nearest; ties to even)" | |
132 | } | |
133 | ||
134 | # Check each valid value of the frm register. | |
135 | test_fcsr 0x0 0x1 "RTZ (Round towards zero)" | |
136 | test_fcsr 0x0 0x2 "RDN (Round down towards -INF)" | |
137 | test_fcsr 0x0 0x3 "RUP (Round up towards +INF)" | |
138 | test_fcsr 0x0 0x4 "RMM (Round to nearest; ties to max magnitude)" | |
139 | test_fcsr 0x0 0x5 "INVALID\[5\]" | |
140 | test_fcsr 0x0 0x6 "INVALID\[6\]" | |
141 | test_fcsr 0x0 0x7 "INVALID\[7\] (Dynamic rounding mode)" |