From 3971886ac1616c4125531e42a884f031e27f7e21 Mon Sep 17 00:00:00 2001 From: Andrew Cagney Date: Mon, 5 May 1997 12:46:25 +0000 Subject: [PATCH] Add flakey floating-point support to the TI c80 simulator. --- sim/common/ChangeLog | 10 + sim/common/Make-common.in | 11 +- sim/common/sim-fpu.c | 169 ++++++++++++++ sim/common/sim-fpu.h | 68 ++++++ sim/common/sim-inline.c | 78 +++++++ sim/common/sim-inline.h | 562 ++++++++++++++++++++++++++++++++++++++++++++++ sim/common/sim-trace.c | 235 ++++++++++++++++++- sim/common/sim-trace.h | 73 +++++- sim/testsuite/.Sanitize | 1 + sim/tic80/ChangeLog | 13 ++ sim/tic80/Makefile.in | 7 +- sim/tic80/alu.h | 34 ++- sim/tic80/cpu.h | 5 + sim/tic80/insns | 316 +++++++++++++++++++++----- 14 files changed, 1520 insertions(+), 62 deletions(-) create mode 100644 sim/common/sim-fpu.c create mode 100644 sim/common/sim-fpu.h create mode 100644 sim/common/sim-inline.c create mode 100644 sim/common/sim-inline.h diff --git a/sim/common/ChangeLog b/sim/common/ChangeLog index 6ffc2b2..482c498 100644 --- a/sim/common/ChangeLog +++ b/sim/common/ChangeLog @@ -1,3 +1,13 @@ +Mon May 5 13:19:16 1997 Andrew Cagney + + * sim-trace.h (TRACE_FPU_IDX): Add Floating-point specific + tracing. + + * sim-fpu.h, sim-fpu.c: New files - prototype for generic target + fpu support. + + * sim-inline.h, sim-inline.c: Add support for SIM_FPU. + Fri May 2 17:59:42 1997 Andrew Cagney * sim-core.c (sim_core_map_to_str): New function ascii equivalent diff --git a/sim/common/Make-common.in b/sim/common/Make-common.in index 1654b8e..c2b2fff 100644 --- a/sim/common/Make-common.in +++ b/sim/common/Make-common.in @@ -191,6 +191,7 @@ sim-n-bits_h = $(srcdir)/../common/sim-n-bits.h sim-core_h = $(srcdir)/../common/sim-core.h sim-n-core_h = $(srcdir)/../common/sim-n-core.h sim-events_h = $(srcdir)/../common/sim-events.h +sim-fpu_h = $(srcdir)/../common/sim-fpu.h sim-io_h = $(srcdir)/../common/sim-io.h sim-options_h = $(srcdir)/../common/sim-options.h @@ -246,6 +247,14 @@ sim-events.c: $(srcdir)/../common/sim-events.c cat $(srcdir)/../common/$@ >> tmp-$@ $(srcdir)/../../move-if-change tmp-$@ $@ +sim-fpu.o: sim-fpu.c $(sim-fpu_h) $(sim-assert_h) \ + $(SIM_EXTRA_DEPS) +sim-fpu.c: $(srcdir)/../common/sim-fpu.c + rm -f $@ tmp-$@ + echo "# 1 \"$(srcdir)/../common/$@\"" > tmp-$@ + cat $(srcdir)/../common/$@ >> tmp-$@ + $(srcdir)/../../move-if-change tmp-$@ $@ + sim-inline.c: $(srcdir)/../common/sim-inline.c rm -f $@ tmp-$@ echo "# 1 \"$(srcdir)/../common/$@\"" > tmp-$@ @@ -302,7 +311,7 @@ cgen-trace.o: $(srcdir)/../common/cgen-trace.c $(sim_main_headers) \ $(CC) -c $(srcdir)/../common/cgen-trace.c $(ALL_CFLAGS) cgen-utils.o: $(srcdir)/../common/cgen-utils.c $(sim_main_headers) \ - $(SIM_EXTRA_DEPS) cgen-mem.h cgen-sem.h + $(SIM_EXTRA_DEPS) mem-ops.h sem-ops.h $(CC) -c $(srcdir)/../common/cgen-utils.c $(ALL_CFLAGS) # Support targets. diff --git a/sim/common/sim-fpu.c b/sim/common/sim-fpu.c new file mode 100644 index 0000000..b02530c --- /dev/null +++ b/sim/common/sim-fpu.c @@ -0,0 +1,169 @@ +/* Simulator Floating-point support. + Copyright (C) 1997 Free Software Foundation, Inc. + Contributed by Cygnus Support. + +This file is part of GDB, the GNU debugger. + +This program is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +This program is distributed in the hope that it 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 this program; if not, write to the Free Software Foundation, Inc., +59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ + + + +#ifndef _SIM_FPU_C_ +#define _SIM_FPU_C_ + +#include "sim-main.h" +#include "sim-fpu.h" + +#include + + +INLINE_SIM_FPU (sim_fpu) +sim_fpu_add (sim_fpu l, + sim_fpu r) +{ + sim_fpu ans; + ans.val = l.val + r.val; + return ans; +} + + +INLINE_SIM_FPU (sim_fpu) +sim_fpu_sub (sim_fpu l, + sim_fpu r) +{ + sim_fpu ans; + ans.val = l.val - r.val; + return ans; +} + + +INLINE_SIM_FPU (sim_fpu) +sim_fpu_mul (sim_fpu l, + sim_fpu r) +{ + sim_fpu ans; + ans.val = l.val * r.val; + return ans; +} + + +INLINE_SIM_FPU (sim_fpu) +sim_fpu_div (sim_fpu l, + sim_fpu r) +{ + sim_fpu ans; + ans.val = l.val / r.val; + return ans; +} + + +INLINE_SIM_FPU (sim_fpu) +sim_fpu_inv (sim_fpu r) +{ + sim_fpu ans; + ans.val = 1 / r.val; + return ans; +} + + +INLINE_SIM_FPU (sim_fpu) +sim_fpu_sqrt (sim_fpu r) +{ + sim_fpu ans; + ans.val = sqrt (r.val); + return ans; +} + + +INLINE_SIM_FPU (sim_fpu) +sim_fpu_32to (unsigned32 s) +{ + sim_fpu ans; + ans.val = *(float*) &s; + return ans; +} + + +INLINE_SIM_FPU (sim_fpu) +sim_fpu_64to (unsigned64 s) +{ + sim_fpu ans; + ans.val = *(double*) &s; + return ans; +} + + +INLINE_SIM_FPU (unsigned32) +sim_fpu_to32 (sim_fpu l) +{ + float s = l.val; + return *(unsigned32*) &s; +} + + +INLINE_SIM_FPU (unsigned64) +sim_fpu_to64 (sim_fpu s) +{ + return *(unsigned64*) &s.val; +} + + +INLINE_SIM_FPU (float) +sim_fpu_2f (sim_fpu f) +{ + return f.val; +} + + +INLINE_SIM_FPU (double) +sim_fpu_2d (sim_fpu s) +{ + return s.val; +} + + +INLINE_SIM_FPU (sim_fpu) +sim_fpu_f2 (float f) +{ + sim_fpu ans; + ans.val = f; + return ans; +} + + +INLINE_SIM_FPU (sim_fpu) +sim_fpu_d2 (double d) +{ + sim_fpu ans; + ans.val = d; + return ans; +} + + +INLINE_SIM_FPU (int) +sim_fpu_is_nan (sim_fpu d) +{ + return 0; /* FIXME - detect NaN */ +} + + +INLINE_SIM_FPU (int) +sim_fpu_cmp (sim_fpu l, + sim_fpu r) +{ + return l.val - r.val; +} + +#endif diff --git a/sim/common/sim-fpu.h b/sim/common/sim-fpu.h new file mode 100644 index 0000000..a40b4c9 --- /dev/null +++ b/sim/common/sim-fpu.h @@ -0,0 +1,68 @@ +/* Simulator Floating-point support. + Copyright (C) 1997 Free Software Foundation, Inc. + Contributed by Cygnus Support. + +This file is part of GDB, the GNU debugger. + +This program is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +This program is distributed in the hope that it 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 this program; if not, write to the Free Software Foundation, Inc., +59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ + + + +#ifndef _SIM_FPU_H_ +#define _SIM_FPU_H_ + +/* the FPU intermediate type */ + +typedef struct _sim_fpu { + double val; +} sim_fpu; + + +/* Arrithmetic operators */ + +INLINE_SIM_FPU (sim_fpu) sim_fpu_add (sim_fpu l, sim_fpu r); +INLINE_SIM_FPU (sim_fpu) sim_fpu_sub (sim_fpu l, sim_fpu r); +INLINE_SIM_FPU (sim_fpu) sim_fpu_mul (sim_fpu l, sim_fpu r); +INLINE_SIM_FPU (sim_fpu) sim_fpu_div (sim_fpu l, sim_fpu r); +INLINE_SIM_FPU (sim_fpu) sim_fpu_inv (sim_fpu l); +INLINE_SIM_FPU (sim_fpu) sim_fpu_sqrt (sim_fpu sqr); + + +/* Conversions single/double to/from fpu type */ + +INLINE_SIM_FPU (sim_fpu) sim_fpu_32to (unsigned32 s); +INLINE_SIM_FPU (sim_fpu) sim_fpu_64to (unsigned64 s); + +INLINE_SIM_FPU (unsigned32) sim_fpu_to32 (sim_fpu s); +INLINE_SIM_FPU (unsigned64) sim_fpu_to64 (sim_fpu s); + +INLINE_SIM_FPU (float) sim_fpu_2f (sim_fpu f); +INLINE_SIM_FPU (double) sim_fpu_2d (sim_fpu d); + +INLINE_SIM_FPU (sim_fpu) sim_fpu_f2 (float f); +INLINE_SIM_FPU (sim_fpu) sim_fpu_d2 (double d); + + +/* Signalling or NonSignalling NaN */ + +INLINE_SIM_FPU (int) sim_fpu_is_nan (sim_fpu s); + + +/* compare l with r; return <0, ==0, >0 accordingly */ + +INLINE_SIM_FPU (int) sim_fpu_cmp (sim_fpu l, sim_fpu r); + + +#endif diff --git a/sim/common/sim-inline.c b/sim/common/sim-inline.c new file mode 100644 index 0000000..dffa103 --- /dev/null +++ b/sim/common/sim-inline.c @@ -0,0 +1,78 @@ +/* This file is part of the program psim. + + Copyright (C) 1994-1997, Andrew Cagney + Copyright (C) 1997, Free Software Foundation, Inc. + + This program is free software; you can redistribute it and/or modify + it 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. + + This program is distributed in the hope that it 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 this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + + */ + + +#ifndef _SIM_INLINE_C_ +#define _SIM_INLINE_C_ + +#include "sim-inline.h" + + +#if defined(SIM_BITS_INLINE) +#if ((SIM_BITS_INLINE & INCLUDE_MODULE) \ + && !(SIM_BITS_INLINE & INCLUDED_BY_MODULE)) +#include "sim-bits.c" +#endif +#endif + + +#if defined(SIM_CORE_INLINE) +#if ((SIM_CORE_INLINE & INCLUDE_MODULE) \ + && !(SIM_CORE_INLINE & INCLUDED_BY_MODULE)) +#include "sim-core.c" +#endif +#endif + + +#if defined(SIM_ENDIAN_INLINE) +#if ((SIM_ENDIAN_INLINE & INCLUDE_MODULE) \ + && !(SIM_ENDIAN_INLINE & INCLUDED_BY_MODULE)) +#include "sim-endian.c" +#endif +#endif + + +#if defined(SIM_EVENTS_INLINE) +#if ((SIM_EVENTS_INLINE & INCLUDE_MODULE) \ + && !(SIM_EVENTS_INLINE & INCLUDED_BY_MODULE)) +#include "sim-events.c" +#endif +#endif + + +#if defined(SIM_FPU_INLINE) +#if ((SIM_FPU_INLINE & INCLUDE_MODULE) \ + && !(SIM_FPU_INLINE & INCLUDED_BY_MODULE)) +#include "sim-fpu.c" +#endif +#endif + + +#if defined(SIM_IO_INLINE) +#if ((SIM_IO_INLINE & INCLUDE_MODULE) \ + && !(SIM_IO_INLINE & INCLUDED_BY_MODULE)) +#include "sim-io.c" +#endif +#endif + + + +#endif diff --git a/sim/common/sim-inline.h b/sim/common/sim-inline.h new file mode 100644 index 0000000..7e4ec7a --- /dev/null +++ b/sim/common/sim-inline.h @@ -0,0 +1,562 @@ +/* This file is part of the program psim. + + Copyright (C) 1994-1997, Andrew Cagney + Copyright (C) 1997, Free Software Foundation, Inc. + + This program is free software; you can redistribute it and/or modify + it 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. + + This program is distributed in the hope that it 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 this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + + */ + + +#ifndef _SIM_INLINE_H_ +#define _SIM_INLINE_H_ + + +/* INLINE CODE SELECTION: + + GCC -O3 attempts to inline any function or procedure in scope. The + options below facilitate fine grained control over what is and what + isn't made inline. For instance it can control things down to a + specific modules static routines. Doing this allows the compiler + to both eliminate the overhead of function calls and (as a + consequence) also eliminate further dead code. + + On a CISC (x86) I've found that I can achieve an order of magintude + speed improvement (x3-x5). In the case of RISC (sparc) while the + performance gain isn't as great it is still significant. + + Each module is controled by the macro _INLINE which can + have the values described below + + 0 Do not inline any thing for the given module + + The following additional values are `bit fields' and can be + combined. + + REVEAL_MODULE: + + Include the C file for the module into the file being compiled + but do not make the functions within the module inline. + + While of no apparent benefit, this makes it possible for the + included module, when compiled to inline its calls to what + would otherwize be external functions. + + INLINE_MODULE: + + Make external functions within the module `inline'. Thus if + the module is included into a file being compiled, calls to + its funtions can be eliminated. 2 implies 1. + + INLINE_LOCALS: + + Make internal (static) functions within the module `inline'. + + In addition to this, modules have been put into two categories. + + INCLUDED_BY_MODULE + + eg sim-endian.h sim-bits.h + + Because these modules are small and simple and do not have + any complex interdendencies they are configured, if + _INLINE is so enabled, to inline themselves in all + modules that include those files. + + For the default build, this is a real win as all byte + conversion and bit manipulation functions are inlined. + + !INCLUDED_BY_MODULE + + Complex modules - the rest + + These are all handled using the files sim-inline.h and + sim-inline.c. The main simulator engine includes both of + these and hence includes all remaining code. + + The following abreviations are available: + + INCLUDE_MODULE == (REVEAL_MODULE | INLINE_MODULE) + + ALL_INLINE == (REVEAL_MODULE | INLINE_MODULE | INLINE_LOCALS) + + ALL_BY_MODULE = (INCLUDED_BY_MODULE | ALL_INLINE) + + IMPLEMENTATION: + + The inline ability is enabled by prefixing every data / function + declaration and definition with one of the following: + + + INLINE_ + + Prefix to any global function that is a candidate for being + inline. + + values - `', `static', `static INLINE' + + + EXTERN_ + + Prefix to any global data structures for the module. Global + functions that are not to be inlined shall also be prefixed + with this. + + values - `', `static', `static' + + + STATIC_INLINE_ + + Prefix to any local (static) function that is a candidate for + being made inline. + + values - `static', `static INLINE' + + + static + + Prefix all local data structures. Local functions that are not + to be inlined shall also be prefixed with this. + + values - `static', `static' + + nb: will not work for modules that are being inlined for every + use (white lie). + + + extern + #ifndef _SIM_INLINE_C_ + #endif + + Prefix to any declaration of a global object (function or + variable) that should not be inlined and should have only one + definition. The #ifndef wrapper goes around the definition + propper to ensure that only one copy is generated. + + nb: this will not work when a module is being inlined for every + use. + + + STATIC_ + + Replaced by either `static' or `EXTERN_MODULE'. + + + REALITY CHECK: + + This is not for the faint hearted. I've seen GCC get up to 500mb + trying to compile what this can create. + + Some of the modules do not yet implement the WITH_INLINE_STATIC + option. Instead they use the macro STATIC_INLINE to control their + local function. + + Because of the way that GCC parses __attribute__(), the macro's + need to be adjacent to the functioin name rather then at the start + of the line vis: + + int STATIC_INLINE_MODULE f(void); + void INLINE_MODULE *g(void); + + */ + + +#define REVEAL_MODULE 1 +#define INLINE_MODULE 2 +#define INCLUDE_MODULE (INLINE_MODULE | REVEAL_MODULE) +#define INLINE_LOCALS 4 +#define ALL_INLINE 7 +#define ALL_BY_MODULE (INCLUDED_BY_MODULE | ALL_INLINE) + +#define INCLUDED_BY_MODULE 16 +#define REGPARM_MODULE 32 + + +/* Default macro to simplify control several of key the inlines */ + +#ifndef DEFAULT_INLINE +#define DEFAULT_INLINE INLINE_LOCALS +#endif + + + +/* Your compilers inline prefix */ + +#ifndef INLINE +#if defined(__GNUC__) && defined(__OPTIMIZE__) +#define INLINE __inline__ +#else +#define INLINE /*inline*/ +#endif +#endif + + + +/* Your compiler's static prefix */ + +#ifndef STATIC_INLINE +#define STATIC_INLINE static INLINE +#endif + + + +/* Your compiler's no-return reserved word */ + +#ifndef NORETURN +#define NORETURN +#endif + + + +/* Your compilers's unused reserved word */ + +#if !defined (UNUSED) +#if (!defined(__GNUC__) \ + || (__GNUC__ < 2) \ + || (__GNUC__ == 2 && __GNUC_MINOR__ < 7)) +#define UNUSED +#else +#define UNUSED __attribute__((__unused__)) +#endif +#endif + + + + +/* Your compilers nonstandard function call mechanism prefix */ + +#if !defined REGPARM +#if defined(__GNUC__) && (defined(__i386__) || defined(__i486__) || defined(__i586__) || defined(__i686__)) +#if (WITH_REGPARM && WITH_STDCALL) +#define REGPARM __attribute__((__regparm__(WITH_REGPARM),__stdcall__)) +#else +#if (WITH_REGPARM && !WITH_STDCALL) +#define REGPARM __attribute__((__regparm__(WITH_REGPARM))) +#else +#if (!WITH_REGPARM && WITH_STDCALL) +#define REGPARM __attribute__((__stdcall__)) +#endif +#endif +#endif +#endif +#endif + +#if !defined REGPARM +#define REGPARM +#endif + + + +/* sim-bits */ + +#if (SIM_BITS_INLINE & REGPARM_MODULE) +# define REGPARM_SIM_BITS REGPARM +#else +# define REGPARM_SIM_BITS +#endif + +#if (((SIM_BITS_INLINE & INCLUDED_BY_MODULE) || defined(_SIM_INLINE_C_)) \ + && !defined(_SIM_BITS_C_) && (SIM_BITS_INLINE & INCLUDE_MODULE)) +# if (SIM_BITS_INLINE & INLINE_MODULE) +# define INLINE_SIM_BITS(TYPE) static INLINE TYPE UNUSED +# define EXTERN_SIM_BITS(TYPE) static TYPE UNUSED REGPARM_SIM_BITS +# else +# define INLINE_SIM_BITS(TYPE) static TYPE UNUSED REGPARM_SIM_BITS +# define EXTERN_SIM_BITS(TYPE) static TYPE UNUSED REGPARM_SIM_BITS +# endif +#else +# define INLINE_SIM_BITS(TYPE) TYPE REGPARM_SIM_BITS +# define EXTERN_SIM_BITS(TYPE) TYPE REGPARM_SIM_BITS +#endif + +#if (SIM_BITS_INLINE & INLINE_LOCALS) +# define STATIC_INLINE_SIM_BITS(TYPE) static INLINE TYPE +#else +# define STATIC_INLINE_SIM_BITS(TYPE) static TYPE REGPARM_SIM_BITS +#endif + + + +/* sim-core */ + +#if (SIM_CORE_INLINE & REGPARM_MODULE) +# define REGPARM_SIM_CORE REGPARM +#else +# define REGPARM_SIM_CORE +#endif + +#if (((SIM_CORE_INLINE & INCLUDED_BY_MODULE) || defined(_SIM_INLINE_C_)) \ + && !defined(_SIM_CORE_C_) && (SIM_CORE_INLINE & INCLUDE_MODULE)) +# if (SIM_CORE_INLINE & INLINE_MODULE) +# define INLINE_SIM_CORE(TYPE) static INLINE TYPE UNUSED +# define EXTERN_SIM_CORE(TYPE) static TYPE UNUSED REGPARM_SIM_CORE +#else +# define INLINE_SIM_CORE(TYPE) static TYPE UNUSED REGPARM_SIM_CORE +# define EXTERN_SIM_CORE(TYPE) static TYPE UNUSED REGPARM_SIM_CORE +#endif +#else +# define INLINE_SIM_CORE(TYPE) TYPE REGPARM_SIM_CORE +# define EXTERN_SIM_CORE(TYPE) TYPE REGPARM_SIM_CORE +#endif + +#if (SIM_CORE_INLINE & INLINE_LOCALS) +# define STATIC_INLINE_SIM_CORE(TYPE) static INLINE TYPE +#else +# define STATIC_INLINE_SIM_CORE(TYPE) static TYPE REGPARM_SIM_CORE +#endif + + + +/* sim-endian */ + +#if (SIM_ENDIAN_INLINE & REGPARM_MODULE) +# define REGPARM_SIM_ENDIAN REGPARM +#else +# define REGPARM_SIM_ENDIAN +#endif + +#if (((SIM_ENDIAN_INLINE & INCLUDED_BY_MODULE) || defined(_SIM_INLINE_C_)) \ + && !defined(_SIM_ENDIAN_C_) && (SIM_ENDIAN_INLINE & INCLUDE_MODULE)) +# if (SIM_ENDIAN_INLINE & INLINE_MODULE) +# define INLINE_SIM_ENDIAN(TYPE) static INLINE TYPE UNUSED +# define EXTERN_SIM_ENDIAN(TYPE) static TYPE UNUSED REGPARM_SIM_ENDIAN +# else +# define INLINE_SIM_ENDIAN(TYPE) static TYPE UNUSED REGPARM_SIM_ENDIAN +# define EXTERN_SIM_ENDIAN(TYPE) static TYPE UNUSED REGPARM_SIM_ENDIAN +# endif +#else +# define INLINE_SIM_ENDIAN(TYPE) TYPE REGPARM_SIM_ENDIAN +# define EXTERN_SIM_ENDIAN(TYPE) TYPE REGPARM_SIM_ENDIAN +#endif + +#if (SIM_ENDIAN_INLINE & INLINE_LOCALS) +# define STATIC_INLINE_SIM_ENDIAN(TYPE) static INLINE TYPE +#else +# define STATIC_INLINE_SIM_ENDIAN(TYPE) static TYPE REGPARM_SIM_ENDIAN +#endif + + + +/* sim-events */ + +#if (SIM_EVENTS_INLINE & REGPARM_MODULE) +# define REGPARM_SIM_EVENTS REGPARM +#else +# define REGPARM_SIM_EVENTS +#endif + +#if (((SIM_EVENTS_INLINE & INCLUDED_BY_MODULE) || defined(_SIM_INLINE_C_)) \ + && !defined(_SIM_EVENTS_C_) && (SIM_EVENTS_INLINE & INCLUDE_MODULE)) +# if (SIM_EVENTS_INLINE & INLINE_MODULE) +# define INLINE_SIM_EVENTS(TYPE) static INLINE TYPE UNUSED +# define EXTERN_SIM_EVENTS(TYPE) static TYPE UNUSED REGPARM_SIM_EVENTS +# else +# define INLINE_SIM_EVENTS(TYPE) static TYPE UNUSED REGPARM_SIM_EVENTS +# define EXTERN_SIM_EVENTS(TYPE) static TYPE UNUSED REGPARM_SIM_EVENTS +# endif +#else +# define INLINE_SIM_EVENTS(TYPE) TYPE REGPARM_SIM_EVENTS +# define EXTERN_SIM_EVENTS(TYPE) TYPE REGPARM_SIM_EVENTS +#endif + +#if (SIM_EVENTS_INLINE & INLINE_LOCALS) +# define STATIC_INLINE_SIM_EVENTS(TYPE) static INLINE TYPE +#else +# define STATIC_INLINE_SIM_EVENTS(TYPE) static TYPE REGPARM_SIM_EVENTS +#endif + + + +/* sim-fpu */ + +#if (SIM_FPU_INLINE & REGPARM_MODULE) +# define REGPARM_SIM_FPU REGPARM +#else +# define REGPARM_SIM_FPU +#endif + +#if (((SIM_FPU_INLINE & INCLUDED_BY_MODULE) || defined(_SIM_INLINE_C_)) \ + && !defined(_SIM_FPU_C_) && (SIM_FPU_INLINE & INCLUDE_MODULE)) +# if (SIM_FPU_INLINE & INLINE_MODULE) +# define INLINE_SIM_FPU(TYPE) static INLINE TYPE UNUSED +# define EXTERN_SIM_FPU(TYPE) static TYPE UNUSED REGPARM_SIM_FPU +# else +# define INLINE_SIM_FPU(TYPE) static TYPE UNUSED REGPARM_SIM_FPU +# define EXTERN_SIM_FPU(TYPE) static TYPE UNUSED REGPARM_SIM_FPU +# endif +#else +# define INLINE_SIM_FPU(TYPE) TYPE REGPARM_SIM_FPU +# define EXTERN_SIM_FPU(TYPE) TYPE REGPARM_SIM_FPU +#endif + +#if (SIM_FPU_INLINE & INLINE_LOCALS) +# define STATIC_INLINE_SIM_FPU(TYPE) static INLINE TYPE +#else +# define STATIC_INLINE_SIM_FPU(TYPE) static TYPE REGPARM_SIM_FPU +#endif + + + +/* sim-types */ + +#if (SIM_TYPES_INLINE & REGPARM_MODULE) +# define REGPARM_SIM_TYPES REGPARM +#else +# define REGPARM_SIM_TYPES +#endif + +#if (((SIM_TYPES_INLINE & INCLUDED_BY_MODULE) || defined(_SIM_INLINE_C_)) \ + && !defined(_SIM_TYPES_C_) && (SIM_TYPES_INLINE & INCLUDE_MODULE)) +# if (SIM_TYPES_INLINE & INLINE_MODULE) +# define INLINE_SIM_TYPES(TYPE) static INLINE TYPE UNUSED +# define EXTERN_SIM_TYPES(TYPE) static TYPE UNUSED REGPARM_SIM_TYPES +# else +# define INLINE_SIM_TYPES(TYPE) static TYPE UNUSED REGPARM_SIM_TYPES +# define EXTERN_SIM_TYPES(TYPE) static TYPE UNUSED REGPARM_SIM_TYPES +# endif +#else +# define INLINE_SIM_TYPES(TYPE) TYPE REGPARM_SIM_TYPES +# define EXTERN_SIM_TYPES(TYPE) TYPE REGPARM_SIM_TYPES +#endif + +#if (SIM_TYPES_INLINE & INLINE_LOCALS) +# define STATIC_INLINE_SIM_TYPES(TYPE) static INLINE TYPE +#else +# define STATIC_INLINE_SIM_TYPES(TYPE) static TYPE REGPARM_SIM_TYPES +#endif + + + +/* icache */ + +#if (ICACHE_INLINE & REGPARM_MODULE) +# define REGPARM_ICACHE REGPARM +#else +# define REGPARM_ICACHE +#endif + +#if (((ICACHE_INLINE & INCLUDED_BY_MODULE) || defined(_SIM_INLINE_C_)) \ + && !defined(_ICACHE_C_) && (ICACHE_INLINE & INCLUDE_MODULE)) +# if (ICACHE_INLINE & INLINE_MODULE) +# define INLINE_ICACHE(TYPE) static INLINE TYPE UNUSED +# define EXTERN_ICACHE(TYPE) static TYPE UNUSED REGPARM_ICACHE +#else +# define INLINE_ICACHE(TYPE) static TYPE UNUSED REGPARM_ICACHE +# define EXTERN_ICACHE(TYPE) static TYPE UNUSED REGPARM_ICACHE +#endif +#else +# define INLINE_ICACHE(TYPE) TYPE REGPARM_ICACHE +# define EXTERN_ICACHE(TYPE) TYPE REGPARM_ICACHE +#endif + +#if (ICACHE_INLINE & INLINE_LOCALS) +# define STATIC_INLINE_ICACHE(TYPE) static INLINE TYPE +#else +# define STATIC_INLINE_ICACHE(TYPE) static TYPE REGPARM_ICACHE +#endif + + + +/* idecode */ + +#if (IDECODE_INLINE & REGPARM_MODULE) +# define REGPARM_IDECODE REGPARM +#else +# define REGPARM_IDECODE +#endif + +#if (((IDECODE_INLINE & INCLUDED_BY_MODULE) || defined(_SIM_INLINE_C_)) \ + && !defined(_IDECODE_C_) && (IDECODE_INLINE & INCLUDE_MODULE)) +# if (IDECODE_INLINE & INLINE_MODULE) +# define INLINE_IDECODE(TYPE) static INLINE TYPE UNUSED +# define EXTERN_IDECODE(TYPE) static TYPE UNUSED REGPARM_IDECODE +#else +# define INLINE_IDECODE(TYPE) static TYPE UNUSED REGPARM_IDECODE +# define EXTERN_IDECODE(TYPE) static TYPE UNUSED REGPARM_IDECODE +#endif +#else +# define INLINE_IDECODE(TYPE) TYPE REGPARM_IDECODE +# define EXTERN_IDECODE(TYPE) TYPE REGPARM_IDECODE +#endif + +#if (IDECODE_INLINE & INLINE_LOCALS) +# define STATIC_INLINE_IDECODE(TYPE) static INLINE TYPE +#else +# define STATIC_INLINE_IDECODE(TYPE) static TYPE REGPARM_IDECODE +#endif + + + +/* semantics */ + +#if (SEMANTICS_INLINE & REGPARM_MODULE) +# define REGPARM_SEMANTICS REGPARM +#else +# define REGPARM_SEMANTICS +#endif + +#if (((SEMANTICS_INLINE & INCLUDED_BY_MODULE) || defined(_SIM_INLINE_C_)) \ + && !defined(_SEMANTICS_C_) && (SEMANTICS_INLINE & INCLUDE_MODULE)) +# if (SEMANTICS_INLINE & INLINE_MODULE) +# define INLINE_SEMANTICS(TYPE) static INLINE TYPE UNUSED +# define EXTERN_SEMANTICS(TYPE) static TYPE UNUSED REGPARM_SEMANTICS +#else +# define INLINE_SEMANTICS(TYPE) static TYPE UNUSED REGPARM_SEMANTICS +# define EXTERN_SEMANTICS(TYPE) static TYPE UNUSED REGPARM_SEMANTICS +#endif +#else +# define INLINE_SEMANTICS(TYPE) TYPE REGPARM_SEMANTICS +# define EXTERN_SEMANTICS(TYPE) TYPE REGPARM_SEMANTICS +#endif + +#if (SEMANTICS_INLINE & INLINE_LOCALS) +# define STATIC_INLINE_SEMANTICS(TYPE) static INLINE TYPE +#else +# define STATIC_INLINE_SEMANTICS(TYPE) static TYPE REGPARM_SEMANTICS +#endif + + + +/* support */ + +#if (SUPPORT_INLINE & REGPARM_MODULE) +# define REGPARM_SUPPORT REGPARM +#else +# define REGPARM_SUPPORT +#endif + +#if (((SUPPORT_INLINE & INCLUDED_BY_MODULE) || defined(_SIM_INLINE_C_)) \ + && !defined(_SUPPORT_C_) && (SUPPORT_INLINE & INCLUDE_MODULE)) +# if (SUPPORT_INLINE & INLINE_MODULE) +# define INLINE_SUPPORT(TYPE) static INLINE TYPE UNUSED +# define EXTERN_SUPPORT(TYPE) static TYPE UNUSED REGPARM_SUPPORT +#else +# define INLINE_SUPPORT(TYPE) static TYPE UNUSED REGPARM_SUPPORT +# define EXTERN_SUPPORT(TYPE) static TYPE UNUSED REGPARM_SUPPORT +#endif +#else +# define INLINE_SUPPORT(TYPE) TYPE REGPARM_SUPPORT +# define EXTERN_SUPPORT(TYPE) TYPE REGPARM_SUPPORT +#endif + +#if (SUPPORT_INLINE & INLINE_LOCALS) +# define STATIC_INLINE_SUPPORT(TYPE) static INLINE TYPE +#else +# define STATIC_INLINE_SUPPORT(TYPE) static TYPE REGPARM_SUPPORT +#endif + + + +#endif diff --git a/sim/common/sim-trace.c b/sim/common/sim-trace.c index ffdaf32..b4f7704 100644 --- a/sim/common/sim-trace.c +++ b/sim/common/sim-trace.c @@ -20,11 +20,236 @@ with this program; if not, write to the Free Software Foundation, Inc., #include "sim-main.h" #include "sim-io.h" +#include "sim-options.h" +#ifdef HAVE_STRING_H +#include +#else +#ifdef HAVE_STRINGS_H +#include +#endif +#endif + +static MODULE_UNINSTALL_FN trace_uninstall; + +static DECLARE_OPTION_HANDLER (trace_option_handler); + +#define OPTION_TRACE_INSN (OPTION_START + 0) +#define OPTION_TRACE_DECODE (OPTION_START + 1) +#define OPTION_TRACE_EXTRACT (OPTION_START + 2) +#define OPTION_TRACE_LINENUM (OPTION_START + 3) +#define OPTION_TRACE_MEMORY (OPTION_START + 4) +#define OPTION_TRACE_MODEL (OPTION_START + 5) +#define OPTION_TRACE_ALU (OPTION_START + 6) +#define OPTION_TRACE_CORE (OPTION_START + 7) +#define OPTION_TRACE_EVENTS (OPTION_START + 8) +#define OPTION_TRACE_FPU (OPTION_START + 9) +#define OPTION_TRACE_FILE (OPTION_START + 10) + +static const OPTION trace_options[] = +{ + { {"trace", no_argument, NULL, 't'}, + 't', NULL, "Perform tracing", + trace_option_handler }, + { {"trace-insn", no_argument, NULL, OPTION_TRACE_INSN}, + '\0', NULL, "Perform instruction tracing", + trace_option_handler }, + { {"trace-decode", no_argument, NULL, OPTION_TRACE_DECODE}, + '\0', NULL, "Perform instruction decoding tracing", + trace_option_handler }, + { {"trace-extract", no_argument, NULL, OPTION_TRACE_EXTRACT}, + '\0', NULL, "Perform instruction extraction tracing", + trace_option_handler }, + { {"trace-linenum", no_argument, NULL, OPTION_TRACE_LINENUM}, + '\0', NULL, "Perform line number tracing", + trace_option_handler }, + { {"trace-memory", no_argument, NULL, OPTION_TRACE_MEMORY}, + '\0', NULL, "Perform memory tracing", + trace_option_handler }, + { {"trace-model", no_argument, NULL, OPTION_TRACE_MODEL}, + '\0', NULL, "Perform model tracing", + trace_option_handler }, + { {"trace-alu", no_argument, NULL, OPTION_TRACE_ALU}, + '\0', NULL, "Perform ALU tracing", + trace_option_handler }, + { {"trace-core", no_argument, NULL, OPTION_TRACE_CORE}, + '\0', NULL, "Perform CORE tracing", + trace_option_handler }, + { {"trace-events", no_argument, NULL, OPTION_TRACE_EVENTS}, + '\0', NULL, "Perform EVENTS tracing", + trace_option_handler }, + { {"trace-fpu", no_argument, NULL, OPTION_TRACE_FPU}, + '\0', NULL, "Perform FPU tracing", + trace_option_handler }, + { {"trace-file", required_argument, NULL, OPTION_TRACE_FILE}, + '\0', "FILE NAME", "Specify tracing output file", + trace_option_handler }, + { {NULL, no_argument, NULL, 0}, '\0', NULL, NULL, NULL } +}; + +static SIM_RC +trace_option_handler (sd, opt, arg) + SIM_DESC sd; + int opt; + char *arg; +{ + int i,n; + + switch (opt) + { + case 't' : + if (! WITH_TRACE) + sim_io_eprintf (sd, "Tracing not compiled in, `-t' ignored\n"); + else + { + for (n = 0; n < MAX_NR_PROCESSORS; ++n) + for (i = 0; i < MAX_TRACE_VALUES; ++i) + CPU_TRACE_FLAGS (STATE_CPU (sd, n))[i] = 1; + STATE_CORE(sd)->trace = 1; + STATE_EVENTS(sd)->trace = 1; + } + break; + + case OPTION_TRACE_INSN : + if (WITH_TRACE_INSN_P) + for (n = 0; n < MAX_NR_PROCESSORS; ++n) + CPU_TRACE_FLAGS (STATE_CPU (sd, n))[TRACE_INSN_IDX] = 1; + else + sim_io_eprintf (sd, "Instruction tracing not compiled in, `--trace-insn' ignored\n"); + break; + + case OPTION_TRACE_DECODE : + if (WITH_TRACE_DECODE_P) + for (n = 0; n < MAX_NR_PROCESSORS; ++n) + CPU_TRACE_FLAGS (STATE_CPU (sd, n))[TRACE_DECODE_IDX] = 1; + else + sim_io_eprintf (sd, "Decode tracing not compiled in, `--trace-decode' ignored\n"); + break; + + case OPTION_TRACE_EXTRACT : + if (WITH_TRACE_EXTRACT_P) + for (n = 0; n < MAX_NR_PROCESSORS; ++n) + CPU_TRACE_FLAGS (STATE_CPU (sd, n))[TRACE_EXTRACT_IDX] = 1; + else + sim_io_eprintf (sd, "Extract tracing not compiled in, `--trace-extract' ignored\n"); + break; + + case OPTION_TRACE_LINENUM : + if (WITH_TRACE_LINENUM_P) + for (n = 0; n < MAX_NR_PROCESSORS; ++n) + CPU_TRACE_FLAGS (STATE_CPU (sd, n))[TRACE_LINENUM_IDX] = 1; + else + sim_io_eprintf (sd, "Line number tracing not compiled in, `--trace-linenum' ignored\n"); + break; + + case OPTION_TRACE_MEMORY : + if (WITH_TRACE_MEMORY_P) + for (n = 0; n < MAX_NR_PROCESSORS; ++n) + CPU_TRACE_FLAGS (STATE_CPU (sd, n))[TRACE_MEMORY_IDX] = 1; + else + sim_io_eprintf (sd, "Memory tracing not compiled in, `--trace-memory' ignored\n"); + break; + + case OPTION_TRACE_MODEL : + if (WITH_TRACE_MODEL_P) + for (n = 0; n < MAX_NR_PROCESSORS; ++n) + CPU_TRACE_FLAGS (STATE_CPU (sd, n))[TRACE_MODEL_IDX] = 1; + else + sim_io_eprintf (sd, "Model tracing not compiled in, `--trace-model' ignored\n"); + break; + + case OPTION_TRACE_ALU : + if (WITH_TRACE_ALU_P) + for (n = 0; n < MAX_NR_PROCESSORS; ++n) + CPU_TRACE_FLAGS (STATE_CPU (sd, n))[TRACE_ALU_IDX] = 1; + else + sim_io_eprintf (sd, "ALU tracing not compiled in, `--trace-alu' ignored\n"); + break; + + case OPTION_TRACE_CORE : + if (WITH_TRACE_CORE_P) + { + for (n = 0; n < MAX_NR_PROCESSORS; ++n) + CPU_TRACE_FLAGS (STATE_CPU (sd, n))[TRACE_CORE_IDX] = 1; + STATE_CORE(sd)->trace = 1; + } + else + sim_io_eprintf (sd, "CORE tracing not compiled in, `--trace-core' ignored\n"); + break; + + case OPTION_TRACE_EVENTS : + if (WITH_TRACE_EVENTS_P) + { + for (n = 0; n < MAX_NR_PROCESSORS; ++n) + CPU_TRACE_FLAGS (STATE_CPU (sd, n))[TRACE_EVENTS_IDX] = 1; + STATE_EVENTS(sd)->trace = 1; + } + else + sim_io_eprintf (sd, "EVENTS tracing not compiled in, `--trace-events' ignored\n"); + break; + + case OPTION_TRACE_FPU : + if (WITH_TRACE_FPU_P) + for (n = 0; n < MAX_NR_PROCESSORS; ++n) + CPU_TRACE_FLAGS (STATE_CPU (sd, n))[TRACE_FPU_IDX] = 1; + else + sim_io_eprintf (sd, "FPU tracing not compiled in, `--trace-fpu' ignored\n"); + break; + + case OPTION_TRACE_FILE : + if (! WITH_TRACE) + sim_io_eprintf (sd, "Tracing not compiled in, `--trace-file' ignored\n"); + else + { + FILE *f = fopen (arg, "w"); + + if (f == NULL) + { + sim_io_eprintf (sd, "Unable to open trace output file `%s'\n", arg); + return SIM_RC_FAIL; + } + for (n = 0; n < MAX_NR_PROCESSORS; ++n) + TRACE_FILE (CPU_TRACE_DATA (STATE_CPU (sd, n))) = f; + } + break; + } + + return SIM_RC_OK; +} + +/* Install tracing support. */ + +SIM_RC +trace_install (SIM_DESC sd) +{ + int i; + + sim_add_option_table (sd, trace_options); + for (i = 0; i < MAX_NR_PROCESSORS; ++i) + memset (CPU_TRACE_DATA (STATE_CPU (sd, i)), 0, + sizeof (* CPU_TRACE_DATA (STATE_CPU (sd, i)))); + sim_module_add_uninstall_fn (sd, trace_uninstall); + return SIM_RC_OK; +} + +static void +trace_uninstall (SIM_DESC sd) +{ + int i; + + for (i = 0; i < MAX_NR_PROCESSORS; ++i) + { + TRACE_DATA *data = CPU_TRACE_DATA (STATE_CPU (sd, i)); + if (TRACE_FILE (data) != NULL) + fclose (TRACE_FILE (data)); + } +} + void -trace_printf VPARAMS ((sim_cpu *cpu, const char *fmt, ...)) +trace_printf VPARAMS ((SIM_DESC sd, sim_cpu *cpu, const char *fmt, ...)) { #ifndef __STDC__ + SIM_DESC sd; sim_cpu *cpu; const char *fmt; #endif @@ -32,15 +257,15 @@ trace_printf VPARAMS ((sim_cpu *cpu, const char *fmt, ...)) VA_START (ap, fmt); #ifndef __STDC__ + sd = va_arg (ap, SIM_DESC); cpu = va_arg (ap, sim_cpu *); fmt = va_arg (ap, const char *); #endif - if (CPU_TRACE_FILE (cpu) == NULL) - (* STATE_CALLBACK (CPU_STATE (cpu))->evprintf_filtered) - (STATE_CALLBACK (CPU_STATE (cpu)), fmt, ap); + if (cpu != NULL && TRACE_FILE (CPU_TRACE_DATA (cpu)) != NULL) + vfprintf (TRACE_FILE (CPU_TRACE_DATA (cpu)), fmt, ap); else - vfprintf (CPU_TRACE_FILE (cpu), fmt, ap); + sim_io_evprintf (sd, fmt, ap); va_end (ap); } diff --git a/sim/common/sim-trace.h b/sim/common/sim-trace.h index ff28a6b..2a98808 100644 --- a/sim/common/sim-trace.h +++ b/sim/common/sim-trace.h @@ -23,6 +23,71 @@ with this program; if not, write to the Free Software Foundation, Inc., #ifndef SIM_TRACE_H #define SIM_TRACE_H +/* Maximum number of traceable entities. */ +#ifndef MAX_TRACE_VALUES +#define MAX_TRACE_VALUES 12 +#endif + +/* Standard traceable entities. */ +#define TRACE_INSN_IDX 0 +#define TRACE_DECODE_IDX 1 +#define TRACE_EXTRACT_IDX 2 +#define TRACE_LINENUM_IDX 3 +#define TRACE_MEMORY_IDX 4 +#define TRACE_MODEL_IDX 5 +#define TRACE_ALU_IDX 6 +#define TRACE_CORE_IDX 7 +#define TRACE_EVENTS_IDX 8 +#define TRACE_FPU_IDX 9 +#define TRACE_NEXT_IDX 16 /* simulator specific trace bits begin here */ + +/* Masks so WITH_TRACE can have symbolic values. */ +#define TRACE_insn 1 +#define TRACE_decode 2 +#define TRACE_extract 4 +#define TRACE_linenum 8 +#define TRACE_memory 16 +#define TRACE_model 32 +#define TRACE_alu 64 +#define TRACE_core 128 +#define TRACE_events 256 +#define TRACE_fpu 512 + +/* Preprocessor macros to simplify tests of WITH_TRACE. */ +#define WITH_TRACE_INSN_P (WITH_TRACE & TRACE_insn) +#define WITH_TRACE_DECODE_P (WITH_TRACE & TRACE_decode) +#define WITH_TRACE_EXTRACT_P (WITH_TRACE & TRACE_extract) +#define WITH_TRACE_LINENUM_P (WITH_TRACE & TRACE_linenum) +#define WITH_TRACE_MEMORY_P (WITH_TRACE & TRACE_memory) +#define WITH_TRACE_MODEL_P (WITH_TRACE & TRACE_model) +#define WITH_TRACE_ALU_P (WITH_TRACE & TRACE_alu) +#define WITH_TRACE_CORE_P (WITH_TRACE & TRACE_core) +#define WITH_TRACE_EVENTS_P (WITH_TRACE & TRACE_events) +#define WITH_TRACE_FPU_P (WITH_TRACE & TRACE_fpu) + +/* Tracing install handler. */ +MODULE_INSTALL_FN trace_install; + +/* Struct containing all trace data. */ + +typedef struct { + /* Boolean array of specified tracing flags. */ + /* ??? It's not clear that using an array vs a bit mask is faster. + Consider the case where one wants to test whether any of several bits + are set. */ + char trace_flags[MAX_TRACE_VALUES]; +#define TRACE_FLAGS(t) ((t)->trace_flags) + + /* Tracing output goes to this or stderr if NULL. + We can't store `stderr' here as stderr goes through a callback. */ + FILE *trace_file; +#define TRACE_FILE(t) ((t)->trace_file) +} TRACE_DATA; + +/* Usage macros. */ + +#define CPU_TRACE_FLAGS(cpu) TRACE_FLAGS (CPU_TRACE_DATA (cpu)) + /* forward reference */ struct _sim_cpu; @@ -37,10 +102,14 @@ struct _sim_cpu; #define TRACE_INSN_P(cpu) TRACE_P (cpu, TRACE_INSN_IDX) /* Non-zero if "--trace-decode" specified for CPU. */ #define TRACE_DECODE_P(cpu) TRACE_P (cpu, TRACE_DECODE_IDX) +/* Non-zero if "--trace-fpu" specified for CPU. */ +#define TRACE_FPU_P(cpu) TRACE_P (cpu, TRACE_FPU_IDX) -extern void trace_printf PARAMS ((struct _sim_cpu *, const char *, ...)); +extern void trace_printf PARAMS ((SIM_DESC, sim_cpu *, const char *, ...)); -/* Debug support. */ +/* Debug support. + This is included here because there isn't enough of it to justify + a sim-debug.h. */ /* Return non-zero if debugging of IDX for CPU is enabled. */ #define DEBUG_P(cpu, idx) \ diff --git a/sim/testsuite/.Sanitize b/sim/testsuite/.Sanitize index 558b4e5..3fbbadd 100644 --- a/sim/testsuite/.Sanitize +++ b/sim/testsuite/.Sanitize @@ -38,6 +38,7 @@ configure.in Things-to-lose: common +tic80-coff Do-last: diff --git a/sim/tic80/ChangeLog b/sim/tic80/ChangeLog index 99ea871..5aebb29 100644 --- a/sim/tic80/ChangeLog +++ b/sim/tic80/ChangeLog @@ -1,3 +1,16 @@ +Mon May 5 14:10:17 1997 Andrew Cagney + + * insn (cmnd): No-op cache flushes. + + * insns (do_trap): Allow writes to STDERR. + + * Makefile.in (SIM_OBJS): Link in sim-fpu.o. + (SIM_EXTRA_LIBS): Link in the math library. + + * alu.h: Add support for floating point unit using sim-alu. + + * insns (fadd, fsub, fmpy, fdiv, fcmp, frnd*): Implement. + Fri May 2 14:57:14 1997 Andrew Cagney * sim-calls.c: Include sim-utils.h and sim-options.h. diff --git a/sim/tic80/Makefile.in b/sim/tic80/Makefile.in index 3391a79..21be037 100644 --- a/sim/tic80/Makefile.in +++ b/sim/tic80/Makefile.in @@ -21,12 +21,16 @@ SIM_OBJS = sim-endian.o sim-bits.o sim-config.o interp.o \ sim-module.o \ sim-options.o \ sim-trace.o \ - sim-profile.o + sim-profile.o \ + sim-fpu.o # List of extra dependencies. # Generally this consists of simulator specific files included by sim-main.h. SIM_EXTRA_DEPS = itable.h idecode.h cpu.h alu.h +# List of extra libraries to link with +SIM_EXTRA_LIBS = -lm + # List of generators SIM_GEN=tmp-igen @@ -36,6 +40,7 @@ SIM_ENDIAN=@sim_endian@ SIM_HOSTENDIAN=@sim_hostendian@ SIM_INLINE=@sim_inline@ SIM_RESERVED_BITS=@sim_reserved_bits@ +SIM_ALIGNMENT=@sim_alignment@ SIM_EXTRA_CFLAGS = \ $(SIM_WARNINGS) \ diff --git a/sim/tic80/alu.h b/sim/tic80/alu.h index 7312f60..3a325e1 100644 --- a/sim/tic80/alu.h +++ b/sim/tic80/alu.h @@ -1,10 +1,30 @@ +/* Texas Instruments TMS320C80 (MVP) Simulator. + Copyright (C) 1997 Free Software Foundation, Inc. + Contributed by Cygnus Support. + +This file is part of GDB, the GNU debugger. + +This program is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +This program is distributed in the hope that it 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 this program; if not, write to the Free Software Foundation, Inc., +59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ + + + #ifndef _TIC80_ALU_H_ #define _TIC80_ALU_H_ #define ALU_CARRY 0 /* FIXME */ -#include "sim-alu.h" - #define ALU32_END(TARG) \ { \ (TARG) = (unsigned32)alu_carry_val; /* FIXME */ \ @@ -12,6 +32,9 @@ #define ALU_END(TARG) ALU32_END(TARG) +#include "sim-alu.h" + + /* Bring data in from the cold */ @@ -37,4 +60,11 @@ do { \ nia.ip += sizeof (instruction_word); \ nia.dp += sizeof (instruction_word); + + +/* Floating point support */ + +#include "sim-fpu.h" + + #endif diff --git a/sim/tic80/cpu.h b/sim/tic80/cpu.h index 9e81980..9133632 100644 --- a/sim/tic80/cpu.h +++ b/sim/tic80/cpu.h @@ -29,3 +29,8 @@ struct _sim_cpu { #define GPR(N) ((CPU)->reg[N]) #define ACC(N) ((CPU)->acc[N]) + +#define SP_FPR(N) (GPR(N)) +#define DP_FPR(N) (*(unsigned64*)&GPR(N)) +#define vSP_FPR(N) (N == 0 ? (unsigned32)0 : GPR(N)) +#define vDP_FPR(N) (*(unsigned64*)&GPR(N)) diff --git a/sim/tic80/insns b/sim/tic80/insns index 71a0e8f..35cfbf3 100644 --- a/sim/tic80/insns +++ b/sim/tic80/insns @@ -1,3 +1,24 @@ +// Texas Instruments TMS320C80 (MVP) Simulator. +// Copyright (C) 1997 Free Software Foundation, Inc. +// Contributed by Cygnus Support. +// +// This file is part of GDB, the GNU debugger. +// +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation; either version 2, or (at your option) +// any later version. +// +// This program is distributed in the hope that it 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 this program; if not, write to the Free Software Foundation, Inc., +// 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ + + // The following is called when ever an illegal instruction is // encountered ::internal::illegal @@ -185,10 +206,50 @@ instruction_address::function::do_bsr:instruction_address nia, signed32 *rLink, // cmnd +void::function::do_cmnd:signed32 source + int Reset = EXTRACTED32 (source, 31, 31); + int Halt = EXTRACTED32 (source, 30, 30); + int Unhalt = EXTRACTED32 (source, 29, 29); + /* int ICR = EXTRACTED32 (source, 28, 28); */ + /* int DCR = EXTRACTED32 (source, 27, 27); */ + int Task = EXTRACTED32 (source, 14, 14); + int Msg = EXTRACTED32 (source, 13, 13); + int VC = EXTRACTED32 (source, 10, 10); + int TC = EXTRACTED32 (source, 9, 9); + int MP = EXTRACTED32 (source, 8, 8); + int PP = EXTRACTED32 (source, 3, 0); + /* what is implemented? */ + if (PP != 0) + engine_error (SD, CPU, cia, "0x%lx: cmnd - PPs not supported", + (unsigned long) cia.ip); + if (VC != 0) + engine_error (SD, CPU, cia, "0x%lx: cmnd - VC not supported", + (unsigned long) cia.ip); + if (TC != 0) + engine_error (SD, CPU, cia, "0x%lx: cmnd - TC not supported", + (unsigned long) cia.ip); + if (MP) + { + if (Reset || Halt) + engine_halt (SD, CPU, cia, sim_exited, 0); + if (Unhalt) + engine_error (SD, CPU, cia, "0x%lx: cmnd - Can not unhalt the MP", + (unsigned long) cia.ip); + /* if (ICR || DCR); */ + if (Task) + engine_error (SD, CPU, cia, "0x%lx: cmnd - Can not Task the MP", + (unsigned long) cia.ip); + if (Msg) + engine_error (SD, CPU, cia, "0x%lx: cmnd - Msg to MP not suported", + (unsigned long) cia.ip); + } 31./,21.0b0000010,14.UI::::cmnd i -31./,21.0b110000010,12.0,11./,4.Source1::::cmnd r + do_cmnd (_SD, UI); +31./,21.0b110000010,12.0,11./,4.Source::::cmnd r + do_cmnd (_SD, rSource); 31./,21.0b110000010,12.1,11./::::cmnd l - + long_immediate (LongUnsignedImmediate); + do_cmnd (_SD, LongUnsignedImmediate); // cmp unsigned32::function::cmp_vals:signed32 s1, unsigned32 u1, signed32 s2, unsigned32 u2 @@ -281,76 +342,208 @@ void::function::do_dst:int Source, unsigned32 Base, unsigned32 *rBase, int m , i // extu - see shift.dz +sim_fpu::function::get_fp_reg:int reg, unsigned32 val, int precision + switch (precision) + { + case 0: /* single */ + if (reg == 0) + return sim_fpu_32to (0); + else + return sim_fpu_32to (val); + case 1: /* double */ + if (reg < 0) + return sim_fpu_32to (val); + if (reg & 1) + engine_error (SD, CPU, cia, "DP FP register must be even"); + if (reg <= 1) + engine_error (SD, CPU, cia, "DP FP register must be >= 2"); + return sim_fpu_64to (INSERTED64 (GPR(reg + 1), 63, 32) + | INSERTED64 (GPR(reg), 31, 0)); + case 2: /* 32 bit signed integer */ + if (reg == 0) + return sim_fpu_32to (0); + else + return sim_fpu_d2 ((signed32) val); + case 3: /* 32 bit unsigned integer */ + if (reg == 0) + return sim_fpu_32to (0); + else + return sim_fpu_d2 ((unsigned32) val); + default: + engine_error (SD, CPU, cia, "Unsupported FP precision"); + } + return sim_fpu_32to (0); +void::function::set_fp_reg:int Dest, sim_fpu val, int PD + switch (PD) + { + case 0: /* single */ + { + GPR (Dest) = sim_fpu_to32 (val); + break; + } + case 1: /* double */ + { + unsigned64 v = *(unsigned64*) &val; + if (Dest & 1) + engine_error (SD, CPU, cia, "DP FP Dest register must be even"); + if (Dest <= 1) + engine_error (SD, CPU, cia, "DP FP Dest register must be >= 2"); + GPR (Dest) = EXTRACTED64 (v, 21, 0); + GPR (Dest + 1) = EXTRACTED64 (v, 63, 32); + break; + } + case 2: /* signed */ + /* FIXME - rounding */ + GPR (Dest) = sim_fpu_2d (val); + break; + case 3: /* unsigned */ + /* FIXME - rounding */ + GPR (Dest) = sim_fpu_2d (val); + break; + default: + engine_error (SD, CPU, cia, "Unsupported FP precision"); + } + // fadd.{s|d}{s|d}{s|d} -#void::function::do_fadd:unsigned32 *rDest, unsigned32 Source1, unsigned32 Source2 -# sim_io_error ("fadd"); +void::function::do_fadd:int Dest, int PD, sim_fpu s1, sim_fpu s2 + sim_fpu ans = sim_fpu_add (s1, s2); + if (TRACE_FPU_P(CPU)) + trace_printf (SD, CPU, "0x%lx: fadd - %f + %f = %f\n", + (unsigned long) cia.ip, + sim_fpu_2d (s1), sim_fpu_2d (s2), + sim_fpu_2d (ans)); + set_fp_reg (_SD, Dest, ans, PD); 31.Dest,26.Source2,21.0b111110000,12.0,11.r,10.PD,8.P2,6.P1,4.Source1::::fadd r -# do_fadd (_SD, rDest, rSource1, rSource2); + do_fadd (_SD, Dest, PD, + get_fp_reg (_SD, Source1, rSource1, P1), + get_fp_reg (_SD, Source2, rSource2, P2)); 31.Dest,26.Source2,21.0b111110000,12.1,11.r,10.PD,8.P2,6.P1,4./::::fadd l -# do_fadd (_SD, rDest, LongSignedImmediate, rSource2); + long_immediate (SinglePrecisionFloatingPoint); + do_fadd (_SD, Dest, PD, + get_fp_reg (_SD, -1, SinglePrecisionFloatingPoint, P1), + get_fp_reg (_SD, Source2, rSource2, P2)); // fcmp.{s|d}{s|d}{s|d} -#void::function::do_fcmp:unsigned32 *rDest, unsigned32 Source1, unsigned32 Source2 -# sim_io_error ("fcmp"); +void::function::do_fcmp:unsigned32 *rDest, sim_fpu s1, sim_fpu s2 + *rDest = 0; + if (sim_fpu_is_nan (s1) || sim_fpu_is_nan (s2)) + *rDest |= BIT32 (30); + else + { + *rDest |= BIT32 (31); + if (sim_fpu_cmp (s1, s2) == 0) *rDest |= BIT32(20); + if (sim_fpu_cmp (s1, s2) != 0) *rDest |= BIT32(21); + if (sim_fpu_cmp (s1, s2) > 0) *rDest |= BIT32(22); + if (sim_fpu_cmp (s1, s2) <= 0) *rDest |= BIT32(23); + if (sim_fpu_cmp (s1, s2) < 0) *rDest |= BIT32(24); + if (sim_fpu_cmp (s1, s2) >= 0) *rDest |= BIT32(25); + if (sim_fpu_cmp (s1, sim_fpu_32to (0)) < 0 + || sim_fpu_cmp (s1, s2) > 0) *rDest |= BIT32(26); + if (sim_fpu_cmp (sim_fpu_32to (0), s1) < 0 + && sim_fpu_cmp (s1, s2) < 0) *rDest |= BIT32(27); + if (sim_fpu_cmp (sim_fpu_32to (0), s1) <= 0 + && sim_fpu_cmp (s1, s2) <= 0) *rDest |= BIT32(28); + if (sim_fpu_cmp (s1, sim_fpu_32to (0)) <= 0 + || sim_fpu_cmp (s1, s2) >= 0) *rDest |= BIT32(29); + } + if (TRACE_FPU_P (CPU)) + trace_printf (SD, CPU, "0x%lx: fcmp - %f >=< %f - 0x%08x\n", + (unsigned long) cia.ip, + sim_fpu_2d (s1), sim_fpu_2d (s2), + (unsigned long) *rDest); 31.Dest,26.Source2,21.0b111110101,12.0,11./,10.0,8.P2,6.P1,4.Source1::::fcmp r -# do_fcmp (_SD, rDest, rSource1, rSource2); + do_fcmp (_SD, rDest, + get_fp_reg (_SD, Source1, rSource1, P1), + get_fp_reg (_SD, Source2, rSource2, P2)); 31.Dest,26.Source2,21.0b111110101,12.1,11./,10.0,8.P2,6.P1,4./::::fcmp l -# do_fcmp (_SD, rDest, LongSignedImmediate, rSource2); + long_immediate (SinglePrecisionFloatingPoint); + do_fcmp (_SD, rDest, + get_fp_reg (_SD, -1, SinglePrecisionFloatingPoint, P1), + get_fp_reg (_SD, Source2, rSource2, P2)); + // fdiv.{s|d}{s|d}{s|d} -#void::function::do_fdiv:unsigned32 *rDest, unsigned32 Source1, unsigned32 Source2 -# sim_io_error ("fdiv"); +void::function::do_fdiv:int Dest, int PD, sim_fpu s1, sim_fpu s2 + sim_fpu ans = sim_fpu_div (s1, s2); + if (TRACE_FPU_P(CPU)) + trace_printf (SD, CPU, "0x%lx: fdiv - %f / %f = %f\n", + (unsigned long) cia.ip, + sim_fpu_2d (s1), sim_fpu_2d (s2), + sim_fpu_2d (ans)); + set_fp_reg (_SD, Dest, ans, PD); 31.Dest,26.Source2,21.0b111110011,12.0,11./,10.PD,8.P2,6.P1,4.Source1::::fdiv r -# do_fdiv (_SD, rDest, rSource1, rSource2); + do_fdiv (_SD, Dest, PD, + get_fp_reg (_SD, Source1, rSource1, P1), + get_fp_reg (_SD, Source2, rSource2, P2)); 31.Dest,26.Source2,21.0b111110011,12.1,11./,10.PD,8.P2,6.P1,4./::::fdiv l -# do_fdiv (_SD, rDest, LongSignedImmediate, rSource2); + long_immediate (SinglePrecisionFloatingPoint); + do_fdiv (_SD, Dest, PD, + get_fp_reg (_SD, -1, SinglePrecisionFloatingPoint, P1), + get_fp_reg (_SD, Source2, rSource2, P2)); // fmpy.{s|d|i|u}{s|d|i|u}{s|d|i|u} -#void::function::do_fmpy:unsigned32 *rDest, unsigned32 Source1, unsigned32 Source2 -# sim_io_error ("fmpy"); +void::function::do_fmpy:int Dest, int PD, sim_fpu s1, sim_fpu s2 + sim_fpu ans = sim_fpu_mul (s1, s2); + if (TRACE_FPU_P(CPU)) + trace_printf (SD, CPU, "0x%lx: fmpy - %f * %f = %f\n", + (unsigned long) cia.ip, + sim_fpu_2d (s1), sim_fpu_2d (s2), + sim_fpu_2d (ans)); + set_fp_reg (_SD, Dest, ans, PD); 31.Dest,26.Source2,21.0b111110010,12.0,11./,10.PD,8.P2,6.P1,4.Source1::::fmpy r -# do_fmpy (_SD, rDest, rSource1, rSource2); + do_fmpy (_SD, Dest, PD, + get_fp_reg (_SD, Source1, rSource1, P1), + get_fp_reg (_SD, Source2, rSource2, P2)); 31.Dest,26.Source2,21.0b111110010,12.1,11./,10.PD,8.P2,6.P1,4./::::fmpy l -# do_fmpy (_SD, rDest, LongSignedImmediate, rSource2); + long_immediate (SinglePrecisionFloatingPoint); + do_fmpy (_SD, Dest, PD, + get_fp_reg (_SD, -1, SinglePrecisionFloatingPoint, P1), + get_fp_reg (_SD, Source2, rSource2, P2)); // frndm.{s|d|i|u}{s|d|i|u}{s|d|i|u} -#void::function::do_frndm:unsigned32 *rDest, unsigned32 Source1, unsigned32 Source2 -# sim_io_error ("frndm"); -31.Dest,26.Source2,21.0b111110100,12.0,11.r,10.PD,8.0b11,6.P1,4.Source1::::frndm r -# do_frndm (_SD, rDest, rSource1, rSource2); +void::function::do_frnd:int Dest, int PD, sim_fpu s1 + set_fp_reg (_SD, Dest, s1, PD); +31.Dest,26.Source2,21.0b111110100,12.0,11.r,10.PD,8.0b11,6.P1,4.Source::::frndm r + do_frnd (_SD, Dest, PD, + get_fp_reg (_SD, Source, rSource, P1)); 31.Dest,26.Source2,21.0b111110100,12.1,11.r,10.PD,8.0b11,6.P1,4./::::frndm l -# do_frndm (_SD, rDest, LongSignedImmediate, rSource2); + long_immediate (SinglePrecisionFloatingPoint); + do_frnd (_SD, Dest, PD, + get_fp_reg (_SD, -1, SinglePrecisionFloatingPoint, P1)); // frndn.{s|d|i|u}{s|d|i|u}{s|d|i|u} -#void::function::do_frndn:unsigned32 *rDest, unsigned32 Source1, unsigned32 Source2 -# sim_io_error ("frndn"); -31.Dest,26.Source2,21.0b111110100,12.0,11.r,10.PD,8.0b00,6.P1,4.Source1::::frndn r -# do_frndn (_SD, rDest, rSource1, rSource2); +31.Dest,26.Source2,21.0b111110100,12.0,11.r,10.PD,8.0b00,6.P1,4.Source::::frndn r + do_frnd (_SD, Dest, PD, + get_fp_reg (_SD, Source, rSource, P1)); 31.Dest,26.Source2,21.0b111110100,12.1,11.r,10.PD,8.0b00,6.P1,4./::::frndn l -# do_frndn (_SD, rDest, LongSignedImmediate, rSource2); + long_immediate (SinglePrecisionFloatingPoint); + do_frnd (_SD, Dest, PD, + get_fp_reg (_SD, -1, SinglePrecisionFloatingPoint, P1)); // frndp.{s|d|i|u}{s|d|i|u}{s|d|i|u} -#void::function::do_frndp:unsigned32 *rDest, unsigned32 Source1, unsigned32 Source2 -# sim_io_error ("frndp"); -#31.Dest,26.Source2,21.0b111110100,12.0,11.r,10.PD,8.0b10,6.P1,4.Source1::::frndp r -# do_frndp (_SD, rDest, rSource1, rSource2); -#31.Dest,26.Source2,21.0b111110100,12.1,11.r,10.PD,8.0b10,6.P1,4./::::frndp l -# do_frndp (_SD, rDest, LongSignedImmediate, rSource2); +31.Dest,26.Source2,21.0b111110100,12.0,11.r,10.PD,8.0b10,6.P1,4.Source::::frndp r + do_frnd (_SD, Dest, PD, + get_fp_reg (_SD, Source, rSource, P1)); +31.Dest,26.Source2,21.0b111110100,12.1,11.r,10.PD,8.0b10,6.P1,4./::::frndp l + long_immediate (SinglePrecisionFloatingPoint); + do_frnd (_SD, Dest, PD, + get_fp_reg (_SD, -1, SinglePrecisionFloatingPoint, P1)); // frndz.{s|d|i|u}{s|d|i|u}{s|d|i|u} -#void::function::do_frndz:unsigned32 *rDest, unsigned32 Source1, unsigned32 Source2 -# sim_io_error ("frndz"); -31.Dest,26.Source2,21.0b111110100,12.0,11.r,10.PD,8.0b01,6.P1,4.Source1::::frndz r -# do_frndz (_SD, rDest, rSource1, rSource2); +31.Dest,26.Source2,21.0b111110100,12.0,11.r,10.PD,8.0b01,6.P1,4.Source::::frndz r + do_frnd (_SD, Dest, PD, + get_fp_reg (_SD, Source, rSource, P1)); 31.Dest,26.Source2,21.0b111110100,12.1,11.r,10.PD,8.0b01,6.P1,4./::::frndz l -# do_frndz (_SD, rDest, LongSignedImmediate, rSource2); + long_immediate (SinglePrecisionFloatingPoint); + do_frnd (_SD, Dest, PD, + get_fp_reg (_SD, -1, SinglePrecisionFloatingPoint, P1)); // fsqrt.{s|d}{s|d}{s|d} @@ -363,12 +556,23 @@ void::function::do_dst:int Source, unsigned32 Base, unsigned32 *rBase, int m , i // fsub.{s|d}{s|d}{s|d} -#void::function::do_fsub:unsigned32 *rDest, unsigned32 Source1, unsigned32 Source2 -# sim_io_error ("fsub"); +void::function::do_fsub:int Dest, int PD, sim_fpu s1, sim_fpu s2 + sim_fpu ans = sim_fpu_sub (s1, s2); + if (TRACE_FPU_P(CPU)) + trace_printf (SD, CPU, "0x%lx: fsub - %f + %f = %f\n", + (unsigned long) cia.ip, + sim_fpu_2d (s1), sim_fpu_2d (s2), + sim_fpu_2d (ans)); + set_fp_reg (_SD, Dest, ans, PD); 31.Dest,26.Source2,21.0b111110001,12.0,11.r,10.PD,8.P2,6.P1,4.Source1::::fsub r -# do_fsub (_SD, rDest, rSource1, rSource2); + do_fsub (_SD, Dest, PD, + get_fp_reg (_SD, Source1, rSource1, P1), + get_fp_reg (_SD, Source2, rSource2, P2)); 31.Dest,26.Source2,21.0b111110001,12.1,11.r,10.PD,8.P2,6.P1,4./::::fsub l -# do_fsub (_SD, rDest, LongSignedImmediate, rSource2); + long_immediate (SinglePrecisionFloatingPoint); + do_fsub (_SD, Dest, PD, + get_fp_reg (_SD, -1, SinglePrecisionFloatingPoint, P1), + get_fp_reg (_SD, Source2, rSource2, P2)); // illop @@ -390,7 +594,9 @@ instruction_address::function::do_jsr:instruction_address nia, signed32 *rLink, *rLink = cia.dp + sizeof (instruction_word); nia.dp = offset + base; if (nia.dp & 0x3) - engine_error (SD, CPU, cia, "destination address 0x%lx misaligned", + engine_error (SD, CPU, cia, + "0x%lx: destination address 0x%lx misaligned", + (unsigned long) cia.ip, (unsigned long) nia.dp); return nia; 31.Link,26.Base,21.0b100010,15.A,14.SignedOffset::::jsr i @@ -752,16 +958,24 @@ void::function::do_trap:unsigned32 trap_number case 4: /* WRITE */ { int i; - if (GPR(2) != 1) + if (GPR(2) == 1) + for (i = 0; i < GPR(6); i++) + { + char c; + c = MEM (unsigned, GPR(4) + i, 1); + sim_io_write_stdout (SD, &c, 1); + } + else if (GPR(2) == 2) + for (i = 0; i < GPR(6); i++) + { + char c; + c = MEM (unsigned, GPR(4) + i, 1); + sim_io_write_stderr (SD, &c, 1); + } + else engine_error (SD, CPU, cia, "0x%lx: write to invalid fid %d", (unsigned long) cia.ip, GPR(2)); - for (i = 0; i < GPR(6); i++) - { - char c; - c = MEM (unsigned, GPR(4) + i, 1); - sim_io_write_stdout (SD, &c, 1); - } GPR(2) = GPR(6); break; } -- 2.7.4