mirror of
https://sourceware.org/git/binutils-gdb.git
synced 2024-12-21 04:42:53 +08:00
fd3619828e
This large patch removes the unnecessary bfd parameter from various bfd section macros and functions. The bfd is hardly ever used and if needed for the bfd_set_section_* or bfd_rename_section functions can be found via section->owner except for the com, und, abs, and ind std_section special sections. Those sections shouldn't be modified anyway. The patch also removes various bfd_get_section_<field> macros, replacing their use with bfd_section_<field>, and adds bfd_set_section_lma. I've also fixed a minor bug in gas where compressed section renaming was done directly rather than calling bfd_rename_section. This would have broken bfd_get_section_by_name and similar functions, but that hardly mattered at such a late stage in gas processing. bfd/ * bfd-in.h (bfd_get_section_name, bfd_get_section_vma), (bfd_get_section_lma, bfd_get_section_alignment), (bfd_get_section_size, bfd_get_section_flags), (bfd_get_section_userdata): Delete. (bfd_section_name, bfd_section_size, bfd_section_vma), (bfd_section_lma, bfd_section_alignment): Lose bfd parameter. (bfd_section_flags, bfd_section_userdata): New. (bfd_is_com_section): Rename parameter. * section.c (bfd_set_section_userdata, bfd_set_section_vma), (bfd_set_section_alignment, bfd_set_section_flags, bfd_rename_section), (bfd_set_section_size): Delete bfd parameter, rename section parameter. (bfd_set_section_lma): New. * bfd-in2.h: Regenerate. * mach-o.c (bfd_mach_o_init_section_from_mach_o): Delete bfd param, update callers. * aoutx.h, * bfd.c, * coff-alpha.c, * coff-arm.c, * coff-mips.c, * coff64-rs6000.c, * coffcode.h, * coffgen.c, * cofflink.c, * compress.c, * ecoff.c, * elf-eh-frame.c, * elf-hppa.h, * elf-ifunc.c, * elf-m10200.c, * elf-m10300.c, * elf-properties.c, * elf-s390-common.c, * elf-vxworks.c, * elf.c, * elf32-arc.c, * elf32-arm.c, * elf32-avr.c, * elf32-bfin.c, * elf32-cr16.c, * elf32-cr16c.c, * elf32-cris.c, * elf32-crx.c, * elf32-csky.c, * elf32-d10v.c, * elf32-epiphany.c, * elf32-fr30.c, * elf32-frv.c, * elf32-ft32.c, * elf32-h8300.c, * elf32-hppa.c, * elf32-i386.c, * elf32-ip2k.c, * elf32-iq2000.c, * elf32-lm32.c, * elf32-m32c.c, * elf32-m32r.c, * elf32-m68hc1x.c, * elf32-m68k.c, * elf32-mcore.c, * elf32-mep.c, * elf32-metag.c, * elf32-microblaze.c, * elf32-moxie.c, * elf32-msp430.c, * elf32-mt.c, * elf32-nds32.c, * elf32-nios2.c, * elf32-or1k.c, * elf32-ppc.c, * elf32-pru.c, * elf32-rl78.c, * elf32-rx.c, * elf32-s390.c, * elf32-score.c, * elf32-score7.c, * elf32-sh.c, * elf32-spu.c, * elf32-tic6x.c, * elf32-tilepro.c, * elf32-v850.c, * elf32-vax.c, * elf32-visium.c, * elf32-xstormy16.c, * elf32-xtensa.c, * elf64-alpha.c, * elf64-bpf.c, * elf64-hppa.c, * elf64-ia64-vms.c, * elf64-mmix.c, * elf64-ppc.c, * elf64-s390.c, * elf64-sparc.c, * elf64-x86-64.c, * elflink.c, * elfnn-aarch64.c, * elfnn-ia64.c, * elfnn-riscv.c, * elfxx-aarch64.c, * elfxx-mips.c, * elfxx-sparc.c, * elfxx-tilegx.c, * elfxx-x86.c, * i386msdos.c, * linker.c, * mach-o.c, * mmo.c, * opncls.c, * pdp11.c, * pei-x86_64.c, * peicode.h, * reloc.c, * section.c, * syms.c, * vms-alpha.c, * xcofflink.c: Update throughout for bfd section macro and function changes. binutils/ * addr2line.c, * bucomm.c, * coffgrok.c, * dlltool.c, * nm.c, * objcopy.c, * objdump.c, * od-elf32_avr.c, * od-macho.c, * od-xcoff.c, * prdbg.c, * rdcoff.c, * rddbg.c, * rescoff.c, * resres.c, * size.c, * srconv.c, * strings.c, * windmc.c: Update throughout for bfd section macro and function changes. gas/ * as.c, * as.h, * dw2gencfi.c, * dwarf2dbg.c, * ecoff.c, * read.c, * stabs.c, * subsegs.c, * subsegs.h, * write.c, * config/obj-coff-seh.c, * config/obj-coff.c, * config/obj-ecoff.c, * config/obj-elf.c, * config/obj-macho.c, * config/obj-som.c, * config/tc-aarch64.c, * config/tc-alpha.c, * config/tc-arc.c, * config/tc-arm.c, * config/tc-avr.c, * config/tc-bfin.c, * config/tc-bpf.c, * config/tc-d10v.c, * config/tc-d30v.c, * config/tc-epiphany.c, * config/tc-fr30.c, * config/tc-frv.c, * config/tc-h8300.c, * config/tc-hppa.c, * config/tc-i386.c, * config/tc-ia64.c, * config/tc-ip2k.c, * config/tc-iq2000.c, * config/tc-lm32.c, * config/tc-m32c.c, * config/tc-m32r.c, * config/tc-m68hc11.c, * config/tc-mep.c, * config/tc-microblaze.c, * config/tc-mips.c, * config/tc-mmix.c, * config/tc-mn10200.c, * config/tc-mn10300.c, * config/tc-msp430.c, * config/tc-mt.c, * config/tc-nds32.c, * config/tc-or1k.c, * config/tc-ppc.c, * config/tc-pru.c, * config/tc-rl78.c, * config/tc-rx.c, * config/tc-s12z.c, * config/tc-s390.c, * config/tc-score.c, * config/tc-score7.c, * config/tc-sh.c, * config/tc-sparc.c, * config/tc-spu.c, * config/tc-tic4x.c, * config/tc-tic54x.c, * config/tc-tic6x.c, * config/tc-tilegx.c, * config/tc-tilepro.c, * config/tc-v850.c, * config/tc-visium.c, * config/tc-wasm32.c, * config/tc-xc16x.c, * config/tc-xgate.c, * config/tc-xstormy16.c, * config/tc-xtensa.c, * config/tc-z8k.c: Update throughout for bfd section macro and function changes. * write.c (compress_debug): Use bfd_rename_section. gdb/ * aarch64-linux-tdep.c, * arm-tdep.c, * auto-load.c, * coff-pe-read.c, * coffread.c, * corelow.c, * dbxread.c, * dicos-tdep.c, * dwarf2-frame.c, * dwarf2read.c, * elfread.c, * exec.c, * fbsd-tdep.c, * gcore.c, * gdb_bfd.c, * gdb_bfd.h, * hppa-tdep.c, * i386-cygwin-tdep.c, * i386-fbsd-tdep.c, * i386-linux-tdep.c, * jit.c, * linux-tdep.c, * machoread.c, * maint.c, * mdebugread.c, * minidebug.c, * mips-linux-tdep.c, * mips-sde-tdep.c, * mips-tdep.c, * mipsread.c, * nto-tdep.c, * objfiles.c, * objfiles.h, * osabi.c, * ppc-linux-tdep.c, * ppc64-tdep.c, * record-btrace.c, * record-full.c, * remote.c, * rs6000-aix-tdep.c, * rs6000-tdep.c, * s390-linux-tdep.c, * s390-tdep.c, * solib-aix.c, * solib-dsbt.c, * solib-frv.c, * solib-spu.c, * solib-svr4.c, * solib-target.c, * spu-linux-nat.c, * spu-tdep.c, * symfile-mem.c, * symfile.c, * symmisc.c, * symtab.c, * target.c, * windows-nat.c, * xcoffread.c, * cli/cli-dump.c, * compile/compile-object-load.c, * mi/mi-interp.c: Update throughout for bfd section macro and function changes. * gcore (gcore_create_callback): Use bfd_set_section_lma. * spu-tdep.c (spu_overlay_new_objfile): Likewise. gprof/ * corefile.c, * symtab.c: Update throughout for bfd section macro and function changes. ld/ * ldcref.c, * ldctor.c, * ldelf.c, * ldlang.c, * pe-dll.c, * emultempl/aarch64elf.em, * emultempl/aix.em, * emultempl/armcoff.em, * emultempl/armelf.em, * emultempl/cr16elf.em, * emultempl/cskyelf.em, * emultempl/m68hc1xelf.em, * emultempl/m68kelf.em, * emultempl/mipself.em, * emultempl/mmix-elfnmmo.em, * emultempl/mmo.em, * emultempl/msp430.em, * emultempl/nios2elf.em, * emultempl/pe.em, * emultempl/pep.em, * emultempl/ppc64elf.em, * emultempl/xtensaelf.em: Update throughout for bfd section macro and function changes. libctf/ * ctf-open-bfd.c: Update throughout for bfd section macro changes. opcodes/ * arc-ext.c: Update throughout for bfd section macro changes. sim/ * common/sim-load.c, * common/sim-utils.c, * cris/sim-if.c, * erc32/func.c, * lm32/sim-if.c, * m32c/load.c, * m32c/trace.c, * m68hc11/interp.c, * ppc/hw_htab.c, * ppc/hw_init.c, * rl78/load.c, * rl78/trace.c, * rx/gdb-if.c, * rx/load.c, * rx/trace.c: Update throughout for bfd section macro changes.
857 lines
17 KiB
C
857 lines
17 KiB
C
/* gdb-if.c -- sim interface to GDB.
|
|
|
|
Copyright (C) 2008-2019 Free Software Foundation, Inc.
|
|
Contributed by Red Hat, Inc.
|
|
|
|
This file is part of the GNU simulators.
|
|
|
|
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/>. */
|
|
|
|
#include "config.h"
|
|
#include <stdio.h>
|
|
#include <assert.h>
|
|
#include <signal.h>
|
|
#include <string.h>
|
|
#include <ctype.h>
|
|
#include <stdlib.h>
|
|
|
|
#include "ansidecl.h"
|
|
#include "gdb/callback.h"
|
|
#include "gdb/remote-sim.h"
|
|
#include "gdb/signals.h"
|
|
#include "gdb/sim-rx.h"
|
|
|
|
#include "cpu.h"
|
|
#include "mem.h"
|
|
#include "load.h"
|
|
#include "syscalls.h"
|
|
#include "err.h"
|
|
#include "trace.h"
|
|
|
|
/* Ideally, we'd wrap up all the minisim's data structures in an
|
|
object and pass that around. However, neither GDB nor run needs
|
|
that ability.
|
|
|
|
So we just have one instance, that lives in global variables, and
|
|
each time we open it, we re-initialize it. */
|
|
struct sim_state
|
|
{
|
|
const char *message;
|
|
};
|
|
|
|
static struct sim_state the_minisim = {
|
|
"This is the sole rx minisim instance. See libsim.a's global variables."
|
|
};
|
|
|
|
static int rx_sim_is_open;
|
|
|
|
SIM_DESC
|
|
sim_open (SIM_OPEN_KIND kind,
|
|
struct host_callback_struct *callback,
|
|
struct bfd *abfd, char * const *argv)
|
|
{
|
|
if (rx_sim_is_open)
|
|
fprintf (stderr, "rx minisim: re-opened sim\n");
|
|
|
|
/* The 'run' interface doesn't use this function, so we don't care
|
|
about KIND; it's always SIM_OPEN_DEBUG. */
|
|
if (kind != SIM_OPEN_DEBUG)
|
|
fprintf (stderr, "rx minisim: sim_open KIND != SIM_OPEN_DEBUG: %d\n",
|
|
kind);
|
|
|
|
set_callbacks (callback);
|
|
|
|
/* We don't expect any command-line arguments. */
|
|
|
|
init_mem ();
|
|
init_regs ();
|
|
execution_error_init_debugger ();
|
|
|
|
sim_disasm_init (abfd);
|
|
rx_sim_is_open = 1;
|
|
return &the_minisim;
|
|
}
|
|
|
|
static void
|
|
check_desc (SIM_DESC sd)
|
|
{
|
|
if (sd != &the_minisim)
|
|
fprintf (stderr, "rx minisim: desc != &the_minisim\n");
|
|
}
|
|
|
|
void
|
|
sim_close (SIM_DESC sd, int quitting)
|
|
{
|
|
check_desc (sd);
|
|
|
|
/* Not much to do. At least free up our memory. */
|
|
init_mem ();
|
|
|
|
rx_sim_is_open = 0;
|
|
}
|
|
|
|
static bfd *
|
|
open_objfile (const char *filename)
|
|
{
|
|
bfd *prog = bfd_openr (filename, 0);
|
|
|
|
if (!prog)
|
|
{
|
|
fprintf (stderr, "Can't read %s\n", filename);
|
|
return 0;
|
|
}
|
|
|
|
if (!bfd_check_format (prog, bfd_object))
|
|
{
|
|
fprintf (stderr, "%s not a rx program\n", filename);
|
|
return 0;
|
|
}
|
|
|
|
return prog;
|
|
}
|
|
|
|
static struct swap_list
|
|
{
|
|
bfd_vma start, end;
|
|
struct swap_list *next;
|
|
} *swap_list = NULL;
|
|
|
|
static void
|
|
free_swap_list (void)
|
|
{
|
|
while (swap_list)
|
|
{
|
|
struct swap_list *next = swap_list->next;
|
|
free (swap_list);
|
|
swap_list = next;
|
|
}
|
|
}
|
|
|
|
/* When running in big endian mode, we must do an additional
|
|
byte swap of memory areas used to hold instructions. See
|
|
the comment preceding rx_load in load.c to see why this is
|
|
so.
|
|
|
|
Construct a list of memory areas that must be byte swapped.
|
|
This list will be consulted when either reading or writing
|
|
memory. */
|
|
|
|
static void
|
|
build_swap_list (struct bfd *abfd)
|
|
{
|
|
asection *s;
|
|
free_swap_list ();
|
|
|
|
/* Nothing to do when in little endian mode. */
|
|
if (!rx_big_endian)
|
|
return;
|
|
|
|
for (s = abfd->sections; s; s = s->next)
|
|
{
|
|
if ((s->flags & SEC_LOAD) && (s->flags & SEC_CODE))
|
|
{
|
|
struct swap_list *sl;
|
|
bfd_size_type size;
|
|
|
|
size = bfd_section_size (s);
|
|
if (size <= 0)
|
|
continue;
|
|
|
|
sl = malloc (sizeof (struct swap_list));
|
|
assert (sl != NULL);
|
|
sl->next = swap_list;
|
|
sl->start = bfd_section_lma (s);
|
|
sl->end = sl->start + size;
|
|
swap_list = sl;
|
|
}
|
|
}
|
|
}
|
|
|
|
static int
|
|
addr_in_swap_list (bfd_vma addr)
|
|
{
|
|
struct swap_list *s;
|
|
|
|
for (s = swap_list; s; s = s->next)
|
|
{
|
|
if (s->start <= addr && addr < s->end)
|
|
return 1;
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
SIM_RC
|
|
sim_load (SIM_DESC sd, const char *prog, struct bfd *abfd, int from_tty)
|
|
{
|
|
check_desc (sd);
|
|
|
|
if (!abfd)
|
|
abfd = open_objfile (prog);
|
|
if (!abfd)
|
|
return SIM_RC_FAIL;
|
|
|
|
rx_load (abfd, get_callbacks ());
|
|
build_swap_list (abfd);
|
|
|
|
return SIM_RC_OK;
|
|
}
|
|
|
|
SIM_RC
|
|
sim_create_inferior (SIM_DESC sd, struct bfd *abfd,
|
|
char * const *argv, char * const *env)
|
|
{
|
|
check_desc (sd);
|
|
|
|
if (abfd)
|
|
{
|
|
rx_load (abfd, NULL);
|
|
build_swap_list (abfd);
|
|
}
|
|
|
|
return SIM_RC_OK;
|
|
}
|
|
|
|
int
|
|
sim_read (SIM_DESC sd, SIM_ADDR mem, unsigned char *buf, int length)
|
|
{
|
|
int i;
|
|
|
|
check_desc (sd);
|
|
|
|
if (mem == 0)
|
|
return 0;
|
|
|
|
execution_error_clear_last_error ();
|
|
|
|
for (i = 0; i < length; i++)
|
|
{
|
|
bfd_vma addr = mem + i;
|
|
int do_swap = addr_in_swap_list (addr);
|
|
buf[i] = mem_get_qi (addr ^ (do_swap ? 3 : 0));
|
|
|
|
if (execution_error_get_last_error () != SIM_ERR_NONE)
|
|
return i;
|
|
}
|
|
|
|
return length;
|
|
}
|
|
|
|
int
|
|
sim_write (SIM_DESC sd, SIM_ADDR mem, const unsigned char *buf, int length)
|
|
{
|
|
int i;
|
|
|
|
check_desc (sd);
|
|
|
|
execution_error_clear_last_error ();
|
|
|
|
for (i = 0; i < length; i++)
|
|
{
|
|
bfd_vma addr = mem + i;
|
|
int do_swap = addr_in_swap_list (addr);
|
|
mem_put_qi (addr ^ (do_swap ? 3 : 0), buf[i]);
|
|
|
|
if (execution_error_get_last_error () != SIM_ERR_NONE)
|
|
return i;
|
|
}
|
|
|
|
return length;
|
|
}
|
|
|
|
/* Read the LENGTH bytes at BUF as an little-endian value. */
|
|
static DI
|
|
get_le (unsigned char *buf, int length)
|
|
{
|
|
DI acc = 0;
|
|
while (--length >= 0)
|
|
acc = (acc << 8) + buf[length];
|
|
|
|
return acc;
|
|
}
|
|
|
|
/* Read the LENGTH bytes at BUF as a big-endian value. */
|
|
static DI
|
|
get_be (unsigned char *buf, int length)
|
|
{
|
|
DI acc = 0;
|
|
while (length-- > 0)
|
|
acc = (acc << 8) + *buf++;
|
|
|
|
return acc;
|
|
}
|
|
|
|
/* Store VAL as a little-endian value in the LENGTH bytes at BUF. */
|
|
static void
|
|
put_le (unsigned char *buf, int length, DI val)
|
|
{
|
|
int i;
|
|
|
|
for (i = 0; i < length; i++)
|
|
{
|
|
buf[i] = val & 0xff;
|
|
val >>= 8;
|
|
}
|
|
}
|
|
|
|
/* Store VAL as a big-endian value in the LENGTH bytes at BUF. */
|
|
static void
|
|
put_be (unsigned char *buf, int length, DI val)
|
|
{
|
|
int i;
|
|
|
|
for (i = length-1; i >= 0; i--)
|
|
{
|
|
buf[i] = val & 0xff;
|
|
val >>= 8;
|
|
}
|
|
}
|
|
|
|
|
|
static int
|
|
check_regno (enum sim_rx_regnum regno)
|
|
{
|
|
return 0 <= regno && regno < sim_rx_num_regs;
|
|
}
|
|
|
|
static size_t
|
|
reg_size (enum sim_rx_regnum regno)
|
|
{
|
|
size_t size;
|
|
|
|
switch (regno)
|
|
{
|
|
case sim_rx_r0_regnum:
|
|
size = sizeof (regs.r[0]);
|
|
break;
|
|
case sim_rx_r1_regnum:
|
|
size = sizeof (regs.r[1]);
|
|
break;
|
|
case sim_rx_r2_regnum:
|
|
size = sizeof (regs.r[2]);
|
|
break;
|
|
case sim_rx_r3_regnum:
|
|
size = sizeof (regs.r[3]);
|
|
break;
|
|
case sim_rx_r4_regnum:
|
|
size = sizeof (regs.r[4]);
|
|
break;
|
|
case sim_rx_r5_regnum:
|
|
size = sizeof (regs.r[5]);
|
|
break;
|
|
case sim_rx_r6_regnum:
|
|
size = sizeof (regs.r[6]);
|
|
break;
|
|
case sim_rx_r7_regnum:
|
|
size = sizeof (regs.r[7]);
|
|
break;
|
|
case sim_rx_r8_regnum:
|
|
size = sizeof (regs.r[8]);
|
|
break;
|
|
case sim_rx_r9_regnum:
|
|
size = sizeof (regs.r[9]);
|
|
break;
|
|
case sim_rx_r10_regnum:
|
|
size = sizeof (regs.r[10]);
|
|
break;
|
|
case sim_rx_r11_regnum:
|
|
size = sizeof (regs.r[11]);
|
|
break;
|
|
case sim_rx_r12_regnum:
|
|
size = sizeof (regs.r[12]);
|
|
break;
|
|
case sim_rx_r13_regnum:
|
|
size = sizeof (regs.r[13]);
|
|
break;
|
|
case sim_rx_r14_regnum:
|
|
size = sizeof (regs.r[14]);
|
|
break;
|
|
case sim_rx_r15_regnum:
|
|
size = sizeof (regs.r[15]);
|
|
break;
|
|
case sim_rx_isp_regnum:
|
|
size = sizeof (regs.r_isp);
|
|
break;
|
|
case sim_rx_usp_regnum:
|
|
size = sizeof (regs.r_usp);
|
|
break;
|
|
case sim_rx_intb_regnum:
|
|
size = sizeof (regs.r_intb);
|
|
break;
|
|
case sim_rx_pc_regnum:
|
|
size = sizeof (regs.r_pc);
|
|
break;
|
|
case sim_rx_ps_regnum:
|
|
size = sizeof (regs.r_psw);
|
|
break;
|
|
case sim_rx_bpc_regnum:
|
|
size = sizeof (regs.r_bpc);
|
|
break;
|
|
case sim_rx_bpsw_regnum:
|
|
size = sizeof (regs.r_bpsw);
|
|
break;
|
|
case sim_rx_fintv_regnum:
|
|
size = sizeof (regs.r_fintv);
|
|
break;
|
|
case sim_rx_fpsw_regnum:
|
|
size = sizeof (regs.r_fpsw);
|
|
break;
|
|
case sim_rx_acc_regnum:
|
|
size = sizeof (regs.r_acc);
|
|
break;
|
|
default:
|
|
size = 0;
|
|
break;
|
|
}
|
|
return size;
|
|
}
|
|
|
|
int
|
|
sim_fetch_register (SIM_DESC sd, int regno, unsigned char *buf, int length)
|
|
{
|
|
size_t size;
|
|
DI val;
|
|
|
|
check_desc (sd);
|
|
|
|
if (!check_regno (regno))
|
|
return 0;
|
|
|
|
size = reg_size (regno);
|
|
|
|
if (length != size)
|
|
return 0;
|
|
|
|
switch (regno)
|
|
{
|
|
case sim_rx_r0_regnum:
|
|
val = get_reg (0);
|
|
break;
|
|
case sim_rx_r1_regnum:
|
|
val = get_reg (1);
|
|
break;
|
|
case sim_rx_r2_regnum:
|
|
val = get_reg (2);
|
|
break;
|
|
case sim_rx_r3_regnum:
|
|
val = get_reg (3);
|
|
break;
|
|
case sim_rx_r4_regnum:
|
|
val = get_reg (4);
|
|
break;
|
|
case sim_rx_r5_regnum:
|
|
val = get_reg (5);
|
|
break;
|
|
case sim_rx_r6_regnum:
|
|
val = get_reg (6);
|
|
break;
|
|
case sim_rx_r7_regnum:
|
|
val = get_reg (7);
|
|
break;
|
|
case sim_rx_r8_regnum:
|
|
val = get_reg (8);
|
|
break;
|
|
case sim_rx_r9_regnum:
|
|
val = get_reg (9);
|
|
break;
|
|
case sim_rx_r10_regnum:
|
|
val = get_reg (10);
|
|
break;
|
|
case sim_rx_r11_regnum:
|
|
val = get_reg (11);
|
|
break;
|
|
case sim_rx_r12_regnum:
|
|
val = get_reg (12);
|
|
break;
|
|
case sim_rx_r13_regnum:
|
|
val = get_reg (13);
|
|
break;
|
|
case sim_rx_r14_regnum:
|
|
val = get_reg (14);
|
|
break;
|
|
case sim_rx_r15_regnum:
|
|
val = get_reg (15);
|
|
break;
|
|
case sim_rx_isp_regnum:
|
|
val = get_reg (isp);
|
|
break;
|
|
case sim_rx_usp_regnum:
|
|
val = get_reg (usp);
|
|
break;
|
|
case sim_rx_intb_regnum:
|
|
val = get_reg (intb);
|
|
break;
|
|
case sim_rx_pc_regnum:
|
|
val = get_reg (pc);
|
|
break;
|
|
case sim_rx_ps_regnum:
|
|
val = get_reg (psw);
|
|
break;
|
|
case sim_rx_bpc_regnum:
|
|
val = get_reg (bpc);
|
|
break;
|
|
case sim_rx_bpsw_regnum:
|
|
val = get_reg (bpsw);
|
|
break;
|
|
case sim_rx_fintv_regnum:
|
|
val = get_reg (fintv);
|
|
break;
|
|
case sim_rx_fpsw_regnum:
|
|
val = get_reg (fpsw);
|
|
break;
|
|
case sim_rx_acc_regnum:
|
|
val = ((DI) get_reg (acchi) << 32) | get_reg (acclo);
|
|
break;
|
|
default:
|
|
fprintf (stderr, "rx minisim: unrecognized register number: %d\n",
|
|
regno);
|
|
return -1;
|
|
}
|
|
|
|
if (rx_big_endian)
|
|
put_be (buf, length, val);
|
|
else
|
|
put_le (buf, length, val);
|
|
|
|
return size;
|
|
}
|
|
|
|
int
|
|
sim_store_register (SIM_DESC sd, int regno, unsigned char *buf, int length)
|
|
{
|
|
size_t size;
|
|
DI val;
|
|
|
|
check_desc (sd);
|
|
|
|
if (!check_regno (regno))
|
|
return -1;
|
|
|
|
size = reg_size (regno);
|
|
|
|
if (length != size)
|
|
return -1;
|
|
|
|
if (rx_big_endian)
|
|
val = get_be (buf, length);
|
|
else
|
|
val = get_le (buf, length);
|
|
|
|
switch (regno)
|
|
{
|
|
case sim_rx_r0_regnum:
|
|
put_reg (0, val);
|
|
break;
|
|
case sim_rx_r1_regnum:
|
|
put_reg (1, val);
|
|
break;
|
|
case sim_rx_r2_regnum:
|
|
put_reg (2, val);
|
|
break;
|
|
case sim_rx_r3_regnum:
|
|
put_reg (3, val);
|
|
break;
|
|
case sim_rx_r4_regnum:
|
|
put_reg (4, val);
|
|
break;
|
|
case sim_rx_r5_regnum:
|
|
put_reg (5, val);
|
|
break;
|
|
case sim_rx_r6_regnum:
|
|
put_reg (6, val);
|
|
break;
|
|
case sim_rx_r7_regnum:
|
|
put_reg (7, val);
|
|
break;
|
|
case sim_rx_r8_regnum:
|
|
put_reg (8, val);
|
|
break;
|
|
case sim_rx_r9_regnum:
|
|
put_reg (9, val);
|
|
break;
|
|
case sim_rx_r10_regnum:
|
|
put_reg (10, val);
|
|
break;
|
|
case sim_rx_r11_regnum:
|
|
put_reg (11, val);
|
|
break;
|
|
case sim_rx_r12_regnum:
|
|
put_reg (12, val);
|
|
break;
|
|
case sim_rx_r13_regnum:
|
|
put_reg (13, val);
|
|
break;
|
|
case sim_rx_r14_regnum:
|
|
put_reg (14, val);
|
|
break;
|
|
case sim_rx_r15_regnum:
|
|
put_reg (15, val);
|
|
break;
|
|
case sim_rx_isp_regnum:
|
|
put_reg (isp, val);
|
|
break;
|
|
case sim_rx_usp_regnum:
|
|
put_reg (usp, val);
|
|
break;
|
|
case sim_rx_intb_regnum:
|
|
put_reg (intb, val);
|
|
break;
|
|
case sim_rx_pc_regnum:
|
|
put_reg (pc, val);
|
|
break;
|
|
case sim_rx_ps_regnum:
|
|
put_reg (psw, val);
|
|
break;
|
|
case sim_rx_bpc_regnum:
|
|
put_reg (bpc, val);
|
|
break;
|
|
case sim_rx_bpsw_regnum:
|
|
put_reg (bpsw, val);
|
|
break;
|
|
case sim_rx_fintv_regnum:
|
|
put_reg (fintv, val);
|
|
break;
|
|
case sim_rx_fpsw_regnum:
|
|
put_reg (fpsw, val);
|
|
break;
|
|
case sim_rx_acc_regnum:
|
|
put_reg (acclo, val & 0xffffffff);
|
|
put_reg (acchi, (val >> 32) & 0xffffffff);
|
|
break;
|
|
default:
|
|
fprintf (stderr, "rx minisim: unrecognized register number: %d\n",
|
|
regno);
|
|
return 0;
|
|
}
|
|
|
|
return size;
|
|
}
|
|
|
|
void
|
|
sim_info (SIM_DESC sd, int verbose)
|
|
{
|
|
check_desc (sd);
|
|
|
|
printf ("The rx minisim doesn't collect any statistics.\n");
|
|
}
|
|
|
|
static volatile int stop;
|
|
static enum sim_stop reason;
|
|
int siggnal;
|
|
|
|
|
|
/* Given a signal number used by the RX bsp (that is, newlib),
|
|
return a target signal number used by GDB. */
|
|
static int
|
|
rx_signal_to_gdb_signal (int rx)
|
|
{
|
|
switch (rx)
|
|
{
|
|
case 4:
|
|
return GDB_SIGNAL_ILL;
|
|
|
|
case 5:
|
|
return GDB_SIGNAL_TRAP;
|
|
|
|
case 10:
|
|
return GDB_SIGNAL_BUS;
|
|
|
|
case 11:
|
|
return GDB_SIGNAL_SEGV;
|
|
|
|
case 24:
|
|
return GDB_SIGNAL_XCPU;
|
|
|
|
case 2:
|
|
return GDB_SIGNAL_INT;
|
|
|
|
case 8:
|
|
return GDB_SIGNAL_FPE;
|
|
|
|
case 6:
|
|
return GDB_SIGNAL_ABRT;
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
|
|
/* Take a step return code RC and set up the variables consulted by
|
|
sim_stop_reason appropriately. */
|
|
void
|
|
handle_step (int rc)
|
|
{
|
|
if (execution_error_get_last_error () != SIM_ERR_NONE)
|
|
{
|
|
reason = sim_stopped;
|
|
siggnal = GDB_SIGNAL_SEGV;
|
|
}
|
|
if (RX_STEPPED (rc) || RX_HIT_BREAK (rc))
|
|
{
|
|
reason = sim_stopped;
|
|
siggnal = GDB_SIGNAL_TRAP;
|
|
}
|
|
else if (RX_STOPPED (rc))
|
|
{
|
|
reason = sim_stopped;
|
|
siggnal = rx_signal_to_gdb_signal (RX_STOP_SIG (rc));
|
|
}
|
|
else
|
|
{
|
|
assert (RX_EXITED (rc));
|
|
reason = sim_exited;
|
|
siggnal = RX_EXIT_STATUS (rc);
|
|
}
|
|
}
|
|
|
|
|
|
void
|
|
sim_resume (SIM_DESC sd, int step, int sig_to_deliver)
|
|
{
|
|
int rc;
|
|
|
|
check_desc (sd);
|
|
|
|
if (sig_to_deliver != 0)
|
|
{
|
|
fprintf (stderr,
|
|
"Warning: the rx minisim does not implement "
|
|
"signal delivery yet.\n" "Resuming with no signal.\n");
|
|
}
|
|
|
|
execution_error_clear_last_error ();
|
|
|
|
if (step)
|
|
{
|
|
rc = setjmp (decode_jmp_buf);
|
|
if (rc == 0)
|
|
rc = decode_opcode ();
|
|
handle_step (rc);
|
|
}
|
|
else
|
|
{
|
|
/* We don't clear 'stop' here, because then we would miss
|
|
interrupts that arrived on the way here. Instead, we clear
|
|
the flag in sim_stop_reason, after GDB has disabled the
|
|
interrupt signal handler. */
|
|
for (;;)
|
|
{
|
|
if (stop)
|
|
{
|
|
stop = 0;
|
|
reason = sim_stopped;
|
|
siggnal = GDB_SIGNAL_INT;
|
|
break;
|
|
}
|
|
|
|
rc = setjmp (decode_jmp_buf);
|
|
if (rc == 0)
|
|
rc = decode_opcode ();
|
|
|
|
if (execution_error_get_last_error () != SIM_ERR_NONE)
|
|
{
|
|
reason = sim_stopped;
|
|
siggnal = GDB_SIGNAL_SEGV;
|
|
break;
|
|
}
|
|
|
|
if (!RX_STEPPED (rc))
|
|
{
|
|
handle_step (rc);
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
int
|
|
sim_stop (SIM_DESC sd)
|
|
{
|
|
stop = 1;
|
|
|
|
return 1;
|
|
}
|
|
|
|
void
|
|
sim_stop_reason (SIM_DESC sd, enum sim_stop *reason_p, int *sigrc_p)
|
|
{
|
|
check_desc (sd);
|
|
|
|
*reason_p = reason;
|
|
*sigrc_p = siggnal;
|
|
}
|
|
|
|
void
|
|
sim_do_command (SIM_DESC sd, const char *cmd)
|
|
{
|
|
const char *args;
|
|
char *p = strdup (cmd);
|
|
|
|
check_desc (sd);
|
|
|
|
/* Skip leading whitespace. */
|
|
while (isspace (*p))
|
|
p++;
|
|
|
|
/* Find the extent of the command word. */
|
|
for (p = cmd; *p; p++)
|
|
if (isspace (*p))
|
|
break;
|
|
|
|
/* Null-terminate the command word, and record the start of any
|
|
further arguments. */
|
|
if (*p)
|
|
{
|
|
*p = '\0';
|
|
args = p + 1;
|
|
while (isspace (*args))
|
|
args++;
|
|
}
|
|
else
|
|
args = p;
|
|
|
|
if (strcmp (cmd, "trace") == 0)
|
|
{
|
|
if (strcmp (args, "on") == 0)
|
|
trace = 1;
|
|
else if (strcmp (args, "off") == 0)
|
|
trace = 0;
|
|
else
|
|
printf ("The 'sim trace' command expects 'on' or 'off' "
|
|
"as an argument.\n");
|
|
}
|
|
else if (strcmp (cmd, "verbose") == 0)
|
|
{
|
|
if (strcmp (args, "on") == 0)
|
|
verbose = 1;
|
|
else if (strcmp (args, "noisy") == 0)
|
|
verbose = 2;
|
|
else if (strcmp (args, "off") == 0)
|
|
verbose = 0;
|
|
else
|
|
printf ("The 'sim verbose' command expects 'on', 'noisy', or 'off'"
|
|
" as an argument.\n");
|
|
}
|
|
else
|
|
printf ("The 'sim' command expects either 'trace' or 'verbose'"
|
|
" as a subcommand.\n");
|
|
|
|
free (p);
|
|
}
|
|
|
|
char **
|
|
sim_complete_command (SIM_DESC sd, const char *text, const char *word)
|
|
{
|
|
return NULL;
|
|
}
|