From: Ian Lance Taylor Date: Thu, 1 Apr 1993 02:14:29 +0000 (+0000) Subject: * subsegs.c (subseg_new): Set output_section of new section. X-Git-Url: https://git.libre-soc.org/?a=commitdiff_plain;h=670a50ebf65de85eab0ccf22da227e218f704037;p=binutils-gdb.git * subsegs.c (subseg_new): Set output_section of new section. * as.c (perform_an_assemly_pass): Don't set output_section here. * expr.c (expr_part, expr): Turn off section assertions for ECOFF, since it has additional sections. * read.c (s_lcomm): For MIPS ECOFF, put small objects in .sbss, not bss_section. * config/obj-ecoff.h (TARGET_SYMBOL_FIELDS): Added ecoff_undefined field. * config/obj-ecoff.c (obj_symbol_new_hook): Initialize ecoff_undefined field. (add_file): If using stabs, just output a stabs symbol rather than creating a new fdr. (obj_ecoff_begin, obj_ecoff_bend): Ignore line number by reading it with get_absolute_expression, rather than skipping it by hand. (obj_ecoff_loc): If using stabs, just output a stabs symbol rather than ECOFF line number information. (obj_ecoff_stab): Accept non-zero values for stabs line number. (ecoff_build_symbols): Set ifilesym correctly. Set storage class to small, undefined and/or readonly sections if appropriate. Don't output symbol names containing \001 characters. (ecoff_frob_file): Make sure at least one fdr is output. * config/tc-mips.h: Define TC_MIPS. * config/tc-mips.c (g_switch_value): New static variable. (md_assemble): Set gp size of output BFD. (gp_reference): New function; returns 1 if expression can be accesssed via gp. Always returns 0 if not using ECOFF. (macro_build): Convert BFD_RELOC_LO16 to BFD_RELOC_MIPS_GPREL if possible. (macro): Generate sequences using gp if possible. (md_parse_option): Ignore -EL and -EB. Parse -G. (md_apply_fix): Added BFD_RELOC_MIPS_GPREL to ignored case. (s_change_sec): Handle .rdata and .sdata for ECOFF. (s_extern): Mark symbol as external. Set ecoff_undefined field. --- diff --git a/gas/ChangeLog b/gas/ChangeLog index 951b1a7b8af..ce9a9dbb000 100644 --- a/gas/ChangeLog +++ b/gas/ChangeLog @@ -1,5 +1,47 @@ +Wed Mar 31 17:53:54 1993 Ian Lance Taylor (ian@cygnus.com) + + * subsegs.c (subseg_new): Set output_section of new section. + * as.c (perform_an_assemly_pass): Don't set output_section here. + * expr.c (expr_part, expr): Turn off section assertions for ECOFF, + since it has additional sections. + * read.c (s_lcomm): For MIPS ECOFF, put small objects in .sbss, + not bss_section. + * config/obj-ecoff.h (TARGET_SYMBOL_FIELDS): Added + ecoff_undefined field. + * config/obj-ecoff.c (obj_symbol_new_hook): Initialize + ecoff_undefined field. + (add_file): If using stabs, just output a stabs symbol rather than + creating a new fdr. + (obj_ecoff_begin, obj_ecoff_bend): Ignore line number by reading + it with get_absolute_expression, rather than skipping it by hand. + (obj_ecoff_loc): If using stabs, just output a stabs symbol rather + than ECOFF line number information. + (obj_ecoff_stab): Accept non-zero values for stabs line number. + (ecoff_build_symbols): Set ifilesym correctly. Set storage class + to small, undefined and/or readonly sections if appropriate. + Don't output symbol names containing \001 characters. + (ecoff_frob_file): Make sure at least one fdr is output. + * config/tc-mips.h: Define TC_MIPS. + * config/tc-mips.c (g_switch_value): New static variable. + (md_assemble): Set gp size of output BFD. + (gp_reference): New function; returns 1 if expression can be + accesssed via gp. Always returns 0 if not using ECOFF. + (macro_build): Convert BFD_RELOC_LO16 to BFD_RELOC_MIPS_GPREL if + possible. + (macro): Generate sequences using gp if possible. + (md_parse_option): Ignore -EL and -EB. Parse -G. + (md_apply_fix): Added BFD_RELOC_MIPS_GPREL to ignored case. + (s_change_sec): Handle .rdata and .sdata for ECOFF. + (s_extern): Mark symbol as external. Set ecoff_undefined field. + Tue Mar 30 10:11:41 1993 Ken Raeburn (raeburn@cambridge.cygnus.com) + * output-file.c (output_file_create): Don't call as_perror for + filename rejected by application. + + * as.c (main) [BFD_ASSEMBLER]: If errors occur, close and unlink + the output file. + * doc/as.texinfo: Don't use @value in node names for the moment; references don't appear to work right. diff --git a/gas/config/obj-ecoff.c b/gas/config/obj-ecoff.c index d0a9b044e93..5677ee14275 100644 --- a/gas/config/obj-ecoff.c +++ b/gas/config/obj-ecoff.c @@ -30,6 +30,8 @@ #include "aout/stab_gnu.h" #include "../bfd/libecoff.h" +#include + /* Why isn't this in coff/sym.h? */ #define ST_RFDESCAPE 0xfff @@ -1578,6 +1580,7 @@ obj_symbol_new_hook (symbolP) { symbolP->ecoff_file = cur_file_ptr; symbolP->ecoff_symbol = 0; + symbolP->ecoff_undefined = 0; } /* Add a page to a varray object. */ @@ -2203,6 +2206,8 @@ add_procedure (func) new_proc_ptr->pdr.isym = -1; new_proc_ptr->pdr.iline = -1; + new_proc_ptr->pdr.lnLow = -1; + new_proc_ptr->pdr.lnHigh = -1; /* Push the start of the function. */ new_proc_ptr->sym = add_ecoff_symbol ((const char *) NULL, st_Proc, sc_Text, @@ -2261,6 +2266,17 @@ add_file (file_name, indx) } } + /* If we're creating stabs, then we don't actually make a new FDR. + Instead, we just create a stabs symbol. */ + if (stabs_seen) + { + (void) add_ecoff_symbol (file_name, st_Nil, sc_Nil, + symbol_new ("L0\001", now_seg, + frag_now_fix (), frag_now), + 0, MIPS_MARK_STAB (N_SOL)); + return; + } + first_ch = *file_name; /* See if the file has already been created. */ @@ -2440,9 +2456,8 @@ obj_ecoff_begin (ignore) *input_line_pointer = name_end; /* The line number follows, but we don't use it. */ - while (! is_end_of_line[*input_line_pointer]) - input_line_pointer++; - input_line_pointer++; + (void) get_absolute_expression (); + demand_empty_rest_of_line (); } /* Parse .bend directives which have a label as the first argument @@ -2486,9 +2501,8 @@ obj_ecoff_bend (ignore) *input_line_pointer = name_end; /* The line number follows, but we don't use it. */ - while (! is_end_of_line[*input_line_pointer]) - input_line_pointer++; - input_line_pointer++; + (void) get_absolute_expression (); + demand_empty_rest_of_line (); } /* COFF debugging information is provided as a series of directives @@ -3201,7 +3215,6 @@ static void obj_ecoff_loc (ignore) int ignore; { - char buf[20]; lineno_list_t *list; if (cur_file_ptr == (efdr_t *) NULL) @@ -3223,6 +3236,17 @@ obj_ecoff_loc (ignore) get_absolute_expression (); SKIP_WHITESPACE (); + /* If we're building stabs, then output a special label rather than + ECOFF line number info. */ + if (stabs_seen) + { + (void) add_ecoff_symbol ((char *) NULL, st_Label, sc_Text, + symbol_new ("L0\001", now_seg, + frag_now_fix (), frag_now), + 0, get_absolute_expression ()); + return; + } + list = allocate_lineno_list (); list->next = (lineno_list_t *) NULL; @@ -3395,17 +3419,14 @@ obj_ecoff_stab (type) value = 0; st = st_Label; - sc = sc_Undefined; + sc = sc_Text; } else { - /* Skip 0, */ - if (get_absolute_expression () != 0) - { - as_warn ("Bad .stab%c directive (expected 0)", type); - demand_empty_rest_of_line (); - return; - } + /* The next number is sometimes the line number of the + declaration. We have nowhere to put it, so we just ignore + it. */ + (void) get_absolute_expression (); SKIP_WHITESPACE (); if (*input_line_pointer++ != ',') @@ -3442,17 +3463,8 @@ obj_ecoff_stab (type) sym = symbol_find_or_make (name); - /* Traditionally, N_LBRAC and N_RBRAC are *not* relocated. */ - if (code == N_LBRAC || code == N_RBRAC) - { - sc = sc_Nil; - st = st_Nil; - } - else - { - sc = sc_Undefined; - st = st_Nil; - } + sc = sc_Nil; + st = st_Nil; value = 0; *input_line_pointer = name_end; @@ -3512,6 +3524,7 @@ ecoff_longword_adjust (buf, bufend, offset, bufptrptr) add = 4 - (offset & 3); if (*bufend - (*buf + offset) < add) (void) ecoff_add_bytes (buf, bufend, *buf + offset, add); + memset (*buf + offset, 0, add); offset += add; if (bufptrptr != (char **) NULL) *bufptrptr = *buf + offset; @@ -3536,6 +3549,7 @@ ecoff_build_lineno (buf, bufend, offset, linecntptr) proc_t *proc; long c; long iline; + long totcount; bufptr = *buf + offset; @@ -3544,11 +3558,28 @@ ecoff_build_lineno (buf, bufend, offset, linecntptr) last = (lineno_list_t *) NULL; c = offset; iline = 0; + totcount = 0; for (l = first_lineno; l != (lineno_list_t *) NULL; l = l->next) { long count; long delta; - int didone; + + /* Get the offset to the memory address of the next line number + (in words). Do this first, so that we can skip ahead to the + next useful line number entry. */ + if (l->next == (lineno_list_t *) NULL) + count = 0; + else + { + count = ((l->next->frag->fr_address + l->next->paddr + - (l->frag->fr_address + l->paddr)) + >> 2); + if (count <= 0) + { + /* Don't change last, so we still get the right delta. */ + continue; + } + } if (l->file != file || l->proc != proc) { @@ -3557,11 +3588,11 @@ ecoff_build_lineno (buf, bufend, offset, linecntptr) if (l->file != file && file != (efdr_t *) NULL) { file->fdr.cbLine = c - file->fdr.cbLineOffset; - file->fdr.cline = iline - file->fdr.ilineBase; + /* The cline field is ill-documented. This is a guess + at the right value. */ + file->fdr.cline = totcount + count; } - c = ecoff_longword_adjust (buf, bufend, c, &bufptr); - if (l->file != file) { file = l->file; @@ -3573,33 +3604,18 @@ ecoff_build_lineno (buf, bufend, offset, linecntptr) proc = l->proc; if (proc != (proc_t *) NULL) { - /* The iline field is ill-documented. This is a - guess at the right value. */ - proc->pdr.iline = l->frag->fr_address + l->paddr; proc->pdr.lnLow = l->lineno; proc->pdr.cbLineOffset = c - file->fdr.cbLineOffset; + /* The iline field is ill-documented. This is a + guess at the right value. */ + proc->pdr.iline = totcount; } } last = (lineno_list_t *) NULL; } - /* Get the offset to the memory address of the next line number - (in words). */ - if (l->next == (lineno_list_t *) NULL) - count = 0; - else - { - count = (((l->next->frag->fr_address + l->next->paddr - - (l->frag->fr_address + l->paddr)) - >> 2) - - 1); - if (count < 0) - { - /* Don't change last, so we still get the right delta. */ - continue; - } - } + totcount += count; /* Get the offset to this line number. */ if (last == (lineno_list_t *) NULL) @@ -3607,40 +3623,30 @@ ecoff_build_lineno (buf, bufend, offset, linecntptr) else delta = l->lineno - last->lineno; - /* We can only adjust the address by 16 words at a time. */ - didone = 0; - while (count > 0x10) + /* Put in the offset to this line number. */ + while (delta != 0) { - if (bufptr >= *bufend) - bufptr = ecoff_add_bytes (buf, bufend, bufptr, (long) 1); - if (delta >= 7) - { - *bufptr++ = 0x0f + (7 << 4); - delta -= 7; - } - else if (delta <= -7) + int setcount; + + /* 1 is added to each count read. */ + --count; + /* We can only adjust the word count by up to 15 words at a + time. */ + if (count <= 0x0f) { - *bufptr++ = 0x0f + (-7 << 4); - delta += 7; + setcount = count; + count = 0; } else { - *bufptr++ = 0x0f + (delta << 4); - delta = 0; + setcount = 0x0f; + count -= 0x0f; } - ++c; - count -= 0x10; - didone = 1; - } - - /* Put in the offset to this line number. */ - while (delta != 0 || ! didone) - { if (delta >= -7 && delta <= 7) { if (bufptr >= *bufend) bufptr = ecoff_add_bytes (buf, bufend, bufptr, (long) 1); - *bufptr++ = count + (delta << 4); + *bufptr++ = setcount + (delta << 4); delta = 0; ++c; } @@ -3650,7 +3656,7 @@ ecoff_build_lineno (buf, bufend, offset, linecntptr) if (*bufend - bufptr < 3) bufptr = ecoff_add_bytes (buf, bufend, bufptr, (long) 3); - *bufptr++ = count + (8 << 4); + *bufptr++ = setcount + (8 << 4); if (delta < -0x8000) { set = -0x8000; @@ -3670,8 +3676,26 @@ ecoff_build_lineno (buf, bufend, offset, linecntptr) *bufptr++ = set & 0xffff; c += 3; } - count = 0; - didone = 1; + } + + /* Finish adjusting the count. */ + while (count > 0) + { + if (bufptr >= *bufend) + bufptr = ecoff_add_bytes (buf, bufend, bufptr, (long) 1); + /* 1 is added to each count read. */ + --count; + if (count > 0x0f) + { + *bufptr++ = 0x0f; + count -= 0x0f; + } + else + { + *bufptr++ = count; + count = 0; + } + ++c; } ++iline; @@ -3683,7 +3707,7 @@ ecoff_build_lineno (buf, bufend, offset, linecntptr) if (file != (efdr_t *) NULL) { file->fdr.cbLine = c - file->fdr.cbLineOffset; - file->fdr.cline = iline - file->fdr.ilineBase; + file->fdr.cline = totcount; } c = ecoff_longword_adjust (buf, bufend, c, &bufptr); @@ -3736,8 +3760,6 @@ ecoff_build_symbols (buf, efdr_t *fil_ptr; efdr_t *fil_end; - ifilesym = isym; - if (file_link->next == (vlinks_t *) NULL) fil_cnt = file_desc.objects_last_page; else @@ -3749,6 +3771,7 @@ ecoff_build_symbols (buf, vlinks_t *sym_link; fil_ptr->fdr.isymBase = isym; + ifilesym = isym; for (sym_link = fil_ptr->symbols.first; sym_link != (vlinks_t *) NULL; sym_link = sym_link->next) @@ -3782,35 +3805,79 @@ ecoff_build_symbols (buf, as_sym = sym_ptr->as_sym; if (as_sym != (symbolS *) NULL) { - sym_ptr->ecoff_sym.value = S_GET_VALUE (as_sym); + symint_t indx; + + /* The value of a block start symbol is the + offset from the start of the procedure. For + other symbols we just use the gas value. */ + if (sym_ptr->ecoff_sym.st == (int) st_Block + && sym_ptr->ecoff_sym.sc == (int) sc_Text) + { + know (sym_ptr->proc_ptr != (proc_t *) NULL); + sym_ptr->ecoff_sym.value = + (S_GET_VALUE (as_sym) + - S_GET_VALUE (sym_ptr->proc_ptr->sym->as_sym)); + } + else + sym_ptr->ecoff_sym.value = S_GET_VALUE (as_sym); /* Get the type and storage class based on where - the symbol actually wound up. */ + the symbol actually wound up. Traditionally, + N_LBRAC and N_RBRAC are *not* relocated. */ + indx = sym_ptr->ecoff_sym.index; if (sym_ptr->ecoff_sym.st == st_Nil && sym_ptr->ecoff_sym.sc == sc_Nil - && ! MIPS_IS_STAB (&sym_ptr->ecoff_sym)) + && (! MIPS_IS_STAB (&sym_ptr->ecoff_sym) + || ((MIPS_UNMARK_STAB (indx) != N_LBRAC) + && (MIPS_UNMARK_STAB (indx) != N_RBRAC)))) { + segT seg; + const char *segname; st_t st; sc_t sc; + seg = S_GET_SEGMENT (as_sym); + segname = segment_name (seg); + if (S_IS_EXTERNAL (as_sym) || ! S_IS_DEFINED (as_sym)) st = st_Global; - else if (S_GET_SEGMENT (as_sym) == text_section) + else if (seg == text_section) st = st_Label; else st = st_Static; - if (! S_IS_DEFINED (as_sym)) - sc = sc_Undefined; + if (! S_IS_DEFINED (as_sym) + || as_sym->ecoff_undefined) + { + if (S_GET_VALUE (as_sym) > 0 + && (S_GET_VALUE (as_sym) + <= bfd_get_gp_size (stdoutput))) + sc = sc_SUndefined; + else + sc = sc_Undefined; + } else if (S_IS_COMMON (as_sym)) - sc = sc_Common; - else if (S_GET_SEGMENT (as_sym) == text_section) + { + if (S_GET_VALUE (as_sym) > 0 + && (S_GET_VALUE (as_sym) + <= bfd_get_gp_size (stdoutput))) + sc = sc_SCommon; + else + sc = sc_Common; + } + else if (seg == text_section) sc = sc_Text; - else if (S_GET_SEGMENT (as_sym) == data_section) + else if (seg == data_section) sc = sc_Data; - else if (S_GET_SEGMENT (as_sym) == bss_section) + else if (strcmp (segname, ".rdata") == 0) + sc = sc_RData; + else if (strcmp (segname, ".sdata") == 0) + sc = sc_SData; + else if (seg == bss_section) sc = sc_Bss; + else if (strcmp (segname, ".sbss") == 0) + sc = sc_SBss; else abort (); @@ -3827,13 +3894,17 @@ ecoff_build_symbols (buf, if ((S_IS_EXTERNAL (as_sym) || ! S_IS_DEFINED (as_sym)) && sym_ptr->proc_ptr == (proc_t *) NULL - && sym_ptr->ecoff_sym.st != (int) st_Nil) + && sym_ptr->ecoff_sym.st != (int) st_Nil + && ! MIPS_IS_STAB (&sym_ptr->ecoff_sym)) local = 0; /* If an st_end symbol has an associated gas symbol, then it is a local label created for - a .bend or .end directive. */ - if (local && sym_ptr->ecoff_sym.st != st_End) + a .bend or .end directive. Stabs line + numbers will have \001 in the names. */ + if (local + && sym_ptr->ecoff_sym.st != st_End + && strchr (sym_ptr->name, '\001') == 0) sym_ptr->ecoff_sym.iss = add_string (&fil_ptr->strings, fil_ptr->str_hash, @@ -3876,10 +3947,11 @@ ecoff_build_symbols (buf, } /* The value of the symbol marking the end of a - procedure or block is the size of the - procedure or block. */ - if ((begin_type == st_Proc || begin_type == st_Block) - && sym_ptr->ecoff_sym.sc != (int) sc_Info) + procedure is the size of the procedure. The + value of the symbol marking the end of a + block is the offset from the start of the + procedure to the block. */ + if (begin_type == st_Proc) { know (as_sym != (symbolS *) NULL); know (begin_ptr->as_sym != (symbolS *) NULL); @@ -3887,6 +3959,15 @@ ecoff_build_symbols (buf, (S_GET_VALUE (as_sym) - S_GET_VALUE (begin_ptr->as_sym)); } + else if (begin_type == st_Block + && sym_ptr->ecoff_sym.sc != (int) sc_Info) + { + know (as_sym != (symbolS *) NULL); + know (sym_ptr->proc_ptr != (proc_t *) NULL); + sym_ptr->ecoff_sym.value = + (S_GET_VALUE (as_sym) + - S_GET_VALUE (sym_ptr->proc_ptr->sym->as_sym)); + } } for (f = sym_ptr->forward_ref; @@ -3908,18 +3989,21 @@ ecoff_build_symbols (buf, ecoff_swap_sym_out (stdoutput, &sym_ptr->ecoff_sym, sym_out); ++sym_out; + sym_ptr->sym_index = isym; - ++isym; if (sym_ptr->proc_ptr != (proc_t *) NULL && sym_ptr->proc_ptr->sym == sym_ptr) sym_ptr->proc_ptr->pdr.isym = isym - ifilesym; + + ++isym; } /* If this is an external symbol, swap it out. */ if (as_sym != (symbolS *) NULL && (S_IS_EXTERNAL (as_sym) - || ! S_IS_DEFINED (as_sym))) + || ! S_IS_DEFINED (as_sym)) + && ! MIPS_IS_STAB (&sym_ptr->ecoff_sym)) { EXTR ext; @@ -4325,6 +4409,10 @@ ecoff_frob_file () struct hash_control *ext_str_hash; char *set; + /* Make sure we have a file. */ + if (first_file == (efdr_t *) NULL) + add_file ((const char *) NULL, 0); + /* Handle any top level tags. */ for (ptag = top_tag_head->first_tag; ptag != (tag_t *) NULL; @@ -4477,8 +4565,6 @@ ecoff_frob_file () #undef SET - /* FIXME: set the gp value. */ - /* FIXME: set the register masks. */ ecoff_data (stdoutput)->raw_size = offset; diff --git a/gas/config/tc-mips.c b/gas/config/tc-mips.c index e37e5f70aba..3a853f210d5 100644 --- a/gas/config/tc-mips.c +++ b/gas/config/tc-mips.c @@ -41,6 +41,7 @@ #include "mips-opcode.h" #define AT 1 +#define GP 28 #define RA 31 static int mips_warn_about_macros; @@ -49,6 +50,11 @@ static int mips_nomove; static int mips_noat; static int mips_nobopt; +#ifdef OBJ_ECOFF +/* The size of the small data section. */ +static int g_switch_value = 8; +#endif + #define N_RMASK 0xc4 #define N_VFP 0xd4 @@ -84,7 +90,7 @@ const char FLT_CHARS[] = "rRsSfFdDxXpP"; but nothing is ideal around here. */ -static char *insn_error; +static char *insn_error; static int byte_order = BYTE_ORDER; @@ -99,25 +105,26 @@ static int auto_align = 1; #define internalError() as_fatal ("MIPS internal Error"); #endif -static void append_insn PARAMS ((struct mips_cl_insn *ip, - expressionS *p, +static void append_insn PARAMS ((struct mips_cl_insn * ip, + expressionS * p, bfd_reloc_code_real_type r)); -static void macro_build PARAMS ((int *counter, expressionS *ep, +static int gp_reference PARAMS ((expressionS * ep)); +static void macro_build PARAMS ((int *counter, expressionS * ep, const char *name, const char *fmt, ...)); -static void macro_build_lui PARAMS ((int *counter, expressionS *ep, +static void macro_build_lui PARAMS ((int *counter, expressionS * ep, int regnum)); static void set_at PARAMS ((int *counter, int reg)); static void set_at_unsigned PARAMS ((int *counter, int reg)); -static void check_absolute_expr PARAMS ((struct mips_cl_insn *ip, - expressionS *expr)); +static void check_absolute_expr PARAMS ((struct mips_cl_insn * ip, + expressionS * expr)); static void load_register PARAMS ((int *counter, - struct mips_cl_insn *ip, - int reg, expressionS *ep)); -static void macro PARAMS ((struct mips_cl_insn *ip)); -static void mips_ip PARAMS ((char *str, struct mips_cl_insn *ip)); -static int my_getSmallExpression PARAMS ((expressionS *ep, char *str)); -static void my_getExpression PARAMS ((expressionS *ep, char *str)); + struct mips_cl_insn * ip, + int reg, expressionS * ep)); +static void macro PARAMS ((struct mips_cl_insn * ip)); +static void mips_ip PARAMS ((char *str, struct mips_cl_insn * ip)); +static int my_getSmallExpression PARAMS ((expressionS * ep, char *str)); +static void my_getExpression PARAMS ((expressionS * ep, char *str)); static symbolS *get_symbol PARAMS ((void)); static long get_optional_absolute_expression PARAMS ((void)); static void s_align PARAMS ((int)); @@ -160,51 +167,52 @@ static void s_mask PARAMS ((char)); const pseudo_typeS md_pseudo_table[] = { - /* MIPS specific pseudo-ops. */ - { "option", s_option, 0 }, - { "set", s_mipsset, 0 }, - { "rdata", s_change_sec, 'r', }, - { "sdata", s_change_sec, 's', }, + /* MIPS specific pseudo-ops. */ + {"option", s_option, 0}, + {"set", s_mipsset, 0}, + {"rdata", s_change_sec, 'r',}, + {"sdata", s_change_sec, 's',}, - /* Relatively generic pseudo-ops that happen to be used on MIPS + /* Relatively generic pseudo-ops that happen to be used on MIPS chips. */ - { "asciiz", stringer, 1 }, - { "bss", s_change_sec, 'b' }, - { "err", s_err, 0 }, - { "half", s_cons, 1 }, + {"asciiz", stringer, 1}, + {"bss", s_change_sec, 'b'}, + {"err", s_err, 0}, + {"half", s_cons, 1}, - /* These pseudo-ops are defined in read.c, but must be overridden + /* These pseudo-ops are defined in read.c, but must be overridden here for one reason or another. */ - { "align", s_align, 0 }, - { "byte", s_cons, 0 }, - { "data", s_change_sec, 'd' }, - { "double", s_float_cons, 1 }, - { "extern", s_extern, 0 }, - { "float", s_float_cons, 0 }, - { "text", s_change_sec, 't' }, - { "word", s_cons, 2 }, + {"align", s_align, 0}, + {"byte", s_cons, 0}, + {"data", s_change_sec, 'd'}, + {"double", s_float_cons, 1}, + {"extern", s_extern, 0}, + {"float", s_float_cons, 0}, + {"text", s_change_sec, 't'}, + {"word", s_cons, 2}, #ifndef OBJ_ECOFF - /* These pseudo-ops should be defined by the object file format. + /* These pseudo-ops should be defined by the object file format. However, ECOFF is the only format which currently defines them, so we have versions here for a.out. */ - { "aent", s_ent, 1 }, - { "end", s_mipsend, 0 }, - { "ent", s_ent, 0 }, - { "file", s_file, 0 }, - { "fmask", s_ignore, 'F' }, - { "frame", s_ignore, 0 }, - { "loc", s_ignore, 0 }, - { "mask", s_ignore, 'R' }, - { "verstamp", s_ignore, 0 }, + {"aent", s_ent, 1}, + {"end", s_mipsend, 0}, + {"ent", s_ent, 0}, + {"file", s_file, 0}, + {"fmask", s_ignore, 'F'}, + {"frame", s_ignore, 0}, + {"loc", s_ignore, 0}, + {"mask", s_ignore, 'R'}, + {"verstamp", s_ignore, 0}, #endif - /* Sentinel. */ - { NULL } + /* Sentinel. */ + {NULL} }; -const relax_typeS md_relax_table[] = { - 0 +const relax_typeS md_relax_table[] = +{ + 0 }; @@ -220,36 +228,42 @@ static bfd_reloc_code_real_type offset_reloc; * set up all the tables, etc. that the MD part of the assembler will need. */ void -md_begin() +md_begin () { - register char *retval = NULL; - register unsigned int i = 0; + register char *retval = NULL; + register unsigned int i = 0; - if ((op_hash = hash_new()) == NULL) { - as_fatal("Virtual memory exhausted"); + if ((op_hash = hash_new ()) == NULL) + { + as_fatal ("Virtual memory exhausted"); } - for (i = 0; i < NUMOPCODES;) { - const char *name = mips_opcodes[i].name; - - retval = hash_insert(op_hash, name, &mips_opcodes[i]); - if (retval != NULL && *retval != '\0') { - fprintf (stderr, "internal error: can't hash `%s': %s\n", - mips_opcodes[i].name, retval); - as_fatal ("Broken assembler. No assembly attempted."); - } - do { - if ((mips_opcodes[i].match & mips_opcodes[i].mask) != - mips_opcodes[i].match) { - fprintf (stderr, "internal error: bad opcode: `%s' \"%s\"\n", - mips_opcodes[i].name, mips_opcodes[i].args); - as_fatal ("Broken assembler. No assembly attempted."); + for (i = 0; i < NUMOPCODES;) + { + const char *name = mips_opcodes[i].name; + + retval = hash_insert (op_hash, name, &mips_opcodes[i]); + if (retval != NULL && *retval != '\0') + { + fprintf (stderr, "internal error: can't hash `%s': %s\n", + mips_opcodes[i].name, retval); + as_fatal ("Broken assembler. No assembly attempted."); + } + do + { + if ((mips_opcodes[i].match & mips_opcodes[i].mask) != + mips_opcodes[i].match) + { + fprintf (stderr, "internal error: bad opcode: `%s' \"%s\"\n", + mips_opcodes[i].name, mips_opcodes[i].args); + as_fatal ("Broken assembler. No assembly attempted."); } - ++i; - } while ((i < NUMOPCODES) && !strcmp(mips_opcodes[i].name, name)); + ++i; + } + while ((i < NUMOPCODES) && !strcmp (mips_opcodes[i].name, name)); } #ifndef OBJ_ECOFF - md_obj_begin (); + md_obj_begin (); #endif } @@ -262,36 +276,42 @@ md_end () } void -md_assemble(str) - char *str; +md_assemble (str) + char *str; { - struct mips_cl_insn insn; - static int init; - - if (!init) { - /* set the default alignment for the text section (2**2) */ - /* This should go in md_begin but text_section isn't initialized then */ - record_alignment(text_section, 2); - init = 1; + struct mips_cl_insn insn; + static int init; + + if (!init) + { + /* set the default alignment for the text section (2**2) */ + /* This should go in md_begin but text_section isn't initialized then */ + record_alignment (text_section, 2); + bfd_set_gp_size (stdoutput, g_switch_value); + init = 1; } - imm_expr.X_seg = absent_section; - offset_expr.X_seg = absent_section; + imm_expr.X_seg = absent_section; + offset_expr.X_seg = absent_section; - mips_ip(str, &insn); - if (insn_error) { - as_bad("%s `%s'", insn_error, str); - return; + mips_ip (str, &insn); + if (insn_error) + { + as_bad ("%s `%s'", insn_error, str); + return; + } + if (insn.insn_mo->pinfo == INSN_MACRO) + { + macro (&insn); } - if (insn.insn_mo->pinfo == INSN_MACRO) { - macro(&insn); - } else { - if (imm_expr.X_seg != absent_section) - append_insn(&insn, &imm_expr, imm_reloc); - else if (offset_expr.X_seg != absent_section) - append_insn(&insn, &offset_expr, offset_reloc); - else - append_insn(&insn, NULL, BFD_RELOC_UNUSED); + else + { + if (imm_expr.X_seg != absent_section) + append_insn (&insn, &imm_expr, imm_reloc); + else if (offset_expr.X_seg != absent_section) + append_insn (&insn, &offset_expr, offset_reloc); + else + append_insn (&insn, NULL, BFD_RELOC_UNUSED); } } @@ -303,75 +323,116 @@ md_assemble(str) * Output an instruction. */ static void -append_insn(ip, address_expr, reloc_type) - struct mips_cl_insn *ip; - expressionS *address_expr; - bfd_reloc_code_real_type reloc_type; +append_insn (ip, address_expr, reloc_type) + struct mips_cl_insn *ip; + expressionS *address_expr; + bfd_reloc_code_real_type reloc_type; { - char *f; + char *f; - f = frag_more(4); -#if 0 /* This is testing the address of the frag, not the alignment of + f = frag_more (4); +#if 0 /* This is testing the address of the frag, not the alignment of the instruction in the current section. */ - if ((int) f & 3) { - as_bad(ALIGN_ERR); - as_bad(ALIGN_ERR2); + if ((int) f & 3) + { + as_bad (ALIGN_ERR); + as_bad (ALIGN_ERR2); } #endif - if (address_expr != NULL) { - fixS *fixP; + if (address_expr != NULL) + { + fixS *fixP; - if (address_expr->X_seg == &bfd_abs_section) { - switch (reloc_type) { + if (address_expr->X_seg == &bfd_abs_section) + { + switch (reloc_type) + { case BFD_RELOC_32: - ip->insn_opcode |= address_expr->X_add_number; - break; + ip->insn_opcode |= address_expr->X_add_number; + break; case BFD_RELOC_LO16: - ip->insn_opcode |= address_expr->X_add_number & 0xffff; - break; + ip->insn_opcode |= address_expr->X_add_number & 0xffff; + break; case BFD_RELOC_MIPS_JMP: case BFD_RELOC_16_PCREL_S2: - goto need_reloc; + goto need_reloc; default: - internalError(); + internalError (); } - } else { - assert(reloc_type != BFD_RELOC_UNUSED); + } + else + { + assert (reloc_type != BFD_RELOC_UNUSED); need_reloc: - fixP = fix_new(frag_now, f - frag_now->fr_literal, 4, - address_expr->X_add_symbol, - address_expr->X_subtract_symbol, - address_expr->X_add_number, - reloc_type == BFD_RELOC_16_PCREL_S2, - reloc_type); + fixP = fix_new (frag_now, f - frag_now->fr_literal, 4, + address_expr->X_add_symbol, + address_expr->X_subtract_symbol, + address_expr->X_add_number, + reloc_type == BFD_RELOC_16_PCREL_S2, + reloc_type); } } - md_number_to_chars(f, ip->insn_opcode, 4); - - /* - * Fill all delay slots with nops. - */ - if (!mips_noreorder) { - if (ip->insn_mo->pinfo & ANY_DELAY) { - f = frag_more(4); - md_number_to_chars(f, 0, 4); + md_number_to_chars (f, ip->insn_opcode, 4); + + /* + * Fill all delay slots with nops. + */ + if (!mips_noreorder) + { + if (ip->insn_mo->pinfo & ANY_DELAY) + { + f = frag_more (4); + md_number_to_chars (f, 0, 4); }; - /* One extra nop */ - if (ip->insn_mo->pinfo & INSN_EXTRA_DELAY) { - f = frag_more(4); - md_number_to_chars(f, 0, 4); + /* One extra nop */ + if (ip->insn_mo->pinfo & INSN_EXTRA_DELAY) + { + f = frag_more (4); + md_number_to_chars (f, 0, 4); } } } +/* Return 1 if an expression can be accessed via the GP register. */ + +static int +gp_reference (ep) + expressionS *ep; +{ +#ifdef OBJ_ECOFF + symbolS *sym; + const char *segname; + + sym = ep->X_add_symbol; + if (sym == (symbolS *) NULL + || ep->X_subtract_symbol != (symbolS *) NULL) + return 0; + if (! S_IS_DEFINED (sym) + && S_GET_VALUE (sym) != 0 + && S_GET_VALUE (sym) <= g_switch_value) + return 1; + segname = segment_name (S_GET_SEGMENT (ep->X_add_symbol)); + return (strcmp (segname, ".sdata") == 0 + || strcmp (segname, ".sbss") == 0); +#else /* ! defined (OBJ_ECOFF) */ + /* The GP register is only used for ECOFF. */ + return 0; +#endif /* ! defined (OBJ_ECOFF) */ +} + +/* Build an instruction created by a macro expansion. This is passed + a pointer to the count of instructions created so far, an + expression, the name of the instruction to build, an operand format + string, and corresponding arguments. */ + #ifndef NO_STDARG static void macro_build (int *counter, - expressionS *ep, + expressionS * ep, const char *name, const char *fmt, ...) @@ -385,113 +446,124 @@ macro_build (counter, ep, name, fmt, va_alist) va_dcl #endif /* ! defined (NO_STDARG) */ { - struct mips_cl_insn insn; - bfd_reloc_code_real_type r; - va_list args; + struct mips_cl_insn insn; + bfd_reloc_code_real_type r; + va_list args; #ifndef NO_STDARG - va_start(args, fmt); + va_start (args, fmt); #else - va_start(args); + va_start (args); #endif - /* - * If the macro is about to expand into a second instruction, - * print a warning if needed. We need to pass ip as a parameter - * to generate a better warning message here... - */ - if (mips_warn_about_macros && *counter == 1) - as_warn("Macro instruction expanded into multiple instructions"); - - *counter += 1; /* bump instruction counter */ - - r = BFD_RELOC_UNUSED; - insn.insn_mo = (struct mips_opcode *) hash_find(op_hash, name); - assert(insn.insn_mo); - assert(strcmp(name, insn.insn_mo->name) == 0); - - while (strcmp(fmt, insn.insn_mo->args) != 0) { - ++insn.insn_mo; - assert(insn.insn_mo->name); - assert(strcmp(name, insn.insn_mo->name) == 0); + /* + * If the macro is about to expand into a second instruction, + * print a warning if needed. We need to pass ip as a parameter + * to generate a better warning message here... + */ + if (mips_warn_about_macros && *counter == 1) + as_warn ("Macro instruction expanded into multiple instructions"); + + *counter += 1; /* bump instruction counter */ + + r = BFD_RELOC_UNUSED; + insn.insn_mo = (struct mips_opcode *) hash_find (op_hash, name); + assert (insn.insn_mo); + assert (strcmp (name, insn.insn_mo->name) == 0); + + while (strcmp (fmt, insn.insn_mo->args) != 0) + { + ++insn.insn_mo; + assert (insn.insn_mo->name); + assert (strcmp (name, insn.insn_mo->name) == 0); } - assert(insn.insn_mo->pinfo != INSN_MACRO); - insn.insn_opcode = insn.insn_mo->match; - for (;;) { - switch (*fmt++) { + assert (insn.insn_mo->pinfo != INSN_MACRO); + insn.insn_opcode = insn.insn_mo->match; + for (;;) + { + switch (*fmt++) + { case '\0': - break; + break; case ',': case '(': case ')': - continue; + continue; case 't': case 'w': - insn.insn_opcode |= va_arg(args, int) << 16; - continue; + insn.insn_opcode |= va_arg (args, int) << 16; + continue; case 'c': case 'T': case 'W': - insn.insn_opcode |= va_arg(args, int) << 16; - continue; + insn.insn_opcode |= va_arg (args, int) << 16; + continue; case 'd': - insn.insn_opcode |= va_arg(args, int) << 11; - continue; + insn.insn_opcode |= va_arg (args, int) << 11; + continue; case 'V': case 'S': - insn.insn_opcode |= va_arg(args, int) << 11; - continue; + insn.insn_opcode |= va_arg (args, int) << 11; + continue; case '<': - insn.insn_opcode |= va_arg(args, int) << 6; - continue; + insn.insn_opcode |= va_arg (args, int) << 6; + continue; case 'D': - insn.insn_opcode |= va_arg(args, int) << 6; - continue; + insn.insn_opcode |= va_arg (args, int) << 6; + continue; case 'b': case 's': case 'r': case 'v': - insn.insn_opcode |= va_arg(args, int) << 21; - continue; + insn.insn_opcode |= va_arg (args, int) << 21; + continue; case 'i': case 'j': case 'o': - r = BFD_RELOC_LO16; - continue; + r = BFD_RELOC_LO16; + continue; case 'p': - assert(ep != NULL); - /* - * This allows macro() to pass an immediate expression for - * creating short branches without creating a symbol. - * Note that the expression still might come from the assembly - * input, in which case the value is not checked for range nor - * is a relocation entry generated (yuck). - */ - if (ep->X_add_symbol == NULL && ep->X_seg == &bfd_abs_section) { - insn.insn_opcode |= (ep->X_add_number >> 2) & 0xffff; - ep = NULL; - } else - r = BFD_RELOC_16_PCREL_S2; - continue; + assert (ep != NULL); + /* + * This allows macro() to pass an immediate expression for + * creating short branches without creating a symbol. + * Note that the expression still might come from the assembly + * input, in which case the value is not checked for range nor + * is a relocation entry generated (yuck). + */ + if (ep->X_add_symbol == NULL && ep->X_seg == &bfd_abs_section) + { + insn.insn_opcode |= (ep->X_add_number >> 2) & 0xffff; + ep = NULL; + } + else + r = BFD_RELOC_16_PCREL_S2; + continue; default: - internalError(); + internalError (); } - break; + break; } - va_end(args); - assert(r == BFD_RELOC_UNUSED ? ep == NULL : ep != NULL); - append_insn(&insn, ep, r); + va_end (args); + assert (r == BFD_RELOC_UNUSED ? ep == NULL : ep != NULL); + + /* Use GP relative addressing if possible. */ + if (r == BFD_RELOC_LO16 + && gp_reference (ep)) + r = BFD_RELOC_MIPS_GPREL; + + append_insn (&insn, ep, r); } /* @@ -503,45 +575,49 @@ macro_build_lui (counter, ep, regnum) expressionS *ep; int regnum; { - expressionS high_expr; - struct mips_cl_insn insn; - bfd_reloc_code_real_type r; - CONST char *name = "lui"; - CONST char *fmt = "t,u"; - - high_expr = *ep; - - if (high_expr.X_seg == &bfd_abs_section) { - /* we can compute the instruction now without a relocation entry */ - if (high_expr.X_add_number & 0x8000) - high_expr.X_add_number += 0x10000; - high_expr.X_add_number = - ((unsigned long) high_expr.X_add_number >> 16) & 0xffff; - r = BFD_RELOC_UNUSED; - } else - r = BFD_RELOC_HI16_S; - - /* - * If the macro is about to expand into a second instruction, - * print a warning if needed. We need to pass ip as a parameter - * to generate a better warning message here... - */ - if (mips_warn_about_macros && *counter == 1) - as_warn("Macro instruction expanded into multiple instructions"); - - *counter += 1; /* bump instruction counter */ - - insn.insn_mo = (struct mips_opcode *) hash_find(op_hash, name); - assert(insn.insn_mo); - assert(strcmp(name, insn.insn_mo->name) == 0); - assert(strcmp(fmt, insn.insn_mo->args) == 0); - - insn.insn_opcode = insn.insn_mo->match | (regnum << 16); - if (r == BFD_RELOC_UNUSED) { - insn.insn_opcode |= high_expr.X_add_number; - append_insn(&insn, NULL, r); - } else - append_insn(&insn, &high_expr, r); + expressionS high_expr; + struct mips_cl_insn insn; + bfd_reloc_code_real_type r; + CONST char *name = "lui"; + CONST char *fmt = "t,u"; + + high_expr = *ep; + + if (high_expr.X_seg == &bfd_abs_section) + { + /* we can compute the instruction now without a relocation entry */ + if (high_expr.X_add_number & 0x8000) + high_expr.X_add_number += 0x10000; + high_expr.X_add_number = + ((unsigned long) high_expr.X_add_number >> 16) & 0xffff; + r = BFD_RELOC_UNUSED; + } + else + r = BFD_RELOC_HI16_S; + + /* + * If the macro is about to expand into a second instruction, + * print a warning if needed. We need to pass ip as a parameter + * to generate a better warning message here... + */ + if (mips_warn_about_macros && *counter == 1) + as_warn ("Macro instruction expanded into multiple instructions"); + + *counter += 1; /* bump instruction counter */ + + insn.insn_mo = (struct mips_opcode *) hash_find (op_hash, name); + assert (insn.insn_mo); + assert (strcmp (name, insn.insn_mo->name) == 0); + assert (strcmp (fmt, insn.insn_mo->args) == 0); + + insn.insn_opcode = insn.insn_mo->match | (regnum << 16); + if (r == BFD_RELOC_UNUSED) + { + insn.insn_opcode |= high_expr.X_add_number; + append_insn (&insn, NULL, r); + } + else + append_insn (&insn, &high_expr, r); } /* set_at() @@ -554,22 +630,23 @@ set_at (counter, reg) int reg; { - switch (imm_expr.X_add_number & 0xffff8000) { - case 0: - case 0xffff8000: - macro_build(counter, &imm_expr, "slti", "t,r,j", AT, reg); - return; + switch (imm_expr.X_add_number & 0xffff8000) + { + case 0: + case 0xffff8000: + macro_build (counter, &imm_expr, "slti", "t,r,j", AT, reg); + return; - case 0x8000: - macro_build(counter, &imm_expr, "ori", "t,r,i", AT, 0); - break; + case 0x8000: + macro_build (counter, &imm_expr, "ori", "t,r,i", AT, 0); + break; - default: - macro_build_lui(counter, &imm_expr, AT); - if (imm_expr.X_add_number & 0xffff) - macro_build(counter, &imm_expr, "addiu", "t,r,j", AT, AT); - } - macro_build(counter, NULL, "slt", "d,v,t", AT, reg, AT); + default: + macro_build_lui (counter, &imm_expr, AT); + if (imm_expr.X_add_number & 0xffff) + macro_build (counter, &imm_expr, "addiu", "t,r,j", AT, AT); + } + macro_build (counter, NULL, "slt", "d,v,t", AT, reg, AT); } /* set_at_unsigned() @@ -583,22 +660,23 @@ set_at_unsigned (counter, reg) int reg; { - switch (imm_expr.X_add_number & 0xffff8000) { - case 0: - case 0xffff8000: - macro_build(counter, &imm_expr, "sltiu", "t,r,j", AT, reg); - return; + switch (imm_expr.X_add_number & 0xffff8000) + { + case 0: + case 0xffff8000: + macro_build (counter, &imm_expr, "sltiu", "t,r,j", AT, reg); + return; - case 0x8000: - macro_build(counter, &imm_expr, "ori", "t,r,i", AT, 0); - break; + case 0x8000: + macro_build (counter, &imm_expr, "ori", "t,r,i", AT, 0); + break; - default: - macro_build_lui(counter, &imm_expr, AT); - if (imm_expr.X_add_number & 0xffff) - macro_build(counter, &imm_expr, "addiu", "t,r,j", AT, AT); - } - macro_build(counter, NULL, "sltu", "d,v,t", AT, reg, AT); + default: + macro_build_lui (counter, &imm_expr, AT); + if (imm_expr.X_add_number & 0xffff) + macro_build (counter, &imm_expr, "addiu", "t,r,j", AT, AT); + } + macro_build (counter, NULL, "sltu", "d,v,t", AT, reg, AT); } static void @@ -608,7 +686,7 @@ check_absolute_expr (ip, expr) { if (expr->X_seg != &bfd_abs_section) - as_warn("Instruction %s requires absolute expression", ip->insn_mo->name); + as_warn ("Instruction %s requires absolute expression", ip->insn_mo->name); } /* load_register() @@ -617,26 +695,27 @@ check_absolute_expr (ip, expr) */ static void load_register (counter, ip, reg, ep) - int *counter; - struct mips_cl_insn *ip; - int reg; - expressionS *ep; + int *counter; + struct mips_cl_insn *ip; + int reg; + expressionS *ep; { - switch (ep->X_add_number & 0xffff8000) { - case 0: - case 0xffff8000: - macro_build(counter, ep, "addiu", "t,r,j", reg, 0); - break; - - case 0x8000: - macro_build(counter, ep, "ori", "t,r,i", reg, 0); - break; - - default: - macro_build_lui(counter, ep, reg); - if (ep->X_add_number & 0xffff) - macro_build(counter, ep, "addiu", "t,r,j", reg, reg); - } + switch (ep->X_add_number & 0xffff8000) + { + case 0: + case 0xffff8000: + macro_build (counter, ep, "addiu", "t,r,j", reg, 0); + break; + + case 0x8000: + macro_build (counter, ep, "ori", "t,r,i", reg, 0); + break; + + default: + macro_build_lui (counter, ep, reg); + if (ep->X_add_number & 0xffff) + macro_build (counter, ep, "addiu", "t,r,j", reg, reg); + } } @@ -662,29 +741,31 @@ static void macro (ip) struct mips_cl_insn *ip; { - register int treg, sreg, dreg, breg; - int tempreg; - int mask; - int icnt = 0; - int used_at; - int save_reorder_condition; - expressionS expr1; - const char *s; - - treg = (ip->insn_opcode >> 16) & 0x1f; - dreg = (ip->insn_opcode >> 11) & 0x1f; - sreg = breg = (ip->insn_opcode >> 21) & 0x1f; - mask = ip->insn_mo->mask; - - expr1.X_seg = &bfd_abs_section; - expr1.X_subtract_symbol = NULL; - expr1.X_add_symbol = NULL; - expr1.X_add_number = 1; - - switch (mask) { + register int treg, sreg, dreg, breg; + int tempreg; + int mask; + int icnt = 0; + int used_at; + int save_reorder_condition; + expressionS expr1; + const char *s; + const char *fmt; + + treg = (ip->insn_opcode >> 16) & 0x1f; + dreg = (ip->insn_opcode >> 11) & 0x1f; + sreg = breg = (ip->insn_opcode >> 21) & 0x1f; + mask = ip->insn_mo->mask; + + expr1.X_seg = &bfd_abs_section; + expr1.X_subtract_symbol = NULL; + expr1.X_add_symbol = NULL; + expr1.X_add_number = 1; + + switch (mask) + { case M_ABS: case M_ABSU: - /* + /* Note: mips algorithm requires the move in the delay slot.
: bgez $a0,0x4001bc : move v0,$a0 @@ -692,464 +773,521 @@ macro (ip) : nop */ - save_reorder_condition = mips_noreorder; - mips_noreorder = 1; + save_reorder_condition = mips_noreorder; + mips_noreorder = 1; - expr1.X_add_number = 8; - macro_build(&icnt, &expr1, "bgez", "s,p", sreg); - macro_build(&icnt, NULL, "move", "d,s", dreg, sreg, 0); - macro_build(&icnt, NULL, mask == M_ABS ? "sub" : "subu", "d,v,t", - dreg, 0, sreg); + expr1.X_add_number = 8; + macro_build (&icnt, &expr1, "bgez", "s,p", sreg); + macro_build (&icnt, NULL, "move", "d,s", dreg, sreg, 0); + macro_build (&icnt, NULL, mask == M_ABS ? "sub" : "subu", "d,v,t", + dreg, 0, sreg); - mips_noreorder = save_reorder_condition; - return; + mips_noreorder = save_reorder_condition; + return; case M_ADD_I: case M_ADDU_I: - switch (imm_expr.X_add_number & 0xffff8000) { - case 0: - case 0xffff8000: - macro_build(&icnt, &imm_expr, - mask == M_ADD_I ? "addi" : "addiu", "t,r,j", treg, sreg); - return; - - case 0x8000: - macro_build(&icnt, &imm_expr, "ori", "t,r,i", AT, 0); - break; + switch (imm_expr.X_add_number & 0xffff8000) + { + case 0: + case 0xffff8000: + macro_build (&icnt, &imm_expr, + mask == M_ADD_I ? "addi" : "addiu", "t,r,j", treg, sreg); + return; - default: - macro_build_lui(&icnt, &imm_expr, AT); - if (imm_expr.X_add_number & 0xffff) - macro_build(&icnt, &imm_expr, "addiu", "t,r,j", AT, AT); - break; + case 0x8000: + macro_build (&icnt, &imm_expr, "ori", "t,r,i", AT, 0); + break; + + default: + macro_build_lui (&icnt, &imm_expr, AT); + if (imm_expr.X_add_number & 0xffff) + macro_build (&icnt, &imm_expr, "addiu", "t,r,j", AT, AT); + break; } - macro_build(&icnt, NULL, - mask == M_ADD_I ? "add" : "addu", "d,v,t", treg, sreg, AT); - break; + macro_build (&icnt, NULL, + mask == M_ADD_I ? "add" : "addu", "d,v,t", treg, sreg, AT); + break; case M_AND_I: case M_OR_I: case M_NOR_I: case M_XOR_I: - switch (imm_expr.X_add_number & 0xffff8000) { + switch (imm_expr.X_add_number & 0xffff8000) + { case 0: case 0x8000: - switch (mask) { + switch (mask) + { case M_AND_I: - macro_build(&icnt, &imm_expr, "andi", "t,r,i", treg, sreg); - return; + macro_build (&icnt, &imm_expr, "andi", "t,r,i", treg, sreg); + return; case M_OR_I: - macro_build(&icnt, &imm_expr, "ori", "t,r,i", treg, sreg); - return; + macro_build (&icnt, &imm_expr, "ori", "t,r,i", treg, sreg); + return; case M_NOR_I: - macro_build(&icnt, &imm_expr, "ori", "t,r,i", treg, sreg); - macro_build(&icnt, &imm_expr, "nor", "d,v,t", treg, treg, 0); - return; + macro_build (&icnt, &imm_expr, "ori", "t,r,i", treg, sreg); + macro_build (&icnt, &imm_expr, "nor", "d,v,t", treg, treg, 0); + return; case M_XOR_I: - macro_build(&icnt, &imm_expr, "xori", "t,r,i", treg, sreg); - return; + macro_build (&icnt, &imm_expr, "xori", "t,r,i", treg, sreg); + return; default: - internalError(); + internalError (); } case 0xffff8000: - macro_build(&icnt, &imm_expr, "addiu", "t,r,j", AT, 0); - break; + macro_build (&icnt, &imm_expr, "addiu", "t,r,j", AT, 0); + break; default: - macro_build_lui(&icnt, &imm_expr, AT); - if (imm_expr.X_add_number & 0xffff) - macro_build(&icnt, &imm_expr, "addiu", "t,r,j", AT, AT); + macro_build_lui (&icnt, &imm_expr, AT); + if (imm_expr.X_add_number & 0xffff) + macro_build (&icnt, &imm_expr, "addiu", "t,r,j", AT, AT); } - switch (mask) { + switch (mask) + { case M_AND_I: - macro_build(&icnt, NULL, "and", "d,v,t", treg, sreg, AT); - break; + macro_build (&icnt, NULL, "and", "d,v,t", treg, sreg, AT); + break; case M_OR_I: - macro_build(&icnt, NULL, "or", "d,v,t", treg, sreg, AT); - break; + macro_build (&icnt, NULL, "or", "d,v,t", treg, sreg, AT); + break; case M_NOR_I: - macro_build(&icnt, NULL, "nor", "d,v,t", treg, sreg, AT); - break; + macro_build (&icnt, NULL, "nor", "d,v,t", treg, sreg, AT); + break; case M_XOR_I: - macro_build(&icnt, NULL, "xor", "d,v,t", treg, sreg, AT); - break; + macro_build (&icnt, NULL, "xor", "d,v,t", treg, sreg, AT); + break; default: - internalError(); + internalError (); } - break; + break; case M_BEQ_I: case M_BNE_I: - if (imm_expr.X_add_number == 0) { - macro_build(&icnt, &offset_expr, mask == M_BEQ_I ? "beq" : "bne", - "s,t,p", sreg, 0); - return; - } - load_register(&icnt, ip, AT, &imm_expr); - macro_build(&icnt, &offset_expr, mask == M_BEQ_I ? "beq" : "bne", - "s,t,p", sreg, AT); - break; + if (imm_expr.X_add_number == 0) + { + macro_build (&icnt, &offset_expr, mask == M_BEQ_I ? "beq" : "bne", + "s,t,p", sreg, 0); + return; + } + load_register (&icnt, ip, AT, &imm_expr); + macro_build (&icnt, &offset_expr, mask == M_BEQ_I ? "beq" : "bne", + "s,t,p", sreg, AT); + break; case M_BGE: - if (treg == 0) { - macro_build(&icnt, &offset_expr, "bgez", "s,p", sreg); - return; + if (treg == 0) + { + macro_build (&icnt, &offset_expr, "bgez", "s,p", sreg); + return; } - macro_build(&icnt, NULL, "slt", "d,v,t", AT, sreg, treg); - macro_build(&icnt, &offset_expr, "beq", "s,t,p", AT, 0); - break; + 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: - imm_expr.X_add_number++; - /* FALLTHROUGH */ + imm_expr.X_add_number++; + /* FALLTHROUGH */ case M_BGE_I: - if (imm_expr.X_add_number == 0) { - macro_build(&icnt, &offset_expr, "bgez", "s,p", sreg); - return; + if (imm_expr.X_add_number == 0) + { + macro_build (&icnt, &offset_expr, "bgez", "s,p", sreg); + return; } - if (imm_expr.X_add_number == 1) { - macro_build(&icnt, &offset_expr, "bgtz", "s,p", sreg); - return; + if (imm_expr.X_add_number == 1) + { + macro_build (&icnt, &offset_expr, "bgtz", "s,p", sreg); + return; } - set_at(&icnt, sreg); - macro_build(&icnt, &offset_expr, "beq", "s,t,p", AT, 0); - break; + set_at (&icnt, sreg); + macro_build (&icnt, &offset_expr, "beq", "s,t,p", AT, 0); + break; case M_BGEU: - if (treg == 0) { - macro_build(&icnt, &offset_expr, "b", "p"); - return; + if (treg == 0) + { + macro_build (&icnt, &offset_expr, "b", "p"); + return; } - macro_build(&icnt, NULL, "sltu", "d,v,t", AT, sreg, treg); - macro_build(&icnt, &offset_expr, "beq", "s,t,p", AT, 0); - break; + 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_BGEU_I: - if (imm_expr.X_add_number == 0) { - macro_build(&icnt, &offset_expr, "b", "p"); - return; + if (imm_expr.X_add_number == 0) + { + macro_build (&icnt, &offset_expr, "b", "p"); + return; } - if (imm_expr.X_add_number == 1) { - macro_build(&icnt, &offset_expr, "bne", "s,t,p", sreg, 0); - return; + if (imm_expr.X_add_number == 1) + { + macro_build (&icnt, &offset_expr, "bne", "s,t,p", sreg, 0); + return; } - set_at_unsigned(&icnt, sreg); - macro_build(&icnt, &offset_expr, "beq", "s,t,p", AT, 0); - break; + set_at_unsigned (&icnt, sreg); + macro_build (&icnt, &offset_expr, "beq", "s,t,p", AT, 0); + break; case M_BGT: - if (treg == 0) { - macro_build(&icnt, &offset_expr, "bgtz", "s,p", sreg); - return; + if (treg == 0) + { + macro_build (&icnt, &offset_expr, "bgtz", "s,p", sreg); + return; } - macro_build(&icnt, NULL, "slt", "d,v,t", AT, treg, sreg); - macro_build(&icnt, &offset_expr, "bne", "s,t,p", AT, 0); - break; + macro_build (&icnt, NULL, "slt", "d,v,t", AT, treg, sreg); + macro_build (&icnt, &offset_expr, "bne", "s,t,p", AT, 0); + break; case M_BGTU: - if (treg == 0) { - macro_build(&icnt, &offset_expr, "bne", "s,t,p", sreg, 0); - return; + if (treg == 0) + { + macro_build (&icnt, &offset_expr, "bne", "s,t,p", sreg, 0); + return; } - macro_build(&icnt, NULL, "sltu", "d,v,t", AT, treg, sreg); - macro_build(&icnt, &offset_expr, "bne", "s,t,p", AT, 0); - break; + 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; + 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; - } - macro_build(&icnt, NULL, "slt", "d,v,t", AT, treg, sreg); - macro_build(&icnt, &offset_expr, "beq", "s,t,p", AT, 0); - break; + if (treg == 0) + { + macro_build (&icnt, &offset_expr, "blez", "s,p", sreg); + 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 == 0) { - 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++; - set_at(&icnt, sreg); - macro_build(&icnt, &offset_expr, "bne", "s,t,p", AT, 0); - break; + if (imm_expr.X_add_number == 0) + { + 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++; + set_at (&icnt, sreg); + 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; + 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; + 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 == 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; + 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; + 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; + 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; + 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 == 0) + { + macro_build (&icnt, &offset_expr, "bltz", "s,p", sreg); + return; } - if (imm_expr.X_add_number == 1) { - macro_build(&icnt, &offset_expr, "blez", "s,p", sreg); - return; + if (imm_expr.X_add_number == 1) + { + macro_build (&icnt, &offset_expr, "blez", "s,p", sreg); + return; } - set_at(&icnt, sreg); - macro_build(&icnt, &offset_expr, "bne", "s,t,p", AT, 0); - break; + set_at (&icnt, sreg); + macro_build (&icnt, &offset_expr, "bne", "s,t,p", AT, 0); + break; case M_BLTU: - if (treg == 0) { - /* NOP */ - if (mips_noreorder) - as_warn("Instruction %s is a nop; deleted", ip->insn_mo->name); - return; - } - macro_build(&icnt, NULL, "sltu", "d,v,t", AT, sreg, treg); - macro_build(&icnt, &offset_expr, "bne", "s,t,p", AT, 0); - break; + if (treg == 0) + { + /* NOP */ + if (mips_noreorder) + as_warn ("Instruction %s is a nop; deleted", ip->insn_mo->name); + 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; + 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) { - as_warn("Divide by zero."); - macro_build(&icnt, NULL, "break", "c", 7); - return; - } - - save_reorder_condition = mips_noreorder; - mips_noreorder = 1; - macro_build(&icnt, NULL, "div", "s,t", sreg, treg); - expr1.X_add_number = 8; - macro_build(&icnt, &expr1, "bne", "s,t,p", treg, 0); - macro_build(&icnt, NULL, "nop", "", 0); - macro_build(&icnt, NULL, "break", "c", 7); - expr1.X_add_number = -1; - macro_build(&icnt, &expr1, "addiu", "t,r,j", AT, 0); - expr1.X_add_number = 16; - macro_build(&icnt, &expr1, "bne", "s,t,p", treg, AT); - expr1.X_add_number = 0x80000000; - macro_build_lui(&icnt, &expr1, AT); - expr1.X_add_number = 8; - macro_build(&icnt, &expr1, "bne", "s,t,p", sreg, AT); - macro_build(&icnt, NULL, "nop", "", 0); - macro_build(&icnt, NULL, "break", "c", 6); - mips_noreorder = save_reorder_condition; - macro_build(&icnt, NULL, mask == M_DIV_3 ? "mflo" : "mfhi", "d", dreg); - /* with reorder on there will be two implicit nop instructions here. */ - break; + if (treg == 0) + { + as_warn ("Divide by zero."); + macro_build (&icnt, NULL, "break", "c", 7); + return; + } + + save_reorder_condition = mips_noreorder; + mips_noreorder = 1; + macro_build (&icnt, NULL, "div", "s,t", sreg, treg); + expr1.X_add_number = 8; + macro_build (&icnt, &expr1, "bne", "s,t,p", treg, 0); + macro_build (&icnt, NULL, "nop", "", 0); + macro_build (&icnt, NULL, "break", "c", 7); + expr1.X_add_number = -1; + macro_build (&icnt, &expr1, "addiu", "t,r,j", AT, 0); + expr1.X_add_number = 16; + macro_build (&icnt, &expr1, "bne", "s,t,p", treg, AT); + expr1.X_add_number = 0x80000000; + macro_build_lui (&icnt, &expr1, AT); + expr1.X_add_number = 8; + macro_build (&icnt, &expr1, "bne", "s,t,p", sreg, AT); + macro_build (&icnt, NULL, "nop", "", 0); + macro_build (&icnt, NULL, "break", "c", 6); + mips_noreorder = save_reorder_condition; + macro_build (&icnt, NULL, mask == M_DIV_3 ? "mflo" : "mfhi", "d", dreg); + /* with reorder on there will be two implicit nop instructions here. */ + break; case M_DIV_3I: case M_DIVU_3I: case M_REM_3I: case M_REMU_3I: - if (imm_expr.X_add_number == 0) { - as_warn("Divide by zero."); - macro_build(&icnt, NULL, "break", "c", 7); - return; - } - if (imm_expr.X_add_number == 1) { - if (mask == (int)M_DIV_3I || mask == (int)M_DIVU_3I) - macro_build(&icnt, NULL, "move", "d,s", dreg, sreg); + if (imm_expr.X_add_number == 0) + { + as_warn ("Divide by zero."); + macro_build (&icnt, NULL, "break", "c", 7); + return; + } + if (imm_expr.X_add_number == 1) + { + if (mask == (int) M_DIV_3I || mask == (int) M_DIVU_3I) + macro_build (&icnt, NULL, "move", "d,s", dreg, sreg); else - macro_build(&icnt, NULL, "move", "d,s", dreg, 0); + macro_build (&icnt, NULL, "move", "d,s", dreg, 0); return; } - load_register(&icnt, ip, AT, &imm_expr); - if (mask == (int)M_DIV_3I || mask == (int)M_REM_3I) - macro_build(&icnt, NULL, "div", "s,t", sreg, AT); - else - macro_build(&icnt, NULL, "divu", "s,t", sreg, AT); - - if (mask == (int)M_DIV_3I || mask == (int)M_DIVU_3I) - macro_build(&icnt, NULL, "mflo", "d", dreg); - else - macro_build(&icnt, NULL, "mfhi", "d", dreg); - /* two implicit nop's required for mflo or mfhi */ - break; + load_register (&icnt, ip, AT, &imm_expr); + if (mask == (int) M_DIV_3I || mask == (int) M_REM_3I) + macro_build (&icnt, NULL, "div", "s,t", sreg, AT); + else + macro_build (&icnt, NULL, "divu", "s,t", sreg, AT); - case M_DIVU_3: - case M_REMU_3: - save_reorder_condition = mips_noreorder; - mips_noreorder = 1; - macro_build(&icnt, NULL, "divu", "s,t", sreg, treg); - expr1.X_add_number = 8; - macro_build(&icnt, &expr1, "bne", "s,t,p", treg, 0); - macro_build(&icnt, NULL, "nop", "", 0); - macro_build(&icnt, NULL, "break", "c", 7); - mips_noreorder = save_reorder_condition; - macro_build(&icnt, NULL, mask == M_DIVU_3 ? "mflo" : "mfhi", "d", dreg); - /* with reorder on there will be two implicit nop instructions here. */ - return; + if (mask == (int) M_DIV_3I || mask == (int) M_DIVU_3I) + macro_build (&icnt, NULL, "mflo", "d", dreg); + else + macro_build (&icnt, NULL, "mfhi", "d", dreg); + /* two implicit nop's required for mflo or mfhi */ + break; + + case M_DIVU_3: + case M_REMU_3: + save_reorder_condition = mips_noreorder; + mips_noreorder = 1; + macro_build (&icnt, NULL, "divu", "s,t", sreg, treg); + expr1.X_add_number = 8; + macro_build (&icnt, &expr1, "bne", "s,t,p", treg, 0); + macro_build (&icnt, NULL, "nop", "", 0); + macro_build (&icnt, NULL, "break", "c", 7); + mips_noreorder = save_reorder_condition; + macro_build (&icnt, NULL, mask == M_DIVU_3 ? "mflo" : "mfhi", "d", dreg); + /* with reorder on there will be two implicit nop instructions here. */ + return; case M_LA: - if (offset_expr.X_seg == &bfd_abs_section) { - load_register(&icnt, ip, treg, &offset_expr); - return; + if (offset_expr.X_seg == &bfd_abs_section) + { + load_register (&icnt, ip, treg, &offset_expr); + return; } - macro_build_lui(&icnt, &offset_expr, treg); - macro_build(&icnt, &offset_expr, "addiu", "t,r,j", treg, treg); - return; + if (gp_reference (&offset_expr)) + macro_build (&icnt, &offset_expr, "addiu", "t,r,j", treg, GP); + else + { + macro_build_lui (&icnt, &offset_expr, treg); + macro_build (&icnt, &offset_expr, "addiu", "t,r,j", treg, treg); + } + return; case M_LA_AB: - tempreg = (breg == treg) ? AT : treg; - if (offset_expr.X_seg == &bfd_abs_section) - load_register(&icnt, ip, tempreg, &offset_expr); - else { - macro_build_lui(&icnt, &offset_expr, tempreg); - macro_build(&icnt, &offset_expr, "addiu", "t,r,j", tempreg, tempreg); - } - if (breg != 0) - macro_build(&icnt, NULL, "addu", "d,v,t", treg, tempreg, breg); - if (breg == treg) - break; - return; + tempreg = (breg == treg) ? AT : treg; + if (offset_expr.X_seg == &bfd_abs_section) + load_register (&icnt, ip, tempreg, &offset_expr); + else if (gp_reference (&offset_expr)) + macro_build (&icnt, &offset_expr, "addiu", "t,r,j", tempreg, GP); + else + { + macro_build_lui (&icnt, &offset_expr, tempreg); + macro_build (&icnt, &offset_expr, "addiu", "t,r,j", tempreg, tempreg); + } + if (breg != 0) + macro_build (&icnt, NULL, "addu", "d,v,t", treg, tempreg, breg); + if (breg == treg) + break; + return; case M_LB_AB: - s = "lb"; - goto ld; + s = "lb"; + goto ld; case M_LBU_AB: - s = "lbu"; - goto ld; + s = "lbu"; + goto ld; case M_LH_AB: - s = "lh"; - goto ld; + s = "lh"; + goto ld; case M_LHU_AB: - s = "lhu"; - goto ld; + s = "lhu"; + goto ld; case M_LW_AB: - s = "lw"; - goto ld; + s = "lw"; + goto ld; case M_LWC0_AB: - s = "lwc0"; - goto ld; + s = "lwc0"; + goto ld; case M_LWC1_AB: - s = "lwc1"; - goto ld; + s = "lwc1"; + goto ld; case M_LWC2_AB: - s = "lwc2"; - goto ld; + s = "lwc2"; + goto ld; case M_LWC3_AB: - s = "lwc3"; - goto ld; + s = "lwc3"; + goto ld; case M_LWL_AB: - s = "lwl"; - goto ld; + s = "lwl"; + goto ld; case M_LWR_AB: - s = "lwr"; + s = "lwr"; ld: - if (breg == treg || mask == M_LWC1_AB) { - tempreg = AT; - used_at = 1; - } else { - tempreg = treg; - used_at = 0; - } - goto ld_st; + if (breg == treg || mask == M_LWC1_AB) + { + tempreg = AT; + used_at = 1; + } + else + { + tempreg = treg; + used_at = 0; + } + goto ld_st; case M_SB_AB: - s = "sb"; - goto st; + s = "sb"; + goto st; case M_SH_AB: - s = "sh"; - goto st; + s = "sh"; + goto st; case M_SW_AB: - s = "sw"; - goto st; + s = "sw"; + goto st; case M_SWC0_AB: - s = "swc0"; - goto st; + s = "swc0"; + goto st; case M_SWC1_AB: - s = "swc1"; - goto st; + s = "swc1"; + goto st; case M_SWC2_AB: - s = "swc2"; - goto st; + s = "swc2"; + goto st; case M_SWC3_AB: - s = "swc3"; - goto st; + s = "swc3"; + goto st; case M_SWL_AB: - s = "swl"; - goto st; + s = "swl"; + goto st; case M_SWR_AB: - s = "swr"; + s = "swr"; st: - tempreg = AT; - used_at = 1; + tempreg = AT; + used_at = 1; ld_st: - macro_build_lui(&icnt, &offset_expr, tempreg); - if (breg != 0) - macro_build(&icnt, NULL, "addu", "d,v,t", tempreg, tempreg, breg); - macro_build(&icnt, &offset_expr, s, - mask == M_LWC1_AB || mask == M_SWC1_AB ? "T,o(b)" : "t,o(b)", - treg, tempreg); - if (used_at) - break; - return; + if (mask == M_LWC1_AB || mask == M_SWC1_AB) + fmt = "T,o(b)"; + else + fmt = "t,o(b)"; + if (gp_reference (&offset_expr)) + { + if (breg == 0) + { + macro_build (&icnt, &offset_expr, s, fmt, treg, GP); + return; + } + macro_build (&icnt, (expressionS *) NULL, "addu", "d,v,t", + tempreg, breg, GP); + } + else + { + macro_build_lui (&icnt, &offset_expr, tempreg); + if (breg != 0) + macro_build (&icnt, NULL, "addu", "d,v,t", tempreg, tempreg, breg); + } + macro_build (&icnt, &offset_expr, s, fmt, treg, tempreg); + if (used_at) + break; + return; case M_LI: - load_register(&icnt, ip, treg, &imm_expr); - return; + load_register (&icnt, ip, treg, &imm_expr); + return; case M_LI_D: - /* + /* 0x400370
: lui $at,%hi(foo) 0x400374 : lw $v0,%lo(foo)($at) 0x400378 : lw $v1,%lo(foo+4)($at) @@ -1157,479 +1295,562 @@ macro (ip) : .float 3.133435 */ - macro_build_lui(&icnt, &offset_expr, AT); - macro_build(&icnt, &offset_expr, "lw", "t,o(b)", treg, AT); - offset_expr.X_add_number = 4; - macro_build(&icnt, &offset_expr, "lw", "t,o(b)", treg+1, AT); - break; + /* FIXME: I don't think this is used at present, because the 'F' + format character is not supported. When this is supported, + it should use the GP register. */ + macro_build_lui (&icnt, &offset_expr, AT); + macro_build (&icnt, &offset_expr, "lw", "t,o(b)", treg, AT); + offset_expr.X_add_number = 4; + macro_build (&icnt, &offset_expr, "lw", "t,o(b)", treg + 1, AT); + break; case M_LI_DD: - /* + /* 0x4003a0
: lwc1 $f0,-32752($gp) 0x4003a4 : lwc1 $f1,-32748($gp) 0x4003a8 : nop */ - sreg = (ip->insn_opcode >> 11) & 0x1f; /* Fs reg */ - macro_build(&icnt, &offset_expr, "lwc1", "T,o(b)", treg, AT); - offset_expr.X_add_number = 4; - macro_build(&icnt, &offset_expr, "lwc1", "T,o(b)", treg+1, AT); - break; + /* FIXME: This is nonsense. It isn't used anyhow. */ + sreg = (ip->insn_opcode >> 11) & 0x1f; /* Fs reg */ + macro_build (&icnt, &offset_expr, "lwc1", "T,o(b)", treg, AT); + offset_expr.X_add_number = 4; + macro_build (&icnt, &offset_expr, "lwc1", "T,o(b)", treg + 1, AT); + break; case M_L_DOB: - save_reorder_condition = mips_noreorder; - mips_noreorder = 1; - macro_build(&icnt, &offset_expr, "lwc1", "T,o(b)", treg, 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); - return; + save_reorder_condition = mips_noreorder; + mips_noreorder = 1; + macro_build (&icnt, &offset_expr, "lwc1", "T,o(b)", treg, 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); + return; case M_L_DAB: - /* - * The MIPS assembler seems to check for X_add_number not - * being double aligned and generating: - * lui at,%hi(foo+1) - * addu at,at,v1 - * addiu at,at,%lo(foo+1) - * lwc1 f2,0(at) - * lwc1 f3,4(at) - * But, the resulting address is the same after relocation so why - * generate the extra instruction? - */ - macro_build_lui(&icnt, &offset_expr, AT); - if (breg != 0) - macro_build(&icnt, NULL, "addu", "d,v,t", AT, AT, breg); - save_reorder_condition = mips_noreorder; - mips_noreorder = 1; - macro_build(&icnt, &offset_expr, "lwc1", "T,o(b)", treg, AT); - /* 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, AT); + /* + * The MIPS assembler seems to check for X_add_number not + * being double aligned and generating: + * lui at,%hi(foo+1) + * addu at,at,v1 + * addiu at,at,%lo(foo+1) + * lwc1 f2,0(at) + * lwc1 f3,4(at) + * But, the resulting address is the same after relocation so why + * generate the extra instruction? + */ + if (gp_reference (&offset_expr)) + { + if (breg == 0) + tempreg = GP; + else + { + macro_build (&icnt, &offset_expr, "addu", "d,v,t", AT, breg, GP); + tempreg = AT; + } + } + else + { + macro_build_lui (&icnt, &offset_expr, AT); + if (breg != 0) + macro_build (&icnt, NULL, "addu", "d,v,t", AT, AT, breg); + tempreg = AT; + } + save_reorder_condition = mips_noreorder; + mips_noreorder = 1; + macro_build (&icnt, &offset_expr, "lwc1", "T,o(b)", treg, 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); + if (tempreg == AT) break; + return; case M_LD_OB: - s = "lw"; - goto sd_ob; + s = "lw"; + goto sd_ob; case M_SD_OB: - s = "sw"; + s = "sw"; sd_ob: - macro_build(&icnt, &offset_expr, s, "t,o(b)", treg, breg); - offset_expr.X_add_number = 4; - macro_build(&icnt, &offset_expr, s, "t,o(b)", treg+1, breg); - return; + macro_build (&icnt, &offset_expr, s, "t,o(b)", treg, breg); + offset_expr.X_add_number = 4; + macro_build (&icnt, &offset_expr, s, "t,o(b)", treg + 1, breg); + return; case M_LD_AB: - s = "lw"; - if (breg == treg) { - tempreg = AT; - used_at = 1; - } else { - tempreg = treg; - used_at = 0; - } - goto sd_ab; + s = "lw"; + if (breg == treg) + { + tempreg = AT; + used_at = 1; + } + else + { + tempreg = treg; + used_at = 0; + } + goto sd_ab; case M_SD_AB: - s = "sw"; - tempreg = AT; - used_at = 1; + s = "sw"; + tempreg = AT; + used_at = 1; sd_ab: - macro_build_lui(&icnt, &offset_expr, tempreg); - if (breg != 0) - macro_build(&icnt, NULL, "addu", "d,v,t", tempreg, tempreg, breg); - macro_build(&icnt, &offset_expr, s, "t,o(b)", treg, tempreg); - offset_expr.X_add_number += 4; - macro_build(&icnt, &offset_expr, s, "t,o(b)", treg+1, tempreg); - if (used_at) - break; - return; + if (gp_reference (&offset_expr)) + { + if (breg == 0) + { + tempreg = GP; + used_at = 0; + } + else + macro_build (&icnt, (expressionS *) NULL, "addu", "d,v,t", + tempreg, breg, GP); + } + else + { + macro_build_lui (&icnt, &offset_expr, tempreg); + if (breg != 0) + macro_build (&icnt, NULL, "addu", "d,v,t", tempreg, tempreg, breg); + } + macro_build (&icnt, &offset_expr, s, "t,o(b)", treg, tempreg); + offset_expr.X_add_number += 4; + macro_build (&icnt, &offset_expr, s, "t,o(b)", treg + 1, tempreg); + if (used_at) + break; + return; case M_MUL: - macro_build(&icnt, NULL, "multu", "s,t", sreg, treg); - macro_build(&icnt, NULL, "mflo", "d", dreg); - /* two implicit nop's required for mflo */ - return; + macro_build (&icnt, NULL, "multu", "s,t", sreg, treg); + macro_build (&icnt, NULL, "mflo", "d", dreg); + /* two implicit nop's required for mflo */ + return; case M_MUL_I: - /* - * The mips assembler some times generates shifts and adds. - * Im not trying to be that fancy. GCC should do this for us - * anyway. - */ - load_register(&icnt, ip, AT, &imm_expr); - macro_build(&icnt, NULL, "mult", "s,t", sreg, AT); - macro_build(&icnt, NULL, "mflo", "d", dreg); - /* two implicit nop's required for mflo */ - break; + /* + * The mips assembler some times generates shifts and adds. + * Im not trying to be that fancy. GCC should do this for us + * anyway. + */ + load_register (&icnt, ip, AT, &imm_expr); + macro_build (&icnt, NULL, "mult", "s,t", sreg, AT); + macro_build (&icnt, NULL, "mflo", "d", dreg); + /* two implicit nop's required for mflo */ + break; case M_ROL: - macro_build(&icnt, NULL, "subu", "d,v,t", AT, 0, treg); - macro_build(&icnt, NULL, "srlv", "d,t,s", AT, sreg, AT); - macro_build(&icnt, NULL, "sllv", "d,t,s", dreg, sreg, treg); - macro_build(&icnt, NULL, "or", "d,v,t", dreg, dreg, AT); - break; + macro_build (&icnt, NULL, "subu", "d,v,t", AT, 0, treg); + macro_build (&icnt, NULL, "srlv", "d,t,s", AT, sreg, AT); + macro_build (&icnt, NULL, "sllv", "d,t,s", dreg, sreg, treg); + macro_build (&icnt, NULL, "or", "d,v,t", dreg, dreg, AT); + break; case M_ROL_I: - macro_build(&icnt, NULL, "sll", "d,w,<", AT, sreg, - imm_expr.X_add_number & 0x1f); - macro_build(&icnt, NULL, "srl", "d,w,<", dreg, sreg, - (0 - imm_expr.X_add_number) & 0x1f); - macro_build(&icnt, NULL, "or", "d,v,t", dreg, dreg, AT); - break; + macro_build (&icnt, NULL, "sll", "d,w,<", AT, sreg, + imm_expr.X_add_number & 0x1f); + macro_build (&icnt, NULL, "srl", "d,w,<", dreg, sreg, + (0 - imm_expr.X_add_number) & 0x1f); + macro_build (&icnt, NULL, "or", "d,v,t", dreg, dreg, AT); + break; case M_ROR: - macro_build(&icnt, NULL, "subu", "d,v,t", AT, 0, treg); - macro_build(&icnt, NULL, "sllv", "d,t,s", AT, sreg, AT); - macro_build(&icnt, NULL, "srlv", "d,t,s", dreg, sreg, treg); - macro_build(&icnt, NULL, "or", "d,v,t", dreg, dreg, AT); - break; + macro_build (&icnt, NULL, "subu", "d,v,t", AT, 0, treg); + macro_build (&icnt, NULL, "sllv", "d,t,s", AT, sreg, AT); + macro_build (&icnt, NULL, "srlv", "d,t,s", dreg, sreg, treg); + macro_build (&icnt, NULL, "or", "d,v,t", dreg, dreg, AT); + break; case M_ROR_I: - macro_build(&icnt, NULL, "srl", "d,w,<", AT, sreg, - imm_expr.X_add_number & 0x1f); - macro_build(&icnt, NULL, "sll", "d,w,<", dreg, sreg, - (0 - imm_expr.X_add_number) & 0x1f); - macro_build(&icnt, NULL, "or", "d,v,t", dreg, dreg, AT); - break; + macro_build (&icnt, NULL, "srl", "d,w,<", AT, sreg, + imm_expr.X_add_number & 0x1f); + macro_build (&icnt, NULL, "sll", "d,w,<", dreg, sreg, + (0 - imm_expr.X_add_number) & 0x1f); + macro_build (&icnt, NULL, "or", "d,v,t", dreg, dreg, AT); + break; case M_S_DOB: - macro_build(&icnt, &offset_expr, "swc1", "T,o(b)", treg, breg); - offset_expr.X_add_number += 4; - macro_build(&icnt, &offset_expr, "swc1", "T,o(b)", treg+1, breg); - return; + macro_build (&icnt, &offset_expr, "swc1", "T,o(b)", treg, breg); + offset_expr.X_add_number += 4; + macro_build (&icnt, &offset_expr, "swc1", "T,o(b)", treg + 1, breg); + return; case M_S_DAB: - macro_build_lui(&icnt, &offset_expr, AT); - if (breg != 0) - macro_build(&icnt, NULL, "addu", "d,v,t", AT, AT, breg); - macro_build(&icnt, &offset_expr, "swc1", "T,o(b)", treg, AT); - offset_expr.X_add_number += 4; - macro_build(&icnt, &offset_expr, "swc1", "T,o(b)", treg+1, AT); + if (gp_reference (&offset_expr)) + { + if (breg == 0) + tempreg = GP; + else + { + macro_build (&icnt, (expressionS *) NULL, "addu", "d,v,t", + AT, breg, GP); + tempreg = AT; + } + } + else + { + macro_build_lui (&icnt, &offset_expr, AT); + if (breg != 0) + macro_build (&icnt, NULL, "addu", "d,v,t", AT, AT, breg); + tempreg = AT; + } + macro_build (&icnt, &offset_expr, "swc1", "T,o(b)", treg, tempreg); + offset_expr.X_add_number += 4; + macro_build (&icnt, &offset_expr, "swc1", "T,o(b)", treg + 1, tempreg); + if (tempreg == AT) break; + return; case M_SEQ: - if (sreg == 0) - macro_build(&icnt, &expr1, "sltiu", "t,r,j", dreg, treg); - else if (treg == 0) - macro_build(&icnt, &expr1, "sltiu", "t,r,j", dreg, sreg); - else { - macro_build(&icnt, NULL, "xor", "d,v,t", dreg, sreg, treg); - macro_build(&icnt, &expr1, "sltiu", "t,r,j", dreg, dreg); + if (sreg == 0) + macro_build (&icnt, &expr1, "sltiu", "t,r,j", dreg, treg); + else if (treg == 0) + macro_build (&icnt, &expr1, "sltiu", "t,r,j", dreg, sreg); + else + { + macro_build (&icnt, NULL, "xor", "d,v,t", dreg, sreg, treg); + macro_build (&icnt, &expr1, "sltiu", "t,r,j", dreg, dreg); } - return; + return; case M_SEQ_I: - if (imm_expr.X_add_number == 0) { - macro_build(&icnt, &expr1, "sltiu", "t,r,j", dreg, sreg); - return; + if (imm_expr.X_add_number == 0) + { + macro_build (&icnt, &expr1, "sltiu", "t,r,j", dreg, sreg); + return; } - if (sreg == 0) { - /* result is always false */ - macro_build(&icnt, NULL, "move", "d,s", dreg, 0); - return; + if (sreg == 0) + { + /* result is always false */ + macro_build (&icnt, NULL, "move", "d,s", dreg, 0); + return; } - switch (imm_expr.X_add_number & 0xffff8000) { + switch (imm_expr.X_add_number & 0xffff8000) + { case 0: case 0x8000: - macro_build(&icnt, &imm_expr, "xori", "t,r,i", dreg, sreg); - used_at = 0; - break; + macro_build (&icnt, &imm_expr, "xori", "t,r,i", dreg, sreg); + used_at = 0; + break; case 0xffff8000: - if (imm_expr.X_add_number != -32768) { - imm_expr.X_add_number = -imm_expr.X_add_number; - macro_build(&icnt, &imm_expr, "addiu", "t,r,j", dreg, sreg); - used_at = 0; - break; + if (imm_expr.X_add_number != -32768) + { + imm_expr.X_add_number = -imm_expr.X_add_number; + macro_build (&icnt, &imm_expr, "addiu", "t,r,j", dreg, sreg); + used_at = 0; + break; } - /* FALLTHROUGH */ + /* FALLTHROUGH */ default: - macro_build_lui(&icnt, &imm_expr, AT); - if (imm_expr.X_add_number & 0xffff) - macro_build(&icnt, &imm_expr, "addiu", "t,r,j", AT, AT); - macro_build(&icnt, NULL, "xor", "d,v,t", dreg, sreg, AT); - used_at = 1; - } - macro_build(&icnt, &expr1, "sltiu", "t,r,j", dreg, dreg); - if (used_at) - break; - return; + macro_build_lui (&icnt, &imm_expr, AT); + if (imm_expr.X_add_number & 0xffff) + macro_build (&icnt, &imm_expr, "addiu", "t,r,j", AT, AT); + macro_build (&icnt, NULL, "xor", "d,v,t", dreg, sreg, AT); + used_at = 1; + } + macro_build (&icnt, &expr1, "sltiu", "t,r,j", dreg, dreg); + if (used_at) + break; + return; case M_SGE: /* sreg >= treg <==> not (sreg < treg) */ - s = "slt"; - goto sge; + s = "slt"; + goto sge; case M_SGEU: - s = "sltu"; + s = "sltu"; sge: - macro_build(&icnt, NULL, s, "d,v,t", dreg, sreg, treg); - macro_build(&icnt, &expr1, "xori", "t,r,i", dreg, dreg); - return; + macro_build (&icnt, NULL, s, "d,v,t", dreg, sreg, treg); + macro_build (&icnt, &expr1, "xori", "t,r,i", dreg, dreg); + return; - case M_SGE_I: /* sreg >= I <==> not (sreg < I) */ + case M_SGE_I: /* sreg >= I <==> not (sreg < I) */ case M_SGEU_I: - if (imm_expr.X_add_number < 32768 && imm_expr.X_add_number > -32769) { - macro_build(&icnt, &expr1, - mask == M_SGE_I ? "slti" : "sltiu", "t,r,j", dreg, sreg); - used_at = 0; - } else { - load_register(&icnt, ip, AT, &imm_expr); - macro_build(&icnt, NULL, - mask == M_SGE_I ? "slt" : "sltu", "d,v,t", dreg, sreg, AT); - used_at = 1; - } - macro_build(&icnt, &expr1, "xori", "t,r,i", dreg, dreg); - if (used_at) - break; - return; + if (imm_expr.X_add_number < 32768 && imm_expr.X_add_number > -32769) + { + macro_build (&icnt, &expr1, + mask == M_SGE_I ? "slti" : "sltiu", "t,r,j", dreg, sreg); + used_at = 0; + } + else + { + load_register (&icnt, ip, AT, &imm_expr); + macro_build (&icnt, NULL, + mask == M_SGE_I ? "slt" : "sltu", "d,v,t", dreg, sreg, AT); + used_at = 1; + } + macro_build (&icnt, &expr1, "xori", "t,r,i", dreg, dreg); + if (used_at) + break; + return; case M_SGT: /* sreg > treg <==> treg < sreg */ - s = "slt"; - goto sgt; + s = "slt"; + goto sgt; case M_SGTU: - s = "sltu"; + s = "sltu"; sgt: - macro_build(&icnt, NULL, s, "d,v,t", dreg, treg, sreg); - return; + macro_build (&icnt, NULL, s, "d,v,t", dreg, treg, sreg); + return; - case M_SGT_I: /* sreg > I <==> I < sreg */ - s = "slt"; - goto sgti; + case M_SGT_I: /* sreg > I <==> I < sreg */ + s = "slt"; + goto sgti; case M_SGTU_I: - s = "sltu"; + s = "sltu"; sgti: - load_register(&icnt, ip, AT, &imm_expr); - macro_build(&icnt, NULL, s, "d,v,t", dreg, AT, sreg); - break; + load_register (&icnt, ip, AT, &imm_expr); + macro_build (&icnt, NULL, s, "d,v,t", dreg, AT, sreg); + break; - case M_SLE: /* sreg <= treg <==> treg >= sreg <==> not (treg < sreg) */ - s = "slt"; - goto sle; + case M_SLE: /* sreg <= treg <==> treg >= sreg <==> not (treg < sreg) */ + s = "slt"; + goto sle; case M_SLEU: - s = "sltu"; + 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); - return; + macro_build (&icnt, NULL, s, "d,v,t", dreg, treg, sreg); + macro_build (&icnt, &imm_expr, "xori", "t,r,i", dreg, dreg); + return; - case M_SLE_I: /* sreg <= I <==> I >= sreg <==> not (I < sreg) */ - s = "slt"; - goto slei; + case M_SLE_I: /* sreg <= I <==> I >= sreg <==> not (I < sreg) */ + s = "slt"; + goto slei; case M_SLEU_I: - s = "sltu"; + s = "sltu"; 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); - break; + 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); + break; case M_SLT_I: - if (imm_expr.X_add_number < 32768 && imm_expr.X_add_number > -32769) { - macro_build(&icnt, &imm_expr, "slti", "t,r,j", dreg, sreg); - return; + if (imm_expr.X_add_number < 32768 && imm_expr.X_add_number > -32769) + { + macro_build (&icnt, &imm_expr, "slti", "t,r,j", dreg, sreg); + return; } - load_register(&icnt, ip, AT, &imm_expr); - macro_build(&icnt, NULL, "slt", "d,v,t", dreg, sreg, AT); - break; + load_register (&icnt, ip, AT, &imm_expr); + macro_build (&icnt, NULL, "slt", "d,v,t", dreg, sreg, AT); + break; case M_SLTU_I: - if (imm_expr.X_add_number < 32768 && imm_expr.X_add_number > -32769) { - macro_build(&icnt, &imm_expr, "sltiu", "t,r,j", dreg, sreg); - return; + if (imm_expr.X_add_number < 32768 && imm_expr.X_add_number > -32769) + { + macro_build (&icnt, &imm_expr, "sltiu", "t,r,j", dreg, sreg); + return; } - load_register(&icnt, ip, AT, &imm_expr); - macro_build(&icnt, NULL, "sltu", "d,v,t", dreg, sreg, AT); - break; + load_register (&icnt, ip, AT, &imm_expr); + macro_build (&icnt, NULL, "sltu", "d,v,t", dreg, sreg, AT); + break; case M_SNE: - if (sreg == 0) - macro_build(&icnt, NULL, "sltu", "d,v,t", dreg, 0, treg); - else if (treg == 0) - macro_build(&icnt, NULL, "sltu", "d,v,t", dreg, 0, sreg); - else { - macro_build(&icnt, NULL, "xor", "d,v,t", dreg, sreg, treg); - macro_build(&icnt, NULL, "sltu", "d,v,t", dreg, 0, dreg); + if (sreg == 0) + macro_build (&icnt, NULL, "sltu", "d,v,t", dreg, 0, treg); + else if (treg == 0) + macro_build (&icnt, NULL, "sltu", "d,v,t", dreg, 0, sreg); + else + { + macro_build (&icnt, NULL, "xor", "d,v,t", dreg, sreg, treg); + macro_build (&icnt, NULL, "sltu", "d,v,t", dreg, 0, dreg); } - return; + return; case M_SNE_I: - if (imm_expr.X_add_number == 0) { - macro_build(&icnt, NULL, "sltu", "d,v,t", dreg, 0, sreg); - return; + if (imm_expr.X_add_number == 0) + { + macro_build (&icnt, NULL, "sltu", "d,v,t", dreg, 0, sreg); + return; } - if (sreg == 0) { - /* result is always true */ - macro_build(&icnt, &expr1, "addiu", "t,r,j", dreg, 0); - return; + if (sreg == 0) + { + /* result is always true */ + macro_build (&icnt, &expr1, "addiu", "t,r,j", dreg, 0); + return; } - switch (imm_expr.X_add_number & 0xffff8000) { + switch (imm_expr.X_add_number & 0xffff8000) + { case 0: case 0x8000: - macro_build(&icnt, &imm_expr, "xori", "t,r,i", dreg, sreg); - used_at = 0; - break; + macro_build (&icnt, &imm_expr, "xori", "t,r,i", dreg, sreg); + used_at = 0; + break; case 0xffff8000: - if (imm_expr.X_add_number != -32768) { - imm_expr.X_add_number = -imm_expr.X_add_number; - macro_build(&icnt, &imm_expr, "addiu", "t,r,j", dreg, sreg); - used_at = 0; - break; + if (imm_expr.X_add_number != -32768) + { + imm_expr.X_add_number = -imm_expr.X_add_number; + macro_build (&icnt, &imm_expr, "addiu", "t,r,j", dreg, sreg); + used_at = 0; + break; } - /* FALLTHROUGH */ + /* FALLTHROUGH */ default: - macro_build_lui(&icnt, &imm_expr, AT); - if (imm_expr.X_add_number & 0xffff) - macro_build(&icnt, &imm_expr, "addiu", "t,r,j", AT, AT); - macro_build(&icnt, NULL, "xor", "d,v,t", dreg, sreg, AT); - used_at = 1; - } - macro_build(&icnt, NULL, "sltu", "d,v,t", dreg, 0, dreg); - if (used_at) - break; - return; + macro_build_lui (&icnt, &imm_expr, AT); + if (imm_expr.X_add_number & 0xffff) + macro_build (&icnt, &imm_expr, "addiu", "t,r,j", AT, AT); + macro_build (&icnt, NULL, "xor", "d,v,t", dreg, sreg, AT); + used_at = 1; + } + macro_build (&icnt, NULL, "sltu", "d,v,t", dreg, 0, dreg); + if (used_at) + break; + return; case M_SUB_I: - if (imm_expr.X_add_number < 32768 && imm_expr.X_add_number > -32768) { - imm_expr.X_add_number = -imm_expr.X_add_number; - macro_build(&icnt, &imm_expr, "addi", "t,r,j", dreg, sreg); - return; + if (imm_expr.X_add_number < 32768 && imm_expr.X_add_number > -32768) + { + imm_expr.X_add_number = -imm_expr.X_add_number; + macro_build (&icnt, &imm_expr, "addi", "t,r,j", dreg, sreg); + return; } - load_register(&icnt, ip, AT, &imm_expr); - macro_build(&icnt, NULL, "sub", "d,v,t", dreg, sreg, AT); - break; + load_register (&icnt, ip, AT, &imm_expr); + macro_build (&icnt, NULL, "sub", "d,v,t", dreg, sreg, AT); + break; case M_SUBU_I: - if (imm_expr.X_add_number < 32768 && imm_expr.X_add_number > -32768) { - imm_expr.X_add_number = -imm_expr.X_add_number; - macro_build(&icnt, &imm_expr, "addiu", "t,r,j", dreg, sreg); - return; + if (imm_expr.X_add_number < 32768 && imm_expr.X_add_number > -32768) + { + imm_expr.X_add_number = -imm_expr.X_add_number; + macro_build (&icnt, &imm_expr, "addiu", "t,r,j", dreg, sreg); + return; } - load_register(&icnt, ip, AT, &imm_expr); - macro_build(&icnt, NULL, "subu", "d,v,t", dreg, sreg, AT); - break; + load_register (&icnt, ip, AT, &imm_expr); + macro_build (&icnt, NULL, "subu", "d,v,t", dreg, sreg, AT); + break; case M_TRUNCWD: case M_TRUNCWS: - sreg = (ip->insn_opcode >> 11) & 0x1f; /* floating reg */ - dreg = (ip->insn_opcode >> 06) & 0x1f; /* floating reg */ - - /* - * Is the double cfc1 instruction a bug in the mips assembler; - * or is there a reason for it? - */ - save_reorder_condition = mips_noreorder; - mips_noreorder = 1; - macro_build(&icnt, NULL, "cfc1", "t,d", treg, 31); - macro_build(&icnt, NULL, "cfc1", "t,d", treg, 31); - macro_build(&icnt, NULL, "nop", ""); - expr1.X_add_number = 3; - macro_build(&icnt, &expr1, "ori", "t,r,i", AT, treg); - expr1.X_add_number = 2; - macro_build(&icnt, &expr1, "xori", "t,r,i", AT, AT); - macro_build(&icnt, NULL, "ctc1", "t,d", AT, 31); - macro_build(&icnt, NULL, "nop", ""); - macro_build(&icnt, NULL, - mask == M_TRUNCWD ? "cvt.w.d" : "cvt.w.s", "D,S", dreg, sreg); - macro_build(&icnt, NULL, "ctc1", "t,d", treg, 31); - macro_build(&icnt, NULL, "nop", ""); - mips_noreorder = save_reorder_condition; - break; + sreg = (ip->insn_opcode >> 11) & 0x1f; /* floating reg */ + dreg = (ip->insn_opcode >> 06) & 0x1f; /* floating reg */ + + /* + * Is the double cfc1 instruction a bug in the mips assembler; + * or is there a reason for it? + */ + save_reorder_condition = mips_noreorder; + mips_noreorder = 1; + macro_build (&icnt, NULL, "cfc1", "t,d", treg, 31); + macro_build (&icnt, NULL, "cfc1", "t,d", treg, 31); + macro_build (&icnt, NULL, "nop", ""); + expr1.X_add_number = 3; + macro_build (&icnt, &expr1, "ori", "t,r,i", AT, treg); + expr1.X_add_number = 2; + macro_build (&icnt, &expr1, "xori", "t,r,i", AT, AT); + macro_build (&icnt, NULL, "ctc1", "t,d", AT, 31); + macro_build (&icnt, NULL, "nop", ""); + macro_build (&icnt, NULL, + mask == M_TRUNCWD ? "cvt.w.d" : "cvt.w.s", "D,S", dreg, sreg); + macro_build (&icnt, NULL, "ctc1", "t,d", treg, 31); + macro_build (&icnt, NULL, "nop", ""); + mips_noreorder = save_reorder_condition; + break; case M_ULH: - s = "lb"; - goto ulh; + s = "lb"; + goto ulh; case M_ULHU: - s = "lbu"; + s = "lbu"; ulh: - /* avoid load delay */ - offset_expr.X_add_number += 1; - macro_build(&icnt, &offset_expr, s, "t,o(b)", treg, breg); - offset_expr.X_add_number -= 1; - macro_build(&icnt, &offset_expr, "lbu", "t,o(b)", AT, breg); - macro_build(&icnt, NULL, "sll", "d,w,<", treg, treg, 8); - macro_build(&icnt,NULL, "or", "d,v,t", treg, treg, AT); - break; + /* avoid load delay */ + offset_expr.X_add_number += 1; + macro_build (&icnt, &offset_expr, s, "t,o(b)", treg, breg); + offset_expr.X_add_number -= 1; + macro_build (&icnt, &offset_expr, "lbu", "t,o(b)", AT, breg); + macro_build (&icnt, NULL, "sll", "d,w,<", treg, treg, 8); + macro_build (&icnt, NULL, "or", "d,v,t", treg, treg, AT); + break; case M_ULW: - /* does this work on a big endian machine? */ - offset_expr.X_add_number += 3; - macro_build(&icnt, &offset_expr, "lwl", "t,o(b)", treg, breg); - offset_expr.X_add_number -= 3; - macro_build(&icnt, &offset_expr, "lwr", "t,o(b)", treg, breg); - return; + /* does this work on a big endian machine? */ + offset_expr.X_add_number += 3; + macro_build (&icnt, &offset_expr, "lwl", "t,o(b)", treg, breg); + offset_expr.X_add_number -= 3; + macro_build (&icnt, &offset_expr, "lwr", "t,o(b)", treg, breg); + return; case M_ULH_A: case M_ULHU_A: case M_ULW_A: - if (offset_expr.X_seg == &bfd_abs_section) - load_register(&icnt, ip, AT, &offset_expr); - else { - macro_build_lui(&icnt, &offset_expr, AT); - macro_build(&icnt, &offset_expr, "addiu", "t,r,j", AT, AT); - } - if (mask == M_ULW_A) { - expr1.X_add_number = 3; - macro_build(&icnt, &expr1, "lwl", "t,o(b)", treg, AT); - imm_expr.X_add_number = 0; - macro_build(&icnt, &expr1, "lwr", "t,o(b)", treg, AT); - } else { - macro_build(&icnt, &expr1, - mask == M_ULH_A ? "lb" : "lbu", "t,o(b)", treg, AT); - imm_expr.X_add_number = 0; - macro_build(&icnt, &expr1, "lbu", "t,o(b)", AT, AT); - macro_build(&icnt, NULL, "sll", "d,w,<", treg, treg, 8); - macro_build(&icnt, NULL, "or", "d,v,t", treg, treg, AT); + if (offset_expr.X_seg == &bfd_abs_section) + load_register (&icnt, ip, AT, &offset_expr); + else if (gp_reference (&offset_expr)) + macro_build (&icnt, &offset_expr, "addiu", "t,r,j", AT, GP); + else + { + macro_build_lui (&icnt, &offset_expr, AT); + macro_build (&icnt, &offset_expr, "addiu", "t,r,j", AT, AT); } - break; + if (mask == M_ULW_A) + { + expr1.X_add_number = 3; + macro_build (&icnt, &expr1, "lwl", "t,o(b)", treg, AT); + imm_expr.X_add_number = 0; + macro_build (&icnt, &expr1, "lwr", "t,o(b)", treg, AT); + } + else + { + macro_build (&icnt, &expr1, + mask == M_ULH_A ? "lb" : "lbu", "t,o(b)", treg, AT); + imm_expr.X_add_number = 0; + macro_build (&icnt, &expr1, "lbu", "t,o(b)", AT, AT); + macro_build (&icnt, NULL, "sll", "d,w,<", treg, treg, 8); + macro_build (&icnt, NULL, "or", "d,v,t", treg, treg, AT); + } + break; case M_USH: - macro_build(&icnt, &offset_expr, "sb", "t,o(b)", treg, breg); - macro_build(&icnt, NULL, "srl", "d,w,<", AT, treg, 8); - offset_expr.X_add_number += 1; - macro_build(&icnt, &offset_expr, "sb", "t,o(b)", AT, breg); - break; + macro_build (&icnt, &offset_expr, "sb", "t,o(b)", treg, breg); + macro_build (&icnt, NULL, "srl", "d,w,<", AT, treg, 8); + offset_expr.X_add_number += 1; + macro_build (&icnt, &offset_expr, "sb", "t,o(b)", AT, breg); + break; case M_USW: - offset_expr.X_add_number += 3; - macro_build(&icnt, &offset_expr, "swl", "t,o(b)", treg, breg); - offset_expr.X_add_number -= 3; - macro_build(&icnt, &offset_expr, "swr", "t,o(b)", treg, breg); - return; + offset_expr.X_add_number += 3; + macro_build (&icnt, &offset_expr, "swl", "t,o(b)", treg, breg); + offset_expr.X_add_number -= 3; + macro_build (&icnt, &offset_expr, "swr", "t,o(b)", treg, breg); + return; case M_USH_A: case M_USW_A: - if (offset_expr.X_seg == &bfd_abs_section) - load_register(&icnt, ip, AT, &offset_expr); - else { - macro_build_lui(&icnt, &offset_expr, AT); - macro_build(&icnt, &offset_expr, "addiu", "t,r,j", AT, AT); - } - if (mask == M_USW_A) { - expr1.X_add_number = 3; - macro_build(&icnt, &expr1, "swl", "t,o(b)", treg, AT); - expr1.X_add_number = 0; - macro_build(&icnt, &expr1, "swr", "t,o(b)", treg, AT); - } else { - expr1.X_add_number = 0; - macro_build(&icnt, &expr1, "sb", "t,o(b)", treg, AT); - macro_build(&icnt, NULL, "srl", "d,w,<", treg, treg, 8); - expr1.X_add_number = 1; - macro_build(&icnt, &expr1, "sb", "t,o(b)", treg, AT); - expr1.X_add_number = 0; - macro_build(&icnt, &expr1, "lbu", "t,o(b)", AT, AT); - macro_build(&icnt, NULL, "sll", "d,w,<", treg, treg, 8); - macro_build(&icnt, NULL, "or", "d,v,t", treg, treg, AT); + if (offset_expr.X_seg == &bfd_abs_section) + load_register (&icnt, ip, AT, &offset_expr); + else if (gp_reference (&offset_expr)) + macro_build (&icnt, &offset_expr, "addiu", "t,r,j", AT, GP); + else + { + macro_build_lui (&icnt, &offset_expr, AT); + macro_build (&icnt, &offset_expr, "addiu", "t,r,j", AT, AT); } - break; + if (mask == M_USW_A) + { + expr1.X_add_number = 3; + macro_build (&icnt, &expr1, "swl", "t,o(b)", treg, AT); + expr1.X_add_number = 0; + macro_build (&icnt, &expr1, "swr", "t,o(b)", treg, AT); + } + else + { + expr1.X_add_number = 0; + macro_build (&icnt, &expr1, "sb", "t,o(b)", treg, AT); + macro_build (&icnt, NULL, "srl", "d,w,<", treg, treg, 8); + expr1.X_add_number = 1; + macro_build (&icnt, &expr1, "sb", "t,o(b)", treg, AT); + expr1.X_add_number = 0; + macro_build (&icnt, &expr1, "lbu", "t,o(b)", AT, AT); + macro_build (&icnt, NULL, "sll", "d,w,<", treg, treg, 8); + macro_build (&icnt, NULL, "or", "d,v,t", treg, treg, AT); + } + break; default: - as_bad("Macro %s not implemented yet", ip->insn_mo->name); + as_bad ("Macro %s not implemented yet", ip->insn_mo->name); } - if (mips_noat) - as_warn("Macro used $at after \".set noat\""); + if (mips_noat) + as_warn ("Macro used $at after \".set noat\""); } @@ -1643,362 +1864,400 @@ mips_ip (str, ip) char *str; struct mips_cl_insn *ip; { - char *s; - const char *args; - char c; - struct mips_opcode *insn; - char *argsStart; - unsigned int regno; - unsigned int lastregno = 0; - char *s_reset; - - insn_error = NULL; - - for (s = str; islower(*s) || (*s >= '0' && *s <= '3') || *s == '.'; ++s) - continue; - switch (*s) { - + char *s; + const char *args; + char c; + struct mips_opcode *insn; + char *argsStart; + unsigned int regno; + unsigned int lastregno = 0; + char *s_reset; + + insn_error = NULL; + + for (s = str; islower (*s) || (*s >= '0' && *s <= '3') || *s == '.'; ++s) + continue; + switch (*s) + { case '\0': - break; + break; case ' ': - *s++ = '\0'; - break; + *s++ = '\0'; + break; default: - as_warn("Unknown opcode: `%s'", str); - exit(1); + as_warn ("Unknown opcode: `%s'", str); + exit (1); } - if ((insn = (struct mips_opcode *) hash_find(op_hash, str)) == NULL) { - as_warn("`%s' not in hash table.", str); - insn_error = "ERROR: Unrecognized opcode"; - return; + if ((insn = (struct mips_opcode *) hash_find (op_hash, str)) == NULL) + { + as_warn ("`%s' not in hash table.", str); + insn_error = "ERROR: Unrecognized opcode"; + return; } - argsStart = s; - for (;;) { - assert(strcmp(insn->name, str) == 0); - ip->insn_mo = insn; - ip->insn_opcode = insn->match; - for (args = insn->args; ; ++args) { - if (*s == ' ') - ++s; - switch (*args) { - - case '\0': /* end of args */ - if (*s == '\0') - return; - break; + argsStart = s; + for (;;) + { + assert (strcmp (insn->name, str) == 0); + ip->insn_mo = insn; + ip->insn_opcode = insn->match; + for (args = insn->args;; ++args) + { + if (*s == ' ') + ++s; + switch (*args) + { + case '\0': /* end of args */ + if (*s == '\0') + return; + break; case ',': - if (*s++ == *args) - continue; - s--; - switch (*++args) { + if (*s++ == *args) + continue; + s--; + switch (*++args) + { case 'r': case 'v': - ip->insn_opcode |= lastregno << 21; - continue; + ip->insn_opcode |= lastregno << 21; + continue; case 'w': case 'W': - ip->insn_opcode |= lastregno << 16; - continue; + ip->insn_opcode |= lastregno << 16; + continue; case 'V': - ip->insn_opcode |= lastregno << 11; - continue; + ip->insn_opcode |= lastregno << 11; + continue; } - break; + break; case '(': - /* handle optional base register. - Either the base register is omitted or - we must have a left paren. */ - /* this is dependent on the next operand specifier - is a 'b' for base register */ - assert(args[1] == 'b'); - if (*s == '\0') - return; - - case ')': /* these must match exactly */ - if (*s++ == *args) - continue; - break; - - case '<': /* must be at least one digit */ - /* - * According to the manual, if the shift amount is greater - * than 31 or less than 0 the the shift amount should be - * mod 32. In reality the mips assembler issues an error. - * We issue a warning and do the mod. - */ - my_getExpression(&imm_expr, s); - check_absolute_expr(ip, &imm_expr); - if ((unsigned long) imm_expr.X_add_number > 31) { - as_warn("Improper shift amount (%d)", - imm_expr.X_add_number); - imm_expr.X_add_number = imm_expr.X_add_number % 32; - } - ip->insn_opcode |= imm_expr.X_add_number << 6; - imm_expr.X_seg = absent_section; - s = expr_end; - continue; + /* handle optional base register. + Either the base register is omitted or + we must have a left paren. */ + /* this is dependent on the next operand specifier + is a 'b' for base register */ + assert (args[1] == 'b'); + if (*s == '\0') + return; - case 'c': /* break code */ - my_getExpression(&imm_expr, s); - check_absolute_expr(ip, &imm_expr); - if ((unsigned)imm_expr.X_add_number > 1023) - as_warn("Illegal break code (%d)", imm_expr.X_add_number); - ip->insn_opcode |= imm_expr.X_add_number << 16; - imm_expr.X_seg = absent_section; - s = expr_end; + case ')': /* these must match exactly */ + if (*s++ == *args) continue; - - case 'b': /* base register */ - case 'd': /* destination register */ - case 's': /* source register */ - case 't': /* target register */ - case 'r': /* both target and source */ - case 'v': /* both dest and source */ - case 'w': /* both dest and target */ - s_reset = s; - if (s[0] == '$') { - if (isdigit(s[1])) { - ++s; - regno = 0; - do { - regno *= 10; - regno += *s - '0'; - ++s; - } while (isdigit(*s)); - } else if (s[1] == 'f' && s[2] == 'p') { - s += 3; - regno = 30; - } else if (s[1] == 's' && s[2] == 'p') { - s += 3; - regno = 29; - } else if (s[1] == 'g' && s[2] == 'p') { - s += 3; - regno = 28; - } else if (s[1] == 'a' && s[2] == 't') { - s += 3; - regno = 1; - } else - goto notreg; - if (regno > 31) - as_bad("Invalid register number (%d)", regno); - if (regno == AT && !mips_noat) - as_warn("Used $at without \".set noat\""); - c = *args; - if (*s == ' ') - s++; - if (args[1] != *s) { - if (c == 'r' || c == 'v' || c == 'w') { - regno = lastregno; - s = s_reset; - args++; - } + break; + + case '<': /* must be at least one digit */ + /* + * According to the manual, if the shift amount is greater + * than 31 or less than 0 the the shift amount should be + * mod 32. In reality the mips assembler issues an error. + * We issue a warning and do the mod. + */ + my_getExpression (&imm_expr, s); + check_absolute_expr (ip, &imm_expr); + if ((unsigned long) imm_expr.X_add_number > 31) + { + as_warn ("Improper shift amount (%d)", + imm_expr.X_add_number); + imm_expr.X_add_number = imm_expr.X_add_number % 32; + } + ip->insn_opcode |= imm_expr.X_add_number << 6; + imm_expr.X_seg = absent_section; + s = expr_end; + continue; + + case 'c': /* break code */ + my_getExpression (&imm_expr, s); + check_absolute_expr (ip, &imm_expr); + if ((unsigned) imm_expr.X_add_number > 1023) + as_warn ("Illegal break code (%d)", imm_expr.X_add_number); + ip->insn_opcode |= imm_expr.X_add_number << 16; + imm_expr.X_seg = absent_section; + s = expr_end; + continue; + + case 'b': /* base register */ + case 'd': /* destination register */ + case 's': /* source register */ + case 't': /* target register */ + case 'r': /* both target and source */ + case 'v': /* both dest and source */ + case 'w': /* both dest and target */ + s_reset = s; + if (s[0] == '$') + { + if (isdigit (s[1])) + { + ++s; + regno = 0; + do + { + regno *= 10; + regno += *s - '0'; + ++s; + } + while (isdigit (*s)); + } + else if (s[1] == 'f' && s[2] == 'p') + { + s += 3; + regno = 30; + } + else if (s[1] == 's' && s[2] == 'p') + { + s += 3; + regno = 29; + } + else if (s[1] == 'g' && s[2] == 'p') + { + s += 3; + regno = 28; } - switch (c) { + else if (s[1] == 'a' && s[2] == 't') + { + s += 3; + regno = 1; + } + else + goto notreg; + if (regno > 31) + as_bad ("Invalid register number (%d)", regno); + if (regno == AT && !mips_noat) + as_warn ("Used $at without \".set noat\""); + c = *args; + if (*s == ' ') + s++; + if (args[1] != *s) + { + if (c == 'r' || c == 'v' || c == 'w') + { + regno = lastregno; + s = s_reset; + args++; + } + } + switch (c) + { case 'r': case 's': case 'v': case 'b': - ip->insn_opcode |= regno << 21; - break; + ip->insn_opcode |= regno << 21; + break; case 'd': - ip->insn_opcode |= regno << 11; - break; + ip->insn_opcode |= regno << 11; + break; case 'w': case 't': - ip->insn_opcode |= regno << 16; + ip->insn_opcode |= regno << 16; } - lastregno = regno; - continue; + lastregno = regno; + continue; } notreg: - switch (*args++) { + switch (*args++) + { case 'r': case 'v': - ip->insn_opcode |= lastregno << 21; - continue; + ip->insn_opcode |= lastregno << 21; + continue; case 'w': - ip->insn_opcode |= lastregno << 16; - continue; + ip->insn_opcode |= lastregno << 16; + continue; } - break; + break; - case 'D': /* floating point destination register */ - case 'S': /* floating point source register */ - case 'T': /* floating point target register */ + case 'D': /* floating point destination register */ + case 'S': /* floating point source register */ + case 'T': /* floating point target register */ case 'V': case 'W': - s_reset = s; - if (s[0] == '$' && s[1] == 'f' && isdigit(s[2])) { - s += 2; - regno = 0; - do { - regno *= 10; - regno += *s - '0'; - ++s; - } while (isdigit(*s)); - - if (regno > 31) - as_bad("Invalid float register number (%d)", regno); - - if ((regno & 1) && - !(strcmp(str, "mtc1") == 0 || - strcmp(str, "mfc1") == 0 || - strcmp(str, "lwc1") == 0 || - strcmp(str, "swc1") == 0)) - as_warn("Float register should be even, was %d", - regno); - - c = *args; - if (*s == ' ') - s++; - if (args[1] != *s) { - if (c == 'V' || c == 'W') { - regno = lastregno; - s = s_reset; - args++; + s_reset = s; + if (s[0] == '$' && s[1] == 'f' && isdigit (s[2])) + { + s += 2; + regno = 0; + do + { + regno *= 10; + regno += *s - '0'; + ++s; + } + while (isdigit (*s)); + + if (regno > 31) + as_bad ("Invalid float register number (%d)", regno); + + if ((regno & 1) && + !(strcmp (str, "mtc1") == 0 || + strcmp (str, "mfc1") == 0 || + strcmp (str, "lwc1") == 0 || + strcmp (str, "swc1") == 0)) + as_warn ("Float register should be even, was %d", + regno); + + c = *args; + if (*s == ' ') + s++; + if (args[1] != *s) + { + if (c == 'V' || c == 'W') + { + regno = lastregno; + s = s_reset; + args++; } } - switch (c) { + switch (c) + { case 'D': - ip->insn_opcode |= regno << 6; - break; + ip->insn_opcode |= regno << 6; + break; case 'V': case 'S': - ip->insn_opcode |= regno << 11; - break; + ip->insn_opcode |= regno << 11; + break; case 'W': case 'T': - ip->insn_opcode |= regno << 16; + ip->insn_opcode |= regno << 16; } - lastregno = regno; - continue; + lastregno = regno; + continue; } - switch (*args++) { + switch (*args++) + { case 'V': - ip->insn_opcode |= lastregno << 11; - continue; + ip->insn_opcode |= lastregno << 11; + continue; case 'W': - ip->insn_opcode |= lastregno << 16; - continue; + ip->insn_opcode |= lastregno << 16; + continue; } - break; + break; case 'I': - my_getExpression(&imm_expr, s); - check_absolute_expr(ip, &imm_expr); - s = expr_end; - continue; + my_getExpression (&imm_expr, s); + check_absolute_expr (ip, &imm_expr); + s = expr_end; + continue; case 'A': - my_getExpression(&offset_expr, s); - imm_reloc = BFD_RELOC_32; - s = expr_end; - continue; + my_getExpression (&offset_expr, s); + imm_reloc = BFD_RELOC_32; + s = expr_end; + continue; case 'F': - as_bad("Floating point constants only implemented for pseudo ops."); - continue; - - case 'i': /* 16 bit unsigned immediate */ - case 'j': /* 16 bit signed immediate */ - imm_reloc = BFD_RELOC_LO16; - c = my_getSmallExpression(&imm_expr, s); - if (c) { - if (c != 'l') { - if (imm_expr.X_seg == &bfd_abs_section) - imm_expr.X_add_number = - (imm_expr.X_add_number >> 16) & 0xffff; - else if (c == 'h') - imm_reloc = BFD_RELOC_HI16_S; - else - imm_reloc = BFD_RELOC_HI16; + as_bad ("Floating point constants only implemented for pseudo ops."); + continue; + + case 'i': /* 16 bit unsigned immediate */ + case 'j': /* 16 bit signed immediate */ + imm_reloc = BFD_RELOC_LO16; + c = my_getSmallExpression (&imm_expr, s); + if (c) + { + if (c != 'l') + { + if (imm_expr.X_seg == &bfd_abs_section) + imm_expr.X_add_number = + (imm_expr.X_add_number >> 16) & 0xffff; + else if (c == 'h') + imm_reloc = BFD_RELOC_HI16_S; + else + imm_reloc = BFD_RELOC_HI16; } - } else - check_absolute_expr(ip, &imm_expr); - if (*args == 'i') { - if ((unsigned long) imm_expr.X_add_number > 65535) - as_bad("16 bit expression not in range 0..65535"); - } else { - if (imm_expr.X_add_number < -32768 || + } + else + check_absolute_expr (ip, &imm_expr); + if (*args == 'i') + { + if ((unsigned long) imm_expr.X_add_number > 65535) + as_bad ("16 bit expression not in range 0..65535"); + } + else + { + if (imm_expr.X_add_number < -32768 || imm_expr.X_add_number > 32767) - as_bad("16 bit expression not in range -32768..32767"); + as_bad ("16 bit expression not in range -32768..32767"); } - s = expr_end; - continue; - - case 'o': /* 16 bit offset */ - c = my_getSmallExpression(&offset_expr, s); - /* - * If this value won't fit into a 16 bit offset, then - * go find a macro that will generate the 32 bit offset - * code pattern. - */ - if ((offset_expr.X_add_symbol - && offset_expr.X_seg != &bfd_abs_section) - || offset_expr.X_subtract_symbol - || offset_expr.X_add_number > 32767 - || offset_expr.X_add_number < -32768) - break; - - offset_reloc = BFD_RELOC_LO16; - if (c == 'h' || c == 'H') - offset_expr.X_add_number = - (offset_expr.X_add_number >> 16) & 0xffff; - s = expr_end; - continue; - - case 'p': /* pc relative offset */ - offset_reloc = BFD_RELOC_16_PCREL_S2; - my_getExpression(&offset_expr, s); - s = expr_end; - continue; + s = expr_end; + continue; + + case 'o': /* 16 bit offset */ + c = my_getSmallExpression (&offset_expr, s); + /* + * If this value won't fit into a 16 bit offset, then + * go find a macro that will generate the 32 bit offset + * code pattern. + */ + if ((offset_expr.X_add_symbol + && offset_expr.X_seg != &bfd_abs_section) + || offset_expr.X_subtract_symbol + || offset_expr.X_add_number > 32767 + || offset_expr.X_add_number < -32768) + break; - case 'u': /* upper 16 bits */ - c = my_getSmallExpression(&imm_expr, s); - if ((unsigned long)imm_expr.X_add_number > 65535) - as_bad("lui expression not in range 0..65535"); - imm_reloc = BFD_RELOC_LO16; - if (c) { - if (c != 'l') { - if (imm_expr.X_seg == &bfd_abs_section) - imm_expr.X_add_number = - (imm_expr.X_add_number >> 16) & 0xffff; - else if (c == 'h') - imm_reloc = BFD_RELOC_HI16_S; - else - imm_reloc = BFD_RELOC_HI16; + offset_reloc = BFD_RELOC_LO16; + if (c == 'h' || c == 'H') + offset_expr.X_add_number = + (offset_expr.X_add_number >> 16) & 0xffff; + s = expr_end; + continue; + + case 'p': /* pc relative offset */ + offset_reloc = BFD_RELOC_16_PCREL_S2; + my_getExpression (&offset_expr, s); + s = expr_end; + continue; + + case 'u': /* upper 16 bits */ + c = my_getSmallExpression (&imm_expr, s); + if ((unsigned long) imm_expr.X_add_number > 65535) + as_bad ("lui expression not in range 0..65535"); + imm_reloc = BFD_RELOC_LO16; + if (c) + { + if (c != 'l') + { + if (imm_expr.X_seg == &bfd_abs_section) + imm_expr.X_add_number = + (imm_expr.X_add_number >> 16) & 0xffff; + else if (c == 'h') + imm_reloc = BFD_RELOC_HI16_S; + else + imm_reloc = BFD_RELOC_HI16; } } - s = expr_end; - continue; + s = expr_end; + continue; - case 'a': /* 26 bit address */ - my_getExpression(&offset_expr, s); - s = expr_end; - offset_reloc = BFD_RELOC_MIPS_JMP; - continue; + case 'a': /* 26 bit address */ + my_getExpression (&offset_expr, s); + s = expr_end; + offset_reloc = BFD_RELOC_MIPS_JMP; + continue; default: - fprintf(stderr, "bad char = '%c'\n", *args); - internalError(); + fprintf (stderr, "bad char = '%c'\n", *args); + internalError (); } - break; + break; } - /* Args don't match. */ - if (insn + 1 < &mips_opcodes[NUMOPCODES] && - !strcmp(insn->name, insn[1].name)) { - ++insn; - s = argsStart; - continue; + /* Args don't match. */ + if (insn + 1 < &mips_opcodes[NUMOPCODES] && + !strcmp (insn->name, insn[1].name)) + { + ++insn; + s = argsStart; + continue; } - insn_error = "ERROR: Illegal operands"; - return; + insn_error = "ERROR: Illegal operands"; + return; } } @@ -2007,101 +2266,114 @@ mips_ip (str, ip) static int my_getSmallExpression (ep, str) - expressionS *ep; - char *str; + expressionS *ep; + char *str; { - char *sp; - int c = 0; - - if (*str == ' ') - str++; - if (*str == LP - || (*str == '%' && - ((str[1] == 'h' && str[2] == 'i') - || (str[1] == 'H' && str[2] == 'I') - || (str[1] == 'l' && str[2] == 'o')) - && str[3] == LP)) { - if (*str == LP) - c = 0; - else { - c = str[1]; - str += 3; - } - - /* - * A small expression may be followed by a base register. - * Scan to the end of this operand, and then back over a possible - * base register. Then scan the small expression up to that - * point. (Based on code in sparc.c...) - */ - for (sp = str; *sp && *sp != ','; sp++) - ; - if (sp - 4 >= str && sp[-1] == RP) { - if (isdigit(sp[-2])) { - for (sp -= 3; sp >= str && isdigit(*sp); sp--) - ; - if (*sp == '$' && sp > str && sp[-1] == LP) { - sp--; - goto do_it; + char *sp; + int c = 0; + + if (*str == ' ') + str++; + if (*str == LP + || (*str == '%' && + ((str[1] == 'h' && str[2] == 'i') + || (str[1] == 'H' && str[2] == 'I') + || (str[1] == 'l' && str[2] == 'o')) + && str[3] == LP)) + { + if (*str == LP) + c = 0; + else + { + c = str[1]; + str += 3; + } + + /* + * A small expression may be followed by a base register. + * Scan to the end of this operand, and then back over a possible + * base register. Then scan the small expression up to that + * point. (Based on code in sparc.c...) + */ + for (sp = str; *sp && *sp != ','; sp++) + ; + if (sp - 4 >= str && sp[-1] == RP) + { + if (isdigit (sp[-2])) + { + for (sp -= 3; sp >= str && isdigit (*sp); sp--) + ; + if (*sp == '$' && sp > str && sp[-1] == LP) + { + sp--; + goto do_it; } - } else if (sp - 5 >= str - && sp[-5] == LP - && sp[-4] == '$' - && ((sp[-3] == 'f' && sp[-2] == 'p') - || (sp[-3] == 's' && sp[-2] == 'p') - || (sp[-3] == 'g' && sp[-2] == 'p') - || (sp[-3] == 'a' && sp[-2] == 't'))) { - sp -= 5; + } + else if (sp - 5 >= str + && sp[-5] == LP + && sp[-4] == '$' + && ((sp[-3] == 'f' && sp[-2] == 'p') + || (sp[-3] == 's' && sp[-2] == 'p') + || (sp[-3] == 'g' && sp[-2] == 'p') + || (sp[-3] == 'a' && sp[-2] == 't'))) + { + sp -= 5; do_it: - if (sp == str) { - /* no expression means zero offset */ - if (c) { - /* %xx(reg) is an error */ - ep->X_seg = absent_section; - expr_end = str - 3; - } else { - ep->X_seg = &bfd_abs_section; - expr_end = sp; + if (sp == str) + { + /* no expression means zero offset */ + if (c) + { + /* %xx(reg) is an error */ + ep->X_seg = absent_section; + expr_end = str - 3; } - ep->X_add_symbol = NULL; - ep->X_subtract_symbol = NULL; - ep->X_add_number = 0; - } else { - *sp = '\0'; - my_getExpression(ep, str); - *sp = LP; + else + { + ep->X_seg = &bfd_abs_section; + expr_end = sp; + } + ep->X_add_symbol = NULL; + ep->X_subtract_symbol = NULL; + ep->X_add_number = 0; + } + else + { + *sp = '\0'; + my_getExpression (ep, str); + *sp = LP; } - return c; + return c; } } } - my_getExpression(ep, str); - return c; /* => %hi or %lo encountered */ + my_getExpression (ep, str); + return c; /* => %hi or %lo encountered */ } static void my_getExpression (ep, str) - expressionS *ep; - char *str; + expressionS *ep; + char *str; { - char *save_in; - asection *seg; - - save_in = input_line_pointer; - input_line_pointer = str; - seg = expression(ep); - expr_end = input_line_pointer; - input_line_pointer = save_in; + char *save_in; + asection *seg; + + save_in = input_line_pointer; + input_line_pointer = str; + seg = expression (ep); + expr_end = input_line_pointer; + input_line_pointer = save_in; } char * -md_atof (type,litP,sizeP) +md_atof (type, litP, sizeP) char type; char *litP; int *sizeP; { - internalError(); - return NULL; + internalError (); + return NULL; } void @@ -2110,50 +2382,49 @@ md_number_to_chars (buf, val, n) long val; int n; { - - switch (byte_order) { + switch (byte_order) + { case LITTLE_ENDIAN: - switch (n) { - + switch (n) + { case 4: - *buf++ = val; - *buf++ = val >> 8; - *buf++ = val >> 16; - *buf = val >> 24; - return; + *buf++ = val; + *buf++ = val >> 8; + *buf++ = val >> 16; + *buf = val >> 24; + return; - case 2: - *buf++ = val; - *buf = val >> 8; - return; + case 2: + *buf++ = val; + *buf = val >> 8; + return; case 1: - *buf = val; - return; + *buf = val; + return; default: - internalError(); + internalError (); } case BIG_ENDIAN: - - switch (n) { - + switch (n) + { case 4: - *buf++ = val >> 24; - *buf++ = val >> 16; - case 2: - *buf++ = val >> 8; + *buf++ = val >> 24; + *buf++ = val >> 16; + case 2: + *buf++ = val >> 8; case 1: - *buf = val; - return; + *buf = val; + return; default: - internalError(); + internalError (); } default: - internalError(); + internalError (); } } @@ -2163,20 +2434,49 @@ md_parse_option (argP, cntP, vecP) int *cntP; char ***vecP; { - /* Accept -nocpp but ignore it. */ - if (!strcmp(*argP, "nocpp")) { - *argP += 5; - return 1; + /* Accept -nocpp but ignore it. */ + if (!strcmp (*argP, "nocpp")) + { + *argP += 5; + return 1; + } + + if (strcmp (*argP, "EL") == 0 + || strcmp (*argP, "EB") == 0) + { + /* FIXME: This breaks -L -EL. */ + flagseen['L'] = 0; + *argP = ""; + return 1; + } + +#ifdef OBJ_ECOFF + if (**argP == 'G') + { + if ((*argP)[1] != '\0') + g_switch_value = atoi (*argP + 1); + else if (*cntP) + { + **vecP = (char *) NULL; + (*cntP)--; + (*vecP)++; + g_switch_value = atoi (**vecP); + } + else + as_warn ("Number expected after -G"); + *argP = ""; + return 1; } - return 1; /* pretend you parsed the character */ +#endif + return 1; /* pretend you parsed the character */ } long md_pcrel_from (fixP) fixS *fixP; { - /* return the address of the delay slot */ - return fixP->fx_size + fixP->fx_where + fixP->fx_frag->fr_address; + /* return the address of the delay slot */ + return fixP->fx_size + fixP->fx_where + fixP->fx_frag->fr_address; } int @@ -2184,174 +2484,181 @@ md_apply_fix (fixP, valueP) fixS *fixP; long *valueP; { - unsigned char *buf; - long insn, value; + unsigned char *buf; + long insn, value; - assert(fixP->fx_size == 4); + assert (fixP->fx_size == 4); - value = *valueP; - fixP->fx_addnumber = value; /* Remember value for tc_gen_reloc */ + value = *valueP; + fixP->fx_addnumber = value; /* Remember value for tc_gen_reloc */ - switch (fixP->fx_r_type) { + switch (fixP->fx_r_type) + { case BFD_RELOC_32: case BFD_RELOC_MIPS_JMP: case BFD_RELOC_HI16: case BFD_RELOC_HI16_S: case BFD_RELOC_LO16: - /* Nothing needed to do. The value comes from the reloc entry */ - return 1; + case BFD_RELOC_MIPS_GPREL: + /* Nothing needed to do. The value comes from the reloc entry */ + return 1; case BFD_RELOC_16_PCREL_S2: - /* - * We need to save the bits in the instruction since fixup_segment() - * might be deleting the relocation entry (i.e., a branch within - * the current segment). - */ - if (value & 0x3) - as_warn("Branch to odd address (%x)", value); - value >>= 2; - if ((value & ~0xFFFF) && (value & ~0xFFFF) != (-1 & ~0xFFFF)) - as_bad("Relocation overflow"); - - /* update old instruction data */ - buf = (unsigned char *)(fixP->fx_where + fixP->fx_frag->fr_literal); - switch (byte_order) { + /* + * We need to save the bits in the instruction since fixup_segment() + * might be deleting the relocation entry (i.e., a branch within + * the current segment). + */ + if (value & 0x3) + as_warn ("Branch to odd address (%x)", value); + value >>= 2; + if ((value & ~0xFFFF) && (value & ~0xFFFF) != (-1 & ~0xFFFF)) + as_bad ("Relocation overflow"); + + /* update old instruction data */ + buf = (unsigned char *) (fixP->fx_where + fixP->fx_frag->fr_literal); + switch (byte_order) + { case LITTLE_ENDIAN: - insn = (buf[3] << 24) | (buf[2] << 16) | (buf[1] << 8) | buf[0]; - break; + insn = (buf[3] << 24) | (buf[2] << 16) | (buf[1] << 8) | buf[0]; + break; case BIG_ENDIAN: - insn = (buf[0] << 24) | (buf[1] << 16) | (buf[2] << 8) | buf[3]; - break; + insn = (buf[0] << 24) | (buf[1] << 16) | (buf[2] << 8) | buf[3]; + break; default: - internalError(); - return 0; + internalError (); + return 0; } - insn |= value & 0xFFFF; - md_number_to_chars(buf, insn, 4); - break; + insn |= value & 0xFFFF; + md_number_to_chars (buf, insn, 4); + break; default: - internalError(); + internalError (); } - return 1; + return 1; } #if 0 void -printInsn(oc) - unsigned long oc; +printInsn (oc) + unsigned long oc; { - const struct mips_opcode *p; - int treg, sreg, dreg, shamt; - short imm; - const char *args; - int i; - - for (i = 0; i < NUMOPCODES; ++i) { - p = &mips_opcodes[i]; - if (((oc & p->mask) == p->match) && (p->pinfo != INSN_MACRO)) { - printf("%08lx %s\t", oc, p->name); - treg = (oc >> 16) & 0x1f; - sreg = (oc >> 21) & 0x1f; - dreg = (oc >> 11) & 0x1f; - shamt = (oc >> 6) & 0x1f; - imm = oc; - for (args = p->args; ; ++args) { - switch (*args) { + const struct mips_opcode *p; + int treg, sreg, dreg, shamt; + short imm; + const char *args; + int i; + for (i = 0; i < NUMOPCODES; ++i) + { + p = &mips_opcodes[i]; + if (((oc & p->mask) == p->match) && (p->pinfo != INSN_MACRO)) + { + printf ("%08lx %s\t", oc, p->name); + treg = (oc >> 16) & 0x1f; + sreg = (oc >> 21) & 0x1f; + dreg = (oc >> 11) & 0x1f; + shamt = (oc >> 6) & 0x1f; + imm = oc; + for (args = p->args;; ++args) + { + switch (*args) + { case '\0': - printf("\n"); - break; + printf ("\n"); + break; case ',': case '(': case ')': - printf("%c", *args); - continue; + printf ("%c", *args); + continue; case 'r': - assert(treg == sreg); - printf("$%d,$%d", treg, sreg); - continue; + assert (treg == sreg); + printf ("$%d,$%d", treg, sreg); + continue; case 'd': - printf("$%d", dreg); - continue; + printf ("$%d", dreg); + continue; case 't': - printf("$%d", treg); - continue; + printf ("$%d", treg); + continue; case 'b': case 's': - printf("$%d", sreg); - continue; + printf ("$%d", sreg); + continue; case 'a': - printf("0x%08lx", oc & 0x1ffffff); - continue; + printf ("0x%08lx", oc & 0x1ffffff); + continue; case 'i': case 'j': case 'o': case 'u': - printf("%d", imm); - continue; + printf ("%d", imm); + continue; case '<': - printf("$%d", shamt); - continue; + printf ("$%d", shamt); + continue; default: - internalError(); + internalError (); } - break; + break; } - return; + return; } } - printf("%08lx UNDEFINED\n", oc); + printf ("%08lx UNDEFINED\n", oc); } #endif static symbolS * get_symbol () { - int c; - char *name; - symbolS *p; - - name = input_line_pointer; - c = get_symbol_end(); - p = (symbolS *) symbol_find_or_make(name); - *input_line_pointer = c; - return p; + int c; + char *name; + symbolS *p; + + name = input_line_pointer; + c = get_symbol_end (); + p = (symbolS *) symbol_find_or_make (name); + *input_line_pointer = c; + return p; } static long get_optional_absolute_expression () { - expressionS exp; - asection *s; + expressionS exp; + asection *s; - s = expression(&exp); - if (!(s == &bfd_abs_section || s == big_section || s == absent_section)) { - as_bad("Bad Absolute Expression."); + s = expression (&exp); + if (!(s == &bfd_abs_section || s == big_section || s == absent_section)) + { + as_bad ("Bad Absolute Expression."); } - return exp.X_add_number; + return exp.X_add_number; } static void s_align (x) int x; { - register int temp; - register long temp_fill; - long max_alignment = 15; + register int temp; + register long temp_fill; + long max_alignment = 15; - /* + /* o Note that the assembler pulls down any immediately preceeding label to the aligned address. @@ -2363,56 +2670,74 @@ s_align (x) */ - temp = get_absolute_expression (); - if (temp > max_alignment) - as_bad("Alignment too large: %d. assumed.", temp = max_alignment); - else if (temp < 0) { - as_warn("Alignment negative: 0 assumed."); - temp = 0; + temp = get_absolute_expression (); + if (temp > max_alignment) + as_bad ("Alignment too large: %d. assumed.", temp = max_alignment); + else if (temp < 0) + { + as_warn ("Alignment negative: 0 assumed."); + temp = 0; + } + if (*input_line_pointer == ',') + { + input_line_pointer++; + temp_fill = get_absolute_expression (); + } + else + temp_fill = 0; + if (temp) + { + auto_align = 1; + if (!need_pass_2) + frag_align (temp, (int) temp_fill); } - if (*input_line_pointer == ',') { - input_line_pointer ++; - temp_fill = get_absolute_expression (); - } else - temp_fill = 0; - if (temp) { - auto_align = 1; - if (!need_pass_2) - frag_align (temp, (int)temp_fill); - } else { - auto_align = 0; + else + { + auto_align = 0; } - record_alignment(now_seg, temp); + record_alignment (now_seg, temp); - demand_empty_rest_of_line(); + demand_empty_rest_of_line (); } static void s_change_sec (sec) int sec; { - switch (sec) { + switch (sec) + { case 't': - s_text(); - break; + s_text (); + break; case 'r': +#ifdef OBJ_ECOFF + subseg_new (".rdata", (subsegT) get_absolute_expression ()); + break; +#else + /* Fall through. */ +#endif case 'd': - s_data(); - break; + s_data (); + break; case 'b': #ifdef BFD_ASSEMBLER - subseg_set (bss_section, (subsegT) get_absolute_expression ()); + subseg_set (bss_section, (subsegT) get_absolute_expression ()); #else - subseg_new (bss_section, (subsegT) get_absolute_expression ()); + subseg_new (bss_section, (subsegT) get_absolute_expression ()); +#endif + demand_empty_rest_of_line (); + break; + case 's': +#ifdef OBJ_ECOFF + subseg_new (".sdata", (subsegT) get_absolute_expression ()); + break; +#else + as_bad ("Global pointers not supported; recompile -G 0"); + return; #endif - demand_empty_rest_of_line (); - break; - default: - as_bad("Global pointers not supported; recompile -G 0"); - return; } - auto_align = 1; + auto_align = 1; } static void @@ -2420,146 +2745,190 @@ s_cons (log_size) int log_size; { - if (log_size > 0 && auto_align) - frag_align(log_size, 0); - cons(1 << log_size); + if (log_size > 0 && auto_align) + frag_align (log_size, 0); + cons (1 << log_size); } static void s_err (x) int x; { - as_fatal("Encountered `.err', aborting assembly"); + as_fatal ("Encountered `.err', aborting assembly"); } static void s_extern (x) int x; { - long size; - symbolS *symbolP; - - symbolP = get_symbol(); - if (*input_line_pointer == ',') - input_line_pointer++; - size = get_optional_absolute_expression(); - S_SET_VALUE(symbolP, size); + long size; + symbolS *symbolP; + + symbolP = get_symbol (); + if (*input_line_pointer == ',') + input_line_pointer++; + size = get_optional_absolute_expression (); + S_SET_VALUE (symbolP, size); + S_SET_EXTERNAL (symbolP); + +#ifdef OBJ_ECOFF + /* ECOFF needs to distinguish a .comm symbol from a .extern symbol, + so we use an additional ECOFF specific field. */ + symbolP->ecoff_undefined = 1; +#endif } static void s_float_cons (is_double) int is_double; { - char *f; - short words[4]; - int error_code, repeat; - extern FLONUM_TYPE generic_floating_point_number; - - if (auto_align) - if (is_double) - frag_align(3, 0); - else - frag_align(2, 0); - - SKIP_WHITESPACE (); - if (! is_end_of_line [(unsigned char) *input_line_pointer]) { - do { - error_code = atof_generic(&input_line_pointer, ".", EXP_CHARS, - &generic_floating_point_number); - if (error_code) { - if (error_code == ERROR_EXPONENT_OVERFLOW) - as_warn("Bad floating-point constant: exponent overflow"); - else - as_warn("Bad floating-point constant: unknown error code=%d.", error_code); + char *f; + short words[4]; + int error_code, repeat; + extern FLONUM_TYPE generic_floating_point_number; + + if (auto_align) + if (is_double) + frag_align (3, 0); + else + frag_align (2, 0); + + SKIP_WHITESPACE (); + if (!is_end_of_line[(unsigned char) *input_line_pointer]) + { + do + { + error_code = atof_generic (&input_line_pointer, ".", EXP_CHARS, + &generic_floating_point_number); + if (error_code) + { + if (error_code == ERROR_EXPONENT_OVERFLOW) + as_warn ("Bad floating-point constant: exponent overflow"); + else + as_warn ("Bad floating-point constant: unknown error code=%d.", error_code); } - if (is_double) { - gen_to_words((LITTLENUM_TYPE *)words, - 4 /* precision */, - 11 /* exponent_bits */ ); - } else { - gen_to_words((LITTLENUM_TYPE *)words, - 2 /* precision */, - 8 /* exponent_bits */ ); + if (is_double) + { + gen_to_words ((LITTLENUM_TYPE *) words, + 4 /* precision */ , + 11 /* exponent_bits */ ); + } + else + { + gen_to_words ((LITTLENUM_TYPE *) words, + 2 /* precision */ , + 8 /* exponent_bits */ ); } - if (*input_line_pointer == ':') { - input_line_pointer++; - repeat = get_absolute_expression(); - } else { - repeat = 1; + if (*input_line_pointer == ':') + { + input_line_pointer++; + repeat = get_absolute_expression (); } - if (is_double) { - f = frag_more(repeat * 8); - for (;repeat--; f += 8) { - md_number_to_chars(f+6, words[0], 2); - md_number_to_chars(f+4, words[1], 2); - md_number_to_chars(f+2, words[2], 2); - md_number_to_chars(f, words[3], 2); + else + { + repeat = 1; + } + if (is_double) + { + f = frag_more (repeat * 8); + for (; repeat--; f += 8) + { + md_number_to_chars (f + 6, words[0], 2); + md_number_to_chars (f + 4, words[1], 2); + md_number_to_chars (f + 2, words[2], 2); + md_number_to_chars (f, words[3], 2); } - } else { - f = frag_more(repeat * 4); - for (;repeat--; f += 4) { - md_number_to_chars(f+2, words[0], 2); - md_number_to_chars(f, words[1], 2); + } + else + { + f = frag_more (repeat * 4); + for (; repeat--; f += 4) + { + md_number_to_chars (f + 2, words[0], 2); + md_number_to_chars (f, words[1], 2); } } - SKIP_WHITESPACE(); - if (*input_line_pointer != ',') break; - input_line_pointer++; - SKIP_WHITESPACE(); - } while (1); + SKIP_WHITESPACE (); + if (*input_line_pointer != ',') + break; + input_line_pointer++; + SKIP_WHITESPACE (); + } + while (1); } - demand_empty_rest_of_line(); + demand_empty_rest_of_line (); } static void s_option (x) int x; { - if (strcmp(input_line_pointer, "O1") != 0 - && strcmp(input_line_pointer, "O2") != 0) - as_warn("Unrecognized option"); - demand_empty_rest_of_line(); + if (strcmp (input_line_pointer, "O1") != 0 + && strcmp (input_line_pointer, "O2") != 0) + as_warn ("Unrecognized option"); + demand_empty_rest_of_line (); } static void s_mipsset (x) int x; { - char *name = input_line_pointer, ch; - - while (!is_end_of_line[(unsigned char) *input_line_pointer]) - input_line_pointer++; - ch = *input_line_pointer; - *input_line_pointer = '\0'; - - if (strcmp(name, "reorder") == 0) { - mips_noreorder = 0; - } else if (strcmp(name, "noreorder") == 0) { - mips_noreorder = 1; - } else if (strcmp(name, "at") == 0) { - mips_noat = 0; - } else if (strcmp(name, "noat") == 0) { - mips_noat = 1; - } else if (strcmp(name, "macro") == 0) { - mips_warn_about_macros = 0; - } else if (strcmp(name, "nomacro") == 0) { - if (mips_noreorder == 0) - as_bad("`noreorder' must be set before `nomacro'"); - mips_warn_about_macros = 1; - } else if (strcmp(name, "move") == 0 || strcmp(name, "novolatile") == 0) { - mips_nomove = 0; - } else if (strcmp(name, "nomove") == 0 || strcmp(name, "volatile") == 0) { - mips_nomove = 1; - } else if (strcmp(name, "bopt") == 0) { - mips_nobopt = 0; - } else if (strcmp(name, "nobopt") == 0) { - mips_nobopt = 1; - } else { - as_warn("Tried to set unrecognized symbol: %s\n", name); + char *name = input_line_pointer, ch; + + while (!is_end_of_line[(unsigned char) *input_line_pointer]) + input_line_pointer++; + ch = *input_line_pointer; + *input_line_pointer = '\0'; + + if (strcmp (name, "reorder") == 0) + { + mips_noreorder = 0; + } + else if (strcmp (name, "noreorder") == 0) + { + mips_noreorder = 1; + } + else if (strcmp (name, "at") == 0) + { + mips_noat = 0; + } + else if (strcmp (name, "noat") == 0) + { + mips_noat = 1; } - *input_line_pointer = ch; - demand_empty_rest_of_line(); + else if (strcmp (name, "macro") == 0) + { + mips_warn_about_macros = 0; + } + else if (strcmp (name, "nomacro") == 0) + { + if (mips_noreorder == 0) + as_bad ("`noreorder' must be set before `nomacro'"); + mips_warn_about_macros = 1; + } + else if (strcmp (name, "move") == 0 || strcmp (name, "novolatile") == 0) + { + mips_nomove = 0; + } + else if (strcmp (name, "nomove") == 0 || strcmp (name, "volatile") == 0) + { + mips_nomove = 1; + } + else if (strcmp (name, "bopt") == 0) + { + mips_nobopt = 0; + } + else if (strcmp (name, "nobopt") == 0) + { + mips_nobopt = 1; + } + else + { + as_warn ("Tried to set unrecognized symbol: %s\n", name); + } + *input_line_pointer = ch; + demand_empty_rest_of_line (); } int @@ -2623,7 +2992,7 @@ tc_gen_reloc (section, fixp) #ifdef OBJ_ELF reloc->addend = 0; #else - reloc->addend = - reloc->address; + reloc->addend = -reloc->address; #endif reloc->howto = bfd_reloc_type_lookup (stdoutput, fixp->fx_r_type); assert (reloc->howto != 0); @@ -2642,23 +3011,23 @@ tc_gen_reloc (section, fixp) /* should never be called */ long -md_section_align(seg, addr) - asection *seg; - long addr; +md_section_align (seg, addr) + asection *seg; + long addr; { - int align = bfd_get_section_alignment(stdoutput, seg); + int align = bfd_get_section_alignment (stdoutput, seg); - return ((addr + (1 << align) - 1) & (-1 << align)); + return ((addr + (1 << align) - 1) & (-1 << align)); } int -md_estimate_size_before_relax(fragP, segtype) - fragS *fragP; - asection *segtype; +md_estimate_size_before_relax (fragP, segtype) + fragS *fragP; + asection *segtype; { - as_fatal("md_estimate_size_before_relax"); - return(1); -} /* md_estimate_size_before_relax() */ + as_fatal ("md_estimate_size_before_relax"); + return (1); +} /* md_estimate_size_before_relax() */ #ifndef OBJ_ECOFF @@ -2669,19 +3038,22 @@ md_estimate_size_before_relax(fragP, segtype) any debugging information, but they do simple checking and someday somebody may make them useful. */ -typedef struct loc { - struct loc *loc_next; - unsigned long loc_fileno; - unsigned long loc_lineno; - unsigned long loc_offset; - unsigned short loc_delta; - unsigned short loc_count; +typedef struct loc +{ + struct loc *loc_next; + unsigned long loc_fileno; + unsigned long loc_lineno; + unsigned long loc_offset; + unsigned short loc_delta; + unsigned short loc_count; #if 0 - fragS *loc_frag; + fragS *loc_frag; #endif -} locS; +} +locS; -typedef struct proc { +typedef struct proc + { struct proc *proc_next; struct symbol *proc_isym; struct symbol *proc_end; @@ -2695,16 +3067,19 @@ typedef struct proc { locS *proc_iline; struct file *proc_file; int proc_index; -} procS; + } +procS; -typedef struct file { +typedef struct file + { struct file *file_next; unsigned long file_fileno; struct symbol *file_symbol; struct symbol *file_end; struct proc *file_proc; int file_numprocs; -} fileS; + } +fileS; static struct obstack proc_frags; static procS *proc_lastP; @@ -2714,7 +3089,7 @@ static int numprocs; static void md_obj_begin () { - obstack_begin(&proc_frags, 0x2000); + obstack_begin (&proc_frags, 0x2000); } static void @@ -2722,7 +3097,7 @@ md_obj_end () { /* check for premature end, nesting errors, etc */ if (proc_lastP && proc_lastP->proc_end == NULL) - as_warn("missing `.end' at end of assembly"); + as_warn ("missing `.end' at end of assembly"); } extern char hex_value[]; @@ -2730,43 +3105,52 @@ extern char hex_value[]; static long get_number () { - int negative = 0; - long val = 0; + int negative = 0; + long val = 0; - if (*input_line_pointer == '-') { - ++input_line_pointer; - negative = 1; + if (*input_line_pointer == '-') + { + ++input_line_pointer; + negative = 1; } - if (!isdigit(*input_line_pointer)) - as_bad("Expected simple number."); - if (input_line_pointer[0] == '0') { - if (input_line_pointer[1] == 'x') { - input_line_pointer += 2; - while (isxdigit(*input_line_pointer)) { - val <<= 4; - val |= hex_value[(int) *input_line_pointer++]; + if (!isdigit (*input_line_pointer)) + as_bad ("Expected simple number."); + if (input_line_pointer[0] == '0') + { + if (input_line_pointer[1] == 'x') + { + input_line_pointer += 2; + while (isxdigit (*input_line_pointer)) + { + val <<= 4; + val |= hex_value[(int) *input_line_pointer++]; } - return negative ? -val : val; - } else { - ++input_line_pointer; - while (isdigit(*input_line_pointer)) { - val <<= 3; - val |= *input_line_pointer++ - '0'; + return negative ? -val : val; + } + else + { + ++input_line_pointer; + while (isdigit (*input_line_pointer)) + { + val <<= 3; + val |= *input_line_pointer++ - '0'; } - return negative ? -val : val; + return negative ? -val : val; } } - if (!isdigit(*input_line_pointer)) { - printf(" *input_line_pointer == '%c' 0x%02x\n", - *input_line_pointer, *input_line_pointer); - as_warn("Invalid number"); - return -1; + if (!isdigit (*input_line_pointer)) + { + printf (" *input_line_pointer == '%c' 0x%02x\n", + *input_line_pointer, *input_line_pointer); + as_warn ("Invalid number"); + return -1; } - while (isdigit(*input_line_pointer)) { - val *= 10; - val += *input_line_pointer++ - '0'; + while (isdigit (*input_line_pointer)) + { + val *= 10; + val += *input_line_pointer++ - '0'; } - return negative ? -val : val; + return negative ? -val : val; } /* The .file directive; just like the usual .file directive, but there @@ -2776,10 +3160,10 @@ static void s_file (x) int x; { - int line; + int line; - line = get_number(); - s_app_file(); + line = get_number (); + s_app_file (); } @@ -2789,27 +3173,31 @@ static void s_mipsend (x) int x; { - symbolS *p; - - if (!is_end_of_line[(unsigned char) *input_line_pointer]) { - p = get_symbol(); - demand_empty_rest_of_line(); - } else - p = NULL; - if (now_seg != text_section) - as_warn(".end not in text section"); - if (!proc_lastP) { - as_warn(".end and no .ent seen yet."); - return; + symbolS *p; + + if (!is_end_of_line[(unsigned char) *input_line_pointer]) + { + p = get_symbol (); + demand_empty_rest_of_line (); + } + else + p = NULL; + if (now_seg != text_section) + as_warn (".end not in text section"); + if (!proc_lastP) + { + as_warn (".end and no .ent seen yet."); + return; } - if (p != NULL) { - assert(S_GET_NAME(p)); - if (strcmp(S_GET_NAME(p), S_GET_NAME(proc_lastP->proc_isym))) - as_warn(".end symbol does not match .ent symbol."); + if (p != NULL) + { + assert (S_GET_NAME (p)); + if (strcmp (S_GET_NAME (p), S_GET_NAME (proc_lastP->proc_isym))) + as_warn (".end symbol does not match .ent symbol."); } - proc_lastP->proc_end = (symbolS *) 1; + proc_lastP->proc_end = (symbolS *) 1; } /* The .aent and .ent directives. */ @@ -2818,84 +3206,86 @@ static void s_ent (aent) int aent; { - int number = 0; - procS *procP; - symbolS *symbolP; - - symbolP = get_symbol(); - if (*input_line_pointer == ',') - input_line_pointer++; - if (isdigit(*input_line_pointer) || *input_line_pointer == '-') - number = get_number(); - if (now_seg != text_section) - as_warn(".ent or .aent not in text section."); - - if (!aent && proc_lastP && proc_lastP->proc_end == NULL) - as_warn("missing `.end'"); - - if (!aent) { - procP = (procS *) obstack_alloc(&proc_frags, sizeof(*procP)); - procP->proc_isym = symbolP; - procP->proc_reg_mask = 0; - procP->proc_reg_offset = 0; - procP->proc_fpreg_mask = 0; - procP->proc_fpreg_offset = 0; - procP->proc_frameoffset = 0; - procP->proc_framereg = 0; - procP->proc_pcreg = 0; - procP->proc_end = NULL; - procP->proc_next = NULL; - if (proc_lastP) - proc_lastP->proc_next = procP; - else - proc_rootP = procP; - proc_lastP = procP; - numprocs++; + int number = 0; + procS *procP; + symbolS *symbolP; + + symbolP = get_symbol (); + if (*input_line_pointer == ',') + input_line_pointer++; + if (isdigit (*input_line_pointer) || *input_line_pointer == '-') + number = get_number (); + if (now_seg != text_section) + as_warn (".ent or .aent not in text section."); + + if (!aent && proc_lastP && proc_lastP->proc_end == NULL) + as_warn ("missing `.end'"); + + if (!aent) + { + procP = (procS *) obstack_alloc (&proc_frags, sizeof (*procP)); + procP->proc_isym = symbolP; + procP->proc_reg_mask = 0; + procP->proc_reg_offset = 0; + procP->proc_fpreg_mask = 0; + procP->proc_fpreg_offset = 0; + procP->proc_frameoffset = 0; + procP->proc_framereg = 0; + procP->proc_pcreg = 0; + procP->proc_end = NULL; + procP->proc_next = NULL; + if (proc_lastP) + proc_lastP->proc_next = procP; + else + proc_rootP = procP; + proc_lastP = procP; + numprocs++; } - demand_empty_rest_of_line(); + demand_empty_rest_of_line (); } /* The .frame directive. */ static void s_frame (x) - int x; + int x; { #if 0 - char str[100]; - symbolS *symP; - int frame_reg; - int frame_off; - int pcreg; - - frame_reg = tc_get_register(); - if (*input_line_pointer == ',') - input_line_pointer++; - frame_off = get_optional_absolute_expression(); - if (*input_line_pointer == ',') - input_line_pointer++; - pcreg = tc_get_register(); - - /* bob third eye */ - assert(proc_rootP); - proc_rootP->proc_framereg = frame_reg; - proc_rootP->proc_frameoffset = frame_off; - proc_rootP->proc_pcreg = pcreg; - /* bob macho .frame */ - - /* We don't have to write out a frame stab for unoptimized code. */ - if (!(frame_reg == 30 && frame_off == 0)) { - if (!proc_lastP) - as_warn("No .ent for .frame to use." ); - (void) sprintf(str, "R%d;%d", frame_reg, frame_off ); - symP = symbol_new(str, N_VFP, 0, frag_now ); - S_SET_TYPE(symP, N_RMASK); - S_SET_OTHER(symP, 0); - S_SET_DESC(symP, 0); - symP->sy_forward = proc_lastP->proc_isym; - /* bob perhaps I should have used pseudo set */ + char str[100]; + symbolS *symP; + int frame_reg; + int frame_off; + int pcreg; + + frame_reg = tc_get_register (); + if (*input_line_pointer == ',') + input_line_pointer++; + frame_off = get_optional_absolute_expression (); + if (*input_line_pointer == ',') + input_line_pointer++; + pcreg = tc_get_register (); + + /* bob third eye */ + assert (proc_rootP); + proc_rootP->proc_framereg = frame_reg; + proc_rootP->proc_frameoffset = frame_off; + proc_rootP->proc_pcreg = pcreg; + /* bob macho .frame */ + + /* We don't have to write out a frame stab for unoptimized code. */ + if (!(frame_reg == 30 && frame_off == 0)) + { + if (!proc_lastP) + as_warn ("No .ent for .frame to use."); + (void) sprintf (str, "R%d;%d", frame_reg, frame_off); + symP = symbol_new (str, N_VFP, 0, frag_now); + S_SET_TYPE (symP, N_RMASK); + S_SET_OTHER (symP, 0); + S_SET_DESC (symP, 0); + symP->sy_forward = proc_lastP->proc_isym; + /* bob perhaps I should have used pseudo set */ } - demand_empty_rest_of_line(); + demand_empty_rest_of_line (); #endif } @@ -2906,48 +3296,54 @@ s_mask (reg_type) char reg_type; { #if 0 - char str[100], *strP; - symbolS *symP; - int i; - unsigned int mask; - int off; - - mask = get_number(); - if (*input_line_pointer == ',') - input_line_pointer++; - off = get_absolute_expression(); - - /* bob only for coff */ - assert(proc_rootP); - if (reg_type == 'F' ) { - proc_rootP->proc_fpreg_mask = mask; - proc_rootP->proc_fpreg_offset = off; - } else { - proc_rootP->proc_reg_mask = mask; - proc_rootP->proc_reg_offset = off; + char str[100], *strP; + symbolS *symP; + int i; + unsigned int mask; + int off; + + mask = get_number (); + if (*input_line_pointer == ',') + input_line_pointer++; + off = get_absolute_expression (); + + /* bob only for coff */ + assert (proc_rootP); + if (reg_type == 'F') + { + proc_rootP->proc_fpreg_mask = mask; + proc_rootP->proc_fpreg_offset = off; } + else + { + proc_rootP->proc_reg_mask = mask; + proc_rootP->proc_reg_offset = off; + } + + /* bob macho .mask + .fmask */ - /* bob macho .mask + .fmask */ - - /* We don't have to write out a mask stab if no saved regs. */ - if (!(mask == 0)) { - if (!proc_lastP) - as_warn("No .ent for .mask to use." ); - strP = str; - for (i=0; i<32; i++ ) { - if (mask%2) { - sprintf(strP, "%c%d,", reg_type, i ); - strP += strlen(strP); - } + /* We don't have to write out a mask stab if no saved regs. */ + if (!(mask == 0)) + { + if (!proc_lastP) + as_warn ("No .ent for .mask to use."); + strP = str; + for (i = 0; i < 32; i++) + { + if (mask % 2) + { + sprintf (strP, "%c%d,", reg_type, i); + strP += strlen (strP); + } mask /= 2; - } - sprintf(strP, ";%d,", off ); - symP = symbol_new(str, N_RMASK, 0, frag_now); - S_SET_TYPE(symP, N_RMASK); - S_SET_OTHER(symP, 0); - S_SET_DESC(symP, 0); - symP->sy_forward = proc_lastP->proc_isym; - /* bob perhaps I should have used pseudo set */ + } + sprintf (strP, ";%d,", off); + symP = symbol_new (str, N_RMASK, 0, frag_now); + S_SET_TYPE (symP, N_RMASK); + S_SET_OTHER (symP, 0); + S_SET_DESC (symP, 0); + symP->sy_forward = proc_lastP->proc_isym; + /* bob perhaps I should have used pseudo set */ } #endif } @@ -2959,22 +3355,21 @@ s_loc (x) int x; { #if 0 - symbolS * symbolP; - int lineno; - int addroff; + symbolS *symbolP; + int lineno; + int addroff; - assert(now_seg == text_section); + assert (now_seg == text_section); - lineno = get_number(); - addroff = obstack_next_free(&frags) - frag_now->fr_literal; + lineno = get_number (); + addroff = obstack_next_free (&frags) - frag_now->fr_literal; - symbolP = symbol_new ("", N_SLINE, addroff, frag_now); - S_SET_TYPE(symbolP, N_SLINE); - S_SET_OTHER(symbolP, 0); - S_SET_DESC(symbolP, lineno); - symbolP->sy_segment = now_seg; + symbolP = symbol_new ("", N_SLINE, addroff, frag_now); + S_SET_TYPE (symbolP, N_SLINE); + S_SET_OTHER (symbolP, 0); + S_SET_DESC (symbolP, lineno); + symbolP->sy_segment = now_seg; #endif } #endif /* ! defined (OBJ_ECOFF) */ - diff --git a/gas/config/tc-mips.h b/gas/config/tc-mips.h new file mode 100644 index 00000000000..b0fb9f7b46d --- /dev/null +++ b/gas/config/tc-mips.h @@ -0,0 +1,94 @@ +/* tc-mips.c -- header file for tc-mips.c. + Copyright (C) 1993 Free Software Foundation, Inc. + Contributed by the OSF and Ralph Campbell. + Written by Keith Knowles and Ralph Campbell, working independently. + Modified for ECOFF support by Ian Lance Taylor of Cygnus Support. + + This file is part of GAS. + + GAS is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2, or (at your option) + any later version. + + GAS is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with GAS; see the file COPYING. If not, write to + the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */ + +#define TC_MIPS + +#define TARGET_ARCH bfd_arch_mips + +#define NO_LISTING +#define ONLY_STANDARD_ESCAPES +#define BACKSLASH_V +#define WORKING_DOT_WORD 1 +#define OLD_FLOAT_READS +#define LOCAL_LABELS_FB + +#ifdef OBJ_ECOFF +#define LOCAL_LABEL(name) ((name)[0] == '$' && (name)[1] == 'L') +#endif + +#define md_undefined_symbol(name) (0) +#define md_operand(x) + +#define LITTLE_ENDIAN 1234 +#define BIG_ENDIAN 4321 + +/* If neither TARGET_BYTES_BIG_ENDIAN nor TARGET_BYTES_LITTLE_ENDIAN + is specified, default to big endian. */ +#ifndef TARGET_BYTES_BIG_ENDIAN +#ifndef TARGET_BYTES_LITTLE_ENDIAN +#define TARGET_BYTES_BIG_ENDIAN +#endif +#endif + +#ifdef TARGET_BYTES_BIG_ENDIAN +#define BYTE_ORDER BIG_ENDIAN +#else +#define BYTE_ORDER LITTLE_ENDIAN +#endif + +#ifndef TARGET_FORMAT +#ifdef OBJ_AOUT +#ifdef TARGET_BYTES_BIG_ENDIAN +#define TARGET_FORMAT "aout-mips-big" +#else +#define TARGET_FORMAT "aout-mips-little" +#endif +#endif /* OBJ_AOUT */ +#ifdef OBJ_ECOFF +#ifdef TARGET_BYTES_BIG_ENDIAN +#define TARGET_FORMAT "ecoff-bigmips" +#else +#define TARGET_FORMAT "ecoff-littlemips" +#endif +#endif /* OBJ_ECOFF */ +#endif /* ! defined (TARGET_FORMAT) */ + +struct mips_opcode { + const char *name; + const char *args; + unsigned long match; + unsigned long mask; /* used only for error checking */ + unsigned long pinfo; /* Information used for insn/pipeline scheduling. */ +}; + +struct mips_cl_insn { + unsigned long insn_opcode; + const struct mips_opcode *insn_mo; +}; + +#ifndef BFD_ASSEMBLER +#define md_convert_frag(h,f) {as_fatal ("MIPS convert_frag\n");} +#else +#define md_convert_frag(b,s,f) {as_fatal ("MIPS convert_frag\n");} +#endif + +extern int tc_get_register PARAMS ((void));