mirror of
https://github.com/darlinghq/darling-gdb.git
synced 2025-02-06 09:19:05 +00:00
Instruction decode generator taken from the PowerPC simulator
and being made more generic.
This commit is contained in:
parent
317df3b530
commit
a4c97499d9
175
sim/igen/Makefile.in
Normal file
175
sim/igen/Makefile.in
Normal file
@ -0,0 +1,175 @@
|
||||
#
|
||||
# This file is part of the program psim.
|
||||
#
|
||||
# Copyright (C) 1994-1997, Andrew Cagney <cagney@highland.com.au>
|
||||
# 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.
|
||||
#
|
||||
|
||||
default: all
|
||||
|
||||
VPATH = @srcdir@
|
||||
srcdir = @srcdir@
|
||||
srcroot = $(srcdir)/../..
|
||||
|
||||
prefix = @prefix@
|
||||
exec_prefix = @exec_prefix@
|
||||
|
||||
host_alias = @host_alias@
|
||||
target_alias = @target_alias@
|
||||
program_transform_name = @program_transform_name@
|
||||
bindir = @bindir@
|
||||
libdir = @libdir@
|
||||
tooldir = $(libdir)/$(target_alias)
|
||||
|
||||
datadir = @datadir@
|
||||
mandir = @mandir@
|
||||
man1dir = $(mandir)/man1
|
||||
man2dir = $(mandir)/man2
|
||||
man3dir = $(mandir)/man3
|
||||
man4dir = $(mandir)/man4
|
||||
man5dir = $(mandir)/man5
|
||||
man6dir = $(mandir)/man6
|
||||
man7dir = $(mandir)/man7
|
||||
man8dir = $(mandir)/man8
|
||||
man9dir = $(mandir)/man9
|
||||
infodir = @infodir@
|
||||
includedir = @includedir@
|
||||
|
||||
SHELL = /bin/sh
|
||||
|
||||
INSTALL = $(srcroot)/install.sh -c
|
||||
INSTALL_PROGRAM = @INSTALL_PROGRAM@
|
||||
INSTALL_DATA = @INSTALL_DATA@
|
||||
INSTALL_XFORM = $(INSTALL) -t='$(program_transform_name)'
|
||||
INSTALL_XFORM1= $(INSTALL_XFORM) -b=.1
|
||||
|
||||
AR = @AR@
|
||||
AR_FLAGS = rc
|
||||
CC = @CC@
|
||||
CFLAGS = @CFLAGS@
|
||||
CC_FOR_BUILD = @CC_FOR_BUILD@
|
||||
BISON = bison
|
||||
MAKEINFO = makeinfo
|
||||
RANLIB = @RANLIB@
|
||||
|
||||
STD_CFLAGS = $(CFLAGS) $(INLINE_CFLAGS) $(CONFIG_CFLAGS) $(WARNING_CFLAGS) $(SIM_CFLAGS) $(HDEFINES) $(TDEFINES) $(INCLUDES)
|
||||
NOWARN_CFLAGS = $(CFLAGS) $(INLINE_CFLAGS) $(CONFIG_CFLAGS) $(SIM_CFLAGS) $(HDEFINES) $(TDEFINES) $(INCLUDES)
|
||||
BUILD_CFLAGS = -g -O $(INCLUDES) $(WARNING_CFLAGS)
|
||||
|
||||
BUILD_LDFLAGS =
|
||||
|
||||
.NOEXPORT:
|
||||
MAKEOVERRIDES=
|
||||
|
||||
LIB_INCLUDES = -I$(srcdir)/../../include
|
||||
INCLUDES = -I. -I$(srcdir) $(LIB_INCLUDES)
|
||||
|
||||
LIBIBERTY_LIB = ../../libiberty/libiberty.a
|
||||
|
||||
|
||||
IGENLIB= libigen.a
|
||||
|
||||
all: igen $(IGENLIB)
|
||||
|
||||
.c.o:
|
||||
$(CC_FOR_BUILD) -c $(STD_CFLAGS) $<
|
||||
|
||||
filter_filename.o: filter_filename.c filter_filename.h config.h ppc-config.h
|
||||
|
||||
igen: igen.o $(IGENLIB)
|
||||
$(CC_FOR_BUILD) $(BUILD_CFLAGS) $(BUILD_LDFLAGS) -o igen igen.o $(IGENLIB) $(LIBIBERTY_LIB)
|
||||
|
||||
IGEN_OBJS=\
|
||||
table.o \
|
||||
lf.o misc.o \
|
||||
filter_host.o \
|
||||
ld-decode.o \
|
||||
ld-cache.o \
|
||||
filter.o \
|
||||
ld-insn.o \
|
||||
gen-model.o \
|
||||
gen-itable.o \
|
||||
gen-icache.o \
|
||||
gen-semantics.o \
|
||||
gen-idecode.o \
|
||||
gen-support.o \
|
||||
gen-engine.o
|
||||
|
||||
igen.o: igen.c misc.h filter_host.h lf.h table.h ld-decode.h ld-cache.h ld-insn.h filter.h gen-model.h gen-itable.h gen-icache.h gen-idecode.h gen-engine.h gen-semantics.h gen-support.h igen.h
|
||||
$(CC_FOR_BUILD) $(BUILD_CFLAGS) -c $(srcdir)/igen.c
|
||||
|
||||
$(IGENLIB): $(IGEN_OBJS)
|
||||
rm -f $(IGENLIB)
|
||||
$(AR) $(AR_FLAGS) $(IGENLIB) $(IGEN_OBJS)
|
||||
$(RANLIB) $(IGENLIB)
|
||||
|
||||
|
||||
tmp-filter: filter.c misc.h misc.o
|
||||
$(CC_FOR_BUILD) $(BUILD_CFLAGS) $(BUILD_LDFLAGS) -o tmp-filter -DMAIN $(srcdir)/filter.c misc.o $(BUILD_LIBS)
|
||||
|
||||
tmp-ld-decode: ld-decode.o misc.o lf.o table.o filter_host.o
|
||||
$(CC_FOR_BUILD) $(BUILD_CFLAGS) $(BUILD_LDFLAGS) -o tmp-ld-decode -DMAIN $(srcdir)/ld-decode.c misc.o lf.o table.o filter_host.o $(BUILD_LIBS)
|
||||
|
||||
tmp-ld-cache: ld-cache.o misc.o lf.o table.o filter_host.o
|
||||
$(CC_FOR_BUILD) $(BUILD_CFLAGS) $(BUILD_LDFLAGS) -o tmp-ld-cache -DMAIN $(srcdir)/ld-cache.c misc.o lf.o table.o filter_host.o $(BUILD_LIBS)
|
||||
|
||||
tmp-ld-insn: ld-insn.o misc.o lf.o table.o ld-decode.o filter_host.o filter.o
|
||||
$(CC_FOR_BUILD) $(BUILD_CFLAGS) $(BUILD_LDFLAGS) -o tmp-ld-insn -DMAIN $(srcdir)/ld-insn.c misc.o lf.o table.o ld-decode.o filter_host.o filter.o $(BUILD_LIBS)
|
||||
|
||||
filter_host.o: filter_host.c filter_host.h
|
||||
table.o: table.c misc.h filter_host.h lf.h table.h
|
||||
lf.o: lf.c misc.h filter_host.h lf.h
|
||||
filter.o: filter.c misc.h lf.h table.h filter.h
|
||||
ld-decode.o: ld-decode.c misc.h lf.h table.h ld-decode.h
|
||||
ld-cache.o: ld-cache.c misc.h lf.h table.h ld-cache.h
|
||||
ld-insn.o: ld-insn.c misc.h lf.h table.h ld-insn.h ld-decode.h igen.h
|
||||
gen-model.o: gen-model.c misc.h lf.h table.h gen-model.h ld-decode.h igen.h ld-insn.h
|
||||
gen-itable.o: gen-itable.c misc.h lf.h table.h gen-itable.h ld-decode.h igen.h ld-insn.h igen.h
|
||||
gen-icache.o: gen-icache.c misc.h lf.h table.h gen-icache.h ld-decode.h igen.h ld-insn.h gen-semantics.h gen-idecode.h
|
||||
gen-semantics.o: gen-semantics.c misc.h lf.h table.h gen-semantics.h ld-decode.h igen.h ld-insn.h
|
||||
gen-idecode.o: gen-idecode.c misc.h lf.h table.h gen-idecode.h gen-icache.h gen-semantics.h ld-decode.h igen.h ld-insn.h
|
||||
gen-engine.o: gen-engine.c misc.h lf.h table.h gen-idecode.h gen-engine.h gen-icache.h gen-semantics.h ld-decode.h igen.h ld-insn.h
|
||||
gen-support.o: gen-support.c misc.h lf.h table.h gen-support.h ld-decode.h igen.h ld-insn.h
|
||||
misc.o: misc.c misc.h filter_host.h
|
||||
|
||||
|
||||
tags etags: TAGS
|
||||
|
||||
TAGS:
|
||||
etags $(srcdir)/*.h $(srcdir)/*.c
|
||||
|
||||
clean mostlyclean:
|
||||
rm -f tmp-* *.[oasi] core igen
|
||||
|
||||
distclean realclean: clean
|
||||
rm -f TAGS Makefile config.cache config.status config.h defines.h stamp-h config.log
|
||||
|
||||
maintainer-clean: distclean
|
||||
rm -f *~ *.log ppc-config.h core *.core
|
||||
|
||||
Makefile: Makefile.in config.status
|
||||
CONFIG_FILES=Makefile CONFIG_HEADERS= $(SHELL) ./config.status
|
||||
|
||||
config.h: stamp-h ; @true
|
||||
stamp-h: config.in config.status
|
||||
CONFIG_FILES= CONFIG_HEADERS=config.h:config.in $(SHELL) ./config.status
|
||||
|
||||
config.status: configure
|
||||
$(SHELL) ./config.status --recheck
|
||||
|
||||
install:
|
||||
#
|
31
sim/igen/config.in
Normal file
31
sim/igen/config.in
Normal file
@ -0,0 +1,31 @@
|
||||
/* config.in. Generated automatically from configure.in by autoheader. */
|
||||
|
||||
/* Define if you have the <dirent.h> header file. */
|
||||
#undef HAVE_DIRENT_H
|
||||
|
||||
/* Define if you have the <ndir.h> header file. */
|
||||
#undef HAVE_NDIR_H
|
||||
|
||||
/* Define if you have the <stdlib.h> header file. */
|
||||
#undef HAVE_STDLIB_H
|
||||
|
||||
/* Define if you have the <string.h> header file. */
|
||||
#undef HAVE_STRING_H
|
||||
|
||||
/* Define if you have the <strings.h> header file. */
|
||||
#undef HAVE_STRINGS_H
|
||||
|
||||
/* Define if you have the <sys/dir.h> header file. */
|
||||
#undef HAVE_SYS_DIR_H
|
||||
|
||||
/* Define if you have the <sys/ndir.h> header file. */
|
||||
#undef HAVE_SYS_NDIR_H
|
||||
|
||||
/* Define if you have the <sys/stat.h> header file. */
|
||||
#undef HAVE_SYS_STAT_H
|
||||
|
||||
/* Define if you have the <sys/types.h> header file. */
|
||||
#undef HAVE_SYS_TYPES_H
|
||||
|
||||
/* Define if you have the <unistd.h> header file. */
|
||||
#undef HAVE_UNISTD_H
|
34
sim/igen/configure.in
Normal file
34
sim/igen/configure.in
Normal file
@ -0,0 +1,34 @@
|
||||
dnl Process this file with autoconf to produce a configure script.
|
||||
AC_PREREQ(2.5)dnl
|
||||
AC_INIT(Makefile.in)
|
||||
|
||||
AC_PROG_INSTALL
|
||||
AC_PROG_CC
|
||||
|
||||
# Put a plausible default for CC_FOR_BUILD in Makefile.
|
||||
if test "x$cross_compiling" = "xno"; then
|
||||
CC_FOR_BUILD='$(CC)'
|
||||
else
|
||||
CC_FOR_BUILD=gcc
|
||||
fi
|
||||
|
||||
|
||||
AC_CONFIG_AUX_DIR(`cd $srcdir;pwd`/../..)
|
||||
AC_CANONICAL_SYSTEM
|
||||
AC_ARG_PROGRAM
|
||||
|
||||
. ${srcdir}/../../bfd/configure.host
|
||||
|
||||
AC_CONFIG_HEADER(config.h:config.in)
|
||||
|
||||
AC_CHECK_HEADERS(stdlib.h string.h strings.h sys/stat.h sys/types.h unistd.h)
|
||||
AC_HEADER_DIRENT
|
||||
|
||||
AC_SUBST(CC_FOR_BUILD)
|
||||
AC_SUBST(CFLAGS)
|
||||
AR=${AR-ar}
|
||||
AC_SUBST(AR)
|
||||
AC_PROG_RANLIB
|
||||
|
||||
AC_OUTPUT(Makefile,
|
||||
[case x$CONFIG_HEADERS in xconfig.h:config.in) echo > stamp-h ;; esac])
|
150
sim/igen/filter.c
Normal file
150
sim/igen/filter.c
Normal file
@ -0,0 +1,150 @@
|
||||
/* This file is part of the program psim.
|
||||
|
||||
Copyright (C) 1994-1995, Andrew Cagney <cagney@highland.com.au>
|
||||
|
||||
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.
|
||||
|
||||
*/
|
||||
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#ifdef HAVE_STRING_H
|
||||
#include <string.h>
|
||||
#else
|
||||
#ifdef HAVE_STRINGS_H
|
||||
#include <strings.h>
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#include "misc.h"
|
||||
#include "filter.h"
|
||||
|
||||
struct _filter {
|
||||
char *flag;
|
||||
filter *next;
|
||||
};
|
||||
|
||||
|
||||
filter *
|
||||
new_filter(const char *filt,
|
||||
filter *filters)
|
||||
{
|
||||
while (strlen(filt) > 0) {
|
||||
filter *new_filter;
|
||||
/* break up the filt list */
|
||||
char *end = strchr(filt, ',');
|
||||
char *next;
|
||||
int len;
|
||||
if (end == NULL) {
|
||||
end = strchr(filt, '\0');
|
||||
next = end;
|
||||
}
|
||||
else {
|
||||
next = end + 1;
|
||||
}
|
||||
len = end - filt;
|
||||
/* add to filter list */
|
||||
new_filter = ZALLOC(filter);
|
||||
new_filter->flag = (char*)zalloc(len + 1);
|
||||
strncpy(new_filter->flag, filt, len);
|
||||
new_filter->next = filters;
|
||||
filters = new_filter;
|
||||
filt = next;
|
||||
}
|
||||
return filters;
|
||||
}
|
||||
|
||||
|
||||
int
|
||||
is_filtered_out(const char *flags,
|
||||
filter *filters)
|
||||
{
|
||||
while (strlen(flags) > 0) {
|
||||
int present;
|
||||
filter *filt = filters;
|
||||
/* break the string up */
|
||||
char *end = strchr(flags, ',');
|
||||
char *next;
|
||||
int len;
|
||||
if (end == NULL) {
|
||||
end = strchr(flags, '\0');
|
||||
next = end;
|
||||
}
|
||||
else {
|
||||
next = end + 1;
|
||||
}
|
||||
len = end - flags;
|
||||
/* check that it is present */
|
||||
present = 0;
|
||||
filt = filters;
|
||||
while (filt != NULL) {
|
||||
if (strncmp(flags, filt->flag, len) == 0
|
||||
&& strlen(filt->flag) == len) {
|
||||
present = 1;
|
||||
break;
|
||||
}
|
||||
filt = filt->next;
|
||||
}
|
||||
if (!present)
|
||||
return 1;
|
||||
flags = next;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
int
|
||||
it_is(const char *flag,
|
||||
const char *flags)
|
||||
{
|
||||
int flag_len = strlen(flag);
|
||||
while (*flags != '\0') {
|
||||
if (!strncmp(flags, flag, flag_len)
|
||||
&& (flags[flag_len] == ',' || flags[flag_len] == '\0'))
|
||||
return 1;
|
||||
while (*flags != ',') {
|
||||
if (*flags == '\0')
|
||||
return 0;
|
||||
flags++;
|
||||
}
|
||||
flags++;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
#ifdef MAIN
|
||||
int
|
||||
main(int argc, char **argv)
|
||||
{
|
||||
filter *filters = NULL;
|
||||
int i;
|
||||
if (argc < 2) {
|
||||
printf("Usage: filter <flags> <filter> ...\n");
|
||||
exit (1);
|
||||
}
|
||||
/* load the filter up */
|
||||
for (i = 2; i < argc; i++)
|
||||
filters = new_filter(argv[i], filters);
|
||||
if (is_filtered_out(argv[1], filters))
|
||||
printf("fail\n");
|
||||
else
|
||||
printf("pass\n");
|
||||
return 0;
|
||||
}
|
||||
#endif
|
43
sim/igen/filter.h
Normal file
43
sim/igen/filter.h
Normal file
@ -0,0 +1,43 @@
|
||||
/* This file is part of the program psim.
|
||||
|
||||
Copyright (C) 1994-1995, Andrew Cagney <cagney@highland.com.au>
|
||||
|
||||
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.
|
||||
|
||||
*/
|
||||
|
||||
|
||||
typedef struct _filter filter;
|
||||
|
||||
|
||||
/* append the filter onto the end of the list */
|
||||
|
||||
extern filter *new_filter
|
||||
(const char *filt,
|
||||
filter *filters);
|
||||
|
||||
|
||||
/* returns true if the flags are non empty and some are missing from the filter list */
|
||||
|
||||
extern int is_filtered_out
|
||||
(const char *flags,
|
||||
filter *filters);
|
||||
|
||||
/* true if the flag is in the list */
|
||||
|
||||
extern int it_is
|
||||
(const char *flag,
|
||||
const char *flags);
|
||||
|
37
sim/igen/filter_host.c
Normal file
37
sim/igen/filter_host.c
Normal file
@ -0,0 +1,37 @@
|
||||
/* This file is part of the program psim.
|
||||
|
||||
Copyright (C) 1994-1995, Andrew Cagney <cagney@highland.com.au>
|
||||
|
||||
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.
|
||||
|
||||
*/
|
||||
|
||||
#include "config.h"
|
||||
#include "filter_host.h"
|
||||
|
||||
/* Shorten traces by eliminating the directory component to filenames. */
|
||||
const char *
|
||||
filter_filename (const char *filename)
|
||||
{
|
||||
const char *p = filename;
|
||||
const char *last = filename;
|
||||
int ch;
|
||||
|
||||
while ((ch = *p++) != '\0' && ch != ':')
|
||||
if (ch == '/')
|
||||
last = p;
|
||||
|
||||
return last;
|
||||
}
|
27
sim/igen/filter_host.h
Normal file
27
sim/igen/filter_host.h
Normal file
@ -0,0 +1,27 @@
|
||||
/* This file is part of the program psim.
|
||||
|
||||
Copyright (C) 1994-1995, Andrew Cagney <cagney@highland.com.au>
|
||||
|
||||
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 _FILTER_FILENAME_H
|
||||
#define _FILTER_FILENAME_H
|
||||
|
||||
/* Remove directory part from filename */
|
||||
extern const char *
|
||||
filter_filename(const char *filename);
|
||||
#endif
|
29
sim/igen/gen-engine.h
Normal file
29
sim/igen/gen-engine.h
Normal file
@ -0,0 +1,29 @@
|
||||
/* This file is part of the program psim.
|
||||
|
||||
Copyright (C) 1994-1995, Andrew Cagney <cagney@highland.com.au>
|
||||
|
||||
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.
|
||||
|
||||
*/
|
||||
|
||||
extern void gen_engine_h
|
||||
(lf *file,
|
||||
insn_table *table,
|
||||
cache_table *cache_rules);
|
||||
|
||||
extern void gen_engine_c
|
||||
(lf *file,
|
||||
insn_table *table,
|
||||
cache_table *cache_rules);
|
68
sim/igen/gen-icache.h
Normal file
68
sim/igen/gen-icache.h
Normal file
@ -0,0 +1,68 @@
|
||||
/* This file is part of the program psim.
|
||||
|
||||
Copyright (C) 1994-1995, Andrew Cagney <cagney@highland.com.au>
|
||||
|
||||
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.
|
||||
|
||||
*/
|
||||
|
||||
|
||||
|
||||
/* Output code to manipulate the instruction cache: either create it
|
||||
or reference it */
|
||||
|
||||
typedef enum {
|
||||
declare_variables,
|
||||
define_variables,
|
||||
undef_variables,
|
||||
} icache_decl_type;
|
||||
|
||||
typedef enum {
|
||||
do_not_use_icache = 0,
|
||||
get_values_from_icache = 0x1,
|
||||
put_values_in_icache = 0x2,
|
||||
both_values_and_icache = 0x3,
|
||||
} icache_body_type;
|
||||
|
||||
extern void print_icache_body
|
||||
(lf *file,
|
||||
insn *instruction,
|
||||
insn_bits *expanded_bits,
|
||||
cache_table *cache_rules,
|
||||
icache_decl_type what_to_declare,
|
||||
icache_body_type what_to_do);
|
||||
|
||||
|
||||
/* Output an instruction cache decode function */
|
||||
|
||||
extern insn_handler print_icache_declaration;
|
||||
extern insn_handler print_icache_definition;
|
||||
|
||||
|
||||
/* Output an instruction cache support function */
|
||||
|
||||
extern function_handler print_icache_internal_function_declaration;
|
||||
extern function_handler print_icache_internal_function_definition;
|
||||
|
||||
|
||||
/* Output the instruction cache table data structure */
|
||||
|
||||
extern void print_icache_struct
|
||||
(insn_table *instructions,
|
||||
cache_table *cache_rules,
|
||||
lf *file);
|
||||
|
||||
|
||||
/* Output a single instructions decoder */
|
40
sim/igen/gen-idecode.h
Normal file
40
sim/igen/gen-idecode.h
Normal file
@ -0,0 +1,40 @@
|
||||
/* This file is part of the program psim.
|
||||
|
||||
Copyright (C) 1994-1995, Andrew Cagney <cagney@highland.com.au>
|
||||
|
||||
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.
|
||||
|
||||
*/
|
||||
|
||||
extern void gen_idecode_h
|
||||
(lf *file,
|
||||
insn_table *table,
|
||||
cache_table *cache_rules);
|
||||
|
||||
extern void gen_idecode_c
|
||||
(lf *file,
|
||||
insn_table *table,
|
||||
cache_table *cache_rules);
|
||||
|
||||
|
||||
/* Output code to do any final checks on the decoded instruction.
|
||||
This includes things like verifying any on decoded fields have the
|
||||
correct value and checking that (for floating point) floating point
|
||||
hardware isn't disabled */
|
||||
|
||||
extern void print_idecode_validate
|
||||
(lf *file,
|
||||
insn *instruction,
|
||||
opcode_field *opcodes);
|
28
sim/igen/gen-itable.h
Normal file
28
sim/igen/gen-itable.h
Normal file
@ -0,0 +1,28 @@
|
||||
/* This file is part of the program psim.
|
||||
|
||||
Copyright (C) 1994-1995, Andrew Cagney <cagney@highland.com.au>
|
||||
|
||||
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.
|
||||
|
||||
*/
|
||||
|
||||
|
||||
extern void gen_itable_h
|
||||
(insn_table *table,
|
||||
lf *file);
|
||||
|
||||
extern void gen_itable_c
|
||||
(insn_table *table,
|
||||
lf *file);
|
393
sim/igen/gen-model.c
Normal file
393
sim/igen/gen-model.c
Normal file
@ -0,0 +1,393 @@
|
||||
/* This file is part of the program psim.
|
||||
|
||||
Copyright (C) 1994-1995, Andrew Cagney <cagney@highland.com.au>
|
||||
|
||||
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.
|
||||
|
||||
*/
|
||||
|
||||
|
||||
#include "misc.h"
|
||||
#include "lf.h"
|
||||
#include "table.h"
|
||||
|
||||
#include "filter.h"
|
||||
|
||||
#include "ld-decode.h"
|
||||
#include "ld-insn.h"
|
||||
|
||||
#include "gen-model.h"
|
||||
|
||||
#ifndef NULL
|
||||
#define NULL 0
|
||||
#endif
|
||||
|
||||
|
||||
static void
|
||||
model_c_or_h_data(insn_table *table,
|
||||
lf *file,
|
||||
table_entry *data)
|
||||
{
|
||||
if (data->annex) {
|
||||
table_entry_print_cpp_line_nr(file, data);
|
||||
lf_print__c_code(file, data->annex);
|
||||
lf_print__internal_reference(file);
|
||||
lf_printf(file, "\n");
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
model_c_or_h_function(insn_table *entry,
|
||||
lf *file,
|
||||
table_entry *function,
|
||||
char *prefix)
|
||||
{
|
||||
if (function->fields[function_type] == NULL
|
||||
|| function->fields[function_type][0] == '\0') {
|
||||
error("Model function type not specified for %s", function->fields[function_name]);
|
||||
}
|
||||
lf_printf(file, "\n");
|
||||
lf_print_function_type(file, function->fields[function_type], prefix, " ");
|
||||
lf_printf(file, "%s\n(%s);\n",
|
||||
function->fields[function_name],
|
||||
function->fields[function_param]);
|
||||
lf_printf(file, "\n");
|
||||
}
|
||||
|
||||
void
|
||||
gen_model_h(insn_table *table, lf *file)
|
||||
{
|
||||
insn *insn_ptr;
|
||||
model *model_ptr;
|
||||
insn *macro;
|
||||
char *name;
|
||||
int model_create_p = 0;
|
||||
int model_init_p = 0;
|
||||
int model_halt_p = 0;
|
||||
int model_mon_info_p = 0;
|
||||
int model_mon_info_free_p = 0;
|
||||
|
||||
for(macro = model_macros; macro; macro = macro->next) {
|
||||
model_c_or_h_data(table, file, macro->file_entry);
|
||||
}
|
||||
|
||||
lf_printf(file, "typedef enum _model_enum {\n");
|
||||
lf_printf(file, " MODEL_NONE,\n");
|
||||
for (model_ptr = models; model_ptr; model_ptr = model_ptr->next) {
|
||||
lf_printf(file, " MODEL_%s,\n", model_ptr->name);
|
||||
}
|
||||
lf_printf(file, " nr_models\n");
|
||||
lf_printf(file, "} model_enum;\n");
|
||||
lf_printf(file, "\n");
|
||||
|
||||
lf_printf(file, "#define DEFAULT_MODEL MODEL_%s\n", (models) ? models->name : "NONE");
|
||||
lf_printf(file, "\n");
|
||||
|
||||
lf_printf(file, "typedef struct _model_data model_data;\n");
|
||||
lf_printf(file, "typedef struct _model_time model_time;\n");
|
||||
lf_printf(file, "\n");
|
||||
|
||||
lf_printf(file, "extern model_enum current_model;\n");
|
||||
lf_printf(file, "extern const char *model_name[ (int)nr_models ];\n");
|
||||
lf_printf(file, "extern const char *const *const model_func_unit_name[ (int)nr_models ];\n");
|
||||
lf_printf(file, "extern const model_time *const model_time_mapping[ (int)nr_models ];\n");
|
||||
lf_printf(file, "\n");
|
||||
|
||||
for(insn_ptr = model_functions; insn_ptr; insn_ptr = insn_ptr->next) {
|
||||
model_c_or_h_function(table, file, insn_ptr->file_entry, "INLINE_MODEL");
|
||||
name = insn_ptr->file_entry->fields[function_name];
|
||||
if (strcmp (name, "model_create") == 0)
|
||||
model_create_p = 1;
|
||||
else if (strcmp (name, "model_init") == 0)
|
||||
model_init_p = 1;
|
||||
else if (strcmp (name, "model_halt") == 0)
|
||||
model_halt_p = 1;
|
||||
else if (strcmp (name, "model_mon_info") == 0)
|
||||
model_mon_info_p = 1;
|
||||
else if (strcmp (name, "model_mon_info_free") == 0)
|
||||
model_mon_info_free_p = 1;
|
||||
}
|
||||
|
||||
if (!model_create_p) {
|
||||
lf_print_function_type(file, "model_data *", "INLINE_MODEL", " ");
|
||||
lf_printf(file, "model_create\n");
|
||||
lf_printf(file, "(cpu *processor);\n");
|
||||
lf_printf(file, "\n");
|
||||
}
|
||||
|
||||
if (!model_init_p) {
|
||||
lf_print_function_type(file, "void", "INLINE_MODEL", " ");
|
||||
lf_printf(file, "model_init\n");
|
||||
lf_printf(file, "(model_data *model_ptr);\n");
|
||||
lf_printf(file, "\n");
|
||||
}
|
||||
|
||||
if (!model_halt_p) {
|
||||
lf_print_function_type(file, "void", "INLINE_MODEL", " ");
|
||||
lf_printf(file, "model_halt\n");
|
||||
lf_printf(file, "(model_data *model_ptr);\n");
|
||||
lf_printf(file, "\n");
|
||||
}
|
||||
|
||||
if (!model_mon_info_p) {
|
||||
lf_print_function_type(file, "model_print *", "INLINE_MODEL", " ");
|
||||
lf_printf(file, "model_mon_info\n");
|
||||
lf_printf(file, "(model_data *model_ptr);\n");
|
||||
lf_printf(file, "\n");
|
||||
}
|
||||
|
||||
if (!model_mon_info_free_p) {
|
||||
lf_print_function_type(file, "void", "INLINE_MODEL", " ");
|
||||
lf_printf(file, "model_mon_info_free\n");
|
||||
lf_printf(file, "(model_data *model_ptr,\n");
|
||||
lf_printf(file, " model_print *info_ptr);\n");
|
||||
lf_printf(file, "\n");
|
||||
}
|
||||
|
||||
lf_print_function_type(file, "void", "INLINE_MODEL", " ");
|
||||
lf_printf(file, "model_set\n");
|
||||
lf_printf(file, "(const char *name);\n");
|
||||
}
|
||||
|
||||
/****************************************************************/
|
||||
|
||||
typedef struct _model_c_passed_data model_c_passed_data;
|
||||
struct _model_c_passed_data {
|
||||
lf *file;
|
||||
model *model_ptr;
|
||||
};
|
||||
|
||||
static void
|
||||
model_c_insn(insn_table *entry,
|
||||
lf *phony_file,
|
||||
void *data,
|
||||
insn *instruction,
|
||||
int depth)
|
||||
{
|
||||
model_c_passed_data *data_ptr = (model_c_passed_data *)data;
|
||||
lf *file = data_ptr->file;
|
||||
char *current_name = data_ptr->model_ptr->printable_name;
|
||||
table_model_entry *model_ptr = instruction->file_entry->model_first;
|
||||
|
||||
while (model_ptr) {
|
||||
if (model_ptr->fields[insn_model_name] == current_name) {
|
||||
lf_printf(file, " { %-*s }, /* %s */\n",
|
||||
max_model_fields_len,
|
||||
model_ptr->fields[insn_model_fields],
|
||||
instruction->file_entry->fields[insn_name]);
|
||||
return;
|
||||
}
|
||||
|
||||
model_ptr = model_ptr->next;
|
||||
}
|
||||
|
||||
lf_printf(file, " { %-*s }, /* %s */\n",
|
||||
max_model_fields_len,
|
||||
data_ptr->model_ptr->insn_default,
|
||||
instruction->file_entry->fields[insn_name]);
|
||||
}
|
||||
|
||||
static void
|
||||
model_c_function(insn_table *table,
|
||||
lf *file,
|
||||
table_entry *function,
|
||||
const char *prefix)
|
||||
{
|
||||
if (function->fields[function_type] == NULL
|
||||
|| function->fields[function_type][0] == '\0') {
|
||||
error("Model function return type not specified for %s", function->fields[function_name]);
|
||||
}
|
||||
else {
|
||||
lf_printf(file, "\n");
|
||||
lf_print_function_type(file, function->fields[function_type], prefix, "\n");
|
||||
lf_printf(file, "%s(%s)\n",
|
||||
function->fields[function_name],
|
||||
function->fields[function_param]);
|
||||
}
|
||||
table_entry_print_cpp_line_nr(file, function);
|
||||
lf_printf(file, "{\n");
|
||||
if (function->annex) {
|
||||
lf_indent(file, +2);
|
||||
lf_print__c_code(file, function->annex);
|
||||
lf_indent(file, -2);
|
||||
}
|
||||
lf_printf(file, "}\n");
|
||||
lf_print__internal_reference(file);
|
||||
lf_printf(file, "\n");
|
||||
}
|
||||
|
||||
void
|
||||
gen_model_c(insn_table *table, lf *file)
|
||||
{
|
||||
insn *insn_ptr;
|
||||
model *model_ptr;
|
||||
char *name;
|
||||
int model_create_p = 0;
|
||||
int model_init_p = 0;
|
||||
int model_halt_p = 0;
|
||||
int model_mon_info_p = 0;
|
||||
int model_mon_info_free_p = 0;
|
||||
|
||||
lf_printf(file, "\n");
|
||||
lf_printf(file, "#include \"cpu.h\"\n");
|
||||
lf_printf(file, "#include \"mon.h\"\n");
|
||||
lf_printf(file, "\n");
|
||||
lf_printf(file, "#ifdef HAVE_STDLIB_H\n");
|
||||
lf_printf(file, "#include <stdlib.h>\n");
|
||||
lf_printf(file, "#endif\n");
|
||||
lf_printf(file, "\n");
|
||||
|
||||
for(insn_ptr = model_data; insn_ptr; insn_ptr = insn_ptr->next) {
|
||||
model_c_or_h_data(table, file, insn_ptr->file_entry);
|
||||
}
|
||||
|
||||
for(insn_ptr = model_static; insn_ptr; insn_ptr = insn_ptr->next) {
|
||||
model_c_or_h_function(table, file, insn_ptr->file_entry, "/*h*/STATIC");
|
||||
}
|
||||
|
||||
for(insn_ptr = model_internal; insn_ptr; insn_ptr = insn_ptr->next) {
|
||||
model_c_or_h_function(table, file, insn_ptr->file_entry, "STATIC_INLINE_MODEL");
|
||||
}
|
||||
|
||||
for(insn_ptr = model_static; insn_ptr; insn_ptr = insn_ptr->next) {
|
||||
model_c_function(table, file, insn_ptr->file_entry, "/*c*/STATIC");
|
||||
}
|
||||
|
||||
for(insn_ptr = model_internal; insn_ptr; insn_ptr = insn_ptr->next) {
|
||||
model_c_function(table, file, insn_ptr->file_entry, "STATIC_INLINE_MODEL");
|
||||
}
|
||||
|
||||
for(insn_ptr = model_functions; insn_ptr; insn_ptr = insn_ptr->next) {
|
||||
model_c_function(table, file, insn_ptr->file_entry, "INLINE_MODEL");
|
||||
name = insn_ptr->file_entry->fields[function_name];
|
||||
if (strcmp (name, "model_create") == 0)
|
||||
model_create_p = 1;
|
||||
else if (strcmp (name, "model_init") == 0)
|
||||
model_init_p = 1;
|
||||
else if (strcmp (name, "model_halt") == 0)
|
||||
model_halt_p = 1;
|
||||
else if (strcmp (name, "model_mon_info") == 0)
|
||||
model_mon_info_p = 1;
|
||||
else if (strcmp (name, "model_mon_info_free") == 0)
|
||||
model_mon_info_free_p = 1;
|
||||
}
|
||||
|
||||
if (!model_create_p) {
|
||||
lf_print_function_type(file, "model_data *", "INLINE_MODEL", "\n");
|
||||
lf_printf(file, "model_create(cpu *processor)\n");
|
||||
lf_printf(file, "{\n");
|
||||
lf_printf(file, " return (model_data *)0;\n");
|
||||
lf_printf(file, "}\n");
|
||||
lf_printf(file, "\n");
|
||||
}
|
||||
|
||||
if (!model_init_p) {
|
||||
lf_print_function_type(file, "void", "INLINE_MODEL", "\n");
|
||||
lf_printf(file, "model_init(model_data *model_ptr)\n");
|
||||
lf_printf(file, "{\n");
|
||||
lf_printf(file, "}\n");
|
||||
lf_printf(file, "\n");
|
||||
}
|
||||
|
||||
if (!model_halt_p) {
|
||||
lf_print_function_type(file, "void", "INLINE_MODEL", "\n");
|
||||
lf_printf(file, "model_halt(model_data *model_ptr)\n");
|
||||
lf_printf(file, "{\n");
|
||||
lf_printf(file, "}\n");
|
||||
lf_printf(file, "\n");
|
||||
}
|
||||
|
||||
if (!model_mon_info_p) {
|
||||
lf_print_function_type(file, "model_print *", "INLINE_MODEL", "\n");
|
||||
lf_printf(file, "model_mon_info(model_data *model_ptr)\n");
|
||||
lf_printf(file, "{\n");
|
||||
lf_printf(file, " return (model_print *)0;\n");
|
||||
lf_printf(file, "}\n");
|
||||
lf_printf(file, "\n");
|
||||
}
|
||||
|
||||
if (!model_mon_info_free_p) {
|
||||
lf_print_function_type(file, "void", "INLINE_MODEL", "\n");
|
||||
lf_printf(file, "model_mon_info_free(model_data *model_ptr,\n");
|
||||
lf_printf(file, " model_print *info_ptr)\n");
|
||||
lf_printf(file, "{\n");
|
||||
lf_printf(file, "}\n");
|
||||
lf_printf(file, "\n");
|
||||
}
|
||||
|
||||
lf_printf(file, "/* Insn functional unit info */\n");
|
||||
for(model_ptr = models; model_ptr; model_ptr = model_ptr->next) {
|
||||
model_c_passed_data data;
|
||||
|
||||
lf_printf(file, "static const model_time model_time_%s[] = {\n", model_ptr->name);
|
||||
data.file = file;
|
||||
data.model_ptr = model_ptr;
|
||||
insn_table_traverse_insn(table,
|
||||
NULL, (void *)&data,
|
||||
model_c_insn);
|
||||
|
||||
lf_printf(file, "};\n");
|
||||
lf_printf(file, "\n");
|
||||
lf_printf(file, "\f\n");
|
||||
}
|
||||
|
||||
lf_printf(file, "#ifndef _INLINE_C_\n");
|
||||
lf_printf(file, "const model_time *const model_time_mapping[ (int)nr_models ] = {\n");
|
||||
lf_printf(file, " (const model_time *const)0,\n");
|
||||
for(model_ptr = models; model_ptr; model_ptr = model_ptr->next) {
|
||||
lf_printf(file, " model_time_%s,\n", model_ptr->name);
|
||||
}
|
||||
lf_printf(file, "};\n");
|
||||
lf_printf(file, "#endif\n");
|
||||
lf_printf(file, "\n");
|
||||
|
||||
lf_printf(file, "\f\n");
|
||||
lf_printf(file, "/* map model enumeration into printable string */\n");
|
||||
lf_printf(file, "#ifndef _INLINE_C_\n");
|
||||
lf_printf(file, "const char *model_name[ (int)nr_models ] = {\n");
|
||||
lf_printf(file, " \"NONE\",\n");
|
||||
for (model_ptr = models; model_ptr; model_ptr = model_ptr->next) {
|
||||
lf_printf(file, " \"%s\",\n", model_ptr->printable_name);
|
||||
}
|
||||
lf_printf(file, "};\n");
|
||||
lf_printf(file, "#endif\n");
|
||||
lf_printf(file, "\n");
|
||||
|
||||
lf_print_function_type(file, "void", "INLINE_MODEL", "\n");
|
||||
lf_printf(file, "model_set(const char *name)\n");
|
||||
lf_printf(file, "{\n");
|
||||
if (models) {
|
||||
lf_printf(file, " model_enum model;\n");
|
||||
lf_printf(file, " for(model = MODEL_%s; model < nr_models; model++) {\n", models->name);
|
||||
lf_printf(file, " if(strcmp(name, model_name[model]) == 0) {\n");
|
||||
lf_printf(file, " current_model = model;\n");
|
||||
lf_printf(file, " return;\n");
|
||||
lf_printf(file, " }\n");
|
||||
lf_printf(file, " }\n");
|
||||
lf_printf(file, "\n");
|
||||
lf_printf(file, " error(\"Unknown model '%%s', Models which are known are:%%s\n\",\n");
|
||||
lf_printf(file, " name,\n");
|
||||
lf_printf(file, " \"");
|
||||
for(model_ptr = models; model_ptr; model_ptr = model_ptr->next) {
|
||||
lf_printf(file, "\\n\\t%s", model_ptr->printable_name);
|
||||
}
|
||||
lf_printf(file, "\");\n");
|
||||
} else {
|
||||
lf_printf(file, " error(\"No models are currently known about\");\n");
|
||||
}
|
||||
|
||||
lf_printf(file, "}\n");
|
||||
}
|
||||
|
30
sim/igen/gen-model.h
Normal file
30
sim/igen/gen-model.h
Normal file
@ -0,0 +1,30 @@
|
||||
/* This file is part of the program psim.
|
||||
|
||||
Copyright (C) 1994-1995, Andrew Cagney <cagney@highland.com.au>
|
||||
|
||||
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.
|
||||
|
||||
*/
|
||||
|
||||
|
||||
|
||||
extern void gen_model_h
|
||||
(insn_table *table,
|
||||
lf *file);
|
||||
|
||||
|
||||
extern void gen_model_c
|
||||
(insn_table *table,
|
||||
lf *file);
|
81
sim/igen/gen-semantics.h
Normal file
81
sim/igen/gen-semantics.h
Normal file
@ -0,0 +1,81 @@
|
||||
/* This file is part of the program psim.
|
||||
|
||||
Copyright (C) 1994-1995, Andrew Cagney <cagney@highland.com.au>
|
||||
|
||||
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.
|
||||
|
||||
*/
|
||||
|
||||
|
||||
/* Creates the files semantics.[hc].
|
||||
|
||||
The generated file semantics contains functions that implement the
|
||||
operations required to model a single target processor instruction.
|
||||
|
||||
Several different variations on the semantics file can be created:
|
||||
|
||||
o uncached
|
||||
|
||||
No instruction cache exists. The semantic function
|
||||
needs to generate any required values locally.
|
||||
|
||||
o cached - separate cracker and semantic
|
||||
|
||||
Two independant functions are created. Firstly the
|
||||
function that cracks an instruction entering it into a
|
||||
cache and secondly the semantic function propper that
|
||||
uses the cache.
|
||||
|
||||
o cached - semantic + cracking semantic
|
||||
|
||||
The function that cracks the instruction and enters
|
||||
all values into the cache also contains a copy of the
|
||||
semantic code (avoiding the need to call both the
|
||||
cracker and the semantic function when there is a
|
||||
cache miss).
|
||||
|
||||
For each of these general forms, several refinements can occure:
|
||||
|
||||
o do/don't duplicate/expand semantic functions
|
||||
|
||||
As a consequence of decoding an instruction, the
|
||||
decoder, as part of its table may have effectivly made
|
||||
certain of the variable fields in an instruction
|
||||
constant. Separate functions for each of the
|
||||
alternative values for what would have been treated as
|
||||
a variable part can be created.
|
||||
|
||||
o use cache struct directly.
|
||||
|
||||
When a cracking cache is present, the semantic
|
||||
functions can be generated to either hold intermediate
|
||||
cache values in local variables or always refer to the
|
||||
contents of the cache directly. */
|
||||
|
||||
|
||||
|
||||
extern insn_handler print_semantic_declaration;
|
||||
extern insn_handler print_semantic_definition;
|
||||
|
||||
extern void print_idecode_illegal
|
||||
(lf *file,
|
||||
const char *result);
|
||||
|
||||
extern void print_semantic_body
|
||||
(lf *file,
|
||||
insn *instruction,
|
||||
insn_bits *expanded_bits,
|
||||
opcode_field *opcodes);
|
||||
|
29
sim/igen/gen-support.h
Normal file
29
sim/igen/gen-support.h
Normal file
@ -0,0 +1,29 @@
|
||||
/* This file is part of the program psim.
|
||||
|
||||
Copyright (C) 1994-1995, Andrew Cagney <cagney@highland.com.au>
|
||||
|
||||
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.
|
||||
|
||||
*/
|
||||
|
||||
|
||||
extern void gen_support_h
|
||||
(insn_table *table,
|
||||
lf *file);
|
||||
|
||||
extern void gen_support_c
|
||||
(insn_table *table,
|
||||
lf *file);
|
||||
|
115
sim/igen/ld-cache.c
Normal file
115
sim/igen/ld-cache.c
Normal file
@ -0,0 +1,115 @@
|
||||
/* This file is part of the program psim.
|
||||
|
||||
Copyright (C) 1994,1995,1996, Andrew Cagney <cagney@highland.com.au>
|
||||
|
||||
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.
|
||||
|
||||
*/
|
||||
|
||||
|
||||
#include "misc.h"
|
||||
#include "lf.h"
|
||||
#include "table.h"
|
||||
#include "ld-cache.h"
|
||||
|
||||
#ifndef NULL
|
||||
#define NULL 0
|
||||
#endif
|
||||
|
||||
|
||||
enum {
|
||||
ca_type,
|
||||
ca_field_name,
|
||||
ca_derived_name,
|
||||
ca_type_def,
|
||||
ca_expression,
|
||||
nr_cache_rule_fields,
|
||||
};
|
||||
|
||||
static const name_map cache_type_map[] = {
|
||||
{ "cache", cache_value },
|
||||
{ "compute", compute_value },
|
||||
{ "scratch", scratch_value },
|
||||
{ NULL, 0 },
|
||||
};
|
||||
|
||||
|
||||
cache_table *
|
||||
load_cache_table(char *file_name,
|
||||
int hi_bit_nr)
|
||||
{
|
||||
table *file = table_open(file_name, nr_cache_rule_fields, 0);
|
||||
table_entry *entry;
|
||||
cache_table *table = NULL;
|
||||
cache_table **curr_rule = &table;
|
||||
while ((entry = table_entry_read(file)) != NULL) {
|
||||
cache_table *new_rule = ZALLOC(cache_table);
|
||||
new_rule->type = name2i(entry->fields[ca_type], cache_type_map);
|
||||
new_rule->field_name = entry->fields[ca_field_name];
|
||||
new_rule->derived_name = entry->fields[ca_derived_name];
|
||||
new_rule->type_def = (strlen(entry->fields[ca_type_def])
|
||||
? entry->fields[ca_type_def]
|
||||
: NULL);
|
||||
new_rule->expression = (strlen(entry->fields[ca_expression]) > 0
|
||||
? entry->fields[ca_expression]
|
||||
: NULL);
|
||||
new_rule->file_entry = entry;
|
||||
*curr_rule = new_rule;
|
||||
curr_rule = &new_rule->next;
|
||||
}
|
||||
return table;
|
||||
}
|
||||
|
||||
|
||||
|
||||
#ifdef MAIN
|
||||
|
||||
static void
|
||||
dump_cache_rule(cache_table* rule,
|
||||
int indent)
|
||||
{
|
||||
dumpf(indent, "((cache_table*)0x%x\n", rule);
|
||||
dumpf(indent, " (type %s)\n", i2name(rule->type, cache_type_map));
|
||||
dumpf(indent, " (field_name \"%s\")\n", rule->field_name);
|
||||
dumpf(indent, " (derived_name \"%s\")\n", rule->derived_name);
|
||||
dumpf(indent, " (type-def \"%s\")\n", rule->type_def);
|
||||
dumpf(indent, " (expression \"%s\")\n", rule->expression);
|
||||
dumpf(indent, " (next 0x%x)\n", rule->next);
|
||||
dumpf(indent, " )\n");
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
dump_cache_rules(cache_table* rule,
|
||||
int indent)
|
||||
{
|
||||
while (rule) {
|
||||
dump_cache_rule(rule, indent);
|
||||
rule = rule->next;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
int
|
||||
main(int argc, char **argv)
|
||||
{
|
||||
cache_table *rules;
|
||||
if (argc != 3)
|
||||
error("Usage: cache <cache-file> <hi-bit-nr>\n");
|
||||
rules = load_cache_table(argv[1], a2i(argv[2]));
|
||||
dump_cache_rules(rules, 0);
|
||||
return 0;
|
||||
}
|
||||
#endif
|
81
sim/igen/ld-cache.h
Normal file
81
sim/igen/ld-cache.h
Normal file
@ -0,0 +1,81 @@
|
||||
/* This file is part of the program psim.
|
||||
|
||||
Copyright (C) 1994,1995,1996, Andrew Cagney <cagney@highland.com.au>
|
||||
|
||||
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.
|
||||
|
||||
*/
|
||||
|
||||
/* Instruction unpacking:
|
||||
|
||||
Once the instruction has been decoded, the register (and other)
|
||||
fields within the instruction need to be extracted.
|
||||
|
||||
The table that follows determines how each field should be treated.
|
||||
Importantly it considers the case where the extracted field is to
|
||||
be used immediatly or stored in an instruction cache.
|
||||
|
||||
<type>
|
||||
|
||||
Indicates what to do with the cache entry. If a cache is to be
|
||||
used. SCRATCH and CACHE values are defined when a cache entry is
|
||||
being filled while CACHE and COMPUTE values are defined in the
|
||||
semantic code.
|
||||
|
||||
Zero marks the end of the table. More importantly 1. indicates
|
||||
that the entry is valid and can be cached. 2. indicates that that
|
||||
the entry is valid but can not be cached.
|
||||
|
||||
<field_name>
|
||||
|
||||
The field name as given in the instruction spec.
|
||||
|
||||
<derived_name>
|
||||
|
||||
A new name for <field_name> once it has been extracted from the
|
||||
instruction (and possibly stored in the instruction cache).
|
||||
|
||||
<type>
|
||||
|
||||
String specifying the storage type for <new_name> (the extracted
|
||||
field>.
|
||||
|
||||
<expression>
|
||||
|
||||
Specifies how to get <new_name> from <old_name>. If null, old and
|
||||
new name had better be the same. */
|
||||
|
||||
|
||||
typedef enum {
|
||||
scratch_value,
|
||||
cache_value,
|
||||
compute_value,
|
||||
} cache_rule_type;
|
||||
|
||||
typedef struct _cache_table cache_table;
|
||||
struct _cache_table {
|
||||
cache_rule_type type;
|
||||
char *field_name;
|
||||
char *derived_name;
|
||||
char *type_def;
|
||||
char *expression;
|
||||
table_entry *file_entry;
|
||||
cache_table *next;
|
||||
};
|
||||
|
||||
|
||||
extern cache_table *load_cache_table
|
||||
(char *file_name,
|
||||
int hi_bit_nr);
|
155
sim/igen/ld-decode.c
Normal file
155
sim/igen/ld-decode.c
Normal file
@ -0,0 +1,155 @@
|
||||
/* This file is part of the program psim.
|
||||
|
||||
Copyright (C) 1994,1995,1996, Andrew Cagney <cagney@highland.com.au>
|
||||
|
||||
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.
|
||||
|
||||
*/
|
||||
|
||||
/* load the opcode stat structure */
|
||||
|
||||
#include "misc.h"
|
||||
#include "lf.h"
|
||||
#include "table.h"
|
||||
#include "ld-decode.h"
|
||||
|
||||
#ifndef NULL
|
||||
#define NULL 0
|
||||
#endif
|
||||
|
||||
enum {
|
||||
op_options,
|
||||
op_first,
|
||||
op_last,
|
||||
op_force_first,
|
||||
op_force_last,
|
||||
op_force_expansion,
|
||||
op_special_mask,
|
||||
op_special_value,
|
||||
op_special_constant,
|
||||
nr_decode_fields,
|
||||
};
|
||||
|
||||
static const name_map decode_type_map[] = {
|
||||
{ "normal", normal_decode_rule },
|
||||
{ "expand-forced", expand_forced_rule },
|
||||
{ "boolean", boolean_rule },
|
||||
{ NULL, normal_decode_rule },
|
||||
};
|
||||
|
||||
static const name_map decode_gen_map[] = {
|
||||
{ "array", array_gen },
|
||||
{ "switch", switch_gen },
|
||||
{ "padded-switch", padded_switch_gen },
|
||||
{ "goto-switch", goto_switch_gen },
|
||||
{ NULL, -1 },
|
||||
};
|
||||
|
||||
static const name_map decode_slash_map[] = {
|
||||
{ "variable-slash", 0 },
|
||||
{ "constant-slash", 1 },
|
||||
{ NULL },
|
||||
};
|
||||
|
||||
|
||||
static decode_gen_type overriding_gen_type = invalid_gen;
|
||||
|
||||
void
|
||||
force_decode_gen_type(const char *type)
|
||||
{
|
||||
overriding_gen_type = name2i(type, decode_gen_map);
|
||||
}
|
||||
|
||||
|
||||
decode_table *
|
||||
load_decode_table(char *file_name,
|
||||
int hi_bit_nr)
|
||||
{
|
||||
table *file = table_open(file_name, nr_decode_fields, 0);
|
||||
table_entry *entry;
|
||||
decode_table *table = NULL;
|
||||
decode_table **curr_rule = &table;
|
||||
while ((entry = table_entry_read(file)) != NULL) {
|
||||
decode_table *new_rule = ZALLOC(decode_table);
|
||||
new_rule->type = name2i(entry->fields[op_options], decode_type_map);
|
||||
new_rule->gen = (overriding_gen_type != invalid_gen
|
||||
? overriding_gen_type
|
||||
: name2i(entry->fields[op_options], decode_gen_map));
|
||||
new_rule->force_slash = name2i(entry->fields[op_options], decode_slash_map);
|
||||
new_rule->first = target_a2i(hi_bit_nr, entry->fields[op_first]);
|
||||
new_rule->last = target_a2i(hi_bit_nr, entry->fields[op_last]);
|
||||
new_rule->force_first = (strlen(entry->fields[op_force_first])
|
||||
? target_a2i(hi_bit_nr, entry->fields[op_force_first])
|
||||
: new_rule->last + 1);
|
||||
new_rule->force_last = (strlen(entry->fields[op_force_last])
|
||||
? target_a2i(hi_bit_nr, entry->fields[op_force_last])
|
||||
: new_rule->first - 1);
|
||||
new_rule->force_expansion = entry->fields[op_force_expansion];
|
||||
new_rule->special_mask = a2i(entry->fields[op_special_mask]);
|
||||
new_rule->special_value = a2i(entry->fields[op_special_value]);
|
||||
new_rule->special_constant = a2i(entry->fields[op_special_constant]);
|
||||
*curr_rule = new_rule;
|
||||
curr_rule = &new_rule->next;
|
||||
}
|
||||
return table;
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
dump_decode_rule(decode_table *rule,
|
||||
int indent)
|
||||
{
|
||||
dumpf(indent, "((decode_table*)%p\n", rule);
|
||||
if (rule) {
|
||||
dumpf(indent, " (type %s)\n", i2name(rule->type, decode_type_map));
|
||||
dumpf(indent, " (gen %s)\n", i2name(rule->gen, decode_gen_map));
|
||||
dumpf(indent, " (force_slash %d)\n", rule->force_slash);
|
||||
dumpf(indent, " (first %d)\n", rule->first);
|
||||
dumpf(indent, " (last %d)\n", rule->last);
|
||||
dumpf(indent, " (force_first %d)\n", rule->force_first);
|
||||
dumpf(indent, " (force_last %d)\n", rule->force_last);
|
||||
dumpf(indent, " (force_expansion \"%s\")\n", rule->force_expansion);
|
||||
dumpf(indent, " (special_mask 0x%x)\n", rule->special_mask);
|
||||
dumpf(indent, " (special_value 0x%x)\n", rule->special_value);
|
||||
dumpf(indent, " (special_constant 0x%x)\n", rule->special_constant);
|
||||
dumpf(indent, " (next 0x%x)\n", rule->next);
|
||||
}
|
||||
dumpf(indent, " )\n");
|
||||
}
|
||||
|
||||
|
||||
#ifdef MAIN
|
||||
|
||||
static void
|
||||
dump_decode_rules(decode_table *rule,
|
||||
int indent)
|
||||
{
|
||||
while (rule) {
|
||||
dump_decode_rule(rule, indent);
|
||||
rule = rule->next;
|
||||
}
|
||||
}
|
||||
|
||||
int
|
||||
main(int argc, char **argv)
|
||||
{
|
||||
decode_table *rules;
|
||||
if (argc != 3)
|
||||
error("Usage: decode <decode-file> <hi-bit-nr>\n");
|
||||
rules = load_decode_table(argv[1], a2i(argv[2]));
|
||||
dump_decode_rules(rules, 0);
|
||||
return 0;
|
||||
}
|
||||
#endif
|
143
sim/igen/ld-decode.h
Normal file
143
sim/igen/ld-decode.h
Normal file
@ -0,0 +1,143 @@
|
||||
/* This file is part of the program psim.
|
||||
|
||||
Copyright (C) 1994,1995,1996, Andrew Cagney <cagney@highland.com.au>
|
||||
|
||||
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.
|
||||
|
||||
*/
|
||||
|
||||
/* Instruction decode table:
|
||||
|
||||
<options>:<first>:<last>:<force-first>:<force-last>:<force-expand>:<special>...
|
||||
|
||||
|
||||
|
||||
Ignore the below:
|
||||
|
||||
|
||||
The instruction decode table contains rules that dictate how igen
|
||||
is going to firstly break down the opcode table and secondly
|
||||
|
||||
The table that follows is used by gen to construct a decision tree
|
||||
that can identify each possible instruction. Gen then outputs this
|
||||
decision tree as (according to config) a table or switch statement
|
||||
as the function idecode.
|
||||
|
||||
In parallel to this, as mentioned above, WITH_EXPANDED_SEMANTICS
|
||||
determines of the semantic functions themselves should be expanded
|
||||
in a similar way.
|
||||
|
||||
<first>
|
||||
<last>
|
||||
|
||||
Range of bits (within the instruction) that should be searched for
|
||||
an instruction field. Within such ranges, gen looks for opcodes
|
||||
(constants), registers (strings) and reserved bits (slash) and
|
||||
according to the rules that follows includes or excludes them from
|
||||
a possible instruction field.
|
||||
|
||||
<force_first>
|
||||
<force_last>
|
||||
|
||||
If an instruction field was found, enlarge the field size so that
|
||||
it is forced to at least include bits starting from <force_first>
|
||||
(<force_last>). To stop this occuring, use <force_first> = <last>
|
||||
+ 1 and <force_last> = <first> - 1.
|
||||
|
||||
<force_slash>
|
||||
|
||||
Treat `/' fields as a constant instead of variable when looking for
|
||||
an instruction field.
|
||||
|
||||
<force_expansion>
|
||||
|
||||
Treat any contained register (string) fields as constant when
|
||||
determining the instruction field. For the instruction decode (and
|
||||
controled by IDECODE_EXPAND_SEMANTICS) this forces the expansion of
|
||||
what would otherwize be non constant bits of an instruction.
|
||||
|
||||
<use_switch>
|
||||
|
||||
Should this table be expanded using a switch statement (val 1) and
|
||||
if so, should it be padded with entries so as to force the compiler
|
||||
to generate a jump table (val 2). Or a branch table (val 3).
|
||||
|
||||
<special_mask>
|
||||
<special_value>
|
||||
<special_rule>
|
||||
<special_constant>
|
||||
|
||||
Special rule to fine tune how specific (or groups) of instructions
|
||||
are expanded. The applicability of the rule is determined by
|
||||
|
||||
<special_mask> != 0 && (instruction> & <special_mask>) == <special_value>
|
||||
|
||||
Where <instruction> is obtained by looking only at constant fields
|
||||
with in an instructions spec. When determining an expansion, the
|
||||
rule is only considered when a node contains a single instruction.
|
||||
<special_rule> can be any of:
|
||||
|
||||
0: for this instruction, expand by earlier rules
|
||||
1: expand bits <force_low> .. <force_hi> only
|
||||
2: boolean expansion of only zero/non-zero cases
|
||||
3: boolean expansion of equality of special constant
|
||||
|
||||
*/
|
||||
|
||||
|
||||
typedef enum {
|
||||
normal_decode_rule,
|
||||
expand_forced_rule,
|
||||
boolean_rule,
|
||||
nr_decode_rules
|
||||
} decode_special_type;
|
||||
|
||||
typedef enum {
|
||||
invalid_gen,
|
||||
array_gen,
|
||||
switch_gen,
|
||||
padded_switch_gen,
|
||||
goto_switch_gen,
|
||||
nr_decode_gen_types,
|
||||
} decode_gen_type;
|
||||
|
||||
|
||||
typedef struct _decode_table decode_table;
|
||||
struct _decode_table {
|
||||
decode_special_type type;
|
||||
decode_gen_type gen;
|
||||
int first;
|
||||
int last;
|
||||
int force_first;
|
||||
int force_last;
|
||||
int force_slash;
|
||||
char *force_expansion;
|
||||
unsigned special_mask;
|
||||
unsigned special_value;
|
||||
unsigned special_constant;
|
||||
decode_table *next;
|
||||
};
|
||||
|
||||
|
||||
extern void force_decode_gen_type
|
||||
(const char *type);
|
||||
|
||||
extern decode_table *load_decode_table
|
||||
(char *file_name,
|
||||
int hi_bit_nr);
|
||||
|
||||
extern void dump_decode_rule
|
||||
(decode_table *rule,
|
||||
int indent);
|
226
sim/igen/misc.c
Normal file
226
sim/igen/misc.c
Normal file
@ -0,0 +1,226 @@
|
||||
/* This file is part of the program psim.
|
||||
|
||||
Copyright (C) 1994-1995, Andrew Cagney <cagney@highland.com.au>
|
||||
|
||||
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.
|
||||
|
||||
*/
|
||||
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdarg.h>
|
||||
#include <ctype.h>
|
||||
|
||||
#include "config.h"
|
||||
#include "misc.h"
|
||||
|
||||
#ifdef HAVE_STDLIB_H
|
||||
#include <stdlib.h>
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_STRING_H
|
||||
#include <string.h>
|
||||
#else
|
||||
#ifdef HAVE_STRINGS_H
|
||||
#include <strings.h>
|
||||
#endif
|
||||
#endif
|
||||
|
||||
void
|
||||
error (char *msg, ...)
|
||||
{
|
||||
va_list ap;
|
||||
va_start(ap, msg);
|
||||
vprintf(msg, ap);
|
||||
va_end(ap);
|
||||
exit (1);
|
||||
}
|
||||
|
||||
void *
|
||||
zalloc(long size)
|
||||
{
|
||||
void *memory = malloc(size);
|
||||
if (memory == NULL)
|
||||
error("zalloc failed\n");
|
||||
memset(memory, 0, size);
|
||||
return memory;
|
||||
}
|
||||
|
||||
void
|
||||
dumpf (int indent, char *msg, ...)
|
||||
{
|
||||
va_list ap;
|
||||
for (; indent > 0; indent--)
|
||||
printf(" ");
|
||||
va_start(ap, msg);
|
||||
vprintf(msg, ap);
|
||||
va_end(ap);
|
||||
}
|
||||
|
||||
|
||||
unsigned long long
|
||||
a2i(const char *a)
|
||||
{
|
||||
int neg = 0;
|
||||
int base = 10;
|
||||
unsigned long long num = 0;
|
||||
int looping;
|
||||
|
||||
while (isspace (*a))
|
||||
a++;
|
||||
|
||||
if (*a == '-') {
|
||||
neg = 1;
|
||||
a++;
|
||||
}
|
||||
|
||||
if (*a == '0') {
|
||||
if (a[1] == 'x' || a[1] == 'X') {
|
||||
a += 2;
|
||||
base = 16;
|
||||
} else if (a[1] == 'b' || a[1] == 'b') {
|
||||
a += 2;
|
||||
base = 2;
|
||||
}
|
||||
else
|
||||
base = 8;
|
||||
}
|
||||
|
||||
looping = 1;
|
||||
while (looping) {
|
||||
int ch = *a++;
|
||||
|
||||
switch (base) {
|
||||
default:
|
||||
looping = 0;
|
||||
break;
|
||||
|
||||
case 2:
|
||||
if (ch >= '0' && ch <= '1') {
|
||||
num = (num * 2) + (ch - '0');
|
||||
} else {
|
||||
looping = 0;
|
||||
}
|
||||
break;
|
||||
|
||||
case 10:
|
||||
if (ch >= '0' && ch <= '9') {
|
||||
num = (num * 10) + (ch - '0');
|
||||
} else {
|
||||
looping = 0;
|
||||
}
|
||||
break;
|
||||
|
||||
case 8:
|
||||
if (ch >= '0' && ch <= '7') {
|
||||
num = (num * 8) + (ch - '0');
|
||||
} else {
|
||||
looping = 0;
|
||||
}
|
||||
break;
|
||||
|
||||
case 16:
|
||||
if (ch >= '0' && ch <= '9') {
|
||||
num = (num * 16) + (ch - '0');
|
||||
} else if (ch >= 'a' && ch <= 'f') {
|
||||
num = (num * 16) + (ch - 'a' + 10);
|
||||
} else if (ch >= 'A' && ch <= 'F') {
|
||||
num = (num * 16) + (ch - 'A' + 10);
|
||||
} else {
|
||||
looping = 0;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (neg)
|
||||
num = - num;
|
||||
|
||||
return num;
|
||||
}
|
||||
|
||||
unsigned
|
||||
target_a2i(int ms_bit_nr,
|
||||
const char *a)
|
||||
{
|
||||
if (ms_bit_nr)
|
||||
return (ms_bit_nr - a2i(a));
|
||||
else
|
||||
return a2i(a);
|
||||
}
|
||||
|
||||
unsigned
|
||||
i2target(int ms_bit_nr,
|
||||
unsigned bit)
|
||||
{
|
||||
if (ms_bit_nr)
|
||||
return ms_bit_nr - bit;
|
||||
else
|
||||
return bit;
|
||||
}
|
||||
|
||||
|
||||
int
|
||||
name2i(const char *names,
|
||||
const name_map *map)
|
||||
{
|
||||
const name_map *curr;
|
||||
const char *name = names;
|
||||
while (*name != '\0') {
|
||||
/* find our name */
|
||||
char *end = strchr(name, ',');
|
||||
char *next;
|
||||
int len;
|
||||
if (end == NULL) {
|
||||
end = strchr(name, '\0');
|
||||
next = end;
|
||||
}
|
||||
else {
|
||||
next = end + 1;
|
||||
}
|
||||
len = end - name;
|
||||
/* look it up */
|
||||
curr = map;
|
||||
while (curr->name != NULL) {
|
||||
if (strncmp(curr->name, name, len) == 0
|
||||
&& strlen(curr->name) == len)
|
||||
return curr->i;
|
||||
curr++;
|
||||
}
|
||||
name = next;
|
||||
}
|
||||
/* nothing found, possibly return a default */
|
||||
curr = map;
|
||||
while (curr->name != NULL)
|
||||
curr++;
|
||||
if (curr->i >= 0)
|
||||
return curr->i;
|
||||
else
|
||||
error("%s contains no valid names\n", names);
|
||||
return 0;
|
||||
}
|
||||
|
||||
const char *
|
||||
i2name(const int i,
|
||||
const name_map *map)
|
||||
{
|
||||
while (map->name != NULL) {
|
||||
if (map->i == i)
|
||||
return map->name;
|
||||
map++;
|
||||
}
|
||||
error("map lookup failed for %d\n", i);
|
||||
return NULL;
|
||||
}
|
94
sim/igen/misc.h
Normal file
94
sim/igen/misc.h
Normal file
@ -0,0 +1,94 @@
|
||||
/* This file is part of the program psim.
|
||||
|
||||
Copyright (C) 1994-1995, Andrew Cagney <cagney@highland.com.au>
|
||||
|
||||
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.
|
||||
|
||||
*/
|
||||
|
||||
|
||||
/* Frustrating header junk */
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#include <stdio.h>
|
||||
#include <ctype.h>
|
||||
|
||||
#ifdef HAVE_STRING_H
|
||||
#include <string.h>
|
||||
#else
|
||||
#ifdef HAVE_STRINGS_H
|
||||
#include <strings.h>
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_STDLIB_H
|
||||
#include <stdlib.h>
|
||||
#endif
|
||||
|
||||
#if !defined (__attribute__) && (!defined(__GNUC__) || __GNUC__ < 2 || (__GNUC__ == 2 && __GNUC_MINOR__ < 7))
|
||||
#define __attribute__(arg)
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
#include "filter_host.h"
|
||||
|
||||
extern void error
|
||||
(char *msg, ...);
|
||||
|
||||
#define ASSERT(EXPRESSION) \
|
||||
do { \
|
||||
if (!(EXPRESSION)) { \
|
||||
error("%s:%d: assertion failed - %s\n", \
|
||||
filter_filename (__FILE__), __LINE__, #EXPRESSION); \
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
#define ZALLOC(TYPE) (TYPE*)zalloc(sizeof(TYPE))
|
||||
|
||||
extern void *zalloc
|
||||
(long size);
|
||||
|
||||
extern void dumpf
|
||||
(int indent, char *msg, ...);
|
||||
|
||||
extern unsigned target_a2i
|
||||
(int ms_bit_nr,
|
||||
const char *a);
|
||||
|
||||
extern unsigned i2target
|
||||
(int ms_bit_nr,
|
||||
unsigned bit);
|
||||
|
||||
extern unsigned long long a2i
|
||||
(const char *a);
|
||||
|
||||
/* Try looking for name in the map table (returning the corresponding
|
||||
integer value). If that fails, try converting the name into an
|
||||
integer */
|
||||
|
||||
typedef struct _name_map {
|
||||
const char *name;
|
||||
int i;
|
||||
} name_map;
|
||||
|
||||
extern int name2i
|
||||
(const char *name,
|
||||
const name_map *map);
|
||||
|
||||
extern const char *i2name
|
||||
(const int i,
|
||||
const name_map *map);
|
Loading…
x
Reference in New Issue
Block a user