ADDS Rn, #1
ADDS Rd, Rn, #1
The ARM documentation specifies that in the first instruction if the Rd is optional and if ommitted Rd equals Rn. So both instructions should be the same when compiled. But our compiler is generating:
binary 0x3F01 for SUBS R7,#1
and
binary 0x1E7F for SUBS R7,R7,#1
using the instruction decoding 0x3F01 equals to 001 11 111 00000001 001
001 -> add/substract/compare/move immediate
11 -> opcode is substract imm
111 -> R7
00000001 -> value 1
using the instruction decoding
0x1E7F equals 000111 1 001 111 111
000111 -> add/substract register
1 -> substract immediate
001 -> value 1
111 -> R7
111 -> R7
So both instructions are performing the same action. Any idea why the the compiler might generate different binary?
CodePudding user response:
The ARM documentation specifies that in the first instruction if the Rd is optional and if ommitted Rd equals Rn. So both instructions should be the same when compiled.
First of all, you should note that there are two different ARM instruction sets: The "traditional" 32-bit instruction set and the "Thumb" instruction set.
Your CPU obviously uses the "Thumb" instruction set.
Many statements about the ARM instruction set refer to the "traditional" one.
In the traditional instruction set, both forms (SUBS R7, #1
and SUBS R7, R7, #1
) indeed result in the same instruction: 0xE2577001.
However, in the "Thumb" instruction set, there are two different encodings:
SUBS Rd, Rn, #imm
allowing two different registers to be specified for Rd
and Rn
but only allowing an immediate value in the range 0...7.
SUBS Rd, #imm
only allowing the one-register form but allowing an immediate value in the range 0...255.
However, SUBS R7, R7, #1
and SUBS R7, #1
do the same.
Any idea why the the compiler might generate different binary?
If you explicitly type SUBS R7, R7, #1
or SUBS R7, #1
in assembly code?
Because you might also type SUBS R7, R6, #1
or SUBS R7, #90
. In these cases, the compiler must handle both variants differently!
So it always handles these two variants differently because it would make more effort to check if both registers are equal or to check if the immediate value is smaller than 8.
CodePudding user response:
I found how the compiler generated the 3F01
and 1E7F
binaries.
.thumb generated 3F01
while .thumb2
generated 1E7F