[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[MiNT] Gemdos function: Super()



Hi,

I've experimented tonight with the Super() call using Pure C and my own tos binding library.

I'll start with the part which seems clear:
When an application (in user mode) calls Super(0), it switches to supervisor mode using its current stack pointer as supervisor stack pointer. The old supervisor stackpointer is returned as a result of the call. After that, it calls Super(old_ssp), passing the old supervisor stack pointer. This call changes back to user mode and sets the supervisor stack to "old_ssp". The supervisor stack pointer is copied back to user stack pointer. The use of "old_ssp=Super(0)" and "Super(old_ssp)" allows the application to switch to supervisor mode without modifying its stack pointer (i.e. if the compiler has put some temporary variables onto the stack, they are still accessible between the calls).

But what happens if the application specifies its own supervisor stack?
When the appliation calls "Super(my_stack)", it switches into supervisor mode, receiving the old supervisor stack pointer as a result of this call. But as we specified our own stack, we loose control over the content of the old stack. I.e. we don't have access to our temporary variables and return addresses which laid on the old stack. (OK, you can use assembler to get the content of USP register, but hey: we're programming in C :-)) After this, our application calls "Super(old_ssp)", which puts it back into user mode, but replaces the user stack pointer with the current supervisor stack pointer! We've finally lost complete control on our old user stack containing our temporary data (at least if we didn't save it by accessing USP).

So what's the use of this function? I mean, what's the use of Super(my_stack), if I can't get back to my old stack. I always thought that the Super() function is just a facility to switch back and forth between user and supervisor mode. But this variant is an exception.

Up to now I've never read something about this. Why is this behaviour not documented anywhere? (I.e. I've read in no documentation that switching back from supervisor mode to user mode should not be done with Super(), as this will just copy SSP to USP.)

To make a final point:
The following binding for Super() can only work with "Super(0/1)" and "Super(old_ssp)", because of the stack-switching-behavior of this call:
   Super:
     pea    (A0)
     move.w #32,-(sp)
     trap   #1
     addq.l #6
     rts

It's not possible to implement the "Super(my_stack)" call as a subroutine, because after switching the stack, we've lost the return address, which can only be restored by accessing USP in assembly language.


regards
Philipp