Re: Errors occurred when building GDB using instuctions from EAN2 at

View: New views
6 Messages — Rating Filter:   Alert me  

Re: Errors occurred when building GDB using instuctions from EAN2 at

by rich_daddio :: Rate this Message:

Reply to Author | View Threaded | Show Only this Message

Hi,
We have seen similar problems building our own chain with certain
releases of Ubuntu/gcc-4.x. There are security issues that can cause
it see link below.

Yan Morvan recently fixed this in our toolchain following Frysinger's
suggestion here:
http://blackfin.uclinux.org/gf/project/toolchain/tracker/?action=TrackerItemEdit&tracker_item_id=4802

Perhaps Yan can give you some pointers as well.

Thanks,

Rich
----- Original Message -----
From: Jeremy Bennett<jeremy.bennett@e...>
To:
Date: Thu Feb 26 19:00:09 CET 2009
Subject: [openrisc] Errors occurred when building GDB using
instuctions
        from EAN2 at www.embecosm.com

> On Thu, 2009-02-26 at 22:31 +0800, Sigma HH wrote:
> > Hi everyone,
> >
> > When I build GDB following instructions from EAN2, the
> following
> > errors occurred, it may be caused by "warnings being
> treated as
> > errors" because of flag "-Werror", can anyone
> help to fix this? Thanks
> > very much!
> >
> Hi Sigma HH,
> Thanks for the heads up on this. I haven't seen this with GCC 4.3.0
> on
> Fedora.
> I am rather surprised that GCC complains about CORE_ADDR being
> unsuitable for %08llx, since CORE_ADDR is a typedef for unsigned
> long
> long.
> The complaints about using %llu for unsigned long are more
> reasonable.
> I'm surprised I haven't seen this as a fault with GCC 4.3.0.
> Please would you file it as a bug in the OR1200 tracker
> (http://www.opencores.org/ptracker.cgi/list/or1k), so we can get it
> fixed.
> These problems occur in the code for the legacy OpenRISC JTAG
> interface,
> which has now been replaced by the standard RSP interface.
> Pending a new release of GDB, I suggest you go through or1k-tdep.c
> and
> explicitly cast each of the arguments causing complaint to unsigned
> long
> long).
> HTH,
> Jeremy
> > I build it in Ubuntu, using gcc 4.1.3
> >
> > Regards.
> >
> > Sigma HH
> >
> >
>
//---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------

> >
> > ......................
> >
> > config.status: creating gdb.threads/Makefile
> > config.status: creating gdb.trace/Makefile
> > config.status: creating gdb.xml/Makefile
> > make[2]: Entering directory
> > `/home/xuebo/downloads/or1k_downloads/build_gdb/sim'
> > make[2]: Leaving directory
> > `/home/xuebo/downloads/or1k_downloads/build_gdb/sim'
> > make[2]: Entering directory
> > `/home/xuebo/downloads/or1k_downloads/build_gdb/gdb'
> > CONFIG_HEADERS=config.h:config.in \
> > CONFIG_COMMANDS=default \
> > CONFIG_FILES= \
> > CONFIG_LINKS= \
> > /bin/bash config.status
> > config.status: creating config.h
> > config.status: config.h is unchanged
> > config.status: executing default commands
> > gcc -c -g -O2 -I. -I../../gdb-6.8/gdb
> -I../../gdb-6.8/gdb/config
> > -DLOCALEDIR="\"/opt/or32/share/locale\""
> -DHAVE_CONFIG_H
> > -I./../gdb-6.8/gdb/../include/opcode
> > -I../../gdb-6.8/gdb/../readline/.. -I../bfd
> -I../../gdb-6.8/gdb/../bfd
> > -I../../gdb-6.8/gdb/../include -I../libdecnumber
> > -I../../gdb-6.8/gdb/../libdecnumber -DMI_OUT=1 -DTUI=1 -Wall
> > -Wdeclaration-after-statement -Wpointer-arith
> -Wformat-nonliteral
> > -Wno-pointer-sign -Wno-unused -Wno-switch -Wno-char-subscripts
> > -Werror ../../gdb-6.8/gdb/gdb.c
> > gcc -c -g -O2 -I. -I../../gdb-6.8/gdb
> -I../../gdb-6.8/gdb/config
> > -DLOCALEDIR="\"/opt/or32/share/locale\""
> -DHAVE_CONFIG_H
> > -I../../gdb-6.8/gdb/../include/opcode
> > -I../../gdb-6.8/gdb/../readline/.. -I../bfd
> -I../../gdb-6.8/gdb/../bfd
> > -I../../gdb-6.8/gdb/../include -I../libdecnumber
> > -I../../gdb-6.8/gdb/../libdecnumber -DMI_OUT=1 -DTUI=1 -Wall
> > -Wdeclaration-after-statement -Wpointer-arith
> -Wformat-nonliteral
> > -Wno-pointer-sign -Wno-unused -Wno-switch -Wno-char-subscripts
> > -Werror ../../gdb-6.8/gdb/or1k-tdep.c
> > cc1: warnings being treated as errors
> > ../../gdb-6.8/gdb/or1k-tdep.c: In function
> ‘or1k_frame_unwind_cache’:
> > ../../gdb-6.8/gdb/or1k-tdep.c:705: warning: format
> ‘%08llx’ expects
> > type ‘long long unsigned int’, but argument 2 has
> type ‘CORE_ADDR’
> > ../../gdb-6.8/gdb/or1k-tdep.c:724: warning: format
> ‘%08llx’ expects
> > type ‘long long unsigned int’, but argument 2 has
> type ‘CORE_ADDR’
> > ../../gdb-6.8/gdb/or1k-tdep.c:732: warning: format
> ‘%08llx’ expects
> > type ‘long long unsigned int’, but argument 2 has
> type ‘CORE_ADDR’
> > ../../gdb-6.8/gdb/or1k-tdep.c: In function
> ‘or1k_skip_prologue’:
> > ../../gdb-6.8/gdb/or1k-tdep.c:1374: warning: format
> ‘%08llx’ expects
> > type ‘long long unsigned int’, but argument 2 has
> type ‘CORE_ADDR’
> > ../../gdb-6.8/gdb/or1k-tdep.c:1399: warning: format
> ‘%08llx’ expects
> > type ‘long long unsigned int’, but argument 2 has
> type ‘CORE_ADDR’
> > ../../gdb-6.8/gdb/or1k-tdep.c:1413: warning: format
> ‘%08llx’ expects
> > type ‘long long unsigned int’, but argument 2 has
> type ‘CORE_ADDR’
> > ../../gdb-6.8/gdb/or1k-tdep.c:1442: warning: format
> ‘%08llx’ expects
> > type ‘long long unsigned int’, but argument 2 has
> type ‘CORE_ADDR’
> > ../../gdb-6.8/gdb/or1k-tdep.c:1475: warning: format
> ‘%08llx’ expects
> > type ‘long long unsigned int’, but argument 2 has
> type ‘CORE_ADDR’ > ../../gdb-6.8/gdb/or1k-tdep.c: In
> function ‘or1k_write_spr’: >
> ../../gdb-6.8/gdb/or1k-tdep.c:2854: warning: format
> ‘%8llx’ expects > type ‘long long unsigned
> int’, but argument 4 has type ‘long unsigned >
> int’ > ../../gdb-6.8/gdb/or1k-tdep.c: In function
> ‘or1k_info_spr_command’: >
> ../../gdb-6.8/gdb/or1k-tdep.c:2900: warning: format
> ‘%llu’ expects > type ‘long long unsigned
> int’, but argument 8 has type ‘long unsigned >
> int’ > ../../gdb-6.8/gdb/or1k-tdep.c:2900: warning: format
> ‘%llx’ expects > type ‘long long unsigned
> int’, but argument 9 has type ‘long unsigned >
> int’ > ../../gdb-6.8/gdb/or1k-tdep.c:2915: warning: format
> ‘%llu’ expects > type ‘long long unsigned
> int’, but argument 8 has type ‘long unsigned >
> int’ > ../../gdb-6.8/gdb/or1k-tdep.c:2915: warning: format
> ‘%llx’ expects > type ‘long long unsigned
> int’, but argument 9 has type ‘long unsigned >
> int’ > ../../gdb-6.8/gdb/or1k-tdep.c: In function
> ‘or1k_spr_command’: >
> ../../gdb-6.8/gdb/or1k-tdep.c:2972: warning: format
> ‘%llu’ expects > type ‘long long unsigned
> int’, but argument 8 has type ‘long unsigned >
> int’ > ../../gdb-6.8/gdb/or1k-tdep.c:2972: warning: format
> ‘%llx’ expects > type ‘long long unsigned
> int’, but argument 9 has type ‘long unsigned >
> int’ > ../../gdb-6.8/gdb/or1k-tdep.c:2972: warning: format
> ‘%llu’ expects > type ‘long long unsigned
> int’, but argument 10 has type ‘long unsigned >
> int’ > ../../gdb-6.8/gdb/or1k-tdep.c:2972: warning: format
> ‘%llx’ expects > type ‘long long unsigned
> int’, but argument 11 has type ‘long unsigned >
> int’ > make[2]: *** [or1k-tdep.o] Error 1 > make[2]:
> Leaving directory >
> `/home/xuebo/downloads/or1k_downloads/build_gdb/gdb' > make[1]:
> *** [all-gdb] Error 2 > make[1]: Leaving directory >
> `/home/xuebo/downloads/or1k_downloads/build_gdb' > make: ***
> [all] Error 2 > xuebo at
> ubuntu:~/downloads/or1k_downloads/build_gdb$ ls > >
>
//------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------

> > > _______________________________________________ >
> http://www.opencores.org/mailman/listinfo/openrisc -- Tel: +44
> (1202) 416955 Cell: +44 (7970) 676050 SkypeID: jeremybennett Email:
> jeremy.bennett at embecosm.com Web: www.embecosm.com
>
_______________________________________________
http://www.opencores.org/mailman/listinfo/openrisc

Re: Errors occurred when building GDB using instuctions from EAN2 at

by Sigma HH :: Rate this Message:

Reply to Author | View Threaded | Show Only this Message

Hi,

I have successfully built GDB on Ubuntu using gcc4.1.3 after I explicitly cast each of the arguments causing complaint to long long unsigned int in the following files:

or1k-tdep.c
remote-or1k.c
or1k-jtag.c

the modified file is attached in this mail.

Unfortrunately, when I contiue to build Linux kernel (2.6.23) following instructions in EAN2, the folloing error occurs:

====================================================================
xuebo@ubuntu:~/downloads/or1k_downloads/linux-2.6.23$ make vmlinux ARCH=or32 COROSS_COMPILE=/opt/or32/bin/or32-uclinux-
make: or32-elf-gcc: Command not found
make: or32-elf-gcc: Command not found
scripts/kconfig/conf -s arch/or32/Kconfig
drivers/macintosh/Kconfig:121:warning: 'select' used by config symbol 'PMAC_APM_EMU' refers to undefined symbol 'APM_EMULATION'
make: or32-elf-gcc: Command not found
make: or32-elf-gcc: Command not found
  CHK     include/linux/version.h
  CHK     include/linux/utsrelease.h
  CC      arch/or32/kernel/asm-offsets.s
/bin/sh: or32-elf-gcc: not found
make[1]: *** [arch/or32/kernel/asm-offsets.s] Error 127
make: *** [prepare0] Error 2
=====================================================================

Any idea about this? Thanks for the help!

Best Regards.

Sigma HH


2009/2/27 <rich_daddio@...>
Hi,
We have seen similar problems building our own chain with certain
releases of Ubuntu/gcc-4.x. There are security issues that can cause
it see link below.

Yan Morvan recently fixed this in our toolchain following Frysinger's
suggestion here:
http://blackfin.uclinux.org/gf/project/toolchain/tracker/?action=TrackerItemEdit&tracker_item_id=4802

Perhaps Yan can give you some pointers as well.

Thanks,

Rich
----- Original Message -----
From: Jeremy Bennett<jeremy.bennett@e...>
To:
Date: Thu Feb 26 19:00:09 CET 2009
Subject: [openrisc] Errors occurred when building GDB using
instuctions
       from EAN2 at www.embecosm.com

> On Thu, 2009-02-26 at 22:31 +0800, Sigma HH wrote:
> > Hi everyone,
> >
> > When I build GDB following instructions from EAN2, the
> following
> > errors occurred, it may be caused by "warnings being
> treated as
> > errors" because of flag "-Werror", can anyone
> help to fix this? Thanks
> > very much!
> >
> Hi Sigma HH,
> Thanks for the heads up on this. I haven't seen this with GCC 4.3.0
> on
> Fedora.
> I am rather surprised that GCC complains about CORE_ADDR being
> unsuitable for %08llx, since CORE_ADDR is a typedef for unsigned
> long
> long.
> The complaints about using %llu for unsigned long are more
> reasonable.
> I'm surprised I haven't seen this as a fault with GCC 4.3.0.
> Please would you file it as a bug in the OR1200 tracker
> (http://www.opencores.org/ptracker.cgi/list/or1k), so we can get it
> fixed.
> These problems occur in the code for the legacy OpenRISC JTAG
> interface,
> which has now been replaced by the standard RSP interface.
> Pending a new release of GDB, I suggest you go through or1k-tdep.c
> and
> explicitly cast each of the arguments causing complaint to unsigned
> long
> long).
> HTH,
> Jeremy
> > I build it in Ubuntu, using gcc 4.1.3
> >
> > Regards.
> >
> > Sigma HH
> >
> >
>
//---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------

> >
> > ......................
> >
> > config.status: creating gdb.threads/Makefile
> > config.status: creating gdb.trace/Makefile
> > config.status: creating gdb.xml/Makefile
> > make[2]: Entering directory
> > `/home/xuebo/downloads/or1k_downloads/build_gdb/sim'
> > make[2]: Leaving directory
> > `/home/xuebo/downloads/or1k_downloads/build_gdb/sim'
> > make[2]: Entering directory
> > `/home/xuebo/downloads/or1k_downloads/build_gdb/gdb'
> > CONFIG_HEADERS=config.h:config.in \
> > CONFIG_COMMANDS=default \
> > CONFIG_FILES= \
> > CONFIG_LINKS= \
> > /bin/bash config.status
> > config.status: creating config.h
> > config.status: config.h is unchanged
> > config.status: executing default commands
> > gcc -c -g -O2 -I. -I../../gdb-6.8/gdb
> -I../../gdb-6.8/gdb/config
> > -DLOCALEDIR="\"/opt/or32/share/locale\""
> -DHAVE_CONFIG_H
> > -I./../gdb-6.8/gdb/../include/opcode
> > -I../../gdb-6.8/gdb/../readline/.. -I../bfd
> -I../../gdb-6.8/gdb/../bfd
> > -I../../gdb-6.8/gdb/../include -I../libdecnumber
> > -I../../gdb-6.8/gdb/../libdecnumber -DMI_OUT=1 -DTUI=1 -Wall
> > -Wdeclaration-after-statement -Wpointer-arith
> -Wformat-nonliteral
> > -Wno-pointer-sign -Wno-unused -Wno-switch -Wno-char-subscripts
> > -Werror ../../gdb-6.8/gdb/gdb.c
> > gcc -c -g -O2 -I. -I../../gdb-6.8/gdb
> -I../../gdb-6.8/gdb/config
> > -DLOCALEDIR="\"/opt/or32/share/locale\""
> -DHAVE_CONFIG_H
> > -I../../gdb-6.8/gdb/../include/opcode
> > -I../../gdb-6.8/gdb/../readline/.. -I../bfd
> -I../../gdb-6.8/gdb/../bfd
> > -I../../gdb-6.8/gdb/../include -I../libdecnumber
> > -I../../gdb-6.8/gdb/../libdecnumber -DMI_OUT=1 -DTUI=1 -Wall
> > -Wdeclaration-after-statement -Wpointer-arith
> -Wformat-nonliteral
> > -Wno-pointer-sign -Wno-unused -Wno-switch -Wno-char-subscripts
> > -Werror ../../gdb-6.8/gdb/or1k-tdep.c
> > cc1: warnings being treated as errors
> > ../../gdb-6.8/gdb/or1k-tdep.c: In function
> ‘or1k_frame_unwind_cache’:
> > ../../gdb-6.8/gdb/or1k-tdep.c:705: warning: format
> ‘%08llx’ expects
> > type ‘long long unsigned int’, but argument 2 has
> type ‘CORE_ADDR’
> > ../../gdb-6.8/gdb/or1k-tdep.c:724: warning: format
> ‘%08llx’ expects
> > type ‘long long unsigned int’, but argument 2 has
> type ‘CORE_ADDR’
> > ../../gdb-6.8/gdb/or1k-tdep.c:732: warning: format
> ‘%08llx’ expects
> > type ‘long long unsigned int’, but argument 2 has
> type ‘CORE_ADDR’
> > ../../gdb-6.8/gdb/or1k-tdep.c: In function
> ‘or1k_skip_prologue’:
> > ../../gdb-6.8/gdb/or1k-tdep.c:1374: warning: format
> ‘%08llx’ expects
> > type ‘long long unsigned int’, but argument 2 has
> type ‘CORE_ADDR’
> > ../../gdb-6.8/gdb/or1k-tdep.c:1399: warning: format
> ‘%08llx’ expects
> > type ‘long long unsigned int’, but argument 2 has
> type ‘CORE_ADDR’
> > ../../gdb-6.8/gdb/or1k-tdep.c:1413: warning: format
> ‘%08llx’ expects
> > type ‘long long unsigned int’, but argument 2 has
> type ‘CORE_ADDR’
> > ../../gdb-6.8/gdb/or1k-tdep.c:1442: warning: format
> ‘%08llx’ expects
> > type ‘long long unsigned int’, but argument 2 has
> type ‘CORE_ADDR’
> > ../../gdb-6.8/gdb/or1k-tdep.c:1475: warning: format
> ‘%08llx’ expects
> > type ‘long long unsigned int’, but argument 2 has
> type ‘CORE_ADDR’ > ../../gdb-6.8/gdb/or1k-tdep.c: In
> function ‘or1k_write_spr’: >
> ../../gdb-6.8/gdb/or1k-tdep.c:2854: warning: format
> ‘%8llx’ expects > type ‘long long unsigned
> int’, but argument 4 has type ‘long unsigned >
> int’ > ../../gdb-6.8/gdb/or1k-tdep.c: In function
> ‘or1k_info_spr_command’: >
> ../../gdb-6.8/gdb/or1k-tdep.c:2900: warning: format
> ‘%llu’ expects > type ‘long long unsigned
> int’, but argument 8 has type ‘long unsigned >
> int’ > ../../gdb-6.8/gdb/or1k-tdep.c:2900: warning: format
> ‘%llx’ expects > type ‘long long unsigned
> int’, but argument 9 has type ‘long unsigned >
> int’ > ../../gdb-6.8/gdb/or1k-tdep.c:2915: warning: format
> ‘%llu’ expects > type ‘long long unsigned
> int’, but argument 8 has type ‘long unsigned >
> int’ > ../../gdb-6.8/gdb/or1k-tdep.c:2915: warning: format
> ‘%llx’ expects > type ‘long long unsigned
> int’, but argument 9 has type ‘long unsigned >
> int’ > ../../gdb-6.8/gdb/or1k-tdep.c: In function
> ‘or1k_spr_command’: >
> ../../gdb-6.8/gdb/or1k-tdep.c:2972: warning: format
> ‘%llu’ expects > type ‘long long unsigned
> int’, but argument 8 has type ‘long unsigned >
> int’ > ../../gdb-6.8/gdb/or1k-tdep.c:2972: warning: format
> ‘%llx’ expects > type ‘long long unsigned
> int’, but argument 9 has type ‘long unsigned >
> int’ > ../../gdb-6.8/gdb/or1k-tdep.c:2972: warning: format
> ‘%llu’ expects > type ‘long long unsigned
> int’, but argument 10 has type ‘long unsigned >
> int’ > ../../gdb-6.8/gdb/or1k-tdep.c:2972: warning: format
> ‘%llx’ expects > type ‘long long unsigned
> int’, but argument 11 has type ‘long unsigned >
> int’ > make[2]: *** [or1k-tdep.o] Error 1 > make[2]:
> Leaving directory >
> `/home/xuebo/downloads/or1k_downloads/build_gdb/gdb' > make[1]:
> *** [all-gdb] Error 2 > make[1]: Leaving directory >
> `/home/xuebo/downloads/or1k_downloads/build_gdb' > make: ***
> [all] Error 2 > xuebo at
> ubuntu:~/downloads/or1k_downloads/build_gdb$ ls > >
>
//------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------

> > > _______________________________________________ >
> http://www.opencores.org/mailman/listinfo/openrisc -- Tel: +44
> (1202) 416955 Cell: +44 (7970) 676050 SkypeID: jeremybennett Email:
> jeremy.bennett at embecosm.com Web: www.embecosm.com
>
_______________________________________________
http://www.opencores.org/mailman/listinfo/openrisc


[or1k-tdep.c]

/* Target-dependent code for the or1k architecture, for GDB, the GNU Debugger.

   Copyright 1988-2008, Free Software Foundation, Inc.
   Copyright (C) 2008 Embecosm Limited

   Contributed by Alessandro Forin(af@... at CMU
   and by Per Bothner(bothner@...) at U.Wisconsin.
   Contributor Jeremy Bennett <jeremy.bennett@...>

   This file is part of GDB.

   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 the Free
   Software Foundation; either version 3 of the License, or (at your option)
   any later version.

   This program is distributed in the hope that it will be useful, but WITHOUT
   ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
   FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
   more details.

   You should have received a copy of the GNU General Public License along
   with this program.  If not, see <http://www.gnu.org/licenses/>.  */

/*-----------------------------------------------------------------------------
   This version for the OpenRISC 1000 architecture is a rewrite by Jeremy
   Bennett of the old GDB 5.3 interface to make use of gdbarch for GDB 6.8.

   The code tries to follow the GDB coding style.

   Commenting is Doxygen compatible.

   Much has been stripped out in the interests of getting a basic working
   system. This is described as the OpenRISC 1000 target architecture, so
   should work with 16, 32 and 64 bit versions of that architecture and should
   work whether or not they have floating point and/or vector registers.

   There was never a capability to run simulator commands (no remote target
   implemented the required function), so that has been removed.

   The info trace command has been removed. The meaning of this is not clear -
   it relies on a value in register 255 of the debug group, which is
   undocumented.

   All the hardware trace has been removed for the time being. The new debug
   interface does not support hardware trace, so there is no plan to reinstate
   this functionality.

   Support for multiple contexts (which was rudimentary, and not working) has
   been removed. */
/*---------------------------------------------------------------------------*/

#include "demangle.h"
#include "defs.h"
#include "gdb_string.h"
#include "frame.h"
#include "inferior.h"
#include "symtab.h"
#include "value.h"
#include "gdbcmd.h"
#include "language.h"
#include "gdbcore.h"
#include "symfile.h"
#include "objfiles.h"
#include "gdbtypes.h"
#include "target.h"
#include "regcache.h"

#include "opcode/or32.h"
#include "or1k-tdep.h"

#include "safe-ctype.h"
#include "block.h"
#include "reggroups.h"
#include "arch-utils.h"
#include "frame.h"
#include "frame-unwind.h"
#include "frame-base.h"
#include "dwarf2-frame.h"
#include "trad-frame.h"

#include <inttypes.h>


/* Forward declarations of support functions for the architecture definition */

static unsigned long int
                     or1k_fetch_instruction (struct frame_info *next_frame,
                                             CORE_ADDR          addr);
static void          or1k_store_instruction( struct frame_info *next_frame,
                                           CORE_ADDR          addr,
                                           unsigned long int  insn);

/* Forward declaration of support functions for frame handling */

static int   or1k_frame_size (struct frame_info *next_frame,
                              CORE_ADDR          func_start_addr);
static int   or1k_frame_fp_loc (struct frame_info *next_frame,
                                CORE_ADDR          func_start_addr);
static int   or1k_frame_size_check (struct frame_info *next_frame,
                                    CORE_ADDR          func_start_addr);
static int   or1k_link_address (struct frame_info *next_frame,
                                CORE_ADDR          func_start_addr);
static int   or1k_get_saved_reg (struct frame_info *next_frame,
                                 CORE_ADDR          instr_start_addr,
                                 int               *reg_offset);
static struct trad_frame_cache
            *or1k_frame_unwind_cache (struct frame_info  *next_frame,
                                      void              **this_prologue_cache);
static void  or1k_frame_this_id (struct frame_info  *next_frame,
                                 void              **this_prologue_cache,
                                 struct frame_id    *this_id);
static void  or1k_frame_prev_register (struct frame_info  *next_frame,
                                       void              **this_prologue_cache,
                                       int                 regnum,
                                       int                *optimizedp,
                                       enum lval_type     *lvalp,
                                       CORE_ADDR          *addrp,
                                       int                *realregp,
                                       gdb_byte           *bufferp);
static CORE_ADDR
             or1k_frame_base_address (struct frame_info  *next_frame,
                                      void              **this_prologue_cache);

/* Forward declarations of functions which define the architecture */

static enum return_value_convention
                        or1k_return_value (struct gdbarch  *gdbarch,
                                           struct type     *type,
                                           struct regcache *regcache,
                                           gdb_byte        *readbuf,
                                           const gdb_byte  *writebuf);
static const gdb_byte  *or1k_breakpoint_from_pc (struct gdbarch *gdbarch,
                                                 CORE_ADDR      *bp_addr,
                                                 int            *bp_size);
static int     or1k_single_step_through_delay (struct gdbarch    *gdbarch,
                                               struct frame_info *this_frame);
static void             or1k_pseudo_register_read (struct gdbarch  *gdbarch,
                                                   struct regcache *regcache,
                                                   int              regnum,
                                                   gdb_byte        *buf);
static void             or1k_pseudo_register_write (struct gdbarch  *gdbarch,
                                                    struct regcache *regcache,
                                                    int              regnum,
                                                    const gdb_byte  *buf);
static const char      *or1k_register_name (struct gdbarch *gdbarch,
                                            int             regnum);
static struct type     *or1k_register_type (struct gdbarch *arch,
                                            int             regnum);
static void             or1k_registers_info (struct gdbarch    *gdbarch,
                                             struct ui_file    *file,
                                             struct frame_info *frame,
                                             int                regnum,
                                             int                all);
static int              or1k_register_reggroup_p (struct gdbarch  *gdbarch,
                                                  int              regnum,
                                                  struct reggroup *group);
static CORE_ADDR        or1k_skip_prologue (struct gdbarch *gdbarch,
                                            CORE_ADDR       pc);
static CORE_ADDR        or1k_frame_align (struct gdbarch *gdbarch,
                                          CORE_ADDR       sp);
static CORE_ADDR        or1k_unwind_pc (struct gdbarch    *gdbarch,
                                        struct frame_info *next_frame);
static CORE_ADDR        or1k_unwind_sp (struct gdbarch    *gdbarch,
                                        struct frame_info *next_frame);
static CORE_ADDR        or1k_push_dummy_call (struct gdbarch  *gdbarch,
                                              struct value    *function,
                                              struct regcache *regcache,
                                              CORE_ADDR        bp_addr,
                                              int              nargs,
                                              struct value   **args,
                                              CORE_ADDR        sp,
                                              int              struct_return,
                                              CORE_ADDR        struct_addr);
static struct frame_id  or1k_unwind_dummy_id (struct gdbarch    *gdbarch,
                                              struct frame_info *next_frame);
static const struct frame_unwind *
                        or1k_frame_sniffer (struct frame_info *next_frame);

/* Forward declaration of architecture set up functions */

static struct gdbarch *or1k_gdbarch_init (struct gdbarch_info  info,
                                          struct gdbarch_list *arches);

static void            or1k_dump_tdep (struct gdbarch *gdbarch,
                                       struct ui_file *file);

/* Forward declarations of functions which extend GDB */

static const char     *or1k_spr_group_name (int  group);
static char           *or1k_spr_register_name (int   group,
                                               int   index,
                                               char *name);
static int             or1k_groupnum_from_name (char *group_name);
static int             or1k_regnum_from_name (int   group,
                                              char *name);
static int             or1k_tokenize (char  *str,
                                      char **tok);
static char           *or1k_parse_spr_params (char *args,
                                              int  *group,
                                              int  *index,
                                              int   is_set);
static ULONGEST        or1k_read_spr (unsigned int  regnum);
static void            or1k_write_spr (unsigned int  regnum,
                                       ULONGEST      data);
static void            info_spr_command (char *args,
                                         int   from_tty);
static void            or1k_spr_command (char *args,
                                         int   from_tty);
static void            info_matchpoints_command (char *args,
                                                 int   from_tty);



/* Support functions for the architecture definition */


/*----------------------------------------------------------------------------*/
/*!Get an instruction from a frame

   This reads from memory, but if the instruction has been substituted by a
   software breakpoint, returns the instruction that has been replaced, NOT
   the break point instruction

   Depending on whether this has a frame available we use a frame based memory
   access or independent memory access. Underneath they are both the same, but
   annoyingly save_frame_unwind_memory inverts the status returned!

   @param[in] next_frame  Information about the next frame.
   @param[in] addr        Address from which to get the instruction

   @return  The instruction */
/*---------------------------------------------------------------------------*/

static unsigned long int
or1k_fetch_instruction (struct frame_info *next_frame,
                        CORE_ADDR          addr)
{
  char  buf[OR1K_INSTLEN];
  int   status;

  struct frame_info *this_frame = get_prev_frame (next_frame);
  if (NULL != this_frame)
    {
      status = !(safe_frame_unwind_memory (this_frame, addr, buf,
                                           OR1K_INSTLEN));
    }
  else
    {
      status = read_memory_nobpt (addr, buf, OR1K_INSTLEN);
    }

  if (0 != status)
    {
      memory_error (status, addr);
    }

  return  (unsigned long int)(extract_unsigned_integer (buf, OR1K_INSTLEN));

} /* or1k_fetch_instruction() */


/*----------------------------------------------------------------------------*/
/*!Store an instruction in a frame

   This writes to memory. Unlike its counterpart to fetch the instruction it
   does nothing about breakpoints

   Depending on whether this has a frame available we use a frame based memory
   access or independent memory access.

   @param[in] next_frame  Information about the next frame. Here for
                          compatibility with the fetch function, but ignored.
   @param[in] addr        Address to which to put the instruction
   @param[in] insn        The instruction to be written */
/*---------------------------------------------------------------------------*/

static void
or1k_store_instruction (struct frame_info *next_frame,
                        CORE_ADDR          addr,
                        unsigned long int  insn)
{
  write_memory_unsigned_integer( addr, sizeof( insn ), insn );

} /* or1k_store_instruction() */





/* Support functions for frame handling */


/*----------------------------------------------------------------------------*/
/*!Return the size of the new stack frame

   Given the function start address, find the size of the stack frame. We are
   looking for the instruction

   @verbatim
   l.addi  r1,r1,-<frame_size>
   @endverbatim

   If this is not found at the start address, then this must be frameless
   invocation, for which we return size 0.

   @see or1k_frame_unwind_cache() for details of the OR1K prolog

   @param[in]  next_frame       The NEXT frame (i.e. inner from here, the one
                                THIS frame called), or NULL if this
                                information is not available.
   @param[in]  instr_addr       Function start address

   @return  The size of the new stack frame, or zero if this is frameless */
/*---------------------------------------------------------------------------*/

static int
or1k_frame_size (struct frame_info *next_frame,
                 CORE_ADDR          instr_addr)
{
  uint32_t  instr  = or1k_fetch_instruction (next_frame, instr_addr);
  int       opcode = OR1K_OPCODE1 (instr);
  int       rd;
  int       ra;
  int       imm;

  if (OR1K_OP_ADDI != opcode)
    {
      return  0;
    }

  rd  = OR1K_D_REG (instr);
  ra  = OR1K_A_REG (instr);
  imm = OR1K_IMM (instr);

  if((OR1K_SP_REGNUM == rd) && (OR1K_SP_REGNUM == ra))
    {
      return  -imm; /* Falling stack */
    }
  else
    {
      return 0;
    }
} /* or1k_frame_size() */


/*----------------------------------------------------------------------------*/
/*!Return the offset from the stack pointer of the saved FP location

   Given the function start address, find the size of the stack frame. We are
   looking for the instruction

   @verbatim
   l.sw    <save_loc>(r1),r2
   @endverbatim

   If this is not found at the start address + 4, then this is an error.

   @see or1k_frame_unwind_cache() for details of the OR1K prolog

   @param[in]  next_frame   The NEXT frame (i.e. inner from here, the one THIS
                            frame called), or NULL if this information is not
                            available.
   @param[in]  instr_addr   Address where we find this instruction (function
                            start + OR1K_INSTLEN)

   @return  The offset from the stack pointer where the old frame pointer is
   saved or -1 if we don't find this instruction. */
/*--------------------------------------------------------------------------*/

static int
or1k_frame_fp_loc (struct frame_info *next_frame,
                   CORE_ADDR          instr_addr)
{
  uint32_t  instr  = or1k_fetch_instruction (next_frame, instr_addr);
  int       opcode = OR1K_OPCODE1 (instr);
  int       ra;
  int       rb;
  int       imm;

  if (OR1K_OP_SW != opcode)
    {
      return  -1;
    }

  ra  = OR1K_A_REG (instr);
  rb  = OR1K_B_REG (instr);
  imm = OR1K_IMM2 (instr);

  if((OR1K_SP_REGNUM != ra) || (OR1K_FP_REGNUM != rb))
    {
      return  -1;
    }

  return imm;

} /* or1k_frame_fp_loc() */


/*----------------------------------------------------------------------------*/
/*!Check the frame size is what expected

   Given the function start address, find the setting of the frame
   pointer. This should choose a frame size matching that used earlier to set
   the stack pointer. We look for the instruction:

   @verbatim
   l.addi  r2,r1,<frame_size>
   @endverbatim

   If this is not found at the start address + 8, with the expected frame size
   then this is an error.

   There is no return value - the function raises an error if the instruction
   is not found.

   @see or1k_frame_unwind_cache() for details of the OR1K prolog

   @param[in]  next_frame  The NEXT frame (i.e. inner from here, the one THIS
                           frame called), or NULL if this information is not
                           available.
   @param[in]  instr_addr  Address where we find this instruction (function
                           start + 2*OR1K_INSTLEN)

                           @return  The frame size found, or -1 if the instruction was not there. */
/*---------------------------------------------------------------------------*/

static int
or1k_frame_size_check (struct frame_info *next_frame,
                       CORE_ADDR          instr_addr)
{
  uint32_t  instr  = or1k_fetch_instruction (next_frame, instr_addr);
  int       opcode = OR1K_OPCODE1 (instr);
  int       rd;
  int       ra;
  int       imm;

  if (OR1K_OP_ADDI != opcode)
    {
      return  -1;
    }

  rd  = OR1K_D_REG (instr);
  ra  = OR1K_A_REG (instr);
  imm = OR1K_IMM (instr);

  if((OR1K_SP_REGNUM != ra) || (OR1K_FP_REGNUM != rd))
    {
      return -1;
    }

  return  imm;

} /* or1k_frame_size_check() */


/*----------------------------------------------------------------------------*/
/*!See if the link (return) address is saved as expected

   Given the function start address, find the saving of the link address. The
   location (as an offset from the stack pointer) should be 4 less than the
   offset where the frame pointer was saved. We look for the instruction:

   @verbatim
   l.sw    <save_loc-4>(r1),r9
   @endverbatim

   This instruction may be missing - leaf functions do not necessarily save
   the return address on the stack.

   @see or1k_frame_unwind_cache() for details of the OR1K prolog

   @param[in]  next_frame  The NEXT frame (i.e. inner from here, the one THIS
                           frame called), or NULL if this information is not
                           available.
   @param[in]  instr_addr  Address where we find this instruction (function
                           start + 12)

                           @return  The link offset if the instruction was found, -1 otherwise */
/*---------------------------------------------------------------------------*/

static int
or1k_link_address (struct frame_info *next_frame,
                   CORE_ADDR          instr_addr)
{
  uint32_t  instr  = or1k_fetch_instruction (next_frame, instr_addr);
  int       opcode = OR1K_OPCODE1 (instr);
  int       ra;
  int       rb;
  int       imm;

  if (OR1K_OP_SW != opcode)
    {
      return  -1;
    }

  ra  = OR1K_A_REG (instr);
  rb  = OR1K_B_REG (instr);
  imm = OR1K_IMM2 (instr);

  if((OR1K_SP_REGNUM != ra) || (OR1K_LR_REGNUM != rb))
    {
      return  -1;
    }

  return  imm;

} /* or1k_link_address() */


/*----------------------------------------------------------------------------*/
/*!Get a saved register's details

   Given an address, see if it contains an instruction to save a register with
   the specified offset from the stack pointer. The locations increment by 4
   from the location where the FP was saved for each callee saved register. We
   look for the instruction:

   @verbatim
   l.sw    x(r1),ry
   @endverbatim

   If this is found with the expected offset (x), then the register number
   (y) is returned. If not -1 is returned (not a register). The register
   must be one of the 10 callee saved registers (r10, r12, r14, r16, r18, r20,
   r22, r24, r26, r28, r30).

   @see or1k_frame_unwind_cache() for details of the OR1K prolog

   @param[in]  next_frame  The NEXT frame (i.e. inner from here, the one THIS
                           frame called), or NULL if this information is not
                           available.
   @param[in]  instr_addr  Location of this instruction
   @param[out] reg_offset  Offset where the register is saved

   @return  The register number if this instruction is found, otherwise -1 */
/*---------------------------------------------------------------------------*/

static int
or1k_get_saved_reg (struct frame_info *next_frame,
                    CORE_ADDR          instr_addr,
                    int               *reg_offset)
{
  uint32_t  instr  = or1k_fetch_instruction (next_frame, instr_addr);
  int       opcode = OR1K_OPCODE1 (instr);
  int       ra;
  int       rb;
  int       imm;

  if (OR1K_OP_SW != opcode)
    {
      return -1;
    }

  ra  = OR1K_A_REG (instr);
  rb  = OR1K_B_REG (instr);
  imm = OR1K_IMM2 (instr);

  if(OR1K_SP_REGNUM != ra)
    {
      return -1;
    }

  if ((1 == (rb % 2)) || rb < 10)
    {
      return  -1; /* Not a callee saved register */
    }

  *reg_offset = imm;
  return  rb;

} /* or1k_get_saved_reg() */


/*----------------------------------------------------------------------------*/
/*!Initialize a prologue (unwind) cache

   Build up the information (saved registers etc) for the given frame if it
   does not already exist.

   The OR1K has a falling stack frame and a simple prolog. The Stack pointer
   is R1 and the frame pointer R2. The frame base is therefore the address
   held in R2 and the stack pointer (R1) is the frame base of the NEXT frame.

   @verbatim
   l.addi  r1,r1,-frame_size # SP now points to end of new stack frame
   l.sw    save_loc(r1),r2      # old FP saved in new stack frame
   l.addi  r2,r1,frame_size     # FP now points to base of new stack frame
   l.sw    save_loc-4(r1),r9    # Link (return) address
   l.sw    x(r1),ry             # Save any callee saved regs
   @endverbatim

   The frame pointer is not necessarily saved right at the end of the stack
   frame - OR1K saves enough space for any args to called functions right at
   the end. The offsets x for the various registers saved always rise in
   increments of 4, starting at save_loc+4.

   This prolog is used, even for -O3 with GCC.

   All this analysis must allow for the possibility that the PC is in the
   middle of the prologue. Data should only be set up insofar as it has been
   computed.

   A suite of "helper" routines are used, allowing reuse for
   or1k_skip_prologue().

   Reportedly, this is only valid for frames less than 0x7fff in size.

   @param[in]     next_frame           The NEXT frame (i.e. inner from here,
                                       the one THIS frame called)
   @param[in,out] this_prologue_cache  The prologue cache. If not supplied, we
                                       build it.

                                       @return  The prolog cache (duplicates the return through the argument) */
/*---------------------------------------------------------------------------*/

static struct trad_frame_cache *
or1k_frame_unwind_cache (struct frame_info  *next_frame,
                         void              **this_prologue_cache)
{
  struct gdbarch          *gdbarch;
  struct trad_frame_cache *info;

  CORE_ADDR                this_pc;
  CORE_ADDR                this_sp;
  int                      frame_size;
  int                      fp_save_offset;
  int                      tmp;

  CORE_ADDR                start_iaddr;
  CORE_ADDR                saved_regs_iaddr;
  CORE_ADDR                prologue_end_iaddr;
  CORE_ADDR                end_iaddr;
 
  int                      regnum;

  /* Nothing to do if we already have this info */
  if (NULL != *this_prologue_cache)
    {
      return *this_prologue_cache;
    }

  gdbarch = get_frame_arch (next_frame);

  /* Get a new prologue cache and populate it with default values */
  info                 = trad_frame_cache_zalloc (next_frame);
  *this_prologue_cache = info;

  /* Find the start address of THIS function (which is a NORMAL frame, even if
     the NEXT frame is the sentinel frame) and the end of its prologue.  */
  start_iaddr        = frame_func_unwind (next_frame, NORMAL_FRAME);
  prologue_end_iaddr = skip_prologue_using_sal (start_iaddr);

  /* Return early if GDB couldn't find the function.  */
  if (start_iaddr == 0)
    {
      return  info;
    }

  /* Unwind key registers for THIS frame. */
  this_pc = or1k_unwind_pc (gdbarch, next_frame);
  this_sp = or1k_unwind_sp (gdbarch, next_frame);

  /* The frame base of THIS frame is its stack pointer. This is the same
     whether we are frameless or not. */
  trad_frame_set_this_base (info, this_sp);

  /* We should only examine code that is in the prologue and which has been
     executed. This is all code up to (but not including) end_iaddr. */
  end_iaddr = (this_pc > prologue_end_iaddr) ? prologue_end_iaddr : this_pc;

  /* The default is to find the PC of the PREVIOUS frame in the link register
     of this frame. This may be changed if we find the link register was saved
     on the stack. */
  trad_frame_set_reg_realreg (info, OR1K_NPC_REGNUM, OR1K_LR_REGNUM);

  /* All the following analysis only occurs if we are in the prologue and have
     executed the code. Get THIS frame size (which implies framelessness if
     zero) */

  if (end_iaddr > start_iaddr)
    {
      frame_size = or1k_frame_size (next_frame, start_iaddr);
    }
  else
    {
      frame_size = 0;
    }

  /* If we are not frameless, check the other standard components are present
     as expected */
  if ((0 != frame_size) && (end_iaddr > (start_iaddr + OR1K_INSTLEN)))
    {
      int  i;

      /* If we are not frameless, the frame pointer of the PREVIOUS frame can
         be found at offset fp_save_offset from the stack pointer in THIS
         frame. */
      fp_save_offset = or1k_frame_fp_loc (next_frame,
                                          start_iaddr + OR1K_INSTLEN);
      if (-1 == fp_save_offset)
        {
          error ("or1k_frame_unwind_cache: "
                 "invalid frame pointer save instruction at address %08llx\n",
                 (long long unsigned int)(ULONGEST)(start_iaddr + OR1K_INSTLEN));
        }
      else
        {
          trad_frame_set_reg_addr (info, OR1K_FP_REGNUM,
                                   this_sp + fp_save_offset);
        }

      /* The frame pointer should be set up to match the allocated stack
         size */
      if (end_iaddr > (start_iaddr + (2 * OR1K_INSTLEN)))
        {
          tmp = or1k_frame_size_check (next_frame,
                                       start_iaddr + (2 * OR1K_INSTLEN));

          if (-1 == tmp)
            {
              error ("or1k_frame_unwind_cache: "
                     "no frame pointer set up instruction at address %08llx\n",
                     (long long unsigned int)(ULONGEST)(start_iaddr + (2 * OR1K_INSTLEN)));
            }
          else if (frame_size != tmp)
            {
              error ("or1k_frame_unwind_cache: "
                     "frame pointer set to wrong size  at address %08llx: "
                     "expected %d, got %d\n",
                     (long long unsigned int)(ULONGEST)(start_iaddr + (2* OR1K_INSTLEN)), frame_size,
                     tmp);
            }
          else
            {
              /* If we have got this far, the stack pointer of the PREVIOUS
                 frame is the frame pointer of THIS frame. */
              trad_frame_set_reg_realreg (info, OR1K_SP_REGNUM, OR1K_FP_REGNUM);
            }
        }
      /* If the link register is saved in the THIS frame, it holds the value
         of the PC in the PREVIOUS frame. This overwrites the previous
         information about finding the PC in the link register. */
      if (end_iaddr > (start_iaddr + (2 * OR1K_INSTLEN)))
        {
          tmp = or1k_link_address (next_frame,
                                   start_iaddr + (3 * OR1K_INSTLEN));
          if ((-1 != tmp) && (tmp == (fp_save_offset - OR1K_INSTLEN)))
            {
              trad_frame_set_reg_addr (info, OR1K_LR_REGNUM, this_sp + tmp);
              trad_frame_set_reg_addr (info, OR1K_NPC_REGNUM, this_sp + tmp);
              saved_regs_iaddr = start_iaddr + (3 * OR1K_INSTLEN);
            }
          else
            {
              saved_regs_iaddr = start_iaddr + (2 * OR1K_INSTLEN);
            }

          /* Retrieve any saved register information */
          for (i = OR1K_INSTLEN;
               saved_regs_iaddr + i < end_iaddr;
               i += OR1K_INSTLEN)
            {
              regnum = or1k_get_saved_reg (next_frame, saved_regs_iaddr + i,
                                           &tmp);

              if ((regnum < 0) || (tmp != (fp_save_offset + i)))
                {
                  break; /* End of register saves */
                }

              /* The register in the PREVIOUS frame can be found at this
                 location in THIS frame */
              trad_frame_set_reg_addr (info, regnum,
                                       this_sp + fp_save_offset + i);
            }
        }
    }

  /* Build the frame ID */
  trad_frame_set_id (info, frame_id_build (this_sp, start_iaddr));

  return info;

} /* or1k_frame_unwind_cache() */


/*----------------------------------------------------------------------------*/
/*!Find the frame ID of this frame

   Given a GDB frame (called by THIS frame), determine the address of oru
   frame and from this create a new GDB frame struct. The info required is
   obtained from the prologue cache for THIS frame.

   @param[in] next_frame            The NEXT frame (i.e. inner from here, the
                                    one THIS frame called)
   @param[in]  this_prologue_cache  Any cached prologue for THIS function.
   @param[out] this_id              Frame ID of our own frame.

   @return  Frame ID for THIS frame */
/*---------------------------------------------------------------------------*/

static void
or1k_frame_this_id (struct frame_info  *next_frame,
                    void              **this_prologue_cache,
                    struct frame_id    *this_id)
{
  struct trad_frame_cache *info =
    or1k_frame_unwind_cache (next_frame, this_prologue_cache);

  trad_frame_get_id (info, this_id);

} /* or1k_frame_this_id() */


/*----------------------------------------------------------------------------*/
/*!Get a register from THIS frame

   Given a pointer to the NEXT frame, return the details of a register in the
   PREVIOUS frame.

   @param[in] next_frame            The NEXT frame (i.e. inner from here, the
                                    one THIS frame called)
   @param[in]  this_prologue_cache  Any cached prologue associated with THIS
                                    frame, which may therefore tell us about
                                    registers in the PREVIOUS frame.
   @param[in]  regnum               The register of interest in the PREVIOUS
                                    frame
   @param[out] optimizedp           True (1) if the register has been
                                    optimized out.
   @param[out] lvalp                What sort of l-value (if any) does the
                                    register represent
   @param[out] addrp                Address in THIS frame where the register's
                                    value may be found (-1 if not available)
   @param[out] realregp             Register in this frame where the
                                    register's value may be found (-1 if not
                                    available)
   @param[out] bufferp              If non-NULL, buffer where the value held
   in the register may be put */
/*--------------------------------------------------------------------------*/

static void
or1k_frame_prev_register (struct frame_info  *next_frame,
                          void              **this_prologue_cache,
                          int                 regnum,
                          int                *optimizedp,
                          enum lval_type     *lvalp,
                          CORE_ADDR          *addrp,
                          int                *realregp,
                          gdb_byte           *bufferp)
{
  struct trad_frame_cache *info =
    or1k_frame_unwind_cache (next_frame, this_prologue_cache);

  trad_frame_get_register (info, next_frame, regnum, optimizedp, lvalp, addrp,
                           realregp, bufferp);

} /* or1k_frame_prev_register() */


/*----------------------------------------------------------------------------*/
/*!Return the base address of the frame

   The commenting in the GDB source code could mean our stack pointer or our
   frame pointer, since we have a falling stack, but index within the frame
   using negative offsets from the FP.

   This seems to be the function used to determine the value of $fp, but the
   value required seems to be the stack pointer, so we return that, even if
   the value of $fp will be wrong.

   @param[in] next_frame            The NEXT frame (i.e. inner from here, the
                                    one THIS frame called)
   @param[in]  this_prologue_cache  Any cached prologue for THIS function.

   @return  The frame base address */
/*---------------------------------------------------------------------------*/

static CORE_ADDR
or1k_frame_base_address (struct frame_info  *next_frame,
                         void              **this_prologue_cache)
{
  return  frame_unwind_register_unsigned (next_frame, OR1K_SP_REGNUM);

} /* or1k_frame_base_address() */




/* Functions defining the architecture */


/*----------------------------------------------------------------------------*/
/*!Determine the return convention used for a given type

   Optionally, fetch or set the return value via "readbuf" or "writebuf"
   respectively using "regcache" for the register values.

   The OpenRISC 1000 returns scalar values via R11 and (for 64 bit values on
   32 bit architectures) R12. Structs and unions are returned by reference,
   with the address in R11

   Throughout use read_memory(), not target_read_memory(), since the address
   may be invalid and we want an error reported (read_memory() is
   target_read_memory() with error reporting).

   @todo This implementation is labelled OR1K, but in fact is just for the 32
         bit version, OR32. This should be made explicit

   @param[in]  gdbarch   The GDB architecture being used
   @param[in]  type      The type of the entity to be returned
   @param[in]  regcache  The register cache
   @param[in]  readbuf   Buffer into which the return value should be written
   @param[out] writebuf  Buffer from which the return value should be written

   @return  The type of return value */
/*---------------------------------------------------------------------------*/

static enum return_value_convention
or1k_return_value (struct gdbarch  *gdbarch,
                   struct type     *type,
                   struct regcache *regcache,
                   gdb_byte        *readbuf,
                   const gdb_byte  *writebuf)
{
  enum type_code  rv_type = TYPE_CODE (type);
  unsigned int    rv_size = TYPE_LENGTH (type);
  ULONGEST        tmp;

  /* Deal with struct/union and large scalars first. Large (> 4 byte) scalars
     are returned via a pointer (despite what is says in the architecture
     document). Result pointed to by R11 */

  if((TYPE_CODE_STRUCT == rv_type) ||
     (TYPE_CODE_UNION  == rv_type) ||
     (rv_size          >  4))
    {
      if (readbuf)
        {
          regcache_cooked_read_unsigned (regcache, OR1K_RV_REGNUM, &tmp);
          read_memory (tmp, readbuf, rv_size);
        }
      if (writebuf)
        {
          regcache_cooked_read_unsigned (regcache, OR1K_RV_REGNUM, &tmp);
          write_memory (tmp, writebuf, rv_size);
        }

      return RETURN_VALUE_ABI_RETURNS_ADDRESS;
    }

  /* 1-4 byte scalars are returned in R11 */

  if (readbuf)
    {
      regcache_cooked_read_unsigned (regcache, OR1K_RV_REGNUM, &tmp);
      store_unsigned_integer (readbuf, rv_size, tmp);
    }
  if (writebuf)
    {
      gdb_byte buf[4];
      memset (buf, 0, sizeof (buf)); /* Pad with zeros if < 4 bytes */

      if (BFD_ENDIAN_BIG == gdbarch_byte_order (gdbarch))
        {
          memcpy (buf + sizeof (buf) - rv_size, writebuf, rv_size);
        }
      else
        {
          memcpy (buf,                          writebuf, rv_size);
        }

      regcache_cooked_write (regcache, OR1K_RV_REGNUM, buf);
    }

  return RETURN_VALUE_REGISTER_CONVENTION;

} /* or1k_return_value() */


/*----------------------------------------------------------------------------*/
/*!Determine the instruction to use for a breakpoint.

   Given the address at which to insert a breakpoint (bp_addr), what will
   that breakpoint be?

   For or1k, we have a breakpoint instruction. Since all or1k instructions
   are 32 bits, this is all we need, regardless of address.

   @param[in]  gdbarch  The GDB architecture being used
   @param[in]  bp_addr  The breakpoint address in question
   @param[out] bp_size  The size of instruction selected

   @return  The chosen breakpoint instruction */
/*---------------------------------------------------------------------------*/

static const gdb_byte *
or1k_breakpoint_from_pc (struct gdbarch *gdbarch,
                         CORE_ADDR      *bp_addr,
                         int            *bp_size)
{
  static const gdb_byte breakpoint[] = OR1K_BRK_INSTR_STRUCT;

  *bp_size = OR1K_INSTLEN;
  return breakpoint;

} /* or1k_breakpoint_from_pc() */


/*----------------------------------------------------------------------------*/
/*!Determine if we are executing a delay slot

   Looks at the instruction at the previous instruction to see if it was one
   with a delay slot.

   @param[in] gdbarch     The GDB architecture being used
   @param[in] this_frame  Information about THIS frame

   @return  1 (true) if this instruction is executing a delay slot, 0 (false)
   otherwise. */
/*--------------------------------------------------------------------------*/

static int
or1k_single_step_through_delay( struct gdbarch    *gdbarch,
                                struct frame_info *this_frame )
{
  struct regcache   *regcache = get_current_regcache ();
  ULONGEST           val;
  CORE_ADDR          ppc;
  int                index;

  /* Get and decode the previous instruction. */
  regcache_cooked_read_unsigned (regcache, OR1K_PPC_REGNUM, &val);
  ppc        = (CORE_ADDR)val;
  index      = insn_decode (or1k_fetch_instruction (this_frame, ppc));

  /* We are only executing a delay slot if the previous instruction was a
     branch or jump. */
  return or32_opcodes[index].flags & OR32_IF_DELAY;

} /* or1k_single_step_through_delay() */


/*----------------------------------------------------------------------------*/
/*!Read a pseudo register

   Since we have no pseudo registers this is a null function for now.

   @todo The floating point and vector registers ought to be done as
         pseudo-registers.

   @param[in]  gdbarch   The GDB architecture to consider
   @param[in]  regcache  The cached register values as an array
   @param[in]  regnum    The register to read
   @param[out] buf       A buffer to put the result in */
/*---------------------------------------------------------------------------*/

static void
or1k_pseudo_register_read (struct gdbarch  *gdbarch,
                           struct regcache *regcache,
                           int              regnum,
                           gdb_byte        *buf)
{
  return;

} /* or1k_pseudo_register_read() */


/*----------------------------------------------------------------------------*/
/*!Write a pseudo register

   Since we have no pseudo registers this is a null function for now.

   @todo The floating point and vector registers ought to be done as
         pseudo-registers.

   @param[in] gdbarch   The GDB architecture to consider
   @param[in] regcache  The cached register values as an array
   @param[in] regnum    The register to read
   @param[in] buf       A buffer with the value to write */
/*---------------------------------------------------------------------------*/

static void
or1k_pseudo_register_write (struct gdbarch  *gdbarch,
                            struct regcache *regcache,
                            int              regnum,
                            const gdb_byte  *buf)
{
  return;

} /* or1k_pseudo_register_write() */


/*----------------------------------------------------------------------------*/
/*!Return the register name for the OpenRISC 1000 architecture

   This version converted to ANSI C, made static and incorporates the static
   table of register names (this is the only place it is referenced).

   @todo The floating point and vector registers ought to be done as
         pseudo-registers.

   @param[in] gdbarch  The GDB architecture being used
   @param[in] regnum    The register number

   @return  The textual name of the register */
/*---------------------------------------------------------------------------*/

static const char *
or1k_register_name (struct gdbarch *gdbarch,
                    int             regnum)
{
  static char *or1k_gdb_reg_names[OR1K_TOTAL_NUM_REGS] =
    {
      /* general purpose registers */
      "gpr0",  "gpr1",  "gpr2",  "gpr3",  "gpr4",  "gpr5",  "gpr6",  "gpr7",
      "gpr8",  "gpr9",  "gpr10", "gpr11", "gpr12", "gpr13", "gpr14", "gpr15",
      "gpr16", "gpr17", "gpr18", "gpr19", "gpr20", "gpr21", "gpr22", "gpr23",
      "gpr24", "gpr25", "gpr26", "gpr27", "gpr28", "gpr29", "gpr30", "gpr31",

      /* previous program counter, next program counter and status register */
      "ppc",   "npc",   "sr"

      /* Floating point and vector registers may appear as pseudo registers in
         the future. */
    };

  return or1k_gdb_reg_names[regnum];

} /* or1k_register_name() */


/*----------------------------------------------------------------------------*/
/*!Identify the type of a register

   @todo I don't fully understand exactly what this does, but I think this
         makes sense!

   @param[in] arch     The GDB architecture to consider
   @param[in] regnum   The register to identify

   @return  The type of the register */
/*---------------------------------------------------------------------------*/

static struct type *
or1k_register_type (struct gdbarch *arch,
                    int             regnum)
{
  static struct type *void_func_ptr = NULL;
  static struct type *void_ptr      = NULL;

  /* Set up the static pointers once, the first time*/
  if (NULL == void_func_ptr)
    {
      void_ptr = lookup_pointer_type (builtin_type_void);
      void_func_ptr =
        lookup_pointer_type (lookup_function_type (builtin_type_void));
    }

  if((regnum >= 0) && (regnum < OR1K_TOTAL_NUM_REGS))
    {
      switch (regnum)
        {
        case OR1K_PPC_REGNUM:
        case OR1K_NPC_REGNUM:
          return void_func_ptr; /* Pointer to code */

        case OR1K_SP_REGNUM:
        case OR1K_FP_REGNUM:
          return void_ptr; /* Pointer to data */

        default:
          return builtin_type_int32; /* Data */
        }
    }

  internal_error (__FILE__, __LINE__,
                  _("or1k_register_type: illegal register number %d"), regnum);

} /* or1k_register_type() */


/*----------------------------------------------------------------------------*/
/*!Handle the "info register" command

   Print the identified register, unless it is -1, in which case print all
   the registers. If all is 1 means all registers, otherwise only the core
   GPRs.

   @todo At present all registers are printed with the default method. Should
         there be something special for FP registers?

   @param[in] gdbarch  The GDB architecture being used
   @param[in] file     File handle for use with any custom I/O
   @param[in] frame    Frame info for use with custom output
   @param[in] regnum   Register of interest, or -1 if all registers
   @param[in] all      1 if all means all, 0 if all means just GPRs
 
   @return  The aligned stack frame address */
/*---------------------------------------------------------------------------*/

static void
or1k_registers_info (struct gdbarch    *gdbarch,
                     struct ui_file    *file,
                     struct frame_info *frame,
                     int                regnum,
                     int                all)
{
  if (-1 == regnum)
    {
      /* Do all (valid) registers */
      unsigned int  lim = all ? OR1K_NUM_REGS : OR1K_MAX_GPR_REGS;

      for (regnum = 0; regnum < lim; regnum++) {
        if ('\0' != *(or1k_register_name (gdbarch, regnum)))
          {
            or1k_registers_info (gdbarch, file, frame, regnum, all);
          }
      }
    }
  else
    {
      /* Do one specified register - if it is part of this architecture */
      if ('\0' == *(or1k_register_name (gdbarch, regnum)))
        {
          error ("Not a valid register for the current processor type");
        }
      else
        {
          default_print_registers_info (gdbarch, file, frame, regnum, all);
        }
    }
} /* or1k_registers_info() */


/*----------------------------------------------------------------------------*/
/*!Identify if a register belongs to a specified group

   Return true if the specified register is a member of the specified
   register group.
 
   These are the groups of registers that can be displayed via "info reg".
 
   @todo The Vector and Floating Point registers ought to be displayed as
         pseudo-registers.
 
   @param[in] gdbarch  The GDB architecture to consider
   @param[in] regnum   The register to consider
   @param[in] group    The group to consider

   @return  True (1) if regnum is a member of group */
/*---------------------------------------------------------------------------*/

static int
or1k_register_reggroup_p (struct gdbarch  *gdbarch,
                          int              regnum,
                          struct reggroup *group)
{
  struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);

  /* All register group */
  if (group == all_reggroup)
    {
      return ((regnum >= 0) &&
              (regnum < OR1K_TOTAL_NUM_REGS) &&
              (or1k_register_name (gdbarch, regnum)[0] != '\0'));
    }

  /* For now everything except the PC */
  if (group == general_reggroup)
    {
      return ((regnum >= OR1K_ZERO_REGNUM) &&
              (regnum <  tdep->num_gpr_regs) &&
              (regnum != OR1K_PPC_REGNUM) &&
              (regnum != OR1K_NPC_REGNUM));
    }

  if (group == float_reggroup)
    {
      return 0; /* No float regs.  */
    }

  if (group == vector_reggroup)
    {
      return 0; /* No vector regs.  */
    }

  /* For any that are not handled above.  */
  return default_register_reggroup_p (gdbarch, regnum, group);

} /* or1k_register_reggroup_p() */


/*----------------------------------------------------------------------------*/
/*!Skip a function prolog

   If the input address, PC, is in a function prologue, return the address of
   the end of the prologue, otherwise return the input  address.

   @see For details of the stack frame, see the function
   or1k_frame_unwind_cache().

   This function reuses the helper functions from or1k_frame_unwind_cache() to
   locate the various parts of the prolog.

   This is very tricky. Essentially we look for the parts of a prolog.  If we
   get a mismatch, we never know if it is because we are not in prolog, or
   because the prolog is broken.

   @param[in] gdbarch  The GDB architecture being used
   @param[in] pc       Current program counter

   @return  The address of the end of the prolog if the PC is in a function
   prologue, otherwise the input  address. */
/*--------------------------------------------------------------------------*/

static CORE_ADDR
or1k_skip_prologue (struct gdbarch *gdbarch,
                    CORE_ADDR       pc)
{
  enum {
    OR1K_FRAME_SIZE,
    OR1K_FP_SAVED,
    OR1K_NEW_FP,
    OR1K_LR_SAVE,
    OR1K_REG_SAVE,
    OR1K_NO_PROLOGUE
  } start_pos = OR1K_NO_PROLOGUE;

  CORE_ADDR  addr     = pc;
  int        frame_size;
  int        fp_save_offset;
  int        tmp;
  int        i;

  CORE_ADDR  start_addr;
  CORE_ADDR  end_addr;
 
  /* Try using SAL first */
  if (find_pc_partial_function (pc, NULL, &start_addr, &end_addr))
    {
      CORE_ADDR  prologue_end = skip_prologue_using_sal( pc );

      if (prologue_end > pc)
        {
          return  prologue_end;
        }
      else
        {
          return  pc;
        }
    }

  frame_size = or1k_frame_size (NULL, addr);

  if (0 != frame_size)
    {
      /* We seem to have the start of a prolog */
      start_pos = OR1K_FRAME_SIZE;
      addr += OR1K_INSTLEN;
    }

  /* Look for the previous frame pointer being saved. If we are in a frame,
     then this must be here. */
  fp_save_offset = or1k_frame_fp_loc (NULL, addr);

  switch (start_pos)
   {
    case OR1K_FRAME_SIZE:
      if (-1 == fp_save_offset)
        {
          error ("or1k_skip_prolog: "
                 "old frame pointer not saved at address %08llx: giving up\n",
                 (long long unsigned int)(ULONGEST)addr);
        }
      else
        {
          addr += OR1K_INSTLEN;
        }

      break;

    default:
      start_pos  = OR1K_FP_SAVED;
      addr      += OR1K_INSTLEN;
      break;
    }

  /* Look for new FP being set up. This must match the frame_size if that is
     known. */
  tmp = or1k_frame_size_check (NULL, addr);
  switch (start_pos)
   {
    case OR1K_FRAME_SIZE:
      if (frame_size != tmp)
        {
          error ("or1k_skip_prolog: "
                 "frame pointer set to wrong size  at address %08llx: "
                 "expected %d, got %d\n", (long long unsigned int)(ULONGEST)addr, frame_size, tmp);
        }
      else
        {
          addr += OR1K_INSTLEN;
        }

      break;

    case OR1K_FP_SAVED:
      if (-1 == tmp)
        {
          error ("or1k_skip_prolog: "
                 "no frame pointer set up instruction at address %08llx\n",
                 (long long unsigned int)(ULONGEST)addr);
        }
      else
        {
          addr += OR1K_INSTLEN;
        }

      break;

    default:
      if (-1 != tmp)
        {
          start_pos  = OR1K_NEW_FP;
          addr      += OR1K_INSTLEN;
        }
    }

  /* Look for the link register being saved. If we are in a prolog sequence,
     and is there then it should save to a particular location. */
  tmp = or1k_link_address (NULL, addr);
  switch (start_pos)
   {
    case OR1K_FRAME_SIZE:
    case OR1K_FP_SAVED:
      if ((-1 != tmp) && (tmp != fp_save_offset - OR1K_INSTLEN))
        {
          error ("or1k_skip_prolog: "
                 "link address saved to wrong offset at address %08llx: "
                 "expected %d, got %d\n", (long long unsigned int)(ULONGEST)addr,
                 fp_save_offset - OR1K_INSTLEN, tmp);
        }
      else
        {
          addr += OR1K_INSTLEN;
        }

      break;

    default:
      if (-1 != tmp)
        {
          start_pos  = OR1K_LR_SAVE;
          addr      += OR1K_INSTLEN;
        }
    }

  /* Skip saved registers */
  for (i = 0;; i += OR1K_INSTLEN)
   {
      int  regnum = or1k_get_saved_reg (NULL, addr, &tmp);

      switch (start_pos)
        {
        case OR1K_FRAME_SIZE:
        case OR1K_FP_SAVED:
          if (-1  != regnum)
           {
              if (tmp != fp_save_offset + ((i - 1) * OR1K_INSTLEN))
                {
                  error ("or1k_skip_prolog: callee register saved to wrong "
                         "offset at address %08llx: "
                         "expected %d, got %d\n", (long long unsigned int)(ULONGEST)addr,
                         fp_save_offset + ((i - 1) * OR1K_INSTLEN), tmp);
                }
              else
                {
                  addr += 4;
                }
            }
          else
           {
              return  addr;
            }

          break;

        case OR1K_NEW_FP:
        case OR1K_LR_SAVE:
        case OR1K_REG_SAVE:
          if (-1 != regnum)
           {
              addr += 4;
            }
          else
           {
              return  addr;
            }

        default:
          if (-1 != regnum)
           {
              start_pos  = OR1K_REG_SAVE;
              addr += 4;
            }
          else
           {
              return  pc; /* Not in a prolog */
            }

          break;
        }
    }
} /* or1k_skip_prologue() */


/*----------------------------------------------------------------------------*/
/*!Align the stack frame

   OpenRISC 1000 uses a falling stack frame, so this aligns down to the
   nearest 8 bytes. Useful when we'be building a dummy frame.

   @param[in] gdbarch  The GDB architecture being used
   @param[in] sp       Current stack pointer

   @return  The aligned stack frame address */
/*---------------------------------------------------------------------------*/

static CORE_ADDR
or1k_frame_align (struct gdbarch *gdbarch,
                  CORE_ADDR       sp)
{
  return align_down (sp, OR1K_STACK_ALIGN);

} /* or1k_frame_align() */


/*----------------------------------------------------------------------------*/
/*!Unwind the program counter from a stack frame

   This just uses the built in frame unwinder

   @param[in] gdbarch     The GDB architecture being used
   @param[in] next_frame  Frame info for the NEXT frame
 
   @return  The program counter for THIS frame */
/*---------------------------------------------------------------------------*/

static CORE_ADDR
or1k_unwind_pc (struct gdbarch    *gdbarch,
                struct frame_info *next_frame)
{
  return frame_unwind_register_unsigned (next_frame, OR1K_NPC_REGNUM);

} /* or1k_unwind_pc() */


/*----------------------------------------------------------------------------*/
/*!Unwind the stack pointer from a stack frame

   This just uses the built in frame unwinder

   @param[in] gdbarch     The GDB architecture being used
   @param[in] next_frame  Frame info for the NEXT frame
 
   @return  The stack pointer for THIS frame */
/*---------------------------------------------------------------------------*/

static CORE_ADDR
or1k_unwind_sp (struct gdbarch    *gdbarch,
                struct frame_info *next_frame)
{
  return frame_unwind_register_unsigned (next_frame, OR1K_SP_REGNUM);

} /* or1k_unwind_sp() */


/*----------------------------------------------------------------------------*/
/*!Create a dummy stack frame

   The arguments are placed in registers and/or pushed on the stack as per the
   OR1K ABI.

   @param[in] gdbarch        The architecture to use
   @param[in] function       Pointer to the function that will be called
   @param[in] regcache       The register cache to use
   @param[in] bp_addr        Breakpoint address
   @param[in] nargs          Number of ags to push
   @param[in] args           The arguments
   @param[in] sp             The stack pointer
   @param[in] struct_return  True (1) if this returns a structure
   @param[in] struct_addr    Address for returning structures

   @return  The updated stack pointer */
/*---------------------------------------------------------------------------*/

static CORE_ADDR
or1k_push_dummy_call (struct gdbarch  *gdbarch,
                      struct value    *function,
                      struct regcache *regcache,
                      CORE_ADDR        bp_addr,
                      int              nargs,
                      struct value   **args,
                      CORE_ADDR        sp,
                      int              struct_return,
                      CORE_ADDR        struct_addr)
{
  int           argreg;
  int           argnum;
  int           first_stack_arg;
  int           stack_offset = 0;

  unsigned int  bpa = (gdbarch_tdep (gdbarch))->bytes_per_address;
  unsigned int  bpw = (gdbarch_tdep (gdbarch))->bytes_per_word;

  /* Return address */
  regcache_cooked_write_unsigned (regcache, OR1K_LR_REGNUM, bp_addr);

  /* Register for the next argument */
  argreg = OR1K_FIRST_ARG_REGNUM;

  /* Location for a returned structure. This is passed as a silent first
     argument. */

  if (struct_return)
    {
      regcache_cooked_write_unsigned (regcache, OR1K_FIRST_ARG_REGNUM,
                                      struct_addr);
      argreg++;
    }

  /* Put as many args as possible in registers */
  for (argnum = 0; argnum < nargs; argnum++)
    {
      char           *val;
      char            valbuf[sizeof (ULONGEST) ];

      struct value   *arg      = args[argnum];
      struct type    *arg_type = check_typedef (value_type (arg));
      int             len      = arg_type->length;
      enum type_code  typecode = arg_type->main_type->code;

      /* The EABI passes structures that do not fit in a register by
         reference. In all other cases, pass the structure by value.  */
      if((len > bpw) &&
         ((TYPE_CODE_STRUCT == typecode) || (TYPE_CODE_UNION == typecode)))
        {

          store_unsigned_integer (valbuf, bpa, value_offset (arg));
          len      = bpa;
          val      = valbuf;
        }
      else
        {
          val = (char *)value_contents (arg);
        }  

      if((len > bpw) && (argreg <= (OR1K_LAST_ARG_REGNUM - 1)))
        {

          /* Big scalars use two registers, must be pair aligned. This code
             breaks if we can have quad-word scalars (e.g. long double). */
          ULONGEST regval = extract_unsigned_integer (val, len);

          gdb_assert (len <= (bpw * 2));

          argreg = 1 == (argreg & 1) ? argreg + 1 : argreg;
          regcache_cooked_write_unsigned (regcache, argreg, regval >> bpw);
          regcache_cooked_write_unsigned (regcache, argreg + 1,
                                          regval && ((ULONGEST)(1 << bpw) - 1));
          argreg += 2;
        }
      else if (argreg <= OR1K_LAST_ARG_REGNUM)
        {
          regcache_cooked_write_unsigned (regcache, argreg,
                                          extract_unsigned_integer (val, len));
          argreg++;
        }
      else
        {
          /* Run out of regs */
          break;
        }
    }

  first_stack_arg = argnum;

  /* If we get here with argnum < nargs, then arguments remain to be placed on
     the stack. This is tricky, since they must be pushed in reverse order and
     the stack in the end must be aligned. The only solution is to do it in
     two stages, the first to compute the stack size, the second to save the
     args. */

  for (argnum = first_stack_arg; argnum < nargs; argnum++)
    {
      struct value   *arg      = args[argnum];
      struct type    *arg_type = check_typedef (value_type (arg));
      int             len      = arg_type->length;
      enum type_code  typecode = arg_type->main_type->code;

      if((len > bpw) &&
         ((TYPE_CODE_STRUCT == typecode) || (TYPE_CODE_UNION == typecode)))
        {
          /* Large structures are passed as addresses */
          sp -= bpa;
        }
      else
        {
        /* Big scalars use more than one word. Code here allows for future
         quad-word entities (e.g. long double) */
          sp -= ((len + bpw - 1) / bpw) * bpw;
        }
    }

  sp           = gdbarch_frame_align (gdbarch, sp);
  stack_offset = 0;

  /* Push the remaining args on the stack */
  for (argnum = first_stack_arg; argnum < nargs; argnum++)
    {
      char           *val;
      char            valbuf[sizeof (ULONGEST) ];

      struct value   *arg      = args[argnum];
      struct type    *arg_type = check_typedef (value_type (arg));
      int             len      = arg_type->length;
      enum type_code  typecode = arg_type->main_type->code;

      /* The EABI passes structures that do not fit in a register by
         reference. In all other cases, pass the structure by value.  */
      if((len > bpw) &&
         ((TYPE_CODE_STRUCT == typecode) || (TYPE_CODE_UNION == typecode)))
        {

          store_unsigned_integer (valbuf, bpa, value_offset (arg));
          len      = bpa;
          val      = valbuf;
        }
      else
        {
          val = (char *)value_contents (arg);
        }  

      gdb_assert (len <= (bpw * 2));

      write_memory (sp + stack_offset, val, len);
      stack_offset += ((len + bpw - 1) / bpw) * bpw;
    }

  /* Save the updated stack pointer */
  regcache_cooked_write_unsigned (regcache, OR1K_SP_REGNUM, sp);

  return sp;

} /* or1k_push_dummy_call() */


/*----------------------------------------------------------------------------*/
/*!Unwind a dummy stack frame

   Tear down a dummy frame created by or1k_push_dummy_call(). This data has to
   be constructed manually from the data in our hand. The frame_id info in
   next_frame is not complete, and a call to unwind it will just recurse to us
   (we think).

   The stack pointer and program counter can be unwound. From the program
   counter, the start of the function can be determined.

   @param[in] gdbarch     The architecture to use
   @param[in] next_frame  Information about the next frame

   @return  Frame ID of the preceding frame */
/*---------------------------------------------------------------------------*/

static struct frame_id
or1k_unwind_dummy_id (struct gdbarch    *gdbarch,
                      struct frame_info *next_frame)
{
  CORE_ADDR  this_sp = gdbarch_unwind_sp (gdbarch, next_frame);
  CORE_ADDR  this_pc = gdbarch_unwind_pc (gdbarch, next_frame);

  CORE_ADDR  start_addr;
  CORE_ADDR  end_addr;
 
  /* Try using SAL to find the true function start. Otherwise the PC will
     have to be a proxy for the start of the function. */
  if (find_pc_partial_function (this_pc, NULL, &start_addr, &end_addr))
    {
      return  frame_id_build (this_sp, start_addr);
    }
  else
    {
      return  frame_id_build (this_sp, this_pc);
    }

} /* or1k_unwind_dummy_id() */


/*----------------------------------------------------------------------------*/
/*!The OpenRISC 1000 registered frame sniffer

   This function just identifies our family of frame sniffing functions.
 
   @param[in] next_frame  The "next" (i.e. inner, newer from here, the one
                          THIS frame called) frame.

                          @return  A pointer to a struct identifying the sniffing functions */
/*---------------------------------------------------------------------------*/

static const struct frame_unwind *
or1k_frame_sniffer (struct frame_info *next_frame)
{
  static const struct frame_unwind or1k_frame_unwind = {
    .type          = NORMAL_FRAME,
    .this_id       = or1k_frame_this_id,
    .prev_register = or1k_frame_prev_register,
    .unwind_data   = NULL,
    .sniffer       = NULL,
    .prev_pc       = NULL,
    .dealloc_cache = NULL
  };

  return  &or1k_frame_unwind;

} /* or1k_frame_sniffer() */


/*----------------------------------------------------------------------------*/
/*!Architecture initialization for OpenRISC 1000

   Looks for a candidate architecture in the list of architectures supplied
   using the info supplied. If none match, create a new architecture.

   @param[in] info    Information about the target architecture
   @param[in] arches  The list of currently know architectures

   @return  A structure describing the target architecture */
/*---------------------------------------------------------------------------*/

static struct gdbarch *
or1k_gdbarch_init (struct gdbarch_info  info,
                   struct gdbarch_list *arches)
{
  static struct frame_base     or1k_frame_base;
  struct        gdbarch       *gdbarch;
  struct        gdbarch_tdep  *tdep;
  const struct  bfd_arch_info *binfo;

  /* Find a candidate among the list of pre-declared architectures.  */
  arches = gdbarch_list_lookup_by_info (arches, &info);
  if (NULL != arches)
    {
      return arches->gdbarch;
    }

  /* None found, create a new architecture from the information
     provided. Can't initialize all the target dependencies until we actually
     know which target we are talking to, but put in some defaults for now. */

  binfo                   = info.bfd_arch_info;
  tdep                    = xmalloc (sizeof *tdep);
  tdep->num_matchpoints   = OR1K_MAX_MATCHPOINTS;
  tdep->num_gpr_regs      = OR1K_MAX_GPR_REGS;
  tdep->bytes_per_word    = binfo->bits_per_word    / binfo->bits_per_byte;
  tdep->bytes_per_address = binfo->bits_per_address / binfo->bits_per_byte;
  gdbarch                 = gdbarch_alloc (&info, tdep);

  /* Target data types.  */
  set_gdbarch_short_bit             (gdbarch, 16);
  set_gdbarch_int_bit               (gdbarch, 32);
  set_gdbarch_long_bit              (gdbarch, 32);
  set_gdbarch_long_long_bit         (gdbarch, 64);
  set_gdbarch_float_bit             (gdbarch, 32);
  set_gdbarch_float_format          (gdbarch, floatformats_ieee_single);
  set_gdbarch_double_bit            (gdbarch, 64);
  set_gdbarch_double_format         (gdbarch, floatformats_ieee_double);
  set_gdbarch_long_double_bit       (gdbarch, 64);
  set_gdbarch_long_double_format    (gdbarch, floatformats_ieee_double);
  set_gdbarch_ptr_bit               (gdbarch, binfo->bits_per_address);
  set_gdbarch_addr_bit              (gdbarch, binfo->bits_per_address);
  set_gdbarch_char_signed           (gdbarch, 1);

  /* Information about the target architecture */
  set_gdbarch_return_value          (gdbarch, or1k_return_value);
  set_gdbarch_breakpoint_from_pc    (gdbarch, or1k_breakpoint_from_pc);
  set_gdbarch_single_step_through_delay
                                    (gdbarch, or1k_single_step_through_delay);
  set_gdbarch_have_nonsteppable_watchpoint
                                    (gdbarch, 1);
  switch (gdbarch_byte_order (gdbarch))
    {
    case BFD_ENDIAN_BIG:
      set_gdbarch_print_insn        (gdbarch, print_insn_big_or32);
      break;

    case BFD_ENDIAN_LITTLE:
      set_gdbarch_print_insn        (gdbarch, print_insn_little_or32);
      break;

    case BFD_ENDIAN_UNKNOWN:
      error ("or1k_gdbarch_init: Unknown endianism");
      break;
    }

  /* Register architecture */
  set_gdbarch_pseudo_register_read  (gdbarch, or1k_pseudo_register_read);
  set_gdbarch_pseudo_register_write (gdbarch, or1k_pseudo_register_write);
  set_gdbarch_num_regs              (gdbarch, OR1K_NUM_REGS);
  set_gdbarch_num_pseudo_regs       (gdbarch, OR1K_NUM_PSEUDO_REGS);
  set_gdbarch_sp_regnum             (gdbarch, OR1K_SP_REGNUM);
  set_gdbarch_pc_regnum             (gdbarch, OR1K_NPC_REGNUM);
  set_gdbarch_ps_regnum             (gdbarch, OR1K_SR_REGNUM);
  set_gdbarch_deprecated_fp_regnum  (gdbarch, OR1K_FP_REGNUM);

  /* Functions to supply register information */
  set_gdbarch_register_name         (gdbarch, or1k_register_name);
  set_gdbarch_register_type         (gdbarch, or1k_register_type);
  set_gdbarch_print_registers_info  (gdbarch, or1k_registers_info);
  set_gdbarch_register_reggroup_p   (gdbarch, or1k_register_reggroup_p);

  /* Functions to analyse frames */
  set_gdbarch_skip_prologue         (gdbarch, or1k_skip_prologue);
  set_gdbarch_inner_than            (gdbarch, core_addr_lessthan);
  set_gdbarch_frame_align           (gdbarch, or1k_frame_align);
  set_gdbarch_frame_red_zone_size   (gdbarch, OR1K_FRAME_RED_ZONE_SIZE);

  /* Functions to access frame data */
  set_gdbarch_unwind_pc             (gdbarch, or1k_unwind_pc);
  set_gdbarch_unwind_sp             (gdbarch, or1k_unwind_sp);

  /* Functions handling dummy frames */
  set_gdbarch_push_dummy_call       (gdbarch, or1k_push_dummy_call);
  set_gdbarch_unwind_dummy_id       (gdbarch, or1k_unwind_dummy_id);

  /* High level frame base sniffer */
  or1k_frame_base.unwind      = or1k_frame_sniffer (NULL);
  or1k_frame_base.this_base   = or1k_frame_base_address;
  or1k_frame_base.this_locals = or1k_frame_base_address;
  or1k_frame_base.this_args   = or1k_frame_base_address;
  frame_base_set_default            (gdbarch, &or1k_frame_base);

  /* Low level frame sniffers */
  frame_unwind_append_sniffer       (gdbarch, dwarf2_frame_sniffer);
  frame_unwind_append_sniffer       (gdbarch, or1k_frame_sniffer);


  return gdbarch;

} /* or1k_gdbarch_init() */


/*----------------------------------------------------------------------------*/
/*!Dump the target specific data for this architecture

   @param[in] gdbarch  The architecture of interest
   @param[in] file     Where to dump the data */
/*---------------------------------------------------------------------------*/

static void
or1k_dump_tdep (struct gdbarch *gdbarch,
                struct ui_file *file)
{
  struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);

  if (NULL == tdep)
    {
      return; /* Nothing to report */
    }

  fprintf_unfiltered (file, "or1k_dump_tdep: %d matchpoints available\n",
                      tdep->num_matchpoints);
  fprintf_unfiltered (file, "or1k_dump_tdep: %d general purpose registers\n",
                      tdep->num_gpr_regs);
  fprintf_unfiltered (file, "or1k_dump_tdep: %d bytes per word\n",
                      tdep->bytes_per_word);
  fprintf_unfiltered (file, "or1k_dump_tdep: %d bytes per address\n",
                      tdep->bytes_per_address);

} /* or1k_dump_tdep() */



/* Functions to add extra commands to GDB */


/*----------------------------------------------------------------------------*/
/*!Returns a special purpose register group name

   @param[in]  group  The SPR group number

   @return  The SPR name (pointer to the name argument) */
/*---------------------------------------------------------------------------*/

static const char *
or1k_spr_group_name (int  group)
{
  static const char *or1k_group_names[OR1K_NUM_SPGS] =
    {
      "SYS",
      "DMMU",
      "IMMU",
      "DCACHE",
      "ICACHE",
      "MAC",
      "DEBUG",
      "PERF",
      "POWER",
      "PIC",
      "TIMER",
      "FPU"
    };

  if ((0 <= group) && (group < OR1K_NUM_SPGS))
    {
      return or1k_group_names[group];
    }
  else
    {
      return "";
    }
} /* or1k_spr_group_name() */


/*----------------------------------------------------------------------------*/
/*!Returns a special purpose register name

   @param[in]  group  The SPR group
   @param[in]  index  The index within the SPR group
   @param[out] name   Array to put the name in

   @return  The SPR name (pointer to the name argument) */
/*---------------------------------------------------------------------------*/

static char *
or1k_spr_register_name (int   group,
                        int   index,
                        char *name)
{
  char di;

  switch (group)
    {

    case OR1K_SPG_SYS:
      /* 1:1 names */
      switch (index)
        {
        case OR1K_SPG_SYS_VR:       sprintf (name, "VR"      ); return  name;
        case OR1K_SPG_SYS_UPR:      sprintf (name, "UPR"     ); return  name;
        case OR1K_SPG_SYS_CPUCFGR:  sprintf (name, "CPUCFGR" ); return  name;
        case OR1K_SPG_SYS_DMMUCFGR: sprintf (name, "DMMUCFGR"); return  name;
        case OR1K_SPG_SYS_IMMUCFGR: sprintf (name, "IMMUCFGR"); return  name;
        case OR1K_SPG_SYS_DCCFGR:   sprintf (name, "DCCFGR"  ); return  name;
        case OR1K_SPG_SYS_ICCFGR:   sprintf (name, "ICCFGR"  ); return  name;
        case OR1K_SPG_SYS_DCFGR:    sprintf (name, "DCFGR"   ); return  name;
        case OR1K_SPG_SYS_PCCFGR:   sprintf (name, "PCCFGR"  ); return  name;
        case OR1K_SPG_SYS_NPC:      sprintf (name, "NPC"     ); return  name;
        case OR1K_SPG_SYS_SR:       sprintf (name, "SR"      ); return  name;
        case OR1K_SPG_SYS_PPC:      sprintf (name, "PPC"     ); return  name;
        case OR1K_SPG_SYS_FPCSR:    sprintf (name, "FPCSR"   ); return  name;
        }

      /* Exception PC regs */
      if((OR1K_SPG_SYS_EPCR <= index) &&
         (index             <= OR1K_SPG_SYS_EPCR_END))
        {
          sprintf (name, "EPCR%d", index - OR1K_SPG_SYS_EPCR);
          return  name;
        }

      /* Exception EA regs */
      if((OR1K_SPG_SYS_EEAR <= index) &&
         (index             <= OR1K_SPG_SYS_EEAR_END))
        {
          sprintf (name, "EEAR%d", index - OR1K_SPG_SYS_EEAR);
          return  name;
        }

      /* Exception SR regs */
      if((OR1K_SPG_SYS_ESR <= index) &&
         (index            <= OR1K_SPG_SYS_ESR_END))
        {
          sprintf (name, "ESR%d", index - OR1K_SPG_SYS_ESR);
          return  name;
        }

      /* GPRs */
      if((OR1K_SPG_SYS_GPR <= index) &&
         (index            <= OR1K_SPG_SYS_GPR_END))
        {
          sprintf (name, "GPR%d", index - OR1K_SPG_SYS_GPR);
          return  name;
        }

      break;

    case OR1K_SPG_DMMU:
    case OR1K_SPG_IMMU:
      /* MMU registers. Use DMMU constants throughout, but these are identical
         to the corresponding IMMU constants */
      di = OR1K_SPG_DMMU == group ? 'D' : 'I';

      /* 1:1 names */
      switch (index)
        {
        case OR1K_SPG_DMMU_DMMUCR:
          sprintf (name, "%cMMUCR",  di); return  name;
        case OR1K_SPG_DMMU_DMMUPR:
          sprintf (name, "%cMMUPR",  di); return  name;
        case OR1K_SPG_DMMU_DTLBEIR:
          sprintf (name, "%cTLBEIR", di); return  name;
        }

      /* ATB Match registers */
      if((OR1K_SPG_DMMU_DATBMR <= index) &&
         (index                <= OR1K_SPG_DMMU_DATBMR_END))
        {
          sprintf (name, "%cATBMR%d", di, index - OR1K_SPG_DMMU_DATBMR);
          return  name;
        }

      /* ATB Translate registers */
      if((OR1K_SPG_DMMU_DATBTR <= index) &&
         (index                <= OR1K_SPG_DMMU_DATBTR_END))
        {
          sprintf (name, "%cATBTR%d", di, index - OR1K_SPG_DMMU_DATBTR);
          return  name;
        }

      /* TLB Way 1 Match registers */
      if((OR1K_SPG_DMMU_DTLBW1MR <= index) &&
         (index                <= OR1K_SPG_DMMU_DTLBW1MR_END))
        {
          sprintf (name, "%cTLBW1MR%d", di, index - OR1K_SPG_DMMU_DTLBW1MR);
          return  name;
        }

      /* TLB Way 1 Translate registers */
      if((OR1K_SPG_DMMU_DTLBW1TR <= index) &&
         (index                <= OR1K_SPG_DMMU_DTLBW1TR_END))
        {
          sprintf (name, "%cTLBW1TR%d", di, index - OR1K_SPG_DMMU_DTLBW1TR);
          return  name;
        }

      /* TLB Way 2 Match registers */
      if((OR1K_SPG_DMMU_DTLBW2MR <= index) &&
         (index                <= OR1K_SPG_DMMU_DTLBW2MR_END))
        {
          sprintf (name, "%cTLBW2MR%d", di, index - OR1K_SPG_DMMU_DTLBW2MR);
          return  name;
        }

      /* TLB Way 2 Translate registers */
      if((OR1K_SPG_DMMU_DTLBW2TR <= index) &&
         (index                <= OR1K_SPG_DMMU_DTLBW2TR_END))
        {
          sprintf (name, "%cTLBW2TR%d", di, index - OR1K_SPG_DMMU_DTLBW2TR);
          return  name;
        }

      /* TLB Way 3 Match registers */
      if((OR1K_SPG_DMMU_DTLBW3MR <= index) &&
         (index                <= OR1K_SPG_DMMU_DTLBW3MR_END))
        {
          sprintf (name, "%cTLBW3MR%d", di, index - OR1K_SPG_DMMU_DTLBW3MR);
          return  name;
        }

      /* TLB Way 3 Translate registers */
      if((OR1K_SPG_DMMU_DTLBW3TR <= index) &&
         (index                <= OR1K_SPG_DMMU_DTLBW3TR_END))
        {
          sprintf (name, "%cTLBW3TR%d", di, index - OR1K_SPG_DMMU_DTLBW3TR);
          return  name;
        }

      break;

    case OR1K_SPG_DC:
      /* Data cache registers. These do not have an exact correspondence with
         their instruction cache counterparts, so must be done separately. */

      /* 1:1 names */
      switch (index)
        {
        case OR1K_SPG_DC_DCCR:  sprintf (name, "DCCR" ); return  name;
        case OR1K_SPG_DC_DCBPR: sprintf (name, "DCBPR"); return  name;
        case OR1K_SPG_DC_DCBFR: sprintf (name, "DCBFR"); return  name;
        case OR1K_SPG_DC_DCBIR: sprintf (name, "DCBIR"); return  name;
        case OR1K_SPG_DC_DCBWR: sprintf (name, "DCBWR"); return  name;
        case OR1K_SPG_DC_DCBLR: sprintf (name, "DCBLR"); return  name;
        }

      break;

    case OR1K_SPG_IC:
      /* Instruction cache registers */

      /* 1:1 names */
      switch (index)
        {
        case OR1K_SPG_IC_ICCR:  sprintf (name, "ICCR" ); return  name;
        case OR1K_SPG_IC_ICBPR: sprintf (name, "ICBPR"); return  name;
        case OR1K_SPG_IC_ICBIR: sprintf (name, "ICBIR"); return  name;
        case OR1K_SPG_IC_ICBLR: sprintf (name, "ICBLR"); return  name;
        }

      break;

    case OR1K_SPG_MAC:
      /* MAC registers */

      /* 1:1 names */
      switch (index)
        {
        case OR1K_SPG_MAC_MACLO: sprintf (name, "MACLO"); return  name;
        case OR1K_SPG_MAC_MACHI: sprintf (name, "MACHI"); return  name;
        }

      break;

    case OR1K_SPG_DEBUG:
      /* Debug registers */

      /* Debug Value registers */
      if((OR1K_SPG_DEBUG_DVR <= index) &&
         (index                <= OR1K_SPG_DEBUG_DVR_END))
        {
          sprintf (name, "DVR%d", index - OR1K_SPG_DEBUG_DVR);
          return  name;
        }

      /* Debug Control registers */
      if((OR1K_SPG_DEBUG_DCR <= index) &&
         (index                <= OR1K_SPG_DEBUG_DCR_END))
        {
          sprintf (name, "DCR%d", index - OR1K_SPG_DEBUG_DCR);
          return  name;
        }

      /* 1:1 names */
      switch (index)
        {
        case OR1K_SPG_DEBUG_DMR1:  sprintf (name, "DMR1" ); return  name;
        case OR1K_SPG_DEBUG_DMR2:  sprintf (name, "DMR2" ); return  name;
        case OR1K_SPG_DEBUG_DCWR0: sprintf (name, "DCWR0"); return  name;
        case OR1K_SPG_DEBUG_DCWR1: sprintf (name, "DCWR1"); return  name;
        case OR1K_SPG_DEBUG_DSR:   sprintf (name, "DSR"  ); return  name;
        case OR1K_SPG_DEBUG_DRR:   sprintf (name, "DRR"  ); return  name;
        }

      break;

    case OR1K_SPG_PC:
      /* Performance Counter registers */

      /* Performance Counters Count registers */
      if((OR1K_SPG_PC_PCCR <= index) &&
         (index                <= OR1K_SPG_PC_PCCR_END))
        {
          sprintf (name, "PCCR%d", index - OR1K_SPG_PC_PCCR);
          return  name;
        }

      /* Performance Counters Mode registers */
      if((OR1K_SPG_PC_PCMR <= index) &&
         (index                <= OR1K_SPG_PC_PCMR_END))
        {
          sprintf (name, "PCMR%d", index - OR1K_SPG_PC_PCMR);
          return  name;
        }

      break;

    case OR1K_SPG_PM:
      /* Power Management registers */

      /* 1:1 names */
      switch (index)
        {
        case OR1K_SPG_PM_PMR:  sprintf (name, "PMR"); return  name;
        }

      break;

    case OR1K_SPG_PIC:
      /* Programmable Interrupt Controller registers */

      /* 1:1 names */
      switch (index)
        {
        case OR1K_SPG_PIC_PICMR:  sprintf (name, "PICMR"); return  name;
        case OR1K_SPG_PIC_PICSR:  sprintf (name, "PICSR"); return  name;
        }

      break;

    case OR1K_SPG_TT:
      /* Tick Timer registers */

      /* 1:1 names */
      switch (index)
        {
        case OR1K_SPG_TT_TTMR:  sprintf (name, "TTMR"); return  name;
        case OR1K_SPG_TT_TTCR:  sprintf (name, "TTCR"); return  name;
        }

      break;

    case OR1K_SPG_FPU:

      break;
    }

  /* Not a recognized register */
  strcpy (name, "");
  return  name;

} /* or1k_spr_register_name() */


/*----------------------------------------------------------------------------*/
/*!Get SPR group number from a name

   @param[in] group_name  SPR register group

   @return  The index, or negative if no match. */
/*----------------------------------------------------------------------------*/

static int
or1k_groupnum_from_name (char *group_name)
{
  int  group;

  for (group = 0; group < OR1K_NUM_SPGS; group++)
    {
      if (0 == strcasecmp (group_name, or1k_spr_group_name (group)))
        {
          return group;
        }
    }

  return -1;

} /* or1k_groupnum_from_name() */


/*----------------------------------------------------------------------------*/
/*!Get register index in special purpose register group from name

   The name may either be SPR<group_num>_<index> or a known unique name. In
   either case the group number must match the supplied group number.

   @param[in] group  SPR register group
   @param[in] name   Register name

   @return  The index, or negative if no match. */
/*----------------------------------------------------------------------------*/

static int
or1k_regnum_from_name (int   group,
                       char *name)
{
  /* Last valid register in each group. */
  static const int  or1k_spr_group_last[OR1K_NUM_SPGS] =
    {
      OR1K_SPG_SYS_LAST,
      OR1K_SPG_DMMU_LAST,
      OR1K_SPG_IMMU_LAST,
      OR1K_SPG_DC_LAST,
      OR1K_SPG_IC_LAST,
      OR1K_SPG_MAC_LAST,
      OR1K_SPG_DEBUG_LAST,
      OR1K_SPG_PC_LAST,
      OR1K_SPG_PM_LAST,
      OR1K_SPG_PIC_LAST,
      OR1K_SPG_TT_LAST,
      OR1K_SPG_FPU_LAST
    };

  int  i;
  char  spr_name[32];

  if (0 == strcasecmp (name, "SPR"))
    {
      char *ptr_c;      

      /* Skip SPR */
      name += 3;

      /* Get group number */
      i = (int) strtoul (name, &ptr_c, 10);
      if (*ptr_c != '_' || i != group)
        {
          return -1;
        }

      /* Get index */
      ptr_c++;
      i = (int) strtoul (name, &ptr_c, 10);
      if (*ptr_c)
        {
          return -1;
        }
      else
        {
          return  i;
        }
    }

  /* Look for a "known" name in this group */
  for (i = 0; i <= or1k_spr_group_last[group]; i++)
    {
      char *s = or1k_spr_register_name (group, i, spr_name);

      if (0 == strcasecmp (name, s))
        {
          return i;
        }
    }

  /* Failure */
  return -1;

} /* or1k_regnum_from_name() */


/*----------------------------------------------------------------------------*/
/*!Get the next token from a string

   I can't believe there isn't a library argument for this, but strtok is
   deprecated.

   Take a string and find the start of the next token and its length. A token
   is anything containing non-blank characters.

   @param[in]  str  The string to look at (may be NULL).
   @param[out] tok  Pointer to the start of the token within str. May be NULL
                    if this result is not wanted (e.g. just the length is
                    wanted. If no token is found will be the NULL char at the
                    end of the string, if the original str was NULL, this will
                    be NULL.

                    @return  The length of the token found */
/*----------------------------------------------------------------------------*/

static int
or1k_tokenize (char  *str,
               char **tok)
{
  char *ptr;
  int   len;

  /* Deal with NULL argument */
  if (NULL == str)
    {
      if (NULL != tok)
        {
          *tok = NULL;
        }
      return 0;
    }

  /* Find the start */
  for (ptr = str; ISBLANK (*ptr) ; ptr++)
    {
      continue;
    }

  /* Return the start pointer if requested */
  if (NULL != tok)
    {
      *tok = ptr;
    }

  /* Find the end and put in EOS */
  for (len = 0;  ('\0' != ptr[len]) && (!ISBLANK (ptr[len])); len++)
    {
      continue;
    }

  return len;

} /* or1k_tokenize() */


/*----------------------------------------------------------------------------*/
/*!Parses args for spr commands

   Determines the special purpose register (SPR) name and puts result into
   group and index

   Syntax is:

   @verbatim
   <spr_args>    -> <group_ref> | <reg_name>
   <group_ref>   -> <group_id> <index>
   <group_id>    -> <group_num> | <group_name>
   @endverbatim

   Where the indices/names have to be valid.

   So to parse, we look for 1 or 2 args. If 1 it must be a unique register
   name. If 2, the first must be a group number or name and the second an
   index within that group.

   Also responsible for providing diagnostics if the arguments do not match.

   Rewritten for GDB 6.8 to use the new UI calls and remove assorted
   bugs. Syntax also slightly restricted to be more comprehensible.

   @param[in]  arg_str  The argument string
   @param[out] group    The group this SPR belongs in, or -1 to indicate
                        failure
   @param[out] index    Index of the register within the group, or -1 to
                        indicate the whole group
   @param[in]  is_set   1 (true) if we are called from the "spr" command (so
                        there is an extra arg) rather than the "info spr"
                        command. Needed to distinguish between the case where
                        info is sought from a register specified as group and
                        index and setting a uniquely identified register to a
                        value.

                        @return  A pointer to any remaining args */
/*---------------------------------------------------------------------------*/

static char *
or1k_parse_spr_params (char *arg_str,
                       int  *group,
                       int  *index,
                       int   is_set)
{
  struct {
    char              *str;
    int                len;
    unsigned long int  val;
    int                is_num;
  } arg[3] = {
    {
      .str    = NULL,
      .len    = 0,
      .val    = 0,
      .is_num = 0,
    },
   {
      .str    = NULL,
      .len    = 0,
      .val    = 0,
      .is_num = 0,
    },
   {
      .str    = NULL,
      .len    = 0,
      .val    = 0,
      .is_num = 0,
    }
  };

  int   num_args;
  char *trailer  = arg_str;
  char *tmp_str;
  int   i;

  char  spr_name[32];

  /* Break out the arguments. Note that the strings are NOT null terminated
     (we don't want to change arg_str), so we must rely on len. The stroul
     call will still work, since there is always a non-digit char (possibly EOS)
     after the last digit. */
  if (NULL == arg_str)
    {
      num_args = 0;
    }
  else
    {
      for (num_args = 0; num_args < 3; num_args++)
        {
          arg[num_args].len = or1k_tokenize (trailer, &(arg[num_args].str));
          trailer           = arg[num_args].str + arg[num_args].len;

          if (0 == arg[num_args].len)
            {
              break;
            }
        }
    }

  /* Patch nulls into the arg strings and see about values. Couldn't do this
     earlier, since we needed the next char clean to check later args. This
     means advancing trailer, UNLESS it was already at EOS */

  if((NULL != arg_str) && ('\0' != *trailer))
    {
      trailer++;
    }

  for (i = 0; i < num_args; i++)
    {
      (arg[i].str)[arg[i].len] = '\0';
      errno                    = 0;
      arg[i].val               = strtoul (arg[i].str, &tmp_str, 0);
      arg[i].is_num            = (0 == errno) && ('\0' == *tmp_str);
    }

  /* Deal with the case where we are setting a register, so the final argument
     should be disregarded (it is the trailer). Do this anyway if we get a
     third argument */
  if ((is_set & (num_args > 0)) || (num_args > 2))
    {
      trailer = arg[num_args - 1].str;
      num_args--;
    }

  /* Deal with different numbers of args */

  switch (num_args)
    {

    case 0:
      ui_out_message (uiout, 0,
                      "Usage: <command> <register>      |\n"
                      "       <command> <group>         |\n"
                      "       <command> <group> <index>\n"
                      "Valid groups are:\n");
      for (i = 0; i < OR1K_NUM_SPGS; i++)
        {
          ui_out_field_string (uiout, NULL, or1k_spr_group_name  (i));
          ui_out_spaces (uiout, 1);
          ui_out_wrap_hint (uiout, NULL);
        }
      ui_out_field_string (uiout, NULL, "\n");

      *index = -1;
      return  trailer;

    case 1:
      /* See if it is a numeric group */
      if (arg[0].is_num)
        {
          if (arg[0].val < OR1K_NUM_SPGS)
            {
              *group = arg[0].val;
              *index = -1;
              return trailer;
            }
          else
            {
              ui_out_message (uiout, 0,
                              "Group index should be in the range 0 - %d\n",
                              OR1K_NUM_SPGS);
              *group = -1;
              *index = -1;
              return trailer;
            }
        }

      /* Is is it a group name? */
      *group = or1k_groupnum_from_name (arg[0].str);
      if (*group >= 0)
        {
          *index = -1;
          return trailer;
        }

      /* See if it is a valid register name in any group */
      for (*group = 0; *group < OR1K_NUM_SPGS; (*group)++)
        {
          *index = or1k_regnum_from_name (*group, arg[0].str);
     
          if (*index >= 0)
            {
              return  trailer;
            }
        }

      /* Couldn't find it - print out a rude message */
      ui_out_message (uiout, 0,
                      "Group or register name not recognized.\n"
                      "Valid groups are:\n");
      for (i = 0; i < OR1K_NUM_SPGS; i++)
        {
          ui_out_field_string (uiout, NULL, or1k_spr_group_name (i));
          ui_out_spaces (uiout, 1);
          ui_out_wrap_hint (uiout, NULL);
        }
      ui_out_field_string (uiout, NULL, "\n");

      *group = -1;
      *index = -1;
      return  trailer;

    case 2:
      /* See if first arg is a numeric group */
      if (arg[0].is_num)
        {
          if (arg[0].val < OR1K_NUM_SPGS)
            {
              *group = arg[0].val;
              *index = -1;
            }
          else
            {
              ui_out_message (uiout, 0,
                              "Group index should be in the range 0 - %d\n",
                              OR1K_NUM_SPGS - 1);
              *group = -1;
              *index = -1;
              return trailer;
            }
        }
      else
        {
          /* Is is it a group name? */
          *group = or1k_groupnum_from_name (arg[0].str);
          if (*group >= 0)
            {
              *index = -1;
            }
          else
            {
              ui_out_message (uiout, 0,
                              "Group name not recognized.\n"
                              "Valid groups are:\n");
              for (i = 0; i < OR1K_NUM_SPGS; i++)
                {
                  ui_out_field_string (uiout, NULL, or1k_spr_group_name (i));
                  ui_out_spaces (uiout, 1);
                  ui_out_wrap_hint (uiout, NULL);
                }
              ui_out_field_string (uiout, NULL, "\n");

              *group = -1;
              *index = -1;
              return  trailer;
            }
        }

      /* Is second arg an index or name? */
      if (arg[1].is_num)
        {
          if (arg[1].val < OR1K_SPG_SIZE)
            {
              /* Check this really is a register */
              if (0 != strlen (or1k_spr_register_name (*group, arg[1].val,
                                                       spr_name)))
                {
                  *index = arg[1].val;
                  return trailer;
                }
              else
                {
                  ui_out_message (uiout, 0,
                                  "No valid register at that index in group\n");
                  *group = -1;
                  *index = -1;
                  return  trailer;
                }
            }
          else
            {
              ui_out_message (uiout, 0,
                              "Register index should be in the range 0 - %d\n",
                              OR1K_SPG_SIZE - 1);
              *group = -1;
              *index = -1;
              return  trailer;
            }
        }

      /* Must be a name */
      *index = or1k_regnum_from_name (*group, arg[1].str);
     
      if (*index >= 0)
        {
          return trailer;
        }

      /* Couldn't find it - print out a rude message */
      ui_out_message (uiout, 0, "Register name not recognized in group.\n");
      *group = -1;
      *index = -1;
      return  trailer;
   
    default:
      /* Anything else is an error */
      ui_out_message (uiout, 0, "Unable to parse arguments\n");
      *group = -1;
      *index = -1;
      return  trailer;
    }
} /* or1k_parse_spr_params() */


/*---------------------------------------------------------------------------*/
/*!Read a special purpose register from the target

   This has to be done using the target remote command "readspr"

   @param[in] regnum  The register to read

   @return  The value read */
/*---------------------------------------------------------------------------*/

static ULONGEST
or1k_read_spr (unsigned int  regnum)
{
  struct ui_file    *uibuf = mem_fileopen ();
  char               cmd[sizeof ("readspr ffff")];
  unsigned long int  data;
  char              *res;
  long int           len;

  /* Create the command string and pass it to target remote command function */
  sprintf (cmd, "readspr %4x", regnum);
  target_rcmd (cmd, uibuf);

  /* Get the output for the UI file as a string */
  res = ui_file_xstrdup (uibuf, &len);
  sscanf (res, "%lx", &data);

  /* Tidy up */
  xfree (res);
  ui_file_delete (uibuf);

  return  (ULONGEST)data;

} /* or1k_read_spr() */


/*---------------------------------------------------------------------------*/
/*!Write a special purpose register on the target

   This has to be done using the target remote command "writespr"

   Since the SPRs may map to GPR's or the other GDB register (PPC, NPC, SR),
   any register cache is flushed.

   @param[in] regnum  The register to write
   @param[in] data  The value to write */
/*---------------------------------------------------------------------------*/

static void
or1k_write_spr (unsigned int  regnum,
                ULONGEST      data)
{
  struct ui_file    *uibuf = mem_fileopen ();
  char               cmd[sizeof ("writespr ffff ffffffff")];
  char              *res;
  long int           len;

  /* Create the command string and pass it to target remote command function */
  sprintf (cmd, "writespr %4x %8llx", regnum, (long long unsigned int)data);
  target_rcmd (cmd, uibuf);

  /* Flush the register cache */
  registers_changed ();

  /* We ignore the result - Rcmd can put out its own error messages. Just
     tidy up */
  ui_file_delete (uibuf);

} /* or1k_write_spr() */


/*----------------------------------------------------------------------------*/
/*!Show the value of a special purpose register or group

   This is a custom extension to the GDB info command.

   @param[in] args
   @param[in] from_tty  True (1) if GDB is running from a TTY, false (0)
   otherwise. */
/*---------------------------------------------------------------------------*/

static void
or1k_info_spr_command (char *args,
                       int   from_tty)
{
  int  group;
  int  index;

  char  spr_name[32];

  or1k_parse_spr_params (args, &group, &index, 0);

  if (group < 0)
    {
      return; /* Couldn't parse the args */
    }

  if (index >= 0)
    {
      ULONGEST  value = or1k_read_spr (OR1K_SPR (group, index));

      ui_out_field_fmt (uiout, NULL, "%s.%s = SPR%i_%i = %llu (0x%llx)\n",
                        or1k_spr_group_name (group),
                        or1k_spr_register_name (group, index, spr_name), group,
                        index, (long long unsigned int)value, (long long unsigned int)value);
    }
  else
    {
      /* Print all valid registers in the group */
      for (index = 0; index < OR1K_SPG_SIZE; index++)
        {
          if (0 != strlen (or1k_spr_register_name (group, index, spr_name)))
            {
              ULONGEST  value = or1k_read_spr (OR1K_SPR (group, index));

              ui_out_field_fmt (uiout, NULL,
                                "%s.%s = SPR%i_%i = %llu (0x%llx)\n",
                                or1k_spr_group_name (group),
                                or1k_spr_register_name (group, index, spr_name),
                                group, index, (long long unsigned int)value, (long long unsigned int)value);
            }
        }
    }
} /* or1k_info_spr_command() */


/*----------------------------------------------------------------------------*/
/*!Set a special purpose register

   This is a custom command added to GDB.

   @param[in] args
   @param[in] from_tty  True (1) if GDB is running from a TTY, false (0)
   otherwise. */
/*---------------------------------------------------------------------------*/

static void
or1k_spr_command (char *args,
                  int   from_tty)
{
  int   group;
  int   index;
  char *tmp_str;
  char *nargs = or1k_parse_spr_params (args, &group, &index, 1);

  ULONGEST  old_val;
  ULONGEST  new_val;

  char  spr_name[32];

  /* Do we have a valid register spec? */
  if (index < 0)
    {
      return; /* Parser will have printed the error message */
    }

  /* Do we have a value to set? */

  errno = 0;
  new_val = (ULONGEST)strtoul (nargs, &tmp_str, 0);

  if((0 != errno) || ('\0' != *tmp_str))
    {
      ui_out_message (uiout, 0, "Invalid value - register not changed\n");
      return;
    }

  old_val = or1k_read_spr (OR1K_SPR (group, index));

  or1k_write_spr (OR1K_SPR (group, index) , new_val);

  ui_out_field_fmt (uiout, NULL,
                    "%s.%s (SPR%i_%i) set to %llu (0x%llx), "
                    "was: %llu (0x%llx)\n",
                    or1k_spr_group_name (group),
                    or1k_spr_register_name (group, index, spr_name) , group,
                    index, (long long unsigned int)new_val, (long long unsigned int)new_val, (long long unsigned int)old_val, (long long unsigned int)old_val);

} /* or1k_spr_command() */


/*----------------------------------------------------------------------------*/
/*!Main entry point for target architecture initialization

   In this version initializes the architecture via
   registers_gdbarch_init(). Add a command to set and show special purpose
   registers. */
/*---------------------------------------------------------------------------*/

void
_initialize_or1k_tdep (void)
{
  /* Register this architecture. We should do this for or16 and or64 when
     they have their BFD defined. */
  gdbarch_register (bfd_arch_or32, or1k_gdbarch_init, or1k_dump_tdep);

  /* Initialize the automata for the assembler */
  build_automata();

  /* Commands to show and set special purpose registers */
  add_info ("spr", or1k_info_spr_command,
            "Show the value of a special purpose register");
  add_com ("spr", class_support, or1k_spr_command,
           "Set a special purpose register");

} /* _initialize_or1k_tdep() */


[or1k-tdep.c]

/* Target-dependent code for the or1k architecture, for GDB, the GNU Debugger.

   Copyright 1988-2008, Free Software Foundation, Inc.
   Copyright (C) 2008 Embecosm Limited

   Contributed by Alessandro Forin(af@... at CMU
   and by Per Bothner(bothner@...) at U.Wisconsin.
   Contributor Jeremy Bennett <jeremy.bennett@...>

   This file is part of GDB.

   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 the Free
   Software Foundation; either version 3 of the License, or (at your option)
   any later version.

   This program is distributed in the hope that it will be useful, but WITHOUT
   ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
   FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
   more details.

   You should have received a copy of the GNU General Public License along
   with this program.  If not, see <http://www.gnu.org/licenses/>.  */

/*-----------------------------------------------------------------------------
   This version for the OpenRISC 1000 architecture is a rewrite by Jeremy
   Bennett of the old GDB 5.3 interface to make use of gdbarch for GDB 6.8.

   The code tries to follow the GDB coding style.

   Commenting is Doxygen compatible.

   Much has been stripped out in the interests of getting a basic working
   system. This is described as the OpenRISC 1000 target architecture, so
   should work with 16, 32 and 64 bit versions of that architecture and should
   work whether or not they have floating point and/or vector registers.

   There was never a capability to run simulator commands (no remote target
   implemented the required function), so that has been removed.

   The info trace command has been removed. The meaning of this is not clear -
   it relies on a value in register 255 of the debug group, which is
   undocumented.

   All the hardware trace has been removed for the time being. The new debug
   interface does not support hardware trace, so there is no plan to reinstate
   this functionality.

   Support for multiple contexts (which was rudimentary, and not working) has
   been removed. */
/*---------------------------------------------------------------------------*/

#include "demangle.h"
#include "defs.h"
#include "gdb_string.h"
#include "frame.h"
#include "inferior.h"
#include "symtab.h"
#include "value.h"
#include "gdbcmd.h"
#include "language.h"
#include "gdbcore.h"
#include "symfile.h"
#include "objfiles.h"
#include "gdbtypes.h"
#include "target.h"
#include "regcache.h"

#include "opcode/or32.h"
#include "or1k-tdep.h"

#include "safe-ctype.h"
#include "block.h"
#include "reggroups.h"
#include "arch-utils.h"
#include "frame.h"
#include "frame-unwind.h"
#include "frame-base.h"
#include "dwarf2-frame.h"
#include "trad-frame.h"

#include <inttypes.h>


/* Forward declarations of support functions for the architecture definition */

static unsigned long int
                     or1k_fetch_instruction (struct frame_info *next_frame,
                                             CORE_ADDR          addr);
static void          or1k_store_instruction( struct frame_info *next_frame,
                                           CORE_ADDR          addr,
                                           unsigned long int  insn);

/* Forward declaration of support functions for frame handling */

static int   or1k_frame_size (struct frame_info *next_frame,
                              CORE_ADDR          func_start_addr);
static int   or1k_frame_fp_loc (struct frame_info *next_frame,
                                CORE_ADDR          func_start_addr);
static int   or1k_frame_size_check (struct frame_info *next_frame,
                                    CORE_ADDR          func_start_addr);
static int   or1k_link_address (struct frame_info *next_frame,
                                CORE_ADDR          func_start_addr);
static int   or1k_get_saved_reg (struct frame_info *next_frame,
                                 CORE_ADDR          instr_start_addr,
                                 int               *reg_offset);
static struct trad_frame_cache
            *or1k_frame_unwind_cache (struct frame_info  *next_frame,
                                      void              **this_prologue_cache);
static void  or1k_frame_this_id (struct frame_info  *next_frame,
                                 void              **this_prologue_cache,
                                 struct frame_id    *this_id);
static void  or1k_frame_prev_register (struct frame_info  *next_frame,
                                       void              **this_prologue_cache,
                                       int                 regnum,
                                       int                *optimizedp,
                                       enum lval_type     *lvalp,
                                       CORE_ADDR          *addrp,
                                       int                *realregp,
                                       gdb_byte           *bufferp);
static CORE_ADDR
             or1k_frame_base_address (struct frame_info  *next_frame,
                                      void              **this_prologue_cache);

/* Forward declarations of functions which define the architecture */

static enum return_value_convention
                        or1k_return_value (struct gdbarch  *gdbarch,
                                           struct type     *type,
                                           struct regcache *regcache,
                                           gdb_byte        *readbuf,
                                           const gdb_byte  *writebuf);
static const gdb_byte  *or1k_breakpoint_from_pc (struct gdbarch *gdbarch,
                                                 CORE_ADDR      *bp_addr,
                                                 int            *bp_size);
static int     or1k_single_step_through_delay (struct gdbarch    *gdbarch,
                                               struct frame_info *this_frame);
static void             or1k_pseudo_register_read (struct gdbarch  *gdbarch,
                                                   struct regcache *regcache,
                                                   int              regnum,
                                                   gdb_byte        *buf);
static void             or1k_pseudo_register_write (struct gdbarch  *gdbarch,
                                                    struct regcache *regcache,
                                                    int              regnum,
                                                    const gdb_byte  *buf);
static const char      *or1k_register_name (struct gdbarch *gdbarch,
                                            int             regnum);
static struct type     *or1k_register_type (struct gdbarch *arch,
                                            int             regnum);
static void             or1k_registers_info (struct gdbarch    *gdbarch,
                                             struct ui_file    *file,
                                             struct frame_info *frame,
                                             int                regnum,
                                             int                all);
static int              or1k_register_reggroup_p (struct gdbarch  *gdbarch,
                                                  int              regnum,
                                                  struct reggroup *group);
static CORE_ADDR        or1k_skip_prologue (struct gdbarch *gdbarch,
                                            CORE_ADDR       pc);
static CORE_ADDR        or1k_frame_align (struct gdbarch *gdbarch,
                                          CORE_ADDR       sp);
static CORE_ADDR        or1k_unwind_pc (struct gdbarch    *gdbarch,
                                        struct frame_info *next_frame);
static CORE_ADDR        or1k_unwind_sp (struct gdbarch    *gdbarch,
                                        struct frame_info *next_frame);
static CORE_ADDR        or1k_push_dummy_call (struct gdbarch  *gdbarch,
                                              struct value    *function,
                                              struct regcache *regcache,
                                              CORE_ADDR        bp_addr,
                                              int              nargs,
                                              struct value   **args,
                                              CORE_ADDR        sp,
                                              int              struct_return,
                                              CORE_ADDR        struct_addr);
static struct frame_id  or1k_unwind_dummy_id (struct gdbarch    *gdbarch,
                                              struct frame_info *next_frame);
static const struct frame_unwind *
                        or1k_frame_sniffer (struct frame_info *next_frame);

/* Forward declaration of architecture set up functions */

static struct gdbarch *or1k_gdbarch_init (struct gdbarch_info  info,
                                          struct gdbarch_list *arches);

static void            or1k_dump_tdep (struct gdbarch *gdbarch,
                                       struct ui_file *file);

/* Forward declarations of functions which extend GDB */

static const char     *or1k_spr_group_name (int  group);
static char           *or1k_spr_register_name (int   group,
                                               int   index,
                                               char *name);
static int             or1k_groupnum_from_name (char *group_name);
static int             or1k_regnum_from_name (int   group,
                                              char *name);
static int             or1k_tokenize (char  *str,
                                      char **tok);
static char           *or1k_parse_spr_params (char *args,
                                              int  *group,
                                              int  *index,
                                              int   is_set);
static ULONGEST        or1k_read_spr (unsigned int  regnum);
static void            or1k_write_spr (unsigned int  regnum,
                                       ULONGEST      data);
static void            info_spr_command (char *args,
                                         int   from_tty);
static void            or1k_spr_command (char *args,
                                         int   from_tty);
static void            info_matchpoints_command (char *args,
                                                 int   from_tty);



/* Support functions for the architecture definition */


/*----------------------------------------------------------------------------*/
/*!Get an instruction from a frame

   This reads from memory, but if the instruction has been substituted by a
   software breakpoint, returns the instruction that has been replaced, NOT
   the break point instruction

   Depending on whether this has a frame available we use a frame based memory
   access or independent memory access. Underneath they are both the same, but
   annoyingly save_frame_unwind_memory inverts the status returned!

   @param[in] next_frame  Information about the next frame.
   @param[in] addr        Address from which to get the instruction

   @return  The instruction */
/*---------------------------------------------------------------------------*/

static unsigned long int
or1k_fetch_instruction (struct frame_info *next_frame,
                        CORE_ADDR          addr)
{
  char  buf[OR1K_INSTLEN];
  int   status;

  struct frame_info *this_frame = get_prev_frame (next_frame);
  if (NULL != this_frame)
    {
      status = !(safe_frame_unwind_memory (this_frame, addr, buf,
                                           OR1K_INSTLEN));
    }
  else
    {
      status = read_memory_nobpt (addr, buf, OR1K_INSTLEN);
    }

  if (0 != status)
    {
      memory_error (status, addr);
    }

  return  (unsigned long int)(extract_unsigned_integer (buf, OR1K_INSTLEN));

} /* or1k_fetch_instruction() */


/*----------------------------------------------------------------------------*/
/*!Store an instruction in a frame

   This writes to memory. Unlike its counterpart to fetch the instruction it
   does nothing about breakpoints

   Depending on whether this has a frame available we use a frame based memory
   access or independent memory access.

   @param[in] next_frame  Information about the next frame. Here for
                          compatibility with the fetch function, but ignored.
   @param[in] addr        Address to which to put the instruction
   @param[in] insn        The instruction to be written */
/*---------------------------------------------------------------------------*/

static void
or1k_store_instruction (struct frame_info *next_frame,
                        CORE_ADDR          addr,
                        unsigned long int  insn)
{
  write_memory_unsigned_integer( addr, sizeof( insn ), insn );

} /* or1k_store_instruction() */





/* Support functions for frame handling */


/*----------------------------------------------------------------------------*/
/*!Return the size of the new stack frame

   Given the function start address, find the size of the stack frame. We are
   looking for the instruction

   @verbatim
   l.addi  r1,r1,-<frame_size>
   @endverbatim

   If this is not found at the start address, then this must be frameless
   invocation, for which we return size 0.

   @see or1k_frame_unwind_cache() for details of the OR1K prolog

   @param[in]  next_frame       The NEXT frame (i.e. inner from here, the one
                                THIS frame called), or NULL if this
                                information is not available.
   @param[in]  instr_addr       Function start address

   @return  The size of the new stack frame, or zero if this is frameless */
/*---------------------------------------------------------------------------*/

static int
or1k_frame_size (struct frame_info *next_frame,
                 CORE_ADDR          instr_addr)
{
  uint32_t  instr  = or1k_fetch_instruction (next_frame, instr_addr);
  int       opcode = OR1K_OPCODE1 (instr);
  int       rd;
  int       ra;
  int       imm;

  if (OR1K_OP_ADDI != opcode)
    {
      return  0;
    }

  rd  = OR1K_D_REG (instr);
  ra  = OR1K_A_REG (instr);
  imm = OR1K_IMM (instr);

  if((OR1K_SP_REGNUM == rd) && (OR1K_SP_REGNUM == ra))
    {
      return  -imm; /* Falling stack */
    }
  else
    {
      return 0;
    }
} /* or1k_frame_size() */


/*----------------------------------------------------------------------------*/
/*!Return the offset from the stack pointer of the saved FP location

   Given the function start address, find the size of the stack frame. We are
   looking for the instruction

   @verbatim
   l.sw    <save_loc>(r1),r2
   @endverbatim

   If this is not found at the start address + 4, then this is an error.

   @see or1k_frame_unwind_cache() for details of the OR1K prolog

   @param[in]  next_frame   The NEXT frame (i.e. inner from here, the one THIS
                            frame called), or NULL if this information is not
                            available.
   @param[in]  instr_addr   Address where we find this instruction (function
                            start + OR1K_INSTLEN)

   @return  The offset from the stack pointer where the old frame pointer is
   saved or -1 if we don't find this instruction. */
/*--------------------------------------------------------------------------*/

static int
or1k_frame_fp_loc (struct frame_info *next_frame,
                   CORE_ADDR          instr_addr)
{
  uint32_t  instr  = or1k_fetch_instruction (next_frame, instr_addr);
  int       opcode = OR1K_OPCODE1 (instr);
  int       ra;
  int       rb;
  int       imm;

  if (OR1K_OP_SW != opcode)
    {
      return  -1;
    }

  ra  = OR1K_A_REG (instr);
  rb  = OR1K_B_REG (instr);
  imm = OR1K_IMM2 (instr);

  if((OR1K_SP_REGNUM != ra) || (OR1K_FP_REGNUM != rb))
    {
      return  -1;
    }

  return imm;

} /* or1k_frame_fp_loc() */


/*----------------------------------------------------------------------------*/
/*!Check the frame size is what expected

   Given the function start address, find the setting of the frame
   pointer. This should choose a frame size matching that used earlier to set
   the stack pointer. We look for the instruction:

   @verbatim
   l.addi  r2,r1,<frame_size>
   @endverbatim

   If this is not found at the start address + 8, with the expected frame size
   then this is an error.

   There is no return value - the function raises an error if the instruction
   is not found.

   @see or1k_frame_unwind_cache() for details of the OR1K prolog

   @param[in]  next_frame  The NEXT frame (i.e. inner from here, the one THIS
                           frame called), or NULL if this information is not
                           available.
   @param[in]  instr_addr  Address where we find this instruction (function
                           start + 2*OR1K_INSTLEN)

                           @return  The frame size found, or -1 if the instruction was not there. */
/*---------------------------------------------------------------------------*/

static int
or1k_frame_size_check (struct frame_info *next_frame,
                       CORE_ADDR          instr_addr)
{
  uint32_t  instr  = or1k_fetch_instruction (next_frame, instr_addr);
  int       opcode = OR1K_OPCODE1 (instr);
  int       rd;
  int       ra;
  int       imm;

  if (OR1K_OP_ADDI != opcode)
    {
      return  -1;
    }

  rd  = OR1K_D_REG (instr);
  ra  = OR1K_A_REG (instr);
  imm = OR1K_IMM (instr);

  if((OR1K_SP_REGNUM != ra) || (OR1K_FP_REGNUM != rd))
    {
      return -1;
    }

  return  imm;

} /* or1k_frame_size_check() */


/*----------------------------------------------------------------------------*/
/*!See if the link (return) address is saved as expected

   Given the function start address, find the saving of the link address. The
   location (as an offset from the stack pointer) should be 4 less than the
   offset where the frame pointer was saved. We look for the instruction:

   @verbatim
   l.sw    <save_loc-4>(r1),r9
   @endverbatim

   This instruction may be missing - leaf functions do not necessarily save
   the return address on the stack.

   @see or1k_frame_unwind_cache() for details of the OR1K prolog

   @param[in]  next_frame  The NEXT frame (i.e. inner from here, the one THIS
                           frame called), or NULL if this information is not
                           available.
   @param[in]  instr_addr  Address where we find this instruction (function
                           start + 12)

                           @return  The link offset if the instruction was found, -1 otherwise */
/*---------------------------------------------------------------------------*/

static int
or1k_link_address (struct frame_info *next_frame,
                   CORE_ADDR          instr_addr)
{
  uint32_t  instr  = or1k_fetch_instruction (next_frame, instr_addr);
  int       opcode = OR1K_OPCODE1 (instr);
  int       ra;
  int       rb;
  int       imm;

  if (OR1K_OP_SW != opcode)
    {
      return  -1;
    }

  ra  = OR1K_A_REG (instr);
  rb  = OR1K_B_REG (instr);
  imm = OR1K_IMM2 (instr);

  if((OR1K_SP_REGNUM != ra) || (OR1K_LR_REGNUM != rb))
    {
      return  -1;
    }

  return  imm;

} /* or1k_link_address() */


/*----------------------------------------------------------------------------*/
/*!Get a saved register's details

   Given an address, see if it contains an instruction to save a register with
   the specified offset from the stack pointer. The locations increment by 4
   from the location where the FP was saved for each callee saved register. We
   look for the instruction:

   @verbatim
   l.sw    x(r1),ry
   @endverbatim

   If this is found with the expected offset (x), then the register number
   (y) is returned. If not -1 is returned (not a register). The register
   must be one of the 10 callee saved registers (r10, r12, r14, r16, r18, r20,
   r22, r24, r26, r28, r30).

   @see or1k_frame_unwind_cache() for details of the OR1K prolog

   @param[in]  next_frame  The NEXT frame (i.e. inner from here, the one THIS
                           frame called), or NULL if this information is not
                           available.
   @param[in]  instr_addr  Location of this instruction
   @param[out] reg_offset  Offset where the register is saved

   @return  The register number if this instruction is found, otherwise -1 */
/*---------------------------------------------------------------------------*/

static int
or1k_get_saved_reg (struct frame_info *next_frame,
                    CORE_ADDR          instr_addr,
                    int               *reg_offset)
{
  uint32_t  instr  = or1k_fetch_instruction (next_frame, instr_addr);
  int       opcode = OR1K_OPCODE1 (instr);
  int       ra;
  int       rb;
  int       imm;

  if (OR1K_OP_SW != opcode)
    {
      return -1;
    }

  ra  = OR1K_A_REG (instr);
  rb  = OR1K_B_REG (instr);
  imm = OR1K_IMM2 (instr);

  if(OR1K_SP_REGNUM != ra)
    {
      return -1;
    }

  if ((1 == (rb % 2)) || rb < 10)
    {
      return  -1; /* Not a callee saved register */
    }

  *reg_offset = imm;
  return  rb;

} /* or1k_get_saved_reg() */


/*----------------------------------------------------------------------------*/
/*!Initialize a prologue (unwind) cache

   Build up the information (saved registers etc) for the given frame if it
   does not already exist.

   The OR1K has a falling stack frame and a simple prolog. The Stack pointer
   is R1 and the frame pointer R2. The frame base is therefore the address
   held in R2 and the stack pointer (R1) is the frame base of the NEXT frame.

   @verbatim
   l.addi  r1,r1,-frame_size # SP now points to end of new stack frame
   l.sw    save_loc(r1),r2      # old FP saved in new stack frame
   l.addi  r2,r1,frame_size     # FP now points to base of new stack frame
   l.sw    save_loc-4(r1),r9    # Link (return) address
   l.sw    x(r1),ry             # Save any callee saved regs
   @endverbatim

   The frame pointer is not necessarily saved right at the end of the stack
   frame - OR1K saves enough space for any args to called functions right at
   the end. The offsets x for the various registers saved always rise in
   increments of 4, starting at save_loc+4.

   This prolog is used, even for -O3 with GCC.

   All this analysis must allow for the possibility that the PC is in the
   middle of the prologue. Data should only be set up insofar as it has been
   computed.

   A suite of "helper" routines are used, allowing reuse for
   or1k_skip_prologue().

   Reportedly, this is only valid for frames less than 0x7fff in size.

   @param[in]     next_frame           The NEXT frame (i.e. inner from here,
                                       the one THIS frame called)
   @param[in,out] this_prologue_cache  The prologue cache. If not supplied, we
                                       build it.

                                       @return  The prolog cache (duplicates the return through the argument) */
/*---------------------------------------------------------------------------*/

static struct trad_frame_cache *
or1k_frame_unwind_cache (struct frame_info  *next_frame,
                         void              **this_prologue_cache)
{
  struct gdbarch          *gdbarch;
  struct trad_frame_cache *info;

  CORE_ADDR                this_pc;
  CORE_ADDR                this_sp;
  int                      frame_size;
  int                      fp_save_offset;
  int                      tmp;

  CORE_ADDR                start_iaddr;
  CORE_ADDR                saved_regs_iaddr;
  CORE_ADDR                prologue_end_iaddr;
  CORE_ADDR                end_iaddr;
 
  int                      regnum;

  /* Nothing to do if we already have this info */
  if (NULL != *this_prologue_cache)
    {
      return *this_prologue_cache;
    }

  gdbarch = get_frame_arch (next_frame);

  /* Get a new prologue cache and populate it with default values */
  info                 = trad_frame_cache_zalloc (next_frame);
  *this_prologue_cache = info;

  /* Find the start address of THIS function (which is a NORMAL frame, even if
     the NEXT frame is the sentinel frame) and the end of its prologue.  */
  start_iaddr        = frame_func_unwind (next_frame, NORMAL_FRAME);
  prologue_end_iaddr = skip_prologue_using_sal (start_iaddr);

  /* Return early if GDB couldn't find the function.  */
  if (start_iaddr == 0)
    {
      return  info;
    }

  /* Unwind key registers for THIS frame. */
  this_pc = or1k_unwind_pc (gdbarch, next_frame);
  this_sp = or1k_unwind_sp (gdbarch, next_frame);

  /* The frame base of THIS frame is its stack pointer. This is the same
     whether we are frameless or not. */
  trad_frame_set_this_base (info, this_sp);

  /* We should only examine code that is in the prologue and which has been
     executed. This is all code up to (but not including) end_iaddr. */
  end_iaddr = (this_pc > prologue_end_iaddr) ? prologue_end_iaddr : this_pc;

  /* The default is to find the PC of the PREVIOUS frame in the link register
     of this frame. This may be changed if we find the link register was saved
     on the stack. */
  trad_frame_set_reg_realreg (info, OR1K_NPC_REGNUM, OR1K_LR_REGNUM);

  /* All the following analysis only occurs if we are in the prologue and have
     executed the code. Get THIS frame size (which implies framelessness if
     zero) */

  if (end_iaddr > start_iaddr)
    {
      frame_size = or1k_frame_size (next_frame, start_iaddr);
    }
  else
    {
      frame_size = 0;
    }

  /* If we are not frameless, check the other standard components are present
     as expected */
  if ((0 != frame_size) && (end_iaddr > (start_iaddr + OR1K_INSTLEN)))
    {
      int  i;

      /* If we are not frameless, the frame pointer of the PREVIOUS frame can
         be found at offset fp_save_offset from the stack pointer in THIS
         frame. */
      fp_save_offset = or1k_frame_fp_loc (next_frame,
                                          start_iaddr + OR1K_INSTLEN);
      if (-1 == fp_save_offset)
        {
          error ("or1k_frame_unwind_cache: "
                 "invalid frame pointer save instruction at address %08llx\n",
                 (long long unsigned int)(ULONGEST)(start_iaddr + OR1K_INSTLEN));
        }
      else
        {
          trad_frame_set_reg_addr (info, OR1K_FP_REGNUM,
                                   this_sp + fp_save_offset);
        }

      /* The frame pointer should be set up to match the allocated stack
         size */
      if (end_iaddr > (start_iaddr + (2 * OR1K_INSTLEN)))
        {
          tmp = or1k_frame_size_check (next_frame,
                                       start_iaddr + (2 * OR1K_INSTLEN));

          if (-1 == tmp)
            {
              error ("or1k_frame_unwind_cache: "
                     "no frame pointer set up instruction at address %08llx\n",
                     (long long unsigned int)(ULONGEST)(start_iaddr + (2 * OR1K_INSTLEN)));
            }
          else if (frame_size != tmp)
            {
              error ("or1k_frame_unwind_cache: "
                     "frame pointer set to wrong size  at address %08llx: "
                     "expected %d, got %d\n",
                     (long long unsigned int)(ULONGEST)(start_iaddr + (2* OR1K_INSTLEN)), frame_size,
                     tmp);
            }
          else
            {
              /* If we have got this far, the stack pointer of the PREVIOUS
                 frame is the frame pointer of THIS frame. */
              trad_frame_set_reg_realreg (info, OR1K_SP_REGNUM, OR1K_FP_REGNUM);
            }
        }
      /* If the link register is saved in the THIS frame, it holds the value
         of the PC in the PREVIOUS frame. This overwrites the previous
         information about finding the PC in the link register. */
      if (end_iaddr > (start_iaddr + (2 * OR1K_INSTLEN)))
        {
          tmp = or1k_link_address (next_frame,
                                   start_iaddr + (3 * OR1K_INSTLEN));
          if ((-1 != tmp) && (tmp == (fp_save_offset - OR1K_INSTLEN)))
            {
              trad_frame_set_reg_addr (info, OR1K_LR_REGNUM, this_sp + tmp);
              trad_frame_set_reg_addr (info, OR1K_NPC_REGNUM, this_sp + tmp);
              saved_regs_iaddr = start_iaddr + (3 * OR1K_INSTLEN);
            }
          else
            {
              saved_regs_iaddr = start_iaddr + (2 * OR1K_INSTLEN);
            }

          /* Retrieve any saved register information */
          for (i = OR1K_INSTLEN;
               saved_regs_iaddr + i < end_iaddr;
               i += OR1K_INSTLEN)
            {
              regnum = or1k_get_saved_reg (next_frame, saved_regs_iaddr + i,
                                           &tmp);

              if ((regnum < 0) || (tmp != (fp_save_offset + i)))
                {
                  break; /* End of register saves */
                }

              /* The register in the PREVIOUS frame can be found at this
                 location in THIS frame */
              trad_frame_set_reg_addr (info, regnum,
                                       this_sp + fp_save_offset + i);
            }
        }
    }

  /* Build the frame ID */
  trad_frame_set_id (info, frame_id_build (this_sp, start_iaddr));

  return info;

} /* or1k_frame_unwind_cache() */


/*----------------------------------------------------------------------------*/
/*!Find the frame ID of this frame

   Given a GDB frame (called by THIS frame), determine the address of oru
   frame and from this create a new GDB frame struct. The info required is
   obtained from the prologue cache for THIS frame.

   @param[in] next_frame            The NEXT frame (i.e. inner from here, the
                                    one THIS frame called)
   @param[in]  this_prologue_cache  Any cached prologue for THIS function.
   @param[out] this_id              Frame ID of our own frame.

   @return  Frame ID for THIS frame */
/*---------------------------------------------------------------------------*/

static void
or1k_frame_this_id (struct frame_info  *next_frame,
                    void              **this_prologue_cache,
                    struct frame_id    *this_id)
{
  struct trad_frame_cache *info =
    or1k_frame_unwind_cache (next_frame, this_prologue_cache);

  trad_frame_get_id (info, this_id);

} /* or1k_frame_this_id() */


/*----------------------------------------------------------------------------*/
/*!Get a register from THIS frame

   Given a pointer to the NEXT frame, return the details of a register in the
   PREVIOUS frame.

   @param[in] next_frame            The NEXT frame (i.e. inner from here, the
                                    one THIS frame called)
   @param[in]  this_prologue_cache  Any cached prologue associated with THIS
                                    frame, which may therefore tell us about
                                    registers in the PREVIOUS frame.
   @param[in]  regnum               The register of interest in the PREVIOUS
                                    frame
   @param[out] optimizedp           True (1) if the register has been
                                    optimized out.
   @param[out] lvalp                What sort of l-value (if any) does the
                                    register represent
   @param[out] addrp                Address in THIS frame where the register's
                                    value may be found (-1 if not available)
   @param[out] realregp             Register in this frame where the
                                    register's value may be found (-1 if not
                                    available)
   @param[out] bufferp              If non-NULL, buffer where the value held
   in the register may be put */
/*--------------------------------------------------------------------------*/

static void
or1k_frame_prev_register (struct frame_info  *next_frame,
                          void              **this_prologue_cache,
                          int                 regnum,
                          int                *optimizedp,
                          enum lval_type     *lvalp,
                          CORE_ADDR          *addrp,
                          int                *realregp,
                          gdb_byte           *bufferp)
{
  struct trad_frame_cache *info =
    or1k_frame_unwind_cache (next_frame, this_prologue_cache);

  trad_frame_get_register (info, next_frame, regnum, optimizedp, lvalp, addrp,
                           realregp, bufferp);

} /* or1k_frame_prev_register() */


/*----------------------------------------------------------------------------*/
/*!Return the base address of the frame

   The commenting in the GDB source code could mean our stack pointer or our
   frame pointer, since we have a falling stack, but index within the frame
   using negative offsets from the FP.

   This seems to be the function used to determine the value of $fp, but the
   value required seems to be the stack pointer, so we return that, even if
   the value of $fp will be wrong.

   @param[in] next_frame            The NEXT frame (i.e. inner from here, the
                                    one THIS frame called)
   @param[in]  this_prologue_cache  Any cached prologue for THIS function.

   @return  The frame base address */
/*---------------------------------------------------------------------------*/

static CORE_ADDR
or1k_frame_base_address (struct frame_info  *next_frame,
                         void              **this_prologue_cache)
{
  return  frame_unwind_register_unsigned (next_frame, OR1K_SP_REGNUM);

} /* or1k_frame_base_address() */




/* Functions defining the architecture */


/*----------------------------------------------------------------------------*/
/*!Determine the return convention used for a given type

   Optionally, fetch or set the return value via "readbuf" or "writebuf"
   respectively using "regcache" for the register values.

   The OpenRISC 1000 returns scalar values via R11 and (for 64 bit values on
   32 bit architectures) R12. Structs and unions are returned by reference,
   with the address in R11

   Throughout use read_memory(), not target_read_memory(), since the address
   may be invalid and we want an error reported (read_memory() is
   target_read_memory() with error reporting).

   @todo This implementation is labelled OR1K, but in fact is just for the 32
         bit version, OR32. This should be made explicit

   @param[in]  gdbarch   The GDB architecture being used
   @param[in]  type      The type of the entity to be returned
   @param[in]  regcache  The register cache
   @param[in]  readbuf   Buffer into which the return value should be written
   @param[out] writebuf  Buffer from which the return value should be written

   @return  The type of return value */
/*---------------------------------------------------------------------------*/

static enum return_value_convention
or1k_return_value (struct gdbarch  *gdbarch,
                   struct type     *type,
                   struct regcache *regcache,
                   gdb_byte        *readbuf,
                   const gdb_byte  *writebuf)
{
  enum type_code  rv_type = TYPE_CODE (type);
  unsigned int    rv_size = TYPE_LENGTH (type);
  ULONGEST        tmp;

  /* Deal with struct/union and large scalars first. Large (> 4 byte) scalars
     are returned via a pointer (despite what is says in the architecture
     document). Result pointed to by R11 */

  if((TYPE_CODE_STRUCT == rv_type) ||
     (TYPE_CODE_UNION  == rv_type) ||
     (rv_size          >  4))
    {
      if (readbuf)
        {
          regcache_cooked_read_unsigned (regcache, OR1K_RV_REGNUM, &tmp);
          read_memory (tmp, readbuf, rv_size);
        }
      if (writebuf)
        {
          regcache_cooked_read_unsigned (regcache, OR1K_RV_REGNUM, &tmp);
          write_memory (tmp, writebuf, rv_size);
        }

      return RETURN_VALUE_ABI_RETURNS_ADDRESS;
    }

  /* 1-4 byte scalars are returned in R11 */

  if (readbuf)
    {
      regcache_cooked_read_unsigned (regcache, OR1K_RV_REGNUM, &tmp);
      store_unsigned_integer (readbuf, rv_size, tmp);
    }
  if (writebuf)
    {
      gdb_byte buf[4];
      memset (buf, 0, sizeof (buf)); /* Pad with zeros if < 4 bytes */

      if (BFD_ENDIAN_BIG == gdbarch_byte_order (gdbarch))
        {
          memcpy (buf + sizeof (buf) - rv_size, writebuf, rv_size);
        }
      else
        {
          memcpy (buf,                          writebuf, rv_size);
        }

      regcache_cooked_write (regcache, OR1K_RV_REGNUM, buf);
    }

  return RETURN_VALUE_REGISTER_CONVENTION;

} /* or1k_return_value() */


/*----------------------------------------------------------------------------*/
/*!Determine the instruction to use for a breakpoint.

   Given the address at which to insert a breakpoint (bp_addr), what will
   that breakpoint be?

   For or1k, we have a breakpoint instruction. Since all or1k instructions
   are 32 bits, this is all we need, regardless of address.

   @param[in]  gdbarch  The GDB architecture being used
   @param[in]  bp_addr  The breakpoint address in question
   @param[out] bp_size  The size of instruction selected

   @return  The chosen breakpoint instruction */
/*---------------------------------------------------------------------------*/

static const gdb_byte *
or1k_breakpoint_from_pc (struct gdbarch *gdbarch,
                         CORE_ADDR      *bp_addr,
                         int            *bp_size)
{
  static const gdb_byte breakpoint[] = OR1K_BRK_INSTR_STRUCT;

  *bp_size = OR1K_INSTLEN;
  return breakpoint;

} /* or1k_breakpoint_from_pc() */


/*----------------------------------------------------------------------------*/
/*!Determine if we are executing a delay slot

   Looks at the instruction at the previous instruction to see if it was one
   with a delay slot.

   @param[in] gdbarch     The GDB architecture being used
   @param[in] this_frame  Information about THIS frame

   @return  1 (true) if this instruction is executing a delay slot, 0 (false)
   otherwise. */
/*--------------------------------------------------------------------------*/

static int
or1k_single_step_through_delay( struct gdbarch    *gdbarch,
                                struct frame_info *this_frame )
{
  struct regcache   *regcache = get_current_regcache ();
  ULONGEST           val;
  CORE_ADDR          ppc;
  int                index;

  /* Get and decode the previous instruction. */
  regcache_cooked_read_unsigned (regcache, OR1K_PPC_REGNUM, &val);
  ppc        = (CORE_ADDR)val;
  index      = insn_decode (or1k_fetch_instruction (this_frame, ppc));

  /* We are only executing a delay slot if the previous instruction was a
     branch or jump. */
  return or32_opcodes[index].flags & OR32_IF_DELAY;

} /* or1k_single_step_through_delay() */


/*----------------------------------------------------------------------------*/
/*!Read a pseudo register

   Since we have no pseudo registers this is a null function for now.

   @todo The floating point and vector registers ought to be done as
         pseudo-registers.

   @param[in]  gdbarch   The GDB architecture to consider
   @param[in]  regcache  The cached register values as an array
   @param[in]  regnum    The register to read
   @param[out] buf       A buffer to put the result in */
/*---------------------------------------------------------------------------*/

static void
or1k_pseudo_register_read (struct gdbarch  *gdbarch,
                           struct regcache *regcache,
                           int              regnum,
                           gdb_byte        *buf)
{
  return;

} /* or1k_pseudo_register_read() */


/*----------------------------------------------------------------------------*/
/*!Write a pseudo register

   Since we have no pseudo registers this is a null function for now.

   @todo The floating point and vector registers ought to be done as
         pseudo-registers.

   @param[in] gdbarch   The GDB architecture to consider
   @param[in] regcache  The cached register values as an array
   @param[in] regnum    The register to read
   @param[in] buf       A buffer with the value to write */
/*---------------------------------------------------------------------------*/

static void
or1k_pseudo_register_write (struct gdbarch  *gdbarch,
                            struct regcache *regcache,
                            int              regnum,
                            const gdb_byte  *buf)
{
  return;

} /* or1k_pseudo_register_write() */


/*----------------------------------------------------------------------------*/
/*!Return the register name for the OpenRISC 1000 architecture

   This version converted to ANSI C, made static and incorporates the static
   table of register names (this is the only place it is referenced).

   @todo The floating point and vector registers ought to be done as
         pseudo-registers.

   @param[in] gdbarch  The GDB architecture being used
   @param[in] regnum    The register number

   @return  The textual name of the register */
/*---------------------------------------------------------------------------*/

static const char *
or1k_register_name (struct gdbarch *gdbarch,
                    int             regnum)
{
  static char *or1k_gdb_reg_names[OR1K_TOTAL_NUM_REGS] =
    {
      /* general purpose registers */
      "gpr0",  "gpr1",  "gpr2",  "gpr3",  "gpr4",  "gpr5",  "gpr6",  "gpr7",
      "gpr8",  "gpr9",  "gpr10", "gpr11", "gpr12", "gpr13", "gpr14", "gpr15",
      "gpr16", "gpr17", "gpr18", "gpr19", "gpr20", "gpr21", "gpr22", "gpr23",
      "gpr24", "gpr25", "gpr26", "gpr27", "gpr28", "gpr29", "gpr30", "gpr31",

      /* previous program counter, next program counter and status register */
      "ppc",   "npc",   "sr"

      /* Floating point and vector registers may appear as pseudo registers in
         the future. */
    };

  return or1k_gdb_reg_names[regnum];

} /* or1k_register_name() */


/*----------------------------------------------------------------------------*/
/*!Identify the type of a register

   @todo I don't fully understand exactly what this does, but I think this
         makes sense!

   @param[in] arch     The GDB architecture to consider
   @param[in] regnum   The register to identify

   @return  The type of the register */
/*---------------------------------------------------------------------------*/

static struct type *
or1k_register_type (struct gdbarch *arch,
                    int             regnum)
{
  static struct type *void_func_ptr = NULL;
  static struct type *void_ptr      = NULL;

  /* Set up the static pointers once, the first time*/
  if (NULL == void_func_ptr)
    {
      void_ptr = lookup_pointer_type (builtin_type_void);
      void_func_ptr =
        lookup_pointer_type (lookup_function_type (builtin_type_void));
    }

  if((regnum >= 0) && (regnum < OR1K_TOTAL_NUM_REGS))
    {
      switch (regnum)
        {
        case OR1K_PPC_REGNUM:
        case OR1K_NPC_REGNUM:
          return void_func_ptr; /* Pointer to code */

        case OR1K_SP_REGNUM:
        case OR1K_FP_REGNUM:
          return void_ptr; /* Pointer to data */

        default:
          return builtin_type_int32; /* Data */
        }
    }

  internal_error (__FILE__, __LINE__,
                  _("or1k_register_type: illegal register number %d"), regnum);

} /* or1k_register_type() */


/*----------------------------------------------------------------------------*/
/*!Handle the "info register" command

   Print the identified register, unless it is -1, in which case print all
   the registers. If all is 1 means all registers, otherwise only the core
   GPRs.

   @todo At present all registers are printed with the default method. Should
         there be something special for FP registers?

   @param[in] gdbarch  The GDB architecture being used
   @param[in] file     File handle for use with any custom I/O
   @param[in] frame    Frame info for use with custom output
   @param[in] regnum   Register of interest, or -1 if all registers
   @param[in] all      1 if all means all, 0 if all means just GPRs
 
   @return  The aligned stack frame address */
/*---------------------------------------------------------------------------*/

static void
or1k_registers_info (struct gdbarch    *gdbarch,
                     struct ui_file    *file,
                     struct frame_info *frame,
                     int                regnum,
                     int                all)
{
  if (-1 == regnum)
    {
      /* Do all (valid) registers */
      unsigned int  lim = all ? OR1K_NUM_REGS : OR1K_MAX_GPR_REGS;

      for (regnum = 0; regnum < lim; regnum++) {
        if ('\0' != *(or1k_register_name (gdbarch, regnum)))
          {
            or1k_registers_info (gdbarch, file, frame, regnum, all);
          }
      }
    }
  else
    {
      /* Do one specified register - if it is part of this architecture */
      if ('\0' == *(or1k_register_name (gdbarch, regnum)))
        {
          error ("Not a valid register for the current processor type");
        }
      else
        {
          default_print_registers_info (gdbarch, file, frame, regnum, all);
        }
    }
} /* or1k_registers_info() */


/*----------------------------------------------------------------------------*/
/*!Identify if a register belongs to a specified group

   Return true if the specified register is a member of the specified
   register group.
 
   These are the groups of registers that can be displayed via "info reg".
 
   @todo The Vector and Floating Point registers ought to be displayed as
         pseudo-registers.
 
   @param[in] gdbarch  The GDB architecture to consider
   @param[in] regnum   The register to consider
   @param[in] group    The group to consider

   @return  True (1) if regnum is a member of group */
/*---------------------------------------------------------------------------*/

static int
or1k_register_reggroup_p (struct gdbarch  *gdbarch,
                          int              regnum,
                          struct reggroup *group)
{
  struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);

  /* All register group */
  if (group == all_reggroup)
    {
      return ((regnum >= 0) &&
              (regnum < OR1K_TOTAL_NUM_REGS) &&
              (or1k_register_name (gdbarch, regnum)[0] != '\0'));
    }

  /* For now everything except the PC */
  if (group == general_reggroup)
    {
      return ((regnum >= OR1K_ZERO_REGNUM) &&
              (regnum <  tdep->num_gpr_regs) &&
              (regnum != OR1K_PPC_REGNUM) &&
              (regnum != OR1K_NPC_REGNUM));
    }

  if (group == float_reggroup)
    {
      return 0; /* No float regs.  */
    }

  if (group == vector_reggroup)
    {
      return 0; /* No vector regs.  */
    }

  /* For any that are not handled above.  */
  return default_register_reggroup_p (gdbarch, regnum, group);

} /* or1k_register_reggroup_p() */


/*----------------------------------------------------------------------------*/
/*!Skip a function prolog

   If the input address, PC, is in a function prologue, return the address of
   the end of the prologue, otherwise return the input  address.

   @see For details of the stack frame, see the function
   or1k_frame_unwind_cache().

   This function reuses the helper functions from or1k_frame_unwind_cache() to
   locate the various parts of the prolog.

   This is very tricky. Essentially we look for the parts of a prolog.  If we
   get a mismatch, we never know if it is because we are not in prolog, or
   because the prolog is broken.

   @param[in] gdbarch  The GDB architecture being used
   @param[in] pc       Current program counter

   @return  The address of the end of the prolog if the PC is in a function
   prologue, otherwise the input  address. */
/*--------------------------------------------------------------------------*/

static CORE_ADDR
or1k_skip_prologue (struct gdbarch *gdbarch,
                    CORE_ADDR       pc)
{
  enum {
    OR1K_FRAME_SIZE,
    OR1K_FP_SAVED,
    OR1K_NEW_FP,
    OR1K_LR_SAVE,
    OR1K_REG_SAVE,
    OR1K_NO_PROLOGUE
  } start_pos = OR1K_NO_PROLOGUE;

  CORE_ADDR  addr     = pc;
  int        frame_size;
  int        fp_save_offset;
  int        tmp;
  int        i;

  CORE_ADDR  start_addr;
  CORE_ADDR  end_addr;
 
  /* Try using SAL first */
  if (find_pc_partial_function (pc, NULL, &start_addr, &end_addr))
    {
      CORE_ADDR  prologue_end = skip_prologue_using_sal( pc );

      if (prologue_end > pc)
        {
          return  prologue_end;
        }
      else
        {
          return  pc;
        }
    }

  frame_size = or1k_frame_size (NULL, addr);

  if (0 != frame_size)
    {
      /* We seem to have the start of a prolog */
      start_pos = OR1K_FRAME_SIZE;
      addr += OR1K_INSTLEN;
    }

  /* Look for the previous frame pointer being saved. If we are in a frame,
     then this must be here. */
  fp_save_offset = or1k_frame_fp_loc (NULL, addr);

  switch (start_pos)
   {
    case OR1K_FRAME_SIZE:
      if (-1 == fp_save_offset)
        {
          error ("or1k_skip_prolog: "
                 "old frame pointer not saved at address %08llx: giving up\n",
                 (long long unsigned int)(ULONGEST)addr);
        }
      else
        {
          addr += OR1K_INSTLEN;
        }

      break;

    default:
      start_pos  = OR1K_FP_SAVED;
      addr      += OR1K_INSTLEN;
      break;
    }

  /* Look for new FP being set up. This must match the frame_size if that is
     known. */
  tmp = or1k_frame_size_check (NULL, addr);
  switch (start_pos)
   {
    case OR1K_FRAME_SIZE:
      if (frame_size != tmp)
        {
          error ("or1k_skip_prolog: "
                 "frame pointer set to wrong size  at address %08llx: "
                 "expected %d, got %d\n", (long long unsigned int)(ULONGEST)addr, frame_size, tmp);
        }
      else
        {
          addr += OR1K_INSTLEN;
        }

      break;

    case OR1K_FP_SAVED:
      if (-1 == tmp)
        {
          error ("or1k_skip_prolog: "
                 "no frame pointer set up instruction at address %08llx\n",
                 (long long unsigned int)(ULONGEST)addr);
        }
      else
        {
          addr += OR1K_INSTLEN;
        }

      break;

    default:
      if (-1 != tmp)
        {
          start_pos  = OR1K_NEW_FP;
          addr      += OR1K_INSTLEN;
        }
    }

  /* Look for the link register being saved. If we are in a prolog sequence,
     and is there then it should save to a particular location. */
  tmp = or1k_link_address (NULL, addr);
  switch (start_pos)
   {
    case OR1K_FRAME_SIZE:
    case OR1K_FP_SAVED:
      if ((-1 != tmp) && (tmp != fp_save_offset - OR1K_INSTLEN))
        {
          error ("or1k_skip_prolog: "
                 "link address saved to wrong offset at address %08llx: "
                 "expected %d, got %d\n", (long long unsigned int)(ULONGEST)addr,
                 fp_save_offset - OR1K_INSTLEN, tmp);
        }
      else
        {
          addr += OR1K_INSTLEN;
        }

      break;

    default:
      if (-1 != tmp)
        {
          start_pos  = OR1K_LR_SAVE;
          addr      += OR1K_INSTLEN;
        }
    }

  /* Skip saved registers */
  for (i = 0;; i += OR1K_INSTLEN)
   {
      int  regnum = or1k_get_saved_reg (NULL, addr, &tmp);

      switch (start_pos)
        {
        case OR1K_FRAME_SIZE:
        case OR1K_FP_SAVED:
          if (-1  != regnum)
           {
              if (tmp != fp_save_offset + ((i - 1) * OR1K_INSTLEN))
                {
                  error ("or1k_skip_prolog: callee register saved to wrong "
                         "offset at address %08llx: "
                         "expected %d, got %d\n", (long long unsigned int)(ULONGEST)addr,
                         fp_save_offset + ((i - 1) * OR1K_INSTLEN), tmp);
                }
              else
                {
                  addr += 4;
                }
            }
          else
           {
              return  addr;
            }

          break;

        case OR1K_NEW_FP:
        case OR1K_LR_SAVE:
        case OR1K_REG_SAVE:
          if (-1 != regnum)
           {
              addr += 4;
            }
          else
           {
              return  addr;
            }

        default:
          if (-1 != regnum)
           {
              start_pos  = OR1K_REG_SAVE;
              addr += 4;
            }
          else
           {
              return  pc; /* Not in a prolog */
            }

          break;
        }
    }
} /* or1k_skip_prologue() */


/*----------------------------------------------------------------------------*/
/*!Align the stack frame

   OpenRISC 1000 uses a falling stack frame, so this aligns down to the
   nearest 8 bytes. Useful when we'be building a dummy frame.

   @param[in] gdbarch  The GDB architecture being used
   @param[in] sp       Current stack pointer

   @return  The aligned stack frame address */
/*---------------------------------------------------------------------------*/

static CORE_ADDR
or1k_frame_align (struct gdbarch *gdbarch,
                  CORE_ADDR       sp)
{
  return align_down (sp, OR1K_STACK_ALIGN);

} /* or1k_frame_align() */


/*----------------------------------------------------------------------------*/
/*!Unwind the program counter from a stack frame

   This just uses the built in frame unwinder

   @param[in] gdbarch     The GDB architecture being used
   @param[in] next_frame  Frame info for the NEXT frame
 
   @return  The program counter for THIS frame */
/*---------------------------------------------------------------------------*/

static CORE_ADDR
or1k_unwind_pc (struct gdbarch    *gdbarch,
                struct frame_info *next_frame)
{
  return frame_unwind_register_unsigned (next_frame, OR1K_NPC_REGNUM);

} /* or1k_unwind_pc() */


/*----------------------------------------------------------------------------*/
/*!Unwind the stack pointer from a stack frame

   This just uses the built in frame unwinder

   @param[in] gdbarch     The GDB architecture being used
   @param[in] next_frame  Frame info for the NEXT frame
 
   @return  The stack pointer for THIS frame */
/*---------------------------------------------------------------------------*/

static CORE_ADDR
or1k_unwind_sp (struct gdbarch    *gdbarch,
                struct frame_info *next_frame)
{
  return frame_unwind_register_unsigned (next_frame, OR1K_SP_REGNUM);

} /* or1k_unwind_sp() */


/*----------------------------------------------------------------------------*/
/*!Create a dummy stack frame

   The arguments are placed in registers and/or pushed on the stack as per the
   OR1K ABI.

   @param[in] gdbarch        The architecture to use
   @param[in] function       Pointer to the function that will be called
   @param[in] regcache       The register cache to use
   @param[in] bp_addr        Breakpoint address
   @param[in] nargs          Number of ags to push
   @param[in] args           The arguments
   @param[in] sp             The stack pointer
   @param[in] struct_return  True (1) if this returns a structure
   @param[in] struct_addr    Address for returning structures

   @return  The updated stack pointer */
/*---------------------------------------------------------------------------*/

static CORE_ADDR
or1k_push_dummy_call (struct gdbarch  *gdbarch,
                      struct value    *function,
                      struct regcache *regcache,
                      CORE_ADDR        bp_addr,
                      int              nargs,
                      struct value   **args,
                      CORE_ADDR        sp,
                      int              struct_return,
                      CORE_ADDR        struct_addr)
{
  int           argreg;
  int           argnum;
  int           first_stack_arg;
  int           stack_offset = 0;

  unsigned int  bpa = (gdbarch_tdep (gdbarch))->bytes_per_address;
  unsigned int  bpw = (gdbarch_tdep (gdbarch))->bytes_per_word;

  /* Return address */
  regcache_cooked_write_unsigned (regcache, OR1K_LR_REGNUM, bp_addr);

  /* Register for the next argument */
  argreg = OR1K_FIRST_ARG_REGNUM;

  /* Location for a returned structure. This is passed as a silent first
     argument. */

  if (struct_return)
    {
      regcache_cooked_write_unsigned (regcache, OR1K_FIRST_ARG_REGNUM,
                                      struct_addr);
      argreg++;
    }

  /* Put as many args as possible in registers */
  for (argnum = 0; argnum < nargs; argnum++)
    {
      char           *val;
      char            valbuf[sizeof (ULONGEST) ];

      struct value   *arg      = args[argnum];
      struct type    *arg_type = check_typedef (value_type (arg));
      int             len      = arg_type->length;
      enum type_code  typecode = arg_type->main_type->code;

      /* The EABI passes structures that do not fit in a register by
         reference. In all other cases, pass the structure by value.  */
      if((len > bpw) &&
         ((TYPE_CODE_STRUCT == typecode) || (TYPE_CODE_UNION == typecode)))
        {

          store_unsigned_integer (valbuf, bpa, value_offset (arg));
          len      = bpa;
          val      = valbuf;
        }
      else
        {
          val = (char *)value_contents (arg);
        }  

      if((len > bpw) && (argreg <= (OR1K_LAST_ARG_REGNUM - 1)))
        {

          /* Big scalars use two registers, must be pair aligned. This code
             breaks if we can have quad-word scalars (e.g. long double). */
          ULONGEST regval = extract_unsigned_integer (val, len);

          gdb_assert (len <= (bpw * 2));

          argreg = 1 == (argreg & 1) ? argreg + 1 : argreg;
          regcache_cooked_write_unsigned (regcache, argreg, regval >> bpw);
          regcache_cooked_write_unsigned (regcache, argreg + 1,
                                          regval && ((ULONGEST)(1 << bpw) - 1));
          argreg += 2;
        }
      else if (argreg <= OR1K_LAST_ARG_REGNUM)
        {
          regcache_cooked_write_unsigned (regcache, argreg,
                                          extract_unsigned_integer (val, len));
          argreg++;
        }
      else
        {
          /* Run out of regs */
          break;
        }
    }

  first_stack_arg = argnum;

  /* If we get here with argnum < nargs, then arguments remain to be placed on
     the stack. This is tricky, since they must be pushed in reverse order and
     the stack in the end must be aligned. The only solution is to do it in
     two stages, the first to compute the stack size, the second to save the
     args. */

  for (argnum = first_stack_arg; argnum < nargs; argnum++)
    {
      struct value   *arg      = args[argnum];
      struct type    *arg_type = check_typedef (value_type (arg));
      int             len      = arg_type->length;
      enum type_code  typecode = arg_type->main_type->code;

      if((len > bpw) &&
         ((TYPE_CODE_STRUCT == typecode) || (TYPE_CODE_UNION == typecode)))
        {
          /* Large structures are passed as addresses */
          sp -= bpa;
        }
      else
        {
        /* Big scalars use more than one word. Code here allows for future
         quad-word entities (e.g. long double) */
          sp -= ((len + bpw - 1) / bpw) * bpw;
        }
    }

  sp           = gdbarch_frame_align (gdbarch, sp);
  stack_offset = 0;

  /* Push the remaining args on the stack */
  for (argnum = first_stack_arg; argnum < nargs; argnum++)
    {
      char           *val;
      char            valbuf[sizeof (ULONGEST) ];

      struct value   *arg      = args[argnum];
      struct type    *arg_type = check_typedef (value_type (arg));
      int             len      = arg_type->length;
      enum type_code  typecode = arg_type->main_type->code;

      /* The EABI passes structures that do not fit in a register by
         reference. In all other cases, pass the structure by value.  */
      if((len > bpw) &&
         ((TYPE_CODE_STRUCT == typecode) || (TYPE_CODE_UNION == typecode)))
        {

          store_unsigned_integer (valbuf, bpa, value_offset (arg));
          len      = bpa;
          val      = valbuf;
        }
      else
        {
          val = (char *)value_contents (arg);
        }  

      gdb_assert (len <= (bpw * 2));

      write_memory (sp + stack_offset, val, len);
      stack_offset += ((len + bpw - 1) / bpw) * bpw;
    }

  /* Save the updated stack pointer */
  regcache_cooked_write_unsigned (regcache, OR1K_SP_REGNUM, sp);

  return sp;

} /* or1k_push_dummy_call() */


/*----------------------------------------------------------------------------*/
/*!Unwind a dummy stack frame

   Tear down a dummy frame created by or1k_push_dummy_call(). This data has to
   be constructed manually from the data in our hand. The frame_id info in
   next_frame is not complete, and a call to unwind it will just recurse to us
   (we think).

   The stack pointer and program counter can be unwound. From the program
   counter, the start of the function can be determined.

   @param[in] gdbarch     The architecture to use
   @param[in] next_frame  Information about the next frame

   @return  Frame ID of the preceding frame */
/*---------------------------------------------------------------------------*/

static struct frame_id
or1k_unwind_dummy_id (struct gdbarch    *gdbarch,
                      struct frame_info *next_frame)
{
  CORE_ADDR  this_sp = gdbarch_unwind_sp (gdbarch, next_frame);
  CORE_ADDR  this_pc = gdbarch_unwind_pc (gdbarch, next_frame);

  CORE_ADDR  start_addr;
  CORE_ADDR  end_addr;
 
  /* Try using SAL to find the true function start. Otherwise the PC will
     have to be a proxy for the start of the function. */
  if (find_pc_partial_function (this_pc, NULL, &start_addr, &end_addr))
    {
      return  frame_id_build (this_sp, start_addr);
    }
  else
    {
      return  frame_id_build (this_sp, this_pc);
    }

} /* or1k_unwind_dummy_id() */


/*----------------------------------------------------------------------------*/
/*!The OpenRISC 1000 registered frame sniffer

   This function just identifies our family of frame sniffing functions.
 
   @param[in] next_frame  The "next" (i.e. inner, newer from here, the one
                          THIS frame called) frame.

                          @return  A pointer to a struct identifying the sniffing functions */
/*---------------------------------------------------------------------------*/

static const struct frame_unwind *
or1k_frame_sniffer (struct frame_info *next_frame)
{
  static const struct frame_unwind or1k_frame_unwind = {
    .type          = NORMAL_FRAME,
    .this_id       = or1k_frame_this_id,
    .prev_register = or1k_frame_prev_register,
    .unwind_data   = NULL,
    .sniffer       = NULL,
    .prev_pc       = NULL,
    .dealloc_cache = NULL
  };

  return  &or1k_frame_unwind;

} /* or1k_frame_sniffer() */


/*----------------------------------------------------------------------------*/
/*!Architecture initialization for OpenRISC 1000

   Looks for a candidate architecture in the list of architectures supplied
   using the info supplied. If none match, create a new architecture.

   @param[in] info    Information about the target architecture
   @param[in] arches  The list of currently know architectures

   @return  A structure describing the target architecture */
/*---------------------------------------------------------------------------*/

static struct gdbarch *
or1k_gdbarch_init (struct gdbarch_info  info,
                   struct gdbarch_list *arches)
{
  static struct frame_base     or1k_frame_base;
  struct        gdbarch       *gdbarch;
  struct        gdbarch_tdep  *tdep;
  const struct  bfd_arch_info *binfo;

  /* Find a candidate among the list of pre-declared architectures.  */
  arches = gdbarch_list_lookup_by_info (arches, &info);
  if (NULL != arches)
    {
      return arches->gdbarch;
    }

  /* None found, create a new architecture from the information
     provided. Can't initialize all the target dependencies until we actually
     know which target we are talking to, but put in some defaults for now. */

  binfo                   = info.bfd_arch_info;
  tdep                    = xmalloc (sizeof *tdep);
  tdep->num_matchpoints   = OR1K_MAX_MATCHPOINTS;
  tdep->num_gpr_regs      = OR1K_MAX_GPR_REGS;
  tdep->bytes_per_word    = binfo->bits_per_word    / binfo->bits_per_byte;
  tdep->bytes_per_address = binfo->bits_per_address / binfo->bits_per_byte;
  gdbarch                 = gdbarch_alloc (&info, tdep);

  /* Target data types.  */
  set_gdbarch_short_bit             (gdbarch, 16);
  set_gdbarch_int_bit               (gdbarch, 32);
  set_gdbarch_long_bit              (gdbarch, 32);
  set_gdbarch_long_long_bit         (gdbarch, 64);
  set_gdbarch_float_bit             (gdbarch, 32);
  set_gdbarch_float_format          (gdbarch, floatformats_ieee_single);
  set_gdbarch_double_bit            (gdbarch, 64);
  set_gdbarch_double_format         (gdbarch, floatformats_ieee_double);
  set_gdbarch_long_double_bit       (gdbarch, 64);
  set_gdbarch_long_double_format    (gdbarch, floatformats_ieee_double);
  set_gdbarch_ptr_bit               (gdbarch, binfo->bits_per_address);
  set_gdbarch_addr_bit              (gdbarch, binfo->bits_per_address);
  set_gdbarch_char_signed           (gdbarch, 1);

  /* Information about the target architecture */
  set_gdbarch_return_value          (gdbarch, or1k_return_value);
  set_gdbarch_breakpoint_from_pc    (gdbarch, or1k_breakpoint_from_pc);
  set_gdbarch_single_step_through_delay
                                    (gdbarch, or1k_single_step_through_delay);
  set_gdbarch_have_nonsteppable_watchpoint
                                    (gdbarch, 1);
  switch (gdbarch_byte_order (gdbarch))
    {
    case BFD_ENDIAN_BIG:
      set_gdbarch_print_insn        (gdbarch, print_insn_big_or32);
      break;

    case BFD_ENDIAN_LITTLE:
      set_gdbarch_print_insn        (gdbarch, print_insn_little_or32);
      break;

    case BFD_ENDIAN_UNKNOWN:
      error ("or1k_gdbarch_init: Unknown endianism");
      break;
    }

  /* Register architecture */
  set_gdbarch_pseudo_register_read  (gdbarch, or1k_pseudo_register_read);
  set_gdbarch_pseudo_register_write (gdbarch, or1k_pseudo_register_write);
  set_gdbarch_num_regs              (gdbarch, OR1K_NUM_REGS);
  set_gdbarch_num_pseudo_regs       (gdbarch, OR1K_NUM_PSEUDO_REGS);
  set_gdbarch_sp_regnum             (gdbarch, OR1K_SP_REGNUM);
  set_gdbarch_pc_regnum             (gdbarch, OR1K_NPC_REGNUM);
  set_gdbarch_ps_regnum             (gdbarch, OR1K_SR_REGNUM);
  set_gdbarch_deprecated_fp_regnum  (gdbarch, OR1K_FP_REGNUM);

  /* Functions to supply register information */
  set_gdbarch_register_name         (gdbarch, or1k_register_name);
  set_gdbarch_register_type         (gdbarch, or1k_register_type);
  set_gdbarch_print_registers_info  (gdbarch, or1k_registers_info);
  set_gdbarch_register_reggroup_p   (gdbarch, or1k_register_reggroup_p);

  /* Functions to analyse frames */
  set_gdbarch_skip_prologue         (gdbarch, or1k_skip_prologue);
  set_gdbarch_inner_than            (gdbarch, core_addr_lessthan);
  set_gdbarch_frame_align           (gdbarch, or1k_frame_align);
  set_gdbarch_frame_red_zone_size   (gdbarch, OR1K_FRAME_RED_ZONE_SIZE);

  /* Functions to access frame data */
  set_gdbarch_unwind_pc             (gdbarch, or1k_unwind_pc);
  set_gdbarch_unwind_sp             (gdbarch, or1k_unwind_sp);

  /* Functions handling dummy frames */
  set_gdbarch_push_dummy_call       (gdbarch, or1k_push_dummy_call);
  set_gdbarch_unwind_dummy_id       (gdbarch, or1k_unwind_dummy_id);

  /* High level frame base sniffer */
  or1k_frame_base.unwind      = or1k_frame_sniffer (NULL);
  or1k_frame_base.this_base   = or1k_frame_base_address;
  or1k_frame_base.this_locals = or1k_frame_base_address;
  or1k_frame_base.this_args   = or1k_frame_base_address;
  frame_base_set_default            (gdbarch, &or1k_frame_base);

  /* Low level frame sniffers */
  frame_unwind_append_sniffer       (gdbarch, dwarf2_frame_sniffer);
  frame_unwind_append_sniffer       (gdbarch, or1k_frame_sniffer);


  return gdbarch;

} /* or1k_gdbarch_init() */


/*----------------------------------------------------------------------------*/
/*!Dump the target specific data for this architecture

   @param[in] gdbarch  The architecture of interest
   @param[in] file     Where to dump the data */
/*---------------------------------------------------------------------------*/

static void
or1k_dump_tdep (struct gdbarch *gdbarch,
                struct ui_file *file)
{
  struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);

  if (NULL == tdep)
    {
      return; /* Nothing to report */
    }

  fprintf_unfiltered (file, "or1k_dump_tdep: %d matchpoints available\n",
                      tdep->num_matchpoints);
  fprintf_unfiltered (file, "or1k_dump_tdep: %d general purpose registers\n",
                      tdep->num_gpr_regs);
  fprintf_unfiltered (file, "or1k_dump_tdep: %d bytes per word\n",
                      tdep->bytes_per_word);
  fprintf_unfiltered (file, "or1k_dump_tdep: %d bytes per address\n",
                      tdep->bytes_per_address);

} /* or1k_dump_tdep() */



/* Functions to add extra commands to GDB */


/*----------------------------------------------------------------------------*/
/*!Returns a special purpose register group name

   @param[in]  group  The SPR group number

   @return  The SPR name (pointer to the name argument) */
/*---------------------------------------------------------------------------*/

static const char *
or1k_spr_group_name (int  group)
{
  static const char *or1k_group_names[OR1K_NUM_SPGS] =
    {
      "SYS",
      "DMMU",
      "IMMU",
      "DCACHE",
      "ICACHE",
      "MAC",
      "DEBUG",
      "PERF",
      "POWER",
      "PIC",
      "TIMER",
      "FPU"
    };

  if ((0 <= group) && (group < OR1K_NUM_SPGS))
    {
      return or1k_group_names[group];
    }
  else
    {
      return "";
    }
} /* or1k_spr_group_name() */


/*----------------------------------------------------------------------------*/
/*!Returns a special purpose register name

   @param[in]  group  The SPR group
   @param[in]  index  The index within the SPR group
   @param[out] name   Array to put the name in

   @return  The SPR name (pointer to the name argument) */
/*---------------------------------------------------------------------------*/

static char *
or1k_spr_register_name (int   group,
                        int   index,
                        char *name)
{
  char di;

  switch (group)
    {

    case OR1K_SPG_SYS:
      /* 1:1 names */
      switch (index)
        {
        case OR1K_SPG_SYS_VR:       sprintf (name, "VR"      ); return  name;
        case OR1K_SPG_SYS_UPR:      sprintf (name, "UPR"     ); return  name;
        case OR1K_SPG_SYS_CPUCFGR:  sprintf (name, "CPUCFGR" ); return  name;
        case OR1K_SPG_SYS_DMMUCFGR: sprintf (name, "DMMUCFGR"); return  name;
        case OR1K_SPG_SYS_IMMUCFGR: sprintf (name, "IMMUCFGR"); return  name;
        case OR1K_SPG_SYS_DCCFGR:   sprintf (name, "DCCFGR"  ); return  name;
        case OR1K_SPG_SYS_ICCFGR:   sprintf (name, "ICCFGR"  ); return  name;
        case OR1K_SPG_SYS_DCFGR:    sprintf (name, "DCFGR"   ); return  name;
        case OR1K_SPG_SYS_PCCFGR:   sprintf (name, "PCCFGR"  ); return  name;
        case OR1K_SPG_SYS_NPC:      sprintf (name, "NPC"     ); return  name;
        case OR1K_SPG_SYS_SR:       sprintf (name, "SR"      ); return  name;
        case OR1K_SPG_SYS_PPC:      sprintf (name, "PPC"     ); return  name;
        case OR1K_SPG_SYS_FPCSR:    sprintf (name, "FPCSR"   ); return  name;
        }

      /* Exception PC regs */
      if((OR1K_SPG_SYS_EPCR <= index) &&
         (index             <= OR1K_SPG_SYS_EPCR_END))
        {
          sprintf (name, "EPCR%d", index - OR1K_SPG_SYS_EPCR);
          return  name;
        }

      /* Exception EA regs */
      if((OR1K_SPG_SYS_EEAR <= index) &&
         (index             <= OR1K_SPG_SYS_EEAR_END))
        {
          sprintf (name, "EEAR%d", index - OR1K_SPG_SYS_EEAR);
          return  name;
        }

      /* Exception SR regs */
      if((OR1K_SPG_SYS_ESR <= index) &&
         (index            <= OR1K_SPG_SYS_ESR_END))
        {
          sprintf (name, "ESR%d", index - OR1K_SPG_SYS_ESR);
          return  name;
        }

      /* GPRs */
      if((OR1K_SPG_SYS_GPR <= index) &&
         (index            <= OR1K_SPG_SYS_GPR_END))
        {
          sprintf (name, "GPR%d", index - OR1K_SPG_SYS_GPR);
          return  name;
        }

      break;

    case OR1K_SPG_DMMU:
    case OR1K_SPG_IMMU:
      /* MMU registers. Use DMMU constants throughout, but these are identical
         to the corresponding IMMU constants */
      di = OR1K_SPG_DMMU == group ? 'D' : 'I';

      /* 1:1 names */
      switch (index)
        {
        case OR1K_SPG_DMMU_DMMUCR:
          sprintf (name, "%cMMUCR",  di); return  name;
        case OR1K_SPG_DMMU_DMMUPR:
          sprintf (name, "%cMMUPR",  di); return  name;
        case OR1K_SPG_DMMU_DTLBEIR:
          sprintf (name, "%cTLBEIR", di); return  name;
        }

      /* ATB Match registers */
      if((OR1K_SPG_DMMU_DATBMR <= index) &&
         (index                <= OR1K_SPG_DMMU_DATBMR_END))
        {
          sprintf (name, "%cATBMR%d", di, index - OR1K_SPG_DMMU_DATBMR);
          return  name;
        }

      /* ATB Translate registers */
      if((OR1K_SPG_DMMU_DATBTR <= index) &&
         (index                <= OR1K_SPG_DMMU_DATBTR_END))
        {
          sprintf (name, "%cATBTR%d", di, index - OR1K_SPG_DMMU_DATBTR);
          return  name;
        }

      /* TLB Way 1 Match registers */
      if((OR1K_SPG_DMMU_DTLBW1MR <= index) &&
         (index                <= OR1K_SPG_DMMU_DTLBW1MR_END))
        {
          sprintf (name, "%cTLBW1MR%d", di, index - OR1K_SPG_DMMU_DTLBW1MR);
          return  name;
        }

      /* TLB Way 1 Translate registers */
      if((OR1K_SPG_DMMU_DTLBW1TR <= index) &&
         (index                <= OR1K_SPG_DMMU_DTLBW1TR_END))
        {
          sprintf (name, "%cTLBW1TR%d", di, index - OR1K_SPG_DMMU_DTLBW1TR);
          return  name;
        }

      /* TLB Way 2 Match registers */
      if((OR1K_SPG_DMMU_DTLBW2MR <= index) &&
         (index                <= OR1K_SPG_DMMU_DTLBW2MR_END))
        {
          sprintf (name, "%cTLBW2MR%d", di, index - OR1K_SPG_DMMU_DTLBW2MR);
          return  name;
        }

      /* TLB Way 2 Translate registers */
      if((OR1K_SPG_DMMU_DTLBW2TR <= index) &&
         (index                <= OR1K_SPG_DMMU_DTLBW2TR_END))
        {
          sprintf (name, "%cTLBW2TR%d", di, index - OR1K_SPG_DMMU_DTLBW2TR);
          return  name;
        }

      /* TLB Way 3 Match registers */
      if((OR1K_SPG_DMMU_DTLBW3MR <= index) &&
         (index                <= OR1K_SPG_DMMU_DTLBW3MR_END))
        {
          sprintf (name, "%cTLBW3MR%d", di, index - OR1K_SPG_DMMU_DTLBW3MR);
          return  name;
        }

      /* TLB Way 3 Translate registers */
      if((OR1K_SPG_DMMU_DTLBW3TR <= index) &&
         (index                <= OR1K_SPG_DMMU_DTLBW3TR_END))
        {
          sprintf (name, "%cTLBW3TR%d", di, index - OR1K_SPG_DMMU_DTLBW3TR);
          return  name;
        }

      break;

    case OR1K_SPG_DC:
      /* Data cache registers. These do not have an exact correspondence with
         their instruction cache counterparts, so must be done separately. */

      /* 1:1 names */
      switch (index)
        {
        case OR1K_SPG_DC_DCCR:  sprintf (name, "DCCR" ); return  name;
        case OR1K_SPG_DC_DCBPR: sprintf (name, "DCBPR"); return  name;
        case OR1K_SPG_DC_DCBFR: sprintf (name, "DCBFR"); return  name;
        case OR1K_SPG_DC_DCBIR: sprintf (name, "DCBIR"); return  name;
        case OR1K_SPG_DC_DCBWR: sprintf (name, "DCBWR"); return  name;
        case OR1K_SPG_DC_DCBLR: sprintf (name, "DCBLR"); return  name;
        }

      break;

    case OR1K_SPG_IC:
      /* Instruction cache registers */

      /* 1:1 names */
      switch (index)
        {
        case OR1K_SPG_IC_ICCR:  sprintf (name, "ICCR" ); return  name;
        case OR1K_SPG_IC_ICBPR: sprintf (name, "ICBPR"); return  name;
        case OR1K_SPG_IC_ICBIR: sprintf (name, "ICBIR"); return  name;
        case OR1K_SPG_IC_ICBLR: sprintf (name, "ICBLR"); return  name;
        }

      break;

    case OR1K_SPG_MAC:
      /* MAC registers */

      /* 1:1 names */
      switch (index)
        {
        case OR1K_SPG_MAC_MACLO: sprintf (name, "MACLO"); return  name;
        case OR1K_SPG_MAC_MACHI: sprintf (name, "MACHI"); return  name;
        }

      break;

    case OR1K_SPG_DEBUG:
      /* Debug registers */

      /* Debug Value registers */
      if((OR1K_SPG_DEBUG_DVR <= index) &&
         (index                <= OR1K_SPG_DEBUG_DVR_END))
        {
          sprintf (name, "DVR%d", index - OR1K_SPG_DEBUG_DVR);
          return  name;
        }

      /* Debug Control registers */
      if((OR1K_SPG_DEBUG_DCR <= index) &&
         (index                <= OR1K_SPG_DEBUG_DCR_END))
        {
          sprintf (name, "DCR%d", index - OR1K_SPG_DEBUG_DCR);
          return  name;
        }

      /* 1:1 names */
      switch (index)
        {
        case OR1K_SPG_DEBUG_DMR1:  sprintf (name, "DMR1" ); return  name;
        case OR1K_SPG_DEBUG_DMR2:  sprintf (name, "DMR2" ); return  name;
        case OR1K_SPG_DEBUG_DCWR0: sprintf (name, "DCWR0"); return  name;
        case OR1K_SPG_DEBUG_DCWR1: sprintf (name, "DCWR1"); return  name;
        case OR1K_SPG_DEBUG_DSR:   sprintf (name, "DSR"  ); return  name;
        case OR1K_SPG_DEBUG_DRR:   sprintf (name, "DRR"  ); return  name;
        }

      break;

    case OR1K_SPG_PC:
      /* Performance Counter registers */

      /* Performance Counters Count registers */
      if((OR1K_SPG_PC_PCCR <= index) &&
         (index                <= OR1K_SPG_PC_PCCR_END))
        {
          sprintf (name, "PCCR%d", index - OR1K_SPG_PC_PCCR);
          return  name;
        }

      /* Performance Counters Mode registers */
      if((OR1K_SPG_PC_PCMR <= index) &&
         (index                <= OR1K_SPG_PC_PCMR_END))
        {
          sprintf (name, "PCMR%d", index - OR1K_SPG_PC_PCMR);
          return  name;
        }

      break;

    case OR1K_SPG_PM:
      /* Power Management registers */

      /* 1:1 names */
      switch (index)
        {
        case OR1K_SPG_PM_PMR:  sprintf (name, "PMR"); return  name;
        }

      break;

    case OR1K_SPG_PIC:
      /* Programmable Interrupt Controller registers */

      /* 1:1 names */
      switch (index)
        {
        case OR1K_SPG_PIC_PICMR:  sprintf (name, "PICMR"); return  name;
        case OR1K_SPG_PIC_PICSR:  sprintf (name, "PICSR"); return  name;
        }

      break;

    case OR1K_SPG_TT:
      /* Tick Timer registers */

      /* 1:1 names */
      switch (index)
        {
        case OR1K_SPG_TT_TTMR:  sprintf (name, "TTMR"); return  name;
        case OR1K_SPG_TT_TTCR:  sprintf (name, "TTCR"); return  name;
        }

      break;

    case OR1K_SPG_FPU:

      break;
    }

  /* Not a recognized register */
  strcpy (name, "");
  return  name;

} /* or1k_spr_register_name() */


/*----------------------------------------------------------------------------*/
/*!Get SPR group number from a name

   @param[in] group_name  SPR register group

   @return  The index, or negative if no match. */
/*----------------------------------------------------------------------------*/

static int
or1k_groupnum_from_name (char *group_name)
{
  int  group;

  for (group = 0; group < OR1K_NUM_SPGS; group++)
    {
      if (0 == strcasecmp (group_name, or1k_spr_group_name (group)))
        {
          return group;
        }
    }

  return -1;

} /* or1k_groupnum_from_name() */


/*----------------------------------------------------------------------------*/
/*!Get register index in special purpose register group from name

   The name may either be SPR<group_num>_<index> or a known unique name. In
   either case the group number must match the supplied group number.

   @param[in] group  SPR register group
   @param[in] name   Register name

   @return  The index, or negative if no match. */
/*----------------------------------------------------------------------------*/

static int
or1k_regnum_from_name (int   group,
                       char *name)
{
  /* Last valid register in each group. */
  static const int  or1k_spr_group_last[OR1K_NUM_SPGS] =
    {
      OR1K_SPG_SYS_LAST,
      OR1K_SPG_DMMU_LAST,
      OR1K_SPG_IMMU_LAST,
      OR1K_SPG_DC_LAST,
      OR1K_SPG_IC_LAST,
      OR1K_SPG_MAC_LAST,
      OR1K_SPG_DEBUG_LAST,
      OR1K_SPG_PC_LAST,
      OR1K_SPG_PM_LAST,
      OR1K_SPG_PIC_LAST,
      OR1K_SPG_TT_LAST,
      OR1K_SPG_FPU_LAST
    };

  int  i;
  char  spr_name[32];

  if (0 == strcasecmp (name, "SPR"))
    {
      char *ptr_c;      

      /* Skip SPR */
      name += 3;

      /* Get group number */
      i = (int) strtoul (name, &ptr_c, 10);
      if (*ptr_c != '_' || i != group)
        {
          return -1;
        }

      /* Get index */
      ptr_c++;
      i = (int) strtoul (name, &ptr_c, 10);
      if (*ptr_c)
        {
          return -1;
        }
      else
        {
          return  i;
        }
    }

  /* Look for a "known" name in this group */
  for (i = 0; i <= or1k_spr_group_last[group]; i++)
    {
      char *s = or1k_spr_register_name (group, i, spr_name);

      if (0 == strcasecmp (name, s))
        {
          return i;
        }
    }

  /* Failure */
  return -1;

} /* or1k_regnum_from_name() */


/*----------------------------------------------------------------------------*/
/*!Get the next token from a string

   I can't believe there isn't a library argument for this, but strtok is
   deprecated.

   Take a string and find the start of the next token and its length. A token
   is anything containing non-blank characters.

   @param[in]  str  The string to look at (may be NULL).
   @param[out] tok  Pointer to the start of the token within str. May be NULL
                    if this result is not wanted (e.g. just the length is
                    wanted. If no token is found will be the NULL char at the
                    end of the string, if the original str was NULL, this will
                    be NULL.

                    @return  The length of the token found */
/*----------------------------------------------------------------------------*/

static int
or1k_tokenize (char  *str,
               char **tok)
{
  char *ptr;
  int   len;

  /* Deal with NULL argument */
  if (NULL == str)
    {
      if (NULL != tok)
        {
          *tok = NULL;
        }
      return 0;
    }

  /* Find the start */
  for (ptr = str; ISBLANK (*ptr) ; ptr++)
    {
      continue;
    }

  /* Return the start pointer if requested */
  if (NULL != tok)
    {
      *tok = ptr;
    }

  /* Find the end and put in EOS */
  for (len = 0;  ('\0' != ptr[len]) && (!ISBLANK (ptr[len])); len++)
    {
      continue;
    }

  return len;

} /* or1k_tokenize() */


/*----------------------------------------------------------------------------*/
/*!Parses args for spr commands

   Determines the special purpose register (SPR) name and puts result into
   group and index

   Syntax is:

   @verbatim
   <spr_args>    -> <group_ref> | <reg_name>
   <group_ref>   -> <group_id> <index>
   <group_id>    -> <group_num> | <group_name>
   @endverbatim

   Where the indices/names have to be valid.

   So to parse, we look for 1 or 2 args. If 1 it must be a unique register
   name. If 2, the first must be a group number or name and the second an
   index within that group.

   Also responsible for providing diagnostics if the arguments do not match.

   Rewritten for GDB 6.8 to use the new UI calls and remove assorted
   bugs. Syntax also slightly restricted to be more comprehensible.

   @param[in]  arg_str  The argument string
   @param[out] group    The group this SPR belongs in, or -1 to indicate
                        failure
   @param[out] index    Index of the register within the group, or -1 to
                        indicate the whole group
   @param[in]  is_set   1 (true) if we are called from the "spr" command (so
                        there is an extra arg) rather than the "info spr"
                        command. Needed to distinguish between the case where
                        info is sought from a register specified as group and
                        index and setting a uniquely identified register to a
                        value.

                        @return  A pointer to any remaining args */
/*---------------------------------------------------------------------------*/

static char *
or1k_parse_spr_params (char *arg_str,
                       int  *group,
                       int  *index,
                       int   is_set)
{
  struct {
    char              *str;
    int                len;
    unsigned long int  val;
    int                is_num;
  } arg[3] = {
    {
      .str    = NULL,
      .len    = 0,
      .val    = 0,
      .is_num = 0,
    },
   {
      .str    = NULL,
      .len    = 0,
      .val    = 0,
      .is_num = 0,
    },
   {
      .str    = NULL,
      .len    = 0,
      .val    = 0,
      .is_num = 0,
    }
  };

  int   num_args;
  char *trailer  = arg_str;
  char *tmp_str;
  int   i;

  char  spr_name[32];

  /* Break out the arguments. Note that the strings are NOT null terminated
     (we don't want to change arg_str), so we must rely on len. The stroul
     call will still work, since there is always a non-digit char (possibly EOS)
     after the last digit. */
  if (NULL == arg_str)
    {
      num_args = 0;
    }
  else
    {
      for (num_args = 0; num_args < 3; num_args++)
        {
          arg[num_args].len = or1k_tokenize (trailer, &(arg[num_args].str));
          trailer           = arg[num_args].str + arg[num_args].len;

          if (0 == arg[num_args].len)
            {
              break;
            }
        }
    }

  /* Patch nulls into the arg strings and see about values. Couldn't do this
     earlier, since we needed the next char clean to check later args. This
     means advancing trailer, UNLESS it was already at EOS */

  if((NULL != arg_str) && ('\0' != *trailer))
    {
      trailer++;
    }

  for (i = 0; i < num_args; i++)
    {
      (arg[i].str)[arg[i].len] = '\0';
      errno                    = 0;
      arg[i].val               = strtoul (arg[i].str, &tmp_str, 0);
      arg[i].is_num            = (0 == errno) && ('\0' == *tmp_str);
    }

  /* Deal with the case where we are setting a register, so the final argument
     should be disregarded (it is the trailer). Do this anyway if we get a
     third argument */
  if ((is_set & (num_args > 0)) || (num_args > 2))
    {
      trailer = arg[num_args - 1].str;
      num_args--;
    }

  /* Deal with different numbers of args */

  switch (num_args)
    {

    case 0:
      ui_out_message (uiout, 0,
                      "Usage: <command> <register>      |\n"
                      "       <command> <group>         |\n"
                      "       <command> <group> <index>\n"
                      "Valid groups are:\n");
      for (i = 0; i < OR1K_NUM_SPGS; i++)
        {
          ui_out_field_string (uiout, NULL, or1k_spr_group_name  (i));
          ui_out_spaces (uiout, 1);
          ui_out_wrap_hint (uiout, NULL);
        }
      ui_out_field_string (uiout, NULL, "\n");

      *index = -1;
      return  trailer;

    case 1:
      /* See if it is a numeric group */
      if (arg[0].is_num)
        {
          if (arg[0].val < OR1K_NUM_SPGS)
            {
              *group = arg[0].val;
              *index = -1;
              return trailer;
            }
          else
            {
              ui_out_message (uiout, 0,
                              "Group index should be in the range 0 - %d\n",
                              OR1K_NUM_SPGS);
              *group = -1;
              *index = -1;
              return trailer;
            }
        }

      /* Is is it a group name? */
      *group = or1k_groupnum_from_name (arg[0].str);
      if (*group >= 0)
        {
          *index = -1;
          return trailer;
        }

      /* See if it is a valid register name in any group */
      for (*group = 0; *group < OR1K_NUM_SPGS; (*group)++)
        {
          *index = or1k_regnum_from_name (*group, arg[0].str);
     
          if (*index >= 0)
            {
              return  trailer;
            }
        }

      /* Couldn't find it - print out a rude message */
      ui_out_message (uiout, 0,
                      "Group or register name not recognized.\n"
                      "Valid groups are:\n");
      for (i = 0; i < OR1K_NUM_SPGS; i++)
        {
          ui_out_field_string (uiout, NULL, or1k_spr_group_name (i));
          ui_out_spaces (uiout, 1);
          ui_out_wrap_hint (uiout, NULL);
        }
      ui_out_field_string (uiout, NULL, "\n");

      *group = -1;
      *index = -1;
      return  trailer;

    case 2:
      /* See if first arg is a numeric group */
      if (arg[0].is_num)
        {
          if (arg[0].val < OR1K_NUM_SPGS)
            {
              *group = arg[0].val;
              *index = -1;
            }
          else
            {
              ui_out_message (uiout, 0,
                              "Group index should be in the range 0 - %d\n",
                              OR1K_NUM_SPGS - 1);
              *group = -1;
              *index = -1;
              return trailer;
            }
        }
      else
        {
          /* Is is it a group name? */
          *group = or1k_groupnum_from_name (arg[0].str);
          if (*group >= 0)
            {
              *index = -1;
            }
          else
            {
              ui_out_message (uiout, 0,
                              "Group name not recognized.\n"
                              "Valid groups are:\n");
              for (i = 0; i < OR1K_NUM_SPGS; i++)
                {
                  ui_out_field_string (uiout, NULL, or1k_spr_group_name (i));
                  ui_out_spaces (uiout, 1);
                  ui_out_wrap_hint (uiout, NULL);
                }
              ui_out_field_string (uiout, NULL, "\n");

              *group = -1;
              *index = -1;
              return  trailer;
            }
        }

      /* Is second arg an index or name? */
      if (arg[1].is_num)
        {
          if (arg[1].val < OR1K_SPG_SIZE)
            {
              /* Check this really is a register */
              if (0 != strlen (or1k_spr_register_name (*group, arg[1].val,
                                                       spr_name)))
                {
                  *index = arg[1].val;
                  return trailer;
                }
              else
                {
                  ui_out_message (uiout, 0,
                                  "No valid register at that index in group\n");
                  *group = -1;
                  *index = -1;
                  return  trailer;
                }
            }
          else
            {
              ui_out_message (uiout, 0,
                              "Register index should be in the range 0 - %d\n",
                              OR1K_SPG_SIZE - 1);
              *group = -1;
              *index = -1;
              return  trailer;
            }
        }

      /* Must be a name */
      *index = or1k_regnum_from_name (*group, arg[1].str);
     
      if (*index >= 0)
        {
          return trailer;
        }

      /* Couldn't find it - print out a rude message */
      ui_out_message (uiout, 0, "Register name not recognized in group.\n");
      *group = -1;
      *index = -1;
      return  trailer;
   
    default:
      /* Anything else is an error */
      ui_out_message (uiout, 0, "Unable to parse arguments\n");
      *group = -1;
      *index = -1;
      return  trailer;
    }
} /* or1k_parse_spr_params() */


/*---------------------------------------------------------------------------*/
/*!Read a special purpose register from the target

   This has to be done using the target remote command "readspr"

   @param[in] regnum  The register to read

   @return  The value read */
/*---------------------------------------------------------------------------*/

static ULONGEST
or1k_read_spr (unsigned int  regnum)
{
  struct ui_file    *uibuf = mem_fileopen ();
  char               cmd[sizeof ("readspr ffff")];
  unsigned long int  data;
  char              *res;
  long int           len;

  /* Create the command string and pass it to target remote command function */
  sprintf (cmd, "readspr %4x", regnum);
  target_rcmd (cmd, uibuf);

  /* Get the output for the UI file as a string */
  res = ui_file_xstrdup (uibuf, &len);
  sscanf (res, "%lx", &data);

  /* Tidy up */
  xfree (res);
  ui_file_delete (uibuf);

  return  (ULONGEST)data;

} /* or1k_read_spr() */


/*---------------------------------------------------------------------------*/
/*!Write a special purpose register on the target

   This has to be done using the target remote command "writespr"

   Since the SPRs may map to GPR's or the other GDB register (PPC, NPC, SR),
   any register cache is flushed.

   @param[in] regnum  The register to write
   @param[in] data  The value to write */
/*---------------------------------------------------------------------------*/

static void
or1k_write_spr (unsigned int  regnum,
                ULONGEST      data)
{
  struct ui_file    *uibuf = mem_fileopen ();
  char               cmd[sizeof ("writespr ffff ffffffff")];
  char              *res;
  long int           len;

  /* Create the command string and pass it to target remote command function */
  sprintf (cmd, "writespr %4x %8llx", regnum, (long long unsigned int)data);
  target_rcmd (cmd, uibuf);

  /* Flush the register cache */
  registers_changed ();

  /* We ignore the result - Rcmd can put out its own error messages. Just
     tidy up */
  ui_file_delete (uibuf);

} /* or1k_write_spr() */


/*----------------------------------------------------------------------------*/
/*!Show the value of a special purpose register or group

   This is a custom extension to the GDB info command.

   @param[in] args
   @param[in] from_tty  True (1) if GDB is running from a TTY, false (0)
   otherwise. */
/*---------------------------------------------------------------------------*/

static void
or1k_info_spr_command (char *args,
                       int   from_tty)
{
  int  group;
  int  index;

  char  spr_name[32];

  or1k_parse_spr_params (args, &group, &index, 0);

  if (group < 0)
    {
      return; /* Couldn't parse the args */
    }

  if (index >= 0)
    {
      ULONGEST  value = or1k_read_spr (OR1K_SPR (group, index));

      ui_out_field_fmt (uiout, NULL, "%s.%s = SPR%i_%i = %llu (0x%llx)\n",
                        or1k_spr_group_name (group),
                        or1k_spr_register_name (group, index, spr_name), group,
                        index, (long long unsigned int)value, (long long unsigned int)value);
    }
  else
    {
      /* Print all valid registers in the group */
      for (index = 0; index < OR1K_SPG_SIZE; index++)
        {
          if (0 != strlen (or1k_spr_register_name (group, index, spr_name)))
            {
              ULONGEST  value = or1k_read_spr (OR1K_SPR (group, index));

              ui_out_field_fmt (uiout, NULL,
                                "%s.%s = SPR%i_%i = %llu (0x%llx)\n",
                                or1k_spr_group_name (group),
                                or1k_spr_register_name (group, index, spr_name),
                                group, index, (long long unsigned int)value, (long long unsigned int)value);
            }
        }
    }
} /* or1k_info_spr_command() */


/*----------------------------------------------------------------------------*/
/*!Set a special purpose register

   This is a custom command added to GDB.

   @param[in] args
   @param[in] from_tty  True (1) if GDB is running from a TTY, false (0)
   otherwise. */
/*---------------------------------------------------------------------------*/

static void
or1k_spr_command (char *args,
                  int   from_tty)
{
  int   group;
  int   index;
  char *tmp_str;
  char *nargs = or1k_parse_spr_params (args, &group, &index, 1);

  ULONGEST  old_val;
  ULONGEST  new_val;

  char  spr_name[32];

  /* Do we have a valid register spec? */
  if (index < 0)
    {
      return; /* Parser will have printed the error message */
    }

  /* Do we have a value to set? */

  errno = 0;
  new_val = (ULONGEST)strtoul (nargs, &tmp_str, 0);

  if((0 != errno) || ('\0' != *tmp_str))
    {
      ui_out_message (uiout, 0, "Invalid value - register not changed\n");
      return;
    }

  old_val = or1k_read_spr (OR1K_SPR (group, index));

  or1k_write_spr (OR1K_SPR (group, index) , new_val);

  ui_out_field_fmt (uiout, NULL,
                    "%s.%s (SPR%i_%i) set to %llu (0x%llx), "
                    "was: %llu (0x%llx)\n",
                    or1k_spr_group_name (group),
                    or1k_spr_register_name (group, index, spr_name) , group,
                    index, (long long unsigned int)new_val, (long long unsigned int)new_val, (long long unsigned int)old_val, (long long unsigned int)old_val);

} /* or1k_spr_command() */


/*----------------------------------------------------------------------------*/
/*!Main entry point for target architecture initialization

   In this version initializes the architecture via
   registers_gdbarch_init(). Add a command to set and show special purpose
   registers. */
/*---------------------------------------------------------------------------*/

void
_initialize_or1k_tdep (void)
{
  /* Register this architecture. We should do this for or16 and or64 when
     they have their BFD defined. */
  gdbarch_register (bfd_arch_or32, or1k_gdbarch_init, or1k_dump_tdep);

  /* Initialize the automata for the assembler */
  build_automata();

  /* Commands to show and set special purpose registers */
  add_info ("spr", or1k_info_spr_command,
            "Show the value of a special purpose register");
  add_com ("spr", class_support, or1k_spr_command,
           "Set a special purpose register");

} /* _initialize_or1k_tdep() */


[remote-or1k.c]

/* Remote debugging interface for various or1k debugging protocols.
   Currently supported or1k targets are: simulator, jtag, dummy.

   Copyright 1993-1995, 2000 Free Software Foundation, Inc.
   Copyright 2008 Embecosm Limited

   Contributed by Cygnus Support.  Written by Marko Mlinar
   <markom@...>
   Contributor Jeremy Bennett <jeremy.bennett@...>

   This file is part of GDB.

   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 the Free
   Software Foundation; either version 3 of the License, or (at your option)
   any later version.

   This program is distributed in the hope that it will be useful, but WITHOUT
   ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
   FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
   more details.

   You should have received a copy of the GNU General Public License along
   with this program.  If not, see <http://www.gnu.org/licenses/>.
*/

/*--------------------------------------------------------------------------*/
/*!Updated for GDB 6.8 by Jeremy Bennett. All code converted to ANSI C style
   and in general to GDB format. All global OpenRISC specific functions and
   variables should now have a prefix of or1k_ or OR1K_.

   This original code defined three possible remote targets "jtag", "sim" and
   "dummy", all using the OpenRISC 1000 remote protocol. However only "jtag"
   is actually implemented, and in this version, all the redundant code is
   stripped out. The intention is that in time all remote debugging will be
   via the Remote Serial Protocol.

   Commenting compatible with Doxygen added throughout. */
/*---------------------------------------------------------------------------*/


#include "defs.h"
#include "inferior.h"
#include "bfd.h"
#include "symfile.h"
#include "gdb_wait.h"
#include "gdbcmd.h"
#include "gdbcore.h"
#include "target.h"
#include "gdb_string.h"
#include "event-loop.h"
#include "event-top.h"
#include "inf-loop.h"
#include "regcache.h"

#include <signal.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/ioctl.h>
#include <fcntl.h>

#include "or1k-tdep.h"
#include "or1k-jtag.h"
#include "exceptions.h"
#include "frame.h"
#include "opcode/or32.h"
#include "solib.h"

#include <arpa/inet.h>


/*! The current OR1K target */
static struct target_ops  or1k_target;

/*! Are we single stepping */
static int  or1k_is_single_stepping;

/*! Cached OR1K debug register values (ignores counters for now). */
static struct {
  unsigned long int  dvr[OR1K_MAX_MATCHPOINTS];
  struct {
    enum {
      OR1K_CT_DISABLED = 0, /* Disabled */
      OR1K_CT_FETCH    = 1, /* Compare to fetch EA */
      OR1K_CT_LEA      = 2, /* Compare to load EA */
      OR1K_CT_SEA      = 3, /* Compare to store EA */
      OR1K_CT_LDATA    = 4, /* Compare to load data */
      OR1K_CT_SDATA    = 5, /* Compare to store data */
      OR1K_CT_AEA      = 6, /* Compare to load/store EA */
      OR1K_CT_ADATA    = 7 /* Compare to load/store data */
    }    ct; /* Compare to what? */
    int  sc; /* Signed comparision */
    enum {
      OR1K_CC_MASKED   = 0,
      OR1K_CC_EQ       = 1,
      OR1K_CC_LT       = 2,
      OR1K_CC_LE       = 3,
      OR1K_CC_GT       = 4,
      OR1K_CC_GE       = 5,
      OR1K_CC_NE       = 6,
      OR1K_CC_RESERVED = 7
    }    cc; /* Compare operation */
    int  dp; /* DVR/DCP present */
  }                  dcr[OR1K_MAX_MATCHPOINTS];
  unsigned long int  dmr1;
  unsigned long int  dmr2;
  unsigned long int  dsr;
  unsigned long int  drr;
} or1k_dbgcache;

/*! Old SIGINT handler.  */
static void (*or1k_old_intr_handler) (int) = NULL;

/* Forward declaration of global functions to access SPRs. */

ULONGEST  or1k_read_spr (unsigned int  regnum);
void      or1k_write_spr (unsigned int  regnum,
                          ULONGEST      data);

/* Forward declaration of support functions to handle user interrupt */

static void  or1k_interrupt_query();
static void  or1k_interrupt (int signo);
static void  or1k_interrupt_twice (int signo);

/* Forward declaration of support functions to handle breakpoints */

static unsigned char  or1k_gdb_to_dcr_type (enum target_hw_bp_type  gdb_type);
static int            or1k_set_breakpoint (CORE_ADDR  addr);
static int            or1k_clear_breakpoint (CORE_ADDR  addr);
static int            or1k_watchpoint_gc ();
static int            or1k_stopped_watchpoint_info (CORE_ADDR *addr_p,
                                                    int       *mp_p);

/* Forward declarations of support functions for the remote operations */

static int        or1k_regnum_to_sprnum (int regnum);
static void       or1k_commit_debug_registers();
static void       or1k_start_remote (struct ui_out *uiout,
                                     void          *arg);

/* Forward declarations of functions for the remote operations */

static void     or1k_files_info (struct target_ops *target);
static void     or1k_open (char *name,
                           int   from_tty);
static void     or1k_close (int quitting);
static void     or1k_detach (char *args,
                             int   from_tty);
static void     or1k_fetch_registers (struct regcache *regcache,
                                      int              regnum);
static void     or1k_store_registers (struct regcache *regcache,
                                      int              regnum);
static void     or1k_prepare_to_store (struct regcache *regcache);
static LONGEST  or1k_xfer_partial (struct target_ops  *ops,
                                   enum target_object  object,
                                   const char         *annex,
                                   gdb_byte           *readbuf,
                                   const gdb_byte     *writebuf,
                                   ULONGEST            offset,
                                   LONGEST             len);
static int      or1k_insert_breakpoint (struct bp_target_info *bpi);
static int      or1k_remove_breakpoint (struct bp_target_info *bpi);
static int      or1k_can_use_hw_matchpoint (int  type,
                                            int  count,
                                            int  othertype);
static int      or1k_insert_hw_breakpoint (struct bp_target_info *bpi);
static int      or1k_remove_hw_breakpoint (struct bp_target_info *bpi);
static int      or1k_insert_watchpoint (CORE_ADDR  addr,
                                        int        len,
                                        int        type);
static int      or1k_remove_watchpoint (CORE_ADDR  addr,
                                        int        len,
                                        int        type);
static int      or1k_stopped_by_watchpoint();
static int      or1k_stopped_data_address (struct target_ops *target,
                                           CORE_ADDR         *addr_p);
static int      or1k_region_ok_for_hw_watchpoint (CORE_ADDR  addr,
                                                  int        len);
static void     or1k_resume (ptid_t              ptid,
                             int                 step,
                             enum target_signal  sig);
static ptid_t   or1k_wait (ptid_t                    remote_ptid,
                           struct target_waitstatus *status);
static void     or1k_stop ();
static void     or1k_kill ();
static void     or1k_create_inferior (char  *execfile,
                                      char  *args,
                                      char **env,
                                      int    from_tty);
static void     or1k_mourn_inferior ();
static void     or1k_rcmd (char           *command,
                           struct ui_file *outbuf);


/*---------------------------------------------------------------------------*/
/*!Ask the user about an interrupt

  Ctrl-C has been received. */
/*---------------------------------------------------------------------------*/

static void
or1k_interrupt_query()
{
  target_terminal_ours ();

  if (query ("OpenRISC remote JTAG interrupted while waiting for the program\n"
             "Give up (and stop debugging it)? "))
    {
      const struct gdb_exception e = {
        .reason  = RETURN_QUIT,
        .error   = GENERIC_ERROR,
        .message = "OpenRISC remote JTAG debugging interrupted"
      };

      or1k_mourn_inferior ();
      throw_exception (e);
    }

  target_terminal_inferior ();

} /* or1k_interrupt_query() */


/*---------------------------------------------------------------------------*/
/*!The command line interface's stop routine from an interrupt

   Attempt to stop the processor. Set a more severe interrupt routine, so that
   a second ctrl-C will force more aggressive behavior.

   @param[in] signo  The signal which triggered this handle (always SIGINT) */
/*---------------------------------------------------------------------------*/

static void
or1k_interrupt (int signo)
{
  quit_flag = 1; /* For passive stops */
  or1k_stop (); /* Actively stall the processor */

  /* If this doesn't work, try more severe steps. */
  signal (signo, or1k_interrupt_twice);

} /* or1k_interrupt() */


/*---------------------------------------------------------------------------*/
/*!More aggressive interrupt handler

   The user typed ^C twice. We ask if they want to kill everything. If they
   don't we put this signal handler back in place, so another ctrl-C will
   bring us back heer.

   @param[in] signo  The signal which triggered this handle (always SIGINT) */
/*---------------------------------------------------------------------------*/

static void
or1k_interrupt_twice (int signo)
{
  /* Restore the old interrupt handler */
  if (NULL != or1k_old_intr_handler)
    {
      signal (signo, or1k_old_intr_handler);
    }

  or1k_interrupt_query();

  /* If we carry on keep this as the signal handler */
  signal (signo, or1k_interrupt_twice);

} /* or1k_interrupt_twice() */


/*---------------------------------------------------------------------------*/
/*!Translate GDB watchpoint type into data control register compare to bits

   @param[in] gdb_type  GDB watchpoint type

   @return  The corresponding data control register compare to bits */
/*---------------------------------------------------------------------------*/

static unsigned char
or1k_gdb_to_dcr_type (enum target_hw_bp_type  gdb_type)
{
  switch (gdb_type)
    {
    case hw_write:  return  OR1K_CT_SEA;
    case hw_read:   return  OR1K_CT_LEA;
    case hw_access: return  OR1K_CT_AEA;

    default:
      error  ("or1k_gdb_to_dcr_type: Invalid type %d\n", gdb_type );
      return  -1;
    }
} /* or1k_gdb_to_dcr_type */


/*---------------------------------------------------------------------------*/
/*!Find the first free matchpoint

  @return  The first free matchpoint, or -1 if none is available. */
/*---------------------------------------------------------------------------*/

static int
or1k_first_free_matchpoint ()
{
  struct gdbarch_tdep *tdep = gdbarch_tdep (current_gdbarch);
  int i;
 
  /* Search for unused matchpoint.  */
  for (i = 0; i < tdep->num_matchpoints; i++)
    {
      if (!or1k_dbgcache.dcr[i].dp)
        {
          return  i;
        }
    }

  return  -1;

} /* or1k_first_free_matchpoint() */


/*---------------------------------------------------------------------------*/
/*!Set a breakpoint.

   @param[in] addr  The address at which to set the breakpoint

   @return  0 if the breakpoint was set, non-zero otherwise */
/*---------------------------------------------------------------------------*/

static int
or1k_set_breakpoint (CORE_ADDR  addr)
{
  int mp = or1k_first_free_matchpoint();

  if (mp < 0)
    {
      return  1;
    }

  /* Set the value register to the address where we should breakpoint and the
     control register for unsigned match to the fetched effective address. */
  or1k_dbgcache.dvr[mp]    = addr;

  or1k_dbgcache.dcr[mp].dp = 1;
  or1k_dbgcache.dcr[mp].cc = OR1K_CC_EQ;
  or1k_dbgcache.dcr[mp].sc = 0;
  or1k_dbgcache.dcr[mp].ct = OR1K_CT_FETCH;

  /* No chaining here. Watchpoint triggers a break */
  or1k_dbgcache.dmr1 &= ~(OR1K_DMR1_CW << (OR1K_DMR1_CW_SZ * mp));
  or1k_dbgcache.dmr2 |= (1 << (mp + OR1K_DMR2_WGB_OFF));

  return 0;

} /* or1k_set_breakpoint() */


/*---------------------------------------------------------------------------*/
/*!See if a matchpoint has the given qualities

   The fields in the matchpoint DVR and DCR registers must match and the
   matchpoint must be in use.

   @param[in] mp    The matchpoint of interest
   @param[in] addr  The address to compare
   @param[in] cc    The condition code to compare
   @param[in] sc    The signedness to compare
   @param[in] ct    The comparision type to compare

   @return  1 (true) if the fields are the same and the matchpoint is in use */
/*---------------------------------------------------------------------------*/

static int
or1k_matchpoint_equal (int            mp,
                       CORE_ADDR      addr,
                       unsigned char  cc,
                       unsigned char  sc,
                       unsigned char  ct)
{
  int res =  or1k_dbgcache.dcr[mp].dp          &&
            (or1k_dbgcache.dcr[mp].cc == cc  ) &&
            (or1k_dbgcache.dcr[mp].sc == sc  ) &&
            (or1k_dbgcache.dcr[mp].ct == ct  ) &&
            (or1k_dbgcache.dvr[mp]    == addr);

  return  res;

} /* or1k_matchpoint_equal() */


/*---------------------------------------------------------------------------*/
/*!Clear a breakpoint.

   @param[in] addr  The address at which to clear the breakpoint

   @return  0 if the breakpoint was cleared, non-zero otherwise */
/*---------------------------------------------------------------------------*/

static int
or1k_clear_breakpoint (CORE_ADDR  addr)
{
  struct gdbarch_tdep *tdep = gdbarch_tdep (current_gdbarch);
  int                  mp;
 
  /* Search for matching breakpoint.  */
  for (mp = 0; mp < tdep->num_matchpoints; mp++)
    {
      if (or1k_matchpoint_equal (mp, addr, OR1K_CC_EQ, 0, OR1K_CT_FETCH))
        {
          break;
        }
    }

  if (mp >= tdep->num_matchpoints)
    {
      return 1;
    }

  /* Mark the matchpoint unused and clear its bits in the assign to counter,
     watchpoint generating break and breakpoint status bits in DMR2. */
  or1k_dbgcache.dcr[mp].dp = 0;
 
  or1k_dbgcache.dmr2 &= ~(1 << (mp + OR1K_DMR2_AWTC_OFF));
  or1k_dbgcache.dmr2 &= ~(1 << (mp + OR1K_DMR2_WGB_OFF));
  or1k_dbgcache.dmr2 &= ~(1 << (mp + OR1K_DMR2_WBS_OFF));

  return 0;

} /* or1k_clear_breakpoint() */


/*---------------------------------------------------------------------------*/
/*!Garbage collect the HW watchpoints

   Some functions require more than one OpenRISC 1000 HW watchpoint to be
   chained together. Chained wathcpoints must be adjacent, but setting of
   breakpoints (which uses a single HW matchpoint/watchpoint) can lead to
   fragmentation of the watchpoint list.

   This function allows the currently used matchpoints to be shuffled up. In
   other words we have a GARBAGE COLLECTOR (omninous music, thunder
   clouds gather, lightning flashes).

   For added fun, watchpoints 8 and 9 cannot be moved, and hence nothing that
   depends on them.

   @return  The number of free watchpoints */
/*---------------------------------------------------------------------------*/

static int
or1k_watchpoint_gc ()
{
  struct gdbarch_tdep *tdep          = gdbarch_tdep (current_gdbarch);
  unsigned long int    bits;
  int                  first_free;
  int                  first_used;
  int                  first_fixed;
 
  /* Find the last moveable watchpoint by starting from the top and working
     down until we find a point where the watchpoint is not dependent on its
     predecessor. */

  for (first_fixed = tdep->num_matchpoints; first_fixed > 0; first_fixed--)
    {
      bits = (or1k_dbgcache.dmr1 >> (OR1K_DMR1_CW_SZ * first_fixed)) &
             OR1K_DMR1_CW;

      if ((OR1K_DMR1_CW_AND != bits) && (OR1K_DMR1_CW_OR != bits))
        {
          break; /* Chain is broken */
        }
    }

  /* Give up if there aren't two to be considered */
  if (first_fixed < 2)
    {
      return  first_fixed;
    }

  /* Move matchpoints, and hence unused HW watchpoints to the top (i.e to
     first_fixed - 1). If we move a matchpoint, then all the HW watchpoints
     above must be shuffled down. Although HW watchpoints refer to
     matchpoints, it is a fixed reference based on index. So long as the HW
     watchpoint and the matchpoint are moved together, and the ordering
     remains unchanged all will be OK. Any chained watchpoints will be
     adjacent, and will remain adjacent after this exercise. */

  first_free = 0;
  first_used = 0;

  while (1)
    {
      /* Find the first free matchpoint */
      for( ; first_free < first_fixed; first_free++ )
        {
          if (!(or1k_dbgcache.dcr[first_free].dp))
            {
              break;
            }
        }

      if (first_free > (first_fixed - 2))
        {
          return first_fixed - first_free; /* No more to move */
        }

      /* Find the first fixed breakpoint */
      for (first_used = first_free + 1; first_used < first_fixed; first_used++)
        {
          if (or1k_dbgcache.dcr[first_used].dp)
            {
              break;
            }
        }

      if (first_used >  (first_fixed - 1))
        {
          return first_fixed - first_free; /* No more to move */
        }

      /* Move matchpoint in DVR and DCR registers. */
      or1k_dbgcache.dvr[first_free]    = or1k_dbgcache.dvr[first_used];
      or1k_dbgcache.dcr[first_free]    = or1k_dbgcache.dcr[first_used];
      or1k_dbgcache.dcr[first_used].dp = 0;

      /* Copy chaining bits in DMR1.  */
      bits = (or1k_dbgcache.dmr1 >> (OR1K_DMR1_CW_SZ * first_used)) &
             OR1K_DMR1_CW;
      or1k_dbgcache.dmr1 &= ~(OR1K_DMR1_CW << (OR1K_DMR1_CW_SZ * first_used));
      or1k_dbgcache.dmr1 &= ~(OR1K_DMR1_CW << (OR1K_DMR1_CW_SZ * first_free));
      or1k_dbgcache.dmr1 |=  (bits         << (OR1K_DMR1_CW_SZ * first_free));
                         
      /* Copy assign to counter, watchpoint generating break and breakpoint
         status bits in DMR2 */

      bits = (or1k_dbgcache.dmr2 >> (OR1K_DMR2_AWTC_OFF + first_used)) & 1;
      or1k_dbgcache.dmr2 &= ~(1    << (OR1K_DMR2_AWTC_OFF + first_used));
      or1k_dbgcache.dmr2 &= ~(1    << (OR1K_DMR2_AWTC_OFF + first_free));
      or1k_dbgcache.dmr2 |=  (bits << (OR1K_DMR2_AWTC_OFF + first_free));

      bits = (or1k_dbgcache.dmr2 >> (OR1K_DMR2_WGB_OFF + first_used)) & 1;
      or1k_dbgcache.dmr2 &= ~(1    << (OR1K_DMR2_WGB_OFF + first_used));
      or1k_dbgcache.dmr2 &= ~(1    << (OR1K_DMR2_WGB_OFF + first_free));
      or1k_dbgcache.dmr2 |=  (bits << (OR1K_DMR2_WGB_OFF + first_free));

      bits = (or1k_dbgcache.dmr2 >> (OR1K_DMR2_WBS_OFF + first_used)) & 1;
      or1k_dbgcache.dmr2 &= ~(1    << (OR1K_DMR2_WBS_OFF + first_used));
      or1k_dbgcache.dmr2 &= ~(1    << (OR1K_DMR2_WBS_OFF + first_free));
      or1k_dbgcache.dmr2 |=  (bits << (OR1K_DMR2_WBS_OFF + first_free));

      first_free++;
    }
} /* or1k_watchpoint_gc() */
 

/*---------------------------------------------------------------------------*/
/*!Find if we were stopped by a watchpoint, and if so which address

   This is true if a triggered breakpoint was ANDed with the previous
   watchpoint in the chain. If so, the previous matchpoint has the start
   address.

   This is an internal utility for use by or1k_stopped_watchpoint() and
   or1k_stopped_data_address().

   @note This will only find the FIRST watchpoint triggered.

   @param[out] addr_p  Where to put the address associated with the
                       watchpoint if non-NULL
   @param[out] mp_p    Where to put the matchpoint which triggered the WP

   @return  1 (true) if we get the address, 0 (false) otherwise */
/*---------------------------------------------------------------------------*/

static int
or1k_stopped_watchpoint_info (CORE_ADDR *addr_p,
                              int       *mp_p)
{
  struct gdbarch_tdep *tdep = gdbarch_tdep (current_gdbarch);
  int                  mp;

  /* Cannot be the first matchpoint (it has to AND with one previous) */
  for( mp = 1 ; mp < tdep->num_matchpoints ; mp++ )
    {
      if (((or1k_dbgcache.dmr2 >> (mp + OR1K_DMR2_WBS_OFF)) & 1) &&
          (OR1K_DMR1_CW_AND ==
           ((or1k_dbgcache.dmr1 >> (mp * OR1K_DMR1_CW_SZ)) & OR1K_DMR1_CW)))
        {
          if (NULL != addr_p)
            {
              *addr_p = or1k_dbgcache.dvr[mp - 1];
            }

          if (NULL != mp_p)
            {
              *mp_p = mp;
            }

          return  1;
        }
    }

  return  0;

} /* or1k_stopped_watchpoint_info() */


/*---------------------------------------------------------------------------*/
/*!Convert a register number to SPR number

   OR1K debug unit has GPRs mapped to SPRs, which are not compact, so we are
   mapping them for GDB.

   Rewritten by CZ 12/09/01

   @param[in] regnum  The register

   @return  The corresponding SPR or -1 on failure */
/*---------------------------------------------------------------------------*/

static int
or1k_regnum_to_sprnum (int regnum)
{
  /* The GPRs map as a block */
  if (regnum < OR1K_MAX_GPR_REGS)
    {
      return  OR1K_SPR (OR1K_SPG_SYS, OR1K_SPG_SYS_GPR + regnum);
    }

  /* The "special" registers */
  switch (regnum)
    {
    case OR1K_PPC_REGNUM: return  OR1K_NPC_SPRNUM;
    case OR1K_NPC_REGNUM: return  OR1K_NPC_SPRNUM;
    case OR1K_SR_REGNUM:  return  OR1K_SR_SPRNUM;

    default:
      error ("or1k_regnum_to_sprnum: invalid register number!");
      break;
    }

  return -1;

} /* or1k_regnum_to_sprnum() */


/*---------------------------------------------------------------------------*/
/*!Sync debug registers

   Synchronizes debug registers in memory with those on target. This used to
   track if there was any change, but there always is with debuggers, so now
   we just write them every time.

   The old code did a lot of this via low-level manipulation of the JTAG
   interface. For now it is replaced by straightward reading/writing of the
   SPRs. */
/*---------------------------------------------------------------------------*/

static void
or1k_commit_debug_registers()
{
  struct gdbarch_tdep *tdep = gdbarch_tdep (current_gdbarch);
  int                  i;

  /* Matchpoints (breakpoints, watchpoints).  */
  for (i = 0; i < tdep->num_matchpoints; i++)
    {
      unsigned long int  dcr = 0;

      dcr |= or1k_dbgcache.dcr[i].dp ? OR1K_DCR_DP : 0;
      dcr |= (or1k_dbgcache.dcr[i].cc << OR1K_DCR_CC_OFF) & OR1K_DCR_CC;
      dcr |= or1k_dbgcache.dcr[i].sc ? OR1K_DCR_SC : 0;
      dcr |= (or1k_dbgcache.dcr[i].ct << OR1K_DCR_CT_OFF) & OR1K_DCR_CT;

      or1k_jtag_write_spr (OR1K_DVR0_SPRNUM + i, or1k_dbgcache.dvr[i]);
      or1k_jtag_write_spr (OR1K_DCR0_SPRNUM + i, dcr);
    }

  or1k_jtag_write_spr (OR1K_DMR1_SPRNUM, or1k_dbgcache.dmr1);
  or1k_jtag_write_spr (OR1K_DMR2_SPRNUM, or1k_dbgcache.dmr2);
  or1k_jtag_write_spr (OR1K_DSR_SPRNUM,  or1k_dbgcache.dsr);
  or1k_jtag_write_spr (OR1K_DRR_SPRNUM,  or1k_dbgcache.drr);

} /* or1k_commit_debug_registers() */


/*---------------------------------------------------------------------------*/
/*!Start the remote target

   This is a wrapper for GDB's start_remote function, suitable for use with
   catch_exception.

   @param[in] uiout  UI handle - not used
   @param[in] arg_p  Reference to the generic argument supplied through
                     catch_exception. In this case a pointer to the from_tty
                     parameter. */
/*--------------------------------------------------------------------------*/

static void
or1k_start_remote (struct ui_out *uiout,
                   void          *arg_p)
{
  int  from_tty = *((int *)arg_p);

  start_remote( from_tty );

} /* or1k_start_remote() */


/*---------------------------------------------------------------------------*/
/*!Print info on this target.

  @param[in] target  GDB ops for the target - ignored. */
/*---------------------------------------------------------------------------*/

static void
or1k_files_info (struct target_ops *target)
{
  const char *status_name[] =
    {
      "UNDEFINED",
      "CONNECTING",
      "DISCONNECTING",
      "RUNNING",
      "STOPPED"
    };

  char *file = "nothing";

  if (exec_bfd)
    {
      file = bfd_get_filename (exec_bfd);
    }

  printf_filtered ("File \"%s\"", file);

  if (exec_bfd)
    {
      printf_filtered ("attached to %s running program %s: ",
                       target_shortname, file);
    }
} /* or1k_files_info() */


/*---------------------------------------------------------------------------*/
/*!Open a connection to the remote server

   Initialise the connection, then push the current target.

   @param[in] name      The arguments passed to the target command on GDB -
                        usually the address of the remote server
   @param[in] from_tty  1 (true) if the GDB session is being run from a
                        terminal and so can receive messages. 0 (false)
                        otherwise. */
/*---------------------------------------------------------------------------*/

static void
or1k_open (char *name,
           int   from_tty)
{
  struct gdbarch_tdep *tdep     = gdbarch_tdep (current_gdbarch);
  int                  i;
  unsigned int         tmp;
  struct gdb_exception ex;

  /* Check nothing's still running. This will call or1k_close if anything is,
     which will close the connection. Having done this, any remaining target
     instances should be unpushed from the stack */
  target_preopen (from_tty);
  unpush_target (&or1k_target);

  /* Initialize the connection to the remote target. */
  or1k_jtag_init (name);

  /* Make sure we have system and debug groups implemented. */
  tmp = or1k_jtag_read_spr (OR1K_UPR_SPRNUM);
  if (0 == (tmp & OR1K_SPR_UPR_UP))
    {
      error ("or1k_open: system group missing");
    }
  if (0 == (tmp & OR1K_SPR_UPR_DUP))
    {
      error ("or1k_open: debug group missing");
    }

  /* Determine number of gpr_regs (this is a bit simplified - the bit just
     means "less than 32", but we assume that means 16) and the number of
     supported watchpoints. */
  tmp                = or1k_jtag_read_spr (OR1K_CPUCFGR_SPRNUM);
  tdep->num_gpr_regs = (0 == (tmp & OR1K_SPR_CPUCFGR_CGF)) ? 32 : 16;

  tmp                   = or1k_jtag_read_spr (OR1K_DCFGR_SPRNUM);
  tdep->num_matchpoints = (tmp & OR1K_SPR_DCFGR_NDP) + 1;

  /* Stall the processor. A pause after stalling is appropriate for real
     hardware. */
  or1k_jtag_stall ();
  usleep (1000);

  /* Initialize the debug register cache. The DSR is set to stop when
     breakpoint occurs. The cache will be written out before unstalling the
     processor. */
  for (i = 0; i < tdep->num_matchpoints; i++)
    {
      or1k_dbgcache.dvr[i] = 0;
      memset (&or1k_dbgcache.dcr[i], 0, sizeof (or1k_dbgcache.dcr[i]));
    }

  or1k_dbgcache.dmr1 = 0;
  or1k_dbgcache.dmr2 = 0;
  or1k_dbgcache.dsr  = OR1K_DSR_TE;
  or1k_dbgcache.drr  = 0;
   
  /* The remote target connection stalls the target, so all aspects of a
     running connection are there, except it doesn't actually have
     execution. So we call target_mark_running, but then immediately mark it
     as not having execution */
  push_target (&or1k_target);
  target_mark_running (&or1k_target);
  target_has_execution = 0;

  /* Get rid of any old shared library symbols. */
  no_shared_libraries (NULL, 0);

  /* We don't have a concept of processs or threads, so we use the null PTID
     for the target. Set this here before the start_remote() code uses it. */
  inferior_ptid = null_ptid;

  /* Start the remote target. Uses our own wrapper, so we can wrap it to
     catch the exeception if it goes tits up. */
  ex = catch_exception (uiout, or1k_start_remote, &from_tty, RETURN_MASK_ALL);
  if (ex.reason < 0)
    {
      pop_target ();
      throw_exception (ex);
    }

} /* or1k_open() */


/*---------------------------------------------------------------------------*/
/*!Close a connection to the remote server

   Use the target extra op is there is one. Don't mourn the inferior - it
   calls us, so we'll get a never ending loop!

   param[in] quitting  If true (1) GDB is going to shut down, so don't worry
   to wait for everything to complete. */
/*--------------------------------------------------------------------------*/

static void
or1k_close (int quitting)
{
  or1k_jtag_close ();

} /* or1k_close() */


/*---------------------------------------------------------------------------*/
/*!Detach from the remote server

   There is only one remote connection, so no argument should be given.

   @param[in] args      Any args given to the detach command
   @param[in] from_tty  True (1) if this GDB session is run from a terminal,
   so messages can be output. */
/*---------------------------------------------------------------------------*/

static void
or1k_detach (char *args,
             int   from_tty)
{
  if (args)
    {
      error ("or1k_detach: \"detach\" takes no arg when remote debugging\n");
    }

  or1k_close (1);

  if (from_tty)
    {
      printf_unfiltered ("Ending remote or1k debugging\n");
    }
} /* or1k_detach() */


/*---------------------------------------------------------------------------*/
/*!Fetch remote registers

   The remote registers are fetched into the register cache

   @param[in] regcache  The register cache to use
   @param[in] regnum    The desired register number, or -1 if all are wanted */
/*---------------------------------------------------------------------------*/

static void
or1k_fetch_registers (struct regcache *regcache,
                      int              regnum)
{
  unsigned long int  val;
  char               buf[sizeof (CORE_ADDR) ];

  if (-1 == regnum)
    {
      /* Get the lot */
      for (regnum = 0; regnum < OR1K_NUM_REGS; regnum++)
        {
          or1k_fetch_registers (regcache, regnum);
        }
      return;
    }

  if (regnum >= OR1K_NUM_REGS)
    {
      error ("or1k_fetch_registers: invalid register number");
    }

  /* Convert to SPRNUM and read.  */
  val = or1k_jtag_read_spr (or1k_regnum_to_sprnum (regnum));

  /* We got the number the register holds, but gdb expects to see a value in
     the target byte ordering.

     This is new for GDB 6.8. Not sure if I need get_thread_regcache() using
     the ptid instead here. The old code used supply_register(), but that no
     longer exists, so we hope regcache_raw_supply will do instead. */

  store_unsigned_integer (buf, sizeof (CORE_ADDR), val);
  regcache_raw_supply (regcache, regnum, buf);

} /* or1k_fetch_registers() */


/*---------------------------------------------------------------------------*/
/*!Store remote registers

   The remote registers are written from the register cache

   @param[in] regcache  The register cache to use
   @param[in] regnum    The desired register number, or -1 if all are wanted */
/*---------------------------------------------------------------------------*/

static void
or1k_store_registers (struct regcache *regcache,
                      int              regnum)
{
  ULONGEST         res;

  if (-1 == regnum)
    {
      for (regnum = 0; regnum < OR1K_NUM_REGS; regnum++)
        {
          or1k_store_registers (regcache, regnum);
        }
      return;
    }

  if (regnum >= OR1K_NUM_REGS)
    {
      error ("or1k_store_registers: invalid register number");
    }

  regcache = get_current_regcache();
  regcache_cooked_read_unsigned (regcache, regnum, &res);
  or1k_jtag_write_spr (or1k_regnum_to_sprnum (regnum), res);

} /* or1k_store_registers() */


/*---------------------------------------------------------------------------*/
/*!Prepare to store registers

   This is a null function for the OpenRisc 1000 architecture

   @param[in] regcache  The register cache to use */
/*---------------------------------------------------------------------------*/

static void
or1k_prepare_to_store (struct regcache *regcache)
{
  return;

} /* or1k_prepare_to_store() */


/*---------------------------------------------------------------------------*/
/*!Transfer some data to or from the target

   One and only one of readbuf or writebuf should be non-NULL, which indicates
   whether this is a read or write operation.

   OR1K reads and writes are in words, so we may need to do partial
   read/writes at each end of the transfer.

   @param[in]  ops       The target_ops vector to use
   @param[in]  object    The type of object to transfer
   @param[in]  annex     Additional object specific information (not used)
   @param[out] readbuf   Buffer for read data
   @param[in]  writebuf  Buffer of data to write
   @param[in]  offset    Offset into object
   @param[in]  len       Max bytes to transer

   @return  Number of bytes transferred or -1 if not supported */
/*---------------------------------------------------------------------------*/

LONGEST  or1k_xfer_partial (struct target_ops  *ops,
                                 enum target_object  object,
                                 const char         *annex,
                                 gdb_byte           *readbuf,
                                 const gdb_byte     *writebuf,
                                 ULONGEST            offset,
                                 LONGEST             len)
{
  /* Only memory transfer is currently supported */
  if (TARGET_OBJECT_MEMORY != object)
    {
      return  -1;
    }

  if (NULL == writebuf)
    {
      /* Must be a read */
      gdb_assert (NULL != readbuf);
     
      return  or1k_jtag_read_mem (offset, readbuf, len);
    }
  else
    {
      return  or1k_jtag_write_mem (offset, writebuf, len);
    }
} /* or1k_xfer_partial() */
   

/*---------------------------------------------------------------------------*/
/*!Insert a breakpoint

   Try to insert a breakpoint. Use hardware breakpoints if they are supported,
   software breakpoints otherwise.

   @param[in] bpi  Break point info with details of the address and a cache to
                   hold the existing memory value if overwriting.

                   @return  0 if the breakpoint was set, non-zero otherwise */
/*---------------------------------------------------------------------------*/

static int
or1k_insert_breakpoint (struct bp_target_info *bpi)
{
  if (0 == or1k_set_breakpoint (bpi->placed_address))
    {
      return 0;
    }
  else
    {
      return  memory_insert_breakpoint (bpi);
    }
} /* or1k_insert_breakpoint() */


/*---------------------------------------------------------------------------*/
/*!Remove a breakpoint

   @param[in] bpi  Break point info with details of the address and a cache to
                   hold the existing memory value if overwriting.

                   @return  0 if the breakpoint was cleared, non-zero otherwise */
/*---------------------------------------------------------------------------*/

static int
or1k_remove_breakpoint (struct bp_target_info *bpi)
{
  /* First try to remove HW breakpoint at address */
  if (0 != or1k_clear_breakpoint (bpi->placed_address))
    {
      return  memory_remove_breakpoint (bpi);
    }
  else
    {
      return  0;
    }
} /* or1k_remove_breakpoint() */


/*---------------------------------------------------------------------------*/
/*!Tell whether we can support a hardware breakpoint or watchpoint

   There are only a fixed number of hardware breakpoints available. Check if
   there are any left. Hardware watchpoints need TWO matchpoints.

   This is only an approximation. An exact response would need full knowledge
   of all the HW resources requested and would need to guarantee those
   resources were not subsequently cannabalized for non-HW breakpoints and
   watchpoints.

   The algorithm is to multiply count by 1 for breakpoints and 2 for
   watchpoints and add 2 if othertype is set. Any matchpoints already used are
   ignored (we cannot know if they relate to the question currently being
   asked). This approach means we will never reject when there is HW
   breakpoint resource available, but we may sometimes accept when there turns
   out to be no HW resource available. But GDB handles that OK (see section
   5.1.2 in the user guide).

   @param[in] type       What type of matchpoint are we asking about? This
                         function is apparently only called for
                         bp_hardware_watchpoint, bp_read_watchpoint,
                         bp_write_watchpoint (but the enum is called
                         access_watchpoint) or bp_hardware_breakpoint
   @param[in] count      How many of this type of matchpoint have been used
                         (including this one)
   @param[in] othertype  1 (true) if this is a call about a watchpoint and
                         watchpoints (but not breakpoints) of other types have
                         been set.

   @return  the number of watchpoints of this type that can be set if count
            watchpoints can be set, 0 if watchpoints of this type cannot be
            set and negative if watchpoints of this type can be set, but there
            are none available. */
/*--------------------------------------------------------------------------*/

static int
or1k_can_use_hw_matchpoint (int  type,
                            int  count,
                            int  othertype)
{
  struct gdbarch_tdep *tdep = gdbarch_tdep (current_gdbarch);

  switch (type)
    {
    case bp_hardware_breakpoint:
      if (count <= tdep->num_matchpoints)
        {
          return  tdep->num_matchpoints;
        }
      else
        {
          return -1;
        }

    case bp_hardware_watchpoint:
    case bp_read_watchpoint:
    case bp_access_watchpoint:
      if ((2 * (othertype + count)) <= tdep->num_matchpoints)
        {
          return  tdep->num_matchpoints / (2 * (othertype + count));
        }
      else
        {
          return  -1;
        }

    default:
      warning( "Request to use unknown hardware matchpoint type: %d\n",
               type );
      return  0;
    }

} /* or1k_can_use_hw_matchpoint() */


/*---------------------------------------------------------------------------*/
/*!Insert a hardware breakpoint

   Try to insert a hardware breakpoint if they are supported.

   @param[in] bpi  Break point info with details of the address and a cache to
                   hold the existing memory value if overwriting.

                   @return  0 if the breakpoint was set, non-zero otherwise */
/*---------------------------------------------------------------------------*/

static int
or1k_insert_hw_breakpoint (struct bp_target_info *bpi)
{
  return  or1k_set_breakpoint (bpi->placed_address);

} /* or1k_insert_hw_breakpoint() */


/*---------------------------------------------------------------------------*/
/*!Remove a hardware breakpoint

   @param[in] bpi  Break point info with details of the address and a cache to
                   hold the existing memory value if overwriting.

                   @return  0 if the breakpoint was cleared, non-zero otherwise */
/*---------------------------------------------------------------------------*/

static int
or1k_remove_hw_breakpoint (struct bp_target_info *bpi)
{
  return  or1k_clear_breakpoint (bpi->placed_address);

} /* or1k_remove_hw_breakpoint() */


/*---------------------------------------------------------------------------*/
/*!Set a data watchpoint.

   A GDB data watchpoint uses a pair of HW watchpoints. The first looks for
   accesses greater than or equal to the start address, the second looks for
   accesses less than or equal to the end address. This allows watching of any
   length of object.

   However because of the way the OpenRISC 1000 chains its watchpoints, a
   suitable adjacent pair must be found. So the watchpoint garbage collector
   is used to shuffle them all up.

   @param[in] addr  Address to be watched
   @param[in] len   Length of the entity to be watched
   @param[in] type  hw_write (0) for a write watchpoint, hw_read (1) for a
                    read watchpoint, or hw_access (2) for a read/write
                    watchpoint.

   @return  0 if the watchpoint was set, -1 otherwise (it must be -1, not just
   any non-zero number, since breakpoint.c tests explicitly for -1 */
/*--------------------------------------------------------------------------*/

static int
or1k_insert_watchpoint (CORE_ADDR  addr,
                        int        len,
                        int        type)
{
  unsigned char        dcr_ct = or1k_gdb_to_dcr_type (type);
  int                  first_free;
 
  if (len < 1)
    {
      return  -1;
    }

  /* Garbage collect and see if we have two adjacent watchpoints available. */

  if( or1k_watchpoint_gc() < 2 )
    {
      return  -1;
    }


  /* Set lower bound at first free matchpoint. */
  first_free               = or1k_first_free_matchpoint();

  or1k_dbgcache.dvr[first_free]     = addr;
  or1k_dbgcache.dcr[first_free].dp  = 1;
  or1k_dbgcache.dcr[first_free].cc  = OR1K_CC_GE;
  or1k_dbgcache.dcr[first_free].sc  = 0;
  or1k_dbgcache.dcr[first_free].ct  = dcr_ct;

  /* Set upper watchpoint bound at next matchpoint. GC guarantees
     it is free. */
  first_free++;

  or1k_dbgcache.dvr[first_free]     = addr + len - 1;
  or1k_dbgcache.dcr[first_free].dp  = 1;
  or1k_dbgcache.dcr[first_free].cc  = OR1K_CC_LE;
  or1k_dbgcache.dcr[first_free].sc  = 0;
  or1k_dbgcache.dcr[first_free].ct  = dcr_ct;
   
  /* Set && chaining of the second matchpoint to the first. This is the only
     one which should generate a breakpoint, since it only occurs when BOTH
     matchpoints trigger. */
  or1k_dbgcache.dmr1 &= ~(OR1K_DMR1_CW     << (OR1K_DMR1_CW_SZ * first_free));
  or1k_dbgcache.dmr1 |=  (OR1K_DMR1_CW_AND << (OR1K_DMR1_CW_SZ * first_free));
  or1k_dbgcache.dmr2 |= (1 << (first_free + OR1K_DMR2_WGB_OFF));

  return 0;

} /* or1k_insert_watchpoint() */


/*---------------------------------------------------------------------------*/
/*!Remove a data watchpoint.

   @param[in] addr  Address being watched
   @param[in] len   Length of the entity being watched
   @param[in] type  0 for a write watchpoint, 1 for a read watchpoint, or 2
                    for a read/write watchpoint

                    @return  0 if the watchpoint was cleared, non-zero otherwise */
/*---------------------------------------------------------------------------*/

static int
or1k_remove_watchpoint (CORE_ADDR  addr,
                        int        len,
                        int        type)
{
  struct gdbarch_tdep *tdep = gdbarch_tdep (current_gdbarch);
  unsigned char        dcr_ct;
  CORE_ADDR            end_addr;
  int                  mp;

  if (len < 1)
    {
      return -1;
    }

  dcr_ct   = or1k_gdb_to_dcr_type (type);
  end_addr = addr + len - 1;

  /* Find the right one. PS. Don't be tempted to compare mp against
     tdep->num_matchpoints - 1. It's unsigned and can be 0, so you'd go
     on for ever! */
  for (mp = 0; (mp + 1) < tdep->num_matchpoints; mp++)
    {
      if (or1k_matchpoint_equal( mp,     addr,     OR1K_CC_GE, 0, dcr_ct) &&
          or1k_matchpoint_equal( mp + 1, end_addr, OR1K_CC_LE, 0, dcr_ct))
        {
          break;
        }
    }
 
  if ((mp + 1) >= tdep->num_matchpoints)
    {
      return -1;
    }

  /* Mark each matchpoint unused and clear the bits for the second watchpoint
     in the assign to counter, watchpoint generating break and breakpoint
     status bits in DMR2. */

  or1k_dbgcache.dcr[mp].dp = 0;

  mp++;
  or1k_dbgcache.dcr[mp].dp = 0;
  or1k_dbgcache.dmr2 &= ~(1 << (mp + OR1K_DMR2_AWTC_OFF));
  or1k_dbgcache.dmr2 &= ~(1 << (mp + OR1K_DMR2_WGB_OFF));
  or1k_dbgcache.dmr2 &= ~(1 << (mp + OR1K_DMR2_WBS_OFF));

  return 0;

} /* or1k_remove_watchpoint() */


/*---------------------------------------------------------------------------*/
/*!Report if we stopped due to a watchpoint

   All the information is calculated by or1k_stopped_data_address, so we must
   reuse that.

   @return  1 (true) if we were stopped by a watchpoint, 0 (false) otherwise */
/*---------------------------------------------------------------------------*/

static int
or1k_stopped_by_watchpoint()
{
  return  or1k_stopped_watchpoint_info (NULL, NULL);

} /* or1k_stopped_by_watchpoint() */


/*---------------------------------------------------------------------------*/
/*!Address for which we were stopped by a remote watchpoint

   This is true if a triggered breakpoint was ANDed with the previous
   watchpoint in the chain. If so, the previous matchpoint has the start
   address.

   This function is called once when a watchpoint is hit, and must clear the
   watchpoint status

   @param[in]  target  The target_ops we are using. Not clear why we need
                       this!
   @param[out] addr_p  Where to put the address associated with the
                       watchpoint.

                       @return  1 (true) if we get the address, 0 (false) otherwise */
/*---------------------------------------------------------------------------*/

static int
or1k_stopped_data_address (struct target_ops *target,
                           CORE_ADDR         *addr_p)
{
  int  mp;

  /* Clear the result info if there was a watchpoint */
  if( or1k_stopped_watchpoint_info (addr_p, &mp))
    {
      or1k_dbgcache.dmr2 &= ~(1 << (mp + OR1K_DMR2_WBS_OFF));
      return  1;
    }
  else
    {
      return  0;
    }
} /* or1k_stopped_data_address() */


/*---------------------------------------------------------------------------*/
/*!Can we put a HW watchpoint of the given size at the given address

   We can always use a HW watchpoint, so long as there are HW watchpoints
   available. This doesn't have to check availablility (see
   or1k_can_use_hw_matchpoint().

   @param[in] addr  The address of interest
   @param[in] len   The length of the region to watch

   @return  1 (true) to indicate we always can do a HW watchpoint */
/*---------------------------------------------------------------------------*/

static int
or1k_region_ok_for_hw_watchpoint (CORE_ADDR  addr,
                                  int        len)
{
  return  1;

} /* or1k_region_ok_for_hw_watchpoint */


/*---------------------------------------------------------------------------*/
/*!Resume execution of the target process.

   "step" says whether to single-step or to run free; "siggnal" is the signal
   value (e.g. SIGINT) to be given to the target, or zero for no signal.

   When we enter this routine the target should be stalled.

   In general GDB sorts out issues of restarting across breakpoints. However
   have to deal with the special case where a breakpoint occurred in the delay
   slot of a branch instruction. In this case the branch should be restarted,
   BUT ONLY if the branch had originally been executed.

   For now we ignore this case (it really is very hard.

   @param[in]  ptid  The process or thread ID - ignored here
   @param[in]  step  If true (1) single step the target
   @param[in]  sig   Signal to give to the target */
/*---------------------------------------------------------------------------*/

static void
or1k_resume (ptid_t              ptid,
             int                 step,
             enum target_signal  sig)
{
  /* Note if we are single stepping. For use when waiting */
  or1k_is_single_stepping = step;

  /* The debug reason register and the watchpoint break status
     are both cleared before resuming. */
  or1k_dbgcache.drr   = 0;
  or1k_dbgcache.dmr2 &= ~OR1K_DMR2_WBS_MASK;

  /* Set single stepping if required */
  if (step)
    {
      or1k_dbgcache.dmr1 |= OR1K_DMR1_ST;
    }
  else
    {
      or1k_dbgcache.dmr1 &= ~OR1K_DMR1_ST;
    }

  or1k_commit_debug_registers();

  /* We can now continue normally, independent of step. If this is called for
     the first time due to a run command, we won't actually be executing, so
     start the target running. */

  or1k_jtag_write_spr( OR1K_NPC_SPRNUM, read_pc());
  target_has_execution = 1;
  or1k_jtag_unstall ();

} /* or1k_resume() */


/*---------------------------------------------------------------------------*/
/*!Wait until the remote server stops, and return a wait status.

   Seems to assume that the remote target is identified solely by PID with no
   thread or lightweight thread component.

   This is mostly a case of just sorting out the type of exception. GDB will
   automatically sort out restarting with breakpoints removed etc.

   @note The old code differentiated a high priority and a low priority
         interrupt, which no longer exists on the OR1K. The old code also
         omitted tick timer and floating point exceptions, which have been
         added.

   @param[in]  remote_ptid  The process/thread ID of the remote target
   @param[out] status       Status of the waiting process

   @return  The remote_ptid unchanged */
/*---------------------------------------------------------------------------*/

static ptid_t
or1k_wait (ptid_t                    remote_ptid,
           struct target_waitstatus *status)
{
  unsigned long int  addr;
  char               buf[OR1K_INSTLEN];
  int                res;

  /* Set new signal handler (so we can interrupt with ctrl-C) and then wait
     for the OR1K to stall. */
  or1k_old_intr_handler = signal (SIGINT, or1k_interrupt);
  or1k_jtag_wait (or1k_is_single_stepping);
  signal (SIGINT, or1k_old_intr_handler);

  /* Registers and frame caches are now all unreliable */
  registers_changed();

  /* Refresh the debug registers that may have changed */
  or1k_dbgcache.drr  = or1k_jtag_read_spr (OR1K_DRR_SPRNUM);
  or1k_dbgcache.dmr2 = or1k_jtag_read_spr (OR1K_DMR2_SPRNUM);

  /* If we got a trap, then it was a breakpoint/watchpoint of some sort (but
     not single step, which does not set the trap exception). We need to back
     up the program counter, so the instruction will be re-executed. This
     must be the value of the PPC, in case we have just done a branch. */

  if (OR1K_DRR_TE == (or1k_dbgcache.drr & OR1K_DRR_TE))
    {
      write_pc (or1k_jtag_read_spr (OR1K_PPC_SPRNUM));
    }

  /* Single step does not set trap exception, so we set it manually to
     simplify our code. */
  if (OR1K_DMR1_ST == (or1k_dbgcache.dmr1 & OR1K_DMR1_ST))
    {
      or1k_dbgcache.drr |= OR1K_DRR_TE;
    }

  status->kind = TARGET_WAITKIND_STOPPED;

  /* Map OR1K exception to GDB signal. If multiple signals are set, only the
     least significant in the DRR is used (the expression here yields the LSB
     in a 2's complement machine) */
  switch (or1k_dbgcache.drr & (-or1k_dbgcache.drr))
    {
    case OR1K_DRR_RSTE:  status->value.sig = TARGET_SIGNAL_PWR;  break;
    case OR1K_DRR_BUSEE: status->value.sig = TARGET_SIGNAL_BUS;  break;
    case OR1K_DRR_DPFE:  status->value.sig = TARGET_SIGNAL_SEGV; break;
    case OR1K_DRR_IPFE:  status->value.sig = TARGET_SIGNAL_SEGV; break;
    case OR1K_DRR_TTE:   status->value.sig = TARGET_SIGNAL_ALRM; break;
    case OR1K_DRR_AE:    status->value.sig = TARGET_SIGNAL_BUS;  break;
    case OR1K_DRR_IIE:   status->value.sig = TARGET_SIGNAL_ILL;  break;
    case OR1K_DRR_INTE:  status->value.sig = TARGET_SIGNAL_INT;  break;
    case OR1K_DRR_DME:   status->value.sig = TARGET_SIGNAL_SEGV; break;
    case OR1K_DRR_IME:   status->value.sig = TARGET_SIGNAL_SEGV; break;
    case OR1K_DRR_RE:    status->value.sig = TARGET_SIGNAL_FPE;  break;
    case OR1K_DRR_SCE:   status->value.sig = TARGET_SIGNAL_USR2; break;
    case OR1K_DRR_FPE:   status->value.sig = TARGET_SIGNAL_FPE;  break;
    case OR1K_DRR_TE:    status->value.sig = TARGET_SIGNAL_TRAP; break;

    default:
      /* This just means the target stopped without raising any
         interrupt. This happens at reset and exit. The latter we distinquish
         by looking at the instruction just executed, to see if it is
         "l.nop NOP_EXIT". If this is the case, get the result from GPR 3 and
         set the NPC to the reset vector, so a new start will behave well. */

      addr = or1k_jtag_read_spr (OR1K_PPC_SPRNUM);
      res  = read_memory_nobpt (addr, buf, OR1K_INSTLEN);
      if (0 != res)
        {
          memory_error (res, addr);
        }

      if (OR1K_NOP_EXIT ==
          (unsigned long int)(extract_unsigned_integer (buf, OR1K_INSTLEN)))
        {
          ULONGEST  val;

          regcache_cooked_read_unsigned(get_current_regcache(),
                                        OR1K_FIRST_ARG_REGNUM, &val);
          status->value.integer = val;
          status->kind          = TARGET_WAITKIND_EXITED;
          write_pc (OR1K_RESET_VECTOR);
        }
      else
        {
          status->value.sig     = TARGET_SIGNAL_DEFAULT;
        }
      break;
    }

  /* Clear the reason register */
  or1k_dbgcache.drr = 0;

  return remote_ptid;

} /* or1k_wait() */


/*---------------------------------------------------------------------------*/
/*!Stop the remote process

   This is the generic stop called via the target vector. When a target
   interrupt is requested, either by the command line or the GUI, we will
   eventually end up here.

   Just stall the processor, put it into single step mode and unstall. */
/*---------------------------------------------------------------------------*/

static void
or1k_stop ()
{
  /* We should not stop the target immediately, since it can be in an
     unfinished state.  So we do a single step.  This should not affect
     anything.  */
  or1k_jtag_stall();

  /* HW STEP.  Set OR1K_DMR1_ST.  */
  or1k_dbgcache.dmr1 |= OR1K_DMR1_ST;
  or1k_commit_debug_registers();

  or1k_jtag_unstall();

} /* or1k_stop () */


/*---------------------------------------------------------------------------*/
/*!Kill the process running on the board

   We just ignore the target. Mourning the inferior will cause the connection
   to be closed. */
/*---------------------------------------------------------------------------*/

static void
or1k_kill ()
{
  or1k_mourn_inferior ();

} /* or1k_kill () */


/*---------------------------------------------------------------------------*/
/*!Start running on the target board by creating an inferior process

   @param[in] execfile  What to run
   @param[in] args      Arguments to pass to the inferior process
   @param[in] env       Environment for the inferior process
   @param[in] from_tty  1 (true) if this session can write to the terminal */
/*---------------------------------------------------------------------------*/

static void
or1k_create_inferior (char  *execfile,
                      char  *args,
                      char **env,
                      int    from_tty)
{
  CORE_ADDR entry_pt;

  if ((NULL != args) && ('\0' != args[0]))
    {
      warning ("or1k_create_inferior: "
               "can't pass arguments to remote OR1K board - ignored");

      /* And don't try to use them on the next "run" command.  */
      execute_command ("set args", from_tty);
    }

  if ((NULL == execfile) || (NULL == exec_bfd))
    {
      warning (
        "or1k_create_inferior: no executable file symbols specified\n"
        "execution will proceed without symbol table. Use the \"file\"\n"
        "command to rectify this.\n");
    }

  /* The code won't actually start executing until it is unstalled in
     or1k_resume(), so we'll call target_mark_running() there. Tidy up from
     last time we were running. */
  init_wait_for_inferior ();

} /* or1k_create_inferior () */


/*---------------------------------------------------------------------------*/
/*!Mourn the inferior process

   We don't atually want to unpush the target - we should be able to call run
   again to restart it. Use the generic mourn and mark it as exited (it it was
   running). */
/*---------------------------------------------------------------------------*/

static void
or1k_mourn_inferior ()
{
  generic_mourn_inferior ();

  if( target_has_execution )
    {
      target_mark_exited (&or1k_target);
    }
} /* or1k_mourn_inferior () */


/*---------------------------------------------------------------------------*/
/*!Send a command to the remote target

   The target can't actually run any remote commands, in the sense of having a
   command interpreter. However we use this as a GDB "standard" way of
   wrapping up commands to access the SPRs.

   Current commands supported are:
   - readspr  <regno>
   - writespr <regno> <value>

   The output is either the value read (for successful read) or OK (for
   successful write) or E01 to indicate and wrror. All values are represented
   as unsigned hex.

   @param[in]  command  The command to execute
   @param[out] output   The result of the command                            */
/*---------------------------------------------------------------------------*/

static void  or1k_rcmd (char           *command,
                        struct ui_file *outbuf)
{
  /* Sort out which command */
  if (0 == strncmp ("readspr", command, strlen ("readspr")))
    {
      unsigned int  regno; /* SPR to read */

      if (1 != sscanf (command, "readspr %4x", ®no))
        {
          error ("or1k_rcmd: unrecognized readspr");
          fputs_unfiltered ("E01", outbuf);
        }
      else
        {
          char      strbuf[sizeof ("ffffffff")];
          ULONGEST  data = or1k_jtag_read_spr (regno);

          sprintf (strbuf, "%8llx", (long long unsigned int)data);
          fputs_unfiltered (strbuf, outbuf);
        }
    }
  else if (0 == strncmp ("writespr", command, strlen ("writespr")))
    {
      unsigned int  regno; /* SPR to write */
      long long unsigned int      data; /* Value to write */

      if (2 != sscanf (command, "writespr %4x %8llx", ®no, &data))
        {
          error ("or1k_rcmd: unrecognized writespr");
          fputs_unfiltered ("E01", outbuf);
        }
      else
        {
          or1k_jtag_write_spr (regno, data);
          fputs_unfiltered ("OK", outbuf);
        }
    }
  else
    {
      error ("or1k_rcmd: unrecognized remote command");
      fputs_unfiltered ("E01", outbuf);
    }
} /* or1k_rcmd () */


/*---------------------------------------------------------------------------*/
/*!Main entry point for the remote OpenRISC JTAG protocol

   Initializes the target ops for each version of the remote
   protocol. Currently only the JTAG protocol is implemented.

   @note Earlier versions of this code provided for a "sim" and "dummy"
         target. However these never had any functionality, so have been
         deleted.

         @return  New CRC */
/*---------------------------------------------------------------------------*/

  void
_initialize_remote_or1k()
{
  /* Set up the JTAG ops. */

  or1k_target.to_shortname                   = "jtag";
  or1k_target.to_longname                    =
    "OpenRISC 1000 debugging over JTAG port";
  or1k_target.to_doc                         =
    "Debug a board using the OpenRISC 1000 JTAG debugging protocol. The\n"
    "target may be connected directly via the parallel port, or may be a\n"
    "remote connection over TCP/IP to another machine, an instance of the\n"
    "Or1ksim architectural simulator, or physical hardware connected by USB\n"
    "with its own standalone control program.\n"
    "\n"
    "The argument is the parallel port device (e.g. /dev/jp) to which it is\n"
    "connected locally or a URL of the form jtag://<hostname>:<port> or\n"
    "jtag://<hostname>:<service> identifying the remote connection.";

  or1k_target.to_files_info                  = or1k_files_info;
  or1k_target.to_stratum                     = process_stratum;
  or1k_target.to_has_all_memory              = 1;
  or1k_target.to_has_memory                  = 1;
  or1k_target.to_has_stack                   = 1;
  or1k_target.to_has_registers               = 1;
  or1k_target.to_has_execution               = 0;
  or1k_target.to_have_steppable_watchpoint   = 0;
  or1k_target.to_have_continuable_watchpoint = 0;

  or1k_target.to_open                        = or1k_open;
  or1k_target.to_close                       = or1k_close;
  or1k_target.to_detach                      = or1k_detach;

  or1k_target.to_fetch_registers             = or1k_fetch_registers;
  or1k_target.to_store_registers             = or1k_store_registers;
  or1k_target.to_prepare_to_store            = or1k_prepare_to_store;
  or1k_target.to_load                        = generic_load;
  or1k_target.to_xfer_partial                = or1k_xfer_partial;

  or1k_target.to_insert_breakpoint           = or1k_insert_breakpoint;
  or1k_target.to_remove_breakpoint           = or1k_remove_breakpoint;
  or1k_target.to_can_use_hw_breakpoint       = or1k_can_use_hw_matchpoint;
  or1k_target.to_insert_hw_breakpoint        = or1k_insert_hw_breakpoint;
  or1k_target.to_remove_hw_breakpoint        = or1k_remove_hw_breakpoint;
  or1k_target.to_insert_watchpoint           = or1k_insert_watchpoint;
  or1k_target.to_remove_watchpoint           = or1k_remove_watchpoint;
  or1k_target.to_stopped_by_watchpoint       = or1k_stopped_by_watchpoint;
  or1k_target.to_stopped_data_address        = or1k_stopped_data_address;
  or1k_target.to_region_ok_for_hw_watchpoint = or1k_region_ok_for_hw_watchpoint;

  or1k_target.to_resume                      = or1k_resume;
  or1k_target.to_wait                        = or1k_wait;
  or1k_target.to_stop                        = or1k_stop;
  or1k_target.to_kill                        = or1k_kill;
  or1k_target.to_create_inferior             = or1k_create_inferior;
  or1k_target.to_mourn_inferior              = or1k_mourn_inferior;

  or1k_target.to_rcmd                        = or1k_rcmd;

  or1k_target.to_magic                       = OPS_MAGIC;

  /* Tell GDB about the new target */

  add_target (&or1k_target);

} /* _initialize_remote_or1k() */


/* EOF */


_______________________________________________
http://www.opencores.org/mailman/listinfo/openrisc

Re: Errors occurred when building GDB using instuctions from EAN2 at

by Jeremy Bennett-4 :: Rate this Message:

Reply to Author | View Threaded | Show Only this Message

On Sat, 2009-02-28 at 00:37 +0800, Sigma HH wrote:

> Hi,
>
> I have successfully built GDB on Ubuntu using gcc4.1.3 after I
> explicitly cast each of the arguments causing complaint to long long
> unsigned int in the following files:
>
> or1k-tdep.c
> remote-or1k.c
> or1k-jtag.c
>
> the modified file is attached in this mail.
>
> Unfortrunately, when I contiue to build Linux kernel (2.6.23)
> following instructions in EAN2, the folloing error occurs:
>
> ====================================================================
> xuebo@ubuntu:~/downloads/or1k_downloads/linux-2.6.23$ make vmlinux
> ARCH=or32 COROSS_COMPILE=/opt/or32/bin/or32-uclinux-
> make: or32-elf-gcc: Command not found
> make: or32-elf-gcc: Command not found
> scripts/kconfig/conf -s arch/or32/Kconfig
> drivers/macintosh/Kconfig:121:warning: 'select' used by config symbol
> 'PMAC_APM_EMU' refers to undefined symbol 'APM_EMULATION'
> make: or32-elf-gcc: Command not found
> make: or32-elf-gcc: Command not found
>   CHK     include/linux/version.h
>   CHK     include/linux/utsrelease.h
>   CC      arch/or32/kernel/asm-offsets.s
> /bin/sh: or32-elf-gcc: not found
> make[1]: *** [arch/or32/kernel/asm-offsets.s] Error 127
> make: *** [prepare0] Error 2
> =====================================================================
>
> Any idea about this? Thanks for the help!

Hi Sigma HH,

Thanks for fixing the GDB files. Could you send me a diff of the
changes, and I'll get them incorporated.

For Linux, you have a typo. It should be "CROSS_COMPILE", not
"COROSS_COMPILE".

HTH,


Jeremy

--
Tel:      +44 (1202) 416955
Cell:     +44 (7970) 676050
SkypeID: jeremybennett
Email:   jeremy.bennett@...
Web:     www.embecosm.com


_______________________________________________
http://www.opencores.org/mailman/listinfo/openrisc

Re: Errors occurred when building GDB using instuctions from EAN2 at

by Sigma HH :: Rate this Message:

Reply to Author | View Threaded | Show Only this Message

Hi Jeremy,

Thanks very much for your help, the linux kernel has been compiled successfully!

A "tar.bz2" is attached in this mail, it contains 3 patch files for each of the three modified files
or1k-tdep.c
remote-or1k.c
or1k-jtag.c

Maybe the bug-report at http://www.opencores.org/ptracker.cgi/list/or1k can be closed.

BR,

Sigma

2009/2/28 Jeremy Bennett <jeremy.bennett@...>
On Sat, 2009-02-28 at 00:37 +0800, Sigma HH wrote:
> Hi,
>
> I have successfully built GDB on Ubuntu using gcc4.1.3 after I
> explicitly cast each of the arguments causing complaint to long long
> unsigned int in the following files:
>
> or1k-tdep.c
> remote-or1k.c
> or1k-jtag.c
>
> the modified file is attached in this mail.
>
> Unfortrunately, when I contiue to build Linux kernel (2.6.23)
> following instructions in EAN2, the folloing error occurs:
>
> ====================================================================
> xuebo@ubuntu:~/downloads/or1k_downloads/linux-2.6.23$ make vmlinux
> ARCH=or32 COROSS_COMPILE=/opt/or32/bin/or32-uclinux-
> make: or32-elf-gcc: Command not found
> make: or32-elf-gcc: Command not found
> scripts/kconfig/conf -s arch/or32/Kconfig
> drivers/macintosh/Kconfig:121:warning: 'select' used by config symbol
> 'PMAC_APM_EMU' refers to undefined symbol 'APM_EMULATION'
> make: or32-elf-gcc: Command not found
> make: or32-elf-gcc: Command not found
>   CHK     include/linux/version.h
>   CHK     include/linux/utsrelease.h
>   CC      arch/or32/kernel/asm-offsets.s
> /bin/sh: or32-elf-gcc: not found
> make[1]: *** [arch/or32/kernel/asm-offsets.s] Error 127
> make: *** [prepare0] Error 2
> =====================================================================
>
> Any idea about this? Thanks for the help!

Hi Sigma HH,

Thanks for fixing the GDB files. Could you send me a diff of the
changes, and I'll get them incorporated.

For Linux, you have a typo. It should be "CROSS_COMPILE", not
"COROSS_COMPILE".

HTH,


Jeremy

--
Tel:      +44 (1202) 416955
Cell:     +44 (7970) 676050
SkypeID: jeremybennett
Email:   jeremy.bennett@...
Web:     www.embecosm.com


_______________________________________________
http://www.opencores.org/mailman/listinfo/openrisc


_______________________________________________
http://www.opencores.org/mailman/listinfo/openrisc

Re: Errors occurred when building GDB using instuctions from EAN2 at

by Sigma HH :: Rate this Message:

Reply to Author | View Threaded | Show Only this Message

Hi Jeremy,

The attachment is forgot in previous email, please check this one.

BR

Sigma

2009/2/28 Sigma HH <sigmahh@...>
Hi Jeremy,

Thanks very much for your help, the linux kernel has been compiled successfully!

A "tar.bz2" is attached in this mail, it contains 3 patch files for each of the three modified files
or1k-tdep.c
remote-or1k.c
or1k-jtag.c

Maybe the bug-report at http://www.opencores.org/ptracker.cgi/list/or1k can be closed.

BR,

Sigma

2009/2/28 Jeremy Bennett <jeremy.bennett@...>

On Sat, 2009-02-28 at 00:37 +0800, Sigma HH wrote:
> Hi,
>
> I have successfully built GDB on Ubuntu using gcc4.1.3 after I
> explicitly cast each of the arguments causing complaint to long long
> unsigned int in the following files:
>
> or1k-tdep.c
> remote-or1k.c
> or1k-jtag.c
>
> the modified file is attached in this mail.
>
> Unfortrunately, when I contiue to build Linux kernel (2.6.23)
> following instructions in EAN2, the folloing error occurs:
>
> ====================================================================
> xuebo@ubuntu:~/downloads/or1k_downloads/linux-2.6.23$ make vmlinux
> ARCH=or32 COROSS_COMPILE=/opt/or32/bin/or32-uclinux-
> make: or32-elf-gcc: Command not found
> make: or32-elf-gcc: Command not found
> scripts/kconfig/conf -s arch/or32/Kconfig
> drivers/macintosh/Kconfig:121:warning: 'select' used by config symbol
> 'PMAC_APM_EMU' refers to undefined symbol 'APM_EMULATION'
> make: or32-elf-gcc: Command not found
> make: or32-elf-gcc: Command not found
>   CHK     include/linux/version.h
>   CHK     include/linux/utsrelease.h
>   CC      arch/or32/kernel/asm-offsets.s
> /bin/sh: or32-elf-gcc: not found
> make[1]: *** [arch/or32/kernel/asm-offsets.s] Error 127
> make: *** [prepare0] Error 2
> =====================================================================
>
> Any idea about this? Thanks for the help!

Hi Sigma HH,

Thanks for fixing the GDB files. Could you send me a diff of the
changes, and I'll get them incorporated.

For Linux, you have a typo. It should be "CROSS_COMPILE", not
"COROSS_COMPILE".

HTH,


Jeremy

--
Tel:      +44 (1202) 416955
Cell:     +44 (7970) 676050
SkypeID: jeremybennett
Email:   jeremy.bennett@...
Web:     www.embecosm.com


_______________________________________________
http://www.opencores.org/mailman/listinfo/openrisc




_______________________________________________
http://www.opencores.org/mailman/listinfo/openrisc

gdb-6.8-tdep-jtag-remote.or1k.ubuntu.patch.tar.bz2 (2K) Download Attachment

Re: Errors occurred when building GDB using instuctions from EAN2 at

by Jeremy Bennett-4 :: Rate this Message:

Reply to Author | View Threaded | Show Only this Message

On Sat, 2009-02-28 at 17:54 +0800, Sigma HH wrote:
> Hi Jeremy,
>
> The attachment is forgot in previous email, please check this one.

Hi Sigma HH,

Thanks for your contribution. I've committed it to CVS and created a new
patch file which people can download.


Jeremy

--
Tel:      +44 (1202) 416955
Cell:     +44 (7970) 676050
SkypeID: jeremybennett
Email:   jeremy.bennett@...
Web:     www.embecosm.com


_______________________________________________
http://www.opencores.org/mailman/listinfo/openrisc