# My Computer Architecture

This is a WIP of my own ISA.

## General

The architecture is:

- RISC
- purely load/store
- 8 bit with 16 bit addressing (the amount of memory available is dependent on implementation)
- non-constant CPI (instructions take variable number of clock cycles to execute)
- purely Von Neumann (instructions and data in the same memory)
- memory mapped I/O
- for multiple-byte values little endian is used
- no CPU modes, memory protection and similar BS
- no interrupts
- ascending stack

## Registers

There are 12 8 bit registers: R0 to R11 (corresponding to numbers 0 to 11). Some registers for pairs which are denoted as RX:RY where RX is the register storing the upper 8 bits and RY register storing the lower 8 bits.

- R0 - R4: general purpose registers
- R5 = FL: flag register, starting with LSB:
  - x: reserved
  - x: reserved
  - x: reserved
  - x: reserved
  - x: reserved
  - Z (zero): set by operations if the result was 0
  - C (carry): is set by addition and similar instructions on over flow.
  - T (test): is set by test operations, affect conditional jumps.
- R6:R7 = AP: addressing pointer
- R8:R9 = SP: stack pointer
- R10:R11 = IP: instruction pointer

## Operation

Upon start/reset the computer clears all registers to 0 except for IP which is set to 2. Instructions then start to be executed until either halting instruction is encountered, in which cases the computer sets the corresponding exit code and then stops executing instructions.

The stack pointer should be initialized by the program, typically as one of the first operations.

During execution of instruction X IP will contain the address of instruction X. The instruction itself may or may not modify the value of IP. When execution of X has finished, IP is incremented by 2.

As long as the computer is running the clock tick counter (see memory layout) is incremented after every clock tick (note that execution of one instruction may take more than one clock tick).

## Instruction Set

The instruction size is fixed at 16 bits. The first 8 bits are the opcode, the following 8 bits hold the arguments.

Instruction arguments are always numerical. Bits that aren't used for arguments should always be 0 and bits used for arguments may only contain allowed values, otherwise the instruction may be considered malformed.

In the following table argument are specified from the LSB with the number of bits in the brackets.

| abbr. | name                 | opcode | arguments | description                           | flags |
| ----- | -------------------- | ------ | --------- | ------------------------------------- | ----- |
|       |                      |        |           | **ARITHMETIC**                        |       |
| ADD   | add                  |        |r1(4) r2(4)| CLC; ADD r1 r2                        | CZ    |
| ADC   | add with carry       |        |r1(4) r2(4)| r1 := r1 + r2 + FL[C];                | CZ    |
| SUB   | substract            |        |r1(4) r2(4)| NEG r2; ADD r1 r2                     | CZ    |
| SUC   | substract with carry |        |r1(4) r2(4)| NEG r2; ADC r1 r2                     | CZ    |
| NEG   | arithmetic neg.      |        | r(4)      | r := -r (two's complement)            | Z     |
| MUL   | multiply             |        |           |                                       |       |
| INC   | increment            |        | r(4)      |                                       | CZ    |
| DEC   | decrement            |        | r(4)      |                                       | CZ    |
| ADI   | add immediate        |        | n(8)      | r1 := r1 + n; FL[C] = carry           | CZ    |
| SUI   | substract immediate  |        | n(8)      | r1 := r1 + neg(n); FL[C] = carry      | CZ    |
|       |                      |        |           | **LOGIC**                             |       |
| ORR   | bitwise OR           |        |           |                                       | Z     |
| AND   | bitwise AND          |        |           |                                       | Z     |
| XOR   | bitwise XOR          |        |           |                                       | Z     |
| NOT   | bitwise NOT          |        | r(4)      | r := bitwise_not(r)                   | Z     |
| TOL   | to logical value     |        |r1(4) r2(4)|r1 := 1 if r2 != 0 else 0              | Z     |
|       |                      |        |           | **MEMORY**                            |       |          
| LDM   | load from memory     |00000010| r(4)      | r := mem[AP]                          |       |
| STM   | store to memory      |00000011| r(4)      | mem[AP] := r                          |       |
| PSH   | push onto stack      |00000010| r(4)      | mem[SP] := r; SP++                    |       |
| POP   | pop from stack       |00000011| r(4)      | r := mem[SP]; SP--                    |       |
| LI0   | load immediate to R0 |        | v(8)      | R0 := v                               |       |
| LI1   | load immediate to R1 |        | v(8)      | R1 := v                               |       |
| MOV   | move                 |00000001|r1(4) r2(4)| r1 := r2                              |       |
| BST   | set bit              |        |r(4) b(3)  | r[b] := 1                             | Z     |
| BCL   | clear bit            |        |r(4) b(3)  | r[b] := 0                             | Z     |
| BNO   | negate bit           |        |r(4) b(3)  | r[b] := not(r[b])                     | Z     |
|       |                      |        |           | **TESTS**                             |       |
| TST   | test bit             |        |r(4) b(3)  | FL[T] := r[b]                         | T     |
| LUU   |compare less uns. uns.|        |           |                                       | T     |
| LUS   |compare less uns. sig.|        |           |                                       | T     |
| LSS   |compare less sig. sig.|        |           |                                       | T     |
| EQU   | equals               |        |r1(4) r2(4)| FL[T] := R1 == R2                     | T     |
|       |                      |        |           | **OTHER**                             |       |
| SR0   | shift right 0        |        |           |                                       | CZ    |
| SRC   | shift right copy     |        |           |                                       | CZ    |
| SL0   | shift left 0         |        |           |r := r << n (LSB := 0); FL[C] := r[MSB]| CZ    |
| SLC   | shift left copy      |        |           |r := r << n (keep LSB); FL[C] := r[MSB]| CZ    |
| SWP   | swap                 |        |r1(4) r2(4)| swap(r1,r2)                           |       |
|       |                      |        |           | **CONTROL**                           |       |
| JIF   | jump if              |        |           | if (FL[T]) IP := AP - 2               |       |
| JIN   | jump if not          |        |           | if (!FL[T]) IP := AP - 2              |       |
| SIF   | skip if              |        | n(8)      | if (FL[T]) IP := IP + offset(n)       |       |
| SIN   | skip if              |        | n(8)      | if (!FL[T]) IP := IP + offset(n)      |       | 
| END   | end                  |11111111|           |                                       |       |
| NOP   | no operation         |00000000|           | do nothing, waste a cycle             |       |

offset(n) = 2 * (n <= 127 ? n + 1 : n - 256)

pseudo instructions:

| abbr. | parameter | name                 | definition                      |
| ----- | --------- | -------------------- | ------------------------------- |
| JMP   |           | jump                 | MOV 10 6; MOV 11 7              |
| CLC   |           | clear carry          | BLC 5 6                         |

TODO: instructions have to be aligned???

## Memory

The memory model is Von Neumann (same memory for data and program instructions). Memory also serves for I/O mapping.

Every byte has access priviledges, R (reading allowed), W (writing allowed), RW (both reading and writing allowed) or none (inaccessible). Violating the priviledge results in program halting immediately and corresponding exit code being set.

The memory layout follows:

| addresses (hex) | type | description                                                                        |
| --------------- | ---- | ---------------------------------------------------------------------------------- |
| 0000            |      | NULL address, inaccessible, allows definition of NULL pointer to be 0.             |
| 0001            |      | Unusable, exists to make instructions word-aligned.                                |
| 0002            | RW   | Start of program instructions.                                                     |
| PRG_END         | RW   | Last program instruction (has to be END), this is program-specific.                |
|                 | RW   | Stack memory.                                                                      |
| STACK_END       | RW   | Highest possible stack address (configurable).                                     |
|                 | RW   | Program working memory                                                             |
| MEM_END         | RW   | Highest address of a continuous RW block since 0001, platform specific.            |
|                 |      | SPECIAL MEMORY FOLLOWS (available regardless of memory amount)                     |
| ff00 ... ff7f   | ???  | Platform-specific (including priviledges) I/O mapped ports.                        |
|                 |      | Reserved.                                                                          |
| fff9 fffa       | WR   | STACK_END, if R12:R13 == this number, program halts. Can be 0 (unlimited stack).   |
| fffb fffc       | R    | RAM amount, contains the number MEM_END.                                           |
| fffd fffe       | R    | Tick count, counts (with overflow) clock ticks since program start.                |
| ffff            | R    | After program contains the exit code (see below).                                  |

TODO: STACK???

Exits codes (at least the values 0xff and 0x00 have to be implemented):

- 0x00: No error, program ended normally with the END instruction.
- 0x01: Read from inaccessible memory address error.
- 0x02: Write to inaccessible or read-only memory address error.
- 0x03: Invalid instruction encountered.
- 0x04: Stack overflow.
- 0xff: Error without further specified details.

# Assembler