Пример #1
0
/* MVS note this is deprecated.  */
static void
mn10300_store_return_value (struct type *type,
			    struct regcache *regcache, const void *valbuf)
{
  struct gdbarch *gdbarch = get_regcache_arch (regcache);
  int len = TYPE_LENGTH (type);
  int reg, regsz;
  
  if (TYPE_CODE (type) == TYPE_CODE_PTR)
    reg = 4;
  else
    reg = 0;

  regsz = register_size (gdbarch, reg);

  if (len <= regsz)
    regcache_raw_write_part (regcache, reg, 0, len, valbuf);
  else if (len <= 2 * regsz)
    {
      regcache_raw_write (regcache, reg, valbuf);
      gdb_assert (regsz == register_size (gdbarch, reg + 1));
      regcache_raw_write_part (regcache, reg+1, 0,
			       len - regsz, (char *) valbuf + regsz);
    }
  else
    internal_error (__FILE__, __LINE__,
		    _("Cannot store return value %d bytes long."), len);
}
Пример #2
0
static void
swapped_regcache_raw_write_part (struct regcache *regcache, int regnum,
                                 int offset, int len, const gdb_byte *buf)
{
  int j;
  gdb_byte swapper_buf[16];

  if (regnum < AMD64_XMM0_REGNUM || regnum > AMD64_XMM0_REGNUM + 15)
    {
       regcache_raw_write_part (regcache, regnum, offset, len, buf);
       return;
    }

  regcache_raw_read (regcache, regnum, swapper_buf);
  for (j = 0; j < 8; j++)
    {
      gdb_byte tmp = swapper_buf[j];
      swapper_buf[j] = swapper_buf[16 - j - 1];
      swapper_buf[16 - j - 1] = tmp;
    }

  memcpy (&swapper_buf[offset], buf, len);
  for (j = 0; j < 8; j++)
     {
       gdb_byte tmp = swapper_buf[j];
       swapper_buf[j] = swapper_buf[16 - j - 1];
       swapper_buf[16 - j - 1] = tmp;
     }
  regcache_raw_write (regcache, regnum, swapper_buf);
}
Пример #3
0
static void
m68k_store_return_value (struct type *type, struct regcache *regcache,
			 const gdb_byte *valbuf)
{
  int len = TYPE_LENGTH (type);

  if (len <= 4)
    regcache_raw_write_part (regcache, M68K_D0_REGNUM, 4 - len, len, valbuf);
  else if (len <= 8)
    {
      regcache_raw_write_part (regcache, M68K_D0_REGNUM, 8 - len,
			       len - 4, valbuf);
      regcache_raw_write (regcache, M68K_D1_REGNUM, valbuf + (len - 4));
    }
  else
    internal_error (__FILE__, __LINE__,
		    _("Cannot store return value of %d bytes long."), len);
}
Пример #4
0
static enum return_value_convention
amd64_windows_return_value (struct gdbarch *gdbarch, struct value *function,
			    struct type *type, struct regcache *regcache,
			    gdb_byte *readbuf, const gdb_byte *writebuf)
{
  int len = TYPE_LENGTH (type);
  int regnum = -1;

  /* See if our value is returned through a register.  If it is, then
     store the associated register number in REGNUM.  */
  switch (TYPE_CODE (type))
    {
      case TYPE_CODE_FLT:
      case TYPE_CODE_DECFLOAT:
        /* __m128, __m128i, __m128d, floats, and doubles are returned
           via XMM0.  */
        if (len == 4 || len == 8 || len == 16)
          regnum = AMD64_XMM0_REGNUM;
        break;
      default:
        /* All other values that are 1, 2, 4 or 8 bytes long are returned
           via RAX.  */
        if (len == 1 || len == 2 || len == 4 || len == 8)
          regnum = AMD64_RAX_REGNUM;
        break;
    }

  if (regnum < 0)
    {
      /* RAX contains the address where the return value has been stored.  */
      if (readbuf)
        {
	  ULONGEST addr;

	  regcache_raw_read_unsigned (regcache, AMD64_RAX_REGNUM, &addr);
	  read_memory (addr, readbuf, TYPE_LENGTH (type));
	}
      return RETURN_VALUE_ABI_RETURNS_ADDRESS;
    }
  else
    {
      /* Extract the return value from the register where it was stored.  */
      if (readbuf)
	regcache_raw_read_part (regcache, regnum, 0, len, readbuf);
      if (writebuf)
	regcache_raw_write_part (regcache, regnum, 0, len, writebuf);
      return RETURN_VALUE_REGISTER_CONVENTION;
    }
}
Пример #5
0
static CORE_ADDR
amd64_push_arguments(struct regcache *regcache, int nargs,
		     struct value **args, CORE_ADDR sp, int struct_return)
{
  static int integer_regnum[] =
  {
    AMD64_RDI_REGNUM,		/* %rdi */
    AMD64_RSI_REGNUM,		/* %rsi */
    AMD64_RDX_REGNUM,		/* %rdx */
    AMD64_RCX_REGNUM,		/* %rcx */
    8,				/* %r8 */
    9				/* %r9 */
  };
  static int sse_regnum[] =
  {
    /* %xmm0 ... %xmm7 */
    AMD64_XMM0_REGNUM + 0, AMD64_XMM1_REGNUM,
    AMD64_XMM0_REGNUM + 2, AMD64_XMM0_REGNUM + 3,
    AMD64_XMM0_REGNUM + 4, AMD64_XMM0_REGNUM + 5,
    AMD64_XMM0_REGNUM + 6, AMD64_XMM0_REGNUM + 7,
  };
  struct value **stack_args = alloca(nargs * sizeof(struct value *));
  int num_stack_args = 0;
  int num_elements = 0;
  int element = 0;
  int integer_reg = 0;
  int sse_reg = 0;
  int i;

  /* Reserve a register for the "hidden" argument: */
  if (struct_return)
    integer_reg++;

  for (i = 0; i < nargs; i++)
    {
      struct type *type = value_type(args[i]);
      int len = TYPE_LENGTH(type);
      enum amd64_reg_class reg_class[2];
      int needed_integer_regs = 0;
      int needed_sse_regs = 0;
      int j;

      /* Classify argument: */
      amd64_classify(type, reg_class);

      /* Calculate the number of integer and SSE registers needed for
         this argument.  */
      for (j = 0; j < 2; j++)
	{
	  if (reg_class[j] == AMD64_INTEGER)
	    needed_integer_regs++;
	  else if (reg_class[j] == AMD64_SSE)
	    needed_sse_regs++;
	}

      /* Check whether enough registers are available, and if the
         argument should be passed in registers at all.  */
      if (((size_t)(integer_reg + needed_integer_regs) > ARRAY_SIZE(integer_regnum))
	  || ((size_t)(sse_reg + needed_sse_regs) > ARRAY_SIZE(sse_regnum))
	  || ((needed_integer_regs == 0) && (needed_sse_regs == 0)))
	{
	  /* The argument will be passed on the stack: */
	  num_elements += ((len + 7) / 8);
	  stack_args[num_stack_args++] = args[i];
	}
      else
	{
	  /* The argument will be passed in registers: */
	  const gdb_byte *valbuf = value_contents(args[i]);
	  gdb_byte buf[8];

	  gdb_assert(len <= 16);

	  for (j = 0; len > 0; j++, len -= 8)
	    {
	      int regnum = -1;
	      int offset = 0;

	      switch (reg_class[j])
		{
		case AMD64_INTEGER:
		  regnum = integer_regnum[integer_reg++];
		  break;

		case AMD64_SSE:
		  regnum = sse_regnum[sse_reg++];
		  break;

		case AMD64_SSEUP:
		  gdb_assert(sse_reg > 0);
		  regnum = sse_regnum[sse_reg - 1];
		  offset = 8;
		  break;

		default:
		  gdb_assert(!"Unexpected register class.");
		}

	      gdb_assert(regnum != -1);
	      memset(buf, 0, sizeof(buf));
	      memcpy(buf, (valbuf + j * 8), min(len, 8));

              /* APPLE LOCAL: We keep the XMM registers in "user's view"
               * byte order inside gdb, so we need to unswap them before
               * the ABI read/writes, which assume the byte order of the
               * actual machine: */
              if ((reg_class[j] == AMD64_SSE)
                  || (reg_class[j] == AMD64_SSEUP))
	        swapped_regcache_raw_write_part(regcache, regnum, offset,
                                                8, buf);
              else
	        regcache_raw_write_part(regcache, regnum, offset, 8, buf);
	    }
	}
    }

  /* Allocate space for the arguments on the stack: */
  sp -= (num_elements * 8);

  /* The psABI says that "The end of the input argument area shall be
     aligned on a 16 byte boundary."  */
  sp &= ~0xf;

  /* Write out the arguments to the stack: */
  for (i = 0; i < num_stack_args; i++)
    {
      struct type *type = value_type(stack_args[i]);
      const gdb_byte *valbuf = value_contents(stack_args[i]);
      int len = TYPE_LENGTH(type);

      write_memory(sp + element * 8, valbuf, len);
      element += ((len + 7) / 8);
    }

  /* The psABI says that "For calls that may call functions that use
     varargs or stdargs (prototype-less calls or calls to functions
     containing ellipsis (...) in the declaration) %al is used as
     hidden argument to specify the number of SSE registers used.  */
  regcache_raw_write_unsigned(regcache, AMD64_RAX_REGNUM, sse_reg);
  return sp;
}
Пример #6
0
static enum return_value_convention
amd64_return_value(struct gdbarch *gdbarch, struct type *type,
		   struct regcache *regcache,
		   gdb_byte *readbuf, const gdb_byte *writebuf)
{
  enum amd64_reg_class reg_class[2];
  int len = TYPE_LENGTH(type);
  static int integer_regnum[] = { AMD64_RAX_REGNUM, AMD64_RDX_REGNUM };
  static int sse_regnum[] = { AMD64_XMM0_REGNUM, AMD64_XMM1_REGNUM };
  int integer_reg = 0;
  int sse_reg = 0;
  int i;

  gdb_assert(!(readbuf && writebuf));

  /* 1. Classify the return type with the classification algorithm: */
  amd64_classify(type, reg_class);

  /* 2. If the type has class MEMORY, then the caller provides space
     for the return value and passes the address of this storage in
     %rdi as if it were the first argument to the function. In effect,
     this address becomes a hidden first argument.

     On return %rax will contain the address that has been passed in
     by the caller in %rdi.  */
  if (reg_class[0] == AMD64_MEMORY)
    {
      /* As indicated by the comment above, the ABI guarantees that we
         can always find the return value just after the function has
         returned.  */

      if (readbuf)
	{
	  ULONGEST addr;

	  regcache_raw_read_unsigned(regcache, AMD64_RAX_REGNUM, &addr);
	  read_memory(addr, readbuf, TYPE_LENGTH(type));
	}

      return RETURN_VALUE_ABI_RETURNS_ADDRESS;
    }

  gdb_assert(reg_class[1] != AMD64_MEMORY);
  gdb_assert(len <= 16);

  for (i = 0; len > 0; i++, len -= 8)
    {
      int regnum = -1;
      int offset = 0;

      switch (reg_class[i])
	{
	case AMD64_INTEGER:
	  /* 3. If the class is INTEGER, the next available register
	     of the sequence %rax, %rdx is used.  */
	  regnum = integer_regnum[integer_reg++];
	  break;

	case AMD64_SSE:
	  /* 4. If the class is SSE, the next available SSE register
             of the sequence %xmm0, %xmm1 is used.  */
	  regnum = sse_regnum[sse_reg++];
	  break;

	case AMD64_SSEUP:
	  /* 5. If the class is SSEUP, the eightbyte is passed in the
	     upper half of the last used SSE register.  */
	  gdb_assert (sse_reg > 0);
	  regnum = sse_regnum[sse_reg - 1];
	  offset = 8;
	  break;

	case AMD64_X87:
	  /* 6. If the class is X87, the value is returned on the X87
             stack in %st0 as 80-bit x87 number.  */
	  regnum = AMD64_ST0_REGNUM;
	  if (writebuf)
	    i387_return_value(gdbarch, regcache);
	  break;

	case AMD64_X87UP:
	  /* 7. If the class is X87UP, the value is returned together
             with the previous X87 value in %st0.  */
	  gdb_assert((i > 0) && (reg_class[0] == AMD64_X87));
	  regnum = AMD64_ST0_REGNUM;
	  offset = 8;
	  len = 2;
	  break;

	case AMD64_NO_CLASS:
	  continue;

	default:
	  gdb_assert(!"Unexpected register class.");
	}

      gdb_assert(regnum != -1);

      /* APPLE LOCAL: We keep the XMM registers in the "user's view"
         byte order inside gdb so we need to unswap them before the
         ABI read/writes which assume the actual machine byte order.  */

      if ((readbuf || writebuf)
          && ((regnum == sse_regnum[0]) || (regnum == sse_regnum[1])))
        {
          if (readbuf)
	    swapped_regcache_raw_read_part(regcache, regnum, offset,
                                           min(len, 8), readbuf + i * 8);
          if (writebuf)
	    swapped_regcache_raw_write_part(regcache, regnum, offset,
                                            min(len, 8), writebuf + i * 8);
          continue;
        }

      if (readbuf)
	regcache_raw_read_part(regcache, regnum, offset, min(len, 8),
                               readbuf + i * 8);
      if (writebuf)
	regcache_raw_write_part(regcache, regnum, offset, min(len, 8),
                                writebuf + i * 8);
    }

  return RETURN_VALUE_REGISTER_CONVENTION;
}