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.
	* 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.
This commit is contained in:
Jim Blandy 2006-01-23 22:10:41 +00:00
parent dda6380765
commit d45a4bef83
35 changed files with 17347 additions and 0 deletions

View File

@ -1,3 +1,11 @@
2006-01-23 Jim Blandy <jimb@redhat.com>
Add simulator for Renesas M32C and M16C.
* m32c: New directory.
* configure.ac: Add entry for Renesas M32C.
* configure: Regenerate.
2006-01-10 Hans-Peter Nilsson <hp@axis.com>
* cris/cris-tmpl.c (MY (f_model_insn_before)): Only display basic

8
sim/configure vendored
View File

@ -278,6 +278,7 @@ ac_subdirs_all="$ac_subdirs_all d10v"
ac_subdirs_all="$ac_subdirs_all frv"
ac_subdirs_all="$ac_subdirs_all h8300"
ac_subdirs_all="$ac_subdirs_all iq2000"
ac_subdirs_all="$ac_subdirs_all m32c"
ac_subdirs_all="$ac_subdirs_all m32r"
ac_subdirs_all="$ac_subdirs_all m68hc11"
ac_subdirs_all="$ac_subdirs_all mcore"
@ -3458,6 +3459,13 @@ subdirs="$subdirs iq2000"
testsuite=yes
common=yes
;;
m32c-*-*)
subdirs="$subdirs m32c"
common=yes
;;
m32r-*-*)

View File

@ -73,6 +73,10 @@ if test "${enable_sim}" != no; then
testsuite=yes
common=yes
;;
m32c-*-*)
AC_CONFIG_SUBDIRS(m32c)
common=yes
;;
m32r-*-*)
AC_CONFIG_SUBDIRS(m32r)
testsuite=yes

40
sim/m32c/ChangeLog Normal file
View File

@ -0,0 +1,40 @@
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.
* 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.

93
sim/m32c/Makefile.in Normal file
View File

@ -0,0 +1,93 @@
#### Makefile.in --- Makefile template for the M32C simulator
### Copyright (C) 2005 Free Software Foundation, Inc.
### Contributed by Red Hat, Inc.
###
### This file is part of the GNU simulators.
###
### The GNU simulators are free software; you can redistribute them and/or
### modify them under the terms of the GNU General Public License as
### published by the Free Software Foundation; either version 2 of the
### License, or (at your option) any later version.
###
### The GNU simulators are distributed in the hope that they will be
### useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
### MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
### General Public License for more details.
###
### You should have received a copy of the GNU General Public License
### along with the GNU simulators; if not, write to the Free Software
### Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
### 02110-1301, USA
## COMMON_PRE_CONFIG_FRAG
SIM_EXTRA_CFLAGS = -Wall
SIM_RUN_OBJS = \
main.o \
$(ENDLIST)
SIM_OBJS = \
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

36
sim/m32c/blinky.S Normal file
View File

@ -0,0 +1,36 @@
;;; blinky.S --- sample program to blink LED's on M32C simulator
;;;
;;; Copyright (C) 2005 Free Software Foundation, Inc.
;;; Contributed by Red Hat, Inc.
;;;
;;; This file is part of the GNU simulators.
;;;
;;; The GNU simulators are free software; you can redistribute them
;;; and/or modify them under the terms of the GNU General Public
;;; License as published by the Free Software Foundation; either
;;; version 2 of the License, or (at your option) any later version.
;;;
;;; The GNU simulators are distributed in the hope that they will be
;;; useful, but WITHOUT ANY WARRANTY; without even the implied
;;; warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
;;; PURPOSE. See the GNU General Public License for more details.
;;;
;;; You should have received a copy of the GNU General Public License
;;; along with the GNU simulators; if not, write to the Free Software
;;; Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
;;; 02110-1301, USA
.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

0
sim/m32c/config.in Normal file
View File

8523
sim/m32c/configure vendored Executable file

File diff suppressed because it is too large Load Diff

33
sim/m32c/configure.in Normal file
View File

@ -0,0 +1,33 @@
dnl Process this file with autoconf to produce a configure script.
dnl Copyright (C) 2005 Free Software Foundation, Inc.
dnl Contributed by Red Hat, Inc.
dnl
dnl This file is part of the GNU simulators.
dnl
dnl The GNU simulators are free software; you can redistribute them and/or
dnl modify them under the terms of the GNU General Public License as
dnl published by the Free Software Foundation; either version 2 of the
dnl License, or (at your option) any later version.
dnl
dnl The GNU simulators are distributed in the hope that they will be
dnl useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
dnl MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
dnl General Public License for more details.
dnl
dnl You should have received a copy of the GNU General Public License
dnl along with the GNU simulators; if not, write to the Free Software
dnl Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
dnl 02110-1301, USA
dnl
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

224
sim/m32c/cpu.h Normal file
View File

@ -0,0 +1,224 @@
/* cpu.h --- declarations for the M32C core.
Copyright (C) 2005 Free Software Foundation, Inc.
Contributed by Red Hat, Inc.
This file is part of the GNU simulators.
The GNU simulators are free software; you can redistribute them and/or
modify them under the terms of the GNU General Public License as
published by the Free Software Foundation; either version 2 of the
License, or (at your option) any later version.
The GNU simulators are distributed in the hope that they will be
useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
General Public License for more details.
You should have received a copy of the GNU General Public License
along with the GNU simulators; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
02110-1301, USA */
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 ();

710
sim/m32c/gdb-if.c Normal file
View File

@ -0,0 +1,710 @@
/* gdb.c --- sim interface to GDB.
Copyright (C) 2005 Free Software Foundation, Inc.
Contributed by Red Hat, Inc.
This file is part of the GNU simulators.
The GNU simulators are free software; you can redistribute them and/or
modify them under the terms of the GNU General Public License as
published by the Free Software Foundation; either version 2 of the
License, or (at your option) any later version.
The GNU simulators are distributed in the hope that they will be
useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
General Public License for more details.
You should have received a copy of the GNU General Public License
along with the GNU simulators; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
02110-1301, USA */
#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");
}

34
sim/m32c/gloss.S Normal file
View File

@ -0,0 +1,34 @@
;;; gloss.S --- system calls for sample2.x
;;;
;;; Copyright (C) 2005 Free Software Foundation, Inc.
;;; Contributed by Red Hat, Inc.
;;;
;;; This file is part of the GNU simulators.
;;;
;;; The GNU simulators are free software; you can redistribute them
;;; and/or modify them under the terms of the GNU General Public
;;; License as published by the Free Software Foundation; either
;;; version 2 of the License, or (at your option) any later version.
;;;
;;; The GNU simulators are distributed in the hope that they will be
;;; useful, but WITHOUT ANY WARRANTY; without even the implied
;;; warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
;;; PURPOSE. See the GNU General Public License for more details.
;;;
;;; You should have received a copy of the GNU General Public License
;;; along with the GNU simulators; if not, write to the Free Software
;;; Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
;;; 02110-1301, USA
;;; See the 'sample2.x' target in Makefile.in.
.global _exit
_exit:
mov.b #1,r0l
ste.b r0l,0xe0000
rts
.global _foo
_foo:
mov.b #2,r0l
ste.b r0l,0xe0000
rts

61
sim/m32c/int.c Normal file
View File

@ -0,0 +1,61 @@
/* int.c --- M32C interrupt handling.
Copyright (C) 2005 Free Software Foundation, Inc.
Contributed by Red Hat, Inc.
This file is part of the GNU simulators.
The GNU simulators are free software; you can redistribute them and/or
modify them under the terms of the GNU General Public License as
published by the Free Software Foundation; either version 2 of the
License, or (at your option) any later version.
The GNU simulators are distributed in the hope that they will be
useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
General Public License for more details.
You should have received a copy of the GNU General Public License
along with the GNU simulators; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
02110-1301, USA */
#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);
}

25
sim/m32c/int.h Normal file
View File

@ -0,0 +1,25 @@
/* int.h --- interface to M32C interrupt handling.
Copyright (C) 2005 Free Software Foundation, Inc.
Contributed by Red Hat, Inc.
This file is part of the GNU simulators.
The GNU simulators are free software; you can redistribute them and/or
modify them under the terms of the GNU General Public License as
published by the Free Software Foundation; either version 2 of the
License, or (at your option) any later version.
The GNU simulators are distributed in the hope that they will be
useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
General Public License for more details.
You should have received a copy of the GNU General Public License
along with the GNU simulators; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
02110-1301, USA */
extern void trigger_fixed_interrupt (int addr);
extern void trigger_based_interrupt (int vector);

131
sim/m32c/load.c Normal file
View File

@ -0,0 +1,131 @@
/* load.c --- loading object files into the M32C simulator.
Copyright (C) 2005 Free Software Foundation, Inc.
Contributed by Red Hat, Inc.
This file is part of the GNU simulators.
The GNU simulators are free software; you can redistribute them and/or
modify them under the terms of the GNU General Public License as
published by the Free Software Foundation; either version 2 of the
License, or (at your option) any later version.
The GNU simulators are distributed in the hope that they will be
useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
General Public License for more details.
You should have received a copy of the GNU General Public License
along with the GNU simulators; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
02110-1301, USA */
#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);
}

29
sim/m32c/load.h Normal file
View File

@ -0,0 +1,29 @@
/* load.h --- interface to loading object files into the M32C simulator.
Copyright (C) 2005 Free Software Foundation, Inc.
Contributed by Red Hat, Inc.
This file is part of the GNU simulators.
The GNU simulators are free software; you can redistribute them and/or
modify them under the terms of the GNU General Public License as
published by the Free Software Foundation; either version 2 of the
License, or (at your option) any later version.
The GNU simulators are distributed in the hope that they will be
useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
General Public License for more details.
You should have received a copy of the GNU General Public License
along with the GNU simulators; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
02110-1301, USA */
#include "bfd.h"
extern int default_machine;
void m32c_set_mach (int mach);
void m32c_load (bfd *);

2104
sim/m32c/m32c.opc Normal file

File diff suppressed because it is too large Load Diff

138
sim/m32c/main.c Normal file
View File

@ -0,0 +1,138 @@
/* main.c --- main function for stand-alone M32C simulator.
Copyright (C) 2005 Free Software Foundation, Inc.
Contributed by Red Hat, Inc.
This file is part of the GNU simulators.
The GNU simulators are free software; you can redistribute them and/or
modify them under the terms of the GNU General Public License as
published by the Free Software Foundation; either version 2 of the
License, or (at your option) any later version.
The GNU simulators are distributed in the hope that they will be
useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
General Public License for more details.
You should have received a copy of the GNU General Public License
along with the GNU simulators; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
02110-1301, USA */
#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 ();
}
}

377
sim/m32c/mem.c Normal file
View File

@ -0,0 +1,377 @@
/* mem.c --- memory for M32C simulator.
Copyright (C) 2005 Free Software Foundation, Inc.
Contributed by Red Hat, Inc.
This file is part of the GNU simulators.
The GNU simulators are free software; you can redistribute them and/or
modify them under the terms of the GNU General Public License as
published by the Free Software Foundation; either version 2 of the
License, or (at your option) any later version.
The GNU simulators are distributed in the hope that they will be
useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
General Public License for more details.
You should have received a copy of the GNU General Public License
along with the GNU simulators; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
02110-1301, USA */
#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;
}

43
sim/m32c/mem.h Normal file
View File

@ -0,0 +1,43 @@
/* mem.h --- interface to memory for M32C simulator.
Copyright (C) 2005 Free Software Foundation, Inc.
Contributed by Red Hat, Inc.
This file is part of the GNU simulators.
The GNU simulators are free software; you can redistribute them and/or
modify them under the terms of the GNU General Public License as
published by the Free Software Foundation; either version 2 of the
License, or (at your option) any later version.
The GNU simulators are distributed in the hope that they will be
useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
General Public License for more details.
You should have received a copy of the GNU General Public License
along with the GNU simulators; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
02110-1301, USA */
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);

79
sim/m32c/misc.c Normal file
View File

@ -0,0 +1,79 @@
/* misc.c --- miscellaneous utility functions for M32C simulator.
Copyright (C) 2005 Free Software Foundation, Inc.
Contributed by Red Hat, Inc.
This file is part of the GNU simulators.
The GNU simulators are free software; you can redistribute them and/or
modify them under the terms of the GNU General Public License as
published by the Free Software Foundation; either version 2 of the
License, or (at your option) any later version.
The GNU simulators are distributed in the hope that they will be
useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
General Public License for more details.
You should have received a copy of the GNU General Public License
along with the GNU simulators; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
02110-1301, USA */
#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;
}

27
sim/m32c/misc.h Normal file
View File

@ -0,0 +1,27 @@
/* misc.h --- interface to miscellaneous utility functions for M32C simulator.
Copyright (C) 2005 Free Software Foundation, Inc.
Contributed by Red Hat, Inc.
This file is part of the GNU simulators.
The GNU simulators are free software; you can redistribute them and/or
modify them under the terms of the GNU General Public License as
published by the Free Software Foundation; either version 2 of the
License, or (at your option) any later version.
The GNU simulators are distributed in the hope that they will be
useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
General Public License for more details.
You should have received a copy of the GNU General Public License
along with the GNU simulators; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
02110-1301, USA */
int bcd2int (int bcd, int w);
int int2bcd (int val, int w);
char *comma (unsigned int u);

730
sim/m32c/opc2c.c Normal file
View File

@ -0,0 +1,730 @@
/* opc2c.c --- generate C simulator code from from .opc file
Copyright (C) 2005 Free Software Foundation, Inc.
Contributed by Red Hat, Inc.
This file is part of the GNU simulators.
The GNU simulators are free software; you can redistribute them and/or
modify them under the terms of the GNU General Public License as
published by the Free Software Foundation; either version 2 of the
License, or (at your option) any later version.
The GNU simulators are distributed in the hope that they will be
useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
General Public License for more details.
You should have received a copy of the GNU General Public License
along with the GNU simulators; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
02110-1301, USA */
#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, " /** ", 6) == 0
&& (isdigit (line[6]) || memcmp (line + 6, "VARY", 4) == 0))
line += 2;
if (line[0] == '/' && line[1] == '*' && line[2] == '*')
{
if (strncmp (line, "/** */", 6) == 0)
{
op = &suffix_text;
op->lineno = lineno;
}
else if (strncmp (line, "/** VARY ", 9) == 0)
process_vary (line + 9);
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 + 4; *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;
}

1580
sim/m32c/r8c.opc Normal file

File diff suppressed because it is too large Load Diff

624
sim/m32c/reg.c Normal file
View File

@ -0,0 +1,624 @@
/* reg.c --- register set model for M32C simulator.
Copyright (C) 2005 Free Software Foundation, Inc.
Contributed by Red Hat, Inc.
This file is part of the GNU simulators.
The GNU simulators are free software; you can redistribute them and/or
modify them under the terms of the GNU General Public License as
published by the Free Software Foundation; either version 2 of the
License, or (at your option) any later version.
The GNU simulators are distributed in the hope that they will be
useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
General Public License for more details.
You should have received a copy of the GNU General Public License
along with the GNU simulators; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
02110-1301, USA */
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "cpu.h"
int verbose = 0;
int trace = 0;
int enable_counting = 0;
regs_type regs;
int addr_mask = 0xffff;
int membus_mask = 0xfffff;
int m32c_cpu = 0;
int step_result;
unsigned int heapbottom = 0;
unsigned int heaptop = 0;
char *reg_names[] = {
"mem",
"r0", "r0h", "r0l",
"r1", "r1h", "r1l",
"r2", "r2r0",
"r3", "r3r1",
"r3r1r2r0",
"r3r2r1r0",
"a0",
"a1", "a1a0",
"sb", "fb",
"intb", "intbl", "intbh",
"sp", "usp", "isp", "pc", "flags"
};
int reg_bytes[] = {
0,
2, 1, 1,
2, 1, 1,
2, 4,
2, 4,
8,
8,
2,
2, 4,
2, 2,
2, 1, 3,
2, 2, 2, 3, 2
};
unsigned int b2mask[] = { 0, 0xff, 0xffff, 0xffffff, 0xffffffff };
unsigned int b2signbit[] = { 0, (1 << 7), (1 << 15), (1 << 24), (1 << 31) };
int b2maxsigned[] = { 0, 0x7f, 0x7fff, 0x7fffff, 0x7fffffff };
int b2minsigned[] = { 0, -128, -32768, -8388608, -2147483647 - 1 };
static regs_type oldregs;
void
init_regs (void)
{
memset (&regs, 0, sizeof (regs));
memset (&oldregs, 0, sizeof (oldregs));
}
void
set_pointer_width (int bytes)
{
if (bytes == 2)
{
addr_mask = 0xffff;
membus_mask = 0x000fffff;
reg_bytes[a0] = reg_bytes[a1] = reg_bytes[sb] = reg_bytes[fb] =
reg_bytes[sp] = reg_bytes[usp] = reg_bytes[isp] = 2;
}
else
{
addr_mask = 0xffffff;
membus_mask = 0x00ffffff;
reg_bytes[a0] = reg_bytes[a1] = reg_bytes[sb] = reg_bytes[fb] =
reg_bytes[sp] = reg_bytes[usp] = reg_bytes[isp] = 3;
}
}
void
m32c_set_cpu (int cpu)
{
switch (cpu)
{
case CPU_R8C:
case CPU_M16C:
set_pointer_width (2);
decode_opcode = decode_r8c;
break;
case CPU_M32CM:
case CPU_M32C:
set_pointer_width (3);
decode_opcode = decode_m32c;
break;
default:
abort ();
}
m32c_cpu = cpu;
}
static unsigned int
get_reg_i (reg_id id)
{
reg_bank_type *b = regs.r + (FLAG_B ? 1 : 0);
switch (id)
{
case r0:
return b->r_r0;
case r0h:
return b->r_r0 >> 8;
case r0l:
return b->r_r0 & 0xff;
case r1:
return b->r_r1;
case r1h:
return b->r_r1 >> 8;
case r1l:
return b->r_r1 & 0xff;
case r2:
return b->r_r2;
case r2r0:
return b->r_r2 * 65536 + b->r_r0;
case r3:
return b->r_r3;
case r3r1:
return b->r_r3 * 65536 + b->r_r1;
case a0:
return b->r_a0 & addr_mask;
case a1:
return b->r_a1 & addr_mask;
case a1a0:
return (b->r_a1 & 0xffff) * 65536 | (b->r_a0 & 0xffff);
case sb:
return b->r_sb & addr_mask;
case fb:
return b->r_fb & addr_mask;
case intb:
return regs.r_intbh * 65536 + regs.r_intbl;
case intbl:
return regs.r_intbl;
case intbh:
return regs.r_intbh;
case sp:
return ((regs.r_flags & FLAGBIT_U) ? regs.r_usp : regs.
r_isp) & addr_mask;
case usp:
return regs.r_usp & addr_mask;
case isp:
return regs.r_isp & addr_mask;
case pc:
return regs.r_pc & membus_mask;
case flags:
return regs.r_flags;
default:
abort ();
}
}
unsigned int
get_reg (reg_id id)
{
unsigned int rv = get_reg_i (id);
if (trace > ((id != pc && id != fb && id != sp) ? 0 : 1))
printf ("get_reg (%s) = %0*x\n", reg_names[id], reg_bytes[id] * 2, rv);
return rv;
}
DI
get_reg_ll (reg_id id)
{
reg_bank_type *b = regs.r + (FLAG_B ? 1 : 0);
switch (id)
{
case r3r1r2r0:
return ((DI) b->r_r3 << 48
| (DI) b->r_r1 << 32 | (DI) b->r_r2 << 16 | (DI) b->r_r0);
case r3r2r1r0:
return ((DI) b->r_r3 << 48
| (DI) b->r_r2 << 32 | (DI) b->r_r1 << 16 | (DI) b->r_r0);
default:
return get_reg (id);
}
}
static int highest_sp = 0, lowest_sp = 0xffffff;
void
stack_heap_stats ()
{
printf ("heap: %08x - %08x (%d bytes)\n", heapbottom, heaptop,
heaptop - heapbottom);
printf ("stack: %08x - %08x (%d bytes)\n", lowest_sp, highest_sp,
highest_sp - lowest_sp);
}
void
put_reg (reg_id id, unsigned int v)
{
if (trace > ((id != pc) ? 0 : 1))
printf ("put_reg (%s) = %0*x\n", reg_names[id], reg_bytes[id] * 2, v);
reg_bank_type *b = regs.r + (FLAG_B ? 1 : 0);
switch (id)
{
case r0:
b->r_r0 = v;
break;
case r0h:
b->r_r0 = (b->r_r0 & 0xff) | (v << 8);
break;
case r0l:
b->r_r0 = (b->r_r0 & 0xff00) | (v & 0xff);
break;
case r1:
b->r_r1 = v;
break;
case r1h:
b->r_r1 = (b->r_r1 & 0xff) | (v << 8);
break;
case r1l:
b->r_r1 = (b->r_r1 & 0xff00) | (v & 0xff);
break;
case r2:
b->r_r2 = v;
break;
case r2r0:
b->r_r0 = v & 0xffff;
b->r_r2 = v >> 16;
break;
case r3:
b->r_r3 = v;
break;
case r3r1:
b->r_r1 = v & 0xffff;
b->r_r3 = v >> 16;
break;
case a0:
b->r_a0 = v & addr_mask;
break;
case a1:
b->r_a1 = v & addr_mask;
break;
case a1a0:
b->r_a0 = v & 0xffff;
b->r_a1 = v >> 16;
break;
case sb:
b->r_sb = v & addr_mask;
break;
case fb:
b->r_fb = v & addr_mask;
break;
case intb:
regs.r_intbl = v & 0xffff;
regs.r_intbh = v >> 16;
break;
case intbl:
regs.r_intbl = v & 0xffff;
break;
case intbh:
regs.r_intbh = v & 0xff;
break;
case sp:
{
SI *spp;
if (regs.r_flags & FLAGBIT_U)
spp = &regs.r_usp;
else
spp = &regs.r_isp;
*spp = v & addr_mask;
if (*spp < heaptop)
{
printf ("collision: pc %08lx heap %08x stack %08lx\n", regs.r_pc,
heaptop, *spp);
exit (1);
}
if (*spp < lowest_sp)
lowest_sp = *spp;
if (*spp > highest_sp)
highest_sp = *spp;
break;
}
case usp:
regs.r_usp = v & addr_mask;
break;
case isp:
regs.r_isp = v & addr_mask;
break;
case pc:
regs.r_pc = v & membus_mask;
break;
case flags:
regs.r_flags = v;
break;
default:
abort ();
}
}
int
condition_true (int cond_id)
{
int f;
if (A16)
{
static const char *cond_name[] = {
"C", "C&!Z", "Z", "S",
"!C", "!(C&!Z)", "!Z", "!S",
"(S^O)|Z", "O", "!(S^O)", "unk",
"!((S^O)|Z)", "!O", "S^O", "unk"
};
switch (cond_id)
{
case 0:
f = FLAG_C;
break; /* GEU/C */
case 1:
f = FLAG_C & !FLAG_Z;
break; /* GTU */
case 2:
f = FLAG_Z;
break; /* EQ/Z */
case 3:
f = FLAG_S;
break; /* N */
case 4:
f = !FLAG_C;
break; /* LTU/NC */
case 5:
f = !(FLAG_C & !FLAG_Z);
break; /* LEU */
case 6:
f = !FLAG_Z;
break; /* NE/NZ */
case 7:
f = !FLAG_S;
break; /* PZ */
case 8:
f = (FLAG_S ^ FLAG_O) | FLAG_Z;
break; /* LE */
case 9:
f = FLAG_O;
break; /* O */
case 10:
f = !(FLAG_S ^ FLAG_O);
break; /* GE */
case 12:
f = !((FLAG_S ^ FLAG_O) | FLAG_Z);
break; /* GT */
case 13:
f = !FLAG_O;
break; /* NO */
case 14:
f = FLAG_S ^ FLAG_O;
break; /* LT */
default:
f = 0;
break;
}
if (trace)
printf ("cond[%d] %s = %s\n", cond_id, cond_name[cond_id & 15],
f ? "true" : "false");
}
else
{
static const char *cond_name[] = {
"!C", "LEU", "!Z", "PZ",
"!O", "GT", "GE", "?",
"C", "GTU", "Z", "N",
"O", "LE", "LT", "!?"
};
switch (cond_id)
{
case 0:
f = !FLAG_C;
break; /* LTU/NC */
case 1:
f = !(FLAG_C & !FLAG_Z);
break; /* LEU */
case 2:
f = !FLAG_Z;
break; /* NE/NZ */
case 3:
f = !FLAG_S;
break; /* PZ */
case 4:
f = !FLAG_O;
break; /* NO */
case 5:
f = !((FLAG_S ^ FLAG_O) | FLAG_Z);
break; /* GT */
case 6:
f = !(FLAG_S ^ FLAG_O);
break; /* GE */
case 8:
f = FLAG_C;
break; /* GEU/C */
case 9:
f = FLAG_C & !FLAG_Z;
break; /* GTU */
case 10:
f = FLAG_Z;
break; /* EQ/Z */
case 11:
f = FLAG_S;
break; /* N */
case 12:
f = FLAG_O;
break; /* O */
case 13:
f = (FLAG_S ^ FLAG_O) | FLAG_Z;
break; /* LE */
case 14:
f = FLAG_S ^ FLAG_O;
break; /* LT */
default:
f = 0;
break;
}
if (trace)
printf ("cond[%d] %s = %s\n", cond_id, cond_name[cond_id & 15],
f ? "true" : "false");
}
return f;
}
void
set_flags (int mask, int newbits)
{
int i;
regs.r_flags &= ~mask;
regs.r_flags |= newbits & mask;
if (trace)
{
printf ("flags now \033[32m %d", (regs.r_flags >> (A16 ? 8 : 12)) & 7);
for (i = 7; i >= 0; i--)
if (regs.r_flags & (1 << i))
putchar ("CDZSBOIU"[i]);
else
putchar ('-');
printf ("\033[0m\n");
}
}
void
set_oszc (int value, int b, int c)
{
int mask = b2mask[b];
int f = 0;
if (c)
f |= FLAGBIT_C;
if ((value & mask) == 0)
f |= FLAGBIT_Z;
if (value & b2signbit[b])
f |= FLAGBIT_S;
if ((value > b2maxsigned[b]) || (value < b2minsigned[b]))
f |= FLAGBIT_O;
set_flags (FLAGBIT_Z | FLAGBIT_S | FLAGBIT_O | FLAGBIT_C, f);
}
void
set_szc (int value, int b, int c)
{
int mask = b2mask[b];
int f = 0;
if (c)
f |= FLAGBIT_C;
if ((value & mask) == 0)
f |= FLAGBIT_Z;
if (value & b2signbit[b])
f |= FLAGBIT_S;
set_flags (FLAGBIT_Z | FLAGBIT_S | FLAGBIT_C, f);
}
void
set_osz (int value, int b)
{
int mask = b2mask[b];
int f = 0;
if ((value & mask) == 0)
f |= FLAGBIT_Z;
if (value & b2signbit[b])
f |= FLAGBIT_S;
if (value & ~mask && (value & ~mask) != ~mask)
f |= FLAGBIT_O;
set_flags (FLAGBIT_Z | FLAGBIT_S | FLAGBIT_O, f);
}
void
set_sz (int value, int b)
{
int mask = b2mask[b];
int f = 0;
if ((value & mask) == 0)
f |= FLAGBIT_Z;
if (value & b2signbit[b])
f |= FLAGBIT_S;
set_flags (FLAGBIT_Z | FLAGBIT_S, f);
}
void
set_zc (int z, int c)
{
set_flags (FLAGBIT_C | FLAGBIT_Z,
(c ? FLAGBIT_C : 0) | (z ? FLAGBIT_Z : 0));
}
void
set_c (int c)
{
set_flags (FLAGBIT_C, c ? FLAGBIT_C : 0);
}
void
put_reg_ll (reg_id id, DI v)
{
reg_bank_type *b = regs.r + (FLAG_B ? 1 : 0);
switch (id)
{
case r3r1r2r0:
b->r_r3 = v >> 48;
b->r_r1 = v >> 32;
b->r_r2 = v >> 16;
b->r_r0 = v;
break;
case r3r2r1r0:
b->r_r3 = v >> 48;
b->r_r2 = v >> 32;
b->r_r1 = v >> 16;
b->r_r0 = v;
break;
default:
put_reg (id, v);
}
}
#define TRC(f,n, id) \
if (oldregs.f != regs.f) \
{ \
printf(" %s %0*x:%0*x", n, \
reg_bytes[id]*2, (unsigned int)oldregs.f, \
reg_bytes[id]*2, (unsigned int)regs.f); \
oldregs.f = regs.f; \
}
void
trace_register_changes ()
{
if (!trace)
return;
printf ("\033[36mREGS:");
TRC (r[0].r_r0, "r0", r0);
TRC (r[0].r_r1, "r1", r1);
TRC (r[0].r_r2, "r2", r2);
TRC (r[0].r_r3, "r3", r3);
TRC (r[0].r_a0, "a0", a0);
TRC (r[0].r_a1, "a1", a1);
TRC (r[0].r_sb, "sb", sb);
TRC (r[0].r_fb, "fb", fb);
TRC (r[1].r_r0, "r0'", r0);
TRC (r[1].r_r1, "r1'", r1);
TRC (r[1].r_r2, "r2'", r2);
TRC (r[1].r_r3, "r3'", r3);
TRC (r[1].r_a0, "a0'", a0);
TRC (r[1].r_a1, "a1'", a1);
TRC (r[1].r_sb, "sb'", sb);
TRC (r[1].r_fb, "fb'", fb);
TRC (r_intbh, "intbh", intbh);
TRC (r_intbl, "intbl", intbl);
TRC (r_usp, "usp", usp);
TRC (r_isp, "isp", isp);
TRC (r_pc, "pc", pc);
TRC (r_flags, "flags", flags);
printf ("\033[0m\n");
}

71
sim/m32c/safe-fgets.c Normal file
View File

@ -0,0 +1,71 @@
/* safe-fgets.c --- like fgets, but allocates its own static buffer.
Copyright (C) 2005 Free Software Foundation, Inc.
Contributed by Red Hat, Inc.
This file is part of the GNU simulators.
The GNU simulators are free software; you can redistribute them and/or
modify them under the terms of the GNU General Public License as
published by the Free Software Foundation; either version 2 of the
License, or (at your option) any later version.
The GNU simulators are distributed in the hope that they will be
useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
General Public License for more details.
You should have received a copy of the GNU General Public License
along with the GNU simulators; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
02110-1301, USA */
#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;
}

29
sim/m32c/safe-fgets.h Normal file
View File

@ -0,0 +1,29 @@
/* safe-fgets.h --- interface to safe version of fgets.
Copyright (C) 2005 Free Software Foundation, Inc.
Contributed by Red Hat, Inc.
This file is part of the GNU simulators.
The GNU simulators are free software; you can redistribute them and/or
modify them under the terms of the GNU General Public License as
published by the Free Software Foundation; either version 2 of the
License, or (at your option) any later version.
The GNU simulators are distributed in the hope that they will be
useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
General Public License for more details.
You should have received a copy of the GNU General Public License
along with the GNU simulators; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
02110-1301, USA */
#ifndef _safe_gets_h_
#define _safe_gets_h_
char *safe_fgets (FILE *f);
#endif

31
sim/m32c/sample.S Normal file
View File

@ -0,0 +1,31 @@
;;; sample.S --- simple test program for M32C simulator
;;;
;;; Copyright (C) 2005 Free Software Foundation, Inc.
;;; Contributed by Red Hat, Inc.
;;;
;;; This file is part of the GNU simulators.
;;;
;;; The GNU simulators are free software; you can redistribute them
;;; and/or modify them under the terms of the GNU General Public
;;; License as published by the Free Software Foundation; either
;;; version 2 of the License, or (at your option) any later version.
;;;
;;; The GNU simulators are distributed in the hope that they will be
;;; useful, but WITHOUT ANY WARRANTY; without even the implied
;;; warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
;;; PURPOSE. See the GNU General Public License for more details.
;;;
;;; You should have received a copy of the GNU General Public License
;;; along with the GNU simulators; if not, write to the Free Software
;;; Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
;;; 02110-1301, USA
;;; See the 'sample.x' and sample.mot targets in Makefile.in.
.text
.global _start
_start:
mov.w #0x1234,r1
mov.w r1,r3 | sha.w #-8,r3 | sha.w #-7,r3
brk

43
sim/m32c/sample.ld Normal file
View File

@ -0,0 +1,43 @@
/* sample2.ld --- linker script for sample2.x
Copyright (C) 2005 Free Software Foundation, Inc.
Contributed by Red Hat, Inc.
This file is part of the GNU simulators.
The GNU simulators are free software; you can redistribute them and/or
modify them under the terms of the GNU General Public License as
published by the Free Software Foundation; either version 2 of the
License, or (at your option) any later version.
The GNU simulators are distributed in the hope that they will be
useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
General Public License for more details.
You should have received a copy of the GNU General Public License
along with the GNU simulators; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
02110-1301, USA */
/* See the 'sample2.x' target in Makefile.in. */
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
}

30
sim/m32c/sample2.c Normal file
View File

@ -0,0 +1,30 @@
/* sample2.c --- main source for sample2.x test program for M32C simulator
Copyright (C) 2005 Free Software Foundation, Inc.
Contributed by Red Hat, Inc.
This file is part of the GNU simulators.
The GNU simulators are free software; you can redistribute them and/or
modify them under the terms of the GNU General Public License as
published by the Free Software Foundation; either version 2 of the
License, or (at your option) any later version.
The GNU simulators are distributed in the hope that they will be
useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
General Public License for more details.
You should have received a copy of the GNU General Public License
along with the GNU simulators; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
02110-1301, USA */
/* See the 'sample2.x' target in Makefile.in. */
void exit (int);
start ()
{
foo (1, 2, 3, 4);
exit (5);
}

780
sim/m32c/srcdest.c Normal file
View File

@ -0,0 +1,780 @@
/* srcdest.c --- decoding M32C addressing modes.
Copyright (C) 2005 Free Software Foundation, Inc.
Contributed by Red Hat, Inc.
This file is part of the GNU simulators.
The GNU simulators are free software; you can redistribute them and/or
modify them under the terms of the GNU General Public License as
published by the Free Software Foundation; either version 2 of the
License, or (at your option) any later version.
The GNU simulators are distributed in the hope that they will be
useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
General Public License for more details.
You should have received a copy of the GNU General Public License
along with the GNU simulators; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
02110-1301, USA */
#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);
}

336
sim/m32c/syscalls.c Normal file
View File

@ -0,0 +1,336 @@
/* syscalls.c --- implement system calls for the M32C simulator.
Copyright (C) 2005 Free Software Foundation, Inc.
Contributed by Red Hat, Inc.
This file is part of the GNU simulators.
The GNU simulators are free software; you can redistribute them and/or
modify them under the terms of the GNU General Public License as
published by the Free Software Foundation; either version 2 of the
License, or (at your option) any later version.
The GNU simulators are distributed in the hope that they will be
useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
General Public License for more details.
You should have received a copy of the GNU General Public License
along with the GNU simulators; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
02110-1301, USA */
#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;
}
}

26
sim/m32c/syscalls.h Normal file
View File

@ -0,0 +1,26 @@
/* syscalls.h --- interface to syscalls for the M32C sim.
Copyright (C) 2005 Free Software Foundation, Inc.
Contributed by Red Hat, Inc.
This file is part of the GNU simulators.
The GNU simulators are free software; you can redistribute them and/or
modify them under the terms of the GNU General Public License as
published by the Free Software Foundation; either version 2 of the
License, or (at your option) any later version.
The GNU simulators are distributed in the hope that they will be
useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
General Public License for more details.
You should have received a copy of the GNU General Public License
along with the GNU simulators; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
02110-1301, USA */
struct host_callback_struct;
extern void set_callbacks (struct host_callback_struct *);
extern void m32c_syscall (int id);

315
sim/m32c/trace.c Normal file
View File

@ -0,0 +1,315 @@
/* trace.c --- tracing output for the M32C simulator.
Copyright (C) 2005 Free Software Foundation, Inc.
Contributed by Red Hat, Inc.
This file is part of the GNU simulators.
The GNU simulators are free software; you can redistribute them and/or
modify them under the terms of the GNU General Public License as
published by the Free Software Foundation; either version 2 of the
License, or (at your option) any later version.
The GNU simulators are distributed in the hope that they will be
useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
General Public License for more details.
You should have received a copy of the GNU General Public License
along with the GNU simulators; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
02110-1301, USA */
#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;
}

25
sim/m32c/trace.h Normal file
View File

@ -0,0 +1,25 @@
/* trace.h --- interface to tracing output for the M32C simulator.
Copyright (C) 2005 Free Software Foundation, Inc.
Contributed by Red Hat, Inc.
This file is part of the GNU simulators.
The GNU simulators are free software; you can redistribute them and/or
modify them under the terms of the GNU General Public License as
published by the Free Software Foundation; either version 2 of the
License, or (at your option) any later version.
The GNU simulators are distributed in the hope that they will be
useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
General Public License for more details.
You should have received a copy of the GNU General Public License
along with the GNU simulators; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
02110-1301, USA */
void sim_disasm_init (bfd *prog);
extern void sim_disasm_one (void);