SWI argument with (code pointer | flags)

Charles Ferguson gerph at gerph.org
Fri Oct 27 22:46:13 BST 2023


On Fri, 27 Oct 2023, Dave Lambley via oslib-user wrote:

> Hello,
>  
> I have been working on riscose[1] and have come across an odd usage of OS_Control in some very
> old code. R0 is being passed with bit 31 set. I have two questions.

I'm not aware of any particular use of this - OS_Control is legacy and has 
been deprecated since RISC OS 2, AIUI. The Archimedes PRM makes no 
reference to the non-26bit flag state.

https://www.4corn.co.uk/archive/docs/Archimedes%20Programmer's%20Reference%20Manual%20-%20Volume%201-opt.pdf

It's entirely likely that it would have been irrelevant on 26bit systems 
though as that was part of the processor flags.

> 1) Is OSLib able to represent an argument being a code pointer being OR'd with flags? I remember
> there being some calls which did in 26 bit times, but cannot find today.

There certainly were some; but even if there were, they'll be largely 
unusable in any modern software. Modern being post-RISC OS 3.5 with 
dynamic areas.

> 2) Might anyone remember what the flag would indicate? It's not documented in the online PRMs.
> The RISC OS 2 source has a BIC with 0xfc000003 before jumping to the error handler, which
> suggests to me that at some point those bits were used for something.

More likely than not this was to avoid accidentally changing mode or 
setting the flags. I doubt it ever meant anything.

Hmm. That said, it might have meant something to Brazil? But then 
knowledge of how Brazil worked is lost to time, mostly.

The RISC OS 2 sources I see here looks like this:

```
        LDR     r14, [r12, #ErrHan]     ; And go to error handler
        BIC     r14, r14, #ARM_CC_Mask
        STR     r14, [r12, #Curr_Active_Object]
        LDR     r0,  [r12, #ErrHan_ws]  ; r0 is his wp

        LDRB    r10, [r12, #CallBack_Flag]
        CMP     r10, #0

        Pull    "r10-r12", EQ
        MOVEQS  pc, r14                 ; USR mode, IRQs enabled
```

ARM_CC_Mask is, as you say, &fc000003. Because the return is through
`MOVS pc, r14`, this will enter the error handler in USR mode with the
IRQ and FIQ disable clear (and the other flags too) which was surely 
intentional.

There's always a possibility that the author was using the fact that
the top 6 bits were available as a means to store some data for free.
People were 'clever' like that.

I'd suggest that you probably want to have a compilation option that 
allows you to operate in either 26bit compatibility mode or not... or just 
ignore it and don't let people do that. You could, of course, just treat
OS_Control as being a 26bit-only interface and ALWAYS strip off the flag 
bits, since it's been deprecated since RISC OS 2 and nobody should be 
using it any more.

> http://www.riscos.com/support/developers/prm/progenv.html#88693
>  
> Cheers,
> Dave
>  
> [1] https://repo.or.cz/riscose.git

Seems a fair implementation.

RISCOS Pyromaniac implementation is:

```
@handlers.swi.register(swis.OS_Control)
def swi_OS_Control(ro, swin, regs):
    """
    OS_Control - Read/Write handler addresses

    =>  R0 = pointer to error handler, or 0 to read
        R1 = pointer to error buffer, or 0 to read
        R2 = pointer to escape handler, or 0 to read
        R3 = pointer to event handler, or 0 to read

    <=  R0 = pointer to previous error handler
        R1 = pointer to previous error buffer
        R2 = pointer to previous escape handler
        R3 = pointer to previous event handler
    """

    errorhandler = regs[0]
    errorbuffer = regs[1]
    escapehandler = regs[2]
    eventhandler = regs[3]

    regs[0], _, regs[1] = ro.kernel.api.os_changeenvironment(envnumbers.ErrorHandler,
                                                             handler=errorhandler,
                                                             handlerbuffer=errorbuffer)

    regs[2], _, _ = ro.kernel.api.os_changeenvironment(envnumbers.EscapeHandler,
                                                       handler=escapehandler)

    regs[3], _, _ = ro.kernel.api.os_changeenvironment(envnumbers.EventHandler,
                                                       handler=eventhandler)
```

Which is also different from the actual implementation in RISC OS Classic, 
but sufficient to meet the API.

However, this also reminds me that I don't have any explicit tests for 
OS_Control or the other legacy interfaces in RISC OS Pyromaniac. I would 
be interested if you have any tests yourself for those interfaces?

-- 
Charles Justin Ferguson
[ All information, speculation, opinion or data within, or attached to,
  this email is private and confidential. Such content may not be
  disclosed to third parties, or a public forum, without explicit
  permission being granted. ]


More information about the oslib-user mailing list