# How are processor instructions stored in RAM?

I've recently been designing a simple 8-bit microprocessor, similar to the Intel 8008. It doesn't make use of anything advanced as pipelining, as my knowledge isn't at that level yet to know how to implement it.

The address length of 14 bits, and an instruction lengths ranging from 1 to 3 bytes.

I've been researching, and I found that instructions generally span across multiple addresses in memory. For example, a 2 byte instruction could store the opcode-byte in one address, and a one-byte data value in the following.

However, when fetching an instruction from memory, does this mean that the processor has to make up to 3 memory calls just for the fetch stage?

Or, is there a different way to store the instructions to get around this? Just to note, my processor also doesn't use any caching, meaning it has to get instructions and data exclusively from RAM.

Also, how would this work for jump instructions? If I want to jump to a specific instruction in the program, but don't know the address in memory because of all the other multi-length instructions.

I would appreciate feedback on any of these questions.

• As far as I know, instructions are always stored contiguously in RAM. You can't know how many bytes to load before you have partially decoded the instruction, so per-byte fetches seem logical. Anyway, loading three bytes every time (and dropping the extraneous ones) might make sense if this speeds-up the memory access. Oct 10, 2022 at 11:24
• Regarding the jumps, well, you simply adjust the PC after you have computed the address. Anyway, in the case of conditional jumps not taken, you don't even have to compute the address. Oct 10, 2022 at 11:27

Some processors - generally, 32-bit RISC ones - make sure that all instructions fit in one location in memory. This works for them because 32 bits is enough to fit plenty of instructions, and it makes it easy for the processor to load instructions. All the instruction operands are included as part of the instruction. The instructions are often bigger than they need to be, but the simplicity can be worth it.

8-bit processors don't do this, because you can't really fit enough instructions in only 8 bits. You can only fit 256 instructions, in fact. If they have 4-bit operands (not enough) you can only fit 16 instructions (also not enough). So multi-byte instructions are a necessity.

However, 256 is plenty of opcodes. In the 8-bit era it was typical that a CPU would read a 1-byte opcode, and then the operands (if any) would be in the next 1 or 2 bytes.

Almost. You could do this. But 8-bit CPUs generally do not have 3-byte instruction registers. Instead, the instructions are designed so only the opcode needs to be stored in the opcode register is needed, and the operand bytes can go directly to their final destination. An instruction like ADD BC, 1234 might process the bytes like this:

1. load the MAR with the PC address, increment the PC, and load from memory into the opcode register
2. load the MAR with the PC address, increment the PC, load from memory into the ALU right input, load from register C into the ALU left input, set the ALU mode to ADD, store from the ALU output into register C
3. load the MAR with the PC address, increment the PC, load from memory into the ALU right input, load from register B into the ALU left input, set the ALU mode to ADC (add-with-carry), store from the ALU output into register B

To keep track of the steps, you might find it helpful to add a step counter "mini-register" which increments each cycle, except at the end of the instruction when it resets. Then you can use the opcode register and the step counter and combinational logic to select what the CPU should do in the current clock cycle. If you use a ROM chip instead of combinational logic, the contents of the ROM are called microcode.

For jump and call instructions specifically (with 16-bit addresses), the Z80 CPU uses an extra, hidden 16-bit register called WZ. Normally you would load 16 bits from memory into a register by loading one half, then the other half. But when you are loading into the program counter, you can't do this, because if you load the first half of the program counter then it messes up the address you load the second half from. So it loads the halves into WZ and then transfers WZ to PC.

To save having a WZ register, a different idea is to make the programmer load the address into a register, then jump to the address in the register. You can still have relative jumps (add an 8-bit value to the PC) and page-relative jumps (loading the lower 8 bits only) without needing any extra registers.

Also, how would this work for jump instructions? If I want to jump to a specific instruction in the program, but don't know the address in memory because of all the other multi-length instructions