2

I've got some ARM code that I'm trying to run on the Cortex M3. The majority of my code in written in Thumb, compiled from C - but for some functions I'd like to be able to run normal ARM code (as I understand it, this is possible on the M3?).

So...

Original C code and assembly:

int donothing(int a) {
  return a;
}


00000068 <donothing>:
  68:   e52db004    push    {fp}        ; (str fp, [sp, #-4]!)
  6c:   e28db000    add fp, sp, #0
  70:   e24dd00c    sub sp, sp, #12
  74:   e50b0008    str r0, [fp, #-8]
  78:   e51b3008    ldr r3, [fp, #-8]
  7c:   e1a00003    mov r0, r3
  80:   e28bd000    add sp, fp, #0
  84:   e8bd0800    ldmfd   sp!, {fp}
  88:   e12fff1e    bx  lr

Compiled using arm-none-eabi-gcc -mfloat-abi=soft -nostdinc -nostdlib

I branch to this with blx r4 - which should exchange if the base address&3 is 0, which it is.

Stepping through this in GDB, it HardFaults as soon as it gets to the line shown, even though the address contains the right data.

(gdb) p/x *0x2000934c 
$2 = 0xe52db004

The code (with BLX) works perfectly for Thumb code though...

Any idea what's going on? Thanks!

Michael Foukarakis
  • 39,737
  • 6
  • 87
  • 123
Gordon Williams
  • 1,856
  • 1
  • 17
  • 31
  • 5
    The M3 doesn't have an ARM mode. It supports the Thumb-2 instruction set, which includes some 32-bit instructions (see e.g. http://www.arm.com/files/pdf/Cortex-M3_programming_for_ARM7_developers.pdf) – Michael Apr 10 '14 at 18:46
  • That advice applies to [the whole *Cortex-M* series](http://en.wikipedia.org/wiki/ARM_Cortex-M). The particular instruction supported by each *Cortex-M* variation is given there. The are all *Thumb/Thumb2*; Ie, they execute with CPSR bit 5 is set. – artless noise Apr 10 '14 at 19:05
  • The obvious question is _why_? Thumb-2 covers all but the more esoteric corners of the ARM ISA - most ARM assembly code should convert with minimal tweaking unless you're overusing conditional execution (which would be sub-optimal even in ARM mode on modern cores). For compiled code, instruction set should be a non-issue. Admittedly the M3 is a subset of Thumb-2, but it's only really the DSP stuff that's missing. – Notlikethat Apr 10 '14 at 20:11
  • the cortex-m0 and -m1 are armv6m which has only a dozen or two thumb2 extensions, the cortex-m3 and -m4 are armv7m which has about 150 thumb2 extensions, so be careful trying to lump the two together when comparing thumb2 to arm. – old_timer Apr 10 '14 at 21:05
  • just compile for thumb -mthumb... – old_timer Apr 10 '14 at 21:07
  • why does the compiler use `add fp, sp, #0`? Is `mov fp, sp` not possible? Sorry but I don't know about ARM assembly – phuclv Apr 11 '14 at 00:40
  • first off get the arm manuals. Second I assume what happened here is that the compiler uses that instruction to create a stack frame, but in this specific case there is nothing to put there so it adds zero. If there were some local variables the operand would be something else. – old_timer Apr 11 '14 at 03:11
  • Thanks for clearing that up - I did try and find out, but I couldn't find anywhere that specifically said that ARM instructions weren't supported. For instance http://en.wikipedia.org/wiki/ARM_Cortex-M#Instruction_sets leaves me with totally the wrong impression. As some background: I write Espruino, a JavaScript interpreter for uCs. There's an interface to it that runs in the web browser and I wanted to add the ability to add inline C. I can compile TinyCC to JavaScript using Emscripten so it'd be perfect - but it only seems to produce ARM code. – Gordon Williams Apr 11 '14 at 09:09
  • *All four Cortex-M cores implement a common instruction subset that consists of: Thumb subset, Thumb-2 subset, and multiply.* from that section seems pretty clear. – artless noise Apr 11 '14 at 18:27
  • @LưuVĩnhPhúc The common ARM entry is `push {fp,...}`, where more than one register is saved; especially always `push {fp,lr}`, for non-leaf functions. He has compiled with *-O0* and no optimizations are done. The whole function would be `bx lr` with optimizations. – artless noise Apr 11 '14 at 18:34
  • @Notlikethat: Code which makes heavy use of conditional execution can work out better on ARM than Thumb2 unless a processor can keep its prefetch buffer full while processing what are effectively 48-bit instructions (ITxx followed by a 32-bit instruction). ARM's LDRB also allows address-shifting modes which aren't available on Thumb2. Those modes would be more useful if they could implicitly mask off the low bits when using LDR/LDRH, but I've written some code for a 70MHz ARM7-TDMI which has an extremely tight interpreter loop that needs to use a few bits from RAM to select an operation. – supercat Jul 27 '16 at 20:58

1 Answers1

5

Cortex-M processors do not support ARM mode instructions. They only support Thumb-2, which includes a mixture of 16 and 32-bit instructions. There is no way to run ARM instructions on a Cortex-M.

Variable Length Coder
  • 7,958
  • 2
  • 25
  • 29