As title says it's fourth generation of 'simpleton famility'. From the beginning it was inspired by 'Gigatron TTL', but now it is something very different.
First of all: memory and registers are 16-bit wide.
There are eight registers R0-R7 and 128Kb of 65636 16-bit memory cells.
So, instruction opcode is 16-bit wide too. There is the only one instruction format:
Every instruction takes two operands X and Y, writes them into ALU with operation code (INSTR) and writes result to the destination R.
So, fields X, Y and R are registers codes 0-7. Plus bit of indirection (XI, YI, RI) which tells to work with memory cell register points to.
So, every instruction has format: R = Y op X, where op is operation code. Square brackets around operand mean indirect mode. I prefer such syntax in assembler too.
Registers R5-R7 have synonyms and special features:
R5 - SP - stack pointer - post-increments after indirect reading and pre-decrements before indirect writing.
R6 - PC - program counter - always post-increments after indirect reading
R7 = PSW = processor status word (flags, including enable/disable interrupts). Indirect reading/writing is meaningless, so it works as 'immediate indirect' address mode (data from *PC++ serves as address of memory cell we work with).
Immediate data is available as indirect PC reading because after reading instruction code PC post-increments (as always) and points to next word and will be advanced to the next word after indirect reading.
So, we could have next instructions in asm syntax:
Code: Select all
R0 = R1 + R2 ; regular add R1 = R1 +c R3 ; add with carry [ R2 ] = 100 + R4 ; add R4 with immediate (PC+indirect) 100 and write it to memory R2 points to [ R3 ] = R4 + [ 200h ] ; immediate indirect [ 200h ] (PSW+indirect) [ 100 ] = 20 + [ 101 ] ; register-free 4-word-long instruction
Some of them treats field XI+X of instruction as 'inplace immediate -8..+7'.
Current INSTR codes:
00 - ADDIS - add Y with INPLACE immediate in XI+X silent (doesn't update flags!)
01 - ADDI - add Y with INPLACE immediate in XI+X
02 - ADDS - add silent (doesn't update flags)
03 - ADD - add
04 - ADC - add with carry
05 - SUB - sub -
06 - SBC - sub with carry
07 - AND - and
08 - OR - or
09 - XOR - xor
10 - CMP - compare (as if Y - X)
11 - CADD - conditional add. never updates flags. (see below!)
12 - RRCI - rotate Y right (cyclic) by INPLACE immediate bit, carry gets last rotated bit
13 - RRC - rotate Y right (cyclic) by X bit, carry gets last rotated bit
- If operation doesn't update flags we use <- instead of = in asm.
- There is no separate MOVE opcode because it's ADDIS with 0 in XI+X:
R0 <- R1 + 1
R1 <- [ R2 ] + 0
[ R2 ] <- R1
[ R3 ] <- [ 100 ]
- wrriting immediate in PC is JUMP and adding (silent) PC with immediate is relative JUMP:
PC <- address ; JUMP
PC <- PC + offset ; RELATIVE JUMP
- conditional add is the key to the conditional branching, it works in this way:
X argument (16 bit) is decoupled in two parts: upper 3 bits are conditional code and lower 13 bits are sign-extended to 16 bit of -4096..+4095 addendum. But if condition is false - ALU skips addition and returns Y without changes.
So, to implement conditional branching we just do:
PC <- PC +condition OFFSET
Assembler provides automatic offset calculation for labels of course.
For simplicity alternate syntax is supported:
- CALL may be implemented as:
[ SP ] <- PC + 2 ; It's short ADDIS 1-word instruction
PC <- ADDRESS ; ADDRESS is immediate, so this instruction is 2-word. That is why we PUSH in stack PC+2
- RET is just:
PC <- [ SP ] ; Again, it's ADDIS opcode
- ADDI could be used as move with updating flags (testing move, useful in loops like STRCPY).
Code: Select all
StrCpy: ; R1 - pointer to src, R2 - pointer to dst [ R2 ] = [ R1 ] ; it's ADDI instruction JZ Exit R1 <- R1 + 1 R2 <- R2 + 1 PC <- StrCpy Exit: PC <- [ SP ] ; ADDIS as RET
PSW = PSW & mask1
PSW = PSW | mask2 ; ~mask1 of course
I have emulator + assembler for Simpleton 3 and I'm in process of remaking it for subj. So there is nothing to show right now.