| /* |
| * Test ARMv6-M UNDEFINED 32-bit instructions |
| * |
| * Copyright 2018 Red Hat Inc. |
| * |
| * This work is licensed under the terms of the GNU GPL, version 2 |
| * or later. See the COPYING file in the top-level directory. |
| */ |
| |
| /* |
| * Test that UNDEFINED 32-bit instructions fault as expected. This is an |
| * interesting test because ARMv6-M shares code with its more fully-featured |
| * siblings and it's necessary to verify that its limited instruction set is |
| * emulated correctly. |
| * |
| * The emulator must be invoked with -semihosting so that the test case can |
| * terminate with exit code 0 on success or 1 on failure. |
| * |
| * Failures can be debugged with -d in_asm,int,exec,cpu and the |
| * gdbstub (-S -s). |
| */ |
| |
| .syntax unified |
| .cpu cortex-m0 |
| .thumb |
| |
| /* |
| * Memory map |
| */ |
| #define SRAM_BASE 0x20000000 |
| #define SRAM_SIZE (16 * 1024) |
| |
| /* |
| * Semihosting interface on ARM T32 |
| * See "Semihosting for AArch32 and AArch64 Version 2.0 Documentation" by ARM |
| */ |
| #define semihosting_call bkpt 0xab |
| #define SYS_EXIT 0x18 |
| |
| vector_table: |
| .word SRAM_BASE + SRAM_SIZE /* 0. SP_main */ |
| .word exc_reset_thumb /* 1. Reset */ |
| .word 0 /* 2. NMI */ |
| .word exc_hard_fault_thumb /* 3. HardFault */ |
| .rept 7 |
| .word 0 /* 4-10. Reserved */ |
| .endr |
| .word 0 /* 11. SVCall */ |
| .word 0 /* 12. Reserved */ |
| .word 0 /* 13. Reserved */ |
| .word 0 /* 14. PendSV */ |
| .word 0 /* 15. SysTick */ |
| .rept 32 |
| .word 0 /* 16-47. External Interrupts */ |
| .endr |
| |
| exc_reset: |
| .equ exc_reset_thumb, exc_reset + 1 |
| .global exc_reset_thumb |
| /* The following 32-bit UNDEFINED instructions are tested by executing |
| * them. The HardFault exception handler should execute and return to |
| * the next test case. If no exception is raised the test fails. |
| */ |
| |
| /* Table A5-9 32-bit Thumb encoding */ |
| .short 0b1110100000000000 |
| .short 0b0000000000000000 |
| b not_reached |
| .short 0b1110100000000000 |
| .short 0b1000000000000000 |
| b not_reached |
| .short 0b1111100000000000 |
| .short 0b0000000000000000 |
| b not_reached |
| .short 0b1111100000000000 |
| .short 0b1000000000000000 |
| b not_reached |
| .short 0b1111000000000000 |
| .short 0b0000000000000000 |
| b not_reached |
| |
| /* Table A5-10 Branch and miscellaneous control instructions */ |
| .short 0b1111011111110000 |
| .short 0b1010000000000000 |
| b not_reached |
| |
| /* The following are valid 32-bit instructions that must not raise a |
| * HardFault. |
| */ |
| |
| /* B4.2.3 Move to Special Register (moves to IPSR are ignored) */ |
| msr ipsr, r0 |
| b 1f |
| b not_reached |
| 1: |
| /* B4.2.2 Move from Special Register */ |
| mrs r0, ipsr |
| b 1f |
| b not_reached |
| 1: |
| /* A6.7.13 Branch with Link (immediate) */ |
| bl 1f |
| 1: |
| b 1f |
| b not_reached |
| 1: |
| /* A6.7.21 Data Memory Barrier */ |
| dmb |
| b 1f |
| b not_reached |
| 1: |
| /* A6.7.22 Data Synchronization Barrier */ |
| dsb |
| b 1f |
| b not_reached |
| 1: |
| /* A6.7.24 Instruction Memory Barrier */ |
| isb |
| b 1f |
| b not_reached |
| 1: |
| |
| /* Success! */ |
| movs r0, 1 |
| b exit |
| |
| not_reached: /* Failure :( */ |
| movs r0, 0 |
| b exit |
| |
| /* When a HardFault occurs, return to pc+6 (test cases are 3 halfwords long) */ |
| exc_hard_fault: |
| .equ exc_hard_fault_thumb, exc_hard_fault + 1 |
| .global exc_hard_fault_thumb |
| ldr r0, [sp, 0x18] |
| adds r0, 6 |
| str r0, [sp, 0x18] |
| bx lr |
| |
| /* |
| * exit: Terminate emulator |
| * @r0: 0 - failure, 1 - success |
| */ |
| exit: |
| movs r1, 0 |
| cmp r0, 1 |
| bne 1f |
| ldr r1, ADP_Stopped_ApplicationExit |
| 1: |
| movs r0, SYS_EXIT |
| semihosting_call |
| .align 2 |
| ADP_Stopped_ApplicationExit: |
| .word 0x20026 |