aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorIan Lance Taylor <ian@airs.com>1993-05-27 19:29:38 +0000
committerIan Lance Taylor <ian@airs.com>1993-05-27 19:29:38 +0000
commit9a7d824a261ba7785702c5a3b5bc6bf3a3b12213 (patch)
treeb6939d9264356d6aef256ddd19a347630a42c2a3
parentd34094e8e0bd8749e890a012c218923656d53774 (diff)
downloadfsf-binutils-gdb-9a7d824a261ba7785702c5a3b5bc6bf3a3b12213.zip
fsf-binutils-gdb-9a7d824a261ba7785702c5a3b5bc6bf3a3b12213.tar.gz
fsf-binutils-gdb-9a7d824a261ba7785702c5a3b5bc6bf3a3b12213.tar.bz2
* 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.
-rw-r--r--gas/ChangeLog30
-rw-r--r--gas/app.c162
-rw-r--r--gas/config/obj-coffbfd.c14
-rw-r--r--gas/config/tc-mips.c203
-rw-r--r--gas/read.c114
5 files changed, 342 insertions, 181 deletions
diff --git a/gas/ChangeLog b/gas/ChangeLog
index ae17364..7c039b9 100644
--- a/gas/ChangeLog
+++ b/gas/ChangeLog
@@ -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)
* config/obj-bout.h (S_GET_VALUE): Removed unnecessary cast.
diff --git a/gas/app.c b/gas/app.c
index 1983c3c..01fea74 100644
--- a/gas/app.c
+++ b/gas/app.c
@@ -23,7 +23,7 @@
/* App, the assembler pre-processor. This pre-processor strips out excess
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.
*/
@@ -87,16 +87,16 @@ do_scrub_begin ()
lex[*p] = LEX_IS_SYMBOL_COMPONENT;
} /* 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++)
{
lex[*p] = LEX_IS_COMMENT_START;
} /* 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++)
{
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
5: parsing a string, then go to old-state
6: putting out \ escape in a "d string.
- 7: After putting out a .app-file, put out string.
- 8: After putting out a .app-file string, flush until newline.
+ 7: After putting out a .appfile, put out string.
+ 8: After putting out a .appfile string, flush until newline.
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
-2: flush text until a '*' '/' is seen, then go to state old_state
*/
- /* I added state 9 because the MIPS ECOFF assembler uses constructs
- like ``.loc 1 20''. This was turning into ``.loc 120''. State 9
- ensures that a space is never dropped immediately following a
- character which could appear in a identifier. It is still
- dropped following a comma, so this has no effect for most
- assemblers. I hope. Ian Taylor, ian@cygnus.com. */
+ /* I added states 9 and 10 because the MIPS ECOFF assembler uses
+ constructs like ``.loc 1 20''. This was turning into ``.loc
+ 120''. States 9 and 10 ensure that a space is never dropped in
+ between characters which could appear in a identifier. Ian
+ Taylor, ian@cygnus.com. */
register int ch, ch2 = 0;
@@ -308,7 +308,7 @@ do_scrub_next_char (get, unget)
if (ch == '"')
{
(*unget) (ch);
- out_string = "\n.app-file ";
+ out_string = "\n.appfile ";
old_state = 7;
state = -1;
return *out_string++;
@@ -406,7 +406,7 @@ do_scrub_next_char (get, unget)
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: */
ch = (*get) ();
@@ -454,12 +454,15 @@ recycle:
case 1:
BAD_CASE (state); /* We can't get here */
case 2:
- case 9:
state = 3;
(*unget) (ch);
return ' '; /* Sp after opco */
case 3:
goto recycle; /* Sp in operands */
+ case 9:
+ case 10:
+ state = 10; /* Sp after symbol char */
+ goto recycle;
default:
BAD_CASE (state);
}
@@ -501,12 +504,17 @@ recycle:
{
if (ch2 != EOF)
(*unget) (ch2);
+ if (state == 9 || state == 10)
+ state = 3;
return ch;
}
break;
case LEX_IS_STRINGQUOTE:
- old_state = state;
+ if (state == 9 || state == 10)
+ old_state = 3;
+ else
+ old_state = state;
state = 5;
return ch;
#ifndef MRI
@@ -526,8 +534,7 @@ recycle:
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) ()) != '\'')
{
#ifdef REQUIRE_CHAR_CLOSE_QUOTE
@@ -540,14 +547,19 @@ recycle:
{
return out_buf[0];
}
- old_state = state;
+ if (state == 9 || state == 10)
+ old_state = 3;
+ else
+ old_state = state;
state = -1;
out_string = out_buf;
return *out_string++;
#endif
#endif
case LEX_IS_COLON:
- if (state != 3)
+ if (state == 9 || state == 10)
+ state = 3;
+ else if (state != 3)
state = 0;
return ch;
@@ -565,53 +577,58 @@ recycle:
return ch;
case LEX_IS_LINE_COMMENT_START:
- if (state != 0) /* Not at start of line, act normal */
- 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 == '/')
+ if (state == 0) /* Only comment at start of line. */
{
- ch2 = (*get) ();
- if (ch2 == '*')
- {
- state = -2;
- return (do_scrub_next_char (get, unget));
- }
- else
+ /* 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 == '/')
{
- (*unget) (ch2);
- }
- } /* bad hack */
+ ch2 = (*get) ();
+ if (ch2 == '*')
+ {
+ state = -2;
+ return (do_scrub_next_char (get, unget));
+ }
+ else
+ {
+ (*unget) (ch2);
+ }
+ } /* bad hack */
- 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))
+ do
ch = (*get) ();
+ while (ch != EOF && IS_WHITESPACE (ch));
if (ch == EOF)
- as_warn ("EOF in Comment: Newline inserted");
- state = 0;
- return '\n';
+ {
+ 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) ();
+ 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:
do
ch = (*get) ();
@@ -622,6 +639,15 @@ recycle:
return '\n';
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)
state = 9;
/* Fall through. */
@@ -644,6 +670,11 @@ recycle:
state = 3;
return ch;
}
+ else if (state == 10)
+ {
+ state = 3;
+ return ch;
+ }
else
{
return ch; /* Opcode or operands already */
@@ -675,11 +706,4 @@ as_warn (str)
#endif
-/*
- * Local Variables:
- * comment-column: 0
- * fill-column: 131
- * End:
- */
-
/* end of app.c */
diff --git a/gas/config/obj-coffbfd.c b/gas/config/obj-coffbfd.c
index 36e9fdc..d5282fa 100644
--- a/gas/config/obj-coffbfd.c
+++ b/gas/config/obj-coffbfd.c
@@ -142,7 +142,7 @@ static void EXFUN( obj_coff_bss,(void));
static void EXFUN( obj_coff_ident,(void));
static void EXFUN (obj_coff_endef, (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_size, (void));
static void EXFUN (obj_coff_tag, (void));
@@ -163,6 +163,7 @@ const pseudo_typeS obj_pseudo_table[] =
{"endef", obj_coff_endef, 0},
{"line", obj_coff_line, 0},
{"ln", obj_coff_ln, 0},
+ {"appline", obj_coff_ln, 1},
{"scl", obj_coff_scl, 0},
{"size", obj_coff_size, 0},
{"tag", obj_coff_tag, 0},
@@ -776,11 +777,12 @@ stack_top (st)
*/
static void
-obj_coff_ln ()
+obj_coff_ln (appline)
+ int appline;
{
int l;
- if (def_symbol_in_progress != NULL)
+ if (! appline && def_symbol_in_progress != NULL)
{
as_warn (".ln pseudo-op inside .def/.endef: ignored.");
demand_empty_rest_of_line ();
@@ -797,7 +799,9 @@ obj_coff_ln ()
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)
{
- obj_coff_ln ();
+ obj_coff_ln (0);
return;
} /* if it looks like a stabs style line */
diff --git a/gas/config/tc-mips.c b/gas/config/tc-mips.c
index 3a853f2..6a5e79f 100644
--- a/gas/config/tc-mips.c
+++ b/gas/config/tc-mips.c
@@ -405,12 +405,27 @@ gp_reference (ep)
{
#ifdef OBJ_ECOFF
symbolS *sym;
+ const char *symname;
const char *segname;
sym = ep->X_add_symbol;
if (sym == (symbolS *) NULL
|| ep->X_subtract_symbol != (symbolS *) NULL)
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)
&& S_GET_VALUE (sym) != 0
&& S_GET_VALUE (sym) <= g_switch_value)
@@ -883,13 +898,28 @@ macro (ip)
macro_build (&icnt, &offset_expr, "bgez", "s,p", sreg);
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, &offset_expr, "beq", "s,t,p", AT, 0);
break;
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++;
/* FALLTHROUGH */
+
case M_BGE_I:
if (imm_expr.X_add_number == 0)
{
@@ -901,26 +931,39 @@ macro (ip)
macro_build (&icnt, &offset_expr, "bgtz", "s,p", sreg);
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);
macro_build (&icnt, &offset_expr, "beq", "s,t,p", AT, 0);
break;
case M_BGEU:
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;
}
macro_build (&icnt, NULL, "sltu", "d,v,t", AT, sreg, treg);
macro_build (&icnt, &offset_expr, "beq", "s,t,p", AT, 0);
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:
if (imm_expr.X_add_number == 0)
- {
- macro_build (&icnt, &offset_expr, "b", "p");
- return;
- }
+ goto do_true;
if (imm_expr.X_add_number == 1)
{
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);
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, &offset_expr, "bne", "s,t,p", AT, 0);
break;
@@ -946,50 +994,44 @@ macro (ip)
macro_build (&icnt, &offset_expr, "bne", "s,t,p", sreg, 0);
return;
}
+ if (sreg == 0)
+ goto do_false;
macro_build (&icnt, NULL, "sltu", "d,v,t", AT, treg, sreg);
macro_build (&icnt, &offset_expr, "bne", "s,t,p", AT, 0);
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:
if (treg == 0)
{
macro_build (&icnt, &offset_expr, "blez", "s,p", sreg);
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, &offset_expr, "beq", "s,t,p", AT, 0);
break;
case M_BLE_I:
+ if (imm_expr.X_add_number == 0x7fffffff)
+ goto do_true;
+ imm_expr.X_add_number++;
+ /* FALLTHROUGH */
+
+ case M_BLT_I:
if (imm_expr.X_add_number == 0)
{
- macro_build (&icnt, &offset_expr, "blez", "s,p", sreg);
+ macro_build (&icnt, &offset_expr, "bltz", "s,p", sreg);
return;
}
- if (imm_expr.X_add_number == -1)
+ if (imm_expr.X_add_number == 1)
{
- macro_build (&icnt, &offset_expr, "bltz", "s,p", sreg);
+ macro_build (&icnt, &offset_expr, "blez", "s,p", sreg);
return;
}
- imm_expr.X_add_number++;
set_at (&icnt, sreg);
macro_build (&icnt, &offset_expr, "bne", "s,t,p", AT, 0);
break;
@@ -1000,22 +1042,26 @@ macro (ip)
macro_build (&icnt, &offset_expr, "beq", "s,t,p", sreg, 0);
return;
}
+ if (sreg == 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;
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:
if (imm_expr.X_add_number == 0)
+ goto do_false;
+ if (imm_expr.X_add_number == 1)
{
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;
@@ -1026,54 +1072,27 @@ macro (ip)
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:
- if (imm_expr.X_add_number == 0)
- {
- macro_build (&icnt, &offset_expr, "bltz", "s,p", sreg);
- return;
- }
- if (imm_expr.X_add_number == 1)
+ if (sreg == 0)
{
- macro_build (&icnt, &offset_expr, "blez", "s,p", sreg);
+ macro_build (&icnt, &offset_expr, "bgtz", "s,p", treg);
return;
}
- set_at (&icnt, sreg);
+ 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)
{
- /* NOP */
- if (mips_noreorder)
- as_warn ("Instruction %s is a nop; deleted", ip->insn_mo->name);
+ 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_BLTU_I:
- if (imm_expr.X_add_number == 0)
- {
- /* NOP */
- if (mips_noreorder)
- as_warn ("Instruction %s is a nop; deleted", ip->insn_mo->name);
- return;
- }
- if (imm_expr.X_add_number == 1)
- {
- macro_build (&icnt, &offset_expr, "beq", "s,t,p", sreg, 0);
- return;
- }
- set_at_unsigned (&icnt, sreg);
- macro_build (&icnt, &offset_expr, "bne", "s,t,p", AT, 0);
- break;
-
case M_DIV_3:
case M_REM_3:
if (treg == 0)
@@ -1318,13 +1337,19 @@ macro (ip)
break;
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;
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 */
mips_noreorder = save_reorder_condition;
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;
case M_L_DAB:
@@ -1356,13 +1381,19 @@ macro (ip)
macro_build (&icnt, NULL, "addu", "d,v,t", AT, AT, breg);
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;
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 */
mips_noreorder = save_reorder_condition;
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)
break;
return;
@@ -1469,9 +1500,15 @@ macro (ip)
break;
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;
- 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;
case M_S_DAB:
@@ -1493,9 +1530,15 @@ macro (ip)
macro_build (&icnt, NULL, "addu", "d,v,t", AT, AT, breg);
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;
- 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)
break;
return;
@@ -1520,7 +1563,8 @@ macro (ip)
}
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);
return;
}
@@ -1610,7 +1654,7 @@ macro (ip)
s = "sltu";
sle:
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;
case M_SLE_I: /* sreg <= I <==> I >= sreg <==> not (I < sreg) */
@@ -1621,7 +1665,7 @@ macro (ip)
slei:
load_register (&icnt, ip, AT, &imm_expr);
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;
case M_SLT_I:
@@ -1664,7 +1708,8 @@ macro (ip)
}
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);
return;
}
@@ -3163,7 +3208,7 @@ s_file (x)
int line;
line = get_number ();
- s_app_file ();
+ s_app_file (0);
}
diff --git a/gas/read.c b/gas/read.c
index 2b450a6..78061ef 100644
--- a/gas/read.c
+++ b/gas/read.c
@@ -27,6 +27,7 @@ the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
#define MASK_CHAR ((int)(unsigned char)-1)
#endif
+
/* This is the largest known floating point format (for now). It will
grow when we do 4361 style flonums. */
@@ -44,6 +45,12 @@ the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
#endif
#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.
* fill it a nop instruction so that the disassembler does not choke
@@ -195,7 +202,8 @@ static const pseudo_typeS potable[] =
/* err */
/* extend */
{"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},
{"fill", s_fill, 0},
{"float", float_cons, 'f'},
@@ -405,7 +413,7 @@ read_a_source_file (name)
* [In case of pseudo-op, s->'.'.]
* Input_line_pointer->'\0' where c was.
*/
- if (c == ':')
+ if (TC_START_LABEL(c, input_line_pointer))
{
colon (s); /* user-defined label */
*input_line_pointer++ = ':'; /* Put ':' back for error messages' sake. */
@@ -828,8 +836,16 @@ s_data ()
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
-s_app_file ()
+s_app_file (appfile)
+ int appfile;
{
register char *s;
int length;
@@ -837,14 +853,41 @@ s_app_file ()
/* Some assemblers tolerate immediately following '"' */
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 ();
+#ifdef LISTING
+ if (listing)
+ listing_source_file (s);
+#endif
}
#ifdef OBJ_COFF
c_dot_file_symbol (s);
#endif /* OBJ_COFF */
} /* 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
s_fill ()
{
@@ -943,8 +986,11 @@ s_lcomm (needs_align)
register char *p;
register int temp;
register symbolS *symbolP;
+ segT current_seg = now_seg;
+ subsegT current_subseg = now_subseg;
const int max_alignment = 15;
int align = 0;
+ segT bss_seg = bss_section;
name = input_line_pointer;
c = get_symbol_end ();
@@ -973,6 +1019,14 @@ s_lcomm (needs_align)
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)
{
align = 0;
@@ -1001,7 +1055,7 @@ s_lcomm (needs_align)
align = 0;
as_warn ("Alignment negative. 0 assumed.");
}
- record_alignment (bss_section, align);
+ record_alignment (bss_seg, align);
} /* if needs align */
*p = 0;
@@ -1013,23 +1067,21 @@ s_lcomm (needs_align)
S_GET_OTHER (symbolP) == 0 &&
S_GET_DESC (symbolP) == 0 &&
#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)))
{
char *p;
- segT current_seg = now_seg;
- subsegT current_subseg = now_subseg;
#ifdef BFD_ASSEMBLER
- subseg_set (bss_section, 1);
+ subseg_set (bss_seg, 1);
#else
- subseg_new (bss_section, 1);
+ subseg_new (bss_seg, 1);
#endif
if (align)
frag_align (align, 0);
/* 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 = frag_now;
@@ -1037,7 +1089,7 @@ s_lcomm (needs_align)
temp, (char *)0);
*p = 0;
- S_SET_SEGMENT (symbolP, bss_section);
+ S_SET_SEGMENT (symbolP, bss_seg);
#ifdef OBJ_COFF
/* 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);
}
#endif /* OBJ_COFF */
-#ifdef BFD_ASSEMBLER
- subseg_set (current_seg, current_subseg);
-#else
- subseg_new (current_seg, current_subseg);
-#endif
}
else
{
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() */
void
@@ -1406,18 +1458,23 @@ pseudo_set (symbolP)
&& (S_GET_SEGMENT (exp.X_add_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.",
- S_GET_NAME (exp.X_add_symbol), S_GET_NAME (exp.X_subtract_symbol));
- need_pass_2++;
+ exp.X_add_number += S_GET_VALUE (exp.X_add_symbol) -
+ S_GET_VALUE (exp.X_subtract_symbol);
+ goto abs;
}
- exp.X_add_number += S_GET_VALUE (exp.X_add_symbol) -
- S_GET_VALUE (exp.X_subtract_symbol);
+ as_bad ("Invalid expression: separation between symbols `%s'",
+ 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
- as_bad ("Complex expression. Absolute segment assumed.");
- goto abs;
+ {
+ as_bad ("Complex expression. Absolute segment assumed.");
+ goto abs;
+ }
}
else if (segment == absolute_section)
{
@@ -1785,6 +1842,7 @@ cons (nbytes)
/* undefined_section, others */
{
defalt:
+ md_number_to_chars (p, (long) 0, nbytes);
#ifdef BFD_ASSEMBLER
fix_new (frag_now, p - frag_now->fr_literal, nbytes,
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);
know (length <= MAXIMUM_NUMBER_OF_CHARS_FOR_FLOAT);
know (length > 0);
- if (*err)
+ if (err && *err)
{
as_bad ("Bad floating literal: %s", err);
ignore_rest_of_line ();