aboutsummaryrefslogtreecommitdiff
path: root/gas
diff options
context:
space:
mode:
authorIan Lance Taylor <ian@airs.com>1993-04-01 02:14:29 +0000
committerIan Lance Taylor <ian@airs.com>1993-04-01 02:14:29 +0000
commit670a50ebf65de85eab0ccf22da227e218f704037 (patch)
tree1c276cc2005d44c84d9dfa5d4b1698ecb7facabc /gas
parent8155a95d965478c30f59cbc63a7a2bef01ef884a (diff)
downloadgdb-670a50ebf65de85eab0ccf22da227e218f704037.zip
gdb-670a50ebf65de85eab0ccf22da227e218f704037.tar.gz
gdb-670a50ebf65de85eab0ccf22da227e218f704037.tar.bz2
* 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.
Diffstat (limited to 'gas')
-rw-r--r--gas/ChangeLog42
-rw-r--r--gas/config/obj-ecoff.c286
-rw-r--r--gas/config/tc-mips.c4021
-rw-r--r--gas/config/tc-mips.h94
4 files changed, 2530 insertions, 1913 deletions
diff --git a/gas/ChangeLog b/gas/ChangeLog
index 951b1a7..ce9a9db 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 d0a9b04..5677ee1 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 <ctype.h>
+
/* 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 e37e5f7..3a853f2 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.
<main>: bgez $a0,0x4001bc <main+12>
<main+4>: move v0,$a0
@@ -692,464 +773,521 @@ macro (ip)
<main+12>: 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 <main>: lui $at,%hi(foo)
0x400374 <main+4>: lw $v0,%lo(foo)($at)
0x400378 <main+8>: lw $v1,%lo(foo+4)($at)
@@ -1157,479 +1295,562 @@ macro (ip)
<foo>:
.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 <main>: lwc1 $f0,-32752($gp)
0x4003a4 <main+4>: lwc1 $f1,-32748($gp)
0x4003a8 <main+8>: 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 0000000..b0fb9f7
--- /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));