aboutsummaryrefslogtreecommitdiff
path: root/gas
diff options
context:
space:
mode:
authorTom Rix <trix@redhat.com>2002-05-30 16:16:30 +0000
committerTom Rix <trix@redhat.com>2002-05-30 16:16:30 +0000
commit8ade06a8146be564c93d5c2ccf5b5f2da9467eff (patch)
tree3b36761deadebf1c8bd11475c56bc9f24ab62a51 /gas
parent8c2784a5a4551a25636e262f332d4d955fe4824a (diff)
downloadgdb-8ade06a8146be564c93d5c2ccf5b5f2da9467eff.zip
gdb-8ade06a8146be564c93d5c2ccf5b5f2da9467eff.tar.gz
gdb-8ade06a8146be564c93d5c2ccf5b5f2da9467eff.tar.bz2
d10v fixes.
Diffstat (limited to 'gas')
-rw-r--r--gas/ChangeLog13
-rw-r--r--gas/config/tc-d10v.c136
2 files changed, 77 insertions, 72 deletions
diff --git a/gas/ChangeLog b/gas/ChangeLog
index 51c53f7..e214fbf 100644
--- a/gas/ChangeLog
+++ b/gas/ChangeLog
@@ -1,3 +1,16 @@
+2002-05-30 Diego Novillo <dnovillo@redhat.com>
+
+ * gas/config/tc-d10v.c (check_resource_conflict): Only check
+ write-write conflicts.
+ (md_assemble): Reformat introductory comment.
+ (parallel_ok): Prevent packing only if the first
+ instruction cannot be packed.
+
+2002-05-30 Jason Eckhardt <jle@redhat.com>
+ Tom Rix <trix@redhat.com>
+
+ * config/tc-d10v.c (build_insn): Check for immediates.
+
2002-05-28 Thiemo Seufer <seufer@csv.ica.uni-stuttgart.de>
* config/tc-mips.c: Replace GP in comments by $gp.
diff --git a/gas/config/tc-d10v.c b/gas/config/tc-d10v.c
index 6b53409..679315f 100644
--- a/gas/config/tc-d10v.c
+++ b/gas/config/tc-d10v.c
@@ -99,9 +99,9 @@ static int parallel_ok PARAMS ((struct d10v_opcode *opcode1, unsigned long insn1
struct d10v_opcode *opcode2, unsigned long insn2,
packing_type exec_type));
-static void check_resource_conflict PARAMS ((struct d10v_opcode *opcode1,
- unsigned long insn1,
- struct d10v_opcode *opcode2,
+static void check_resource_conflict PARAMS ((struct d10v_opcode *opcode1,
+ unsigned long insn1,
+ struct d10v_opcode *opcode2,
unsigned long insn2));
static symbolS * find_symbol_matching_register PARAMS ((expressionS *));
@@ -647,8 +647,15 @@ build_insn (opcode, opers, insn)
opers[i].X_add_number = number;
}
else
- fixups->fix[fixups->fc].reloc =
- get_reloc ((struct d10v_operand *) &d10v_operands[opcode->operands[i]]);
+ {
+ fixups->fix[fixups->fc].reloc =
+ get_reloc ((struct d10v_operand *) &d10v_operands[opcode->operands[i]]);
+
+ /* Check that a immediate was passed to ops that expect one. */
+ if ((flags & OPERAND_NUM)
+ && (fixups->fix[fixups->fc].reloc == 0))
+ as_bad (_("operand is not an immediate"));
+ }
if (fixups->fix[fixups->fc].reloc == BFD_RELOC_16 ||
fixups->fix[fixups->fc].reloc == BFD_RELOC_D10V_18)
@@ -662,7 +669,7 @@ build_insn (opcode, opers, insn)
(flags & OPERAND_ADDR) ? true : false;
(fixups->fc)++;
}
-
+
/* Truncate to the proper number of bits. */
if ((opers[i].X_op == O_constant) && check_range (number, bits, flags))
as_bad (_("operand out of range: %lu"), number);
@@ -670,8 +677,8 @@ build_insn (opcode, opers, insn)
insn = insn | (number << shift);
}
- /* kludge: for DIVS, we need to put the operands in twice on the second
- pass, format is changed to LONG_R to force the second set of operands
+ /* kludge: for DIVS, we need to put the operands in twice on the second
+ pass, format is changed to LONG_R to force the second set of operands
to not be shifted over 15. */
if ((opcode->opcode == OPCODE_DIVS) && (format == LONG_L))
insn = build_insn (opcode, opers, insn);
@@ -728,8 +735,8 @@ write_1_short (opcode, insn, fx)
if (opcode->exec_type & PARONLY)
as_fatal (_("Instruction must be executed in parallel with another instruction."));
- /* The other container needs to be NOP.
- According to 4.3.1: for FM=00, sub-instructions performed only by IU
+ /* The other container needs to be NOP.
+ According to 4.3.1: for FM=00, sub-instructions performed only by IU
cannot be encoded in L-container. */
if (opcode->unit == IU)
insn |= FM00 | (NOP << 15); /* Right container. */
@@ -941,11 +948,10 @@ parallel_ok (op1, insn1, op2, insn2, exec_type)
|| (op1->unit == MU && op2->unit == MU))
return 0;
- /* If this is auto parallization, and either instruction is a branch,
- don't parallel. */
+ /* If this is auto parallelization, and the first instruction is a
+ branch or should not be packed, then don't parallelize. */
if (exec_type == PACK_UNSPEC
- && (op1->exec_type & (ALONE | BRANCH)
- || op2->exec_type & (ALONE | BRANCH)))
+ && (op1->exec_type & (ALONE | BRANCH)))
return 0;
/* The idea here is to create two sets of bitmasks (mod and used)
@@ -963,8 +969,8 @@ parallel_ok (op1, insn1, op2, insn2, exec_type)
and the second reads the PSW (which includes C, F0, and F1), then
they cannot operate safely in parallel. */
- /* The bitmasks (mod and used) look like this (bit 31 = MSB).
- r0-r15 0-15
+ /* The bitmasks (mod and used) look like this (bit 31 = MSB).
+ r0-r15 0-15
a0-a1 16-17
cr (not psw) 18
psw 19
@@ -1051,13 +1057,13 @@ parallel_ok (op1, insn1, op2, insn2, exec_type)
/* Determine if there are any resource conflicts among two manually
parallelized instructions. Some of this was lifted from parallel_ok. */
-static void
+static void
check_resource_conflict (op1, insn1, op2, insn2)
struct d10v_opcode *op1, *op2;
unsigned long insn1, insn2;
{
int i, j, flags, mask, shift, regno;
- unsigned long ins, mod[2], used[2];
+ unsigned long ins, mod[2];
struct d10v_opcode *op;
if ((op1->exec_type & SEQ)
@@ -1076,20 +1082,17 @@ check_resource_conflict (op1, insn1, op2, insn2)
return;
}
- /* The idea here is to create two sets of bitmasks (mod and used)
- which indicate which registers are modified or used by each
- instruction. The operation can only be done in parallel if
- instruction 1 and instruction 2 modify different registers, and
- the first instruction does not modify registers that the second
- is using (The second instruction can modify registers that the
- first is using as they are only written back after the first
- instruction has completed). Accesses to control registers
- and memory are treated as accesses to a single register. So if
- both instructions write memory or if the first instruction writes
- memory and the second reads, then they cannot be done in
- parallel. We treat reads to the PSW (which includes C, F0, and F1)
- in isolation. So simultaneously writing C and F0 in two different
- sub-instructions is permitted. */
+ /* See if both instructions write to the same resource.
+
+ The idea here is to create two sets of bitmasks (mod and used) which
+ indicate which registers are modified or used by each instruction.
+ The operation can only be done in parallel if neither instruction
+ modifies the same register. Accesses to control registers and memory
+ are treated as accesses to a single register. So if both instructions
+ write memory or if the first instruction writes memory and the second
+ reads, then they cannot be done in parallel. We treat reads to the PSW
+ (which includes C, F0, and F1) in isolation. So simultaneously writing
+ C and F0 in two different sub-instructions is permitted. */
/* The bitmasks (mod and used) look like this (bit 31 = MSB).
r0-r15 0-15
@@ -1112,7 +1115,7 @@ check_resource_conflict (op1, insn1, op2, insn2)
op = op2;
ins = insn2;
}
- mod[j] = used[j] = 0;
+ mod[j] = 0;
if (op->exec_type & BRANCH_LINK)
mod[j] |= 1 << 13;
@@ -1127,54 +1130,43 @@ check_resource_conflict (op1, insn1, op2, insn2)
if (flags & (OPERAND_ACC0 | OPERAND_ACC1))
regno += 16;
else if (flags & OPERAND_CONTROL) /* mvtc or mvfc */
- {
+ {
if (regno == 0)
regno = 19;
else
- regno = 18;
+ regno = 18;
}
else if (flags & OPERAND_FFLAG)
regno = 22;
else if (flags & OPERAND_CFLAG)
regno = 21;
-
- if ( flags & OPERAND_DEST )
+
+ if (flags & OPERAND_DEST
+ /* Auto inc/dec also modifies the register. */
+ || (op->operands[i + 1] != 0
+ && (d10v_operands[op->operands[i + 1]].flags
+ & (OPERAND_PLUS | OPERAND_MINUS)) != 0))
{
mod[j] |= 1 << regno;
if (flags & OPERAND_EVEN)
mod[j] |= 1 << (regno + 1);
}
- else
- {
- used[j] |= 1 << regno ;
- if (flags & OPERAND_EVEN)
- used[j] |= 1 << (regno + 1);
-
- /* Auto inc/dec also modifies the register. */
- if (op->operands[i+1] != 0
- && (d10v_operands[op->operands[i+1]].flags
- & (OPERAND_PLUS | OPERAND_MINUS)) != 0)
- mod[j] |= 1 << regno;
- }
}
else if (flags & OPERAND_ATMINUS)
{
/* SP implicitly used/modified. */
mod[j] |= 1 << 15;
- used[j] |= 1 << 15;
}
}
- if (op->exec_type & RMEM)
- used[j] |= 1 << 20;
- else if (op->exec_type & WMEM)
+
+ if (op->exec_type & WMEM)
mod[j] |= 1 << 20;
- else if (op->exec_type & RF0)
- used[j] |= 1 << 22;
else if (op->exec_type & WF0)
mod[j] |= 1 << 22;
else if (op->exec_type & WCAR)
mod[j] |= 1 << 21;
}
+
if ((mod[0] & mod[1]) == 0)
return;
else
@@ -1198,7 +1190,7 @@ check_resource_conflict (op1, insn1, op2, insn2)
}
/* This is the main entry point for the machine-dependent assembler.
- STR points to a machine-dependent instruction. This function is
+ str points to a machine-dependent instruction. This function is
supposed to emit the frags/bytes it assembles to. For the D10V, it
mostly handles the special VLIW parsing and packing and leaves the
difficult stuff to do_assemble(). */
@@ -1294,7 +1286,7 @@ md_assemble (str)
d10v_cleanup ();
if (prev_opcode
- && (0 == write_2_short (prev_opcode, prev_insn, opcode, insn, extype,
+ && (0 == write_2_short (prev_opcode, prev_insn, opcode, insn, extype,
fixups)))
{
/* No instructions saved. */
@@ -1520,7 +1512,7 @@ find_opcode (opcode, myops)
}
match = 0;
-
+
/* Now search the opcode table table for one with operands
that matches what we've got. */
while (!match)
@@ -1562,19 +1554,19 @@ find_opcode (opcode, myops)
break;
}
- /* Unfortunatly, for the indirect operand in instructions such
- as ``ldb r1, @(c,r14)'' this function can be passed
- X_op == O_register (because 'c' is a valid register name).
- However we cannot just ignore the case when X_op == O_register
- but flags & OPERAND_REG is null, so we check to see if a symbol
- of the same name as the register exists. If the symbol does
- exist, then the parser was unable to distinguish the two cases
+ /* Unfortunatly, for the indirect operand in instructions such
+ as ``ldb r1, @(c,r14)'' this function can be passed
+ X_op == O_register (because 'c' is a valid register name).
+ However we cannot just ignore the case when X_op == O_register
+ but flags & OPERAND_REG is null, so we check to see if a symbol
+ of the same name as the register exists. If the symbol does
+ exist, then the parser was unable to distinguish the two cases
and we fix things here. (Ref: PR14826) */
if (!(flags & OPERAND_REG) && (X_op == O_register))
{
symbolS * sym;
-
+
sym = find_symbol_matching_register (& myops[i]);
if (sym != NULL)
@@ -1769,13 +1761,13 @@ md_apply_fix3 (fixP, valP, seg)
XXX - Do we have to worry about branches to a symbol + offset ? */
if (fixP->fx_addsy != NULL
&& S_IS_EXTERN (fixP->fx_addsy) )
- {
- segT fseg = S_GET_SEGMENT (fixP->fx_addsy);
- segment_info_type *segf = seg_info(fseg);
+ {
+ segT fseg = S_GET_SEGMENT (fixP->fx_addsy);
+ segment_info_type *segf = seg_info(fseg);
if ( segf && segf->sym != fixP->fx_addsy)
value = 0;
- }
+ }
/* Drop through. */
case BFD_RELOC_D10V_18:
/* Instruction addresses are always right-shifted by 2. */
@@ -1789,9 +1781,9 @@ md_apply_fix3 (fixP, valP, seg)
rep = (struct d10v_opcode *) hash_find (d10v_hash, "rep");
repi = (struct d10v_opcode *) hash_find (d10v_hash, "repi");
if ((insn & FM11) == FM11
- && ((repi != NULL
+ && ((repi != NULL
&& (insn & repi->mask) == (unsigned) repi->opcode)
- || (rep != NULL
+ || (rep != NULL
&& (insn & rep->mask) == (unsigned) rep->opcode))
&& value < 4)
as_fatal