Replace constant values 8 to 15 by AMD64_R8_REGNUM to
[deliverable/binutils-gdb.git] / gdb / amd64-tdep.c
index 987f80db14d4ae668d6d842012a5081428ef8e62..4d6b325207ab4f0e7de4afcf06fc1639cb1c4a03 100644 (file)
@@ -1,7 +1,6 @@
 /* Target-dependent code for AMD64.
 
-   Copyright (C) 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010,
-   2011 Free Software Foundation, Inc.
+   Copyright (C) 2001-2013 Free Software Foundation, Inc.
 
    Contributed by Jiri Smid, SuSE Labs.
 
@@ -44,6 +43,8 @@
 
 #include "features/i386/amd64.c"
 #include "features/i386/amd64-avx.c"
+#include "features/i386/x32.c"
+#include "features/i386/x32-avx.c"
 
 #include "ax.h"
 #include "ax-gdb.h"
@@ -91,17 +92,6 @@ static const char *amd64_ymmh_names[] =
   "ymm12h", "ymm13h", "ymm14h", "ymm15h"
 };
 
-/* The registers used to pass integer arguments during a function call.  */
-static int amd64_dummy_call_integer_regs[] =
-{
-  AMD64_RDI_REGNUM,            /* %rdi */
-  AMD64_RSI_REGNUM,            /* %rsi */
-  AMD64_RDX_REGNUM,            /* %rdx */
-  AMD64_RCX_REGNUM,            /* %rcx */
-  8,                           /* %r8 */
-  9                            /* %r9 */
-};
-
 /* DWARF Register Number Mapping as defined in the System V psABI,
    section 3.6.  */
 
@@ -119,7 +109,14 @@ static int amd64_dwarf_regmap[] =
   AMD64_RSP_REGNUM,
 
   /* Extended Integer Registers 8 - 15.  */
-  8, 9, 10, 11, 12, 13, 14, 15,
+  AMD64_R8_REGNUM,             /* %r8 */
+  AMD64_R9_REGNUM,             /* %r9 */
+  AMD64_R10_REGNUM,            /* %r10 */
+  AMD64_R11_REGNUM,            /* %r11 */
+  AMD64_R12_REGNUM,            /* %r12 */
+  AMD64_R13_REGNUM,            /* %r13 */
+  AMD64_R14_REGNUM,            /* %r14 */
+  AMD64_R15_REGNUM,            /* %r15 */
 
   /* Return Address RA.  Mapped to RIP.  */
   AMD64_RIP_REGNUM,
@@ -257,7 +254,8 @@ static const char *amd64_word_names[] =
 static const char *amd64_dword_names[] =
 {
   "eax", "ebx", "ecx", "edx", "esi", "edi", "ebp", "esp", 
-  "r8d", "r9d", "r10d", "r11d", "r12d", "r13d", "r14d", "r15d"
+  "r8d", "r9d", "r10d", "r11d", "r12d", "r13d", "r14d", "r15d",
+  "eip"
 };
 
 /* Return the name of register REGNUM.  */
@@ -389,6 +387,20 @@ amd64_pseudo_register_write (struct gdbarch *gdbarch,
 
 \f
 
+/* Register classes as defined in the psABI.  */
+
+enum amd64_reg_class
+{
+  AMD64_INTEGER,
+  AMD64_SSE,
+  AMD64_SSEUP,
+  AMD64_X87,
+  AMD64_X87UP,
+  AMD64_COMPLEX_X87,
+  AMD64_NO_CLASS,
+  AMD64_MEMORY
+};
+
 /* Return the union class of CLASS1 and CLASS2.  See the psABI for
    details.  */
 
@@ -425,6 +437,8 @@ amd64_merge_classes (enum amd64_reg_class class1, enum amd64_reg_class class2)
   return AMD64_SSE;
 }
 
+static void amd64_classify (struct type *type, enum amd64_reg_class class[2]);
+
 /* Return non-zero if TYPE is a non-POD structure or union type.  */
 
 static int
@@ -444,12 +458,10 @@ amd64_non_pod_p (struct type *type)
 static void
 amd64_classify_aggregate (struct type *type, enum amd64_reg_class class[2])
 {
-  int len = TYPE_LENGTH (type);
-
   /* 1. If the size of an object is larger than two eightbytes, or in
         C++, is a non-POD structure or union type, or contains
         unaligned fields, it has class memory.  */
-  if (len > 16 || amd64_non_pod_p (type))
+  if (TYPE_LENGTH (type) > 16 || amd64_non_pod_p (type))
     {
       class[0] = class[1] = AMD64_MEMORY;
       return;
@@ -469,7 +481,7 @@ amd64_classify_aggregate (struct type *type, enum amd64_reg_class class[2])
 
       /* All fields in an array have the same type.  */
       amd64_classify (subtype, class);
-      if (len > 8 && class[1] == AMD64_NO_CLASS)
+      if (TYPE_LENGTH (type) > 8 && class[1] == AMD64_NO_CLASS)
        class[1] = class[0];
     }
   else
@@ -546,7 +558,7 @@ amd64_classify_aggregate (struct type *type, enum amd64_reg_class class[2])
 
 /* Classify TYPE, and store the result in CLASS.  */
 
-void
+static void
 amd64_classify (struct type *type, enum amd64_reg_class class[2])
 {
   enum type_code code = TYPE_CODE (type);
@@ -586,6 +598,23 @@ amd64_classify (struct type *type, enum amd64_reg_class class[2])
     /* Class X87 and X87UP.  */
     class[0] = AMD64_X87, class[1] = AMD64_X87UP;
 
+  /* Arguments of complex T where T is one of the types float or
+     double get treated as if they are implemented as:
+
+     struct complexT {
+       T real;
+       T imag;
+     };  */
+  else if (code == TYPE_CODE_COMPLEX && len == 8)
+    class[0] = AMD64_SSE;
+  else if (code == TYPE_CODE_COMPLEX && len == 16)
+    class[0] = class[1] = AMD64_SSE;
+
+  /* A variable of type complex long double is classified as type
+     COMPLEX_X87.  */
+  else if (code == TYPE_CODE_COMPLEX && len == 32)
+    class[0] = AMD64_COMPLEX_X87;
+
   /* Aggregates.  */
   else if (code == TYPE_CODE_ARRAY || code == TYPE_CODE_STRUCT
           || code == TYPE_CODE_UNION)
@@ -593,11 +622,10 @@ amd64_classify (struct type *type, enum amd64_reg_class class[2])
 }
 
 static enum return_value_convention
-amd64_return_value (struct gdbarch *gdbarch, struct type *func_type,
+amd64_return_value (struct gdbarch *gdbarch, struct value *function,
                    struct type *type, struct regcache *regcache,
                    gdb_byte *readbuf, const gdb_byte *writebuf)
 {
-  struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
   enum amd64_reg_class class[2];
   int len = TYPE_LENGTH (type);
   static int integer_regnum[] = { AMD64_RAX_REGNUM, AMD64_RDX_REGNUM };
@@ -607,10 +635,9 @@ amd64_return_value (struct gdbarch *gdbarch, struct type *func_type,
   int i;
 
   gdb_assert (!(readbuf && writebuf));
-  gdb_assert (tdep->classify);
 
   /* 1. Classify the return type with the classification algorithm.  */
-  tdep->classify (type, class);
+  amd64_classify (type, 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
@@ -636,6 +663,30 @@ amd64_return_value (struct gdbarch *gdbarch, struct type *func_type,
       return RETURN_VALUE_ABI_RETURNS_ADDRESS;
     }
 
+  /* 8. If the class is COMPLEX_X87, the real part of the value is
+        returned in %st0 and the imaginary part in %st1.  */
+  if (class[0] == AMD64_COMPLEX_X87)
+    {
+      if (readbuf)
+       {
+         regcache_raw_read (regcache, AMD64_ST0_REGNUM, readbuf);
+         regcache_raw_read (regcache, AMD64_ST1_REGNUM, readbuf + 16);
+       }
+
+      if (writebuf)
+       {
+         i387_return_value (gdbarch, regcache);
+         regcache_raw_write (regcache, AMD64_ST0_REGNUM, writebuf);
+         regcache_raw_write (regcache, AMD64_ST1_REGNUM, writebuf + 16);
+
+         /* Fix up the tag word such that both %st(0) and %st(1) are
+            marked as valid.  */
+         regcache_raw_write_unsigned (regcache, AMD64_FTAG_REGNUM, 0xfff);
+       }
+
+      return RETURN_VALUE_REGISTER_CONVENTION;
+    }
+
   gdb_assert (class[1] != AMD64_MEMORY);
   gdb_assert (len <= 16);
 
@@ -708,11 +759,15 @@ static CORE_ADDR
 amd64_push_arguments (struct regcache *regcache, int nargs,
                      struct value **args, CORE_ADDR sp, int struct_return)
 {
-  struct gdbarch *gdbarch = get_regcache_arch (regcache);
-  struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
-  int *integer_regs = tdep->call_dummy_integer_regs;
-  int num_integer_regs = tdep->call_dummy_num_integer_regs;
-
+  static int integer_regnum[] =
+  {
+    AMD64_RDI_REGNUM,          /* %rdi */
+    AMD64_RSI_REGNUM,          /* %rsi */
+    AMD64_RDX_REGNUM,          /* %rdx */
+    AMD64_RCX_REGNUM,          /* %rcx */
+    AMD64_R8_REGNUM,           /* %r8 */
+    AMD64_R9_REGNUM            /* %r9 */
+  };
   static int sse_regnum[] =
   {
     /* %xmm0 ... %xmm7 */
@@ -722,11 +777,6 @@ amd64_push_arguments (struct regcache *regcache, int nargs,
     AMD64_XMM0_REGNUM + 6, AMD64_XMM0_REGNUM + 7,
   };
   struct value **stack_args = alloca (nargs * sizeof (struct value *));
-  /* An array that mirrors the stack_args array.  For all arguments
-     that are passed by MEMORY, if that argument's address also needs
-     to be stored in a register, the ARG_ADDR_REGNO array will contain
-     that register number (or a negative value otherwise).  */
-  int *arg_addr_regno = alloca (nargs * sizeof (int));
   int num_stack_args = 0;
   int num_elements = 0;
   int element = 0;
@@ -734,8 +784,6 @@ amd64_push_arguments (struct regcache *regcache, int nargs,
   int sse_reg = 0;
   int i;
 
-  gdb_assert (tdep->classify);
-
   /* Reserve a register for the "hidden" argument.  */
   if (struct_return)
     integer_reg++;
@@ -750,7 +798,7 @@ amd64_push_arguments (struct regcache *regcache, int nargs,
       int j;
 
       /* Classify argument.  */
-      tdep->classify (type, class);
+      amd64_classify (type, class);
 
       /* Calculate the number of integer and SSE registers needed for
          this argument.  */
@@ -764,25 +812,13 @@ amd64_push_arguments (struct regcache *regcache, int nargs,
 
       /* Check whether enough registers are available, and if the
          argument should be passed in registers at all.  */
-      if (integer_reg + needed_integer_regs > num_integer_regs
+      if (integer_reg + needed_integer_regs > ARRAY_SIZE (integer_regnum)
          || 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];
-          /* If this is an AMD64_MEMORY argument whose address must also
-             be passed in one of the integer registers, reserve that
-             register and associate this value to that register so that
-             we can store the argument address as soon as we know it.  */
-          if (class[0] == AMD64_MEMORY
-              && tdep->memory_args_by_pointer
-              && integer_reg < tdep->call_dummy_num_integer_regs)
-            arg_addr_regno[num_stack_args] =
-              tdep->call_dummy_integer_regs[integer_reg++];
-          else
-            arg_addr_regno[num_stack_args] = -1;
-          num_stack_args++;
+         stack_args[num_stack_args++] = args[i];
        }
       else
        {
@@ -800,7 +836,7 @@ amd64_push_arguments (struct regcache *regcache, int nargs,
              switch (class[j])
                {
                case AMD64_INTEGER:
-                 regnum = integer_regs[integer_reg++];
+                 regnum = integer_regnum[integer_reg++];
                  break;
 
                case AMD64_SSE:
@@ -838,19 +874,8 @@ amd64_push_arguments (struct regcache *regcache, int nargs,
       struct type *type = value_type (stack_args[i]);
       const gdb_byte *valbuf = value_contents (stack_args[i]);
       int len = TYPE_LENGTH (type);
-      CORE_ADDR arg_addr = sp + element * 8;
-
-      write_memory (arg_addr, valbuf, len);
-      if (arg_addr_regno[i] >= 0)
-        {
-          /* We also need to store the address of that argument in
-             the given register.  */
-          gdb_byte buf[8];
-          enum bfd_endian byte_order = gdbarch_byte_order (gdbarch);
-
-          store_unsigned_integer (buf, 8, byte_order, arg_addr);
-          regcache_cooked_write (regcache, arg_addr_regno[i], buf);
-        }
+
+      write_memory (sp + element * 8, valbuf, len);
       element += ((len + 7) / 8);
     }
 
@@ -869,7 +894,6 @@ amd64_push_dummy_call (struct gdbarch *gdbarch, struct value *function,
                       int struct_return, CORE_ADDR struct_addr)
 {
   enum bfd_endian byte_order = gdbarch_byte_order (gdbarch);
-  struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
   gdb_byte buf[8];
 
   /* Pass arguments.  */
@@ -878,19 +902,10 @@ amd64_push_dummy_call (struct gdbarch *gdbarch, struct value *function,
   /* Pass "hidden" argument".  */
   if (struct_return)
     {
-      /* The "hidden" argument is passed throught the first argument
-         register.  */
-      const int arg_regnum = tdep->call_dummy_integer_regs[0];
-
       store_unsigned_integer (buf, 8, byte_order, struct_addr);
-      regcache_cooked_write (regcache, arg_regnum, buf);
+      regcache_cooked_write (regcache, AMD64_RDI_REGNUM, buf);
     }
 
-  /* Reserve some memory on the stack for the integer-parameter registers,
-     if required by the ABI.  */
-  if (tdep->integer_param_regs_saved_in_caller_frame)
-    sp -= tdep->call_dummy_num_integer_regs * 8;
-
   /* Store return address.  */
   sp -= 8;
   store_unsigned_integer (buf, 8, byte_order, bp_addr);
@@ -1259,7 +1274,7 @@ amd64_displaced_step_copy_insn (struct gdbarch *gdbarch,
                                struct regcache *regs)
 {
   int len = gdbarch_max_insn_length (gdbarch);
-  /* Extra space for sentinels so fixup_{riprel,displaced_copy don't have to
+  /* Extra space for sentinels so fixup_{riprel,displaced_copy} don't have to
      continually watch for running off the end of the buffer.  */
   int fixup_sentinel_space = len;
   struct displaced_step_closure *dsc =
@@ -1591,7 +1606,7 @@ amd64_relocate_instruction (struct gdbarch *gdbarch,
       /* Where "ret" in the original code will return to.  */
       ret_addr = oldloc + insn_length;
       push_buf[0] = 0x68; /* pushq $...  */
-      memcpy (&push_buf[1], &ret_addr, 4);
+      store_unsigned_integer (&push_buf[1], 4, byte_order, ret_addr);
       /* Push the push.  */
       append_insns (to, 5, push_buf);
 
@@ -1859,6 +1874,188 @@ amd64_analyze_stack_align (CORE_ADDR pc, CORE_ADDR current_pc,
   return min (pc + offset + 2, current_pc);
 }
 
+/* Similar to amd64_analyze_stack_align for x32.  */
+
+static CORE_ADDR
+amd64_x32_analyze_stack_align (CORE_ADDR pc, CORE_ADDR current_pc,
+                              struct amd64_frame_cache *cache) 
+{
+  /* There are 2 code sequences to re-align stack before the frame
+     gets set up:
+
+       1. Use a caller-saved saved register:
+
+               leaq  8(%rsp), %reg
+               andq  $-XXX, %rsp
+               pushq -8(%reg)
+
+          or
+
+               [addr32] leal  8(%rsp), %reg
+               andl  $-XXX, %esp
+               [addr32] pushq -8(%reg)
+
+       2. Use a callee-saved saved register:
+
+               pushq %reg
+               leaq  16(%rsp), %reg
+               andq  $-XXX, %rsp
+               pushq -8(%reg)
+
+          or
+
+               pushq %reg
+               [addr32] leal  16(%rsp), %reg
+               andl  $-XXX, %esp
+               [addr32] pushq -8(%reg)
+
+     "andq $-XXX, %rsp" can be either 4 bytes or 7 bytes:
+     
+       0x48 0x83 0xe4 0xf0                     andq $-16, %rsp
+       0x48 0x81 0xe4 0x00 0xff 0xff 0xff      andq $-256, %rsp
+
+     "andl $-XXX, %esp" can be either 3 bytes or 6 bytes:
+     
+       0x83 0xe4 0xf0                  andl $-16, %esp
+       0x81 0xe4 0x00 0xff 0xff 0xff   andl $-256, %esp
+   */
+
+  gdb_byte buf[19];
+  int reg, r;
+  int offset, offset_and;
+
+  if (target_read_memory (pc, buf, sizeof buf))
+    return pc;
+
+  /* Skip optional addr32 prefix.  */
+  offset = buf[0] == 0x67 ? 1 : 0;
+
+  /* Check caller-saved saved register.  The first instruction has
+     to be "leaq 8(%rsp), %reg" or "leal 8(%rsp), %reg".  */
+  if (((buf[offset] & 0xfb) == 0x48 || (buf[offset] & 0xfb) == 0x40)
+      && buf[offset + 1] == 0x8d
+      && buf[offset + 3] == 0x24
+      && buf[offset + 4] == 0x8)
+    {
+      /* MOD must be binary 10 and R/M must be binary 100.  */
+      if ((buf[offset + 2] & 0xc7) != 0x44)
+       return pc;
+
+      /* REG has register number.  */
+      reg = (buf[offset + 2] >> 3) & 7;
+
+      /* Check the REX.R bit.  */
+      if ((buf[offset] & 0x4) != 0)
+       reg += 8;
+
+      offset += 5;
+    }
+  else
+    {
+      /* Check callee-saved saved register.  The first instruction
+        has to be "pushq %reg".  */
+      reg = 0;
+      if ((buf[offset] & 0xf6) == 0x40
+         && (buf[offset + 1] & 0xf8) == 0x50)
+       {
+         /* Check the REX.B bit.  */
+         if ((buf[offset] & 1) != 0)
+           reg = 8;
+
+         offset += 1;
+       }
+      else if ((buf[offset] & 0xf8) != 0x50)
+       return pc;
+
+      /* Get register.  */
+      reg += buf[offset] & 0x7;
+
+      offset++;
+
+      /* Skip optional addr32 prefix.  */
+      if (buf[offset] == 0x67)
+       offset++;
+
+      /* The next instruction has to be "leaq 16(%rsp), %reg" or
+        "leal 16(%rsp), %reg".  */
+      if (((buf[offset] & 0xfb) != 0x48 && (buf[offset] & 0xfb) != 0x40)
+         || buf[offset + 1] != 0x8d
+         || buf[offset + 3] != 0x24
+         || buf[offset + 4] != 0x10)
+       return pc;
+
+      /* MOD must be binary 10 and R/M must be binary 100.  */
+      if ((buf[offset + 2] & 0xc7) != 0x44)
+       return pc;
+      
+      /* REG has register number.  */
+      r = (buf[offset + 2] >> 3) & 7;
+
+      /* Check the REX.R bit.  */
+      if ((buf[offset] & 0x4) != 0)
+       r += 8;
+
+      /* Registers in pushq and leaq have to be the same.  */
+      if (reg != r)
+       return pc;
+
+      offset += 5;
+    }
+
+  /* Rigister can't be %rsp nor %rbp.  */
+  if (reg == 4 || reg == 5)
+    return pc;
+
+  /* The next instruction may be "andq $-XXX, %rsp" or
+     "andl $-XXX, %esp".  */
+  if (buf[offset] != 0x48)
+    offset--;
+
+  if (buf[offset + 2] != 0xe4
+      || (buf[offset + 1] != 0x81 && buf[offset + 1] != 0x83))
+    return pc;
+
+  offset_and = offset;
+  offset += buf[offset + 1] == 0x81 ? 7 : 4;
+
+  /* Skip optional addr32 prefix.  */
+  if (buf[offset] == 0x67)
+    offset++;
+
+  /* The next instruction has to be "pushq -8(%reg)".  */
+  r = 0;
+  if (buf[offset] == 0xff)
+    offset++;
+  else if ((buf[offset] & 0xf6) == 0x40
+          && buf[offset + 1] == 0xff)
+    {
+      /* Check the REX.B bit.  */
+      if ((buf[offset] & 0x1) != 0)
+       r = 8;
+      offset += 2;
+    }
+  else
+    return pc;
+
+  /* 8bit -8 is 0xf8.  REG must be binary 110 and MOD must be binary
+     01.  */
+  if (buf[offset + 1] != 0xf8
+      || (buf[offset] & 0xf8) != 0x70)
+    return pc;
+
+  /* R/M has register.  */
+  r += buf[offset] & 7;
+
+  /* Registers in leaq and pushq have to be the same.  */
+  if (reg != r)
+    return pc;
+
+  if (current_pc > pc + offset_and)
+    cache->saved_sp_reg = amd64_arch_reg_to_regnum (reg);
+
+  return min (pc + offset + 2, current_pc);
+}
+
 /* Do a limited analysis of the prologue at PC and update CACHE
    accordingly.  Bail out early if CURRENT_PC is reached.  Return the
    address where the analysis stopped.
@@ -1866,10 +2063,16 @@ amd64_analyze_stack_align (CORE_ADDR pc, CORE_ADDR current_pc,
    We will handle only functions beginning with:
 
       pushq %rbp        0x55
-      movq %rsp, %rbp   0x48 0x89 0xe5
+      movq %rsp, %rbp   0x48 0x89 0xe5 (or 0x48 0x8b 0xec)
 
-   Any function that doesn't start with this sequence will be assumed
-   to have no prologue and thus no valid frame pointer in %rbp.  */
+   or (for the X32 ABI):
+
+      pushq %rbp        0x55
+      movl %esp, %ebp   0x89 0xe5 (or 0x8b 0xec)
+
+   Any function that doesn't start with one of these sequences will be
+   assumed to have no prologue and thus no valid frame pointer in
+   %rbp.  */
 
 static CORE_ADDR
 amd64_analyze_prologue (struct gdbarch *gdbarch,
@@ -1877,14 +2080,23 @@ amd64_analyze_prologue (struct gdbarch *gdbarch,
                        struct amd64_frame_cache *cache)
 {
   enum bfd_endian byte_order = gdbarch_byte_order (gdbarch);
-  static gdb_byte proto[3] = { 0x48, 0x89, 0xe5 }; /* movq %rsp, %rbp */
+  /* There are two variations of movq %rsp, %rbp.  */
+  static const gdb_byte mov_rsp_rbp_1[3] = { 0x48, 0x89, 0xe5 };
+  static const gdb_byte mov_rsp_rbp_2[3] = { 0x48, 0x8b, 0xec };
+  /* Ditto for movl %esp, %ebp.  */
+  static const gdb_byte mov_esp_ebp_1[2] = { 0x89, 0xe5 };
+  static const gdb_byte mov_esp_ebp_2[2] = { 0x8b, 0xec };
+
   gdb_byte buf[3];
   gdb_byte op;
 
   if (current_pc <= pc)
     return current_pc;
 
-  pc = amd64_analyze_stack_align (pc, current_pc, cache);
+  if (gdbarch_ptr_bit (gdbarch) == 32)
+    pc = amd64_x32_analyze_stack_align (pc, current_pc, cache);
+  else
+    pc = amd64_analyze_stack_align (pc, current_pc, cache);
 
   op = read_memory_unsigned_integer (pc, 1, byte_order);
 
@@ -1899,14 +2111,30 @@ amd64_analyze_prologue (struct gdbarch *gdbarch,
       if (current_pc <= pc + 1)
         return current_pc;
 
-      /* Check for `movq %rsp, %rbp'.  */
       read_memory (pc + 1, buf, 3);
-      if (memcmp (buf, proto, 3) != 0)
-       return pc + 1;
 
-      /* OK, we actually have a frame.  */
-      cache->frameless_p = 0;
-      return pc + 4;
+      /* Check for `movq %rsp, %rbp'.  */
+      if (memcmp (buf, mov_rsp_rbp_1, 3) == 0
+         || memcmp (buf, mov_rsp_rbp_2, 3) == 0)
+       {
+         /* OK, we actually have a frame.  */
+         cache->frameless_p = 0;
+         return pc + 4;
+       }
+
+      /* For X32, also check for `movq %esp, %ebp'.  */
+      if (gdbarch_ptr_bit (gdbarch) == 32)
+       {
+         if (memcmp (buf, mov_esp_ebp_1, 2) == 0
+             || memcmp (buf, mov_esp_ebp_2, 2) == 0)
+           {
+             /* OK, we actually have a frame.  */
+             cache->frameless_p = 0;
+             return pc + 3;
+           }
+       }
+
+      return pc + 1;
     }
 
   return pc;
@@ -1999,6 +2227,22 @@ amd64_skip_prologue (struct gdbarch *gdbarch, CORE_ADDR start_pc)
 {
   struct amd64_frame_cache cache;
   CORE_ADDR pc;
+  CORE_ADDR func_addr;
+
+  if (find_pc_partial_function (start_pc, NULL, &func_addr, NULL))
+    {
+      CORE_ADDR post_prologue_pc
+       = skip_prologue_using_sal (gdbarch, func_addr);
+      struct symtab *s = find_pc_symtab (func_addr);
+
+      /* Clang always emits a line note before the prologue and another
+        one after.  We trust clang to emit usable line notes.  */
+      if (post_prologue_pc
+         && (s != NULL
+             && s->producer != NULL
+             && strncmp (s->producer, "clang ", sizeof ("clang ") - 1) == 0))
+        return max (start_pc, post_prologue_pc);
+    }
 
   amd64_init_frame_cache (&cache);
   pc = amd64_analyze_prologue (gdbarch, start_pc, 0xffffffffffffffffLL,
@@ -2652,10 +2896,6 @@ amd64_init_abi (struct gdbarch_info info, struct gdbarch *gdbarch)
   set_gdbarch_push_dummy_call (gdbarch, amd64_push_dummy_call);
   set_gdbarch_frame_align (gdbarch, amd64_frame_align);
   set_gdbarch_frame_red_zone_size (gdbarch, 128);
-  tdep->call_dummy_num_integer_regs =
-    ARRAY_SIZE (amd64_dummy_call_integer_regs);
-  tdep->call_dummy_integer_regs = amd64_dummy_call_integer_regs;
-  tdep->classify = amd64_classify;
 
   set_gdbarch_convert_register_p (gdbarch, i387_convert_register_p);
   set_gdbarch_register_to_value (gdbarch, i387_register_to_value);
@@ -2689,6 +2929,53 @@ amd64_init_abi (struct gdbarch_info info, struct gdbarch *gdbarch)
   set_gdbarch_relocate_instruction (gdbarch, amd64_relocate_instruction);
 
   set_gdbarch_gen_return_address (gdbarch, amd64_gen_return_address);
+
+  /* SystemTap variables and functions.  */
+  set_gdbarch_stap_integer_prefix (gdbarch, "$");
+  set_gdbarch_stap_register_prefix (gdbarch, "%");
+  set_gdbarch_stap_register_indirection_prefix (gdbarch, "(");
+  set_gdbarch_stap_register_indirection_suffix (gdbarch, ")");
+  set_gdbarch_stap_is_single_operand (gdbarch,
+                                     i386_stap_is_single_operand);
+  set_gdbarch_stap_parse_special_token (gdbarch,
+                                       i386_stap_parse_special_token);
+}
+\f
+
+static struct type *
+amd64_x32_pseudo_register_type (struct gdbarch *gdbarch, int regnum)
+{
+  struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
+
+  switch (regnum - tdep->eax_regnum)
+    {
+    case AMD64_RBP_REGNUM:     /* %ebp */
+    case AMD64_RSP_REGNUM:     /* %esp */
+      return builtin_type (gdbarch)->builtin_data_ptr;
+    case AMD64_RIP_REGNUM:     /* %eip */
+      return builtin_type (gdbarch)->builtin_func_ptr;
+    }
+
+  return i386_pseudo_register_type (gdbarch, regnum);
+}
+
+void
+amd64_x32_init_abi (struct gdbarch_info info, struct gdbarch *gdbarch)
+{
+  struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
+  const struct target_desc *tdesc = info.target_desc;
+
+  amd64_init_abi (info, gdbarch);
+
+  if (! tdesc_has_registers (tdesc))
+    tdesc = tdesc_x32;
+  tdep->tdesc = tdesc;
+
+  tdep->num_dword_regs = 17;
+  set_tdesc_pseudo_register_type (gdbarch, amd64_x32_pseudo_register_type);
+
+  set_gdbarch_long_bit (gdbarch, 32);
+  set_gdbarch_ptr_bit (gdbarch, 32);
 }
 
 /* Provide a prototype to silence -Wmissing-prototypes.  */
@@ -2699,6 +2986,8 @@ _initialize_amd64_tdep (void)
 {
   initialize_tdesc_amd64 ();
   initialize_tdesc_amd64_avx ();
+  initialize_tdesc_x32 ();
+  initialize_tdesc_x32_avx ();
 }
 \f
 
@@ -2723,7 +3012,8 @@ amd64_supply_fxsave (struct regcache *regcache, int regnum,
 
   i387_supply_fxsave (regcache, regnum, fxsave);
 
-  if (fxsave && gdbarch_ptr_bit (gdbarch) == 64)
+  if (fxsave
+      && gdbarch_bfd_arch_info (gdbarch)->bits_per_word == 64)
     {
       const gdb_byte *regs = fxsave;
 
@@ -2745,7 +3035,8 @@ amd64_supply_xsave (struct regcache *regcache, int regnum,
 
   i387_supply_xsave (regcache, regnum, xsave);
 
-  if (xsave && gdbarch_ptr_bit (gdbarch) == 64)
+  if (xsave
+      && gdbarch_bfd_arch_info (gdbarch)->bits_per_word == 64)
     {
       const gdb_byte *regs = xsave;
 
@@ -2773,7 +3064,7 @@ amd64_collect_fxsave (const struct regcache *regcache, int regnum,
 
   i387_collect_fxsave (regcache, regnum, fxsave);
 
-  if (gdbarch_ptr_bit (gdbarch) == 64)
+  if (gdbarch_bfd_arch_info (gdbarch)->bits_per_word == 64)
     {
       if (regnum == -1 || regnum == I387_FISEG_REGNUM (tdep))
        regcache_raw_collect (regcache, I387_FISEG_REGNUM (tdep), regs + 12);
@@ -2794,7 +3085,7 @@ amd64_collect_xsave (const struct regcache *regcache, int regnum,
 
   i387_collect_xsave (regcache, regnum, xsave, gcore);
 
-  if (gdbarch_ptr_bit (gdbarch) == 64)
+  if (gdbarch_bfd_arch_info (gdbarch)->bits_per_word == 64)
     {
       if (regnum == -1 || regnum == I387_FISEG_REGNUM (tdep))
        regcache_raw_collect (regcache, I387_FISEG_REGNUM (tdep),
This page took 0.032995 seconds and 4 git commands to generate.