0

I'm attempting to figure out some ARM assembly for an STM32 microcontroller. When I try to assemble the instruction mov r0, #0, I get:

core.S:27: Error: cannot honor width suffix -- `mov r0,#0'

yet it works when I use movs r0, #0. Here, it says that the "s" only affects whether condition flags are updated.

I have a similar problem with add r0, r0, #1 vs adds r0, r0, #1.

Can someone please explain why movs works and mov doesn't?

Peter Cordes
  • 328,167
  • 45
  • 605
  • 847
puritii
  • 1,069
  • 1
  • 7
  • 18
  • 2
    look at the instruction set there is no mov only a movs for the base thumb instruction set. the thumb2 extensions likely have a mov without the s. – old_timer Dec 21 '20 at 02:32
  • 1
    please acquire and read the instruction set documentation before attempting assembly language. arm's documents are better than most. – old_timer Dec 21 '20 at 02:32
  • actually it is also documented in the link you provided although the arm architectural reference manual is preferred, then you use a syntax manual like this for the target assembler once you know the instruction – old_timer Dec 21 '20 at 02:34
  • @old_timer The link I have clearly says that `mov` is supported for both arm and thumb. Is it wrong? – puritii Dec 21 '20 at 02:37
  • 2
    thumb16 movs unless inside an it block – old_timer Dec 21 '20 at 02:41
  • it is better to use the more clearly defined architecture documentation than this misleading assembly language documentation. and/or when you have an issue where the tool complains and the assembly language documentation is misleading then go to the instruction set documentation. – old_timer Dec 21 '20 at 02:43
  • 1
    Look at your link where it says "The following forms of this instruction are available in Thumb code". – Nate Eldredge Dec 21 '20 at 02:44
  • stm32 is too broad as some are armv6-m some armv7-m some armv8-m some armv8.1-m and within armv8-m you have at least two variants (base and mainline?) in the field today. – old_timer Dec 21 '20 at 02:45
  • 2
    your mcu may very well support the armv7- m thumb2 extensions, but you have not told the assembler as such. – old_timer Dec 21 '20 at 02:46
  • Related: [ARM assembly cannot use immediate values and ADDS/ADCS together](https://stackoverflow.com/q/30980160) but that doesn't clearly state that `mov` doesn't exist in Thumb1 only `movs`. – Peter Cordes Dec 21 '20 at 03:21
  • 1
    Looking at the v8-A ISA references for ARM and Thumb (which I don't think changed for v8) - https://developer.arm.com/docs/ddi0597/i/base-instructions-alphabetic-order/mov-movs-immediate-move-immediate indicates that if you're using the 16-bit MOV instruction then, as @old_timer said, you have to be inside an IT block. Otherwise it's MOVS. – bouteillebleu Dec 30 '20 at 19:56

1 Answers1

2

So currently within the STM32 world you have four different instruction sets based on armv6m, armv7m and armv8m. Technically for now the armv8m baseline matches armv6m and armv8m mainline extensions matches armv7m.

So the armv6m instruction set in theory works for all cortex-ms at this time and it uses the tranditional all thumb variants (going back to armv4t's thumb instruction set) add and mov.

.cpu arm7tdmi
.thumb
.syntax unified
mov r1,#1
movs r1,#1

so.s: Assembler messages:
so.s:4: Error: cannot honor width suffix -- `mov r1,#1'

.cpu arm7tdmi
.thumb
.syntax unified
movs r1,#1
movs r1,#1

Disassembly of section .text:

00000000 <.text>:
   0:   2101        movs    r1, #1
   2:   2101        movs    r1, #1

.cpu cortex-m0
.thumb
.syntax unified
mov r1,#1
movs r1,#1

so.s: Assembler messages:
so.s:4: Error: cannot honor width suffix -- `mov r1,#1'

.cpu cortex-m3
.thumb
.syntax unified
mov r1,#1
movs r1,#1

Disassembly of section .text:

00000000 <.text>:
   0:   f04f 0101   mov.w   r1, #1
   4:   2101        movs    r1, #1

Now the ARMv7m document says this:

Encoding T1  All versions of the Thumb instruction set.
MOVS <Rd>,#<imm8>  Outside IT block.
MOV<c> <Rd>,#<imm8> Inside IT block.

armv6m does not have the it instruction so this is a touch misleading, the movs encoding is supported by all thumb variants, but not the other.

.cpu cortex-m3
.thumb
.syntax unified

itt ne
movne r1,#1
mov r1,#2
mov r1,#3

so.s: Assembler messages:
so.s:7: Error: instruction not allowed in IT block -- `mov r1,#2'

so you cannot use it there either.

.cpu cortex-m3
.thumb
.syntax unified

itt ne
movne r1,#1
movsne r1,#2
mov r1,#3

Disassembly of section .text:

00000000 <.text>:
   0:   bf1c        itt ne
   2:   2101        movne   r1, #1
   4:   f05f 0102   movsne.w    r1, #2
   8:   f04f 0103   mov.w   r1, #3

The short answer is that you cannot because the instruction does not exist. If you are using unified syntax documentation that glosses over which instruction sets are supported, then you have, as many others, fallen into the trap of the major failing of the unified syntax. A pretty serious oops, on ARM's part. Just have instruction sets like every one else, done.

stm32 is too broad you have cortex-m0, m0+, m3, m4, m7, and flavors of m8. m0 and m0+ and some m8's are basically armv6m and this instruction is not supported in any way. The m3,m4,m7 and some m8's it is as a thumb2 extension or with a condition specification within an it block.

With the unified syntax and thumb it is best to add the s unless you definitely do not want it then hope for the best.

If you are using the original gnu assembler thumb syntax, then, thanks to I assume a combination of ARM's documentation (at that time) and the gnu folks, you can't have the s (for some instructions)

.arch armv5t
.thumb
mov r1,#3
movs r1,#3
add r1,r2,r3
adds r1,r2,r3

so.s: Assembler messages:
so.s:6: Error: instruction not supported in Thumb16 mode -- `adds r1,r2,r3'
.arch armv5t
.thumb
.syntax unified
mov r1,#3
movs r1,#3
add r1,r2,r3
adds r1,r2,r3

so.s: Assembler messages:
so.s:4: Error: cannot honor width suffix -- `mov r1,#3'
so.s:6: Error: cannot honor width suffix -- `add r1,r2,r3'

And last but not least, assembly language (the syntax) is specific to the tool (the assembler) not the target (arm/thumb). So all of the above is gnu assembler for many of the versions that support various flavors of the thumb instruction sets. You can look at armasm (tool from ARM not GNU) as well as perhaps others, and their rules may vary. So within armasm it may very well be proper syntax as the mov r1,#1 shown in these last examples

.arch armv5t
.thumb
mov r1,#3
movs r1,#3
add r1,r2,r3

Disassembly of section .text:

00000000 <.text>:
   0:   2103        movs    r1, #3
   2:   2103        movs    r1, #3
   4:   18d1        adds    r1, r2, r3

indicates. (also note the disassembler folks and assembler folks disagree as well, I do not have a binutils from the pre-unified-syntax era to see what it showed).

ARM's documentation is going to be either specific to no tool as the authors of the architecture are different than the tool creator/maintainers. Or they may attempt to get along and have the architecture documents match their internal tools. But that in no way means gnu has to conform and sadly people that port targets to gnu assembler seem to have a habit of not supporting the processor vendors syntax completely, there is often a painful or annoying twist.

(How you read that ARM ARM, you could have used the s option as it shows the arm equivalent, with the s option, the defined syntax in the doc did not show that so depending on the assembler author, they had to pick one or make up some syntax).

halfer
  • 19,824
  • 17
  • 99
  • 186
old_timer
  • 69,149
  • 8
  • 89
  • 168