Chapter 6: Instruction Encoding
This chapter is normative. It fixes the byte-level structure of an instruction: the opcode byte, the operand bytes, and the placement of immediate values.
6.1 Instruction shape
Instructions are variable-length. An instruction is:
- one opcode byte, then
- zero, one, two, or three operand bytes (one per operand), then
- for an immediate source operand, the immediate bytes, little-endian.
There are no other instruction components. The decoder reads the opcode byte, uses it to determine how many operand bytes and immediate bytes follow, and advances the program counter (RP) past the whole instruction. When an instruction has two parameters, the first is the source and the second is the destination. Three-operand instructions (LEA, CMPXCHG, MULW, UMULW, FMADD, FMSUB) name their operands in the order the instruction's entry in Chapter 7 gives.
6.2 The opcode byte
The opcode byte is two flag (mode) bits plus a six-bit base opcode:
%BBxx`xxxx bits 7,6 mode bits (Chapter 5 section 5.1)
%xxBB`BBBB bits 5..0 base opcode (0..63)
The six base-opcode bits give 64 base slots. Most instructions occupy one base slot and
use the two mode bits to select the addressing-mode form (regVal $0x, immVal $4x,
regAddr $8x, immAddr $Cx). Some families instead pack multiple register-only
micro-ops into one base slot using the two high bits as a "condition row" selector rather
than as addressing-mode bits:
- Condition families (Jcc, SETcc): the two high bits select the condition row and the
base slot selects the column; together
(row * 3 + col)indexes one shared predicate table (Chapter 7 section 7.6/7.7). - Row-packed unary families: for example base
$31packs INC ($31), DEC ($71), NOT ($B1), NEG ($F1); base$29packs SETINT / CLRINT / SETCRY / CLRCRY; base$27packs RET ($27), IRET ($67), NOP ($A7), with row 3 ($E7) reserved. (BRK is the standalone byte$FF, not a member of base$27.) The FP unary/min-max/convert families are row-packed the same way (Chapter 8).
Which interpretation applies is fixed per base slot by the instruction map (Appendix A); the decoder does not choose.
6.3 Operand bytes
Each operand is one byte (Chapter 5 sections 5.3, 5.4):
- A register operand byte is register nibble + subregister nibble (
$3E= R3.W0). - An immediate source operand byte carries the immediate width in its low three bits
(
$02= a 4-byte immediate follows).
An instruction with N operands has N operand bytes, in source-then-destination order (with the three-operand order per the instruction's entry).
6.4 Immediate placement
Immediate bytes follow the operand bytes, in little-endian order, in the width the source operand byte selected (1, 2, 4, or 8 bytes). Only a source operand can be an immediate; a destination is always a register or a memory address named by a register or immediate.
6.5 Worked example
CP $FFCC4411 R3 encodes as seven bytes:
$41 $02 $3E $11 $44 $CC $FF
| | | |
| | | +-- immediate $FFCC4411, little-endian (low byte first)
| | +-------- destination operand byte: R3 ($3) . W0 ($E)
| +-------------- source operand byte: immediate size $2 = 4 bytes
+-------------------- opcode: base $01, mode bit 6 set (immediate source) = "CP immVal reg"
The decoder reads $41, sees an immVal-form CP, reads the source operand byte $02 (a
4-byte immediate), reads the destination operand byte $3E, then reads the four immediate
bytes, and advances RP by seven. Because CP is narrower (32-bit immediate) than its
destination (R3.W0, 64-bit), the value is sign-extended (Chapter 5 section 5.6).
6.6 Decoded-but-undefined fields
Operand-field encodings split into two cases. The undefined immediate-size encoding
4..7 decodes to the value-initialized default and never traps (Chapter 5 section 5.4). The
undefined subregister selector $F, by contrast, is a deterministic illegal-operand
trap (cause 0; Chapter 3 section 3.3, Chapter 10). An undefined opcode byte is likewise
the illegal-instruction trap (cause 0). So an undefined opcode and an undefined subregister
both trap; only the undefined immediate-size field has a defined non-trapping default.
Sourcing
- Instruction shape and the source-then-destination order: README "Instruction Description".
- Opcode byte structure and the 64 base slots: README "Opcode Bytes";
src/maize_cpu.hopcode_flag*(lines 26-29) and the base-opcode constants;docs/spec/reservations.mdsection 1. - Row-packed / condition families:
src/maize_cpu.hcond_row_*and the Jcc/SETcc/unary constants (lines ~638-745);src/cpu.cppdecode_condition/eval_condition(lines ~775-800). - Immediate placement: README "Instruction Description" and "Immediate Parameter".