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