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:
parent
dda6380765
commit
d45a4bef83
@ -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
8
sim/configure
vendored
@ -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-*-*)
|
||||
|
||||
|
||||
|
@ -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
40
sim/m32c/ChangeLog
Normal 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
93
sim/m32c/Makefile.in
Normal 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
36
sim/m32c/blinky.S
Normal 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
0
sim/m32c/config.in
Normal file
8523
sim/m32c/configure
vendored
Executable 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
33
sim/m32c/configure.in
Normal 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
224
sim/m32c/cpu.h
Normal 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
710
sim/m32c/gdb-if.c
Normal 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
34
sim/m32c/gloss.S
Normal 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
61
sim/m32c/int.c
Normal 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
25
sim/m32c/int.h
Normal 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
131
sim/m32c/load.c
Normal 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
29
sim/m32c/load.h
Normal 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
2104
sim/m32c/m32c.opc
Normal file
File diff suppressed because it is too large
Load Diff
138
sim/m32c/main.c
Normal file
138
sim/m32c/main.c
Normal 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
377
sim/m32c/mem.c
Normal 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
43
sim/m32c/mem.h
Normal 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
79
sim/m32c/misc.c
Normal 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
27
sim/m32c/misc.h
Normal 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
730
sim/m32c/opc2c.c
Normal 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
1580
sim/m32c/r8c.opc
Normal file
File diff suppressed because it is too large
Load Diff
624
sim/m32c/reg.c
Normal file
624
sim/m32c/reg.c
Normal 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 (®s, 0, sizeof (regs));
|
||||
memset (&oldregs, 0, sizeof (oldregs));
|
||||
}
|
||||
|
||||
void
|
||||
set_pointer_width (int bytes)
|
||||
{
|
||||
if (bytes == 2)
|
||||
{
|
||||
addr_mask = 0xffff;
|
||||
membus_mask = 0x000fffff;
|
||||
reg_bytes[a0] = reg_bytes[a1] = reg_bytes[sb] = reg_bytes[fb] =
|
||||
reg_bytes[sp] = reg_bytes[usp] = reg_bytes[isp] = 2;
|
||||
}
|
||||
else
|
||||
{
|
||||
addr_mask = 0xffffff;
|
||||
membus_mask = 0x00ffffff;
|
||||
reg_bytes[a0] = reg_bytes[a1] = reg_bytes[sb] = reg_bytes[fb] =
|
||||
reg_bytes[sp] = reg_bytes[usp] = reg_bytes[isp] = 3;
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
m32c_set_cpu (int cpu)
|
||||
{
|
||||
switch (cpu)
|
||||
{
|
||||
case CPU_R8C:
|
||||
case CPU_M16C:
|
||||
set_pointer_width (2);
|
||||
decode_opcode = decode_r8c;
|
||||
break;
|
||||
case CPU_M32CM:
|
||||
case CPU_M32C:
|
||||
set_pointer_width (3);
|
||||
decode_opcode = decode_m32c;
|
||||
break;
|
||||
default:
|
||||
abort ();
|
||||
}
|
||||
m32c_cpu = cpu;
|
||||
}
|
||||
|
||||
static unsigned int
|
||||
get_reg_i (reg_id id)
|
||||
{
|
||||
reg_bank_type *b = regs.r + (FLAG_B ? 1 : 0);
|
||||
|
||||
switch (id)
|
||||
{
|
||||
case r0:
|
||||
return b->r_r0;
|
||||
case r0h:
|
||||
return b->r_r0 >> 8;
|
||||
case r0l:
|
||||
return b->r_r0 & 0xff;
|
||||
case r1:
|
||||
return b->r_r1;
|
||||
case r1h:
|
||||
return b->r_r1 >> 8;
|
||||
case r1l:
|
||||
return b->r_r1 & 0xff;
|
||||
case r2:
|
||||
return b->r_r2;
|
||||
case r2r0:
|
||||
return b->r_r2 * 65536 + b->r_r0;
|
||||
case r3:
|
||||
return b->r_r3;
|
||||
case r3r1:
|
||||
return b->r_r3 * 65536 + b->r_r1;
|
||||
|
||||
case a0:
|
||||
return b->r_a0 & addr_mask;
|
||||
case a1:
|
||||
return b->r_a1 & addr_mask;
|
||||
case a1a0:
|
||||
return (b->r_a1 & 0xffff) * 65536 | (b->r_a0 & 0xffff);
|
||||
|
||||
case sb:
|
||||
return b->r_sb & addr_mask;
|
||||
case fb:
|
||||
return b->r_fb & addr_mask;
|
||||
|
||||
case intb:
|
||||
return regs.r_intbh * 65536 + regs.r_intbl;
|
||||
case intbl:
|
||||
return regs.r_intbl;
|
||||
case intbh:
|
||||
return regs.r_intbh;
|
||||
|
||||
case sp:
|
||||
return ((regs.r_flags & FLAGBIT_U) ? regs.r_usp : regs.
|
||||
r_isp) & addr_mask;
|
||||
case usp:
|
||||
return regs.r_usp & addr_mask;
|
||||
case isp:
|
||||
return regs.r_isp & addr_mask;
|
||||
|
||||
case pc:
|
||||
return regs.r_pc & membus_mask;
|
||||
case flags:
|
||||
return regs.r_flags;
|
||||
default:
|
||||
abort ();
|
||||
}
|
||||
}
|
||||
|
||||
unsigned int
|
||||
get_reg (reg_id id)
|
||||
{
|
||||
unsigned int rv = get_reg_i (id);
|
||||
if (trace > ((id != pc && id != fb && id != sp) ? 0 : 1))
|
||||
printf ("get_reg (%s) = %0*x\n", reg_names[id], reg_bytes[id] * 2, rv);
|
||||
return rv;
|
||||
}
|
||||
|
||||
DI
|
||||
get_reg_ll (reg_id id)
|
||||
{
|
||||
reg_bank_type *b = regs.r + (FLAG_B ? 1 : 0);
|
||||
|
||||
switch (id)
|
||||
{
|
||||
case r3r1r2r0:
|
||||
return ((DI) b->r_r3 << 48
|
||||
| (DI) b->r_r1 << 32 | (DI) b->r_r2 << 16 | (DI) b->r_r0);
|
||||
case r3r2r1r0:
|
||||
return ((DI) b->r_r3 << 48
|
||||
| (DI) b->r_r2 << 32 | (DI) b->r_r1 << 16 | (DI) b->r_r0);
|
||||
default:
|
||||
return get_reg (id);
|
||||
}
|
||||
}
|
||||
|
||||
static int highest_sp = 0, lowest_sp = 0xffffff;
|
||||
|
||||
void
|
||||
stack_heap_stats ()
|
||||
{
|
||||
printf ("heap: %08x - %08x (%d bytes)\n", heapbottom, heaptop,
|
||||
heaptop - heapbottom);
|
||||
printf ("stack: %08x - %08x (%d bytes)\n", lowest_sp, highest_sp,
|
||||
highest_sp - lowest_sp);
|
||||
}
|
||||
|
||||
void
|
||||
put_reg (reg_id id, unsigned int v)
|
||||
{
|
||||
if (trace > ((id != pc) ? 0 : 1))
|
||||
printf ("put_reg (%s) = %0*x\n", reg_names[id], reg_bytes[id] * 2, v);
|
||||
|
||||
reg_bank_type *b = regs.r + (FLAG_B ? 1 : 0);
|
||||
switch (id)
|
||||
{
|
||||
case r0:
|
||||
b->r_r0 = v;
|
||||
break;
|
||||
case r0h:
|
||||
b->r_r0 = (b->r_r0 & 0xff) | (v << 8);
|
||||
break;
|
||||
case r0l:
|
||||
b->r_r0 = (b->r_r0 & 0xff00) | (v & 0xff);
|
||||
break;
|
||||
case r1:
|
||||
b->r_r1 = v;
|
||||
break;
|
||||
case r1h:
|
||||
b->r_r1 = (b->r_r1 & 0xff) | (v << 8);
|
||||
break;
|
||||
case r1l:
|
||||
b->r_r1 = (b->r_r1 & 0xff00) | (v & 0xff);
|
||||
break;
|
||||
case r2:
|
||||
b->r_r2 = v;
|
||||
break;
|
||||
case r2r0:
|
||||
b->r_r0 = v & 0xffff;
|
||||
b->r_r2 = v >> 16;
|
||||
break;
|
||||
case r3:
|
||||
b->r_r3 = v;
|
||||
break;
|
||||
case r3r1:
|
||||
b->r_r1 = v & 0xffff;
|
||||
b->r_r3 = v >> 16;
|
||||
break;
|
||||
|
||||
case a0:
|
||||
b->r_a0 = v & addr_mask;
|
||||
break;
|
||||
case a1:
|
||||
b->r_a1 = v & addr_mask;
|
||||
break;
|
||||
case a1a0:
|
||||
b->r_a0 = v & 0xffff;
|
||||
b->r_a1 = v >> 16;
|
||||
break;
|
||||
|
||||
case sb:
|
||||
b->r_sb = v & addr_mask;
|
||||
break;
|
||||
case fb:
|
||||
b->r_fb = v & addr_mask;
|
||||
break;
|
||||
|
||||
case intb:
|
||||
regs.r_intbl = v & 0xffff;
|
||||
regs.r_intbh = v >> 16;
|
||||
break;
|
||||
case intbl:
|
||||
regs.r_intbl = v & 0xffff;
|
||||
break;
|
||||
case intbh:
|
||||
regs.r_intbh = v & 0xff;
|
||||
break;
|
||||
|
||||
case sp:
|
||||
{
|
||||
SI *spp;
|
||||
if (regs.r_flags & FLAGBIT_U)
|
||||
spp = ®s.r_usp;
|
||||
else
|
||||
spp = ®s.r_isp;
|
||||
*spp = v & addr_mask;
|
||||
if (*spp < heaptop)
|
||||
{
|
||||
printf ("collision: pc %08lx heap %08x stack %08lx\n", regs.r_pc,
|
||||
heaptop, *spp);
|
||||
exit (1);
|
||||
}
|
||||
if (*spp < lowest_sp)
|
||||
lowest_sp = *spp;
|
||||
if (*spp > highest_sp)
|
||||
highest_sp = *spp;
|
||||
break;
|
||||
}
|
||||
case usp:
|
||||
regs.r_usp = v & addr_mask;
|
||||
break;
|
||||
case isp:
|
||||
regs.r_isp = v & addr_mask;
|
||||
break;
|
||||
|
||||
case pc:
|
||||
regs.r_pc = v & membus_mask;
|
||||
break;
|
||||
case flags:
|
||||
regs.r_flags = v;
|
||||
break;
|
||||
default:
|
||||
abort ();
|
||||
}
|
||||
}
|
||||
|
||||
int
|
||||
condition_true (int cond_id)
|
||||
{
|
||||
int f;
|
||||
if (A16)
|
||||
{
|
||||
static const char *cond_name[] = {
|
||||
"C", "C&!Z", "Z", "S",
|
||||
"!C", "!(C&!Z)", "!Z", "!S",
|
||||
"(S^O)|Z", "O", "!(S^O)", "unk",
|
||||
"!((S^O)|Z)", "!O", "S^O", "unk"
|
||||
};
|
||||
switch (cond_id)
|
||||
{
|
||||
case 0:
|
||||
f = FLAG_C;
|
||||
break; /* GEU/C */
|
||||
case 1:
|
||||
f = FLAG_C & !FLAG_Z;
|
||||
break; /* GTU */
|
||||
case 2:
|
||||
f = FLAG_Z;
|
||||
break; /* EQ/Z */
|
||||
case 3:
|
||||
f = FLAG_S;
|
||||
break; /* N */
|
||||
case 4:
|
||||
f = !FLAG_C;
|
||||
break; /* LTU/NC */
|
||||
case 5:
|
||||
f = !(FLAG_C & !FLAG_Z);
|
||||
break; /* LEU */
|
||||
case 6:
|
||||
f = !FLAG_Z;
|
||||
break; /* NE/NZ */
|
||||
case 7:
|
||||
f = !FLAG_S;
|
||||
break; /* PZ */
|
||||
|
||||
case 8:
|
||||
f = (FLAG_S ^ FLAG_O) | FLAG_Z;
|
||||
break; /* LE */
|
||||
case 9:
|
||||
f = FLAG_O;
|
||||
break; /* O */
|
||||
case 10:
|
||||
f = !(FLAG_S ^ FLAG_O);
|
||||
break; /* GE */
|
||||
case 12:
|
||||
f = !((FLAG_S ^ FLAG_O) | FLAG_Z);
|
||||
break; /* GT */
|
||||
case 13:
|
||||
f = !FLAG_O;
|
||||
break; /* NO */
|
||||
case 14:
|
||||
f = FLAG_S ^ FLAG_O;
|
||||
break; /* LT */
|
||||
|
||||
default:
|
||||
f = 0;
|
||||
break;
|
||||
}
|
||||
if (trace)
|
||||
printf ("cond[%d] %s = %s\n", cond_id, cond_name[cond_id & 15],
|
||||
f ? "true" : "false");
|
||||
}
|
||||
else
|
||||
{
|
||||
static const char *cond_name[] = {
|
||||
"!C", "LEU", "!Z", "PZ",
|
||||
"!O", "GT", "GE", "?",
|
||||
"C", "GTU", "Z", "N",
|
||||
"O", "LE", "LT", "!?"
|
||||
};
|
||||
switch (cond_id)
|
||||
{
|
||||
case 0:
|
||||
f = !FLAG_C;
|
||||
break; /* LTU/NC */
|
||||
case 1:
|
||||
f = !(FLAG_C & !FLAG_Z);
|
||||
break; /* LEU */
|
||||
case 2:
|
||||
f = !FLAG_Z;
|
||||
break; /* NE/NZ */
|
||||
case 3:
|
||||
f = !FLAG_S;
|
||||
break; /* PZ */
|
||||
|
||||
case 4:
|
||||
f = !FLAG_O;
|
||||
break; /* NO */
|
||||
case 5:
|
||||
f = !((FLAG_S ^ FLAG_O) | FLAG_Z);
|
||||
break; /* GT */
|
||||
case 6:
|
||||
f = !(FLAG_S ^ FLAG_O);
|
||||
break; /* GE */
|
||||
|
||||
case 8:
|
||||
f = FLAG_C;
|
||||
break; /* GEU/C */
|
||||
case 9:
|
||||
f = FLAG_C & !FLAG_Z;
|
||||
break; /* GTU */
|
||||
case 10:
|
||||
f = FLAG_Z;
|
||||
break; /* EQ/Z */
|
||||
case 11:
|
||||
f = FLAG_S;
|
||||
break; /* N */
|
||||
|
||||
case 12:
|
||||
f = FLAG_O;
|
||||
break; /* O */
|
||||
case 13:
|
||||
f = (FLAG_S ^ FLAG_O) | FLAG_Z;
|
||||
break; /* LE */
|
||||
case 14:
|
||||
f = FLAG_S ^ FLAG_O;
|
||||
break; /* LT */
|
||||
|
||||
default:
|
||||
f = 0;
|
||||
break;
|
||||
}
|
||||
if (trace)
|
||||
printf ("cond[%d] %s = %s\n", cond_id, cond_name[cond_id & 15],
|
||||
f ? "true" : "false");
|
||||
}
|
||||
return f;
|
||||
}
|
||||
|
||||
void
|
||||
set_flags (int mask, int newbits)
|
||||
{
|
||||
int i;
|
||||
regs.r_flags &= ~mask;
|
||||
regs.r_flags |= newbits & mask;
|
||||
if (trace)
|
||||
{
|
||||
printf ("flags now \033[32m %d", (regs.r_flags >> (A16 ? 8 : 12)) & 7);
|
||||
for (i = 7; i >= 0; i--)
|
||||
if (regs.r_flags & (1 << i))
|
||||
putchar ("CDZSBOIU"[i]);
|
||||
else
|
||||
putchar ('-');
|
||||
printf ("\033[0m\n");
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
set_oszc (int value, int b, int c)
|
||||
{
|
||||
int mask = b2mask[b];
|
||||
int f = 0;
|
||||
|
||||
if (c)
|
||||
f |= FLAGBIT_C;
|
||||
if ((value & mask) == 0)
|
||||
f |= FLAGBIT_Z;
|
||||
if (value & b2signbit[b])
|
||||
f |= FLAGBIT_S;
|
||||
if ((value > b2maxsigned[b]) || (value < b2minsigned[b]))
|
||||
f |= FLAGBIT_O;
|
||||
set_flags (FLAGBIT_Z | FLAGBIT_S | FLAGBIT_O | FLAGBIT_C, f);
|
||||
}
|
||||
|
||||
void
|
||||
set_szc (int value, int b, int c)
|
||||
{
|
||||
int mask = b2mask[b];
|
||||
int f = 0;
|
||||
|
||||
if (c)
|
||||
f |= FLAGBIT_C;
|
||||
if ((value & mask) == 0)
|
||||
f |= FLAGBIT_Z;
|
||||
if (value & b2signbit[b])
|
||||
f |= FLAGBIT_S;
|
||||
set_flags (FLAGBIT_Z | FLAGBIT_S | FLAGBIT_C, f);
|
||||
}
|
||||
|
||||
void
|
||||
set_osz (int value, int b)
|
||||
{
|
||||
int mask = b2mask[b];
|
||||
int f = 0;
|
||||
|
||||
if ((value & mask) == 0)
|
||||
f |= FLAGBIT_Z;
|
||||
if (value & b2signbit[b])
|
||||
f |= FLAGBIT_S;
|
||||
if (value & ~mask && (value & ~mask) != ~mask)
|
||||
f |= FLAGBIT_O;
|
||||
set_flags (FLAGBIT_Z | FLAGBIT_S | FLAGBIT_O, f);
|
||||
}
|
||||
|
||||
void
|
||||
set_sz (int value, int b)
|
||||
{
|
||||
int mask = b2mask[b];
|
||||
int f = 0;
|
||||
|
||||
if ((value & mask) == 0)
|
||||
f |= FLAGBIT_Z;
|
||||
if (value & b2signbit[b])
|
||||
f |= FLAGBIT_S;
|
||||
set_flags (FLAGBIT_Z | FLAGBIT_S, f);
|
||||
}
|
||||
|
||||
void
|
||||
set_zc (int z, int c)
|
||||
{
|
||||
set_flags (FLAGBIT_C | FLAGBIT_Z,
|
||||
(c ? FLAGBIT_C : 0) | (z ? FLAGBIT_Z : 0));
|
||||
}
|
||||
|
||||
void
|
||||
set_c (int c)
|
||||
{
|
||||
set_flags (FLAGBIT_C, c ? FLAGBIT_C : 0);
|
||||
}
|
||||
|
||||
void
|
||||
put_reg_ll (reg_id id, DI v)
|
||||
{
|
||||
reg_bank_type *b = regs.r + (FLAG_B ? 1 : 0);
|
||||
|
||||
switch (id)
|
||||
{
|
||||
case r3r1r2r0:
|
||||
b->r_r3 = v >> 48;
|
||||
b->r_r1 = v >> 32;
|
||||
b->r_r2 = v >> 16;
|
||||
b->r_r0 = v;
|
||||
break;
|
||||
case r3r2r1r0:
|
||||
b->r_r3 = v >> 48;
|
||||
b->r_r2 = v >> 32;
|
||||
b->r_r1 = v >> 16;
|
||||
b->r_r0 = v;
|
||||
break;
|
||||
default:
|
||||
put_reg (id, v);
|
||||
}
|
||||
}
|
||||
|
||||
#define TRC(f,n, id) \
|
||||
if (oldregs.f != regs.f) \
|
||||
{ \
|
||||
printf(" %s %0*x:%0*x", n, \
|
||||
reg_bytes[id]*2, (unsigned int)oldregs.f, \
|
||||
reg_bytes[id]*2, (unsigned int)regs.f); \
|
||||
oldregs.f = regs.f; \
|
||||
}
|
||||
|
||||
void
|
||||
trace_register_changes ()
|
||||
{
|
||||
if (!trace)
|
||||
return;
|
||||
printf ("\033[36mREGS:");
|
||||
TRC (r[0].r_r0, "r0", r0);
|
||||
TRC (r[0].r_r1, "r1", r1);
|
||||
TRC (r[0].r_r2, "r2", r2);
|
||||
TRC (r[0].r_r3, "r3", r3);
|
||||
TRC (r[0].r_a0, "a0", a0);
|
||||
TRC (r[0].r_a1, "a1", a1);
|
||||
TRC (r[0].r_sb, "sb", sb);
|
||||
TRC (r[0].r_fb, "fb", fb);
|
||||
TRC (r[1].r_r0, "r0'", r0);
|
||||
TRC (r[1].r_r1, "r1'", r1);
|
||||
TRC (r[1].r_r2, "r2'", r2);
|
||||
TRC (r[1].r_r3, "r3'", r3);
|
||||
TRC (r[1].r_a0, "a0'", a0);
|
||||
TRC (r[1].r_a1, "a1'", a1);
|
||||
TRC (r[1].r_sb, "sb'", sb);
|
||||
TRC (r[1].r_fb, "fb'", fb);
|
||||
TRC (r_intbh, "intbh", intbh);
|
||||
TRC (r_intbl, "intbl", intbl);
|
||||
TRC (r_usp, "usp", usp);
|
||||
TRC (r_isp, "isp", isp);
|
||||
TRC (r_pc, "pc", pc);
|
||||
TRC (r_flags, "flags", flags);
|
||||
printf ("\033[0m\n");
|
||||
}
|
71
sim/m32c/safe-fgets.c
Normal file
71
sim/m32c/safe-fgets.c
Normal 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
29
sim/m32c/safe-fgets.h
Normal 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
31
sim/m32c/sample.S
Normal 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
43
sim/m32c/sample.ld
Normal 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
30
sim/m32c/sample2.c
Normal 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
780
sim/m32c/srcdest.c
Normal 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
336
sim/m32c/syscalls.c
Normal 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
26
sim/m32c/syscalls.h
Normal 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
315
sim/m32c/trace.c
Normal 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
25
sim/m32c/trace.h
Normal 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);
|
Loading…
x
Reference in New Issue
Block a user