Stack Operations

A project log for Suite-16

Suite-16 is a 16-bit cpu built entirely from TTL. It is a personal exploration of how hardware and software interact.

monsonitemonsonite 10/26/2019 at 12:210 Comments

Charles Moore's Forth is based on a 16-bit virtual machine that passes parameters between functions using the Parameter Stack (also known as Data Stack).

A stack is just a Last In, First Out (LIFO) structure contained in consecutive memory locations. The stack is often placed in the top of memory and grows downwards. So the top of the stack (TOS) is the lowest in memory of all stack items.

A register or zeropage variable acts as the stack pointer and is pre-decremented when an item is pushed onto the stack, and post-incremented when an item is popped off the stack. The stack pointer always points to the Top of Stack.

Suite-16 has PUSH and POP operations that may be used with any of the general purpose registers - so multiple independent stacks can be created. The only overhead is the assignment of a register solely as use as a stack pointer to one stack and a suitable section in memory. The stack pointer register should be initialised to it's upper boundary value - for example 0x2000 in RAM.

The contents of the accumulator R0 are pushed to the memory location addressed by Rn, after Rn has been decremented. Similarly the top member of the stack is popped into the Accumulator and then Rn is incremented.

The other use of stacks is to hold the return address of subroutines. When a subroutine is called the PC is pushed onto the top of the return stack, and popped back to the PC when a return instruction is executed. With this stacking arrangement it allows for the automatic nesting of subroutines.

Here's how the PUSH and POP instructions are coded on the simulator:

case 0x6:   R[0] = M[R[n]]  ; R[n]= R[n]+1   ;  break ; /* POP with post-increment of pointer Rn */
case 0x7:   R[n]= R[n]-1    ; M[R[n]] = R[0] ;  break ; /* PUSH with pre-decrement of pointer Rn */  

M[R[n]] is word in RAM pointed to by the stack pointer R[n]    R[0] is our accumulator.

The other instructions that use a stack are the CALL and RETurn:  Here R[15] is dedicated as the Return Stack Pointer RSP.

case 0x8:  R[15]= R[15]-1 ; M[R[15]] = PC ; PC = addr ; break ; // CALL (zero page) use R15 as RSP 
case 0x9:  PC = M[R[15]]  ; R[15]= R[15]+1            ; break ; // RET

 A later log will look at the stack manipulation words such as DUP, DROP, SWAP, OVER that are frequently used in Forth.