ARM assembly cannot use immediate values and ADDS/ADCS together
Asked Answered
C

3

11

I am currently trying to speed up some of my C functions on a Cortex-M0 (Freescale KL25Z) using assembly. I get a problem with this minimal test program:

@.syntax unified
.cpu cortex-m0
.text
  .global test
  .code 16
test:
  mov r0, #0
  adds r0, r0, #1
  bx lr

When I try to assemble my .s file to a .o file, I get this error

$ arm-none-eabi-as test.s -o test.o
test.s: Assembler messages:
test.s:8: Error: instruction not supported in Thumb16 mode -- `adds r0,r0,#1'

The error message doesn't make sense to me, ADDS is a valid instruction acording to this document. I found a possible answer on stackoverflow and added the line at the beginning of the program (".syntax unified" worked, like the second answer suggested). This resulted in fixing this problem, I can now use instructions like ADDS and ADCS, but I did get a new error:

$ arm-none-eabi-as test.s -o test.o
test.s: Assembler messages:
test.s:7: Error: cannot honor width suffix -- `mov r0,#0'

Some instructions using immediate values get this error. I am compiling on Mac OS 10.9.5. I can't find a solution to this via Google or Stackoverflow and have no idea how to get around these errors.

$ arm-none-eabi-gcc --version
arm-none-eabi-gcc (GNU Tools for ARM Embedded Processors) 4.9.3 20150303 (release) [ARM/embedded-4_9-branch revision 221220]
Copyright (C) 2014 Free Software Foundation, Inc.
This is free software; see the source for copying conditions.  There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.

$ arm-none-eabi-as --version
GNU assembler (GNU Tools for ARM Embedded Processors) 2.24.0.20150304
Copyright 2013 Free Software Foundation, Inc.
This program is free software; you may redistribute it under the terms of
the GNU General Public License version 3 or later.
This program has absolutely no warranty.
This assembler was configured for a target of `arm-none-eabi'.
Clichy answered 22/6, 2015 at 12:35 Comment(1)
gnu assembler is particularly annoying in this respect. when disassembling thumb it will show an adds for example, but when you code with adds it complains, since thumb (not thumb2 extensions this is a cortex-m0 anyway) doesnt have a choice anyway, you cant get it wrong. now then syntax unified and thumb2 get in the way and make it hard to get the right instruction, I am still resisting the transition but you should at least try the unified syntax and see if you can get the right encoding.Curiel
D
4

Somewhat ironically, by using UAL syntax to solve the first problem you've now hit pretty much the same thing, but the other way round and with a rather more cryptic symptom.

The only Thumb encodings for (non-flag-setting) mov with an immediate operand are 32-bit ones, however Cortex-M0 doesn't support those, so the assembler ends up choking on its own constraints. In UAL you have to explicitly use movs to get the only "move immediate" instruction Cortex-M0 actually has.

Deduct answered 22/6, 2015 at 13:6 Comment(0)
C
6

what Jester said:

.cpu cortex-m0
.text
  .thumb

  .thumb_func
  .global test
test:
  mov r0, #0
  add r0, r0, #1
  bx lr

which gives

   0:   2000        movs    r0, #0
   2:   3001        adds    r0, #1
   4:   4770        bx  lr

or if you go with syntax unified then you have to put the s on there

.syntax unified
.cpu cortex-m0
.text
  .thumb

  .thumb_func
  .global test
test:
  movs r0, #0
  adds r0, r0, #1
  bx lr

which also gives

00000000 <test>:
   0:   2000        movs    r0, #0
   2:   3001        adds    r0, #1
   4:   4770        bx  lr
Curiel answered 22/6, 2015 at 13:23 Comment(1)
I'm reassembling disassembled code, .syntax unified did what I wanted.Palenque
D
4

Somewhat ironically, by using UAL syntax to solve the first problem you've now hit pretty much the same thing, but the other way round and with a rather more cryptic symptom.

The only Thumb encodings for (non-flag-setting) mov with an immediate operand are 32-bit ones, however Cortex-M0 doesn't support those, so the assembler ends up choking on its own constraints. In UAL you have to explicitly use movs to get the only "move immediate" instruction Cortex-M0 actually has.

Deduct answered 22/6, 2015 at 13:6 Comment(0)
G
1

In thumb mode, you can not use adds, you only have add. As such, the correct code is:

.cpu cortex-m0
.text
  .global test
  .code 16
test:
  mov r0, #0
  add r0, r0, #1
  bx lr
Gylys answered 22/6, 2015 at 12:47 Comment(2)
Add-immediate is only available as ADDS, add-register is only available as ADD, for Cortex-M0 at leastProspector
Oh, but in divided syntax for thumb mode, apparently the assembler requires you to call it add even though it does update flags, and the ARM manual I linked 4 years ago does call it adds. I just checked and current arm-none-eabi-as arm-thumb.s does error on adds r0,r0,#1 or adds r0,#1, but accepts them as add.Prospector

© 2022 - 2024 — McMap. All rights reserved.