This is the mail archive of the
gdb-patches@sourceware.org
mailing list for the GDB project.
RFA: contribute Renesas M32C sim
- From: Jim Blandy <jimb at redhat dot com>
- To: gdb-patches at sourceware dot org
- Date: Fri, 07 Oct 2005 13:44:09 -0700
- Subject: 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 (®s, 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 = ®s.r_usp;
+ else
+ spp = ®s.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, §ion_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);