💾 Archived View for envs.net › ~ae › gemlog › designing-simple-isa.gmi captured on 2024-07-09 at 00:50:59. Gemini links have been rewritten to link to archived content

View Raw

More Information

⬅️ Previous capture (2022-04-28)

-=-=-=-=-=-=-

Designing a simple processor architecture

Last edited: 04/12/2022

I've already mentioned this idea on my Mastodon account a while ago, but I feel like it's time to actually start working on it, now that I have very little schoolwork to do.

The main idea behind the project is to design a simple 16-bit RISC instruction set architecture that I will one day implement in hardware. Here are the design goals:

Base specs

So, with that in mind, here are the basic specification:

Basic ISA

The ISA is generally meant to be as simple as possible, with every instruction doing exclusively one thing. And by that, I mean /really/ only one thing: the only way to write constants into registers is the pl instruction, every other instruction only takes registers.

Here are the basic instructions (%W means word-sized register, %B means a byte-sized one, and $B and %W mean an integer constant):

Code  Mnemonic and usage      Encoding (in hex)               Action
-----------------------------------------------------------------------------------------------------------------------------------
00    nop                     00 00 00 00                     Nothing, it does nothing.
01    plw $W, %W              01 $---$ %W                     Place the constant into a word-sized register.
02    plb $B, %B              02 $ %B 00                     Place the constant into a byte-sized register.
03    stw %W, %W              03 %W %W 00                     Store the contents of the first register to the address in the other.
04    stb %B, %W              04 %B %B 00                     Same as above, but storing only a byte.
05    ldw %W, %W              05 %W %W 00                     Load a word from the address in the first register into the second.
06    ldb %W, %B              06 %W %B 00                     Same as above, but loading only a byte.
07    cpw %W, %W              07 %W %W 00                     Copy the contents of the first register into the second.
08    cpb %B, %B              08 %B %B 00                     Same as above, but copy an 8-bit register.
09    eqw %W, %W              09 %W %W 00                     Compare two words and set or unset the EQ flag.
0A    eqb %B, %B              0A %B %B 00                     Same as above, but with bytes.
0B    gtw %W, %W              0B %W %W 00                     Compare two words and set the GT flag if the first value is bigger.
0C    gtb %B, %B              0C %B %B 00                     Same as above, but with bytes.
0D    ltw %W, %W              0D %W %W 00                     Same as above, with words and the LT flag.
0E    ltb %B, %B              0E %B %B 00                     Same as above, with bytes.
0F    c0w %W                  0F %W 00 00                     Set the ZR flag if the register is all zeros.
10    c0b %B                  10 %B 00 00                     Same as above, but with bytes.
11    adw %W, %W              11 %W %W 00                     Add a word to another word, store the result in the second register.
12    adb %B, %B              12 %B %B 00                     Same as above, with bytes.
13    sbw %W, %W              13 %W %W 00                     Subtract the first value from the second, store the result in the second.
14    sbb %B, %B              14 %B %B 00                     The same thing with bytes.
15    skz                     15 00 00 00                     Skip the next instruction if ZR is set.
22    skn                     22 00 00 00                     Skip the next instruction if ZR is /not/ set.
16    skg                     16 00 00 00                     Skip the next instruction if GT is set.
17    skl                     17 00 00 00                     Skip the next instruction if LT is set.
18    skq                     18 00 00 00                     Skip the next instruction if EQ is set.
19    cns %W, %B, %B          19 %W %B %B                     Fill the word by concatenating the two bytes together (first byte goes first).
1A    rdl %W, %B              1A %W %B 00                     Read the first byte of the word into the register.
1B    rdh %W, %B              1B %W %B 00                     Same, but with the second byte.
1C    anw %W, %W              1C %W %W 00                     AND the two words together, store the result in the first.
1D    anb %B, %B              1D %B %B 00                     Same, with bytes.
1E    xow %W, %W              1E %W %W 00                     XOR the two words and store the result in the first.
1F    xob %B, %B              1F %B %B 00                     Same with bytes.
20    orw %W, %W              20 %W %W 00                     OR two words together, store the result in the first.
21    orb %B, %B              21 %B %B 00                     Same with bytes.
23    ngw %W                  23 %W 00 00                     Negate (bit by bit) the word.
24    ngb %B                  24 %B 00 00                     Same with bytes.

As you've probably noticed, there's no conditional jump. That's because there's no need for one: you can just use plw to set the ip to whatever you need.

Also, here's a table of the registers and flags:

The ID is decimal this time

ID Name
----------
00 ip
01 w1
02 w2
03 w3
...
14 w14
15 sp
16 b1
...
31 b15

Flags (one bit each):
LT: lesser than
GT: greater than
EQ: equal
ZR: zero
<unallocated>
<unallocated>
<unallocated>
<unallocated>

The unallocated bits may be used for any purpose.

Technically, the stack pointer is also just a general purpose register, but it gets a special name to help prevent chaos. It can be used as a general purpose register if you want, though.

Extra notes

Implementation

I'm still gonna work on this, it's not done yet. I promise I'll make it work soon-ish.