ARM Thumb assembler

45 views
Skip to first unread message

da...@boddie.org.uk

unread,
Sep 28, 2021, 5:43:57 PM9/28/21
to inferno-os
While experimenting with a Cortex-M4 microcontroller, I tried to generate code using the obsolete tc compiler and tl linker in utils.

I discovered that I could pass the -t option to 5a but the linker generates standard 32-bit ARM assembly code. The linker generates Thumb code for the object code from the tc compiler. The result is a mixture of the two which doesn't work.

Did I miss an option for the assembler or linker, or is it known to be broken?

Charles Forsyth

unread,
Sep 30, 2021, 7:15:12 AM9/30/21
to da...@boddie.org.uk, inferno-os
The support is Thumb-1, and the architecture did indeed mix normal ARM and Thumb instructions. https://apt.cs.manchester.ac.uk/ftp/pub/apt/peve/PEVE05/Slides/05_Thumb.pdf talks a bit about it.
The loader does some analysis to find the boundaries and insert the interlink instructions automatically (the instructions that switch between modes, BX?).

Thumb-2 is significantly different, with enough changes and additions to make it self-supporting, so that trap handling and so on can be done without ARM32.

By the way, by accident the tl/mkfile installs as 5l , which you don't want to do, and you should check that you haven't overwritten the current 5l.
I've pushed a change to bitbucket to stop that.

--
You received this message because you are subscribed to the Google Groups "inferno-os" group.
To unsubscribe from this group and stop receiving emails from it, send an email to inferno-os+...@googlegroups.com.
To view this discussion on the web, visit https://groups.google.com/d/msgid/inferno-os/de172412-3fae-4070-96dd-00cb64991614n%40googlegroups.com.

Charles Forsyth

unread,
Sep 30, 2021, 7:45:17 AM9/30/21
to da...@boddie.org.uk, inferno-os
A bit more background. I copied the dual-mode 5l to tl about 6 years ago, and stripped the Thumb-1 support from 5l, because by then Thumb-1 had been replaced by Thumb-2,
so the extra baggage in 5l wasn't terribly useful any more. I think we had only one project that tried Thumb mode, which is why tc ta and the dual 5l existed, but it didn't really carry its weight.
The Thumb-2 processors were typically Thumb-2 only, since they didn't need ARM32 mode at all, and I'd have treated ta tc and tl as a completely new architecture, disjoint from ARM32,
and the result would have been much simpler.
But I'm afraid I had no real enthusiasm or time for actually doing it. As you've found, though, there are still Thumb-2 microcontrollers, which might make a compiler suite useful.

David Boddie

unread,
Sep 30, 2021, 8:07:47 AM9/30/21
to Charles Forsyth, inferno-os
Thanks for the information! I'll pull the change and submit a pull request
for a compiler error I found.

I'll take another look at the assembler and loader to see if I can get it
to generate Thumb instructions instead of ARM32 ones. Do you know if there
are any existing ports to Thumb hardware that show the use of Thumb code in
the assembler?
> > <https://groups.google.com/d/msgid/inferno-os/de172412-3fae-4070-96dd-00c
> > b64991614n%40googlegroups.com?utm_medium=email&utm_source=footer> .




Charles Forsyth

unread,
Sep 30, 2021, 8:41:20 AM9/30/21
to David Boddie, inferno-os
I missed one point in your earlier note. 5a can be used for both, because the loader does instruction (format) selection with the Plan 9 compilers.
The rule is that you stick to a subset of the ARM assembly that's compatible with the Thumb architecture, notably 2-operand instructions.
The .t file is actually the same format and instruction content as .5 in any case. 5l detects a Thumb function and switches its instruction selection accordingly, using Thumb encodings,
and also setting things up for the interworking code I mentioned before. tc sets the Thumb function flag automatically. You need to do it yourself when using 5a.
That's because the same .s can have a mixture of ARM and Thumb functions (eg, when doing trap handling, which on Thumb-1 traps into ARM code first and needs extra despatching code to switch).
How is that done?

TEXT allthumbs(SB), 4, $0

It's that , 4, in the TEXT directive that corresponds to the ALLTHUMBS flag in 5.out.h. That's the signal to the loader that the following function is Thumb-1.

Charles Forsyth

unread,
Sep 30, 2021, 8:43:41 AM9/30/21
to David Boddie, inferno-os
You can see the restrictions on the assembly code needed if you look at tc -S x.c compared to 5c -S x.c

I'd expect the loader to whine if you were to go out of the acceptable subset in the scope of a Thumb function.

Charles Forsyth

unread,
Sep 30, 2021, 9:38:51 AM9/30/21
to David Boddie, inferno-os
Also note that to make it easier to spot, you can do
THUMB = 4
TEXT thumbs(SB), THUMB, $0
...
TEXT another(SB), THUMB, ...

David Boddie

unread,
Sep 30, 2021, 11:30:08 AM9/30/21
to Charles Forsyth, inferno-os
Thanks for all the background and hints!

I was also passing the -a option to 5l/tl to see what the generated assembly
looked like. It was the 4 in the TEXT directive that I was missing.

My test program now builds and runs fine on the board I am using. The only
hack I'm doing at the moment involves post-processing the vector table to set
bit 0 for all the Thumb entry point addresses.

Ideally, I'd do something like this:

TEXT vectors(SB), $0
WORD $STACKTOP
WORD $reset(SB)|1
...

But that isn't valid syntax. I noticed that the assembly for some platforms
includes + or - in WORD directives, such as this from os/boot/pc/l.s:

WORD $now16real-KZERO(SB)

I haven't had a lot of success crafting an expression that parses correctly
or produces a correct entry.

At least I can proceed a bit further. Thanks again!

Charles Forsyth

unread,
Sep 30, 2021, 3:09:43 PM9/30/21
to David Boddie, inferno-os
I'm sorry I decided not to do a Thumb-2 implementation, but given that I decided that over 6 years ago and you're the first to ask directly about it since then, perhaps it was at worst a neutral decision!

Charles Forsyth

unread,
Sep 30, 2021, 3:13:15 PM9/30/21
to David Boddie, inferno-os
It was partly coloured by my view that ARM had lost its way. ARM32 was a compact implementation of a 32-bit processor with a subtle but expressive order code. Then they did Thumb-1, but because someone else (MIPS, IBM) had patented compressed code, they did a subset of some things you could do in 32-bits but encoded in 16 bits and still a 32-bit machine (registers etc). Sometime later they decided they needed a full self-supporting 32-bit architecture and forgot they already had one. I wasn't impressed.

David Boddie

unread,
Sep 30, 2021, 3:52:13 PM9/30/21
to Charles Forsyth, inferno-os
Well, I largely ignored Thumb when it first appeared.

I watched this talk recently:

A History of The ARM Microprocessor | Dave Jaggar
https://www.youtube.com/watch?v=_6sh097Dk5k

According to Wikipedia, ARM had to license patents from Hitachi, so they
didn't completely manage to swerve that danger.

Having browsed the Thumb-2 supplement, I can say that they like making lots
of different instruction encodings:

https://class.ece.iastate.edu/cpre288/resources/docs/
Thumb-2SupplementReferenceManual.pdf

I'm not sure a Thumb-2 implementation is really needed, at least for what I
want to use the compiler for. If I get to the point where I think I want to
run Inferno on this hardware - which would be a stretch - then I think I'd
start by hacking in additional instructions using macros before seeing which
instructions I'd really need.

For reference, this is the microcontroller I'm playing with:

https://www.microchip.com/en-us/product/ATSAMD51J20A

David Boddie

unread,
Feb 13, 2022, 7:34:40 PM2/13/22
to inferno-os
Bringing this thread back...

On Thursday, 30 September 2021 21:52:07 CET David Boddie wrote:

> I'm not sure a Thumb-2 implementation is really needed, at least for what I
> want to use the compiler for. If I get to the point where I think I want to
> run Inferno on this hardware - which would be a stretch - then I think I'd
> start by hacking in additional instructions using macros before seeing which
> instructions I'd really need.
>
> For reference, this is the microcontroller I'm playing with:
>
> https://www.microchip.com/en-us/product/ATSAMD51J20A

I set that one aside because I found it easier to get started with an
STM32F405 MCU, as I mentioned on the 9fans mailing list:

https://9fans.topicbox.com/groups/9fans/Ta4e584a373b05553-Me02d5cb4e136e32f9d0015d0/building-blocks-speaking-9p

It turned out that I misunderstood how some of the support functions are
supposed to work, so I had working versions of _div, _divu, _mod and _modu
for simple use cases, but I had missed that the linker generates code to
call them in a particular way. Since the MCU provides SDIV and UDIV
instructions, I moved those functions into the linker.

The other issue is to do with the implementation of _mulv which the compiler
relies on to perform multiplication of vlongs. I think I have implemented
something that works for Thumb-2, though I'm not sure how reliable it is.

I'm also concerned that I haven't set up the allocator correctly and given
processes enough stack space. It's possible that processes are overwriting
each other if their stacks overflow.

I think I'll have to dig out the Raspberry Pi Zero to verify some things.

David


Anthony Sorace

unread,
Feb 15, 2022, 1:23:51 AM2/15/22
to David Boddie, inferno-os
On Feb 13, 2022, at 16:34 , David Boddie <da...@boddie.org.uk> wrote:
>
> I set that one aside because I found it easier to get started with an
> STM32F405 MCU, as I mentioned on the 9fans mailing list:

This is great. The old thread was super encouraging for a project I'd started and had to put on the back burner before getting near as far as you have. It's based on a STM32F303CCT6, which looks like it's in the same boat thumb-wise (although I'm jealous of your memory sizes). Thanks for sharing your work here.

David Boddie

unread,
Feb 15, 2022, 6:38:26 AM2/15/22
to Anthony Sorace, inferno-os
Thanks for the encouragement. I'm currently fighting the exception model for
Thumb-2 so I've got to keep my motivation up!

The STM32F303CCT6 is similar in some ways to the MCU used on the Teensy 3.1
board I have - now a discontinued product. At some point I'll have to try
the compilers out on that.

David


Reply all
Reply to author
Forward
0 new messages