1 /*
2 * AVR disassembler
3 *
4 * Copyright (c) 2019-2020 Richard Henderson <rth@twiddle.net>
5 * Copyright (c) 2019-2020 Michael Rolnik <mrolnik@gmail.com>
6 *
7 * This program is free software: you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation, either version 2 of the License, or
10 * (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, see <http://www.gnu.org/licenses/>.
19 */
20
21 #include "qemu/osdep.h"
22 #include "cpu.h"
23
24 typedef struct {
25 disassemble_info *info;
26 uint16_t next_word;
27 bool next_word_used;
28 } DisasContext;
29
to_regs_16_31_by_one(DisasContext * ctx,int indx)30 static int to_regs_16_31_by_one(DisasContext *ctx, int indx)
31 {
32 return 16 + (indx % 16);
33 }
34
to_regs_16_23_by_one(DisasContext * ctx,int indx)35 static int to_regs_16_23_by_one(DisasContext *ctx, int indx)
36 {
37 return 16 + (indx % 8);
38 }
39
to_regs_24_30_by_two(DisasContext * ctx,int indx)40 static int to_regs_24_30_by_two(DisasContext *ctx, int indx)
41 {
42 return 24 + (indx % 4) * 2;
43 }
44
to_regs_00_30_by_two(DisasContext * ctx,int indx)45 static int to_regs_00_30_by_two(DisasContext *ctx, int indx)
46 {
47 return (indx % 16) * 2;
48 }
49
next_word(DisasContext * ctx)50 static uint16_t next_word(DisasContext *ctx)
51 {
52 ctx->next_word_used = true;
53 return ctx->next_word;
54 }
55
append_16(DisasContext * ctx,int x)56 static int append_16(DisasContext *ctx, int x)
57 {
58 return x << 16 | next_word(ctx);
59 }
60
61 /* Include the auto-generated decoder. */
62 static bool decode_insn(DisasContext *ctx, uint16_t insn);
63 #include "decode-insn.c.inc"
64
65 #define output(mnemonic, format, ...) \
66 (pctx->info->fprintf_func(pctx->info->stream, "%-9s " format, \
67 mnemonic, ##__VA_ARGS__))
68
avr_print_insn(bfd_vma addr,disassemble_info * info)69 int avr_print_insn(bfd_vma addr, disassemble_info *info)
70 {
71 DisasContext ctx = { info };
72 DisasContext *pctx = &ctx;
73 bfd_byte buffer[4];
74 uint16_t insn;
75 int status;
76
77 status = info->read_memory_func(addr, buffer, 2, info);
78 if (status != 0) {
79 info->memory_error_func(status, addr, info);
80 return -1;
81 }
82 insn = bfd_getl16(buffer);
83
84 status = info->read_memory_func(addr + 2, buffer + 2, 2, info);
85 if (status == 0) {
86 ctx.next_word = bfd_getl16(buffer + 2);
87 }
88
89 if (!decode_insn(&ctx, insn)) {
90 output(".db", "0x%02x, 0x%02x", buffer[0], buffer[1]);
91 }
92
93 if (!ctx.next_word_used) {
94 return 2;
95 } else if (status == 0) {
96 return 4;
97 }
98 info->memory_error_func(status, addr + 2, info);
99 return -1;
100 }
101
102
103 #define INSN(opcode, format, ...) \
104 static bool trans_##opcode(DisasContext *pctx, arg_##opcode * a) \
105 { \
106 output(#opcode, format, ##__VA_ARGS__); \
107 return true; \
108 }
109
110 #define INSN_MNEMONIC(opcode, mnemonic, format, ...) \
111 static bool trans_##opcode(DisasContext *pctx, arg_##opcode * a) \
112 { \
113 output(mnemonic, format, ##__VA_ARGS__); \
114 return true; \
115 }
116
117 /*
118 * C Z N V S H T I
119 * 0 1 2 3 4 5 6 7
120 */
121 static const char brbc[][5] = {
122 "BRCC", "BRNE", "BRPL", "BRVC", "BRGE", "BRHC", "BRTC", "BRID"
123 };
124
125 static const char brbs[][5] = {
126 "BRCS", "BREQ", "BRMI", "BRVS", "BRLT", "BRHS", "BRTS", "BRIE"
127 };
128
129 static const char bset[][4] = {
130 "SEC", "SEZ", "SEN", "SEZ", "SES", "SEH", "SET", "SEI"
131 };
132
133 static const char bclr[][4] = {
134 "CLC", "CLZ", "CLN", "CLZ", "CLS", "CLH", "CLT", "CLI"
135 };
136
137 /*
138 * Arithmetic Instructions
139 */
140 INSN(ADD, "r%d, r%d", a->rd, a->rr)
141 INSN(ADC, "r%d, r%d", a->rd, a->rr)
142 INSN(ADIW, "r%d:r%d, %d", a->rd + 1, a->rd, a->imm)
143 INSN(SUB, "r%d, r%d", a->rd, a->rr)
144 INSN(SUBI, "r%d, %d", a->rd, a->imm)
145 INSN(SBC, "r%d, r%d", a->rd, a->rr)
146 INSN(SBCI, "r%d, %d", a->rd, a->imm)
147 INSN(SBIW, "r%d:r%d, %d", a->rd + 1, a->rd, a->imm)
148 INSN(AND, "r%d, r%d", a->rd, a->rr)
149 INSN(ANDI, "r%d, %d", a->rd, a->imm)
150 INSN(OR, "r%d, r%d", a->rd, a->rr)
151 INSN(ORI, "r%d, %d", a->rd, a->imm)
152 INSN(EOR, "r%d, r%d", a->rd, a->rr)
153 INSN(COM, "r%d", a->rd)
154 INSN(NEG, "r%d", a->rd)
155 INSN(INC, "r%d", a->rd)
156 INSN(DEC, "r%d", a->rd)
157 INSN(MUL, "r%d, r%d", a->rd, a->rr)
158 INSN(MULS, "r%d, r%d", a->rd, a->rr)
159 INSN(MULSU, "r%d, r%d", a->rd, a->rr)
160 INSN(FMUL, "r%d, r%d", a->rd, a->rr)
161 INSN(FMULS, "r%d, r%d", a->rd, a->rr)
162 INSN(FMULSU, "r%d, r%d", a->rd, a->rr)
163 INSN(DES, "%d", a->imm)
164
165 /*
166 * Branch Instructions
167 */
168 INSN(RJMP, ".%+d", a->imm * 2)
169 INSN(IJMP, "")
170 INSN(EIJMP, "")
171 INSN(JMP, "0x%x", a->imm * 2)
172 INSN(RCALL, ".%+d", a->imm * 2)
173 INSN(ICALL, "")
174 INSN(EICALL, "")
175 INSN(CALL, "0x%x", a->imm * 2)
176 INSN(RET, "")
177 INSN(RETI, "")
178 INSN(CPSE, "r%d, r%d", a->rd, a->rr)
179 INSN(CP, "r%d, r%d", a->rd, a->rr)
180 INSN(CPC, "r%d, r%d", a->rd, a->rr)
181 INSN(CPI, "r%d, %d", a->rd, a->imm)
182 INSN(SBRC, "r%d, %d", a->rr, a->bit)
183 INSN(SBRS, "r%d, %d", a->rr, a->bit)
184 INSN(SBIC, "$%d, %d", a->reg, a->bit)
185 INSN(SBIS, "$%d, %d", a->reg, a->bit)
186 INSN_MNEMONIC(BRBS, brbs[a->bit], ".%+d", a->imm * 2)
187 INSN_MNEMONIC(BRBC, brbc[a->bit], ".%+d", a->imm * 2)
188
189 /*
190 * Data Transfer Instructions
191 */
192 INSN(MOV, "r%d, r%d", a->rd, a->rr)
193 INSN(MOVW, "r%d:r%d, r%d:r%d", a->rd + 1, a->rd, a->rr + 1, a->rr)
194 INSN(LDI, "r%d, %d", a->rd, a->imm)
195 INSN(LDS, "r%d, %d", a->rd, a->imm)
196 INSN(LDX1, "r%d, X", a->rd)
197 INSN(LDX2, "r%d, X+", a->rd)
198 INSN(LDX3, "r%d, -X", a->rd)
199 INSN(LDY2, "r%d, Y+", a->rd)
200 INSN(LDY3, "r%d, -Y", a->rd)
201 INSN(LDZ2, "r%d, Z+", a->rd)
202 INSN(LDZ3, "r%d, -Z", a->rd)
203 INSN(LDDY, "r%d, Y+%d", a->rd, a->imm)
204 INSN(LDDZ, "r%d, Z+%d", a->rd, a->imm)
205 INSN(STS, "%d, r%d", a->imm, a->rd)
206 INSN(STX1, "X, r%d", a->rr)
207 INSN(STX2, "X+, r%d", a->rr)
208 INSN(STX3, "-X, r%d", a->rr)
209 INSN(STY2, "Y+, r%d", a->rd)
210 INSN(STY3, "-Y, r%d", a->rd)
211 INSN(STZ2, "Z+, r%d", a->rd)
212 INSN(STZ3, "-Z, r%d", a->rd)
213 INSN(STDY, "Y+%d, r%d", a->imm, a->rd)
214 INSN(STDZ, "Z+%d, r%d", a->imm, a->rd)
215 INSN(LPM1, "")
216 INSN(LPM2, "r%d, Z", a->rd)
217 INSN(LPMX, "r%d, Z+", a->rd)
218 INSN(ELPM1, "")
219 INSN(ELPM2, "r%d, Z", a->rd)
220 INSN(ELPMX, "r%d, Z+", a->rd)
221 INSN(SPM, "")
222 INSN(SPMX, "Z+")
223 INSN(IN, "r%d, $%d", a->rd, a->imm)
224 INSN(OUT, "$%d, r%d", a->imm, a->rd)
225 INSN(PUSH, "r%d", a->rd)
226 INSN(POP, "r%d", a->rd)
227 INSN(XCH, "Z, r%d", a->rd)
228 INSN(LAC, "Z, r%d", a->rd)
229 INSN(LAS, "Z, r%d", a->rd)
230 INSN(LAT, "Z, r%d", a->rd)
231
232 /*
233 * Bit and Bit-test Instructions
234 */
235 INSN(LSR, "r%d", a->rd)
236 INSN(ROR, "r%d", a->rd)
237 INSN(ASR, "r%d", a->rd)
238 INSN(SWAP, "r%d", a->rd)
239 INSN(SBI, "$%d, %d", a->reg, a->bit)
240 INSN(CBI, "%d, %d", a->reg, a->bit)
241 INSN(BST, "r%d, %d", a->rd, a->bit)
242 INSN(BLD, "r%d, %d", a->rd, a->bit)
243 INSN_MNEMONIC(BSET, bset[a->bit], "")
244 INSN_MNEMONIC(BCLR, bclr[a->bit], "")
245
246 /*
247 * MCU Control Instructions
248 */
249 INSN(BREAK, "")
250 INSN(NOP, "")
251 INSN(SLEEP, "")
252 INSN(WDR, "")
253