A simple register VM written in Rust
Your code was very readable and easy to follow. Most of my suggestions center around trying to showcase some more Rust idioms and features. 


A collection of registers in normally called a register file.
Since the constant for the number of registers is only used to declare the register file, create a type alias and use that. This sets you up nicely to make it a standalone type in the future.
I'm glad to see names for registers in Instruction, but maybe give them more meaningful names? Add is a great example - which registers are the inputs and which is the output?
You almost always want to derive Debug for a type. Copy and Clone are also very common. Implementing PartialEq will allow easier test writing.
There's a distinct lack of types and methods, overall the code feels pretty C-like. I'd associate functions with types, making them methods. For example, decode is the most obvious change to me.
Returning an Option from decode is iffy. Failing to decode an instruction doesn't seem like the absence of a value, it feels like a failure, which is normally reserved for Result.
When splitting match arms onto a different line from the pattern, use braces.
Consider inlining some of the instruction implementations into execute as many are only one line long anyway.
In a processor, it's very typical to automatically increment the program counter every instruction. Branch offsets take that automatic increment into account. This is nice here because it removes pc from all the non-branching methods. I just subtracted 1 when applying the jump, but it's probably better to fixup the offsets.
Create a type for sequences of instructions, I used Program. This will give you somewhere to hang fetch.




type RegisterFile = [u16; 3];

#[derive(Debug, Copy, Clone)]
enum Instruction {
    Halt,
    Load { reg: usize, value: u16 },
    Swap { reg1: usize, reg2: usize, reg3: usize },
    Add { reg1: usize, reg2: usize, reg3: usize },
    Branch { offset: usize }
}

impl Instruction {
    fn decode(encoded_instruction: u16) -&gt; Option&lt;Self&gt; {
        let operator = encoded_instruction &gt;&gt; 12;
        let reg1 = ((encoded_instruction &gt;&gt; 8) &amp; 0xF) as usize;
        let reg2 = ((encoded_instruction &gt;&gt; 4) &amp; 0xF) as usize;
        let reg3 = (encoded_instruction &amp; 0xF) as usize;
        let offset = (encoded_instruction &amp; 0xFFF) as usize;
        let value = encoded_instruction &amp; 0xFF;

        match operator {
            0 =&gt; Some(Instruction::Halt),
            1 =&gt; Some(Instruction::Load { reg: reg1, value: value }),
            2 =&gt; Some(Instruction::Swap { reg1: reg1, reg2: reg2, reg3: reg3 }),
            3 =&gt; Some(Instruction::Add { reg1: reg1, reg2: reg2, reg3: reg3 }),
            4 =&gt; Some(Instruction::Branch { offset: offset }),
            _ =&gt; None,
        }
    }

    fn execute(&amp;self, registers: &amp;mut [u16], pc: &amp;mut usize) -&gt; bool {
        match *self {
            Instruction::Load { reg, value } =&gt; {
                load(reg, value, registers);
            },
            Instruction::Swap { reg1, reg2, reg3 } =&gt; {
                swap(reg1, reg2, reg3, registers);
            },
            Instruction::Add { reg1, reg2, reg3 } =&gt; {
                add(reg1, reg2, reg3, registers);
            },
            Instruction::Branch { offset } =&gt; {
                branch(offset, pc);
            },
            Instruction::Halt =&gt; {
                halt(registers);
                return false;
            },
        }

        true
    }
}

fn halt(register_file: &amp;[u16]) {
    println!("{:?}", register_file[0]);
}

fn load(register: usize, value: u16, register_file: &amp;mut [u16]) {
    register_file[register] = value;
}

fn swap(reg1: usize, reg2: usize, reg3: usize, register_file: &amp;mut [u16]) {
    register_file[reg3] = register_file[reg1];
    register_file[reg1] = register_file[reg2];
    register_file[reg2] = register_file[reg3];
}

fn add(reg1: usize, reg2: usize, reg3: usize, register_file: &amp;mut [u16]) {
    register_file[reg3] = register_file[reg1] + register_file[reg2];
}

fn branch(offset: usize, pc: &amp;mut usize) {
    *pc -= offset - 1;
}

struct Program&lt;'a&gt; {
    instructions: &amp;'a [u16],
}

impl&lt;'a&gt; Program&lt;'a&gt; {
    fn fetch(&amp;self, pc: usize) -&gt; u16 {
        self.instructions[pc]
    }
}

fn cpu(program: Program) {
    let mut pc = 0;
    let mut registers = RegisterFile::default();

    loop {
        let encoded_instruction = program.fetch(pc);
        let decoded_instruction = Instruction::decode(encoded_instruction);

        match decoded_instruction {
            Some(instr) =&gt; {
                if !instr.execute(&amp;mut registers, &amp;mut pc) { break }
            }
            None =&gt; break,
        }

        pc += 1;
    }
}

fn main() {
    let encoded_instructions = Program { instructions: &amp;[0x1110, 0x2100, 0x3010, 0x0] };

    cpu(encoded_instructions);
}