* mips-tdep.c (make_mips16_addr): New function.
authorKevin Buettner <kevinb@redhat.com>
Fri, 17 Dec 2010 21:39:27 +0000 (21:39 +0000)
committerKevin Buettner <kevinb@redhat.com>
Fri, 17 Dec 2010 21:39:27 +0000 (21:39 +0000)
(mips_elf_make_msymbol_special): Don't set the low bit in the
symbol's address.
(mips_read_pc, mips_unwind_pc, mips_addr_bits_remove): Strip bit
indicating mips16 address, if present.
(mips_write_pc): Set bit indicating mips16 address when in a mips16
function.
(mips_eabi_push_dummy_call, mips_o64_push_dummy_call): Likewise,
but for each function pointer argument to inferior function call.

gdb/ChangeLog
gdb/mips-tdep.c

index 0efe32700a63a03c755a02970ce3955c6de26923..46f4fe479061fda6ec8b30018b863bab91185710 100644 (file)
@@ -1,3 +1,15 @@
+2010-12-17  Kevin Buettner  <kevinb@redhat.com>
+
+       * mips-tdep.c (make_mips16_addr): New function.
+       (mips_elf_make_msymbol_special): Don't set the low bit in the
+       symbol's address.
+       (mips_read_pc, mips_unwind_pc, mips_addr_bits_remove): Strip bit
+       indicating mips16 address, if present.
+       (mips_write_pc): Set bit indicating mips16 address when in a mips16
+       function.
+       (mips_eabi_push_dummy_call, mips_o64_push_dummy_call): Likewise,
+       but for each function pointer argument to inferior function call.
+
 2010-12-17  Tom Tromey  <tromey@redhat.com>
 
        * psympriv.h (struct partial_symtab) <readin>: Move field
index 6b9c5f6c83b7bb6377098f74baebc0355df00fef..81f2d7de63cce4bda6ba399857b1f54eefe1c034 100644 (file)
@@ -205,6 +205,12 @@ unmake_mips16_addr (CORE_ADDR addr)
   return ((addr) & ~(CORE_ADDR) 1);
 }
 
+static CORE_ADDR
+make_mips16_addr (CORE_ADDR addr)
+{
+  return ((addr) | (CORE_ADDR) 1);
+}
+
 /* Return the MIPS ABI associated with GDBARCH.  */
 enum mips_abi
 mips_abi (struct gdbarch *gdbarch)
@@ -264,7 +270,6 @@ mips_elf_make_msymbol_special (asymbol * sym, struct minimal_symbol *msym)
   if (((elf_symbol_type *) (sym))->internal_elf_sym.st_other == STO_MIPS16)
     {
       MSYMBOL_TARGET_FLAG_1 (msym) = 1;
-      SYMBOL_VALUE_ADDRESS (msym) |= 1;
     }
 }
 
@@ -931,14 +936,21 @@ mips_read_pc (struct regcache *regcache)
   ULONGEST pc;
   int regnum = mips_regnum (get_regcache_arch (regcache))->pc;
   regcache_cooked_read_signed (regcache, regnum, &pc);
+  if (is_mips16_addr (pc))
+    pc = unmake_mips16_addr (pc);
   return pc;
 }
 
 static CORE_ADDR
 mips_unwind_pc (struct gdbarch *gdbarch, struct frame_info *next_frame)
 {
-  return frame_unwind_register_signed
-          (next_frame, gdbarch_num_regs (gdbarch) + mips_regnum (gdbarch)->pc);
+  ULONGEST pc;
+
+  pc = frame_unwind_register_signed
+        (next_frame, gdbarch_num_regs (gdbarch) + mips_regnum (gdbarch)->pc);
+  if (is_mips16_addr (pc))
+    pc = unmake_mips16_addr (pc);
+  return pc;
 }
 
 static CORE_ADDR
@@ -967,7 +979,10 @@ static void
 mips_write_pc (struct regcache *regcache, CORE_ADDR pc)
 {
   int regnum = mips_regnum (get_regcache_arch (regcache))->pc;
-  regcache_cooked_write_unsigned (regcache, regnum, pc);
+  if (mips_pc_is_mips16 (pc))
+    regcache_cooked_write_unsigned (regcache, regnum, make_mips16_addr (pc));
+  else
+    regcache_cooked_write_unsigned (regcache, regnum, pc);
 }
 
 /* Fetch and return instruction from the specified location.  If the PC
@@ -2450,6 +2465,10 @@ static CORE_ADDR
 mips_addr_bits_remove (struct gdbarch *gdbarch, CORE_ADDR addr)
 {
   struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
+
+  if (is_mips16_addr (addr))
+    addr = unmake_mips16_addr (addr);
+
   if (mips_mask_address_p (tdep) && (((ULONGEST) addr) >> 32 == 0xffffffffUL))
     /* This hack is a work-around for existing boards using PMON, the
        simulator, and any other 64-bit targets that doesn't have true
@@ -2869,9 +2888,25 @@ mips_eabi_push_dummy_call (struct gdbarch *gdbarch, struct value *function,
                            "mips_eabi_push_dummy_call: %d len=%d type=%d",
                            argnum + 1, len, (int) typecode);
 
+      /* Function pointer arguments to mips16 code need to be made into
+         mips16 pointers.  */
+      if (typecode == TYPE_CODE_PTR
+          && TYPE_CODE (TYPE_TARGET_TYPE (arg_type)) == TYPE_CODE_FUNC)
+       {
+         CORE_ADDR addr = extract_signed_integer (value_contents (arg),
+                                                  len, byte_order);
+         if (mips_pc_is_mips16 (addr))
+           {
+             store_signed_integer (valbuf, len, byte_order, 
+                                   make_mips16_addr (addr));
+             val = valbuf;
+           }
+         else
+           val = value_contents (arg);
+       }
       /* The EABI passes structures that do not fit in a register by
          reference.  */
-      if (len > regsize
+      else if (len > regsize
          && (typecode == TYPE_CODE_STRUCT || typecode == TYPE_CODE_UNION))
        {
          store_unsigned_integer (valbuf, regsize, byte_order,
@@ -4159,6 +4194,7 @@ mips_o64_push_dummy_call (struct gdbarch *gdbarch, struct value *function,
   for (argnum = 0; argnum < nargs; argnum++)
     {
       const gdb_byte *val;
+      gdb_byte valbuf[MAX_REGISTER_SIZE];
       struct value *arg = args[argnum];
       struct type *arg_type = check_typedef (value_type (arg));
       int len = TYPE_LENGTH (arg_type);
@@ -4171,6 +4207,21 @@ mips_o64_push_dummy_call (struct gdbarch *gdbarch, struct value *function,
 
       val = value_contents (arg);
 
+      /* Function pointer arguments to mips16 code need to be made into
+         mips16 pointers.  */
+      if (typecode == TYPE_CODE_PTR
+          && TYPE_CODE (TYPE_TARGET_TYPE (arg_type)) == TYPE_CODE_FUNC)
+       {
+         CORE_ADDR addr = extract_signed_integer (value_contents (arg),
+                                                  len, byte_order);
+         if (mips_pc_is_mips16 (addr))
+           {
+             store_signed_integer (valbuf, len, byte_order, 
+                                   make_mips16_addr (addr));
+             val = valbuf;
+           }
+       }
+
       /* Floating point arguments passed in registers have to be
          treated specially.  On 32-bit architectures, doubles
          are passed in register pairs; the even register gets