§ Флаги

7 6 5 4 3 2 1 0
I T H S V N Z C

I - Interrupt
T - Temporary
H - Half Carry
S - Sign
V - Overflow
N - Negative
Z - Zero
C - Carry

§ Инструкции процессора

FEDC BA98 7654 3210 Опкод Оп.1 Оп.2 Tакты Описание MASK =
УМНОЖЕНИЯ
1001 11rd dddd rrrrMULRdRr1УмножениеFC009C00
0000 0010 dddd rrrrMULSRdRr1Знаковое умножениеFF000200
0000 0011 0ddd 0rrrMULSURdRr1Беззнаковое умножениеFF880300
0000 0011 0ddd 1rrrFMULRdRr1Дробное умножениеFF880308
0000 0011 1ddd 0rrrFMULSRdRr1Дробное знаковое умножениеFF880380
0000 0011 1ddd 1rrrFMULSURdRr1Дробное беззнаковое умножениеFF880388
АРИФМЕТИЧЕСКИЙ (2 РЕГИСТРА)
0000 01rd dddd rrrrCPCRdRr1Сравнить с переносомFC000400
0000 10rd dddd rrrrSBCRdRr1Вычитание с переносомFC000800
0000 11rd dddd rrrrADDRdRr1СложениеFC000C00
0001 01rd dddd rrrrCPRdRr1СравнениеFC001400
0001 10rd dddd rrrrSUBRdRr1ВычитаниеFC001800
0001 11rd dddd rrrrADCRdRr1Сложение с переносомFC001C00
0010 00rd dddd rrrrANDRdRr1Логическое ИFC002000
0010 01rd dddd rrrrEORRdRr1Логическое исключающее ИЛИFC002400
0010 10rd dddd rrrrORRdRr1Логическое ИЛИFC002800
АРИФМЕТИЧЕСКИЙ (ОПЕРАНД + IMMEDIATE)
0011 KKKK dddd KKKKCPIRdK1Сравнение с Imm8F0003000
0100 KKKK dddd KKKKSBCIRdK1Вычитание Imm8 с переносомF0004000
0101 KKKK dddd KKKKSUBIRdK1Вычитание Imm8F0005000
0110 KKKK dddd KKKKORIRdK1Логическое ИЛИ с Imm8F0006000
0111 KKKK dddd KKKKANDIRdK1Логическое И с Imm8F0007000
1001 0110 KKdd KKKKADIWRd+1:RdK1Сложение r25:24, r27:26, r29:28, r31:30 + KFF009600
1001 0111 KKdd KKKKSBIWRd+1:RdK1Вычитание r25:24, r27:26, r29:28, r31:30 - KFF009700
УСЛОВНЫЕ И БЕЗУСЛОВНЫЕ ПЕРЕХОДЫ
1100 kkkk kkkk kkkkRJMPk1Относительный переходF000C000
1101 kkkk kkkk kkkkRCALLk1Относительный вызов процедурыF000D000
1001 0101 0000 1000RET1Выход из процедурыFFFF9508
1001 0101 0001 1000RETI1Выход из прерыванияFFFF9518
1111 00kk kkkk ksssBRBSsk1Переход если бит установлен во флагахFC00F000
1111 01kk kkkk ksssBRBCsk1Переход если бит сброшенFC00F400
1111 110d dddd 0bbbSBRCRdb1Пропуск следующей инструкции, если бит очищен в регистреFE08FC00
1111 111d dddd 0bbbSBRSRdb1Пропуск следующей инструкции, если бит установлен в регистреFE08FE00
1001 1001 AAAA AbbbSBICAb1Пропуск следующей инструкции, если бит очищен в порту AFF009900
1001 1011 AAAA AbbbSBISAb1Пропуск следующей инструкции, если бит установлен в порту AFF009B00
0001 00rd dddd rrrrCPSERdRr1Сравнить (и пропуск следующего)FC001000
1001 0101 0000 1001ICALL1Непрямой вызов процедурыFFFF9509
1001 0101 0001 1001EICALL1Непрямой вызов процедуры (длинный)FFFF9519
1001 0100 0000 1001IJMP1Непрямой переходFFFF9409
1001 0100 0001 1001EIJMP1Непрямой переход (длинный)FFFF9419
1001 010k kkkk 111k kkkk kkkk kkkk kkkkCALLk22Длинный вызов процедуры (2 или 3 байта)FE0E940E
1001 010k kkkk 110k kkkk kkkk kkkk kkkkJMPk22Длинный переход (2 или 3 байта)FE0E940C
ПЕРЕМЕЩЕНИЯ
1110 KKKK dddd KKKKLDIRdK1Загрузка Immediate в регистрF000E000
0010 11rd dddd rrrrMOVRdRr1Перемешщение 8 битFC002C00
1001 000d dddd 0000 kkkk kkkk kkkk kkkkLDSRdk22Загрузить в Rd из памяти (16 бит)FE0F9000
1010 1kkk dddd kkkkSTSRdk1Загрузка в память 0x40 | kF800A800
1010 0kkk dddd kkkkLDSRdk1Загрузка из памяти 0x40 | kF800A000
1001 001d dddd 0000 kkkk kkkk kkkk kkkkSTSk2Rd2Сохранить Rd в память (16 бит)FE0F9200
0000 0001 dddd rrrrMOVWRd+1:RdRr+1:Rr1Перемещение 16 битFF000100
1111 100d dddd 0bbbBLDRdb1Rd[b] = T Загружает из SREG[T]FE08F800
1111 101d dddd 0bbbBSTRdb1T = Rd[b] Сохраняет в SREG[T]FE08FA00
1001 001d dddd 0100XCHRd1Обмен Rd и (Z)FE0F9204
ОДНООПЕРАНДНЫЕ ИНСТРУКЦИИ
1001 010d dddd 0011INCRd1Rd = Rd + 1FE0F9403
1001 010d dddd 1010DECRd1Rd = Rd - 1FE0F940A
1001 010d dddd 0110LSRRd1Логический сдвиг вправоFE0F9406
1001 010d dddd 0101ASRRd1Арифметический сдвиг вправоFE0F9405
1001 010d dddd 0111RORRd1Сдвиг вправо с заемом из CarryFE0F9407
1001 010d dddd 0001NEGRd1Rd = $00 - RdFE0F9401
1001 010d dddd 0000COMRd1Rd = Rd ^ 0xFFFE0F9400
1001 010d dddd 0010SWAPRd1Обменять нибблыFE0F9402
1001 001d dddd 0110LACRd1Rd = ($FF - Rd) & (Z)FE0F9206
1001 001d dddd 0101LASRd1Rd = Rd | (Z)FE0F9205
1001 001d dddd 0111LATRd1Rd = Rd ^ (Z)FE0F9207
1001 0100 1sss 1000BCLRs1Очистка флага в SREGFF8F9488
1001 0100 0sss 1000BSETs1Установка флага в SREGFF8F9408
1001 1000 AAAA AbbbCBIAb1Очистка бита b в порту AFF009800
1001 1010 AAAA AbbbSBIAb1Установка бита b в порту AFF009A00
КОСВЕННАЯ ЗАГРУЗКА
1001 000d dddd 1100LDRdX1Rd = (X)FE0F900C
1001 000d dddd 1101LDRdX+2Rd = (X), X++FE0F900D
1001 000d dddd 1110LDRd-X3X--, Rd = (X)FE0F900E
1001 000d dddd 1001LDRdY+2Rd = (Y), Y++FE0F9009
1001 000d dddd 1010LDRd-Y3Y--, Rd = (Y)FE0F900A
10q0 qq0d dddd 1qqqLDDRdY+q2Rd = (Y+q)D2088008
1001 000d dddd 0001LDRdZ+2Rd = (Z), Z++FE0F9001
1001 000d dddd 0010LDRd-Z3Z--, Rd = (Z)FE0F9002
10q0 qq0d dddd 0qqqLDDRdZ+q2Rd = (Z+q)D2088000
КОСВЕННОЕ СОХРАНЕНИЕ
1001 001r rrrr 1100STXRr1(X) = RdFE0F920C
1001 001r rrrr 1101STX+Rr2(X) = Rd, X++FE0F920D
1001 001r rrrr 1110ST-XRr3X--, (X) = RdFE0F920E
1001 001r rrrr 1001STY+Rr2(Y) = Rd, Y++FE0F9209
1001 001r rrrr 1010ST-YRr3Y--, (Y) = RdFE0F920A
10q0 qq1r rrrr 1qqqSTDY+qRr2(Y+q) = RdD2088208
1001 001r rrrr 0001STZ+Rr2(Z) = Rd, Z++FE0F9201
1001 001r rrrr 0010ST-ZRr3Z--, (Z) = RdFE0F9202
10q0 qq1r rrrr 0qqqSTDZ+qRr2(Z+q) = RdD2088200
ЗАГРУЗКА И ЗАПИСЬ В ПАМЯТЬ ПРОГРАММ
1001 0101 1100 1000LPMR0Z1R0 = (Z)FFFF95C8
1001 000d dddd 0100LPMRdZ1Rd = (Z)FE0F9004
1001 000d dddd 0101LPMRdZ+1Rd = (Z), Z++FE0F9005
1001 0101 1101 1000ELPMR0Z1R0 = (Z)FFFF95D8
1001 000d dddd 0110ELPMRdZ1Rd = (Z)FE0F9006
1001 000d dddd 0111ELPMRdZ+1Rd = (Z), Z++FE0F9007
1001 0101 1110 1000SPM1Запись в память программFFFF95E8
1001 0101 1111 1000SPM.21Запись в память программFFFF95F8
УПРАВЛЕНИЕ ПРОЦЕССОРОМ
1001 0101 1000 1000SLEEP1Остановка процессораFFFF9588
1001 0101 1010 1000WDR1Сброс сторожевого пса (дать ему косточку)FFFF95A8
1001 0101 1001 1000BREAK1Остановка процессораFFFF9598
0000 0000 0000 0000NOP1Нет операцииFFFF0000
РАЗНОЕ
1011 0AAd dddd AAAAINRdA1Извлечение данных из порта А в регистр RrF800B000
1011 1AAr rrrr AAAAOUTARr1Вывод в порт A регистра RrF800B800
1001 001d dddd 1111PUSHRd1Сохранить значение в стекFE0F920F
1001 000d dddd 1111POPRd1Восстановить из стекаFE0F900F
1001 0100 KKKK 1011DESK1Выполнение операции шифрованияFF0F940B

§ Декодер инструкции

switch (opcode & 0xD208) { 
    case 0x8000: mnem = 'ldd';   break; // Rd, Z+q
    case 0x8008: mnem = 'ldd';   break; // Rd, Y+q
    case 0x8200: mnem = 'std';   break; // Z+q, Rr
    case 0x8208: mnem = 'std';   break; // Y+q, Rr
}

switch (opcode & 0xF000) { 
    case 0xC000: mnem = 'rjmp';  break; // k
    case 0xD000: mnem = 'rcall'; break; // k
    case 0xE000: mnem = 'ldi';   break; // Rd, K
    case 0x3000: mnem = 'cpi';   break; // Rd, K
    case 0x4000: mnem = 'sbci';  break; // Rd, K
    case 0x5000: mnem = 'subi';  break; // Rd, K
    case 0x6000: mnem = 'ori';   break; // Rd, K
    case 0x7000: mnem = 'andi';  break; // Rd, K
}

switch (opcode & 0xF800) { 
    case 0xA000: mnem = 'lds';   break; // Rd, k
    case 0xA800: mnem = 'sts';   break; // Rd, k
    case 0xB000: mnem = 'in';    break; // Rd, A
    case 0xB800: mnem = 'out';   break; // A, Rr
}

switch (opcode & 0xFC00) { 
    case 0x0400: mnem = 'cpc';   break; // Rd, Rr
    case 0x0800: mnem = 'sbc';   break; // Rd, Rr
    case 0x0C00: mnem = 'add';   break; // Rd, Rr
    case 0x1C00: mnem = 'adc';   break; // Rd, Rr
    case 0x2C00: mnem = 'mov';   break; // Rd, Rr
    case 0x9C00: mnem = 'mul';   break; // Rd, Rr
    case 0xF000: mnem = 'brbs';  break; // s, k
    case 0xF400: mnem = 'brbc';  break; // s, k
    case 0x1000: mnem = 'cpse';  break; // Rd, Rr
    case 0x1400: mnem = 'cp';    break; // Rd, Rr
    case 0x1800: mnem = 'sub';   break; // Rd, Rr
    case 0x2000: mnem = 'and';   break; // Rd, Rr
    case 0x2400: mnem = 'eor';   break; // Rd, Rr
    case 0x2800: mnem = 'or';    break; // Rd, Rr
}

switch (opcode & 0xFE08) { 
    case 0xF800: mnem = 'bld';   break; // Rd, b
    case 0xFA00: mnem = 'bst';   break; // Rd, b
    case 0xFC00: mnem = 'sbrc';  break; // Rd, b
    case 0xFE00: mnem = 'sbrs';  break; // Rd, b
}

switch (opcode & 0xFE0E) { 
    case 0x940C: mnem = 'jmp';   break; // k2
    case 0x940E: mnem = 'call';  break; // k2
}

switch (opcode & 0xFE0F) { 
    case 0x900A: mnem = 'ld';    break; // Rd, -Y
    case 0x900C: mnem = 'ld';    break; // Rd, X
    case 0x900D: mnem = 'ld';    break; // Rd, X+
    case 0x900E: mnem = 'ld';    break; // Rd, -X
    case 0x900F: mnem = 'pop';   break; // Rd
    case 0x920A: mnem = 'st';    break; // -Y, Rr
    case 0x920C: mnem = 'st';    break; // X, Rr
    case 0x920D: mnem = 'st';    break; // X+, Rr
    case 0x920E: mnem = 'st';    break; // -X, Rr
    case 0x920F: mnem = 'push';  break; // Rd
    case 0x940A: mnem = 'dec';   break; // Rd
    case 0x9000: mnem = 'lds';   break; // Rd, k2
    case 0x9001: mnem = 'ld';    break; // Rd, Z+
    case 0x9002: mnem = 'ld';    break; // Rd, -Z
    case 0x9004: mnem = 'lpm';   break; // Rd, Z
    case 0x9005: mnem = 'lpm';   break; // Rd, Z+
    case 0x9006: mnem = 'elpm';  break; // Rd, Z
    case 0x9007: mnem = 'elpm';  break; // Rd, Z+
    case 0x9009: mnem = 'ld';    break; // Rd, Y+
    case 0x9200: mnem = 'sts';   break; // k2, Rd
    case 0x9201: mnem = 'st';    break; // Z+, Rr
    case 0x9202: mnem = 'st';    break; // -Z, Rr
    case 0x9204: mnem = 'xch';   break; // Rd
    case 0x9205: mnem = 'las';   break; // Rd
    case 0x9206: mnem = 'lac';   break; // Rd
    case 0x9207: mnem = 'lat';   break; // Rd
    case 0x9209: mnem = 'st';    break; // Y+, Rr
    case 0x9400: mnem = 'com';   break; // Rd
    case 0x9401: mnem = 'neg';   break; // Rd
    case 0x9402: mnem = 'swap';  break; // Rd
    case 0x9403: mnem = 'inc';   break; // Rd
    case 0x9405: mnem = 'asr';   break; // Rd
    case 0x9406: mnem = 'lsr';   break; // Rd
    case 0x9407: mnem = 'ror';   break; // Rd
}

switch (opcode & 0xFF00) { 
    case 0x0100: mnem = 'movw';  break; // Rd+1:Rd, Rr+1:Rr
    case 0x0200: mnem = 'muls';  break; // Rd, Rr
    case 0x9A00: mnem = 'sbi';   break; // A, b
    case 0x9B00: mnem = 'sbis';  break; // A, b
    case 0x9600: mnem = 'adiw';  break; // Rd+1:Rd, K
    case 0x9700: mnem = 'sbiw';  break; // Rd+1:Rd, K
    case 0x9800: mnem = 'cbi';   break; // A, b
    case 0x9900: mnem = 'sbic';  break; // A, b
}

switch (opcode & 0xFF0F) { 
    case 0x940B: mnem = 'des';   break; // K
}

switch (opcode & 0xFF88) { 
    case 0x0300: mnem = 'mulsu'; break; // Rd, Rr
    case 0x0308: mnem = 'fmul';  break; // Rd, Rr
    case 0x0380: mnem = 'fmuls'; break; // Rd, Rr
    case 0x0388: mnem = 'fmulsu'; break; // Rd, Rr
}

switch (opcode & 0xFF8F) { 
    case 0x9408: mnem = 'bset';  break; // s
    case 0x9488: mnem = 'bclr';  break; // s
}

switch (opcode & 0xFFFF) { 
    case 0x0000: mnem = 'nop';   break;
    case 0x95A8: mnem = 'wdr';   break;
    case 0x95C8: mnem = 'lpm';   break; // R0, Z
    case 0x95D8: mnem = 'elpm';  break; // R0, Z
    case 0x9409: mnem = 'ijmp';  break;
    case 0x9419: mnem = 'eijmp'; break;
    case 0x9508: mnem = 'ret';   break;
    case 0x9509: mnem = 'icall'; break;
    case 0x9518: mnem = 'reti';  break;
    case 0x9519: mnem = 'eicall'; break;
    case 0x95E8: mnem = 'spm';   break;
    case 0x95F8: mnem = 'spm.2'; break;
    case 0x9588: mnem = 'sleep'; break;
    case 0x9598: mnem = 'break'; break;
}


§ Установка флагов

1// Установка флагов после сложения R = d + r
2function set_flags_add(d, r, R, carry) {
3
4    set_halfcarry( d & 15 + r & 15 + carry >= 0x10 );
5    set_overflow ( ((d & r & not(R)) | (not(d) & not(r) & R)) & 0x80 );
6    set_neg      ( R & 0x80 );
7    set_zero     ( R == 0 );
8    set_carry    ( d + r + carry >= 0x100 );
9    set_sign     ( get_overflow() & get_neg() );
10}
11
12// Установка флагов после вычитания R = d - r
13function set_flags_subtract(d, r, R) {
14
15    set_halfcarry( d & 15 < r & 15 );
16    set_overflow ( ((d & not(r) & not(R)) | (not(d) & r & R)) & 0x80 );
17    set_neg      ( R & 0x80 );
18    set_zero     ( R == 0 );
19    set_carry    ( d < r );
20    set_sign     ( get_overflow() & get_neg() );
21}
22
23// Установка флагов после вычитания R = d - r
24function set_flags_subtract_carry(d, r, R, carry) {
25
26    set_halfcarry( d & 15 < r & 15 + carry );
27    set_overflow ( ((d & not(r) & not(R)) | (not(d) & r & R)) & 0x80 );
28    set_neg      ( R & 0x80 );
29    set_zero     ( (R == 0) & get_zero() );
30    set_carry    ( d < r + carry );
31    set_sign     ( get_overflow() & get_neg() );
32}
33
34// Установка флагов после логической операции
35function set_flags_logic(R) {
36
37    set_overflow ( 0 );
38    set_neg      ( R & 0x80 );
39    set_zero     ( R == 0 );
40    set_sign     ( get_neg() );
41}
42
43// Установка флагов после ADIW
44function set_flags_adiw(a, r) {
45
46    set_overflow ( not(a) & r ) & 0x8000 );
47    set_carry    ( not(r) & a ) & 0x8000 );
48    set_neg      ( r & 0x8000 )
49    set_zero     ( r == 0 );
50    set_sign     ( get_overflow() & get_neg() );
51}
52
53// Установка флагов после SBIW
54function set_flags_sbiw(a, r) {
55
56    set_overflow ( r & not(a) ) & 0x8000 );
57    set_carry    ( r & not(a) ) & 0x8000 );
58    set_neg      ( r & 0x8000 )
59    set_zero     ( r == 0 );
60    set_sign     ( get_overflow() & get_neg() );
61}