Suggestion: API modules
tymaja (278) 172 posts |
Regarding CallASWI; I thought of that, but then realised that it has a specific SWI number, and is actually part of the ‘original’ SWI system (the one we are still using), and thought it could get confusing to recycle that for a new usage all these decades later. CallASWI is tied to the current ‘SWI-number-in-instruction’ system, whereas I was thinking more of a new way to call SWIs without needing to read the instruction into the data cache (which still happens with CallASWI) |
Rick Murray (539) 13806 posts |
Problem is, SWI 0 already exists, and it is used → Perhaps a middle ground could be to use CallASWI, and then (in 64 bit only), define CallASWI to be SWI 0 and require the number to be passed in a register? |
tymaja (278) 172 posts |
SWI -1? :) CallASWI may actually be a good idea – if we are going to go platform agnostic, then having everything linked into a single SWI would make it easier to use macros / etc to remap syscall type features on any CPU architecture to map to (an updated CallASWI) |
David J. Ruck (33) 1629 posts |
Any SWI system on a 64 bit RISC OS is going to have a completely different calling mechanism at the assembler level, but as it’s a completely different assembly language there is no need to try to retain any compatibly with the existing mechanism. What will need to be done is a translation layer between old and new SWI systems. In BBC BASIC programs this can be done by the SYS keyword, C and other higher level languages will have to be relinked against a new library which implements the translation. |
tymaja (278) 172 posts |
“Any SWI system on a 64 bit RISC OS is going to have a completely different calling mechanism at the assembler level, but as it’s a completely different assembly language there is no need to try to retain any compatibly with the existing mechanism.” Agreed; this is one reason for looking at ‘SWI without the number encoded in the instruction’; if we move to different platforms like ARM64, or even more different platforms like RISC-V or x86-64, then relying upon a single instruction in the design of RISC OS 64 for the ‘SWI’ interface will be a good thing |
Stuart Swales (8827) 1349 posts |
Ignoring the other instructions required to compose the syscall/SWI number ;-) |
Dave Higton (1515) 3497 posts |
Follow the SWI instruction by the SWI number to be called. This is not unlike the current mechanism, which has to read the full instruction (pointed to be R14-4) to get the SWI number as data. It doesn’t require the SWI number to be passed in a register. |
Chris Mahoney (1684) 2165 posts |
For those who haven’t watched Gerph’s 64-bit presentation, his suggestion – as I understood it – is to put the SWI number in R10 (known as x10 on a 64-bit machine) and then call SVC 0. |
tymaja (278) 172 posts |
.bq “ Ignoring the other instructions required to compose the syscall/SWI number ;-)” I thought about that – however – there will be cases where it isn’t obvious; an example could be a program that wants to preserve flags (excluding overflow) across a SWI call. If wanting to shrink code size (and thus cache usage, depending on the purpose of the code), it could have a subroutine DOSWI1 If code used this subroutine for SWI calls, it would not be immediately apparent what the code did (at least in disassembly) |
Rick Murray (539) 13806 posts |
That’s 26 bit behaviour. The idea of preserving flags across SWI calls was ditched in 32 bit. Stuff just doesn’t expect that to happen any more.
Stash R14 (return address) on the stack. Seems clear enough to me. ;) Just… I’d not be writing my code with clever tricks that assume the flags span SWI calls (which was always a bit dodgy given that lots of things mess with the C flag). |
Simon Willcocks (1499) 509 posts |
We’ve really got to get away from thinking at the assembler level, registers and flags, and switch to thinking at the functional level. RISC OS modules provide commands and up to 64 functions that can be called from programs. The functions can take multiple1 input parameters and return multiple output values or an error2 (which makes them different from functions in most programming languages). Traditionally, the functions operate on a single module (or the preferred instantiation3). The APIModules idea allows the functions to be associated with objects managed by a module (and multiple modules providing the same functions).4 1 Up to 10? 2 Editied to add error return 3 preferred instantiation, along with current filing system are abominations that affect every program running. In a multi-tasking environment, that’s a really Bad Thing. 4 Will object orientation ever really catch on? |
Stuart Swales (8827) 1349 posts |
It’s a BBC Micro. |
Simon Willcocks (1499) 509 posts |
Don’t I know it! My umpteeth approach to making it work in multi-processing system is to have one special SVC stack that’s owned by one task at a time while it executes any legacy SWI. Everything else that doesn’t call a legacy SWI can get on and do its thing. |
Rick Murray (539) 13806 posts |
Yes. The previous assembler wrapper is a good example, because it won’t look anything like that in 64 bit and, really, remind me again why – in 2024 – we’re using assembler for anything more than “because I can”?
Looks like both BASIC and _kernel_swi() permits R0-R9 to be used.
Not so much. In combination with FileSwitch and paths, these issues really only affect command line programs and lazy programmers that make too many assumptions. But it is, as Stuart points out, a factor of the single-process single-context behaviour of the OS in general. Unless, of course, anybody here thinks that preserving the API that has been us through since when I was at school all those many years ago is preferable to such things as pre-emption and using multiple concurrent cores? |
Simon Willcocks (1499) 509 posts |
I don’t think that will be a problem; even Intel has “In 64-bit mode, sixteen general-purpose registers available”. |
Stuart Swales (8827) 1349 posts |
That would be me. As the old saying goes “If I were going there, I wouldn’t start from here” |
Simon Willcocks (1499) 509 posts |
It’s possible to both preserve the old API and to utilise such things as pre-emption and using multiple concurrent cores in new programs. Honest! |
Rick Murray (539) 13806 posts |
Wimp_SendMessage → UserMessageRecorded. Not to mention a potential for a lot of time wasting fiddles in order that a task could be swapped out during a redraw loop. Oh, and you’re on your own with printing. There’s a reason it single tasks. |
Simon Willcocks (1499) 509 posts |
Yes, and like I said up there:
That includes Wimp SWIs, but they only block the main task in a program, new programs can be merrily doing their own thing on all the cores. I also expect that secondary tasks could be allowed to do Wimp_UpdateWindow/Wimp_GetRectangle loops while the main task is polling. |
Steve Pampling (1551) 8155 posts |
Cos it’s processor intensive and needs to be offloaded? |
Rick Murray (539) 13806 posts |
You forget the font/VDU/ColourTrans contexts. These might be able to be saved around task switches, but it’ll be a bit ewww to have to do.
I draw your attention this ickiness. |
Simon Willcocks (1499) 509 posts |
No, because anything using those mechanisms will be running under the Wimp, thus cooperatively tasking. OS_WriteC style output will become the exception, rather than the norm, precisely because it does affect the whole system. Most programs will output to a pipe. Legacy programs that need it are probably too old to cope with 4k displays, and can have a VDU code interpreter sitting on the other end of the pipe. The names Druck and GraphTask ring a bell. I’m sure the font module code can be modified to maintain two contexts: one for the fonts loaded, and the other for a particular client’s choices. Draw only needs the latter. The system can simply claim an instance to implement the original SWIs. |
tymaja (278) 172 posts |
An ARM64 example (it is actually quite similar!) DOSVC1 of course, this is using X13 rather than SP… I don’t think any new code for the kernel should be in assembly (with the exception of the very low level code that has to be, such as the parts of the memory management code that directly alter system registers). I also think that RISC OS 64 should be written in C, not assembler. All that said, the reason I discussed assembler is because it is, in some ways, intricately tied to some aspects of RISC OS. One example is BASIC; it has a built in assembler. I am hopeful that, in RISC OS 64, there will still be a way to call system calls from assembler, so that this can be done from BASIC assembled code. While we should remove assembly from RISC OS itself, assembly will still also be helpful in BASIC code, for optimising small parts of it (so, this is one example of how assembly still has some uses). Looking at the BBC BASIC reference manual, the ‘SYS’ command in BASIC … also returns the processor flags to a variable! So this is another reason flags still have some role – they are built into the API, at least in BASIC (it would be trivial to ‘set the error bit’ when returning from a SYS call in BASIC if the kernel returns ‘an error’, of course). |
tymaja (278) 172 posts |
.bq “Oh, and we’d probably need to replace the SWI mechanism with something that isn’t going to run into problems on less capable processors than the ARM.” One way to make it more flexible could be to have a ‘bit’ in the SWI number, as we do now with the ‘X’ bit, which is set if we pass a parameter block, rather than registers; ‘R1’ could then be a pointer to such a parameter block, which itself is just R1,R2 … etc in sequence, and which could also be used for returning modified registers. That would allow multi-register SWI use on CPUs that support it, or parameter blocks on CPUs that don’t; While this is, of course, going back to ‘the CPU’ level, there will always need to be a low level ‘SYSCALL’ – the other OSes do this too – Linux SVC #0. In higher level languages, these options could be made transparent. In C, you could just include |
Simon Willcocks (1499) 509 posts |
(It’s b q dot, not dot b q!)
That’s unnecessary; the platform the code is running on will be the same for both module and caller, so they just both have to use whatever mechanism is required by the processor. This is what I meant by “We’ve really got to get away from thinking at the assembler level, registers and flags, and switch to thinking at the functional level.” |