Mirror of the gdb-patches mailing list
 help / color / mirror / Atom feed
* [sim] new port: Renesas RL78
@ 2011-11-16  6:07 DJ Delorie
  2011-11-16 19:09 ` Mike Frysinger
                   ` (3 more replies)
  0 siblings, 4 replies; 19+ messages in thread
From: DJ Delorie @ 2011-11-16  6:07 UTC (permalink / raw)
  To: gdb-patches


The Renesas RL78 is a new low-power 8/16 bit microcontroller, with an
architecture much like the original Z80.  However, it has four
register banks and a 1 Mb address space with default 16 bit pointers
and segment registers to access outside the default segments (code:
first 64k, data: last 64k).  The RL78 family is a direct descendant of
the 78K0R and R8C families (78K0R cpu core, R8C peripherals).

The binutils port is already committed, this sim uses the opcode
decoder in libopcodes.

http://www.renesas.com/pr/mcu/rl78/

Target: rl78-elf

Maintainer: I volunteer to be the maintainer for this simulator.

Note: There's a GDB port also, which will be submitted independently
of this.  The GDB interface for the simulator will be included in that
patch.

Note: This simulator reuses a lot of code from the RX simulator.
Hopefully I removed all the RX-specific stuff ;-)

[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 configure.tgt
--- sim/configure.tgt	4 Jun 2011 17:44:20 -0000	1.4
+++ sim/configure.tgt	16 Nov 2011 05:44:53 -0000
@@ -87,10 +87,13 @@ case "${target}" in
        sim_testsuite=yes
        ;;
    rx-*-*)
        SIM_ARCH(rx)
        ;;
+   rl78-*-*)
+       SIM_ARCH(rl78)
+       ;;
    sh64*-*-*)
        SIM_ARCH(sh64)
        sim_testsuite=yes
        ;;
    sh*-*-*)
Index: sim/rl78/Makefile.in
===================================================================
RCS file: sim/rl78/Makefile.in
diff -N sim/rl78/Makefile.in
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ sim/rl78/Makefile.in	16 Nov 2011 05:44:53 -0000
@@ -0,0 +1,56 @@
+#### 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 \
+	$(ENDLIST)
+
+SIM_OBJS = \
+	load.o \
+	mem.o \
+	cpu.o \
+	rl78.o \
+	trace.o \
+	$(ENDLIST)
+
+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
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ sim/rl78/config.in	16 Nov 2011 05:44:53 -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.in
===================================================================
RCS file: sim/rl78/configure.in
diff -N sim/rl78/configure.in
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ sim/rl78/configure.in	16 Nov 2011 05:44:54 -0000
@@ -0,0 +1,33 @@
+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.5)dnl
+AC_INIT(Makefile.in)
+AC_CONFIG_HEADER(config.h:config.in)
+AC_CHECK_HEADERS(getopt.h)
+
+sinclude(../common/aclocal.m4)
+
+# Bugs in autoconf 2.59 break the call to SIM_AC_COMMON, hack around
+# it by inlining the macro's contents.
+sinclude(../common/common.m4)
+
+SIM_AC_OUTPUT
Index: sim/rl78/cpu.c
===================================================================
RCS file: sim/rl78/cpu.c
diff -N sim/rl78/cpu.c
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ sim/rl78/cpu.c	16 Nov 2011 05:44:54 -0000
@@ -0,0 +1,333 @@
+/* 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 <stdlib.h>
+#include <string.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 ();
+    }
+}
+
+char *
+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];
+  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 ()
+{
+  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 ()
+{
+  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
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ sim/rl78/cpu.h	16 Nov 2011 05:44:54 -0000
@@ -0,0 +1,95 @@
+/* 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/>.  */
+
+#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 char *reg_names[];
+
+void init_cpu (void);
+void set_flags (int mask, int newbits);
+void set_c (int c);
+int  get_c ();
+
+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 ();
+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 (char *filename);
+extern unsigned int counts_per_insn[0x100000];
Index: sim/rl78/load.c
===================================================================
RCS file: sim/rl78/load.c
diff -N sim/rl78/load.c
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ sim/rl78/load.c	16 Nov 2011 05:44:54 -0000
@@ -0,0 +1,165 @@
+/* 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 <stdlib.h>
+#include <stdio.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)
+{
+  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, "Failed to get size of program headers\n");
+      return;
+    }
+  phdrs = malloc (sizeof_phdrs);
+  if (phdrs == NULL)
+    {
+      fprintf (stderr, "Failed allocate memory to hold program headers\n");
+      return;
+    }
+  num_headers = bfd_get_elf_phdrs (prog, phdrs);
+  if (num_headers < 1)
+    {
+      fprintf (stderr, "Failed to read program headers\n");
+      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, "Failed to allocate buffer to hold program segment\n");
+	  continue;
+	}
+
+      offset = p->p_offset;
+      if (prog->iovec->bseek (prog, offset, SEEK_SET) != 0)
+	{
+	  fprintf (stderr, "Failed to seek to offset %lx\n", (long) offset);
+	  continue;
+	}
+
+      if (prog->iovec->bread (prog, buf, size) != size)
+	{
+	  fprintf (stderr, "Failed to read %lx bytes\n", size);
+	  continue;
+	}
+
+      if (base > 0xeffff || base + size > 0xeffff)
+	{
+	  fprintf (stderr, "Can't load image to RAM/SFR space: 0x%lx - 0x%lx\n",
+		   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
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ sim/rl78/load.h	16 Nov 2011 05:44:54 -0000
@@ -0,0 +1,25 @@
+/* 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/>.  */
+
+
+#include "bfd.h"
+#include "gdb/callback.h"
+
+void rl78_load (bfd *, host_callback *callbacks);
Index: sim/rl78/main.c
===================================================================
RCS file: sim/rl78/main.c
diff -N sim/rl78/main.c
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ sim/rl78/main.c	16 Nov 2011 05:44:54 -0000
@@ -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>
+#ifdef HAVE_STDLIB_H
+#include <stdlib.h>
+#endif
+#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 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;
+
+  setbuf(stdout, NULL);
+
+  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 = strdup (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);
+  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
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ sim/rl78/mem.c	16 Nov 2011 05:44:54 -0000
@@ -0,0 +1,422 @@
+/* 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 ()
+{
+  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);
+  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
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ sim/rl78/mem.h	16 Nov 2011 05:44:54 -0000
@@ -0,0 +1,50 @@
+/* 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/>.
+*/
+
+#define MEM_SIZE 0x100000
+
+/* Only for cpu.c to use.  */
+extern unsigned char memory[];
+
+void init_mem ();
+
+/* 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);
Index: sim/rl78/rl78.c
===================================================================
RCS file: sim/rl78/rl78.c
diff -N sim/rl78/rl78.c
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ sim/rl78/rl78.c	16 Nov 2011 05:44:54 -0000
@@ -0,0 +1,943 @@
+/* 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;
+
+#define xSTACK_TTY "/dev/pts/1"
+#ifdef STACK_TTY
+static FILE *stack_tty = NULL;
+static void
+init_stack_tty ()
+{
+  stack_tty = fopen (STACK_TTY, "w");
+  if (!stack_tty)
+    {
+      fprintf(stderr, "cannot open %s\n", STACK_TTY);
+      exit(1);
+    }
+  setbuf(stack_tty, NULL);
+  fprintf (stack_tty, "\033[1;1H\033[J");
+}
+#endif
+
+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) \
+  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 ()); \
+    }
+
+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 ()
+{
+  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 ()
+{
+  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 (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 ()
+{
+  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;
+#ifdef STACK_TTY
+      if (!stack_tty)
+	init_stack_tty ();
+      {
+	time_t now;
+	time(&now);
+	struct tm *tm = localtime(&now);
+	fprintf(stack_tty, "%08x %02d:%02d:%02d\n",
+		pc, tm->tm_hour, tm->tm_min, tm->tm_sec);
+      }
+#endif
+#if 0
+      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);
+#ifdef STACK_TTY
+      if (!stack_tty)
+	init_stack_tty ();
+      fprintf(stack_tty, "\033[A\033[K");
+#endif
+#if 0
+      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
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ sim/rl78/trace.c	16 Nov 2011 05:44:54 -0000
@@ -0,0 +1,341 @@
+/* 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
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ sim/rl78/trace.h	16 Nov 2011 05:44:54 -0000
@@ -0,0 +1,24 @@
+/* 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/>.  */
+
+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 *);


^ permalink raw reply	[flat|nested] 19+ messages in thread

* Re: [sim] new port: Renesas RL78
  2011-11-16  6:07 [sim] new port: Renesas RL78 DJ Delorie
@ 2011-11-16 19:09 ` Mike Frysinger
  2011-11-16 19:36   ` DJ Delorie
  2011-11-17 19:16   ` DJ Delorie
  2011-11-28 20:03 ` DJ Delorie
                   ` (2 subsequent siblings)
  3 siblings, 2 replies; 19+ messages in thread
From: Mike Frysinger @ 2011-11-16 19:09 UTC (permalink / raw)
  To: gdb-patches; +Cc: DJ Delorie

[-- Attachment #1: Type: Text/Plain, Size: 8736 bytes --]

On Wednesday 16 November 2011 01:06:30 DJ Delorie wrote:
> Note: This simulator reuses a lot of code from the RX simulator.
> Hopefully I removed all the RX-specific stuff ;-)

i know a lot of the comments below apply to the rx sim too ... oh well ;)

seems like there's a bunch of common/ code this port could utilize ... like 
all the tracing logic ...

> --- /dev/null	1 Jan 1970 00:00:00 -0000
> +++ sim/rl78/Makefile.in	16 Nov 2011 05:44:53 -0000
>
> +SIM_RUN_OBJS = \
> +	main.o \

can't you use nrun.o ?

> +	$(ENDLIST)

this $(ENDLIST) business looks like dead code ?

> +LIBS = $B/bfd/libbfd.a $B/libiberty/libiberty.a

common/Make-common.in already sets up $(BFD_LIB) and $(LIBIBERTY_LIB), and 
adds them to $(LIBDEPS) and $(EXTRA_LIBS), so you shouldn't have to either 
hardcode the reference yourself, or even refer to them at all ...

> +arch = rl78

looks like we should expand configure.tgt:SIM_ARCH to automatically export 
@SIM_ARCH@ to Makefiles, and have the default arch value be @SIM_ARCH@.

> --- /dev/null	1 Jan 1970 00:00:00 -0000
> +++ sim/rl78/configure.in	16 Nov 2011 05:44:54 -0000
>
> +AC_PREREQ(2.5)dnl
> +AC_INIT(Makefile.in)
> +AC_CONFIG_HEADER(config.h:config.in)
> +AC_CHECK_HEADERS(getopt.h)
> +
> +sinclude(../common/aclocal.m4)
> +
> +# Bugs in autoconf 2.59 break the call to SIM_AC_COMMON, hack around
> +# it by inlining the macro's contents.
> +sinclude(../common/common.m4)

this is out of date.  please look at latest rx/configure.ac to see what your 
code should now look like.

> --- /dev/null	1 Jan 1970 00:00:00 -0000
> +++ sim/rl78/cpu.c	16 Nov 2011 05:44:54 -0000
>
> +/* 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/>.  */

shouldn't these lines be indented ?  seems to apply to most of the files in 
this patchset, so i won't comment again ...

> +int verbose = 0;
> +int trace = 0;
> +int rl78_in_gdb = 1;
> +int timer_enabled = 2;

yikes, global variables make me cry

> +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/ ?

> +static void trace_register_init ();

shouldn't that be "(void)" ?

> +char *
> +reg_names[] = {

const char * const reg_names[]

be nice if this weren't global too ...

> +static char *
> +psw_string (int psw)
> +{
> +  static char buf[30];
> +  char *comma = "";

const char *comma

> +  printf("%s", buf);

debug code ?

> +void
> +trace_register_changes ()

(void) ... seems to be a lot in this patchset like this, so i probably missed 
some ... might want to grep ...

> +      printf ("PSW: \033[31m");
> +      psw_string (old_psw);
> +      printf (" \033[32m");

yikes, unavoidable ascii escapes ?

> +static void
> +trace_register_init ()

(void)

> --- /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 ?

> +#include <setjmp.h>

doesn't seem to be used here

> +int  get_c ();

(void)

> --- /dev/null	1 Jan 1970 00:00:00 -0000
> +++ sim/rl78/load.c	16 Nov 2011 05:44:54 -0000
>
> +/* 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);
> +}

this looks like it could be generally useful.  wonder if we should move it to 
common/ and give it a better name like cb_printf().

> +void
> +rl78_load (bfd *prog, host_callback *callbacks)
> +{
> ...
> +  phdrs = malloc (sizeof_phdrs);
> +  if (phdrs == NULL)
> +    {
> +      fprintf (stderr, "Failed allocate memory to hold program
> headers\n"); +      return;
> +    }
> ...
> +      buf = malloc (size);
> +      if (buf == NULL)
> +	{
> +	  fprintf (stderr, "Failed to allocate buffer to hold program
> segment\n"); +	  continue;
> +	}

don't we have xmalloc() ?

> --- /dev/null	1 Jan 1970 00:00:00 -0000
> +++ sim/rl78/load.h	16 Nov 2011 05:44:54 -0000

ifdef's for multiple inclusion ?

> --- /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.  
should probably be consistent ...

> +int
> +main (int argc, char **argv)
> +{
> ...
> +  setbuf(stdout, NULL);

doesn't this hurt performance ?  especially when tracing ?

also, need space before the "("

> +	  dump_counts_filename = strdup (optarg);

does it need to be strdup-ed ?  it's a pointer into argv, so it should be safe 
to use as is ... otherwise, this should be xstrdup().

could also constify dump_counts_filename

> +  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);
> +    }

most sim's output prefix argv[0] in the error message.  otherwise, it can be a 
little confusing where this error message is coming from when looking at 
testsuite logs like gcc.



> --- /dev/null	1 Jan 1970 00:00:00 -0000
> +++ sim/rl78/mem.c	16 Nov 2011 05:44:54 -0000

seems like much of the utility of this file is duplicating the core mappings 
logic in like common/sim-core.c :/

> +void
> +init_mem ()

(void)

> --- /dev/null	1 Jan 1970 00:00:00 -0000
> +++ sim/rl78/mem.h	16 Nov 2011 05:44:54 -0000

ifdef multiple inclusion protection ...

> +void init_mem ();

(void)

> --- /dev/null	1 Jan 1970 00:00:00 -0000
> +++ sim/rl78/rl78.c	16 Nov 2011 05:44:54 -0000
>
> +#define xSTACK_TTY "/dev/pts/1"
> +#ifdef STACK_TTY
> +static FILE *stack_tty = NULL;
> +static void
> +init_stack_tty ()

(void)

> +{
> +  stack_tty = fopen (STACK_TTY, "w");
> +  if (!stack_tty)
> +    {
> +      fprintf(stderr, "cannot open %s\n", STACK_TTY);
> +      exit(1);
> +    }
> +  setbuf(stack_tty, NULL);

need space before the "("

> +  fprintf (stack_tty, "\033[1;1H\033[J");
> +}
> +#endif

in general though, yikes ... looks like this would be better as a command line 
option specifying the output ...

> +#define WILD_JUMP_CHECK(new_pc) \
> +  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 ()); \
> +    }

put this into a do{...}while(0) block to avoid surprises wrt "else" ?

> +static int
> +get_carry ()

(void)

> +void
> +dump_counts_per_insn (char *filename)

const

> +  f = fopen(filename, "w");

needs space before the "("

> +  for (i=0; i<0x100000; i++)

needs spaces around those operators

> +int
> +decode_opcode ()

(void)

> +      tprintf("BRANCH_COND: ");
> +      CLOCKS(3);

space before the "(".  seems to apply to many tprintf's/CLOCK's in this file, 
so i've squashed other comments along these lines.

> +	time(&now);
> +	struct tm *tm = localtime(&now);
> +	fprintf(stack_tty, "%08x %02d:%02d:%02d\n",
> +		pc, tm->tm_hour, tm->tm_min, tm->tm_sec);

needs spaces before the "("

> +#if 0
> +      if (trace)
> +	{
> +	  int i;
> +	  skip_init ++;
> +	  for (i=0; i<8; i++)
> +	    printf(" %02x", mem_get_qi (0xf0000 | (a + i)) & 0xff);
> +	  skip_init --;
> +	}
> +#endif

just delete then ?

> --- /dev/null	1 Jan 1970 00:00:00 -0000
> +++ sim/rl78/trace.h	16 Nov 2011 05:44:54 -0000

ifdef multiple inclusion protection ...
-mike

[-- Attachment #2: This is a digitally signed message part. --]
[-- Type: application/pgp-signature, Size: 836 bytes --]

^ permalink raw reply	[flat|nested] 19+ messages in thread

* Re: [sim] new port: Renesas RL78
  2011-11-16 19:09 ` Mike Frysinger
@ 2011-11-16 19:36   ` DJ Delorie
  2011-11-16 19:47     ` Mike Frysinger
  2011-11-17 19:16   ` DJ Delorie
  1 sibling, 1 reply; 19+ messages in thread
From: DJ Delorie @ 2011-11-16 19:36 UTC (permalink / raw)
  To: Mike Frysinger; +Cc: gdb-patches


Replying only to the things that don't require a code change ("yet"
perhaps):

> > +	$(ENDLIST)
> 
> this $(ENDLIST) business looks like dead code ?

I've been brainwashed to end lists like this so that new lines always
end with a continuation char, which - in ancient and possibly modern
source control systems - prevents two independent additions from
becoming dependent on each other.  It also allows you to sort or
otherwise mess with the list, without worrying about which lines have
continuation characters and which don't.

> > +  printf("%s", buf);
> 
> debug code ?

trace code.

> > +      printf ("PSW: \033[31m");
> > +      psw_string (old_psw);
> > +      printf (" \033[32m");
> 
> yikes, unavoidable ascii escapes ?

Yup.  I'm a big fan of color when I'm sifting through at megabytes of
machine traces.

> > +#include <setjmp.h>
> 
> doesn't seem to be used here

A jmp_buf is declared in that file.

> > +int
> > +main (int argc, char **argv)
> > +{
> > ...
> > +  setbuf(stdout, NULL);
> 
> doesn't this hurt performance ?  especially when tracing ?

Very important when emulating the target serial port, though.  I
suppose I could rework that logic, but so far I've mostly been worried
about "runs correctly" and not "runs fast".

> > --- /dev/null	1 Jan 1970 00:00:00 -0000
> > +++ sim/rl78/mem.c	16 Nov 2011 05:44:54 -0000
> 
> seems like much of the utility of this file is duplicating the core mapping=
> s=20
> logic in like common/sim-core.c :/

It's mostly about emulating memory-mapped hardware and the weird RL78
mapping rules, though.  The common parts are a small part of it.

> > +  fprintf (stack_tty, "\033[1;1H\033[J");
> > +}
> > +#endif
> 
> in general though, yikes ... looks like this would be better as a command l=
> ine=20
> option specifying the output ...

Perhaps.  I'm used to being able to just tweak the sources as needed ;-)

And again, that's probably not code you *want* the average person to
use.  What it does is maintain a LIVE stack trace on a tty while the
sim is running, so you can spot "stuck" patterns.

> > +#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 ?

No, I keep chunks like this around if they're useful for exotic
debugging needs that don't warrant a command line option.  This chunk,
for example, dumps the on-stack arguments to the trace for each CALL
insn.


^ permalink raw reply	[flat|nested] 19+ messages in thread

* Re: [sim] new port: Renesas RL78
  2011-11-16 19:36   ` DJ Delorie
@ 2011-11-16 19:47     ` Mike Frysinger
  2011-11-16 21:45       ` Mike Frysinger
  0 siblings, 1 reply; 19+ messages in thread
From: Mike Frysinger @ 2011-11-16 19:47 UTC (permalink / raw)
  To: DJ Delorie; +Cc: gdb-patches

[-- Attachment #1: Type: Text/Plain, Size: 2225 bytes --]

On Wednesday 16 November 2011 14:36:20 DJ Delorie wrote:
> > > +	$(ENDLIST)
> > 
> > this $(ENDLIST) business looks like dead code ?
> 
> I've been brainwashed to end lists like this so that new lines always
> end with a continuation char, which - in ancient and possibly modern
> source control systems - prevents two independent additions from
> becoming dependent on each other.  It also allows you to sort or
> otherwise mess with the list, without worrying about which lines have
> continuation characters and which don't.

sounds like it should be a standard in the wider binutils/gdb/etc... tree, or 
should be omitted and forgotten about.  all these youngsters don't have a clue 
what "$(ENDLIST)" is for, and heaven forbid someone has ENDLIST exported in 
their env when running `make` ;).

> > > +int
> > > +main (int argc, char **argv)
> > > +{
> > > ...
> > > +  setbuf(stdout, NULL);
> > 
> > doesn't this hurt performance ?  especially when tracing ?
> 
> Very important when emulating the target serial port, though.  I
> suppose I could rework that logic, but so far I've mostly been worried
> about "runs correctly" and not "runs fast".

hmm, personally i've left that up to the host to run `stty` rather than 
mucking about with terminal settings on people.  although that covers input 
and not output.

for output, i have my uart simulator explicitly flush whenever it has data to 
right.  that way general things writing to stdout don't take a penalty, but 
the serial which wants bytes sent immediately still work.

> > > --- /dev/null	1 Jan 1970 00:00:00 -0000
> > > +++ sim/rl78/mem.c	16 Nov 2011 05:44:54 -0000
> > 
> > seems like much of the utility of this file is duplicating the core
> > mapping= s=20
> > logic in like common/sim-core.c :/
> 
> It's mostly about emulating memory-mapped hardware and the weird RL78
> mapping rules, though.  The common parts are a small part of it.

common/ provides frameworks for emulating memory mapped devices :).  the 
Blackfin port uses this heavily so that specific devices are cleanly managed in 
sep files.  see all the fun bfin/dv-* files.

although converting to that is probably non-trivial.
-mike

[-- Attachment #2: This is a digitally signed message part. --]
[-- Type: application/pgp-signature, Size: 836 bytes --]

^ permalink raw reply	[flat|nested] 19+ messages in thread

* Re: [sim] new port: Renesas RL78
  2011-11-16 19:47     ` Mike Frysinger
@ 2011-11-16 21:45       ` Mike Frysinger
  0 siblings, 0 replies; 19+ messages in thread
From: Mike Frysinger @ 2011-11-16 21:45 UTC (permalink / raw)
  To: gdb-patches; +Cc: DJ Delorie

[-- Attachment #1: Type: Text/Plain, Size: 1231 bytes --]

On Wednesday 16 November 2011 14:47:28 Mike Frysinger wrote:
> On Wednesday 16 November 2011 14:36:20 DJ Delorie wrote:
> > > > +int
> > > > +main (int argc, char **argv)
> > > > +{
> > > > ...
> > > > +  setbuf(stdout, NULL);
> > > 
> > > doesn't this hurt performance ?  especially when tracing ?
> > 
> > Very important when emulating the target serial port, though.  I
> > suppose I could rework that logic, but so far I've mostly been worried
> > about "runs correctly" and not "runs fast".
> 
> for output, i have my uart simulator explicitly flush whenever it has data
> to right.  that way general things writing to stdout don't take a penalty,
> but the serial which wants bytes sent immediately still work.

ugh, s/right/write/

in case it's interesting, i'm referring to the file sim/bfin/dv-bfin_uart.c.  in 
there is a bfin_uart_write_buffer() helper which is called two different ways: 
when a buffer is transferred to the device via DMA (so from 
bfin_uart_dma_write_buffer() which is a callback from common device framework), 
or when someone writes the memory-mapped transmit register (so from 
bfin_uart_io_write_buffer() which is a callback from common memory framework).

HTH
-mike

[-- Attachment #2: This is a digitally signed message part. --]
[-- Type: application/pgp-signature, Size: 836 bytes --]

^ permalink raw reply	[flat|nested] 19+ messages in thread

* Re: [sim] new port: Renesas RL78
  2011-11-16 19:09 ` Mike Frysinger
  2011-11-16 19:36   ` DJ Delorie
@ 2011-11-17 19:16   ` DJ Delorie
  2011-11-17 19:39     ` Mike Frysinger
  1 sibling, 1 reply; 19+ messages in thread
From: DJ Delorie @ 2011-11-17 19:16 UTC (permalink / raw)
  To: Mike Frysinger; +Cc: gdb-patches


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


^ permalink raw reply	[flat|nested] 19+ messages in thread

* Re: [sim] new port: Renesas RL78
  2011-11-17 19:16   ` DJ Delorie
@ 2011-11-17 19:39     ` Mike Frysinger
  2011-11-17 19:48       ` DJ Delorie
  0 siblings, 1 reply; 19+ messages in thread
From: Mike Frysinger @ 2011-11-17 19:39 UTC (permalink / raw)
  To: DJ Delorie; +Cc: gdb-patches

[-- Attachment #1: Type: Text/Plain, Size: 776 bytes --]

On Thursday 17 November 2011 14:16:10 DJ Delorie wrote:
> > don't we have xmalloc() ?
> 
> We do, but it exits without telling you why it's exiting, other than
> "out of memory".  Changed anyway.

true, but that's the standard in this tree i think.  although in the patch 
below, seems like you still use malloc() everywhere and there are no xmalloc() 
calls ...

> --- 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.

looks like you've got some breakage here :)
-mike

[-- Attachment #2: This is a digitally signed message part. --]
[-- Type: application/pgp-signature, Size: 836 bytes --]

^ permalink raw reply	[flat|nested] 19+ messages in thread

* Re: [sim] new port: Renesas RL78
  2011-11-17 19:39     ` Mike Frysinger
@ 2011-11-17 19:48       ` DJ Delorie
  2011-11-17 19:53         ` Mike Frysinger
  0 siblings, 1 reply; 19+ messages in thread
From: DJ Delorie @ 2011-11-17 19:48 UTC (permalink / raw)
  To: Mike Frysinger; +Cc: gdb-patches


Oops, forgot to redo the patch after my final edits...

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:42:15 -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:42:15 -0000
@@ -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
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:42:15 -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:42:16 -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
+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
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:42:16 -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:42:16 -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:42:16 -0000
@@ -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);
+}
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:42:16 -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:42:16 -0000
@@ -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);
+}
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:42:16 -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:42:16 -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:42:16 -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:42:17 -0000
@@ -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;
+}
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:42:17 -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


^ permalink raw reply	[flat|nested] 19+ messages in thread

* Re: [sim] new port: Renesas RL78
  2011-11-17 19:48       ` DJ Delorie
@ 2011-11-17 19:53         ` Mike Frysinger
  2011-11-17 21:34           ` DJ Delorie
  0 siblings, 1 reply; 19+ messages in thread
From: Mike Frysinger @ 2011-11-17 19:53 UTC (permalink / raw)
  To: DJ Delorie; +Cc: gdb-patches

[-- Attachment #1: Type: Text/Plain, Size: 395 bytes --]

On Thursday 17 November 2011 14:47:54 DJ Delorie wrote:
> +      for (i=0; i<32; i++)

seems many of the for loops in here need to have spaces added around their 
operators.
	for (i = 0; i < 32; i++)

otherwise, didn't really see anything else from scanning through.  other than 
my overall comment that it'd be nice if this used common/ instead of doing 
everything itself ;).
-mike

[-- Attachment #2: This is a digitally signed message part. --]
[-- Type: application/pgp-signature, Size: 836 bytes --]

^ permalink raw reply	[flat|nested] 19+ messages in thread

* Re: [sim] new port: Renesas RL78
  2011-11-17 19:53         ` Mike Frysinger
@ 2011-11-17 21:34           ` DJ Delorie
  2011-11-17 21:44             ` Mike Frysinger
  0 siblings, 1 reply; 19+ messages in thread
From: DJ Delorie @ 2011-11-17 21:34 UTC (permalink / raw)
  To: Mike Frysinger; +Cc: gdb-patches


I think I got all the spacing issues... assuming I didn't miss a regex
or something.

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 21:31:46 -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 21:31:47 -0000
@@ -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
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 21:31:47 -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 21:31:48 -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
+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
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 21:31:48 -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 21:31:48 -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 21:31:48 -0000
@@ -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);
+}
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 21:31:48 -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 21:31:48 -0000
@@ -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);
+}
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 21:31:48 -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 21:31:48 -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 21:31:48 -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 21:31:48 -0000
@@ -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;
+}
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 21:31:48 -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


^ permalink raw reply	[flat|nested] 19+ messages in thread

* Re: [sim] new port: Renesas RL78
  2011-11-17 21:34           ` DJ Delorie
@ 2011-11-17 21:44             ` Mike Frysinger
  0 siblings, 0 replies; 19+ messages in thread
From: Mike Frysinger @ 2011-11-17 21:44 UTC (permalink / raw)
  To: DJ Delorie; +Cc: gdb-patches

[-- Attachment #1: Type: Text/Plain, Size: 194 bytes --]

On Thursday 17 November 2011 16:33:32 DJ Delorie wrote:
> I think I got all the spacing issues... assuming I didn't miss a regex
> or something.

i've got nothing new to complain about ;)
-mike

[-- Attachment #2: This is a digitally signed message part. --]
[-- Type: application/pgp-signature, Size: 836 bytes --]

^ permalink raw reply	[flat|nested] 19+ messages in thread

* Re: [sim] new port: Renesas RL78
  2011-11-16  6:07 [sim] new port: Renesas RL78 DJ Delorie
  2011-11-16 19:09 ` Mike Frysinger
@ 2011-11-28 20:03 ` DJ Delorie
  2011-11-28 20:13   ` Mike Frysinger
  2011-11-28 21:01   ` Stan Shebs
  2011-11-29  1:38 ` Mike Frysinger
  2012-03-23  4:33 ` Mike Frysinger
  3 siblings, 2 replies; 19+ messages in thread
From: DJ Delorie @ 2011-11-28 20:03 UTC (permalink / raw)
  To: gdb-patches


Ping?

I covered all the comments from Mike, but even if there are no further
comments, I still need a global maintainer to approve it and my offer
of maintainership.

http://sourceware.org/ml/gdb-patches/2011-11/msg00418.html
http://sourceware.org/ml/gdb-patches/2011-11/msg00489.html

Thanks!
DJ


^ permalink raw reply	[flat|nested] 19+ messages in thread

* Re: [sim] new port: Renesas RL78
  2011-11-28 20:03 ` DJ Delorie
@ 2011-11-28 20:13   ` Mike Frysinger
  2011-11-28 21:01   ` Stan Shebs
  1 sibling, 0 replies; 19+ messages in thread
From: Mike Frysinger @ 2011-11-28 20:13 UTC (permalink / raw)
  To: DJ Delorie; +Cc: gdb-patches

On Mon, Nov 28, 2011 at 15:03, DJ Delorie wrote:
> I covered all the comments from Mike, but even if there are no further
> comments, I still need a global maintainer to approve it and my offer
> of maintainership.

i don't think we currently have global sim maintainers, so it'd fall
on the head of the global gdb maintainers
-mike


^ permalink raw reply	[flat|nested] 19+ messages in thread

* Re: [sim] new port: Renesas RL78
  2011-11-28 20:03 ` DJ Delorie
  2011-11-28 20:13   ` Mike Frysinger
@ 2011-11-28 21:01   ` Stan Shebs
  2011-11-28 21:16     ` DJ Delorie
  2011-11-29  3:50     ` DJ Delorie
  1 sibling, 2 replies; 19+ messages in thread
From: Stan Shebs @ 2011-11-28 21:01 UTC (permalink / raw)
  To: gdb-patches

On 11/28/11 12:03 PM, DJ Delorie wrote:
> Ping?
>
> I covered all the comments from Mike, but even if there are no further
> comments, I still need a global maintainer to approve it and my offer
> of maintainership.
>
> http://sourceware.org/ml/gdb-patches/2011-11/msg00418.html
> http://sourceware.org/ml/gdb-patches/2011-11/msg00489.html
>

Let's put it in, and it's all yours. :-)

Stan
stan@codesourcery.com


^ permalink raw reply	[flat|nested] 19+ messages in thread

* Re: [sim] new port: Renesas RL78
  2011-11-28 21:01   ` Stan Shebs
@ 2011-11-28 21:16     ` DJ Delorie
  2011-11-29  3:50     ` DJ Delorie
  1 sibling, 0 replies; 19+ messages in thread
From: DJ Delorie @ 2011-11-28 21:16 UTC (permalink / raw)
  To: Stan Shebs; +Cc: gdb-patches


> Let's put it in, and it's all yours. :-)

Thanks!


^ permalink raw reply	[flat|nested] 19+ messages in thread

* Re: [sim] new port: Renesas RL78
  2011-11-16  6:07 [sim] new port: Renesas RL78 DJ Delorie
  2011-11-16 19:09 ` Mike Frysinger
  2011-11-28 20:03 ` DJ Delorie
@ 2011-11-29  1:38 ` Mike Frysinger
  2012-03-23  4:33 ` Mike Frysinger
  3 siblings, 0 replies; 19+ messages in thread
From: Mike Frysinger @ 2011-11-29  1:38 UTC (permalink / raw)
  To: gdb-patches; +Cc: DJ Delorie

[-- Attachment #1: Type: Text/Plain, Size: 660 bytes --]

On Wednesday 16 November 2011 01:06:30 DJ Delorie wrote:
> The Renesas RL78 is a new low-power 8/16 bit microcontroller, with an
> architecture much like the original Z80.  However, it has four
> register banks and a 1 Mb address space with default 16 bit pointers
> and segment registers to access outside the default segments (code:
> first 64k, data: last 64k).  The RL78 family is a direct descendant of
> the 78K0R and R8C families (78K0R cpu core, R8C peripherals).

might want to add a note to gdb's NEWS file.  it isn't the "best" location for 
sim news, but it's the only place we have atm, and it's what we've done in the 
past ...
-mike

[-- Attachment #2: This is a digitally signed message part. --]
[-- Type: application/pgp-signature, Size: 836 bytes --]

^ permalink raw reply	[flat|nested] 19+ messages in thread

* Re: [sim] new port: Renesas RL78
  2011-11-28 21:01   ` Stan Shebs
  2011-11-28 21:16     ` DJ Delorie
@ 2011-11-29  3:50     ` DJ Delorie
  2011-11-29  4:08       ` Eli Zaretskii
  1 sibling, 1 reply; 19+ messages in thread
From: DJ Delorie @ 2011-11-29  3:50 UTC (permalink / raw)
  To: Stan Shebs; +Cc: gdb-patches


Done!  Patch as per previous email, NEWS diff attached.  Thanks!

Index: gdb/NEWS
===================================================================
RCS file: /cvs/src/src/gdb/NEWS,v
retrieving revision 1.469
diff -p -U5 -r1.469 NEWS
--- gdb/NEWS    20 Nov 2011 23:59:47 -0000      1.469
+++ gdb/NEWS    29 Nov 2011 03:29:03 -0000
@@ -231,10 +231,14 @@ qTMinFTPILen
 
 * New targets
 
 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.
 
 *** Changes in GDB 7.3


^ permalink raw reply	[flat|nested] 19+ messages in thread

* Re: [sim] new port: Renesas RL78
  2011-11-29  3:50     ` DJ Delorie
@ 2011-11-29  4:08       ` Eli Zaretskii
  0 siblings, 0 replies; 19+ messages in thread
From: Eli Zaretskii @ 2011-11-29  4:08 UTC (permalink / raw)
  To: DJ Delorie; +Cc: stanshebs, gdb-patches

> Date: Mon, 28 Nov 2011 22:50:02 -0500
> From: DJ Delorie <dj@redhat.com>
> CC: gdb-patches@sourceware.org
> 
> 
> Done!  Patch as per previous email, NEWS diff attached.  Thanks!
> 
> Index: gdb/NEWS
> ===================================================================
> RCS file: /cvs/src/src/gdb/NEWS,v
> retrieving revision 1.469
> diff -p -U5 -r1.469 NEWS
> --- gdb/NEWS    20 Nov 2011 23:59:47 -0000      1.469
> +++ gdb/NEWS    29 Nov 2011 03:29:03 -0000
> @@ -231,10 +231,14 @@ qTMinFTPILen
>  
>  * New targets
>  
>  Texas Instruments TMS320C6x            tic6x-*-*
>  
> +* New Simulators
> +
> +Renesas RL78                           rl78-*-elf
> +

OK, thanks.


^ permalink raw reply	[flat|nested] 19+ messages in thread

* Re: [sim] new port: Renesas RL78
  2011-11-16  6:07 [sim] new port: Renesas RL78 DJ Delorie
                   ` (2 preceding siblings ...)
  2011-11-29  1:38 ` Mike Frysinger
@ 2012-03-23  4:33 ` Mike Frysinger
  3 siblings, 0 replies; 19+ messages in thread
From: Mike Frysinger @ 2012-03-23  4:33 UTC (permalink / raw)
  To: gdb-patches; +Cc: DJ Delorie

[-- Attachment #1: Type: Text/Plain, Size: 437 bytes --]

On Wednesday 16 November 2011 01:06:30 DJ Delorie wrote:
> [sim]
> 	* configure.tgt: Add rl78 support.
> 	* configure: Regenerate.
> 	* rl78: New directory.

testsuite/configure needs to be regenerated whenever configure.tgt is updated.  
not sure if adding a comment to the top of the file would make that obvious.  
not a big deal obviously if you don't have a testsuite for your target :).

i've regenerated it now.
-mike

[-- Attachment #2: This is a digitally signed message part. --]
[-- Type: application/pgp-signature, Size: 836 bytes --]

^ permalink raw reply	[flat|nested] 19+ messages in thread

end of thread, other threads:[~2012-03-23  4:33 UTC | newest]

Thread overview: 19+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2011-11-16  6:07 [sim] new port: Renesas RL78 DJ Delorie
2011-11-16 19:09 ` Mike Frysinger
2011-11-16 19:36   ` DJ Delorie
2011-11-16 19:47     ` Mike Frysinger
2011-11-16 21:45       ` Mike Frysinger
2011-11-17 19:16   ` DJ Delorie
2011-11-17 19:39     ` Mike Frysinger
2011-11-17 19:48       ` DJ Delorie
2011-11-17 19:53         ` Mike Frysinger
2011-11-17 21:34           ` DJ Delorie
2011-11-17 21:44             ` Mike Frysinger
2011-11-28 20:03 ` DJ Delorie
2011-11-28 20:13   ` Mike Frysinger
2011-11-28 21:01   ` Stan Shebs
2011-11-28 21:16     ` DJ Delorie
2011-11-29  3:50     ` DJ Delorie
2011-11-29  4:08       ` Eli Zaretskii
2011-11-29  1:38 ` Mike Frysinger
2012-03-23  4:33 ` Mike Frysinger

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox