* avr-tdep.c (avr_extract_return_value): New function.
[deliverable/binutils-gdb.git] / gdb / avr-tdep.c
index 59fcf10d64c451859db01599bfccd5aa2e20def3..cb23746819eb9aa7441e03a7f3e120efb75fde9e 100644 (file)
@@ -19,7 +19,7 @@
    Foundation, Inc., 59 Temple Place - Suite 330,
    Boston, MA 02111-1307, USA.  */
 
-/* Contributed by Theodore A. Roth, troth@verinet.com */
+/* Contributed by Theodore A. Roth, troth@openavr.org */
 
 /* Portions of this file were taken from the original gdb-4.18 patch developed
    by Denis Chertykov, denisc@overta.ru */
@@ -176,60 +176,18 @@ avr_register_name (int regnum)
   return register_names[regnum];
 }
 
-/* Index within `registers' of the first byte of the space for
-   register REGNUM.  */
-
-static int
-avr_register_byte (int regnum)
-{
-  if (regnum < AVR_PC_REGNUM)
-    return regnum;
-  else
-    return AVR_PC_REG_INDEX;
-}
-
-/* Number of bytes of storage in the actual machine representation for
-   register REGNUM.  */
-
-static int
-avr_register_raw_size (int regnum)
-{
-  switch (regnum)
-    {
-    case AVR_PC_REGNUM:
-      return 4;
-    case AVR_SP_REGNUM:
-    case AVR_FP_REGNUM:
-      return 2;
-    default:
-      return 1;
-    }
-}
-
-/* Number of bytes of storage in the program's representation
-   for register N.  */
-
-static int
-avr_register_virtual_size (int regnum)
-{
-  return TYPE_LENGTH (REGISTER_VIRTUAL_TYPE (regnum));
-}
-
 /* Return the GDB type object for the "standard" data type
    of data in register N.  */
 
 static struct type *
-avr_register_virtual_type (int regnum)
+avr_register_type (struct gdbarch *gdbarch, int reg_nr)
 {
-  switch (regnum)
-    {
-    case AVR_PC_REGNUM:
-      return builtin_type_unsigned_long;
-    case AVR_SP_REGNUM:
-      return builtin_type_unsigned_short;
-    default:
-      return builtin_type_unsigned_char;
-    }
+  if (reg_nr == AVR_PC_REGNUM)
+    return builtin_type_uint32;
+  if (reg_nr == AVR_SP_REGNUM)
+    return builtin_type_void_data_ptr;
+  else
+    return builtin_type_uint8;
 }
 
 /* Instruction address checks and convertions. */
@@ -311,7 +269,7 @@ avr_address_to_pointer (struct type *type, void *buf, CORE_ADDR addr)
       || TYPE_CODE (TYPE_TARGET_TYPE (type)) == TYPE_CODE_METHOD)
     {
       store_unsigned_integer (buf, TYPE_LENGTH (type),
-                             avr_convert_iaddr_to_raw (addr));
+                             avr_convert_iaddr_to_raw (addr >> 1));
     }
   else
     {
@@ -324,21 +282,13 @@ avr_address_to_pointer (struct type *type, void *buf, CORE_ADDR addr)
 static CORE_ADDR
 avr_pointer_to_address (struct type *type, const void *buf)
 {
-  CORE_ADDR addr = extract_address (buf, TYPE_LENGTH (type));
-
-  if (TYPE_CODE_SPACE (TYPE_TARGET_TYPE (type)))
-    {
-      fprintf_unfiltered (gdb_stderr, "CODE_SPACE ---->> ptr->addr: 0x%lx\n",
-                         addr);
-      fprintf_unfiltered (gdb_stderr,
-                         "+++ If you see this, please send me an email <troth@verinet.com>\n");
-    }
+  CORE_ADDR addr = extract_unsigned_integer (buf, TYPE_LENGTH (type));
 
   /* Is it a code address?  */
   if (TYPE_CODE (TYPE_TARGET_TYPE (type)) == TYPE_CODE_FUNC
       || TYPE_CODE (TYPE_TARGET_TYPE (type)) == TYPE_CODE_METHOD
       || TYPE_CODE_SPACE (TYPE_TARGET_TYPE (type)))
-    return avr_make_iaddr (addr);
+    return avr_make_iaddr (addr << 1);
   else
     return avr_make_saddr (addr);
 }
@@ -384,41 +334,16 @@ avr_write_sp (CORE_ADDR val)
 static CORE_ADDR
 avr_read_fp (void)
 {
-  return (avr_make_saddr (read_register (AVR_FP_REGNUM)));
-}
-
-/* Translate a GDB virtual ADDR/LEN into a format the remote target
-   understands.  Returns number of bytes that can be transfered
-   starting at TARG_ADDR.  Return ZERO if no bytes can be transfered
-   (segmentation fault).
-
-   TRoth/2002-04-08: Could this be used to check for dereferencing an invalid
-   pointer? */
-
-static void
-avr_remote_translate_xfer_address (CORE_ADDR memaddr, int nr_bytes,
-                                  CORE_ADDR *targ_addr, int *targ_len)
-{
-  long out_addr;
-  long out_len;
+  CORE_ADDR fp;
 
-  /* FIXME: TRoth: Do nothing for now. Will need to examine memaddr at this
-     point and see if the high bit are set with the masks that we want. */
+  fp = read_register (AVR_FP_REGNUM);
+  fp += (read_register (AVR_FP_REGNUM+1) << 8);
 
-  *targ_addr = memaddr;
-  *targ_len = nr_bytes;
+  return (avr_make_saddr (fp));
 }
 
-/* Function pointers obtained from the target are half of what gdb expects so
-   multiply by 2. */
-
-static CORE_ADDR
-avr_convert_from_func_ptr_addr (CORE_ADDR addr)
-{
-  return addr * 2;
-}
-
-/* avr_scan_prologue is also used as the frame_init_saved_regs().
+/* avr_scan_prologue is also used as the
+   deprecated_frame_init_saved_regs().
 
    Put here the code to store, into fi->saved_regs, the addresses of
    the saved registers of frame described by FRAME_INFO.  This
@@ -433,26 +358,81 @@ avr_convert_from_func_ptr_addr (CORE_ADDR addr)
      3) the offsets of saved regs
    This information is stored in the "extra_info" field of the frame_info.
 
-   A typical AVR function prologue might look like this:
-        push rXX
-        push r28
-        push r29
-        in r28,__SP_L__
-        in r29,__SP_H__
-        sbiw r28,<LOCALS_SIZE>
-        in __tmp_reg__,__SREG__
+   Some devices lack the sbiw instruction, so on those replace this:
+        sbiw    r28, XX
+   with this:
+        subi    r28,lo8(XX)
+        sbci    r29,hi8(XX)
+
+   A typical AVR function prologue with a frame pointer might look like this:
+        push    rXX        ; saved regs
+        ...
+        push    r28
+        push    r29
+        in      r28,__SP_L__
+        in      r29,__SP_H__
+        sbiw    r28,<LOCALS_SIZE>
+        in      __tmp_reg__,__SREG__
+        cli
+        out     __SP_H__,r29
+        out     __SREG__,__tmp_reg__
+        out     __SP_L__,r28
+
+   A typical AVR function prologue without a frame pointer might look like
+   this:
+        push    rXX        ; saved regs
+        ...
+
+   A main function prologue looks like this:
+        ldi     r28,lo8(<RAM_ADDR> - <LOCALS_SIZE>)
+        ldi     r29,hi8(<RAM_ADDR> - <LOCALS_SIZE>)
+        out     __SP_H__,r29
+        out     __SP_L__,r28
+
+   A signal handler prologue looks like this:
+        push    __zero_reg__
+        push    __tmp_reg__
+        in      __tmp_reg__, __SREG__
+        push    __tmp_reg__
+        clr     __zero_reg__
+        push    rXX             ; save registers r18:r27, r30:r31
+        ...
+        push    r28             ; save frame pointer
+        push    r29
+        in      r28, __SP_L__
+        in      r29, __SP_H__
+        sbiw    r28, <LOCALS_SIZE>
+        out     __SP_H__, r29
+        out     __SP_L__, r28
+        
+   A interrupt handler prologue looks like this:
+        sei
+        push    __zero_reg__
+        push    __tmp_reg__
+        in      __tmp_reg__, __SREG__
+        push    __tmp_reg__
+        clr     __zero_reg__
+        push    rXX             ; save registers r18:r27, r30:r31
+        ...
+        push    r28             ; save frame pointer
+        push    r29
+        in      r28, __SP_L__
+        in      r29, __SP_H__
+        sbiw    r28, <LOCALS_SIZE>
         cli
-        out __SP_L__,r28
-        out __SREG__,__tmp_reg__
-        out __SP_H__,r29
-
-  A `-mcall-prologues' prologue look like this:
-        ldi r26,<LOCALS_SIZE>
-        ldi r27,<LOCALS_SIZE>/265
-        ldi r30,pm_lo8(.L_foo_body)
-        ldi r31,pm_hi8(.L_foo_body)
-        rjmp __prologue_saves__+RRR
-  .L_foo_body:  */
+        out     __SP_H__, r29
+        sei     
+        out     __SP_L__, r28
+
+   A `-mcall-prologues' prologue looks like this (Note that the megas use a
+   jmp instead of a rjmp, thus the prologue is one word larger since jmp is a
+   32 bit insn and rjmp is a 16 bit insn):
+        ldi     r26,lo8(<LOCALS_SIZE>)
+        ldi     r27,hi8(<LOCALS_SIZE>)
+        ldi     r30,pm_lo8(.L_foo_body)
+        ldi     r31,pm_hi8(.L_foo_body)
+        rjmp    __prologue_saves__+RRR
+        .L_foo_body:  */
 
 static void
 avr_scan_prologue (struct frame_info *fi)
@@ -469,7 +449,7 @@ avr_scan_prologue (struct frame_info *fi)
   unsigned char prologue[AVR_MAX_PROLOGUE_SIZE];
   int vpc = 0;
 
-  fi->extra_info->framereg = AVR_SP_REGNUM;
+  get_frame_extra_info (fi)->framereg = AVR_SP_REGNUM;
 
   if (find_pc_partial_function
       (get_frame_pc (fi), &name, &prologue_start, &prologue_end))
@@ -491,8 +471,8 @@ avr_scan_prologue (struct frame_info *fi)
   /* Search the prologue looking for instructions that set up the
      frame pointer, adjust the stack pointer, and save registers.  */
 
-  fi->extra_info->framesize = 0;
-  prologue_len = prologue_end - prologue_start;
+  get_frame_extra_info (fi)->framesize = 0;
+  prologue_len = min (prologue_end - prologue_start, AVR_MAX_PROLOGUE_SIZE);
   read_memory (prologue_start, prologue, prologue_len);
 
   /* Scanning main()'s prologue
@@ -509,7 +489,7 @@ avr_scan_prologue (struct frame_info *fi)
        0xcd, 0xbf              /* out __SP_L__,r28 */
       };
 
-      fi->extra_info->framereg = AVR_FP_REGNUM;
+      get_frame_extra_info (fi)->framereg = AVR_FP_REGNUM;
       insn = EXTRACT_INSN (&prologue[vpc]);
       /* ldi r28,lo8(<RAM_ADDR> - <LOCALS_SIZE>) */
       if ((insn & 0xf0f0) == 0xe0c0)
@@ -524,17 +504,16 @@ avr_scan_prologue (struct frame_info *fi)
                {
                  deprecated_update_frame_base_hack (fi, locals);
 
-                 fi->extra_info->is_main = 1;
+                 get_frame_extra_info (fi)->is_main = 1;
                  return;
                }
            }
        }
     }
 
-  /* Scanning `-mcall-prologues' prologue
-     FIXME: mega prologue have a 12 bytes long */
+  /* Scanning `-mcall-prologues' prologue  */
 
-  while (prologue_len <= 12)   /* I'm use while to avoit many goto's */
+  while (1)    /* Using a while to avoid many goto's */
     {
       int loc_size;
       int body_addr;
@@ -564,9 +543,6 @@ avr_scan_prologue (struct frame_info *fi)
        break;
       body_addr |= ((insn & 0xf) | ((insn & 0x0f00) >> 4)) << 8;
 
-      if (body_addr != (prologue_start + 10) / 2)
-       break;
-
       msymbol = lookup_minimal_symbol ("__prologue_saves__", NULL, NULL);
       if (!msymbol)
        break;
@@ -574,15 +550,33 @@ avr_scan_prologue (struct frame_info *fi)
       /* FIXME: prologue for mega have a JMP instead of RJMP */
       insn = EXTRACT_INSN (&prologue[vpc + 8]);
       /* rjmp __prologue_saves__+RRR */
-      if ((insn & 0xf000) != 0xc000)
-       break;
+      if ((insn & 0xf000) == 0xc000)
+        {
+          /* Extract PC relative offset from RJMP */
+          i = (insn & 0xfff) | (insn & 0x800 ? (-1 ^ 0xfff) : 0);
+          /* Convert offset to byte addressable mode */
+          i *= 2;
+          /* Destination address */
+          i += prologue_start + 10;
+
+          if (body_addr != (prologue_start + 10) / 2)
+            break;
+        }
+      /* jmp __prologue_saves__+RRR */
+      else if ((insn & 0xfe0e) == 0x940c)
+        {
+          /* Extract absolute PC address from JMP */
+          i = (((insn & 0x1) | ((insn & 0x1f0) >> 3) << 16)
+            | (EXTRACT_INSN (&prologue[vpc + 10]) & 0xffff));
+          /* Convert address to byte addressable mode */
+          i *= 2;
+
+          if (body_addr != (prologue_start + 12)/2)
+            break;
+        }
+      else
+        break;
 
-      /* Extract PC relative offset from RJMP */
-      i = (insn & 0xfff) | (insn & 0x800 ? (-1 ^ 0xfff) : 0);
-      /* Convert offset to byte addressable mode */
-      i *= 2;
-      /* Destination address */
-      i += vpc + prologue_start + 10;
       /* Resovle offset (in words) from __prologue_saves__ symbol.
          Which is a pushes count in `-mcall-prologues' mode */
       num_pushes = AVR_MAX_PUSHES - (i - SYMBOL_VALUE_ADDRESS (msymbol)) / 2;
@@ -601,9 +595,9 @@ avr_scan_prologue (struct frame_info *fi)
               from <= AVR_LAST_PUSHED_REGNUM; ++from)
            get_frame_saved_regs (fi)[from] = ++i;
        }
-      fi->extra_info->locals_size = loc_size;
-      fi->extra_info->framesize = loc_size + num_pushes;
-      fi->extra_info->framereg = AVR_FP_REGNUM;
+      get_frame_extra_info (fi)->locals_size = loc_size;
+      get_frame_extra_info (fi)->framesize = loc_size + num_pushes;
+      get_frame_extra_info (fi)->framereg = AVR_FP_REGNUM;
       return;
     }
 
@@ -624,14 +618,14 @@ avr_scan_prologue (struct frame_info *fi)
          vpc += sizeof (img);
          get_frame_saved_regs (fi)[0] = 2;
          get_frame_saved_regs (fi)[1] = 1;
-         fi->extra_info->framesize += 3;
+         get_frame_extra_info (fi)->framesize += 3;
        }
       else if (memcmp (img + 1, prologue, sizeof (img) - 1) == 0)
        {
          vpc += sizeof (img) - 1;
          get_frame_saved_regs (fi)[0] = 2;
          get_frame_saved_regs (fi)[1] = 1;
-         fi->extra_info->framesize += 3;
+         get_frame_extra_info (fi)->framesize += 3;
        }
     }
 
@@ -645,8 +639,8 @@ avr_scan_prologue (struct frame_info *fi)
        {
          /* Bits 4-9 contain a mask for registers R0-R32. */
          regno = (insn & 0x1f0) >> 4;
-         ++fi->extra_info->framesize;
-         get_frame_saved_regs (fi)[regno] = fi->extra_info->framesize;
+         ++get_frame_extra_info (fi)->framesize;
+         get_frame_saved_regs (fi)[regno] = get_frame_extra_info (fi)->framesize;
          scan_stage = 1;
        }
       else
@@ -669,7 +663,7 @@ avr_scan_prologue (struct frame_info *fi)
       if (memcmp (prologue + vpc, img, sizeof (img)) == 0)
        {
          vpc += 4;
-         fi->extra_info->framereg = AVR_FP_REGNUM;
+         get_frame_extra_info (fi)->framereg = AVR_FP_REGNUM;
          scan_stage = 2;
        }
     }
@@ -677,12 +671,12 @@ avr_scan_prologue (struct frame_info *fi)
   /* Third stage of the prologue scanning. (Really two stages)
      Scan for:
      sbiw r28,XX or subi r28,lo8(XX)
-     sbci r29,hi8(XX)
+                    sbci r29,hi8(XX)
      in __tmp_reg__,__SREG__
      cli
-     out __SP_L__,r28
+     out __SP_H__,r29
      out __SREG__,__tmp_reg__
-     out __SP_H__,r29 */
+     out __SP_L__,r28 */
 
   if (scan_stage == 2 && vpc + 12 <= prologue_len)
     {
@@ -690,19 +684,19 @@ avr_scan_prologue (struct frame_info *fi)
       unsigned char img[] = {
        0x0f, 0xb6,             /* in r0,0x3f */
        0xf8, 0x94,             /* cli */
-       0xcd, 0xbf,             /* out 0x3d,r28 ; SPL */
+       0xde, 0xbf,             /* out 0x3e,r29 ; SPH */
        0x0f, 0xbe,             /* out 0x3f,r0  ; SREG */
-       0xde, 0xbf              /* out 0x3e,r29 ; SPH */
+       0xcd, 0xbf              /* out 0x3d,r28 ; SPL */
       };
       unsigned char img_sig[] = {
-       0xcd, 0xbf,             /* out 0x3d,r28 ; SPL */
-       0xde, 0xbf              /* out 0x3e,r29 ; SPH */
+       0xde, 0xbf,             /* out 0x3e,r29 ; SPH */
+       0xcd, 0xbf              /* out 0x3d,r28 ; SPL */
       };
       unsigned char img_int[] = {
        0xf8, 0x94,             /* cli */
-       0xcd, 0xbf,             /* out 0x3d,r28 ; SPL */
+       0xde, 0xbf,             /* out 0x3e,r29 ; SPH */
        0x78, 0x94,             /* sei */
-       0xde, 0xbf              /* out 0x3e,r29 ; SPH */
+       0xcd, 0xbf              /* out 0x3d,r28 ; SPL */
       };
 
       insn = EXTRACT_INSN (&prologue[vpc]);
@@ -718,8 +712,8 @@ avr_scan_prologue (struct frame_info *fi)
        }
       else
        return;
-      fi->extra_info->locals_size = locals_size;
-      fi->extra_info->framesize += locals_size;
+      get_frame_extra_info (fi)->locals_size = locals_size;
+      get_frame_extra_info (fi)->framesize += locals_size;
     }
 }
 
@@ -734,37 +728,41 @@ avr_init_extra_frame_info (int fromleaf, struct frame_info *fi)
 {
   int reg;
 
-  if (fi->next)
-    deprecated_update_frame_pc_hack (fi, FRAME_SAVED_PC (fi->next));
+  if (get_next_frame (fi))
+    deprecated_update_frame_pc_hack (fi, DEPRECATED_FRAME_SAVED_PC (get_next_frame (fi)));
 
   frame_extra_info_zalloc (fi, sizeof (struct frame_extra_info));
   frame_saved_regs_zalloc (fi);
 
-  fi->extra_info->return_pc = 0;
-  fi->extra_info->args_pointer = 0;
-  fi->extra_info->locals_size = 0;
-  fi->extra_info->framereg = 0;
-  fi->extra_info->framesize = 0;
-  fi->extra_info->is_main = 0;
+  get_frame_extra_info (fi)->return_pc = 0;
+  get_frame_extra_info (fi)->args_pointer = 0;
+  get_frame_extra_info (fi)->locals_size = 0;
+  get_frame_extra_info (fi)->framereg = 0;
+  get_frame_extra_info (fi)->framesize = 0;
+  get_frame_extra_info (fi)->is_main = 0;
 
   avr_scan_prologue (fi);
 
   if (DEPRECATED_PC_IN_CALL_DUMMY (get_frame_pc (fi), get_frame_base (fi),
                                   get_frame_base (fi)))
     {
-      /* We need to setup fi->frame here because run_stack_dummy gets it wrong
-         by assuming it's always FP.  */
+      /* We need to setup fi->frame here because call_function_by_hand
+         gets it wrong by assuming it's always FP.  */
       deprecated_update_frame_base_hack (fi, deprecated_read_register_dummy (get_frame_pc (fi), get_frame_base (fi),
                                                                             AVR_PC_REGNUM));
     }
-  else if (!fi->next)          /* this is the innermost frame? */
-    deprecated_update_frame_base_hack (fi, read_register (fi->extra_info->framereg));
-  else if (fi->extra_info->is_main != 1)       /* not the innermost frame, not `main' */
+  else if (!get_next_frame (fi))
+    /* this is the innermost frame? */
+    deprecated_update_frame_base_hack (fi, read_register (get_frame_extra_info (fi)->framereg));
+  else if (get_frame_extra_info (fi)->is_main != 1)
+    /* not the innermost frame, not `main' */
     /* If we have an next frame,  the callee saved it. */
     {
-      struct frame_info *next_fi = fi->next;
-      if (fi->extra_info->framereg == AVR_SP_REGNUM)
-       deprecated_update_frame_base_hack (fi, get_frame_base (next_fi) + 2 /* ret addr */ + next_fi->extra_info->framesize);
+      struct frame_info *next_fi = get_next_frame (fi);
+      if (get_frame_extra_info (fi)->framereg == AVR_SP_REGNUM)
+       deprecated_update_frame_base_hack (fi, (get_frame_base (next_fi)
+                                               + 2 /* ret addr */
+                                               + get_frame_extra_info (next_fi)->framesize));
       /* FIXME: I don't analyse va_args functions  */
       else
        {
@@ -773,7 +771,7 @@ avr_init_extra_frame_info (int fromleaf, struct frame_info *fi)
          unsigned int fp_low, fp_high;
 
          /* Scan all frames */
-         for (; next_fi; next_fi = next_fi->next)
+         for (; next_fi; next_fi = get_next_frame (next_fi))
            {
              /* look for saved AVR_FP_REGNUM */
              if (get_frame_saved_regs (next_fi)[AVR_FP_REGNUM] && !fp)
@@ -794,23 +792,24 @@ avr_init_extra_frame_info (int fromleaf, struct frame_info *fi)
   /* TRoth: Do we want to do this if we are in main? I don't think we should
      since return_pc makes no sense when we are in main. */
 
-  if ((get_frame_pc (fi)) && (fi->extra_info->is_main == 0))   /* We are not in CALL_DUMMY */
+  if ((get_frame_pc (fi)) && (get_frame_extra_info (fi)->is_main == 0))
+    /* We are not in CALL_DUMMY */
     {
       CORE_ADDR addr;
       int i;
 
-      addr = get_frame_base (fi) + fi->extra_info->framesize + 1;
+      addr = get_frame_base (fi) + get_frame_extra_info (fi)->framesize + 1;
 
       /* Return address in stack in different endianness */
 
-      fi->extra_info->return_pc =
+      get_frame_extra_info (fi)->return_pc =
        read_memory_unsigned_integer (avr_make_saddr (addr), 1) << 8;
-      fi->extra_info->return_pc |=
+      get_frame_extra_info (fi)->return_pc |=
        read_memory_unsigned_integer (avr_make_saddr (addr + 1), 1);
 
       /* This return address in words,
          must be converted to the bytes address */
-      fi->extra_info->return_pc *= 2;
+      get_frame_extra_info (fi)->return_pc *= 2;
 
       /* Resolve a pushed registers addresses */
       for (i = 0; i < NUM_REGS; i++)
@@ -857,7 +856,7 @@ avr_pop_frame (void)
        }
 
       /* Don't forget the update the PC too!  */
-      write_pc (frame->extra_info->return_pc);
+      write_pc (get_frame_extra_info (frame)->return_pc);
     }
   flush_cached_frames ();
 }
@@ -874,7 +873,7 @@ avr_frame_saved_pc (struct frame_info *frame)
                                           get_frame_base (frame),
                                           AVR_PC_REGNUM);
   else
-    return frame->extra_info->return_pc;
+    return get_frame_extra_info (frame)->return_pc;
 }
 
 static CORE_ADDR
@@ -887,34 +886,6 @@ avr_saved_pc_after_call (struct frame_info *frame)
   return (m2 | (m1 << 8)) * 2;
 }
 
-/* Figure out where in REGBUF the called function has left its return value.
-   Copy that into VALBUF. */
-
-static void
-avr_extract_return_value (struct type *type, char *regbuf, char *valbuf)
-{
-  int wordsize, len;
-
-  wordsize = 2;
-
-  len = TYPE_LENGTH (type);
-
-  switch (len)
-    {
-    case 1:                    /* (char) */
-    case 2:                    /* (short), (int) */
-      memcpy (valbuf, regbuf + REGISTER_BYTE (24), 2);
-      break;
-    case 4:                    /* (long), (float) */
-      memcpy (valbuf, regbuf + REGISTER_BYTE (22), 4);
-      break;
-    case 8:                    /* (double) (doesn't seem to happen, which is good,
-                                  because this almost certainly isn't right.  */
-      error ("I don't know how a double is returned.");
-      break;
-    }
-}
-
 /* Returns the return address for a dummy. */
 
 static CORE_ADDR
@@ -923,35 +894,6 @@ avr_call_dummy_address (void)
   return entry_point_address ();
 }
 
-/* Place the appropriate value in the appropriate registers.
-   Primarily used by the RETURN command.  */
-
-static void
-avr_store_return_value (struct type *type, char *valbuf)
-{
-  int wordsize, len, regval;
-
-  wordsize = 2;
-
-  len = TYPE_LENGTH (type);
-  switch (len)
-    {
-    case 1:                    /* char */
-    case 2:                    /* short, int */
-      regval = extract_address (valbuf, len);
-      write_register (0, regval);
-      break;
-    case 4:                    /* long, float */
-      regval = extract_address (valbuf, len);
-      write_register (0, regval >> 16);
-      write_register (1, regval & 0xffff);
-      break;
-    case 8:                    /* presumeably double, but doesn't seem to happen */
-      error ("I don't know how to return a double.");
-      break;
-    }
-}
-
 /* Setup the return address for a dummy frame, as called by
    call_function_by_hand.  Only necessary when you are using an empty
    CALL_DUMMY. */
@@ -1026,8 +968,8 @@ avr_frame_address (struct frame_info *fi)
 
 /* Given a GDB frame, determine the address of the calling function's
    frame.  This will be used to create a new GDB frame struct, and
-   then INIT_EXTRA_FRAME_INFO and DEPRECATED_INIT_FRAME_PC will be
-   called for the new frame.
+   then DEPRECATED_INIT_EXTRA_FRAME_INFO and DEPRECATED_INIT_FRAME_PC
+   will be called for the new frame.
 
    For us, the frame address is its stack pointer value, so we look up
    the function prologue to determine the caller's sp value, and return it.  */
@@ -1040,14 +982,14 @@ avr_frame_chain (struct frame_info *frame)
                                   get_frame_base (frame)))
     {
       /* initialize the return_pc now */
-      frame->extra_info->return_pc
+      get_frame_extra_info (frame)->return_pc
        = deprecated_read_register_dummy (get_frame_pc (frame),
                                          get_frame_base (frame),
                                          AVR_PC_REGNUM);
       return get_frame_base (frame);
     }
-  return (frame->extra_info->is_main ? 0
-         : get_frame_base (frame) + frame->extra_info->framesize + 2 /* ret addr */ );
+  return (get_frame_extra_info (frame)->is_main ? 0
+         : get_frame_base (frame) + get_frame_extra_info (frame)->framesize + 2 /* ret addr */ );
 }
 
 /* Store the address of the place in which to copy the structure the
@@ -1062,17 +1004,6 @@ avr_store_struct_return (CORE_ADDR addr, CORE_ADDR sp)
   write_register (0, addr);
 }
 
-/* Extract from an array REGBUF containing the (raw) register state
-   the address in which a function should return its structure value,
-   as a CORE_ADDR (or an expression that can be used as one). */
-
-static CORE_ADDR
-avr_extract_struct_value_address (char *regbuf)
-{
-  return (extract_address ((regbuf) + REGISTER_BYTE (0),
-                          REGISTER_RAW_SIZE (0)) | AVR_SMEM_START);
-}
-
 /* Setup the function arguments for calling a function in the inferior.
 
    On the AVR architecture, there are 18 registers (R25 to R8) which are
@@ -1144,24 +1075,63 @@ avr_push_arguments (int nargs, struct value **args, CORE_ADDR sp,
       while (len > 0)
        {                       /* there's room in registers */
          len -= wordsize;
-         regval = extract_address (val + len, wordsize);
+         regval = extract_unsigned_integer (val + len, wordsize);
          write_register (argreg--, regval);
        }
     }
   return sp;
 }
 
+/* Not all avr devices support the BREAK insn. Those that don't should treat
+   it as a NOP. Thus, it should be ok. Since the avr is currently a remote
+   only target, this shouldn't be a problem (I hope). TRoth/2003-05-14  */
+
+static const unsigned char *
+avr_breakpoint_from_pc (CORE_ADDR * pcptr, int *lenptr)
+{
+    static unsigned char avr_break_insn [] = { 0x98, 0x95 };
+    *lenptr = sizeof (avr_break_insn);
+    return avr_break_insn;
+}
+
+/* Given a return value in `regbuf' with a type `valtype', 
+   extract and copy its value into `valbuf'.
+
+   Return values are always passed via registers r25:r24:...  */
+
+static void
+avr_extract_return_value (struct type *type, struct regcache *regcache,
+                          void *valbuf)
+{
+  if (TYPE_LENGTH (type) == 1)
+    {
+      ULONGEST c;
+
+      /* For single byte return values, r25 is always cleared, so we can
+         ignore it.  */
+      regcache_cooked_read_unsigned (regcache, 24, &c);
+      store_unsigned_integer (valbuf, 1, c);
+    }
+  else
+    {
+      int i;
+      /* The MSB of the return value is always in r25, calculate which
+         register holds the LSB.  */
+      int lsb_reg = 25 - TYPE_LENGTH (type) + 1;
+
+      for (i=0; i< TYPE_LENGTH (type); i++)
+        {
+          regcache_cooked_read (regcache, lsb_reg + i,
+                                (bfd_byte *) valbuf + i);
+        }
+    }
+}
+
 /* Initialize the gdbarch structure for the AVR's. */
 
 static struct gdbarch *
 avr_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches)
 {
-  /* FIXME: TRoth/2002-02-18: I have no idea if avr_call_dummy_words[] should
-     be bigger or not. Initial testing seems to show that `call my_func()`
-     works and backtrace from a breakpoint within the call looks correct.
-     Admittedly, I haven't tested with more than a very simple program. */
-  static LONGEST avr_call_dummy_words[] = { 0 };
-
   struct gdbarch *gdbarch;
   struct gdbarch_tdep *tdep;
 
@@ -1207,77 +1177,50 @@ avr_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches)
 
   set_gdbarch_read_pc (gdbarch, avr_read_pc);
   set_gdbarch_write_pc (gdbarch, avr_write_pc);
-  set_gdbarch_read_fp (gdbarch, avr_read_fp);
+  set_gdbarch_deprecated_target_read_fp (gdbarch, avr_read_fp);
   set_gdbarch_read_sp (gdbarch, avr_read_sp);
-  set_gdbarch_write_sp (gdbarch, avr_write_sp);
+  set_gdbarch_deprecated_dummy_write_sp (gdbarch, avr_write_sp);
 
   set_gdbarch_num_regs (gdbarch, AVR_NUM_REGS);
 
   set_gdbarch_sp_regnum (gdbarch, AVR_SP_REGNUM);
-  set_gdbarch_fp_regnum (gdbarch, AVR_FP_REGNUM);
+  set_gdbarch_deprecated_fp_regnum (gdbarch, AVR_FP_REGNUM);
   set_gdbarch_pc_regnum (gdbarch, AVR_PC_REGNUM);
 
   set_gdbarch_register_name (gdbarch, avr_register_name);
-  set_gdbarch_register_size (gdbarch, 1);
-  set_gdbarch_register_bytes (gdbarch, AVR_NUM_REG_BYTES);
-  set_gdbarch_register_byte (gdbarch, avr_register_byte);
-  set_gdbarch_register_raw_size (gdbarch, avr_register_raw_size);
-  set_gdbarch_max_register_raw_size (gdbarch, 4);
-  set_gdbarch_register_virtual_size (gdbarch, avr_register_virtual_size);
-  set_gdbarch_max_register_virtual_size (gdbarch, 4);
-  set_gdbarch_register_virtual_type (gdbarch, avr_register_virtual_type);
+  set_gdbarch_register_type (gdbarch, avr_register_type);
 
+  set_gdbarch_extract_return_value (gdbarch, avr_extract_return_value);
   set_gdbarch_print_insn (gdbarch, print_insn_avr);
 
   set_gdbarch_call_dummy_address (gdbarch, avr_call_dummy_address);
-  set_gdbarch_call_dummy_start_offset (gdbarch, 0);
-  set_gdbarch_call_dummy_breakpoint_offset_p (gdbarch, 1);
-  set_gdbarch_call_dummy_breakpoint_offset (gdbarch, 0);
-  set_gdbarch_call_dummy_length (gdbarch, 0);
-  set_gdbarch_call_dummy_p (gdbarch, 1);
-  set_gdbarch_call_dummy_words (gdbarch, avr_call_dummy_words);
-  set_gdbarch_call_dummy_stack_adjust_p (gdbarch, 0);
-  set_gdbarch_fix_call_dummy (gdbarch, generic_fix_call_dummy);
-
-/*    set_gdbarch_believe_pcc_promotion (gdbarch, 1); // TRoth: should this be set? */
 
   set_gdbarch_address_to_pointer (gdbarch, avr_address_to_pointer);
   set_gdbarch_pointer_to_address (gdbarch, avr_pointer_to_address);
-  set_gdbarch_deprecated_extract_return_value (gdbarch, avr_extract_return_value);
-  set_gdbarch_push_arguments (gdbarch, avr_push_arguments);
-  set_gdbarch_push_dummy_frame (gdbarch, generic_push_dummy_frame);
-  set_gdbarch_push_return_address (gdbarch, avr_push_return_address);
-  set_gdbarch_pop_frame (gdbarch, avr_pop_frame);
-
-  set_gdbarch_deprecated_store_return_value (gdbarch, avr_store_return_value);
+  set_gdbarch_deprecated_push_arguments (gdbarch, avr_push_arguments);
+  set_gdbarch_deprecated_push_return_address (gdbarch, avr_push_return_address);
+  set_gdbarch_deprecated_pop_frame (gdbarch, avr_pop_frame);
 
   set_gdbarch_use_struct_convention (gdbarch, generic_use_struct_convention);
-  set_gdbarch_store_struct_return (gdbarch, avr_store_struct_return);
-  set_gdbarch_deprecated_extract_struct_value_address
-    (gdbarch, avr_extract_struct_value_address);
+  set_gdbarch_deprecated_store_struct_return (gdbarch, avr_store_struct_return);
 
-  set_gdbarch_frame_init_saved_regs (gdbarch, avr_scan_prologue);
-  set_gdbarch_init_extra_frame_info (gdbarch, avr_init_extra_frame_info);
+  set_gdbarch_deprecated_frame_init_saved_regs (gdbarch, avr_scan_prologue);
+  set_gdbarch_deprecated_init_extra_frame_info (gdbarch, avr_init_extra_frame_info);
   set_gdbarch_skip_prologue (gdbarch, avr_skip_prologue);
-/*    set_gdbarch_prologue_frameless_p (gdbarch, avr_prologue_frameless_p); */
   set_gdbarch_inner_than (gdbarch, core_addr_lessthan);
 
   set_gdbarch_decr_pc_after_break (gdbarch, 0);
+  set_gdbarch_breakpoint_from_pc (gdbarch, avr_breakpoint_from_pc);
 
   set_gdbarch_function_start_offset (gdbarch, 0);
-  set_gdbarch_remote_translate_xfer_address (gdbarch,
-                                            avr_remote_translate_xfer_address);
+
   set_gdbarch_frame_args_skip (gdbarch, 0);
   set_gdbarch_frameless_function_invocation (gdbarch, frameless_look_for_prologue);    /* ??? */
-  set_gdbarch_frame_chain (gdbarch, avr_frame_chain);
-  set_gdbarch_frame_saved_pc (gdbarch, avr_frame_saved_pc);
+  set_gdbarch_deprecated_frame_chain (gdbarch, avr_frame_chain);
+  set_gdbarch_deprecated_frame_saved_pc (gdbarch, avr_frame_saved_pc);
   set_gdbarch_frame_args_address (gdbarch, avr_frame_address);
   set_gdbarch_frame_locals_address (gdbarch, avr_frame_address);
-  set_gdbarch_saved_pc_after_call (gdbarch, avr_saved_pc_after_call);
-  set_gdbarch_frame_num_args (gdbarch, frame_num_args_unknown);
-
-  set_gdbarch_convert_from_func_ptr_addr (gdbarch,
-                                         avr_convert_from_func_ptr_addr);
+  set_gdbarch_deprecated_saved_pc_after_call (gdbarch, avr_saved_pc_after_call);
 
   return gdbarch;
 }
@@ -1306,13 +1249,11 @@ avr_io_reg_read_command (char *args, int from_tty)
   unsigned int val;
   int i, j, k, step;
 
-/*    fprintf_unfiltered (gdb_stderr, "DEBUG: avr_io_reg_read_command (\"%s\", %d)\n", */
-/*             args, from_tty); */
-
   if (!current_target.to_query)
     {
       fprintf_unfiltered (gdb_stderr,
-                         "ERR: info io_registers NOT supported by current target\n");
+                         "ERR: info io_registers NOT supported by current "
+                          "target\n");
       return;
     }
 
@@ -1348,7 +1289,10 @@ avr_io_reg_read_command (char *args, int from_tty)
 
   for (i = 0; i < nreg; i += step)
     {
-      j = step - (nreg % step);        /* how many registers this round? */
+      /* how many registers this round? */
+      j = step;
+      if ((i+j) >= nreg)
+        j = nreg - i;           /* last block is less than 8 registers */
 
       snprintf (query, sizeof (query) - 1, "avr.io_reg:%x,%x", i, j);
       target_query ((int) 'R', query, buf, &bufsiz);
@@ -1369,6 +1313,8 @@ avr_io_reg_read_command (char *args, int from_tty)
     }
 }
 
+extern initialize_file_ftype _initialize_avr_tdep; /* -Wmissing-prototypes */
+
 void
 _initialize_avr_tdep (void)
 {
This page took 0.036072 seconds and 4 git commands to generate.