This guide describes the problems regarding making software for older versions of RISC OS work on new (current) systems, such as the Beagle board, RaspberryPi, Panda board, etc.
While RISC OS itself is largely the same at the API level, the underlying hardware is fundamentally different.
If you are new to programming the ARM, I do not recommend this guide as it will make numerous references to “old” and “new” methods. No production ARM offers the older 26 bit modes, and it’s probably been a decade since any did. Please don’t waste your time learning any of this unless you have a specific need of this information.
If you recall, RISC OS originally ran on the ARM 2 and ARM 3 processors in such advanced (for their time) machines as the A310, A440, A3000, and the A5000. In those days, the machine had a 26 bit address bus permitting a maximum of 64MB to be addressed. Because of this, various processor “flags” (the current operating mode, the result of the least mathematical calculation, etc) were incorporated into the “Program Counter” that pointed to the address of the instruction being executed.
This describes the behaviour of all versions of RISC OS prior to RISC OS 5.
In this day and age, modern System-on-Chip (SoC) boards are likely to come with at least 256MB on board, and the more your board costs, the more it is likely to offer, up to Gigabyte sizes.
This necessitated a change in how the ARM addresses memory and holds status. R15, or PC, is now a full 32 bit pointer and the Processor Status Register (for the status and operating mode) is now a new special register. The differences are explained in more detail here
To put it bluntly, unless your programs are written in BASIC, your old code will not work (at least, not natively – you can run many old programs using Aemulor. You can read what Aemulor does and visit the Aemulor site).
Due to the changes between older systems and modern ones, there are a number of issues that may affect your program:
If your program is written in BASIC, with no assembly language code contained within, then you do not need to do anything special once you have made modifications as necessary for the issues described above.
The official development suite contains an updated 32 bit safe version of the ABC compiler. So long as your program does not contain embedded assembler code, once you have resolved the issues mentioned above, it should suffice to rebuild your program from source using the latest version of the compiler.
Most software for RISC OS is written in C due to its speed, flexibility, and greater ease of maintenance than other languages available.
If your program is written in pure C, once you have resolved the issues mentioned above, all you will then need to do is to rebuild your project using the latest official development suite or GCC if you originally used that.
If you are using libraries that are not the standard libraries provided with the compiler, you will need to replace your older libraries with newer, compatible, versions. In order to help you:
Assembly language is the most complicated as it needs to be modified by hand and due to the earlier API’s requirement that flags be preserved, there are likely to be a lot of places where minor modification is necessary.
The first thing you must do is to pick up a copy of The ARM Club’s ARMalyser. This tool is invaluable in helping to detect parts of code that need changing.
Continue reading…
The first main problem, and the complete show-stopper, is that the Processor Status Register (PSR) and the Program Counter (PC) are no longer combined. As a result of this, anything that tries to manipulate the PSR by performing operations on PC will fail. An example is returning from an instruction with the V set using ORRS PC, LR, #(1 << 28)
.
You should note that the following instructions will no longer work as expected:
MOVS PC
TEQP
LDM ^
TST xx, PC
The second problem that affects modern processors is the behaviour of unaligned loads – that is to say, executing an LDR
instruction on an address that is not word aligned.
This issue has always been contentious, and it can be roughly summarised as follows:
LDM
, STM
, and STR
would ignore bits 0 and 1 and access a word aligned addressLDR
would load from a word aligned address and rotate in a complex mannerLDM
and STM
will always abort.LDR
and STR
will perform sequential memory accesses to read or write a word at a non-aligned addressThe ARMv7 compatibility primer describes the behaviour of non-aligned loads and stores in more detail.
It is worth mentioning that if you are using LDR
to read data byte by byte, you should be using LDRB
instead.
The legitimate way of detecting a 32 bit system is to called the SWI OS_PlatformFeatures, which will return various flags that indicate the features of the current system. You are particularly interested in bit 6 which means that it is a 32 bit version of RISC OS, and bit 7 which means the processor does not support the older 26 bit mode.
In assembler, the following code can be used to detect a 32 bit mode:
TEQ R0, R0 ; Set Z flag TEQ PC, PC ; Set Z flag if in 32 bit mode
This works because the second operand to TEQ will include the flags in 26-bit mode, but not in 32-bit mode, whereas the first operand never includes the flags. We are therefore comparing PC with PC+PSR if in 26-bit mode, but comparing PC with PC in 32-bit mode. This will set Z in 32-bit mode but not in 26-bit mode since we know at least one bit (the Z flag) is set in the PSR. Note that the first instruction can be omitted if a flag is known to be set (eg the V flag) or if not in user mode (since one of the mode flag bits will be set).
If in SVC mode (a relocatable module), you could also use the instruction:
CMP PC, PC
This replies EQual on a 32 bit system, and NotEqual on a 26 bit system, for the same reasons as above (comparing PC with PC+PSR and a mode bit is set; so will differ on a 26 bit system, but will be identical on a 32 bit system as the mode bit is stored elsewhere).
Work in progress – more to come.