1# This testcase is part of GDB, the GNU debugger. 2 3# Copyright 2017-2020 Free Software Foundation, Inc. 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 18if {![istarget "arc*-*-*"]} then { 19 verbose "Skipping ARC prologue test." 20 return 21} 22 23standard_testfile .S 24 25if { [prepare_for_testing "failed to prepare" $testfile $srcfile] } { 26 return -1 27} 28 29if ![runto_main] { 30 fail "can't run to main" 31 return 0 32} 33 34# Convert list of saved registers and their offsets to a GDB string. 35proc 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 71proc 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 98prologue_test "standard_prologue" { {r13 0} {r14 4} {r18 8} {blink 12} } 99prologue_test "mini_prologue" { {r13 0} {r14 8} {r15 4} {blink 12} } 100prologue_test "no_subsp_prologue" { {r13 8} {r20 4} {r25 0} {blink 12} } 101prologue_test "leaf_prologue" { {r13 0} {r15 4} } 102prologue_test "pushfp_prologue" { {r13 8} {r14 4} {fp 0} } 0 103prologue_test "fp_prologue_with_store" { {r13 12} {r14 8} {r15 0} {fp 4} } 4 104prologue_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. 107prologue_test "noncallee_saved_regs_r12_push" { {r12 0} {r13 4} } 108prologue_test "noncallee_saved_regs_r2_push" { {r2 0} {r13 4} } 109prologue_test "noncallee_saved_regs_gp_push" { {r25 4} {gp 0} } 110prologue_test "noncallee_saved_regs_lp_count" { {r25 4} {lp_count 0} } 111prologue_test "noncallee_saved_regs_blink_out_of_prologue" { {r25 8} {gp 4} \ 112 {blink 0}} 113# Argument registers are not reported as "saved" regs. 114prologue_test "arg_regs_fp" { {r0 12} {r1 8} {r7 4} {r8 0} {fp 16} } 16 115prologue_test "arg_regs_fp_mov_s" { {r0 4} {r8 0} {fp 8} } 8 116prologue_test "arg_regs_sp" { {r0 0} {r1 4} {r7 8} {r8 12} {r13 16} {r14 20} } 117prologue_test "enter_s_nop" 118prologue_test "enter_s_blink" { {blink 0} } 119prologue_test "enter_s_fp" { {fp 0} } 0 120# Layout of registers as stored by enter_s doesn't conform to ARC ABI. 121prologue_test "enter_s_r13" { {r13 4} {fp 8} {blink 0} } 0 122prologue_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. 126prologue_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. 131gdb_breakpoint nested_prologue_inner temporary 132gdb_continue_to_breakpoint nested_prologue_inner 133gdb_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" 136set regs [saved_regs_to_str {r13 r18} "nested_prologue_inner"] 137gdb_test "info frame" ".*Saved registers:$regs" \ 138 "saved registers in nested_prologue_inner" 139set regs [saved_regs_to_str {r14 r15 blink} "nested_prologue_inner"] 140gdb_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. 145prologue_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 150prologue_test "branch_in_prologue" { {r13 0} } 151prologue_test "cond_branch_in_prologue" { {r13 4} } 152prologue_test "jump_in_prologue" { {r13 0} } 153prologue_test "cond_jump_in_prologue" { {r13 4} } 154prologue_test "predicated_insn" { {r13 8} {r15 0} } 155prologue_test "loop_in_prologue" { {r25 4} {lp_count 0} } 156prologue_test "store_constant" { {r13 8} {r14 4} } 157prologue_test "st_c_limm" { {r15 0} } 158prologue_test "st_ab_writeback" { {r13 8} {r14 4} {r15 0} } 159prologue_test "st_as_writeback" { {r13 8} {r14 4} {r15 0} } 160prologue_test "sth_as_writeback" { {r13 8} {r15 0} } 161prologue_test "std_as_writeback" { {r13 12} {r14 4} {r15 8} {r16 0} } 162prologue_test "st_halfword" { {r13 8} {r15 0} } 163prologue_test "sts_halfword" { {r13 8} {r15 0} } 164prologue_test "st_byte" { {r13 8} {r15 0} } 165prologue_test "sts_byte" { {r13 8} {r15 0} } 166prologue_test "sts_byte_sp" { {r13 8} {r15 0} } 167prologue_test "st_double" { {r14 16} {r15 20} {r18 8} {r19 12}} 168prologue_test "r_relative_store" { {r13 8} {r14 4} {r15 0} } 169prologue_test "r_relative_sub_store" { {r13 8} {r14 4} {r15 0} } 170prologue_test "r_relative_store_st_s" { {r13 8} {r14 0} {r15 4} } 171prologue_test "r_relative_store_unknown" { {r13 8} } 172prologue_test "st_s_r0gp" { {r13 8} } 173prologue_test "push_s_prologue" { {r0 28} {r1 16} {r2 4} {r3 24} {r12 32} \ 174 {r13 20} {r14 12} {r15 8} {blink 0}} 175prologue_test "sub_s_cbu3" { {r13 4} {r14 0} } 176prologue_test "sub_s_bbc" { {r1 4} {r13 12} {r14 0} } 177prologue_test "sub_s_bbu5" { {r13 8} {r14 0} } 178prologue_test "sub_0bc" { {r13 4} {r14 0} } 179prologue_test "sub_alimmb" { {r13 4} {r14 0} } 180prologue_test "sub_s_ne_bbb" { {r13 0} } 181prologue_test "mov_limm" { {r13 4} {r14 0} } 182prologue_test "mov0c_limm" { {r13 4} {r14 0} } 183prologue_test "mov_s_hs3" { {r13 4} {r14 0} } 184prologue_test "mov_s_bu8" { {r13 4} {r14 0} } 185prologue_test "mov_s_ne_bh" { {r13 0} } 186prologue_test "unstored_reg" { {r13 0} {r14 4} } 187prologue_test "double_store" { {r14 0} } 188 189# alloca() tests 190gdb_breakpoint alloca_inner temporary 191gdb_continue_to_breakpoint alloca_inner 192gdb_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" 195set regs [saved_regs_to_str {r13 r14} alloca_inner] 196gdb_test "info frame 0" ".*Saved registers:$regs" \ 197 "saved registers in alloca_inner" 198set regs [saved_regs_to_str {fp blink} alloca_inner] 199gdb_test "info frame 1" ".*Saved registers:$regs" \ 200 "saved registers in alloca_outer" 201 202