Syscalls

From WikiPrizm
Revision as of 21:57, 4 December 2014 by ProgrammerNerd (talk | contribs)
Jump to navigationJump to search

If you are looking for the list of syscalls, see Category:Syscalls instead.

This page has not been completed. Parts may be missing or reorganized before completed. Information is provided as-is and may have errors.

The version of CASIOWIN on the Prizm supports system calls, like on previous models such as the fx-9860G and similar. On this Wiki, system calls are usually abbreviated as syscalls.

Most of the addresses on the table of system calls are entry-points to functions, but some of the addresses point to data like glyph tables.

A list of the known syscalls that correspond to functions is available here.

Calling convention

To access a system call, code should jump to 0x80020070 with the syscall number in register R0. After the syscall is executed, it will jump back to the calling code.

MOV.L   syscall_number, R0
MOV.L   #H'80020070, R2
JMP     @R2
NOP
NOP     ; execution will resume here

The NOP after the JMP is necessary because in the SH-4 instruction set, JMP is a delayed branch instruction (the instruction after the JMP will execute before the jump occurs). The second NOP could really be anything (your code).

Syscall numbers

The numbers for the syscalls are documented on the Wiki page for each one. Note that the syscalls documented, and their numbers, refer to the Prizm models (fx-CG10 and fx-CG20), not the fx-9860G and alikes! Some syscalls have corresponding versions in the CASIOWIN that runs on these previous models, but others are new and others have changed behavior despite sharing the same signature.

What is available as syscalls

Most OS functions, even insignificant ones, appear to be exposed as syscalls. Most likely, in the build process of the OS, a syscall table is exported, based on all the functions (and possibly other symbols) found in the code, and put at a specific place in the resulting OS binary. Of course, in order to guarantee that add-ins stay compatible across OS versions, the system used to build this table must keep numbers for existing syscalls the same across builds.

The support for syscalls is essential for add-ins to work. Official add-ins are most likely linked against the syscall table as generated during the OS build process. This would allow for coding add-ins using the same function names as used the core OS code.

Apparently certain libraries, such as zlib (included for decoding and encoding of g3p pictures), are not exposed directly through syscalls. This can be due to the fact that the OS code is linked against a cross-compiled zlib, but zlib source files are not present in the OS code tree, so its functions escape being included in the syscall table during the build process.

What uses syscalls

Apart from add-ins, it is not clear whether internal apps also use the syscall calling convention (i.e., jump to 0x80020070) to call core OS functions.

How they work

This section may be considered to be a form of optional reading to a beginner. Understanding this is not critical to writing an application (add-in) for the Casio Prizm however doing so many be of benefit. One thing we get out of this is that all syscalls are functions and that there is no form of bounds checking so make sure you are calling a valid syscall. You will notice in the first section (Calling convention) each Syscall has an unique number. This does not necessarily mean that all different values have a different function. You will also notice that we are using the jmp instruction to go to address 0x80020070. This is a physical address on the flash memory and the code starting at that address is:

! ---------------------------------------------------------------------------
                mov.l   #SyscallJumpTable, r2
                shll2   r0
                mov.l   @(r0,r2), r0
                jmp     @r0
                nop

So what this does is takes the syscall number, multiplies it by four (pointers are four bytes which is due to the fact that the SH-4 is a 32bit cpu) and then gets the pointer to the function at that offset and jumps to the address that was just retrieved. You may be wondering how this function will return. It is simple, the syscalls end with rts.