Mirror of the gdb-patches mailing list
 help / color / mirror / Atom feed
* RFA: contribute Renesas M32C sim
@ 2005-10-07 20:46 Jim Blandy
  2005-10-07 21:03 ` Daniel Jacobowitz
                   ` (2 more replies)
  0 siblings, 3 replies; 14+ messages in thread
From: Jim Blandy @ 2005-10-07 20:46 UTC (permalink / raw)
  To: gdb-patches


DJ Delorie is the target maintainer for the M32C, so the rules in
sim/MAINTAINERS make him the maintainer of this sim by default.

sim/ChangeLog:
2005-10-06  Jim Blandy  <jimb@redhat.com>
	
	Add simulator for Renesas M32C and M16C.
	
	* m32c: New directory.
	* configure.ac: Add entry for Renesas M32C.
	* configure: Regenerate.

sim/m32c/ChangeLog:
2005-10-06  Jim Blandy  <jimb@redhat.com>

	Simulator for Renesas M32C and M16C, by DJ Delorie <dj@redhat.com>,
	with further work from Jim Blandy <jimb@redhat.com> and
	Kevin Buettner <kevinb@redhat.com>.
	
	* ChangeLog: New.
	* Makefile.in: New.
	* blinky.S: New.
	* config.in: New.
	* configure: New.
	* configure.in: New.
	* cpu.h: New.
	* gdb-if.c: New.
	* gloss.S: New.
	* int.c: New.
	* int.h: New.
	* load.c: New.
	* load.h: New.
	* m32c.opc: New.
	* main.c: New.
	* mem.c: New.
	* mem.h: New.
	* misc.c: New.
	* misc.h: New.
	* opc2c.c: New.
	* r8c.opc: New.
	* reg.c: New.
	* run-m32c.cc: New.
	* safe-fgets.c: New.
	* safe-fgets.h: New.
	* sample.S: New.
	* sample.ld: New.
	* sample2.c: New.
	* srcdest.c: New.
	* syscalls.c: New.
	* syscalls.h: New.
	* trace.c: New.
	* trace.h: New.

Index: sim/configure.ac
===================================================================
RCS file: /cvs/src/src/sim/configure.ac,v
retrieving revision 1.7
diff -c -p -r1.7 configure.ac
*** sim/configure.ac	17 May 2005 14:11:24 -0000	1.7
--- sim/configure.ac	6 Oct 2005 22:36:51 -0000
*************** if test "${enable_sim}" != no; then
*** 73,78 ****
--- 73,82 ----
  	   testsuite=yes
  	   common=yes
  	   ;;
+        m32c-*-*)
+            AC_CONFIG_SUBDIRS(m32c)
+            common=yes
+            ;;
         m32r-*-*)
             AC_CONFIG_SUBDIRS(m32r)
  	   testsuite=yes
Index: sim/m32c/Makefile.in
===================================================================
RCS file: sim/m32c/Makefile.in
diff -N sim/m32c/Makefile.in
*** sim/m32c/Makefile.in	1 Jan 1970 00:00:00 -0000
--- sim/m32c/Makefile.in	6 Oct 2005 22:36:51 -0000
***************
*** 0 ****
--- 1,72 ----
+ 
+ ## COMMON_PRE_CONFIG_FRAG
+ 
+ SIM_EXTRA_CFLAGS = -Wall
+ 
+ SIM_RUN_OBJS = \
+ 	main.o \
+ 	$(ENDLIST)
+ 
+ SIM_OBJS = \
+ 	gdb-if.o \
+ 	int.o \
+ 	load.o \
+ 	mem.o \
+ 	misc.o \
+ 	reg.o \
+ 	r8c.o \
+ 	m32c.o \
+ 	srcdest.o \
+ 	syscalls.o \
+ 	trace.o \
+ 	$(ENDLIST)
+ 
+ # SIM_EXTRA_ALL = sample.x sample2.x
+ 
+ LIBS = $B/bfd/libbfd.a $B/libiberty/libiberty.a
+ 
+ ## COMMON_POST_CONFIG_FRAG
+ 
+ arch = m32c
+ 
+ r8c.c : r8c.opc opc2c
+ 	./opc2c -l r8c.out $(srcdir)/r8c.opc > r8c.c
+ 
+ m32c.c : m32c.opc opc2c
+ 	./opc2c -l m32c.out $(srcdir)/m32c.opc > m32c.c
+ 
+ opc2c : opc2c.o safe-fgets.o
+ 	$(CC) $(CFLAGS) $(LDFLAGS) $^ -o $@
+ 
+ sample.x : $(srcdir)/sample.S $(srcdir)/sample.ld
+ 	../../gcc/xgcc $(CPUFLAGS) -B../../gcc/ -c $(srcdir)/sample.S -o sample.o
+ 	../../ld/ld-new sample.o -o sample.x -T$(srcdir)/sample.ld
+ 
+ sample.mot : sample.x
+ 	../../binutils/objcopy --srec-forceS3 -O srec sample.x sample.mot
+ 
+ sample2.x : sample2.o gloss.o $(srcdir)/sample.ld
+ 	../../ld/ld-new sample2.o gloss.o -o sample2.x -T$(srcdir)/sample.ld
+ 
+ sample2.o : $(srcdir)/sample2.c
+ 	../../gcc/xgcc $(CPUFLAGS) -B../../gcc/ -c $(srcdir)/sample2.c -o sample2.o
+ 
+ gloss.o : $(srcdir)/gloss.S
+ 	../../gcc/xgcc $(CPUFLAGS) -B../../gcc/ -c $(srcdir)/gloss.S -o gloss.o
+ 
+ encodings:
+ 	grep '/\* [01]' $(srcdir)/r8c.opc | sort
+ 
+ gdb-if.o : cpu.h mem.h load.h syscalls.h
+ int.o : int.h cpu.h mem.h
+ load.o : load.h cpu.h mem.h
+ main.o : cpu.h mem.h misc.h load.h
+ mem.o : mem.h cpu.h syscalls.h
+ misc.o : cpu.h misc.h
+ opc2c.o : safe-fgets.h
+ reg.o : cpu.h
+ safe-fgets.o : safe-fgets.h
+ srcdest.c : cpu.h mem.h
+ syscalls.c : cpu.h mem.h syscalls.h
+ 
+ r8c.o : cpu.h mem.h misc.h int.h
Index: sim/m32c/blinky.S
===================================================================
RCS file: sim/m32c/blinky.S
diff -N sim/m32c/blinky.S
*** sim/m32c/blinky.S	1 Jan 1970 00:00:00 -0000
--- sim/m32c/blinky.S	6 Oct 2005 22:36:51 -0000
***************
*** 0 ****
--- 1,14 ----
+ 	.text
+ 
+ 	.global _start
+ _start:
+ 	mov.w	#0xe1,a0
+ top:
+ 	sub.w	#1,r0
+ 	mov.b	r0h,[a0]
+ 
+ 	mov.w	#1000,r1
+ loop:
+ 	adjnz.w	#-1,r1,loop
+ 
+ 	jmp.w	top
Index: sim/m32c/config.in
===================================================================
RCS file: sim/m32c/config.in
diff -N sim/m32c/config.in
Index: sim/m32c/configure.in
===================================================================
RCS file: sim/m32c/configure.in
diff -N sim/m32c/configure.in
*** sim/m32c/configure.in	1 Jan 1970 00:00:00 -0000
--- sim/m32c/configure.in	6 Oct 2005 22:36:52 -0000
***************
*** 0 ****
--- 1,12 ----
+ dnl Process this file with autoconf to produce a configure script.
+ AC_PREREQ(2.5)dnl
+ AC_INIT(Makefile.in)
+ AC_CONFIG_HEADER(config.h:config.in)
+ 
+ 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/m32c/cpu.h
===================================================================
RCS file: sim/m32c/cpu.h
diff -N sim/m32c/cpu.h
*** sim/m32c/cpu.h	1 Jan 1970 00:00:00 -0000
--- sim/m32c/cpu.h	6 Oct 2005 22:36:52 -0000
***************
*** 0 ****
--- 1,196 ----
+ extern int verbose;
+ extern int trace;
+ extern int enable_counting;
+ 
+ typedef unsigned char QI;
+ typedef unsigned short HI;
+ typedef unsigned long SI;
+ typedef unsigned long long DI;
+ 
+ #define CPU_R8C		0x11
+ #define CPU_M16C	0x12
+ #define CPU_M32CM	0x23
+ #define CPU_M32C	0x24
+ extern int m32c_cpu;
+ void m32c_set_cpu (int cpu);
+ 
+ #define A16 (m32c_cpu & 0x10)
+ #define A24 (m32c_cpu & 0x20)
+ 
+ typedef struct {
+   HI r_r0;
+   HI r_r2;
+   HI r_r1;
+   HI r_r3;
+   SI r_a0;
+   SI r_a1;
+   SI r_sb;
+   SI r_fb;
+ } reg_bank_type;
+ 
+ typedef struct {
+   reg_bank_type r[2];
+   QI r_intbh;
+   HI r_intbl;
+   SI r_usp;
+   SI r_isp;
+   SI r_pc;
+   HI r_flags;
+ } regs_type;
+ 
+ extern regs_type regs;
+ extern int addr_mask;
+ extern int membus_mask;
+ 
+ #define FLAGBIT_C	0x0001
+ #define FLAGBIT_D	0x0002
+ #define FLAGBIT_Z	0x0004
+ #define FLAGBIT_S	0x0008
+ #define FLAGBIT_B	0x0010
+ #define FLAGBIT_O	0x0020
+ #define FLAGBIT_I	0x0040
+ #define FLAGBIT_U	0x0080
+ 
+ #define REG_BANK (regs.r_flags & FLAG_B ? 1 : 0)
+ 
+ typedef enum {
+   mem,
+   r0, r0h, r0l,
+   r1, r1h, r1l,
+   r2, r2r0,
+   r3, r3r1,
+   r3r1r2r0,
+   r3r2r1r0,
+   a0,
+   a1, a1a0,
+   sb, fb,
+   intb, intbl, intbh,
+   sp, usp, isp, pc, flags,
+   num_regs
+ } reg_id;
+ 
+ extern char *reg_names[];
+ extern int reg_bytes[];
+ 
+ extern unsigned int b2mask[];
+ extern unsigned int b2signbit[];
+ extern int b2maxsigned[];
+ extern int b2minsigned[];
+ 
+ void init_regs (void);
+ void stack_heap_stats (void);
+ void set_pointer_width (int bytes);
+ unsigned int get_reg (reg_id id);
+ DI get_reg_ll (reg_id id);
+ void put_reg (reg_id id, unsigned int value);
+ void put_reg_ll (reg_id id, DI value);
+ 
+ void set_flags (int mask, int newbits);
+ void set_oszc (int value, int bytes, int c);
+ void set_szc (int value, int bytes, int c);
+ void set_osz (int value, int bytes);
+ void set_sz (int value, int bytes);
+ void set_zc (int z, int c);
+ void set_c (int c);
+ 
+ const char *bits(int v, int b);
+ 
+ typedef struct {
+   QI bytes;
+   QI mem;
+   HI mask;
+   union {
+     unsigned int addr;
+     reg_id reg;
+   } u;
+ } srcdest;
+ 
+ void    decode_indirect (int src_indirect, int dest_indirect);
+ void    decode_index (int src_addend, int dest_addend);
+ 
+ /* r8c */
+ srcdest decode_srcdest4 (int destcode, int bw);
+ srcdest decode_dest3 (int destcode, int bw);
+ srcdest decode_src2 (int srccode, int bw, int d);
+ srcdest decode_dest1 (int destcode, int bw);
+ srcdest decode_jumpdest (int destcode, int w);
+ srcdest decode_cr (int crcode);
+ srcdest decode_cr_b (int crcode, int bank);
+ #define CR_B_DCT0	0
+ #define CR_B_INTB	1
+ #define CR_B_DMA0	2
+ 
+ /* m32c */
+ srcdest decode_dest23 (int ddd, int dd, int bytes);
+ srcdest decode_src23 (int sss, int ss, int bytes);
+ srcdest decode_src3 (int sss, int bytes);
+ srcdest decode_dest2 (int dd, int bytes);
+ 
+ srcdest widen_sd (srcdest sd);
+ srcdest reg_sd (reg_id reg);
+ 
+ /* Mask has the one appropriate bit set.  */
+ srcdest decode_bit (int destcode);
+ srcdest decode_bit11 (int op0);
+ int get_bit (srcdest sd);
+ void put_bit (srcdest sd, int val);
+ int get_bit2 (srcdest sd, int bit);
+ void put_bit2 (srcdest sd, int bit, int val);
+ 
+ int get_src (srcdest sd);
+ void put_dest (srcdest sd, int value);
+ 
+ int condition_true (int cond_id);
+ 
+ #define FLAG(f) (regs.r_flags & f ? 1 : 0)
+ #define FLAG_C	FLAG(FLAGBIT_C)
+ #define FLAG_D	FLAG(FLAGBIT_D)
+ #define FLAG_Z	FLAG(FLAGBIT_Z)
+ #define FLAG_S	FLAG(FLAGBIT_S)
+ #define FLAG_B	FLAG(FLAGBIT_B)
+ #define FLAG_O	FLAG(FLAGBIT_O)
+ #define FLAG_I	FLAG(FLAGBIT_I)
+ #define FLAG_U	FLAG(FLAGBIT_U)
+ 
+ /* Instruction step return codes.
+    Suppose one of the decode_* functions below returns a value R:
+    - If M32C_STEPPED (R), then the single-step completed normally.
+    - If M32C_HIT_BREAK (R), then the program hit a breakpoint.
+    - If M32C_EXITED (R), then the program has done an 'exit' system
+      call, and the exit code is M32C_EXIT_STATUS (R).
+    - If M32C_STOPPED (R), then a signal (number M32C_STOP_SIG (R)) was
+      generated.
+ 
+    For building step return codes:
+    - M32C_MAKE_STEPPED is the return code for finishing a normal step.
+    - M32C_MAKE_HIT_BREAK is the return code for hitting a breakpoint.
+    - M32C_MAKE_EXITED (C) is the return code for exiting with status C.
+    - M32C_MAKE_STOPPED (S) is the return code for stopping on signal S.  */
+ #define M32C_MAKE_STEPPED()   (0)
+ #define M32C_MAKE_HIT_BREAK() (1)
+ #define M32C_MAKE_EXITED(c)   (((int) (c) << 8) + 2)
+ #define M32C_MAKE_STOPPED(s)  (((int) (s) << 8) + 3)
+ 
+ #define M32C_STEPPED(r)       ((r) == M32C_MAKE_STEPPED ())
+ #define M32C_HIT_BREAK(r)     ((r) == M32C_MAKE_HIT_BREAK ())
+ #define M32C_EXITED(r)        (((r) & 0xff) == 2)
+ #define M32C_EXIT_STATUS(r)   ((r) >> 8)
+ #define M32C_STOPPED(r)       (((r) & 0xff) == 3)
+ #define M32C_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;
+ 
+ /* Used to detect heap/stack collisions */
+ extern unsigned int heaptop;
+ extern unsigned int heapbottom;
+ 
+ /* Points to one of the below functions, set by m32c_load().  */
+ extern int (*decode_opcode)();
+ 
+ extern int decode_r8c();
+ extern int decode_m32c();
+ 
+ extern void trace_register_changes ();
Index: sim/m32c/gdb-if.c
===================================================================
RCS file: sim/m32c/gdb-if.c
diff -N sim/m32c/gdb-if.c
*** sim/m32c/gdb-if.c	1 Jan 1970 00:00:00 -0000
--- sim/m32c/gdb-if.c	6 Oct 2005 22:36:52 -0000
***************
*** 0 ****
--- 1,611 ----
+ /* gdb.c --- sim interface to GDB.  */
+ 
+ #include <stdio.h>
+ #include <assert.h>
+ #include <signal.h>
+ #include <string.h>
+ #include <ctype.h>
+ 
+ #include "ansidecl.h"
+ #include "gdb/callback.h"
+ #include "gdb/remote-sim.h"
+ #include "gdb/signals.h"
+ #include "gdb/sim-m32c.h"
+ 
+ #include "cpu.h"
+ #include "mem.h"
+ #include "load.h"
+ #include "syscalls.h"
+ 
+ /* I don't want to wrap up all the minisim's data structures in an
+    object and pass that around.  That'd be a big change, and neither
+    GDB nor run needs that ability.
+ 
+    So we just have one instance, that lives in global variables, and
+    each time we open it, we re-initialize it.  */
+ struct sim_state
+ {
+   const char *message;
+ };
+ 
+ static struct sim_state the_minisim = {
+   "This is the sole m32c minisim instance.  See libsim.a's global variables."
+ };
+ 
+ static int open;
+ 
+ SIM_DESC 
+ sim_open (SIM_OPEN_KIND kind,
+ 	  struct host_callback_struct *callback,
+ 	  struct bfd *abfd,
+ 	  char **argv)
+ {
+   if (open)
+     fprintf (stderr, "m32c minisim: re-opened sim\n");
+ 
+   /* The 'run' interface doesn't use this function, so we don't care
+      about KIND; it's always SIM_OPEN_DEBUG.  */
+   if (kind != SIM_OPEN_DEBUG)
+     fprintf (stderr, "m32c minisim: sim_open KIND != SIM_OPEN_DEBUG: %d\n",
+ 	     kind);
+ 
+   if (abfd)
+     m32c_set_mach (bfd_get_mach (abfd));
+ 
+   /* We can use ABFD, if non-NULL to select the appropriate
+      architecture.  But we only support the r8c right now.  */
+ 
+   set_callbacks (callback);
+ 
+   /* We don't expect any command-line arguments.  */
+ 
+   init_mem ();
+   init_regs ();
+ 
+   open = 1;
+   return &the_minisim;
+ }
+ 
+ static void
+ check_desc (SIM_DESC sd)
+ {
+   if (sd != &the_minisim)
+     fprintf (stderr, "m32c minisim: desc != &the_minisim\n");
+ }
+ 
+ void
+ sim_close (SIM_DESC sd, int quitting)
+ {
+   check_desc (sd);
+ 
+   /* Not much to do.  At least free up our memory.  */
+   init_mem ();
+   
+   open = 0;
+ }
+ 
+ static bfd *
+ open_objfile (const char *filename)
+ {
+   bfd *prog = bfd_openr (filename, 0);
+ 
+   if (! prog)
+     {
+       fprintf (stderr, "Can't read %s\n", filename);
+       return 0;
+     }
+ 
+   if (! bfd_check_format (prog, bfd_object))
+     {
+       fprintf (stderr, "%s not a m32c program\n", filename);
+       return 0;
+     }
+ 
+   return prog;
+ }
+ 
+ 
+ SIM_RC
+ sim_load (SIM_DESC sd, char *prog, struct bfd *abfd, int from_tty)
+ {
+   check_desc (sd);
+ 
+   if (! abfd)
+     abfd = open_objfile (prog);
+   if (! abfd)
+     return SIM_RC_FAIL;
+ 
+   m32c_load (abfd);
+ 
+   return SIM_RC_OK;
+ }
+ 
+ SIM_RC
+ sim_create_inferior (SIM_DESC sd, struct bfd *abfd, char **argv, char **env)
+ {
+   check_desc (sd);
+ 
+   if (abfd)
+     m32c_load (abfd);
+ 
+   return SIM_RC_OK;
+ }
+ 
+ int
+ sim_read (SIM_DESC sd, SIM_ADDR mem, unsigned char *buf, int length)
+ {
+   check_desc (sd);
+ 
+   if (mem == 0)
+     return 0;
+ 
+   mem_get_blk ((int) mem, buf, length);
+ 
+   return length;
+ }
+ 
+ int
+ sim_write (SIM_DESC sd, SIM_ADDR mem, unsigned char *buf, int length)
+ {
+   check_desc (sd);
+ 
+   mem_put_blk ((int) mem, buf, length);
+ 
+   return length;
+ }
+ 
+ 
+ /* Read the LENGTH bytes at BUF as an little-endian value.  */
+ static DI
+ get_le (unsigned char *buf, int length)
+ {
+   DI acc = 0;
+   while (--length >= 0)
+     acc = (acc << 8) + buf[length];
+ 
+   return acc;
+ }
+ 
+ /* Store VAL as a little-endian value in the LENGTH bytes at BUF.  */
+ static void
+ put_le (unsigned char *buf, int length, DI val)
+ {
+   int i;
+ 
+   for (i = 0; i < length; i++)
+     {
+       buf[i] = val & 0xff;
+       val >>= 8;
+     }
+ }
+ 
+ static int
+ check_regno (enum m32c_sim_reg regno)
+ {
+   return 0 <= regno && regno < m32c_sim_reg_num_regs;
+ }
+ 
+ static size_t
+ mask_size (int addr_mask)
+ {
+   switch (addr_mask)
+     {
+     case 0xffff:
+       return 2;
+     case 0xfffff:
+     case 0xffffff:
+       return 3;
+     default:
+       fprintf (stderr,
+ 	       "m32c minisim: addr_mask_size: unexpected mask 0x%x\n",
+ 	       addr_mask);
+       return sizeof (addr_mask);
+     }
+ }
+ 
+ static size_t
+ reg_size (enum m32c_sim_reg regno)
+ {
+   switch (regno)
+     {
+     case m32c_sim_reg_r0_bank0:		
+     case m32c_sim_reg_r1_bank0:		
+     case m32c_sim_reg_r2_bank0:		
+     case m32c_sim_reg_r3_bank0:		
+     case m32c_sim_reg_r0_bank1:
+     case m32c_sim_reg_r1_bank1:
+     case m32c_sim_reg_r2_bank1:
+     case m32c_sim_reg_r3_bank1:
+     case m32c_sim_reg_flg:
+     case m32c_sim_reg_svf:
+       return 2;
+ 
+     case m32c_sim_reg_a0_bank0:         
+     case m32c_sim_reg_a1_bank0:		
+     case m32c_sim_reg_fb_bank0:		
+     case m32c_sim_reg_sb_bank0:		
+     case m32c_sim_reg_a0_bank1:
+     case m32c_sim_reg_a1_bank1:
+     case m32c_sim_reg_fb_bank1:
+     case m32c_sim_reg_sb_bank1:
+     case m32c_sim_reg_usp:
+     case m32c_sim_reg_isp:
+       return mask_size (addr_mask);
+ 
+     case m32c_sim_reg_pc:
+     case m32c_sim_reg_intb:
+     case m32c_sim_reg_svp:
+     case m32c_sim_reg_vct:
+       return mask_size (membus_mask);
+ 
+     case m32c_sim_reg_dmd0:
+     case m32c_sim_reg_dmd1:
+       return 1;
+ 
+     case m32c_sim_reg_dct0:
+     case m32c_sim_reg_dct1:
+     case m32c_sim_reg_drc0:
+     case m32c_sim_reg_drc1:
+       return 2;
+ 
+     case m32c_sim_reg_dma0:
+     case m32c_sim_reg_dma1:
+     case m32c_sim_reg_dsa0:
+     case m32c_sim_reg_dsa1:
+     case m32c_sim_reg_dra0:
+     case m32c_sim_reg_dra1:
+       return 3;
+ 
+     default:
+       fprintf (stderr, "m32c minisim: unrecognized register number: %d\n",
+ 	       regno);
+       return -1;
+     }
+ }
+ 
+ int
+ sim_fetch_register (SIM_DESC sd, int regno, unsigned char *buf, int length)
+ {
+   size_t size;
+ 
+   check_desc (sd);
+ 
+   if (! check_regno (regno))
+     return 0;
+ 
+   size = reg_size (regno);
+   if (length == size)
+     {
+       DI val;
+ 
+       switch (regno)
+ 	{
+ 	case m32c_sim_reg_r0_bank0: val = regs.r[0].r_r0; break;
+ 	case m32c_sim_reg_r1_bank0: val = regs.r[0].r_r1; break;
+ 	case m32c_sim_reg_r2_bank0: val = regs.r[0].r_r2; break;
+ 	case m32c_sim_reg_r3_bank0: val = regs.r[0].r_r3; break;
+ 	case m32c_sim_reg_a0_bank0: val = regs.r[0].r_a0; break;
+ 	case m32c_sim_reg_a1_bank0: val = regs.r[0].r_a1; break;
+ 	case m32c_sim_reg_fb_bank0: val = regs.r[0].r_fb; break;
+ 	case m32c_sim_reg_sb_bank0: val = regs.r[0].r_sb; break;
+ 	case m32c_sim_reg_r0_bank1: val = regs.r[1].r_r0; break;
+ 	case m32c_sim_reg_r1_bank1: val = regs.r[1].r_r1; break;
+ 	case m32c_sim_reg_r2_bank1: val = regs.r[1].r_r2; break;
+ 	case m32c_sim_reg_r3_bank1: val = regs.r[1].r_r3; break;
+ 	case m32c_sim_reg_a0_bank1: val = regs.r[1].r_a0; break;
+ 	case m32c_sim_reg_a1_bank1: val = regs.r[1].r_a1; break;
+ 	case m32c_sim_reg_fb_bank1: val = regs.r[1].r_fb; break;
+ 	case m32c_sim_reg_sb_bank1: val = regs.r[1].r_sb; break;
+ 
+ 	case m32c_sim_reg_usp: 	    val = regs.r_usp;	  break;
+ 	case m32c_sim_reg_isp: 	    val = regs.r_isp;	  break;
+ 	case m32c_sim_reg_pc:  	    val = regs.r_pc; 	  break;
+ 	case m32c_sim_reg_intb:
+ 	  val = regs.r_intbl * 65536 + regs.r_intbl;      break;
+ 	case m32c_sim_reg_flg:      val = regs.r_flags;   break;
+ 
+ 	  /* These registers aren't implemented by the minisim.  */
+ 	case m32c_sim_reg_svf:
+ 	case m32c_sim_reg_svp:
+ 	case m32c_sim_reg_vct:
+ 	case m32c_sim_reg_dmd0:
+ 	case m32c_sim_reg_dmd1:
+ 	case m32c_sim_reg_dct0:
+ 	case m32c_sim_reg_dct1:
+ 	case m32c_sim_reg_drc0:
+ 	case m32c_sim_reg_drc1:
+ 	case m32c_sim_reg_dma0:
+ 	case m32c_sim_reg_dma1:
+ 	case m32c_sim_reg_dsa0:
+ 	case m32c_sim_reg_dsa1:
+ 	case m32c_sim_reg_dra0:
+ 	case m32c_sim_reg_dra1:
+ 	  return 0;
+ 
+ 	default:
+ 	  fprintf (stderr, "m32c minisim: unrecognized register number: %d\n",
+ 		   regno);
+ 	  return -1;
+ 	}
+ 
+       put_le (buf, length, val);
+     }
+ 
+   return size;
+ }
+ 
+ int
+ sim_store_register (SIM_DESC sd, int regno, unsigned char *buf, int length)
+ {
+   size_t size;
+ 
+   check_desc (sd);
+ 
+   if (! check_regno (regno))
+     return 0;
+ 
+   size = reg_size (regno);
+ 
+   if (length == size)
+     {
+       DI val = get_le (buf, length);
+ 
+       switch (regno)
+ 	{
+ 	case m32c_sim_reg_r0_bank0: regs.r[0].r_r0 = val & 0xffff;    	break;
+ 	case m32c_sim_reg_r1_bank0: regs.r[0].r_r1 = val & 0xffff;    	break;
+ 	case m32c_sim_reg_r2_bank0: regs.r[0].r_r2 = val & 0xffff;    	break;
+ 	case m32c_sim_reg_r3_bank0: regs.r[0].r_r3 = val & 0xffff;    	break;
+ 	case m32c_sim_reg_a0_bank0: regs.r[0].r_a0 = val & addr_mask; 	break;
+ 	case m32c_sim_reg_a1_bank0: regs.r[0].r_a1 = val & addr_mask; 	break;
+ 	case m32c_sim_reg_fb_bank0: regs.r[0].r_fb = val & addr_mask; 	break;
+ 	case m32c_sim_reg_sb_bank0: regs.r[0].r_sb = val & addr_mask; 	break;
+ 	case m32c_sim_reg_r0_bank1: regs.r[1].r_r0 = val & 0xffff;    	break;
+ 	case m32c_sim_reg_r1_bank1: regs.r[1].r_r1 = val & 0xffff;    	break;
+ 	case m32c_sim_reg_r2_bank1: regs.r[1].r_r2 = val & 0xffff;    	break;
+ 	case m32c_sim_reg_r3_bank1: regs.r[1].r_r3 = val & 0xffff;    	break;
+ 	case m32c_sim_reg_a0_bank1: regs.r[1].r_a0 = val & addr_mask; 	break;
+ 	case m32c_sim_reg_a1_bank1: regs.r[1].r_a1 = val & addr_mask; 	break;
+ 	case m32c_sim_reg_fb_bank1: regs.r[1].r_fb = val & addr_mask; 	break;
+ 	case m32c_sim_reg_sb_bank1: regs.r[1].r_sb = val & addr_mask; 	break;
+ 
+ 	case m32c_sim_reg_usp: 	    regs.r_usp     = val & addr_mask; 	break;
+ 	case m32c_sim_reg_isp: 	    regs.r_isp     = val & addr_mask; 	break;
+ 	case m32c_sim_reg_pc:  	    regs.r_pc      = val & membus_mask; break;
+ 	case m32c_sim_reg_intb:
+ 	  regs.r_intbl = (val & membus_mask) & 0xffff;
+ 	  regs.r_intbh = (val & membus_mask) >> 16;
+ 	  break;
+ 	case m32c_sim_reg_flg:      regs.r_flags   = val & 0xffff;      break;
+ 
+ 	  /* These registers aren't implemented by the minisim.  */
+ 	case m32c_sim_reg_svf:
+ 	case m32c_sim_reg_svp:
+ 	case m32c_sim_reg_vct:
+ 	case m32c_sim_reg_dmd0:
+ 	case m32c_sim_reg_dmd1:
+ 	case m32c_sim_reg_dct0:
+ 	case m32c_sim_reg_dct1:
+ 	case m32c_sim_reg_drc0:
+ 	case m32c_sim_reg_drc1:
+ 	case m32c_sim_reg_dma0:
+ 	case m32c_sim_reg_dma1:
+ 	case m32c_sim_reg_dsa0:
+ 	case m32c_sim_reg_dsa1:
+ 	case m32c_sim_reg_dra0:
+ 	case m32c_sim_reg_dra1:
+ 	  return 0;
+ 
+ 	default:
+ 	  fprintf (stderr, "m32c minisim: unrecognized register number: %d\n",
+ 		   regno);
+ 	  return -1;
+ 	}
+     }
+ 
+   return size;
+ }
+ 
+ void
+ sim_info (SIM_DESC sd, int verbose)
+ {
+   check_desc (sd);
+ 
+   printf ("The m32c minisim doesn't collect any statistics.\n");
+ }
+ 
+ static volatile int stop;
+ static enum sim_stop reason;
+ int siggnal;
+ 
+ 
+ /* Given a signal number used by the M32C bsp (that is, newlib),
+    return a host signal number.  (Oddly, the gdb/sim interface uses
+    host signal numbers...)  */
+ int
+ m32c_signal_to_host (int m32c)
+ {
+   switch (m32c)
+     {
+     case 4:
+ #ifdef SIGILL
+       return SIGILL;
+ #else
+       return SIGSEGV;
+ #endif
+ 
+     case 5:
+       return SIGTRAP;
+ 
+     case 10:
+ #ifdef SIGBUS
+       return SIGBUS;
+ #else
+       return SIGSEGV;
+ #endif
+ 
+     case 11: 
+       return SIGSEGV;
+ 
+     case 24:
+ #ifdef SIGXCPU
+       return SIGXCPU;
+ #else
+       break;
+ #endif
+ 
+     case 2:
+       return SIGINT;
+ 
+     case 8:
+ #ifdef SIGFPE
+       return SIGFPE;
+ #else
+       break;
+ #endif
+ 
+     case 6:
+       return SIGABRT;
+     }
+ 
+   return 0;
+ }
+ 
+ 
+ /* Take a step return code RC and set up the variables consulted by
+    sim_stop_reason appropriately.  */
+ void
+ handle_step (int rc)
+ {
+   if (M32C_STEPPED (rc)
+       || M32C_HIT_BREAK (rc))
+     {
+       reason = sim_stopped;
+       siggnal = TARGET_SIGNAL_TRAP;
+     }
+   else if (M32C_STOPPED (rc))
+     {
+       reason = sim_stopped;
+       siggnal = m32c_signal_to_host (M32C_STOP_SIG (rc));
+     }
+   else
+     {
+       assert (M32C_EXITED (rc));
+       reason = sim_exited;
+       siggnal = M32C_EXIT_STATUS (rc);
+     }
+ }
+ 
+ 
+ void
+ sim_resume (SIM_DESC sd, int step, int sig_to_deliver)
+ {
+   check_desc (sd);
+ 
+   if (sig_to_deliver != 0)
+     {
+       fprintf (stderr, 
+ 	       "Warning: the m32c minisim does not implement "
+ 	       "signal delivery yet.\n"
+ 	       "Resuming with no signal.\n");
+     }
+ 
+   if (step)
+     handle_step (decode_opcode ());
+   else
+     {
+       /* We don't clear 'stop' here, because then we would miss
+ 	 interrupts that arrived on the way here.  Instead, we clear
+ 	 the flag in sim_stop_reason, after GDB has disabled the
+ 	 interrupt signal handler.  */
+       for (;;)
+ 	{
+ 	  if (stop)
+ 	    {
+ 	      stop = 0;
+ 	      reason = sim_stopped;
+ 	      siggnal = TARGET_SIGNAL_INT;
+ 	      break;
+ 	    }
+ 
+ 	  int rc = decode_opcode ();
+ 
+ 	  if (! M32C_STEPPED (rc))
+ 	    {
+ 	      handle_step (rc);
+ 	      break;
+ 	    }
+ 	}
+     }
+ }
+ 
+ int
+ sim_stop (SIM_DESC sd)
+ {
+   stop = 1;
+ 
+   return 1;
+ }
+ 
+ void
+ sim_stop_reason (SIM_DESC sd, enum sim_stop *reason_p, int *sigrc_p)
+ {
+   check_desc (sd);
+ 
+   *reason_p = reason;
+   *sigrc_p = siggnal;
+ }
+ 
+ void
+ sim_do_command (SIM_DESC sd, char *cmd)
+ {
+   check_desc (sd);
+ 
+   char *p = cmd;
+ 
+   /* Skip leading whitespace.  */
+   while (isspace (*p))
+     p++;
+ 
+   /* Find the extent of the command word.  */
+   for (p = cmd; *p; p++)
+     if (isspace (*p))
+       break;
+ 
+   /* Null-terminate the command word, and record the start of any
+      further arguments.  */
+   char *args;
+   if (*p)
+     {
+       *p = '\0';
+       args = p + 1;
+       while (isspace (*args))
+ 	args++;
+     }
+   else
+     args = p;
+ 
+   if (strcmp (cmd, "trace") == 0)
+     {
+       if (strcmp (args, "on") == 0)
+ 	trace = 1;
+       else if (strcmp (args, "off") == 0)
+ 	trace = 0;
+       else
+ 	printf ("The 'sim trace' command expects 'on' or 'off' "
+ 		"as an argument.\n");
+     }
+   else if (strcmp (cmd, "verbose") == 0)
+     {
+       if (strcmp (args, "on") == 0)
+ 	verbose = 1;
+       else if (strcmp (args, "off") == 0)
+ 	verbose = 0;
+       else
+ 	printf ("The 'sim verbose' command expects 'on' or 'off'"
+ 		" as an argument.\n");
+     }
+   else
+     printf ("The 'sim' command expects either 'trace' or 'verbose'"
+ 	    " as a subcommand.\n");
+ }
Index: sim/m32c/gloss.S
===================================================================
RCS file: sim/m32c/gloss.S
diff -N sim/m32c/gloss.S
*** sim/m32c/gloss.S	1 Jan 1970 00:00:00 -0000
--- sim/m32c/gloss.S	6 Oct 2005 22:36:52 -0000
***************
*** 0 ****
--- 1,11 ----
+ 	.global	_exit
+ _exit:
+ 	mov.b	#1,r0l
+ 	ste.b	r0l,0xe0000
+ 	rts
+ 
+ 	.global	_foo
+ _foo:
+ 	mov.b	#2,r0l
+ 	ste.b	r0l,0xe0000
+ 	rts
Index: sim/m32c/int.c
===================================================================
RCS file: sim/m32c/int.c
diff -N sim/m32c/int.c
*** sim/m32c/int.c	1 Jan 1970 00:00:00 -0000
--- sim/m32c/int.c	6 Oct 2005 22:36:52 -0000
***************
*** 0 ****
--- 1,36 ----
+ #include "int.h"
+ #include "cpu.h"
+ #include "mem.h"
+ 
+ void
+ trigger_fixed_interrupt (int addr)
+ {
+   int s = get_reg (sp);
+   int f = get_reg (flags);
+   int p = get_reg (pc);
+ 
+   if (A16)
+     {
+       s -= 4;
+       put_reg (sp, s);
+       mem_put_hi (s, p);
+       mem_put_qi (s+2, f);
+       mem_put_qi (s+3, ((f >> 4) & 0x0f) | (p >> 16));
+     } else {
+       s -= 6;
+       put_reg (sp, s);
+       mem_put_si (s, p);
+       mem_put_hi (s+4, f);
+     }
+   put_reg (pc, mem_get_psi (addr));
+   set_flags (FLAGBIT_U | FLAGBIT_I | FLAGBIT_D, 0);
+ }
+ 
+ void
+ trigger_based_interrupt (int vector)
+ {
+   int addr = get_reg (intb) + vector * 4;
+   if (vector <= 31)
+     set_flags (FLAGBIT_U, 0);
+   trigger_fixed_interrupt (addr);
+ }
Index: sim/m32c/int.h
===================================================================
RCS file: sim/m32c/int.h
diff -N sim/m32c/int.h
*** sim/m32c/int.h	1 Jan 1970 00:00:00 -0000
--- sim/m32c/int.h	6 Oct 2005 22:36:52 -0000
***************
*** 0 ****
--- 1,2 ----
+ extern void trigger_fixed_interrupt (int addr);
+ extern void trigger_based_interrupt (int vector);
Index: sim/m32c/load.c
===================================================================
RCS file: sim/m32c/load.c
diff -N sim/m32c/load.c
*** sim/m32c/load.c	1 Jan 1970 00:00:00 -0000
--- sim/m32c/load.c	6 Oct 2005 22:36:52 -0000
***************
*** 0 ****
--- 1,107 ----
+ #include <stdlib.h>
+ #include <stdio.h>
+ #include <string.h>
+ 
+ #include "bfd.h"
+ 
+ #include "cpu.h"
+ #include "mem.h"
+ 
+ int (*decode_opcode)() = 0;
+ int default_machine = 0;
+ 
+ void
+ m32c_set_mach (unsigned long mach)
+ {
+   switch (mach)
+     {
+     case bfd_mach_m16c:
+       m32c_set_cpu (CPU_M16C);
+       if (verbose)
+ 	fprintf (stderr, "[cpu: r8c/m16c]\n");
+       break;
+     case bfd_mach_m32c:
+       m32c_set_cpu (CPU_M32C);
+       if (verbose)
+ 	fprintf (stderr, "[cpu: m32cm/m32c]\n");
+       break;
+     default:
+       fprintf (stderr, "unknown m32c machine type 0x%lx\n", mach);
+       decode_opcode = 0;
+       break;
+     }
+ }
+ 
+ void
+ m32c_load (bfd *prog)
+ {
+   asection *s;
+   unsigned long mach = bfd_get_mach (prog);
+   unsigned long highest_addr_loaded = 0;
+ 
+   if (mach == 0 && default_machine != 0)
+     mach = default_machine;
+ 
+   m32c_set_mach (mach);
+ 
+   for (s = prog->sections; s; s = s->next) 
+     {
+ #if 0
+       /* This was a good idea until we started storing the RAM data in
+ 	 ROM, at which point everything was all messed up.  The code
+ 	 remains as a reminder.  */
+       if ((s->flags & SEC_ALLOC) && !(s->flags & SEC_READONLY))
+ 	{
+ 	  if (strcmp (bfd_get_section_name (prog, s), ".stack"))
+ 	    {
+ 	      int secend = bfd_get_section_size (s) + bfd_section_lma (prog, s);
+ 	      if (heaptop < secend && bfd_section_lma (prog, s) < 0x10000)
+ 		{
+ 		  heaptop = heapbottom = secend;
+ 		}
+ 	    }
+ 	}
+ #endif
+       if (s->flags & SEC_LOAD)
+ 	{
+ 	  char *buf;
+ 	  bfd_size_type size;
+ 
+ 	  size = bfd_get_section_size (s);
+ 	  if (size <= 0)
+ 	    continue;
+ 
+ 	  bfd_vma base = bfd_section_lma (prog, s);
+ 	  if (verbose)
+ 	    fprintf(stderr, "[load a=%08x s=%08x %s]\n",
+ 		    (int)base, (int)size, bfd_get_section_name (prog, s));
+ 	  buf = (char *) malloc (size);
+ 	  bfd_get_section_contents (prog, s, buf, 0, size);
+ 	  mem_put_blk (base, buf, size);
+ 	  free (buf);
+ 	  if (highest_addr_loaded < base + size - 1 && size >= 4)
+ 	    highest_addr_loaded = base + size - 1;
+ 	}
+     }
+ 
+   if (strcmp (bfd_get_target (prog), "srec") == 0)
+     {
+       heaptop = heapbottom = 0;
+       switch (mach)
+ 	{
+ 	case bfd_mach_m16c:
+ 	  if (highest_addr_loaded > 0x10000)
+ 	    regs.r_pc = mem_get_si (0x000ffffc) & membus_mask;
+ 	  else
+ 	    regs.r_pc = mem_get_si (0x000fffc) & membus_mask;
+ 	  break;
+ 	case bfd_mach_m32c:
+ 	  regs.r_pc = mem_get_si (0x00fffffc) & membus_mask;
+ 	  break;
+ 	}
+     }
+   else
+     regs.r_pc = prog->start_address;
+   if (verbose)
+     fprintf(stderr, "[start pc=%08x]\n", (unsigned int)regs.r_pc);
+ }
Index: sim/m32c/load.h
===================================================================
RCS file: sim/m32c/load.h
diff -N sim/m32c/load.h
*** sim/m32c/load.h	1 Jan 1970 00:00:00 -0000
--- sim/m32c/load.h	6 Oct 2005 22:36:52 -0000
***************
*** 0 ****
--- 1,6 ----
+ #include "bfd.h"
+ 
+ extern int default_machine;
+ 
+ void m32c_set_mach (int mach);
+ void m32c_load (bfd *);
Index: sim/m32c/m32c.opc
===================================================================
RCS file: sim/m32c/m32c.opc
diff -N sim/m32c/m32c.opc
*** sim/m32c/m32c.opc	1 Jan 1970 00:00:00 -0000
--- sim/m32c/m32c.opc	6 Oct 2005 22:36:52 -0000
***************
*** 0 ****
--- 1,2072 ----
+ #include <stdio.h>		/* -*- mode: c -*- */
+ #include <stdlib.h>
+ 
+ #include "cpu.h"
+ #include "mem.h"
+ #include "misc.h"
+ #include "int.h"
+ 
+ #define AU  __attribute__((unused))
+ 
+ #define tprintf if (trace) printf
+ 
+ static unsigned char
+ getbyte ()
+ {
+   int tsave = trace;
+   unsigned char b;
+ 
+   if (trace == 1)
+     trace = 0;
+   b = mem_get_pc ();
+   regs.r_pc ++;
+   trace = tsave;
+   return b;
+ }
+ 
+ #define M32C_ONLY() /* FIXME: add something here */
+ 
+ #define GETBYTE() (op[opi++] = getbyte())
+ 
+ #define UNSUPPORTED() unsupported("unsupported", orig_pc)
+ #define NOTYET() unsupported("unimplemented", orig_pc)
+ 
+ static void
+ unsupported (char *tag, int orig_pc)
+ {
+   int i;
+   printf("%s opcode at %08x\n", tag, orig_pc);
+   regs.r_pc = orig_pc;
+   for (i=0; i<2; i++)
+     {
+       int b = mem_get_pc();
+       printf(" %s", bits(b>>4, 4));
+       printf(" %s", bits(b, 4));
+       regs.r_pc ++;
+     }
+   printf("\n");
+   regs.r_pc = orig_pc;
+   for (i=0; i<6; i++)
+     {
+       printf(" %02x", mem_get_pc ());
+       regs.r_pc ++;
+     }
+   printf("\n");
+   exit(1);
+ }
+ 
+ static int
+ IMM(int bytes)
+ {
+   int rv = 0;
+   switch (bytes)
+     {
+     case 1:
+       rv = mem_get_qi (get_reg(pc));
+       break;
+     case 2:
+       rv = mem_get_hi (get_reg(pc));
+       break;
+     case 3:
+       rv = mem_get_psi (get_reg(pc));
+       break;
+     case 4:
+       rv = mem_get_si (get_reg(pc));
+       break;
+     }
+   regs.r_pc += bytes;
+   return rv;
+ }
+ 
+ #define IMM4() (immm >= 8 ? 7 - immm : immm + 1)
+ 
+ #define NO_PREFIX() PREFIX(0,0,0)
+ 
+ void
+ prefix (src_allowed, dest_allowed, index_bytewidth)
+ {
+ }
+ 
+ #define MATH_OP(dc,s,c,op) \
+ { \
+   int ma, mb; \
+   ma = get_src(dc); \
+   mb = s & b2mask[dc.bytes]; \
+   ll = (long long)ma op (long long)mb op c; \
+   tprintf("0x%x " #op " 0x%x " #op " 0x%x = 0x%llx\n", ma, mb, c, ll); \
+   ma = sign_ext (ma, dc.bytes * 8); \
+   mb = sign_ext (s, dc.bytes * 8); \
+   v = ma op mb op c; \
+   tprintf("%d " #op " %d " #op " %d = %d\n", ma, mb, c, v); \
+   set_oszc (v, dc.bytes, ll > ((1 op 1) ? b2mask[dc.bytes] : 0)); \
+   put_dest (dc, v); \
+ }
+ 
+ #define LOGIC_OP(dc,s,op) \
+ { \
+   int ma, mb; \
+   ma = get_src(dc); \
+   mb = s & b2mask[dc.bytes]; \
+   v = ma op mb; \
+   tprintf("0x%x " #op " 0x%x = 0x%x\n", ma, mb, v); \
+   set_sz (v, dc.bytes); \
+   put_dest (dc, v); \
+ }
+ 
+ #define BIT_OP(dc,bit,expr) \
+   b = get_bit2 (dc, bitindex == -1 ? bit : bitindex); \
+   v = expr; \
+   tprintf ("b=%d, bit=%d, carry=%d, %s = %d\n", b,  bitindex == -1 ? bit : bitindex, carry, #expr, v); \
+   put_bit2 (dc,  bitindex == -1 ? bit : bitindex, v);
+ 
+ #define BIT_OPC(dc,bit,expr) \
+   b = get_bit2 (dc,  bitindex == -1 ? bit : bitindex); \
+   v = expr; \
+   tprintf ("b=%d, bit=%d, carry=%d, %s = %d\n", b,  bitindex == -1 ? bit : bitindex, carry, #expr, v); \
+   set_c (v);
+ 
+ #define carry (FLAG_C ? 1 : 0)
+ 
+ static void
+ cmp (int d, int s, int bytes)
+ {
+   int a, b, f=0;
+   a = d - s;
+   b = sign_ext (d, bytes*8) - sign_ext (s, bytes*8);
+   tprintf ("cmp: %x - %x = %08x, %x - %x = %d\n",
+ 	   d, s, a,
+ 	   sign_ext(d,bytes*8), sign_ext(s,bytes*8), b);
+ 
+   if (b == 0)
+     f |= FLAGBIT_Z;
+   if (b & b2signbit[bytes])
+     f |= FLAGBIT_S;
+   if ((d & b2mask[bytes]) >= (s & b2mask[bytes]))
+     f |= FLAGBIT_C;
+   if (b < b2minsigned[bytes] || b > b2maxsigned[bytes])
+     f |= FLAGBIT_O;
+ 
+   set_flags (FLAGBIT_Z | FLAGBIT_S | FLAGBIT_O | FLAGBIT_C, f);
+ }
+ 
+ static void
+ dadd_op (int ddd, int dd, int sss, int ss, int imm, int add, int cy, int w)
+ {
+   srcdest sc, dc;
+   int a, b=0, res;
+ 
+   prefix (0, 0, 0);
+ 
+   if (!imm)
+     {
+       sc = decode_src23 (sss, ss, w+1);
+       b = get_src (sc);
+     }
+   dc = decode_dest23 (ddd, dd, w+1);
+   a = get_src (dc);
+   if (imm)
+     b = IMM(w+1);
+ 
+   a = bcd2int(a, w);
+   b = bcd2int(b, w);
+ 
+   tprintf("decimal: %d %s %d", a, add?"+":"-", b);
+   if (cy)
+     tprintf(" c=%d", carry);
+ 
+   if (add)
+     {
+       res = a + b;
+       if (cy)
+ 	res += carry;
+       cy = res > (w ? 9999 : 99);
+     }
+   else
+     {
+       res = a - b;
+       if (cy)
+ 	res -= (1-carry);
+       cy = res >= 0;
+       if (res < 0)
+ 	res += w ? 10000 : 100;
+     }
+ 
+   res = int2bcd (res, w);
+   tprintf(" = %x\n", res);
+ 
+   set_szc (res, w+1, cy);
+ 
+   put_dest (dc, res);
+ }
+ #define DADDV(A,C) dadd_op(ddd, dd, sss, ss, 0, A, C, w)
+ #define DADDI(A,C) dadd_op(ddd, dd, 0, 0, 1, A, C, w)
+ 
+ static void
+ div_op (int sss, int ss, int u, int x, int bytes)
+ {
+   srcdest sc;
+   int s, v, a, b;
+ 
+   if (sss == -1)
+     s = IMM(bytes);
+   else
+     {
+       sc = decode_dest23 (sss, ss, bytes);
+       s = get_src (sc);
+     }
+ 
+   v = get_reg (bytes > 1 ? r2r0 : r0);
+ 
+   if (!u)
+     {
+       /* FIXME? do we sign extend a0/a1 to .L?  Docs say zero extend.  */
+       s = sign_ext (s, bytes*8);
+       v = sign_ext (v, bytes*8);
+     }
+ 
+   if (s == 0)
+     {
+       set_flags (FLAGBIT_O, FLAGBIT_O);
+       return;
+     }
+ 
+   if (u)
+     {
+       a = (unsigned int)v / (unsigned int)s;
+       b = (unsigned int)v % (unsigned int)s;
+     }
+   else
+     {
+       a = v / s;
+       b = v % s;
+     }
+   if (x)
+     {
+       if ((s > 0 && b < 0)
+ 	  || (s < 0 && b > 0))
+ 	{
+ 	  a --;
+ 	  b += s;
+ 	}
+     }
+   tprintf ("%d / %d = %d rem %d\n", v, s, a, b);
+   if ((!u && (a > b2maxsigned[bytes]
+ 	      || a < b2minsigned[bytes]))
+       || (u && (a > b2mask[bytes])))
+     set_flags (FLAGBIT_O, FLAGBIT_O);
+   else
+     set_flags (FLAGBIT_O, 0);
+ 
+   switch (bytes)
+     {
+     case 1:
+       put_reg (r0l, a);
+       put_reg (r0h, b);
+       break;
+     case 2:
+       put_reg (r0, a);
+       put_reg (r2, b);
+       break;
+     case 4:
+       put_reg (r2r0, a);
+       break;
+     }
+ }
+ 
+ static void
+ index_op (int sss, int ss, int do_s, int do_d, int scale, int w)
+ {
+   srcdest sc = decode_src23 (sss, ss, w+1);
+   int v = get_src (sc) * scale;
+   tprintf("%d = %d * %d, %d %d\n", v, get_src(sc), scale, do_s, do_d);
+   decode_index (do_s * v, do_d * v);
+ }
+ #define INDEXOP(scale,do_s,do_d) index_op (sss, ss, do_s, do_d, scale, w); goto next_opcode
+ 
+ static void
+ rot_op (srcdest sd, int rotc, int count)
+ {
+   int mask = (sd.bytes == 2) ? 0xffff : 0xff;
+   int msb = (sd.bytes == 2) ? 0x8000 : 0x80;
+   int v = get_src (sd);
+   int c = carry, ct;
+ 
+   tprintf("%s %x by %d\n", rotc ? "rotc" : "rot", v, count);
+   tprintf (": %s %d\n", bits(v, 8*sd.bytes), c);
+   while (count > 0)
+     {
+       ct = (v & msb) ? 1 : 0;
+       v <<= 1;
+       v |= rotc ? c : ct;
+       v &= mask;
+       c = ct;
+       tprintf (": %s %d\n", bits(v, 8*sd.bytes), c);
+       count --;
+     }
+   while (count < 0)
+     {
+       ct = v & 1;
+       v >>= 1;
+       v |= (rotc ? c : ct) * msb;
+       c = ct;
+       tprintf (": %s %d\n", bits(v, 8*sd.bytes), c);
+       count ++;
+     }
+   put_dest (sd, v);
+   set_szc (v, sd.bytes, c);
+ }
+ 
+ static void
+ shift_op (srcdest sd, int arith, int count, int setc)
+ {
+   int mask = (sd.bytes == 2) ? 0xffff : 0xff;
+   int msb = (sd.bytes == 2) ? 0x8000 : 0x80;
+   int v = get_src (sd);
+   int c = 0;
+   int o = 0;
+ 
+   if (sd.bytes == 4)
+     {
+       mask = 0xffffffffU;
+       msb = 0x80000000U;
+     }
+ 
+   tprintf("%s %x by %d\n", arith ? "sha" : "shl", v, count);
+   tprintf (": %s %d %d\n", bits(v, 8*sd.bytes), c, o);
+   while (count > 0)
+     {
+       c = (v & msb) ? 1 : 0;
+       v <<= 1;
+       v &= mask;
+       if (c != ((v & msb) ? 1 : 0))
+ 	o = 1;
+       tprintf (": %s %d %d\n", bits(v, 8*sd.bytes), c, o);
+       count --;
+     }
+   while (count < 0)
+     {
+       c = v & 1;
+       if (arith)
+ 	v = (v & msb) | (v >> 1);
+       else
+ 	v = (v >> 1) & (msb - 1);
+       tprintf (": %s %d %d\n", bits(v, 8*sd.bytes), c, o);
+       count ++;
+     }
+   put_dest (sd, v);
+   set_sz (v, sd.bytes);
+   if (setc)
+     set_c (c);
+   set_flags (FLAGBIT_O, o ? FLAGBIT_O : 0);
+ }
+ 
+ int
+ decode_m32c()
+ {
+   unsigned char op[40];
+   int opi;
+   int orig_pc;
+   int v, a, b;
+   long long ll;
+   srcdest sc, dc;
+   int imm;
+   int bitindex = -1;
+   int t0, t1=0, t2, t3=0;
+   int ta0, ta1, dif;
+ 
+   step_result = M32C_MAKE_STEPPED ();
+ 
+   decode_indirect (0, 0);
+   decode_index (0, 0);
+ 
+ next_opcode:
+   opi = 0;
+   orig_pc = get_reg (pc);
+ 
+   tprintf("trace: decode pc = %06x\n", orig_pc);
+ 
+   /* VARY sss 000 001 010 011 100 */
+   /* VARY ddd 000 001 010 011 100 */
+ 
+   /* 0000 1001				indirect dest */
+ 
+   decode_indirect (0, 1);
+   goto next_opcode;
+ 
+   /* 0100 0001				indirect src */
+ 
+   decode_indirect (1, 0);
+   goto next_opcode;
+ 
+   /* 0100 1001				indirect src and dest */
+ 
+   decode_indirect (1, 1);
+   goto next_opcode;
+ 
+   /* 1010 ddd w dd01 1111		ABS.size dest */
+ 
+   prefix (0, 1, 0);
+   dc = decode_dest23 (ddd, dd, w+1);
+   v = sign_ext (get_src (dc), w?16:8);
+   a = v<0 ? -v : v;
+   tprintf("abs(%d) = %d\n", v, a);
+   set_osz(a, w+1);
+   put_dest (dc, a);
+ 
+   /* 0000 0001 1000 ddd w dd10 1110	ADC.size #IMM,dest */
+ 
+   prefix (0, 0, 0);
+   dc = decode_dest23 (ddd, dd, w+1);
+   imm = IMM (w+1);
+   MATH_OP (dc, imm, carry, +);
+ 
+   /* 0000 0001 1sss ddd w dd ss 0100	ADC.size src,dest */
+ 
+   prefix (0, 0, 0);
+   sc = decode_src23 (sss, ss, w+1);
+   dc = decode_dest23 (ddd, dd, w+1);
+   b = get_src (sc);
+   MATH_OP (dc, b, carry, +);
+ 
+   /* 1011 ddd w dd01 1110		ADCF.size dest */
+ 
+   prefix (0, 1, 0);
+   dc = decode_dest23 (ddd, dd, w+1);
+   MATH_OP (dc, 0, carry, +);
+ 
+   /* 1000 ddd w dd10 1110		ADD.size:G #IMM,dest */
+ 
+   prefix (0, 1, 0);
+   dc = decode_dest23(ddd, dd, w+1);
+   imm = IMM(w+1);
+   MATH_OP (dc, imm, 0, +);
+ 
+   /* 1000 ddd0 dd11 0001		ADD.L:G #IMM,dest */
+ 
+   prefix (0, 1, 0);
+   dc = decode_dest23(ddd, dd, 4);
+   imm = IMM(4);
+   MATH_OP (dc, imm, 0, +);
+ 
+   /* 111L ddd w dd11 immm		ADD.size:Q #IMM,dest */
+ 
+   prefix (0, 1, 0);
+   dc = decode_dest23(ddd, dd, L ? 4 : (w+1));
+   imm = sign_ext (immm, 4);
+   MATH_OP (dc, imm, 0, +);
+ 
+   /* 00dd 011w				ADD.size:S #IMM,dest */
+ 
+   prefix (0, 1, 0);
+   dc = decode_dest2(dd, w+1);
+   imm = IMM (w+1);
+   MATH_OP (dc, imm, 0, +);
+ 
+   /* 10i0 110d				ADD.L:S #IMM,A0/A1 */
+ 
+   prefix (0, 0, 0);
+   dc = reg_sd (d ? a1 : a0);
+   imm = i ? 2 : 1;
+   MATH_OP (dc, imm, 0, +);
+ 
+   /* 1sss ddd w dd ss 1000		ADD.size:G src,dest */
+ 
+   prefix (1, 1, 0);
+   sc = decode_src23(sss, ss, w+1);
+   dc = decode_dest23(ddd, dd, w+1);
+   b = get_src (sc);
+   MATH_OP (dc, b, 0, +);
+ 
+   /* 1sss ddd1 dd ss 0010		ADD.L:G src,dest */
+ 
+   prefix (1, 1, 0);
+   sc = decode_src23(sss, ss, 4);
+   dc = decode_dest23(ddd, dd, 4);
+   b = get_src (sc);
+   MATH_OP (dc, b, 0, +);
+ 
+   /* 1011 0110 0001 0011		ADD.L:G #IMM16,SP */
+ 
+   prefix (0, 0, 0);
+   dc = reg_sd (sp);
+   b = sign_ext (IMM(2), 16);
+   MATH_OP (dc, b, 0, +);
+ 
+   /* 01ii 001i				ADD.L:Q #IMM3,SP */
+ 
+   prefix (0, 0, 0);
+   dc = reg_sd (sp);
+   b = ii * 2 + i + 1;
+   MATH_OP (dc, b, 0, +);
+ 
+   /* 1011 0110 0000 0011		ADD.L:S #IMM8,SP */
+ 
+   prefix (0, 0, 0);
+   dc = reg_sd (sp);
+   b = sign_ext (IMM(1), 8);
+   MATH_OP (dc, b, 0, +);
+ 
+   /* 1000 ddd0 dd01 0001		ADDX #IMM,dest */
+ 
+   prefix (0, 1, 0);
+   dc = decode_dest23(ddd, dd, 4);
+   imm = sign_ext (IMM(1), 8);
+   MATH_OP (dc, imm, 0, +);
+ 
+   /* 1sss ddd0 dd ss 0010		ADDX src,dest */
+ 
+   prefix (1, 1, 0);
+   sc = decode_src23(sss, ss, 1);
+   dc = decode_dest23(ddd, dd, 4);
+   b = sign_ext (get_src (sc), 8);
+   MATH_OP (dc, b, 0, +);
+ 
+   /* 1111 ddd w dd01 immm		ADJNZ.size #IMM,dest,label */
+ 
+   prefix (0, 0, 0);
+   dc = decode_dest23 (ddd, dd, w+1);
+   v = get_src (dc);
+   imm = sign_ext(immm, 4);
+   tprintf("%d + %d = %d\n", v, imm, v+imm);
+   v += imm;
+   put_dest (dc, v);
+   a = sign_ext (IMM(1), 8);
+   if ((v & (w ? 0xffff : 0xff)) != 0)
+     {
+       tprintf("jmp: %x + 2 + %d = ", get_reg (pc), a);
+       put_reg (pc, orig_pc + 2 + a);
+       tprintf("%x\n", get_reg (pc));
+     }
+ 
+   /* 1000 ddd w dd11 1111		AND.size:G #IMM,dest */
+ 
+   prefix (0, 1, 0);
+   dc = decode_dest23(ddd, dd, w+1);
+   imm = IMM(w+1);
+   LOGIC_OP (dc, imm, &);
+ 
+   /* 01dd 110w				AND.size:S #IMM,dest */
+ 
+   prefix (0, 1, 0);
+   dc = decode_dest2(dd, w+1);
+   imm = IMM (w+1);
+   LOGIC_OP (dc, imm, &);
+ 
+   /* 1sss ddd w dd ss 1101		AND.size:G src,dest */
+ 
+   prefix (1, 1, 0);
+   sc = decode_src23(sss, ss, w+1);
+   dc = decode_dest23(ddd, dd, w+1);
+   b = get_src (sc);
+   LOGIC_OP (dc, b, &);
+ 
+   /* 0000 0001 1101 sss0 ss00 1bit	BAND src */
+ 
+   sc = decode_src23 (sss, ss, 1);
+   BIT_OPC (sc, bit, b & carry);
+ 
+   /* 1101 ddd0 dd11 0bit		BCLR dest */
+ 
+   dc = decode_dest23 (ddd, dd, 1);
+   BIT_OP (dc, bit, 0);
+ 
+   /* 1100 ddd w dd10 1110		BITINDEX.size src */
+ 
+   prefix (0, 0, 0);
+   dc = decode_dest23 (ddd, dd, w+1);
+   bitindex = get_src (dc);
+   tprintf ("bitindex set to %d\n", bitindex);
+   goto next_opcode;
+ 
+   /* 1101 ddd0 dd01 0bit		BMcnd dest */
+ 
+   prefix (0, 0, 0);
+   dc = decode_dest23 (ddd, dd, 1);
+   if (condition_true (IMM (1)))
+     put_bit2 (dc, bit, 1);
+   else
+     put_bit2 (dc, bit, 0);
+ 
+   /* 1101 1001 0c10 1cnd		BMcnd C */
+ 
+   prefix (0, 0, 0);
+   if (condition_true (c * 8 + cnd))
+     set_c (1);
+   else
+     set_c (0);
+ 
+   /* 0000 0001 1101 sss0 ss01 1bit	BNAND src */
+ 
+   prefix (0, 0, 0);
+   sc = decode_src23 (sss, ss, 1);
+   BIT_OPC (sc, bit, !b & carry);
+ 
+   /* 0000 0001 1101 sss0 ss11 0bit	BNOR src */
+ 
+   prefix (0, 0, 0);
+   sc = decode_src23 (sss, ss, 1);
+   BIT_OPC (sc, bit, !b | carry);
+ 
+   /* 1101 ddd0 dd01 1bit		BNOT dest */
+ 
+   prefix (0, 0, 0);
+   dc = decode_dest23 (ddd, dd, 1);
+   BIT_OP (dc, bit, !b);
+ 
+   /* 0000 0001 1101 sss0 ss00 0bit	BNTST src */
+ 
+   prefix (0, 0, 0);
+   sc = decode_dest23 (sss, ss, 1);
+   b = get_bit2 (sc, bit);
+   set_zc (!b, !b);
+ 
+   /* 0000 0001 1101 sss0 ss11 1bit	BNXOR src */
+ 
+   prefix (0, 0, 0);
+   sc = decode_src23 (sss, ss, 1);
+   BIT_OPC (sc, bit, !b ^ carry);
+ 
+   /* 0000 0001 1101 sss0 ss10 0bit	BOR src */
+ 
+   prefix (0, 0, 0);
+   sc = decode_src23 (sss, ss, 1);
+   BIT_OPC (sc, bit, b | carry);
+ 
+   /* 0000 0000				BRK */
+ 
+   /* We report the break to our caller with the PC still pointing at the 
+      breakpoint instruction.  */
+   put_reg (pc, orig_pc);
+   if (verbose)
+     printf("[break]\n");
+   return M32C_MAKE_HIT_BREAK ();
+ 
+   /* 0000 1000				BRK */
+ 
+   if (verbose)
+     printf("[break2]\n");
+   return M32C_MAKE_HIT_BREAK ();
+ 
+   /* 1101 ddd0 dd11 1bit		BSET dest */
+ 
+   dc = decode_dest23 (ddd, dd, 1);
+   BIT_OP (dc, bit, 1);
+ 
+   /* 1101 sss0 ss00 0bit		BTST:G src */
+ 
+   prefix (0, 0, 0);
+   sc = decode_src23 (sss, ss, 1);
+   b = get_bit2 (sc, bit);
+   set_zc (!b, b);
+ 
+   /* 00bb 101b				BTST:S src */
+ 
+   sc = decode_src23 (3, 3, 1); /* bit,base:19 */
+   b = get_bit2 (sc, bb*2 + b);
+   set_zc (!b, b);
+ 
+   /* 1101 ddd0 dd10 0bit		BTSTC dest */
+ 
+   prefix (0, 0, 0);
+   sc = decode_dest23 (ddd, dd, 1);
+   b = get_bit2 (sc, bit);
+   set_zc (!b, b);
+   put_bit2 (sc, bit, 0);
+ 
+   /* 1101 ddd0 dd10 1bit		BTSTS dest */
+ 
+   prefix (0, 0, 0);
+   sc = decode_dest23 (ddd, dd, 1);
+   b = get_bit2 (sc, bit);
+   set_zc (!b, b);
+   put_bit2 (sc, bit, 1);
+ 
+   /* 0000 0001 1101 sss0 ss10 1bit	BXOR src */
+ 
+   prefix (0, 0, 0);
+   sc = decode_src23 (sss, ss, 1);
+   BIT_OPC (sc, bit, b ^ carry);
+ 
+   /* 0000 0001 1000 ddd w dd11 1110	CLIP.size #IMM1,#IMM2,dest */
+ 
+   prefix (0, 0, 0);
+   dc = decode_dest23 (ddd, dd, w+1);
+   a = sign_ext (IMM(w+1), w*8+8);
+   b = sign_ext (IMM(w+1), w*8+8);
+   v = sign_ext (get_src (dc), w*8+8);
+   tprintf("clip %d <= %d <= %d : ", a, v, b);
+   if (a > v)
+     v = a;
+   if (v > b)
+     v = b;
+   tprintf("%d\n", v);
+   put_dest (dc, v);
+ 
+   /* 1001 ddd w dd10 1110		CMP.size:G #IMM,dest */
+ 
+   prefix (0, 1, 0);
+   dc = decode_dest23 (ddd, dd, w+1);
+   v = get_src (dc);
+   imm = IMM(w+1);
+   cmp (v, imm, w+1);
+ 
+   /* 1010 ddd0 dd11 0001		CMP.L:G #IMM32,dest */
+ 
+   prefix (0, 1, 0);
+   dc = decode_dest23 (ddd, dd, 4);
+   v = get_src (dc);
+   imm = IMM(4);
+   cmp (v, imm, 4);
+ 
+   /* 1110 ddd w dd01 immm		CMP.size:Q #IMM,dest */
+ 
+   prefix (0, 1, 0);
+   dc = decode_dest23 (ddd, dd, w+1);
+   v = get_src (dc);
+   immm = sign_ext (immm, 4);
+   cmp (v, immm, w+1);
+ 
+   /* 01dd 011w				CMP.size:S #IMM,dest */
+ 
+   prefix (0, 1, 0);
+   dc = decode_dest2 (dd, w+1);
+   v = get_src (dc);
+   imm = sign_ext (IMM(w+1),w*8+8);
+   cmp (v, imm, w+1);
+ 
+   /* 1sss ddd w dd ss 0110		CMP.size:G src,dest */
+ 
+   prefix (1, 1, 0);
+   sc = decode_src23 (sss, ss, w+1);
+   dc = decode_dest23 (ddd, dd, w+1);
+   a = get_src (dc);
+   b = get_src (sc);
+   cmp (a, b, w+1);
+ 
+   /* 1sss ddd1 dd ss 0001		CMP.L:G src,dest */
+ 
+   prefix (1, 1, 0);
+   sc = decode_src23 (sss, ss, 4);
+   dc = decode_dest23 (ddd, dd, 4);
+   a = get_src (dc);
+   b = get_src (sc);
+   cmp (a, b, 4);
+ 
+   /* 01dd 000w				CMP.size:S src,R0/R0L */
+ 
+   prefix (0, 1, 0);
+   dc = decode_dest2 (dd, w+1);
+   a = get_reg (w ? r0 : r0l);
+   b = get_src (dc);
+   cmp (a, b, w+1);
+ 
+   /* 1010 ddd0 dd01 0001		CMPX #IMM,dest */
+ 
+   prefix (0, 1, 0);
+   dc = decode_dest23 (ddd, dd, 4);
+   v = get_src (dc);
+   imm = sign_ext (IMM(1), 8);
+   cmp (v, imm, 4);
+ 
+   /* 0000 0001 1000 ddd w dd00 1110	DADC.size #IMM,dest */
+ 
+   DADDI(1,1);
+ 
+   /* 0000 0001 1sss ddd w dd ss 1000	DADC.size src,dest */
+ 
+   DADDV(1,1);
+ 
+   /* 0000 0001 1000 ddd w dd01 1110	DADD.size #IMM,dest */
+ 
+   DADDI(1,0);
+ 
+   /* 0000 0001 1sss ddd w dd ss 0000	DADD.size src,dest */
+ 
+   DADDV(1,0);
+ 
+   /* 1011 ddd w dd00 1110		DEC.size dest */
+ 
+   prefix (0, 1, 0);
+   dc = decode_dest23 (ddd, dd, w+1);
+   a = get_src (dc);
+   v = a-1;
+   tprintf ("%x -- = %x\n", a, v);
+   set_sz (v, w+1);
+   put_dest (dc, v);
+ 
+   /* 1011 0000 010w 0011		DIV.size #IMM */
+ 
+   prefix (0, 0, 0);
+   div_op (-1, 0, 0, 0, w+1);
+ 
+   /* 1000 sss w ss01 1110		DIV.size src */
+ 
+   prefix (0, 1, 0);
+   div_op (sss, ss, 0, 0, w+1);
+ 
+   /* 0000 0001 1010 sss1 ss01 1111	DIV.L src */
+ 
+   M32C_ONLY();
+   prefix (0, 0, 0);
+   div_op (sss, ss, 0, 0, 4);
+ 
+   /* 1011 0000 000w 0011		DIVU.size #IMM */
+ 
+   prefix (0, 0, 0);
+   div_op (-1, 0, 1, 0, w+1);
+ 
+   /* 1000 sss w ss00 1110		DIVU.size src */
+ 
+   prefix (0, 1, 0);
+   div_op (sss, ss, 1, 0, w+1);
+ 
+   /* 0000 0001 1010 sss1 ss00 1111	DIVU.L src */
+ 
+   M32C_ONLY();
+   prefix (0, 0, 0);
+   div_op (sss, ss, 1, 0, 4);
+ 
+   /* 1011 0010 010w 0011		DIVX.size #IMM */
+ 
+   prefix (0, 0, 0);
+   div_op (-1, 0, 0, 1, w+1);
+ 
+   /* 1001 sss w ss01 1110		DIVX.size src */
+ 
+   prefix (0, 1, 0);
+   div_op (sss, ss, 0, 1, w+1);
+ 
+   /* 0000 0001 1010 sss1 ss10 1111	DIVX.L src */
+ 
+   M32C_ONLY();
+   prefix (0, 0, 0);
+   div_op (sss, ss, 0, 1, 4);
+ 
+   /* 0000 0001 1001 ddd w dd00 1110	DSBB.size #IMM,dest */
+ 
+   DADDI(0,1);
+ 
+   /* 0000 0001 1sss ddd w dd ss 1010	DSBB.size src,dest */
+ 
+   DADDV(0,1);
+ 
+   /* 0000 0001 1001 ddd w dd01 1110	DSUB.size #IMM,dest */
+ 
+   DADDI(0,0);
+ 
+   /* 0000 0001 1sss ddd w dd ss 0010	DSUB.size src,dest */
+ 
+   DADDV(0,0);
+ 
+   /* 1110 1100				ENTER #IMM */
+ 
+   imm = IMM(1);
+   put_reg (sp, get_reg (sp) - 4);
+   mem_put_si (get_reg (sp), get_reg (fb));
+   put_reg (fb, get_reg (sp));
+   put_reg (sp, get_reg (sp) - imm);
+ 
+   /* 1111 1100				EXITD */
+ 
+   put_reg (sp, get_reg (fb));
+   put_reg (fb, mem_get_si (get_reg (sp)));
+   put_reg (sp, get_reg (sp) + 4);
+   put_reg (pc, mem_get_si (get_reg (sp)));
+   put_reg (sp, get_reg (sp) + 4);
+ 
+   /* 1100 ddd w dd01 1110		EXTS.size dest */
+ 
+   prefix (0, 0, 0);
+   dc = decode_dest23 (ddd, dd, w+1);
+   v = sign_ext (get_src (dc), (w+1)*8);
+   dc = widen_sd (dc);
+   put_dest (dc, v);
+   set_sz (v, (w+1)*2);
+ 
+   /* 0000 0001 1sss ddd0 dd ss 0111	EXTS.B src,dest */
+ 
+   prefix (0, 0, 0);
+   sc = decode_src23 (sss, ss, 1);
+   dc = decode_dest23 (ddd, dd, 2);
+   v = sign_ext (get_src (sc), 8);
+   put_dest (dc, v);
+   set_sz (v, 16);
+ 
+   /* 0000 0001 1sss ddd0 dd ss 1011	EXTZ src,dest */
+ 
+   prefix (0, 0, 0);
+   sc = decode_src23 (sss, ss, 1);
+   dc = decode_dest23 (ddd, dd, 2);
+   v = get_src (sc);
+   put_dest (dc, v);
+   set_sz (v, 16);
+ 
+   /* 1101 0011 1110 1dst		FCLR dest */
+ 
+   set_flags (1 << dst, 0);
+ 
+   /* 1001 1111				FREIT */
+ 
+   NOTYET();
+ 
+   /* 1101 0001 1110 1dst		FSET dest */
+   
+   set_flags (1 << dst, 1 << dst);
+ 
+   /* 1010 ddd w dd00 1110		INC.size dest */
+ 
+   prefix (0, 1, 0);
+   dc = decode_dest23 (ddd, dd, w+1);
+   a = get_src (dc);
+   v = a+1;
+   tprintf ("%x ++ = %x\n", a, v);
+   set_sz (v, w+1);
+   put_dest (dc, v);
+ 
+   /* 1000 sss0 ss0w 0011		INDEXB.size src */
+   INDEXOP(1, 1, 1);
+   /* 1010 sss0 ss0w 0011		INDEXBD.size src */
+   INDEXOP(1, 0, 1);
+   /* 1100 sss0 ss0w 0011		INDEXBS.size src */
+   INDEXOP(1, 1, 0);
+   /* 1001 sss0 ss1w 0011		INDEXL.size src */
+   INDEXOP(4, 1, 1);
+   /* 1011 sss0 ss1w 0011		INDEXLD.size src */
+   INDEXOP(4, 0, 1);
+   /* 1001 sss0 ss0w 0011		INDEXLS.size src */
+   INDEXOP(4, 1, 0);
+   /* 1000 sss0 ss1w 0011		INDEXW.size src */
+   INDEXOP(2, 1, 1);
+   /* 1010 sss0 ss1w 0011		INDEXWD.size src */
+   INDEXOP(2, 0, 1);
+   /* 1100 sss0 ss1w 0011		INDEXWS.size src */
+   INDEXOP(2, 1, 0);
+ 
+   /* 1011 1110 vector00			INT #IMM */
+ 
+   prefix (0, 0, 0);
+   trigger_based_interrupt (vector);
+ 
+   /* 1011 1111				INTO */
+ 
+   prefix (0, 0, 0);
+   if (FLAG_O)
+     trigger_fixed_interrupt (0xffffe0);
+ 
+   /* 1ccc 101c				Jcnd label */
+ 
+   prefix (0, 0, 0);
+   v = sign_ext (IMM(1), 8);
+   if (condition_true (ccc*2+c))
+     put_reg (pc, orig_pc + 1 + v);
+ 
+   /* 01dd 101d				JMP.S label */
+ 
+   prefix (0, 0, 0);
+   put_reg (pc, orig_pc + (dd*2+d) + 2);
+ 
+   /* 1011 1011				JMP.B label */
+ 
+   prefix (0, 0, 0);
+   imm = sign_ext (IMM(1), 8);
+   if (imm == -1)
+     {
+       if (verbose)
+ 	printf("[jmp-to-self detected as exit]\n");
+       return M32C_MAKE_HIT_BREAK ();
+     }
+   put_reg (pc, orig_pc + 1 + imm);
+ 
+   /* 1100 1110				JMP.W label */
+ 
+   prefix (0, 0, 0);
+   imm = sign_ext (IMM(2), 16);
+   put_reg (pc, orig_pc + 1 + imm);
+ 
+   /* 1100 1100				JMP.A label */
+   
+   prefix (0, 0, 0);
+   imm = IMM(3);
+   put_reg (pc, imm);
+ 
+   /* 1100 sss1 ss00 1111		JMPI.W src */
+ 
+   prefix (0, 0, 0);
+   sc = decode_src23 (sss, ss, 2);
+   a = get_src (sc);
+   a = sign_ext (a, 16);
+   put_reg (pc, orig_pc + a);
+ 
+   /* 1000 sss0 ss00 0001		JMPI.A src */
+ 
+   prefix (0, 0, 0);
+   sc = decode_src23 (sss, ss, 3);
+   a = get_src (sc);
+   put_reg (pc, a);
+ 
+   /* 1101 1100				JMPS #IMM8 */
+ 
+   prefix (0, 0, 0);
+   imm = IMM(1);
+   a = 0xff0000 + mem_get_hi (0xfffe00 - imm * 2);
+   put_reg (pc, a);
+ 
+   /* 1100 1111				JSR.W label */
+ 
+   prefix (0, 0, 0);
+   imm = sign_ext (IMM(2), 16);
+   put_reg (sp, get_reg (sp) - 4);
+   mem_put_si (get_reg (sp), get_reg (pc));
+   put_reg (pc, orig_pc + imm + 1);
+ 
+   /* 1100 1101				JSR.A label */
+ 
+   prefix (0, 0, 0);
+   imm = IMM(3);
+   put_reg (sp, get_reg (sp) - 4);
+   mem_put_si (get_reg (sp), get_reg (pc));
+   put_reg (pc, imm);
+ 
+   /* 1100 sss1 ss01 1111		JSRI.W src */
+ 
+   prefix (0, 0, 0);
+   sc = decode_src23 (sss, ss, 2);
+   a = get_src (sc);
+   a = sign_ext (a, 16);
+   put_reg (sp, get_reg (sp) - 4);
+   mem_put_si (get_reg (sp), get_reg (pc));
+   put_reg (pc, orig_pc + a);
+ 
+   /* 1001 sss0 ss00 0001		JSRI.A src */
+ 
+   prefix (0, 0, 0);
+   sc = decode_src23 (sss, ss, 3);
+   a = get_src (sc);
+   put_reg (sp, get_reg (sp) - 4);
+   mem_put_si (get_reg (sp), get_reg (pc));
+   put_reg (pc, a);
+ 
+   /* 1101 1101				JSRS #IMM8 */
+ 
+   prefix (0, 0, 0);
+   imm = IMM(1);
+   a = 0xff0000 + mem_get_hi (0xfffe00 - imm * 2);
+   put_reg (sp, get_reg (sp) - 4);
+   mem_put_si (get_reg (sp), get_reg (pc));
+   put_reg (pc, a);
+ 
+   /* 1101 0101 1010 1dst		LDC #IMM16,dest */
+ 
+   imm = IMM(2);
+   dc = decode_cr_b (dst, CR_B_DCT0);
+   put_dest (dc, imm);
+ 
+   /* 1101 0101 0010 1dst		LDC #IMM24,dest */
+ 
+   imm = IMM(3);
+   dc = decode_cr_b (dst, CR_B_INTB);
+   put_dest (dc, imm);
+ 
+   /* 1101 0101 0110 1dst		LDC #IMM24,dest */
+ 
+   imm = IMM(3);
+   dc = decode_cr_b (dst, CR_B_DMA0);
+   put_dest (dc, imm);
+ 
+   /* 0000 0001 1101 sss1 ss00 1dst	LDC src,dest */
+ 
+   prefix (0, 0, 0);
+   sc = decode_src23 (sss, ss, 2);
+   dc = decode_cr_b (dst, CR_B_DCT0);
+   a = get_src (sc);
+   put_dest (dc, a);
+ 
+   /* 1101 sss1 ss00 0dst		LDC src,dest */
+ 
+   prefix (0, 0, 0);
+   sc = decode_src23 (sss, ss, 3);
+   dc = decode_cr_b (dst, CR_B_INTB);
+   a = get_src (sc);
+   put_dest (dc, a);
+ 
+   /* 0000 0001 1101 sss1 ss00 0dst	LDC src,dest */
+ 
+   prefix (0, 0, 0);
+   sc = decode_src23 (sss, ss, 3);
+   dc = decode_cr_b (dst, CR_B_DMA0);
+   a = get_src (sc);
+   put_dest (dc, a);
+ 
+   /* 1011 0110 1100 0011		LDCTX */
+ 
+   NOTYET();
+ 
+   /* 1101 0101 1110 1imm		LDIPL #IMM */
+ 
+   set_flags (0x7000, imm*0x1000);
+ 
+   /* 0000 0001 1000 ddd w dd11 1111	MAX.size #IMM,dest */
+ 
+   prefix (0, 0, 0);
+   w++;
+   dc = decode_dest23 (ddd, dd, w);
+   imm = sign_ext (IMM(w), w*8);
+   a = sign_ext (get_src (dc), w*8);
+   tprintf ("max %d %d\n", imm, a);
+   if (imm > a)
+     put_dest (dc, imm);
+ 
+   /* 0000 0001 1sss ddd w dd ss 1101	MAX.size src,dest */
+ 
+   prefix (0, 0, 0);
+   w++;
+   sc = decode_src23 (sss, ss, w);
+   dc = decode_dest23 (ddd, dd, w);
+   b = sign_ext (get_src (sc), w*8);
+   a = sign_ext (get_src (dc), w*8);
+   tprintf ("max %d %d\n", b, a);
+   if (b > a)
+     put_dest (dc, b);
+ 
+   /* 0000 0001 1000 ddd w dd10 1111	MIN.size #IMM,dest */
+ 
+   prefix (0, 0, 0);
+   w++;
+   dc = decode_dest23 (ddd, dd, w);
+   imm = sign_ext (IMM(w), w*8);
+   a = sign_ext (get_src (dc), w*8);
+   tprintf ("min %d %d\n", imm, a);
+   if (imm < a)
+     put_dest (dc, imm);
+ 
+   /* 0000 0001 1sss ddd w dd ss 1100	MIN.size src,dest */
+ 
+   prefix (0, 0, 0);
+   w++;
+   sc = decode_src23 (sss, ss, w);
+   dc = decode_dest23 (ddd, dd, w);
+   b = sign_ext (get_src (sc), w*8);
+   a = sign_ext (get_src (dc), w*8);
+   tprintf ("min %d %d\n", b, a);
+   if (b < a)
+     put_dest (dc, b);
+ 
+   /* 1001 ddd w dd10 1111		MOV.size:G #IMM,dest */
+ 
+   dc = decode_dest23 (ddd, dd, w+1);
+   imm = IMM(w+1);
+   v = imm;
+   tprintf("%x = %x\n", v, v);
+   set_sz(v, w+1);
+   put_dest (dc, v);
+ 
+   /* 1011 ddd0 dd11 0001		MOV.L:G #IMM,dest */
+ 
+   dc = decode_dest23 (ddd, dd, 4);
+   imm = IMM(4);
+   v = imm;
+   tprintf("%x = %x\n", v, v);
+   set_sz(v, 4);
+   put_dest (dc, v);
+ 
+   /* 1111 ddd w dd10 immm		MOV.size:Q #IMM4,dest */
+ 
+   dc = decode_dest23 (ddd, dd, w+1);
+   imm = sign_ext (immm, 4);
+   v = imm;
+   tprintf("%x = %d\n", v, v);
+   set_sz(v, w+1);
+   put_dest (dc, v);
+ 
+   /* 00dd 010w				MOV.size:S #IMM,dest */
+ 
+   prefix (0, 1, 0);
+   dc = decode_dest2 (dd, w+1);
+   imm = IMM(w+1);
+   put_dest (dc, imm);
+   set_sz (imm, w+1);
+ 
+   /* 10w1 110d				MOV.size:S #IMM,a0/a1 */
+ 
+   imm = IMM(w ? 3 : 2);
+   put_reg (d ? a1 : a0, imm);
+   set_sz (imm & addr_mask, w+1);
+ 
+   /* 00dd 001w				MOV.size:Z #0,dest */
+ 
+   prefix (0, 1, 0);
+   dc = decode_dest2 (dd, w+1);
+   put_dest (dc, 0);
+   set_sz (0, w+1);
+ 
+   /* 1sss ddd w dd ss 1011		MOV.size:G src,dest */
+ 
+   prefix (1, 1, 0);
+   sc = decode_src23 (sss, ss, w+1);
+   dc = decode_dest23 (ddd, dd, w+1);
+   v = get_src (sc);
+   put_dest (dc, v);
+   set_sz (v, w+1);
+ 
+   /* 1sss ddd1 dd ss 0011		MOV.L:G src,dest */
+ 
+   prefix (1, 1, 0);
+   sc = decode_src23 (sss, ss, 4);
+   dc = decode_dest23 (ddd, dd, 4);
+   v = get_src (sc);
+   put_dest (dc, v);
+   set_sz (v, 4);
+ 
+   /* VARY SS 01 10 11 */
+   /* 00SS 100w				MOV.size:S src,R0L/R0 */
+ 
+   prefix (0, 1, 0);
+   sc = decode_dest2 (SS, w+1);
+   v = get_src (sc);
+   put_reg (w ? r0 : r0l, v);
+   set_sz (v, w+1);
+ 
+   /* 01ss 111w				MOV.size:S src,R1L/R1 */
+ 
+   prefix (0, 1, 0);
+   sc = decode_dest2 (ss, w+1);
+   v = get_src (sc);
+   put_reg (w ? r1 : r1l, v);
+   set_sz (v, w+1);
+ 
+   /* VARY DD 01 10 11 */
+   /* 00DD 000w				MOV.size:S R0L/R0,dest */
+ 
+   prefix (0, 1, 0);
+   dc = decode_dest2 (DD, w+1);
+   v = get_reg (w ? r0 : r0l);
+   put_dest (dc, v);
+   set_sz (v, w+1);
+ 
+   /* 01ss 100d				MOV.L:S src,A0/A1 */
+ 
+   prefix (0, 1, 0);
+   sc = decode_dest2 (ss, 4);
+   v = get_src (sc);
+   put_reg (d ? a1 : a0, v);
+   set_sz (v, 4);
+ 
+   /* 1011 ddd w dd00 1111		MOV.size:G dsp:8[SP], dest */
+ 
+   prefix (0, 0, 0);
+   imm = IMM(1);
+   dc = decode_dest23 (ddd, dd, w+1);
+   a = get_reg (sp) + sign_ext (imm, 8);
+   a &= addr_mask;
+   if (w)
+     v = mem_get_hi (a);
+   else
+     v = mem_get_qi (a);
+   put_dest (dc, v);
+   set_sz (v, w+1);
+ 
+   /* 1010 sss w ss00 1111		MOV.size:G src,dsp:8[SP] */
+ 
+   prefix (0, 0, 0);
+   sc = decode_dest23 (sss, ss, w+1);
+   imm = IMM(1);
+   a = get_reg (sp) + sign_ext (imm, 8);
+   a &= addr_mask;
+   v = get_src (sc);
+   if (w)
+     mem_put_hi (a, v);
+   else
+     mem_put_qi (a, v);
+   set_sz (v, w+1);
+ 
+   /* 1101 sss1 ss01 1dst		MOVA src,dest */
+ 
+   static reg_id map[8] = { r2r0, r3r1, a0, a1 };
+   prefix (0, 0, 0);
+   sc = decode_src23 (sss, ss, 1);
+   if (!sc.mem || !map[dst])
+     UNSUPPORTED();
+   put_reg (map[dst], sc.u.addr);
+ 
+   /* 0000 0001 1011 ddd0 dd hl 1110	MOVdir R0L,dest */
+ 
+   prefix (0, 0, 0);
+   dc = decode_dest23 (ddd, dd, 1);
+   a = get_src (dc);
+   b = get_reg (r0l);
+   switch (hl)
+     {
+     case 0: a = (a & 0xf0) | (b & 0x0f); break;
+     case 1: a = (a & 0xf0) | ((b>>4) & 0x0f); break;
+     case 2: a = (a & 0x0f) | ((b & 0x0f)<<4); break;
+     case 3: a = (a & 0x0f) | (b & 0xf0); break;
+     }
+   put_dest (dc, a);
+ 
+   /* 0000 0001 1010 sss0 ss hl 1110	MOVdir src,R0L */
+ 
+   prefix (0, 0, 0);
+   sc = decode_dest23 (sss, ss, 1);
+   a = get_reg (r0l);
+   b = get_src (dc);
+   switch (hl)
+     {
+     case 0: a = (a & 0xf0) | (b & 0x0f); break;
+     case 1: a = (a & 0xf0) | ((b>>4) & 0x0f); break;
+     case 2: a = (a & 0x0f) | ((b & 0x0f)<<4); break;
+     case 3: a = (a & 0x0f) | (b & 0xf0); break;
+     }
+   put_reg (r0l, a);
+ 
+   /* 1011 ddd0 dd01 0001		MOVX #IMM,dest */
+ 
+   prefix (0, 1, 0);
+   dc = decode_dest23 (ddd, dd, 4);
+   imm = sign_ext (IMM(1), 8);
+   put_dest (dc, imm);
+   set_sz (imm, 1);
+ 
+   /* 1000 ddd w dd01 1111		MUL.size #IMM,dest */
+ 
+   prefix (0, 1, 0);
+   w ++;
+   dc = decode_dest23 (ddd, dd, w);
+   v = sign_ext (get_src (dc), w*8);
+   imm = sign_ext (IMM(w), w*8);
+   tprintf("%d * %d = %d\n", v, imm, v*imm);
+   v *= imm;
+   dc = widen_sd (dc);
+   put_dest (dc, v);
+ 
+   /* 1sss ddd w dd ss 1100		MUL.size src,dest */
+ 
+   prefix (1, 1, 0);
+   w ++;
+   sc = decode_src23 (sss, ss, w);
+   dc = decode_dest23 (ddd, dd, w);
+   a = sign_ext (get_src (sc), w*8);
+   b = sign_ext (get_src (dc), w*8);
+   tprintf("%d * %d = %d\n", a, b, a*b);
+   v = a * b;
+   dc = widen_sd (dc);
+   put_dest (dc, v);
+ 
+   /* 0000 0001 1000 sss1 ss01 1111	MUL.L src,R2R0 */
+ 
+   M32C_ONLY();
+   prefix (0, 0, 0);
+   sc = decode_src23 (sss, ss, 4);
+   a = sign_ext (get_src (sc), 32);
+   b = sign_ext (get_reg (r2r0), 32);
+   ll = (long long)a * (long long)b;
+   tprintf("%d * %d = %lld (%llx)\n", a, b, ll, ll);
+   if (ll < b2minsigned[4] || ll > b2maxsigned[4])
+     set_flags (FLAGBIT_O, FLAGBIT_O);
+   else
+     set_flags (FLAGBIT_O, 0);
+   put_reg (r2r0, (int)ll);
+ 
+   /* 1100 sss1 ss11 1110		MULEX src */
+ 
+   prefix (0, 1, 0);
+   sc = decode_dest23 (sss, ss, 2);
+   a = sign_ext (get_src (sc), 16);
+   b = sign_ext (get_reg (r2r0), 32);
+   ll = (long long)a * (long long)b;
+   tprintf("%d * %d = %lld (%llx)\n", a, b, ll, ll);
+   put_reg (r2r0, (int)ll);
+   put_reg (r1, (int)(ll >> 32));
+ 
+   /* 1000 ddd w dd00 1111		MULU.size #IMM,dest */
+ 
+   prefix (0, 1, 0);
+   w ++;
+   dc = decode_dest23 (ddd, dd, w);
+   v = get_src (dc);
+   imm = IMM(w);
+   tprintf("%d * %d = %d\n", v, imm, v*imm);
+   v *= imm;
+   dc = widen_sd (dc);
+   put_dest (dc, v);
+ 
+   /* 1sss ddd w dd ss 0100		MULU.size src,dest */
+ 
+   prefix (1, 1, 0);
+   w ++;
+   sc = decode_src23 (sss, ss, w);
+   dc = decode_dest23 (ddd, dd, w);
+   a = get_src (sc);
+   b = get_src (dc);
+   tprintf("%d * %d = %d\n", a, b, a*b);
+   v = a * b;
+   dc = widen_sd (dc);
+   put_dest (dc, v);
+ 
+   /* 0000 0001 1000 sss1 ss00 1111	MULU.L src,R2R0 */
+ 
+   M32C_ONLY();
+   prefix (0, 0, 0);
+   sc = decode_src23 (sss, ss, 4);
+   a = get_src (sc);
+   b = get_reg (r2r0);
+   ll = (long long)a * (long long)b;
+   tprintf("%d * %d = %lld (%llx)\n", a, b, ll, ll);
+   if (ll < b2minsigned[4] || ll > b2maxsigned[4])
+     set_flags (FLAGBIT_O, FLAGBIT_O);
+   else
+     set_flags (FLAGBIT_O, 0);
+   put_reg (r2r0, (int)ll);
+ 
+   /* 1010 ddd w dd10 1111		NEG.size dest */
+ 
+   prefix (0, 1, 0);
+   dc = decode_dest23 (ddd, dd, w+1);
+   a = sign_ext (get_src (dc), (w+1)*8);
+   v = -a;
+   tprintf("%d * -1 = %d\n", a, v);
+   set_oszc(v, w+1, v==0);
+   put_dest (dc, v);
+ 
+   /* 1101 1110				NOP */
+ 
+   tprintf("nop\n");
+ 
+   /* 1010 ddd w dd01 1110		NOT.size dest */
+ 
+   prefix (0, 1, 0);
+   dc = decode_dest23 (ddd, dd, w+1);
+   a = get_src (dc);
+   v = ~a;
+   tprintf("~ %x = %x\n", a, v);
+   set_sz(v, w+1);
+   put_dest (dc, v);
+ 
+   /* 1000 ddd w dd10 1111		OR.size:G #IMM,dest */
+ 
+   prefix (0, 1, 0);
+   dc = decode_dest23(ddd, dd, w+1);
+   imm = IMM(w+1);
+   LOGIC_OP (dc, imm, |);
+ 
+   /* 01dd 010w				OR.size:S #IMM,dest */
+ 
+   prefix (0, 1, 0);
+   dc = decode_dest2(dd, w+1);
+   imm = IMM (w+1);
+   LOGIC_OP (dc, imm, |);
+ 
+   /* 1sss ddd w dd ss 0101		OR.size:G src,dest */
+ 
+   prefix (1, 1, 0);
+   sc = decode_src23(sss, ss, w+1);
+   dc = decode_dest23(ddd, dd, w+1);
+   b = get_src (sc);
+   LOGIC_OP (dc, b, |);
+ 
+   /* 1011 ddd w dd10 1111		POP.size dest */
+ 
+   prefix (0, 1, 0);
+   dc = decode_dest23 (ddd, dd, w+1);
+   if (w)
+     a = mem_get_hi (get_reg (sp));
+   else
+     a = mem_get_qi (get_reg (sp));
+   put_reg (sp, get_reg (sp) + 2);
+   tprintf("pop%s: %x\n", w ? "hi" : "qi", a);
+   put_dest (dc, a);
+ 
+   /* 1101 0011 1010 1dst		POPC dest */
+ 
+   prefix (0, 0, 0);
+   dc = decode_cr_b (dst, CR_B_DCT0);
+   a = mem_get_hi (get_reg (sp));
+   put_reg (sp, get_reg (sp) + 2);
+   tprintf("pophi: %x\n", a);
+   put_dest (dc, a);
+ 
+   /* 1101 0011 0010 1dst		POPC dest */
+ 
+   prefix (0, 0, 0);
+   dc = decode_cr_b (dst, CR_B_INTB);
+   a = mem_get_si (get_reg (sp));
+   put_reg (sp, get_reg (sp) + 4);
+   tprintf("popsi: %x\n", a);
+   put_dest (dc, a);
+ 
+   /* 1000 1110				POPM dest */
+ 
+   static int map[] = { r0, r1, r2, r3, a0, a1, sb, fb };
+   prefix (0, 0, 0);
+   imm = IMM(1);
+   tprintf("popm: %x\n", imm);
+   for (a=0; a<4; a++)
+     if (imm & (1<<a))
+       {
+ 	v = mem_get_hi (get_reg (sp));
+ 	put_reg (map[a], v);
+ 	put_reg (sp, get_reg (sp) + 2);
+       }
+   for (; a<8; a++)
+     if (imm & (1<<a))
+       {
+ 	v = mem_get_si (get_reg (sp));
+ 	put_reg (map[a], v);
+ 	put_reg (sp, get_reg (sp) + 4);
+       }
+ 
+   /* 1010 111w				PUSH.size #IMM */
+ 
+   prefix (0, 0, 0);
+   imm = IMM(w+1);
+   tprintf("push%s: %x\n", w ? "hi" : "qi", imm);
+   int a = get_reg (sp) - 2;
+   if (w)
+     mem_put_hi (a, imm);
+   else
+     mem_put_qi (a, imm);
+   put_reg (sp, a);
+ 
+   /* 1100 sss w ss00 1110		PUSH.size src */
+ 
+   prefix (0, 1, 0);
+   sc = decode_dest23 (sss, ss, w+1);
+   a = get_src (sc);
+   put_reg (sp, get_reg (sp) - 2);
+   if (w)
+     mem_put_hi (get_reg (sp), a);
+   else
+     mem_put_qi (get_reg (sp), a);
+   tprintf("push%s: %x\n", w ? "hi" : "qi", a);
+ 
+   /* 1011 0110 0101 0011		PUSH.L #IMM32 */
+ 
+   imm = IMM(4);
+   put_reg (sp, get_reg (sp) - 4);
+   mem_put_si (get_reg (sp), imm);
+ 
+   /* 1010 sss0 ss00 0001		PUSH.L src */
+ 
+   prefix (0, 1, 0);
+   sc = decode_dest23 (sss, ss, 4);
+   a = get_src (sc);
+   put_reg (sp, get_reg (sp) - 4);
+   mem_put_si (get_reg (sp), a);
+ 
+   /* 1011 0sa0 ss00 0001		PUSHA src */
+ 
+   prefix (0, 0, 0);
+   sc = decode_dest23 (sa, ss, 1);
+   put_reg (sp, get_reg (sp) - 4);
+   mem_put_hi (get_reg (sp), sc.u.addr);
+   tprintf("pushsi: %x\n", sc.u.addr);
+ 
+   /* 1101 0001 1010 1src		PUSHC src */
+ 
+   prefix (0, 0, 0);
+   sc = decode_cr_b (src, CR_B_DCT0);
+   a = get_src (sc);
+   put_reg (sp, get_reg (sp) - 2);
+   mem_put_hi (get_reg (sp), a);
+   tprintf("pushhi: %x\n", a);
+ 
+   /* 1101 0001 0010 1src		PUSHC src */
+ 
+   prefix (0, 0, 0);
+   sc = decode_cr_b (src, CR_B_INTB);
+   a = get_src (sc);
+   put_reg (sp, get_reg (sp) - 4);
+   mem_put_si (get_reg (sp), a);
+   tprintf("pushsi: %x\n", a);
+ 
+   /* 1000 1111				PUSHM src */
+ 
+   static int map[] = { fb, sb, a1, a0, r3, r2, r1, r0 };
+   imm = IMM(1);
+   tprintf("pushm: %x\n", imm);
+   for (a=0; a<4; a++)
+     if (imm & (1<<a))
+       {
+ 	put_reg (sp, get_reg (sp) - 4);
+ 	v = get_reg (map[a]);
+ 	mem_put_si (get_reg (sp), v);
+       }
+   for (; a<8; a++)
+     if (imm & (1<<a))
+       {
+ 	put_reg (sp, get_reg (sp) - 2);
+ 	v = get_reg (map[a]);
+ 	mem_put_hi (get_reg (sp), v);
+       }
+ 
+   /* 1001 1110				REIT */
+ 
+   a = get_reg (sp);
+   put_reg (pc, mem_get_si (a));
+   a += 4;
+   put_reg (flags, mem_get_hi (a));
+   a += 2;
+   put_reg (sp, a);
+ 
+   /* 1011 1000 010w 0011		RMPA.size */
+ 
+   int count = get_reg (r3);
+   int list1 = get_reg (a0);
+   int list2 = get_reg (a1);
+   long long sum = get_reg_ll (r3r1r2r0) & 0xffffff;
+ 
+   while (count)
+     {
+       if (w)
+ 	{
+ 	  a = sign_ext (mem_get_hi (list1), 16);
+ 	  b = sign_ext (mem_get_hi (list2), 16);
+ 	}
+       else
+ 	{
+ 	  a = sign_ext (mem_get_qi (list1), 8);
+ 	  b = sign_ext (mem_get_qi (list2), 8);
+ 	}
+       tprintf("%lld + %d * %d = ", sum, a, b);
+       sum += a * b;
+       tprintf("%lld\n", sum);
+       list1 += w ? 2 : 1;
+       list2 += w ? 2 : 1;
+       count --;
+     }
+   put_reg (r3, count);
+   put_reg (a0, list1);
+   put_reg (a1, list2);
+   put_reg (r2r0, (int)(sum & 0xffffffffU));
+   put_reg (r1, (int)(sum >> 32));
+ 
+   /* 1011 ddd w dd10 1110		ROLC.size dest */
+ 
+   prefix (0, 1, 0);
+   dc = decode_dest23 (ddd, dd, w+1);
+   rot_op (dc, 1, 1);
+ 
+   /* 1010 ddd w dd10 1110		RORC.size dest */
+ 
+   prefix (0, 1, 0);
+   dc = decode_dest23 (ddd, dd, w+1);
+   rot_op (dc, 1, -1);
+ 
+   /* 1110 ddd w dd10 immm		ROT.size #IMM, dest */
+ 
+   prefix (0, 1, 0);
+   dc = decode_dest23 (ddd, dd, w+1);
+   rot_op (dc, IMM4(), -1);
+ 
+   /* 1010 ddd w dd11 1111		ROT.size R1H,dest */
+ 
+   prefix (0, 1, 0);
+   dc = decode_dest23 (ddd, dd, w+1);
+   a = sign_ext (get_reg (r1h), 8);
+   rot_op (dc, a, -1);
+ 
+   /* 1101 1111				RTS */
+ 
+   put_reg (pc, mem_get_si (get_reg (sp)));
+   put_reg (sp, get_reg (sp) + 4);
+ 
+   /* 0000 0001 1001 ddd w dd10 1110	SBB.size #IMM, dest */
+ 
+   prefix (0, 0, 0);
+   dc = decode_dest23 (ddd, dd, w+1);
+   imm = IMM (w+1);
+   MATH_OP (dc, imm, !carry, -);
+ 
+   /* 0000 0001 1sss ddd w dd ss 0110	SBB.size src,dest */
+ 
+   prefix (0, 0, 0);
+   sc = decode_src23 (sss, ss, w+1);
+   dc = decode_dest23 (ddd, dd, w+1);
+   MATH_OP (dc, get_src (sc), !carry, -);
+ 
+   /* 1101 ddd1 dd11 cond		SCcond dest */
+ 
+   prefix (0, 1, 0);
+   dc = decode_dest23 (ddd, dd, 2);
+   if (condition_true (cond))
+     put_dest (dc, 1);
+   else
+     put_dest (dc, 0);
+ 
+   /* 1011 1000 110w 0011		SCMPU.size */
+ 
+   ta0 = get_reg (a0);
+   ta1 = get_reg (a1);
+ 
+   for (;;)
+     {
+       t0 = mem_get_qi (ta0);
+       t2 = mem_get_qi (ta1);
+       if (w)
+ 	{
+ 	  t1 = mem_get_qi (ta0 + 1);
+ 	  t3 = mem_get_qi (ta1 + 1);
+ 	}
+       dif = t0 - t2;
+       if (dif == 0 && t0 != 0 && w)
+ 	dif = t1 - t3;
+       set_oszc (dif, 1, dif > 0);
+ 
+       ta0 += w ? 2 : 1;
+       ta1 += w ? 2 : 1;
+ 
+       if (t0 == 0 || t0 != t2)
+ 	break;
+       if (w && (t1 == 0 || t1 != t3))
+ 	break;
+     }
+ 
+   /* 1111 ddd w dd00 immm		SHA.size #IMM,dest */
+ 
+   prefix (0, 1, 0);
+   dc = decode_dest23 (ddd, dd, w+1);
+   shift_op (dc, 1, IMM4(), 1);
+ 
+   /* 1010 ddd0 dd10 0001		SHA.L #IMM,dest */
+ 
+   prefix (0, 1, 0);
+   dc = decode_dest23 (ddd, dd, 4);
+   imm = sign_ext (IMM(1), 8);
+   shift_op (dc, 1, imm, 1);
+ 
+   /* 1011 ddd w dd11 1110		SHA.size R1H,dest */
+ 
+   prefix (0, 1, 0);
+   dc = decode_dest23 (ddd, dd, w+1);
+   a = sign_ext (get_reg (r1h), 8);
+   shift_op (dc, 1, a, 1);
+ 
+   /* 1100 ddd0 dd01 0001		SHA.L	R1H,dest */
+ 
+   prefix (0, 1, 0);
+   dc = decode_dest23 (ddd, dd, 4);
+   a = sign_ext (get_reg (r1h), 8);
+   shift_op (dc, 1, a, 1);
+ 
+   /* 1100 ddd0 dd10 0001		SHANC.L #IMM,dest */
+ 
+   M32C_ONLY();
+   prefix (0, 1, 0);
+   dc = decode_dest23 (ddd, dd, 4);
+   imm = sign_ext (IMM(1), 8);
+   shift_op (dc, 1, imm, 0);
+ 
+   /* 1110 ddd w dd00 immm		SHL.size #IMM, dest */
+ 
+   prefix (0, 1, 0);
+   dc = decode_dest23 (ddd, dd, w+1);
+   shift_op (dc, 0, IMM4(), 1);
+ 
+   /* 1001 ddd0 dd10 0001		SHL.L #IMM, dest */
+ 
+   prefix (0, 1, 0);
+   dc = decode_dest23 (ddd, dd, 4);
+   imm = sign_ext (IMM(1), 8);
+   shift_op (dc, 0, imm, 1);
+ 
+   /* 1010 ddd w dd11 1110		SHL.size R1H,dest */
+ 
+   prefix (0, 1, 0);
+   dc = decode_dest23 (ddd, dd, w+1);
+   a = sign_ext (get_reg (r1h), 8);
+   shift_op (dc, 0, a, 1);
+ 
+   /* 1100 ddd0 dd00 0001		SHL.L R1H,dest */
+ 
+   prefix (0, 1, 0);
+   dc = decode_dest23 (ddd, dd, 4);
+   a = sign_ext (get_reg (r1h), 8);
+   shift_op (dc, 0, a, 1);
+ 
+   /* 1000 ddd0 dd10 0001		SHLNC.L #IMM,dest */
+ 
+   M32C_ONLY();
+   prefix (0, 1, 0);
+   dc = decode_dest23 (ddd, dd, 4);
+   imm = sign_ext (IMM(1), 8);
+   shift_op (dc, 0, imm, 0);
+ 
+   /* 1011 0010 100w 0011		SIN.size */
+ 
+   v = get_reg (a0);
+   a = get_reg (a1);
+   b = get_reg (r3);
+   if (b) for (;b;)
+     {
+       if (w)
+ 	mem_put_hi(a, mem_get_hi (v));
+       else
+ 	mem_put_qi(a, mem_get_qi (v));
+       a += w ? 2 : 1;
+       b --;
+     }
+   put_reg (a0, v);
+   put_reg (a1, a);
+   put_reg (r3, b);
+ 
+   /* 1011 0110 100w 0011		SMOVB.size */
+ 
+   v = get_reg (a0);
+   a = get_reg (a1);
+   b = get_reg (r3);
+   if (b) for (;b;)
+     {
+       if (w)
+ 	mem_put_hi(a, mem_get_hi (v));
+       else
+ 	mem_put_qi(a, mem_get_qi (v));
+       v -= w ? 2 : 1;
+       a -= w ? 2 : 1;
+       b --;
+     }
+   put_reg (a0, v);
+   put_reg (a1, a);
+   put_reg (r3, b);
+ 
+   /* 1011 0000 100w 0011		SMOVF.size */
+ 
+   v = get_reg (a0);
+   a = get_reg (a1);
+   b = get_reg (r3);
+   if (b) for (;b;)
+     {
+       if (w)
+ 	mem_put_hi(a, mem_get_hi (v));
+       else
+ 	mem_put_qi(a, mem_get_qi (v));
+       v += w ? 2 : 1;
+       a += w ? 2 : 1;
+       b --;
+     }
+   put_reg (a0, v);
+   put_reg (a1, a);
+   put_reg (r3, b);
+ 
+   /* 1011 1000 100w 0011		SMOVU.size */
+ 
+   v = get_reg (a0);
+   a = get_reg (a1);
+   do
+     {
+       if (w)
+ 	mem_put_hi(a, (t0 = mem_get_hi (v)));
+       else
+ 	mem_put_qi(a, (t0 = mem_get_qi (v)));
+       v += w ? 2 : 1;
+       a += w ? 2 : 1;
+       if (t0 == 0
+ 	  || (w && ((t0 & 0xff) == 0 || (t0 & 0xff00) == 0)))
+ 	break;
+     } while (1);
+   put_reg (a0, v);
+   put_reg (a1, a);
+ 
+   /* 1011 0100 100w 0011		SOUT.size */
+ 
+   v = get_reg (a0);
+   a = get_reg (a1);
+   b = get_reg (r3);
+   for (;b;)
+     {
+       if (w)
+ 	mem_put_hi(a, mem_get_hi (v));
+       else
+ 	mem_put_qi(a, mem_get_qi (v));
+       v += w ? 2 : 1;
+       b --;
+     }
+   put_reg (a0, v);
+   put_reg (a1, a);
+   put_reg (r3, b);
+ 
+   /* 1011 1000 000w 0011		SSTR.size */
+ 
+   a = get_reg (a1);
+   b = get_reg (r3);
+   for (;b;)
+     {
+       if (w)
+ 	mem_put_hi(a, r0);
+       else
+ 	mem_put_qi(a, r0 & 0xff);
+       a += w ? 2 : 1;
+       b --;
+     }
+   put_reg (a1, a);
+   put_reg (r3, b);
+ 
+   /* 0000 0001 1101 ddd1 dd01 0src	STC src,dest */
+ 
+   prefix (0, 0, 0);
+   dc = decode_dest23 (ddd, dd, 4);
+   sc = decode_cr_b (src, CR_B_DMA0);
+   a = get_src (sc);
+   put_dest (dc, a);
+ 
+   /* 0000 0001 1101 ddd1 dd01 1src	STC src,dest */
+ 
+   prefix (0, 0, 0);
+   dc = decode_dest23 (ddd, dd, 2);
+   sc = decode_cr_b (src, CR_B_DCT0);
+   a = get_src (sc);
+   put_dest (dc, a);
+ 
+   /* 1101 ddd1 dd01 0src		STC src,dest */
+ 
+   prefix (0, 0, 0);
+   dc = decode_dest23 (ddd, dd, 4);
+   sc = decode_cr_b (src, CR_B_INTB);
+   a = get_src (sc);
+   put_dest (dc, a);
+ 
+   /* 1011 0110 1101 0011		STCX abs16,abs24 */
+ 
+   NOTYET();
+ 
+   /* 1001 ddd w dd01 1111		STNZ.size #IMM,dest */
+ 
+   prefix (0, 1, 0);
+   dc = decode_dest23 (ddd, dd, w+1);
+   imm = IMM(w+1);
+   if (! FLAG_Z)
+     put_dest (dc, imm);
+ 
+   /* 1001 ddd w dd00 1111		STZ.size #IMM,dest */
+ 
+   prefix (0, 1, 0);
+   dc = decode_dest23 (ddd, dd, w+1);
+   imm = IMM(w+1);
+   if (FLAG_Z)
+     put_dest (dc, imm);
+ 
+   /* 1001 ddd w dd11 1111		STZX.size #IMM1,#IMM2,dest */
+ 
+   prefix (0, 1, 0);
+   dc = decode_dest23 (ddd, dd, w+1);
+   a = IMM(w+1);
+   b = IMM(w+1);
+   if (FLAG_Z)
+     put_dest (dc, a);
+   else
+     put_dest (dc, b);
+ 
+   /* 1000 ddd w dd11 1110		SUB.size:G #IMM,dest */
+ 
+   prefix (0, 1, 0);
+   dc = decode_dest23(ddd, dd, w+1);
+   imm = IMM(w+1);
+   MATH_OP (dc, imm, 0, -);
+ 
+   /* 1001 ddd0 dd11 0001		SUB.L:G #IMM,dest */
+ 
+   prefix (0, 1, 0);
+   dc = decode_dest23(ddd, dd, 4);
+   imm = IMM(4);
+   MATH_OP (dc, imm, 0, -);
+ 
+   /* 00dd 111w				SUB.size:S #IMM,dest */
+ 
+   prefix (0, 1, 0);
+   dc = decode_dest2(dd, w+1);
+   imm = IMM (w+1);
+   MATH_OP (dc, imm, 0, -);
+ 
+   /* 1sss ddd w dd ss 1010		SUB.size:G src,dest */
+ 
+   prefix (1, 1, 0);
+   sc = decode_src23(sss, ss, w+1);
+   dc = decode_dest23(ddd, dd, w+1);
+   b = get_src (sc);
+   MATH_OP (dc, b, 0, -);
+ 
+   /* 1sss ddd1 dd ss 0000		SUB.L:G src,dest */
+ 
+   prefix (1, 1, 0);
+   sc = decode_src23(sss, ss, 4);
+   dc = decode_dest23(ddd, dd, 4);
+   b = get_src (sc);
+   MATH_OP (dc, b, 0, -);
+ 
+   /* 1001 ddd0 dd01 0001		SUBX #IMM,dest */
+ 
+   prefix (0, 1, 0);
+   dc = decode_dest23(ddd, dd, 4);
+   imm = sign_ext (IMM(1), 8);
+   MATH_OP (dc, imm, 0, -);
+ 
+   /* 1sss ddd0 dd ss 0000		SUBX src,dest */
+ 
+   prefix (1, 1, 0);
+   sc = decode_src23(sss, ss, 1);
+   dc = decode_dest23(ddd, dd, 4);
+   b = sign_ext (get_src (sc), 8);
+   MATH_OP (dc, b, 0, -);
+ 
+   /* 1001 ddd w dd11 1110		TST.size:G #IMM,dest */
+ 
+   prefix (0, 0, 0);
+   dc = decode_dest23 (ddd, dd, w+1);
+   imm = IMM(w+1);
+   a = get_src (dc);
+   v = a & imm;
+   set_sz (v, w+1);
+ 
+   /* 00dd 110w				TST.size:S #IMM,dest */
+ 
+   prefix (0, 0, 0);
+   dc = decode_dest2 (dd, w+1);
+   imm = IMM(w+1);
+   a = get_src (dc);
+   v = a & imm;
+   set_sz (v, w+1);
+ 
+   /* 0000 0001 1sss ddd w dd ss 1001	TST.size:G src,dest */
+ 
+   prefix (0, 0, 0);
+   sc = decode_src23 (sss, ss, w+1);
+   dc = decode_dest23 (ddd, dd, w+1);
+   b = get_src (sc);
+   a = get_src (dc);
+   v = a & b;
+   set_sz (v, w+1);
+ 
+   /* 1111 1111				UND */
+ 
+   trigger_fixed_interrupt (0xffffdc);
+ 
+   /* 1011 0010 0000 0011		WAIT */
+ 
+   ;
+ 
+   /* 1101 ddd w dd00 1src		XCHG.size src,dest */
+ 
+   dc = decode_dest23 (ddd, dd, w+1);
+   sc = decode_src3 (src, w+1);
+   a = get_src (dc);
+   b = get_src (sc);
+   put_dest (dc, b);
+   put_dest (sc, a);
+ 
+   /* 1001 ddd w dd00 1110		XOR.size #IMM,dest */
+ 
+   prefix (0, 1, 0);
+   dc = decode_dest23(ddd, dd, w+1);
+   imm = IMM(w+1);
+   LOGIC_OP (dc, imm, ^);
+ 
+   /* 1sss ddd w dd ss 1001		XOR.size src,dest */
+ 
+   prefix (1, 1, 0);
+   sc = decode_src23(sss, ss, w+1);
+   dc = decode_dest23(ddd, dd, w+1);
+   b = get_src (sc);
+   LOGIC_OP (dc, b, ^);
+ 
+ /* */
+ 
+   return step_result;
+ }
Index: sim/m32c/main.c
===================================================================
RCS file: sim/m32c/main.c
diff -N sim/m32c/main.c
*** sim/m32c/main.c	1 Jan 1970 00:00:00 -0000
--- sim/m32c/main.c	6 Oct 2005 22:36:52 -0000
***************
*** 0 ****
--- 1,114 ----
+ #include <stdio.h>
+ #include <string.h>
+ #include <stdlib.h>
+ #include <unistd.h>
+ #include <assert.h>
+ #include <setjmp.h>
+ #include <signal.h>
+ 
+ #include "bfd.h"
+ 
+ #include "cpu.h"
+ #include "mem.h"
+ #include "misc.h"
+ #include "load.h"
+ #include "trace.h"
+ 
+ static int disassemble = 0;
+ static unsigned int cycles = 0;
+ 
+ static void
+ done(int exit_code)
+ {
+   if (verbose)
+     {
+       stack_heap_stats();
+       mem_usage_stats();
+       printf("insns: %14s\n", comma(cycles));
+     }
+   exit(exit_code);
+ }
+ 
+ int
+ main(int argc, char **argv)
+ {
+   int o;
+   int save_trace;
+   bfd *prog;
+ 
+   while ((o = getopt(argc, argv, "tvdm:")) != -1)
+     switch (o)
+       {
+       case 't':
+ 	trace ++;
+ 	break;
+       case 'v':
+ 	verbose ++;
+ 	break;
+       case 'd':
+ 	disassemble ++;
+ 	break;
+       case 'm':
+ 	if (strcmp (optarg, "r8c") == 0
+ 	    || strcmp (optarg, "m16c") == 0)
+ 	  default_machine = bfd_mach_m16c;
+ 	else if (strcmp (optarg, "m32cm") == 0
+ 	    || strcmp (optarg, "m32c") == 0)
+ 	  default_machine = bfd_mach_m32c;
+ 	else
+ 	  {
+ 	    fprintf(stderr, "Invalid machine: %s\n", optarg);
+ 	    exit(1);
+ 	  }
+ 	break;
+       case '?':
+ 	fprintf(stderr, "usage: run [-v] [-t] [-d] [-m r8c||m16c|m32cm|m32c] program\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 m32c program\n", argv[optind]);
+       exit(1);
+     }
+ 
+   save_trace = trace;
+   trace = 0;
+   m32c_load (prog);
+   trace = save_trace;
+ 
+   if (disassemble)
+     sim_disasm_init (prog);
+ 
+   while (1)
+     {
+       int rc;
+ 
+       if (trace)
+ 	printf("\n");
+ 
+       if (disassemble)
+ 	sim_disasm_one();
+ 
+       enable_counting = verbose;
+       cycles ++;
+       rc = decode_opcode ();
+       enable_counting = 0;
+ 
+       if (M32C_HIT_BREAK (rc))
+ 	done(1);
+       else if (M32C_EXITED (rc))
+ 	done(M32C_EXIT_STATUS (rc));
+       else
+ 	assert (M32C_STEPPED (rc));
+ 
+       trace_register_changes ();
+     }
+ }
Index: sim/m32c/mem.c
===================================================================
RCS file: sim/m32c/mem.c
diff -N sim/m32c/mem.c
*** sim/m32c/mem.c	1 Jan 1970 00:00:00 -0000
--- sim/m32c/mem.c	6 Oct 2005 22:36:52 -0000
***************
*** 0 ****
--- 1,347 ----
+ #include <stdio.h>
+ #include <stdlib.h>
+ #include <string.h>
+ 
+ #include "mem.h"
+ #include "cpu.h"
+ #include "syscalls.h"
+ #include "misc.h"
+ 
+ #define L1_BITS  (10)
+ #define L2_BITS  (10)
+ #define OFF_BITS (12)
+ 
+ #define L1_LEN  (1 << L1_BITS)
+ #define L2_LEN  (1 << L2_BITS)
+ #define OFF_LEN (1 << OFF_BITS)
+ 
+ static unsigned char **pt[L1_LEN];
+ 
+ /* [ get=0/put=1 ][ byte size ] */
+ static unsigned int mem_counters[2][4];
+ 
+ #define COUNT(isput,bytes) if (verbose && enable_counting) mem_counters[isput][bytes]++
+ 
+ void
+ init_mem (void)
+ {
+   int i, j;
+ 
+   for (i = 0; i < L1_LEN; i++)
+     if (pt[i])
+       {
+ 	for (j = 0; j < L2_LEN; j++)
+ 	  if (pt[i][j])
+ 	    free (pt[i][j]);
+ 	free (pt[i]);
+       }
+   memset (pt, 0, sizeof (pt));
+   memset (mem_counters, 0, sizeof (mem_counters));
+ }
+ 
+ static unsigned char *
+ mem_ptr (address)
+ {
+   int pt1 = (address >> (L2_BITS + OFF_BITS)) & ((1 << L1_BITS) - 1);
+   int pt2 = (address >>            OFF_BITS ) & ((1 << L2_BITS) - 1);
+   int pto = address & ((1 << OFF_BITS) - 1);
+ 
+   if (address == 0)
+     {
+       printf("NULL pointer dereference\n");
+       exit(1);
+     }
+ 
+   if (pt[pt1] == 0)
+     pt[pt1] = (unsigned char **) calloc (L2_LEN, sizeof(char **));
+   if (pt[pt1][pt2] == 0)
+     {
+       pt[pt1][pt2] = (unsigned char *) malloc (OFF_LEN);
+       memset (pt[pt1][pt2], 0, OFF_LEN);
+     }
+ 
+   return pt[pt1][pt2] + pto;
+ }
+ 
+ static void
+ used (int rstart, int i, int j)
+ {
+   int rend = i << (L2_BITS + OFF_BITS);
+   rend += j << OFF_BITS;
+   if (rstart == 0xe0000 && rend == 0xe1000)
+     return;
+   printf("mem:   %08x - %08x (%dk bytes)\n", rstart, rend-1, (rend-rstart)/1024);
+ }
+ 
+ static char *
+ mcs(int isput, int bytes)
+ {
+   return comma(mem_counters[isput][bytes]);
+ }
+ 
+ void
+ mem_usage_stats ()
+ {
+   int i, j;
+   int rstart=0;
+   int pending = 0;
+ 
+   for (i = 0; i < L1_LEN; i++)
+     if (pt[i])
+       {
+ 	for (j = 0; j < L2_LEN; j++)
+ 	  if (pt[i][j])
+ 	    {
+ 	      if (!pending)
+ 		{
+ 		  pending = 1;
+ 		  rstart = (i << (L2_BITS + OFF_BITS)) + (j << OFF_BITS);
+ 		}
+ 	    }
+ 	  else if (pending)
+ 	    {
+ 	      pending = 0;
+ 	      used(rstart, i, j);
+ 	    }
+       }
+     else
+       {
+ 	if (pending)
+ 	  {
+ 	    pending = 0;
+ 	    used(rstart, i, 0);
+ 	  }
+       }
+   /*      mem foo: 123456789012 123456789012 123456789012 123456789012 123456789012 */
+   printf("                 byte        short      pointer         long        fetch\n");
+   printf("mem get: %12s %12s %12s %12s %12s\n",
+ 	 mcs (0, 1), mcs (0, 2), mcs (0, 3), mcs (0, 4), mcs (0, 0));
+   printf("mem put: %12s %12s %12s %12s\n",
+ 	 mcs (1, 1), mcs (1, 2), mcs (1, 3), mcs (1, 4));
+ }
+ 
+ static int tpr = 0;
+ static void
+ s (int address, char *dir)
+ {
+   if (tpr == 0)
+     printf("MEM[%0*x] %s", membus_mask == 0xfffff ? 5 : 6, address, dir);
+   tpr++;
+ }
+ #define S(d) if (trace) s(address, d)
+ static void
+ e()
+ {
+   if (!trace)
+     return;
+   tpr--;
+   if (tpr == 0)
+     printf("\n");
+ }
+ #define E() if (trace) e()
+ 
+ void
+ mem_put_byte (int address, unsigned char value)
+ {
+   unsigned char *m;
+   address &= membus_mask;
+   m = mem_ptr(address);
+   if (trace)
+     printf(" %02x", value);
+   *m = value;
+   switch (address)
+     {
+     case 0x00e1:
+       {
+ 	static int old_led = -1;
+ 	static char *led_on[]  = {"\033[31m O ", "\033[32m O ", "\033[34m O "};
+ 	static char *led_off[] = {"\033[0m · ", "\033[0m · ", "\033[0m · "};
+ 	int i;
+ 	if (old_led != value)
+ 	  {
+ 	    fputs("  ", stdout);
+ 	    for (i=0; i<3; i++)
+ 	      if (value & (1<<i))
+ 		fputs(led_off[i], stdout);
+ 	      else
+ 		fputs(led_on[i], stdout);
+ 	    fputs("\033[0m\r", stdout);
+ 	    fflush(stdout);
+ 	    old_led = value;
+ 	  }
+       }
+       break;
+ 
+     case 0x400:
+       m32c_syscall (value);
+       break;
+ 
+     case 0x401:
+       putchar (value);
+       break;
+ 
+     case 0x402:
+       printf ("SimTrace: %06lx %02x\n", regs.r_pc, value);
+       break;
+ 
+     case 0x403:
+       printf ("SimTrap: %06lx %02x\n", regs.r_pc, value);
+       abort ();
+     }
+ }
+ 
+ void
+ mem_put_qi (int address, unsigned char value)
+ {
+   S ("<=");
+   mem_put_byte (address, value & 0xff);
+   E ();
+   COUNT(1,1);
+ }
+ 
+ void
+ mem_put_hi (int address, unsigned short value)
+ {
+   S ("<=");
+   mem_put_byte (address, value & 0xff);
+   mem_put_byte (address+1, value >> 8);
+   E ();
+   COUNT(1,2);
+ }
+ 
+ void
+ mem_put_psi (int address, unsigned long value)
+ {
+   S ("<=");
+   mem_put_byte (address, value & 0xff);
+   mem_put_byte (address+1, (value >> 8) & 0xff);
+   mem_put_byte (address+2, value >> 16);
+   E ();
+   COUNT(1,3);
+ }
+ 
+ void
+ mem_put_si (int address, unsigned long value)
+ {
+   S("<=");
+   mem_put_byte (address, value & 0xff);
+   mem_put_byte (address+1, (value >> 8) & 0xff);
+   mem_put_byte (address+2, (value >> 16) & 0xff);
+   mem_put_byte (address+3, (value >> 24) & 0xff);
+   E();
+   COUNT(1,4);
+ }
+ 
+ void
+ mem_put_blk (int address, void *bufptr, int nbytes)
+ {
+   S("<=");
+   if (enable_counting)
+     mem_counters[1][1] += nbytes;
+   while (nbytes--)
+     mem_put_byte (address++, *(unsigned char *)bufptr++);
+   E();
+ }
+ 
+ unsigned char
+ mem_get_pc ()
+ {
+   unsigned char *m = mem_ptr(regs.r_pc & membus_mask);
+   COUNT(0,0);
+   return *m;
+ }
+ 
+ static unsigned char
+ mem_get_byte (int address)
+ {
+   unsigned char *m;
+   address &= membus_mask;
+   S("=>");
+   m = mem_ptr(address);
+   if (trace)
+     {
+       if (tpr)
+ 	printf(" %02x", *m);
+       else
+ 	{
+ 	  S("=>");
+ 	  printf(" %02x", *m);
+ 	  E();
+ 	}
+     }
+   E();
+   return *m;
+ }
+ 
+ unsigned char
+ mem_get_qi (int address)
+ {
+   unsigned char rv;
+   S("=>");
+   rv = mem_get_byte (address);
+   COUNT(0,1);
+   E();
+   return rv;
+ }
+ 
+ unsigned short
+ mem_get_hi (int address)
+ {
+   unsigned short rv;
+   S("=>");
+   rv = mem_get_byte (address);
+   rv |= mem_get_byte (address+1) * 256;
+   COUNT(0,2);
+   E();
+   return rv;
+ }
+ 
+ unsigned long
+ mem_get_psi (int address)
+ {
+   unsigned long rv;
+   S("=>");
+   rv = mem_get_byte (address);
+   rv |= mem_get_byte (address+1) * 256;
+   rv |= mem_get_byte (address+2) * 65536;
+   COUNT(0,3);
+   E();
+   return rv;
+ }
+ 
+ unsigned long
+ mem_get_si (int address)
+ {
+   unsigned long rv;
+   S("=>");
+   rv = mem_get_byte (address);
+   rv |= mem_get_byte (address + 1) << 8;
+   rv |= mem_get_byte (address + 2) << 16;
+   rv |= mem_get_byte (address + 3) << 24;
+   COUNT(0,4);
+   E();
+   return rv;
+ }
+ 
+ void
+ mem_get_blk (int address, void *bufptr, int nbytes)
+ {
+   S("=>");
+   if (enable_counting)
+     mem_counters[0][1] += nbytes;
+   while (nbytes--)
+     *(char *)bufptr++ = mem_get_byte (address++);
+   E();
+ }
+ 
+ int
+ sign_ext(int v, int bits)
+ {
+   if (bits < 32)
+     {
+       v &= (1<<bits) - 1;
+       if (v & (1<<(bits-1)))
+ 	v -= (1<<bits);
+     }
+   return v;
+ }
Index: sim/m32c/mem.h
===================================================================
RCS file: sim/m32c/mem.h
diff -N sim/m32c/mem.h
*** sim/m32c/mem.h	1 Jan 1970 00:00:00 -0000
--- sim/m32c/mem.h	6 Oct 2005 22:36:52 -0000
***************
*** 0 ****
--- 1,20 ----
+ void init_mem (void);
+ void mem_usage_stats (void);
+ 
+ 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, void *bufptr, int nbytes);
+ 
+ unsigned char mem_get_pc ();
+ 
+ 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/m32c/misc.c
===================================================================
RCS file: sim/m32c/misc.c
diff -N sim/m32c/misc.c
*** sim/m32c/misc.c	1 Jan 1970 00:00:00 -0000
--- sim/m32c/misc.c	6 Oct 2005 22:36:52 -0000
***************
*** 0 ****
--- 1,54 ----
+ #include <stdio.h>
+ 
+ #include "cpu.h"
+ #include "misc.h"
+ 
+ int
+ bcd2int (int bcd, int w)
+ {
+   int v=0, m=1, i;
+   for (i = 0; i < (w ? 4 : 2); i++)
+     {
+       v += (bcd % 16) * m;
+       m *= 10;
+       bcd /= 16;
+     }
+   return v;
+ }
+ 
+ int
+ int2bcd (int v, int w)
+ {
+   int bcd=0, m=1, i;
+   for (i = 0; i < (w ? 4 : 2); i++)
+     {
+       bcd += (v % 10) * m;
+       m *= 16;
+       v /= 10;
+     }
+   return bcd;
+ }
+ 
+ char *
+ comma(unsigned int u)
+ {
+   static char buf[5][20];
+   static int bi = 0;
+   int comma=0;
+   char *bp;
+ 
+   bi = (bi+1) % 5;
+   bp = buf[bi] + 19;
+   *--bp = 0;
+   do {
+     if (comma == 3)
+       {
+ 	*--bp = ',';
+ 	comma = 0;
+       }
+     comma ++;
+     *--bp = '0' + (u % 10);
+     u /= 10;
+   } while (u);
+   return bp;
+ }
Index: sim/m32c/misc.h
===================================================================
RCS file: sim/m32c/misc.h
diff -N sim/m32c/misc.h
*** sim/m32c/misc.h	1 Jan 1970 00:00:00 -0000
--- sim/m32c/misc.h	6 Oct 2005 22:36:52 -0000
***************
*** 0 ****
--- 1,4 ----
+ int bcd2int (int bcd, int w);
+ int int2bcd (int val, int w);
+ 
+ char *comma (unsigned int u);
Index: sim/m32c/opc2c.c
===================================================================
RCS file: sim/m32c/opc2c.c
diff -N sim/m32c/opc2c.c
*** sim/m32c/opc2c.c	1 Jan 1970 00:00:00 -0000
--- sim/m32c/opc2c.c	6 Oct 2005 22:36:52 -0000
***************
*** 0 ****
--- 1,693 ----
+ #include <stdio.h>
+ #include <string.h>
+ #include <ctype.h>
+ #include <stdlib.h>
+ 
+ #include "safe-fgets.h"
+ 
+ static int errors = 0;
+ 
+ #define MAX_BYTES 10
+ 
+ typedef struct {
+   int varyno:16;
+   int byte:8;
+   int shift:8;
+ } VaryRef;
+ 
+ typedef struct {
+   char nbytes;
+   char dbytes;
+   char id[MAX_BYTES*8+1];
+   unsigned char var_start[MAX_BYTES*8+1];
+   struct {
+     unsigned char decodable_mask;
+     unsigned char decodable_bits;
+   } b[MAX_BYTES];
+   char *comment;
+   int lineno;
+   int nlines;
+   char **lines;
+   struct Indirect *last_ind;
+   int semantics_label;
+   int nvaries;
+   VaryRef *vary;
+ } opcode;
+ 
+ int n_opcodes;
+ opcode **opcodes;
+ opcode *op;
+ 
+ typedef struct {
+   char *name;
+   int nlen;
+   unsigned char mask;
+   int n_patterns;
+   unsigned char *patterns;
+ } Vary;
+ 
+ Vary **vary = 0;
+ int n_varies = 0;
+ 
+ unsigned char cur_bits[MAX_BYTES+1];
+ 
+ char *orig_filename;
+ 
+ FILE *sim_log = 0;
+ #define lprintf if (sim_log) fprintf
+ 
+ opcode prefix_text, suffix_text;
+ 
+ typedef enum {
+   T_unused,
+   T_op,
+   T_indirect,
+   T_done
+ } OpType;
+ 
+ typedef struct Indirect {
+   OpType type;
+   union {
+     struct Indirect *ind;
+     opcode *op;
+   } u;
+ } Indirect;
+ 
+ Indirect indirect[256];
+ 
+ static int
+ next_varybits (int bits, opcode *op, int byte)
+ {
+   int mask = op->b[byte].decodable_mask;
+   int i;
+ 
+   for (i=0; i<8; i++)
+     if (!(mask & (1<<i)))
+       {
+ 	if (bits & (1<<i))
+ 	  {
+ 	    bits &= ~(1<<i);
+ 	  }
+ 	else
+ 	  {
+ 	    bits |= (1<<i);
+ 	    return bits;
+ 	  }
+       }
+   return 0;
+ }
+ 
+ static int
+ valid_varybits (int bits, opcode *op, int byte)
+ {
+   if (op->nvaries)
+     {
+       int vn;
+       for (vn=0; vn<op->nvaries; vn++)
+ 	{
+ 	  int found = 0;
+ 	  int i;
+ 	  int ob;
+ 
+ 	  if (byte != op->vary[vn].byte)
+ 	    continue;
+ 	  Vary *v = vary[op->vary[vn].varyno];
+ 	  ob = (bits >> op->vary[vn].shift) & v->mask;
+ 	  lprintf(sim_log, "varybits: vary %s ob %x\n", v->name, ob);
+ 
+ 	  for (i=0; i<v->n_patterns; i++)
+ 	    if (ob == v->patterns[i])
+ 	      {
+ 		lprintf(sim_log, "  found at %d\n", i);
+ 		found = 1;
+ 		break;
+ 	      }
+ 	  if (!found)
+ 	    return 0;
+ 	}
+     }
+   return 1;
+ }
+ 
+ char *
+ prmb (int mask, int bits)
+ {
+   static char buf[8][30];
+   static int bn = 0;
+   char *bp;
+ 
+   bn = (bn+1) % 8;
+   bp = buf[bn];
+   int i;
+   for (i=0; i<8; i++)
+     {
+       int bit = 0x80 >> i;
+       if (! (mask & bit))
+ 	*bp++ = '-';
+       else if (bits & bit)
+ 	*bp++ = '1';
+       else
+ 	*bp++ = '0';
+       if (i % 4 == 3)
+ 	*bp++ = ' ';
+     }
+   *--bp = 0;
+   return buf[bn];
+ }
+ 
+ static int
+ op_cmp (const void *va, const void *vb)
+ {
+   const opcode *a = *(const opcode **)va;
+   const opcode *b = *(const opcode **)vb;
+ 
+   if (a->nbytes != b->nbytes)
+     return a->nbytes - b->nbytes;
+ 
+   return strcmp (a->id, b->id);
+ }
+ 
+ void
+ dump_lines (opcode *op, int level, Indirect *ind)
+ {
+   char *varnames[40];
+   int i, vn=0;
+ 
+   if (op->semantics_label)
+     {
+       printf("%*sgoto op_semantics_%d;\n", level, "", op->semantics_label);
+       return;
+     }
+ 
+   if (ind != op->last_ind)
+     {
+       static int labelno = 0;
+       labelno ++;
+       printf("%*sop_semantics_%d:\n", level, "", labelno);
+       op->semantics_label = labelno;
+     }
+ 
+   if (op->comment) {
+     level += 2;
+     printf("%*s{\n", level, "");
+     printf("%*s  %s\n", level, "", op->comment);
+   }
+ 
+   for (i=0; i<op->nbytes*8;)
+     {
+       if (isalpha(op->id[i]))
+ 	{
+ 	  int byte = i >> 3;
+ 	  int mask = 0;
+ 	  int shift = 0;
+ 	  char name[33];
+ 	  char *np = name;
+ 	  while (op->id[i] && isalpha(op->id[i]))
+ 	    {
+ 	      mask = (mask << 1) | 1;
+ 	      shift = 7 - (i & 7);
+ 	      *np++ = op->id[i++];
+ 	      if (op->var_start[i])
+ 		break;
+ 	    }
+ 	  *np = 0;
+ 	  varnames[vn++] = strdup (name);
+ 	  printf("#line %d \"%s\"\n", op->lineno, orig_filename);
+ 	  if (mask & ~0xff)
+ 	    {
+ 	      fprintf (stderr, "Error: variable %s spans bytes: %s\n",
+ 		       name, op->comment);
+ 	      errors ++;
+ 	    }
+ 	  else if (shift && (mask != 0xff))
+ 	    printf("%*s  int %s AU = (op[%d] >> %d) & 0x%02x;\n",
+ 		   level, "", name, byte, shift, mask);
+ 	  else if (mask != 0xff)
+ 	    printf("%*s  int %s AU = op[%d] & 0x%02x;\n",
+ 		   level, "", name, byte, mask);
+ 	  else
+ 	    printf("%*s  int %s AU = op[%d];\n",
+ 		   level, "", name, byte);
+ 	}
+       else
+ 	i++;
+     }
+   if (op->comment)
+     {
+       printf("%*s  if (trace) {\n", level, "");
+       printf("%*s      printf(\"\\033[33m%%s\\033[0m ", level, "");
+       for (i=0; i<op->nbytes; i++)
+ 	printf(" %%02x");
+       printf("\\n\"");
+       printf(",\n%*s             \"%s\"", level, "", op->comment);
+       for (i=0; i<op->nbytes; i++)
+ 	{
+ 	  if (i == 0)
+ 	    printf(",\n%*s             op[%d]", level, "", i);
+ 	  else
+ 	    printf(", op[%d]", i);
+ 	}
+       printf(");\n");
+       for (i=0; i<vn; i++)
+ 	printf("%*s      printf(\"  %s = 0x%%x%s\", %s);\n", level, "", varnames[i],
+ 	       (i<vn-1)?",":"\\n", varnames[i]);
+       printf("%*s    }\n", level, "");
+     }
+   printf("#line %d \"%s\"\n", op->lineno+1, orig_filename);
+   for (i=0; i<op->nlines; i++)
+     printf("%*s%s", level, "", op->lines[i]);
+   if (op->comment)
+     printf("%*s}\n", level, "");
+ }
+ 
+ void
+ store_opcode_bits (opcode *op, int byte, Indirect *ind)
+ {
+   int bits = op->b[byte].decodable_bits;
+ 
+   do {
+     if (!valid_varybits (bits, op, byte))
+       continue;
+ 
+     switch (ind[bits].type)
+       {
+       case T_unused:
+ 	if (byte == op->dbytes-1)
+ 	  {
+ 	    ind[bits].type = T_op;
+ 	    ind[bits].u.op = op;
+ 	    op->last_ind = ind;
+ 	    break;
+ 	  }
+ 	else
+ 	  {
+ 	    int i2;
+ 	    ind[bits].type = T_indirect;
+ 	    ind[bits].u.ind = (Indirect *)malloc (256*sizeof(Indirect));
+ 	    for (i2=0; i2<256; i2++)
+ 	      ind[bits].u.ind[i2].type = T_unused;
+ 	    store_opcode_bits (op, byte+1, ind[bits].u.ind);
+ 	  }
+ 	break;
+ 
+       case T_indirect:
+ 	if (byte < op->dbytes-1)
+ 	  store_opcode_bits (op, byte+1, ind[bits].u.ind);
+ 	break;
+ 
+       case T_op:
+ 	break;
+ 
+       case T_done:
+ 	break;
+       }
+   } while ((bits = next_varybits (bits, op, byte)) != 0);
+ }
+ 
+ void
+ emit_indirect (Indirect *ind, int byte)
+ {
+   int unsup = 0;
+   int j, n, mask;
+ 
+   mask = 0;
+   for (j=0; j<256; j++)
+     {
+       switch (ind[j].type)
+ 	{
+ 	case T_indirect:
+ 	  mask = 0xff;
+ 	  break;
+ 	case T_op:
+ 	  mask |= ind[j].u.op->b[byte].decodable_mask;
+ 	  break;
+ 	case T_done:
+ 	case T_unused:
+ 	  break;
+ 	}
+     }
+ 
+   printf("%*s  GETBYTE();\n", byte*6, "");
+   printf("%*s  switch (op[%d] & 0x%02x) {\n", byte*6, "", byte, mask);
+   for (j=0; j<256; j++)
+     if ((j & ~mask) == 0)
+       {
+ 	switch (ind[j].type)
+ 	  {
+ 	  case T_done:
+ 	    break;
+ 	  case T_unused:
+ 	    unsup = 1;
+ 	    break;
+ 	  case T_op:
+ 	    for (n = j; n < 256; n++)
+ 	      if ((n & ~mask) == 0
+ 		  && ind[n].type == T_op
+ 		  && ind[n].u.op == ind[j].u.op)
+ 		{
+ 		  ind[n].type = T_done;
+ 		  printf("%*s    case 0x%02x:\n", byte*6, "", n);
+ 		}
+ 	    for (n=byte; n<ind[j].u.op->nbytes-1; n++)
+ 	      printf("%*s      GETBYTE();\n", byte*6, "");
+ 	    dump_lines(ind[j].u.op, byte*6+6, ind);
+ 	    printf("%*s      break;\n", byte*6, "");
+ 	    break;
+ 	  case T_indirect:
+ 	    printf("%*s    case 0x%02x:\n", byte*6, "", j);
+ 			     emit_indirect (ind[j].u.ind, byte+1);
+ 			     printf("%*s      break;\n", byte*6, "");
+ 			     break;
+ 	  }
+       }
+   if (unsup)
+     printf("%*s    default: UNSUPPORTED(); break;\n", byte*6, "");
+   printf("%*s  }\n", byte*6, "");
+ }
+ 
+ static char *
+ pv_dup (char *p, char *ep)
+ {
+   int n = ep - p;
+   char *rv = (char *) malloc (n + 1);
+   memcpy (rv, p, n);
+   rv[n] = 0;
+   return rv;
+ }
+ 
+ static unsigned char
+ str2mask (char *str, char *ep)
+ {
+   unsigned char rv = 0;
+   while (str < ep)
+     {
+       rv *= 2;
+       if (*str == '1')
+ 	rv += 1;
+       str ++;
+     }
+   return rv;
+ }
+ 
+ static void
+ process_vary (char *line)
+ {
+   char *cp, *ep;
+   Vary *v = (Vary *) malloc (sizeof (Vary));
+ 
+   n_varies ++;
+   if (vary)
+     vary = (Vary **) realloc (vary, n_varies * sizeof (Vary *));
+   else
+     vary = (Vary **) malloc (n_varies * sizeof (Vary *));
+   vary[n_varies-1] = v;
+ 
+   cp = line;
+ 
+   for (cp = line; isspace(*cp); cp++) ;
+   for (ep=cp; *ep && !isspace(*ep); ep++) ;
+ 
+   v->name = pv_dup (cp, ep);
+   v->nlen = strlen (v->name);
+   v->mask = (1 << v->nlen) - 1;
+ 
+   v->n_patterns = 0;
+   v->patterns = (unsigned char *) malloc (1);
+   while (1)
+     {
+       for (cp = ep; isspace(*cp); cp++) ;
+       if (! isdigit (*cp))
+ 	break;
+       for (ep=cp; *ep && !isspace(*ep); ep++) ;
+       v->n_patterns ++;
+       v->patterns = (unsigned char *) realloc (v->patterns, v->n_patterns);
+       v->patterns[v->n_patterns-1] = str2mask (cp, ep);
+     }
+ }
+ 
+ static int
+ fieldcmp (opcode *op, int bit, char *name)
+ {
+   int n = strlen (name);
+   if (memcmp (op->id + bit, name, n) == 0
+       && (!isalpha(op->id[bit+n])
+ 	  || op->var_start[bit+n]))
+     return 1;
+   return 0;
+ }
+ 
+ static void
+ log_indirect (Indirect *ind, int byte)
+ {
+   int i, j;
+   char *last_c = 0;
+ 
+   for (i=0; i<256; i++)
+     {
+       if (ind[i].type == T_unused)
+ 	continue;
+ 
+       for (j=0; j<byte; j++)
+ 	fprintf(sim_log, "%s ", prmb(255, cur_bits[j]));
+       fprintf(sim_log, "%s ", prmb(255, i));
+ 
+       switch (ind[i].type)
+ 	{
+ 	case T_op:
+ 	case T_done:
+ 	  if (last_c && (ind[i].u.op->comment == last_c))
+ 	    fprintf(sim_log, "''\n");
+ 	  else
+ 	    fprintf(sim_log, "%s\n", ind[i].u.op->comment);
+ 	  last_c = ind[i].u.op->comment;
+ 	  break;
+ 	case T_unused:
+ 	  fprintf(sim_log, "-\n");
+ 	  break;
+ 	case T_indirect:
+ 	  fprintf(sim_log, "indirect\n");
+ 	  cur_bits[byte] = i;
+ 	  log_indirect (ind[i].u.ind, byte+1);
+ 	  last_c = 0;
+ 	  break;
+ 	}
+     }
+ }
+ 
+ int
+ main(int argc, char **argv)
+ {
+   char *line;
+   FILE *in;
+   int lineno = 0;
+   int i;
+   VaryRef *vlist;
+ 
+   if (argc > 2 && strcmp (argv[1], "-l") == 0)
+     {
+       sim_log = fopen(argv[2], "w");
+       fprintf(stderr, "sim_log: %s\n", argv[2]);
+       argc -= 2;
+       argv += 2;
+     }
+ 
+   if (argc < 2)
+     {
+       fprintf(stderr, "usage: opc2c infile.opc > outfile.opc\n");
+       exit(1);
+     }
+ 
+   orig_filename = argv[1];
+   in = fopen (argv[1], "r");
+   if (!in)
+     {
+       fprintf(stderr, "Unable to open file %s for reading\n", argv[1]);
+       perror("The error was");
+       exit(1);
+     }
+ 
+   n_opcodes = 0;
+   opcodes = (opcode **)malloc(sizeof(opcode *));
+   op = &prefix_text;
+   op->lineno = 1;
+   while ((line = safe_fgets (in)) != 0)
+     {
+       lineno ++;
+       if (strncmp (line, "  /* ", 5) == 0
+ 	  && (isdigit (line[5]) || memcmp (line+5, "VARY", 4) == 0))
+ 	line += 2;
+       if (line[0] == '/' && line[1] == '*')
+ 	{
+ 	  if (strncmp (line, "/* */", 5) == 0)
+ 	    {
+ 	      op = &suffix_text;
+ 	      op->lineno = lineno;
+ 	    }
+ 	  else if (strncmp (line, "/* VARY ", 8) == 0)
+ 	    process_vary (line+8);
+ 	  else
+ 	    {
+ 	      char *lp;
+ 	      int i, bit, byte;
+ 	      int var_start = 1;
+ 
+ 	      n_opcodes ++;
+ 	      opcodes = (opcode **) realloc (opcodes, n_opcodes * sizeof (opcode *));
+ 	      op = (opcode *) malloc (sizeof (opcode));
+ 	      opcodes[n_opcodes - 1] = op;
+ 
+ 	      op->nbytes = op->dbytes = 0;
+ 	      memset (op->id, 0, sizeof(op->id));
+ 	      memset (op->var_start, 0, sizeof(op->var_start));
+ 	      for (i=0; i<MAX_BYTES; i++)
+ 		{
+ 		  op->b[i].decodable_mask = 0;
+ 		  op->b[i].decodable_bits = 0;
+ 		}
+ 	      op->comment = strdup (line);
+ 	      op->comment[strlen(op->comment)-1] = 0;
+ 	      while (op->comment[0] && isspace (op->comment[0]))
+ 		op->comment ++;
+ 	      op->lineno = lineno;
+ 	      op->nlines = 0;
+ 	      op->lines = 0;
+ 	      op->last_ind = 0;
+ 	      op->semantics_label = 0;
+ 	      op->nvaries = 0;
+ 	      op->vary = 0;
+ 
+ 	      i = 0;
+ 	      for (lp = line+3; *lp; lp++)
+ 		{
+ 		  bit = 7 - (i & 7);
+ 		  byte = i >> 3;
+ 
+ 		  if (strncmp (lp, "*/", 2) == 0)
+ 		    break;
+ 		  else if ((lp[0] == ' ' && lp[1] == ' ') || (lp[0] == '\t'))
+ 		    break;
+ 		  else if (*lp == ' ')
+ 		    var_start = 1;
+ 		  else
+ 		    {
+ 		      if (*lp == '0' || *lp == '1')
+ 			{
+ 			  op->b[byte].decodable_mask |= 1 << bit;
+ 			  var_start = 1;
+ 			  if (op->dbytes < byte+1)
+ 			    op->dbytes = byte+1;
+ 			}
+ 		      else if (var_start)
+ 			{
+ 			  op->var_start[i] = 1;
+ 			  var_start = 0;
+ 			}
+ 		      if (*lp == '1')
+ 			op->b[byte].decodable_bits |= 1 << bit;
+ 
+ 		      op->nbytes = byte + 1;
+ 		      op->id[i++] = *lp;
+ 		    }
+ 		}
+ 	    }
+ 	}
+       else
+ 	{
+ 	  op->nlines ++;
+ 	  if (op->lines)
+ 	    op->lines = (char **) realloc (op->lines, op->nlines * sizeof (char *));
+ 	  else
+ 	    op->lines = (char **) malloc (op->nlines * sizeof (char *));
+ 	  op->lines[op->nlines-1] = strdup (line);
+ 	}
+     }
+ 
+   {
+     int i, j;
+     for (i=0; i<n_varies; i++)
+       {
+ 	Vary *v = vary[i];
+ 	lprintf(sim_log, "V[%s] %d\n", v->name, v->nlen);
+ 	for (j=0; j<v->n_patterns; j++)
+ 	  lprintf(sim_log, "  P %02x\n", v->patterns[j]);
+       }
+   }
+ 
+   for (i=n_opcodes-2; i>= 0; i--)
+     {
+       if (opcodes[i]->nlines == 0)
+ 	{
+ 	  opcodes[i]->nlines = opcodes[i+1]->nlines;
+ 	  opcodes[i]->lines = opcodes[i+1]->lines;
+ 	}
+     }
+ 
+   for (i=0; i<256; i++)
+     indirect[i].type = T_unused;
+ 
+   qsort (opcodes, n_opcodes, sizeof(opcodes[0]), op_cmp);
+ 
+   vlist = (VaryRef *) malloc (n_varies * sizeof (VaryRef));
+ 
+   for (i=0; i<n_opcodes; i++)
+     {
+       int j, b, v;
+ 
+       for (j=0; j<opcodes[i]->nbytes; j++)
+ 	lprintf(sim_log, "%s ", prmb(opcodes[i]->b[j].decodable_mask, opcodes[i]->b[j].decodable_bits));
+       lprintf(sim_log, " %s\n", opcodes[i]->comment);
+ 
+       for (j=0; j<opcodes[i]->nbytes; j++)
+ 	{
+ 	  for (b=0; b<8; b++)
+ 	    if (isalpha (opcodes[i]->id[j*8+b]))
+ 	      for (v=0; v<n_varies; v++)
+ 		if (fieldcmp (opcodes[i], j*8+b,
+ 			      vary[v]->name))
+ 		  {
+ 		    int nv = opcodes[i]->nvaries ++;
+ 		    if (nv)
+ 		      opcodes[i]->vary = (VaryRef *) realloc (opcodes[i]->vary, (nv+1) * sizeof(VaryRef));
+ 		    else
+ 		      opcodes[i]->vary = (VaryRef *) malloc ((nv+1) * sizeof(VaryRef));
+ 
+ 		    opcodes[i]->vary[nv].varyno = v;
+ 		    opcodes[i]->vary[nv].byte = j;
+ 		    opcodes[i]->vary[nv].shift = 8 - b - vary[v]->nlen;
+ 		    lprintf(sim_log, "[vary %s shift %d]\n",
+ 			    vary[v]->name, opcodes[i]->vary[nv].shift);
+ 		  }
+ 			  
+ 	}
+     }
+ 
+   for (i=0; i<n_opcodes; i++)
+     {
+       int i2;
+       int bytes = opcodes[i]->dbytes;
+ 
+       lprintf (sim_log, "\nmask:");
+       for (i2=0; i2<opcodes[i]->nbytes; i2++)
+ 	lprintf (sim_log, " %02x", opcodes[i]->b[i2].decodable_mask);
+       lprintf(sim_log, "%*s%s\n", 13-3*opcodes[i]->nbytes, "", opcodes[i]->comment);
+ 
+       lprintf (sim_log, "bits:");
+       for (i2=0; i2<opcodes[i]->nbytes; i2++)
+ 	lprintf (sim_log, " %02x", opcodes[i]->b[i2].decodable_bits);
+       lprintf(sim_log, "%*s(%s) %d byte%s\n", 13-3*opcodes[i]->nbytes, "",
+ 	      opcodes[i]->id, bytes, bytes==1 ? "" : "s");
+ 
+       store_opcode_bits (opcodes[i], 0, indirect);
+     }
+ 
+   dump_lines (&prefix_text, 0, 0);
+ 
+   emit_indirect (indirect, 0);
+ 
+   dump_lines (&suffix_text, 0, 0);
+ 
+   if (sim_log)
+     log_indirect (indirect, 0);
+ 
+   return errors;
+ }
Index: sim/m32c/r8c.opc
===================================================================
RCS file: sim/m32c/r8c.opc
diff -N sim/m32c/r8c.opc
*** sim/m32c/r8c.opc	1 Jan 1970 00:00:00 -0000
--- sim/m32c/r8c.opc	6 Oct 2005 22:36:52 -0000
***************
*** 0 ****
--- 1,1557 ----
+ #include <stdio.h>		/* -*- mode: c -*- */
+ #include <stdlib.h>
+ 
+ #include "cpu.h"
+ #include "mem.h"
+ #include "misc.h"
+ #include "int.h"
+ 
+ #define AU  __attribute__((unused))
+ 
+ #define tprintf if (trace) printf
+ 
+ static unsigned char
+ getbyte ()
+ {
+   int tsave = trace;
+   unsigned char b;
+ 
+   if (trace == 1)
+     trace = 0;
+   b = mem_get_pc ();
+   regs.r_pc ++;
+   trace = tsave;
+   return b;
+ }
+ 
+ #define M16C_ONLY() /* FIXME: add something here */
+ 
+ #define GETBYTE() (op[opi++] = getbyte())
+ 
+ #define UNSUPPORTED() unsupported("unsupported", orig_pc)
+ #define NOTYET() unsupported("unimplemented", orig_pc)
+ 
+ static void
+ unsupported (char *tag, int orig_pc)
+ {
+   int i;
+   printf("%s opcode at %08x\n", tag, orig_pc);
+   regs.r_pc = orig_pc;
+   for (i=0; i<2; i++)
+     {
+       int b = mem_get_pc();
+       printf(" %s", bits(b>>4, 4));
+       printf(" %s", bits(b, 4));
+       regs.r_pc ++;
+     }
+   printf("\n");
+   regs.r_pc = orig_pc;
+   for (i=0; i<6; i++)
+     {
+       printf(" %02x", mem_get_pc ());
+       regs.r_pc ++;
+     }
+   printf("\n");
+   exit(1);
+ }
+ 
+ static int
+ IMM(bw)
+ {
+   int rv = getbyte ();
+   if (bw)
+     rv = rv + 256 * getbyte();
+   if (bw == 2)
+     rv = rv + 65536 * getbyte();
+   return rv;
+ }
+ 
+ #define IMM4() (immm >= 8 ? 7 - immm : immm + 1)
+ 
+ #define UNARY_SOP \
+   dc = decode_srcdest4 (dest, w); \
+   v = sign_ext (get_src (dc), w?16:8);
+ 
+ #define UNARY_UOP \
+   dc = decode_srcdest4 (dest, w); \
+   v = get_src (dc);
+ 
+ #define BINARY_SOP \
+   sc = decode_srcdest4 (srcx, w); \
+   dc = decode_srcdest4 (dest, w); \
+   a = sign_ext (get_src (sc), w?16:8); \
+   b = sign_ext (get_src (dc), w?16:8);
+ 
+ #define BINARY_UOP \
+   sc = decode_srcdest4 (srcx, w); \
+   dc = decode_srcdest4 (dest, w); \
+   a = get_src (sc); \
+   b = get_src (dc);
+ 
+ #define carry (FLAG_C ? 1 : 0)
+ 
+ static void
+ cmp (int d, int s, int w)
+ {
+   int a, b, f=0;
+   int mask = w ? 0xffff : 0xff;
+   a = d - s;
+   b = sign_ext (d, w?16:8) - sign_ext (s, w?16:8);
+   tprintf ("cmp: %x - %x = %08x, %x - %x = %d\n",
+ 	   d, s, a,
+ 	   sign_ext(d,w?16:8), sign_ext(s,w?16:8), b);
+ 
+   if (b == 0)
+     f |= FLAGBIT_Z;
+   if (b & (w ? 0x8000 : 0x80))
+     f |= FLAGBIT_S;
+   if ((d & mask) >= (s & mask))
+     f |= FLAGBIT_C;
+   if (b < (w ? -32768 : -128) || b > (w ? 32767 : 127))
+     f |= FLAGBIT_O;
+ 
+   set_flags (FLAGBIT_Z | FLAGBIT_S | FLAGBIT_O | FLAGBIT_C, f);
+ }
+ 
+ static void
+ div_op (int s, int u, int x, int w)
+ {
+   srcdest sc;
+   int v, a, b;
+ 
+   if (s == -1)
+     s = IMM(w);
+   else
+     {
+       sc = decode_srcdest4 (s, w);
+       s = get_src (sc);
+     }
+ 
+   v = get_reg (w ? r2r0 : r0);
+ 
+   if (!u)
+     {
+       s = sign_ext (s, w ? 16 : 8);
+       v = sign_ext (v, w ? 16 : 8);
+     }
+ 
+   if (s == 0)
+     {
+       set_flags (FLAGBIT_O, FLAGBIT_O);
+       return;
+     }
+ 
+   if (u)
+     {
+       a = (unsigned int)v / (unsigned int)s;
+       b = (unsigned int)v % (unsigned int)s;
+     }
+   else
+     {
+       a = v / s;
+       b = v % s;
+     }
+   if (x)
+     {
+       if ((s > 0 && b < 0)
+ 	  || (s < 0 && b > 0))
+ 	{
+ 	  a --;
+ 	  b += s;
+ 	}
+     }
+   tprintf ("%d / %d = %d rem %d\n", v, s, a, b);
+   if ((!u && (a > (w ? 32767 : 127)
+ 	     || a < (w ? -32768 : -129)))
+       || (u && (a > (w ? 65536 : 255))))
+     set_flags (FLAGBIT_O, FLAGBIT_O);
+   else
+     set_flags (FLAGBIT_O, 0);
+ 
+   put_reg (w ? r0 : r0l, a);
+   put_reg (w ? r2 : r0h, b);
+ }
+ 
+ static void
+ rot_op (srcdest sd, int rotc, int count)
+ {
+   int mask = (sd.bytes == 2) ? 0xffff : 0xff;
+   int msb = (sd.bytes == 2) ? 0x8000 : 0x80;
+   int v = get_src (sd);
+   int c = carry, ct;
+ 
+   tprintf("%s %x by %d\n", rotc ? "rotc" : "rot", v, count);
+   tprintf (": %s %d\n", bits(v, 8*sd.bytes), c);
+   while (count > 0)
+     {
+       ct = (v & msb) ? 1 : 0;
+       v <<= 1;
+       v |= rotc ? c : ct;
+       v &= mask;
+       c = ct;
+       tprintf (": %s %d\n", bits(v, 8*sd.bytes), c);
+       count --;
+     }
+   while (count < 0)
+     {
+       ct = v & 1;
+       v >>= 1;
+       v |= (rotc ? c : ct) * msb;
+       c = ct;
+       tprintf (": %s %d\n", bits(v, 8*sd.bytes), c);
+       count ++;
+     }
+   put_dest (sd, v);
+   set_szc (v, sd.bytes, c);
+ }
+ 
+ static void
+ shift_op (srcdest sd, int arith, int count)
+ {
+   int mask = (sd.bytes == 2) ? 0xffff : 0xff;
+   int msb = (sd.bytes == 2) ? 0x8000 : 0x80;
+   int v = get_src (sd);
+   int c = 0;
+ 
+   if (sd.bytes == 4)
+     {
+       mask = 0xffffffffU;
+       msb = 0x80000000U;
+     }
+ 
+   tprintf("%s %x by %d\n", arith ? "sha" : "shl", v, count);
+   tprintf (": %s %d\n", bits(v, 8*sd.bytes), c);
+   while (count > 0)
+     {
+       c = (v & msb) ? 1 : 0;
+       v <<= 1;
+       v &= mask;
+       tprintf (": %s %d\n", bits(v, 8*sd.bytes), c);
+       count --;
+     }
+   while (count < 0)
+     {
+       c = v & 1;
+       if (arith)
+ 	v = (v & msb) | (v >> 1);
+       else
+ 	v = (v >> 1) & (msb - 1);
+       tprintf (": %s %d\n", bits(v, 8*sd.bytes), c);
+       count ++;
+     }
+   put_dest (sd, v);
+   set_szc (v, sd.bytes, c);
+ }
+ 
+ #define MATH_OP(dc,s,c,op,carryrel) \
+   a = get_src(dc); \
+   b = s & b2mask[dc.bytes]; \
+   v2 = a op b op c; \
+   tprintf("0x%x " #op " 0x%x " #op " 0x%x = 0x%x\n", a, b, c, v2); \
+   a = sign_ext (a, dc.bytes * 8); \
+   b = sign_ext (s, dc.bytes * 8); \
+   v = a op b op c; \
+   tprintf("%d " #op " %d " #op " %d = %d\n", a, b, c, v); \
+   set_oszc (v, dc.bytes, v2 carryrel); \
+   put_dest (dc, v2);
+ 
+ #define BIT_OP(field,expr) \
+   dc = decode_bit (field); \
+   b = get_bit (dc); \
+   v = expr; \
+   tprintf ("b=%d, carry=%d, %s = %d\n", b, carry, #expr, v); \
+   put_bit (dc, v);
+ 
+ #define BIT_OPC(field,expr) \
+   dc = decode_bit (field); \
+   b = get_bit (dc); \
+   v = expr; \
+   tprintf ("b=%d, carry=%d, %s = %d\n", b, carry, #expr, v); \
+   set_c (v);
+ 
+ int
+ decode_r8c()
+ {
+   unsigned char op[40];
+   int opi = 0;
+   int v, v2, a, b;
+   int orig_pc = get_reg (pc);
+   srcdest sc, dc;
+   int imm;
+ 
+   step_result = M32C_MAKE_STEPPED ();
+ 
+   tprintf("trace: decode pc = %05x\n", orig_pc);
+ 
+   /* VARY dst 011 100 101 110 111 */
+ 
+   /* 0111 011w 1111 dest  ABS.size dest */
+ 
+   UNARY_SOP;
+   a = v<0 ? -v : v;
+   tprintf("abs(%d) = %d\n", v, a);
+   set_osz(a, w+1);
+   put_dest (dc, a);
+ 
+   /* 0111 011w 0110 dest  ADC.size #IMM,dest */
+ 
+   dc = decode_srcdest4(dest, w);
+   imm = IMM(w);
+   MATH_OP (dc, imm, carry, +, > (w?0xffff:0xff));
+ 
+   /* 1011 000w srcx dest  ADC.size src,dest */
+ 
+   sc = decode_srcdest4(srcx, w);
+   dc = decode_srcdest4(dest, w);
+   b = get_src (sc);
+   MATH_OP (dc, b, carry, +, > (w?0xffff:0xff));
+ 
+   /* 0111 011w 1110 dest  ADCF.size dest */
+ 
+   dc = decode_srcdest4(dest, w);
+   MATH_OP (dc, 0, carry, +, > (w?0xffff:0xff));
+ 
+   /* 0111 011w 0100 dest  ADD.size:G #imm,dest */
+ 
+   dc = decode_srcdest4(dest, w);
+   imm = IMM(w);
+   MATH_OP (dc, imm, 0, +, > (w?0xffff:0xff));
+ 
+   /* 1100 100w immm dest  ADD.size:Q #IMM,dest */
+ 
+   dc = decode_srcdest4(dest, w);
+   imm = sign_ext (immm, 4);
+   MATH_OP (dc, imm, 0, +, > (w?0xffff:0xff));
+ 
+   /* 1000 0dst            ADD.B:S #IMM8,dst */
+ 
+   imm = IMM(0);
+   dc = decode_dest3 (dst, 0);
+   MATH_OP (dc, imm, 0, +, > 0xff);
+ 
+   /* 1010 000w srcx dest  ADD.size:G src,dest */
+ 
+   sc = decode_srcdest4(srcx, w);
+   dc = decode_srcdest4(dest, w);
+   b = get_src (sc);
+   MATH_OP (dc, b, 0, +, > (w?0xffff:0xff));
+ 
+   /* 0010 0d sr           ADD.B:S src,R0L/R0H */
+ 
+   sc = decode_src2 (sr, 0, d);
+   dc = decode_dest1 (d, 0);
+   b = get_src (sc);
+   MATH_OP (dc, b, 0, +, > 0xff);
+ 
+   /* 0111 110w 1110 1011  ADD.size:G #IMM,sp */
+ 
+   dc = reg_sd (sp);
+   imm = sign_ext (IMM(w), w?16:8);
+   MATH_OP (dc, imm, 0, +, > 0xffff);
+ 
+   /* 0111 1101 1011 immm  ADD.size:Q #IMM,sp */
+ 
+   dc = reg_sd (sp);
+   imm = sign_ext (immm, 4);
+   MATH_OP (dc, imm, 0, +, > 0xffff);
+ 
+   /* 1111 100w immm dest  ADJNZ.size #IMM,dest,label */
+ 
+   UNARY_UOP;
+   imm = sign_ext(immm, 4);
+   tprintf("%x + %d = %x\n", v, imm, v+imm);
+   v += imm;
+   put_dest (dc, v);
+   a = sign_ext (IMM(0), 8);
+   if ((v & (w ? 0xffff : 0xff)) != 0)
+     {
+       tprintf("jmp: %x + 2 + %d = ", get_reg (pc), a);
+       put_reg (pc, orig_pc + 2 + a);
+       tprintf("%x\n", get_reg (pc));
+     }
+ 
+   /* 0111 011w 0010 dest  AND.size:G #IMM,dest */
+ 
+   UNARY_UOP;
+   imm = IMM(w);
+   tprintf ("%x & %x = %x\n", v, imm, v & imm);
+   v &= imm;
+   set_sz (v, w+1);
+   put_dest (dc, v);
+ 
+   /* 1001 0dst            AND.B:S #IMM8,dest */
+ 
+   imm = IMM(0);
+   dc = decode_dest3 (dst, 0);
+   v = get_src (dc);
+   tprintf("%x & %x = %x\n", v, imm, v & imm);
+   v &= imm;
+   set_sz (v, 1);
+   put_dest (dc, v);
+ 
+   /* 1001 000w srcx dest  AND.size:G src.dest */
+ 
+   BINARY_UOP;
+   tprintf ("%x & %x = %x\n", a, b, a & b);
+   v = a & b;
+   set_sz (v, w+1);
+   put_dest (dc, v);
+ 
+   /* 0001 0d sr           AND.B:S src,R0L/R0H */
+ 
+   sc = decode_src2 (sr, 0, d);
+   dc = decode_dest1 (d, 0);
+   a = get_src (sc);
+   b = get_src (dc);
+   v = a & b;
+   tprintf("%x & %x = %x\n", a, b, v);
+   set_sz (v, 1);
+   put_dest (dc, v);
+ 
+   /* 0111 1110 0100 srcx  BAND src */
+ 
+   BIT_OPC (srcx, b & carry);
+ 
+   /* 0111 1110 1000 dest  BCLR:G dest */
+ 
+   dc = decode_bit (dest);
+   put_bit (dc, 0);
+ 
+   /* 0100 0bit            BCLR:S bit,base:11[SB] */
+ 
+   dc = decode_bit11 (bit);
+   put_bit (dc, 0);
+ 
+   /* 0111 1110 0010 dest  BMcnd dest  */
+ 
+   dc = decode_bit (dest);
+   if (condition_true (IMM (0)))
+     put_bit (dc, 1);
+   else
+     put_bit (dc, 0);
+ 
+   /* 0111 1101 1101 cond  BMcnd C  */
+ 
+   if (condition_true (cond))
+     set_c (1);
+   else
+     set_c (0);
+ 
+   /* 0111 1110 0101 srcx  BNAND src */
+ 
+   BIT_OPC (srcx, !b & carry);
+ 
+   /* 0111 1110 0111 srcx  BNOR src */
+ 
+   BIT_OPC (srcx, !b | carry);
+ 
+   /* 0111 1110 1010 dest  BNOT:G dest */
+ 
+   BIT_OP (dest, !b);
+ 
+   /* 0101 0bit            BNOT:S bit,base:11[SB] */
+ 
+   dc = decode_bit11 (bit);
+   put_bit (dc, !get_bit (dc));
+ 
+   /* 0111 1110 0011 srcx  BNTST src */
+ 
+   dc = decode_bit (srcx);
+   b = get_bit (dc);
+   set_zc (!b, !b);
+ 
+   /* 0111 1110 1101 srcx  BNXOR src */
+ 
+   BIT_OPC (srcx, !b ^ carry);
+ 
+   /* 0111 1110 0110 srcx  BOR src */
+ 
+   BIT_OPC (srcx, b | carry);
+ 
+   /* 0000 0000            BRK */
+ 
+   /* We report the break to our caller with the PC still pointing at the 
+      breakpoint instruction.  */
+   put_reg (pc, orig_pc);
+   if (verbose)
+     printf("[break]\n");
+   return M32C_MAKE_HIT_BREAK ();
+ 
+   /* 0111 1110 1001 dest  BSET:G dest */
+ 
+   dc = decode_bit (dest);
+   put_bit (dc, 1);
+ 
+   /* 0100 1bit            BSET:S bit,base:11[SB] */
+ 
+   dc = decode_bit11 (bit);
+   put_bit (dc, 1);
+ 
+   /* 0111 1110 1011 srcx  BTST:G src */
+ 
+   dc = decode_bit (srcx);
+   b = get_bit (dc);
+   set_zc (!b, b);
+ 
+   /* 0101 1bit            BTST:S bit,base:11[SB] */
+ 
+   dc = decode_bit11 (bit);
+   b = get_bit (dc);
+   set_zc (!b, b);
+ 
+   /* 0111 1110 0000 dest  BTSTC dest */
+ 
+   dc = decode_bit (dest);
+   b = get_bit (dc);
+   set_zc (!b, b);
+   put_bit (dc, 0);
+ 
+   /* 0111 1110 0001 dest  BTSTS dest */
+ 
+   dc = decode_bit (dest);
+   b = get_bit (dc);
+   set_zc (!b, b);
+   put_bit (dc, 1);
+ 
+   /* 0111 1110 1100 srcx  BXOR src */
+ 
+   BIT_OPC (srcx, b ^ carry);
+ 
+   /* 0111 011w 1000 dest  CMP.size:G #IMM,dest */
+ 
+   UNARY_UOP;
+   imm = IMM(w);
+   cmp (v, imm, w);
+ 
+   /* 1101 000w immm dest  CMP.size:Q #IMM,dest */
+ 
+   UNARY_UOP;
+   immm = sign_ext (immm, 4);
+   cmp (v, immm, w);
+ 
+   /* 1110 0dst            CMP.B:S #IMM8,dest */
+ 
+   imm = IMM(0);
+   dc = decode_dest3 (dst, 0);
+   v = get_src (dc);
+   cmp (v, imm, 0);
+ 
+   /* 1100 000w srcx dest  CMP.size:G src,dest */
+ 
+   BINARY_UOP;
+   cmp(b, a, w);
+ 
+   /* 0011 1d sr           CMP.B:S src,R0L/R0H */
+ 
+   sc = decode_src2 (sr, 0, d);
+   dc = decode_dest1 (d, 0);
+   a = get_src (sc);
+   b = get_src (dc);
+   cmp (b, a, 0);
+ 
+   /* 0111 110w 1110 i1c s  DADC,DADD,DSBB,DSUB */
+ 
+   /* w = width, i = immediate, c = carry, s = subtract */
+ 
+   int src = i ? IMM(w) : get_reg (w ? r1 : r0h);
+   int dest = get_reg (w ? r0 : r0l);
+   int res;
+ 
+   src = bcd2int(src, w);
+   dest = bcd2int(dest, w);
+ 
+   tprintf("decimal: %d %s %d", dest, s?"-":"+", src);
+   if (c)
+     tprintf(" c=%d", carry);
+ 
+   if (!s)
+     {
+       res = dest + src;
+       if (c)
+ 	res += carry;
+       c = res > (w ? 9999 : 99);
+     }
+   else
+     {
+       res = dest - src;
+       if (c)
+ 	res -= (1-carry);
+       c = res >= 0;
+       if (res < 0)
+ 	res += w ? 10000 : 100;
+     }
+ 
+   res = int2bcd (res, w);
+   tprintf(" = %x\n", res);
+ 
+   set_szc (res, w+1, c);
+ 
+   put_reg (w ? r0 : r0l, res);
+ 
+   /* 1010 1dst            DEC.B dest */
+ 
+   dc = decode_dest3 (dst, 0);
+   v = get_src (dc);
+   tprintf("%x -- = %x\n", v, v-1);
+   v --;
+   set_sz (v, 1);
+   put_dest (dc, v);
+ 
+   /* 1111 d010            DEC.W dest */
+ 
+   v = get_reg (d ? a1 : a0);
+   tprintf("%x -- = %x\n", v, v-1);
+   v --;
+   set_sz (v, 2);
+   put_reg (d ? a1 : a0, v);
+ 
+   /* 0111 110w 1110 0001  DIV.size #IMM */
+ 
+   div_op (-1, 0, 0, w);
+ 
+   /* 0111 011w 1101 srcx  DIV.size src */
+ 
+   div_op (srcx, 0, 0, w);
+ 
+   /* 0111 110w 1110 0000  DIVU.size #IMM */
+ 
+   div_op (-1, 1, 0, w);
+ 
+   /* 0111 011w 1100 srcx  DIVU.size src */
+ 
+   div_op (srcx, 1, 0, w);
+ 
+   /* 0111 110w 1110 0011  DIVX.size #IMM */
+ 
+   div_op (-1, 0, 1, w);
+ 
+   /* 0111 011w 1001 srcx  DIVX.size src */
+ 
+   div_op (srcx, 0, 1, w);
+ 
+   /* 0111 1100 1111 0010  ENTER #IMM8 */
+ 
+   imm = IMM(0);
+   put_reg (sp, get_reg (sp) - 2);
+   mem_put_hi (get_reg (sp), get_reg (fb));
+   put_reg (fb, get_reg (sp));
+   put_reg (sp, get_reg (sp) - imm);
+ 
+   /* 0111 1101 1111 0010  EXITD */
+ 
+   put_reg (sp, get_reg (fb));
+   put_reg (fb, mem_get_hi (get_reg (sp)));
+   put_reg (sp, get_reg (sp) + 2);
+   put_reg (pc, mem_get_psi (get_reg (sp)));
+   put_reg (sp, get_reg (sp) + 3);
+ 
+   /* 0111 1100 0110 dest  EXTS.B dest */
+ 
+   dc = decode_srcdest4 (dest, 0);
+   v = sign_ext (get_src (dc), 8);
+   dc = widen_sd (dc);
+   put_dest (dc, v);
+   set_sz (v, 1);
+ 
+   /* 0111 1100 1111 0011  EXTS.W R0 */
+ 
+   v = sign_ext (get_reg (r0), 16);
+   put_reg (r2r0, v);
+   set_sz (v, 2);
+ 
+   /* 1110 1011 0flg 0101  FCLR dest */
+ 
+   set_flags (1 << flg, 0);
+ 
+   /* 1110 1011 0flg 0100  FSET dest */
+ 
+   set_flags (1 << flg, 1 << flg);
+ 
+   /* 1010 0dst            INC.B dest */
+ 
+   dc = decode_dest3 (dst, 0);
+   v = get_src (dc);
+   tprintf("%x ++ = %x\n", v, v+1);
+   v ++;
+   set_sz (v, 1);
+   put_dest (dc, v);
+ 
+   /* 1011 d010            INC.W dest */
+ 
+   v = get_reg (d ? a1 : a0);
+   tprintf("%x ++ = %x\n", v, v+1);
+   v ++;
+   set_sz (v, 2);
+   put_reg (d ? a1 : a0, v);
+ 
+   /* 1110 1011 11vector   INT #imm */
+ 
+   trigger_based_interrupt (vector);
+ 
+   /* 1111 0110            INTO */
+ 
+   if (FLAG_O)
+     trigger_fixed_interrupt (0xffe0);
+ 
+   /* 0110 1cnd            Jcnd label */
+ 
+   v = sign_ext (IMM(0), 8);
+   if (condition_true (cnd))
+     put_reg (pc, orig_pc + 1 + v);
+ 
+   /* 0111 1101 1100 cond  Jcnd label */
+ 
+   v = sign_ext (IMM(0), 8);
+   if (condition_true (cond))
+     put_reg (pc, orig_pc + 2 + v);
+ 
+   /* 0110 0dsp            JMP.S label */
+ 
+   put_reg (pc, orig_pc + 2 + dsp);
+ 
+   /* 1111 1110            JMP.B label */
+ 
+   imm = sign_ext (IMM(0), 8);
+   if (imm == -1)
+     {
+       if (verbose)
+ 	printf("[jmp-to-self detected as exit]\n");
+       return M32C_MAKE_HIT_BREAK ();
+     }
+   put_reg (pc, orig_pc + 1 + imm);
+ 
+   /* 1111 0100            JMP.W label */
+ 
+   imm = sign_ext (IMM(1), 16);
+   put_reg (pc, orig_pc + 1 + imm);
+ 
+   /* 1111 1100            JMP.A label */
+   
+   imm = IMM(2);
+   put_reg (pc, imm);
+ 
+   /* 0111 1101 0010 srcx  JMPI.W src */
+ 
+   sc = decode_jumpdest (srcx, 1);
+   a = get_src (sc);
+   a = sign_ext (a, 16);
+   put_reg (pc, orig_pc + a);
+ 
+   /* 0111 1101 0000 srcx  JMPI.A src */
+ 
+   sc = decode_jumpdest (srcx, 0);
+   a = get_src (sc);
+   put_reg (pc, a);
+ 
+   /* 1110 1110            JMPS #IMM8 */
+ 
+   M16C_ONLY();
+ 
+   imm = IMM(0);
+   a = 0xf0000 + mem_get_hi (0xffffe - imm * 2);
+   put_reg (pc, a);
+ 
+   /* 1111 0101            JSR.W label */
+ 
+   imm = sign_ext (IMM(1), 16);
+   put_reg (sp, get_reg (sp) - 3);
+   mem_put_psi (get_reg (sp), get_reg (pc));
+   put_reg (pc, orig_pc + imm + 1);
+ 
+   /* 1111 1101            JSR.A label */
+ 
+   imm = IMM(2);
+   put_reg (sp, get_reg (sp) - 3);
+   mem_put_psi (get_reg (sp), get_reg (pc));
+   put_reg (pc, imm);
+ 
+   /* 0111 1101 0011 srcx  JSRI.W src */
+ 
+   sc = decode_jumpdest (srcx, 1);
+   a = get_src (sc);
+   a = sign_ext (a, 16);
+ 
+   put_reg (sp, get_reg (sp) - 3);
+   mem_put_psi (get_reg (sp), get_reg (pc));
+   put_reg (pc, orig_pc + a);
+ 
+   /* 0111 1101 0001 srcx  JSRI.A src */
+ 
+   sc = decode_jumpdest (srcx, 0);
+   a = get_src (sc);
+ 
+   put_reg (sp, get_reg (sp) - 3);
+   mem_put_psi (get_reg (sp), get_reg (pc));
+   put_reg (pc, a);
+ 
+   /* 1110 1111            JSRS #IMM8 */
+ 
+   M16C_ONLY();
+ 
+   imm = IMM(0);
+   a = 0xf0000 + mem_get_hi (0xffffe - imm * 2);
+ 
+   put_reg (sp, get_reg (sp) - 3);
+   mem_put_psi (get_reg (sp), get_reg (pc));
+   put_reg (pc, a);
+ 
+   /* 1110 1011 0reg 0000  LDC #IMM16,dest */
+ 
+   dc = decode_cr (reg);
+   imm = IMM(1);
+   put_dest (dc, imm);
+ 
+   /* 0111 1010 1reg srcx  LDC src,dest */
+ 
+   dc = decode_cr (reg);
+   sc = decode_srcdest4 (srcx,1);
+   put_dest (dc, get_src (sc));
+ 
+   /* 0111 1100 1111 0000  LDCTX abs16,abs20 */
+ 
+   NOTYET();
+ 
+   /* 0111 010w 1000 dest  LDE.size abs20,dest */
+ 
+   dc = decode_srcdest4 (dest, w);
+   imm = IMM(2);
+   if (w)
+     v = mem_get_hi (imm);
+   else
+     v = mem_get_qi (imm);
+   put_dest (dc, v);
+ 
+   /* 0111 010w 1001 dest  LDE.size dsp:20[a0], dest */
+ 
+   dc = decode_srcdest4 (dest, w);
+   imm = IMM(2) + get_reg (a0);
+   if (w)
+     v = mem_get_hi (imm);
+   else
+     v = mem_get_qi (imm);
+   put_dest (dc, v);
+ 
+   /* 0111 010w 1010 dest  LDE.size [a1a0],dest */
+   
+   dc = decode_srcdest4 (dest, w);
+   imm = get_reg (a1a0);
+   if (w)
+     v = mem_get_hi (imm);
+   else
+     v = mem_get_qi (imm);
+   put_dest (dc, v);
+ 
+   /* 0111 1101 1010 0imm  LDIPL #IMM */
+ 
+   set_flags (0x700, imm*0x100);
+ 
+   /* 0111 010w 1100 dest  MOV.size:G #IMM,dest */
+ 
+   UNARY_UOP;
+   imm = IMM(w);
+   v = imm;
+   tprintf("%x = %x\n", v, v);
+   set_sz(v, w+1);
+   put_dest (dc, v);
+ 
+   /* 1101 100w immm dest  MOV.size:Q #IMM,dest */
+ 
+   UNARY_SOP;
+   v = sign_ext (immm, 4);
+   tprintf ("%x = %x\n", v, v);
+   set_sz (v, w+1);
+   put_dest (dc, v);
+ 
+   /* 1100 0dst            MOV.B:S #IMM8,dest */
+ 
+   imm = IMM(0);
+   dc = decode_dest3 (dst, 0);
+   v = imm;
+   tprintf("%x = %x\n", v, v);
+   set_sz (v, 1);
+   put_dest (dc, v);
+ 
+   /* 1w10 d010            MOV.size:S #IMM,dest */
+ 
+   /* Note that for w, 0=W and 1=B unlike the usual meaning.  */
+   v = IMM(1-w);
+   tprintf("%x = %x\n", v, v);
+   set_sz (v, 2-w);
+   put_reg (d ? a1 : a0, v);
+ 
+   /* 1011 0dst            MOV.B:Z #0,dest */
+ 
+   dc = decode_dest3 (dst, 0);
+   v = 0;
+   set_sz (v, 1);
+   put_dest (dc, v);
+ 
+   /* 0111 001w srcx dest  MOV.size:G src,dest */
+ 
+   sc = decode_srcdest4 (srcx, w);
+   dc = decode_srcdest4 (dest, w);
+   v = get_src (sc);
+   set_sz (v, w+1);
+   put_dest (dc, v);
+ 
+   /* 0011 0d sr           MOV.B:S src,dest */
+ 
+   sc = decode_src2 (sr, 0, d);
+   v = get_src (sc);
+   set_sz (v, 1);
+   put_reg (d ? a1 : a0, v);
+ 
+   /* 0000 0s ds           MOV.B:S R0L/R0H,dest */
+ 
+   if (ds == 0)
+     UNSUPPORTED();
+   dc = decode_src2 (ds, 0, s);
+   v = get_reg (s ? r0h : r0l);
+   set_sz (v, 1);
+   put_dest (dc, v);
+ 
+   /* 0000 1d sr           MOV.B:S src,R0L/R0H */
+ 
+   sc = decode_src2 (sr, 0, d);
+   v = get_src (sc);
+   set_sz (v, 1);
+   put_reg (d ? r0h : r0l, v);
+ 
+   /* 0111 010w 1011 dest  MOV.size:G dsp:8[SP], dest */
+ 
+   dc = decode_srcdest4 (dest, w);
+   imm = IMM(0);
+   a = get_reg (sp) + sign_ext (imm, 8);
+   a &= addr_mask;
+   if (w)
+     v = mem_get_hi (a);
+   else
+     v = mem_get_qi (a);
+   set_sz (v, w+1);
+   put_dest (dc, v);
+ 
+   /* 0111 010w 0011 srcx  MOV.size:G src, disp8[SP] */
+ 
+   sc = decode_srcdest4 (srcx, w);
+   imm = IMM(0);
+   a = get_reg (sp) + sign_ext (imm, 8);
+   a &= addr_mask;
+   v = get_src (sc);
+   if (w)
+     mem_put_hi (a, v);
+   else
+     mem_put_qi (a, v);
+   set_sz (v, w+1);
+ 
+   /* 1110 1011 0reg 1src  MOVA src,dest */
+ 
+   static reg_id map[] = { r0, r1, r2, r3, a0, a1, 0, 0 };
+   sc = decode_srcdest4 (8 + src, 0);
+   put_reg (map[reg], sc.u.addr);
+ 
+   /* 0111 1100 10hl dest  MOVdir R0L,dest */
+ 
+   if (dest == 0 || dest == 4 || dest == 5)
+     UNSUPPORTED();
+   dc = decode_srcdest4 (dest, 0);
+   a = get_src (dc);
+   b = get_reg (r0l);
+   switch (hl)
+     {
+     case 0: a = (a & 0xf0) | (b & 0x0f); break;
+     case 1: a = (a & 0xf0) | ((b>>4) & 0x0f); break;
+     case 2: a = (a & 0x0f) | ((b & 0x0f)<<4); break;
+     case 3: a = (a & 0x0f) | (b & 0xf0); break;
+     }
+   put_dest (dc, a);
+ 
+   /* 0111 1100 00hl srcx  MOVdir src,R0L */
+ 
+   if (srcx == 0 || srcx == 4 || srcx == 5)
+     UNSUPPORTED();
+   sc = decode_srcdest4 (srcx, 0);
+   a = get_reg (r0l);
+   b = get_src (sc);
+   switch (hl)
+     {
+     case 0: a = (a & 0xf0) | (b & 0x0f); break;
+     case 1: a = (a & 0xf0) | ((b>>4) & 0x0f); break;
+     case 2: a = (a & 0x0f) | ((b & 0x0f)<<4); break;
+     case 3: a = (a & 0x0f) | (b & 0xf0); break;
+     }
+   put_reg (r0l, a);
+ 
+   /* 0111 110w 0101 dest  MUL.size #IMM,dest */
+ 
+   UNARY_SOP;
+   imm = sign_ext (IMM(w), w?16:8);
+   tprintf("%d * %d = %d\n", v, imm, v*imm);
+   v *= imm;
+   dc = widen_sd (dc);
+   put_dest (dc, v);
+ 
+   /* 0111 100w srcx dest  MUL.size src,dest */
+ 
+   BINARY_SOP;
+   v = a * b;
+   tprintf("%d * %d = %d\n", a, b, v);
+   dc = widen_sd (dc);
+   put_dest (dc, v);
+ 
+   /* 0111 110w 0100 dest  MULU.size #IMM,dest */
+ 
+   UNARY_UOP;
+   imm = IMM(w);
+   tprintf("%u * %u = %u\n", v, imm, v*imm);
+   v *= imm;
+   dc = widen_sd (dc);
+   put_dest (dc, v);
+ 
+   /* 0111 000w srcx dest  MULU.size src,dest */
+ 
+   BINARY_UOP;
+   v = a * b;
+   tprintf("%u * %u = %u\n", a, b, v);
+   dc = widen_sd (dc);
+   put_dest (dc, v);
+ 
+   /* 0111 010w 0101 dest  NEG.size dest */
+ 
+   UNARY_SOP;
+   tprintf("%d * -1 = %d\n", v, -v);
+   v = -v;
+   set_oszc (v, w+1, v == 0);
+   put_dest (dc, v);
+ 
+   /* 0000 0100            NOP */
+ 
+   tprintf("nop\n");
+ 
+   /* 0111 010w 0111 dest  NOT.size:G */
+ 
+   UNARY_UOP;
+   tprintf("~ %x = %x\n", v, ~v);
+   v = ~v;
+   set_sz (v, w+1);
+   put_dest (dc, v);
+ 
+   /* 1011 1dst            NOT.B:S dest */
+ 
+   dc = decode_dest3 (dst, 0);
+   v = get_src (dc);
+   tprintf("~ %x = %x\n", v, ~v);
+   v = ~v;
+   set_sz (v, 1);
+   put_dest (dc, v);
+ 
+   /* 0111 011w 0011 dest  OR.size:G #IMM,dest */
+ 
+   UNARY_UOP;
+   imm = IMM(w);
+   tprintf ("%x | %x = %x\n", v, imm, v | imm);
+   v |= imm;
+   set_sz (v, w+1);
+   put_dest (dc, v);
+ 
+   /* 1001 1dst            OR.B:S #IMM8,dest */
+ 
+   imm = IMM(0);
+   dc = decode_dest3 (dst, 0);
+   v = get_src (dc);
+   tprintf("%x | %x = %x\n", v, imm, v|imm);
+   v |= imm;
+   set_sz (v, 1);
+   put_dest (dc, v);
+ 
+   /* 1001 100w srcx dest  OR.size:G src,dest */
+ 
+   BINARY_UOP;
+   tprintf ("%x | %x = %x\n", a, b, a | b);
+   v = a | b;
+   set_sz (v, w+1);
+   put_dest (dc, v);
+ 
+   /* 0001 1d sr           OR.B:S src,R0L/R0H */
+ 
+   sc = decode_src2 (sr, 0, d);
+   dc = decode_dest1 (d, 0);
+   a = get_src (sc);
+   b = get_src (dc);
+   v = a | b;
+   tprintf("%x | %x = %x\n", a, b, v);
+   set_sz (v, 1);
+   put_dest (dc, v);
+ 
+   /* 0111 010w 1101 dest  POP.size:G dest */
+ 
+   dc = decode_srcdest4 (dest, w);
+   if (w)
+     {
+       v = mem_get_hi (get_reg (sp));
+       put_reg (sp, get_reg (sp) + 2);
+       tprintf("pophi: %x\n", v);
+     }
+   else
+     {
+       v = mem_get_qi (get_reg (sp));
+       put_reg (sp, get_reg (sp) + 1);
+       tprintf("popqi: %x\n", v);
+     }
+   put_dest (dc, v);
+ 
+   /* 1001 d010            POP.B:S dest */
+ 
+   v = mem_get_qi (get_reg (sp));
+   put_reg (d ? r0h : r0l, v);
+   put_reg (sp, get_reg (sp) + 1);
+   tprintf("popqi: %x\n", v);
+ 
+   /* 1101 d010            POP.W:S dest */
+ 
+   v = mem_get_hi (get_reg (sp));
+   put_reg (d ? a1 : a0, v);
+   put_reg (sp, get_reg (sp) + 2);
+   tprintf("pophi: %x\n", v);
+ 
+   /* 1110 1011 0reg 0011  POPC dest */
+ 
+   dc = decode_cr (reg);
+   v = mem_get_hi (get_reg (sp));
+   put_dest (dc, v);
+   put_reg (sp, get_reg (sp) + 2);
+   tprintf("popc: %x\n", v);
+ 
+   /* 1110 1101            POPM dest */
+ 
+   static int map[] = { r0, r1, r2, r3, a0, a1, sb, fb };
+   imm = IMM(0);
+   tprintf("popm: %x\n", imm);
+   for (a=0; a<8; a++)
+     if (imm & (1<<a))
+       {
+ 	v = mem_get_hi (get_reg (sp));
+ 	put_reg (map[a], v);
+ 	put_reg (sp, get_reg (sp) + 2);
+       }
+ 
+   /* 0111 110w 1110 0010  PUSH.size:G #IMM */
+ 
+   imm = IMM(w);
+   if (w)
+     {
+       put_reg (sp, get_reg (sp) - 2);
+       mem_put_hi (get_reg (sp), imm);
+       tprintf("pushhi %04x\n", imm);
+     }
+   else
+     {
+       put_reg (sp, get_reg (sp) - 1);
+       mem_put_qi (get_reg (sp), imm);
+       tprintf("pushqi %02x\n", imm);
+     }
+ 
+   /* 0111 010w 0100 srcx  PUSH.size:G src */
+ 
+   sc = decode_srcdest4 (srcx, w);
+   v = get_src (sc);
+   if (w)
+     {
+       put_reg (sp, get_reg (sp) - 2);
+       mem_put_hi (get_reg (sp), v);
+       tprintf("pushhi: %x\n", v);
+     }
+   else
+     {
+       put_reg (sp, get_reg (sp) - 1);
+       mem_put_qi (get_reg (sp), v);
+       tprintf("pushqi: %x\n", v);
+     }
+ 
+   /* 1000 s010            PUSH.B:S src */
+ 
+   v = get_reg (s ? r0h : r0l);
+   put_reg (sp, get_reg (sp) - 1);
+   mem_put_qi (get_reg (sp), v);
+   tprintf("pushqi: %x\n", v);
+ 
+   /* 1100 s010            PUSH.W:S src */
+ 
+   v = get_reg (s ? a1 : a0);
+   put_reg (sp, get_reg (sp) - 2);
+   mem_put_hi (get_reg (sp), v);
+   tprintf("pushhi: %x\n", v);
+ 
+   /* 0111 1101 1001 srcx  PUSHA src */
+ 
+   sc = decode_srcdest4 (srcx, 0);
+   put_reg (sp, get_reg (sp) - 2);
+   mem_put_hi (get_reg (sp), sc.u.addr);
+   tprintf("pushhi: %x\n", sc.u.addr);
+ 
+   /* 1110 1011 0src 0010  PUSHC src */
+ 
+   sc = decode_cr (src);
+   put_reg (sp, get_reg (sp) - 2);
+   v = get_src (sc);
+   mem_put_hi (get_reg (sp), v);
+   tprintf("pushc: %x\n", v);
+ 
+   /* 1110 1100            PUSHM src */
+ 
+   static int map[] = { fb, sb, a1, a0, r3, r2, r1, r0 };
+   imm = IMM(0);
+   tprintf("pushm: %x\n", imm);
+   for (a=0; a<8; a++)
+     if (imm & (1<<a))
+       {
+ 	put_reg (sp, get_reg (sp) - 2);
+ 	v = get_reg (map[a]);
+ 	mem_put_hi (get_reg (sp), v);
+       }
+ 
+   /* 1111 1011            REIT */
+ 
+   a = get_reg (sp);
+   v = (mem_get_hi (a)
+        + 65536 * (mem_get_qi (a+3) & 0x0f));
+   b = (mem_get_qi (a+2)
+        + 16 * (mem_get_qi (a+3) & 0xf0));
+   put_reg (pc, v);
+   put_reg (flags, b);
+   put_reg (sp, get_reg (sp) + 4);
+ 
+   /* 0111 110w 1111 0001  RMPA.size */
+ 
+   int count = get_reg (r3);
+   int list1 = get_reg (a0);
+   int list2 = get_reg (a1);
+   int sum = get_reg (w ? r2r0 : r0);
+ 
+   while (count)
+     {
+       if (w)
+ 	{
+ 	  a = sign_ext (mem_get_hi (list1), 16);
+ 	  b = sign_ext (mem_get_hi (list2), 16);
+ 	}
+       else
+ 	{
+ 	  a = sign_ext (mem_get_qi (list1), 8);
+ 	  b = sign_ext (mem_get_qi (list2), 8);
+ 	}
+       tprintf("%d + %d * %d = ", sum, a, b);
+       sum += a * b;
+       tprintf("%d\n", sum);
+       list1 += w ? 2 : 1;
+       list2 += w ? 2 : 1;
+       count --;
+     }
+   put_reg (r3, count);
+   put_reg (a0, list1);
+   put_reg (a1, list2);
+   put_reg (w ? r2r0 : r0, sum);
+ 
+   /* 0111 011w 1010 dest  ROLC.size dest */
+ 
+   dc = decode_srcdest4 (dest, w);
+   rot_op (dc, 1, 1);
+ 
+   /* 0111 011w 1011 dest  RORC.size dest */
+ 
+   dc = decode_srcdest4 (dest, w);
+   rot_op (dc, 1, -1);
+ 
+   /* 1110 000w immm dest  ROT.size #IMM,dest */
+ 
+   dc = decode_srcdest4 (dest, w);
+   rot_op (dc, 0, IMM4());
+ 
+   /* 0111 010w 0110 dest  ROT.size R1H,dest */
+ 
+   dc = decode_srcdest4 (dest, w);
+   rot_op (dc, 0, sign_ext (get_reg (r1h), 8));
+ 
+   /* 1111 0011            RTS */
+ 
+   put_reg (pc, mem_get_psi (get_reg (sp)));
+   put_reg (sp, get_reg (sp) + 3);
+ 
+   /* 0111 011w 0111 dest  SBB.size #IMM,dest */
+ 
+   dc = decode_srcdest4 (dest, w);
+   imm = IMM(w);
+   MATH_OP (dc, imm, !carry, -, >= 0);
+ 
+   /* 1011 100w srcx dest  SBB.size src,dest */
+ 
+   sc = decode_srcdest4(srcx, w);
+   dc = decode_srcdest4(dest, w);
+   b = get_src (sc);
+   MATH_OP (dc, b, !carry, -, >= 0);
+ 
+   /* 1111 000w immm dest  SHA.size #IMM, dest */
+ 
+   dc = decode_srcdest4(dest, w);
+   shift_op (dc, 1, IMM4());
+ 
+   /* 0111 010w 1111 dest  SHA.size R1H,dest */
+ 
+   dc = decode_srcdest4(dest, w);
+   a = sign_ext (get_reg (r1h), 8);
+   shift_op (dc, 1, a);
+ 
+   /* 1110 1011 101d immm  SHA.L #IMM, dest */
+ 
+   dc = reg_sd (d ? r3r1 : r2r0);
+   shift_op (dc, 1, IMM4());
+ 
+   /* 1110 1011 001d 0001  SHA.L R1H,dest */
+ 
+   dc = reg_sd (d ? r3r1 : r2r0);
+   a = sign_ext (get_reg (r1h), 8);
+   shift_op (dc, 1, a);
+ 
+   /* 1110 100w immm dest  SHL.size #IMM, dest */
+ 
+   dc = decode_srcdest4(dest, w);
+   shift_op (dc, 0, IMM4());
+ 
+   /* 0111 010w 1110 dest  SHL.size R1H,dest */
+ 
+   dc = decode_srcdest4(dest, w);
+   a = sign_ext (get_reg (r1h), 8);
+   shift_op (dc, 0, a);
+ 
+   /* 1110 1011 100d immm  SHL.L #IMM,dest */
+ 
+   dc = reg_sd (d ? r3r1 : r2r0);
+   shift_op (dc, 0, IMM4());
+ 
+   /* 1110 1011 000d 0001  SHL.L R1H,dest */
+ 
+   dc = reg_sd (d ? r3r1 : r2r0);
+   a = sign_ext (get_reg (r1h), 8);
+   shift_op (dc, 0, a);
+ 
+   /* 0111 110w 1110 100b  SMOVB.size */
+ 
+   int count = get_reg (r3);
+   int s1 = get_reg (a0) + (get_reg (r1h) << 16);
+   int s2 = get_reg (a1);
+   int inc = (w ? 2 : 1) * (b ? -1 : 1);
+ 
+   while (count)
+     {
+       if (w)
+ 	{
+ 	  v = mem_get_hi (s1);
+ 	  mem_put_hi (s2, v);
+ 	}
+       else
+ 	{
+ 	  v = mem_get_qi (s1);
+ 	  mem_put_qi (s2, v);
+ 	}
+       s1 += inc;
+       s2 += inc;
+       count --;
+     }
+   put_reg (r3, count);
+   put_reg (a0, s1 & 0xffff);
+   put_reg (a1, s2);
+   put_reg (r1h, s1 >> 16);
+ 
+   /* 0111 110w 1110 1010  SSTR.size */
+ 
+   int count = get_reg (r3);
+   int s1 = get_reg (a1);
+   v = get_reg (w ? r0 : r0h);
+ 
+   while (count)
+     {
+       if (w)
+ 	{
+ 	  mem_put_hi (s1, v);
+ 	  s1 += 2;
+ 	}
+       else
+ 	{
+ 	  mem_put_qi (s1, v);
+ 	  s1 += 1;
+ 	}
+       count --;
+     }
+   put_reg (r3, count);
+   put_reg (a1, s1);
+ 
+   /* 0111 1011 1src dest  STC src,dest */
+ 
+   dc = decode_srcdest4 (dest, 1);
+   sc = decode_cr (src);
+   put_dest (dc, get_src(sc));
+ 
+   /* 0111 1100 1100 dest  STC PC,dest */
+ 
+   dc = decode_srcdest4 (dest, 1);
+   dc.bytes = 3;
+   put_dest (dc, orig_pc);
+ 
+   /* 0111 1101 1111 0000  STCTX abs16,abs20 */
+ 
+   NOTYET();
+ 
+   /* 0111 010w 0000 srcx  STE.size src,abs20 */
+ 
+   sc = decode_srcdest4 (srcx, w);
+   a = IMM(2);
+   v = get_src (sc);
+   if (w)
+     mem_put_hi (a, v);
+   else
+     mem_put_qi (a, v);
+   if (srcx == 4 || srcx == 5)
+     {
+       v = get_reg (sc.u.reg);
+       set_sz (v, 2);
+     }
+   else
+     set_sz (v, w+1);
+     
+   /* 0111 010w 0001 srcx  STE.size src,disp20[a0] */
+ 
+   sc = decode_srcdest4 (srcx, w);
+   a = get_reg(a0) + IMM(2);
+   v = get_src (sc);
+   if (w)
+     mem_put_hi (a, v);
+   else
+     mem_put_qi (a, v);
+   if (srcx == 4 || srcx == 5)
+     {
+       v = get_reg (sc.u.reg);
+       set_sz (v, 2);
+     }
+   else
+     set_sz (v, w+1);
+ 
+   /* 0111 010w 0010 srcx  STE.size src,[a1a0] */
+ 
+   sc = decode_srcdest4 (srcx, w);
+   a = get_reg(a1a0);
+   v = get_src (sc);
+   if (w)
+     mem_put_hi (a, v);
+   else
+     mem_put_qi (a, v);
+   if (srcx == 4 || srcx == 5)
+     {
+       v = get_reg (sc.u.reg);
+       set_sz (v, 2);
+     }
+   else
+     set_sz (v, w+1);
+ 
+   /* 1101 0dst            STNZ #IMM8,dest */
+ 
+   imm = IMM(0);
+   dc = decode_dest3(dst, 0);
+   if (!FLAG_Z)
+     put_dest (dc, imm);
+ 
+   /* 1100 1dst            STZ #IMM8,dest */
+ 
+   imm = IMM(0);
+   dc = decode_dest3(dst, 0);
+   if (FLAG_Z)
+     put_dest (dc, imm);
+ 
+   /* 1101 1dst            STZX #IMM81,#IMM82,dest */
+ 
+   a = IMM(0);
+   dc = decode_dest3(dst, 0);
+   b = IMM(0);
+   if (FLAG_Z)
+     put_dest (dc, a);
+   else
+     put_dest (dc, b);
+ 
+   /* 0111 011w 0101 dest  SUB.size:G #IMM,dest */
+ 
+   dc = decode_srcdest4 (dest, w);
+   imm = IMM(w);
+   MATH_OP (dc, imm, 0, -, >= 0);
+ 
+   /* 1000 1dst            SUB.B:S #IMM8,dest */
+ 
+   imm = IMM(0);
+   dc = decode_dest3 (dst, 0);
+   MATH_OP (dc, imm, 0, -, >= 0);
+ 
+   /* 1010 100w srcx dest  SUB.size:G src,dest */
+ 
+   sc = decode_srcdest4(srcx, w);
+   dc = decode_srcdest4(dest, w);
+   b = get_src (sc);
+   MATH_OP (dc, b, 0, -, > 0);
+ 
+   /* 0010 1d sr           SUB.B:S src,R0L/R0H */
+ 
+   sc = decode_src2 (sr, 0, d);
+   dc = decode_dest1 (d, 0);
+   b = get_src (sc);
+   MATH_OP (dc, b, 0, -, > 0);
+ 
+   /* 0111 011w 0000 dest  TST.size #IMM, dest */
+ 
+   UNARY_UOP;
+   imm = IMM(w);
+   tprintf ("%x & %x = %x\n", v, imm, v & imm);
+   v &= imm;
+   set_sz (v, w+1);
+ 
+   /* 1000 000w srcx dest  TST.size src,dest */
+ 
+   BINARY_UOP;
+   tprintf ("%x & %x = %x\n", a, b, a & b);
+   v = a & b;
+   set_sz (v, w+1);
+ 
+   /* 1111 1111            UND */
+ 
+   trigger_fixed_interrupt (0xffdc);
+ 
+   /* 0111 1101 1111 0011  WAIT */
+ 
+   tprintf("waiting...\n");
+ 
+   /* 0111 101w 00sr dest  XCHG.size src,dest */
+ 
+   sc = decode_srcdest4 (sr, w);
+   dc = decode_srcdest4 (dest, w);
+   a = get_src (sc);
+   b = get_src (dc);
+   put_dest (dc, a);
+   put_dest (sc, b);
+ 
+   /* 0111 011w 0001 dest  XOR.size #IMM,dest */
+ 
+   UNARY_UOP;
+   imm = IMM(w);
+   tprintf ("%x ^ %x = %x\n", v, imm, v ^ imm);
+   v ^= imm;
+   set_sz (v, w+1);
+   put_dest (dc, v);
+ 
+   /* 1000 100w srcx dest  XOR.size src,dest */
+ 
+   BINARY_UOP;
+   tprintf ("%x ^ %x = %x\n", a, b, a ^ b);
+   v = a ^ b;
+   set_sz (v, w+1);
+   put_dest (dc, v);
+   
+   /*                      OP */
+ /* */
+ 
+   return step_result;
+ }
Index: sim/m32c/reg.c
===================================================================
RCS file: sim/m32c/reg.c
diff -N sim/m32c/reg.c
*** sim/m32c/reg.c	1 Jan 1970 00:00:00 -0000
--- sim/m32c/reg.c	6 Oct 2005 22:36:52 -0000
***************
*** 0 ****
--- 1,542 ----
+ #include <stdio.h>
+ #include <stdlib.h>
+ #include <string.h>
+ 
+ #include "cpu.h"
+ 
+ int verbose = 0;
+ int trace = 0;
+ int enable_counting = 0;
+ 
+ regs_type regs;
+ int addr_mask = 0xffff;
+ int membus_mask = 0xfffff;
+ int m32c_cpu = 0;
+ int step_result;
+ unsigned int heapbottom = 0;
+ unsigned int heaptop = 0;
+ 
+ char *reg_names[] = {
+   "mem",
+   "r0", "r0h", "r0l",
+   "r1", "r1h", "r1l",
+   "r2", "r2r0",
+   "r3", "r3r1",
+   "r3r1r2r0",
+   "r3r2r1r0",
+   "a0",
+   "a1", "a1a0",
+   "sb", "fb",
+   "intb", "intbl", "intbh",
+   "sp", "usp", "isp", "pc", "flags"
+ };
+ 
+ int reg_bytes[] = {
+   0,
+   2, 1, 1,
+   2, 1, 1,
+   2, 4,
+   2, 4,
+   8,
+   8,
+   2,
+   2, 4,
+   2, 2,
+   2, 1, 3,
+   2, 2, 2, 3, 2
+ };
+ 
+ 
+ unsigned int b2mask[] = { 0, 0xff, 0xffff, 0xffffff, 0xffffffff };
+ unsigned int b2signbit[] = { 0, (1<<7), (1<<15), (1<<24), (1<<31) };
+ int b2maxsigned[] = { 0, 0x7f, 0x7fff, 0x7fffff, 0x7fffffff };
+ int b2minsigned[] = { 0, -128, -32768, -8388608, -2147483647-1 };
+ 
+ static regs_type oldregs;
+ 
+ void
+ init_regs (void)
+ {
+   memset (&regs, 0, sizeof (regs));
+   memset (&oldregs, 0, sizeof (oldregs));
+ }
+ 
+ void
+ set_pointer_width (int bytes)
+ {
+   if (bytes == 2)
+     {
+       addr_mask = 0xffff;
+       membus_mask = 0x000fffff;
+       reg_bytes[a0] = reg_bytes[a1] = reg_bytes[sb] = reg_bytes[fb] =
+ 	reg_bytes[sp] = reg_bytes[usp] = reg_bytes[isp] = 2;
+     }
+   else
+     {
+       addr_mask = 0xffffff;
+       membus_mask = 0x00ffffff;
+       reg_bytes[a0] = reg_bytes[a1] = reg_bytes[sb] = reg_bytes[fb] =
+ 	reg_bytes[sp] = reg_bytes[usp] = reg_bytes[isp] = 3;
+     }
+ }
+ 
+ void
+ m32c_set_cpu (int cpu)
+ {
+   switch (cpu)
+     {
+     case CPU_R8C:
+     case CPU_M16C:
+       set_pointer_width (2);
+       decode_opcode = decode_r8c;
+       break;
+     case CPU_M32CM:
+     case CPU_M32C:
+       set_pointer_width (3);
+       decode_opcode = decode_m32c;
+       break;
+     default:
+       abort();
+     }
+   m32c_cpu = cpu;
+ }
+ 
+ static unsigned int
+ get_reg_i (reg_id id)
+ {
+   reg_bank_type *b = regs.r + (FLAG_B ? 1 : 0);
+ 
+   switch (id)
+     {
+     case r0:
+       return b->r_r0;
+     case r0h:
+       return b->r_r0 >> 8;
+     case r0l:
+       return b->r_r0 & 0xff;
+     case r1:
+       return b->r_r1;
+     case r1h:
+       return b->r_r1 >> 8;
+     case r1l:
+       return b->r_r1 & 0xff;
+     case r2:
+       return b->r_r2;
+     case r2r0:
+       return b->r_r2 * 65536 + b->r_r0;
+     case r3:
+       return b->r_r3;
+     case r3r1:
+       return b->r_r3 * 65536 + b->r_r1;
+ 
+     case a0:
+       return b->r_a0 & addr_mask;
+     case a1:
+       return b->r_a1 & addr_mask;
+     case a1a0:
+       return (b->r_a1 & 0xffff) * 65536 | (b->r_a0 & 0xffff);
+ 
+     case sb:
+       return b->r_sb & addr_mask;
+     case fb:
+       return b->r_fb & addr_mask;
+ 
+     case intb:
+       return regs.r_intbh * 65536 + regs.r_intbl;
+     case intbl:
+       return regs.r_intbl;
+     case intbh:
+       return regs.r_intbh;
+ 
+     case sp:
+       return ((regs.r_flags & FLAGBIT_U) ? regs.r_usp : regs.r_isp) & addr_mask;
+     case usp:
+       return regs.r_usp & addr_mask;
+     case isp:
+       return regs.r_isp & addr_mask;
+ 
+     case pc:
+       return regs.r_pc & membus_mask;
+     case flags:
+       return regs.r_flags;
+     default:
+       abort();
+     }
+ }
+ 
+ unsigned int
+ get_reg (reg_id id)
+ {
+   unsigned int rv = get_reg_i (id);
+   if (trace > ((id != pc && id != fb && id != sp) ? 0 : 1))
+     printf("get_reg (%s) = %0*x\n", reg_names[id], reg_bytes[id]*2, rv);
+   return rv;
+ }
+ 
+ DI
+ get_reg_ll (reg_id id)
+ {
+   reg_bank_type *b = regs.r + (FLAG_B ? 1 : 0);
+ 
+   switch (id)
+     {
+     case r3r1r2r0:
+       return ((DI)b->r_r3 << 48
+ 	      | (DI)b->r_r1 << 32
+ 	      | (DI)b->r_r2 << 16
+ 	      | (DI)b->r_r0);
+     case r3r2r1r0:
+       return ((DI)b->r_r3 << 48
+ 	      | (DI)b->r_r2 << 32
+ 	      | (DI)b->r_r1 << 16
+ 	      | (DI)b->r_r0);
+     default:
+       return get_reg (id);
+     }
+ }
+ 
+ static int highest_sp=0, lowest_sp=0xffffff;
+ 
+ void
+ stack_heap_stats ()
+ {
+   printf("heap:  %08x - %08x (%d bytes)\n", heapbottom, heaptop, heaptop-heapbottom);
+   printf("stack: %08x - %08x (%d bytes)\n", lowest_sp, highest_sp, highest_sp - lowest_sp);
+ }
+ 
+ void
+ put_reg (reg_id id, unsigned int v)
+ {
+   if (trace > ((id != pc) ? 0 : 1))
+     printf("put_reg (%s) = %0*x\n", reg_names[id], reg_bytes[id]*2, v);
+     
+   reg_bank_type *b = regs.r + (FLAG_B ? 1 : 0);
+   switch (id)
+     {
+     case r0:
+       b->r_r0 = v;
+       break;
+     case r0h:
+       b->r_r0 = (b->r_r0 & 0xff) | (v << 8);
+       break;
+     case r0l:
+       b->r_r0 = (b->r_r0 & 0xff00) | (v & 0xff);
+       break;
+     case r1:
+       b->r_r1 = v;
+       break;
+     case r1h:
+       b->r_r1 = (b->r_r1 & 0xff) | (v << 8);
+       break;
+     case r1l:
+       b->r_r1 = (b->r_r1 & 0xff00) | (v & 0xff);
+       break;
+     case r2:
+       b->r_r2 = v;
+       break;
+     case r2r0:
+       b->r_r0 = v & 0xffff;
+       b->r_r2 = v >> 16;
+       break;
+     case r3:
+       b->r_r3 = v;
+       break;
+     case r3r1:
+       b->r_r1 = v & 0xffff;
+       b->r_r3 = v >> 16;
+       break;
+ 
+     case a0:
+       b->r_a0 = v & addr_mask;
+       break;
+     case a1:
+       b->r_a1 = v & addr_mask;
+       break;
+     case a1a0:
+       b->r_a0 = v & 0xffff;
+       b->r_a1 = v >> 16;
+       break;
+ 
+     case sb:
+       b->r_sb = v & addr_mask;
+       break;
+     case fb:
+       b->r_fb = v & addr_mask;
+       break;
+ 
+     case intb:
+       regs.r_intbl = v & 0xffff;
+       regs.r_intbh = v >> 16;
+       break;
+     case intbl:
+       regs.r_intbl = v & 0xffff;
+       break;
+     case intbh:
+       regs.r_intbh = v & 0xff;
+       break;
+ 
+     case sp:
+       {
+ 	SI *spp;
+ 	if (regs.r_flags & FLAGBIT_U)
+ 	  spp = &regs.r_usp;
+ 	else
+ 	  spp = &regs.r_isp;
+ 	*spp = v & addr_mask;
+ 	if (*spp < heaptop)
+ 	  {
+ 	    printf("collision: pc %08lx heap %08x stack %08lx\n", regs.r_pc, heaptop, *spp);
+ 	    exit(1);
+ 	  }
+ 	if (*spp < lowest_sp)
+ 	  lowest_sp = *spp;
+ 	if (*spp > highest_sp)
+ 	  highest_sp = *spp;
+ 	break;
+       }
+     case usp:
+       regs.r_usp = v & addr_mask;
+       break;
+     case isp:
+       regs.r_isp = v & addr_mask;
+       break;
+ 
+     case pc:
+       regs.r_pc = v & membus_mask;
+       break;
+     case flags:
+       regs.r_flags = v;
+       break;
+     default:
+       abort();
+     }
+ }
+ 
+ int
+ condition_true (int cond_id)
+ {
+   int f;
+   if (A16)
+     {
+       static const char *cond_name[] = {
+ 	"C", "C&!Z", "Z", "S",
+ 	"!C", "!(C&!Z)", "!Z", "!S",
+ 	"(S^O)|Z", "O", "!(S^O)", "unk",
+ 	"!((S^O)|Z)", "!O", "S^O", "unk"};
+       switch (cond_id)
+ 	{
+ 	case 0: f = FLAG_C; break; /* GEU/C */
+ 	case 1: f = FLAG_C & ! FLAG_Z; break; /* GTU */
+ 	case 2: f = FLAG_Z; break; /* EQ/Z*/
+ 	case 3: f = FLAG_S; break; /* N */
+ 	case 4: f = ! FLAG_C; break; /* LTU/NC */
+ 	case 5: f = ! (FLAG_C & !FLAG_Z); break; /* LEU */
+ 	case 6: f = ! FLAG_Z; break; /* NE/NZ */
+ 	case 7: f = ! FLAG_S; break; /* PZ */
+ 
+ 	case 8: f = (FLAG_S ^ FLAG_O) | FLAG_Z; break; /* LE */
+ 	case 9: f = FLAG_O; break; /* O */
+ 	case 10: f = !(FLAG_S ^ FLAG_O); break; /* GE */
+ 	case 12: f = !((FLAG_S ^ FLAG_O) | FLAG_Z); break; /* GT */
+ 	case 13: f = ! FLAG_O; break; /* NO */
+ 	case 14: f = FLAG_S ^ FLAG_O; break; /* LT */
+ 
+ 	default:
+ 	  f = 0;
+ 	  break;
+ 	}
+       if (trace)
+ 	printf("cond[%d] %s = %s\n", cond_id, cond_name[cond_id&15], f?"true":"false");
+     }
+   else
+     {
+       static const char *cond_name[] = {
+ 	"!C", "LEU", "!Z", "PZ",
+ 	"!O", "GT", "GE", "?",
+ 	"C", "GTU", "Z", "N",
+ 	"O", "LE", "LT", "!?"};
+       switch (cond_id)
+ 	{
+ 	case 0: f = ! FLAG_C; break; /* LTU/NC */
+ 	case 1: f = ! (FLAG_C & !FLAG_Z); break; /* LEU */
+ 	case 2: f = ! FLAG_Z; break; /* NE/NZ */
+ 	case 3: f = ! FLAG_S; break; /* PZ */
+ 
+ 	case 4: f = ! FLAG_O; break; /* NO */
+ 	case 5: f = !((FLAG_S ^ FLAG_O) | FLAG_Z); break; /* GT */
+ 	case 6: f = !(FLAG_S ^ FLAG_O); break; /* GE */
+ 
+ 	case 8: f = FLAG_C; break; /* GEU/C */
+ 	case 9: f = FLAG_C & ! FLAG_Z; break; /* GTU */
+ 	case 10: f = FLAG_Z; break; /* EQ/Z*/
+ 	case 11: f = FLAG_S; break; /* N */
+ 
+ 	case 12: f = FLAG_O; break; /* O */
+ 	case 13: f = (FLAG_S ^ FLAG_O) | FLAG_Z; break; /* LE */
+ 	case 14: f = FLAG_S ^ FLAG_O; break; /* LT */
+ 
+ 	default:
+ 	  f = 0;
+ 	  break;
+ 	}
+       if (trace)
+ 	printf("cond[%d] %s = %s\n", cond_id, cond_name[cond_id&15], f?"true":"false");
+     }
+   return f;
+ }
+ 
+ void
+ set_flags (int mask, int newbits)
+ {
+   int i;
+   regs.r_flags &= ~mask;
+   regs.r_flags |= newbits & mask;
+   if (trace)
+     {
+       printf("flags now \033[32m %d", (regs.r_flags >> (A16 ? 8 : 12))&7);
+       for (i=7; i>=0; i--)
+ 	if (regs.r_flags & (1<<i))
+ 	  putchar("CDZSBOIU"[i]);
+ 	else
+ 	  putchar('-');
+       printf("\033[0m\n");
+     }
+ }
+ 
+ void
+ set_oszc (int value, int b, int c)
+ {
+   int mask = b2mask[b];
+   int f = 0;
+ 
+   if (c)
+     f |= FLAGBIT_C;
+   if ((value & mask) == 0)
+     f |= FLAGBIT_Z;
+   if (value & b2signbit[b])
+     f |= FLAGBIT_S;
+   if ((value > b2maxsigned[b])
+       || (value < b2minsigned[b]))
+     f |= FLAGBIT_O;
+   set_flags (FLAGBIT_Z | FLAGBIT_S | FLAGBIT_O | FLAGBIT_C, f);
+ }
+ 
+ void
+ set_szc (int value, int b, int c)
+ {
+   int mask = b2mask[b];
+   int f = 0;
+ 
+   if (c)
+     f |= FLAGBIT_C;
+   if ((value & mask) == 0)
+     f |= FLAGBIT_Z;
+   if (value & b2signbit[b])
+     f |= FLAGBIT_S;
+   set_flags (FLAGBIT_Z | FLAGBIT_S | FLAGBIT_C, f);
+ }
+ 
+ void
+ set_osz (int value, int b)
+ {
+   int mask = b2mask[b];
+   int f = 0;
+ 
+   if ((value & mask) == 0)
+     f |= FLAGBIT_Z;
+   if (value & b2signbit[b])
+     f |= FLAGBIT_S;
+   if (value & ~mask
+       && (value & ~mask) != ~mask)
+     f |= FLAGBIT_O;
+   set_flags (FLAGBIT_Z | FLAGBIT_S | FLAGBIT_O, f);
+ }
+ 
+ void
+ set_sz (int value, int b)
+ {
+   int mask = b2mask[b];
+   int f = 0;
+ 
+   if ((value & mask) == 0)
+     f |= FLAGBIT_Z;
+   if (value & b2signbit[b])
+     f |= FLAGBIT_S;
+   set_flags (FLAGBIT_Z | FLAGBIT_S, f);
+ }
+ 
+ void
+ set_zc (int z, int c)
+ {
+   set_flags (FLAGBIT_C | FLAGBIT_Z, (c ? FLAGBIT_C : 0) | (z ? FLAGBIT_Z : 0));
+ }
+ 
+ void
+ set_c (int c)
+ {
+   set_flags (FLAGBIT_C, c ? FLAGBIT_C : 0);
+ }
+ 
+ void
+ put_reg_ll (reg_id id, DI v)
+ {
+   reg_bank_type *b = regs.r + (FLAG_B ? 1 : 0);
+ 
+   switch (id)
+     {
+     case r3r1r2r0:
+       b->r_r3 = v>>48;
+       b->r_r1 = v>>32;
+       b->r_r2 = v>>16;
+       b->r_r0 = v;
+       break;
+     case r3r2r1r0:
+       b->r_r3 = v>>48;
+       b->r_r2 = v>>32;
+       b->r_r1 = v>>16;
+       b->r_r0 = v;
+       break;
+     default:
+       put_reg (id, v);
+     }
+ }
+ 
+ #define TRC(f,n, id) \
+   if (oldregs.f != regs.f) \
+     { \
+       printf("  %s %0*x:%0*x", n, \
+ 	     reg_bytes[id]*2, (unsigned int)oldregs.f, \
+ 	     reg_bytes[id]*2, (unsigned int)regs.f); \
+       oldregs.f = regs.f; \
+     }
+ 
+ void
+ trace_register_changes ()
+ {
+   if (!trace)
+     return;
+   printf("\033[36mREGS:");
+   TRC(r[0].r_r0, "r0", r0);
+   TRC(r[0].r_r1, "r1", r1);
+   TRC(r[0].r_r2, "r2", r2);
+   TRC(r[0].r_r3, "r3", r3);
+   TRC(r[0].r_a0, "a0", a0);
+   TRC(r[0].r_a1, "a1", a1);
+   TRC(r[0].r_sb, "sb", sb);
+   TRC(r[0].r_fb, "fb", fb);
+   TRC(r[1].r_r0, "r0'", r0);
+   TRC(r[1].r_r1, "r1'", r1);
+   TRC(r[1].r_r2, "r2'", r2);
+   TRC(r[1].r_r3, "r3'", r3);
+   TRC(r[1].r_a0, "a0'", a0);
+   TRC(r[1].r_a1, "a1'", a1);
+   TRC(r[1].r_sb, "sb'", sb);
+   TRC(r[1].r_fb, "fb'", fb);
+   TRC(r_intbh, "intbh", intbh);
+   TRC(r_intbl, "intbl", intbl);
+   TRC(r_usp, "usp", usp);
+   TRC(r_isp, "isp", isp);
+   TRC(r_pc, "pc", pc);
+   TRC(r_flags, "flags", flags);
+   printf("\033[0m\n");
+ }
Index: sim/m32c/run-m32c.cc
===================================================================
RCS file: sim/m32c/run-m32c.cc
diff -N sim/m32c/run-m32c.cc
*** sim/m32c/run-m32c.cc	1 Jan 1970 00:00:00 -0000
--- sim/m32c/run-m32c.cc	6 Oct 2005 22:36:53 -0000
***************
*** 0 ****
--- 1,1140 ----
+ #include <sstream>
+ #include <string>
+ #include <iostream>
+ #include <sys/types.h>
+ #include <unistd.h>
+ #include <sys/stat.h>
+ #include <sys/mman.h> /* mmap() is defined in this header */
+ #include <fcntl.h>
+ #include <stdlib.h>
+ #include <stdio.h>
+ extern "C" {
+ #include "elfload.h"
+ }
+ 
+ #define USI unsigned long
+ #define SI long
+ #define UHI unsigned short
+ #define HI short
+ #define UQI unsigned char
+ #define QI char
+ 
+ enum modes_t {qi=0, hi=1, si=2};
+ enum op_fetch_t {src_op=1, dest_op=0};
+ 
+ class m32c_cpu_type
+ {
+  public:
+ 
+   // CPU state information.
+ 
+   // Hardware elements.
+   union r2r0 {
+     int r2r0;
+     struct hi
+     {
+       HI r2;
+       HI r0;
+     } hi;
+     struct qi
+     {
+       QI r2l;
+       QI r2h;
+       QI r0l;
+       QI r0h;
+     } qi;
+   } r2r0;
+   union r3r1 {
+     int r3r1;
+     struct hi
+     {
+       HI r3;
+       HI r1;
+     } hi;
+     struct qi
+     {
+       QI r3l;
+       QI r3h;
+       QI r1l;
+       QI r1h;
+     } qi;
+   } r3r1;
+   union a1a0 
+   {
+     int a1a0;
+     struct hi
+     {
+       HI a1;
+       HI a0;
+     } hi;
+   } a1a0;
+   HI h_sb;
+   HI h_sp;
+   HI h_fb;
+ 
+   union memory
+   {
+     QI qi [16 * 1024];
+     HI hi [8 * 1024];
+     int si [4 * 1024];
+   } memory;
+   
+   /* program counter */
+   int h_pc;
+ 
+   /* flags */
+   union flags
+   {
+     QI flags;
+     struct
+     {
+       int u : 1;
+       int i : 1;
+       int o : 1;
+       int b : 1;
+       int s : 1;
+       int z : 1;
+       int d : 1;
+       int c : 1;
+     } flag;
+   } flags;
+ 
+   /* program text */
+   union text
+   {
+     QI *h_qitext;
+     HI *h_hitext;
+   } text;
+ 
+   inline std::string h_gregname (int regno, modes_t mode)
+     {
+       switch (regno)
+ 	{
+ 	case 0:
+ 	  switch (mode)
+ 	    {
+ 	    case qi: return "r0l";
+ 	    case hi: return "r0";
+ 	    case si: return "r2r0";
+ 	    }
+ 	case 1:
+ 	  switch (mode)
+ 	    {
+ 	    case qi: return "r0h";
+ 	    case hi: return "r1";
+ 	    case si: return "r3r1";
+ 	    }
+ 	case 2:
+ 	  switch (mode)
+ 	    {
+ 	    case qi: return "r1l";
+ 	    case hi: return "r2";
+ 	    }
+ 	case 3:
+ 	  switch (mode)
+ 	    {
+ 	    case qi: return "r1h";
+ 	    case hi: return "r3";
+ 	    }
+ 	}
+     }
+ 
+   inline std::string h_aregname (int regno, modes_t mode)
+     {
+       switch (regno)
+ 	{
+ 	case 0:
+ 	  switch (mode)
+ 	    {
+ 	    case hi: return "a0";
+ 	    case si: return "a1a0";
+ 	    }
+ 	case 1:
+ 	  switch (mode)
+ 	    {
+ 	    case hi: return "a1";
+ 	    }
+ 	}
+     }
+   
+   // C++ register access function templates
+ #define current_cpu this
+   inline int h_rget (int regno, modes_t mode) const
+     {
+       switch (mode)
+ 	{
+ 	case qi:
+ 	  switch (regno)
+ 	    {
+ 	    case 0: return this->r2r0.qi.r0l;
+ 	    case 1: return this->r2r0.qi.r0h;
+ 	    case 2: return this->r3r1.qi.r1l;
+ 	    case 3: return this->r3r1.qi.r1h;
+ 	    }
+ 	case hi:
+ 	  switch (regno)
+ 	    {
+ 	    case 0: return this->r2r0.hi.r0;
+ 	    case 1: return this->r3r1.hi.r1;
+ 	    case 2: return this->r2r0.hi.r2;
+ 	    case 3: return this->r3r1.hi.r3;
+ 	    }
+ 	case si:
+ 	  switch (regno)
+ 	    {
+ 	    case 0: return this->r2r0.r2r0;
+ 	    case 1: return this->r3r1.r3r1;
+ 	    }
+ 	}
+     }
+   
+ 
+   inline int h_rset (int regno, modes_t mode, int newval)
+     {
+       switch (mode)
+ 	{
+ 	case qi:
+ 	  switch (regno)
+ 	    {
+ 	    case 0: return this->r2r0.qi.r0l = newval;
+ 	    case 1: return this->r2r0.qi.r0h = newval;
+ 	    case 2: return this->r3r1.qi.r1l = newval;
+ 	    case 3: return this->r3r1.qi.r1h = newval;
+ 	    }
+ 	case hi:
+ 	  switch (regno)
+ 	    {
+ 	    case 0: return this->r2r0.hi.r0 = newval;
+ 	    case 1: return this->r3r1.hi.r1 = newval;
+ 	    case 2: return this->r2r0.hi.r2 = newval;
+ 	    case 3: return this->r3r1.hi.r3 = newval;
+ 	    }
+ 	case si:
+ 	  switch (regno)
+ 	    {
+ 	    case 0: return this->r2r0.r2r0 = newval;
+ 	    case 1: return this->r3r1.r3r1 = newval;
+ 	    }
+ 	}
+     }
+ 
+   inline unsigned HI h_ahi_get (int regno) const
+     {
+       switch (regno)
+ 	{
+ 	case 1: return this->a1a0.hi.a1;
+ 	case 0: return this->a1a0.hi.a0;
+ 	}
+     }
+   inline unsigned HI h_ahi_set (int regno, HI newval)
+     {
+       switch (regno)
+ 	{
+ 	case 1: return this->a1a0.hi.a1 = newval;
+ 	case 0: return this->a1a0.hi.a0 = newval;
+ 	}
+     }
+ 
+   inline int h_memget (int address, modes_t mode)
+     {
+       if (mode == qi)
+ 	return this->memory.qi[address];
+       else if (mode == hi)
+ 	return this->memory.hi[address / 2];
+       else if (mode == si)
+ 	return this->memory.hi[address / 4];
+     }
+ 
+   inline int h_memset (int address, int newval, modes_t mode)
+     {
+       if (mode == qi)
+ 	return this->memory.qi[address] = newval;
+       else if (mode == hi)
+ 	return this->memory.hi[address / 2] = newval;
+       else if (mode == si)
+ 	return this->memory.hi[address / 4] = newval;
+     }
+ 
+   inline int h_sb_get () const { return this->h_sb; }
+   inline int h_fb_get () const { return this->h_fb; }
+   inline int h_sp_get () const { return this->h_sp; }
+   inline void h_sp_set (int newval) { this->h_sp = newval; }
+   inline int h_pc_get () const { return this->h_pc; }
+   inline int h_flag_c_get () const { return this->flags.flag.c; }
+   inline void h_flag_c_set (int newval) { this->flags.flag.c = newval; }
+   inline int h_flag_o_get () const { return this->flags.flag.o; }
+   inline void h_flag_o_set (int newval) { this->flags.flag.o = newval; }
+   inline int h_flag_s_get () const { return this->flags.flag.s; }
+   inline void h_flag_s_set (int newval) { this->flags.flag.s = newval; }
+   inline int h_flag_z_get () const { return this->flags.flag.z; }
+   inline void h_flag_z_set (int newval) { this->flags.flag.z = newval; }
+   inline void h_pc_inc (int newval) { this->h_pc = this->h_pc + newval; }
+   inline void h_pc_set (int newval) { this->h_pc = newval; }
+   inline void h_fb_set (int newval) { this->h_fb = newval; }
+   inline QI* h_qitext_get () const { return this->text.h_qitext; }
+   inline void h_qitext_set (QI* newval) { this->text.h_qitext = newval; }
+   inline HI* h_hitext_get () const { return this->text.h_hitext; }
+   inline void h_hitext_set (HI* newval) { this->text.h_hitext = newval; }
+ 
+   std::string insn_str;
+   std::string trace_str;
+   unsigned long long raw_insn;
+ } m32c_cpu;
+ 
+ bool disassemble = true;
+ 
+ bool
+ addhi_cf (HI s1, HI s2)
+   {
+     return (UHI)((UHI)s1 + (UHI)s2)
+       < (UHI)s1;
+   }
+ 
+ bool
+ subhi_cf (HI s1, HI s2)
+   {
+     return (UHI)s1 < (UHI)s2;
+   }
+ 
+ bool
+ addhi_of (HI s1, HI s2)
+   {
+     return ((((HI)s1 < 0) == ((HI)s2 < 0))
+ 	   && (((HI)s1 < 0) != (((HI)((HI)s1 + (HI)s2)) < 0)));
+   }
+ 
+ bool
+ subhi_of (HI s1, HI s2)
+   {
+     return ((((HI)s1 < 0) == ((HI)s2 < 0))
+      && (((HI)s1 < 0) != (((HI)((HI)s1 - (HI)s2)) < 0)));
+   }
+ 
+ 
+ bool
+ addqi_cf (QI s1, QI s2)
+   {
+     return (UQI)((UQI)s1 + (UQI)s2)
+       < (UQI)s1;
+   }
+ 
+ bool
+ subqi_cf (QI s1, QI s2)
+   {
+     return (UQI)s1 < (UQI)s2;
+   }
+ 
+ bool
+ addqi_of (QI s1, QI s2)
+   {
+     return ((((QI)s1 < 0) == ((QI)s2 < 0))
+ 	   && (((QI)s1 < 0) != (((QI)((QI)s1 + (QI)s2)) < 0)));
+   }
+ 
+ bool
+ subqi_of (QI s1, QI s2)
+   {
+     return ((((QI)s1 < 0) == ((QI)s2 < 0))
+      && (((QI)s1 < 0) != (((QI)((QI)s1 - (QI)s2)) < 0)));
+   }
+ 
+ 
+ HI
+ get_bits (const void *p, int bits, int big_p)
+ {
+   const QI *addr = (QI*)p;
+   HI data;
+   int i;
+   int bytes;
+  
+   if (bits % 8 != 0)
+     abort ();
+  
+   data = 0;
+   bytes = bits / 8;
+   for (i = 0; i < bytes; i++)
+     {
+       int index = big_p ? i : bytes - i - 1;
+       data = (USI)(data << 8) | (UQI)addr[index];
+     }
+   return data;
+ }
+ 
+ std::string int_to_string (HI x)
+ {
+   std::ostringstream o;
+   if (o << "0x" << std::hex << x)
+     return o.str();
+   return "conversion error";
+ }
+ 
+ int
+ get_src (int src, modes_t mode, bool inc_pc)
+ {
+   int offset;
+   QI *qi_addr;
+   HI *hi_addr;
+   
+   switch (src)
+     {
+     case 0:
+       if (inc_pc)
+ 	m32c_cpu.insn_str = m32c_cpu.insn_str + m32c_cpu.h_gregname (0, mode) + ",";
+ //       m32c_cpu.trace_str = m32c_cpu.h_gregname (0, mode) + "="
+ // 	+ int_to_string (m32c_cpu.h_rget (0, mode));
+       return m32c_cpu.h_rget (0, mode);
+     case 1:
+       if (inc_pc)
+ 	m32c_cpu.insn_str = m32c_cpu.insn_str + m32c_cpu.h_gregname (1, mode);
+ //       m32c_cpu.trace_str = m32c_cpu.h_gregname (1, mode) + "="
+ // 	+ int_to_string (m32c_cpu.h_rget (1, mode));
+       return m32c_cpu.h_rget (1, mode);
+     case 2:
+       if (inc_pc)
+ 	m32c_cpu.insn_str = m32c_cpu.insn_str + m32c_cpu.h_gregname (2, mode);
+ //       m32c_cpu.trace_str = m32c_cpu.h_gregname (2, mode) + "="
+ // 	+ int_to_string (m32c_cpu.h_rget (2, mode));
+       return m32c_cpu.h_rget (2, mode);
+     case 3:
+       if (inc_pc)
+ 	m32c_cpu.insn_str = m32c_cpu.insn_str + m32c_cpu.h_gregname (3, mode);
+ //       m32c_cpu.trace_str = m32c_cpu.h_gregname (3, mode) + "="
+ // 	+ int_to_string (m32c_cpu.h_rget (3, mode));
+       return m32c_cpu.h_rget (3, mode);
+     case 4:
+       if (inc_pc)
+ 	m32c_cpu.insn_str = m32c_cpu.insn_str + m32c_cpu.h_aregname (0, mode);
+ //       m32c_cpu.trace_str = m32c_cpu.h_aregname (0, mode) + "="
+ // 	+ int_to_string (m32c_cpu.h_ahi_get (0));
+       return m32c_cpu.h_ahi_get (0);
+     case 5:
+       if (inc_pc)
+ 	m32c_cpu.insn_str = m32c_cpu.insn_str + m32c_cpu.h_aregname (1, mode);
+ //       m32c_cpu.trace_str = m32c_cpu.h_aregname (1, mode) + "="
+ // 	+ int_to_string (m32c_cpu.h_ahi_get (1));
+       return m32c_cpu.h_ahi_get (1);
+     case 6:
+       if (inc_pc)
+ 	m32c_cpu.insn_str = m32c_cpu.insn_str + "[a0]";
+ //       m32c_cpu.trace_str = int_to_string (m32c_cpu.h_ahi_get (0)) + "="
+ // 	+ int_to_string (m32c_cpu.h_memget (m32c_cpu.h_ahi_get (0), mode));
+       return m32c_cpu.h_memget (m32c_cpu.h_ahi_get (0), mode);
+     case 7:
+       if (inc_pc)
+ 	m32c_cpu.insn_str = m32c_cpu.insn_str + "[a1],";
+ //       m32c_cpu.trace_str = int_to_string (m32c_cpu.h_ahi_get (1)) + "="
+ // 	+ int_to_string (m32c_cpu.h_memget (m32c_cpu.h_ahi_get (1), mode));
+       return m32c_cpu.h_memget (m32c_cpu.h_ahi_get (1), mode);
+     case 8:
+       {
+ 	qi_addr = m32c_cpu.h_qitext_get() + m32c_cpu.h_pc_get();
+ 	offset = get_bits (qi_addr, 8, 0);
+ 	if (inc_pc)
+ 	  {
+ 	    m32c_cpu.insn_str = m32c_cpu.insn_str + int_to_string (offset)
+ 	      + "[a0],";
+ 	    m32c_cpu.raw_insn = (m32c_cpu.raw_insn << 8) + offset;
+ 	    m32c_cpu.h_pc_inc(1);
+ 	  }
+ // 	m32c_cpu.trace_str = int_to_string (m32c_cpu.h_ahi_get (0) + offset)
+ // 	  + "=" + int_to_string (m32c_cpu.h_memget (m32c_cpu.h_ahi_get (0) + offset, qi));
+ 	return m32c_cpu.h_memget (m32c_cpu.h_ahi_get (0) + offset, qi);
+       }
+     case 9:
+       {
+ 	qi_addr = m32c_cpu.h_qitext_get() + m32c_cpu.h_pc_get();
+ 	offset = get_bits (qi_addr, 8, 0);
+ 	if (inc_pc)
+ 	  {
+ 	    m32c_cpu.insn_str = m32c_cpu.insn_str + int_to_string (offset)
+ 	      + "[a1],";
+ 	    m32c_cpu.raw_insn = (m32c_cpu.raw_insn << 8) + offset;
+ 	    m32c_cpu.h_pc_inc(1);
+ 	  }
+ // 	m32c_cpu.trace_str = int_to_string (m32c_cpu.h_ahi_get (1) + offset)
+ // 	  + "=" + int_to_string (m32c_cpu.h_memget (m32c_cpu.h_ahi_get (1) + offset, qi));
+ 	return m32c_cpu.h_memget (m32c_cpu.h_ahi_get (1) + offset, qi);
+       }
+     case 10:
+       {
+ 	qi_addr = m32c_cpu.h_qitext_get() + m32c_cpu.h_pc_get();
+ 	offset = get_bits (qi_addr, 8, 0);
+ 	if (inc_pc)
+ 	  {
+ 	    m32c_cpu.insn_str = m32c_cpu.insn_str + int_to_string (offset)
+ 	      + "[sb],";
+ 	    m32c_cpu.raw_insn = (m32c_cpu.raw_insn << 8) + offset;
+ 	    m32c_cpu.h_pc_inc(1);
+ 	  }
+ // 	m32c_cpu.trace_str = int_to_string (m32c_cpu.h_sb_get () + offset)
+ // 	  + "=" + int_to_string (m32c_cpu.h_memget (m32c_cpu.h_sb_get () + offset, qi));
+ 	return m32c_cpu.h_memget (m32c_cpu.h_sb_get () + offset, qi);
+       }
+     case 11:
+       {
+ 	qi_addr = m32c_cpu.h_qitext_get() + m32c_cpu.h_pc_get();
+ 	offset = get_bits (qi_addr, 8, 0);
+ 	if (inc_pc)
+ 	  {
+ 	    m32c_cpu.insn_str = m32c_cpu.insn_str + int_to_string (offset)
+ 	      + "[fb],";
+ 	    m32c_cpu.raw_insn = (m32c_cpu.raw_insn << 8) + offset;
+ 	    m32c_cpu.h_pc_inc(1);
+ 	  }
+ // 	m32c_cpu.trace_str = int_to_string (m32c_cpu.h_fb_get () + offset)
+ // 	  + "=" + int_to_string (m32c_cpu.h_memget (m32c_cpu.h_fb_get () + offset, qi));
+ 	return m32c_cpu.h_memget (m32c_cpu.h_fb_get () + offset, qi);
+       }
+     case 12:
+       {
+ 	hi_addr = (HI*)(m32c_cpu.h_qitext_get() + m32c_cpu.h_pc_get());
+ 	offset = get_bits (hi_addr, 16, 0);
+ 	if (inc_pc)
+ 	  {
+ 	    m32c_cpu.insn_str = m32c_cpu.insn_str + int_to_string (offset)
+ 	      + "[a0],";
+ 	    m32c_cpu.raw_insn = (m32c_cpu.raw_insn << 8) + offset;
+ 	    m32c_cpu.h_pc_inc(2);
+ 	  }
+ // 	m32c_cpu.trace_str = int_to_string (m32c_cpu.h_ahi_get (0) + offset)
+ // 	  + "=" + int_to_string (m32c_cpu.h_memget (m32c_cpu.h_ahi_get (0) + offset, hi));
+ 	return m32c_cpu.h_memget (m32c_cpu.h_ahi_get (0) + offset, hi);
+       }
+     case 13:
+       {
+ 	hi_addr = (HI*)(m32c_cpu.h_qitext_get() + m32c_cpu.h_pc_get());
+ 	offset = get_bits (hi_addr, 16, 0);
+ 	if (inc_pc)
+ 	  {
+ 	    m32c_cpu.insn_str = m32c_cpu.insn_str + int_to_string (offset)
+ 	      + "[a1],";
+ 	    m32c_cpu.raw_insn = (m32c_cpu.raw_insn << 8) + offset;
+ 	    m32c_cpu.h_pc_inc(2);
+ 	  }
+ // 	m32c_cpu.trace_str = int_to_string (m32c_cpu.h_ahi_get (1) + offset)
+ // 	  + "=" + int_to_string (m32c_cpu.h_memget (m32c_cpu.h_ahi_get (1) + offset, hi));
+ 	return m32c_cpu.h_memget (m32c_cpu.h_ahi_get (1) + offset, qi);
+       }
+     case 14:
+       {
+ 	hi_addr = (HI*)(m32c_cpu.h_qitext_get() + m32c_cpu.h_pc_get());
+ 	offset = get_bits (hi_addr, 16, 0);
+ 	if (inc_pc)
+ 	  {
+ 	    m32c_cpu.insn_str = m32c_cpu.insn_str + int_to_string (offset)
+ 	      + "[sb],";
+ 	    m32c_cpu.raw_insn = (m32c_cpu.raw_insn << 8) + offset;
+ 	    m32c_cpu.h_pc_inc(2);
+ 	  }
+ // 	m32c_cpu.trace_str = int_to_string (m32c_cpu.h_sb_get () + offset)
+ // 	  + "=" + int_to_string (m32c_cpu.h_memget (m32c_cpu.h_sb_get () + offset, hi));
+ 	return m32c_cpu.h_memget (m32c_cpu.h_sb_get () + offset, qi);
+       }
+     case 15:
+       {
+ 	hi_addr = (HI*)(m32c_cpu.h_qitext_get() + m32c_cpu.h_pc_get());
+ 	offset = get_bits (hi_addr, 16, 0);
+ 	if (inc_pc)
+ 	  {
+ 	    m32c_cpu.insn_str = m32c_cpu.insn_str + int_to_string (offset) + ",";
+ 	    m32c_cpu.raw_insn = (m32c_cpu.raw_insn << 16) + offset;
+ 	    m32c_cpu.h_pc_inc(2);
+ 	  }
+ 	m32c_cpu.trace_str = int_to_string (offset) + "="
+ 	  + int_to_string (m32c_cpu.h_memget (offset, hi)) + " ";
+ 	return m32c_cpu.h_memget (offset, hi);
+       }
+     }
+ }
+ 
+ int
+ get_imm_src (int src, modes_t mode)
+ {
+   UHI offset;
+   QI *qi_addr;
+   HI *hi_addr;
+   int size;
+   
+   switch (mode)
+     {
+     case qi: size = 8; break;
+     case hi: size = 16; break;
+     case si: size = 32; break;
+     }
+   
+   switch (src)
+     {
+     case 0:
+     case 1:
+     case 2:
+     case 3:
+     case 4:
+     case 5:
+     case 6:
+     case 7:
+       qi_addr = m32c_cpu.h_qitext_get() + m32c_cpu.h_pc_get();
+       offset = get_bits (qi_addr, size, 0);
+       m32c_cpu.insn_str = m32c_cpu.insn_str + int_to_string (offset) + ",";
+       m32c_cpu.raw_insn = (m32c_cpu.raw_insn << size) + offset;
+       return offset;
+     case 8:
+     case 9:
+     case 10:
+     case 11:
+       {
+ 	qi_addr = m32c_cpu.h_qitext_get() + m32c_cpu.h_pc_get() + 1;
+ 	offset = get_bits (qi_addr, size, 0);
+ 	m32c_cpu.insn_str = m32c_cpu.insn_str + int_to_string (offset) + ",";
+ 	m32c_cpu.raw_insn = (m32c_cpu.raw_insn << size) + offset;
+ 	return offset;
+       }
+     case 12:
+     case 13:
+     case 14:
+     case 15:
+       {
+ 	qi_addr = m32c_cpu.h_qitext_get() + m32c_cpu.h_pc_get() + 2;
+ 	offset = get_bits (qi_addr, size, 0);
+ 	m32c_cpu.insn_str = m32c_cpu.insn_str + int_to_string (offset) + ",";
+ 	m32c_cpu.raw_insn = (m32c_cpu.raw_insn << size) + offset;
+ 	return offset;
+       }
+     }
+ }
+ 
+ int
+ put_dest (int dest, int newval, modes_t mode)
+ {
+   int offset;
+   QI *qi_addr;
+   HI *hi_addr;
+   int size;
+   
+   switch (mode)
+     {
+     case qi: size = 8; break;
+     case hi: size = 16; break;
+     case si: size = 32; break;
+     }
+ 
+   switch (dest)
+     {
+     case 0:
+       qi_addr = m32c_cpu.h_qitext_get() + m32c_cpu.h_pc_get();
+       m32c_cpu.insn_str = m32c_cpu.insn_str + m32c_cpu.h_gregname (0, mode);
+       m32c_cpu.trace_str = m32c_cpu.trace_str
+ 	+ m32c_cpu.h_gregname (0, mode) + "=" + int_to_string (newval);
+       return m32c_cpu.h_rset (0, mode, newval);
+     case 1:
+       qi_addr = m32c_cpu.h_qitext_get() + m32c_cpu.h_pc_get();
+       m32c_cpu.insn_str = m32c_cpu.insn_str + m32c_cpu.h_gregname (1, mode);
+       m32c_cpu.trace_str = m32c_cpu.trace_str +
+ 	m32c_cpu.h_gregname (1, mode) + "=" + int_to_string (newval);
+       return m32c_cpu.h_rset (1, mode, newval);
+     case 2:
+       qi_addr = m32c_cpu.h_qitext_get() + m32c_cpu.h_pc_get();
+       m32c_cpu.insn_str = m32c_cpu.insn_str + m32c_cpu.h_gregname (2, mode);
+       m32c_cpu.trace_str = m32c_cpu.trace_str +
+ 	m32c_cpu.h_gregname (2, mode) + "=" + int_to_string (newval);
+       return m32c_cpu.h_rset (2, mode, newval);
+     case 3:
+       qi_addr = m32c_cpu.h_qitext_get() + m32c_cpu.h_pc_get();
+       m32c_cpu.insn_str = m32c_cpu.insn_str + m32c_cpu.h_gregname (3, mode);
+       m32c_cpu.trace_str = m32c_cpu.trace_str +
+ 	m32c_cpu.h_gregname (3, mode) + "=" + int_to_string (newval);
+       return m32c_cpu.h_rset (3, mode, newval);
+     case 4:
+       qi_addr = m32c_cpu.h_qitext_get() + m32c_cpu.h_pc_get();
+       m32c_cpu.insn_str = m32c_cpu.insn_str + m32c_cpu.h_aregname (0, mode);
+       m32c_cpu.trace_str = m32c_cpu.trace_str +
+ 	m32c_cpu.h_aregname (0, mode) + "=" + int_to_string (newval);
+       return m32c_cpu.h_ahi_set (0, newval);
+     case 5:
+       qi_addr = m32c_cpu.h_qitext_get() + m32c_cpu.h_pc_get();
+       m32c_cpu.insn_str = m32c_cpu.insn_str + m32c_cpu.h_aregname (1, mode);
+       m32c_cpu.trace_str = m32c_cpu.trace_str +
+ 	m32c_cpu.h_aregname (1, mode) + "=" + int_to_string (newval);
+       return m32c_cpu.h_ahi_set (1, newval);
+     case 6:
+       qi_addr = m32c_cpu.h_qitext_get() + m32c_cpu.h_pc_get();
+       m32c_cpu.insn_str = m32c_cpu.insn_str + "[a0]";
+       m32c_cpu.trace_str = int_to_string (m32c_cpu.h_ahi_get (0)) + "="
+ 	+ int_to_string (newval);
+       return m32c_cpu.h_memset (m32c_cpu.h_ahi_get (0), newval, mode);
+     case 7:
+       qi_addr = m32c_cpu.h_qitext_get() + m32c_cpu.h_pc_get();
+       m32c_cpu.insn_str = m32c_cpu.insn_str + "[a1]";
+       m32c_cpu.trace_str = int_to_string (m32c_cpu.h_ahi_get (1)) + "="
+ 	+ int_to_string (newval);
+       return m32c_cpu.h_memset (m32c_cpu.h_ahi_get (1), newval, mode);
+     case 8:
+       qi_addr = m32c_cpu.h_qitext_get() + m32c_cpu.h_pc_get();
+       offset = get_bits (qi_addr, 8, 0);
+       m32c_cpu.h_pc_inc(1);
+       m32c_cpu.insn_str = m32c_cpu.insn_str + int_to_string (offset) + "[a0]";
+       m32c_cpu.raw_insn = (m32c_cpu.raw_insn << 8) + offset;
+       m32c_cpu.trace_str = int_to_string (m32c_cpu.h_ahi_get (0) + offset)
+ 	  + "=" + int_to_string (newval);
+       return m32c_cpu.h_memset (m32c_cpu.h_ahi_get (0) + offset, newval, mode);
+     case 9:
+       qi_addr = m32c_cpu.h_qitext_get() + m32c_cpu.h_pc_get();
+       offset = get_bits (qi_addr, 8, 0);
+       m32c_cpu.h_pc_inc(1);
+       m32c_cpu.insn_str = m32c_cpu.insn_str + int_to_string (offset) + "[a1]";
+       m32c_cpu.raw_insn = (m32c_cpu.raw_insn << 8) + offset;
+       m32c_cpu.trace_str = int_to_string (m32c_cpu.h_ahi_get (1) + offset)
+ 	  + "=" + int_to_string (newval);
+       return m32c_cpu.h_memset (m32c_cpu.h_ahi_get (1) + offset, newval, mode);
+     case 10:
+       qi_addr = m32c_cpu.h_qitext_get() + m32c_cpu.h_pc_get();
+       offset = get_bits (qi_addr, 8, 0);
+       m32c_cpu.h_pc_inc(1);
+       m32c_cpu.insn_str = m32c_cpu.insn_str + int_to_string (offset) + "[sb]";
+       m32c_cpu.raw_insn = (m32c_cpu.raw_insn << 8) + offset;
+       m32c_cpu.trace_str = int_to_string (m32c_cpu.h_sb_get () + offset)
+ 	  + "=" + int_to_string (newval);
+       return m32c_cpu.h_memset (m32c_cpu.h_sb_get () + offset, newval, mode);
+     case 11:
+ 						    qi_addr = m32c_cpu.h_qitext_get() + m32c_cpu.h_pc_get();
+       offset = get_bits (qi_addr, 8, 0);
+       m32c_cpu.h_pc_inc(1);
+       m32c_cpu.insn_str = m32c_cpu.insn_str + int_to_string (offset) + "[fb]";
+       m32c_cpu.raw_insn = (m32c_cpu.raw_insn << 8) + offset;
+       m32c_cpu.trace_str = int_to_string (m32c_cpu.h_fb_get () + offset)
+ 	+ "=" + int_to_string (newval);
+       return m32c_cpu.h_memset (m32c_cpu.h_fb_get () + offset, newval, mode);
+     case 12:
+       hi_addr = (HI*)(m32c_cpu.h_qitext_get() + m32c_cpu.h_pc_get());
+       offset = get_bits (hi_addr, 16, 0);
+       m32c_cpu.h_pc_inc(2);
+       m32c_cpu.insn_str = m32c_cpu.insn_str + int_to_string (offset) + "[a0]";
+       m32c_cpu.raw_insn = (m32c_cpu.raw_insn << 16) + offset;
+       m32c_cpu.trace_str = int_to_string (m32c_cpu.h_ahi_get (0) + offset)
+ 	  + "=" + int_to_string (newval);
+       return m32c_cpu.h_memset (m32c_cpu.h_ahi_get (0) + offset, newval, mode);
+     case 13:
+       hi_addr = (HI*)(m32c_cpu.h_qitext_get() + m32c_cpu.h_pc_get());
+       offset = get_bits (hi_addr, 16, 0);
+       m32c_cpu.h_pc_inc(2);
+       m32c_cpu.insn_str = m32c_cpu.insn_str + int_to_string (offset) + "[a1]";
+       m32c_cpu.raw_insn = (m32c_cpu.raw_insn << 16) + offset;
+       m32c_cpu.trace_str = int_to_string (m32c_cpu.h_ahi_get (1) + offset)
+ 	+ "=" + int_to_string (newval);
+       return m32c_cpu.h_memset (m32c_cpu.h_ahi_get (1) + offset, newval, mode);
+     case 14:
+       hi_addr = (HI*)(m32c_cpu.h_qitext_get() + m32c_cpu.h_pc_get());
+       offset = get_bits (hi_addr, 16, 0);
+       m32c_cpu.h_pc_inc(2);
+       m32c_cpu.insn_str = m32c_cpu.insn_str + int_to_string (offset) + "[sb]";
+       m32c_cpu.raw_insn = (m32c_cpu.raw_insn << 16) + offset;
+       m32c_cpu.trace_str = int_to_string (m32c_cpu.h_sb_get () + offset)
+ 	+ "=" + int_to_string (newval);
+       return m32c_cpu.h_memset (m32c_cpu.h_sb_get () + offset, newval, mode);
+     case 15:
+       hi_addr = (HI*)(m32c_cpu.h_qitext_get() + m32c_cpu.h_pc_get());
+       offset = get_bits (hi_addr, 16, 0);
+       m32c_cpu.h_pc_inc(2);
+       m32c_cpu.insn_str = m32c_cpu.insn_str + int_to_string (offset);
+       m32c_cpu.raw_insn = (m32c_cpu.raw_insn << 16) + offset;
+       m32c_cpu.trace_str = int_to_string (offset) + "=" + int_to_string (newval);
+       return m32c_cpu.h_memset (offset, newval, mode);
+     }
+ }
+ 
+ #define BIT(n) ((unsigned long)(insn>>(15 - (n))) & 1)       /* bit n of instruction */
+ #define BITS(s,l) ((unsigned long)(insn << (s + 16)) >> (32 - (l)))
+ 
+ enum execute_status {have_exit=1};
+ 
+ execute_status
+ execute_insn ()
+ {
+   QI qi_src;
+   QI qi_dest;
+   HI hi_src;
+   HI hi_dest;
+   UHI insn;
+   QI *qi_addr;
+   HI *hi_addr;
+   
+   hi_addr = (HI*)(m32c_cpu.h_qitext_get() + m32c_cpu.h_pc_get());
+   insn = get_bits (hi_addr, 16, 1);
+   m32c_cpu.h_pc_inc(2);
+   m32c_cpu.raw_insn = insn;
+ 
+   // op imm,dest
+   switch (BITS (0, 12))
+     {
+     case 0x76F:
+       m32c_cpu.insn_str = "abs.b ";
+       qi_src = get_src (BITS (12, 4), qi, dest_op);
+       put_dest (BITS (12, 4), abs (qi_src), qi);
+       goto DONE_ONE_INSN;
+     case 0x77F:
+       m32c_cpu.insn_str = "abs.w ";
+       hi_src = get_src (BITS (12, 4), hi, dest_op);
+       put_dest (BITS (12, 4), abs (hi_src), hi);
+       goto DONE_ONE_INSN;
+     case 0x766:
+       m32c_cpu.insn_str = "adc.b.g ";
+       qi_src = get_imm_src (BITS (12, 4), qi);
+       qi_dest = get_src (BITS (12, 4), qi, dest_op);
+       put_dest (BITS (12, 4), qi_src + qi_dest + m32c_cpu.h_flag_c_get(), qi);
+       m32c_cpu.h_pc_inc (1);	// allow for imm
+       goto DONE_ONE_INSN;
+     case 0x776:
+       m32c_cpu.insn_str = "adc.w.g ";
+       hi_src = get_imm_src (BITS (12, 4), hi);
+       hi_dest = get_src (BITS (12, 4), hi, dest_op);
+       put_dest (BITS (12, 4), hi_src + hi_dest + m32c_cpu.h_flag_c_get(), hi);
+       m32c_cpu.h_pc_inc (2);	// allow for imm
+       goto DONE_ONE_INSN;
+     case 0x76E:
+       m32c_cpu.insn_str = "adcf.b ";
+       qi_src = get_src (BITS (12, 4), qi, dest_op);
+       put_dest (BITS (12, 4), qi_src + m32c_cpu.h_flag_c_get(), qi);
+       goto DONE_ONE_INSN;
+     case 0x77E:
+       m32c_cpu.insn_str = "adcf.w ";
+       hi_src = get_src (BITS (12, 4), hi, dest_op);
+       put_dest (BITS (12, 4), hi_src + m32c_cpu.h_flag_c_get(), hi);
+       goto DONE_ONE_INSN;
+     case 0x764:
+       m32c_cpu.insn_str = "add.b.g ";
+       qi_src = get_imm_src (BITS (12, 4), qi);
+       qi_dest = get_src (BITS (12, 4), qi, dest_op);
+       put_dest (BITS (12, 4), qi_src + qi_dest, qi);
+       m32c_cpu.h_pc_inc (1);	// allow for imm
+       goto DONE_ONE_INSN;
+     case 0x774:
+       m32c_cpu.insn_str = "add.w.g ";
+       hi_src = get_imm_src (BITS (12, 4), hi);
+       hi_dest = get_src (BITS (12, 4), hi, dest_op);
+       put_dest (BITS (12, 4), hi_src + hi_dest, hi);
+       m32c_cpu.h_pc_inc (2);	// allow for imm
+       goto DONE_ONE_INSN;
+     case 0x7DB:
+       m32c_cpu.insn_str = "add.b.q ";
+       qi_src = (signed QI) BITS (12, 4);
+       m32c_cpu.insn_str = m32c_cpu.insn_str + int_to_string (qi_src) + ",sp";
+       m32c_cpu.h_sp_set (qi_src + m32c_cpu.h_sp_get());
+       goto DONE_ONE_INSN;
+     case 0x762:
+       m32c_cpu.insn_str = "and.b.g ";
+       qi_src = get_imm_src (BITS (12, 4), qi);
+       qi_dest = get_src (BITS (12, 4), qi, dest_op);
+       put_dest (BITS (12, 4), qi_src & qi_dest, qi);
+       m32c_cpu.h_pc_inc (1);	// allow for imm
+       goto DONE_ONE_INSN;
+     case 0x772:
+       m32c_cpu.insn_str = "and.w.g ";
+       hi_src = get_imm_src (BITS (12, 4), hi);
+       hi_dest = get_src (BITS (12, 4), hi, dest_op);
+       put_dest (BITS (12, 4), hi_src & hi_dest, hi);
+       m32c_cpu.h_pc_inc (2);	// allow for imm
+       goto DONE_ONE_INSN;
+     case 0x768:
+       m32c_cpu.insn_str = "cmp.b.g ";
+       qi_src = get_imm_src (BITS (12, 4), qi);
+       m32c_cpu.insn_str = m32c_cpu.insn_str + int_to_string (qi_src);
+       qi_dest = get_src (BITS (12, 4), qi, src_op);
+       m32c_cpu.h_flag_c_set (! subqi_cf (qi_src, qi_dest));
+       m32c_cpu.h_flag_o_set (! subqi_of (qi_src, qi_dest));
+       m32c_cpu.h_flag_z_set ((qi_src - qi_dest) == 0);
+       m32c_cpu.h_flag_s_set (qi_src < qi_dest);
+       m32c_cpu.h_pc_inc (1);	// allow for imm
+       goto DONE_ONE_INSN;
+     case 0x778:
+       m32c_cpu.insn_str = "cmp.w.g ";
+       hi_src = get_imm_src (BITS (12, 4), hi);
+       hi_dest = get_src (BITS (12, 4), hi, src_op);
+       m32c_cpu.h_flag_c_set (! subhi_cf (hi_src, hi_dest));
+       m32c_cpu.h_flag_o_set (! subhi_of (hi_src, hi_dest));
+       m32c_cpu.h_flag_z_set ((hi_src - hi_dest) == 0);
+       m32c_cpu.h_flag_s_set (hi_src < hi_dest);
+       m32c_cpu.h_pc_inc (2);	// allow for imm
+       goto DONE_ONE_INSN;
+     case 0x76D:
+       {
+ 	QI quotient;
+ 	QI remainder;
+ 	m32c_cpu.insn_str = "div.b ";
+ 	qi_src = get_src (BITS (12, 4), qi, src_op);
+ 	quotient = m32c_cpu.h_rget (0, hi) / qi_src;
+ 	remainder = m32c_cpu.h_rget (0, hi) % qi_src;
+ 	m32c_cpu.h_rset (0, qi, quotient);
+ 	m32c_cpu.h_rset (1, qi, remainder);
+ 	m32c_cpu.trace_str = m32c_cpu.trace_str
+ 	  + m32c_cpu.h_gregname (0, qi) + "=" + int_to_string (quotient) + " "
+ 	  + m32c_cpu.h_gregname (1, qi)
+ 	  + "=" + int_to_string (remainder);
+ 	goto DONE_ONE_INSN;
+       }
+     case 0x77D:
+       {
+ 	HI quotient;
+ 	HI remainder;
+ 	m32c_cpu.insn_str = "div.w ";
+ 	hi_src = get_src (BITS (12, 4), hi, src_op);
+ 	quotient = m32c_cpu.h_rget (0, si) / hi_src;
+ 	remainder = m32c_cpu.h_rget (0, si) % hi_src;
+ 	m32c_cpu.h_rset (0, hi, quotient);
+ 	m32c_cpu.h_rset (1, hi, remainder);
+ 	m32c_cpu.trace_str = m32c_cpu.trace_str
+ 	  + m32c_cpu.h_gregname (0, hi) + "="
+ 	  + int_to_string (quotient) + " " + m32c_cpu.h_gregname (1, hi) + "="
+ 	  + int_to_string (remainder);
+ 	goto DONE_ONE_INSN;
+       }
+     case 0x76C:
+       {
+ 	QI quotient;
+ 	QI remainder;
+ 	m32c_cpu.insn_str = "divu.b ";
+ 	qi_src = get_src (BITS (12, 4), qi, src_op);
+ 	quotient = (UHI)m32c_cpu.h_rget (0, hi) / (UQI)qi_src;
+ 	remainder = (UHI)m32c_cpu.h_rget (0, hi) % (UQI)qi_src;
+ 	m32c_cpu.h_rset (0, qi, quotient);
+ 	m32c_cpu.h_rset (1, qi, remainder);
+ 	m32c_cpu.trace_str = m32c_cpu.trace_str
+ 	  + m32c_cpu.h_gregname (0, qi) + "="
+ 	  + int_to_string (quotient) + " " + m32c_cpu.h_gregname (1, qi) + "="
+ 	  + int_to_string (remainder);
+ 	goto DONE_ONE_INSN;
+       }
+     case 0x77C:
+       {
+ 	HI quotient;
+ 	HI remainder;
+ 	m32c_cpu.insn_str = "divu.w ";
+ 	hi_src = get_src (BITS (12, 4), hi, src_op);
+ 	quotient = (USI)m32c_cpu.h_rget (0, si) / (UHI)hi_src;
+ 	remainder = (USI)m32c_cpu.h_rget (0, si) % (UHI)hi_src;
+ 	m32c_cpu.h_rset (0, hi, quotient);
+ 	m32c_cpu.h_rset (1, hi, remainder);
+ 	m32c_cpu.trace_str = m32c_cpu.trace_str
+ 	  + m32c_cpu.h_gregname (0, hi) + "="
+ 	  + int_to_string (quotient) + " " + m32c_cpu.h_gregname (1, hi) + "="
+ 	  + int_to_string (remainder);
+ 	goto DONE_ONE_INSN;
+       }
+     case 0x74C:
+       m32c_cpu.insn_str = "mov.b ";
+       qi_src = get_imm_src (BITS (12, 4), qi);
+       put_dest (BITS (12, 4), qi_src, qi);
+       m32c_cpu.h_pc_inc (1);	// allow for imm
+       goto DONE_ONE_INSN;
+     case 0x75C:
+       m32c_cpu.insn_str = "mov.w ";
+       hi_src = get_imm_src (BITS (12, 4), hi);
+       put_dest (BITS (12, 4), hi_src, hi);
+       m32c_cpu.h_pc_inc (2);	// allow for imm
+       goto DONE_ONE_INSN;
+     default:
+       break;
+     }
+ 
+   // op src,dest
+   switch (BITS (0, 8))
+     {
+     case 0xB0:
+       m32c_cpu.insn_str = "adc.b.g ";
+       qi_src = get_src (BITS (8, 4), qi, src_op);
+       qi_dest = get_src (BITS (12, 4), qi, dest_op);
+       put_dest (BITS (12, 4), qi_src + qi_dest + m32c_cpu.h_flag_c_get(), qi);
+       goto DONE_ONE_INSN;
+     case 0xB1:
+       m32c_cpu.insn_str = "adc.w.g ";
+       hi_src = get_src (BITS (8, 4), hi, src_op);
+       hi_dest = get_src (BITS (12, 4), hi, dest_op);
+       put_dest (BITS (12, 4), hi_src + hi_dest + m32c_cpu.h_flag_c_get(), hi);
+       goto DONE_ONE_INSN;
+     case 0xA0:
+       m32c_cpu.insn_str = "add.b.g ";
+       qi_src = get_src (BITS (8, 4), qi, src_op);
+       qi_dest = get_src (BITS (12, 4), qi, dest_op);
+       put_dest (BITS (12, 4), qi_src + qi_dest, qi);
+       goto DONE_ONE_INSN;
+     case 0xA1:
+       m32c_cpu.insn_str = "add.w.g ";
+       hi_src = get_src (BITS (8, 4), hi, src_op);
+       hi_dest = get_src (BITS (12, 4), hi, dest_op);
+       put_dest (BITS (12, 4), hi_src + hi_dest, hi);
+       goto DONE_ONE_INSN;
+     case 0xC8:
+       m32c_cpu.insn_str = "add.b.q ";
+       qi_src = (signed QI) BITS (8, 4);
+       m32c_cpu.insn_str = m32c_cpu.insn_str + int_to_string (qi_src) + ",";
+       qi_dest = get_src (BITS (12, 4), qi, dest_op);
+       put_dest (BITS (12, 4), qi_src + qi_dest, qi);
+       goto DONE_ONE_INSN;
+     case 0xC9:
+       m32c_cpu.insn_str = "add.w.q ";
+       hi_src = (signed HI) BITS (8, 4);
+       m32c_cpu.insn_str = m32c_cpu.insn_str + int_to_string (hi_src) + ",";
+       hi_dest = get_src (BITS (12, 4), hi, dest_op);
+       put_dest (BITS (12, 4), hi_src + hi_dest, hi);
+       goto DONE_ONE_INSN;
+     case 0x90:
+       m32c_cpu.insn_str = "and.b.g ";
+       qi_src = get_src (BITS (8, 4), qi, src_op);
+       qi_dest = get_src (BITS (12, 4), qi, dest_op);
+       put_dest (BITS (12, 4), qi_src & qi_dest, qi);
+       goto DONE_ONE_INSN;
+     case 0x91:
+       m32c_cpu.insn_str = "and.w.g ";
+       hi_src = get_src (BITS (8, 4), hi, src_op);
+       hi_dest = get_src (BITS (12, 4), hi, dest_op);
+       put_dest (BITS (12, 4), hi_src & hi_dest, hi);
+       goto DONE_ONE_INSN;
+     case 0xC0:
+       m32c_cpu.insn_str = "cmp.b.g ";
+       qi_src = get_src (BITS (8, 4), qi, src_op);
+       qi_dest = get_src (BITS (12, 4), qi, src_op);
+       m32c_cpu.h_flag_c_set (! subqi_cf (qi_src, qi_dest));
+       m32c_cpu.h_flag_o_set (! subqi_of (qi_src, qi_dest));
+       m32c_cpu.h_flag_z_set ((qi_src - qi_dest) == 0);
+       m32c_cpu.h_flag_s_set (qi_src < qi_dest);
+       goto DONE_ONE_INSN;
+     case 0xC1:
+       m32c_cpu.insn_str = "cmp.w.g ";
+       hi_src = get_src (BITS (8, 4), hi, src_op);
+       hi_dest = get_src (BITS (12, 4), hi, src_op);
+       m32c_cpu.h_flag_c_set (! subhi_cf (hi_src, hi_dest));
+       m32c_cpu.h_flag_o_set (! subhi_of (hi_src, hi_dest));
+       m32c_cpu.h_flag_z_set ((hi_src - hi_dest) == 0);
+       m32c_cpu.h_flag_s_set (hi_src < hi_dest);
+       goto DONE_ONE_INSN;
+     case 0xD0:
+       m32c_cpu.insn_str = "cmp.b.q ";
+       qi_src = (signed QI) BITS (8, 4);
+       qi_dest = get_src (BITS (12, 4), qi, dest_op);
+       m32c_cpu.h_flag_c_set (! subqi_cf (qi_src, qi_dest));
+       m32c_cpu.h_flag_o_set (! subqi_of (qi_src, qi_dest));
+       m32c_cpu.h_flag_z_set ((qi_src - qi_dest) == 0);
+       m32c_cpu.h_flag_s_set (qi_src < qi_dest);
+       goto DONE_ONE_INSN;
+     case 0xD1:
+       m32c_cpu.insn_str = "cmp.w.q ";
+       hi_src = (signed HI) BITS (8, 4);
+       hi_dest = get_src (BITS (12, 4), hi, dest_op);
+       m32c_cpu.h_flag_c_set (! subhi_cf (hi_src, hi_dest));
+       m32c_cpu.h_flag_o_set (! subhi_of (hi_src, hi_dest));
+       m32c_cpu.h_flag_z_set ((hi_src - hi_dest) == 0);
+       m32c_cpu.h_flag_s_set (hi_src < hi_dest);
+       goto DONE_ONE_INSN;
+     case 0x72:
+       m32c_cpu.insn_str = "mov.b ";
+       qi_src = get_src (BITS (8, 4), qi, src_op);
+       put_dest (BITS (12, 4), (qi_src), qi);
+       goto DONE_ONE_INSN;
+     case 0x73:
+       m32c_cpu.insn_str = "mov.w ";
+       hi_src = get_src (BITS (8, 4), hi, src_op);
+       put_dest (BITS (12, 4), (hi_src), hi);
+       goto DONE_ONE_INSN;
+     case 0x04:
+       m32c_cpu.insn_str = "nop ";
+       m32c_cpu.h_pc_inc (1);
+       goto DONE_ONE_INSN;
+     case 0xEB:
+       return have_exit;
+     default:
+       goto DONE_ONE_INSN;
+     }
+ 
+   switch (BITS (0, 12))
+     {
+     case 0x7CF2:
+       m32c_cpu.insn_str = "enter ";
+       qi_addr = m32c_cpu.h_qitext_get() + m32c_cpu.h_pc_get();
+       qi_src = get_bits (qi_addr, 8, 0);
+       m32c_cpu.insn_str = m32c_cpu.insn_str + int_to_string (qi_src);
+       m32c_cpu.raw_insn = (m32c_cpu.raw_insn << 8) + qi_src;
+       m32c_cpu.h_sp_set (m32c_cpu.h_sp_get() - 2);
+       m32c_cpu.h_memset (m32c_cpu.h_sp_get(), m32c_cpu.h_fb_get(), hi);
+       m32c_cpu.h_fb_set (m32c_cpu.h_sp_get());
+       m32c_cpu.h_sp_set (m32c_cpu.h_sp_get() - qi_src);
+       m32c_cpu.trace_str = "fb=" + int_to_string (m32c_cpu.h_fb_get()) + " sp="
+ 	+ int_to_string (m32c_cpu.h_sp_get());
+       m32c_cpu.h_pc_inc (1);
+     }
+ 
+ DONE_ONE_INSN:
+   if (disassemble)
+     {
+       std::cout << std::hex << m32c_cpu.raw_insn << "\t";
+       std::cout << m32c_cpu.insn_str << "\t";
+       std::cout << m32c_cpu.trace_str << std::endl;
+       std::cout << std::hex << m32c_cpu.h_pc_get() << " ";
+       m32c_cpu.raw_insn = 0;
+       m32c_cpu.insn_str = "";
+       m32c_cpu.trace_str = "";
+     }
+   // TODO add(3) add(5) adjnz and(2) and(4) b* cmp(3) cmp(5) dadc dadd dec
+   // div(1) divu(1) divx dsbb dsub
+ }
+ 
+ const struct TextSection *section_table;
+ 
+ int
+ main (int argc, QI **argv)
+ {
+  int fdin;
+  QI *src;
+  struct stat statbuf;
+  USI entry;
+  int endian;
+  USI e_flags;
+  int text_end;
+ 
+  if (argc != 2)
+    {
+      std::cout << "usage:" << argv[0] << "Executable-File" << std::endl;
+      exit (1);
+    }
+  
+  /* open the input file */
+  if ((fdin = open (argv[1], O_RDONLY)) < 0)
+    {
+      std::cout << "Cannot open" << argv[1] << std::endl;
+      exit (1);
+    }
+ 
+  /* find size of input file */
+  if (fstat (fdin,&statbuf) < 0)
+    {
+      std::cout << "fstat error" << std::endl;
+      exit (1);
+    }
+ 
+  /* mmap the input file */
+  if ((src = (QI*) mmap (0, statbuf.st_size, PROT_READ, MAP_SHARED, fdin, 0))
+      == (caddr_t) -1)
+    {
+      std::cout << "mmap error for input" << std::endl;
+      exit (1);
+    }
+ 
+ 
+  if (! readElfFile (src, &entry, &endian, &e_flags, &section_table,
+ 		    m32c_cpu.memory.qi))
+    {
+      std::cout << "File is not an Elf Executable" << std::endl;
+      exit (1);
+    }
+    
+  // m32c_cpu.h_pc_set (textSectionOffset());
+  // m32c_cpu.h_hitext_set ((HI*)src);
+  // memcpy (m32c_cpu.memory.qi, src + textSectionOffset(), textSectionEnd());
+  munmap(0, statbuf.st_size);
+  m32c_cpu.h_pc_set (entry);
+  m32c_cpu.h_qitext_set (m32c_cpu.memory.qi);
+  text_end = m32c_cpu.h_pc_get() + textSectionEnd();
+ 
+  for (int i = 0; m32c_cpu.h_pc_get() <= text_end; i++)
+    {
+      if (execute_insn () == have_exit)
+        break;
+    }
+ }
Index: sim/m32c/safe-fgets.c
===================================================================
RCS file: sim/m32c/safe-fgets.c
diff -N sim/m32c/safe-fgets.c
*** sim/m32c/safe-fgets.c	1 Jan 1970 00:00:00 -0000
--- sim/m32c/safe-fgets.c	6 Oct 2005 22:36:53 -0000
***************
*** 0 ****
--- 1,47 ----
+ #include <stdio.h>
+ #include <stdlib.h>
+ 
+ #include "safe-fgets.h"
+ 
+ static char *line_buf = 0;
+ static int line_buf_size = 0;
+ 
+ #define LBUFINCR 100
+ 
+ char *
+ safe_fgets(FILE *f)
+ {
+   char *line_ptr;
+   
+   if (line_buf == 0)
+   {
+     line_buf = (char *)malloc(LBUFINCR);
+     line_buf_size = LBUFINCR;
+   }
+ 
+   /* points to last byte */
+   line_ptr = line_buf + line_buf_size - 1;
+ 
+   /* so we can see if fgets put a 0 there */
+   *line_ptr = 1;
+   if (fgets(line_buf, line_buf_size, f) == 0)
+     return 0;
+ 
+   /* we filled the buffer? */
+   while (line_ptr[0] == 0 && line_ptr[-1] != '\n')
+   {
+     /* Make the buffer bigger and read more of the line */
+     line_buf_size += LBUFINCR;
+     line_buf = (char *) realloc (line_buf, line_buf_size);
+ 
+     /* points to last byte again */
+     line_ptr = line_buf + line_buf_size - 1;
+     /* so we can see if fgets put a 0 there */
+     *line_ptr = 1;
+ 
+     if (fgets(line_buf+line_buf_size-LBUFINCR-1, LBUFINCR+1, f) == 0)
+       return 0;
+   }
+ 
+   return line_buf;
+ }
Index: sim/m32c/safe-fgets.h
===================================================================
RCS file: sim/m32c/safe-fgets.h
diff -N sim/m32c/safe-fgets.h
*** sim/m32c/safe-fgets.h	1 Jan 1970 00:00:00 -0000
--- sim/m32c/safe-fgets.h	6 Oct 2005 22:36:53 -0000
***************
*** 0 ****
--- 1,6 ----
+ #ifndef _safe_gets_h_
+ #define _safe_gets_h_
+ 
+ char* safe_fgets(FILE *f);
+ 
+ #endif
Index: sim/m32c/sample.S
===================================================================
RCS file: sim/m32c/sample.S
diff -N sim/m32c/sample.S
*** sim/m32c/sample.S	1 Jan 1970 00:00:00 -0000
--- sim/m32c/sample.S	6 Oct 2005 22:36:53 -0000
***************
*** 0 ****
--- 1,7 ----
+ 	.text
+ 
+ 	.global _start
+ _start:
+ 	mov.w	#0x1234,r1
+ 	mov.w r1,r3 | sha.w #-8,r3 | sha.w #-7,r3
+ 	brk
Index: sim/m32c/sample.ld
===================================================================
RCS file: sim/m32c/sample.ld
diff -N sim/m32c/sample.ld
*** sim/m32c/sample.ld	1 Jan 1970 00:00:00 -0000
--- sim/m32c/sample.ld	6 Oct 2005 22:36:53 -0000
***************
*** 0 ****
--- 1,19 ----
+ ENTRY(_start)
+ 
+ MEMORY {
+ 	RAM1 (w) : ORIGIN = 0xc800, LENGTH = 0x0200
+ 	RAM2 (w) : ORIGIN = 0xca56, LENGTH = 0x1000
+ 	ROM  (w) : ORIGIN = 0x30000, LENGTH = 0x1000
+ }
+ 
+ SECTIONS {
+ 	.data : {
+ 		*(.data*)
+ 	} > RAM1
+ 	.text : {
+ 		*(.text*)
+ 	} > RAM2
+ 	.fardata : {
+ 		*(.fardata*)
+ 	} > ROM
+ }
Index: sim/m32c/sample2.c
===================================================================
RCS file: sim/m32c/sample2.c
diff -N sim/m32c/sample2.c
*** sim/m32c/sample2.c	1 Jan 1970 00:00:00 -0000
--- sim/m32c/sample2.c	6 Oct 2005 22:36:53 -0000
***************
*** 0 ****
--- 1,7 ----
+ void exit(int);
+ 
+ start()
+ {
+   foo(1,2,3,4);
+   exit(5);
+ }
Index: sim/m32c/srcdest.c
===================================================================
RCS file: sim/m32c/srcdest.c
diff -N sim/m32c/srcdest.c
*** sim/m32c/srcdest.c	1 Jan 1970 00:00:00 -0000
--- sim/m32c/srcdest.c	6 Oct 2005 22:36:53 -0000
***************
*** 0 ****
--- 1,599 ----
+ #include <stdio.h>
+ #include <stdlib.h>
+ 
+ #include "cpu.h"
+ #include "mem.h"
+ 
+ static int src_indirect = 0;
+ static int dest_indirect = 0;
+ static int src_addend = 0;
+ static int dest_addend = 0;
+ 
+ static int disp8()
+ {
+   int rv;
+   int tsave = trace;
+ 
+   if (trace == 1)
+     trace = 0;
+   rv = mem_get_qi (get_reg (pc));
+   regs.r_pc ++;
+   trace = tsave;
+   return rv;
+ }
+ 
+ static int disp16()
+ {
+   int rv;
+   int tsave = trace;
+ 
+   if (trace == 1)
+     trace = 0;
+   rv = mem_get_hi (get_reg (pc));
+   regs.r_pc += 2;
+   trace = tsave;
+   return rv;
+ }
+ 
+ static int disp24()
+ {
+   int rv;
+   int tsave = trace;
+ 
+   if (trace == 1)
+     trace = 0;
+   rv= mem_get_psi (get_reg (pc));
+   regs.r_pc += 3;
+   trace = tsave;
+   return rv;
+ }
+ 
+ static int disp20()
+ {
+   return disp24() & 0x000fffff;
+ }
+ 
+ const char *
+ bits (int v, int b)
+ {
+   static char buf[17];
+   char *bp = buf+16;
+   *bp = 0;
+   while (b)
+     {
+       *--bp = (v & 1) ? '1' : '0';
+       v >>= 1;
+       b--;
+     }
+   return bp;
+ }
+ 
+ static const char *the_bits = 0;
+ 
+ void
+ decode_indirect (int si, int di)
+ {
+   src_indirect = si;
+   dest_indirect = di;
+   if (trace && (si || di))
+     printf("indirect: s:%d d:%d\n", si, di);
+ }
+ 
+ void
+ decode_index (int sa, int da)
+ {
+   src_addend = sa;
+   dest_addend = da;
+   if (trace && (sa || da))
+     printf("index: s:%d d:%d\n", sa, da);
+ }
+ 
+ srcdest
+ decode_srcdest4 (int destcode, int bw)
+ {
+   srcdest sd;
+   sd.bytes = bw ? 2 : 1;
+   sd.mem = (destcode >= 6) ? 1 : 0;
+   static const char *dc_wnames[16] = {"r0", "r1", "r2", "r3",
+ 				      "a0", "a1", "[a0]", "[a1]",
+ 				      "disp8[a0]", "disp8[a1]", "disp8[sb]", "disp8[fb]",
+ 				      "disp16[a0]", "disp16[a1]", "disp16[sb]", "disp16"};
+   static const char *dc_bnames[4] = {"r0l", "r0h", "r1l", "r1h"};;
+ 
+   if (trace)
+     {
+       const char *n = dc_wnames[destcode];
+       if (bw == 0 && destcode <= 3)
+ 	n = dc_bnames[destcode];
+       if (!the_bits)
+ 	the_bits = bits(destcode, 4);
+       printf("decode: %s (%d) : %s\n", the_bits, destcode, n);
+       the_bits = 0;
+     }
+ 
+   switch (destcode)
+     {
+     case 0x0: sd.u.reg = bw ? r0 : r0l; break;
+     case 0x1: sd.u.reg = bw ? r1 : r0h; break;
+     case 0x2: sd.u.reg = bw ? r2 : r1l; break;
+     case 0x3: sd.u.reg = bw ? r3 : r1h; break;
+     case 0x4: sd.u.reg = a0; break;
+     case 0x5: sd.u.reg = a1; break;
+     case 0x6: sd.u.addr = get_reg (a0); break;
+     case 0x7: sd.u.addr = get_reg (a1); break;
+     case 0x8: sd.u.addr = get_reg (a0) + disp8(); break;
+     case 0x9: sd.u.addr = get_reg (a1) + disp8(); break;
+     case 0xa: sd.u.addr = get_reg (sb) + disp8(); break;
+     case 0xb: sd.u.addr = get_reg (fb) + sign_ext (disp8(), 8); break;
+     case 0xc: sd.u.addr = get_reg (a0) + disp16(); break;
+     case 0xd: sd.u.addr = get_reg (a1) + disp16(); break;
+     case 0xe: sd.u.addr = get_reg (sb) + disp16(); break;
+     case 0xf: sd.u.addr = disp16(); break;
+     default: abort();
+     }
+   if (sd.mem)
+     sd.u.addr &= addr_mask;
+   return sd;
+ }
+ 
+ srcdest
+ decode_jumpdest (int destcode, int w)
+ {
+   srcdest sd;
+   sd.bytes = w ? 2 : 3;
+   sd.mem = (destcode >= 6) ? 1 : 0;
+   static const char *dc_wnames[16] = {"r0", "r1", "r2", "r3",
+ 				      "a0", "a1", "[a0]", "[a1]",
+ 				      "disp8[a0]", "disp8[a1]", "disp8[sb]", "disp8[fb]",
+ 				      "disp20[a0]", "disp20[a1]", "disp16[sb]", "abs16"};
+   static const char *dc_anames[4] = {"r0l", "r0h", "r1l", "r1h"};
+ 
+   if (trace)
+     {
+       const char *n = dc_wnames[destcode];
+       if (w == 0 && destcode <= 3)
+ 	n = dc_anames[destcode];
+       if (!the_bits)
+ 	the_bits = bits(destcode, 4);
+       printf("decode: %s : %s\n", the_bits, n);
+       the_bits = 0;
+     }
+ 
+   switch (destcode)
+     {
+     case 0x0: sd.u.reg = w ? r0 : r2r0; break;
+     case 0x1: sd.u.reg = w ? r1 : r2r0; break;
+     case 0x2: sd.u.reg = w ? r2 : r3r1; break;
+     case 0x3: sd.u.reg = w ? r3 : r3r1; break;
+     case 0x4: sd.u.reg = w ? a0 : a1a0; break;
+     case 0x5: sd.u.reg = w ? a1 : a1a0; break;
+     case 0x6: sd.u.addr = get_reg (a0); break;
+     case 0x7: sd.u.addr = get_reg (a1); break;
+     case 0x8: sd.u.addr = get_reg (a0) + disp8(); break;
+     case 0x9: sd.u.addr = get_reg (a1) + disp8(); break;
+     case 0xa: sd.u.addr = get_reg (sb) + disp8(); break;
+     case 0xb: sd.u.addr = get_reg (fb) + sign_ext (disp8(), 8); break;
+     case 0xc: sd.u.addr = get_reg (a0) + disp20(); break;
+     case 0xd: sd.u.addr = get_reg (a1) + disp20(); break;
+     case 0xe: sd.u.addr = get_reg (sb) + disp16(); break;
+     case 0xf: sd.u.addr = disp16(); break;
+     default: abort();
+     }
+   if (sd.mem)
+     sd.u.addr &= addr_mask;
+   return sd;
+ }
+ 
+ srcdest
+ decode_dest3 (int destcode, int bw)
+ {
+   static char map[8] = { -1, -1, -1, 1, 0, 10, 11, 15 };
+ 
+   the_bits = bits(destcode, 3);
+   return decode_srcdest4(map[destcode], bw);
+ }
+ 
+ srcdest
+ decode_src2 (int srccode, int bw, int d)
+ {
+   static char map[4] = { 0, 10, 11, 15 };
+ 
+   the_bits = bits(srccode, 2);
+   return decode_srcdest4(srccode ? map[srccode] : 1-d, bw);
+ }
+ 
+ static struct {
+   reg_id b_regno;
+   reg_id w_regno;
+   int is_memory;
+   int disp_bytes;
+   char *name;
+ } modes23[] = {
+   { a0, a0, 1, 0, "[A0]"},		/* 0 0 0 0 0 */
+   { a1, a1, 1, 0, "[A1]" },		/* 0 0 0 0 1 */
+   { a0, a0, 0, 0, "A0" },		/* 0 0 0 1 0 */
+   { a1, a1, 0, 0, "A1" },		/* 0 0 0 1 1 */
+   { a0, a0, 1, 1, "dsp:8[A0]" },	/* 0 0 1 0 0 */
+   { a1, a1, 1, 1, "dsp:8[A1]" },	/* 0 0 1 0 1 */
+   { sb, sb, 1, 1, "dsp:8[SB]" },	/* 0 0 1 1 0 */
+   { fb, fb, 1, -1, "dsp:8[FB]" },	/* 0 0 1 1 1 */
+   { a0, a0, 1, 2, "dsp:16[A0]" },	/* 0 1 0 0 0 */
+   { a1, a1, 1, 2, "dsp:16[A1]" },	/* 0 1 0 0 1 */
+   { sb, sb, 1, 2, "dsp:16[SB]" },	/* 0 1 0 1 0 */
+   { fb, fb, 1, -2, "dsp:16[FB]" },	/* 0 1 0 1 1 */
+   { a0, a0, 1, 3, "dsp:24[A0]" },	/* 0 1 1 0 0 */
+   { a1, a1, 1, 3, "dsp:24[A1]" },	/* 0 1 1 0 1 */
+   { mem, mem, 1, 3, "abs24" },		/* 0 1 1 1 0 */
+   { mem, mem, 1, 2, "abs16" },		/* 0 1 1 1 1 */
+   { r0h, r2, 0, 0, "R0H/R2" },		/* 1 0 0 0 0 */
+   { r1h, r3, 0, 0, "R1H/R3" },		/* 1 0 0 0 1 */
+   { r0l, r0, 0, 0, "R0L/R0" },		/* 1 0 0 1 0 */
+   { r1l, r1, 0, 0, "R1L/R1" },		/* 1 0 0 1 1 */
+ };
+ 
+ static srcdest
+ decode_sd23 (int bbb, int bb, int bytes, int ind, int add)
+ {
+   srcdest sd;
+   int code = (bbb << 2) | bb;
+ 
+   if (code >= sizeof (modes23) / sizeof (modes23[0]))
+     abort();
+ 
+   if (trace)
+     {
+       char *b1 = "";
+       char *b2 = "";
+       char ad[30];
+       if (ind)
+ 	{
+ 	  b1 = "[";
+ 	  b2 = "]";
+ 	}
+       if (add)
+ 	sprintf(ad, "%+d", add);
+       else
+ 	ad[0] = 0;
+       if (!the_bits)
+ 	the_bits = bits(code, 4);
+       printf("decode: %s (%d) : %s%s%s%s\n", the_bits, code, b1, modes23[code].name, ad, b2);
+       the_bits = 0;
+     }
+ 
+   sd.bytes = bytes;
+   sd.mem = modes23[code].is_memory;
+   if (sd.mem)
+     {
+       if (modes23[code].w_regno == mem)
+ 	sd.u.addr = 0;
+       else
+ 	sd.u.addr = get_reg (modes23[code].w_regno);
+       switch (modes23[code].disp_bytes)
+ 	{
+ 	case 1:
+ 	  sd.u.addr += disp8 ();
+ 	  break;
+ 	case 2:
+ 	  sd.u.addr += disp16 ();
+ 	  break;
+ 	case -1:
+ 	  sd.u.addr += sign_ext (disp8 (), 8);
+ 	  break;
+ 	case -2:
+ 	  sd.u.addr += sign_ext (disp16 (), 16);
+ 	  break;
+ 	case 3:
+ 	  sd.u.addr += disp24 ();
+ 	  break;
+ 	default:
+ 	  break;
+ 	}
+       if (add)
+ 	sd.u.addr += add;
+       if (ind)
+ 	sd.u.addr = mem_get_si (sd.u.addr & membus_mask);
+       sd.u.addr &= membus_mask;
+     }
+   else
+     {
+       sd.u.reg = (bytes>1) ? modes23[code].w_regno : modes23[code].b_regno;
+       if (bytes == 3 || bytes == 4)
+ 	{
+ 	  switch (sd.u.reg)
+ 	    {
+ 	    case r0: sd.u.reg = r2r0; break;
+ 	    case r1: sd.u.reg = r3r1; break;
+ 	    case r2: abort();
+ 	    case r3: abort();
+ 	    default: ;
+ 	    }
+ 	}
+ 	  
+     }
+   return sd;
+ }
+ 
+ srcdest
+ decode_dest23 (int ddd, int dd, int bytes)
+ {
+   return decode_sd23 (ddd, dd, bytes, dest_indirect, dest_addend);
+ }
+ 
+ srcdest
+ decode_src23 (int sss, int ss, int bytes)
+ {
+   return decode_sd23 (sss, ss, bytes, src_indirect, src_addend);
+ }
+ 
+ srcdest
+ decode_dest2 (int dd, int bytes)
+ {
+   /* r0l/r0, abs16, dsp:8[SB], dsp:8[FB] */
+   static char map[4] = { 0x12, 0x0f, 0x06, 0x07 };
+ 
+   the_bits = bits(dd, 2);
+   return decode_sd23 (map[dd]>>2, map[dd]&3, bytes, dest_indirect, dest_addend);
+ }
+ 
+ srcdest
+ decode_src3 (int sss, int bytes)
+ {
+   /* r0, r1, a0, a1, r2, r3, N/A, N/A */
+   static char map[8] = { 0x12, 0x13, 0x02, 0x03, 0x10, 0x11, 0, 0 };
+ 
+   the_bits = bits(sss, 3);
+   return decode_sd23 (map[sss]>>2, map[sss]&3, bytes, src_indirect, src_addend);
+ }
+ 
+ srcdest
+ decode_dest1 (int destcode, int bw)
+ {
+   the_bits = bits(destcode, 1);
+   return decode_srcdest4(destcode, bw);
+ }
+ 
+ srcdest
+ decode_cr (int crcode)
+ {
+   static int regcode[] = { 0, intbl, intbh, flags, isp, sp, sb, fb };
+   srcdest sd;
+   sd.mem = 0;
+   sd.bytes = 2;
+   sd.u.reg = regcode[crcode & 7];
+   return sd;
+ }
+ 
+ srcdest
+ decode_cr_b (int crcode, int bank)
+ {
+   /* FIXME: intbl, intbh, isp */
+   static int regcode[3][8] = {
+     { 0, 0, flags, 0, 0, 0, 0, 0 },
+     { intb, sp, sb, fb, 0, 0, 0, isp },
+     { 0, 0, 0, 0, 0, 0, 0, 0 }};
+   srcdest sd;
+   sd.mem = 0;
+   sd.bytes = bank ? 3 : 2;
+   sd.u.reg = regcode[bank][crcode & 7];
+   return sd;
+ }
+ 
+ srcdest
+ widen_sd (srcdest sd)
+ {
+   sd.bytes *= 2;
+   if (!sd.mem)
+     switch (sd.u.reg)
+       {
+       case r0l: sd.u.reg = r0; break;
+       case r0:  sd.u.reg = r2r0; break;
+       case r1l: sd.u.reg = r1; break;
+       case r1:  sd.u.reg = r3r1; break;
+       case a0:
+ 	if (A16)
+ 	  sd.u.reg = a1a0;
+ 	break;
+       default: break;
+       }
+   return sd;
+ }
+ 
+ srcdest
+ reg_sd (reg_id reg)
+ {
+   srcdest rv;
+   rv.bytes = reg_bytes[reg];
+   rv.mem = 0;
+   rv.u.reg = reg;
+   return rv;
+ }
+ 
+ int
+ get_src (srcdest sd)
+ {
+   int v;
+   if (sd.mem)
+     {
+       switch (sd.bytes)
+ 	{
+ 	case 1:
+ 	  v = mem_get_qi (sd.u.addr);
+ 	  break;
+ 	case 2:
+ 	  v = mem_get_hi (sd.u.addr);
+ 	  break;
+ 	case 3:
+ 	  v = mem_get_psi (sd.u.addr);
+ 	  break;
+ 	case 4:
+ 	  v = mem_get_si (sd.u.addr);
+ 	  break;
+ 	default:
+ 	  abort();
+ 	}
+     }
+   else
+     {
+       v = get_reg (sd.u.reg);
+       switch (sd.bytes)
+ 	{
+ 	case 1: v &= 0xff; break;
+ 	case 2: v &= 0xffff; break;
+ 	case 3: v &= 0xffffff; break;
+ 	}
+     }
+   return v;
+ }
+ 
+ void
+ put_dest (srcdest sd, int v)
+ {
+   if (sd.mem)
+     {
+       switch (sd.bytes)
+ 	{
+ 	case 1:
+ 	  mem_put_qi (sd.u.addr, v);
+ 	  break;
+ 	case 2:
+ 	  mem_put_hi (sd.u.addr, v);
+ 	  break;
+ 	case 3:
+ 	  mem_put_psi (sd.u.addr, v);
+ 	  break;
+ 	case 4:
+ 	  mem_put_si (sd.u.addr, v);
+ 	  break;
+ 	}
+     }
+   else
+     {
+       switch (sd.bytes)
+ 	{
+ 	case 1: v &= 0xff; break;
+ 	case 2: v &= 0xffff; break;
+ 	case 3: v &= 0xffffff; break;
+ 	}
+       put_reg (sd.u.reg, v);
+     }
+ }
+ 
+ srcdest
+ decode_bit (int destcode)
+ {
+   srcdest sd;
+   int addr = 0;
+   static const char *dc_names[] = {"r0", "r1", "r2", "r3",
+ 				   "a0", "a1", "[a0]", "[a1]",
+ 				   "disp8[a0]", "disp8[a1]", "disp8[sb]", "disp8[fb]",
+ 				   "disp16[a0]", "disp16[a1]", "disp16[sb]", "abs16"};
+     
+   if (trace)
+     {
+       const char *the_bits = bits(destcode, 4);
+       printf("decode: %s : %s\n", the_bits, dc_names[destcode]);
+     }
+ 
+   switch (destcode)
+     {
+     case 0: sd.u.reg = r0; break;
+     case 1: sd.u.reg = r1; break;
+     case 2: sd.u.reg = r2; break;
+     case 3: sd.u.reg = r3; break;
+     case 4: sd.u.reg = a0; break;
+     case 5: sd.u.reg = a1; break;
+     case 6: addr = get_reg (a0); break;
+     case 7: addr = get_reg (a1); break;
+     case 8: addr = get_reg (a0) + disp8 (); break;
+     case 9: addr = get_reg (a1) + disp8 (); break;
+     case 10: addr = get_reg (sb)*8 + disp8 (); break;
+     case 11: addr = get_reg (fb)*8 + sign_ext (disp8 (), 8); break;
+     case 12: addr = get_reg (a0) + disp16 (); break;
+     case 13: addr = get_reg (a1) + disp16 (); break;
+     case 14: addr = get_reg (sb) + disp16 (); break;
+     case 15: addr = disp16 (); break;
+     }
+ 
+   if (destcode < 6)
+     {
+       int d = disp8();
+       sd.mem = 0;
+       sd.mask = 1 << (d & 0x0f);
+     }
+   else
+     {
+       addr &= addr_mask;
+       sd.mem = 1;
+       sd.mask = 1 << (addr & 7);
+       sd.u.addr = addr >> 3;
+     }
+   return sd;
+ }
+ 
+ srcdest
+ decode_bit11 (int op0)
+ {
+   srcdest sd;
+   sd.mask = 1 << (op0 & 7);
+   sd.mem = 1;
+   sd.u.addr = get_reg (sb) + disp8 ();
+   return sd;
+ }
+ 
+ int
+ get_bit (srcdest sd)
+ {
+   int b;
+   if (sd.mem)
+     b = mem_get_qi (sd.u.addr) & sd.mask;
+   else
+     b = get_reg (sd.u.reg) & sd.mask;
+   return b ? 1 : 0;
+ }
+ 
+ void
+ put_bit (srcdest sd, int val)
+ {
+   int b;
+   if (sd.mem)
+     b = mem_get_qi (sd.u.addr);
+   else
+     b = get_reg (sd.u.reg);
+   if (val)
+     b |= sd.mask;
+   else
+     b &= ~sd.mask;
+   if (sd.mem)
+     mem_put_qi (sd.u.addr, b);
+   else
+     put_reg (sd.u.reg, b);
+ }
+ 
+ int
+ get_bit2 (srcdest sd, int bit)
+ {
+   int b;
+   if (sd.mem)
+     b = mem_get_qi (sd.u.addr + (bit >> 3)) & (1 << (bit & 7));
+   else
+     b = get_reg (sd.u.reg) & (1 << bit);
+   return b ? 1 : 0;
+ }
+ 
+ void
+ put_bit2 (srcdest sd, int bit, int val)
+ {
+   int b;
+   if (sd.mem)
+     b = mem_get_qi (sd.u.addr + (bit >> 3));
+   else
+     b = get_reg (sd.u.reg);
+   if (val)
+     b |= (1 << (bit & 7));
+   else
+     b &= ~(1 << (bit & 7));
+   if (sd.mem)
+     mem_put_qi (sd.u.addr + (bit >> 3), b);
+   else
+     put_reg (sd.u.reg, b);
+ }
Index: sim/m32c/syscalls.c
===================================================================
RCS file: sim/m32c/syscalls.c
diff -N sim/m32c/syscalls.c
*** sim/m32c/syscalls.c	1 Jan 1970 00:00:00 -0000
--- sim/m32c/syscalls.c	6 Oct 2005 22:36:53 -0000
***************
*** 0 ****
--- 1,298 ----
+ #include <stdio.h>
+ #include <stdlib.h>
+ #include <fcntl.h>
+ #include <unistd.h>
+ #include <sys/time.h>
+ 
+ #include "gdb/callback.h"
+ 
+ #include "cpu.h"
+ #include "mem.h"
+ #include "syscalls.h"
+ 
+ #include "../../libgloss/syscall.h"
+ 
+ /* The current syscall callbacks we're using.  */
+ static struct host_callback_struct *callbacks;
+ 
+ void
+ set_callbacks (struct host_callback_struct *cb)
+ {
+   callbacks = cb;
+ }
+ 
+ 
+ /* A16 ABI: arg1 in r1l (QI) or r1 (HI) or stack
+             arg2 in r2 (HI) or stack
+ 	    arg3..N on stack
+ 	    padding: none
+ 
+    A24 ABI: arg1 in r0l (QI) or r0 (HI) or stack
+ 	    arg2..N on stack
+ 	    padding: qi->hi
+ 
+    return value in r0l (QI) r0 (HI) r2r0 (SI)
+      structs: pointer pushed on stack last
+ 
+ */
+ 
+ int argp, stackp;
+ 
+ static int
+ arg(int bytes)
+ {
+   int rv = 0;
+   argp++;
+   if (A16)
+     {
+       switch (argp)
+ 	{
+ 	case 1:
+ 	  if (bytes == 1)
+ 	    return get_reg (r1l);
+ 	  if (bytes == 2)
+ 	    return get_reg (r1);
+ 	  break;
+ 	case 2:
+ 	  if (bytes == 2)
+ 	    return get_reg (r2);
+ 	  break;
+ 	}
+     }
+   else
+     {
+       switch (argp)
+ 	{
+ 	case 1:
+ 	  if (bytes == 1)
+ 	    return get_reg (r0l);
+ 	  if (bytes == 2)
+ 	    return get_reg (r0);
+ 	  break;
+ 	}
+     }
+   if (bytes == 0)
+     bytes = 2;
+   switch (bytes)
+     {
+     case 1:
+       rv = mem_get_qi (get_reg (sp) + stackp);
+       if (A24)
+ 	stackp ++;
+       break;
+     case 2:
+       rv = mem_get_hi (get_reg (sp) + stackp);
+       break;
+     case 3:
+       rv = mem_get_psi (get_reg (sp) + stackp);
+       if (A24)
+ 	stackp ++;
+       break;
+     case 4:
+       rv = mem_get_si (get_reg (sp) + stackp);
+       break;
+     }
+   stackp += bytes;
+   return rv;
+ }
+ 
+ static void
+ read_target (char *buffer, int address, int count, int asciiz)
+ {
+   char byte;
+   while (count > 0)
+     {
+       byte = mem_get_qi (address++);
+       *buffer++ = byte;
+       if (asciiz && (byte == 0))
+ 	return;
+       count --;
+     }
+ }
+ 
+ static void
+ write_target (char *buffer, int address, int count, int asciiz)
+ {
+   char byte;
+   while (count > 0)
+     {
+       byte = *buffer++;
+       mem_put_qi (address++, byte);
+       if (asciiz && (byte == 0))
+ 	return;
+       count --;
+     }
+ }
+ 
+ #define PTRSZ (A16 ? 2 : 3)
+ 
+ static char *callnames[] = {
+   "SYS_zero",
+   "SYS_exit",
+   "SYS_open",
+   "SYS_close",
+   "SYS_read",
+   "SYS_write",
+   "SYS_lseek",
+   "SYS_unlink",
+   "SYS_getpid",
+   "SYS_kill",
+   "SYS_fstat",
+   "SYS_sbrk",
+   "SYS_argvlen",
+   "SYS_argv",
+   "SYS_chdir",
+   "SYS_stat",
+   "SYS_chmod",
+   "SYS_utime",
+   "SYS_time",
+   "SYS_gettimeofday",
+   "SYS_times",
+   "SYS_link"
+ };
+ 
+ void
+ m32c_syscall (int id)
+ {
+   static char buf[256];
+   int rv;
+ 
+   argp = 0;
+   stackp = A16 ? 3 : 4;
+   if (trace)
+     printf("\033[31m/* SYSCALL(%d) = %s */\033[0m\n", id, callnames[id]);
+   switch (id)
+     {
+     case SYS_exit:
+       {
+ 	int ec = arg(2);
+ 	if (verbose)
+ 	  printf("[exit %d]\n", ec);
+ 	step_result = M32C_MAKE_EXITED (ec);
+       }
+       break;
+ 
+     case SYS_open:
+       {
+ 	int path = arg(PTRSZ);
+ 	int oflags = arg(2);
+ 	int cflags = arg(2);
+ 
+ 	read_target (buf, path, 256, 1);
+ 	if (trace) printf("open(\"%s\",0x%x,%#o) = ", buf, oflags, cflags);
+ 
+ 	if (callbacks)
+ 	  /* The callback vector ignores CFLAGS.  */
+ 	  rv = callbacks->open (callbacks, buf, oflags);
+ 	else
+ 	  {
+ 	    int h_oflags = 0;
+ 
+ 	    if (oflags & 0x0001) h_oflags |= O_WRONLY;
+ 	    if (oflags & 0x0002) h_oflags |= O_RDWR;
+ 	    if (oflags & 0x0200) h_oflags |= O_CREAT;
+ 	    if (oflags & 0x0008) h_oflags |= O_APPEND;
+ 	    if (oflags & 0x0400) h_oflags |= O_TRUNC;
+ 	    rv = open (buf, h_oflags, cflags);
+ 	  }
+ 	if (trace) printf("%d\n", rv);
+ 	put_reg (r0, rv);
+       }
+       break;
+ 
+     case SYS_close:
+       {
+ 	int fd = arg(2);
+ 
+ 	if (callbacks)
+ 	  rv = callbacks->close(callbacks, fd);
+ 	else if (fd > 2)
+ 	  rv = close(fd);
+ 	else
+ 	  rv = 0;
+ 	if (trace) printf("close(%d) = %d\n", fd, rv);
+ 	put_reg (r0, rv);
+       }
+       break;
+ 
+     case SYS_read:
+       {
+ 	int fd = arg(2);
+ 	int addr = arg(PTRSZ);
+ 	int count = arg(2);
+ 
+ 	if (count > sizeof(buf))
+ 	  count = sizeof(buf);
+ 	if (callbacks)
+ 	  rv = callbacks->read (callbacks, fd, buf, count);
+ 	else
+ 	  rv = read (fd, buf, count);
+ 	if (trace) printf("read(%d,%d) = %d\n", fd, count, rv);
+ 	if (rv > 0)
+ 	  write_target (buf, addr, rv, 0);
+ 	put_reg (r0, rv);
+       }
+       break;
+ 
+     case SYS_write:
+       {
+ 	int fd = arg(2);
+ 	int addr = arg(PTRSZ);
+ 	int count = arg(2);
+ 
+ 	if (count > sizeof(buf))
+ 	  count = sizeof(buf);
+ 	if (trace) printf("write(%d,0x%x,%d)\n", fd, addr, count);
+ 	read_target (buf, addr, count, 0);
+ 	if (trace) fflush(stdout);
+ 	if (callbacks)
+ 	  rv = callbacks->write (callbacks, fd, buf, count);
+ 	else
+ 	  rv = write (fd, buf, count);
+ 	if (trace) printf("write(%d,%d) = %d\n", fd, count, rv);
+ 	put_reg (r0, rv);
+       }
+       break;
+ 
+     case SYS_getpid:
+       put_reg (r0, 42);
+       break;
+ 
+     case SYS_gettimeofday:
+       {
+ 	int tvaddr = arg(PTRSZ);
+ 	struct timeval tv;
+ 
+ 	rv = gettimeofday (&tv, 0);
+ 	if (trace) printf("gettimeofday: %ld sec %ld usec to 0x%x\n", tv.tv_sec, tv.tv_usec, tvaddr);
+ 	mem_put_si (tvaddr, tv.tv_sec);
+ 	mem_put_si (tvaddr+4, tv.tv_usec);
+ 	put_reg (r0, rv);
+       }
+       break;
+ 
+     case SYS_kill:
+       {
+ 	int pid = arg(2);
+ 	int sig = arg(2);
+ 	if (pid == 42)
+ 	  {
+ 	    if (verbose)
+ 	      printf("[signal %d]\n", sig);
+ 	    step_result = M32C_MAKE_STOPPED (sig);
+ 	  }
+       }
+       break;
+ 
+     case 11:
+       {
+ 	int heaptop_arg = arg(PTRSZ);
+ 	if (trace) printf("sbrk: heap top set to %x\n", heaptop_arg);
+ 	heaptop = heaptop_arg;
+ 	if (heapbottom == 0)
+ 	  heapbottom = heaptop_arg;
+       }
+       break;
+ 
+     }
+ }
Index: sim/m32c/syscalls.h
===================================================================
RCS file: sim/m32c/syscalls.h
diff -N sim/m32c/syscalls.h
*** sim/m32c/syscalls.h	1 Jan 1970 00:00:00 -0000
--- sim/m32c/syscalls.h	6 Oct 2005 22:36:53 -0000
***************
*** 0 ****
--- 1,3 ----
+ struct host_callback_struct;
+ extern void set_callbacks (struct host_callback_struct *);
+ extern void m32c_syscall (int id);
Index: sim/m32c/trace.c
===================================================================
RCS file: sim/m32c/trace.c
diff -N sim/m32c/trace.c
*** sim/m32c/trace.c	1 Jan 1970 00:00:00 -0000
--- sim/m32c/trace.c	6 Oct 2005 22:36:53 -0000
***************
*** 0 ****
--- 1,280 ----
+ #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 "m32c-desc.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;
+ 
+ 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];
+ }
+ 
+ void
+ sim_disasm_one()
+ {
+   static int initted = 0;
+   static asymbol **symtab = 0;
+   static int symcount = 0;
+   static int last_sym = -1;
+   static struct disassemble_info info;
+   int storage, sym, bestaddr;
+   int min, max, i;
+   static asection *code_section = 0;
+   static bfd_vma code_base = 0;
+   asection *s;
+   int save_trace = trace;
+ 
+   static const char *prev_filename = "";
+   static int prev_lineno = 0;
+   const char *filename;
+   const char *functionname;
+   unsigned int lineno;
+ 
+   int mypc = get_reg (pc);
+ 
+   if (current_bfd == 0)
+     return;
+ 
+   trace = 0;
+ 
+   if (!initted)
+     {
+       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_m32c;
+ 	  info.mach = default_machine;
+ 	}
+       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;
+ 	    }
+ 	}
+     }
+ 
+   filename = functionname = 0;
+   lineno = 0;
+   if (bfd_find_nearest_line (current_bfd, code_section, symtab, mypc - code_base,
+ 			     &filename, &functionname, &lineno))
+     {
+       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
+ 	}
+     }
+ 
+   opbuf[0] = 0;
+   printf("\033[33m%06x: ", mypc);
+   max = print_insn_m32c(mypc, &info);
+   for (i=0; i<max; i++)
+     printf("%02x", mem_get_qi(mypc+i));
+   for (; i<6; i++)
+     printf("  ");
+   printf("%-16s  ", opbuf);
+ 
+   printf("\033[0m\n");
+   trace = save_trace;
+ }
Index: sim/m32c/trace.h
===================================================================
RCS file: sim/m32c/trace.h
diff -N sim/m32c/trace.h
*** sim/m32c/trace.h	1 Jan 1970 00:00:00 -0000
--- sim/m32c/trace.h	6 Oct 2005 22:36:53 -0000
***************
*** 0 ****
--- 1,2 ----
+ void sim_disasm_init(bfd *prog);
+ extern void sim_disasm_one (void);


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

* Re: RFA: contribute Renesas M32C sim
  2005-10-07 20:46 RFA: contribute Renesas M32C sim Jim Blandy
@ 2005-10-07 21:03 ` Daniel Jacobowitz
  2005-10-09  0:29   ` Jim Blandy
  2005-10-09 20:15 ` Daniel Jacobowitz
  2005-10-15 12:06 ` Eli Zaretskii
  2 siblings, 1 reply; 14+ messages in thread
From: Daniel Jacobowitz @ 2005-10-07 21:03 UTC (permalink / raw)
  To: Jim Blandy; +Cc: gdb-patches

On Fri, Oct 07, 2005 at 01:44:09PM -0700, Jim Blandy wrote:
> 
> DJ Delorie is the target maintainer for the M32C, so the rules in
> sim/MAINTAINERS make him the maintainer of this sim by default.

GDB does not contain an m32c port, and DJ is only listed for DJGPP in
gdb/MAINTAINERS.  So I don't see how that can be true.  He's only
listed for m32c in newlib.


-- 
Daniel Jacobowitz
CodeSourcery, LLC


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

* Re: RFA: contribute Renesas M32C sim
  2005-10-07 21:03 ` Daniel Jacobowitz
@ 2005-10-09  0:29   ` Jim Blandy
  0 siblings, 0 replies; 14+ messages in thread
From: Jim Blandy @ 2005-10-09  0:29 UTC (permalink / raw)
  To: gdb-patches


Daniel Jacobowitz <drow@false.org> writes:
> On Fri, Oct 07, 2005 at 01:44:09PM -0700, Jim Blandy wrote:
>> 
>> DJ Delorie is the target maintainer for the M32C, so the rules in
>> sim/MAINTAINERS make him the maintainer of this sim by default.
>
> GDB does not contain an m32c port, and DJ is only listed for DJGPP in
> gdb/MAINTAINERS.  So I don't see how that can be true.  He's only
> listed for m32c in newlib.

... I was confused.  sim/MAINTAINERS is clear, but I misread it.

DJ Delorie has volunteered to maintain the m32c sim; he is its author.


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

* Re: RFA: contribute Renesas M32C sim
  2005-10-07 20:46 RFA: contribute Renesas M32C sim Jim Blandy
  2005-10-07 21:03 ` Daniel Jacobowitz
@ 2005-10-09 20:15 ` Daniel Jacobowitz
  2005-10-12 18:21   ` Jim Blandy
  2005-10-12 22:12   ` Jim Blandy
  2005-10-15 12:06 ` Eli Zaretskii
  2 siblings, 2 replies; 14+ messages in thread
From: Daniel Jacobowitz @ 2005-10-09 20:15 UTC (permalink / raw)
  To: Jim Blandy; +Cc: gdb-patches

There's a limit to how useful I can be reviewing sim patches, but I'll
try.

The most glaring omission is copyright notices.  Not a single one. 
Pretty much every file should have one.  I assume the intention is to
assign this contribution to the FSF.

There seem to be a lot of too-long lines.

> + void
> + prefix (src_allowed, dest_allowed, index_bytewidth)
> + {
> + }

And what's that for?

-- 
Daniel Jacobowitz
CodeSourcery, LLC


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

* Re: RFA: contribute Renesas M32C sim
  2005-10-09 20:15 ` Daniel Jacobowitz
@ 2005-10-12 18:21   ` Jim Blandy
       [not found]     ` <jimb@redhat.com>
  2005-10-12 22:12   ` Jim Blandy
  1 sibling, 1 reply; 14+ messages in thread
From: Jim Blandy @ 2005-10-12 18:21 UTC (permalink / raw)
  To: gdb-patches

Daniel Jacobowitz <drow@false.org> writes:
> The most glaring omission is copyright notices.  Not a single one. 
> Pretty much every file should have one.  I assume the intention is to
> assign this contribution to the FSF.

My face is red.  Of course there should be copyright notices.

> There seem to be a lot of too-long lines.

I'll address those.

>> + void
>> + prefix (src_allowed, dest_allowed, index_bytewidth)
>> + {
>> + }
>
> And what's that for?

I don't know.  I thought it was some sort of annotation for opc2c to
consume, but that doesn't seem to be so.  I'll find out.


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

* Re: RFA: contribute Renesas M32C sim
  2005-10-09 20:15 ` Daniel Jacobowitz
  2005-10-12 18:21   ` Jim Blandy
@ 2005-10-12 22:12   ` Jim Blandy
  2006-01-23  2:03     ` Daniel Jacobowitz
  1 sibling, 1 reply; 14+ messages in thread
From: Jim Blandy @ 2005-10-12 22:12 UTC (permalink / raw)
  To: gdb-patches

[-- Attachment #1: Type: text/plain, Size: 211 bytes --]


I think the attached patch should address the points you raised:

- I added copyright notices.
- I ran the code through gdb_indent.sh, and fixed up some further messes.
- I added a comment to m32c.opc:prefix.


[-- Attachment #2: Patch to add Renesas M32C sim to GDB tree --]
[-- Type: application/x-gzip, Size: 41707 bytes --]

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

* Re: RFA: contribute Renesas M32C sim
  2005-10-07 20:46 RFA: contribute Renesas M32C sim Jim Blandy
  2005-10-07 21:03 ` Daniel Jacobowitz
  2005-10-09 20:15 ` Daniel Jacobowitz
@ 2005-10-15 12:06 ` Eli Zaretskii
  2005-10-17 23:26   ` Jim Blandy
  2 siblings, 1 reply; 14+ messages in thread
From: Eli Zaretskii @ 2005-10-15 12:06 UTC (permalink / raw)
  To: Jim Blandy; +Cc: gdb-patches

> From: Jim Blandy <jimb@redhat.com>
> Date: Fri, 07 Oct 2005 13:44:09 -0700
> 
> DJ Delorie is the target maintainer for the M32C, so the rules in
> sim/MAINTAINERS make him the maintainer of this sim by default.
> 
> sim/ChangeLog:
> 2005-10-06  Jim Blandy  <jimb@redhat.com>
> 	
> 	Add simulator for Renesas M32C and M16C.
> 	
> 	* m32c: New directory.
> 	* configure.ac: Add entry for Renesas M32C.
> 	* configure: Regenerate.

Please make sure to add a notice about this new simulator to gdb/NEWS.


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

* Re: RFA: contribute Renesas M32C sim
  2005-10-15 12:06 ` Eli Zaretskii
@ 2005-10-17 23:26   ` Jim Blandy
  0 siblings, 0 replies; 14+ messages in thread
From: Jim Blandy @ 2005-10-17 23:26 UTC (permalink / raw)
  To: Eli Zaretskii; +Cc: gdb-patches


Eli Zaretskii <eliz@gnu.org> writes:
>> From: Jim Blandy <jimb@redhat.com>
>> Date: Fri, 07 Oct 2005 13:44:09 -0700
>> 
>> DJ Delorie is the target maintainer for the M32C, so the rules in
>> sim/MAINTAINERS make him the maintainer of this sim by default.
>> 
>> sim/ChangeLog:
>> 2005-10-06  Jim Blandy  <jimb@redhat.com>
>> 	
>> 	Add simulator for Renesas M32C and M16C.
>> 	
>> 	* m32c: New directory.
>> 	* configure.ac: Add entry for Renesas M32C.
>> 	* configure: Regenerate.
>
> Please make sure to add a notice about this new simulator to gdb/NEWS.

Yes --- thanks for reminding me of that.  I've added:

    * New simulators

    Renesas M32C / M16C             m32c-elf

I appreciate Daniel's read-over.  Is someone willing to sign off on
the revised sim?


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

* Re: RFA: contribute Renesas M32C sim
       [not found]     ` <jimb@redhat.com>
@ 2005-12-14 18:40       ` DJ Delorie
  2005-12-15  0:01         ` Daniel Jacobowitz
  0 siblings, 1 reply; 14+ messages in thread
From: DJ Delorie @ 2005-12-14 18:40 UTC (permalink / raw)
  To: gdb-patches


> >> + void
> >> + prefix (src_allowed, dest_allowed, index_bytewidth)
> >> + {
> >> + }
> >
> > And what's that for?
> 
> I don't know.  I thought it was some sort of annotation for opc2c to
> consume, but that doesn't seem to be so.  I'll find out.

I remember talking to Jim about this, but I don't see him answering in
the mail archives, and since I was checking on the m32c/gdb status I
figured I'd at least get this one answered.

In short, that function exists so it can be called, it's the callers
that are important at the moment.

The callers act as documentation for what prefixes and indexes are
permitted for each opcode.  As I was going through the tedious process
of implementing each opcode, I added all the calls to prefix() with
the correct arguments.  The function does nothing yet, but at some
point in the future it may fault if prefixes are used where the real
chip doesn't support them.


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

* Re: RFA: contribute Renesas M32C sim
  2005-12-14 18:40       ` DJ Delorie
@ 2005-12-15  0:01         ` Daniel Jacobowitz
  2005-12-15 14:48           ` Jim Blandy
  0 siblings, 1 reply; 14+ messages in thread
From: Daniel Jacobowitz @ 2005-12-15  0:01 UTC (permalink / raw)
  To: gdb-patches

On Tue, Dec 13, 2005 at 05:43:06PM -0500, DJ Delorie wrote:
> 
> > >> + void
> > >> + prefix (src_allowed, dest_allowed, index_bytewidth)
> > >> + {
> > >> + }
> > >
> > > And what's that for?
> > 
> > I don't know.  I thought it was some sort of annotation for opc2c to
> > consume, but that doesn't seem to be so.  I'll find out.
> 
> I remember talking to Jim about this, but I don't see him answering in
> the mail archives, and since I was checking on the m32c/gdb status I
> figured I'd at least get this one answered.
> 
> In short, that function exists so it can be called, it's the callers
> that are important at the moment.
> 
> The callers act as documentation for what prefixes and indexes are
> permitted for each opcode.  As I was going through the tedious process
> of implementing each opcode, I added all the calls to prefix() with
> the correct arguments.  The function does nothing yet, but at some
> point in the future it may fault if prefixes are used where the real
> chip doesn't support them.

Then please add some useful information there, so that the next
reviewer through the code does not remove it :-)

-- 
Daniel Jacobowitz
CodeSourcery, LLC


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

* Re: RFA: contribute Renesas M32C sim
  2005-12-15  0:01         ` Daniel Jacobowitz
@ 2005-12-15 14:48           ` Jim Blandy
  2005-12-15 16:18             ` Daniel Jacobowitz
  0 siblings, 1 reply; 14+ messages in thread
From: Jim Blandy @ 2005-12-15 14:48 UTC (permalink / raw)
  To: gdb-patches

The (unposted) code I've got currently reads:

/* Indicate which sorts of prefixes are allowed for the current
   opcode.  */
void
prefix (src_allowed, dest_allowed, index_bytewidth)
{
  /* At the moment, we don't do anything with this information.  We
     just wanted to get the information entered in some
     machine-readable form while we were going through all the
     opcodes.  */
}


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

* Re: RFA: contribute Renesas M32C sim
  2005-12-15 14:48           ` Jim Blandy
@ 2005-12-15 16:18             ` Daniel Jacobowitz
  0 siblings, 0 replies; 14+ messages in thread
From: Daniel Jacobowitz @ 2005-12-15 16:18 UTC (permalink / raw)
  To: gdb-patches

On Tue, Dec 13, 2005 at 04:39:54PM -0800, Jim Blandy wrote:
> The (unposted) code I've got currently reads:
> 
> /* Indicate which sorts of prefixes are allowed for the current
>    opcode.  */
> void
> prefix (src_allowed, dest_allowed, index_bytewidth)
> {
>   /* At the moment, we don't do anything with this information.  We
>      just wanted to get the information entered in some
>      machine-readable form while we were going through all the
>      opcodes.  */
> }

Perfect :-)

-- 
Daniel Jacobowitz
CodeSourcery, LLC


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

* Re: RFA: contribute Renesas M32C sim
  2005-10-12 22:12   ` Jim Blandy
@ 2006-01-23  2:03     ` Daniel Jacobowitz
  2006-01-23 22:11       ` Jim Blandy
  0 siblings, 1 reply; 14+ messages in thread
From: Daniel Jacobowitz @ 2006-01-23  2:03 UTC (permalink / raw)
  To: gdb-patches

On Wed, Oct 12, 2005 at 03:12:22PM -0700, Jim Blandy wrote:
> 
> I think the attached patch should address the points you raised:
> 
> - I added copyright notices.
> - I ran the code through gdb_indent.sh, and fixed up some further messes.
> - I added a comment to m32c.opc:prefix.

Hi Jim,

Anything ever come of this?  I don't see a reason to hold off on the
revised patch.

-- 
Daniel Jacobowitz
CodeSourcery


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

* Re: RFA: contribute Renesas M32C sim
  2006-01-23  2:03     ` Daniel Jacobowitz
@ 2006-01-23 22:11       ` Jim Blandy
  0 siblings, 0 replies; 14+ messages in thread
From: Jim Blandy @ 2006-01-23 22:11 UTC (permalink / raw)
  To: gdb-patches

On 1/22/06, Daniel Jacobowitz <drow@false.org> wrote:
> Anything ever come of this?  I don't see a reason to hold off on the
> revised patch.

I've committed the revised patch.  Thanks for the reminder.

For the GDB port, I still need to rework the prologue analyzer as you suggested.


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

end of thread, other threads:[~2006-01-23 22:11 UTC | newest]

Thread overview: 14+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2005-10-07 20:46 RFA: contribute Renesas M32C sim Jim Blandy
2005-10-07 21:03 ` Daniel Jacobowitz
2005-10-09  0:29   ` Jim Blandy
2005-10-09 20:15 ` Daniel Jacobowitz
2005-10-12 18:21   ` Jim Blandy
     [not found]     ` <jimb@redhat.com>
2005-12-14 18:40       ` DJ Delorie
2005-12-15  0:01         ` Daniel Jacobowitz
2005-12-15 14:48           ` Jim Blandy
2005-12-15 16:18             ` Daniel Jacobowitz
2005-10-12 22:12   ` Jim Blandy
2006-01-23  2:03     ` Daniel Jacobowitz
2006-01-23 22:11       ` Jim Blandy
2005-10-15 12:06 ` Eli Zaretskii
2005-10-17 23:26   ` Jim Blandy

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