1 /* 2 * vAVRdisasm - AVR program disassembler. 3 * Version 1.6 - February 2010. 4 * Written by Vanya A. Sergeev - <vsergeev@gmail.com> 5 * 6 * Copyright (C) 2007 Vanya A. Sergeev 7 * This program is free software; you can redistribute it and/or 8 * modify it under the terms of the GNU General Public License 9 * as published by the Free Software Foundation; either version 2 10 * of the License, or (at your option) any later version. 11 * 12 * This program is distributed in the hope that it will be useful, 13 * but WITHOUT ANY WARRANTY; without even the implied warranty of 14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 * GNU General Public License for more details. 16 * 17 * You should have received a copy of the GNU General Public License 18 * along with this program; if not, write to the Free Software 19 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. 20 * 21 * avrinstructionset.c - AVR instruction set data structure stored in an 22 * array of instruction info structures, as defined in avrdisasm.h. 23 * 24 */ 25 26 /* Sorted by number of operands so disassembler can find the most 27 * simplifed form of an instruction first. 28 * i.e. clr R16 instead of eor R16, R16 */ 29 /* I decided to have the operand masks and types here in the 30 * main instruction set data structure of the disassembler for clean 31 * opcode recognition and operand extraction. It's much more straight 32 * forward to work with numbers (duh) then manipulating ugly operand 33 * strings such as "000011rdddddrrrr" for the add instruction. */ 34 /* This was my first disassembler, and my program ended evolving with this 35 * data structure. Turns out it makes code quite clear, and it generalizes the 36 * entire disassembly process, but development probably took about 2x longer 37 * instead of hard coding the disassembly for different types of operands. */ 38 /* But this disassembler model can be applied to virtually any 16-bit 39 * or less opcode architecture, making it very flexible in nature--I don't 40 * have to rewrite all of the operand disassembly code for interpreting 41 * different r, d, K, k, s, etc. characters in the opcode, which all stand 42 * for a different operand type, because they are clearly written out 43 * in the instruction set data structure. 44 */ 45 46 instructionInfo instructionSet[AVR_TOTAL_INSTRUCTIONS] = { 47 {"break", 0x9598, 0, {0x0000, 0x0000}, {OPERAND_NONE, OPERAND_NONE}}, 48 {"clc", 0x9488, 0, {0x0000, 0x0000}, {OPERAND_NONE, OPERAND_NONE}}, 49 {"clh", 0x94d8, 0, {0x0000, 0x0000}, {OPERAND_NONE, OPERAND_NONE}}, 50 {"cli", 0x94f8, 0, {0x0000, 0x0000}, {OPERAND_NONE, OPERAND_NONE}}, 51 {"cln", 0x94a8, 0, {0x0000, 0x0000}, {OPERAND_NONE, OPERAND_NONE}}, 52 {"cls", 0x94c8, 0, {0x0000, 0x0000}, {OPERAND_NONE, OPERAND_NONE}}, 53 {"clt", 0x94e8, 0, {0x0000, 0x0000}, {OPERAND_NONE, OPERAND_NONE}}, 54 {"clv", 0x94b8, 0, {0x0000, 0x0000}, {OPERAND_NONE, OPERAND_NONE}}, 55 {"clz", 0x9498, 0, {0x0000, 0x0000}, {OPERAND_NONE, OPERAND_NONE}}, 56 {"eicall", 0x9519, 0, {0x0000, 0x0000}, {OPERAND_NONE, OPERAND_NONE}}, 57 {"eijmp", 0x9419, 0, {0x0000, 0x0000}, {OPERAND_NONE, OPERAND_NONE}}, 58 {"elpm", 0x95d8, 0, {0x0000, 0x0000}, {OPERAND_NONE, OPERAND_NONE}}, 59 {"icall", 0x9509, 0, {0x0000, 0x0000}, {OPERAND_NONE, OPERAND_NONE}}, 60 {"ijmp", 0x9409, 0, {0x0000, 0x0000}, {OPERAND_NONE, OPERAND_NONE}}, 61 {"lpm", 0x95c8, 0, {0x0000, 0x0000}, {OPERAND_NONE, OPERAND_NONE}}, 62 {"nop", 0x0000, 0, {0x0000, 0x0000}, {OPERAND_NONE, OPERAND_NONE}}, 63 {"ret", 0x9508, 0, {0x0000, 0x0000}, {OPERAND_NONE, OPERAND_NONE}}, 64 {"reti", 0x9518, 0, {0x0000, 0x0000}, {OPERAND_NONE, OPERAND_NONE}}, 65 {"sec", 0x9408, 0, {0x0000, 0x0000}, {OPERAND_NONE, OPERAND_NONE}}, 66 {"seh", 0x9458, 0, {0x0000, 0x0000}, {OPERAND_NONE, OPERAND_NONE}}, 67 {"sei", 0x9478, 0, {0x0000, 0x0000}, {OPERAND_NONE, OPERAND_NONE}}, 68 {"sen", 0x9428, 0, {0x0000, 0x0000}, {OPERAND_NONE, OPERAND_NONE}}, 69 {"ses", 0x9448, 0, {0x0000, 0x0000}, {OPERAND_NONE, OPERAND_NONE}}, 70 {"set", 0x9468, 0, {0x0000, 0x0000}, {OPERAND_NONE, OPERAND_NONE}}, 71 {"sev", 0x9438, 0, {0x0000, 0x0000}, {OPERAND_NONE, OPERAND_NONE}}, 72 {"sez", 0x9418, 0, {0x0000, 0x0000}, {OPERAND_NONE, OPERAND_NONE}}, 73 {"sleep", 0x9588, 0, {0x0000, 0x0000}, {OPERAND_NONE, OPERAND_NONE}}, 74 {"spm", 0x95e8, 0, {0x0000, 0x0000}, {OPERAND_NONE, OPERAND_NONE}}, 75 {"spm", 0x95f8, 1, {0x0000, 0x0000}, {OPERAND_ZP, OPERAND_NONE}}, 76 {"wdr", 0x95a8, 0, {0x0000, 0x0000}, {OPERAND_NONE, OPERAND_NONE}}, 77 {"des", 0x940b, 1, {0x00f0, 0x0000}, {OPERAND_DES_ROUND, OPERAND_NONE}}, 78 {"asr", 0x9405, 1, {0x01f0, 0x0000}, {OPERAND_REGISTER, OPERAND_NONE}}, 79 {"bclr", 0x9488, 1, {0x0070, 0x0000}, {OPERAND_BIT, OPERAND_NONE}}, 80 {"brcc", 0xf400, 1, {0x03f8, 0x0000}, {OPERAND_BRANCH_ADDRESS, OPERAND_NONE}}, 81 {"brcs", 0xf000, 1, {0x03f8, 0x0000}, {OPERAND_BRANCH_ADDRESS, OPERAND_NONE}}, 82 {"breq", 0xf001, 1, {0x03f8, 0x0000}, {OPERAND_BRANCH_ADDRESS, OPERAND_NONE}}, 83 {"brge", 0xf404, 1, {0x03f8, 0x0000}, {OPERAND_BRANCH_ADDRESS, OPERAND_NONE}}, 84 {"brhc", 0xf405, 1, {0x03f8, 0x0000}, {OPERAND_BRANCH_ADDRESS, OPERAND_NONE}}, 85 {"brhs", 0xf005, 1, {0x03f8, 0x0000}, {OPERAND_BRANCH_ADDRESS, OPERAND_NONE}}, 86 {"brid", 0xf407, 1, {0x03f8, 0x0000}, {OPERAND_BRANCH_ADDRESS, OPERAND_NONE}}, 87 {"brie", 0xf007, 1, {0x03f8, 0x0000}, {OPERAND_BRANCH_ADDRESS, OPERAND_NONE}}, 88 {"brlo", 0xf000, 1, {0x03f8, 0x0000}, {OPERAND_BRANCH_ADDRESS, OPERAND_NONE}}, 89 {"brlt", 0xf004, 1, {0x03f8, 0x0000}, {OPERAND_BRANCH_ADDRESS, OPERAND_NONE}}, 90 {"brmi", 0xf002, 1, {0x03f8, 0x0000}, {OPERAND_BRANCH_ADDRESS, OPERAND_NONE}}, 91 {"brne", 0xf401, 1, {0x03f8, 0x0000}, {OPERAND_BRANCH_ADDRESS, OPERAND_NONE}}, 92 {"brpl", 0xf402, 1, {0x03f8, 0x0000}, {OPERAND_BRANCH_ADDRESS, OPERAND_NONE}}, 93 {"brsh", 0xf400, 1, {0x03f8, 0x0000}, {OPERAND_BRANCH_ADDRESS, OPERAND_NONE}}, 94 {"brtc", 0xf406, 1, {0x03f8, 0x0000}, {OPERAND_BRANCH_ADDRESS, OPERAND_NONE}}, 95 {"brts", 0xf006, 1, {0x03f8, 0x0000}, {OPERAND_BRANCH_ADDRESS, OPERAND_NONE}}, 96 {"brvc", 0xf403, 1, {0x03f8, 0x0000}, {OPERAND_BRANCH_ADDRESS, OPERAND_NONE}}, 97 {"brvs", 0xf003, 1, {0x03f8, 0x0000}, {OPERAND_BRANCH_ADDRESS, OPERAND_NONE}}, 98 {"bset", 0x9408, 1, {0x0070, 0x0000}, {OPERAND_BIT, OPERAND_NONE}}, 99 {"call", 0x940e, 1, {0x01f1, 0x0000}, {OPERAND_LONG_ABSOLUTE_ADDRESS, OPERAND_NONE}}, 100 {"clr", 0x2400, 1, {0x01f0, 0x020f}, {OPERAND_REGISTER, OPERAND_REGISTER_GHOST}}, 101 {"com", 0x9400, 1, {0x01f0, 0x0000}, {OPERAND_REGISTER, OPERAND_NONE}}, 102 {"dec", 0x940a, 1, {0x01f0, 0x0000}, {OPERAND_REGISTER, OPERAND_NONE}}, 103 {"inc", 0x9403, 1, {0x01f0, 0x0000}, {OPERAND_REGISTER, OPERAND_NONE}}, 104 {"jmp", 0x940c, 1, {0x01f1, 0x0000}, {OPERAND_LONG_ABSOLUTE_ADDRESS, OPERAND_NONE}}, 105 {"lpm", 0x9004, 2, {0x01f0, 0x0000}, {OPERAND_REGISTER, OPERAND_Z}}, 106 {"lpm", 0x9005, 2, {0x01f0, 0x0000}, {OPERAND_REGISTER, OPERAND_ZP}}, 107 {"lsl", 0x0c00, 1, {0x01f0, 0x020f}, {OPERAND_REGISTER, OPERAND_REGISTER_GHOST}}, 108 {"lsr", 0x9406, 1, {0x01f0, 0x0000}, {OPERAND_REGISTER, OPERAND_NONE}}, 109 {"neg", 0x9401, 1, {0x01f0, 0x0000}, {OPERAND_REGISTER, OPERAND_NONE}}, 110 {"pop", 0x900f, 1, {0x01f0, 0x0000}, {OPERAND_REGISTER, OPERAND_NONE}}, 111 {"xch", 0x9204, 2, {0x0000, 0x01f0}, {OPERAND_Z, OPERAND_REGISTER}}, 112 {"las", 0x9205, 2, {0x0000, 0x01f0}, {OPERAND_Z, OPERAND_REGISTER}}, 113 {"lac", 0x9206, 2, {0x0000, 0x01f0}, {OPERAND_Z, OPERAND_REGISTER}}, 114 {"lat", 0x9207, 2, {0x0000, 0x01f0}, {OPERAND_Z, OPERAND_REGISTER}}, 115 {"push", 0x920f, 1, {0x01f0, 0x0000}, {OPERAND_REGISTER, OPERAND_NONE}}, 116 {"rcall", 0xd000, 1, {0x0fff, 0x0000}, {OPERAND_RELATIVE_ADDRESS, OPERAND_NONE}}, 117 {"rjmp", 0xc000, 1, {0x0fff, 0x0000}, {OPERAND_RELATIVE_ADDRESS, OPERAND_NONE}}, 118 {"rol", 0x1c00, 1, {0x01f0, 0x020f}, {OPERAND_REGISTER, OPERAND_REGISTER_GHOST}}, 119 {"ror", 0x9407, 1, {0x01f0, 0x0000}, {OPERAND_REGISTER, OPERAND_NONE}}, 120 {"ser", 0xef0f, 1, {0x00f0, 0x0000}, {OPERAND_REGISTER_STARTR16, OPERAND_NONE}}, 121 {"swap", 0x9402, 1, {0x01f0, 0x0000}, {OPERAND_REGISTER, OPERAND_NONE}}, 122 {"tst", 0x2000, 1, {0x01f0, 0x020f}, {OPERAND_REGISTER, OPERAND_REGISTER_GHOST}}, 123 124 {"adc", 0x1c00, 2, {0x01f0, 0x020f}, {OPERAND_REGISTER, OPERAND_REGISTER}}, 125 {"add", 0x0c00, 2, {0x01f0, 0x020f}, {OPERAND_REGISTER, OPERAND_REGISTER}}, 126 {"adiw", 0x9600, 2, {0x0030, 0x00cf}, {OPERAND_REGISTER_EVEN_PAIR_STARTR24, OPERAND_DATA}}, 127 {"and", 0x2000, 2, {0x01f0, 0x020f}, {OPERAND_REGISTER, OPERAND_REGISTER}}, 128 {"andi", 0x7000, 2, {0x00f0, 0x0f0f}, {OPERAND_REGISTER_STARTR16, OPERAND_DATA}}, 129 {"bld", 0xf800, 2, {0x01f0, 0x0007}, {OPERAND_REGISTER, OPERAND_BIT}}, 130 {"brbc", 0xf400, 2, {0x0007, 0x03f8}, {OPERAND_BIT, OPERAND_BRANCH_ADDRESS}}, 131 {"brbs", 0xf000, 2, {0x0007, 0x03f8}, {OPERAND_BIT, OPERAND_BRANCH_ADDRESS}}, 132 {"bst", 0xfa00, 2, {0x01f0, 0x0007}, {OPERAND_REGISTER, OPERAND_BIT}}, 133 {"cbi", 0x9800, 2, {0x00f8, 0x0007}, {OPERAND_IO_REGISTER, OPERAND_BIT}}, 134 {"cbr", 0x7000, 2, {0x00f0, 0x0f0f}, {OPERAND_REGISTER_STARTR16, OPERAND_COMPLEMENTED_DATA}}, 135 {"cp", 0x1400, 2, {0x01f0, 0x020f}, {OPERAND_REGISTER, OPERAND_REGISTER}}, 136 {"cpc", 0x0400, 2, {0x01f0, 0x020f}, {OPERAND_REGISTER, OPERAND_REGISTER}}, 137 {"cpi", 0x3000, 2, {0x00f0, 0x0f0f}, {OPERAND_REGISTER_STARTR16, OPERAND_DATA}}, 138 {"cpse", 0x1000, 2, {0x01f0, 0x020f}, {OPERAND_REGISTER, OPERAND_REGISTER}}, 139 {"elpm", 0x9006, 2, {0x01f0, 0x0000}, {OPERAND_REGISTER, OPERAND_Z}}, 140 {"elpm", 0x9007, 2, {0x01f0, 0x0000}, {OPERAND_REGISTER, OPERAND_ZP}}, 141 {"eor", 0x2400, 2, {0x01f0, 0x020f}, {OPERAND_REGISTER, OPERAND_REGISTER}}, 142 {"fmul", 0x0308, 2, {0x0070, 0x0007}, {OPERAND_REGISTER_STARTR16, OPERAND_REGISTER_STARTR16}}, 143 {"fmuls", 0x0380, 2, {0x0070, 0x0007}, {OPERAND_REGISTER_STARTR16, OPERAND_REGISTER_STARTR16}}, 144 {"fmulsu", 0x0388, 2, {0x0070, 0x0007}, {OPERAND_REGISTER_STARTR16, OPERAND_REGISTER_STARTR16}}, 145 {"in", 0xb000, 2, {0x01f0, 0x060f}, {OPERAND_REGISTER, OPERAND_DATA}}, 146 {"ld", 0x900c, 2, {0x01f0, 0x0000}, {OPERAND_REGISTER, OPERAND_X}}, 147 {"ld", 0x900d, 2, {0x01f0, 0x0000}, {OPERAND_REGISTER, OPERAND_XP}}, 148 {"ld", 0x900e, 2, {0x01f0, 0x0000}, {OPERAND_REGISTER, OPERAND_MX}}, 149 {"ld", 0x8008, 2, {0x01f0, 0x0000}, {OPERAND_REGISTER, OPERAND_Y}}, 150 {"ld", 0x9009, 2, {0x01f0, 0x0000}, {OPERAND_REGISTER, OPERAND_YP}}, 151 {"ld", 0x900a, 2, {0x01f0, 0x0000}, {OPERAND_REGISTER, OPERAND_MY}}, 152 {"ld", 0x8000, 2, {0x01f0, 0x0000}, {OPERAND_REGISTER, OPERAND_Z}}, 153 {"ld", 0x9001, 2, {0x01f0, 0x0000}, {OPERAND_REGISTER, OPERAND_ZP}}, 154 {"ld", 0x9002, 2, {0x01f0, 0x0000}, {OPERAND_REGISTER, OPERAND_MZ}}, 155 {"ldd", 0x8008, 2, {0x01f0, 0x2c07}, {OPERAND_REGISTER, OPERAND_YPQ}}, 156 {"ldd", 0x8000, 2, {0x01f0, 0x2c07}, {OPERAND_REGISTER, OPERAND_ZPQ}}, 157 {"ldi", 0xe000, 2, {0x00f0, 0x0f0f}, {OPERAND_REGISTER_STARTR16, OPERAND_DATA}}, 158 {"std", 0x8208, 2, {0x2c07, 0x01f0}, {OPERAND_YPQ, OPERAND_REGISTER}}, 159 {"std", 0x8200, 2, {0x2c07, 0x01f0}, {OPERAND_ZPQ, OPERAND_REGISTER}}, 160 {"lds", 0x9000, 2, {0x01f0, 0x0000}, {OPERAND_REGISTER, OPERAND_LONG_ABSOLUTE_ADDRESS}}, 161 {"lds", 0xA000, 2, {0x00f0, 0x070f}, {OPERAND_REGISTER_STARTR16, OPERAND_DATA}}, 162 {"mov", 0x2c00, 2, {0x01f0, 0x020f}, {OPERAND_REGISTER, OPERAND_REGISTER}}, 163 {"movw", 0x0100, 2, {0x00f0, 0x000f}, {OPERAND_REGISTER_EVEN_PAIR, OPERAND_REGISTER_EVEN_PAIR}}, 164 {"mul", 0x9c00, 2, {0x01f0, 0x020f}, {OPERAND_REGISTER, OPERAND_REGISTER}}, 165 {"muls", 0x0200, 2, {0x00f0, 0x000f}, {OPERAND_REGISTER_STARTR16, OPERAND_REGISTER_STARTR16}}, 166 {"mulsu", 0x0300, 2, {0x0070, 0x0007}, {OPERAND_REGISTER_STARTR16, OPERAND_REGISTER_STARTR16}}, 167 {"or", 0x2800, 2, {0x01f0, 0x020f}, {OPERAND_REGISTER, OPERAND_REGISTER}}, 168 {"ori", 0x6000, 2, {0x00f0, 0x0f0f}, {OPERAND_REGISTER_STARTR16, OPERAND_DATA}}, 169 {"out", 0xb800, 2, {0x060f, 0x01f0}, {OPERAND_IO_REGISTER, OPERAND_REGISTER}}, 170 {"sbc", 0x0800, 2, {0x01f0, 0x020f}, {OPERAND_REGISTER, OPERAND_REGISTER}}, 171 {"sbci", 0x4000, 2, {0x00f0, 0x0f0f}, {OPERAND_REGISTER_STARTR16, OPERAND_DATA}}, 172 {"sbi", 0x9a00, 2, {0x00f8, 0x0007}, {OPERAND_IO_REGISTER, OPERAND_BIT}}, 173 {"sbic", 0x9900, 2, {0x00f8, 0x0007}, {OPERAND_IO_REGISTER, OPERAND_BIT}}, 174 {"sbis", 0x9b00, 2, {0x00f8, 0x0007}, {OPERAND_IO_REGISTER, OPERAND_BIT}}, 175 {"sbiw", 0x9700, 2, {0x0030, 0x00cf}, {OPERAND_REGISTER_EVEN_PAIR_STARTR24, OPERAND_DATA}}, 176 {"sbr", 0x6000, 2, {0x00f0, 0x0f0f}, {OPERAND_REGISTER_STARTR16, OPERAND_DATA}}, 177 {"sbrc", 0xfc00, 2, {0x01f0, 0x0007}, {OPERAND_REGISTER, OPERAND_BIT}}, 178 {"sbrs", 0xfe00, 2, {0x01f0, 0x0007}, {OPERAND_REGISTER, OPERAND_BIT}}, 179 {"st", 0x920c, 2, {0x0000, 0x01f0}, {OPERAND_X, OPERAND_REGISTER}}, 180 {"st", 0x920d, 2, {0x0000, 0x01f0}, {OPERAND_XP, OPERAND_REGISTER}}, 181 {"st", 0x920e, 2, {0x0000, 0x01f0}, {OPERAND_MX, OPERAND_REGISTER}}, 182 {"st", 0x8208, 2, {0x0000, 0x01f0}, {OPERAND_Y, OPERAND_REGISTER}}, 183 {"st", 0x9209, 2, {0x0000, 0x01f0}, {OPERAND_YP, OPERAND_REGISTER}}, 184 {"st", 0x920a, 2, {0x0000, 0x01f0}, {OPERAND_MY, OPERAND_REGISTER}}, 185 {"st", 0x8200, 2, {0x0000, 0x01f0}, {OPERAND_Z, OPERAND_REGISTER}}, 186 {"st", 0x9201, 2, {0x0000, 0x01f0}, {OPERAND_ZP, OPERAND_REGISTER}}, 187 {"st", 0x9202, 2, {0x0000, 0x01f0}, {OPERAND_MZ, OPERAND_REGISTER}}, 188 {"sts", 0x9200, 2, {0x0000, 0x01f0}, {OPERAND_LONG_ABSOLUTE_ADDRESS, OPERAND_REGISTER}}, 189 {"sts", 0xA800, 2, {0x00f0, 0x070f}, {OPERAND_DATA, OPERAND_REGISTER_STARTR16}}, // was {OPERAND_REGISTER_STARTR16, OPERAND_DATA}, bug? 190 {"sub", 0x1800, 2, {0x01f0, 0x020f}, {OPERAND_REGISTER, OPERAND_REGISTER}}, 191 {"subi", 0x5000, 2, {0x00f0, 0x0f0f}, {OPERAND_REGISTER_STARTR16, OPERAND_DATA}}, 192 {".word", 0x0000, 1, {0xFFFF, 0x0000}, {OPERAND_WORD_DATA, OPERAND_NONE}}, 193 }; 194