Automatic date update in version.in
[binutils-gdb.git] / gdb / testsuite / gdb.reverse / aarch64-mops.exp
blob05a991d4bfb9c46476e8ac1beb0676610d6c3e23
1 # Copyright 2024 Free Software Foundation, Inc.
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.
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.
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/>.
16 # Test instruction record for AArch64 FEAT_MOPS instructions.
17 # Based on gdb.reverse/ppc_record_test_isa_3_1.exp
19 # The basic flow of the record tests are:
20 #    1) Stop before executing the instructions of interest.  Record
21 #       the initial value of the registers that the instruction will
22 #       change, i.e. the destination register.
23 #    2) Execute the instructions.  Record the new value of the
24 #       registers that changed.
25 #    3) Reverse the direction of the execution and execute back to
26 #       just before the instructions of interest.  Record the final
27 #       value of the registers of interest.
28 #    4) Check that the initial and new values of the registers are
29 #       different, i.e. the instruction changed the registers as expected.
30 #    5) Check that the initial and final values of the registers are
31 #       the same, i.e. GDB record restored the registers to their
32 #       original values.
34 require allow_aarch64_mops_tests
36 standard_testfile
38 if { [prepare_for_testing "failed to prepare" ${testfile} ${srcfile} \
39           [list debug additional_flags=-march=armv9.3-a]] } {
40     return -1
43 if ![runto_main] {
44     return -1
47 gdb_test_no_output "record full"
49 foreach_with_prefix insn_prefix {"set" "cpy" "cpyf"} {
50     global decimal hex
52     set before_seq [gdb_get_line_number "Before ${insn_prefix}p"]
53     set after_seq [gdb_get_line_number "After ${insn_prefix}e"]
55     gdb_test "break $before_seq" \
56         "Breakpoint $decimal at $hex: file .*/aarch64-mops.c, line $decimal\\." \
57         "break before instruction sequence"
58     gdb_continue_to_breakpoint "about to execute instruction sequence" \
59         [multi_line ".*/aarch64-mops.c:$decimal" \
60              "$decimal\[ \t\]+__asm__ volatile \\(\"${insn_prefix}p \[^\r\n\]+\""]
62     # Depending on the compiler, the line number information may put GDB a few
63     # instructions before the beginning of the asm statement.
64     arrive_at_instruction "${insn_prefix}p"
65     # Add a breakpoint that we're sure is at the prologue instruction.
66     gdb_test "break *\$pc" \
67         "Breakpoint $decimal at $hex: file .*/aarch64-mops.c, line $decimal\\." \
68         "break at prologue instruction"
70     # Record the initial memory and register values.
71     set dest_initial [get_valueof "/x" "dest" "unable to read initial" \
72                           "get dest initial value"]
73     set x19_initial [capture_command_output "info register x19" ""]
74     set x21_initial [capture_command_output "info register x21" ""]
76     # The set instructions use the ZERO variable, but not Q nor SOURCE,
77     # and the other instructions are the opposite.
78     if {[string compare $insn_prefix "set"] == 0} {
79         set x22_initial [capture_command_output "info register x22" ""]
80     } else {
81         set x20_initial [capture_command_output "info register x20" ""]
82         set source_initial [get_valueof "/x" "source" "unable to read initial" \
83                                 "get source initial value"]
84     }
86     gdb_test "break $after_seq" \
87         "Breakpoint $decimal at $hex: file .*/aarch64-mops.c, line $decimal\\." \
88         "break after instruction sequence"
89     gdb_continue_to_breakpoint "executed instruction sequence" \
90         [multi_line ".*/aarch64-mops.c:$decimal" "$decimal\[ \t\]+p = dest;"]
92     # Record the new memory and register values.
93     set dest_new [get_valueof "/x" "dest" "unable to read new" \
94                           "get dest new value"]
95     set x19_new [capture_command_output "info register x19" ""]
96     set x21_new [capture_command_output "info register x21" ""]
98     if {[string compare $insn_prefix "set"] == 0} {
99         set x22_new [capture_command_output "info register x22" ""]
100     } else {
101         set x20_new [capture_command_output "info register x20" ""]
102         set source_new [get_valueof "/x" "source" "unable to read new" \
103                             "get source new value"]
104     }
106     # Execute in reverse to before the instruction sequence.
107     gdb_test_no_output "set exec-direction reverse"
109     gdb_continue_to_breakpoint "reversed execution of instruction sequence" \
110         [multi_line ".*/aarch64-mops.c:$decimal" \
111              "$decimal\[ \t\]+__asm__ volatile \\(\"${insn_prefix}p \[^\r\n\]+\""]
113     # Record the final memory and register values.
114     set dest_final [get_valueof "/x" "dest" "unable to read final" \
115                         "get dest final value"]
116     set x19_final [capture_command_output "info register x19" ""]
117     set x21_final [capture_command_output "info register x21" ""]
119     if {[string compare $insn_prefix "set"] == 0} {
120         set x22_final [capture_command_output "info register x22" ""]
121     } else {
122         set x20_final [capture_command_output "info register x20" ""]
123         set source_final [get_valueof "/x" "source" "unable to read final" \
124                               "get source final value"]
125     }
127     # Check initial and new values of dest are different.
128     gdb_assert [string compare $dest_initial $dest_new] \
129         "check dest initial value versus dest new value"
131     # Check initial and new values of x19 are different.
132     gdb_assert [string compare $x19_initial $x19_new] \
133         "check x19 initial value versus x19 new value"
135     # Check initial and new values of x21 are different.
136     gdb_assert [string compare $x21_initial $x21_new] \
137         "check x21 initial value versus x21 new value"
139     if {[string compare $insn_prefix "set"] == 0} {
140         # Check initial and new values of x22 are the same.
141         # The register with the value to set shouldn't change.
142         gdb_assert ![string compare $x22_initial $x22_new] \
143             "check x22 initial value versus x22 new value"
144     } else {
145         # Check initial and new values of x20 are different.
146         gdb_assert [string compare $x20_initial $x20_new] \
147             "check x20 initial value versus x20 new value"
148         # Check initial and new values of source are the same.
149         gdb_assert ![string compare $source_initial $source_new] \
150             "check source initial value versus source new value"
151     }
153     # Check initial and final values of dest are the same.
154     gdb_assert ![string compare $dest_initial $dest_final] \
155         "check dest initial value versus dest final value"
157     # Check initial and final values of x19 are the same.
158     gdb_assert ![string compare $x19_initial $x19_final] \
159         "check x19 initial value versus x19 final value"
161     # Check initial and final values of x21 are the same.
162     gdb_assert ![string compare $x21_initial $x21_final] \
163         "check x21 initial value versus x21 final value"
165     if {[string compare $insn_prefix "set"] == 0} {
166         # Check initial and final values of x22 are the same.
167         gdb_assert ![string compare $x22_initial $x22_final] \
168             "check x22 initial value versus x22 final value"
169     } else {
170         # Check initial and final values of x20 are the same.
171         gdb_assert ![string compare $x20_initial $x20_final] \
172             "check x20 initial value versus x20 final value"
174         # Check initial and final values of source are the same.
175         gdb_assert ![string compare $source_initial $source_final] \
176             "check source initial value versus source final value"
177     }
179     # Restore forward execution and go to end of recording.
180     gdb_test_no_output "set exec-direction forward"
181     gdb_test "record goto end" \
182         [multi_line \
183              "Go forward to insn number $decimal" \
184              "#0  main \\(\\) at .*/aarch64-mops.c:$decimal" \
185              "$decimal\[ \t\]+p = dest;"]