* app.c (do_scrub_begin): Let line_comment_chars override

comment_chars.
	(do_scrub_next_char): If a line comment character is not at the
	start of a line, treat it as a comment character if it is one.
	For a CPP line comment use pseudo-op .appline rather than .line.
	* input-scrub.c (logical_input_line): Make int rather than
	unsigned.
	(input_scrub_push, input_scrub_begin): Initialize
	logical_input_line to -1 rather than 0.
	(bump_line_counters): Increment logical_input_line.
	(new_logical_line): If line_number is -2, decrement
	logical_input_line.
	(as_where): Use logical_input_line even if it is 0.
	* read.h (s_app_file prototype): Now takes an int argument.
	* read.c (potable): Make .appfile call s_app_file with 1.  New
	.appline pseudo-op calls s_app_line.
	(s_app_file): If .appfile, call new_logical_line with -2 to
	account for newline inserted by do_scrub_next_char.  If listing,
	call listing_source_file.
	(s_app_line): New function to handle fake pseudo-op .appline.
	* config/obj-coff.c (obj_pseudo_table): Make .appline call
	obj_coff_ln.
	(obj_coff_ln): Added argument to indicate whether .appline.
	* config/obj-coffbfd.c (obj_pseudo_table): Make .appline call
	obj_coff_ln.
	(obj_coff_ln): Added argument to indicate whether .appline.
	* config/tc-mips.c (s_file): Pass argument to s_app_file.
This commit is contained in:
Ian Lance Taylor 1993-05-27 19:29:38 +00:00
parent d34094e8e0
commit 9a7d824a26
5 changed files with 360 additions and 199 deletions

View file

@ -1,3 +1,33 @@
Thu May 27 11:07:50 1993 Ian Lance Taylor (ian@cygnus.com)
* app.c (do_scrub_begin): Let line_comment_chars override
comment_chars.
(do_scrub_next_char): If a line comment character is not at the
start of a line, treat it as a comment character if it is one.
For a CPP line comment use pseudo-op .appline rather than .line.
* input-scrub.c (logical_input_line): Make int rather than
unsigned.
(input_scrub_push, input_scrub_begin): Initialize
logical_input_line to -1 rather than 0.
(bump_line_counters): Increment logical_input_line.
(new_logical_line): If line_number is -2, decrement
logical_input_line.
(as_where): Use logical_input_line even if it is 0.
* read.h (s_app_file prototype): Now takes an int argument.
* read.c (potable): Make .appfile call s_app_file with 1. New
.appline pseudo-op calls s_app_line.
(s_app_file): If .appfile, call new_logical_line with -2 to
account for newline inserted by do_scrub_next_char. If listing,
call listing_source_file.
(s_app_line): New function to handle fake pseudo-op .appline.
* config/obj-coff.c (obj_pseudo_table): Make .appline call
obj_coff_ln.
(obj_coff_ln): Added argument to indicate whether .appline.
* config/obj-coffbfd.c (obj_pseudo_table): Make .appline call
obj_coff_ln.
(obj_coff_ln): Added argument to indicate whether .appline.
* config/tc-mips.c (s_file): Pass argument to s_app_file.
Tue May 25 11:59:07 1993 Ian Lance Taylor (ian@cygnus.com) Tue May 25 11:59:07 1993 Ian Lance Taylor (ian@cygnus.com)
* config/obj-bout.h (S_GET_VALUE): Removed unnecessary cast. * config/obj-bout.h (S_GET_VALUE): Removed unnecessary cast.

162
gas/app.c
View file

@ -23,7 +23,7 @@
/* App, the assembler pre-processor. This pre-processor strips out excess /* App, the assembler pre-processor. This pre-processor strips out excess
spaces, turns single-quoted characters into a decimal constant, and turns spaces, turns single-quoted characters into a decimal constant, and turns
# <number> <filename> <garbage> into a .line <number>\n.app-file <filename> # <number> <filename> <garbage> into a .line <number>\n.file <filename>
pair. This needs better error-handling. pair. This needs better error-handling.
*/ */
@ -87,16 +87,16 @@ do_scrub_begin ()
lex[*p] = LEX_IS_SYMBOL_COMPONENT; lex[*p] = LEX_IS_SYMBOL_COMPONENT;
} /* declare symbol characters */ } /* declare symbol characters */
for (p = line_comment_chars; *p; p++)
{
lex[*p] = LEX_IS_LINE_COMMENT_START;
} /* declare line comment chars */
for (p = comment_chars; *p; p++) for (p = comment_chars; *p; p++)
{ {
lex[*p] = LEX_IS_COMMENT_START; lex[*p] = LEX_IS_COMMENT_START;
} /* declare comment chars */ } /* declare comment chars */
for (p = line_comment_chars; *p; p++)
{
lex[*p] = LEX_IS_LINE_COMMENT_START;
} /* declare line comment chars */
for (p = line_separator_chars; *p; p++) for (p = line_separator_chars; *p; p++)
{ {
lex[*p] = LEX_IS_LINE_SEPARATOR; lex[*p] = LEX_IS_LINE_SEPARATOR;
@ -247,19 +247,19 @@ do_scrub_next_char (get, unget)
4: after putting out a .line, put out digits 4: after putting out a .line, put out digits
5: parsing a string, then go to old-state 5: parsing a string, then go to old-state
6: putting out \ escape in a "d string. 6: putting out \ escape in a "d string.
7: After putting out a .app-file, put out string. 7: After putting out a .appfile, put out string.
8: After putting out a .app-file string, flush until newline. 8: After putting out a .appfile string, flush until newline.
9: After seeing symbol char in state 3 (keep 1white after symchar) 9: After seeing symbol char in state 3 (keep 1white after symchar)
10: After seeing whitespace in state 9 (keep white before symchar)
-1: output string in out_string and go to the state in old_state -1: output string in out_string and go to the state in old_state
-2: flush text until a '*' '/' is seen, then go to state old_state -2: flush text until a '*' '/' is seen, then go to state old_state
*/ */
/* I added state 9 because the MIPS ECOFF assembler uses constructs /* I added states 9 and 10 because the MIPS ECOFF assembler uses
like ``.loc 1 20''. This was turning into ``.loc 120''. State 9 constructs like ``.loc 1 20''. This was turning into ``.loc
ensures that a space is never dropped immediately following a 120''. States 9 and 10 ensure that a space is never dropped in
character which could appear in a identifier. It is still between characters which could appear in a identifier. Ian
dropped following a comma, so this has no effect for most Taylor, ian@cygnus.com. */
assemblers. I hope. Ian Taylor, ian@cygnus.com. */
register int ch, ch2 = 0; register int ch, ch2 = 0;
@ -308,7 +308,7 @@ do_scrub_next_char (get, unget)
if (ch == '"') if (ch == '"')
{ {
(*unget) (ch); (*unget) (ch);
out_string = "\n.app-file "; out_string = "\n.appfile ";
old_state = 7; old_state = 7;
state = -1; state = -1;
return *out_string++; return *out_string++;
@ -406,7 +406,7 @@ do_scrub_next_char (get, unget)
return ch; return ch;
} }
/* OK, we are somewhere in states 0 through 4 or 9 */ /* OK, we are somewhere in states 0 through 4 or 9 through 10 */
/* flushchar: */ /* flushchar: */
ch = (*get) (); ch = (*get) ();
@ -454,12 +454,15 @@ recycle:
case 1: case 1:
BAD_CASE (state); /* We can't get here */ BAD_CASE (state); /* We can't get here */
case 2: case 2:
case 9:
state = 3; state = 3;
(*unget) (ch); (*unget) (ch);
return ' '; /* Sp after opco */ return ' '; /* Sp after opco */
case 3: case 3:
goto recycle; /* Sp in operands */ goto recycle; /* Sp in operands */
case 9:
case 10:
state = 10; /* Sp after symbol char */
goto recycle;
default: default:
BAD_CASE (state); BAD_CASE (state);
} }
@ -501,12 +504,17 @@ recycle:
{ {
if (ch2 != EOF) if (ch2 != EOF)
(*unget) (ch2); (*unget) (ch2);
if (state == 9 || state == 10)
state = 3;
return ch; return ch;
} }
break; break;
case LEX_IS_STRINGQUOTE: case LEX_IS_STRINGQUOTE:
old_state = state; if (state == 9 || state == 10)
old_state = 3;
else
old_state = state;
state = 5; state = 5;
return ch; return ch;
#ifndef MRI #ifndef MRI
@ -526,8 +534,7 @@ recycle:
sprintf (out_buf, "%d", (int) (unsigned char) ch); sprintf (out_buf, "%d", (int) (unsigned char) ch);
/* None of these 'x constants for us. We want 'x'. /* None of these 'x constants for us. We want 'x'. */
*/
if ((ch = (*get) ()) != '\'') if ((ch = (*get) ()) != '\'')
{ {
#ifdef REQUIRE_CHAR_CLOSE_QUOTE #ifdef REQUIRE_CHAR_CLOSE_QUOTE
@ -540,14 +547,19 @@ recycle:
{ {
return out_buf[0]; return out_buf[0];
} }
old_state = state; if (state == 9 || state == 10)
old_state = 3;
else
old_state = state;
state = -1; state = -1;
out_string = out_buf; out_string = out_buf;
return *out_string++; return *out_string++;
#endif #endif
#endif #endif
case LEX_IS_COLON: case LEX_IS_COLON:
if (state != 3) if (state == 9 || state == 10)
state = 3;
else if (state != 3)
state = 0; state = 0;
return ch; return ch;
@ -565,53 +577,58 @@ recycle:
return ch; return ch;
case LEX_IS_LINE_COMMENT_START: case LEX_IS_LINE_COMMENT_START:
if (state != 0) /* Not at start of line, act normal */ if (state == 0) /* Only comment at start of line. */
goto de_fault;
/* FIXME-someday: The two character comment stuff was badly
thought out. On i386, we want '/' as line comment start AND
we want C style comments. hence this hack. The whole
lexical process should be reworked. xoxorich. */
if (ch == '/')
{ {
ch2 = (*get) (); /* FIXME-someday: The two character comment stuff was badly
if (ch2 == '*') thought out. On i386, we want '/' as line comment start
AND we want C style comments. hence this hack. The
whole lexical process should be reworked. xoxorich. */
if (ch == '/')
{ {
state = -2; ch2 = (*get) ();
return (do_scrub_next_char (get, unget)); if (ch2 == '*')
} {
else state = -2;
{ return (do_scrub_next_char (get, unget));
(*unget) (ch2); }
} else
} /* bad hack */ {
(*unget) (ch2);
}
} /* bad hack */
do do
ch = (*get) ();
while (ch != EOF && IS_WHITESPACE (ch));
if (ch == EOF)
{
as_warn ("EOF in comment: Newline inserted");
return '\n';
}
if (ch < '0' || ch > '9')
{
/* Non-numerics: Eat whole comment line */
while (ch != EOF && !IS_NEWLINE (ch))
ch = (*get) (); ch = (*get) ();
while (ch != EOF && IS_WHITESPACE (ch));
if (ch == EOF) if (ch == EOF)
as_warn ("EOF in Comment: Newline inserted"); {
state = 0; as_warn ("EOF in comment: Newline inserted");
return '\n'; return '\n';
}
if (ch < '0' || ch > '9')
{
/* Non-numerics: Eat whole comment line */
while (ch != EOF && !IS_NEWLINE (ch))
ch = (*get) ();
if (ch == EOF)
as_warn ("EOF in Comment: Newline inserted");
state = 0;
return '\n';
}
/* Numerics begin comment. Perhaps CPP `# 123 "filename"' */
(*unget) (ch);
old_state = 4;
state = -1;
out_string = ".appline ";
return *out_string++;
} }
/* Numerics begin comment. Perhaps CPP `# 123 "filename"' */
(*unget) (ch);
old_state = 4;
state = -1;
out_string = ".line ";
return *out_string++;
/* We have a line comment character which is not at the start of
a line. If this is also a normal comment character, fall
through. Otherwise treat it as a default character. */
if (strchr (comment_chars, ch) == NULL)
goto de_fault;
/* Fall through. */
case LEX_IS_COMMENT_START: case LEX_IS_COMMENT_START:
do do
ch = (*get) (); ch = (*get) ();
@ -622,6 +639,15 @@ recycle:
return '\n'; return '\n';
case LEX_IS_SYMBOL_COMPONENT: case LEX_IS_SYMBOL_COMPONENT:
if (state == 10)
{
/* This is a symbol character following another symbol
character, with whitespace in between. We skipped the
whitespace earlier, so output it now. */
(*unget) (ch);
state = 3;
return ' ';
}
if (state == 3) if (state == 3)
state = 9; state = 9;
/* Fall through. */ /* Fall through. */
@ -644,6 +670,11 @@ recycle:
state = 3; state = 3;
return ch; return ch;
} }
else if (state == 10)
{
state = 3;
return ch;
}
else else
{ {
return ch; /* Opcode or operands already */ return ch; /* Opcode or operands already */
@ -675,11 +706,4 @@ as_warn (str)
#endif #endif
/*
* Local Variables:
* comment-column: 0
* fill-column: 131
* End:
*/
/* end of app.c */ /* end of app.c */

View file

@ -142,7 +142,7 @@ static void EXFUN( obj_coff_bss,(void));
static void EXFUN( obj_coff_ident,(void)); static void EXFUN( obj_coff_ident,(void));
static void EXFUN (obj_coff_endef, (void)); static void EXFUN (obj_coff_endef, (void));
static void EXFUN (obj_coff_line, (void)); static void EXFUN (obj_coff_line, (void));
static void EXFUN (obj_coff_ln, (void)); static void EXFUN (obj_coff_ln, (int));
static void EXFUN (obj_coff_scl, (void)); static void EXFUN (obj_coff_scl, (void));
static void EXFUN (obj_coff_size, (void)); static void EXFUN (obj_coff_size, (void));
static void EXFUN (obj_coff_tag, (void)); static void EXFUN (obj_coff_tag, (void));
@ -163,6 +163,7 @@ const pseudo_typeS obj_pseudo_table[] =
{"endef", obj_coff_endef, 0}, {"endef", obj_coff_endef, 0},
{"line", obj_coff_line, 0}, {"line", obj_coff_line, 0},
{"ln", obj_coff_ln, 0}, {"ln", obj_coff_ln, 0},
{"appline", obj_coff_ln, 1},
{"scl", obj_coff_scl, 0}, {"scl", obj_coff_scl, 0},
{"size", obj_coff_size, 0}, {"size", obj_coff_size, 0},
{"tag", obj_coff_tag, 0}, {"tag", obj_coff_tag, 0},
@ -776,11 +777,12 @@ stack_top (st)
*/ */
static void static void
obj_coff_ln () obj_coff_ln (appline)
int appline;
{ {
int l; int l;
if (def_symbol_in_progress != NULL) if (! appline && def_symbol_in_progress != NULL)
{ {
as_warn (".ln pseudo-op inside .def/.endef: ignored."); as_warn (".ln pseudo-op inside .def/.endef: ignored.");
demand_empty_rest_of_line (); demand_empty_rest_of_line ();
@ -797,7 +799,9 @@ obj_coff_ln ()
if (listing) if (listing)
{ {
listing_source_line (l + line_base - 1); if (! appline)
l += line_base - 1;
listing_source_line (l);
} }
} }
@ -1095,7 +1099,7 @@ obj_coff_line ()
if (def_symbol_in_progress == NULL) if (def_symbol_in_progress == NULL)
{ {
obj_coff_ln (); obj_coff_ln (0);
return; return;
} /* if it looks like a stabs style line */ } /* if it looks like a stabs style line */

View file

@ -405,12 +405,27 @@ gp_reference (ep)
{ {
#ifdef OBJ_ECOFF #ifdef OBJ_ECOFF
symbolS *sym; symbolS *sym;
const char *symname;
const char *segname; const char *segname;
sym = ep->X_add_symbol; sym = ep->X_add_symbol;
if (sym == (symbolS *) NULL if (sym == (symbolS *) NULL
|| ep->X_subtract_symbol != (symbolS *) NULL) || ep->X_subtract_symbol != (symbolS *) NULL)
return 0; return 0;
/* Certain symbols can not be referenced off the GP, although it
appears as though they can. */
symname = S_GET_NAME (sym);
if (symname != (const char *) NULL
&& (strcmp (symname, "eprol") == 0
|| strcmp (symname, "etext") == 0
|| strcmp (symname, "_gp") == 0
|| strcmp (symname, "edata") == 0
|| strcmp (symname, "_fbss") == 0
|| strcmp (symname, "_fdata") == 0
|| strcmp (symname, "_ftext") == 0
|| strcmp (symname, "end") == 0))
return 0;
if (! S_IS_DEFINED (sym) if (! S_IS_DEFINED (sym)
&& S_GET_VALUE (sym) != 0 && S_GET_VALUE (sym) != 0
&& S_GET_VALUE (sym) <= g_switch_value) && S_GET_VALUE (sym) <= g_switch_value)
@ -883,13 +898,28 @@ macro (ip)
macro_build (&icnt, &offset_expr, "bgez", "s,p", sreg); macro_build (&icnt, &offset_expr, "bgez", "s,p", sreg);
return; return;
} }
if (sreg == 0)
{
macro_build (&icnt, &offset_expr, "blez", "s,p", treg);
return;
}
macro_build (&icnt, NULL, "slt", "d,v,t", AT, sreg, treg); macro_build (&icnt, NULL, "slt", "d,v,t", AT, sreg, treg);
macro_build (&icnt, &offset_expr, "beq", "s,t,p", AT, 0); macro_build (&icnt, &offset_expr, "beq", "s,t,p", AT, 0);
break; break;
case M_BGT_I: case M_BGT_I:
/* check for > max integer */
if (imm_expr.X_add_number == 0x7fffffff)
{
do_false:
/* result is always false */
as_warn ("Branch %s is always false (nop)", ip->insn_mo->name);
macro_build (&icnt, NULL, "nop", "", 0);
return;
}
imm_expr.X_add_number++; imm_expr.X_add_number++;
/* FALLTHROUGH */ /* FALLTHROUGH */
case M_BGE_I: case M_BGE_I:
if (imm_expr.X_add_number == 0) if (imm_expr.X_add_number == 0)
{ {
@ -901,26 +931,39 @@ macro (ip)
macro_build (&icnt, &offset_expr, "bgtz", "s,p", sreg); macro_build (&icnt, &offset_expr, "bgtz", "s,p", sreg);
return; return;
} }
if (imm_expr.X_add_number == 0x80000000)
{
do_true:
/* result is always true */
as_warn ("Branch %s is always true", ip->insn_mo->name);
macro_build (&icnt, &offset_expr, "b", "p");
return;
}
set_at (&icnt, sreg); set_at (&icnt, sreg);
macro_build (&icnt, &offset_expr, "beq", "s,t,p", AT, 0); macro_build (&icnt, &offset_expr, "beq", "s,t,p", AT, 0);
break; break;
case M_BGEU: case M_BGEU:
if (treg == 0) if (treg == 0)
goto do_true;
if (sreg == 0)
{ {
macro_build (&icnt, &offset_expr, "b", "p"); macro_build (&icnt, &offset_expr, "beq", "s,t,p", 0, treg);
return; return;
} }
macro_build (&icnt, NULL, "sltu", "d,v,t", AT, sreg, treg); macro_build (&icnt, NULL, "sltu", "d,v,t", AT, sreg, treg);
macro_build (&icnt, &offset_expr, "beq", "s,t,p", AT, 0); macro_build (&icnt, &offset_expr, "beq", "s,t,p", AT, 0);
break; break;
case M_BGTU_I:
if (sreg == 0 || imm_expr.X_add_number == 0xffffffff)
goto do_false;
imm_expr.X_add_number++;
/* FALLTHROUGH */
case M_BGEU_I: case M_BGEU_I:
if (imm_expr.X_add_number == 0) if (imm_expr.X_add_number == 0)
{ goto do_true;
macro_build (&icnt, &offset_expr, "b", "p");
return;
}
if (imm_expr.X_add_number == 1) if (imm_expr.X_add_number == 1)
{ {
macro_build (&icnt, &offset_expr, "bne", "s,t,p", sreg, 0); macro_build (&icnt, &offset_expr, "bne", "s,t,p", sreg, 0);
@ -936,6 +979,11 @@ macro (ip)
macro_build (&icnt, &offset_expr, "bgtz", "s,p", sreg); macro_build (&icnt, &offset_expr, "bgtz", "s,p", sreg);
return; return;
} }
if (sreg == 0)
{
macro_build (&icnt, &offset_expr, "bltz", "s,p", treg);
return;
}
macro_build (&icnt, NULL, "slt", "d,v,t", AT, treg, sreg); macro_build (&icnt, NULL, "slt", "d,v,t", AT, treg, sreg);
macro_build (&icnt, &offset_expr, "bne", "s,t,p", AT, 0); macro_build (&icnt, &offset_expr, "bne", "s,t,p", AT, 0);
break; break;
@ -946,89 +994,32 @@ macro (ip)
macro_build (&icnt, &offset_expr, "bne", "s,t,p", sreg, 0); macro_build (&icnt, &offset_expr, "bne", "s,t,p", sreg, 0);
return; return;
} }
if (sreg == 0)
goto do_false;
macro_build (&icnt, NULL, "sltu", "d,v,t", AT, treg, sreg); macro_build (&icnt, NULL, "sltu", "d,v,t", AT, treg, sreg);
macro_build (&icnt, &offset_expr, "bne", "s,t,p", AT, 0); macro_build (&icnt, &offset_expr, "bne", "s,t,p", AT, 0);
break; break;
case M_BGTU_I:
if (imm_expr.X_add_number == 0)
{
macro_build (&icnt, &offset_expr, "bne", "s,t,p", sreg, 0);
return;
}
if (imm_expr.X_add_number == -1)
{
/* NOP */
if (mips_noreorder)
as_warn ("Instruction %s is a nop; deleted", ip->insn_mo->name);
return;
}
imm_expr.X_add_number++;
set_at_unsigned (&icnt, sreg);
macro_build (&icnt, &offset_expr, "beq", "s,t,p", AT, 0);
break;
case M_BLE: case M_BLE:
if (treg == 0) if (treg == 0)
{ {
macro_build (&icnt, &offset_expr, "blez", "s,p", sreg); macro_build (&icnt, &offset_expr, "blez", "s,p", sreg);
return; return;
} }
if (sreg == 0)
{
macro_build (&icnt, &offset_expr, "bgez", "s,p", treg);
return;
}
macro_build (&icnt, NULL, "slt", "d,v,t", AT, treg, sreg); macro_build (&icnt, NULL, "slt", "d,v,t", AT, treg, sreg);
macro_build (&icnt, &offset_expr, "beq", "s,t,p", AT, 0); macro_build (&icnt, &offset_expr, "beq", "s,t,p", AT, 0);
break; break;
case M_BLE_I: case M_BLE_I:
if (imm_expr.X_add_number == 0) if (imm_expr.X_add_number == 0x7fffffff)
{ goto do_true;
macro_build (&icnt, &offset_expr, "blez", "s,p", sreg);
return;
}
if (imm_expr.X_add_number == -1)
{
macro_build (&icnt, &offset_expr, "bltz", "s,p", sreg);
return;
}
imm_expr.X_add_number++; imm_expr.X_add_number++;
set_at (&icnt, sreg); /* FALLTHROUGH */
macro_build (&icnt, &offset_expr, "bne", "s,t,p", AT, 0);
break;
case M_BLEU:
if (treg == 0)
{
macro_build (&icnt, &offset_expr, "beq", "s,t,p", sreg, 0);
return;
}
macro_build (&icnt, NULL, "sltu", "d,v,t", AT, treg, sreg);
macro_build (&icnt, &offset_expr, "beq", "s,t,p", AT, 0);
break;
case M_BLEU_I:
if (imm_expr.X_add_number == 0)
{
macro_build (&icnt, &offset_expr, "beq", "s,t,p", sreg, 0);
return;
}
if (imm_expr.X_add_number == -1)
{
macro_build (&icnt, &offset_expr, "b", "p");
return;
}
imm_expr.X_add_number++;
set_at_unsigned (&icnt, sreg);
macro_build (&icnt, &offset_expr, "bne", "s,t,p", AT, 0);
break;
case M_BLT:
if (treg == 0)
{
macro_build (&icnt, &offset_expr, "bltz", "s,p", sreg);
return;
}
macro_build (&icnt, NULL, "slt", "d,v,t", AT, sreg, treg);
macro_build (&icnt, &offset_expr, "bne", "s,t,p", AT, 0);
break;
case M_BLT_I: case M_BLT_I:
if (imm_expr.X_add_number == 0) if (imm_expr.X_add_number == 0)
@ -1045,26 +1036,27 @@ macro (ip)
macro_build (&icnt, &offset_expr, "bne", "s,t,p", AT, 0); macro_build (&icnt, &offset_expr, "bne", "s,t,p", AT, 0);
break; break;
case M_BLTU: case M_BLEU:
if (treg == 0) if (treg == 0)
{ {
/* NOP */ macro_build (&icnt, &offset_expr, "beq", "s,t,p", sreg, 0);
if (mips_noreorder)
as_warn ("Instruction %s is a nop; deleted", ip->insn_mo->name);
return; return;
} }
macro_build (&icnt, NULL, "sltu", "d,v,t", AT, sreg, treg); if (sreg == 0)
macro_build (&icnt, &offset_expr, "bne", "s,t,p", AT, 0); goto do_true;
macro_build (&icnt, NULL, "sltu", "d,v,t", AT, treg, sreg);
macro_build (&icnt, &offset_expr, "beq", "s,t,p", AT, 0);
break; break;
case M_BLEU_I:
if (sreg == 0 || imm_expr.X_add_number == 0xffffffff)
goto do_true;
imm_expr.X_add_number++;
/* FALLTHROUGH */
case M_BLTU_I: case M_BLTU_I:
if (imm_expr.X_add_number == 0) if (imm_expr.X_add_number == 0)
{ goto do_false;
/* NOP */
if (mips_noreorder)
as_warn ("Instruction %s is a nop; deleted", ip->insn_mo->name);
return;
}
if (imm_expr.X_add_number == 1) if (imm_expr.X_add_number == 1)
{ {
macro_build (&icnt, &offset_expr, "beq", "s,t,p", sreg, 0); macro_build (&icnt, &offset_expr, "beq", "s,t,p", sreg, 0);
@ -1074,6 +1066,33 @@ macro (ip)
macro_build (&icnt, &offset_expr, "bne", "s,t,p", AT, 0); macro_build (&icnt, &offset_expr, "bne", "s,t,p", AT, 0);
break; break;
case M_BLT:
if (treg == 0)
{
macro_build (&icnt, &offset_expr, "bltz", "s,p", sreg);
return;
}
if (sreg == 0)
{
macro_build (&icnt, &offset_expr, "bgtz", "s,p", treg);
return;
}
macro_build (&icnt, NULL, "slt", "d,v,t", AT, sreg, treg);
macro_build (&icnt, &offset_expr, "bne", "s,t,p", AT, 0);
break;
case M_BLTU:
if (treg == 0)
goto do_false;
if (sreg == 0)
{
macro_build (&icnt, &offset_expr, "bne", "s,t,p", 0, treg);
return;
}
macro_build (&icnt, NULL, "sltu", "d,v,t", AT, sreg, treg);
macro_build (&icnt, &offset_expr, "bne", "s,t,p", AT, 0);
break;
case M_DIV_3: case M_DIV_3:
case M_REM_3: case M_REM_3:
if (treg == 0) if (treg == 0)
@ -1318,13 +1337,19 @@ macro (ip)
break; break;
case M_L_DOB: case M_L_DOB:
/* Even on a big endian machine $fn comes before $fn+1. We have
to adjust when loading from memory. */
save_reorder_condition = mips_noreorder; save_reorder_condition = mips_noreorder;
mips_noreorder = 1; mips_noreorder = 1;
macro_build (&icnt, &offset_expr, "lwc1", "T,o(b)", treg, breg); macro_build (&icnt, &offset_expr, "lwc1", "T,o(b)",
byte_order == LITTLE_ENDIAN ? treg : treg + 1,
breg);
/* unecessary implicit nop */ /* unecessary implicit nop */
mips_noreorder = save_reorder_condition; mips_noreorder = save_reorder_condition;
offset_expr.X_add_number += 4; offset_expr.X_add_number += 4;
macro_build (&icnt, &offset_expr, "lwc1", "T,o(b)", treg + 1, breg); macro_build (&icnt, &offset_expr, "lwc1", "T,o(b)",
byte_order == LITTLE_ENDIAN ? treg + 1 : treg,
breg);
return; return;
case M_L_DAB: case M_L_DAB:
@ -1356,13 +1381,19 @@ macro (ip)
macro_build (&icnt, NULL, "addu", "d,v,t", AT, AT, breg); macro_build (&icnt, NULL, "addu", "d,v,t", AT, AT, breg);
tempreg = AT; tempreg = AT;
} }
/* Even on a big endian machine $fn comes before $fn+1. We have
to adjust when loading from memory. */
save_reorder_condition = mips_noreorder; save_reorder_condition = mips_noreorder;
mips_noreorder = 1; mips_noreorder = 1;
macro_build (&icnt, &offset_expr, "lwc1", "T,o(b)", treg, tempreg); macro_build (&icnt, &offset_expr, "lwc1", "T,o(b)",
byte_order == LITTLE_ENDIAN ? treg : treg + 1,
tempreg);
/* unecessary implicit nop */ /* unecessary implicit nop */
mips_noreorder = save_reorder_condition; mips_noreorder = save_reorder_condition;
offset_expr.X_add_number += 4; offset_expr.X_add_number += 4;
macro_build (&icnt, &offset_expr, "lwc1", "T,o(b)", treg + 1, tempreg); macro_build (&icnt, &offset_expr, "lwc1", "T,o(b)",
byte_order == LITTLE_ENDIAN ? treg + 1 : treg,
tempreg);
if (tempreg == AT) if (tempreg == AT)
break; break;
return; return;
@ -1469,9 +1500,15 @@ macro (ip)
break; break;
case M_S_DOB: case M_S_DOB:
macro_build (&icnt, &offset_expr, "swc1", "T,o(b)", treg, breg); /* Even on a big endian machine $fn comes before $fn+1. We have
to adjust when storing to memory. */
macro_build (&icnt, &offset_expr, "swc1", "T,o(b)",
byte_order == LITTLE_ENDIAN ? treg : treg + 1,
breg);
offset_expr.X_add_number += 4; offset_expr.X_add_number += 4;
macro_build (&icnt, &offset_expr, "swc1", "T,o(b)", treg + 1, breg); macro_build (&icnt, &offset_expr, "swc1", "T,o(b)",
byte_order == LITTLE_ENDIAN ? treg + 1 : treg,
breg);
return; return;
case M_S_DAB: case M_S_DAB:
@ -1493,9 +1530,15 @@ macro (ip)
macro_build (&icnt, NULL, "addu", "d,v,t", AT, AT, breg); macro_build (&icnt, NULL, "addu", "d,v,t", AT, AT, breg);
tempreg = AT; tempreg = AT;
} }
macro_build (&icnt, &offset_expr, "swc1", "T,o(b)", treg, tempreg); /* Even on a big endian machine $fn comes before $fn+1. We have
to adjust when storing to memory. */
macro_build (&icnt, &offset_expr, "swc1", "T,o(b)",
byte_order == LITTLE_ENDIAN ? treg : treg + 1,
tempreg);
offset_expr.X_add_number += 4; offset_expr.X_add_number += 4;
macro_build (&icnt, &offset_expr, "swc1", "T,o(b)", treg + 1, tempreg); macro_build (&icnt, &offset_expr, "swc1", "T,o(b)",
byte_order == LITTLE_ENDIAN ? treg + 1 : treg,
tempreg);
if (tempreg == AT) if (tempreg == AT)
break; break;
return; return;
@ -1520,7 +1563,8 @@ macro (ip)
} }
if (sreg == 0) if (sreg == 0)
{ {
/* result is always false */ as_warn ("Instruction %s: result is always false",
ip->insn_mo->name);
macro_build (&icnt, NULL, "move", "d,s", dreg, 0); macro_build (&icnt, NULL, "move", "d,s", dreg, 0);
return; return;
} }
@ -1610,7 +1654,7 @@ macro (ip)
s = "sltu"; s = "sltu";
sle: sle:
macro_build (&icnt, NULL, s, "d,v,t", dreg, treg, sreg); macro_build (&icnt, NULL, s, "d,v,t", dreg, treg, sreg);
macro_build (&icnt, &imm_expr, "xori", "t,r,i", dreg, dreg); macro_build (&icnt, &expr1, "xori", "t,r,i", dreg, dreg);
return; return;
case M_SLE_I: /* sreg <= I <==> I >= sreg <==> not (I < sreg) */ case M_SLE_I: /* sreg <= I <==> I >= sreg <==> not (I < sreg) */
@ -1621,7 +1665,7 @@ macro (ip)
slei: slei:
load_register (&icnt, ip, AT, &imm_expr); load_register (&icnt, ip, AT, &imm_expr);
macro_build (&icnt, NULL, s, "d,v,t", dreg, AT, sreg); macro_build (&icnt, NULL, s, "d,v,t", dreg, AT, sreg);
macro_build (&icnt, &offset_expr, "xori", "t,r,i", dreg, dreg); macro_build (&icnt, &expr1, "xori", "t,r,i", dreg, dreg);
break; break;
case M_SLT_I: case M_SLT_I:
@ -1664,7 +1708,8 @@ macro (ip)
} }
if (sreg == 0) if (sreg == 0)
{ {
/* result is always true */ as_warn ("Instruction %s: result is always true",
ip->insn_mo->name);
macro_build (&icnt, &expr1, "addiu", "t,r,j", dreg, 0); macro_build (&icnt, &expr1, "addiu", "t,r,j", dreg, 0);
return; return;
} }
@ -3163,7 +3208,7 @@ s_file (x)
int line; int line;
line = get_number (); line = get_number ();
s_app_file (); s_app_file (0);
} }

View file

@ -27,6 +27,7 @@ the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
#define MASK_CHAR ((int)(unsigned char)-1) #define MASK_CHAR ((int)(unsigned char)-1)
#endif #endif
/* This is the largest known floating point format (for now). It will /* This is the largest known floating point format (for now). It will
grow when we do 4361 style flonums. */ grow when we do 4361 style flonums. */
@ -44,6 +45,12 @@ the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
#endif #endif
#include "obstack.h" #include "obstack.h"
#include "listing.h"
#ifndef TC_START_LABEL
#define TC_START_LABEL(x,y) (x==':')
#endif
/* The NOP_OPCODE is for the alignment fill value. /* The NOP_OPCODE is for the alignment fill value.
* fill it a nop instruction so that the disassembler does not choke * fill it a nop instruction so that the disassembler does not choke
@ -195,7 +202,8 @@ static const pseudo_typeS potable[] =
/* err */ /* err */
/* extend */ /* extend */
{"extern", s_ignore, 0}, /* We treat all undef as ext */ {"extern", s_ignore, 0}, /* We treat all undef as ext */
{"appfile", s_app_file, 0}, {"appfile", s_app_file, 1},
{"appline", s_app_line, 0},
{"file", s_app_file, 0}, {"file", s_app_file, 0},
{"fill", s_fill, 0}, {"fill", s_fill, 0},
{"float", float_cons, 'f'}, {"float", float_cons, 'f'},
@ -405,7 +413,7 @@ read_a_source_file (name)
* [In case of pseudo-op, s->'.'.] * [In case of pseudo-op, s->'.'.]
* Input_line_pointer->'\0' where c was. * Input_line_pointer->'\0' where c was.
*/ */
if (c == ':') if (TC_START_LABEL(c, input_line_pointer))
{ {
colon (s); /* user-defined label */ colon (s); /* user-defined label */
*input_line_pointer++ = ':'; /* Put ':' back for error messages' sake. */ *input_line_pointer++ = ':'; /* Put ':' back for error messages' sake. */
@ -828,8 +836,16 @@ s_data ()
demand_empty_rest_of_line (); demand_empty_rest_of_line ();
} }
/* Handle the .appfile pseudo-op. This is automatically generated by
do_scrub_next_char when a preprocessor # line comment is seen with
a file name. This default definition may be overridden by the
object or CPU specific pseudo-ops. This function is also the
default definition for .file; the APPFILE argument is 1 for
.appfile, 0 for .file. */
void void
s_app_file () s_app_file (appfile)
int appfile;
{ {
register char *s; register char *s;
int length; int length;
@ -837,14 +853,41 @@ s_app_file ()
/* Some assemblers tolerate immediately following '"' */ /* Some assemblers tolerate immediately following '"' */
if ((s = demand_copy_string (&length)) != 0) if ((s = demand_copy_string (&length)) != 0)
{ {
new_logical_line (s, -1); /* If this is a fake .appfile, a fake newline was inserted into
the buffer. Passing -2 to new_logical_line tells it to
account for it. */
new_logical_line (s, appfile ? -2 : -1);
demand_empty_rest_of_line (); demand_empty_rest_of_line ();
#ifdef LISTING
if (listing)
listing_source_file (s);
#endif
} }
#ifdef OBJ_COFF #ifdef OBJ_COFF
c_dot_file_symbol (s); c_dot_file_symbol (s);
#endif /* OBJ_COFF */ #endif /* OBJ_COFF */
} /* s_app_file() */ } /* s_app_file() */
/* Handle the .appline pseudo-op. This is automatically generated by
do_scrub_next_char when a preprocessor # line comment is seen.
This default definition may be overridden by the object or CPU
specific pseudo-ops. */
void
s_app_line ()
{
int l;
/* The given number is that of the next line. */
l = get_absolute_expression () - 1;
new_logical_line ((char *) NULL, l);
#ifdef LISTING
if (listing)
listing_source_line (l);
#endif
demand_empty_rest_of_line ();
}
void void
s_fill () s_fill ()
{ {
@ -943,8 +986,11 @@ s_lcomm (needs_align)
register char *p; register char *p;
register int temp; register int temp;
register symbolS *symbolP; register symbolS *symbolP;
segT current_seg = now_seg;
subsegT current_subseg = now_subseg;
const int max_alignment = 15; const int max_alignment = 15;
int align = 0; int align = 0;
segT bss_seg = bss_section;
name = input_line_pointer; name = input_line_pointer;
c = get_symbol_end (); c = get_symbol_end ();
@ -973,6 +1019,14 @@ s_lcomm (needs_align)
return; return;
} }
#ifdef TC_MIPS
#ifdef OBJ_ECOFF
/* For MIPS ECOFF, small objects are put in .sbss. */
if (temp <= bfd_get_gp_size (stdoutput))
bss_seg = subseg_new (".sbss", 1);
#endif
#endif
if (needs_align) if (needs_align)
{ {
align = 0; align = 0;
@ -1001,7 +1055,7 @@ s_lcomm (needs_align)
align = 0; align = 0;
as_warn ("Alignment negative. 0 assumed."); as_warn ("Alignment negative. 0 assumed.");
} }
record_alignment (bss_section, align); record_alignment (bss_seg, align);
} /* if needs align */ } /* if needs align */
*p = 0; *p = 0;
@ -1013,23 +1067,21 @@ s_lcomm (needs_align)
S_GET_OTHER (symbolP) == 0 && S_GET_OTHER (symbolP) == 0 &&
S_GET_DESC (symbolP) == 0 && S_GET_DESC (symbolP) == 0 &&
#endif /* OBJ_AOUT or OBJ_BOUT */ #endif /* OBJ_AOUT or OBJ_BOUT */
(S_GET_SEGMENT (symbolP) == bss_section (S_GET_SEGMENT (symbolP) == bss_seg
|| (!S_IS_DEFINED (symbolP) && S_GET_VALUE (symbolP) == 0))) || (!S_IS_DEFINED (symbolP) && S_GET_VALUE (symbolP) == 0)))
{ {
char *p; char *p;
segT current_seg = now_seg;
subsegT current_subseg = now_subseg;
#ifdef BFD_ASSEMBLER #ifdef BFD_ASSEMBLER
subseg_set (bss_section, 1); subseg_set (bss_seg, 1);
#else #else
subseg_new (bss_section, 1); subseg_new (bss_seg, 1);
#endif #endif
if (align) if (align)
frag_align (align, 0); frag_align (align, 0);
/* detach from old frag */ /* detach from old frag */
if (S_GET_SEGMENT (symbolP) == bss_section) if (S_GET_SEGMENT (symbolP) == bss_seg)
symbolP->sy_frag->fr_symbol = NULL; symbolP->sy_frag->fr_symbol = NULL;
symbolP->sy_frag = frag_now; symbolP->sy_frag = frag_now;
@ -1037,7 +1089,7 @@ s_lcomm (needs_align)
temp, (char *)0); temp, (char *)0);
*p = 0; *p = 0;
S_SET_SEGMENT (symbolP, bss_section); S_SET_SEGMENT (symbolP, bss_seg);
#ifdef OBJ_COFF #ifdef OBJ_COFF
/* The symbol may already have been created with a preceding /* The symbol may already have been created with a preceding
@ -1048,19 +1100,19 @@ s_lcomm (needs_align)
S_SET_STORAGE_CLASS (symbolP, C_STAT); S_SET_STORAGE_CLASS (symbolP, C_STAT);
} }
#endif /* OBJ_COFF */ #endif /* OBJ_COFF */
#ifdef BFD_ASSEMBLER
subseg_set (current_seg, current_subseg);
#else
subseg_new (current_seg, current_subseg);
#endif
} }
else else
{ {
as_bad ("Ignoring attempt to re-define symbol %s.", name); as_bad ("Ignoring attempt to re-define symbol %s.", name);
} }
demand_empty_rest_of_line ();
return; #ifdef BFD_ASSEMBLER
subseg_set (current_seg, current_subseg);
#else
subseg_new (current_seg, current_subseg);
#endif
demand_empty_rest_of_line ();
} /* s_lcomm() */ } /* s_lcomm() */
void void
@ -1406,18 +1458,23 @@ pseudo_set (symbolP)
&& (S_GET_SEGMENT (exp.X_add_symbol) == && (S_GET_SEGMENT (exp.X_add_symbol) ==
S_GET_SEGMENT (exp.X_subtract_symbol))) S_GET_SEGMENT (exp.X_subtract_symbol)))
{ {
if (exp.X_add_symbol->sy_frag != exp.X_subtract_symbol->sy_frag) if (exp.X_add_symbol->sy_frag == exp.X_subtract_symbol->sy_frag)
{ {
as_bad ("Unknown expression: symbols %s and %s are in different frags.", exp.X_add_number += S_GET_VALUE (exp.X_add_symbol) -
S_GET_NAME (exp.X_add_symbol), S_GET_NAME (exp.X_subtract_symbol)); S_GET_VALUE (exp.X_subtract_symbol);
need_pass_2++; goto abs;
} }
exp.X_add_number += S_GET_VALUE (exp.X_add_symbol) - as_bad ("Invalid expression: separation between symbols `%s'",
S_GET_VALUE (exp.X_subtract_symbol); S_GET_NAME (exp.X_add_symbol));
as_bad (" and `%s' may not be constant",
S_GET_NAME (exp.X_subtract_symbol));
need_pass_2++;
} }
else else
as_bad ("Complex expression. Absolute segment assumed."); {
goto abs; as_bad ("Complex expression. Absolute segment assumed.");
goto abs;
}
} }
else if (segment == absolute_section) else if (segment == absolute_section)
{ {
@ -1785,6 +1842,7 @@ cons (nbytes)
/* undefined_section, others */ /* undefined_section, others */
{ {
defalt: defalt:
md_number_to_chars (p, (long) 0, nbytes);
#ifdef BFD_ASSEMBLER #ifdef BFD_ASSEMBLER
fix_new (frag_now, p - frag_now->fr_literal, nbytes, fix_new (frag_now, p - frag_now->fr_literal, nbytes,
exp.X_add_symbol, exp.X_subtract_symbol, exp.X_add_symbol, exp.X_subtract_symbol,
@ -2051,7 +2109,7 @@ float_cons (float_type) /* Worker to do .float etc statements. */
err = md_atof (float_type, temp, &length); err = md_atof (float_type, temp, &length);
know (length <= MAXIMUM_NUMBER_OF_CHARS_FOR_FLOAT); know (length <= MAXIMUM_NUMBER_OF_CHARS_FOR_FLOAT);
know (length > 0); know (length > 0);
if (*err) if (err && *err)
{ {
as_bad ("Bad floating literal: %s", err); as_bad ("Bad floating literal: %s", err);
ignore_rest_of_line (); ignore_rest_of_line ();