2004-06-06 Randolph Chung <tausq@debian.org>
[platform/upstream/binutils.git] / gdb / sh-tdep.c
index 52c2be5..866a351 100644 (file)
@@ -311,6 +311,9 @@ sh_breakpoint_from_pc (CORE_ADDR *pcptr, int *lenptr)
 #define GET_SOURCE_REG(x)      (((x) >> 4) & 0xf)
 #define GET_TARGET_REG(x)      (((x) >> 8) & 0xf)
 
+/* JSR @Rm         0100mmmm00001011 */
+#define IS_JSR(x)              (((x) & 0xf0ff) == 0x400b)
+
 /* STS.L PR,@-r15  0100111100100010
    r15-4-->r15, PR-->(r15) */
 #define IS_STS(x)              ((x) == 0x4f22)
@@ -437,9 +440,9 @@ sh_analyze_prologue (CORE_ADDR pc, CORE_ADDR current_pc,
              if (reg < 14)
                {
                  sav_reg = reg;
-                 offset = (((inst & 0xff) ^ 0x80) - 0x80) << 1;
+                 offset = (inst & 0xff) << 1;
                  sav_offset =
-                   read_memory_integer (((pc + 4) & ~3) + offset, 2);
+                   read_memory_integer ((pc + 4) + offset, 2);
                }
            }
        }
@@ -447,13 +450,13 @@ sh_analyze_prologue (CORE_ADDR pc, CORE_ADDR current_pc,
        {
          if (sav_reg < 0)
            {
-             reg = (inst & 0x0f00) >> 8;
+             reg = GET_TARGET_REG (inst);
              if (reg < 14)
                {
                  sav_reg = reg;
-                 offset = (((inst & 0xff) ^ 0x80) - 0x80) << 1;
+                 offset = (inst & 0xff) << 2;
                  sav_offset =
-                   read_memory_integer (((pc + 4) & ~3) + offset, 4);
+                   read_memory_integer (((pc & 0xfffffffc) + 4) + offset, 4);
                }
            }
        }
@@ -479,8 +482,7 @@ sh_analyze_prologue (CORE_ADDR pc, CORE_ADDR current_pc,
        }
       else if (IS_MOV_SP_FP (inst))
        {
-         if (!cache->uses_fp)
-           cache->uses_fp = 1;
+         cache->uses_fp = 1;
          /* At this point, only allow argument register moves to other
             registers or argument register moves to @(X,fp) which are
             moving the register arguments onto the stack area allocated
@@ -510,6 +512,20 @@ sh_analyze_prologue (CORE_ADDR pc, CORE_ADDR current_pc,
            }
          break;
        }
+      else if (IS_JSR (inst))
+       {
+         /* We have found a jsr that has been scheduled into the prologue.
+            If we continue the scan and return a pc someplace after this,
+            then setting a breakpoint on this function will cause it to
+            appear to be called after the function it is calling via the
+            jsr, which will be very confusing.  Most likely the next
+            instruction is going to be IS_MOV_SP_FP in the delay slot.  If
+            so, note that before returning the current pc. */
+         inst = read_memory_integer (pc + 2, 2);
+         if (IS_MOV_SP_FP (inst))
+           cache->uses_fp = 1;
+         break;
+       }
 #if 0                          /* This used to just stop when it found an instruction that
                                   was not considered part of the prologue.  Now, we just
                                   keep going looking for likely instructions. */
@@ -869,7 +885,7 @@ sh_treat_as_flt_p (struct type *type)
 
 static CORE_ADDR
 sh_push_dummy_call_fpu (struct gdbarch *gdbarch,
-                       CORE_ADDR func_addr,
+                       struct value *function,
                        struct regcache *regcache,
                        CORE_ADDR bp_addr, int nargs,
                        struct value **args,
@@ -981,7 +997,7 @@ sh_push_dummy_call_fpu (struct gdbarch *gdbarch,
 
 static CORE_ADDR
 sh_push_dummy_call_nofpu (struct gdbarch *gdbarch,
-                         CORE_ADDR func_addr,
+                         struct value *function,
                          struct regcache *regcache,
                          CORE_ADDR bp_addr,
                          int nargs, struct value **args,
@@ -1131,7 +1147,11 @@ sh3e_sh4_store_return_value (struct type *type, struct regcache *regcache,
       int len = TYPE_LENGTH (type);
       int i, regnum = FP0_REGNUM;
       for (i = 0; i < len; i += 4)
-       regcache_raw_write (regcache, regnum++, (char *) valbuf + i);
+       if (TARGET_BYTE_ORDER == BFD_ENDIAN_LITTLE)
+         regcache_raw_write (regcache, regnum++,
+                             (char *) valbuf + len - 4 - i);
+       else
+         regcache_raw_write (regcache, regnum++, (char *) valbuf + i);
     }
   else
     sh_default_store_return_value (type, regcache, valbuf);
@@ -1519,8 +1539,8 @@ sh_default_register_type (struct gdbarch *gdbarch, int reg_nr)
    because they are stored as 4 individual FP elements. */
 
 static void
-sh_sh4_register_convert_to_virtual (int regnum, struct type *type,
-                                   char *from, char *to)
+sh_register_convert_to_virtual (int regnum, struct type *type,
+                               char *from, char *to)
 {
   if (regnum >= DR0_REGNUM && regnum <= DR_LAST_REGNUM)
     {
@@ -1535,8 +1555,8 @@ sh_sh4_register_convert_to_virtual (int regnum, struct type *type,
 }
 
 static void
-sh_sh4_register_convert_to_raw (struct type *type, int regnum,
-                               const void *from, void *to)
+sh_register_convert_to_raw (struct type *type, int regnum,
+                           const void *from, void *to)
 {
   if (regnum >= DR0_REGNUM && regnum <= DR_LAST_REGNUM)
     {
@@ -1587,10 +1607,9 @@ sh_pseudo_register_read (struct gdbarch *gdbarch, struct regcache *regcache,
                            + register_size (gdbarch,
                                             base_regnum) * portion));
       /* We must pay attention to the endiannes. */
-      sh_sh4_register_convert_to_virtual (reg_nr,
-                                         gdbarch_register_type (gdbarch,
-                                                                reg_nr),
-                                         temp_buffer, buffer);
+      sh_register_convert_to_virtual (reg_nr,
+                                     gdbarch_register_type (gdbarch, reg_nr),
+                                     temp_buffer, buffer);
     }
   else if (reg_nr >= FV0_REGNUM && reg_nr <= FV_LAST_REGNUM)
     {
@@ -1617,8 +1636,8 @@ sh_pseudo_register_write (struct gdbarch *gdbarch, struct regcache *regcache,
       base_regnum = dr_reg_base_num (reg_nr);
 
       /* We must pay attention to the endiannes. */
-      sh_sh4_register_convert_to_raw (gdbarch_register_type (gdbarch, reg_nr),
-                                     reg_nr, buffer, temp_buffer);
+      sh_register_convert_to_raw (gdbarch_register_type (gdbarch, reg_nr),
+                                 reg_nr, buffer, temp_buffer);
 
       /* Write the real regs for which this one is an alias.  */
       for (portion = 0; portion < 2; portion++)
@@ -1777,35 +1796,23 @@ sh_print_registers_info (struct gdbarch *gdbarch, struct ui_file *file,
   else
     /* do all (or most) registers */
     {
-      regnum = 0;
-      while (regnum < NUM_REGS)
+      for (regnum = 0; regnum < NUM_REGS; ++regnum)
        {
          /* If the register name is empty, it is undefined for this
             processor, so don't display anything.  */
          if (REGISTER_NAME (regnum) == NULL
              || *(REGISTER_NAME (regnum)) == '\0')
-           {
-             regnum++;
-             continue;
-           }
+           continue;
 
          if (TYPE_CODE (gdbarch_register_type (gdbarch, regnum)) ==
              TYPE_CODE_FLT)
            {
+             /* true for "INFO ALL-REGISTERS" command */
              if (fpregs)
-               {
-                 /* true for "INFO ALL-REGISTERS" command */
-                 sh_do_fp_register (gdbarch, file, regnum);    /* FP regs */
-                 regnum++;
-               }
-             else
-               regnum += (FP_LAST_REGNUM - FP0_REGNUM);        /* skip FP regs */
+               sh_do_fp_register (gdbarch, file, regnum);      /* FP regs */
            }
          else
-           {
-             sh_do_register (gdbarch, file, regnum);   /* All other regs */
-             regnum++;
-           }
+           sh_do_register (gdbarch, file, regnum);     /* All other regs */
        }
 
       if (fpregs)
@@ -1874,8 +1881,8 @@ sh_dsp_register_sim_regno (int nr)
     return SIM_SH_RS_REGNUM;
   if (nr == RE_REGNUM)
     return SIM_SH_RE_REGNUM;
-  if (nr >= R0_BANK_REGNUM && nr <= R7_BANK_REGNUM)
-    return nr - R0_BANK_REGNUM + SIM_SH_R0_BANK_REGNUM;
+  if (nr >= DSP_R0_BANK_REGNUM && nr <= DSP_R7_BANK_REGNUM)
+    return nr - DSP_R0_BANK_REGNUM + SIM_SH_R0_BANK_REGNUM;
   return nr;
 }
 
@@ -2224,8 +2231,7 @@ sh_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches)
 
   set_gdbarch_push_dummy_call (gdbarch, sh_push_dummy_call_nofpu);
 
-  set_gdbarch_frameless_function_invocation (gdbarch,
-                                            frameless_look_for_prologue);
+  set_gdbarch_deprecated_frameless_function_invocation (gdbarch, legacy_frameless_look_for_prologue);
   set_gdbarch_believe_pcc_promotion (gdbarch, 1);
 
   set_gdbarch_frame_align (gdbarch, sh_frame_align);