gdb: add target_ops::supports_displaced_step
[deliverable/binutils-gdb.git] / opcodes / avr-dis.c
index 6fcd58cc6f8d33d1c0f8d969dc539de53ac64d8f..23d5b3f6f2c834c96e0c1c00c140960895838e16 100644 (file)
 /* Disassemble AVR instructions.
-   Copyright (C) 1999, 2000 Free Software Foundation, Inc.
+   Copyright (C) 1999-2020 Free Software Foundation, Inc.
 
    Contributed by Denis Chertykov <denisc@overta.ru>
 
-This program is free software; you can redistribute it and/or modify
-it under the terms of the GNU General Public License as published by
-the Free Software Foundation; either version 2 of the License, or
-(at your option) any later version.
+   This file is part of libopcodes.
 
-This program is distributed in the hope that it will be useful,
-but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-GNU General Public License for more details.
+   This library is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 3, or (at your option)
+   any later version.
 
-You should have received a copy of the GNU General Public License
-along with this program; if not, write to the Free Software
-Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.  */
+   It is distributed in the hope that it will be useful, but WITHOUT
+   ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+   or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public
+   License for more details.
 
+   You should have received a copy of the GNU General Public License
+   along with this program; if not, write to the Free Software
+   Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston,
+   MA 02110-1301, USA.  */
 
 #include "sysdep.h"
-#include "dis-asm.h"
+#include <assert.h>
+#include "disassemble.h"
 #include "opintl.h"
+#include "libiberty.h"
+#include "bfd_stdint.h"
 
-typedef unsigned char u8;
-typedef unsigned short u16;
-typedef unsigned long u32;
-
-#define IFMASK(a,b)     ((opcode & (a)) == (b))
-
-static char* SREG_flags = "CZNVSHTI";
-static char* sect94[] = {"COM","NEG","SWAP","INC",0,"ASR","LSR","ROR",
-                        0,0,"DEC",0,0,0,0,0};
-static char* sect98[] = {"CBI","SBIC","SBI","SBIS"};
-static char* branchs[] = {
-  "BRCS","BREQ","BRMI","BRVS",
-  "BRLT","BRHS","BRTS","BRIE",
-  "BRCC","BRNE","BRPL","BRVC",
-  "BRGE","BRHC","BRTC","BRID"
+struct avr_opcodes_s
+{
+  char *name;
+  char *constraints;
+  char *opcode;
+  int insn_size;               /* In words.  */
+  int isa;
+  unsigned int bin_opcode;
 };
 
-static char* last4[] = {"BLD","BST","SBRC","SBRS"};
-
+#define AVR_INSN(NAME, CONSTR, OPCODE, SIZE, ISA, BIN) \
+{#NAME, CONSTR, OPCODE, SIZE, ISA, BIN},
 
-static void dispLDD PARAMS ((u16, char *));
-
-static void
-dispLDD (opcode, dest)
-     u16 opcode;
-     char *dest;
+const struct avr_opcodes_s avr_opcodes[] =
 {
-  opcode = (((opcode & 0x2000) >> 8) | ((opcode & 0x0c00) >> 7)
-           | (opcode & 7));
-  sprintf(dest, "%d", opcode);
-}
-
+  #include "opcode/avr.h"
+  {NULL, NULL, NULL, 0, 0, 0}
+};
 
-static void regPP PARAMS ((u16, char *));
+static const char * comment_start = "0x";
 
-static void
-regPP (opcode, dest)
-     u16 opcode;
-     char *dest;
+static int
+avr_operand (unsigned int insn, unsigned int insn2, unsigned int pc, int constraint,
+             char *opcode_str, char *buf, char *comment, int regs, int *sym, bfd_vma *sym_addr)
 {
-  opcode = ((opcode & 0x0600) >> 5) | (opcode & 0xf);
-  sprintf(dest, "0x%02X", opcode);
-}
+  int ok = 1;
+  *sym = 0;
 
+  switch (constraint)
+    {
+      /* Any register operand.  */
+    case 'r':
+      if (regs)
+       insn = (insn & 0xf) | ((insn & 0x0200) >> 5); /* Source register.  */
+      else
+       insn = (insn & 0x01f0) >> 4; /* Destination register.  */
 
-static void reg50 PARAMS ((u16, char *));
-
-static void
-reg50 (opcode, dest)
-     u16 opcode;
-     char *dest;
-{
-  opcode = (opcode & 0x01f0) >> 4;
-  sprintf(dest, "R%d", opcode);
-}
-
+      sprintf (buf, "r%d", insn);
+      break;
 
-static void reg104 PARAMS ((u16, char *));
+    case 'd':
+      if (regs)
+       sprintf (buf, "r%d", 16 + (insn & 0xf));
+      else
+       sprintf (buf, "r%d", 16 + ((insn & 0xf0) >> 4));
+      break;
 
-static void
-reg104 (opcode, dest)
-     u16 opcode;
-     char *dest;
-{
-  opcode = (opcode & 0xf) | ((opcode & 0x0200) >> 5);
-  sprintf(dest, "R%d", opcode);
-}
+    case 'w':
+      sprintf (buf, "r%d", 24 + ((insn & 0x30) >> 3));
+      break;
 
+    case 'a':
+      if (regs)
+       sprintf (buf, "r%d", 16 + (insn & 7));
+      else
+       sprintf (buf, "r%d", 16 + ((insn >> 4) & 7));
+      break;
 
-static void reg40 PARAMS ((u16, char *));
+    case 'v':
+      if (regs)
+       sprintf (buf, "r%d", (insn & 0xf) * 2);
+      else
+       sprintf (buf, "r%d", ((insn & 0xf0) >> 3));
+      break;
 
-static void
-reg40 (opcode, dest)
-     u16 opcode;
-     char *dest;
-{
-  opcode = (opcode & 0xf0) >> 4;
-  sprintf(dest, "R%d", opcode + 16);
-}
+    case 'e':
+      {
+       char *xyz;
 
+       switch (insn & 0x100f)
+         {
+           case 0x0000: xyz = "Z";  break;
+           case 0x1001: xyz = "Z+"; break;
+           case 0x1002: xyz = "-Z"; break;
+           case 0x0008: xyz = "Y";  break;
+           case 0x1009: xyz = "Y+"; break;
+           case 0x100a: xyz = "-Y"; break;
+           case 0x100c: xyz = "X";  break;
+           case 0x100d: xyz = "X+"; break;
+           case 0x100e: xyz = "-X"; break;
+           default: xyz = "??"; ok = 0;
+         }
+       strcpy (buf, xyz);
 
-static void reg20w PARAMS ((u16, char *));
+       if (AVR_UNDEF_P (insn))
+         sprintf (comment, _("undefined"));
+      }
+      break;
 
-static void
-reg20w (opcode, dest)
-     u16 opcode;
-     char *dest;
-{
-  opcode = (opcode & 0x30) >> 4;
-  sprintf(dest, "R%d", 24 + opcode * 2);
-}
+    case 'z':
+      *buf++ = 'Z';
 
+      /* Check for post-increment. */
+      char *s;
+      for (s = opcode_str; *s; ++s)
+        {
+          if (*s == '+')
+            {
+             if (insn & (1 << (15 - (s - opcode_str))))
+               *buf++ = '+';
+              break;
+            }
+        }
 
-static void reg_fmul_d PARAMS ((u16, char *));
+      *buf = '\0';
+      if (AVR_UNDEF_P (insn))
+       sprintf (comment, _("undefined"));
+      break;
+
+    case 'b':
+      {
+       unsigned int x;
+
+       x = (insn & 7);
+       x |= (insn >> 7) & (3 << 3);
+       x |= (insn >> 8) & (1 << 5);
+
+       if (insn & 0x8)
+         *buf++ = 'Y';
+       else
+         *buf++ = 'Z';
+       sprintf (buf, "+%d", x);
+       sprintf (comment, "0x%02x", x);
+      }
+      break;
+
+    case 'h':
+      *sym = 1;
+      *sym_addr = ((((insn & 1) | ((insn & 0x1f0) >> 3)) << 16) | insn2) * 2;
+      /* See PR binutils/2454.  Ideally we would like to display the hex
+        value of the address only once, but this would mean recoding
+        objdump_print_address() which would affect many targets.  */
+      sprintf (buf, "%#lx", (unsigned long) *sym_addr);
+      strcpy (comment, comment_start);
+      break;
+
+    case 'L':
+      {
+       int rel_addr = (((insn & 0xfff) ^ 0x800) - 0x800) * 2;
+       sprintf (buf, ".%+-8d", rel_addr);
+        *sym = 1;
+        *sym_addr = pc + 2 + rel_addr;
+       strcpy (comment, comment_start);
+      }
+      break;
+
+    case 'l':
+      {
+       int rel_addr = ((((insn >> 3) & 0x7f) ^ 0x40) - 0x40) * 2;
+
+       sprintf (buf, ".%+-8d", rel_addr);
+        *sym = 1;
+        *sym_addr = pc + 2 + rel_addr;
+       strcpy (comment, comment_start);
+      }
+      break;
+
+    case 'i':
+      {
+        unsigned int val = insn2 | 0x800000;
+        *sym = 1;
+        *sym_addr = val;
+        sprintf (buf, "0x%04X", insn2);
+        strcpy (comment, comment_start);
+      }
+      break;
+
+    case 'j':
+      {
+        unsigned int val = ((insn & 0xf) | ((insn & 0x600) >> 5)
+                                         | ((insn & 0x100) >> 2));
+       if ((insn & 0x100) == 0)
+         val |= 0x80;
+        *sym = 1;
+        *sym_addr = val | 0x800000;
+        sprintf (buf, "0x%02x", val);
+        strcpy (comment, comment_start);
+      }
+      break;
+
+    case 'M':
+      sprintf (buf, "0x%02X", ((insn & 0xf00) >> 4) | (insn & 0xf));
+      sprintf (comment, "%d", ((insn & 0xf00) >> 4) | (insn & 0xf));
+      break;
+
+    case 'n':
+      sprintf (buf, "??");
+      /* xgettext:c-format */
+      opcodes_error_handler (_("internal disassembler error"));
+      ok = 0;
+      break;
+
+    case 'K':
+      {
+       unsigned int x;
+
+       x = (insn & 0xf) | ((insn >> 2) & 0x30);
+       sprintf (buf, "0x%02x", x);
+       sprintf (comment, "%d", x);
+      }
+      break;
+
+    case 's':
+      sprintf (buf, "%d", insn & 7);
+      break;
+
+    case 'S':
+      sprintf (buf, "%d", (insn >> 4) & 7);
+      break;
+
+    case 'P':
+      {
+       unsigned int x;
+
+       x = (insn & 0xf);
+       x |= (insn >> 5) & 0x30;
+       sprintf (buf, "0x%02x", x);
+       sprintf (comment, "%d", x);
+      }
+      break;
+
+    case 'p':
+      {
+       unsigned int x;
+
+       x = (insn >> 3) & 0x1f;
+       sprintf (buf, "0x%02x", x);
+       sprintf (comment, "%d", x);
+      }
+      break;
+
+    case 'E':
+      sprintf (buf, "%d", (insn >> 4) & 15);
+      break;
+
+    case '?':
+      *buf = '\0';
+      break;
+
+    default:
+      sprintf (buf, "??");
+      /* xgettext:c-format */
+      opcodes_error_handler (_("unknown constraint `%c'"), constraint);
+      ok = 0;
+    }
 
-static void
-reg_fmul_d (opcode, dest)
-     u16 opcode;
-     char *dest;
-{
-  sprintf(dest, "R%d", 16 + ((opcode >> 4) & 7));
+    return ok;
 }
 
+/* Read the opcode from ADDR.  Return 0 in success and save opcode
+   in *INSN, otherwise, return -1.  */
 
-static void reg_fmul_r PARAMS ((u16, char *));
-
-static void
-reg_fmul_r (opcode, dest)
-     u16 opcode;
-     char *dest;
+static int
+avrdis_opcode (bfd_vma addr, disassemble_info *info, uint16_t *insn)
 {
-  sprintf(dest, "R%d", 16 + (opcode & 7));
-}
+  bfd_byte buffer[2];
+  int status;
 
+  status = info->read_memory_func (addr, buffer, 2, info);
 
-static void reg_muls_d PARAMS ((u16, char *));
+  if (status == 0)
+    {
+      *insn = bfd_getl16 (buffer);
+      return 0;
+    }
 
-static void
-reg_muls_d (opcode, dest)
-     u16 opcode;
-     char *dest;
-{
-  sprintf(dest, "R%d", 16 + ((opcode >> 4) & 0xf));
+  info->memory_error_func (status, addr, info);
+  return -1;
 }
 
 
-static void reg_muls_r PARAMS ((u16, char *));
-
-static void
-reg_muls_r (opcode, dest)
-     u16 opcode;
-     char *dest;
+int
+print_insn_avr (bfd_vma addr, disassemble_info *info)
 {
-  sprintf(dest, "R%d", 16 + (opcode & 0xf));
-}
-
-
-static void reg_movw_d PARAMS ((u16, char *));
+  uint16_t insn, insn2;
+  const struct avr_opcodes_s *opcode;
+  static unsigned int *maskptr;
+  void *stream = info->stream;
+  fprintf_ftype prin = info->fprintf_func;
+  static unsigned int *avr_bin_masks;
+  static int initialized;
+  int cmd_len = 2;
+  int ok = 0;
+  char op1[20], op2[20], comment1[40], comment2[40];
+  int sym_op1 = 0, sym_op2 = 0;
+  bfd_vma sym_addr1, sym_addr2;
 
-static void
-reg_movw_d (opcode, dest)
-     u16 opcode;
-     char *dest;
-{
-  sprintf(dest, "R%d", 2 * ((opcode >> 4) & 0xf));
-}
 
+  if (!initialized)
+    {
+      unsigned int nopcodes;
+
+      /* PR 4045: Try to avoid duplicating the 0x prefix that
+        objdump_print_addr() will put on addresses when there
+        is no symbol table available.  */
+      if (info->symtab_size == 0)
+       comment_start = " ";
+
+      nopcodes = sizeof (avr_opcodes) / sizeof (struct avr_opcodes_s);
+
+      avr_bin_masks = xmalloc (nopcodes * sizeof (unsigned int));
+
+      for (opcode = avr_opcodes, maskptr = avr_bin_masks;
+          opcode->name;
+          opcode++, maskptr++)
+       {
+         char * s;
+         unsigned int bin = 0;
+         unsigned int mask = 0;
+
+         for (s = opcode->opcode; *s; ++s)
+           {
+             bin <<= 1;
+             mask <<= 1;
+             bin |= (*s == '1');
+             mask |= (*s == '1' || *s == '0');
+           }
+         assert (s - opcode->opcode == 16);
+         assert (opcode->bin_opcode == bin);
+         *maskptr = mask;
+       }
+
+      initialized = 1;
+    }
 
-static void reg_movw_r PARAMS ((u16, char *));
+  if (avrdis_opcode (addr, info, &insn)  != 0)
+    return -1;
 
-static void
-reg_movw_r (opcode, dest)
-     u16 opcode;
-     char *dest;
-{
-  sprintf(dest, "R%d", 2 * (opcode & 0xf));
-}
+  for (opcode = avr_opcodes, maskptr = avr_bin_masks;
+       opcode->name;
+       opcode++, maskptr++)
+    {
+      if ((opcode->isa == AVR_ISA_TINY) && (info->mach != bfd_mach_avrtiny))
+        continue;
+      if ((insn & *maskptr) == opcode->bin_opcode)
+        break;
+    }
 
+  /* Special case: disassemble `ldd r,b+0' as `ld r,b', and
+     `std b+0,r' as `st b,r' (next entry in the table).  */
 
-static void lit404 PARAMS ((u16, char *));
+  if (AVR_DISP0_P (insn))
+    opcode++;
 
-static void
-lit404 (opcode, dest)
-     u16 opcode;
-     char *dest;
-{
-  opcode = ((opcode & 0xf00) >> 4) | (opcode & 0xf);
-  sprintf(dest, "0x%02X", opcode);
-}
+  op1[0] = 0;
+  op2[0] = 0;
+  comment1[0] = 0;
+  comment2[0] = 0;
 
+  if (opcode->name)
+    {
+      char *constraints = opcode->constraints;
+      char *opcode_str = opcode->opcode;
 
-static void lit204 PARAMS ((u16, char *));
+      insn2 = 0;
+      ok = 1;
 
-static void
-lit204 (opcode, dest)
-     u16 opcode;
-     char *dest;
-{
-  opcode = ((opcode & 0xc0) >> 2) | (opcode & 0xf);
-  sprintf(dest, "0x%02X", opcode);
-}
+      if (opcode->insn_size > 1)
+       {
+         if (avrdis_opcode (addr + 2, info, &insn2) != 0)
+           return -1;
+         cmd_len = 4;
+       }
 
+      if (*constraints && *constraints != '?')
+       {
+         int regs = REGISTER_P (*constraints);
 
-static void add0fff PARAMS ((u16, char *, int));
-
-static void
-add0fff (op, dest, pc)
-     u16 op;
-     char *dest;
-     int pc;
-{
-  int rel_addr = (((op & 0xfff) ^ 0x800) - 0x800) * 2;
-  sprintf(dest, ".%+-8d ; 0x%06X", rel_addr, pc + 2 + rel_addr);
-}
+         ok = avr_operand (insn, insn2, addr, *constraints, opcode_str, op1, comment1, 0, &sym_op1, &sym_addr1);
 
+         if (ok && *(++constraints) == ',')
+           ok = avr_operand (insn, insn2, addr, *(++constraints), opcode_str, op2,
+                             *comment1 ? comment2 : comment1, regs, &sym_op2, &sym_addr2);
+       }
+    }
 
-static void add03f8 PARAMS ((u16, char *, int));
+  if (!ok)
+    {
+      /* Unknown opcode, or invalid combination of operands.  */
+      sprintf (op1, "0x%04x", insn);
+      op2[0] = 0;
+      sprintf (comment1, "????");
+      comment2[0] = 0;
+    }
 
-static void
-add03f8 (op, dest, pc)
-     u16 op;
-     char *dest;
-     int pc;
-{
-  int rel_addr = ((((op >> 3) & 0x7f) ^ 0x40) - 0x40) * 2;
-  sprintf(dest, ".%+-8d ; 0x%06X", rel_addr, pc + 2 + rel_addr);
-}
+  (*prin) (stream, "%s", ok ? opcode->name : ".word");
 
+  if (*op1)
+      (*prin) (stream, "\t%s", op1);
 
-static u16 avrdis_opcode PARAMS ((bfd_vma, disassemble_info *));
+  if (*op2)
+    (*prin) (stream, ", %s", op2);
 
-static u16
-avrdis_opcode (addr, info)
-     bfd_vma addr;
-     disassemble_info *info;
-{
-  bfd_byte buffer[2];
-  int status;
-  status = info->read_memory_func(addr, buffer, 2, info);
-  if (status != 0)
-    {
-      info->memory_error_func(status, addr, info);
-      return -1;
-    }
-  return bfd_getl16 (buffer);
-}
+  if (*comment1)
+    (*prin) (stream, "\t; %s", comment1);
 
+  if (sym_op1)
+    info->print_address_func (sym_addr1, info);
 
-int
-print_insn_avr(addr, info)
-     bfd_vma addr;
-     disassemble_info *info;
-{
-  char rr[200];
-  char rd[200];
-  u16 opcode;
-  void *stream = info->stream;
-  fprintf_ftype prin = info->fprintf_func;
-  int cmd_len = 2;
+  if (*comment2)
+    (*prin) (stream, " %s", comment2);
 
-  opcode = avrdis_opcode (addr, info);
+  if (sym_op2)
+    info->print_address_func (sym_addr2, info);
 
-  if (IFMASK(0xd000, 0x8000))
-    {
-      char letter;
-      reg50(opcode, rd);
-      dispLDD(opcode, rr);
-      if (opcode & 8)
-       letter = 'Y';
-      else
-       letter = 'Z';
-      if (opcode & 0x0200)
-       (*prin) (stream, "    STD     %c+%s,%s", letter, rr, rd);
-      else
-       (*prin) (stream, "    LDD     %s,%c+%s", rd, letter, rr);
-    }
-  else
-    {
-      switch (opcode & 0xf000)
-        {
-        case 0x0000:
-         {
-           reg50(opcode, rd);
-           reg104(opcode, rr);
-           switch (opcode & 0x0c00)
-             {
-             case 0x0000:
-               switch (opcode & 0x0300)
-                 {
-                 case 0x0000:
-                   (*prin) (stream, "    NOP");
-                   break;
-                 case 0x0100:
-                   reg_movw_d(opcode, rd);
-                   reg_movw_r(opcode, rr);
-                   (*prin) (stream, "    MOVW    %s,%s", rd, rr);
-                   break;
-                 case 0x0200:
-                   reg_muls_d(opcode, rd);
-                   reg_muls_r(opcode, rr);
-                   (*prin) (stream, "    MULS    %s,%s", rd, rr);
-                   break;
-                 case 0x0300:
-                   reg_fmul_d(opcode, rd);
-                   reg_fmul_r(opcode, rr);
-                   if (IFMASK(0x88, 0))
-                     (*prin) (stream, "    MULSU   %s,%s", rd, rr);
-                   else if (IFMASK(0x88, 8))
-                     (*prin) (stream, "    FMUL    %s,%s", rd, rr);
-                   else if (IFMASK(0x88, 0x80))
-                     (*prin) (stream, "    FMULS   %s,%s", rd, rr);
-                   else
-                     (*prin) (stream, "    FMULSU  %s,%s", rd, rr);
-                 }
-               break;
-             case 0x0400:
-               (*prin) (stream, "    CPC     %s,%s", rd, rr);
-               break;
-             case 0x0800:
-               (*prin) (stream, "    SBC     %s,%s", rd, rr);
-               break;
-             case 0x0c00:
-               (*prin) (stream, "    ADD     %s,%s", rd, rr);
-               break;
-             }
-         }
-         break;
-        case 0x1000:
-         {
-           reg50(opcode, rd);
-           reg104(opcode, rr);
-           switch (opcode & 0x0c00)
-             {
-             case 0x0000:
-               (*prin) (stream, "    CPSE    %s,%s", rd, rr);
-               break;
-             case 0x0400:
-               (*prin) (stream, "    CP      %s,%s", rd, rr);
-               break;
-             case 0x0800:
-               (*prin) (stream, "    SUB     %s,%s", rd, rr);
-               break;
-             case 0x0c00:
-               (*prin) (stream, "    ADC     %s,%s", rd, rr);
-               break;
-             }
-         }
-         break;
-        case 0x2000:
-         {
-           reg50(opcode, rd);
-           reg104(opcode, rr);
-           switch (opcode & 0x0c00)
-             {
-             case 0x0000:
-               (*prin) (stream, "    AND     %s,%s", rd, rr);
-               break;
-             case 0x0400:
-               (*prin) (stream, "    EOR     %s,%s", rd, rr);
-               break;
-             case 0x0800:
-               (*prin) (stream, "    OR      %s,%s", rd, rr);
-               break;
-             case 0x0c00:
-               (*prin) (stream, "    MOV     %s,%s", rd, rr);
-               break;
-             }
-         }
-         break;
-        case 0x3000:
-         {
-           reg40(opcode, rd);
-           lit404(opcode, rr);
-           (*prin) (stream, "    CPI     %s,%s", rd, rr);
-         }
-         break;
-        case 0x4000:
-         {
-           reg40(opcode, rd);
-           lit404(opcode, rr);
-           (*prin) (stream, "    SBCI    %s,%s", rd, rr);
-         }
-         break;
-        case 0x5000:
-         {
-           reg40(opcode, rd);
-           lit404(opcode, rr);
-           (*prin) (stream, "    SUBI    %s,%s", rd, rr);
-         }
-         break;
-        case 0x6000:
-         {
-           reg40(opcode, rd);
-           lit404(opcode, rr);
-           (*prin) (stream, "    ORI     %s,%s", rd, rr);
-         }
-         break;
-        case 0x7000:
-         {
-           reg40(opcode, rd);
-           lit404(opcode, rr);
-           (*prin) (stream, "    ANDI    %s,%s", rd, rr);
-         }
-         break;
-        case 0x9000:
-         {
-           switch (opcode & 0x0e00)
-             {
-             case 0x0000:
-               {
-                 reg50(opcode, rd);
-                 switch (opcode & 0xf)
-                   {
-                   case 0x0:
-                     {
-                       (*prin) (stream, "    LDS     %s,0x%04X", rd,
-                                avrdis_opcode(addr + 2, info));
-                       cmd_len = 4;
-                     }
-                     break;
-                   case 0x1:
-                     (*prin) (stream, "    LD      %s,Z+", rd);
-                     break;
-                   case 0x2:
-                     (*prin) (stream, "    LD      %s,-Z", rd);
-                     break;
-                   case 0x4:
-                     (*prin) (stream, "    LPM     %s,Z", rd);
-                     break;
-                   case 0x5:
-                     (*prin) (stream, "    LPM     %s,Z+", rd);
-                     break;
-                   case 0x6:
-                     (*prin) (stream, "    ELPM    %s,Z", rd);
-                     break;
-                   case 0x7:
-                     (*prin) (stream, "    ELPM    %s,Z+", rd);
-                     break;
-                   case 0x9:
-                     (*prin) (stream, "    LD      %s,Y+", rd);
-                     break;
-                   case 0xa:
-                     (*prin) (stream, "    LD      %s,-Y", rd);
-                     break;
-                   case 0xc:
-                     (*prin) (stream, "    LD      %s,X", rd);
-                     break;
-                   case 0xd:
-                     (*prin) (stream, "    LD      %s,X+", rd);
-                     break;
-                   case 0xe:
-                     (*prin) (stream, "    LD      %s,-X", rd);
-                     break;
-                   case 0xf:
-                     (*prin) (stream, "    POP     %s", rd);
-                     break;
-                   default:
-                     (*prin) (stream, "    ????");
-                     break;
-                   }
-               }
-               break;
-             case 0x0200:
-               {
-                 reg50(opcode, rd);
-                 switch (opcode & 0xf)
-                   {
-                   case 0x0:
-                     {
-                       (*prin) (stream, "    STS     0x%04X,%s",
-                                avrdis_opcode(addr + 2, info), rd);
-                       cmd_len = 4;
-                     }
-                     break;
-                   case 0x1:
-                     (*prin) (stream, "    ST      Z+,%s", rd);
-                     break;
-                   case 0x2:
-                     (*prin) (stream, "    ST      -Z,%s", rd);
-                     break;
-                   case 0x9:
-                     (*prin) (stream, "    ST      Y+,%s", rd);
-                     break;
-                   case 0xa:
-                     (*prin) (stream, "    ST      -Y,%s", rd);
-                     break;
-                   case 0xc:
-                     (*prin) (stream, "    ST      X,%s", rd);
-                     break;
-                   case 0xd:
-                     (*prin) (stream, "    ST      X+,%s", rd);
-                     break;
-                   case 0xe:
-                     (*prin) (stream, "    ST      -X,%s", rd);
-                     break;
-                   case 0xf:
-                     (*prin) (stream, "    PUSH    %s", rd);
-                     break;
-                   default:
-                     (*prin) (stream, "    ????");
-                     break;
-                   }
-               }
-               break;
-             case 0x0400:
-               {
-                 if (IFMASK(0x020c, 0x000c))
-                   {
-                     u32 k = ((opcode & 0x01f0) >> 3) | (opcode & 1);
-                     k = (k << 16) | avrdis_opcode(addr + 2, info);
-                     if (opcode & 0x0002)
-                       (*prin) (stream, "    CALL    0x%06X", k*2);
-                     else
-                       (*prin) (stream, "    JMP     0x%06X", k*2);
-                     cmd_len = 4;
-                   }
-                 else if (IFMASK(0x010f, 0x0008))
-                   {
-                     int sf = (opcode & 0x70) >> 4;
-                     if (opcode & 0x0080)
-                       (*prin) (stream, "    CL%c", SREG_flags[sf]);
-                     else
-                       (*prin) (stream, "    SE%c", SREG_flags[sf]);
-                   }
-                 else if (IFMASK(0x001f, 0x0009))
-                   {
-                     if (opcode & 0x0100)
-                       (*prin) (stream, "    ICALL");
-                     else
-                       (*prin) (stream, "    IJMP");
-                   }
-                 else if (IFMASK(0x001f, 0x0019))
-                   {
-                     if (opcode & 0x0100)
-                       (*prin) (stream, "    EICALL");
-                     else
-                       (*prin) (stream, "    EIJMP");
-                   }
-                 else if (IFMASK(0x010f, 0x0108))
-                   {
-                     if (IFMASK(0x0090, 0x0000))
-                       (*prin) (stream, "    RET");
-                     else if (IFMASK(0x0090, 0x0010))
-                       (*prin) (stream, "    RETI");
-                     else if (IFMASK(0x00e0, 0x0080))
-                       (*prin) (stream, "    SLEEP");
-                     else if (IFMASK(0x00e0, 0x00a0))
-                       (*prin) (stream, "    WDR");
-                     else if (IFMASK(0x00f0, 0x00c0))
-                       (*prin) (stream, "    LPM");
-                     else if (IFMASK(0x00f0, 0x00d0))
-                       (*prin) (stream, "    ELPM");
-                     else if (IFMASK(0x00f0, 0x00e0))
-                       (*prin) (stream, "    SPM");
-                     else if (IFMASK(0x00f0, 0x00f0))
-                       (*prin) (stream, "    ESPM");
-                     else
-                       (*prin) (stream, "    ????");
-                   }
-                 else
-                   {
-                     const char* p;
-                     reg50(opcode, rd);
-                     p = sect94[opcode & 0xf];
-                     if (!p)
-                       p = "????";
-                     (*prin) (stream, "    %-8s%s", p, rd);
-                   }
-               }
-               break;
-             case 0x0600:
-               {
-                 if (opcode & 0x0200)
-                   {
-                     lit204(opcode, rd);
-                     reg20w(opcode, rr);
-                     if (opcode & 0x0100)
-                       (*prin) (stream, "    SBIW    %s,%s", rr, rd);
-                     else
-                       (*prin) (stream, "    ADIW    %s,%s", rr, rd);
-                   }
-               }
-               break;
-             case 0x0800:
-             case 0x0a00:
-               {
-                 (*prin) (stream, "    %-8s0x%02X,%d",
-                          sect98[(opcode & 0x0300) >> 8],
-                          (opcode & 0xf8) >> 3,
-                          opcode & 7);
-               }
-               break;
-             default:
-               {
-                 reg50(opcode, rd);
-                 reg104(opcode, rr);
-                 (*prin) (stream, "    MUL     %s,%s", rd, rr);
-               }
-             }
-         }
-         break;
-        case 0xb000:
-         {
-           reg50(opcode, rd);
-           regPP(opcode, rr);
-           if (opcode & 0x0800)
-             (*prin) (stream, "    OUT     %s,%s", rr, rd);
-           else
-             (*prin) (stream, "    IN      %s,%s", rd, rr);
-         }
-         break;
-        case 0xc000:
-         {
-           add0fff(opcode, rd, addr);
-           (*prin) (stream, "    RJMP    %s", rd);
-         }
-         break;
-        case 0xd000:
-         {
-           add0fff(opcode, rd, addr);
-           (*prin) (stream, "    RCALL   %s", rd);
-         }
-         break;
-        case 0xe000:
-         {
-           reg40(opcode, rd);
-           lit404(opcode, rr);
-           (*prin) (stream, "    LDI     %s,%s", rd, rr);
-         }
-         break;
-        case 0xf000:
-         {
-           if (opcode & 0x0800)
-             {
-               reg50(opcode, rd);
-               (*prin) (stream, "    %-8s%s,%d",
-                        last4[(opcode & 0x0600) >> 9],
-                        rd, opcode & 7);
-             }
-           else
-             {
-               char* p;
-               add03f8(opcode, rd, addr);
-               p = branchs[((opcode & 0x0400) >> 7) | (opcode & 7)];
-               (*prin) (stream, "    %-8s%s", p, rd);
-             }
-         }
-         break;
-        }
-    }
   return cmd_len;
 }
This page took 0.049176 seconds and 4 git commands to generate.