]>
git.ipfire.org Git - thirdparty/binutils-gdb.git/blob - opcodes/avr-dis.c
1 /* Disassemble AVR instructions.
2 Copyright (C) 1999, 2000 Free Software Foundation, Inc.
4 Contributed by Denis Chertykov <denisc@overta.ru>
6 This program is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 2 of the License, or
9 (at your option) any later version.
11 This program is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU General Public License for more details.
16 You should have received a copy of the GNU General Public License
17 along with this program; if not, write to the Free Software
18 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
24 typedef unsigned char u8
;
25 typedef unsigned short u16
;
26 typedef unsigned long u32
;
28 #define IFMASK(a,b) ((opcode & (a)) == (b))
30 static char* SREG_flags
= "CZNVSHTI";
31 static char* sect94
[] = {"COM","NEG","SWAP","INC","NULL","ASR","LSR","ROR",
33 static char* sect98
[] = {"CBI","SBIC","SBI","SBIS"};
34 static char* branchs
[] = {
35 "BRCS","BREQ","BRMI","BRVS",
36 "BRLT","BRHS","BRTS","BRIE",
37 "BRCC","BRNE","BRPL","BRVC",
38 "BRGE","BRHC","BRTC","BRID"
41 static char* last4
[] = {"BLD","BST","SBRC","SBRS"};
44 static void dispLDD
PARAMS ((u16
, char *));
47 dispLDD (opcode
, dest
)
51 opcode
= (((opcode
& 0x2000) >> 8) | ((opcode
& 0x0c00) >> 7)
53 sprintf(dest
, "%d", opcode
);
57 static void regPP
PARAMS ((u16
, char *));
64 opcode
= ((opcode
& 0x0600) >> 5) | (opcode
& 0xf);
65 sprintf(dest
, "0x%02X", opcode
);
69 static void reg50
PARAMS ((u16
, char *));
76 opcode
= (opcode
& 0x01f0) >> 4;
77 sprintf(dest
, "R%d", opcode
);
81 static void reg104
PARAMS ((u16
, char *));
88 opcode
= (opcode
& 0xf) | ((opcode
& 0x0200) >> 5);
89 sprintf(dest
, "R%d", opcode
);
93 static void reg40
PARAMS ((u16
, char *));
100 opcode
= (opcode
& 0xf0) >> 4;
101 sprintf(dest
, "R%d", opcode
+ 16);
105 static void reg20w
PARAMS ((u16
, char *));
108 reg20w (opcode
, dest
)
112 opcode
= (opcode
& 0x30) >> 4;
113 sprintf(dest
, "R%d", 24 + opcode
* 2);
117 static void lit404
PARAMS ((u16
, char *));
120 lit404 (opcode
, dest
)
124 opcode
= ((opcode
& 0xf00) >> 4) | (opcode
& 0xf);
125 sprintf(dest
, "0x%02X", opcode
);
129 static void lit204
PARAMS ((u16
, char *));
132 lit204 (opcode
, dest
)
136 opcode
= ((opcode
& 0xc0) >> 2) | (opcode
& 0xf);
137 sprintf(dest
, "0x%02X", opcode
);
141 static void add0fff
PARAMS ((u16
, char *, int));
144 add0fff (op
, dest
, pc
)
149 int rel_addr
= (((op
& 0xfff) ^ 0x800) - 0x800) * 2;
150 sprintf(dest
, ".%+-8d ; 0x%06X", rel_addr
, pc
+ 2 + rel_addr
);
154 static void add03f8
PARAMS ((u16
, char *, int));
157 add03f8 (op
, dest
, pc
)
162 int rel_addr
= ((((op
>> 3) & 0x7f) ^ 0x40) - 0x40) * 2;
163 sprintf(dest
, ".%+-8d ; 0x%06X", rel_addr
, pc
+ 2 + rel_addr
);
167 static u16 avrdis_opcode
PARAMS ((bfd_vma
, disassemble_info
*));
170 avrdis_opcode (addr
, info
)
172 disassemble_info
*info
;
176 status
= info
->read_memory_func(addr
, buffer
, 2, info
);
179 info
->memory_error_func(status
, addr
, info
);
182 return bfd_getl16 (buffer
);
187 print_insn_avr(addr
, info
)
189 disassemble_info
*info
;
194 void *stream
= info
->stream
;
195 fprintf_ftype prin
= info
->fprintf_func
;
198 opcode
= avrdis_opcode (addr
, info
);
200 if (IFMASK(0xd000, 0x8000))
210 (*prin
) (stream
, " STD %c+%s,%s", letter
, rr
, rd
);
212 (*prin
) (stream
, " LDD %s,%c+%s", rd
, letter
, rr
);
216 switch (opcode
& 0xf000)
222 switch (opcode
& 0x0c00)
225 (*prin
) (stream
, " NOP");
228 (*prin
) (stream
, " CPC %s,%s", rd
, rr
);
231 (*prin
) (stream
, " SBC %s,%s", rd
, rr
);
234 (*prin
) (stream
, " ADD %s,%s", rd
, rr
);
243 switch (opcode
& 0x0c00)
246 (*prin
) (stream
, " CPSE %s,%s", rd
, rr
);
249 (*prin
) (stream
, " CP %s,%s", rd
, rr
);
252 (*prin
) (stream
, " SUB %s,%s", rd
, rr
);
255 (*prin
) (stream
, " ADC %s,%s", rd
, rr
);
264 switch (opcode
& 0x0c00)
267 (*prin
) (stream
, " AND %s,%s", rd
, rr
);
270 (*prin
) (stream
, " EOR %s,%s", rd
, rr
);
273 (*prin
) (stream
, " OR %s,%s", rd
, rr
);
276 (*prin
) (stream
, " MOV %s,%s", rd
, rr
);
285 (*prin
) (stream
, " CPI %s,%s", rd
, rr
);
292 (*prin
) (stream
, " SBCI %s,%s", rd
, rr
);
299 (*prin
) (stream
, " SUBI %s,%s", rd
, rr
);
306 (*prin
) (stream
, " ORI %s,%s", rd
, rr
);
313 (*prin
) (stream
, " ANDI %s,%s", rd
, rr
);
318 switch (opcode
& 0x0e00)
323 switch (opcode
& 0xf)
327 (*prin
) (stream
, " LDS %s,0x%04X", rd
,
328 avrdis_opcode(addr
+ 2, info
));
333 (*prin
) (stream
, " LD %s,Z+", rd
);
336 (*prin
) (stream
, " LD %s,-Z", rd
);
339 (*prin
) (stream
, " LD %s,Y+", rd
);
342 (*prin
) (stream
, " LD %s,-Y", rd
);
345 (*prin
) (stream
, " LD %s,X", rd
);
348 (*prin
) (stream
, " LD %s,X+", rd
);
351 (*prin
) (stream
, " LD %s,-X", rd
);
354 (*prin
) (stream
, " POP %s", rd
);
357 (*prin
) (stream
, " ????");
365 switch (opcode
& 0xf)
369 (*prin
) (stream
, " STS 0x%04X,%s",
370 avrdis_opcode(addr
+ 2, info
), rd
);
375 (*prin
) (stream
, " ST Z+,%s", rd
);
378 (*prin
) (stream
, " ST -Z,%s", rd
);
381 (*prin
) (stream
, " ST Y+,%s", rd
);
384 (*prin
) (stream
, " ST -Y,%s", rd
);
387 (*prin
) (stream
, " ST X,%s", rd
);
390 (*prin
) (stream
, " ST X+,%s", rd
);
393 (*prin
) (stream
, " ST -X,%s", rd
);
396 (*prin
) (stream
, " PUSH %s", rd
);
399 (*prin
) (stream
, " ????");
406 if (IFMASK(0x020c, 0x000c))
408 u32 k
= ((opcode
& 0x01f0) >> 3) | (opcode
& 1);
409 k
= (k
<< 16) | avrdis_opcode(addr
+ 2, info
);
411 (*prin
) (stream
, " CALL 0x%06X", k
*2);
413 (*prin
) (stream
, " JMP 0x%06X", k
*2);
416 else if (IFMASK(0x010f, 0x0008))
418 int sf
= (opcode
& 0x70) >> 4;
420 (*prin
) (stream
, " CL%c", SREG_flags
[sf
]);
422 (*prin
) (stream
, " SE%c", SREG_flags
[sf
]);
424 else if (IFMASK(0x000f, 0x0009))
427 (*prin
) (stream
, " ICALL");
429 (*prin
) (stream
, " IJMP");
431 else if (IFMASK(0x010f, 0x0108))
433 if (IFMASK(0x0090, 0x0000))
434 (*prin
) (stream
, " RET");
435 else if (IFMASK(0x0090, 0x0010))
436 (*prin
) (stream
, " RETI");
437 else if (IFMASK(0x00e0, 0x0080))
438 (*prin
) (stream
, " SLEEP");
439 else if (IFMASK(0x00e0, 0x00a0))
440 (*prin
) (stream
, " WDR");
441 else if (IFMASK(0x00f0, 0x00c0))
442 (*prin
) (stream
, " LPM");
443 else if (IFMASK(0x00f0, 0x00d0))
444 (*prin
) (stream
, " ELPM");
446 (*prin
) (stream
, " ????");
452 p
= sect94
[opcode
& 0xf];
455 (*prin
) (stream
, " %-8s%s", p
, rd
);
466 (*prin
) (stream
, " SBIW %s,%s", rr
, rd
);
468 (*prin
) (stream
, " ADIW %s,%s", rr
, rd
);
475 (*prin
) (stream
, " %-8s0x%02X,%d",
476 sect98
[(opcode
& 0x0300) >> 8],
477 (opcode
& 0xf8) >> 3,
485 (*prin
) (stream
, " MUL %s,%s", rd
, rr
);
495 (*prin
) (stream
, " OUT %s,%s", rr
, rd
);
497 (*prin
) (stream
, " IN %s,%s", rd
, rr
);
502 add0fff(opcode
, rd
, addr
);
503 (*prin
) (stream
, " RJMP %s", rd
);
508 add0fff(opcode
, rd
, addr
);
509 (*prin
) (stream
, " RCALL %s", rd
);
516 (*prin
) (stream
, " LDI %s,%s", rd
, rr
);
524 (*prin
) (stream
, " %-8s%s,%d",
525 last4
[(opcode
& 0x0600) >> 9],
531 add03f8(opcode
, rd
, addr
);
532 p
= branchs
[((opcode
& 0x0400) >> 7) | (opcode
& 7)];
533 (*prin
) (stream
, " %-8s%s", p
, rd
);