why below compiles :
ITE EQ
MRSEQ R0, MSP
MRSNE R0, PSP
but this not:
ITT NE
MRSN
but this not:
ITT NE MRSNE R0, PSP MRSEQ R0, MSP
First you have some concept issues. What is ITT
all about? First some history. The early ARM CPUs did not support Thumb (16bit), nor Thumb2 (mix 16/32bit) encoding. For the pure ARM, a large part (4 leading bits) are dedicated to conditional execution. The Thumb instruction set does not support conditional execution. For the Thumb2 (what you want on your Cortex-M part), there is a variation on conditional execution. Instead of compiling a condition in each instruction, there is an it
instruction which sets 8 bits in the condition register.
The it
instruction gives a comparison to test (EQ
, NE
, LO
, etc). It then gives up to four conditionals instructions. From the Cortex-A programmer's manual,
Section A.1.34
IT (If-then) makes up to four following instructions conditional (known as the IT
block). The conditions can all be the same, or some can be the logical inverse of others. IT
is a pseudo-instruction in ARM state.
Syntax: IT{x{y{z}}} {cond}
where: cond is a condition code. See Section 6.1.2 which specifies the condition for the first instruction in the IT block.
x , y and z specify the condition switch for the second, third and fourth instructions in the IT
block, for example, ITTET
.
The condition switch can be either:
In order to support both Thumb2 and ARM assembler, a new mode called unified assembler language was created.Ref: Unified Syntax
For pure ARM, the IT
evaluates to nothing. The instructions are encoded with the conditions. For the Thumb2, it primes the condition registers to setup the condition bits. There are three modes of ARM assembler; .arm
, .thumb
and .unified
. Also .code 32
and .code 16
. Depending on the mode in use and the particular assembler (Gnu, ARM, etc) you will get different warnings and/or errors. However, this pattern will never fail for your sequence,
ITE NE ; first NE, 2nd !NE = EQ (Thumb2)
MRSNE R0, PSP ; first NE (ARM)
MRSEQ R0, MSP ; 2nd !NE = EQ (ARM)
The MRS
instructions are the 'IT block'. In your case, you use thumb2 special registers, so the unified syntax doesn't make a lot of sense for the task at hand. See note below.
There are some rules you should be aware of to make unified IT
blocks.
IT
block should not set the condition codes. Ie, cmpne
instruction.IT
block.IT
, so the cond in the IT
must match the first instruction.PSR
, cpsr
, etc. See Note movlo r1, #-1
moveq r1, #0
movhi r1, #1
Would work in ARM, but not Thumb2. In your case, you broke rule '4' and get an error.
Example:
.text
.syntax unified
ITE NE @ first NE, 2nd !NE = EQ (Thumb2)
movne R0, #1 @ first NE (ARM)
moveq R0, #2 @ 2nd !NE = EQ (ARM)
Disassembled ARM,
00000000 <.text>:
0: 13a00001 movne r0, #1
4: 03a00002 moveq r0, #2
Disassembled thumb2,
00000000 <.text>:
0: bf14 ite ne
2: 2001 movne r0, #1
4: 2002 moveq r0, #2
For the thumb2, this is the equivalent without the ITE
instruction,
00000000 <.text>:
0: 2001 movs r0, #1
2: 2002 movs r0, #2
Ie, two moves setting the condition codes. The 2nd number in the dis-assembler is the machine code of course. For a thumb2 OS/scheduler, it will restore the condition register which restores the IT
state and you can enter into the middle of the IT
block. It is also possible to do this manually (however, it maybe highly CPU specific and is not documented that I know of).
Note: For Cortex-M scheduler code which alters the PSR
, you need to use branches. These registers are controlling the IT
block execution. You should not modify the PSR
in the IT
block. The same applies for any context restore instructions; I am not 100% familiar with Cortex-M mode switching which involves changing the active PSR
.