# Copyright 2023-2024 Free Software Foundation, Inc. # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 3 of the License, or # (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program. If not, see . */ # Support routines for aarch64 scalable extension tests # Load generic aarch64 test dependencies. load_lib aarch64.exp # # Return a regular expression that matches what gdb would print for a # SVE Z register of length VL in state STATE. The Z register should be filled # with BYTE_SVE and the FPSIMD registers should be filled with BYTE_FPSIMD. # # The pattern is of the form # # {BYTE_FPSIMD } # # or # # {BYTE_FPSIMD , 0 } # # or # # {BYTE_SVE } # proc sve_value_pattern { state vl byte_fpsimd byte_sve } { set brace_open "{" set brace_close "}" append data $brace_open if { $state == "fpsimd" || $state == "za" } { if { $vl > 16 } { set sve_repeat_count [expr $vl - 16] append data "$byte_fpsimd , 0 " } else { append data "$byte_fpsimd " } } else { append data "$byte_sve " } append data $brace_close verbose -log "sve_value_pattern pattern string is..." verbose -log $data return $data } # # Return the SVCR value based on STATE. # SVCR is only available when SME is available. # proc get_svcr_value { state } { if { $state == "ssve" } { return "= \\\[ SM \\\]" } elseif { $state == "za" } { return "= \\\[ ZA \\\]" } elseif { $state == "za_ssve" } { return "= \\\[ SM ZA \\\]" } return "= \\\[ \\\]" } # # Return the state string based on STATE # proc state_id_to_state_string { state } { if {$state == 0} { return "fpsimd" } elseif {$state == 1} { return "sve" } elseif {$state == 2} { return "ssve" } elseif {$state == 3} { return "za" } elseif {$state == 4} { return "za_ssve" } } # # Given a test ID, return the string representing the register state. # The state is one of fpsimd, sve, ssve, za and za_ssve. # proc test_id_to_state { id } { set state [expr $id / 25] return [state_id_to_state_string $state] } # # Given a test ID, return the associated vector length. # proc test_id_to_vl { id } { return [expr 16 << (($id / 5) % 5)] } # # Given a test ID, return the associated streaming vector length. # proc test_id_to_svl { id } { return [expr 16 << ($id % 5)] } # # Validate the values of the SVE registers. # proc check_sve_regs { byte state vl svl } { # If streaming mode is enabled, the vector length is the streaming # vector length. set z_pattern "" set z_size 0 if {$state == "ssve" || $state == "za_ssve"} { set z_pattern [string_to_regexp [1d_array_value_pattern $byte $svl]] set z_size $svl } else { set z_size $vl if {$state == "fpsimd" || $state == "za"} { # If there is no SVE/SSVE state, the contents of the Z/P/FFR registers # are zero. if {$vl == 16} { set z_pattern [string_to_regexp [1d_array_value_pattern $byte $vl]] } else { set z_repeats [expr $vl - 16] set z_pattern [string_to_regexp "{$byte , 0 }"] } } else { set z_pattern [string_to_regexp [1d_array_value_pattern $byte $vl]] } } set p_size [expr $z_size / 8] # If there is no SVE/SSVE state, the contents of the Z/P/FFR registers # are zero. set p_byte $byte if {$state == "fpsimd" || $state == "za"} { set p_byte 0 } set p_pattern [string_to_regexp [1d_array_value_pattern $p_byte $p_size]] for {set number 0} {$number < 32} {incr number} { set register_name "\$z${number}\.b\.u" gdb_test "print sizeof $register_name" " = $z_size" gdb_test "print $register_name" $z_pattern } for {set number 0} {$number < 16} {incr number} { set register_name "\$p${number}" gdb_test "print sizeof $register_name" " = $p_size" gdb_test "print $register_name" $p_pattern } gdb_test "print \$ffr" $p_pattern } # # Validate the values of the SME registers. # proc check_sme_regs { byte state svl } { # ZA contents are only available when the ZA state is enabled. Otherwise # the ZA contents are unavailable (zeroed out). set za_pattern "" set expected_za_size [expr $svl * $svl] if {$state != "za" && $state != "za_ssve"} { set byte 0 } set za_pattern [string_to_regexp [2d_array_value_pattern $byte $svl $svl]] gdb_test "print sizeof \$za" " = $expected_za_size" gdb_test "print \$za" $za_pattern } # # Validate the values of the SME2 registers. # proc check_sme2_regs { byte } { # The size of the ZT registers should always be fixed to 64 bytes. set zt_size 64 gdb_test "print sizeof \$zt0" " = $zt_size" # Check that we have the expected pattern of bytes for the ZT registers. set zt_pattern [string_to_regexp [1d_array_value_pattern $byte $zt_size]] gdb_test "print \$zt0" $zt_pattern } # # With register STATE, vector length VL and streaming vector length SVL, # run some register state checks to make sure the values are the expected # ones # proc check_state { state vl svl } { # The FPSIMD registers are initialized with a value of 0x55 (85) # for each byte. # # The SVE registers are initialized with a value of 0xff (255) for each # byte, including the predicate registers and FFR. # # The SME (ZA) register is initialized with a value of 0xaa (170) for # each byte. # # The SME2 (ZT) registers are initialized with a value of 0xff (255) for # each byte. # Check VG to make sure it is correct set expected_vg [expr $vl / 8] # If streaming mode is enabled, then vg is actually svg. if {$state == "ssve" || $state == "za_ssve"} { set expected_vg [expr $svl / 8] } gdb_test "print \$vg" " = ${expected_vg}" # Check SVG to make sure it is correct set expected_svg [expr $svl / 8] gdb_test "print \$svg" " = ${expected_svg}" # Check the value of SVCR. gdb_test "print \$svcr" [get_svcr_value $state] # When we have any SVE or SSVE state, the FPSIMD registers will have # the same values as the SVE/SSVE Z registers. set fpsimd_byte 85 if {$state == "sve" || $state == "ssve" || $state == "za_ssve"} { set fpsimd_byte 255 } set sve_byte 255 if {$state == "fpsimd" || $state == "za"} { set sve_byte 85 } # Check FPSIMD registers check_fpsimd_regs $fpsimd_byte $state $vl $svl # Check SVE registers check_sve_regs $sve_byte $state $vl $svl # Check SME registers check_sme_regs 170 $state $svl # Check SME2 registers if [is_sme2_available] { # The SME2 ZT0 register will always be zero, except when ZA is active. set sme2_byte 0 if {$state == "za" || $state == "za_ssve"} { set sme2_byte 255 } # The target supports SME2, so check the ZT register values. check_sme2_regs $sme2_byte } } # # Return 1 if SME2 is available (meaning the ZT0 register exists). # Return 0 otherwise. # proc is_sme2_available { } { # Does the ZT0 register exist? gdb_test_multiple "print \$zt0" "" { -re " = void.*${::gdb_prompt} $" { # SME2 is not available. return 0 } -re " = {.*}\r\n${::gdb_prompt} $" { # SME2 is available. return 1 } } }