xref: /netbsd-src/external/gpl3/gdb.old/dist/gdb/testsuite/gdb.arch/powerpc-htm-regs.exp (revision 345cf9fb81bd0411c53e25d62cd93bdcaa865312)
1# Copyright (C) 2018-2020 Free Software Foundation, Inc.
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
28if {![istarget "powerpc*-*-linux*"]} then {
29    verbose "Skipping PowerPC test for HTM registers."
30    return
31}
32
33standard_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
38proc 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
55proc 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
73with_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.
133if {[build_executable "compile" $binfile $srcfile {debug}] == -1} {
134    return
135}
136
137clean_restart $binfile
138
139gdb_breakpoint [gdb_get_line_number "first marker"] temporary
140
141gdb_run_cmd
142
143# Wait for the prompt.
144gdb_test "" "Temporary breakpoint.*"
145
146if {[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
155for {set i 0} {$i < 32} {incr i 1} {
156    gdb_test_no_output "set \$r$i = $i"
157}
158
159gdb_test_no_output "set \$xer = 0xc0000000"
160
161# FPRs
162gdb_test_no_output "set \$f0 = 0.5"
163for {set i 1} {$i < 32} {incr i 1} {
164    gdb_test_no_output "set \$f$i = \$f[expr $i - 1] + 1.0"
165}
166
167gdb_test_no_output "set \$fpscr = 0x84005000"
168
169# VRs
170for {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
176gdb_test_no_output "set \$dscr = 0x2"
177gdb_test_no_output "set \$tar = &main" "set tar"
178
179# Get the pre-transactional value of the registers.
180for {set i 0} {$i < 32} {incr i 1} {
181    set "r$i" [get_hexadecimal_valueof "\$r$i" "default0"]
182}
183
184set cr [get_hexadecimal_valueof "\$cr" "default0"]
185set xer [get_hexadecimal_valueof "\$xer" "default0"]
186set lr [get_hexadecimal_valueof "\$lr" "default0"]
187set ctr [get_hexadecimal_valueof "\$ctr" "default0"]
188
189for {set i 0} {$i < 32} {incr i 1} {
190    set "f$i" [get_valueof "" "\$f$i" "default0"]
191}
192
193set fpscr [get_hexadecimal_valueof "\$fpscr" "default0"]
194
195for {set i 0} {$i < 32} {incr i 1} {
196    set "vr$i" [get_hexadecimal_valueof "\$vr$i.uint128" "default0"]
197}
198
199set vscr [get_hexadecimal_valueof "\$vscr" "default0"]
200set vrsave [get_hexadecimal_valueof "\$vrsave" "default0"]
201
202for {set i 0} {$i < 64} {incr i 1} {
203    set "vs$i" [get_hexadecimal_valueof "\$vs$i.uint128" "default0"]
204}
205
206set dscr [get_hexadecimal_valueof "\$dscr" "default0"]
207set ppr [get_hexadecimal_valueof "\$ppr" "default0"]
208set tar [get_hexadecimal_valueof "\$tar" "default0"]
209
210gdb_test "stepi" "asm.*bc.*"
211
212proc 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
241for {set i 0} {$i < 32} {incr i 1} {
242    test_register_match "cr$i" "r$i" 1
243}
244
245test_register_match "ccr" "cr" 1
246test_register_match "cxer" "xer" 1
247test_register_match "clr" "lr" 1
248test_register_match "cctr" "ctr" 1
249
250for {set i 0} {$i < 32} {incr i 1} {
251    test_register_match "cf$i" "f$i" 0
252}
253
254test_register_match "cfpscr" "fpscr" 1
255
256for {set i 0} {$i < 32} {incr i 1} {
257    test_register_match "cvr$i.uint128" "vr$i" 1
258}
259
260test_register_match "cvscr" "vscr" 1
261test_register_match "cvrsave" "vrsave" 1
262
263for {set i 0} {$i < 64} {incr i 1} {
264    test_register_match "cvs$i.uint128" "vs$i" 1
265}
266
267test_register_match "cdscr" "dscr" 1
268test_register_match "cppr" "ppr" 1
269test_register_match "ctar" "tar" 1
270
271# Support for writing to the checkpointed registers is not
272# currently available in the gdbserver stub.
273if [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.
281for {set i 0} {$i < 32} {incr i 1} {
282    gdb_test_no_output "set \$cr$i = $i + 0xC00"
283}
284
285gdb_test_no_output "set \$cf0 = 0.25"
286for {set i 1} {$i < 32} {incr i 1} {
287    gdb_test_no_output "set \$cf$i = \$cf[expr $i - 1] + 1.0"
288}
289
290for {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.
297with_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
311gdb_breakpoint [gdb_get_line_number "second marker"]
312
313gdb_test "continue"
314
315with_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
329