1
votes

I am working on designing and implementing a simple 8-bit computer. I intend to have an 8-bit data bus, 8-bit address bus, and 8-bit instructions. I intend to have a RISC style load-store architecture. I am working on designing the instruction set, and am trying to determine if it is possible to have exclusively 8-bit instructions (meaning no multi-byte instructions).

If an instruction is 8-bits, some of those bit fields will be occupied by the opcode, and the remaining may be occupied by a representation of data to work on. For example, consider a load immediate instruction that takes an address and loads the contents of memory at that address into a specific register in the CPU. As the opcode for the load immediate instruction will occupy a couple bits, there is not room for a full 8-bit address in the instruction. For example, if the opcode for this instruction is '11' in binary, only 6 bits remain for the address to load from.

It seems to me the only option is to extend immediate type instructions to two bytes, where the first contains the opcode and the second contains the immediate value. Is there another way to do this? Perhaps there are other techniques?

1
There is no way to code a n-bits address in an n-bits instruction. In RISC architectures, the memory address for ld/st is in a 32 bits register and the instruction only codes an offset in an immediate (most of the time on 16 bits). But 8 bits is not enough to code all instructions in a processor. You should consider coding all instructions on 16 bits. In real 8 bits uP like the 8085 or 8051, instructions are variable length 1 to 3 bytes.Alain Merigot
You don't need a "load register from immediate address" opcode, you can trivially and inefficiently replace it with e.g. "reset register", "increment register", and "load register from address in register".that other guy
@thatotherguy: Or more typically, by supporting an addressing mode with a small immediate. e.g. MIPS's only addressing mode is disp16(reg) with 16 immediate bits. For small absolute addresses, you can use the zero register as the "base".Peter Cordes
@AlainMerigot: Closer examples to what the OP is designing are AVR: an 8-bit RISC microcontroller with 32x 8-bit registers, and 2-byte fixed-width instructions, and up to 16-bit memory addresses. microchip.com/webdoc/avrassembler/… shows the encodings. Or some toy ISAs like LC-3 What is happening in the diagram of LC3? - it has 15 opcodes, and only 8 registers so the instruction words need 4-bit opcodes and 3x 3-bit operand fields, or an immediate. (Non-destructive 3-operand ISA)Peter Cordes

1 Answers

2
votes

Are two-byte instructions necessary for an 8-bit instruction set architecture?

No, 2-byte instructions aren't strictly necessary. However without 2-byte instructions you need a lot more instructions to do the same work.

For example, if you can't do "mov r1,0x9F" (to load the 8-bit value into r1) because that requires an opcode plus an 8-bit immediate value, then you could work around it by joining multiple smaller immediate values together with a sequence like:

mov r1,0x9     ;4-bit opcode, 4-bit immediate, r1 = 0x09
shl r1,4       ;4-bit opcode, 4-bit immediate, r1 = 0x90
or r1,0x0F     ;4-bit opcode, 4-bit immediate; r1 = 0x9F

Of course this is awful (3 times as many instructions and 50% increase in code size compared to 2-byte instructions).

There are also other way to work around the problem.

One alternative is to have a "load immediate and shift left by 4" into a single instruction, or have a "load high bits with immediate" and "load low bits with immediate" instructions, so the example above might become:

load_high_bits r1,0x9     ;4-bit opcode, 4-bit immediate, r1 = 0x09
load_low_bits r1,0x0F     ;4-bit opcode, 4-bit immediate; r1 = 0x9F

Another alternative is to have a constant pool that can be accessed with smaller addresses. For example, if you have a "load constant" instruction that takes a 4-bit immediate value, then you could store 16 (8-bit) constants in memory and load them with something like load r1, [4_bit_offset]. You could also use an (implied?) base register to allow the constant pool to be at any address (so you can load constants from the address "8-bit base register + 4-bit offset"), like "load r1,[r2 + 4_bit_offset]".