Stack Pointer A7
Moderators: simonsunnyboy, Mug UK, Zorro 2, Moderator Team
Stack Pointer A7
I know that in 68000 assembly the stack pointer and register A7 are the same thing. I've also read that in Supervisor Mode, there's a separate A7 stack pointer.
So does this mean that if I'm in User mode I can modify and abuse the stack pointer, and interrupts will still work as they use the Supervisor stack pointer?
A question about OS calls though - since they work through the Trap #n instruction, do they use Supervisor Mode and the alternate stack pointer?
And to make a call to the OS you put numbers on the stack and call a particular Ttrap. But how does the function you're calling know whether you put your data on the User Stack or the Supervisor Stack?
So does this mean that if I'm in User mode I can modify and abuse the stack pointer, and interrupts will still work as they use the Supervisor stack pointer?
A question about OS calls though - since they work through the Trap #n instruction, do they use Supervisor Mode and the alternate stack pointer?
And to make a call to the OS you put numbers on the stack and call a particular Ttrap. But how does the function you're calling know whether you put your data on the User Stack or the Supervisor Stack?
Last edited by joefish on Tue Nov 01, 2016 5:32 pm, edited 1 time in total.
-
- Obsessive compulsive Atari behavior
- Posts: 126
- Joined: Thu Sep 29, 2005 5:03 pm
Re: Stack Pointer A7
Thanks, yes, that's the sort of thing I want to do.
But that first call to TRAP #14 runs from USER mode (and sets things into SUPERVISOR mode), so its parameters had to be pushed onto the USER Stack. But the later call to Trap #1 to return to TOS is done from SUPERVISOR mode, so its parameters were pushed onto the SUPERVISOR stack. How does the operating system know which stack the parameters are on when it's called via a Trap #n instruction? The only thing I can think of is that it peeks into the stack to find the Status Register that was pushed at the time of the Trap and then decide whether to use the USP or the SSP to find its parameters. But is it that clever, or am I missing something?
But that first call to TRAP #14 runs from USER mode (and sets things into SUPERVISOR mode), so its parameters had to be pushed onto the USER Stack. But the later call to Trap #1 to return to TOS is done from SUPERVISOR mode, so its parameters were pushed onto the SUPERVISOR stack. How does the operating system know which stack the parameters are on when it's called via a Trap #n instruction? The only thing I can think of is that it peeks into the stack to find the Status Register that was pushed at the time of the Trap and then decide whether to use the USP or the SSP to find its parameters. But is it that clever, or am I missing something?
Re: Stack Pointer A7
OK, answering my own question, from the ROM disassembly:
http://www.atari-forum.com/viewtopic.php?f=68&t=27704
[/size]
Yes, it is that clever. So it's safe to drop into USER mode and abuse the A7 register, then pop back up into USER mode at will, and still call TOS from either (assuming the stack at the time is OK for putting parameters on). I also like the use of an unassigned Trap vector for a quick Supervisor Mode switch.
I do notice though that the Trap handler, if it needs to fetch parameters from the User SP, changes the SSP to the USP value for the duration of the call, so if the call needs the stack it will be using the User Stack space.
What I'm thinking of is prepared tables of data and jumps that I can point A7 at and just do an RTS to kick it off. The next address on the stack is a function to jump to, some parameters for it to pull off, and then it can tail-call the next stacked function with another RTS. The final address is a jump back to my main code.
The big risk of doing something like this is that an interrupt occurs and pushes some junk into your neatly prepared table, corrupting it for the next time around. But if you do this in User Mode then the only thing that can interrupt it is a Supervisor Mode event which will have its own Stack Pointer.
http://www.atari-forum.com/viewtopic.php?f=68&t=27704
Code: Select all
trp14h: lea trp14tab(pc),a0 ; a0 -> trap14 jump table
bra.s traph
trp13h: lea trp13tab(pc),a0 ; a0 -> trap13 jump table
traph: movea.l (savptr).l,a1 ; a1 - registers save area
move.w (sp)+,d0 ; pop SR and save it
move.w d0,-(a1) ; (need in D0 for user-mode test)
move.l (sp)+,-(a1) ; save return addr
tst.w (_longframe).w
beq.s traph2
tst.w (sp)+
traph2: movem.l d3-d7/a3-a7,-(a1) ; save C registers + super stack
move.l a1,(savptr).l ; update save-area pointer
Code: Select all
* make sure we have the right stack, call function:
btst #13,d0 ; was in user mode?
bne.s b_supr ; (was in super: use super stack)
move usp,sp ; use user stack
Code: Select all
b_supr: move.w (sp)+,d0 ; get function#
cmp.w (a0)+,d0 ; out of range?
bge.s b_exit ; (yes, so punt)
move.w d0,d1
lsl.w #2,d1 ; turn D0 into longword index
move.l (a0,d1.w),d1 ; get pointer to function handler
movea.l d1,a0 ; (quick and dirty test-for-negative)
bpl.s b_1 ; points to code
movea.l (a0),a0 ; indirect through RAM...
b_1: suba.l a5,a5 ; a5 -> zero page
jsr (a0) ; call BIOS function
I do notice though that the Trap handler, if it needs to fetch parameters from the User SP, changes the SSP to the USP value for the duration of the call, so if the call needs the stack it will be using the User Stack space.
What I'm thinking of is prepared tables of data and jumps that I can point A7 at and just do an RTS to kick it off. The next address on the stack is a function to jump to, some parameters for it to pull off, and then it can tail-call the next stacked function with another RTS. The final address is a jump back to my main code.
The big risk of doing something like this is that an interrupt occurs and pushes some junk into your neatly prepared table, corrupting it for the next time around. But if you do this in User Mode then the only thing that can interrupt it is a Supervisor Mode event which will have its own Stack Pointer.
Re: Stack Pointer A7
I'm not sure if it's relevant, but if you're in supervisor mode you can definitely abuse the user stack pointer for your own purposes. I'm using it as an extra general-purpose register in one of my programs with no ill effect. You probably want to save the old value of usp and restore it at program exit though.
Re: Stack Pointer A7
The user stack is per definition "abused"; things are pushed on it, it's changed between tasks (even in single-TOS; accessories, remember?).
In your trap handler, you'll have to check the Status Register in the stack frame. It will reveal the CPU state prior to the exception. Based on that, you decide where to fetch your parameters.
Example (this is for the 68030; you'll have to change it a bit for the 68000):
(I'm using GAS, syntax will obviously be different on a real assembler).
In your trap handler, you'll have to check the Status Register in the stack frame. It will reveal the CPU state prior to the exception. Based on that, you decide where to fetch your parameters.
Example (this is for the 68030; you'll have to change it a bit for the 68000):
Code: Select all
_trap_handler: move.l sp,a0
move.w (a0)+,d0 /* sr */
addq.l #6,a0 /* +ret+formatcode (CHANGE to #4 for 68000 iirc) */
btst #0xd,d0
jbne 1$
move.l usp,a0
1$: move.w (a0)+,d0 // Fetch a 16-bit parameter.
move.l (a0)+,d1 // Fetch a 32-bit parameter.
Ain't no space like PeP-space.
Re: Stack Pointer A7
I´m not sure I´m doing it correctly. By far the supervisor mode is in more creative dispel. Note the Supervisor Stack will align well without having used the User Stack. I will send a link to how I solve it , shortly.
Re: Stack Pointer A7
[img]
Anyone got one of them to sell?
Anyone got one of them to sell?
You do not have the required permissions to view the files attached to this post.
Last edited by arcx on Sat Apr 16, 2016 11:11 am, edited 1 time in total.
Re: Stack Pointer A7

arcx wrote:
Anyone got one of them to sell?