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