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