static symbolS *d30v_last_label;
/* Two nops */
-#define NOP_LEFT ((long long)NOP << 32)
-#define NOP_RIGHT ((long long)NOP)
+#define NOP_LEFT ((long long) NOP << 32)
+#define NOP_RIGHT ((long long) NOP)
#define NOP2 (FM00 | NOP_LEFT | NOP_RIGHT)
/* local functions */
if ((num > max) || (num < min))
retval = 1;
}
+
return retval;
}
void
md_begin ()
{
- struct d30v_opcode *opcode;
+ struct d30v_opcode * opcode;
d30v_hash = hash_new ();
/* Insert opcode names into a hash table. */
fx->fc = 0;
}
-/* Write out a short form instruction if possible; */
-/* return number of instructions not written out. */
+/* Write out a short form instruction if possible.
+ Return number of instructions not written out. */
static int
write_2_short (opcode1, insn1, opcode2, insn2, exec_type, fx)
struct d30v_insn *opcode1, *opcode2;
if (exec_type == EXEC_SEQ
&& (opcode1->op->flags_used & (FLAG_JMP | FLAG_JSR))
+ && ((opcode1->op->flags_used & FLAG_DELAY) == 0)
&& ((opcode1->ecc == ECC_AL) || ! Optimizing))
{
- /* Unconditional branches kill instructions in the right bin.
- Conditional branches don't always but if we are not
- optimizing, then we want to produce an error about such
- constructs. For the purposes of this test, subroutine
- calls are considered to be branches. */
+ /* Unconditional, non-delayed branches kill instructions in
+ the right bin. Conditional branches don't always but if
+ we are not optimizing, then we have been asked to produce
+ an error about such constructs. For the purposes of this
+ test, subroutine calls are considered to be branches. */
write_1_short (opcode1, insn1, fx->next, false);
return 1;
}
}
}
else if (opcode1->op->flags_used & (FLAG_JMP | FLAG_JSR)
+ && ((opcode1->op->flags_used & FLAG_DELAY) == 0)
&& ((opcode1->ecc == ECC_AL) || ! Optimizing))
{
- /* We must emit branch type instruction on its own with
- nothing in the right container. */
+ /* We must emit (non-delayed) branch type instructions
+ on their own with nothing in the right container. */
write_1_short (opcode1, insn1, fx->next, false);
return 1;
}
case EXEC_PARALLEL: /* parallel */
flag_explicitly_parallel = flag_xp_state;
if (! parallel_ok (opcode1, insn1, opcode2, insn2, exec_type))
- as_fatal (_("Instructions may not be executed in parallel"));
+ as_bad (_("Instructions may not be executed in parallel"));
else if (opcode1->op->unit == IU)
{
if (opcode2->op->unit == IU)
- as_fatal (_("Two IU instructions may not be executed in parallel"));
+ as_bad (_("Two IU instructions may not be executed in parallel"));
as_warn (_("Swapping instruction order"));
insn = FM00 | (insn2 << 32) | insn1;
}
else if (opcode2->op->unit == MU)
{
if (opcode1->op->unit == MU)
- as_fatal (_("Two MU instructions may not be executed in parallel"));
+ as_bad (_("Two MU instructions may not be executed in parallel"));
else if (opcode1->op->unit == EITHER_BUT_PREFER_MU)
as_warn (_("Executing %s in IU may not work"), opcode1->op->name);
as_warn (_("Swapping instruction order"));
case EXEC_SEQ: /* sequential */
if (opcode1->op->unit == IU)
- as_fatal (_("IU instruction may not be in the left container"));
+ as_bad (_("IU instruction may not be in the left container"));
if (prev_left_kills_right_p)
- as_warn (_("special left instruction `%s' kills instruction "
+ as_bad (_("special left instruction `%s' kills instruction "
"`%s' in right container"),
opcode1->op->name, opcode2->op->name);
if (opcode2->op->unit == EITHER_BUT_PREFER_MU)
case EXEC_REVSEQ: /* reverse sequential */
if (opcode2->op->unit == MU)
- as_fatal (_("MU instruction may not be in the right container"));
+ as_bad (_("MU instruction may not be in the right container"));
if (opcode2->op->unit == EITHER_BUT_PREFER_MU)
as_warn (_("Executing %s in IU may not work"), opcode2->op->name);
insn = FM10 | (insn1 << 32) | insn2;
}
}
}
-
+
flags_set1 = op1->op->flags_set;
flags_set2 = op2->op->flags_set;
flags_used1 = op1->op->flags_used;
don't trust the human if both instructions modify the same
register but we do trust the human if they modify the same
flags. */
+ /* We have now been requested not to trust the human if the
+ instructions modify the same flag registers either. */
if (flag_explicitly_parallel)
{
- if ((j < 2) && (mod_reg[0][j] & mod_reg[1][j]) != 0)
+ if ((mod_reg[0][j] & mod_reg[1][j]) != 0)
return 0;
}
else
/* Assemble first instruction and save it. */
prev_insn = do_assemble (str, &prev_opcode, 1, 0);
if (prev_insn == -1)
- as_fatal (_("Cannot assemble instruction"));
+ as_bad (_("Cannot assemble instruction"));
if (prev_opcode.form->form >= LONG)
- as_fatal (_("First opcode is long. Unable to mix instructions as specified."));
+ as_bad (_("First opcode is long. Unable to mix instructions as specified."));
fixups = fixups->next;
str = str2 + 2;
prev_seg = now_seg;
etype = extype;
return;
}
- as_fatal (_("Cannot assemble instruction"));
+ as_bad (_("Cannot assemble instruction"));
}
if (etype != EXEC_UNKNOWN)
if (opcode.form->form >= LONG)
{
if (extype != EXEC_UNKNOWN)
- as_fatal (_("Instruction uses long version, so it cannot be mixed as specified"));
+ as_bad (_("Instruction uses long version, so it cannot be mixed as specified"));
d30v_cleanup (false);
write_long (& opcode, insn, fixups);
prev_insn = -1;
}
- else if ((prev_insn != -1) &&
- (write_2_short
- (& prev_opcode, (long) prev_insn, & opcode, (long) insn, extype, fixups) == 0))
+ else if ((prev_insn != -1)
+ && (write_2_short
+ (& prev_opcode, (long) prev_insn, & opcode,
+ (long) insn, extype, fixups) == 0))
{
/* No instructions saved. */
prev_insn = -1;
else
{
if (extype != EXEC_UNKNOWN)
- as_fatal (_("Unable to mix instructions as specified"));
+ as_bad (_("Unable to mix instructions as specified"));
/* Save off last instruction so it may be packed on next pass. */
memcpy (&prev_opcode, &opcode, sizeof (prev_opcode));
}
if (nlen == 0)
- return (-1);
+ return -1;
name[nlen] = 0;
char tmp[4];
strncpy (tmp, op_end + 1, 2);
tmp[2] = 0;
- as_fatal (_("unknown condition code: %s"),tmp);
+ as_bad (_("unknown condition code: %s"),tmp);
return -1;
}
- /* printf("condition code=%d\n",i); */
+ /* printf ("condition code=%d\n",i); */
opcode->ecc = i;
op_end += 3;
}
if (i < 3 || i > 6)
{
name[p+2]=0;
- as_fatal (_("cmpu doesn't support condition code %s"),&name[p]);
+ as_bad (_("cmpu doesn't support condition code %s"),&name[p]);
}
}
if (!*str)
{
name[p+2]=0;
- as_fatal (_("unknown condition code: %s"),&name[p]);
+ as_bad (_("unknown condition code: %s"),&name[p]);
}
cmp_hack = i;
/* find the first opcode with the proper name */
opcode->op = (struct d30v_opcode *)hash_find (d30v_hash, name);
if (opcode->op == NULL)
- as_fatal (_("unknown opcode: %s"),name);
+ as_bad (_("unknown opcode: %s"),name);
save = input_line_pointer;
input_line_pointer = op_end;
{
opcode->op++;
if (strcmp (opcode->op->name, name))
- as_fatal (_("operands for opcode `%s' do not match any valid format"), name);
+ as_bad (_("operands for opcode `%s' do not match any valid format"), name);
}
input_line_pointer = save;
|| ((flags & OPERAND_ACC) && !(num & OPERAND_ACC))
|| (!(flags & OPERAND_ACC) && (num & OPERAND_ACC))
|| ((flags & OPERAND_FLAG) && !(num & OPERAND_FLAG))
- || (!(flags & OPERAND_FLAG) && (num & OPERAND_FLAG))
+ || (!(flags & (OPERAND_FLAG | OPERAND_CONTROL)) && (num & OPERAND_FLAG))
|| ((flags & OPERAND_CONTROL)
&& !(num & (OPERAND_CONTROL | OPERAND_FLAG))))
{
/* printf("through the loop: match=%d\n",match); */
/* We're only done if the operands matched so far AND there
are no more to check. */
- if (match && myops[j].X_op == 0)
- return fm;
+ if (match && myops[j].X_op == 0)
+ {
+ /* Final check - issue a warning if an odd numbered register
+ is used as the first register in an instruction that reads
+ or writes 2 registers. */
+
+ for (j = 0; fm->operands[j]; j++)
+ if (myops[j].X_op == O_register
+ && (myops[j].X_add_number & 1)
+ && (d30v_operand_table[fm->operands[j]].flags & OPERAND_2REG))
+ as_warn (\
+_("Odd numbered register used as target of multi-register instruction"));
+
+ return fm;
+ }
fm = (struct d30v_format *)&d30v_format_table[++k];
}
/* printf("trying another format: i=%d\n",i); */
int
md_apply_fix3 (fixp, valuep, seg)
- fixS *fixp;
- valueT *valuep;
+ fixS * fixp;
+ valueT * valuep;
segT seg;
{
- char *where;
+ char * where;
unsigned long insn, insn2;
long value;
-
+
if (fixp->fx_addsy == (symbolS *) NULL)
{
- value = *valuep;
+ value = * valuep;
fixp->fx_done = 1;
}
else if (fixp->fx_pcrel)
- {
- value = *valuep;
- }
+ value = * valuep;
else
{
value = fixp->fx_offset;
+
if (fixp->fx_subsy != (symbolS *) NULL)
{
if (S_GET_SEGMENT (fixp->fx_subsy) == absolute_section)
switch (fixp->fx_r_type)
{
- case BFD_RELOC_8:
- /* Caused by a bad .byte directive. */
- as_fatal (_("line %d: unable to place address of symbol '%s' into a byte"),
- fixp->fx_line, S_GET_NAME (fixp->fx_addsy));
- break;
+ case BFD_RELOC_8: /* Caused by a bad .byte directive. */
+ /* Drop trhough. */
- case BFD_RELOC_16:
- /* Caused by a bad .short directive. */
- as_fatal (_("line %d: unable to place address of symbol '%s' into a short"),
- fixp->fx_line, S_GET_NAME (fixp->fx_addsy));
- break;
+ case BFD_RELOC_16: /* Caused by a bad .short directive. */
+ /* Drop through. */
- case BFD_RELOC_64:
- /* Caused by a bad .quad directive. */
- as_fatal (_("line %d: unable to place address of symbol '%s' into a .quad"),
- fixp->fx_line, S_GET_NAME (fixp->fx_addsy));
- break;
+ case BFD_RELOC_64: /* Caused by a bad .quad directive. */
+ {
+ char * size;
+
+ size = (fixp->fx_r_type == BFD_RELOC_8) ? _("byte")
+ : (fixp->fx_r_type == BFD_RELOC_16) ? _("short")
+ : _("quad");
+
+ if (fixp->fx_addsy == NULL)
+ as_bad (_("line %d: unable to place address into a %s"),
+ fixp->fx_line, size);
+ else
+ as_bad (_("line %d: unable to place address of symbol '%s' into a %s"),
+ fixp->fx_line,
+ S_GET_NAME (fixp->fx_addsy),
+ size);
+ break;
+ }
case BFD_RELOC_D30V_6:
check_size (value, 6, fixp->fx_file, fixp->fx_line);
break;
default:
- as_fatal (_("line %d: unknown relocation type: 0x%x"),fixp->fx_line,fixp->fx_r_type);
+ as_bad (_("line %d: unknown relocation type: 0x%x"),
+ fixp->fx_line,fixp->fx_r_type);
}
+
return 0;
}