* config/tc-sparc.c (last_insn): New static variable.

(md_assemble): Warn about putting floating point branches in a
	delay slot.  If architecture is less than v9, insert NOP
	instructions between floating point instructions and floating
	point branches.  (The SunOS assembler does both these operations.)
	Save the last instruction opcode.
	(sparc_ip): Add pinsn parameter.  Change caller.
PR 355.
This commit is contained in:
Ian Lance Taylor
1996-04-11 21:35:01 +00:00
parent 1dd37c4885
commit ed94c2b89d
2 changed files with 54 additions and 5 deletions

View File

@ -1,5 +1,13 @@
Thu Apr 11 12:39:02 1996 Ian Lance Taylor <ian@cygnus.com> Thu Apr 11 12:39:02 1996 Ian Lance Taylor <ian@cygnus.com>
* config/tc-sparc.c (last_insn): New static variable.
(md_assemble): Warn about putting floating point branches in a
delay slot. If architecture is less than v9, insert NOP
instructions between floating point instructions and floating
point branches. (The SunOS assembler does both these operations.)
Save the last instruction opcode.
(sparc_ip): Add pinsn parameter. Change caller.
* config/tc-m68k.c (md_estimate_size_before_relax): Correct check * config/tc-m68k.c (md_estimate_size_before_relax): Correct check
for byte jump to next instruction to skip empty frags. for byte jump to next instruction to skip empty frags.

View File

@ -26,7 +26,7 @@
/* careful, this file includes data *declarations* */ /* careful, this file includes data *declarations* */
#include "opcode/sparc.h" #include "opcode/sparc.h"
static void sparc_ip PARAMS ((char *)); static void sparc_ip PARAMS ((char *, const struct sparc_opcode **));
/* Current architecture. We don't bump up unless necessary. */ /* Current architecture. We don't bump up unless necessary. */
static enum sparc_opcode_arch_val current_architecture = SPARC_OPCODE_ARCH_V6; static enum sparc_opcode_arch_val current_architecture = SPARC_OPCODE_ARCH_V6;
@ -180,6 +180,9 @@ static int special_case;
#define SPECIAL_CASE_SET 1 #define SPECIAL_CASE_SET 1
#define SPECIAL_CASE_FDIV 2 #define SPECIAL_CASE_FDIV 2
/* The last instruction to be assembled. */
static const struct sparc_opcode *last_insn;
/* /*
* sort of like s_lcomm * sort of like s_lcomm
* *
@ -660,8 +663,15 @@ sparc_md_end ()
bfd_set_arch_mach (stdoutput, bfd_arch_sparc, bfd_mach_sparc_v8plus); bfd_set_arch_mach (stdoutput, bfd_arch_sparc, bfd_mach_sparc_v8plus);
else if (current_architecture == SPARC_OPCODE_ARCH_V9A) else if (current_architecture == SPARC_OPCODE_ARCH_V9A)
bfd_set_arch_mach (stdoutput, bfd_arch_sparc, bfd_mach_sparc_v8plusa); bfd_set_arch_mach (stdoutput, bfd_arch_sparc, bfd_mach_sparc_v8plusa);
else if (current_architecture == SPARC_OPCODE_ARCH_SPARCLET)
bfd_set_arch_mach (stdoutput, bfd_arch_sparc, bfd_mach_sparc_sparclet);
else else
bfd_set_arch_mach (stdoutput, bfd_arch_sparc, bfd_mach_sparc); {
/* The sparclite is treated like a normal sparc. Perhaps it shouldn't
be but for now it is (since that's the way it's always been
treated). */
bfd_set_arch_mach (stdoutput, bfd_arch_sparc, bfd_mach_sparc);
}
#endif #endif
} }
@ -669,11 +679,34 @@ void
md_assemble (str) md_assemble (str)
char *str; char *str;
{ {
const struct sparc_opcode *insn;
char *toP; char *toP;
int rsd; int rsd;
know (str); know (str);
sparc_ip (str); sparc_ip (str, &insn);
/* We warn about attempts to put a floating point branch in a delay
slot. */
if (insn != NULL
&& last_insn != NULL
&& (insn->flags & F_FBR) != 0
&& (last_insn->flags & F_DELAYED) != 0)
as_warn ("FP branch in delay slot");
/* SPARC before v9 requires a nop instruction between a floating
point instruction and a floating point branch. We insert one
automatically, with a warning. */
if (max_architecture < SPARC_OPCODE_ARCH_V9
&& insn != NULL
&& last_insn != NULL
&& (insn->flags & F_FBR) != 0
&& (last_insn->flags & F_FLOAT) != 0)
{
as_warn ("FP branch preceded by FP instruction; NOP inserted");
toP = frag_more (4);
md_number_to_chars (toP, (valueT) 0x01000000, 4);
}
/* See if "set" operand is absolute and small; skip sethi if so. */ /* See if "set" operand is absolute and small; skip sethi if so. */
if (special_case == SPECIAL_CASE_SET if (special_case == SPECIAL_CASE_SET
@ -705,6 +738,8 @@ md_assemble (str)
the_insn.reloc); the_insn.reloc);
} }
last_insn = insn;
switch (special_case) switch (special_case)
{ {
case SPECIAL_CASE_SET: case SPECIAL_CASE_SET:
@ -821,8 +856,9 @@ parse_const_expr_arg (input_pointerP, valueP)
} }
static void static void
sparc_ip (str) sparc_ip (str, pinsn)
char *str; char *str;
const struct sparc_opcode **pinsn;
{ {
char *error_message = ""; char *error_message = "";
char *s; char *s;
@ -858,6 +894,7 @@ sparc_ip (str)
as_fatal ("Unknown opcode: `%s'", str); as_fatal ("Unknown opcode: `%s'", str);
} }
insn = (struct sparc_opcode *) hash_find (op_hash, str); insn = (struct sparc_opcode *) hash_find (op_hash, str);
*pinsn = insn;
if (insn == NULL) if (insn == NULL)
{ {
as_bad ("Unknown opcode: `%s'", str); as_bad ("Unknown opcode: `%s'", str);
@ -1243,6 +1280,7 @@ sparc_ip (str)
break; break;
case 'r': /* next operand must be a register */ case 'r': /* next operand must be a register */
case 'O':
case '1': case '1':
case '2': case '2':
case 'd': case 'd':
@ -1337,7 +1375,6 @@ sparc_ip (str)
it goes in the opcode. */ it goes in the opcode. */
switch (*args) switch (*args)
{ {
case '1': case '1':
opcode |= mask << 14; opcode |= mask << 14;
continue; continue;
@ -1353,6 +1390,10 @@ sparc_ip (str)
case 'r': case 'r':
opcode |= (mask << 25) | (mask << 14); opcode |= (mask << 25) | (mask << 14);
continue; continue;
case 'O':
opcode |= (mask << 25) | (mask << 0);
continue;
} }
} }
break; break;