diff options
Diffstat (limited to 'gas')
-rw-r--r-- | gas/ChangeLog | 30 | ||||
-rw-r--r-- | gas/app.c | 162 | ||||
-rw-r--r-- | gas/config/obj-coffbfd.c | 14 | ||||
-rw-r--r-- | gas/config/tc-mips.c | 203 | ||||
-rw-r--r-- | gas/read.c | 114 |
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. @@ -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); } @@ -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 (); |