OpenCores
URL https://opencores.org/ocsvn/openrisc/openrisc/trunk

Subversion Repositories openrisc

[/] [openrisc/] [trunk/] [gnu-old/] [gdb-7.1/] [gdb/] [score-tdep.c] - Diff between revs 834 and 842

Go to most recent revision | Only display areas with differences | Details | Blame | View Log

Rev 834 Rev 842
/* Target-dependent code for the S+core architecture, for GDB,
/* Target-dependent code for the S+core architecture, for GDB,
   the GNU Debugger.
   the GNU Debugger.
 
 
   Copyright (C) 2006, 2007, 2008, 2009, 2010 Free Software Foundation, Inc.
   Copyright (C) 2006, 2007, 2008, 2009, 2010 Free Software Foundation, Inc.
 
 
   Contributed by Qinwei (qinwei@sunnorth.com.cn)
   Contributed by Qinwei (qinwei@sunnorth.com.cn)
   Contributed by Ching-Peng Lin (cplin@sunplus.com)
   Contributed by Ching-Peng Lin (cplin@sunplus.com)
 
 
   This file is part of GDB.
   This file is part of GDB.
 
 
   This program is free software; you can redistribute it and/or modify
   This program is free software; you can redistribute it and/or modify
   it under the terms of the GNU General Public License as published by
   it under the terms of the GNU General Public License as published by
   the Free Software Foundation; either version 3 of the License, or
   the Free Software Foundation; either version 3 of the License, or
   (at your option) any later version.
   (at your option) any later version.
 
 
   This program is distributed in the hope that it will be useful,
   This program is distributed in the hope that it will be useful,
   but WITHOUT ANY WARRANTY; without even the implied warranty of
   but WITHOUT ANY WARRANTY; without even the implied warranty of
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   GNU General Public License for more details.
   GNU General Public License for more details.
 
 
   You should have received a copy of the GNU General Public License
   You should have received a copy of the GNU General Public License
   along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
   along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
 
 
#include "defs.h"
#include "defs.h"
#include "gdb_assert.h"
#include "gdb_assert.h"
#include "inferior.h"
#include "inferior.h"
#include "symtab.h"
#include "symtab.h"
#include "objfiles.h"
#include "objfiles.h"
#include "gdbcore.h"
#include "gdbcore.h"
#include "target.h"
#include "target.h"
#include "arch-utils.h"
#include "arch-utils.h"
#include "regcache.h"
#include "regcache.h"
#include "regset.h"
#include "regset.h"
#include "dis-asm.h"
#include "dis-asm.h"
#include "frame-unwind.h"
#include "frame-unwind.h"
#include "frame-base.h"
#include "frame-base.h"
#include "trad-frame.h"
#include "trad-frame.h"
#include "dwarf2-frame.h"
#include "dwarf2-frame.h"
#include "score-tdep.h"
#include "score-tdep.h"
 
 
#define G_FLD(_i,_ms,_ls) \
#define G_FLD(_i,_ms,_ls) \
    ((unsigned)((_i) << (31 - (_ms))) >> (31 - (_ms) + (_ls)))
    ((unsigned)((_i) << (31 - (_ms))) >> (31 - (_ms) + (_ls)))
 
 
typedef struct{
typedef struct{
    unsigned long long v;
    unsigned long long v;
    unsigned long long raw;
    unsigned long long raw;
    unsigned int len;
    unsigned int len;
}inst_t;
}inst_t;
 
 
struct score_frame_cache
struct score_frame_cache
{
{
  CORE_ADDR base;
  CORE_ADDR base;
  CORE_ADDR fp;
  CORE_ADDR fp;
  struct trad_frame_saved_reg *saved_regs;
  struct trad_frame_saved_reg *saved_regs;
};
};
 
 
static int target_mach = bfd_mach_score7;
static int target_mach = bfd_mach_score7;
 
 
static struct type *
static struct type *
score_register_type (struct gdbarch *gdbarch, int regnum)
score_register_type (struct gdbarch *gdbarch, int regnum)
{
{
  gdb_assert (regnum >= 0
  gdb_assert (regnum >= 0
              && regnum < ((target_mach == bfd_mach_score7) ? SCORE7_NUM_REGS : SCORE3_NUM_REGS));
              && regnum < ((target_mach == bfd_mach_score7) ? SCORE7_NUM_REGS : SCORE3_NUM_REGS));
  return builtin_type (gdbarch)->builtin_uint32;
  return builtin_type (gdbarch)->builtin_uint32;
}
}
 
 
static CORE_ADDR
static CORE_ADDR
score_unwind_sp (struct gdbarch *gdbarch, struct frame_info *next_frame)
score_unwind_sp (struct gdbarch *gdbarch, struct frame_info *next_frame)
{
{
  return frame_unwind_register_unsigned (next_frame, SCORE_SP_REGNUM);
  return frame_unwind_register_unsigned (next_frame, SCORE_SP_REGNUM);
}
}
 
 
static CORE_ADDR
static CORE_ADDR
score_unwind_pc (struct gdbarch *gdbarch, struct frame_info *next_frame)
score_unwind_pc (struct gdbarch *gdbarch, struct frame_info *next_frame)
{
{
  return frame_unwind_register_unsigned (next_frame, SCORE_PC_REGNUM);
  return frame_unwind_register_unsigned (next_frame, SCORE_PC_REGNUM);
}
}
 
 
static const char *
static const char *
score7_register_name (struct gdbarch *gdbarch, int regnum)
score7_register_name (struct gdbarch *gdbarch, int regnum)
{
{
  const char *score_register_names[] = {
  const char *score_register_names[] = {
    "r0",  "r1",  "r2",  "r3",  "r4",  "r5",  "r6",  "r7",
    "r0",  "r1",  "r2",  "r3",  "r4",  "r5",  "r6",  "r7",
    "r8",  "r9",  "r10", "r11", "r12", "r13", "r14", "r15",
    "r8",  "r9",  "r10", "r11", "r12", "r13", "r14", "r15",
    "r16", "r17", "r18", "r19", "r20", "r21", "r22", "r23",
    "r16", "r17", "r18", "r19", "r20", "r21", "r22", "r23",
    "r24", "r25", "r26", "r27", "r28", "r29", "r30", "r31",
    "r24", "r25", "r26", "r27", "r28", "r29", "r30", "r31",
 
 
    "PSR",     "COND",  "ECR",     "EXCPVEC", "CCR",
    "PSR",     "COND",  "ECR",     "EXCPVEC", "CCR",
    "EPC",     "EMA",   "TLBLOCK", "TLBPT",   "PEADDR",
    "EPC",     "EMA",   "TLBLOCK", "TLBPT",   "PEADDR",
    "TLBRPT",  "PEVN",  "PECTX",   "LIMPFN",  "LDMPFN",
    "TLBRPT",  "PEVN",  "PECTX",   "LIMPFN",  "LDMPFN",
    "PREV",    "DREG",  "PC",      "DSAVE",   "COUNTER",
    "PREV",    "DREG",  "PC",      "DSAVE",   "COUNTER",
    "LDCR",    "STCR",  "CEH",     "CEL",
    "LDCR",    "STCR",  "CEH",     "CEL",
  };
  };
 
 
  gdb_assert (regnum >= 0 && regnum < SCORE7_NUM_REGS);
  gdb_assert (regnum >= 0 && regnum < SCORE7_NUM_REGS);
  return score_register_names[regnum];
  return score_register_names[regnum];
}
}
 
 
static const char *
static const char *
score3_register_name (struct gdbarch *gdbarch, int regnum)
score3_register_name (struct gdbarch *gdbarch, int regnum)
{
{
  const char *score_register_names[] = {
  const char *score_register_names[] = {
    "r0",  "r1",  "r2",  "r3",  "r4",  "r5",  "r6",  "r7",
    "r0",  "r1",  "r2",  "r3",  "r4",  "r5",  "r6",  "r7",
    "r8",  "r9",  "r10", "r11", "r12", "r13", "r14", "r15",
    "r8",  "r9",  "r10", "r11", "r12", "r13", "r14", "r15",
    "r16", "r17", "r18", "r19", "r20", "r21", "r22", "r23",
    "r16", "r17", "r18", "r19", "r20", "r21", "r22", "r23",
    "r24", "r25", "r26", "r27", "r28", "r29", "r30", "r31",
    "r24", "r25", "r26", "r27", "r28", "r29", "r30", "r31",
 
 
    "PSR",      "COND",   "ECR",   "EXCPVEC",  "CCR",
    "PSR",      "COND",   "ECR",   "EXCPVEC",  "CCR",
    "EPC",      "EMA",    "PREV",  "DREG",     "DSAVE",
    "EPC",      "EMA",    "PREV",  "DREG",     "DSAVE",
    "COUNTER",  "LDCR",   "STCR",  "CEH",      "CEL",
    "COUNTER",  "LDCR",   "STCR",  "CEH",      "CEL",
    "",         "",       "PC",
    "",         "",       "PC",
  };
  };
 
 
  gdb_assert (regnum >= 0 && regnum < SCORE3_NUM_REGS);
  gdb_assert (regnum >= 0 && regnum < SCORE3_NUM_REGS);
  return score_register_names[regnum];
  return score_register_names[regnum];
}
}
 
 
#if WITH_SIM
#if WITH_SIM
static int
static int
score_register_sim_regno (struct gdbarch *gdbarch, int regnum)
score_register_sim_regno (struct gdbarch *gdbarch, int regnum)
{
{
  gdb_assert (regnum >= 0
  gdb_assert (regnum >= 0
              && regnum < ((target_mach == bfd_mach_score7) ? SCORE7_NUM_REGS : SCORE3_NUM_REGS));
              && regnum < ((target_mach == bfd_mach_score7) ? SCORE7_NUM_REGS : SCORE3_NUM_REGS));
  return regnum;
  return regnum;
}
}
#endif
#endif
 
 
static int
static int
score_print_insn (bfd_vma memaddr, struct disassemble_info *info)
score_print_insn (bfd_vma memaddr, struct disassemble_info *info)
{
{
  if (info->endian == BFD_ENDIAN_BIG)
  if (info->endian == BFD_ENDIAN_BIG)
    return print_insn_big_score (memaddr, info);
    return print_insn_big_score (memaddr, info);
  else
  else
    return print_insn_little_score (memaddr, info);
    return print_insn_little_score (memaddr, info);
}
}
 
 
static inst_t *
static inst_t *
score7_fetch_inst (struct gdbarch *gdbarch, CORE_ADDR addr, char *memblock)
score7_fetch_inst (struct gdbarch *gdbarch, CORE_ADDR addr, char *memblock)
{
{
  enum bfd_endian byte_order = gdbarch_byte_order (gdbarch);
  enum bfd_endian byte_order = gdbarch_byte_order (gdbarch);
  static inst_t inst = { 0, 0, 0 };
  static inst_t inst = { 0, 0, 0 };
  char buf[SCORE_INSTLEN] = { 0 };
  char buf[SCORE_INSTLEN] = { 0 };
  int big;
  int big;
  int ret;
  int ret;
 
 
  if (target_has_execution && memblock != NULL)
  if (target_has_execution && memblock != NULL)
    {
    {
      /* Fetch instruction from local MEMBLOCK.  */
      /* Fetch instruction from local MEMBLOCK.  */
      memcpy (buf, memblock, SCORE_INSTLEN);
      memcpy (buf, memblock, SCORE_INSTLEN);
    }
    }
  else
  else
    {
    {
      /* Fetch instruction from target.  */
      /* Fetch instruction from target.  */
      ret = target_read_memory (addr & ~0x3, buf, SCORE_INSTLEN);
      ret = target_read_memory (addr & ~0x3, buf, SCORE_INSTLEN);
      if (ret)
      if (ret)
        {
        {
          error ("Error: target_read_memory in file:%s, line:%d!",
          error ("Error: target_read_memory in file:%s, line:%d!",
                  __FILE__, __LINE__);
                  __FILE__, __LINE__);
          return 0;
          return 0;
        }
        }
    }
    }
 
 
  inst.raw = extract_unsigned_integer (buf, SCORE_INSTLEN, byte_order);
  inst.raw = extract_unsigned_integer (buf, SCORE_INSTLEN, byte_order);
  inst.len = (inst.raw & 0x80008000) ? 4 : 2;
  inst.len = (inst.raw & 0x80008000) ? 4 : 2;
  inst.v = ((inst.raw >> 16 & 0x7FFF) << 15) | (inst.raw & 0x7FFF);
  inst.v = ((inst.raw >> 16 & 0x7FFF) << 15) | (inst.raw & 0x7FFF);
  big = (byte_order == BFD_ENDIAN_BIG);
  big = (byte_order == BFD_ENDIAN_BIG);
  if (inst.len == 2)
  if (inst.len == 2)
    {
    {
      if (big ^ ((addr & 0x2) == 2))
      if (big ^ ((addr & 0x2) == 2))
        inst.v = G_FLD (inst.v, 29, 15);
        inst.v = G_FLD (inst.v, 29, 15);
      else
      else
        inst.v = G_FLD (inst.v, 14, 0);
        inst.v = G_FLD (inst.v, 14, 0);
    }
    }
  return &inst;
  return &inst;
}
}
 
 
static inst_t *
static inst_t *
score3_adjust_pc_and_fetch_inst (CORE_ADDR *pcptr, int *lenptr,
score3_adjust_pc_and_fetch_inst (CORE_ADDR *pcptr, int *lenptr,
                                 enum bfd_endian byte_order)
                                 enum bfd_endian byte_order)
{
{
  static inst_t inst = { 0, 0, 0 };
  static inst_t inst = { 0, 0, 0 };
 
 
  struct breakplace
  struct breakplace
  {
  {
    int break_offset;
    int break_offset;
    int inst_len;
    int inst_len;
  };
  };
  /*     raw        table 1 (column 2, 3, 4)
  /*     raw        table 1 (column 2, 3, 4)
    *  0  1  0  *   # 2
    *  0  1  0  *   # 2
    *  0  1  1  0   # 3
    *  0  1  1  0   # 3
    0  1  1  0  *   # 6
    0  1  1  0  *   # 6
                    table 2 (column 1, 2, 3)
                    table 2 (column 1, 2, 3)
    *  0  0  *  *   # 0, 4
    *  0  0  *  *   # 0, 4
    0  1  0  *  *   # 2
    0  1  0  *  *   # 2
    1  1  0  *  *   # 6
    1  1  0  *  *   # 6
   */
   */
 
 
  static const struct breakplace bk_table[16] =
  static const struct breakplace bk_table[16] =
    {
    {
      /* table 1 */
      /* table 1 */
      {0, 0},
      {0, 0},
      {0, 0},
      {0, 0},
      {0, 4},
      {0, 4},
      {0, 6},
      {0, 6},
      {0, 0},
      {0, 0},
      {0, 0},
      {0, 0},
      {-2, 6},
      {-2, 6},
      {0, 0},
      {0, 0},
      /* table 2 */
      /* table 2 */
      {0, 2},
      {0, 2},
      {0, 0},
      {0, 0},
      {-2, 4},
      {-2, 4},
      {0, 0},
      {0, 0},
      {0, 2},
      {0, 2},
      {0, 0},
      {0, 0},
      {-4, 6},
      {-4, 6},
      {0, 0}
      {0, 0}
    };
    };
 
 
#define EXTRACT_LEN 2
#define EXTRACT_LEN 2
  CORE_ADDR adjust_pc = *pcptr & ~0x1;
  CORE_ADDR adjust_pc = *pcptr & ~0x1;
  int inst_len;
  int inst_len;
  gdb_byte buf[5][EXTRACT_LEN] =
  gdb_byte buf[5][EXTRACT_LEN] =
    {
    {
      {'\0', '\0'},
      {'\0', '\0'},
      {'\0', '\0'},
      {'\0', '\0'},
      {'\0', '\0'},
      {'\0', '\0'},
      {'\0', '\0'},
      {'\0', '\0'},
      {'\0', '\0'}
      {'\0', '\0'}
    };
    };
  int ret;
  int ret;
  unsigned int raw;
  unsigned int raw;
  unsigned int cbits = 0;
  unsigned int cbits = 0;
  int bk_index;
  int bk_index;
  int i, count;
  int i, count;
 
 
  inst.v = 0;
  inst.v = 0;
  inst.raw = 0;
  inst.raw = 0;
  inst.len = 0;
  inst.len = 0;
 
 
  adjust_pc -= 4;
  adjust_pc -= 4;
  for (i = 0; i < 5; i++)
  for (i = 0; i < 5; i++)
    {
    {
      ret = target_read_memory (adjust_pc + 2 * i, buf[i], EXTRACT_LEN);
      ret = target_read_memory (adjust_pc + 2 * i, buf[i], EXTRACT_LEN);
      if (ret != 0)
      if (ret != 0)
        {
        {
          buf[i][0] = '\0';
          buf[i][0] = '\0';
          buf[i][1] = '\0';
          buf[i][1] = '\0';
          if (i == 2)
          if (i == 2)
            error ("Error: target_read_memory in file:%s, line:%d!",
            error ("Error: target_read_memory in file:%s, line:%d!",
                   __FILE__, __LINE__);
                   __FILE__, __LINE__);
        }
        }
 
 
      raw = extract_unsigned_integer (buf[i], EXTRACT_LEN, byte_order);
      raw = extract_unsigned_integer (buf[i], EXTRACT_LEN, byte_order);
      cbits = (cbits << 1) | (raw >> 15);
      cbits = (cbits << 1) | (raw >> 15);
    }
    }
  adjust_pc += 4;
  adjust_pc += 4;
 
 
  if (cbits & 0x4)
  if (cbits & 0x4)
    {
    {
      /* table 1 */
      /* table 1 */
      cbits = (cbits >> 1) & 0x7;
      cbits = (cbits >> 1) & 0x7;
      bk_index = cbits;
      bk_index = cbits;
    }
    }
  else
  else
    {
    {
      /* table 2 */
      /* table 2 */
      cbits = (cbits >> 2) & 0x7;
      cbits = (cbits >> 2) & 0x7;
      bk_index = cbits + 8;
      bk_index = cbits + 8;
    }
    }
 
 
  gdb_assert (!((bk_table[bk_index].break_offset == 0)
  gdb_assert (!((bk_table[bk_index].break_offset == 0)
                && (bk_table[bk_index].inst_len == 0)));
                && (bk_table[bk_index].inst_len == 0)));
 
 
  inst.len = bk_table[bk_index].inst_len;
  inst.len = bk_table[bk_index].inst_len;
 
 
  i = (bk_table[bk_index].break_offset + 4) / 2;
  i = (bk_table[bk_index].break_offset + 4) / 2;
  count = inst.len / 2;
  count = inst.len / 2;
  for (; count > 0; i++, count--)
  for (; count > 0; i++, count--)
    {
    {
      inst.raw = (inst.raw << 16)
      inst.raw = (inst.raw << 16)
                 | extract_unsigned_integer (buf[i], EXTRACT_LEN, byte_order);
                 | extract_unsigned_integer (buf[i], EXTRACT_LEN, byte_order);
    }
    }
 
 
  switch (inst.len)
  switch (inst.len)
    {
    {
    case 2:
    case 2:
      inst.v = inst.raw & 0x7FFF;
      inst.v = inst.raw & 0x7FFF;
      break;
      break;
    case 4:
    case 4:
      inst.v = ((inst.raw >> 16 & 0x7FFF) << 15) | (inst.raw & 0x7FFF);
      inst.v = ((inst.raw >> 16 & 0x7FFF) << 15) | (inst.raw & 0x7FFF);
      break;
      break;
    case 6:
    case 6:
      inst.v = ((inst.raw >> 32 & 0x7FFF) << 30)
      inst.v = ((inst.raw >> 32 & 0x7FFF) << 30)
               | ((inst.raw >> 16 & 0x7FFF) << 15) | (inst.raw & 0x7FFF);
               | ((inst.raw >> 16 & 0x7FFF) << 15) | (inst.raw & 0x7FFF);
      break;
      break;
    }
    }
 
 
  if (pcptr)
  if (pcptr)
    *pcptr = adjust_pc + bk_table[bk_index].break_offset;
    *pcptr = adjust_pc + bk_table[bk_index].break_offset;
  if (lenptr)
  if (lenptr)
    *lenptr = bk_table[bk_index].inst_len;
    *lenptr = bk_table[bk_index].inst_len;
 
 
#undef EXTRACT_LEN
#undef EXTRACT_LEN
 
 
  return &inst;
  return &inst;
}
}
 
 
static const gdb_byte *
static const gdb_byte *
score7_breakpoint_from_pc (struct gdbarch *gdbarch, CORE_ADDR *pcptr,
score7_breakpoint_from_pc (struct gdbarch *gdbarch, CORE_ADDR *pcptr,
                           int *lenptr)
                           int *lenptr)
{
{
  enum bfd_endian byte_order = gdbarch_byte_order (gdbarch);
  enum bfd_endian byte_order = gdbarch_byte_order (gdbarch);
  gdb_byte buf[SCORE_INSTLEN] = { 0 };
  gdb_byte buf[SCORE_INSTLEN] = { 0 };
  int ret;
  int ret;
  unsigned int raw;
  unsigned int raw;
 
 
  if ((ret = target_read_memory (*pcptr & ~0x3, buf, SCORE_INSTLEN)) != 0)
  if ((ret = target_read_memory (*pcptr & ~0x3, buf, SCORE_INSTLEN)) != 0)
    {
    {
      error ("Error: target_read_memory in file:%s, line:%d!",
      error ("Error: target_read_memory in file:%s, line:%d!",
             __FILE__, __LINE__);
             __FILE__, __LINE__);
    }
    }
  raw = extract_unsigned_integer (buf, SCORE_INSTLEN, byte_order);
  raw = extract_unsigned_integer (buf, SCORE_INSTLEN, byte_order);
 
 
  if (byte_order == BFD_ENDIAN_BIG)
  if (byte_order == BFD_ENDIAN_BIG)
    {
    {
      if (!(raw & 0x80008000))
      if (!(raw & 0x80008000))
        {
        {
          /* 16bits instruction.  */
          /* 16bits instruction.  */
          static gdb_byte big_breakpoint16[] = { 0x60, 0x02 };
          static gdb_byte big_breakpoint16[] = { 0x60, 0x02 };
          *pcptr &= ~0x1;
          *pcptr &= ~0x1;
          *lenptr = sizeof (big_breakpoint16);
          *lenptr = sizeof (big_breakpoint16);
          return big_breakpoint16;
          return big_breakpoint16;
        }
        }
      else
      else
        {
        {
          /* 32bits instruction.  */
          /* 32bits instruction.  */
          static gdb_byte big_breakpoint32[] = { 0x80, 0x00, 0x80, 0x06 };
          static gdb_byte big_breakpoint32[] = { 0x80, 0x00, 0x80, 0x06 };
          *pcptr &= ~0x3;
          *pcptr &= ~0x3;
          *lenptr = sizeof (big_breakpoint32);
          *lenptr = sizeof (big_breakpoint32);
          return big_breakpoint32;
          return big_breakpoint32;
        }
        }
    }
    }
  else
  else
    {
    {
      if (!(raw & 0x80008000))
      if (!(raw & 0x80008000))
        {
        {
          /* 16bits instruction.  */
          /* 16bits instruction.  */
          static gdb_byte little_breakpoint16[] = { 0x02, 0x60 };
          static gdb_byte little_breakpoint16[] = { 0x02, 0x60 };
          *pcptr &= ~0x1;
          *pcptr &= ~0x1;
          *lenptr = sizeof (little_breakpoint16);
          *lenptr = sizeof (little_breakpoint16);
          return little_breakpoint16;
          return little_breakpoint16;
        }
        }
      else
      else
        {
        {
          /* 32bits instruction.  */
          /* 32bits instruction.  */
          static gdb_byte little_breakpoint32[] = { 0x06, 0x80, 0x00, 0x80 };
          static gdb_byte little_breakpoint32[] = { 0x06, 0x80, 0x00, 0x80 };
          *pcptr &= ~0x3;
          *pcptr &= ~0x3;
          *lenptr = sizeof (little_breakpoint32);
          *lenptr = sizeof (little_breakpoint32);
          return little_breakpoint32;
          return little_breakpoint32;
        }
        }
    }
    }
}
}
 
 
static const gdb_byte *
static const gdb_byte *
score3_breakpoint_from_pc (struct gdbarch *gdbarch, CORE_ADDR *pcptr,
score3_breakpoint_from_pc (struct gdbarch *gdbarch, CORE_ADDR *pcptr,
                           int *lenptr)
                           int *lenptr)
{
{
  enum bfd_endian byte_order = gdbarch_byte_order (gdbarch);
  enum bfd_endian byte_order = gdbarch_byte_order (gdbarch);
  CORE_ADDR adjust_pc = *pcptr;
  CORE_ADDR adjust_pc = *pcptr;
  int len;
  int len;
  static gdb_byte score_break_insns[6][6] = {
  static gdb_byte score_break_insns[6][6] = {
    /* The following three instructions are big endian.  */
    /* The following three instructions are big endian.  */
    { 0x00, 0x20 },
    { 0x00, 0x20 },
    { 0x80, 0x00, 0x00, 0x06 },
    { 0x80, 0x00, 0x00, 0x06 },
    { 0x80, 0x00, 0x80, 0x00, 0x00, 0x00 },
    { 0x80, 0x00, 0x80, 0x00, 0x00, 0x00 },
    /* The following three instructions are little endian.  */
    /* The following three instructions are little endian.  */
    { 0x20, 0x00 },
    { 0x20, 0x00 },
    { 0x00, 0x80, 0x06, 0x00 },
    { 0x00, 0x80, 0x06, 0x00 },
    { 0x00, 0x80, 0x00, 0x80, 0x00, 0x00 }};
    { 0x00, 0x80, 0x00, 0x80, 0x00, 0x00 }};
 
 
  gdb_byte *p = NULL;
  gdb_byte *p = NULL;
  int index = 0;
  int index = 0;
 
 
  score3_adjust_pc_and_fetch_inst (&adjust_pc, &len, byte_order);
  score3_adjust_pc_and_fetch_inst (&adjust_pc, &len, byte_order);
 
 
  index = ((byte_order == BFD_ENDIAN_BIG) ? 0 : 3) + (len / 2 - 1);
  index = ((byte_order == BFD_ENDIAN_BIG) ? 0 : 3) + (len / 2 - 1);
  p = score_break_insns[index];
  p = score_break_insns[index];
 
 
  *pcptr = adjust_pc;
  *pcptr = adjust_pc;
  *lenptr = len;
  *lenptr = len;
 
 
  return p;
  return p;
}
}
 
 
static CORE_ADDR
static CORE_ADDR
score_adjust_breakpoint_address (struct gdbarch *gdbarch, CORE_ADDR bpaddr)
score_adjust_breakpoint_address (struct gdbarch *gdbarch, CORE_ADDR bpaddr)
{
{
  CORE_ADDR adjust_pc = bpaddr;
  CORE_ADDR adjust_pc = bpaddr;
 
 
  if (target_mach == bfd_mach_score3)
  if (target_mach == bfd_mach_score3)
    score3_adjust_pc_and_fetch_inst (&adjust_pc, NULL,
    score3_adjust_pc_and_fetch_inst (&adjust_pc, NULL,
                                     gdbarch_byte_order (gdbarch));
                                     gdbarch_byte_order (gdbarch));
  else
  else
    adjust_pc = align_down (adjust_pc, 2);
    adjust_pc = align_down (adjust_pc, 2);
 
 
  return adjust_pc;
  return adjust_pc;
}
}
 
 
static CORE_ADDR
static CORE_ADDR
score_frame_align (struct gdbarch *gdbarch, CORE_ADDR addr)
score_frame_align (struct gdbarch *gdbarch, CORE_ADDR addr)
{
{
  return align_down (addr, 16);
  return align_down (addr, 16);
}
}
 
 
static void
static void
score_xfer_register (struct regcache *regcache, int regnum, int length,
score_xfer_register (struct regcache *regcache, int regnum, int length,
                     enum bfd_endian endian, gdb_byte *readbuf,
                     enum bfd_endian endian, gdb_byte *readbuf,
                     const gdb_byte *writebuf, int buf_offset)
                     const gdb_byte *writebuf, int buf_offset)
{
{
  int reg_offset = 0;
  int reg_offset = 0;
  gdb_assert (regnum >= 0
  gdb_assert (regnum >= 0
              && regnum < ((target_mach == bfd_mach_score7) ? SCORE7_NUM_REGS : SCORE3_NUM_REGS));
              && regnum < ((target_mach == bfd_mach_score7) ? SCORE7_NUM_REGS : SCORE3_NUM_REGS));
 
 
  switch (endian)
  switch (endian)
    {
    {
    case BFD_ENDIAN_BIG:
    case BFD_ENDIAN_BIG:
      reg_offset = SCORE_REGSIZE - length;
      reg_offset = SCORE_REGSIZE - length;
      break;
      break;
    case BFD_ENDIAN_LITTLE:
    case BFD_ENDIAN_LITTLE:
      reg_offset = 0;
      reg_offset = 0;
      break;
      break;
    case BFD_ENDIAN_UNKNOWN:
    case BFD_ENDIAN_UNKNOWN:
      reg_offset = 0;
      reg_offset = 0;
      break;
      break;
    default:
    default:
      error ("Error: score_xfer_register in file:%s, line:%d!",
      error ("Error: score_xfer_register in file:%s, line:%d!",
             __FILE__, __LINE__);
             __FILE__, __LINE__);
    }
    }
 
 
  if (readbuf != NULL)
  if (readbuf != NULL)
    regcache_cooked_read_part (regcache, regnum, reg_offset, length,
    regcache_cooked_read_part (regcache, regnum, reg_offset, length,
                               readbuf + buf_offset);
                               readbuf + buf_offset);
  if (writebuf != NULL)
  if (writebuf != NULL)
    regcache_cooked_write_part (regcache, regnum, reg_offset, length,
    regcache_cooked_write_part (regcache, regnum, reg_offset, length,
                                writebuf + buf_offset);
                                writebuf + buf_offset);
}
}
 
 
static enum return_value_convention
static enum return_value_convention
score_return_value (struct gdbarch *gdbarch, struct type *func_type,
score_return_value (struct gdbarch *gdbarch, struct type *func_type,
                    struct type *type, struct regcache *regcache,
                    struct type *type, struct regcache *regcache,
                    gdb_byte * readbuf, const gdb_byte * writebuf)
                    gdb_byte * readbuf, const gdb_byte * writebuf)
{
{
  if (TYPE_CODE (type) == TYPE_CODE_STRUCT
  if (TYPE_CODE (type) == TYPE_CODE_STRUCT
      || TYPE_CODE (type) == TYPE_CODE_UNION
      || TYPE_CODE (type) == TYPE_CODE_UNION
      || TYPE_CODE (type) == TYPE_CODE_ARRAY)
      || TYPE_CODE (type) == TYPE_CODE_ARRAY)
    return RETURN_VALUE_STRUCT_CONVENTION;
    return RETURN_VALUE_STRUCT_CONVENTION;
  else
  else
    {
    {
      int offset;
      int offset;
      int regnum;
      int regnum;
      for (offset = 0, regnum = SCORE_A0_REGNUM;
      for (offset = 0, regnum = SCORE_A0_REGNUM;
           offset < TYPE_LENGTH (type);
           offset < TYPE_LENGTH (type);
           offset += SCORE_REGSIZE, regnum++)
           offset += SCORE_REGSIZE, regnum++)
        {
        {
          int xfer = SCORE_REGSIZE;
          int xfer = SCORE_REGSIZE;
          if (offset + xfer > TYPE_LENGTH (type))
          if (offset + xfer > TYPE_LENGTH (type))
            xfer = TYPE_LENGTH (type) - offset;
            xfer = TYPE_LENGTH (type) - offset;
          score_xfer_register (regcache, regnum, xfer,
          score_xfer_register (regcache, regnum, xfer,
                               gdbarch_byte_order(gdbarch),
                               gdbarch_byte_order(gdbarch),
                               readbuf, writebuf, offset);
                               readbuf, writebuf, offset);
        }
        }
      return RETURN_VALUE_REGISTER_CONVENTION;
      return RETURN_VALUE_REGISTER_CONVENTION;
    }
    }
}
}
 
 
static struct frame_id
static struct frame_id
score_dummy_id (struct gdbarch *gdbarch, struct frame_info *this_frame)
score_dummy_id (struct gdbarch *gdbarch, struct frame_info *this_frame)
{
{
  return frame_id_build (
  return frame_id_build (
           get_frame_register_unsigned (this_frame, SCORE_SP_REGNUM),
           get_frame_register_unsigned (this_frame, SCORE_SP_REGNUM),
           get_frame_pc (this_frame));
           get_frame_pc (this_frame));
}
}
 
 
static int
static int
score_type_needs_double_align (struct type *type)
score_type_needs_double_align (struct type *type)
{
{
  enum type_code typecode = TYPE_CODE (type);
  enum type_code typecode = TYPE_CODE (type);
 
 
  if ((typecode == TYPE_CODE_INT && TYPE_LENGTH (type) == 8)
  if ((typecode == TYPE_CODE_INT && TYPE_LENGTH (type) == 8)
      || (typecode == TYPE_CODE_FLT && TYPE_LENGTH (type) == 8))
      || (typecode == TYPE_CODE_FLT && TYPE_LENGTH (type) == 8))
    return 1;
    return 1;
  else if (typecode == TYPE_CODE_STRUCT || typecode == TYPE_CODE_UNION)
  else if (typecode == TYPE_CODE_STRUCT || typecode == TYPE_CODE_UNION)
    {
    {
      int i, n;
      int i, n;
 
 
      n = TYPE_NFIELDS (type);
      n = TYPE_NFIELDS (type);
      for (i = 0; i < n; i++)
      for (i = 0; i < n; i++)
        if (score_type_needs_double_align (TYPE_FIELD_TYPE (type, i)))
        if (score_type_needs_double_align (TYPE_FIELD_TYPE (type, i)))
          return 1;
          return 1;
      return 0;
      return 0;
    }
    }
  return 0;
  return 0;
}
}
 
 
static CORE_ADDR
static CORE_ADDR
score_push_dummy_call (struct gdbarch *gdbarch, struct value *function,
score_push_dummy_call (struct gdbarch *gdbarch, struct value *function,
                       struct regcache *regcache, CORE_ADDR bp_addr,
                       struct regcache *regcache, CORE_ADDR bp_addr,
                       int nargs, struct value **args, CORE_ADDR sp,
                       int nargs, struct value **args, CORE_ADDR sp,
                       int struct_return, CORE_ADDR struct_addr)
                       int struct_return, CORE_ADDR struct_addr)
{
{
  enum bfd_endian byte_order = gdbarch_byte_order (gdbarch);
  enum bfd_endian byte_order = gdbarch_byte_order (gdbarch);
  int argnum;
  int argnum;
  int argreg;
  int argreg;
  int arglen = 0;
  int arglen = 0;
  CORE_ADDR stack_offset = 0;
  CORE_ADDR stack_offset = 0;
  CORE_ADDR addr = 0;
  CORE_ADDR addr = 0;
 
 
  /* Step 1, Save RA.  */
  /* Step 1, Save RA.  */
  regcache_cooked_write_unsigned (regcache, SCORE_RA_REGNUM, bp_addr);
  regcache_cooked_write_unsigned (regcache, SCORE_RA_REGNUM, bp_addr);
 
 
  /* Step 2, Make space on the stack for the args.  */
  /* Step 2, Make space on the stack for the args.  */
  struct_addr = align_down (struct_addr, 16);
  struct_addr = align_down (struct_addr, 16);
  sp = align_down (sp, 16);
  sp = align_down (sp, 16);
  for (argnum = 0; argnum < nargs; argnum++)
  for (argnum = 0; argnum < nargs; argnum++)
    arglen += align_up (TYPE_LENGTH (value_type (args[argnum])),
    arglen += align_up (TYPE_LENGTH (value_type (args[argnum])),
                        SCORE_REGSIZE);
                        SCORE_REGSIZE);
  sp -= align_up (arglen, 16);
  sp -= align_up (arglen, 16);
 
 
  argreg = SCORE_BEGIN_ARG_REGNUM;
  argreg = SCORE_BEGIN_ARG_REGNUM;
 
 
  /* Step 3, Check if struct return then save the struct address to
  /* Step 3, Check if struct return then save the struct address to
     r4 and increase the stack_offset by 4.  */
     r4 and increase the stack_offset by 4.  */
  if (struct_return)
  if (struct_return)
    {
    {
      regcache_cooked_write_unsigned (regcache, argreg++, struct_addr);
      regcache_cooked_write_unsigned (regcache, argreg++, struct_addr);
      stack_offset += SCORE_REGSIZE;
      stack_offset += SCORE_REGSIZE;
    }
    }
 
 
  /* Step 4, Load arguments:
  /* Step 4, Load arguments:
     If arg length is too long (> 4 bytes), then split the arg and
     If arg length is too long (> 4 bytes), then split the arg and
     save every parts.  */
     save every parts.  */
  for (argnum = 0; argnum < nargs; argnum++)
  for (argnum = 0; argnum < nargs; argnum++)
    {
    {
      struct value *arg = args[argnum];
      struct value *arg = args[argnum];
      struct type *arg_type = check_typedef (value_type (arg));
      struct type *arg_type = check_typedef (value_type (arg));
      enum type_code typecode = TYPE_CODE (arg_type);
      enum type_code typecode = TYPE_CODE (arg_type);
      const gdb_byte *val = value_contents (arg);
      const gdb_byte *val = value_contents (arg);
      int downward_offset = 0;
      int downward_offset = 0;
      int odd_sized_struct_p;
      int odd_sized_struct_p;
      int arg_last_part_p = 0;
      int arg_last_part_p = 0;
 
 
      arglen = TYPE_LENGTH (arg_type);
      arglen = TYPE_LENGTH (arg_type);
      odd_sized_struct_p = (arglen > SCORE_REGSIZE
      odd_sized_struct_p = (arglen > SCORE_REGSIZE
                            && arglen % SCORE_REGSIZE != 0);
                            && arglen % SCORE_REGSIZE != 0);
 
 
      /* If a arg should be aligned to 8 bytes (long long or double),
      /* If a arg should be aligned to 8 bytes (long long or double),
         the value should be put to even register numbers.  */
         the value should be put to even register numbers.  */
      if (score_type_needs_double_align (arg_type))
      if (score_type_needs_double_align (arg_type))
        {
        {
          if (argreg & 1)
          if (argreg & 1)
            argreg++;
            argreg++;
        }
        }
 
 
      /* If sizeof a block < SCORE_REGSIZE, then Score GCC will chose
      /* If sizeof a block < SCORE_REGSIZE, then Score GCC will chose
         the default "downward"/"upward" method:
         the default "downward"/"upward" method:
 
 
         Example:
         Example:
 
 
         struct struc
         struct struc
         {
         {
           char a; char b; char c;
           char a; char b; char c;
         } s = {'a', 'b', 'c'};
         } s = {'a', 'b', 'c'};
 
 
         Big endian:    s = {X, 'a', 'b', 'c'}
         Big endian:    s = {X, 'a', 'b', 'c'}
         Little endian: s = {'a', 'b', 'c', X}
         Little endian: s = {'a', 'b', 'c', X}
 
 
         Where X is a hole.  */
         Where X is a hole.  */
 
 
      if (gdbarch_byte_order(gdbarch) == BFD_ENDIAN_BIG
      if (gdbarch_byte_order(gdbarch) == BFD_ENDIAN_BIG
          && (typecode == TYPE_CODE_STRUCT
          && (typecode == TYPE_CODE_STRUCT
              || typecode == TYPE_CODE_UNION)
              || typecode == TYPE_CODE_UNION)
          && argreg > SCORE_LAST_ARG_REGNUM
          && argreg > SCORE_LAST_ARG_REGNUM
          && arglen < SCORE_REGSIZE)
          && arglen < SCORE_REGSIZE)
        downward_offset += (SCORE_REGSIZE - arglen);
        downward_offset += (SCORE_REGSIZE - arglen);
 
 
      while (arglen > 0)
      while (arglen > 0)
        {
        {
          int partial_len = arglen < SCORE_REGSIZE ? arglen : SCORE_REGSIZE;
          int partial_len = arglen < SCORE_REGSIZE ? arglen : SCORE_REGSIZE;
          ULONGEST regval = extract_unsigned_integer (val, partial_len,
          ULONGEST regval = extract_unsigned_integer (val, partial_len,
                                                      byte_order);
                                                      byte_order);
 
 
          /* The last part of a arg should shift left when
          /* The last part of a arg should shift left when
             gdbarch_byte_order is BFD_ENDIAN_BIG.  */
             gdbarch_byte_order is BFD_ENDIAN_BIG.  */
          if (byte_order == BFD_ENDIAN_BIG
          if (byte_order == BFD_ENDIAN_BIG
              && arg_last_part_p == 1
              && arg_last_part_p == 1
              && (typecode == TYPE_CODE_STRUCT
              && (typecode == TYPE_CODE_STRUCT
                  || typecode == TYPE_CODE_UNION))
                  || typecode == TYPE_CODE_UNION))
            regval <<= ((SCORE_REGSIZE - partial_len) * TARGET_CHAR_BIT);
            regval <<= ((SCORE_REGSIZE - partial_len) * TARGET_CHAR_BIT);
 
 
          /* Always increase the stack_offset and save args to stack.  */
          /* Always increase the stack_offset and save args to stack.  */
          addr = sp + stack_offset + downward_offset;
          addr = sp + stack_offset + downward_offset;
          write_memory (addr, val, partial_len);
          write_memory (addr, val, partial_len);
 
 
          if (argreg <= SCORE_LAST_ARG_REGNUM)
          if (argreg <= SCORE_LAST_ARG_REGNUM)
            {
            {
              regcache_cooked_write_unsigned (regcache, argreg++, regval);
              regcache_cooked_write_unsigned (regcache, argreg++, regval);
              if (arglen > SCORE_REGSIZE && arglen < SCORE_REGSIZE * 2)
              if (arglen > SCORE_REGSIZE && arglen < SCORE_REGSIZE * 2)
                arg_last_part_p = 1;
                arg_last_part_p = 1;
            }
            }
 
 
          val += partial_len;
          val += partial_len;
          arglen -= partial_len;
          arglen -= partial_len;
          stack_offset += align_up (partial_len, SCORE_REGSIZE);
          stack_offset += align_up (partial_len, SCORE_REGSIZE);
        }
        }
    }
    }
 
 
  /* Step 5, Save SP.  */
  /* Step 5, Save SP.  */
  regcache_cooked_write_unsigned (regcache, SCORE_SP_REGNUM, sp);
  regcache_cooked_write_unsigned (regcache, SCORE_SP_REGNUM, sp);
 
 
  return sp;
  return sp;
}
}
 
 
static CORE_ADDR
static CORE_ADDR
score7_skip_prologue (struct gdbarch *gdbarch, CORE_ADDR pc)
score7_skip_prologue (struct gdbarch *gdbarch, CORE_ADDR pc)
{
{
  CORE_ADDR cpc = pc;
  CORE_ADDR cpc = pc;
  int iscan = 32, stack_sub = 0;
  int iscan = 32, stack_sub = 0;
  while (iscan-- > 0)
  while (iscan-- > 0)
    {
    {
      inst_t *inst = score7_fetch_inst (gdbarch, cpc, NULL);
      inst_t *inst = score7_fetch_inst (gdbarch, cpc, NULL);
      if (!inst)
      if (!inst)
        break;
        break;
      if ((inst->len == 4) && !stack_sub
      if ((inst->len == 4) && !stack_sub
          && (G_FLD (inst->v, 29, 25) == 0x1
          && (G_FLD (inst->v, 29, 25) == 0x1
              && G_FLD (inst->v, 24, 20) == 0x0))
              && G_FLD (inst->v, 24, 20) == 0x0))
        {
        {
          /* addi r0, offset */
          /* addi r0, offset */
          stack_sub = cpc + SCORE_INSTLEN;
          stack_sub = cpc + SCORE_INSTLEN;
          pc = cpc + SCORE_INSTLEN;
          pc = cpc + SCORE_INSTLEN;
        }
        }
      else if ((inst->len == 4)
      else if ((inst->len == 4)
               && (G_FLD (inst->v, 29, 25) == 0x0)
               && (G_FLD (inst->v, 29, 25) == 0x0)
               && (G_FLD (inst->v, 24, 20) == 0x2)
               && (G_FLD (inst->v, 24, 20) == 0x2)
               && (G_FLD (inst->v, 19, 15) == 0x0)
               && (G_FLD (inst->v, 19, 15) == 0x0)
               && (G_FLD (inst->v, 14, 10) == 0xF)
               && (G_FLD (inst->v, 14, 10) == 0xF)
               && (G_FLD (inst->v, 9, 0) == 0x56))
               && (G_FLD (inst->v, 9, 0) == 0x56))
        {
        {
          /* mv r2, r0  */
          /* mv r2, r0  */
          pc = cpc + SCORE_INSTLEN;
          pc = cpc + SCORE_INSTLEN;
          break;
          break;
        }
        }
      else if ((inst->len == 2)
      else if ((inst->len == 2)
               && (G_FLD (inst->v, 14, 12) == 0x0)
               && (G_FLD (inst->v, 14, 12) == 0x0)
               && (G_FLD (inst->v, 11, 8) == 0x2)
               && (G_FLD (inst->v, 11, 8) == 0x2)
               && (G_FLD (inst->v, 7, 4) == 0x0)
               && (G_FLD (inst->v, 7, 4) == 0x0)
               && (G_FLD (inst->v, 3, 0) == 0x3))
               && (G_FLD (inst->v, 3, 0) == 0x3))
        {
        {
          /* mv! r2, r0 */
          /* mv! r2, r0 */
          pc = cpc + SCORE16_INSTLEN;
          pc = cpc + SCORE16_INSTLEN;
          break;
          break;
        }
        }
      else if ((inst->len == 2)
      else if ((inst->len == 2)
               && ((G_FLD (inst->v, 14, 12) == 3)    /* j15 form */
               && ((G_FLD (inst->v, 14, 12) == 3)    /* j15 form */
                   || (G_FLD (inst->v, 14, 12) == 4) /* b15 form */
                   || (G_FLD (inst->v, 14, 12) == 4) /* b15 form */
                   || (G_FLD (inst->v, 14, 12) == 0x0
                   || (G_FLD (inst->v, 14, 12) == 0x0
                       && G_FLD (inst->v, 3, 0) == 0x4))) /* br! */
                       && G_FLD (inst->v, 3, 0) == 0x4))) /* br! */
        break;
        break;
      else if ((inst->len == 4)
      else if ((inst->len == 4)
               && ((G_FLD (inst->v, 29, 25) == 2)    /* j32 form */
               && ((G_FLD (inst->v, 29, 25) == 2)    /* j32 form */
                   || (G_FLD (inst->v, 29, 25) == 4) /* b32 form */
                   || (G_FLD (inst->v, 29, 25) == 4) /* b32 form */
                   || (G_FLD (inst->v, 29, 25) == 0x0
                   || (G_FLD (inst->v, 29, 25) == 0x0
                       && G_FLD (inst->v, 6, 1) == 0x4)))  /* br */
                       && G_FLD (inst->v, 6, 1) == 0x4)))  /* br */
        break;
        break;
 
 
      cpc += (inst->len == 2) ? SCORE16_INSTLEN : SCORE_INSTLEN;
      cpc += (inst->len == 2) ? SCORE16_INSTLEN : SCORE_INSTLEN;
    }
    }
  return pc;
  return pc;
}
}
 
 
static CORE_ADDR
static CORE_ADDR
score3_skip_prologue (struct gdbarch *gdbarch, CORE_ADDR pc)
score3_skip_prologue (struct gdbarch *gdbarch, CORE_ADDR pc)
{
{
  CORE_ADDR cpc = pc;
  CORE_ADDR cpc = pc;
  int iscan = 32, stack_sub = 0;
  int iscan = 32, stack_sub = 0;
  while (iscan-- > 0)
  while (iscan-- > 0)
    {
    {
      inst_t *inst
      inst_t *inst
        = score3_adjust_pc_and_fetch_inst (&cpc, NULL, gdbarch_byte_order (gdbarch));
        = score3_adjust_pc_and_fetch_inst (&cpc, NULL, gdbarch_byte_order (gdbarch));
 
 
      if (!inst)
      if (!inst)
        break;
        break;
      if (inst->len == 4 && !stack_sub
      if (inst->len == 4 && !stack_sub
          && (G_FLD (inst->v, 29, 25) == 0x1)
          && (G_FLD (inst->v, 29, 25) == 0x1)
          && (G_FLD (inst->v, 19, 17) == 0x0)
          && (G_FLD (inst->v, 19, 17) == 0x0)
          && (G_FLD (inst->v, 24, 20) == 0x0))
          && (G_FLD (inst->v, 24, 20) == 0x0))
        {
        {
          /* addi r0, offset */
          /* addi r0, offset */
          stack_sub = cpc + inst->len;
          stack_sub = cpc + inst->len;
          pc = cpc + inst->len;
          pc = cpc + inst->len;
        }
        }
      else if (inst->len == 4
      else if (inst->len == 4
               && (G_FLD (inst->v, 29, 25) == 0x0)
               && (G_FLD (inst->v, 29, 25) == 0x0)
               && (G_FLD (inst->v, 24, 20) == 0x2)
               && (G_FLD (inst->v, 24, 20) == 0x2)
               && (G_FLD (inst->v, 19, 15) == 0x0)
               && (G_FLD (inst->v, 19, 15) == 0x0)
               && (G_FLD (inst->v, 14, 10) == 0xF)
               && (G_FLD (inst->v, 14, 10) == 0xF)
               && (G_FLD (inst->v, 9, 0) == 0x56))
               && (G_FLD (inst->v, 9, 0) == 0x56))
        {
        {
          /* mv r2, r0  */
          /* mv r2, r0  */
          pc = cpc + inst->len;
          pc = cpc + inst->len;
          break;
          break;
        }
        }
      else if ((inst->len == 2)
      else if ((inst->len == 2)
               && (G_FLD (inst->v, 14, 10) == 0x10)
               && (G_FLD (inst->v, 14, 10) == 0x10)
               && (G_FLD (inst->v, 9, 5) == 0x2)
               && (G_FLD (inst->v, 9, 5) == 0x2)
               && (G_FLD (inst->v, 4, 0) == 0x0))
               && (G_FLD (inst->v, 4, 0) == 0x0))
        {
        {
          /* mv! r2, r0 */
          /* mv! r2, r0 */
          pc = cpc + inst->len;
          pc = cpc + inst->len;
          break;
          break;
        }
        }
      else if (inst->len == 2
      else if (inst->len == 2
               && ((G_FLD (inst->v, 14, 12) == 3) /* b15 form */
               && ((G_FLD (inst->v, 14, 12) == 3) /* b15 form */
                   || (G_FLD (inst->v, 14, 12) == 0x0
                   || (G_FLD (inst->v, 14, 12) == 0x0
                       && G_FLD (inst->v, 11, 5) == 0x4))) /* br! */
                       && G_FLD (inst->v, 11, 5) == 0x4))) /* br! */
        break;
        break;
      else if (inst->len == 4
      else if (inst->len == 4
               && ((G_FLD (inst->v, 29, 25) == 2)    /* j32 form */
               && ((G_FLD (inst->v, 29, 25) == 2)    /* j32 form */
                   || (G_FLD (inst->v, 29, 25) == 4))) /* b32 form */
                   || (G_FLD (inst->v, 29, 25) == 4))) /* b32 form */
        break;
        break;
 
 
      cpc += inst->len;
      cpc += inst->len;
    }
    }
  return pc;
  return pc;
}
}
 
 
static int
static int
score7_in_function_epilogue_p (struct gdbarch *gdbarch, CORE_ADDR cur_pc)
score7_in_function_epilogue_p (struct gdbarch *gdbarch, CORE_ADDR cur_pc)
{
{
  inst_t *inst = score7_fetch_inst (gdbarch, cur_pc, NULL);
  inst_t *inst = score7_fetch_inst (gdbarch, cur_pc, NULL);
 
 
  if (inst->v == 0x23)
  if (inst->v == 0x23)
    return 1;   /* mv! r0, r2 */
    return 1;   /* mv! r0, r2 */
  else if (G_FLD (inst->v, 14, 12) == 0x2
  else if (G_FLD (inst->v, 14, 12) == 0x2
           && G_FLD (inst->v, 3, 0) == 0xa)
           && G_FLD (inst->v, 3, 0) == 0xa)
    return 1;   /* pop! */
    return 1;   /* pop! */
  else if (G_FLD (inst->v, 14, 12) == 0x0
  else if (G_FLD (inst->v, 14, 12) == 0x0
           && G_FLD (inst->v, 7, 0) == 0x34)
           && G_FLD (inst->v, 7, 0) == 0x34)
    return 1;   /* br! r3 */
    return 1;   /* br! r3 */
  else if (G_FLD (inst->v, 29, 15) == 0x2
  else if (G_FLD (inst->v, 29, 15) == 0x2
           && G_FLD (inst->v, 6, 1) == 0x2b)
           && G_FLD (inst->v, 6, 1) == 0x2b)
    return 1;   /* mv r0, r2 */
    return 1;   /* mv r0, r2 */
  else if (G_FLD (inst->v, 29, 25) == 0x0
  else if (G_FLD (inst->v, 29, 25) == 0x0
           && G_FLD (inst->v, 6, 1) == 0x4
           && G_FLD (inst->v, 6, 1) == 0x4
           && G_FLD (inst->v, 19, 15) == 0x3)
           && G_FLD (inst->v, 19, 15) == 0x3)
    return 1;   /* br r3 */
    return 1;   /* br r3 */
  else
  else
    return 0;
    return 0;
}
}
 
 
static int
static int
score3_in_function_epilogue_p (struct gdbarch *gdbarch, CORE_ADDR cur_pc)
score3_in_function_epilogue_p (struct gdbarch *gdbarch, CORE_ADDR cur_pc)
{
{
  CORE_ADDR pc = cur_pc;
  CORE_ADDR pc = cur_pc;
  inst_t *inst
  inst_t *inst
    = score3_adjust_pc_and_fetch_inst (&pc, NULL, gdbarch_byte_order (gdbarch));
    = score3_adjust_pc_and_fetch_inst (&pc, NULL, gdbarch_byte_order (gdbarch));
 
 
  if (inst->len == 2
  if (inst->len == 2
      && (G_FLD (inst->v, 14, 10) == 0x10)
      && (G_FLD (inst->v, 14, 10) == 0x10)
      && (G_FLD (inst->v, 9, 5) == 0x0)
      && (G_FLD (inst->v, 9, 5) == 0x0)
      && (G_FLD (inst->v, 4, 0) == 0x2))
      && (G_FLD (inst->v, 4, 0) == 0x2))
    return 1;   /* mv! r0, r2 */
    return 1;   /* mv! r0, r2 */
  else if (inst->len == 4
  else if (inst->len == 4
           && (G_FLD (inst->v, 29, 25) == 0x0)
           && (G_FLD (inst->v, 29, 25) == 0x0)
           && (G_FLD (inst->v, 24, 20) == 0x2)
           && (G_FLD (inst->v, 24, 20) == 0x2)
           && (G_FLD (inst->v, 19, 15) == 0x0)
           && (G_FLD (inst->v, 19, 15) == 0x0)
           && (G_FLD (inst->v, 14, 10) == 0xF)
           && (G_FLD (inst->v, 14, 10) == 0xF)
           && (G_FLD (inst->v, 9, 0) == 0x56))
           && (G_FLD (inst->v, 9, 0) == 0x56))
    return 1;   /* mv r0, r2 */
    return 1;   /* mv r0, r2 */
  else if (inst->len == 2
  else if (inst->len == 2
           && (G_FLD (inst->v, 14, 12) == 0x0)
           && (G_FLD (inst->v, 14, 12) == 0x0)
           && (G_FLD (inst->v, 11, 5) == 0x2))
           && (G_FLD (inst->v, 11, 5) == 0x2))
    return 1;   /* pop! */
    return 1;   /* pop! */
  else if (inst->len == 2
  else if (inst->len == 2
           && (G_FLD (inst->v, 14, 12) == 0x0)
           && (G_FLD (inst->v, 14, 12) == 0x0)
           && (G_FLD (inst->v, 11, 7) == 0x0)
           && (G_FLD (inst->v, 11, 7) == 0x0)
           && (G_FLD (inst->v, 6, 5) == 0x2))
           && (G_FLD (inst->v, 6, 5) == 0x2))
    return 1;   /* rpop! */
    return 1;   /* rpop! */
  else if (inst->len == 2
  else if (inst->len == 2
           && (G_FLD (inst->v, 14, 12) == 0x0)
           && (G_FLD (inst->v, 14, 12) == 0x0)
           && (G_FLD (inst->v, 11, 5) == 0x4)
           && (G_FLD (inst->v, 11, 5) == 0x4)
           && (G_FLD (inst->v, 4, 0) == 0x3))
           && (G_FLD (inst->v, 4, 0) == 0x3))
    return 1;   /* br! r3 */
    return 1;   /* br! r3 */
  else if (inst->len == 4
  else if (inst->len == 4
           && (G_FLD (inst->v, 29, 25) == 0x0)
           && (G_FLD (inst->v, 29, 25) == 0x0)
           && (G_FLD (inst->v, 24, 20) == 0x0)
           && (G_FLD (inst->v, 24, 20) == 0x0)
           && (G_FLD (inst->v, 19, 15) == 0x3)
           && (G_FLD (inst->v, 19, 15) == 0x3)
           && (G_FLD (inst->v, 14, 10) == 0xF)
           && (G_FLD (inst->v, 14, 10) == 0xF)
           && (G_FLD (inst->v, 9, 0) == 0x8))
           && (G_FLD (inst->v, 9, 0) == 0x8))
    return 1;   /* br r3 */
    return 1;   /* br r3 */
  else
  else
    return 0;
    return 0;
}
}
 
 
static char *
static char *
score7_malloc_and_get_memblock (CORE_ADDR addr, CORE_ADDR size)
score7_malloc_and_get_memblock (CORE_ADDR addr, CORE_ADDR size)
{
{
  int ret;
  int ret;
  char *memblock = NULL;
  char *memblock = NULL;
 
 
  if (size < 0)
  if (size < 0)
    {
    {
      error ("Error: malloc size < 0 in file:%s, line:%d!",
      error ("Error: malloc size < 0 in file:%s, line:%d!",
             __FILE__, __LINE__);
             __FILE__, __LINE__);
      return NULL;
      return NULL;
    }
    }
  else if (size == 0)
  else if (size == 0)
    return NULL;
    return NULL;
 
 
  memblock = (char *) xmalloc (size);
  memblock = (char *) xmalloc (size);
  memset (memblock, 0, size);
  memset (memblock, 0, size);
  ret = target_read_memory (addr & ~0x3, memblock, size);
  ret = target_read_memory (addr & ~0x3, memblock, size);
  if (ret)
  if (ret)
    {
    {
      error ("Error: target_read_memory in file:%s, line:%d!",
      error ("Error: target_read_memory in file:%s, line:%d!",
             __FILE__, __LINE__);
             __FILE__, __LINE__);
      return NULL;
      return NULL;
    }
    }
  return memblock;
  return memblock;
}
}
 
 
static void
static void
score7_free_memblock (char *memblock)
score7_free_memblock (char *memblock)
{
{
  xfree (memblock);
  xfree (memblock);
}
}
 
 
static void
static void
score7_adjust_memblock_ptr (char **memblock, CORE_ADDR prev_pc,
score7_adjust_memblock_ptr (char **memblock, CORE_ADDR prev_pc,
                           CORE_ADDR cur_pc)
                           CORE_ADDR cur_pc)
{
{
  if (prev_pc == -1)
  if (prev_pc == -1)
    {
    {
      /* First time call this function, do nothing.  */
      /* First time call this function, do nothing.  */
    }
    }
  else if (cur_pc - prev_pc == 2 && (cur_pc & 0x3) == 0)
  else if (cur_pc - prev_pc == 2 && (cur_pc & 0x3) == 0)
    {
    {
      /* First 16-bit instruction, then 32-bit instruction.  */
      /* First 16-bit instruction, then 32-bit instruction.  */
      *memblock += SCORE_INSTLEN;
      *memblock += SCORE_INSTLEN;
    }
    }
  else if (cur_pc - prev_pc == 4)
  else if (cur_pc - prev_pc == 4)
    {
    {
      /* Is 32-bit instruction, increase MEMBLOCK by 4.  */
      /* Is 32-bit instruction, increase MEMBLOCK by 4.  */
      *memblock += SCORE_INSTLEN;
      *memblock += SCORE_INSTLEN;
    }
    }
}
}
 
 
static void
static void
score7_analyze_prologue (CORE_ADDR startaddr, CORE_ADDR pc,
score7_analyze_prologue (CORE_ADDR startaddr, CORE_ADDR pc,
                        struct frame_info *this_frame,
                        struct frame_info *this_frame,
                        struct score_frame_cache *this_cache)
                        struct score_frame_cache *this_cache)
{
{
  struct gdbarch *gdbarch = get_frame_arch (this_frame);
  struct gdbarch *gdbarch = get_frame_arch (this_frame);
  CORE_ADDR sp;
  CORE_ADDR sp;
  CORE_ADDR fp;
  CORE_ADDR fp;
  CORE_ADDR cur_pc = startaddr;
  CORE_ADDR cur_pc = startaddr;
 
 
  int sp_offset = 0;
  int sp_offset = 0;
  int ra_offset = 0;
  int ra_offset = 0;
  int fp_offset = 0;
  int fp_offset = 0;
  int ra_offset_p = 0;
  int ra_offset_p = 0;
  int fp_offset_p = 0;
  int fp_offset_p = 0;
  int inst_len = 0;
  int inst_len = 0;
 
 
  char *memblock = NULL;
  char *memblock = NULL;
  char *memblock_ptr = NULL;
  char *memblock_ptr = NULL;
  CORE_ADDR prev_pc = -1;
  CORE_ADDR prev_pc = -1;
 
 
  /* Allocate MEMBLOCK if PC - STARTADDR > 0.  */
  /* Allocate MEMBLOCK if PC - STARTADDR > 0.  */
  memblock_ptr = memblock =
  memblock_ptr = memblock =
    score7_malloc_and_get_memblock (startaddr, pc - startaddr);
    score7_malloc_and_get_memblock (startaddr, pc - startaddr);
 
 
  sp = get_frame_register_unsigned (this_frame, SCORE_SP_REGNUM);
  sp = get_frame_register_unsigned (this_frame, SCORE_SP_REGNUM);
  fp = get_frame_register_unsigned (this_frame, SCORE_FP_REGNUM);
  fp = get_frame_register_unsigned (this_frame, SCORE_FP_REGNUM);
 
 
  for (; cur_pc < pc; prev_pc = cur_pc, cur_pc += inst_len)
  for (; cur_pc < pc; prev_pc = cur_pc, cur_pc += inst_len)
    {
    {
      inst_t *inst = NULL;
      inst_t *inst = NULL;
      if (memblock != NULL)
      if (memblock != NULL)
        {
        {
          /* Reading memory block from target succefully and got all
          /* Reading memory block from target succefully and got all
             the instructions(from STARTADDR to PC) needed.  */
             the instructions(from STARTADDR to PC) needed.  */
          score7_adjust_memblock_ptr (&memblock, prev_pc, cur_pc);
          score7_adjust_memblock_ptr (&memblock, prev_pc, cur_pc);
          inst = score7_fetch_inst (gdbarch, cur_pc, memblock);
          inst = score7_fetch_inst (gdbarch, cur_pc, memblock);
        }
        }
      else
      else
        {
        {
          /* Otherwise, we fetch 4 bytes from target, and GDB also
          /* Otherwise, we fetch 4 bytes from target, and GDB also
             work correctly.  */
             work correctly.  */
          inst = score7_fetch_inst (gdbarch, cur_pc, NULL);
          inst = score7_fetch_inst (gdbarch, cur_pc, NULL);
        }
        }
 
 
      /* FIXME: make a full-power prologue analyzer */
      /* FIXME: make a full-power prologue analyzer */
      if (inst->len == 2)
      if (inst->len == 2)
        {
        {
          inst_len = SCORE16_INSTLEN;
          inst_len = SCORE16_INSTLEN;
 
 
          if (G_FLD (inst->v, 14, 12) == 0x2
          if (G_FLD (inst->v, 14, 12) == 0x2
              && G_FLD (inst->v, 3, 0) == 0xe)
              && G_FLD (inst->v, 3, 0) == 0xe)
            {
            {
              /* push! */
              /* push! */
              sp_offset += 4;
              sp_offset += 4;
 
 
              if (G_FLD (inst->v, 11, 7) == 0x6
              if (G_FLD (inst->v, 11, 7) == 0x6
                  && ra_offset_p == 0)
                  && ra_offset_p == 0)
                {
                {
                  /* push! r3, [r0] */
                  /* push! r3, [r0] */
                  ra_offset = sp_offset;
                  ra_offset = sp_offset;
                  ra_offset_p = 1;
                  ra_offset_p = 1;
                }
                }
              else if (G_FLD (inst->v, 11, 7) == 0x4
              else if (G_FLD (inst->v, 11, 7) == 0x4
                       && fp_offset_p == 0)
                       && fp_offset_p == 0)
                {
                {
                  /* push! r2, [r0] */
                  /* push! r2, [r0] */
                  fp_offset = sp_offset;
                  fp_offset = sp_offset;
                  fp_offset_p = 1;
                  fp_offset_p = 1;
                }
                }
            }
            }
          else if (G_FLD (inst->v, 14, 12) == 0x2
          else if (G_FLD (inst->v, 14, 12) == 0x2
                   && G_FLD (inst->v, 3, 0) == 0xa)
                   && G_FLD (inst->v, 3, 0) == 0xa)
            {
            {
              /* pop! */
              /* pop! */
              sp_offset -= 4;
              sp_offset -= 4;
            }
            }
          else if (G_FLD (inst->v, 14, 7) == 0xc1
          else if (G_FLD (inst->v, 14, 7) == 0xc1
                   && G_FLD (inst->v, 2, 0) == 0x0)
                   && G_FLD (inst->v, 2, 0) == 0x0)
            {
            {
              /* subei! r0, n */
              /* subei! r0, n */
              sp_offset += (int) pow (2, G_FLD (inst->v, 6, 3));
              sp_offset += (int) pow (2, G_FLD (inst->v, 6, 3));
            }
            }
          else if (G_FLD (inst->v, 14, 7) == 0xc0
          else if (G_FLD (inst->v, 14, 7) == 0xc0
                   && G_FLD (inst->v, 2, 0) == 0x0)
                   && G_FLD (inst->v, 2, 0) == 0x0)
            {
            {
              /* addei! r0, n */
              /* addei! r0, n */
              sp_offset -= (int) pow (2, G_FLD (inst->v, 6, 3));
              sp_offset -= (int) pow (2, G_FLD (inst->v, 6, 3));
            }
            }
        }
        }
      else
      else
        {
        {
          inst_len = SCORE_INSTLEN;
          inst_len = SCORE_INSTLEN;
 
 
          if (G_FLD(inst->v, 29, 25) == 0x3
          if (G_FLD(inst->v, 29, 25) == 0x3
              && G_FLD(inst->v, 2, 0) == 0x4
              && G_FLD(inst->v, 2, 0) == 0x4
              && G_FLD(inst->v, 19, 15) == 0)
              && G_FLD(inst->v, 19, 15) == 0)
            {
            {
                /* sw rD, [r0, offset]+ */
                /* sw rD, [r0, offset]+ */
                sp_offset += SCORE_INSTLEN;
                sp_offset += SCORE_INSTLEN;
 
 
                if (G_FLD(inst->v, 24, 20) == 0x3)
                if (G_FLD(inst->v, 24, 20) == 0x3)
                  {
                  {
                      /* rD = r3 */
                      /* rD = r3 */
                      if (ra_offset_p == 0)
                      if (ra_offset_p == 0)
                        {
                        {
                            ra_offset = sp_offset;
                            ra_offset = sp_offset;
                            ra_offset_p = 1;
                            ra_offset_p = 1;
                        }
                        }
                  }
                  }
                else if (G_FLD(inst->v, 24, 20) == 0x2)
                else if (G_FLD(inst->v, 24, 20) == 0x2)
                  {
                  {
                      /* rD = r2 */
                      /* rD = r2 */
                      if (fp_offset_p == 0)
                      if (fp_offset_p == 0)
                        {
                        {
                            fp_offset = sp_offset;
                            fp_offset = sp_offset;
                            fp_offset_p = 1;
                            fp_offset_p = 1;
                        }
                        }
                  }
                  }
            }
            }
          else if (G_FLD(inst->v, 29, 25) == 0x14
          else if (G_FLD(inst->v, 29, 25) == 0x14
                   && G_FLD(inst->v, 19,15) == 0)
                   && G_FLD(inst->v, 19,15) == 0)
            {
            {
                /* sw rD, [r0, offset] */
                /* sw rD, [r0, offset] */
                if (G_FLD(inst->v, 24, 20) == 0x3)
                if (G_FLD(inst->v, 24, 20) == 0x3)
                  {
                  {
                      /* rD = r3 */
                      /* rD = r3 */
                      ra_offset = sp_offset - G_FLD(inst->v, 14, 0);
                      ra_offset = sp_offset - G_FLD(inst->v, 14, 0);
                      ra_offset_p = 1;
                      ra_offset_p = 1;
                  }
                  }
                else if (G_FLD(inst->v, 24, 20) == 0x2)
                else if (G_FLD(inst->v, 24, 20) == 0x2)
                  {
                  {
                      /* rD = r2 */
                      /* rD = r2 */
                      fp_offset = sp_offset - G_FLD(inst->v, 14, 0);
                      fp_offset = sp_offset - G_FLD(inst->v, 14, 0);
                      fp_offset_p = 1;
                      fp_offset_p = 1;
                  }
                  }
            }
            }
          else if (G_FLD (inst->v, 29, 15) == 0x1c60
          else if (G_FLD (inst->v, 29, 15) == 0x1c60
                   && G_FLD (inst->v, 2, 0) == 0x0)
                   && G_FLD (inst->v, 2, 0) == 0x0)
            {
            {
              /* lw r3, [r0]+, 4 */
              /* lw r3, [r0]+, 4 */
              sp_offset -= SCORE_INSTLEN;
              sp_offset -= SCORE_INSTLEN;
              ra_offset_p = 1;
              ra_offset_p = 1;
            }
            }
          else if (G_FLD (inst->v, 29, 15) == 0x1c40
          else if (G_FLD (inst->v, 29, 15) == 0x1c40
                   && G_FLD (inst->v, 2, 0) == 0x0)
                   && G_FLD (inst->v, 2, 0) == 0x0)
            {
            {
              /* lw r2, [r0]+, 4 */
              /* lw r2, [r0]+, 4 */
              sp_offset -= SCORE_INSTLEN;
              sp_offset -= SCORE_INSTLEN;
              fp_offset_p = 1;
              fp_offset_p = 1;
            }
            }
 
 
          else if (G_FLD (inst->v, 29, 17) == 0x100
          else if (G_FLD (inst->v, 29, 17) == 0x100
                   && G_FLD (inst->v, 0, 0) == 0x0)
                   && G_FLD (inst->v, 0, 0) == 0x0)
            {
            {
              /* addi r0, -offset */
              /* addi r0, -offset */
              sp_offset += 65536 - G_FLD (inst->v, 16, 1);
              sp_offset += 65536 - G_FLD (inst->v, 16, 1);
            }
            }
          else if (G_FLD (inst->v, 29, 17) == 0x110
          else if (G_FLD (inst->v, 29, 17) == 0x110
                   && G_FLD (inst->v, 0, 0) == 0x0)
                   && G_FLD (inst->v, 0, 0) == 0x0)
            {
            {
              /* addi r2, offset */
              /* addi r2, offset */
              if (pc - cur_pc > 4)
              if (pc - cur_pc > 4)
                {
                {
                  unsigned int save_v = inst->v;
                  unsigned int save_v = inst->v;
                  inst_t *inst2 =
                  inst_t *inst2 =
                    score7_fetch_inst (gdbarch, cur_pc + SCORE_INSTLEN, NULL);
                    score7_fetch_inst (gdbarch, cur_pc + SCORE_INSTLEN, NULL);
                  if (inst2->v == 0x23)
                  if (inst2->v == 0x23)
                    {
                    {
                      /* mv! r0, r2 */
                      /* mv! r0, r2 */
                      sp_offset -= G_FLD (save_v, 16, 1);
                      sp_offset -= G_FLD (save_v, 16, 1);
                    }
                    }
                }
                }
            }
            }
        }
        }
    }
    }
 
 
  /* Save RA.  */
  /* Save RA.  */
  if (ra_offset_p == 1)
  if (ra_offset_p == 1)
    {
    {
      if (this_cache->saved_regs[SCORE_PC_REGNUM].addr == -1)
      if (this_cache->saved_regs[SCORE_PC_REGNUM].addr == -1)
        this_cache->saved_regs[SCORE_PC_REGNUM].addr =
        this_cache->saved_regs[SCORE_PC_REGNUM].addr =
          sp + sp_offset - ra_offset;
          sp + sp_offset - ra_offset;
    }
    }
  else
  else
    {
    {
      this_cache->saved_regs[SCORE_PC_REGNUM] =
      this_cache->saved_regs[SCORE_PC_REGNUM] =
        this_cache->saved_regs[SCORE_RA_REGNUM];
        this_cache->saved_regs[SCORE_RA_REGNUM];
    }
    }
 
 
  /* Save FP.  */
  /* Save FP.  */
  if (fp_offset_p == 1)
  if (fp_offset_p == 1)
    {
    {
      if (this_cache->saved_regs[SCORE_FP_REGNUM].addr == -1)
      if (this_cache->saved_regs[SCORE_FP_REGNUM].addr == -1)
        this_cache->saved_regs[SCORE_FP_REGNUM].addr =
        this_cache->saved_regs[SCORE_FP_REGNUM].addr =
          sp + sp_offset - fp_offset;
          sp + sp_offset - fp_offset;
    }
    }
 
 
  /* Save SP and FP.  */
  /* Save SP and FP.  */
  this_cache->base = sp + sp_offset;
  this_cache->base = sp + sp_offset;
  this_cache->fp = fp;
  this_cache->fp = fp;
 
 
  /* Don't forget to free MEMBLOCK if we allocated it.  */
  /* Don't forget to free MEMBLOCK if we allocated it.  */
  if (memblock_ptr != NULL)
  if (memblock_ptr != NULL)
    score7_free_memblock (memblock_ptr);
    score7_free_memblock (memblock_ptr);
}
}
 
 
static void
static void
score3_analyze_prologue (CORE_ADDR startaddr, CORE_ADDR pc,
score3_analyze_prologue (CORE_ADDR startaddr, CORE_ADDR pc,
                        struct frame_info *this_frame,
                        struct frame_info *this_frame,
                        struct score_frame_cache *this_cache)
                        struct score_frame_cache *this_cache)
{
{
  CORE_ADDR sp;
  CORE_ADDR sp;
  CORE_ADDR fp;
  CORE_ADDR fp;
  CORE_ADDR cur_pc = startaddr;
  CORE_ADDR cur_pc = startaddr;
  enum bfd_endian byte_order = gdbarch_byte_order (get_frame_arch (this_frame));
  enum bfd_endian byte_order = gdbarch_byte_order (get_frame_arch (this_frame));
 
 
  int sp_offset = 0;
  int sp_offset = 0;
  int ra_offset = 0;
  int ra_offset = 0;
  int fp_offset = 0;
  int fp_offset = 0;
  int ra_offset_p = 0;
  int ra_offset_p = 0;
  int fp_offset_p = 0;
  int fp_offset_p = 0;
  int inst_len = 0;
  int inst_len = 0;
 
 
  CORE_ADDR prev_pc = -1;
  CORE_ADDR prev_pc = -1;
 
 
  sp = get_frame_register_unsigned (this_frame, SCORE_SP_REGNUM);
  sp = get_frame_register_unsigned (this_frame, SCORE_SP_REGNUM);
  fp = get_frame_register_unsigned (this_frame, SCORE_FP_REGNUM);
  fp = get_frame_register_unsigned (this_frame, SCORE_FP_REGNUM);
 
 
  for (; cur_pc < pc; prev_pc = cur_pc, cur_pc += inst_len)
  for (; cur_pc < pc; prev_pc = cur_pc, cur_pc += inst_len)
    {
    {
      inst_t *inst = NULL;
      inst_t *inst = NULL;
 
 
      inst = score3_adjust_pc_and_fetch_inst (&cur_pc, &inst_len, byte_order);
      inst = score3_adjust_pc_and_fetch_inst (&cur_pc, &inst_len, byte_order);
 
 
      /* FIXME: make a full-power prologue analyzer */
      /* FIXME: make a full-power prologue analyzer */
      if (inst->len == 2)
      if (inst->len == 2)
        {
        {
          if (G_FLD (inst->v, 14, 12) == 0x0
          if (G_FLD (inst->v, 14, 12) == 0x0
              && G_FLD (inst->v, 11, 7) == 0x0
              && G_FLD (inst->v, 11, 7) == 0x0
              && G_FLD (inst->v, 6, 5) == 0x3)
              && G_FLD (inst->v, 6, 5) == 0x3)
            {
            {
              /* push! */
              /* push! */
              sp_offset += 4;
              sp_offset += 4;
 
 
              if (G_FLD (inst->v, 4, 0) == 0x3
              if (G_FLD (inst->v, 4, 0) == 0x3
                  && ra_offset_p == 0)
                  && ra_offset_p == 0)
                {
                {
                  /* push! r3, [r0] */
                  /* push! r3, [r0] */
                  ra_offset = sp_offset;
                  ra_offset = sp_offset;
                  ra_offset_p = 1;
                  ra_offset_p = 1;
                }
                }
              else if (G_FLD (inst->v, 4, 0) == 0x2
              else if (G_FLD (inst->v, 4, 0) == 0x2
                       && fp_offset_p == 0)
                       && fp_offset_p == 0)
                {
                {
                  /* push! r2, [r0] */
                  /* push! r2, [r0] */
                  fp_offset = sp_offset;
                  fp_offset = sp_offset;
                  fp_offset_p = 1;
                  fp_offset_p = 1;
                }
                }
            }
            }
          else if (G_FLD (inst->v, 14, 12) == 0x6
          else if (G_FLD (inst->v, 14, 12) == 0x6
                   && G_FLD (inst->v, 11, 10) == 0x3)
                   && G_FLD (inst->v, 11, 10) == 0x3)
            {
            {
              /* rpush! */
              /* rpush! */
              int start_r = G_FLD (inst->v, 9, 5);
              int start_r = G_FLD (inst->v, 9, 5);
              int cnt = G_FLD (inst->v, 4, 0);
              int cnt = G_FLD (inst->v, 4, 0);
 
 
              if ((ra_offset_p == 0)
              if ((ra_offset_p == 0)
                  && (start_r <= SCORE_RA_REGNUM)
                  && (start_r <= SCORE_RA_REGNUM)
                  && (SCORE_RA_REGNUM < start_r + cnt))
                  && (SCORE_RA_REGNUM < start_r + cnt))
                {
                {
                  /* rpush! contains r3 */
                  /* rpush! contains r3 */
                  ra_offset_p = 1;
                  ra_offset_p = 1;
                  ra_offset = sp_offset + 4 * (SCORE_RA_REGNUM - start_r) + 4;
                  ra_offset = sp_offset + 4 * (SCORE_RA_REGNUM - start_r) + 4;
                }
                }
 
 
              if ((fp_offset_p == 0)
              if ((fp_offset_p == 0)
                  && (start_r <= SCORE_FP_REGNUM)
                  && (start_r <= SCORE_FP_REGNUM)
                  && (SCORE_FP_REGNUM < start_r + cnt))
                  && (SCORE_FP_REGNUM < start_r + cnt))
                {
                {
                  /* rpush! contains r2 */
                  /* rpush! contains r2 */
                  fp_offset_p = 1;
                  fp_offset_p = 1;
                  fp_offset = sp_offset + 4 * (SCORE_FP_REGNUM - start_r) + 4;
                  fp_offset = sp_offset + 4 * (SCORE_FP_REGNUM - start_r) + 4;
                }
                }
 
 
              sp_offset += 4 * cnt;
              sp_offset += 4 * cnt;
            }
            }
          else if (G_FLD (inst->v, 14, 12) == 0x0
          else if (G_FLD (inst->v, 14, 12) == 0x0
                   && G_FLD (inst->v, 11, 7) == 0x0
                   && G_FLD (inst->v, 11, 7) == 0x0
                   && G_FLD (inst->v, 6, 5) == 0x2)
                   && G_FLD (inst->v, 6, 5) == 0x2)
            {
            {
              /* pop! */
              /* pop! */
              sp_offset -= 4;
              sp_offset -= 4;
            }
            }
          else if (G_FLD (inst->v, 14, 12) == 0x6
          else if (G_FLD (inst->v, 14, 12) == 0x6
                   && G_FLD (inst->v, 11, 10) == 0x2)
                   && G_FLD (inst->v, 11, 10) == 0x2)
            {
            {
              /* rpop! */
              /* rpop! */
              sp_offset -= 4 * G_FLD (inst->v, 4, 0);
              sp_offset -= 4 * G_FLD (inst->v, 4, 0);
            }
            }
          else if (G_FLD (inst->v, 14, 12) == 0x5
          else if (G_FLD (inst->v, 14, 12) == 0x5
                   && G_FLD (inst->v, 11, 10) == 0x3
                   && G_FLD (inst->v, 11, 10) == 0x3
                   && G_FLD (inst->v, 9, 6) == 0x0)
                   && G_FLD (inst->v, 9, 6) == 0x0)
            {
            {
              /* addi! r0, -offset */
              /* addi! r0, -offset */
              int imm = G_FLD (inst->v, 5, 0);
              int imm = G_FLD (inst->v, 5, 0);
              if (imm >> 5)
              if (imm >> 5)
                imm = -(0x3F - imm + 1);
                imm = -(0x3F - imm + 1);
              sp_offset -= imm;
              sp_offset -= imm;
            }
            }
          else if (G_FLD (inst->v, 14, 12) == 0x5
          else if (G_FLD (inst->v, 14, 12) == 0x5
                   && G_FLD (inst->v, 11, 10) == 0x3
                   && G_FLD (inst->v, 11, 10) == 0x3
                   && G_FLD (inst->v, 9, 6) == 0x2)
                   && G_FLD (inst->v, 9, 6) == 0x2)
            {
            {
              /* addi! r2, offset */
              /* addi! r2, offset */
              if (pc - cur_pc >= 2)
              if (pc - cur_pc >= 2)
                {
                {
                  unsigned int save_v = inst->v;
                  unsigned int save_v = inst->v;
                  inst_t *inst2;
                  inst_t *inst2;
 
 
                  cur_pc += inst->len;
                  cur_pc += inst->len;
                  inst2 = score3_adjust_pc_and_fetch_inst (&cur_pc, NULL, byte_order);
                  inst2 = score3_adjust_pc_and_fetch_inst (&cur_pc, NULL, byte_order);
 
 
                  if (inst2->len == 2
                  if (inst2->len == 2
                      && G_FLD (inst2->v, 14, 10) == 0x10
                      && G_FLD (inst2->v, 14, 10) == 0x10
                      && G_FLD (inst2->v, 9, 5) == 0x0
                      && G_FLD (inst2->v, 9, 5) == 0x0
                      && G_FLD (inst2->v, 4, 0) == 0x2)
                      && G_FLD (inst2->v, 4, 0) == 0x2)
                    {
                    {
                      /* mv! r0, r2 */
                      /* mv! r0, r2 */
                      int imm = G_FLD (inst->v, 5, 0);
                      int imm = G_FLD (inst->v, 5, 0);
                      if (imm >> 5)
                      if (imm >> 5)
                        imm = -(0x3F - imm + 1);
                        imm = -(0x3F - imm + 1);
                      sp_offset -= imm;
                      sp_offset -= imm;
                    }
                    }
                }
                }
            }
            }
        }
        }
      else if (inst->len == 4)
      else if (inst->len == 4)
        {
        {
          if (G_FLD (inst->v, 29, 25) == 0x3
          if (G_FLD (inst->v, 29, 25) == 0x3
              && G_FLD (inst->v, 2, 0) == 0x4
              && G_FLD (inst->v, 2, 0) == 0x4
              && G_FLD (inst->v, 24, 20) == 0x3
              && G_FLD (inst->v, 24, 20) == 0x3
              && G_FLD (inst->v, 19, 15) == 0x0)
              && G_FLD (inst->v, 19, 15) == 0x0)
            {
            {
              /* sw r3, [r0, offset]+ */
              /* sw r3, [r0, offset]+ */
              sp_offset += inst->len;
              sp_offset += inst->len;
              if (ra_offset_p == 0)
              if (ra_offset_p == 0)
                {
                {
                  ra_offset = sp_offset;
                  ra_offset = sp_offset;
                  ra_offset_p = 1;
                  ra_offset_p = 1;
                }
                }
            }
            }
          else if (G_FLD (inst->v, 29, 25) == 0x3
          else if (G_FLD (inst->v, 29, 25) == 0x3
                   && G_FLD (inst->v, 2, 0) == 0x4
                   && G_FLD (inst->v, 2, 0) == 0x4
                   && G_FLD (inst->v, 24, 20) == 0x2
                   && G_FLD (inst->v, 24, 20) == 0x2
                   && G_FLD (inst->v, 19, 15) == 0x0)
                   && G_FLD (inst->v, 19, 15) == 0x0)
            {
            {
              /* sw r2, [r0, offset]+ */
              /* sw r2, [r0, offset]+ */
              sp_offset += inst->len;
              sp_offset += inst->len;
              if (fp_offset_p == 0)
              if (fp_offset_p == 0)
                {
                {
                  fp_offset = sp_offset;
                  fp_offset = sp_offset;
                  fp_offset_p = 1;
                  fp_offset_p = 1;
                }
                }
            }
            }
          else if (G_FLD (inst->v, 29, 25) == 0x7
          else if (G_FLD (inst->v, 29, 25) == 0x7
                   && G_FLD (inst->v, 2, 0) == 0x0
                   && G_FLD (inst->v, 2, 0) == 0x0
                   && G_FLD (inst->v, 24, 20) == 0x3
                   && G_FLD (inst->v, 24, 20) == 0x3
                   && G_FLD (inst->v, 19, 15) == 0x0)
                   && G_FLD (inst->v, 19, 15) == 0x0)
            {
            {
              /* lw r3, [r0]+, 4 */
              /* lw r3, [r0]+, 4 */
              sp_offset -= inst->len;
              sp_offset -= inst->len;
              ra_offset_p = 1;
              ra_offset_p = 1;
            }
            }
          else if (G_FLD (inst->v, 29, 25) == 0x7
          else if (G_FLD (inst->v, 29, 25) == 0x7
                   && G_FLD (inst->v, 2, 0) == 0x0
                   && G_FLD (inst->v, 2, 0) == 0x0
                   && G_FLD (inst->v, 24, 20) == 0x2
                   && G_FLD (inst->v, 24, 20) == 0x2
                   && G_FLD (inst->v, 19, 15) == 0x0)
                   && G_FLD (inst->v, 19, 15) == 0x0)
            {
            {
              /* lw r2, [r0]+, 4 */
              /* lw r2, [r0]+, 4 */
              sp_offset -= inst->len;
              sp_offset -= inst->len;
              fp_offset_p = 1;
              fp_offset_p = 1;
            }
            }
          else if (G_FLD (inst->v, 29, 25) == 0x1
          else if (G_FLD (inst->v, 29, 25) == 0x1
                   && G_FLD (inst->v, 19, 17) == 0x0
                   && G_FLD (inst->v, 19, 17) == 0x0
                   && G_FLD (inst->v, 24, 20) == 0x0
                   && G_FLD (inst->v, 24, 20) == 0x0
                   && G_FLD (inst->v, 0, 0) == 0x0)
                   && G_FLD (inst->v, 0, 0) == 0x0)
            {
            {
              /* addi r0, -offset */
              /* addi r0, -offset */
              int imm = G_FLD (inst->v, 16, 1);
              int imm = G_FLD (inst->v, 16, 1);
              if (imm >> 15)
              if (imm >> 15)
                imm = -(0xFFFF - imm + 1);
                imm = -(0xFFFF - imm + 1);
              sp_offset -= imm;
              sp_offset -= imm;
            }
            }
          else if (G_FLD (inst->v, 29, 25) == 0x1
          else if (G_FLD (inst->v, 29, 25) == 0x1
                   && G_FLD (inst->v, 19, 17) == 0x0
                   && G_FLD (inst->v, 19, 17) == 0x0
                   && G_FLD (inst->v, 24, 20) == 0x2
                   && G_FLD (inst->v, 24, 20) == 0x2
                   && G_FLD (inst->v, 0, 0) == 0x0)
                   && G_FLD (inst->v, 0, 0) == 0x0)
            {
            {
              /* addi r2, offset */
              /* addi r2, offset */
              if (pc - cur_pc >= 2)
              if (pc - cur_pc >= 2)
                {
                {
                  unsigned int save_v = inst->v;
                  unsigned int save_v = inst->v;
                  inst_t *inst2;
                  inst_t *inst2;
 
 
                  cur_pc += inst->len;
                  cur_pc += inst->len;
                  inst2 = score3_adjust_pc_and_fetch_inst (&cur_pc, NULL, byte_order);
                  inst2 = score3_adjust_pc_and_fetch_inst (&cur_pc, NULL, byte_order);
 
 
                  if (inst2->len == 2
                  if (inst2->len == 2
                      && G_FLD (inst2->v, 14, 10) == 0x10
                      && G_FLD (inst2->v, 14, 10) == 0x10
                      && G_FLD (inst2->v, 9, 5) == 0x0
                      && G_FLD (inst2->v, 9, 5) == 0x0
                      && G_FLD (inst2->v, 4, 0) == 0x2)
                      && G_FLD (inst2->v, 4, 0) == 0x2)
                    {
                    {
                      /* mv! r0, r2 */
                      /* mv! r0, r2 */
                      int imm = G_FLD (inst->v, 16, 1);
                      int imm = G_FLD (inst->v, 16, 1);
                      if (imm >> 15)
                      if (imm >> 15)
                        imm = -(0xFFFF - imm + 1);
                        imm = -(0xFFFF - imm + 1);
                      sp_offset -= imm;
                      sp_offset -= imm;
                    }
                    }
                }
                }
            }
            }
        }
        }
    }
    }
 
 
  /* Save RA.  */
  /* Save RA.  */
  if (ra_offset_p == 1)
  if (ra_offset_p == 1)
    {
    {
      if (this_cache->saved_regs[SCORE_PC_REGNUM].addr == -1)
      if (this_cache->saved_regs[SCORE_PC_REGNUM].addr == -1)
        this_cache->saved_regs[SCORE_PC_REGNUM].addr =
        this_cache->saved_regs[SCORE_PC_REGNUM].addr =
          sp + sp_offset - ra_offset;
          sp + sp_offset - ra_offset;
    }
    }
  else
  else
    {
    {
      this_cache->saved_regs[SCORE_PC_REGNUM] =
      this_cache->saved_regs[SCORE_PC_REGNUM] =
        this_cache->saved_regs[SCORE_RA_REGNUM];
        this_cache->saved_regs[SCORE_RA_REGNUM];
    }
    }
 
 
  /* Save FP.  */
  /* Save FP.  */
  if (fp_offset_p == 1)
  if (fp_offset_p == 1)
    {
    {
      if (this_cache->saved_regs[SCORE_FP_REGNUM].addr == -1)
      if (this_cache->saved_regs[SCORE_FP_REGNUM].addr == -1)
        this_cache->saved_regs[SCORE_FP_REGNUM].addr =
        this_cache->saved_regs[SCORE_FP_REGNUM].addr =
          sp + sp_offset - fp_offset;
          sp + sp_offset - fp_offset;
    }
    }
 
 
  /* Save SP and FP.  */
  /* Save SP and FP.  */
  this_cache->base = sp + sp_offset;
  this_cache->base = sp + sp_offset;
  this_cache->fp = fp;
  this_cache->fp = fp;
}
}
 
 
static struct score_frame_cache *
static struct score_frame_cache *
score_make_prologue_cache (struct frame_info *this_frame, void **this_cache)
score_make_prologue_cache (struct frame_info *this_frame, void **this_cache)
{
{
  struct score_frame_cache *cache;
  struct score_frame_cache *cache;
 
 
  if ((*this_cache) != NULL)
  if ((*this_cache) != NULL)
    return (*this_cache);
    return (*this_cache);
 
 
  cache = FRAME_OBSTACK_ZALLOC (struct score_frame_cache);
  cache = FRAME_OBSTACK_ZALLOC (struct score_frame_cache);
  (*this_cache) = cache;
  (*this_cache) = cache;
  cache->saved_regs = trad_frame_alloc_saved_regs (this_frame);
  cache->saved_regs = trad_frame_alloc_saved_regs (this_frame);
 
 
  /* Analyze the prologue.  */
  /* Analyze the prologue.  */
  {
  {
    const CORE_ADDR pc = get_frame_pc (this_frame);
    const CORE_ADDR pc = get_frame_pc (this_frame);
    CORE_ADDR start_addr;
    CORE_ADDR start_addr;
 
 
    find_pc_partial_function (pc, NULL, &start_addr, NULL);
    find_pc_partial_function (pc, NULL, &start_addr, NULL);
    if (start_addr == 0)
    if (start_addr == 0)
      return cache;
      return cache;
 
 
    if (target_mach == bfd_mach_score3)
    if (target_mach == bfd_mach_score3)
      score3_analyze_prologue (start_addr, pc, this_frame, *this_cache);
      score3_analyze_prologue (start_addr, pc, this_frame, *this_cache);
    else
    else
      score7_analyze_prologue (start_addr, pc, this_frame, *this_cache);
      score7_analyze_prologue (start_addr, pc, this_frame, *this_cache);
  }
  }
 
 
  /* Save SP.  */
  /* Save SP.  */
  trad_frame_set_value (cache->saved_regs, SCORE_SP_REGNUM, cache->base);
  trad_frame_set_value (cache->saved_regs, SCORE_SP_REGNUM, cache->base);
 
 
  return (*this_cache);
  return (*this_cache);
}
}
 
 
static void
static void
score_prologue_this_id (struct frame_info *this_frame, void **this_cache,
score_prologue_this_id (struct frame_info *this_frame, void **this_cache,
                        struct frame_id *this_id)
                        struct frame_id *this_id)
{
{
  struct score_frame_cache *info = score_make_prologue_cache (this_frame,
  struct score_frame_cache *info = score_make_prologue_cache (this_frame,
                                                              this_cache);
                                                              this_cache);
  (*this_id) = frame_id_build (info->base, get_frame_func (this_frame));
  (*this_id) = frame_id_build (info->base, get_frame_func (this_frame));
}
}
 
 
static struct value *
static struct value *
score_prologue_prev_register (struct frame_info *this_frame,
score_prologue_prev_register (struct frame_info *this_frame,
                              void **this_cache, int regnum)
                              void **this_cache, int regnum)
{
{
  struct score_frame_cache *info = score_make_prologue_cache (this_frame,
  struct score_frame_cache *info = score_make_prologue_cache (this_frame,
                                                              this_cache);
                                                              this_cache);
  return trad_frame_get_prev_register (this_frame, info->saved_regs, regnum);
  return trad_frame_get_prev_register (this_frame, info->saved_regs, regnum);
}
}
 
 
static const struct frame_unwind score_prologue_unwind =
static const struct frame_unwind score_prologue_unwind =
{
{
  NORMAL_FRAME,
  NORMAL_FRAME,
  score_prologue_this_id,
  score_prologue_this_id,
  score_prologue_prev_register,
  score_prologue_prev_register,
  NULL,
  NULL,
  default_frame_sniffer,
  default_frame_sniffer,
  NULL
  NULL
};
};
 
 
static CORE_ADDR
static CORE_ADDR
score_prologue_frame_base_address (struct frame_info *this_frame,
score_prologue_frame_base_address (struct frame_info *this_frame,
                                   void **this_cache)
                                   void **this_cache)
{
{
  struct score_frame_cache *info =
  struct score_frame_cache *info =
    score_make_prologue_cache (this_frame, this_cache);
    score_make_prologue_cache (this_frame, this_cache);
  return info->fp;
  return info->fp;
}
}
 
 
static const struct frame_base score_prologue_frame_base =
static const struct frame_base score_prologue_frame_base =
{
{
  &score_prologue_unwind,
  &score_prologue_unwind,
  score_prologue_frame_base_address,
  score_prologue_frame_base_address,
  score_prologue_frame_base_address,
  score_prologue_frame_base_address,
  score_prologue_frame_base_address,
  score_prologue_frame_base_address,
};
};
 
 
static const struct frame_base *
static const struct frame_base *
score_prologue_frame_base_sniffer (struct frame_info *this_frame)
score_prologue_frame_base_sniffer (struct frame_info *this_frame)
{
{
  return &score_prologue_frame_base;
  return &score_prologue_frame_base;
}
}
 
 
/* Core file support (dirty hack)
/* Core file support (dirty hack)
 
 
   The core file MUST be generated by GNU/Linux on S+core */
   The core file MUST be generated by GNU/Linux on S+core */
 
 
static void
static void
score7_linux_supply_gregset(const struct regset *regset,
score7_linux_supply_gregset(const struct regset *regset,
                struct regcache *regcache,
                struct regcache *regcache,
                int regnum, const void *gregs_buf, size_t len)
                int regnum, const void *gregs_buf, size_t len)
{
{
    int regno;
    int regno;
    elf_gregset_t *gregs;
    elf_gregset_t *gregs;
 
 
    gdb_assert (regset != NULL);
    gdb_assert (regset != NULL);
    gdb_assert ((regcache != NULL) && (gregs_buf != NULL));
    gdb_assert ((regcache != NULL) && (gregs_buf != NULL));
 
 
    gregs = (elf_gregset_t *) gregs_buf;
    gregs = (elf_gregset_t *) gregs_buf;
 
 
    for (regno = 0; regno < 32; regno++)
    for (regno = 0; regno < 32; regno++)
        if (regnum == -1 || regnum == regno)
        if (regnum == -1 || regnum == regno)
            regcache_raw_supply (regcache, regno, gregs->regs + regno);
            regcache_raw_supply (regcache, regno, gregs->regs + regno);
 
 
    {
    {
        struct sreg {
        struct sreg {
                int regnum;
                int regnum;
                void *buf;
                void *buf;
        } sregs [] = {
        } sregs [] = {
                { 55, &(gregs->cel) },  /* CEL */
                { 55, &(gregs->cel) },  /* CEL */
                { 54, &(gregs->ceh) },  /* CEH */
                { 54, &(gregs->ceh) },  /* CEH */
                { 53, &(gregs->sr0) },  /* sr0, i.e. cnt or COUNTER */
                { 53, &(gregs->sr0) },  /* sr0, i.e. cnt or COUNTER */
                { 52, &(gregs->sr1) },  /* sr1, i.e. lcr or LDCR */
                { 52, &(gregs->sr1) },  /* sr1, i.e. lcr or LDCR */
                { 51, &(gregs->sr1) },  /* sr2, i.e. scr or STCR */
                { 51, &(gregs->sr1) },  /* sr2, i.e. scr or STCR */
 
 
                /* Exception occured at this address, exactly the PC we want */
                /* Exception occured at this address, exactly the PC we want */
                { 49, &(gregs->cp0_epc) }, /* PC */
                { 49, &(gregs->cp0_epc) }, /* PC */
 
 
                { 38, &(gregs->cp0_ema) }, /* EMA */
                { 38, &(gregs->cp0_ema) }, /* EMA */
                { 37, &(gregs->cp0_epc) }, /* EPC */
                { 37, &(gregs->cp0_epc) }, /* EPC */
                { 34, &(gregs->cp0_ecr) }, /* ECR */
                { 34, &(gregs->cp0_ecr) }, /* ECR */
                { 33, &(gregs->cp0_condition) }, /* COND */
                { 33, &(gregs->cp0_condition) }, /* COND */
                { 32, &(gregs->cp0_psr) }, /* PSR */
                { 32, &(gregs->cp0_psr) }, /* PSR */
        };
        };
 
 
        for (regno = 0; regno < sizeof(sregs)/sizeof(sregs[0]); regno++)
        for (regno = 0; regno < sizeof(sregs)/sizeof(sregs[0]); regno++)
            if (regnum == -1 || regnum == sregs[regno].regnum)
            if (regnum == -1 || regnum == sregs[regno].regnum)
                regcache_raw_supply (regcache, sregs[regno].regnum, sregs[regno].buf);
                regcache_raw_supply (regcache, sregs[regno].regnum, sregs[regno].buf);
    }
    }
}
}
 
 
/* Return the appropriate register set from the core section identified
/* Return the appropriate register set from the core section identified
   by SECT_NAME and SECT_SIZE. */
   by SECT_NAME and SECT_SIZE. */
 
 
static const struct regset *
static const struct regset *
score7_linux_regset_from_core_section(struct gdbarch *gdbarch,
score7_linux_regset_from_core_section(struct gdbarch *gdbarch,
                    const char *sect_name, size_t sect_size)
                    const char *sect_name, size_t sect_size)
{
{
    struct gdbarch_tdep *tdep;
    struct gdbarch_tdep *tdep;
 
 
    gdb_assert (gdbarch != NULL);
    gdb_assert (gdbarch != NULL);
    gdb_assert (sect_name != NULL);
    gdb_assert (sect_name != NULL);
 
 
    tdep = gdbarch_tdep (gdbarch);
    tdep = gdbarch_tdep (gdbarch);
 
 
    if (strcmp(sect_name, ".reg") == 0 && sect_size == sizeof(elf_gregset_t))
    if (strcmp(sect_name, ".reg") == 0 && sect_size == sizeof(elf_gregset_t))
    {
    {
        if (tdep->gregset == NULL)
        if (tdep->gregset == NULL)
            tdep->gregset = regset_alloc (gdbarch, score7_linux_supply_gregset, NULL);
            tdep->gregset = regset_alloc (gdbarch, score7_linux_supply_gregset, NULL);
        return tdep->gregset;
        return tdep->gregset;
    }
    }
 
 
    return NULL;
    return NULL;
}
}
 
 
static struct gdbarch *
static struct gdbarch *
score_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches)
score_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches)
{
{
  struct gdbarch *gdbarch;
  struct gdbarch *gdbarch;
  struct gdbarch_tdep *tdep;
  struct gdbarch_tdep *tdep;
  target_mach = info.bfd_arch_info->mach;
  target_mach = info.bfd_arch_info->mach;
 
 
  arches = gdbarch_list_lookup_by_info (arches, &info);
  arches = gdbarch_list_lookup_by_info (arches, &info);
  if (arches != NULL)
  if (arches != NULL)
    {
    {
      return (arches->gdbarch);
      return (arches->gdbarch);
    }
    }
  tdep = xcalloc(1, sizeof(struct gdbarch_tdep));
  tdep = xcalloc(1, sizeof(struct gdbarch_tdep));
  gdbarch = gdbarch_alloc (&info, tdep);
  gdbarch = gdbarch_alloc (&info, tdep);
 
 
  set_gdbarch_short_bit (gdbarch, 16);
  set_gdbarch_short_bit (gdbarch, 16);
  set_gdbarch_int_bit (gdbarch, 32);
  set_gdbarch_int_bit (gdbarch, 32);
  set_gdbarch_float_bit (gdbarch, 32);
  set_gdbarch_float_bit (gdbarch, 32);
  set_gdbarch_double_bit (gdbarch, 64);
  set_gdbarch_double_bit (gdbarch, 64);
  set_gdbarch_long_double_bit (gdbarch, 64);
  set_gdbarch_long_double_bit (gdbarch, 64);
#if WITH_SIM
#if WITH_SIM
  set_gdbarch_register_sim_regno (gdbarch, score_register_sim_regno);
  set_gdbarch_register_sim_regno (gdbarch, score_register_sim_regno);
#endif
#endif
  set_gdbarch_pc_regnum (gdbarch, SCORE_PC_REGNUM);
  set_gdbarch_pc_regnum (gdbarch, SCORE_PC_REGNUM);
  set_gdbarch_sp_regnum (gdbarch, SCORE_SP_REGNUM);
  set_gdbarch_sp_regnum (gdbarch, SCORE_SP_REGNUM);
  set_gdbarch_adjust_breakpoint_address (gdbarch, score_adjust_breakpoint_address);
  set_gdbarch_adjust_breakpoint_address (gdbarch, score_adjust_breakpoint_address);
  set_gdbarch_register_type (gdbarch, score_register_type);
  set_gdbarch_register_type (gdbarch, score_register_type);
  set_gdbarch_frame_align (gdbarch, score_frame_align);
  set_gdbarch_frame_align (gdbarch, score_frame_align);
  set_gdbarch_inner_than (gdbarch, core_addr_lessthan);
  set_gdbarch_inner_than (gdbarch, core_addr_lessthan);
  set_gdbarch_unwind_sp (gdbarch, score_unwind_sp);
  set_gdbarch_unwind_sp (gdbarch, score_unwind_sp);
  set_gdbarch_unwind_pc (gdbarch, score_unwind_pc);
  set_gdbarch_unwind_pc (gdbarch, score_unwind_pc);
  set_gdbarch_print_insn (gdbarch, score_print_insn);
  set_gdbarch_print_insn (gdbarch, score_print_insn);
 
 
  switch (target_mach)
  switch (target_mach)
    {
    {
    case bfd_mach_score7:
    case bfd_mach_score7:
      set_gdbarch_breakpoint_from_pc (gdbarch, score7_breakpoint_from_pc);
      set_gdbarch_breakpoint_from_pc (gdbarch, score7_breakpoint_from_pc);
      set_gdbarch_skip_prologue (gdbarch, score7_skip_prologue);
      set_gdbarch_skip_prologue (gdbarch, score7_skip_prologue);
      set_gdbarch_in_function_epilogue_p (gdbarch, score7_in_function_epilogue_p);
      set_gdbarch_in_function_epilogue_p (gdbarch, score7_in_function_epilogue_p);
      set_gdbarch_register_name (gdbarch, score7_register_name);
      set_gdbarch_register_name (gdbarch, score7_register_name);
      set_gdbarch_num_regs (gdbarch, SCORE7_NUM_REGS);
      set_gdbarch_num_regs (gdbarch, SCORE7_NUM_REGS);
      /* Core file support. */
      /* Core file support. */
      set_gdbarch_regset_from_core_section (gdbarch, score7_linux_regset_from_core_section);
      set_gdbarch_regset_from_core_section (gdbarch, score7_linux_regset_from_core_section);
      break;
      break;
 
 
    case bfd_mach_score3:
    case bfd_mach_score3:
      set_gdbarch_breakpoint_from_pc (gdbarch, score3_breakpoint_from_pc);
      set_gdbarch_breakpoint_from_pc (gdbarch, score3_breakpoint_from_pc);
      set_gdbarch_skip_prologue (gdbarch, score3_skip_prologue);
      set_gdbarch_skip_prologue (gdbarch, score3_skip_prologue);
      set_gdbarch_in_function_epilogue_p (gdbarch, score3_in_function_epilogue_p);
      set_gdbarch_in_function_epilogue_p (gdbarch, score3_in_function_epilogue_p);
      set_gdbarch_register_name (gdbarch, score3_register_name);
      set_gdbarch_register_name (gdbarch, score3_register_name);
      set_gdbarch_num_regs (gdbarch, SCORE3_NUM_REGS);
      set_gdbarch_num_regs (gdbarch, SCORE3_NUM_REGS);
      break;
      break;
    }
    }
 
 
  /* Watchpoint hooks.  */
  /* Watchpoint hooks.  */
  set_gdbarch_have_nonsteppable_watchpoint (gdbarch, 1);
  set_gdbarch_have_nonsteppable_watchpoint (gdbarch, 1);
 
 
  /* Dummy frame hooks.  */
  /* Dummy frame hooks.  */
  set_gdbarch_return_value (gdbarch, score_return_value);
  set_gdbarch_return_value (gdbarch, score_return_value);
  set_gdbarch_call_dummy_location (gdbarch, AT_ENTRY_POINT);
  set_gdbarch_call_dummy_location (gdbarch, AT_ENTRY_POINT);
  set_gdbarch_dummy_id (gdbarch, score_dummy_id);
  set_gdbarch_dummy_id (gdbarch, score_dummy_id);
  set_gdbarch_push_dummy_call (gdbarch, score_push_dummy_call);
  set_gdbarch_push_dummy_call (gdbarch, score_push_dummy_call);
 
 
  /* Normal frame hooks.  */
  /* Normal frame hooks.  */
  dwarf2_append_unwinders (gdbarch);
  dwarf2_append_unwinders (gdbarch);
  frame_base_append_sniffer (gdbarch, dwarf2_frame_base_sniffer);
  frame_base_append_sniffer (gdbarch, dwarf2_frame_base_sniffer);
  frame_unwind_append_unwinder (gdbarch, &score_prologue_unwind);
  frame_unwind_append_unwinder (gdbarch, &score_prologue_unwind);
  frame_base_append_sniffer (gdbarch, score_prologue_frame_base_sniffer);
  frame_base_append_sniffer (gdbarch, score_prologue_frame_base_sniffer);
 
 
  return gdbarch;
  return gdbarch;
}
}
 
 
extern initialize_file_ftype _initialize_score_tdep;
extern initialize_file_ftype _initialize_score_tdep;
 
 
void
void
_initialize_score_tdep (void)
_initialize_score_tdep (void)
{
{
  gdbarch_register (bfd_arch_score, score_gdbarch_init, NULL);
  gdbarch_register (bfd_arch_score, score_gdbarch_init, NULL);
}
}
 
 

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.