aboutsummaryrefslogtreecommitdiff
path: root/gas/config
diff options
context:
space:
mode:
authorDawn Perchik <dawn@cygnus>1997-02-23 22:23:12 +0000
committerDawn Perchik <dawn@cygnus>1997-02-23 22:23:12 +0000
commitefec4a282c17a6814a2ff28b15d6305af8aaf2bb (patch)
tree4e9afaa9bb6cb915bd311a7b7425ef13ede8cc1b /gas/config
parentc7583da0b6ef488954a9c299d95452e5e081e22e (diff)
downloadgdb-efec4a282c17a6814a2ff28b15d6305af8aaf2bb.zip
gdb-efec4a282c17a6814a2ff28b15d6305af8aaf2bb.tar.gz
gdb-efec4a282c17a6814a2ff28b15d6305af8aaf2bb.tar.bz2
* 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.
Diffstat (limited to 'gas/config')
-rw-r--r--gas/config/tc-mips.c159
1 files changed, 158 insertions, 1 deletions
diff --git a/gas/config/tc-mips.c b/gas/config/tc-mips.c
index 1eb151f..f22f8e8 100644
--- a/gas/config/tc-mips.c
+++ b/gas/config/tc-mips.c
@@ -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;