This repository contains some build tools for RISC OS 64bit binaries.
There are multiple directories within this repositories that contain binaries:
clib
contains the C library. This must be built first.absolutes
contains absolute files (AIF).modules
contains module files.utilities
contains utilities.
To build these on a POSIX system you will require Docker for the cross compiler.
The C library can be built with:
make
The C library is limited in functionality, but provides sufficient implementation for simple tools to be ported. Additional functions can be added as necessary. The library is usable with both absolutes and modules.
The absolute test files can be built with:
make all
Individual files can be built with:
make TARGET=<filename>
The binaries will be produced as ,ff8
suffixed files. There is also a .map
suffixed file, which contains a description of where the content lives within
the file.
The module test files can be built with:
make all
Individual files can be built with:
make TARGET=<filename>
The binaries will be produced as ,ffa
suffixed files. Again a .map
file is
present.
Sample utility files can be built with:
make all
Individual files can be built with:
make TARGET=<filename>
The binaries will be produced as ,ffc
suffixed files. Again a .map
file is
present.
The 64bit AIF format has been defined as follows:
Offset | Value | Instructions | Meaning |
---|---|---|---|
&000 | &e1a00000 | ARM32: NOP |
ARM32 decompression |
&004 | &e1a00000 | ARM32: NOP |
ARM32 reloc |
&008 | &e1a00000 | ARM32: NOP |
ARM32 zero init |
&00C | &eb00000b | ARM32: BL entry |
ARM32 image entry |
&010 | &ef000011 | ARM32: SWI OS_Exit |
explicit OS_Exit |
&014 | variable | code + static data size | read only size |
&018 | variable | R/W data size | read write size |
&01C | &0 | - | debug size |
&020 | variable | zero init size | zero init size |
&024 | &0 | - | debug type |
&028 | &8000 | - | linked base address |
&02C | &0 | - | workspace size (obsolete) |
&030 | &40 | - | address mode |
&034 | &0 | - | data base address |
&038 | &0 | - | reserved |
&03c | &0 | - | reserved |
&040 | &e28f0000 | ARM32: entry: ADR r0, error_block |
ARM32 error report |
&044 | &ef00002b | ARM32: SWI OS_GenerateError |
|
&048 | &0 | ARM32: error_block: DCD 0 |
|
&04c | string | ARM32: = "AArch64 binaries cannot be run on 32bit RISC OS", 0 |
|
&07c | &0 | ARM32: DCD 0 |
|
... | |||
&100 | &D503201F | ARM64: NOP |
AArch64 decompression |
&104 | &94000004 | ARM64: BL zeroinit |
AArch64 zero init |
&108 | &9400001F | ARM64: BL entry |
AArch64 entry point |
This follows the pattern defined in https://riscos.com/support/developers/riscos6/programmer/codeformats.html for Absolute files, with '64' in place of the bitness.
The 64bit module format is only slightly varied from that defined previously, following the definition in https://pyromaniac.riscos.online/pyromaniac/prm/kernel/modules/modules-supplement.html.
From the standard 32bit module, there are the following differences:
- The initialisation offset has bit 30 set. This indicates that the module is not ARM. The architecture is defined within the feature flags.
- The feature flags bits 4-7 contains the architecture type:
- 0 = AArch32
- 1 = AArch64
- 2 = x86 64bit
- 15 = Python
- The feature flags bit 2 indicates that a zero-initialisation size is present following the feature flags.
- The module will have its zero-initialisation area initialised to 0.
- The module will always be allocated on a page boundary plus 4. That is, the base address of the module in hex will always end in
004
. This allows the standard mechanism for referencing addresses using theADRP
instruction to be used. - Modules will never be multiply instantiated.
- All module entry points follow the pattern of the CMHG entry points, rather than the original register assignments, with the exception of R12 which remains in x12.
- The initialisation entry point:
x0
-> start stringx1
= instance number (always 0)x12
= private word pointer
- The finalisation entry point:
x12
= private word pointer
- The SWI entry point:
x0
= SWI offsetx1
-> register block (x0-x9 on entry)x12
= private word pointer
- The command entry point:
x0
-> argument stringx1
= count of argumentsx2
= command numberx12
= private word pointer
- The initialisation entry point:
- All module entry points which can return an error pointer, must return the error pointer in R0, or 0. The V flag need not be set. This follows the pattern of CMHG entry points.
- All interfaces are assumed to use the frame pointer for a call chain, and should not 0 this value on entry.
Utilities, like AIF files, have an ARM 32bit header. This follows the standard utility file format defined at https://riscos.com/support/developers/riscos6/programmer/codeformats.html
The format has been extended, thus:
Offset | Value | Instructions | Meaning |
---|---|---|---|
&000 | &ea000005 | ARM32: B &1C |
ARM32 entry |
&004 | &79766748 | - | magic 1 |
&008 | &216c6776 | - | magic 2 |
&00c | variable | code + static size | Read-only size |
&010 | variable | R/W data size | Read-write size |
&014 | &00000040 | Bitness + flags | |
&018 | variable | offset of ARM64 entry | |
&01c | &e28f0004 | ARM32: ADR r0, &24 |
ARM32 error report |
&020 | &e3500102 | ARM32: CMP r0, #&80000000 |
|
&024 | &e1a0f00e | ARM32: MOV pc, lr |
|
&028 | &00000000 | ARM32: error number | |
&02c | &63724141 | ARM32: = "AArch64 binaries cannot be run on 32bit RISC OS" ,0 |
The utility file will be entered at the offset given at offset &18.
Future versions of this specification may require that the utility be loaded at a page boundary plus 4 bytes, as modules are.