1# Copyright 2015-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# Test vector register access for s390 platforms. 17 18if { ![istarget s390-*-*] && ![istarget s390x-*-* ] } { 19 verbose "Skipping s390 vector register tests." 20 return 21} 22 23standard_testfile .S 24 25if [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 32if { [prepare_for_testing "failed to prepare" $testfile $srcfile \ 33 [list "additional_flags=-mzarch"]] } { 34 return -1 35} 36 37if ![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 45gdb_breakpoint "check_vx" 46gdb_continue_to_breakpoint "first vector insn" 47set before_pc 0 48gdb_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 54gdb_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 71set after_pc 0 72gdb_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 78if [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 85if { $coredir != "" } { 86 gdb_test {print (int) setrlimit (4, &(unsigned long [2]){~0UL, ~0UL})} \ 87 " = .*" "setrlimit" 88 gdb_test "print (int) chdir (\"${coredir}\")" " = 0" "chdir" 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 95set a_high 1 96set a_low 2 97set b_high 3 98set b_low 5 99 100set a [expr ($a_high << 32) | $a_low] 101set b [expr ($b_high << 32) | $b_low] 102 103for {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 116gdb_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 123gdb_continue_to_breakpoint "store vrs" 124set vregs [capture_command_output "x/64xg &save_area" ""] 125 126set i 0 127foreach {- 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 138if { $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 146gdb_continue_to_breakpoint "change vrs" 147set vregs [capture_command_output "info registers vector" ""] 148 149# Format a 128-bit value, given individual 4-byte values, as hex. 150# Suppress leading zeros. 151proc hex128 {a_high a_low b_high b_low} { 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 156} 157 158set j 1 159foreach {- 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" 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] ] } { 168 fail "compare \$v$i" 169 } 170 incr j 1 171} 172 173if { $j != 33 } { 174 fail "info registers vector" 175} 176 177if { $coredir == "" } { 178 return 179} 180 181# Take a core dump. 182 183gdb_test "signal SIGABRT" "Program terminated with signal SIGABRT, .*" 184gdb_exit 185 186# Find the core file and rename it (avoid accumulating core files). 187 188set cores [glob -nocomplain -directory $coredir *core*] 189if {[llength $cores] != 1} { 190 untested "core file not found" 191 remote_exec build "rm -rf $coredir" 192 return -1 193} 194set destcore [standard_output_file ${testfile}.core] 195remote_exec build "mv [file join $coredir [lindex $cores 0]] $destcore" 196remote_exec build "rm -rf $coredir" 197 198# Restart gdb and load the core file. Compare the VRs. 199 200clean_restart ${testfile} 201 202with_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} 213