Home > OS >  ARM assembler instruction "ADDS Rn, #1" versus "ADDS Rd, Rn, #1"
ARM assembler instruction "ADDS Rn, #1" versus "ADDS Rd, Rn, #1"

Time:02-18

  1. ADDS Rn, #1
  2. 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

enter image description here

  • Related