blob: d18ca56b4ad6b4e4786a864236482a3ee2b93a36 [file] [log] [blame]
/*
* 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