Commit | Line | Data |
---|---|---|
42a4f53d | 1 | # Copyright (C) 2018-2019 Free Software Foundation, Inc. |
8d619c01 EBM |
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 | # This file is part of the gdb testsuite. | |
17 | ||
18 | # Test access to HTM (Hardware Transactional Memory) registers. The | |
19 | # tests read the values of various registers before stepping the | |
20 | # inferior through a "tbegin." instruction to start a transaction, | |
21 | # then the checkpointed versions of the registers are checked against | |
22 | # the pre-transactional values. Then, new values are written to some | |
23 | # of the checkpointed registers, these values are read back and saved, | |
24 | # the inferior continues until the transaction aborts, and the regular | |
25 | # registers are then checked against the saved values, because the | |
26 | # abort should have reverted the registers to these values. | |
27 | ||
28 | if {![istarget "powerpc*-*-linux*"]} then { | |
29 | verbose "Skipping PowerPC test for HTM registers." | |
30 | return | |
31 | } | |
32 | ||
33 | standard_testfile .c .gen.c | |
34 | ||
35 | # First check if our processor and kernel support access to | |
36 | # the registers we need and to the HTM facility. | |
37 | ||
38 | proc check_register_access { regname } { | |
39 | global gdb_prompt | |
40 | ||
41 | set test "$regname register access" | |
42 | gdb_test_multiple "info reg $regname" "$test" { | |
43 | -re "Invalid register.*\r\n$gdb_prompt $" { | |
44 | unsupported "$test" | |
45 | return 0 | |
46 | } | |
47 | -re "\r\n$regname.*\r\n$gdb_prompt $" { | |
48 | pass "$test" | |
49 | return 1 | |
50 | } | |
51 | } | |
52 | return 0 | |
53 | } | |
54 | ||
55 | proc check_htm_support {} { | |
56 | global gdb_prompt | |
57 | set test "htm support" | |
58 | ||
59 | gdb_test_multiple "stepi" "$test" { | |
60 | -re "Illegal instruction.*\r\n$gdb_prompt $" { | |
61 | unsupported $test | |
62 | return 0 | |
63 | } | |
64 | -re "nop.*\r\n$gdb_prompt $" | |
65 | { | |
66 | pass $test | |
67 | return 1 | |
68 | } | |
69 | } | |
70 | return 0; | |
71 | } | |
72 | ||
73 | with_test_prefix "check htm support" { | |
74 | set gen_src [standard_output_file $srcfile2] | |
75 | ||
76 | gdb_produce_source $gen_src { | |
77 | int main () { | |
78 | asm volatile ("tbegin."); // marker | |
79 | asm volatile ("nop"); | |
80 | return 0; | |
81 | } | |
82 | } | |
83 | ||
84 | if {[build_executable "compile" $binfile $gen_src {debug}] == -1} { | |
85 | return | |
86 | } | |
87 | ||
88 | clean_restart $binfile | |
89 | ||
90 | # Displaced-stepping a tbegin. causes problems, | |
91 | # so we make the breakpoint temporary. | |
92 | gdb_breakpoint [gdb_get_line_number "marker" "$gen_src"] temporary | |
93 | ||
94 | gdb_run_cmd | |
95 | ||
96 | # Wait for the prompt. | |
97 | if {[gdb_test "" "Temporary breakpoint.*"] != 0 } { | |
98 | return | |
99 | } | |
100 | ||
101 | # Make sure that we stopped at the right place (just before tbegin. is | |
102 | # executed). | |
103 | if { [gdb_test "x/i \$pc" "=> $hex.*:.*tbegin\\..*" "disassemble tbegin"] != 0} { | |
104 | return | |
105 | } | |
106 | ||
107 | if {![check_register_access "vs0"]} { | |
108 | return | |
109 | } | |
110 | ||
111 | if {![check_register_access "texasr"]} { | |
112 | return | |
113 | } | |
114 | ||
115 | if {![check_register_access "dscr"]} { | |
116 | return | |
117 | } | |
118 | ||
119 | if {![check_register_access "ppr"]} { | |
120 | return | |
121 | } | |
122 | ||
123 | if {![check_register_access "tar"]} { | |
124 | return | |
125 | } | |
126 | ||
127 | if {![check_htm_support]} { | |
128 | return | |
129 | } | |
130 | } | |
131 | ||
132 | # Now do the actual test. | |
133 | if {[build_executable "compile" $binfile $srcfile {debug}] == -1} { | |
134 | return | |
135 | } | |
136 | ||
137 | clean_restart $binfile | |
138 | ||
139 | gdb_breakpoint [gdb_get_line_number "first marker"] temporary | |
140 | ||
141 | gdb_run_cmd | |
142 | ||
143 | # Wait for the prompt. | |
144 | gdb_test "" "Temporary breakpoint.*" | |
145 | ||
146 | if {[gdb_test "x/i \$pc" "=> $hex.*:.*tbegin\\..*" "disassemble tbegin"] != 0} { | |
147 | return | |
148 | } | |
149 | ||
150 | # Now we write non-zero values to some registers, then read the values | |
151 | # of various registers, then stepi to start the transaction. The | |
152 | # checkpointed register state should correspond to the values we read. | |
153 | ||
154 | # Write to the GPRs | |
155 | for {set i 0} {$i < 32} {incr i 1} { | |
156 | gdb_test_no_output "set \$r$i = $i" | |
157 | } | |
158 | ||
159 | gdb_test_no_output "set \$xer = 0xc0000000" | |
160 | ||
161 | # FPRs | |
162 | gdb_test_no_output "set \$f0 = 0.5" | |
163 | for {set i 1} {$i < 32} {incr i 1} { | |
164 | gdb_test_no_output "set \$f$i = \$f[expr $i - 1] + 1.0" | |
165 | } | |
166 | ||
167 | gdb_test_no_output "set \$fpscr = 0x84005000" | |
168 | ||
169 | # VRs | |
170 | for {set i 0} {$i < 32} {incr i 1} { | |
171 | for {set j 0} {$j < 4} {incr j 1} { | |
172 | gdb_test_no_output "set \$vr$i.v4_int32\[$j\] = $i" | |
173 | } | |
174 | } | |
175 | ||
176 | gdb_test_no_output "set \$dscr = 0x2" | |
177 | gdb_test_no_output "set \$tar = &main" "set tar" | |
178 | ||
179 | # Get the pre-transactional value of the registers. | |
180 | for {set i 0} {$i < 32} {incr i 1} { | |
181 | set "r$i" [get_hexadecimal_valueof "\$r$i" "default0"] | |
182 | } | |
183 | ||
184 | set cr [get_hexadecimal_valueof "\$cr" "default0"] | |
185 | set xer [get_hexadecimal_valueof "\$xer" "default0"] | |
186 | set lr [get_hexadecimal_valueof "\$lr" "default0"] | |
187 | set ctr [get_hexadecimal_valueof "\$ctr" "default0"] | |
188 | ||
189 | for {set i 0} {$i < 32} {incr i 1} { | |
190 | set "f$i" [get_valueof "" "\$f$i" "default0"] | |
191 | } | |
192 | ||
193 | set fpscr [get_hexadecimal_valueof "\$fpscr" "default0"] | |
194 | ||
195 | for {set i 0} {$i < 32} {incr i 1} { | |
196 | set "vr$i" [get_hexadecimal_valueof "\$vr$i.uint128" "default0"] | |
197 | } | |
198 | ||
199 | set vscr [get_hexadecimal_valueof "\$vscr" "default0"] | |
200 | set vrsave [get_hexadecimal_valueof "\$vrsave" "default0"] | |
201 | ||
202 | for {set i 0} {$i < 64} {incr i 1} { | |
203 | set "vs$i" [get_hexadecimal_valueof "\$vs$i.uint128" "default0"] | |
204 | } | |
205 | ||
206 | set dscr [get_hexadecimal_valueof "\$dscr" "default0"] | |
207 | set ppr [get_hexadecimal_valueof "\$ppr" "default0"] | |
208 | set tar [get_hexadecimal_valueof "\$tar" "default0"] | |
209 | ||
210 | gdb_test "stepi" "asm.*bc.*" | |
211 | ||
212 | proc test_register_match {reg_name reg_var_name hex} { | |
213 | set test "$reg_name matches $reg_var_name" | |
214 | ||
215 | # In some infrequent cases CXER doesn't match the | |
216 | # pre-transactional XER, possibly due to a linux kernel bug. | |
217 | set should_xfail 0 | |
218 | if [istarget "powerpc*-*-linux*" && reg_name == "cxer"] { | |
219 | set should_xfail 1 | |
220 | } | |
221 | ||
222 | upvar $reg_var_name expected_val | |
223 | ||
224 | if {$hex} { | |
225 | set actual_val [get_hexadecimal_valueof "\$$reg_name" "default1"] | |
226 | } else { | |
227 | set actual_val [get_valueof "" "\$$reg_name" "default1"] | |
228 | } | |
229 | ||
230 | if { "$expected_val" == "$actual_val" } { | |
231 | pass $test | |
232 | } else { | |
233 | if {$should_xfail} { | |
234 | xfail $test | |
235 | } else { | |
236 | fail $test | |
237 | } | |
238 | } | |
239 | } | |
240 | ||
241 | for {set i 0} {$i < 32} {incr i 1} { | |
242 | test_register_match "cr$i" "r$i" 1 | |
243 | } | |
244 | ||
245 | test_register_match "ccr" "cr" 1 | |
246 | test_register_match "cxer" "xer" 1 | |
247 | test_register_match "clr" "lr" 1 | |
248 | test_register_match "cctr" "ctr" 1 | |
249 | ||
250 | for {set i 0} {$i < 32} {incr i 1} { | |
251 | test_register_match "cf$i" "f$i" 0 | |
252 | } | |
253 | ||
254 | test_register_match "cfpscr" "fpscr" 1 | |
255 | ||
256 | for {set i 0} {$i < 32} {incr i 1} { | |
257 | test_register_match "cvr$i.uint128" "vr$i" 1 | |
258 | } | |
259 | ||
260 | test_register_match "cvscr" "vscr" 1 | |
261 | test_register_match "cvrsave" "vrsave" 1 | |
262 | ||
263 | for {set i 0} {$i < 64} {incr i 1} { | |
264 | test_register_match "cvs$i.uint128" "vs$i" 1 | |
265 | } | |
266 | ||
267 | test_register_match "cdscr" "dscr" 1 | |
268 | test_register_match "cppr" "ppr" 1 | |
269 | test_register_match "ctar" "tar" 1 | |
270 | ||
271 | # Support for writing to the checkpointed registers is not | |
272 | # currently available in the gdbserver stub. | |
273 | if [target_is_gdbserver] { | |
274 | unsupported "write to checkpointed registers" | |
275 | return | |
276 | } | |
277 | ||
278 | # Now write different values to some of the checkpointed registers and | |
279 | # check that the transaction abort reverts the register to these | |
280 | # values. | |
281 | for {set i 0} {$i < 32} {incr i 1} { | |
282 | gdb_test_no_output "set \$cr$i = $i + 0xC00" | |
283 | } | |
284 | ||
285 | gdb_test_no_output "set \$cf0 = 0.25" | |
286 | for {set i 1} {$i < 32} {incr i 1} { | |
287 | gdb_test_no_output "set \$cf$i = \$cf[expr $i - 1] + 1.0" | |
288 | } | |
289 | ||
290 | for {set i 0} {$i < 32} {incr i 1} { | |
291 | for {set j 0} {$j < 4} {incr j 1} { | |
292 | gdb_test_no_output "set \$cvr$i.v4_int32\[$j\] = $i + 0xF00" | |
293 | } | |
294 | } | |
295 | ||
296 | # Read back the values. | |
297 | with_test_prefix "after write" { | |
298 | for {set i 0} {$i < 32} {incr i 1} { | |
299 | set "cr$i" [get_hexadecimal_valueof "\$cr$i" "default0"] | |
300 | } | |
301 | ||
302 | for {set i 0} {$i < 32} {incr i 1} { | |
303 | set "cf$i" [get_valueof "" "\$cf$i" "default0"] | |
304 | } | |
305 | ||
306 | for {set i 0} {$i < 64} {incr i 1} { | |
307 | set "cvs$i" [get_hexadecimal_valueof "\$cvs$i.uint128" "default0"] | |
308 | } | |
309 | } | |
310 | ||
311 | gdb_breakpoint [gdb_get_line_number "second marker"] | |
312 | ||
313 | gdb_test "continue" | |
314 | ||
315 | with_test_prefix "after transaction failure" { | |
316 | for {set i 0} {$i < 32} {incr i 1} { | |
317 | test_register_match "r$i" "cr$i" 1 | |
318 | } | |
319 | ||
320 | for {set i 0} {$i < 32} {incr i 1} { | |
321 | test_register_match "f$i" "cf$i" 0 | |
322 | } | |
323 | ||
324 | for {set i 0} {$i < 64} {incr i 1} { | |
325 | test_register_match "vs$i.uint128" "cvs$i" 1 | |
326 | } | |
327 | } | |
328 |