4 * Copyright (c) 2019-2020 Richard Henderson <rth@twiddle.net>
5 * Copyright (c) 2019-2020 Michael Rolnik <mrolnik@gmail.com>
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.
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.
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/>.
21 #include "qemu/osdep.h"
25 disassemble_info
*info
;
30 static int to_regs_16_31_by_one(DisasContext
*ctx
, int indx
)
32 return 16 + (indx
% 16);
35 static int to_regs_16_23_by_one(DisasContext
*ctx
, int indx
)
37 return 16 + (indx
% 8);
40 static int to_regs_24_30_by_two(DisasContext
*ctx
, int indx
)
42 return 24 + (indx
% 4) * 2;
45 static int to_regs_00_30_by_two(DisasContext
*ctx
, int indx
)
47 return (indx
% 16) * 2;
50 static uint16_t next_word(DisasContext
*ctx
)
52 ctx
->next_word_used
= true;
53 return ctx
->next_word
;
56 static int append_16(DisasContext
*ctx
, int x
)
58 return x
<< 16 | next_word(ctx
);
61 /* Include the auto-generated decoder. */
62 static bool decode_insn(DisasContext
*ctx
, uint16_t insn
);
63 #include "decode-insn.c.inc"
65 #define output(mnemonic, format, ...) \
66 (pctx->info->fprintf_func(pctx->info->stream, "%-9s " format, \
67 mnemonic, ##__VA_ARGS__))
69 int avr_print_insn(bfd_vma addr
, disassemble_info
*info
)
72 DisasContext
*pctx
= &ctx
;
79 status
= info
->read_memory_func(addr
, buffer
, 4, info
);
81 info
->memory_error_func(status
, addr
, info
);
84 insn
= bfd_getl16(buffer
);
85 ctx
.next_word
= bfd_getl16(buffer
+ 2);
86 ctx
.next_word_used
= false;
88 if (!decode_insn(&ctx
, insn
)) {
89 output(".db", "0x%02x, 0x%02x", buffer
[0], buffer
[1]);
92 return ctx
.next_word_used
? 4 : 2;
96 #define INSN(opcode, format, ...) \
97 static bool trans_##opcode(DisasContext *pctx, arg_##opcode * a) \
99 output(#opcode, format, ##__VA_ARGS__); \
103 #define INSN_MNEMONIC(opcode, mnemonic, format, ...) \
104 static bool trans_##opcode(DisasContext *pctx, arg_##opcode * a) \
106 output(mnemonic, format, ##__VA_ARGS__); \
114 static const char brbc
[][5] = {
115 "BRCC", "BRNE", "BRPL", "BRVC", "BRGE", "BRHC", "BRTC", "BRID"
118 static const char brbs
[][5] = {
119 "BRCS", "BREQ", "BRMI", "BRVS", "BRLT", "BRHS", "BRTS", "BRIE"
122 static const char bset
[][4] = {
123 "SEC", "SEZ", "SEN", "SEZ", "SES", "SEH", "SET", "SEI"
126 static const char bclr
[][4] = {
127 "CLC", "CLZ", "CLN", "CLZ", "CLS", "CLH", "CLT", "CLI"
131 * Arithmetic Instructions
133 INSN(ADD
, "r%d, r%d", a
->rd
, a
->rr
)
134 INSN(ADC
, "r%d, r%d", a
->rd
, a
->rr
)
135 INSN(ADIW
, "r%d:r%d, %d", a
->rd
+ 1, a
->rd
, a
->imm
)
136 INSN(SUB
, "r%d, r%d", a
->rd
, a
->rr
)
137 INSN(SUBI
, "r%d, %d", a
->rd
, a
->imm
)
138 INSN(SBC
, "r%d, r%d", a
->rd
, a
->rr
)
139 INSN(SBCI
, "r%d, %d", a
->rd
, a
->imm
)
140 INSN(SBIW
, "r%d:r%d, %d", a
->rd
+ 1, a
->rd
, a
->imm
)
141 INSN(AND
, "r%d, r%d", a
->rd
, a
->rr
)
142 INSN(ANDI
, "r%d, %d", a
->rd
, a
->imm
)
143 INSN(OR
, "r%d, r%d", a
->rd
, a
->rr
)
144 INSN(ORI
, "r%d, %d", a
->rd
, a
->imm
)
145 INSN(EOR
, "r%d, r%d", a
->rd
, a
->rr
)
146 INSN(COM
, "r%d", a
->rd
)
147 INSN(NEG
, "r%d", a
->rd
)
148 INSN(INC
, "r%d", a
->rd
)
149 INSN(DEC
, "r%d", a
->rd
)
150 INSN(MUL
, "r%d, r%d", a
->rd
, a
->rr
)
151 INSN(MULS
, "r%d, r%d", a
->rd
, a
->rr
)
152 INSN(MULSU
, "r%d, r%d", a
->rd
, a
->rr
)
153 INSN(FMUL
, "r%d, r%d", a
->rd
, a
->rr
)
154 INSN(FMULS
, "r%d, r%d", a
->rd
, a
->rr
)
155 INSN(FMULSU
, "r%d, r%d", a
->rd
, a
->rr
)
156 INSN(DES
, "%d", a
->imm
)
159 * Branch Instructions
161 INSN(RJMP
, ".%+d", a
->imm
* 2)
164 INSN(JMP
, "0x%x", a
->imm
* 2)
165 INSN(RCALL
, ".%+d", a
->imm
* 2)
168 INSN(CALL
, "0x%x", a
->imm
* 2)
171 INSN(CPSE
, "r%d, r%d", a
->rd
, a
->rr
)
172 INSN(CP
, "r%d, r%d", a
->rd
, a
->rr
)
173 INSN(CPC
, "r%d, r%d", a
->rd
, a
->rr
)
174 INSN(CPI
, "r%d, %d", a
->rd
, a
->imm
)
175 INSN(SBRC
, "r%d, %d", a
->rr
, a
->bit
)
176 INSN(SBRS
, "r%d, %d", a
->rr
, a
->bit
)
177 INSN(SBIC
, "$%d, %d", a
->reg
, a
->bit
)
178 INSN(SBIS
, "$%d, %d", a
->reg
, a
->bit
)
179 INSN_MNEMONIC(BRBS
, brbs
[a
->bit
], ".%+d", a
->imm
* 2)
180 INSN_MNEMONIC(BRBC
, brbc
[a
->bit
], ".%+d", a
->imm
* 2)
183 * Data Transfer Instructions
185 INSN(MOV
, "r%d, r%d", a
->rd
, a
->rr
)
186 INSN(MOVW
, "r%d:r%d, r%d:r%d", a
->rd
+ 1, a
->rd
, a
->rr
+ 1, a
->rr
)
187 INSN(LDI
, "r%d, %d", a
->rd
, a
->imm
)
188 INSN(LDS
, "r%d, %d", a
->rd
, a
->imm
)
189 INSN(LDX1
, "r%d, X", a
->rd
)
190 INSN(LDX2
, "r%d, X+", a
->rd
)
191 INSN(LDX3
, "r%d, -X", a
->rd
)
192 INSN(LDY2
, "r%d, Y+", a
->rd
)
193 INSN(LDY3
, "r%d, -Y", a
->rd
)
194 INSN(LDZ2
, "r%d, Z+", a
->rd
)
195 INSN(LDZ3
, "r%d, -Z", a
->rd
)
196 INSN(LDDY
, "r%d, Y+%d", a
->rd
, a
->imm
)
197 INSN(LDDZ
, "r%d, Z+%d", a
->rd
, a
->imm
)
198 INSN(STS
, "%d, r%d", a
->imm
, a
->rd
)
199 INSN(STX1
, "X, r%d", a
->rr
)
200 INSN(STX2
, "X+, r%d", a
->rr
)
201 INSN(STX3
, "-X, r%d", a
->rr
)
202 INSN(STY2
, "Y+, r%d", a
->rd
)
203 INSN(STY3
, "-Y, r%d", a
->rd
)
204 INSN(STZ2
, "Z+, r%d", a
->rd
)
205 INSN(STZ3
, "-Z, r%d", a
->rd
)
206 INSN(STDY
, "Y+%d, r%d", a
->imm
, a
->rd
)
207 INSN(STDZ
, "Z+%d, r%d", a
->imm
, a
->rd
)
209 INSN(LPM2
, "r%d, Z", a
->rd
)
210 INSN(LPMX
, "r%d, Z+", a
->rd
)
212 INSN(ELPM2
, "r%d, Z", a
->rd
)
213 INSN(ELPMX
, "r%d, Z+", a
->rd
)
216 INSN(IN
, "r%d, $%d", a
->rd
, a
->imm
)
217 INSN(OUT
, "$%d, r%d", a
->imm
, a
->rd
)
218 INSN(PUSH
, "r%d", a
->rd
)
219 INSN(POP
, "r%d", a
->rd
)
220 INSN(XCH
, "Z, r%d", a
->rd
)
221 INSN(LAC
, "Z, r%d", a
->rd
)
222 INSN(LAS
, "Z, r%d", a
->rd
)
223 INSN(LAT
, "Z, r%d", a
->rd
)
226 * Bit and Bit-test Instructions
228 INSN(LSR
, "r%d", a
->rd
)
229 INSN(ROR
, "r%d", a
->rd
)
230 INSN(ASR
, "r%d", a
->rd
)
231 INSN(SWAP
, "r%d", a
->rd
)
232 INSN(SBI
, "$%d, %d", a
->reg
, a
->bit
)
233 INSN(CBI
, "%d, %d", a
->reg
, a
->bit
)
234 INSN(BST
, "r%d, %d", a
->rd
, a
->bit
)
235 INSN(BLD
, "r%d, %d", a
->rd
, a
->bit
)
236 INSN_MNEMONIC(BSET
, bset
[a
->bit
], "")
237 INSN_MNEMONIC(BCLR
, bclr
[a
->bit
], "")
240 * MCU Control Instructions