* 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

@@ -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;