* itbl-parse.y: Fix indentation mistakes from indent program.

* itbl-lex.l: Fix indentation mistakes from indent program.
	* itbl-ops.h: Add include for ansidecl.h.
	Add PARAMS around function arguments.
	Add declaration for itbl_have_entries.
	* itbl-ops.c: Add PARAMS around function arguments.
	* Makefile.in: Add itbl build rules.
	Add dependancies for itbl files to mips target.
	* as.c: Add itbl support.
	Add new option "--insttbl" for dynamically extending instruction set.
	* as.h: Declare insttbl_file_name;
	the name of file defining extensions to the basic instruction set
	* configure.in, configure: Add itbl-parse.o, itbl-lex.o, and
	itbl-ops.o to extra_objects for mips configuration.
	Add include file link from itbl-cpu.h to
	config/itbl-${target_cpu_type}.h.
	* config/tc-mips.c: Allow copz instructions.
	Add notes for future additions to the itbl support.
	Add debug macros.
	(macro): Call itbl_assemble to assemble itbl instructions.
	See if an unknown register is specified in an itbl entry.
This commit is contained in:
Dawn Perchik 1997-02-23 22:23:12 +00:00
parent c7583da0b6
commit efec4a282c
10 changed files with 1322 additions and 806 deletions

View File

@ -1,3 +1,27 @@
Sat Feb 22 21:25:00 1997 Dawn Perchik <dawn@cygnus.com>
* itbl-parse.y: Fix indentation mistakes from indent program.
* itbl-lex.l: Fix indentation mistakes from indent program.
* itbl-ops.h: Add include for ansidecl.h.
Add PARAMS around function arguments.
Add declaration for itbl_have_entries.
* itbl-ops.c: Add PARAMS around function arguments.
* Makefile.in: Add itbl build rules.
Add dependancies for itbl files to mips target.
* as.c: Add itbl support.
Add new option "--insttbl" for dynamically extending instruction set.
* as.h: Declare insttbl_file_name;
the name of file defining extensions to the basic instruction set
* configure.in, configure: Add itbl-parse.o, itbl-lex.o, and
itbl-ops.o to extra_objects for mips configuration.
Add include file link from itbl-cpu.h to
config/itbl-${target_cpu_type}.h.
* config/tc-mips.c: Allow copz instructions.
Add notes for future additions to the itbl support.
Add debug macros.
(macro): Call itbl_assemble to assemble itbl instructions.
See if an unknown register is specified in an itbl entry.
Sat Feb 22 20:53:01 1997 Fred Fish <fnf@cygnus.com>
* doc/internals.texi (CPU backend): Fix typo in md_section_align
description.

View File

@ -62,7 +62,7 @@ INSTALL_DATA = @INSTALL_DATA@
INSTALL_XFORM = $(INSTALL) -t='$(program_transform_name)'
INSTALL_XFORM1= $(INSTALL_XFORM) -b=.1
DISTSTUFF= make-gas.com m68k-parse.c
DISTSTUFF= make-gas.com m68k-parse.c itbl-parse.y itbl-lex.l itbl-ops.c
AR = ar
AR_FLAGS = qv
@ -72,11 +72,11 @@ MAKEINFO = makeinfo
TEXI2DVI = texi2dvi
RANLIB = ranlib
CC = @CC@
CFLAGS = -g
LDFLAGS =
HLDFLAGS = @HLDFLAGS@
HLDENV = @HLDENV@
RPATH_ENVVAR = @RPATH_ENVVAR@
CFLAGS = -g
LDFLAGS =
MAKEOVERRIDES=
@ -107,6 +107,12 @@ RUNTEST = `if [ -f $${srcdir}/../dejagnu/runtest ] ; then \
fi`
RUNTESTFLAGS=
# use @target_cpu_type@ for refering to configured target name
IT_HDRS=itbl-parse.h $(srcdir)/itbl-ops.h itbl-cpu.h
IT_SRCS=itbl-parse.c itbl-lex.c $(srcdir)/itbl-ops.c
IT_DEPS=$(srcdir)/itbl-parse.y $(srcdir)/itbl-lex.l $(srcdir)/config/itbl-@target_cpu_type@.h
IT_OBJS=itbl-parse.o itbl-lex.o itbl-ops.o
# Lists of files for various purposes.
REAL_SOURCES = \
@ -123,6 +129,7 @@ REAL_SOURCES = \
$(srcdir)/hash.c \
$(srcdir)/input-file.c \
$(srcdir)/input-scrub.c \
$(srcdir)/itbl-ops.c \
$(srcdir)/literal.c \
$(srcdir)/messages.c \
$(srcdir)/output-file.c \
@ -150,6 +157,7 @@ REAL_HEADERS = \
$(srcdir)/frags.h \
$(srcdir)/hash.h \
$(srcdir)/input-file.h \
$(srcdir)/itbl-ops.h \
$(srcdir)/listing.h \
$(srcdir)/tc.h \
$(srcdir)/obj.h \
@ -164,7 +172,8 @@ LINKED_HEADERS = \
targ-env.h \
targ-cpu.h \
obj-format.h \
atof-targ.h
atof-targ.h \
itbl-cpu.h
HEADERS = $(LINKED_HEADERS) $(REAL_HEADERS)
@ -259,7 +268,7 @@ as.new: $(OBJS) $(LIBDEPS)
$(OBJS): config.h as.h targ-env.h obj-format.h targ-cpu.h flonum.h expr.h \
struc-symbol.h write.h frags.h hash.h read.h symbols.h tc.h obj.h \
listing.h bignum.h $(srcdir)/../include/libiberty.h
listing.h bignum.h $(IT_HDRS) $(srcdir)/../include/libiberty.h
gasp.new: $(GASPOBJS) ../libiberty/libiberty.a
$(CC) $(ALL_CFLAGS) $(LDFLAGS) -o gasp.new $(GASPOBJS) ../libiberty/libiberty.a $(LOADLIBES)
@ -345,7 +354,8 @@ TARG_CPU_DEP_i960 =
TARG_CPU_DEP_m68k = $(srcdir)/../include/opcode/m68k.h \
$(srcdir)/config/m68k-parse.h subsegs.h
TARG_CPU_DEP_m88k = $(srcdir)/config/m88k-opcode.h subsegs.h
TARG_CPU_DEP_mips = $(srcdir)/../include/opcode/mips.h subsegs.h
TARG_CPU_DEP_mips = $(srcdir)/../include/opcode/mips.h subsegs.h \
$(srcdir)/config/itbl-mips.h
TARG_CPU_DEP_ns32k =
TARG_CPU_DEP_ppc = subsegs.h
TARG_CPU_DEP_sh = $(srcdir)/../opcodes/sh-opc.h subsegs.h
@ -388,7 +398,7 @@ ecoff.o : ecoff.c ecoff.h \
stabs.o : stabs.c subsegs.h $(srcdir)/../include/aout/stab_gnu.h
atof-targ.o : atof-targ.c
obj-format.o : obj-format.c
targ-cpu.o : targ-cpu.c $(TARG_CPU_DEP_@target_cpu_type@)
targ-cpu.o : targ-cpu.c $(TARG_CPU_DEP_@target_cpu_type@) $(IT_HDRS)
obj-elf.o : $(srcdir)/config/obj-elf.c
$(CC) -c $(ALL_CFLAGS) $(CPPFLAGS) $(INCLUDES) $(srcdir)/config/obj-elf.c
@ -407,6 +417,51 @@ m68k-parse.c: $(srcdir)/config/m68k-parse.y
mv -f y.tab.c m68k-parse.c
m68k-parse.o: m68k-parse.c $(srcdir)/config/m68k-parse.h
# The instruction table specification lexical analyzer and parser.
itbl-cpu.h : $(srcdir)/config/itbl-@target_cpu_type@.h
itbl-parse.h : $(srcdir)/itbl-parse.y
itbl-parse.c : $(srcdir)/itbl-parse.y
itbl-lex.c : $(srcdir)/itbl-lex.l
itbl-lex.c: $(srcdir)/itbl-lex.l
$(LEX) $(LEXFLAGS) $(srcdir)/itbl-lex.l
mv -f lex.yy.c itbl-lex.c
itbl-lex.o: itbl-lex.c
$(CC) -Wall -c $(ALL_CFLAGS) $(CPPFLAGS) $(INCLUDES) itbl-lex.c
itbl-parse.c itbl-parse.h: $(srcdir)/itbl-parse.y
$(YACC) -d $(YACCFLAGS) $(srcdir)/itbl-parse.y
mv -f y.tab.c itbl-parse.c
mv -f y.tab.h itbl-parse.h
itbl-parse.o: itbl-parse.c itbl-parse.h $(srcdir)/itbl-ops.h itbl-cpu.h
$(CC) -Wall -c $(ALL_CFLAGS) $(CPPFLAGS) $(INCLUDES) itbl-parse.c
itbl-ops.o: $(srcdir)/itbl-ops.c \
$(srcdir)/itbl-ops.h itbl-cpu.h itbl-parse.h
$(CC) -c $(ALL_CFLAGS) $(CPPFLAGS) $(INCLUDES) $(srcdir)/itbl-ops.c
# stand-alone assembler & disassembler
itbl-test-ops.o: $(srcdir)/itbl-ops.c \
$(srcdir)/itbl-ops.h itbl-cpu.h itbl-parse.h
$(CC) -o itbl-test-ops.o -DSTAND_ALONE -c $(ALL_CFLAGS) $(CPPFLAGS) $(INCLUDES) $(srcdir)/itbl-ops.c
itbl-test.o: $(srcdir)/itbl-test.c $(srcdir)/itbl-ops.h itbl-cpu.h
$(CC) -c -DSTAND_ALONE $(ALL_CFLAGS) $(INCLUDES) $(srcdir)/itbl-test.c
IT_TEST_OBJS= itbl-parse.o itbl-lex.o itbl-test-ops.o
itbl-test: $(IT_TEST_OBJS) itbl-test.o $(LIBDEPS)
$(CC) $(ALL_CFLAGS) $(LDFLAGS) -o itbl-test itbl-test.o $(IT_TEST_OBJS) $(LIBS)
# target itbl definitions for configuring coprocessor itbl support.
# configure should have taken care of this for us...
itbl-cpu.h: $(srcdir)/config/itbl-@target_cpu_type@.h
ln -s $(srcdir)/config/itbl-@target_cpu_type@.h itbl-cpu.h
# Remake the info files.
doc: $(srcdir)/as.info
@ -428,6 +483,7 @@ clean mostlyclean: clean-here
DISTCLEAN_HERE = config.status Makefile targ-env.h targ-cpu.h \
targ-cpu.c obj-format.h obj-format.c atof-targ.c TAGS \
atof-targ.h itbl-cpu.h \
config-stamp config.h conf config.log config.cache .gdbinit \
testsuite/Makefile testsuite/config.status

View File

@ -1,5 +1,5 @@
/* as.c - GAS main program.
Copyright (C) 1987, 90, 91, 92, 93, 94, 95, 1996
Copyright (C) 1987, 90, 91, 92, 93, 94, 95, 96, 1997
Free Software Foundation, Inc.
This file is part of GAS, the GNU Assembler.
@ -35,7 +35,6 @@
*/
#include "ansidecl.h"
#include "libiberty.h"
#define COMMON
@ -85,6 +84,16 @@ struct defsym_list
};
static struct defsym_list *defsyms;
/* Keep a record of the itbl files we read in. */
struct itbl_file_list
{
struct itbl_file_list *next;
char *name;
};
static struct itbl_file_list *itbl_files;
void
print_version_id ()
@ -134,6 +143,8 @@ Options:\n\
--statistics print various measured statistics from execution\n\
--version print assembler version number and exit\n\
-W suppress warnings\n\
-t,--itbl INSTTBL extend instruction set to include instrictions\n\
matching the specifications defined in file INSTTBL\n\
-w ignored\n\
-X ignored\n\
-Z generate object file even after errors\n");
@ -267,6 +278,8 @@ parse_args (pargc, pargv)
'v',
#endif
'w', 'X',
/* New option for extending instruction set (see also --itbl below) */
't',
'\0'
};
struct option *longopts;
@ -289,7 +302,15 @@ parse_args (pargc, pargv)
#define OPTION_EMULATION (OPTION_STD_BASE + 6)
{"emulation", required_argument, NULL, OPTION_EMULATION},
#define OPTION_DEFSYM (OPTION_STD_BASE + 7)
{"defsym", required_argument, NULL, OPTION_DEFSYM}
{"defsym", required_argument, NULL, OPTION_DEFSYM},
#define OPTION_INSTTBL (OPTION_STD_BASE + 8)
/* New option for extending instruction set (see also -t above).
* The "-t file" or "--itbl file" option extends the basic set
* of valid instructions by reading "file", a text file containing
* a list of instruction formats. The additional opcodes and their
* formats are added to the built-in set of instructions, and
* mnemonics for new registers may also be defined. */
{"itbl", required_argument, NULL, OPTION_INSTTBL}
};
/* Construct the option lists from the standard list and the
@ -422,6 +443,32 @@ the GNU General Public License. This program has absolutely no warranty.\n");
}
break;
case OPTION_INSTTBL:
case 't':
{
/* optarg is the name of the file containing the instruction
formats, opcodes, register names, etc. */
struct itbl_file_list *n;
n = (struct itbl_file_list *) xmalloc (sizeof *n);
n->next = itbl_files;
n->name = optarg;
itbl_files = n;
/* Parse the file and add the new instructions to our internal
table. If multiple instruction tables are specified, the
information from this table gets appended onto the existing
internal table. */
itbl_files->name = xstrdup (optarg);
if (itbl_parse(itbl_files->name) != 0)
{
fprintf (stderr, "Failed to read instruction table %s\n",
itbl_files->name);
exit (EXIT_SUCCESS);
}
}
break;
case 'J':
flag_signed_overflow_ok = 1;
break;
@ -543,6 +590,7 @@ main (argc, argv)
start_time = get_run_time ();
if (debug_memory)
{
#ifdef BFD_ASSEMBLER
@ -581,7 +629,7 @@ main (argc, argv)
symbol_begin ();
frag_init ();
subsegs_begin ();
parse_args (&argc, &argv);
parse_args (&argc, &argv);
read_begin ();
input_scrub_begin ();
expr_begin ();
@ -614,6 +662,8 @@ main (argc, argv)
tc_init_after_args ();
#endif
itbl_init ();
/* Now that we have fully initialized, and have created the output
file, define any symbols requested by --defsym command line
arguments. */
@ -639,8 +689,7 @@ main (argc, argv)
#endif
if (seen_at_least_1_file ()
&& !((had_warnings () && flag_always_generate_output)
|| had_errors () > 0))
&& (flag_always_generate_output || had_errors () == 0))
keep_it = 1;
else
keep_it = 0;
@ -659,6 +708,9 @@ main (argc, argv)
output_file_close (out_file_name);
#endif
if (had_errors () > 0 && ! flag_always_generate_output)
keep_it = 0;
if (!keep_it)
unlink (out_file_name);
@ -668,8 +720,7 @@ main (argc, argv)
/* Use xexit instead of return, because under VMS environments they
may not place the same interpretation on the value given. */
if ((had_warnings () && flag_always_generate_output)
|| had_errors () > 0)
if (had_errors () > 0)
xexit (EXIT_FAILURE);
xexit (EXIT_SUCCESS);
}

View File

@ -36,6 +36,13 @@
#endif
#include "opcode/mips.h"
#include "itbl-ops.h"
#ifdef DEBUG
#define DBG(x) printf x
#else
#define DBG(x)
#endif
#ifdef OBJ_MAYBE_ELF
/* Clean up namespace so we can include obj-elf.h too. */
@ -159,6 +166,7 @@ static int interlocks = -1;
/* As with "interlocks" this is used by hardware that has FP
(co-processor) interlocks. */
/* Itbl support may require additional care here. */
static int cop_interlocks = -1;
/* MIPS PIC level. */
@ -872,6 +880,7 @@ md_begin ()
else
interlocks = 0;
/* Itbl support may require additional care here. */
if (mips_cpu == 4300)
cop_interlocks = 1;
else
@ -1099,7 +1108,11 @@ md_assemble (str)
if (mips16)
mips16_ip (str, &insn);
else
{
mips_ip (str, &insn);
DBG(("returned from mips_ip(%s) insn_opcode = 0x%x\n",
str, insn.insn_opcode));
}
if (insn_error)
{
@ -1221,6 +1234,7 @@ reg_needs_delay (reg)
delays delay the use of general register rt for one
instruction on the r3000. The r6000 and r4000 use
interlocks. */
/* Itbl support may require additional care here. */
know (prev_pinfo & INSN_WRITE_GPR_T);
if (reg == ((prev_insn.insn_opcode >> OP_SH_RT) & OP_MASK_RT))
return 1;
@ -1314,6 +1328,7 @@ append_insn (place, ip, address_expr, reloc_type, unmatched_hi)
delays delay the use of general register rt for one
instruction on the r3000. The r6000 and r4000 use
interlocks. */
/* Itbl support may require additional care here. */
know (prev_pinfo & INSN_WRITE_GPR_T);
if (mips_optimize == 0
|| insn_uses_reg (ip,
@ -1343,6 +1358,9 @@ append_insn (place, ip, address_expr, reloc_type, unmatched_hi)
knowledge of CP0 handling, and the coprocessors other
than the floating point unit are not distinguished at
all. */
/* Itbl support may require additional care here. FIXME!
Need to modify this to include knowledge about
user specified delays! */
if (prev_pinfo & INSN_WRITE_FPR_T)
{
if (mips_optimize == 0
@ -1369,6 +1387,7 @@ append_insn (place, ip, address_expr, reloc_type, unmatched_hi)
instruction may set the condition codes, and the
current instruction uses them, we must insert two
NOPS. */
/* Itbl support may require additional care here. */
if (mips_optimize == 0
|| ((prev_pinfo & INSN_WRITE_COND_CODE)
&& (pinfo & INSN_READ_COND_CODE)))
@ -1387,6 +1406,7 @@ append_insn (place, ip, address_expr, reloc_type, unmatched_hi)
(this means it is a floating point comparison
instruction). If this instruction uses the condition
codes, we need to insert a single NOP. */
/* Itbl support may require additional care here. */
if (mips_optimize == 0
|| (pinfo & INSN_READ_COND_CODE))
++nops;
@ -1414,6 +1434,7 @@ append_insn (place, ip, address_expr, reloc_type, unmatched_hi)
/* If the previous instruction was in a noreorder section, then
we don't want to insert the nop after all. */
/* Itbl support may require additional care here. */
if (prev_insn_unreordered)
nops = 0;
@ -1675,7 +1696,10 @@ append_insn (place, ip, address_expr, reloc_type, unmatched_hi)
mips_cprmask[1] |= 1 << ((ip->insn_opcode >> OP_SH_FR) & OP_MASK_FR);
if (pinfo & INSN_COP)
{
/* We don't keep enough information to sort these cases out. */
/* We don't keep enough information to sort these cases out.
The itbl support does keep this information however, although
we currently don't support itbl fprmats as part of the cop
instruction. May want to add this support in the future. */
}
/* Never set the bit for $0, which is always zero. */
mips_gprmask &=~ 1 << 0;
@ -1776,6 +1800,7 @@ append_insn (place, ip, address_expr, reloc_type, unmatched_hi)
|| (! mips16
&& mips_isa < 4
&& (prev_pinfo
/* Itbl support may require additional care here. */
& (INSN_LOAD_COPROC_DELAY
| INSN_COPROC_MOVE_DELAY
| INSN_WRITE_COND_CODE)))
@ -1787,6 +1812,7 @@ append_insn (place, ip, address_expr, reloc_type, unmatched_hi)
&& mips_isa < 2
&& (prev_pinfo
& (INSN_LOAD_MEMORY_DELAY
/* Itbl support may require additional care here. */
| INSN_COPROC_MEMORY_DELAY)))
/* We can not swap with a branch instruction. */
|| (prev_pinfo
@ -1891,6 +1917,7 @@ append_insn (place, ip, address_expr, reloc_type, unmatched_hi)
can not swap. */
|| (! mips16
&& mips_isa < 4
/* Itbl support may require additional care here. */
&& ((prev_prev_insn.insn_mo->pinfo & INSN_LOAD_COPROC_DELAY)
|| (mips_isa < 2
&& (prev_prev_insn.insn_mo->pinfo
@ -2108,6 +2135,7 @@ mips_emit_delays (insns)
& (INSN_LOAD_MEMORY_DELAY
| INSN_COPROC_MEMORY_DELAY))))
{
/* Itbl support may require additional care here. */
++nops;
if ((! mips16
&& mips_isa < 4
@ -2129,6 +2157,7 @@ mips_emit_delays (insns)
&& ((prev_prev_insn.insn_mo->pinfo & INSN_READ_HI)
|| (prev_prev_insn.insn_mo->pinfo & INSN_READ_LO))))
{
/* Itbl support may require additional care here. */
if (! prev_prev_insn_unreordered)
++nops;
}
@ -4421,18 +4450,22 @@ macro (ip)
goto ld;
case M_LWC0_AB:
s = "lwc0";
/* Itbl support may require additional care here. */
coproc = 1;
goto ld;
case M_LWC1_AB:
s = "lwc1";
/* Itbl support may require additional care here. */
coproc = 1;
goto ld;
case M_LWC2_AB:
s = "lwc2";
/* Itbl support may require additional care here. */
coproc = 1;
goto ld;
case M_LWC3_AB:
s = "lwc3";
/* Itbl support may require additional care here. */
coproc = 1;
goto ld;
case M_LWL_AB:
@ -4445,14 +4478,17 @@ macro (ip)
goto ld;
case M_LDC1_AB:
s = "ldc1";
/* Itbl support may require additional care here. */
coproc = 1;
goto ld;
case M_LDC2_AB:
s = "ldc2";
/* Itbl support may require additional care here. */
coproc = 1;
goto ld;
case M_LDC3_AB:
s = "ldc3";
/* Itbl support may require additional care here. */
coproc = 1;
goto ld;
case M_LDL_AB:
@ -4494,18 +4530,22 @@ macro (ip)
goto st;
case M_SWC0_AB:
s = "swc0";
/* Itbl support may require additional care here. */
coproc = 1;
goto st;
case M_SWC1_AB:
s = "swc1";
/* Itbl support may require additional care here. */
coproc = 1;
goto st;
case M_SWC2_AB:
s = "swc2";
/* Itbl support may require additional care here. */
coproc = 1;
goto st;
case M_SWC3_AB:
s = "swc3";
/* Itbl support may require additional care here. */
coproc = 1;
goto st;
case M_SWL_AB:
@ -4523,13 +4563,16 @@ macro (ip)
case M_SDC1_AB:
s = "sdc1";
coproc = 1;
/* Itbl support may require additional care here. */
goto st;
case M_SDC2_AB:
s = "sdc2";
/* Itbl support may require additional care here. */
coproc = 1;
goto st;
case M_SDC3_AB:
s = "sdc3";
/* Itbl support may require additional care here. */
coproc = 1;
goto st;
case M_SDL_AB:
@ -4541,6 +4584,7 @@ macro (ip)
tempreg = AT;
used_at = 1;
ld_st:
/* Itbl support may require additional care here. */
if (mask == M_LWC1_AB
|| mask == M_SWC1_AB
|| mask == M_LDC1_AB
@ -4939,6 +4983,7 @@ macro (ip)
* But, the resulting address is the same after relocation so why
* generate the extra instruction?
*/
/* Itbl support may require additional care here. */
coproc = 1;
if (mips_isa >= 2)
{
@ -4959,6 +5004,7 @@ macro (ip)
s = "swc1";
fmt = "T,o(b)";
/* Itbl support may require additional care here. */
coproc = 1;
goto ldd_std;
@ -4994,6 +5040,7 @@ macro (ip)
/* Even on a big endian machine $fn comes before $fn+1. We have
to adjust when loading from memory. We set coproc if we must
load $fn+1 first. */
/* Itbl support may require additional care here. */
if (! target_big_endian)
coproc = 0;
@ -5042,6 +5089,7 @@ macro (ip)
used_at = 1;
}
/* Itbl support may require additional care here. */
macro_build ((char *) NULL, &icnt, &offset_expr, s, fmt,
coproc ? treg + 1 : treg,
(int) BFD_RELOC_MIPS_GPREL, tempreg);
@ -5051,6 +5099,7 @@ macro (ip)
undesired nop. */
hold_mips_optimize = mips_optimize;
mips_optimize = 2;
/* Itbl support may require additional care here. */
macro_build ((char *) NULL, &icnt, &offset_expr, s, fmt,
coproc ? treg : treg + 1,
(int) BFD_RELOC_MIPS_GPREL, tempreg);
@ -5084,6 +5133,7 @@ macro (ip)
if (p != NULL)
p += 4;
}
/* Itbl support may require additional care here. */
macro_build (p, &icnt, &offset_expr, s, fmt,
coproc ? treg + 1 : treg,
(int) BFD_RELOC_LO16, AT);
@ -5091,6 +5141,7 @@ macro (ip)
p += 4;
/* FIXME: How do we handle overflow here? */
offset_expr.X_add_number += 4;
/* Itbl support may require additional care here. */
macro_build (p, &icnt, &offset_expr, s, fmt,
coproc ? treg : treg + 1,
(int) BFD_RELOC_LO16, AT);
@ -5131,6 +5182,7 @@ macro (ip)
macro_build ((char *) NULL, &icnt, (expressionS *) NULL,
mips_isa < 3 ? "addu" : "daddu",
"d,v,t", AT, breg, AT);
/* Itbl support may require additional care here. */
macro_build ((char *) NULL, &icnt, &expr1, s, fmt,
coproc ? treg + 1 : treg,
(int) BFD_RELOC_LO16, AT);
@ -5140,6 +5192,7 @@ macro (ip)
nop. */
hold_mips_optimize = mips_optimize;
mips_optimize = 2;
/* Itbl support may require additional care here. */
macro_build ((char *) NULL, &icnt, &expr1, s, fmt,
coproc ? treg : treg + 1,
(int) BFD_RELOC_LO16, AT);
@ -5197,6 +5250,7 @@ macro (ip)
macro_build ((char *) NULL, &icnt, (expressionS *) NULL,
mips_isa < 3 ? "addu" : "daddu",
"d,v,t", AT, breg, AT);
/* Itbl support may require additional care here. */
macro_build ((char *) NULL, &icnt, &expr1, s, fmt,
coproc ? treg + 1 : treg,
(int) BFD_RELOC_LO16, AT);
@ -5206,6 +5260,7 @@ macro (ip)
nop. */
hold_mips_optimize = mips_optimize;
mips_optimize = 2;
/* Itbl support may require additional care here. */
macro_build ((char *) NULL, &icnt, &expr1, s, fmt,
coproc ? treg : treg + 1,
(int) BFD_RELOC_LO16, AT);
@ -5235,6 +5290,7 @@ macro (ip)
"d,v,t", AT, breg, AT);
p += 4;
}
/* Itbl support may require additional care here. */
macro_build (p, &icnt, &expr1, s, fmt,
coproc ? treg + 1 : treg,
(int) BFD_RELOC_LO16, AT);
@ -5245,6 +5301,7 @@ macro (ip)
nop. */
hold_mips_optimize = mips_optimize;
mips_optimize = 2;
/* Itbl support may require additional care here. */
macro_build (p, &icnt, &expr1, s, fmt,
coproc ? treg : treg + 1,
(int) BFD_RELOC_LO16, AT);
@ -5274,10 +5331,12 @@ macro (ip)
used_at = 1;
}
/* Itbl support may require additional care here. */
macro_build ((char *) NULL, &icnt, &offset_expr, s, fmt,
coproc ? treg + 1 : treg,
(int) BFD_RELOC_MIPS_GPREL, tempreg);
offset_expr.X_add_number += 4;
/* Itbl support may require additional care here. */
macro_build ((char *) NULL, &icnt, &offset_expr, s, fmt,
coproc ? treg : treg + 1,
(int) BFD_RELOC_MIPS_GPREL, tempreg);
@ -5303,8 +5362,59 @@ macro (ip)
macro_build ((char *) NULL, &icnt, &offset_expr, s, "t,o(b)", treg + 1,
(int) BFD_RELOC_LO16, breg);
return;
/* New code added to support COPZ instructions.
This code builds table entries out of the macros in mip_opcodes.
R4000 uses interlocks to handle coproc delays.
Other chips (like the R3000) require nops to be inserted for delays.
FIXME: Currently, we require that the user handle delays.
In order to fill delay slots for non-interlocked chips,
we must have a way to specify delays based on the coprocessor.
Eg. 4 cycles if load coproc reg from memory, 1 if in cache, etc.
What are the side-effects of the cop instruction?
What cache support might we have and what are its effects?
Both coprocessor & memory require delays. how long???
What registers are read/set/modified?
If an itbl is provided to interpret cop instructions,
this knowledge can be encoded in the itbl spec. */
case M_COP0:
s = "cop0";
goto copz;
case M_COP1:
s = "cop1";
goto copz;
case M_COP2:
s = "cop2";
goto copz;
case M_COP3:
s = "cop3";
copz:
/* For now we just do C (same as Cz). */
macro_build ((char *) NULL, &icnt, &offset_expr, s, "C");
return;
#ifdef LOSING_COMPILER
default:
/* Try and see if this is a new itbl instruction.
This code builds table entries out of the macros in mip_opcodes.
FIXME: For now we just assemble the expression and pass it's
value along as a 32-bit immediate.
We may want to have the assembler assemble this value,
so that we gain the assembler's knowledge of delay slots,
symbols, etc.
Would it be more efficient to use mask (id) here? */
if (itbl_have_entries
&& immed_expr = itbl_assemble(ip->insn_mo->name, ""), immed_expr)
{
s = ip->insn_mo->name;
s2 = "cop3";
coproc = ITBL_DECODE_PNUM(immed_expr);;
macro_build ((char *) NULL, &icnt, &immed_expr, s, "C");
return;
}
macro2 (ip);
return;
}
@ -5967,6 +6077,8 @@ macro2 (ip)
break;
default:
/* FIXME: Check if this is one of the itbl macros, since they are
added dynamically. */
as_bad ("Macro %s not implemented yet", ip->insn_mo->name);
break;
}
@ -6485,6 +6597,30 @@ mips_ip (str, ip)
s += 4;
regno = KT1;
}
else if (itbl_have_entries)
{
char *p, *n;
int r;
p = s+1; /* advance past '$' */
n = itbl_get_field(&p); /* n is name */
/* See if this is a register defined in an
itbl entry */
if (r = itbl_get_reg_val(n), r)
{
/* Get_field advances to the start of the next
field, so we need to back rack to the end of
the last field. */
if (p)
s = p-1;
else
s = strchr(s,'\0');
regno = r;
}
else
goto notreg;
}
else
goto notreg;
}
@ -6508,6 +6644,9 @@ mips_ip (str, ip)
/* 'z' only matches $0. */
if (c == 'z' && regno != 0)
break;
/* Now that we have assembled one operand, we use the args string
* to figure out where it goes in the instruction. */
switch (c)
{
case 'r':
@ -6540,6 +6679,11 @@ mips_ip (str, ip)
is $0. This only matches $0, and is checked
outside the switch. */
break;
case 'D':
/* Itbl operand; not yet implemented. FIXME ?? */
break;
/* What about all other operands like 'i',
which can be specified in the opcode table? */
}
lastregno = regno;
continue;
@ -8309,6 +8453,19 @@ MIPS options:\n\
#endif
}
void
mips_init_after_args ()
{
if (itbl_have_entries)
{
/* initialize opcodes */
bfd_mips_num_opcodes = bfd_mips_num_builtin_opcodes;
mips_opcodes = (struct mips_opcode*) mips_builtin_opcodes;
}
}
long
md_pcrel_from (fixP)
fixS *fixP;

25
gas/configure vendored
View File

@ -1017,6 +1017,8 @@ EOF
;;
esac
# additional parsers based on cpu-type
case ${cpu_type} in
m68k)
case ${extra_objects} in
@ -1024,6 +1026,27 @@ EOF
*) extra_objects="$extra_objects m68k-parse.o" ;;
esac
;;
mips)
echo ${extra_objects} | grep -s "itbl-parse.o"
if test $? -ne 0 ; then
extra_objects="$extra_objects itbl-parse.o"
fi
echo ${extra_objects} | grep -s "itbl-lex.o"
if test $? -ne 0 ; then
extra_objects="$extra_objects itbl-lex.o"
fi
echo ${extra_objects} | grep -s "itbl-ops.o"
if test $? -ne 0 ; then
extra_objects="$extra_objects itbl-ops.o"
fi
;;
*)
;;
esac
# See if we really can support this configuration with the emulation code.
@ -1267,8 +1290,10 @@ EOF
files="config/tc-${target_cpu_type}.c config/tc-${target_cpu_type}.h \
config/obj-${obj_format}.h config/obj-${obj_format}.c \
config/te-${te_file}.h config/atof-${atof}.c \
config/itbl-${target_cpu_type}.h \
$extra_files"
links="targ-cpu.c targ-cpu.h obj-format.h obj-format.c targ-env.h atof-targ.c \
itbl-cpu.h \
$extra_links"
case ${primary_bfd_gas}-${target_cpu_type}-${obj_format} in

View File

@ -365,6 +365,26 @@ changequote([,])dnl
*) extra_objects="$extra_objects m68k-parse.o" ;;
esac
;;
mips)
`echo ${extra_objects}` | grep -s "itbl-parse.o"
if test $? -ne 0 ; then
extra_objects="$extra_objects itbl-parse.o"
fi
`echo ${extra_objects}` | grep -s "itbl-lex.o"
if test $? -ne 0 ; then
extra_objects="$extra_objects itbl-lex.o"
fi
`echo ${extra_objects}` | grep -s "itbl-ops.o"
if test $? -ne 0 ; then
extra_objects="$extra_objects itbl-ops.o"
fi
;;
*)
;;
esac
# See if we really can support this configuration with the emulation code.
@ -527,8 +547,10 @@ AC_DEFINE_UNQUOTED(DEFAULT_EMULATION, "$DEFAULT_EMULATION")
files="config/tc-${target_cpu_type}.c config/tc-${target_cpu_type}.h \
config/obj-${obj_format}.h config/obj-${obj_format}.c \
config/te-${te_file}.h config/atof-${atof}.c \
config/itbl-${target_cpu_type}.h \
$extra_files"
links="targ-cpu.c targ-cpu.h obj-format.h obj-format.c targ-env.h atof-targ.c \
itbl-cpu.h \
$extra_links"
case ${primary_bfd_gas}-${target_cpu_type}-${obj_format} in

View File

@ -1,3 +1,25 @@
/* itbl-lex.l
Copyright (C) 1997 Free Software Foundation, Inc.
This file is part of GAS, the GNU Assembler.
GAS 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.
GAS 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 GAS; see the file COPYING. If not, write to the Free
Software Foundation, 59 Temple Place - Suite 330, Boston, MA
02111-1307, USA. */
%{
#include <stdio.h>
#include <string.h>
@ -23,64 +45,70 @@ HEX [0-9A-Fa-f]
%%
"creg"|"CREG" {
return CREG;
}
"dreg"|"DREG" {
return DREG;
}
"greg"|"GREG" {
return GREG;
}
"immed"|"IMMED" {
return IMMED;
}
"addr"|"ADDR" {
return ADDR;
}
"insn"|"INSN" {
return INSN;
}
"creg"|"CREG" {
return CREG;
}
"dreg"|"DREG" {
return DREG;
}
"greg"|"GREG" {
return GREG;
}
"immed"|"IMMED" {
return IMMED;
}
"addr"|"ADDR" {
return ADDR;
}
"insn"|"INSN" {
return INSN;
}
"p"{DIGIT} {
yytext[yyleng]=0;
yylval.processor = strtoul(yytext+1,0,0);
return PNUM;
}
{DIGIT}+ {
yytext[yyleng]=0;
yylval.num = strtoul(yytext,0,0);
return NUM;
}
"0x"{HEX}+ {
yytext[yyleng]=0;
yylval.num = strtoul(yytext,0,0);
return NUM;
}
yytext[yyleng] = 0;
yylval.processor = strtoul (yytext+1, 0, 0);
return PNUM;
}
{DIGIT}+ {
yytext[yyleng] = 0;
yylval.num = strtoul (yytext, 0, 0);
return NUM;
}
"0x"{HEX}+ {
yytext[yyleng] = 0;
yylval.num = strtoul (yytext, 0, 0);
return NUM;
}
{ALPHA}{ALNUM}* {
yytext[yyleng]=0;
yylval.str = strdup(yytext);
return ID;
}
yytext[yyleng] = 0;
yylval.str = strdup (yytext);
return ID;
}
";"|"#" {
int c;
while ((c = input()) != EOF) {
if (c == '\n')
{
unput(c);
break;
}
}
}
int c;
while ((c = input ()) != EOF)
{
if (c == '\n')
{
unput (c);
break;
}
}
}
"\n" {
insntbl_line++;
MDBG(("in lex, NL=%d (x%x)\n",NL,NL));
return NL;
}
" "|"\t" { }
. {
MDBG(("char=%x,%d\n",yytext[0],yytext[0]));
return yytext[0];
}
insntbl_line++;
MDBG (("in lex, NL = %d (x%x)\n", NL, NL));
return NL;
}
" "|"\t" {
}
. {
MDBG (("char = %x, %d\n", yytext[0], yytext[0]));
return yytext[0];
}
%%
int yywrap() { return 1; }
int
yywrap ()
{
return 1;
}

File diff suppressed because it is too large Load Diff

View File

@ -1,18 +1,40 @@
/* itbl-ops.h
Copyright (C) 1997 Free Software Foundation, Inc.
This file is part of GAS, the GNU Assembler.
GAS 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.
GAS 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 GAS; see the file COPYING. If not, write to the Free
Software Foundation, 59 Temple Place - Suite 330, Boston, MA
02111-1307, USA. */
/* External functions, constants and defines for itbl support */
#include "ansidecl.h"
#include "itbl-cpu.h"
/* Defaults for definitions required by generic code */
/* Defaults for definitions required by generic code */
#ifndef ITBL_NUMBER_OF_PROCESSORS
#define ITBL_NUMBER_OF_PROCESSORS 1
#endif
#ifndef ITBL_MAX_BITPOS
#ifndef ITBL_MAX_BITPOS
#define ITBL_MAX_BITPOS 31
#endif
#ifndef ITBL_TYPE
#ifndef ITBL_TYPE
#define ITBL_TYPE unsigned long
#endif
@ -31,45 +53,50 @@
typedef ITBL_TYPE t_insn;
/* types of entries */
typedef enum
{
typedef enum
{
e_insn,
e_dreg,
e_regtype0 = e_dreg,
e_regtype0 = e_dreg,
e_creg,
e_greg,
e_addr,
e_nregtypes = e_greg+1,
e_nregtypes = e_greg + 1,
e_immed,
e_ntypes,
e_invtype /* invalid type */
} e_type;
e_invtype /* invalid type */
} e_type;
typedef enum
{
typedef enum
{
e_p0,
e_nprocs=NUMBER_OF_PROCESSORS,
e_invproc /* invalid processor */
} e_processor;
e_nprocs = NUMBER_OF_PROCESSORS,
e_invproc /* invalid processor */
} e_processor;
/* 0 means an instruction table was not specified. */
extern int itbl_have_entries;
/* These routines are visible to the main part of the assembler */
int itbl_parse(char* insntbl);
void itbl_init(void);
char *itbl_get_field(char **s);
unsigned long itbl_assemble(char *name, char *operands);
int itbl_disassemble(char *str, unsigned long insn);
int itbl_parse(char *tbl); /* parses insn tbl */
unsigned long itbl_get_reg_val(char *name);
unsigned long itbl_get_val(e_processor processor, e_type type, char *name);
char *itbl_get_name(e_processor processor, e_type type, unsigned long val);
int itbl_parse PARAMS ((char *insntbl));
void itbl_init PARAMS ((void));
char *itbl_get_field PARAMS ((char **s));
unsigned long itbl_assemble PARAMS ((char *name, char *operands));
int itbl_disassemble PARAMS ((char *str, unsigned long insn));
int itbl_parse PARAMS ((char *tbl)); /* parses insn tbl */
unsigned long itbl_get_reg_val PARAMS ((char *name));
unsigned long itbl_get_val PARAMS ((e_processor processor, e_type type,
char *name));
char *itbl_get_name PARAMS ((e_processor processor, e_type type,
unsigned long val));
/* These routines are called by the table parser used to build the
* dynamic list of new processor instructions and registers. */
struct itbl_entry *itbl_add_reg(int yyproc, int yytype, char *regname, int regnum);
struct itbl_entry *itbl_add_insn(int yyproc, char *name, unsigned long value,
int sbit, int ebit, unsigned long flags);
struct itbl_field *itbl_add_operand(struct itbl_entry *e, int yytype,
int sbit, int ebit, unsigned long flags);
/* These routines are called by the table parser used to build the
dynamic list of new processor instructions and registers. */
struct itbl_entry *itbl_add_reg PARAMS ((int yyproc, int yytype,
char *regname, int regnum));
struct itbl_entry *itbl_add_insn PARAMS ((int yyproc, char *name,
unsigned long value, int sbit, int ebit, unsigned long flags));
struct itbl_field *itbl_add_operand PARAMS ((struct itbl_entry * e, int yytype,
int sbit, int ebit, unsigned long flags));

View File

@ -1,4 +1,27 @@
/* itbl-parse.y
Copyright (C) 1997 Free Software Foundation, Inc.
This file is part of GAS, the GNU Assembler.
GAS 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.
GAS 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 GAS; see the file COPYING. If not, write to the Free
Software Foundation, 59 Temple Place - Suite 330, Boston, MA
02111-1307, USA. */
%{
/*
Yacc grammar for instruction table entries.
@ -6,8 +29,8 @@ Yacc grammar for instruction table entries.
=======================================================================
Original Instruction table specification document:
MIPS Coprocessor Table Specification
====================================
MIPS Coprocessor Table Specification
====================================
This document describes the format of the MIPS coprocessor table. The
table specifies a list of valid functions, data registers and control
@ -31,9 +54,9 @@ complete name of the table, including path and extension.
Examples:
gas -t cop.tbl test.s -o test.o
gas -t /usr/local/lib/cop.tbl test.s -o test.o
gas --itbl d:\gnu\data\cop.tbl test.s -o test.o
gas -t cop.tbl test.s -o test.o
gas -t /usr/local/lib/cop.tbl test.s -o test.o
gas --itbl d:\gnu\data\cop.tbl test.s -o test.o
Only one table may be supplied during a single invocation of
the assembler.
@ -46,30 +69,37 @@ Below is a list of the valid coprocessor instruction classes for
any given coprocessor "z". These instructions are already recognized
by the assembler, and are listed here only for reference.
Class format instructions
Class format instructions
-------------------------------------------------
Class1: op base rt offset
LWCz rt,offset(base)
SWCz rt,offset(base)
Class2: COPz sub rt rd 0
MTCz rt,rd
MFCz rt,rd
CTCz rt,rd
CFCz rt,rd
Class3: COPz CO cofun
COPz cofun
Class4: COPz BC br offset
BCzT offset
BCzF offset
Class5: COPz sub rt rd 0
DMFCz rt,rd
DMTCz rt,rd
Class6: op base rt offset
LDCz rt,offset(base)
SDCz rt,offset(base)
Class7: COPz BC br offset
BCzTL offset
BCzFL offset
Class1:
op base rt offset
LWCz rt,offset (base)
SWCz rt,offset (base)
Class2:
COPz sub rt rd 0
MTCz rt,rd
MFCz rt,rd
CTCz rt,rd
CFCz rt,rd
Class3:
COPz CO cofun
COPz cofun
Class4:
COPz BC br offset
BCzT offset
BCzF offset
Class5:
COPz sub rt rd 0
DMFCz rt,rd
DMTCz rt,rd
Class6:
op base rt offset
LDCz rt,offset (base)
SDCz rt,offset (base)
Class7:
COPz BC br offset
BCzTL offset
BCzFL offset
The coprocessor table defines coprocessor-specific registers that can
be used with all of the above classes of instructions, where
@ -90,41 +120,41 @@ Table Grammar
Here is the grammar for the coprocessor table:
table -> entry*
table -> entry*
entry -> [z entrydef] [comment] '\n'
entry -> [z entrydef] [comment] '\n'
entrydef -> type name val
entrydef -> 'insn' name val funcdef ; type of entry (instruction)
entrydef -> type name val
entrydef -> 'insn' name val funcdef ; type of entry (instruction)
z -> 'p'['0'..'3'] ; processor number
type -> ['dreg' | 'creg' | 'greg' ] ; type of entry (register)
z -> 'p'['0'..'3'] ; processor number
type -> ['dreg' | 'creg' | 'greg' ] ; type of entry (register)
; 'dreg', 'creg' or 'greg' specifies a data, control, or general
; register mnemonic, respectively
name -> [ltr|dec]* ; mnemonic of register/function
val -> [dec|hex] ; register/function number (integer constant)
; register mnemonic, respectively
name -> [ltr|dec]* ; mnemonic of register/function
val -> [dec|hex] ; register/function number (integer constant)
funcdef -> frange flags fields
; bitfield range for opcode
; list of fields' formats
fields -> field*
field -> [','] ftype frange flags
flags -> ['*' flagexpr]
flagexpr -> '[' flagexpr ']'
flagexpr -> val '|' flagexpr
ftype -> [ type | 'immed' | 'addr' ]
funcdef -> frange flags fields
; bitfield range for opcode
; list of fields' formats
fields -> field*
field -> [','] ftype frange flags
flags -> ['*' flagexpr]
flagexpr -> '[' flagexpr ']'
flagexpr -> val '|' flagexpr
ftype -> [ type | 'immed' | 'addr' ]
; 'immed' specifies an immediate value; see grammar for "val" above
; 'addr' specifies a C identifier; name of symbol to be resolved at
; link time
frange -> ':' val '-' val ; starting to ending bit positions, where
; where 0 is least significant bit
frange -> (null) ; default range of 31-0 will be assumed
; 'addr' specifies a C identifier; name of symbol to be resolved at
; link time
frange -> ':' val '-' val ; starting to ending bit positions, where
; where 0 is least significant bit
frange -> (null) ; default range of 31-0 will be assumed
comment -> [';'|'#'] [char]*
char -> any printable character
ltr -> ['a'..'z'|'A'..'Z']
dec -> ['0'..'9']* ; value in decimal
hex -> '0x'['0'..'9' | 'a'..'f' | 'A'..'F']* ; value in hexidecimal
comment -> [';'|'#'] [char]*
char -> any printable character
ltr -> ['a'..'z'|'A'..'Z']
dec -> ['0'..'9']* ; value in decimal
hex -> '0x'['0'..'9' | 'a'..'f' | 'A'..'F']* ; value in hexidecimal
Examples
@ -134,15 +164,15 @@ Example 1:
The table:
p1 dreg d1 1 ; data register "d1" for COP1 has value 1
p1 creg c3 3 ; ctrl register "c3" for COP1 has value 3
p3 func fill 0x1f:24-20 ; function "fill" for COP3 has value 31 and
; no fields
p1 dreg d1 1 ; data register "d1" for COP1 has value 1
p1 creg c3 3 ; ctrl register "c3" for COP1 has value 3
p3 func fill 0x1f:24-20 ; function "fill" for COP3 has value 31 and
; no fields
will allow the assembler to accept the following coprocessor instructions:
LWC1 d1,0x100($2)
fill
LWC1 d1,0x100 ($2)
fill
Here, the general purpose register "$2", and instruction "LWC1", are standard
mnemonics built-in to the MIPS assembler.
@ -152,46 +182,46 @@ Example 2:
The table:
p3 dreg d3 3 ; data register "d3" for COP3 has value 3
p3 creg c2 22 ; control register "c2" for COP3 has value 22
p3 func fee 0x1f:24-20 dreg:17-13 creg:12-8 immed:7-0
; function "fee" for COP3 has value 31, and 3 fields
; consisting of a data register, a control register,
; and an immediate value.
p3 dreg d3 3 ; data register "d3" for COP3 has value 3
p3 creg c2 22 ; control register "c2" for COP3 has value 22
p3 func fee 0x1f:24-20 dreg:17-13 creg:12-8 immed:7-0
; function "fee" for COP3 has value 31, and 3 fields
; consisting of a data register, a control register,
; and an immediate value.
will allow the assembler to accept the following coprocessor instruction:
fee d3,c2,0x1
fee d3,c2,0x1
and will emit the object code:
31-26 25 24-20 19-18 17-13 12-8 7-0
COPz CO fun dreg creg immed
010011 1 11111 00 00011 10110 00000001
31-26 25 24-20 19-18 17-13 12-8 7-0
COPz CO fun dreg creg immed
010011 1 11111 00 00011 10110 00000001
0x4ff07601
0x4ff07601
Example 3:
The table:
p3 dreg d3 3 ; data register "d3" for COP3 has value 3
p3 creg c2 22 ; control register "c2" for COP3 has value 22
p3 func fuu 0x01f00001 dreg:17-13 creg:12-8
p3 dreg d3 3 ; data register "d3" for COP3 has value 3
p3 creg c2 22 ; control register "c2" for COP3 has value 22
p3 func fuu 0x01f00001 dreg:17-13 creg:12-8
will allow the assembler to accept the following coprocessor
instruction:
fuu d3,c2
fuu d3,c2
and will emit the object code:
31-26 25 24-20 19-18 17-13 12-8 7-0
COPz CO fun dreg creg
010011 1 11111 00 00011 10110 00000001
31-26 25 24-20 19-18 17-13 12-8 7-0
COPz CO fun dreg creg
010011 1 11111 00 00011 10110 00000001
0x4ff07601
0x4ff07601
In this way, the programmer can force arbitrary bits of an instruction
to have predefined values.
@ -205,7 +235,8 @@ use 0s to mask out the ranges which don't apply.
May decide to modify the syntax to allow commas separate multiple
ranges within an instruction (range','range).
Changes in grammar: The number of parms argument to the function entry
Changes in grammar:
The number of parms argument to the function entry
was deleted from the original format such that we now count the fields.
----
@ -245,169 +276,184 @@ FIXME! hex is ambiguous with any digit
static int sbit, ebit;
static struct itbl_entry *insn=0;
extern int insntbl_line;
int yyparse(void);
int yylex(void);
int yyparse (void);
int yylex (void);
%}
%union {
%union
{
char *str;
int num;
int processor;
unsigned long val;
}
}
%token DREG CREG GREG IMMED ADDR INSN NUM ID NL PNUM
%type <val> value flags flagexpr
%type <num> number NUM ftype regtype pnum PNUM
%type <str> ID name
%token DREG CREG GREG IMMED ADDR INSN NUM ID NL PNUM
%type <val> value flags flagexpr
%type <num> number NUM ftype regtype pnum PNUM
%type <str> ID name
%start insntbl
%%
insntbl: entrys
insntbl:
entrys
;
entrys: entry entrys
entrys:
entry entrys
|
;
entry: pnum regtype name value NL
{
DBG(("line %d: entry pnum=%d type=%d name=%s value=x%x\n",
insntbl_line, $1, $2, $3, $4));
itbl_add_reg($1, $2, $3, $4);
}
entry:
pnum regtype name value NL
{
DBG (("line %d: entry pnum=%d type=%d name=%s value=x%x\n",
insntbl_line, $1, $2, $3, $4));
itbl_add_reg ($1, $2, $3, $4);
}
| pnum INSN name value range flags
{
DBG(("line %d: entry pnum=%d type=INSN name=%s value=x%x",
insntbl_line, $1, $3, $4));
DBG((" sbit=%d ebit=%d flags=0x%x\n", sbit, ebit, $6));
insn=itbl_add_insn($1, $3, $4, sbit, ebit, $6);
}
{
DBG (("line %d: entry pnum=%d type=INSN name=%s value=x%x",
insntbl_line, $1, $3, $4));
DBG ((" sbit=%d ebit=%d flags=0x%x\n", sbit, ebit, $6));
insn=itbl_add_insn ($1, $3, $4, sbit, ebit, $6);
}
fieldspecs NL
| NL
| error NL
;
fieldspecs: ',' fieldspec fieldspecs
fieldspecs:
',' fieldspec fieldspecs
| fieldspec fieldspecs
|
;
ftype: regtype
{
DBGL2(("ftype\n"));
$$ = $1;
}
ftype:
regtype
{
DBGL2 (("ftype\n"));
$$ = $1;
}
| ADDR
{
DBGL2(("addr\n"));
$$ = ADDR;
}
{
DBGL2 (("addr\n"));
$$ = ADDR;
}
| IMMED
{
DBGL2(("immed\n"));
$$ = IMMED;
}
{
DBGL2 (("immed\n"));
$$ = IMMED;
}
;
fieldspec: ftype range flags
{
DBG(("line %d: field type=%d sbit=%d ebit=%d, flags=0x%x\n",
insntbl_line, $1, sbit, ebit, $3));
itbl_add_operand(insn, $1, sbit, ebit, $3);
}
fieldspec:
ftype range flags
{
DBG (("line %d: field type=%d sbit=%d ebit=%d, flags=0x%x\n",
insntbl_line, $1, sbit, ebit, $3));
itbl_add_operand (insn, $1, sbit, ebit, $3);
}
;
flagexpr: NUM '|' flagexpr
{
$$ = $1 | $3;
}
flagexpr:
NUM '|' flagexpr
{
$$ = $1 | $3;
}
| '[' flagexpr ']'
{
$$ = $2;
}
{
$$ = $2;
}
| NUM
{
$$ = $1;
}
{
$$ = $1;
}
;
flags: '*' flagexpr
{
DBGL2(("flags=%d\n", $2));
$$ = $2;
}
flags:
'*' flagexpr
{
DBGL2 (("flags=%d\n", $2));
$$ = $2;
}
|
{
$$ = 0;
}
{
$$ = 0;
}
;
range: ':' NUM '-' NUM
{
DBGL2(("range %d %d\n", $2, $4));
sbit = $2;
ebit = $4;
}
range:
':' NUM '-' NUM
{
DBGL2 (("range %d %d\n", $2, $4));
sbit = $2;
ebit = $4;
}
|
{
sbit = 31;
ebit = 0;
}
{
sbit = 31;
ebit = 0;
}
;
pnum: PNUM
{
DBGL2(("pnum=%d\n",$1));
$$ = $1;
}
pnum:
PNUM
{
DBGL2 (("pnum=%d\n",$1));
$$ = $1;
}
;
regtype: DREG
{
DBGL2(("dreg\n"));
$$ = DREG;
}
regtype:
DREG
{
DBGL2 (("dreg\n"));
$$ = DREG;
}
| CREG
{
DBGL2(("creg\n"));
$$ = CREG;
}
{
DBGL2 (("creg\n"));
$$ = CREG;
}
| GREG
{
DBGL2(("greg\n"));
$$ = GREG;
}
{
DBGL2 (("greg\n"));
$$ = GREG;
}
;
name: ID
{
DBGL2(("name=%s\n",$1));
$$ = $1;
}
name:
ID
{
DBGL2 (("name=%s\n",$1));
$$ = $1;
}
;
number: NUM
{
DBGL2(("num=%d\n",$1));
$$ = $1;
}
number:
NUM
{
DBGL2 (("num=%d\n",$1));
$$ = $1;
}
;
value: NUM
{
DBGL2(("val=x%x\n",$1));
$$ = $1;
}
value:
NUM
{
DBGL2 (("val=x%x\n",$1));
$$ = $1;
}
;
%%
void yyerror(char *msg)
void
yyerror (char *msg)
{
printf("line %d: %s\n", insntbl_line, msg);
printf ("line %d: %s\n", insntbl_line, msg);
}