Programmer's model: ------------------- +-------+ +-----+ | ACC | | TOP | +-------+ +-----+ | N-1 | +---+---+---+ +-----+ | C | N | Z | | N-2 | +---+---+---+ +-----+ flags stack +----+----+----+ | AC | IN | IZ | +----+----+----+ alternate flags +-----+----+ +----+ | IEN | IE | | PC | +-----+----+ +----+ interrupt prog. counter The NANDputer has a single accumulator, and dual sets of flag registers. These two sets of flags are swapped when interrupts are active. This allows the CPU itself to save the flag states without the programmer having to do it. The programmer must save and restore the accumulator, however. The stack is 3 levels deep, and data pushes down and pops up. The interrupt has two associated flags: the IEN flag sits on the general RAM bank register at bit 4, and the IE flag is internal. The IE flag cannot be tested or affected, except by an interrupt which sets it, or RETI which clears it. a reset also clears IE. All ALU operations are performed either on the accumulator only, between the accumulator and memory, or between the accumulator and a constant. instruction set key: -------------------- n = 8 bit RAM address w = 8 bit immediate value r = 12 bit address p = 8 bit IO port address x = don't care bits (n) = the memory at RAM address n N.M = bit M of N c = carry flag | = logical OR & = logical AND ^ = logical XOR << shift left >> shift right Ordered numeric list of instructions ------------------------------------ All CPU instructions are a single 16 bit word. Each instruction takes exactly 1 CPU cycle (composed of 16 T states, and 3 nonoverlapping clocks, for a total of 96 crystal clocks per CPU cycle). Skip instructions take "2" cycles, because the next instruction is NOP'd out, rather than actually skipped over. 0xxx NOP 10xx NOP 11xx NOP 12nn OFFSET n PC <- PC + (n) + 1 13nn OFFSET n PC <- PC + (n) + 1 (alternate to above) 14xx NOP 15xx NOP 16xx NOP 17xx NOP 18xx NOP 19xx NOP 1Axx NOP 1Bxx NOP 1Cxx NOP 1Dxx NOP 1Exx NOP 1Fxx NOP 2tnn BCF n,t clears bit t of (n) 3tnn BSF n,t sets bit t of (n) 4tnn BTFSS n,t if (n).t is set, skip next instruction 5tnn BTFSC n,t if (n).t is clear, skip next instruction 6rrr JMP r PC <- r 7rrr CALL r PC <- r; (top of stack) <- PC 80ww LDAR #w a <- w 81ww XORR #w a <- a ^ w 82ww ANDR #w a <- a & w 83ww ORR #w a <- a | w 84ww RLR #w a <- w << 1 c <- w.7 85ww RLCR #w a <- w << 1 | c; c <- w.7 86ww RRR #w a <- w >> 1 | c << 7 c <- w.0 87ww RRCR #w a <- w >> 1 | c << 7; c <- w.0 88ww ADDR #w a <- a + w c = carry 89ww SUBR #w a <- a - w c = carry 8Aww DECR #w a <- w - 1 8Bww INCR #w a <- w + 1 8Cww ADCR #w a <- a + w + c; c = carry 8Dww SBCR #w a <- a - w + c; c = carry 8EXX RET PC <- (top of stack) + 1 8FXX RETI PC <- (top of stack); IEN <= 1 90ww LDA #w a <- w 91ww XOR #w a <- a ^ w 92ww AND #w a <- a & w 93ww OR #w a <- a | w 94ww RL #w a <- w << 1 c <- w.7 95ww RLC #w a <- w << 1 | c; c <- w.7 96ww RR #w a <- w >> 1 | c << 7 c <- w.0 97ww RRC #w a <- w >> 1 | c << 7; c <- w.0 98ww ADD #w a <- a + w c = carry 99ww SUB #w a <- a - w c = carry 9Aww DEC #w a <- w - 1 9Bww INC #w a <- w + 1 9Cww ADC #w a <- a + w + c; c = carry 9Dww SBC #w a <- a - w + c; c = carry 9Epp OUT (p) port(p) <- a 9Fpp IN (p) a <- port(p) A0nn LDA n a <- (n) A1nn XOR n a <- a ^ (n) A2nn AND n a <- a & (n) A3nn OR n a <- a | (n) A4nn RL n a <- (n) << 1; c <- (n).7 A5nn RLC n a <- (n) << 1 | c; c <- (n).7 A6nn RR n a <- (n) >> 1; c <- (n).0 A7nn RRC n a <- (n) >> 1 | (c << 7); c <- (n).0 A8nn ADD n a <- a + (n); c = carry A9nn SUB n a <- a - (n); c = carry AAnn DEC n a <- (n) - 1 ABnn INC n a <- (n) + 1 ACnn ADC n a <- a + (n) + c; c = carry ADnn SBC n a <- a - (n) + c; c = carry AEnn SETA a <- 0ffh AFnn CLRA a <- 000h B0nn STA n (n) <- a B1nn XOR n,m (n) <- a ^ (n) B2nn AND n,m (n) <- a & (n) B3nn OR n,m (n) <- a | (n) B4nn RL n,m (n) <- (n) << 1; c <- (n).7 B5nn RLC n,m (n) <- (n) << 1 | c; c <- (n).7 B6nn RR n,m (n) <- (n) >> 1; c <- (n).0 B7nn RRC n,m (n) <- (n) >> 1 | (c << 7); c <- (n).0 B8nn ADD n,m (n) <- a + (n); c = carry B9nn SUB n,m (n) <- a - (n); c = carry BAnn DEC n,m (n) <- (n) - 1 BBnn INC n,m (n) <- (n) + 1 BCnn ADC n,m (n) <- a + (n) + c; c = carry BDnn SBC n,m (n) <- a - (n) + c; c = carry BEnn SET n (n) <- 0ffh BFnn CLR n (n) <- 000h C0nn LDASZ n a <- (n) C1nn XORSZ n a <- a ^ (n) C2nn ANDSZ n a <- a & (n) C3nn ORSZ n a <- a | (n) C4nn RLSZ n a <- (n) << 1; c <- (n).7 C5nn RLCSZ n a <- (n) << 1 | c; c <- (n).7 C6nn RRSZ n a <- (n) >> 1; c <- (n).0 C7nn RRCSZ n a <- (n) >> 1 | (c << 7); c <- (n).0 C8nn ADDSZ n a <- a + (n); c = carry C9nn SUBSZ n a <- a - (n); c = carry CAnn DECSZ n a <- (n) - 1 CBnn INCSZ n a <- (n) + 1 CCnn ADCSZ n a <- a + (n) + c; c = carry CDnn SBCSZ n a <- a - (n) + c; c = carry CEnn SETASZ a <- 0ffh CFnn CLRASZ a <- 000h D0nn STASZ n (n) <- a D1nn XORSZ n,m (n) <- a ^ (n) D2nn ANDSZ n,m (n) <- a & (n) D3nn ORSZ n,m (n) <- a | (n) D4nn RLSZ n,m (n) <- (n) << 1; c <- (n).7 D5nn RLCSZ n,m (n) <- (n) << 1 | c; c <- (n).7 D6nn RRSZ n,m (n) <- (n) >> 1; c <- (n).0 D7nn RRCSZ n,m (n) <- (n) >> 1 | (c << 7); c <- (n).0 D8nn ADDSZ n,m (n) <- a + (n); c = carry D9nn SUBSZ n,m (n) <- a - (n); c = carry DAnn DECSZ n,m (n) <- (n) - 1 DBnn INCSZ n,m (n) <- (n) + 1 DCnn ADCSZ n,m (n) <- a + (n) + c; c = carry DDnn SBCSZ n,m (n) <- a - (n) + c; c = carry DEnn SETSZ n (n) <- 0ffh DFnn CLRSZ n (n) <- 000h E0nn LDASNZ n a <- (n) E1nn XORSNZ n a <- a ^ (n) E2nn ANDSNZ n a <- a & (n) E3nn ORSNZ n a <- a | (n) E4nn RLSNZ n a <- (n) << 1; c <- (n).7 E5nn RLCSNZ n a <- (n) << 1 | c; c <- (n).7 E6nn RRSNZ n a <- (n) >> 1; c <- (n).0 E7nn RRCSNZ n a <- (n) >> 1 | (c << 7); c <- (n).0 E8nn ADDSNZ n a <- a + (n); c = carry E9nn SUBSNZ n a <- a - (n); c = carry EAnn DECSNZ n a <- (n) - 1 EBnn INCSNZ n a <- (n) + 1 ECnn ADCSNZ n a <- a + (n) + c; c = carry EDnn SBCSNZ n a <- a - (n) + c; c = carry EEnn SETASNZ a <- 0ffh EFnn CLRASNZ a <- 000h F0nn STASNZ n (n) <- a F1nn XORSNZ n,m (n) <- a ^ (n) F2nn ANDSNZ n,m (n) <- a & (n) F3nn ORSNZ n,m (n) <- a | (n) F4nn RLSNZ n,m (n) <- (n) << 1; c <- (n).7 F5nn RLCSNZ n,m (n) <- (n) << 1 | c; c <- (n).7 F6nn RRSNZ n,m (n) <- (n) >> 1; c <- (n).0 F7nn RRCSNZ n,m (n) <- (n) >> 1 | (c << 7); c <- (n).0 F8nn ADDSNZ n,m (n) <- a + (n); c = carry F9nn SUBSNZ n,m (n) <- a - (n); c = carry FAnn DECSNZ n,m (n) <- (n) - 1 FBnn INCSNZ n,m (n) <- (n) + 1 FCnn ADCSNZ n,m (n) <- a + (n) + c; c = carry FDnn SBCSNZ n,m (n) <- a - (n) + c; c = carry FEnn SETSNZ n (n) <- 0ffh FFnn CLRSNZ n (n) <- 000h ???? interrupt (top of stack) <- PC; PC <- 0008h; IEN <- 0 Detailed instruction description -------------------------------- Normal ALU instructions: --- There are 6 kinds of normal ALU instructions. All work similar, except the next instruction can be skipped depending on the state of the zero flag. The upper nybble of the instruction determines what will happen after the ALU operation is performed. For example, we'll use the XOR instruction. There are 6 forms of the XOR instruction: A136 XOR 36h B136 XOR 36h,m C136 XORSZ 36h D136 XORSZ 36h,m E136 XORSNZ 36h F136 XORSNZ 36h,m These six instructions all perform the same XOR operation between the accumulator and memory (in our case RAM location 36h). The zero and sign flags are both updated with the result of the XOR. Bit 12 of the instruction determines where the result of the XOR goes- 0 = accumulator; 1 = memory where the operand was read (36h in this case). Then bits 13-15 determine what happens after the XOR occurs. The instruction can optionally skip the NEXT instruction depending on the state of the zero flag. It can either skip the next instruction if zero is set (XORSZ) or clear (XORSNZ). This lets you perform looping fairly easily as so: lda #12h ;12h counts in our loop sta 002h ;store our 12h value into RAM location 2 loop: ;code for our loop goes here decsz 002h,m ;decrement location 2, and skip next instruction at 0 jmp loop ;jump and do loop again There are several "less useful" instructions such as: CEnn SETASZ a <- 0ffh CFnn CLRASZ a <- 000h DEnn SETSZ n (n) <- 0ffh DFnn CLRSZ n (n) <- 000h EEnn SETASNZ a <- 0ffh EFnn CLRASNZ a <- 000h FEnn SETSNZ n (n) <- 0ffh FFnn CLRSNZ n (n) <- 000h These are byproduct of how the cpu functions. They can still be used, but will always or never skip the next instruction. i.e. SETASZ will set the accumulator to FFh, and clear the Z flag and set the N flag, so it will never skip the next instruction. -- All ALU instructions except STA affect N and Z flags. Some ALU instructions affect the C flag, as indicated in the instruction list. No other instructions (except BSF and BCF) affect the flags. Interrupts DO affect the flags by switching in an "alternate" set. This obviates the need for the programmer to save the flags manually. Reloading the flags would've been painful, requiring many instructions to restore them. Synopsis of the various ALU instructions: --- (note: only the prototypical case is shown here, the other 5 work nearly identically, as explained above) LDA n a <- (n) The byte of data at memory location (n) is loaded into the accumulator. N and Z are affected. STA n (n) <- a The accumulator is stored into memory at (n). Flags are NOT affected. XOR n AND n OR n The accumulator is logically XOR/AND/OR'd with memory byte (n). N and Z are affected. RL n The byte of memory at (n) is rotated left one bit. The upper bit is loaded into C. N and Z are both affected. Bit 0 of (n) is loaded with 0. RR n Similar to above, except (n) is rotated right, and bit is loaded into C. Bit 7 of (n) is loaded with 0. RLC n Similar to RL n, except the carry flag is pushed into bit 0 of (n). RRC n Similar to RR n, except the carry flag is pushed into bit 7 of (n). ADD n Adds the accumulator to (n). C is affected by the result of the addition, as are N and Z. Carry is set if the addition overflows; i.e. 1+ff = 100h. Examples: (n) acc result C N Z ----------------------------- 00 00 00 0 0 1 01 ff 00 1 0 1 02 ff 01 1 0 1 81 ff 80 1 1 0 44 88 cc 0 1 0 ADC n Works similar to ADD n, except the carry flag is added too. Examples: (n) acc cyin result C N Z ---------------------------------- 00 00 1 01 0 0 0 01 ff 1 01 1 0 1 02 ff 0 01 1 0 1 81 ff 0 80 1 1 0 ff ff 1 ff 1 1 0 SUB n Subtracts (n) from the accumulator. All flags affected. Carry is CLEAR if the subtraction underflows; i.e. 80 - 81 = FF and carry will be clear. If C is set, there was no underflow. Examples: (n) acc result C N Z ----------------------------- 00 88 88 1 1 0 88 00 78 0 0 0 01 FF FE 1 1 0 54 54 00 1 0 1 SBC n Works similar to SUB n, except carry is added also. result = Acc - (n) + C Examples: (n) acc cyin result C N Z ---------------------------------- 00 00 0 ff 0 1 0 ;we subtracted 1 since C was clear going in 01 02 1 01 1 0 0 ;we subtracted 1 from acc 01 02 0 00 1 0 1 ;we subtracted 2 because carry was clear DEC n INC n These instructions either add or subtract 1 from (n). C is NOT affected, however N and Z are. SETA CLRA SET (n) CLR (n) These instructions either set all bits or clear all bits of (n) or Acc. The Z and N flags are affected: SET always sets N and clears Z; CLR always sets Z and clears N. Immediate ALU instructions: --- The immediate ALU instructions work very similar to the normal ALU instructions, except they operate on immediate data from the instruction word, instead of using it as an address to RAM. The immediate instructions work exactly the same as the normal ALU instructions do, except the result is always placed into the accumulator. The immediate instructions also have one other frill, which is any of them can be used as a return instruction. This seems strange at first, but makes good sense- you can use LDAR # to load the accumulator with a value and return. This, along with the OFFSET instruction can be used to make a data table where the accumulator is loaded with the desired table index, and the table itself made up of multiple LDAR # instructions each returning a byte of data. Bit based operations: --- There are a couple different types of bit based operations that can be performed. BSF n,t BCF n,t These two instructions can set or clear (respectively) a single bit of RAM. No flags are affected and only bit t of (n) is affected. BTFSC n,t BTFSS n,t These two instructions will skip the NEXT instruction, based on the state of bit t on memory byte (n). BTFSC will bit test memory and skip the next instruction if the bit was clear. BTFSS works oppsite- it skips if the bit was set. Program flow: --- JMP a This instruction will jump to address "a" in memory. "a" is a 12 bit address. To get a full 16 bits worth of address, there is a bank register. The bank register lives at RAM address FAh. The lower 4 bits are readable and writable and store the current 4K ROM bank. See the "memory banking" section for more information on RAM and ROM banks. CALL a Similar to a JMP, this will first push the program counter onto the stack, then jump to "a". As with JMP, a is a 12 bit address. RET Pops the PC off the top of stack and adds 1 to it, then puts it into PC. RETI Pops the PC off the top of stack and puts it into PC without adding 1. The reason RET adds 1 and RETI does not, has to do with how interrupts work. If 1 was not added to PC after popping from a RET, the program counter would get "stuck" on the CALL instruction: some code: 0100: LDA #12h 0101: CALL 0123h 0102: STA 088h Here is what happens: First, the LDA #12 loads 12 into the accumulator. Next, the call is performed, which pushes 0101h onto the top of stack. Then, the subroutine runs and returns. Finally, return pops the PC off the stack (0101h) and puts it into PC. If 1 was not added here, it'd return to 0101h and the CALL would execute again, indefinitely! This actually happened since I didn't realize this would happen at first. NAND gate UHE10B was added specifically to set carry when performing RET, vs. RETI. RETI must NOT increment the PC after popping it off the stack, because interrupts work by forcing the instruction CALL 0008h onto the data latch instead of the byte in ROM. This is done by gate URD8D. Here's some typical code: 0100: LDA #34h 0101: STA 088h 0102: INC 077h 0103: CALL 0122h 0104: STA 089h now, if an interrupt occurs between the instructions STA 088h and INC 077h: 0100: LDA #34h 0101: STA 088h 0102: CALL 0008h ;the interrupt substitutes the next instruction for this one. 0008: first instruction of interrupt routine So when the call occurs, it pushes 0102h onto the top of stack like any other call instruction would've. To end the interrupt, you use the RETI instruction which then re-enables interrupts, and pops the PC off the stack (0102h). 0102h is the instruction that we pre-empted by the interrupt and never actually executed, so this time we DO want to execute it to continue the program flow. Thus, we do not want to add 1. NOTE: RET/RETI will restore the original ROM bank # on return. this lets you do "bank fall through" springboards to get to routines in other banks, and they can return you to the proper executing bank. See RAM/ROM banking section for more information. OFFSET n This instruction is how calculated goto's are done. (Accumulator + 1) is added to the program counter. Only the lower 12 bits are updated so you cannot cross 4K pages with it. Any wrapping that occurs will wrap around from the top of the page to the bottom of the page. This allows a full 256 byte table which does not have to be aligned to an 8 bit page; it can be anywhere in the 4K page so long as it doesn't wrap pages. An example: STA address CALL tablelut ... tablelut: OFFSET address LDAR #12h LDAR #34h LDAR #56h LDAR #78h if (address) is equal to 00h, nothing is added, and execution falls through to the LDAR #12h instruction. If (address) equals 01h, then 1 is added to the PC, and then PC is incremented. This then points PC to the LDAR #34h instruction, and so on. IO instructions: --- OUT (P) This instruction will write a byte of data from the accumulator to IO port P, which is an 8 bit address. The IO ports live on the RAM bus (see RAM/ROM banking section). IN (P) This instruction reads port P and writes its value to the accumulator. RAM and ROM banking: -------------------- RAM on the NANDputer operates with an 8 bit data bus, and an 8 bit address bus. This allows for direct access of up to 256 bytes of RAM. The upper 16 bytes of this address space (F0-FF) comprises the special function registers. They are mapped over top of RAM and thus RAM can "Shadow" these registers. i.e. the RAM bank at FAh is write only, but because RAM is mapped underneath, the value written can be read by reading FAh. This saved many gates by using the RAM itself to store the values for later reading. There are two special "index" registers. These allow one to read and write memory indirectly. They hold the address in memory which will be read or written. Each index register is independent and 8 bits wide. Thus, it can select any byte of memory in the 8 bit address range. These index registers allow code to more efficiently move memory or run through tables, etc. The special function registers are mapped like so: F0-F2 : not used at the moment (for inputs though) F3 : hard input port F4 : accumulator F5 : status register (flags) F6 : index data port 0 F7 : index data port 1 F8 : not used at the moment (for more write registers) F9 : hard output port FA : ROM bank FB : general RAM bank # (bits 0-3) and interrupt enable (bit 7) FC : index register 0 FD : index bank 0 FE : index register 1 FF : index bank 1 Writing to any of these 16 locations writes to RAM "underneath". Reading returns either RAM contents (F8-FF) or other data (F0-F7). This makes F0-F7 "write only" to RAM. We CAN read these values, however. The NANDputer can access up to 4K of RAM. The instructions, however, can only access up to 256 bytes of RAM. To access more memory, the RAM is bankswitched. This is implemented in the (hopefully) least painful way. There are three RAM bank registers: FB which is the "general" RAM bank. This RAM bank is used for every single instruction that accesses memory. The 4 bits written here determine which of the 16 256 byte banks is to be used. This is true except the case when one of the two index registers are being used. In these cases, the index bank is substituted for the "general" bank. The index registers also lets the programmer "get to" all 256 bytes in each bank. When using the index registers, the F0-FF addresses will always access RAM and never a special function register. The programmer can also get to the shadow memory under the SFRs. This is always mapped at FF0-FFF in RAM. Writing to F0-FF will always write to memory at FF0-FFF in the RAM, regardless of the "general" bank that is set. In most cases, the general RAM bank can be set to F, provided 240 bytes is enough for all desired program variables that are not arrays. The index registers can be used to get to memory at 000-eff with no "holes". NOTE: The accumulator and status registers can be accessed like any other memory location. While you could add numbers to the flags register, doing so isn't terribly useful. This allows for the accumulator itself to be operated on in instructions such as CLR n INC n RL n etc. NOTE: If the status register is used in any ALU operation, the status register is updated twice- first with the result and again with the flag values of the operation. ROM banking: --- The ROM bankswitching works similar to the RAM version. ROM is in 4K pages vs. 256 word ones, however. As before there are 16 ROM banks, each 4K in size for a total of 64K words. There's a ROM bank register mapped in at FA. Writing here instantaniously changes banks by changing the state of the upper 4 program ROM address lines. When a CALL instruction is performed, this bank address is pushed onto the stack. When a RET instruction is performed, the bank is popped off the stack into FA. This lets one use "springboards" like this to call code in another bank, and return gracefully: (bank 0) 0100: STA 012h 0101: CALL 0ff0h ;this pushes bank 0 onto the stack along with 0101h for the PC. 0ff0: LDA #07h ;we will jump to bank 7 0ff1: STA 0fah ;write to bankswitching register (bank 7) 0ff2: JMP 0005h ;gets us to the start of our routine in bank 7 0005: LDA #12h ;this is our routine 0006: STA 034h 0007: RET ;pops the PC *and* bank 0 off the stack, returning us to bank 0 (bank 0) 0102: STA 088h ;instruction after our call Having to write the bank is kind of a drag, because it makes it more difficult to put a value into the accumulator before calling our function. There are a few thing we can do to make this slightly easier, like using bank set instructions to set individual bits on the banking register, but this will only get us to banks 1, 2, 4, or 8 for example. Another method would be to load the accumulator's upper 4 bits with a value and the lower 4 with the desired bank. Finally, data could simply be STA'd into memory first before performing the write. IO Ports: --- The IO ports on the NANDputer share the RAM bus. The lower 8 bits of the ROM data bus determine which 8 bit IO port to use, and the IN and OUT signals determine which of the two instructions is currently executing. Some logic is required to turn this into a proper 8 bit "Z80-like" IO bus, which is shown on the schematic. This produces an 8 bit address bus and an 8 bit, bidirectional data bus and two control signals, /WR and /RD. During output instructions, the accumulator is output on the data bus, then /WR is pulsed. During input instructions, the desired device presents its data on the data bus, then /RD is pulsed and data is latched into the latch. This circuit can thus directly interface to all sorts of peripheral chips such as the 8255, 8251, 8253, etc. using minimal address decoding with i.e. a 74HC138. Hard IO ports: --- There are a few "hard" IO ports which are either input only (F0-F3) or output only (F8, F9). Currently, only the input port F3 and output port F9 are implemented. The rest would be easy to add if they were needed. I would've added them probably if there was room on the perf boards for them. an WR_F8 control signal was provided, along with three serial input data ports for F0-F2. Interrupts: --- Interrupts on the NANDputer consist of a single maskable interrupt, which is level sensitive. A high level on the IRQ line will cause an interrupt to occur, if the CPU is not already in the interrupt handler, and interrupts are enabled. The interrupt enable flag is bit 4 of the general RAM bank register. When set, interrupts are enabled. When clear, interrupts are disabled. When an interrupt occurs, several things happen: * The PC will be set to 0008h * The bank will be FORCED to 0. Entire interrupt handler must fit in bank 0. * The 3 flags (N, Z, C) will be swapped for an alternate set * Interrupts will be disabled (internal, non-testable flag). The flags being swapped saves the programmer having to save or restore them. Bank 0 is always forced (writing to FA will NOT affect bank!). And interrupts will be disabled. The interrupt enable flag on the general RAM bank register does not get cleared. When an interrupt ends via the RETI instruction: * The PC will be restored to its former location * The bank will be restored, and a bank other than 0 can now be accessed * The 3 flags are swapped back in, swapping out the set used in the interrupt * The interrupts are re-enabled. Only an RETI instruction can return from an interrupt. There's a flipflop that is set when an interrupt occurs and RETI clears this flipflop to end the interrupt condition. Resetting the CPU will also clear this flipflop to end any interrupt condition that may have been present. Reset: --- Reset will clear any interrupt condition, and reset the bank to 0, and the PC to 0. Execution commences at address 0000h in ROM. Nothing else is changed. The accumulator, flags, and RAM will be untouched. Stack: --- The stack is three levels deep. It does not occupy RAM and is contained in NAND gate latches. The stack is three levels, so that the interrupt can call 1 level deep worth of subroutines, the main loop can call 1 level deep worth of subroutines, and the interrupt itself can use up the 3rd level. Obviously any other combination can be used. i.e. two levels in the main loop and no levels in the interrupt, etc. If too many things are pushed into the stack, the oldest entries are lost. Each time an item is popped off the stack, the other items "move up" one position, and the oldest entry is duplicated. The 3rd and all subsequent pops will produce the same value.