1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
pub mod binary;

pub type Gpr = u8;
pub type GprPair = u8;
pub type Address = u32;
pub type RelativeAddress = u32;
pub type RelativeAddress7 = i8;

#[derive(Copy,Clone,Debug,PartialEq,Eq)]
pub enum Variant
{
    Normal,
    Predecrement,
    Postincrement,
}


/// An instruction.
#[derive(Copy,Clone,Debug,PartialEq,Eq)]
pub enum Instruction
{
    Inc(Gpr),
    Dec(Gpr),
    Com(Gpr),
    Neg(Gpr),
    Push(Gpr),
    Pop(Gpr),
    Swap(Gpr),

    Subi(Gpr, u8),
    Sbci(Gpr, u8),
    Andi(Gpr, u8),
    Ori(Gpr, u8),
    Cpi(Gpr, u8),
    Ldi(Gpr, u8),

    Add(Gpr, Gpr),
    Adc(Gpr, Gpr),
    Sub(Gpr, Gpr),
    Sbc(Gpr, Gpr),
    Mul(Gpr, Gpr),
    And(Gpr, Gpr),
    Or(Gpr, Gpr),
    Eor(Gpr, Gpr),
    Cpse(Gpr, Gpr),
    Cp(Gpr, Gpr),
    Cpc(Gpr, Gpr),
    Mov(Gpr, Gpr),
    Movw(GprPair, GprPair),

    In(Gpr, u8),
    Out(u8, Gpr),
    /// Set bit in IO register.
    Sbi(u8, u8),
    /// Clear bit in IO register.
    Cbi(u8, u8),

    Jmp(u32),
    Call(u32),
    Rjmp(i16),
    Rcall(i16),

    Brbs(u8, RelativeAddress7),
    Brbc(u8, RelativeAddress7),
    Breq(RelativeAddress7),
    Brne(RelativeAddress7),
    Brcs(RelativeAddress7),
    Brcc(RelativeAddress7),
    Brsh(RelativeAddress7),
    Brlo(RelativeAddress7),
    Brmi(RelativeAddress7),
    Brpl(RelativeAddress7),
    Brge(RelativeAddress7),
    Brlt(RelativeAddress7),
    Brhs(RelativeAddress7),
    Brhc(RelativeAddress7),
    Brts(RelativeAddress7),
    Brtc(RelativeAddress7),
    Brvs(RelativeAddress7),
    Brvc(RelativeAddress7),
    Brie(RelativeAddress7),
    Brid(RelativeAddress7),

    St(GprPair, Gpr, Variant),
    Ld(Gpr, GprPair, Variant),

    Std(GprPair, u8, Gpr),
    Ldd(Gpr, GprPair, u8),

    /// Load program memory.
    /// `GprPair` is always the `Z` register.
    /// The `bool` is whether to postincrement.
    Lpm(Gpr, GprPair, bool),

    Nop,
    Ret,
    Reti,
}

impl Instruction
{
    pub fn size(self) -> u8 {
        match self {
            Instruction::Jmp(..) => 4,
            Instruction::Call(..) => 4,
            _ => 2,
        }
    }

}