This is the mail archive of the gdb-patches@sourceware.org mailing list for the GDB project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

Re: [sim] new port: Renesas RL78


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


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]