]>
Commit | Line | Data |
---|---|---|
fe5f7374 AK |
1 | # This testcase is part of GDB, the GNU debugger. |
2 | ||
42a4f53d | 3 | # Copyright 2017-2019 Free Software Foundation, Inc. |
fe5f7374 AK |
4 | |
5 | # This program is free software; you can redistribute it and/or modify | |
6 | # it under the terms of the GNU General Public License as published by | |
7 | # the Free Software Foundation; either version 3 of the License, or | |
8 | # (at your option) any later version. | |
9 | # | |
10 | # This program is distributed in the hope that it will be useful, | |
11 | # but WITHOUT ANY WARRANTY; without even the implied warranty of | |
12 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
13 | # GNU General Public License for more details. | |
14 | # | |
15 | # You should have received a copy of the GNU General Public License | |
16 | # along with this program. If not, see <http://www.gnu.org/licenses/>. | |
17 | ||
18 | if {![istarget "arc*-*-*"]} then { | |
19 | verbose "Skipping ARC prologue test." | |
20 | return | |
21 | } | |
22 | ||
23 | standard_testfile .S | |
24 | ||
25 | if { [prepare_for_testing "failed to prepare" $testfile $srcfile] } { | |
26 | return -1 | |
27 | } | |
28 | ||
29 | if ![runto_main] { | |
812cd6eb | 30 | fail "can't run to main" |
fe5f7374 AK |
31 | return 0 |
32 | } | |
33 | ||
34 | # Convert list of saved registers and their offsets to a GDB string. | |
35 | proc saved_regs_to_str { savedregs funcname } { | |
36 | set str "" | |
37 | # If blink is stored, that it is present twice in saved regs - as blink and | |
38 | # as pc. | |
39 | set has_blink 0 | |
40 | set blink_addr 0 | |
41 | foreach r $savedregs { | |
42 | if { [llength $r] == 1 } { | |
43 | append str ".*$r at.*" | |
44 | } else { | |
45 | set name [lindex $r 0] | |
46 | set offset [lindex $r 1] | |
47 | set addr [get_hexadecimal_valueof "\$sp+$offset" 0 \ | |
48 | "get value of $name@sp+$offset in $funcname"] | |
49 | append str "\\s*$name at $addr,?" | |
50 | if { $name == "blink" } { | |
51 | set has_blink 1 | |
52 | set blink_addr $addr | |
53 | } | |
54 | } | |
55 | } | |
56 | if { $has_blink == 1 } { | |
57 | append str "\\s*pc at $blink_addr" | |
58 | } | |
59 | return $str | |
60 | } | |
61 | ||
62 | # Arguments: | |
63 | # funcname - name of function to test | |
64 | # savedregs - list of register saved in the frame. Each entry can be either | |
65 | # a string, where it is a register name, or it is a list of two | |
66 | # items - name of register and it's offset relatively to SP in | |
67 | # the memory. SP value is at the moment of prologue end. | |
68 | # fp_offset - if not an empty string, then proc will test that FP register | |
69 | # has a value that is (SP + offset). | |
70 | ||
71 | proc prologue_test {funcname {savedregs ""} {fp_offset ""} } { | |
72 | global hex | |
73 | gdb_breakpoint $funcname temporary | |
74 | gdb_continue_to_breakpoint $funcname | |
75 | gdb_test "backtrace 10" \ | |
76 | "#0\[ \t\]*$hex in $funcname .*\r\n#1\[ \t\]*$hex in main.*" \ | |
77 | "backtrace in $funcname" | |
78 | if { $savedregs != "" } { | |
79 | set str [saved_regs_to_str $savedregs $funcname] | |
80 | gdb_test "info frame" \ | |
81 | ".*Saved registers:$str" \ | |
82 | "saved registers in $funcname" | |
83 | } | |
84 | if { $fp_offset != "" } { | |
85 | set sp [get_integer_valueof \$sp -1 "get value of sp in $funcname"] | |
86 | set fp_val [expr $sp + $fp_offset] | |
87 | set fp_real_val \ | |
88 | [get_integer_valueof \$fp 0 "get value of fp in $funcname"] | |
89 | if { $fp_real_val != $fp_val } { | |
90 | fail "check FP value in $funcname" | |
91 | } else { | |
92 | pass "check FP value in $funcname" | |
93 | } | |
94 | } | |
95 | } | |
96 | ||
97 | ||
98 | prologue_test "standard_prologue" { {r13 0} {r14 4} {r18 8} {blink 12} } | |
99 | prologue_test "mini_prologue" { {r13 0} {r14 8} {r15 4} {blink 12} } | |
100 | prologue_test "no_subsp_prologue" { {r13 8} {r20 4} {r25 0} {blink 12} } | |
101 | prologue_test "leaf_prologue" { {r13 0} {r15 4} } | |
102 | prologue_test "pushfp_prologue" { {r13 8} {r14 4} {fp 0} } 0 | |
103 | prologue_test "fp_prologue_with_store" { {r13 12} {r14 8} {r15 0} {fp 4} } 4 | |
104 | prologue_test "noncallee_saved_regs_r12_st" { {r12 0} {r13 4} } | |
105 | # Register offset is specified relatively to SP at the prologue end, so | |
106 | # "push r12" hasn't been executed at this moment. | |
107 | prologue_test "noncallee_saved_regs_r12_push" { {r12 0} {r13 4} } | |
108 | prologue_test "noncallee_saved_regs_r2_push" { {r2 0} {r13 4} } | |
109 | prologue_test "noncallee_saved_regs_gp_push" { {r25 4} {gp 0} } | |
110 | prologue_test "noncallee_saved_regs_lp_count" { {r25 4} {lp_count 0} } | |
111 | prologue_test "noncallee_saved_regs_blink_out_of_prologue" { {r25 8} {gp 4} \ | |
112 | {blink 0}} | |
113 | # Argument registers are not reported as "saved" regs. | |
114 | prologue_test "arg_regs_fp" { {r0 12} {r1 8} {r7 4} {r8 0} {fp 16} } 16 | |
115 | prologue_test "arg_regs_fp_mov_s" { {r0 4} {r8 0} {fp 8} } 8 | |
116 | prologue_test "arg_regs_sp" { {r0 0} {r1 4} {r7 8} {r8 12} {r13 16} {r14 20} } | |
117 | prologue_test "enter_s_nop" | |
118 | prologue_test "enter_s_blink" { {blink 0} } | |
119 | prologue_test "enter_s_fp" { {fp 0} } 0 | |
120 | # Layout of registers as stored by enter_s doesn't conform to ARC ABI. | |
121 | prologue_test "enter_s_r13" { {r13 4} {fp 8} {blink 0} } 0 | |
122 | prologue_test "enter_s_r15" { {r13 0} {r14 4} {r15 8} } 0 | |
123 | # This enter_s saves GP, however because it is not a "calle-saved register", | |
124 | # GDB will not report it as "saved register" (but maybe it should). GP is at | |
125 | # offset 56. | |
126 | prologue_test "enter_s_all" { {r13 4} {r14 8} {r15 12} {r16 16} {r17 20} \ | |
127 | {r18 24} {r19 28} {r20 32} {r21 36} {r22 40} {r23 44} {r24 48} {r25 52} \ | |
128 | {gp 56} {fp 60} {blink 0} } 0 | |
129 | ||
130 | # Test more levels of backtrace. | |
131 | gdb_breakpoint nested_prologue_inner temporary | |
132 | gdb_continue_to_breakpoint nested_prologue_inner | |
133 | gdb_test "backtrace 10" \ | |
134 | "#0\[ \t\]*$hex in nested_prologue_inner .*\r\n#1\[ \t\]*$hex in nested_prologue_outer .*\r\n#2\[ \t\]*$hex in main.*" \ | |
135 | "backtrace in nested_prologue_inner" | |
136 | set regs [saved_regs_to_str {r13 r18} "nested_prologue_inner"] | |
137 | gdb_test "info frame" ".*Saved registers:$regs" \ | |
138 | "saved registers in nested_prologue_inner" | |
139 | set regs [saved_regs_to_str {r14 r15 blink} "nested_prologue_inner"] | |
140 | gdb_test "info frame 1" ".*Saved registers:$regs" \ | |
141 | "saved registers in nested_prologue_outer" | |
142 | ||
143 | # sub sp,sp for local variables is part of prologue, hence should be added to | |
144 | # all of those offsets. | |
145 | prologue_test "max_length_prologue" { {r0 72} {r1 76} {r2 80} {r3 84} {r4 88} \ | |
146 | {r5 92} {r6 96} {r7 100} {r13 20} {r14 24} {r15 28} {r16 32} \ | |
147 | {r17 36} {r18 40} {r19 44} {r20 48} {r21 52} {r22 56} {r23 60} {r24 64} \ | |
148 | {r25 68} {fp 16} {blink 104} } | |
149 | ||
150 | prologue_test "branch_in_prologue" { {r13 0} } | |
151 | prologue_test "cond_branch_in_prologue" { {r13 4} } | |
152 | prologue_test "jump_in_prologue" { {r13 0} } | |
153 | prologue_test "cond_jump_in_prologue" { {r13 4} } | |
154 | prologue_test "predicated_insn" { {r13 8} {r15 0} } | |
155 | prologue_test "loop_in_prologue" { {r25 4} {lp_count 0} } | |
156 | prologue_test "store_constant" { {r13 8} {r14 4} } | |
157 | prologue_test "st_c_limm" { {r15 0} } | |
158 | prologue_test "st_ab_writeback" { {r13 8} {r14 4} {r15 0} } | |
159 | prologue_test "st_as_writeback" { {r13 8} {r14 4} {r15 0} } | |
160 | prologue_test "sth_as_writeback" { {r13 8} {r15 0} } | |
161 | prologue_test "std_as_writeback" { {r13 12} {r14 4} {r15 8} {r16 0} } | |
162 | prologue_test "st_halfword" { {r13 8} {r15 0} } | |
163 | prologue_test "sts_halfword" { {r13 8} {r15 0} } | |
164 | prologue_test "st_byte" { {r13 8} {r15 0} } | |
165 | prologue_test "sts_byte" { {r13 8} {r15 0} } | |
166 | prologue_test "sts_byte_sp" { {r13 8} {r15 0} } | |
167 | prologue_test "st_double" { {r14 16} {r15 20} {r18 8} {r19 12}} | |
168 | prologue_test "r_relative_store" { {r13 8} {r14 4} {r15 0} } | |
169 | prologue_test "r_relative_sub_store" { {r13 8} {r14 4} {r15 0} } | |
170 | prologue_test "r_relative_store_st_s" { {r13 8} {r14 0} {r15 4} } | |
171 | prologue_test "r_relative_store_unknown" { {r13 8} } | |
172 | prologue_test "st_s_r0gp" { {r13 8} } | |
173 | prologue_test "push_s_prologue" { {r0 28} {r1 16} {r2 4} {r3 24} {r12 32} \ | |
174 | {r13 20} {r14 12} {r15 8} {blink 0}} | |
175 | prologue_test "sub_s_cbu3" { {r13 4} {r14 0} } | |
176 | prologue_test "sub_s_bbc" { {r1 4} {r13 12} {r14 0} } | |
177 | prologue_test "sub_s_bbu5" { {r13 8} {r14 0} } | |
178 | prologue_test "sub_0bc" { {r13 4} {r14 0} } | |
179 | prologue_test "sub_alimmb" { {r13 4} {r14 0} } | |
180 | prologue_test "sub_s_ne_bbb" { {r13 0} } | |
181 | prologue_test "mov_limm" { {r13 4} {r14 0} } | |
182 | prologue_test "mov0c_limm" { {r13 4} {r14 0} } | |
183 | prologue_test "mov_s_hs3" { {r13 4} {r14 0} } | |
184 | prologue_test "mov_s_bu8" { {r13 4} {r14 0} } | |
185 | prologue_test "mov_s_ne_bh" { {r13 0} } | |
186 | prologue_test "unstored_reg" { {r13 0} {r14 4} } | |
187 | prologue_test "double_store" { {r14 0} } | |
188 | ||
189 | # alloca() tests | |
190 | gdb_breakpoint alloca_inner temporary | |
191 | gdb_continue_to_breakpoint alloca_inner | |
192 | gdb_test "backtrace 3" \ | |
193 | "#0\[ \t\]*$hex in alloca_inner .*\r\n#1\[ \t\]*$hex in alloca_outer .*\r\n#2\[ \t\]*$hex in main.*" \ | |
194 | "backtrace in alloca_inner" | |
195 | set regs [saved_regs_to_str {r13 r14} alloca_inner] | |
196 | gdb_test "info frame 0" ".*Saved registers:$regs" \ | |
197 | "saved registers in alloca_inner" | |
198 | set regs [saved_regs_to_str {fp blink} alloca_inner] | |
199 | gdb_test "info frame 1" ".*Saved registers:$regs" \ | |
200 | "saved registers in alloca_outer" | |
201 |