* mips-tdep.c (mips_skip_mips16_trampoline_code): Sign-extend
authorMaciej W. Rozycki <macro@linux-mips.org>
Thu, 8 Dec 2011 19:03:24 +0000 (19:03 +0000)
committerMaciej W. Rozycki <macro@linux-mips.org>
Thu, 8 Dec 2011 19:03:24 +0000 (19:03 +0000)
address chunks retrieved from decoded lui/addiu pairs.

gdb/ChangeLog
gdb/mips-tdep.c

index 2fb4758e56335ec50416b09f1a77ae97ff7eecf7..209f7b944782e8067628deb0d6222064e5ca46c9 100644 (file)
@@ -1,3 +1,9 @@
+2011-12-08  Maciej W. Rozycki  <macro@mips.com>
+            Maciej W. Rozycki  <macro@codesourcery.com>
+
+       * mips-tdep.c (mips_skip_mips16_trampoline_code): Sign-extend
+       address chunks retrieved from decoded lui/addiu pairs.
+
 2011-12-08  Maciej W. Rozycki  <macro@codesourcery.com>
 
        * mips-tdep.c (extended_offset): Correct calculation.
index 0f9a4abe0acc3da59bfd4a9a14ec6e1a6a5acdb0..0b950f27b152e4b2ae72e2f3b52d5713c76f0093 100644 (file)
@@ -5356,7 +5356,6 @@ mips_skip_mips16_trampoline_code (struct frame_info *frame, CORE_ADDR pc)
                 address from those two instructions.  */
 
              CORE_ADDR target_pc = get_frame_register_signed (frame, 2);
-             ULONGEST inst;
              int i;
 
              /* See if the name of the target function is  __fn_stub_*.  */
@@ -5373,11 +5372,15 @@ mips_skip_mips16_trampoline_code (struct frame_info *frame, CORE_ADDR pc)
                 instructions.  FIXME.  */
              for (i = 0, pc = 0; i < 20; i++, target_pc += MIPS_INSN32_SIZE)
                {
-                 inst = mips_fetch_instruction (gdbarch, target_pc);
+                 ULONGEST inst = mips_fetch_instruction (gdbarch, target_pc);
+                 CORE_ADDR addr = inst;
+
                  if ((inst & 0xffff0000) == 0x3c010000)        /* lui $at */
-                   pc = (inst << 16) & 0xffff0000;             /* high word */
+                   pc = (((addr & 0xffff) ^ 0x8000) - 0x8000) << 16;
+                                                               /* high word */
                  else if ((inst & 0xffff0000) == 0x24210000)   /* addiu $at */
-                   return pc | (inst & 0xffff);                /* low word */
+                   return pc + ((addr & 0xffff) ^ 0x8000) - 0x8000;
+                                                               /* low word */
                }
 
              /* Couldn't find the lui/addui pair, so return stub address.  */