ARM IT conditional instruction assembler (armcc)

arm, assembly, conditional-statements

Solution

Overview

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,

Documentation

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:

- T (Then), which applies the condition cond to the instruction.

- E (Else), which applies the inverse condition of cond to the instruction.

Limitations of Thumb2 conditional blocks

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.

- The `IT` block should not set the condition codes. Ie, `cmpne` instruction.

- You should not branch into the `IT` block.

- We always start with `IT`, so the cond in the `IT` must match the first instruction.

- Following instruction must match cond, if 'T' or !cond if 'E'.

- You should not alter the condition register `PSR`, `cpsr`, etc. See Note

- You can only mix opposite types. For instance,

     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. As well, the ARM allowed unconditional instructions to be mixed with conditional instructions. But generally, it is a high price to pay to have these extra bits of the opcode when 90-99% of cases are unconditional execution in compiled code.

Examining opcodes

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).

The Thumb2 is 6 bytes and the ARM code is 8 bytes for equivalent functionality. The Thumb2 will require more code space if 'wide' (32bit) opcodes are in the conditional block.

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`.

Problem

why below compiles : ``` ITE EQ MRSEQ R0, MSP MRSNE R0, PSP ``` but this not: ``` ITT NE MRSNE R0, PSP MRSEQ R0, MSP ``` Is it possible, that both MRSNE R0, PSP and MRSEQ R0, MSP execute (this is my case)? ``` This compiles: ``` ``` ITT NE MRSNE R0, PSP MRSNE R0, MSP ``` Is it ARM standard?

Original source

Related problems