This is the mail archive of the
gdb-patches@sourceware.org
mailing list for the GDB project.
Re: [sim] new port: Renesas RL78
Comments inlined and new patch attached.
> can't you use nrun.o ?
In theory, I could switch to the common runtime, but it's not worth it
for such a tiny file, which has all the rl78-specific options in it
anyway.
> > + $(ENDLIST)
>
> this $(ENDLIST) business looks like dead code ?
Deleted.
> > +LIBS =3D $B/bfd/libbfd.a $B/libiberty/libiberty.a
>
> common/Make-common.in already sets up $(BFD_LIB) and $(LIBIBERTY_LIB), and=
Deleted.
> > +++ sim/rl78/configure.in 16 Nov 2011 05:44:54 -0000
>
> this is out of date. please look at latest rx/configure.ac to see what
Fixed.
> > +You should have received a copy of the GNU General Public License
> > +along with this program. If not, see <http://www.gnu.org/licenses/>. */
>
> shouldn't these lines be indented ?
Done.
> > +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;
>
> do we allow CamelCase in sim/ ?
Apparently, yes.
> > +static void trace_register_init ();
>
> shouldn't that be "(void)" ?
Fixed throughout.
> > +char *
> > +reg_names[] =3D {
>
> const char * const reg_names[]
Fixed.
> const char *comma
Fixed.
> > +void
> > +trace_register_changes ()
>
> (void) ... seems to be a lot in this patchset like this, so i
> probably miss ed some ... might want to grep ...
Grepped and fixed.
> > --- /dev/null 1 Jan 1970 00:00:00 -0000
> > +++ sim/rl78/cpu.h 16 Nov 2011 05:44:54 -0000
>
> should this header have ifdef protection against multiple inclusion ?
Fixed throughout.
> don't we have xmalloc() ?
We do, but it exits without telling you why it's exiting, other than
"out of memory". Changed anyway.
> > --- /dev/null 1 Jan 1970 00:00:00 -0000
> > +++ sim/rl78/main.c 16 Nov 2011 05:44:54 -0000
> >
> > +#ifdef HAVE_STDLIB_H
> > +#include <stdlib.h>
> > +#endif
>
> other places in this patchset you've included stdlib.h unconditionally. =20
> should probably be consistent ...
I took those out. stdlib.h is ancient ANSI C, we already depend on
newer stuff anyway.
> > + setbuf(stdout, NULL);
>
> doesn't this hurt performance ? especially when tracing ?
Moved to an fflush in mem.c
> > + dump_counts_filename =3D strdup (optarg);
>
> does it need to be strdup-ed ?
strdup removed.
> could also constify dump_counts_filename
Done.
> > + if (!bfd_check_format (prog, bfd_object))
> > + {
> > + fprintf (stderr, "%s not a rl78 program\n", argv[optind]);
> > + exit (1);
> > + }
>
> most sim's output prefix argv[0] in the error message.
Done.
> > +#ifdef STACK_TTY
>
> in general though, yikes ...
I just took that out. I can re-add it later if I need that particular
bit of functionality.
> put this into a do{...}while(0) block to avoid surprises wrt "else" ?
Done.
> > +void
> > +dump_counts_per_insn (char *filename)
>
> const
Done.
> > + for (i=3D0; i<0x100000; i++)
>
> needs spaces around those operators
Done.
> > +#if 0
> > + if (trace)
> > + {
> > + int i;
> > + skip_init ++;
> > + for (i=3D0; i<8; i++)
> > + printf(" %02x", mem_get_qi (0xf0000 | (a + i)) & 0xff);
> > + skip_init --;
> > + }
> > +#endif
>
> just delete then ?
I commented within them explaining what they were for.
[sim]
* configure.tgt: Add rl78 support.
* configure: Regenerate.
* rl78: New directory.
Index: sim/configure.tgt
===================================================================
RCS file: /cvs/src/src/sim/configure.tgt,v
retrieving revision 1.4
diff -p -U5 -r1.4 sim/configure.tgt
--- sim/configure.tgt 4 Jun 2011 17:44:20 -0000 1.4
+++ sim/configure.tgt 17 Nov 2011 19:03:41 -0000
@@ -84,10 +84,13 @@ case "${target}" in
;;
moxie-*-*)
SIM_ARCH(moxie)
sim_testsuite=yes
;;
+ rl78-*-*)
+ SIM_ARCH(rl78)
+ ;;
rx-*-*)
SIM_ARCH(rx)
;;
sh64*-*-*)
SIM_ARCH(sh64)
Index: sim/rl78/Makefile.in
===================================================================
RCS file: sim/rl78/Makefile.in
diff -N sim/rl78/Makefile.in
--- sim/rl78/Makefile.in 1 Jan 1970 00:00:00 -0000
+++ sim/rl78/Makefile.in 17 Nov 2011 19:03:42 -0000
@@ -0,0 +1,54 @@
+#### 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
+
+LIBS = $B/bfd/libbfd.a $B/libiberty/libiberty.a
+
+## 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
Index: sim/rl78/config.in
===================================================================
RCS file: sim/rl78/config.in
diff -N sim/rl78/config.in
--- sim/rl78/config.in 1 Jan 1970 00:00:00 -0000
+++ sim/rl78/config.in 17 Nov 2011 19:03:42 -0000
@@ -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
Index: sim/rl78/configure.ac
===================================================================
RCS file: sim/rl78/configure.ac
diff -N sim/rl78/configure.ac
--- sim/rl78/configure.ac 1 Jan 1970 00:00:00 -0000
+++ sim/rl78/configure.ac 17 Nov 2011 19:03:42 -0000
@@ -0,0 +1,30 @@
+dnl Process this file with autoconf to produce a configure script.
+
+dnl Copyright (C) 2005, 2007, 2008, 2009, 2010, 2011
+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
Index: sim/rl78/cpu.c
===================================================================
RCS file: sim/rl78/cpu.c
diff -N sim/rl78/cpu.c
--- sim/rl78/cpu.c 1 Jan 1970 00:00:00 -0000
+++ sim/rl78/cpu.c 17 Nov 2011 19:03:42 -0000
@@ -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);
+}
Index: sim/rl78/cpu.h
===================================================================
RCS file: sim/rl78/cpu.h
diff -N sim/rl78/cpu.h
--- sim/rl78/cpu.h 1 Jan 1970 00:00:00 -0000
+++ sim/rl78/cpu.h 17 Nov 2011 19:03:42 -0000
@@ -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
Index: sim/rl78/load.c
===================================================================
RCS file: sim/rl78/load.c
diff -N sim/rl78/load.c
--- sim/rl78/load.c 1 Jan 1970 00:00:00 -0000
+++ sim/rl78/load.c 17 Nov 2011 19:03:42 -0000
@@ -0,0 +1,166 @@
+/* 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 "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 = malloc (sizeof_phdrs);
+ if (phdrs == NULL)
+ {
+ fprintf (stderr, "%s: Failed allocate memory to hold program headers\n", simname);
+ return;
+ }
+ 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 = malloc (size);
+ if (buf == NULL)
+ {
+ fprintf (stderr, "%s: Failed to allocate buffer to hold program segment\n", simname);
+ continue;
+ }
+
+ 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);
+}
Index: sim/rl78/load.h
===================================================================
RCS file: sim/rl78/load.h
diff -N sim/rl78/load.h
--- sim/rl78/load.h 1 Jan 1970 00:00:00 -0000
+++ sim/rl78/load.h 17 Nov 2011 19:03:42 -0000
@@ -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
Index: sim/rl78/main.c
===================================================================
RCS file: sim/rl78/main.c
diff -N sim/rl78/main.c
--- sim/rl78/main.c 1 Jan 1970 00:00:00 -0000
+++ sim/rl78/main.c 17 Nov 2011 19:03:42 -0000
@@ -0,0 +1,166 @@
+/* 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 "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;
+
+ 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);
+}
Index: sim/rl78/mem.c
===================================================================
RCS file: sim/rl78/mem.c
diff -N sim/rl78/mem.c
--- sim/rl78/mem.c 1 Jan 1970 00:00:00 -0000
+++ sim/rl78/mem.c 17 Nov 2011 19:03:42 -0000
@@ -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;
+}
Index: sim/rl78/mem.h
===================================================================
RCS file: sim/rl78/mem.h
diff -N sim/rl78/mem.h
--- sim/rl78/mem.h 1 Jan 1970 00:00:00 -0000
+++ sim/rl78/mem.h 17 Nov 2011 19:03:42 -0000
@@ -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
Index: sim/rl78/rl78.c
===================================================================
RCS file: sim/rl78/rl78.c
diff -N sim/rl78/rl78.c
--- sim/rl78/rl78.c 1 Jan 1970 00:00:00 -0000
+++ sim/rl78/rl78.c 17 Nov 2011 19:03:42 -0000
@@ -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 ();
+}
Index: sim/rl78/trace.c
===================================================================
RCS file: sim/rl78/trace.c
diff -N sim/rl78/trace.c
--- sim/rl78/trace.c 1 Jan 1970 00:00:00 -0000
+++ sim/rl78/trace.c 17 Nov 2011 19:03:42 -0000
@@ -0,0 +1,342 @@
+/* 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 "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 *) malloc (sizeof (Files));
+ f->next = files;
+ files = f;
+ f->filename = strdup (filename);
+ f->data = (char *) malloc (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 **) malloc (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 **) malloc (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;
+}
Index: sim/rl78/trace.h
===================================================================
RCS file: sim/rl78/trace.h
diff -N sim/rl78/trace.h
--- sim/rl78/trace.h 1 Jan 1970 00:00:00 -0000
+++ sim/rl78/trace.h 17 Nov 2011 19:03:42 -0000
@@ -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