Instruction Set Architecture

ISA is the most important. Caches and extra circuitry can be added onto a processor later. But the ISA can seldom be changed after the CPU is done being made.

Why can’t we just have all the instructions we want on a chip?

  1. There is finite room on the chip. Designers are given a finite number of transistors to work with. The 8086 had a budget of 30 thousand transistors. the Apple M@ has 134 billion.
  2. The more transistors you buy, the more expensive the chip is.
  3. If you throw in everything, you’re adding a bunch of useless stuff, and by definition that means you can’t add as much stuff later. So it’s hard to extend.
  4. You have to have legacy support. Once you make a decision, later down the road chagning that decision is hard. People have to live with it.
  5. too complex

As usual, you want to start with something very simple and expand it later as needed. This is the same with math proofs, and the same with software.

The efficiency of your programs largely depends on the instructions that they use.

The size of individual cpu instructions is dependent on the total number of instructions that the cpu supports.

You can in general only have instructions that match the smallest unit that the bus can get, or a multiple of 8. So on an intel machine, you might have instructions that are 8 bits, 16 bits, 32 bits, etc. On ARM machines, since RISC, they only allow instructions in 32 or 64 bit lengths(all instructions must be the same size).

There are benefits and costs to each approach. Using variable length is harder to decode, but you can save some memory for example. This does mean though that a few bits have to be saved just to explain the length of the instruction.

It’s much easier to add instructions later than to remove them. So make a MVP type thing, keeping the instructions simple. Save some room for expansion later.

The process for designing an instruction set is something like:

  1. Look at sillicon budget, decide between variable and fixed length instructions
  2. Reserve some of the space you have left for future instructions
  3. Implement basic instructions that are required like movs, add, sub, etc. This includes jumps and conditional jumps as well as io.
  4. Assign op codes using a structure that makes sense. Group instructions that are similar together. The way you do this is part of the art.

The rest of the chapter is dedicated to putting this theory into practice designing a small ISA. Not as useful as the assembly book to read after. It also dives into 8086 instruction encodings, which I can review in depth while programming assembly.