* configure.tgt: Add rl78 support.
* configure: Regenerate.
* rl78: New directory.
* MAINTAINERS: Add myself as RL78 maintainer.
[gdb]
* NEWS: Mention RL78 simulator.
This commit is contained in:
DJ Delorie 2011-11-29 03:49:09 +00:00
parent 1e3a8f45c5
commit 87326c782a
20 changed files with 8649 additions and 0 deletions

View File

@ -1,3 +1,7 @@
2011-11-28 DJ Delorie <dj@redhat.com>
* NEWS: Mention RL78 simulator.
2011-11-28 Joel Brobecker <brobecker@adacore.com>
* symfile.h (struct quick_symbol_functions): Fix the documentation

View File

@ -233,6 +233,10 @@ qTMinFTPILen
Texas Instruments TMS320C6x tic6x-*-*
* New Simulators
Renesas RL78 rl78-*-elf
*** Changes in GDB 7.3.1
* The build failure for NetBSD and OpenBSD targets have now been fixed.

View File

@ -1,3 +1,10 @@
2011-11-28 DJ Delorie <dj@redhat.com>
* configure.tgt: Add rl78 support.
* configure: Regenerate.
* rl78: New directory.
* MAINTAINERS: Add myself as RL78 maintainer.
2011-07-08 Hans-Peter Nilsson <hp@axis.com>
* MAINTAINERS: Remove Thiemo Seufer.

View File

@ -15,6 +15,7 @@ cr16 M R Swami Reddy <MR.Swami.Reddy@nsc.com>
frv Dave Brolley <brolley@redhat.com>
igen (igen simulators)
lm32 Jon Beniston <jon@beniston.com>
rl78 DJ Delorie <dj@redhat.com>
m32c DJ Delorie <dj@redhat.com>
m32r Doug Evans <dje@sebabeach.org>
m68hc11 Stephane Carrez <stcarrez@nerim.fr>

8
sim/configure vendored
View File

@ -652,6 +652,7 @@ microblaze
mips
mn10300
moxie
rl78
rx
sh64
sh
@ -3773,6 +3774,13 @@ subdirs="$subdirs arm"
subdirs="$subdirs rx"
;;
rl78-*-*)
sim_arch=rl78
subdirs="$subdirs rl78"
;;
sh64*-*-*)

View File

@ -86,6 +86,9 @@ case "${target}" in
SIM_ARCH(moxie)
sim_testsuite=yes
;;
rl78-*-*)
SIM_ARCH(rl78)
;;
rx-*-*)
SIM_ARCH(rx)
;;

52
sim/rl78/Makefile.in Normal file
View File

@ -0,0 +1,52 @@
#### Makefile.in --- Makefile template for the RL78 simulator
### Copyright (C) 2008, 2009, 2010, 2011 Free Software Foundation, Inc.
### Contributed by Red Hat, Inc.
###
### This file is part of the GNU simulators.
###
### The GNU simulators are free software; you can redistribute them and/or
### modify them under the terms of the GNU General Public License as
### published by the Free Software Foundation; either version 2 of the
### License, or (at your option) any later version.
###
### The GNU simulators are distributed in the hope that they 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 the GNU simulators; if not, write to the Free Software
### Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
### 02110-1301, USA
## COMMON_PRE_CONFIG_FRAG
SIM_EXTRA_CFLAGS = -Wall
SIM_RUN_OBJS = \
main.o
SIM_OBJS = \
load.o \
mem.o \
cpu.o \
rl78.o \
trace.o
## COMMON_POST_CONFIG_FRAG
arch = rl78
err.o : err.h
fpu.o : cpu.h fpu.h
gdb-if.o : cpu.h mem.h load.h \
$(srcdir)/../../include/gdb/callback.h \
$(srcdir)/../../include/gdb/remote-sim.h \
$(srcdir)/../../include/gdb/signals.h \
$(srcdir)/../../include/gdb/sim-rl78.h
load.o : ../../bfd/bfd.h cpu.h mem.h
main.o : ../../bfd/bfd.h cpu.h mem.h load.h
mem.o : mem.h cpu.h
reg.o : cpu.h
rl78.o : $(srcdir)/../../include/opcode/rl78.h cpu.h mem.h

113
sim/rl78/config.in Normal file
View File

@ -0,0 +1,113 @@
/* config.in. Generated from configure.in 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 <getopt.h> header file. */
#undef HAVE_GETOPT_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 <zlib.h> header file. */
#undef HAVE_ZLIB_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 home page for this package. */
#undef PACKAGE_URL
/* Define to the version of this package. */
#undef PACKAGE_VERSION
/* Additional package description */
#undef PKGVERSION
/* Bug reporting address */
#undef REPORT_BUGS_TO
/* 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
/* --enable-cycle-accurate */
#undef CYCLE_ACCURATE
/* --enable-cycle-stats */
#undef CYCLE_STATS

5867
sim/rl78/configure vendored Executable file

File diff suppressed because it is too large Load Diff

30
sim/rl78/configure.ac Normal file
View File

@ -0,0 +1,30 @@
dnl Process this file with autoconf to produce a configure script.
dnl Copyright (C) 2005, 2007, 2008, 2009, 2010, 2011
dnl 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_OUTPUT

334
sim/rl78/cpu.c Normal file
View File

@ -0,0 +1,334 @@
/* cpu.c --- CPU for RL78 simulator.
Copyright (C) 2011
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 <string.h>
#include <stdlib.h>
#include "opcode/rl78.h"
#include "mem.h"
#include "cpu.h"
int verbose = 0;
int trace = 0;
int rl78_in_gdb = 1;
int timer_enabled = 2;
#define REGISTER_ADDRESS 0xffee0
typedef struct {
unsigned char x;
unsigned char a;
unsigned char c;
unsigned char b;
unsigned char e;
unsigned char d;
unsigned char l;
unsigned char h;
} RegBank;
static void trace_register_init ();
/* This maps PSW to a pointer into memory[] */
static RegBank *regbase_table[256];
#define regbase regbase_table[memory[RL78_SFR_PSW]]
#define REG(r) ((regbase)->r)
void
init_cpu (void)
{
int i;
init_mem ();
memset (memory+REGISTER_ADDRESS, 0x11, 8 * 4);
memory[RL78_SFR_PSW] = 0x06;
memory[RL78_SFR_ES] = 0x0f;
memory[RL78_SFR_CS] = 0x00;
memory[RL78_SFR_PMC] = 0x00;
for (i = 0; i < 256; i ++)
{
int rb0 = (i & RL78_PSW_RBS0) ? 1 : 0;
int rb1 = (i & RL78_PSW_RBS1) ? 2 : 0;
int rb = rb1 | rb0;
regbase_table[i] = (RegBank *)(memory + (3 - rb) * 8 + REGISTER_ADDRESS);
}
trace_register_init ();
/* This means "by default" */
timer_enabled = 2;
}
SI
get_reg (RL78_Register regno)
{
switch (regno)
{
case RL78_Reg_None:
/* Conditionals do this. */
return 0;
default:
abort ();
case RL78_Reg_X: return REG (x);
case RL78_Reg_A: return REG (a);
case RL78_Reg_C: return REG (c);
case RL78_Reg_B: return REG (b);
case RL78_Reg_E: return REG (e);
case RL78_Reg_D: return REG (d);
case RL78_Reg_L: return REG (l);
case RL78_Reg_H: return REG (h);
case RL78_Reg_AX: return REG (a) * 256 + REG (x);
case RL78_Reg_BC: return REG (b) * 256 + REG (c);
case RL78_Reg_DE: return REG (d) * 256 + REG (e);
case RL78_Reg_HL: return REG (h) * 256 + REG (l);
case RL78_Reg_SP: return memory[RL78_SFR_SP] + 256 * memory[RL78_SFR_SP+1];
case RL78_Reg_PSW: return memory[RL78_SFR_PSW];
case RL78_Reg_CS: return memory[RL78_SFR_CS];
case RL78_Reg_ES: return memory[RL78_SFR_ES];
case RL78_Reg_PMC: return memory[RL78_SFR_PMC];
case RL78_Reg_MEM: return memory[RL78_SFR_MEM];
}
}
extern unsigned char initted[];
SI
set_reg (RL78_Register regno, SI val)
{
switch (regno)
{
case RL78_Reg_None:
abort ();
case RL78_Reg_X: REG (x) = val; break;
case RL78_Reg_A: REG (a) = val; break;
case RL78_Reg_C: REG (c) = val; break;
case RL78_Reg_B: REG (b) = val; break;
case RL78_Reg_E: REG (e) = val; break;
case RL78_Reg_D: REG (d) = val; break;
case RL78_Reg_L: REG (l) = val; break;
case RL78_Reg_H: REG (h) = val; break;
case RL78_Reg_AX:
REG (a) = val >> 8;
REG (x) = val & 0xff;
break;
case RL78_Reg_BC:
REG (b) = val >> 8;
REG (c) = val & 0xff;
break;
case RL78_Reg_DE:
REG (d) = val >> 8;
REG (e) = val & 0xff;
break;
case RL78_Reg_HL:
REG (h) = val >> 8;
REG (l) = val & 0xff;
break;
case RL78_Reg_SP:
if (val & 1)
{
printf ("Warning: SP value 0x%04x truncated at pc=0x%05x\n", val, pc);
val &= ~1;
}
{
int old_sp = get_reg (RL78_Reg_SP);
if (val < old_sp)
{
int i;
for (i = val; i < old_sp; i ++)
initted[i + 0xf0000] = 0;
}
}
memory[RL78_SFR_SP] = val & 0xff;
memory[RL78_SFR_SP + 1] = val >> 8;
break;
case RL78_Reg_PSW: memory[RL78_SFR_PSW] = val; break;
case RL78_Reg_CS: memory[RL78_SFR_CS] = val; break;
case RL78_Reg_ES: memory[RL78_SFR_ES] = val; break;
case RL78_Reg_PMC: memory[RL78_SFR_PMC] = val; break;
case RL78_Reg_MEM: memory[RL78_SFR_MEM] = val; break;
}
return val;
}
int
condition_true (RL78_Condition cond_id, int val)
{
int psw = get_reg (RL78_Reg_PSW);
int z = (psw & RL78_PSW_Z) ? 1 : 0;
int cy = (psw & RL78_PSW_CY) ? 1 : 0;
switch (cond_id)
{
case RL78_Condition_T:
return val != 0;
case RL78_Condition_F:
return val == 0;
case RL78_Condition_C:
return cy;
case RL78_Condition_NC:
return !cy;
case RL78_Condition_H:
return !(z | cy);
case RL78_Condition_NH:
return z | cy;
case RL78_Condition_Z:
return z;
case RL78_Condition_NZ:
return !z;
default:
abort ();
}
}
const char * const
reg_names[] = {
"none",
"x",
"a",
"c",
"b",
"e",
"d",
"l",
"h",
"ax",
"bc",
"de",
"hl",
"sp",
"psw",
"cs",
"es",
"pmc",
"mem"
};
static char *
psw_string (int psw)
{
static char buf[30];
const char *comma = "";
buf[0] = 0;
if (psw == 0)
strcpy (buf, "-");
else
{
#define PSW1(bit, name) if (psw & bit) { strcat (buf, comma); strcat (buf, name); comma = ","; }
PSW1 (RL78_PSW_IE, "ie");
PSW1 (RL78_PSW_Z, "z");
PSW1 (RL78_PSW_RBS1, "r1");
PSW1 (RL78_PSW_AC, "ac");
PSW1 (RL78_PSW_RBS0, "r0");
PSW1 (RL78_PSW_ISP1, "i1");
PSW1 (RL78_PSW_ISP0, "i0");
PSW1 (RL78_PSW_CY, "cy");
}
printf ("%s", buf);
return buf;
}
static unsigned char old_regs[32];
static int old_psw;
static int old_sp;
int trace_register_words;
void
trace_register_changes (void)
{
int i;
int any = 0;
if (!trace)
return;
#define TB(name,nv,ov) if (nv != ov) { printf ("%s: \033[31m%02x \033[32m%02x\033[0m ", name, ov, nv); ov = nv; any = 1; }
#define TW(name,nv,ov) if (nv != ov) { printf ("%s: \033[31m%04x \033[32m%04x\033[0m ", name, ov, nv); ov = nv; any = 1; }
if (trace_register_words)
{
#define TRW(name, idx) TW (name, memory[REGISTER_ADDRESS + (idx)], old_regs[idx])
for (i = 0; i < 32; i += 2)
{
char buf[10];
int o, n, a;
switch (i)
{
case 0: strcpy (buf, "AX"); break;
case 2: strcpy (buf, "BC"); break;
case 4: strcpy (buf, "DE"); break;
case 6: strcpy (buf, "HL"); break;
default: sprintf (buf, "r%d", i); break;
}
a = REGISTER_ADDRESS + (i ^ 0x18);
o = old_regs[i ^ 0x18] + old_regs[(i ^ 0x18) + 1] * 256;
n = memory[a] + memory[a + 1] * 256;
TW (buf, n, o);
old_regs[i ^ 0x18] = n;
old_regs[(i ^ 0x18) + 1] = n >> 8;
}
}
else
{
for (i = 0; i < 32; i ++)
{
char buf[10];
if (i < 8)
{
buf[0] = "XACBEDLH"[i];
buf[1] = 0;
}
else
sprintf (buf, "r%d", i);
#define TRB(name, idx) TB (name, memory[REGISTER_ADDRESS + (idx)], old_regs[idx])
TRB (buf, i ^ 0x18);
}
}
if (memory[RL78_SFR_PSW] != old_psw)
{
printf ("PSW: \033[31m");
psw_string (old_psw);
printf (" \033[32m");
psw_string (memory[RL78_SFR_PSW]);
printf ("\033[0m ");
old_psw = memory[RL78_SFR_PSW];
any = 1;
}
TW ("SP", mem_get_hi (RL78_SFR_SP), old_sp);
if (any)
printf ("\n");
}
static void
trace_register_init (void)
{
memcpy (old_regs, memory + REGISTER_ADDRESS, 8 * 4);
old_psw = memory[RL78_SFR_PSW];
old_sp = mem_get_hi (RL78_SFR_SP);
}

101
sim/rl78/cpu.h Normal file
View File

@ -0,0 +1,101 @@
/* cpu.h --- declarations for the RL78 core.
Copyright (C) 2005, 2007, 2008, 2009, 2010, 2011
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_RL78_CPU_H_
#define SIM_RL78_CPU_H_
#include <stdint.h>
#include <setjmp.h>
#include "opcode/rl78.h"
extern int verbose;
extern int trace;
typedef uint8_t QI;
typedef uint16_t HI;
typedef uint32_t SI;
extern int rl78_in_gdb;
SI get_reg (RL78_Register);
SI set_reg (RL78_Register, SI);
SI pc;
extern const char * const reg_names[];
void init_cpu (void);
void set_flags (int mask, int newbits);
void set_c (int c);
int get_c (void);
const char *bits (int v, int b);
int condition_true (RL78_Condition cond_id, int val);
/* Instruction step return codes.
Suppose one of the decode_* functions below returns a value R:
- If RL78_STEPPED (R), then the single-step completed normally.
- If RL78_HIT_BREAK (R), then the program hit a breakpoint.
- If RL78_EXITED (R), then the program has done an 'exit' system
call, and the exit code is RL78_EXIT_STATUS (R).
- If RL78_STOPPED (R), then a signal (number RL78_STOP_SIG (R)) was
generated.
For building step return codes:
- RL78_MAKE_STEPPED is the return code for finishing a normal step.
- RL78_MAKE_HIT_BREAK is the return code for hitting a breakpoint.
- RL78_MAKE_EXITED (C) is the return code for exiting with status C.
- RL78_MAKE_STOPPED (S) is the return code for stopping on signal S. */
#define RL78_MAKE_STEPPED() (1)
#define RL78_MAKE_HIT_BREAK() (2)
#define RL78_MAKE_EXITED(c) (((int) (c) << 8) + 3)
#define RL78_MAKE_STOPPED(s) (((int) (s) << 8) + 4)
#define RL78_STEPPED(r) ((r) == RL78_MAKE_STEPPED ())
#define RL78_HIT_BREAK(r) ((r) == RL78_MAKE_HIT_BREAK ())
#define RL78_EXITED(r) (((r) & 0xff) == 3)
#define RL78_EXIT_STATUS(r) ((r) >> 8)
#define RL78_STOPPED(r) (((r) & 0xff) == 4)
#define RL78_STOP_SIG(r) ((r) >> 8)
/* The step result for the current step. Global to allow
communication between the stepping function and the system
calls. */
extern int step_result;
extern int decode_opcode (void);
extern int trace_register_words;
extern void trace_register_changes (void);
extern void generate_access_exception (void);
extern jmp_buf decode_jmp_buf;
extern long long total_clocks;
extern int pending_clocks;
extern int timer_enabled;
extern void dump_counts_per_insn (const char * filename);
extern unsigned int counts_per_insn[0x100000];
#endif

158
sim/rl78/load.c Normal file
View File

@ -0,0 +1,158 @@
/* load.c --- loading object files into the RL78 simulator.
Copyright (C) 2005, 2007, 2008, 2009, 2010, 2011
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 <stdlib.h>
#include <string.h>
#include "libiberty.h"
#include "bfd.h"
#include "libbfd.h"
#include "cpu.h"
#include "mem.h"
#include "load.h"
#include "elf/internal.h"
#include "elf/common.h"
/* Helper function for invoking a GDB-specified printf. */
static void
xprintf (host_callback *callback, const char *fmt, ...)
{
va_list ap;
va_start (ap, fmt);
(*callback->vprintf_filtered) (callback, fmt, ap);
va_end (ap);
}
/* Given a file offset, look up the section name. */
static const char *
find_section_name_by_offset (bfd *abfd, file_ptr filepos)
{
asection *s;
for (s = abfd->sections; s; s = s->next)
if (s->filepos == filepos)
return bfd_get_section_name (abfd, s);
return "(unknown)";
}
void
rl78_load (bfd *prog, host_callback *callbacks, const char * const simname)
{
Elf_Internal_Phdr * phdrs;
long sizeof_phdrs;
int num_headers;
int i;
int max_rom = 0;
init_cpu ();
/* Note we load by ELF program header not by BFD sections.
This is because BFD sections get their information from
the ELF section structure, which only includes a VMA value
and not an LMA value. */
sizeof_phdrs = bfd_get_elf_phdr_upper_bound (prog);
if (sizeof_phdrs == 0)
{
fprintf (stderr, "%s: Failed to get size of program headers\n", simname);
return;
}
phdrs = xmalloc (sizeof_phdrs);
num_headers = bfd_get_elf_phdrs (prog, phdrs);
if (num_headers < 1)
{
fprintf (stderr, "%s: Failed to read program headers\n", simname);
return;
}
for (i = 0; i < num_headers; i++)
{
Elf_Internal_Phdr * p = phdrs + i;
char *buf;
bfd_vma size;
bfd_vma base;
file_ptr offset;
size = p->p_filesz;
if (size <= 0)
continue;
base = p->p_paddr;
if (verbose > 1)
fprintf (stderr, "[load segment: lma=%08x vma=%08x size=%08x]\n",
(int) base, (int) p->p_vaddr, (int) size);
if (callbacks)
xprintf (callbacks,
"Loading section %s, size %#lx lma %08lx vma %08lx\n",
find_section_name_by_offset (prog, p->p_offset),
size, base, p->p_vaddr);
buf = xmalloc (size);
offset = p->p_offset;
if (prog->iovec->bseek (prog, offset, SEEK_SET) != 0)
{
fprintf (stderr, "%s, Failed to seek to offset %lx\n", simname, (long) offset);
continue;
}
if (prog->iovec->bread (prog, buf, size) != size)
{
fprintf (stderr, "%s: Failed to read %lx bytes\n", simname, size);
continue;
}
if (base > 0xeffff || base + size > 0xeffff)
{
fprintf (stderr, "%s, Can't load image to RAM/SFR space: 0x%lx - 0x%lx\n",
simname, base, base+size);
continue;
}
if (max_rom < base + size)
max_rom = base + size;
mem_put_blk (base, buf, size);
free (buf);
}
free (phdrs);
mem_rom_size (max_rom);
pc = prog->start_address;
if (strcmp (bfd_get_target (prog), "srec") == 0
|| pc == 0)
{
pc = mem_get_hi (0);
}
if (verbose > 1)
fprintf (stderr, "[start pc=%08x]\n", (unsigned int) pc);
}

30
sim/rl78/load.h Normal file
View File

@ -0,0 +1,30 @@
/* load.h --- interface to loading object files into the RX simulator.
Copyright (C) 2008, 2009, 2010, 2011 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_RL78_LOAD_H_
#define SIM_RL78_LOAD_H_
#include "bfd.h"
#include "gdb/callback.h"
void rl78_load (bfd *, host_callback *callbacks, const char * const simname);
#endif

169
sim/rl78/main.c Normal file
View File

@ -0,0 +1,169 @@
/* main.c --- main function for stand-alone RL78 simulator.
Copyright (C) 2011
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 <string.h>
#include <stdlib.h>
#ifdef HAVE_UNISTD_H
#include <unistd.h>
#endif
#include <assert.h>
#include <setjmp.h>
#include <signal.h>
#ifdef HAVE_GETOPT_H
#include <getopt.h>
#endif
#include "libiberty.h"
#include "bfd.h"
#include "cpu.h"
#include "mem.h"
#include "load.h"
#include "trace.h"
static int disassemble = 0;
static const char * dump_counts_filename = NULL;
static void
done (int exit_code)
{
if (verbose)
{
printf ("Exit code: %d\n", exit_code);
printf ("total clocks: %lld\n", total_clocks);
}
if (dump_counts_filename)
dump_counts_per_insn (dump_counts_filename);
exit (exit_code);
}
int
main (int argc, char **argv)
{
int o;
int save_trace;
bfd *prog;
int rc;
xmalloc_set_program_name (argv[0]);
while ((o = getopt (argc, argv, "tvdr:D:")) != -1)
{
switch (o)
{
case 't':
trace ++;
break;
case 'v':
verbose ++;
break;
case 'd':
disassemble ++;
break;
case 'r':
mem_ram_size (atoi (optarg));
break;
case 'D':
dump_counts_filename = optarg;
break;
case '?':
{
fprintf (stderr,
"usage: run [options] program [arguments]\n");
fprintf (stderr,
"\t-v\t\t- increase verbosity.\n"
"\t-t\t\t- trace.\n"
"\t-d\t\t- disassemble.\n"
"\t-r <bytes>\t- ram size.\n"
"\t-D <filename>\t- dump cycle count histogram\n");
exit (1);
}
}
}
prog = bfd_openr (argv[optind], 0);
if (!prog)
{
fprintf (stderr, "Can't read %s\n", argv[optind]);
exit (1);
}
if (!bfd_check_format (prog, bfd_object))
{
fprintf (stderr, "%s not a rl78 program\n", argv[optind]);
exit (1);
}
init_cpu ();
rl78_in_gdb = 0;
save_trace = trace;
trace = 0;
rl78_load (prog, 0, argv[0]);
trace = save_trace;
sim_disasm_init (prog);
rc = setjmp (decode_jmp_buf);
if (rc == 0)
{
if (!trace && !disassemble)
{
/* This will longjmp to the above if an exception
happens. */
for (;;)
decode_opcode ();
}
else
while (1)
{
if (trace)
printf ("\n");
if (disassemble)
sim_disasm_one ();
rc = decode_opcode ();
if (trace)
trace_register_changes ();
}
}
if (RL78_HIT_BREAK (rc))
done (1);
else if (RL78_EXITED (rc))
done (RL78_EXIT_STATUS (rc));
else if (RL78_STOPPED (rc))
{
if (verbose)
printf ("Stopped on signal %d\n", RL78_STOP_SIG (rc));
exit (1);
}
done (0);
exit (0);
}

426
sim/rl78/mem.c Normal file
View File

@ -0,0 +1,426 @@
/* mem.c --- memory for RL78 simulator.
Copyright (C) 2011
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 <stdlib.h>
#include <string.h>
#include "opcode/rl78.h"
#include "mem.h"
#include "cpu.h"
#define ILLEGAL_OPCODE 0xff
int rom_limit = 0x100000;
int ram_base = 0xf8000;
unsigned char memory[MEM_SIZE];
#define MASK 0xfffff
unsigned char initted[MEM_SIZE];
int skip_init = 0;
#define tprintf if (trace) printf
void
init_mem (void)
{
memset (memory, ILLEGAL_OPCODE, sizeof (memory));
memset (memory + 0xf0000, 0x33, 0x10000);
memset (initted, 0, sizeof (initted));
memset (initted + 0xffee0, 1, 0x00120);
memset (initted + 0xf0000, 1, 0x01000);
}
void
mem_ram_size (int ram_bytes)
{
ram_base = 0x100000 - ram_bytes;
}
void
mem_rom_size (int rom_bytes)
{
rom_limit = rom_bytes;
}
/* ---------------------------------------------------------------------- */
/* Note: the RL78 memory map has a few surprises. For starters, part
of the first 64k is mapped to the last 64k, depending on an SFR bit
and how much RAM the chip has. This is simulated here, as are a
few peripherals. */
/* This is stdout. We only care about the data byte, not the upper byte. */
#define SDR00 0xfff10
#define SSR00 0xf0100
#define TS0 0xf01b2
/* RL78/G13 multiply/divide peripheral. */
#define MDUC 0xf00e8
#define MDAL 0xffff0
#define MDAH 0xffff2
#define MDBL 0xffff4
#define MDBH 0xffff6
#define MDCL 0xf00e0
#define MDCH 0xf00e2
static long long mduc_clock = 0;
static int mda_set = 0;
#define MDA_SET 15
static int last_addr_was_mirror;
static int
address_mapping (int address)
{
address &= MASK;
if (address >= 0xf1000 && address < ram_base)
{
address &= 0xffff;
tprintf ("&");
if (memory[RL78_SFR_PMC] & 1)
{
tprintf ("|");
address |= 0x10000;
}
last_addr_was_mirror = 1;
}
else
last_addr_was_mirror = 0;
return address;
}
static void
mem_put_byte (int address, unsigned char value)
{
address = address_mapping (address);
memory [address] = value;
initted [address] = 1;
if (address == SDR00)
{
putchar (value);
fflush (stdout);
}
if (address == TS0)
{
if (timer_enabled == 2)
{
total_clocks = 0;
pending_clocks = 0;
memset (counts_per_insn, 0, sizeof (counts_per_insn));
memory[0xf0180] = 0xff;
memory[0xf0181] = 0xff;
}
if (value & 1)
timer_enabled = 1;
else
timer_enabled = 0;
}
if (address == RL78_SFR_SP && value & 1)
{
printf ("Warning: SP value 0x%04x truncated at pc=0x%05x\n", value, pc);
value &= ~1;
}
if (address == MDUC)
{
if ((value & 0x81) == 0x81)
{
/* division */
mduc_clock = total_clocks;
}
}
if ((address & ~3) == MDAL)
{
mda_set |= (1 << (address & 3));
if (mda_set == MDA_SET)
{
long als, ahs;
unsigned long alu, ahu;
long rvs;
long mdc;
unsigned long rvu;
mda_set = 0;
switch (memory [MDUC] & 0xc8)
{
case 0x00:
alu = mem_get_hi (MDAL);
ahu = mem_get_hi (MDAH);
rvu = alu * ahu;
tprintf ("MDUC: %lu * %lu = %lu\n", alu, ahu, rvu);
mem_put_si (MDBL, rvu);
break;
case 0x08:
als = sign_ext (mem_get_hi (MDAL), 16);
ahs = sign_ext (mem_get_hi (MDAH), 16);
rvs = als * ahs;
tprintf ("MDUC: %ld * %ld = %ld\n", als, ahs, rvs);
mem_put_si (MDBL, rvs);
break;
case 0x40:
alu = mem_get_hi (MDAL);
ahu = mem_get_hi (MDAH);
rvu = alu * ahu;
mem_put_si (MDBL, rvu);
mdc = mem_get_si (MDCL);
tprintf ("MDUC: %lu * %lu + %lu = ", alu, ahu, mdc);
mdc += (long) rvu;
tprintf ("%lu\n", mdc);
mem_put_si (MDCL, mdc);
break;
case 0x48:
als = sign_ext (mem_get_hi (MDAL), 16);
ahs = sign_ext (mem_get_hi (MDAH), 16);
rvs = als * ahs;
mem_put_si (MDBL, rvs);
mdc = mem_get_si (MDCL);
tprintf ("MDUC: %ld * %ld + %ld = ", als, ahs, mdc);
tprintf ("%ld\n", mdc);
mdc += rvs;
mem_put_si (MDCL, mdc);
break;
}
}
}
}
extern long long total_clocks;
static unsigned char
mem_get_byte (int address)
{
address = address_mapping (address);
switch (address)
{
case SSR00:
case SSR00 + 1:
return 0x00;
case 0xf00f0:
return 0;
case 0xf0180:
case 0xf0181:
return memory[address];
case MDUC:
{
unsigned char mduc = memory [MDUC];
if ((mduc & 0x81) == 0x81
&& total_clocks > mduc_clock + 16)
{
unsigned long a, b, q, r;
memory [MDUC] &= 0xfe;
a = mem_get_si (MDAL);
b = mem_get_si (MDAL);
if (b == 0)
{
q = ~0;
r = ~0;
}
else
{
q = a / b;
r = a % b;
}
tprintf ("MDUC: %lu / %lu = q %lu, r %lu\n", a, b, q, r);
mem_put_si (MDAL, q);
mem_put_si (MDCL, r);
}
return memory[address];
}
case MDCL:
case MDCL + 1:
case MDCH:
case MDCH + 1:
return memory[address];
}
if (address < 0xf1000 && address >= 0xf0000)
{
#if 1
/* Note: comment out this return to trap the invalid access
instead of returning an "undefined" value. */
return 0x11;
#else
fprintf (stderr, "SFR access error: addr 0x%05x pc 0x%05x\n", address, pc);
exit (1);
#endif
}
#if 0
/* Uncomment this block if you want to trap on reads from unwritten memory. */
if (!skip_init && !initted [address])
{
static int uninit_count = 0;
fprintf (stderr, "\033[31mwarning :read from uninit addr %05x pc %05x\033[0m\n", address, pc);
uninit_count ++;
if (uninit_count > 5)
exit (1);
}
#endif
return memory [address];
}
extern jmp_buf decode_jmp_buf;
#define DO_RETURN(x) longjmp (decode_jmp_buf, x)
#define CHECK_ALIGNMENT(a,v,m) \
if (a & m) { printf ("Misalignment addr 0x%05x val 0x%04x pc %05x\n", (int)a, (int)v, (int)pc); \
DO_RETURN (RL78_MAKE_HIT_BREAK ()); }
/* ---------------------------------------------------------------------- */
#define SPECIAL_ADDR(a) (0xffff0 <= a || (0xffee0 <= a && a < 0xfff00))
void
mem_put_qi (int address, unsigned char value)
{
if (!SPECIAL_ADDR (address))
tprintf ("\033[34m([%05X]<-%02X)\033[0m", address, value);
mem_put_byte (address, value);
}
void
mem_put_hi (int address, unsigned short value)
{
if (!SPECIAL_ADDR (address))
tprintf ("\033[34m([%05X]<-%04X)\033[0m", address, value);
CHECK_ALIGNMENT (address, value, 1);
if (address > 0xffff8 && address != RL78_SFR_SP)
{
tprintf ("Word access to 0x%05x!!\n", address);
DO_RETURN (RL78_MAKE_HIT_BREAK ());
}
mem_put_byte (address, value);
mem_put_byte (address + 1, value >> 8);
}
void
mem_put_psi (int address, unsigned long value)
{
tprintf ("\033[34m([%05X]<-%06lX)\033[0m", address, value);
mem_put_byte (address, value);
mem_put_byte (address + 1, value >> 8);
mem_put_byte (address + 2, value >> 16);
}
void
mem_put_si (int address, unsigned long value)
{
tprintf ("\033[34m([%05X]<-%08lX)\033[0m", address, value);
CHECK_ALIGNMENT (address, value, 3);
mem_put_byte (address, value);
mem_put_byte (address + 1, value >> 8);
mem_put_byte (address + 2, value >> 16);
mem_put_byte (address + 3, value >> 24);
}
void
mem_put_blk (int address, const void *bufptr, int nbytes)
{
const unsigned char *bp = (unsigned char *)bufptr;
while (nbytes --)
mem_put_byte (address ++, *bp ++);
}
unsigned char
mem_get_pc (int address)
{
/* Catch obvious problems. */
if (address >= rom_limit && address < 0xf0000)
return 0xff;
/* This does NOT go through the flash mirror area; you cannot
execute out of the mirror. */
return memory [address & MASK];
}
unsigned char
mem_get_qi (int address)
{
int v;
v = mem_get_byte (address);
if (!SPECIAL_ADDR (address))
tprintf ("\033[35m([%05X]->%04X)\033[0m", address, v);
if (last_addr_was_mirror)
{
pending_clocks += 3;
tprintf ("ROM read\n");
}
return v;
}
unsigned short
mem_get_hi (int address)
{
int v;
v = mem_get_byte (address)
| mem_get_byte (address + 1) * 256;
CHECK_ALIGNMENT (address, v, 1);
if (!SPECIAL_ADDR (address))
tprintf ("\033[35m([%05X]->%04X)\033[0m", address, v);
if (last_addr_was_mirror)
{
pending_clocks += 3;
tprintf ("ROM read\n");
}
return v;
}
unsigned long
mem_get_psi (int address)
{
int v;
v = mem_get_byte (address)
| mem_get_byte (address + 1) * 256
| mem_get_byte (address + 2) * 65536;
tprintf ("\033[35m([%05X]->%04X)\033[0m", address, v);
return v;
}
unsigned long
mem_get_si (int address)
{
int v;
v = mem_get_byte (address)
| mem_get_byte (address + 1) * 256
| mem_get_byte (address + 2) * 65536
| mem_get_byte (address + 2) * 16777216;
CHECK_ALIGNMENT (address, v, 3);
tprintf ("(\033[35m[%05X]->%04X)\033[0m", address, v);
return v;
}
void
mem_get_blk (int address, void *bufptr, int nbytes)
{
unsigned char *bp = (unsigned char *)bufptr;
while (nbytes --)
*bp ++ = mem_get_byte (address ++);
}
int
sign_ext (int v, int bits)
{
if (bits < 8 * sizeof (int))
{
v &= (1 << bits) - 1;
if (v & (1 << (bits - 1)))
v -= (1 << bits);
}
return v;
}

55
sim/rl78/mem.h Normal file
View File

@ -0,0 +1,55 @@
/* mem.h --- interface to memory for RL78 simulator.
Copyright (C) 2011
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_RL78_MEM_H_
#define SIM_RL78_MEM_H_
#define MEM_SIZE 0x100000
/* Only for cpu.c to use. */
extern unsigned char memory[];
void init_mem (void);
/* Pass the amount of bytes, like 2560 for 2.5k */
void mem_ram_size (int ram_bytes);
void mem_rom_size (int rom_bytes);
void mem_put_qi (int address, unsigned char value);
void mem_put_hi (int address, unsigned short value);
void mem_put_psi (int address, unsigned long value);
void mem_put_si (int address, unsigned long value);
void mem_put_blk (int address, const void *bufptr, int nbytes);
unsigned char mem_get_pc (int address);
unsigned char mem_get_qi (int address);
unsigned short mem_get_hi (int address);
unsigned long mem_get_psi (int address);
unsigned long mem_get_si (int address);
void mem_get_blk (int address, void *bufptr, int nbytes);
int sign_ext (int v, int bits);
#endif

915
sim/rl78/rl78.c Normal file
View File

@ -0,0 +1,915 @@
/* rl78.c --- opcode semantics for stand-alone RL78 simulator.
Copyright (C) 2008, 2009, 2010, 2011 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 <stdlib.h>
#include <string.h>
#include <signal.h>
#include <setjmp.h>
#include <time.h>
#include "opcode/rl78.h"
#include "cpu.h"
#include "mem.h"
extern int skip_init;
static int opcode_pc = 0;
jmp_buf decode_jmp_buf;
#define DO_RETURN(x) longjmp (decode_jmp_buf, x)
#define tprintf if (trace) printf
#define WILD_JUMP_CHECK(new_pc) \
do { \
if (new_pc == 0 || new_pc > 0xfffff) \
{ \
pc = opcode_pc; \
fprintf (stderr, "Wild jump to 0x%x from 0x%x!\n", new_pc, pc); \
DO_RETURN (RL78_MAKE_HIT_BREAK ()); \
} \
} while (0)
typedef struct {
unsigned long dpc;
} RL78_Data;
static int
rl78_get_byte (void *vdata)
{
RL78_Data *rl78_data = (RL78_Data *)vdata;
int rv = mem_get_pc (rl78_data->dpc);
rl78_data->dpc ++;
return rv;
}
static int
op_addr (const RL78_Opcode_Operand *o, int for_data)
{
int v = o->addend;
if (o->reg != RL78_Reg_None)
v += get_reg (o->reg);
if (o->reg2 != RL78_Reg_None)
v += get_reg (o->reg2);
if (o->use_es)
v |= (get_reg (RL78_Reg_ES) & 0xf) << 16;
else if (for_data)
v |= 0xf0000;
v &= 0xfffff;
return v;
}
static int
get_op (const RL78_Opcode_Decoded *rd, int i, int for_data)
{
int v, r;
const RL78_Opcode_Operand *o = rd->op + i;
switch (o->type)
{
case RL78_Operand_None:
/* condition code does this. */
v = 0;
break;
case RL78_Operand_Immediate:
tprintf (" #");
v = o->addend;
break;
case RL78_Operand_Register:
tprintf (" %s=", reg_names[o->reg]);
v = get_reg (o->reg);
break;
case RL78_Operand_Bit:
tprintf (" %s.%d=", reg_names[o->reg], o->bit_number);
v = get_reg (o->reg);
v = (v & (1 << o->bit_number)) ? 1 : 0;
break;
case RL78_Operand_Indirect:
v = op_addr (o, for_data);
tprintf (" [0x%x]=", v);
if (rd->size == RL78_Word)
v = mem_get_hi (v);
else
v = mem_get_qi (v);
break;
case RL78_Operand_BitIndirect:
v = op_addr (o, for_data);
tprintf (" [0x%x].%d=", v, o->bit_number);
v = (mem_get_qi (v) & (1 << o->bit_number)) ? 1 : 0;
break;
case RL78_Operand_PreDec:
r = get_reg (o->reg);
tprintf (" [--%s]", reg_names[o->reg]);
if (rd->size == RL78_Word)
{
r -= 2;
v = mem_get_hi (r | 0xf0000);
}
else
{
r -= 1;
v = mem_get_qi (r | 0xf0000);
}
set_reg (o->reg, r);
break;
case RL78_Operand_PostInc:
tprintf (" [%s++]", reg_names[o->reg]);
r = get_reg (o->reg);
if (rd->size == RL78_Word)
{
v = mem_get_hi (r | 0xf0000);
r += 2;
}
else
{
v = mem_get_qi (r | 0xf0000);
r += 1;
}
set_reg (o->reg, r);
break;
default:
abort ();
}
tprintf ("%d", v);
return v;
}
static void
put_op (const RL78_Opcode_Decoded *rd, int i, int for_data, int v)
{
int r, a;
const RL78_Opcode_Operand *o = rd->op + i;
tprintf (" -> ");
switch (o->type)
{
case RL78_Operand_Register:
tprintf ("%s", reg_names[o->reg]);
set_reg (o->reg, v);
break;
case RL78_Operand_Bit:
tprintf ("%s.%d", reg_names[o->reg], o->bit_number);
r = get_reg (o->reg);
if (v)
r |= (1 << o->bit_number);
else
r &= ~(1 << o->bit_number);
set_reg (o->reg, r);
break;
case RL78_Operand_Indirect:
r = op_addr (o, for_data);
tprintf ("[0x%x]", r);
if (rd->size == RL78_Word)
mem_put_hi (r, v);
else
mem_put_qi (r, v);
break;
case RL78_Operand_BitIndirect:
a = op_addr (o, for_data);
tprintf ("[0x%x].%d", a, o->bit_number);
r = mem_get_qi (a);
if (v)
r |= (1 << o->bit_number);
else
r &= ~(1 << o->bit_number);
mem_put_qi (a, r);
break;
case RL78_Operand_PreDec:
r = get_reg (o->reg);
tprintf ("[--%s]", reg_names[o->reg]);
if (rd->size == RL78_Word)
{
r -= 2;
set_reg (o->reg, r);
mem_put_hi (r | 0xf0000, v);
}
else
{
r -= 1;
set_reg (o->reg, r);
mem_put_qi (r | 0xf0000, v);
}
break;
case RL78_Operand_PostInc:
tprintf ("[%s++]", reg_names[o->reg]);
r = get_reg (o->reg);
if (rd->size == RL78_Word)
{
mem_put_hi (r | 0xf0000, v);
r += 2;
}
else
{
mem_put_qi (r | 0xf0000, v);
r += 1;
}
set_reg (o->reg, r);
break;
default:
abort ();
}
tprintf ("\n");
}
static void
op_flags (int before, int after, int mask, RL78_Size size)
{
int vmask, cmask, amask, avmask;
if (size == RL78_Word)
{
cmask = 0x10000;
vmask = 0xffff;
amask = 0x100;
avmask = 0x0ff;
}
else
{
cmask = 0x100;
vmask = 0xff;
amask = 0x10;
avmask = 0x0f;
}
int psw = get_reg (RL78_Reg_PSW);
psw &= ~mask;
if (mask & RL78_PSW_CY)
{
if ((after & cmask) != (before & cmask))
psw |= RL78_PSW_CY;
}
if (mask & RL78_PSW_AC)
{
if ((after & amask) != (before & amask)
&& (after & avmask) < (before & avmask))
psw |= RL78_PSW_AC;
}
if (mask & RL78_PSW_Z)
{
if (! (after & vmask))
psw |= RL78_PSW_Z;
}
set_reg (RL78_Reg_PSW, psw);
}
#define FLAGS(before,after) if (opcode.flags) op_flags (before, after, opcode.flags, opcode.size)
#define PD(x) put_op (&opcode, 0, 1, x)
#define PS(x) put_op (&opcode, 1, 1, x)
#define GD() get_op (&opcode, 0, 1)
#define GS() get_op (&opcode, 1, 1)
#define GPC() gpc (&opcode, 0)
static int
gpc (RL78_Opcode_Decoded *opcode, int idx)
{
int a = get_op (opcode, 0, 1);
if (opcode->op[idx].type == RL78_Operand_Register)
a =(a & 0x0ffff) | ((get_reg (RL78_Reg_CS) & 0x0f) << 16);
else
a &= 0xfffff;
return a;
}
static int
get_carry (void)
{
return (get_reg (RL78_Reg_PSW) & RL78_PSW_CY) ? 1 : 0;
}
static void
set_carry (int c)
{
int p = get_reg (RL78_Reg_PSW);
tprintf ("set_carry (%d)\n", c ? 1 : 0);
if (c)
p |= RL78_PSW_CY;
else
p &= ~RL78_PSW_CY;
set_reg (RL78_Reg_PSW, p);
}
/* We simulate timer TM00 in interval mode, no clearing, with
interrupts. I.e. it's a cycle counter. */
unsigned int counts_per_insn[0x100000];
int pending_clocks = 0;
long long total_clocks = 0;
#define TCR0 0xf0180
#define MK1 0xfffe6
static void
process_clock_tick (void)
{
unsigned short cnt;
unsigned short ivect;
unsigned short mask;
unsigned char psw;
int save_trace;
save_trace = trace;
trace = 0;
pending_clocks ++;
counts_per_insn[opcode_pc] += pending_clocks;
total_clocks += pending_clocks;
while (pending_clocks)
{
pending_clocks --;
cnt = mem_get_hi (TCR0);
cnt --;
mem_put_hi (TCR0, cnt);
if (cnt != 0xffff)
continue;
/* overflow. */
psw = get_reg (RL78_Reg_PSW);
ivect = mem_get_hi (0x0002c);
mask = mem_get_hi (MK1);
if ((psw & RL78_PSW_IE)
&& (ivect != 0)
&& !(mask & 0x0010))
{
unsigned short sp = get_reg (RL78_Reg_SP);
set_reg (RL78_Reg_SP, sp - 4);
sp --;
mem_put_qi (sp | 0xf0000, psw);
sp -= 3;
mem_put_psi (sp | 0xf0000, pc);
psw &= ~RL78_PSW_IE;
set_reg (RL78_Reg_PSW, psw);
pc = ivect;
/* Spec says 9-14 clocks */
pending_clocks += 9;
}
}
trace = save_trace;
}
void
dump_counts_per_insn (const char * filename)
{
int i;
FILE *f;
f = fopen (filename, "w");
if (!f)
{
perror (filename);
return;
}
for (i = 0; i < 0x100000; i ++)
{
if (counts_per_insn[i])
fprintf (f, "%05x %d\n", i, counts_per_insn[i]);
}
fclose (f);
}
static void
CLOCKS (int n)
{
pending_clocks += n - 1;
}
int
decode_opcode (void)
{
RL78_Data rl78_data;
RL78_Opcode_Decoded opcode;
int opcode_size;
int a, b, v, v2;
unsigned int u, u2;
int obits;
rl78_data.dpc = pc;
opcode_size = rl78_decode_opcode (pc, &opcode,
rl78_get_byte, &rl78_data);
opcode_pc = pc;
pc += opcode_size;
trace_register_words = opcode.size == RL78_Word ? 1 : 0;
/* Used by shfit/rotate instructions */
obits = opcode.size == RL78_Word ? 16 : 8;
switch (opcode.id)
{
case RLO_add:
tprintf ("ADD: ");
a = GS ();
b = GD ();
v = a + b;
FLAGS (b, v);
PD (v);
if (opcode.op[0].type == RL78_Operand_Indirect)
CLOCKS (2);
break;
case RLO_addc:
tprintf ("ADDC: ");
a = GS ();
b = GD ();
v = a + b + get_carry ();
FLAGS (b, v);
PD (v);
if (opcode.op[0].type == RL78_Operand_Indirect)
CLOCKS (2);
break;
case RLO_and:
tprintf ("AND: ");
a = GS ();
b = GD ();
v = a & b;
FLAGS (b, v);
PD (v);
if (opcode.op[0].type == RL78_Operand_Indirect)
CLOCKS (2);
break;
case RLO_branch_cond:
case RLO_branch_cond_clear:
tprintf ("BRANCH_COND: ");
if (!condition_true (opcode.op[1].condition, GS ()))
{
tprintf (" false\n");
if (opcode.op[1].condition == RL78_Condition_T
|| opcode.op[1].condition == RL78_Condition_F)
CLOCKS (3);
else
CLOCKS (2);
break;
}
if (opcode.id == RLO_branch_cond_clear)
PS (0);
tprintf (" ");
if (opcode.op[1].condition == RL78_Condition_T
|| opcode.op[1].condition == RL78_Condition_F)
CLOCKS (3); /* note: adds two clocks, total 5 clocks */
else
CLOCKS (2); /* note: adds one clock, total 4 clocks */
case RLO_branch:
tprintf ("BRANCH: ");
v = GPC ();
WILD_JUMP_CHECK (v);
pc = v;
tprintf (" => 0x%05x\n", pc);
CLOCKS (3);
break;
case RLO_break:
tprintf ("BRK: ");
CLOCKS (5);
if (rl78_in_gdb)
DO_RETURN (RL78_MAKE_HIT_BREAK ());
else
DO_RETURN (RL78_MAKE_EXITED (1));
break;
case RLO_call:
tprintf ("CALL: ");
a = get_reg (RL78_Reg_SP);
set_reg (RL78_Reg_SP, a - 4);
mem_put_psi ((a - 4) | 0xf0000, pc);
v = GPC ();
WILD_JUMP_CHECK (v);
pc = v;
#if 0
/* Enable this code to dump the arguments for each call. */
if (trace)
{
int i;
skip_init ++;
for (i = 0; i < 8; i ++)
printf (" %02x", mem_get_qi (0xf0000 | (a + i)) & 0xff);
skip_init --;
}
#endif
tprintf ("\n");
CLOCKS (3);
break;
case RLO_cmp:
tprintf ("CMP: ");
a = GD ();
b = GS ();
v = a - b;
FLAGS (b, v);
tprintf (" (%d)\n", v);
break;
case RLO_divhu:
a = get_reg (RL78_Reg_AX);
b = get_reg (RL78_Reg_DE);
tprintf (" %d / %d = ", a, b);
if (b == 0)
{
tprintf ("%d rem %d\n", 0xffff, a);
set_reg (RL78_Reg_AX, 0xffff);
set_reg (RL78_Reg_DE, a);
}
else
{
v = a / b;
a = a % b;
tprintf ("%d rem %d\n", v, a);
set_reg (RL78_Reg_AX, v);
set_reg (RL78_Reg_DE, a);
}
CLOCKS (9);
break;
case RLO_divwu:
{
unsigned long bcax, hlde, quot, rem;
bcax = get_reg (RL78_Reg_AX) + 65536 * get_reg (RL78_Reg_BC);
hlde = get_reg (RL78_Reg_DE) + 65536 * get_reg (RL78_Reg_HL);
tprintf (" %lu / %lu = ", bcax, hlde);
if (hlde == 0)
{
tprintf ("%lu rem %lu\n", 0xffffLU, bcax);
set_reg (RL78_Reg_AX, 0xffffLU);
set_reg (RL78_Reg_BC, 0xffffLU);
set_reg (RL78_Reg_DE, bcax);
set_reg (RL78_Reg_HL, bcax >> 16);
}
else
{
quot = bcax / hlde;
rem = bcax % hlde;
tprintf ("%lu rem %lu\n", quot, rem);
set_reg (RL78_Reg_AX, quot);
set_reg (RL78_Reg_BC, quot >> 16);
set_reg (RL78_Reg_DE, rem);
set_reg (RL78_Reg_HL, rem >> 16);
}
}
CLOCKS (17);
break;
case RLO_halt:
tprintf ("HALT.\n");
DO_RETURN (RL78_MAKE_EXITED (get_reg (RL78_Reg_A)));
case RLO_mov:
tprintf ("MOV: ");
a = GS ();
FLAGS (a, a);
PD (a);
break;
#define MACR 0xffff0
case RLO_mach:
tprintf ("MACH:");
a = sign_ext (get_reg (RL78_Reg_AX), 16);
b = sign_ext (get_reg (RL78_Reg_BC), 16);
v = sign_ext (mem_get_si (MACR), 32);
tprintf ("%08x %d + %d * %d = ", v, v, a, b);
v2 = sign_ext (v + a * b, 32);
tprintf ("%08x %d\n", v2, v2);
mem_put_si (MACR, v2);
a = get_reg (RL78_Reg_PSW);
v ^= v2;
if (v & (1<<31))
a |= RL78_PSW_CY;
else
a &= ~RL78_PSW_CY;
if (v2 & (1 << 31))
a |= RL78_PSW_AC;
else
a &= ~RL78_PSW_AC;
set_reg (RL78_Reg_PSW, a);
CLOCKS (3);
break;
case RLO_machu:
tprintf ("MACHU:");
a = get_reg (RL78_Reg_AX);
b = get_reg (RL78_Reg_BC);
u = mem_get_si (MACR);
tprintf ("%08x %u + %u * %u = ", u, u, a, b);
u2 = (u + (unsigned)a * (unsigned)b) & 0xffffffffUL;
tprintf ("%08x %u\n", u2, u2);
mem_put_si (MACR, u2);
a = get_reg (RL78_Reg_PSW);
if (u2 < u)
a |= RL78_PSW_CY;
else
a &= ~RL78_PSW_CY;
a &= ~RL78_PSW_AC;
set_reg (RL78_Reg_PSW, a);
CLOCKS (3);
break;
case RLO_mulu:
tprintf ("MULU:");
a = get_reg (RL78_Reg_A);
b = get_reg (RL78_Reg_X);
v = a * b;
tprintf (" %d * %d = %d\n", a, b, v);
set_reg (RL78_Reg_AX, v);
break;
case RLO_mulh:
tprintf ("MUL:");
a = sign_ext (get_reg (RL78_Reg_AX), 16);
b = sign_ext (get_reg (RL78_Reg_BC), 16);
v = a * b;
tprintf (" %d * %d = %d\n", a, b, v);
set_reg (RL78_Reg_BC, v >> 16);
set_reg (RL78_Reg_AX, v);
CLOCKS (2);
break;
case RLO_mulhu:
tprintf ("MULHU:");
a = get_reg (RL78_Reg_AX);
b = get_reg (RL78_Reg_BC);
v = a * b;
tprintf (" %d * %d = %d\n", a, b, v);
set_reg (RL78_Reg_BC, v >> 16);
set_reg (RL78_Reg_AX, v);
CLOCKS (2);
break;
case RLO_nop:
tprintf ("NOP.\n");
break;
case RLO_or:
tprintf ("OR:");
a = GS ();
b = GD ();
v = a | b;
FLAGS (b, v);
PD (v);
if (opcode.op[0].type == RL78_Operand_Indirect)
CLOCKS (2);
break;
case RLO_ret:
tprintf ("RET: ");
a = get_reg (RL78_Reg_SP);
v = mem_get_psi (a | 0xf0000);
WILD_JUMP_CHECK (v);
pc = v;
set_reg (RL78_Reg_SP, a + 4);
#if 0
/* Enable this code to dump the return values for each return. */
if (trace)
{
int i;
skip_init ++;
for (i = 0; i < 8; i ++)
printf (" %02x", mem_get_qi (0xffef0 + i) & 0xff);
skip_init --;
}
#endif
tprintf ("\n");
CLOCKS (6);
break;
case RLO_reti:
tprintf ("RETI: ");
a = get_reg (RL78_Reg_SP);
v = mem_get_psi (a | 0xf0000);
WILD_JUMP_CHECK (v);
pc = v;
b = mem_get_qi ((a + 3) | 0xf0000);
set_reg (RL78_Reg_PSW, b);
set_reg (RL78_Reg_SP, a + 4);
tprintf ("\n");
break;
case RLO_rol:
tprintf ("ROL:"); /* d <<= s */
a = GS ();
b = GD ();
v = b;
while (a --)
{
v = b << 1;
v |= (b >> (obits - 1)) & 1;
set_carry ((b >> (obits - 1)) & 1);
b = v;
}
PD (v);
break;
case RLO_rolc:
tprintf ("ROLC:"); /* d <<= s */
a = GS ();
b = GD ();
v = b;
while (a --)
{
v = b << 1;
v |= get_carry ();
set_carry ((b >> (obits - 1)) & 1);
b = v;
}
PD (v);
break;
case RLO_ror:
tprintf ("ROR:"); /* d >>= s */
a = GS ();
b = GD ();
v = b;
while (a --)
{
v = b >> 1;
v |= (b & 1) << (obits - 1);
set_carry (b & 1);
b = v;
}
PD (v);
break;
case RLO_rorc:
tprintf ("RORC:"); /* d >>= s */
a = GS ();
b = GD ();
v = b;
while (a --)
{
v = b >> 1;
v |= (get_carry () << (obits - 1));
set_carry (b & 1);
b = v;
}
PD (v);
break;
case RLO_sar:
tprintf ("SAR:"); /* d >>= s */
a = GS ();
b = GD ();
v = b;
while (a --)
{
v = b >> 1;
v |= b & (1 << (obits - 1));
set_carry (b & 1);
b = v;
}
PD (v);
break;
case RLO_sel:
tprintf ("SEL:");
a = GS ();
b = get_reg (RL78_Reg_PSW);
b &= ~(RL78_PSW_RBS1 | RL78_PSW_RBS0);
if (a & 1)
b |= RL78_PSW_RBS0;
if (a & 2)
b |= RL78_PSW_RBS1;
set_reg (RL78_Reg_PSW, b);
tprintf ("\n");
break;
case RLO_shl:
tprintf ("SHL%d:", obits); /* d <<= s */
a = GS ();
b = GD ();
v = b;
while (a --)
{
v = b << 1;
tprintf ("b = 0x%x & 0x%x\n", b, 1<<(obits - 1));
set_carry (b & (1<<(obits - 1)));
b = v;
}
PD (v);
break;
case RLO_shr:
tprintf ("SHR:"); /* d >>= s */
a = GS ();
b = GD ();
v = b;
while (a --)
{
v = b >> 1;
set_carry (b & 1);
b = v;
}
PD (v);
break;
case RLO_skip:
tprintf ("SKIP: ");
if (!condition_true (opcode.op[1].condition, GS ()))
{
tprintf (" false\n");
break;
}
rl78_data.dpc = pc;
opcode_size = rl78_decode_opcode (pc, &opcode,
rl78_get_byte, &rl78_data);
pc += opcode_size;
tprintf (" skipped: %s\n", opcode.syntax);
break;
case RLO_stop:
tprintf ("STOP.\n");
DO_RETURN (RL78_MAKE_EXITED (get_reg (RL78_Reg_A)));
DO_RETURN (RL78_MAKE_HIT_BREAK ());
case RLO_sub:
tprintf ("SUB: ");
a = GS ();
b = GD ();
v = b - a;
FLAGS (b, v);
PD (v);
tprintf ("%d (0x%x) - %d (0x%x) = %d (0x%x)\n", b, b, a, a, v, v);
if (opcode.op[0].type == RL78_Operand_Indirect)
CLOCKS (2);
break;
case RLO_subc:
tprintf ("SUBC: ");
a = GS ();
b = GD ();
v = b - a - get_carry ();
FLAGS (b, v);
PD (v);
if (opcode.op[0].type == RL78_Operand_Indirect)
CLOCKS (2);
break;
case RLO_xch:
tprintf ("XCH: ");
a = GS ();
b = GD ();
PD (a);
PS (b);
break;
case RLO_xor:
tprintf ("XOR:");
a = GS ();
b = GD ();
v = a ^ b;
FLAGS (b, v);
PD (v);
if (opcode.op[0].type == RL78_Operand_Indirect)
CLOCKS (2);
break;
default:
tprintf ("Unknown opcode?\n");
DO_RETURN (RL78_MAKE_HIT_BREAK ());
}
if (timer_enabled)
process_clock_tick ();
return RL78_MAKE_STEPPED ();
}

343
sim/rl78/trace.c Normal file
View File

@ -0,0 +1,343 @@
/* trace.c --- tracing output for the RL78 simulator.
Copyright (C) 2005, 2007, 2008, 2009, 2010, 2011
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"
#include "cpu.h"
#include "mem.h"
#include "load.h"
static int
sim_dis_read (bfd_vma memaddr, bfd_byte * ptr, unsigned int length,
struct disassemble_info *info)
{
mem_get_blk (memaddr, ptr, length);
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)
{
register 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;
*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
sim_disasm_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
sim_get_current_source_location (const char ** pfilename,
const char ** pfunctionname,
unsigned int * plineno)
{
static int initted = 0;
int mypc = pc;
if (current_bfd == NULL)
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_rl78;
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
sim_disasm_one (void)
{
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;
int save_trace = trace;
int mypc = pc;
if (! sim_get_current_source_location (& filename, & functionname, & lineno))
return;
trace = 0;
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 ++;
printf
("========================================"
"=====================================\n");
printf ("\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]);
printf ("\033[43;30m%s", bfd_asymbol_name (symtab[min]));
if (bestaddr != mypc)
printf ("+%d", mypc - bestaddr);
printf (":\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
}
#define TCR0 0xf0180
opbuf[0] = 0;
#ifdef CYCLE_ACCURATE
printf ("\033[33m %04u %06x: ", (int)(regs.cycle_count % 10000), mypc);
#else
printf ("\033[33m %08llx %06x: ", total_clocks, mypc);
#endif
max = print_insn_rl78 (mypc, & info);
for (i = 0; i < max; i ++)
printf ("%02x", mem_get_qi (mypc + i));
do
{
printf (" ");
i ++;
}
while (i < 6);
printf ("%-16s ", opbuf);
printf ("\033[0m\n");
trace = save_trace;
}

29
sim/rl78/trace.h Normal file
View File

@ -0,0 +1,29 @@
/* trace.h --- interface to tracing output for the RX simulator.
Copyright (C) 2005, 2007, 2008, 2009, 2010, 2011
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_RL78_TRACE_H_
#define SIM_RL78_TRACE_H_
extern void sim_disasm_init (bfd *);
extern void sim_disasm_one (void);
extern int sim_get_current_source_location (const char **, const char **, unsigned int *);
#endif