Browse Source
* configure.tgt: Add it. * configure: Regenerate. * gennltvals.sh: Add msp430 support. * nltvals.def: Regenerate. * Makefile.in: New. * aclocal.m4: Generate. * config.in: Generate. * configure.ac: New. * configure: Generate. * msp430-sim.c: New. * msp430-sim.h: New. * sim-main.h: New. * trace.c: New. * trace.h: New.binutils-2_24-branch
17 changed files with 8534 additions and 0 deletions
@ -0,0 +1,12 @@ |
|||
2013-06-21 Nick Clifton <nickc@redhat.com> |
|||
|
|||
* Makefile.in: New. |
|||
* aclocal.m4: Generate. |
|||
* config.in: Generate. |
|||
* configure.ac: New. |
|||
* configure: Generate. |
|||
* msp430-sim.c: New. |
|||
* msp430-sim.h: New. |
|||
* sim-main.h: New. |
|||
* trace.c: New. |
|||
* trace.h: New. |
|||
@ -0,0 +1,66 @@ |
|||
# Makefile template for Configure for the MSP430 sim library.
|
|||
# Copyright 2012 Free Software Foundation, Inc.
|
|||
# Written by Red Hat Inc.
|
|||
#
|
|||
# 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, write to the Free Software
|
|||
# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
|||
|
|||
## COMMON_PRE_CONFIG_FRAG
|
|||
|
|||
# These variables are given default values in COMMON_PRE_CONFIG_FRAG.
|
|||
# We override the ones we need to here.
|
|||
# Not all of these need to be mentioned, only the necessary ones.
|
|||
# In fact it is better to *not* mention ones if the value is the default.
|
|||
|
|||
# List of object files, less common parts.
|
|||
SIM_OBJS = \
|
|||
$(SIM_NEW_COMMON_OBJS) \
|
|||
msp430-sim.o \
|
|||
trace.o \
|
|||
sim-cpu.o \
|
|||
sim-engine.o \
|
|||
sim-hload.o \
|
|||
sim-hrw.o \
|
|||
sim-reason.o \
|
|||
sim-reg.o \
|
|||
sim-resume.o \
|
|||
sim-stop.o \
|
|||
$(SIM_EXTRA_OBJS) |
|||
|
|||
# List of extra dependencies.
|
|||
# Generally this consists of simulator specific files included by sim-main.h.
|
|||
SIM_EXTRA_DEPS = |
|||
# List of flags to always pass to $(CC).
|
|||
SIM_EXTRA_CFLAGS = |
|||
# List of extra libraries to link with.
|
|||
SIM_EXTRA_LIBS = |
|||
# List of extra program dependencies.
|
|||
SIM_EXTRA_LIBDEPS = |
|||
# List of main object files for `run'.
|
|||
SIM_RUN_OBJS = nrun.o |
|||
# Dependency of `all' to build any extra files.
|
|||
SIM_EXTRA_ALL = |
|||
# Dependency of `install' to install any extra files.
|
|||
SIM_EXTRA_INSTALL = |
|||
# Dependency of `clean' to clean any extra files.
|
|||
SIM_EXTRA_CLEAN = |
|||
|
|||
# This selects the MSP430 newlib/libgloss syscall definitions.
|
|||
NL_TARGET = -DNL_TARGET_msp430 |
|||
|
|||
## COMMON_POST_CONFIG_FRAG
|
|||
|
|||
# Rules need to build $(SIM_OBJS), plus whatever else the target wants.
|
|||
|
|||
# ... target specific rules ...
|
|||
@ -0,0 +1,90 @@ |
|||
# generated automatically by aclocal 1.11.3 -*- Autoconf -*- |
|||
|
|||
# Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, |
|||
# 2005, 2006, 2007, 2008, 2009, 2010, 2011 Free Software Foundation, |
|||
# Inc. |
|||
# This file is free software; the Free Software Foundation |
|||
# gives unlimited permission to copy and/or distribute it, |
|||
# with or without modifications, as long as this notice is preserved. |
|||
|
|||
# This program is distributed in the hope that it will be useful, |
|||
# but WITHOUT ANY WARRANTY, to the extent permitted by law; without |
|||
# even the implied warranty of MERCHANTABILITY or FITNESS FOR A |
|||
# PARTICULAR PURPOSE. |
|||
|
|||
# AM_CONDITIONAL -*- Autoconf -*- |
|||
|
|||
# Copyright (C) 1997, 2000, 2001, 2003, 2004, 2005, 2006, 2008 |
|||
# Free Software Foundation, Inc. |
|||
# |
|||
# This file is free software; the Free Software Foundation |
|||
# gives unlimited permission to copy and/or distribute it, |
|||
# with or without modifications, as long as this notice is preserved. |
|||
|
|||
# serial 9 |
|||
|
|||
# AM_CONDITIONAL(NAME, SHELL-CONDITION) |
|||
# ------------------------------------- |
|||
# Define a conditional. |
|||
AC_DEFUN([AM_CONDITIONAL], |
|||
[AC_PREREQ(2.52)dnl |
|||
ifelse([$1], [TRUE], [AC_FATAL([$0: invalid condition: $1])], |
|||
[$1], [FALSE], [AC_FATAL([$0: invalid condition: $1])])dnl |
|||
AC_SUBST([$1_TRUE])dnl |
|||
AC_SUBST([$1_FALSE])dnl |
|||
_AM_SUBST_NOTMAKE([$1_TRUE])dnl |
|||
_AM_SUBST_NOTMAKE([$1_FALSE])dnl |
|||
m4_define([_AM_COND_VALUE_$1], [$2])dnl |
|||
if $2; then |
|||
$1_TRUE= |
|||
$1_FALSE='#' |
|||
else |
|||
$1_TRUE='#' |
|||
$1_FALSE= |
|||
fi |
|||
AC_CONFIG_COMMANDS_PRE( |
|||
[if test -z "${$1_TRUE}" && test -z "${$1_FALSE}"; then |
|||
AC_MSG_ERROR([[conditional "$1" was never defined. |
|||
Usually this means the macro was only invoked conditionally.]]) |
|||
fi])]) |
|||
|
|||
# Copyright (C) 2003, 2005 Free Software Foundation, Inc. |
|||
# |
|||
# This file is free software; the Free Software Foundation |
|||
# gives unlimited permission to copy and/or distribute it, |
|||
# with or without modifications, as long as this notice is preserved. |
|||
|
|||
# serial 2 |
|||
|
|||
# Check whether the underlying file-system supports filenames |
|||
# with a leading dot. For instance MS-DOS doesn't. |
|||
AC_DEFUN([AM_SET_LEADING_DOT], |
|||
[rm -rf .tst 2>/dev/null |
|||
mkdir .tst 2>/dev/null |
|||
if test -d .tst; then |
|||
am__leading_dot=. |
|||
else |
|||
am__leading_dot=_ |
|||
fi |
|||
rmdir .tst 2>/dev/null |
|||
AC_SUBST([am__leading_dot])]) |
|||
|
|||
# Copyright (C) 2006, 2008, 2010 Free Software Foundation, Inc. |
|||
# |
|||
# This file is free software; the Free Software Foundation |
|||
# gives unlimited permission to copy and/or distribute it, |
|||
# with or without modifications, as long as this notice is preserved. |
|||
|
|||
# serial 3 |
|||
|
|||
# _AM_SUBST_NOTMAKE(VARIABLE) |
|||
# --------------------------- |
|||
# Prevent Automake from outputting VARIABLE = @VARIABLE@ in Makefile.in. |
|||
# This macro is traced by Automake. |
|||
AC_DEFUN([_AM_SUBST_NOTMAKE]) |
|||
|
|||
# AM_SUBST_NOTMAKE(VARIABLE) |
|||
# -------------------------- |
|||
# Public sister of _AM_SUBST_NOTMAKE. |
|||
AC_DEFUN([AM_SUBST_NOTMAKE], [_AM_SUBST_NOTMAKE($@)]) |
|||
|
|||
@ -0,0 +1,92 @@ |
|||
/* config.in. Generated from configure.ac by autoheader. */ |
|||
|
|||
/* Define to 1 if translation of program messages to the user's native |
|||
language is requested. */ |
|||
#undef ENABLE_NLS |
|||
|
|||
/* Define to 1 if you have the <dlfcn.h> header file. */ |
|||
#undef HAVE_DLFCN_H |
|||
|
|||
/* Define to 1 if you have the <errno.h> header file. */ |
|||
#undef HAVE_ERRNO_H |
|||
|
|||
/* Define to 1 if you have the <fcntl.h> header file. */ |
|||
#undef HAVE_FCNTL_H |
|||
|
|||
/* Define to 1 if you have the <fpu_control.h> header file. */ |
|||
#undef HAVE_FPU_CONTROL_H |
|||
|
|||
/* Define to 1 if you have the `getrusage' function. */ |
|||
#undef HAVE_GETRUSAGE |
|||
|
|||
/* Define to 1 if you have the <inttypes.h> header file. */ |
|||
#undef HAVE_INTTYPES_H |
|||
|
|||
/* Define to 1 if you have the `nsl' library (-lnsl). */ |
|||
#undef HAVE_LIBNSL |
|||
|
|||
/* Define to 1 if you have the `socket' library (-lsocket). */ |
|||
#undef HAVE_LIBSOCKET |
|||
|
|||
/* Define to 1 if you have the <memory.h> header file. */ |
|||
#undef HAVE_MEMORY_H |
|||
|
|||
/* Define to 1 if you have the `sigaction' function. */ |
|||
#undef HAVE_SIGACTION |
|||
|
|||
/* Define to 1 if you have the <stdint.h> header file. */ |
|||
#undef HAVE_STDINT_H |
|||
|
|||
/* Define to 1 if you have the <stdlib.h> header file. */ |
|||
#undef HAVE_STDLIB_H |
|||
|
|||
/* Define to 1 if you have the <strings.h> header file. */ |
|||
#undef HAVE_STRINGS_H |
|||
|
|||
/* Define to 1 if you have the <string.h> header file. */ |
|||
#undef HAVE_STRING_H |
|||
|
|||
/* Define to 1 if you have the <sys/resource.h> header file. */ |
|||
#undef HAVE_SYS_RESOURCE_H |
|||
|
|||
/* Define to 1 if you have the <sys/stat.h> header file. */ |
|||
#undef HAVE_SYS_STAT_H |
|||
|
|||
/* Define to 1 if you have the <sys/time.h> header file. */ |
|||
#undef HAVE_SYS_TIME_H |
|||
|
|||
/* Define to 1 if you have the <sys/types.h> header file. */ |
|||
#undef HAVE_SYS_TYPES_H |
|||
|
|||
/* Define to 1 if you have the `time' function. */ |
|||
#undef HAVE_TIME |
|||
|
|||
/* Define to 1 if you have the <time.h> header file. */ |
|||
#undef HAVE_TIME_H |
|||
|
|||
/* Define to 1 if you have the <unistd.h> header file. */ |
|||
#undef HAVE_UNISTD_H |
|||
|
|||
/* Define to 1 if you have the `__setfpucw' function. */ |
|||
#undef HAVE___SETFPUCW |
|||
|
|||
/* Define to the address where bug reports for this package should be sent. */ |
|||
#undef PACKAGE_BUGREPORT |
|||
|
|||
/* Define to the full name of this package. */ |
|||
#undef PACKAGE_NAME |
|||
|
|||
/* Define to the full name and version of this package. */ |
|||
#undef PACKAGE_STRING |
|||
|
|||
/* Define to the one symbol short name of this package. */ |
|||
#undef PACKAGE_TARNAME |
|||
|
|||
/* Define to the version of this package. */ |
|||
#undef PACKAGE_VERSION |
|||
|
|||
/* Define as the return type of signal handlers (`int' or `void'). */ |
|||
#undef RETSIGTYPE |
|||
|
|||
/* Define to 1 if you have the ANSI C header files. */ |
|||
#undef STDC_HEADERS |
|||
File diff suppressed because it is too large
@ -0,0 +1,32 @@ |
|||
dnl Process this file with autoconf to produce a configure script. |
|||
|
|||
dnl Copyright (C) 2005, 2007-2013 Free Software Foundation, Inc. |
|||
dnl Contributed by Red Hat, Inc. |
|||
dnl |
|||
dnl This file is part of the GNU simulators. |
|||
dnl |
|||
dnl This program is free software; you can redistribute it and/or modify |
|||
dnl it under the terms of the GNU General Public License as published by |
|||
dnl the Free Software Foundation; either version 3 of the License, or |
|||
dnl (at your option) any later version. |
|||
dnl |
|||
dnl This program is distributed in the hope that it will be useful, |
|||
dnl but WITHOUT ANY WARRANTY; without even the implied warranty of |
|||
dnl MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
|||
dnl GNU General Public License for more details. |
|||
dnl |
|||
dnl You should have received a copy of the GNU General Public License |
|||
dnl along with this program. If not, see <http://www.gnu.org/licenses/>. |
|||
dnl |
|||
AC_PREREQ(2.64)dnl |
|||
AC_INIT(Makefile.in) |
|||
sinclude(../common/acinclude.m4) |
|||
|
|||
SIM_AC_COMMON |
|||
|
|||
AC_CHECK_HEADERS(getopt.h) |
|||
|
|||
SIM_AC_OPTION_ENDIAN(LITTLE_ENDIAN) |
|||
SIM_AC_OPTION_ALIGNMENT(STRICT_ALIGNMENT,STRICT_ALIGNMENT) |
|||
|
|||
SIM_AC_OUTPUT |
|||
File diff suppressed because it is too large
@ -0,0 +1,31 @@ |
|||
/* Simulator for TI MSP430 and MSP430x processors.
|
|||
|
|||
Copyright (C) 2012-2013 Free Software Foundation, Inc. |
|||
Contributed by Red Hat, Inc. |
|||
|
|||
This file is part of 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/>. */
|
|||
|
|||
#ifndef _MSP430_SIM_H_ |
|||
#define _MSP430_SIM_H_ |
|||
|
|||
struct msp430_cpu_state |
|||
{ |
|||
int regs[16]; |
|||
int cio_breakpoint; |
|||
int cio_buffer; |
|||
}; |
|||
|
|||
#endif |
|||
@ -0,0 +1,120 @@ |
|||
/* Simulator for TI MSP430 and MSP430X processors.
|
|||
|
|||
Copyright (C) 2012-2013 Free Software Foundation, Inc. |
|||
Contributed by Red Hat, Inc. |
|||
|
|||
This file is part of 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/>. */
|
|||
|
|||
#ifndef _MSP430_MAIN_SIM_H_ |
|||
#define _MSP430_MAIN_SIM_H_ |
|||
|
|||
#include "sim-basics.h" |
|||
#include "sim-signal.h" |
|||
|
|||
typedef unsigned32 sim_cia; |
|||
|
|||
typedef struct _sim_cpu SIM_CPU; |
|||
|
|||
#include "msp430-sim.h" |
|||
#include "sim-base.h" |
|||
|
|||
struct _sim_cpu |
|||
{ |
|||
/* Simulator specific members. */ |
|||
struct msp430_cpu_state state; |
|||
sim_cpu_base base; |
|||
}; |
|||
|
|||
struct sim_state |
|||
{ |
|||
sim_cpu *cpu[MAX_NR_PROCESSORS]; |
|||
|
|||
#if (WITH_SMP) |
|||
#error WITH_SMP not supported by MSP430 sim |
|||
#else |
|||
#define STATE_CPU(sd,n) ((sd)->cpu[0]) |
|||
#endif |
|||
|
|||
asymbol **symbol_table; |
|||
long number_of_symbols; |
|||
#define STATE_SYMBOL_TABLE(sd) ((sd)->symbol_table) |
|||
#define STATE_NUM_SYMBOLS(sd) ((sd)->number_of_symbols) |
|||
|
|||
/* Simulator specific members. */ |
|||
sim_state_base base; |
|||
}; |
|||
|
|||
#define MSP430_CPU(sd) (STATE_CPU ((sd), 0)) |
|||
#define MSP430_CPU_STATE(sd) (MSP430_CPU ((sd)->state)) |
|||
|
|||
#define CIA_GET(CPU) ((CPU)->state.regs[0] + 0) |
|||
#define CIA_SET(CPU,VAL) ((CPU)->state.regs[0] = (VAL)) |
|||
|
|||
#include "sim-config.h" |
|||
#include "sim-types.h" |
|||
#include "sim-engine.h" |
|||
#include "sim-options.h" |
|||
#include "run-sim.h" |
|||
|
|||
#define MAYBE_TRACE(type, cpu, fmt, ...) \ |
|||
do \ |
|||
{ \ |
|||
if (TRACE_##type##_P (cpu)) \ |
|||
trace_generic (CPU_STATE (cpu), cpu, TRACE_##type##_IDX, \ |
|||
fmt, ## __VA_ARGS__); \ |
|||
} \ |
|||
while (0) |
|||
|
|||
#define TRACE_INSN(cpu, fmt, ...) MAYBE_TRACE (INSN, cpu, fmt, ## __VA_ARGS__) |
|||
#define TRACE_DECODE(cpu, fmt, ...) MAYBE_TRACE (DECODE, cpu, fmt, ## __VA_ARGS__) |
|||
#define TRACE_EXTRACT(cpu, fmt, ...) MAYBE_TRACE (EXTRACT, cpu, fmt, ## __VA_ARGS__) |
|||
#define TRACE_SYSCALL(cpu, fmt, ...) MAYBE_TRACE (SYSCALL, cpu, fmt, ## __VA_ARGS__) |
|||
|
|||
#define TRACE_CORE(cpu, addr, size, map, val) \ |
|||
do \ |
|||
{ \ |
|||
MAYBE_TRACE (CORE, cpu, "%cBUS %s %i bytes @ 0x%08x: 0x%0*x", \ |
|||
map == exec_map ? 'I' : 'D', \ |
|||
map == write_map ? "STORE" : "FETCH", \ |
|||
size, addr, size * 2, val); \ |
|||
PROFILE_COUNT_CORE (cpu, addr, size, map); \ |
|||
} \ |
|||
while (0) |
|||
|
|||
#define TRACE_EVENTS(cpu, fmt, ...) MAYBE_TRACE (EVENTS, cpu, fmt, ## __VA_ARGS__) |
|||
|
|||
#define TRACE_BRANCH(cpu, oldpc, newpc, fmt, ...) \ |
|||
do \ |
|||
{ \ |
|||
MAYBE_TRACE (BRANCH, cpu, fmt " to %#x", ## __VA_ARGS__, newpc); \ |
|||
} \ |
|||
while (0) |
|||
|
|||
extern void trace_register (SIM_DESC, sim_cpu *, const char *, ...) |
|||
__attribute__((format (printf, 3, 4))); |
|||
|
|||
#define TRACE_REGISTER(cpu, fmt, ...) \ |
|||
do \ |
|||
{ \ |
|||
if (TRACE_CORE_P (cpu)) \ |
|||
trace_register (CPU_STATE (cpu), cpu, fmt, ## __VA_ARGS__); \ |
|||
} \ |
|||
while (0) |
|||
|
|||
#define TRACE_REG(cpu, reg, val) \ |
|||
TRACE_REGISTER (cpu, "wrote R%d = %#x", reg, val) |
|||
|
|||
#endif /* _MSP430_MAIN_SIM_H_ */ |
|||
@ -0,0 +1,318 @@ |
|||
/* trace.c --- tracing output for the MSP430 simulator.
|
|||
|
|||
Copyright (C) 2005, 2007-2013 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 <stdarg.h> |
|||
#include <string.h> |
|||
#include <stdlib.h> |
|||
#include <sys/types.h> |
|||
#include <sys/stat.h> |
|||
#include <ctype.h> |
|||
|
|||
#include "libiberty.h" |
|||
#include "bfd.h" |
|||
#include "dis-asm.h" |
|||
|
|||
static int |
|||
sim_dis_read (bfd_vma memaddr, bfd_byte * ptr, unsigned int length, |
|||
struct disassemble_info *info) |
|||
{ |
|||
return 0; |
|||
} |
|||
|
|||
/* Filter out (in place) symbols that are useless for disassembly.
|
|||
COUNT is the number of elements in SYMBOLS. |
|||
Return the number of useful symbols. */ |
|||
|
|||
static long |
|||
remove_useless_symbols (asymbol ** symbols, long count) |
|||
{ |
|||
asymbol **in_ptr = symbols, **out_ptr = symbols; |
|||
|
|||
while (-- count >= 0) |
|||
{ |
|||
asymbol *sym = *in_ptr ++; |
|||
|
|||
if (strstr (sym->name, "gcc2_compiled")) |
|||
continue; |
|||
if (sym->name == NULL || sym->name[0] == '\0') |
|||
continue; |
|||
if (sym->flags & (BSF_DEBUGGING)) |
|||
continue; |
|||
if (bfd_is_und_section (sym->section) |
|||
|| bfd_is_com_section (sym->section)) |
|||
continue; |
|||
|
|||
if (sym->name[0] == '.' && sym->name[1] == 'L') |
|||
continue; |
|||
|
|||
/* If the symbol ends in ^A or ^B it is
|
|||
an assembler generated local label. */ |
|||
if (sym->name[strlen (sym->name) - 1] < 32) |
|||
continue; |
|||
|
|||
*out_ptr++ = sym; |
|||
} |
|||
return out_ptr - symbols; |
|||
} |
|||
|
|||
static int |
|||
compare_symbols (const PTR ap, const PTR bp) |
|||
{ |
|||
const asymbol *a = *(const asymbol **) ap; |
|||
const asymbol *b = *(const asymbol **) bp; |
|||
|
|||
if (bfd_asymbol_value (a) > bfd_asymbol_value (b)) |
|||
return 1; |
|||
else if (bfd_asymbol_value (a) < bfd_asymbol_value (b)) |
|||
return -1; |
|||
return 0; |
|||
} |
|||
|
|||
static char opbuf[1000]; |
|||
|
|||
static int |
|||
op_printf (char *buf, char *fmt, ...) |
|||
{ |
|||
int ret; |
|||
va_list ap; |
|||
|
|||
va_start (ap, fmt); |
|||
ret = vsprintf (opbuf + strlen (opbuf), fmt, ap); |
|||
va_end (ap); |
|||
return ret; |
|||
} |
|||
|
|||
static bfd * current_bfd = NULL; |
|||
static asymbol ** symtab = NULL; |
|||
static int symcount = 0; |
|||
static asection * code_section = NULL; |
|||
static bfd_vma code_base = 0; |
|||
static struct disassemble_info info; |
|||
|
|||
void |
|||
msp430_trace_init (bfd *prog) |
|||
{ |
|||
current_bfd = prog; |
|||
} |
|||
|
|||
typedef struct Files |
|||
{ |
|||
struct Files *next; |
|||
char *filename; |
|||
int nlines; |
|||
char **lines; |
|||
char *data; |
|||
} Files; |
|||
Files *files = 0; |
|||
|
|||
static char * |
|||
load_file_and_line (const char *filename, int lineno) |
|||
{ |
|||
Files *f; |
|||
for (f = files; f; f = f->next) |
|||
if (strcmp (f->filename, filename) == 0) |
|||
break; |
|||
if (!f) |
|||
{ |
|||
int i; |
|||
struct stat s; |
|||
const char *found_filename, *slash; |
|||
|
|||
found_filename = filename; |
|||
while (1) |
|||
{ |
|||
if (stat (found_filename, &s) == 0) |
|||
break; |
|||
slash = strchr (found_filename, '/'); |
|||
if (!slash) |
|||
return ""; |
|||
found_filename = slash + 1; |
|||
} |
|||
|
|||
f = (Files *) xmalloc (sizeof (Files)); |
|||
f->next = files; |
|||
files = f; |
|||
f->filename = xstrdup (filename); |
|||
f->data = (char *) xmalloc (s.st_size + 2); |
|||
FILE *file = fopen (found_filename, "rb"); |
|||
fread (f->data, 1, s.st_size, file); |
|||
f->data[s.st_size] = 0; |
|||
fclose (file); |
|||
|
|||
f->nlines = 1; |
|||
for (i = 0; i < s.st_size; i ++) |
|||
if (f->data[i] == '\n') |
|||
f->nlines ++; |
|||
f->lines = (char **) xmalloc (f->nlines * sizeof (char *)); |
|||
f->lines[0] = f->data; |
|||
f->nlines = 1; |
|||
for (i = 0; i < s.st_size; i ++) |
|||
if (f->data[i] == '\n') |
|||
{ |
|||
f->lines[f->nlines] = f->data + i + 1; |
|||
while (*f->lines[f->nlines] == ' ' |
|||
|| *f->lines[f->nlines] == '\t') |
|||
f->lines[f->nlines] ++; |
|||
f->nlines ++; |
|||
f->data[i] = 0; |
|||
} |
|||
} |
|||
if (lineno < 1 || lineno > f->nlines) |
|||
return ""; |
|||
return f->lines[lineno - 1]; |
|||
} |
|||
|
|||
int |
|||
msp430_get_current_source_location (int mypc, |
|||
const char ** pfilename, |
|||
const char ** pfunctionname, |
|||
unsigned int * plineno) |
|||
{ |
|||
static int initted = 0; |
|||
|
|||
if (current_bfd == NULL) |
|||
{ |
|||
printf("no bfd\n"); |
|||
return 0; |
|||
} |
|||
|
|||
if (!initted) |
|||
{ |
|||
int storage; |
|||
asection * s; |
|||
|
|||
initted = 1; |
|||
memset (& info, 0, sizeof (info)); |
|||
INIT_DISASSEMBLE_INFO (info, stdout, op_printf); |
|||
info.read_memory_func = sim_dis_read; |
|||
info.arch = bfd_get_arch (current_bfd); |
|||
info.mach = bfd_get_mach (current_bfd); |
|||
if (info.mach == 0) |
|||
info.arch = bfd_arch_msp430; |
|||
|
|||
disassemble_init_for_target (& info); |
|||
|
|||
storage = bfd_get_symtab_upper_bound (current_bfd); |
|||
if (storage > 0) |
|||
{ |
|||
symtab = (asymbol **) xmalloc (storage); |
|||
symcount = bfd_canonicalize_symtab (current_bfd, symtab); |
|||
symcount = remove_useless_symbols (symtab, symcount); |
|||
qsort (symtab, symcount, sizeof (asymbol *), compare_symbols); |
|||
} |
|||
|
|||
for (s = current_bfd->sections; s; s = s->next) |
|||
{ |
|||
if (s->flags & SEC_CODE || code_section == 0) |
|||
{ |
|||
code_section = s; |
|||
code_base = bfd_section_lma (current_bfd, s); |
|||
break; |
|||
} |
|||
} |
|||
} |
|||
|
|||
*pfilename = *pfunctionname = NULL; |
|||
*plineno = 0; |
|||
|
|||
bfd_find_nearest_line |
|||
(current_bfd, code_section, symtab, mypc - code_base, |
|||
pfilename, pfunctionname, plineno); |
|||
|
|||
return 1; |
|||
} |
|||
|
|||
void |
|||
msp430_trace_one (int mypc) |
|||
{ |
|||
static int last_sym = -1; |
|||
static const char * prev_filename = ""; |
|||
static int prev_lineno = 0; |
|||
const char * filename; |
|||
const char * functionname; |
|||
unsigned int lineno; |
|||
int sym, bestaddr; |
|||
int min, max, i; |
|||
|
|||
if (! msp430_get_current_source_location (mypc, & filename, & functionname, & lineno)) |
|||
return; |
|||
|
|||
if (filename && functionname && lineno) |
|||
{ |
|||
if (lineno != prev_lineno || strcmp (prev_filename, filename)) |
|||
{ |
|||
char * the_line = load_file_and_line (filename, lineno); |
|||
const char * slash = strrchr (filename, '/'); |
|||
|
|||
if (!slash) |
|||
slash = filename; |
|||
else |
|||
slash ++; |
|||
fprintf |
|||
(stderr, "========================================" |
|||
"=====================================\n"); |
|||
fprintf (stderr, "\033[37;41m %s:%d: \033[33;40m %s\033[K\033[0m\n", |
|||
slash, lineno, the_line); |
|||
} |
|||
prev_lineno = lineno; |
|||
prev_filename = filename; |
|||
} |
|||
|
|||
min = -1; |
|||
max = symcount; |
|||
while (min < max - 1) |
|||
{ |
|||
bfd_vma sa; |
|||
|
|||
sym = (min + max) / 2; |
|||
sa = bfd_asymbol_value (symtab[sym]); |
|||
/*printf ("checking %4d %08x %s\n",
|
|||
sym, sa, bfd_asymbol_name (symtab[sym])); */ |
|||
if (sa > mypc) |
|||
max = sym; |
|||
else if (sa < mypc) |
|||
min = sym; |
|||
else |
|||
{ |
|||
min = sym; |
|||
break; |
|||
} |
|||
} |
|||
|
|||
if (min != -1 && min != last_sym) |
|||
{ |
|||
bestaddr = bfd_asymbol_value (symtab[min]); |
|||
fprintf (stderr, "\033[43;30m%s", bfd_asymbol_name (symtab[min])); |
|||
if (bestaddr != mypc) |
|||
fprintf (stderr, "+%d", mypc - bestaddr); |
|||
fprintf (stderr, ":\t\t\t\033[0m\n"); |
|||
last_sym = min; |
|||
#if 0 |
|||
if (trace == 1) |
|||
if (strcmp (bfd_asymbol_name (symtab[min]), "abort") == 0 |
|||
|| strcmp (bfd_asymbol_name (symtab[min]), "exit") == 0) |
|||
trace = 0; |
|||
#endif |
|||
} |
|||
} |
|||
@ -0,0 +1,28 @@ |
|||
/* trace.h --- interface to tracing output for the MSP430 simulator.
|
|||
|
|||
Copyright (C) 2005, 2007-2013 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/>. */
|
|||
|
|||
#ifndef SIM_MSP430_TRACE_H_ |
|||
#define SIM_MSP430_TRACE_H_ |
|||
|
|||
extern void msp430_trace_init (bfd *); |
|||
extern void msp430_trace_one (int pc); |
|||
extern int msp430_get_current_source_location (const char **, const char **, unsigned int *); |
|||
|
|||
#endif |
|||
Loading…
Reference in new issue