Instruction Set Changes for ARM (Compact 2013)
3/26/2014
When porting your code to ARM, keep in mind the following ARM instruction set requirements and limitations for Windows Embedded Compact 2013:
- Only ARMv7 Thumb-2 instructions are supported. For more information, see the ARM and Thumb-2 Instruction Set Quick Reference.
- Reset and exception handlers in Thumb-2 mode are not supported.
- The CPU must be in Thumb-2 mode before running any Windows Embedded Compact 2013 code.
- The CPU must have a VFPv3-D32 coprocessor. This means that a full set of 32 registers are available for use and that you can use the floating point registers for parameter passing. Registers d8 through d15 are non-volatile and you must restore their previous values if you use them. IEEE floating point exceptions are not supported.
You should keep your ARM mode code in a separate ASM file from ASM files containing Thumb-2 code, and be sure to explicitly specify Thumb mode when assembling your ASM files containing Thumb-2 code. Mixing ARM mode instructions and Thumb-2 instructions in the same ASM module will not work correctly. For example, ARM mode code that calls Thumb-2 mode code via BLX is supposed to branch to an address that has the least significant bit (LSB) set to 1. However, the LSB will not be set unless the Thumb-2 mode function is defined in a separate assembly code file that is specifically assembled as Thumb mode code.
The assembler sets the LSB of each word of a symbol in a code section because it interprets them as destination instructions. In thumb mode, setting the low order bit informs the CPU that it should switch to thumb mode, if it is not already in that mode. Move non-code symbols such as g_oalAddressTable to the DATAAREA instead of the TEXTAREA so that the assembler doesn’t set the LSB of non-code symbols.
If the bootloader starts in ARM mode, switch to Thumb-2 mode in your bootloader initialization code. Note that the jump page at the top of the nb0 file created by ROMIMAGE.exe assumes that the bootloader starts in ARM mode and makes the switch to Thumb-2 mode. Also, do not set the Thumb exception enable bit (TE) in CP15::SCTRL in an effort to enable exception handlers in Thumb-2 mode.
If you have used hard-coded instruction opcodes to work around an assembler that doesn’t support a particular instruction, you will need to update these instructions to their Thumb-2 variants. For example, if your assembler didn’t recognize the mnemonic for Secure Monitor Call (SMC) and you hard-coded the instruction opcode by using DCD, you must rewrite the instructions by using the ARM Unified Assembly Language (UAL) mnemonic. Otherwise, you will get an exception when the non-Thumb-2 instruction is executed.
The following example shows a code fragment with hardcoded instructions that are not supported in Thumb-2 mode.
Warning
For readability, the following code example does not contain security checking or error handling. Do not use the following code in a production environment.
;-------------------------------------------------------------------------------
; Function: SomeFunction
;
; Hard-coding fmrx because the assembler being used didn't support it
DCD 0xeef82a10 ; fmrx r2, fpexc
orr r11, r10, r9, lsl r5 ; orr with rotation isn't supported in thumb2 mode
; These instructions move the pc forward two instructions. But in thumb-2 mode
; instructions are 2 bytes instead of 4, so this code will overshoot the desired
; address.
; Additionally, pc arithmetic is not allowed in the UAL
addne r0, pc, #g_oalAddressTable - (. + 8) ;pc arithmetic not allowed in UAL
addeq r0, pc, #g_oalAddressTableHynix - (. + 8)
...
Rewriting the instructions by using UAL mnemonic equivalent opcodes updates this code for Thumb-2, as shown in the following example.
;-------------------------------------------------------------------------------
; Function: SomeFunction
;
...
vmrs r2, fpexc ; Instead of using DCD to hard code instructions,
; use the Thumb-2 UAL mnemonic equivalent
lsl r6, r9, r5 ; Use this sequence to replace the orr with rotation
; instruction. (r6) = r9 << r5
orr r11, r10, r6
adrne r0, g_oalAddressTable ; Replace pc-relative calculation (.+8) which
adreq r0, g_oalAddressTableHynix ; is only valid in ARM mode.