www.riscos.com Technical Support:
The StrongARM Processor


Introduction to the StrongARM Revision 3, 04-Oct-96

SA Support

This note describes the new or revised SWIs in the StrongARM-aware version of RISC OS, and gives some guidance on use.


OS_MMUControl (page 5a-70)

This SWI has a new reason code, to support platform independent cache and/or TLB flushing:

OS_MMUControl 1 (SWI &6B)

Cache flush request

 On entry
 R0 = reason code and flags
  bits 0-7= 1 (reason code)
  bits 8-28 reserved (must be zero)
  bit 29 set if flush of single entry, else complete flush
  bit 30 set if processor TLBs are to be flushed
  bit 31 set if processor caches are to be flushed
 R1 = logical address, if R0 bit 29 set

On exit:
R0,R1 preserved

Interrupt status is not altered
Fast interrupts are enabled

Processor mode:
Processor is in SVC mode

SWI is not re-entrant

This call implements platform independent cache and/or TLB flushing.

WARNING: This SWI reason code is only intended for occasional, unavoidable requirements for cache/TLB flushing. You should respect the performance implications of this SWI reason code, in a similar way to SWI OS_SynchroniseCodeAreas.

Currently, bit 29 is ignored, so that only whole flushing of caches and/or TLBs are supported. A cache will be cleaned before flushing, where the processor supports a write-back cache.

This reason code is not re-entrant. Interrupts are not disabled during the flush, so the cache or TLB flush can only be considered to be complete with respect to logical addresses that are not currently involved in interrupts.

OS_File 12, 14, 16 and 255 (page 2-40)

If R3 bit 31 is set on entry, the file being loaded will be treated as code, and the relevant area will be synchronised using OS_SynchroniseCodeAreas if necessary.

A filetype for Code (&F95) has been allocated, with the intention that it be a parallel of Data (&FFD), and when it is loaded a synchronise is automatically performed. However this functionality has _not_ been implemented in RISC OS 3.70; you will still need to set bit 31 as described above.

Note that the *Load command calls OS_File 255 with bit 31 of R3 set, so no synchronise is required. This is to aid backwards compatibility; if no synchronisation is required, then use OS_File 255 directly.

DMA (page 5a-83)

The DMA Manager now marks pages uncacheable for both transfers from device to memory and transfers from memory to device. This is to ensure StrongARM's write-back cache is cleaned before the transfer starts.



Service_UKCompression (Service call &B7)

An application that may need unsqueezing/patching has just been loaded

On entry;

 R0 = subreason code
  0 -> first pass (unsqueeze)
  1 -> second pass (patch)
  all other codes reserved
 R1 = &B7 (reason code)
 R2 = load address
 R3 = size
 R4 = execute address
 R5 = filename (as passed to FileSwitch, not canonicalised)

On exit:

R1 preserved to pass on, or 0 to claim if you know you have performed all required unsqueezeing/patching for this pass.
R3 may be modified to indicate an altered size (eg after unsqueezing)
R4 may be modified to specify an new execute address
Other registers preserved

This service call is passed around when an Absolute (&FF8) file is run. The sequence of events is as follows.

1. The image is loaded.
2. If it does not contain an unsqueezed AIF header, then Service_UKCompression 0 is issued.
3. Service_UKCompression 1 is issued.
4. OS_SynchroniseCodeAreas is called.

Therefore unsqueezers and patchers need not do any synchronisation except that necessary for their internal working (they may want to alter some code, synchronise, and call it before returning from the service call).

Two modules are supplied with RISC OS 3.7 that use this service call:

UnsqueezeAIF will unsqueeze squeezed AIF images on the first pass, and squeezed non-AIF images by code modification (so the unsqueeze will not occur until after stage 5 above)

AppPatcher will patch squeezed and unsqueezed AIF images containing certain common code sequences that are known to fail on StrongARM.

Scanning an application for code sequences is a relatively slow operation. Therefore a bit has been allocated in the AIF header to indicate that a program is "StrongARM-ready". If bit 31 of the 13th word of the AIF header (ie bit 31 of location &8030 in the loaded image) is set, the patching stage will be skipped (in RISC OS 3.7 by AppPatcher claiming the service call and doing nothing; in a future version of RISC OS FileSwitch may not issue the service call). The program will still be automatically unsqueezed; it is recommended that you continue to use the existing Squeeze utility provided with Acorn C/C++, and rely on the operating system to unsqueeze the image for you.


Service_ModulePreInit (Service call &B9)

A module is about to be initialised

On entry:

 R0 = module address
 R1 = &B9 (reason code)
 R2 = module length

On exit:
R1 preserved to pass on

This service is called just before a module is initialised. When a module is *RMLoaded:

1. The module is loaded into memory
2. The module is unsqueezed if necessary
3. Service_ModulePreInit is called
4. OS_SynchroniseCodeAreas is called

This service call is intended to allow run-time patching of modules.



OS_PlatformFeatures (SWI &6D)

Determine various features of the host platform

On entry:

 R0 = reason code (bits 0-15) and flags (bits 16-31, reason code specific)
 Other registers depend upon the reason code

On exit:
Registers depend upon the reason code

Interrupt status is unaltered
Fast interrupts are enabled

Processor mode
Processor is in SVC mode

SWI is re-entrant

This new SWI is used to determine various feaures of the platform that the application or module is running on.

The particular action of OS_PlatformFeatures is given by the reason code in bits 0-15 of R0 as follows:

R0 Action 0 Read code features


OS_PlatformFeatures 0 (SWI &6D)

Read code features

On entry:

 R0 = 0 (reason code); all flags are reserved, so bits 16-31 must be clear

On exit:
R0 = bit mask of features: Bits Meaning 0 Must tell OS when code areas change (by calling OS_SynchroniseCodeAreas) 1 Enabling, then immediately disabling interrupts will _not_ give interrupts a chance to occur 2 Must be in 32 bit mode to read hardware vectors 3 Storing PC to memory (eg with STR or STM) stores PC+8 rather than PC+12 4 Data aborts occur with 'full early' timing (ie. as defined by ARM architecture 4)

If bit 1 of R0 set then R1 -> routine to call between IRQ enable & disable.

This call determines features of the host processor's instruction set.

Platforms running ARM 6 or 7 cores will return with R0 bits 0-4 clear; platforms running StrongARM will return with bits 0-4 set. For compatibility with older versions of RISC OS, you should call this SWI in the X form; if V is set on return and the error is 'SWI not known', then this can be taken as equivalent to a return with R0 bits 0-4 clear. Note that the easiest way to deal with the PC+8/PC+12 issue across all platforms is to make sure that the code is valid in either case (typically with judicious use of NOPs).

The routine pointed to by R1 is suitable for calling from any 26-bit mode; it preserves all flags and registers, and is reentrant. It should be called as follows

  LDRR0, irqroutine ; Load address previously stored in workspace
   MOVR14, PC; Get return address of PC+8
   MOVPC, R0 ; Call routine
   ... ; Code returns here


OS_SynchroniseCodeAreas (SWI &6E)

Inform the OS that code has been altered

On entry:

R0 = flags
 bit 0 clearEntire address space to be synchronised.
 bit 0 setAddress range to be synchronised.
 bits 1-31Reserved

If R0 bit 0 is set then:
R1 = low address of range (word aligned)
R2 = high address (word aligned, _inclusive_)

On exit:
R0-R2 preserved

Interrupt status is not altered Fast interrupts are enabled

Processor mode:
Processor is in SVC mode

SWI is not re-entrant

This new SWI informs the OS that code has been newly generated or modified in memory, before any attempt is made to execute the code.

WARNING: This SWI is only intended for synchronisation with unavoidable use of dynamic code, because of the potential for large performance penalties. There is no longer any justification in RISC OS applications for frequent code modification. This call must never be used in an interrupt routine. Examples of reasonable use include one-off loading, relocation etc. of subsidiary code or libraries.

When using this SWI, you should use the ranged variant wherever possible, in order to minimise the performance penalty.

The call may take a long time to return (up to around 0.5ms), so it should not be called with interrupts disabled.

For compatibility with older versions of RISC OS, you should either have determined (with OS_PlatformFeatures) that this SWI should not be called, or always call this SWI in the X form, and ignore any error returned. On platforms that do not require code synchronisation (as indicated by OS_PlatformFeatures 0), OS_SynchroniseCodeAreas will do nothing.

Note that standard loading of applications or modules (and the standard C overlay system) are automatically handled by the OS, and do not require synchronisation. This may be defeated by custom squeezing, failure to use a standard AIF header for applications, and so on.



Call a run-time determined SWI

On entry:

 R0-R9 as required for target SWI
 R10 = target SWI number

On exit:
R0-R9 as defined by target SWI
R10 preserved

Interrupt status:
As defined by target SWI

Processor mode:
As defined by target SWI

As defined by target SWI

This new SWI allows a target SWI number to be determined at run time, and passed in a register. This removes the need for a common idiom of dynamic code, in language library SWI veneers for example. In an APCS-R library, OS_CallASWIR12 may be more appropriate (see below).

Note that OS_CallASWI is merely an alias for calling the target SWI. It has no entry/exit conditions of its own, except for the special use of R10. To call a target SWI with X bit set, us the X form of the SWI number in R10; there is no distinction between OS_CallASWI and XOS_CallASWI.

You cannot call OS_CallASWI or OS_CallASWIR12 via OS_CallASWI, since there is no defined final target SWI in this case.

You cannot usefully call OS_BreakPt or OS_CallAVector using OS_CallASWI, as OS_CallASWI will corrupt the processor flags before entering the target SWI.

For future compatibility, you should always use this SWI in preference to any local construction for calling a SWI by number. For compatibility with older versions of RISC OS, a new CallASWI module will be made available (see below).

Note that this SWI calling mechanism is almost certainly faster than any other alternative implementation, including the original _kernel_swi and _swix code contained in older versions of the SharedCLibrary. The new SharedCLibrary now simply uses OS_CallASWIR12 for _kernel_swi and _swix.

OS_CallASWI cannot be called from BASIC as BASIC only passes registers R0-R7 via its SYS instruction. It would not be useful anyway.


OS_AMBControl (SWI &70)

This SWI is for system use only; you must not use it in your own code.


OS_CallASWIR12 (SWI &71)

Call a run-time determined SWI

On entry:

R0-R9 as required for target SWI R12 = target SWI number

On exit:
R0-R9 as defined by target SWI
R12 preserved

Interrupt status:
As defined by target SWI

Processor mode:
As defined by target SWI

As defined by target SWI

This call is identical to OS_CallASWI, except that it uses R12 to specify the target SWI. This may be more convenient in some environments. In particular under APCS-R, R10 is the stack limit pointer, which must be preserved at all times; if a SWI called using OS_CallASWI were to abort or generate an error the run-time library would usually examine R10 and decide that it had no stack to handle the abort or error. Therefore APCS-R libraries must use OS_CallASWIR12 (R12 being a scratch register under APCS-R).



The CallASWI module provides support under RISC OS 3.1, 3.5 and 3.6 for the following SWIs:

  • OS_CallASWI
  • OS_CallASWIR12
  • OS_PlatformFeatures
  • OS_SynchroniseCodeAreas

This will enable application programmers and library writers to use the new calls freely without any worries about backwards compatibility. There is no performance penalty for the use of these SWIs via the CallASWI module. One slight caveat is that older machines will not know the _names_ of these SWIs; they would have to be called by number from BASIC.

Return to section Index

© 3QD Developments Ltd 2013