SWI argument with (code pointer | flags)

Dave Lambley dave at lambley.me.uk
Tue Oct 31 19:21:18 GMT 2023


> On 27/10/2023 22:46 BST Charles Ferguson <gerph at gerph.org> wrote:
> 
>  
> 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.

Yes, the practical thing to do is perhaps to treat OS_Control as a 26-bit only interface and mask off the bits on entry. It's _possible_ that there's some code which reads the error handler address and makes use of the bits, but seems unlikely.

> > 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?

I'm afraid not, although a set of regression testing executables would be a nice thing to start building.

All the best,
Dave



More information about the oslib-user mailing list