1 /* Disassemble AVR instructions. 2 Copyright 1999, 2000 Free Software Foundation, Inc. 3 4 Contributed by Denis Chertykov <denisc@overta.ru> 5 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. 10 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. 15 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. */ 19 20 #include <assert.h> 21 #include "sysdep.h" 22 #include "dis-asm.h" 23 #include "opintl.h" 24 #include "libiberty.h" 25 26 struct avr_opcodes_s 27 { 28 char *name; 29 char *constraints; 30 char *opcode; 31 int insn_size; /* in words */ 32 int isa; 33 unsigned int bin_opcode; 34 }; 35 36 #define AVR_INSN(NAME, CONSTR, OPCODE, SIZE, ISA, BIN) \ 37 {#NAME, CONSTR, OPCODE, SIZE, ISA, BIN}, 38 39 const struct avr_opcodes_s avr_opcodes[] = 40 { 41 #include "opcode/avr.h" 42 {NULL, NULL, NULL, 0, 0, 0} 43 }; 44 45 static int avr_operand PARAMS ((unsigned int, unsigned int, 46 unsigned int, int, char *, char *, int)); 47 48 static int 49 avr_operand (insn, insn2, pc, constraint, buf, comment, regs) 50 unsigned int insn; 51 unsigned int insn2; 52 unsigned int pc; 53 int constraint; 54 char *buf; 55 char *comment; 56 int regs; 57 { 58 int ok = 1; 59 60 switch (constraint) 61 { 62 /* Any register operand. */ 63 case 'r': 64 if (regs) 65 insn = (insn & 0xf) | ((insn & 0x0200) >> 5); /* source register */ 66 else 67 insn = (insn & 0x01f0) >> 4; /* destination register */ 68 69 sprintf (buf, "r%d", insn); 70 break; 71 72 case 'd': 73 if (regs) 74 sprintf (buf, "r%d", 16 + (insn & 0xf)); 75 else 76 sprintf (buf, "r%d", 16 + ((insn & 0xf0) >> 4)); 77 break; 78 79 case 'w': 80 sprintf (buf, "r%d", 24 + ((insn & 0x30) >> 3)); 81 break; 82 83 case 'a': 84 if (regs) 85 sprintf (buf, "r%d", 16 + (insn & 7)); 86 else 87 sprintf (buf, "r%d", 16 + ((insn >> 4) & 7)); 88 break; 89 90 case 'v': 91 if (regs) 92 sprintf (buf, "r%d", (insn & 0xf) * 2); 93 else 94 sprintf (buf, "r%d", ((insn & 0xf0) >> 3)); 95 break; 96 97 case 'e': 98 { 99 char *xyz; 100 101 switch (insn & 0x100f) 102 { 103 case 0x0000: xyz = "Z"; break; 104 case 0x1001: xyz = "Z+"; break; 105 case 0x1002: xyz = "-Z"; break; 106 case 0x0008: xyz = "Y"; break; 107 case 0x1009: xyz = "Y+"; break; 108 case 0x100a: xyz = "-Y"; break; 109 case 0x100c: xyz = "X"; break; 110 case 0x100d: xyz = "X+"; break; 111 case 0x100e: xyz = "-X"; break; 112 default: xyz = "??"; ok = 0; 113 } 114 sprintf (buf, xyz); 115 116 if (AVR_UNDEF_P (insn)) 117 sprintf (comment, _("undefined")); 118 } 119 break; 120 121 case 'z': 122 *buf++ = 'Z'; 123 if (insn & 0x1) 124 *buf++ = '+'; 125 *buf = '\0'; 126 if (AVR_UNDEF_P (insn)) 127 sprintf (comment, _("undefined")); 128 break; 129 130 case 'b': 131 { 132 unsigned int x; 133 134 x = (insn & 7); 135 x |= (insn >> 7) & (3 << 3); 136 x |= (insn >> 8) & (1 << 5); 137 138 if (insn & 0x8) 139 *buf++ = 'Y'; 140 else 141 *buf++ = 'Z'; 142 sprintf (buf, "+%d", x); 143 sprintf (comment, "0x%02x", x); 144 } 145 break; 146 147 case 'h': 148 sprintf (buf, "0x%x", 149 ((((insn & 1) | ((insn & 0x1f0) >> 3)) << 16) | insn2) * 2); 150 break; 151 152 case 'L': 153 { 154 int rel_addr = (((insn & 0xfff) ^ 0x800) - 0x800) * 2; 155 sprintf (buf, ".%+-8d", rel_addr); 156 sprintf (comment, "0x%x", pc + 2 + rel_addr); 157 } 158 break; 159 160 case 'l': 161 { 162 int rel_addr = ((((insn >> 3) & 0x7f) ^ 0x40) - 0x40) * 2; 163 sprintf (buf, ".%+-8d", rel_addr); 164 sprintf (comment, "0x%x", pc + 2 + rel_addr); 165 } 166 break; 167 168 case 'i': 169 sprintf (buf, "0x%04X", insn2); 170 break; 171 172 case 'M': 173 sprintf (buf, "0x%02X", ((insn & 0xf00) >> 4) | (insn & 0xf)); 174 sprintf (comment, "%d", ((insn & 0xf00) >> 4) | (insn & 0xf)); 175 break; 176 177 case 'n': 178 sprintf (buf, "??"); 179 fprintf (stderr, _("Internal disassembler error")); 180 ok = 0; 181 break; 182 183 case 'K': 184 { 185 unsigned int x; 186 187 x = (insn & 0xf) | ((insn >> 2) & 0x30); 188 sprintf (buf, "0x%02x", x); 189 sprintf (comment, "%d", x); 190 } 191 break; 192 193 case 's': 194 sprintf (buf, "%d", insn & 7); 195 break; 196 197 case 'S': 198 sprintf (buf, "%d", (insn >> 4) & 7); 199 break; 200 201 case 'P': 202 { 203 unsigned int x; 204 x = (insn & 0xf); 205 x |= (insn >> 5) & 0x30; 206 sprintf (buf, "0x%02x", x); 207 sprintf (comment, "%d", x); 208 } 209 break; 210 211 case 'p': 212 { 213 unsigned int x; 214 215 x = (insn >> 3) & 0x1f; 216 sprintf (buf, "0x%02x", x); 217 sprintf (comment, "%d", x); 218 } 219 break; 220 221 case '?': 222 *buf = '\0'; 223 break; 224 225 default: 226 sprintf (buf, "??"); 227 fprintf (stderr, _("unknown constraint `%c'"), constraint); 228 ok = 0; 229 } 230 231 return ok; 232 } 233 234 static unsigned short avrdis_opcode PARAMS ((bfd_vma, disassemble_info *)); 235 236 static unsigned short 237 avrdis_opcode (addr, info) 238 bfd_vma addr; 239 disassemble_info *info; 240 { 241 bfd_byte buffer[2]; 242 int status; 243 status = info->read_memory_func(addr, buffer, 2, info); 244 if (status != 0) 245 { 246 info->memory_error_func(status, addr, info); 247 return -1; 248 } 249 return bfd_getl16 (buffer); 250 } 251 252 253 int 254 print_insn_avr(addr, info) 255 bfd_vma addr; 256 disassemble_info *info; 257 { 258 unsigned int insn, insn2; 259 const struct avr_opcodes_s *opcode; 260 static unsigned int *maskptr; 261 void *stream = info->stream; 262 fprintf_ftype prin = info->fprintf_func; 263 static unsigned int *avr_bin_masks; 264 static int initialized; 265 int cmd_len = 2; 266 int ok = 0; 267 char op1[20], op2[20], comment1[40], comment2[40]; 268 269 if (!initialized) 270 { 271 unsigned int nopcodes; 272 273 nopcodes = sizeof (avr_opcodes) / sizeof (struct avr_opcodes_s); 274 275 avr_bin_masks = (unsigned int *) 276 xmalloc (nopcodes * sizeof (unsigned int)); 277 278 for (opcode = avr_opcodes, maskptr = avr_bin_masks; 279 opcode->name; 280 opcode++, maskptr++) 281 { 282 char * s; 283 unsigned int bin = 0; 284 unsigned int mask = 0; 285 286 for (s = opcode->opcode; *s; ++s) 287 { 288 bin <<= 1; 289 mask <<= 1; 290 bin |= (*s == '1'); 291 mask |= (*s == '1' || *s == '0'); 292 } 293 assert (s - opcode->opcode == 16); 294 assert (opcode->bin_opcode == bin); 295 *maskptr = mask; 296 } 297 298 initialized = 1; 299 } 300 301 insn = avrdis_opcode (addr, info); 302 303 for (opcode = avr_opcodes, maskptr = avr_bin_masks; 304 opcode->name; 305 opcode++, maskptr++) 306 { 307 if ((insn & *maskptr) == opcode->bin_opcode) 308 break; 309 } 310 311 /* Special case: disassemble `ldd r,b+0' as `ld r,b', and 312 `std b+0,r' as `st b,r' (next entry in the table). */ 313 314 if (AVR_DISP0_P (insn)) 315 opcode++; 316 317 op1[0] = 0; 318 op2[0] = 0; 319 comment1[0] = 0; 320 comment2[0] = 0; 321 322 if (opcode->name) 323 { 324 char *op = opcode->constraints; 325 326 insn2 = 0; 327 ok = 1; 328 329 if (opcode->insn_size > 1) 330 { 331 insn2 = avrdis_opcode (addr + 2, info); 332 cmd_len = 4; 333 } 334 335 if (*op && *op != '?') 336 { 337 int regs = REGISTER_P (*op); 338 339 ok = avr_operand (insn, insn2, addr, *op, op1, comment1, 0); 340 341 if (ok && *(++op) == ',') 342 ok = avr_operand (insn, insn2, addr, *(++op), op2, 343 *comment1 ? comment2 : comment1, regs); 344 } 345 } 346 347 if (!ok) 348 { 349 /* Unknown opcode, or invalid combination of operands. */ 350 sprintf (op1, "0x%04x", insn); 351 op2[0] = 0; 352 sprintf (comment1, "????"); 353 comment2[0] = 0; 354 } 355 356 (*prin) (stream, "%s", ok ? opcode->name : ".word"); 357 358 if (*op1) 359 (*prin) (stream, "\t%s", op1); 360 361 if (*op2) 362 (*prin) (stream, ", %s", op2); 363 364 if (*comment1) 365 (*prin) (stream, "\t; %s", comment1); 366 367 if (*comment2) 368 (*prin) (stream, " %s", comment2); 369 370 return cmd_len; 371 } 372