Commit | Line | Data |
---|---|---|
3666a048 | 1 | # Copyright 2015-2021 Free Software Foundation, Inc. |
4fa5d7b4 AA |
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 | # Test vector register access for s390 platforms. | |
17 | ||
18 | if { ![istarget s390-*-*] && ![istarget s390x-*-* ] } { | |
19 | verbose "Skipping s390 vector register tests." | |
20 | return | |
21 | } | |
22 | ||
23 | standard_testfile .S | |
24 | ||
25 | if [isnative] { | |
26 | # Create a temporary directory, to take a core dump there later. | |
27 | set coredir [standard_output_file ${testfile}.d] | |
28 | remote_exec build "rm -rf $coredir" | |
29 | remote_exec build "mkdir $coredir" | |
30 | } | |
31 | ||
5b362f04 | 32 | if { [prepare_for_testing "failed to prepare" $testfile $srcfile \ |
af9fd6f8 | 33 | [list "additional_flags=-mzarch"]] } { |
4fa5d7b4 AA |
34 | return -1 |
35 | } | |
36 | ||
37 | if ![runto_main] { | |
38 | untested "could not run to main" | |
39 | return -1 | |
40 | } | |
41 | ||
42 | # Run to the first vector instruction and step it. If the inferior | |
43 | # doesn't crash, we have vector support. | |
44 | ||
45 | gdb_breakpoint "check_vx" | |
46 | gdb_continue_to_breakpoint "first vector insn" | |
47 | set before_pc 0 | |
48 | gdb_test_multiple "x/i \$pc" "get PC at vector insn" { | |
49 | -re "(0x\\S+)\\s+\\S+\\s+vlr\\s+.*$gdb_prompt $" { | |
50 | set before_pc $expect_out(1,string) | |
51 | } | |
52 | } | |
53 | ||
54 | gdb_test_multiple "stepi" "check for vector support" { | |
55 | -re "Program received signal SIGILL,.*\r\n$gdb_prompt $" { | |
56 | unsupported "no vector support." | |
57 | return | |
58 | } | |
59 | -re "\[0-9\]+.*\r\n$gdb_prompt $" { | |
60 | pass "vector support available" | |
61 | } | |
62 | -re "$gdb_prompt $" { | |
63 | fail "no vector support (unknown error)" | |
64 | return | |
65 | } | |
66 | } | |
67 | ||
68 | # Has the PC advanced by the expected amount? The kernel may do | |
69 | # something special for the first vector insn in the process. | |
70 | ||
71 | set after_pc 0 | |
72 | gdb_test_multiple "x/i \$pc" "get PC after vector insn" { | |
73 | -re "(0x\\S+)\\s+.*$gdb_prompt $" { | |
74 | set after_pc $expect_out(1,string) | |
75 | } | |
76 | } | |
77 | ||
78 | if [expr $before_pc + 6 != $after_pc] { | |
79 | fail "stepping first vector insn" | |
80 | } | |
81 | ||
82 | # Lift the core file limit, if possible, and change into the temporary | |
83 | # directory. | |
84 | ||
85 | if { $coredir != "" } { | |
634c1c31 | 86 | gdb_test {print (int) setrlimit (4, &(unsigned long [2]){~0UL, ~0UL})} \ |
4fa5d7b4 | 87 | " = .*" "setrlimit" |
634c1c31 | 88 | gdb_test "print (int) chdir (\"${coredir}\")" " = 0" "chdir" |
4fa5d7b4 AA |
89 | } |
90 | ||
91 | # Initialize all vector registers with GDB "set" commands, using | |
92 | # distinct values. Handle left and right halves separately, in | |
93 | # pseudo-random order. | |
94 | ||
95 | set a_high 1 | |
96 | set a_low 2 | |
97 | set b_high 3 | |
98 | set b_low 5 | |
99 | ||
100 | set a [expr ($a_high << 32) | $a_low] | |
101 | set b [expr ($b_high << 32) | $b_low] | |
102 | ||
103 | for {set j 0} {$j < 32} {incr j 1} { | |
104 | set i [expr 17 * $j % 32] | |
105 | gdb_test_no_output \ | |
106 | "set \$v$i.v2_int64\[0\] = [expr $a * ($i + 1)]" \ | |
107 | "set v$i left" | |
108 | set i [expr 19 * (31 - $j) % 32] | |
109 | gdb_test_no_output \ | |
110 | "set \$v$i.v2_int64\[1\] = [expr $b * (32 - $i)]" \ | |
111 | "set v$i right" | |
112 | } | |
113 | ||
114 | # Verify a vector register's union members. | |
115 | ||
116 | gdb_test "info register v0 v31" \ | |
117 | "v4_float .* v2_double .* v16_int8 .* v8_int16 .* v4_int32 .* v2_int64 .* uint128\ | |
118 | .*v4_float .* v2_double .* v16_int8 .* v8_int16 .* v4_int32 .* v2_int64 .* uint128 .*" | |
119 | ||
120 | # Let the inferior store all vector registers in a buffer, then dump | |
121 | # the buffer and check it. | |
122 | ||
123 | gdb_continue_to_breakpoint "store vrs" | |
124 | set vregs [capture_command_output "x/64xg &save_area" ""] | |
125 | ||
126 | set i 0 | |
127 | foreach {- left right} [regexp -all -inline -line {^.*:\s+(\w+)\s+(\w+)} $vregs] { | |
128 | if [expr $left != $a * ($i + 1) || $right != $b * (32 - $i)] { | |
129 | fail "verify \$v$i after set" | |
130 | } | |
131 | if { $i < 16 } { | |
132 | # Check that the FP register was updated accordingly. | |
133 | gdb_test "info register f$i" "raw ${left}.*" | |
134 | } | |
135 | incr i 1 | |
136 | } | |
137 | ||
138 | if { $i != 32 } { | |
139 | fail "dump save area (bad output)" | |
140 | } | |
141 | ||
142 | # Let the inferior change all VRs according to a simple algorithm, | |
143 | # then print all VRs and compare their values with our result of the | |
144 | # same algorithm. | |
145 | ||
146 | gdb_continue_to_breakpoint "change vrs" | |
147 | set vregs [capture_command_output "info registers vector" ""] | |
148 | ||
30a25466 | 149 | # Format a 128-bit value, given individual 4-byte values, as hex. |
031ed05d | 150 | # Suppress leading zeros. |
30a25466 | 151 | proc hex128 {a_high a_low b_high b_low} { |
031ed05d AA |
152 | set result [format "%x%08x%08x%08x" $a_high $a_low $b_high $b_low] |
153 | regsub -- "^0*" $result "" result | |
154 | if { $result eq "" } { set result 0 } | |
155 | return $result | |
30a25466 TT |
156 | } |
157 | ||
4fa5d7b4 AA |
158 | set j 1 |
159 | foreach {- r i val} [regexp -all -inline -line \ | |
160 | {^(\D*)(\d+)\s+.*?uint128 = 0x([0-9a-f]+?)} $vregs] { | |
161 | if { $r ne "v" } { | |
162 | fail "info registers vector: bad line $j" | |
031ed05d AA |
163 | } elseif { $val ne [hex128 \ |
164 | [expr $a_high * ($i + 1) * $a_high ] \ | |
165 | [expr $a_low * ($i + 1) * $a_low ] \ | |
166 | [expr $b_high * (32 - $i) * $b_high * 32] \ | |
167 | [expr $b_low * (32 - $i) * $b_low * 32] ] } { | |
4fa5d7b4 AA |
168 | fail "compare \$v$i" |
169 | } | |
170 | incr j 1 | |
171 | } | |
172 | ||
173 | if { $j != 33 } { | |
174 | fail "info registers vector" | |
175 | } | |
176 | ||
177 | if { $coredir == "" } { | |
178 | return | |
179 | } | |
180 | ||
181 | # Take a core dump. | |
182 | ||
183 | gdb_test "signal SIGABRT" "Program terminated with signal SIGABRT, .*" | |
184 | gdb_exit | |
185 | ||
186 | # Find the core file and rename it (avoid accumulating core files). | |
187 | ||
188 | set cores [glob -nocomplain -directory $coredir *core*] | |
189 | if {[llength $cores] != 1} { | |
190 | untested "core file not found" | |
191 | remote_exec build "rm -rf $coredir" | |
192 | return -1 | |
193 | } | |
194 | set destcore [standard_output_file ${testfile}.core] | |
195 | remote_exec build "mv [file join $coredir [lindex $cores 0]] $destcore" | |
196 | remote_exec build "rm -rf $coredir" | |
197 | ||
198 | # Restart gdb and load the core file. Compare the VRs. | |
199 | ||
200 | clean_restart ${testfile} | |
201 | ||
202 | with_test_prefix "core" { | |
203 | set core_loaded [gdb_core_cmd $destcore "load"] | |
204 | if { $core_loaded != -1 } { | |
205 | set vregs_from_core [capture_command_output "info registers vector" ""] | |
206 | if { $vregs_from_core eq $vregs } { | |
207 | pass "compare vector registers" | |
208 | } else { | |
209 | fail "vector registers mismatch" | |
210 | } | |
211 | } | |
212 | } |