| /* Copyright 2010-2021 Free Software Foundation, Inc. |
| |
| This file is part of GDB. |
| |
| 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 <http://www.gnu.org/licenses/>. */ |
| |
| .syntax unified |
| .text |
| .type main,%function |
| #if defined (__thumb__) |
| .code 16 |
| .thumb_func |
| #endif |
| .globl main |
| main: |
| push {r7, lr} |
| add sp, sp, #4 |
| mov r7, sp |
| |
| |
| /* Test call and return */ |
| .global test_call |
| test_call: |
| bl test_call_subr |
| .global test_ret_end |
| test_ret_end: |
| nop @ Location test_ret_end |
| |
| /* Test branch */ |
| bl test_branch |
| |
| /* Test ldr from pc */ |
| bl test_ldr_pc |
| |
| /* Test ldm/stm only in ARM mode */ |
| #if !defined (__thumb__) |
| bl test_ldm_stm_pc |
| #endif |
| |
| /* Test ldrX literal in ARM and Thumb-2 */ |
| #if !defined (__thumb__) || defined(__thumb2__) |
| bl test_ldr_literal |
| #endif |
| |
| /* Test ldr literal in Thumb */ |
| #if defined(__thumb__) |
| bl test_ldr_literal_16 |
| #endif |
| |
| /* Test cbnz/cbz in Thumb-2 */ |
| #if defined(__thumb2__) |
| bl test_cbz_cbnz |
| #endif |
| |
| /* Test adr in Thumb and Thumb-2 */ |
| #if defined(__thumb__) |
| bl test_adr |
| #endif |
| /* Test 32-bit adr in ARM and Thumb-2 */ |
| #if defined(__thumb2__) || !defined(__thumb__) |
| bl test_adr_32bit |
| #endif |
| |
| bl test_pop_pc |
| |
| /* Test str in ARM mode and Thumb-2 */ |
| #if !defined(__thumb__) |
| bl test_str_pc |
| #endif |
| |
| /* Test add with pc in Thumb and Thumb-2 */ |
| #if defined(__thumb__) |
| bl test_add_rn_pc |
| #endif |
| /* Return */ |
| mov sp, r7 |
| sub sp, sp, #4 |
| movs r0, #0 |
| pop {r7, pc} |
| .size main, .-main |
| |
| .global test_call_subr |
| #if defined (__thumb__) |
| .code 16 |
| .thumb_func |
| #endif |
| .type test_call_subr, %function |
| test_call_subr: |
| nop |
| .global test_call_end |
| test_call_end: |
| nop @ Location test_call_end |
| .global test_ret |
| test_ret: |
| bx lr |
| .size test_call_subr, .-test_call_subr |
| |
| |
| .global test_branch |
| #if defined (__thumb__) |
| .code 16 |
| .thumb_func |
| #endif |
| .type test_branch, %function |
| test_branch: |
| b L_branch |
| .global L_branch |
| L_branch: |
| bx lr |
| .size test_branch, .-test_branch |
| |
| .global test_ldr_pc |
| #if defined (__thumb__) |
| .code 16 |
| .thumb_func |
| #endif |
| .type test_ldr_pc, %function |
| test_ldr_pc: |
| ldr r1, [pc, #0] |
| |
| .global test_ldr_pc_ret |
| test_ldr_pc_ret: |
| bx lr |
| .size test_ldr_pc, .-test_ldr_pc |
| |
| #if !defined (__thumb__) |
| .global test_ldm_stm_pc |
| .type test_ldm_stm_pc, %function |
| test_ldm_stm_pc: |
| stmdb sp!, {lr, pc} |
| ldmia sp!, {r0, r1} |
| ldr r0, .L1 |
| stmdb sp!, {r0} |
| .global test_ldm_pc |
| test_ldm_pc: |
| ldmia sp!, {pc} |
| .global test_ldm_stm_pc_ret |
| test_ldm_stm_pc_ret: |
| bx lr |
| .align 2 |
| .L1: |
| .word test_ldm_stm_pc_ret |
| .size test_ldm_stm_pc, .-test_ldm_stm_pc |
| #endif |
| |
| #if !defined (__thumb__) || defined(__thumb2__) |
| .global test_ldr_literal |
| .type test_ldr_literal, %function |
| test_ldr_literal: |
| ldrh r0, [pc] |
| .global test_ldrsb_literal |
| test_ldrsb_literal: |
| ldrsb r0, [pc] |
| .global test_ldrsh_literal |
| test_ldrsh_literal: |
| ldrsh r0, [pc] |
| .global test_ldr_literal_end |
| test_ldr_literal_end: |
| bx lr |
| .size test_ldr_literal, .-test_ldr_literal |
| #endif |
| |
| #if defined(__thumb__) |
| .global test_ldr_literal_16 |
| .code 16 |
| .thumb_func |
| test_ldr_literal_16: |
| ldr r0, .L2 |
| .global test_ldr_literal_16_end |
| test_ldr_literal_16_end: |
| bx lr |
| .align 2 |
| .L2: |
| .word test_ldr_literal_16 |
| .size test_ldr_literal_16, .-test_ldr_literal_16 |
| #endif |
| |
| #if defined(__thumb2__) |
| .global test_cbz_cbnz |
| .code 16 |
| .thumb_func |
| test_cbz_cbnz: |
| movs r0, #0 |
| .global test_zero_cbnz |
| test_zero_cbnz: |
| cbnz r0, .L3 |
| .global test_zero_cbz |
| test_zero_cbz: |
| cbz r0, .L3 |
| .L3: |
| movs r0, #1 |
| .global test_non_zero_cbz |
| test_non_zero_cbz: |
| cbz r0, .L4 |
| .global test_non_zero_cbnz |
| test_non_zero_cbnz: |
| cbnz r0, .L4 |
| nop |
| .L4: |
| .global test_cbz_cbnz_end |
| test_cbz_cbnz_end: |
| bx lr |
| .size test_cbz_cbnz, .-test_cbz_cbnz |
| #endif |
| |
| #if defined(__thumb__) |
| .global test_adr |
| .code 16 |
| .thumb_func |
| test_adr: |
| adr r0, .L8 |
| nop |
| nop |
| nop |
| .L8: |
| .global test_adr_end |
| test_adr_end: |
| bx lr |
| .size test_adr, .-test_adr |
| #endif |
| |
| #if defined(__thumb2__) || !defined(__thumb__) |
| .global test_adr_32bit |
| #if defined(__thumb2__) |
| .code 16 |
| .thumb_func |
| #endif |
| test_adr_32bit: |
| adr r0, .L6 |
| nop |
| .L6: |
| nop |
| .global test_adr_32bit_after |
| test_adr_32bit_after: |
| adr r0, .L6 |
| |
| .global test_adr_32bit_end |
| test_adr_32bit_end: |
| bx lr |
| .size test_adr_32bit, .-test_adr_32bit |
| #endif |
| |
| .global test_pop_pc |
| .type test_pop_pc, %function |
| #if defined(__thumb__) |
| .code 16 |
| .thumb_func |
| #endif |
| |
| test_pop_pc: |
| ldr r1, .L1_right |
| ldr r2, .L1_wrong |
| #if defined(__thumb__) |
| movs r0, #1 |
| orrs r1, r0 |
| orrs r2, r0 |
| #endif |
| push {r1} |
| push {r2} |
| .global test_pop_pc_1 |
| test_pop_pc_1: |
| pop {r1, pc} |
| |
| test_pop_pc_2_start: |
| ldr r1, .L2_right |
| #if defined(__thumb__) |
| movs r0, #1 |
| orrs r1, r0 |
| #endif |
| push {r1} |
| .global test_pop_pc_2 |
| test_pop_pc_2: |
| pop {pc} |
| |
| /* Test pop instruction with full register list. */ |
| test_pop_pc_3_start: |
| ldr r1, .L3_right |
| ldr r2, .L3_wrong |
| #if defined(__thumb__) |
| movs r0, #1 |
| orrs r1, r0 |
| orrs r2, r0 |
| #endif |
| push {r7} |
| push {r1} /* Push the right address so that PC will get it. */ |
| /* Push the wrong address so r0-r7 will get the wrong a ddress. If PC |
| is set from any of them, we can get a FAIL. */ |
| push {r2} |
| push {r2} |
| push {r2} |
| push {r2} |
| push {r2} |
| push {r2} |
| push {r2} |
| push {r2} |
| test_pop_pc_3: |
| pop {r0,r1,r2,r3,r4,r5,r6,r7,pc} |
| .global test_pop_pc_ret |
| test_pop_pc_ret: |
| pop {r7} |
| bx lr |
| |
| .global test_pop_pc_1_right |
| test_pop_pc_1_right: |
| b test_pop_pc_2_start /* right */ |
| .global test_pop_pc_1_wrong |
| test_pop_pc_1_wrong: |
| b test_pop_pc_2_start /* wrong */ |
| .global test_pop_pc_2_right |
| test_pop_pc_2_right: |
| b test_pop_pc_3_start /* right */ |
| .global test_pop_pc_2_wrong |
| test_pop_pc_2_wrong: |
| b test_pop_pc_3_start /* wrong */ |
| .global test_pop_pc_3_right |
| test_pop_pc_3_right: |
| b test_pop_pc_ret /* right */ |
| .global test_pop_pc_3_wrong |
| test_pop_pc_3_wrong: |
| b test_pop_pc_ret /* wrong */ |
| |
| .align 2 |
| .L1_right: |
| .word test_pop_pc_1_right |
| .L1_wrong: |
| .word test_pop_pc_1_wrong |
| .L2_right: |
| .word test_pop_pc_2_right |
| .L2_wrong: |
| .word test_pop_pc_2_wrong |
| .L3_right: |
| .word test_pop_pc_3_right |
| .L3_wrong: |
| .word test_pop_pc_3_wrong |
| .size test_pop_pc, .-test_pop_pc |
| |
| #if !defined(__thumb__) |
| #if defined (__thumb2__) |
| .code 16 |
| .thumb_func |
| #endif |
| .global test_str_pc |
| .type test_str_pc, %function |
| test_str_pc: |
| str pc, [sp, #-4] |
| ldr r0, [sp, #-4] |
| sub r0, r0, pc |
| /* compute offset again without displaced stepping. */ |
| str pc, [sp, #-4] |
| ldr r1, [sp, #-4] |
| sub r1, r1, pc |
| |
| /* r0 should be equal to r1. */ |
| cmp r0, r1 |
| bne pc_offset_wrong |
| |
| .global pc_offset_right |
| pc_offset_right: |
| b test_str_pc_end |
| |
| .global pc_offset_wrong |
| pc_offset_wrong: |
| nop |
| |
| .global test_str_pc_end |
| test_str_pc_end: |
| bx lr |
| #endif |
| |
| #if defined(__thumb__) |
| .global test_add_rn_pc |
| .code 16 |
| .thumb_func |
| test_add_rn_pc: |
| mov r3, 4 |
| test_add_rn_pc_start: |
| add r3, pc |
| .global test_add_rn_pc_end |
| test_add_rn_pc_end: |
| bx lr |
| .size test_add_rn_pc, .-test_add_rn_pc |
| #endif |