OpenCores
URL https://opencores.org/ocsvn/openrisc/openrisc/trunk

Subversion Repositories openrisc

[/] [openrisc/] [trunk/] [gnu-old/] [gdb-7.1/] [gdb/] [rs6000-aix-tdep.c] - Diff between revs 834 and 842

Go to most recent revision | Only display areas with differences | Details | Blame | View Log

Rev 834 Rev 842
/* Native support code for PPC AIX, for GDB the GNU debugger.
/* Native support code for PPC AIX, for GDB the GNU debugger.
 
 
   Copyright (C) 2006, 2007, 2008, 2009, 2010 Free Software Foundation, Inc.
   Copyright (C) 2006, 2007, 2008, 2009, 2010 Free Software Foundation, Inc.
 
 
   Free Software Foundation, Inc.
   Free Software Foundation, Inc.
 
 
   This file is part of GDB.
   This file is part of GDB.
 
 
   This program is free software; you can redistribute it and/or modify
   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
   it under the terms of the GNU General Public License as published by
   the Free Software Foundation; either version 3 of the License, or
   the Free Software Foundation; either version 3 of the License, or
   (at your option) any later version.
   (at your option) any later version.
 
 
   This program is distributed in the hope that it will be useful,
   This program is distributed in the hope that it will be useful,
   but WITHOUT ANY WARRANTY; without even the implied warranty of
   but WITHOUT ANY WARRANTY; without even the implied warranty of
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   GNU General Public License for more details.
   GNU General Public License for more details.
 
 
   You should have received a copy of the GNU General Public License
   You should have received a copy of the GNU General Public License
   along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
   along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
 
 
#include "defs.h"
#include "defs.h"
#include "gdb_string.h"
#include "gdb_string.h"
#include "gdb_assert.h"
#include "gdb_assert.h"
#include "osabi.h"
#include "osabi.h"
#include "regcache.h"
#include "regcache.h"
#include "regset.h"
#include "regset.h"
#include "gdbtypes.h"
#include "gdbtypes.h"
#include "gdbcore.h"
#include "gdbcore.h"
#include "target.h"
#include "target.h"
#include "value.h"
#include "value.h"
#include "infcall.h"
#include "infcall.h"
#include "objfiles.h"
#include "objfiles.h"
#include "breakpoint.h"
#include "breakpoint.h"
#include "rs6000-tdep.h"
#include "rs6000-tdep.h"
#include "ppc-tdep.h"
#include "ppc-tdep.h"
 
 
/* Hook for determining the TOC address when calling functions in the
/* Hook for determining the TOC address when calling functions in the
   inferior under AIX. The initialization code in rs6000-nat.c sets
   inferior under AIX. The initialization code in rs6000-nat.c sets
   this hook to point to find_toc_address.  */
   this hook to point to find_toc_address.  */
 
 
CORE_ADDR (*rs6000_find_toc_address_hook) (CORE_ADDR) = NULL;
CORE_ADDR (*rs6000_find_toc_address_hook) (CORE_ADDR) = NULL;
 
 
/* If the kernel has to deliver a signal, it pushes a sigcontext
/* If the kernel has to deliver a signal, it pushes a sigcontext
   structure on the stack and then calls the signal handler, passing
   structure on the stack and then calls the signal handler, passing
   the address of the sigcontext in an argument register. Usually
   the address of the sigcontext in an argument register. Usually
   the signal handler doesn't save this register, so we have to
   the signal handler doesn't save this register, so we have to
   access the sigcontext structure via an offset from the signal handler
   access the sigcontext structure via an offset from the signal handler
   frame.
   frame.
   The following constants were determined by experimentation on AIX 3.2.  */
   The following constants were determined by experimentation on AIX 3.2.  */
#define SIG_FRAME_PC_OFFSET 96
#define SIG_FRAME_PC_OFFSET 96
#define SIG_FRAME_LR_OFFSET 108
#define SIG_FRAME_LR_OFFSET 108
#define SIG_FRAME_FP_OFFSET 284
#define SIG_FRAME_FP_OFFSET 284
 
 
 
 
/* Core file support.  */
/* Core file support.  */
 
 
static struct ppc_reg_offsets rs6000_aix32_reg_offsets =
static struct ppc_reg_offsets rs6000_aix32_reg_offsets =
{
{
  /* General-purpose registers.  */
  /* General-purpose registers.  */
  208, /* r0_offset */
  208, /* r0_offset */
  4,  /* gpr_size */
  4,  /* gpr_size */
  4,  /* xr_size */
  4,  /* xr_size */
  24, /* pc_offset */
  24, /* pc_offset */
  28, /* ps_offset */
  28, /* ps_offset */
  32, /* cr_offset */
  32, /* cr_offset */
  36, /* lr_offset */
  36, /* lr_offset */
  40, /* ctr_offset */
  40, /* ctr_offset */
  44, /* xer_offset */
  44, /* xer_offset */
  48, /* mq_offset */
  48, /* mq_offset */
 
 
  /* Floating-point registers.  */
  /* Floating-point registers.  */
  336, /* f0_offset */
  336, /* f0_offset */
  56, /* fpscr_offset */
  56, /* fpscr_offset */
  4,  /* fpscr_size */
  4,  /* fpscr_size */
 
 
  /* AltiVec registers.  */
  /* AltiVec registers.  */
  -1, /* vr0_offset */
  -1, /* vr0_offset */
  -1, /* vscr_offset */
  -1, /* vscr_offset */
  -1 /* vrsave_offset */
  -1 /* vrsave_offset */
};
};
 
 
static struct ppc_reg_offsets rs6000_aix64_reg_offsets =
static struct ppc_reg_offsets rs6000_aix64_reg_offsets =
{
{
  /* General-purpose registers.  */
  /* General-purpose registers.  */
  0, /* r0_offset */
  0, /* r0_offset */
  8,  /* gpr_size */
  8,  /* gpr_size */
  4,  /* xr_size */
  4,  /* xr_size */
  264, /* pc_offset */
  264, /* pc_offset */
  256, /* ps_offset */
  256, /* ps_offset */
  288, /* cr_offset */
  288, /* cr_offset */
  272, /* lr_offset */
  272, /* lr_offset */
  280, /* ctr_offset */
  280, /* ctr_offset */
  292, /* xer_offset */
  292, /* xer_offset */
  -1, /* mq_offset */
  -1, /* mq_offset */
 
 
  /* Floating-point registers.  */
  /* Floating-point registers.  */
  312, /* f0_offset */
  312, /* f0_offset */
  296, /* fpscr_offset */
  296, /* fpscr_offset */
  4,  /* fpscr_size */
  4,  /* fpscr_size */
 
 
  /* AltiVec registers.  */
  /* AltiVec registers.  */
  -1, /* vr0_offset */
  -1, /* vr0_offset */
  -1, /* vscr_offset */
  -1, /* vscr_offset */
  -1 /* vrsave_offset */
  -1 /* vrsave_offset */
};
};
 
 
 
 
/* Supply register REGNUM in the general-purpose register set REGSET
/* Supply register REGNUM in the general-purpose register set REGSET
   from the buffer specified by GREGS and LEN to register cache
   from the buffer specified by GREGS and LEN to register cache
   REGCACHE.  If REGNUM is -1, do this for all registers in REGSET.  */
   REGCACHE.  If REGNUM is -1, do this for all registers in REGSET.  */
 
 
static void
static void
rs6000_aix_supply_regset (const struct regset *regset,
rs6000_aix_supply_regset (const struct regset *regset,
                          struct regcache *regcache, int regnum,
                          struct regcache *regcache, int regnum,
                          const void *gregs, size_t len)
                          const void *gregs, size_t len)
{
{
  ppc_supply_gregset (regset, regcache, regnum, gregs, len);
  ppc_supply_gregset (regset, regcache, regnum, gregs, len);
  ppc_supply_fpregset (regset, regcache, regnum, gregs, len);
  ppc_supply_fpregset (regset, regcache, regnum, gregs, len);
}
}
 
 
/* Collect register REGNUM in the general-purpose register set
/* Collect register REGNUM in the general-purpose register set
   REGSET. from register cache REGCACHE into the buffer specified by
   REGSET. from register cache REGCACHE into the buffer specified by
   GREGS and LEN.  If REGNUM is -1, do this for all registers in
   GREGS and LEN.  If REGNUM is -1, do this for all registers in
   REGSET.  */
   REGSET.  */
 
 
static void
static void
rs6000_aix_collect_regset (const struct regset *regset,
rs6000_aix_collect_regset (const struct regset *regset,
                           const struct regcache *regcache, int regnum,
                           const struct regcache *regcache, int regnum,
                           void *gregs, size_t len)
                           void *gregs, size_t len)
{
{
  ppc_collect_gregset (regset, regcache, regnum, gregs, len);
  ppc_collect_gregset (regset, regcache, regnum, gregs, len);
  ppc_collect_fpregset (regset, regcache, regnum, gregs, len);
  ppc_collect_fpregset (regset, regcache, regnum, gregs, len);
}
}
 
 
/* AIX register set.  */
/* AIX register set.  */
 
 
static struct regset rs6000_aix32_regset =
static struct regset rs6000_aix32_regset =
{
{
  &rs6000_aix32_reg_offsets,
  &rs6000_aix32_reg_offsets,
  rs6000_aix_supply_regset,
  rs6000_aix_supply_regset,
  rs6000_aix_collect_regset,
  rs6000_aix_collect_regset,
};
};
 
 
static struct regset rs6000_aix64_regset =
static struct regset rs6000_aix64_regset =
{
{
  &rs6000_aix64_reg_offsets,
  &rs6000_aix64_reg_offsets,
  rs6000_aix_supply_regset,
  rs6000_aix_supply_regset,
  rs6000_aix_collect_regset,
  rs6000_aix_collect_regset,
};
};
 
 
/* Return the appropriate register set for the core section identified
/* Return the appropriate register set for the core section identified
   by SECT_NAME and SECT_SIZE.  */
   by SECT_NAME and SECT_SIZE.  */
 
 
static const struct regset *
static const struct regset *
rs6000_aix_regset_from_core_section (struct gdbarch *gdbarch,
rs6000_aix_regset_from_core_section (struct gdbarch *gdbarch,
                                     const char *sect_name, size_t sect_size)
                                     const char *sect_name, size_t sect_size)
{
{
  if (gdbarch_tdep (gdbarch)->wordsize == 4)
  if (gdbarch_tdep (gdbarch)->wordsize == 4)
    {
    {
      if (strcmp (sect_name, ".reg") == 0 && sect_size >= 592)
      if (strcmp (sect_name, ".reg") == 0 && sect_size >= 592)
        return &rs6000_aix32_regset;
        return &rs6000_aix32_regset;
    }
    }
  else
  else
    {
    {
      if (strcmp (sect_name, ".reg") == 0 && sect_size >= 576)
      if (strcmp (sect_name, ".reg") == 0 && sect_size >= 576)
        return &rs6000_aix64_regset;
        return &rs6000_aix64_regset;
    }
    }
 
 
  return NULL;
  return NULL;
}
}
 
 
 
 
/* Pass the arguments in either registers, or in the stack. In RS/6000,
/* Pass the arguments in either registers, or in the stack. In RS/6000,
   the first eight words of the argument list (that might be less than
   the first eight words of the argument list (that might be less than
   eight parameters if some parameters occupy more than one word) are
   eight parameters if some parameters occupy more than one word) are
   passed in r3..r10 registers.  float and double parameters are
   passed in r3..r10 registers.  float and double parameters are
   passed in fpr's, in addition to that.  Rest of the parameters if any
   passed in fpr's, in addition to that.  Rest of the parameters if any
   are passed in user stack.  There might be cases in which half of the
   are passed in user stack.  There might be cases in which half of the
   parameter is copied into registers, the other half is pushed into
   parameter is copied into registers, the other half is pushed into
   stack.
   stack.
 
 
   Stack must be aligned on 64-bit boundaries when synthesizing
   Stack must be aligned on 64-bit boundaries when synthesizing
   function calls.
   function calls.
 
 
   If the function is returning a structure, then the return address is passed
   If the function is returning a structure, then the return address is passed
   in r3, then the first 7 words of the parameters can be passed in registers,
   in r3, then the first 7 words of the parameters can be passed in registers,
   starting from r4.  */
   starting from r4.  */
 
 
static CORE_ADDR
static CORE_ADDR
rs6000_push_dummy_call (struct gdbarch *gdbarch, struct value *function,
rs6000_push_dummy_call (struct gdbarch *gdbarch, struct value *function,
                        struct regcache *regcache, CORE_ADDR bp_addr,
                        struct regcache *regcache, CORE_ADDR bp_addr,
                        int nargs, struct value **args, CORE_ADDR sp,
                        int nargs, struct value **args, CORE_ADDR sp,
                        int struct_return, CORE_ADDR struct_addr)
                        int struct_return, CORE_ADDR struct_addr)
{
{
  struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
  struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
  enum bfd_endian byte_order = gdbarch_byte_order (gdbarch);
  enum bfd_endian byte_order = gdbarch_byte_order (gdbarch);
  int ii;
  int ii;
  int len = 0;
  int len = 0;
  int argno;                    /* current argument number */
  int argno;                    /* current argument number */
  int argbytes;                 /* current argument byte */
  int argbytes;                 /* current argument byte */
  gdb_byte tmp_buffer[50];
  gdb_byte tmp_buffer[50];
  int f_argno = 0;               /* current floating point argno */
  int f_argno = 0;               /* current floating point argno */
  int wordsize = gdbarch_tdep (gdbarch)->wordsize;
  int wordsize = gdbarch_tdep (gdbarch)->wordsize;
  CORE_ADDR func_addr = find_function_addr (function, NULL);
  CORE_ADDR func_addr = find_function_addr (function, NULL);
 
 
  struct value *arg = 0;
  struct value *arg = 0;
  struct type *type;
  struct type *type;
 
 
  ULONGEST saved_sp;
  ULONGEST saved_sp;
 
 
  /* The calling convention this function implements assumes the
  /* The calling convention this function implements assumes the
     processor has floating-point registers.  We shouldn't be using it
     processor has floating-point registers.  We shouldn't be using it
     on PPC variants that lack them.  */
     on PPC variants that lack them.  */
  gdb_assert (ppc_floating_point_unit_p (gdbarch));
  gdb_assert (ppc_floating_point_unit_p (gdbarch));
 
 
  /* The first eight words of ther arguments are passed in registers.
  /* The first eight words of ther arguments are passed in registers.
     Copy them appropriately.  */
     Copy them appropriately.  */
  ii = 0;
  ii = 0;
 
 
  /* If the function is returning a `struct', then the first word
  /* If the function is returning a `struct', then the first word
     (which will be passed in r3) is used for struct return address.
     (which will be passed in r3) is used for struct return address.
     In that case we should advance one word and start from r4
     In that case we should advance one word and start from r4
     register to copy parameters.  */
     register to copy parameters.  */
  if (struct_return)
  if (struct_return)
    {
    {
      regcache_raw_write_unsigned (regcache, tdep->ppc_gp0_regnum + 3,
      regcache_raw_write_unsigned (regcache, tdep->ppc_gp0_regnum + 3,
                                   struct_addr);
                                   struct_addr);
      ii++;
      ii++;
    }
    }
 
 
/*
/*
   effectively indirect call... gcc does...
   effectively indirect call... gcc does...
 
 
   return_val example( float, int);
   return_val example( float, int);
 
 
   eabi:
   eabi:
   float in fp0, int in r3
   float in fp0, int in r3
   offset of stack on overflow 8/16
   offset of stack on overflow 8/16
   for varargs, must go by type.
   for varargs, must go by type.
   power open:
   power open:
   float in r3&r4, int in r5
   float in r3&r4, int in r5
   offset of stack on overflow different
   offset of stack on overflow different
   both:
   both:
   return in r3 or f0.  If no float, must study how gcc emulates floats;
   return in r3 or f0.  If no float, must study how gcc emulates floats;
   pay attention to arg promotion.
   pay attention to arg promotion.
   User may have to cast\args to handle promotion correctly
   User may have to cast\args to handle promotion correctly
   since gdb won't know if prototype supplied or not.
   since gdb won't know if prototype supplied or not.
 */
 */
 
 
  for (argno = 0, argbytes = 0; argno < nargs && ii < 8; ++ii)
  for (argno = 0, argbytes = 0; argno < nargs && ii < 8; ++ii)
    {
    {
      int reg_size = register_size (gdbarch, ii + 3);
      int reg_size = register_size (gdbarch, ii + 3);
 
 
      arg = args[argno];
      arg = args[argno];
      type = check_typedef (value_type (arg));
      type = check_typedef (value_type (arg));
      len = TYPE_LENGTH (type);
      len = TYPE_LENGTH (type);
 
 
      if (TYPE_CODE (type) == TYPE_CODE_FLT)
      if (TYPE_CODE (type) == TYPE_CODE_FLT)
        {
        {
 
 
          /* Floating point arguments are passed in fpr's, as well as gpr's.
          /* Floating point arguments are passed in fpr's, as well as gpr's.
             There are 13 fpr's reserved for passing parameters. At this point
             There are 13 fpr's reserved for passing parameters. At this point
             there is no way we would run out of them.  */
             there is no way we would run out of them.  */
 
 
          gdb_assert (len <= 8);
          gdb_assert (len <= 8);
 
 
          regcache_cooked_write (regcache,
          regcache_cooked_write (regcache,
                                 tdep->ppc_fp0_regnum + 1 + f_argno,
                                 tdep->ppc_fp0_regnum + 1 + f_argno,
                                 value_contents (arg));
                                 value_contents (arg));
          ++f_argno;
          ++f_argno;
        }
        }
 
 
      if (len > reg_size)
      if (len > reg_size)
        {
        {
 
 
          /* Argument takes more than one register.  */
          /* Argument takes more than one register.  */
          while (argbytes < len)
          while (argbytes < len)
            {
            {
              gdb_byte word[MAX_REGISTER_SIZE];
              gdb_byte word[MAX_REGISTER_SIZE];
              memset (word, 0, reg_size);
              memset (word, 0, reg_size);
              memcpy (word,
              memcpy (word,
                      ((char *) value_contents (arg)) + argbytes,
                      ((char *) value_contents (arg)) + argbytes,
                      (len - argbytes) > reg_size
                      (len - argbytes) > reg_size
                        ? reg_size : len - argbytes);
                        ? reg_size : len - argbytes);
              regcache_cooked_write (regcache,
              regcache_cooked_write (regcache,
                                    tdep->ppc_gp0_regnum + 3 + ii,
                                    tdep->ppc_gp0_regnum + 3 + ii,
                                    word);
                                    word);
              ++ii, argbytes += reg_size;
              ++ii, argbytes += reg_size;
 
 
              if (ii >= 8)
              if (ii >= 8)
                goto ran_out_of_registers_for_arguments;
                goto ran_out_of_registers_for_arguments;
            }
            }
          argbytes = 0;
          argbytes = 0;
          --ii;
          --ii;
        }
        }
      else
      else
        {
        {
          /* Argument can fit in one register.  No problem.  */
          /* Argument can fit in one register.  No problem.  */
          int adj = gdbarch_byte_order (gdbarch)
          int adj = gdbarch_byte_order (gdbarch)
                    == BFD_ENDIAN_BIG ? reg_size - len : 0;
                    == BFD_ENDIAN_BIG ? reg_size - len : 0;
          gdb_byte word[MAX_REGISTER_SIZE];
          gdb_byte word[MAX_REGISTER_SIZE];
 
 
          memset (word, 0, reg_size);
          memset (word, 0, reg_size);
          memcpy (word, value_contents (arg), len);
          memcpy (word, value_contents (arg), len);
          regcache_cooked_write (regcache, tdep->ppc_gp0_regnum + 3 +ii, word);
          regcache_cooked_write (regcache, tdep->ppc_gp0_regnum + 3 +ii, word);
        }
        }
      ++argno;
      ++argno;
    }
    }
 
 
ran_out_of_registers_for_arguments:
ran_out_of_registers_for_arguments:
 
 
  regcache_cooked_read_unsigned (regcache,
  regcache_cooked_read_unsigned (regcache,
                                 gdbarch_sp_regnum (gdbarch),
                                 gdbarch_sp_regnum (gdbarch),
                                 &saved_sp);
                                 &saved_sp);
 
 
  /* Location for 8 parameters are always reserved.  */
  /* Location for 8 parameters are always reserved.  */
  sp -= wordsize * 8;
  sp -= wordsize * 8;
 
 
  /* Another six words for back chain, TOC register, link register, etc.  */
  /* Another six words for back chain, TOC register, link register, etc.  */
  sp -= wordsize * 6;
  sp -= wordsize * 6;
 
 
  /* Stack pointer must be quadword aligned.  */
  /* Stack pointer must be quadword aligned.  */
  sp &= -16;
  sp &= -16;
 
 
  /* If there are more arguments, allocate space for them in
  /* If there are more arguments, allocate space for them in
     the stack, then push them starting from the ninth one.  */
     the stack, then push them starting from the ninth one.  */
 
 
  if ((argno < nargs) || argbytes)
  if ((argno < nargs) || argbytes)
    {
    {
      int space = 0, jj;
      int space = 0, jj;
 
 
      if (argbytes)
      if (argbytes)
        {
        {
          space += ((len - argbytes + 3) & -4);
          space += ((len - argbytes + 3) & -4);
          jj = argno + 1;
          jj = argno + 1;
        }
        }
      else
      else
        jj = argno;
        jj = argno;
 
 
      for (; jj < nargs; ++jj)
      for (; jj < nargs; ++jj)
        {
        {
          struct value *val = args[jj];
          struct value *val = args[jj];
          space += ((TYPE_LENGTH (value_type (val))) + 3) & -4;
          space += ((TYPE_LENGTH (value_type (val))) + 3) & -4;
        }
        }
 
 
      /* Add location required for the rest of the parameters.  */
      /* Add location required for the rest of the parameters.  */
      space = (space + 15) & -16;
      space = (space + 15) & -16;
      sp -= space;
      sp -= space;
 
 
      /* This is another instance we need to be concerned about
      /* This is another instance we need to be concerned about
         securing our stack space. If we write anything underneath %sp
         securing our stack space. If we write anything underneath %sp
         (r1), we might conflict with the kernel who thinks he is free
         (r1), we might conflict with the kernel who thinks he is free
         to use this area.  So, update %sp first before doing anything
         to use this area.  So, update %sp first before doing anything
         else.  */
         else.  */
 
 
      regcache_raw_write_signed (regcache,
      regcache_raw_write_signed (regcache,
                                 gdbarch_sp_regnum (gdbarch), sp);
                                 gdbarch_sp_regnum (gdbarch), sp);
 
 
      /* If the last argument copied into the registers didn't fit there
      /* If the last argument copied into the registers didn't fit there
         completely, push the rest of it into stack.  */
         completely, push the rest of it into stack.  */
 
 
      if (argbytes)
      if (argbytes)
        {
        {
          write_memory (sp + 24 + (ii * 4),
          write_memory (sp + 24 + (ii * 4),
                        value_contents (arg) + argbytes,
                        value_contents (arg) + argbytes,
                        len - argbytes);
                        len - argbytes);
          ++argno;
          ++argno;
          ii += ((len - argbytes + 3) & -4) / 4;
          ii += ((len - argbytes + 3) & -4) / 4;
        }
        }
 
 
      /* Push the rest of the arguments into stack.  */
      /* Push the rest of the arguments into stack.  */
      for (; argno < nargs; ++argno)
      for (; argno < nargs; ++argno)
        {
        {
 
 
          arg = args[argno];
          arg = args[argno];
          type = check_typedef (value_type (arg));
          type = check_typedef (value_type (arg));
          len = TYPE_LENGTH (type);
          len = TYPE_LENGTH (type);
 
 
 
 
          /* Float types should be passed in fpr's, as well as in the
          /* Float types should be passed in fpr's, as well as in the
             stack.  */
             stack.  */
          if (TYPE_CODE (type) == TYPE_CODE_FLT && f_argno < 13)
          if (TYPE_CODE (type) == TYPE_CODE_FLT && f_argno < 13)
            {
            {
 
 
              gdb_assert (len <= 8);
              gdb_assert (len <= 8);
 
 
              regcache_cooked_write (regcache,
              regcache_cooked_write (regcache,
                                     tdep->ppc_fp0_regnum + 1 + f_argno,
                                     tdep->ppc_fp0_regnum + 1 + f_argno,
                                     value_contents (arg));
                                     value_contents (arg));
              ++f_argno;
              ++f_argno;
            }
            }
 
 
          write_memory (sp + 24 + (ii * 4), value_contents (arg), len);
          write_memory (sp + 24 + (ii * 4), value_contents (arg), len);
          ii += ((len + 3) & -4) / 4;
          ii += ((len + 3) & -4) / 4;
        }
        }
    }
    }
 
 
  /* Set the stack pointer.  According to the ABI, the SP is meant to
  /* Set the stack pointer.  According to the ABI, the SP is meant to
     be set _before_ the corresponding stack space is used.  On AIX,
     be set _before_ the corresponding stack space is used.  On AIX,
     this even applies when the target has been completely stopped!
     this even applies when the target has been completely stopped!
     Not doing this can lead to conflicts with the kernel which thinks
     Not doing this can lead to conflicts with the kernel which thinks
     that it still has control over this not-yet-allocated stack
     that it still has control over this not-yet-allocated stack
     region.  */
     region.  */
  regcache_raw_write_signed (regcache, gdbarch_sp_regnum (gdbarch), sp);
  regcache_raw_write_signed (regcache, gdbarch_sp_regnum (gdbarch), sp);
 
 
  /* Set back chain properly.  */
  /* Set back chain properly.  */
  store_unsigned_integer (tmp_buffer, wordsize, byte_order, saved_sp);
  store_unsigned_integer (tmp_buffer, wordsize, byte_order, saved_sp);
  write_memory (sp, tmp_buffer, wordsize);
  write_memory (sp, tmp_buffer, wordsize);
 
 
  /* Point the inferior function call's return address at the dummy's
  /* Point the inferior function call's return address at the dummy's
     breakpoint.  */
     breakpoint.  */
  regcache_raw_write_signed (regcache, tdep->ppc_lr_regnum, bp_addr);
  regcache_raw_write_signed (regcache, tdep->ppc_lr_regnum, bp_addr);
 
 
  /* Set the TOC register, get the value from the objfile reader
  /* Set the TOC register, get the value from the objfile reader
     which, in turn, gets it from the VMAP table.  */
     which, in turn, gets it from the VMAP table.  */
  if (rs6000_find_toc_address_hook != NULL)
  if (rs6000_find_toc_address_hook != NULL)
    {
    {
      CORE_ADDR tocvalue = (*rs6000_find_toc_address_hook) (func_addr);
      CORE_ADDR tocvalue = (*rs6000_find_toc_address_hook) (func_addr);
      regcache_raw_write_signed (regcache, tdep->ppc_toc_regnum, tocvalue);
      regcache_raw_write_signed (regcache, tdep->ppc_toc_regnum, tocvalue);
    }
    }
 
 
  target_store_registers (regcache, -1);
  target_store_registers (regcache, -1);
  return sp;
  return sp;
}
}
 
 
static enum return_value_convention
static enum return_value_convention
rs6000_return_value (struct gdbarch *gdbarch, struct type *func_type,
rs6000_return_value (struct gdbarch *gdbarch, struct type *func_type,
                     struct type *valtype, struct regcache *regcache,
                     struct type *valtype, struct regcache *regcache,
                     gdb_byte *readbuf, const gdb_byte *writebuf)
                     gdb_byte *readbuf, const gdb_byte *writebuf)
{
{
  struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
  struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
  enum bfd_endian byte_order = gdbarch_byte_order (gdbarch);
  enum bfd_endian byte_order = gdbarch_byte_order (gdbarch);
  gdb_byte buf[8];
  gdb_byte buf[8];
 
 
  /* The calling convention this function implements assumes the
  /* The calling convention this function implements assumes the
     processor has floating-point registers.  We shouldn't be using it
     processor has floating-point registers.  We shouldn't be using it
     on PowerPC variants that lack them.  */
     on PowerPC variants that lack them.  */
  gdb_assert (ppc_floating_point_unit_p (gdbarch));
  gdb_assert (ppc_floating_point_unit_p (gdbarch));
 
 
  /* AltiVec extension: Functions that declare a vector data type as a
  /* AltiVec extension: Functions that declare a vector data type as a
     return value place that return value in VR2.  */
     return value place that return value in VR2.  */
  if (TYPE_CODE (valtype) == TYPE_CODE_ARRAY && TYPE_VECTOR (valtype)
  if (TYPE_CODE (valtype) == TYPE_CODE_ARRAY && TYPE_VECTOR (valtype)
      && TYPE_LENGTH (valtype) == 16)
      && TYPE_LENGTH (valtype) == 16)
    {
    {
      if (readbuf)
      if (readbuf)
        regcache_cooked_read (regcache, tdep->ppc_vr0_regnum + 2, readbuf);
        regcache_cooked_read (regcache, tdep->ppc_vr0_regnum + 2, readbuf);
      if (writebuf)
      if (writebuf)
        regcache_cooked_write (regcache, tdep->ppc_vr0_regnum + 2, writebuf);
        regcache_cooked_write (regcache, tdep->ppc_vr0_regnum + 2, writebuf);
 
 
      return RETURN_VALUE_REGISTER_CONVENTION;
      return RETURN_VALUE_REGISTER_CONVENTION;
    }
    }
 
 
  /* If the called subprogram returns an aggregate, there exists an
  /* If the called subprogram returns an aggregate, there exists an
     implicit first argument, whose value is the address of a caller-
     implicit first argument, whose value is the address of a caller-
     allocated buffer into which the callee is assumed to store its
     allocated buffer into which the callee is assumed to store its
     return value. All explicit parameters are appropriately
     return value. All explicit parameters are appropriately
     relabeled.  */
     relabeled.  */
  if (TYPE_CODE (valtype) == TYPE_CODE_STRUCT
  if (TYPE_CODE (valtype) == TYPE_CODE_STRUCT
      || TYPE_CODE (valtype) == TYPE_CODE_UNION
      || TYPE_CODE (valtype) == TYPE_CODE_UNION
      || TYPE_CODE (valtype) == TYPE_CODE_ARRAY)
      || TYPE_CODE (valtype) == TYPE_CODE_ARRAY)
    return RETURN_VALUE_STRUCT_CONVENTION;
    return RETURN_VALUE_STRUCT_CONVENTION;
 
 
  /* Scalar floating-point values are returned in FPR1 for float or
  /* Scalar floating-point values are returned in FPR1 for float or
     double, and in FPR1:FPR2 for quadword precision.  Fortran
     double, and in FPR1:FPR2 for quadword precision.  Fortran
     complex*8 and complex*16 are returned in FPR1:FPR2, and
     complex*8 and complex*16 are returned in FPR1:FPR2, and
     complex*32 is returned in FPR1:FPR4.  */
     complex*32 is returned in FPR1:FPR4.  */
  if (TYPE_CODE (valtype) == TYPE_CODE_FLT
  if (TYPE_CODE (valtype) == TYPE_CODE_FLT
      && (TYPE_LENGTH (valtype) == 4 || TYPE_LENGTH (valtype) == 8))
      && (TYPE_LENGTH (valtype) == 4 || TYPE_LENGTH (valtype) == 8))
    {
    {
      struct type *regtype = register_type (gdbarch, tdep->ppc_fp0_regnum);
      struct type *regtype = register_type (gdbarch, tdep->ppc_fp0_regnum);
      gdb_byte regval[8];
      gdb_byte regval[8];
 
 
      /* FIXME: kettenis/2007-01-01: Add support for quadword
      /* FIXME: kettenis/2007-01-01: Add support for quadword
         precision and complex.  */
         precision and complex.  */
 
 
      if (readbuf)
      if (readbuf)
        {
        {
          regcache_cooked_read (regcache, tdep->ppc_fp0_regnum + 1, regval);
          regcache_cooked_read (regcache, tdep->ppc_fp0_regnum + 1, regval);
          convert_typed_floating (regval, regtype, readbuf, valtype);
          convert_typed_floating (regval, regtype, readbuf, valtype);
        }
        }
      if (writebuf)
      if (writebuf)
        {
        {
          convert_typed_floating (writebuf, valtype, regval, regtype);
          convert_typed_floating (writebuf, valtype, regval, regtype);
          regcache_cooked_write (regcache, tdep->ppc_fp0_regnum + 1, regval);
          regcache_cooked_write (regcache, tdep->ppc_fp0_regnum + 1, regval);
        }
        }
 
 
      return RETURN_VALUE_REGISTER_CONVENTION;
      return RETURN_VALUE_REGISTER_CONVENTION;
  }
  }
 
 
  /* Values of the types int, long, short, pointer, and char (length
  /* Values of the types int, long, short, pointer, and char (length
     is less than or equal to four bytes), as well as bit values of
     is less than or equal to four bytes), as well as bit values of
     lengths less than or equal to 32 bits, must be returned right
     lengths less than or equal to 32 bits, must be returned right
     justified in GPR3 with signed values sign extended and unsigned
     justified in GPR3 with signed values sign extended and unsigned
     values zero extended, as necessary.  */
     values zero extended, as necessary.  */
  if (TYPE_LENGTH (valtype) <= tdep->wordsize)
  if (TYPE_LENGTH (valtype) <= tdep->wordsize)
    {
    {
      if (readbuf)
      if (readbuf)
        {
        {
          ULONGEST regval;
          ULONGEST regval;
 
 
          /* For reading we don't have to worry about sign extension.  */
          /* For reading we don't have to worry about sign extension.  */
          regcache_cooked_read_unsigned (regcache, tdep->ppc_gp0_regnum + 3,
          regcache_cooked_read_unsigned (regcache, tdep->ppc_gp0_regnum + 3,
                                         &regval);
                                         &regval);
          store_unsigned_integer (readbuf, TYPE_LENGTH (valtype), byte_order,
          store_unsigned_integer (readbuf, TYPE_LENGTH (valtype), byte_order,
                                  regval);
                                  regval);
        }
        }
      if (writebuf)
      if (writebuf)
        {
        {
          /* For writing, use unpack_long since that should handle any
          /* For writing, use unpack_long since that should handle any
             required sign extension.  */
             required sign extension.  */
          regcache_cooked_write_unsigned (regcache, tdep->ppc_gp0_regnum + 3,
          regcache_cooked_write_unsigned (regcache, tdep->ppc_gp0_regnum + 3,
                                          unpack_long (valtype, writebuf));
                                          unpack_long (valtype, writebuf));
        }
        }
 
 
      return RETURN_VALUE_REGISTER_CONVENTION;
      return RETURN_VALUE_REGISTER_CONVENTION;
    }
    }
 
 
  /* Eight-byte non-floating-point scalar values must be returned in
  /* Eight-byte non-floating-point scalar values must be returned in
     GPR3:GPR4.  */
     GPR3:GPR4.  */
 
 
  if (TYPE_LENGTH (valtype) == 8)
  if (TYPE_LENGTH (valtype) == 8)
    {
    {
      gdb_assert (TYPE_CODE (valtype) != TYPE_CODE_FLT);
      gdb_assert (TYPE_CODE (valtype) != TYPE_CODE_FLT);
      gdb_assert (tdep->wordsize == 4);
      gdb_assert (tdep->wordsize == 4);
 
 
      if (readbuf)
      if (readbuf)
        {
        {
          gdb_byte regval[8];
          gdb_byte regval[8];
 
 
          regcache_cooked_read (regcache, tdep->ppc_gp0_regnum + 3, regval);
          regcache_cooked_read (regcache, tdep->ppc_gp0_regnum + 3, regval);
          regcache_cooked_read (regcache, tdep->ppc_gp0_regnum + 4,
          regcache_cooked_read (regcache, tdep->ppc_gp0_regnum + 4,
                                regval + 4);
                                regval + 4);
          memcpy (readbuf, regval, 8);
          memcpy (readbuf, regval, 8);
        }
        }
      if (writebuf)
      if (writebuf)
        {
        {
          regcache_cooked_write (regcache, tdep->ppc_gp0_regnum + 3, writebuf);
          regcache_cooked_write (regcache, tdep->ppc_gp0_regnum + 3, writebuf);
          regcache_cooked_write (regcache, tdep->ppc_gp0_regnum + 4,
          regcache_cooked_write (regcache, tdep->ppc_gp0_regnum + 4,
                                 writebuf + 4);
                                 writebuf + 4);
        }
        }
 
 
      return RETURN_VALUE_REGISTER_CONVENTION;
      return RETURN_VALUE_REGISTER_CONVENTION;
    }
    }
 
 
  return RETURN_VALUE_STRUCT_CONVENTION;
  return RETURN_VALUE_STRUCT_CONVENTION;
}
}
 
 
/* Support for CONVERT_FROM_FUNC_PTR_ADDR (ARCH, ADDR, TARG).
/* Support for CONVERT_FROM_FUNC_PTR_ADDR (ARCH, ADDR, TARG).
 
 
   Usually a function pointer's representation is simply the address
   Usually a function pointer's representation is simply the address
   of the function. On the RS/6000 however, a function pointer is
   of the function. On the RS/6000 however, a function pointer is
   represented by a pointer to an OPD entry. This OPD entry contains
   represented by a pointer to an OPD entry. This OPD entry contains
   three words, the first word is the address of the function, the
   three words, the first word is the address of the function, the
   second word is the TOC pointer (r2), and the third word is the
   second word is the TOC pointer (r2), and the third word is the
   static chain value.  Throughout GDB it is currently assumed that a
   static chain value.  Throughout GDB it is currently assumed that a
   function pointer contains the address of the function, which is not
   function pointer contains the address of the function, which is not
   easy to fix.  In addition, the conversion of a function address to
   easy to fix.  In addition, the conversion of a function address to
   a function pointer would require allocation of an OPD entry in the
   a function pointer would require allocation of an OPD entry in the
   inferior's memory space, with all its drawbacks.  To be able to
   inferior's memory space, with all its drawbacks.  To be able to
   call C++ virtual methods in the inferior (which are called via
   call C++ virtual methods in the inferior (which are called via
   function pointers), find_function_addr uses this function to get the
   function pointers), find_function_addr uses this function to get the
   function address from a function pointer.  */
   function address from a function pointer.  */
 
 
/* Return real function address if ADDR (a function pointer) is in the data
/* Return real function address if ADDR (a function pointer) is in the data
   space and is therefore a special function pointer.  */
   space and is therefore a special function pointer.  */
 
 
static CORE_ADDR
static CORE_ADDR
rs6000_convert_from_func_ptr_addr (struct gdbarch *gdbarch,
rs6000_convert_from_func_ptr_addr (struct gdbarch *gdbarch,
                                   CORE_ADDR addr,
                                   CORE_ADDR addr,
                                   struct target_ops *targ)
                                   struct target_ops *targ)
{
{
  struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
  struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
  enum bfd_endian byte_order = gdbarch_byte_order (gdbarch);
  enum bfd_endian byte_order = gdbarch_byte_order (gdbarch);
  struct obj_section *s;
  struct obj_section *s;
 
 
  s = find_pc_section (addr);
  s = find_pc_section (addr);
 
 
  /* Normally, functions live inside a section that is executable.
  /* Normally, functions live inside a section that is executable.
     So, if ADDR points to a non-executable section, then treat it
     So, if ADDR points to a non-executable section, then treat it
     as a function descriptor and return the target address iff
     as a function descriptor and return the target address iff
     the target address itself points to a section that is executable.  */
     the target address itself points to a section that is executable.  */
  if (s && (s->the_bfd_section->flags & SEC_CODE) == 0)
  if (s && (s->the_bfd_section->flags & SEC_CODE) == 0)
    {
    {
      CORE_ADDR pc =
      CORE_ADDR pc =
        read_memory_unsigned_integer (addr, tdep->wordsize, byte_order);
        read_memory_unsigned_integer (addr, tdep->wordsize, byte_order);
      struct obj_section *pc_section = find_pc_section (pc);
      struct obj_section *pc_section = find_pc_section (pc);
 
 
      if (pc_section && (pc_section->the_bfd_section->flags & SEC_CODE))
      if (pc_section && (pc_section->the_bfd_section->flags & SEC_CODE))
        return pc;
        return pc;
    }
    }
 
 
  return addr;
  return addr;
}
}
 
 
 
 
/* Calculate the destination of a branch/jump.  Return -1 if not a branch.  */
/* Calculate the destination of a branch/jump.  Return -1 if not a branch.  */
 
 
static CORE_ADDR
static CORE_ADDR
branch_dest (struct frame_info *frame, int opcode, int instr,
branch_dest (struct frame_info *frame, int opcode, int instr,
             CORE_ADDR pc, CORE_ADDR safety)
             CORE_ADDR pc, CORE_ADDR safety)
{
{
  struct gdbarch *gdbarch = get_frame_arch (frame);
  struct gdbarch *gdbarch = get_frame_arch (frame);
  struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
  struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
  enum bfd_endian byte_order = gdbarch_byte_order (gdbarch);
  enum bfd_endian byte_order = gdbarch_byte_order (gdbarch);
  CORE_ADDR dest;
  CORE_ADDR dest;
  int immediate;
  int immediate;
  int absolute;
  int absolute;
  int ext_op;
  int ext_op;
 
 
  absolute = (int) ((instr >> 1) & 1);
  absolute = (int) ((instr >> 1) & 1);
 
 
  switch (opcode)
  switch (opcode)
    {
    {
    case 18:
    case 18:
      immediate = ((instr & ~3) << 6) >> 6;     /* br unconditional */
      immediate = ((instr & ~3) << 6) >> 6;     /* br unconditional */
      if (absolute)
      if (absolute)
        dest = immediate;
        dest = immediate;
      else
      else
        dest = pc + immediate;
        dest = pc + immediate;
      break;
      break;
 
 
    case 16:
    case 16:
      immediate = ((instr & ~3) << 16) >> 16;   /* br conditional */
      immediate = ((instr & ~3) << 16) >> 16;   /* br conditional */
      if (absolute)
      if (absolute)
        dest = immediate;
        dest = immediate;
      else
      else
        dest = pc + immediate;
        dest = pc + immediate;
      break;
      break;
 
 
    case 19:
    case 19:
      ext_op = (instr >> 1) & 0x3ff;
      ext_op = (instr >> 1) & 0x3ff;
 
 
      if (ext_op == 16)         /* br conditional register */
      if (ext_op == 16)         /* br conditional register */
        {
        {
          dest = get_frame_register_unsigned (frame, tdep->ppc_lr_regnum) & ~3;
          dest = get_frame_register_unsigned (frame, tdep->ppc_lr_regnum) & ~3;
 
 
          /* If we are about to return from a signal handler, dest is
          /* If we are about to return from a signal handler, dest is
             something like 0x3c90.  The current frame is a signal handler
             something like 0x3c90.  The current frame is a signal handler
             caller frame, upon completion of the sigreturn system call
             caller frame, upon completion of the sigreturn system call
             execution will return to the saved PC in the frame.  */
             execution will return to the saved PC in the frame.  */
          if (dest < AIX_TEXT_SEGMENT_BASE)
          if (dest < AIX_TEXT_SEGMENT_BASE)
            dest = read_memory_unsigned_integer
            dest = read_memory_unsigned_integer
                     (get_frame_base (frame) + SIG_FRAME_PC_OFFSET,
                     (get_frame_base (frame) + SIG_FRAME_PC_OFFSET,
                      tdep->wordsize, byte_order);
                      tdep->wordsize, byte_order);
        }
        }
 
 
      else if (ext_op == 528)   /* br cond to count reg */
      else if (ext_op == 528)   /* br cond to count reg */
        {
        {
          dest = get_frame_register_unsigned (frame, tdep->ppc_ctr_regnum) & ~3;
          dest = get_frame_register_unsigned (frame, tdep->ppc_ctr_regnum) & ~3;
 
 
          /* If we are about to execute a system call, dest is something
          /* If we are about to execute a system call, dest is something
             like 0x22fc or 0x3b00.  Upon completion the system call
             like 0x22fc or 0x3b00.  Upon completion the system call
             will return to the address in the link register.  */
             will return to the address in the link register.  */
          if (dest < AIX_TEXT_SEGMENT_BASE)
          if (dest < AIX_TEXT_SEGMENT_BASE)
            dest = get_frame_register_unsigned (frame, tdep->ppc_lr_regnum) & ~3;
            dest = get_frame_register_unsigned (frame, tdep->ppc_lr_regnum) & ~3;
        }
        }
      else
      else
        return -1;
        return -1;
      break;
      break;
 
 
    default:
    default:
      return -1;
      return -1;
    }
    }
  return (dest < AIX_TEXT_SEGMENT_BASE) ? safety : dest;
  return (dest < AIX_TEXT_SEGMENT_BASE) ? safety : dest;
}
}
 
 
/* AIX does not support PT_STEP.  Simulate it.  */
/* AIX does not support PT_STEP.  Simulate it.  */
 
 
static int
static int
rs6000_software_single_step (struct frame_info *frame)
rs6000_software_single_step (struct frame_info *frame)
{
{
  struct gdbarch *gdbarch = get_frame_arch (frame);
  struct gdbarch *gdbarch = get_frame_arch (frame);
  struct address_space *aspace = get_frame_address_space (frame);
  struct address_space *aspace = get_frame_address_space (frame);
  enum bfd_endian byte_order = gdbarch_byte_order (gdbarch);
  enum bfd_endian byte_order = gdbarch_byte_order (gdbarch);
  int ii, insn;
  int ii, insn;
  CORE_ADDR loc;
  CORE_ADDR loc;
  CORE_ADDR breaks[2];
  CORE_ADDR breaks[2];
  int opcode;
  int opcode;
 
 
  loc = get_frame_pc (frame);
  loc = get_frame_pc (frame);
 
 
  insn = read_memory_integer (loc, 4, byte_order);
  insn = read_memory_integer (loc, 4, byte_order);
 
 
  if (ppc_deal_with_atomic_sequence (frame))
  if (ppc_deal_with_atomic_sequence (frame))
    return 1;
    return 1;
 
 
  breaks[0] = loc + PPC_INSN_SIZE;
  breaks[0] = loc + PPC_INSN_SIZE;
  opcode = insn >> 26;
  opcode = insn >> 26;
  breaks[1] = branch_dest (frame, opcode, insn, loc, breaks[0]);
  breaks[1] = branch_dest (frame, opcode, insn, loc, breaks[0]);
 
 
  /* Don't put two breakpoints on the same address. */
  /* Don't put two breakpoints on the same address. */
  if (breaks[1] == breaks[0])
  if (breaks[1] == breaks[0])
    breaks[1] = -1;
    breaks[1] = -1;
 
 
  for (ii = 0; ii < 2; ++ii)
  for (ii = 0; ii < 2; ++ii)
    {
    {
      /* ignore invalid breakpoint. */
      /* ignore invalid breakpoint. */
      if (breaks[ii] == -1)
      if (breaks[ii] == -1)
        continue;
        continue;
      insert_single_step_breakpoint (gdbarch, aspace, breaks[ii]);
      insert_single_step_breakpoint (gdbarch, aspace, breaks[ii]);
    }
    }
 
 
  errno = 0;                     /* FIXME, don't ignore errors! */
  errno = 0;                     /* FIXME, don't ignore errors! */
  /* What errors?  {read,write}_memory call error().  */
  /* What errors?  {read,write}_memory call error().  */
  return 1;
  return 1;
}
}
 
 
static enum gdb_osabi
static enum gdb_osabi
rs6000_aix_osabi_sniffer (bfd *abfd)
rs6000_aix_osabi_sniffer (bfd *abfd)
{
{
 
 
  if (bfd_get_flavour (abfd) == bfd_target_xcoff_flavour);
  if (bfd_get_flavour (abfd) == bfd_target_xcoff_flavour);
    return GDB_OSABI_AIX;
    return GDB_OSABI_AIX;
 
 
  return GDB_OSABI_UNKNOWN;
  return GDB_OSABI_UNKNOWN;
}
}
 
 
static void
static void
rs6000_aix_init_osabi (struct gdbarch_info info, struct gdbarch *gdbarch)
rs6000_aix_init_osabi (struct gdbarch_info info, struct gdbarch *gdbarch)
{
{
  struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
  struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
 
 
  /* RS6000/AIX does not support PT_STEP.  Has to be simulated.  */
  /* RS6000/AIX does not support PT_STEP.  Has to be simulated.  */
  set_gdbarch_software_single_step (gdbarch, rs6000_software_single_step);
  set_gdbarch_software_single_step (gdbarch, rs6000_software_single_step);
 
 
  /* Displaced stepping is currently not supported in combination with
  /* Displaced stepping is currently not supported in combination with
     software single-stepping.  */
     software single-stepping.  */
  set_gdbarch_displaced_step_copy_insn (gdbarch, NULL);
  set_gdbarch_displaced_step_copy_insn (gdbarch, NULL);
  set_gdbarch_displaced_step_fixup (gdbarch, NULL);
  set_gdbarch_displaced_step_fixup (gdbarch, NULL);
  set_gdbarch_displaced_step_free_closure (gdbarch, NULL);
  set_gdbarch_displaced_step_free_closure (gdbarch, NULL);
  set_gdbarch_displaced_step_location (gdbarch, NULL);
  set_gdbarch_displaced_step_location (gdbarch, NULL);
 
 
  set_gdbarch_push_dummy_call (gdbarch, rs6000_push_dummy_call);
  set_gdbarch_push_dummy_call (gdbarch, rs6000_push_dummy_call);
  set_gdbarch_return_value (gdbarch, rs6000_return_value);
  set_gdbarch_return_value (gdbarch, rs6000_return_value);
  set_gdbarch_long_double_bit (gdbarch, 8 * TARGET_CHAR_BIT);
  set_gdbarch_long_double_bit (gdbarch, 8 * TARGET_CHAR_BIT);
 
 
  /* Handle RS/6000 function pointers (which are really function
  /* Handle RS/6000 function pointers (which are really function
     descriptors).  */
     descriptors).  */
  set_gdbarch_convert_from_func_ptr_addr
  set_gdbarch_convert_from_func_ptr_addr
    (gdbarch, rs6000_convert_from_func_ptr_addr);
    (gdbarch, rs6000_convert_from_func_ptr_addr);
 
 
  /* Core file support.  */
  /* Core file support.  */
  set_gdbarch_regset_from_core_section
  set_gdbarch_regset_from_core_section
    (gdbarch, rs6000_aix_regset_from_core_section);
    (gdbarch, rs6000_aix_regset_from_core_section);
 
 
  if (tdep->wordsize == 8)
  if (tdep->wordsize == 8)
    tdep->lr_frame_offset = 16;
    tdep->lr_frame_offset = 16;
  else
  else
    tdep->lr_frame_offset = 8;
    tdep->lr_frame_offset = 8;
 
 
  if (tdep->wordsize == 4)
  if (tdep->wordsize == 4)
    /* PowerOpen / AIX 32 bit.  The saved area or red zone consists of
    /* PowerOpen / AIX 32 bit.  The saved area or red zone consists of
       19 4 byte GPRS + 18 8 byte FPRs giving a total of 220 bytes.
       19 4 byte GPRS + 18 8 byte FPRs giving a total of 220 bytes.
       Problem is, 220 isn't frame (16 byte) aligned.  Round it up to
       Problem is, 220 isn't frame (16 byte) aligned.  Round it up to
       224.  */
       224.  */
    set_gdbarch_frame_red_zone_size (gdbarch, 224);
    set_gdbarch_frame_red_zone_size (gdbarch, 224);
  else
  else
    set_gdbarch_frame_red_zone_size (gdbarch, 0);
    set_gdbarch_frame_red_zone_size (gdbarch, 0);
}
}
 
 
/* Provide a prototype to silence -Wmissing-prototypes.  */
/* Provide a prototype to silence -Wmissing-prototypes.  */
extern initialize_file_ftype _initialize_rs6000_aix_tdep;
extern initialize_file_ftype _initialize_rs6000_aix_tdep;
 
 
void
void
_initialize_rs6000_aix_tdep (void)
_initialize_rs6000_aix_tdep (void)
{
{
  gdbarch_register_osabi_sniffer (bfd_arch_rs6000,
  gdbarch_register_osabi_sniffer (bfd_arch_rs6000,
                                  bfd_target_xcoff_flavour,
                                  bfd_target_xcoff_flavour,
                                  rs6000_aix_osabi_sniffer);
                                  rs6000_aix_osabi_sniffer);
  gdbarch_register_osabi_sniffer (bfd_arch_powerpc,
  gdbarch_register_osabi_sniffer (bfd_arch_powerpc,
                                  bfd_target_xcoff_flavour,
                                  bfd_target_xcoff_flavour,
                                  rs6000_aix_osabi_sniffer);
                                  rs6000_aix_osabi_sniffer);
 
 
  gdbarch_register_osabi (bfd_arch_rs6000, 0, GDB_OSABI_AIX,
  gdbarch_register_osabi (bfd_arch_rs6000, 0, GDB_OSABI_AIX,
                          rs6000_aix_init_osabi);
                          rs6000_aix_init_osabi);
  gdbarch_register_osabi (bfd_arch_powerpc, 0, GDB_OSABI_AIX,
  gdbarch_register_osabi (bfd_arch_powerpc, 0, GDB_OSABI_AIX,
                          rs6000_aix_init_osabi);
                          rs6000_aix_init_osabi);
}
}
 
 
 
 

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.