Showing changes from revision #10 to #11:
Added | Removed | Changed
Warning: The current and/or previous revision contained markup errors which prevented proper diff analysis. A guess at markup correction has been made but the diff may not be a truly accurate reflection of the real changes.
There is currently a bias towards using the older FPA instruction set for floating point operations ostensiby ostensibly because the majority ofRISC OS systems were based around the ARM7500FE or lacked floating point hardware entirely – and in that situation a floating point emulator was a good way to have code be able to run in either scenario.
Since ARM11 the scales have tipped the other way as these cores implement one variant or another of the VFP hardware macrocell, Arm’s replacement for the FPA. Ignoring VFPv1, since RISC OS never ran on any of the chips and version 1 has since been obsoleted, this means VFPv2 or VFPv3 or VFPv4.
This proposal looks at how to better integrate hardware floating point support within RISC OS, primarily for those clients of the Shared C Library, but also setting out examples by which hardware floating point support can be detected so that when multiple variants are supplied the correct one is run.
IHI0042 – Procedure Call Standard for the Arm 32-bit Architecture
DUI0041 – ARM Object Format (AOF)
VFP implementations of transcendental functions and decimal conversion
BASICVFP
Taking FP seriously
FP support
VFP context switching
FPA is the original Floating Point Accelerator, coprocessor numbers 1 & 2 for the ARM.
VFP is the Vector Floating Point unit, coprocessor numbers 10 & 11 for the ARM.
The APCS is the ARM Procedure Calling Standard, treated as a synonym here for ATPCS (for ARM/Thumb PCS), and AAPCS (for ARM Architecture PCS).
An ABI defines an Application Binary Interface, comprising a base ABI for the core-registers only and basis for several variants.
The original APCS had 4 independent choices, leading to a potential of 16 combinations
Of those 16 combinations the two most commonly encountered on RISC OS are
Name | PC | Stack checking | FP arguments | Reentrancy | Equivalent tool setting |
---|---|---|---|---|---|
APCS-R | 26b | Explicit, register SL | In integer registers | Not reentrant | -apcs 3/26/swst/nofpregargs/nonreent |
APCS-32 | 32b | Explicit, register SL | In integer registers | Not reentrant | -apcs 3/32/swst/nofpregargs/nonreent |
APCS-U and APCS-M were never used on RISC OS, and APCS-A support was withdrawn in SharedCLibrary 5.06.
In the context of this proposal the only one to review is the choice of passing FP arguments in integer registers is a compromise
Code which was built to use VFP, and thus follows the new APCS-VFP, will need to call a new library initialisation SWI during startup. One SWI for application clients and one for module clients (cf. SharedCLibrary_LibInitAPCS_32 and SharedCLibrary_LibInitModuleAPCS_32). If the SharedCLibrary is too old the unknown SWI error returned will prevent the application or module from starting.
The C library runtime will create a VFP context, since there isn’t a global context as for FPA, and destroy it on library close down if the application or module quits along with file handles and the other usual exit clear up.
Code which doesn’t use the Shared C Library is responsible for managing its own context. For example BASIC compiled using the ABC compiler uses its own ABCLibrary support module and uses VFPSupport directly to manage contexts.
A number of the C functions from
For ease of maintenance moving the floating point library code out of cl_body.s would be worthwhile. They will each need an equivalent implementation in VFP, or some of the more obscure functions could be veneered by swapping the word order from VFP to FPA and calling the existing proven code.
Variadic functions such as printf() receive all their arguments in integer registers. This causes an issue for floating point values which are always widened to doubles, since doubles for an FPA client have the word order reversed compared with VFP. By the time the variadic function is called the type information which was to hand at the compiling stage has been lost so this will either require two copies of the variadic functions, or some abstraction at the point va_arg() is used to retrieve a double.
Some later variants of the VFP macrocell don’t raise an abort for invalid operations such as the square root of a negative number. The compiler may opt to insert checks of the FPSCR after certain operations or on return from a function for example in order to prevent invalid results from silently being propagated. This will need support functions in the Shared C Library to report them to the signal handler in the C environment, so that they may be handled in a controlled manner.
Selecting an environment using !Builder runs the corresponding ToolOptions for the selected APCS to alias the CC and ObjAsm commands.
Besides CC and ObjAsm the CMHG, resgen, and DefMod commands will need updating to ensure they at least set the VFP area flag in the object file. They don’t output floating point instructions themselves of course, but without the matching area flag many link time warnings will be produced when trying to mix object files with conflicting FP calling standards.
The target for a complete operating system ROM is known and fixed, therefore for a ROM build a specific combination of CPU, FPU, and APCS can be selected to take full advantage of the instruction set available.
For example a Cortex-A15 based system is new enough to have VFPv4 and uses the ARMv7 opcodes, its memory system permits halfword loads and stores but forbids unaligned loads, so the APCS settings might look like:
CC -apcs 3/32bit/fpregargs/vfp -cpu 7 -fpu VFPv4 -memaccess +L22+S22-L41
ObjAsm -apcs 3/32bit/fpregargs/vfp -cpu 7 --fpu VFPv4
Assuming the other options take their default values.
Any disc based component will need to adopt the lowest common denominator settings for any processor supported by RISC OS which also runs VFP opcodes, potentially under emulation. If support for FPA is also required, the source code will need to be compiled/assembled twice and two binaries produced.
That would mean disc based components could only assume VFPv2 and continue to target a generic ARMv3, its memory system forbids halfword loads and stores and unaligned loads, so the APCS settings might look like:
CC -apcs 3/32bit/fpregargs/vfp -arch 3 -fpu VFPv2 -memaccess -L22-S22-L41
ObjAsm -apcs 3/32bit/fpregargs/vfp -arch 3 --fpu VFPv2
Assuming the other options take their default values.
On platforms which predate the VFP coprocessor an attempt to execute VFP instructions causes an undefined instruction abort. This could be used to trap attempts to run code which was written to use VFP and instead emulate it using the integer register set.
The existing VFPSupport module already contains a partial integer-only floating point engine based on John Hauser’s softfloat.
Because all of the steps: abort-decode-emulate-return are the same as currently performed by the FPEmulator, we would reasonably expect it to be no worse performance than emulating FPA is. This would mean it would be possible to deliver a single binary to a user and they would be able to run it regardless, much as is done with programs written to use FPA, except that now most users would see a considerable performance boost on platforms containing a VFP macrocell (and no change in performance if not).
A copy of the VFPSupport module would also need to be present in order to provide management of contexts and similar SWIs to client programs in addition to the emulator itself.
All of the Single Instruction Multiple Data (SIMD) operations are fitted into the portion of the instruction space previously used by the NV
condition code. Prior to ARMv5 this was treated as a no-operation and would be silently stepped over regardless of the bit pattern in the remaining 28 bits.
This means any platforms prior to ARMv5 could not trap NEON instructions for emulation, therefore any VFP Emulator would be bound by only using the floating point instructions. This is convenient because it removes a great deal of complexity in attempting to emulate the whole of the SIMD operations, and is consistent with the ‘lowest common denominator’ toolchain switches for disc components covered earlier.
Conversely the FP operations invoked by executing an FPA opcode (such as ADFS
to add two single precision numbers) could in theory be sped up by doing the addition using the corresponding VFP operation within FPEmulator (a VADD.F32
in this example).
However this concept suffers from a number of drawbacks, negating some benefit at the expense of considerable engineering effort:
At a minimum applications should RMEnsure VFPSupport 0.18, and if that is found to be absent attempt to load it, and if still found to be absent refuse to continue – conclude that the system does not support floating point on a VFP coprocessor:
RMEnsure VFPSupport 0.00 RMLoad System:Modules.VFPSupport
RMEnsure VFPSupport 0.18 Error This application requires VFPSupport 0.18 or later to run
Rather than throwing an error, this technique can be extended to fallback to an FPA copy of the application if it is found that VFP isn’t available. A typical application directory for MyApp might contain the files shown below.
Notice a second !RunImage is present with a ‘V’ suffix, now the obey file !Run can automatically select the most appropriate executable:
RMensure SharedCLibrary 0.00 RMLoad System:Modules.CLib RMensure SharedCLibrary 7.00 Error MyApp needs SharedCLibrary 7.00 or later to run RMensure FPEmulator 0.00 RMLoad System:Modules.FPEmulator RMensure FPEmulator 4.09 Error MyApp needs FPEmulator 4.09 or later to run Set MyApp$RunSuffix MyApp$Suffix V RMensure VFPSupport 0.18 Unset MyApp$Suffix Run <Obey$Dir>.!RunImage<MyApp$Suffix>
Notes:
sin()
or log()
have been usedIt is assumed that a softloading version of VFPSupport, which would be required on systems where the VFP opcodes are trapped and emulated by a VFPEmulator, would load the prerequisite VFPEmulator itself during module initialisation. Therefore there is no check on the presence of VFPEmulator required.
Phase | Status | Completion | Latest updates |
---|---|---|---|
Conceptual design | In progress | 0% | 26-Dec-2021 Document created |
Mock ups/visualisation | - | - | - |
Prototype coding | - | - | - |
Final implementation | - | - | - |
Testing/integration | - | - | - |
v1.00 – 26-Dec-2021