Reputation: 355
Most examples have IT commands such as the following,
ITTE NE ; IT can be omitted
ANDNE r0,r0,r1 ; 16-bit AND, not ANDS
ADDSNE r2,r2,#1 ; 32-bit ADDS (16-bit ADDS does not set flags in IT block)
MOVEQ r2,r3 ; 16-bit MOV
ITT AL ; emit 2 non-flag setting 16-bit instructions
ADDAL r0,r0,r1 ; 16-bit ADD, not ADDS
SUBAL r2,r2,#1 ; 16-bit SUB, not SUB
ADD r0,r0,r1 ; expands into 32-bit ADD, and is not in IT block
ITT EQ
MOVEQ r0,r1
BEQ dloop ; branch at end of IT block is permitted
ITT EQ
MOVEQ r0,r1
BKPT #1 ; BKPT always executes
ADDEQ r0,r0,#1
I want to look at for example the last IT block in the examples. Im really confused what is happening. For MOVEQ, I thought it was checking if r0 = r1, and moving r1 into r0 if they were equal. But that doesn't make sense if they are equal. What is really going on?
I wrote a thumb code that checks which number is greater:
cmp r0, r1
ITE HS
movhs r0, r0
movlo r0, r1
Here I needed to compare registers before the IT block... But why do all the examples not include a comparison atleast before hand? Would there been another way to write an IT block for my example that doesn't include a comparison? What's really going on in these examples?
Upvotes: 1
Views: 1093
Reputation: 364428
Flags are an input to predicated instructions inside an IT block. Yes, you do put a cmp
or adds
or whatever other flag-setting instruction at some point before an it
. It doesn't have to be right before.
The examples you show exist to document corner cases for IT
, not full/complete examples of using it to actually do something specific.
The documentation for a conditional branch instruction doesn't typically show flag-setting instructions either.
According to ARM's docs
With the exception of CMP, CMN, and TST, the 16-bit instructions that normally affect the condition code flags, do not affect them when used inside an IT block.
But one of the examples does clearly show that you can change flags with a 32-bit adds
inside an IT block, and this tells us that regular compare/test instructions are allowed.
The docs don't make it clear that changes to flags within an IT block have an effect on later predicated instructions inside the block. @DanLewis's answer confirms that they do.
In ARM mode, no IT block is needed to predicate execution (4 bits in every instruction encode a predicate) so flag-setting instructions obviously affect later instructions. It makes sense that it works the same way in Thumb mode, especially since IT
is optional in some syntaxes. (Some assemblers will insert it for you in unified syntax if assembling for thumb mode.)
Upvotes: 4
Reputation: 93
@Darklink9110: yes, you can change flags inside an IT block, the docs are clear on that. > They're not clear on whether that has any effect on the rest of the current block.
I tested the following two functions on an ARM Cortex-M4 (Thumb-2) to find out, and it turns out that if an instruction inside an IT block changes the flags, then subsequent instructions in the same IT block (1) such as ADC, SBC, and RRX do use the new flag values, and (2) may have their enabled/disabled status changed according to the new flag values.
// Inside an IT block, do instructions that use the carry flag (e.g., ADC) see // changes to the carry flag caused by previous instructions in the same IT block? Test1: MOV R0,1 // R0 = 1 CMP R0,R0 // C = 0, Z = 1 (EQ) ITT EQ LSRSEQ R0,R0,1 // C = 1, Z = 1 (EQ), R0 = 0 ADCEQ R0,R0,0 // R0 = R0 + C BX LR // **Returns 1 in R0** // Do flags that are changed by instruction in an IT block update which // subsequent instructions in the same IT block are enabled/disabled? Test2: MOV R0,1 // R0 = 1 CMP R0,R0 // Z = 1 (EQ) ITT EQ CMPEQ R0,0 // Z = 0 (NE) MOVEQ R0,0 // R0 = 0 ? (Disabled!) BX LR // **Returns 1 in R0**
Upvotes: 1