Just-About Usable Computer ISA Spec
A fantasy 8-bit Harvard-architecture kinda-RISC-but-kinda-CISC CPU design.
A JAUC interpreter written in Java
Memory
The JAUC architecture allows for 65528 instructions in program address space and up to 64KiB of data address space.
The first 8 words of the program space are reserved for 8 interrupt vector addresses. If the vector address is zero, program execution is immediately halted for inspection in a debugger or monitor.
Program execution begins at program address 8.
Registers
There are 8 8-bit general-purpose registers. The 1st register is hardwired to zero. The 8th general-purpose register is 16 bits wide. The 8th register is used by the LLJ and ULL instructions for long-distance jumps.
There is an internal 256-word stack used for 16-bit procedure return addresses. A stack interrupt is triggered when this stack overflows or underflows.
There is another internal 256-byte general-purpose stack usable by programs. A stack interrupt is triggered when this stack overflows or underflows.
The Instruction Pointer (IP) register is an internal register pointing to the current instruction being executed. It cannot be accessed outside of jump instructions.
The Interrupt Return Pointer (IRP) register is an internal register that is used to store the return address for an interrupt handler. It cannot be accessed by user code.
Interrupts
When an interrupt is triggered, the current instruction's address plus one is pushed to the internal return address stack. If an interrupt occurs during an interrupt handler, a double-fault occurs and the CPU resets. A debugger or monitor may catch the double-fault and halt execution without resetting the CPU.
Interrupt List
- 0 Invalid Instruction
- 1 Instruction Stack Underflow/Overflow
- 2 Data Stack Underflow/Overflow
- 3 User 1 (Timer)
- 4 User 2 (Keyboard)
- 5 User 3 (Disk)
- 6 User 4 (Network)
- 7 Invalid Memory Access
Instruction Encoding
All instructions are 16 bits wide.
For A-type instructions, the first 5 bits of the first byte is the instruction opcode and the final 3 bits of the first byte is the target register. The second byte specifies two operand registers encoded in each nibble. An operand register nibble higher than 7 will trigger an invalid instruction interrupt.
For I-type instructions, the first 5 bits of the first byte is the instruction opcode and the final 3 bits of the first byte is the target register. The second byte is an immediate operand.
For J-type instructions, the first 5 bits of the first byte is the instruction opcode and the final 3 bits are set to zero. A J-type instruction with the final 3 bits not set to zero will trigger an invalid instruction interrupt. The second byte is an immediate operand.
Opcode Listing
Below is a list of opcodes numbers, their types, their assembler mnemonic, and a description of their effect.
Only the low byte of register 8 is directly usable. Register 8's high byte can only be accessed by bit shifting.
- J 00 HLT — Halts program execution.
- I 01 OIO — Output I/O. The target register's value is sent to the I/O device specified by the operand.
- I 02 IIO — Input I/O. The target register is set to a value returned by the operand-specified I/O device.
- I 03 LDI — Load Immediate. The target register's value is replaced with the operand value.
- A 04 ADD — Add. The sum of the two operand registers' values is stored in the target register.
- A 05 SUB — Subtract. The first operand register's value is subtracted by the second operand register's value, and the result is written into the target register. Setting the first operand value to 0xFF allows for a ones-compliment NOT operation.
- I 06 ADI — Add Immediate. The operand value is added to the target register.
- A 07 AND — Logical AND. The target register's value is set to the logical AND of the two operand registers' values.
- A 08 BOR — Logical OR. The target register's value is set to the logical OR of the two operand registers' values.
- A 09 XOR — Logical XOR. The target register's value is set to the logical XOR of the two operand registers' values.
- A 10 SHL — Shift Left. The target register's value is set to the first operand register's value left shifted by a number of bits specified in the second operand register.
- A 11 SHR — Shift Right. The target register's value is set to the first operand register's value right shifted by a number of bits specified in the second operand register.
- A 12 SSR — Signed Shift Right. The target register's value is set to the first operand register's value right shifted by a number of bits specified in the second operand register. The first operand register's sign will be extended, rather than set directly to zero.
- A 13 BRO — Bit Rotate. The target register's value is set to the first operand register's value right-shift rotated by a number of bits specified in the second operand register. A number higher than 8 in the second operand register will left-rotate the first operand register's value.
- I 14 SPU — Stack Push. The target register's value is pushed to the internal data stack. A stack interrupt will be triggered if no space is left on the stack. The operand byte is ignored.
- I 15 SPO — Stack Pop. The target register's value is set to the topmost value in the internal stack, which is then removed. The operand byte is ignored.
- I 16 LSJ — Linked Short Jump. The next instruction's address is pushed to the internal return address stack, then the signed operand byte is added to the IP register.
- I 17 USJ — Unlinked Short Jump. The signed operand byte is added to the IP register without pushing a return address to the internal return address stack.
- J 18 LLJ — Linked Long Jump. The next instruction's address is pushed to the internal return address stack, then the IP register is set to register 8's value.
- I 19 CSJ — Conditional Short Jump. If the target register is not zero, the signed immediate operand is added to the IP register. A return address is not pushed to the return address stack.
- I 20 CLJ — Conditional Long Jump. If the target register is not zero, the IP register is set to the value of the 8th register. A return address is pushed to the return address stack.
- J 21 RET — Return. The topmost address from the return address stack is popped into the IP register.
- A 22 CLT — Condition, Less Than. If the first operand register has a lower value than the second operand register, the target register is set to 0x01. Otherwise, it is set to 0x00.
- A 23 CEQ — Condition, Equal. If the first operand register has an equal value to the second operand register, the target register is set to 0x01. Otherwise, it is set to 0x00.
- A 24 SVR — Save Register. The target register's value is saved to the address specified by the two operand registers. The first is the low byte, and the second is the high byte.
- A 25 LDR — Load Register. The target register's value is taken from data memory at the address specified by the two operand registers. The first is the low byte, the second is the high byte.
- J 26 IRE — Interrupt Return. The CPU leaves interrupt handling mode and execution resumes at the last instruction address plus one. An invalid instruction interrupt is triggered if this instruction is used outside of an interrupt handler.
- J 27-31 UNK — Reserved. An invalid instruction interrupt is triggered.