Suggestion: API modules
tymaja (278) 172 posts |
I was thinking more about things like backward compatibility with older RISC OS software (particularly BBC BASIC programs, which call SWIs, pass values, even check flags); having some way to interface between the ARM32 API, and (any future APIs) does seem important; the current API does, like Linux / MacOS / Windows, use registers and assembler |
Rick Murray (539) 13806 posts |
Think you meant X14. ;)
That’s pretty much a given. If we could recompile the OS with a new target processor and different glue logic, we wouldn’t be where we are now.
Why? There isn’t anything like the prevalence of assembler on Windows, for example. Maybe somebody somewhere wrote some code in assembler, but it’s all hidden away under friendly API calls that happen at a much higher level. This is how it should be.
If one is still needing to optimise BASIC on hardware approaching 1½-2GHz, one is probably not using the right language. I would like to take a moment to point to the various AmCog games, that perform quite well, and are supplied as uncrunched BASIC. Not only that, but there are some “mistakes” in there, like using floating point variables as flags, that will work but will have a small speed hit due to not being a plain integer. And, yet, on a recent RISC OS machine, it works just fine. The sorts of hardware we have today, I can’t help but think that it’s the algorithm that will have the biggest effect on performance. And if you’re doing the sorts of things where BASIC takes too long, you probably ought to be using a compiled language. Which, pretty much means C as there’s not a lot of choice on RISC OS…
It has to. The original API was written with the expectation of stuff being written in assembler, so it was specified that the ‘V’ flag being set would flag an error. This does not have to be the case. A lot of DeskLib returns values into a variable passed to the function, and the function itself either returns NULL or a pointer to an error block (this isn’t always the case, the File_* library in particular behaves differently) which means that it isn’t necessary for the average program to mess with this sort of low level stuff if you use a library that hides the specifics. This is a particularly RISC OS problem due to the entire API largely revolving around SWI calls. Do you think the likes of Windows and Linux have loads of little bits of library written in assembler to perform all the system calls? A modern OS just doesn’t work like that.
Of course. There is always a need for an application to ask the kernel to do something, and the system call mechanism is necessary to switch to kernel code with kernel privileges. However on other OSs, this is pretty much only for communicating with the kernel. On RISC OS, the system call is an implicit and major part of the programmer API – in order to turn a word of data into a musical note on my piano, my software makes a system call that is marshalled to my MIDI module that runs with kernel level privileges (why!?!) which then parses the data and drops it into a buffer where it eventually gets sent to the device. If I want to open a window, system call. If I want to read the current time, system call. Write a character on the screen? Guess what…
You’re doing it wrong – you’re approaching it from the point of view of an assembler programmer. BASIC does loads of system calls. Like RECTANGLE FILL pulls apart the parameters and calls OS_Plot, for example. But you don’t realise that because it’s a friendly BASIC keyword. I wrote several applications for Windows using VisualBasic. There were keywords. There were libraries (OCX and such). There were things (timers, pictures, windows, etc) that had attributes (filename, width, duration, etc). Pretty much all of the code worked around interacting with these ‘things’. I don’t think I made one system call ever in any of my VB code. If I needed additional functions, it was possible to merge in another library and use the facilities it offered. Sure, there were limitations, namely VB used the xxxA interface rather than the xxxW one so it always ran in CP-1252 mode, which was kind of dumb given that VB represented strings internally as UTF-16 but used the ANSI (8 bit) API. But for the stuff I was writing, that wasn’t really an issue. It’s a major pain in the arse to get foreign squiggles working on RISC OS too. Maybe some of these libraries make a bunch of system calls internally. I don’t know. Really, unless you are working at the OS level, you shouldn’t need to know. You shouldn’t need to know what registers to put where in order to read the contents of a directory. You should just call a function that returns the next filename, or NULL if there aren’t any more. Which means maybe a future RISC OS can look at having a way for a program to hook itself to a set of higher level functions that it can call (think CLib but everywhere) rather than messing around with the low level stuff? |
tymaja (278) 172 posts |
Yes (at least Linux). Windows will also have to do this – every true* system function will need to be written in assembler! *specifically, the interface between the CPU, the MMU, and the OS, has to be in assembler!. Linux even has syscalls for character printing, system clock, etc, loads of syscalls that map fairly well to RISC OS SWIs; One thing I realise : I’m working on BASIC, which is ‘very’ assembler! And I am trying to convert it to ARM64 (to learn how the data flow works, to be able to upgrade ARM32 BASIC strings + FP + int). ARM BBC BASIC is similar to an OS in several ways, and it has its own ‘APIs’ (it is an API in a way), plus it is in assembler, so one has to work in an assembler way when working with the original source code. I personally think converting ARM32 BBC BASIC to alternate CPUs could be helpful for RISC OS, in the short – medium term. It is much easier than rewriting it in a different language (for now). It also helps keep the ‘unexpected / unpredictable behaviours’ closer to ARM32 BBC BASIC (such as specifying 33-bit binary numbers not throwing any kind of error, or doing ‘variable=variable+1’ not throwing an error if the variable doesn’t exist, etc). Such unexpected behaviours will eventually require lots of ‘edge-case’ C code to mimic how BBC BASIC has always handled such things. I do think almost all of RISC OS should be in C though :) |
Dave Higton (1515) 3497 posts |
I’ve done quite a bit of embedded programming on a couple of ARM chips (STR711, LPC1114). This was entirely in C, using the free IAR compiler. Access to all the peripherals included. The IAR tools supply a tiny library of chip-specific code that’s in assembly language, just enough to boot it and call main(), and that’s it. So I simply do not believe the argument that anything other than those first few bootstrap instructions has to be written in assembler. If a compiler behaves like the IAR one, even the HAL can be written in C. |
Stuart Swales (8827) 1349 posts |
Fully concur, same reasons, and not just embedded ARM. The reason Arthur / RISC OS was not written in C is that we did not – and still do not – possess a C compiler that can produce relocatable read-only code. [And, of course, back in the day APCS used the wrong register as stack pointer.] |
tymaja (278) 172 posts |
I still believe that only assembly instructions can alter system registers.I do agree that abstraction is important. Abstraction will mean we can talk to a C MMU library, from C HAL code, and the C MMU library can talk to some small assembler libraries, which can be hand-coded per architecture, which would make it so much easier to move beyond ARM64 CPUs The C compiler not producing relocatable read-only code is interesting – are we working on a way to upgrade this? |
Chris Mahoney (1684) 2165 posts |
Having made a little “toy OS” myself that can boot to a desktop with a functional mouse and movable windows, entirely in C, I don’t know why you’d worry yourself with assembly in the modern era. |
Dave Higton (1515) 3497 posts |
Well, some of us have told you that we’ve already done it in C. |
Rick Murray (539) 13806 posts |
Yup. Written an interrupt handler and directly poked the serial port hardware. In TurboC. I don’t know x86. When I was vaguely taught 80286 a billion years ago, I don’t pay much attention as I thought it was bloody awful, a complete clustermew compared to what my ARM2 was doing. How? Pointers. Define an int (for word access (note that “word” size may depend upon the system)) or char (byte access). Point it at whatever the thing is. Use it. Something like this: char *thisbyte = hardware_address; hardware_register = thisbyte[0]; You only need assembler for the real low level stuff that can’t be done in a higher level language, like, say, the first few instructions of an abort handler… |
David J. Ruck (33) 1629 posts |
What the BASIC SYS command will have to do on any 64 bit RISC OS is emulate the way old 32-bit SWIs work including returning flags, even though 64 bit SWI call mechanism is likely to completely different (fixed SWI instruction code, SWI number in register, no flags and 64 bit addresses). Calling new native 64 bit SWIs will need a new keyword, such as SYS64, as there is no overlap between the two mechanisms. This is similar to how BBC BASIC handled the move from 8 bit to 32 bit, allowing the use of old MOS APIs on RISC OS e.g. CALL &FFF4 was translated to the new OS_Byte SWI, and the SYS keyword was introduced to call RISC OS SWIs. |
tymaja (278) 172 posts |
Agreed! (System registers need assembler) – CPU system registers. But they really only need 1 instruction to do the MCR/MRC of said registee – the rest can be in C!
The good thing is that the SYS handler code is quite compact, so adding such a conversion layer shouldn’t be too bad, when the time comes! SYS64 would be easy to implement from the SYS handler code also. |