32-bit compatibility overview
=============================

Document version 0.12, 23 January 2003


Overview
--------
RISC OS was originally designed for the ARM 2 and ARM 3 processors, which had
a 26-bit address bus and a combined 24-bit program counter + 8-bit status
flags in register R15.

The ARM 6 expanded the address bus and program counter to 32 bits and moved
the status flags to a separate register, but included backwards-compatible
26-bit modes to allow ARM 2 and ARM 3 user programs to run unmodified. The
latest ARM processors have removed these 26-bit compatibility modes in
favour of the new 16-bit "Thumb" architecture. As a result, versions of RISC
OS for new processors such as the ARM 9, 10 and XScale will be 32-bit only,
using only 32-bit modes.

In the past RISC OS has used only 26-bit modes for backwards compatibility
(with the exception of FIQ handlers and, in RISC OS 4, the FPEmulator).
Indeed, current versions of RISC OS do not support operation in 32-bit modes
for general applications or modules.

As a result, most RISC OS software was originally designed to run in a
26-bit mode, and needs updating to work on a 32-bit system. The components
included here will allow programs to be built so they run on any system from
an ARM2 Archimedes to an Intel 80200-based platform. This is achieved by
creating 26/32-bit neutral code that performs the same when running in either
a 26-bit or 32-bit mode.

Undocumented OS interfaces
--------------------------
We reiterate here the standard warning about reliance on undocumented OS
interfaces and accesses to private OS workspace. If such things are
attempted, no amount of 32-bit mode compatibility will allow you to run on
new hardware.

In particular, 32-bit RISC OS has a radically different memory map, so
hard-coded knowledge of addresses should be avoided, apart from application
space starting at &8000.

The locations of any areas such as the RMA and screen memory should be read
using the provided system calls. The expectation is that a 32-bit RISC OS
will allow (virtually) unlimited application slot size. This mandates that
all the system workspace currently in the region 01C00000-06000000 will move.

Also bear in mind that modern RISC OS computers are unlikely to use IOMD/VIDC
compatible peripherals. Use OS calls rather than attempting direct hardware
access.

Device drivers are unlikely to work on new hardware. However, the more
abstraction steps you can take, the more chance you have. For example,
Podule_ReadInfo will tell you which interrupt device to claim for your
podule, and will give you addresses of interrupt mask registers. R3 on entry
to IRQ routines contains a pointer to the I/O controller - use it and
although your code may not work on a non IOMD-compatible system, it will
stand a better chance of working on an IOMD-compatible system with a
different memory map.

Other warnings
--------------
In the past it has been common to store flags at the top or bottom of
pointers. This is likely to cause problems on 32-bit systems. In particular,
a revised memory map will lead to many things being much higher in memory.
Also, function pointers may have bits 0 and 1 set if Thumb is in use.

All existing ARM warnings in the PRM and Acorn Assembler manuals hold true -
it is more likely than ever that deprecated sequences will fail to work.
For example, all NV condition instructions are now either UNDEFINED or
have new functions in architecture 5 (as implemented in the ARM10 and
XScale).

Also ARM architecture 5 introduces new behaviour - a load from memory
of the PC will cause the processor to automatically switch to Thumb mode
if bit(0) of the loaded value is set. Beware.

BASIC programs
--------------
Pure BASIC programs should work unmodified on a 32-bit RISC OS, subject to
the warnings above.

C programs
----------
Pure C applications and modules should work unmodified on a 32-bit RISC OS,
following recompilation using the components provided here. Once recompiled,
these programs will require the Shared C Library provided here to operate on
existing versions of RISC OS.

To compile 32-bit programs:

 1) Install the new tools and libraries provided here.

 2) Build your program.

 3) Ensure that no attribute conflict warnings are produced by the linker
    (as will occur if you are mixing APCS-R and APCS-32 code/libraries).

 4) Ensure that the necessary software components are available in your
    program's !Run file as follows:
    
        RMEnsure UtilityModule 3.10 Error This application requires RISC OS 3.10 or later
        RMEnsure UtilityModule 5.00 RMEnsure CallASWI 0.03 RMLoad System:Modules.CallASWI
        RMEnsure UtilityModule 5.00 RMEnsure CallASWI 0.03 Error This application requires CallASWI 0.03 or later
        RMEnsure FPEmulator 4.03 RMLoad System:Modules.FPEmulator
        RMEnsure FPEmulator 4.03 Error This application requires FPEmulator 4.03 or later
        RMEnsure SharedCLibrary 5.17 RMLoad System:Modules.CLib
        RMEnsure SharedCLibrary 5.34 Error This application requires SharedCLibrary 5.34 or later

Note that you should always specify 5.17 (the first 32-bit version)
as the version of the Shared C Library required in the first RMEnsure -
this will avoid the potentially fatal possibility of killing a RAM
version that is currently in use (killing the ROM version is safe).
The second RMEnsure asks for 5.34, as that is the first non-beta
version. If you do require a newer version, only change the second
RMEnsure.

The components provided within the enclosed !System application, together
with the !SysMerge obey file, may be freely distributed with your RISC OS
software.

Care should be taken if you are building a C module that is potentially
shared by a number of programs - if your program installs a newer, 32-bit
version of this shared module in a central location, existing programs may
load the module without RMEnsuring the appropriate C library etc, causing
problems if those programs are loaded first. This can be dealt with by
installing the latest version of !System, which ensures the minimum
components (as above) that are needed to run 32-bit programs are loaded when
it is first seen.

Assembler programs
------------------
Hand-coded assembler programs, or subcomponents of programs should be written
to be 26/32-bit neutral. For simple APCS fragments, this is straightforward.

For routines that need to manipulate the PSR or provide RISC OS module entry
points, it is more complicated. The amount of complexity can be reduced by
dropping RISC OS 3.1 compatibility, hence allowing the assumption that
MRS/MSR instructions are available. More technical details of RISC OS APIs
and 26/32-bit techniques are provided in the accompanying documents.

If you are writing much ARM code, obtain a copy of the latest ARM
Architecture Reference Manual, commonly referred to as the ARM ARM.
This is available as a printed book and also in PDF format free of charge
from ARM upon request (ARM document number DDI-0100).

APCS-32
-------
The new APCS variant for RISC OS is called "APCS-32"; it is the same as
APCS-R, except that it is 32-bit PC, and LFM/SFM are used. Note that APCS-32
adds 2 extra provisos over basic APCS-3:

APCS-32 code must work when called in a 26-bit mode. This precludes
constructs like:
     
            ADD     a1, a1, pc     ; may or may not add PSR flags
     
APCS-32 code must be able to call APCS-26 code (but not vice-versa).
This requires that lr must contain the PSR flags on entry to all
functions if the code is running in a 26-bit mode. So the following
is illegal:
     
            ADR     lr, return     ; doesn't include PSR flags
            MOV     pc, r2
     return
     
The following is legal:
     
            MOV     lr, pc         ; includes PSR flags in 26-bit mode
            MOV     pc, r2

APCS-32 is transitional. It is likely that a move to a form of the new
ATPCS will occur in the future. In that event, a new ATPCS C library would
operate alongside the APCS-32 library to allow both old and new applications
to work together.

How to be 26/32-bit neutral
---------------------------
Be aware that your program may be running in either 26 or 32-bit modes. As an
application, you may be running in USR26 or USR32. As a module, you may be in
SVC26 or SVC32. As a TickerV claimant you may be in IRQ26 or IRQ32. Write
your code accordingly. Do not use <dop>S PC,... or LDM {...,PC}^ instructions
except where documented as legal for 32-bit code.

It is often easiest to change function calls to not preserve the PSR. If
PSR preservation is required, it can be done explicitly with MRS/MSR.

Use MRS and MSR instead of TEQP etc - these calls work perfectly well on the
ARM 6 or later in either 26 or 32-bit modes. If RISC OS 3.1 compatibility is
required, check the current processor mode and dynamically choose whether to
use TEQP or MSR. Alternatively, use processor-independent instructions like
CMP PC,#0 to clear the Z flag. Avoid instructions like CMP PC,#&80000000 to
set the V flag -  the program counter may be above &80000000.

Another possibility is to use macros controlled by build switches then
produce separate RISC OS 3.1 and 3.5+ versions of your modules. This is the
technique used by the FPEmulator module (although its 26/32-bit issues are
more complex than most).

Be aware of the differences in behaviour on a 32-bit system. In particular,
SWIs will no longer be expected to preserve flags as stated on PRM 1-29;
indeed, they usually cannot. Flags may still be set to report results.

Avoid code sequences that have a different effect in 26 and 32-bit modes.
For example:
             
Don't use:
           ADD   R0,R0,R15        ; includes PSR in R15 on a 26-bit system
Use:
           ADD   R0,R15,R0        ; never includes PSR
Don't use:
           BIC   R0,LR,#&FC000003 ; to find address of caller
Use:
           SUB   R0,LR,PC         ; R0 = LR - PC {- PSR}
           ADD   R0,PC,R0         ; R0 = LR {- PSR} + 4
           SUB   R0,R0,#4         ; R0 = LR {- PSR}
or:
           RSB   R0,PC,PC         ; R0 = PC {+ PSR} - PC = {PSR} 
           SUB   R0,LR,R0         ; R0 = LR {- PSR}

In both of the last two cases, the assumption is that the PSR has not been
altered since function entry.

More technical information is provided in the accompanying document.

The Shared C Library
--------------------
The Shared C Library module supplied here is suitable for RISC OS 3.10 or
later. It requires FPEmulator 4.03 or later (to support the LFM and SFM
instructions) and it also requires the CallASWI module on RISC OS 3.60 or
earlier.

The C library supports the new APCS-32 calling standard, together with the
existing APCS-R. It no longer supports APCS-A.

On a 32-bit RISC OS APCS-R will no longer be supported, unless via some
form of 26-bit emulation software.

CallASWI
--------
CallASWI 0.03 is an update to the CallASWI module provided with RISC OS 3.70;
it ensures correct operation following a soft reset - particularly critical
when the Shared C Library is relying on it.

FPEmulator
----------
Version 4.19 of the Floating Point Emulator / FPA Support Code is provided
here, in three forms to match different versions of RISC OS. Version 4.03 or
later is required to support the LFM and SFM instructions used by the Shared
C Library, and expected to be used by APCS-32 programs. An appropriate
version is present in RISC OS 3.5 or later, but will need to be soft-loaded
for RISC OS 3.1.

The FPPC hardware floating point system is no longer supported.

ANSILib
-------
The ANSILib library supplied here is suitable for RISC OS 3.50 or later. It
is provided for debug purposes only - linking it with released applications
is liable to impact future compatibility.

CMHG
----
The version of CMHG supplied here will create APCS-32 module headers that are
compatible with RISC OS 3.1 onwards, and will support 32-bit processors; it
will set the "32-bit compatible" module header flag - it is up to you to
ensure any assembler linked in to the module is 32-bit compatible.
