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


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

RFA: contribute Renesas M32C sim


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


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